mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-21 21:10:30 +01:00
af0312c7d4
Fixes https://github.com/Aurorastation/Aurora.3/issues/18504 Fixes https://github.com/Aurorastation/Aurora.3/issues/21064 Fixes https://github.com/Aurorastation/Aurora.3/issues/21267 Fixes https://github.com/Aurorastation/Aurora.3/issues/21455 Fixes https://github.com/Aurorastation/Aurora.3/issues/21535 Miscellaneous bugfixes, code cleanup, etc. Smaller batches this time. changes: - spellcheck: "Renames 'gibber' to 'autobutcher'." - code_imp: "Cleans up a lot of old autobutcher code." - code_imp: "Simplifies and unifies a lot of circuit board naming code." - code_imp: "Updates various code comments to DMDocs format." - balance: "Slightly increased damage of beating someone with a ladder." - bugfix: "Fixes foreign speech displaying the translated versions in langchat for non-fluent listeners." - bugfix: "Fixes whispered speech langchat; whispers are now correctly italicized." - bugfix: "Fixes shouted speech langchat; shouts are now correctly biggified." - bugfix: "Adds missing Omni Gas Mixer, Gas Meter options from RFD-P." - bugfix: "Adds missing circuit boards for bioballistic delivery system, lysis-isolation centrifuge, and autobutcher to allow for construction and deconstruction." - bugfix: "Fixes empty algae chips bag having description set for its name." - bugfix: "Adds fallback_specific_heat values to several reagents that were missing them." - bugfix: "Fixes antimateriel projectiles being erroneously damage-capped when hitting walls." - bugfix: "Fixes laser beam effects not using the base colors of their beam VFX." - qol: "Added helpful feedback hint to move closer when someone speaks aloud within 4 tiles while you're in vacuum (as features go, this one felt more like a bug to experience)." - qol: "Updated various examine hints." --------- Signed-off-by: Batrachophreno <Batrochophreno@gmail.com>
301 lines
13 KiB
Plaintext
301 lines
13 KiB
Plaintext
/atom/var/langchat_height = 32 // abovetile usually
|
|
/atom/var/langchat_color = "#FFFFFF"
|
|
/atom/var/langchat_styles = ""
|
|
|
|
#define LANGCHAT_LONGEST_TEXT 64
|
|
#define LANGCHAT_WIDTH 96
|
|
#define LANGCHAT_MAX_ALPHA 196
|
|
|
|
//pop defines
|
|
#define LANGCHAT_DEFAULT_POP 0 //normal message
|
|
#define LANGCHAT_PANIC_POP 1 //this causes shaking
|
|
#define LANGCHAT_FAST_POP 2 //this just makes it go away faster
|
|
|
|
// params for default pop
|
|
#define LANGCHAT_MESSAGE_POP_TIME 3
|
|
#define LANGCHAT_MESSAGE_POP_Y_SINK 8
|
|
|
|
// params for panic pop
|
|
#define LANGCHAT_MESSAGE_PANIC_POP_TIME 1
|
|
#define LANGCHAT_MESSAGE_PANIC_POP_Y_SINK 8
|
|
#define LANGCHAT_MESSAGE_PANIC_SHAKE_SIZE 6
|
|
#define LANGCHAT_MESSAGE_PANIC_SHAKE_TIMES 6
|
|
#define LANGCHAT_MESSAGE_PANIC_SHAKE_TIME_TAKEN 1
|
|
// params for fast pop
|
|
#define LANGCHAT_MESSAGE_FAST_POP_TIME 1
|
|
#define LANGCHAT_MESSAGE_FAST_POP_Y_SINK 8
|
|
|
|
#define langchat_client_enabled(M) (M && M.client && M.client.prefs && (M.client.prefs.toggles_secondary & FLOATING_MESSAGES))
|
|
|
|
/*
|
|
* Duplicate vars and logic created for untranslated images for the sake of getting an untranslated langchat to display for listeners who do not understand
|
|
* the language being spoken. Someone could certainly think of cleaner ways to do this, but for want of a better solution right now, it has been implemented
|
|
* in this rote manner to make it easier to strip out in future if it needs replaced.
|
|
*/
|
|
|
|
/atom/var/image/langchat_image
|
|
/atom/var/image/langchat_image_untranslated
|
|
/atom/var/list/mob/langchat_listeners
|
|
/atom/var/list/mob/langchat_listeners_untranslated
|
|
|
|
/// Hides the images, if they exist. Do not null the langchat images; they are rotated when the mob is buckled or proned to maintain text orientation.
|
|
/atom/proc/langchat_drop_images()
|
|
if(langchat_listeners)
|
|
for(var/mob/M in langchat_listeners)
|
|
if(M.client)
|
|
M.client.images -= langchat_image
|
|
for(var/mob/M in langchat_listeners_untranslated)
|
|
if(M.client)
|
|
M.client.images -= langchat_image_untranslated
|
|
langchat_listeners = null
|
|
langchat_listeners_untranslated = null
|
|
|
|
/atom/proc/get_maxptext_x_offset(image/maptext_image)
|
|
return (world.icon_size / 2) - (maptext_image.maptext_width / 2)
|
|
|
|
/atom/movable/get_maxptext_x_offset(image/maptext_image)
|
|
return (bound_width / 2) - (maptext_image.maptext_width / 2)
|
|
|
|
/mob/get_maxptext_x_offset(image/maptext_image)
|
|
return (icon_size / 2) - (maptext_image.maptext_width / 2)
|
|
|
|
/// Creates the image if it doesn't exist, resets settings that are modified by speech procs.
|
|
/atom/proc/langchat_make_image(override_color = null)
|
|
if(!langchat_image)
|
|
langchat_image = image(null, src)
|
|
langchat_image.layer = 20
|
|
langchat_image.plane = RUNECHAT_PLANE
|
|
langchat_image.appearance_flags = NO_CLIENT_COLOR|KEEP_APART|RESET_COLOR|RESET_TRANSFORM
|
|
langchat_image.maptext_y = langchat_height
|
|
langchat_image.maptext_height = 64
|
|
langchat_image.maptext_y -= LANGCHAT_MESSAGE_POP_Y_SINK
|
|
langchat_image.maptext_x = get_maxptext_x_offset(langchat_image)
|
|
|
|
langchat_image.pixel_y = 0
|
|
langchat_image.alpha = 0
|
|
langchat_image.color = override_color ? override_color : langchat_color
|
|
if(appearance_flags & PIXEL_SCALE)
|
|
langchat_image.appearance_flags |= PIXEL_SCALE
|
|
|
|
/mob/langchat_make_image(override_color = null)
|
|
var/new_image = FALSE
|
|
if(!langchat_image)
|
|
new_image = TRUE
|
|
. = ..()
|
|
// Recenter for icons more than 32 wide
|
|
if(new_image)
|
|
langchat_image.maptext_x += (icon_size - 32) / 2
|
|
|
|
/// Creates the (untranslated) image if it doesn't exist, resets settings that are modified by speech procs.
|
|
/atom/proc/langchat_make_image_untranslated(override_color = null)
|
|
if(!langchat_image_untranslated)
|
|
langchat_image_untranslated = image(null, src)
|
|
langchat_image_untranslated.layer = 20
|
|
langchat_image_untranslated.plane = RUNECHAT_PLANE
|
|
langchat_image_untranslated.appearance_flags = NO_CLIENT_COLOR|KEEP_APART|RESET_COLOR|RESET_TRANSFORM
|
|
langchat_image_untranslated.maptext_y = langchat_height
|
|
langchat_image_untranslated.maptext_height = 64
|
|
langchat_image_untranslated.maptext_y -= LANGCHAT_MESSAGE_POP_Y_SINK
|
|
langchat_image_untranslated.maptext_x = get_maxptext_x_offset(langchat_image_untranslated)
|
|
|
|
langchat_image_untranslated.pixel_y = 0
|
|
langchat_image_untranslated.alpha = 0
|
|
langchat_image_untranslated.color = override_color ? override_color : langchat_color
|
|
if(appearance_flags & PIXEL_SCALE)
|
|
langchat_image_untranslated.appearance_flags |= PIXEL_SCALE
|
|
|
|
/mob/langchat_make_image_untranslated(override_color = null)
|
|
var/new_image = FALSE
|
|
if(!langchat_image_untranslated)
|
|
new_image = TRUE
|
|
. = ..()
|
|
// Recenter for icons more than 32 wide
|
|
if(new_image)
|
|
langchat_image_untranslated.maptext_x += (icon_size - 32) / 2
|
|
|
|
/mob/abstract/ghost/langchat_make_image(override_color = null)
|
|
if(!override_color)
|
|
override_color = "#c51fb7"
|
|
. = ..()
|
|
langchat_image.appearance_flags |= RESET_ALPHA
|
|
|
|
/atom/proc/langchat_speech(message, list/listeners, datum/language/language, override_color, skip_language_check = FALSE, animation_style = LANGCHAT_DEFAULT_POP, list/additional_styles = list("langchat"))
|
|
langchat_drop_images()
|
|
langchat_make_image(override_color)
|
|
langchat_make_image_untranslated(override_color)
|
|
|
|
langchat_listeners = listeners
|
|
langchat_listeners_untranslated = list()
|
|
var/mob/listener
|
|
// Listener list management.
|
|
for(listener in langchat_listeners)
|
|
// Remove those who have the langchat_client disabled or who are deaf.
|
|
if(!langchat_client_enabled(listener) || listener.ear_deaf)
|
|
langchat_listeners -= listener
|
|
continue
|
|
// Handle listeners who don't understand the language being spoken.
|
|
if(!skip_language_check && !listener.say_understands(src, language))
|
|
langchat_listeners_untranslated += listener
|
|
langchat_listeners -= listener
|
|
|
|
// Generate the translated langchat_image.
|
|
langchat_image.maptext = generate_text_image(message, additional_styles = additional_styles)
|
|
langchat_image.maptext_width = LANGCHAT_WIDTH
|
|
langchat_image.maptext_x = get_maxptext_x_offset(langchat_image)
|
|
for(var/mob/comprehending_listener in langchat_listeners)
|
|
comprehending_listener.client.images += langchat_image
|
|
|
|
// Generate the untranslated langchat_image. Note that we have to loop through confused listeners first here, as some
|
|
// might know languages that confer partial comprehension, and that would result in a unique langchat image.
|
|
for(var/mob/confused_listener in langchat_listeners_untranslated)
|
|
langchat_image_untranslated.maptext = generate_text_image(message, language, additional_styles, confused_listener.languages)
|
|
langchat_image_untranslated.maptext_width = LANGCHAT_WIDTH
|
|
langchat_image_untranslated.maptext_x = get_maxptext_x_offset(langchat_image_untranslated)
|
|
confused_listener.client.images += langchat_image_untranslated
|
|
|
|
var/timer = (length(message) / LANGCHAT_LONGEST_TEXT) * 4 SECONDS + 2 SECONDS
|
|
|
|
if(isturf(loc))
|
|
langchat_image.loc = src
|
|
if(langchat_image_untranslated)
|
|
langchat_image_untranslated.loc = src
|
|
else
|
|
langchat_image.loc = recursive_holder_check(src)
|
|
if(langchat_image_untranslated)
|
|
langchat_image_untranslated.loc = recursive_holder_check(src)
|
|
|
|
animate_style(langchat_image, animation_style)
|
|
if(langchat_listeners_untranslated)
|
|
animate_style(langchat_image_untranslated, animation_style)
|
|
|
|
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, langchat_drop_images), language), timer, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_NO_HASH_WAIT)
|
|
|
|
/atom/proc/langchat_long_speech(message, list/listeners, datum/language/language, override_color, skip_language_check = FALSE)
|
|
langchat_drop_images()
|
|
langchat_make_image()
|
|
langchat_make_image_untranslated(override_color)
|
|
|
|
var/text_left = null
|
|
var/truncated_message = message
|
|
|
|
langchat_listeners = listeners
|
|
var/mob/listener
|
|
// Listener list management.
|
|
for(listener in langchat_listeners)
|
|
// Remove those who have the langchat_client disabled or who are deaf.
|
|
if(!langchat_client_enabled(listener) || listener.ear_deaf)
|
|
langchat_listeners -= listener
|
|
// Handle listeners who don't understand the language being spoken.
|
|
if(!skip_language_check && !listener.say_understands(src, language))
|
|
langchat_listeners_untranslated += listener
|
|
langchat_listeners -= listener
|
|
|
|
if(length(message) > LANGCHAT_LONGEST_TEXT)
|
|
truncated_message = copytext_char(message, 1, LANGCHAT_LONGEST_TEXT - 5) + "..."
|
|
text_left = "..." + copytext_char(message, LANGCHAT_LONGEST_TEXT - 5)
|
|
var/timer = 6 SECONDS
|
|
if(text_left)
|
|
timer = 4 SECONDS
|
|
truncated_message = "<span class='center [langchat_styles] langchat_announce langchat'>[truncated_message]</span>"
|
|
|
|
// Generate the translated langchat_image.
|
|
langchat_image.maptext = generate_text_image(truncated_message)
|
|
langchat_image.maptext_width = LANGCHAT_WIDTH
|
|
langchat_image.maptext_x = get_maxptext_x_offset(langchat_image)
|
|
for(var/mob/comprehending_listener in langchat_listeners)
|
|
comprehending_listener.client.images += langchat_image
|
|
|
|
// Generate the untranslated langchat_image. Note that we have to loop through confused listeners first here, as some
|
|
// might know languages that confer partial comprehension, and that would result in a unique langchat image.
|
|
for(var/mob/confused_listener in langchat_listeners_untranslated)
|
|
langchat_image_untranslated.maptext = confused_listener.generate_text_image(truncated_message, src)
|
|
langchat_image_untranslated.maptext_width = LANGCHAT_WIDTH
|
|
langchat_image_untranslated.maptext_x = get_maxptext_x_offset(langchat_image_untranslated)
|
|
confused_listener.client.images += langchat_image_untranslated
|
|
|
|
if(isturf(loc))
|
|
langchat_image.loc = src
|
|
if(langchat_image_untranslated)
|
|
langchat_image_untranslated.loc = src
|
|
else
|
|
langchat_image.loc = recursive_holder_check(src)
|
|
if(langchat_image_untranslated)
|
|
langchat_image_untranslated.loc = recursive_holder_check(src)
|
|
|
|
animate_style(langchat_image)
|
|
if(langchat_listeners_untranslated)
|
|
animate_style(langchat_image_untranslated)
|
|
|
|
if(text_left)
|
|
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, langchat_long_speech), text_left, listeners, language), timer, TIMER_OVERRIDE|TIMER_UNIQUE|TIMER_NO_HASH_WAIT)
|
|
else
|
|
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, langchat_drop_images), language), timer, TIMER_OVERRIDE|TIMER_UNIQUE|TIMER_NO_HASH_WAIT)
|
|
|
|
/**
|
|
* Generates the maptext_image, translated or untranslated, for a given message.
|
|
*/
|
|
/atom/proc/generate_text_image(message, datum/language/language = null, list/additional_styles = list("langchat"), list/languages = null)
|
|
var/text_to_display = message
|
|
var/use_mob_style = TRUE
|
|
var/image/r_icon
|
|
|
|
if(language)
|
|
message = language.scramble(message, languages)
|
|
text_to_display = message
|
|
|
|
if(length(text_to_display) > LANGCHAT_LONGEST_TEXT)
|
|
text_to_display = copytext_char(text_to_display, 1, LANGCHAT_LONGEST_TEXT + 1) + "..."
|
|
if(additional_styles.Find("emote"))
|
|
additional_styles.Remove("emote")
|
|
use_mob_style = FALSE
|
|
r_icon = image('icons/mob/chat_icons.dmi', icon_state = "emote")
|
|
else if(additional_styles.Find("virtual-speaker"))
|
|
additional_styles.Remove("virtual-speaker")
|
|
r_icon = image('icons/mob/chat_icons.dmi', icon_state = "radio")
|
|
if(r_icon)
|
|
text_to_display = "\icon[r_icon]&zwsp;[text_to_display]"
|
|
|
|
text_to_display = "<span class='center [additional_styles != null ? additional_styles.Join(" ") : ""] [use_mob_style ? langchat_styles : ""] langchat'>[text_to_display]</span>"
|
|
return text_to_display
|
|
|
|
/**
|
|
* Animate the given maptext_image.
|
|
*/
|
|
/atom/proc/animate_style(var/image/langchat_image, animation_style = LANGCHAT_DEFAULT_POP)
|
|
if(langchat_image)
|
|
switch(animation_style)
|
|
if(LANGCHAT_DEFAULT_POP)
|
|
langchat_image.alpha = 0
|
|
animate(langchat_image, pixel_y = langchat_image.pixel_y + LANGCHAT_MESSAGE_POP_Y_SINK, alpha = LANGCHAT_MAX_ALPHA, time = LANGCHAT_MESSAGE_POP_TIME)
|
|
if(LANGCHAT_PANIC_POP)
|
|
langchat_image.alpha = LANGCHAT_MAX_ALPHA
|
|
animate(langchat_image, pixel_y = langchat_image.pixel_y + LANGCHAT_MESSAGE_PANIC_POP_Y_SINK, time = LANGCHAT_MESSAGE_PANIC_POP_TIME)
|
|
animate(pixel_x = langchat_image.pixel_x - LANGCHAT_MESSAGE_PANIC_SHAKE_SIZE, time = LANGCHAT_MESSAGE_PANIC_SHAKE_TIME_TAKEN, easing = CUBIC_EASING)
|
|
for(var/i = 1 to LANGCHAT_MESSAGE_PANIC_SHAKE_TIMES)
|
|
animate(pixel_x = langchat_image.pixel_x + 2*LANGCHAT_MESSAGE_PANIC_SHAKE_SIZE, time = 2*LANGCHAT_MESSAGE_PANIC_SHAKE_TIME_TAKEN, easing = CUBIC_EASING)
|
|
animate(pixel_x = langchat_image.pixel_x - 2*LANGCHAT_MESSAGE_PANIC_SHAKE_SIZE, time = LANGCHAT_MESSAGE_PANIC_SHAKE_TIME_TAKEN, easing = CUBIC_EASING)
|
|
animate(pixel_x = langchat_image.pixel_x + LANGCHAT_MESSAGE_PANIC_SHAKE_SIZE, time = LANGCHAT_MESSAGE_PANIC_SHAKE_TIME_TAKEN, easing = CUBIC_EASING)
|
|
if(LANGCHAT_FAST_POP)
|
|
langchat_image.alpha = 0
|
|
animate(langchat_image, pixel_y = langchat_image.pixel_y + LANGCHAT_MESSAGE_FAST_POP_Y_SINK, alpha = LANGCHAT_MAX_ALPHA, time = LANGCHAT_MESSAGE_FAST_POP_TIME)
|
|
|
|
/** Displays image to a single listener after it was built above eg. for chaining different game logic than speech code
|
|
This does just that, doesn't check deafness or language! Do what you will in that regard **/
|
|
/atom/proc/langchat_display_image(mob/M)
|
|
if(langchat_image)
|
|
if(!langchat_client_enabled(M))
|
|
return
|
|
if(!langchat_listeners) // shouldn't happen
|
|
langchat_listeners = list()
|
|
langchat_listeners |= M
|
|
M.client.images += langchat_image
|
|
|
|
/// Will attempt to find what's holding this item if it's being contained by something, ie if it's in a satchel held by a human, this'll return the human
|
|
/proc/recursive_holder_check(obj/item/held_item, recursion_limit = 3)
|
|
if(recursion_limit <= 0)
|
|
return held_item
|
|
if(!held_item.loc || isturf(held_item.loc))
|
|
return held_item
|
|
recursion_limit--
|
|
return recursive_holder_check(held_item.loc, recursion_limit)
|