diff --git a/beestation.dme b/beestation.dme index 5b300777e55a9..c0fa325b7febb 100644 --- a/beestation.dme +++ b/beestation.dme @@ -2585,6 +2585,7 @@ #include "code\modules\elevator\elevator_interface.dm" #include "code\modules\elevator\elevator_segment.dm" #include "code\modules\emoji\emoji_parse.dm" +#include "code\modules\emote_panel\emote_panel.dm" #include "code\modules\error_handler\error_handler.dm" #include "code\modules\error_handler\error_viewer.dm" #include "code\modules\events\_event.dm" diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm index dbd4f1aefcf54..67b47015d3249 100644 --- a/code/__DEFINES/say.dm +++ b/code/__DEFINES/say.dm @@ -107,11 +107,23 @@ //Used in visible_message_flags, audible_message_flags and message_mods #define CHATMESSAGE_EMOTE "emotemessage" +/// By default, self_message will respect the visual / audible component of the message. +/// Meaning that if the message is visual, and sourced from a blind mob, they will not see it. +/// This flag skips that behavior, and will always show the self message to the mob. +#define ALWAYS_SHOW_SELF_MESSAGE "showselfmessage" + ///How far away blind people can see visible messages from #define BLIND_TEXT_DIST 2 -// Emote flags - +// Bitflags for emotes, used in var/emote_type of the emote datum +/// Is the emote audible #define EMOTE_AUDIBLE (1<<0) -#define EMOTE_ANIMATED (1<<1) +/// Is the emote visible +#define EMOTE_VISIBLE (1<<1) +/// Is it an emote that should be shown regardless of blindness/deafness +#define EMOTE_IMPORTANT (1<<2) +/// Emote only prints to runechat, not to the chat window +#define EMOTE_RUNECHAT (1<<3) +// Animated emote bitflag +#define EMOTE_ANIMATED (1<<4) diff --git a/code/__DEFINES/species.dm b/code/__DEFINES/species.dm index 1bd7b69f2f158..b743ca3356bb6 100644 --- a/code/__DEFINES/species.dm +++ b/code/__DEFINES/species.dm @@ -112,12 +112,16 @@ // Sounds used by species for "nasal/lungs" emotes - the DEFAULT being used mainly by humans, lizards, and ethereals becase biology idk #define SPECIES_DEFAULT_COUGH_SOUND(user) user.gender == FEMALE ? pick(\ - 'sound/emotes/female/female_cough_1.ogg',\ - 'sound/emotes/female/female_cough_2.ogg',\ - 'sound/emotes/female/female_cough_3.ogg') : pick(\ - 'sound/emotes/male/male_cough_1.ogg',\ - 'sound/emotes/male/male_cough_2.ogg',\ - 'sound/emotes/male/male_cough_3.ogg') + 'sound/emotes/female/female_cough_1.ogg',\ + 'sound/emotes/female/female_cough_2.ogg',\ + 'sound/emotes/female/female_cough_3.ogg',\ + 'sound/emotes/female/female_cough_4.ogg',\ + 'sound/emotes/female/female_cough_5.ogg',\ + 'sound/emotes/female/female_cough_6.ogg',\ + 'sound/emotes/female/female_cough_7.ogg') : pick(\ + 'sound/emotes/male/male_cough_1.ogg',\ + 'sound/emotes/male/male_cough_2.ogg',\ + 'sound/emotes/male/male_cough_3.ogg') #define SPECIES_DEFAULT_GASP_SOUND(user) user.gender == FEMALE ? pick(\ 'sound/emotes/female/gasp_f1.ogg',\ 'sound/emotes/female/gasp_f2.ogg',\ @@ -132,5 +136,15 @@ 'sound/emotes/male/gasp_m5.ogg',\ 'sound/emotes/male/gasp_m6.ogg') #define SPECIES_DEFAULT_SIGH_SOUND(user) user.gender == FEMALE ? 'sound/emotes/female/female_sigh.ogg' : 'sound/emotes/male/male_sigh.ogg' -#define SPECIES_DEFAULT_SNEEZE_SOUND(user) user.gender == FEMALE ? 'sound/emotes/female/female_sneeze.ogg' : 'sound/emotes/male/male_sneeze.ogg' +#define SPECIES_DEFAULT_SNEEZE_SOUND(user) user.gender == FEMALE ? pick(\ + 'sound/emotes/female/female_sneeze1.ogg',\ + 'sound/emotes/female/female_sneeze2.ogg') : pick(\ + 'sound/emotes/male/male_sneeze1.ogg',\ + 'sound/emotes/male/male_sneeze2.ogg') #define SPECIES_DEFAULT_SNIFF_SOUND(user) user.gender == FEMALE ? 'sound/emotes/female/female_sniff.ogg' : 'sound/emotes/male/male_sniff.ogg' +#define SPECIES_DEFAULT_GIGGLE_SOUND(user) user.gender == FEMALE ? pick(\ + 'sound/emotes/female/female_giggle_1.ogg',\ + 'sound/emotes/female/female_giggle_2.ogg') : pick(\ + 'sound/emotes/male/male_giggle_1.ogg',\ + 'sound/emotes/male/male_giggle_2.ogg',\ + 'sound/emotes/male/male_giggle_3.ogg') diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index d6e721d5ce87f..2d121bb1829d5 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -300,3 +300,10 @@ DEFINE_BITFIELD(mecha_flags, list( "IS_ENCLOSED" = IS_ENCLOSED, "HAS_LIGHTS" = HAS_LIGHTS, )) + +DEFINE_BITFIELD(emote_flags, list( + "EMOTE_AUDIBLE" = EMOTE_AUDIBLE, + "EMOTE_VISIBLE" = EMOTE_VISIBLE, + "EMOTE_IMPORTANT" = EMOTE_IMPORTANT, + "EMOTE_ANIMATED" = EMOTE_ANIMATED, +)) diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index 09e74a3e7b511..7eeed5c3d7f8d 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -1,6 +1,7 @@ /datum/emote var/key = "" //What calls the emote var/key_third_person = "" //This will also call the emote + var/name = "" // Needed for more user-friendly emote names, so emotes with keys like "aflap" will show as "flap angry". Defaulted to key. var/message = "" //Message displayed when emote is used var/message_mime = "" //Message displayed if the user is a mime var/message_alien = "" //Message displayed if the user is a grown alien @@ -12,8 +13,8 @@ var/message_insect = "" //Message to display if the user is a moth, apid or flyperson var/message_simple = "" //Message to display if the user is a simple_animal var/message_param = "" //Message to display if a param was given - /// Emote flags (EMOTE_AUDIBLE and EMOTE_ANIMATED) - var/emote_type = 0 + /// Whether the emote is visible and/or audible bitflag + var/emote_type = NONE /// Checks if the mob can use its hands before performing the emote. var/hands_use_check = FALSE var/muzzle_ignore = FALSE //Will only work if the emote is EMOTE_AUDIBLE @@ -57,7 +58,11 @@ mob_type_blacklist_typecache = typecacheof(mob_type_blacklist_typecache) mob_type_ignore_stat_typecache = typecacheof(mob_type_ignore_stat_typecache) + if(!name) + name = key + /datum/emote/proc/run_emote(mob/user, params, type_override, intentional = FALSE) + SHOULD_CALL_PARENT(TRUE) if(!can_run_emote(user, TRUE, intentional)) return FALSE @@ -88,22 +93,81 @@ var/space = should_have_space_before_emote(html_decode(msg)[1]) ? " " : "" msg = punctuate(msg) - var/dchatmsg = "[user][space][msg]" + var/is_important = emote_type & EMOTE_IMPORTANT + var/is_visual = emote_type & EMOTE_VISIBLE + var/is_audible = emote_type & EMOTE_AUDIBLE - for(var/mob/M in GLOB.dead_mob_list) - if(!M.client || isnewplayer(M)) - continue - var/T = get_turf(user) - if(M.stat == DEAD && M?.client.prefs?.read_player_preference(/datum/preference/toggle/chat_ghostsight) && !(M in viewers(T, null))) - if(user.mind || M.client.prefs?.read_player_preference(/datum/preference/toggle/chat_followghostmindless)) - M.show_message("[FOLLOW_LINK(M, user)] [dchatmsg]") - else - M.show_message("[dchatmsg]") + // Emote doesn't get printed to chat, runechat only + if(emote_type & EMOTE_RUNECHAT) + for(var/mob/viewer as anything in viewers(user)) + if(isnull(viewer.client)) + continue + if(!is_important && viewer != user && (!is_visual || !is_audible)) + if(is_audible && !viewer.can_hear()) + continue + if(is_visual && viewer.is_blind()) + continue + if(user.runechat_prefs_check(viewer, CHATMESSAGE_EMOTE)) + create_chat_message( + speaker = user, + raw_message = msg, + message_mods = list(CHATMESSAGE_EMOTE = TRUE), + ) + else if(is_important) + to_chat(viewer, "[user] [msg]") + else if(is_audible && is_visual) + viewer.show_message( + "[user] [msg]", MSG_AUDIBLE, + "You see how [user] [msg]", MSG_VISUAL, + ) + else if(is_audible) + viewer.show_message("[user] [msg]", MSG_AUDIBLE) + else if(is_visual) + viewer.show_message("[user] [msg]", MSG_VISUAL) + return TRUE // Early exit so no dchat message - if(emote_type & EMOTE_AUDIBLE) - user.audible_message(msg, audible_message_flags = list(CHATMESSAGE_EMOTE = TRUE), separation = space) + // The emote has some important information, and should always be shown to the user + else if(is_important) + for(var/mob/viewer as anything in viewers(user)) + to_chat(viewer, "[user] [msg]") + if(user.runechat_prefs_check(viewer, list(CHATMESSAGE_EMOTE = TRUE))) + create_chat_message(user, null, list(viewer), msg, null, list(CHATMESSAGE_EMOTE = TRUE)) + // Emotes has both an audible and visible component + // Prioritize audible, and provide a visible message if the user is deaf + else if(is_visual && is_audible) + user.audible_message( + message = msg, + deaf_message = "You see how [user] [msg]", + self_message = msg, + audible_message_flags = list(CHATMESSAGE_EMOTE = TRUE, ALWAYS_SHOW_SELF_MESSAGE = TRUE), + separation = space + ) + // Emote is entirely audible, no visible component + else if(is_audible) + user.audible_message( + message = msg, + self_message = msg, + audible_message_flags = list(CHATMESSAGE_EMOTE = TRUE), + separation = space + ) + // Emote is entirely visible, no audible component + else if(is_visual) + user.visible_message( + message = msg, + self_message = msg, + visible_message_flags = list(CHATMESSAGE_EMOTE = TRUE, ALWAYS_SHOW_SELF_MESSAGE = TRUE), + ) else - user.visible_message(msg, visible_message_flags = list(CHATMESSAGE_EMOTE = TRUE), separation = space) + CRASH("Emote [type] has no valid emote type set!") + + if(!isnull(user.client)) + var/dchatmsg = "[user] [msg]" + for(var/mob/ghost as anything in GLOB.dead_mob_list - viewers(get_turf(user))) + if(isnull(ghost.client) || isnewplayer(ghost)) + continue + if(!ghost?.client.prefs?.read_player_preference(/datum/preference/toggle/chat_ghostsight)) + continue + to_chat(ghost, "[FOLLOW_LINK(ghost, user)] [dchatmsg]") return TRUE /datum/emote/proc/get_sound(mob/living/user) diff --git a/code/modules/asset_cache/asset_list.dm b/code/modules/asset_cache/asset_list.dm index ad9daa916ba87..b52d4b8ba99ec 100644 --- a/code/modules/asset_cache/asset_list.dm +++ b/code/modules/asset_cache/asset_list.dm @@ -21,6 +21,7 @@ GLOBAL_LIST_EMPTY(asset_datums) /// Whether or not this asset can be cached across rounds of the same commit under the `CACHE_ASSETS` config. /// This is not a *guarantee* the asset will be cached. Not all asset subtypes respect this field, and the /// config can, of course, be disabled. + /// Disable this if your asset can change between rounds on the same exact version of the code. var/cross_round_cachable = FALSE /// Whether or not this asset should be loaded in the "early assets" SS @@ -146,6 +147,7 @@ GLOBAL_LIST_EMPTY(asset_datums) /datum/asset/spritesheet _abstract = /datum/asset/spritesheet + cross_round_cachable = TRUE var/name /// List of arguments to pass into queuedInsert /// Exists so we can queue icon insertion, mostly for stuff like preferences @@ -158,6 +160,9 @@ GLOBAL_LIST_EMPTY(asset_datums) /// If this asset should be fully loaded on new /// Defaults to false so we can process this stuff nicely var/load_immediately = FALSE + VAR_PRIVATE + // Kept in state so that the result is the same, even when the files are created, for this run + should_refresh = null /datum/asset/spritesheet/proc/should_load_immediately() #ifdef DO_NOT_DEFER_ASSETS @@ -170,12 +175,9 @@ GLOBAL_LIST_EMPTY(asset_datums) if (..()) return TRUE - // Static so that the result is the same, even when the files are created, for this run - var/static/should_refresh = null - if (isnull(should_refresh)) // `fexists` seems to always fail on static-time - should_refresh = !fexists("[ASSET_CROSS_ROUND_CACHE_DIRECTORY]/spritesheet.[name].css") + should_refresh = !fexists(css_cache_filename()) || !fexists(data_cache_filename()) return should_refresh @@ -329,8 +331,17 @@ GLOBAL_LIST_EMPTY(asset_datums) return out.Join("\n") +/datum/asset/spritesheet/proc/css_cache_filename() + return "[ASSET_CROSS_ROUND_CACHE_DIRECTORY]/spritesheet.[name].css" + +/datum/asset/spritesheet/proc/data_cache_filename() + return "[ASSET_CROSS_ROUND_CACHE_DIRECTORY]/spritesheet.[name].json" + /datum/asset/spritesheet/proc/read_from_cache() - var/replaced_css = rustg_file_read("[ASSET_CROSS_ROUND_CACHE_DIRECTORY]/spritesheet.[name].css") + return read_css_from_cache() && read_data_from_cache() + +/datum/asset/spritesheet/proc/read_css_from_cache() + var/replaced_css = file2text(css_cache_filename()) var/regex/find_background_urls = regex(@"background:url\('%(.+?)%'\)", "g") while (find_background_urls.Find(replaced_css)) @@ -352,6 +363,14 @@ GLOBAL_LIST_EMPTY(asset_datums) return TRUE +/datum/asset/spritesheet/proc/read_data_from_cache() + var/json = json_decode(file2text(data_cache_filename())) + + if (islist(json["sprites"])) + sprites = json["sprites"] + + return TRUE + /datum/asset/spritesheet/proc/send_from_cache(client/client) if (isnull(cached_spritesheets_needed)) stack_trace("cached_spritesheets_needed was null when sending assets from [type] from cache") @@ -367,6 +386,10 @@ GLOBAL_LIST_EMPTY(asset_datums) return SSassets.transport.get_asset_url(asset) /datum/asset/spritesheet/proc/write_to_cache() + write_css_to_cache() + write_data_to_cache() + +/datum/asset/spritesheet/proc/write_css_to_cache() for (var/size_id in sizes) var/datum/asset_cache_item/temp = SSassets.cache["[name]_[size_id].png"] fcopy(temp.resource, "[ASSET_CROSS_ROUND_CACHE_DIRECTORY]/spritesheet.[name]_[size_id].png") @@ -375,7 +398,12 @@ GLOBAL_LIST_EMPTY(asset_datums) var/mock_css = generate_css() generating_cache = FALSE - rustg_file_write(mock_css, "[ASSET_CROSS_ROUND_CACHE_DIRECTORY]/spritesheet.[name].css") + rustg_file_write(mock_css, css_cache_filename()) + +/datum/asset/spritesheet/proc/write_data_to_cache() + rustg_file_write(json_encode(list( + "sprites" = sprites, + )), data_cache_filename()) /datum/asset/spritesheet/proc/get_cached_url_mappings() var/list/mappings = list() diff --git a/code/modules/client/preferences/middleware/antags.dm b/code/modules/client/preferences/middleware/antags.dm index e151400e22558..3edf7d2a5a206 100644 --- a/code/modules/client/preferences/middleware/antags.dm +++ b/code/modules/client/preferences/middleware/antags.dm @@ -133,7 +133,6 @@ /datum/asset/spritesheet/antagonists name = "antagonists" early = TRUE - cross_round_cachable = TRUE /datum/asset/spritesheet/antagonists/create_spritesheets() var/list/generated_icons = list() diff --git a/code/modules/client/preferences/middleware/species.dm b/code/modules/client/preferences/middleware/species.dm index 6d82d09917947..f960128e0d2f7 100644 --- a/code/modules/client/preferences/middleware/species.dm +++ b/code/modules/client/preferences/middleware/species.dm @@ -9,7 +9,6 @@ /datum/asset/spritesheet/species name = "species" early = TRUE - cross_round_cachable = TRUE /datum/asset/spritesheet/species/create_spritesheets() var/list/to_insert = list() diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index e25003b96afd4..673634303abac 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -10,6 +10,7 @@ var/adjusted_flags = null var/voice_change = FALSE //Used to mask/change the user's voice, only specific masks can set this to TRUE var/obj/item/organ/tongue/chosen_tongue = null + var/unique_death /// The unique sound effect of dying while wearing this /obj/item/clothing/mask/attack_self(mob/user) if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE)) diff --git a/code/modules/clothing/masks/hailer.dm b/code/modules/clothing/masks/hailer.dm index 7dd01b5036195..fdc91b95f9be1 100644 --- a/code/modules/clothing/masks/hailer.dm +++ b/code/modules/clothing/masks/hailer.dm @@ -14,6 +14,7 @@ visor_flags_inv = HIDEFACE | HIDESNOUT flags_cover = MASKCOVERSMOUTH | MASKCOVERSEYES visor_flags_cover = MASKCOVERSMOUTH | MASKCOVERSEYES + unique_death = 'sound/voice/sec_death.ogg' var/aggressiveness = 2 var/cooldown_special var/recent_uses = 0 diff --git a/code/modules/emote_panel/emote_panel.dm b/code/modules/emote_panel/emote_panel.dm new file mode 100644 index 0000000000000..72caf05e92b27 --- /dev/null +++ b/code/modules/emote_panel/emote_panel.dm @@ -0,0 +1,64 @@ +/datum/emote_panel + var/list/blacklisted_emotes = list("me", "help") + +/datum/emote_panel/ui_static_data(mob/user) + var/list/data = list() + + var/list/emotes = list() + var/list/keys = list() + + for(var/key in GLOB.emote_list) + for(var/datum/emote/emote in GLOB.emote_list[key]) + if(emote.key in keys) + continue + if(emote.key in blacklisted_emotes) + continue + if(emote.can_run_emote(user, status_check = FALSE, intentional = FALSE)) + keys += emote.key + emotes += list(list( + "key" = emote.key, + "name" = emote.name, + "hands" = emote.hands_use_check, + "visible" = emote.emote_type & EMOTE_VISIBLE, + "audible" = emote.emote_type & EMOTE_AUDIBLE, + "sound" = !isnull(emote.get_sound(user)), + "use_params" = emote.message_param, + )) + + data["emotes"] = emotes + + return data + +/datum/emote_panel/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + switch(action) + if("play_emote") + var/emote_key = params["emote_key"] + if(isnull(emote_key) || !GLOB.emote_list[emote_key]) + return + var/use_params = params["use_params"] + var/datum/emote/emote = GLOB.emote_list[emote_key][1] + var/emote_param + if(emote.message_param && use_params) + emote_param = tgui_input_text(ui.user, "Add params to the emote...", emote.message_param) + ui.user.emote(emote_key, message = emote_param, intentional = TRUE) + +/datum/emote_panel/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "EmotePanel") + ui.open() + +/datum/emote_panel/ui_state(mob/user) + return GLOB.always_state + +/mob/living/verb/emote_panel() + set name = "Emote Panel" + set category = "IC" + + var/static/datum/emote_panel/emote_panel + if(isnull(emote_panel)) + emote_panel = new + emote_panel.ui_interact(src) diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 2285b80496d9f..edff4142e2d86 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -26,6 +26,7 @@ hands_use_check = TRUE mob_type_allowed_typecache = list(/mob/living, /mob/dead/observer) mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/living/silicon/ai) + emote_type = EMOTE_VISIBLE /datum/emote/flip/run_emote(mob/user, params , type_override, intentional) . = ..() @@ -41,6 +42,7 @@ hands_use_check = TRUE mob_type_allowed_typecache = list(/mob/living, /mob/dead/observer) mob_type_ignore_stat_typecache = list(/mob/dead/observer) + emote_type = EMOTE_VISIBLE /datum/emote/spin/run_emote(mob/user, params , type_override, intentional) . = ..() @@ -62,8 +64,10 @@ key = "inhale" key_third_person = "inhales" message = "breathes in" + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE /datum/emote/exhale key = "exhale" key_third_person = "exhales" message = "breathes out" + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm index 2101a9406c67f..69f8e02e2320e 100644 --- a/code/modules/mob/living/basic/basic.dm +++ b/code/modules/mob/living/basic/basic.dm @@ -141,6 +141,12 @@ icon_state = icon_living density = initial(density) +/mob/living/basic/examine(mob/user) + . = ..() + if(stat != DEAD) + return + . += "Upon closer examination, [p_they()] appear[p_s()] to be [HAS_TRAIT(user.mind, TRAIT_NAIVE) ? "asleep" : "dead"]." + /mob/living/basic/proc/melee_attack(atom/target) src.face_atom(target) // if(SEND_SIGNAL(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, target) & COMPONENT_HOSTILE_NO_ATTACK) diff --git a/code/modules/mob/living/brain/emote.dm b/code/modules/mob/living/brain/emote.dm index 7c962a101f5b7..75599e892a25d 100644 --- a/code/modules/mob/living/brain/emote.dm +++ b/code/modules/mob/living/brain/emote.dm @@ -1,6 +1,7 @@ /datum/emote/brain mob_type_allowed_typecache = list(/mob/living/brain) mob_type_blacklist_typecache = list() + emote_type = EMOTE_AUDIBLE /datum/emote/brain/can_run_emote(mob/user, status_check = TRUE, intentional) . = ..() @@ -11,24 +12,21 @@ /datum/emote/brain/alarm key = "alarm" message = "sounds an alarm." - emote_type = EMOTE_AUDIBLE /datum/emote/brain/alert key = "alert" message = "lets out a distressed noise." - emote_type = EMOTE_AUDIBLE /datum/emote/brain/flash key = "flash" message = "blinks their lights." + emote_type = EMOTE_VISIBLE /datum/emote/brain/notice key = "notice" message = "plays a loud tone." - emote_type = EMOTE_AUDIBLE /datum/emote/brain/whistle key = "whistle" key_third_person = "whistles" message = "whistles." - emote_type = EMOTE_AUDIBLE diff --git a/code/modules/mob/living/carbon/alien/emote.dm b/code/modules/mob/living/carbon/alien/emote.dm index e1b6ab0cc9c52..18b2555e781fd 100644 --- a/code/modules/mob/living/carbon/alien/emote.dm +++ b/code/modules/mob/living/carbon/alien/emote.dm @@ -11,6 +11,7 @@ key_third_person = "hisses" message_alien = "hisses." message_larva = "hisses softly." + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE /datum/emote/living/alien/hiss/get_sound(mob/living/user) if(isalienadult(user)) @@ -21,7 +22,7 @@ key_third_person = "roars" message_alien = "roars." message_larva = "softly roars." - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE vary = TRUE /datum/emote/living/alien/roar/get_sound(mob/living/user) diff --git a/code/modules/mob/living/carbon/emote.dm b/code/modules/mob/living/carbon/emote.dm index 4b3beebc9e457..a8d7f19daa9a5 100644 --- a/code/modules/mob/living/carbon/emote.dm +++ b/code/modules/mob/living/carbon/emote.dm @@ -5,15 +5,19 @@ key = "airguitar" message = "is strumming the air and headbanging like a safari chimp" hands_use_check = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/blink key = "blink" key_third_person = "blinks" message = "blinks" + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/blink_r key = "blink_r" + name = "blink (Rapid)" message = "blinks rapidly" + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/clap key = "clap" @@ -21,7 +25,7 @@ message = "claps" muzzle_ignore = TRUE hands_use_check = TRUE - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE vary = TRUE /datum/emote/living/carbon/clap/can_run_emote(mob/user, status_check = TRUE, intentional) @@ -44,6 +48,7 @@ key_third_person = "eyerolls" message = "rolls their eyes" vary = TRUE + emote_type = EMOTE_VISIBLE mob_type_blacklist_typecache = list(/mob/living/carbon/alien) /datum/emote/living/carbon/eyeroll/can_run_emote(mob/user, status_check = TRUE, intentional) @@ -57,13 +62,14 @@ key_third_person = "gnarls" message = "gnarls and shows its teeth.." mob_type_allowed_typecache = list(/mob/living/carbon/monkey) + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE /datum/emote/living/carbon/moan key = "moan" key_third_person = "moans" message = "moans" message_mime = "appears to moan" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE /datum/emote/living/carbon/roll key = "roll" @@ -71,6 +77,7 @@ message = "rolls" mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien) hands_use_check = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/scratch key = "scratch" @@ -78,6 +85,7 @@ message = "scratches" mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien) hands_use_check = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/screech key = "screech" @@ -96,10 +104,10 @@ 'sound/creatures/monkey/monkey_screech_7.ogg') /datum/emote/living/carbon/snap - emote_type = EMOTE_AUDIBLE muzzle_ignore = TRUE hands_use_check = TRUE vary = TRUE + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE /datum/emote/living/carbon/snap/can_run_emote(mob/user, status_check = TRUE, intentional) if(!..()) @@ -133,6 +141,7 @@ key = "roar" key_third_person = "roars" message = "roars" + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE /datum/emote/living/carbon/sign key = "sign" @@ -140,6 +149,7 @@ message_param = "signs the number %t" mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien) hands_use_check = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/sign/select_param(mob/user, params) . = ..() @@ -152,22 +162,25 @@ message_param = "raises %t fingers" mob_type_allowed_typecache = list(/mob/living/carbon/human) hands_use_check = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/tail key = "tail" message = "waves their tail" mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien) + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/wink key = "wink" key_third_person = "winks" message = "winks" + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/sweatdrop key = "sweatdrop" key_third_person = "sweatdrops" message = "sweats" - emote_type = EMOTE_ANIMATED + emote_type = EMOTE_ANIMATED | EMOTE_VISIBLE sound_volume = 25 vary = TRUE overlay_icon_state = "sweatdrop" @@ -176,9 +189,12 @@ emote_length = 3 SECONDS sound = 'sound/emotes/sweatdrop.ogg' +/datum/emote/living/carbon/sweatdrop/sweat //This is entirely the same as sweatdrop, however people might use either, so i'm adding this one instead of editing the other one. + key = "sweat" + /datum/emote/living/carbon/annoyed key = "annoyed" - emote_type = EMOTE_ANIMATED + emote_type = EMOTE_ANIMATED | EMOTE_VISIBLE sound_volume = 25 vary = TRUE overlay_icon_state = "annoyed" @@ -190,7 +206,7 @@ /datum/emote/living/carbon/glasses key = "glasses" message = "pushes up their glasses" - emote_type = EMOTE_ANIMATED + emote_type = EMOTE_ANIMATED | EMOTE_VISIBLE overlay_icon_state = "glasses" emote_length = 1 SECONDS diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 1f58b92024368..953f5ee00dbee 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -8,7 +8,7 @@ key = "cry" key_third_person = "cries" message = "cries" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE //Cry in silence as you should. /datum/emote/living/carbon/human/cry/run_emote(mob/user, params, type_override, intentional) . = ..() @@ -34,14 +34,16 @@ key = "dap" key_third_person = "daps" message = "sadly can't find anybody to give daps to, and daps themself. Shameful" - message_param = "give daps to %t" + message_param = "gives daps to %t" hands_use_check = TRUE + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE /datum/emote/living/carbon/human/etwitch key = "etwitch" key_third_person = "twitches their ears" message = "twitches their ears" vary = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/human/etwitch/can_run_emote(mob/user, status_check = TRUE, intentional) if(!..()) @@ -52,6 +54,7 @@ /datum/emote/living/carbon/human/eyebrow key = "eyebrow" message = "raises an eyebrow" + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/human/grumble key = "grumble" @@ -64,7 +67,7 @@ message = "shakes their own hand" message_param = "shakes hands with %t" hands_use_check = TRUE - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/human/hug key = "hug" @@ -72,17 +75,18 @@ message = "hugs themself" message_param = "hugs %t" hands_use_check = TRUE - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/human/mumble key = "mumble" key_third_person = "mumbles" message = "mumbles" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE /datum/emote/living/carbon/human/offer key = "offer" message = "offers an item" + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/human/moth // allow mothroach as well as human base mob - species check is done in can_run_emote @@ -101,7 +105,7 @@ message = "lets out a tiny squeak" emote_type = EMOTE_AUDIBLE vary = TRUE - sound = 'sound/emotes/mothsqueak.ogg' + sound = 'sound/emotes/moth/mothsqueak.ogg' /datum/emote/living/carbon/human/moth/chitter key = "chitter" @@ -109,13 +113,13 @@ message = "chitters" emote_type = EMOTE_AUDIBLE vary = TRUE - sound = 'sound/emotes/mothchitter.ogg' + sound = 'sound/emotes/moth/mothchitter.ogg' /datum/emote/living/carbon/human/scream key = "scream" key_third_person = "screams" message = "screams" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE vary = TRUE /datum/emote/living/carbon/human/scream/get_sound(mob/living/user) @@ -127,11 +131,13 @@ /datum/emote/living/carbon/human/pale key = "pale" message = "goes pale for a second" + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/human/raise key = "raise" key_third_person = "raises" message = "raises a hand" + emote_type = EMOTE_VISIBLE hands_use_check = TRUE /datum/emote/living/carbon/human/salute @@ -139,17 +145,26 @@ key_third_person = "salutes" message = "salutes" message_param = "salutes to %t" + emote_type = EMOTE_VISIBLE hands_use_check = TRUE /datum/emote/living/carbon/human/shrug key = "shrug" key_third_person = "shrugs" message = "shrugs" + emote_type = EMOTE_VISIBLE + +/datum/emote/living/carbon/human/tilt + key = "tilt" + key_third_person = "tilts their head to the side" + message = "tilts their head to the side" + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/human/wag key = "wag" key_third_person = "wags" message = "wags their tail" + emote_type = EMOTE_VISIBLE /datum/emote/living/carbon/human/wag/run_emote(mob/user, params, type_override, intentional) . = ..() @@ -178,6 +193,7 @@ key = "wing" key_third_person = "wings" message = "their wings" + emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE /datum/emote/living/carbon/human/wing/run_emote(mob/user, params, type_override, intentional) . = ..() @@ -205,6 +221,7 @@ if(istype(wings)) if(wings.flight_level >= WINGS_FLYING) return TRUE + return FALSE /mob/living/carbon/human/proc/Togglewings() if(!dna || !dna.species) @@ -254,12 +271,14 @@ key_third_person = "beeps" message = "beeps" message_param = "beeps at %t" + emote_type = EMOTE_AUDIBLE /datum/emote/living/carbon/human/robot_tongue/boop key = "boop" key_third_person = "boops" message = "boops." sound = 'sound/machines/boop.ogg' + emote_type = EMOTE_AUDIBLE /datum/emote/living/carbon/human/robot_tongue/beep/run_emote(mob/user, params) if(..()) @@ -270,6 +289,7 @@ key_third_person = "buzzes" message = "buzzes" message_param = "buzzes at %t" + emote_type = EMOTE_AUDIBLE /datum/emote/living/carbon/human/robot_tongue/buzz/run_emote(mob/user, params) if(..()) @@ -278,6 +298,7 @@ /datum/emote/living/carbon/human/robot_tongue/buzz2 key = "buzz2" message = "buzzes twice" + emote_type = EMOTE_AUDIBLE /datum/emote/living/carbon/human/robot_tongue/buzz2/run_emote(mob/user, params) if(..()) @@ -287,6 +308,7 @@ key = "chime" key_third_person = "chimes" message = "chimes" + emote_type = EMOTE_AUDIBLE /datum/emote/living/carbon/human/robot_tongue/chime/run_emote(mob/user, params) if(..()) @@ -297,6 +319,7 @@ key_third_person = "pings" message = "pings" message_param = "pings at %t" + emote_type = EMOTE_AUDIBLE /datum/emote/living/carbon/human/robot_tongue/ping/run_emote(mob/user, params) if(..()) @@ -324,6 +347,7 @@ key = "honk" key_third_person = "honks" message = "honks" + emote_type = EMOTE_AUDIBLE /datum/emote/living/carbon/human/robot_tongue/clown/honk/run_emote(mob/user, params) if(..()) @@ -333,6 +357,7 @@ key = "sad" key_third_person = "plays a sad trombone" message = "plays a sad trombone" + emote_type = EMOTE_AUDIBLE /datum/emote/living/carbon/human/robot_tongue/clown/sad/run_emote(mob/user, params) if(..()) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index b8a3cc83af3a9..2c4e4ec209664 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -2435,6 +2435,9 @@ GLOBAL_LIST_EMPTY(features_by_species) /datum/species/proc/get_cough_sound(mob/living/carbon/user) return +/datum/species/proc/get_cry_sound(mob/living/carbon/user) + return + /datum/species/proc/get_gasp_sound(mob/living/carbon/user) return @@ -2447,6 +2450,9 @@ GLOBAL_LIST_EMPTY(features_by_species) /datum/species/proc/get_sniff_sound(mob/living/carbon/user) return +/datum/species/proc/get_giggle_sound(mob/living/carbon/user) + return + /datum/species/proc/get_clear_sound(mob/living/carbon/user) return diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm index be59dc9e0cc70..2c2c6be29cb23 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -194,6 +194,9 @@ /datum/species/ethereal/get_sniff_sound(mob/living/carbon/user) return SPECIES_DEFAULT_SNIFF_SOUND(user) +/datum/species/ethereal/get_giggle_sound(mob/living/carbon/user) + return SPECIES_DEFAULT_GIGGLE_SOUND(user) + /datum/species/ethereal/get_features() var/list/features = ..() diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm index 6c0ad26df0a4e..fe144a6ef7efc 100644 --- a/code/modules/mob/living/carbon/human/species_types/humans.dm +++ b/code/modules/mob/living/carbon/human/species_types/humans.dm @@ -43,6 +43,9 @@ /datum/species/human/get_sniff_sound(mob/living/carbon/user) return SPECIES_DEFAULT_SNIFF_SOUND(user) +/datum/species/human/get_giggle_sound(mob/living/carbon/user) + return SPECIES_DEFAULT_GIGGLE_SOUND(user) + /datum/species/human/prepare_human_for_preview(mob/living/carbon/human/human) human.hair_style = "Business Hair" human.hair_color = "b96" // brown diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 6be939510e757..7b32986dea02a 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -78,6 +78,9 @@ /datum/species/lizard/get_sniff_sound(mob/living/carbon/user) return SPECIES_DEFAULT_SNIFF_SOUND(user) +/datum/species/lizard/get_giggle_sound(mob/living/carbon/user) + return SPECIES_DEFAULT_GIGGLE_SOUND(user) + /datum/species/lizard/get_species_description() return "Lizardpeople, unlike many 'Animalid' species, are not derived from humans, and are simply bipedal reptile-like people. \ Lizards often find great pride in their species." diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index 8dfbd2ac4a660..6b2683571c83c 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -60,7 +60,7 @@ return 0 /datum/species/moth/get_laugh_sound(mob/living/carbon/user) - return 'sound/emotes/mothlaugh.ogg' + return 'sound/emotes/moth/mothlaugh.ogg' /datum/species/moth/get_scream_sound(mob/living/carbon/user) return 'sound/voice/moth/scream_moth.ogg' diff --git a/code/modules/mob/living/carbon/human/species_types/oozelings.dm b/code/modules/mob/living/carbon/human/species_types/oozelings.dm index 35dc8f5afb36d..a3aaaeefebfee 100644 --- a/code/modules/mob/living/carbon/human/species_types/oozelings.dm +++ b/code/modules/mob/living/carbon/human/species_types/oozelings.dm @@ -213,6 +213,9 @@ /datum/species/oozeling/get_sniff_sound(mob/living/carbon/user) return SPECIES_DEFAULT_SNIFF_SOUND(user) +/datum/species/oozeling/get_giggle_sound(mob/living/carbon/user) + return SPECIES_DEFAULT_GIGGLE_SOUND(user) + /datum/species/oozeling/get_species_description() return "Literally made of jelly, Oozelings are squishy friends aboard Space Station 13." diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index 584ea5dddfa43..3f72ccca4d850 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -156,6 +156,9 @@ /datum/species/plasmaman/get_sniff_sound(mob/living/carbon/user) return SPECIES_DEFAULT_SNIFF_SOUND(user) +/datum/species/plasmaman/get_giggle_sound(mob/living/carbon/user) + return SPECIES_DEFAULT_GIGGLE_SOUND(user) + /datum/species/plasmaman/get_species_description() return "Found on the Icemoon of Freyja, plasmamen consist of colonial \ fungal organisms which together form a sentient being. In human space, \ diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 6908a0bbb88da..fd5bd82cd86a2 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -11,6 +11,7 @@ key = "blush" key_third_person = "blushes" message = "blushes" + emote_type = EMOTE_VISIBLE /// Timer for the blush visual to wear off /datum/emote/living/blush/run_emote(mob/user, params, type_override, intentional) @@ -39,37 +40,39 @@ key_third_person = "bows" message = "bows" message_param = "bows to %t" + emote_type = EMOTE_VISIBLE hands_use_check = TRUE /datum/emote/living/burp key = "burp" key_third_person = "burps" message = "burps" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/choke key = "choke" key_third_person = "chokes" message = "chokes" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/cross key = "cross" key_third_person = "crosses" message = "crosses their arms" + emote_type = EMOTE_VISIBLE hands_use_check = TRUE /datum/emote/living/chuckle key = "chuckle" key_third_person = "chuckles" message = "chuckles" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/collapse key = "collapse" key_third_person = "collapses" message = "collapses" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/collapse/run_emote(mob/user, params, type_override, intentional) . = ..() @@ -82,6 +85,7 @@ key_third_person = "dances" message = "dances around happily" hands_use_check = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/deathgasp key = "deathgasp" @@ -94,6 +98,7 @@ message_monkey = "lets out a faint chimper as it collapses and stops moving" message_ipc = "gives one shrill beep before falling limp, their monitor flashing blue before completely shutting off" message_simple = "stops moving" + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE | EMOTE_IMPORTANT stat_allowed = HARD_CRIT /datum/emote/living/deathgasp/run_emote(mob/user, params, type_override, intentional) @@ -102,22 +107,28 @@ message_simple = S.deathmessage . = ..() message_simple = initial(message_simple) - if(. && user.deathsound) - if(isliving(user)) - var/mob/living/L = user - if(!L.can_speak_vocal() || L.oxyloss >= 50) - return //stop the sound if oxyloss too high/cant speak + var/mob/living/living_user = user + if(!. && !living_user.can_speak_vocal() || living_user.getOxyLoss() >= 50) + return //stop the sound if oxyloss too high/cant speak + var/mob/living/carbon/carbon_user = user + // For masks that give unique death sounds + if(istype(carbon_user) && isclothing(carbon_user.wear_mask) && carbon_user.wear_mask.unique_death) + playsound(carbon_user, carbon_user.wear_mask.unique_death, 200, TRUE, TRUE) + return + if(user.deathsound) playsound(user, user.deathsound, 200, TRUE, TRUE) /datum/emote/living/drool key = "drool" key_third_person = "drools" message = "drools" + emote_type = EMOTE_VISIBLE /datum/emote/living/faint key = "faint" key_third_person = "faints" message = "faints" + emote_type = EMOTE_VISIBLE /datum/emote/living/faint/run_emote(mob/user, params, type_override, intentional) . = ..() @@ -130,82 +141,110 @@ key_third_person = "flaps" message = "flaps their wings" hands_use_check = TRUE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE var/wing_time = 10 /datum/emote/living/flap/run_emote(mob/user, params, type_override, intentional) . = ..() if(. && ishuman(user)) var/mob/living/carbon/human/H = user + var/obj/item/organ/wings/wings = H.getorganslot(ORGAN_SLOT_WINGS) if(H.Togglewings()) addtimer(CALLBACK(H,TYPE_PROC_REF(/mob/living/carbon/human, Togglewings)), wing_time) + // play moth flutter noise if moth wing + if(istype(wings, /obj/item/organ/wings/moth)) + playsound(H, 'sound/emotes/moth/moth_flutter.ogg', 50, TRUE) /datum/emote/living/flap/aflap key = "aflap" key_third_person = "aflaps" + name = "flap (Angry)" message = "flaps their wings aggressively" hands_use_check = TRUE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE wing_time = 5 /datum/emote/living/frown key = "frown" key_third_person = "frowns" message = "frowns" + emote_type = EMOTE_VISIBLE /datum/emote/living/gag key = "gag" key_third_person = "gags" message = "gags" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/giggle key = "giggle" key_third_person = "giggles" message = "giggles" message_mime = "giggles silently" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE + +/datum/emote/living/giggle/get_sound(mob/living/user) + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + return H?.dna?.species?.get_giggle_sound(H) /datum/emote/living/glare key = "glare" key_third_person = "glares" message = "glares" message_param = "glares at %t" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE /datum/emote/living/grin key = "grin" key_third_person = "grins" message = "grins" + emote_type = EMOTE_VISIBLE /datum/emote/living/groan key = "groan" key_third_person = "groans" message = "groans" message_mime = "appears to groan" + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/grimace key = "grimace" key_third_person = "grimaces" message = "grimaces" + emote_type = EMOTE_VISIBLE /datum/emote/living/jump key = "jump" key_third_person = "jumps" message = "jumps" hands_use_check = TRUE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE + +/datum/emote/living/jump/run_emote(mob/living/user, params, type_override, intentional) + . = ..() + if(!.) + return FALSE + animate(user, pixel_y = user.pixel_y + 4, time = 0.1 SECONDS) + animate(pixel_y = user.pixel_y - 4, time = 0.1 SECONDS) + +/datum/emote/living/jump/get_sound(mob/living/user) + return 'sound/weapons/thudswoosh.ogg' /datum/emote/living/kiss key = "kiss" key_third_person = "kisses" message = "blows a kiss" message_param = "blows a kiss to %t" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/laugh key = "laugh" key_third_person = "laughs" message = "laughs" message_mime = "laughs silently" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE vary = TRUE /datum/emote/living/laugh/can_run_emote(mob/living/user, status_check = TRUE , intentional) @@ -227,12 +266,14 @@ key_third_person = "looks" message = "looks" message_param = "looks at %t" + emote_type = EMOTE_VISIBLE /datum/emote/living/nod key = "nod" key_third_person = "nods" message = "nods" message_param = "nods at %t" + emote_type = EMOTE_VISIBLE /datum/emote/living/point key = "point" @@ -240,6 +281,7 @@ message = "points" message_param = "points at %t" hands_use_check = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/point/run_emote(mob/user, params, type_override, intentional) message_param = initial(message_param) // reset @@ -258,14 +300,14 @@ key = "pout" key_third_person = "pouts" message = "pouts" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/scream key = "scream" key_third_person = "screams" message = "screams" message_mime = "acts out a scream" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE mob_type_blacklist_typecache = list(/mob/living/carbon/human) //Humans get specialized scream. /datum/emote/living/scream/select_message_type(mob/user, intentional) @@ -277,41 +319,62 @@ key = "scowl" key_third_person = "scowls" message = "scowls" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE /datum/emote/living/shake key = "shake" key_third_person = "shakes" message = "shakes their head" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE /datum/emote/living/shiver key = "shiver" key_third_person = "shiver" message = "shivers" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE + +#define SHIVER_LOOP_DURATION (1 SECONDS) +/datum/emote/living/shiver/run_emote(mob/living/user, params, type_override, intentional) + . = ..() + if(!.) + return FALSE + animate(user, pixel_x = user.pixel_x + 1, time = 0.1 SECONDS) + for(var/i in 1 to SHIVER_LOOP_DURATION / (0.2 SECONDS)) //desired total duration divided by the iteration duration to give the necessary iteration count + animate(pixel_x = user.pixel_x - 1, time = 0.1 SECONDS) + animate(pixel_x = user.pixel_x + 1, time = 0.1 SECONDS) + animate(pixel_x = user.pixel_x - 1, time = 0.1 SECONDS) +#undef SHIVER_LOOP_DURATION /datum/emote/living/sit key = "sit" key_third_person = "sits" message = "sits down" + emote_type = EMOTE_VISIBLE /datum/emote/living/smile key = "smile" key_third_person = "smiles" message = "smiles" + emote_type = EMOTE_VISIBLE /datum/emote/living/smug key = "smug" key_third_person = "smugs" message = "grins smugly" + emote_type = EMOTE_VISIBLE + +/datum/emote/living/smirk + key = "smirk" + key_third_person = "smirks" + message = "smirks" + emote_type = EMOTE_VISIBLE /datum/emote/living/snore key = "snore" key_third_person = "snores" message = "snores" message_mime = "sleeps soundly" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE stat_allowed = UNCONSCIOUS /datum/emote/living/stare @@ -319,22 +382,25 @@ key_third_person = "stares" message = "stares" message_param = "stares at %t" + emote_type = EMOTE_VISIBLE /datum/emote/living/strech key = "stretch" key_third_person = "stretches" message = "stretches their arms" + emote_type = EMOTE_VISIBLE /datum/emote/living/sulk key = "sulk" key_third_person = "sulks" message = "sulks down sadly" + emote_type = EMOTE_VISIBLE /datum/emote/living/surrender key = "surrender" key_third_person = "surrenders" message = "puts their hands on their head and falls to the ground, surrendering" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/surrender/run_emote(mob/user, params, type_override, intentional) . = ..() @@ -346,48 +412,97 @@ key = "sway" key_third_person = "sways" message = "sways around dizzily" + emote_type = EMOTE_VISIBLE + +/datum/emote/living/sway/run_emote(mob/living/user, params, type_override, intentional) + . = ..() + if(!.) + return FALSE + animate(user, pixel_x = user.pixel_x + 2, time = 0.5 SECONDS) + for(var/i in 1 to 2) + animate(pixel_x = user.pixel_x - 4, time = 1.0 SECONDS) + animate(pixel_x = user.pixel_x + 4, time = 1.0 SECONDS) + animate(pixel_x = user.pixel_x - 2, time = 0.5 SECONDS) /datum/emote/living/tremble key = "tremble" key_third_person = "trembles" - message = "trembles in fear" + message = "trembles" + emote_type = EMOTE_VISIBLE + +#define TREMBLE_LOOP_DURATION (4.4 SECONDS) +/datum/emote/living/tremble/run_emote(mob/living/user, params, type_override, intentional) + . = ..() + if(!.) + return FALSE + animate(user, pixel_x = user.pixel_x + 2, time = 0.2 SECONDS) + for(var/i in 1 to TREMBLE_LOOP_DURATION / (0.4 SECONDS)) //desired total duration divided by the iteration duration to give the necessary iteration count + animate(pixel_x = user.pixel_x - 2, time = 0.2 SECONDS) + animate(pixel_x = user.pixel_x + 2, time = 0.2 SECONDS) + animate(pixel_x = user.pixel_x - 2, time = 0.2 SECONDS) +#undef TREMBLE_LOOP_DURATION /datum/emote/living/twitch key = "twitch" key_third_person = "twitches" message = "twitches violently" + emote_type = EMOTE_VISIBLE + +/datum/emote/living/twitch/run_emote(mob/living/user, params, type_override, intentional) + . = ..() + if(!.) + return FALSE + animate(user, pixel_x = user.pixel_x - 1, time = 0.1 SECONDS) + animate(pixel_x = user.pixel_x + 1, time = 0.1 SECONDS) + animate(time = 0.1 SECONDS) + animate(pixel_x = user.pixel_x - 1, time = 0.1 SECONDS) + animate(pixel_x = user.pixel_x + 1, time = 0.1 SECONDS) /datum/emote/living/twitch_s key = "twitch_s" + name = "twitch (Slight)" message = "twitches" + emote_type = EMOTE_VISIBLE + +/datum/emote/living/twitch_s/run_emote(mob/living/user, params, type_override, intentional) + . = ..() + if(!.) + return FALSE + animate(user, pixel_x = user.pixel_x - 1, time = 0.1 SECONDS) + animate(pixel_x = user.pixel_x + 1, time = 0.1 SECONDS) /datum/emote/living/wave key = "wave" key_third_person = "waves" message = "waves" + emote_type = EMOTE_VISIBLE /datum/emote/living/whimper key = "whimper" key_third_person = "whimpers" message = "whimpers" message_mime = "appears hurt" + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/wsmile key = "wsmile" key_third_person = "wsmiles" + name = "smile (Weak)" message = "smiles weakly" + emote_type = EMOTE_VISIBLE /datum/emote/living/yawn key = "yawn" key_third_person = "yawns" message = "yawns" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/custom key = "me" key_third_person = "custom" message = null mob_type_blacklist_typecache = /mob/living/brain + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/custom/can_run_emote(mob/user, status_check, intentional) . = ..() && intentional @@ -411,11 +526,17 @@ to_chat(user, "You cannot send IC messages (muted).") return FALSE else if(!params) - var/custom_emote = stripped_input(usr, "Choose an emote to display.") + var/custom_emote = stripped_input(user, "Choose an emote to display.") if(custom_emote && !check_invalid(user, custom_emote)) - var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable") - if(type == "Hearable") - emote_type |= EMOTE_AUDIBLE + var/list/emote_list = list("Audible", "Visible", "Both") + var/type = tgui_input_list(user, "Is this a visible or audible emote?", "Emote Type", emote_list) + switch(type) + if("Audible") + emote_type |= EMOTE_AUDIBLE + if("Visible") + emote_type |= EMOTE_VISIBLE + if("Both") + emote_type |= EMOTE_VISIBLE | EMOTE_AUDIBLE message = user.say_emphasis(custom_emote) else message = params @@ -423,7 +544,7 @@ emote_type = type_override . = ..() message = null - emote_type = 0 + emote_type = null /datum/emote/living/custom/replace_pronoun(mob/user, message) return message @@ -432,6 +553,7 @@ key = "help" /datum/emote/living/help/run_emote(mob/user, params, type_override, intentional) + . = ..() var/list/keys = list() var/list/message = list("Available emotes, you can use them with say \"*emote\": ") @@ -462,12 +584,14 @@ message = "beeps" message_param = "beeps at %t" sound = 'sound/machines/twobeep.ogg' + emote_type = EMOTE_AUDIBLE mob_type_allowed_typecache = list(/mob/living/brain, /mob/living/silicon, /mob/living/simple_animal/hostile/mining_drone) /datum/emote/living/circle key = "circle" key_third_person = "circles" hands_use_check = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/circle/run_emote(mob/user, params, type_override, intentional) . = ..() @@ -483,6 +607,7 @@ key = "slap" key_third_person = "slaps" hands_use_check = TRUE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/slap/run_emote(mob/user, params, type_override, intentional) . = ..() @@ -500,6 +625,7 @@ key_third_person = "highfives" message = "raises their hand" hands_use_check = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/raisehand/run_emote(mob/user, params, type_override, intentional) . = ..() @@ -516,6 +642,7 @@ key_third_person = "fingerguns" message = "forms their fingers into the shape of a crude gun" hands_use_check = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/fingergun/run_emote(mob/user, params, type_override, intentional) . = ..() @@ -533,6 +660,7 @@ message = "clicks their tongue" message_ipc = "makes a click sound" message_insect = "clicks their mandibles" + emote_type = EMOTE_AUDIBLE /datum/emote/living/click/get_sound(mob/living/user) if(ismoth(user) || isapid(user) || isflyperson(user) || istype(user, /mob/living/basic/mothroach)) @@ -546,6 +674,7 @@ key = "zap" key_third_person = "zaps" message = "zaps" + emote_type = EMOTE_AUDIBLE /datum/emote/living/zap/can_run_emote(mob/user, status_check = TRUE , intentional) . = ..() @@ -562,11 +691,13 @@ key = "hum" key_third_person = "hums" message = "hums" + emote_type = EMOTE_AUDIBLE /datum/emote/living/hiss key = "hiss" key_third_person = "hisses" message = "hisses" + emote_type = EMOTE_AUDIBLE /datum/emote/living/hiss/get_sound(mob/living/user) if(islizard(user)) @@ -582,6 +713,7 @@ message_simple = "attempts a thumbs up" message_param = "flashes a thumbs up at %t" hands_use_check = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/thumbs_down key = "thumbsdown" @@ -593,6 +725,7 @@ message_simple = "attempts a thumbs down" message_param = "flashes a thumbs down at %t" hands_use_check = TRUE + emote_type = EMOTE_VISIBLE /datum/emote/living/whistle key="whistle" @@ -601,14 +734,14 @@ message_robot = "whistles a few synthesized notes" message_AI = "whistles a synthesized song" message_ipc = "whistles a few synthesized notes" + emote_type = EMOTE_AUDIBLE /datum/emote/living/whistle/get_sound(mob/living/user) - return 'sound/items/megaphone.ogg' + return 'sound/emotes/whistle1.ogg' /// Breathing required + audible emotes /datum/emote/living/must_breathe - emote_type = EMOTE_AUDIBLE vary = TRUE /datum/emote/living/must_breathe/can_run_emote(mob/user, status_check = TRUE, intentional) @@ -621,11 +754,13 @@ key = "clear" key_third_person = "clears their throat" message = "clears their throat" + emote_type = EMOTE_AUDIBLE /datum/emote/living/must_breathe/cough key = "cough" key_third_person = "coughs" message = "coughs" + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/must_breathe/cough/can_run_emote(mob/user, status_check = TRUE, intentional) return ..() && !HAS_TRAIT(user, TRAIT_SOOTHED_THROAT) @@ -640,6 +775,7 @@ key = "gasp" key_third_person = "gasps" message = "gasps" + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE // You can see a person gasping. /datum/emote/living/must_breathe/gasp/get_sound(mob/living/user) if(!ishuman(user)) @@ -651,12 +787,13 @@ key = "huff" key_third_person = "huffs" message ="lets out a huff" + emote_type = EMOTE_AUDIBLE /datum/emote/living/must_breathe/sigh key = "sigh" key_third_person = "sighs" message = "sighs" - emote_type = EMOTE_AUDIBLE|EMOTE_ANIMATED + emote_type = EMOTE_ANIMATED | EMOTE_AUDIBLE | EMOTE_VISIBLE emote_length = 3 SECONDS overlay_y_offset = -1 overlay_icon_state = "sigh" @@ -671,6 +808,7 @@ key = "sneeze" key_third_person = "sneezes" message = "sneezes" + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/living/must_breathe/sneeze/get_sound(mob/living/user) if(!ishuman(user)) @@ -682,6 +820,7 @@ key = "sniff" key_third_person = "sniffs" message = "sniffs" + emote_type = EMOTE_AUDIBLE /datum/emote/living/must_breathe/sniff/get_sound(mob/living/user) if(!ishuman(user)) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 22bbed72e029a..a31a5c1916f75 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -101,7 +101,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list( if(!message) return - message = check_for_custom_say_emote(message, message_mods) + if(!forced && !saymode) + message = check_for_custom_say_emote(message, message_mods) switch(stat) if(SOFT_CRIT) diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/emotes.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/emotes.dm index a265a7582c7a4..d3ed774cb60c1 100644 --- a/code/modules/mob/living/simple_animal/hostile/gorilla/emotes.dm +++ b/code/modules/mob/living/simple_animal/hostile/gorilla/emotes.dm @@ -8,4 +8,5 @@ message = "oogas" message_param = "oogas at %t" sound = 'sound/creatures/gorilla.ogg' + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE diff --git a/code/modules/mob/living/simple_animal/slime/emote.dm b/code/modules/mob/living/simple_animal/slime/emote.dm index c4526623762c6..da3a77b9ada00 100644 --- a/code/modules/mob/living/simple_animal/slime/emote.dm +++ b/code/modules/mob/living/simple_animal/slime/emote.dm @@ -6,27 +6,31 @@ key = "bounce" key_third_person = "bounces" message = "bounces in place." + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/slime/jiggle key = "jiggle" key_third_person = "jiggles" message = "jiggles!" + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/slime/light key = "light" key_third_person = "lights" message = "lights up for a bit, then stops." + emote_type = EMOTE_VISIBLE /datum/emote/slime/vibrate key = "vibrate" key_third_person = "vibrates" message = "vibrates!" + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE /datum/emote/slime/squish key = "squish" key_third_person = "squishes" message = "squishes" - emote_type = EMOTE_AUDIBLE + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE sound_volume = 25 /datum/emote/slime/squish/get_sound(mob/living/user) @@ -35,6 +39,7 @@ /datum/emote/slime/mood key = "moodnone" var/mood = null + emote_type = EMOTE_VISIBLE /datum/emote/slime/mood/run_emote(mob/user, params, type_override, intentional) . = ..() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index b81ca6908319b..e3e077c32a5bb 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -155,32 +155,37 @@ /mob/proc/show_message(msg, type, alt_msg, alt_type, avoid_highlighting = FALSE, dist)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2) if(!client) - return + return FALSE msg = copytext_char(msg, 1, MAX_MESSAGE_LEN) + // Return TRUE if we sent the original msg, otherwise return FALSE + . = TRUE if(type) if(type & MSG_VISUAL && (is_blind() && dist > BLIND_TEXT_DIST))//Vision related if(!alt_msg) - return + return FALSE else msg = alt_msg type = alt_type + . = FALSE if(type & MSG_AUDIBLE && !can_hear())//Hearing related if(!alt_msg) - return + return FALSE else msg = alt_msg type = alt_type + . = FALSE if(type & MSG_VISUAL && is_blind()) - return + return FALSE // voice muffling if(stat == UNCONSCIOUS || stat == HARD_CRIT) if(type & MSG_AUDIBLE) //audio to_chat(src, "... You can almost hear something ...") return to_chat(src, msg, avoid_highlighting = avoid_highlighting) + return . /atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, list/visible_message_flags, allow_inside_usr = FALSE, separation = " ") @@ -233,8 +238,22 @@ /mob/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, list/visible_message_flags, separation = " ") . = ..() - if(self_message) - show_message(self_message, MSG_VISUAL, blind_message, MSG_AUDIBLE) + if(!self_message) + return + var/raw_self_message = self_message + var/self_runechat = FALSE + if(LAZYFIND(visible_message_flags, CHATMESSAGE_EMOTE)) + self_message = "[src] [self_message]" // May make more sense as "You do x" + + if(LAZYFIND(visible_message_flags, ALWAYS_SHOW_SELF_MESSAGE)) + to_chat(src, self_message) + self_runechat = TRUE + + else + self_runechat = show_message(self_message, MSG_VISUAL, blind_message, MSG_AUDIBLE) + + if(self_runechat && (LAZYFIND(visible_message_flags, CHATMESSAGE_EMOTE)) && runechat_prefs_check(src, visible_message_flags)) + create_chat_message(src, null, list(src), raw_message = raw_self_message, message_mods = visible_message_flags) /** * Show a message to all mobs in earshot of this atom @@ -280,8 +299,21 @@ */ /mob/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, list/audible_message_flags, separation = " ") . = ..() - if(self_message) - show_message(self_message, MSG_AUDIBLE, deaf_message, MSG_VISUAL) + if(!self_message) + return + + var/raw_self_message = self_message + var/self_runechat = FALSE + if(LAZYFIND(audible_message_flags, CHATMESSAGE_EMOTE)) + self_message = "[src] [self_message]" + if(LAZYFIND(audible_message_flags, ALWAYS_SHOW_SELF_MESSAGE)) + to_chat(src, self_message) + self_runechat = TRUE + else + self_runechat = show_message(self_message, MSG_AUDIBLE, deaf_message, MSG_VISUAL) + + if(self_runechat && (LAZYFIND(audible_message_flags, CHATMESSAGE_EMOTE)) && runechat_prefs_check(src, audible_message_flags)) + create_chat_message(src, null, list(src), raw_message = raw_self_message, message_mods = audible_message_flags) ///Returns the client runechat visible messages preference according to the message type. /atom/proc/runechat_prefs_check(mob/target, list/visible_message_flags) @@ -289,14 +321,14 @@ return FALSE if (!target.client?.prefs.read_player_preference(/datum/preference/toggle/enable_runechat_non_mobs)) return FALSE - if(LAZYFIND(visible_message_flags, CHATMESSAGE_EMOTE) && !target.client.prefs.read_player_preference(/datum/preference/toggle/see_rc_emotes)) + if((LAZYFIND(visible_message_flags, CHATMESSAGE_EMOTE)) && !target.client.prefs.read_player_preference(/datum/preference/toggle/see_rc_emotes)) return FALSE return TRUE /mob/runechat_prefs_check(mob/target, list/visible_message_flags) if(!target.client?.prefs.read_player_preference(/datum/preference/toggle/enable_runechat)) return FALSE - if(LAZYFIND(visible_message_flags, CHATMESSAGE_EMOTE) && !target.client.prefs.read_player_preference(/datum/preference/toggle/see_rc_emotes)) + if((LAZYFIND(visible_message_flags, CHATMESSAGE_EMOTE)) && !target.client.prefs.read_player_preference(/datum/preference/toggle/see_rc_emotes)) return FALSE return TRUE diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index f720d113c9d1c..6205706f1cefc 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -28,6 +28,7 @@ /mob/verb/me_verb(message as text) set name = "Me" set category = "IC" + set desc = "Perform a custom emote. Leave blank to pick between an audible or a visible emote (Defaults to visible)." if(GLOB.say_disabled) //This is here to try to identify lag problems to_chat(usr, "Speech is currently admin-disabled.") @@ -35,7 +36,7 @@ message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) - usr.emote("me",1,message,TRUE) + usr.emote("me",EMOTE_VISIBLE|EMOTE_AUDIBLE,message,TRUE) ///Speak as a dead person (ghost etc) /mob/proc/say_dead(var/message) @@ -120,7 +121,7 @@ return message if(is_banned_from(ckey, "Emote")) return copytext(message, customsaypos + 1) - mods[MODE_CUSTOM_SAY_EMOTE] = trim_right(LOWER_TEXT(copytext_char(message, 1, customsaypos))) + mods[MODE_CUSTOM_SAY_EMOTE] = trim_right(copytext(message, 1, customsaypos)) message = trim_left(copytext(message, customsaypos + 1)) if(!message) mods[MODE_CUSTOM_SAY_ERASE_INPUT] = TRUE diff --git a/sound/attributions.txt b/sound/attributions.txt index 3d594595af61a..9fa3c9dfce2e4 100644 --- a/sound/attributions.txt +++ b/sound/attributions.txt @@ -2,3 +2,12 @@ sound/items/handling/standard_stamp.ogg is adapted from tom_woysky's "Stamp.wav" sound/ambience/antag/abductee.ogg is from "Warp SFX" https://freesound.org/people/Breviceps/sounds/453391 (CC0) sound/ambience/antag/brainwash.ogg is from "nog.wav" https://freesound.org/people/_NOMINAL_/sounds/124602 (CC-BY 3.0) sound/ambience/antag/hypnosis.ogg is from "Flashback.wav" https://freesound.org/people/Sclolex/sounds/342103 (CC0) + + +modified by grungussuss: +male_sneeze2.ogg: https://freesound.org/people/InspectorJ/sounds/352177/ , license: CC BY 4.0 DEED +female_cough_4.ogg: https://freesound.org/people/OwlStorm/sounds/151213/ , license: CC0 1.0 DEED +female_cough_5.ogg: https://freesound.org/people/thatkellytrna/sounds/425777/ , license: CC0 1.0 DEED +female_cough_6.ogg: https://freesound.org/people/DarkNightPrincess/sounds/625322/ , license: CC0 1.0 DEED +female_cough_7.ogg: https://freesound.org/people/drotzruhn/sounds/405206/ , license: CC BY 4.0 DEED +whistle1.ogg: https://freesound.org/people/taure/sounds/411638/ , license: CC0 1.0 DEED diff --git a/sound/emotes/female/female_cough_4.ogg b/sound/emotes/female/female_cough_4.ogg new file mode 100644 index 0000000000000..53af74368c3bf Binary files /dev/null and b/sound/emotes/female/female_cough_4.ogg differ diff --git a/sound/emotes/female/female_cough_5.ogg b/sound/emotes/female/female_cough_5.ogg new file mode 100644 index 0000000000000..eb3551a31fecb Binary files /dev/null and b/sound/emotes/female/female_cough_5.ogg differ diff --git a/sound/emotes/female/female_cough_6.ogg b/sound/emotes/female/female_cough_6.ogg new file mode 100644 index 0000000000000..7562661bd4853 Binary files /dev/null and b/sound/emotes/female/female_cough_6.ogg differ diff --git a/sound/emotes/female/female_cough_7.ogg b/sound/emotes/female/female_cough_7.ogg new file mode 100644 index 0000000000000..62938b7b761af Binary files /dev/null and b/sound/emotes/female/female_cough_7.ogg differ diff --git a/sound/emotes/female/female_sneeze.ogg b/sound/emotes/female/female_sneeze1.ogg similarity index 100% rename from sound/emotes/female/female_sneeze.ogg rename to sound/emotes/female/female_sneeze1.ogg diff --git a/sound/emotes/female/female_sneeze2.ogg b/sound/emotes/female/female_sneeze2.ogg new file mode 100644 index 0000000000000..8fe020a8c7e8a Binary files /dev/null and b/sound/emotes/female/female_sneeze2.ogg differ diff --git a/sound/emotes/male/male_giggle_1.ogg b/sound/emotes/male/male_giggle_1.ogg new file mode 100644 index 0000000000000..7ba3a11664090 Binary files /dev/null and b/sound/emotes/male/male_giggle_1.ogg differ diff --git a/sound/emotes/male/male_giggle_2.ogg b/sound/emotes/male/male_giggle_2.ogg new file mode 100644 index 0000000000000..85eb97fd63ffd Binary files /dev/null and b/sound/emotes/male/male_giggle_2.ogg differ diff --git a/sound/emotes/male/male_giggle_3.ogg b/sound/emotes/male/male_giggle_3.ogg new file mode 100644 index 0000000000000..d248f4d0d89d8 Binary files /dev/null and b/sound/emotes/male/male_giggle_3.ogg differ diff --git a/sound/emotes/male/male_sneeze.ogg b/sound/emotes/male/male_sneeze1.ogg similarity index 100% rename from sound/emotes/male/male_sneeze.ogg rename to sound/emotes/male/male_sneeze1.ogg diff --git a/sound/emotes/male/male_sneeze2.ogg b/sound/emotes/male/male_sneeze2.ogg new file mode 100644 index 0000000000000..1c7e8f42534d8 Binary files /dev/null and b/sound/emotes/male/male_sneeze2.ogg differ diff --git a/sound/emotes/moth/moth_flutter.ogg b/sound/emotes/moth/moth_flutter.ogg new file mode 100644 index 0000000000000..f5737d522ca20 Binary files /dev/null and b/sound/emotes/moth/moth_flutter.ogg differ diff --git a/sound/emotes/mothchitter.ogg b/sound/emotes/moth/mothchitter.ogg similarity index 100% rename from sound/emotes/mothchitter.ogg rename to sound/emotes/moth/mothchitter.ogg diff --git a/sound/emotes/mothlaugh.ogg b/sound/emotes/moth/mothlaugh.ogg similarity index 100% rename from sound/emotes/mothlaugh.ogg rename to sound/emotes/moth/mothlaugh.ogg diff --git a/sound/emotes/mothsqueak.ogg b/sound/emotes/moth/mothsqueak.ogg similarity index 100% rename from sound/emotes/mothsqueak.ogg rename to sound/emotes/moth/mothsqueak.ogg diff --git a/sound/emotes/scream_moth.ogg b/sound/emotes/moth/scream_moth.ogg similarity index 100% rename from sound/emotes/scream_moth.ogg rename to sound/emotes/moth/scream_moth.ogg diff --git a/sound/emotes/whistle1.ogg b/sound/emotes/whistle1.ogg new file mode 100644 index 0000000000000..4109260659723 Binary files /dev/null and b/sound/emotes/whistle1.ogg differ diff --git a/sound/voice/moth/credit.txt b/sound/voice/moth/credit.txt new file mode 100644 index 0000000000000..584d169bc09dc --- /dev/null +++ b/sound/voice/moth/credit.txt @@ -0,0 +1,5 @@ +"moth_flutter" modified from +https://freesound.org/people/Godowan/sounds/240476/ +(CC 0 license) + +who knows where the original moth scream noise was I sure as hell don't diff --git a/sound/voice/sec_death.ogg b/sound/voice/sec_death.ogg new file mode 100644 index 0000000000000..25f9b24c313f2 Binary files /dev/null and b/sound/voice/sec_death.ogg differ diff --git a/tgui/packages/tgui/components/SearchBar.tsx b/tgui/packages/tgui/components/SearchBar.tsx new file mode 100644 index 0000000000000..9f4e410f073f6 --- /dev/null +++ b/tgui/packages/tgui/components/SearchBar.tsx @@ -0,0 +1,38 @@ +import { Icon, Input, Stack } from '.'; + +type RequiredProps = { + /** The state variable. */ + query: string; + /** The function to call when the user searches. */ + onSearch: (query: string) => void; +}; + +type OptionalProps = Partial<{ + /** Whether the input should be focused on mount. */ + autoFocus: boolean; + /** Whether to show the search icon. */ + noIcon: boolean; + /** The placeholder text. */ + placeholder: string; + /** Override styles of the search bar. */ + style: Partial; +}>; + +type Props = RequiredProps & OptionalProps; + +/** + * Simple component for searching. + * This component does not accept box props - just recreate it if needed + */ +export const SearchBar = (props: Props, content) => { + const { autoFocus, noIcon = false, onSearch, placeholder = 'Search...', query = '', style } = props; + + return ( + + {!noIcon && } + + onSearch(value)} placeholder={placeholder} value={query} /> + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/EmotePanel.tsx b/tgui/packages/tgui/interfaces/EmotePanel.tsx new file mode 100644 index 0000000000000..f894dd529727f --- /dev/null +++ b/tgui/packages/tgui/interfaces/EmotePanel.tsx @@ -0,0 +1,203 @@ +import { useBackend, useLocalState } from '../backend'; +import { Window } from '../layouts'; +import { Button, Section, Flex, Icon, Box } from '../components'; +import { BooleanLike } from '../../common/react'; +import { SearchBar } from '../components/SearchBar'; +import { capitalize } from '../../common/string'; + +type Emote = { + key: string; + name: string; + hands: BooleanLike; + visible: BooleanLike; + audible: BooleanLike; + sound: BooleanLike; + use_params: BooleanLike; +}; + +type EmotePanelData = { + emotes: Emote[]; +}; + +export const EmotePanelContent = (props, context) => { + const { act, data } = useBackend(context); + const { emotes } = data; + + const [filterVisible, toggleVisualFilter] = useLocalState(context, 'filterVisible', false); + + const [filterAudible, toggleAudibleFilter] = useLocalState(context, 'filterAudible', false); + + const [filterSound, toggleSoundFilter] = useLocalState(context, 'filterSound', false); + + const [filterHands, toggleHandsFilter] = useLocalState(context, 'filterHands', false); + + const [filterUseParams, toggleUseParamsFilter] = useLocalState(context, 'filterUseParams', false); + + const [useParams, toggleUseParams] = useLocalState(context, 'useParams', false); + + const [searchText, setSearchText] = useLocalState(context, 'search_text', ''); + + const [showNames, toggleShowNames] = useLocalState(context, 'showNames', true); + + const [showIcons, toggleShowIcons] = useLocalState(context, 'showIcons', false); + + return ( +
+
+
+
0 ? `Search results of "${searchText}"` : `All Emotes`} + buttons={ + + + + + + + + + + }> + + + {emotes + .filter( + (emote) => + emote.key && + (searchText.length > 0 + ? emote.key.toLowerCase().includes(searchText.toLowerCase()) || + emote.name.toLowerCase().includes(searchText.toLowerCase()) + : true) && + (filterVisible ? emote.visible : true) && + (filterAudible ? emote.audible : true) && + (filterSound ? emote.sound : true) && + (filterHands ? emote.hands : true) && + (filterUseParams ? emote.use_params : true) + ) + .sort((a, b) => (a.name > b.name ? 1 : -1)) + .map((emote) => ( + + ))} + + +
+
+ ); +}; + +const EmoteIcons = (props, context) => { + const { visible, audible, sound, hands, use_params, margin } = props; + + return ( + + + + + + + + ); +}; + +export const EmotePanel = (props, context) => { + return ( + + + + + + ); +};