Skip to content

Commit 1e309ef

Browse files
authored
adds status emoji flicking (#7320)
tl;dr you can make stuff like the beserk icon come on at will for your character.
1 parent 505018c commit 1e309ef

File tree

7 files changed

+203
-0
lines changed

7 files changed

+203
-0
lines changed

citadel.dme

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,7 @@
754754
#include "code\datums\radiation_wave.dm"
755755
#include "code\datums\shieldcall.dm"
756756
#include "code\datums\soul_link.dm"
757+
#include "code\datums\status_emoji.dm"
757758
#include "code\datums\sun.dm"
758759
#include "code\datums\weakref.dm"
759760
#include "code\datums\world_topic.dm"
@@ -852,6 +853,7 @@
852853
#include "code\datums\components\mobs\parry_frame.dm"
853854
#include "code\datums\components\movable\aquarium.dm"
854855
#include "code\datums\components\movable\spatial_grid.dm"
856+
#include "code\datums\components\movable\status_emoji.dm"
855857
#include "code\datums\components\objects\slippery.dm"
856858
#include "code\datums\components\riding\riding_filter.dm"
857859
#include "code\datums\components\riding\riding_handler.dm"
@@ -4394,6 +4396,8 @@
43944396
#include "code\modules\mob\observer\dead\perspective.dm"
43954397
#include "code\modules\mob\observer\dead\say.dm"
43964398
#include "code\modules\mob\verbs\feign_impairment.dm"
4399+
#include "code\modules\mob\verbs\flick_status_emoji.dm"
4400+
#include "code\modules\mob\verbs\flick_status_emoji_quick.dm"
43974401
#include "code\modules\mob\verbs\horizontal_invert_self.dm"
43984402
#include "code\modules\mob\verbs\vertical_invert_self.dm"
43994403
#include "code\modules\modular_computers\laptop_vendor.dm"
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//* This file is explicitly licensed under the MIT license. *//
2+
//* Copyright (c) 2025 Citadel Station Developers *//
3+
4+
/datum/component/status_emoji
5+
dupe_type = COMPONENT_DUPE_HIGHLANDER
6+
registered_type = /datum/component/status_emoji
7+
var/datum/status_emoji/emoji
8+
var/image/overlay
9+
10+
/datum/component/status_emoji/Initialize(datum/status_emoji/emoji_datum, duration)
11+
. = ..()
12+
if(. == COMPONENT_INCOMPATIBLE)
13+
return
14+
if(!ismovable(parent))
15+
return COMPONENT_INCOMPATIBLE
16+
emoji = emoji_datum
17+
QDEL_IN(src, duration)
18+
19+
/datum/component/status_emoji/RegisterWithParent()
20+
var/atom/movable/casted = parent
21+
generate_overlay(casted)
22+
casted.add_overlay(overlay, TRUE)
23+
24+
/datum/component/status_emoji/UnregisterFromParent()
25+
var/atom/movable/casted = parent
26+
casted.cut_overlay(overlay, TRUE)
27+
overlay = null
28+
29+
/datum/component/status_emoji/proc/generate_overlay(atom/movable/align_to)
30+
ASSERT(!overlay)
31+
overlay = image(emoji.icon, emoji.icon_state)
32+
align_to.get_centering_pixel_x_offset()
33+
34+
// we always align to their icon's top right.
35+
var/align_x = (align_to.get_pixel_x_self_width() - emoji.icon_size_x) + emoji.shift_x
36+
var/align_y = (align_to.get_pixel_y_self_width() - emoji.icon_size_y) + emoji.shift_y
37+
38+
overlay.pixel_x = align_x
39+
overlay.pixel_y = align_y

code/datums/status_emoji.dm

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//* This file is explicitly licensed under the MIT license. *//
2+
//* Copyright (c) 2025 Citadel Station Developers *//
3+
4+
GLOBAL_LIST_INIT(status_emojis, init_status_emojis())
5+
6+
/proc/init_status_emojis()
7+
. = list()
8+
for(var/datum/status_emoji/path as anything in subtypesof(/datum/status_emoji))
9+
if(path.abstract_type == path)
10+
continue
11+
. += new path
12+
// quack. duck typing to the rescue (and chagrin of whoever has to fix this 2 years later)
13+
tim_sort(., /proc/cmp_name_asc)
14+
15+
/**
16+
* A status emoji to be flicked by mobs, primarily.
17+
* * That said, this contains alignment data that can be used to align it to any atom, so...
18+
* * Icon states are assumed to be aligned to top right of the icon size. Provide alignment offsets if needed.
19+
*/
20+
/datum/status_emoji
21+
abstract_type = /datum/status_emoji
22+
var/name
23+
var/icon = 'icons/screen/status_emojis.dmi'
24+
var/icon_state
25+
26+
var/icon_size_x = 32
27+
var/icon_size_y = 32
28+
29+
var/shift_x = 0
30+
var/shift_y = 0
31+
32+
/datum/status_emoji/annoyed
33+
name = "Annoyed"
34+
icon_state = "annoyed"
35+
36+
/datum/status_emoji/berserk
37+
name = "Berserk"
38+
icon_state = "berserk"
39+
40+
/datum/status_emoji/confused
41+
name = "Confused"
42+
icon_state = "confused"
43+
44+
/datum/status_emoji/depression
45+
name = "Depression"
46+
icon_state = "depression"
47+
shift_y = 3
48+
49+
/datum/status_emoji/frustration
50+
name = "Frustration"
51+
icon_state = "frustration"
52+
53+
/datum/status_emoji/joyous
54+
name = "Joyous"
55+
icon_state = "joyous"
56+
57+
/datum/status_emoji/panic
58+
name = "Panic"
59+
icon_state = "panic"
60+
61+
/datum/status_emoji/tired
62+
name = "Tired"
63+
icon_state = "tired"

code/game/atoms/_atom.dm

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,7 @@
804804

805805
//? Pixel Offsets
806806

807+
// todo: figure out exactly what we're doing here because this is a dumpster fire; we need to well-define what each of htese is supposed to do.
807808
// todo: at some point we need to optimize this entire chain of bullshit, proccalls are expensive yo
808809

809810
/atom/proc/set_pixel_x(val)
@@ -888,3 +889,17 @@
888889
/atom/proc/auto_pixel_offset_to_center()
889890
set_base_pixel_y(get_centering_pixel_y_offset())
890891
set_base_pixel_x(get_centering_pixel_x_offset())
892+
893+
/**
894+
* Get the left-to-right lower-left to top-right width of our icon in pixels.
895+
* * This is used to align some overlays like HUD overlays.
896+
*/
897+
/atom/proc/get_pixel_x_self_width()
898+
return icon_x_dimension
899+
900+
/**
901+
* Get the left-to-right lower-left to top-right width of our icon in pixels.
902+
* * This is used to align some overlays like HUD overlays.
903+
*/
904+
/atom/proc/get_pixel_y_self_width()
905+
return icon_y_dimension
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//* This file is explicitly licensed under the MIT license. *//
2+
//* Copyright (c) 2025 Citadel Station Developers *//
3+
4+
// todo: DECLARE_MOB_VERB
5+
/mob/verb/flick_status_emoji(emoji_name as text|null)
6+
set name = "Flick Status Emoji"
7+
set desc = "Flicks a status emoji on yourself."
8+
set category = VERB_CATEGORY_IC
9+
10+
// No filtering for now
11+
var/list/datum/status_emoji/possible = GLOB.status_emojis
12+
13+
var/datum/status_emoji/picked
14+
15+
if(emoji_name)
16+
for(var/datum/status_emoji/emoji as anything in possible)
17+
if(ckey(emoji.name) != ckey(emoji_name))
18+
continue
19+
picked = emoji
20+
break
21+
if(!picked)
22+
to_chat(src, SPAN_WARNING("There's no status emoji named '[emoji_name]' ([ckey(emoji_name)])"))
23+
return
24+
else
25+
picked = tgui_input_list(
26+
src,
27+
"Pick a status emoji to flick.",
28+
"Flick Status Emoji",
29+
possible,
30+
)
31+
if(!picked)
32+
return
33+
34+
var/seconds = tgui_input_number(
35+
src,
36+
"How long? (seconds)",
37+
"Flick Status Emoji",
38+
10,
39+
60 * 5,
40+
1,
41+
)
42+
var/duration = round(seconds * 10, world.tick_lag)
43+
AddComponent(/datum/component/status_emoji, picked, duration)
44+
to_chat(src, SPAN_NOTICE("You make a '[picked]' expression."))
45+
log_game("[key_name(src)] flicked a status emoji: [picked]")
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//* This file is explicitly licensed under the MIT license. *//
2+
//* Copyright (c) 2025 Citadel Station Developers *//
3+
4+
// todo: DECLARE_MOB_VERB
5+
/mob/verb/flick_status_emoji_quick(emoji_name as text|null)
6+
set name = "Flick Status Emoji (Quick)"
7+
set desc = "Flicks a status emoji on yourself."
8+
set category = VERB_CATEGORY_IC
9+
10+
// No filtering for now
11+
var/list/datum/status_emoji/possible = GLOB.status_emojis
12+
13+
var/datum/status_emoji/picked
14+
15+
if(emoji_name)
16+
for(var/datum/status_emoji/emoji as anything in possible)
17+
if(ckey(emoji.name) != ckey(emoji_name))
18+
continue
19+
picked = emoji
20+
break
21+
if(!picked)
22+
to_chat(src, SPAN_WARNING("There's no status emoji named '[emoji_name]' ([ckey(emoji_name)])"))
23+
return
24+
else
25+
picked = tgui_input_list(
26+
src,
27+
"Pick a status emoji to flick.",
28+
"Flick Status Emoji",
29+
possible,
30+
)
31+
if(!picked)
32+
return
33+
34+
var/duration = 7.5 SECONDS
35+
AddComponent(/datum/component/status_emoji, picked, duration)
36+
to_chat(src, SPAN_NOTICE("You make a '[picked]' expression."))
37+
log_game("[key_name(src)] flicked a status emoji: [picked]")

icons/screen/status_emojis.dmi

3.2 KB
Binary file not shown.

0 commit comments

Comments
 (0)