Ports Runechat

This commit is contained in:
Chompstation Bot
2021-05-30 22:51:20 +00:00
parent 1c3e965b5c
commit 4476e4104d
48 changed files with 4183 additions and 1255 deletions

View File

@@ -93,6 +93,8 @@ What is the naming convention for planes or layers?
#define BELOW_MOB_LAYER 3.9 // Should be converted to plane swaps
#define ABOVE_MOB_LAYER 4.1 // Should be converted to plane swaps
#define ABOVE_MOB_PLANE -24
// Invisible things plane
#define CLOAKED_PLANE -15
@@ -122,6 +124,7 @@ What is the naming convention for planes or layers?
#define PLANE_PLANETLIGHTING 4 //Lighting on planets
#define PLANE_LIGHTING 5 //Where the lighting (and darkness) lives
#define PLANE_LIGHTING_ABOVE 6 //For glowy eyes etc. that shouldn't be affected by darkness
#define PLANE_RUNECHAT 7
#define PLANE_GHOSTS 10 //Spooooooooky ghooooooosts
#define PLANE_AI_EYE 11 //The AI eye lives here

View File

@@ -20,6 +20,8 @@
#define TICKS2DS(T) ((T) TICKS) // Convert ticks to deciseconds
#define DS2NEARESTTICK(DS) TICKS2DS(-round(-(DS2TICKS(DS))))
var/world_startup_time
/proc/get_game_time()
var/global/time_offset = 0
var/global/last_time = 0

330
code/datums/chat_message.dm Normal file
View File

