diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index e4e490a41dc04c..11141d7e02fc8e 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -148,6 +148,9 @@ ///Popup Chat Messages #define RUNECHAT_PLANE 250 +/// Plane for balloon text (text that fades up) +#define BALLOON_CHAT_PLANE 251 + ///Debug Atmos Overlays #define ATMOS_GROUP_PLANE 450 diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 320ee46a68aa28..a7a08510cc7228 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -454,9 +454,6 @@ GLOBAL_LIST_INIT(pda_styles, sortList(list(MONO, VT, ORBITRON, SHARE))) #define EGG_LAYING_MESSAGES list("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.") -/// Prepares a text to be used for maptext. Use this so it doesn't look hideous. -#define MAPTEXT(text) {"[##text]"} - //Filters #define AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, color="#04080FAA") #define GAUSSIAN_BLUR(filter_size) filter(type="blur", size=filter_size) diff --git a/code/__DEFINES/text.dm b/code/__DEFINES/text.dm new file mode 100644 index 00000000000000..58c24747e017af --- /dev/null +++ b/code/__DEFINES/text.dm @@ -0,0 +1,5 @@ +/// Prepares a text to be used for maptext. Use this so it doesn't look hideous. +#define MAPTEXT(text) {"[##text]"} + +/// Macro from Lummox used to get height from a MeasureText proc +#define WXH_TO_HEIGHT(x) text2num(copytext(x, findtextEx(x, "x") + 1)) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 600164cb3ce183..9b83f6e6d8c7f5 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -343,6 +343,10 @@ O.screen_loc = screen_loc return O +/// Removes an image from a client's `.images`. Useful as a callback. +/proc/remove_image_from_client(image/image, client/remove_from) + remove_from?.images -= image + /proc/remove_images_from_clients(image/I, list/show_to) for(var/client/C in show_to) C.images -= I diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm index 7d1f5114561c70..78152337492ca0 100644 --- a/code/datums/chatmessage.dm +++ b/code/datums/chatmessage.dm @@ -16,8 +16,6 @@ #define CHAT_MESSAGE_MAX_LENGTH 110 /// The dimensions of the chat message icons #define CHAT_MESSAGE_ICON_SIZE 9 -/// Macro from Lummox used to get height from a MeasureText proc -#define WXH_TO_HEIGHT(x) text2num(copytext(x, findtextEx(x, "x") + 1)) ///Base layer of chat elements #define CHAT_LAYER 1 @@ -317,4 +315,3 @@ #undef CHAT_LAYER_Z_STEP #undef CHAT_LAYER_MAX_Z #undef CHAT_MESSAGE_ICON_SIZE -#undef WXH_TO_HEIGHT diff --git a/code/modules/balloon_alert/balloon_alert.dm b/code/modules/balloon_alert/balloon_alert.dm new file mode 100644 index 00000000000000..c068d08d56ce70 --- /dev/null +++ b/code/modules/balloon_alert/balloon_alert.dm @@ -0,0 +1,54 @@ +#define BALLOON_TEXT_WIDTH 200 +#define BALLOON_TEXT_SPAWN_TIME (0.2 SECONDS) +#define BALLOON_TEXT_FADE_TIME (0.1 SECONDS) +#define BALLOON_TEXT_FULLY_VISIBLE_TIME (0.7 SECONDS) +#define BALLOON_TEXT_TOTAL_LIFETIME (BALLOON_TEXT_SPAWN_TIME + BALLOON_TEXT_FULLY_VISIBLE_TIME + BALLOON_TEXT_FADE_TIME) + +/// Creates text that will float from the atom upwards to the viewer. +/atom/proc/balloon_alert(mob/viewer, text) + var/client/viewer_client = viewer.client + if (isnull(viewer_client)) + return + + var/bound_width = world.icon_size + if (ismovable(src)) + var/atom/movable/movable_source = src + bound_width = movable_source.bound_width + + var/image/balloon_alert = image(loc = loc, layer = ABOVE_MOB_LAYER) + balloon_alert.plane = BALLOON_CHAT_PLANE + balloon_alert.alpha = 0 + balloon_alert.maptext = MAPTEXT("[text]") + balloon_alert.maptext_x = (BALLOON_TEXT_WIDTH - bound_width) * -0.5 + balloon_alert.maptext_height = WXH_TO_HEIGHT(viewer_client?.MeasureText(text, null, BALLOON_TEXT_WIDTH)) + balloon_alert.maptext_width = BALLOON_TEXT_WIDTH + + viewer_client?.images += balloon_alert + + animate( + balloon_alert, + pixel_y = world.icon_size * 1.2, + time = BALLOON_TEXT_TOTAL_LIFETIME, + easing = SINE_EASING | EASE_OUT, + ) + + animate( + alpha = 255, + time = BALLOON_TEXT_SPAWN_TIME, + easing = CUBIC_EASING | EASE_OUT, + flags = ANIMATION_PARALLEL, + ) + + animate( + alpha = 0, + time = BALLOON_TEXT_FULLY_VISIBLE_TIME, + easing = CUBIC_EASING | EASE_IN, + ) + + addtimer(CALLBACK(GLOBAL_PROC, .proc/remove_image_from_client, balloon_alert, viewer_client), BALLOON_TEXT_TOTAL_LIFETIME) + +#undef BALLOON_TEXT_FADE_TIME +#undef BALLOON_TEXT_FULLY_VISIBLE_TIME +#undef BALLOON_TEXT_SPAWN_TIME +#undef BALLOON_TEXT_TOTAL_LIFETIME +#undef BALLOON_TEXT_WIDTH diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 4a633ee408dbe3..d269c59b11ac89 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -56,7 +56,7 @@ amount_per_transfer_from_this = possible_transfer_amounts[i+1] else amount_per_transfer_from_this = possible_transfer_amounts[1] - to_chat(user, "[src]'s transfer amount is now [amount_per_transfer_from_this] units.") + balloon_alert(user, "Transferring [amount_per_transfer_from_this]u") return /obj/item/reagent_containers/pre_attack_secondary(atom/target, mob/living/user, params) diff --git a/tgstation.dme b/tgstation.dme index 4432a414ff6f2c..ba9c16bf75697f 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -135,6 +135,7 @@ #include "code\__DEFINES\strippable.dm" #include "code\__DEFINES\subsystems.dm" #include "code\__DEFINES\supermatter.dm" +#include "code\__DEFINES\text.dm" #include "code\__DEFINES\tgs.config.dm" #include "code\__DEFINES\tgs.dm" #include "code\__DEFINES\tgui.dm" @@ -1883,6 +1884,7 @@ #include "code\modules\awaymissions\mission_code\stationCollision.dm" #include "code\modules\awaymissions\mission_code\undergroundoutpost45.dm" #include "code\modules\awaymissions\mission_code\wildwest.dm" +#include "code\modules\balloon_alert\balloon_alert.dm" #include "code\modules\buildmode\bm_mode.dm" #include "code\modules\buildmode\buildmode.dm" #include "code\modules\buildmode\buttons.dm"