Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
101 changes: 86 additions & 15 deletions code/game/objects/effects/decals/cleanable/humans.dm
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// NON-MODULE CHANGE : This whole file

/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 @@ -34,10 +33,15 @@
/// The process to drying out, recorded in deciseconds
VAR_FINAL/drying_progress = 0

/obj/effect/decal/cleanable/blood/Initialize(mapload, list/datum/disease/diseases)
/// Lazylist of smell elements present, so we can remove them as we change dna and bloodiness
VAR_PRIVATE/list/smell_elements_present
/// Tracks the bloodiness at the last time we refreshed smells, we can avoid refreshing until a significant change has been made
VAR_PRIVATE/last_bloodiness_refresh = 0

/obj/effect/decal/cleanable/blood/Initialize(mapload, list/datum/disease/diseases, list/starting_dna)
. = ..()
if(mapload)
add_blood_DNA(list("UNKNOWN DNA" = random_human_blood_type()))
if(mapload || starting_dna)
init_dna(starting_dna)
if(dried)
dry()
else if(can_dry)
Expand All @@ -48,6 +52,9 @@
STOP_PROCESSING(SSblood_drying, src)
return ..()

/obj/effect/decal/cleanable/blood/proc/init_dna(list/starting_dna)
add_blood_DNA(starting_dna || list("UNKNOWN DNA" = random_human_blood_type()))

/obj/effect/decal/cleanable/blood/on_entered(datum/source, atom/movable/AM)
if(dried)
return
Expand Down Expand Up @@ -151,8 +158,61 @@
update_appearance()
update_atom_colour()
STOP_PROCESSING(SSblood_drying, src)
clear_smells()
return TRUE

/obj/effect/decal/cleanable/blood/adjust_bloodiness(by_amount)
. = ..()
if(!. || abs(last_bloodiness_refresh - bloodiness) < BLOOD_AMOUNT_PER_DECAL * 0.2)
return

refresh_smells()

/// Add the passed smell with the passed category to the blood
/// Can optionally pass a multiplier which affects both intensity and radius
/obj/effect/decal/cleanable/blood/proc/add_smell(smell, category, multiplier = 1)
var/intensity = max(floor(bloodiness * 0.2 * multiplier), SMELL_INTENSITY_FAINT)
var/radius = round(bloodiness * 0.04 * multiplier)
AddElement(/datum/element/simple_smell, \
smell = smell, \
category = category, \
intensity = intensity, \
radius = radius, \
id = "dna", \
smell_basetype = /datum/smell/blood, \
)
LAZYADD(smell_elements_present, list(list(
"smell" = smell,
"category" = category,
"intensity" = intensity,
"radius" = radius,
)))

/obj/effect/decal/cleanable/blood/proc/refresh_smells()
clear_smells()
var/list/unique_smells = list()
for(var/some_dna, blood_type in GET_ATOM_BLOOD_DNA(src))
var/datum/blood_type/blood = find_blood_type(blood_type)
if(!blood.scent_text)
continue
unique_smells["[blood.scent_text]-[blood.scent_category]"] += 1
for(var/blood_smell, count in unique_smells)
var/resplit_smell = splittext(blood_smell, "-")
add_smell(text2path(resplit_smell[1]) || resplit_smell[1], resplit_smell[2], count / GET_ATOM_BLOOD_DNA_LENGTH(src))
last_bloodiness_refresh = bloodiness

/obj/effect/decal/cleanable/blood/proc/clear_smells()
for(var/list/smell_element as anything in smell_elements_present)
RemoveElement(/datum/element/simple_smell, \
smell = smell_element["smell"], \
category = smell_element["category"], \
intensity = smell_element["intensity"], \
radius = smell_element["radius"], \
id = "dna", \
smell_basetype = /datum/smell/blood, \
)
LAZYREMOVE(smell_elements_present, list(smell_element))

/obj/effect/decal/cleanable/blood/lazy_init_reagents()
var/list/all_dna = GET_ATOM_BLOOD_DNA(src)
var/list/reagents_to_add = list()
Expand Down Expand Up @@ -208,11 +268,11 @@
icon_state = "trails_1"
random_icon_states = null
base_name = "trail of"
bloodiness = BLOOD_AMOUNT_PER_DECAL * 0.1
bloodiness = BLOOD_AMOUNT_PER_DECAL * 0.15
/// All the components of the trail
var/list/obj/effect/decal/cleanable/blood/trail/trail_components

