diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm
index 009ed44faf3f..e8bc1d954eb8 100644
--- a/code/__DEFINES/admin.dm
+++ b/code/__DEFINES/admin.dm
@@ -69,27 +69,6 @@
#define ADMIN_VERBOSEJMP(src) "[src ? "[AREACOORD(src)] [ADMIN_JMP(src)]" : "nonexistent location"]"
#define ADMIN_INDIVIDUALLOG(user) "(LOGS)"
-#define ADMIN_PUNISHMENT_LIGHTNING "Lightning bolt"
-#define ADMIN_PUNISHMENT_BRAINDAMAGE "Brain damage"
-#define ADMIN_PUNISHMENT_GIB "Gib"
-#define ADMIN_PUNISHMENT_BSA "Bluespace Artillery Device"
-#define ADMIN_PUNISHMENT_FIREBALL "Fireball"
-#define ADMIN_PUNISHMENT_ROD "Immovable Rod"
-#define ADMIN_PUNISHMENT_SUPPLYPOD_QUICK "Supply Pod (Quick)"
-#define ADMIN_PUNISHMENT_SUPPLYPOD "Supply Pod"
-#define ADMIN_PUNISHMENT_MAZING "Puzzle"
-#define ADMIN_PUNISHMENT_PIE "Cream Pie"
-#define ADMIN_PUNISHMENT_CUSTOM_PIE "Custom Cream Pie"
-#define ADMIN_PUNISHMENT_SHOES "Knot Shoes"
-#define ADMIN_PUNISHMENT_CRACK ":B:oneless"
-#define ADMIN_PUNISHMENT_BLEED ":B:loodless"
-#define ADMIN_PUNISHMENT_SCARIFY "Scarify"
-#define ADMIN_PUNISHMENT_PICKLE "Pickle-ify"
-#define ADMIN_PUNISHMENT_FRY "Fry"
-#define ADMIN_PUNISHMENT_PERFORATE ":B:erforate"
-#define ADMIN_PUNISHMENT_CLUWNE "Cluwne"
-#define ADMIN_PUNISHMENT_GOODBYE "Their final message" //sandstorm
-
#define AHELP_ACTIVE 1
#define AHELP_CLOSED 2
#define AHELP_RESOLVED 3
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 41c164b6676b..28e0d9d15988 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -712,3 +712,11 @@
#define COMSIG_ALARM_TRIGGERED "comsig_alarm_triggered"
///Send when an alarm source is cleared (alarm_type, area/source_area)
#define COMSIG_ALARM_CLEARED "comsig_alarm_clear"
+
+/// Admin helps
+/// From /datum/admin_help/RemoveActive().
+/// Fired when an adminhelp is made inactive either due to closing or resolving.
+#define COMSIG_ADMIN_HELP_MADE_INACTIVE "admin_help_made_inactive"
+
+/// Called when the player replies. From /client/proc/cmd_admin_pm().
+#define COMSIG_ADMIN_HELP_REPLIED "admin_help_replied"
diff --git a/code/__DEFINES/layers_planes.dm b/code/__DEFINES/layers_planes.dm
index 578dfe87e565..64d8b5f02cf0 100644
--- a/code/__DEFINES/layers_planes.dm
+++ b/code/__DEFINES/layers_planes.dm
@@ -200,5 +200,8 @@
#define SPLASHSCREEN_PLANE 90
#define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE"
+// Admin popup layer
+#define ADMIN_POPUP_LAYER 1
+
///Layer for screentips
#define SCREENTIP_LAYER 40
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index a1d7705b09e9..633df695c4aa 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -78,11 +78,6 @@
for(var/path in subtypesof(/datum/surgery))
GLOB.surgeries_list += new path()
- //Emotes
- for(var/path in subtypesof(/datum/emote))
- var/datum/emote/E = new path()
- E.emote_list[E.key] = E
-
for(var/path in subtypesof(/datum/bark))
var/datum/bark/B = new path()
GLOB.bark_list[B.id] = path
@@ -96,7 +91,7 @@
// Keybindings
init_keybindings()
-
+ GLOB.emote_list = init_emote_list()
init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes)
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(init_ref_coin_values)) //so the current procedure doesn't sleep because of UNTIL()
diff --git a/code/__SPLURTCODE/DEFINES/admin.dm b/code/__SPLURTCODE/DEFINES/admin.dm
deleted file mode 100644
index b78b257663dc..000000000000
--- a/code/__SPLURTCODE/DEFINES/admin.dm
+++ /dev/null
@@ -1,6 +0,0 @@
-#define ADMIN_PUNISHMENT_TABLETIDESTATIONWIDE "Tabletide Stationwide"
-#define ADMIN_PUNISHMENT_FAKEBWOINK "Fake Bwoink"
-#define ADMIN_PUNISHMENT_NUGGET "Nugget"
-#define ADMIN_PUNISHMENT_BREADIFY ":b:read"
-#define ADMIN_PUNISHMENT_BOOKIFY "Bookify"
-#define ADMIN_PUNISHMENT_BONK "Bonk"
diff --git a/code/_globalvars/lists/admin.dm b/code/_globalvars/lists/admin.dm
new file mode 100644
index 000000000000..9ee6ab6208b4
--- /dev/null
+++ b/code/_globalvars/lists/admin.dm
@@ -0,0 +1,8 @@
+/proc/init_smites()
+ var/list/smites = list()
+ for (var/_smite_path in subtypesof(/datum/smite))
+ var/datum/smite/smite_path = _smite_path
+ smites[initial(smite_path.name)] = smite_path
+ return smites
+
+GLOBAL_LIST_INIT_TYPED(smites, /datum/smite, init_smites())
diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm
index 5cbfd9f21257..07c250d83670 100644
--- a/code/_globalvars/lists/mobs.dm
+++ b/code/_globalvars/lists/mobs.dm
@@ -39,6 +39,8 @@ GLOBAL_LIST_EMPTY(sentient_disease_instances)
GLOBAL_LIST_EMPTY(latejoin_ai_cores)
+GLOBAL_LIST_EMPTY(emote_list)
+
GLOBAL_LIST_EMPTY(mob_config_movespeed_type_lookup)
GLOBAL_LIST_EMPTY(mob_config_movespeed_type_lookup_floating)
@@ -99,6 +101,24 @@ GLOBAL_LIST_EMPTY(pre_setup_antags) //minds that have been picked as antag by th
var/mob/M = i
M.update_config_movespeed()
+/proc/init_emote_list()
+ . = list()
+ for(var/path in subtypesof(/datum/emote))
+ var/datum/emote/E = new path()
+ if(E.key)
+ if(!.[E.key])
+ .[E.key] = list(E)
+ else
+ .[E.key] += E
+ else if(E.message) //Assuming all non-base emotes have this
+ stack_trace("Keyless emote: [E.type]")
+
+ if(E.key_third_person) //This one is optional
+ if(!.[E.key_third_person])
+ .[E.key_third_person] = list(E)
+ else
+ .[E.key_third_person] |= E
+
//blood types
GLOBAL_LIST_INIT(regular_bloods,list(
"O-",
diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm
index 64be4216ffcb..94941509a73f 100644
--- a/code/controllers/configuration/entries/general.dm
+++ b/code/controllers/configuration/entries/general.dm
@@ -349,3 +349,6 @@
default = list()
/datum/config_entry/flag/toast_notification_on_init
+
+/// Gives the ability to send players a maptext popup.
+/datum/config_entry/flag/popup_admin_pm
diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm
index 529f9dee5c3c..2725a71eebc5 100644
--- a/code/controllers/subsystem/traumas.dm
+++ b/code/controllers/subsystem/traumas.dm
@@ -39,7 +39,8 @@ SUBSYSTEM_DEF(traumas)
"mimes" = strings(PHOBIA_FILE, "mimes"),
"cats" = strings(PHOBIA_FILE, "cats"),
"syndicate"= strings(PHOBIA_FILE, "syndicate"),
- "eye" = strings(PHOBIA_FILE, "eye")
+ "eye" = strings(PHOBIA_FILE, "eye"),
+ "ocky icky" = strings(PHOBIA_FILE, "ocky icky")
)
phobia_mobs = list("spiders" = typecacheof(list(/mob/living/simple_animal/hostile/poison/giant_spider)),
diff --git a/code/datums/brain_damage/phobia.dm b/code/datums/brain_damage/phobia.dm
index 10c217c6a9cc..4dbe2d507a59 100644
--- a/code/datums/brain_damage/phobia.dm
+++ b/code/datums/brain_damage/phobia.dm
@@ -213,3 +213,7 @@
/datum/brain_trauma/mild/phobia/conspiracies
phobia_type = "conspiracies"
random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/ocky_icky
+ phobia_type = "ocky icky"
+ random_gain = FALSE
diff --git a/code/datums/components/admin_popup.dm b/code/datums/components/admin_popup.dm
new file mode 100644
index 000000000000..0542dd1a0ccf
--- /dev/null
+++ b/code/datums/components/admin_popup.dm
@@ -0,0 +1,125 @@
+/// Applied to clients when they receive an admin popup, alerting them to
+/// their ticket.
+/datum/component/admin_popup
+ /// The user's most active ticket. If this is resolved, closed, or replied to,
+ /// then the component will delete itself.
+ var/datum/admin_help/ticket
+
+ var/atom/movable/screen/admin_popup/admin_popup
+
+/datum/component/admin_popup/Initialize(datum/admin_help/ticket)
+ if (!istype(parent, /client))
+ return COMPONENT_INCOMPATIBLE
+
+ if (!istype(ticket))
+ return COMPONENT_INCOMPATIBLE
+
+ create_notice()
+
+ RegisterSignal(
+ ticket,
+ list(
+ COMSIG_ADMIN_HELP_MADE_INACTIVE,
+ COMSIG_ADMIN_HELP_REPLIED,
+ COMSIG_PARENT_QDELETING,
+ ),
+ PROC_REF(delete_self),
+ )
+
+/datum/component/admin_popup/Destroy(force)
+ var/client/parent_client = parent
+
+ parent_client?.screen -= admin_popup
+ QDEL_NULL(admin_popup)
+
+ if (!QDELETED(ticket))
+ UnregisterSignal(ticket, list(
+ COMSIG_ADMIN_HELP_MADE_INACTIVE,
+ COMSIG_ADMIN_HELP_REPLIED,
+ COMSIG_PARENT_QDELETING,
+ ))
+
+ ticket = null
+
+ return ..()
+
+/datum/component/admin_popup/proc/create_notice()
+ if(admin_popup)
+ qdel(admin_popup)
+ admin_popup = new
+
+ var/client/parent_client = parent
+ admin_popup.maptext_width = view_to_pixels(parent_client.view_size.getView())[1]
+ parent_client.screen += admin_popup
+
+/datum/component/admin_popup/proc/delete_self()
+ SIGNAL_HANDLER
+ qdel(src)
+
+/// The UI element for admin popups
+/atom/movable/screen/admin_popup
+ icon = null
+ icon_state = null
+ plane = ABOVE_HUD_PLANE
+ layer = ADMIN_POPUP_LAYER
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ screen_loc = "TOP-5,LEFT"
+ maptext_height = 480
+ maptext_width = 480
+ maptext = ""
+
+ var/static/list/colors = list(
+ COLOR_RED,
+ COLOR_ORANGE,
+ COLOR_YELLOW,
+ COLOR_LIME,
+ COLOR_CYAN,
+ COLOR_PURPLE,
+ )
+
+ /// The last color chosen in the animation, sourced from the static list colors.
+ var/last_color_index = 0
+
+ /// The `world.time` when the last color update occurred.
+ var/last_update_time = 0
+
+/atom/movable/screen/admin_popup/Initialize(mapload, datum/hud/hud_owner, ...)
+ . = ..()
+
+ START_PROCESSING(SSobj, src)
+ update_text()
+
+/atom/movable/screen/admin_popup/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/atom/movable/screen/admin_popup/process(seconds_per_tick)
+ update_text()
+
+/atom/movable/screen/admin_popup/proc/update_text()
+ // Even if processing time changes, we want this to remain slow.
+ // We want to pester them into reading their ticket, not give them a seizure!
+ if (world.time - last_update_time < 2 SECONDS)
+ return
+
+ last_color_index = (last_color_index % colors.len) + 1
+
+ var/message = ""
+ message += "HEY!
An admin is trying to talk to you!
Check your chat window,
and click their name to respond!"
+ message += ""
+
+ maptext = MAPTEXT(message)
+ last_update_time = world.time
+
+/// Tries to give the target an admin popup.
+/// If it fails, will send the error to the passed admin.
+/proc/give_admin_popup(client/target, client/admin, message)
+ log_admin("[key_name(admin)] sent an admin popup to [key_name(target)].")
+
+ var/datum/admin_help/current_ticket = target.current_ticket
+ if (!current_ticket)
+ to_chat(admin, span_warning("[key_name(target)] had no active ahelp, aborting."))
+ return
+
+ admin.cmd_admin_pm(target, message)
+ target.AddComponent(/datum/component/admin_popup, current_ticket)
diff --git a/code/datums/components/manual_blinking.dm b/code/datums/components/manual_blinking.dm
new file mode 100644
index 000000000000..d5afbcabdc60
--- /dev/null
+++ b/code/datums/components/manual_blinking.dm
@@ -0,0 +1,83 @@
+/datum/component/manual_blinking
+ dupe_mode = COMPONENT_DUPE_UNIQUE
+
+ var/obj/item/organ/eyes/E
+ var/warn_grace = FALSE
+ var/warn_dying = FALSE
+ var/last_blink
+ var/check_every = 20 SECONDS
+ var/grace_period = 6 SECONDS
+ var/damage_rate = 1 // organ damage taken per tick
+ var/list/valid_emotes = list(/datum/emote/living/carbon/blink, /datum/emote/living/carbon/blink_r)
+
+/datum/component/manual_blinking/Initialize()
+ if(!iscarbon(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ var/mob/living/carbon/C = parent
+ E = C.getorganslot(ORGAN_SLOT_EYES)
+
+ if(E)
+ START_PROCESSING(SSdcs, src)
+ last_blink = world.time
+ to_chat(C, "You suddenly realize you're blinking manually.")
+
+/datum/component/manual_blinking/Destroy(force, silent)
+ E = null
+ STOP_PROCESSING(SSdcs, src)
+ to_chat(parent, "You revert back to automatic blinking.")
+ return ..()
+
+/datum/component/manual_blinking/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_MOB_EMOTE, .proc/check_emote)
+ RegisterSignal(parent, COMSIG_ORGAN_INSERTED, .proc/check_added_organ)
+ RegisterSignal(parent, COMSIG_ORGAN_REMOVED, .proc/check_removed_organ)
+ RegisterSignal(parent, COMSIG_LIVING_REVIVE, .proc/restart)
+ RegisterSignal(parent, COMSIG_MOB_DEATH, .proc/pause)
+
+/datum/component/manual_blinking/UnregisterFromParent()
+ UnregisterSignal(parent, COMSIG_MOB_EMOTE)
+ UnregisterSignal(parent, COMSIG_ORGAN_INSERTED)
+ UnregisterSignal(parent, COMSIG_ORGAN_REMOVED)
+ UnregisterSignal(parent, COMSIG_LIVING_REVIVE)
+ UnregisterSignal(parent, COMSIG_MOB_DEATH)
+
+/datum/component/manual_blinking/proc/restart()
+ START_PROCESSING(SSdcs, src)
+
+/datum/component/manual_blinking/proc/pause()
+ STOP_PROCESSING(SSdcs, src)
+
+/datum/component/manual_blinking/process()
+ var/mob/living/carbon/C = parent
+
+ if(world.time > (last_blink + check_every + grace_period))
+ if(!warn_dying)
+ to_chat(C, "Your eyes begin to wither, you need to blink!")
+ warn_dying = TRUE
+
+ E.applyOrganDamage(damage_rate)
+ else if(world.time > (last_blink + check_every))
+ if(!warn_grace)
+ to_chat(C, "You feel a need to blink!")
+ warn_grace = TRUE
+
+/datum/component/manual_blinking/proc/check_added_organ(mob/who_cares, obj/item/organ/O)
+ var/obj/item/organ/eyes/new_eyes = O
+
+ if(istype(new_eyes,/obj/item/organ/eyes))
+ E = new_eyes
+ START_PROCESSING(SSdcs, src)
+
+/datum/component/manual_blinking/proc/check_removed_organ(mob/who_cares, obj/item/organ/O)
+ var/obj/item/organ/eyes/bye_beyes = O // oh come on, that's pretty good
+
+ if(istype(bye_beyes, /obj/item/organ/eyes))
+ E = null
+ STOP_PROCESSING(SSdcs, src)
+
+/datum/component/manual_blinking/proc/check_emote(mob/living/carbon/user, datum/emote/emote)
+ if(emote.type in valid_emotes)
+ warn_grace = FALSE
+ warn_dying = FALSE
+ last_blink = world.time
diff --git a/code/datums/components/manual_breathing.dm b/code/datums/components/manual_breathing.dm
new file mode 100644
index 000000000000..45155285bf0c
--- /dev/null
+++ b/code/datums/components/manual_breathing.dm
@@ -0,0 +1,93 @@
+/datum/component/manual_breathing
+ dupe_mode = COMPONENT_DUPE_UNIQUE
+
+ var/obj/item/organ/lungs/L
+ var/warn_grace = FALSE
+ var/warn_dying = FALSE
+ var/last_breath
+ var/check_every = 12 SECONDS
+ var/grace_period = 6 SECONDS
+ var/damage_rate = 1 // organ damage taken per tick
+ var/datum/emote/next_breath_type = /datum/emote/inhale
+
+/datum/component/manual_breathing/Initialize()
+ if(!iscarbon(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ var/mob/living/carbon/C = parent
+ L = C.getorganslot(ORGAN_SLOT_LUNGS)
+
+ if(L)
+ START_PROCESSING(SSdcs, src)
+ last_breath = world.time
+ to_chat(C, "You suddenly realize you're breathing manually.")
+
+/datum/component/manual_breathing/Destroy(force, silent)
+ L = null
+ STOP_PROCESSING(SSdcs, src)
+ to_chat(parent, "You revert back to automatic breathing.")
+ return ..()
+
+/datum/component/manual_breathing/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_MOB_EMOTE, .proc/check_emote)
+ RegisterSignal(parent, COMSIG_ORGAN_INSERTED, .proc/check_added_organ)
+ RegisterSignal(parent, COMSIG_ORGAN_REMOVED, .proc/check_removed_organ)
+ RegisterSignal(parent, COMSIG_LIVING_REVIVE, .proc/restart)
+ RegisterSignal(parent, COMSIG_MOB_DEATH, .proc/pause)
+
+/datum/component/manual_breathing/UnregisterFromParent()
+ UnregisterSignal(parent, COMSIG_MOB_EMOTE)
+ UnregisterSignal(parent, COMSIG_ORGAN_INSERTED)
+ UnregisterSignal(parent, COMSIG_ORGAN_REMOVED)
+ UnregisterSignal(parent, COMSIG_LIVING_REVIVE)
+ UnregisterSignal(parent, COMSIG_MOB_DEATH)
+
+/datum/component/manual_breathing/proc/restart()
+ START_PROCESSING(SSdcs, src)
+
+/datum/component/manual_breathing/proc/pause()
+ STOP_PROCESSING(SSdcs, src)
+
+/datum/component/manual_breathing/process()
+ var/mob/living/carbon/C = parent
+
+ var/next_text = initial(next_breath_type.key)
+ if(world.time > (last_breath + check_every + grace_period))
+ if(!warn_dying)
+ to_chat(C, "You begin to suffocate, you need to [next_text]!")
+ warn_dying = TRUE
+
+ L.applyOrganDamage(damage_rate)
+ C.losebreath += 0.8
+ else if(world.time > (last_breath + check_every))
+ if(!warn_grace)
+ to_chat(C, "You feel a need to [next_text]!")
+ warn_grace = TRUE
+
+/datum/component/manual_breathing/proc/check_added_organ(mob/who_cares, obj/item/organ/O)
+ var/obj/item/organ/eyes/new_lungs = O
+
+ if(istype(new_lungs,/obj/item/organ/lungs))
+ L = new_lungs
+ START_PROCESSING(SSdcs, src)
+
+/datum/component/manual_breathing/proc/check_removed_organ(mob/who_cares, obj/item/organ/O)
+ var/obj/item/organ/lungs/old_lungs = O
+
+ if(istype(old_lungs, /obj/item/organ/lungs))
+ L = null
+ STOP_PROCESSING(SSdcs, src)
+
+/datum/component/manual_breathing/proc/check_emote(mob/living/carbon/user, datum/emote/emote)
+ if(emote.type == next_breath_type)
+ if(next_breath_type == /datum/emote/inhale)
+ next_breath_type = /datum/emote/exhale
+ else
+ next_breath_type = /datum/emote/inhale
+
+ warn_grace = FALSE
+ warn_dying = FALSE
+ last_breath = world.time
+
+ var/mob/living/carbon/C = parent
+ C.losebreath = max(0, C.losebreath - 0.4)
diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm
index e5a453b2e866..a26e345e957e 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
@@ -11,21 +12,19 @@
var/message_simple = "" //Message to display if the user is a simple_animal
var/message_param = "" //Message to display if a param was given
var/emote_type = EMOTE_VISIBLE //Whether the emote is visible or audible
+ var/sound
var/restraint_check = FALSE //Checks if the mob is restrained before performing the emote
var/muzzle_ignore = FALSE //Will only work if the emote is EMOTE_AUDIBLE
var/list/mob_type_allowed_typecache = /mob //Types that are allowed to use that emote
var/list/mob_type_blacklist_typecache //Types that are NOT allowed to use that emote
var/list/mob_type_ignore_stat_typecache
var/stat_allowed = CONSCIOUS
- var/static/list/emote_list = list()
var/static/regex/stop_bad_mime = regex(@"says|exclaims|yells|asks")
var/chat_popup = TRUE //Skyrat edit
var/image_popup
/datum/emote/New()
- if(key_third_person)
- emote_list[key_third_person] = src
if (ispath(mob_type_allowed_typecache))
switch (mob_type_allowed_typecache)
if (/mob)
@@ -39,6 +38,9 @@
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)
. = TRUE
if(!can_run_emote(user, TRUE, intentional))
@@ -81,6 +83,9 @@
flick_emote_popup_on_mob(user, image_popup, 40)
//End of skyrat changes
+/datum/emote/proc/get_sound(mob/living/user)
+ return sound //by default just return this var.
+
/datum/emote/proc/replace_pronoun(mob/user, message)
if(findtext(message, "their"))
message = replacetext(message, "their", user.p_their())
@@ -149,12 +154,61 @@
return FALSE
/datum/emote/sound
- var/sound //Sound to play when emote is called
var/vary = FALSE //used for the honk borg emote
var/volume = 50
+ // Default time before using another audio emote
+ var/emote_cooldown = 1 SECONDS
+
+ // Default volume of the emote
+ var/emote_volume = 50
+
+ // Default range modifier
+ var/emote_range = -1
+ var/emote_distance_multiplier = SOUND_DEFAULT_DISTANCE_MULTIPLIER
+ var/emote_distance_multiplier_min_range = SOUND_DEFAULT_MULTIPLIER_EFFECT_RANGE
+
+ // Default pitch variance
+ var/emote_pitch_variance = 1
+
+ // Default audio falloff settings
+ var/emote_falloff_exponent = SOUND_FALLOFF_EXPONENT
+ var/emote_falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE
+
+ // Default frequency
+ var/emote_frequency = null
+
+ // Default channel
+ var/emote_channel = 0
+
+ // Should the emote consider atmospheric pressure?
+ var/emote_check_pressure = TRUE
+
+ // Should the emote ignore walls?
+ var/emote_ignore_walls = FALSE
+
+ // Default wet and dry settings (???)
+ var/emote_wetness = -10000
+ var/emote_dryness = 0
mob_type_allowed_typecache = list(/mob/living/brain, /mob/living/silicon, /mob/camera/aiEye)
+/datum/emote/sound/can_run_emote(mob/living/user, status_check, intentional = FALSE)
+ . = ..()
+
+ // Check parent return
+ if(!.)
+ return FALSE
+
+ // Check cooldown
+ if(user?.nextsoundemote >= world.time)
+ return FALSE
+
+ // Allow use
+ return TRUE
+
/datum/emote/sound/run_emote(mob/user, params)
. = ..()
if(.)
- playsound(user.loc, sound, volume, vary)
+ playsound(user.loc, sound, emote_volume, emote_pitch_variance, emote_range, emote_falloff_exponent, emote_frequency, emote_channel, emote_check_pressure, emote_ignore_walls, emote_falloff_distance, emote_wetness, emote_dryness, emote_distance_multiplier, emote_distance_multiplier_min_range)
+
+ //Cooldown.
+ user.nextsoundemote = world.time + emote_cooldown
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 68ebc567d123..cf59117895de 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1229,9 +1229,9 @@
if(obj_integrity < max_integrity)
if(!W.tool_start_check(user, amount=0))
return
- user.visible_message("[user] чинит шлюз сваркой.", \
- "Вы начинаете чинить шлюз...", \
- "Вы слышите звук сварки.")
+ user.visible_message("[user] is welding the airlock.", \
+ "You begin repairing the airlock...", \
+ "You hear welding.")
if(W.use_tool(src, user, 40, volume=50, extra_checks = CALLBACK(src, PROC_REF(weld_checks), W, user)))
obj_integrity = max_integrity
machine_stat &= ~BROKEN
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 7a8ea640c941..53b00e7c5f83 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -30,6 +30,7 @@ GLOBAL_PROTECT(admin_verbs_admin)
// /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage
/datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/
/datum/verbs/menu/Admin/verb/playerpanel,
+ /client/proc/cmd_admin_rejuvenate, // SPLURT EDIT
/client/proc/game_panel, /*game panel, allows to change game-mode etc*/
/client/proc/check_ai_laws, /*shows AI and borg laws*/
// /client/proc/ghost_pool_protection, /*opens a menu for toggling ghost roles*/
@@ -238,6 +239,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
/client/proc/toggle_view_range,
/client/proc/cmd_admin_check_contents,
/datum/admins/proc/access_news_network,
+ /client/proc/cmd_admin_rejuvenate, // SPLURT EDIT
/client/proc/admin_end_shift,
/client/proc/admin_call_shuttle,
/client/proc/admin_cancel_shuttle,
diff --git a/code/modules/admin/smites/berforate.dm b/code/modules/admin/smites/berforate.dm
new file mode 100644
index 000000000000..b8b4e2f8c792
--- /dev/null
+++ b/code/modules/admin/smites/berforate.dm
@@ -0,0 +1,46 @@
+/// Fires an absurd amount of bullets at the target
+/datum/smite/berforate
+ name = ":B:erforate"
+ /// Determines how fucked the target is
+ var/hatred
+/datum/smite/berforate/configure(client/user)
+ var/static/list/how_fucked_is_this_dude = list("A little", "A lot", "So fucking much", "FUCK THIS DUDE")
+ hatred = input(user, "How much do you hate this guy?") in how_fucked_is_this_dude
+/datum/smite/berforate/effect(client/user, mob/living/target)
+ . = ..()
+ if (!iscarbon(target))
+ to_chat(user, "This must be used on a carbon mob.", confidential = TRUE)
+ return
+ var/repetitions
+ var/shots_per_limb_per_rep = 2
+ var/damage
+ switch (hatred)
+ if ("A little")
+ repetitions = 1
+ damage = 5
+ if ("A lot")
+ repetitions = 2
+ damage = 8
+ if ("So fucking much")
+ repetitions = 3
+ damage = 10
+ if ("FUCK THIS DUDE")
+ repetitions = 4
+ damage = 10
+ var/mob/living/carbon/dude = target
+ var/list/open_adj_turfs = get_adjacent_open_turfs(dude)
+ var/list/wound_bonuses = list(15, 70, 110, 250)
+ var/delay_per_shot = 1
+ var/delay_counter = 1
+ dude.Immobilize(5 SECONDS)
+ for (var/wound_bonus_rep in 1 to repetitions)
+ for (var/_limb in dude.bodyparts)
+ var/obj/item/bodypart/limb = _limb
+ var/shots_this_limb = 0
+ for (var/_iter_turf in shuffle(open_adj_turfs))
+ var/turf/iter_turf = _iter_turf
+ addtimer(CALLBACK(GLOBAL_PROC, .proc/firing_squad, dude, iter_turf, limb.body_zone, wound_bonuses[wound_bonus_rep], damage), delay_counter)
+ delay_counter += delay_per_shot
+ shots_this_limb += 1
+ if (shots_this_limb > shots_per_limb_per_rep)
+ break
diff --git a/code/modules/admin/smites/bloodless.dm b/code/modules/admin/smites/bloodless.dm
new file mode 100644
index 000000000000..68b67e7c1371
--- /dev/null
+++ b/code/modules/admin/smites/bloodless.dm
@@ -0,0 +1,17 @@
+/// Slashes up the target
+/datum/smite/bloodless
+ name = ":B:loodless"
+/datum/smite/bloodless/effect(client/user, mob/living/target)
+ . = ..()
+ if(!iscarbon(target))
+ to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE)
+ return
+ var/mob/living/carbon/carbon_target = target
+ for(var/_limb in carbon_target.bodyparts)
+ var/obj/item/bodypart/limb = _limb
+ var/type_wound = pick(list(/datum/wound/slash/severe, /datum/wound/slash/moderate))
+ limb.force_wound_upwards(type_wound, smited = TRUE)
+ type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate))
+ limb.force_wound_upwards(type_wound, smited = TRUE)
+ type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe))
+ limb.force_wound_upwards(type_wound, smited = TRUE)
diff --git a/code/modules/admin/smites/boneless.dm b/code/modules/admin/smites/boneless.dm
new file mode 100644
index 000000000000..6d35508f3981
--- /dev/null
+++ b/code/modules/admin/smites/boneless.dm
@@ -0,0 +1,13 @@
+/// Gives the target critically bad wounds
+/datum/smite/boneless
+ name = ":B:oneless"
+/datum/smite/boneless/effect(client/user, mob/living/target)
+ . = ..()
+ if (!iscarbon(target))
+ to_chat(user, "This must be used on a carbon mob.", confidential = TRUE)
+ return
+ var/mob/living/carbon/carbon_target = target
+ for(var/_limb in carbon_target.bodyparts)
+ var/obj/item/bodypart/limb = _limb
+ var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate))
+ limb.force_wound_upwards(type_wound, smited = TRUE)
diff --git a/code/modules/admin/smites/bonk.dm b/code/modules/admin/smites/bonk.dm
new file mode 100644
index 000000000000..9921f21a7fdd
--- /dev/null
+++ b/code/modules/admin/smites/bonk.dm
@@ -0,0 +1,9 @@
+/// Bonks the target
+/datum/smite/bonk
+ name = "Bonk"
+
+/datum/smite/bonk/effect(client/user, mob/living/target)
+ . = ..()
+ playsound(target, 'modular_splurt/sound/misc/bonk.ogg', 100, 1)
+ target.AddElement(/datum/element/squish, 60 SECONDS)
+ to_chat(target, "Bonk.")
diff --git a/code/modules/admin/smites/bookify.dm b/code/modules/admin/smites/bookify.dm
new file mode 100644
index 000000000000..eba95af53865
--- /dev/null
+++ b/code/modules/admin/smites/bookify.dm
@@ -0,0 +1,13 @@
+#define BOOKIFY_TIME (2 SECONDS)
+/// Turns the target into a book
+/datum/smite/bookify
+ name = "Bookify"
+
+/datum/smite/bookify/effect(client/user, mob/living/carbon/human/target as mob)
+ . = ..()
+ var/mutable_appearance/book_appearance = mutable_appearance('icons/obj/library.dmi', "book")
+ var/mutable_appearance/transform_scanline = mutable_appearance('modular_splurt/icons/effects/effects.dmi', "transform_effect")
+ target.transformation_animation(book_appearance, time = BOOKIFY_TIME, transform_overlay=transform_scanline, reset_after=TRUE)
+ addtimer(CALLBACK(GLOBAL_PROC, .proc/bookify, target), BOOKIFY_TIME)
+ playsound(target, 'modular_splurt/sound/misc/bookify.ogg', 60, 1)
+#undef BOOKIFY_TIME
diff --git a/code/modules/admin/smites/brain_damage.dm b/code/modules/admin/smites/brain_damage.dm
new file mode 100644
index 000000000000..ce7d6ae47841
--- /dev/null
+++ b/code/modules/admin/smites/brain_damage.dm
@@ -0,0 +1,6 @@
+/// Inflicts crippling brain damage on the target
+/datum/smite/brain_damage
+ name = "Brain damage"
+/datum/smite/brain_damage/effect(client/user, mob/living/target)
+ . = ..()
+ target.adjustOrganLoss(ORGAN_SLOT_BRAIN, BRAIN_DAMAGE_DEATH - 1, BRAIN_DAMAGE_DEATH - 1)
diff --git a/code/modules/admin/smites/bread.dm b/code/modules/admin/smites/bread.dm
new file mode 100644
index 000000000000..a92c5c8e2745
--- /dev/null
+++ b/code/modules/admin/smites/bread.dm
@@ -0,0 +1,14 @@
+#define BREADIFY_TIME (5 SECONDS)
+
+/// Turns the target into bread
+/datum/smite/bread
+ name = "Bread"
+
+/datum/smite/bread/effect(client/user, mob/living/target)
+ . = ..()
+ var/mutable_appearance/bread_appearance = mutable_appearance('icons/obj/food/burgerbread.dmi', "bread")
+ var/mutable_appearance/transform_scanline = mutable_appearance('modular_splurt/icons/effects/effects.dmi', "transform_effect")
+ target.transformation_animation(bread_appearance,time = BREADIFY_TIME, transform_overlay=transform_scanline, reset_after=TRUE)
+ addtimer(CALLBACK(GLOBAL_PROC, .proc/breadify, target), BREADIFY_TIME)
+
+#undef BREADIFY_TIME
diff --git a/code/modules/admin/smites/bsa.dm b/code/modules/admin/smites/bsa.dm
new file mode 100644
index 000000000000..fa89af32e766
--- /dev/null
+++ b/code/modules/admin/smites/bsa.dm
@@ -0,0 +1,32 @@
+#define BSA_CHANCE_TO_BREAK_TILE_TO_PLATING 80
+#define BSA_MAX_DAMAGE 99
+#define BSA_PARALYZE_TIME (40 SECONDS)
+#define BSA_STUTTER_TIME (40 SECONDS)
+
+/// Fires the BSA at the target
+/datum/smite/bsa
+ name = "Bluespace Artillery Device"
+
+/datum/smite/bsa/effect(client/user, mob/living/target)
+ . = ..()
+
+ explosion(target.loc, 0, 0, 0, 0)
+
+ var/turf/open/floor/target_turf = get_turf(target)
+ if (istype(target_turf))
+ if (prob(BSA_CHANCE_TO_BREAK_TILE_TO_PLATING))
+ target_turf.break_tile_to_plating()
+ else
+ target_turf.break_tile()
+
+ if (target.health <= 1)
+ target.gib(1, 1)
+ else
+ target.adjustBruteLoss(min(BSA_MAX_DAMAGE, target.health - 1))
+ target.DefaultCombatKnockdown(BSA_PARALYZE_TIME)
+ target.stuttering = 20
+
+#undef BSA_CHANCE_TO_BREAK_TILE_TO_PLATING
+#undef BSA_MAX_DAMAGE
+#undef BSA_PARALYZE_TIME
+#undef BSA_STUTTER_TIME
diff --git a/code/modules/admin/smites/cluwne.dm b/code/modules/admin/smites/cluwne.dm
new file mode 100644
index 000000000000..a097a0f16af3
--- /dev/null
+++ b/code/modules/admin/smites/cluwne.dm
@@ -0,0 +1,10 @@
+/// Cluwneifies the target
+/datum/smite/cluwne
+ name = "Cluwne"
+
+/datum/smite/cluwne/effect(client/user, mob/living/carbon/human/target as mob)
+ . = ..()
+ if(!iscarbon(target))
+ to_chat(usr,"This must be used on a carbon mob.")
+ return
+ target.cluwneify()
diff --git a/code/modules/admin/smites/custompie.dm b/code/modules/admin/smites/custompie.dm
new file mode 100644
index 000000000000..890907ecfc5a
--- /dev/null
+++ b/code/modules/admin/smites/custompie.dm
@@ -0,0 +1,18 @@
+/// Throws a custom pie at the target
+/datum/smite/custompie
+ name = "Custom Pie"
+
+/datum/smite/custompie/effect(client/user, mob/living/target)
+ . = ..()
+ var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new()
+ if(!A.reagents)
+ var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num|null
+ if(amount)
+ A.create_reagents(amount)
+ if(A.reagents)
+ var/chosen_id = choose_reagent_id(usr)
+ if(chosen_id)
+ var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num|null
+ if(amount)
+ A.reagents.add_reagent(chosen_id, amount)
+ A.splat(target)
diff --git a/code/modules/admin/smites/dock_pay.dm b/code/modules/admin/smites/dock_pay.dm
new file mode 100644
index 000000000000..0ce91bbd4b70
--- /dev/null
+++ b/code/modules/admin/smites/dock_pay.dm
@@ -0,0 +1,31 @@
+/// Docks the target's pay
+/datum/smite/dock_pay
+ name = "Dock Pay"
+
+/datum/smite/dock_pay/effect(client/user, mob/living/target)
+ . = ..()
+ if (!iscarbon(target))
+ to_chat(user, span_warning("This must be used on a carbon mob."), confidential = TRUE)
+ return
+ var/mob/living/carbon/dude = target
+ var/obj/item/card/id/card = dude.get_idcard(TRUE)
+ if (!card)
+ to_chat(user, span_warning("[dude] does not have an ID card on!"), confidential = TRUE)
+ return
+ if (!card.registered_account)
+ to_chat(user, span_warning("[dude] does not have an ID card with an account!"), confidential = TRUE)
+ return
+ if (card.registered_account.account_balance == 0)
+ to_chat(user, span_warning("ID Card lacks any funds. No pay to dock."))
+ return
+ var/new_cost = input("How much pay are we docking? Current balance: [card.registered_account.account_balance] credits.", "BUDGET CUTS") as num|null
+ if (!new_cost)
+ return
+ if (!(card.registered_account.has_money(new_cost)))
+ to_chat(user, span_warning("ID Card lacked funds. Emptying account."))
+ card.registered_account.bank_card_talk("[new_cost] credits deducted from your account based on performance review.")
+ card.registered_account.account_balance = 0
+ else
+ card.registered_account.account_balance = card.registered_account.account_balance - new_cost
+ card.registered_account.bank_card_talk("[new_cost] credits deducted from your account based on performance review.")
+ SEND_SOUND(target, 'sound/machines/buzz-sigh.ogg')
diff --git a/code/modules/admin/smites/fake_bwoink.dm b/code/modules/admin/smites/fake_bwoink.dm
new file mode 100644
index 000000000000..a4179ff5ce82
--- /dev/null
+++ b/code/modules/admin/smites/fake_bwoink.dm
@@ -0,0 +1,7 @@
+/// Sends the target a fake adminhelp sound
+/datum/smite/fake_bwoink
+ name = "Fake bwoink"
+
+/datum/smite/fake_bwoink/effect(client/user, mob/living/target)
+ . = ..()
+ SEND_SOUND(target, 'sound/effects/adminhelp.ogg')
diff --git a/code/modules/admin/smites/finalmessage.dm b/code/modules/admin/smites/finalmessage.dm
new file mode 100644
index 000000000000..b5fdbfeb0b03
--- /dev/null
+++ b/code/modules/admin/smites/finalmessage.dm
@@ -0,0 +1,12 @@
+/// Their Final Message
+/datum/smite/finalmessage
+ name = "Final Message"
+
+/datum/smite/finalmessage/effect(client/user, mob/living/target)
+ . = ..()
+ var/mob/living/C = target
+ if(C.stat == DEAD)
+ to_chat(usr, "[C] is dead!")
+ return
+ else
+ C.goodbye()
diff --git a/code/modules/admin/smites/fireball.dm b/code/modules/admin/smites/fireball.dm
new file mode 100644
index 000000000000..98dad65d8251
--- /dev/null
+++ b/code/modules/admin/smites/fireball.dm
@@ -0,0 +1,7 @@
+/// Throws a fireball down at the target
+/datum/smite/fireball
+ name = "Fireball"
+
+/datum/smite/fireball/effect(client/user, mob/living/target)
+ . = ..()
+ new /obj/effect/temp_visual/target(get_turf(target))
diff --git a/code/modules/admin/smites/fry.dm b/code/modules/admin/smites/fry.dm
new file mode 100644
index 000000000000..66a4100f1031
--- /dev/null
+++ b/code/modules/admin/smites/fry.dm
@@ -0,0 +1,7 @@
+/// Fry the target
+/datum/smite/fry
+ name = "Fry"
+
+/datum/smite/fry/effect(client/user, mob/living/target)
+ . = ..()
+ target.fry()
diff --git a/code/modules/admin/smites/gib.dm b/code/modules/admin/smites/gib.dm
new file mode 100644
index 000000000000..37f1e1c8b498
--- /dev/null
+++ b/code/modules/admin/smites/gib.dm
@@ -0,0 +1,7 @@
+/// Gibs the target
+/datum/smite/gib
+ name = "Gib"
+
+/datum/smite/gib/effect(client/user, mob/living/target)
+ . = ..()
+ target.gib(FALSE)
diff --git a/code/modules/admin/smites/immerse.dm b/code/modules/admin/smites/immerse.dm
new file mode 100644
index 000000000000..9cdd8aca95ec
--- /dev/null
+++ b/code/modules/admin/smites/immerse.dm
@@ -0,0 +1,9 @@
+/// "Fully immerses" the player, making them manually breathe and blink
+/datum/smite/immerse
+ name = "Fully Immerse"
+
+/datum/smite/immerse/effect(client/user, mob/living/target)
+ . = ..()
+ immerse_player(target)
+ SEND_SOUND(target, sound('sound/misc/roleplay.ogg'))
+ to_chat(target, span_boldnotice("Please roleplay appropriately, okay?"))
diff --git a/code/modules/admin/smites/knot_shoes.dm b/code/modules/admin/smites/knot_shoes.dm
new file mode 100644
index 000000000000..057dbd743607
--- /dev/null
+++ b/code/modules/admin/smites/knot_shoes.dm
@@ -0,0 +1,15 @@
+/// Ties the target's shoes
+/datum/smite/knot_shoes
+ name = "Knot Shoes"
+
+/datum/smite/knot_shoes/effect(client/user, mob/living/target)
+ . = ..()
+ if (!iscarbon(target))
+ to_chat(user, span_warning("This must be used on a carbon mob."), confidential = TRUE)
+ return
+ var/mob/living/carbon/dude = target
+ var/obj/item/clothing/shoes/sick_kicks = dude.shoes
+ if (!sick_kicks?.can_be_tied)
+ to_chat(user, span_warning("[dude] does not have knottable shoes!"), confidential = TRUE)
+ return
+ sick_kicks.adjust_laces(SHOES_KNOTTED)
diff --git a/code/modules/admin/smites/lightning.dm b/code/modules/admin/smites/lightning.dm
new file mode 100644
index 000000000000..93527fad8b9e
--- /dev/null
+++ b/code/modules/admin/smites/lightning.dm
@@ -0,0 +1,20 @@
+/// Strikes the target with a lightning bolt
+/datum/smite/lightning
+ name = "Lightning bolt"
+
+/datum/smite/lightning/effect(client/user, mob/living/target)
+ . = ..()
+ lightningbolt(target)
+ to_chat(target, "The gods have punished you for your sins!")
+
+///this is the actual bolt effect and damage, made into its own proc because it is used elsewhere
+/proc/lightningbolt(mob/living/user)
+ playsound(get_turf(user), 'modular_splurt/sound/misc/NOW.ogg', 75, FALSE)
+ sleep(4 SECONDS)
+ var/turf/T = get_step(get_step(user, NORTH), NORTH)
+ T.Beam(user, icon_state="lightning[rand(1,12)]", time = 5)
+ user.adjustFireLoss(75)
+ if(ishuman(user))
+ var/mob/living/carbon/human/human_target = user
+ human_target.electrocution_animation(40)
+
diff --git a/code/modules/admin/smites/nugget.dm b/code/modules/admin/smites/nugget.dm
new file mode 100644
index 000000000000..86fd9af9cf50
--- /dev/null
+++ b/code/modules/admin/smites/nugget.dm
@@ -0,0 +1,21 @@
+/// Rips off all the limbs of the target
+/datum/smite/nugget
+ name = "Nugget"
+
+/datum/smite/nugget/effect(client/user, mob/living/target)
+ . = ..()
+
+ if (!iscarbon(target))
+ to_chat(user, span_warning("This must be used on a carbon mob."), confidential = TRUE)
+ return
+
+ var/mob/living/carbon/carbon_target = target
+ var/timer = 2 SECONDS
+ for (var/_limb in carbon_target.bodyparts)
+ var/obj/item/bodypart/limb = _limb
+ if (limb.body_part == HEAD || limb.body_part == CHEST)
+ continue
+ addtimer(CALLBACK(limb, TYPE_PROC_REF(/obj/item/bodypart/, dismember)), timer)
+ addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound), carbon_target, 'modular_splurt/sound/effects/cartoon_pop.ogg', 70), timer)
+ addtimer(CALLBACK(carbon_target, TYPE_PROC_REF(/mob/living/, spin), 4, 1), timer - 0.4 SECONDS)
+ timer += 2 SECONDS
diff --git a/code/modules/admin/smites/phobia_ocky_icky.dm b/code/modules/admin/smites/phobia_ocky_icky.dm
new file mode 100644
index 000000000000..8295b062cf26
--- /dev/null
+++ b/code/modules/admin/smites/phobia_ocky_icky.dm
@@ -0,0 +1,8 @@
+/// "Immerses" the player, making them unable to use some OOC terms IC
+/datum/smite/ocky_icky
+ name = "Ocky icky phobia"
+
+/datum/smite/ocky_icky/effect(client/user, mob/living/target)
+ . = ..()
+ var/mob/living/carbon/ocker = target
+ ocker.gain_trauma(/datum/brain_trauma/mild/phobia/ocky_icky, TRAUMA_RESILIENCE_LOBOTOMY)
diff --git a/code/modules/admin/smites/pickle.dm b/code/modules/admin/smites/pickle.dm
new file mode 100644
index 000000000000..18e370e535bb
--- /dev/null
+++ b/code/modules/admin/smites/pickle.dm
@@ -0,0 +1,7 @@
+/// Turns the target into a pickle
+/datum/smite/pickle
+ name = "Pickle"
+
+/datum/smite/pickle/effect(client/user, mob/living/target)
+ . = ..()
+ target.turn_into_pickle()
diff --git a/code/modules/admin/smites/pie.dm b/code/modules/admin/smites/pie.dm
new file mode 100644
index 000000000000..d21a891dde22
--- /dev/null
+++ b/code/modules/admin/smites/pie.dm
@@ -0,0 +1,8 @@
+/// Throws a pie at the target
+/datum/smite/pie
+ name = "Pie"
+
+/datum/smite/pie/effect(client/user, mob/living/target)
+ . = ..()
+ var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target))
+ creamy.splat(target)
diff --git a/code/modules/admin/smites/puzzle.dm b/code/modules/admin/smites/puzzle.dm
new file mode 100644
index 000000000000..ffaee1441205
--- /dev/null
+++ b/code/modules/admin/smites/puzzle.dm
@@ -0,0 +1,8 @@
+/// Turns the user into a sliding puzzle
+/datum/smite/puzzle
+ name = "Puzzle"
+
+/datum/smite/puzzle/effect(client/user, mob/living/target)
+ . = ..()
+ if(!puzzle_imprison(target))
+ to_chat(user, "Imprisonment failed!", confidential = TRUE)
diff --git a/code/modules/admin/smites/rod.dm b/code/modules/admin/smites/rod.dm
new file mode 100644
index 000000000000..8598258e36b2
--- /dev/null
+++ b/code/modules/admin/smites/rod.dm
@@ -0,0 +1,17 @@
+/// Throw an immovable rod at the target
+/datum/smite/rod
+ name = "Immovable Rod"
+ var/force_looping = FALSE
+
+/datum/smite/rod/configure(client/user)
+ var/loop_input = tgui_alert(usr,"Would you like this rod to force-loop across space z-levels?", "Loopy McLoopface", list("Yes", "No"))
+
+ force_looping = (loop_input == "Yes")
+
+/datum/smite/rod/effect(client/user, mob/living/target)
+ . = ..()
+ var/turf/target_turf = get_turf(target)
+ var/startside = pick(GLOB.cardinals)
+ var/turf/start_turf = spaceDebrisStartLoc(startside, target_turf.z)
+ var/turf/end_turf = spaceDebrisFinishLoc(startside, target_turf.z)
+ new /obj/effect/immovablerod(start_turf, end_turf, target, force_looping)
diff --git a/code/modules/admin/smites/scarify.dm b/code/modules/admin/smites/scarify.dm
new file mode 100644
index 000000000000..fcbe2062e891
--- /dev/null
+++ b/code/modules/admin/smites/scarify.dm
@@ -0,0 +1,12 @@
+/// Gives the target fake scars
+/datum/smite/scarify
+ name = "Scarify"
+
+/datum/smite/scarify/effect(client/user, mob/living/target)
+ . = ..()
+ if(!iscarbon(target))
+ to_chat(user, span_warning("This must be used on a carbon mob."), confidential = TRUE)
+ return
+ var/mob/living/carbon/dude = target
+ dude.generate_fake_scars(rand(1, 4))
+ to_chat(dude, span_warning("You feel your body grow jaded and torn..."))
diff --git a/code/modules/admin/smites/shoes.dm b/code/modules/admin/smites/shoes.dm
new file mode 100644
index 000000000000..ff74e509436f
--- /dev/null
+++ b/code/modules/admin/smites/shoes.dm
@@ -0,0 +1,15 @@
+/// Ties the target's shoes
+/datum/smite/shoes
+ name = "Knot Shoes"
+
+/datum/smite/shoes/effect(client/user, mob/living/target)
+ . = ..()
+ if(!iscarbon(target))
+ to_chat(usr,"This must be used on a carbon mob.")
+ return
+ var/mob/living/carbon/C = target
+ var/obj/item/clothing/shoes/sick_kicks = C.shoes
+ if(!sick_kicks?.can_be_tied)
+ to_chat(usr,"[C] does not have knottable shoes!")
+ return
+ sick_kicks.adjust_laces(SHOES_KNOTTED)
diff --git a/code/modules/admin/smites/smite.dm b/code/modules/admin/smites/smite.dm
new file mode 100644
index 000000000000..b767f47f8fe3
--- /dev/null
+++ b/code/modules/admin/smites/smite.dm
@@ -0,0 +1,17 @@
+/// A smite, used by admins to punish players, or for their own amusement
+/datum/smite
+ /// The name of the smite, shown in the menu
+ var/name
+
+ /// Should this smite write to logs?
+ var/should_log = TRUE
+
+/// Called once after either choosing the option to smite a player, or when selected in smite build mode.
+/// Use this to prompt the user configuration options.
+/// Return FALSE if the smite should not be used.
+/datum/smite/proc/configure(client/user)
+
+/// The effect of the smite, make sure to call this in your own smites
+/datum/smite/proc/effect(client/user, mob/living/target)
+ if (should_log)
+ user.punish_log(target, name)
diff --git a/code/modules/admin/smites/supply_pod.dm b/code/modules/admin/smites/supply_pod.dm
new file mode 100644
index 000000000000..187507e9bb40
--- /dev/null
+++ b/code/modules/admin/smites/supply_pod.dm
@@ -0,0 +1,21 @@
+#define SUPPLY_POD_FIRE_RANGE
+
+/// Throws a supply pod at the target, with no item inside
+/datum/smite/supply_pod
+ name = "Supply Pod"
+
+ // punish_log() is handled by the centcom_podlauncher datum
+ should_log = FALSE
+
+/datum/smite/supply_pod/effect(client/user, mob/living/target)
+ . = ..()
+ var/datum/centcom_podlauncher/plaunch = new(user)
+ plaunch.specificTarget = target
+ plaunch.launchChoice = 0
+ plaunch.damageChoice = 1
+ plaunch.explosionChoice = 1
+ plaunch.temp_pod.damage = 40 // bring the mother fuckin ruckus
+ plaunch.temp_pod.explosionSize = list(0, 0, 0, SUPPLY_POD_FIRE_RANGE)
+ plaunch.temp_pod.effectStun = TRUE
+
+#undef SUPPLY_POD_FIRE_RANGE
diff --git a/code/modules/admin/smites/supply_pod_quick.dm b/code/modules/admin/smites/supply_pod_quick.dm
new file mode 100644
index 000000000000..ccb04d47cee7
--- /dev/null
+++ b/code/modules/admin/smites/supply_pod_quick.dm
@@ -0,0 +1,49 @@
+#define SUPPLY_POD_QUICK_DAMAGE 40
+#define SUPPLY_POD_QUICK_FIRE_RANGE 2
+
+/// Quickly throws a supply pod at the target, optionally with an item
+/datum/smite/supply_pod_quick
+ name = "Supply Pod (Quick)"
+
+ /// What is sent down with the pod
+ var/target_path
+
+/datum/smite/supply_pod_quick/configure(client/user)
+ var/attempted_target_path = input(
+ user,
+ "Enter typepath of an atom you'd like to send with the pod (type \"empty\" to send an empty pod):",
+ "Typepath",
+ "/obj/item/reagent_containers/food/snacks/grown/harebell",
+ ) as null|text
+ if (isnull(attempted_target_path)) //The user pressed "Cancel"
+ return FALSE
+
+ if (attempted_target_path == "empty")
+ target_path = null
+ return
+
+ // if you didn't type empty, we want to load the pod with a delivery
+ var/delivery = text2path(attempted_target_path)
+ if(!ispath(delivery))
+ delivery = pick_closest_path(attempted_target_path)
+ if(!delivery)
+ alert(user, "ERROR: Incorrect / improper path given.")
+ return FALSE
+ target_path = delivery
+
+/datum/smite/supply_pod_quick/effect(client/user, mob/living/target)
+ . = ..()
+
+ var/area/pod_storage_area = locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas
+ var/obj/structure/closet/supplypod/centcompod/pod = new(pick(get_area_turfs(pod_storage_area)))
+ pod.damage = SUPPLY_POD_QUICK_DAMAGE
+ pod.explosionSize = list(0, 0, 0, SUPPLY_POD_QUICK_FIRE_RANGE)
+ pod.effectStun = TRUE
+
+ if (!isnull(target_path))
+ new target_path(pod)
+
+ new /obj/effect/pod_landingzone(get_turf(target), pod)
+
+#undef SUPPLY_POD_QUICK_DAMAGE
+#undef SUPPLY_POD_QUICK_FIRE_RANGE
diff --git a/code/modules/admin/smites/tabletide.dm b/code/modules/admin/smites/tabletide.dm
new file mode 100644
index 000000000000..a2c342584074
--- /dev/null
+++ b/code/modules/admin/smites/tabletide.dm
@@ -0,0 +1,16 @@
+/// Tableslam the target
+/datum/smite/tabletide
+ name = "Table Tideslam"
+
+/datum/smite/tabletide/effect(client/user, mob/living/target)
+ . = ..()
+ priority_announce(html_decode("[target] has brought the wrath of the gods upon themselves and is now being tableslammed across the station. Please stand by."), null, 'sound/misc/announce.ogg', "CentCom")
+ var/list/areas = list()
+ for(var/area/A in world)
+ if(A.z == SSmapping.station_start)
+ areas += A
+ SEND_SOUND(target, sound('modular_splurt/sound/misc/slamofthenorthstar.ogg',volume=60))
+ for(var/area/A in areas)
+ for(var/obj/structure/table/T in A)
+ T.tablepush(target, target)
+ sleep(1)
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index ffe284aa712d..eb42828744c6 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1997,6 +1997,22 @@
to_chat(H, "Your prayers have been answered!! You received the best cookie!")
SEND_SOUND(H, sound('sound/effects/pray_chaplain.ogg'))
+ else if (href_list["adminpopup"])
+ if (!check_rights(R_ADMIN))
+ return
+
+ var/message = input(owner, "As well as a popup, they'll also be sent a message to reply to. What do you want that to be?", "Message") as text|null
+ if (!message)
+ to_chat(owner, span_notice("Popup cancelled."))
+ return
+
+ var/client/target = locate(href_list["adminpopup"])
+ if (!istype(target))
+ to_chat(owner, span_notice("The mob doesn't exist anymore!"))
+ return
+
+ give_admin_popup(target, owner, message)
+
else if(href_list["adminsmite"])
if(!check_rights(R_ADMIN|R_FUN))
return
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index a3f654811290..284cdcf5b39e 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -249,6 +249,9 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(state == AHELP_ACTIVE)
. += ClosureLinks(ref_src)
+ if (CONFIG_GET(flag/popup_admin_pm))
+ . += " (POPUP)"
+
//private
/datum/admin_help/proc/ClosureLinks(ref_src)
if(!ref_src)
@@ -332,6 +335,8 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(initiator && initiator.current_ticket == src)
initiator.current_ticket = null
+ SEND_SIGNAL(src, COMSIG_ADMIN_HELP_MADE_INACTIVE)
+
//Mark open ticket as closed/meme
/datum/admin_help/proc/Close(key_name = key_name_admin(usr), silent = FALSE)
if(state != AHELP_ACTIVE)
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index 950a06b2b927..4969962e4cbb 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -172,6 +172,7 @@
if(holder && recipient.holder && !current_ticket) //Both are admins, and this is not a reply to our own ticket.
badmin = TRUE
if(recipient.holder && !badmin)
+ SEND_SIGNAL(current_ticket, COMSIG_ADMIN_HELP_REPLIED)
if(holder)
to_chat(recipient, "Admin PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]", confidential = TRUE)
to_chat(src, "Admin PM to-[key_name(recipient, src, 1)]: [keywordparsedmsg]", confidential = TRUE)
@@ -215,9 +216,6 @@
//always play non-admin recipients the adminhelp sound
SEND_SOUND(recipient, sound('sound/effects/adminhelp.ogg'))
- //AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn
- if(CONFIG_GET(flag/popup_admin_pm))
- INVOKE_ASYNC(src, PROC_REF(popup_admin_pm), recipient, msg)
else //neither are admins
to_chat(src, "Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.", confidential = TRUE)
@@ -235,17 +233,6 @@
if(X.key!=key && X.key!=recipient.key) //check client/X is an admin and isn't the sender or recipient
to_chat(X, "PM: [key_name(src, X, 0)]->[key_name(recipient, X, 0)]: [keywordparsedmsg]" , confidential = TRUE)
-/client/proc/popup_admin_pm(client/recipient, msg)
- var/sender = src
- var/sendername = key
- var/reply = input(recipient, msg,"Admin PM from-[sendername]", "") as message|null //show message and await a reply
- if(recipient && reply)
- if(sender)
- recipient.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them
- else
- adminhelp(reply) //sender has left, adminhelp instead
-
-
/proc/IrcPm(target,msg,sender)
return TgsPm(target,msg,sender) //compatability moment.
diff --git a/code/modules/admin/verbs/bluespacearty.dm b/code/modules/admin/verbs/bluespacearty.dm
deleted file mode 100644
index 23fff5ece938..000000000000
--- a/code/modules/admin/verbs/bluespacearty.dm
+++ /dev/null
@@ -1,26 +0,0 @@
-/client/proc/bluespace_artillery(mob/M in GLOB.mob_list)
- if(!holder || !check_rights(R_FUN))
- return
-
- var/mob/living/target = M
-
- if(!isliving(target))
- to_chat(usr, "This can only be used on instances of type /mob/living", confidential = TRUE)
- return
-
- explosion(target.loc, 0, 0, 0, 0)
-
- var/turf/open/floor/T = get_turf(target)
- if(istype(T))
- if(prob(80))
- T.break_tile_to_plating()
- else
- T.break_tile()
-
- if(target.health <= 1)
- target.gib(1, 1)
- else
- target.adjustBruteLoss(min(99,(target.health - 1)))
- target.DefaultCombatKnockdown(400)
- target.stuttering = 20
-
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index cd8c849c4580..c7dcac83df8d 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -539,6 +539,26 @@
return dresscode
+/client/proc/cmd_admin_rejuvenate(mob/living/M in GLOB.mob_list)
+ set category = "Debug"
+ set name = "Rejuvenate"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(!mob)
+ return
+ if(!istype(M))
+ alert("Cannot revive a ghost")
+ return
+ M.revive(full_heal = 1, admin_revive = 1)
+
+ log_admin("[key_name(usr)] healed / revived [key_name(M)]")
+ var/msg = "Admin [key_name_admin(usr)] healed / revived [ADMIN_LOOKUPFLW(M)]!"
+ message_admins(msg)
+ admin_ticket_log(M, msg)
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Rejuvinate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
/client/proc/startSinglo()
set category = "Debug"
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 519154c597d9..3f70ab295f1d 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -474,26 +474,6 @@ Traitors and the like can also be revived with the previous role mostly intact.
SSblackbox.record_feedback("tally", "admin_verb", 1, "Add Custom AI Law") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/client/proc/cmd_admin_rejuvenate(mob/living/M in GLOB.mob_list)
- set category = "Special Verbs"
- set name = "Rejuvenate"
-
- if(!check_rights(R_ADMIN))
- return
-
- if(!mob)
- return
- if(!istype(M))
- alert("Cannot revive a ghost")
- return
- M.revive(full_heal = 1, admin_revive = 1)
-
- log_admin("[key_name(usr)] healed / revived [key_name(M)]")
- var/msg = "Admin [key_name_admin(usr)] healed / revived [ADMIN_LOOKUPFLW(M)]!"
- message_admins(msg)
- admin_ticket_log(M, msg)
- SSblackbox.record_feedback("tally", "admin_verb", 1, "Rejuvinate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
/client/proc/cmd_admin_create_centcom_report()
set category = "Admin.Events"
set name = "Create Command Report"
@@ -1283,266 +1263,34 @@ Traitors and the like can also be revived with the previous role mostly intact.
busy_toggling_fov = FALSE
-/client/proc/smite(mob/living/carbon/human/target as mob)
+/client/proc/smite(mob/living/target as mob)
set name = "Smite"
set category = "Admin.Fun"
if(!check_rights(R_ADMIN) || !check_rights(R_FUN))
return
- var/list/punishment_list = list(
- ADMIN_PUNISHMENT_PIE,
- ADMIN_PUNISHMENT_CUSTOM_PIE,
- ADMIN_PUNISHMENT_FIREBALL,
- ADMIN_PUNISHMENT_LIGHTNING,
- ADMIN_PUNISHMENT_BRAINDAMAGE,
- ADMIN_PUNISHMENT_BSA,
- ADMIN_PUNISHMENT_GIB,
- ADMIN_PUNISHMENT_SUPPLYPOD_QUICK,
- ADMIN_PUNISHMENT_SUPPLYPOD,
- ADMIN_PUNISHMENT_MAZING,
- ADMIN_PUNISHMENT_ROD,
- ADMIN_PUNISHMENT_SHOES,
- ADMIN_PUNISHMENT_PICKLE,
- ADMIN_PUNISHMENT_FRY,
- ADMIN_PUNISHMENT_CRACK,
- ADMIN_PUNISHMENT_BLEED,
- ADMIN_PUNISHMENT_SCARIFY,
- ADMIN_PUNISHMENT_CLUWNE,
- ADMIN_PUNISHMENT_GOODBYE,
- ADMIN_PUNISHMENT_TABLETIDESTATIONWIDE,
- ADMIN_PUNISHMENT_FAKEBWOINK,
- ADMIN_PUNISHMENT_NUGGET,
- ADMIN_PUNISHMENT_BREADIFY,
- ADMIN_PUNISHMENT_BOOKIFY,
- ADMIN_PUNISHMENT_BONK)
-
- var/punishment = tgui_input_list(usr, "Choose a punishment", "Divine Smiting", punishment_list)
+
+ var/punishment = tgui_input_list(usr, "Choose a punishment", "DIVINE SMITING", GLOB.smites)
if(QDELETED(target) || !punishment)
return
- switch(punishment)
- if(ADMIN_PUNISHMENT_LIGHTNING)
- if(prob(75))
- playsound(target, 'modular_splurt/sound/misc/NOW.ogg', 75, FALSE)
- sleep(4 SECONDS)
- var/turf/T = get_step(get_step(target, NORTH), NORTH)
- T.Beam(target, icon_state="lightning[rand(1,12)]", time = 5)
- target.adjustFireLoss(75)
- target.electrocution_animation(40)
- to_chat(target, "The gods have punished you for your sins!")
- if(ADMIN_PUNISHMENT_BRAINDAMAGE)
- target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 199, 199)
- if(ADMIN_PUNISHMENT_GIB)
- target.gib(FALSE)
- if(ADMIN_PUNISHMENT_BSA)
- bluespace_artillery(target)
- if(ADMIN_PUNISHMENT_FIREBALL)
- new /obj/effect/temp_visual/target(get_turf(target))
- if(ADMIN_PUNISHMENT_ROD)
- var/turf/T = get_turf(target)
- var/startside = pick(GLOB.cardinals)
- var/turf/startT = spaceDebrisStartLoc(startside, T.z)
- var/turf/endT = spaceDebrisFinishLoc(startside, T.z)
- new /obj/effect/immovablerod(startT, endT,target)
- if(ADMIN_PUNISHMENT_SUPPLYPOD_QUICK)
- var/target_path = input(usr,"Enter typepath of an atom you'd like to send with the pod (type \"empty\" to send an empty pod):" ,"Typepath","/obj/item/reagent_containers/food/snacks/grown/harebell") as null|text
- var/area/pod_storage_area = locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas
- var/obj/structure/closet/supplypod/centcompod/pod = new(pick(get_area_turfs(pod_storage_area))) //Lets not runtime
- pod.damage = 40
- pod.explosionSize = list(0,0,0,2)
- pod.effectStun = TRUE
- if (isnull(target_path)) //The user pressed "Cancel"
- return
- if (target_path != "empty")//if you didn't type empty, we want to load the pod with a delivery
- var/delivery = text2path(target_path)
- if(!ispath(delivery))
- delivery = pick_closest_path(target_path)
- if(!delivery)
- alert("ERROR: Incorrect / improper path given.")
- new delivery(pod)
- new /obj/effect/pod_landingzone(get_turf(target), pod)
- if(ADMIN_PUNISHMENT_SUPPLYPOD)
- var/datum/centcom_podlauncher/plaunch = new(usr)
- if(!holder)
- return
- plaunch.specificTarget = target
- plaunch.launchChoice = 0
- plaunch.damageChoice = 1
- plaunch.explosionChoice = 1
- plaunch.temp_pod.damage = 40//bring the mother fuckin ruckus
- plaunch.temp_pod.explosionSize = list(0,0,0,2)
- plaunch.temp_pod.effectStun = TRUE
- return //We return here because punish_log() is handled by the centcom_podlauncher datum
-
- if(ADMIN_PUNISHMENT_MAZING)
- if(!puzzle_imprison(target))
- to_chat(usr,"Imprisonment failed!")
- return
- if(ADMIN_PUNISHMENT_PIE)
- var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target))
- creamy.splat(target)
- if(ADMIN_PUNISHMENT_CUSTOM_PIE)
- var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new()
- if(!A.reagents)
- var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num|null
- if(amount)
- A.create_reagents(amount)
- if(A.reagents)
- var/chosen_id = choose_reagent_id(usr)
- if(chosen_id)
- var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num|null
- if(amount)
- A.reagents.add_reagent(chosen_id, amount)
- A.splat(target)
- if(ADMIN_PUNISHMENT_CRACK)
- if(!iscarbon(target))
- to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE)
- return
- var/mob/living/carbon/C = target
- for(var/i in C.bodyparts)
- var/obj/item/bodypart/squish_part = i
- var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate))
- squish_part.force_wound_upwards(type_wound, smited=TRUE)
- if(ADMIN_PUNISHMENT_BLEED)
- if(!iscarbon(target))
- to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE)
- return
- var/mob/living/carbon/C = target
- for(var/i in C.bodyparts)
- var/obj/item/bodypart/slice_part = i
- var/type_wound = pick(list(/datum/wound/slash/severe, /datum/wound/slash/moderate))
- slice_part.force_wound_upwards(type_wound, smited=TRUE)
- type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate))
- slice_part.force_wound_upwards(type_wound, smited=TRUE)
- type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe))
- slice_part.force_wound_upwards(type_wound, smited=TRUE)
- if(ADMIN_PUNISHMENT_SCARIFY)
- if(!iscarbon(target))
- to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE)
- return
- var/mob/living/carbon/dude = target
- dude.generate_fake_scars(rand(1, 4))
- to_chat(dude, "You feel your body grow jaded and torn...")
- if(ADMIN_PUNISHMENT_PERFORATE)
- if(!iscarbon(target))
- to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE)
- return
+ var/smite_path = GLOB.smites[punishment]
+ var/datum/smite/smite = new smite_path
+ var/configuration_success = smite.configure(usr)
+ if (configuration_success == FALSE)
+ return
+ smite.effect(src, target)
- var/list/how_fucked_is_this_dude = list("A little", "A lot", "So fucking much", "FUCK THIS DUDE")
- var/hatred = input("How much do you hate this guy?") in how_fucked_is_this_dude
- var/repetitions
- var/shots_per_limb_per_rep = 2
- var/damage
- switch(hatred)
- if("A little")
- repetitions = 1
- damage = 5
- if("A lot")
- repetitions = 2
-
- damage = 8
- if("So fucking much")
- repetitions = 3
- damage = 10
- if("FUCK THIS DUDE")
- repetitions = 4
- damage = 10
-
- var/mob/living/carbon/dude = target
- var/list/open_adj_turfs = get_adjacent_open_turfs(dude)
- var/list/wound_bonuses = list(15, 70, 110, 250)
-
- var/delay_per_shot = 1
- var/delay_counter = 1
-
- dude.Immobilize(5 SECONDS)
- for(var/wound_bonus_rep in 1 to repetitions)
- for(var/i in dude.bodyparts)
- var/obj/item/bodypart/slice_part = i
- var/shots_this_limb = 0
- for(var/t in shuffle(open_adj_turfs))
- var/turf/iter_turf = t
- addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(firing_squad), dude, iter_turf, slice_part.body_zone, wound_bonuses[wound_bonus_rep], damage), delay_counter)
- delay_counter += delay_per_shot
- shots_this_limb++
- if(shots_this_limb > shots_per_limb_per_rep)
- break
- if(ADMIN_PUNISHMENT_PICKLE)
- target.turn_into_pickle()
- if(ADMIN_PUNISHMENT_FRY)
- target.fry()
-
- if(ADMIN_PUNISHMENT_SHOES)
- if(!iscarbon(target))
- to_chat(usr,"This must be used on a carbon mob.")
- return
- var/mob/living/carbon/C = target
- var/obj/item/clothing/shoes/sick_kicks = C.shoes
- if(!sick_kicks?.can_be_tied)
- to_chat(usr,"[C] does not have knottable shoes!")
- return
- sick_kicks.adjust_laces(SHOES_KNOTTED)
- if(ADMIN_PUNISHMENT_CLUWNE)
- if(!iscarbon(target))
- to_chat(usr,"This must be used on a carbon mob.")
- return
- target.cluwneify()
- if(ADMIN_PUNISHMENT_GOODBYE) //sandstorm punish :) it starts here
- var/mob/living/C = target
- if(C.stat == DEAD)
- to_chat(usr, "[C] is dead!")
- return
- else
- C.goodbye() //sandstorm punish and ends here.
- if(ADMIN_PUNISHMENT_TABLETIDESTATIONWIDE) //SPLURT punishments start here
- priority_announce(html_decode("[target] has brought the wrath of the gods upon themselves and is now being tableslammed across the station. Please stand by."), null, 'sound/misc/announce.ogg', "CentCom")
- var/list/areas = list()
- for(var/area/A in world)
- if(A.z == SSmapping.station_start)
- areas += A
- SEND_SOUND(target, sound('modular_splurt/sound/misc/slamofthenorthstar.ogg',volume=60))
- for(var/area/A in areas)
- for(var/obj/structure/table/T in A)
- T.tablepush(target, target)
- sleep(1)
- if(ADMIN_PUNISHMENT_FAKEBWOINK)
- SEND_SOUND(target, 'sound/effects/adminhelp.ogg')
- if(ADMIN_PUNISHMENT_NUGGET)
- if (!iscarbon(target))
- return
- var/mob/living/carbon/carbon_target = target
- var/timer = 2 SECONDS
- for (var/_limb in carbon_target.bodyparts)
- var/obj/item/bodypart/limb = _limb
- if (limb.body_part == HEAD || limb.body_part == CHEST)
- continue
- addtimer(CALLBACK(limb, TYPE_PROC_REF(/obj/item/bodypart, dismember)), timer)
- addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound), carbon_target, 'modular_splurt/sound/effects/cartoon_pop.ogg', 70), timer)
- addtimer(CALLBACK(carbon_target, TYPE_PROC_REF(/mob/living, spin), 4, 1), timer - 0.4 SECONDS)
- timer += 2 SECONDS
- if(ADMIN_PUNISHMENT_BREADIFY)
- #define BREADIFY_TIME (5 SECONDS)
- var/mutable_appearance/bread_appearance = mutable_appearance('icons/obj/food/burgerbread.dmi', "bread")
- var/mutable_appearance/transform_scanline = mutable_appearance('modular_splurt/icons/effects/effects.dmi', "transform_effect")
- target.transformation_animation(bread_appearance, time = BREADIFY_TIME, transform_overlay=transform_scanline, reset_after=TRUE)
- addtimer(CALLBACK(src, PROC_REF(breadify), target), BREADIFY_TIME)
- #undef BREADIFY_TIME
- if(ADMIN_PUNISHMENT_BOOKIFY)
- #define BOOKIFY_TIME (2 SECONDS)
- var/mutable_appearance/book_appearance = mutable_appearance('icons/obj/library.dmi', "book")
- var/mutable_appearance/transform_scanline = mutable_appearance('modular_splurt/icons/effects/effects.dmi', "transform_effect")
- target.transformation_animation(book_appearance, time = BOOKIFY_TIME, transform_overlay=transform_scanline, reset_after=TRUE)
- addtimer(CALLBACK(src, PROC_REF(bookify), target), BOOKIFY_TIME)
- playsound(target, 'modular_splurt/sound/misc/bookify.ogg', 60, 1)
- #undef BOOKIFY_TIME
- if(ADMIN_PUNISHMENT_BONK)
- playsound(target, 'modular_splurt/sound/misc/bonk.ogg', 100, 1)
- target.AddElement(/datum/element/squish, 60 SECONDS)
- to_chat(target, "Bonk.")
-
- punish_log(target, punishment)
+/proc/breadify(atom/movable/target)
+ var/obj/item/reagent_containers/food/snacks/store/bread/plain/funnyBread = new(get_turf(target))
+ target.forceMove(funnyBread)
+
+/proc/bookify(atom/movable/target)
+ var/obj/item/reagent_containers/food/snacks/store/book/funnyBook = new(get_turf(target))
+ target.forceMove(funnyBook)
+ funnyBook.name = "Book of " + target.name
/**
* firing_squad is a proc for the :B:erforate smite to shoot each individual bullet at them, so that we can add actual delays without sleep() nonsense
*
@@ -1569,10 +1317,10 @@ Traitors and the like can also be revived with the previous role mostly intact.
divine_wrath.fire()
/client/proc/punish_log(var/whom, var/punishment)
- var/msg = "[key_name_admin(usr)] punished [key_name_admin(whom)] with [punishment]."
+ var/msg = "[key_name_admin(src)] punished [key_name_admin(whom)] with [punishment]."
message_admins(msg)
admin_ticket_log(whom, msg)
- log_admin("[key_name(usr)] punished [key_name(whom)] with [punishment].")
+ log_admin("[key_name(src)] punished [key_name(whom)] with [punishment].")
/client/proc/trigger_centcom_recall()
if(!check_rights(R_ADMIN))
@@ -1747,3 +1495,19 @@ Traitors and the like can also be revived with the previous role mostly intact.
log_admin("[key_name(usr)] spawned floor cluwne.")
message_admins("[key_name(usr)] spawned floor cluwne.")
*/
+
+/// "Immerse", or how I made the entire playerbase quit the game.
+/proc/immerse_player(mob/living/carbon/target, toggle=TRUE, remove=FALSE)
+ var/list/immersion_components = list(/datum/component/manual_breathing, /datum/component/manual_blinking)
+
+ for(var/immersies in immersion_components)
+ var/has_component = target.GetComponent(immersies)
+
+ if(has_component && (toggle || remove))
+ qdel(has_component)
+ else if(toggle || !remove)
+ target.AddComponent(immersies)
+
+/proc/mass_immerse(remove=FALSE)
+ for(var/mob/living/carbon/M in GLOB.mob_list)
+ immerse_player(M, toggle=FALSE, remove=remove)
diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm
index c7b352390658..84a91113bce3 100644
--- a/code/modules/admin/verbs/secrets.dm
+++ b/code/modules/admin/verbs/secrets.dm
@@ -567,20 +567,21 @@
message_admins("[key_name_admin(holder)] has removed everyone from \
purrbation.")
log_admin("[key_name(holder)] has removed everyone from purrbation.")
- // if("massimmerse") // my immursion is ruinned :(
- // if(!is_funmin)
- // return
- // mass_immerse()
- // message_admins("[key_name_admin(holder)] has Fully Immersed
- // everyone!")
- // log_admin("[key_name(holder)] has Fully Immersed everyone.")
- // if("unmassimmerse")
- // if(!is_funmin)
- // return
- // mass_immerse(remove=TRUE)
- // message_admins("[key_name_admin(holder)] has Un-Fully Immersed
- // everyone!")
- // log_admin("[key_name(holder)] has Un-Fully Immersed everyone.")
+ // Shh!! Don't let badmins know this isn't actually a button!
+ if("massimmerse")
+ if(!is_funmin)
+ return
+ mass_immerse()
+ message_admins("[key_name_admin(holder)] has Fully Immersed \
+ everyone!")
+ log_admin("[key_name(holder)] has Fully Immersed everyone.")
+ if("unmassimmerse")
+ if(!is_funmin)
+ return
+ mass_immerse(remove=TRUE)
+ message_admins("[key_name_admin(holder)] has Un-Fully Immersed \
+ everyone!")
+ log_admin("[key_name(holder)] has Un-Fully Immersed everyone.")
if(E)
E.processing = FALSE
if(E.announce_when>0)
diff --git a/code/modules/buildmode/submodes/smite.dm b/code/modules/buildmode/submodes/smite.dm
new file mode 100644
index 000000000000..5f5050b41f38
--- /dev/null
+++ b/code/modules/buildmode/submodes/smite.dm
@@ -0,0 +1,40 @@
+/datum/buildmode_mode/smite
+ key = "smite"
+ var/datum/smite/selected_smite
+
+/datum/buildmode_mode/smite/Destroy()
+ selected_smite = null
+ return ..()
+
+/datum/buildmode_mode/smite/show_help(client/user)
+ to_chat(user, "***********************************************************\n\
+ Right Mouse Button on buildmode button = Select smite to use.\n\
+ Left Mouse Button on mob/living = Smite the mob.\n\
+ ***********************************************************")
+
+/datum/buildmode_mode/smite/change_settings(client/user)
+ var/punishment = input(user, "Choose a punishment", "DIVINE SMITING") as null|anything in GLOB.smites
+ var/smite_path = GLOB.smites[punishment]
+ var/datum/smite/picking_smite = new smite_path
+ var/configuration_success = picking_smite.configure(user)
+ if (configuration_success == FALSE)
+ return
+ selected_smite = picking_smite
+
+/datum/buildmode_mode/smite/handle_click(client/user, params_string, object)
+ var/list/params = params2list(params_string)
+
+ if (!check_rights(R_ADMIN | R_FUN))
+ return
+
+ if (!params.Find("left"))
+ return
+
+ if (!isliving(object))
+ return
+
+ if (selected_smite == null)
+ to_chat(user, "No smite selected.")
+ return
+
+ selected_smite.effect(user, object)
diff --git a/code/modules/emote_panel/emote_panel.dm b/code/modules/emote_panel/emote_panel.dm
new file mode 100644
index 000000000000..029f69ebb950
--- /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))
+ keys += emote.key
+ emotes += list(list(
+ "key" = emote.key,
+ "name" = emote.name,
+ "hands" = emote.restraint_check,
+ "visible" = emote.emote_type & (EMOTE_VISIBLE || EMOTE_BOTH || EMOTE_OMNI),
+ "audible" = emote.emote_type & (EMOTE_AUDIBLE || EMOTE_BOTH || EMOTE_OMNI),
+ "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 3c7476ff3b15..bfee6b87c067 100644
--- a/code/modules/mob/emote.dm
+++ b/code/modules/mob/emote.dm
@@ -7,12 +7,16 @@
param = copytext(act, custom_param + length(act[custom_param]))
act = copytext(act, 1, custom_param)
- var/datum/emote/E
- E = E.emote_list[act]
- if(!E)
- to_chat(src, "Unusable emote '[act]'. Say *help for a list.")
+ var/list/key_emotes = GLOB.emote_list[act]
+ for(var/datum/emote/emote in key_emotes)
+ if(!emote.can_run_emote(src, TRUE, intentional, param))
+ continue
+ if(emote.run_emote(src, param, m_type, intentional))
+ SEND_SIGNAL(src, COMSIG_MOB_EMOTE, emote, act, m_type, message, intentional)
+ return TRUE
+ if(!key_emotes)
+ to_chat(src, span_notice("Unusable emote '[act]'. Say *help for a list."))
return
- E.run_emote(src, param, m_type, intentional)
/datum/emote/flip
key = "flip"
diff --git a/code/modules/mob/living/carbon/emote.dm b/code/modules/mob/living/carbon/emote.dm
index 49501e0315ec..f59c24635bc0 100644
--- a/code/modules/mob/living/carbon/emote.dm
+++ b/code/modules/mob/living/carbon/emote.dm
@@ -10,9 +10,10 @@
/datum/emote/living/carbon/blink_r
key = "blink_r"
+ name = "blink rapidly"
message = "blinks rapidly."
-/datum/emote/living/carbon/clap
+/datum/emote/sound/human/clap
key = "clap"
key_third_person = "claps"
message = "claps."
@@ -20,18 +21,9 @@
restraint_check = TRUE
emote_type = EMOTE_AUDIBLE
-/datum/emote/living/carbon/clap/run_emote(mob/living/user, params)
+/datum/emote/sound/human/clap/run_emote(mob/user, params)
+ sound = pick('sound/misc/clap1.ogg', 'sound/misc/clap2.ogg', 'sound/misc/clap3.ogg', 'sound/misc/clap4.ogg')
. = ..()
- if (.)
- if (ishuman(user))
- // Need hands to clap
- if (!user.get_bodypart(BODY_ZONE_L_ARM) || !user.get_bodypart(BODY_ZONE_R_ARM))
- return
- var/clap = pick('sound/misc/clap1.ogg',
- 'sound/misc/clap2.ogg',
- 'sound/misc/clap3.ogg',
- 'sound/misc/clap4.ogg')
- playsound(user, clap, 50, 1, -1)
/datum/emote/living/carbon/gnarl
key = "gnarl"
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index 2f5a4e01e93f..cc41a8afd391 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -99,7 +99,7 @@
else
H.dna.species.stop_wagging_tail(H)
-/datum/emote/living/carbon/human/wag/can_run_emote(mob/user, status_check = TRUE)
+/datum/emote/living/carbon/human/wag/can_run_emote(mob/user, status_check = TRUE, intentional = FALSE)
if(!..() || !ishuman(user))
return FALSE
var/mob/living/carbon/human/H = user
@@ -135,7 +135,7 @@
else
. = "closes " + message
-/datum/emote/living/carbon/human/wing/can_run_emote(mob/user, status_check = TRUE)
+/datum/emote/living/carbon/human/wing/can_run_emote(mob/user, status_check = TRUE, intentional = FALSE)
if(!..() || !ishuman(user))
return FALSE
var/mob/living/carbon/human/H = user
@@ -162,7 +162,7 @@
T.Entered(src)
/datum/emote/sound/human
- mob_type_allowed_typecache = list(/mob/living/carbon/human)
+ mob_type_allowed_typecache = list(/mob/living/) // /sound/human/ became the global emote type, so this is now the only valid typecache
emote_type = EMOTE_AUDIBLE
/datum/emote/sound/human/buzz
@@ -247,6 +247,7 @@
//the actual emotes
/datum/emote/living/carbon/human/rockpaperscissors
+ key = "rps" // Give rockpaperscissors a key so it STOPS RUNTIMING
message = "is attempting to play rock paper scissors!"
/datum/emote/living/carbon/human/rockpaperscissors/rock
diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm
index e2ed7830f789..ead41dab4f6a 100644
--- a/code/modules/mob/living/emote.dm
+++ b/code/modules/mob/living/emote.dm
@@ -222,7 +222,7 @@
/datum/emote/living/audio_emote
emote_type = EMOTE_AUDIBLE
-/datum/emote/living/audio_emote/can_run_emote(mob/living/user, status_check = TRUE)
+/datum/emote/living/audio_emote/can_run_emote(mob/living/user, status_check = TRUE, intentional = FALSE)
. = ..()
if(. && iscarbon(user))
var/mob/living/carbon/C = user
@@ -508,14 +508,12 @@
var/list/keys = list()
var/list/message = list("Available emotes, you can use them with say \"*emote\": ")
- var/datum/emote/E
- var/list/emote_list = E.emote_list
- for(var/e in emote_list)
- if(e in keys)
- continue
- E = emote_list[e]
- if(E.can_run_emote(user, status_check = FALSE))
- keys += E.key
+ for(var/key in GLOB.emote_list)
+ for(var/datum/emote/emote_action in GLOB.emote_list[key])
+ if(emote_action.key in keys)
+ continue
+ if(emote_action.can_run_emote(user, status_check = FALSE , intentional = TRUE))
+ keys += emote_action.key
keys = sort_list(keys)
@@ -595,3 +593,12 @@
var/mob/living/carbon/C = user
if(isjellyperson(C))
pick(playsound(C, 'sound/effects/meatslap.ogg', 50, 1),playsound(C, 'sound/effects/gib_step.ogg', 50, 1))
+
+/datum/emote/inhale
+ key = "inhale"
+ key_third_person = "inhales"
+ message = "breathes in."
+/datum/emote/exhale
+ key = "exhale"
+ key_third_person = "exhales"
+ message = "breathes out."
diff --git a/config/entries/admin.txt b/config/entries/admin.txt
index d7932bbe1330..75fc08f99ef3 100644
--- a/config/entries/admin.txt
+++ b/config/entries/admin.txt
@@ -30,9 +30,9 @@ MENTOR_LEGACY_SYSTEM
## Uncomment this to forbid admins from possessing the singularity.
#FORBID_SINGULO_POSSESSION
-## Uncomment to show a popup 'reply to' window to every non-admin that receives an adminPM.
-## The intention is to make adminPMs more visible. (although I fnd popups annoying so this defaults to off)
-#POPUP_ADMIN_PM
+## Uncomment to give admins the ability to send a maptext popup to players.
+## Only fires when an admin requests it, not every ahelp.
+POPUP_ADMIN_PM
## Uncomment this to let players see their own notes (they can still be set by admins only)
#SEE_OWN_NOTES
diff --git a/html/changelogs/archive/2024-09.yml b/html/changelogs/archive/2024-09.yml
index 59cf3517cd76..ea4daf1e0dd4 100644
--- a/html/changelogs/archive/2024-09.yml
+++ b/html/changelogs/archive/2024-09.yml
@@ -32,3 +32,12 @@
- rscadd: New space ruins
- tweak: several edits to simplemobs such as seeing their health
- imageadd: TG sprites for doors, floors and other items
+ ariaworld:
+ - rscadd: Added some safeguards to RD console & design datums.
+ - rscadd: Added Beach, Forest, Jungle, Prison, and Winter apartments to infinidorm.
+2024-09-26:
+ Just-Sim:
+ - bugfix: Fixed cluttercode.
+2024-09-28:
+ Just-Sim:
+ - code_imp: Changed a lot of emotes.
\ No newline at end of file
diff --git a/html/changelogs/archive/2024-10.yml b/html/changelogs/archive/2024-10.yml
index 0df8e19a721e..9e45fd44e7d2 100644
--- a/html/changelogs/archive/2024-10.yml
+++ b/html/changelogs/archive/2024-10.yml
@@ -1,3 +1,11 @@
+2024-10-01:
+ Just-Sim:
+ - rscadd: Added Emote Panel
+ - rscdel: Remove herobrine.
+ - refactor: refactored emote code.
+2024-10-05:
+ Just-Sim:
+ - bugfix: fixes bugs brought about by the emote panel
2024-10-07:
SaraSayomi:
- bugfix: Crop top
diff --git a/icons/misc/buildmode.dmi b/icons/misc/buildmode.dmi
index f0de428b6c55..45ff81ba2de9 100644
Binary files a/icons/misc/buildmode.dmi and b/icons/misc/buildmode.dmi differ
diff --git a/modular_citadel/code/modules/mob/cit_emotes.dm b/modular_citadel/code/modules/mob/cit_emotes.dm
index 88ea10b943a7..79c5499e7622 100644
--- a/modular_citadel/code/modules/mob/cit_emotes.dm
+++ b/modular_citadel/code/modules/mob/cit_emotes.dm
@@ -68,268 +68,162 @@
message = "makes a very loud noise."
. = ..()
-/datum/emote/living/snap
+/datum/emote/sound/human/snap
key = "snap"
key_third_person = "snaps"
message = "snaps their fingers."
emote_type = EMOTE_AUDIBLE
muzzle_ignore = TRUE
restraint_check = TRUE
+ emote_pitch_variance = FALSE
+ sound = 'modular_citadel/sound/voice/snap.ogg'
-/datum/emote/living/snap/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- playsound(user, 'modular_citadel/sound/voice/snap.ogg', 50, 1, -1)
-
-/datum/emote/living/snap2
+/datum/emote/sound/human/snap2
key = "snap2"
key_third_person = "snaps twice"
+ name = "snap twice"
message = "snaps twice."
emote_type = EMOTE_AUDIBLE
muzzle_ignore = TRUE
restraint_check = TRUE
+ emote_pitch_variance = FALSE
+ sound = 'modular_citadel/sound/voice/snap2.ogg'
-/datum/emote/living/snap2/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- playsound(user, 'modular_citadel/sound/voice/snap2.ogg', 50, 1, -1)
-
-/datum/emote/living/snap3
+/datum/emote/sound/human/snap3
key = "snap3"
key_third_person = "snaps thrice"
+ name = "snap thrice"
message = "snaps thrice."
emote_type = EMOTE_AUDIBLE
muzzle_ignore = TRUE
restraint_check = TRUE
+ emote_pitch_variance = FALSE
+ sound = 'modular_citadel/sound/voice/snap3.ogg'
-/datum/emote/living/snap3/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- playsound(user, 'modular_citadel/sound/voice/snap3.ogg', 50, 1, -1)
-
-/datum/emote/living/awoo
+/datum/emote/sound/human/awoo
key = "awoo"
key_third_person = "lets out an awoo"
message = "lets out an awoo!"
emote_type = EMOTE_AUDIBLE
muzzle_ignore = FALSE
restraint_check = FALSE
+ sound = 'modular_citadel/sound/voice/awoo.ogg'
-/datum/emote/living/awoo/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- playsound(user, 'modular_citadel/sound/voice/awoo.ogg', 50, 1, -1)
-
-/datum/emote/living/hiss
+/datum/emote/sound/human/hiss
key = "hiss"
key_third_person = "hisses"
message = "hisses!"
emote_type = EMOTE_AUDIBLE
muzzle_ignore = FALSE
restraint_check = FALSE
+ sound = 'modular_citadel/sound/voice/hiss.ogg'
-/datum/emote/living/hiss/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- playsound(user, 'modular_citadel/sound/voice/hiss.ogg', 50, 1, -1)
-
-/datum/emote/living/purr
+/datum/emote/sound/human/purr
key = "purr"
key_third_person = "purrs softly"
message = "purrs softly."
emote_type = EMOTE_AUDIBLE
muzzle_ignore = FALSE
restraint_check = FALSE
+ sound = 'modular_citadel/sound/voice/purr.ogg'
-/datum/emote/living/purr/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- playsound(user, 'modular_citadel/sound/voice/purr.ogg', 50, 1, -1)
-
-/datum/emote/living/nya
+/datum/emote/sound/human/nya
key = "nya"
key_third_person = "lets out a nya"
message = "lets out a nya!"
emote_type = EMOTE_AUDIBLE
muzzle_ignore = FALSE
restraint_check = FALSE
+ sound = 'modular_citadel/sound/voice/nya.ogg'
-/datum/emote/living/nya/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- playsound(user, 'modular_citadel/sound/voice/nya.ogg', 50, 1, -1)
-
-/datum/emote/living/weh
+/datum/emote/sound/human/weh
key = "weh"
key_third_person = "lets out a weh"
message = "lets out a weh!"
emote_type = EMOTE_AUDIBLE
muzzle_ignore = FALSE
restraint_check = FALSE
+ sound = 'modular_citadel/sound/voice/weh.ogg'
-/datum/emote/living/weh/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- playsound(user, 'modular_citadel/sound/voice/weh.ogg', 50, 1, -1)
-
-/datum/emote/living/peep
+/datum/emote/sound/human/peep
key = "peep"
key_third_person = "peeps like a bird"
message = "peeps like a bird!"
emote_type = EMOTE_AUDIBLE
muzzle_ignore = FALSE
restraint_check = FALSE
+ sound = 'modular_citadel/sound/voice/peep.ogg'
-/datum/emote/living/peep/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- playsound(user, 'modular_citadel/sound/voice/peep.ogg', 50, 1, -1)
-
-/datum/emote/living/dab
+/datum/emote/sound/human/dab
key = "dab"
key_third_person = "suddenly hits a dab"
message = "suddenly hits a dab!"
emote_type = EMOTE_AUDIBLE
restraint_check = TRUE
-/datum/emote/living/mothsqueak
+/datum/emote/sound/human/mothsqueak
key = "msqueak"
key_third_person = "lets out a tiny squeak"
message = "lets out a tiny squeak!"
emote_type = EMOTE_AUDIBLE
muzzle_ignore = FALSE
restraint_check = FALSE
+ sound = 'modular_citadel/sound/voice/mothsqueak.ogg'
-/datum/emote/living/mothsqueak/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- playsound(user, 'modular_citadel/sound/voice/mothsqueak.ogg', 50, 1, -1)
-
-/datum/emote/living/merp
+/datum/emote/sound/human/merp
key = "merp"
key_third_person = "merps"
message = "merps!"
emote_type = EMOTE_AUDIBLE
muzzle_ignore = FALSE
restraint_check = FALSE
+ emote_cooldown = 0.6 SECONDS
+ sound = 'modular_citadel/sound/voice/merp.ogg'
-/datum/emote/living/merp/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- playsound(user, 'modular_citadel/sound/voice/merp.ogg', 50, 1, -1)
-
-/datum/emote/living/bark
+/datum/emote/sound/human/bark
key = "bark"
key_third_person = "barks"
message = "barks!"
emote_type = EMOTE_AUDIBLE
muzzle_ignore = FALSE
restraint_check = FALSE
+ emote_cooldown = 0.6 SECONDS
-/datum/emote/living/bark/run_emote(mob/living/user, params)
+/datum/emote/sound/human/bark/run_emote(mob/user, params)
+ sound = pick('modular_citadel/sound/voice/bark1.ogg', 'modular_citadel/sound/voice/bark2.ogg')
. = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- var/sound = pick('modular_citadel/sound/voice/bark1.ogg', 'modular_citadel/sound/voice/bark2.ogg')
- playsound(user, sound, 50, 1, -1)
-/datum/emote/living/squish
+/datum/emote/sound/human/squish
key = "squish"
key_third_person = "squishes"
message = "squishes!"
emote_type = EMOTE_AUDIBLE
muzzle_ignore = FALSE
restraint_check = FALSE
+ sound = 'sound/voice/slime_squish.ogg'
-/datum/emote/living/squish/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- var/sound = pick('sound/voice/slime_squish.ogg')
- playsound(user, sound, 50, 1, -1)
-
-/datum/emote/living/pain
+/datum/emote/sound/human/pain
key = "pain"
key_third_person = "cries out in pain!"
message = "cries out in pain!"
emote_type = EMOTE_AUDIBLE
muzzle_ignore = FALSE
restraint_check = FALSE
+ emote_pitch_variance = FALSE
-/datum/emote/living/pain/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- if(user.nextsoundemote >= world.time)
- return
- user.nextsoundemote = world.time + 7
- var/sound
+/datum/emote/sound/human/pain/run_emote(mob/user, params)
if(user.gender == MALE)
sound = pick('modular_citadel/sound/voice/human_male_pain_1.ogg', 'modular_citadel/sound/voice/human_male_pain_2.ogg', 'modular_citadel/sound/voice/human_male_pain_3.ogg', 'modular_citadel/sound/voice/human_male_pain_rare.ogg', 'modular_citadel/sound/voice/human_male_scream_1.ogg', 'modular_citadel/sound/voice/human_male_scream_2.ogg', 'modular_citadel/sound/voice/human_male_scream_3.ogg', 'modular_citadel/sound/voice/human_male_scream_4.ogg')
else
sound = pick('modular_citadel/sound/voice/human_female_pain_1.ogg', 'modular_citadel/sound/voice/human_female_pain_2.ogg', 'modular_citadel/sound/voice/human_female_pain_3.ogg', 'modular_citadel/sound/voice/human_female_scream_2.ogg', 'modular_citadel/sound/voice/human_female_scream_3.ogg', 'modular_citadel/sound/voice/human_female_scream_4.ogg')
- playsound(user, sound, 50, 0, 0)
+ . = ..()
-/datum/emote/living/clap1
+/datum/emote/sound/human/clap1
key = "clap1"
- key_third_person = "claps"
+ key_third_person = "clap1s"
+ name = "clap once"
message = "claps their hands together."
emote_type = EMOTE_AUDIBLE
muzzle_ignore = TRUE
restraint_check = TRUE
-
-/datum/emote/living/clap1/run_emote(mob/living/user, params)
- . = ..()
- if(!.)
- return
- playsound(user, 'modular_citadel/sound/voice/clap.ogg', 50, 1, -1)
+ sound = 'modular_citadel/sound/voice/clap.ogg'
diff --git a/modular_splurt/code/datums/traits/good.dm b/modular_splurt/code/datums/traits/good.dm
index 9367835f2eec..e2025ae166c9 100644
--- a/modular_splurt/code/datums/traits/good.dm
+++ b/modular_splurt/code/datums/traits/good.dm
@@ -96,9 +96,8 @@
SIGNAL_HANDLER
. = FALSE
- var/datum/emote/E
- E = E.emote_list[lowertext(emote_args[EMOTE_ACT])]
- if(TIMER_COOLDOWN_CHECK(quirk_holder, COOLDOWN_DOMINANT_SNAP) || !findtext(E?.key, "snap"))
+ var/key = GLOB.emote_list[lowertext(emote_args[EMOTE_ACT])]
+ if(TIMER_COOLDOWN_CHECK(quirk_holder, COOLDOWN_DOMINANT_SNAP) || !findtext(key, "snap"))
return
for(var/mob/living/carbon/human/sub in hearers(DOMINANT_DETECT_RANGE, quirk_holder))
if(!sub.has_quirk(/datum/quirk/well_trained) || (sub == quirk_holder))
@@ -109,7 +108,7 @@
good_x = "boy"
if(FEMALE)
good_x = "girl"
- switch(E?.key)
+ switch(key)
if("snap")
sub.dir = get_dir(sub, quirk_holder)
sub.emote(pick("blush", "pant"))
diff --git a/modular_splurt/code/modules/admin/verbs/randomverbs.dm b/modular_splurt/code/modules/admin/verbs/randomverbs.dm
index a0c81e3f195c..157cb6688342 100644
--- a/modular_splurt/code/modules/admin/verbs/randomverbs.dm
+++ b/modular_splurt/code/modules/admin/verbs/randomverbs.dm
@@ -1,12 +1,3 @@
-/client/proc/breadify(atom/movable/target)
- var/obj/item/reagent_containers/food/snacks/store/bread/plain/funnyBread = new(get_turf(target))
- target.forceMove(funnyBread)
-
-/client/proc/bookify(atom/movable/target)
- var/obj/item/reagent_containers/food/snacks/store/book/funnyBook = new(get_turf(target))
- target.forceMove(funnyBook)
- funnyBook.name = "Book of " + target.name
-
/client/proc/cmd_admin_subtle_headset_message(mob/M, sender = null)
if(!ismob(M))
return
diff --git a/modular_splurt/code/modules/mob/living/carbon/human/species_types/teshari.dm b/modular_splurt/code/modules/mob/living/carbon/human/species_types/teshari.dm
index 1cb171d13c98..70ddf0212c4c 100644
--- a/modular_splurt/code/modules/mob/living/carbon/human/species_types/teshari.dm
+++ b/modular_splurt/code/modules/mob/living/carbon/human/species_types/teshari.dm
@@ -61,60 +61,60 @@
/datum/language/schechi
-/datum/emote/living/audio/teshari/teshsqueak
+/datum/emote/sound/teshari/teshsqueak
key = "surprised"
key_third_person = "surprised"
message = "chirps in surprise!"
message_mime = "lets out an inaudible chirp!"
- emote_sound = 'modular_splurt/sound/voice/teshsqueak.ogg' // Copyright CC BY 3.0 InspectorJ (freesound.org) for the source audio.
+ sound = 'modular_splurt/sound/voice/teshsqueak.ogg' // Copyright CC BY 3.0 InspectorJ (freesound.org) for the source audio.
emote_cooldown = 2.1 SECONDS
-/datum/emote/living/audio/teshari/teshsqueak/run_emote(mob/user, params)
+/datum/emote/sound/teshari/teshsqueak/run_emote(mob/user, params)
var/datum/dna/D = user.has_dna()
if(D.species.name != "Teshari")
return
// Return normally
. = ..()
-/datum/emote/living/audio/teshari/teshchirp
+/datum/emote/sound/teshari/teshchirp
key = "tchirp"
key_third_person = "tchirp"
message = "chirps!"
message_mime = "lets out an inaudible chirp!"
- emote_sound = 'modular_splurt/sound/voice/teshchirp.ogg' // Copyright CC BY 3.0 InspectorJ (freesound.org) for the source audio.
+ sound = 'modular_splurt/sound/voice/teshchirp.ogg' // Copyright CC BY 3.0 InspectorJ (freesound.org) for the source audio.
emote_cooldown = 2.1 SECONDS
-/datum/emote/living/audio/teshari/teshchirp/run_emote(mob/user, params)
+/datum/emote/sound/teshari/teshchirp/run_emote(mob/user, params)
var/datum/dna/D = user.has_dna()
if(D.species.name != "Teshari")
return
// Return normally
. = ..()
-/datum/emote/living/audio/teshari/trill
+/datum/emote/sound/teshari/trill
key = "trill"
key_third_person = "trill"
message = "trills!"
message_mime = "lets out an inaudible chirp!"
- emote_sound = 'modular_splurt/sound/voice/teshtrill.ogg' // Copyright CC BY 3.0 InspectorJ (freesound.org) for the source audio.
+ sound = 'modular_splurt/sound/voice/teshtrill.ogg' // Copyright CC BY 3.0 InspectorJ (freesound.org) for the source audio.
emote_cooldown = 2.1 SECONDS
-/datum/emote/living/audio/teshari/trill/run_emote(mob/user, params)
+/datum/emote/sound/teshari/trill/run_emote(mob/user, params)
var/datum/dna/D = user.has_dna()
if(D.species.name != "Teshari")
return
// Return normally
. = ..()
-/datum/emote/living/audio/teshari/teshscream
+/datum/emote/sound/teshari/teshscream
key = "teshscream"
key_third_person = "teshscream"
message = "screams!"
message_mime = "lets out an inaudible screams!"
- emote_sound = 'modular_splurt/sound/voice/teshscream.ogg' // Copyright CC BY 3.0 InspectorJ (freesound.org) for the source audio.
+ sound = 'modular_splurt/sound/voice/teshscream.ogg' // Copyright CC BY 3.0 InspectorJ (freesound.org) for the source audio.
emote_cooldown = 2.1 SECONDS
-/datum/emote/living/audio/teshari/teshscream/run_emote(mob/user, params)
+/datum/emote/sound/teshari/teshscream/run_emote(mob/user, params)
var/datum/dna/D = user.has_dna()
if(D.species.name != "Teshari")
return
diff --git a/modular_splurt/code/modules/mob/living/carbon/human/species_types/vox.dm b/modular_splurt/code/modules/mob/living/carbon/human/species_types/vox.dm
index a6da9f28c3e9..78883aea5635 100644
--- a/modular_splurt/code/modules/mob/living/carbon/human/species_types/vox.dm
+++ b/modular_splurt/code/modules/mob/living/carbon/human/species_types/vox.dm
@@ -60,15 +60,15 @@
emote_type = EMOTE_AUDIBLE
-/datum/emote/living/audio/vox/shriek
+/datum/emote/sound/vox/shriek
key = "shriek"
key_third_person = "shrieks"
message = "shrieks!"
message_mime = "lets out an inaudible shriek!"
- emote_sound = 'modular_splurt/sound/voice/shriek1.ogg' // Copyright CC BY 3.0 InspectorJ (freesound.org) for the source audio.
+ sound = 'modular_splurt/sound/voice/shriek1.ogg' // Copyright CC BY 3.0 InspectorJ (freesound.org) for the source audio.
emote_cooldown = 2.1 SECONDS
-/datum/emote/living/audio/vox/shriek/run_emote(mob/user, params)
+/datum/emote/sound/vox/shriek/run_emote(mob/user, params)
var/datum/dna/D = user.has_dna()
if(D.species.name != "Vox")
return
diff --git a/modular_splurt/code/modules/mob/living/emotes.dm b/modular_splurt/code/modules/mob/living/emotes.dm
index 24dc3206052f..08aac4e945d5 100644
--- a/modular_splurt/code/modules/mob/living/emotes.dm
+++ b/modular_splurt/code/modules/mob/living/emotes.dm
@@ -1,3 +1,31 @@
+/* SPLURT STATION Guide:
+To create an emote, create a new /datum/emote/sound/human/ entry.
+ Here are the variables you can set:
+ - "key" is the command that a person will run to execute your emote.
+ - "key_third_person" is another way the command can be run to execute your emote, but in case of third person. (Example: "laugh" & "laughs")
+ - "name" is the name that shows up in the emote panel.
+ - "message" is the message that gets displayed when your emote is executed.
+ - "message_mime" is the message that gets displayed when your emote is executed by a mime.
+ - "emote_cooldown" is the cooldown of your emote (in SECONDS).
+ - "sound" is the sound file that gets played when your emote is executed.
+ - "emote_type" is the type of emote that your emote is.
+ EMOTE_AUDIBLE: Your emote will be audible to everyone. (Except deaf people)
+ EMOTE_VISIBLE: Your emote will be visible to everyone. (Except people who are blind)
+ EMOTE_BOTH: Your emote will be both audible and visible to everyone.
+ EMOTE_OMNI: Your emote will be audible to everyone, and visible to everyone who can see the user.
+ !!! THESE ARE IMPORTANT. THE EMOTE PANEL USES THESE !!!
+ - "restraint_check" is a boolean. If true, the emote will not be able to be used if the user is restrained. Defaults to FALSE.
+ - "mob_type_allowed_typecache" is a list of mob types that are allowed to use your emote. Do not use this unless necessary. Defaults to list(/mob/living).
+ - "emote_volume" is the volume of your emote. Defaults to 50.
+ - "emote_pitch_variance" is a boolean. If true, the emote will have a random pitch. Defaults to FALSE.
+
+To add randomization to your emote, copy and paste this line of code:
+ /datum/emote/sound/human/your_emote_name/run_emote(mob/user, params)
+ sound = pick('sound1.ogg', 'sound2.ogg', 'sound3.ogg')
+ . = ..()
+*/
+
+
//Main code edits
/datum/emote/living/audio_emote/laugh/run_emote(mob/user, params)
. = ..()
@@ -55,88 +83,6 @@
// Play laugh sound
playsound(carbon_user, laugh_sound, 50, 1)
-// Living variant
-/datum/emote/living/audio
- // List of mob types that can run emote
- mob_type_allowed_typecache = list(/mob/living)
-
- // Default type
- // Can be EMOTE_AUDIBLE, EMOTE_VISIBLE, EMOTE_BOTH, or EMOTE_OMNI
- emote_type = EMOTE_AUDIBLE
-
- // Placeholder variables
- // These should NOT appear in-game
- message = "makes an indescribable noise"
- var/emote_sound = 'sound/arcade/Boom.ogg'
-
- // Default time before using another audio emote
- var/emote_cooldown = 1 SECONDS
-
- // Default volume of the emote
- var/emote_volume = 50
-
- // Default range modifier
- var/emote_range = -1
- var/emote_distance_multiplier = SOUND_DEFAULT_DISTANCE_MULTIPLIER
- var/emote_distance_multiplier_min_range = SOUND_DEFAULT_MULTIPLIER_EFFECT_RANGE
-
- // Default pitch variance
- var/emote_pitch_variance = 1
-
- // Default audio falloff settings
- var/emote_falloff_exponent = SOUND_FALLOFF_EXPONENT
- var/emote_falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE
-
- // Default frequency
- var/emote_frequency = null
-
- // Default channel
- var/emote_channel = 0
-
- // Should the emote consider atmospheric pressure?
- var/emote_check_pressure = TRUE
-
- // Should the emote ignore walls?
- var/emote_ignore_walls = FALSE
-
- // Default wet and dry settings (???)
- var/emote_wetness = -10000
- var/emote_dryness = 0
-
-// Check if audio emote can run
-/datum/emote/living/audio/can_run_emote(mob/living/user, status_check)
- . = ..()
-
- // Check parent return
- if(!.)
- return FALSE
-
- // Check cooldown
- if(user?.nextsoundemote >= world.time)
- return FALSE
-
- // Allow use
- return TRUE
-
-// Run audio emote
-/datum/emote/living/audio/run_emote(mob/user, params)
- . = ..()
-
- // Check parent return
- if(!.)
- return
-
- // Check if user is miming
- if(user?.mind?.miming)
- // Do nothing
- return
-
- // Play sound
- // Accepts all possible parameters
- playsound(user.loc, emote_sound, emote_volume, emote_pitch_variance, emote_range, emote_falloff_exponent, emote_frequency, emote_channel, emote_check_pressure, emote_ignore_walls, emote_falloff_distance, emote_wetness, emote_dryness, emote_distance_multiplier, emote_distance_multiplier_min_range)
-
- // Set cooldown
- user.nextsoundemote = world.time + emote_cooldown
/datum/emote/living/surrender/run_emote(mob/user, params, type_override, intentional)
// Set message with pronouns
@@ -162,17 +108,20 @@
key = "ruffle"
key_third_person = "ruffles"
message = "ruffles their wings for a moment."
+ restraint_check = TRUE
+ emote_type = EMOTE_VISIBLE
-/datum/emote/living/fart
+/datum/emote/sound/human/fart
key = "fart"
key_third_person = "farts"
message = "farts out shitcode."
+ sound = 'modular_splurt/sound/voice/farts/fart.ogg'
+ vary = TRUE
+ emote_type = EMOTE_AUDIBLE
+ emote_cooldown = 3 SECONDS
-/datum/emote/living/fart/run_emote(mob/living/user, params, type_override, intentional)
- if(TIMER_COOLDOWN_CHECK(user, COOLDOWN_EMOTE_FART))
- to_chat(user, span_warning("You try your hardest, but no shart comes out."))
- return
- var/list/fart_emotes = list( //cope goonies
+/datum/emote/sound/human/fart/run_emote(mob/user, params, type_override, intentional)
+ var/list/fart_emotes = list(
"lets out a girly little 'toot' from [user.p_their()] butt.",
"farts loudly!",
"lets one rip!",
@@ -214,23 +163,20 @@
"farts, and as such, blob cannot evoulate.",
"farts. It might have been the Citizen Kane of farts."
)
- var/new_message = pick(fart_emotes)
- //new_message = replacetext(new_message, "%OWNER", "\the [user]")
- message = new_message
+ message = pick(fart_emotes)
+ sound = pick(GLOB.brap_noises)
. = ..()
- if(.)
- playsound(user, pick(GLOB.brap_noises), 50, 1, -1)
- TIMER_COOLDOWN_START(user, COOLDOWN_EMOTE_FART, 3 SECONDS)
-/datum/emote/living/audio/cackle
+/datum/emote/sound/human/cackle
key = "cackle"
key_third_person = "cackles"
message = "cackles hysterically!"
message_mime = "cackles silently!"
- emote_sound = 'modular_splurt/sound/voice/cackle_yeen.ogg'
+ sound = 'modular_splurt/sound/voice/cackle_yeen.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 1.6 SECONDS
-/datum/emote/living/audio/speen
+/datum/emote/sound/human/speen
key = "speen"
key_third_person = "speens"
message = "speeeeens!"
@@ -238,10 +184,10 @@
restraint_check = TRUE
mob_type_allowed_typecache = list(/mob/living)
mob_type_ignore_stat_typecache = list(/mob/dead/observer)
- emote_sound = 'modular_splurt/sound/voice/speen.ogg'
+ sound = 'modular_splurt/sound/voice/speen.ogg'
// No cooldown var required
-/datum/emote/living/audio/speen/run_emote(mob/user, params)
+/datum/emote/sound/human/speen/run_emote(mob/user, params)
. = ..()
// Check parent return
@@ -272,28 +218,31 @@
// Unbuckle all mobs
user_cyborg.unbuckle_all_mobs()
-/datum/emote/living/audio/chirp
+/datum/emote/sound/human/chirp
key = "chirp"
key_third_person = "chirps"
message = "chirps!"
message_mime = "chirps silently!"
- emote_sound = 'modular_splurt/sound/voice/chirp.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/chirp.ogg'
emote_cooldown = 0.2 SECONDS
-/datum/emote/living/audio/caw
+/datum/emote/sound/human/caw
key = "caw"
key_third_person = "caws"
message = "caws!"
message_mime = "caws silently!"
- emote_sound = 'modular_splurt/sound/voice/caw.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/caw.ogg'
emote_cooldown = 0.35 SECONDS
-/datum/emote/living/audio/mew
+/datum/emote/sound/human/mew
key = "mew"
key_third_person = "mews"
message = "mews hysterically!"
message_mime = "makes a cat face!"
- emote_sound = 'modular_splurt/sound/voice/meow_meme.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/meow_meme.ogg'
emote_cooldown = 1 SECONDS
/datum/emote/living/burp/run_emote(mob/user, params, type_override, intentional)
@@ -307,12 +256,13 @@
if(.)
playsound(user, pick(burp_noises), 50, 1)
-/datum/emote/living/audio/bleat
+/datum/emote/sound/human/bleat
key = "bleat"
key_third_person = "bleats"
message = "bleats loudly!"
message_mime = "bleats silently!"
- emote_sound = 'modular_splurt/sound/voice/bleat.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/bleat.ogg'
emote_cooldown = 0.7 SECONDS
// /datum/emote/living/carbon/moan/run_emote(mob/user, params, type_override, intentional) //I can't not port this shit, come on.
@@ -335,495 +285,572 @@
// message = "makes a very loud noise."
// . = ..()
-/datum/emote/living/audio/chitter2
+/datum/emote/sound/human/chitter2
key = "chitter2"
key_third_person = "chitters2"
message = "chitters."
message_mime = "chitters silently!"
- emote_sound = 'modular_splurt/sound/voice/moth/mothchitter2.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/moth/mothchitter2.ogg'
emote_cooldown = 0.3 SECONDS
-/datum/emote/living/audio/monkeytwerk
+/datum/emote/sound/human/monkeytwerk
key = "twerk"
key_third_person = "twerks"
message = "shakes it harder than James Russle himself!"
- emote_sound = 'modular_splurt/sound/misc/monkey_twerk.ogg'
+ emote_type = EMOTE_BOTH
+ sound = 'modular_splurt/sound/misc/monkey_twerk.ogg'
emote_cooldown = 3.2 SECONDS
-/datum/emote/living/audio/bruh
+/datum/emote/sound/human/bruh
key = "bruh"
key_third_person = "bruhs"
message = "thinks this is a bruh moment."
message_mime = "silently acknowledges the bruh moment."
- emote_sound = 'modular_splurt/sound/voice/bruh.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/bruh.ogg'
emote_cooldown = 0.6 SECONDS
-/datum/emote/living/audio/bababooey
+/datum/emote/sound/human/bababooey
key = "bababooey"
key_third_person = "bababooeys"
message = "spews bababooey."
message_mime = "spews something silently."
- emote_sound = 'modular_splurt/sound/voice/bababooey/bababooey.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/bababooey/bababooey.ogg'
emote_cooldown = 0.9 SECONDS
-/datum/emote/living/audio/bababooey/run_emote(mob/user, params)
+/datum/emote/sound/human/bababooey/run_emote(mob/user, params)
// Check if user is muzzled
if(user.is_muzzled())
// Set muzzled sound
- emote_sound = 'modular_splurt/sound/voice/bababooey/ffff.ogg'
+ sound = 'modular_splurt/sound/voice/bababooey/ffff.ogg'
// User is not muzzled
else
// Set random emote sound
- emote_sound = pick('modular_splurt/sound/voice/bababooey/bababooey.ogg', 'modular_splurt/sound/voice/bababooey/bababooey2.ogg')
+ sound = pick('modular_splurt/sound/voice/bababooey/bababooey.ogg', 'modular_splurt/sound/voice/bababooey/bababooey2.ogg')
// Return normally
. = ..()
-/datum/emote/living/audio/babafooey
+/datum/emote/sound/human/babafooey
key = "babafooey"
key_third_person = "babafooeys"
message = "spews babafooey."
message_mime = "spews something silently."
- emote_sound = 'modular_splurt/sound/voice/bababooey/babafooey.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/bababooey/babafooey.ogg'
emote_cooldown = 0.85 SECONDS
-/datum/emote/living/audio/fafafooey
+/datum/emote/sound/human/fafafooey
key = "fafafooey"
key_third_person = "fafafooeys"
message = "spews fafafooey."
message_mime = "spews something silently."
- emote_sound = 'modular_splurt/sound/voice/bababooey/fafafooey.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/bababooey/fafafooey.ogg'
emote_cooldown = 0.7 SECONDS
-/datum/emote/living/audio/fafafooey/run_emote(mob/user, params)
+/datum/emote/sound/human/fafafooey/run_emote(mob/user, params)
// Check if user is muzzled
if(user.is_muzzled())
// Set muzzled sound
- emote_sound = 'modular_splurt/sound/voice/bababooey/ffff.ogg'
+ sound = 'modular_splurt/sound/voice/bababooey/ffff.ogg'
// User is not muzzled
else
// Set random emote sound
- emote_sound = pick('modular_splurt/sound/voice/bababooey/fafafooey.ogg', 'modular_splurt/sound/voice/bababooey/fafafooey2.ogg', 'modular_splurt/sound/voice/bababooey/fafafooey3.ogg')
+ sound = pick('modular_splurt/sound/voice/bababooey/fafafooey.ogg', 'modular_splurt/sound/voice/bababooey/fafafooey2.ogg', 'modular_splurt/sound/voice/bababooey/fafafooey3.ogg')
// Return normally
. = ..()
-/datum/emote/living/audio/fafafoggy
+/datum/emote/sound/human/fafafoggy
key = "fafafoggy"
key_third_person = "fafafoggys"
message = "spews fafafoggy."
message_mime = "spews something silently."
- emote_sound = 'modular_splurt/sound/voice/bababooey/fafafoggy.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/bababooey/fafafoggy.ogg'
emote_cooldown = 0.9 SECONDS
-/datum/emote/living/audio/fafafoggy/run_emote(mob/user, params)
+/datum/emote/sound/human/fafafoggy/run_emote(mob/user, params)
// Check if user is muzzled
if(user.is_muzzled())
// Set muzzled sound
- emote_sound = 'modular_splurt/sound/voice/bababooey/ffff.ogg'
+ sound = 'modular_splurt/sound/voice/bababooey/ffff.ogg'
// User is not muzzled
else
// Set random emote sound
- emote_sound = pick('modular_splurt/sound/voice/bababooey/fafafoggy.ogg', 'modular_splurt/sound/voice/bababooey/fafafoggy2.ogg')
+ sound = pick('modular_splurt/sound/voice/bababooey/fafafoggy.ogg', 'modular_splurt/sound/voice/bababooey/fafafoggy2.ogg')
// Return normally
. = ..()
-/datum/emote/living/audio/hohohoy
+/datum/emote/sound/human/hohohoy
key = "hohohoy"
key_third_person = "hohohoys"
message = "spews hohohoy."
message_mime = "spews something silently."
- emote_sound = 'modular_splurt/sound/voice/bababooey/hohohoy.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/bababooey/hohohoy.ogg'
emote_cooldown = 0.7 SECONDS
-/datum/emote/living/audio/ffff
+/datum/emote/sound/human/ffff
key = "ffff"
key_third_person = "ffffs"
message = "spews something softly."
message_mime = "spews something silently."
muzzle_ignore = TRUE
- emote_sound = 'modular_splurt/sound/voice/bababooey/ffff.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/bababooey/ffff.ogg'
emote_cooldown = 0.85 SECONDS
-/datum/emote/living/audio/fafafail
+/datum/emote/sound/human/fafafail
key = "fafafail"
key_third_person = "fafafails"
message = "spews something unintelligible."
message_mime = "spews something silent."
- emote_sound = 'modular_splurt/sound/voice/bababooey/ffffhvh.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/bababooey/ffffhvh.ogg'
emote_cooldown = 1.15 SECONDS
-/datum/emote/living/audio/boowomp
+/datum/emote/sound/human/boowomp
key = "boowomp"
key_third_person = "boowomps"
message = "produces a sad boowomp."
message_mime = "produces a silent boowomp."
- emote_sound = 'modular_splurt/sound/voice/boowomp.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/boowomp.ogg'
emote_cooldown = 0.4 SECONDS
-/datum/emote/living/audio/swaos
+/datum/emote/sound/human/swaos
key = "swaos"
key_third_person = "swaos"
message = "mutters swaos."
message_mime = "imitates swaos."
- emote_sound = 'modular_splurt/sound/voice/swaos.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/swaos.ogg'
emote_cooldown = 0.7 SECONDS
-/datum/emote/living/audio/eyebrow2
+/datum/emote/sound/human/eyebrow2
key = "eyebrow2"
key_third_person = "eyebrows2"
+ name = "raise eyebrow"
message = "raises an eyebrow."
message_mime = "raises an eyebrow with quaking force!"
- emote_sound = 'modular_splurt/sound/voice/vineboom.ogg'
+ emote_type = EMOTE_VISIBLE
+ sound = 'modular_splurt/sound/voice/vineboom.ogg'
emote_cooldown = 2.9 SECONDS
-/datum/emote/living/audio/eyebrow3
+/datum/emote/sound/human/eyebrow3
key = "eyebrow3"
key_third_person = "eyebrows3"
+ name = "eyebrow quizzaciously"
message = "raises an eyebrow quizzaciously."
- emote_sound = 'modular_splurt/sound/voice/moonmen.ogg'
+ emote_type = EMOTE_BOTH
+ sound = 'modular_splurt/sound/voice/moonmen.ogg'
emote_cooldown = 7 SECONDS
-/datum/emote/living/audio/blink2
+/datum/emote/sound/human/blink2
key = "blink2"
key_third_person = "blinks2"
+ name = "blink expressively"
message = "blinks."
message_mime = "blinks expressively."
- emote_sound = 'modular_splurt/sound/voice/blink.ogg'
+ emote_type = EMOTE_VISIBLE
+ sound = 'modular_splurt/sound/voice/blink.ogg'
emote_cooldown = 0.25 SECONDS
-/datum/emote/living/audio/laugh2
+/datum/emote/sound/human/laugh2
key = "laugh2"
key_third_person = "laughs2"
+ name = "king laugh"
message = "laughs like a king."
message_mime = "acts out laughing like a king."
- emote_sound = 'modular_splurt/sound/voice/laugh_king.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/laugh_king.ogg'
// No cooldown var required
-/datum/emote/living/audio/laugh3
+/datum/emote/sound/human/laugh3
key = "laugh3"
key_third_person = "laughs3"
+ name = "silly laugh"
message = "laughs silly."
message_mime = "acts out laughing silly."
- emote_sound = 'modular_splurt/sound/voice/lol.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/lol.ogg'
emote_cooldown = 6.1 SECONDS
-/datum/emote/living/audio/laugh4
+/datum/emote/sound/human/laugh4
key = "laugh4"
key_third_person = "laughs4"
+ name = "burst laughter"
message = "burst into laughter!"
message_mime = "acts out bursting into laughter."
- emote_sound = 'modular_splurt/sound/voice/laugh_muta.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/laugh_muta.ogg'
emote_cooldown = 3 SECONDS
-/datum/emote/living/audio/laugh5
+/datum/emote/sound/human/laugh5
key = "laugh5"
key_third_person = "laughs5"
+ name = "scottish laugh"
message = "laughs in Scottish."
message_mime = "acts out laughing in Scottish."
- emote_sound = 'modular_splurt/sound/voice/laugh_deman.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/laugh_deman.ogg'
emote_cooldown = 2.75 SECONDS
-/datum/emote/living/audio/laugh6
+/datum/emote/sound/human/laugh6
key = "laugh6"
key_third_person = "laughs6"
+ name = "kettle laugh"
message = "laughs like a kettle!"
message_mime = "acts out laughing like a kettle."
- emote_sound = 'modular_splurt/sound/voice/laugh6.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/laugh6.ogg'
emote_cooldown = 4.45 SECONDS
-/datum/emote/living/audio/breakbad
+/datum/emote/sound/human/breakbad
key = "breakbad"
key_third_person = "breakbads"
message = "stares intensively with determination."
- emote_sound = 'modular_splurt/sound/voice/breakbad.ogg'
+ emote_type = EMOTE_BOTH
+ sound = 'modular_splurt/sound/voice/breakbad.ogg'
emote_cooldown = 6.4 SECONDS
-/datum/emote/living/audio/lawyerup
+/datum/emote/sound/human/lawyerup
key = "lawyerup"
key_third_person = "lawyerups"
+ name = "aura expertise"
message = "emits an aura of expertise."
- emote_sound = 'modular_splurt/sound/voice/lawyerup.ogg'
+ emote_type = EMOTE_BOTH
+ sound = 'modular_splurt/sound/voice/lawyerup.ogg'
emote_cooldown = 7.5 SECONDS
-/datum/emote/living/audio/goddamn
+/datum/emote/sound/human/goddamn
key = "damn"
key_third_person = "damns"
+ name = "gah damn"
message = "is in utter stupor."
message_mime = "appears to be in utter stupor."
- emote_sound = 'modular_splurt/sound/voice/god_damn.ogg'
+ emote_type = EMOTE_BOTH
+ sound = 'modular_splurt/sound/voice/god_damn.ogg'
emote_cooldown = 1.25 SECONDS
-/datum/emote/living/audio/spoonful
+/datum/emote/sound/human/spoonful
key = "spoonful"
key_third_person = "spoonfuls"
message = "asks for a spoonful."
message_mime = "pretends to ask for a spoonful."
- emote_sound = 'modular_splurt/sound/voice/spoonful.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/spoonful.ogg'
// No cooldown var required
-/datum/emote/living/audio/ohhmygod
+/datum/emote/sound/human/ohhmygod
key = "mygod"
key_third_person = "omgs"
+ name = "oooh my god"
message = "invokes the presence of Jesus Christ."
message_mime = "invokes the presence of Jesus Christ through silent prayer."
- emote_sound = 'modular_splurt/sound/voice/OMG.ogg'
+ emote_type = EMOTE_OMNI
+ sound = 'modular_splurt/sound/voice/OMG.ogg'
emote_cooldown = 1.6 SECONDS
-/datum/emote/living/audio/whatthehell
+/datum/emote/sound/human/whatthehell
key = "wth"
key_third_person = "wths"
+ name = "whut the heeell"
message = "condemns the abysses of hell!"
message_mime = "silently condemns the abysses of hell!"
- emote_sound = 'modular_splurt/sound/voice/WTH.ogg'
+ emote_type = EMOTE_OMNI
+ sound = 'modular_splurt/sound/voice/WTH.ogg'
emote_cooldown = 4.4 SECONDS
-/datum/emote/living/audio/fusrodah
+/datum/emote/sound/human/fusrodah
key = "fusrodah"
key_third_person = "furodahs"
message = "yells, \"FUS RO DAH!!!\""
message_mime = "acts out a dragon shout."
- emote_sound = 'modular_splurt/sound/voice/fusrodah.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/fusrodah.ogg'
emote_cooldown = 7 SECONDS
-/datum/emote/living/audio/skibidi
+/datum/emote/sound/human/skibidi
key = "skibidi"
key_third_person = "skibidis"
+ name = "skibidi bop mm dada"
message = "yells, \"Skibidi bop mm dada!\""
message_mime = "makes incoherent mouth motions."
- emote_sound = 'modular_splurt/sound/voice/skibidi.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/skibidi.ogg'
emote_cooldown = 1.1 SECONDS
-/datum/emote/living/audio/fbi
+/datum/emote/sound/human/fbi
key = "fbi"
key_third_person = "fbis"
message = "yells, \"FBI OPEN UP!\""
message_mime = "acts out being the FBI."
- emote_sound = 'modular_splurt/sound/voice/fbi.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/fbi.ogg'
emote_cooldown = 2 SECONDS
-/datum/emote/living/audio/illuminati
+/datum/emote/sound/human/illuminati
key = "illuminati"
key_third_person = "illuminatis"
message = "exudes a mysterious aura!"
- emote_sound = 'modular_splurt/sound/voice/illuminati.ogg'
+ emote_type = EMOTE_OMNI
+ sound = 'modular_splurt/sound/voice/illuminati.ogg'
emote_cooldown = 7.8 SECONDS
-/datum/emote/living/audio/bonerif
+/datum/emote/sound/human/bonerif
key = "bonerif"
key_third_person = "bonerifs"
message = "riffs!"
message_mime = "riffs silently!"
- emote_sound = 'modular_splurt/sound/voice/bonerif.ogg'
+ emote_type = EMOTE_VISIBLE
+ restraint_check = TRUE
+ sound = 'modular_splurt/sound/voice/bonerif.ogg'
emote_cooldown = 2 SECONDS
-/datum/emote/living/audio/cry2
+/datum/emote/sound/human/cry2
key = "cry2"
key_third_person = "cries2"
+ name = "king cry"
message = "cries like a king."
message_mime = "acts out crying like a king."
- emote_sound = 'modular_splurt/sound/voice/cry_king.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/cry_king.ogg'
emote_cooldown = 1.6 SECONDS // Uses longest sound's time
-/datum/emote/living/audio/cry2/run_emote(mob/user, params)
+/datum/emote/sound/human/cry2/run_emote(mob/user, params)
// Set random emote sound
- emote_sound = pick('modular_splurt/sound/voice/cry_king.ogg', 'modular_splurt/sound/voice/cry_king2.ogg')
+ sound = pick('modular_splurt/sound/voice/cry_king.ogg', 'modular_splurt/sound/voice/cry_king2.ogg')
// Return normally
. = ..()
-/datum/emote/living/audio/choir
+/datum/emote/sound/human/choir
key = "choir"
key_third_person = "choirs"
message = "let out a choir!"
message_mime = "acts out a choir."
- emote_sound = 'modular_splurt/sound/voice/choir.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/choir.ogg'
emote_cooldown = 6 SECONDS
-/datum/emote/living/audio/agony
+/datum/emote/sound/human/agony
key = "agony"
key_third_person = "agonys"
message = "let out a choir of agony!"
message_mime = "is visibly in agony."
- emote_sound = 'modular_splurt/sound/voice/agony.ogg'
+ emote_type = EMOTE_OMNI
+ sound = 'modular_splurt/sound/voice/agony.ogg'
emote_cooldown = 7 SECONDS
-/datum/emote/living/audio/wtune
+/datum/emote/sound/human/wtune
key = "whistletune"
key_third_person = "whistletunes"
message = "whistles a tune."
message_mime = "makes an expression as if whistling."
- emote_sound = 'modular_splurt/sound/voice/wtune1.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/wtune1.ogg'
emote_cooldown = 4.55 SECONDS // Uses longest sound's time.
-/datum/emote/living/audio/wtune/run_emote(mob/user, params)
+/datum/emote/sound/human/wtune/run_emote(mob/user, params)
// Set random emote sound
- emote_sound = pick('modular_splurt/sound/voice/wtune1.ogg', 'modular_splurt/sound/voice/wtune2.ogg')
+ sound = pick('modular_splurt/sound/voice/wtune1.ogg', 'modular_splurt/sound/voice/wtune2.ogg')
// Return normally
. = ..()
-/datum/emote/living/audio/fiufiu
+/datum/emote/sound/human/fiufiu
key = "wolfwhistle"
key_third_person = "wolfwhistles"
message = "wolf-whistles!" // i am not creative
message_param = "audibly approves %t's appearance."
message_mime = "makes an expression as if inappropriately whistling."
- emote_sound = 'modular_splurt/sound/voice/wolfwhistle.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/wolfwhistle.ogg'
emote_cooldown = 0.78 SECONDS
-/datum/emote/living/audio/terror
+/datum/emote/sound/human/terror
key = "terror"
key_third_person = "terrors"
+ name = "dreadful tune"
message = "whistles some dreadful tune..."
message_mime = "stares with aura full of dread..."
- emote_sound = 'modular_splurt/sound/voice/terror1.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/terror1.ogg'
emote_cooldown = 13.07 SECONDS // Uses longest sound's time.
-/datum/emote/living/audio/terror/run_emote(mob/user, params)
+/datum/emote/sound/human/terror/run_emote(mob/user, params)
// Set random emote sound
- emote_sound = pick('modular_splurt/sound/voice/terror1.ogg', 'modular_splurt/sound/voice/terror2.ogg')
+ sound = pick('modular_splurt/sound/voice/terror1.ogg', 'modular_splurt/sound/voice/terror2.ogg')
// Return normally
. = ..()
-/datum/emote/living/audio/deathglare
+/datum/emote/sound/human/deathglare
key = "glare2"
key_third_person = "glares2"
message = "glares."
message_param = "glares at %t."
- emote_sound = 'modular_splurt/sound/voice/deathglare.ogg'
+ emote_type = EMOTE_VISIBLE
+ sound = 'modular_splurt/sound/voice/deathglare.ogg'
emote_cooldown = 4.4 SECONDS
-/datum/emote/living/audio/sicko
+/datum/emote/sound/human/sicko
key = "sicko"
key_third_person = "sickos"
message = "briefly goes sicko mode!"
message_mime = "briefly imitates sicko mode!"
- emote_sound = 'modular_splurt/sound/voice/sicko.ogg'
+ sound = 'modular_splurt/sound/voice/sicko.ogg'
emote_cooldown = 0.8 SECONDS
-/datum/emote/living/audio/chill
+/datum/emote/sound/human/chill
key = "chill"
key_third_person = "chills"
message = "feels a chill running down their spine..."
message_mime = "acts out a chill running down their spine..."
- emote_sound = 'modular_splurt/sound/voice/waterphone.ogg'
+ emote_type = EMOTE_VISIBLE
+ sound = 'modular_splurt/sound/voice/waterphone.ogg'
emote_cooldown = 3.4 SECONDS
-/datum/emote/living/audio/taunt
+/datum/emote/sound/human/taunt
key = "tt"
key_third_person = "taunts"
+ name = "strike pose"
message = "strikes a pose!"
message_param = "taunts %t!"
- emote_sound = 'modular_splurt/sound/voice/phillyhit.ogg'
+ emote_type = EMOTE_VISIBLE
+ restraint_check = TRUE
+ sound = 'modular_splurt/sound/voice/phillyhit.ogg'
-/datum/emote/living/audio/taunt/alt
+/datum/emote/sound/human/taunt/alt
key = "tt2"
key_third_person = "taunts2"
+ name = "strike pose 2"
emote_volume = 100
- emote_sound = 'modular_splurt/sound/voice/orchestrahit.ogg'
+ sound = 'modular_splurt/sound/voice/orchestrahit.ogg'
-/datum/emote/living/audio/weh2
+/datum/emote/sound/human/weh2
key = "weh2"
key_third_person = "wehs2"
+ name = "weh 2"
message = "let out a weh!"
message_mime = "acts out a weh!"
- emote_sound = 'modular_splurt/sound/voice/weh2.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/weh2.ogg'
emote_cooldown = 0.25 SECONDS
-/datum/emote/living/audio/weh3
+/datum/emote/sound/human/weh3
key = "weh3"
key_third_person = "wehs3"
+ name = "weh 3"
message = "let out a weh!"
message_mime = "acts out a weh!"
- emote_sound = 'modular_splurt/sound/voice/weh3.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/weh3.ogg'
emote_cooldown = 0.25 SECONDS
-/datum/emote/living/audio/weh4
+/datum/emote/sound/human/weh4
key = "weh4"
key_third_person = "wehs4"
+ name = "surprised weh"
message = "let out a surprised weh!"
message_mime = "acts out a surprised weh!"
- emote_sound = 'modular_splurt/sound/voice/weh_s.ogg'
+ emote_type = EMOTE_BOTH
+ sound = 'modular_splurt/sound/voice/weh_s.ogg'
emote_cooldown = 0.35 SECONDS
-/datum/emote/living/audio/waa
+/datum/emote/sound/human/waa
key = "waa"
key_third_person = "waas"
message = "let out a waa!"
message_mime = "acts out a waa!"
- emote_sound = 'modular_splurt/sound/voice/waa.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/waa.ogg'
emote_cooldown = 3.5 SECONDS
-/datum/emote/living/audio/bark2
+/datum/emote/sound/human/bark2
key = "bark2"
key_third_person = "barks2"
+ name = "bark 2"
message = "barks!"
message_mime = "acts out a bark!"
- emote_sound = 'modular_splurt/sound/voice/bark_alt.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/bark_alt.ogg'
emote_cooldown = 0.35 SECONDS
-/datum/emote/living/audio/yap
+/datum/emote/sound/human/yap
key = "yap"
key_third_person = "yaps"
message = "yaps!"
message_mime = "acts out a yap!"
- emote_sound = 'modular_splurt/sound/voice/yap.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/yap.ogg'
emote_cooldown = 0.28 SECONDS
-/datum/emote/living/audio/yip
+/datum/emote/sound/human/yip
key = "yip"
key_third_person = "yips"
message = "yips!"
message_mime = "acts out a yip!"
- emote_sound = 'modular_splurt/sound/voice/yip.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/yip.ogg'
emote_cooldown = 0.2 SECONDS
-/datum/emote/living/audio/bork
+/datum/emote/sound/human/bork
key = "bork"
key_third_person = "borks"
message = "borks!"
message_mime = "acts out a bork!"
- emote_sound = 'modular_splurt/sound/voice/bork.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/bork.ogg'
emote_cooldown = 0.4 SECONDS
-/datum/emote/living/audio/woof
+/datum/emote/sound/human/woof
key = "woof"
key_third_person = "woofs"
message = "woofs!"
message_mime = "acts out a woof!"
- emote_sound = 'modular_splurt/sound/voice/woof.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/woof.ogg'
emote_cooldown = 0.71 SECONDS
-/datum/emote/living/audio/woof/alt
+/datum/emote/sound/human/woof/alt
key = "woof2"
key_third_person = "woofs2"
- emote_sound = 'modular_splurt/sound/voice/woof2.ogg'
+ name = "woof 2"
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/woof2.ogg'
emote_cooldown = 0.3 SECONDS
-/datum/emote/living/audio/howl
+/datum/emote/sound/human/howl
key = "howl"
key_third_person = "howls"
message = "howls!"
message_mime = "acts out a howl!"
- emote_sound = 'modular_splurt/sound/voice/wolfhowl.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/wolfhowl.ogg'
emote_cooldown = 2.04 SECONDS
-/datum/emote/living/audio/coyhowl
+/datum/emote/sound/human/coyhowl
key = "coyhowl"
key_third_person = "coyhowls"
+ name = "coyote howl"
message = "howls like coyote!"
message_mime = "acts out a coyote's howl!"
- emote_sound = 'modular_splurt/sound/voice/coyotehowl.ogg'
+ emote_type = EMOTE_BOTH
+ sound = 'modular_splurt/sound/voice/coyotehowl.ogg'
emote_cooldown = 2.94 SECONDS // Uses longest sound's time
-/datum/emote/living/audio/coyhowl/run_emote(mob/user, params)
- emote_sound = pick('modular_splurt/sound/voice/coyotehowl.ogg', 'modular_splurt/sound/voice/coyotehowl2.ogg', 'modular_splurt/sound/voice/coyotehowl3.ogg', 'modular_splurt/sound/voice/coyotehowl4.ogg', 'modular_splurt/sound/voice/coyotehowl5.ogg')
+/datum/emote/sound/human/coyhowl/run_emote(mob/user, params)
+ sound = pick('modular_splurt/sound/voice/coyotehowl.ogg', 'modular_splurt/sound/voice/coyotehowl2.ogg', 'modular_splurt/sound/voice/coyotehowl3.ogg', 'modular_splurt/sound/voice/coyotehowl4.ogg', 'modular_splurt/sound/voice/coyotehowl5.ogg')
. = ..()
/datum/emote/living/mlem
@@ -832,15 +859,17 @@
message = "sticks their tongue for a moment. Mlem!"
emote_type = EMOTE_VISIBLE
-/datum/emote/living/audio/snore/snore2
+/datum/emote/sound/human/snore/snore2
key = "snore2"
key_third_person = "snores2"
+ name = "earthshaking snore"
message = "lets out an earthshaking snore"
message_mime = "lets out an inaudible snore!"
- emote_sound = 'modular_splurt/sound/voice/aauugghh1.ogg'
+ emote_type = EMOTE_BOTH
+ sound = 'modular_splurt/sound/voice/aauugghh1.ogg'
emote_cooldown = 2.1 SECONDS
-/datum/emote/living/audio/snore/snore2/run_emote(mob/user, params)
+/datum/emote/sound/human/snore/snore2/run_emote(mob/user, params)
var/datum/dna/D = user.has_dna()
var/say_mod = (D ? D.species.say_mod : "says")
var/list/aaauughh = list(
@@ -851,7 +880,7 @@
message = pick(aaauughh)
// Set random emote sound
- emote_sound = pick('modular_splurt/sound/voice/aauugghh1.ogg', 'modular_splurt/sound/voice/aauugghh2.ogg')
+ sound = pick('modular_splurt/sound/voice/aauugghh1.ogg', 'modular_splurt/sound/voice/aauugghh2.ogg')
// Return normally
. = ..()
@@ -859,6 +888,7 @@
/datum/emote/living/pant
key = "pant"
key_third_person = "pants"
+ emote_type = EMOTE_VISIBLE
message = "pants!"
/datum/emote/living/pant/run_emote(mob/user, params, type_override, intentional)
@@ -871,63 +901,69 @@
message = pick(pants)
. = ..()
-/datum/emote/living/audio/yippee
+/datum/emote/sound/human/yippee
key = "yippee"
key_third_person = "yippees"
message = "lets out a yippee!"
message_mime = "acts out a yippee!"
- emote_sound = 'modular_splurt/sound/voice/yippee.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/yippee.ogg'
emote_cooldown = 1.2 SECONDS
-/datum/emote/living/audio/mewo
+/datum/emote/sound/human/mewo
key = "mewo"
key_third_person = "mewos"
message = "mewos!"
message_mime = "mewos silently!"
- emote_sound = 'modular_splurt/sound/voice/mewo.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/mewo.ogg'
emote_cooldown = 0.7 SECONDS
-/datum/emote/living/audio/ara_ara
+/datum/emote/sound/human/ara_ara
key = "ara"
key_third_person = "aras"
+ name = "ara ara"
message = "coos with sultry surprise~..."
message_mime = "exudes a sultry aura~"
- emote_sound = 'modular_splurt/sound/voice/ara-ara.ogg'
+ emote_type = EMOTE_BOTH
+ sound = 'modular_splurt/sound/voice/ara-ara.ogg'
emote_cooldown = 1.25 SECONDS
-/datum/emote/living/audio/ara_ara/alt
+/datum/emote/sound/human/ara_ara/alt
key = "ara2"
- emote_sound = 'modular_splurt/sound/voice/ara-ara2.ogg'
+ name = "ara ara 2"
+ sound = 'modular_splurt/sound/voice/ara-ara2.ogg'
emote_cooldown = 1.3 SECONDS
-/datum/emote/living/audio/missouri
+/datum/emote/sound/human/missouri
key = "missouri"
key_third_person = "missouris"
message = "has relocated to Missouri."
message_mime = "starts thinking about Missouri."
- emote_sound = 'modular_splurt/sound/voice/missouri.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/missouri.ogg'
emote_cooldown = 3.4 SECONDS
-/datum/emote/living/audio/missouri/run_emote(mob/user, params)
+/datum/emote/sound/human/missouri/run_emote(mob/user, params)
// Set message pronouns
message = "appears to believe [user.p_theyre()] in Missouri."
// Return normally
. = ..()
-/datum/emote/living/audio/facemetacarpus
+/datum/emote/sound/human/facemetacarpus
key = "facehand" // Facepalm was taken
key_third_person = "facepalms"
// Message is generated from metacarpus_type below. You shouldn't see this!
message = "creates an error in the code." // Hear a slapping sound
muzzle_ignore = TRUE // Not a spoken emote
restraint_check = TRUE // Uses your hands
- emote_sound = 'modular_splurt/sound/effects/slap.ogg'
+ sound = 'modular_splurt/sound/effects/slap.ogg'
// Defines appendage type for generated message
var/metacarpus_type = "palm" // Default to hands
emote_cooldown = 0.25 SECONDS
-/datum/emote/living/audio/facemetacarpus/run_emote(mob/user, params)
+/datum/emote/sound/human/facemetacarpus/run_emote(mob/user, params)
// Randomly pick a message using metacarpus_type for hand
message = pick(list(
"places [usr.p_their()] [metacarpus_type] across [usr.p_their()] face.",
@@ -938,35 +974,35 @@
// Return normally
. = ..()
-/datum/emote/living/audio/facemetacarpus/paw
+/datum/emote/sound/human/facemetacarpus/paw
key = "facepaw" // For furries
key_third_person = "facepaws"
metacarpus_type = "paw"
-/datum/emote/living/audio/facemetacarpus/claw
+/datum/emote/sound/human/facemetacarpus/claw
key = "faceclaw" // For scalies and avians
key_third_person = "faceclaws"
metacarpus_type = "claw"
-/datum/emote/living/audio/facemetacarpus/wing
+/datum/emote/sound/human/facemetacarpus/wing
key = "facewing" // For avians, harpies or just anyone with wings
key_third_person = "facewings"
metacarpus_type = "wing"
-/datum/emote/living/audio/facemetacarpus/hoof
+/datum/emote/sound/human/facemetacarpus/hoof
key = "facehoof" // For horse enthusiasts
key_third_person = "facehoofs"
metacarpus_type = "hoof"
-/datum/emote/living/audio/poyo
+/datum/emote/sound/human/poyo
key = "poyo"
key_third_person = "poyos"
message = "%SAYS, \"Poyo!\""
message_mime = "acts out an excited motion!"
- emote_sound = 'modular_splurt/sound/voice/barks/poyo.ogg'
+ sound = 'modular_splurt/sound/voice/barks/poyo.ogg'
// No cooldown var required
-/datum/emote/living/audio/poyo/run_emote(mob/user, params)
+/datum/emote/sound/human/poyo/run_emote(mob/user, params)
var/datum/dna/D = user.has_dna()
var/say_mod = (D ? D.species.say_mod : "says")
message = replacetextEx(message, "%SAYS", say_mod)
@@ -974,548 +1010,620 @@
// Return normally
. = ..()
-/datum/emote/living/audio/rizz
+
+/datum/emote/sound/human/rizz
key = "rizz"
key_third_person = "rizzes"
+ name = "THE LOOK"
message = "gives \[The Look\]."
message_param = "looks at %t with bedroom eyes."
message_mime = "makes bedroom eyes."
- emote_sound = 'modular_splurt/sound/voice/rizz.ogg'
+ emote_type = EMOTE_VISIBLE
+ sound = 'modular_splurt/sound/voice/rizz.ogg'
emote_cooldown = 1.43 SECONDS
-/datum/emote/living/audio/buff
+/datum/emote/sound/human/buff
key = "buff"
key_third_person = "buffs"
+ name = "show muscles"
message = "shows off their muscles."
message_param = "shows off their muscles to %t."
- emote_sound = 'modular_splurt/sound/voice/buff.ogg'
+ emote_type = EMOTE_VISIBLE
+ sound = 'modular_splurt/sound/voice/buff.ogg'
emote_cooldown = 4.77 SECONDS
emote_pitch_variance = FALSE
-/datum/emote/living/audio/merowr
+/datum/emote/sound/human/merowr
key = "merowr"
key_third_person = "merowrs"
message = "merowrs!"
message_mime = "acts out a merowr!"
- emote_sound = 'modular_splurt/sound/voice/merowr.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/merowr.ogg'
emote_cooldown = 1.2 SECONDS
-/datum/emote/living/audio/hoot
+/datum/emote/sound/human/hoot
key = "hoot"
key_third_person = "hoots"
message = "hoots!"
message_mime = "acts out a hoot!"
- emote_sound = 'modular_splurt/sound/voice/hoot.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/hoot.ogg'
emote_cooldown = 2.4 SECONDS
-/datum/emote/living/audio/wurble
+/datum/emote/sound/human/wurble
key = "wurble"
key_third_person = "wurbles"
message = "wurbles!"
message_mime = "acts out a wurbling!"
- emote_sound = 'modular_splurt/sound/voice/wurble.ogg'
+ emote_type = EMOTE_BOTH
+ sound = 'modular_splurt/sound/voice/wurble.ogg'
emote_cooldown = 2.3 SECONDS
-/datum/emote/living/audio/warble
+/datum/emote/sound/human/warble
key = "warble"
key_third_person = "warbles"
message = "warbles!"
message_mime = "acts out a warbling!"
- emote_sound = 'modular_splurt/sound/voice/warble.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/warble.ogg'
emote_cooldown = 0.4 SECONDS
-// At the moment of adding it I just realized there's Tesh test-merge going on, so I've added numeral in case if that gets merged in the long run.
-/datum/emote/living/audio/trill2
+//Teshari took *trill
+/datum/emote/sound/human/trill2
key = "trill2"
key_third_person = "trills2"
+ name = "trill"
message = "trills!"
message_mime = "acts out a trilling!"
- emote_sound = 'modular_splurt/sound/voice/trill.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/trill.ogg'
emote_cooldown = 1 SECONDS
-/datum/emote/living/audio/rattlesnek
+/datum/emote/sound/human/rattlesnek
key = "rattle"
key_third_person = "rattles"
message = "rattles!"
message_mime = "acts like a rattling snake."
- emote_sound = 'modular_splurt/sound/voice/rattle.ogg'
+ emote_type = EMOTE_BOTH
+ sound = 'modular_splurt/sound/voice/rattle.ogg'
emote_cooldown = 4 SECONDS
-/datum/emote/living/audio/rpurr
+/datum/emote/sound/human/rpurr
key = "rpurr"
key_third_person = "rpurrs"
+ name = "raptor purr"
message = "purrs like raptor!"
message_mime = "acts like a purring raptor."
- emote_sound = 'modular_splurt/sound/voice/raptor_purr.ogg'
+ emote_type = EMOTE_BOTH
+ sound = 'modular_splurt/sound/voice/raptor_purr.ogg'
emote_cooldown = 1.5 SECONDS
-/datum/emote/living/audio/bawk
+/datum/emote/sound/human/bawk
key = "bawk"
key_third_person = "bawks"
message = "bawks!"
message_mime = "acts like a bawking chicken."
- emote_sound = 'modular_splurt/sound/voice/bawk.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/bawk.ogg'
emote_cooldown = 0.5 SECONDS
-/datum/emote/living/audio/moo
+/datum/emote/sound/human/moo
key = "moo"
key_third_person = "moos"
message = "moos!"
message_mime = "acts like a mooing cow."
- emote_sound = 'modular_splurt/sound/voice/moo.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/moo.ogg'
emote_cooldown = 1.7 SECONDS
-/datum/emote/living/audio/coo
+/datum/emote/sound/human/coo
key = "coo"
key_third_person = "coos"
message = "coos."
message_mime = "acts like a cooing pidgeon."
emote_volume = 30
- emote_sound = 'modular_splurt/sound/voice/coo.ogg'
+ sound = 'modular_splurt/sound/voice/coo.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 0.78 SECONDS
-/datum/emote/living/audio/untitledgoose
+/datum/emote/sound/human/untitledgoose
key = "goosehonk"
- key_third_person = "honks"
+ key_third_person = "goosehonks"
+ name = "goose honk"
message = "honks!"
message_mime = "looks like a duck from hell!"
- emote_sound = 'modular_splurt/sound/voice/goosehonk/sfx_goose_honk_b_01.ogg'
- emote_cooldown = 0.8 SECONDS
-
-/datum/emote/living/audio/untitledgoose/run_emote(mob/user, params)
- emote_sound = pick('modular_splurt/sound/voice/goosehonk/sfx_goose_honk_b_01.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_goose_honk_b_02.ogg','modular_splurt/sound/voice/goosehonk/sfx_goose_honk_b_03.ogg','modular_splurt/sound/voice/goosehonk/sfx_goose_honk_b_06.ogg')
- . = ..()
-
-/datum/emote/living/audio/untitledgooseB
- key = "goosehonkb"
- key_third_person = "honks differently"
- message = "honks differently!"
- message_mime = "looks like a duck from hell!"
- emote_sound = 'modular_splurt/sound/voice/goosehonk/sfx_goose_honk_b_01.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/goosehonk/sfx_goose_honk_b_01.ogg'
emote_cooldown = 0.8 SECONDS
-/datum/emote/living/audio/untitledgooseB/run_emote(mob/user, params)
- emote_sound = pick('modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_02.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_03.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_04.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_06.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_07.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_08.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_09.ogg')
+/datum/emote/sound/human/untitledgoose/run_emote(mob/user, params)
+ sound = pick('modular_splurt/sound/voice/goosehonk/sfx_goose_honk_b_01.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_goose_honk_b_02.ogg','modular_splurt/sound/voice/goosehonk/sfx_goose_honk_b_03.ogg','modular_splurt/sound/voice/goosehonk/sfx_goose_honk_b_06.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_02.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_03.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_04.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_06.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_07.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_08.ogg', 'modular_splurt/sound/voice/goosehonk/sfx_gooseB_honk_09.ogg')
. = ..()
-/datum/emote/living/audio/scream2
+/datum/emote/sound/human/scream2
key = "scream2"
key_third_person = "screams2"
+ name = "silly scream"
message = "screams!"
message_mime = "acts out a rather silly scream!"
- emote_sound = 'modular_splurt/sound/voice/cscream1.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/cscream1.ogg'
emote_cooldown = 3.3 SECONDS // Uses longest sound's time.
emote_pitch_variance = FALSE
-/datum/emote/living/audio/scream2/run_emote(mob/user, params)
- emote_sound = pick('modular_splurt/sound/voice/cscream1.ogg', 'modular_splurt/sound/voice/cscream2.ogg', 'modular_splurt/sound/voice/cscream3.ogg', 'modular_splurt/sound/voice/cscream4.ogg', 'modular_splurt/sound/voice/cscream5.ogg', 'modular_splurt/sound/voice/cscream6.ogg', 'modular_splurt/sound/voice/cscream7.ogg', 'modular_splurt/sound/voice/cscream8.ogg', 'modular_splurt/sound/voice/cscream9.ogg', 'modular_splurt/sound/voice/cscream10.ogg', 'modular_splurt/sound/voice/cscream11.ogg', 'modular_splurt/sound/voice/cscream12.ogg')
+/datum/emote/sound/human/scream2/run_emote(mob/user, params)
+ sound = pick('modular_splurt/sound/voice/cscream1.ogg', 'modular_splurt/sound/voice/cscream2.ogg', 'modular_splurt/sound/voice/cscream3.ogg', 'modular_splurt/sound/voice/cscream4.ogg', 'modular_splurt/sound/voice/cscream5.ogg', 'modular_splurt/sound/voice/cscream6.ogg', 'modular_splurt/sound/voice/cscream7.ogg', 'modular_splurt/sound/voice/cscream8.ogg', 'modular_splurt/sound/voice/cscream9.ogg', 'modular_splurt/sound/voice/cscream10.ogg', 'modular_splurt/sound/voice/cscream11.ogg', 'modular_splurt/sound/voice/cscream12.ogg')
. = ..()
// Here comes gachimuchi
-/datum/emote/living/audio/scream3
+/datum/emote/sound/human/scream3
key = "scream3"
key_third_person = "screams3"
+ name = "gachi scream"
message = "screams manly!"
message_mime = "acts out a rather manly scream!"
- emote_sound = 'modular_splurt/sound/voice/gachi/scream1.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/gachi/scream1.ogg'
emote_cooldown = 4.64 SECONDS // Uses longest sound's time.
-/datum/emote/living/audio/scream3/run_emote(mob/user, params)
- emote_sound = pick('modular_splurt/sound/voice/gachi/scream1.ogg', 'modular_splurt/sound/voice/gachi/scream2.ogg', 'modular_splurt/sound/voice/gachi/scream3.ogg', 'modular_splurt/sound/voice/gachi/scream4.ogg')
+/datum/emote/sound/human/scream3/run_emote(mob/user, params)
+ sound = pick('modular_splurt/sound/voice/gachi/scream1.ogg', 'modular_splurt/sound/voice/gachi/scream2.ogg', 'modular_splurt/sound/voice/gachi/scream3.ogg', 'modular_splurt/sound/voice/gachi/scream4.ogg')
. = ..()
-/datum/emote/living/audio/moan2
+/datum/emote/sound/human/moan2
key = "moan2"
key_third_person = "moans2"
+ name = "gachi moan"
message = "moans somewhat manly!"
message_mime = "acts out a rather manly moan!"
- emote_sound = 'modular_splurt/sound/voice/gachi/moan1.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/gachi/moan1.ogg'
emote_cooldown = 2.7 SECONDS // Uses longest sound's time.
-/datum/emote/living/audio/moan2/run_emote(mob/user, params)
- emote_sound = pick('modular_splurt/sound/voice/gachi/moan1.ogg', 'modular_splurt/sound/voice/gachi/moan2.ogg', 'modular_splurt/sound/voice/gachi/moan3.ogg', 'modular_splurt/sound/voice/gachi/moan4.ogg')
+/datum/emote/sound/human/moan2/run_emote(mob/user, params)
+ sound = pick('modular_splurt/sound/voice/gachi/moan1.ogg', 'modular_splurt/sound/voice/gachi/moan2.ogg', 'modular_splurt/sound/voice/gachi/moan3.ogg', 'modular_splurt/sound/voice/gachi/moan4.ogg')
. = ..()
-/datum/emote/living/audio/woop
+/datum/emote/sound/human/woop
key = "woop"
key_third_person = "woops"
+ name = "gachi woop"
message = "woops!"
message_mime = "silently woops!"
- emote_sound = 'modular_splurt/sound/voice/gachi/woop.ogg'
+ sound = 'modular_splurt/sound/voice/gachi/woop.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_volume = 35
emote_cooldown = 0.4 SECONDS
-/datum/emote/living/audio/whatthehell/right
+/datum/emote/sound/human/whatthehell/right
key = "wth2"
key_third_person = "wths2"
- emote_sound = 'modular_splurt/sound/voice/gachi/wth2.ogg'
+ name = "gachi what the hell"
+ sound = 'modular_splurt/sound/voice/gachi/wth2.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_volume = 100
emote_cooldown = 1.0 SECONDS
-/datum/emote/living/audio/pardon
+/datum/emote/sound/human/pardon
key = "sorry"
key_third_person = "sorrys"
+ name = "gachi sorry"
message = "exclaims, \"Oh shit, I am sorry!\""
- emote_sound = 'modular_splurt/sound/voice/gachi/sorry.ogg'
+ emote_type = EMOTE_AUDIBLE
+ sound = 'modular_splurt/sound/voice/gachi/sorry.ogg'
emote_cooldown = 1.3 SECONDS
-/datum/emote/living/audio/pardonfor
+/datum/emote/sound/human/pardonfor
key = "sorryfor"
key_third_person = "sorrysfor"
+ name = "gachi for what?"
message = "asks, \"Sorry for what?\""
- emote_sound = 'modular_splurt/sound/voice/gachi/sorryfor.ogg'
+ sound = 'modular_splurt/sound/voice/gachi/sorryfor.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 0.9 SECONDS
-/datum/emote/living/audio/fock
+/datum/emote/sound/human/fock
key = "fuckyou"
key_third_person = "fuckyous"
+ name = "gachi fuck you"
message = "curses someone!"
message_param = "curses %t!"
message_mime = "silently curses someone!"
- emote_sound = 'modular_splurt/sound/voice/gachi/fockyou1.ogg'
+ sound = 'modular_splurt/sound/voice/gachi/fockyou1.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 1.18 SECONDS // Uses longest sound's time.
-/datum/emote/living/audio/fock/run_emote(mob/user, params)
- emote_sound = pick('modular_splurt/sound/voice/gachi/fockyou1.ogg', 'modular_splurt/sound/voice/gachi/fockyou2.ogg')
+/datum/emote/sound/human/fock/run_emote(mob/user, params)
+ sound = pick('modular_splurt/sound/voice/gachi/fockyou1.ogg', 'modular_splurt/sound/voice/gachi/fockyou2.ogg')
. = ..()
-/datum/emote/living/audio/letsgo
+/datum/emote/sound/human/letsgo
key = "go"
key_third_person = "goes"
+ name = "gachi come on"
message = "yells, \"Come on, lets go!\""
message_mime = "motions moving forward!"
- emote_sound = 'modular_splurt/sound/voice/gachi/go.ogg'
+ sound = 'modular_splurt/sound/voice/gachi/go.ogg'
+ emote_type = EMOTE_BOTH
emote_cooldown = 1.6 SECONDS
-/datum/emote/living/audio/chuckle2
+/datum/emote/sound/human/chuckle2
key = "chuckle2"
key_third_person = "chuckles2"
+ name = "gachi chuckle"
message = "chuckles."
message_mime = "chuckles silently."
- emote_sound = 'modular_splurt/sound/voice/gachi/chuckle.ogg'
+ sound = 'modular_splurt/sound/voice/gachi/chuckle.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 1.01 SECONDS
-/datum/emote/living/audio/fockslaves
+/datum/emote/sound/human/fockslaves
key = "slaves"
key_third_person = "slaves"
+ name = "gachi slaves"
message = "curses slaves!"
message_mime = "silently curses slaves!"
- emote_sound = 'modular_splurt/sound/voice/gachi/fokensleves.ogg'
+ sound = 'modular_splurt/sound/voice/gachi/fokensleves.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 1.2 SECONDS
-/datum/emote/living/audio/getbuttback
+/datum/emote/sound/human/getbuttback
key = "assback"
key_third_person = "assbacks"
+ name = "gachi ass back"
message = "demands someone's ass to get back here!"
message_param = "demands %t's ass to get back here!"
message_mime = "motions for someone's ass to get back here!"
- emote_sound = 'modular_splurt/sound/voice/gachi/assback.ogg'
+ sound = 'modular_splurt/sound/voice/gachi/assback.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 1.9 SECONDS
-/datum/emote/living/audio/boss
+/datum/emote/sound/human/boss
key = "boss"
key_third_person = "boss"
+ name = "gachi boss of this gym"
message = "seeks the boss of this place!"
message_mime = "stares at the potential boss of this place!"
- emote_sound = 'modular_splurt/sound/voice/gachi/boss.ogg'
+ sound = 'modular_splurt/sound/voice/gachi/boss.ogg'
+ emote_type = EMOTE_VISIBLE
emote_cooldown = 1.68 SECONDS
-/datum/emote/living/audio/attention
+/datum/emote/sound/human/attention
key = "attention"
key_third_person = "attentions"
+ name = "atteeention"
message = "demands an attention!"
message_mime = "seems to be looking for an attention."
emote_volume = 100
- emote_sound = 'modular_splurt/sound/voice/gachi/attention.ogg'
+ sound = 'modular_splurt/sound/voice/gachi/attention.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 1.36 SECONDS
-/datum/emote/living/audio/ah
+/datum/emote/sound/human/ah
key = "ah"
key_third_person = "ahs"
+ name = "gachi ah"
message = "ahs!"
message_mime = "ahs silently!"
- emote_sound = 'modular_splurt/sound/voice/gachi/ah.ogg'
+ sound = 'modular_splurt/sound/voice/gachi/ah.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 0.67 SECONDS
emote_volume = 25
-/datum/emote/living/audio/boolets
+/datum/emote/sound/human/boolets
key = "ammo"
key_third_person = "ammos"
+ name = "more boolets"
message = "is requesting ammo!"
message_mime = "seem to ask for ammo!"
- emote_sound = 'modular_splurt/sound/voice/gachi/boolets.ogg'
+ sound = 'modular_splurt/sound/voice/gachi/boolets.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 1.1 SECONDS // Uses longest sound's time.
emote_volume = 10
-/datum/emote/living/audio/boolets/run_emote(mob/user, params)
- emote_sound = pick('modular_splurt/sound/voice/gachi/boolets.ogg', 'modular_splurt/sound/voice/gachi/boolets2.ogg')
+/datum/emote/sound/human/boolets/run_emote(mob/user, params)
+ sound = pick('modular_splurt/sound/voice/gachi/boolets.ogg', 'modular_splurt/sound/voice/gachi/boolets2.ogg')
. = ..()
-/datum/emote/living/audio/wepon
+/datum/emote/sound/human/wepon
key = "wepon"
key_third_person = "wepons"
+ name = "bigger wepons"
message = "is requesting bigger weapons!"
message_mime = "seem to ask for weapons!"
- emote_sound = 'modular_splurt/sound/voice/gachi/wepons.ogg'
+ sound = 'modular_splurt/sound/voice/gachi/wepons.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 1.07 SECONDS
emote_volume = 10
-/datum/emote/living/audio/sciteam
+/datum/emote/sound/human/sciteam
key = "sciteam"
key_third_person = "sciteams"
+ name = "Science Team"
message = "exclaims, \"I am with the Science team!\""
message_mime = "gestures being with the Science team!"
- emote_sound = 'modular_splurt/sound/voice/sciteam.ogg'
+ sound = 'modular_splurt/sound/voice/sciteam.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 1.32 SECONDS
emote_volume = 90
-/datum/emote/living/audio/ambatukam
+/datum/emote/sound/human/ambatukam
key = "ambatukam"
key_third_person = "ambatukams"
message = "is about to come!"
message_mime = "seems like about to come!"
- emote_sound = 'modular_splurt/sound/voice/ambatukam.ogg'
+ sound = 'modular_splurt/sound/voice/ambatukam.ogg'
+ emote_type = EMOTE_BOTH
emote_cooldown = 2.75 SECONDS
//emote_volume = 30
-/datum/emote/living/audio/ambatukam2
+/datum/emote/sound/human/ambatukam2
key = "ambatukam2"
key_third_person = "ambatukams2"
+ name = "ambatukam 2"
message = "is about to come in harmony!"
message_mime = "seems like about to come in harmony!"
- emote_sound = 'modular_splurt/sound/voice/ambatukam_harmony.ogg'
+ sound = 'modular_splurt/sound/voice/ambatukam_harmony.ogg'
+ emote_type = EMOTE_BOTH
emote_cooldown = 3.42 SECONDS
//emote_volume = 60
-/datum/emote/living/audio/eekum
+/datum/emote/sound/human/eekum
key = "eekumbokum"
key_third_person = "eekumbokums"
message = "eekum-bokums!"
message_mime = "seem to eekum-bokum!"
- emote_sound = 'modular_splurt/sound/voice/eekum-bokum.ogg'
+ sound = 'modular_splurt/sound/voice/eekum-bokum.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 0.9 SECONDS // Uses longest sound's time.
-/datum/emote/living/audio/eekum/run_emote(mob/user, params)
+/datum/emote/sound/human/eekum/run_emote(mob/user, params)
switch(user.gender)
if(MALE) // Game's SFX
- emote_sound = 'modular_splurt/sound/voice/eekum-bokum.ogg'
+ sound = 'modular_splurt/sound/voice/eekum-bokum.ogg'
if(FEMALE) // Korone's
- emote_sound = pick('modular_splurt/sound/voice/eekum-bokum_f1.ogg', 'modular_splurt/sound/voice/eekum-bokum_f2.ogg')
+ sound = pick('modular_splurt/sound/voice/eekum-bokum_f1.ogg', 'modular_splurt/sound/voice/eekum-bokum_f2.ogg')
else // Both
- emote_sound = pick('modular_splurt/sound/voice/eekum-bokum.ogg', 'modular_splurt/sound/voice/eekum-bokum_f1.ogg', 'modular_splurt/sound/voice/eekum-bokum_f2.ogg')
+ sound = pick('modular_splurt/sound/voice/eekum-bokum.ogg', 'modular_splurt/sound/voice/eekum-bokum_f1.ogg', 'modular_splurt/sound/voice/eekum-bokum_f2.ogg')
. = ..()
-/datum/emote/living/audio/bazinga
+/datum/emote/sound/human/bazinga
key = "bazinga"
key_third_person = "bazingas"
message = "exclaims, \"Bazinga!\""
message_mime = "fools someone, silently."
- emote_sound = 'modular_splurt/sound/voice/bazinga.ogg'
+ sound = 'modular_splurt/sound/voice/bazinga.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 0.65 SECONDS
-/datum/emote/living/audio/bazinga/run_emote(mob/user, params)
+/datum/emote/sound/human/bazinga/run_emote(mob/user, params)
if(prob(1)) // If Empah had TTS #25
- emote_sound = 'modular_splurt/sound/voice/bazinga_ebil.ogg'
+ sound = 'modular_splurt/sound/voice/bazinga_ebil.ogg'
emote_pitch_variance = FALSE
emote_cooldown = 1.92 SECONDS
emote_volume = 110
else
- emote_sound = 'modular_splurt/sound/voice/bazinga.ogg'
+ sound = 'modular_splurt/sound/voice/bazinga.ogg'
emote_pitch_variance = TRUE
emote_cooldown = 0.65 SECONDS
emote_volume = 50
. = ..()
-/datum/emote/living/audio/yooo
+/datum/emote/sound/human/yooo
key = "yooo"
key_third_person = "yooos"
message = "thinks they are part of Kabuki play."
- emote_sound = 'modular_splurt/sound/voice/yooo.ogg'
+ sound = 'modular_splurt/sound/voice/yooo.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 2.54 SECONDS
-/datum/emote/living/audio/buzzer_correct
+/datum/emote/sound/human/buzzer_correct
key = "correct"
key_third_person = "corrects"
message = "thinks someone is correct."
message_param = "thinks %t is correct."
- emote_sound = 'modular_splurt/sound/voice/buzzer_correct.ogg'
+ sound = 'modular_splurt/sound/voice/buzzer_correct.ogg'
+ emote_type = EMOTE_OMNI
emote_cooldown = 0.84 SECONDS
-/datum/emote/living/audio/buzzer_incorrect
+/datum/emote/sound/human/buzzer_incorrect
key = "incorrect"
key_third_person = "incorrects"
message = "thinks someone is incorrect."
message_param = "thinks %t is incorrect."
- emote_sound = 'modular_splurt/sound/voice/buzzer_incorrect.ogg'
+ sound = 'modular_splurt/sound/voice/buzzer_incorrect.ogg'
+ emote_type = EMOTE_OMNI
emote_cooldown = 1.21 SECONDS
-/datum/emote/living/audio/ace/
+/datum/emote/sound/human/ace/
key = "objection0"
key_third_person = "objects0"
+ name = "OBJECTION!!"
message = "\<\< OBJECTION!! \>\>"
message_param = "\<\< %t \>\>" // Allows for custom objections, but alas only in lowercase.
message_mime = "points their finger with determination!"
- emote_sound = 'modular_splurt/sound/voice/ace/ace_objection_generic.ogg'
+ sound = 'modular_splurt/sound/voice/ace/ace_objection_generic.ogg'
+ emote_type = EMOTE_OMNI
emote_cooldown = 6.0 SECONDS // This is regardless of sound's length.
emote_volume = 30
-/datum/emote/living/audio/ace/objection
+/datum/emote/sound/human/ace/objection
key = "objection"
key_third_person = "objects"
- emote_sound = 'modular_splurt/sound/voice/ace/ace_objection_m1.ogg'
+ name = "Objection!"
+ sound = 'modular_splurt/sound/voice/ace/ace_objection_m1.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_pitch_variance = FALSE // IT BREAKS THESE SOMEHOW
-/datum/emote/living/audio/ace/objection/run_emote(mob/user, params)
+/datum/emote/sound/human/ace/objection/run_emote(mob/user, params)
switch(user.gender)
if(MALE)
- emote_sound = pick('modular_splurt/sound/voice/ace/ace_objection_m1.ogg', 'modular_splurt/sound/voice/ace/ace_objection_m2.ogg', 'modular_splurt/sound/voice/ace/ace_objection_m3.ogg')
+ sound = pick('modular_splurt/sound/voice/ace/ace_objection_m1.ogg', 'modular_splurt/sound/voice/ace/ace_objection_m2.ogg', 'modular_splurt/sound/voice/ace/ace_objection_m3.ogg')
if(FEMALE)
- emote_sound = pick('modular_splurt/sound/voice/ace/ace_objection_f1.ogg', 'modular_splurt/sound/voice/ace/ace_objection_f2.ogg')
+ sound = pick('modular_splurt/sound/voice/ace/ace_objection_f1.ogg', 'modular_splurt/sound/voice/ace/ace_objection_f2.ogg')
else // Both because I am lazy.
- emote_sound = pick('modular_splurt/sound/voice/ace/ace_objection_m1.ogg', 'modular_splurt/sound/voice/ace/ace_objection_m2.ogg', 'modular_splurt/sound/voice/ace/ace_objection_m3.ogg', 'modular_splurt/sound/voice/ace/ace_objection_f1.ogg', 'modular_splurt/sound/voice/ace/ace_objection_f2.ogg')
+ sound = pick('modular_splurt/sound/voice/ace/ace_objection_m1.ogg', 'modular_splurt/sound/voice/ace/ace_objection_m2.ogg', 'modular_splurt/sound/voice/ace/ace_objection_m3.ogg', 'modular_splurt/sound/voice/ace/ace_objection_f1.ogg', 'modular_splurt/sound/voice/ace/ace_objection_f2.ogg')
. = ..()
-/datum/emote/living/audio/ace/hold_it
+/datum/emote/sound/human/ace/hold_it
key = "holdit"
key_third_person = "holdsit"
+ name = "HOLD IT!!"
message = "\<\< HOLD IT!! \>\>"
- emote_sound = 'modular_splurt/sound/voice/ace/ace_holdit_m1.ogg'
+ sound = 'modular_splurt/sound/voice/ace/ace_holdit_m1.ogg'
+ emote_type = EMOTE_OMNI
emote_pitch_variance = FALSE // IT BREAKS THESE SOMEHOW
-/datum/emote/living/audio/ace/hold_it/run_emote(mob/user, params)
+/datum/emote/sound/human/ace/hold_it/run_emote(mob/user, params)
switch(user.gender)
if(MALE)
- emote_sound = pick('modular_splurt/sound/voice/ace/ace_holdit_m1.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_m2.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_m3.ogg')
+ sound = pick('modular_splurt/sound/voice/ace/ace_holdit_m1.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_m2.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_m3.ogg')
if(FEMALE)
- emote_sound = pick('modular_splurt/sound/voice/ace/ace_holdit_f1.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_f2.ogg')
+ sound = pick('modular_splurt/sound/voice/ace/ace_holdit_f1.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_f2.ogg')
else // Both because I am lazy.
- emote_sound = pick('modular_splurt/sound/voice/ace/ace_holdit_m1.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_m2.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_m3.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_f1.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_f2.ogg')
+ sound = pick('modular_splurt/sound/voice/ace/ace_holdit_m1.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_m2.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_m3.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_f1.ogg', 'modular_splurt/sound/voice/ace/ace_holdit_f2.ogg')
. = ..()
-/datum/emote/living/audio/ace/take_that
+/datum/emote/sound/human/ace/take_that
key = "takethat"
key_third_person = "takesthat"
+ name = "TAKE THAT!!"
message = "\<\< TAKE THAT!! \>\>"
- emote_sound = 'modular_splurt/sound/voice/ace/ace_takethat_m1.ogg'
+ sound = 'modular_splurt/sound/voice/ace/ace_takethat_m1.ogg'
+ emote_type = EMOTE_OMNI
emote_pitch_variance = FALSE // IT BREAKS THESE SOMEHOW
-/datum/emote/living/audio/ace/take_that/run_emote(mob/user, params)
+/datum/emote/sound/human/ace/take_that/run_emote(mob/user, params)
switch(user.gender)
if(MALE)
- emote_sound = pick('modular_splurt/sound/voice/ace/ace_takethat_m1.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_m2.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_m3.ogg')
+ sound = pick('modular_splurt/sound/voice/ace/ace_takethat_m1.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_m2.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_m3.ogg')
if(FEMALE)
- emote_sound = pick('modular_splurt/sound/voice/ace/ace_takethat_f1.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_f2.ogg')
+ sound = pick('modular_splurt/sound/voice/ace/ace_takethat_f1.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_f2.ogg')
else // Both because I am lazy.
- emote_sound = pick('modular_splurt/sound/voice/ace/ace_takethat_m1.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_m2.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_m3.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_f1.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_f2.ogg')
+ sound = pick('modular_splurt/sound/voice/ace/ace_takethat_m1.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_m2.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_m3.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_f1.ogg', 'modular_splurt/sound/voice/ace/ace_takethat_f2.ogg')
. = ..()
-/datum/emote/living/audio/realize
+/datum/emote/sound/human/realize
key = "realize"
key_third_person = "realizes"
message = "realizes something."
- emote_sound = 'modular_splurt/sound/voice/ace/ace_realize.ogg'
+ sound = 'modular_splurt/sound/voice/ace/ace_realize.ogg'
+ emote_type = EMOTE_VISIBLE
emote_cooldown = 1.19 SECONDS
-/datum/emote/living/audio/smirk2
+/datum/emote/sound/human/smirk2
key = "smirk2"
key_third_person = "smirks2"
+ name = "smirk 2"
message = "smirks."
- emote_sound = 'modular_splurt/sound/voice/ace/ace_wubs.ogg'
+ sound = 'modular_splurt/sound/voice/ace/ace_wubs.ogg'
+ emote_type = EMOTE_VISIBLE
emote_cooldown = 0.84 SECONDS
-/datum/emote/living/audio/nani
+/datum/emote/sound/human/nani
key = "nani"
key_third_person = "nanis"
message = "seems confused."
- emote_sound = 'modular_splurt/sound/voice/nani.ogg'
+ sound = 'modular_splurt/sound/voice/nani.ogg'
+ emote_type = EMOTE_VISIBLE
emote_cooldown = 0.5 SECONDS
-/datum/emote/living/audio/canonevent
+/datum/emote/sound/human/canonevent
key = "2099"
key_third_person = "canons"
+ name = "canon event"
message = "thinks this is a canon event."
- emote_sound = 'modular_splurt/sound/voice/canon_event.ogg'
+ sound = 'modular_splurt/sound/voice/canon_event.ogg'
+ emote_type = EMOTE_OMNI
emote_cooldown = 5.0 SECONDS
emote_volume = 27
-/datum/emote/living/audio/meow
+/datum/emote/sound/human/meow
key = "meow"
- key_third_person = "mrowls"
- message = "mrowls!"
- emote_sound = 'modular_citadel/sound/voice/meow1.ogg'
- emote_cooldown = 0.6 SECONDS
- emote_pitch_variance = FALSE
-
-/datum/emote/living/audio/meow2
- key = "meow2"
key_third_person = "meows"
message = "meows!"
- emote_sound = 'modular_splurt/sound/voice/catpeople/cat_meow1.ogg'
+ emote_type = EMOTE_AUDIBLE // No reason mimes shouldn't meow.
+ restraint_check = FALSE
+ sound = 'modular_splurt/sound/voice/catpeople/cat_meow1.ogg'
+
emote_cooldown = 0.8 SECONDS // the longest audio is 1 second but who gives a fuck mrrp mrrp meow
emote_pitch_variance = FALSE // why would you
-/datum/emote/living/audio/meow/run_emote(mob/user, params)
- emote_sound = pick('modular_splurt/sound/voice/catpeople/cat_meow1.ogg', 'modular_splurt/sound/voice/catpeople/cat_meow2.ogg', 'modular_splurt/sound/voice/catpeople/cat_meow3.ogg') // Credit to Nyanotrasen (https://github.com/Nyanotrasen/Nyanotrasen)
+/datum/emote/sound/human/meow/run_emote(mob/user, params)
+ sound = pick('modular_splurt/sound/voice/catpeople/cat_meow1.ogg', 'modular_splurt/sound/voice/catpeople/cat_meow2.ogg', 'modular_splurt/sound/voice/catpeople/cat_meow3.ogg') // Credit to Nyanotrasen (https://github.com/Nyanotrasen/Nyanotrasen)
. = ..()
-/datum/emote/living/audio/meow3
- key = "meow3"
- key_third_person = "mews!"
+/datum/emote/sound/human/meow2
+ key = "meow2"
+ key_third_person = "meows2"
+ name = "meow 2"
message = "mews!"
- emote_sound = 'modular_splurt/sound/voice/catpeople/cat_mew1.ogg'
+ message_mime = "mews silently!"
+ sound = 'modular_splurt/sound/voice/catpeople/cat_mew1.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 0.8 SECONDS // mrrp mrrp meow
emote_pitch_variance = FALSE
-/datum/emote/living/audio/meow2/run_emote(mob/user, params)
- emote_sound = pick('modular_splurt/sound/voice/catpeople/cat_mew1.ogg', 'modular_splurt/sound/voice/catpeople/cat_mew2.ogg') // Credit to Nyanotrasen (https://github.com/Nyanotrasen/Nyanotrasen)
+/datum/emote/sound/human/meow2/run_emote(mob/user, params)
+ sound = pick('modular_splurt/sound/voice/catpeople/cat_mew1.ogg', 'modular_splurt/sound/voice/catpeople/cat_mew2.ogg') // Credit to Nyanotrasen (https://github.com/Nyanotrasen/Nyanotrasen)
. = ..()
-/datum/emote/living/audio/mrowl
- key = "mrowl"
- key_third_person = "mrowls"
- message = "mrowls."
- emote_sound = 'modular_splurt/sound/voice/mrowl.ogg'
- emote_cooldown = 0.95 SECONDS
- emote_pitch_variance = FALSE
-
-/datum/emote/living/audio/mrrp
+/datum/emote/sound/human/mrrp
key = "mrrp"
key_third_person = "mrrps"
message = "trills like a cat!"
- emote_sound = 'modular_splurt/sound/voice/catpeople/cat_mrrp1.ogg'
+ message_mime = "trills silently!"
+ sound = 'modular_splurt/sound/voice/catpeople/cat_mrrp1.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 0.8 SECONDS // mrrp mrrp meow
emote_pitch_variance = FALSE
-/datum/emote/living/audio/mrrp2
- key = "mrrp2"
- key_third_person = "mrrps"
- message = "trills like a cat!"
- emote_sound = 'modular_splurt/sound/voice/catpeople/cat_mrrp2.ogg'
- emote_cooldown = 0.8 SECONDS
+/datum/emote/sound/human/mrrp/run_emote(mob/user, params)
+ sound = pick('modular_splurt/sound/voice/catpeople/cat_mrrp1.ogg', 'modular_splurt/sound/voice/catpeople/cat_mrrp2.ogg')
+ . = ..()
+
+/datum/emote/sound/human/mrowl
+ key = "mrowl"
+ key_third_person = "mrowls"
+ message = "mrowls."
+ sound = 'modular_splurt/sound/voice/mrowl.ogg'
+ emote_type = EMOTE_AUDIBLE
+ emote_cooldown = 0.95 SECONDS
emote_pitch_variance = FALSE
-/datum/emote/living/audio/gay
+/datum/emote/sound/human/gay
key = "gay"
key_third_person = "points at a player"
message = "saw something gay."
- emote_sound = 'modular_splurt/sound/voice/gay-echo.ogg'
+ sound = 'modular_splurt/sound/voice/gay-echo.ogg'
+ emote_type = EMOTE_BOTH
emote_cooldown = 0.95 SECONDS
emote_pitch_variance = FALSE
-/datum/emote/living/audio/flabbergast
+/datum/emote/sound/human/flabbergast
key = "flabbergast"
key_third_person = "is flabbergasted"
message = "looks flabbergasted!"
- emote_sound = 'modular_splurt/sound/voice/flabbergasted.ogg'
+ sound = 'modular_splurt/sound/voice/flabbergasted.ogg'
+ emote_type = EMOTE_AUDIBLE
emote_cooldown = 3.0 SECONDS
emote_pitch_variance = FALSE
emote_volume = 70
-/datum/emote/living/audio/sadness
+/datum/emote/sound/human/rawr
+ key = "rawr"
+ key_third_person = "rawrs"
+ message = "lets out a rawr!"
+ sound = 'modular_sand/sound/voice/rawr.ogg'
+ emote_type = EMOTE_AUDIBLE
+ emote_cooldown = 0.8 SECONDS
+
+/datum/emote/sound/human/sadness
key = "sadness"
key_third_person = "feels sadness"
message = "is experiencing Profound Sadness!"
- emote_sound = 'modular_splurt/sound/voice/sadness.ogg'
- emote_cooldown = 4.0 SECONDS
- emote_pitch_variance = FALSE
- emote_volume = 30
+ sound = 'modular_splurt/sound/voice/sadness.ogg'
+ emote_cooldown = 4 SECONDS
+ vary = FALSE
+ volume = 30
diff --git a/sound/misc/roleplay.ogg b/sound/misc/roleplay.ogg
new file mode 100644
index 000000000000..e9ec54550091
Binary files /dev/null and b/sound/misc/roleplay.ogg differ
diff --git a/strings/phobia.json b/strings/phobia.json
index ee25cc62fa86..d442e9f97909 100644
--- a/strings/phobia.json
+++ b/strings/phobia.json
@@ -38,7 +38,7 @@
"brig",
"gulag"
],
-
+
"conspiracies": [
"central command",
"command",
@@ -296,7 +296,7 @@
"i'll catch you",
"slip"
],
-
+
"syndicate": [
"syndicate",
"changeling",
@@ -315,7 +315,7 @@
"enemy corporation",
"agent"
],
-
+
"anime": [
"anime",
"manga",
@@ -342,5 +342,59 @@
"neet",
"ora",
"~"
+ ],
+ "ocky icky": [
+ "admeme",
+ "admin",
+ "ahelp",
+ "amogus",
+ "antag",
+ "antagonist",
+ "ban",
+ "banned",
+ "chat",
+ "click",
+ "c*der",
+ "coder",
+ "coders",
+ "discord",
+ "erp",
+ "forum",
+ "ick ock",
+ "joever",
+ "k",
+ "kek",
+ "kys",
+ "leddit",
+ "lmao",
+ "lol",
+ "mapper",
+ "moderator",
+ "mods",
+ "muderbone",
+ "murderboning",
+ "ocky",
+ "ooc",
+ "owo",
+ "pwn",
+ "powergame",
+ "reddit",
+ "round",
+ "rule",
+ "rp",
+ "self antag",
+ "selfantag",
+ "sprite",
+ "spriter",
+ "splurt",
+ "sus",
+ "tide",
+ "u",
+ "ur",
+ "uwa",
+ "uwu",
+ "valid",
+ "y",
+ "5head"
]
}
diff --git a/tgstation.dme b/tgstation.dme
index 9de1b2b5d33d..105d49fb44bf 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -280,7 +280,6 @@
#include "code\__SANDCODE\HELPERS\silicon.dm"
#include "code\__SANDCODE\HELPERS\sizecode.dm"
#include "code\__SPLURTCODE\DEFINES\access.dm"
-#include "code\__SPLURTCODE\DEFINES\admin.dm"
#include "code\__SPLURTCODE\DEFINES\atmospherics.dm"
#include "code\__SPLURTCODE\DEFINES\cit_defines.dm"
#include "code\__SPLURTCODE\DEFINES\click.dm"
@@ -318,6 +317,7 @@
#include "code\_globalvars\tgui.dm"
#include "code\_globalvars\traits.dm"
#include "code\_globalvars\lists\achievements.dm"
+#include "code\_globalvars\lists\admin.dm"
#include "code\_globalvars\lists\client.dm"
#include "code\_globalvars\lists\flavor_misc.dm"
#include "code\_globalvars\lists\keybindings.dm"
@@ -597,6 +597,7 @@
#include "code\datums\components\_component.dm"
#include "code\datums\components\acid.dm"
#include "code\datums\components\activity.dm"
+#include "code\datums\components\admin_popup.dm"
#include "code\datums\components\anti_magic.dm"
#include "code\datums\components\area_sound_manager.dm"
#include "code\datums\components\armor_plate.dm"
@@ -631,6 +632,8 @@
#include "code\datums\components\lifesteal.dm"
#include "code\datums\components\lockon_aiming.dm"
#include "code\datums\components\magnetic_catch.dm"
+#include "code\datums\components\manual_blinking.dm"
+#include "code\datums\components\manual_breathing.dm"
#include "code\datums\components\material_container.dm"
#include "code\datums\components\mirage_border.dm"
#include "code\datums\components\mirv.dm"
@@ -1579,13 +1582,43 @@
#include "code\modules\admin\whitelist.dm"
#include "code\modules\admin\callproc\callproc.dm"
#include "code\modules\admin\DB_ban\functions.dm"
+#include "code\modules\admin\smites\berforate.dm"
+#include "code\modules\admin\smites\bloodless.dm"
+#include "code\modules\admin\smites\boneless.dm"
+#include "code\modules\admin\smites\bonk.dm"
+#include "code\modules\admin\smites\bookify.dm"
+#include "code\modules\admin\smites\brain_damage.dm"
+#include "code\modules\admin\smites\bread.dm"
+#include "code\modules\admin\smites\bsa.dm"
+#include "code\modules\admin\smites\cluwne.dm"
+#include "code\modules\admin\smites\custompie.dm"
+#include "code\modules\admin\smites\dock_pay.dm"
+#include "code\modules\admin\smites\fake_bwoink.dm"
+#include "code\modules\admin\smites\finalmessage.dm"
+#include "code\modules\admin\smites\fireball.dm"
+#include "code\modules\admin\smites\fry.dm"
+#include "code\modules\admin\smites\gib.dm"
+#include "code\modules\admin\smites\immerse.dm"
+#include "code\modules\admin\smites\knot_shoes.dm"
+#include "code\modules\admin\smites\lightning.dm"
+#include "code\modules\admin\smites\nugget.dm"
+#include "code\modules\admin\smites\phobia_ocky_icky.dm"
+#include "code\modules\admin\smites\pickle.dm"
+#include "code\modules\admin\smites\pie.dm"
+#include "code\modules\admin\smites\puzzle.dm"
+#include "code\modules\admin\smites\rod.dm"
+#include "code\modules\admin\smites\scarify.dm"
+#include "code\modules\admin\smites\shoes.dm"
+#include "code\modules\admin\smites\smite.dm"
+#include "code\modules\admin\smites\supply_pod.dm"
+#include "code\modules\admin\smites\supply_pod_quick.dm"
+#include "code\modules\admin\smites\tabletide.dm"
#include "code\modules\admin\verbs\adminhelp.dm"
#include "code\modules\admin\verbs\adminjump.dm"
#include "code\modules\admin\verbs\adminpm.dm"
#include "code\modules\admin\verbs\adminsay.dm"
#include "code\modules\admin\verbs\ak47s.dm"
#include "code\modules\admin\verbs\atmosdebug.dm"
-#include "code\modules\admin\verbs\bluespacearty.dm"
#include "code\modules\admin\verbs\borgpanel.dm"
#include "code\modules\admin\verbs\BrokenInhands.dm"
#include "code\modules\admin\verbs\cinematic.dm"
@@ -2072,6 +2105,7 @@
#include "code\modules\buildmode\submodes\fill.dm"
#include "code\modules\buildmode\submodes\mapgen.dm"
#include "code\modules\buildmode\submodes\save_area.dm"
+#include "code\modules\buildmode\submodes\smite.dm"
#include "code\modules\buildmode\submodes\throwing.dm"
#include "code\modules\buildmode\submodes\variable_edit.dm"
#include "code\modules\cargo\bounty.dm"
@@ -2257,6 +2291,7 @@
#include "code\modules\economy\account.dm"
#include "code\modules\economy\paystand.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/tgui/packages/tgui-panel/audio/NowPlayingWidget.js b/tgui/packages/tgui-panel/audio/NowPlayingWidget.js
index 4604a7a86826..3da9335b9786 100644
--- a/tgui/packages/tgui-panel/audio/NowPlayingWidget.js
+++ b/tgui/packages/tgui-panel/audio/NowPlayingWidget.js
@@ -7,6 +7,7 @@
import { toFixed } from 'common/math';
import { useDispatch, useSelector } from 'common/redux';
import { Button, Collapsible, Flex, Knob } from 'tgui/components';
+
import { useSettings } from '../settings';
import { selectAudio } from './selectors';
diff --git a/tgui/packages/tgui/interfaces/EmotePanel.tsx b/tgui/packages/tgui/interfaces/EmotePanel.tsx
new file mode 100644
index 000000000000..fdccbcdb0580
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/EmotePanel.tsx
@@ -0,0 +1,246 @@
+import { BooleanLike } from '../../common/react';
+import { capitalize } from '../../common/string';
+import { useLocalState } from '../backend';
+import { useBackend } from '../backend';
+import { Box, Button, Flex, Icon, Section } from '../components';
+import { Window } from '../layouts';
+import { SearchBar } from './common/SearchBar';
+
+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, 'searchText', '');
+ const [showNames, toggleShowNames] = useLocalState(context, 'showNames', true);
+ const [showIcons, toggleShowIcons] = useLocalState(context, 'showIcons', false);
+
+ return (
+
+
+
+ 0
+ ? `Search results of "${searchText}"`
+ : `All Emotes`
+ }
+ buttons={
+
+ toggleShowNames(!showNames)}
+ height="20px"
+ >
+ {showNames ? 'Show Names' : 'Show Keys'}
+
+ toggleShowIcons(!showIcons)}
+ height="20px"
+ >
+ Show Icons
+
+ toggleUseParams(!useParams)}
+ height="20px" // God knows why classic tg just breaks this button, this is a patchwork solution.
+ >
+ Use Params
+
+
+ }
+ >
+
+
+ {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) => (
+
+ )
+ }
+ onClick={() =>
+ act('play_emote', {
+ emote_key: emote.key,
+ use_params: useParams,
+ })
+ }
+ >
+
+ {showNames
+ ? capitalize(emote.name.toLowerCase())
+ : emote.key}
+
+ {showIcons ? (
+
+ ) : (
+ ''
+ )}
+
+ ))}
+
+
+
+
+ );
+};
+
+const EmoteIcons = (props) => {
+ const { visible, audible, sound, hands, use_params, margin } = props;
+
+ return (
+
+
+
+
+
+
+
+ );
+};
+
+export const EmotePanel = (props) => {
+ return (
+
+
+
+
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/MobInteraction/InfoSection.tsx b/tgui/packages/tgui/interfaces/MobInteraction/InfoSection.tsx
index a5ecc83cf5f4..579ebc7445ac 100644
--- a/tgui/packages/tgui/interfaces/MobInteraction/InfoSection.tsx
+++ b/tgui/packages/tgui/interfaces/MobInteraction/InfoSection.tsx
@@ -1,5 +1,5 @@
import { useBackend } from '../../backend';
-import { BlockQuote, Button, Icon, ProgressBar, Section, Stack, Slider, Tooltip } from '../../components';
+import { BlockQuote, Button, Icon, ProgressBar, Section, Slider, Stack, Tooltip } from '../../components';
type HeaderInfo = {
isTargetSelf: boolean;
diff --git a/tgui/packages/tgui/interfaces/Techweb.js b/tgui/packages/tgui/interfaces/Techweb.js
index 5b2df311020d..ae11e1c6a7dc 100644
--- a/tgui/packages/tgui/interfaces/Techweb.js
+++ b/tgui/packages/tgui/interfaces/Techweb.js
@@ -1,8 +1,9 @@
import { filter, map, sortBy } from 'common/collections';
import { flow } from 'common/fp';
+
import { useBackend, useLocalState } from '../backend';
-import { Button, Section, Modal, Dropdown, Tabs, Box, Input, Flex, ProgressBar, Collapsible, Icon, Divider } from '../components';
-import { Window, NtosWindow } from '../layouts';
+import { Box, Button, Divider, Dropdown, Flex, Input, Modal, ProgressBar, Section, Tabs } from '../components';
+import { NtosWindow, Window } from '../layouts';
// Data reshaping / ingestion (thanks stylemistake for the help, very cool!)
// This is primarily necessary due to measures that are taken to reduce the size
@@ -770,7 +771,7 @@ const TechNode = (props, context) => {
{tier !== 0 && !!compact && !destructive && (
{!!costs && Object.keys(costs).map(key => {
- const cost = costs[key]
+ const cost = costs[key];
const reqPts = Math.max(0, cost);
const nodeProg = Math.min(reqPts, points[key]) || 0;
return (
diff --git a/tgui/packages/tgui/interfaces/common/SearchBar.tsx b/tgui/packages/tgui/interfaces/common/SearchBar.tsx
new file mode 100644
index 000000000000..ab82dfd70843
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/common/SearchBar.tsx
@@ -0,0 +1,52 @@
+import { Icon, Input, Stack } from '../../components';
+
+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 function SearchBar(props: Props) {
+ const {
+ autoFocus,
+ noIcon = false,
+ onSearch,
+ placeholder = 'Search...',
+ query = '',
+ style,
+ } = props;
+
+ return (
+
+ {!noIcon && }
+
+ onSearch(value)}
+ placeholder={placeholder}
+ value={query}
+ />
+
+
+ );
+}