diff --git a/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm b/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm
index 99c924177a..7b15bfb584 100644
--- a/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm
+++ b/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm
@@ -997,14 +997,14 @@
/turf/open/floor/plasteel/freezer,
/area/mine/living_quarters)
"qh" = (
-/obj/structure/sink{
- dir = 8;
- pixel_x = 11
- },
/obj/effect/turf_decal/tile/bar,
/obj/effect/turf_decal/tile/bar{
dir = 1
},
+/obj/structure/sink{
+ dir = 4;
+ pixel_x = 12
+ },
/turf/open/floor/plasteel,
/area/mine/living_quarters)
"qm" = (
@@ -2504,13 +2504,13 @@
/turf/open/floor/plasteel/white,
/area/mine/laborcamp)
"Mj" = (
-/obj/structure/sink{
- dir = 4;
- pixel_x = -12
- },
/obj/structure/mirror{
pixel_x = -28
},
+/obj/structure/sink{
+ dir = 8;
+ pixel_x = -12
+ },
/turf/open/floor/plasteel/freezer,
/area/mine/living_quarters)
"Mk" = (
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index faede2c9ac..d18835f12d 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -339,41 +339,6 @@ GLOBAL_LIST_INIT(greyscale_limb_types, list("human","moth","lizard","pod","plant
//body ids that have prosthetic sprites
GLOBAL_LIST_INIT(prosthetic_limb_types, list("xion","bishop","cybersolutions","grayson","hephaestus","nanotrasen","talon"))
-//FAMILY HEIRLOOM LIST
-//this works by using the first number for the species as a probability to choose one of the items in the following list for their family heirloom
-//if the probability fails, or the species simply isn't in the list, then it defaults to the next global list, which has its own list of items for each job
-//the first item in the list is for if your job isn't in that list
-
-//species-heirloom list (we categorise them by the species id var)
-GLOBAL_LIST_INIT(species_heirlooms, list(
- "dwarf" = list(25, list(/obj/item/reagent_containers/food/drinks/dwarf_mug)), //example: 25% chance for dwarves to get a dwarf mug as their heirloom (normal container but has manly dorf icon)
- "insect" = list(25, list(/obj/item/flashlight/lantern/heirloom_moth)),
- "ipc" = list(25, list(/obj/item/stock_parts/cell/family)), //gives a broken powercell for flavor text!
- "synthliz" = list(25, list(/obj/item/stock_parts/cell/family)), //they're also robots
- "slimeperson" = list(25, list(/obj/item/toy/plush/slimeplushie)),
- "lizard" = list(25, list(/obj/item/toy/plush/lizardplushie)),
- ))
-
-//job-heirloom list
-GLOBAL_LIST_INIT(job_heirlooms, list(
- "NO_JOB" = list(/obj/item/toy/cards/deck, /obj/item/lighter, /obj/item/dice/d20),
- "Clown" = list(/obj/item/paint/anycolor, /obj/item/bikehorn/golden),
- "Mime" = list(/obj/item/paint/anycolor, /obj/item/toy/dummy),
- "Cook" = list(/obj/item/kitchen/knife/scimitar),
- "Botanist" = list(/obj/item/cultivator, /obj/item/reagent_containers/glass/bucket, /obj/item/storage/bag/plants, /obj/item/toy/plush/beeplushie),
- "Medical Doctor" = list(/obj/item/healthanalyzer),
- "Paramedic" = list(/obj/item/lighter), //..why?
- "Station Engineer" = list(/obj/item/wirecutters/brass/family, /obj/item/crowbar/brass/family, /obj/item/screwdriver/brass/family, /obj/item/wrench/brass/family), //brass tools but without the tool speed modifier
- "Atmospheric Technician" = list(/obj/item/extinguisher/mini/family),
- "Lawyer" = list(/obj/item/storage/briefcase/lawyer/family),
- "Janitor" = list(/obj/item/mop),
- "Scientist" = list(/obj/item/toy/plush/slimeplushie),
- "Assistant" = list(/obj/item/clothing/gloves/cut/family),
- "Prisoner" = list (/obj/item/pen/blue),
- "Chaplain" = list(/obj/item/camera/spooky/family),
- "Head of Personnel" = list(/obj/item/pinpointer/ian)
- ))
-
//body ids that have non-gendered bodyparts
GLOBAL_LIST_INIT(nongendered_limb_types, list("fly", "zombie" ,"synth", "shadow", "cultgolem", "agent", "plasmaman", "clockgolem", "clothgolem"))
diff --git a/code/datums/traits/good.dm b/code/datums/traits/good.dm
index e2de71d006..5b00d2e71e 100644
--- a/code/datums/traits/good.dm
+++ b/code/datums/traits/good.dm
@@ -181,10 +181,10 @@
/datum/quirk/trandening
name = "High Luminosity Eyes"
- desc = "When the next big fancy implant came out you had to buy one on impluse!"
+ desc = "When the next big fancy implant came out you had to buy one on impulse! You start the shift with emissive cybernetic eyes that can emit colored beams of light."
value = 1
- gain_text = "You have to keep up with the next big thing!."
- lose_text = "High-tech gizmos are a scam..."
+ gain_text = "You've been keeping up with the latest cybernetic trends!"
+ lose_text = "High powered eye lasers? What were you thinking..."
/datum/quirk/trandening/on_spawn()
// Get targets
@@ -195,6 +195,34 @@
qdel(old_eyes)
new_eyes.Insert(quirk_holder)
+/datum/quirk/trandening/remove()
+ // Get targets
+ var/obj/item/organ/eyes/old_eyes = quirk_holder.getorganslot(ORGAN_SLOT_EYES)
+ var/mob/living/carbon/human/qurk_mob = quirk_holder
+
+ // Check for eyes existing
+ if(!old_eyes)
+ return
+
+ // Check for quirk eyes
+ if(!istype(old_eyes, /obj/item/organ/eyes/robotic/glow))
+ return
+
+ // Define new eyes
+ var/species_eyes = /obj/item/organ/eyes
+
+ // Check for mutant eyes
+ if(qurk_mob.dna.species && qurk_mob.dna.species.mutanteyes)
+ // Set eyes to mutant type
+ species_eyes = qurk_mob.dna.species.mutanteyes
+
+ // Create new eyes item
+ var/obj/item/organ/eyes/new_eyes = new species_eyes()
+
+ // Replace eyes
+ qdel(old_eyes)
+ new_eyes.Insert(quirk_holder)
+
/datum/quirk/bloodpressure
name = "Polycythemia vera"
desc = "You've a treated form of Polycythemia vera that increases the total blood volume inside of you as well as the rate of replenishment!"
diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm
index 8d3acf0f6d..a30e27c8f8 100644
--- a/code/datums/traits/negative.dm
+++ b/code/datums/traits/negative.dm
@@ -43,27 +43,38 @@
GLOBAL_LIST_EMPTY(family_heirlooms)
-/datum/quirk/family_heirloom/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
+/datum/quirk/family_heirloom/on_spawn()
+ // Define holder and type
+ var/mob/living/carbon/human/human_holder = quirk_holder
var/obj/item/heirloom_type
- var/species_heirloom_entry = GLOB.species_heirlooms[H.dna.species.id]
- if(species_heirloom_entry)
- if(prob(species_heirloom_entry[1]))
- heirloom_type = pick(species_heirloom_entry[2])
+
+ // The quirk holder's species - we have a 50% chance, if we have a species with a set heirloom, to choose a species heirloom.
+ var/datum/species/holder_species = human_holder.dna?.species
+ if(holder_species && LAZYLEN(holder_species.family_heirlooms) && prob(50))
+ heirloom_type = pick(holder_species.family_heirlooms)
+ else
+ // Our quirk holder's job
+ var/datum/job/holder_job = SSjob.GetJob(human_holder.last_mind?.assigned_role)
+ if(holder_job && LAZYLEN(holder_job.family_heirlooms))
+ heirloom_type = pick(holder_job.family_heirlooms)
+
+ // If we didn't find an heirloom somehow, throw them a generic one
if(!heirloom_type)
- var/job_heirloom_entry = GLOB.job_heirlooms[quirk_holder.mind.assigned_role]
- if(!job_heirloom_entry)
- heirloom_type = pick(GLOB.job_heirlooms["NO_JOB"]) //consider: should this be a define?
- else
- heirloom_type = pick(job_heirloom_entry)
+ heirloom_type = pick(/obj/item/toy/cards/deck, /obj/item/lighter, /obj/item/dice/d20)
+
+ // Create the heirloom item
heirloom = new heirloom_type(get_turf(quirk_holder))
+
+ // Add to global list
GLOB.family_heirlooms += heirloom
+
+ // Determine and assign item location
var/list/slots = list(
"in your left pocket" = ITEM_SLOT_LPOCKET,
"in your right pocket" = ITEM_SLOT_RPOCKET,
"in your backpack" = ITEM_SLOT_BACKPACK
)
- where = H.equip_in_one_of_slots(heirloom, slots, FALSE) || "at your feet"
+ where = human_holder.equip_in_one_of_slots(heirloom, slots, FALSE) || "at your feet"
/datum/quirk/family_heirloom/post_add()
if(where == "in your backpack")
@@ -75,13 +86,25 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
heirloom.name = "\improper [family_name[family_name.len]] family [heirloom.name]"
/datum/quirk/family_heirloom/on_process()
- if(heirloom in quirk_holder.GetAllContents())
+ // Ignore for dead holder
+ if(quirk_holder.stat == DEAD)
+ return
+
+ // When held: Positive mood
+ if(heirloom && (heirloom in quirk_holder.GetAllContents()))
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "family_heirloom_missing")
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "family_heirloom", /datum/mood_event/family_heirloom)
+
+ // When not held: Negative mood
else
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "family_heirloom")
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "family_heirloom_missing", /datum/mood_event/family_heirloom_missing)
+/datum/quirk/item_quirk/family_heirloom/remove()
+ // Clear mood events when removing this quirk
+ SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "family_heirloom")
+ SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "family_heirloom_missing")
+
/datum/quirk/family_heirloom/clone_data()
return heirloom
diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm
index 8f7043c715..eb5293c07d 100644
--- a/code/datums/traits/neutral.dm
+++ b/code/datums/traits/neutral.dm
@@ -163,22 +163,7 @@
lose_text = "You no longer feel like you should be eating trash."
mob_trait = TRAIT_TRASHCAN
-/datum/quirk/colorist
- name = "Colorist"
- desc = "You like carrying around a hair dye spray to quickly apply color patterns to your hair."
- value = 0
- medical_record_text = "Patient enjoys dyeing their hair with pretty colors."
-
-/datum/quirk/colorist/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/dyespray/spraycan = new(get_turf(quirk_holder))
- H.equip_to_slot(spraycan, ITEM_SLOT_BACKPACK)
- H.regenerate_icons()
-
-/datum/quirk/colorist/post_add()
- var/mob/living/carbon/human/H = quirk_holder
- SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_SHOW, H)
- to_chat(quirk_holder, "You brought some extra dye with you! It's in your bag if you forgot.")
+// Moved Colorist quirk to a loadout item
/datum/quirk/salt_sensitive
name = "Sodium Sensitivity"
diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm
index bcfcbe20f8..0381779531 100644
--- a/code/game/objects/items/storage/firstaid.dm
+++ b/code/game/objects/items/storage/firstaid.dm
@@ -55,8 +55,9 @@
generate_items_inside(items_inside,src)
/obj/item/storage/firstaid/ancient
- icon_state = "firstaid"
- desc = "A first aid kit with the ability to heal common types of injuries."
+ name = "ancient first-aid kit"
+ icon_state = "oldfirstaid"
+ desc = "A first aid kit with the ability to heal common types of injuries. You start thinking of the good old days just by looking at it."
/obj/item/storage/firstaid/ancient/PopulateContents()
if(empty)
@@ -69,6 +70,10 @@
new /obj/item/stack/medical/mesh(src)
new /obj/item/stack/medical/mesh(src)
+/obj/item/storage/firstaid/ancient/heirloom
+ // Long since been ransacked by hungry powergaming assistants breaking into med storage
+ empty = TRUE
+
/obj/item/storage/firstaid/brute
name = "trauma treatment kit"
desc = "A first aid kit for when you get toolboxed."
diff --git a/code/modules/clothing/glasses/prescription_kit.dm b/code/modules/clothing/glasses/prescription_kit.dm
index 0ad6419622..9e324d34f0 100644
--- a/code/modules/clothing/glasses/prescription_kit.dm
+++ b/code/modules/clothing/glasses/prescription_kit.dm
@@ -2,21 +2,31 @@
/obj/item/prescription_kit
name = "prescription lens kit"
- desc = "A disposable kit containing all the needed tools and parts to develop and apply a self-modifying prescription lens overlay device to any eyewear."
+ desc = "A disposable kit containing all the needed tools and parts to develop and apply a self-modifying prescription lens overlay device to any eyewear. \
+ Insert eyewear, receive vision-correcting lenses."
icon = 'icons/obj/device.dmi'
icon_state = "modkit"
-/obj/item/prescription_kit/attack_obj(obj/O, mob/living/user)
- if(!istype(O, /obj/item/clothing/glasses))
+/obj/item/prescription_kit/attackby(obj/item/I, mob/living/user, params)
+ if(istype(I, /obj/item/clothing/glasses) && I.Adjacent(user))
+ var/obj/item/clothing/glasses/target_glasses = I
+ prescribe(target_glasses, user)
+ else
return ..()
- if(istype(O, /obj/item/clothing/glasses))
- var/obj/item/clothing/glasses/target_glasses = O
- if(target_glasses.vision_correction)
- to_chat(user, span_notice("These are already fitted with prescription lenses or otherwise already correct vision!"))
- return
- playsound(src, 'sound/items/screwdriver.ogg', 50, 1)
- user.visible_message(span_notice("[user] fits \the [target_glasses] with a prescription overlay device."), span_notice("You fit \the [target_glasses] with a prescription overlay device."))
- target_glasses.prescribe()
- target_glasses.balloon_alert(user, "prescription fitted!")
- qdel(src)
+/obj/item/prescription_kit/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
+ if(istype(target, /obj/item/clothing/glasses) && target.Adjacent(user))
+ var/obj/item/clothing/glasses/target_glasses = target
+ prescribe(target_glasses, user)
+ else
+ . = ..()
+
+/obj/item/prescription_kit/proc/prescribe(obj/item/clothing/glasses/target_glasses, mob/user)
+ if(target_glasses.vision_correction)
+ to_chat(user, span_notice("These are already fitted with prescription lenses or otherwise already correct vision!"))
+ return
+ playsound(src, 'sound/items/screwdriver.ogg', 50, 1)
+ user.visible_message(span_notice("[user] fits \the [target_glasses] with a prescription overlay device."), span_notice("You fit \the [target_glasses] with a prescription overlay device."))
+ target_glasses.prescribe()
+ target_glasses.balloon_alert(user, "prescription fitted!")
+ qdel(src)
diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm
index 3a40f217dc..7a5ffbbbae 100644
--- a/code/modules/jobs/job_types/_job.dm
+++ b/code/modules/jobs/job_types/_job.dm
@@ -69,6 +69,9 @@
///Is this job affected by weird spawns like the ones from station traits
var/random_spawns_possible = TRUE
+ /// List of family heirlooms this job can get with the family heirloom quirk. List of types.
+ var/list/family_heirlooms
+
var/display_order = JOB_DISPLAY_ORDER_DEFAULT
var/bounty_types = CIV_JOB_BASIC
diff --git a/code/modules/jobs/job_types/assistant.dm b/code/modules/jobs/job_types/assistant.dm
index db5390f323..7ce29db178 100644
--- a/code/modules/jobs/job_types/assistant.dm
+++ b/code/modules/jobs/job_types/assistant.dm
@@ -20,6 +20,11 @@ Assistant
dresscodecompliant = FALSE
always_can_respawn_as = TRUE
threat = 0.2
+
+ family_heirlooms = list(
+ /obj/item/storage/toolbox/mechanical/old/heirloom,
+ /obj/item/clothing/gloves/cut/family
+ )
/datum/job/assistant/get_access()
if(CONFIG_GET(flag/assistants_have_maint_access) || !CONFIG_GET(flag/jobs_have_minimal_access)) //Config has assistant maint access set
diff --git a/code/modules/jobs/job_types/atmospheric_technician.dm b/code/modules/jobs/job_types/atmospheric_technician.dm
index 9aa8ea07c4..551ac63d00 100644
--- a/code/modules/jobs/job_types/atmospheric_technician.dm
+++ b/code/modules/jobs/job_types/atmospheric_technician.dm
@@ -26,6 +26,12 @@
display_order = JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN
threat = 0.5
+
+ family_heirlooms = list(
+ /obj/item/lighter,
+ /obj/item/lighter/greyscale,
+ /obj/item/storage/box/matches
+ )
/datum/outfit/job/atmos
name = "Atmospheric Technician"
diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm
index 70ca762f39..40a1b20cb1 100644
--- a/code/modules/jobs/job_types/bartender.dm
+++ b/code/modules/jobs/job_types/bartender.dm
@@ -20,6 +20,12 @@
bounty_types = CIV_JOB_DRINK
display_order = JOB_DISPLAY_ORDER_BARTENDER
threat = 0.5
+
+ family_heirlooms = list(
+ /obj/item/reagent_containers/rag,
+ /obj/item/clothing/head/that,
+ /obj/item/reagent_containers/food/drinks/shaker
+ )
/datum/outfit/job/bartender
name = "Bartender"
diff --git a/code/modules/jobs/job_types/botanist.dm b/code/modules/jobs/job_types/botanist.dm
index 53502ee30e..7a43837cf4 100644
--- a/code/modules/jobs/job_types/botanist.dm
+++ b/code/modules/jobs/job_types/botanist.dm
@@ -20,6 +20,12 @@
display_order = JOB_DISPLAY_ORDER_BOTANIST
threat = 1.5 // lol powergame
+ family_heirlooms = list(
+ /obj/item/cultivator,
+ /obj/item/reagent_containers/glass/bucket, // Watering cans don't exist yet
+ /obj/item/toy/plush/beeplushie,
+ )
+
/datum/outfit/job/botanist
name = "Botanist"
jobtype = /datum/job/hydro
diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm
index c3765260cc..65811d40a0 100644
--- a/code/modules/jobs/job_types/captain.dm
+++ b/code/modules/jobs/job_types/captain.dm
@@ -32,6 +32,11 @@
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/insanity)
threat = 5
+
+ family_heirlooms = list(
+ /obj/item/reagent_containers/food/drinks/flask/gold,
+ /obj/item/toy/figure/captain
+ )
/datum/job/captain/get_access()
return get_all_accesses()
diff --git a/code/modules/jobs/job_types/cargo_technician.dm b/code/modules/jobs/job_types/cargo_technician.dm
index f8e2f74d80..1188669db5 100644
--- a/code/modules/jobs/job_types/cargo_technician.dm
+++ b/code/modules/jobs/job_types/cargo_technician.dm
@@ -21,6 +21,10 @@
display_order = JOB_DISPLAY_ORDER_CARGO_TECHNICIAN
bounty_types = CIV_JOB_RANDOM
threat = 0.2
+
+ family_heirlooms = list(
+ /obj/item/clipboard
+ )
/datum/outfit/job/cargo_tech
name = "Cargo Technician"
diff --git a/code/modules/jobs/job_types/chaplain.dm b/code/modules/jobs/job_types/chaplain.dm
index ef4f20765c..e7d602bd22 100644
--- a/code/modules/jobs/job_types/chaplain.dm
+++ b/code/modules/jobs/job_types/chaplain.dm
@@ -19,6 +19,11 @@
display_order = JOB_DISPLAY_ORDER_CHAPLAIN
threat = 0.5
+
+ family_heirlooms = list(
+ /obj/item/toy/windupToolbox,
+ /obj/item/reagent_containers/food/drinks/bottle/holywater
+ )
/datum/job/chaplain/after_spawn(mob/living/H, client/C)
diff --git a/code/modules/jobs/job_types/chemist.dm b/code/modules/jobs/job_types/chemist.dm
index 209b3f82d0..9f830ba43c 100644
--- a/code/modules/jobs/job_types/chemist.dm
+++ b/code/modules/jobs/job_types/chemist.dm
@@ -24,6 +24,11 @@
threat = 1.5
starting_modifiers = list(/datum/skill_modifier/job/surgery, /datum/skill_modifier/job/affinity/surgery)
+
+ family_heirlooms = list(
+ /obj/item/book/manual/wiki/chemistry,
+ /obj/item/fermichem/pHbooklet
+ )
/datum/outfit/job/chemist
name = "Chemist"
diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm
index 60b963d7ec..2949758d8a 100644
--- a/code/modules/jobs/job_types/chief_engineer.dm
+++ b/code/modules/jobs/job_types/chief_engineer.dm
@@ -37,6 +37,15 @@
display_order = JOB_DISPLAY_ORDER_CHIEF_ENGINEER
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/paraplegic, /datum/quirk/insanity)
threat = 2
+
+ family_heirlooms = list(
+ /obj/item/clothing/head/hardhat,
+ /obj/item/screwdriver/brass/family,
+ /obj/item/wrench/brass/family,
+ /obj/item/weldingtool/mini, // No brass family variant
+ /obj/item/crowbar/brass/family,
+ /obj/item/wirecutters/brass/family
+ )
/datum/outfit/job/ce
name = "Chief Engineer"
diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm
index 401b503110..f5170fc745 100644
--- a/code/modules/jobs/job_types/chief_medical_officer.dm
+++ b/code/modules/jobs/job_types/chief_medical_officer.dm
@@ -35,6 +35,15 @@
threat = 2
starting_modifiers = list(/datum/skill_modifier/job/surgery, /datum/skill_modifier/job/affinity/surgery)
+
+ family_heirlooms = list(
+ /obj/item/storage/firstaid/ancient/heirloom,
+ /obj/item/scalpel,
+ /obj/item/hemostat,
+ /obj/item/circular_saw,
+ /obj/item/retractor,
+ /obj/item/cautery
+ )
/datum/outfit/job/cmo
name = "Chief Medical Officer"
diff --git a/code/modules/jobs/job_types/clown.dm b/code/modules/jobs/job_types/clown.dm
index 380215a93b..5631ce4624 100644
--- a/code/modules/jobs/job_types/clown.dm
+++ b/code/modules/jobs/job_types/clown.dm
@@ -21,6 +21,10 @@
display_order = JOB_DISPLAY_ORDER_CLOWN
threat = 0 // honk
+
+ family_heirlooms = list(
+ /obj/item/bikehorn/golden
+ )
/datum/outfit/job/clown
name = "Clown"
diff --git a/code/modules/jobs/job_types/cook.dm b/code/modules/jobs/job_types/cook.dm
index 2a021e6575..9947c27ba9 100644
--- a/code/modules/jobs/job_types/cook.dm
+++ b/code/modules/jobs/job_types/cook.dm
@@ -22,6 +22,12 @@
display_order = JOB_DISPLAY_ORDER_COOK
threat = 0.2
+ family_heirlooms = list(
+ /obj/item/reagent_containers/food/condiment/saltshaker,
+ /obj/item/kitchen/rollingpin,
+ /obj/item/clothing/head/chefhat
+ )
+
/datum/outfit/job/cook
name = "Cook"
jobtype = /datum/job/cook
diff --git a/code/modules/jobs/job_types/curator.dm b/code/modules/jobs/job_types/curator.dm
index 254fc15bd4..e6e9394109 100644
--- a/code/modules/jobs/job_types/curator.dm
+++ b/code/modules/jobs/job_types/curator.dm
@@ -19,6 +19,11 @@
display_order = JOB_DISPLAY_ORDER_CURATOR
threat = 0.3
+
+ family_heirlooms = list(
+ /obj/item/pen/fountain,
+ /obj/item/storage/dice
+ )
/datum/outfit/job/curator
name = "Curator"
diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm
index b56ebed191..2330e93147 100644
--- a/code/modules/jobs/job_types/detective.dm
+++ b/code/modules/jobs/job_types/detective.dm
@@ -27,6 +27,10 @@
display_order = JOB_DISPLAY_ORDER_DETECTIVE
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/monophobia)
threat = 1
+
+ family_heirlooms = list(
+ /obj/item/reagent_containers/food/drinks/flask/det
+ )
/datum/outfit/job/detective
name = "Detective"
diff --git a/code/modules/jobs/job_types/geneticist.dm b/code/modules/jobs/job_types/geneticist.dm
index 611c3f99cd..2529eaa024 100644
--- a/code/modules/jobs/job_types/geneticist.dm
+++ b/code/modules/jobs/job_types/geneticist.dm
@@ -24,6 +24,10 @@
threat = 1.5
starting_modifiers = list(/datum/skill_modifier/job/surgery, /datum/skill_modifier/job/affinity/surgery)
+
+ family_heirlooms = list(
+ /obj/item/clothing/under/shorts/purple
+ )
/datum/outfit/job/geneticist
name = "Geneticist"
diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm
index 4c38fc4cf2..6371aaaa9f 100644
--- a/code/modules/jobs/job_types/head_of_personnel.dm
+++ b/code/modules/jobs/job_types/head_of_personnel.dm
@@ -39,6 +39,10 @@
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/prosopagnosia, /datum/quirk/insanity)
threat = 2
+
+ family_heirlooms = list(
+ /obj/item/reagent_containers/food/drinks/trophy/silver_cup
+ )
/datum/outfit/job/hop
diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm
index 5339b5927c..cfe1057f8d 100644
--- a/code/modules/jobs/job_types/head_of_security.dm
+++ b/code/modules/jobs/job_types/head_of_security.dm
@@ -38,6 +38,10 @@
display_order = JOB_DISPLAY_ORDER_HEAD_OF_SECURITY
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/blindness, /datum/quirk/monophobia, /datum/quirk/insanity)
threat = 3
+
+ family_heirlooms = list(
+ /obj/item/book/manual/wiki/security_space_law
+ )
/datum/outfit/job/hos
name = "Head of Security"
diff --git a/code/modules/jobs/job_types/janitor.dm b/code/modules/jobs/job_types/janitor.dm
index c62c2e5b26..59c6997398 100644
--- a/code/modules/jobs/job_types/janitor.dm
+++ b/code/modules/jobs/job_types/janitor.dm
@@ -19,6 +19,13 @@
display_order = JOB_DISPLAY_ORDER_JANITOR
threat = 0.2
+
+ family_heirlooms = list(
+ /obj/item/mop,
+ /obj/item/clothing/suit/caution,
+ /obj/item/reagent_containers/glass/bucket,
+ /obj/item/soap
+ )
/datum/outfit/job/janitor
name = "Janitor"
diff --git a/code/modules/jobs/job_types/lawyer.dm b/code/modules/jobs/job_types/lawyer.dm
index 17c376a5de..4105bd4e6e 100644
--- a/code/modules/jobs/job_types/lawyer.dm
+++ b/code/modules/jobs/job_types/lawyer.dm
@@ -22,6 +22,11 @@
display_order = JOB_DISPLAY_ORDER_LAWYER
threat = 0.3
+
+ family_heirlooms = list(
+ /obj/item/gavelhammer,
+ /obj/item/book/manual/wiki/security_space_law
+ )
/datum/outfit/job/lawyer
name = "Lawyer"
diff --git a/code/modules/jobs/job_types/medical_doctor.dm b/code/modules/jobs/job_types/medical_doctor.dm
index 75a85c88d1..b0a0375517 100644
--- a/code/modules/jobs/job_types/medical_doctor.dm
+++ b/code/modules/jobs/job_types/medical_doctor.dm
@@ -22,6 +22,15 @@
threat = 0.5
starting_modifiers = list(/datum/skill_modifier/job/surgery, /datum/skill_modifier/job/affinity/surgery)
+
+ family_heirlooms = list(
+ /obj/item/storage/firstaid/ancient/heirloom,
+ /obj/item/scalpel,
+ /obj/item/hemostat,
+ /obj/item/circular_saw,
+ /obj/item/retractor,
+ /obj/item/cautery
+ )
/datum/outfit/job/doctor
name = "Medical Doctor"
diff --git a/code/modules/jobs/job_types/mime.dm b/code/modules/jobs/job_types/mime.dm
index 171e0cef8a..84d6bcb1a7 100644
--- a/code/modules/jobs/job_types/mime.dm
+++ b/code/modules/jobs/job_types/mime.dm
@@ -20,6 +20,10 @@
display_order = JOB_DISPLAY_ORDER_MIME
threat = 0
+
+ family_heirlooms = list(
+ /obj/item/reagent_containers/food/snacks/baguette
+ )
/datum/job/mime/after_spawn(mob/living/carbon/human/H, client/C)
. = ..()
diff --git a/code/modules/jobs/job_types/paramedic.dm b/code/modules/jobs/job_types/paramedic.dm
index 2b374921be..73f6c5da5e 100644
--- a/code/modules/jobs/job_types/paramedic.dm
+++ b/code/modules/jobs/job_types/paramedic.dm
@@ -23,6 +23,10 @@
threat = 0.5
starting_modifiers = list(/datum/skill_modifier/job/surgery, /datum/skill_modifier/job/affinity/surgery)
+
+ family_heirlooms = list(
+ /obj/item/storage/firstaid/ancient/heirloom
+ )
/datum/outfit/job/paramedic
name = "Paramedic"
diff --git a/code/modules/jobs/job_types/prisoner.dm b/code/modules/jobs/job_types/prisoner.dm
index 06eafe649b..20a2f463f5 100644
--- a/code/modules/jobs/job_types/prisoner.dm
+++ b/code/modules/jobs/job_types/prisoner.dm
@@ -13,6 +13,10 @@
plasma_outfit = /datum/outfit/plasmaman/prisoner
display_order = JOB_DISPLAY_ORDER_PRISONER
+
+ family_heirlooms = list(
+ /obj/item/pen/blue
+ )
/datum/job/prisoner/get_latejoin_spawn_point()
return get_roundstart_spawn_point()
diff --git a/code/modules/jobs/job_types/quartermaster.dm b/code/modules/jobs/job_types/quartermaster.dm
index 8ea7579127..dd79768282 100644
--- a/code/modules/jobs/job_types/quartermaster.dm
+++ b/code/modules/jobs/job_types/quartermaster.dm
@@ -32,6 +32,11 @@
display_order = JOB_DISPLAY_ORDER_QUARTERMASTER
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/insanity)
threat = 0.5
+
+ family_heirlooms = list(
+ /obj/item/stamp,
+ /obj/item/stamp/denied
+ )
/datum/outfit/job/quartermaster
name = "Quartermaster"
diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm
index 178bcc3188..606c34af5e 100644
--- a/code/modules/jobs/job_types/research_director.dm
+++ b/code/modules/jobs/job_types/research_director.dm
@@ -38,6 +38,10 @@
starting_modifiers = list(/datum/skill_modifier/job/level/wiring)
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/insanity)
threat = 5
+
+ family_heirlooms = list(
+ /obj/item/toy/plush/slimeplushie
+ )
/datum/outfit/job/rd
name = "Research Director"
diff --git a/code/modules/jobs/job_types/roboticist.dm b/code/modules/jobs/job_types/roboticist.dm
index 6f7b91571b..0e48467d91 100644
--- a/code/modules/jobs/job_types/roboticist.dm
+++ b/code/modules/jobs/job_types/roboticist.dm
@@ -24,6 +24,10 @@
display_order = JOB_DISPLAY_ORDER_ROBOTICIST
threat = 1
+
+ family_heirlooms = list(
+ /obj/item/toy/figure/borg
+ )
/datum/outfit/job/roboticist
name = "Roboticist"
diff --git a/code/modules/jobs/job_types/scientist.dm b/code/modules/jobs/job_types/scientist.dm
index 10e3f58594..4bdbe6833b 100644
--- a/code/modules/jobs/job_types/scientist.dm
+++ b/code/modules/jobs/job_types/scientist.dm
@@ -22,6 +22,10 @@
starting_modifiers = list(/datum/skill_modifier/job/level/wiring/basic)
display_order = JOB_DISPLAY_ORDER_SCIENTIST
threat = 1.2
+
+ family_heirlooms = list(
+ /obj/item/toy/plush/slimeplushie
+ )
/datum/outfit/job/scientist
name = "Scientist"
diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm
index 17b699434b..f0e579191a 100644
--- a/code/modules/jobs/job_types/security_officer.dm
+++ b/code/modules/jobs/job_types/security_officer.dm
@@ -28,6 +28,11 @@
display_order = JOB_DISPLAY_ORDER_SECURITY_OFFICER
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/blindness, /datum/quirk/monophobia)
threat = 2
+
+ family_heirlooms = list(
+ /obj/item/book/manual/wiki/security_space_law,
+ /obj/item/clothing/head/beret/sec
+ )
/datum/job/officer/get_access()
var/list/L = list()
diff --git a/code/modules/jobs/job_types/shaft_miner.dm b/code/modules/jobs/job_types/shaft_miner.dm
index e693335779..c6192280c7 100644
--- a/code/modules/jobs/job_types/shaft_miner.dm
+++ b/code/modules/jobs/job_types/shaft_miner.dm
@@ -24,6 +24,11 @@
display_order = JOB_DISPLAY_ORDER_SHAFT_MINER
threat = 1.5
+
+ family_heirlooms = list(
+ /obj/item/pickaxe/mini,
+ /obj/item/shovel
+ )
/datum/outfit/job/miner
name = "Shaft Miner (Lavaland)"
diff --git a/code/modules/jobs/job_types/station_engineer.dm b/code/modules/jobs/job_types/station_engineer.dm
index e2248362d0..58822dc4c5 100644
--- a/code/modules/jobs/job_types/station_engineer.dm
+++ b/code/modules/jobs/job_types/station_engineer.dm
@@ -27,6 +27,15 @@
display_order = JOB_DISPLAY_ORDER_STATION_ENGINEER
threat = 1
+
+ family_heirlooms = list(
+ /obj/item/clothing/head/hardhat,
+ /obj/item/screwdriver/brass/family,
+ /obj/item/wrench/brass/family,
+ /obj/item/weldingtool/mini, // No brass family variant
+ /obj/item/crowbar/brass/family,
+ /obj/item/wirecutters/brass/family
+ )
/datum/outfit/job/engineer
name = "Station Engineer"
diff --git a/code/modules/jobs/job_types/virologist.dm b/code/modules/jobs/job_types/virologist.dm
index be844be529..423a65048f 100644
--- a/code/modules/jobs/job_types/virologist.dm
+++ b/code/modules/jobs/job_types/virologist.dm
@@ -25,6 +25,10 @@
threat = 1.5
starting_modifiers = list(/datum/skill_modifier/job/surgery, /datum/skill_modifier/job/affinity/surgery)
+
+ family_heirlooms = list(
+ /obj/item/reagent_containers/syringe
+ )
/datum/outfit/job/virologist
name = "Virologist"
diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm
index 8e3ef5a253..714c599024 100644
--- a/code/modules/jobs/job_types/warden.dm
+++ b/code/modules/jobs/job_types/warden.dm
@@ -29,6 +29,10 @@
display_order = JOB_DISPLAY_ORDER_WARDEN
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/blindness, /datum/quirk/monophobia)
threat = 2
+
+ family_heirlooms = list(
+ /obj/item/book/manual/wiki/security_space_law
+ )
/datum/job/warden/get_access()
var/list/L = list()
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index d85d40fd94..84581ea0f7 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -237,6 +237,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
///For custom overrides for species ass images
var/icon/ass_image
+ /// List of family heirlooms this species can get with the family heirloom quirk. List of types.
+ var/list/family_heirlooms
+
///////////
// PROCS //
///////////
diff --git a/code/modules/mob/living/carbon/human/species_types/bugmen.dm b/code/modules/mob/living/carbon/human/species_types/bugmen.dm
index 7f9d3f40de..8b4861d558 100644
--- a/code/modules/mob/living/carbon/human/species_types/bugmen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/bugmen.dm
@@ -25,3 +25,7 @@
allowed_limb_ids = list("insect","apid","moth","moth_not_greyscale")
eye_type = "insect"
+
+ family_heirlooms = list(
+ /obj/item/flashlight/lantern/heirloom_moth
+ )
diff --git a/code/modules/mob/living/carbon/human/species_types/dwarves.dm b/code/modules/mob/living/carbon/human/species_types/dwarves.dm
index e0a9bcaa36..2820726313 100644
--- a/code/modules/mob/living/carbon/human/species_types/dwarves.dm
+++ b/code/modules/mob/living/carbon/human/species_types/dwarves.dm
@@ -20,6 +20,11 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
species_language_holder = /datum/language_holder/dwarf
species_category = SPECIES_CATEGORY_BASIC //a kind of human
+ family_heirlooms = list(
+ // Dwarves get a dwarf mug as their heirloom (normal container but has manly dorf icon)
+ /obj/item/reagent_containers/food/drinks/dwarf_mug
+ )
+
/mob/living/carbon/human/species/dwarf //species admin spawn path
race = /datum/species/dwarf //and the race the path is set to.
diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm
index eee5757b46..beebbb1dfd 100644
--- a/code/modules/mob/living/carbon/human/species_types/felinid.dm
+++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm
@@ -13,6 +13,7 @@
wagging_type = "mam_waggingtail"
species_category = SPECIES_CATEGORY_FURRY
ass_image = 'icons/ass/asscat.png'
+ family_heirlooms = list(/obj/item/toy/cattoy)
/datum/species/human/felinid/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
if(ishuman(C))
diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm
index dae4baa4f4..bb532943f8 100644
--- a/code/modules/mob/living/carbon/human/species_types/ipc.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm
@@ -37,6 +37,11 @@
species_category = SPECIES_CATEGORY_ROBOT
wings_icons = SPECIES_WINGS_ROBOT
+ family_heirlooms = list(
+ // Gives a broken powercell for flavor text!
+ /obj/item/stock_parts/cell/family
+ )
+
var/datum/action/innate/monitor_change/screen
languagewhitelist = list("Encoded Audio Language") //Skyrat change - species language whitelist
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index 01f82cbac3..a82f77867f 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -35,6 +35,10 @@
ass_image = 'icons/ass/assslime.png'
blacklisted_quirks = list(/datum/quirk/glass_bones)
+ family_heirlooms = list(
+ /obj/item/toy/plush/slimeplushie
+ )
+
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
C.faction -= "slime"
if(ishuman(C))
diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
index 7d3772e23d..227d24ba70 100644
--- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
@@ -34,6 +34,10 @@
ass_image = 'icons/ass/asslizard.png'
+ family_heirlooms = list(
+ /obj/item/toy/plush/lizardplushie
+ )
+
/datum/species/lizard/random_name(gender,unique,lastname)
if(unique)
return random_unique_lizard_name(gender)
diff --git a/code/modules/mob/living/carbon/human/species_types/synthliz.dm b/code/modules/mob/living/carbon/human/species_types/synthliz.dm
index ec1fd86780..05e075415d 100644
--- a/code/modules/mob/living/carbon/human/species_types/synthliz.dm
+++ b/code/modules/mob/living/carbon/human/species_types/synthliz.dm
@@ -37,3 +37,8 @@
wagging_type = "mam_waggingtail"
species_category = SPECIES_CATEGORY_ROBOT
wings_icons = SPECIES_WINGS_ROBOT
+
+ family_heirlooms = list(
+ // They're also robots
+ /obj/item/stock_parts/cell/family
+ )
diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm
index e1b198ade2..420810d7d2 100644
--- a/code/modules/surgery/organs/augments_chest.dm
+++ b/code/modules/surgery/organs/augments_chest.dm
@@ -20,6 +20,10 @@
if(!. || synthesizing)
return
+ // Check if this user can process nutriment
+ if(HAS_TRAIT(owner, TRAIT_NO_PROCESS_FOOD))
+ return
+
if(owner.nutrition <= hunger_threshold)
synthesizing = TRUE
to_chat(owner, "You feel less hungry...")
diff --git a/code/modules/vending/cartridge.dm b/code/modules/vending/cartridge.dm
index c4b35496c2..d80d8e958e 100644
--- a/code/modules/vending/cartridge.dm
+++ b/code/modules/vending/cartridge.dm
@@ -5,15 +5,34 @@
product_slogans = "Carts to go!"
icon_state = "cart"
icon_deny = "cart-deny"
- products = list(/obj/item/cartridge/medical = 10,
+ products = list(/obj/item/pda/heads = 10, // PDA
+ // Normal staff cards
+ /obj/item/cartridge/medical = 10,
/obj/item/cartridge/engineering = 10,
/obj/item/cartridge/security = 10,
/obj/item/cartridge/janitor = 10,
/obj/item/cartridge/signal/toxins = 10,
/obj/item/cartridge/roboticist = 10,
- /obj/item/pda/heads = 10,
+ /obj/item/cartridge/atmos = 10,
+ /obj/item/cartridge/chemistry = 10,
+ /obj/item/cartridge/detective = 10,
+ /obj/item/cartridge/lawyer = 10,
+ /obj/item/cartridge/curator = 10,
+ /obj/item/cartridge/bartender = 10,
+
+ // Virus cards
+ /obj/item/cartridge/virus/clown = 3,
+ /obj/item/cartridge/virus/mime = 3,
+
+ // Command staff cards
/obj/item/cartridge/captain = 3,
- /obj/item/cartridge/quartermaster = 10)
+ /obj/item/cartridge/quartermaster = 10,
+ /obj/item/cartridge/head = 10,
+ /obj/item/cartridge/hos = 10,
+ /obj/item/cartridge/ce = 10,
+ /obj/item/cartridge/cmo = 10,
+ /obj/item/cartridge/rd = 10)
+
armor = list(MELEE = 100, BULLET = 100, LASER = 100, ENERGY = 100, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 50)
refill_canister = /obj/item/vending_refill/cart
resistance_flags = FIRE_PROOF
diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi
index 0f49bc6d5f..09a9213f2a 100644
Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ
diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi
index 27ad84b1a4..3204b36cc5 100644
Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ
diff --git a/modular_citadel/code/modules/client/loadout/backpack.dm b/modular_citadel/code/modules/client/loadout/backpack.dm
index 5879426041..a0be000b31 100644
--- a/modular_citadel/code/modules/client/loadout/backpack.dm
+++ b/modular_citadel/code/modules/client/loadout/backpack.dm
@@ -190,3 +190,8 @@
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION
subcategory = LOADOUT_SUBCATEGORY_BACKPACK_ACCESSORIES
cost = 0
+
+// Moved here from quirks
+/datum/gear/backpack/dyespray
+ name = "Hair dye spray"
+ path = /obj/item/dyespray