diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm
index d2fd9e8f3ef..167750edc17 100644
--- a/code/__DEFINES/obj_flags.dm
+++ b/code/__DEFINES/obj_flags.dm
@@ -43,8 +43,9 @@
#define SNUG_FIT (1<<9) //! prevents hat throwing from knocking this hat off
#define EFFECT_HAT (1<<10) //! For hats with an effect that shouldn't get knocked off ie finfoil
#define SCAN_REAGENTS (1<<11) //! Allows helmets and glasses to scan reagents.
-#define MASKEXTENDRANGE (1<<12) //! For masks, allows you to breathe from internals on adjecent tiles
-#define NOTCONSUMABLE (1<<13) //! Moths cannot eat clothing with that flag
+#define SCAN_BOOZEPOWER (1<<12) //! Allows helmets and glasses to scan reagents.
+#define MASKEXTENDRANGE (1<<13) //! For masks, allows you to breathe from internals on adjecent tiles
+#define NOTCONSUMABLE (1<<14) //! Moths cannot eat clothing with that flag
/// Flags for the organ_flags var on /obj/item/organ
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 0f7d205b5f5..cec2a4c93e4 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -233,6 +233,19 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_DIGINVIS "digital_invis" //note: diginvis grants digitalcamo, but carbons can tell if you have the digicamo trait on examine
#define TRAIT_NICE_SHOT "nice_shot" //hnnnnnnnggggg..... you're pretty good....
#define TRAIT_ALWAYS_STUBS "always_stubs_toe" //you will always stub your toe on tables, even if you're wearing shoes
+<<<<<<< HEAD
+=======
+#define TRAIT_NAIVE "naive" //All dead people will appear as sleeping.
+#define TRAIT_DROPS_ITEMS_ON_DEATH "drops_items_on_death" //used for battle royale
+#define TRAIT_DRINKSBLOOD "drinks_blood"
+#define TRAIT_SOMMELIER "sommelier" // shows different booze power flavor texts
+#define TRAIT_BARMASTER "bar_master" // always can identify reagents
+
+// You can stare into the abyss, but it does not stare back.
+// You're immune to the hallucination effect of the supermatter, either
+// through force of will, or equipment.
+#define TRAIT_MADNESS_IMMUNE "supermatter_madness_immune"
+>>>>>>> cd0a8c0b5d... Beer goggles now can measure Booze power and expect tastes (#7320)
//non-mob traits
#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 1ebc56dccbd..a86d30fa271 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1606,3 +1606,77 @@ config_setting should be one of the following:
if(-INFINITY to 0, 11 to INFINITY)
CRASH("Can't turn invalid directions!")
return turn(input_dir, 180)
+
+/atom/proc/get_boozepower_text(booze_power, mob/living/L)
+ if(isnull(booze_power))
+ return
+
+ if(HAS_TRAIT(L, TRAIT_SOMMELIER)) // A trained sommelier will have different identifying flavour
+ // because of float values, you need to write like `0 to 10`, `10 to 20`
+ switch(booze_power)
+ if(-INFINITY to 1)
+ . = "For children"
+ if(300 to INFINITY)
+ . = pick("Shift wrecking hammering",
+ "Get new liver after consumption",
+ "Post-consumption support groups exist",
+ "Place in Molotov instead",
+ "To stumble and slur, the will of Bacchus")
+ if(100 to 100)
+ . = "For a real man"
+ // these values must be detected first.
+
+ if(100 to 300)
+ . = "Cheated the blessing"
+ if(90 to 100)
+ . = "Get to drunk tank"
+ if(80 to 90)
+ . = "Liver pickler"
+ if(70 to 80)
+ . = "Drunkard's Challenge"
+ if(60 to 70)
+ . = "Have Shotgun ready"
+ if(50 to 60)
+ . = "3 rounds till down"
+ if(40 to 50)
+ . = "Drunkard's fixers"
+ if(30 to 40)
+ . = "Stick arounds"
+ if(20 to 30)
+ . = "Flask fillers"
+ if(10 to 20)
+ . = "Tipsy stuff"
+ if(1 to 10)
+ . = "Lightweight's dream"
+ else
+ switch(booze_power)
+ if(-INFINITY to 1)
+ . = "Safe for work"
+ if(300 to INFINITY)
+ . = "Lethal"
+ if(100 to 300)
+ . = "Deadly"
+ if(90 to 100)
+ . = "Dangerous"
+ if(80 to 90)
+ . = "Extreme"
+ if(70 to 80)
+ . = "Challenging"
+ if(60 to 70)
+ . = "Stronger"
+ if(50 to 60)
+ . = "Strong"
+ if(40 to 50)
+ . = "Average"
+ if(30 to 40)
+ . = "Less than average"
+ if(20 to 30)
+ . = "Light"
+ if(10 to 20)
+ . = "Mild"
+ if(1 to 10)
+ . = "Delightfully mild"
+
+ if(!.)
+ . = "not measurable. Ask the space god for what's wrong with this drink."
+ CRASH("not valid booze power value is detected: [booze_power]")
diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm
index da5481ffe41..baa73a42dee 100644
--- a/code/_globalvars/bitfields.dm
+++ b/code/_globalvars/bitfields.dm
@@ -197,6 +197,7 @@ DEFINE_BITFIELD(clothing_flags, list(
"SNUG_FIT" = SNUG_FIT,
"EFFECT_HAT" = EFFECT_HAT,
"SCAN_REAGENTS" = SCAN_REAGENTS,
+ "SCAN_BOOZEPOWER" = SCAN_BOOZEPOWER,
))
DEFINE_BITFIELD(tesla_flags, list(
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 68458f190ea..dc3fe75484f 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -516,6 +516,7 @@
if(reagents.flags & TRANSPARENT)
. += "It contains:"
if(length(reagents.reagent_list))
+ //-------- Reagent checks ---------
if(user.can_see_reagents()) //Show each individual reagent
for(var/datum/reagent/R in reagents.reagent_list)
. += "[R.volume] units of [R.name]"
@@ -524,6 +525,25 @@
for(var/datum/reagent/R in reagents.reagent_list)
total_volume += R.volume
. += "[total_volume] units of various reagents"
+ //-------- Beer goggles ---------
+ if(user.can_see_boozepower())
+ var/total_boozepower = 0
+ var/list/taste_list = list()
+
+ // calculates the total booze power from all 'ethanol' reagents
+ for(var/datum/reagent/consumable/ethanol/B in reagents.reagent_list)
+ total_boozepower += B.volume * max(B.boozepwr, 0) // minus booze power is reversed to light drinkers, but is actually 0 to normal drinkers.
+
+ // gets taste results from all reagents
+ for(var/datum/reagent/R in reagents.reagent_list)
+ if(istype(R, /datum/reagent/consumable/ethanol/fruit_wine) && !(user.stat == DEAD) && !(HAS_TRAIT(src, TRAIT_BARMASTER)) ) // taste of fruit wine is mysterious, but can be known by ghosts/some special bar master trait holders
+ taste_list += "
- unexplored taste of the winery (from [R.name])"
+ else
+ taste_list += "
- [R.taste_description] (from [R.name])"
+ if(reagents.total_volume)
+ . += "Booze Power: total [total_boozepower], average [round(total_boozepower/reagents.total_volume, 0.1)] ([get_boozepower_text(total_boozepower/reagents.total_volume, user)])"
+ . += "It would taste like: [english_list(taste_list, comma_text="", and_text="")]."
+ //-------------------------------
else
. += "Nothing."
else if(reagents.flags & AMOUNT_VISIBLE)
diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm
index 9a569fcadc7..ed5387747f4 100644
--- a/code/modules/awaymissions/corpse.dm
+++ b/code/modules/awaymissions/corpse.dm
@@ -411,6 +411,14 @@
glasses = /obj/item/clothing/glasses/sunglasses/advanced/reagent
id = /obj/item/card/id
+/datum/outfit/spacebartender/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
+ ..()
+
+ if(visualsOnly)
+ return
+
+ ADD_TRAIT(H, TRAIT_SOMMELIER, ROUNDSTART_TRAIT)
+
/obj/effect/mob_spawn/human/beach
outfit = /datum/outfit/beachbum
diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm
index 87eb92d5cf7..6fe0e99cc5b 100644
--- a/code/modules/clothing/glasses/_glasses.dm
+++ b/code/modules/clothing/glasses/_glasses.dm
@@ -229,7 +229,7 @@
/obj/item/clothing/glasses/sunglasses/advanced/reagent
name = "beer goggles"
desc = "A pair of sunglasses outfitted with apparatus to scan reagents, as well as providing an innate understanding of liquid viscosity while in motion. Has enhanced shielding which blocks flashes."
- clothing_flags = SCAN_REAGENTS
+ clothing_flags = SCAN_REAGENTS | SCAN_BOOZEPOWER
/obj/item/clothing/glasses/sunglasses/advanced/reagent/equipped(mob/user, slot)
. = ..()
@@ -452,7 +452,7 @@
item_state = "godeye"
vision_flags = SEE_TURFS|SEE_MOBS|SEE_OBJS
darkness_view = 8
- clothing_flags = SCAN_REAGENTS
+ clothing_flags = SCAN_REAGENTS | SCAN_BOOZEPOWER
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
resistance_flags = LAVA_PROOF | FIRE_PROOF
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index f6e5194aacc..ca0b41c7908 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -299,7 +299,7 @@
darkness_view = 8
flash_protect = 2
vision_correction = 1
- clothing_flags = SCAN_REAGENTS
+ clothing_flags = SCAN_REAGENTS | SCAN_BOOZEPOWER
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
hud_type = list(DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC_ADVANCED, DATA_HUD_SECURITY_ADVANCED)
resistance_flags = INDESTRUCTIBLE
diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm
index 572042bc514..34d833b883d 100644
--- a/code/modules/jobs/job_types/bartender.dm
+++ b/code/modules/jobs/job_types/bartender.dm
@@ -36,3 +36,11 @@
backpack_contents = list(/obj/item/storage/box/beanbag=1)
shoes = /obj/item/clothing/shoes/laceup
+
+/datum/outfit/job/bartender/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
+ ..()
+
+ if(visualsOnly)
+ return
+
+ ADD_TRAIT(H, TRAIT_SOMMELIER, ROUNDSTART_TRAIT)
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index 01ab15927b1..196e1d9928a 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -191,3 +191,14 @@
return TRUE
if(isclothing(wear_mask) && (wear_mask.clothing_flags & SCAN_REAGENTS))
return TRUE
+
+/mob/living/carbon/human/can_see_boozepower()
+ . = ..()
+ if(.)
+ return
+ if(isclothing(glasses) && (glasses.clothing_flags & SCAN_BOOZEPOWER))
+ return TRUE
+ if(isclothing(head) && (head.clothing_flags & SCAN_BOOZEPOWER))
+ return TRUE
+ if(isclothing(wear_mask) && (wear_mask.clothing_flags & SCAN_BOOZEPOWER))
+ return TRUE
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 947cdcb8061..21ce9a559ca 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -613,4 +613,19 @@
//Can the mob see reagents inside of containers?
/mob/proc/can_see_reagents()
- return stat == DEAD || has_unlimited_silicon_privilege //Dead guys and silicons can always see reagents
+ . = FALSE
+ if(stat == DEAD) // Dead guys and silicons can always see reagents
+ return TRUE
+ else if(has_unlimited_silicon_privilege)
+ return TRUE
+ else if(HAS_TRAIT(src, TRAIT_BARMASTER)) // If they're a bar master, they know what reagents are at a glance
+ return TRUE
+
+/mob/proc/can_see_boozepower() // same rule above
+ . = FALSE
+ if(stat == DEAD)
+ return TRUE
+ else if(has_unlimited_silicon_privilege)
+ return TRUE
+ else if(HAS_TRAIT(src, TRAIT_BARMASTER))
+ return TRUE
diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm
index d198868f905..0f2f3e04f34 100644
--- a/code/modules/shuttle/special.dm
+++ b/code/modules/shuttle/special.dm
@@ -147,6 +147,9 @@
/mob/living/simple_animal/drone/snowflake/bardrone/Initialize()
. = ..()
access_card.access |= ACCESS_CENT_BAR
+ ADD_TRAIT(src, TRAIT_BARMASTER, ROUNDSTART_TRAIT)
+ ADD_TRAIT(src, TRAIT_SOMMELIER, ROUNDSTART_TRAIT)
+
/mob/living/simple_animal/hostile/alien/maid/barmaid
gold_core_spawnable = NO_SPAWN
@@ -166,6 +169,8 @@
access_card.access = C.get_access()
access_card.access |= ACCESS_CENT_BAR
ADD_TRAIT(access_card, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
+ ADD_TRAIT(src, TRAIT_BARMASTER, ROUNDSTART_TRAIT)
+ ADD_TRAIT(src, TRAIT_SOMMELIER, ROUNDSTART_TRAIT)
/mob/living/simple_animal/hostile/alien/maid/barmaid/Destroy()
qdel(access_card)