Skip to content
12 changes: 12 additions & 0 deletions code/__DEFINES/living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,18 @@
/// For consistent examine span formatting (small size)
#define examining_span_small(msg) span_slightly_smaller(span_infoplain(span_italics(msg)))

// Smell intensities
/// Very faint - Often low enough to not noticed, but if noticed, people get used to it quickly
#define SMELL_INTENSITY_FAINT 1
/// Will be noticed for a short time but eventually people get used to it
#define SMELL_INTENSITY_WEAK 6
/// Noticable, will take a while to get used to
#define SMELL_INTENSITY_MODERATE 12
/// Very strong, hard to ignore, very unlikely to get used to
#define SMELL_INTENSITY_STRONG 24
/// Overpowers all other smells, extremely hard to ignore
#define SMELL_INTENSITY_OVERPOWERING 48

/// Damtype is "physical" like a slap to the face
#define IS_PHYSICAL_DAMAGE(damage_type) (damage_type == BRUTE || damage_type == BURN)
/// Damtype is intended to disable rather than kill
Expand Down
1 change: 1 addition & 0 deletions code/__DEFINES/traits/declarations.dm
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai

//quirk traits
#define TRAIT_ALCOHOL_TOLERANCE "alcohol_tolerance"
#define TRAIT_ANOSMIA "anosmia"
#define TRAIT_HEAVY_DRINKER "heavy_drinker"
#define TRAIT_AGEUSIA "ageusia"
#define TRAIT_HEAVY_SLEEPER "heavy_sleeper"
Expand Down
1 change: 1 addition & 0 deletions code/_globalvars/traits/_traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_ALWAYS_NO_ACCESS" = TRAIT_ALWAYS_NO_ACCESS,
"TRAIT_ALWAYS_WANTED" = TRAIT_ALWAYS_WANTED,
"TRAIT_ANGELIC" = TRAIT_ANGELIC,
"TRAIT_ANOSMIA" = TRAIT_ANOSMIA,
"TRAIT_ANTENNAE" = TRAIT_ANTENNAE,
"TRAIT_ANTICONVULSANT" = TRAIT_ANTICONVULSANT,
"TRAIT_ANTIMAGIC" = TRAIT_ANTIMAGIC,
Expand Down
1 change: 1 addition & 0 deletions code/_globalvars/traits/admin_tooling.dm
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_AGENDER" = TRAIT_AGENDER,
"TRAIT_AGEUSIA" = TRAIT_AGEUSIA,
"TRAIT_ALCOHOL_TOLERANCE" = TRAIT_ALCOHOL_TOLERANCE,
"TRAIT_ANOSMIA" = TRAIT_ANOSMIA,
"TRAIT_ANTIMAGIC" = TRAIT_ANTIMAGIC,
"TRAIT_ANXIOUS" = TRAIT_ANXIOUS,
"TRAIT_BADDNA" = TRAIT_BADDNA,
Expand Down
5 changes: 3 additions & 2 deletions code/datums/components/bakeable.dm
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,11 @@
used_tray.AddToPlate(baked_result)

if(positive_result)
used_oven.visible_message(span_notice("You smell something great coming from [used_oven]."), blind_message = span_notice("You smell something great..."))
new /obj/effect/abstract/smell/oven/good(used_oven.loc)
BLACKBOX_LOG_FOOD_MADE(baked_result.type)
else
used_oven.visible_message(span_warning("You smell a burnt smell coming from [used_oven]."), blind_message = span_warning("You smell a burnt smell..."))
new /obj/effect/abstract/smell/oven/bad(used_oven.loc)

SEND_SIGNAL(parent, COMSIG_ITEM_BAKED, baked_result)
qdel(parent)

Expand Down
2 changes: 1 addition & 1 deletion code/datums/diseases/advance/symptoms/fire.dm
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
living_mob.show_message(span_hear("You hear a crackling noise."), type = MSG_AUDIBLE)
else if(prob(50) && !HAS_TRAIT(living_mob, TRAIT_RESISTHEAT))
to_chat(living_mob, span_warning("You feel hot."))
else
else if(living_mob.can_smell()) //Anosmia quirk holder can't smell anything.
to_chat(living_mob, span_warning("You smell smoke."))

