mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 05:30:05 +01:00
Keen Nose Quirk - The Smell of Discovery (#95697)
## About The Pull Request This adds a new positive quirk called "**Keen Nose**" that costs 3 points. It lets you examine any open container with reagents to smell them. It generates the smell based on the taste description. Also added an effect to pepper spray, where it causes you to lose your sense of smell temporarily. This quirk is blacklisted against the Anosmia quirk, which is the opposite. (no sense of smell) ## Why It's Good For The Game Since there is a serious lack of positive quirks, I figured this one might be useful as a utility quirk. It's a niche thing that could come in handy. Keep in mind, there are several ways to identify chemicals, like using the bartender's beer goggles, the science goggles, a chem machine, or just eyeballing the color. Also, many chems have overlapping taste descriptions (several different things taste like "death") so it's not foolproof.
This commit is contained in:
@@ -1041,6 +1041,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_SETTLER "settler"
|
||||
#define TRAIT_STRONG_STOMACH "strong_stomach"
|
||||
#define TRAIT_VEGETARIAN "trait_vegetarian"
|
||||
#define TRAIT_KEEN_NOSE "keen_nose"
|
||||
|
||||
/// This mob always lands on their feet when they fall, for better or for worse.
|
||||
#define TRAIT_CATLIKE_GRACE "catlike_grace"
|
||||
|
||||
@@ -365,6 +365,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_IN_CALL" = TRAIT_IN_CALL,
|
||||
"TRAIT_IS_WET" = TRAIT_IS_WET,
|
||||
"TRAIT_IWASBATONED" = TRAIT_IWASBATONED,
|
||||
"TRAIT_KEEN_NOSE" = TRAIT_KEEN_NOSE,
|
||||
"TRAIT_KISS_OF_DEATH" = TRAIT_KISS_OF_DEATH,
|
||||
"TRAIT_SEE_BLESSED_TILES" = TRAIT_SEE_BLESSED_TILES,
|
||||
"TRAIT_SYNDIE_KISS" = TRAIT_SYNDIE_KISS,
|
||||
|
||||
@@ -160,6 +160,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
|
||||
"TRAIT_INTROVERT" = TRAIT_INTROVERT,
|
||||
"TRAIT_INVISIBLE_MAN" = TRAIT_INVISIBLE_MAN,
|
||||
"TRAIT_IWASBATONED" = TRAIT_IWASBATONED,
|
||||
"TRAIT_KEEN_NOSE" = TRAIT_KEEN_NOSE,
|
||||
"TRAIT_KISS_OF_DEATH" = TRAIT_KISS_OF_DEATH,
|
||||
"TRAIT_KNOCKEDOUT" = TRAIT_KNOCKEDOUT,
|
||||
"TRAIT_KNOW_ENGI_WIRES" = TRAIT_KNOW_ENGI_WIRES,
|
||||
|
||||
@@ -26,6 +26,7 @@ GLOBAL_LIST_INIT_TYPED(quirk_blacklist, /list/datum/quirk, list(
|
||||
list(/datum/quirk/settler, /datum/quirk/freerunning),
|
||||
list(/datum/quirk/numb, /datum/quirk/selfaware),
|
||||
list(/datum/quirk/empath, /datum/quirk/evil),
|
||||
list(/datum/quirk/keen_nose, /datum/quirk/item_quirk/anosmia),
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(quirk_string_blacklist, generate_quirk_string_blacklist())
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/datum/quirk/keen_nose
|
||||
name = "Keen Nose"
|
||||
desc = "You have a very sensitive nose. You can smell the contents of any open containers you are holding simply by examining them."
|
||||
icon = FA_ICON_FLASK
|
||||
value = 3
|
||||
mob_trait = TRAIT_KEEN_NOSE
|
||||
gain_text = span_notice("You can smell everything around you much more clearly.")
|
||||
lose_text = span_danger("Your sense of smell returns to normal.")
|
||||
medical_record_text = "Patient has an unusually sensitive olfactory system."
|
||||
@@ -44,7 +44,6 @@
|
||||
if(reagents.is_reacting)
|
||||
. += span_warning("It is currently reacting!")
|
||||
. += span_notice("The solution's pH is [round(reagents.ph, 0.01)] and has a temperature of [reagents.chem_temp]K.")
|
||||
|
||||
else
|
||||
. += "It contains:<br>Nothing."
|
||||
else if(reagents.flags & AMOUNT_VISIBLE)
|
||||
@@ -53,8 +52,29 @@
|
||||
else
|
||||
. += span_danger("It's empty.")
|
||||
|
||||
if(HAS_TRAIT(user, TRAIT_KEEN_NOSE))
|
||||
var/sniff_text = get_sniff_examine(user)
|
||||
if(sniff_text)
|
||||
. += sniff_text
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE, user, .)
|
||||
|
||||
/// Returns an examine string describing what the contents of this atom smell like
|
||||
/atom/proc/get_sniff_examine(mob/living/carbon/sniffer)
|
||||
if(!istype(sniffer) || HAS_TRAIT(sniffer, TRAIT_ANOSMIA))
|
||||
return
|
||||
if(!is_open_container() || !reagents?.total_volume)
|
||||
return
|
||||
if(!sniffer.is_holding(src))
|
||||
return
|
||||
if(!sniffer.get_bodypart(BODY_ZONE_HEAD)) // Need a nose to smell
|
||||
return
|
||||
if(sniffer.is_mouth_covered())
|
||||
return span_warning("You can't get a whiff of [src] with your face covered.")
|
||||
|
||||
var/smell_message = generate_reagents_taste_message(reagents.reagent_list, sniffer, 10)
|
||||
return span_notice("You catch a whiff of [src]. It smells like [smell_message].")
|
||||
|
||||
/**
|
||||
* A list of "tags" displayed after atom's description in examine.
|
||||
* This should return an assoc list of tags -> tooltips for them. If item is null, then no tooltip is assigned.
|
||||
|
||||
@@ -473,6 +473,8 @@
|
||||
victim.Knockdown(3 SECONDS)
|
||||
victim.add_movespeed_modifier(/datum/movespeed_modifier/reagent/pepperspray)
|
||||
addtimer(CALLBACK(victim, TYPE_PROC_REF(/mob, remove_movespeed_modifier), /datum/movespeed_modifier/reagent/pepperspray), 10 SECONDS)
|
||||
ADD_TRAIT(victim, TRAIT_ANOSMIA, type)
|
||||
addtimer(TRAIT_CALLBACK_REMOVE(victim, TRAIT_ANOSMIA, type), 30 SECONDS, TIMER_OVERRIDE|TIMER_UNIQUE)
|
||||
victim.update_damage_hud()
|
||||
if(methods & INGEST)
|
||||
if(!holder.has_reagent(/datum/reagent/consumable/milk))
|
||||
|
||||
@@ -1,41 +1,45 @@
|
||||
|
||||
#define TEXT_NO_TASTE "something indescribable"
|
||||
|
||||
//================================TASTE===================================================
|
||||
//=============================== TASTE GRAPH ====================================
|
||||
// //
|
||||
// Flavor Intensity Thresholds (Relative to Detection Threshold % 'DT'): //
|
||||
// 0% 1x DT 2x DT 4x DT 100% //
|
||||
// |----------------|------------------|------------------|-----------------| //
|
||||
// | Undetected | Weak | Mild | Strong | //
|
||||
// |----------------|------------------|------------------|-----------------| //
|
||||
// //
|
||||
//==============================================================================//
|
||||
|
||||
/**
|
||||
* Returns what this reagents in our given list taste like
|
||||
* Returns what the reagents in our given list taste like
|
||||
*
|
||||
* Arguments:
|
||||
* * list/reagent_list - List of reagents to taste.
|
||||
* * mob/living/taster - Who is doing the tasting. Some mobs can pick up specific flavours.
|
||||
* * minimum_percent - The lower the minimum percent, the more sensitive the message is.
|
||||
* * weight_modifier - Value to multiply each reagent's taste weight with.
|
||||
* * detection_threshold_percent - The minimum relative percentage a flavor must reach to be tasted.
|
||||
*/
|
||||
/proc/generate_reagents_taste_message(list/reagent_list, mob/living/taster, minimum_percent)
|
||||
/proc/generate_reagents_taste_message(list/reagent_list, mob/living/taster, detection_threshold_percent)
|
||||
// We can't taste anything
|
||||
if(minimum_percent > 100)
|
||||
if(detection_threshold_percent > 100)
|
||||
return TEXT_NO_TASTE
|
||||
|
||||
// Associative list of our tastes, descriptor - strength
|
||||
// Associative list of our tastes - list("taste description" = strength)
|
||||
var/list/tastes = list()
|
||||
// Total of our taste strengths so far
|
||||
var/total_taste = 0
|
||||
var/total_taste_strength = 0
|
||||
|
||||
for(var/datum/reagent/reagent as anything in reagent_list)
|
||||
if(!reagent.taste_mult)
|
||||
continue
|
||||
|
||||
var/list/taste_data = reagent.get_taste_description(taster)
|
||||
for(var/taste in taste_data)
|
||||
var/taste_strength = taste_data[taste] * reagent.volume * reagent.taste_mult
|
||||
if(taste in tastes)
|
||||
tastes[taste] += taste_strength
|
||||
else
|
||||
tastes[taste] = taste_strength
|
||||
total_taste += taste_strength
|
||||
for(var/taste_desc in taste_data)
|
||||
var/taste_strength = taste_data[taste_desc] * reagent.volume * reagent.taste_mult
|
||||
tastes[taste_desc] += taste_strength
|
||||
total_taste_strength += taste_strength
|
||||
|
||||
// None of our reagents had any flavour
|
||||
if(total_taste <= 0)
|
||||
if(total_taste_strength <= 0)
|
||||
return TEXT_NO_TASTE
|
||||
|
||||
// If we have exactly one taste, don't bother with relative strengths
|
||||
@@ -46,32 +50,33 @@
|
||||
sortTim(tastes, cmp = GLOBAL_PROC_REF(cmp_numeric_dsc), associative = TRUE)
|
||||
|
||||
// Lazylists for different taste strength categories, no need to initialize if we don't have such flavors
|
||||
var/list/strong
|
||||
var/list/mild
|
||||
var/list/hint
|
||||
var/list/strong_tastes
|
||||
var/list/mild_tastes
|
||||
var/list/weak_tastes
|
||||
|
||||
for(var/taste_desc in tastes)
|
||||
var/percent = tastes[taste_desc]/total_taste * 100
|
||||
if(percent < minimum_percent)
|
||||
continue
|
||||
var/relative_taste_percent = (tastes[taste_desc] / total_taste_strength) * 100
|
||||
|
||||
if(percent <= minimum_percent * 2)
|
||||
LAZYADD(hint, taste_desc)
|
||||
else if(percent > minimum_percent * 4)
|
||||
LAZYADD(strong, taste_desc)
|
||||
// From weakest to strongest
|
||||
if(relative_taste_percent < detection_threshold_percent)
|
||||
continue // too weak to detect
|
||||
else if(relative_taste_percent <= detection_threshold_percent * 2)
|
||||
LAZYADD(weak_tastes, taste_desc)
|
||||
else if(relative_taste_percent <= detection_threshold_percent * 4)
|
||||
LAZYADD(mild_tastes, taste_desc)
|
||||
else
|
||||
LAZYADD(mild, taste_desc)
|
||||
LAZYADD(strong_tastes, taste_desc)
|
||||
|
||||
var/list/out = list()
|
||||
var/list/taste_messages = list()
|
||||
|
||||
if(LAZYLEN(strong))
|
||||
out += "the strong flavor of [english_list(strong, TEXT_NO_TASTE)]"
|
||||
if(LAZYLEN(mild))
|
||||
if(LAZYLEN(strong_tastes))
|
||||
taste_messages += "the strong flavor of [english_list(strong_tastes, TEXT_NO_TASTE)]"
|
||||
if(LAZYLEN(mild_tastes))
|
||||
// Prefix "some " if there are strong flavors to avoid seeming like a strong flavor
|
||||
out += "[LAZYLEN(strong) ? "some " : ""][english_list(mild, TEXT_NO_TASTE)]"
|
||||
if(LAZYLEN(hint))
|
||||
out += "a hint of [english_list(hint, TEXT_NO_TASTE)]"
|
||||
taste_messages += "[LAZYLEN(strong_tastes) ? "some " : ""][english_list(mild_tastes, TEXT_NO_TASTE)]"
|
||||
if(LAZYLEN(weak_tastes))
|
||||
taste_messages += "a hint of [english_list(weak_tastes, TEXT_NO_TASTE)]"
|
||||
|
||||
return english_list(out, TEXT_NO_TASTE)
|
||||
return english_list(taste_messages, TEXT_NO_TASTE)
|
||||
|
||||
#undef TEXT_NO_TASTE
|
||||
|
||||
@@ -1981,6 +1981,7 @@
|
||||
#include "code\datums\quirks\positive_quirks\freerunning.dm"
|
||||
#include "code\datums\quirks\positive_quirks\friendly.dm"
|
||||
#include "code\datums\quirks\positive_quirks\jolly.dm"
|
||||
#include "code\datums\quirks\positive_quirks\keen_nose.dm"
|
||||
#include "code\datums\quirks\positive_quirks\light_step.dm"
|
||||
#include "code\datums\quirks\positive_quirks\mime_fan.dm"
|
||||
#include "code\datums\quirks\positive_quirks\musician.dm"
|
||||
|
||||
Reference in New Issue
Block a user