@@ -0,0 +1,330 @@
#define CHAT_MESSAGE_SPAWN_TIME 0.2 SECONDS
#define CHAT_MESSAGE_LIFESPAN 5 SECONDS
#define CHAT_MESSAGE_EOL_FADE 0.7 SECONDS
#define CHAT_MESSAGE_EXP_DECAY 0.8 // Messages decay at pow(factor, idx in stack)
#define CHAT_MESSAGE_HEIGHT_DECAY 0.7 // 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_EXT_WIDTH 128
#define CHAT_MESSAGE_LENGTH 68 // characters
#define CHAT_MESSAGE_EXT_LENGTH 150
#define CHAT_MESSAGE_MOB 1
#define CHAT_MESSAGE_OBJ 2
#define WXH_TO_HEIGHT(x) text2num(copytext((x), findtextEx((x), "x") + 1)) // thanks lummox
#define CHAT_RUNE_EMOTE 0x1
#define CHAT_RUNE_RADIO 0x2
/**
* # Chat Message Overlay
*
* Datum for generating a message overlay on the map
* Ported from TGStation; https://github.com/tgstation/tgstation/pull/50608/, author: bobbahbrown
*/
// Cached runechat icon
var/list/runechat_image_cache = list()
/hook/startup/proc/runechat_images()
var/image/radio_image = image('icons/UI_Icons/chat/chat_icons.dmi', icon_state = "radio")
runechat_image_cache["radio"] = radio_image
var/image/emote_image = image('icons/UI_Icons/chat/chat_icons.dmi', icon_state = "emote")
runechat_image_cache["emote"] = emote_image
return TRUE
/datum/chatmessage
/// The visual element of the chat messsage
var/image/message
/// The location in which the message is appearing
var/atom/message_loc
/// The client who heard this message
var/client/owned_by
/// Contains the scheduled destruction time
var/scheduled_destruction
/// Contains the approximate amount of lines for height decay
var/approx_lines
/// If we are currently processing animation and cleanup at EOL
var/ending_life
/**
* Constructs a chat message overlay
*
* Arguments:
* * text - The text content of the overlay
* * target - The target atom to display the overlay at
* * owner - The mob that owns this overlay, only this mob will be able to view it
* * extra_classes - Extra classes to apply to the span that holds the text
* * lifespan - The lifespan of the message in deciseconds
*/
/datum/chatmessage/New(text, atom/target, mob/owner, list/extra_classes = null, lifespan = CHAT_MESSAGE_LIFESPAN)
. = ..()
if(!istype(target))
CRASH("Invalid target given for chatmessage")
if(!istype(owner) || QDELETED(owner) || !owner.client)
stack_trace("/datum/chatmessage created with [isnull(owner) ? "null" : "invalid"] mob owner")
qdel(src)
return
generate_image(text, target, owner, extra_classes, lifespan)
/datum/chatmessage/Destroy()
if(owned_by)
LAZYREMOVEASSOC(owned_by.seen_messages, message_loc, src)
owned_by.images.Remove(message)
UnregisterSignal(owned_by, COMSIG_PARENT_QDELETING)
if(message_loc)
UnregisterSignal(message_loc, COMSIG_PARENT_QDELETING)
owned_by = null
message_loc = null
message = null
return ..()
/**
* Generates a chat message image representation
*
* Arguments:
* * text - The text content of the overlay
* * target - The target atom to display the overlay at
* * owner - The mob that owns this overlay, only this mob will be able to view it
* * extra_classes - Extra classes to apply to the span that holds the text
* * lifespan - The lifespan of the message in deciseconds
*/
/datum/chatmessage/proc/generate_image(text, atom/target, mob/owner, list/extra_classes, lifespan)
set waitfor = FALSE
// Register client who owns this message
owned_by = owner.client
RegisterSignal(owned_by, COMSIG_PARENT_QDELETING, .proc/qdel_self)
var/extra_length = owned_by.is_preference_enabled(/datum/client_preference/runechat_long_messages)
var/maxlen = extra_length ? CHAT_MESSAGE_EXT_LENGTH : CHAT_MESSAGE_LENGTH
var/msgwidth = extra_length ? CHAT_MESSAGE_EXT_WIDTH : CHAT_MESSAGE_WIDTH
// Clip message
if(length_char(text) > maxlen)
text = copytext_char(text, 1, maxlen + 1) + "..." // BYOND index moment
// Calculate target color if not already present
if(!target.chat_color || target.chat_color_name != target.name)
target.chat_color = colorize_string(target.name)
target.chat_color_darkened = colorize_string(target.name, 0.85, 0.85)
target.chat_color_name = target.name
// Get rid of any URL schemes that might cause BYOND to automatically wrap something in an anchor tag
var/static/regex/url_scheme = new(@"[A-Za-z][A-Za-z0-9+-\.]*:\/\/", "g")
text = replacetext(text, url_scheme, "")
// Reject whitespace
var/static/regex/whitespace = new(@"^\s*$")
if(whitespace.Find(text))
qdel(src)
return
// Non mobs speakers can be small
if(!ismob(target))
extra_classes |= "small"
// If we heard our name, it's important
// Differnt from our own system of name emphasis, maybe unify
var/list/names = splittext(owner.name, " ")
for (var/word in names)
text = replacetext(text, word, "<b>[word]</b>")
var/list/prefixes
// Append prefixes
if(extra_classes.Find("virtual-speaker"))
LAZYADD(prefixes, "\icon[runechat_image_cache["radio"]]")
if(extra_classes.Find("emote"))
// Icon on both ends?
//var/image/I = runechat_image_cache["emote"]
//text = "\icon[I][text]\icon[I]"
// Icon on one end?
//LAZYADD(prefixes, "\icon[runechat_image_cache["emote"]]")
// Asterisks instead?
text = "*&nbsp;[text]&nbsp;*"
text = "[prefixes?.Join("&nbsp;")][text]"
// We dim italicized text to make it more distinguishable from regular text
var/tgt_color = extra_classes.Find("italics") ? target.chat_color_darkened : target.chat_color
// Approximate text height
var/complete_text = "<span class='center maptext [extra_classes != null ? extra_classes.Join(" ") : ""]' style='color: [tgt_color];'>[text]</span>"
var/mheight = WXH_TO_HEIGHT(owned_by.MeasureText(complete_text, null, msgwidth))
approx_lines = max(1, mheight / CHAT_MESSAGE_APPROX_LHEIGHT)
// Translate any existing messages upwards, apply exponential decay factors to timers
message_loc = target
RegisterSignal(message_loc, COMSIG_PARENT_QDELETING, .proc/qdel_self)
if(owned_by.seen_messages)
var/idx = 1
var/combined_height = approx_lines
for(var/msg in owned_by.seen_messages[message_loc])
var/datum/chatmessage/m = msg
animate(m.message, pixel_y = m.message.pixel_y + mheight, time = CHAT_MESSAGE_SPAWN_TIME)
combined_height += m.approx_lines
if(!m.ending_life) // Don't bother!
var/sched_remaining = m.scheduled_destruction - world.time
if(sched_remaining > CHAT_MESSAGE_SPAWN_TIME)
var/remaining_time = (sched_remaining) * (CHAT_MESSAGE_EXP_DECAY ** idx++) * (CHAT_MESSAGE_HEIGHT_DECAY ** combined_height)
m.scheduled_destruction = world.time + remaining_time
spawn(remaining_time)
m.end_of_life()
// Build message image
message = image(loc = message_loc, layer = ABOVE_MOB_LAYER)
message.plane = PLANE_RUNECHAT
message.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA | KEEP_APART
message.alpha = 0
message.pixel_y = owner.bound_height * 0.95
message.maptext_width = msgwidth
message.maptext_height = mheight
message.maptext_x = (msgwidth - owner.bound_width) * -0.5
message.maptext = complete_text
if(owner.contains(target)) // Special case, holding an atom speaking (pAI, recorder...)
message.plane = PLANE_PLAYER_HUD_ABOVE
// View the message
LAZYADDASSOCLIST(owned_by.seen_messages, message_loc, src)
owned_by.images += message
animate(message, alpha = 255, time = CHAT_MESSAGE_SPAWN_TIME)
// Prepare for destruction
scheduled_destruction = world.time + (lifespan - CHAT_MESSAGE_EOL_FADE)
spawn(lifespan - CHAT_MESSAGE_EOL_FADE)
end_of_life()
/**
* Applies final animations to overlay CHAT_MESSAGE_EOL_FADE deciseconds prior to message deletion
*/
/datum/chatmessage/proc/end_of_life(fadetime = CHAT_MESSAGE_EOL_FADE)
if(gc_destroyed || ending_life)
return
ending_life = TRUE
animate(message, alpha = 0, time = fadetime, flags = ANIMATION_PARALLEL)
spawn(fadetime)
qdel(src)
/**
* Creates a message overlay at a defined location for a given speaker
*
* Arguments:
* * speaker - The atom who is saying this message
* * message - The text content of the message
* * italics - Decides if this should be small or not, as generally italics text are for whisper/radio overhear
* * existing_extra_classes - Additional classes to add to the message
*/
/mob/proc/create_chat_message(atom/movable/speaker, message, italics, list/existing_extra_classes, audible = TRUE)
if(!client)
return
// Doesn't want to hear
if(ismob(speaker) && !client.is_preference_enabled(/datum/client_preference/runechat_mob))
return
else if(isobj(speaker) && !client.is_preference_enabled(/datum/client_preference/runechat_obj))
return
// Incapable of receiving
if((audible && is_deaf()) || (!audible && is_blind()))
return
// Check for virtual speakers (aka hearing a message through a radio)
if(existing_extra_classes.Find("radio"))
return
/* Not currently necessary
message = strip_html_properly(message)
if(!message)
return
*/
var/list/extra_classes = list()
extra_classes += existing_extra_classes
if(italics)
extra_classes |= "italics"
if(client.is_preference_enabled(/datum/client_preference/runechat_border))
extra_classes |= "black_outline"
var/dist = get_dist(src, speaker)
switch (dist)
if(4 to 5)
extra_classes |= "small"
if(5 to 16)
extra_classes |= "very_small"
// Display visual above source
new /datum/chatmessage(message, speaker, src, extra_classes)
// Tweak these defines to change the available color ranges
#define CM_COLOR_SAT_MIN 0.6
#define CM_COLOR_SAT_MAX 0.95
#define CM_COLOR_LUM_MIN 0.70
#define CM_COLOR_LUM_MAX 0.90
/**
* Gets a color for a name, will return the same color for a given string consistently within a round.atom
*
* Note that this proc aims to produce pastel-ish colors using the HSL colorspace. These seem to be favorable for displaying on the map.
*
* Arguments:
* * name - The name to generate a color for
* * sat_shift - A value between 0 and 1 that will be multiplied against the saturation
* * lum_shift - A value between 0 and 1 that will be multiplied against the luminescence
*/
/datum/chatmessage/proc/colorize_string(name, sat_shift = 1, lum_shift = 1)
// seed to help randomness
var/static/rseed = rand(1,26)
// get hsl using the selected 6 characters of the md5 hash
var/hash = copytext(md5(name + "[world_startup_time]"), rseed, rseed + 6)
var/h = hex2num(copytext(hash, 1, 3)) * (360 / 255)
var/s = (hex2num(copytext(hash, 3, 5)) >> 2) * ((CM_COLOR_SAT_MAX - CM_COLOR_SAT_MIN) / 63) + CM_COLOR_SAT_MIN
var/l = (hex2num(copytext(hash, 5, 7)) >> 2) * ((CM_COLOR_LUM_MAX - CM_COLOR_LUM_MIN) / 63) + CM_COLOR_LUM_MIN
// adjust for shifts
s *= clamp(sat_shift, 0, 1)
l *= clamp(lum_shift, 0, 1)
// convert to rgba
var/h_int = round(h/60) // mapping each section of H to 60 degree sections
var/c = (1 - abs(2 * l - 1)) * s
var/x = c * (1 - abs((h / 60) % 2 - 1))
var/m = l - c * 0.5
x = (x + m) * 255
c = (c + m) * 255
m *= 255
switch(h_int)
if(0)
return rgb(c,x,m)
if(1)
return rgb(x,c,m)
if(2)
return rgb(m,c,x)
if(3)
return rgb(m,x,c)
if(4)
return rgb(x,m,c)
if(5)
return rgb(c,m,x)
/atom/proc/runechat_message(message, range = world.view, italics, list/classes = list(), audible = TRUE)
var/list/hear = get_mobs_and_objs_in_view_fast(get_turf(src), range, remote_ghosts = FALSE)
var/list/hearing_mobs = hear["mobs"]
for(var/mob in hearing_mobs)
var/mob/M = mob
if(!M.client)
continue
M.create_chat_message(src, message, italics, classes, audible)

View File

