mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-22 20:43:10 +01:00
Ports CM's langchat to replace floating chat. (#20818)
Works generally better and will allow for better customization and emote display. --------- Co-authored-by: realmattatlas <liermattia@gmail.com>
This commit is contained in:
co-authored by
realmattatlas
parent
2700e9b9ca
commit
1738301ea7
@@ -47,6 +47,8 @@ GLOBAL_LIST_INIT(admin_verbs_admin, list(
|
||||
/client/proc/admin_cancel_shuttle, //allows us to cancel the emergency shuttle, sending it back to centcomm,
|
||||
/client/proc/cmd_admin_direct_narrate, //send text directly to a player with no padding. Useful for narratives and fluff-text,
|
||||
/client/proc/cmd_admin_local_narrate, //sends text to all mobs within 7 tiles of src.mob
|
||||
/client/proc/cmd_admin_local_screen_text,
|
||||
/client/proc/cmd_admin_global_screen_text,
|
||||
/client/proc/cmd_admin_world_narrate, //sends text to all players with no padding,
|
||||
/client/proc/cmd_admin_create_centcom_report,
|
||||
/client/proc/check_ai_laws, //shows AI and borg laws,
|
||||
@@ -305,6 +307,8 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
||||
/client/proc/manage_silicon_laws,
|
||||
/client/proc/cmd_admin_direct_narrate,
|
||||
/client/proc/cmd_admin_local_narrate,
|
||||
/client/proc/cmd_admin_local_screen_text,
|
||||
/client/proc/cmd_admin_global_screen_text,
|
||||
/client/proc/cmd_admin_world_narrate,
|
||||
/client/proc/cmd_admin_grab_observers,
|
||||
/client/proc/cmd_admin_create_centcom_report,
|
||||
|
||||
@@ -119,6 +119,65 @@
|
||||
message_admins(SPAN_NOTICE("\bold LocalNarrate: [key_name_admin(usr)] : [msg]<BR>"), 1)
|
||||
feedback_add_details("admin_verb", "LCLN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
/client/proc/cmd_admin_local_screen_text()
|
||||
set category = "Special Verbs"
|
||||
set name = "Local Screen Text"
|
||||
|
||||
if(!check_rights(R_ADMIN, TRUE))
|
||||
return
|
||||
|
||||
var/list/mob/message_mobs = list()
|
||||
var/choice = tgui_alert(usr, "Local Screen Text will send a screen text message to mobs. Do you want the mobs messaged to be only ones that you can see, or ignore blocked vision and message everyone within seven tiles of you?", "Narrate Selection", list("View", "Range", "Cancel"))
|
||||
if(choice != "Cancel")
|
||||
if(choice == "View")
|
||||
message_mobs = mobs_in_view(view, src.mob)
|
||||
else
|
||||
for(var/mob/M in range(view, src.mob))
|
||||
message_mobs += M
|
||||
else
|
||||
return
|
||||
|
||||
var/msg = tgui_input_text(usr, "Insert the screen message you want to send.", "Local Screen Text")
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
var/big_text = tgui_alert(src, "Do you want big or normal text?", "Local Screen Text", list("Big", "Normal"))
|
||||
var/text_type = /atom/movable/screen/text/screen_text
|
||||
if(big_text == "Big")
|
||||
text_type = /atom/movable/screen/text/screen_text/command_order
|
||||
|
||||
for(var/mob/M in message_mobs)
|
||||
if(M.client)
|
||||
M.play_screen_text(msg,text_type, COLOR_RED)
|
||||
log_admin("LocalScreenText: [key_name(usr)] : [msg]")
|
||||
message_admins(SPAN_NOTICE("Local Screen Text: [key_name_admin(usr)] : [msg]"), 1)
|
||||
feedback_add_details("admin_verb", "LSTX") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_admin_global_screen_text()
|
||||
set category = "Special Verbs"
|
||||
set name = "Global Screen Text"
|
||||
|
||||
if(!check_rights(R_ADMIN, TRUE))
|
||||
return
|
||||
|
||||
var/msg = tgui_input_text(usr, "Insert the screen message you want to send.", "Global Screen Text")
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
var/big_text = tgui_alert(src, "Do you want big or normal text?", "Global Screen Text", list("Big", "Normal"))
|
||||
var/text_type = /atom/movable/screen/text/screen_text
|
||||
if(big_text == "Big")
|
||||
text_type = /atom/movable/screen/text/screen_text/command_order
|
||||
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
if(M.client)
|
||||
M.play_screen_text(msg, text_type, COLOR_RED)
|
||||
|
||||
log_admin("GlobalScreenText: [key_name(usr)] : [msg]")
|
||||
message_admins(SPAN_NOTICE("Global Screen Text: [key_name_admin(usr)] : [msg]"), 1)
|
||||
feedback_add_details("admin_verb", "GSTX") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_admin_direct_narrate(var/mob/M) // Targetted narrate -- TLE
|
||||
set category = "Special Verbs"
|
||||
set name = "Direct Narrate"
|
||||
|
||||
@@ -100,3 +100,7 @@
|
||||
|
||||
/// The DPI scale of the client. 1 is equivalent to 100% window scaling, 2 will be 200% window scaling
|
||||
var/window_scaling
|
||||
|
||||
//screen_text vars
|
||||
///lazylist of screen_texts for this client, first in this list is the one playing
|
||||
var/list/atom/movable/screen/text/screen_text/screen_texts
|
||||
|
||||
@@ -386,6 +386,8 @@ GLOBAL_LIST_INIT(localhost_addresses, list(
|
||||
// Forcibly enable hardware-accelerated graphics, as we need them for the lighting overlays.
|
||||
winset(src, null, "command=\".configure graphics-hwmode on\"")
|
||||
|
||||
winset(src, "map", "style=\"[MAP_STYLESHEET]\"")
|
||||
|
||||
if(IsGuestKey(key) && GLOB.config.external_auth)
|
||||
src.authed = FALSE
|
||||
var/mob/abstract/unauthed/m = new()
|
||||
|
||||
@@ -262,7 +262,7 @@
|
||||
pref.floating_chat_color = new_fc_color
|
||||
var/mob/living/carbon/human/H = preference_mob()
|
||||
if(ishuman(H))
|
||||
H.set_floating_chat_color(new_fc_color)
|
||||
H.langchat_color = pref.floating_chat_color
|
||||
return TOPIC_REFRESH
|
||||
|
||||
else if(href_list["speech_bubble_type"])
|
||||
|
||||
@@ -412,7 +412,7 @@ GLOBAL_LIST_EMPTY_TYPED(preferences_datums, /datum/preferences)
|
||||
character.set_species(species)
|
||||
if(character.dna)
|
||||
character.dna.real_name = character.real_name
|
||||
character.set_floating_chat_color(floating_chat_color)
|
||||
character.langchat_color = floating_chat_color
|
||||
|
||||
character.flavor_texts["general"] = flavor_texts["general"]
|
||||
character.flavor_texts[BP_HEAD] = flavor_texts[BP_HEAD]
|
||||
|
||||
@@ -149,7 +149,6 @@
|
||||
return pretext + nametext + subtext
|
||||
|
||||
/mob/proc/custom_emote(var/m_type = VISIBLE_MESSAGE, var/message = null, var/do_show_observers = TRUE)
|
||||
|
||||
if((usr && stat) || (!use_me && usr == src))
|
||||
to_chat(src, "You are unable to emote.")
|
||||
return
|
||||
@@ -157,27 +156,21 @@
|
||||
if(!message)
|
||||
return
|
||||
|
||||
var/animated_chat_message = message
|
||||
|
||||
message = format_emote(src, message)
|
||||
|
||||
if (message)
|
||||
log_emote("[name]/[key] : [message]")
|
||||
|
||||
message = process_chat_markup(message, list("~", "_"))
|
||||
var/langchat_message = message
|
||||
message = format_emote(src, message)
|
||||
var/list/emote_viewers = list()
|
||||
if(m_type == VISIBLE_MESSAGE)
|
||||
visible_message(message, show_observers = do_show_observers)
|
||||
emote_viewers = viewers(world.view, src)
|
||||
else
|
||||
audible_message(message, ghost_hearing = do_show_observers)
|
||||
emote_viewers = get_hearers_in_LOS(world.view, src)
|
||||
|
||||
var/list/hearers = get_hearers_in_view(7, src)
|
||||
var/list/hear_clients = list()
|
||||
for(var/mob/M in hearers)
|
||||
if(M.client)
|
||||
hear_clients |= M.client
|
||||
|
||||
animated_chat_message = SPAN_COLOR("#f3ef09", "*") + animated_chat_message
|
||||
animate_chat(animated_chat_message, null, TRUE, hear_clients, 30)
|
||||
langchat_speech(langchat_message, emote_viewers, GLOB.all_languages, skip_language_check = TRUE, additional_styles = list("emote", "langchat_small"))
|
||||
|
||||
// Specific mob type exceptions below.
|
||||
/mob/living/silicon/ai/emote(var/act, var/type, var/message)
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* These are ported from TGMC and are hopefully more flexible than text blurbs
|
||||
*/
|
||||
|
||||
/**
|
||||
* proc for playing a screen_text on a mob.
|
||||
* enqueues it if a screen text is running and plays i otherwise
|
||||
* Arguments:
|
||||
* * text: text we want to be displayed
|
||||
* * alert_type: typepath for screen text type we want to play here
|
||||
* * override_color: the color of the text to use
|
||||
*/
|
||||
/mob/proc/play_screen_text(text, alert_type = /atom/movable/screen/text/screen_text, override_color = "#FFFFFF")
|
||||
var/atom/movable/screen/text/screen_text/text_box = new alert_type()
|
||||
text_box.text_to_play = text
|
||||
text_box.player = client
|
||||
if(override_color)
|
||||
text_box.color = override_color
|
||||
|
||||
LAZYADD(client.screen_texts, text_box)
|
||||
if(LAZYLEN(client.screen_texts) == 1) //lets only play one at a time, for thematic effect and prevent overlap
|
||||
INVOKE_ASYNC(text_box, TYPE_PROC_REF(/atom/movable/screen/text/screen_text, play_to_client))
|
||||
|
||||
/atom/movable/screen/text/screen_text
|
||||
icon = null
|
||||
icon_state = null
|
||||
alpha = 255
|
||||
|
||||
maptext_height = 64
|
||||
maptext_width = 480
|
||||
maptext_x = 0
|
||||
maptext_y = 0
|
||||
screen_loc = "LEFT,TOP-3"
|
||||
|
||||
///Time taken to fade in as we start printing text
|
||||
var/fade_in_time = 0
|
||||
///Time before fade out after printing is finished
|
||||
var/fade_out_delay = 2 SECONDS
|
||||
///Time taken when fading out after fade_out_delay
|
||||
var/fade_out_time = 0.5 SECONDS
|
||||
///delay between playing each letter. in general use 1 for fluff and 0.5 for time sensitive messsages
|
||||
var/play_delay = 0.5
|
||||
///letters to update by per text to per play_delay
|
||||
var/letters_per_update = 1
|
||||
|
||||
///opening styling for the message
|
||||
var/style_open = "<span class='langchat' style=text-align:center valign='top'>"
|
||||
///closing styling for the message
|
||||
var/style_close = "</span>"
|
||||
///var for the text we are going to play
|
||||
var/text_to_play
|
||||
///The client that this text is for
|
||||
var/client/player
|
||||
|
||||
/atom/movable/screen/text/screen_text/command_order
|
||||
maptext_height = 64
|
||||
maptext_width = 480
|
||||
maptext_x = 0
|
||||
maptext_y = 0
|
||||
screen_loc = "LEFT,TOP-3"
|
||||
|
||||
letters_per_update = 2
|
||||
fade_out_delay = 4.5 SECONDS
|
||||
style_open = "<span class='langchat' style=font-size:16pt;text-align:center valign='top'>"
|
||||
style_close = "</span>"
|
||||
|
||||
///proc for actually playing this screen_text on a mob.
|
||||
/atom/movable/screen/text/screen_text/proc/play_to_client()
|
||||
player?.add_to_screen(src)
|
||||
if(fade_in_time)
|
||||
animate(src, alpha = 255)
|
||||
var/list/lines_to_skip = list()
|
||||
var/static/html_locate_regex = regex("<.*>")
|
||||
var/tag_position = findtext(text_to_play, html_locate_regex)
|
||||
var/reading_tag = TRUE
|
||||
while(tag_position)
|
||||
if(reading_tag)
|
||||
if(text_to_play[tag_position] == ">")
|
||||
reading_tag = FALSE
|
||||
lines_to_skip += tag_position
|
||||
tag_position++
|
||||
else
|
||||
tag_position = findtext(text_to_play, html_locate_regex, tag_position)
|
||||
reading_tag = TRUE
|
||||
|
||||
for(var/letter = 2 to length(text_to_play) + letters_per_update step letters_per_update)
|
||||
if(letter in lines_to_skip)
|
||||
continue
|
||||
maptext = "[style_open][copytext_char(text_to_play, 1, letter)][style_close]"
|
||||
sleep(play_delay)
|
||||
|
||||
addtimer(CALLBACK(src, PROC_REF(after_play)), fade_out_delay)
|
||||
|
||||
///handles post-play effects like fade out after the fade out delay
|
||||
/atom/movable/screen/text/screen_text/proc/after_play()
|
||||
if(!fade_out_time)
|
||||
end_play()
|
||||
return
|
||||
|
||||
animate(src, alpha = 0, time = fade_out_time)
|
||||
addtimer(CALLBACK(src, PROC_REF(end_play)), fade_out_time)
|
||||
|
||||
///ends the play then deletes this screen object and plays the next one in queue if it exists
|
||||
/atom/movable/screen/text/screen_text/proc/end_play()
|
||||
if(!player)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
player.remove_from_screen(src)
|
||||
LAZYREMOVE(player.screen_texts, src)
|
||||
qdel(src)
|
||||
|
||||
if(QDELETED(player))
|
||||
QDEL_NULL_LIST(player.screen_texts)
|
||||
return
|
||||
|
||||
if(LAZYLEN(player.screen_texts))
|
||||
player.screen_texts[1].play_to_client() // Theres more?
|
||||
@@ -142,6 +142,56 @@
|
||||
var/datum/tgui_module/narrate_panel/NP = new /datum/tgui_module/narrate_panel(usr)
|
||||
NP.ui_interact(usr)
|
||||
|
||||
/mob/abstract/ghost/storyteller/verb/local_screen_text()
|
||||
set name = "Local Screen Text"
|
||||
set category = "Storyteller"
|
||||
|
||||
var/list/mob/message_mobs = list()
|
||||
var/choice = html_decode(sanitize(tgui_alert(src, "Local Screen Text will send a screen text message to mobs. Do you want the mobs messaged to be only ones that you can see, or ignore blocked vision and message everyone within seven tiles of you?", "Narrate Selection", list("View", "Range", "Cancel"))))
|
||||
if(choice != "Cancel")
|
||||
if(choice == "View")
|
||||
message_mobs = mobs_in_view(world.view, src)
|
||||
else
|
||||
for(var/mob/M in range(world.view, src))
|
||||
message_mobs += M
|
||||
else
|
||||
return
|
||||
|
||||
var/msg = tgui_input_text(src, "Insert the screen message you want to send.", "Local Screen Text")
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
var/big_text = tgui_alert(src, "Do you want big or normal text?", "Local Screen Text", list("Big", "Normal"))
|
||||
var/text_type = /atom/movable/screen/text/screen_text
|
||||
if(big_text == "Big")
|
||||
text_type = /atom/movable/screen/text/screen_text/command_order
|
||||
|
||||
for(var/mob/M in message_mobs)
|
||||
if(M.client)
|
||||
M.play_screen_text(msg, text_type, COLOR_PURPLE)
|
||||
log_admin("LocalScreenText: [key_name(usr)] : [msg]")
|
||||
message_admins(SPAN_NOTICE("Local Screen Text: [key_name_admin(usr)] : [msg]"), 1)
|
||||
|
||||
/mob/abstract/ghost/storyteller/verb/global_screen_text()
|
||||
set name = "Global Screen Text"
|
||||
set category = "Storyteller"
|
||||
|
||||
var/msg = html_decode(sanitize(tgui_input_text(src, "Insert the screen message you want to send.", "Global Screen Text")))
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
var/big_text = tgui_alert(src, "Do you want big or normal text?", "Global Screen Text", list("Big", "Normal"))
|
||||
var/text_type = /atom/movable/screen/text/screen_text
|
||||
if(big_text == "Big")
|
||||
text_type = /atom/movable/screen/text/screen_text/command_order
|
||||
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
if(M.client)
|
||||
M.play_screen_text(msg, text_type, COLOR_PURPLE)
|
||||
|
||||
log_admin("GlobalScreenText: [key_name(usr)] : [msg]")
|
||||
message_admins(SPAN_NOTICE("Global Screen Text: [key_name_admin(usr)] : [msg]"), 1)
|
||||
|
||||
/mob/abstract/ghost/storyteller/verb/storyteller_direct_narrate(var/mob/M)
|
||||
set name = "Direct Narrate"
|
||||
set category = "Storyteller"
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
// Thanks to Burger from Burgerstation for the foundation for this
|
||||
GLOBAL_LIST_INIT(floating_chat_colors, list())
|
||||
|
||||
///Compute an unique key that is used to associate an image to the client that received said image
|
||||
#define STORED_CHAT_TEXT_HASH(client) "[client.ckey]"
|
||||
/atom/movable
|
||||
/**
|
||||
* A lazy list with the following format:
|
||||
*
|
||||
* * K -> The hash function result of STORED_CHAT_TEXT_HASH, a string
|
||||
* * V -> A `/list` of `/image`, the images are the runetext sent to be shown to the various clients (as per the hash function)
|
||||
*/
|
||||
VAR_PRIVATE/list/stored_chat_text
|
||||
|
||||
/atom/movable/proc/get_floating_chat_color()
|
||||
return get_random_colour(0, 160, 230)
|
||||
|
||||
/atom/movable/proc/set_floating_chat_color(color)
|
||||
GLOB.floating_chat_colors[name] = color
|
||||
|
||||
/atom/movable/proc/animate_chat(message, datum/language/language, small, list/show_to, duration, override_color)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
var/style //additional style params for the message
|
||||
var/fontsize = GENERATE_FLOATING_TEXT_MEDIUM
|
||||
if(small)
|
||||
fontsize = GENERATE_FLOATING_TEXT_SMALL
|
||||
var/limit = 50
|
||||
if(copytext(message, length(message) - 1) == "!!")
|
||||
fontsize = GENERATE_FLOATING_TEXT_LARGE
|
||||
limit = 30
|
||||
style += "font-weight: bold;"
|
||||
|
||||
if(length(message) > limit)
|
||||
message = "[copytext_char(message, 1, limit)]..."
|
||||
|
||||
if(istype(language, /datum/language/noise))
|
||||
message = "<font color='#7F7F7F'>*</font> " + uncapitalize(message)
|
||||
|
||||
if(!GLOB.floating_chat_colors[name])
|
||||
GLOB.floating_chat_colors[name] = get_floating_chat_color()
|
||||
style += "color: [GLOB.floating_chat_colors[name]];"
|
||||
|
||||
send_chat_floating_text_to_clients(show_to, message, fontsize, style, duration, language)
|
||||
|
||||
|
||||
/**
|
||||
* Generates a floating message image and sent it to the clients
|
||||
*
|
||||
*
|
||||
* * show_to - A `/list` of clients to show the image to
|
||||
* * message - A string, the message to show
|
||||
* * style - String, a CSS-DM that will be injected in the style of the maptext, MUST be semicolon (;) terminated
|
||||
* * duration - Duration in deciseconds to show the message for
|
||||
* * language - A `/datum/language`, to appropriately change the image based on the understanding of the mob that receives it
|
||||
*/
|
||||
/atom/movable/proc/send_chat_floating_text_to_clients(list/client/show_to, message, fontsize, style, duration, datum/language/language)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
// create 2 messages, one that appears if you know the language, and one that appears when you don't know the language
|
||||
for(var/client/C in show_to)
|
||||
if(!(C.prefs.toggles_secondary & FLOATING_MESSAGES))
|
||||
continue
|
||||
|
||||
var/message_to_put_in_image
|
||||
|
||||
//See if it needs an understood message, or a gibberish one, to be shown, and generate it
|
||||
if(isnull(language) || C.mob.say_understands(null, language))
|
||||
message_to_put_in_image = capitalize(message)
|
||||
else if(!isnull(language))
|
||||
message_to_put_in_image = language.scramble(message)
|
||||
|
||||
//Generate the image, sent it to the client
|
||||
generate_floating_text(message_to_put_in_image, style, fontsize, duration, C)
|
||||
|
||||
|
||||
/**
|
||||
* Generates a floating text message and takes care of showing it to the client, and remove it
|
||||
*
|
||||
*
|
||||
* * message - String, the text to put into the floating text
|
||||
* * style - String, a CSS-DM that will be injected in the style of the maptext, MUST be semicolon (;) terminated
|
||||
* * fontsize - One of the GENERATE_FLOATING_TEXT_* macros defined in `code\__DEFINES\text.dm`, determines the size
|
||||
* * duration - Duration in deciseconds to show the message for
|
||||
*
|
||||
* This process can sleep as it uses the client to measure the size of text, it should only be called inside a non-blocking call chain
|
||||
*
|
||||
*/
|
||||
/atom/movable/proc/generate_floating_text(message, style, fontsize = GENERATE_FLOATING_TEXT_MEDIUM, duration, client/show_to)
|
||||
set waitfor = FALSE
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
if(!istype(show_to))
|
||||
crash_with("Wrong argument supplied, show_to is not a client!")
|
||||
|
||||
//No point if the source or the destination of the floating text are deleted
|
||||
if(QDELETED(src) || QDELETED(show_to))
|
||||
return FALSE
|
||||
|
||||
var/atom/movable/attached_holder = get_last_atom_before_turf(src)
|
||||
var/image/I = image(null, attached_holder, layer = FLY_LAYER)
|
||||
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA | KEEP_APART | PIXEL_SCALE
|
||||
|
||||
I.plane = HUD_PLANE
|
||||
I.layer = UNDER_HUD_LAYER
|
||||
I.appearance_flags = RESET_COLOR|RESET_ALPHA|RESET_TRANSFORM
|
||||
|
||||
I.alpha = 0
|
||||
|
||||
I.maptext_width = CHAT_MESSAGE_WIDTH
|
||||
|
||||
I.pixel_y = attached_holder.get_floating_chat_y_offset()
|
||||
I.pixel_x = (-round(I.maptext_width/2) + 16) + attached_holder.get_floating_chat_x_offset()
|
||||
|
||||
//Select the various parameters for the maptext, to ensure pixel-perfect scaling
|
||||
var/font_family
|
||||
var/font_size
|
||||
var/other
|
||||
switch(fontsize)
|
||||
if(GENERATE_FLOATING_TEXT_SMALL)
|
||||
font_family = "Spess Font"
|
||||
font_size = 6
|
||||
other = "-dm-text-outline: 1px black sharp; line-height: 1.4;"
|
||||
if(GENERATE_FLOATING_TEXT_MEDIUM)
|
||||
font_family = "Grand9K Pixel"
|
||||
font_size = 6
|
||||
other = "-dm-text-outline: 1px black sharp;"
|
||||
if(GENERATE_FLOATING_TEXT_LARGE)
|
||||
font_family = "Grand9K Pixel"
|
||||
font_size = 12
|
||||
other = "-dm-text-outline: 1.2px black sharp;"
|
||||
else
|
||||
crash_with("Wrong size specified, use one of the defines!")
|
||||
|
||||
var/complete_text = "<span class='center'><span style='font-family: \"[font_family]\"; font-size: [font_size]pt; [other] [style] text-align: center;'>[message]</span></span>"
|
||||
|
||||
I.maptext = complete_text
|
||||
|
||||
//At this point we enter the wait, we patiently wait for the client to tell us how large
|
||||
//the text will be on its screen, as we need that info for the image generation afterwards
|
||||
var/mheight = 0
|
||||
WXH_TO_HEIGHT(show_to.MeasureText(complete_text, null, CHAT_MESSAGE_WIDTH), mheight)
|
||||
|
||||
//Then we register a callback to complete the image generation, this is done to avoid
|
||||
//the proc waking up at the end of a tick and cause overtime
|
||||
SSrunechat.message_queue += CALLBACK(src, PROC_REF(finish_generate_floating_text), I, mheight, show_to, duration)
|
||||
|
||||
|
||||
/**
|
||||
* Runs after the calculation of the client for the runechat size measurement,
|
||||
* takes care of the last things needed to be set on the image, to display it to the clients,
|
||||
* and to register it for removal when it expires
|
||||
*
|
||||
* Should only, ever be called by the runechat subsystem as a consequence of the `generate_floating_text()` callback insertion
|
||||
*/
|
||||
/atom/movable/proc/finish_generate_floating_text(image/runetext_image, mheight, client/show_to, lifespan)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
//The client can go offline, which would cause a runtime below
|
||||
//this prevents the runtime, checking for both null and being deleted
|
||||
if(QDELETED(show_to))
|
||||
return
|
||||
|
||||
runetext_image.maptext_height = mheight * 1.25
|
||||
|
||||
var/stored_chat_text_hash_cache = STORED_CHAT_TEXT_HASH(show_to)
|
||||
|
||||
//Older runetext messages are shifted up so they clear the visual for the new ones
|
||||
for(var/image/old in LAZYACCESS(src.stored_chat_text, stored_chat_text_hash_cache))
|
||||
animate(old, 2, pixel_y = old.pixel_y + min(runetext_image.maptext_height, 45) + 8)
|
||||
|
||||
//We register ourself as a stored chat text image
|
||||
LAZYADDASSOCLIST(src.stored_chat_text, stored_chat_text_hash_cache, runetext_image)
|
||||
|
||||
//Send the image to the client, takes care to remove it afterwards
|
||||
flick_overlay(runetext_image, list(show_to), (lifespan + 2))
|
||||
|
||||
//Animation to show the text "appearing up"
|
||||
animate(runetext_image, 1, alpha = 255, pixel_y = runetext_image.pixel_y + 23)
|
||||
|
||||
//Register a timer for our removal from the list
|
||||
addtimer(CALLBACK(src, PROC_REF(remove_floating_text), runetext_image, stored_chat_text_hash_cache), lifespan)
|
||||
|
||||
|
||||
/// Gives floating text to src upon holder entering
|
||||
/atom/movable/proc/give_floating_text(atom/movable/holder)
|
||||
PRIVATE_PROC(TRUE)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
if(!holder)
|
||||
return
|
||||
for(var/key in holder.stored_chat_text)
|
||||
for(var/image/I in holder.stored_chat_text[key])
|
||||
I.loc = src
|
||||
|
||||
/// Returns floating text to holder upon leaving src
|
||||
/atom/movable/proc/return_floating_text(atom/movable/holder)
|
||||
PRIVATE_PROC(TRUE)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
if(!holder)
|
||||
return
|
||||
for(var/key in holder.stored_chat_text)
|
||||
for(var/image/I in holder.stored_chat_text[key])
|
||||
I.loc = holder
|
||||
|
||||
/atom/movable/proc/remove_floating_text(image/image_to_remove, stored_chat_text_hash)
|
||||
PRIVATE_PROC(TRUE)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
var/list/image/client_associated_images = LAZYACCESS(src.stored_chat_text, stored_chat_text_hash)
|
||||
if(!(client_associated_images?.Find(image_to_remove)))
|
||||
crash_with("Trying to remove a floating text image that is not there!")
|
||||
|
||||
animate(image_to_remove, 2, pixel_y = image_to_remove.pixel_y + 10, alpha = 0)
|
||||
LAZYREMOVEASSOC(src.stored_chat_text, stored_chat_text_hash, image_to_remove)
|
||||
|
||||
#undef STORED_CHAT_TEXT_HASH
|
||||
@@ -352,7 +352,11 @@ var/list/channel_to_radio_key = new
|
||||
speech_bubble.appearance_flags = RESET_COLOR|RESET_ALPHA
|
||||
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(animate_speechbubble), speech_bubble, hear_clients, 30)
|
||||
|
||||
animate_chat(message, speaking, italics, hear_clients, 30)
|
||||
var/list/langchat_styles = list()
|
||||
if(istype(speaking, /datum/language/noise))
|
||||
langchat_styles = list("emote", "langchat_small")
|
||||
|
||||
langchat_speech(message, get_hearers_in_view(message_range, src), speaking, additional_styles = langchat_styles)
|
||||
|
||||
var/bypass_listen_obj = (speaking && (speaking.flags & PASSLISTENOBJ))
|
||||
if(!bypass_listen_obj)
|
||||
|
||||
@@ -252,6 +252,8 @@
|
||||
|
||||
var/list/active_genes=list()
|
||||
var/mob_size = MOB_MEDIUM
|
||||
/// The icon size width of the mob. Used for langchat resizing.
|
||||
var/icon_size = 32
|
||||
|
||||
var/list/progressbars
|
||||
|
||||
|
||||
Reference in New Issue
Block a user