/*
Expand Down
8 changes: 4 additions & 4 deletions code/datums/mood_events/generic_negative_events.dm
Original file line number Diff line number Diff line change
Expand Up @@ -590,14 +590,14 @@
timeout = 1 MINUTES

/datum/mood_event/smoke_in_face
description = "Cigarette smoke is disgusting."
description = "They just blew disgusting smoke in my face!"
mood_change = -3
timeout = 30 SECONDS

/datum/mood_event/smoke_in_face/add_effects(param)
// if(HAS_TRAIT(owner, TRAIT_ANOSMIA))
// description = "Cigarette smoke is unpleasant."
// mood_change = -1
if(!owner.can_smell())
description = "They just blew some unpleasant smoke in my face."
mood_change = -1
if(HAS_TRAIT(owner, TRAIT_SMOKER))
description = "Blowing smoke in my face, really?"
mood_change = 0
Expand Down
8 changes: 0 additions & 8 deletions code/datums/mood_events/needs_events.dm
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,6 @@
description = "Oh god, that's disgusting..."
mood_change = -8

/datum/mood_event/disgust/bad_smell
description = "I can smell something horribly decayed inside this room."
mood_change = -6

/datum/mood_event/disgust/nauseating_stench
description = "The stench of rotting carcasses is unbearable!"
mood_change = -12

/datum/mood_event/disgust/dirty_food
description = "That was too dirty to eat..."
mood_change = -6
Expand Down
4 changes: 4 additions & 0 deletions code/datums/mutations/olfaction.dm
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
to_chat(owner, span_warning("You have no nose!"))
return FALSE

if(!living_cast_on.can_smell()) //Anosmia quirk holders can't smell anything
to_chat(owner, span_warning("You can't smell!"))
return FALSE

return TRUE

/datum/action/cooldown/spell/olfaction/cast(mob/living/cast_on)
Expand Down
9 changes: 9 additions & 0 deletions code/datums/quirks/negative_quirks/anosmia.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/datum/quirk/item_quirk/anosmia
name = "Anosmia"
desc = "For some reason, you can't smell anything."
icon = FA_ICON_HEAD_SIDE_COUGH_SLASH
value = -2
mob_trait = TRAIT_ANOSMIA
gain_text = span_notice("You find yourself unable to smell anything!")
lose_text = span_danger("Suddenly, you can smell again!")
medical_record_text = "Patient has lost their sensation of smell."
5 changes: 5 additions & 0 deletions code/datums/wounds/internal_bleeding.dm
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@
if(QDELETED(src))
return

if(SPT_PROB(1, seconds_per_tick))
var/datum/blood_type/blood_type = victim.get_blood_type()
if(blood_type)
to_chat(victim, span_notice("You can taste [blood_type.reagent_type::name]."))

switch(limb.body_zone)
if(BODY_ZONE_HEAD)
if(SPT_PROB(2, seconds_per_tick))
Expand Down
9 changes: 9 additions & 0 deletions code/game/objects/effects/decals/cleanable/humans.dm
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// NON-MODULE CHANGE : This whole file

#define BLOOD_SMELL_INTENSITY(blood) floor((initial(blood.bloodiness) || blood.bloodiness) * 0.2)
#define BLOOD_SMELL_RADIUS(blood) ceil((initial(blood.bloodiness) || blood.bloodiness) * 0.04)

/obj/effect/decal/cleanable/blood
name = "pool of blood"
desc = "It's weird and gooey. Perhaps it's the chef's cooking?"
Expand Down Expand Up @@ -43,6 +46,7 @@
else if(can_dry)
START_PROCESSING(SSblood_drying, src)
// update_atom_colour() // this is already called by parent via add_atom_colour
AddElement(/datum/element/simple_smell, /datum/smell/blood, BLOOD_SMELL_INTENSITY(src), BLOOD_SMELL_RADIUS(src))

/obj/effect/decal/cleanable/blood/Destroy()
STOP_PROCESSING(SSblood_drying, src)
Expand Down Expand Up @@ -151,6 +155,7 @@
update_appearance()
update_atom_colour()
STOP_PROCESSING(SSblood_drying, src)
RemoveElement(/datum/element/simple_smell, /datum/smell/blood, BLOOD_SMELL_INTENSITY(src), BLOOD_SMELL_RADIUS(src))
return TRUE

/obj/effect/decal/cleanable/blood/lazy_init_reagents()
Expand All @@ -175,6 +180,9 @@
merger.adjust_bloodiness(bloodiness)
merger.slow_dry(1 SECONDS * bloodiness * BLOOD_PER_UNIT_MODIFIER)

#undef BLOOD_SMELL_INTENSITY
#undef BLOOD_SMELL_RADIUS

/obj/effect/decal/cleanable/blood/old
bloodiness = 0
dried = TRUE
Expand Down Expand Up @@ -434,6 +442,7 @@
. = ..()
setDir(pick(GLOB.cardinals))
AddElement(/datum/element/swabable, CELL_LINE_TABLE_SLUDGE, CELL_VIRUS_TABLE_GENERIC, rand(2,4), 10)
AddElement(/datum/element/simple_smell, /datum/smell/decay, SMELL_INTENSITY_STRONG, 1)

/obj/effect/decal/cleanable/blood/drip
name = "drop of blood"
Expand Down
19 changes: 19 additions & 0 deletions code/game/objects/effects/decals/cleanable/misc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,13 @@
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
beauty = -150

/obj/effect/decal/cleanable/vomit/Initialize(mapload, list/datum/disease/diseases)
. = ..()
leave_smell()

/obj/effect/decal/cleanable/vomit/proc/leave_smell()
AddElement(/datum/element/simple_smell, "vomit", SMELL_INTENSITY_STRONG, 1)

/obj/effect/decal/cleanable/vomit/attack_hand(mob/user, list/modifiers)
. = ..()
if(.)
Expand All @@ -187,6 +194,9 @@
icon_state = "vomitnanite_1"
random_icon_states = list("vomitnanite_1", "vomitnanite_2", "vomitnanite_3", "vomitnanite_4")

/obj/effect/decal/cleanable/vomit/nanites/leave_smell()
return

/obj/effect/decal/cleanable/vomit/nebula
name = "nebula vomit"
desc = "Gosh, how... beautiful."
Expand All @@ -198,6 +208,9 @@
. = ..()
update_appearance(UPDATE_OVERLAYS)

/obj/effect/decal/cleanable/vomit/nebula/leave_smell()
return

/obj/effect/decal/cleanable/vomit/nebula/update_overlays()
. = ..()
. += emissive_appearance(icon, icon_state, src, alpha = src.alpha)
Expand All @@ -211,6 +224,9 @@
icon_state += "-old"
AddElement(/datum/element/swabable, CELL_LINE_TABLE_SLUDGE, CELL_VIRUS_TABLE_GENERIC, rand(2,4), 10)

/obj/effect/decal/cleanable/vomit/old/leave_smell()
return

/obj/effect/decal/cleanable/vomit/old/black_bile
name = "black bile"
desc = "There's something wiggling in there..."
Expand Down Expand Up @@ -319,6 +335,7 @@
/obj/effect/decal/cleanable/garbage/Initialize(mapload)
. = ..()
AddElement(/datum/element/swabable, CELL_LINE_TABLE_SLUDGE, CELL_VIRUS_TABLE_GENERIC, rand(2,4), 15)
AddElement(/datum/element/simple_smell, "rotting garbage", SMELL_INTENSITY_MODERATE, 2, "stench")

/obj/effect/decal/cleanable/ants
name = "space ants"
Expand Down Expand Up @@ -438,6 +455,8 @@
if(burn_stacks)
burn_amount = max(min(burn_stacks, 10), 1)

AddElement(/datum/element/simple_smell, "fuel", floor(SMELL_INTENSITY_MODERATE * burn_amount * 0.1), 1, "stench")

/obj/effect/decal/cleanable/fuel_pool/fire_act(exposed_temperature, exposed_volume)
. = ..()
ignite()
Expand Down
18 changes: 1 addition & 17 deletions code/game/objects/effects/decals/cleanable/robots.dm
Original file line number Diff line number Diff line change
Expand Up @@ -87,25 +87,9 @@
/obj/effect/decal/cleanable/oil/Initialize(mapload, list/datum/disease/diseases)
. = ..()
AddElement(/datum/element/easy_ignite) // NON-MODULE CHANGE
AddElement(/datum/element/simple_smell, /datum/smell/oil, SMELL_INTENSITY_STRONG, 2) // NON-MODULE CHANGE
add_blood_DNA(list("CRUDE OIL" = /datum/blood_type/oil)) // NON-MODULE CHANGE : For bloody shoes // Yeah don't think about it too much

// /obj/effect/decal/cleanable/oil/attackby(obj/item/I, mob/living/user)
// var/attacked_by_hot_thing = I.get_temperature()
// if(attacked_by_hot_thing)
// user.visible_message(span_warning("[user] tries to ignite [src] with [I]!"), span_warning("You try to ignite [src] with [I]."))
// log_combat(user, src, (attacked_by_hot_thing < 480) ? "tried to ignite" : "ignited", I)
// fire_act(attacked_by_hot_thing)
// return
// return ..()

// /obj/effect/decal/cleanable/oil/fire_act(exposed_temperature, exposed_volume)
// if(exposed_temperature < 480)
// return
// visible_message(span_danger("[src] catches fire!"))
// var/turf/T = get_turf(src)
// qdel(src)
// new /obj/effect/hotspot(T)

/obj/effect/decal/cleanable/oil/streak
icon_state = "streak1"
random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
Expand Down
2 changes: 2 additions & 0 deletions code/game/objects/items/cigs_lighters.dm
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/// Handles processing the reagents in the cigarette.
/obj/item/cigarette/proc/handle_reagents(mob/living/carbon/smoker, seconds_per_tick)
reagents.expose_temperature(heat, 0.05)
if(reagents.has_reagent(/datum/reagent/drug/nicotine, 1, check_subtypes = TRUE))
new /obj/effect/abstract/smell/cigarette_smoke(get_turf(smoker || src))
if(reagents.total_volume <= 0) //may have reacted and gone to 0 after expose_temperature
return

Expand Down
7 changes: 7 additions & 0 deletions code/game/objects/items/storage/backpack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,13 @@
/datum/component/bloody_spreader,\
blood_dna = list("UNKNOWN DNA" = /datum/blood_type/animal),\
)
AddComponent(
/datum/component/complex_smell, \
duration = INFINITY, \
smell = "meat", \
intensity = SMELL_INTENSITY_STRONG, \
radius = 2, \
)
atom_storage.storage_sound = 'sound/effects/blobattack.ogg'

/*
Expand Down
2 changes: 2 additions & 0 deletions code/game/objects/structures/bonfire.dm
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@
bonfire_burn()
particles = new /particles/bonfire()
START_PROCESSING(SSobj, src)
AddElement(/datum/element/simple_smell, "smoke", SMELL_INTENSITY_STRONG, 5)

/obj/structure/bonfire/fire_act(exposed_temperature, exposed_volume)
start_burning()
Expand Down Expand Up @@ -173,6 +174,7 @@
set_light(0)
QDEL_NULL(particles)
STOP_PROCESSING(SSobj, src)
RemoveElement(/datum/element/simple_smell, "smoke", SMELL_INTENSITY_STRONG, 5)

/obj/structure/bonfire/buckle_mob(mob/living/buckled_mob, force = FALSE, check_loc = TRUE)
if(..())
Expand Down
1 change: 1 addition & 0 deletions code/game/objects/structures/headpike.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
if(mapload)
CheckParts()
pixel_x = rand(-8, 8)
AddElement(/datum/element/simple_smell, /datum/smell/decay, SMELL_INTENSITY_MODERATE, 2)

/obj/structure/headpike/Destroy()
QDEL_NULL(victim)
Expand Down
2 changes: 2 additions & 0 deletions code/game/turfs/open/_open.dm
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
var/broken = FALSE
var/burnt = FALSE

/// Assoc list of smell datum to sum of intensities present on this turf
VAR_FINAL/list/collective_smells

/// Returns a list of every turf state considered "broken".
/// Will be randomly chosen if a turf breaks at runtime.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
/datum/action/changeling/pheromone_receptors/sting_action(mob/living/carbon/user)
..()
var/datum/antagonist/changeling/changeling = IS_CHANGELING(user)
if(HAS_TRAIT(user, TRAIT_ANOSMIA)) //Anosmia quirk holders can't smell anything
to_chat(user, span_warning("We can't smell!"))
return
if(!receptors_active)
to_chat(user, span_warning("We search for the scent of any nearby changelings."))
changeling.chem_recharge_slowdown += 0.25
Expand Down
Loading
Loading