@@ -34,6 +34,15 @@
// Track if we are already had initialize() called to prevent double-initialization.
var/initialized = FALSE
/// Last name used to calculate a color for the chatmessage overlays
var/chat_color_name
/// Last color calculated for the the chatmessage overlays
var/chat_color
/// A luminescence-shifted value of the last color calculated for chatmessage overlays
var/chat_color_darkened
/// The chat color var, without alpha.
var/chat_color_hover
/atom/New(loc, ...)
// Don't call ..() unless /datum/New() ever exists
@@ -490,7 +499,7 @@
// Use for objects performing visible actions
// message is output to anyone who can see, e.g. "The [src] does something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
/atom/proc/visible_message(var/message, var/blind_message, var/list/exclude_mobs, var/range = world.view)
/atom/proc/visible_message(var/message, var/blind_message, var/list/exclude_mobs, var/range = world.view, var/runemessage = "<span style='font-size: 1.5em'>👁</span>")
//VOREStation Edit
var/list/see
@@ -513,6 +522,8 @@
var/mob/M = mob
if(M.see_invisible >= invisibility && MOB_CAN_SEE_PLANE(M, plane))
M.show_message(message, VISIBLE_MESSAGE, blind_message, AUDIBLE_MESSAGE)
if(runemessage != -1)
M.create_chat_message(src, "[runemessage]", FALSE, list("emote"), audible = FALSE)
else if(blind_message)
M.show_message(blind_message, AUDIBLE_MESSAGE)
@@ -521,7 +532,7 @@
// message is the message output to anyone who can hear.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance, var/radio_message)
/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance, var/radio_message, var/runemessage)
var/range = hearing_distance || world.view
var/list/hear = get_mobs_and_objs_in_view_fast(get_turf(src),range,remote_ghosts = FALSE)
@@ -542,6 +553,8 @@
var/mob/M = mob
var/msg = message
M.show_message(msg, AUDIBLE_MESSAGE, deaf_message, VISIBLE_MESSAGE)
if(runemessage != -1)
M.create_chat_message(src, "[runemessage || message]", FALSE, list("emote"))
/atom/movable/proc/dropInto(var/atom/destination)
while(istype(destination))

View File

@@ -191,7 +191,7 @@
update_use_power(USE_POWER_ACTIVE)
regulating_temperature = 1
audible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
"You hear a click and a faint electronic hum.")
"You hear a click and a faint electronic hum.", runemessage = "* click *")
playsound(src, 'sound/machines/click.ogg', 50, 1)
else
//check for when we should stop adjusting temperature
@@ -199,7 +199,7 @@
update_use_power(USE_POWER_IDLE)
regulating_temperature = 0
audible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
"You hear a click as a faint electronic humming stops.")
"You hear a click as a faint electronic humming stops.", runemessage = "* click *")
playsound(src, 'sound/machines/click.ogg', 50, 1)
if(regulating_temperature)

View File

@@ -206,7 +206,7 @@
else if((occupant.health >= heal_level || occupant.health == occupant.getMaxHealth()) && (!eject_wait))
playsound(src, 'sound/machines/medbayscanner1.ogg', 50, 1)
audible_message("\The [src] signals that the cloning process is complete.")
audible_message("\The [src] signals that the cloning process is complete.", runemessage = "* ding *")
connected_message("Cloning Process Complete.")
locked = 0
go_out()

View File

@@ -519,9 +519,9 @@
if(electronics)
sleep(10)
if(oldfuel > fuel && oldfood > food)
src.audible_message("\The [src] lets out a somehow reassuring chime.")
src.audible_message("\The [src] lets out a somehow reassuring chime.", runemessage = "* reassuring chime *")
else if(oldfuel < fuel || oldfood < food)
src.audible_message("\The [src] lets out a somehow ominous chime.")
src.audible_message("\The [src] lets out a somehow ominous chime.", runemessage = "* ominous chime *")
food = oldfood
fuel = oldfuel

View File

@@ -277,7 +277,8 @@ when portals are shortly lived, or when portals are made to be obvious with spec
for(var/thing in mobs_to_relay)
var/mob/mob = thing
var/message = mob.combine_message(message_pieces, verb, M)
var/list/combined = mob.combine_message(message_pieces, verb, M)
var/message = combined["formatted"]
var/name_used = M.GetVoice()
var/rendered = null
rendered = "<span class='game say'><span class='name'>[name_used]</span> [message]</span>"

View File

@@ -246,7 +246,8 @@
//VOREStation Edit End
for(var/mob/mob in mobs_to_relay)
var/message = mob.combine_message(message_pieces, verb, M)
var/list/combined = mob.combine_message(message_pieces, verb, M)
var/message = combined["formatted"]
var/name_used = M.GetVoice()
var/rendered = null
rendered = "<span class='game say'>[bicon(src)] <span class='name'>[name_used]</span> [message]</span>"

View File

@@ -460,7 +460,7 @@
return
playsound(src, 'sound/machines/defib_charge.ogg', 50, 0)
audible_message("<span class='warning'>\The [src] lets out a steadily rising hum...</span>")
audible_message("<span class='warning'>\The [src] lets out a steadily rising hum...</span>", runemessage = "* whines *")
if(!do_after(user, chargetime, H))
return
@@ -527,7 +527,7 @@
H.setBrainLoss(brain_damage)
/obj/item/weapon/shockpaddles/proc/make_announcement(var/message, var/msg_class)
audible_message("<b>\The [src]</b> [message]", "\The [src] vibrates slightly.")
audible_message("<b>\The [src]</b> [message]", "\The [src] vibrates slightly.", runemessage = "* buzz *")
/obj/item/weapon/shockpaddles/emag_act(mob/user)
if(safety)

View File

@@ -31,12 +31,13 @@
/obj/item/device/megaphone/proc/do_broadcast(var/mob/living/user, var/message)
if(emagged)
if(insults)
user.audible_message("<B>[user.GetVoice()]</B>[user.GetAltName()] broadcasts, <FONT size=3>\"[pick(insultmsg)]\"</FONT>")
var/insult = pick(insultmsg)
user.audible_message("<B>[user.GetVoice()]</B>[user.GetAltName()] broadcasts, <FONT size=3>\"[insult]\"</FONT>", runemessage = insult)
insults--
else
to_chat(user, "<span class='warning'>*BZZZZzzzzzt*</span>")
else
user.audible_message("<B>[user.GetVoice()]</B>[user.GetAltName()] broadcasts, <FONT size=3>\"[message]\"</FONT>")
user.audible_message("<B>[user.GetVoice()]</B>[user.GetAltName()] broadcasts, <FONT size=3>\"[message]\"</FONT>", runemessage = message)
/obj/item/device/megaphone/attack_self(var/mob/living/user)
var/message = sanitize(input(user, "Shout a message?", "Megaphone", null) as text)
@@ -131,7 +132,8 @@
/obj/item/device/megaphone/super/do_broadcast(var/mob/living/user, var/message)
if(emagged)
if(insults)
user.audible_message("<B>[user.GetVoice()]</B>[user.GetAltName()] broadcasts, <FONT size=[broadcast_size] face='[broadcast_font]' color='[broadcast_color]'>\"[pick(insultmsg)]\"</FONT>")
var/insult = pick(insultmsg)
user.audible_message("<B>[user.GetVoice()]</B>[user.GetAltName()] broadcasts, <FONT size=[broadcast_size] face='[broadcast_font]' color='[broadcast_color]'>\"[insult]\"</FONT>", runemessage = insult)
if(broadcast_size >= 11)
var/turf/T = get_turf(user)
playsound(src, 'sound/items/AirHorn.ogg', 100, 1)
@@ -160,4 +162,4 @@
qdel(src)
return
else
user.audible_message("<B>[user.GetVoice()]</B>[user.GetAltName()] broadcasts, <FONT size=[broadcast_size] face='[broadcast_font]' color='[broadcast_color]'>\"[message]\"</FONT>")
user.audible_message("<B>[user.GetVoice()]</B>[user.GetAltName()] broadcasts, <FONT size=[broadcast_size] face='[broadcast_font]' color='[broadcast_color]'>\"[message]\"</FONT>", runemessage = message)

