diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index f50c4742910..c95f6a57d8a 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -436,6 +436,15 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Trait granted by [/obj/item/clothing/head/helmet/space/hardsuit/berserker] #define BERSERK_TRAIT "berserk_trait" +/** +* Trait granted by [/mob/living/carbon/Initialize] and +* granted/removed by [/obj/item/organ/tongue] +* Used for ensuring that carbons without tongues cannot taste anything +* so it is added in Initialize, and then removed when a tongue is inserted +* and readded when a tongue is removed. +*/ +#define NO_TONGUE_TRAIT "no_tongue_trait" + /// Trait granted by [/mob/living/silicon/robot] /// Traits applied to a silicon mob by their module. #define MODULE_TRAIT "module_trait" diff --git a/code/game/objects/items/taster.dm b/code/game/objects/items/taster.dm index 3828beb9211..29fa6de03cb 100644 --- a/code/game/objects/items/taster.dm +++ b/code/game/objects/items/taster.dm @@ -6,8 +6,6 @@ w_class = WEIGHT_CLASS_TINY - speech_span = null - var/taste_sensitivity = 15 /obj/item/taster/afterattack(atom/O, mob/user, proximity) @@ -15,6 +13,10 @@ if(!proximity) return - if(O.reagents) - var/message = O.reagents.generate_taste_message(taste_sensitivity) + if(!O.reagents) + to_chat(user, "[src] cannot taste [O], since [O.p_they()] [O.p_have()] have no reagents.") + else if(O.reagents.total_volume == 0) + to_chat(user, "[src] cannot taste [O], since [O.p_they()] [O.p_are()] empty.") + else + var/message = O.reagents.generate_taste_message(user, taste_sensitivity) to_chat(user, "[src] tastes [message] in [O].") diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 05b5a2fb3db..21cfc8a0d00 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -3,6 +3,10 @@ create_reagents(1000) assign_bodypart_ownership() update_body_parts() //to update the carbon's new bodyparts appearance + + // Carbons cannot taste anything without a tongue; the tongue organ removes this on Insert + ADD_TRAIT(src, TRAIT_AGEUSIA, NO_TONGUE_TRAIT) + GLOB.carbon_list += src if(!mapload) //I don't want no gas leaks on my space ruin you hear? RegisterSignal(src, COMSIG_LIVING_DEATH, .proc/attach_rot) diff --git a/code/modules/mob/living/taste.dm b/code/modules/mob/living/taste.dm index 014929f6eee..4c057e729c0 100644 --- a/code/modules/mob/living/taste.dm +++ b/code/modules/mob/living/taste.dm @@ -4,21 +4,32 @@ var/last_taste_time var/last_taste_text +/** + * Gets taste sensitivity of given mob + * + * This is used in calculating what flavours the mob can pick up, + * with a lower number being able to pick up more distinct flavours. + */ /mob/living/proc/get_taste_sensitivity() return DEFAULT_TASTE_SENSITIVITY /mob/living/carbon/get_taste_sensitivity() var/obj/item/organ/tongue/tongue = getorganslot(ORGAN_SLOT_TONGUE) - if(istype(tongue) && !HAS_TRAIT(src, TRAIT_AGEUSIA)) + if(istype(tongue)) . = tongue.taste_sensitivity else - . = 101 // can't taste anything without a tongue + // carbons without tongues normally have TRAIT_AGEUSIA but sensible fallback + . = DEFAULT_TASTE_SENSITIVITY // non destructively tastes a reagent container /mob/living/proc/taste(datum/reagents/from) + if(HAS_TRAIT(src, TRAIT_AGEUSIA)) + return + + if(last_taste_time + 50 < world.time) var/taste_sensitivity = get_taste_sensitivity() - var/text_output = from.generate_taste_message(taste_sensitivity,src) + var/text_output = from.generate_taste_message(src, taste_sensitivity) // We dont want to spam the same message over and over again at the // person. Give it a bit of a buffer. if(hallucination > 50 && prob(25)) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 07bb01cf169..ce2c1b98532 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -946,9 +946,10 @@ * Returns what this holder's reagents taste like * * Arguments: + * * 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. */ -/datum/reagents/proc/generate_taste_message(minimum_percent=15,mob/living/taster) +/datum/reagents/proc/generate_taste_message(mob/living/taster, minimum_percent) var/list/out = list() var/list/tastes = list() //descriptor = strength if(minimum_percent <= 100) diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index 10563177449..455c3d082df 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -8,6 +8,10 @@ attack_verb_simple = list("lick", "slobber", "slap", "french", "tongue") var/list/languages_possible var/say_mod = null + + /// Whether the owner of this tongue can taste anything. Being set to FALSE will mean no taste feedback will be provided. + var/sense_of_taste = TRUE + var/taste_sensitivity = 15 // lower is more sensitive. var/modifies_speech = FALSE var/static/list/languages_possible_base = typecacheof(list( @@ -43,12 +47,24 @@ RegisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech) M.UnregisterSignal(M, COMSIG_MOB_SAY) + /* This could be slightly simpler, by making the removal of the + * NO_TONGUE_TRAIT conditional on the tongue's `sense_of_taste`, but + * then you can distinguish between ageusia from no tongue, and + * ageusia from having a non-tasting tongue. + */ + REMOVE_TRAIT(M, TRAIT_AGEUSIA, NO_TONGUE_TRAIT) + if(!sense_of_taste) + ADD_TRAIT(M, TRAIT_AGEUSIA, ORGAN_TRAIT) + /obj/item/organ/tongue/Remove(mob/living/carbon/M, special = 0) ..() if(say_mod && M.dna && M.dna.species) M.dna.species.say_mod = initial(M.dna.species.say_mod) UnregisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech) M.RegisterSignal(M, COMSIG_MOB_SAY, /mob/living/carbon/.proc/handle_tongueless_speech) + REMOVE_TRAIT(M, TRAIT_AGEUSIA, ORGAN_TRAIT) + // Carbons by default start with NO_TONGUE_TRAIT caused TRAIT_AGEUSIA + ADD_TRAIT(M, TRAIT_AGEUSIA, NO_TONGUE_TRAIT) /obj/item/organ/tongue/could_speak_language(language) return is_type_in_typecache(language, languages_possible) @@ -120,7 +136,7 @@ desc = "A mysterious structure that allows for instant communication between users. Pretty impressive until you need to eat something." icon_state = "tongueayylmao" say_mod = "gibbers" - taste_sensitivity = 101 // ayys cannot taste anything. + sense_of_taste = FALSE modifies_speech = TRUE var/mothership @@ -218,7 +234,7 @@ say_mod = "rattles" attack_verb_continuous = list("bites", "chatters", "chomps", "enamelles", "bones") attack_verb_simple = list("bite", "chatter", "chomp", "enamel", "bone") - taste_sensitivity = 101 // skeletons cannot taste anything + sense_of_taste = FALSE modifies_speech = TRUE var/chattering = FALSE var/phomeme_type = "sans" @@ -279,7 +295,9 @@ speech_args[SPEECH_SPANS] |= SPAN_ROBOT /obj/item/organ/tongue/snail - name = "snailtongue" + name = "radula" + color = "#96DB00" // TODO proper sprite, rather than recoloured pink tongue + desc = "A minutely toothed, chitious ribbon, which as a side effect, makes all snails talk IINNCCRREEDDIIBBLLYY SSLLOOWWLLYY." modifies_speech = TRUE /obj/item/organ/tongue/snail/handle_speech(datum/source, list/speech_args) @@ -299,7 +317,7 @@ say_mod = "crackles" attack_verb_continuous = list("shocks", "jolts", "zaps") attack_verb_simple = list("shock", "jolt", "zap") - taste_sensitivity = 101 // Not a tongue, they can't taste shit + sense_of_taste = FALSE var/static/list/languages_possible_ethereal = typecacheof(list( /datum/language/common, /datum/language/draconic,