Skip to content

Commit

Permalink
Manually ports tgstation/tgstation#74428 due to merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
Koshenko committed Oct 13, 2023
1 parent 53a996f commit 96e7032
Showing 1 changed file with 53 additions and 27 deletions.
80 changes: 53 additions & 27 deletions code/datums/chatmessage.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#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
/// Grace period for fade before we actually delete the chat message
#define CHAT_MESSAGE_GRACE_PERIOD (0.2 SECONDS)
/// 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
Expand Down Expand Up @@ -50,10 +52,10 @@
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
/// Contains ID of assigned timer for end_of_life fading event
var/fadertimer = null
/// States if end_of_life is being executed
var/isFading = FALSE
/// When we started animating the message
var/animate_start = 0
/// Our animation lifespan, how long this message will last
var/animate_lifespan = 0

/**
* Constructs a chat message overlay
Expand All @@ -77,6 +79,8 @@
INVOKE_ASYNC(src, .proc/generate_image, text, target, owner, language, extra_classes, lifespan)

/datum/chatmessage/Destroy()
if(REALTIMEOFDAY < animate_start + animate_lifespan)
stack_trace("Del'd before we finished fading, with [(animate_start + animate_lifespan) - REALTIMEOFDAY] time left")
if (owned_by)
if (owned_by.seen_messages)
LAZYREMOVEASSOC(owned_by.seen_messages, message_loc, src)
Expand Down Expand Up @@ -184,6 +188,7 @@
///necessary because after that call the proc can resume at the end of the tick and cause overtime.
/datum/chatmessage/proc/finish_image_generation(mheight, atom/target, mob/owner, complete_text, lifespan)

var/rough_time = REALTIMEOFDAY
approx_lines = max(1, mheight / CHAT_MESSAGE_APPROX_LHEIGHT)

// Translate any existing messages upwards, apply exponential decay factors to timers
Expand All @@ -192,19 +197,33 @@
var/idx = 1
var/combined_height = approx_lines
for(var/datum/chatmessage/m as anything in owned_by.seen_messages[message_loc])
animate(m.message, pixel_y = m.message.pixel_y + mheight, time = CHAT_MESSAGE_SPAWN_TIME)

combined_height += m.approx_lines

var/time_spent = rough_time - m.animate_start
var/time_before_fade = m.animate_lifespan - CHAT_MESSAGE_EOL_FADE

// When choosing to update the remaining time we have to be careful not to update the
// scheduled time once the EOL has been executed.
if (!m.isFading)
var/sched_remaining = timeleft(m.fadertimer, SSrunechat)
var/remaining_time = max(0, (sched_remaining) * (CHAT_MESSAGE_EXP_DECAY ** idx++) * (CHAT_MESSAGE_HEIGHT_DECAY ** combined_height))
if (remaining_time)
deltimer(m.fadertimer, SSrunechat)
m.fadertimer = addtimer(CALLBACK(m, .proc/end_of_life), remaining_time, TIMER_STOPPABLE|TIMER_DELETE_ME, SSrunechat)
else
m.end_of_life()
if (time_spent >= time_before_fade)
animate(m.message, pixel_y = m.message.pixel_y + mheight, time = CHAT_MESSAGE_SPAWN_TIME, flags = ANIMATION_PARALLEL)
continue

var/remaining_time = time_before_fade * (CHAT_MESSAGE_EXP_DECAY ** idx++) * (CHAT_MESSAGE_HEIGHT_DECAY ** combined_height)
// Ensure we don't accidentially spike alpha up or something silly like that
m.message.alpha = m.get_current_alpha(time_spent)
if (remaining_time > 0)
// Stay faded in for a while, then
animate(m.message, alpha = 255, remaining_time)
// Fade out
animate(alpha = 0, time = CHAT_MESSAGE_EOL_FADE)
m.animate_lifespan = remaining_time + CHAT_MESSAGE_EOL_FADE
else
// Your time has come my son
animate(alpha = 0, time = CHAT_MESSAGE_EOL_FADE)
// We run this after the alpha animate, because we don't want to interrup it, but also don't want to block it by running first
// Sooo instead we do this. bit messy but it fuckin works
animate(m.message, pixel_y = m.message.pixel_y + mheight, time = CHAT_MESSAGE_SPAWN_TIME, flags = ANIMATION_PARALLEL)

// Reset z index if relevant
if (current_z_idx >= CHAT_LAYER_MAX_Z)
Expand All @@ -222,26 +241,32 @@
message.maptext_x = (CHAT_MESSAGE_WIDTH - owner.bound_width) * -0.5
message.maptext = MAPTEXT(complete_text)

animate_start = rough_time
animate_lifespan = lifespan

// View the message
LAZYADDASSOCLIST(owned_by.seen_messages, message_loc, src)
owned_by.images |= message
animate(message, alpha = 255, time = CHAT_MESSAGE_SPAWN_TIME)

// Register with the runechat SS to handle EOL and destruction
var/duration = lifespan - CHAT_MESSAGE_EOL_FADE
fadertimer = addtimer(CALLBACK(src, .proc/end_of_life), duration, TIMER_STOPPABLE|TIMER_DELETE_ME, SSrunechat)
var/time_before_fade = lifespan - CHAT_MESSAGE_SPAWN_TIME - CHAT_MESSAGE_EOL_FADE
// Stay faded in
animate(alpha = 255, time = time_before_fade)
// Fade out
animate(alpha = 0, time = CHAT_MESSAGE_EOL_FADE)

/**
* Applies final animations to overlay CHAT_MESSAGE_EOL_FADE deciseconds prior to message deletion,
* sets timer for scheduling deletion
*
* Arguments:
* * fadetime - The amount of time to animate the message's fadeout for
*/
/datum/chatmessage/proc/end_of_life(fadetime = CHAT_MESSAGE_EOL_FADE)
isFading = TRUE
animate(message, alpha = 0, time = fadetime, flags = ANIMATION_PARALLEL)
addtimer(CALLBACK(GLOBAL_PROC, /proc/qdel, src), fadetime, TIMER_DELETE_ME, SSrunechat)
// Register with the runechat SS to handle destruction
addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, src), lifespan + CHAT_MESSAGE_GRACE_PERIOD, TIMER_DELETE_ME, SSrunechat)

/datum/chatmessage/proc/get_current_alpha(time_spent)
if(time_spent < CHAT_MESSAGE_SPAWN_TIME)
return (time_spent / CHAT_MESSAGE_SPAWN_TIME) * 255

var/time_before_fade = animate_lifespan - CHAT_MESSAGE_EOL_FADE
if(time_spent <= time_before_fade)
return 255

return (1 - ((time_spent - time_before_fade) / CHAT_MESSAGE_EOL_FADE)) * 255

/**
* Creates a message overlay at a defined location for a given speaker
Expand Down Expand Up @@ -331,6 +356,7 @@
#undef CHAT_MESSAGE_SPAWN_TIME
#undef CHAT_MESSAGE_LIFESPAN
#undef CHAT_MESSAGE_EOL_FADE
#undef CHAT_MESSAGE_GRACE_PERIOD
#undef CHAT_MESSAGE_EXP_DECAY
#undef CHAT_MESSAGE_HEIGHT_DECAY
#undef CHAT_MESSAGE_APPROX_LHEIGHT
Expand Down

0 comments on commit 96e7032

Please sign in to comment.