diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 709117de8c..57e1e4bb6a 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -158,7 +158,8 @@
using.alpha = ui_alpha
src.adding += using
- inv_box = new /obj/screen/inventory()
+ inv_box = new /obj/screen/inventory/hand()
+ inv_box.hud = src
inv_box.name = "r_hand"
inv_box.icon = ui_style
inv_box.icon_state = "r_hand_inactive"
@@ -173,7 +174,8 @@
src.r_hand_hud_object = inv_box
src.adding += inv_box
- inv_box = new /obj/screen/inventory()
+ inv_box = new /obj/screen/inventory/hand()
+ inv_box.hud = src
inv_box.name = "l_hand"
inv_box.icon = ui_style
inv_box.icon_state = "l_hand_inactive"
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index d899f62049..3f6758c6ad 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -12,6 +12,7 @@
layer = 20.0
unacidable = 1
var/obj/master = null //A reference to the object in the slot. Grabs or items, generally.
+ var/datum/hud/hud = null // A reference to the owner HUD, if any.
/obj/screen/Destroy()
master = null
@@ -507,3 +508,20 @@
usr.update_inv_l_hand(0)
usr.update_inv_r_hand(0)
return 1
+
+// Hand slots are special to handle the handcuffs overlay
+/obj/screen/inventory/hand
+ var/image/handcuff_overlay
+
+/obj/screen/inventory/hand/update_icon()
+ ..()
+ if(!hud)
+ return
+ if(!handcuff_overlay)
+ var/state = (hud.l_hand_hud_object == src) ? "l_hand_hud_handcuffs" : "r_hand_hud_handcuffs"
+ handcuff_overlay = image("icon"='icons/mob/screen_gen.dmi', "icon_state"=state)
+ overlays.Cut()
+ if(hud.mymob && iscarbon(hud.mymob))
+ var/mob/living/carbon/C = hud.mymob
+ if(C.handcuffed)
+ overlays |= handcuff_overlay
diff --git a/code/game/objects/items/weapons/tanks/tank_types.dm b/code/game/objects/items/weapons/tanks/tank_types.dm
index 10482348c5..39f5e19693 100644
--- a/code/game/objects/items/weapons/tanks/tank_types.dm
+++ b/code/game/objects/items/weapons/tanks/tank_types.dm
@@ -101,9 +101,10 @@
return
/obj/item/weapon/tank/vox //Can't be a child of phoron or the gas amount gets screwey.
- name = "phoron tank" //VOREStation edit
- desc = "Contains dangerous phoron. Do not inhale. Warning: extremely flammable." //VOREStation Edit
- icon_state = "oxygen_fr"
+ name = "phoron tank"
+ desc = "Contains dangerous phoron. Do not inhale. Warning: extremely flammable."
+ icon_state = "phoron_vox"
+ item_state = "oxygen_fr"
gauge_icon = null
flags = CONDUCT
distribute_pressure = ONE_ATMOSPHERE*O2STANDARD
@@ -112,7 +113,7 @@
/obj/item/weapon/tank/vox/New()
..()
- air_contents.adjust_gas("phoron", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) //VOREStation Edit
+ air_contents.adjust_gas("phoron", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
return
/*
diff --git a/code/modules/client/preference_setup/global/setting_datums.dm b/code/modules/client/preference_setup/global/setting_datums.dm
index d446a8f950..71559fed0e 100644
--- a/code/modules/client/preference_setup/global/setting_datums.dm
+++ b/code/modules/client/preference_setup/global/setting_datums.dm
@@ -126,6 +126,12 @@ var/list/_client_preferences_by_type
enabled_description = "Show"
disabled_description = "Hide"
+/datum/client_preference/check_mention
+ description ="Emphasize Name Mention"
+ key = "CHAT_MENTION"
+ enabled_description = "Emphasize"
+ disabled_description = "Normal"
+
/datum/client_preference/show_progress_bar
description ="Progress Bar"
key = "SHOW_PROGRESS"
diff --git a/code/modules/events/canister_leak.dm b/code/modules/events/canister_leak.dm
index 956d8a0940..932a819671 100644
--- a/code/modules/events/canister_leak.dm
+++ b/code/modules/events/canister_leak.dm
@@ -7,7 +7,7 @@
// List of all non-destroyed canisters on station levels
var/list/all_canisters = list()
for(var/obj/machinery/portable_atmospherics/canister/C in machines)
- if(!C.destroyed && (C.z in using_map.station_levels))
+ if(!C.destroyed && (C.z in using_map.station_levels) && C.air_contents.total_moles >= MOLES_CELLSTANDARD)
all_canisters += C
for(var/i in 1 to 10)
diff --git a/code/modules/gamemaster/actions/canister_leak.dm b/code/modules/gamemaster/actions/canister_leak.dm
index ed55c0cded..a294f95736 100644
--- a/code/modules/gamemaster/actions/canister_leak.dm
+++ b/code/modules/gamemaster/actions/canister_leak.dm
@@ -15,7 +15,7 @@
// List of all non-destroyed canisters on station levels
var/list/all_canisters = list()
for(var/obj/machinery/portable_atmospherics/canister/C in machines)
- if(!C.destroyed && (C.z in using_map.station_levels))
+ if(!C.destroyed && (C.z in using_map.station_levels) && C.air_contents.total_moles >= MOLES_CELLSTANDARD)
all_canisters += C
var/obj/machinery/portable_atmospherics/canister/C = pick(all_canisters)
log_debug("canister_leak event: Canister [C] ([C.x],[C.y],[C.z]) destroyed.")
diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm
index 15b9992375..b2748e6f06 100644
--- a/code/modules/mob/emote.dm
+++ b/code/modules/mob/emote.dm
@@ -23,6 +23,8 @@
if (message)
log_emote("[name]/[key] : [message]")
+ message = say_emphasis(message)
+
// Hearing gasp and such every five seconds is not good emotes were not global for a reason.
// Maybe some people are okay with that.
@@ -63,6 +65,8 @@
else
input = message
+ input = say_emphasis(input)
+
if(input)
log_emote("Ghost/[src.key] : [input]")
if(!invisibility) //If the ghost is made visible by admins or cult. And to see if the ghost has toggled its own visibility, as well. -Mech
diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm
index a240277d38..fe8c86619a 100644
--- a/code/modules/mob/hear_say.dm
+++ b/code/modules/mob/hear_say.dm
@@ -49,6 +49,8 @@
if(italics)
message = "[message]"
+ message = say_emphasis(message)
+
var/track = null
if(istype(src, /mob/observer/dead))
if(italics && is_preference_enabled(/datum/client_preference/ghost_radio))
@@ -66,20 +68,73 @@
else
src << "[speaker_name][alt_name] talks but you cannot hear."
else
+ var/message_to_send = null
if(language)
- on_hear_say("[speaker_name][alt_name] [track][language.format_message(message, verb)]")
+ message_to_send = "[speaker_name][alt_name] [track][language.format_message(message, verb)]"
else
- on_hear_say("[speaker_name][alt_name] [track][verb], \"[message]\"")
+ message_to_send = "[speaker_name][alt_name] [track][verb], \"[message]\""
+ if(check_mentioned(message) && is_preference_enabled(/datum/client_preference/check_mention))
+ message_to_send = "[message_to_send]"
+
+ on_hear_say(message_to_send)
+
if (speech_sound && (get_dist(speaker, src) <= world.view && src.z == speaker.z))
var/turf/source = speaker? get_turf(speaker) : get_turf(src)
src.playsound_local(source, speech_sound, sound_vol, 1)
/mob/proc/on_hear_say(var/message)
- src << message
+ to_chat(src, message)
/mob/living/silicon/on_hear_say(var/message)
var/time = say_timestamp()
- src << "[time] [message]"
+ to_chat(src, "[time] [message]")
+
+// Checks if the mob's own name is included inside message. Handles both first and last names.
+/mob/proc/check_mentioned(var/message)
+ var/list/valid_names = splittext(real_name, " ") // Should output list("John", "Doe") as an example.
+ valid_names += special_mentions()
+ for(var/name in valid_names)
+ if(findtext(message, name))
+ return TRUE
+ return FALSE
+
+// Override this if you want something besides the mob's name to count for being mentioned in check_mentioned().
+/mob/proc/special_mentions()
+ return list()
+
+/mob/living/silicon/ai/special_mentions()
+ return list("AI") // AI door!
+
+// Converts specific characters, like *, /, and _ to formatted output.
+/mob/proc/say_emphasis(var/message)
+ message = encode_html_emphasis(message, "/", "i")
+ message = encode_html_emphasis(message, "*", "b")
+ message = encode_html_emphasis(message, "_", "u")
+ return message
+
+// Replaces a character inside message with html tags. Note that html var must not include brackets.
+// Will not create an open html tag if it would not have a closing one.
+/proc/encode_html_emphasis(var/message, var/char, var/html)
+ var/i = 20 // Infinite loop safety.
+ var/pattern = "(?") - 1
+
+ // Now replace both.
+ message = replacetext(message, char, "<[html]>", first, first + 1)
+ message = replacetext(message, char, "[html]>", second + length_increase, second + length_increase + 1)
+
+ // Check again to see if we need to keep going.
+ first = re.Find(message)
+ second = re.Find(message, first + 1)
+ i--
+ if(!i)
+ CRASH("Possible infinite loop occured in encode_html_emphasis().")
+ return message
/mob/proc/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/part_c, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="")
@@ -182,11 +237,15 @@
speaker_name = "[speaker.real_name] ([speaker_name])"
track = "[speaker_name] ([ghost_follow_link(speaker, src)])"
+ message = say_emphasis(message)
+
var/formatted
if(language)
formatted = "[language.format_message_radio(message, verb)][part_c]"
else
formatted = "[verb], \"[message]\"[part_c]"
+
+
if((sdisabilities & DEAF) || ear_deaf)
if(prob(20))
src << "You feel your headset vibrate but can hear nothing from it!"
@@ -197,18 +256,30 @@
return "\[[stationtime2text()]\]"
/mob/proc/on_hear_radio(part_a, speaker_name, track, part_b, formatted)
- src << "[part_a][speaker_name][part_b][formatted]"
+ var/final_message = "[part_a][speaker_name][part_b][formatted]"
+ if(check_mentioned(formatted) && is_preference_enabled(/datum/client_preference/check_mention))
+ final_message = "[final_message]"
+ to_chat(src, final_message)
/mob/observer/dead/on_hear_radio(part_a, speaker_name, track, part_b, formatted)
- src << "[part_a][track][part_b][formatted]"
+ var/final_message = "[part_a][track][part_b][formatted]"
+ if(check_mentioned(formatted) && is_preference_enabled(/datum/client_preference/check_mention))
+ final_message = "[final_message]"
+ to_chat(src, final_message)
/mob/living/silicon/on_hear_radio(part_a, speaker_name, track, part_b, formatted)
var/time = say_timestamp()
- src << "[time][part_a][speaker_name][part_b][formatted]"
+ var/final_message = "[part_a][speaker_name][part_b][formatted]"
+ if(check_mentioned(formatted) && is_preference_enabled(/datum/client_preference/check_mention))
+ final_message = "[time][final_message]"
+ to_chat(src, final_message)
/mob/living/silicon/ai/on_hear_radio(part_a, speaker_name, track, part_b, formatted)
var/time = say_timestamp()
- src << "[time][part_a][track][part_b][formatted]"
+ var/final_message = "[part_a][track][part_b][formatted]"
+ if(check_mentioned(formatted) && is_preference_enabled(/datum/client_preference/check_mention))
+ final_message = "[time][final_message]"
+ to_chat(src, final_message)
/mob/proc/hear_signlang(var/message, var/verb = "gestures", var/datum/language/language, var/mob/speaker = null)
if(!client)
diff --git a/code/modules/mob/language/synthetic.dm b/code/modules/mob/language/synthetic.dm
index dbf91343f1..2a2ddb0ff9 100644
--- a/code/modules/mob/language/synthetic.dm
+++ b/code/modules/mob/language/synthetic.dm
@@ -17,15 +17,19 @@
if (!message)
return
+ message = speaker.say_emphasis(message)
+
var/message_start = "[name], [speaker.name]"
var/message_body = "[speaker.say_quote(message)], \"[message]\""
for (var/mob/M in dead_mob_list)
if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain)) //No meta-evesdropping
- M.show_message("[message_start] ([ghost_follow_link(speaker, M)]) [message_body]", 2)
+ var/message_to_send = "[message_start] ([ghost_follow_link(speaker, M)]) [message_body]"
+ if(M.check_mentioned(message) && M.is_preference_enabled(/datum/client_preference/check_mention))
+ message_to_send = "[message_to_send]"
+ M.show_message(message_to_send, 2)
for (var/mob/living/S in living_mob_list)
-
if(drone_only && !istype(S,/mob/living/silicon/robot/drone))
continue
else if(istype(S , /mob/living/silicon/ai))
@@ -33,7 +37,10 @@
else if (!S.binarycheck())
continue
- S.show_message("[message_start] [message_body]", 2)
+ var/message_to_send = "[message_start] [message_body]"
+ if(S.check_mentioned(message) && S.is_preference_enabled(/datum/client_preference/check_mention))
+ message_to_send = "[message_to_send]"
+ S.show_message(message_to_send, 2)
var/list/listening = hearers(1, src)
listening -= src
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 0c4f178fc5..818224393c 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -910,6 +910,11 @@ var/global/list/damage_icon_parts = list()
if(hud_used)
hud_used.hidden_inventory_update() //Updates the screenloc of the items on the 'other' inventory bar
+//update whether handcuffs appears on our hud.
+/mob/living/carbon/proc/update_hud_handcuffed()
+ if(hud_used && hud_used.l_hand_hud_object && hud_used.r_hand_hud_object)
+ hud_used.l_hand_hud_object.update_icon()
+ hud_used.r_hand_hud_object.update_icon()
/mob/living/carbon/human/update_inv_handcuffed(var/update_icons=1)
if(handcuffed)
@@ -928,6 +933,8 @@ var/global/list/damage_icon_parts = list()
else
overlays_standing[HANDCUFF_LAYER] = null
+
+ update_hud_handcuffed()
if(update_icons) update_icons()
/mob/living/carbon/human/update_inv_legcuffed(var/update_icons=1)
diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm
index f7aaa52f78..0a029cf316 100644
--- a/code/modules/mob/say.dm
+++ b/code/modules/mob/say.dm
@@ -44,6 +44,8 @@
usr << "You have deadchat muted."
return
+ message = say_emphasis(message)
+
say_dead_direct("[pick("complains","moans","whines","laments","blubbers")], \"[message]\"", src)
/mob/proc/say_understands(var/mob/other,var/datum/language/speaking = null)
diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm
index f46326a53e..a1512b11c6 100644
--- a/code/modules/organs/robolimbs.dm
+++ b/code/modules/organs/robolimbs.dm
@@ -112,6 +112,13 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\
unavailable_to_build = 1
parts = list(BP_HEAD)
+/datum/robolimb/morpheus_alt2
+ company = "Morpheus - Skeleton Crew"
+ desc = "This limb is simple and functional; it's basically just a case for a brain."
+ icon = 'icons/mob/human_races/cyberlimbs/morpheus/morpheus_alt2.dmi'
+ unavailable_to_build = 1
+ parts = list(BP_HEAD)
+
/datum/robolimb/veymed
company = "Vey-Med"
desc = "This high quality limb is nearly indistinguishable from an organic one."
diff --git a/code/modules/organs/subtypes/machine.dm b/code/modules/organs/subtypes/machine.dm
index aa62519381..4b0ac91cdc 100644
--- a/code/modules/organs/subtypes/machine.dm
+++ b/code/modules/organs/subtypes/machine.dm
@@ -1,7 +1,6 @@
/obj/item/organ/internal/cell
name = "microbattery"
desc = "A small, powerful cell for use in fully prosthetic bodies."
- icon = 'icons/obj/power.dmi'
icon_state = "scell"
organ_tag = "cell"
parent_organ = BP_TORSO
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
index d31e7f7b36..ac52b72768 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
@@ -699,6 +699,71 @@
cup_name = "cup of iced tea"
cup_desc = "No relation to a certain rap artist/ actor."
+/datum/reagent/drink/tea/minttea
+ name = "Mint Tea"
+ id = "minttea"
+ description = "A tasty mixture of mint and tea. It's apparently good for you!"
+ color = "#A8442C"
+ taste_description = "black tea with tones of mint"
+
+ glass_name = "mint tea"
+ glass_desc = "A tasty mixture of mint and tea. It's apparently good for you!"
+
+ cup_name = "cup of mint tea"
+ cup_desc = "A tasty mixture of mint and tea. It's apparently good for you!"
+
+/datum/reagent/drink/tea/lemontea
+ name = "Lemon Tea"
+ id = "lemontea"
+ description = "A tasty mixture of lemon and tea. It's apparently good for you!"
+ color = "#FC6A00"
+ taste_description = "black tea with tones of lemon"
+
+ glass_name = "lemon tea"
+ glass_desc = "A tasty mixture of lemon and tea. It's apparently good for you!"
+
+ cup_name = "cup of lemon tea"
+ cup_desc = "A tasty mixture of lemon and tea. It's apparently good for you!"
+
+/datum/reagent/drink/tea/limetea
+ name = "Lime Tea"
+ id = "limetea"
+ description = "A tasty mixture of lime and tea. It's apparently good for you!"
+ color = "#DE4300"
+ taste_description = "black tea with tones of lime"
+
+ glass_name = "lime tea"
+ glass_desc = "A tasty mixture of lime and tea. It's apparently good for you!"
+
+ cup_name = "cup of berry tea"
+ cup_desc = "A tasty mixture of lime and tea. It's apparently good for you!"
+
+/datum/reagent/drink/tea/orangetea
+ name = "Orange Tea"
+ id = "orangetea"
+ description = "A tasty mixture of orange and tea. It's apparently good for you!"
+ color = "#FB4F06"
+ taste_description = "black tea with tones of orange"
+
+ glass_name = "orange tea"
+ glass_desc = "A tasty mixture of orange and tea. It's apparently good for you!"
+
+ cup_name = "cup of orange tea"
+ cup_desc = "A tasty mixture of orange and tea. It's apparently good for you!"
+
+/datum/reagent/drink/tea/berrytea
+ name = "Berry Tea"
+ id = "berrytea"
+ description = "A tasty mixture of berries and tea. It's apparently good for you!"
+ color = "#A60735"
+ taste_description = "black tea with tones of berries"
+
+ glass_name = "berry tea"
+ glass_desc = "A tasty mixture of berries and tea. It's apparently good for you!"
+
+ cup_name = "cup of berry tea"
+ cup_desc = "A tasty mixture of berries and tea. It's apparently good for you!"
+
/datum/reagent/drink/coffee
name = "Coffee"
id = "coffee"
@@ -2165,3 +2230,4 @@
glass_name = "special blend whiskey"
glass_desc = "Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything."
+
diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm
index 4d7d13e5b3..d63cacfb94 100644
--- a/code/modules/reagents/Chemistry-Recipes.dm
+++ b/code/modules/reagents/Chemistry-Recipes.dm
@@ -1782,4 +1782,39 @@
id = "arnold_palmer"
result = "arnold_palmer"
required_reagents = list("icetea" = 1, "lemonade" = 1)
- result_amount = 2
\ No newline at end of file
+ result_amount = 2
+
+/datum/chemical_reaction/minttea
+ name = "Mint Tea"
+ id = "minttea"
+ result = "minttea"
+ required_reagents = list("tea" = 5, "mint" = 1)
+ result_amount = 6
+
+/datum/chemical_reaction/lemontea
+ name = "Lemon Tea"
+ id = "lemontea"
+ result = "lemontea"
+ required_reagents = list("tea" = 5, "lemonjuice" = 1)
+ result_amount = 6
+
+/datum/chemical_reaction/limetea
+ name = "Lime Tea"
+ id = "limetea"
+ result = "limetea"
+ required_reagents = list("tea" = 5, "limejuice" = 1)
+ result_amount = 6
+
+/datum/chemical_reaction/limetea
+ name = "Orange Tea"
+ id = "orangetea"
+ result = "orangetea"
+ required_reagents = list("tea" = 5, "orangejuice" = 1)
+ result_amount = 6
+
+/datum/chemical_reaction/berrytea
+ name = "Berry Tea"
+ id = "berrytea"
+ result = "berrytea"
+ required_reagents = list("tea" = 5, "berryjuice" = 1)
+ result_amount = 6
\ No newline at end of file
diff --git a/code/modules/reagents/dispenser/dispenser2_energy.dm b/code/modules/reagents/dispenser/dispenser2_energy.dm
index 2ab4c5641d..d29ed6bbe9 100644
--- a/code/modules/reagents/dispenser/dispenser2_energy.dm
+++ b/code/modules/reagents/dispenser/dispenser2_energy.dm
@@ -57,5 +57,6 @@
/obj/machinery/chemical_dispenser/bar_coffee
dispense_reagents = list(
- "coffee", "cafe_latte", "soy_latte", "hot_coco", "milk", "cream", "tea", "ice"
+ "coffee", "cafe_latte", "soy_latte", "hot_coco", "milk", "cream", "tea", "ice",
+ "orangejuice", "lemonjuice", "limejuice", "berryjuice", "mint"
)
\ No newline at end of file
diff --git a/icons/mob/human_races/cyberlimbs/morpheus/morpheus_alt2.dmi b/icons/mob/human_races/cyberlimbs/morpheus/morpheus_alt2.dmi
new file mode 100644
index 0000000000..6bee009356
Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/morpheus/morpheus_alt2.dmi differ
diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi
index cf74d73796..2071c634d1 100644
Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.dmi differ
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index f8aede48f2..b2ff3108ea 100644
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/icons/obj/tank.dmi b/icons/obj/tank.dmi
index 6c4d65b76e..33cde91a1d 100644
Binary files a/icons/obj/tank.dmi and b/icons/obj/tank.dmi differ