A biological research lab within the HD-10180 system has suffered from a complete containment failure. The SYN-C Brutus is to deliver a nuclear payload via strike team. Everything inside and outside the facility is to be killed on sight, including any research staff. Nuclear authentication codes have been sent via red phone, as have other detailed orders.
The rest of the documents are maps and mundane information regarding the crew's destination.";
+ name = "STERILIZATION ORDERS";
+ desc = "These are particularly boring for what they entail."
+ },
+/turf/open/floor/pod/dark,
+/area/ruin/space/has_grav/infested_frigate)
"eZ" = (
/obj/item/clothing/mask/facehugger/impregnated,
/obj/structure/closet/crate/secure/freezer/pizza,
@@ -525,15 +557,6 @@
/obj/item/kirbyplants/random,
/turf/open/floor/mineral/titanium/tiled/white,
/area/ruin/space/has_grav/infested_frigate)
-"hX" = (
-/obj/structure/cable,
-/obj/machinery/airalarm/directional/north,
-/obj/effect/mapping_helpers/airalarm/all_access,
-/obj/machinery/icecream_vat{
- desc = "Waffle co. actually ordered these guys to steal one of these just to be sure."
- },
-/turf/open/floor/plating,
-/area/ruin/space/has_grav/infested_frigate)
"ie" = (
/obj/structure/showcase/machinery{
icon_state = "autolathe";
@@ -602,6 +625,23 @@
},
/turf/open/floor/mineral/plastitanium/airless,
/area/ruin/space/has_grav/infested_frigate)
+"jx" = (
+/obj/effect/decal/cleanable/glass,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden,
+/turf/open/floor/mineral/plastitanium/red,
+/area/ruin/space/has_grav/infested_frigate)
+"jy" = (
+/obj/effect/turf_decal{
+ icon_state = "warningline_white"
+ },
+/obj/structure/showcase/machinery/tv{
+ icon_state = "computer_broken";
+ desc = "It would have been locked anyway.";
+ name = "syndicate navigation console"
+ },
+/obj/effect/decal/cleanable/glass,
+/turf/open/floor/pod/dark,
+/area/ruin/space/has_grav/infested_frigate)
"kc" = (
/obj/effect/turf_decal{
dir = 8
@@ -680,10 +720,6 @@
},
/turf/closed/wall/mineral/plastitanium,
/area/ruin/space/has_grav/infested_frigate)
-"lp" = (
-/obj/effect/spawner/structure/window/reinforced/plasma/plastitanium,
-/turf/open/floor/plating,
-/area/ruin/space/has_grav/infested_frigate)
"lx" = (
/obj/structure/barricade/security,
/obj/effect/decal/cleanable/blood/gibs{
@@ -790,13 +826,6 @@
},
/turf/open/floor/pod/dark,
/area/ruin/space/has_grav/infested_frigate)
-"no" = (
-/obj/machinery/door/poddoor{
- id = "Brutusexterior"
- },
-/obj/effect/spawner/structure/window/reinforced/plasma/plastitanium,
-/turf/open/floor/plating,
-/area/ruin/space/has_grav/infested_frigate)
"nG" = (
/mob/living/basic/alien{
faction = list("syndicate","xenomorph")
@@ -811,6 +840,17 @@
},
/turf/open/floor/mineral/plastitanium,
/area/ruin/space/has_grav/infested_frigate)
+"nU" = (
+/obj/structure/cable,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/blood{
+ icon_state = "floor5-old"
+ },
+/obj/item/ammo_casing/spent,
+/obj/item/gun/ballistic/automatic/smartgun,
+/obj/effect/mob_spawn/corpse/human/syndicatepilot,
+/turf/open/floor/mineral/plastitanium/red,
+/area/ruin/space/has_grav/infested_frigate)
"oj" = (
/obj/structure/fans/tiny,
/obj/machinery/door/poddoor{
@@ -897,20 +937,6 @@
},
/turf/template_noop,
/area/template_noop)
-"ps" = (
-/obj/structure/table/glass,
-/obj/item/pen{
- pixel_x = 6;
- pixel_y = 6
- },
-/obj/item/phone,
-/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard/rnd_notes{
- default_raw_text = "STERILIZATION ORDERS
Detailed findings:
A biological research lab within the HD-10180 system has suffered from a complete containment failure. The SYN-C Brutus is to deliver a nuclear payload via strike team. Everything inside and outside the facility is to be killed on sight, including any research staff. Nuclear authentication codes have been sent via red phone, as have other detailed orders.
Make two 3x3 grids right next to eachother using anything you can find to mark the ground. I like using the bartenders hologram projector.
\
+
Make two 3x3 grids right next to each other using anything you can find to mark the ground. I like using the bartenders hologram projector.
\
Take turns rolling the dice and moving the dice into one of the three rows on your 3x3 grid.
\
Your goal is to get the most points by putting die of the same number in the same row.
\
If you have two of the same die in the same row, you will add them together and then times the sum by two. Then add that to the rest of the die.
\
diff --git a/code/game/objects/items/dna_probe.dm b/code/game/objects/items/dna_probe.dm
index ee6a32766522f1..57718ca217e0b6 100644
--- a/code/game/objects/items/dna_probe.dm
+++ b/code/game/objects/items/dna_probe.dm
@@ -17,8 +17,6 @@
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
icon_state = "sampler"
item_flags = NOBLUDGEON
- ///Whether we have Carp DNA
- var/carp_dna_loaded = FALSE
///What sources of DNA this sampler can extract from.
var/allowed_scans = DNA_PROBE_SCAN_PLANTS | DNA_PROBE_SCAN_ANIMALS | DNA_PROBE_SCAN_HUMANS
///List of all Animal DNA scanned with this sampler.
@@ -35,10 +33,14 @@
if(dna_vault_ref?.resolve())
// Weirdly we can upload to any existing DNA vault so long as we're linked to any other existing DNA vault.
return try_upload_dna(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING
- else
- return try_linking_vault(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING
+ return try_linking_vault(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING
+
+ if (!valid_scan_target(interacting_with))
+ return NONE
+
+ if (scan_dna(interacting_with, user))
+ return ITEM_INTERACT_SUCCESS
- scan_dna(interacting_with, user)
return ITEM_INTERACT_BLOCKING
/obj/item/dna_probe/proc/try_linking_vault(obj/machinery/dna_vault/target, mob/user)
@@ -78,7 +80,7 @@
playsound(user, 'sound/machines/buzz-sigh.ogg', 50)
balloon_alert(user, "need database!")
return
- if((allowed_scans & DNA_PROBE_SCAN_PLANTS) && istype(target, /obj/machinery/hydroponics))
+ if(istype(target, /obj/machinery/hydroponics))
var/obj/machinery/hydroponics/hydro_tray = target
if(!hydro_tray.myseed)
return
@@ -90,11 +92,12 @@
return
if(hydro_tray.plant_status != HYDROTRAY_PLANT_HARVESTABLE) // So it's bit harder.
to_chat(user, span_alert("Plant needs to be ready to harvest to perform full data scan.")) //Because space dna is actually magic
- return .
+ return
stored_dna_plants[hydro_tray.myseed.type] = TRUE
playsound(src, 'sound/misc/compiler-stage2.ogg', 50)
balloon_alert(user, "data added")
- else if((allowed_scans & DNA_PROBE_SCAN_HUMANS) && ishuman(target))
+ return TRUE
+ else if(ishuman(target))
var/mob/living/carbon/human/human_target = target
if(our_vault.human_dna[human_target.dna.unique_identity])
to_chat(user, span_notice("Humanoid data already present in vault storage."))
@@ -108,23 +111,40 @@
stored_dna_human[human_target.dna.unique_identity] = TRUE
playsound(src, 'sound/misc/compiler-stage2.ogg', 50)
balloon_alert(user, "data added")
+ return TRUE
+
+ if(!isliving(target))
+ return
+
+ var/static/list/non_simple_animals = typecacheof(list(/mob/living/carbon/alien))
+ if(!isanimal_or_basicmob(target) && !is_type_in_typecache(target, non_simple_animals) && !ismonkey(target))
+ return
+
+ var/mob/living/living_target = target
+ if(our_vault.animal_dna[living_target.type])
+ to_chat(user, span_notice("Animal data already present in vault storage."))
+ return
+ if(stored_dna_animal[living_target.type])
+ to_chat(user, span_notice("Animal data already present in local storage."))
+ return
+ if(!(living_target.mob_biotypes & MOB_ORGANIC))
+ to_chat(user, span_alert("No compatible DNA detected."))
+ return .
+ stored_dna_animal[living_target.type] = TRUE
+ playsound(src, 'sound/misc/compiler-stage2.ogg', 50)
+ balloon_alert(user, "data added")
+ return TRUE
- else if((allowed_scans & DNA_PROBE_SCAN_ANIMALS) && isliving(target))
+/obj/item/dna_probe/proc/valid_scan_target(atom/target)
+ if((allowed_scans & DNA_PROBE_SCAN_PLANTS) && istype(target, /obj/machinery/hydroponics))
+ return TRUE
+ if((allowed_scans & DNA_PROBE_SCAN_HUMANS) && ishuman(target))
+ return TRUE
+ if((allowed_scans & DNA_PROBE_SCAN_ANIMALS) && isliving(target))
var/static/list/non_simple_animals = typecacheof(list(/mob/living/carbon/alien))
if(isanimal_or_basicmob(target) || is_type_in_typecache(target, non_simple_animals) || ismonkey(target))
- var/mob/living/living_target = target
- if(our_vault.animal_dna[living_target.type])
- to_chat(user, span_notice("Animal data already present in vault storage."))
- return
- if(stored_dna_animal[living_target.type])
- to_chat(user, span_notice("Animal data already present in local storage."))
- return
- if(!(living_target.mob_biotypes & MOB_ORGANIC))
- to_chat(user, span_alert("No compatible DNA detected."))
- return .
- stored_dna_animal[living_target.type] = TRUE
- playsound(src, 'sound/misc/compiler-stage2.ogg', 50)
- balloon_alert(user, "data added")
+ return TRUE
+ return FALSE
#define CARP_MIX_DNA_TIMER (15 SECONDS)
@@ -132,6 +152,8 @@
/obj/item/dna_probe/carp_scanner
name = "Carp DNA Sampler"
desc = "Can be used to take chemical and genetic samples of animals."
+ ///Whether we have Carp DNA
+ var/carp_dna_loaded = FALSE
/obj/item/dna_probe/carp_scanner/examine_more(mob/user)
. = ..()
@@ -145,6 +167,11 @@
else
return ..()
+/obj/item/dna_probe/carp_scanner/valid_scan_target(atom/target)
+ if (istype(target, /mob/living/basic/carp))
+ return TRUE
+ return ..()
+
/obj/item/dna_probe/carp_scanner/attack_self(mob/user, modifiers)
. = ..()
if(!carp_dna_loaded)
diff --git a/code/game/objects/items/eightball.dm b/code/game/objects/items/eightball.dm
index 719789b2a936c0..bb063f4a1f461a 100644
--- a/code/game/objects/items/eightball.dm
+++ b/code/game/objects/items/eightball.dm
@@ -63,7 +63,9 @@
shaking = TRUE
- start_shaking(user)
+ if (!start_shaking(user))
+ return
+
if(do_after(user, shake_time))
say(get_answer())
@@ -73,7 +75,7 @@
shaking = FALSE
/obj/item/toy/eightball/proc/start_shaking(mob/user)
- return
+ return TRUE
/obj/item/toy/eightball/proc/get_answer()
return pick(possible_answers)
@@ -98,8 +100,7 @@
/obj/item/toy/eightball/haunted
shake_time = 30 SECONDS
cooldown_time = 3 MINUTES
- var/last_message = "Nothing!"
- var/selected_message
+ var/selected_message = "Nothing!"
//these kind of store the same thing but one is easier to work with.
var/list/votes = list()
var/list/voted = list()
@@ -137,7 +138,6 @@
for (var/answer in haunted_answers)
votes[answer] = 0
SSpoints_of_interest.make_point_of_interest(src)
- become_hearing_sensitive()
/obj/item/toy/eightball/haunted/MakeHaunted()
return FALSE
@@ -150,20 +150,19 @@
interact(user)
return ..()
-/obj/item/toy/eightball/haunted/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, list/message_mods = list(), message_range)
- . = ..()
- last_message = raw_message
-
/obj/item/toy/eightball/haunted/start_shaking(mob/user)
// notify ghosts that someone's shaking a haunted eightball
// and inform them of the message, (hopefully a yes/no question)
- selected_message = last_message
+ selected_message = tgui_input_text(user, "What is your question?", "Eightball") || initial(selected_message)
+ if (!(src in user.held_items))
+ return FALSE
notify_ghosts(
"[user] is shaking [src], hoping to get an answer to \"[selected_message]\"",
source = src,
header = "Magic eightball",
click_interact = TRUE,
)
+ return TRUE
/obj/item/toy/eightball/haunted/get_answer()
var/top_amount = 0
@@ -211,13 +210,13 @@
data["question"] = selected_message
data["answers"] = list()
- for(var/pa in haunted_answers)
- var/list/L = list()
- L["answer"] = pa
- L["amount"] = votes[pa]
- L["selected"] = voted[user.ckey]
+ for(var/vote in haunted_answers)
+ var/list/answer_data = list()
+ answer_data["answer"] = vote
+ answer_data["amount"] = votes[vote]
+ answer_data["selected"] = voted[user.ckey]
- data["answers"] += list(L)
+ data["answers"] += list(answer_data)
return data
/obj/item/toy/eightball/haunted/ui_act(action, params)
diff --git a/code/game/objects/items/food/bait.dm b/code/game/objects/items/food/bait.dm
index 047a8a7cd58ce7..f31eb44f308eb0 100644
--- a/code/game/objects/items/food/bait.dm
+++ b/code/game/objects/items/food/bait.dm
@@ -60,9 +60,23 @@
*/
/obj/item/food/bait/doughball/synthetic
name = "synthetic doughball"
- icon_state = "doughball"
+ icon_state = "doughball_blue"
preserved_food = TRUE
/obj/item/food/bait/doughball/synthetic/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_OMNI_BAIT, INNATE_TRAIT)
+
+///Found in the can of omni-baits, only available from the super fishing toolbox, from the fishing mystery box.
+/obj/item/food/bait/doughball/synthetic/super
+ name = "super-doughball"
+ desc = "No fish will be able to resist this."
+ bait_quality = TRAIT_GREAT_QUALITY_BAIT
+
+///Used by the advanced fishing rod
+/obj/item/food/bait/doughball/syntethic/unconsumable
+
+/obj/item/food/bait/doughball/synthetic/unconsumable/Initialize(mapload)
+ . = ..()
+ ADD_TRAIT(src, TRAIT_BAIT_UNCONSUMABLE, INNATE_TRAIT)
+
diff --git a/code/game/objects/items/food/cake.dm b/code/game/objects/items/food/cake.dm
index 0b443554bb3b67..ec3e0a0390caa6 100644
--- a/code/game/objects/items/food/cake.dm
+++ b/code/game/objects/items/food/cake.dm
@@ -45,6 +45,10 @@
foodtypes = GRAIN | DAIRY | SUGAR
slice_type = /obj/item/food/cakeslice/plain
+/obj/item/food/cake/plain/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/customizable_reagent_holder, /obj/item/food/cake/empty, CUSTOM_INGREDIENT_ICON_FILL, max_ingredients = 16)
+
/obj/item/food/cakeslice/plain
name = "plain cake slice"
desc = "Just a slice of cake, it is enough for everyone."
@@ -52,6 +56,23 @@
tastes = list("sweetness" = 2, "cake" = 5)
foodtypes = GRAIN | DAIRY | SUGAR
+/obj/item/food/cake/empty
+ name = "cake"
+ desc = "A custom cake made by an insane chef."
+ icon_state = "cake_custom"
+ foodtypes = GRAIN | DAIRY | SUGAR
+ slice_type = /obj/item/food/cakeslice/empty
+
+/obj/item/food/cakeslice/empty
+ name = "cake slice"
+ desc = "A slice of custom cake, made by an insane chef."
+ icon_state = "cake_custom_slice"
+ foodtypes = GRAIN | DAIRY | SUGAR
+
+/obj/item/food/cakeslice/empty/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/customizable_reagent_holder, null, CUSTOM_INGREDIENT_ICON_FILL, max_ingredients = 16)
+
/obj/item/food/cake/carrot
name = "carrot cake"
desc = "A favorite desert of a certain wascally wabbit. Not a lie."
@@ -521,6 +542,7 @@
foodtypes = GRAIN | SUGAR | DAIRY
slice_type = /obj/item/food/cakeslice/clown_slice
crafting_complexity = FOOD_COMPLEXITY_5
+ crafted_food_buff = /datum/status_effect/food/trait/waddle
/obj/item/food/cakeslice/clown_slice
name = "clown cake slice"
@@ -534,6 +556,7 @@
tastes = list("cake" = 1, "sugar" = 1, "joy" = 10)
foodtypes = GRAIN | SUGAR | DAIRY
crafting_complexity = FOOD_COMPLEXITY_5
+ crafted_food_buff = /datum/status_effect/food/trait/waddle
/obj/item/food/cake/trumpet
name = "spaceman's cake"
diff --git a/code/game/objects/items/food/donkpocket.dm b/code/game/objects/items/food/donkpocket.dm
index d4b4636f15c9b3..b21149da8d044b 100644
--- a/code/game/objects/items/food/donkpocket.dm
+++ b/code/game/objects/items/food/donkpocket.dm
@@ -259,3 +259,105 @@
)
tastes = list("meat" = 2, "dough" = 2, "inner peace" = 1)
foodtypes = GRAIN
+
+/obj/item/food/donkpocket/deluxe
+ name = "\improper Donk-pocket Deluxe"
+ desc = "Donk Co's latest product. Its recipe is a closely guarded secret."
+ icon_state = "donkpocketdeluxe"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 4,
+ /datum/reagent/consumable/nutriment/protein = 2,
+ /datum/reagent/consumable/nutriment/vitamin = 1,
+ /datum/reagent/medicine/omnizine = 2,
+ )
+ tastes = list("quality meat" = 2, "dough" = 2, "raw fanciness" = 1)
+ foodtypes = GRAIN | MEAT
+ crafting_complexity = FOOD_COMPLEXITY_4
+
+ warm_type = /obj/item/food/donkpocket/warm/deluxe
+ var/static/list/deluxe_added_reagents = list(
+ /datum/reagent/medicine/omnizine = 8,
+ )
+
+/obj/item/food/donkpocket/deluxe/make_bakeable()
+ AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, deluxe_added_reagents)
+
+/obj/item/food/donkpocket/deluxe/make_microwaveable()
+ AddElement(/datum/element/microwavable, warm_type, deluxe_added_reagents)
+
+/obj/item/food/donkpocket/warm/deluxe
+ name = "warm Donk-pocket Deluxe"
+ desc = "Donk Co's latest product. It's crispy warm and oh-so perfectly toasted. Damn, that's a good looking Donk."
+ icon_state = "donkpocketdeluxe"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 4,
+ /datum/reagent/consumable/nutriment/protein = 2,
+ /datum/reagent/consumable/nutriment/vitamin = 1,
+ /datum/reagent/medicine/omnizine = 10,
+ )
+ tastes = list("quality meat" = 2, "dough" = 2, "fanciness" = 1)
+ foodtypes = GRAIN | MEAT | FRIED
+
+/obj/item/food/donkpocket/deluxe/nocarb
+ name = "/improper Meat-pocket"
+ desc = "The food of choice for the carnivorous traitor."
+ icon_state = "donkpocketdeluxenocarb"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 4,
+ /datum/reagent/consumable/nutriment/protein = 3,
+ /datum/reagent/medicine/omnizine = 2,
+ )
+ tastes = list("raw meat" = 2, "more meat" = 2, "no carbs" = 1)
+ foodtypes = MEAT | RAW
+ crafting_complexity = FOOD_COMPLEXITY_4
+
+ warm_type = /obj/item/food/donkpocket/warm/deluxe/nocarb
+
+/obj/item/food/donkpocket/deluxe/meat/make_bakeable()
+ AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, deluxe_added_reagents)
+
+/obj/item/food/donkpocket/deluxe/meat/make_microwaveable()
+ AddElement(/datum/element/microwavable, warm_type, deluxe_added_reagents)
+
+/obj/item/food/donkpocket/warm/deluxe/nocarb
+ name = "warm Meat-pocket"
+ desc = "The warm food of choice for the carnivorous traitor."
+ icon_state = "donkpocketdeluxenocarb"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 4,
+ /datum/reagent/consumable/nutriment/protein = 3,
+ /datum/reagent/medicine/omnizine = 10,
+ )
+ tastes = list("meat" = 2, "more meat" = 2, "no carbs" = 1)
+ foodtypes = MEAT
+
+/obj/item/food/donkpocket/deluxe/vegan
+ name = "/improper Donk-roll"
+ desc = "The classic station snack, now with rice! Certified vegan and cruelty free by the Animal Liberation Front."
+ icon_state = "donkpocketdeluxevegan"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 4,
+ /datum/reagent/consumable/nutriment/vitamin = 3,
+ /datum/reagent/medicine/omnizine = 2,
+ )
+ tastes = list("rice patty" = 2, "dough" = 2, "peppery kick" = 1)
+ foodtypes = GRAIN | VEGETABLES
+ crafting_complexity = FOOD_COMPLEXITY_4
+
+/obj/item/food/donkpocket/deluxe/vegan/make_bakeable()
+ AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, deluxe_added_reagents)
+
+/obj/item/food/donkpocket/deluxe/vegan/make_microwaveable()
+ AddElement(/datum/element/microwavable, warm_type, deluxe_added_reagents)
+
+/obj/item/food/donkpocket/warm/deluxe/vegan
+ name = "warm Donk-roll"
+ desc = "The classic station snack, now with rice! It's been fried to perfection."
+ icon_state = "donkpocketdeluxevegan"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 4,
+ /datum/reagent/consumable/nutriment/vitamin = 3,
+ /datum/reagent/medicine/omnizine = 10,
+ )
+ tastes = list("rice patty" = 2, "fried dough" = 2, "peppery kick" = 1)
+ foodtypes = GRAIN | VEGETABLES
diff --git a/code/game/objects/items/food/egg.dm b/code/game/objects/items/food/egg.dm
index b669e16b103cdc..bcc61e721e2113 100644
--- a/code/game/objects/items/food/egg.dm
+++ b/code/game/objects/items/food/egg.dm
@@ -277,6 +277,7 @@ GLOBAL_VAR_INIT(chicks_from_eggs, 0)
foodtypes = MEAT | BREAKFAST | DAIRY
venue_value = FOOD_PRICE_CHEAP
crafting_complexity = FOOD_COMPLEXITY_2
+ crafted_food_buff = /datum/status_effect/food/speech/french
/obj/item/food/omelette/attackby(obj/item/item, mob/user, params)
if(istype(item, /obj/item/kitchen/fork))
diff --git a/code/game/objects/items/food/lizard.dm b/code/game/objects/items/food/lizard.dm
index 47b5ff75109168..2048c997ef9ad4 100644
--- a/code/game/objects/items/food/lizard.dm
+++ b/code/game/objects/items/food/lizard.dm
@@ -156,6 +156,7 @@
desc = "Another example of cultural crossover between lizards and humans, desert snail escargot is closer to the Roman dish cocleas than the contemporary French escargot. It's a common street food in the desert cities."
icon = 'icons/obj/food/lizard.dmi'
icon_state = "lizard_escargot"
+ trash_type = /obj/item/reagent_containers/cup/bowl
food_reagents = list(
/datum/reagent/consumable/nutriment/protein = 6,
/datum/reagent/consumable/nutriment/vitamin = 4,
@@ -188,6 +189,7 @@
desc = "One of the many human foods to make its way to the lizards was french fries, which are called poms-franzisks in Draconic. When topped with barbecued meat and sauce, they make a hearty meal."
icon = 'icons/obj/food/lizard.dmi'
icon_state = "lizard_fries"
+ trash_type = /obj/item/plate
food_reagents = list(
/datum/reagent/consumable/nutriment = 4,
/datum/reagent/consumable/nutriment/protein = 6,
@@ -887,7 +889,7 @@
/obj/item/food/burger/rootrib
name = "rootrib"
- desc = "An elusive rib shaped burger with limited availablity across the galaxy. Now meeting subhuman requirements."
+ desc = "An elusive rib shaped burger with limited availability across the galaxy. Now meeting subhuman requirements."
icon_state = "rootrib"
icon = 'icons/obj/food/lizard.dmi'
food_reagents = list(
diff --git a/code/game/objects/items/food/martian.dm b/code/game/objects/items/food/martian.dm
index 7ceaf1878176c6..748610457ec414 100644
--- a/code/game/objects/items/food/martian.dm
+++ b/code/game/objects/items/food/martian.dm
@@ -102,6 +102,7 @@
desc = "A spice paste from Indonesia, used widely in cooking throughout South East Asia."
icon = 'icons/obj/food/martian.dmi'
icon_state = "sambal"
+ trash_type = /obj/item/reagent_containers/cup/bowl
food_reagents = list(
/datum/reagent/consumable/nutriment/vitamin = 5,
/datum/reagent/consumable/capsaicin = 2
@@ -519,7 +520,7 @@
crafting_complexity = FOOD_COMPLEXITY_3
/obj/item/food/takoyaki/russian
- name = "russian takoyaki"
+ name = "Russian takoyaki"
desc = "A dangerous twist on a classic dish, that makes for the perfect cover for evading the police."
icon = 'icons/obj/food/martian.dmi'
icon_state = "russian_takoyaki"
@@ -535,7 +536,7 @@
/obj/item/food/takoyaki/taco
name = "tacoyaki"
- desc = "Straight outta Mars' most innovative street food stands, it's tacoyaki- trading octopus for taco meat and corn, and worcestershire sauce for queso. ¡Tan sabroso!"
+ desc = "Straight outta Mars' most innovative street food stands, it's tacoyaki- trading octopus for taco meat and corn, and Worcestershire sauce for queso. ¡Tan sabroso!"
icon = 'icons/obj/food/martian.dmi'
icon_state = "tacoyaki"
food_reagents = list(
diff --git a/code/game/objects/items/food/meatdish.dm b/code/game/objects/items/food/meatdish.dm
index c03470ff416b3f..63f42d0d83bcc9 100644
--- a/code/game/objects/items/food/meatdish.dm
+++ b/code/game/objects/items/food/meatdish.dm
@@ -500,7 +500,7 @@
w_class = WEIGHT_CLASS_SMALL
crafting_complexity = FOOD_COMPLEXITY_1
-///Exists purely for the crafting recipe (because itll take subtypes)
+///Exists purely for the crafting recipe (because it'll take subtypes)
/obj/item/food/patty/plain
/obj/item/food/patty/human
@@ -895,9 +895,10 @@
/obj/item/food/beef_stroganoff
name = "beef stroganoff"
- desc = "A russian dish that consists of beef and sauce. Really popular in japan, or at least that's what my animes would allude to."
+ desc = "A Russian dish that consists of beef and sauce. Really popular in Japan, or at least that's what my animes would allude to."
icon = 'icons/obj/food/meat.dmi'
icon_state = "beefstroganoff"
+ trash_type = /obj/item/reagent_containers/cup/bowl
food_reagents = list(
/datum/reagent/consumable/nutriment/protein = 16,
/datum/reagent/consumable/nutriment/vitamin = 4,
@@ -1076,7 +1077,7 @@
crafting_complexity = FOOD_COMPLEXITY_5
/obj/item/food/full_english
- name = "full english breakfast"
+ name = "full English breakfast"
desc = "A hearty plate with all the trimmings, representing the pinnacle of the breakfast art."
icon = 'icons/obj/food/meat.dmi'
icon_state = "full_english"
diff --git a/code/game/objects/items/food/meatslab.dm b/code/game/objects/items/food/meatslab.dm
index a5fe073e56f3fb..3f8cb918eced9a 100644
--- a/code/game/objects/items/food/meatslab.dm
+++ b/code/game/objects/items/food/meatslab.dm
@@ -150,7 +150,7 @@
blood_decal_type = null
/obj/item/food/meat/slab/human/mutant/skeleton/make_processable()
- return //skeletons dont have cutlets
+ return //skeletons don't have cutlets
/obj/item/food/meat/slab/human/mutant/zombie
name = "meat (rotten)"
diff --git a/code/game/objects/items/food/mexican.dm b/code/game/objects/items/food/mexican.dm
index 396e351ff4bde6..fa66db1450c8fd 100644
--- a/code/game/objects/items/food/mexican.dm
+++ b/code/game/objects/items/food/mexican.dm
@@ -196,12 +196,14 @@
w_class = WEIGHT_CLASS_SMALL
venue_value = FOOD_PRICE_LEGENDARY
crafting_complexity = FOOD_COMPLEXITY_5
+ crafted_food_buff = /datum/status_effect/food/trait/ashstorm_immune
/obj/item/food/chipsandsalsa
name = "chips and salsa"
desc = "Some tortilla chips with a cup of zesty salsa. Highly addictive!"
icon = 'icons/obj/food/mexican.dmi'
icon_state = "chipsandsalsa"
+ trash_type = /obj/item/reagent_containers/cup/bowl
food_reagents = list(
/datum/reagent/consumable/nutriment = 4,
/datum/reagent/consumable/capsaicin = 2,
@@ -331,6 +333,7 @@
desc = "A not-so liquid salsa made of pineapples, tomatoes, onions, and chilis. Makes for delightfully contrasting flavors."
icon = 'icons/obj/food/mexican.dmi'
icon_state = "pineapple_salsa"
+ trash_type = /obj/item/reagent_containers/cup/bowl
food_reagents = list(
/datum/reagent/consumable/nutriment = 6,
/datum/reagent/consumable/nutriment/vitamin = 6,
diff --git a/code/game/objects/items/food/misc.dm b/code/game/objects/items/food/misc.dm
index 8ef85c8ea21898..4e8b8cbf2209c3 100644
--- a/code/game/objects/items/food/misc.dm
+++ b/code/game/objects/items/food/misc.dm
@@ -16,6 +16,87 @@
juice_typepath = /datum/reagent/consumable/watermelonjuice
w_class = WEIGHT_CLASS_SMALL
+/obj/item/food/watermelonmush
+ name = "watermelon mush"
+ desc = "A plop of watery goodness."
+ icon = 'icons/obj/service/hydroponics/harvest.dmi'
+ icon_state = "watermelonpulp"
+ food_reagents = list(
+ /datum/reagent/water = 2,
+ /datum/reagent/consumable/nutriment/vitamin = 0.1,
+ /datum/reagent/consumable/nutriment = 0.5,
+ )
+ tastes = list("watermelon" = 1)
+ foodtypes = FRUIT
+ food_flags = FOOD_FINGER_FOOD
+ juice_typepath = /datum/reagent/consumable/watermelonjuice
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/holymelonslice
+ name = "holymelon slice"
+ desc = "A slice of holy goodness."
+ icon = 'icons/obj/service/hydroponics/harvest.dmi'
+ icon_state = "holymelonslice"
+ food_reagents = list(
+ /datum/reagent/water/holywater = 0.5,
+ /datum/reagent/consumable/nutriment/vitamin = 0.2,
+ /datum/reagent/consumable/nutriment = 1,
+ )
+ tastes = list("holymelon" = 1)
+ foodtypes = FRUIT
+ food_flags = FOOD_FINGER_FOOD
+ juice_typepath = /datum/reagent/water/holywater
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/holymelonmush
+ name = "holymelon mush"
+ desc = "A plop of holy goodness."
+ icon = 'icons/obj/service/hydroponics/harvest.dmi'
+ icon_state = "holymelonpulp"
+ food_reagents = list(
+ /datum/reagent/water/holywater = 1,
+ /datum/reagent/consumable/nutriment/vitamin = 0.1,
+ /datum/reagent/consumable/nutriment = 0.5,
+ )
+ tastes = list("holymelon" = 1)
+ foodtypes = FRUIT
+ food_flags = FOOD_FINGER_FOOD
+ juice_typepath = /datum/reagent/water/holywater
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/barrelmelonslice
+ name = "barrelmelon slice"
+ desc = "A slice of beery goodness."
+ icon = 'icons/obj/service/hydroponics/harvest.dmi'
+ icon_state = "barrelmelonslice"
+ food_reagents = list(
+ /datum/reagent/consumable/ethanol/beer = 1,
+ /datum/reagent/consumable/nutriment/vitamin = 0.2,
+ /datum/reagent/consumable/nutriment = 1,
+ )
+ tastes = list("beer" = 1)
+ foodtypes = FRUIT
+ food_flags = FOOD_FINGER_FOOD
+ juice_typepath = /datum/reagent/consumable/ethanol/beer
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/food/barrelmelonmush
+ name = "barrelmelon mush"
+ desc = "A plop of beery goodness."
+ icon = 'icons/obj/service/hydroponics/harvest.dmi'
+ icon_state = "barrelmelonpulp"
+ food_reagents = list(
+ /datum/reagent/consumable/ethanol/beer = 2,
+ /datum/reagent/consumable/nutriment/vitamin = 0.1,
+ /datum/reagent/consumable/nutriment = 0.5,
+ )
+ tastes = list("beer" = 1)
+ foodtypes = FRUIT
+ food_flags = FOOD_FINGER_FOOD
+ juice_typepath = /datum/reagent/consumable/ethanol/beer
+ w_class = WEIGHT_CLASS_SMALL
+
+
/obj/item/food/appleslice
name = "apple slice"
desc = "The perfect after-school snack."
diff --git a/code/game/objects/items/food/monkeycube.dm b/code/game/objects/items/food/monkeycube.dm
index a364a251a83443..02882bb3776f43 100644
--- a/code/game/objects/items/food/monkeycube.dm
+++ b/code/game/objects/items/food/monkeycube.dm
@@ -82,7 +82,7 @@
/obj/item/food/monkeycube/gorilla
name = "gorilla cube"
- desc = "A Waffle Co. brand gorilla cube. Now with extra molecules!"
+ desc = "A Waffle Corp. brand gorilla cube. Now with extra molecules!"
bite_consumption = 20
food_reagents = list(
/datum/reagent/monkey_powder = 30,
diff --git a/code/game/objects/items/food/moth.dm b/code/game/objects/items/food/moth.dm
index b2d9dfdb8fe37a..367a3f29b5cc45 100644
--- a/code/game/objects/items/food/moth.dm
+++ b/code/game/objects/items/food/moth.dm
@@ -9,6 +9,7 @@
Herbs are one such addition, and are particularly beloved."
icon = 'icons/obj/food/moth.dmi'
icon_state = "herby_cheese"
+ trash_type = /obj/item/reagent_containers/cup/bowl
food_reagents = list(/datum/reagent/consumable/nutriment/protein = 6)
tastes = list("cheese" = 1, "herbs" = 1)
foodtypes = DAIRY | VEGETABLES
@@ -461,6 +462,7 @@
it's just sorta what it's always been called."
icon = 'icons/obj/food/moth.dmi'
icon_state = "hua_mulan_congee"
+ trash_type = /obj/item/reagent_containers/cup/bowl
food_reagents = list(
/datum/reagent/consumable/nutriment = 6,
/datum/reagent/consumable/nutriment/vitamin = 10,
@@ -476,6 +478,7 @@
desc = "Polenta loaded with cheese, served with a few discs of fried eggplant and some tomato sauce. Lække!"
icon = 'icons/obj/food/moth.dmi'
icon_state = "fried_eggplant_polenta"
+ trash_type = /obj/item/reagent_containers/cup/bowl
food_reagents = list(
/datum/reagent/consumable/nutriment/protein = 12,
/datum/reagent/consumable/nutriment/vitamin = 6,
diff --git a/code/game/objects/items/food/pastries.dm b/code/game/objects/items/food/pastries.dm
index 1024e44c625f30..83f30ab0b06bdf 100644
--- a/code/game/objects/items/food/pastries.dm
+++ b/code/game/objects/items/food/pastries.dm
@@ -327,6 +327,20 @@
tastes = list("cake" = 3, "blue cherry" = 1)
crafting_complexity = FOOD_COMPLEXITY_3
+/obj/item/food/jupitercupcake
+ name = "jupiter-cup-cake"
+ desc = "A static dessert."
+ icon_state = "jupitercupcake"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 6,
+ /datum/reagent/consumable/nutriment/vitamin = 2,
+ /datum/reagent/consumable/caramel = 3,
+ /datum/reagent/consumable/liquidelectricity/enriched = 3,
+ )
+ tastes = list("cake" = 3, "caramel" = 2, "zap" = 1)
+ crafting_complexity = FOOD_COMPLEXITY_3
+ crafted_food_buff = /datum/status_effect/food/trait/shockimmune
+
/obj/item/food/honeybun
name = "honey bun"
desc = "A sticky pastry bun glazed with honey."
diff --git a/code/game/objects/items/food/pie.dm b/code/game/objects/items/food/pie.dm
index e57759915208d1..0cb5af860e8422 100644
--- a/code/game/objects/items/food/pie.dm
+++ b/code/game/objects/items/food/pie.dm
@@ -11,7 +11,7 @@
crafting_complexity = FOOD_COMPLEXITY_2
/// type is spawned 5 at a time and replaces this pie when processed by cutting tool
var/obj/item/food/pieslice/slice_type
- /// so that the yield can change if it isnt 5
+ /// so that the yield can change if it isn't 5
var/yield = 5
/obj/item/food/pie/make_processable()
@@ -39,6 +39,27 @@
foodtypes = GRAIN
crafting_complexity = FOOD_COMPLEXITY_2
+/obj/item/food/pie/plain/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/customizable_reagent_holder, /obj/item/food/pie/empty, CUSTOM_INGREDIENT_ICON_FILL, max_ingredients = 8)
+
+/obj/item/food/pie/empty
+ name = "pie"
+ desc = "A custom pie made by a crazed chef."
+ icon_state = "pie_custom"
+ foodtypes = GRAIN
+ slice_type = /obj/item/food/pieslice/empty
+
+/obj/item/food/pieslice/empty
+ name = "pie slice"
+ desc = "A custom pie slice made by a crazed chef."
+ icon_state = "pie_custom_slice"
+ foodtypes = GRAIN
+
+/obj/item/food/pieslice/empty/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/customizable_reagent_holder, null, CUSTOM_INGREDIENT_ICON_FILL, max_ingredients = 8)
+
/obj/item/food/pie/cream
name = "banana cream pie"
desc = "Just like back home, on clown planet! HONK!"
@@ -77,7 +98,7 @@
living_target_getting_hit.visible_message(span_warning("[living_target_getting_hit] is creamed by [src]!"), span_userdanger("You've been creamed by [src]!"))
playsound(living_target_getting_hit, SFX_DESECRATION, 50, TRUE)
if(is_creamable && is_type_in_typecache(hit_atom, GLOB.creamable))
- hit_atom.AddComponent(/datum/component/creamed, src)
+ hit_atom.AddComponent(/datum/component/face_decal/creampie, "creampie", EXTERNAL_FRONT)
qdel(src)
/obj/item/food/pie/cream/nostun
@@ -316,6 +337,7 @@
)
tastes = list("nothing" = 3)
foodtypes = GRAIN
+ crafted_food_buff = /datum/status_effect/food/trait/mute
/obj/item/food/pie/berrytart
name = "berry tart"
diff --git a/code/game/objects/items/food/pizza.dm b/code/game/objects/items/food/pizza.dm
index 71dd87af8e1838..bdaab0a72851f4 100644
--- a/code/game/objects/items/food/pizza.dm
+++ b/code/game/objects/items/food/pizza.dm
@@ -169,7 +169,7 @@
/obj/item/food/pizza/vegetable
name = "vegetable pizza"
- desc = "No one of Tomatos Sapiens were harmed during making this pizza."
+ desc = "No one of Tomatoes Sapiens were harmed during making this pizza."
icon_state = "vegetablepizza"
food_reagents = list(
/datum/reagent/consumable/nutriment = 25,
diff --git a/code/game/objects/items/food/snacks.dm b/code/game/objects/items/food/snacks.dm
index cb64c6df52204a..722663cf265e06 100644
--- a/code/game/objects/items/food/snacks.dm
+++ b/code/game/objects/items/food/snacks.dm
@@ -400,7 +400,7 @@ GLOBAL_LIST_INIT(safe_peanut_types, populate_safe_peanut_types())
/obj/item/food/semki
name = "\improper Semki Sunflower Seeds"
- desc = "A pack of roasted sunflower seeds. Beloved by space russians and babushka alike."
+ desc = "A pack of roasted sunflower seeds. Beloved by space Russians and babushka alike."
icon_state = "semki"
trash_type = /obj/item/trash/semki
food_reagents = list(
diff --git a/code/game/objects/items/food/spaghetti.dm b/code/game/objects/items/food/spaghetti.dm
index cab4a62a29f3b3..bf1fca9332a08d 100644
--- a/code/game/objects/items/food/spaghetti.dm
+++ b/code/game/objects/items/food/spaghetti.dm
@@ -249,3 +249,17 @@
tastes = list("noodles" = 5, "fried tofu" = 4, "lime" = 2, "peanut" = 3, "onion" = 2)
foodtypes = GRAIN | VEGETABLES | NUTS | FRUIT
crafting_complexity = FOOD_COMPLEXITY_4
+
+/obj/item/food/spaghetti/carbonara
+ name = "spaghetti carbonara"
+ desc = "Silky eggs, crispy pork, cheesy bliss. Mamma mia!"
+ icon_state = "carbonara"
+ food_reagents = list(
+ /datum/reagent/consumable/nutriment = 10,
+ /datum/reagent/consumable/nutriment/protein = 6,
+ /datum/reagent/consumable/nutriment/vitamin = 4,
+ )
+ tastes = list("spaghetti" = 1, "parmigiano reggiano" = 1, "guanciale" = 1)
+ foodtypes = GRAIN | MEAT | DAIRY
+ crafting_complexity = FOOD_COMPLEXITY_4
+ crafted_food_buff = /datum/status_effect/food/speech/italian
diff --git a/code/game/objects/items/granters/crafting/advanced_donk_recipes.dm b/code/game/objects/items/granters/crafting/advanced_donk_recipes.dm
new file mode 100644
index 00000000000000..1ba2502f37eec9
--- /dev/null
+++ b/code/game/objects/items/granters/crafting/advanced_donk_recipes.dm
@@ -0,0 +1,21 @@
+
+/obj/item/book/granter/crafting_recipe/donk_secret_recipe
+ name = "Donk Co. Secret Recipe"
+ desc = "Documents detailing how to make several Donk Co. branded prototypes."
+ crafting_recipe_types = list(
+ /datum/crafting_recipe/food/donkpocket/deluxe,
+ /datum/crafting_recipe/food/donkpocket/deluxe/nocarb,
+ /datum/crafting_recipe/food/donkpocket/deluxe/vegan,
+ )
+ icon = 'icons/obj/service/bureaucracy.dmi'
+ icon_state = "docs_part"
+ uses = INFINITY
+ remarks = list(
+ "It's written in code...",
+ "Decyphering...",
+ "Studying...",
+ "Got to get the steps in order...",
+ "The six basic food groups...",
+ "The secret formula!",
+ "Three different variants...",
+ )
diff --git a/code/game/objects/items/granters/crafting/fletching.dm b/code/game/objects/items/granters/crafting/fletching.dm
new file mode 100644
index 00000000000000..91ce20c43dd89c
--- /dev/null
+++ b/code/game/objects/items/granters/crafting/fletching.dm
@@ -0,0 +1,22 @@
+
+/obj/item/book/granter/crafting_recipe/fletching
+ name = "Whittle Me This: Fletching for the Modern Spacer"
+ desc = "A how-to guide to crafting and maintaining wooden bows, fletching arrows, and... making violins?"
+ crafting_recipe_types = list(
+ /datum/crafting_recipe/arrow,
+ /datum/crafting_recipe/plastic_arrow,
+ /datum/crafting_recipe/shortbow,
+ /datum/crafting_recipe/holy_arrow,
+ ///datum/crafting_recipe/arrow_quiver, // SKYRAT EDIT REMOVAL: public-knowledge quiver
+ /datum/crafting_recipe/violin,
+ )
+ icon_state = "book4"
+ uses = INFINITY
+ remarks = list(
+ "Okay, so the quality of the wood has some impact.",
+ "I feel like the violin chapter is in here as a joke, surely...",
+ "The author seems oddly proud about how many years they've been hunting in 'these parts'...",
+ "i really wish they'd stop with all the marriage euphemisms...",
+ "I need membership? Membership with what?",
+ "Okay, I think I get the point already...",
+ )
diff --git a/code/game/objects/items/grenades/_grenade.dm b/code/game/objects/items/grenades/_grenade.dm
index 6c84b5cf46eea7..a9fe7e65809ab9 100644
--- a/code/game/objects/items/grenades/_grenade.dm
+++ b/code/game/objects/items/grenades/_grenade.dm
@@ -17,11 +17,13 @@
obj_flags = CONDUCTS_ELECTRICITY
slot_flags = ITEM_SLOT_BELT
max_integrity = 40
+ pickup_sound = 'sound/items/grenade_pick_up.ogg'
+ drop_sound = 'sound/items/grenade_drop.ogg'
/// Bitfields which prevent the grenade from detonating if set. Includes ([GRENADE_DUD]|[GRENADE_USED])
var/dud_flags = NONE
///Is this grenade currently armed?
var/active = FALSE
- ///Is it a cluster grenade? We dont wanna spam admin logs with these.
+ ///Is it a cluster grenade? We don't wanna spam admin logs with these.
var/type_cluster = FALSE
///How long it takes for a grenade to explode after being armed
var/det_time = 5 SECONDS
@@ -46,7 +48,7 @@
var/shrapnel_type
/// the higher this number, the more projectiles are created as shrapnel
var/shrapnel_radius
- ///Did we add the component responsible for spawning sharpnel to this?
+ ///Did we add the component responsible for spawning shrapnel to this?
var/shrapnel_initialized
/obj/item/grenade/Initialize(mapload)
@@ -59,7 +61,7 @@
playsound(src, 'sound/items/eatfood.ogg', 50, TRUE)
arm_grenade(user, det_time)
user.transferItemToLoc(src, user, TRUE)//>eat a grenade set to 5 seconds >rush captain
- sleep(det_time)//so you dont die instantly
+ sleep(det_time)//so you don't die instantly
return dud_flags ? SHAME : BRUTELOSS
/obj/item/grenade/atom_deconstruct(disassembled = TRUE)
diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm
index e485490f077cda..c39e947e2bfe28 100644
--- a/code/game/objects/items/grenades/chem_grenade.dm
+++ b/code/game/objects/items/grenades/chem_grenade.dm
@@ -502,7 +502,7 @@
/obj/item/grenade/chem_grenade/ez_clean
name = "cleaner grenade"
- desc = "Waffle Co.-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas."
+ desc = "Waffle Corp. brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas."
stage = GRENADE_READY
/obj/item/grenade/chem_grenade/ez_clean/Initialize(mapload)
diff --git a/code/game/objects/items/hand_items.dm b/code/game/objects/items/hand_items.dm
index 23fa5f2ad40c96..cf752bf82accb3 100644
--- a/code/game/objects/items/hand_items.dm
+++ b/code/game/objects/items/hand_items.dm
@@ -532,6 +532,12 @@
color = COLOR_BLACK
kiss_type = /obj/projectile/kiss/death
+/obj/item/hand_item/kisser/syndie
+ name = "syndie kiss"
+ desc = "oooooo you like syndicate ur a syndiekisser"
+ color = COLOR_SYNDIE_RED
+ kiss_type = /obj/projectile/kiss/syndie
+
/obj/projectile/kiss
name = "kiss"
icon = 'icons/mob/simple/animal.dmi'
@@ -543,13 +549,21 @@
damage_type = BRUTE
damage = 0 // love can't actually hurt you
armour_penetration = 100 // but if it could, it would cut through even the thickest plate
+ var/silent_blown = FALSE
+
+/obj/projectile/kiss/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/parriable_projectile)
/obj/projectile/kiss/fire(angle, atom/direct_target)
- if(firer)
+ if(firer && !silent_blown)
name = "[name] blown by [firer]"
+
return ..()
/obj/projectile/kiss/Impact(atom/A)
+ def_zone = BODY_ZONE_HEAD // let's keep it PG, people
+
if(damage > 0 || !isliving(A)) // if we do damage or we hit a nonliving thing, we don't have to worry about a harmless hit because we can't wrongly do damage anyway
return ..()
@@ -603,7 +617,6 @@
living_target.visible_message("[living_target] [other_msg]", span_userdanger("Whoa! [self_msg]"))
/obj/projectile/kiss/on_hit(atom/target, blocked, pierce_hit)
- def_zone = BODY_ZONE_HEAD // let's keep it PG, people
. = ..()
if(isliving(target))
var/mob/living/living_target = target
@@ -625,6 +638,18 @@
var/obj/item/organ/internal/heart/dont_go_breakin_my_heart = heartbreakee.get_organ_slot(ORGAN_SLOT_HEART)
dont_go_breakin_my_heart.apply_organ_damage(999)
+// Based on energy gun characteristics
+/obj/projectile/kiss/syndie
+ name = "syndie kiss"
+ color = COLOR_SYNDIE_RED
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser
+ damage_type = BURN
+ armor_flag = LASER
+ armour_penetration = 0
+ damage = 25
+ wound_bonus = -20
+ bare_wound_bonus = 40
+ silent_blown = TRUE
/obj/projectile/kiss/french
name = "french kiss (is that a hint of garlic?)"
diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm
index c5a68260abade4..7edc000920454d 100644
--- a/code/game/objects/items/handcuffs.dm
+++ b/code/game/objects/items/handcuffs.dm
@@ -48,6 +48,8 @@
breakouttime = 1 MINUTES
armor_type = /datum/armor/restraints_handcuffs
custom_price = PAYCHECK_COMMAND * 0.35
+ pickup_sound = 'sound/items/handcuffs_pick_up.ogg'
+ drop_sound = 'sound/items/handcuffs_drop.ogg'
///How long it takes to handcuff someone
var/handcuff_time = 4 SECONDS
@@ -55,6 +57,8 @@
var/handcuff_time_mod = 1
///Sound that plays when starting to put handcuffs on someone
var/cuffsound = 'sound/weapons/handcuffs.ogg'
+ ///Sound that plays when restrain is successful
+ var/cuffsuccesssound = 'sound/items/handcuff_finish.ogg'
///If set, handcuffs will be destroyed on application and leave behind whatever this is set to.
var/trashtype = null
/// How strong the cuffs are. Weak cuffs can be broken with wirecutters or boxcutters.
@@ -120,6 +124,7 @@
return
apply_cuffs(victim, user, dispense = iscyborg(user))
+ playsound(loc, cuffsuccesssound, 30, TRUE, -2)
victim.visible_message(
span_notice("[user] handcuffs [victim]."),
@@ -195,6 +200,8 @@
custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 1.5, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 0.75)
breakouttime = 30 SECONDS
cuffsound = 'sound/weapons/cablecuff.ogg'
+ pickup_sound = null
+ drop_sound = null
restraint_strength = HANDCUFFS_TYPE_WEAK
/obj/item/restraints/handcuffs/cable/Initialize(mapload, new_color)
diff --git a/code/game/objects/items/implants/implant_mindshield.dm b/code/game/objects/items/implants/implant_mindshield.dm
index 67b1f4c6d92ffe..9f7e507f1c3433 100644
--- a/code/game/objects/items/implants/implant_mindshield.dm
+++ b/code/game/objects/items/implants/implant_mindshield.dm
@@ -20,7 +20,7 @@
if(!.)
return FALSE
if(target.mind)
- if((SEND_SIGNAL(target.mind, COMSIG_PRE_MINDSHIELD_IMPLANT, user) & COMPONENT_MINDSHIELD_RESISTED) || target.mind.unconvertable)
+ if((SEND_SIGNAL(target.mind, COMSIG_PRE_MINDSHIELD_IMPLANT, user) & COMPONENT_MINDSHIELD_RESISTED))
if(!silent)
target.visible_message(span_warning("[target] seems to resist the implant!"), span_warning("You feel something interfering with your mental conditioning, but you resist it!"))
removed(target, TRUE)
@@ -30,7 +30,7 @@
if(prob(1) || check_holidays(APRIL_FOOLS))
target.say("I'm out! I quit! Whose kidneys are these?", forced = "They're out! They quit! Whose kidneys do they have?")
- ADD_TRAIT(target, TRAIT_MINDSHIELD, IMPLANT_TRAIT)
+ target.add_traits(list(TRAIT_MINDSHIELD, TRAIT_UNCONVERTABLE), IMPLANT_TRAIT)
target.sec_hud_set_implants()
if(!silent)
to_chat(target, span_notice("You feel a sense of peace and security. You are now protected from brainwashing."))
@@ -42,7 +42,7 @@
return FALSE
if(isliving(target))
var/mob/living/L = target
- REMOVE_TRAIT(L, TRAIT_MINDSHIELD, IMPLANT_TRAIT)
+ target.remove_traits(list(TRAIT_MINDSHIELD, TRAIT_UNCONVERTABLE), IMPLANT_TRAIT)
L.sec_hud_set_implants()
if(target.stat != DEAD && !silent)
to_chat(target, span_boldnotice("Your mind suddenly feels terribly vulnerable. You are no longer safe from brainwashing."))
diff --git a/code/game/objects/items/implants/implantchair.dm b/code/game/objects/items/implants/implantchair.dm
index 5f833e32648750..efbe320d7f0491 100644
--- a/code/game/objects/items/implants/implantchair.dm
+++ b/code/game/objects/items/implants/implantchair.dm
@@ -191,7 +191,7 @@
objective = tgui_input_text(user, "What order do you want to imprint on [C]?", "Brainwashing", max_length = 120)
message_admins("[ADMIN_LOOKUPFLW(user)] set brainwash machine objective to '[objective]'.")
user.log_message("set brainwash machine objective to '[objective]'.", LOG_GAME)
- if(HAS_TRAIT(C, TRAIT_MINDSHIELD))
+ if(HAS_MIND_TRAIT(C, TRAIT_UNCONVERTABLE))
return FALSE
brainwash(C, objective)
message_admins("[ADMIN_LOOKUPFLW(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.")
diff --git a/code/game/objects/items/inducer.dm b/code/game/objects/items/inducer.dm
index d74bb7aa8d10e5..2404974d699708 100644
--- a/code/game/objects/items/inducer.dm
+++ b/code/game/objects/items/inducer.dm
@@ -81,9 +81,9 @@
return
/obj/item/inducer/attackby(obj/item/used_item, mob/user)
+ var/obj/item/stock_parts/power_store/our_cell = get_cell()
if(istype(used_item, /obj/item/stock_parts/power_store))
if(opened)
- var/obj/item/stock_parts/power_store/our_cell = get_cell()
if(isnull(our_cell))
if(!user.transferItemToLoc(used_item, src))
return
@@ -95,6 +95,15 @@
to_chat(user, span_warning("[src] already has \a [our_cell] installed!"))
return
+ if (istype(used_item, /obj/item/stack/sheet/mineral/plasma) && !isnull(our_cell))
+ if(our_cell.charge == our_cell.maxcharge)
+ balloon_alert(user, "already fully charged!")
+ return
+ used_item.use(1)
+ our_cell.give(1.5 * STANDARD_CELL_CHARGE)
+ balloon_alert(user, "cell recharged")
+ return
+
if(cantbeused(user))
return
@@ -187,7 +196,7 @@
opened = TRUE
/obj/item/inducer/orderable
- cell_type = /obj/item/stock_parts/power_store/cell/inducer_supply
+ cell_type = /obj/item/stock_parts/power_store/battery/upgraded
opened = FALSE
/obj/item/inducer/sci
diff --git a/code/game/objects/items/kirby_plants/kirbyplants.dm b/code/game/objects/items/kirby_plants/kirbyplants.dm
index 75363eedaf4ada..3becb1ecb61b35 100644
--- a/code/game/objects/items/kirby_plants/kirbyplants.dm
+++ b/code/game/objects/items/kirby_plants/kirbyplants.dm
@@ -1,4 +1,3 @@
-
/obj/item/kirbyplants
name = "potted plant"
//icon = 'icons/obj/fluff/flora/plants.dmi' // ORIGINAL
diff --git a/code/game/objects/items/knives.dm b/code/game/objects/items/knives.dm
index 1a16b08eb866b5..848058a6a279ea 100644
--- a/code/game/objects/items/knives.dm
+++ b/code/game/objects/items/knives.dm
@@ -166,6 +166,19 @@
force = 15
throwforce = 15
+/obj/item/knife/combat/root
+ name = "cahn'root dagger"
+ icon = 'icons/obj/weapons/stabby.dmi'
+ icon_state = "rootdagger"
+ worn_icon_state = "root_dagger"
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ inhand_icon_state = "rootshiv"
+ embed_type = /datum/embed_data/combat_knife/weak
+ desc = "A root dagger, deceptively sharp. Perfect to hide and stab someone with, or make a couple and throw them at enemies."
+ force = 15
+ throwforce = 15
+
/obj/item/knife/combat/bone
name = "bone dagger"
inhand_icon_state = "bone_dagger"
@@ -177,7 +190,6 @@
desc = "A sharpened bone. The bare minimum in survival."
embed_type = /datum/embed_data/combat_knife/weak
obj_flags = parent_type::obj_flags & ~CONDUCTS_ELECTRICITY
- slot_flags = NONE
force = 15
throwforce = 15
custom_materials = null
@@ -189,7 +201,9 @@
name = "cyborg knife"
icon = 'icons/obj/items_cyborg.dmi'
icon_state = "knife_cyborg"
+ worn_icon_state = "knife_cyborg" //error sprite - this shouldn't have been dropped
desc = "A cyborg-mounted plasteel knife. Extremely sharp and durable."
+ slot_flags = NONE //you can't put this in your mouth
/obj/item/knife/shiv
name = "glass shiv"
@@ -279,3 +293,18 @@
/obj/item/knife/shiv/carrot/suicide_act(mob/living/carbon/user)
user.visible_message(span_suicide("[user] forcefully drives \the [src] into [user.p_their()] eye! It looks like [user.p_theyre()] trying to commit suicide!"))
return BRUTELOSS
+
+/obj/item/knife/shiv/parsnip
+ name = "parsnip shiv"
+ icon_state = "parsnipshiv"
+ inhand_icon_state = "parsnipshiv"
+ desc = "Truly putting 'snip' in the 'parsnip', and it's not sub-par either!"
+ custom_materials = null
+
+/obj/item/knife/shiv/root
+ name = "cahn'root shiv"
+ icon_state = "rootshiv"
+ inhand_icon_state = "rootshiv"
+ desc = "A root sharpened into a shiv. A root source of someone's stab wounds soon, most likely."
+ custom_materials = null
+
diff --git a/code/game/objects/items/maintenance_loot.dm b/code/game/objects/items/maintenance_loot.dm
index 51a272509969c1..74d908732a562b 100644
--- a/code/game/objects/items/maintenance_loot.dm
+++ b/code/game/objects/items/maintenance_loot.dm
@@ -20,6 +20,9 @@
wound_bonus = 20
demolition_mod = 1.25
grind_results = list(/datum/reagent/lead = 20)
+ pickup_sound = 'sound/items/lead_pipe_pickup.ogg'
+ drop_sound = 'sound/items/lead_pipe_drop.ogg'
+ hitsound = 'sound/items/lead_pipe_hit.ogg'
//A good battery early in the shift. Source of lead & sulfuric acid reagents.
//Add lead material to this once implemented.
diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/melee/baton.dm
index 27909b5317e768..6bef1b35f3b9fc 100644
--- a/code/game/objects/items/melee/baton.dm
+++ b/code/game/objects/items/melee/baton.dm
@@ -318,6 +318,8 @@
bare_wound_bonus = 5
clumsy_knockdown_time = 15 SECONDS
active = FALSE
+ pickup_sound = 'sound/items/stun_baton_pick_up.ogg'
+ drop_sound = 'sound/items/stun_baton_drop.ogg'
/// The sound effecte played when our baton is extended.
var/on_sound = 'sound/weapons/batonextend.ogg'
@@ -436,6 +438,8 @@
light_on = FALSE
light_color = LIGHT_COLOR_ORANGE
light_power = 0.5
+ pickup_sound = 'sound/items/stun_baton_pick_up.ogg'
+ drop_sound = 'sound/items/stun_baton_drop.ogg'
var/throw_stun_chance = 35
@@ -504,7 +508,6 @@
/obj/item/melee/baton/security/Exited(atom/movable/mov_content)
. = ..()
if(mov_content == cell)
- cell.update_appearance()
cell = null
active = FALSE
update_appearance()
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index 0f38cf2d5dede6..9e7e9cec7ee382 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -54,7 +54,7 @@
/obj/item/melee/sabre
name = "officer's sabre" //SKYRAT EDIT - Buffed in modular_skyrat/modules/modular_weapons/code/melee.dm
- desc = "An elegant weapon, its monomolecular edge is capable of cutting through flesh and bone with ease."
+ desc = "An elegant weapon, its monomolecular edge is capable of cutting through flesh and bone with ease."
icon = 'icons/obj/weapons/sword.dmi'
icon_state = "sabre"
inhand_icon_state = "sabre"
@@ -164,6 +164,47 @@
user.death(FALSE)
REMOVE_TRAIT(src, TRAIT_NODROP, SABRE_SUICIDE_TRAIT)
+/obj/item/melee/parsnip_sabre
+ name = "parsnip sabre"
+ desc = "A weird, yet elegant weapon. Suprisingly sharp for something made from a parsnip."
+
+ icon = 'icons/obj/weapons/sword.dmi'
+ icon_state = "parsnip_sabre"
+ inhand_icon_state = "parsnip_sabre"
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ force = 15
+ throwforce = 10
+ demolition_mod = 0.3
+ w_class = WEIGHT_CLASS_BULKY
+ block_chance = 40
+ armour_penetration = 40
+ sharpness = SHARP_EDGED
+ attack_verb_continuous = list("slashes", "cuts")
+ attack_verb_simple = list("slash", "cut")
+ block_sound = 'sound/weapons/parry.ogg'
+ hitsound = 'sound/weapons/rapierhit.ogg'
+ custom_materials = null
+ wound_bonus = 5
+ bare_wound_bonus = 15
+
+/obj/item/melee/sabre/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/jousting)
+
+/obj/item/melee/parsnip_sabre/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
+ if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK)
+ final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword
+ return ..()
+
+/obj/item/melee/parsnip_sabre/on_exit_storage(datum/storage/container)
+ . = ..()
+ playsound(container.parent, 'sound/items/unsheath.ogg', 25, TRUE)
+
+/obj/item/melee/parsnip_sabre/on_enter_storage(datum/storage/container)
+ . = ..()
+ playsound(container.parent, 'sound/items/sheath.ogg', 25, TRUE)
+
/obj/item/melee/beesword
name = "The Stinger"
desc = "Taken from a giant bee and folded over one thousand times in pure honey. Can sting through anything."
diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm
index 35e4c7ff72e9f2..95f46da2e10ced 100644
--- a/code/game/objects/items/plushes.dm
+++ b/code/game/objects/items/plushes.dm
@@ -44,7 +44,7 @@
/obj/item/toy/plush/Initialize(mapload)
. = ..()
AddComponent(/datum/component/squeak, squeak_override)
- AddElement(/datum/element/bed_tuckable, mapload, 6, -5, 90)
+ AddElement(/datum/element/bed_tuckable, mapload, 6, 7, 90)
AddElement(/datum/element/toy_talk)
//have we decided if Pinocchio goes in the blue or pink aisle yet?
@@ -793,3 +793,10 @@
inhand_icon_state = "blahaj"
attack_verb_continuous = list("gnaws", "gnashes", "chews")
attack_verb_simple = list("gnaw", "gnash", "chew")
+
+/obj/item/toy/plush/donkpocket
+ name = "donk pocket plushie"
+ desc = "The stuffed companion of choice for the seasoned traitor."
+ icon_state = "donkpocket"
+ attack_verb_continuous = list("donks")
+ attack_verb_simple = list("donk")
diff --git a/code/game/objects/items/rcd/RCD.dm b/code/game/objects/items/rcd/RCD.dm
index cf254e447818d0..669d7e3bab6a61 100644
--- a/code/game/objects/items/rcd/RCD.dm
+++ b/code/game/objects/items/rcd/RCD.dm
@@ -16,6 +16,9 @@
item_flags = NO_MAT_REDEMPTION | NOBLUDGEON
has_ammobar = TRUE
actions_types = list(/datum/action/item_action/rcd_scan)
+ drop_sound = 'sound/items/handling/rcd_drop.ogg'
+ pickup_sound = 'sound/items/handling/rcd_pickup.ogg'
+ sound_vary = TRUE
/// main category of currently selected design[Structures, Airlocks, Airlock Access]
var/root_category
@@ -77,6 +80,10 @@
GLOB.rcd_list -= src
. = ..()
+/obj/item/construction/rcd/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ playsound(src, SFX_TOOL_SWITCH, 20, TRUE)
+
/obj/item/construction/rcd/ui_action_click(mob/user, actiontype)
if (!COOLDOWN_FINISHED(src, destructive_scan_cooldown))
to_chat(user, span_warning("[src] lets out a low buzz."))
@@ -103,7 +110,7 @@
T.rcd_act(user, src, list("[RCD_DESIGN_MODE]" = RCD_TURF, "[RCD_DESIGN_PATH]" = /turf/open/floor/plating/rcd))
useResource(16, user)
activate()
- playsound(loc, 'sound/machines/click.ogg', 50, 1)
+ playsound(get_turf(user), SFX_TOOL_SWITCH, 20, TRUE)
user.gib(DROP_ALL_REMAINS)
return MANUAL_SUICIDE
@@ -144,7 +151,7 @@
//check if we can build our window on the grill
if(target_turf.is_blocked_turf(exclude_mobs = !is_full_tile, source_atom = null, ignore_atoms = structures_to_ignore, type_list = TRUE))
- playsound(loc, 'sound/machines/click.ogg', 50, TRUE)
+ playsound(get_turf(user), SFX_TOOL_SWITCH, 20, TRUE)
balloon_alert(user, "something is blocking the turf")
return FALSE
@@ -155,7 +162,7 @@
else if(rcd_mode == RCD_TURF && rcd_structure == /turf/open/floor/plating/rcd && (!istype(target_turf, /turf/open/floor) || istype(target, /obj/structure/girder)))
//if a player builds a wallgirder on top of himself manually with iron sheets he can't finish the wall if he is still on the girder. Exclude the girder itself when checking for other dense objects on the turf
if(istype(target, /obj/structure/girder) && target_turf.is_blocked_turf(exclude_mobs = FALSE, source_atom = null, ignore_atoms = list(target)))
- playsound(loc, 'sound/machines/click.ogg', 50, TRUE)
+ playsound(get_turf(user), SFX_TOOL_SWITCH, 20, TRUE)
balloon_alert(user, "something is on the girder!")
return FALSE
@@ -190,7 +197,7 @@
//check if the structure can fit on this turf
if(target_turf.is_blocked_turf(exclude_mobs = ignore_mobs, source_atom = null, ignore_atoms = ignored_types, type_list = TRUE))
- playsound(loc, 'sound/machines/click.ogg', 50, TRUE)
+ playsound(get_turf(user), SFX_TOOL_SWITCH, 20, TRUE)
balloon_alert(user, "something is on the tile!")
return FALSE
diff --git a/code/game/objects/items/rcd/RLD.dm b/code/game/objects/items/rcd/RLD.dm
index 2a99f535f42b59..6156cd0ee73e66 100644
--- a/code/game/objects/items/rcd/RLD.dm
+++ b/code/game/objects/items/rcd/RLD.dm
@@ -166,7 +166,7 @@
return ITEM_INTERACT_BLOCKING
activate()
var/obj/machinery/light/L = new /obj/machinery/light(get_turf(winner))
- L.setDir(get_dir(winner, interacting_with))
+ L.setDir(get_dir(interacting_with, winner))
L.color = color_choice
L.set_light_color(color_choice)
return ITEM_INTERACT_SUCCESS
diff --git a/code/game/objects/items/rcd/RPD.dm b/code/game/objects/items/rcd/RPD.dm
index 41a962ed7e7deb..642bbc70623fbd 100644
--- a/code/game/objects/items/rcd/RPD.dm
+++ b/code/game/objects/items/rcd/RPD.dm
@@ -142,6 +142,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
/datum/pipe_info/meter
icon_state = "meter"
dirtype = PIPE_ONEDIR
+ all_layers = TRUE
/datum/pipe_info/meter/New(label)
name = label
@@ -182,6 +183,9 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
custom_materials = list(/datum/material/iron=SHEET_MATERIAL_AMOUNT*37.5, /datum/material/glass=SHEET_MATERIAL_AMOUNT*18.75)
armor_type = /datum/armor/item_pipe_dispenser
resistance_flags = FIRE_PROOF
+ drop_sound = 'sound/items/handling/rpd_drop.ogg'
+ pickup_sound = 'sound/items/handling/rpd_pickup.ogg'
+ sound_vary = TRUE
///Sparks system used when changing device in the UI
var/datum/effect_system/spark_spread/spark_system
///Direction of the device we are going to spawn, set up in the UI
@@ -293,7 +297,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
/obj/item/pipe_dispenser/suicide_act(mob/living/user)
user.visible_message(span_suicide("[user] points the end of the RPD down [user.p_their()] throat and presses a button! It looks like [user.p_theyre()] trying to commit suicide..."))
- playsound(get_turf(user), 'sound/machines/click.ogg', 50, TRUE)
+ playsound(get_turf(user), SFX_TOOL_SWITCH, 20, TRUE)
playsound(get_turf(user), RPD_USE_SOUND, 50, TRUE)
return BRUTELOSS
@@ -359,6 +363,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
/obj/item/pipe_dispenser/ui_act(action, params)
. = ..()
+ playsound(src, SFX_TOOL_SWITCH, 20, TRUE)
if(.)
return
@@ -456,7 +461,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
. = TRUE
if((mode & DESTROY_MODE) && istype(attack_target, /obj/item/pipe) || istype(attack_target, /obj/structure/disposalconstruct) || istype(attack_target, /obj/structure/c_transit_tube) || istype(attack_target, /obj/structure/c_transit_tube_pod) || istype(attack_target, /obj/item/pipe_meter) || istype(attack_target, /obj/structure/disposalpipe/broken))
- playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE)
+ playsound(get_turf(src), SFX_TOOL_SWITCH, 20, TRUE)
playsound(get_turf(src), RPD_USE_SOUND, 50, TRUE)
qdel(attack_target)
return
@@ -478,7 +483,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
balloon_alert(user, "already configured for its directions!")
return
- playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE)
+ playsound(get_turf(src), SFX_TOOL_SWITCH, 20, TRUE)
// Something else could have changed the target's state while we were waiting in do_after
// Most of the edge cases don't matter, but atmos components being able to have live connections not described by initializable directions sounds like a headache at best and an exploit at worst
@@ -542,7 +547,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
if(isclosedturf(attack_target))
balloon_alert(user, "target is blocked!")
return
- playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE)
+ playsound(get_turf(src), SFX_TOOL_SWITCH, 20, TRUE)
if(do_after(user, disposal_build_speed, target = attack_target))
var/obj/structure/disposalconstruct/new_disposals_segment = new (attack_target, queued_pipe_type, queued_pipe_dir, queued_pipe_flipped)
@@ -572,7 +577,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
balloon_alert(user, "something in the way!")
return
- playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE)
+ playsound(get_turf(src), SFX_TOOL_SWITCH, 20, TRUE)
if(do_after(user, transit_build_speed, target = attack_target))
playsound(get_turf(src), RPD_USE_SOUND, 50, TRUE)
if(queued_pipe_type == /obj/structure/c_transit_tube_pod)
@@ -619,7 +624,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
return FALSE
if(!can_make_pipe)
return FALSE
- playsound(get_turf(src), 'sound/machines/click.ogg', 50, vary = TRUE)
+ playsound(get_turf(src), SFX_TOOL_SWITCH, 20, vary = TRUE)
if(!continued_build && !do_after(user, atmos_build_speed, target = atom_to_target))
return FALSE
if(!recipe.all_layers && (layer_to_build == 1 || layer_to_build == 5))
diff --git a/code/game/objects/items/rcd/RPLD.dm b/code/game/objects/items/rcd/RPLD.dm
index 62608aeb7dfdd5..d45ae8cf1a4f90 100644
--- a/code/game/objects/items/rcd/RPLD.dm
+++ b/code/game/objects/items/rcd/RPLD.dm
@@ -159,6 +159,10 @@
return data
+/obj/item/construction/plumbing/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ playsound(src, SFX_TOOL_SWITCH, 20, TRUE)
+
/obj/item/construction/plumbing/handle_ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
switch(action)
if("color")
@@ -185,8 +189,6 @@
blueprint = design
blueprint_changed = TRUE
- playsound(src, 'sound/effects/pop.ogg', 50, vary = FALSE)
-
return TRUE
diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm
index 644823835a993d..63e1c19c64abe8 100644
--- a/code/game/objects/items/religion.dm
+++ b/code/game/objects/items/religion.dm
@@ -386,6 +386,7 @@
icon_state = "crusader"
w_class = WEIGHT_CLASS_NORMAL
armor_type = /datum/armor/shoes_plate
+ body_parts_covered = FEET|LEGS
clothing_traits = list(TRAIT_NO_SLIP_WATER)
cold_protection = FEET
min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT
diff --git a/code/game/objects/items/robot/items/hypo.dm b/code/game/objects/items/robot/items/hypo.dm
index e3bdc8978152bd..09d9c7a9afccd7 100644
--- a/code/game/objects/items/robot/items/hypo.dm
+++ b/code/game/objects/items/robot/items/hypo.dm
@@ -91,6 +91,9 @@
/datum/reagent/consumable/ethanol/fernet,\
)
+#define REAGENT_CONTAINER_INTERNAL "internal_beaker"
+#define REAGENT_CONTAINER_BEVAPPARATUS "beverage_apparatus"
+
///Borg Hypospray
/obj/item/reagent_containers/borghypo
name = "cyborg hypospray"
@@ -329,6 +332,7 @@ SKYRAT EDIT REMOVAL END */
dispensed_temperature = WATER_MATTERSTATE_CHANGE_TEMP //Water stays wet, ice stays ice
default_reagent_types = BASE_SERVICE_REAGENTS
expanded_reagent_types = EXPANDED_SERVICE_REAGENTS
+ var/reagent_search_container = REAGENT_CONTAINER_BEVAPPARATUS
/obj/item/reagent_containers/borghypo/borgshaker/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
@@ -336,6 +340,27 @@ SKYRAT EDIT REMOVAL END */
ui = new(user, src, "BorgShaker", name)
ui.open()
+/obj/item/reagent_containers/borghypo/borgshaker/ui_act(action, params)
+ . = ..()
+ if(.)
+ return
+ var/mob/living/silicon/robot/user = usr
+ switch(action)
+ if("reaction_lookup")
+ if(!iscyborg(usr))
+ return
+ if (reagent_search_container == REAGENT_CONTAINER_BEVAPPARATUS)
+ var/obj/item/borg/apparatus/beaker/service/beverage_apparatus = (locate() in user.model.modules) || (locate() in user.held_items)
+ if (!isnull(beverage_apparatus) && !isnull(beverage_apparatus.stored))
+ beverage_apparatus.stored.reagents.ui_interact(user)
+ else if (reagent_search_container == REAGENT_CONTAINER_INTERNAL)
+ var/obj/item/reagent_containers/cup/beaker/large/internal_beaker = (locate() in user.model.modules) || (locate() in user.held_items)
+ if (!isnull(internal_beaker))
+ internal_beaker.reagents.ui_interact(user)
+ if ("set_preferred_container")
+ reagent_search_container = params["value"]
+ return TRUE
+
/obj/item/reagent_containers/borghypo/borgshaker/ui_data(mob/user)
var/list/drink_reagents = list()
var/list/alcohol_reagents = list()
@@ -358,6 +383,17 @@ SKYRAT EDIT REMOVAL END */
data["sodas"] = drink_reagents
data["alcohols"] = alcohol_reagents
data["selectedReagent"] = selected_reagent?.name
+ data["reagentSearchContainer"] = reagent_search_container
+
+ if(iscyborg(user))
+ var/mob/living/silicon/robot/cyborg = user
+ var/obj/item/borg/apparatus/beaker/service/beverage_apparatus = (locate() in cyborg.model.modules) || (locate() in cyborg.held_items)
+
+ if (isnull(beverage_apparatus))
+ to_chat(user, span_warning("This unit has no beverage apparatus. This shouldn't be possible. Delete yourself, NOW!"))
+ data["apparatusHasItem"] = FALSE
+ else
+ data["apparatusHasItem"] = !isnull(beverage_apparatus.stored)
return data
/obj/item/reagent_containers/borghypo/borgshaker/attack(mob/M, mob/user)
@@ -456,6 +492,8 @@ SKYRAT EDIT REMOVAL END */
dispensed_temperature = WATER_MATTERSTATE_CHANGE_TEMP
default_reagent_types = HACKED_SERVICE_REAGENTS
+#undef REAGENT_CONTAINER_INTERNAL
+#undef REAGENT_CONTAINER_BEVAPPARATUS
#undef BASE_MEDICAL_REAGENTS
#undef EXPANDED_MEDICAL_REAGENTS
#undef HACKED_MEDICAL_REAGENTS
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index fc684fb7a20f72..2bcd23c8379efb 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -208,6 +208,16 @@
items_to_add = list(/obj/item/cautery/prt)
+/obj/item/borg/upgrade/plunger
+ name = "janitor cyborg plunging tool"
+ desc = "An integrated cyborg retractable plunger. It's meant for plunging things, duh."
+ icon_state = "module_janitor"
+ require_model = TRUE
+ model_type = list(/obj/item/robot_model/janitor)
+ model_flags = BORG_MODEL_JANITOR
+
+ items_to_add = list(/obj/item/plunger/cyborg)
+
/obj/item/borg/upgrade/syndicate
name = "illegal equipment module"
desc = "Unlocks the hidden, deadlier functions of a cyborg."
@@ -420,7 +430,8 @@
/obj/item/borg/upgrade/surgery_omnitool
name = "cyborg surgical omni-tool upgrade"
desc = "An upgrade to the Medical model, upgrading the built-in \
- surgical omnitool, to be on par with advanced surgical tools"
+ surgical omnitool, to be on par with advanced surgical tools, allowing for faster surgery. \
+ It also upgrades their scanner."
icon_state = "module_medical"
require_model = TRUE
model_type = list(/obj/item/robot_model/medical, /obj/item/robot_model/syndicate_medical)
diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm
index 1553f0e9c8f29f..c980fe0dbb3596 100644
--- a/code/game/objects/items/shields.dm
+++ b/code/game/objects/items/shields.dm
@@ -99,6 +99,15 @@
max_integrity = 55
w_class = WEIGHT_CLASS_NORMAL
+/obj/item/shield/buckler/moonflower
+ name = "moonflower buckler"
+ desc = "A buckler made from a steel-cap reinforced moonflower."
+ icon_state = "moonflower_buckler"
+ inhand_icon_state = "moonflower_buckler"
+ block_chance = 40
+ max_integrity = 40
+ w_class = WEIGHT_CLASS_NORMAL
+
/obj/item/shield/kite
name = "kite shield"
desc = "Protect your internal organs with this almond shaped shield."
@@ -140,6 +149,8 @@
shield_break_sound = 'sound/effects/glassbr3.ogg'
shield_break_leftover = /obj/item/shard
armor_type = /datum/armor/item_shield/riot
+ pickup_sound = 'sound/items/plastic_shield_pick_up.ogg'
+ drop_sound = 'sound/items/plastic_shield_drop.ogg'
/obj/item/shield/riot/Initialize(mapload)
. = ..()
diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm
index 96fbde554b79e2..53e307e31d6e05 100644
--- a/code/game/objects/items/spear.dm
+++ b/code/game/objects/items/spear.dm
@@ -221,7 +221,7 @@
icon_state = "military_spear0"
base_icon_state = "military_spear0"
icon_prefix = "military_spear"
- name = "military Javelin"
+ name = "military javelin"
desc = "A stick with a seemingly blunt spearhead on its end. Looks like it might break bones easily."
attack_verb_continuous = list("attacks", "pokes", "jabs")
attack_verb_simple = list("attack", "poke", "jab")
diff --git a/code/game/objects/items/stacks/bscrystal.dm b/code/game/objects/items/stacks/bscrystal.dm
index 410724862f3b50..29795410389803 100644
--- a/code/game/objects/items/stacks/bscrystal.dm
+++ b/code/game/objects/items/stacks/bscrystal.dm
@@ -21,6 +21,8 @@
points = 0
refined_type = null
merge_type = /obj/item/stack/ore/bluespace_crystal/refined
+ drop_sound = null //till I make a better one
+ pickup_sound = null
/obj/item/stack/ore/bluespace_crystal/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
. = ..()
@@ -60,6 +62,8 @@
refined_type = null
grind_results = list(/datum/reagent/bluespace = 10, /datum/reagent/silicon = 20)
merge_type = /obj/item/stack/ore/bluespace_crystal/artificial
+ drop_sound = null //till I make a better one
+ pickup_sound = null
//Polycrystals, aka stacks
/obj/item/stack/sheet/bluespace_crystal
@@ -79,6 +83,7 @@
material_type = /datum/material/bluespace
var/crystal_type = /obj/item/stack/ore/bluespace_crystal/refined
+
/obj/item/stack/sheet/bluespace_crystal/attack_self(mob/user)// to prevent the construction menu from ever happening
to_chat(user, span_warning("You cannot crush the polycrystal in-hand, try breaking one off."))
diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm
index 6314c16c8449c6..69dbe87cd5cc9c 100644
--- a/code/game/objects/items/stacks/rods.dm
+++ b/code/game/objects/items/stacks/rods.dm
@@ -41,6 +41,7 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
merge_type = /obj/item/stack/rods
pickup_sound = 'sound/items/iron_rod_pick_up.ogg'
drop_sound = 'sound/items/metal_drop.ogg'
+ sound_vary = TRUE
/datum/embed_data/rods
embed_chance = 50
diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm
index f02a2af11f8355..9dff36dca2dde2 100644
--- a/code/game/objects/items/stacks/sheets/leather.dm
+++ b/code/game/objects/items/stacks/sheets/leather.dm
@@ -5,9 +5,8 @@
inhand_icon_state = null
novariants = TRUE
merge_type = /obj/item/stack/sheet/animalhide
-
- pickup_sound = null
- drop_sound = null
+ pickup_sound = 'sound/items/skin_pick_up.ogg'
+ drop_sound = 'sound/items/skin_drop.ogg'
/obj/item/stack/sheet/animalhide/human
name = "human skin"
@@ -194,6 +193,8 @@ GLOBAL_LIST_INIT(carp_recipes, list ( \
icon_state = "sheet-leather"
inhand_icon_state = null
merge_type = /obj/item/stack/sheet/leather
+ pickup_sound = 'sound/items/skin_pick_up.ogg'
+ drop_sound = 'sound/items/skin_drop.ogg'
GLOBAL_LIST_INIT(leather_recipes, list ( \
new/datum/stack_recipe("wallet", /obj/item/storage/wallet, 1, crafting_flags = NONE, category = CAT_CONTAINERS), \
@@ -244,6 +245,8 @@ GLOBAL_LIST_INIT(leather_recipes, list ( \
icon_state = "sinew"
novariants = TRUE
merge_type = /obj/item/stack/sheet/sinew
+ drop_sound = 'sound/effects/meatslap.ogg'
+ pickup_sound = 'sound/effects/meatslap.ogg'
/obj/item/stack/sheet/sinew/Initialize(mapload, new_amount, merge, list/mat_override, mat_amt)
. = ..()
@@ -345,6 +348,8 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
icon_state = "sheet-hairlesshide"
inhand_icon_state = null
merge_type = /obj/item/stack/sheet/hairlesshide
+ pickup_sound = 'sound/items/skin_pick_up.ogg'
+ drop_sound = 'sound/items/skin_drop.ogg'
/obj/item/stack/sheet/hairlesshide/examine(mob/user)
. = ..()
@@ -358,6 +363,8 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
icon_state = "sheet-wetleather"
inhand_icon_state = null
merge_type = /obj/item/stack/sheet/wethide
+ pickup_sound = 'sound/items/skin_pick_up.ogg'
+ drop_sound = 'sound/items/skin_drop.ogg'
/// Reduced when exposed to high temperatures
var/wetness = 30
/// Kelvin to start drying
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 5d992853da8077..873ddb9acf11cd 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -577,6 +577,8 @@ GLOBAL_LIST_INIT(durathread_recipes, list ( \
grind_results = list(/datum/reagent/cellulose = 20)
var/loom_result = /obj/item/stack/sheet/cloth
var/loom_time = 1 SECONDS
+ drop_sound = 'sound/items/handling/cloth_drop.ogg'
+ pickup_sound = 'sound/items/handling/cloth_pickup.ogg'
/obj/item/stack/sheet/cotton/Initialize(mapload)
. = ..()
@@ -682,6 +684,8 @@ GLOBAL_LIST_INIT(cardboard_recipes, list ( \
merge_type = /obj/item/stack/sheet/cardboard
grind_results = list(/datum/reagent/cellulose = 10)
material_type = /datum/material/cardboard
+ pickup_sound = 'sound/items/cardboard_pick_up.ogg'
+ drop_sound = 'sound/items/cardboard_drop.ogg'
/obj/item/stack/sheet/cardboard/Initialize(mapload, new_amount, merge, list/mat_override, mat_amt)
. = ..()
@@ -941,6 +945,8 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
merge_type = /obj/item/stack/sheet/sandblock
material_type = /datum/material/sand
material_modifier = 1
+ drop_sound = SFX_STONE_DROP
+ pickup_sound = SFX_STONE_PICKUP
/obj/item/stack/sheet/sandblock/fifty
amount = 50
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index de4d7506be3222..adc7d30df1da00 100644
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -79,7 +79,7 @@
))
/obj/item/storage/belt/utility/chief
- name = "\improper Chief Engineer's toolbelt" //"the Chief Engineer's toolbelt", because "Chief Engineer's toolbelt" is not a proper noun
+ name = "chief engineer's toolbelt"
desc = "Holds tools, looks snazzy."
icon_state = "utility_ce"
inhand_icon_state = "utility_ce"
@@ -398,6 +398,9 @@
/obj/item/restraints/legcuffs/bola,
/obj/item/stock_parts/power_store/cell/microfusion, //SKYRAT EDIT ADDITION
))
+ atom_storage.open_sound = 'sound/items/holster.ogg'
+ atom_storage.open_sound_vary = TRUE
+ atom_storage.rustle_sound = FALSE
/obj/item/storage/belt/security/full/PopulateContents()
new /obj/item/reagent_containers/spray/pepper(src)
@@ -554,7 +557,7 @@
/obj/item/storage/belt/military/snack/Initialize(mapload)
. = ..()
- var/sponsor = pick("Donk Co.", "Waffle Co.", "Roffle Co.", "Gorlax Marauders", "Tiger Cooperative")
+ var/sponsor = pick("Donk Co.", "Waffle Corp.", "Roffle Co.", "Gorlex Marauders", "Tiger Cooperative")
desc = "A set of snack-tical webbing worn by athletes of the [sponsor] VR sports division."
atom_storage.max_slots = 6
atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
@@ -849,7 +852,7 @@
AddElement(/datum/element/update_icon_updates_onmob)
atom_storage.max_slots = 1
- atom_storage.rustle_sound = FALSE
+ atom_storage.do_rustle = FALSE
atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY
atom_storage.set_holdable(/obj/item/melee/sabre)
atom_storage.click_alt_open = FALSE
@@ -883,6 +886,50 @@
new /obj/item/melee/sabre(src)
update_appearance()
+/obj/item/storage/belt/grass_sabre
+ name = "sabre sheath"
+ desc = "An simple grass sheath designed to hold a sabre of... some sort. Actual metal one might be too sharp, though..."
+ icon_state = "grass_sheath"
+ inhand_icon_state = "grass_sheath"
+ worn_icon_state = "grass_sheath"
+ w_class = WEIGHT_CLASS_BULKY
+ interaction_flags_click = parent_type::interaction_flags_click | NEED_DEXTERITY | NEED_HANDS
+
+/obj/item/storage/belt/grass_sabre/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/update_icon_updates_onmob)
+
+ atom_storage.max_slots = 1
+ atom_storage.do_rustle = FALSE
+ atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY
+ atom_storage.set_holdable(/obj/item/melee/parsnip_sabre)
+ atom_storage.click_alt_open = FALSE
+
+/obj/item/storage/belt/grass_sabre/examine(mob/user)
+ . = ..()
+ if(length(contents))
+ . += span_notice("Alt-click it to quickly draw the blade.")
+
+/obj/item/storage/belt/grass_sabre/click_alt(mob/user)
+ if(length(contents))
+ var/obj/item/I = contents[1]
+ user.visible_message(span_notice("[user] takes [I] out of [src]."), span_notice("You take [I] out of [src]."))
+ user.put_in_hands(I)
+ update_appearance()
+ else
+ balloon_alert(user, "it's empty!")
+ return CLICK_ACTION_SUCCESS
+
+/obj/item/storage/belt/grass_sabre/update_icon_state()
+ icon_state = initial(inhand_icon_state)
+ inhand_icon_state = initial(inhand_icon_state)
+ worn_icon_state = initial(worn_icon_state)
+ if(contents.len)
+ icon_state += "-sabre"
+ inhand_icon_state += "-sabre"
+ worn_icon_state += "-sabre"
+ return ..()
+
/obj/item/storage/belt/plant
name = "botanical belt"
desc = "A sturdy leather belt used to hold most hydroponics supplies."
diff --git a/code/game/objects/items/storage/boxes/_boxes.dm b/code/game/objects/items/storage/boxes/_boxes.dm
index 56915d8a5fced9..94015272996894 100644
--- a/code/game/objects/items/storage/boxes/_boxes.dm
+++ b/code/game/objects/items/storage/boxes/_boxes.dm
@@ -19,6 +19,8 @@
. = ..()
atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
update_appearance()
+ atom_storage.open_sound = 'sound/items/cardboard_box_open.ogg'
+ atom_storage.rustle_sound = 'sound/items/cardboard_box_rustle.ogg'
/obj/item/storage/box/suicide_act(mob/living/carbon/user)
var/obj/item/bodypart/head/myhead = user.get_bodypart(BODY_ZONE_HEAD)
diff --git a/code/game/objects/items/storage/boxes/job_boxes.dm b/code/game/objects/items/storage/boxes/job_boxes.dm
index ac09b5fbe20e33..2620cb58dc8eab 100644
--- a/code/game/objects/items/storage/boxes/job_boxes.dm
+++ b/code/game/objects/items/storage/boxes/job_boxes.dm
@@ -43,7 +43,7 @@
if(HAS_TRAIT(SSstation, STATION_TRAIT_RADIOACTIVE_NEBULA))
new /obj/item/storage/pill_bottle/potassiodide(src)
- if(SSmapping.is_planetary() && LAZYLEN(SSmapping.multiz_levels))
+ if(length(SSmapping.levels_by_trait(ZTRAIT_STATION)) > 1)
new /obj/item/climbing_hook/emergency(src)
new /obj/item/oxygen_candle(src) //SKYRAT EDIT ADDITION
diff --git a/code/game/objects/items/storage/boxes/science_boxes.dm b/code/game/objects/items/storage/boxes/science_boxes.dm
index f0654cdf024bc3..48ab6cd5b72432 100644
--- a/code/game/objects/items/storage/boxes/science_boxes.dm
+++ b/code/game/objects/items/storage/boxes/science_boxes.dm
@@ -50,12 +50,12 @@
new cube_type(src)
/obj/item/storage/box/monkeycubes/syndicate
- desc = "Waffle Co. brand monkey cubes. Just add water and a dash of subterfuge!"
+ desc = "Waffle Corp. brand monkey cubes. Just add water and a dash of subterfuge!"
cube_type = /obj/item/food/monkeycube/syndicate
/obj/item/storage/box/gorillacubes
name = "gorilla cube box"
- desc = "Waffle Co. brand gorilla cubes. Do not taunt."
+ desc = "Waffle Corp. brand gorilla cubes. Do not taunt."
icon_state = "monkeycubebox"
illustration = null
diff --git a/code/game/objects/items/storage/boxes/security_boxes.dm b/code/game/objects/items/storage/boxes/security_boxes.dm
index 935ead8f93e952..de18eb76258fee 100644
--- a/code/game/objects/items/storage/boxes/security_boxes.dm
+++ b/code/game/objects/items/storage/boxes/security_boxes.dm
@@ -174,6 +174,12 @@
for(var/i in 1 to 7)
new /obj/item/ammo_casing/shotgun/buckshot(src)
+/obj/item/storage/box/lethalshot/old
+
+/obj/item/storage/box/lethalshot/old/PopulateContents()
+ for(var/i in 1 to 7)
+ new /obj/item/ammo_casing/shotgun/buckshot/old(src)
+
/obj/item/storage/box/slugs
name = "box of shotgun shells (Lethal - Slugs)"
desc = "A box full of lethal shotgun slugs, designed for shotguns."
diff --git a/code/game/objects/items/storage/holsters.dm b/code/game/objects/items/storage/holsters.dm
index afb7b0f750b26a..f8dee3afdc7f41 100644
--- a/code/game/objects/items/storage/holsters.dm
+++ b/code/game/objects/items/storage/holsters.dm
@@ -33,6 +33,8 @@
/obj/item/gun/energy/laser/captain,
/obj/item/gun/energy/e_gun/hos,
))
+ atom_storage.open_sound = 'sound/items/holster.ogg'
+ atom_storage.open_sound_vary = TRUE
/obj/item/storage/belt/holster/energy
name = "energy shoulder holsters"
diff --git a/code/game/objects/items/storage/medkit.dm b/code/game/objects/items/storage/medkit.dm
index c3c97c790fdf3f..368ef9c0b406af 100644
--- a/code/game/objects/items/storage/medkit.dm
+++ b/code/game/objects/items/storage/medkit.dm
@@ -18,6 +18,9 @@
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
throw_speed = 3
throw_range = 7
+ drop_sound = 'sound/items/medkit_drop.ogg'
+ pickup_sound = 'sound/items/medkit_pick_up.ogg'
+ sound_vary = TRUE
var/empty = FALSE
/// Defines damage type of the medkit. General ones stay null. Used for medibot healing bonuses
var/damagetype_healed
@@ -79,6 +82,9 @@
/obj/item/storage/medkit/Initialize(mapload)
. = ..()
atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
+ atom_storage.open_sound = 'sound/items/medkit_open.ogg'
+ atom_storage.open_sound_vary = TRUE
+ atom_storage.rustle_sound = 'sound/items/medkit_rustle.ogg'
/obj/item/storage/medkit/regular
icon_state = "medkit"
diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm
index ab3dc930aa8dda..8a2920b6013053 100644
--- a/code/game/objects/items/storage/toolbox.dm
+++ b/code/game/objects/items/storage/toolbox.dm
@@ -33,7 +33,8 @@
if(prob(1))
latches = "triple_latch"
update_appearance()
-
+ atom_storage.open_sound = 'sound/items/toolbox_open.ogg'
+ atom_storage.rustle_sound = 'sound/items/toolbox_rustle.ogg'
AddElement(/datum/element/falling_hazard, damage = force, wound_bonus = wound_bonus, hardhat_safety = TRUE, crushes = FALSE, impact_sound = hitsound)
/obj/item/storage/toolbox/update_overlays()
@@ -350,6 +351,11 @@
weapon_to_spawn = /obj/item/gun/ballistic/automatic/c20r
extra_to_spawn = /obj/item/ammo_box/magazine/smgm45
+/obj/item/storage/toolbox/guncase/smartgun
+ name = "adielle smartgun case"
+ weapon_to_spawn = /obj/item/gun/ballistic/automatic/smartgun
+ extra_to_spawn = /obj/item/ammo_box/magazine/smartgun
+
/obj/item/storage/toolbox/guncase/clandestine
name = "clandestine gun case"
weapon_to_spawn = /obj/item/gun/ballistic/automatic/pistol/clandestine
@@ -444,12 +450,6 @@
weapon_to_spawn = /obj/effect/spawner/random/sakhno
extra_to_spawn = /obj/effect/spawner/random/sakhno/ammo
-/obj/item/storage/toolbox/guncase/soviet/plastikov
- name = "ancient surplus gun case"
- desc = "A gun case. Has the symbol of the Third Soviet Union stamped on the side."
- weapon_to_spawn = /obj/item/gun/ballistic/automatic/plastikov
- extra_to_spawn = /obj/item/food/rationpack //sorry comrade, cannot get you more ammo, here, have lunch
-
/obj/item/storage/toolbox/guncase/monkeycase
name = "monkey gun case"
desc = "Everything a monkey needs to truly go ape-shit. There's a paw-shaped hand scanner lock on the front of the case."
diff --git a/code/game/objects/items/syndie_spraycan.dm b/code/game/objects/items/syndie_spraycan.dm
index 1b7e0d9c4024a3..fb6192c6e39905 100644
--- a/code/game/objects/items/syndie_spraycan.dm
+++ b/code/game/objects/items/syndie_spraycan.dm
@@ -143,7 +143,7 @@
user.visible_message(span_suicide("[user] shakes up [src] with a rattle and lifts it to [user.p_their()] mouth, spraying paint across [user.p_their()] teeth!"))
user.say("WITNESS ME!!", forced="spraycan suicide")
playsound(src, 'sound/effects/spray.ogg', 5, TRUE, 5)
- suicider.update_lips("spray_face", paint_color)
+ suicider.AddComponent(/datum/component/face_decal, "spray", EXTERNAL_ADJACENT, paint_color)
return OXYLOSS
/obj/effect/decal/cleanable/traitor_rune
diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm
index ee1f314c92addf..d89794f420917e 100644
--- a/code/game/objects/items/tanks/tanks.dm
+++ b/code/game/objects/items/tanks/tanks.dm
@@ -22,6 +22,9 @@
slot_flags = ITEM_SLOT_BACK
worn_icon = 'icons/mob/clothing/back.dmi' //since these can also get thrown into suit storage slots. if something goes on the belt, set this to null.
hitsound = 'sound/weapons/smash.ogg'
+ pickup_sound = 'sound/items/gas_tank_pick_up.ogg'
+ drop_sound = 'sound/items/gas_tank_drop.ogg'
+ sound_vary = TRUE
pressure_resistance = ONE_ATMOSPHERE * 5
force = 5
throwforce = 10
diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm
index c6b0d52cdc1c34..20e3846adefabf 100644
--- a/code/game/objects/items/tools/crowbar.dm
+++ b/code/game/objects/items/tools/crowbar.dm
@@ -191,7 +191,7 @@
desc = "A hydraulic prying tool, simple but powerful."
icon = 'icons/obj/items_cyborg.dmi'
icon_state = "toolkit_engiborg_crowbar"
- worn_icon_state = "crowbar"
+ worn_icon_state = "toolkit_engiborg_crowbar" //error sprite - this shouldn't have been dropped
usesound = 'sound/items/jaws_pry.ogg'
force = 10
toolspeed = 0.5
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index 194d9682901007..a5a7235257b567 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -145,22 +145,31 @@
if(user.combat_mode)
return NONE
+ return try_heal_loop(interacting_with, user)
+
+/obj/item/weldingtool/proc/try_heal_loop(atom/interacting_with, mob/living/user, repeating = FALSE)
var/mob/living/carbon/human/attacked_humanoid = interacting_with
var/obj/item/bodypart/affecting = attacked_humanoid.get_bodypart(check_zone(user.zone_selected))
if(isnull(affecting) || !IS_ROBOTIC_LIMB(affecting))
return NONE
- var/use_delay = 1 SECONDS // SKYRAT EDIT: ORIGINAL 0
+ if (!affecting.brute_dam)
+ balloon_alert(user, "limb not damaged")
+ return ITEM_INTERACT_BLOCKING
+ user.visible_message(span_notice("[user] starts to fix some of the dents on [attacked_humanoid == user ? user.p_their() : "[attacked_humanoid]'s"] [affecting.name]."),
+ span_notice("You start fixing some of the dents on [attacked_humanoid == user ? "your" : "[attacked_humanoid]'s"] [affecting.name]."))
+ var/use_delay = 1 SECONDS // SKYRAT EDIT - original repeating ? 1 SECONDS : 0
if(user == attacked_humanoid)
- user.visible_message(span_notice("[user] starts to fix some of the dents on [attacked_humanoid]'s [affecting.name]."),
- span_notice("You start fixing some of the dents on [attacked_humanoid == user ? "your" : "[attacked_humanoid]'s"] [affecting.name]."))
use_delay = 5 SECONDS
if(!use_tool(attacked_humanoid, user, use_delay, volume=50, amount=1))
return ITEM_INTERACT_BLOCKING
- attacked_humanoid.item_heal(user, brute_heal = 15, burn_heal = 0, heal_message_brute = "dents", heal_message_burn = "burnt wires", required_bodytype = BODYTYPE_ROBOTIC)
+ if (!attacked_humanoid.item_heal(user, brute_heal = 15, burn_heal = 0, heal_message_brute = "dents", heal_message_burn = "burnt wires", required_bodytype = BODYTYPE_ROBOTIC))
+ return ITEM_INTERACT_BLOCKING
+
+ INVOKE_ASYNC(src, PROC_REF(try_heal_loop), interacting_with, user, TRUE)
return ITEM_INTERACT_SUCCESS
/obj/item/weldingtool/afterattack(atom/target, mob/user, click_parameters)
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index fbe11fe933d1b8..821f994a1ed6fd 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -160,6 +160,14 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
throw_range = 5
armour_penetration = 35
+/obj/item/claymore/cutlass/old
+ name = "old cutlass"
+ desc = parent_type::desc + " This one seems a tad old."
+ force = 24
+ throwforce = 17
+ armour_penetration = 20
+ block_chance = 30
+
/obj/item/claymore/carrot
name = "carrot sword"
desc = "A full-sized carrot sword. Definitely not good for the eyes, not anymore."
@@ -505,6 +513,36 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
user.visible_message(span_suicide("[user] is strangling [user.p_them()]self with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!"))
return OXYLOSS
+/obj/item/bambostaff
+ name = "Bamboo Staff"
+ desc = "A long bamboo-made staff with steel-capped ends. It is rumoured that initiates of Spider Clan train with such before getting to learn how to use a katana."
+ force = 10
+ block_chance = 45
+ block_sound = 'sound/weapons/genhit.ogg'
+ slot_flags = ITEM_SLOT_BACK
+ w_class = WEIGHT_CLASS_BULKY
+ hitsound = SFX_SWING_HIT
+ attack_verb_continuous = list("smashes", "slams", "whacks", "thwacks")
+ attack_verb_simple = list("smash", "slam", "whack", "thwack")
+ icon = 'icons/obj/weapons/staff.dmi'
+ icon_state = "bambostaff0"
+ base_icon_state = "bambostaff"
+ inhand_icon_state = "bambostaff0"
+ worn_icon_state = "bambostaff0"
+ lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
+
+/obj/item/bambostaff/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/two_handed, \
+ force_unwielded = 10, \
+ force_wielded = 14, \
+ )
+
+/obj/item/bambostaff/update_icon_state()
+ icon_state = inhand_icon_state = "[base_icon_state][HAS_TRAIT(src, TRAIT_WIELDED)]"
+ return ..()
+
/obj/item/cane
name = "cane"
desc = "A cane used by a true gentleman. Or a clown."
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index a5c07b473e15c1..92ca803177ec59 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -96,7 +96,7 @@
/obj/proc/collision_damage(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction)
var/amt = max(0, ((force - (move_resist * MOVE_FORCE_CRUSH_RATIO)) / (move_resist * MOVE_FORCE_CRUSH_RATIO)) * 10)
- take_damage(amt, BRUTE)
+ take_damage(amt, BRUTE, attack_dir = REVERSE_DIR(direction))
/obj/singularity_act()
SSexplosions.high_mov_atom += src
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index ce1b48985bb675..1b9282be66182b 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -7,12 +7,12 @@
/// Extra examine line to describe controls, such as right-clicking, left-clicking, etc.
var/desc_controls
- /// The context returned when an attack against this object doesnt deal any traditional damage to the object.
+ /// The context returned when an attack against this object doesn't deal any traditional damage to the object.
var/no_damage_feedback = "without leaving a mark"
/// Icon to use as a 32x32 preview in crafting menus and such
var/icon_preview
var/icon_state_preview
- /// The vertical pixel offset applied when the object is anchored on a tile with table
+ /// The vertical pixel_z offset applied when the object is anchored on a tile with table
/// Ignored when set to 0 - to avoid shifting directional wall-mounted objects above tables
var/anchored_tabletop_offset = 0
@@ -24,7 +24,7 @@
/// If this attacks a human with no wound armor on the affected body part, add this to the wound mod. Some attacks may be significantly worse at wounding if there's even a slight layer of armor to absorb some of it vs bare flesh
var/bare_wound_bonus = 0
- /// A multiplier to an objecet's force when used against a stucture, vechicle, machine, or robot.
+ /// A multiplier to an object's force when used against a structure, vehicle, machine, or robot.
var/demolition_mod = 1
/// Custom fire overlay icon, will just use the default overlay if this is null
@@ -32,7 +32,7 @@
/// Particles this obj uses when burning, if any
var/burning_particles
- var/drag_slowdown // Amont of multiplicative slowdown applied if pulled. >1 makes you slower, <1 makes you faster.
+ var/drag_slowdown // Amount of multiplicative slowdown applied if pulled. >1 makes you slower, <1 makes you faster.
/// Map tag for something. Tired of it being used on snowflake items. Moved here for some semblance of a standard.
/// Next pr after the network fix will have me refactor door interactions, so help me god.
@@ -70,7 +70,7 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag)
var/total_force = (attacking_item.force * attacking_item.demolition_mod)
- var/damage = take_damage(total_force, attacking_item.damtype, MELEE, 1)
+ var/damage = take_damage(total_force, attacking_item.damtype, MELEE, 1, get_dir(src, user))
var/damage_verb = "hit"
@@ -278,7 +278,14 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag)
return FALSE
return TRUE
-/// Adjusts the vertical pixel offset when the object is anchored on a tile with table
+/// Adjusts the vertical pixel_z offset when the object is anchored on a tile with table
/obj/proc/check_on_table()
- if(anchored_tabletop_offset != 0 && !istype(src, /obj/structure/table) && locate(/obj/structure/table) in loc)
- pixel_y = anchored ? anchored_tabletop_offset : initial(pixel_y)
+ if(anchored_tabletop_offset == 0)
+ return
+ if(istype(src, /obj/structure/table))
+ return
+
+ if(anchored && locate(/obj/structure/table) in loc)
+ pixel_z = anchored_tabletop_offset
+ else
+ pixel_z = initial(pixel_z)
diff --git a/code/game/objects/structures/beds_chairs/alien_nest.dm b/code/game/objects/structures/beds_chairs/alien_nest.dm
index 77759c9e309b08..681724f4d40e19 100644
--- a/code/game/objects/structures/beds_chairs/alien_nest.dm
+++ b/code/game/objects/structures/beds_chairs/alien_nest.dm
@@ -13,6 +13,7 @@
canSmoothWith = SMOOTH_GROUP_ALIEN_NEST
build_stack_type = null
elevation = 0
+ can_deconstruct = FALSE
var/static/mutable_appearance/nest_overlay = mutable_appearance('icons/mob/nonhuman-player/alien.dmi', "nestoverlay", LYING_MOB_LAYER)
/obj/structure/bed/nest/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
@@ -21,10 +22,6 @@
return ..()
-/obj/structure/bed/nest/wrench_act_secondary(mob/living/user, obj/item/weapon)
- return ITEM_INTERACT_BLOCKING
-
-
/obj/structure/bed/nest/user_unbuckle_mob(mob/living/captive, mob/living/hero)
if(!length(buckled_mobs))
return
diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm
index 4cfd6355eb0b25..0fb193a057a148 100644
--- a/code/game/objects/structures/beds_chairs/bed.dm
+++ b/code/game/objects/structures/beds_chairs/bed.dm
@@ -24,6 +24,8 @@
var/build_stack_amount = 2
/// Mobs standing on it are nudged up by this amount. Also used to align the person back when buckled to it after init.
var/elevation = 8
+ /// If this bed can be deconstructed using a wrench
+ var/can_deconstruct = TRUE
/obj/structure/bed/Initialize(mapload)
. = ..()
@@ -34,7 +36,8 @@
/obj/structure/bed/examine(mob/user)
. = ..()
- . += span_notice("It's held together by a couple of bolts.")
+ if (can_deconstruct)
+ . += span_notice("It's held together by a couple of bolts.")
/obj/structure/bed/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
if(held_item)
@@ -56,6 +59,8 @@
return attack_hand(user, modifiers)
/obj/structure/bed/wrench_act_secondary(mob/living/user, obj/item/weapon)
+ if (!can_deconstruct)
+ return NONE
..()
weapon.play_tool_sound(src)
deconstruct(disassembled = TRUE)
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index a843c3e3e4bffa..02a0e320d1ffb8 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -38,7 +38,7 @@ LINEN BINS
/obj/item/bedsheet/Initialize(mapload)
. = ..()
AddComponent(/datum/component/surgery_initiator)
- AddElement(/datum/element/bed_tuckable, mapload, 0, 0, 0)
+ AddElement(/datum/element/bed_tuckable, mapload, 0, 12, 0)
if(bedsheet_type == BEDSHEET_DOUBLE)
stack_amount *= 2
dying_key = DYE_REGISTRY_DOUBLE_BEDSHEET
diff --git a/code/game/objects/structures/cannons/cannon.dm b/code/game/objects/structures/cannons/cannon.dm
index 3408ade8283d0c..3a10cc17189f81 100644
--- a/code/game/objects/structures/cannons/cannon.dm
+++ b/code/game/objects/structures/cannons/cannon.dm
@@ -140,5 +140,17 @@
new /obj/item/stack/rods(src.loc)
. = ..()
+///A cannon found from the fishing mystery box.
+/obj/structure/cannon/mystery_box
+ icon_state = "mystery_box_cannon" //east facing sprite for the presented item, it'll be changed back to normal on init
+ dir = EAST
+ anchored = FALSE
+
+/obj/structure/cannon/mystery_box/Initialize(mapload)
+ . = ..()
+ icon_state = "falconet_patina"
+ reagents.add_reagent(/datum/reagent/gunpowder, charge_size)
+ loaded_cannonball = new(src)
+
#undef BAD_FUEL_DAMAGE_TAX
#undef BAD_FUEL_EXPLODE_PROBABILTY
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 4484e3c512ef3a..27e69dcba56f1c 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -1193,6 +1193,8 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets)
if(!toggle())
return
if(was_opened)
+ if (!target.Move(get_turf(src), get_dir(target, src)))
+ return
target.forceMove(src)
else
target.Knockdown(SHOVE_KNOCKDOWN_SOLID)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index ad6f95f086c16a..4474f1d2feca4e 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -108,7 +108,6 @@
/obj/structure/closet/secure_closet/security/PopulateContents()
..()
new /obj/item/clothing/suit/armor/vest/alt/sec(src)
- new /obj/item/clothing/head/security_cap(src) //SKYRAT EDIT ADDITION
new /obj/item/clothing/head/helmet/sec(src)
new /obj/item/radio/headset/headset_sec(src)
new /obj/item/radio/headset/headset_sec/alt(src)
diff --git a/code/game/objects/structures/crates_lockers/crates/secure.dm b/code/game/objects/structures/crates_lockers/crates/secure.dm
index 81f7b97a3c1599..1a102fdb512fd2 100644
--- a/code/game/objects/structures/crates_lockers/crates/secure.dm
+++ b/code/game/objects/structures/crates_lockers/crates/secure.dm
@@ -122,6 +122,28 @@
icon_state = "robo_secure"
base_icon_state = "robo_secure"
+/obj/structure/closet/crate/secure/trashcart
+ desc = "A heavy, metal trashcart with wheels. It has an electronic lock on it."
+ name = "secure trash cart"
+ max_integrity = 250
+ damage_deflection = 10
+ icon_state = "securetrashcart"
+ base_icon_state = "securetrashcart"
+ paint_jobs = null
+ req_access = list(ACCESS_JANITOR)
+
+/obj/structure/closet/crate/secure/trashcart/filled
+
+/obj/structure/closet/crate/secure/trashcart/filled/PopulateContents()
+ . = ..()
+ for(var/i in 1 to rand(8,12))
+ new /obj/effect/spawner/random/trash/deluxe_garbage(src)
+ if(prob(35))
+ new /obj/effect/spawner/random/trash/garbage(src)
+ for(var/i in 1 to rand(4,6))
+ if(prob(30))
+ new /obj/item/storage/bag/trash/filled(src)
+
/obj/structure/closet/crate/secure/owned
name = "private crate"
desc = "A crate cover designed to only open for who purchased its contents."
diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm
index 49a230d6bdc482..a464f41827678d 100644
--- a/code/game/objects/structures/flora.dm
+++ b/code/game/objects/structures/flora.dm
@@ -2,7 +2,7 @@
name = "flora"
desc = "Some sort of plant."
resistance_flags = FLAMMABLE
- max_integrity = 150
+ max_integrity = 100
anchored = TRUE
drag_slowdown = 1.3
@@ -113,6 +113,12 @@
if(harvest(user))
after_harvest(user)
+/obj/structure/flora/run_atom_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
+ if(damage_flag == MELEE)
+ if(damage_type == BURN)
+ damage_amount *= 4
+ return ..()
+
/obj/structure/flora/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
var/use_default_sound = TRUE //Because I don't wanna do unnecessary bitflag checks in a single if statement, while also allowing for multiple sounds to be played
if(flora_flags & FLORA_HERBAL)
@@ -278,6 +284,7 @@
name = "tree"
desc = "A large tree."
density = TRUE
+ max_integrity = 150
pixel_x = -16
layer = FLY_LAYER
plane = ABOVE_GAME_PLANE
diff --git a/code/game/objects/structures/icemoon/cave_entrance.dm b/code/game/objects/structures/icemoon/cave_entrance.dm
index 4401b87d23eca1..6efa6718759153 100644
--- a/code/game/objects/structures/icemoon/cave_entrance.dm
+++ b/code/game/objects/structures/icemoon/cave_entrance.dm
@@ -178,7 +178,8 @@ GLOBAL_LIST_INIT(ore_probability, list(
if(16)
new /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/doom(loc)
if(17)
- new /obj/item/reagent_containers/cup/glass/drinkingglass/filled/nuka_cola(loc)
+ new /obj/item/clothing/gloves/fingerless/punch_mitts(loc)
+ new /obj/item/clothing/head/cowboy(loc)
if(18)
new /obj/item/soulstone/anybody(loc)
if(19)
diff --git a/code/game/objects/structures/lavaland/geyser.dm b/code/game/objects/structures/lavaland/geyser.dm
index 045a703250b0a7..4168a100751f1a 100644
--- a/code/game/objects/structures/lavaland/geyser.dm
+++ b/code/game/objects/structures/lavaland/geyser.dm
@@ -185,3 +185,7 @@
layer_mode_sprite = "reinforced_plunger_layer"
custom_premium_price = PAYCHECK_CREW * 8
+
+/obj/item/plunger/cyborg/Initialize(mapload)
+ . = ..()
+ ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT)
diff --git a/code/game/objects/structures/lavaland/ore_vent.dm b/code/game/objects/structures/lavaland/ore_vent.dm
index 024276198ab512..f9214b989b95c7 100644
--- a/code/game/objects/structures/lavaland/ore_vent.dm
+++ b/code/game/objects/structures/lavaland/ore_vent.dm
@@ -39,6 +39,7 @@
MEDIUM_VENT_TYPE = 5,
SMALL_VENT_TYPE = 7,
)
+ var/wave_timer = WAVE_DURATION_SMALL
/// What string do we use to warn the player about the excavation event?
var/excavation_warning = "Are you ready to excavate this ore vent?"
@@ -219,6 +220,9 @@
node.arrive(src)
RegisterSignal(node, COMSIG_QDELETING, PROC_REF(handle_wave_conclusion))
RegisterSignal(node, COMSIG_MOVABLE_MOVED, PROC_REF(handle_wave_conclusion))
+ addtimer(CALLBACK(node, TYPE_PROC_REF(/atom, update_appearance)), wave_timer * 0.25)
+ addtimer(CALLBACK(node, TYPE_PROC_REF(/atom, update_appearance)), wave_timer * 0.5)
+ addtimer(CALLBACK(node, TYPE_PROC_REF(/atom, update_appearance)), wave_timer * 0.75)
particles = new /particles/smoke/ash()
for(var/i in 1 to 5) // Clears the surroundings of the ore vent before starting wave defense.
for(var/turf/closed/mineral/rock in oview(i))
@@ -247,11 +251,6 @@
spawn_distance = 4, \
spawn_distance_exclude = 3, \
)
- var/wave_timer = 60 SECONDS
- if(boulder_size == BOULDER_SIZE_MEDIUM)
- wave_timer = 90 SECONDS
- else if(boulder_size == BOULDER_SIZE_LARGE)
- wave_timer = 150 SECONDS
COOLDOWN_START(src, wave_cooldown, wave_timer)
addtimer(CALLBACK(src, PROC_REF(handle_wave_conclusion)), wave_timer)
icon_state = icon_state_tapped
@@ -290,6 +289,7 @@
icon_state = icon_state_tapped
update_appearance(UPDATE_ICON_STATE)
qdel(GetComponent(/datum/component/gps))
+ UnregisterSignal(node, COMSIG_QDELETING)
else
visible_message(span_danger("\the [src] creaks and groans as the mining attempt fails, and the vent closes back up."))
icon_state = initial(icon_state)
@@ -474,18 +474,22 @@
switch(string_boulder_size)
if(LARGE_VENT_TYPE)
boulder_size = BOULDER_SIZE_LARGE
+ wave_timer = WAVE_DURATION_LARGE
if(mapload)
GLOB.ore_vent_sizes["large"] += 1
if(MEDIUM_VENT_TYPE)
boulder_size = BOULDER_SIZE_MEDIUM
+ wave_timer = WAVE_DURATION_MEDIUM
if(mapload)
GLOB.ore_vent_sizes["medium"] += 1
if(SMALL_VENT_TYPE)
boulder_size = BOULDER_SIZE_SMALL
+ wave_timer = WAVE_DURATION_SMALL
if(mapload)
GLOB.ore_vent_sizes["small"] += 1
else
boulder_size = BOULDER_SIZE_SMALL //Might as well set a default value
+ wave_timer = WAVE_DURATION_SMALL
name = initial(name)
diff --git a/code/game/objects/structures/maintenance.dm b/code/game/objects/structures/maintenance.dm
index 768bd22d2abe22..375d5269918937 100644
--- a/code/game/objects/structures/maintenance.dm
+++ b/code/game/objects/structures/maintenance.dm
@@ -31,7 +31,7 @@ at the cost of risking a vicious bite.**/
/obj/structure/moisture_trap/Initialize(mapload)
. = ..()
- ADD_TRAIT(src, TRAIT_FISH_SAFE_STORAGE, TRAIT_GENERIC)
+ AddElement(/datum/element/fish_safe_storage)
AddElement(/datum/element/swabable, CELL_LINE_TABLE_MOIST, CELL_VIRUS_TABLE_GENERIC, rand(2,4), 20)
if(prob(40))
critter_infested = FALSE
diff --git a/code/game/objects/structures/mystery_box.dm b/code/game/objects/structures/mystery_box.dm
index e165c2e295c93b..9bb51ba09cbefe 100644
--- a/code/game/objects/structures/mystery_box.dm
+++ b/code/game/objects/structures/mystery_box.dm
@@ -19,7 +19,6 @@
#define MBOX_DURATION_STANDBY (2.7 SECONDS)
GLOBAL_LIST_INIT(mystery_box_guns, list(
- /obj/item/gun/energy/lasercannon,
/obj/item/gun/energy/recharge/ebow/large,
/obj/item/gun/energy/e_gun,
/obj/item/gun/energy/e_gun/nuclear,
@@ -45,6 +44,7 @@ GLOBAL_LIST_INIT(mystery_box_guns, list(
/obj/item/gun/ballistic/automatic/m90/unrestricted,
/obj/item/gun/ballistic/automatic/tommygun,
/obj/item/gun/ballistic/automatic/wt550,
+ /obj/item/gun/ballistic/automatic/smartgun,
/obj/item/gun/ballistic/rifle/sniper_rifle,
/obj/item/gun/ballistic/rifle/boltaction,
))
@@ -85,6 +85,30 @@ GLOBAL_LIST_INIT(mystery_magic, list(
/obj/item/runic_vendor_scepter,
))
+GLOBAL_LIST_INIT(mystery_fishing, list(
+ /obj/item/storage/toolbox/fishing/master,
+ /obj/item/storage/box/fish_revival_kit,
+ /obj/item/circuitboard/machine/fishing_portal_generator/emagged,
+ /obj/item/fishing_rod/telescopic/master,
+ /obj/item/bait_can/super_baits,
+ /obj/item/storage/fish_case/tiziran,
+ /obj/item/storage/fish_case/syndicate,
+ /obj/item/claymore/cutlass/old,
+ /obj/item/gun/energy/laser/retro/old,
+ /obj/item/gun/energy/laser/musket,
+ /obj/item/gun/energy/disabler/smoothbore,
+ /obj/item/gun/ballistic/rifle/boltaction/surplus,
+ /obj/item/food/rationpack,
+ /obj/item/food/canned/squid_ink,
+ /obj/item/reagent_containers/cup/glass/bottle/rum/aged,
+ /obj/item/storage/bag/money/dutchmen,
+ /obj/item/language_manual/piratespeak,
+ /obj/item/clothing/head/costume/pirate/armored,
+ /obj/item/clothing/suit/costume/pirate/armored,
+ /obj/structure/cannon/mystery_box,
+ /obj/item/stack/cannonball/trashball/four,
+ /obj/item/stack/cannonball/four,
+))
/obj/structure/mystery_box
name = "mystery box"
@@ -117,6 +141,10 @@ GLOBAL_LIST_INIT(mystery_magic, list(
var/grant_extra_mag = TRUE
/// Stores the current sound channel we're using so we can cut off our own sounds as needed. Randomized after each roll
var/current_sound_channel
+ /// How many time can it still be used?
+ var/uses_left
+ /// A list of weakrefs to mind datums of people that opened it and how many times.
+ var/list/datum/weakref/minds_that_opened_us
/obj/structure/mystery_box/Initialize(mapload)
. = ..()
@@ -126,6 +154,7 @@ GLOBAL_LIST_INIT(mystery_magic, list(
QDEL_NULL(presented_item)
if(current_sound_channel)
SSsounds.free_sound_channel(current_sound_channel)
+ minds_that_opened_us = null
return ..()
/obj/structure/mystery_box/attack_hand(mob/living/user, list/modifiers)
@@ -163,6 +192,11 @@ GLOBAL_LIST_INIT(mystery_magic, list(
current_sound_channel = SSsounds.reserve_sound_channel(src)
playsound(src, open_sound, 70, FALSE, channel = current_sound_channel, falloff_exponent = 10)
playsound(src, crate_open_sound, 80)
+ if(user.mind)
+ LAZYINITLIST(minds_that_opened_us)
+ var/datum/weakref/ref = WEAKREF(user.mind)
+ minds_that_opened_us[ref] += 1
+ uses_left--
/// The box has finished choosing, mark it as available for grabbing
/obj/structure/mystery_box/proc/present_weapon()
@@ -186,6 +220,9 @@ GLOBAL_LIST_INIT(mystery_magic, list(
box_close_timer = null
box_expire_timer = null
addtimer(CALLBACK(src, PROC_REF(ready_again)), MBOX_DURATION_STANDBY)
+ if(uses_left <= 0)
+ visible_message("[src] breaks down.")
+ deconstruct(disassembled = FALSE)
/// The cooldown between activations has finished, shake to show that
/obj/structure/mystery_box/proc/ready_again()
@@ -196,22 +233,26 @@ GLOBAL_LIST_INIT(mystery_magic, list(
/// Someone attacked the box with an empty hand, spawn the shown prize and give it to them, then close the box
/obj/structure/mystery_box/proc/grant_weapon(mob/living/user)
- var/obj/item/instantiated_weapon = new presented_item.selected_path(src)
- user.put_in_hands(instantiated_weapon)
-
- if(isgun(instantiated_weapon)) // handle pins + possibly extra ammo
- var/obj/item/gun/instantiated_gun = instantiated_weapon
- instantiated_gun.unlock()
- if(grant_extra_mag && istype(instantiated_gun, /obj/item/gun/ballistic))
- var/obj/item/gun/ballistic/instantiated_ballistic = instantiated_gun
- if(!instantiated_ballistic.internal_magazine)
- var/obj/item/ammo_box/magazine/extra_mag = new instantiated_ballistic.spawn_magazine_type(loc)
- user.put_in_hands(extra_mag)
-
+ var/atom/movable/instantiated_weapon = new presented_item.selected_path(loc)
user.visible_message(span_notice("[user] takes [presented_item] from [src]."), span_notice("You take [presented_item] from [src]."), vision_distance = COMBAT_MESSAGE_RANGE)
playsound(src, grant_sound, 70, FALSE, channel = current_sound_channel, falloff_exponent = 10)
close_box()
+ if(!isitem(instantiated_weapon))
+ return
+ user.put_in_hands(instantiated_weapon)
+
+ if(!isgun(instantiated_weapon))
+ return
+ // handle pins + possibly extra ammo
+ var/obj/item/gun/instantiated_gun = instantiated_weapon
+ instantiated_gun.unlock()
+ if(!grant_extra_mag || !istype(instantiated_gun, /obj/item/gun/ballistic))
+ return
+ var/obj/item/gun/ballistic/instantiated_ballistic = instantiated_gun
+ if(!instantiated_ballistic.internal_magazine)
+ var/obj/item/ammo_box/magazine/extra_mag = new instantiated_ballistic.spawn_magazine_type(loc)
+ user.put_in_hands(extra_mag)
/obj/structure/mystery_box/guns
desc = "A wooden crate that seems equally magical and mysterious, capable of granting the user all kinds of different pieces of gear. This one seems focused on firearms."
@@ -231,6 +272,28 @@ GLOBAL_LIST_INIT(mystery_magic, list(
/obj/structure/mystery_box/wands/generate_valid_types()
valid_types = GLOB.mystery_magic
+///One of a kind, rarely found by fishing in the ocean.
+/obj/structure/mystery_box/fishing
+ name = "treasure chest"
+ desc = "A pirate-y chest that seems equally magial and mysterious, capable of granting the user different pieces of gear."
+ icon_state = "treasure"
+ uses_left = 18
+ max_integrity = 100
+ damage_deflection = 30
+ grant_extra_mag = FALSE
+
+/obj/structure/mystery_box/handle_deconstruct(disassembled)
+ new /obj/item/stack/sheet/mineral/wood(drop_location(), 2)
+ return ..()
+
+/obj/structure/mystery_box/fishing/generate_valid_types()
+ valid_types = GLOB.mystery_fishing
+
+/obj/structure/mystery_box/fishing/activate(mob/living/user)
+ if(user.mind && minds_that_opened_us?[WEAKREF(user.mind)] >= 3)
+ to_chat(user, span_warning("[src] refuses to open to you anymore. Perhaps you should present it to someone else..."))
+ return
+ return ..()
/// This represents the item that comes out of the box and is constantly changing before the box finishes deciding. Can probably be just an /atom or /movable.
/obj/mystery_box_item
@@ -290,14 +353,14 @@ GLOBAL_LIST_INIT(mystery_magic, list(
/// animate() isn't up to the task for queueing up icon changes, so this is the proc we call with timers to update our icon
/obj/mystery_box_item/proc/update_random_icon(new_item_type)
- var/obj/item/new_item = new_item_type
- icon = initial(new_item.icon)
- icon_state = initial(new_item.icon_state)
+ var/atom/movable/new_item = new_item_type
+ icon = new_item::icon
+ icon_state = new_item::icon_state
/obj/mystery_box_item/proc/present_item()
- var/obj/item/selected_item = selected_path
+ var/atom/movable/selected_item = selected_path
add_filter("ready_outline", 2, list("type" = "outline", "color" = COLOR_VIVID_YELLOW, "size" = 0.2))
- name = initial(selected_item.name)
+ name = selected_item::name
parent_box.present_weapon()
claimable = TRUE
diff --git a/code/game/objects/structures/pinatas.dm b/code/game/objects/structures/pinatas.dm
index 63502f12ad5e28..6483d39b1a26cc 100644
--- a/code/game/objects/structures/pinatas.dm
+++ b/code/game/objects/structures/pinatas.dm
@@ -89,3 +89,28 @@
desc = "A papier-mâché corgi that contains various candy and explosives, must be set up before you can smash it."
icon_state = "pinata_syndie"
pinata_type = /obj/structure/pinata/syndie
+
+/obj/structure/pinata/donk
+ name = "donk corgi pinata"
+ desc = "A papier-mâché representation of a corgi that contains all sorts of savory treats."
+ icon_state = "pinata_donk_placed"
+ base_icon_state = "pinata_donk_placed"
+ debris = /obj/effect/decal/cleanable/wrapping/pinata/donk
+ candy_options = list(
+ /obj/item/food/donkpocket/warm,
+ /obj/item/food/donkpocket/warm/pizza,
+ /obj/item/food/donkpocket/warm/honk,
+ /obj/item/food/donkpocket/warm/berry,
+ /obj/item/food/donkpocket/warm,
+ /obj/item/food/tatortot,
+ /obj/item/gun/ballistic/automatic/pistol/toy,
+ /obj/item/hot_potato/harmless/toy,
+ /obj/item/storage/box/donkpockets,
+ /obj/item/toy/plush/donkpocket,
+ )
+
+/obj/item/pinata/donk
+ name = "\improper Donk Co. pinata assembly kit"
+ desc = "A papier-mâché corgi that contains various foodstuff and toys, must be set up before you can smash it."
+ icon_state = "pinata_donk"
+ pinata_type = /obj/structure/pinata/donk
diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm
index c3d9b115f01ded..b23641a416a16f 100644
--- a/code/game/objects/structures/railings.dm
+++ b/code/game/objects/structures/railings.dm
@@ -155,6 +155,7 @@
icon_state = "wooden_railing"
item_deconstruct = /obj/item/stack/sheet/mineral/wood
layer = ABOVE_MOB_LAYER
+ plane = GAME_PLANE
/obj/structure/railing/wooden_fence/Initialize(mapload)
. = ..()
@@ -167,7 +168,6 @@
/obj/structure/railing/wooden_fence/proc/adjust_dir_layer(direction)
layer = (direction & NORTH) ? MOB_LAYER : initial(layer)
- plane = (direction & NORTH) ? GAME_PLANE : initial(plane)
/obj/structure/railing/corner/end/wooden_fence
diff --git a/code/game/objects/structures/shower.dm b/code/game/objects/structures/shower.dm
index 7faf3e5d478ec7..67fe92951d0ae7 100644
--- a/code/game/objects/structures/shower.dm
+++ b/code/game/objects/structures/shower.dm
@@ -195,6 +195,10 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16))
deconstruct()
return TRUE
+/obj/machinery/shower/setDir(newdir)
+ . = ..()
+ update_appearance(UPDATE_OVERLAYS)
+
/obj/machinery/shower/update_overlays()
. = ..()
if(!actually_on)
@@ -202,14 +206,14 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16))
var/mutable_appearance/water_falling = mutable_appearance('icons/obj/watercloset.dmi', "water", ABOVE_MOB_LAYER)
water_falling.color = mix_color_from_reagents(reagents.reagent_list)
switch(dir)
- if(NORTH)
- water_falling.pixel_y += pixel_shift
+
if(SOUTH)
- water_falling.pixel_y -= pixel_shift
+ water_falling.pixel_z -= 24
if(EAST)
- water_falling.pixel_x += pixel_shift
+ water_falling.pixel_w += 16
if(WEST)
- water_falling.pixel_x -= pixel_shift
+ water_falling.pixel_w -= 16
+
. += water_falling
/obj/machinery/shower/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents)
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index e44a2e2596a226..f813e355c7e6fb 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -316,9 +316,11 @@
return NONE
if(!user.transferItemToLoc(tool, drop_location(), silent = FALSE))
return ITEM_INTERACT_BLOCKING
- //Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf)
- tool.pixel_x = clamp(text2num(LAZYACCESS(modifiers, ICON_X)) - 16, -(world.icon_size/2), world.icon_size/2)
- tool.pixel_y = clamp(text2num(LAZYACCESS(modifiers, ICON_Y)) - 16, -(world.icon_size/2), world.icon_size/2)
+ // Items are centered by default, but we move them if click ICON_X and ICON_Y are available
+ if(LAZYACCESS(modifiers, ICON_X) && LAZYACCESS(modifiers, ICON_Y))
+ // Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf)
+ tool.pixel_x = clamp(text2num(LAZYACCESS(modifiers, ICON_X)) - 16, -(world.icon_size*0.5), world.icon_size*0.5)
+ tool.pixel_y = clamp(text2num(LAZYACCESS(modifiers, ICON_Y)) - 16, -(world.icon_size*0.5), world.icon_size*0.5)
AfterPutItemOnTable(tool, user)
return ITEM_INTERACT_SUCCESS
@@ -354,6 +356,7 @@
if((shove_flags & SHOVE_KNOCKDOWN_BLOCKED) || !(shove_flags & SHOVE_BLOCKED))
return
target.Knockdown(SHOVE_KNOCKDOWN_TABLE)
+ target.apply_status_effect(/datum/status_effect/next_shove_stuns)
target.visible_message(span_danger("[shover.name] shoves [target.name] onto \the [src]!"),
span_userdanger("You're shoved onto \the [src] by [shover.name]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, shover)
to_chat(shover, span_danger("You shove [target.name] onto \the [src]!"))
@@ -791,16 +794,6 @@
pushed_mob.set_resting(TRUE, TRUE)
visible_message(span_notice("[user] lays [pushed_mob] on [src]."))
-///Align the mob with the table when buckled.
-/obj/structure/table/optable/post_buckle_mob(mob/living/buckled)
- . = ..()
- buckled.pixel_y += 6
-
-///Disalign the mob with the table when unbuckled.
-/obj/structure/table/optable/post_unbuckle_mob(mob/living/buckled)
- . = ..()
- buckled.pixel_y -= 6
-
/// Any mob that enters our tile will be marked as a potential patient. They will be turned into a patient if they lie down.
/obj/structure/table/optable/proc/mark_patient(datum/source, mob/living/carbon/potential_patient)
SIGNAL_HANDLER
diff --git a/code/game/objects/structures/toiletbong.dm b/code/game/objects/structures/toiletbong.dm
index 0ea21e9ff84803..254f151c017df9 100644
--- a/code/game/objects/structures/toiletbong.dm
+++ b/code/game/objects/structures/toiletbong.dm
@@ -15,7 +15,7 @@
AddComponent(/datum/component/simple_rotation, post_rotation = CALLBACK(src, PROC_REF(post_rotation)))
create_storage(max_total_storage = 100, max_slots = 12, canhold = /obj/item/food)
atom_storage.attack_hand_interact = FALSE
- atom_storage.rustle_sound = FALSE
+ atom_storage.do_rustle = FALSE
atom_storage.animated = FALSE
weed_overlay = mutable_appearance('icons/obj/watercloset.dmi', "[base_icon_state]_overlay")
diff --git a/code/game/objects/structures/water_structures/toilet.dm b/code/game/objects/structures/water_structures/toilet.dm
index 7a64404a238a90..7237cd03c5045a 100644
--- a/code/game/objects/structures/water_structures/toilet.dm
+++ b/code/game/objects/structures/water_structures/toilet.dm
@@ -36,6 +36,7 @@
update_appearance(UPDATE_ICON)
if(mapload && SSmapping.level_trait(z, ZTRAIT_STATION))
AddElement(/datum/element/lazy_fishing_spot, /datum/fish_source/toilet)
+ AddElement(/datum/element/fish_safe_storage)
register_context()
/obj/structure/toilet/add_context(atom/source, list/context, obj/item/held_item, mob/user)
diff --git a/code/game/objects/structures/water_structures/water_source.dm b/code/game/objects/structures/water_structures/water_source.dm
index b7ad26a65ea7e1..9420156d91805b 100644
--- a/code/game/objects/structures/water_structures/water_source.dm
+++ b/code/game/objects/structures/water_structures/water_source.dm
@@ -137,6 +137,15 @@
base_icon_state = "puddle"
resistance_flags = UNACIDABLE
+/obj/structure/water_source/puddle/Initialize(mapload)
+ . = ..()
+ register_context()
+
+/obj/structure/water_source/puddle/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ . = ..()
+ if(isnull(held_item))
+ context[SCREENTIP_CONTEXT_RMB] = "Scoop Tadpoles"
+
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/structure/water_source/puddle/attack_hand(mob/user, list/modifiers)
icon_state = "[base_icon_state]-splash"
@@ -147,3 +156,20 @@
icon_state = "[base_icon_state]-splash"
. = ..()
icon_state = base_icon_state
+
+/obj/structure/water_source/puddle/attack_hand_secondary(mob/living/carbon/human/user, list/modifiers)
+ . = ..()
+ if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
+ return
+ if(DOING_INTERACTION_WITH_TARGET(user, src))
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+ icon_state = "[base_icon_state]-splash"
+ balloon_alert(user, "scooping tadpoles...")
+ if(do_after(user, 5 SECONDS, src))
+ playsound(loc, 'sound/effects/slosh.ogg', 15, TRUE)
+ balloon_alert(user, "got a tadpole")
+ var/obj/item/fish/tadpole/tadpole = new(loc)
+ tadpole.randomize_size_and_weight()
+ user.put_in_hands(tadpole)
+ icon_state = base_icon_state
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
diff --git a/code/game/sound.dm b/code/game/sound.dm
index 01eb5d66ef44cf..7ce288c9db84ad 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -473,4 +473,27 @@
'sound/creatures/monkey/monkey_screech_6.ogg',
'sound/creatures/monkey/monkey_screech_7.ogg',
)
+ if(SFX_TOOL_SWITCH)
+ soundin = 'sound/items/handling/tool_switch.ogg'
+ if(SFX_KEYBOARD_CLICKS)
+ soundin = pick(
+ 'sound/machines/computer/keyboard_clicks_1.ogg',
+ 'sound/machines/computer/keyboard_clicks_2.ogg',
+ 'sound/machines/computer/keyboard_clicks_3.ogg',
+ 'sound/machines/computer/keyboard_clicks_4.ogg',
+ 'sound/machines/computer/keyboard_clicks_5.ogg',
+ 'sound/machines/computer/keyboard_clicks_6.ogg',
+ 'sound/machines/computer/keyboard_clicks_7.ogg',
+ )
+ if(SFX_STONE_DROP)
+ soundin = pick(
+ 'sound/items/stones/stone_drop1.ogg',
+ 'sound/items/stones/stone_drop2.ogg',
+ 'sound/items/stones/stone_drop3.ogg',
+ )
+ if(SFX_STONE_PICKUP)
+ soundin = pick(
+ 'sound/items/stones/stone_pick_up1.ogg',
+ 'sound/items/stones/stone_pick_up2.ogg',
+ )
return soundin
diff --git a/code/game/turfs/closed/indestructible.dm b/code/game/turfs/closed/indestructible.dm
index ed80e02a8be348..470177ee397271 100644
--- a/code/game/turfs/closed/indestructible.dm
+++ b/code/game/turfs/closed/indestructible.dm
@@ -63,6 +63,7 @@
/turf/closed/indestructible/splashscreen
name = "Space Station 13"
desc = null
+ baseturfs = /turf/cordon
icon = 'icons/blanks/blank_title.png'
icon_state = ""
pixel_x = 0 // SKYRAT EDIT - Re-centering the title screen - ORIGINAL: pixel_x = -64
@@ -104,11 +105,6 @@ INITIALIZE_IMMEDIATE(/turf/closed/indestructible/splashscreen)
return ..()
SKYRAT EDIT REMOVAL END */
-/turf/closed/indestructible/start_area
- name = null
- desc = null
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
-
/turf/closed/indestructible/reinforced
name = "reinforced wall"
desc = "A huge chunk of reinforced metal used to separate rooms. Effectively impervious to conventional methods of destruction."
diff --git a/code/game/turfs/closed/minerals.dm b/code/game/turfs/closed/minerals.dm
index 8b29df20ed4c5b..11125a9de0ccc4 100644
--- a/code/game/turfs/closed/minerals.dm
+++ b/code/game/turfs/closed/minerals.dm
@@ -782,7 +782,10 @@
/turf/closed/mineral/gibtonite/attackby(obj/item/attacking_item, mob/living/user, params)
var/previous_stage = stage
- if(istype(attacking_item, /obj/item/mining_scanner) || istype(attacking_item, /obj/item/t_scanner/adv_mining_scanner) && stage == GIBTONITE_ACTIVE)
+ if(istype(attacking_item, /obj/item/goliath_infuser_hammer) && stage == GIBTONITE_ACTIVE)
+ user.visible_message(span_notice("[user] digs [attacking_item] to [src]..."), span_notice("Your tendril hammer instictively digs and wraps around [src] to stop it..."))
+ defuse(user)
+ else if(istype(attacking_item, /obj/item/mining_scanner) || istype(attacking_item, /obj/item/t_scanner/adv_mining_scanner) && stage == GIBTONITE_ACTIVE)
user.visible_message(span_notice("[user] holds [attacking_item] to [src]..."), span_notice("You use [attacking_item] to locate where to cut off the chain reaction and attempt to stop it..."))
defuse(user)
..()
diff --git a/code/game/turfs/open/floor/mineral_floor.dm b/code/game/turfs/open/floor/mineral_floor.dm
index e8be1331378ab4..a8cf2a6f37d078 100644
--- a/code/game/turfs/open/floor/mineral_floor.dm
+++ b/code/game/turfs/open/floor/mineral_floor.dm
@@ -97,6 +97,10 @@
/turf/open/floor/mineral/titanium/blue/airless
initial_gas_mix = AIRLESS_ATMOS
+/turf/open/floor/mineral/titanium/blue/lavaland_atmos
+ initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ planetary_atmos = TRUE
+
/turf/open/floor/mineral/titanium/white
icon_state = "titanium_white"
floor_tile = /obj/item/stack/tile/mineral/titanium/white
diff --git a/code/game/turfs/open/floor/misc_floor.dm b/code/game/turfs/open/floor/misc_floor.dm
index d4866720b494ea..d43e4b5e92fe6f 100644
--- a/code/game/turfs/open/floor/misc_floor.dm
+++ b/code/game/turfs/open/floor/misc_floor.dm
@@ -17,12 +17,17 @@
/turf/open/floor/circuit/Initialize(mapload)
SSmapping.nuke_tiles += src
RegisterSignal(loc, COMSIG_AREA_POWER_CHANGE, PROC_REF(handle_powerchange))
- handle_powerchange(loc)
+ var/area/cur_area = get_area(src)
+ if (!isnull(cur_area))
+ handle_powerchange(cur_area, TRUE)
. = ..()
/turf/open/floor/circuit/Destroy()
SSmapping.nuke_tiles -= src
UnregisterSignal(loc, COMSIG_AREA_POWER_CHANGE)
+ var/area/cur_area = get_area(src)
+ if(on && !isnull(cur_area))
+ cur_area.removeStaticPower(CIRCUIT_FLOOR_POWERUSE, AREA_USAGE_STATIC_LIGHT)
return ..()
/turf/open/floor/circuit/update_appearance(updates)
@@ -47,7 +52,7 @@
handle_powerchange(new_area)
/// Enables/disables our lighting based off our source area
-/turf/open/floor/circuit/proc/handle_powerchange(area/source)
+/turf/open/floor/circuit/proc/handle_powerchange(area/source, mapload = FALSE)
SIGNAL_HANDLER
var/old_on = on
if(always_off)
@@ -59,7 +64,7 @@
if(on)
source.addStaticPower(CIRCUIT_FLOOR_POWERUSE, AREA_USAGE_STATIC_LIGHT)
- else
+ else if (!mapload)
source.removeStaticPower(CIRCUIT_FLOOR_POWERUSE, AREA_USAGE_STATIC_LIGHT)
update_appearance()
diff --git a/code/game/turfs/open/water.dm b/code/game/turfs/open/water.dm
index 7881c63d567609..4a8244a649196c 100644
--- a/code/game/turfs/open/water.dm
+++ b/code/game/turfs/open/water.dm
@@ -41,3 +41,7 @@
baseturfs = /turf/open/water/beach
immerse_overlay_color = "#7799AA"
fishing_datum = /datum/fish_source/ocean/beach
+
+/turf/open/water/lavaland_atmos
+ initial_gas_mix = LAVALAND_DEFAULT_ATMOS
+ planetary_atmos = TRUE
diff --git a/code/game/world.dm b/code/game/world.dm
index 53f3a0fe95d0ef..4b5b598d341ea5 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -1,11 +1,13 @@
#define RESTART_COUNTER_PATH "data/round_counter.txt"
-
+/// Load byond-tracy. If USE_BYOND_TRACY is defined, then this is ignored and byond-tracy is always loaded.
+#define USE_TRACY_PARAMETER "tracy"
/// Force the log directory to be something specific in the data/logs folder
#define OVERRIDE_LOG_DIRECTORY_PARAMETER "log-directory"
/// Prevent the master controller from starting automatically
#define NO_INIT_PARAMETER "no-init"
GLOBAL_VAR(restart_counter)
+GLOBAL_VAR(tracy_log)
/**
* WORLD INITIALIZATION
@@ -67,10 +69,12 @@ GLOBAL_VAR(restart_counter)
#ifdef USE_BYOND_TRACY
#warn USE_BYOND_TRACY is enabled
if(!tracy_initialized)
- init_byond_tracy()
+#else
+ if(!tracy_initialized && (USE_TRACY_PARAMETER in params))
+#endif
+ GLOB.tracy_log = init_byond_tracy()
Genesis(tracy_initialized = TRUE)
return
-#endif
Profile(PROFILE_RESTART)
Profile(PROFILE_RESTART, type = "sendmaps")
@@ -217,6 +221,9 @@ GLOBAL_VAR(restart_counter)
logger.init_logging()
+ if(GLOB.tracy_log)
+ rustg_file_write("[GLOB.tracy_log]", "[GLOB.log_directory]/tracy.loc")
+
var/latest_changelog = file("[global.config.directory]/../html/changelogs/archive/" + time2text(world.timeofday, "YYYY-MM") + ".yml")
GLOB.changelog_hash = fexists(latest_changelog) ? md5(latest_changelog) : 0 //for telling if the changelog has changed recently
@@ -487,7 +494,9 @@ GLOBAL_VAR(restart_counter)
CRASH("Unsupported platform: [system_type]")
var/init_result = call_ext(library, "init")("block")
- if (init_result != "0")
+ if(length(init_result) != 0 && init_result[1] == ".") // if first character is ., then it returned the output filename
+ return init_result
+ else if(init_result != "0")
CRASH("Error initializing byond-tracy: [init_result]")
/world/proc/init_debugger()
@@ -502,4 +511,5 @@ GLOBAL_VAR(restart_counter)
#undef NO_INIT_PARAMETER
#undef OVERRIDE_LOG_DIRECTORY_PARAMETER
+#undef USE_TRACY_PARAMETER
#undef RESTART_COUNTER_PATH
diff --git a/code/modules/admin/antag_panel.dm b/code/modules/admin/antag_panel.dm
index a54aafde916d3f..029de127fa31b0 100644
--- a/code/modules/admin/antag_panel.dm
+++ b/code/modules/admin/antag_panel.dm
@@ -81,6 +81,8 @@ GLOBAL_VAR(antag_prototypes)
result += "No body!"
if(current && HAS_TRAIT(current, TRAIT_MINDSHIELD))
result += "Mindshielded"
+ if(current && HAS_MIND_TRAIT(current, TRAIT_UNCONVERTABLE))
+ result += "Unconvertable"
//Move these to mob
if(iscyborg(current))
var/mob/living/silicon/robot/robot = current
diff --git a/code/modules/admin/smites/supply_pod_quick.dm b/code/modules/admin/smites/supply_pod_quick.dm
index 6012e84ccac435..f222857860e39b 100644
--- a/code/modules/admin/smites/supply_pod_quick.dm
+++ b/code/modules/admin/smites/supply_pod_quick.dm
@@ -37,7 +37,7 @@
podspawn(list(
"target" = get_turf(target),
"path" = /obj/structure/closet/supplypod/centcompod,
- "style" = STYLE_CENTCOM,
+ "style" = /datum/pod_style/centcom,
"spawn" = target_path,
"damage" = SUPPLY_POD_QUICK_DAMAGE,
"explosionSize" = list(0, 0, 0, SUPPLY_POD_QUICK_FIRE_RANGE),
diff --git a/code/modules/admin/verbs/admingame.dm b/code/modules/admin/verbs/admingame.dm
index fd339a1e098800..d537b9ee898e4f 100644
--- a/code/modules/admin/verbs/admingame.dm
+++ b/code/modules/admin/verbs/admingame.dm
@@ -379,7 +379,7 @@ ADMIN_VERB(combo_hud, R_ADMIN, "Toggle Combo HUD", "Toggles the Admin Combo HUD.
combo_hud_enabled = TRUE
- for (var/hudtype in list(DATA_HUD_SECURITY_ADVANCED, DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC_ADVANCED))
+ for (var/hudtype in list(DATA_HUD_SECURITY_ADVANCED, DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC, DATA_HUD_BOT_PATH))
var/datum/atom_hud/atom_hud = GLOB.huds[hudtype]
atom_hud.show_to(mob)
@@ -395,7 +395,7 @@ ADMIN_VERB(combo_hud, R_ADMIN, "Toggle Combo HUD", "Toggles the Admin Combo HUD.
combo_hud_enabled = FALSE
- for (var/hudtype in list(DATA_HUD_SECURITY_ADVANCED, DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC_ADVANCED))
+ for (var/hudtype in list(DATA_HUD_SECURITY_ADVANCED, DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC, DATA_HUD_BOT_PATH))
var/datum/atom_hud/atom_hud = GLOB.huds[hudtype]
atom_hud.hide_from(mob)
diff --git a/code/modules/admin/verbs/ert.dm b/code/modules/admin/verbs/ert.dm
index 5903a2196dcfba..e116a9daf9a53c 100644
--- a/code/modules/admin/verbs/ert.dm
+++ b/code/modules/admin/verbs/ert.dm
@@ -91,6 +91,7 @@
"spawn_admin" = list("desc" = "Spawn yourself as briefing officer", "type" = "boolean", "value" = "[(ertemplate.spawn_admin ? "Yes" : "No")]"),
"notify_players" = list("desc" = "Notify players that you have sent an ERT", "type" = "boolean", "value" = "[(ertemplate.notify_players ? "Yes" : "No")]"), //SKYRAT EDIT ADDITION
"use_custom_shuttle" = list("desc" = "Use the ERT's custom shuttle (if it has one)", "type" = "boolean", "value" = "[(ertemplate.use_custom_shuttle ? "Yes" : "No")]"),
+ "mob_type" = list("desc" = "Base Species", "callback" = CALLBACK(src, PROC_REF(makeERTTemplateModified)), "type" = "datum", "path" = "/mob/living/carbon/human", "subtypesonly" = TRUE, "value" = ertemplate.mob_type),
)
)
@@ -119,6 +120,7 @@
ertemplate.spawn_admin = prefs["spawn_admin"]["value"] == "Yes"
ertemplate.notify_players = prefs["notify_players"]["value"] == "Yes" //SKYRAT EDIT ADDITION
ertemplate.use_custom_shuttle = prefs["use_custom_shuttle"]["value"] == "Yes"
+ ertemplate.mob_type = prefs["mob_type"]["value"]
var/list/spawnpoints = GLOB.emergencyresponseteamspawn
var/index = 0
@@ -224,11 +226,15 @@
continue
//Spawn the body
- var/mob/living/carbon/human/ert_operative = new ertemplate.mobtype(spawnloc)
- chosen_candidate.client.prefs.safe_transfer_prefs_to(ert_operative, is_antag = TRUE)
+ var/mob/living/carbon/human/ert_operative
+ if(ertemplate.mob_type)
+ ert_operative = new ertemplate.mob_type(spawnloc)
+ else
+ ert_operative = new /mob/living/carbon/human(spawnloc)
+ chosen_candidate.client.prefs.safe_transfer_prefs_to(ert_operative, is_antag = TRUE)
ert_operative.key = chosen_candidate.key
- if(ertemplate.enforce_human || !(ert_operative.dna.species.changesource_flags & ERT_SPAWN)) // Don't want any exploding plasmemes
+ if(ertemplate.enforce_human || !(ert_operative.dna.species.changesource_flags & ERT_SPAWN))
ert_operative.set_species(/datum/species/human)
//Give antag datum
diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm
index c4e4257e84fc7e..b70465666f3d05 100644
--- a/code/modules/admin/verbs/playsound.dm
+++ b/code/modules/admin/verbs/playsound.dm
@@ -54,13 +54,13 @@ ADMIN_VERB(play_direct_mob_sound, R_SOUND, "Play Direct Mob Sound", "Play a soun
SEND_SOUND(target, sound)
BLACKBOX_LOG_ADMIN_VERB("Play Direct Mob Sound")
-///Takes an input from either proc/play_web_sound or the request manager and runs it through youtube-dl and prompts the user before playing it to the server.
+///Takes an input from either proc/play_web_sound or the request manager and runs it through yt-dlp and prompts the user before playing it to the server.
/proc/web_sound(mob/user, input, credit)
if(!check_rights(R_SOUND))
return
var/ytdl = CONFIG_GET(string/invoke_youtubedl)
if(!ytdl)
- to_chat(user, span_boldwarning("Youtube-dl was not configured, action unavailable"), confidential = TRUE) //Check config.txt for the INVOKE_YOUTUBEDL value
+ to_chat(user, span_boldwarning("yt-dlp was not configured, action unavailable"), confidential = TRUE) //Check config.txt for the INVOKE_YOUTUBEDL value
return
var/web_sound_url = ""
var/stop_web_sounds = FALSE
@@ -73,14 +73,14 @@ ADMIN_VERB(play_direct_mob_sound, R_SOUND, "Play Direct Mob Sound", "Play a soun
var/stdout = output[SHELLEO_STDOUT]
var/stderr = output[SHELLEO_STDERR]
if(errorlevel)
- to_chat(user, span_boldwarning("Youtube-dl URL retrieval FAILED:"), confidential = TRUE)
+ to_chat(user, span_boldwarning("yt-dlp URL retrieval FAILED:"), confidential = TRUE)
to_chat(user, span_warning("[stderr]"), confidential = TRUE)
return
var/list/data
try
data = json_decode(stdout)
catch(var/exception/e)
- to_chat(user, span_boldwarning("Youtube-dl JSON parsing FAILED:"), confidential = TRUE)
+ to_chat(user, span_boldwarning("yt-dlp JSON parsing FAILED:"), confidential = TRUE)
to_chat(user, span_warning("[e]: [stdout]"), confidential = TRUE)
return
if (data["url"])
diff --git a/code/modules/admin/verbs/server.dm b/code/modules/admin/verbs/server.dm
index e3a66dcd1b3cfe..f0817f06a3680f 100644
--- a/code/modules/admin/verbs/server.dm
+++ b/code/modules/admin/verbs/server.dm
@@ -16,10 +16,15 @@ ADMIN_VERB(toggle_hub, R_SERVER, "Toggle Hub", "Toggles the server's visilibilit
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Hub Visibility", "[GLOB.hub_visibility ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
+#define REGULAR_RESTART "Regular Restart"
+#define REGULAR_RESTART_DELAYED "Regular Restart (with delay)"
+#define HARD_RESTART "Hard Restart (No Delay/Feedback Reason)"
+#define HARDEST_RESTART "Hardest Restart (No actions, just reboot)"
+#define TGS_RESTART "Server Restart (Kill and restart DD)"
ADMIN_VERB(restart, R_SERVER, "Reboot World", "Restarts the world immediately.", ADMIN_CATEGORY_SERVER)
- var/list/options = list("Regular Restart", "Regular Restart (with delay)", "Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)")
+ var/list/options = list(REGULAR_RESTART, REGULAR_RESTART_DELAYED, HARD_RESTART, HARDEST_RESTART)
if(world.TgsAvailable())
- options += "Server Restart (Kill and restart DD)";
+ options += TGS_RESTART;
if(SSticker.admin_delay_notice)
if(alert(user, "Are you sure? An admin has already delayed the round end for the following reason: [SSticker.admin_delay_notice]", "Confirmation", "Yes", "No") != "Yes")
@@ -32,12 +37,12 @@ ADMIN_VERB(restart, R_SERVER, "Reboot World", "Restarts the world immediately.",
BLACKBOX_LOG_ADMIN_VERB("Reboot World")
var/init_by = "Initiated by [user.holder.fakekey ? "Admin" : user.key]."
switch(result)
- if("Regular Restart")
+ if(REGULAR_RESTART)
if(!user.is_localhost())
if(alert(user, "Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart")
return FALSE
SSticker.Reboot(init_by, "admin reboot - by [user.key] [user.holder.fakekey ? "(stealth)" : ""]", 10)
- if("Regular Restart (with delay)")
+ if(REGULAR_RESTART_DELAYED)
var/delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null
if(!delay)
return FALSE
@@ -45,16 +50,22 @@ ADMIN_VERB(restart, R_SERVER, "Reboot World", "Restarts the world immediately.",
if(alert(user,"Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart")
return FALSE
SSticker.Reboot(init_by, "admin reboot - by [user.key] [user.holder.fakekey ? "(stealth)" : ""]", delay * 10)
- if("Hard Restart (No Delay, No Feeback Reason)")
+ if(HARD_RESTART)
to_chat(world, "World reboot - [init_by]")
world.Reboot()
- if("Hardest Restart (No actions, just reboot)")
+ if(HARDEST_RESTART)
to_chat(world, "Hard world reboot - [init_by]")
world.Reboot(fast_track = TRUE)
- if("Server Restart (Kill and restart DD)")
+ if(TGS_RESTART)
to_chat(world, "Server restart - [init_by]")
world.TgsEndProcess()
+#undef REGULAR_RESTART
+#undef REGULAR_RESTART_DELAYED
+#undef HARD_RESTART
+#undef HARDEST_RESTART
+#undef TGS_RESTART
+
ADMIN_VERB(end_round, R_SERVER, "End Round", "Forcibly ends the round and allows the server to restart normally.", ADMIN_CATEGORY_SERVER)
var/confirm = tgui_alert(user, "End the round and restart the game world?", "End Round", list("Yes", "Cancel"))
if(confirm != "Yes")
diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm
index 56ee817f0f5c19..bbc5c7a7b03abb 100644
--- a/code/modules/antagonists/_common/antag_spawner.dm
+++ b/code/modules/antagonists/_common/antag_spawner.dm
@@ -105,7 +105,7 @@
/// The antag datum applied
var/antag_datum = /datum/antagonist/nukeop/reinforcement
/// Style used by the droppod
- var/pod_style = STYLE_SYNDICATE
+ var/pod_style = /datum/pod_style/syndicate
/// Do we use a random subtype of the outfit?
var/use_subtypes = TRUE
/// Where do we land our pod?
@@ -188,7 +188,7 @@
special_role_name = ROLE_CLOWN_OPERATIVE
outfit = /datum/outfit/syndicate/clownop/no_crystals
antag_datum = /datum/antagonist/nukeop/reinforcement/clownop
- pod_style = STYLE_HONK
+ pod_style = /datum/pod_style/clown
use_subtypes = FALSE
//////SYNDICATE BORG
@@ -313,7 +313,7 @@
/// The antag datum applied
var/datum/antagonist/antag_datum
/// Style used by the droppod
- var/pod_style = STYLE_SYNDICATE
+ var/pod_style = /datum/pod_style/syndicate
/// Do we use a random subtype of the outfit?
var/use_subtypes = TRUE
/// The antag role we check if the ghosts have enabled to get the poll.
diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm
index ec0c980d218a14..ef68ea4e602bab 100644
--- a/code/modules/antagonists/abductor/abductor.dm
+++ b/code/modules/antagonists/abductor/abductor.dm
@@ -79,12 +79,13 @@
owner.special_role = ROLE_ABDUCTOR
objectives += team.objectives
finalize_abductor()
- ADD_TRAIT(owner, TRAIT_ABDUCTOR_TRAINING, ABDUCTOR_ANTAGONIST)
+ // We don't want abductors to be converted by other antagonists
+ owner.add_traits(list(TRAIT_ABDUCTOR_TRAINING, TRAIT_UNCONVERTABLE), ABDUCTOR_ANTAGONIST)
return ..()
/datum/antagonist/abductor/on_removal()
owner.special_role = null
- REMOVE_TRAIT(owner, TRAIT_ABDUCTOR_TRAINING, ABDUCTOR_ANTAGONIST)
+ owner.remove_traits(list(TRAIT_ABDUCTOR_TRAINING, TRAIT_UNCONVERTABLE), ABDUCTOR_ANTAGONIST)
return ..()
/datum/antagonist/abductor/greet()
@@ -95,20 +96,20 @@
/datum/antagonist/abductor/proc/finalize_abductor()
//Equip
- var/mob/living/carbon/human/H = owner.current
- H.set_species(/datum/species/abductor)
- var/obj/item/organ/internal/tongue/abductor/T = H.get_organ_slot(ORGAN_SLOT_TONGUE)
- T.mothership = "[team.name]"
+ var/mob/living/carbon/human/new_abductor = owner.current
+ new_abductor.set_species(/datum/species/abductor)
+ var/obj/item/organ/internal/tongue/abductor/abductor_tongue = new_abductor.get_organ_slot(ORGAN_SLOT_TONGUE)
+ abductor_tongue.mothership = "[team.name]"
- H.real_name = "[team.name] [sub_role]"
- H.equipOutfit(outfit)
+ new_abductor.real_name = "[team.name] [sub_role]"
+ new_abductor.equipOutfit(outfit)
// We require that the template be loaded here, so call it in a blocking manner, if its already done loading, this won't block
SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_ABDUCTOR_SHIPS)
//Teleport to ship
for(var/obj/effect/landmark/abductor/LM in GLOB.landmarks_list)
if(istype(LM, landmark_type) && LM.team_number == team.team_number)
- H.forceMove(LM.loc)
+ new_abductor.forceMove(LM.loc)
break
/datum/antagonist/abductor/scientist/on_gain()
@@ -142,13 +143,13 @@
if(!ishuman(owner.current))
to_chat(admin, span_warning("This only works on humans!"))
return
- var/mob/living/carbon/human/H = owner.current
+ var/mob/living/carbon/human/new_abductor = owner.current
var/gear = tgui_alert(admin,"Agent or Scientist Gear", "Gear", list("Agent", "Scientist"))
if(gear)
if(gear == "Agent")
- H.equipOutfit(/datum/outfit/abductor/agent)
+ new_abductor.equipOutfit(/datum/outfit/abductor/agent)
else
- H.equipOutfit(/datum/outfit/abductor/scientist)
+ new_abductor.equipOutfit(/datum/outfit/abductor/scientist)
/datum/team/abductor_team
member_name = "\improper Abductor"
diff --git a/code/modules/antagonists/abductor/equipment/gear/abductor_clothing.dm b/code/modules/antagonists/abductor/equipment/gear/abductor_clothing.dm
index c54ce6937d86f2..e5951473df087d 100644
--- a/code/modules/antagonists/abductor/equipment/gear/abductor_clothing.dm
+++ b/code/modules/antagonists/abductor/equipment/gear/abductor_clothing.dm
@@ -103,6 +103,8 @@
/obj/item/clothing/suit/armor/abductor/vest/proc/return_disguise_name(mob/living/carbon/human/source, list/identity)
SIGNAL_HANDLER
+ if(identity[VISIBLE_NAME_FORCED]) // name-forcing overrides disguise
+ return
identity[VISIBLE_NAME_FACE] = disguise.name
identity[VISIBLE_NAME_ID] = ""
diff --git a/code/modules/antagonists/abductor/equipment/glands/mindshock.dm b/code/modules/antagonists/abductor/equipment/glands/mindshock.dm
index 87870947f17d64..1a3f140c3415d0 100644
--- a/code/modules/antagonists/abductor/equipment/glands/mindshock.dm
+++ b/code/modules/antagonists/abductor/equipment/glands/mindshock.dm
@@ -15,7 +15,7 @@
for(var/mob/living/carbon/target in orange(4,owner_turf))
if(target == owner)
continue
- if(HAS_TRAIT(target, TRAIT_MINDSHIELD))
+ if(HAS_MIND_TRAIT(target, TRAIT_MINDSHIELD))
to_chat(target, span_notice("You hear a faint hum fill your ears, which quickly dies down."))
continue
@@ -41,7 +41,7 @@
if(target_human.stat)
continue
- if(HAS_TRAIT(target_human, TRAIT_MINDSHIELD))
+ if(HAS_MIND_TRAIT(target_human, TRAIT_UNCONVERTABLE))
to_chat(target_human, span_notice("You hear a low drone as something foreign attempts to enter your mind, but the noise fades after a few moments."))
continue
diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm
index f608ae6ccaf51e..6a08d0d9a7109f 100644
--- a/code/modules/antagonists/brother/brother.dm
+++ b/code/modules/antagonists/brother/brother.dm
@@ -94,7 +94,7 @@
flashed.balloon_alert(source, "[flashed.p_theyre()] loyal to someone else!")
return
- if (HAS_TRAIT(flashed, TRAIT_MINDSHIELD))
+ if (HAS_TRAIT(flashed, TRAIT_UNCONVERTABLE))
flashed.balloon_alert(source, "[flashed.p_they()] resist!")
return
@@ -222,6 +222,9 @@
return
. = ..()
member.remove_antag_datum(/datum/antagonist/brother)
+ if (!length(members))
+ qdel(src)
+ return
if (isnull(member.current))
return
for (var/datum/mind/brother_mind as anything in members)
diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm
index be55ab790a831c..e5ca28c3d75582 100644
--- a/code/modules/antagonists/changeling/changeling.dm
+++ b/code/modules/antagonists/changeling/changeling.dm
@@ -573,6 +573,8 @@
new_profile.emissive_eyes = target.emissive_eyes
new_profile.scream_type = target.selected_scream?.type || /datum/scream_type/none
new_profile.laugh_type = target.selected_laugh?.type || /datum/laugh_type/none
+ new_profile.target_body_scaling = target.get_mob_height()
+ new_profile.target_size = target.mob_size
//SKYRAT EDIT ADDITION END
// Grab skillchips they have
@@ -949,6 +951,9 @@
user.regenerate_icons()
user.name = user.get_visible_name()
current_profile = chosen_profile
+ user.mob_size = chosen_profile.target_size
+ //this has to be at the end of the proc or it breaks everything below it, womp womp
+ user.set_mob_height(chosen_profile.target_body_scaling)
// SKYRAT EDIT END
// Changeling profile themselves. Store a data to store what every DNA instance looked like.
diff --git a/code/modules/antagonists/clown_ops/clown_weapons.dm b/code/modules/antagonists/clown_ops/clown_weapons.dm
index 130b6c9af5f1b2..bd2dfd4b0da019 100644
--- a/code/modules/antagonists/clown_ops/clown_weapons.dm
+++ b/code/modules/antagonists/clown_ops/clown_weapons.dm
@@ -17,6 +17,7 @@
desc = "advanced clown shoes that protect the wearer and render them nearly immune to slipping on their own peels. They also squeak at 100% capacity."
clothing_traits = list(TRAIT_NO_SLIP_WATER)
slowdown = SHOES_SLOWDOWN
+ body_parts_covered = FEET|LEGS
armor_type = /datum/armor/clown_shoes_combat
strip_delay = 70
resistance_flags = NONE
@@ -49,6 +50,7 @@
strip_delay = 70
resistance_flags = NONE
always_noslip = TRUE
+ body_parts_covered = FEET|LEGS
/datum/armor/banana_shoes_combat
melee = 25
@@ -192,7 +194,7 @@
//BOMBANANA
/obj/item/seeds/banana/bombanana
- name = "pack of bombanana seeds"
+ name = "bombanana seed pack"
desc = "They're seeds that grow into bombanana trees. When grown, give to the clown."
plantname = "Bombanana Tree"
product = /obj/item/food/grown/banana/bombanana
diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm
index bc71d9386824f4..423ec6b441df52 100644
--- a/code/modules/antagonists/cult/blood_magic.dm
+++ b/code/modules/antagonists/cult/blood_magic.dm
@@ -162,14 +162,14 @@
name = "Stun"
desc = "Empowers your hand to stun and mute a victim on contact. Gets weaker depending on how many have joined the Cult."
button_icon_state = "hand"
- magic_path = "/obj/item/melee/blood_magic/stun"
+ magic_path = /obj/item/melee/blood_magic/stun
health_cost = 10
/datum/action/innate/cult/blood_spell/teleport
name = "Teleport"
desc = "Empowers your hand to teleport yourself or another cultist to a teleport rune on contact."
button_icon_state = "tele"
- magic_path = "/obj/item/melee/blood_magic/teleport"
+ magic_path = /obj/item/melee/blood_magic/teleport
health_cost = 7
/datum/action/innate/cult/blood_spell/emp
@@ -194,20 +194,20 @@
desc = "Empowers your hand to start handcuffing victim on contact, and mute them if successful."
button_icon_state = "cuff"
charges = 4
- magic_path = "/obj/item/melee/blood_magic/shackles"
+ magic_path = /obj/item/melee/blood_magic/shackles
/datum/action/innate/cult/blood_spell/construction
name = "Twisted Construction"
desc = "Empowers your hand to corrupt certain metalic objects. Converts: Plasteel into runed metal 50 metal into a construct shell Living cyborgs into constructs after a delay Cyborg shells into construct shells Purified soulstones (and any shades inside) into cultist soulstones Airlocks into brittle runed airlocks after a delay (harm intent)"
button_icon_state = "transmute"
- magic_path = "/obj/item/melee/blood_magic/construction"
+ magic_path = /obj/item/melee/blood_magic/construction
health_cost = 12
/datum/action/innate/cult/blood_spell/equipment
name = "Summon Combat Equipment"
desc = "Empowers your hand to summon combat gear onto a cultist you touch, including cult armor, a cult bola, and a cult sword. Not recommended for use before the blood cult's presence has been revealed."
button_icon_state = "equip"
- magic_path = "/obj/item/melee/blood_magic/armor"
+ magic_path = /obj/item/melee/blood_magic/armor
/datum/action/innate/cult/blood_spell/dagger
name = "Summon Ritual Dagger"
@@ -339,7 +339,7 @@
invocation = "Fel'th Dol Ab'orod!"
button_icon_state = "manip"
charges = 5
- magic_path = "/obj/item/melee/blood_magic/manipulator"
+ magic_path = /obj/item/melee/blood_magic/manipulator
deletes_on_empty = FALSE
// The "magic hand" items
diff --git a/code/modules/antagonists/cult/cult_other.dm b/code/modules/antagonists/cult/cult_other.dm
index 9435baedba11aa..f9e1462a30efe1 100644
--- a/code/modules/antagonists/cult/cult_other.dm
+++ b/code/modules/antagonists/cult/cult_other.dm
@@ -25,8 +25,6 @@
return FALSE
#endif
- if(target.mind.unconvertable)
- return FALSE
if(ishuman(target) && target.mind.holy_role)
return FALSE
if(specific_cult?.is_sacrifice_target(target.mind))
@@ -36,6 +34,6 @@
return FALSE
if(IS_HERETIC_OR_MONSTER(target))
return FALSE
- if(HAS_TRAIT(target, TRAIT_MINDSHIELD) || issilicon(target) || isbot(target) || isdrone(target))
+ if(HAS_MIND_TRAIT(target, TRAIT_UNCONVERTABLE) || issilicon(target) || isbot(target) || isdrone(target))
return FALSE //can't convert machines, shielded, or braindead
return TRUE
diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm
index ee6adea0c3e8f8..4cd69ac9be2b08 100644
--- a/code/modules/antagonists/ert/ert.dm
+++ b/code/modules/antagonists/ert/ert.dm
@@ -239,6 +239,10 @@
H.open_internals(H.get_item_for_held_index(2))
H.equipOutfit(outfit)
+ if(isplasmaman(H))
+ var/obj/item/mod/control/our_modsuit = locate() in H.get_equipped_items()
+ if(our_modsuit)
+ our_modsuit.install(new /obj/item/mod/module/plasma_stabilizer)
/datum/antagonist/ert/greet()
if(!ert_team)
diff --git a/code/modules/antagonists/heretic/heretic_knowledge.dm b/code/modules/antagonists/heretic/heretic_knowledge.dm
index 16c8bde219c8ef..81573b47915621 100644
--- a/code/modules/antagonists/heretic/heretic_knowledge.dm
+++ b/code/modules/antagonists/heretic/heretic_knowledge.dm
@@ -540,7 +540,7 @@
var/mob/living/mob_to_summon
/datum/heretic_knowledge/summon/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc)
- summon_ritual_mob(user, loc, mob_to_summon)
+ return summon_ritual_mob(user, loc, mob_to_summon)
/**
* Creates the ritual mob and grabs a ghost for it
@@ -640,7 +640,6 @@
/obj/item/restraints/handcuffs/cable/zipties,
/obj/item/circular_saw,
/obj/item/scalpel,
- /obj/item/binoculars,
/obj/item/clothing/gloves/color/yellow,
/obj/item/melee/baton/security,
/obj/item/clothing/glasses/sunglasses,
diff --git a/code/modules/antagonists/heretic/influences.dm b/code/modules/antagonists/heretic/influences.dm
index 350c694012e849..6184879a3587f7 100644
--- a/code/modules/antagonists/heretic/influences.dm
+++ b/code/modules/antagonists/heretic/influences.dm
@@ -251,7 +251,7 @@
return SECONDARY_ATTACK_CALL_NORMAL
if(being_drained)
- balloon_alert(user, "already being drained!")
+ loc.balloon_alert(user, "already being drained!")
else
INVOKE_ASYNC(src, PROC_REF(drain_influence), user, 1)
@@ -283,15 +283,15 @@
/obj/effect/heretic_influence/proc/drain_influence(mob/living/user, knowledge_to_gain)
being_drained = TRUE
- balloon_alert(user, "draining influence...")
+ loc.balloon_alert(user, "draining influence...")
if(!do_after(user, 10 SECONDS, src, hidden = TRUE))
being_drained = FALSE
- balloon_alert(user, "interrupted!")
+ loc.balloon_alert(user, "interrupted!")
return
// We don't need to set being_drained back since we delete after anyways
- balloon_alert(user, "influence drained")
+ loc.balloon_alert(user, "influence drained")
var/datum/antagonist/heretic/heretic_datum = IS_HERETIC(user)
heretic_datum.knowledge_points += knowledge_to_gain
diff --git a/code/modules/antagonists/heretic/knowledge/ash_lore.dm b/code/modules/antagonists/heretic/knowledge/ash_lore.dm
index 496b90b3f1272e..315bb14b6648e8 100644
--- a/code/modules/antagonists/heretic/knowledge/ash_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/ash_lore.dm
@@ -1,7 +1,5 @@
/**
* # The path of Ash.
- * Spell names are in this language: OLD NORDIC
- * Both are related: Nordic Mythology-Yggdrassil-Ash Tree Genus-Ash
*
* Goes as follows:
*
@@ -233,7 +231,7 @@
text = "[generate_heretic_text()] Fear the blaze, for the Ashlord, [user.real_name] has ascended! The flames shall consume all! [generate_heretic_text()]",
title = "[generate_heretic_text()]",
sound = 'sound/ambience/antag/heretic/ascend_ash.ogg',
- color_override = "white",
+ color_override = "pink",
)
var/datum/action/cooldown/spell/fire_sworn/circle_spell = new(user.mind)
diff --git a/code/modules/antagonists/heretic/knowledge/blade_lore.dm b/code/modules/antagonists/heretic/knowledge/blade_lore.dm
index 357e789416d1dd..de79151739f4b5 100644
--- a/code/modules/antagonists/heretic/knowledge/blade_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/blade_lore.dm
@@ -1,7 +1,5 @@
/**
* # The path of Blades. Stab stab.
- * Spell names are in this language: ARAMAIC
- * Both are related: Aramaic-Damascus-Blade
*
* Goes as follows:
*
diff --git a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm
index 8a94aada74a67a..a3e7576132036c 100644
--- a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm
@@ -1,7 +1,5 @@
/**
* # The path of Cosmos.
- * Spell names are in this language: SUMERIAN
- * Both are related: Sumerian-Original-Primordial-Cosmic
*
* Goes as follows:
*
@@ -285,7 +283,7 @@
text = "[generate_heretic_text()] A Star Gazer has arrived into the station, [user.real_name] has ascended! This station is the domain of the Cosmos! [generate_heretic_text()]",
title = "[generate_heretic_text()]",
sound = 'sound/ambience/antag/heretic/ascend_cosmic.ogg',
- color_override = "purple",
+ color_override = "pink",
)
var/mob/living/basic/heretic_summon/star_gazer/star_gazer_mob = new /mob/living/basic/heretic_summon/star_gazer(loc)
star_gazer_mob.maxHealth = INFINITY
diff --git a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm
index 9e963ae9ea71bd..6dde1a3038d4a1 100644
--- a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm
@@ -5,8 +5,6 @@
/**
* # The path of Flesh.
- * Spell names are in this language: LATIN
- * Both are related: Latin-Rome-Hedonism-Flesh
*
* Goes as follows:
*
@@ -332,7 +330,7 @@
text = "[generate_heretic_text()] Ever coiling vortex. Reality unfolded. ARMS OUTREACHED, THE LORD OF THE NIGHT, [user.real_name] has ascended! Fear the ever twisting hand! [generate_heretic_text()]",
title = "[generate_heretic_text()]",
sound = 'sound/ambience/antag/heretic/ascend_flesh.ogg',
- color_override = "red",
+ color_override = "pink",
)
var/datum/action/cooldown/spell/shapeshift/shed_human_form/worm_spell = new(user.mind)
diff --git a/code/modules/antagonists/heretic/knowledge/lock_lore.dm b/code/modules/antagonists/heretic/knowledge/lock_lore.dm
index b238d6dd3c7f3a..ac375d7942a36a 100644
--- a/code/modules/antagonists/heretic/knowledge/lock_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/lock_lore.dm
@@ -1,7 +1,5 @@
/**
* # The path of Lock.
- * Spell names are in this language: EGYPTIAN
- * Both are related: Egyptian-Mysteries-Secrets-Lock
*
* Goes as follows:
*
@@ -138,7 +136,7 @@
/datum/heretic_knowledge/limited_amount/concierge_rite // item that creates 3 max at a time heretic only barriers, probably should limit to 1 only, holy people can also pass
name = "Concierge's Rite"
- desc = "Allows you to transmute a white crayon, a wooden plank, and a multitool to create a Labyrinth Handbook. \
+ desc = "Allows you to transmute a stick of chalk, a wooden plank, and a multitool to create a Labyrinth Handbook. \
It can materialize a barricade at range that only you and people resistant to magic can pass. 3 uses."
gain_text = "The Concierge scribbled my name into the Handbook. \"Welcome to your new home, fellow Steward.\""
required_atoms = list(
@@ -243,7 +241,7 @@
text = "Delta-class dimensional anomaly detec[generate_heretic_text()] Reality rended, torn. Gates open, doors open, [user.real_name] has ascended! Fear the tide! [generate_heretic_text()]",
title = "[generate_heretic_text()]",
sound = 'sound/ambience/antag/heretic/ascend_knock.ogg',
- color_override = "yellow",
+ color_override = "pink",
)
// buffs
diff --git a/code/modules/antagonists/heretic/knowledge/moon_lore.dm b/code/modules/antagonists/heretic/knowledge/moon_lore.dm
index 5ba55b64058cb5..3c6b4e2109b690 100644
--- a/code/modules/antagonists/heretic/knowledge/moon_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/moon_lore.dm
@@ -1,7 +1,5 @@
/**
* # The path of Moon.
- * Spell names are in this language: ANCIENT HEBREW
- * Both are related: Ancient Hebrew-Moon Mysticism-Moon
*
* Goes as follows:
*
@@ -211,7 +209,7 @@
The truth shall finally devour the lie! [generate_heretic_text()]",
title = "[generate_heretic_text()]",
sound = 'sound/ambience/antag/heretic/ascend_moon.ogg',
- color_override = "blue",
+ color_override = "pink",
)
ADD_TRAIT(user, TRAIT_MADNESS_IMMUNE, REF(src))
@@ -236,7 +234,7 @@
to_chat(crewmate, span_boldwarning("[user]'s rise is influencing those who are weak willed. Their minds shall rend." ))
continue
// Mindshielded and anti-magic folks are immune against this effect because this is a magical mind effect
- if(HAS_TRAIT(crewmate, TRAIT_MINDSHIELD) || crewmate.can_block_magic(MAGIC_RESISTANCE))
+ if(HAS_MIND_TRAIT(crewmate, TRAIT_UNCONVERTABLE) || crewmate.can_block_magic(MAGIC_RESISTANCE))
to_chat(crewmate, span_boldwarning("You feel shielded from something." ))
continue
if(amount_of_lunatics > length(GLOB.human_list) * 0.2)
diff --git a/code/modules/antagonists/heretic/knowledge/rust_lore.dm b/code/modules/antagonists/heretic/knowledge/rust_lore.dm
index fe0d03ec18f50e..3a081c8d295fbb 100644
--- a/code/modules/antagonists/heretic/knowledge/rust_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/rust_lore.dm
@@ -1,6 +1,5 @@
/**
* # The path of Rust.
- * Spell names are in this language: OLD SLAVIC
*
* Goes as follows:
*
@@ -257,7 +256,7 @@
text = "[generate_heretic_text()] Fear the decay, for the Rustbringer, [user.real_name] has ascended! None shall escape the corrosion! [generate_heretic_text()]",
title = "[generate_heretic_text()]",
sound = 'sound/ambience/antag/heretic/ascend_rust.ogg',
- color_override = "brown",
+ color_override = "pink",
)
trigger(loc)
RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm
index bc6cb750b219a1..5055d2d9628ce5 100644
--- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm
+++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm
@@ -87,12 +87,11 @@ GLOBAL_LIST_EMPTY(heretic_sacrifice_landmarks)
has_gravity = STANDARD_GRAVITY
ambience_index = AMBIENCE_SPOOKY
sound_environment = SOUND_ENVIRONMENT_CAVE
- area_flags = UNIQUE_AREA | NOTELEPORT | HIDDEN_AREA | BLOCK_SUICIDE
+ area_flags = UNIQUE_AREA | NOTELEPORT | HIDDEN_AREA | BLOCK_SUICIDE | NO_BOH
/area/centcom/heretic_sacrifice/Initialize(mapload)
if(!ambientsounds)
- ambientsounds = GLOB.ambience_assoc[ambience_index]
- ambientsounds += 'sound/ambience/ambiatm1.ogg'
+ ambientsounds = GLOB.ambience_assoc[ambience_index] + 'sound/ambience/ambiatm1.ogg'
return ..()
/area/centcom/heretic_sacrifice/ash //also, the default
diff --git a/code/modules/antagonists/heretic/knowledge/side_ash_moon.dm b/code/modules/antagonists/heretic/knowledge/side_ash_moon.dm
index 758ee0548d5fcf..3ed3f110a802a2 100644
--- a/code/modules/antagonists/heretic/knowledge/side_ash_moon.dm
+++ b/code/modules/antagonists/heretic/knowledge/side_ash_moon.dm
@@ -82,12 +82,3 @@
route = PATH_SIDE
poll_ignore_define = POLL_IGNORE_ASH_SPIRIT
depth = 10
-
-/datum/heretic_knowledge/summon/ashy/cleanup_atoms(list/selected_atoms)
- var/obj/item/bodypart/head/ritual_head = locate() in selected_atoms
- if(!ritual_head)
- CRASH("[type] required a head bodypart, yet did not have one in selected_atoms when it reached cleanup_atoms.")
-
- // Spill out any brains or stuff before we delete it.
- ritual_head.drop_organs()
- return ..()
diff --git a/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm b/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm
index 11918c66a29063..0a4f7fbe86a1ca 100644
--- a/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm
+++ b/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm
@@ -86,7 +86,7 @@
/datum/heretic_knowledge/summon/rusty
name = "Rusted Ritual"
- desc = "Allows you to transmute a pool of vomit, some cable coil, and 5 sheets of titanium into a Rust Walker. \
+ desc = "Allows you to transmute a pool of vomit, some cable coil, and 10 sheets of iron into a Rust Walker. \
Rust Walkers excel at spreading rust and are moderately strong in combat."
gain_text = "I combined my knowledge of creation with my desire for corruption. The Marshal knew my name, and the Rusted Hills echoed out."
next_knowledge = list(
@@ -95,7 +95,7 @@
)
required_atoms = list(
/obj/effect/decal/cleanable/vomit = 1,
- /obj/item/stack/sheet/mineral/titanium = 5,
+ /obj/item/stack/sheet/iron = 10,
/obj/item/stack/cable_coil = 15,
)
mob_to_summon = /mob/living/basic/heretic_summon/rust_walker
@@ -104,11 +104,3 @@
poll_ignore_define = POLL_IGNORE_RUST_SPIRIT
depth = 8
-/datum/heretic_knowledge/summon/rusty/cleanup_atoms(list/selected_atoms)
- var/obj/item/bodypart/head/ritual_head = locate() in selected_atoms
- if(!ritual_head)
- CRASH("[type] required a head bodypart, yet did not have one in selected_atoms when it reached cleanup_atoms.")
-
- // Spill out any brains or stuff before we delete it.
- ritual_head.drop_organs()
- return ..()
diff --git a/code/modules/antagonists/heretic/knowledge/starting_lore.dm b/code/modules/antagonists/heretic/knowledge/starting_lore.dm
index 7cb3b82a39ac21..d8d3b6cc5ab624 100644
--- a/code/modules/antagonists/heretic/knowledge/starting_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/starting_lore.dm
@@ -1,5 +1,4 @@
// Heretic starting knowledge.
-// Default heretic language is Ancient Greek, because, uh, they're like ancient and shit.
/// Global list of all heretic knowledge that have route = PATH_START. List of PATHS.
GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge())
@@ -310,20 +309,26 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge())
required_atoms = list()
research_tree_icon_path = 'icons/mob/actions/actions_animal.dmi'
research_tree_icon_state = "god_transmit"
+ /// amount of research points granted
+ var/reward = 5
/datum/heretic_knowledge/feast_of_owls/can_be_invoked(datum/antagonist/heretic/invoker)
return !invoker.feast_of_owls
/datum/heretic_knowledge/feast_of_owls/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc)
- //amount of research points granted
- var/reward = 5
var/alert = tgui_alert(user,"Do you really want to forsake your ascension? This action cannot be reverted.", "Feast of Owls", list("Yes I'm sure", "No"), 30 SECONDS)
- if( alert != "Yes I'm sure")
+ if(alert != "Yes I'm sure" || QDELETED(user) || QDELETED(src) || get_dist(user, loc) > 2)
return FALSE
- user.set_temp_blindness(reward SECONDS)
- user.AdjustParalyzed(reward SECONDS)
- user.playsound_local(get_turf(user), 'sound/ambience/antag/heretic/heretic_gain_intense.ogg', 100, FALSE, pressure_affected = FALSE, use_reverb = FALSE)
var/datum/antagonist/heretic/heretic_datum = IS_HERETIC(user)
+ if(QDELETED(heretic_datum) || heretic_datum.feast_of_owls)
+ return FALSE
+
+ . = TRUE
+
+ heretic_datum.feast_of_owls = TRUE
+ user.set_temp_blindness(reward * 1 SECONDS)
+ user.AdjustParalyzed(reward * 1 SECONDS)
+ user.playsound_local(get_turf(user), 'sound/ambience/antag/heretic/heretic_gain_intense.ogg', 100, FALSE, pressure_affected = FALSE, use_reverb = FALSE)
for(var/i in 1 to reward)
user.emote("scream")
playsound(loc, 'sound/items/eatfood.ogg', 100, TRUE)
@@ -331,7 +336,10 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge())
to_chat(user, span_danger("You feel something invisible tearing away at your very essence!"))
user.do_jitter_animation()
sleep(1 SECONDS)
- heretic_datum.feast_of_owls = TRUE
+ if(QDELETED(user) || QDELETED(heretic_datum))
+ return FALSE
+
to_chat(user, span_danger(span_big("Your ambition is ravaged, but something powerful remains in its wake...")))
var/drain_message = pick(strings(HERETIC_INFLUENCE_FILE, "drain_message"))
to_chat(user, span_hypnophrase(span_big("[drain_message]")))
+ return .
diff --git a/code/modules/antagonists/heretic/knowledge/void_lore.dm b/code/modules/antagonists/heretic/knowledge/void_lore.dm
index 0fd4f925fa8873..51f0146fca38d8 100644
--- a/code/modules/antagonists/heretic/knowledge/void_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/void_lore.dm
@@ -1,7 +1,5 @@
/**
* # The path of VOID.
- * Spell names are in this language: PALI
- * Both are related: Pali-Buddhism-Nothingness-Void
*
* Goes as follows:
*
@@ -221,7 +219,7 @@
text = "[generate_heretic_text()] The nobleman of void [user.real_name] has arrived, stepping along the Waltz that ends worlds! [generate_heretic_text()]",
title = "[generate_heretic_text()]",
sound = 'sound/ambience/antag/heretic/ascend_void.ogg',
- color_override = "blue",
+ color_override = "pink",
)
ADD_TRAIT(user, TRAIT_RESISTLOWPRESSURE, MAGIC_TRAIT)
diff --git a/code/modules/antagonists/heretic/magic/aggressive_spread.dm b/code/modules/antagonists/heretic/magic/aggressive_spread.dm
index 0c14550f0b2690..dfb4a94847406c 100644
--- a/code/modules/antagonists/heretic/magic/aggressive_spread.dm
+++ b/code/modules/antagonists/heretic/magic/aggressive_spread.dm
@@ -10,8 +10,8 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 30 SECONDS
- invocation = "Agresiv'noe rasprostra-neniye!"
- invocation_type = INVOCATION_SHOUT
+ invocation = "A'GRSV SPR'D"
+ invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
aoe_radius = 2
diff --git a/code/modules/antagonists/heretic/magic/apetravulnera.dm b/code/modules/antagonists/heretic/magic/apetravulnera.dm
index eedef71f4b6c8f..e80d08911848cb 100644
--- a/code/modules/antagonists/heretic/magic/apetravulnera.dm
+++ b/code/modules/antagonists/heretic/magic/apetravulnera.dm
@@ -10,8 +10,8 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 45 SECONDS
- invocation = "Shea' shen-eh!"
- invocation_type = INVOCATION_SHOUT
+ invocation = "AP'TRA VULN'RA!"
+ invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
cast_range = 4
diff --git a/code/modules/antagonists/heretic/magic/ash_ascension.dm b/code/modules/antagonists/heretic/magic/ash_ascension.dm
index 70422a7c48a377..8b564198a61eba 100644
--- a/code/modules/antagonists/heretic/magic/ash_ascension.dm
+++ b/code/modules/antagonists/heretic/magic/ash_ascension.dm
@@ -10,7 +10,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 70 SECONDS
- invocation = "EID'R-ELDR!!!"
+ invocation = "FL'MS"
invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
@@ -72,8 +72,8 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 30 SECONDS
- invocation = "ILLA-LASARA'FOSS!!!"
- invocation_type = INVOCATION_SHOUT
+ invocation = "C'SC'DE"
+ invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
/// The radius the flames will go around the caster.
@@ -112,7 +112,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 300
- invocation = "Eld'sky!"
+ invocation = "F'RE"
invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/ash_jaunt.dm b/code/modules/antagonists/heretic/magic/ash_jaunt.dm
index 4f8c59d635145a..41242063a90988 100644
--- a/code/modules/antagonists/heretic/magic/ash_jaunt.dm
+++ b/code/modules/antagonists/heretic/magic/ash_jaunt.dm
@@ -10,7 +10,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 15 SECONDS
- invocation = "Askgraar' goetur!"
+ invocation = "ASH'N P'SSG'"
invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/blood_cleave.dm b/code/modules/antagonists/heretic/magic/blood_cleave.dm
index b3370a3ccc6146..d5317f23e344bf 100644
--- a/code/modules/antagonists/heretic/magic/blood_cleave.dm
+++ b/code/modules/antagonists/heretic/magic/blood_cleave.dm
@@ -10,7 +10,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 45 SECONDS
- invocation = "Fer're!"
+ invocation = "CL'VE!"
invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/blood_siphon.dm b/code/modules/antagonists/heretic/magic/blood_siphon.dm
index 6280353a072a56..1e3d6258826d4b 100644
--- a/code/modules/antagonists/heretic/magic/blood_siphon.dm
+++ b/code/modules/antagonists/heretic/magic/blood_siphon.dm
@@ -11,7 +11,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 15 SECONDS
- invocation = "Sanguis suctio!"
+ invocation = "FL'MS O'ET'RN'ITY."
invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/burglar_finesse.dm b/code/modules/antagonists/heretic/magic/burglar_finesse.dm
index c5264119bb48e4..a90acb8495f149 100644
--- a/code/modules/antagonists/heretic/magic/burglar_finesse.dm
+++ b/code/modules/antagonists/heretic/magic/burglar_finesse.dm
@@ -9,7 +9,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 40 SECONDS
- invocation = "Khenem"
+ invocation = "Y'O'K!"
invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/cosmic_expansion.dm b/code/modules/antagonists/heretic/magic/cosmic_expansion.dm
index 6869dc0df51c02..3fb197d392cb08 100644
--- a/code/modules/antagonists/heretic/magic/cosmic_expansion.dm
+++ b/code/modules/antagonists/heretic/magic/cosmic_expansion.dm
@@ -11,7 +11,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 45 SECONDS
- invocation = "An'gar baltil!"
+ invocation = "C'SM'S 'XP'ND"
invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/cosmic_runes.dm b/code/modules/antagonists/heretic/magic/cosmic_runes.dm
index e07aa4fbe8b8a3..207b60ae9393ad 100644
--- a/code/modules/antagonists/heretic/magic/cosmic_runes.dm
+++ b/code/modules/antagonists/heretic/magic/cosmic_runes.dm
@@ -11,7 +11,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 15 SECONDS
- invocation = "Is'zara-runen"
+ invocation = "ST'R R'N'"
invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/eldritch_blind.dm b/code/modules/antagonists/heretic/magic/eldritch_blind.dm
index 413ff4fe678105..8df20503821b08 100644
--- a/code/modules/antagonists/heretic/magic/eldritch_blind.dm
+++ b/code/modules/antagonists/heretic/magic/eldritch_blind.dm
@@ -5,7 +5,7 @@
overlay_icon_state = "bg_heretic_border"
school = SCHOOL_FORBIDDEN
- invocation = "Caecus"
+ invocation = "E'E'S"
spell_requirements = NONE
cast_range = 10
diff --git a/code/modules/antagonists/heretic/magic/eldritch_emplosion.dm b/code/modules/antagonists/heretic/magic/eldritch_emplosion.dm
index 4028f80f84ceac..c68ed07c81f8c6 100644
--- a/code/modules/antagonists/heretic/magic/eldritch_emplosion.dm
+++ b/code/modules/antagonists/heretic/magic/eldritch_emplosion.dm
@@ -8,7 +8,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 30 SECONDS
- invocation = "Pulsus Energiae"
+ invocation = "E'P"
invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/eldritch_shapeshift.dm b/code/modules/antagonists/heretic/magic/eldritch_shapeshift.dm
index bde032a3b39fdf..e598f1f9215b93 100644
--- a/code/modules/antagonists/heretic/magic/eldritch_shapeshift.dm
+++ b/code/modules/antagonists/heretic/magic/eldritch_shapeshift.dm
@@ -7,7 +7,7 @@
overlay_icon_state = "bg_heretic_border"
school = SCHOOL_FORBIDDEN
- invocation = "Forma"
+ invocation = "SH'PE"
invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/fire_blast.dm b/code/modules/antagonists/heretic/magic/fire_blast.dm
index 8c6d632be9f2de..4c17ca5ffc0dea 100644
--- a/code/modules/antagonists/heretic/magic/fire_blast.dm
+++ b/code/modules/antagonists/heretic/magic/fire_blast.dm
@@ -12,7 +12,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 45 SECONDS
- invocation = "Eld'fjall!"
+ invocation = "V'LC'N!"
invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
channel_time = 5 SECONDS
diff --git a/code/modules/antagonists/heretic/magic/flesh_ascension.dm b/code/modules/antagonists/heretic/magic/flesh_ascension.dm
index add0704a8d61af..a2d792080e0584 100644
--- a/code/modules/antagonists/heretic/magic/flesh_ascension.dm
+++ b/code/modules/antagonists/heretic/magic/flesh_ascension.dm
@@ -9,7 +9,7 @@
school = SCHOOL_FORBIDDEN
- invocation = "REALITAS EXSERPAT!!"
+ invocation = "REALITY UNCOIL!"
invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/flesh_surgery.dm b/code/modules/antagonists/heretic/magic/flesh_surgery.dm
index a486b986cd81e0..ff474f063198fc 100644
--- a/code/modules/antagonists/heretic/magic/flesh_surgery.dm
+++ b/code/modules/antagonists/heretic/magic/flesh_surgery.dm
@@ -11,8 +11,8 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 20 SECONDS
- invocation = "Carnis chirurgia"
- invocation_type = INVOCATION_WHISPER
+ invocation = "CL'M M'N!" // "CLAIM MINE", but also almost "KALI MA"
+ invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
hand_path = /obj/item/melee/touch_attack/flesh_surgery
diff --git a/code/modules/antagonists/heretic/magic/furious_steel.dm b/code/modules/antagonists/heretic/magic/furious_steel.dm
index 36c7c07608bcbb..0ab882a9289e11 100644
--- a/code/modules/antagonists/heretic/magic/furious_steel.dm
+++ b/code/modules/antagonists/heretic/magic/furious_steel.dm
@@ -11,7 +11,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 60 SECONDS
- invocation = "Ham'sana-qasep!"
+ invocation = "F'LSH'NG S'LV'R!"
invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/manse_link.dm b/code/modules/antagonists/heretic/magic/manse_link.dm
index e077c6db2b45f4..06fd4dd9863f43 100644
--- a/code/modules/antagonists/heretic/magic/manse_link.dm
+++ b/code/modules/antagonists/heretic/magic/manse_link.dm
@@ -11,7 +11,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 20 SECONDS
- invocation = "Diaperaste' to-myalo!"
+ invocation = "PI'RC' TH' M'ND."
invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
antimagic_flags = MAGIC_RESISTANCE|MAGIC_RESISTANCE_MIND
diff --git a/code/modules/antagonists/heretic/magic/mansus_grasp.dm b/code/modules/antagonists/heretic/magic/mansus_grasp.dm
index 803bdd3d218e5f..43dde25374f89a 100644
--- a/code/modules/antagonists/heretic/magic/mansus_grasp.dm
+++ b/code/modules/antagonists/heretic/magic/mansus_grasp.dm
@@ -10,7 +10,7 @@
school = SCHOOL_EVOCATION
cooldown_time = 10 SECONDS
- invocation = "Ad verum per aspera!"
+ invocation = "R'CH T'H TR'TH!"
invocation_type = INVOCATION_SHOUT
// Mimes can cast it. Chaplains can cast it. Anyone can cast it, so long as they have a hand.
spell_requirements = SPELL_CASTABLE_WITHOUT_INVOCATION
diff --git a/code/modules/antagonists/heretic/magic/mind_gate.dm b/code/modules/antagonists/heretic/magic/mind_gate.dm
index aa6b8ef20af4dc..c5a6e74452a615 100644
--- a/code/modules/antagonists/heretic/magic/mind_gate.dm
+++ b/code/modules/antagonists/heretic/magic/mind_gate.dm
@@ -11,7 +11,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 20 SECONDS
- invocation = "Sha'ar ha-da'at"
+ invocation = "Op' 'oY 'Mi'd"
invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
cast_range = 6
diff --git a/code/modules/antagonists/heretic/magic/moon_parade.dm b/code/modules/antagonists/heretic/magic/moon_parade.dm
index 4919500e351de2..3b7f1d007cd6e1 100644
--- a/code/modules/antagonists/heretic/magic/moon_parade.dm
+++ b/code/modules/antagonists/heretic/magic/moon_parade.dm
@@ -11,7 +11,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 30 SECONDS
- invocation = "Tsiyun' levani!"
+ invocation = "L'N'R P'RAD"
invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/moon_ringleader.dm b/code/modules/antagonists/heretic/magic/moon_ringleader.dm
index e62c34bb990bbf..3c0b1d2aedb52c 100644
--- a/code/modules/antagonists/heretic/magic/moon_ringleader.dm
+++ b/code/modules/antagonists/heretic/magic/moon_ringleader.dm
@@ -12,7 +12,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 1 MINUTES
- invocation = "Manahel-qomem!"
+ invocation = "R''S 'E"
invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/moon_smile.dm b/code/modules/antagonists/heretic/magic/moon_smile.dm
index 236fd257e385d2..35f2d77e3e6b6b 100644
--- a/code/modules/antagonists/heretic/magic/moon_smile.dm
+++ b/code/modules/antagonists/heretic/magic/moon_smile.dm
@@ -12,7 +12,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 20 SECONDS
- invocation = "Hiyuk-levana!"
+ invocation = "Mo'N S'M'LE"
invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
cast_range = 6
diff --git a/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm b/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm
index 8a9b60644b6b73..4e37f5db17fed5 100644
--- a/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm
+++ b/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm
@@ -11,7 +11,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 1 MINUTES
- invocation = "Dyrth-a Vaktry'ggjandi"
+ invocation = "GL'RY T' TH' N'GHT'W'TCH'ER"
invocation_type = INVOCATION_WHISPER
spell_requirements = SPELL_REQUIRES_HUMAN
diff --git a/code/modules/antagonists/heretic/magic/realignment.dm b/code/modules/antagonists/heretic/magic/realignment.dm
index dbce0fe0940dd9..d3ddc03fbbef3a 100644
--- a/code/modules/antagonists/heretic/magic/realignment.dm
+++ b/code/modules/antagonists/heretic/magic/realignment.dm
@@ -14,8 +14,8 @@
cooldown_reduction_per_rank = -6 SECONDS // we're not a wizard spell but we use the levelling mechanic
spell_max_level = 10 // we can get up to / over a minute duration cd time
- invocation = "Rasut"
- invocation_type = INVOCATION_WHISPER
+ invocation = "R'S'T."
+ invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
/datum/action/cooldown/spell/realignment/is_valid_target(atom/cast_on)
diff --git a/code/modules/antagonists/heretic/magic/rust_wave.dm b/code/modules/antagonists/heretic/magic/rust_wave.dm
index 7ecb3fd0ffbba7..0282a32b2b6874 100644
--- a/code/modules/antagonists/heretic/magic/rust_wave.dm
+++ b/code/modules/antagonists/heretic/magic/rust_wave.dm
@@ -13,8 +13,8 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 30 SECONDS
- invocation = "Entro'pichniy-plim!"
- invocation_type = INVOCATION_SHOUT
+ invocation = "'NTR'P'C PL'M'"
+ invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
cone_levels = 5
@@ -78,8 +78,8 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 35 SECONDS
- invocation = "Diffunde' verbum!"
- invocation_type = INVOCATION_SHOUT
+ invocation = "SPR'D TH' WO'D"
+ invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
projectile_type = /obj/projectile/magic/aoe/rust_wave
diff --git a/code/modules/antagonists/heretic/magic/star_blast.dm b/code/modules/antagonists/heretic/magic/star_blast.dm
index 294608a03b998a..3eb62b7ada8140 100644
--- a/code/modules/antagonists/heretic/magic/star_blast.dm
+++ b/code/modules/antagonists/heretic/magic/star_blast.dm
@@ -10,7 +10,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 20 SECONDS
- invocation = "Pi-rig is'zara!"
+ invocation = "R'T'T' ST'R!"
invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/star_touch.dm b/code/modules/antagonists/heretic/magic/star_touch.dm
index dff56df4e3f1fa..89c5d02e7d4981 100644
--- a/code/modules/antagonists/heretic/magic/star_touch.dm
+++ b/code/modules/antagonists/heretic/magic/star_touch.dm
@@ -13,7 +13,7 @@
sound = 'sound/items/welder.ogg'
school = SCHOOL_FORBIDDEN
cooldown_time = 15 SECONDS
- invocation = "An'gar sig!"
+ invocation = "ST'R 'N'RG'!"
invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
antimagic_flags = MAGIC_RESISTANCE
diff --git a/code/modules/antagonists/heretic/magic/void_cold_cone.dm b/code/modules/antagonists/heretic/magic/void_cold_cone.dm
index 40dc9612a50f6f..92c45dc10b0100 100644
--- a/code/modules/antagonists/heretic/magic/void_cold_cone.dm
+++ b/code/modules/antagonists/heretic/magic/void_cold_cone.dm
@@ -11,7 +11,7 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 30 SECONDS
- invocation = "Sunya'kop!"
+ invocation = "FR'ZE!"
invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
diff --git a/code/modules/antagonists/heretic/magic/void_phase.dm b/code/modules/antagonists/heretic/magic/void_phase.dm
index f3f0864224c4c6..350ca0f29c1008 100644
--- a/code/modules/antagonists/heretic/magic/void_phase.dm
+++ b/code/modules/antagonists/heretic/magic/void_phase.dm
@@ -12,8 +12,8 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 30 SECONDS
- invocation = "Sunya'sthiti!"
- invocation_type = INVOCATION_SHOUT
+ invocation = "RE'L'TY PH'S'E."
+ invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
cast_range = 9
diff --git a/code/modules/antagonists/heretic/magic/void_pull.dm b/code/modules/antagonists/heretic/magic/void_pull.dm
index dc4673b0714ce4..2021bf8a04e4f8 100644
--- a/code/modules/antagonists/heretic/magic/void_pull.dm
+++ b/code/modules/antagonists/heretic/magic/void_pull.dm
@@ -11,8 +11,8 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 40 SECONDS
- invocation = "Sunya'apamkti!"
- invocation_type = INVOCATION_SHOUT
+ invocation = "BR'NG F'RTH TH'M T' M'."
+ invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
aoe_radius = 7
diff --git a/code/modules/antagonists/heretic/magic/wave_of_desperation.dm b/code/modules/antagonists/heretic/magic/wave_of_desperation.dm
index b9502f08967bbf..3b78b56ddc0ba1 100644
--- a/code/modules/antagonists/heretic/magic/wave_of_desperation.dm
+++ b/code/modules/antagonists/heretic/magic/wave_of_desperation.dm
@@ -11,8 +11,8 @@
school = SCHOOL_FORBIDDEN
cooldown_time = 5 MINUTES
- invocation = "Kher' Sekh-em waaef'k!"
- invocation_type = INVOCATION_SHOUT
+ invocation = "F'K 'FF."
+ invocation_type = INVOCATION_WHISPER
spell_requirements = NONE
aoe_radius = 3
diff --git a/code/modules/antagonists/heretic/status_effects/buffs.dm b/code/modules/antagonists/heretic/status_effects/buffs.dm
index c72e6bfdef1138..1668ea5a11ef72 100644
--- a/code/modules/antagonists/heretic/status_effects/buffs.dm
+++ b/code/modules/antagonists/heretic/status_effects/buffs.dm
@@ -232,6 +232,7 @@
blade_orbit_radius = 20,
time_between_initial_blades = 0.25 SECONDS,
blade_recharge_time = 1 MINUTES,
+ blade_type = /obj/effect/floating_blade,
)
src.blade_recharge_time = blade_recharge_time
diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_authentication_disk.dm b/code/modules/antagonists/nukeop/equipment/nuclear_authentication_disk.dm
index 7e06dd0d6e0503..fa2718833d36f7 100644
--- a/code/modules/antagonists/nukeop/equipment/nuclear_authentication_disk.dm
+++ b/code/modules/antagonists/nukeop/equipment/nuclear_authentication_disk.dm
@@ -26,7 +26,7 @@
/obj/item/disk/nuclear/Initialize(mapload)
. = ..()
- AddElement(/datum/element/bed_tuckable, mapload, 6, -6, 0)
+ AddElement(/datum/element/bed_tuckable, mapload, 6, 6, 0)
AddComponent(/datum/component/stationloving, !fake)
if(!fake)
diff --git a/code/modules/antagonists/nukeop/equipment/overwatch_tools.dm b/code/modules/antagonists/nukeop/equipment/overwatch_tools.dm
index 6c409f063707db..94c16d86dbeb5c 100644
--- a/code/modules/antagonists/nukeop/equipment/overwatch_tools.dm
+++ b/code/modules/antagonists/nukeop/equipment/overwatch_tools.dm
@@ -42,23 +42,4 @@ Happy hunting!
icon_state = "sunhudmed"
flags_cover = GLASSESCOVERSEYES
flash_protect = FLASH_PROTECTION_WELDER
- clothing_traits = list(TRAIT_REAGENT_SCANNER)
- var/list/hudlist = list(DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC_ADVANCED, DATA_HUD_SECURITY_ADVANCED)
-
-/obj/item/clothing/glasses/overwatch/equipped(mob/user, slot)
- . = ..()
- if(!(slot & ITEM_SLOT_EYES) || !ishuman(user))
- return
- for(var/hud in hudlist)
- var/datum/atom_hud/our_hud = GLOB.huds[hud]
- our_hud.show_to(user)
- user.add_traits(list(TRAIT_MEDICAL_HUD, TRAIT_SECURITY_HUD, TRAIT_DIAGNOSTIC_HUD), GLASSES_TRAIT)
-
-/obj/item/clothing/glasses/overwatch/dropped(mob/user)
- . = ..()
- user.remove_traits(list(TRAIT_MEDICAL_HUD, TRAIT_SECURITY_HUD, TRAIT_DIAGNOSTIC_HUD), GLASSES_TRAIT)
- if(!ishuman(user))
- return
- for(var/hud in hudlist)
- var/datum/atom_hud/our_hud = GLOB.huds[hud]
- our_hud.hide_from(user)
+ clothing_traits = list(TRAIT_REAGENT_SCANNER, TRAIT_SECURITY_HUD, TRAIT_MEDICAL_HUD, TRAIT_DIAGNOSTIC_HUD)
diff --git a/code/modules/antagonists/nukeop/outfits.dm b/code/modules/antagonists/nukeop/outfits.dm
index 0d122cff0c0617..bd6dbfacf457a4 100644
--- a/code/modules/antagonists/nukeop/outfits.dm
+++ b/code/modules/antagonists/nukeop/outfits.dm
@@ -102,8 +102,8 @@
name = "Syndicate Operative - Reinforcement"
tc = 0
backpack_contents = list(
- /obj/item/gun/ballistic/automatic/plastikov = 1,
- /obj/item/ammo_box/magazine/plastikov9mm = 2,
+ /obj/item/gun/ballistic/automatic/smartgun = 1,
+ /obj/item/ammo_box/magazine/smartgun = 2,
)
var/faction = "The Syndicate"
@@ -152,7 +152,7 @@
head = /obj/item/clothing/head/utility/hardhat/orange
shoes = /obj/item/clothing/shoes/workboots
glasses = /obj/item/clothing/glasses/meson
- faction = "the Donk Corporation"
+ faction = "Donk Company"
/datum/outfit/syndicate/reinforcement/waffle
name = "Syndicate Operative - Waffle Reinforcement"
diff --git a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm
index 16cad321853d96..c2c8d872cf38ce 100644
--- a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm
+++ b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm
@@ -161,11 +161,14 @@
desc = "A disk that contains advanced surgery procedures, must be loaded into an Operating Console."
surgeries = list(
/datum/surgery/advanced/lobotomy,
+ /datum/surgery/advanced/lobotomy/mechanic,
/datum/surgery/advanced/bioware/vein_threading,
+ /datum/surgery/advanced/bioware/vein_threading/mechanic,
/datum/surgery/advanced/bioware/nerve_splicing,
+ /datum/surgery/advanced/bioware/nerve_splicing/mechanic,
/datum/surgery_step/heal/combo/upgraded,
/datum/surgery_step/pacify,
- /datum/surgery_step/revive,
+ /datum/surgery_step/pacify/mechanic,
)
//Pad & Pad Terminal
diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm
index fa07215cf6715b..88dabd337887cb 100644
--- a/code/modules/antagonists/revolution/revolution.dm
+++ b/code/modules/antagonists/revolution/revolution.dm
@@ -15,9 +15,7 @@
/datum/antagonist/rev/can_be_owned(datum/mind/new_owner)
if(new_owner.assigned_role.job_flags & JOB_HEAD_OF_STAFF)
return FALSE
- if(new_owner.unconvertable)
- return FALSE
- if(new_owner.current && HAS_TRAIT(new_owner.current, TRAIT_MINDSHIELD))
+ if(new_owner.current && HAS_MIND_TRAIT(new_owner.current, TRAIT_UNCONVERTABLE))
return FALSE
return ..()
diff --git a/code/modules/antagonists/spy/spy.dm b/code/modules/antagonists/spy/spy.dm
index 8bcc113f089398..2468eb27cad3f5 100644
--- a/code/modules/antagonists/spy/spy.dm
+++ b/code/modules/antagonists/spy/spy.dm
@@ -8,6 +8,8 @@
hijack_speed = 1
ui_name = "AntagInfoSpy"
preview_outfit = /datum/outfit/spy
+ can_assign_self_objectives = TRUE
+ default_custom_objective = "Rob the station blind."
/// Whether an uplink has been created (successfully or at all)
var/uplink_created = FALSE
/// String displayed in the antag panel pointing the spy to where their uplink is.
diff --git a/code/modules/antagonists/spy/spy_bounty.dm b/code/modules/antagonists/spy/spy_bounty.dm
index 28984ce2272bd2..01a1a1baf7b9a0 100644
--- a/code/modules/antagonists/spy/spy_bounty.dm
+++ b/code/modules/antagonists/spy/spy_bounty.dm
@@ -186,7 +186,7 @@
var/datum/market_item/stolen_good/new_item = new(thing, item_price)
- return SSblackmarket.markets[/datum/market/blackmarket].add_item(new_item)
+ return SSmarket.markets[/datum/market/blackmarket].add_item(new_item)
/// Steal an item
/datum/spy_bounty/objective_item
diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm
index 733e22461c7955..bbdfa77eceacdb 100644
--- a/code/modules/antagonists/traitor/datum_traitor.dm
+++ b/code/modules/antagonists/traitor/datum_traitor.dm
@@ -47,7 +47,8 @@
/// The uplink handler that this traitor belongs to.
var/datum/uplink_handler/uplink_handler
- var/uplink_sale_count = 3
+ var/uplink_sales_min = 4
+ var/uplink_sales_max = 6
///the final objective the traitor has to accomplish, be it escaping, hijacking, or just martyrdom.
var/datum/objective/ending_objective
@@ -98,14 +99,14 @@
var/list/uplink_items = list()
for(var/datum/uplink_item/item as anything in SStraitor.uplink_items)
- if(item.item && !item.cant_discount && (item.purchasable_from & uplink_handler.uplink_flag) && item.cost > 1)
+ if(item.item && !item.cant_discount && (item.purchasable_from & uplink_handler.uplink_flag) && item.cost >= TRAITOR_DISCOUNT_MIN_PRICE)
if(!length(item.restricted_roles) && !length(item.restricted_species))
uplink_items += item
continue
if((uplink_handler.assigned_role in item.restricted_roles) || (uplink_handler.assigned_species in item.restricted_species))
uplink_items += item
continue
- uplink_handler.extra_purchasable += create_uplink_sales(uplink_sale_count, /datum/uplink_category/discounts, 1, uplink_items)
+ uplink_handler.extra_purchasable += create_uplink_sales(rand(uplink_sales_min, uplink_sales_max), /datum/uplink_category/discounts, 1, uplink_items)
if(give_objectives)
forge_traitor_objectives()
diff --git a/code/modules/antagonists/traitor/objectives/final_objective/battle_royale.dm b/code/modules/antagonists/traitor/objectives/final_objective/battle_royale.dm
index 9b8f519da959d0..e5208ff8331b9c 100644
--- a/code/modules/antagonists/traitor/objectives/final_objective/battle_royale.dm
+++ b/code/modules/antagonists/traitor/objectives/final_objective/battle_royale.dm
@@ -38,6 +38,6 @@
equipped = TRUE
podspawn(list(
"target" = get_turf(user),
- "style" = STYLE_SYNDICATE,
+ "style" = /datum/pod_style/syndicate,
"spawn" = /obj/item/storage/box/syndie_kit/battle_royale,
))
diff --git a/code/modules/antagonists/traitor/objectives/final_objective/battlecruiser.dm b/code/modules/antagonists/traitor/objectives/final_objective/battlecruiser.dm
index b136a6f695cb31..7da84f6002619f 100644
--- a/code/modules/antagonists/traitor/objectives/final_objective/battlecruiser.dm
+++ b/code/modules/antagonists/traitor/objectives/final_objective/battlecruiser.dm
@@ -44,6 +44,6 @@
emag_card.team = team
podspawn(list(
"target" = get_turf(user),
- "style" = STYLE_SYNDICATE,
+ "style" = /datum/pod_style/syndicate,
"spawn" = emag_card,
))
diff --git a/code/modules/antagonists/traitor/objectives/final_objective/infect_ai.dm b/code/modules/antagonists/traitor/objectives/final_objective/infect_ai.dm
index c8a4037d20af73..d47a2c6aabc594 100644
--- a/code/modules/antagonists/traitor/objectives/final_objective/infect_ai.dm
+++ b/code/modules/antagonists/traitor/objectives/final_objective/infect_ai.dm
@@ -51,6 +51,6 @@
sent_board = TRUE
podspawn(list(
"target" = get_turf(user),
- "style" = STYLE_SYNDICATE,
+ "style" = /datum/pod_style/syndicate,
"spawn" = /obj/item/ai_module/malf,
))
diff --git a/code/modules/antagonists/traitor/objectives/final_objective/objective_dark_matteor.dm b/code/modules/antagonists/traitor/objectives/final_objective/objective_dark_matteor.dm
index 6f68891bcfe7d2..b90fdba73d03a8 100644
--- a/code/modules/antagonists/traitor/objectives/final_objective/objective_dark_matteor.dm
+++ b/code/modules/antagonists/traitor/objectives/final_objective/objective_dark_matteor.dm
@@ -48,7 +48,7 @@
sent_satellites = TRUE
podspawn(list(
"target" = get_turf(user),
- "style" = STYLE_SYNDICATE,
+ "style" = /datum/pod_style/syndicate,
"spawn" = /obj/structure/closet/crate/engineering/smuggled_meteor_shields,
))
diff --git a/code/modules/antagonists/traitor/objectives/final_objective/romerol.dm b/code/modules/antagonists/traitor/objectives/final_objective/romerol.dm
index 0bfa29f3f168cb..09edc4b0c73954 100644
--- a/code/modules/antagonists/traitor/objectives/final_objective/romerol.dm
+++ b/code/modules/antagonists/traitor/objectives/final_objective/romerol.dm
@@ -41,6 +41,6 @@
sent_romerol = TRUE
podspawn(list(
"target" = get_turf(user),
- "style" = STYLE_SYNDICATE,
+ "style" = /datum/pod_style/syndicate,
"spawn" = /obj/item/storage/box/syndie_kit/romerol,
))
diff --git a/code/modules/antagonists/traitor/objectives/final_objective/supermatter_cascade.dm b/code/modules/antagonists/traitor/objectives/final_objective/supermatter_cascade.dm
index 6c7dfaa2f095d8..2e9396c90b070c 100644
--- a/code/modules/antagonists/traitor/objectives/final_objective/supermatter_cascade.dm
+++ b/code/modules/antagonists/traitor/objectives/final_objective/supermatter_cascade.dm
@@ -52,6 +52,6 @@
sent_crystal = TRUE
podspawn(list(
"target" = get_turf(user),
- "style" = STYLE_SYNDICATE,
+ "style" = /datum/pod_style/syndicate,
"spawn" = /obj/item/destabilizing_crystal,
))
diff --git a/code/modules/antagonists/traitor/uplink_handler.dm b/code/modules/antagonists/traitor/uplink_handler.dm
index f78ddb0247892a..2d27f3c4a0eff4 100644
--- a/code/modules/antagonists/traitor/uplink_handler.dm
+++ b/code/modules/antagonists/traitor/uplink_handler.dm
@@ -126,6 +126,21 @@
on_update()
return TRUE
+/datum/uplink_handler/proc/purchase_raw_tc(mob/user, amount, atom/movable/source)
+ if(shop_locked)
+ return FALSE
+ if(telecrystals < amount)
+ return FALSE
+
+ telecrystals -= amount
+ var/tcs = new /obj/item/stack/telecrystal(get_turf(user), amount)
+ user.put_in_hands(tcs)
+
+ log_uplink("[key_name(user)] purchased [amount] raw telecrystals from [source]'s uplink")
+ on_update()
+ return TRUE
+
+
/// Generates objectives for this uplink handler
/datum/uplink_handler/proc/generate_objectives()
var/potential_objectives_left = maximum_potential_objectives - (length(potential_objectives) + length(active_objectives))
diff --git a/code/modules/antagonists/voidwalker/voidwalker.dm b/code/modules/antagonists/voidwalker/voidwalker.dm
index 6ba5ee4490dc08..6222dc0c35fbec 100644
--- a/code/modules/antagonists/voidwalker/voidwalker.dm
+++ b/code/modules/antagonists/voidwalker/voidwalker.dm
@@ -50,9 +50,10 @@
"They must see what you have seen. They must walk where you have walked. Bring them to the void and show them the truth. The dead cannot know what you know.",
"Recover what you have lost. Bring your children into the inky black and return them to your flock.",
)
- if(prob(20))
- explanation_text += "Man I fucking love glass."
explanation_text = pick(explanation_texts)
+
+ if(prob(5))
+ explanation_text = "Man I fucking love glass."
..()
/datum/objective/voidwalker_objective/check_completion()
diff --git a/code/modules/antagonists/voidwalker/voidwalker_kidnap.dm b/code/modules/antagonists/voidwalker/voidwalker_kidnap.dm
index b763d094cb75a6..f0d4c4349cef73 100644
--- a/code/modules/antagonists/voidwalker/voidwalker_kidnap.dm
+++ b/code/modules/antagonists/voidwalker/voidwalker_kidnap.dm
@@ -72,6 +72,8 @@ GLOBAL_LIST_EMPTY(voidwalker_void)
/obj/effect/wisp_mobile/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
. = ..()
+ maybe_loop_us(movement_dir)
+
var/obj/food = locate(food_type) in loc
if(!food)
return
@@ -94,6 +96,23 @@ GLOBAL_LIST_EMPTY(voidwalker_void)
to_chat(gone, span_boldwarning("You feel it would be very bad to get caught again."))
qdel(src)
+/// Loop us around, maybe, if we're going to bump into a wall
+/obj/effect/wisp_mobile/proc/maybe_loop_us(movement_dir)
+ var/turf/check_turf = get_step(get_turf(src), movement_dir)
+ if(!check_turf?.density) //we're not facing a wall, so dont do anything
+ return
+
+ // Loop us to the other side
+ var/reversed_dir = turn(movement_dir, 180)
+ check_turf = get_turf(src)
+
+ while(!check_turf.density)
+ check_turf = get_step(check_turf, reversed_dir)
+
+ // We found the wall on the opposite side, so take two steps back (one to get off the wall, another to not be wall adjacent)
+ check_turf = get_step(get_step(check_turf, movement_dir), movement_dir)
+ forceMove(check_turf)
+
/// we only exist to be eaten by wisps for food 😔👊
/obj/effect/wisp_food
name = "wisp"
diff --git a/code/modules/antagonists/voidwalker/voidwalker_loot.dm b/code/modules/antagonists/voidwalker/voidwalker_loot.dm
index 8d3420d0a5278d..73ed9c7cd2207f 100644
--- a/code/modules/antagonists/voidwalker/voidwalker_loot.dm
+++ b/code/modules/antagonists/voidwalker/voidwalker_loot.dm
@@ -6,6 +6,9 @@
icon = 'icons/obj/weapons/voidwalker_items.dmi'
icon_state = "cosmic_skull_charged"
+ light_on = TRUE
+ light_color = "#CC00CC"
+ light_range = 3
/// Icon state for when drained
var/drained_icon_state = "cosmic_skull_drained"
/// How many uses does it have left?
@@ -37,3 +40,4 @@
uses--
if(uses <= 0 )
icon_state = drained_icon_state
+ light_on = FALSE
diff --git a/code/modules/antagonists/voidwalker/voidwalker_status_effects.dm b/code/modules/antagonists/voidwalker/voidwalker_status_effects.dm
index 6dc9cdc35ca7bc..7934e757077af0 100644
--- a/code/modules/antagonists/voidwalker/voidwalker_status_effects.dm
+++ b/code/modules/antagonists/voidwalker/voidwalker_status_effects.dm
@@ -21,11 +21,16 @@
/datum/status_effect/planet_allergy
id = "planet_allergy"
duration = INFINITE
- alert_type = /atom/movable/screen/alert/veryhighgravity
+ alert_type = /atom/movable/screen/alert/status_effect/veryhighgravity
/datum/status_effect/planet_allergy/tick()
owner.adjustBruteLoss(1)
+/atom/movable/screen/alert/status_effect/veryhighgravity
+ name = "Crushing Gravity"
+ desc = "You're getting crushed by high gravity, picking up items and movement will be slowed. You'll also accumulate brute damage!"
+ icon_state = "paralysis"
+
/datum/status_effect/void_eatered
duration = 10 SECONDS
remove_on_fullheal = TRUE
diff --git a/code/modules/antagonists/voidwalker/voidwalker_void_eater.dm b/code/modules/antagonists/voidwalker/voidwalker_void_eater.dm
index db638c2b948186..9df3eabab3d218 100644
--- a/code/modules/antagonists/voidwalker/voidwalker_void_eater.dm
+++ b/code/modules/antagonists/voidwalker/voidwalker_void_eater.dm
@@ -31,7 +31,7 @@
AddComponent(/datum/component/temporary_glass_shatterer)
-/obj/item/void_eater/pickup(mob/user)
+/obj/item/void_eater/equipped(mob/user)
. = ..()
RegisterSignal(user, COMSIG_VOIDWALKER_SUCCESFUL_KIDNAP, PROC_REF(refresh))
diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm
index 6cebe8fa1e9746..0230274b8e88b0 100644
--- a/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm
+++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm
@@ -42,9 +42,9 @@
/datum/spellbook_entry/perks/dejavu/proc/give_dejavu(mob/living/carbon/human/wizard, area/new_area)
SIGNAL_HANDLER
- if(new_area == GLOB.areas_by_type[/area/centcom/wizard_station])
+ if(istype(new_area, /area/centcom))
return
- wizard.AddComponent(/datum/component/dejavu/timeline, -1, 60 SECONDS)
+ wizard.AddComponent(/datum/component/dejavu/wizard, 1, 60 SECONDS, TRUE)
UnregisterSignal(wizard, COMSIG_ENTER_AREA)
/datum/spellbook_entry/perks/spell_lottery
diff --git a/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm b/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm
index 79364a80a198a5..15900a6ac0b0a7 100644
--- a/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm
+++ b/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm
@@ -19,7 +19,7 @@
pixel_y = 16
pixel_z = -48
anchored = TRUE
- interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND
+ interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_ATTACK_PAW
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
layer = SIGIL_LAYER
/// How many prior grand rituals have been completed?
diff --git a/code/modules/antagonists/wizard/grand_ritual/grand_side_effect.dm b/code/modules/antagonists/wizard/grand_ritual/grand_side_effect.dm
index ffc2ea5d590af4..a760115a61b9ea 100644
--- a/code/modules/antagonists/wizard/grand_ritual/grand_side_effect.dm
+++ b/code/modules/antagonists/wizard/grand_ritual/grand_side_effect.dm
@@ -335,7 +335,7 @@
/obj/effect/abstract/local_food_rain/proc/drop_food(turf/landing_zone)
podspawn(list(
"target" = landing_zone,
- "style" = STYLE_SEETHROUGH,
+ "style" = /datum/pod_style/seethrough,
"spawn" = get_random_food(),
"delays" = list(POD_TRANSIT = 0, POD_FALLING = (3 SECONDS), POD_OPENING = 0, POD_LEAVING = 0),
"effectStealth" = TRUE,
diff --git a/code/modules/art/paintings.dm b/code/modules/art/paintings.dm
index 8affc71e568f3c..567ac383d94409 100644
--- a/code/modules/art/paintings.dm
+++ b/code/modules/art/paintings.dm
@@ -545,6 +545,8 @@
/obj/item/canvas/twentythree_twentythree,
/obj/item/canvas/twentyfour_twentyfour,
)
+ /// the type of wallframe it 'disassembles' into
+ var/wallframe_type = /obj/item/wallframe/painting
/obj/structure/sign/painting/Initialize(mapload, dir, building)
. = ..()
@@ -565,6 +567,16 @@
else
return ..()
+/obj/structure/sign/painting/knock_down(mob/living/user)
+ var/turf/drop_turf
+ if(user)
+ drop_turf = get_turf(user)
+ else
+ drop_turf = drop_location()
+ current_canvas?.forceMove(drop_turf)
+ var/obj/item/wallframe/frame = new wallframe_type(drop_turf)
+ frame.update_integrity(get_integrity()) //Transfer how damaged it is.
+
/obj/structure/sign/painting/examine(mob/user)
. = ..()
if(persistence_id)
@@ -768,6 +780,7 @@
/obj/item/canvas/thirtysix_twentyfour,
/obj/item/canvas/fortyfive_twentyseven,
)
+ wallframe_type = /obj/item/wallframe/painting/large
/obj/structure/sign/painting/large/Initialize(mapload)
. = ..()
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index 8dd4573fcfde1a..7c23d1dc4cbdbc 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -107,28 +107,14 @@
var/turf/last_turf = final_turfs[length(final_turfs)]
buffer_turf = get_step(last_turf, dir)
- var/beam_target_x = pixel_x
- var/beam_target_y = pixel_y
- // The beam by default will go to middle of turf (because items are in the middle of turfs)
- // So we need to offset it
- if(dir & NORTH)
- beam_target_y += 16
- else if(dir & SOUTH)
- beam_target_y -= 16
- if(dir & WEST)
- beam_target_x -= 16
- else if(dir & EAST)
- beam_target_x += 16
-
active_beam = start_loc.Beam(
BeamTarget = last_turf,
beam_type = /obj/effect/ebeam/reacting/infrared,
icon = 'icons/effects/beam.dmi',
- icon_state = "1-full",
- beam_color = COLOR_RED,
+ icon_state = "infrared",
emissive = TRUE,
- override_target_pixel_x = beam_target_x,
- override_target_pixel_y = beam_target_y,
+ override_target_pixel_x = pixel_x,
+ override_target_pixel_y = pixel_y,
)
RegisterSignal(active_beam, COMSIG_BEAM_ENTERED, PROC_REF(beam_entered))
RegisterSignal(active_beam, COMSIG_BEAM_TURFS_CHANGED, PROC_REF(beam_turfs_changed))
diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm
index 8366bb0f2b3822..0d05d44320d963 100644
--- a/code/modules/assembly/timer.dm
+++ b/code/modules/assembly/timer.dm
@@ -67,6 +67,9 @@
if(!timing)
return
time -= seconds_per_tick
+ if (time == 9 || time == 19 || time == 29)
+ update_appearance()
+
if(time <= 0)
timing = FALSE
timer_end()
@@ -79,9 +82,14 @@
/obj/item/assembly/timer/update_overlays()
. = ..()
attached_overlays = list()
- if(timing)
- . += "timer_timing"
- attached_overlays += "timer_timing"
+ if(!timing)
+ return
+
+ attached_overlays += "timer_timing"
+ for (var/i in 1 to clamp(ceil(time / 10), 1, 3))
+ var/mutable_appearance/timer_light = mutable_appearance(icon, "timer_light", layer, src)
+ timer_light.pixel_x = (i - 1) * 2
+ . += timer_light
/obj/item/assembly/timer/ui_status(mob/user, datum/ui_state/state)
if(is_secured(user))
diff --git a/code/modules/asset_cache/assets/supplypods.dm b/code/modules/asset_cache/assets/supplypods.dm
index fd4c961f103e62..3807c080f6200e 100644
--- a/code/modules/asset_cache/assets/supplypods.dm
+++ b/code/modules/asset_cache/assets/supplypods.dm
@@ -2,26 +2,26 @@
name = "supplypods"
/datum/asset/spritesheet/supplypods/create_spritesheets()
- for (var/style in 1 to length(GLOB.podstyles))
- if (style == STYLE_SEETHROUGH)
- Insert("pod_asset[style]", icon('icons/obj/supplypods.dmi' , "seethrough-icon"))
+ for (var/datum/pod_style/style as anything in typesof(/datum/pod_style))
+ if (ispath(style, /datum/pod_style/seethrough))
+ Insert("pod_asset[style::id]", icon('icons/obj/supplypods.dmi' , "seethrough-icon"))
continue
- var/base = GLOB.podstyles[style][POD_BASE]
+ var/base = style::icon_state
if (!base)
- Insert("pod_asset[style]", icon('icons/obj/supplypods.dmi', "invisible-icon"))
+ Insert("pod_asset[style::id]", icon('icons/obj/supplypods.dmi', "invisible-icon"))
continue
var/icon/podIcon = icon('icons/obj/supplypods.dmi', base)
- var/door = GLOB.podstyles[style][POD_DOOR]
+ var/door = style::has_door
if (door)
door = "[base]_door"
podIcon.Blend(icon('icons/obj/supplypods.dmi', door), ICON_OVERLAY)
- var/shape = GLOB.podstyles[style][POD_SHAPE]
- if (shape == POD_SHAPE_NORML)
- var/decal = GLOB.podstyles[style][POD_DECAL]
+ var/shape = style::shape
+ if (shape == POD_SHAPE_NORMAL)
+ var/decal = style::decal_icon
if (decal)
podIcon.Blend(icon('icons/obj/supplypods.dmi', decal), ICON_OVERLAY)
- var/glow = GLOB.podstyles[style][POD_GLOW]
+ var/glow = style::glow_color
if (glow)
glow = "pod_glow_[glow]"
podIcon.Blend(icon('icons/obj/supplypods.dmi', glow), ICON_OVERLAY)
- Insert("pod_asset[style]", podIcon)
+ Insert("pod_asset[style::id]", podIcon)
diff --git a/code/modules/asset_cache/assets/uplink.dm b/code/modules/asset_cache/assets/uplink.dm
index e85ee1b35b5c13..35a907a234dfa3 100644
--- a/code/modules/asset_cache/assets/uplink.dm
+++ b/code/modules/asset_cache/assets/uplink.dm
@@ -18,10 +18,13 @@
for(var/datum/uplink_item/item_path as anything in subtypesof(/datum/uplink_item))
var/datum/uplink_item/item = new item_path()
+ var/atom/actual_item = item.item
if(item.item) {
items += list(list(
"id" = item_path,
"name" = item.name,
+ "icon" = actual_item.icon,
+ "icon_state" = actual_item.icon_state,
"cost" = item.cost,
"desc" = item.desc,
"category" = item.category ? initial(item.category.name) : null,
diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
index c35bbf34227cbd..7a06572824ae63 100644
--- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
+++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
@@ -271,6 +271,12 @@
#endif
for(var/turf/open/enemy_tile as anything in adjacent_turfs)
+ #ifdef UNIT_TESTS
+ if(!istype(enemy_tile))
+ stack_trace("closed turf inside of adjacent turfs")
+ continue
+ #endif
+
// This var is only rarely set, exists so turfs can request to share at the end of our sharing
// We need this so we can assume share is communative, which we need to do to avoid a hellish amount of garbage_collect()s
if(enemy_tile.run_later)
diff --git a/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm b/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm
index 0cb82c5c77c7c3..6f1e0c6fcd9cbc 100644
--- a/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm
+++ b/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm
@@ -8,7 +8,7 @@
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.05
active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.02
power_channel = AREA_USAGE_ENVIRON
- req_access = list(ACCESS_ATMOSPHERICS)
+ req_access = list(ACCESS_ENGINEERING)
max_integrity = 250
integrity_failure = 0.33
armor_type = /datum/armor/machinery_airalarm
diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm
index 8674e6331e4acd..12e6c684079e65 100644
--- a/code/modules/atmospherics/machinery/atmosmachinery.dm
+++ b/code/modules/atmospherics/machinery/atmosmachinery.dm
@@ -112,7 +112,7 @@
turf_loc.add_blueprints_preround(src)
if(hide)
- RegisterSignal(src, COMSIG_OBJ_HIDE, PROC_REF(on_hide))
+ setup_hiding()
SSspatial_grid.add_grid_awareness(src, SPATIAL_GRID_CONTENTS_TYPE_ATMOS)
SSspatial_grid.add_grid_membership(src, turf_loc, SPATIAL_GRID_CONTENTS_TYPE_ATMOS)
@@ -133,9 +133,18 @@
return ..()
/**
- * Handler for `COMSIG_OBJ_HIDE`, connects only if `hide` is set to `TRUE`. Calls `update_cap_visuals` on pipe and its connected nodes
+ * Sets up our pipe hiding logic, consolidated in one place so subtypes may override it.
+ * This lets subtypes implement their own hiding logic without needing to worry about conflicts with the parent hiding logic.
*/
-/obj/machinery/atmospherics/proc/on_hide(datum/source, underfloor_accessibility)
+/obj/machinery/atmospherics/proc/setup_hiding()
+ // Register pipe cap updating when hidden/unhidden
+ RegisterSignal(src, COMSIG_OBJ_HIDE, PROC_REF(on_hide))
+
+/**
+ * Signal handler. Updates both our pipe cap visuals and those of adjacent nodes.
+ * We update adjacent nodes as their pipe caps are based partially on our state, so they need updating as well.
+ */
+/obj/machinery/atmospherics/proc/on_hide(datum/source)
SHOULD_CALL_PARENT(TRUE)
SIGNAL_HANDLER
@@ -651,7 +660,8 @@
if(HAS_TRAIT(node, TRAIT_UNDERFLOOR))
continue
- if(isplatingturf(get_turf(node)))
+ var/turf/node_turf = get_turf(node)
+ if(isplatingturf(node_turf) || iscatwalkturf(node_turf))
continue
var/connected_dir = get_dir(src, node)
diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
index 25217de538ce17..da6c75d699d087 100644
--- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
+++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
@@ -6,7 +6,7 @@
desc = "Very useful for filtering gasses."
can_unwrench = TRUE
- construction_type = /obj/item/pipe/trinary/flippable
+ construction_type = /obj/item/pipe/trinary/flippable/filter
pipe_state = "filter"
///Rate of transfer of the gases to the outputs
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
index 02f0d20354496b..8a165830cec07b 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
@@ -5,7 +5,7 @@
name = "air vent"
desc = "Has a valve and pump attached to it."
-
+ construction_type = /obj/item/pipe/directional/vent
use_power = IDLE_POWER_USE
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.15
can_unwrench = TRUE
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
index 560c9d717436f1..4da90396052667 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
@@ -3,6 +3,7 @@
name = "air scrubber"
desc = "Has a valve and pump attached to it."
+ construction_type = /obj/item/pipe/directional/scrubber
use_power = IDLE_POWER_USE
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.1
active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.15
diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm
index 37cb21ee8cee4a..2200d10fda5062 100644
--- a/code/modules/atmospherics/machinery/datum_pipeline.dm
+++ b/code/modules/atmospherics/machinery/datum_pipeline.dm
@@ -375,7 +375,7 @@
/obj/effect/abstract/gas_visual/Initialize(mapload)
. = ..()
- color_filter = filter(type="color", color=matrix())
+ color_filter = filter(type="color", color="white")
filters += color_filter
color_filter = filters[filters.len]
if(current_color)
diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm
index 230edc9a897f00..ebc31e847b85a2 100644
--- a/code/modules/atmospherics/machinery/pipes/pipes.dm
+++ b/code/modules/atmospherics/machinery/pipes/pipes.dm
@@ -27,12 +27,11 @@
volume = 35 * device_type
. = ..()
-///I have no idea why there's a new and at this point I'm too afraid to ask
-/obj/machinery/atmospherics/pipe/Initialize(mapload)
- . = ..()
+/obj/machinery/atmospherics/pipe/setup_hiding()
+ AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) //if changing this, change the subtypes RemoveElements too, because thats how bespoke works
- if(hide)
- AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) //if changing this, change the subtypes RemoveElements too, because thats how bespoke works
+ // Registering on `COMSIG_OBJ_HIDE` would cause order of operations issues with undertile, so we register to run when undertile updates instead
+ RegisterSignal(src, COMSIG_UNDERTILE_UPDATED, PROC_REF(on_hide))
/obj/machinery/atmospherics/pipe/on_deconstruction(disassembled)
//we delete the parent here so it initializes air_temporary for us. See /datum/pipeline/Destroy() which calls temporarily_store_air()
diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
index 9729c0871451a0..210eb9b0d9e280 100644
--- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
+++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
@@ -51,6 +51,10 @@
AddElement(/datum/element/elevation, pixel_shift = 8)
register_context()
+/obj/machinery/portable_atmospherics/on_construction(mob/user)
+ . = ..()
+ set_anchored(FALSE)
+
/obj/machinery/portable_atmospherics/on_deconstruction(disassembled)
if(nob_crystal_inserted)
new /obj/item/hypernoblium_crystal(src)
diff --git a/code/modules/awaymissions/mission_code/Beach.dm b/code/modules/awaymissions/mission_code/Beach.dm
new file mode 100644
index 00000000000000..8e05cfe4a5eb1b
--- /dev/null
+++ b/code/modules/awaymissions/mission_code/Beach.dm
@@ -0,0 +1,19 @@
+/area/awaymission/beach
+ name = "Beach"
+ icon_state = "away"
+ static_lighting = FALSE
+ base_lighting_alpha = 255
+ base_lighting_color = "#FFFFCC"
+ requires_power = FALSE
+ has_gravity = STANDARD_GRAVITY
+ ambientsounds = list('sound/ambience/shore.ogg', 'sound/ambience/seag1.ogg','sound/ambience/seag2.ogg','sound/ambience/seag2.ogg','sound/ambience/ambiodd.ogg','sound/ambience/ambinice.ogg')
+
+/obj/item/paper/fluff/old_pirate_note
+ name = "rum-stained letter"
+ icon_state = "scrap_mud"
+ desc = "An unsent letter from a terminally drunk pirate."
+ default_raw_text = {"Dear,
+ I'm sorry I won't sail back home soon,
+ son of a biscuit eater walked the plank with me coffer (or treasure chest as landlubbers call'em),
+ so I got me fishing rod, bottles, waiting to fish the booty back.
+ Luv you hun, I hope this letter find you we-"}
diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm
index 0fdc5093511f2e..b72a6b59dde369 100644
--- a/code/modules/awaymissions/zlevel.dm
+++ b/code/modules/awaymissions/zlevel.dm
@@ -32,15 +32,51 @@ GLOBAL_LIST_INIT(potentialConfigRandomZlevels, generate_map_list_from_directory(
current = D
if(!current)
current = new
+ current.name = name
current.id = id
if(delay)
- current.wait = CONFIG_GET(number/gateway_delay)
+ var/list/waits_by_id = CONFIG_GET(keyed_list/gateway_delays_by_id)
+ var/wait_to_use = !isnull(waits_by_id[id]) ? waits_by_id[id] : CONFIG_GET(number/gateway_delay)
+ current.wait = wait_to_use
GLOB.gateway_destinations += current
current.target_turfs += get_turf(src)
+ return INITIALIZE_HINT_QDEL
/obj/effect/landmark/awaystart/nodelay
delay = FALSE
+/obj/effect/landmark/awaystart/beach
+ name = "beach away spawn"
+ id = AWAYSTART_BEACH
+
+/obj/effect/landmark/awaystart/museum
+ name = "buseum away spawn"
+ id = AWAYSTART_MUSEUM
+
+/obj/effect/landmark/awaystart/research
+ name = "research outpost away spawn"
+ id = AWAYSTART_RESEARCH
+
+/obj/effect/landmark/awaystart/caves
+ name = "caves away spawn"
+ id = AWAYSTART_CAVES
+
+/obj/effect/landmark/awaystart/moonoutpost
+ name = "Moon Outpost 19 away spawn"
+ id = AWAYSTART_MOONOUTPOST
+
+/obj/effect/landmark/awaystart/snowcabin
+ name = "snow cabin away spawn"
+ id = AWAYSTART_SNOWCABIN
+
+/obj/effect/landmark/awaystart/snowdin
+ name = "Snowdin away spawn"
+ id = AWAYSTART_SNOWDIN
+
+/obj/effect/landmark/awaystart/underground
+ name = "Underground Outpost 45 away spawn"
+ id = AWAYSTART_UNDERGROUND
+
/proc/generateMapList(filename)
. = list()
filename = "[global.config.directory]/[SANITIZE_FILENAME(filename)]"
diff --git a/code/modules/bitrunning/components/avatar_connection.dm b/code/modules/bitrunning/components/avatar_connection.dm
index 4274893e998927..6254427af39d94 100644
--- a/code/modules/bitrunning/components/avatar_connection.dm
+++ b/code/modules/bitrunning/components/avatar_connection.dm
@@ -20,7 +20,7 @@
help_text,
)
- if(!isliving(parent) || !isliving(old_body) || !server.is_operational || !pod.is_operational)
+ if(!isliving(parent) || !isliving(old_body) || !old_mind || !server.is_operational || !pod.is_operational)
return COMPONENT_INCOMPATIBLE
var/mob/living/avatar = parent
@@ -66,6 +66,9 @@
if(alias && avatar.real_name != alias)
avatar.fully_replace_character_name(avatar.real_name, alias)
+ for(var/skill_type in old_mind.known_skills)
+ avatar.mind.set_experience(skill_type, old_mind.get_skill_exp(skill_type), silent = TRUE)
+
avatar.playsound_local(avatar, 'sound/magic/blink.ogg', 25, TRUE)
avatar.set_static_vision(2 SECONDS)
avatar.set_temp_blindness(1 SECONDS) // I'm in
@@ -281,6 +284,10 @@
if(isnull(old_mind) || isnull(old_body))
return
+ for(var/skill_type in avatar.mind.known_skills)
+ old_mind.set_experience(skill_type, avatar.mind.get_skill_exp(skill_type), silent = TRUE)
+ avatar.mind.set_experience(skill_type, 0, silent = TRUE)
+
ghost.mind = old_mind
if(old_body.stat != DEAD)
old_mind.transfer_to(old_body, force_key_move = TRUE)
diff --git a/code/modules/bitrunning/turfs.dm b/code/modules/bitrunning/turfs.dm
index 93dce1789c4f62..6ceb31b0e3130f 100644
--- a/code/modules/bitrunning/turfs.dm
+++ b/code/modules/bitrunning/turfs.dm
@@ -1,4 +1,4 @@
-/turf/open/floor/bitrunning_transport
+/turf/open/indestructible/bitrunning_transport
name = "circuit floor"
icon = 'icons/turf/floors.dmi'
desc = "Looks complex. You can see the circuits running through the floor."
diff --git a/code/modules/bitrunning/virtual_domain/domains/island_brawl.dm b/code/modules/bitrunning/virtual_domain/domains/island_brawl.dm
index b745a4746aa24f..84eb53e026a29d 100644
--- a/code/modules/bitrunning/virtual_domain/domains/island_brawl.dm
+++ b/code/modules/bitrunning/virtual_domain/domains/island_brawl.dm
@@ -21,9 +21,17 @@
for(var/obj/effect/mob_spawn/ghost_role/human/virtual_domain/islander/spawner in created_atoms)
custom_spawns += spawner
+ RegisterSignal(spawner, COMSIG_QDELETING, PROC_REF(on_spawner_qdeleted))
RegisterSignals(spawner, list(COMSIG_GHOSTROLE_SPAWNED, COMSIG_BITRUNNER_SPAWNED), PROC_REF(on_spawn))
+/datum/lazy_template/virtual_domain/island_brawl/proc/on_spawner_qdeleted(obj/effect/mob_spawn/ghost_role/human/virtual_domain/islander/source)
+ SIGNAL_HANDLER
+
+ custom_spawns -= source
+ UnregisterSignal(source, COMSIG_QDELETING)
+
+
/// Someone has spawned in, so we check for their death
/datum/lazy_template/virtual_domain/island_brawl/proc/on_spawn(datum/source, mob/living/spawned_mob)
SIGNAL_HANDLER
diff --git a/code/modules/capture_the_flag/medieval_sim/medisim_classes.dm b/code/modules/capture_the_flag/medieval_sim/medisim_classes.dm
index 3c4a55748c4c69..09ed5b40b1f20f 100644
--- a/code/modules/capture_the_flag/medieval_sim/medisim_classes.dm
+++ b/code/modules/capture_the_flag/medieval_sim/medisim_classes.dm
@@ -26,7 +26,7 @@
name = "Redfield Castle Archer"
icon_state = "medisim_archer"
- belt = /obj/item/storage/bag/quiver
+ belt = /obj/item/storage/bag/quiver/full
suit = /obj/item/clothing/suit/armor/vest/cuirass
l_hand = /obj/item/gun/ballistic/bow
diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm
index 5d5bc3f29f57d8..dd779c796ce8f1 100644
--- a/code/modules/cargo/centcom_podlauncher.dm
+++ b/code/modules/cargo/centcom_podlauncher.dm
@@ -67,10 +67,19 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a
var/atom/movable/screen/background/cam_background
var/tabIndex = 1
var/renderLighting = FALSE
+ var/static/list/pod_style_info
+ var/static/list/pod_style_lookup
/datum/centcom_podlauncher/New(user) //user can either be a client or a mob
if (user) //Prevents runtimes on datums being made without clients
setup(user)
+ if (!isnull(pod_style_info))
+ return
+ pod_style_info = list()
+ pod_style_lookup = list()
+ for (var/datum/pod_style/style as anything in typesof(/datum/pod_style))
+ pod_style_info += list(list("id" = style::id, "title" = style::ui_name))
+ pod_style_lookup[style::id] = style
/datum/centcom_podlauncher/proc/setup(user) //H can either be a client or a mob
if (istype(user,/client))
@@ -134,6 +143,7 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a
var/list/data = list()
data["mapRef"] = map_name
data["defaultSoundVolume"] = initial(temp_pod.soundVolume) //default volume for pods
+ data["podStyles"] = pod_style_info
return data
/datum/centcom_podlauncher/ui_data(mob/user) //Sends info about the pod to the UI.
@@ -152,7 +162,7 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a
data["delays"] = temp_pod.delays
data["rev_delays"] = temp_pod.reverse_delays
data["custom_rev_delay"] = temp_pod.custom_rev_delay
- data["styleChoice"] = temp_pod.style //Style is a variable that keeps track of what the pod is supposed to look like. It acts as an index to the GLOB.podstyles list in cargo.dm defines to get the proper icon/name/desc for the pod.
+ data["styleChoice"] = temp_pod.style::id //Style is a variable that keeps track of what the pod is supposed to look like.
data["effectShrapnel"] = temp_pod.effectShrapnel //If true, creates a cloud of shrapnel of a decided type and magnitude on landing
data["shrapnelType"] = "[temp_pod.shrapnel_type]" //Path2String
data["shrapnelMagnitude"] = temp_pod.shrapnel_magnitude
@@ -333,10 +343,10 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a
temp_pod.adminNamed = FALSE
temp_pod.setStyle(temp_pod.style) //This resets the name of the pod based on its current style (see supplypod/setStyle() proc)
return
- var/nameInput= tgui_input_text(usr, "Enter a custom name", "Custom name", GLOB.podstyles[temp_pod.style][POD_NAME], MAX_NAME_LEN) //Gather input for name and desc
+ var/nameInput= tgui_input_text(usr, "Enter a custom name", "Custom name", temp_pod.style::name, MAX_NAME_LEN) //Gather input for name and desc
if (isnull(nameInput))
return
- var/descInput = tgui_input_text(usr, "Enter a custom desc", "Custom description", GLOB.podstyles[temp_pod.style][POD_DESC]) //The GLOB.podstyles is used to get the name, desc, or icon state based on the pod's style
+ var/descInput = tgui_input_text(usr, "Enter a custom desc", "Custom description", temp_pod.style::desc)
if (isnull(descInput))
return
temp_pod.name = nameInput
@@ -504,7 +514,6 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a
temp_pod.soundVolume = soundInput
. = TRUE
////////////////////////////STYLE CHANGES//////////////////
- //Style is a value that is used to keep track of what the pod is supposed to look like. It can be used with the GLOB.podstyles list (in cargo.dm defines)
//as a way to get the proper icon state, name, and description of the pod.
if("tabSwitch")
tabIndex = params["tabIndex"]
@@ -519,7 +528,7 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a
. = TRUE
if("setStyle")
var/chosenStyle = params["style"]
- temp_pod.setStyle(chosenStyle+1)
+ temp_pod.setStyle(pod_style_lookup[chosenStyle])
. = TRUE
if("refresh") //Refresh the Pod bay. User should press this if they spawn something new in the centcom bay. Automatically called whenever the user launches a pod
refreshBay()
@@ -654,11 +663,6 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a
preLaunch() //Fill acceptable turfs from orderedArea, then fill launchList from acceptableTurfs (see proc for more info)
refreshView()
-/area/centcom/central_command_areas/supplypod/pod_storage/Initialize(mapload) //temp_pod holding area
- . = ..()
- var/obj/imgbound = locate() in locate(200,SUPPLYPOD_X_OFFSET*-4.5, 1)
- call(GLOB.podlauncher, "RegisterSignal")(imgbound, "ct[GLOB.podstyles[14][9]]", "[GLOB.podstyles[14][10]]dlauncher")
-
/datum/centcom_podlauncher/proc/createOrderedArea(area/area_to_order) //This assumes the area passed in is a continuous square
if (isnull(area_to_order)) //If theres no supplypod bay mapped into centcom, throw an error
to_chat(holder.mob, "No /area/centcom/central_command_areas/supplypod/loading/one (or /two or /three or /four) in the world! You can make one yourself (then refresh) for now, but yell at a mapper to fix this, today!")
@@ -820,7 +824,7 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a
temp_pod.delays = dataToLoad["delays"]
temp_pod.reverse_delays = dataToLoad["rev_delays"]
temp_pod.custom_rev_delay = dataToLoad["custom_rev_delay"]
- temp_pod.setStyle(dataToLoad["styleChoice"]) //Style is a variable that keeps track of what the pod is supposed to look like. It acts as an index to the GLOB.podstyles list in cargo.dm defines to get the proper icon/name/desc for the pod.
+ temp_pod.setStyle(dataToLoad["styleChoice"]) //Style is a variable that keeps track of what the pod is supposed to look like.
temp_pod.effectShrapnel = dataToLoad["effectShrapnel"] //If true, creates a cloud of shrapnel of a decided type and magnitude on landing
temp_pod.shrapnel_type = text2path(dataToLoad["shrapnelType"])
temp_pod.shrapnel_magnitude = dataToLoad["shrapnelMagnitude"]
@@ -852,14 +856,6 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a
refreshView()
GLOBAL_DATUM_INIT(podlauncher, /datum/centcom_podlauncher, new)
-//Proc for admins to enable others to use podlauncher after roundend
-/datum/centcom_podlauncher/proc/give_podlauncher(mob/living/user, override)
- if (SSticker.current_state < GAME_STATE_FINISHED)
- return
- if (!istype(user))
- user = override
- if (user)
- setup(user)//setup the datum
//Set the dropoff location and indicator to either a specific turf or somewhere in an area
/datum/centcom_podlauncher/proc/setDropoff(target)
diff --git a/code/modules/cargo/exports/fish.dm b/code/modules/cargo/exports/fish.dm
index c68eeaaa70063f..9c34fd3afcaebc 100644
--- a/code/modules/cargo/exports/fish.dm
+++ b/code/modules/cargo/exports/fish.dm
@@ -1,10 +1,9 @@
/datum/export/fish
- cost = 50
+ cost = 30
unit_name = "fish"
export_types = list(/obj/item/fish)
/datum/export/fish/get_cost(obj/item/fish/fish, apply_elastic)
var/elastic_cost = ..()
var/elastic_percent = elastic_cost / init_cost
- var/size_weight_exponentation = (fish.size * fish.weight * 0.01)^0.85
- return round(elastic_cost + size_weight_exponentation * elastic_percent)
+ return fish.get_export_price(elastic_cost, elastic_percent)
diff --git a/code/modules/cargo/goodies.dm b/code/modules/cargo/goodies.dm
index e09c3e2bc958d8..aa42b5cacde443 100644
--- a/code/modules/cargo/goodies.dm
+++ b/code/modules/cargo/goodies.dm
@@ -221,7 +221,7 @@
/datum/supply_pack/goody/fishing_toolbox
name = "Fishing Toolbox"
- desc = "Complete toolbox set for your fishing adventure. Advanced hooks and lines sold separetely."
+ desc = "Complete toolbox set for your fishing adventure. Contains a valuable tip. Advanced hooks and lines sold separetely."
cost = PAYCHECK_CREW * 2
contains = list(/obj/item/storage/toolbox/fishing)
@@ -311,7 +311,7 @@
/datum/supply_pack/goody/climbing_hook
name = "Climbing Hook Single-Pack"
- desc = "A less cheap imported climbing hook. Absolutely no use outside of planetary stations."
+ desc = "A less cheap imported climbing hook. Absolutely no use outside of multi-floor stations."
cost = PAYCHECK_CREW * 5
contains = list(/obj/item/climbing_hook)
@@ -321,3 +321,9 @@
cost = PAYCHECK_COMMAND * 18
access_view = ACCESS_WEAPONS
contains = list(/obj/item/gun/ballistic/shotgun/doublebarrel)
+
+/datum/supply_pack/goody/experimental_medication
+ name = "Experimental Medication Single-Pack"
+ desc = "A single bottle of Interdyne brand experimental medication, used for treating people suffering from hereditary manifold disease."
+ cost = PAYCHECK_CREW * 6.5
+ contains = list(/obj/item/storage/pill_bottle/sansufentanyl)
diff --git a/code/modules/cargo/markets/_market.dm b/code/modules/cargo/markets/_market.dm
index 0a93469411cdb4..4696d3007a7ae6 100644
--- a/code/modules/cargo/markets/_market.dm
+++ b/code/modules/cargo/markets/_market.dm
@@ -6,7 +6,7 @@
var/list/shipping
// Automatic vars, do not touch these.
- /// Items available from this market, populated by SSblackmarket on initialization. Automatically assigned, so don't manually adjust.
+ /// Items available from this market, populated by SSmarket on initialization. Automatically assigned, so don't manually adjust.
var/list/available_items = list()
/// Item categories available from this market, only items which are in these categories can be gotten from this market. Automatically assigned, so don't manually adjust.
var/list/categories = list()
@@ -73,6 +73,20 @@
return FALSE
+/**
+ * A proc that restocks only the EXISTING items of this market.
+ * If you want to selectively restock markets, call SSmarket.restock(market_or_list_of_markets) instead.
+ */
+/datum/market/proc/restock(list/existing_items)
+ for(var/category in available_items)
+ var/category_list = available_items[category]
+ for(var/identifier in category_list)
+ var/datum/market_item/item = category_list[identifier]
+ existing_items |= item.type
+ if(!item.restockable || item.stock >= item.stock_max || !prob(item.availability_prob))
+ continue
+ item.stock += rand(1, item.stock_max - item.stock)
+
/datum/market/blackmarket
name = "Black Market"
shipping = list(
diff --git a/code/modules/cargo/markets/market_item.dm b/code/modules/cargo/markets/market_item.dm
index 5e3ce4efb6c079..faa6c45d795c41 100644
--- a/code/modules/cargo/markets/market_item.dm
+++ b/code/modules/cargo/markets/market_item.dm
@@ -5,7 +5,7 @@
var/desc
/// The category this item belongs to, should be already declared in the market that this item is accessible in.
var/category
- /// "/datum/market"s that this item should be in, used by SSblackmarket on init.
+ /// "/datum/market"s that this item should be in, used by SSmarket on init.
var/list/markets = list(/datum/market/blackmarket)
/// Price for the item, if not set creates a price according to the *_min and *_max vars.
@@ -27,15 +27,21 @@
var/stock_min = 1
/// Maximum amount that there should be of this item in the market if generated randomly.
var/stock_max = 0
- /// Probability for this item to be available. Used by SSblackmarket on init.
+ /// Probability for this item to be available. Used by SSmarket on init.
var/availability_prob
+ /// If set, this icon will be shown in the UI.
+ var/html_icon
+
///The identifier for the market item, generated on runtime and used to access them in the market categories.
var/identifier
///If set, these will override the shipment methods set by the market
var/list/shipping_override
+ /// Can this item be restocked
+ var/restockable = TRUE
+
/datum/market_item/New()
if(isnull(price))
price = rand(price_min, price_max)
@@ -48,9 +54,11 @@
//we're replacing the item to sell, and the old item is an instance!
if(ismovable(item))
UnregisterSignal(item, COMSIG_QDELETING)
+ html_icon = null
item = path_or_ref
identifier = "[path_or_ref]"
if(ismovable(path_or_ref))
+ html_icon = icon2base64(getFlatIcon(item, no_anim=TRUE))
RegisterSignal(item, COMSIG_QDELETING, PROC_REF(on_item_del))
identifier = "[REF(src)]"
@@ -82,7 +90,7 @@
CRASH("Invalid item type for market item [item || "null"]")
/**
- * Buys the item and makes SSblackmarket handle it.
+ * Buys the item and makes SSmarket handle it.
*
* @param uplink The uplink that is buying the item.
* @param buyer The mob that is buying the item.
@@ -102,8 +110,8 @@
// Alright, the item has been purchased.
var/datum/market_purchase/purchase = new(src, uplink, shipping_method, legal_status)
- // SSblackmarket takes care of the shipping.
- if(SSblackmarket.queue_item(purchase))
+ // SSmarket takes care of the shipping.
+ if(SSmarket.queue_item(purchase))
stock--
buyer.log_message("has succesfully purchased [name] using [shipping_method] for shipping.", LOG_ECON)
return TRUE
@@ -139,7 +147,7 @@
/datum/market_purchase/Destroy()
entry = null
uplink = null
- SSblackmarket.queued_purchases -= src
+ SSmarket.queued_purchases -= src
return ..()
/datum/market_purchase/proc/on_instance_del(datum/source)
diff --git a/code/modules/cargo/markets/market_items/hostages.dm b/code/modules/cargo/markets/market_items/hostages.dm
index ed5b1f10a7fcfc..702cea907bdebf 100644
--- a/code/modules/cargo/markets/market_items/hostages.dm
+++ b/code/modules/cargo/markets/market_items/hostages.dm
@@ -5,6 +5,7 @@
stock = 1
availability_prob = 100
shipping_override = list(SHIPPING_METHOD_LTSRBT = 0, SHIPPING_METHOD_SUPPLYPOD = 350)
+ restockable = FALSE
/// temporary reference to the 4 in 7 chances of signaler and electropack.
var/obj/item/assembly/signaler/signaler
diff --git a/code/modules/cargo/markets/market_items/local_goods.dm b/code/modules/cargo/markets/market_items/local_goods.dm
new file mode 100644
index 00000000000000..d81c38fec98bab
--- /dev/null
+++ b/code/modules/cargo/markets/market_items/local_goods.dm
@@ -0,0 +1,25 @@
+///A special category for goods placed on the market by station by someone with the LTSRBT.
+/datum/market_item/local_good
+ category = "Local Goods"
+ abstract_path = /datum/market_item/local_good
+ stock = 1
+ availability_prob = 100
+ restockable = FALSE
+ var/datum/bank_account/seller
+
+/datum/market_item/local_good/New(atom/movable/thing, datum/bank_account/seller)
+ ..()
+ set_item(thing)
+ src.seller = seller
+ if(seller)
+ RegisterSignal(seller, COMSIG_QDELETING, PROC_REF(delete_reference))
+
+/datum/market_item/local_good/buy(obj/item/market_uplink/uplink, mob/buyer, shipping_method, legal_status)
+ . = ..()
+ if(. && seller)
+ seller.adjust_money(round(price * (1 - MARKET_WITHHOLDING_TAX)), "Market: Item Sold")
+ QDEL_IN(src, 10 MINUTES) //This category cannot hold more than 40 items at a time, so we need to clear sold items.
+
+/datum/market_item/local_good/proc/delete_reference(datum/source)
+ SIGNAL_HANDLER
+ seller = null
diff --git a/code/modules/cargo/markets/market_items/stolen_goods.dm b/code/modules/cargo/markets/market_items/stolen_goods.dm
index 02a72f05d26d1c..cb1932673e0e3f 100644
--- a/code/modules/cargo/markets/market_items/stolen_goods.dm
+++ b/code/modules/cargo/markets/market_items/stolen_goods.dm
@@ -4,6 +4,7 @@
abstract_path = /datum/market_item/stolen_good
stock = 1
availability_prob = 100
+ restockable = FALSE
/datum/market_item/stolen_good/New(atom/movable/thing, thing_price)
..()
diff --git a/code/modules/cargo/markets/market_items/tools.dm b/code/modules/cargo/markets/market_items/tools.dm
index 963d7fbaeb0755..0c9969756d30f4 100644
--- a/code/modules/cargo/markets/market_items/tools.dm
+++ b/code/modules/cargo/markets/market_items/tools.dm
@@ -11,7 +11,7 @@
stock_min = 2
stock_max = 4
price_min = CARGO_CRATE_VALUE * 2.5
- price_max = CARGO_CRATE_VALUE * 3.75
+ price_max = CARGO_CRATE_VALUE * 3.25
availability_prob = 100
/datum/market_item/tool/caravan_wrench
diff --git a/code/modules/cargo/markets/market_items/weapons.dm b/code/modules/cargo/markets/market_items/weapons.dm
index 4f20cf865bc9b2..12241450ba59a1 100644
--- a/code/modules/cargo/markets/market_items/weapons.dm
+++ b/code/modules/cargo/markets/market_items/weapons.dm
@@ -24,6 +24,16 @@
stock_max = 4
availability_prob = 40
+/datum/market_item/weapon/buckshot
+ name = "Box of Buckshot Shells"
+ desc = "It wasn't easy since buckshot has been made illegal all over this sector of space, but \
+ we managed to find a large cache of it... somewhere. A word of caution, the stuff may be a tad old."
+ stock_max = 3
+ availability_prob = 35
+ item = /obj/item/storage/box/lethalshot/old
+ price_min = CARGO_CRATE_VALUE * 3
+ price_max = CARGO_CRATE_VALUE * 4.5
+
/datum/market_item/weapon/bone_spear
name = "Bone Spear"
desc = "Authentic tribal spear, made from real bones! A steal at any price, especially if you're a caveman."
diff --git a/code/modules/cargo/markets/market_telepad.dm b/code/modules/cargo/markets/market_telepad.dm
index 7c5b509a9421de..53a3d73ee486ac 100644
--- a/code/modules/cargo/markets/market_telepad.dm
+++ b/code/modules/cargo/markets/market_telepad.dm
@@ -1,3 +1,6 @@
+#define DEFAULT_RESTOCK_COST CARGO_CRATE_VALUE * 3.375
+#define PLACE_ON_MARKET_COST PAYCHECK_LOWER * 1.2
+
/obj/item/circuitboard/machine/ltsrbt
name = "LTSRBT (Machine Board)"
icon_state = "bluespacearray"
@@ -12,12 +15,14 @@
/obj/machinery/ltsrbt
name = "Long-To-Short-Range-Bluespace-Transceiver"
desc = "The LTSRBT is a compact teleportation machine for receiving and sending items outside the station and inside the station.\nUsing teleportation frequencies stolen from NT it is near undetectable.\nEssential for any illegal market operations on NT stations.\n"
- icon = 'icons/obj/machines/telecomms.dmi'
- icon_state = "exonet_node"
+ icon = 'icons/obj/machines/ltsrbt.dmi'
+ icon_state = "ltsrbt_idle"
+ base_icon_state = "ltsrbt"
circuit = /obj/item/circuitboard/machine/ltsrbt
density = TRUE
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 2
+ interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND
/// Divider for energy_usage_per_teleport.
var/power_efficiency = 1
@@ -35,18 +40,283 @@
var/datum/market_purchase/transmitting
/// Queue for purchases that the machine should receive and send.
var/list/datum/market_purchase/queue = list()
+ /// The name of the market item that we've set on the UI
+ var/current_name = ""
+ /// The desc of the market item that we've set on the UI
+ var/current_desc = ""
+ /// The price of the market item that we've set on the UI
+ var/current_price = CARGO_CRATE_VALUE
+ /**
+ * Attacking the machinery with enough credits will restock the markets, allowing for more/better items.
+ * The cost doubles each time this is done.
+ */
+ var/static/restock_cost = DEFAULT_RESTOCK_COST
/obj/machinery/ltsrbt/Initialize(mapload)
. = ..()
- SSblackmarket.telepads += src
+ register_context()
+ SSmarket.telepads += src
+ ADD_TRAIT(src, TRAIT_SECLUDED_LOCATION, INNATE_TRAIT) //you cannot sell disky, boss.
+ update_appearance()
/obj/machinery/ltsrbt/Destroy()
- SSblackmarket.telepads -= src
+ SSmarket.telepads -= src
// Bye bye orders.
- if(length(SSblackmarket.telepads))
- for(var/datum/market_purchase/P in queue)
- SSblackmarket.queue_item(P)
+ if(length(SSmarket.telepads))
+ for(var/datum/market_purchase/purchase in queue)
+ SSmarket.queue_item(purchase)
+ if(receiving)
+ SSmarket.queue_item(receiving)
+ queue = null
+ receiving = null
+ transmitting = null
+ return ..()
+
+/obj/machinery/ltsrbt/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ if(held_item)
+ if(state_open)
+ context[SCREENTIP_CONTEXT_LMB] = "Insert"
+ return CONTEXTUAL_SCREENTIP_SET
+ if(held_item.get_item_credit_value() && !(machine_stat & NOPOWER))
+ context[SCREENTIP_CONTEXT_LMB] = "Restock"
+ return CONTEXTUAL_SCREENTIP_SET
+ return NONE
+ if(state_open)
+ context[SCREENTIP_CONTEXT_LMB] = "Close"
+ return CONTEXTUAL_SCREENTIP_SET
+ context[SCREENTIP_CONTEXT_LMB] = "Open"
+ if(occupant && !(machine_stat & NOPOWER))
+ context[SCREENTIP_CONTEXT_RMB] = "Place on market"
+ return CONTEXTUAL_SCREENTIP_SET
+
+/obj/machinery/ltsrbt/examine(mob/user)
+ . = ..()
+ if(!(machine_stat & NOPOWER))
+ . += span_info("A small display reads:")
+ . += span_tinynoticeital("Current market restock price: [EXAMINE_HINT("[restock_cost] cr")].")
+ . += span_tinynoticeital("Market placement fee: [EXAMINE_HINT("[PLACE_ON_MARKET_COST] cr")].")
+ . += span_tinynoticeital("Withholding tax on local items: [EXAMINE_HINT("[MARKET_WITHHOLDING_TAX * 100]%")].")
+
+/obj/machinery/ltsrbt/update_icon_state()
+ . = ..()
+ if(machine_stat & NOPOWER)
+ icon_state = "[base_icon_state]_off"
+ else
+ icon_state = "[base_icon_state][(receiving || length(queue) || occupant) ? "" : "_idle"]"
+
+/obj/machinery/ltsrbt/update_overlays()
+ . = ..()
+ if(!state_open)
+ . += "[base_icon_state]_closed"
+ else
+ var/mutable_appearance/overlay = mutable_appearance(icon, "[base_icon_state]_open")
+ overlay.pixel_w -= 2
+ overlay.pixel_z -= 1
+ . += overlay
+
+/obj/machinery/ltsrbt/attack_hand(mob/user, list/modifiers)
+ . = ..()
+ if(.)
+ return
+ if(!state_open)
+ open_machine(density_to_set = TRUE)
+ else
+ close_machine()
+
+/obj/machinery/ltsrbt/open_machine(drop = TRUE, density_to_set = FALSE)
+ . = ..()
+ playsound(src, 'sound/machines/oven/oven_open.ogg', 75, TRUE)
+
+/obj/machinery/ltsrbt/close_machine(atom/movable/target, density_to_set = TRUE)
. = ..()
+ playsound(src, 'sound/machines/oven/oven_close.ogg', 75, TRUE)
+
+/obj/machinery/ltsrbt/set_occupant(obj/item/new_occupant)
+ . = ..()
+ if(new_occupant)
+ current_name = new_occupant.name
+ current_desc = new_occupant.desc
+
+/obj/machinery/ltsrbt/can_be_occupant(atom/movable/atom)
+ return isitem(atom) && !atom.anchored
+
+/obj/machinery/ltsrbt/Exited(atom/movable/gone)
+ if(gone == occupant)
+ current_price = initial(current_price)
+ current_name = ""
+ current_desc = ""
+ update_appearance(UPDATE_ICON_STATE)
+ return ..()
+
+/obj/machinery/ltsrbt/attack_hand_secondary(mob/user, list/modifiers)
+ . = ..()
+ if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
+ return
+ if(state_open)
+ balloon_alert(user, "close it first!")
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+ if(!occupant)
+ balloon_alert(user, "nothing loaded!")
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+ if(machine_stat & NOPOWER)
+ balloon_alert(user, "machine unpowered!")
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+ if(!COOLDOWN_FINISHED(src, recharge_cooldown))
+ balloon_alert(user, "on cooldown!")
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+ ui_interact(user)
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+
+/obj/machinery/ltsrbt/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ if(user.combat_mode)
+ return NONE
+
+ var/creds_value = tool.get_item_credit_value()
+
+ if(state_open)
+ if(locate(/mob/living) in tool.get_all_contents())
+ say("Living being detected, cannot sell!")
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
+ return ITEM_INTERACT_BLOCKING
+ if(!user.transferItemToLoc(tool, src))
+ balloon_alert(user, "stuck to your hands!")
+ return ITEM_INTERACT_BLOCKING
+ balloon_alert(user, "item loaded")
+ close_machine(tool)
+ return ITEM_INTERACT_SUCCESS
+ else if(!creds_value)
+ balloon_alert(user, "open the machine!")
+ return ITEM_INTERACT_BLOCKING
+
+ if(machine_stat & NOPOWER)
+ return
+
+ if(creds_value < restock_cost)
+ say("Insufficient credits!")
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
+ return ITEM_INTERACT_BLOCKING
+
+ if(istype(tool, /obj/item/holochip))
+ var/obj/item/holochip/chip = tool
+ chip.spend(restock_cost)
+ else
+ qdel(tool)
+ if(creds_value != restock_cost)
+ var/obj/item/holochip/change = new(loc, creds_value - restock_cost)
+ user.put_in_hands(change)
+
+ SSmarket.restock()
+ restock_cost *= 2
+ return ITEM_INTERACT_SUCCESS
+
+/obj/machinery/ltsrbt/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "LTSRBT", name)
+ ui.open()
+
+/obj/machinery/ltsrbt/ui_state()
+ if(!occupant || !COOLDOWN_FINISHED(src, recharge_cooldown))
+ return GLOB.never_state //close it.
+ else
+ return GLOB.default_state
+
+#define LTSRBT_MIN_PRICE PAYCHECK_LOWER
+#define LTSRBT_MAX_PRICE CARGO_CRATE_VALUE * 50
+
+/obj/machinery/ltsrbt/ui_static_data(mob/user)
+ var/list/data = list()
+ data["loaded_icon"] = icon2base64(getFlatIcon(occupant, no_anim=TRUE))
+ data["min_price"] = LTSRBT_MIN_PRICE
+ data["max_price"] = LTSRBT_MAX_PRICE
+ return data
+
+/obj/machinery/ltsrbt/ui_data(mob/user)
+ var/list/data = list()
+ data["name"] = current_name
+ data["price"] = current_price
+ data["desc"] = current_desc
+ return data
+
+/obj/machinery/ltsrbt/ui_act(action, list/params)
+ . = ..()
+ if(.)
+ return
+ switch(action)
+ if("change_name")
+ var/value = params["value"]
+ if(!CAN_BYPASS_FILTER(usr) && is_ic_filtered_for_pdas(value))
+ return TRUE
+ current_name = trim(value, MAX_NAME_LEN)
+ return TRUE
+ if("change_desc")
+ var/value = params["value"]
+ if(!CAN_BYPASS_FILTER(usr) && is_ic_filtered_for_pdas(value))
+ return TRUE
+ current_desc = trim(value, MAX_DESC_LEN)
+ return TRUE
+ if("change_price")
+ current_price = clamp(params["value"], LTSRBT_MIN_PRICE, LTSRBT_MAX_PRICE)
+ return TRUE
+ if("place_on_market")
+ place_on_market(usr)
+ return TRUE
+
+#undef LTSRBT_MIN_PRICE
+#undef LTSRBT_MAX_PRICE
+
+#define LTSRBT_MAX_MARKET_ITEMS 40
+/obj/machinery/ltsrbt/proc/place_on_market(mob/user)
+ if(QDELETED(occupant))
+ return
+ if(locate(/mob/living) in occupant.get_all_contents())
+ say("Living being detected, cannot sell!")
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
+ return
+ var/datum/bank_account/account
+ var/datum/market/our_market = SSmarket.markets[/datum/market/blackmarket]
+ if(!isAdminGhostAI(user))
+ if(!isliving(user))
+ return
+ if(length(our_market.available_items[/datum/market_item/local_good::category]) >= LTSRBT_MAX_MARKET_ITEMS)
+ say("Local market saturated, buy some goods first!")
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
+ return
+ var/mob/living/living_user = user
+ var/obj/item/card/id/card = living_user.get_idcard(TRUE)
+ if(!(card?.registered_account))
+ say("No bank account to charge market fees detected!")
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
+ return
+ if(!card.registered_account.adjust_money(-PLACE_ON_MARKET_COST, "Market: Placement Fee"))
+ say("Insufficient credits!")
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE)
+ return
+ account = card.registered_account
+
+ var/obj/item/item = occupant //occupant, name, price and desc will be null'd once it exits the machine so we need this.
+ var/name_to_use = current_name || item.name
+ var/desc_to_use = current_desc
+ if(account)
+ desc_to_use += "[current_desc ? " - " : ""]Seller: [account.account_holder]"
+ var/price_to_use = current_price
+ item.moveToNullspace()
+ //Something happened and the item was deleted or relocated as soon as it was moved to nullspace.
+ if(QDELETED(item) || item.loc != null)
+ say("Runtime at market_placement.dm, line 153: item gone!") //metajoke
+ return
+ var/datum/market_item/local_good/new_item = new(item, account)
+ new_item.name = name_to_use
+ new_item.desc = desc_to_use
+ new_item.price = price_to_use
+
+ our_market.add_item(new_item)
+
+ say("Item placed on the market!")
+ playsound(src, 'sound/effects/cashregister.ogg', 40, FALSE)
+ COOLDOWN_START(src, recharge_cooldown, recharge_time * 3)
+
+#undef LTSRBT_MAX_MARKET_ITEMS
/obj/machinery/ltsrbt/RefreshParts()
. = ..()
@@ -54,7 +324,6 @@
// On tier 4 recharge_time should be 20 and by default it is 80 as scanning modules should be tier 1.
for(var/datum/stock_part/scanning_module/scanning_module in component_parts)
recharge_time -= scanning_module.tier * 1 SECONDS
- recharge_cooldown = recharge_time
power_efficiency = 0
for(var/datum/stock_part/micro_laser/laser in component_parts)
@@ -67,6 +336,7 @@
/obj/machinery/ltsrbt/proc/add_to_queue(datum/market_purchase/purchase)
if(!recharge_cooldown && !receiving && !transmitting)
receiving = purchase
+ update_appearance(UPDATE_ICON_STATE)
else
queue += purchase
@@ -80,6 +350,8 @@
if(transmitting == purchase)
transmitting = null
+ update_appearance(UPDATE_ICON_STATE)
+
/obj/machinery/ltsrbt/process(seconds_per_tick)
if(machine_stat & NOPOWER)
return
@@ -102,14 +374,17 @@
transmitting = receiving
receiving = null
- COOLDOWN_START(src, recharge_cooldown, recharge_time)
return
if(transmitting)
if(transmitting.item.loc == turf)
do_teleport(transmitting.item, get_turf(transmitting.uplink))
use_energy(energy_usage_per_teleport / power_efficiency)
QDEL_NULL(transmitting)
+ COOLDOWN_START(src, recharge_cooldown, recharge_time)
return
if(length(queue))
receiving = pick_n_take(queue)
+
+#undef DEFAULT_RESTOCK_COST
+#undef PLACE_ON_MARKET_COST
diff --git a/code/modules/cargo/markets/market_uplink.dm b/code/modules/cargo/markets/market_uplink.dm
index d13f59937b66ca..147e37e3f9d870 100644
--- a/code/modules/cargo/markets/market_uplink.dm
+++ b/code/modules/cargo/markets/market_uplink.dm
@@ -20,7 +20,7 @@
/obj/item/market_uplink/Initialize(mapload)
. = ..()
- // We don't want to go through this at mapload because the SSblackmarket isn't initialized yet.
+ // We don't want to go through this at mapload because the SSmarket isn't initialized yet.
if(mapload)
return
@@ -30,7 +30,7 @@
/obj/item/market_uplink/proc/update_viewing_category()
if(accessible_markets.len)
viewing_market = accessible_markets[1]
- var/list/categories = SSblackmarket.markets[viewing_market].categories
+ var/list/categories = SSmarket.markets[viewing_market].categories
if(categories?.len)
viewing_category = categories[1]
@@ -45,7 +45,7 @@
/obj/item/market_uplink/ui_data(mob/user)
var/list/data = list()
- var/datum/market/market = viewing_market ? SSblackmarket.markets[viewing_market] : null
+ var/datum/market/market = viewing_market ? SSmarket.markets[viewing_market] : null
var/obj/item/card/id/id_card
if(isliving(user))
var/mob/living/livin = user
@@ -80,17 +80,18 @@
"name" = item.name,
"cost" = item.price,
"amount" = item.stock,
- "desc" = item.desc || item.name
+ "desc" = item.desc || item.name,
+ "html_icon" = item.html_icon,
))
return data
/obj/item/market_uplink/ui_static_data(mob/user)
var/list/data = list()
- data["delivery_method_description"] = SSblackmarket.shipping_method_descriptions
- data["ltsrbt_built"] = SSblackmarket.telepads.len
+ data["delivery_method_description"] = SSmarket.shipping_method_descriptions
+ data["ltsrbt_built"] = SSmarket.telepads.len
data["markets"] = list()
for(var/M in accessible_markets)
- var/datum/market/BM = SSblackmarket.markets[M]
+ var/datum/market/BM = SSmarket.markets[M]
data["markets"] += list(list(
"id" = M,
"name" = BM.name
@@ -107,7 +108,7 @@
return
if(isnull(viewing_market))
return
- if(!(params["category"] in SSblackmarket.markets[viewing_market].categories))
+ if(!(params["category"] in SSmarket.markets[viewing_market].categories))
return
viewing_category = params["category"]
. = TRUE
@@ -120,7 +121,7 @@
viewing_market = market
- var/list/categories = SSblackmarket.markets[viewing_market].categories
+ var/list/categories = SSmarket.markets[viewing_market].categories
if(categories?.len)
viewing_category = categories[1]
else
@@ -142,7 +143,7 @@
if(isnull(selected_item))
buying = FALSE
return
- var/datum/market/market = SSblackmarket.markets[viewing_market]
+ var/datum/market/market = SSmarket.markets[viewing_market]
market.purchase(selected_item, viewing_category, params["method"], src, usr)
buying = FALSE
diff --git a/code/modules/cargo/packs/costumes_toys.dm b/code/modules/cargo/packs/costumes_toys.dm
index de84a263597da5..a25c47c5d9f887 100644
--- a/code/modules/cargo/packs/costumes_toys.dm
+++ b/code/modules/cargo/packs/costumes_toys.dm
@@ -90,7 +90,7 @@
/datum/supply_pack/costumes_toys/knucklebones
name = "Knucklebones Game Crate"
desc = "A fun dice game definitely not invented by a cult. Consult your local chaplain regarding \
- approved religious activity. Contains eighteen d6, one white crayon, and instructions on how to play."
+ approved religious activity. Contains eighteen d6, one stick of chalk, and instructions on how to play."
cost = CARGO_CRATE_VALUE * 2
contains = list(/obj/item/dice/d6 = 18,
/obj/item/paper/guides/knucklebone,
diff --git a/code/modules/cargo/packs/engineering.dm b/code/modules/cargo/packs/engineering.dm
index 771cba47df61d7..907ae1598c653e 100644
--- a/code/modules/cargo/packs/engineering.dm
+++ b/code/modules/cargo/packs/engineering.dm
@@ -328,3 +328,12 @@
)
crate_name = "radioactive nebula shielding (IMPORTANT)"
crate_type = /obj/structure/closet/crate/engineering
+
+/datum/supply_pack/engineering/portagrav
+ name = "Portable Gravity Unit Crate"
+ desc = "Contains a portable gravity unit, to make the clown float into the ceiling."
+ cost = CARGO_CRATE_VALUE * 4
+ access_view = ACCESS_ENGINEERING
+ contains = list(/obj/machinery/power/portagrav = 1)
+ crate_name = "portable gravity unit crate"
+ crate_type = /obj/structure/closet/crate/engineering
diff --git a/code/modules/cargo/packs/imports.dm b/code/modules/cargo/packs/imports.dm
index cbab2fe70fa5e7..0ae09f0dc6e0f2 100644
--- a/code/modules/cargo/packs/imports.dm
+++ b/code/modules/cargo/packs/imports.dm
@@ -313,11 +313,29 @@
risky espionage hallway operations. Enjoy our product!"
contraband = TRUE
cost = CARGO_CRATE_VALUE * 6
- contains = list(/obj/item/clothing/under/syndicate/floortilecamo = 3,
- /obj/item/clothing/mask/floortilebalaclava = 3,
- /obj/item/clothing/gloves/combat/floortile = 3,
- /obj/item/clothing/shoes/jackboots/floortile = 3,
- /obj/item/storage/backpack/floortile = 3
+ contains = list(
+ /obj/item/clothing/under/syndicate/floortilecamo = 3,
+ /obj/item/clothing/mask/floortilebalaclava = 3,
+ /obj/item/clothing/gloves/combat/floortile = 3,
+ /obj/item/clothing/shoes/jackboots/floortile = 3,
+ /obj/item/storage/backpack/floortile = 3
)
crate_name = "floortile camouflauge crate"
crate_type = /obj/structure/closet/crate/secure/weapon
+
+/**
+ * The Long To Short Range Bluespace Teleporter, used to deliver (black) market purchases more effiiently
+ * It can also be used to restock it, if you hit it with enough credits.
+ */
+/datum/supply_pack/imports/blackmarket_telepad
+ name = "Black Market LTSRBT"
+ desc = "Need a faster and better way of transporting your illegal goods from and to the \
+ 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
+ contains = list(
+ /obj/item/circuitboard/machine/ltsrbt,
+ /obj/item/stack/ore/bluespace_crystal/artificial = 2,
+ /obj/item/stock_parts/subspace/ansible,
+ )
diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm
index c30a698c06f876..d44e8c42d37835 100644
--- a/code/modules/cargo/packs/medical.dm
+++ b/code/modules/cargo/packs/medical.dm
@@ -121,7 +121,7 @@
/datum/supply_pack/medical/experimentalmedicine
name = "Experimental Medicine Crate"
desc = "A crate containing the medication required for living with Hereditary Manifold Sickness, Sansufentanyl."
- cost = CARGO_CRATE_VALUE * 2
+ cost = CARGO_CRATE_VALUE * 3
contains = list(/obj/item/storage/pill_bottle/sansufentanyl = 2)
crate_name = "experimental medicine crate"
crate_type = /obj/structure/closet/crate/medical
@@ -187,6 +187,6 @@
name = "Strong-Arm Implant Set"
desc = "A crate containing two implants, which can be surgically implanted to empower the strength of human arms. Warranty void if exposed to electromagnetic pulses."
cost = CARGO_CRATE_VALUE * 6
- contains = list(/obj/item/organ/internal/cyberimp/arm/muscle = 2)
+ contains = list(/obj/item/organ/internal/cyberimp/arm/strongarm = 2)
crate_name = "Strong-Arm implant crate"
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
diff --git a/code/modules/cargo/packs/security.dm b/code/modules/cargo/packs/security.dm
index 05360fe913f0a8..8a0765602b342f 100644
--- a/code/modules/cargo/packs/security.dm
+++ b/code/modules/cargo/packs/security.dm
@@ -36,7 +36,7 @@
/datum/supply_pack/security/forensics
name = "Forensics Crate"
desc = "Stay hot on the criminal's heels with Nanotrasen's Detective Essentials™. \
- Contains a forensics scanner, six evidence bags, camera, tape recorder, white crayon, \
+ Contains a forensics scanner, six evidence bags, camera, tape recorder, stick of chalk, \
and of course, a fedora."
cost = CARGO_CRATE_VALUE * 2.5
access_view = ACCESS_MORGUE
diff --git a/code/modules/cargo/packs/service.dm b/code/modules/cargo/packs/service.dm
index 434450b430292a..20323b52960dac 100644
--- a/code/modules/cargo/packs/service.dm
+++ b/code/modules/cargo/packs/service.dm
@@ -303,3 +303,17 @@
contains = list(/obj/item/wallframe/barsign/all_access)
crate_name = "bar sign crate"
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
+
+/datum/supply_pack/service/bowmaking
+ name = "Fletching and Bow-Making Starter Kit"
+ desc = "A fairly outdated copy of 'Whittle Me This: Fletching for the Modern Spacer', along with some useful materials. \
+ For those looking to get into bow-making, or give their LARPing a little more edge, you can't go wrong. Also has \
+ instructions for making violins."
+ cost = CARGO_CRATE_VALUE * 1.5
+ contains = list(
+ /obj/item/book/granter/crafting_recipe/fletching = 1,
+ /obj/item/stack/sheet/mineral/wood = 10,
+ /obj/item/stack/sheet/cloth = 10,
+ )
+ crate_name = "bowmaking starter kit crate"
+ crate_type = /obj/structure/closet/crate/wooden
diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm
index ff1208f634a574..f5915eaed37d3b 100644
--- a/code/modules/cargo/supplypod.dm
+++ b/code/modules/cargo/supplypod.dm
@@ -36,7 +36,7 @@
var/effectQuiet = FALSE //The female sniper. If true, the pod makes no noise (including related explosions, opening sounds, etc)
var/effectMissile = FALSE //If true, the pod deletes the second it lands. If you give it an explosion, it will act like a missile exploding as it hits the ground
var/effectCircle = FALSE //If true, allows the pod to come in at any angle. Bit of a weird feature but whatever its here
- var/style = STYLE_STANDARD //Style is a variable that keeps track of what the pod is supposed to look like. It acts as an index to the GLOB.podstyles list in cargo.dm defines to get the proper icon/name/desc for the pod.
+ var/datum/pod_style/style = /datum/pod_style //Style is a variable that keeps track of what the pod is supposed to look like. Only stores a path, type is set for ease of var access
var/reversing = FALSE //If true, the pod will not send any items. Instead, after opening, it will close again (picking up items/mobs) and fly back to centcom
var/list/reverse_dropoff_coords //Turf that the reverse pod will drop off its newly-acquired cargo to
var/fallingSoundLength = 11
@@ -61,7 +61,7 @@
var/list/turfs_in_cargo = list()
/obj/structure/closet/supplypod/bluespacepod
- style = STYLE_BLUESPACE
+ style = /datum/pod_style/advanced
bluespace = TRUE
explosionSize = list(0,0,1,2)
@@ -83,7 +83,7 @@
name = "Syndicate Extraction Pod"
desc = "A specalised, blood-red styled pod for extracting high-value targets out of active mission areas. Targets must be manually stuffed inside the pod for proper delivery."
specialised = TRUE
- style = STYLE_SYNDICATE
+ style = /datum/pod_style/syndicate
bluespace = TRUE
explosionSize = list(0,0,1,2)
delays = list(POD_TRANSIT = 25, POD_FALLING = 4, POD_OPENING = 30, POD_LEAVING = 30)
@@ -93,7 +93,7 @@
reverse_option_list = list("Mobs"=TRUE,"Objects"=FALSE,"Anchored"=FALSE,"Underfloor"=FALSE,"Wallmounted"=FALSE,"Floors"=FALSE,"Walls"=FALSE, "Mecha"=FALSE)
/obj/structure/closet/supplypod/centcompod
- style = STYLE_CENTCOM
+ style = /datum/pod_style/centcom
bluespace = TRUE
explosionSize = list(0,0,0,0)
delays = list(POD_TRANSIT = 20, POD_FALLING = 4, POD_OPENING = 30, POD_LEAVING = 30)
@@ -121,13 +121,13 @@
desc = "An intimidating supply pod, covered in the blood-red markings"
bluespace = TRUE
explosionSize = list(0,0,0,0)
- style = STYLE_SYNDICATE
+ style = /datum/pod_style/syndicate
specialised = TRUE
/obj/structure/closet/supplypod/deadmatch_missile
name = "cruise missile"
desc = "A big ass missile, likely launched from some far-off deep space missile silo."
- style = STYLE_RED_MISSILE
+ style = /datum/pod_style/missile/syndicate
explosionSize = list(0,1,2,2)
effectShrapnel = TRUE
specialised = TRUE
@@ -153,33 +153,32 @@
style = customStyle
setStyle(style) //Upon initialization, give the supplypod an iconstate, name, and description based on the "style" variable. This system is important for the centcom_podlauncher to function correctly
-/obj/structure/closet/supplypod/proc/setStyle(chosenStyle) //Used to give the sprite an icon state, name, and description.
- style = chosenStyle
- var/base = GLOB.podstyles[chosenStyle][POD_BASE] //GLOB.podstyles is a 2D array we treat as a dictionary. The style represents the verticle index, with the icon state, name, and desc being stored in the horizontal indexes of the 2D array.
- icon_state = base
- decal = GLOB.podstyles[chosenStyle][POD_DECAL]
- rubble_type = GLOB.podstyles[chosenStyle][POD_RUBBLE_TYPE]
+/obj/structure/closet/supplypod/proc/setStyle(datum/pod_style/chosen_style) //Used to give the sprite an icon state, name, and description.
+ style = chosen_style
+ icon_state = chosen_style::icon_state
+ decal = chosen_style::decal_icon
+ rubble_type = chosen_style::rubble_type
if (!adminNamed && !specialised) //We dont want to name it ourselves if it has been specifically named by an admin using the centcom_podlauncher datum
- name = GLOB.podstyles[chosenStyle][POD_NAME]
- desc = GLOB.podstyles[chosenStyle][POD_DESC]
- if (GLOB.podstyles[chosenStyle][POD_DOOR])
- door = "[base]_door"
+ name = chosen_style::name
+ desc = chosen_style::desc
+ if (chosen_style::has_door)
+ door = "[icon_state]_door"
else
door = FALSE
update_appearance()
/obj/structure/closet/supplypod/proc/SetReverseIcon()
fin_mask = "bottomfin"
- if (GLOB.podstyles[style][POD_SHAPE] == POD_SHAPE_NORML)
- icon_state = GLOB.podstyles[style][POD_BASE] + "_reverse"
+ if (style::shape == POD_SHAPE_NORMAL)
+ icon_state = style::icon_state + "_reverse"
pixel_x = initial(pixel_x)
transform = matrix()
update_appearance()
/obj/structure/closet/supplypod/proc/backToNonReverseIcon()
fin_mask = initial(fin_mask)
- if (GLOB.podstyles[style][POD_SHAPE] == POD_SHAPE_NORML)
- icon_state = GLOB.podstyles[style][POD_BASE]
+ if (style::shape == POD_SHAPE_NORMAL)
+ icon_state = style::icon_state
pixel_x = initial(pixel_x)
transform = matrix()
update_appearance()
@@ -189,13 +188,13 @@
/obj/structure/closet/supplypod/update_overlays()
. = ..()
- if(style == STYLE_INVISIBLE)
+ if(ispath(style, /datum/pod_style/invisible))
return
if(rubble)
. += rubble.getForeground(src)
- if(style == STYLE_SEETHROUGH)
+ if(ispath(style, /datum/pod_style/seethrough))
for(var/atom/A in contents)
var/mutable_appearance/itemIcon = new(A)
itemIcon.transform = matrix().Translate(-1 * SUPPLYPOD_X_OFFSET, 0)
@@ -227,7 +226,7 @@
if(decal)
. += decal
return
- else if (GLOB.podstyles[style][POD_SHAPE] != POD_SHAPE_NORML) //If we're not a normal pod shape (aka, if we don't have fins), just add the door without masking
+ else if (style::shape != POD_SHAPE_NORMAL) //If we're not a normal pod shape (aka, if we don't have fins), just add the door without masking
. += door
else
var/icon/masked_door = new(icon, door) //The door we want to apply
@@ -280,7 +279,7 @@
reversing = FALSE //Now that we're done reversing, we set this to false (otherwise we would get stuck in an infinite loop of calling the close proc at the bottom of open_pod() )
bluespace = TRUE //Make it so that the pod doesn't stay in centcom forever
pod_flags &= ~FIRST_SOUNDS //Make it so we play sounds now
- if (!effectQuiet && style != STYLE_SEETHROUGH)
+ if (!effectQuiet && !ispath(style, /datum/pod_style/seethrough))
audible_message(span_notice("The pod hisses, closing and launching itself away from the station."), span_notice("The ground vibrates, and you hear the sound of engines firing."))
stay_after_drop = FALSE
holder.pixel_z = initial(holder.pixel_z)
@@ -356,14 +355,14 @@
opened = TRUE //We set opened to TRUE to avoid spending time trying to open (due to being deleted) during the Destroy() proc
qdel(src)
return
- if (style == STYLE_GONDOLA) //Checks if we are supposed to be a gondola pod. If so, create a gondolapod mob, and move this pod to nullspace. I'd like to give a shout out, to my man oranges
+ if (ispath(style, /datum/pod_style/gondola)) //Checks if we are supposed to be a gondola pod. If so, create a gondolapod mob, and move this pod to nullspace. I'd like to give a shout out, to my man oranges
var/mob/living/basic/pet/gondola/gondolapod/benis = new(turf_underneath, src)
benis.contents |= contents //Move the contents of this supplypod into the gondolapod mob.
for (var/mob/living/mob_in_pod in benis.contents)
mob_in_pod.reset_perspective(null)
moveToNullspace()
addtimer(CALLBACK(src, PROC_REF(open_pod), benis), delays[POD_OPENING]) //After the opening delay passes, we use the open proc from this supplyprod while referencing the contents of the "holder", in this case the gondolapod mob
- else if (style == STYLE_SEETHROUGH)
+ else if (ispath(style, /datum/pod_style/seethrough))
open_pod(src)
else
addtimer(CALLBACK(src, PROC_REF(open_pod), src), delays[POD_OPENING]) //After the opening delay passes, we use the open proc from this supplypod, while referencing this supplypod's contents
@@ -386,11 +385,11 @@
for (var/cargo in holder.contents)
var/atom/movable/movable_cargo = cargo
movable_cargo.forceMove(turf_underneath)
- if (!effectQuiet && !openingSound && style != STYLE_SEETHROUGH && !(pod_flags & FIRST_SOUNDS)) //If we aren't being quiet, play the default pod open sound
+ if (!effectQuiet && !openingSound && !ispath(style, /datum/pod_style/seethrough) && !(pod_flags & FIRST_SOUNDS)) //If we aren't being quiet, play the default pod open sound
playsound(get_turf(holder), open_sound, 15, TRUE, -3)
if (broken) //If the pod is opening because it's been destroyed, we end here
return
- if (style == STYLE_SEETHROUGH)
+ if (ispath(style, /datum/pod_style/seethrough))
startExitSequence(src)
else
if (reversing)
@@ -405,7 +404,7 @@
close(holder)
else if (bluespace) //If we're a bluespace pod, then delete ourselves (along with our holder, if a separate holder exists)
deleteRubble()
- if (!effectQuiet && style != STYLE_INVISIBLE && style != STYLE_SEETHROUGH)
+ if (!effectQuiet && !ispath(style, /datum/pod_style/invisible) && !ispath(style, /datum/pod_style/seethrough))
do_sparks(5, TRUE, holder) //Create some sparks right before closing
qdel(src) //Delete ourselves and the holder
if (holder != src)
@@ -427,18 +426,22 @@
insert(turf_underneath, holder)
/obj/structure/closet/supplypod/insert(atom/to_insert, atom/movable/holder)
- if(insertion_allowed(to_insert))
- if(isturf(to_insert))
- var/turf/turf_to_insert = to_insert
- turfs_in_cargo += turf_to_insert.type
- turf_to_insert.ScrapeAway()
- else
- var/atom/movable/movable_to_insert = to_insert
- movable_to_insert.forceMove(holder)
- return TRUE
- else
+ if(!insertion_allowed(to_insert))
return FALSE
+ if(isturf(to_insert))
+ var/turf/turf_to_insert = to_insert
+ turfs_in_cargo += turf_to_insert.type
+ turf_to_insert.ScrapeAway()
+ return TRUE
+
+ var/atom/movable/movable_to_insert = to_insert
+ if (ismob(movable_to_insert))
+ var/mob/mob_to_insert = movable_to_insert
+ if (!isnull(mob_to_insert.buckled))
+ mob_to_insert.buckled.unbuckle_mob(mob_to_insert, force = TRUE)
+ movable_to_insert.forceMove(holder)
+
/obj/structure/closet/supplypod/insertion_allowed(atom/to_insert)
if(to_insert.invisibility == INVISIBILITY_ABSTRACT)
return FALSE
@@ -542,10 +545,10 @@
update_appearance()
/obj/structure/closet/supplypod/proc/addGlow()
- if (GLOB.podstyles[style][POD_SHAPE] != POD_SHAPE_NORML)
+ if (style::shape != POD_SHAPE_NORMAL)
return
glow_effect = new(src)
- glow_effect.icon_state = "pod_glow_" + GLOB.podstyles[style][POD_GLOW]
+ glow_effect.icon_state = "pod_glow_" + style::glow_color
vis_contents += glow_effect
glow_effect.layer = GASFIRE_LAYER
SET_PLANE_EXPLICIT(glow_effect, ABOVE_GAME_PLANE, src)
@@ -634,7 +637,7 @@
if (type == RUBBLE_THIN)
icon_state += "_thin"
foreground += "_thin"
- if (pod.style == STYLE_BOX)
+ if (ispath(pod.style, /datum/pod_style/box))
verticle_offset = -2
else
verticle_offset = initial(verticle_offset)
@@ -722,12 +725,12 @@
pod.transform = matrix().Turn(rotation)
pod.layer = FLY_LAYER
SET_PLANE_EXPLICIT(pod, ABOVE_GAME_PLANE, src)
- if (pod.style != STYLE_INVISIBLE)
+ if (!ispath(pod.style, /datum/pod_style/invisible))
animate(pod, pixel_z = -1 * abs(sin(rotation))*4, pixel_x = SUPPLYPOD_X_OFFSET + (sin(rotation) * 20), time = pod.delays[POD_FALLING], easing = LINEAR_EASING) //Make the pod fall! At an angle!
addtimer(CALLBACK(src, PROC_REF(endLaunch)), pod.delays[POD_FALLING], TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation
/obj/effect/pod_landingzone/proc/setupSmoke(rotation)
- if (pod.style == STYLE_INVISIBLE || pod.style == STYLE_SEETHROUGH)
+ if (ispath(pod.style, /datum/pod_style/invisible) || ispath(pod.style, /datum/pod_style/seethrough))
return
var/turf/our_turf = get_turf(drop_location())
for ( var/i in 1 to length(smoke_effects))
@@ -746,7 +749,7 @@
QDEL_IN(smoke_part, pod.delays[POD_FALLING] + 35)
/obj/effect/pod_landingzone/proc/drawSmoke()
- if (pod.style == STYLE_INVISIBLE || pod.style == STYLE_SEETHROUGH)
+ if (ispath(pod.style, /datum/pod_style/invisible) || ispath(pod.style, /datum/pod_style/seethrough))
return
for (var/obj/effect/supplypod_smoke/smoke_part in smoke_effects)
animate(smoke_part, alpha = 0, time = 20, flags = ANIMATION_PARALLEL)
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index d37ff1df22e076..2ed6ed0c3d6f6e 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -1237,6 +1237,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
winset(usr, "mainwindow", "can-resize=true")
winset(usr, "mainwindow", "is-maximized=false")
winset(usr, "mainwindow", "on-size=attempt_auto_fit_viewport")
+ attempt_auto_fit_viewport()
/client/verb/toggle_status_bar()
set name = "Toggle Status Bar"
diff --git a/code/modules/client/preferences/clothing.dm b/code/modules/client/preferences/clothing.dm
index b54149db2998b6..e57d87bf2c8215 100644
--- a/code/modules/client/preferences/clothing.dm
+++ b/code/modules/client/preferences/clothing.dm
@@ -155,7 +155,7 @@
return /datum/sprite_accessory/undershirt/sports_bra::name
return ..()
-*/ // NOVA EDIT REMOVAL END
+*/ // SKYRAT EDIT REMOVAL END
/datum/preference/choiced/undershirt/icon_for(value)
var/static/icon/body
diff --git a/code/modules/client/preferences/paraplegic.dm b/code/modules/client/preferences/paraplegic.dm
new file mode 100644
index 00000000000000..1ffa704c77d0bc
--- /dev/null
+++ b/code/modules/client/preferences/paraplegic.dm
@@ -0,0 +1,20 @@
+/datum/preference/choiced/paraplegic
+ category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
+ savefile_key = "paraplegic"
+ savefile_identifier = PREFERENCE_CHARACTER
+
+/datum/preference/choiced/paraplegic/init_possible_values()
+ return GLOB.paraplegic_choice
+
+/datum/preference/choiced/paraplegic/create_default_value()
+ return "Default"
+
+/datum/preference/choiced/paraplegic/is_accessible(datum/preferences/preferences)
+ . = ..()
+ if (!.)
+ return FALSE
+
+ return "Paraplegic" in preferences.all_quirks
+
+/datum/preference/choiced/paraplegic/apply_to_human(mob/living/carbon/human/target, value)
+ return
diff --git a/code/modules/client/preferences/sounds.dm b/code/modules/client/preferences/sounds.dm
index f1778405665ad2..4a0298132c2683 100644
--- a/code/modules/client/preferences/sounds.dm
+++ b/code/modules/client/preferences/sounds.dm
@@ -116,3 +116,9 @@
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
savefile_key = "sound_elevator"
savefile_identifier = PREFERENCE_PLAYER
+
+/// Controls hearing radio noise
+/datum/preference/toggle/radio_noise
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "sound_radio_noise"
+ savefile_identifier = PREFERENCE_PLAYER
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 7034cd3484c23c..65aa5642b8b34c 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -183,19 +183,19 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
apply_all_client_preferences()
//general preferences
- lastchangelog = savefile.get_entry("lastchangelog")
- be_special = savefile.get_entry("be_special")
- default_slot = savefile.get_entry("default_slot")
- chat_toggles = savefile.get_entry("chat_toggles")
- toggles = savefile.get_entry("toggles")
- ignoring = savefile.get_entry("ignoring")
+ lastchangelog = savefile.get_entry("lastchangelog", lastchangelog)
+ be_special = savefile.get_entry("be_special", be_special)
+ default_slot = savefile.get_entry("default_slot", default_slot)
+ chat_toggles = savefile.get_entry("chat_toggles", chat_toggles)
+ toggles = savefile.get_entry("toggles", toggles)
+ ignoring = savefile.get_entry("ignoring", ignoring)
// OOC commendations
- hearted_until = savefile.get_entry("hearted_until")
+ hearted_until = savefile.get_entry("hearted_until", hearted_until)
if(hearted_until > world.realtime)
hearted = TRUE
//favorite outfits
- favorite_outfits = savefile.get_entry("favorite_outfits")
+ favorite_outfits = savefile.get_entry("favorite_outfits", favorite_outfits)
var/list/parsed_favs = list()
for(var/typetext in favorite_outfits)
@@ -205,7 +205,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
favorite_outfits = unique_list(parsed_favs)
// Custom hotkeys
- key_bindings = savefile.get_entry("key_bindings")
+ key_bindings = savefile.get_entry("key_bindings", key_bindings)
//try to fix any outdated data if necessary
if(needs_update >= 0)
diff --git a/code/modules/clothing/chameleon/generic_chameleon_clothing.dm b/code/modules/clothing/chameleon/generic_chameleon_clothing.dm
index 47b6f4db185a57..69800031f73a36 100644
--- a/code/modules/clothing/chameleon/generic_chameleon_clothing.dm
+++ b/code/modules/clothing/chameleon/generic_chameleon_clothing.dm
@@ -107,6 +107,7 @@ do { \
greyscale_colors = null
resistance_flags = NONE
+ body_parts_covered = HANDS|ARMS
armor_type = /datum/armor/gloves_chameleon
actions_types = list(/datum/action/item_action/chameleon/change/gloves)
clothing_traits = list(TRAIT_FAST_CUFFING)
@@ -218,6 +219,7 @@ do { \
desc = "A pair of black shoes."
icon_state = "sneakers"
inhand_icon_state = "sneakers_back"
+ body_parts_covered = FEET|LEGS
greyscale_colors = "#545454#ffffff"
greyscale_config = /datum/greyscale_config/sneakers
greyscale_config_worn = /datum/greyscale_config/sneakers/worn
diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm
index 6e4a727456396f..1c90176bc9e796 100644
--- a/code/modules/clothing/glasses/_glasses.dm
+++ b/code/modules/clothing/glasses/_glasses.dm
@@ -618,7 +618,7 @@
glass_colour_type = FALSE
vision_flags = SEE_TURFS
clothing_traits = list(TRAIT_REAGENT_SCANNER, TRAIT_MADNESS_IMMUNE)
- var/list/hudlist = list(DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC_ADVANCED, DATA_HUD_SECURITY_ADVANCED)
+ var/list/hudlist = list(DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC, DATA_HUD_SECURITY_ADVANCED, DATA_HUD_BOT_PATH)
var/xray = FALSE
/obj/item/clothing/glasses/debug/equipped(mob/user, slot)
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index f82f56a48fbe5b..dc35ab1dbf4c0c 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -2,26 +2,6 @@
name = "HUD"
desc = "A heads-up display that provides important info in (almost) real time."
flags_1 = null //doesn't protect eyes because it's a monocle, duh
- ///A list of atom hud types added to the mob when the glasses are worn on the appropriate slot.
- var/list/hud_types
-
- // NOTE: Just because you have a HUD display doesn't mean you should be able to interact with stuff on examine, that's where the associated trait (TRAIT_MEDICAL_HUD, TRAIT_SECURITY_HUD, etc) is necessary.
-
-/obj/item/clothing/glasses/hud/equipped(mob/living/carbon/human/user, slot)
- ..()
- if(!(slot & ITEM_SLOT_EYES))
- return
- for(var/hud_type in hud_types)
- var/datum/atom_hud/our_hud = GLOB.huds[hud_type]
- our_hud.show_to(user)
-
-/obj/item/clothing/glasses/hud/dropped(mob/living/carbon/human/user)
- ..()
- if(!istype(user) || user.glasses != src)
- return
- for(var/hud_type in hud_types)
- var/datum/atom_hud/our_hud = GLOB.huds[hud_type]
- our_hud.hide_from(user)
/obj/item/clothing/glasses/hud/emp_act(severity)
. = ..()
@@ -56,7 +36,6 @@
name = "health scanner HUD"
desc = "A heads-up display that scans the humanoids in view and provides accurate data about their health status."
icon_state = "healthhud"
- hud_types = list(DATA_HUD_MEDICAL_ADVANCED)
clothing_traits = list(TRAIT_MEDICAL_HUD)
glass_colour_type = /datum/client_colour/glass_colour/lightblue
@@ -64,7 +43,6 @@
name = "health scanner security HUD"
desc = "A heads-up display that scans the humanoids in view and provides accurate data about their health status, ID status and security records."
icon_state = "medsechud"
- hud_types = list(DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_SECURITY_ADVANCED)
clothing_traits = list(TRAIT_MEDICAL_HUD, TRAIT_SECURITY_HUD)
/obj/item/clothing/glasses/hud/health/night
@@ -118,7 +96,6 @@
name = "diagnostic HUD"
desc = "A heads-up display capable of analyzing the integrity and status of robotics and exosuits."
icon_state = "diagnostichud"
- hud_types = list(DATA_HUD_DIAGNOSTIC_BASIC)
clothing_traits = list(TRAIT_DIAGNOSTIC_HUD)
glass_colour_type = /datum/client_colour/glass_colour/lightorange
@@ -161,7 +138,6 @@
name = "security HUD"
desc = "A heads-up display that scans the humanoids in view and provides accurate data about their ID status and security records."
icon_state = "securityhud"
- hud_types = list(DATA_HUD_SECURITY_ADVANCED)
clothing_traits = list(TRAIT_SECURITY_HUD)
glass_colour_type = /datum/client_colour/glass_colour/red
@@ -251,20 +227,18 @@
if (wearer.glasses != src)
return
- for(var/hud_type in hud_types)
- var/datum/atom_hud/our_hud = GLOB.huds[hud_type]
- our_hud.hide_from(user)
+ for(var/trait in clothing_traits)
+ REMOVE_CLOTHING_TRAIT(user, trait)
- if (DATA_HUD_MEDICAL_ADVANCED in hud_types)
- hud_types = null
- else if (DATA_HUD_SECURITY_ADVANCED in hud_types)
- hud_types = list(DATA_HUD_MEDICAL_ADVANCED)
+ if (TRAIT_MEDICAL_HUD in clothing_traits)
+ clothing_traits = null
+ else if (TRAIT_SECURITY_HUD in clothing_traits)
+ clothing_traits = list(TRAIT_MEDICAL_HUD)
else
- hud_types = list(DATA_HUD_SECURITY_ADVANCED)
+ clothing_traits = list(TRAIT_SECURITY_HUD)
- for(var/hud_type in hud_types)
- var/datum/atom_hud/our_hud = GLOB.huds[hud_type]
- our_hud.show_to(user)
+ for(var/trait in clothing_traits)
+ ADD_CLOTHING_TRAIT(user, trait)
/datum/action/item_action/switch_hud
name = "Switch HUD"
@@ -273,20 +247,22 @@
name = "thermal HUD scanner"
desc = "Thermal imaging HUD in the shape of glasses."
icon_state = "thermal"
- hud_types = list(DATA_HUD_SECURITY_ADVANCED)
vision_flags = SEE_MOBS
color_cutoffs = list(25, 8, 5)
glass_colour_type = /datum/client_colour/glass_colour/red
+ clothing_traits = list(TRAIT_SECURITY_HUD)
/obj/item/clothing/glasses/hud/toggle/thermal/attack_self(mob/user)
..()
- var/hud_type = hud_types[1]
+ var/hud_type
+ if (!isnull(clothing_traits) && clothing_traits.len)
+ hud_type = clothing_traits[1]
switch (hud_type)
- if (DATA_HUD_MEDICAL_ADVANCED)
+ if (TRAIT_MEDICAL_HUD)
icon_state = "meson"
color_cutoffs = list(5, 15, 5)
change_glass_color(/datum/client_colour/glass_colour/green)
- if (DATA_HUD_SECURITY_ADVANCED)
+ if (TRAIT_SECURITY_HUD)
icon_state = "thermal"
color_cutoffs = list(25, 8, 5)
change_glass_color(/datum/client_colour/glass_colour/red)
diff --git a/code/modules/clothing/gloves/punch_mitts.dm b/code/modules/clothing/gloves/punch_mitts.dm
new file mode 100644
index 00000000000000..07d93d5ab021cd
--- /dev/null
+++ b/code/modules/clothing/gloves/punch_mitts.dm
@@ -0,0 +1,24 @@
+/obj/item/clothing/gloves/fingerless/punch_mitts
+ name = "punching mitts"
+ desc = "Fingerless gloves with nasty spikes attached. Allows the wearer to utilize the ill-reputed fighting technique known as Hunter Boxing. The style \
+ allows the user to punch wildlife rapidly to death. Supposedly, this is an incredible workout, but few people are insane enough to attempt to \
+ punch every dangerous creature they encounter in the wild to death with their bare hands. Also kinda works against humanoids as well. \
+ Not that you would... right?"
+ icon_state = "punch_mitts"
+ body_parts_covered = HANDS|ARMS
+ resistance_flags = LAVA_PROOF | FIRE_PROOF
+ armor_type = /datum/armor/gloves_mitts
+
+/obj/item/clothing/gloves/fingerless/punch_mitts/Initialize(mapload)
+ . = ..()
+
+ AddComponent(/datum/component/martial_art_giver, /datum/martial_art/boxing/hunter)
+
+/datum/armor/gloves_mitts
+ melee = 25
+ bullet = 5
+ laser = 5
+ energy = 5
+ bomb = 100
+ fire = 100
+ acid = 30
diff --git a/code/modules/clothing/head/costume.dm b/code/modules/clothing/head/costume.dm
index 13a6e549b0e915..5442210aecd731 100644
--- a/code/modules/clothing/head/costume.dm
+++ b/code/modules/clothing/head/costume.dm
@@ -87,6 +87,10 @@
clothing_flags = SNUG_FIT
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
+/obj/item/clothing/head/costume/lobsterhat/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/speechmod, replacements = strings("crustacean_replacement.json", "crustacean"))
+
/obj/item/clothing/head/costume/drfreezehat
name = "doctor freeze's wig"
desc = "A cool wig for cool people."
diff --git a/code/modules/clothing/head/hat.dm b/code/modules/clothing/head/hat.dm
index d9258b8c7ddca3..7b7329088c827b 100644
--- a/code/modules/clothing/head/hat.dm
+++ b/code/modules/clothing/head/hat.dm
@@ -210,6 +210,14 @@
name = "rice hat"
desc = "Welcome to the rice fields, motherfucker."
icon_state = "rice_hat"
+ base_icon_state = "rice_hat"
+ var/reversed = FALSE
+
+/obj/item/clothing/head/costume/rice_hat/click_alt(mob/user)
+ reversed = !reversed
+ worn_icon_state = "[base_icon_state][reversed ? "_kim" : ""]"
+ to_chat(user, span_notice("You [reversed ? "lower" : "raise"] the hat."))
+ update_appearance()
/obj/item/clothing/head/costume/lizard
name = "lizardskin cloche hat"
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 68921334510384..75e31d1318313a 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -101,6 +101,7 @@
name = "tactical combat helmet"
desc = "A tactical black helmet, sealed from outside hazards with a plate of glass and not much else."
icon_state = "marine_command"
+ base_icon_state = "marine_command"
inhand_icon_state = "marine_helmet"
armor_type = /datum/armor/helmet_marine
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
@@ -126,14 +127,17 @@
/obj/item/clothing/head/helmet/marine/security
name = "marine heavy helmet"
icon_state = "marine_security"
+ base_icon_state = "marine_security"
/obj/item/clothing/head/helmet/marine/engineer
name = "marine utility helmet"
icon_state = "marine_engineer"
+ base_icon_state = "marine_engineer"
/obj/item/clothing/head/helmet/marine/medic
name = "marine medic helmet"
icon_state = "marine_medic"
+ base_icon_state = "marine_medic"
/obj/item/clothing/head/helmet/marine/pmc
icon_state = "marine"
@@ -568,3 +572,106 @@
fire = 50
acid = 50
wound = 30
+
+/obj/item/clothing/head/helmet/durability/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
+ take_damage(1, BRUTE, 0, 0)
+
+/obj/item/clothing/head/helmet/durability/watermelon
+ name = "Watermelon Helmet"
+ desc = "A helmet cut out from a watermelon. Might take a few hits, but don't expect it whitstand much."
+ icon_state = "watermelon"
+ inhand_icon_state = "watermelon"
+ flags_inv = HIDEEARS
+ dog_fashion = /datum/dog_fashion/head/watermelon
+ armor_type = /datum/armor/helmet_watermelon
+ max_integrity = 15
+
+/obj/item/clothing/head/helmet/durability/watermelon/fire_resist
+ resistance_flags = FIRE_PROOF
+ armor_type = /datum/armor/helmet_watermelon_fr
+
+/datum/armor/helmet_watermelon
+ melee = 15
+ bullet = 10
+ energy = 10
+ bomb = 10
+ fire = 0
+ acid = 25
+ wound = 5
+
+/datum/armor/helmet_watermelon_fr
+ melee = 15
+ bullet = 10
+ energy = 10
+ bomb = 10
+ fire = 15
+ acid = 30
+ wound = 5
+
+/obj/item/clothing/head/helmet/durability/holymelon
+ name = "Holymelon Helmet"
+ desc = "A helmet from a hollowed out holymelon. Might take a few hits, but don't expect it whitstand much."
+ icon_state = "holymelon"
+ inhand_icon_state = "holymelon"
+ flags_inv = HIDEEARS
+ dog_fashion = /datum/dog_fashion/head/holymelon
+ armor_type = /datum/armor/helmet_watermelon
+ max_integrity = 15
+ var/decayed = FALSE
+
+/obj/item/clothing/head/helmet/durability/holymelon/fire_resist
+ resistance_flags = FIRE_PROOF
+ armor_type = /datum/armor/helmet_watermelon_fr
+
+/obj/item/clothing/head/helmet/durability/holymelon/Initialize(mapload)
+ . = ..()
+ if(decayed)
+ decay()
+ return
+
+ AddComponent(
+ /datum/component/anti_magic, \
+ antimagic_flags = MAGIC_RESISTANCE_HOLY, \
+ inventory_flags = ITEM_SLOT_OCLOTHING, \
+ charges = 1, \
+ drain_antimagic = CALLBACK(src, PROC_REF(drain_antimagic)), \
+ expiration = CALLBACK(src, PROC_REF(decay)) \
+ )
+
+/obj/item/clothing/head/helmet/durability/holymelon/proc/drain_antimagic(mob/user)
+ to_chat(user, span_warning("[src] looses a bit of its shimmer and glossiness..."))
+
+/obj/item/clothing/head/helmet/durability/holymelon/proc/decay()
+ take_damage(8, BRUTE, 0, 0)
+
+/obj/item/clothing/head/helmet/durability/barrelmelon
+ name = "Barrelmelon Helmet"
+ desc = "A helmet from hollowed out barrelmelon. As sturdy as if made from actual wood, though its rigid structure makes it break up quicker."
+ icon_state = "barrelmelon"
+ inhand_icon_state = "barrelmelon"
+ flags_inv = HIDEEARS
+ dog_fashion = /datum/dog_fashion/head/barrelmelon
+ armor_type = /datum/armor/helmet_barrelmelon
+ max_integrity = 10
+
+/obj/item/clothing/head/helmet/durability/barrelmelon/fire_resist
+ resistance_flags = FIRE_PROOF
+ armor_type = /datum/armor/helmet_barrelmelon_fr
+
+/datum/armor/helmet_barrelmelon
+ melee = 25
+ bullet = 20
+ energy = 15
+ bomb = 10
+ fire = 0
+ acid = 35
+ wound = 10
+
+/datum/armor/helmet_barrelmelon_fr
+ melee = 25
+ bullet = 20
+ energy = 15
+ bomb = 10
+ fire = 20
+ acid = 40
+ wound = 10
diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm
index 3003e9a76ee159..4744296cdb8ee8 100644
--- a/code/modules/clothing/head/soft_caps.dm
+++ b/code/modules/clothing/head/soft_caps.dm
@@ -169,9 +169,11 @@
clothing_flags = SNUG_FIT
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE
dog_fashion = null
+ clothing_traits = list(TRAIT_SCARY_FISHERMAN) //Fish, carps, lobstrosities and frogs fear me.
/obj/item/clothing/head/soft/fishing_hat/Initialize(mapload)
. = ..()
+ AddComponent(/datum/component/speechmod, replacements = strings("crustacean_replacement.json", "crustacean")) //you asked for this.
AddElement(/datum/element/skill_reward, /datum/skill/fishing)
#define PROPHAT_MOOD "prophat"
diff --git a/code/modules/clothing/shoes/boots.dm b/code/modules/clothing/shoes/boots.dm
index dbfa4f8b3c40d6..03f174aa43c315 100644
--- a/code/modules/clothing/shoes/boots.dm
+++ b/code/modules/clothing/shoes/boots.dm
@@ -3,6 +3,7 @@
desc = "High speed, low drag combat boots."
icon_state = "jackboots"
inhand_icon_state = "jackboots"
+ body_parts_covered = FEET|LEGS
armor_type = /datum/armor/shoes_combat
strip_delay = 40
resistance_flags = NONE
@@ -49,6 +50,7 @@
resistance_flags = NONE
armor_type = /datum/armor/shoes_jackboots
can_be_tied = FALSE
+ body_parts_covered = FEET|LEGS
/datum/armor/shoes_jackboots
bio = 90
@@ -108,6 +110,7 @@
strip_delay = 4 SECONDS
equip_delay_other = 4 SECONDS
clothing_flags = THICKMATERIAL
+ body_parts_covered = FEET|LEGS
resistance_flags = NONE
/datum/armor/ice_boots_eva
@@ -177,6 +180,7 @@
strip_delay = 40
resistance_flags = NONE
lace_time = 12 SECONDS
+ body_parts_covered = FEET|LEGS
/datum/armor/shoes_pirate
melee = 25
diff --git a/code/modules/clothing/shoes/cowboy.dm b/code/modules/clothing/shoes/cowboy.dm
index 4295b91cad2f51..ab8ef30c99b60c 100644
--- a/code/modules/clothing/shoes/cowboy.dm
+++ b/code/modules/clothing/shoes/cowboy.dm
@@ -109,3 +109,4 @@
desc = "And they sing, oh, ain't you glad you're single? And that song ain't so very far from wrong."
armor_type = /datum/armor/shoes_combat
has_spurs = TRUE
+ body_parts_covered = FEET|LEGS
diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm
index 246cdfee6f51bc..4b8fe43bd96ee2 100644
--- a/code/modules/clothing/spacesuits/_spacesuits.dm
+++ b/code/modules/clothing/spacesuits/_spacesuits.dm
@@ -24,6 +24,7 @@
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF
resistance_flags = NONE
dog_fashion = null
+ slowdown = 0.5
/datum/armor/helmet_space
bio = 100
@@ -47,7 +48,7 @@
/obj/item/tank/internals,
/obj/item/tank/jetpack/oxygen/captain,
)
- slowdown = 1
+ slowdown = 0.5
armor_type = /datum/armor/suit_space
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDESEXTOY|HIDETAIL|HIDETAUR //SKYRAT EDIT CHANGE - ADDED HIDETAIL, HIDETAUR. ADDED HIDESEXTOY TO PREVENT VISUAL BUGS.
cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS
diff --git a/code/modules/clothing/spacesuits/pirate.dm b/code/modules/clothing/spacesuits/pirate.dm
index ca041d68d036f5..73feec525c5486 100644
--- a/code/modules/clothing/spacesuits/pirate.dm
+++ b/code/modules/clothing/spacesuits/pirate.dm
@@ -3,6 +3,7 @@
desc = "A modified helmet to allow space pirates to intimidate their customers whilst staying safe from the void. Comes with some additional protection."
icon_state = "spacepirate"
inhand_icon_state = "space_pirate_helmet"
+ slowdown = 0
armor_type = /datum/armor/space_pirate
strip_delay = 40
equip_delay_other = 20
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index 63a0dd515c3f67..380cd0cf3fb532 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -118,33 +118,45 @@
. = ..()
if(!up)
. += visor_icon
-
-/obj/item/clothing/head/helmet/space/plasmaman/attackby(obj/item/hitting_item, mob/living/user)
- . = ..()
- if(istype(hitting_item, /obj/item/toy/crayon))
- if(smile == FALSE)
- var/obj/item/toy/crayon/CR = hitting_item
- to_chat(user, span_notice("You start drawing a smiley face on the helmet's visor.."))
- if(do_after(user, 2.5 SECONDS, target = src))
- smile = TRUE
- smile_color = CR.paint_color
- to_chat(user, "You draw a smiley on the helmet visor.")
- update_appearance()
- else
- to_chat(user, span_warning("Seems like someone already drew something on this helmet's visor!"))
- return
- if(istype(hitting_item, /obj/item/clothing/head))
- var/obj/item/clothing/hitting_clothing = hitting_item
- if(hitting_clothing.clothing_flags & STACKABLE_HELMET_EXEMPT)
- to_chat(user, span_notice("You cannot place [hitting_clothing.name] on helmet!"))
- return
- if(attached_hat)
- to_chat(user, span_notice("There's already something placed on helmet!"))
- return
- attached_hat = hitting_clothing
- to_chat(user, span_notice("You placed [hitting_clothing.name] on helmet!"))
- hitting_clothing.forceMove(src)
+ if(smile)
+ var/mutable_appearance/smiley = mutable_appearance(icon, smile_state)
+ smiley.color = smile_color
+ . += smiley
+
+/obj/item/clothing/head/helmet/space/plasmaman/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ if(istype(tool, /obj/item/toy/crayon))
+ if(smile)
+ to_chat(user, span_warning("Seems like someone already drew something on [src]'s visor!"))
+ return ITEM_INTERACT_BLOCKING
+
+ var/obj/item/toy/crayon/crayon = tool
+ to_chat(user, span_notice("You start drawing a smiley face on [src]'s visor..."))
+ if(!do_after(user, 2.5 SECONDS, target = src))
+ return ITEM_INTERACT_BLOCKING
+
+ smile = TRUE
+ smile_color = crayon.paint_color
+ to_chat(user, "You draw a smiley on [src] visor.")
update_appearance()
+ return ITEM_INTERACT_SUCCESS
+
+ if(!istype(tool, /obj/item/clothing/head))
+ return NONE
+
+ var/obj/item/clothing/hitting_clothing = tool
+ if(hitting_clothing.clothing_flags & STACKABLE_HELMET_EXEMPT)
+ to_chat(user, span_notice("You cannot place [hitting_clothing.name] on [src]!"))
+ return ITEM_INTERACT_BLOCKING
+
+ if(attached_hat)
+ to_chat(user, span_notice("There's already something placed on [src]!"))
+ return ITEM_INTERACT_BLOCKING
+
+ attached_hat = hitting_clothing
+ to_chat(user, span_notice("You placed [hitting_clothing.name] on [src]!"))
+ hitting_clothing.forceMove(src)
+ update_appearance()
+ return ITEM_INTERACT_SUCCESS
///By the by, helmets have the update_icon_updates_onmob element, so we don't have to call mob.update_worn_head()
/obj/item/clothing/head/helmet/space/plasmaman/worn_overlays(mutable_appearance/standing, isinhands)
diff --git a/code/modules/clothing/spacesuits/santa.dm b/code/modules/clothing/spacesuits/santa.dm
index 138f52e046e471..f6bd1657606c52 100644
--- a/code/modules/clothing/spacesuits/santa.dm
+++ b/code/modules/clothing/spacesuits/santa.dm
@@ -7,6 +7,7 @@
inhand_icon_state = "santahat"
flags_cover = HEADCOVERSEYES
dog_fashion = /datum/dog_fashion/head/santa
+ slowdown = 0
/obj/item/clothing/head/helmet/space/santahat/beardless
icon = 'icons/obj/clothing/head/costume.dmi'
@@ -14,6 +15,7 @@
icon_state = "santahatnorm"
inhand_icon_state = "that"
flags_inv = NONE
+ slowdown = 0
/obj/item/clothing/suit/space/santa
name = "Santa's suit"
diff --git a/code/modules/clothing/spacesuits/softsuit.dm b/code/modules/clothing/spacesuits/softsuit.dm
index 510c9e7056f2fd..0b644286063ecf 100644
--- a/code/modules/clothing/spacesuits/softsuit.dm
+++ b/code/modules/clothing/spacesuits/softsuit.dm
@@ -16,13 +16,14 @@
name = "Engineering Void Helmet"
desc = "A CentCom engineering dark red space suit helmet. While old and dusty, it still gets the job done."
icon_state = "void"
+ slowdown = 2
/obj/item/clothing/suit/space/nasavoid/old
name = "Engineering Voidsuit"
icon_state = "void"
inhand_icon_state = "void_suit"
desc = "A CentCom engineering dark red space suit. Age has degraded the suit making it difficult to move around in."
- slowdown = 4
+ slowdown = 2
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/multitool)
//EVA suit
@@ -72,6 +73,7 @@
inhand_icon_state = "syndicate-helm-orange" //resprite?
armor_type = /datum/armor/space_fragile
strip_delay = 65
+ slowdown = 1
/obj/item/clothing/suit/space/fragile
name = "emergency space suit"
@@ -79,7 +81,7 @@
var/torn = FALSE
icon_state = "syndicate-orange"
inhand_icon_state = "syndicate-orange"
- slowdown = 2
+ slowdown = 1
armor_type = /datum/armor/space_fragile
strip_delay = 65
diff --git a/code/modules/clothing/spacesuits/specialops.dm b/code/modules/clothing/spacesuits/specialops.dm
index cf8fc2a475cc69..caaa32cc24be25 100644
--- a/code/modules/clothing/spacesuits/specialops.dm
+++ b/code/modules/clothing/spacesuits/specialops.dm
@@ -7,6 +7,7 @@
inhand_icon_state = null
greyscale_colors = "#397F3F#FFCE5B"
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT
+ slowdown = 0
flags_inv = 0
armor_type = /datum/armor/space_beret
strip_delay = 130
diff --git a/code/modules/clothing/suits/ablativecoat.dm b/code/modules/clothing/suits/ablativecoat.dm
index 8bc37aaba22b76..32233f23400cc5 100644
--- a/code/modules/clothing/suits/ablativecoat.dm
+++ b/code/modules/clothing/suits/ablativecoat.dm
@@ -50,15 +50,11 @@
/obj/item/clothing/suit/hooded/ablative/on_hood_up(obj/item/clothing/head/hooded/hood)
. = ..()
var/mob/living/carbon/user = loc
- var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_SECURITY_ADVANCED]
ADD_TRAIT(user, TRAIT_SECURITY_HUD, HELMET_TRAIT)
- hud.show_to(user)
balloon_alert(user, "hud enabled")
/obj/item/clothing/suit/hooded/ablative/on_hood_down(obj/item/clothing/head/hooded/hood)
var/mob/living/carbon/user = loc
- var/datum/atom_hud/sec_hud = GLOB.huds[DATA_HUD_SECURITY_ADVANCED]
REMOVE_TRAIT(user, TRAIT_SECURITY_HUD, HELMET_TRAIT)
- sec_hud.hide_from(user)
balloon_alert(user, "hud disabled")
return ..()
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index 9c34574840d798..0d33f0e5f5117f 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -738,3 +738,113 @@
fire = 50
acid = 50
wound = 30
+
+/obj/item/clothing/suit/armor/durability/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
+ take_damage(1, BRUTE, 0, 0)
+
+/obj/item/clothing/suit/armor/durability/watermelon
+ name = "watermelon"
+ desc = "An armour, made from watermelons. Propably won't take too many hits, but at least it looks serious... As serious as worn watermelon can be."
+ icon_state = "watermelon"
+ inhand_icon_state = null
+ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ armor_type = /datum/armor/watermelon
+ strip_delay = 60
+ equip_delay_other = 40
+ clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED)
+ max_integrity = 15
+
+/obj/item/clothing/suit/armor/durability/watermelon/fire_resist
+ resistance_flags = FIRE_PROOF
+ armor_type = /datum/armor/watermelon_fr
+
+/datum/armor/watermelon
+ melee = 15
+ bullet = 10
+ energy = 10
+ bomb = 10
+ fire = 0
+ acid = 25
+ wound = 5
+
+/datum/armor/watermelon_fr
+ melee = 15
+ bullet = 10
+ energy = 10
+ bomb = 10
+ fire = 15
+ acid = 30
+ wound = 5
+
+/obj/item/clothing/suit/armor/durability/holymelon
+ name = "holymelon"
+ desc = "An armour, made from holymelons. Inspires you to go on some sort of a crusade... Perhaps spreading spinach to children?"
+ icon_state = "holymelon"
+ inhand_icon_state = null
+ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ armor_type = /datum/armor/watermelon
+ strip_delay = 60
+ equip_delay_other = 40
+ clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED)
+ max_integrity = 15
+ var/decayed = FALSE
+
+/obj/item/clothing/suit/armor/durability/holymelon/fire_resist
+ resistance_flags = FIRE_PROOF
+ armor_type = /datum/armor/watermelon_fr
+
+/obj/item/clothing/suit/armor/durability/holymelon/Initialize(mapload)
+ . = ..()
+ if(decayed)
+ decay()
+ return
+
+ AddComponent(
+ /datum/component/anti_magic, \
+ antimagic_flags = MAGIC_RESISTANCE_HOLY, \
+ inventory_flags = ITEM_SLOT_OCLOTHING, \
+ charges = 1, \
+ drain_antimagic = CALLBACK(src, PROC_REF(drain_antimagic)), \
+ expiration = CALLBACK(src, PROC_REF(decay)) \
+ )
+
+/obj/item/clothing/suit/armor/durability/holymelon/proc/drain_antimagic(mob/user)
+ to_chat(user, span_warning("[src] looses a bit of its shimmer and glossiness..."))
+
+/obj/item/clothing/suit/armor/durability/holymelon/proc/decay()
+ take_damage(8, BRUTE, 0, 0)
+
+
+/obj/item/clothing/suit/armor/durability/barrelmelon
+ name = "barrelmelon"
+ desc = "An armour, made from barrelmelons. Reeks of ale, inspiring to courageous deeds. Or, perhaps, a bar brawl."
+ icon_state = "barrelmelon"
+ inhand_icon_state = null
+ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ armor_type = /datum/armor/barrelmelon
+ strip_delay = 60
+ equip_delay_other = 40
+ clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED)
+ max_integrity = 10
+
+/obj/item/clothing/suit/armor/durability/barrelmelon/fire_resist
+ resistance_flags = FIRE_PROOF
+ armor_type = /datum/armor/barrelmelon_fr
+
+/datum/armor/barrelmelon
+ melee = 25
+ bullet = 20
+ energy = 15
+ bomb = 10
+ fire = 0
+ acid = 35
+ wound = 10
+
+/datum/armor/barrelmelon_fr
+ melee = 25
+ bullet = 20
+ energy = 15
+ bomb = 10
+ fire = 20
+ acid = 40
+ wound = 10
diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm
index d211b3cc91edf8..cc94b200969bad 100644
--- a/code/modules/clothing/suits/jobs.dm
+++ b/code/modules/clothing/suits/jobs.dm
@@ -225,6 +225,10 @@
blood_overlay_type = "coat"
body_parts_covered = CHEST|ARMS
allowed = list(
+ /obj/item/tank/internals/emergency_oxygen,
+ /obj/item/tank/internals/plasmaman,
+ /obj/item/boxcutter,
+ /obj/item/dest_tagger,
/obj/item/stamp,
/obj/item/storage/bag/mail,
/obj/item/universal_scanner,
diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm
index eb1ccb3c51092b..53026e974bf63a 100644
--- a/code/modules/clothing/suits/wiz_robe.dm
+++ b/code/modules/clothing/suits/wiz_robe.dm
@@ -49,6 +49,17 @@
resistance_flags = FLAMMABLE
dog_fashion = /datum/dog_fashion/head/blue_wizard
+/obj/item/clothing/head/wizard/chanterelle
+ name = "chanterelle hat"
+ desc = "An oversized chanterelle with hollow out space to fit a head in. Kinda looks like wizard's hat."
+ icon_state = "chanterelle"
+ inhand_icon_state = "chanterellehat"
+ armor_type = /datum/armor/none
+ resistance_flags = FLAMMABLE
+
+/obj/item/clothing/head/wizard/chanterelle/fr
+ resistance_flags = FIRE_PROOF
+
/obj/item/clothing/head/wizard/marisa
name = "witch hat"
desc = "Strange-looking hat-wear. Makes you want to cast fireballs."
@@ -205,6 +216,63 @@
actions_types = list(/datum/action/item_action/stickmen)
+/obj/item/clothing/suit/wizrobe/durathread
+ name = "durathread robe"
+ desc = "A rather dull durathread robe; not quite as protective as a proper piece of armour, but much stylish."
+ icon_state = "durathread-fake"
+ inhand_icon_state = null
+ armor_type = /datum/armor/robe_durathread
+ allowed = list(
+ /obj/item/cultivator,
+ /obj/item/geneshears,
+ /obj/item/graft,
+ /obj/item/hatchet,
+ /obj/item/plant_analyzer,
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/reagent_containers/cup/bottle,
+ /obj/item/reagent_containers/cup/tube,
+ /obj/item/reagent_containers/spray/pestspray,
+ /obj/item/reagent_containers/spray/plantbgone,
+ /obj/item/secateurs,
+ /obj/item/seeds,
+ /obj/item/storage/bag/plants,
+ )
+
+/datum/armor/robe_durathread
+ melee = 15
+ bullet = 5
+ laser = 25
+ energy = 30
+ bomb = 10
+ fire = 30
+ acid = 40
+
+/obj/item/clothing/suit/wizrobe/durathread/fire
+ name = "pyromancer robe"
+ desc = "A rather dull durathread robe; not quite as protective as an woven armour, but much stylish."
+ icon_state = "durathread-fire"
+
+/obj/item/clothing/suit/wizrobe/durathread/ice
+ name = "pyromancer robe"
+ desc = "A rather dull durathread robe; not quite as protective as an woven armour, but much stylish."
+ icon_state = "durathread-ice"
+
+/obj/item/clothing/suit/wizrobe/durathread/electric
+ name = "electromancer robe"
+ desc = "Doesn't actually conduit or isolate from electricity. Though it does have some durability on account of being made from durathread."
+ icon_state = "durathread-electric"
+
+/obj/item/clothing/suit/wizrobe/durathread/earth
+ name = "geomancer robe"
+ desc = "A rather dull durathread robe; not quite as protective as an woven armour, but much stylish."
+ icon_state = "durathread-earth"
+
+/obj/item/clothing/suit/wizrobe/durathread/necro
+ name = "necromancer robe"
+ desc = "A rather dull durathread robe; not quite as protective as an woven armour, but much stylish."
+ icon_state = "durathread-necro"
+
+
/obj/item/clothing/suit/wizrobe/paper/ui_action_click(mob/user, action)
stickmen()
diff --git a/code/modules/clothing/under/accessories/_accessories.dm b/code/modules/clothing/under/accessories/_accessories.dm
index 91854bc386bf09..5b25418838ab68 100644
--- a/code/modules/clothing/under/accessories/_accessories.dm
+++ b/code/modules/clothing/under/accessories/_accessories.dm
@@ -89,7 +89,7 @@
atom_storage.close_all()
attach_to.clone_storage(atom_storage)
attach_to.atom_storage.set_real_location(src)
- attach_to.atom_storage.rustle_sound = TRUE // it's on the suit now
+ attach_to.atom_storage.do_rustle = TRUE // it's on the suit now
var/num_other_accessories = LAZYLEN(attach_to.attached_accessories)
layer = FLOAT_LAYER + clamp(attach_to.max_number_of_accessories - num_other_accessories, 0, 10)
diff --git a/code/modules/deathmatch/deathmatch_maps.dm b/code/modules/deathmatch/deathmatch_maps.dm
index 6a8a245abb7956..078555e05accb3 100644
--- a/code/modules/deathmatch/deathmatch_maps.dm
+++ b/code/modules/deathmatch/deathmatch_maps.dm
@@ -1,6 +1,7 @@
-/datum/lazy_template/deathmatch //deathmatch maps that have any possibility of the walls being destroyed should use indestructible walls, because baseturf moment
+/datum/lazy_template/deathmatch
map_dir = "_maps/deathmatch"
place_on_top = TRUE
+ turf_reservation_type = /datum/turf_reservation/turf_not_baseturf
/// Map UI Name
var/name
/// Map Description
diff --git a/code/modules/events/aurora_caelus.dm b/code/modules/events/aurora_caelus.dm
index 0acb0ad9781a7b..875b8c0dcf23a5 100644
--- a/code/modules/events/aurora_caelus.dm
+++ b/code/modules/events/aurora_caelus.dm
@@ -17,10 +17,12 @@
start_when = 21
end_when = 80
-/datum/round_event/aurora_caelus/announce()
+/datum/round_event/aurora_caelus/announce(fake)
priority_announce("[station_name()]: A harmless cloud of ions is approaching your station, and will exhaust their energy battering the hull. Nanotrasen has approved a short break for all employees to relax and observe this very rare event. During this time, starlight will be bright but gentle, shifting between quiet green and blue colors. Any staff who would like to view these lights for themselves may proceed to the area nearest to them with viewing ports to open space. We hope you enjoy the lights.",
sound = 'sound/misc/notice2.ogg',
sender_override = "Nanotrasen Meteorology Division")
+ if (fake)
+ return
for(var/V in GLOB.player_list)
var/mob/M = V
if((M.client.prefs.read_preference(/datum/preference/toggle/sound_midi)) && is_station_level(M.z))
@@ -31,6 +33,8 @@
/datum/round_event/aurora_caelus/start()
if(!prob(1) && !check_holidays(APRIL_FOOLS))
return
+
+ var/list/human_blacklist = list()
for(var/area/station/service/kitchen/affected_area in GLOB.areas)
var/obj/machinery/oven/roast_ruiner = locate() in affected_area
if(roast_ruiner)
@@ -40,10 +44,13 @@
message_admins("Aurora Caelus event caused an oven to ignite at [ADMIN_VERBOSEJMP(ruined_roast)].")
log_game("Aurora Caelus event caused an oven to ignite at [loc_name(ruined_roast)].")
announce_to_ghosts(roast_ruiner)
- for(var/mob/living/carbon/human/seymour as anything in GLOB.human_list)
- if(seymour.mind && istype(seymour.mind.assigned_role, /datum/job/cook))
- seymour.say("My roast is ruined!!!", forced = "ruined roast")
- seymour.emote("scream")
+ for(var/mob/living/carbon/human/seymour in viewers(roast_ruiner, 7))
+ if (seymour in human_blacklist)
+ continue
+ human_blacklist += seymour
+ if(seymour.mind && istype(seymour.mind.assigned_role, /datum/job/cook))
+ seymour.say("My roast is ruined!!!", forced = "ruined roast")
+ seymour.emote("scream")
/datum/round_event/aurora_caelus/tick()
if(activeFor % 8 != 0)
diff --git a/code/modules/events/ghost_role/sentience.dm b/code/modules/events/ghost_role/sentience.dm
index 4017361dba51a3..092813008458ac 100644
--- a/code/modules/events/ghost_role/sentience.dm
+++ b/code/modules/events/ghost_role/sentience.dm
@@ -3,6 +3,7 @@ GLOBAL_LIST_INIT(high_priority_sentience, typecacheof(list(
/mob/living/basic/butterfly,
/mob/living/basic/carp/pet/cayenne,
/mob/living/basic/chicken,
+ /mob/living/basic/crab,
/mob/living/basic/cow,
/mob/living/basic/goat,
/mob/living/basic/lizard,
@@ -18,6 +19,7 @@ GLOBAL_LIST_INIT(high_priority_sentience, typecacheof(list(
/mob/living/simple_animal/bot/secbot/beepsky,
/mob/living/simple_animal/hostile/retaliate/goose/vomit,
/mob/living/basic/bear/snow/misha,
+ /mob/living/basic/mining/lobstrosity/juvenile,
)))
/datum/round_event_control/sentience
diff --git a/code/modules/events/space_vines/vine_event.dm b/code/modules/events/space_vines/vine_event.dm
index 03350abdb0967c..ce9881c9907972 100644
--- a/code/modules/events/space_vines/vine_event.dm
+++ b/code/modules/events/space_vines/vine_event.dm
@@ -39,7 +39,7 @@
for(var/area/station/hallway/area in GLOB.areas)
for(var/turf/open/floor in area.get_turfs_from_all_zlevels())
- if(floor.Enter(vine))
+ if(!isopenspaceturf(floor) && floor.Enter(vine))
turfs += floor
qdel(vine)
diff --git a/code/modules/events/stray_cargo.dm b/code/modules/events/stray_cargo.dm
index 274d45aa7ca8c5..0be1138f59a591 100644
--- a/code/modules/events/stray_cargo.dm
+++ b/code/modules/events/stray_cargo.dm
@@ -183,5 +183,5 @@
///Apply the syndicate pod skin
/datum/round_event/stray_cargo/syndicate/make_pod()
var/obj/structure/closet/supplypod/S = new
- S.setStyle(STYLE_SYNDICATE)
+ S.setStyle(/datum/pod_style/syndicate)
return S
diff --git a/code/modules/fishing/admin.dm b/code/modules/fishing/admin.dm
index 0a9cfc9d51dd99..ba5c29a7fd1729 100644
--- a/code/modules/fishing/admin.dm
+++ b/code/modules/fishing/admin.dm
@@ -48,7 +48,7 @@ ADMIN_VERB(fishing_calculator, R_DEBUG, "Fishing Calculator", "A calculator... f
if(hook_type)
temporary_rod.set_slot(new hook_type(temporary_rod), ROD_SLOT_HOOK)
if(line_type)
- temporary_rod.set_slot(new line_type(temporary_rod), ROD_SLOT_HOOK)
+ temporary_rod.set_slot(new line_type(temporary_rod), ROD_SLOT_LINE)
var/result_table = list()
var/modified_table = spot.get_modified_fish_table(temporary_rod,user)
diff --git a/code/modules/fishing/aquarium/aquarium.dm b/code/modules/fishing/aquarium/aquarium.dm
index 97ce717b4c5247..5afbf4b72d9a94 100644
--- a/code/modules/fishing/aquarium/aquarium.dm
+++ b/code/modules/fishing/aquarium/aquarium.dm
@@ -13,7 +13,7 @@
name = "aquarium"
desc = "A vivarium in which aquatic fauna and flora are usually kept and displayed."
density = TRUE
- anchored = TRUE
+ anchored = FALSE
icon = 'icons/obj/aquarium/tanks.dmi'
icon_state = "aquarium_map"
@@ -35,13 +35,13 @@
var/last_feeding
/// Can fish reproduce in this quarium.
- var/allow_breeding = FALSE
+ var/allow_breeding = TRUE
//This is the area where fish can swim
var/aquarium_zone_min_px = 2
var/aquarium_zone_max_px = 31
var/aquarium_zone_min_py = 10
- var/aquarium_zone_max_py = 24
+ var/aquarium_zone_max_py = 28
var/list/fluid_types = list(AQUARIUM_FLUID_SALTWATER, AQUARIUM_FLUID_FRESHWATER, AQUARIUM_FLUID_SULPHWATEVER, AQUARIUM_FLUID_AIR)
@@ -64,7 +64,7 @@
RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_attacked))
create_reagents(6, SEALED_CONTAINER)
RegisterSignal(reagents, COMSIG_REAGENTS_NEW_REAGENT, PROC_REF(start_autofeed))
- AddComponent(/datum/component/plumbing/aquarium)
+ AddComponent(/datum/component/plumbing/aquarium, start = anchored)
if(current_beauty)
AddElement(/datum/element/beauty, current_beauty)
ADD_KEEP_TOGETHER(src, INNATE_TRAIT)
@@ -390,6 +390,9 @@
#undef AQUARIUM_BORDERS_LAYER
#undef AQUARIUM_BELOW_GLASS_LAYER
+/obj/structure/aquarium/lawyer
+ anchored = TRUE
+
/obj/structure/aquarium/lawyer/Initialize(mapload)
. = ..()
@@ -400,6 +403,9 @@
reagents.add_reagent(/datum/reagent/consumable/nutriment, 2)
+/obj/structure/aquarium/prefilled
+ anchored = TRUE
+
/obj/structure/aquarium/prefilled/Initialize(mapload)
. = ..()
diff --git a/code/modules/fishing/aquarium/aquarium_kit.dm b/code/modules/fishing/aquarium/aquarium_kit.dm
index 1161648f7d15f1..fcb3d90f9f9104 100644
--- a/code/modules/fishing/aquarium/aquarium_kit.dm
+++ b/code/modules/fishing/aquarium/aquarium_kit.dm
@@ -21,15 +21,15 @@
desc = "A resizable case keeping the fish inside in stasis."
icon = 'icons/obj/storage/case.dmi'
icon_state = "fishbox"
-
+ w_class = WEIGHT_CLASS_SMALL
inhand_icon_state = "syringe_kit"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
- storage_type = /datum/storage/fish_case
+ storage_type = /datum/storage/fish_case/adjust_size
/obj/item/storage/fish_case/Initialize(mapload)
- ADD_TRAIT(src, TRAIT_FISH_SAFE_STORAGE, TRAIT_GENERIC) // Before populate so fish instatiates in ready container already
- return ..()
+ . = ..()
+ AddElement(/datum/element/fish_safe_storage)
/obj/item/storage/fish_case/PopulateContents()
var/fish_type = get_fish_type()
@@ -91,6 +91,13 @@
for(var/obj/item/fish/fish as anything in contents)
fish.set_status(FISH_DEAD)
+/obj/item/storage/fish_case/bluespace
+ name = "bluespace fish case"
+ icon_state = "fishbox_bluespace"
+ desc = "An improved fish case to keep large fish in stasis in a compact little space."
+ w_class = WEIGHT_CLASS_NORMAL
+ storage_type = /datum/storage/fish_case
+
/obj/item/aquarium_kit
name = "DIY Aquarium Construction Kit"
desc = "Everything you need to build your own aquarium. Raw materials sold separately."
@@ -109,6 +116,7 @@
icon = 'icons/obj/aquarium/supplies.dmi'
w_class = WEIGHT_CLASS_TINY
+ custom_materials = list(/datum/material/plastic = COIN_MATERIAL_AMOUNT)
var/layer_mode = AQUARIUM_LAYER_MODE_BOTTOM
var/beauty = 150
@@ -117,32 +125,37 @@
AddComponent(/datum/component/aquarium_content, icon, beauty = beauty)
/obj/item/aquarium_prop/rocks
- name = "rocks"
+ name = "decorative rocks"
+ desc = "A bunch of tiny plastic rocks for decorating an aquarium. Surely you could have just used real pebbles?"
icon_state = "rocks"
-/obj/item/aquarium_prop/seaweed_top
- name = "dense seaweeds"
- icon_state = "seaweeds_front"
- layer_mode = AQUARIUM_LAYER_MODE_TOP
-
/obj/item/aquarium_prop/seaweed
- name = "seaweeds"
+ name = "fake seaweed"
+ desc = "Little plastic sheets with weighted bottoms, designed to look like underwater foliage. They can be used to spruce up an aquarium."
icon_state = "seaweeds_back"
layer_mode = AQUARIUM_LAYER_MODE_BOTTOM
+/obj/item/aquarium_prop/seaweed/top
+ desc = "A bunch of artificial plants for an aquarium."
+ icon_state = "seaweeds_front"
+ layer_mode = AQUARIUM_LAYER_MODE_TOP
+
/obj/item/aquarium_prop/sand
name = "aquarium sand"
+ desc = "A plastic board for lining the bottom of an aquarium. It's got a bumpy patterned surface vaguely reminiscent of yellow sand."
icon_state = "sand"
layer_mode = AQUARIUM_LAYER_MODE_BEHIND_GLASS
/obj/item/aquarium_prop/treasure
name = "tiny treasure chest"
+ desc = "A very small plastic treaure chest, with nothing inside. You could put this in an aquarium, and it'll look like very small pirates hid treasure in there. Wouldn't that be nice?"
icon_state = "treasure"
layer_mode = AQUARIUM_LAYER_MODE_BOTTOM
/obj/item/storage/box/aquarium_props
name = "aquarium props box"
desc = "All you need to make your aquarium look good."
+ illustration = "fish"
/obj/item/storage/box/aquarium_props/PopulateContents()
for(var/prop_type in subtypesof(/obj/item/aquarium_prop))
diff --git a/code/modules/fishing/aquarium/fish_analyzer.dm b/code/modules/fishing/aquarium/fish_analyzer.dm
index f59f1901b8563f..3d01479ef5a2f7 100644
--- a/code/modules/fishing/aquarium/fish_analyzer.dm
+++ b/code/modules/fishing/aquarium/fish_analyzer.dm
@@ -65,6 +65,7 @@
if(isfish(target) || istype(target, /obj/structure/aquarium))
scanned_item = WEAKREF(target)
+ SEND_SIGNAL(src, COMSIG_FISH_ANALYZER_ANALYZE_STATUS, target, user)
ui_interact(user)
return ITEM_INTERACT_SUCCESS
diff --git a/code/modules/fishing/bait.dm b/code/modules/fishing/bait.dm
index b67298fab9fea8..78d18aa539e8df 100644
--- a/code/modules/fishing/bait.dm
+++ b/code/modules/fishing/bait.dm
@@ -3,13 +3,16 @@
desc = "there's a lot of them in there, getting them out takes a while though"
icon = 'icons/obj/fishing.dmi'
icon_state = "bait_can"
+ base_icon_state = "bait_can"
w_class = WEIGHT_CLASS_SMALL
/// Tracking until we can take out another bait item
COOLDOWN_DECLARE(bait_removal_cooldown)
/// What bait item it produces
- var/bait_type
+ var/obj/item/bait_type = /obj/item/food/bait
/// Time between bait retrievals
- var/cooldown_time = 10 SECONDS
+ var/cooldown_time = 5 SECONDS
+ /// How many uses does it have left.
+ var/uses_left = 20
/obj/item/bait_can/attack_self(mob/user, modifiers)
. = ..()
@@ -17,19 +20,44 @@
if(fresh_bait)
user.put_in_hands(fresh_bait)
+/obj/item/bait_can/examine(mob/user)
+ . = ..()
+ . += span_info("It[uses_left ? " has got [uses_left] [bait_type::name] left" : "'s empty"].")
+
+/obj/item/bait_can/update_icon_state()
+ . = ..()
+ icon_state = base_icon_state
+ if(uses_left <= initial(uses_left))
+ if(!uses_left)
+ icon_state = "[icon_state]_empty"
+ else
+ icon_state = "[icon_state]_open"
+
/obj/item/bait_can/proc/retrieve_bait(mob/user)
+ if(!uses_left)
+ user.balloon_alert(user, "empty")
+ return
if(!COOLDOWN_FINISHED(src, bait_removal_cooldown))
- user.balloon_alert(user, "wait a bit") //I can't think of generic ic reason.
+ user.balloon_alert(user, "wait a bit")
return
COOLDOWN_START(src, bait_removal_cooldown, cooldown_time)
+ update_appearance()
+ uses_left--
return new bait_type(src)
/obj/item/bait_can/worm
name = "can o' worm"
- desc = "this can got worms."
+ desc = "This can got worms."
bait_type = /obj/item/food/bait/worm
/obj/item/bait_can/worm/premium
name = "can o' worm deluxe"
- desc = "this can got fancy worms."
+ desc = "This can got fancy worms."
bait_type = /obj/item/food/bait/worm/premium
+
+/obj/item/bait_can/super_baits
+ name = "can o' super-baits"
+ desc = "This can got the nectar of god."
+ bait_type = /obj/item/food/bait/doughball/synthetic/super
+ uses_left = 12
+
diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm
index 081f794029041c..509215e350766e 100644
--- a/code/modules/fishing/fish/_fish.dm
+++ b/code/modules/fishing/fish/_fish.dm
@@ -85,10 +85,6 @@
/// The species' name(s) of the parents of the fish. Shown by the fish analyzer.
var/progenitors
- var/flopping = FALSE
-
- var/in_stasis = FALSE
-
// Fishing related properties
/**
@@ -190,9 +186,21 @@
/obj/item/fish/examine(mob/user)
. = ..()
- // All spacemen have magic eyes of fish weight perception until fish scale (get it?) is implemented.
- . += span_notice("It's [size] cm long.")
- . += span_notice("It weighs [weight] g.")
+ if(HAS_MIND_TRAIT(user, TRAIT_EXAMINE_DEEPER_FISH))
+ if(status == FISH_DEAD)
+ . += span_deadsay("it's dead.")
+ var/list/warnings = list()
+ if(is_hungry())
+ warnings += "starving"
+ if(!HAS_TRAIT(src, TRAIT_FISH_STASIS) && !proper_environment())
+ warnings += "drowning"
+ if(health < initial(health) * 0.6)
+ warnings += "sick"
+ if(length(warnings))
+ . += span_warning("it's [english_list(warnings)]")
+ if(HAS_MIND_TRAIT(user, TRAIT_EXAMINE_FISH))
+ . += span_notice("It's [size] cm long.")
+ . += span_notice("It weighs [weight] g.")
///Randomizes weight and size.
/obj/item/fish/proc/randomize_size_and_weight(base_size = average_size, base_weight = average_weight, deviation = 0.2)
@@ -306,13 +314,13 @@
check_environment()
/obj/item/fish/proc/enter_stasis()
- in_stasis = TRUE
+ ADD_TRAIT(src, TRAIT_FISH_STASIS, INNATE_TRAIT)
// Stop processing until inserted into aquarium again.
stop_flopping()
STOP_PROCESSING(SSobj, src)
/obj/item/fish/proc/exit_stasis()
- in_stasis = FALSE
+ REMOVE_TRAIT(src, TRAIT_FISH_STASIS, INNATE_TRAIT)
if(status != FISH_DEAD)
START_PROCESSING(SSobj, src)
@@ -332,15 +340,9 @@
fed_reagents.remove_reagent(fed_reagent_type, 0.1)
SEND_SIGNAL(src, COMSIG_FISH_FED, fed_reagents, fed_reagent_type)
-/obj/item/fish/proc/check_environment(stasis_check = TRUE)
+/obj/item/fish/proc/check_environment()
if(QDELETED(src)) //we don't care anymore
return
- if(stasis_check)
- // Apply/remove stasis as needed
- if(loc && HAS_TRAIT(loc, TRAIT_FISH_SAFE_STORAGE))
- enter_stasis()
- else if(in_stasis)
- exit_stasis()
if(!do_flop_animation)
return
@@ -348,7 +350,7 @@
// Do additional stuff
var/in_aquarium = isaquarium(loc)
// Start flopping if outside of fish container
- var/should_be_flopping = status == FISH_ALIVE && loc && !HAS_TRAIT(loc,TRAIT_FISH_SAFE_STORAGE) && !in_aquarium
+ var/should_be_flopping = status == FISH_ALIVE && !HAS_TRAIT(src, TRAIT_FISH_STASIS) && !in_aquarium
if(should_be_flopping)
start_flopping()
@@ -356,7 +358,7 @@
stop_flopping()
/obj/item/fish/process(seconds_per_tick)
- if(in_stasis || status != FISH_ALIVE)
+ if(HAS_TRAIT(src, TRAIT_FISH_STASIS) || status != FISH_ALIVE)
return
process_health(seconds_per_tick)
@@ -376,7 +378,7 @@
status = FISH_ALIVE
health = initial(health) // since the fishe has been revived
last_feeding = world.time //reset hunger
- check_environment(FALSE)
+ check_environment()
START_PROCESSING(SSobj, src)
if(FISH_DEAD)
status = FISH_DEAD
@@ -390,6 +392,20 @@
update_appearance()
SEND_SIGNAL(src, COMSIG_FISH_STATUS_CHANGED)
+/obj/item/fish/expose_reagents(list/reagents, datum/reagents/source, methods = TOUCH, volume_modifier = 1, show_message = TRUE)
+ . = ..()
+ if(. & COMPONENT_NO_EXPOSE_REAGENTS || status != FISH_DEAD)
+ return
+ var/datum/reagent/medicine/strange_reagent/revival = locate() in reagents
+ if(!revival)
+ return
+ if(reagents[revival] >= 2 * w_class)
+ set_status(FISH_ALIVE)
+ else
+ balloon_alert_to_viewers("twitches for a moment!")
+ animate(src, pixel_x = 1, time = 0.1 SECONDS, loop = 2, flags = ANIMATION_RELATIVE|ANIMATION_PARALLEL)
+ animate(pixel_x = -1, flags = ANIMATION_RELATIVE)
+
/obj/item/fish/proc/use_lazarus(datum/source, obj/item/lazarus_injector/injector, mob/user)
SIGNAL_HANDLER
if(injector.revive_type != SENTIENCE_ORGANIC)
@@ -594,15 +610,15 @@
/// Starts flopping animation
/obj/item/fish/proc/start_flopping()
- if(flopping) //Requires update_transform/animate_wrappers to be less restrictive.
+ if(HAS_TRAIT(src, TRAIT_FISH_FLOPPING)) //Requires update_transform/animate_wrappers to be less restrictive.
return
- flopping = TRUE
+ ADD_TRAIT(src, TRAIT_FISH_FLOPPING, TRAIT_GENERIC)
flop_animation()
/// Stops flopping animation
/obj/item/fish/proc/stop_flopping()
- if(flopping)
- flopping = FALSE
+ if(HAS_TRAIT(src, TRAIT_FISH_FLOPPING))
+ REMOVE_TRAIT(src, TRAIT_FISH_FLOPPING, TRAIT_GENERIC)
animate(src, transform = matrix()) //stop animation
/// Refreshes flopping animation after temporary animation finishes
@@ -611,7 +627,7 @@
addtimer(CALLBACK(src, PROC_REF(refresh_flopping)), animation_duration)
/obj/item/fish/proc/refresh_flopping()
- if(flopping)
+ if(HAS_TRAIT(src, TRAIT_FISH_FLOPPING))
flop_animation()
/obj/item/fish/proc/try_electrogenesis()
@@ -627,6 +643,14 @@
fish_zap_flags |= (ZAP_GENERATES_POWER | ZAP_MOB_STUN)
tesla_zap(source = get_turf(src), zap_range = fish_zap_range, power = fish_zap_power, cutoff = 1 MEGA JOULES, zap_flags = fish_zap_flags)
+///Returns the price of this fish, for the fish export.
+/obj/item/fish/proc/get_export_price(price, percent)
+ var/size_weight_exponentation = (size * weight * 0.01)^0.85
+ var/calculated_price = price + size_weight_exponentation * percent
+ if(HAS_TRAIT(src, TRAIT_FISH_FROM_CASE)) //Avoid printing money by simply ordering fish and sending it back.
+ calculated_price *= 0.05
+ return round(calculated_price)
+
/// Returns random fish, using random_case_rarity probabilities.
/proc/random_fish_type(required_fluid)
var/static/probability_table
diff --git a/code/modules/fishing/fish/fish_types.dm b/code/modules/fishing/fish/fish_types.dm
index 91c7bba5f3d9e3..ce9f36f0553d65 100644
--- a/code/modules/fishing/fish/fish_types.dm
+++ b/code/modules/fishing/fish/fish_types.dm
@@ -81,6 +81,55 @@
required_temperature_max = MIN_AQUARIUM_TEMP+30
beauty = FISH_BEAUTY_GOOD
+/obj/item/fish/tadpole
+ name = "tadpole"
+ desc = "The larval spawn of an amphibian. A very minuscle, round creature with a long tail it uses to swim around."
+ icon_state = "tadpole"
+ dedicated_in_aquarium_icon_state = "tadpole small"
+ average_size = 3
+ average_weight = 10
+ sprite_width = 3
+ sprite_height = 1
+ health = 50
+ feeding_frequency = 1.5 MINUTES
+ required_temperature_min = MIN_AQUARIUM_TEMP+15
+ required_temperature_max = MIN_AQUARIUM_TEMP+20
+ fillet_type = null
+ fish_traits = list(/datum/fish_trait/no_mating) //They grow into frogs and that's it.
+ beauty = FISH_BEAUTY_NULL
+ random_case_rarity = FISH_RARITY_NOPE //Why would you want generic frog tadpoles you get from ponds inside fish cases?
+ /// Once dead, tadpoles disappear after a dozen seconds, since you can get infinite tadpoles.
+ var/del_timerid
+
+/obj/item/fish/tadpole/Initialize(mapload, apply_qualities = TRUE)
+ . = ..()
+ AddComponent(/datum/component/fish_growth, /mob/living/basic/frog, 100 / rand(2.5, 3 MINUTES) * 10)
+ RegisterSignal(src, COMSIG_FISH_BEFORE_GROWING, PROC_REF(growth_checks))
+ RegisterSignal(src, COMSIG_FISH_FINISH_GROWING, PROC_REF(on_growth))
+
+/obj/item/fish/tadpole/set_status(new_status)
+ . = ..()
+ if(status == FISH_DEAD)
+ del_timerid = QDEL_IN_STOPPABLE(src, 12 SECONDS)
+ else
+ deltimer(del_timerid)
+
+/obj/item/fish/tadpole/proc/growth_checks(datum/source, seconds_per_tick)
+ SIGNAL_HANDLER
+ var/hunger = CLAMP01((world.time - last_feeding) / feeding_frequency)
+ if(hunger >= 0.7) //too hungry to grow
+ return COMPONENT_DONT_GROW
+ var/obj/structure/aquarium/aquarium = loc
+ if(!aquarium.allow_breeding) //the aquarium has breeding disabled
+ return COMPONENT_DONT_GROW
+
+/obj/item/fish/tadpole/proc/on_growth(datum/source, mob/living/basic/frog/result)
+ SIGNAL_HANDLER
+ playsound(result, result.attack_sound, 50, TRUE) // reeeeeeeeeeeeeee...
+
+/obj/item/fish/tadpole/get_export_price(price, percent)
+ return 2 //two credits. Tadpoles aren't really that valueable.
+
// Saltwater fish below
/obj/item/fish/clownfish
@@ -252,7 +301,7 @@
sprite_height = 9
sprite_width = 8
stable_population = 4
- feeding_frequency = 15 MINUTES
+ feeding_frequency = 10 MINUTES
random_case_rarity = FISH_RARITY_RARE
fillet_type = /obj/item/food/meat/slab/rawcrab
required_temperature_min = MIN_AQUARIUM_TEMP+9
@@ -270,14 +319,17 @@
evolution_types = list(/datum/fish_evolution/ice_chrab)
compatible_types = list(/obj/item/fish/chasm_crab/ice)
beauty = FISH_BEAUTY_GOOD
- ///Chasm crabs mature into juveline lobstrositiess with time. This is the progess from 0 to 100
- var/maturation = 0
///This value represents how much the crab needs aren't being met. Higher values translate to a more likely hostile lobstrosity.
var/anger = 0
///The lobstrosity type this matures into
var/lob_type = /mob/living/basic/mining/lobstrosity/juvenile/lava
///at which rate the crab gains maturation
- var/growth_rate = 100 / (12 MINUTES) * 10
+ var/growth_rate = 100 / (10 MINUTES) * 10
+
+/obj/item/fish/chasm_crab/Initialize(mapload, apply_qualities = TRUE)
+ . = ..()
+ RegisterSignal(src, COMSIG_FISH_BEFORE_GROWING, PROC_REF(growth_checks))
+ RegisterSignal(src, COMSIG_FISH_FINISH_GROWING, PROC_REF(on_growth))
///A chasm crab growth speed is determined by its initial weight and size, ergo bigger crabs for faster lobstrosities
/obj/item/fish/chasm_crab/update_size_and_weight(new_size = average_size, new_weight = average_weight)
@@ -298,62 +350,41 @@
else if(weight >= 1500)
multiplier += min(0.1 * round((weight - 1000) / 500), 2)
- growth_rate = initial(growth_rate) * multiplier
-
-/obj/item/fish/chasm_crab/process(seconds_per_tick)
- . = ..()
- grow_up(seconds_per_tick)
+ AddComponent(/datum/component/fish_growth, lob_type, initial(growth_rate) * multiplier)
-///Slowly grow up each process tick (in an aquarium). This is its own proc so that it can be used in the unit test.
-/obj/item/fish/chasm_crab/proc/grow_up(seconds_per_tick)
+/obj/item/fish/chasm_crab/proc/growth_checks(datum/source, seconds_per_tick)
+ SIGNAL_HANDLER
var/hunger = CLAMP01((world.time - last_feeding) / feeding_frequency)
if(health <= initial(health) * 0.6 || hunger >= 0.6) //if too hurt or hungry, don't grow.
anger += growth_rate * 2 * seconds_per_tick
- return
+ return COMPONENT_DONT_GROW
+
+ if(hunger >= 0.4) //I'm hungry and angry
+ anger += growth_rate * 0.6 * seconds_per_tick
- if(!isaquarium(loc)) //can't grow outside an aquarium.
+ if(!isaquarium(loc))
return
var/obj/structure/aquarium/aquarium = loc
if(!aquarium.allow_breeding) //the aquarium has breeding disabled
- return
- if(hunger >= 0.4) //I'm hungry and angry
- anger += growth_rate * 0.6 * seconds_per_tick
+ return COMPONENT_DONT_GROW
if(!locate(/obj/item/aquarium_prop) in aquarium) //the aquarium deco is quite barren
anger += growth_rate * 0.25 * seconds_per_tick
var/fish_count = length(aquarium.get_fishes())
if(!ISINRANGE(fish_count, 3, AQUARIUM_MAX_BREEDING_POPULATION * 0.5)) //too lonely or overcrowded
anger += growth_rate * 0.3 * seconds_per_tick
- if(fish_count <= AQUARIUM_MAX_BREEDING_POPULATION * 0.5) //check if there's enough room to maturate.
- maturation += growth_rate * seconds_per_tick
-
- if(maturation >= 100)
- return finish_growing()
-
-///spawn a juvenile lobstrosity on the aquarium turf
-/obj/item/fish/chasm_crab/proc/finish_growing()
- var/mob/living/basic/mining/lobstrosity/juvenile/lob = new lob_type(get_turf(src))
- for(var/trait_type in fish_traits)
- var/datum/fish_trait/trait = GLOB.fish_traits[trait_type]
- trait.apply_to_mob(lob)
+ if(fish_count > AQUARIUM_MAX_BREEDING_POPULATION * 0.5) //check if there's enough room to maturate.
+ return COMPONENT_DONT_GROW
+
+/obj/item/fish/chasm_crab/proc/on_growth(datum/source, mob/living/basic/mining/lobstrosity/juvenile/result)
+ SIGNAL_HANDLER
if(!prob(anger))
- lob.AddElement(/datum/element/ai_retaliate)
- qdel(lob.ai_controller)
- lob.ai_controller = new /datum/ai_controller/basic_controller/lobstrosity/juvenile/calm(lob)
+ result.AddElement(/datum/element/ai_retaliate)
+ qdel(result.ai_controller)
+ result.ai_controller = new /datum/ai_controller/basic_controller/lobstrosity/juvenile/calm(result)
else if(anger < 30) //not really that mad, just a bit unstable.
- qdel(lob.ai_controller)
- lob.ai_controller = new /datum/ai_controller/basic_controller/lobstrosity/juvenile/capricious(lob)
-
- animate(lob, pixel_y = 18, time = 0.4 SECONDS, flags = ANIMATION_RELATIVE, easing = CUBIC_EASING|EASE_OUT)
- animate(pixel_y = -18, time = 0.4 SECONDS, flags = ANIMATION_RELATIVE, easing = CUBIC_EASING|EASE_IN)
- loc.visible_message(span_boldnotice("\A [lob] jumps out of [loc]!"))
- playsound(loc, 'sound/effects/fish_splash.ogg', 60)
-
- ///make sure it moves the next tick so that it properly glides to the next location after jumping off the aquarium.
- addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(random_step), lob, 1, 100), 0.1 SECONDS)
-
- qdel(src)
- return lob
+ qdel(result.ai_controller)
+ result.ai_controller = new /datum/ai_controller/basic_controller/lobstrosity/juvenile/capricious(result)
/obj/item/fish/chasm_crab/ice
name = "arctic chrab"
@@ -434,7 +465,7 @@
)
beauty = FISH_BEAUTY_DISGUSTING
-/obj/item/fish/ratfish/Initialize(mapload)
+/obj/item/fish/ratfish/Initialize(mapload, apply_qualities = TRUE)
. = ..()
//stable pop reflects the config for how many mice migrate. powerful...
stable_population = CONFIG_GET(number/mice_roundstart)
@@ -451,7 +482,7 @@
average_size = 20
average_weight = 400
health = 50
- breeding_timeout = 5 MINUTES
+ breeding_timeout = 2.5 MINUTES
fish_traits = list(/datum/fish_trait/parthenogenesis, /datum/fish_trait/no_mating)
required_temperature_min = MIN_AQUARIUM_TEMP+10
required_temperature_max = MIN_AQUARIUM_TEMP+40
@@ -566,7 +597,7 @@
fish_traits = list(/datum/fish_trait/no_mating) //just to be sure, these shouldn't reproduce
experisci_scannable = FALSE
-/obj/item/fish/holo/Initialize(mapload)
+/obj/item/fish/holo/Initialize(mapload, apply_qualities = TRUE)
. = ..()
var/area/station/holodeck/holo_area = get_area(src)
if(!istype(holo_area))
@@ -655,7 +686,7 @@
fish_traits = list(/datum/fish_trait/antigrav, /datum/fish_trait/mixotroph)
beauty = FISH_BEAUTY_GREAT
-/obj/item/fish/starfish/Initialize(mapload)
+/obj/item/fish/starfish/Initialize(mapload, apply_qualities = TRUE)
. = ..()
update_appearance(UPDATE_OVERLAYS)
@@ -693,7 +724,7 @@
///maximum bonus damage when winded up
var/maximum_bonus = 25
-/obj/item/fish/lavaloop/Initialize(mapload)
+/obj/item/fish/lavaloop/Initialize(mapload, apply_qualities = TRUE)
. = ..()
ADD_TRAIT(src, TRAIT_BYPASS_RANGED_ARMOR, INNATE_TRAIT)
AddComponent(/datum/component/boomerang, throw_range, TRUE)
diff --git a/code/modules/fishing/fishing_equipment.dm b/code/modules/fishing/fishing_equipment.dm
index f6b49a9b523142..5408e411876b9f 100644
--- a/code/modules/fishing/fishing_equipment.dm
+++ b/code/modules/fishing/fishing_equipment.dm
@@ -260,7 +260,6 @@
// Can hold fishing rod despite the size
var/static/list/exception_cache = typecacheof(list(
/obj/item/fishing_rod,
- /obj/item/fishing_line,
))
atom_storage.exception_hold = exception_cache
@@ -269,6 +268,7 @@
new /obj/item/fishing_rod/unslotted(src)
new /obj/item/fishing_hook(src)
new /obj/item/fishing_line(src)
+ new /obj/item/paper/paperslip/fishing_tip(src)
/obj/item/storage/toolbox/fishing/small
name = "compact fishing toolbox"
@@ -285,31 +285,84 @@
new /obj/item/fishing_rod/unslotted(src)
new /obj/item/fishing_hook(src)
new /obj/item/fishing_line(src)
+ new /obj/item/paper/paperslip/fishing_tip(src)
+
+/obj/item/storage/toolbox/fishing/master
+ name = "super fishing toolbox"
+ desc = "Contains EVERYTHING (almost) you need for your fishing trip."
+ icon_state = "gold"
+ inhand_icon_state = "toolbox_gold"
+
+/obj/item/storage/toolbox/fishing/master/PopulateContents()
+ new /obj/item/fishing_rod/telescopic/master(src)
+ new /obj/item/storage/box/fishing_hooks/master(src)
+ new /obj/item/storage/box/fishing_lines/master(src)
+ new /obj/item/bait_can/super_baits(src)
+ new /obj/item/fish_feed(src)
+ new /obj/item/aquarium_kit(src)
+ new /obj/item/fish_analyzer(src)
+ new /obj/item/experi_scanner(src)
/obj/item/storage/box/fishing_hooks
name = "fishing hook set"
+ illustration = "fish"
/obj/item/storage/box/fishing_hooks/PopulateContents()
- . = ..()
new /obj/item/fishing_hook/magnet(src)
new /obj/item/fishing_hook/shiny(src)
new /obj/item/fishing_hook/weighted(src)
+/obj/item/storage/box/fishing_hooks/master
+
+/obj/item/storage/box/fishing_hooks/master/PopulateContents()
+ . = ..()
+ new /obj/item/fishing_hook/stabilized(src)
+ new /obj/item/fishing_hook/jaws(src)
+
/obj/item/storage/box/fishing_lines
name = "fishing line set"
+ illustration = "fish"
/obj/item/storage/box/fishing_lines/PopulateContents()
- . = ..()
new /obj/item/fishing_line/bouncy(src)
new /obj/item/fishing_line/reinforced(src)
new /obj/item/fishing_line/cloaked(src)
+/obj/item/storage/box/fishing_lines/master
+
+/obj/item/storage/box/fishing_lines/master/PopulateContents()
+ . = ..()
+ new /obj/item/fishing_line/auto_reel(src)
+
/obj/item/storage/box/fish_debug
name = "box full of fish"
+ illustration = "fish"
/obj/item/storage/box/fish_debug/PopulateContents()
for(var/fish_type in subtypesof(/obj/item/fish))
new fish_type(src)
+///Used to give the average player info about fishing stuff that's unknown to many.
+/obj/item/paper/paperslip/fishing_tip
+ name = "fishing tip"
+ desc = "A slip of paper containing a pearl of wisdom about fishing within it, though you wish it were an actual pearl."
+
+/obj/item/paper/paperslip/fortune/Initialize(mapload)
+ default_raw_text = pick(GLOB.fishing_tips)
+ return ..()
+
+///From the fishing mystery box. It's basically a lazarus and a few bottles of strange reagents.
+/obj/item/storage/box/fish_revival_kit
+ name = "fish revival kit"
+ desc = "Become a fish doctor today."
+ illustration = "fish"
+
+/obj/item/storage/box/fish_revival_kit/PopulateContents()
+ new /obj/item/lazarus_injector(src)
+ new /obj/item/reagent_containers/cup/bottle/strange_reagent(src)
+ new /obj/item/reagent_containers/cup(src) //to splash the reagents on the fish.
+ new /obj/item/storage/fish_case(src)
+ new /obj/item/storage/fish_case(src)
+
#undef MAGNET_HOOK_BONUS_MULTIPLIER
#undef RESCUE_HOOK_FISH_MULTIPLIER
diff --git a/code/modules/fishing/fishing_minigame.dm b/code/modules/fishing/fishing_minigame.dm
index 0a6b6b7cc87a96..9c70d474a62d73 100644
--- a/code/modules/fishing/fishing_minigame.dm
+++ b/code/modules/fishing/fishing_minigame.dm
@@ -20,13 +20,15 @@
/// The minimum velocity required for the bait to bounce
#define BAIT_MIN_VELOCITY_BOUNCE 150
/// The extra deceleration of velocity that happens when the bait switches direction
-#define BAIT_DECELERATION_MULT 1.5
+#define BAIT_DECELERATION_MULT 1.8
/// Reduce initial completion rate depending on difficulty
#define MAX_FISH_COMPLETION_MALUS 15
/// The window of time between biting phase and back to baiting phase
#define BITING_TIME_WINDOW 4 SECONDS
+/// The multiplier of how much the difficulty negatively impacts the bait height
+#define BAIT_HEIGHT_DIFFICULTY_MALUS 1.3
///Defines to know how the bait is moving on the minigame slider.
#define REELING_STATE_IDLE 0
@@ -36,7 +38,7 @@
///The pixel height of the minigame bar
#define MINIGAME_SLIDER_HEIGHT 76
///The standard pixel height of the bait
-#define MINIGAME_BAIT_HEIGHT 24
+#define MINIGAME_BAIT_HEIGHT 27
///The standard pixel height of the fish (minus a pixel on each direction for the sake of a better looking sprite)
#define MINIGAME_FISH_HEIGHT 4
@@ -82,7 +84,7 @@
/// How much space the fish takes on the minigame slider
var/fish_height = 50
/// How much space the bait takes on the minigame slider
- var/bait_height = 320
+ var/bait_height = 360
/// The height in pixels of the bait bar
var/bait_pixel_height = MINIGAME_BAIT_HEIGHT
/// The height in pixels of the fish
@@ -182,14 +184,16 @@
if(rod.hook.fishing_hook_traits & FISHING_HOOK_KILL)
special_effects |= FISHING_MINIGAME_RULE_KILL
+ completion_loss += user.mind?.get_skill_modifier(/datum/skill/fishing, SKILL_VALUE_MODIFIER)/5
+
if(special_effects & FISHING_MINIGAME_RULE_KILL && ispath(reward_path,/obj/item/fish))
RegisterSignal(comp.fish_source, COMSIG_FISH_SOURCE_REWARD_DISPENSED, PROC_REF(hurt_fish))
difficulty += comp.fish_source.calculate_difficulty(reward_path, rod, user, src)
- difficulty = clamp(round(difficulty), 1, 100)
+ difficulty = clamp(round(difficulty), FISHING_EASY_DIFFICULTY - 5, 100)
if(difficulty > FISHING_EASY_DIFFICULTY)
- completion -= round(MAX_FISH_COMPLETION_MALUS * (difficulty/100), 1)
+ completion -= MAX_FISH_COMPLETION_MALUS * (difficulty * 0.01)
if(HAS_MIND_TRAIT(user, TRAIT_REVEAL_FISH))
fish_icon = GLOB.specific_fish_icons[reward_path] || "fish"
@@ -211,7 +215,7 @@
else
long_jump_chance *= difficulty
- bait_height -= difficulty
+ bait_height -= round(difficulty * BAIT_HEIGHT_DIFFICULTY_MALUS)
bait_pixel_height = round(MINIGAME_BAIT_HEIGHT * (bait_height/initial(bait_height)), 1)
/datum/fishing_challenge/Destroy(force)
@@ -277,11 +281,11 @@
//You need to be holding the rod to use it.
if(LAZYACCESS(modifiers, SHIFT_CLICK) || LAZYACCESS(modifiers, CTRL_CLICK) || LAZYACCESS(modifiers, ALT_CLICK))
return
- if(!source.get_active_held_item(used_rod) && !HAS_TRAIT(source, TRAIT_PROFOUND_FISHER))
+ if(!HAS_TRAIT(source, TRAIT_PROFOUND_FISHER) && source.get_active_held_item() != used_rod)
return
- if(phase == WAIT_PHASE) //Reset wait
+ if(phase == WAIT_PHASE)
send_alert("miss!")
- start_baiting_phase(TRUE)
+ start_baiting_phase(TRUE) //Add in another 3 to 5 seconds for that blunder.
else if(phase == BITING_PHASE)
start_minigame_phase()
return COMSIG_MOB_CANCEL_CLICKON
@@ -329,7 +333,7 @@
if(penalty)
wait_time = min(timeleft(next_phase_timer) + rand(3 SECONDS, 5 SECONDS), 30 SECONDS)
else
- wait_time = rand(1 SECONDS, 30 SECONDS)
+ wait_time = rand(3 SECONDS, 25 SECONDS)
if(special_effects & FISHING_MINIGAME_AUTOREEL && wait_time >= 15 SECONDS)
wait_time = max(wait_time - 7.5 SECONDS, 15 SECONDS)
deltimer(next_phase_timer)
@@ -409,7 +413,6 @@
completion *= 1.2
if(BITING_TIME_WINDOW - 0.5 SECONDS to BITING_TIME_WINDOW)
completion *= 1.4
- completion = round(completion, 1)
if(!prepare_minigame_hud())
return
phase = MINIGAME_PHASE
@@ -736,6 +739,8 @@
#undef MINIGAME_BAIT_HEIGHT
#undef MINIGAME_FISH_HEIGHT
+#undef BAIT_HEIGHT_DIFFICULTY_MALUS
+
#undef REELING_STATE_IDLE
#undef REELING_STATE_UP
#undef REELING_STATE_DOWN
diff --git a/code/modules/fishing/fishing_portal_machine.dm b/code/modules/fishing/fishing_portal_machine.dm
index 494b29b4183eef..8b157cbebfff3d 100644
--- a/code/modules/fishing/fishing_portal_machine.dm
+++ b/code/modules/fishing/fishing_portal_machine.dm
@@ -100,3 +100,7 @@
if(!choice || !can_interact(user))
return
activate(available_fish_sources[choice])
+
+/obj/machinery/fishing_portal_generator/emagged
+ obj_flags = parent_type::obj_flags | EMAGGED
+ circuit = /obj/item/circuitboard/machine/fishing_portal_generator/emagged
diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm
index e6ac4bac8abae0..c36ea48b15c020 100644
--- a/code/modules/fishing/fishing_rod.dm
+++ b/code/modules/fishing/fishing_rod.dm
@@ -101,7 +101,7 @@
/obj/item/fishing_rod/proc/consume_bait(atom/movable/reward)
// catching things that aren't fish or alive mobs doesn't consume baits.
- if(isnull(reward) || isnull(bait))
+ if(isnull(reward) || isnull(bait) || HAS_TRAIT(bait, TRAIT_BAIT_UNCONSUMABLE))
return
if(isliving(reward))
var/mob/living/caught_mob = reward
@@ -536,7 +536,7 @@
ui_description = "This rod has an infinite supply of synth-bait. Also doubles as an Experi-Scanner for fish."
icon_state = "fishing_rod_science"
reel_overlay = "reel_science"
- bait = /obj/item/food/bait/doughball/synthetic
+ bait = /obj/item/food/bait/doughball/synthetic/unconsumable
/obj/item/fishing_rod/tech/Initialize(mapload)
. = ..()
@@ -558,9 +558,6 @@
. = ..()
. += span_notice("Alt-Click to access the Experiment Configuration UI")
-/obj/item/fishing_rod/tech/consume_bait(atom/movable/reward)
- return
-
/obj/item/fishing_rod/tech/use_slot(slot, mob/user, obj/item/new_item)
if(slot == ROD_SLOT_BAIT)
return
@@ -586,7 +583,9 @@
if(owner.hook)
icon_state = owner.hook.icon_state
transform = transform.Scale(1, -1)
- return ..()
+ . = ..()
+ if(!QDELETED(src))
+ our_line = owner.create_fishing_line(src)
/obj/projectile/fishing_cast/on_hit(atom/target, blocked = 0, pierce_hit)
. = ..()
@@ -594,10 +593,6 @@
QDEL_NULL(our_line) //we need to delete the old beam datum, otherwise it won't let you fish.
owner.hook_hit(target)
-/obj/projectile/fishing_cast/fire(angle, atom/direct_target)
- . = ..()
- our_line = owner.create_fishing_line(src)
-
/obj/projectile/fishing_cast/Destroy()
QDEL_NULL(our_line)
owner?.casting = FALSE
diff --git a/code/modules/fishing/sources/_fish_source.dm b/code/modules/fishing/sources/_fish_source.dm
index 602975ed75a00b..4a0419f98f55f4 100644
--- a/code/modules/fishing/sources/_fish_source.dm
+++ b/code/modules/fishing/sources/_fish_source.dm
@@ -57,6 +57,11 @@ GLOBAL_LIST_INIT(specific_fish_icons, zebra_typecacheof(list(
var/explosive_malus = FALSE
/// If explosive_malus is true, this will be used to keep track of the turfs where an explosion happened for when we'll spawn the loot.
var/list/exploded_turfs
+ /// Mindless mobs that can fish will never pull up items on this list
+ var/static/list/profound_fisher_blacklist = typecacheof(list(
+ /mob/living/basic/mining/lobstrosity,
+ /obj/structure/closet/crate/necropolis/tendril,
+ ))
/datum/fish_source/New()
if(!PERFORM_ALL_TESTS(focus_only/fish_sources_tables))
@@ -97,7 +102,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, zebra_typecacheof(list(
. += EXPERT_FISHER_DIFFICULTY_MOD
// Difficulty modifier added by the fisher's skill level
- if(!challenge || !(challenge.special_effects & FISHING_MINIGAME_RULE_NO_EXP))
+ if(!(challenge?.special_effects & FISHING_MINIGAME_RULE_NO_EXP))
. += fisherman.mind?.get_skill_modifier(/datum/skill/fishing, SKILL_VALUE_MODIFIER)
// Difficulty modifier added by the rod
@@ -259,6 +264,9 @@ GLOBAL_LIST(fishing_property_cache)
///Multiplier used to make fishes more common compared to everything else.
var/result_multiplier = 1
+
+ var/list/final_table = fish_table.Copy()
+
if(bait)
if(HAS_TRAIT(bait, TRAIT_GREAT_QUALITY_BAIT))
result_multiplier = 9
@@ -269,10 +277,13 @@ GLOBAL_LIST(fishing_property_cache)
else if(HAS_TRAIT(bait, TRAIT_BASIC_QUALITY_BAIT))
result_multiplier = 2
leveling_exponent = 0.1
+ final_table -= FISHING_DUD
var/list/fish_list_properties = collect_fish_properties()
- var/list/final_table = fish_table.Copy()
+
+ if(HAS_TRAIT(fisherman, TRAIT_PROFOUND_FISHER) && !fisherman.client)
+ final_table -= profound_fisher_blacklist
for(var/result in final_table)
final_table[result] *= rod.hook?.get_hook_bonus_multiplicative(result)
final_table[result] += rod.hook?.get_hook_bonus_additive(result)//Decide on order here so it can be multiplicative
diff --git a/code/modules/fishing/sources/source_types.dm b/code/modules/fishing/sources/source_types.dm
index 583aa3e3e7ea9d..e7192bbd09c7da 100644
--- a/code/modules/fishing/sources/source_types.dm
+++ b/code/modules/fishing/sources/source_types.dm
@@ -9,9 +9,11 @@
/obj/item/fish/lanternfish = 5,
/obj/item/fish/zipzap = 5,
/obj/item/fish/clownfish/lube = 3,
+ /obj/structure/mystery_box/fishing = 1,
)
fish_counts = list(
/obj/item/fish/clownfish/lube = 2,
+ /obj/structure/mystery_box/fishing = 1,
)
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 5
explosive_malus = TRUE
@@ -45,6 +47,7 @@
catalog_description = "Beach dimension (Fishing portal generator)"
radial_name = "Beach"
radial_state = "palm_beach"
+ overlay_state = "portal_beach"
/datum/fish_source/portal/chasm
background = "background_lavaland"
diff --git a/code/modules/food_and_drinks/machinery/microwave.dm b/code/modules/food_and_drinks/machinery/microwave.dm
index 2b790306b5ac74..4fa586401ff561 100644
--- a/code/modules/food_and_drinks/machinery/microwave.dm
+++ b/code/modules/food_and_drinks/machinery/microwave.dm
@@ -416,32 +416,7 @@
balloon_alert(user, "max 1 device!")
return ITEM_INTERACT_BLOCKING
- if(istype(item, /obj/item/storage))
- var/obj/item/storage/tray = item
- var/loaded = 0
-
- if(!istype(item, /obj/item/storage/bag/tray))
- // Non-tray dumping requires a do_after
- to_chat(user, span_notice("You start dumping out the contents of [item] into [src]..."))
- if(!do_after(user, 2 SECONDS, target = tray))
- return ITEM_INTERACT_BLOCKING
-
- for(var/obj/tray_item in tray.contents)
- if(!IS_EDIBLE(tray_item))
- continue
- if(ingredients.len >= max_n_of_items)
- balloon_alert(user, "it's full!")
- return ITEM_INTERACT_BLOCKING
- if(tray.atom_storage.attempt_remove(tray_item, src))
- loaded++
- ingredients += tray_item
- if(loaded)
- open(autoclose = 0.6 SECONDS)
- to_chat(user, span_notice("You insert [loaded] items into \the [src]."))
- update_appearance()
- return ITEM_INTERACT_SUCCESS
-
- if(item.w_class <= WEIGHT_CLASS_NORMAL && !user.combat_mode)
+ if(item.w_class <= WEIGHT_CLASS_NORMAL && !user.combat_mode && isnull(item.atom_storage))
if(ingredients.len >= max_n_of_items)
balloon_alert(user, "it's full!")
return ITEM_INTERACT_BLOCKING
@@ -455,6 +430,43 @@
update_appearance()
return ITEM_INTERACT_SUCCESS
+/obj/machinery/microwave/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers)
+ if (isnull(tool.atom_storage))
+ return
+ handle_dumping(user, tool)
+ return ITEM_INTERACT_BLOCKING
+
+/obj/machinery/microwave/proc/handle_dumping(mob/living/user, obj/item/tool)
+ if(isnull(tool.atom_storage))
+ return
+
+ var/loaded = 0
+ if(!istype(tool, /obj/item/storage/bag/tray))
+ // Non-tray dumping requires a do_after
+ to_chat(user, span_notice("You start dumping out the contents of [tool] into [src]..."))
+ if(!do_after(user, 2 SECONDS, target = tool))
+ return
+
+ for(var/obj/tray_item in tool.contents)
+ if(!IS_EDIBLE(tray_item))
+ continue
+ if(ingredients.len >= max_n_of_items)
+ balloon_alert(user, "it's full!")
+ return
+ if(tool.atom_storage.attempt_remove(tray_item, src))
+ loaded++
+ ingredients += tray_item
+
+ if(loaded)
+ open(autoclose = 0.6 SECONDS)
+ to_chat(user, span_notice("You insert [loaded] items into \the [src]."))
+ update_appearance()
+
+/obj/machinery/microwave/mouse_drop_receive(obj/item/tool, mob/user, params)
+ if (!istype(tool) || isnull(tool.atom_storage))
+ return
+ handle_dumping(user, tool)
+
/obj/machinery/microwave/attack_hand_secondary(mob/user, list/modifiers)
if(user.can_perform_action(src, ALLOW_SILICON_REACH))
if(!length(ingredients))
diff --git a/code/modules/food_and_drinks/machinery/processor.dm b/code/modules/food_and_drinks/machinery/processor.dm
index 03b99f49ef734c..9ddec8165ac289 100644
--- a/code/modules/food_and_drinks/machinery/processor.dm
+++ b/code/modules/food_and_drinks/machinery/processor.dm
@@ -159,7 +159,9 @@
var/duration = (total_time / rating_speed)
INVOKE_ASYNC(src, TYPE_PROC_REF(/atom, Shake), 1, 0, duration)
- sleep(duration)
+ addtimer(CALLBACK(src, PROC_REF(complete_processing)), duration)
+
+/obj/machinery/processor/proc/complete_processing()
for(var/atom/movable/content_item in processor_contents)
var/datum/food_processor_process/recipe = PROCESSOR_SELECT_RECIPE(content_item)
if (!recipe)
diff --git a/code/modules/food_and_drinks/machinery/smartfridge.dm b/code/modules/food_and_drinks/machinery/smartfridge.dm
index 3519c55fc39aca..858e4cd7aefcfe 100644
--- a/code/modules/food_and_drinks/machinery/smartfridge.dm
+++ b/code/modules/food_and_drinks/machinery/smartfridge.dm
@@ -32,6 +32,8 @@
var/welded_down = FALSE
/// The sound of item retrieval
var/vend_sound = 'sound/machines/machine_vend.ogg'
+ /// Whether the UI should be set to list view by default
+ var/default_list_view = FALSE
/obj/machinery/smartfridge/Initialize(mapload)
. = ..()
@@ -369,7 +371,7 @@
var/atom/movable/atom = item
if (!QDELETED(atom))
- var/key = "[atom.type]"
+ var/key = "[atom.type]-[atom.name]"
if (listofitems[key])
listofitems[key]["amount"]++
else
@@ -383,6 +385,7 @@
.["contents"] = sort_list(listofitems)
.["name"] = name
.["isdryer"] = FALSE
+ .["default_list_view"] = default_list_view
/obj/machinery/smartfridge/Exited(atom/movable/gone, direction) // Update the UIs in case something inside is removed
. = ..()
@@ -400,6 +403,7 @@
if("Release")
var/amount = text2num(params["amount"])
var/desired = 1
+ var/dispensed_amount = 0
if(isAI(living_mob))
to_chat(living_mob, span_warning("[src] does not respect your authority!"))
@@ -413,18 +417,19 @@
for(var/obj/item/dispensed_item in src)
if(desired <= 0)
break
- if(istype(dispensed_item, text2path(params["path"])))
+ var/item_name = "[dispensed_item.type]-[replacetext(replacetext(dispensed_item.name, "\proper", ""), "\improper", "")]"
+ if(params["path"] == item_name)
if(dispensed_item in component_parts)
CRASH("Attempted removal of [dispensed_item] component_part from smartfridge via smartfridge interface.")
//dispense the item
if(!living_mob.put_in_hands(dispensed_item))
dispensed_item.forceMove(drop_location())
adjust_item_drop_location(dispensed_item)
- if(vend_sound)
- playsound(src, vend_sound, 50, TRUE, extrarange = -3)
use_energy(active_power_usage)
+ dispensed_amount++
desired--
-
+ if(dispensed_amount && vend_sound)
+ playsound(src, vend_sound, 50, TRUE, extrarange = -3)
if (visible_contents)
update_appearance()
return
@@ -727,6 +732,7 @@
desc = "A refrigerated storage unit for medicine storage."
base_build_path = /obj/machinery/smartfridge/chemistry
contents_overlay_icon = "chem"
+ default_list_view = TRUE
/obj/machinery/smartfridge/chemistry/accept_check(obj/item/weapon)
// not an item or reagent container
@@ -778,6 +784,7 @@
desc = "A refrigerated storage unit for volatile sample storage."
base_build_path = /obj/machinery/smartfridge/chemistry/virology
contents_overlay_icon = "viro"
+ default_list_view = TRUE
/obj/machinery/smartfridge/chemistry/virology/preloaded
initial_contents = list(
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_egg.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_egg.dm
index ec8eda8d3cfff2..7b8c071b3a5390 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_egg.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_egg.dm
@@ -13,7 +13,7 @@
category = CAT_EGG
/datum/crafting_recipe/food/omelette
- name = "Omelette"
+ name = "Omelette du fromage"
reqs = list(
/obj/item/food/egg = 2,
/obj/item/food/cheese/wedge = 2
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_lizard.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_lizard.dm
index 71716a1ee7c2a8..7b253f32ce17d6 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_lizard.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_lizard.dm
@@ -74,7 +74,8 @@
/obj/item/food/grown/garlic = 1,
/datum/reagent/consumable/lemonjuice = 3,
/datum/reagent/consumable/blackpepper = 2,
- /datum/reagent/consumable/nutriment/fat/oil/olive = 3
+ /datum/reagent/consumable/nutriment/fat/oil/olive = 3,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/lizard_escargot
category = CAT_LIZARD
@@ -94,7 +95,8 @@
reqs = list(
/obj/item/food/fries = 1,
/obj/item/food/meat/cutlet = 2,
- /datum/reagent/consumable/bbqsauce = 5
+ /datum/reagent/consumable/bbqsauce = 5,
+ /obj/item/plate = 1,
)
result = /obj/item/food/lizard_fries
category = CAT_LIZARD
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_martian.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_martian.dm
index 02bb9ae7bf82cc..9048964df1c7cd 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_martian.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_martian.dm
@@ -45,6 +45,7 @@
/obj/item/food/grown/onion = 1,
/datum/reagent/consumable/sugar = 3,
/datum/reagent/consumable/limejuice = 3,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/sambal
category = CAT_MARTIAN
@@ -78,6 +79,7 @@
/obj/item/food/meat/cutlet = 1,
/obj/item/food/pineappleslice = 1,
/datum/reagent/consumable/soysauce = 3,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/hurricane_rice
category = CAT_MARTIAN
@@ -91,6 +93,7 @@
/obj/item/food/onion_slice = 1,
/obj/item/food/sausage = 1,
/obj/item/food/grown/chili = 1,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/ikareis
category = CAT_MARTIAN
@@ -103,7 +106,8 @@
/obj/item/food/grown/bell_pepper = 1,
/obj/item/food/pineappleslice = 1,
/obj/item/food/onion_slice = 1,
- /datum/reagent/consumable/soysauce = 5
+ /datum/reagent/consumable/soysauce = 5,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/hawaiian_fried_rice
category = CAT_MARTIAN
@@ -118,6 +122,7 @@
/obj/item/food/grown/peas = 1,
/datum/reagent/consumable/ketchup = 5,
/datum/reagent/consumable/worcestershire = 2,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/ketchup_fried_rice
category = CAT_MARTIAN
@@ -131,6 +136,7 @@
/obj/item/food/cheese/firm_cheese_slice = 1,
/obj/item/food/grown/olive = 1,
/obj/item/food/meatball = 1,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/mediterranean_fried_rice
category = CAT_MARTIAN
@@ -141,6 +147,7 @@
/obj/item/food/boiledrice = 1,
/obj/item/food/egg = 1,
/datum/reagent/consumable/soysauce = 3,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/egg_fried_rice
category = CAT_MARTIAN
@@ -154,6 +161,7 @@
/obj/item/food/meat/cutlet = 1,
/obj/item/food/kimchi = 1,
/obj/item/food/egg = 1,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/bibimbap
category = CAT_MARTIAN
@@ -167,6 +175,7 @@
/obj/item/food/grown/garlic = 1,
/obj/item/food/onion_slice = 1,
/datum/reagent/consumable/nutriment/soup/teriyaki = 4,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/bulgogi_noodles
category = CAT_MARTIAN
@@ -180,6 +189,7 @@
/obj/item/food/onion_slice = 1,
/obj/item/food/katsu_fillet = 1,
/datum/reagent/consumable/worcestershire = 3,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/yakisoba_katsu
category = CAT_MARTIAN
@@ -194,6 +204,7 @@
/obj/item/food/egg = 1,
/datum/reagent/consumable/soysauce = 3,
/datum/reagent/consumable/red_bay = 3,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/martian_fried_noodles
category = CAT_MARTIAN
@@ -203,6 +214,7 @@
reqs = list(
/obj/item/food/spaghetti/boilednoodles = 1,
/datum/reagent/consumable/soysauce = 3,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/simple_fried_noodles
category = CAT_MARTIAN
@@ -222,6 +234,7 @@
/obj/item/food/grown/onion = 1,
/obj/item/food/grown/carrot = 1,
/obj/item/food/grown/potato = 1,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/setagaya_curry
category = CAT_MARTIAN
@@ -545,6 +558,7 @@
/obj/item/food/meat/slab/chicken = 1,
/datum/reagent/consumable/coconut_milk = 5,
/datum/reagent/consumable/curry_powder = 3,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/po_kok_gai
category = CAT_MARTIAN
@@ -579,6 +593,7 @@
/obj/item/food/grown/tomato = 1,
/obj/item/food/uncooked_rice = 1,
/datum/reagent/blood = 5,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/galinha_de_cabidela
category = CAT_MARTIAN
@@ -589,6 +604,7 @@
/obj/item/food/katsu_fillet = 1,
/obj/item/food/boiledrice = 1,
/datum/reagent/consumable/nutriment/soup/curry_sauce = 5,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/katsu_curry
category = CAT_MARTIAN
@@ -600,6 +616,7 @@
/obj/item/food/onion_slice = 1,
/obj/item/food/boiledrice = 1,
/datum/reagent/consumable/nutriment/soup/dashi = 5,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/beef_bowl
category = CAT_MARTIAN
@@ -613,6 +630,7 @@
/obj/item/food/boiledrice = 1,
/datum/reagent/consumable/salt = 2,
/datum/reagent/consumable/nutriment/soup/curry_sauce = 5,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/salt_chilli_bowl
category = CAT_MARTIAN
@@ -625,6 +643,7 @@
/obj/item/food/grown/onion = 1,
/obj/item/food/boiledrice = 1,
/datum/reagent/consumable/nutriment/soup/dashi = 5,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/kansai_bowl
category = CAT_MARTIAN
@@ -637,6 +656,7 @@
/obj/item/food/fishmeat = 1,
/obj/item/food/boiledrice = 1,
/datum/reagent/consumable/cafe_latte = 5,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/eigamudo_curry
category = CAT_MARTIAN
@@ -681,6 +701,7 @@
/datum/reagent/consumable/caramel = 2,
/obj/item/food/icecream = 1,
/datum/reagent/consumable/ethanol/rum = 2,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/pineapple_foster
category = CAT_MARTIAN
@@ -848,6 +869,7 @@
/obj/item/food/fishmeat = 1,
/obj/item/food/boiledrice = 1,
/datum/reagent/consumable/nutriment/soup/dashi = 5,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/salad/sprout_bowl
category = CAT_MARTIAN
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm
index 98eafb66823df8..804956cbeed5b2 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm
@@ -243,6 +243,7 @@
/obj/item/food/grown/onion = 1,
/obj/item/food/grown/tomato = 1,
/obj/item/food/meat/steak = 1,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/beef_stroganoff
category = CAT_MEAT
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_mexican.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_mexican.dm
index 8778ee976ef25b..840d3a8c08b1ab 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_mexican.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_mexican.dm
@@ -120,7 +120,8 @@
/obj/item/food/cornchips = 1,
/obj/item/food/grown/chili = 1,
/obj/item/food/grown/onion = 1,
- /obj/item/food/grown/tomato = 1
+ /obj/item/food/grown/tomato = 1,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/chipsandsalsa
category = CAT_MEXICAN
@@ -198,6 +199,7 @@
/obj/item/food/grown/tomato = 1,
/obj/item/food/grown/onion = 1,
/obj/item/food/grown/chili = 1,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/pineapple_salsa
category = CAT_MEXICAN
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_moth.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_moth.dm
index bb20f4ab0b370a..aeb27f026b2510 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_moth.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_moth.dm
@@ -2,7 +2,8 @@
name = "Herby cheese"
reqs = list(
/obj/item/food/cheese/curd_cheese = 1,
- /obj/item/food/grown/herbs = 4
+ /obj/item/food/grown/herbs = 4,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/herby_cheese
category = CAT_MOTH
@@ -187,7 +188,8 @@
reqs = list(
/datum/reagent/consumable/nutriment/soup/rice_porridge = 10,
/obj/item/food/meat/bacon = 1,
- /obj/item/food/friedegg = 2
+ /obj/item/food/friedegg = 2,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/bowled/hua_mulan_congee
category = CAT_MOTH
@@ -199,7 +201,8 @@
/obj/item/food/grown/eggplant = 1,
/obj/item/food/breadslice/plain = 2,
/obj/item/food/tomato_sauce = 1,
- /obj/item/food/cheese/mozzarella = 1
+ /obj/item/food/cheese/mozzarella = 1,
+ /obj/item/reagent_containers/cup/bowl = 1,
)
result = /obj/item/food/bowled/fried_eggplant_polenta
category = CAT_MOTH
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
index 3ce319b1985a2b..c965526bcb1c67 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
@@ -399,6 +399,42 @@
result = /obj/item/food/donkpocket/gondola
category = CAT_PASTRY
+/datum/crafting_recipe/food/donkpocket/deluxe
+ time = 15
+ name = "Deluxe Donk-pocket"
+ reqs = list(
+ /obj/item/food/pastrybase = 1,
+ /obj/item/food/meatball = 1,
+ /obj/item/food/meat/bacon = 1,
+ /obj/item/food/onion_slice/red = 1
+ )
+ result = /obj/item/food/donkpocket/deluxe
+ category = CAT_PASTRY
+
+/datum/crafting_recipe/food/donkpocket/deluxe/nocarb
+ time = 15
+ name = "Deluxe Meat-pocket"
+ reqs = list(
+ /obj/item/organ/internal/heart = 1,
+ /obj/item/food/meatball = 1,
+ /obj/item/food/meat/slab = 1,
+ /obj/item/food/grown/herbs = 1
+ )
+ result = /obj/item/food/donkpocket/deluxe/nocarb
+ category = CAT_PASTRY
+
+/datum/crafting_recipe/food/donkpocket/deluxe/vegan
+ time = 15
+ name = "Deluxe Donk-roll"
+ reqs = list(
+ /obj/item/food/pastrybase = 1,
+ /obj/item/food/boiledrice = 1,
+ /obj/item/food/grown/bell_pepper = 1,
+ /obj/item/food/tofu = 2
+ )
+ result = /obj/item/food/donkpocket/deluxe/vegan
+ category = CAT_PASTRY
+
////////////////////////////////////////////////MUFFINS////////////////////////////////////////////////
/datum/crafting_recipe/food/muffin
@@ -568,6 +604,16 @@
result = /obj/item/food/cherrycupcake/blue
category = CAT_PASTRY
+/datum/crafting_recipe/food/jupitercupcake
+ name = "Jupiter-cup-cake"
+ reqs = list(
+ /obj/item/food/pastrybase = 1,
+ /obj/item/food/grown/mushroom/jupitercup = 1,
+ /datum/reagent/consumable/caramel = 3,
+ )
+ result = /obj/item/food/jupitercupcake
+ category = CAT_PASTRY
+
/datum/crafting_recipe/food/honeybun
name = "Honey bun"
reqs = list(
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_spaghetti.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_spaghetti.dm
index 589235eacb70cc..edf82287373f07 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_spaghetti.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_spaghetti.dm
@@ -44,7 +44,7 @@
/obj/item/reagent_containers/cup/bowl = 1,
/obj/item/food/spaghetti/boiledspaghetti = 1,
/obj/item/food/meat/cutlet = 2,
- /obj/item/food/grown/cabbage = 1
+ /obj/item/food/grown/cabbage = 1,
)
result = /obj/item/food/spaghetti/beefnoodle
category = CAT_SPAGHETTI
@@ -157,3 +157,15 @@
)
result = /obj/item/food/spaghetti/pad_thai
category = CAT_SPAGHETTI
+
+/datum/crafting_recipe/food/carbonara
+ name = "Spaghetti Carbonara"
+ reqs = list(
+ /obj/item/food/spaghetti/boiledspaghetti = 1,
+ /obj/item/food/cheese/firm_cheese_slice = 1,
+ /obj/item/food/meat/bacon = 1,
+ /obj/item/food/egg = 1,
+ /datum/reagent/consumable/blackpepper = 2,
+ )
+ result = /obj/item/food/spaghetti/carbonara
+ category = CAT_SPAGHETTI
diff --git a/code/modules/hydroponics/grown/aloe.dm b/code/modules/hydroponics/grown/aloe.dm
index cfbefce6dba21e..0548098732622d 100644
--- a/code/modules/hydroponics/grown/aloe.dm
+++ b/code/modules/hydroponics/grown/aloe.dm
@@ -1,7 +1,7 @@
// aloe
/obj/item/seeds/aloe
- name = "pack of aloe seeds"
+ name = "aloe seed pack"
desc = "These seeds grow into aloe."
icon_state = "seed-aloe"
species = "aloe"
diff --git a/code/modules/hydroponics/grown/ambrosia.dm b/code/modules/hydroponics/grown/ambrosia.dm
index 2becc390f39802..92cdc2d62c8c1d 100644
--- a/code/modules/hydroponics/grown/ambrosia.dm
+++ b/code/modules/hydroponics/grown/ambrosia.dm
@@ -11,7 +11,7 @@
// Ambrosia Vulgaris
/obj/item/seeds/ambrosia
- name = "pack of ambrosia vulgaris seeds"
+ name = "ambrosia vulgaris seed pack"
desc = "These seeds grow into common ambrosia, a plant grown by and from medicine."
icon_state = "seed-ambrosiavulgaris"
plant_icon_offset = 0
@@ -36,7 +36,7 @@
// Ambrosia Deus
/obj/item/seeds/ambrosia/deus
- name = "pack of ambrosia deus seeds"
+ name = "ambrosia deus seed pack"
desc = "These seeds grow into ambrosia deus. Could it be the food of the gods..?"
icon_state = "seed-ambrosiadeus"
species = "ambrosiadeus"
@@ -55,7 +55,7 @@
//Ambrosia Gaia
/obj/item/seeds/ambrosia/gaia
- name = "pack of ambrosia gaia seeds"
+ name = "ambrosia gaia seed pack"
desc = "These seeds grow into ambrosia gaia, filled with infinite potential."
icon_state = "seed-ambrosia_gaia"
species = "ambrosia_gaia"
diff --git a/code/modules/hydroponics/grown/apple.dm b/code/modules/hydroponics/grown/apple.dm
index 0079f63ec90230..c1739cc7dea828 100644
--- a/code/modules/hydroponics/grown/apple.dm
+++ b/code/modules/hydroponics/grown/apple.dm
@@ -1,6 +1,6 @@
// Apple
/obj/item/seeds/apple
- name = "pack of apple seeds"
+ name = "apple seed pack"
desc = "These seeds grow into apple trees."
icon_state = "seed-apple"
species = "apple"
@@ -31,7 +31,7 @@
// Gold Apple
/obj/item/seeds/apple/gold
- name = "pack of golden apple seeds"
+ name = "golden apple seed pack"
desc = "These seeds grow into golden apple trees. Good thing there are no firebirds in space."
icon_state = "seed-goldapple"
species = "goldapple"
diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm
index ab38f6889907ad..6e09ee3497cddd 100644
--- a/code/modules/hydroponics/grown/banana.dm
+++ b/code/modules/hydroponics/grown/banana.dm
@@ -1,6 +1,6 @@
// Banana
/obj/item/seeds/banana
- name = "pack of banana seeds"
+ name = "banana seed pack"
desc = "They're seeds that grow into banana trees. When grown, keep away from clown."
icon_state = "seed-banana"
species = "banana"
@@ -91,7 +91,7 @@
// Mimana - invisible sprites are totally a feature!
/obj/item/seeds/banana/mime
- name = "pack of mimana seeds"
+ name = "mimana seed pack"
desc = "They're seeds that grow into mimana trees. When grown, keep away from mime."
icon_state = "seed-mimana"
species = "mimana"
@@ -119,7 +119,7 @@
// Bluespace Banana
/obj/item/seeds/banana/bluespace
- name = "pack of bluespace banana seeds"
+ name = "bluespace banana seed pack"
desc = "They're seeds that grow into bluespace banana trees. When grown, keep away from bluespace clown."
icon_state = "seed-banana-blue"
species = "bluespacebanana"
diff --git a/code/modules/hydroponics/grown/beans.dm b/code/modules/hydroponics/grown/beans.dm
index 974b19889ecba0..885eb77c0c6958 100644
--- a/code/modules/hydroponics/grown/beans.dm
+++ b/code/modules/hydroponics/grown/beans.dm
@@ -1,6 +1,6 @@
// Soybeans
/obj/item/seeds/soya
- name = "pack of soybean seeds"
+ name = "soybean seed pack"
desc = "These seeds grow into soybean plants."
icon_state = "seed-soybean"
species = "soybean"
@@ -30,7 +30,7 @@
// Koibean
/obj/item/seeds/soya/koi
- name = "pack of koibean seeds"
+ name = "koibean seed pack"
desc = "These seeds grow into koibean plants."
icon_state = "seed-koibean"
species = "koibean"
@@ -63,7 +63,7 @@
//Butterbeans, the beans wid da butta!
// Butterbeans! - Squeeze for a single butter slice!
/obj/item/seeds/soya/butter
- name = "pack of butterbean seeds"
+ name = "butterbean seed pack"
desc = "These seeds grow into butterbean plants."
icon_state = "seed-butterbean"
species = "butterbean"
@@ -94,7 +94,7 @@
// Green Beans
/obj/item/seeds/greenbean
- name = "pack of green bean seeds"
+ name = "green bean seed pack"
desc = "These seeds grow into green bean plants."
icon_state = "seed-greenbean"
species = "greenbean"
@@ -123,7 +123,7 @@
// Jumping Bean
/obj/item/seeds/greenbean/jump
- name = "pack of jumping bean seeds"
+ name = "jumping bean seed pack"
desc = "These seeds grow into jumping bean plants."
icon_state = "seed-jumpingbean"
species = "jumpingbean"
diff --git a/code/modules/hydroponics/grown/berries.dm b/code/modules/hydroponics/grown/berries.dm
index 317f8ef2ed87fc..10631e4dcb0b6c 100644
--- a/code/modules/hydroponics/grown/berries.dm
+++ b/code/modules/hydroponics/grown/berries.dm
@@ -1,6 +1,6 @@
// Berries
/obj/item/seeds/berry
- name = "pack of berry seeds"
+ name = "berry seed pack"
desc = "These seeds grow into berry bushes."
icon_state = "seed-berry"
species = "berry"
@@ -31,7 +31,7 @@
// Poison Berries
/obj/item/seeds/berry/poison
- name = "pack of poison-berry seeds"
+ name = "poison-berry seed pack"
desc = "These seeds grow into poison-berry bushes."
icon_state = "seed-poisonberry"
species = "poisonberry"
@@ -55,7 +55,7 @@
// Death Berries
/obj/item/seeds/berry/death
- name = "pack of death-berry seeds"
+ name = "death-berry seed pack"
desc = "These seeds grow into death berries."
icon_state = "seed-deathberry"
species = "deathberry"
@@ -81,7 +81,7 @@
// Glow Berries
/obj/item/seeds/berry/glow
- name = "pack of glow-berry seeds"
+ name = "glow-berry seed pack"
desc = "These seeds grow into glow-berry bushes."
icon_state = "seed-glowberry"
species = "glowberry"
@@ -108,7 +108,7 @@
// Grapes
/obj/item/seeds/grape
- name = "pack of grape seeds"
+ name = "grape seed pack"
desc = "These seeds grow into grape vines."
icon_state = "seed-grapes"
species = "grape"
@@ -143,7 +143,7 @@
// Green Grapes
/obj/item/seeds/grape/green
- name = "pack of green grape seeds"
+ name = "green grape seed pack"
desc = "These seeds grow into green-grape vines."
icon_state = "seed-greengrapes"
species = "greengrape"
@@ -162,7 +162,7 @@
// Toechtauese Berries
/obj/item/seeds/toechtauese
- name = "pack of töchtaüse berry seeds"
+ name = "töchtaüse berry seed pack"
desc = "These seeds grow into töchtaüse bushes."
icon_state = "seed-toechtauese"
species = "toechtauese"
@@ -190,7 +190,7 @@
distill_reagent = /datum/reagent/toxin/itching_powder
/obj/item/seeds/lanternfruit
- name = "pack of lanternfruit seeds"
+ name = "lanternfruit seed pack"
desc = "These seeds grow into lanternfruit pods."
icon_state = "seed-lanternfruit"
species = "lanternfruit"
diff --git a/code/modules/hydroponics/grown/cannabis.dm b/code/modules/hydroponics/grown/cannabis.dm
index b4cd35899d25a5..6309ae8475bf8b 100644
--- a/code/modules/hydroponics/grown/cannabis.dm
+++ b/code/modules/hydroponics/grown/cannabis.dm
@@ -1,6 +1,6 @@
// Cannabis
/obj/item/seeds/cannabis
- name = "pack of cannabis seeds"
+ name = "cannabis seed pack"
desc = "Taxable."
icon_state = "seed-cannabis"
plant_icon_offset = 6
@@ -24,7 +24,7 @@
/obj/item/seeds/cannabis/rainbow
- name = "pack of rainbow weed seeds"
+ name = "rainbow weed seed pack"
desc = "These seeds grow into rainbow weed. Groovy... and also highly addictive."
icon_state = "seed-megacannabis"
icon_grow = "megacannabis-grow"
@@ -36,7 +36,7 @@
rarity = 40
/obj/item/seeds/cannabis/death
- name = "pack of deathweed seeds"
+ name = "deathweed seed pack"
desc = "These seeds grow into deathweed. Not groovy."
icon_state = "seed-blackcannabis"
icon_grow = "blackcannabis-grow"
@@ -48,7 +48,7 @@
rarity = 40
/obj/item/seeds/cannabis/white
- name = "pack of lifeweed seeds"
+ name = "lifeweed seed pack"
desc = "I will give unto him that is munchies of the fountain of the cravings of life, freely."
icon_state = "seed-whitecannabis"
icon_grow = "whitecannabis-grow"
@@ -62,7 +62,7 @@
/obj/item/seeds/cannabis/ultimate
- name = "pack of omega weed seeds"
+ name = "omega weed seed pack"
desc = "These seeds grow into omega weed."
icon_state = "seed-ocannabis"
plant_icon_offset = 0
diff --git a/code/modules/hydroponics/grown/cereals.dm b/code/modules/hydroponics/grown/cereals.dm
index 744c0dc5b023cf..b304382d2dc471 100644
--- a/code/modules/hydroponics/grown/cereals.dm
+++ b/code/modules/hydroponics/grown/cereals.dm
@@ -1,6 +1,6 @@
// Wheat
/obj/item/seeds/wheat
- name = "pack of wheat seeds"
+ name = "wheat seed pack"
desc = "These may, or may not, grow into wheat."
icon_state = "seed-wheat"
species = "wheat"
@@ -30,7 +30,7 @@
// Oat
/obj/item/seeds/wheat/oat
- name = "pack of oat seeds"
+ name = "oat seed pack"
desc = "These may, or may not, grow into oat."
icon_state = "seed-oat"
species = "oat"
@@ -52,7 +52,7 @@
// Rice
/obj/item/seeds/wheat/rice
- name = "pack of rice seeds"
+ name = "rice seed pack"
desc = "These may, or may not, grow into rice."
icon_state = "seed-rice"
species = "rice"
@@ -76,7 +76,7 @@
//Meatwheat - grows into synthetic meat
/obj/item/seeds/wheat/meat
- name = "pack of meatwheat seeds"
+ name = "meatwheat seed pack"
desc = "If you ever wanted to drive a vegetarian to insanity, here's how."
icon_state = "seed-meatwheat"
species = "meatwheat"
diff --git a/code/modules/hydroponics/grown/cherries.dm b/code/modules/hydroponics/grown/cherries.dm
index 4ebd42489d96f8..ad35bacf8fe71a 100644
--- a/code/modules/hydroponics/grown/cherries.dm
+++ b/code/modules/hydroponics/grown/cherries.dm
@@ -1,6 +1,6 @@
// Cherries
/obj/item/seeds/cherry
- name = "pack of cherry pits"
+ name = "cherry pit pack"
desc = "Careful not to crack a tooth on one... That'd be the pits."
icon_state = "seed-cherry"
species = "cherry"
@@ -34,7 +34,7 @@
// Blue Cherries
/obj/item/seeds/cherry/blue
- name = "pack of blue cherry pits"
+ name = "blue cherry pit pack"
desc = "The blue kind of cherries."
icon_state = "seed-bluecherry"
species = "bluecherry"
@@ -57,7 +57,7 @@
//Cherry Bulbs
/obj/item/seeds/cherry/bulb
- name = "pack of cherry bulb pits"
+ name = "cherry bulb pit pack"
desc = "The glowy kind of cherries."
icon_state = "seed-cherrybulb"
species = "cherrybulb"
@@ -82,7 +82,7 @@
//Cherry Bombs
/obj/item/seeds/cherry/bomb
- name = "pack of cherry bomb pits"
+ name = "cherry bomb pit pack"
desc = "They give you vibes of dread and frustration."
icon_state = "seed-cherry_bomb"
species = "cherry_bomb"
diff --git a/code/modules/hydroponics/grown/chili.dm b/code/modules/hydroponics/grown/chili.dm
index 9f6d3bbd08ce0e..1d9aaa8468ebf0 100644
--- a/code/modules/hydroponics/grown/chili.dm
+++ b/code/modules/hydroponics/grown/chili.dm
@@ -1,6 +1,6 @@
// Chili
/obj/item/seeds/chili
- name = "pack of chili seeds"
+ name = "chili seed pack"
desc = "These seeds grow into chili plants. HOT! HOT! HOT!"
icon_state = "seed-chili"
species = "chili"
@@ -30,7 +30,7 @@
// Ice Chili
/obj/item/seeds/chili/ice
- name = "pack of chilly pepper seeds"
+ name = "chilly pepper seed pack"
desc = "These seeds grow into chilly pepper plants."
icon_state = "seed-icepepper"
species = "chiliice"
@@ -56,7 +56,7 @@
// Ghost Chili
/obj/item/seeds/chili/ghost
- name = "pack of ghost chili seeds"
+ name = "ghost chili seed pack"
desc = "These seeds grow into a chili said to be the hottest in the galaxy."
icon_state = "seed-chilighost"
species = "chilighost"
@@ -83,7 +83,7 @@
// Bell Pepper
/obj/item/seeds/chili/bell_pepper
- name = "pack of bell pepper seeds"
+ name = "bell pepper seed pack"
desc = "These seeds grow into bell pepper plants. MILD! MILD! MILD!"
icon_state = "seed-bell-pepper"
species = "bellpepper"
diff --git a/code/modules/hydroponics/grown/citrus.dm b/code/modules/hydroponics/grown/citrus.dm
index c624722f82392b..6bfc8bc203af53 100644
--- a/code/modules/hydroponics/grown/citrus.dm
+++ b/code/modules/hydroponics/grown/citrus.dm
@@ -9,7 +9,7 @@
// Lime
/obj/item/seeds/lime
- name = "pack of lime seeds"
+ name = "lime seed pack"
desc = "These are very sour seeds."
icon_state = "seed-lime"
species = "lime"
@@ -33,7 +33,7 @@
// Orange
/obj/item/seeds/orange
- name = "pack of orange seeds"
+ name = "orange seed pack"
desc = "Sour seeds."
icon_state = "seed-orange"
species = "orange"
@@ -61,7 +61,7 @@
// Lemon
/obj/item/seeds/lemon
- name = "pack of lemon seeds"
+ name = "lemon seed pack"
desc = "These are sour seeds."
icon_state = "seed-lemon"
species = "lemon"
@@ -86,7 +86,7 @@
// Combustible lemon
/obj/item/seeds/firelemon //combustible lemon is too long so firelemon
- name = "pack of combustible lemon seeds"
+ name = "combustible lemon seed pack"
desc = "When life gives you lemons, don't make lemonade. Make life take the lemons back! Get mad! I don't want your damn lemons!"
icon_state = "seed-firelemon"
species = "firelemon"
@@ -112,7 +112,7 @@
//3D Orange
/obj/item/seeds/orange_3d
- name = "pack of extradimensional orange seeds"
+ name = "extradimensional orange seed pack"
desc = "Polygonal seeds."
icon_state = "seed-orange"
species = "orange"
diff --git a/code/modules/hydroponics/grown/cocoa_vanilla.dm b/code/modules/hydroponics/grown/cocoa_vanilla.dm
index 4e9a9810b42804..e4b6c916f7cc99 100644
--- a/code/modules/hydroponics/grown/cocoa_vanilla.dm
+++ b/code/modules/hydroponics/grown/cocoa_vanilla.dm
@@ -1,6 +1,6 @@
// Cocoa Pod
/obj/item/seeds/cocoapod
- name = "pack of cocoa pod seeds"
+ name = "cocoa pod seed pack"
desc = "These seeds grow into cacao trees. They look fattening." //SIC: cocoa is the seeds. The trees are spelled cacao.
icon_state = "seed-cocoapod"
species = "cocoapod"
@@ -31,7 +31,7 @@
// Vanilla Pod
/obj/item/seeds/cocoapod/vanillapod
- name = "pack of vanilla pod seeds"
+ name = "vanilla pod seed pack"
desc = "These seeds grow into vanilla trees. They look fattening."
icon_state = "seed-vanillapod"
species = "vanillapod"
@@ -52,7 +52,7 @@
distill_reagent = /datum/reagent/consumable/vanilla //Takes longer, but you can get even more vanilla from it.
/obj/item/seeds/cocoapod/bungotree
- name = "pack of bungo tree seeds"
+ name = "bungo tree seed pack"
desc = "These seeds grow into bungo trees. They appear to be heavy and almost perfectly spherical."
icon_state = "seed-bungotree"
plant_icon_offset = 4
diff --git a/code/modules/hydroponics/grown/corn.dm b/code/modules/hydroponics/grown/corn.dm
index d5f9f94e1b2dfd..02f77280c5ab9c 100644
--- a/code/modules/hydroponics/grown/corn.dm
+++ b/code/modules/hydroponics/grown/corn.dm
@@ -1,6 +1,6 @@
// Corn
/obj/item/seeds/corn
- name = "pack of corn seeds"
+ name = "corn seed pack"
desc = "I don't mean to sound corny..."
icon_state = "seed-corn"
species = "corn"
@@ -57,7 +57,7 @@
// Snapcorn
/obj/item/seeds/corn/snapcorn
- name = "pack of snapcorn seeds"
+ name = "snapcorn seed pack"
desc = "Oh snap!"
icon_state = "seed-snapcorn"
species = "snapcorn"
@@ -100,7 +100,7 @@
//Pepper-corn - Heh funny.
/obj/item/seeds/corn/pepper
- name = "pack of pepper-corn seeds"
+ name = "pepper-corn seed pack"
desc = "If Peter picked a pack of pepper-corn..."
icon_state = "seed-peppercorn"
species = "peppercorn"
diff --git a/code/modules/hydroponics/grown/cotton.dm b/code/modules/hydroponics/grown/cotton.dm
index 819d97f321f8de..c2149b7a330061 100644
--- a/code/modules/hydroponics/grown/cotton.dm
+++ b/code/modules/hydroponics/grown/cotton.dm
@@ -1,5 +1,5 @@
/obj/item/seeds/cotton
- name = "pack of cotton seeds"
+ name = "cotton seed pack"
desc = "A pack of seeds that'll grow into a cotton plant. Assistants make good free labor if neccesary."
icon_state = "seed-cotton"
species = "cotton"
@@ -45,7 +45,7 @@
//reinforced mutated variant
/obj/item/seeds/cotton/durathread
- name = "pack of durathread seeds"
+ name = "durathread seed pack"
desc = "A pack of seeds that'll grow into an extremely durable thread that could easily rival plasteel if woven properly."
icon_state = "seed-durathread"
species = "durathread"
diff --git a/code/modules/hydroponics/grown/cucumber.dm b/code/modules/hydroponics/grown/cucumber.dm
index f3712c6a5c90a7..a8487a0cac9bc7 100644
--- a/code/modules/hydroponics/grown/cucumber.dm
+++ b/code/modules/hydroponics/grown/cucumber.dm
@@ -1,6 +1,6 @@
// CUCUMBERS YEAH
/obj/item/seeds/cucumber
- name = "pack of cucumber seeds"
+ name = "cucumber seed pack"
desc = "These seeds grow into cucumber plants."
icon_state = "seed-cucumber"
species = "cucumber"
diff --git a/code/modules/hydroponics/grown/eggplant.dm b/code/modules/hydroponics/grown/eggplant.dm
index d4b38c3438bdbe..47cbc6d934cd38 100644
--- a/code/modules/hydroponics/grown/eggplant.dm
+++ b/code/modules/hydroponics/grown/eggplant.dm
@@ -1,6 +1,6 @@
// Eggplant
/obj/item/seeds/eggplant
- name = "pack of eggplant seeds"
+ name = "eggplant seed pack"
desc = "These seeds grow to produce berries that look nothing like eggs."
icon_state = "seed-eggplant"
species = "eggplant"
@@ -25,7 +25,7 @@
// Egg-Plant
/obj/item/seeds/eggplant/eggy
- name = "pack of egg-plant seeds"
+ name = "egg-plant seed pack"
desc = "These seeds grow to produce berries that look a lot like eggs."
icon_state = "seed-eggy"
species = "eggy"
diff --git a/code/modules/hydroponics/grown/flowers.dm b/code/modules/hydroponics/grown/flowers.dm
index 84b1414335cafa..d4ef53474fc975 100644
--- a/code/modules/hydroponics/grown/flowers.dm
+++ b/code/modules/hydroponics/grown/flowers.dm
@@ -1,6 +1,6 @@
// Poppy
/obj/item/seeds/poppy
- name = "pack of poppy seeds"
+ name = "poppy seed pack"
desc = "These seeds grow into poppies."
icon_state = "seed-poppy"
species = "poppy"
@@ -32,7 +32,7 @@
// Lily
/obj/item/seeds/poppy/lily
- name = "pack of lily seeds"
+ name = "lily seed pack"
desc = "These seeds grow into lilies."
icon_state = "seed-lily"
species = "lily"
@@ -52,7 +52,7 @@
//Spacemans's Trumpet
/obj/item/seeds/poppy/lily/trumpet
- name = "pack of spaceman's trumpet seeds"
+ name = "spaceman's trumpet seed pack"
desc = "A plant sculped by extensive genetic engineering. The spaceman's trumpet is said to bear no resemblance to its wild ancestors. Inside NT AgriSci circles it is better known as NTPW-0372."
icon_state = "seed-trumpet"
species = "spacemanstrumpet"
@@ -86,7 +86,7 @@
// Geranium
/obj/item/seeds/poppy/geranium
- name = "pack of geranium seeds"
+ name = "geranium seed pack"
desc = "These seeds grow into geranium."
icon_state = "seed-geranium"
species = "geranium"
@@ -106,7 +106,7 @@
///Fraxinella seeds.
/obj/item/seeds/poppy/geranium/fraxinella
- name = "pack of fraxinella seeds"
+ name = "fraxinella seed pack"
desc = "These seeds grow into fraxinella."
icon_state = "seed-fraxinella"
species = "fraxinella"
@@ -130,7 +130,7 @@
// Harebell
/obj/item/seeds/harebell
- name = "pack of harebell seeds"
+ name = "harebell seed pack"
desc = "These seeds grow into pretty little flowers."
icon_state = "seed-harebell"
plant_icon_offset = 1
@@ -162,7 +162,7 @@
// Sunflower
/obj/item/seeds/sunflower
- name = "pack of sunflower seeds"
+ name = "sunflower seed pack"
desc = "These seeds grow into sunflowers."
icon_state = "seed-sunflower"
species = "sunflower"
@@ -203,7 +203,7 @@
// Moonflower
/obj/item/seeds/sunflower/moonflower
- name = "pack of moonflower seeds"
+ name = "moonflower seed pack"
desc = "These seeds grow into moonflowers."
icon_state = "seed-moonflower"
lefthand_file = 'icons/mob/inhands/items/food_lefthand.dmi'
@@ -231,7 +231,7 @@
// Novaflower
/obj/item/seeds/sunflower/novaflower
- name = "pack of novaflower seeds"
+ name = "novaflower seed pack"
desc = "These seeds grow into novaflowers."
icon_state = "seed-novaflower"
species = "novaflower"
@@ -266,7 +266,7 @@
// Rose
/obj/item/seeds/rose
- name = "pack of rose seeds"
+ name = "rose seed pack"
desc = "These seeds grow into roses."
icon_state = "seed-rose"
species = "rose"
@@ -311,7 +311,7 @@
// Carbon Rose
/obj/item/seeds/carbon_rose
- name = "pack of carbon rose seeds"
+ name = "carbon rose seed pack"
desc = "These seeds grow into carbon roses."
icon_state = "seed-carbonrose"
species = "carbonrose"
diff --git a/code/modules/hydroponics/grown/garlic.dm b/code/modules/hydroponics/grown/garlic.dm
index e37d49fa93032f..755d0c2920a3f8 100644
--- a/code/modules/hydroponics/grown/garlic.dm
+++ b/code/modules/hydroponics/grown/garlic.dm
@@ -1,5 +1,5 @@
/obj/item/seeds/garlic
- name = "pack of garlic seeds"
+ name = "garlic seed pack"
desc = "A packet of extremely pungent seeds."
icon_state = "seed-garlic"
species = "garlic"
diff --git a/code/modules/hydroponics/grown/gatfruit.dm b/code/modules/hydroponics/grown/gatfruit.dm
index f64b6eb3bd4819..c6de17d6eb684c 100644
--- a/code/modules/hydroponics/grown/gatfruit.dm
+++ b/code/modules/hydroponics/grown/gatfruit.dm
@@ -1,7 +1,7 @@
// Gatfruit
/obj/item/seeds/gatfruit
- name = "pack of gatfruit seeds"
+ name = "gatfruit seed pack"
desc = "These seeds grow into .357 revolvers."
icon_state = "seed-gatfruit"
species = "gatfruit"
diff --git a/code/modules/hydroponics/grown/grass_carpet.dm b/code/modules/hydroponics/grown/grass_carpet.dm
index 732a6d32b881b7..a5cdc08fb7658f 100644
--- a/code/modules/hydroponics/grown/grass_carpet.dm
+++ b/code/modules/hydroponics/grown/grass_carpet.dm
@@ -1,6 +1,6 @@
// Grass
/obj/item/seeds/grass
- name = "pack of grass seeds"
+ name = "grass seed pack"
desc = "These seeds grow into grass. Yummy!"
icon_state = "seed-grass"
species = "grass"
@@ -42,7 +42,7 @@
//Fairygrass
/obj/item/seeds/grass/fairy
- name = "pack of fairygrass seeds"
+ name = "fairygrass seed pack"
desc = "These seeds grow into a more mystical grass."
icon_state = "seed-fairygrass"
species = "fairygrass"
@@ -65,7 +65,7 @@
// Carpet
/obj/item/seeds/grass/carpet
- name = "pack of carpet seeds"
+ name = "carpet seed pack"
desc = "These seeds grow into stylish carpet samples."
icon_state = "seed-carpet"
species = "carpet"
diff --git a/code/modules/hydroponics/grown/hedges.dm b/code/modules/hydroponics/grown/hedges.dm
index 9127f70f78fd46..d02949bfd98136 100644
--- a/code/modules/hydroponics/grown/hedges.dm
+++ b/code/modules/hydroponics/grown/hedges.dm
@@ -1,5 +1,5 @@
/obj/item/seeds/shrub
- name = "pack of shrub seeds"
+ name = "shrub seed pack"
desc = "These seeds grow into hedge shrubs."
icon_state = "seed-shrub"
species = "shrub"
diff --git a/code/modules/hydroponics/grown/herbs.dm b/code/modules/hydroponics/grown/herbs.dm
index b22be06ec6aca6..bc450d6857f188 100644
--- a/code/modules/hydroponics/grown/herbs.dm
+++ b/code/modules/hydroponics/grown/herbs.dm
@@ -1,6 +1,6 @@
// Herbs
/obj/item/seeds/herbs
- name = "pack of herb seeds"
+ name = "herb seed pack"
desc = "These seeds grow to produce an assortment of herbs and seasonings."
icon_state = "seed-herbs"
species = "herbs"
diff --git a/code/modules/hydroponics/grown/korta_nut.dm b/code/modules/hydroponics/grown/korta_nut.dm
index cfa6c1e5b51f33..457ebff07163ed 100644
--- a/code/modules/hydroponics/grown/korta_nut.dm
+++ b/code/modules/hydroponics/grown/korta_nut.dm
@@ -1,6 +1,6 @@
//Korta Nut
/obj/item/seeds/korta_nut
- name = "pack of korta nut seeds"
+ name = "korta nut seed pack"
desc = "These seeds grow into korta nut bushes, native to Tizira."
icon_state = "seed-korta"
species = "kortanut"
@@ -29,7 +29,7 @@
//Sweet Korta Nut
/obj/item/seeds/korta_nut/sweet
- name = "pack of sweet korta nut seeds"
+ name = "sweet korta nut seed pack"
desc = "These seeds grow into sweet korta nuts, a mutation of the original species that produces a thick syrup that Tizirans use for desserts."
icon_state = "seed-sweetkorta"
species = "kortanut"
diff --git a/code/modules/hydroponics/grown/kronkus.dm b/code/modules/hydroponics/grown/kronkus.dm
index 90d264230e7503..b4ba30a5eddbe6 100644
--- a/code/modules/hydroponics/grown/kronkus.dm
+++ b/code/modules/hydroponics/grown/kronkus.dm
@@ -1,5 +1,5 @@
/obj/item/seeds/kronkus
- name = "pack of kronkus seeds"
+ name = "kronkus seed pack"
desc = "A pack of highly illegal kronkus seeds.\nPossession of these seeds carries the death penalty in 7 sectors."
icon_state = "seed-kronkus"
plant_icon_offset = 6
diff --git a/code/modules/hydroponics/grown/melon.dm b/code/modules/hydroponics/grown/melon.dm
index 0e59231141fc43..3aca50ae1be54f 100644
--- a/code/modules/hydroponics/grown/melon.dm
+++ b/code/modules/hydroponics/grown/melon.dm
@@ -1,6 +1,6 @@
// Watermelon
/obj/item/seeds/watermelon
- name = "pack of watermelon seeds"
+ name = "watermelon seed pack"
desc = "These seeds grow into watermelon plants."
icon_state = "seed-watermelon"
species = "watermelon"
@@ -27,6 +27,7 @@
name = "watermelon"
desc = "It's full of watery goodness."
icon_state = "watermelon"
+ inhand_icon_state = "watermelon"
bite_consumption_mod = 2
w_class = WEIGHT_CLASS_NORMAL
foodtypes = FRUIT
@@ -39,9 +40,41 @@
/obj/item/food/grown/watermelon/make_dryable()
return //No drying
+/obj/item/food/grown/watermelon/attackby(obj/item/I, mob/user, params)
+ if(!istype(I, /obj/item/kitchen/spoon))
+ return ..()
+
+ var/melon_pulp_count = 1
+ if(seed)
+ melon_pulp_count += round(seed.potency / 25)
+
+ user.balloon_alert(user, "scooped out [melon_pulp_count] pulp(s)")
+ for(var/i in 1 to melon_pulp_count)
+ new /obj/item/food/watermelonmush(user.loc)
+
+ /// The piece of armour melon turns into; either chetsplate or helmet
+ var/obj/item/clothing/melon_armour
+ /// Chance for the armour to be a chestplate instead of the helmet
+ var/melon_chestplate_chance = (max(0, seed.potency - 50) / 50)
+ if (prob(melon_chestplate_chance))
+ if(seed.resistance_flags & FIRE_PROOF)
+ melon_armour = new /obj/item/clothing/suit/armor/durability/watermelon/fire_resist
+ else
+ melon_armour = new /obj/item/clothing/suit/armor/durability/watermelon
+ to_chat(user, span_notice("You hollow the melon into a helmet with [I]."))
+ else
+ if(seed.resistance_flags & FIRE_PROOF)
+ melon_armour = new /obj/item/clothing/head/helmet/durability/watermelon/fire_resist
+ else
+ melon_armour = new /obj/item/clothing/head/helmet/durability/watermelon
+ to_chat(user, span_notice("You hollow the melon into a chestplate with [I]."))
+ remove_item_from_storage(user)
+ qdel(src)
+ user.put_in_hands(melon_armour)
+
// Holymelon
/obj/item/seeds/watermelon/holy
- name = "pack of holymelon seeds"
+ name = "holymelon seed pack"
desc = "These seeds grow into holymelon plants."
icon_state = "seed-holymelon"
species = "holymelon"
@@ -66,6 +99,9 @@
wine_power = 70 //Water to wine, baby.
wine_flavor = "divinity"
+/obj/item/food/grown/holymelon/make_processable()
+ AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/holymelonslice, 5, 20, screentip_verb = "Slice")
+
/obj/item/food/grown/holymelon/make_dryable()
return //No drying
@@ -73,6 +109,39 @@
. = ..()
AddComponent(/datum/component/edible, check_liked = CALLBACK(src, PROC_REF(check_holyness)))
+
+/obj/item/food/grown/holymelon/attackby(obj/item/I, mob/user, params)
+ if(!istype(I, /obj/item/kitchen/spoon))
+ return ..()
+
+ var/holymelon_pulp_count = 1
+ if(seed)
+ holymelon_pulp_count += round(seed.potency / 25)
+
+ user.balloon_alert(user, "scooped out [holymelon_pulp_count] pulp(s)")
+ for(var/i in 1 to holymelon_pulp_count)
+ new /obj/item/food/holymelonmush(user.loc)
+
+ /// The piece of armour holymelon turns into; either chetsplate or helmet
+ var/obj/item/clothing/holymelon_armour
+ /// Chance for the armour to be a chestplate instead of the helmet
+ var/holymelon_chestplate_chance = (max(0, seed.potency - 50) / 50)
+ if (prob(holymelon_chestplate_chance))
+ if(seed.resistance_flags & FIRE_PROOF)
+ holymelon_armour = new /obj/item/clothing/suit/armor/durability/holymelon/fire_resist
+ else
+ holymelon_armour = new /obj/item/clothing/suit/armor/durability/holymelon
+ to_chat(user, span_notice("You hollow the holymelon into a helmet with [I]."))
+ else
+ if(seed.resistance_flags & FIRE_PROOF)
+ holymelon_armour = new /obj/item/clothing/head/helmet/durability/holymelon/fire_resist
+ else
+ holymelon_armour = new /obj/item/clothing/head/helmet/durability/holymelon
+ to_chat(user, span_notice("You hollow the holymelon into a chestplate with [I]."))
+ remove_item_from_storage(user)
+ qdel(src)
+ user.put_in_hands(holymelon_armour)
+
/*
* Callback to be used with the edible component.
* Checks whether or not the person eating the holymelon
@@ -90,7 +159,7 @@
/// Barrel melon Seeds
/obj/item/seeds/watermelon/barrel
- name = "pack of barrelmelon seeds"
+ name = "barrelmelon seed pack"
desc = "These seeds grow into barrelmelon plants."
icon_state = "seed-barrelmelon"
species = "barrelmelon"
@@ -108,4 +177,41 @@
name = "barrelmelon"
desc = "The nutriments within this melon have been compressed and fermented into rich alcohol."
icon_state = "barrelmelon"
+ inhand_icon_state = "barrelmelon"
distill_reagent = /datum/reagent/medicine/antihol //You can call it a integer overflow.
+
+/obj/item/food/grown/barrelmelon/make_processable()
+ AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/barrelmelonslice, 5, 20, screentip_verb = "Chop")
+
+/obj/item/food/grown/barrelmelon/attackby(obj/item/I, mob/user, params)
+ if(!istype(I, /obj/item/kitchen/spoon))
+ return ..()
+
+ var/barrelmelon_pulp_count = 1
+ if(seed)
+ barrelmelon_pulp_count += round(seed.potency / 25)
+
+ user.balloon_alert(user, "scooped out [barrelmelon_pulp_count] pulp(s)")
+ for(var/i in 1 to barrelmelon_pulp_count)
+ new /obj/item/food/barrelmelonmush(user.loc)
+
+ /// The piece of armour barrelmelon turns into; either chetsplate or helmet
+ var/obj/item/clothing/barrelmelon_armour
+ /// Chance for the armour to be a chestplate instead of the helmet
+ var/barrelmelon_chestplate_chance = (max(0, seed.potency - 50) / 50)
+ if (prob(barrelmelon_chestplate_chance))
+ if(seed.resistance_flags & FIRE_PROOF)
+ barrelmelon_armour = new /obj/item/clothing/suit/armor/durability/barrelmelon/fire_resist
+ else
+ barrelmelon_armour = new /obj/item/clothing/suit/armor/durability/barrelmelon
+ to_chat(user, span_notice("You hollow the barrelmelon into a helmet with [I]."))
+ else
+ if(seed.resistance_flags & FIRE_PROOF)
+ barrelmelon_armour = new /obj/item/clothing/head/helmet/durability/barrelmelon/fire_resist
+ else
+ barrelmelon_armour = new /obj/item/clothing/head/helmet/durability/barrelmelon
+ to_chat(user, span_notice("You hollow the barrelmelon into a chestplate with [I]."))
+
+ remove_item_from_storage(user)
+ qdel(src)
+ user.put_in_hands(barrelmelon_armour)
diff --git a/code/modules/hydroponics/grown/mushrooms.dm b/code/modules/hydroponics/grown/mushrooms.dm
index bfc50f0c483b3b..9af495f6a61280 100644
--- a/code/modules/hydroponics/grown/mushrooms.dm
+++ b/code/modules/hydroponics/grown/mushrooms.dm
@@ -11,7 +11,7 @@
// Reishi
/obj/item/seeds/reishi
- name = "pack of reishi mycelium"
+ name = "reishi mycelium pack"
desc = "This mycelium grows into something medicinal and relaxing."
icon_state = "mycelium-reishi"
species = "reishi"
@@ -38,7 +38,7 @@
// Fly Amanita
/obj/item/seeds/amanita
- name = "pack of fly amanita mycelium"
+ name = "fly amanita mycelium pack"
desc = "This mycelium grows into something horrible."
icon_state = "mycelium-amanita"
species = "amanita"
@@ -65,7 +65,7 @@
// Destroying Angel
/obj/item/seeds/angel
- name = "pack of destroying angel mycelium"
+ name = "destroying angel mycelium pack"
desc = "This mycelium grows into something devastating."
icon_state = "mycelium-angel"
species = "angel"
@@ -93,7 +93,7 @@
// Liberty Cap
/obj/item/seeds/liberty
- name = "pack of liberty-cap mycelium"
+ name = "liberty-cap mycelium pack"
desc = "This mycelium grows into liberty-cap mushrooms."
icon_state = "mycelium-liberty"
species = "liberty"
@@ -119,7 +119,7 @@
// Plump Helmet
/obj/item/seeds/plump
- name = "pack of plump-helmet mycelium"
+ name = "plump-helmet mycelium pack"
desc = "This mycelium grows into helmets... maybe."
icon_state = "mycelium-plump"
species = "plump"
@@ -145,7 +145,7 @@
// Walking Mushroom
/obj/item/seeds/plump/walkingmushroom
- name = "pack of walking mushroom mycelium"
+ name = "walking mushroom mycelium pack"
desc = "This mycelium will grow into huge stuff!"
icon_state = "mycelium-walkingmushroom"
species = "walkingmushroom"
@@ -171,7 +171,7 @@
// Chanterelle
/obj/item/seeds/chanter
- name = "pack of chanterelle mycelium"
+ name = "chanterelle mycelium pack"
desc = "This mycelium grows into chanterelle mushrooms."
icon_state = "mycelium-chanter"
species = "chanter"
@@ -197,9 +197,23 @@
desc = "Cantharellus Cibarius: These jolly yellow little shrooms sure look tasty!"
icon_state = "chanterelle"
+/obj/item/food/grown/mushroom/chanterelle/attackby(obj/item/I, mob/user, params)
+ if(!istype(I, /obj/item/kitchen/spoon))
+ return ..()
+ if(seed.potency < 95)
+ return ..()
+
+ to_chat(user, span_notice("You hollow up the chanterelle with [I]."))
+ remove_item_from_storage(user)
+ if(seed.resistance_flags & FIRE_PROOF)
+ user.put_in_hands(new /obj/item/clothing/head/wizard/chanterelle/fr())
+ else
+ user.put_in_hands(new /obj/item/clothing/head/wizard/chanterelle())
+ qdel(src)
+
//Jupiter Cup
/obj/item/seeds/chanter/jupitercup
- name = "pack of jupiter cup mycelium"
+ name = "jupiter cup mycelium pack"
desc = "This mycelium grows into jupiter cups. Zeus would be envious at the power at your fingertips."
icon_state = "mycelium-jupitercup"
species = "jupitercup"
@@ -224,7 +238,7 @@
// Glowshroom
/obj/item/seeds/glowshroom
- name = "pack of glowshroom mycelium"
+ name = "glowshroom mycelium pack"
desc = "This mycelium -glows- into mushrooms!"
icon_state = "mycelium-glowshroom"
species = "glowshroom"
@@ -279,7 +293,7 @@
// Glowcap
/obj/item/seeds/glowshroom/glowcap
- name = "pack of glowcap mycelium"
+ name = "glowcap mycelium pack"
desc = "This mycelium -powers- into mushrooms!"
icon_state = "mycelium-glowcap"
species = "glowcap"
@@ -303,7 +317,7 @@
//Shadowshroom
/obj/item/seeds/glowshroom/shadowshroom
- name = "pack of shadowshroom mycelium"
+ name = "shadowshroom mycelium pack"
desc = "This mycelium will grow into something shadowy."
icon_state = "mycelium-shadowshroom"
species = "shadowshroom"
@@ -332,7 +346,7 @@
investigate_log("was planted by [key_name(user)] at [AREACOORD(user)]", INVESTIGATE_BOTANY)
/obj/item/seeds/odious_puffball
- name = "pack of odious pullball spores"
+ name = "odious pullball spore pack"
desc = "These spores reek! Disgusting."
icon_state = "seed-odiouspuffball"
species = "odiouspuffball"
diff --git a/code/modules/hydroponics/grown/olive.dm b/code/modules/hydroponics/grown/olive.dm
index 38102cacb24eab..0b2f52c7a5e7bb 100644
--- a/code/modules/hydroponics/grown/olive.dm
+++ b/code/modules/hydroponics/grown/olive.dm
@@ -1,6 +1,6 @@
// Olive
/obj/item/seeds/olive
- name = "pack of olive seeds"
+ name = "olive seed pack"
desc = "These seeds grow into olive trees."
icon_state = "seed-olive"
species = "olive"
diff --git a/code/modules/hydroponics/grown/onion.dm b/code/modules/hydroponics/grown/onion.dm
index 8f948407a37b85..0d33c3e1f395d7 100644
--- a/code/modules/hydroponics/grown/onion.dm
+++ b/code/modules/hydroponics/grown/onion.dm
@@ -1,5 +1,5 @@
/obj/item/seeds/onion
- name = "pack of onion seeds"
+ name = "onion seed pack"
desc = "These seeds grow into onions."
icon_state = "seed-onion"
species = "onion"
@@ -29,7 +29,7 @@
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/onion_slice, 2, 15, screentip_verb = "Cut")
/obj/item/seeds/onion/red
- name = "pack of red onion seeds"
+ name = "red onion seed pack"
desc = "For growing exceptionally potent onions."
icon_state = "seed-onionred"
species = "onion_red"
diff --git a/code/modules/hydroponics/grown/peanut.dm b/code/modules/hydroponics/grown/peanut.dm
index 69cf6d9e0568dc..6560ec196c9189 100644
--- a/code/modules/hydroponics/grown/peanut.dm
+++ b/code/modules/hydroponics/grown/peanut.dm
@@ -1,6 +1,6 @@
// Peanuts!
/obj/item/seeds/peanut
- name = "pack of peanut seeds"
+ name = "peanut seed pack"
desc = "These seeds grow into peanut plants."
icon_state = "seed-peanut"
species = "peanut"
diff --git a/code/modules/hydroponics/grown/peas.dm b/code/modules/hydroponics/grown/peas.dm
index c232ed247c6905..66eaec6ff1d54d 100644
--- a/code/modules/hydroponics/grown/peas.dm
+++ b/code/modules/hydroponics/grown/peas.dm
@@ -1,6 +1,6 @@
// Finally, peas. Base plant.
/obj/item/seeds/peas
- name = "pack of pea pods"
+ name = "pea pod pack"
desc = "These seeds grows into vitamin rich peas!"
icon_state = "seed-peas"
species = "peas"
@@ -29,7 +29,7 @@
// Laughin' Peas
/obj/item/seeds/peas/laugh
- name = "pack of laughin' peas"
+ name = "laughin' pea pack"
desc = "These seeds give off a very soft purple glow.. they should grow into Laughin' Peas."
icon_state = "seed-laughpeas"
species = "laughpeas"
@@ -61,7 +61,7 @@
// World Peas - Peace at last, peace at last...
/obj/item/seeds/peas/laugh/peace
- name = "pack of world peas"
+ name = "world pea pack"
desc = "These rather large seeds give off a soothing blue glow..."
icon_state = "seed-worldpeas"
species = "worldpeas"
diff --git a/code/modules/hydroponics/grown/pineapple.dm b/code/modules/hydroponics/grown/pineapple.dm
index 3c0e462f38855c..5de85e9168f1f5 100644
--- a/code/modules/hydroponics/grown/pineapple.dm
+++ b/code/modules/hydroponics/grown/pineapple.dm
@@ -1,6 +1,6 @@
// Pineapple!
/obj/item/seeds/pineapple
- name = "pack of pineapple seeds"
+ name = "pineapple seed pack"
desc = "Oooooooooooooh!"
icon_state = "seed-pineapple"
species = "pineapple"
diff --git a/code/modules/hydroponics/grown/plum.dm b/code/modules/hydroponics/grown/plum.dm
index cac12bdb1eb5dc..c11acdf2db5536 100644
--- a/code/modules/hydroponics/grown/plum.dm
+++ b/code/modules/hydroponics/grown/plum.dm
@@ -1,6 +1,6 @@
// Plum
/obj/item/seeds/plum
- name = "pack of plum seeds"
+ name = "plum seed pack"
desc = "These seeds grow into plum trees."
icon_state = "seed-plum"
species = "plum"
@@ -28,7 +28,7 @@
// Plumb
/obj/item/seeds/plum/plumb
- name = "pack of plumb seeds"
+ name = "plumb seed pack"
desc = "These seeds grow into plumb trees."
icon_state = "seed-plumb"
species = "plumb"
diff --git a/code/modules/hydroponics/grown/potato.dm b/code/modules/hydroponics/grown/potato.dm
index 837937e41d1280..c57111b86d0c0e 100644
--- a/code/modules/hydroponics/grown/potato.dm
+++ b/code/modules/hydroponics/grown/potato.dm
@@ -1,6 +1,6 @@
// Potato
/obj/item/seeds/potato
- name = "pack of potato seeds"
+ name = "potato seed pack"
desc = "Boil 'em! Mash 'em! Stick 'em in a stew!"
icon_state = "seed-potato"
species = "potato"
@@ -50,7 +50,7 @@
// Sweet Potato
/obj/item/seeds/potato/sweet
- name = "pack of sweet potato seeds"
+ name = "sweet potato seed pack"
desc = "These seeds grow into sweet potato plants."
icon_state = "seed-sweetpotato"
species = "sweetpotato"
diff --git a/code/modules/hydroponics/grown/pumpkin.dm b/code/modules/hydroponics/grown/pumpkin.dm
index 11130c153344ab..dce207302c306a 100644
--- a/code/modules/hydroponics/grown/pumpkin.dm
+++ b/code/modules/hydroponics/grown/pumpkin.dm
@@ -1,6 +1,6 @@
// Pumpkin
/obj/item/seeds/pumpkin
- name = "pack of pumpkin seeds"
+ name = "pumpkin seed pack"
desc = "These seeds grow into pumpkin vines."
icon_state = "seed-pumpkin"
plant_icon_offset = 4
@@ -40,7 +40,7 @@
// Blumpkin
/obj/item/seeds/pumpkin/blumpkin
- name = "pack of blumpkin seeds"
+ name = "blumpkin seed pack"
desc = "These seeds grow into blumpkin vines."
icon_state = "seed-blumpkin"
species = "blumpkin"
diff --git a/code/modules/hydroponics/grown/rainbow_bunch.dm b/code/modules/hydroponics/grown/rainbow_bunch.dm
index 4ffad4583c705e..c3d21347bf9539 100644
--- a/code/modules/hydroponics/grown/rainbow_bunch.dm
+++ b/code/modules/hydroponics/grown/rainbow_bunch.dm
@@ -1,5 +1,5 @@
/obj/item/seeds/rainbow_bunch
- name = "pack of rainbow bunch seeds"
+ name = "rainbow bunch seed pack"
desc = "A pack of seeds that'll grow into a beautiful bush of various colored flowers."
icon_state = "seed-rainbowbunch"
species = "rainbowbunch"
diff --git a/code/modules/hydroponics/grown/random.dm b/code/modules/hydroponics/grown/random.dm
index 560e3c71e5ce6e..3a97277f0d85cc 100644
--- a/code/modules/hydroponics/grown/random.dm
+++ b/code/modules/hydroponics/grown/random.dm
@@ -1,7 +1,7 @@
//Random seeds; stats, traits, and plant type are randomized for each seed.
/obj/item/seeds/random
- name = "pack of strange seeds"
+ name = "strange seed pack"
desc = "Mysterious seeds as strange as their name implies. Spooky."
icon_state = "seed-x"
species = "?????"
diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm
index 88c8572a3ae75e..47047f2e48c377 100644
--- a/code/modules/hydroponics/grown/replicapod.dm
+++ b/code/modules/hydroponics/grown/replicapod.dm
@@ -2,7 +2,7 @@
// Yes, i'm talking about cabbage, baby! No, just kidding, but cabbages are the precursor to replica pods, so they are here as well.
/obj/item/seeds/cabbage
- name = "pack of cabbage seeds"
+ name = "cabbage seed pack"
desc = "These seeds grow into cabbages."
icon_state = "seed-cabbage"
species = "cabbage"
@@ -31,7 +31,7 @@
///The actual replica pods themselves!
/obj/item/seeds/replicapod
- name = "pack of replica pod seeds"
+ name = "replica pod seed pack"
desc = "These seeds grow into replica pods. They say these are used to harvest humans."
icon_state = "seed-replicapod"
plant_icon_offset = 2
diff --git a/code/modules/hydroponics/grown/root.dm b/code/modules/hydroponics/grown/root.dm
index c272b1e448462c..4393d76a5fa226 100644
--- a/code/modules/hydroponics/grown/root.dm
+++ b/code/modules/hydroponics/grown/root.dm
@@ -1,6 +1,6 @@
// Carrot
/obj/item/seeds/carrot
- name = "pack of carrot seeds"
+ name = "carrot seed pack"
desc = "These seeds grow into carrots."
icon_state = "seed-carrot"
species = "carrot"
@@ -12,7 +12,7 @@
instability = 15
growthstages = 3
growing_icon = 'icons/obj/service/hydroponics/growing_vegetables.dmi'
- mutatelist = list(/obj/item/seeds/carrot/parsnip)
+ mutatelist = list(/obj/item/seeds/carrot/parsnip, /obj/item/seeds/carrot/cahnroot)
reagents_add = list(/datum/reagent/medicine/oculine = 0.1, /datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.05)
/obj/item/food/grown/carrot
@@ -26,24 +26,26 @@
wine_power = 30
/obj/item/food/grown/carrot/attackby(obj/item/I, mob/user, params)
- if(I.get_sharpness())
- var/carrot_blade
- var/carrot_sword_chance = (max(0, seed.potency - 50) / 50)
- if (prob(carrot_sword_chance))
- carrot_blade = new /obj/item/claymore/carrot
- to_chat(user, span_notice("You sharpen the carrot into a sword with [I]."))
- else
- carrot_blade = new /obj/item/knife/shiv/carrot
- to_chat(user, span_notice("You sharpen the carrot into a shiv with [I]."))
- remove_item_from_storage(user)
- qdel(src)
- user.put_in_hands(carrot_blade)
- else
+ if(!I.get_sharpness())
return ..()
+ /// The blade carrot will turn into once sharpened
+ var/obj/item/carrot_blade
+ /// Chance for it to become a sword rather than a shiv
+ var/carrot_sword_chance = (max(0, seed.potency - 50) / 50)
+ if (prob(carrot_sword_chance))
+ carrot_blade = new /obj/item/claymore/carrot
+ to_chat(user, span_notice("You sharpen the carrot into a sword with [I]."))
+ else
+ carrot_blade = new /obj/item/knife/shiv/carrot
+ to_chat(user, span_notice("You sharpen the carrot into a shiv with [I]."))
+ remove_item_from_storage(user)
+ qdel(src)
+ user.put_in_hands(carrot_blade)
+
// Parsnip
/obj/item/seeds/carrot/parsnip
- name = "pack of parsnip seeds"
+ name = "parsnip seed pack"
desc = "These seeds grow into parsnips."
icon_state = "seed-parsnip"
species = "parsnip"
@@ -62,10 +64,73 @@
juice_typepath = /datum/reagent/consumable/parsnipjuice
wine_power = 35
+/obj/item/food/grown/parsnip/attackby(obj/item/I, mob/user, params)
+ if(!I.get_sharpness())
+ return ..()
+
+ /// The blade parsnip will turn into once sharpened
+ var/obj/item/parsnip_blade
+ /// Chance for it to become a sabre rather than a shiv
+ var/parsnip_sabre_chance = (max(0, seed.potency - 50) / 50)
+ if (prob(parsnip_sabre_chance))
+ parsnip_blade = new /obj/item/melee/parsnip_sabre
+ to_chat(user, span_notice("You sharpen the parsnip into a sabre with [I]."))
+ else
+ parsnip_blade = new /obj/item/knife/shiv/parsnip
+ to_chat(user, span_notice("You sharpen the parsnip into a shiv with [I]."))
+ remove_item_from_storage(user)
+ qdel(src)
+ user.put_in_hands(parsnip_blade)
+
+
+// Cahn'root
+/obj/item/seeds/carrot/cahnroot
+ name = "cahn'root seed pack"
+ desc = "These seeds grow into cahn'roots."
+ icon_state = "seed-cahn'root"
+ species = "cahn'root"
+ plantname = "Cahn'root"
+ product = /obj/item/food/grown/cahnroot
+ genes = list(/datum/plant_gene/trait/plant_type/weed_hardy)
+ endurance = 50
+ instability = 10
+ icon_dead = "cahn'root-dead"
+ mutatelist = null
+ reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.05, /datum/reagent/consumable/nutriment = 0.05, /datum/reagent/cellulose = 0.01, /datum/reagent/consumable/sugar = 0.01)
+ rarity = 10
+ graft_gene = /datum/plant_gene/trait/plant_type/weed_hardy
+
+/obj/item/food/grown/cahnroot
+ seed = /obj/item/seeds/carrot/cahnroot
+ name = "cahn'root"
+ desc = "Heavily modified version of terran carrot, originally made to survive the scarciest of environments by an enterprising scientist of Moth Flotilla, Cahn'Mang."
+ icon_state = "cahn'root"
+ foodtypes = VEGETABLES
+ juice_typepath = null
+ tastes = list("sweet dirt" = 1)
+ distill_reagent = /datum/reagent/consumable/rootbeer
+
+/obj/item/food/grown/cahnroot/attackby(obj/item/I, mob/user, params)
+ if(!I.get_sharpness())
+ return ..()
+
+ /// The blade cahn'root will turn into once sharpened
+ var/obj/item/knife/root_blade
+ /// Chance for it to become a dagger rather than a shiv
+ var/root_dagger_chance = (max(0, seed.potency - 25) / 50)
+ if (prob(root_dagger_chance))
+ root_blade = new /obj/item/knife/combat/root
+ to_chat(user, span_notice("You sharpen the cahn'root into a dagger with [I]."))
+ else
+ root_blade = new /obj/item/knife/shiv/root
+ to_chat(user, span_notice("You sharpen the cahn'root into a shiv with [I]."))
+ remove_item_from_storage(user)
+ qdel(src)
+ user.put_in_hands(root_blade)
// White-Beet
/obj/item/seeds/whitebeet
- name = "pack of white-beet seeds"
+ name = "white-beet seed pack"
desc = "These seeds grow into sugary beet producing plants."
icon_state = "seed-whitebeet"
species = "whitebeet"
@@ -91,7 +156,7 @@
// Red Beet
/obj/item/seeds/redbeet
- name = "pack of redbeet seeds"
+ name = "redbeet seed pack"
desc = "These seeds grow into red beet producing plants."
icon_state = "seed-redbeet"
species = "redbeet"
diff --git a/code/modules/hydroponics/grown/seedling.dm b/code/modules/hydroponics/grown/seedling.dm
index 57fd11280b6ede..9ce83acfa9e36d 100644
--- a/code/modules/hydroponics/grown/seedling.dm
+++ b/code/modules/hydroponics/grown/seedling.dm
@@ -1,5 +1,5 @@
/obj/item/seeds/seedling
- name = "pack of seedling seeds"
+ name = "seedling seed pack"
desc = "These seeds grow into a floral assistant which can help look after other plants!"
icon_state = "seed-seedling"
growing_icon = 'icons/obj/service/hydroponics/growing_fruits.dmi'
diff --git a/code/modules/hydroponics/grown/sugarcane.dm b/code/modules/hydroponics/grown/sugarcane.dm
index 1c5c55fece08d0..e7845f1e556079 100644
--- a/code/modules/hydroponics/grown/sugarcane.dm
+++ b/code/modules/hydroponics/grown/sugarcane.dm
@@ -1,7 +1,7 @@
// Sugarcane
/obj/item/seeds/sugarcane
- name = "pack of sugarcane seeds"
+ name = "sugarcane seed pack"
desc = "These seeds grow into sugarcane."
icon_state = "seed-sugarcane"
species = "sugarcane"
@@ -28,7 +28,7 @@
///and bamboo!
/obj/item/seeds/bamboo
- name = "pack of bamboo seeds"
+ name = "bamboo seed pack"
desc = "A plant known for its flexible and resistant logs."
icon_state = "seed-bamboo"
species = "bamboo"
@@ -59,7 +59,7 @@
//Saltcane - Gross, salty shafts!
/obj/item/seeds/sugarcane/saltcane
- name = "pack of saltcane seeds"
+ name = "saltcane seed pack"
desc = "These seeds grow into saltcane."
icon_state = "seed-saltcane"
species = "saltcane"
diff --git a/code/modules/hydroponics/grown/tea_coffee.dm b/code/modules/hydroponics/grown/tea_coffee.dm
index 366dd8b45237ec..26a215be720b44 100644
--- a/code/modules/hydroponics/grown/tea_coffee.dm
+++ b/code/modules/hydroponics/grown/tea_coffee.dm
@@ -1,6 +1,6 @@
// Tea
/obj/item/seeds/tea
- name = "pack of tea aspera seeds"
+ name = "tea aspera seed pack"
desc = "These seeds grow into tea plants."
icon_state = "seed-teaaspera"
species = "teaaspera"
@@ -27,7 +27,7 @@
// Tea Astra
/obj/item/seeds/tea/astra
- name = "pack of tea astra seeds"
+ name = "tea astra seed pack"
icon_state = "seed-teaastra"
species = "teaastra"
plantname = "Tea Astra Plant"
@@ -46,7 +46,7 @@
// Coffee
/obj/item/seeds/coffee
- name = "pack of coffee arabica seeds"
+ name = "coffee arabica seed pack"
desc = "These seeds grow into coffee arabica bushes."
icon_state = "seed-coffeea"
species = "coffeea"
@@ -75,7 +75,7 @@
// Coffee Robusta
/obj/item/seeds/coffee/robusta
- name = "pack of coffee robusta seeds"
+ name = "coffee robusta seed pack"
desc = "These seeds grow into coffee robusta bushes."
icon_state = "seed-coffeer"
species = "coffeer"
diff --git a/code/modules/hydroponics/grown/tobacco.dm b/code/modules/hydroponics/grown/tobacco.dm
index 87f8253a4d96b5..29e8fba6d6a8b0 100644
--- a/code/modules/hydroponics/grown/tobacco.dm
+++ b/code/modules/hydroponics/grown/tobacco.dm
@@ -1,6 +1,6 @@
// Tobacco
/obj/item/seeds/tobacco
- name = "pack of tobacco seeds"
+ name = "tobacco seed pack"
desc = "These seeds grow into tobacco plants."
icon_state = "seed-tobacco"
species = "tobacco"
@@ -24,7 +24,7 @@
// Space Tobacco
/obj/item/seeds/tobacco/space
- name = "pack of space tobacco seeds"
+ name = "space tobacco seed pack"
desc = "These seeds grow into space tobacco plants."
icon_state = "seed-stobacco"
species = "stobacco"
diff --git a/code/modules/hydroponics/grown/tomato.dm b/code/modules/hydroponics/grown/tomato.dm
index e676d822bbf1a8..1459887d6facbd 100644
--- a/code/modules/hydroponics/grown/tomato.dm
+++ b/code/modules/hydroponics/grown/tomato.dm
@@ -1,6 +1,6 @@
// Tomato
/obj/item/seeds/tomato
- name = "pack of tomato seeds"
+ name = "tomato seed pack"
desc = "These seeds grow into tomato plants."
icon_state = "seed-tomato"
species = "tomato"
@@ -29,7 +29,7 @@
// Blood Tomato
/obj/item/seeds/tomato/blood
- name = "pack of blood-tomato seeds"
+ name = "blood-tomato seed pack"
desc = "These seeds grow into blood-tomato plants."
icon_state = "seed-bloodtomato"
species = "bloodtomato"
@@ -52,7 +52,7 @@
// Blue Tomato
/obj/item/seeds/tomato/blue
- name = "pack of blue-tomato seeds"
+ name = "blue-tomato seed pack"
desc = "These seeds grow into blue-tomato plants."
icon_state = "seed-bluetomato"
species = "bluetomato"
@@ -77,7 +77,7 @@
// Bluespace Tomato
/obj/item/seeds/tomato/blue/bluespace
- name = "pack of bluespace tomato seeds"
+ name = "bluespace tomato seed pack"
desc = "These seeds grow into bluespace tomato plants."
icon_state = "seed-bluespacetomato"
species = "bluespacetomato"
@@ -101,7 +101,7 @@
// Killer Tomato
/obj/item/seeds/tomato/killer
- name = "pack of killer-tomato seeds"
+ name = "killer-tomato seed pack"
desc = "These seeds grow into killer-tomato plants."
icon_state = "seed-killertomato"
species = "killertomato"
diff --git a/code/modules/hydroponics/grown/towercap.dm b/code/modules/hydroponics/grown/towercap.dm
index 1082b51665ff7c..a09e4e61b4d15b 100644
--- a/code/modules/hydroponics/grown/towercap.dm
+++ b/code/modules/hydroponics/grown/towercap.dm
@@ -1,5 +1,5 @@
/obj/item/seeds/tower
- name = "pack of tower-cap mycelium"
+ name = "tower-cap mycelium pack"
desc = "This mycelium grows into tower-cap mushrooms."
icon_state = "mycelium-tower"
species = "towercap"
@@ -20,7 +20,7 @@
graft_gene = /datum/plant_gene/trait/plant_type/fungal_metabolism
/obj/item/seeds/tower/steel
- name = "pack of steel-cap mycelium"
+ name = "steel-cap mycelium pack"
desc = "This mycelium grows into steel logs."
icon_state = "mycelium-steelcap"
species = "steelcap"
diff --git a/code/modules/hydroponics/grown/weeds/kudzu.dm b/code/modules/hydroponics/grown/weeds/kudzu.dm
index 86b49672705b96..a0a3c9405718c9 100644
--- a/code/modules/hydroponics/grown/weeds/kudzu.dm
+++ b/code/modules/hydroponics/grown/weeds/kudzu.dm
@@ -1,7 +1,7 @@
// A very special plant, deserving its own file.
/obj/item/seeds/kudzu
- name = "pack of kudzu seeds"
+ name = "kudzu seed pack"
desc = "These seeds grow into a weed that grows incredibly fast."
icon_state = "seed-kudzu"
plant_icon_offset = 2
diff --git a/code/modules/hydroponics/grown/weeds/nettle.dm b/code/modules/hydroponics/grown/weeds/nettle.dm
index 98868b8d6e748b..33a0f6288912d9 100644
--- a/code/modules/hydroponics/grown/weeds/nettle.dm
+++ b/code/modules/hydroponics/grown/weeds/nettle.dm
@@ -1,5 +1,5 @@
/obj/item/seeds/nettle
- name = "pack of nettle seeds"
+ name = "nettle seed pack"
desc = "These seeds grow into nettles."
icon_state = "seed-nettle"
plant_icon_offset = 0
@@ -17,7 +17,7 @@
graft_gene = /datum/plant_gene/trait/plant_type/weed_hardy
/obj/item/seeds/nettle/death
- name = "pack of death-nettle seeds"
+ name = "death-nettle seed pack"
desc = "These seeds grow into death-nettles."
icon_state = "seed-deathnettle"
species = "deathnettle"
diff --git a/code/modules/hydroponics/grown/weeds/starthistle.dm b/code/modules/hydroponics/grown/weeds/starthistle.dm
index 74627a31f88e81..af94cf3d985088 100644
--- a/code/modules/hydroponics/grown/weeds/starthistle.dm
+++ b/code/modules/hydroponics/grown/weeds/starthistle.dm
@@ -1,6 +1,6 @@
// Starthistle
/obj/item/seeds/starthistle
- name = "pack of starthistle seeds"
+ name = "starthistle seed pack"
desc = "A robust species of weed that often springs up in-between the cracks of spaceship parking lots."
icon_state = "seed-starthistle"
plant_icon_offset = 3
@@ -33,7 +33,7 @@
// Corpse flower
/obj/item/seeds/starthistle/corpse_flower
- name = "pack of corpse flower seeds"
+ name = "corpse flower seed pack"
desc = "A species of plant that emits a horrible odor. The odor stops being produced in difficult atmospheric conditions."
icon_state = "seed-corpse-flower"
species = "corpse-flower"
@@ -46,7 +46,7 @@
//Galaxy Thistle
/obj/item/seeds/galaxythistle
- name = "pack of galaxythistle seeds"
+ name = "galaxythistle seed pack"
desc = "An impressive species of weed that is thought to have evolved from the simple milk thistle. Contains flavolignans that can help repair a damaged liver."
icon_state = "seed-galaxythistle"
species = "galaxythistle"
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index 5708327747bcd3..8856667ae5384c 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -157,6 +157,11 @@
icon = 'icons/obj/service/hydroponics/equipment.dmi'
icon_state = "hydrotray3"
+/obj/machinery/hydroponics/constructable/fullupgrade
+ name = "deluxe hydroponics tray"
+ desc = "A basin used to grown plants in, packed full of cutting-edge technology."
+ circuit = /obj/item/circuitboard/machine/hydroponics/fullupgrade
+
/obj/machinery/hydroponics/constructable/Initialize(mapload)
. = ..()
AddComponent(/datum/component/simple_rotation)
@@ -798,15 +803,7 @@
if(isnull(particles))
particles = new /particles/pollen()
if(myseed.instability >= 20 && prob(70) && length(T.myseed.reagents_add))
- var/list/datum/plant_gene/reagent/possible_reagents = list()
- for(var/datum/plant_gene/reagent/reag in T.myseed.genes)
- possible_reagents += reag
- var/datum/plant_gene/reagent/reagent_gene = pick(possible_reagents) //Let this serve as a lession to delete your WIP comments before merge.
- if(reagent_gene.can_add(myseed))
- if(!reagent_gene.try_upgrade_gene(myseed))
- myseed.genes += reagent_gene.Copy()
- myseed.reagents_from_genes()
- continue
+ myseed.perform_reagent_pollination(T.myseed)
if(!any_adjacent)
particles = null
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index 13a49b35189053..3b151042042377 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -616,3 +616,38 @@
/obj/item/grown/get_plant_seed()
return seed
+
+
+
+
+
+
+/obj/item/seeds/proc/perform_reagent_pollination(obj/item/seeds/donor)
+ var/list/datum/plant_gene/reagent/valid_reagents = list()
+ for(var/datum/plant_gene/reagent/donor_reagent in donor.genes)
+ var/repeated = FALSE
+ for(var/datum/plant_gene/reagent/receptor_reagent in genes)
+ if(donor_reagent.reagent_id == receptor_reagent.reagent_id)
+ if(receptor_reagent.rate < donor_reagent.rate)
+ receptor_reagent.rate = donor_reagent.rate
+ // sucessful pollination/upgrade, we stop here.
+ reagents_from_genes()
+ return
+ else
+ repeated = TRUE
+ break
+
+ if(!repeated)
+ valid_reagents += donor_reagent
+
+ if(length(valid_reagents))
+ // pick a valid reagent that our receptor seed don't have and add the gene to it
+ var/datum/plant_gene/reagent/selected_reagent = pick(valid_reagents)
+
+ genes += selected_reagent.Copy()
+ reagents_from_genes()
+
+
+
+
+
diff --git a/code/modules/jobs/job_types/assistant/gimmick_assistants.dm b/code/modules/jobs/job_types/assistant/gimmick_assistants.dm
index 17bd554f39bd11..16c0e0378443c2 100644
--- a/code/modules/jobs/job_types/assistant/gimmick_assistants.dm
+++ b/code/modules/jobs/job_types/assistant/gimmick_assistants.dm
@@ -167,6 +167,7 @@
belt = /obj/item/storage/belt/utility/full
head = /obj/item/clothing/head/utility/hardhat
uniform = /obj/item/clothing/under/color/yellow
+ l_pocket = /obj/item/modular_computer/pda/assistant
outfit_weight = 6
diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm
index 13a4162ff3be95..c0f200c82f7b6a 100644
--- a/code/modules/jobs/job_types/bartender.dm
+++ b/code/modules/jobs/job_types/bartender.dm
@@ -59,6 +59,8 @@
glasses = /obj/item/clothing/glasses/sunglasses/reagent
shoes = /obj/item/clothing/shoes/laceup
+ skillchips = list(/obj/item/skillchip/drunken_brawler)
+
/datum/outfit/job/bartender/post_equip(mob/living/carbon/human/H, visualsOnly)
. = ..()
diff --git a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm
index df658d71dddc2c..e75dd7593e09d3 100644
--- a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm
+++ b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm
@@ -564,7 +564,7 @@
/obj/item/nullrod/bostaff
name = "monk's staff"
desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts, it is now used to harass the clown."
- force = 15
+ force = 14
block_chance = 40
block_sound = 'sound/weapons/genhit.ogg'
slot_flags = ITEM_SLOT_BACK
@@ -574,11 +574,24 @@
attack_verb_simple = list("smash", "slam", "whack", "thwack")
icon = 'icons/obj/weapons/staff.dmi'
icon_state = "bostaff0"
+ base_icon_state = "bostaff"
inhand_icon_state = "bostaff0"
worn_icon_state = "bostaff0"
lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
- menu_description = "A staff which provides a medium-low chance of blocking incoming melee attacks and deals a little less damage. Can be worn on the back."
+ menu_description = "A staff which provides a medium-low chance of blocking incoming melee attacks and deals less damage, unless dual-wielded. Can be worn on the back."
+
+/obj/item/nullrod/bostaff/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/two_handed, \
+ force_unwielded = 14, \
+ force_wielded = 18, \
+ )
+
+/obj/item/nullrod/bostaff/update_icon_state()
+ icon_state = inhand_icon_state = "[base_icon_state][HAS_TRAIT(src, TRAIT_WIELDED)]"
+ return ..()
+
// Arrhythmic Knife - Lets your walk without rhythm by varying your walk speed. Can't be put away.
diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm
index f3627c3c2a2579..17dcf4d0b509cc 100644
--- a/code/modules/jobs/job_types/head_of_security.dm
+++ b/code/modules/jobs/job_types/head_of_security.dm
@@ -55,6 +55,7 @@
suit_store = /obj/item/gun/energy/e_gun
backpack_contents = list(
/obj/item/evidencebag = 1,
+ /obj/item/choice_beacon/security_pistol = 1, //Skyrat Addition
)
belt = /obj/item/modular_computer/pda/heads/hos
ears = /obj/item/radio/headset/heads/hos/alt
diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm
index 01eec3830e9524..d0c340156c316b 100644
--- a/code/modules/jobs/job_types/security_officer.dm
+++ b/code/modules/jobs/job_types/security_officer.dm
@@ -223,12 +223,14 @@ GLOBAL_LIST_EMPTY(security_officer_distribution)
suit_store = /obj/item/gun/energy/disabler
backpack_contents = list(
/obj/item/evidencebag = 1,
+ /obj/item/choice_beacon/security_pistol = 1, //SKYRAT ADDITION
)
belt = /obj/item/modular_computer/pda/security
ears = /obj/item/radio/headset/headset_sec/alt
gloves = /obj/item/clothing/gloves/color/black/security
head = /obj/item/clothing/head/security_garrison //SKYRAT EDIT CHANGE - Original: /obj/item/clothing/head/helmet/sec
shoes = /obj/item/clothing/shoes/jackboots/sec
+ glasses = /obj/item/clothing/glasses/hud/security //SKYRAT EDIT - ADDITION
l_pocket = /obj/item/restraints/handcuffs
r_pocket = /obj/item/assembly/flash/handheld
diff --git a/code/modules/language/_language_manuals.dm b/code/modules/language/_language_manuals.dm
index eb4ca456440d85..7a4298a06b1500 100644
--- a/code/modules/language/_language_manuals.dm
+++ b/code/modules/language/_language_manuals.dm
@@ -85,6 +85,14 @@
. = ..()
name = "extended [initial(language.name)] manual"
+/obj/item/language_manual/piratespeak
+ name = "\improper Captain Pete's Guide to Pirate Lingo"
+ icon_state = "book_pirate"
+ desc = "A book containing all the knowledge, jargon and buzzwords to speak like a true old salt."
+ language = /datum/language/piratespeak
+ flavour_text = "Blimey! I feel less of a landlubber now."
+ charges = 5
+
// So drones can teach borgs and AI dronespeak. For best effect, combine with mother drone lawset.
/obj/item/language_manual/dronespeak_manual
name = "dronespeak manual"
diff --git a/code/modules/library/skill_learning/skillchip.dm b/code/modules/library/skill_learning/skillchip.dm
index cc284b91454aa0..b8903e5bde09a5 100644
--- a/code/modules/library/skill_learning/skillchip.dm
+++ b/code/modules/library/skill_learning/skillchip.dm
@@ -141,6 +141,7 @@
* * silent - Boolean. Whether or not an activation message should be shown to the user.
*/
/obj/item/skillchip/proc/on_activate(mob/living/carbon/user, silent=FALSE)
+ SHOULD_CALL_PARENT(TRUE)
if(!silent && activate_message)
to_chat(user, activate_message)
@@ -175,6 +176,7 @@
* * silent - Boolean. Whether or not a deactivation message should be shown to the user.
*/
/obj/item/skillchip/proc/on_deactivate(mob/living/carbon/user, silent=FALSE)
+ SHOULD_CALL_PARENT(TRUE)
if(!silent && deactivate_message)
to_chat(user, deactivate_message)
@@ -484,9 +486,9 @@
/obj/item/skillchip/master_angler
name = "Mast-Angl-Er skillchip"
- auto_traits = list(TRAIT_REVEAL_FISH, TRAIT_EXAMINE_FISHING_SPOT)
+ auto_traits = list(TRAIT_REVEAL_FISH, TRAIT_EXAMINE_FISHING_SPOT, TRAIT_EXAMINE_FISH, TRAIT_EXAMINE_DEEPER_FISH)
skill_name = "Fisherman's Discernment"
- skill_description = "Lists fishes when examining a fishing spot, and gives a hint of whatever thing's biting the hook."
+ skill_description = "Lists fishes when examining a fishing spot, gives a hint of whatever thing's biting the hook and more."
skill_icon = "fish"
activate_message = span_notice("You feel the knowledge and passion of several sunbaked, seasoned fishermen burn within you.")
deactivate_message = span_notice("You no longer feel like casting a fishing rod by the sunny riverside.")
@@ -499,3 +501,104 @@
skill_icon = FA_ICON_DRUMSTICK_BITE
activate_message = span_notice("You think of your favourite food and realise that you can rotate its flavour in your mind.")
deactivate_message = span_notice("You feel your food-based mind palace crumbling...")
+
+/obj/item/skillchip/drunken_brawler
+ name = "F0RC3 4DD1CT10N skillchip"
+ auto_traits = list(TRAIT_DRUNKEN_BRAWLER)
+ skill_name = "Drunken Unarmed Proficiency"
+ skill_description = "When intoxicated, you gain increased unarmed effectiveness."
+ skill_icon = "wine-bottle"
+ activate_message = span_notice("You honestly could do with a drink. Never know when someone might try and jump you around here.")
+ deactivate_message = span_notice("You suddenly feel a lot safer going around the station sober... ")
+
+/obj/item/skillchip/musical
+ name = "\improper Old Copy of \"Space Station 13: The Musical\""
+ desc = "An old copy of \"Space Station 13: The Musical\", \
+ ran on the station's 100th anniversary...Or maybe it was the 200th?"
+ skill_name = "Memory of a Musical"
+ skill_description = "Allows you to hit that high note, like those that came a century before us."
+ skill_icon = FA_ICON_MUSIC
+ activate_message = span_notice("You feel like you could \u2669 sing a soooong! \u266B")
+ deactivate_message = span_notice("The musical fades from your mind, leaving you with a sense of nostalgia.")
+ custom_premium_price = PAYCHECK_CREW * 4
+
+/obj/item/skillchip/musical/Initialize(mapload, is_removable)
+ . = ..()
+ name = replacetext(name, "Old", round(CURRENT_STATION_YEAR - pick(50, 100, 150, 200, 250), 5))
+
+/obj/item/skillchip/musical/on_activate(mob/living/carbon/user, silent = FALSE)
+ . = ..()
+ RegisterSignal(user, COMSIG_MOB_SAY, PROC_REF(make_music))
+
+/obj/item/skillchip/musical/on_deactivate(mob/living/carbon/user, silent)
+ . = ..()
+ UnregisterSignal(user, COMSIG_MOB_SAY)
+
+/obj/item/skillchip/musical/proc/make_music(mob/living/carbon/source, list/say_args)
+ SIGNAL_HANDLER
+
+ var/raw_message = say_args[SPEECH_MESSAGE]
+ var/list/words = splittext(raw_message, " ")
+ if(length(words) <= 1)
+ say_args[SPEECH_MODS][MODE_SING] = TRUE
+ return
+ var/last_word = words[length(words)]
+ var/num_chars = length_char(last_word)
+ var/last_vowel = ""
+ // find the last vowel present in the word
+ for(var/i in 1 to num_chars)
+ var/char = copytext_char(last_word, i, i + 1)
+ if(char in VOWELS)
+ last_vowel = char
+
+ // now we'll reshape the final word to make it sound like they're singing it
+ var/final_word = ""
+ var/has_ellipsis = copytext(last_word, -3) == "..."
+ for(var/i in 1 to num_chars)
+ var/char = copytext_char(last_word, i, i + 1)
+ // replacing any final periods with exclamation marks (so long as it's not an ellipsis)
+ if(char == "." && i == num_chars && !has_ellipsis)
+ final_word += "!"
+ // or if it's the vowel we found, we're gonna repeat it a few times (holding the note)
+ else if(char == last_vowel)
+ for(var/j in 1 to 4)
+ final_word += char
+ // if we dragged out the last character of the word, just period it
+ if(i == num_chars)
+ final_word += "."
+ // no special handing otherwise
+ else
+ final_word += char
+
+ if(!has_ellipsis)
+ // adding an extra exclamation mark at the end if there's no period
+ var/last_char = copytext_char(final_word, -1)
+ if(last_char != ".")
+ final_word += "!"
+
+ words[length(words)] = final_word
+ // now we siiiiiiing
+ say_args[SPEECH_MESSAGE] = jointext(words, " ")
+ say_args[SPEECH_MODS][MODE_SING] = TRUE
+
+/obj/item/skillchip/musical/examine(mob/user)
+ . = ..()
+ . += span_tinynoticeital("Huh, looks like it'd fit in a skillchip adapter.")
+
+/obj/item/skillchip/musical/examine_more(mob/user)
+ . = ..()
+ var/list/songs = list()
+ songs += "• \"The Ballad of Space Station 13\""
+ songs += "• \"The Captain's Call\""
+ songs += "• \"A Mime's Lament\""
+ songs += "• \"Banned from Cargo\""
+ songs += "• \"Botany Blues\""
+ songs += "• \"Clown Song\""
+ songs += "• \"Elegy to an Engineer\""
+ songs += "• \"Medical Malpractitioner\""
+ songs += "• \"Security Strike\""
+ songs += "• \"Send for the Shuttle\""
+ songs += "• And one song scratched out..."
+
+ . += span_notice("On the back of the chip, you see a list of songs:")
+ . += span_smallnotice("[jointext(songs, " ")]")
diff --git a/code/modules/lighting/lighting_setup.dm b/code/modules/lighting/lighting_setup.dm
deleted file mode 100644
index c148530d1cd863..00000000000000
--- a/code/modules/lighting/lighting_setup.dm
+++ /dev/null
@@ -1,12 +0,0 @@
-
-/proc/create_all_lighting_objects()
- for(var/area/area as anything in GLOB.areas)
- if(!area.static_lighting)
- continue
- for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists())
- for(var/turf/area_turf as anything in zlevel_turfs)
- if(area_turf.space_lit)
- continue
- new /datum/lighting_object(area_turf)
- CHECK_TICK
- CHECK_TICK
diff --git a/code/modules/loadout/categories/pocket.dm b/code/modules/loadout/categories/pocket.dm
index 8206192bb81003..2689c2b726e42a 100644
--- a/code/modules/loadout/categories/pocket.dm
+++ b/code/modules/loadout/categories/pocket.dm
@@ -106,10 +106,6 @@
name = "Plush (Moth)"
item_path = /obj/item/toy/plush/moth
-/datum/loadout_item/pocket_items/plush/narsie
- name = "Plush (Nar'sie)"
- item_path = /obj/item/toy/plush/narplush
-
/datum/loadout_item/pocket_items/plush/nukie
name = "Plush (Nukie)"
item_path = /obj/item/toy/plush/nukeplushie
@@ -122,10 +118,6 @@
name = "Plush (Plasmaman)"
item_path = /obj/item/toy/plush/plasmamanplushie
-/datum/loadout_item/pocket_items/plush/ratvar
- name = "Plush (Ratvar)"
- item_path = /obj/item/toy/plush/ratplush
-
/datum/loadout_item/pocket_items/plush/rouny
name = "Plush (Rouny)"
item_path = /obj/item/toy/plush/rouny
diff --git a/code/modules/lootpanel/contents.dm b/code/modules/lootpanel/contents.dm
index 44f4acd47f24c4..2fcd4201d8a7c3 100644
--- a/code/modules/lootpanel/contents.dm
+++ b/code/modules/lootpanel/contents.dm
@@ -21,6 +21,8 @@
if(!istype(thing))
stack_trace("Non-atom in the contents of [source_turf]!")
continue
+ if(QDELETED(thing))
+ continue
if(thing.mouse_opacity == MOUSE_OPACITY_TRANSPARENT)
continue
if(thing.IsObscured())
diff --git a/code/modules/lootpanel/search_object.dm b/code/modules/lootpanel/search_object.dm
index 149be76e710647..2cb0bdf85dba96 100644
--- a/code/modules/lootpanel/search_object.dm
+++ b/code/modules/lootpanel/search_object.dm
@@ -62,6 +62,7 @@
/datum/search_object/Destroy(force)
item = null
+ icon = null
return ..()
@@ -75,6 +76,9 @@
/datum/search_object/proc/on_item_moved(atom/source)
SIGNAL_HANDLER
+ if(QDELETED(src))
+ return
+
qdel(src)
@@ -82,4 +86,4 @@
/datum/search_object/proc/on_turf_change(turf/source, path, list/new_baseturfs, flags, list/post_change_callbacks)
SIGNAL_HANDLER
- post_change_callbacks += CALLBACK(src, GLOBAL_PROC_REF(qdel), src)
+ post_change_callbacks += CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), src)
diff --git a/code/modules/mafia/roles/roles.dm b/code/modules/mafia/roles/roles.dm
index ab1a1cc0e454b7..4cfd7662d843e3 100644
--- a/code/modules/mafia/roles/roles.dm
+++ b/code/modules/mafia/roles/roles.dm
@@ -189,6 +189,6 @@
team_span = "comradio"
the = FALSE
result += span_notice("The [span_bold("[name]")] is aligned with [the ? "the " : ""][team_desc]")
- result += "\"[desc]\""
+ result += "\"[initial(desc)]\""
result += span_notice("[name] wins when they [win_condition]")
to_chat(clueless, result.Join(""))
diff --git a/code/modules/mapfluff/ruins/spaceruin_code/hauntedtradingpost.dm b/code/modules/mapfluff/ruins/spaceruin_code/hauntedtradingpost.dm
new file mode 100644
index 00000000000000..03bd6c224deda1
--- /dev/null
+++ b/code/modules/mapfluff/ruins/spaceruin_code/hauntedtradingpost.dm
@@ -0,0 +1,383 @@
+//code & items for the hauntedtradingpost.dmm ruin
+//CONTAINS: [Lore Papers],[Outpost ID Cards],[Gimmick Treasure],[Hazards & Traps],[Custom Turrets]
+
+// [Lore Papers]
+// clues to traps that exist in the ruin or just insights into the backstory of the place
+/obj/item/paper/fluff/ruins/hauntedtradingpost/warning
+ name = "Last Warning"
+ default_raw_text = "Next person who breaks a vending machine fucking around with those fucking toy guns gets fired on the spot. Try me. I am SICK of this shit.
Signed, Your Fucking Boss (Who Can Fucking Fire Your Ass)"
+
+/obj/item/paper/fluff/ruins/hauntedtradingpost/warning/turrets
+ name = "Warning! Important! Read this!"
+ default_raw_text = "Foam darts do not go in the defence turrets! Live ammo only!"
+
+/obj/item/paper/fluff/ruins/hauntedtradingpost/brainstorming
+ name = "Notes"
+ default_raw_text = "Branding: Pizza In Your Pocket (check focus groups)
Tomato Mozzerella Basil etc
Spider 17-02667 Store 31-00314
18,000 approx BSD
common allergens - ?
6127"
+
+/obj/item/paper/fluff/ruins/hauntedtradingpost/brainstorming/eureka
+ default_raw_text = "Got some ingredients from the moth trading fleet and used some of our discretionary budget to hire some factory space. Prototypes are going down well with both public and employees. If we can get central to fund mass production we'll be seeing a 18% permanant increase in regional profit according to AI. This fits the local brunch market *perfectly*."
+
+/obj/item/paper/fluff/ruins/hauntedtradingpost/brainstorming/eureka2
+ default_raw_text = "Early experiments with a fully carb-free recipe going well. Taste tests are all positive, just need a way to reduce costs."
+
+/obj/item/paper/fluff/ruins/hauntedtradingpost/brainstorming/eureka3
+ default_raw_text = "PROJECT BIG DONK RnD has a few prototypes prepared. Testing will be complete by the end of the week."
+
+/obj/item/paper/fluff/ruins/hauntedtradingpost/rpgclub
+ name = "RPG Club"
+ default_raw_text = "RPG Club is every Thursday from 20:00 to 01:00 AM. Entry to the break room is strictly by invitation only during that period of time.
We apologise for any inconvenience."
+
+/obj/item/paper/fluff/ruins/hauntedtradingpost/rpgrules
+ name = "GM Notes"
+ default_raw_text = "Session 4 NPCS Shadow Warriors S A T C H 40 65 40 15 10
Shadow Clan Underlord S A T C H 40 65 40 15 10 Note: Gets shadow magic.
Dire Corgi S A T C H 60 25 65 25 12
If they beat this let them roll on loot table 4 twice but if it's 65-70 or 15-30 make it magic boots instead."
+
+/obj/item/paper/fluff/ruins/hauntedtradingpost/curatorsnote
+ name = "For Adventurers"
+ default_raw_text = "The food court and the stalls are safe, everywhere else isn't. There's safes in the stalls and I didn't have a way to open them so if you can get whatever's inside, good for you. The employees area can be entered by tailing the bots, but security systems are active back there. I got shot by a turret taking a look, and when I stitched myself up and tried the other door I walked into a booby trap and nearly lost an arm.
If you're investigating this signal - BEWARE. For the record, I decided nothing in there's worth the risk. If you're braver than me, good luck. Signed, Curator P."
+
+/obj/item/paper/fluff/ruins/hauntedtradingpost/officememo
+ name = "Memo"
+ default_raw_text = "The AI-Guided Defense System Will Stay Active Indefinitely To Protect Company Property. Please Ensure All Personal Items Are Removed From The Premises, As They Will Be Impossible To Recover If Forgotten.
Donk Co. Takes No Responsibility For Lost Personal Property Or Affects."
+
+/obj/item/paper/fluff/ruins/hauntedtradingpost/receipt
+ name = "Old Receipt"
+ desc = "A ratty old sales receipt printed on cheap thermal paper."
+ default_raw_text = "DONK CO OUTLET 6013 YOUR SERVER TODAY WAS: COLM