From 6c71d076490691551fdfe28a6db3eba71fa1ac94 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Fri, 21 Aug 2020 15:24:04 +0200 Subject: [PATCH] [MIRROR] Adds Time-Based Layering to Runechat Messages + Refactoring (#457) * Merge pull request #52959 from bobbahbrown/runechat-changes Adds Time-Based Layering to Runechat Messages + Refactoring * Adds Time-Based Layering to Runechat Messages + Refactoring Co-authored-by: nemvar <47324920+nemvar@users.noreply.github.com> --- code/__DEFINES/layers.dm | 3 ++- code/datums/chatmessage.dm | 44 ++++++++++++++++++++++++++----------- code/modules/mob/mob_say.dm | 2 +- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index 9866dad079a..5ed50cdc536 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -93,7 +93,8 @@ #define EMISSIVE_BLOCKER_LAYER 12 #define EMISSIVE_BLOCKER_RENDER_TARGET "*EMISSIVE_BLOCKER_PLANE" -#define CHAT_LAYER 12.1 +#define CHAT_LAYER 12.0001 // Do not insert layers between these two values +#define CHAT_LAYER_MAX 12.9999 #define EMISSIVE_PLANE 13 #define EMISSIVE_LAYER 13 diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm index 3df701ff190..9b88de2f932 100644 --- a/code/datums/chatmessage.dm +++ b/code/datums/chatmessage.dm @@ -1,12 +1,25 @@ +/// How long the chat message's spawn-in animation will occur for #define CHAT_MESSAGE_SPAWN_TIME 0.2 SECONDS +/// How long the chat message will exist prior to any exponential decay #define CHAT_MESSAGE_LIFESPAN 5 SECONDS +/// How long the chat message's end of life fading animation will occur for #define CHAT_MESSAGE_EOL_FADE 0.7 SECONDS -#define CHAT_MESSAGE_EXP_DECAY 0.7 // Messages decay at pow(factor, idx in stack) -#define CHAT_MESSAGE_HEIGHT_DECAY 0.9 // Increase message decay based on the height of the message -#define CHAT_MESSAGE_APPROX_LHEIGHT 11 // Approximate height in pixels of an 'average' line, used for height decay -#define CHAT_MESSAGE_WIDTH 96 // pixels -#define CHAT_MESSAGE_MAX_LENGTH 110 // characters -#define WXH_TO_HEIGHT(x) text2num(copytext((x), findtextEx((x), "x") + 1)) // thanks lummox +/// Factor of how much the message index (number of messages) will account to exponential decay +#define CHAT_MESSAGE_EXP_DECAY 0.7 +/// Factor of how much height will account to exponential decay +#define CHAT_MESSAGE_HEIGHT_DECAY 0.9 +/// Approximate height in pixels of an 'average' line, used for height decay +#define CHAT_MESSAGE_APPROX_LHEIGHT 11 +/// Max width of chat message in pixels +#define CHAT_MESSAGE_WIDTH 96 +/// Max length of chat message in characters +#define CHAT_MESSAGE_MAX_LENGTH 110 +/// Maximum precision of float before rounding errors occur (in this context) +#define CHAT_LAYER_Z_STEP 0.0001 +/// The number of z-layer 'slices' usable by the chat message layering +#define CHAT_LAYER_MAX_Z (CHAT_LAYER_MAX - CHAT_LAYER) / CHAT_LAYER_Z_STEP +/// Macro from Lummox used to get height from a MeasureText proc +#define WXH_TO_HEIGHT(x) text2num(copytext(x, findtextEx(x, "x") + 1)) /** * # Chat Message Overlay @@ -30,6 +43,8 @@ var/datum/chatmessage/next /// Contains the reference to the previous chatmessage in the bucket, used by runechat subsystem var/datum/chatmessage/prev + /// The current index used for adjusting the layer of each sequential chat message such that recent messages will overlay older ones + var/static/current_z_idx = 0 /** * Constructs a chat message overlay @@ -122,12 +137,8 @@ var/tgt_color = extra_classes.Find("italics") ? target.chat_color_darkened : target.chat_color // Approximate text height - // Note we have to replace HTML encoded metacharacters otherwise MeasureText will return a zero height - // BYOND Bug #2563917 - // Construct text - var/static/regex/html_metachars = new(@"&[A-Za-z]{1,7};", "g") var/complete_text = "[text]" - var/mheight = WXH_TO_HEIGHT(owned_by.MeasureText(replacetext(complete_text, html_metachars, "m"), null, CHAT_MESSAGE_WIDTH)) + var/mheight = WXH_TO_HEIGHT(owned_by.MeasureText(complete_text, null, CHAT_MESSAGE_WIDTH)) approx_lines = max(1, mheight / CHAT_MESSAGE_APPROX_LHEIGHT) // Translate any existing messages upwards, apply exponential decay factors to timers @@ -147,8 +158,12 @@ var/remaining_time = (sched_remaining) * (CHAT_MESSAGE_EXP_DECAY ** idx++) * (CHAT_MESSAGE_HEIGHT_DECAY ** combined_height) m.enter_subsystem(world.time + remaining_time) // push updated time to runechat SS + // Reset z index if relevant + if (current_z_idx >= CHAT_LAYER_MAX_Z) + current_z_idx = 0 + // Build message image - message = image(loc = message_loc, layer = CHAT_LAYER) + message = image(loc = message_loc, layer = CHAT_LAYER + CHAT_LAYER_Z_STEP * current_z_idx++) message.plane = GAME_PLANE message.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA | KEEP_APART message.alpha = 0 @@ -170,9 +185,12 @@ /** * Applies final animations to overlay CHAT_MESSAGE_EOL_FADE deciseconds prior to message deletion, * sets time for scheduling deletion and re-enters the runechat SS for qdeling + * + * Arguments: + * * fadetime - The amount of time to animate the message's fadeout for */ /datum/chatmessage/proc/end_of_life(fadetime = CHAT_MESSAGE_EOL_FADE) - eol_complete = scheduled_destruction + CHAT_MESSAGE_EOL_FADE + eol_complete = scheduled_destruction + fadetime animate(message, alpha = 0, time = fadetime, flags = ANIMATION_PARALLEL) enter_subsystem(eol_complete) // re-enter the runechat SS with the EOL completion time to QDEL self diff --git a/code/modules/mob/mob_say.dm b/code/modules/mob/mob_say.dm index fbae71a67cf..aacc44e60db 100644 --- a/code/modules/mob/mob_say.dm +++ b/code/modules/mob/mob_say.dm @@ -81,7 +81,7 @@ if(SEND_SIGNAL(src, COMSIG_MOB_DEADSAY, message) & MOB_DEADSAY_SIGNAL_INTERCEPT) return var/displayed_key = key - if(client.holder?.fakekey) + if(client?.holder?.fakekey) displayed_key = null deadchat_broadcast(rendered, source, follow_target = src, speaker_key = displayed_key)