/obj/effect/decal/cleanable/blood/trail_holder/Initialize(mapload)
/obj/effect/decal/cleanable/blood/trail_holder/Initialize(mapload, list/datum/disease/diseases, list/starting_dna)
. = ..()
icon_state = ""
if(mapload)
Expand Down Expand Up @@ -297,7 +357,7 @@
desc = "A trail of blood."
beauty = -50
decay_bloodiness = FALSE // bloodiness is used as a metric for for how big the sprite is, so don't decay passively
bloodiness = BLOOD_AMOUNT_PER_DECAL * 0.1
bloodiness = BLOOD_AMOUNT_PER_DECAL * 0.15
icon_state = "ltrails_1"
random_icon_states = list("ltrails_1", "ltrails_2")
base_name = ""
Expand All @@ -314,6 +374,11 @@
very_bloody = TRUE
icon_state = pick("trails_1", "trails_2")

/obj/effect/decal/cleanable/blood/trail/add_smell(smell, category, multiplier)
if(!isturf(loc))
return // fake
return ..()

/obj/effect/decal/cleanable/blood/gibs
name = "gibs"
desc = "They look bloody and gruesome."
Expand All @@ -332,7 +397,7 @@
///Information about the diseases our streaking spawns
var/list/streak_diseases

/obj/effect/decal/cleanable/blood/gibs/Initialize(mapload, list/datum/disease/diseases)
/obj/effect/decal/cleanable/blood/gibs/Initialize(mapload, list/datum/disease/diseases, list/starting_dna)
. = ..()
RegisterSignal(src, COMSIG_MOVABLE_PIPE_EJECTING, PROC_REF(on_pipe_eject))

Expand Down Expand Up @@ -430,21 +495,27 @@
dry_prefix = ""
dry_desc = ""

/obj/effect/decal/cleanable/blood/gibs/old/Initialize(mapload, list/datum/disease/diseases)
/obj/effect/decal/cleanable/blood/gibs/old/Initialize(mapload, list/datum/disease/diseases, list/starting_dna)
. = ..()
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"
desc = "A spattering."
icon_state = "drip5" //using drip5 since the others tend to blend in with pipes & wires.
random_icon_states = list("drip1","drip2","drip3","drip4","drip5")
bloodiness = BLOOD_AMOUNT_PER_DECAL * 0.2 * BLOOD_PER_UNIT_MODIFIER
bloodiness = BLOOD_AMOUNT_PER_DECAL * 0.1
base_name = "drop of"
dry_desc = "A dried spattering."
drying_time = 1 MINUTES

/obj/effect/decal/cleanable/blood/drip/add_smell(smell, category, multiplier)
if(!isturf(loc))
return // fake
return ..()

//BLOODY FOOTPRINTS
/obj/effect/decal/cleanable/blood/footprints
name = "footprints"
Expand All @@ -468,7 +539,7 @@
/obj/effect/decal/cleanable/blood/footprints/get_save_vars()
return ..() - NAMEOF(src, icon_state)

/obj/effect/decal/cleanable/blood/footprints/Initialize(mapload)
/obj/effect/decal/cleanable/blood/footprints/Initialize(mapload, list/datum/disease/diseases, list/starting_dna)
. = ..()
icon_state = "" //All of the footprint visuals come from overlays
if(mapload)
Expand Down Expand Up @@ -581,7 +652,7 @@
/// Tracks what direction we're flying
var/flight_dir = NONE

/obj/effect/decal/cleanable/blood/hitsplatter/Initialize(mapload, list/datum/disease/diseases, splatter_strength)
/obj/effect/decal/cleanable/blood/hitsplatter/Initialize(mapload, list/datum/disease/diseases, list/starting_dna, splatter_strength)
. = ..()
prev_loc = loc //Just so we are sure prev_loc exists
if(splatter_strength)
Expand Down Expand Up @@ -685,9 +756,9 @@
/obj/effect/decal/cleanable/blood/pre_dna
var/list/dna_types = list("UNKNOWN DNA A" = /datum/blood_type/crew/human/a_minus)

/obj/effect/decal/cleanable/blood/pre_dna/Initialize(mapload)
. = ..()
add_blood_DNA(dna_types)
/obj/effect/decal/cleanable/blood/pre_dna/Initialize(mapload, list/datum/disease/diseases, list/starting_dna)
starting_dna = dna_types
return ..()

/obj/effect/decal/cleanable/blood/pre_dna/lizard
dna_types = list("UNKNOWN DNA A" = /datum/blood_type/crew/lizard)
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
Loading