View File

@@ -258,13 +258,13 @@
var/playedmessage = mytape.storedinfo[i]
if (findtextEx(playedmessage,"*",1,2)) //remove marker for action sounds
playedmessage = copytext(playedmessage,2)
T.audible_message("<font color=Maroon><B>Tape Recorder</B>: [playedmessage]</font>")
T.audible_message("<font color=Maroon><B>Tape Recorder</B>: [playedmessage]</font>", runemessage = playedmessage)
if(mytape.storedinfo.len < i+1)
playsleepseconds = 1
sleep(10)
T = get_turf(src)
T.audible_message("<font color=Maroon><B>Tape Recorder</B>: End of recording.</font>")
T.audible_message("<font color=Maroon><B>Tape Recorder</B>: End of recording.</font>", runemessage = "* click *")
break
else
playsleepseconds = mytape.timestamp[i+1] - mytape.timestamp[i]
@@ -272,7 +272,7 @@
if(playsleepseconds > 14)
sleep(10)
T = get_turf(src)
T.audible_message("<font color=Maroon><B>Tape Recorder</B>: Skipping [playsleepseconds] seconds of silence</font>")
T.audible_message("<font color=Maroon><B>Tape Recorder</B>: Skipping [playsleepseconds] seconds of silence</font>", runemessage = "* tape winding *")
playsleepseconds = 1
sleep(10 * playsleepseconds)
@@ -282,7 +282,7 @@
if(emagged)
var/turf/T = get_turf(src)
T.audible_message("<font color=Maroon><B>Tape Recorder</B>: This tape recorder will self-destruct in... Five.</font>")
T.audible_message("<font color=Maroon><B>Tape Recorder</B>: This tape recorder will self-destruct in... Five.</font>", runemessage = "* beep beep *")
sleep(10)
T = get_turf(src)
T.audible_message("<font color=Maroon><B>Tape Recorder</B>: Four.</font>")

View File

@@ -24,5 +24,6 @@
var/message = sanitize(input(user,"Choose a message to relay to those around you.") as text|null)
if(message)
var/obj/item/device/text_to_speech/O = src
audible_message("[bicon(O)] \The [O.name] states, \"[message]\"")
audible_message("[bicon(src)] \The [src.name] states, \"[message]\"", runemessage = "* synthesized speech *")
if(ismob(loc))
loc.audible_message("", runemessage = "\[TTS Voice\] [message]")

View File

@@ -33,12 +33,12 @@
if(isnull(insults))
playsound(src, 'sound/voice/halt.ogg', 100, 1, vary = 0)
user.audible_message("<span class='warning'>[user]'s [name] rasps, \"[use_message]\"</span>", "<span class='warning'>\The [user] holds up \the [name].</span>")
user.audible_message("<span class='warning'>[user]'s [name] rasps, \"[use_message]\"</span>", "<span class='warning'>\The [user] holds up \the [name].</span>", runemessage = "\[TTS Voice\] [use_message]")
else
if(insults > 0)
playsound(src, 'sound/voice/binsult.ogg', 100, 1, vary = 0)
// Yes, it used to show the transcription of the sound clip. That was a) inaccurate b) immature as shit.
user.audible_message("<span class='warning'>[user]'s [name] gurgles something indecipherable and deeply offensive.</span>", "<span class='warning'>\The [user] holds up \the [name].</span>")
user.audible_message("<span class='warning'>[user]'s [name] gurgles something indecipherable and deeply offensive.</span>", "<span class='warning'>\The [user] holds up \the [name].</span>", runemessage = "\[TTS Voice\] #&@&^%(*")
insults--
else
to_chat(user, "<span class='danger'>*BZZZZZZZZT*</span>")

View File

@@ -305,7 +305,8 @@
for(var/wr_master in masters)
var/weakref/wr = wr_master
var/mob/master = wr.resolve()
var/message = master.combine_message(message_pieces, verb, M)
var/list/combined = master.combine_message(message_pieces, verb, M)
var/message = combined["formatted"]
var/rendered = "<i><span class='game say'>UAV received: <span class='name'>[name_used]</span> [message]</span></i>"
master.show_message(rendered, 2)

View File

@@ -1,5 +1,6 @@
#define RECOMMENDED_VERSION 501
/world/New()
world_startup_time = world.timeofday
to_world_log("Map Loading Complete")
//logs
//VOREStation Edit Start

View File

@@ -324,8 +324,7 @@
var/message = sanitize(input("What do you want the message to be?", "Make Sound") as text|null)
if(!message)
return
for (var/mob/V in hearers(O))
V.show_message(message, 2)
O.audible_message(message)
log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z]. make a sound")
message_admins("<font color='blue'>[key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z]. make a sound.</font>", 1)
feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!

View File

@@ -104,7 +104,7 @@
sleep(1 SECOND)
shadekin.dir = SOUTH
sleep(1 SECOND)
shadekin.audible_message("<b>[shadekin]</b> belches loudly!")
shadekin.audible_message("<b>[shadekin]</b> belches loudly!", runemessage = "* URRRRRP *")
sleep(2 SECONDS)
shadekin.phase_shift()
target.transforming = FALSE //Undo cheap hack

View File

@@ -77,3 +77,6 @@
var/connection_realtime
///world.timeofday they connected
var/connection_timeofday
// Runechat messages
var/list/seen_messages

View File

@@ -291,6 +291,32 @@ var/list/_client_preferences_by_type
enabled_description = "Show"
disabled_description = "Hide"
/datum/client_preference/runechat_mob
description = "Runechat (Mobs)"
key = "RUNECHAT_MOB"
enabled_description = "Show"
disabled_description = "Hide"
/datum/client_preference/runechat_obj
description = "Runechat (Objs)"
key = "RUNECHAT_OBJ"
enabled_description = "Show"
disabled_description = "Hide"
/datum/client_preference/runechat_border
description = "Runechat Message Border"
key = "RUNECHAT_BORDER"
enabled_description = "Show"
disabled_description = "Hide"
enabled_by_default = FALSE
/datum/client_preference/runechat_long_messages
description = "Runechat Message Length"
key = "RUNECHAT_LONG"
enabled_description = "ERP KING"
disabled_description = "Normie"
enabled_by_default = FALSE
/datum/client_preference/status_indicators/toggled(mob/preference_mob, enabled)
. = ..()
if(preference_mob && preference_mob.plane_holder)

View File

@@ -144,7 +144,7 @@
if(usr.stat) return
if(!jingled)
usr.audible_message("[usr] jingles the [src]'s bell.")
usr.audible_message("[usr] jingles the [src]'s bell.", runemessage = "* jingle *")
playsound(src, 'sound/items/pickup/ring.ogg', 50, 1)
jingled = 1
addtimer(CALLBACK(src, .proc/jingledreset), 50)

View File

