Ports Goonchat from Baystation. (#9635)

changes:

    rscadd: "Ported a new chat system, Goonchat, that allows for cool things like changing font style, size, spacing, highlighting up to 5 strings in the chat, and DARK MODE."
    rscadd: "Repeated chat messages can now get compacted. You can disable this in goonchat settings."
    rscadd: "You can change icon style to any font on your system."
    tweak: "The game window has been altered a bit to adjust for this."
    rscdel: "Removed skin style prefs as they are no longer used."
This commit is contained in:
Matt Atlas
2020-09-24 23:06:04 +03:00
committed by GitHub
parent a7401aeb1d
commit d4666caaac
277 changed files with 4057 additions and 2955 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
* Pretty much pokes the MC to make sure it's still alive.
**/
#define FAILSAFE_MSG(msg) admin_notice("<big><em><font color='red'>FAILSAFE: </font><font color='black'>[msg]</font></em></big>", R_DEBUG|R_ADMIN|R_DEV)
#define FAILSAFE_MSG(msg) admin_notice("<big><em><span class='warning'>FAILSAFE: </span><font color='black'>[msg]</font></em></big>", R_DEBUG|R_ADMIN|R_DEV)
var/datum/controller/failsafe/Failsafe
+83
View File
@@ -0,0 +1,83 @@
var/datum/controller/subsystem/chat/SSchat
/datum/controller/subsystem/chat
name = "Chat"
wait = 1
flags = SS_FIRE_IN_LOBBY
priority = SS_PRIORITY_CHAT
init_order = SS_INIT_CHAT
var/list/payload = list()
/datum/controller/subsystem/chat/Initialize()
NEW_SS_GLOBAL(SSchat)
/datum/controller/subsystem/chat/fire()
for(var/i in payload)
var/client/C = i
to_target(C, output(payload[C], "browseroutput:output"))
payload -= C
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/chat/proc/queue(target, message, handle_whitespace = TRUE, trailing_newline = TRUE)
if(!target || !message)
return
if(!istext(message))
CRASH("to_chat called with invalid input type")
if(target == world)
target = clients
//Some macros remain in the string even after parsing and fuck up the eventual output
var/original_message = message
message = replacetext(message, "\improper", "")
message = replacetext(message, "\proper", "")
if(handle_whitespace)
message = replacetext(message, "\n", "<br>")
message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]")
if (trailing_newline)
message += "<br>"
//url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript.
//Do the double-encoding here to save nanoseconds
var/twiceEncoded = url_encode(url_encode(message))
if(islist(target))
for(var/I in target)
var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible
if(!C)
return
//Send it to the old style output window.
legacy_chat(C, original_message)
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
continue
if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue
C.chatOutput.messageQueue += message
continue
payload[C] += twiceEncoded
else
var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible
if(!C)
return
//Send it to the old style output window.
legacy_chat(C, original_message)
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
return
if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue
C.chatOutput.messageQueue += message
return
payload[C] += twiceEncoded
@@ -189,7 +189,6 @@
SearchVar(debugobj)
SearchVar(mods)
SearchVar(gravity_is_on)
SearchVar(server_greeting)
SearchVar(awaydestinations)
SearchVar(fileaccess_timer)
SearchVar(custom_event_msg)
+32
View File
@@ -0,0 +1,32 @@
/datum/controller/subsystem/ping
name = "Ping"
priority = SS_PRIORITY_PING
wait = 3 SECONDS
flags = SS_NO_INIT | SS_FIRE_IN_LOBBY
var/list/currentrun = list()
/datum/controller/subsystem/ping/stat_entry()
..("P:[clients.len]")
/datum/controller/subsystem/ping/fire(resumed = 0)
if (!resumed)
src.currentrun = clients.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while (currentrun.len)
var/client/C = currentrun[currentrun.len]
currentrun.len--
if (!C || !C.chatOutput || !C.chatOutput.loaded)
if (MC_TICK_CHECK)
return
continue
// softPang isn't handled anywhere but it'll always reset the opts.lastPang.
C.chatOutput.ehjax_send(data = C.is_afk(29) ? "softPang" : "pang")
if (MC_TICK_CHECK)
return
-39
View File
@@ -28,47 +28,8 @@ var/datum/controller/subsystem/theming/SStheming
)
)
var/skin_files = list("Light" = "interface/skin.txt", "Dark" = "interface/dark.txt")
var/skin_themes
/datum/controller/subsystem/theming/New()
NEW_SS_GLOBAL(SStheming)
skin_themes = list()
/datum/controller/subsystem/theming/Initialize(start_timeofday)
for(var/name in skin_files)
skin_themes[name] = list()
var/loaded = file2list(skin_files[name])
for(var/op in loaded)
var/split = text2list(op, " ")
if(!islist(skin_themes[name][split[1]]))
skin_themes[name][split[1]] = list()
skin_themes[name][split[1]] += split[2]
for(var/mob/M in mob_list)
if(M.client)
apply_theme_from_perfs(M.client)
..()
/datum/controller/subsystem/theming/proc/apply_theme_from_perfs(var/user)
var/client/c
if(ismob(user))
var/mob/M = user
c = M.client
if(isclient(user))
c = user
if(!isclient(c))
return
apply_theme(user, c.prefs.skin_theme)
/datum/controller/subsystem/theming/proc/apply_theme(var/user, var/theme = "Dark")
if(!isclient(user) && !ismob(user))
return
var/skin = skin_themes[theme]
if(!skin)
return
for(var/param in skin)
winset(user, param, jointext(skin[param], ";"))
/datum/controller/subsystem/theming/proc/get_html_theme(var/mob/user)
var/client/cl = null
+19 -19
View File
@@ -244,22 +244,22 @@ var/datum/controller/subsystem/ticker/SSticker
var/turf/playerTurf = get_turf(Player)
if(emergency_shuttle.departed && emergency_shuttle.evac)
if(isNotAdminLevel(playerTurf.z))
to_chat(Player, "<font color='blue'><b>You managed to survive, but were marooned on [station_name()] as [Player.real_name]...</b></font>")
to_chat(Player, "<span class='notice'><b>You managed to survive, but were marooned on [station_name()] as [Player.real_name]...</b></span>")
else
to_chat(Player, "<font color='green'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></font>")
to_chat(Player, "<span class='good'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></span>")
else if(isAdminLevel(playerTurf.z))
to_chat(Player, "<font color='green'><b>You successfully underwent crew transfer after events on [station_name()] as [Player.real_name].</b></font>")
to_chat(Player, "<span class='good'><b>You successfully underwent crew transfer after events on [station_name()] as [Player.real_name].</b></span>")
else if(issilicon(Player))
to_chat(Player, "<font color='green'><b>You remain operational after the events on [station_name()] as [Player.real_name].</b></font>")
to_chat(Player, "<span class='good'><b>You remain operational after the events on [station_name()] as [Player.real_name].</b></span>")
else
to_chat(Player, "<font color='blue'><b>You missed the crew transfer after the events on [station_name()] as [Player.real_name].</b></font>")
to_chat(Player, "<span class='notice'><b>You missed the crew transfer after the events on [station_name()] as [Player.real_name].</b></span>")
else
if(istype(Player,/mob/abstract/observer))
var/mob/abstract/observer/O = Player
if(!O.started_as_observer)
to_chat(Player, "<font color='red'><b>You did not survive the events on [station_name()]...</b></font>")
to_chat(Player, "<span class='warning'><b>You did not survive the events on [station_name()]...</b></span>")
else
to_chat(Player, "<font color='red'><b>You did not survive the events on [station_name()]...</b></font>")
to_chat(Player, "<span class='warning'><b>You did not survive the events on [station_name()]...</b></span>")
to_world("<br>")
for (var/mob/living/silicon/ai/aiPlayer in mob_list)
@@ -331,8 +331,8 @@ var/datum/controller/subsystem/ticker/SSticker
m = pick(randomtips)
if(m)
to_world("<font color='purple'><b>Tip of the round: \
</b>[html_encode(m)]</font>")
to_world("<span class='vote'><b>Tip of the round: \
</b>[html_encode(m)]</span>")
/datum/controller/subsystem/ticker/proc/print_testmerges()
var/data = revdata.testmerge_overview()
@@ -360,7 +360,7 @@ var/datum/controller/subsystem/ticker/SSticker
pregame_timeleft = dynamic_time
log_debug("SSticker: dynamic set pregame time [dynamic_time]s was greater than configured autogamemode time, not clamping.")
to_world("<B><FONT color='blue'>Welcome to the pre-game lobby!</FONT></B>")
to_world("<B><span class='notice'>Welcome to the pre-game lobby!</span></B>")
to_world("Please, setup your character and select ready. Game will start in [pregame_timeleft] seconds.")
/datum/controller/subsystem/ticker/proc/setup()
@@ -472,8 +472,8 @@ var/datum/controller/subsystem/ticker/SSticker
//Deleting Startpoints but we need the ai point to AI-ize people later
if (S.name != "AI")
qdel(S)
to_world("<FONT color='blue'><B>Enjoy the game!</B></FONT>")
to_world(sound('sound/AI/welcome.ogg'))
to_world("<span class='notice'><B>Enjoy the game!</B></span>")
sound_to(world, sound('sound/AI/welcome.ogg'))
//Holiday Round-start stuff ~Carn
Holiday_Game_Start()
@@ -544,18 +544,18 @@ var/datum/controller/subsystem/ticker/SSticker
if("mercenary") //Nuke wasn't on station when it blew up
flick("intro_nuke",cinematic)
sleep(35)
to_world(sound('sound/effects/explosionfar.ogg'))
sound_to(world, sound('sound/effects/explosionfar.ogg'))
flick("station_intact_fade_red",cinematic)
cinematic.icon_state = "summary_nukefail"
else
flick("intro_nuke",cinematic)
sleep(35)
to_world(sound('sound/effects/explosionfar.ogg'))
sound_to(world, sound('sound/effects/explosionfar.ogg'))
//flick("end",cinematic)
if(2) //nuke was nowhere nearby //TODO: a really distant explosion animation
sleep(50)
to_world(sound('sound/effects/explosionfar.ogg'))
sound_to(world, sound('sound/effects/explosionfar.ogg'))
else //station was destroyed
if( mode && !override )
@@ -565,25 +565,25 @@ var/datum/controller/subsystem/ticker/SSticker
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red",cinematic)
to_world(sound('sound/effects/explosionfar.ogg'))
sound_to(world, sound('sound/effects/explosionfar.ogg'))
cinematic.icon_state = "summary_nukewin"
if("AI malfunction") //Malf (screen,explosion,summary)
flick("intro_malf",cinematic)
sleep(76)
flick("station_explode_fade_red",cinematic)
to_world(sound('sound/effects/explosionfar.ogg'))
sound_to(world, sound('sound/effects/explosionfar.ogg'))
cinematic.icon_state = "summary_malf"
if("blob") //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red",cinematic)
to_world(sound('sound/effects/explosionfar.ogg'))
sound_to(world, sound('sound/effects/explosionfar.ogg'))
cinematic.icon_state = "summary_selfdes"
else //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red", cinematic)
to_world(sound('sound/effects/explosionfar.ogg'))
sound_to(world, sound('sound/effects/explosionfar.ogg'))
cinematic.icon_state = "summary_selfdes"
//If its actually the end of the round, wait for it to end.
+9 -9
View File
@@ -98,13 +98,13 @@ var/datum/controller/subsystem/vote/SSvote
else
factor = 1.4
choices["Initiate Crew Transfer"]["votes"] = round(choices["Initiate Crew Transfer"]["votes"] * factor)
to_world("<font color='purple'>Crew Transfer Factor: [factor]</font>")
to_world("<span class='vote'>Crew Transfer Factor: [factor]</span>")
greatest_votes = max(choices["Initiate Crew Transfer"]["votes"], choices["Continue The Round"]["votes"])
if(mode == "crew_transfer")
if(round(get_round_duration() / 36000)+12 <= 14)
// Credit to Scopes @ oldcode.
to_world("<font color='purple'><b>Majority voting rule in effect. 2/3rds majority needed to initiate transfer.</b></font>")
to_world("<span class='vote'><b>Majority voting rule in effect. 2/3rds majority needed to initiate transfer.</b></span>")
choices["Initiate Crew Transfer"]["votes"] = round(choices["Initiate Crew Transfer"]["votes"] - round(total_votes / 3))
greatest_votes = max(choices["Initiate Crew Transfer"]["votes"], choices["Continue The Round"]["votes"])
@@ -143,7 +143,7 @@ var/datum/controller/subsystem/vote/SSvote
if(mode == "add_antagonist")
antag_add_failed = 1
log_vote(text)
to_world("<font color='purple'>[text]</font>")
to_world("<span class='vote'>[text]</span>")
/datum/controller/subsystem/vote/proc/result()
. = announce_result()
@@ -173,7 +173,7 @@ var/datum/controller/subsystem/vote/SSvote
if(mode == "gamemode") //fire this even if the vote fails.
if(!round_progressing)
round_progressing = 1
to_world("<font color='red'><b>The round will start soon.</b></font>")
to_world("<span class='warning'><b>The round will start soon.</b></span>")
if(restart)
to_world("World restarting due to vote...")
@@ -287,20 +287,20 @@ var/datum/controller/subsystem/vote/SSvote
text += "\n[sanitizeSafe(question)]"
log_vote(text)
to_world("<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src];open=1'>here</a> to place your votes.\nYou have [config.vote_period/10] seconds to vote.</font>")
to_world("<span class='vote'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src];open=1'>here</a> to place your votes.\nYou have [config.vote_period/10] seconds to vote.</span>")
for(var/cc in clients)
var/client/C = cc
if(C.prefs.asfx_togs & ASFX_VOTE) //Personal mute
switch(vote_type)
if("crew_transfer")
C << sound('sound/effects/vote.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
sound_to(C, sound('sound/effects/vote.ogg', repeat = 0, wait = 0, volume = 50, channel = 3))
if("gamemode")
C << sound('sound/ambience/vote_alarm.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
sound_to(C, sound('sound/ambience/vote_alarm.ogg', repeat = 0, wait = 0, volume = 50, channel = 3))
if("custom")
C << sound('sound/ambience/vote_alarm.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
sound_to(C, sound('sound/ambience/vote_alarm.ogg', repeat = 0, wait = 0, volume = 50, channel = 3))
if(mode == "gamemode" && round_progressing)
round_progressing = 0
to_world("<font color='red'><b>Round start has been delayed.</b></font>")
to_world("<span class='warning'><b>Round start has been delayed.</b></span>")
SSvueui.check_uis_for_change(src)
return 1
return 0
+4 -4
View File
@@ -271,14 +271,14 @@
if (istype(A, /atom/movable/openspace/overlay))
var/atom/movable/openspace/overlay/OO = A
var/atom/movable/AA = OO.associated_atom
out += "<li>\icon[A] plane [A.plane], layer [A.layer], depth [OO.depth], associated Z-level [AA.z] - [OO.type] copying [AA] ([AA.type])</li>"
out += "<li>[icon2html(A, usr)] plane [A.plane], layer [A.layer], depth [OO.depth], associated Z-level [AA.z] - [OO.type] copying [AA] ([AA.type])</li>"
else if (isturf(A))
if (A == T)
out += "<li>\icon[A] plane [A.plane], layer [A.layer], Z-level [A.z] - [A] ([A.type]) - <font color='green'>SELF</font></li>"
out += "<li>[icon2html(A, usr)] plane [A.plane], layer [A.layer], Z-level [A.z] - [A] ([A.type]) - <span class='good'>SELF</span></li>"
else // foreign turfs - not visible here, but good for figuring out layering
out += "<li>\icon[A] plane [A.plane], layer [A.layer], Z-level [A.z] - [A] ([A.type]) - <font color='red'>FOREIGN</font></li>"
out += "<li>[icon2html(A, usr)] plane [A.plane], layer [A.layer], Z-level [A.z] - [A] ([A.type]) - <span class='warning'>FOREIGN</span></li>"
else
out += "<li>\icon[A] plane [A.plane], layer [A.layer], Z-level [A.z] - [A] ([A.type])</li>"
out += "<li>[icon2html(A, usr)] plane [A.plane], layer [A.layer], Z-level [A.z] - [A] ([A.type])</li>"
out += "</ul>"