@@ -103,11 +103,14 @@ var/global/list/emotes_by_key
if(target)
use_1p = replace_target_tokens(use_1p, target)
use_1p = "<span class='emote'>[capitalize(replace_user_tokens(use_1p, user))]</span>"
var/use_3p = get_emote_message_3p(user, target, extra_params)
if(use_3p)
var/prefinal_3p
var/use_3p
var/raw_3p = get_emote_message_3p(user, target, extra_params)
if(raw_3p)
if(target)
use_3p = replace_target_tokens(use_3p, target)
use_3p = "<span class='emote'><b>\The [user]</b> [replace_user_tokens(use_3p, user)]</span>"
raw_3p = replace_target_tokens(raw_3p, target)
prefinal_3p = replace_user_tokens(raw_3p, user)
use_3p = "<span class='emote'><b>\The [user]</b> [prefinal_3p]</span>"
var/use_radio = get_radio_message(user)
if(use_radio)
if(target)
@@ -124,12 +127,12 @@ var/global/list/emotes_by_key
if(isliving(user))
var/mob/living/L = user
if(L.silent)
M.visible_message(message = "[user] opens their mouth silently!", self_message = "You cannot say anything!", blind_message = emote_message_impaired)
M.visible_message(message = "[user] opens their mouth silently!", self_message = "You cannot say anything!", blind_message = emote_message_impaired, runemessage = "opens their mouth silently!")
return
else
M.audible_message(message = use_3p, self_message = use_1p, deaf_message = emote_message_impaired, hearing_distance = use_range, radio_message = use_radio)
M.audible_message(message = use_3p, self_message = use_1p, deaf_message = emote_message_impaired, hearing_distance = use_range, radio_message = use_radio, runemessage = prefinal_3p)
else
M.visible_message(message = use_3p, self_message = use_1p, blind_message = emote_message_impaired, range = use_range)
M.visible_message(message = use_3p, self_message = use_1p, blind_message = emote_message_impaired, range = use_range, runemessage = prefinal_3p)
do_extra(user, target)
do_sound(user)

View File

@@ -86,7 +86,8 @@
return
if(use_emote.message_type == AUDIBLE_MESSAGE && is_muzzled())
audible_message("<b>\The [src]</b> [use_emote.emote_message_muffled || "makes a muffled sound."]")
var/muffle_message = use_emote.emote_message_muffled || "makes a muffled sound."
audible_message("<b>\The [src]</b> [muffle_message]", runemessage = "* [muffle_message] *")
return
next_emote = world.time + use_emote.emote_delay
@@ -149,7 +150,7 @@
subtext = html_encode(subtext)
// Store the player's name in a nice bold, naturalement
nametext = "<B>[emoter]</B>"
return pretext + nametext + subtext
return list("pretext" = pretext, "nametext" = nametext, "subtext" = subtext)
/mob/proc/custom_emote(var/m_type = VISIBLE_MESSAGE, var/message, var/range = world.view)
@@ -163,8 +164,14 @@
else
input = message
var/list/formatted
var/runemessage
if(input)
message = format_emote(src, message)
formatted = format_emote(src, message)
message = formatted["pretext"] + formatted["nametext"] + formatted["subtext"]
runemessage = formatted["subtext"]
// This is just personal preference (but I'm objectively right) that custom emotes shouldn't have periods at the end in runechat
runemessage = replacetext(runemessage,".","",length(runemessage),length(runemessage)+1)
else
return
@@ -192,6 +199,7 @@
if(isobserver(M))
message = "<span class='emote'><B>[src]</B> ([ghost_follow_link(src, M)]) [input]</span>"
M.show_message(message, m_type)
M.create_chat_message(src, "[runemessage]", FALSE, list("emote"), (m_type == AUDIBLE_MESSAGE))
for(var/obj in o_viewers)
var/obj/O = obj

View File

@@ -138,7 +138,7 @@
text = get_pin_data(IC_INPUT, 1)
if(!isnull(text))
var/obj/O = assembly ? loc : assembly
audible_message("[bicon(O)] \The [O.name] states, \"[text]\"")
audible_message("[bicon(O)] \The [O.name] states, \"[text]\"", runemessage = text)
/obj/item/integrated_circuit/output/text_to_speech/advanced
name = "advanced text-to-speech circuit"

View File

@@ -2,7 +2,9 @@
/mob/proc/combine_message(var/list/message_pieces, var/verb, var/mob/speaker, always_stars = FALSE, var/radio = FALSE)
var/iteration_count = 0
var/msg = "" // This is to make sure that the pieces have actually added something
. = "[verb], \""
var/raw_msg = ""
. = list("formatted" = "[verb], \"", "raw" = "")
for(var/datum/multilingual_say_piece/SP in message_pieces)
iteration_count++
var/piece = SP.message
@@ -27,6 +29,9 @@
if(istype(S.say_list) && length(S.say_list.speak))
piece = pick(S.say_list.speak)
raw_msg += (piece + " ")
//HTML formatting
if(!SP.speaking) // Catch the most generic case first
piece = "<span class='message body'>[piece]</span>"
else if(radio) // SP.speaking == TRUE enforced by previous !SP.speaking
@@ -38,10 +43,11 @@
if(msg == "")
// There is literally no content left in this message, we need to shut this shit down
. = "" // hear_say will suppress it
.["formatted"] = "" // hear_say will suppress it
else
. = trim(. + trim(msg))
. += "\""
.["formatted"] = trim(.["formatted"] + trim(msg))
.["formatted"] += "\""
.["raw"] = trim(raw_msg)
/mob/proc/saypiece_scramble(datum/multilingual_say_piece/SP)
if(SP.speaking)
@@ -76,7 +82,8 @@
var/mob/living/carbon/human/H = speaker
speaker_name = H.GetVoice()
var/message = combine_message(message_pieces, verb, speaker)
var/list/combined = combine_message(message_pieces, verb, speaker)
var/message = combined["formatted"]
if(message == "")
return
@@ -109,6 +116,7 @@
message_to_send = "<font size='3'><b>[message_to_send]</b></font>"
on_hear_say(message_to_send)
create_chat_message(speaker, combined["raw"], italics, list())
if(speech_sound && (get_dist(speaker, src) <= world.view && z == speaker.z))
var/turf/source = speaker ? get_turf(speaker) : get_turf(src)
@@ -164,7 +172,8 @@
if(!client)
return
var/message = combine_message(message_pieces, verb, speaker, always_stars = hard_to_hear, radio = TRUE)
var/list/combined = combine_message(message_pieces, verb, speaker, always_stars = hard_to_hear, radio = TRUE)
var/message = combined["formatted"]
if(sleeping || stat == UNCONSCIOUS) //If unconscious or sleeping
hear_sleep(multilingual_to_message(message_pieces))
return
@@ -272,7 +281,8 @@
return
/mob/proc/hear_holopad_talk(list/message_pieces, var/verb = "says", var/mob/speaker = null)
var/message = combine_message(message_pieces, verb, speaker)
var/list/combined = combine_message(message_pieces, verb, speaker)
var/message = combined["formatted"]
var/name = speaker.name
if(!say_understands(speaker))

View File

@@ -38,20 +38,26 @@ var/list/department_radio_keys = list(
":Y" = "Explorer", ".Y" = "Explorer",
":A" = "Talon", ".A" = "Talon", //VOREStation Add,
//kinda localization -- rastaf0
//same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding.
":<EFBFBD>" = "right ear", ".<EFBFBD>" = "right ear",
":<EFBFBD>" = "left ear", ".<EFBFBD>" = "left ear",
":<EFBFBD>" = "intercom", ".<EFBFBD>" = "intercom",
":<EFBFBD>" = "department", ".<EFBFBD>" = "department",
":<EFBFBD>" = "Command", ".<EFBFBD>" = "Command",
":<EFBFBD>" = "Science", ".<EFBFBD>" = "Science",
":<EFBFBD>" = "Medical", ".<EFBFBD>" = "Medical",
":<EFBFBD>" = "Engineering", ".<EFBFBD>" = "Engineering",
":<EFBFBD>" = "Security", ".<EFBFBD>" = "Security",
":<EFBFBD>" = "whisper", ".<EFBFBD>" = "whisper",
":<EFBFBD>" = "Mercenary", ".<EFBFBD>" = "Mercenary",
":<EFBFBD>" = "Supply", ".<EFBFBD>" = "Supply",
// Cyrillic characters on the same keys on the Russian QWERTY (phonetic) layout
":к" = "right ear", ".к" = "right ear",
":д" = "left ear", ".д" = "left ear",
":ш" = "intercom", ".ш" = "intercom",
":р" = "department", ".р" = "department",
":+" = "special", ".+" = "special", //activate radio-specific special functions
":с" = "Command", ".с" = "Command",
":т" = "Science", ".т" = "Science",
":ь" = "Medical", ".ь" = "Medical",
":у" = "Engineering", ".у" = "Engineering",
":л" = "Response Team", ".л" = "Response Team",
":ы" = "Security", ".ы" = "Security",
":ц" = "whisper", ".ц" = "whisper",
":е" = "Mercenary", ".е" = "Mercenary",
":ч" = "Raider", ".ч" = "Raider",
":г" = "Supply", ".г" = "Supply",
":м" = "Service", ".м" = "Service",
":з" = "AI Private", ".з" = "AI Private",
":н" = "Explorer", ".н" = "Explorer",
":ф" = "Talon", ".ф" = "Talon" //VOREStation Add
)
@@ -367,16 +373,17 @@ proc/get_radio_key_from_channel(var/channel)
//VOREStation Add End
var/dst = get_dist(get_turf(M),get_turf(src))
var/runechat_enabled = M.client?.is_preference_enabled(/datum/client_preference/runechat_mob)
if(dst <= message_range || (M.stat == DEAD && !forbid_seeing_deadchat)) //Inside normal message range, or dead with ears (handled in the view proc)
if(M.client)
if(M.client && !runechat_enabled)
var/image/I1 = listening[M] || speech_bubble
images_to_clients[I1] |= M.client
M << I1
M.hear_say(message_pieces, verb, italics, src, speech_sound, sound_vol)
if(whispering && !isobserver(M)) //Don't even bother with these unless whispering
if(dst > message_range && dst <= w_scramble_range) //Inside whisper scramble range
if(M.client)
if(M.client && !runechat_enabled)
var/image/I2 = listening[M] || speech_bubble
images_to_clients[I2] |= M.client
M << I2

View File

@@ -961,7 +961,8 @@ var/list/ai_verbs_default = list(
return track // Feed variable back to AI
/mob/living/silicon/ai/proc/relay_speech(mob/living/M, list/message_pieces, verb)
var/message = combine_message(message_pieces, verb, M)
var/list/combined = combine_message(message_pieces, verb, M)
var/message = combined["formatted"]
var/name_used = M.GetVoice()
//This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only.
var/rendered = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> [message]</span></i>"

View File

@@ -72,7 +72,8 @@
O.hear_talk(src, message_pieces, verb)
/*Radios "filter out" this conversation channel so we don't need to account for them.
This is another way of saying that we won't bother dealing with them.*/
to_chat(src, "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [combine_message(message_pieces, verb, src)]</span></i>")
var/list/combined = combine_message(message_pieces, verb, src)
to_chat(src, "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [combined["formatted"]]</span></i>")
else
to_chat(src, "No holopad connected.")
return 0

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,8 @@
var/obj/screen/shadekin/shadekin_display = null
var/obj/screen/xenochimera/danger_level/xenochimera_danger_display = null
var/size_multiplier = 1 //multiplier for the mob's icon size
/mob/drop_location()
if(temporary_form)
return temporary_form.drop_location()

View File

@@ -98,7 +98,7 @@
"You begin climbing [direction] \the [src]!",
"You hear the grunting and clanging of a metal ladder being used.")
target_ladder.audible_message("<span class='notice'>You hear something coming [direction] \the [src]</span>")
target_ladder.audible_message("<span class='notice'>You hear something coming [direction] \the [src]</span>", runemessage = "* clank clank *")
if(do_after(M, climb_time, src))
var/turf/T = get_turf(target_ladder)

View File

@@ -59,7 +59,7 @@
if(lattice)
var/pull_up_time = max(5 SECONDS + (src.movement_delay() * 10), 1)
to_chat(src, "<span class='notice'>You grab \the [lattice] and start pulling yourself upward...</span>")
destination.audible_message("<span class='notice'>You hear something climbing up \the [lattice].</span>")
destination.audible_message("<span class='notice'>You hear something climbing up \the [lattice].</span>", runemessage = "* clank clang *")
if(do_after(src, pull_up_time))
to_chat(src, "<span class='notice'>You pull yourself up.</span>")
else
@@ -74,7 +74,7 @@
if(!destination?.Enter(src, old_dest))
to_chat(src, "<span class='notice'>There's something in the way up above in that direction, try another.</span>")
return 0
destination.audible_message("<span class='notice'>You hear something climbing up \the [catwalk].</span>")
destination.audible_message("<span class='notice'>You hear something climbing up \the [catwalk].</span>", runemessage = "* clank clang *")
if(do_after(src, pull_up_time))
to_chat(src, "<span class='notice'>You pull yourself up.</span>")
else
@@ -90,8 +90,8 @@
return 0
var/fly_time = max(7 SECONDS + (H.movement_delay() * 10), 1) //So it's not too useful for combat. Could make this variable somehow, but that's down the road.
to_chat(src, "<span class='notice'>You begin to fly upwards...</span>")
destination.audible_message("<span class='notice'>You hear the flapping of wings.</span>")
H.audible_message("<span class='notice'>[H] begins to flap \his wings, preparing to move upwards!</span>")
destination.audible_message("<span class='notice'>You hear the flapping of wings.</span>", runemessage = "* flap flap *")
H.audible_message("<span class='notice'>[H] begins to flap \his wings, preparing to move upwards!</span>", runemessage = "* flap flap *")
if(do_after(H, fly_time) && H.flying)
to_chat(src, "<span class='notice'>You fly upwards.</span>")
else

View File

@@ -77,7 +77,8 @@
mobs_to_relay = in_range["mobs"]
for(var/mob/mob in mobs_to_relay)
var/message = mob.combine_message(message_pieces, verb, M)
var/list/combined = mob.combine_message(message_pieces, verb, M)
var/message = combined["formatted"]
var/name_used = M.GetVoice()
var/rendered = null
rendered = "<span class='game say'>[bicon(icon_object)] <span class='name'>[name_used]</span> [message]</span>"

View File

@@ -150,7 +150,7 @@
if(!is_on())
return 0
if(!check_fuel() || (use_power_oneoff(charge_per_burn) < charge_per_burn) || check_blockage())
audible_message(src,"<span class='warning'>[src] coughs once and goes silent!</span>")
audible_message(src,"<span class='warning'>[src] coughs once and goes silent!</span>", runemessage = "* sputtercough *")
update_use_power(USE_POWER_OFF)
return 0

View File

@@ -111,28 +111,28 @@
playsound(src, "sound/machines/copier.ogg", 100, 1)
sleep(11)
copy(copyitem)
audible_message("<span class='notice'>You can hear [src] whirring as it finishes printing.</span>")
audible_message("<span class='notice'>You can hear [src] whirring as it finishes printing.</span>", runemessage = "* whirr *")
playsound(src, "sound/machines/buzzbeep.ogg", 30)
else if (istype(copyitem, /obj/item/weapon/photo))
playsound(src, "sound/machines/copier.ogg", 100, 1)
sleep(11)
photocopy(copyitem)
audible_message("<span class='notice'>You can hear [src] whirring as it finishes printing.</span>")
audible_message("<span class='notice'>You can hear [src] whirring as it finishes printing.</span>", runemessage = "* whirr *")
playsound(src, "sound/machines/buzzbeep.ogg", 30)
else if (istype(copyitem, /obj/item/weapon/paper_bundle))
sleep(11)
playsound(src, "sound/machines/copier.ogg", 100, 1)
var/obj/item/weapon/paper_bundle/B = bundlecopy(copyitem)
sleep(11*B.pages.len)
audible_message("<span class='notice'>You can hear [src] whirring as it finishes printing.</span>")
audible_message("<span class='notice'>You can hear [src] whirring as it finishes printing.</span>", runemessage = "* whirr *")
playsound(src, "sound/machines/buzzbeep.ogg", 30)
else if (has_buckled_mobs()) // VOREStation EDIT: For ass-copying.
playsound(src, "sound/machines/copier.ogg", 100, 1)
audible_message("<span class='notice'>You can hear [src] whirring as it attempts to scan.</span>")
audible_message("<span class='notice'>You can hear [src] whirring as it attempts to scan.</span>", runemessage = "* whirr *")
sleep(rand(20,45)) // Sit with your bare ass on the copier for a random time, feel like a fool, get stared at.
copyass(user)
sleep(15)
audible_message("<span class='notice'>You can hear [src] whirring as it finishes printing.</span>")
audible_message("<span class='notice'>You can hear [src] whirring as it finishes printing.</span>", runemessage = "* whirr *")
playsound(src, "sound/machines/buzzbeep.ogg", 30)
else
to_chat(user, "<span class='warning'>\The [copyitem] can't be copied by [src].</span>")

View File

@@ -208,7 +208,7 @@
/obj/item/weapon/gun/magnetic/matfed/phoronbore/process()
if(generator_state && !mat_storage)
audible_message(SPAN_NOTICE("\The [src] goes quiet."),SPAN_NOTICE("A motor noise cuts out."))
audible_message(SPAN_NOTICE("\The [src] goes quiet."),SPAN_NOTICE("A motor noise cuts out."), runemessage = "* goes quiet *")
soundloop.stop()
generator_state = GEN_OFF
@@ -258,12 +258,12 @@
soundloop.start()
time_started = world.time
cell?.use(100)
audible_message(SPAN_NOTICE("\The [src] starts chugging."),SPAN_NOTICE("A motor noise starts up."))
audible_message(SPAN_NOTICE("\The [src] starts chugging."),SPAN_NOTICE("A motor noise starts up."), runemessage = "* whirr *")
generator_state = GEN_IDLE
else if(generator_state > GEN_OFF && time_started + 3 SECONDS < world.time)
soundloop.stop()
audible_message(SPAN_NOTICE("\The [src] goes quiet."),SPAN_NOTICE("A motor noise cuts out."))
audible_message(SPAN_NOTICE("\The [src] goes quiet."),SPAN_NOTICE("A motor noise cuts out."), runemessage = "* goes quiet *")
generator_state = GEN_OFF
/obj/item/weapon/gun/magnetic/matfed/phoronbore/loaded

View File

@@ -271,6 +271,7 @@
if(loaded) //Safety.
if(istype(loaded, /obj/item/weapon/fuel_assembly))
var/obj/item/weapon/fuel_assembly/rod = loaded
<<<<<<< HEAD
//CHOMPEdit Begin
switch(rod.fuel_type)
if("composite") //Safety check for rods spawned in without a fueltype.
@@ -287,6 +288,47 @@
spawn(5)
visible_message("<span class='danger'>\The [src] begins to rattle, its acceleration chamber collapsing in on itself!</span>")
removable_components = FALSE
||||||| parent of a5d4d7e601... Merge pull request #10479 from VOREStation/Arokha/runechat
if(rod.fuel_type == "composite" || rod.fuel_type == "deuterium") //Safety check for rods spawned in without a fueltype.
projectile_type = /obj/item/projectile/bullet/magnetic/fuelrod
else if(rod.fuel_type == "tritium")
projectile_type = /obj/item/projectile/bullet/magnetic/fuelrod/tritium
else if(rod.fuel_type == "phoron")
projectile_type = /obj/item/projectile/bullet/magnetic/fuelrod/phoron
else if(rod.fuel_type == "supermatter")
projectile_type = /obj/item/projectile/bullet/magnetic/fuelrod/supermatter
visible_message("<span class='danger'>The barrel of \the [src] glows a blinding white!</span>")
spawn(5)
visible_message("<span class='danger'>\The [src] begins to rattle, its acceleration chamber collapsing in on itself!</span>")
removable_components = FALSE
spawn(15)
audible_message("<span class='critical'>\The [src]'s power supply begins to overload as the device crumples!</span>") //Why are you still holding this?
playsound(src, 'sound/effects/grillehit.ogg', 10, 1)
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
var/turf/T = get_turf(src)
sparks.set_up(2, 1, T)
sparks.start()
=======
if(rod.fuel_type == "composite" || rod.fuel_type == "deuterium") //Safety check for rods spawned in without a fueltype.
projectile_type = /obj/item/projectile/bullet/magnetic/fuelrod
else if(rod.fuel_type == "tritium")
projectile_type = /obj/item/projectile/bullet/magnetic/fuelrod/tritium
else if(rod.fuel_type == "phoron")
projectile_type = /obj/item/projectile/bullet/magnetic/fuelrod/phoron
else if(rod.fuel_type == "supermatter")
projectile_type = /obj/item/projectile/bullet/magnetic/fuelrod/supermatter
visible_message("<span class='danger'>The barrel of \the [src] glows a blinding white!</span>")
spawn(5)
visible_message("<span class='danger'>\The [src] begins to rattle, its acceleration chamber collapsing in on itself!</span>")
removable_components = FALSE
spawn(15)
audible_message("<span class='critical'>\The [src]'s power supply begins to overload as the device crumples!</span>", runemessage = "* VWRRRRRRRR *") //Why are you still holding this?
playsound(src, 'sound/effects/grillehit.ogg', 10, 1)
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
var/turf/T = get_turf(src)
sparks.set_up(2, 1, T)
sparks.start()
>>>>>>> a5d4d7e601... Merge pull request #10479 from VOREStation/Arokha/runechat
spawn(15)
audible_message("<span class='critical'>\The [src]'s power supply begins to overload as the device crumples!</span>") //Why are you still holding this?
playsound(src, 'sound/effects/grillehit.ogg', 10, 1)

View File

@@ -130,12 +130,12 @@ var/global/list/obj/machinery/message_server/message_servers = list()
if(2)
if(!Console.silent)
playsound(Console, 'sound/machines/twobeep.ogg', 50, 1)
Console.audible_message(text("[bicon(Console)] *The Requests Console beeps: 'PRIORITY Alert in [sender]'"),,5)
Console.audible_message(text("[bicon(Console)] *The Requests Console beeps: 'PRIORITY Alert in [sender]'"),,5, runemessage = "* beep! beep! *")
Console.message_log += list(list("High Priority message from [sender]", "[authmsg]"))
else
if(!Console.silent)
playsound(Console, 'sound/machines/twobeep.ogg', 50, 1)
Console.audible_message(text("[bicon(Console)] *The Requests Console beeps: 'Message from [sender]'"),,4)
Console.audible_message(text("[bicon(Console)] *The Requests Console beeps: 'Message from [sender]'"),,4, runemessage = "* beep beep *")
Console.message_log += list(list("Message from [sender]", "[authmsg]"))
Console.set_light(2)

View File

@@ -154,7 +154,7 @@
else if(((occupant.health == occupant.maxHealth)) && (!eject_wait))
playsound(src, 'sound/machines/ding.ogg', 50, 1)
audible_message("\The [src] signals that the growing process is complete.")
audible_message("\The [src] signals that the growing process is complete.", runemessage = "* ding *")
connected_message("Growing Process Complete.")
locked = 0
go_out()

View File

@@ -119,7 +119,7 @@
continue
if(!H.shuttle_comp || !(get_area(H) in shuttle_area))
H.shuttle_comp = null
H.audible_message("<span class='warning'>\The [H] pings as it loses it's connection with the ship.</span>")
H.audible_message("<span class='warning'>\The [H] pings as it loses it's connection with the ship.</span>", runemessage = "* ping *")
H.update_hud("discon")
helmets -= H
else

View File

@@ -28,7 +28,7 @@
priority_mode = TRUE
cancel_pending_floors()
update_ext_panel_icons()
control_panel_interior.audible_message("<span class='info'>This turbolift is responding to a priority call. Please exit the lift when it stops and make way.</span>")
control_panel_interior.audible_message("<span class='info'>This turbolift is responding to a priority call. Please exit the lift when it stops and make way.</span>", runemessage = "* BUZZ *")
spawn(time)
priority_mode = FALSE
update_ext_panel_icons()
@@ -158,7 +158,7 @@
doors_closing = 0
if(!fire_mode)
open_doors()
control_panel_interior.audible_message("\The [current_floor.ext_panel] buzzes loudly.")
control_panel_interior.audible_message("\The [current_floor.ext_panel] buzzes loudly.", runemessage = "* BUZZ *")
playsound(control_panel_interior, "sound/machines/buzz-two.ogg", 50, 1)
return 0

View File

@@ -130,10 +130,10 @@
return
lift.update_fire_mode(!lift.fire_mode)
if(lift.fire_mode)
audible_message("<span class='danger'>Firefighter Mode Activated. Door safeties disabled. Manual control engaged.</span>")
audible_message("<span class='danger'>Firefighter Mode Activated. Door safeties disabled. Manual control engaged.</span>", runemessage = "* SCREECH *")
playsound(src, 'sound/machines/airalarm.ogg', 25, 0, 4, volume_channel = VOLUME_CHANNEL_ALARMS)
else
audible_message("<span class='warning'>Firefighter Mode Deactivated. Door safeties enabled. Automatic control engaged.</span>")
audible_message("<span class='warning'>Firefighter Mode Deactivated. Door safeties enabled. Automatic control engaged.</span>", runemessage = "* ding *")
return
. = ..()

View File

@@ -40,7 +40,7 @@
if(!moved) // nowhere to go....
LM.gib()
else // the mob is too big to just move, so we need to give up what we're doing
audible_message("\The [src]'s motors grind as they quickly reverse direction, unable to safely close.")
audible_message("\The [src]'s motors grind as they quickly reverse direction, unable to safely close.", runemessage = "* WRRRRR *")
cur_command = null // the door will just keep trying otherwise
return 0
return ..()

View File

@@ -42,7 +42,16 @@
user.client.eye = target_move //if we don't do this, Byond only updates the eye every tick - required for smooth movement
if(world.time > user.next_play_vent)
user.next_play_vent = world.time+30
playsound(src, 'sound/machines/ventcrawl.ogg', 50, 1, -3)
var/turf/T = get_turf(src)
playsound(T, 'sound/machines/ventcrawl.ogg', 50, 1, -3)
var/message = pick(
prob(90);"* clunk *",
prob(90);"* thud *",
prob(90);"* clatter *",
prob(1);"* <span style='font-size:2em'>ඞ</span> *"
)
T.runechat_message(message)
else
if((direction & initialize_directions) || is_type_in_list(src, ventcrawl_machinery) && src.can_crawl_through()) //if we move in a way the pipe can connect, but doesn't - or we're in a vent
user.remove_ventcrawl()

View File

@@ -554,7 +554,7 @@
//He's dead, jim
if((state == 1) && owner && (owner.stat == DEAD))
update_state(2)
audible_message("<span class='warning'>The [name] begins flashing red.</span>")
visible_message("<span class='warning'>The [name] begins flashing red.</span>")
sleep(30)
visible_message("<span class='warning'>The [name] shatters into dust!</span>")
if(owner_c)

View File

@@ -1,7 +1,6 @@
// Adding needed defines to /mob/living
// Note: Polaris had this on /mob/living/carbon/human We need it higher up for animals and stuff.
/mob/living
var/size_multiplier = 1 //multiplier for the mob's icon size
var/holder_default
var/step_mechanics_pref = TRUE // Allow participation in macro-micro step mechanics
var/pickup_pref = TRUE // Allow participation in macro-micro pickup mechanics

View File

@@ -1282,7 +1282,7 @@ window "mapwindow"
saved-params = "icon-size"
on-show = ".winset\"mainwindow.mainvsplit.left=mapwindow\""
on-hide = ".winset\"mainwindow.mainvsplit.left=\""
style=".center { text-align: center; } .maptext { font-family: 'Small Fonts'; font-size: 7px; -dm-text-outline: 1px black; color: white; line-height: 1.1; } .small { font-size: 6px; } .big { font-size: 8px; } .reallybig { font-size: 8px; } .extremelybig { font-size: 8px; } .clown { color: #FF69Bf;} .tajaran {color: #803B56;} .skrell {color: #00CED1;} .solcom {color: #22228B;} .com_srus {color: #7c4848;} .zombie {color: #ff0000;} .soghun {color: #228B22;} .vox {color: #AA00AA;} .diona {color: #804000; font-weight: bold;} .trinary {color: #727272;} .kidan {color: #664205;} .slime {color: #0077AA;} .drask {color: #a3d4eb;} .vulpkanin {color: #B97A57;} .abductor {color: #800080; font-style: italic;} .his_grace { color: #15D512; } .hypnophrase { color: #0d0d0d; font-weight: bold; } .yell { font-weight: bold; }"
style=".center { text-align: center; } .runechatdiv {background-color: #20202070} .black_outline { -dm-text-outline: 1px black } .boldtext { font-weight: bold; } .maptext { font-family: 'Small Fonts'; font-size: 7px; color: white; line-height: 1.1; } .command_headset { font-weight: bold; font-size: 8px; } .small { font-size: 6px; } .very_small { font-size: 5px;} .big { font-size: 8px; } .reallybig { font-size: 8px; } .extremelybig { font-size: 8px; } .greentext { color: #00FF00; font-size: 7px; } .redtext { color: #FF0000; font-size: 7px; } .clown { color: #FF69Bf; font-size: 7px; font-weight: bold; } .his_grace { color: #15D512; } .hypnophrase { color: #0d0d0d; font-weight: bold; } .yell { font-weight: bold; } .italics { font-size: 7px; font-style: italic; }"
window "outputwindow"
elem "outputwindow"

View File

@@ -325,6 +325,7 @@
#include "code\datums\browser.dm"
#include "code\datums\callback.dm"
#include "code\datums\category.dm"
#include "code\datums\chat_message.dm"
#include "code\datums\computerfiles.dm"
#include "code\datums\datacore.dm"
#include "code\datums\datum.dm"