diff --git a/.github/workflows/autochangelog.yml b/.github/workflows/autochangelog.yml
index d0ab3fe4f6..b3f02e955a 100644
--- a/.github/workflows/autochangelog.yml
+++ b/.github/workflows/autochangelog.yml
@@ -22,7 +22,7 @@ jobs:
- name: Ensure +x on CI directory
run: |
chmod -R +x ./tools/ci
- - uses: actions/setup-python@v5
+ - uses: actions/setup-python@v4
with:
python-version: '3.7'
- name: Generate Changelog
diff --git a/code/__defines/chat.dm b/code/__defines/chat.dm
index 70ac35bada..37624e1f4d 100644
--- a/code/__defines/chat.dm
+++ b/code/__defines/chat.dm
@@ -3,11 +3,6 @@
* SPDX-License-Identifier: MIT
*/
-/// How many chat payloads to keep in history
-#define CHAT_RELIABILITY_HISTORY_SIZE 5
-/// How many resends to allow before giving up
-#define CHAT_RELIABILITY_MAX_RESENDS 3
-
#define MESSAGE_TYPE_SYSTEM "system"
#define MESSAGE_TYPE_LOCALCHAT "localchat"
#define MESSAGE_TYPE_PLOCALCHAT "plocalchat"
@@ -15,7 +10,6 @@
#define MESSAGE_TYPE_NIF "nif"
#define MESSAGE_TYPE_INFO "info"
#define MESSAGE_TYPE_WARNING "warning"
-#define MESSAGE_TYPE_VORE "vore"
#define MESSAGE_TYPE_DEADCHAT "deadchat"
#define MESSAGE_TYPE_OOC "ooc"
#define MESSAGE_TYPE_LOOC "looc"
diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm
index 47be30be4e..31970b792f 100644
--- a/code/_helpers/icons.dm
+++ b/code/_helpers/icons.dm
@@ -519,37 +519,6 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
return list(rsc_ref, hash, "asset.[hash]")
-/// Gets a dummy savefile for usage in icon generation.
-/// Savefiles generated from this proc will be empty.
-/proc/get_dummy_savefile(from_failure = FALSE)
- var/static/next_id = 0
- if(next_id++ > 9)
- next_id = 0
- var/savefile_path = "tmp/dummy-save-[next_id].sav"
- try
- if(fexists(savefile_path))
- fdel(savefile_path)
- return new /savefile(savefile_path)
- catch(var/exception/error)
- // if we failed to create a dummy once, try again; maybe someone slept somewhere they shouldnt have
- if(from_failure) // this *is* the retry, something fucked up
- CRASH("get_dummy_savefile failed to create a dummy savefile: '[error]'")
- return get_dummy_savefile(from_failure = TRUE)
-
-/**
- * Converts an icon to base64. Operates by putting the icon in the iconCache savefile,
- * exporting it as text, and then parsing the base64 from that.
- * (This relies on byond automatically storing icons in savefiles as base64)
- */
-/proc/icon2base64(icon/icon)
- if (!isicon(icon))
- return FALSE
- var/savefile/dummySave = get_dummy_savefile()
- WRITE_FILE(dummySave["dummy"], icon)
- var/iconData = dummySave.ExportText("dummy")
- var/list/partial = splittext(iconData, "{")
- return replacetext(copytext_char(partial[2], 3, -5), "\n", "") //if cleanup fails we want to still return the correct base64
-
///given a text string, returns whether it is a valid dmi icons folder path
/proc/is_valid_dmi_file(icon_path)
if(!istext(icon_path) || !length(icon_path))
@@ -704,39 +673,6 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
return get_asset_url(key)
return ""
-/proc/icon2base64html(target, var/custom_classes = "")
- if (!target)
- return
- var/static/list/bicon_cache = list()
- if (isicon(target))
- var/icon/target_icon = target
- var/icon_base64 = icon2base64(target_icon)
-
- if (target_icon.Height() > world.icon_size || target_icon.Width() > world.icon_size)
- var/icon_md5 = md5(icon_base64)
- icon_base64 = bicon_cache[icon_md5]
- if (!icon_base64) // Doesn't exist yet, make it.
- bicon_cache[icon_md5] = icon_base64 = icon2base64(target_icon)
-
-
- return "
"
-
- // Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with.
- var/atom/target_atom = target
- var/key = "[istype(target_atom.icon, /icon) ? "[REF(target_atom.icon)]" : target_atom.icon]:[target_atom.icon_state]"
-
-
- if (!bicon_cache[key]) // Doesn't exist, make it.
- var/icon/target_icon = icon(target_atom.icon, target_atom.icon_state, SOUTH, 1)
- if (ishuman(target)) // Shitty workaround for a BYOND issue.
- var/icon/temp = target_icon
- target_icon = icon()
- target_icon.Insert(temp, dir = SOUTH)
-
- bicon_cache[key] = icon2base64(target_icon)
-
- return "
"
-
//Costlier version of icon2html() that uses getFlatIcon() to account for overlays, underlays, etc. Use with extreme moderation, ESPECIALLY on mobs.
/proc/costly_icon2html(thing, target, sourceonly = FALSE)
if (!thing)
diff --git a/code/_helpers/logging.dm b/code/_helpers/logging.dm
index fb1ba7fa07..737b00a7d0 100644
--- a/code/_helpers/logging.dm
+++ b/code/_helpers/logging.dm
@@ -46,9 +46,7 @@
for(var/client/C in GLOB.admins)
if(C.is_preference_enabled(/datum/client_preference/debug/show_debug_logs))
- to_chat(C,
- type = MESSAGE_TYPE_DEBUG,
- html = "DEBUG: [text]")
+ to_chat(C, "DEBUG: [text]")
/proc/log_game(text)
if (config.log_game)
diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm
index 07a2bfaceb..c0b6bd5001 100644
--- a/code/_helpers/text.dm
+++ b/code/_helpers/text.dm
@@ -345,7 +345,7 @@
if(!text_tag_cache[tagname])
var/icon/tag = icon(text_tag_icons, tagname)
text_tag_cache[tagname] = bicon(tag, TRUE, "text_tag")
- if(!C.tgui_panel.is_ready() || C.tgui_panel.oldchat)
+ if(C.chatOutput.broken)
return "
"
return text_tag_cache[tagname]
diff --git a/code/_macros.dm b/code/_macros.dm
index 169a897881..737b317abe 100644
--- a/code/_macros.dm
+++ b/code/_macros.dm
@@ -12,7 +12,7 @@
// #define to_chat(target, message) target << message Not anymore!
//#define to_chat to_chat_filename=__FILE__;to_chat_line=__LINE__;to_chat_src=src;__to_chat
-//#define to_chat __to_chat
+#define to_chat __to_chat
#define to_world(message) to_chat(world, message)
#define to_world_log(message) world.log << message
// TODO - Baystation has this log to crazy places. For now lets just world.log, but maybe look into it later.
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index a7ff03177d..213fe57b90 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -89,7 +89,7 @@
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc))
if(isturf(A) || isturf(A.loc))
- if(A.Adjacent(src) || (W && W.attack_can_reach(src, A, W.reach))) // see adjacent.dm, allows robots to use ranged melee weapons
+ if(A.Adjacent(src)) // see adjacent.dm
var/resolved = A.attackby(W, src, 1)
if(!resolved && A && W)
diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm
index c494fd685e..114f178653 100644
--- a/code/_onclick/hud/robot.dm
+++ b/code/_onclick/hud/robot.dm
@@ -217,13 +217,13 @@ var/obj/screen/robot_inventory
update_robot_modules_display()
-/datum/hud/proc/update_robot_modules_display(var/reset = FALSE)
+/datum/hud/proc/update_robot_modules_display()
if(!isrobot(mymob))
return
var/mob/living/silicon/robot/r = mymob
- if(r.shown_robot_modules && !reset)
+ if(r.shown_robot_modules)
//Modules display is shown
//r.client.screen += robot_inventory //"store" icon
@@ -292,4 +292,4 @@ var/obj/screen/robot_inventory
return sprite_datum.sprite_hud_icon_state
if(modtype)
return lowertext(modtype)
- return "nomod"
+ return "nomod"
\ No newline at end of file
diff --git a/code/controllers/subsystems/chat.dm b/code/controllers/subsystems/chat.dm
index b8b2917c8d..92a1be2757 100644
--- a/code/controllers/subsystems/chat.dm
+++ b/code/controllers/subsystems/chat.dm
@@ -1,100 +1,77 @@
-/*!
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
- */
-
SUBSYSTEM_DEF(chat)
name = "Chat"
- flags = SS_TICKER|SS_NO_INIT
- wait = 1
+ flags = SS_TICKER
+ wait = 1 // SS_TICKER means this runs every tick
priority = FIRE_PRIORITY_CHAT
init_order = INIT_ORDER_CHAT
- /// Assosciates a ckey with a list of messages to send to them.
- var/list/list/datum/chat_payload/client_to_payloads = list()
+ var/list/list/msg_queue = list() //List of lists
- /// Associates a ckey with an assosciative list of their last CHAT_RELIABILITY_HISTORY_SIZE messages.
- var/list/list/datum/chat_payload/client_to_reliability_history = list()
-
- /// Assosciates a ckey with their next sequence number.
- var/list/client_to_sequence_number = list()
-
-/datum/controller/subsystem/chat/proc/generate_payload(client/target, message_data)
- var/sequence = client_to_sequence_number[target.ckey]
- client_to_sequence_number[target.ckey] += 1
-
- var/datum/chat_payload/payload = new
- payload.sequence = sequence
- payload.content = message_data
-
- if(!(target.ckey in client_to_reliability_history))
- client_to_reliability_history[target.ckey] = list()
- var/list/client_history = client_to_reliability_history[target.ckey]
- client_history["[sequence]"] = payload
-
- if(length(client_history) > CHAT_RELIABILITY_HISTORY_SIZE)
- var/oldest = text2num(client_history[1])
- for(var/index in 2 to length(client_history))
- var/test = text2num(client_history[index])
- if(test < oldest)
- oldest = test
- client_history -= "[oldest]"
- return payload
-
-/datum/controller/subsystem/chat/proc/send_payload_to_client(client/target, datum/chat_payload/payload)
- target.tgui_panel.window.send_message("chat/message", payload.into_message())
- SEND_TEXT(target, payload.get_content_as_html())
+/datum/controller/subsystem/chat/Initialize(timeofday)
+ init_vchat()
+ ..()
/datum/controller/subsystem/chat/fire()
- for(var/ckey in client_to_payloads)
- var/client/target = GLOB.directory[ckey]
- if(isnull(target)) // verify client still exists
- LAZYREMOVE(client_to_payloads, ckey)
- continue
-
- for(var/datum/chat_payload/payload as anything in client_to_payloads[ckey])
- send_payload_to_client(target, payload)
- LAZYREMOVE(client_to_payloads, ckey)
+ var/list/msg_queue = src.msg_queue // Local variable for sanic speed.
+ for(var/client/C as anything in msg_queue)
+ var/list/messages = msg_queue[C]
+ msg_queue -= C
+ if (C)
+ C << output(jsEncode(messages), "htmloutput:putmessage")
if(MC_TICK_CHECK)
return
-/datum/controller/subsystem/chat/proc/queue(queue_target, list/message_data)
- var/list/targets = islist(queue_target) ? queue_target : list(queue_target)
- for(var/target in targets)
- var/client/client = CLIENT_FROM_VAR(target)
- if(isnull(client))
- continue
- LAZYADDASSOCLIST(client_to_payloads, client.ckey, generate_payload(client, message_data))
+/datum/controller/subsystem/chat/stat_entry()
+ ..("C:[msg_queue.len]")
-/datum/controller/subsystem/chat/proc/send_immediate(send_target, list/message_data)
- var/list/targets = islist(send_target) ? send_target : list(send_target)
- for(var/target in targets)
- var/client/client = CLIENT_FROM_VAR(target)
- if(isnull(client))
- continue
- send_payload_to_client(client, generate_payload(client, message_data))
-
-/datum/controller/subsystem/chat/proc/handle_resend(client/client, sequence)
- var/list/client_history = client_to_reliability_history[client.ckey]
- sequence = "[sequence]"
- if(isnull(client_history) || !(sequence in client_history))
+/datum/controller/subsystem/chat/proc/queue(target, time, message, handle_whitespace = TRUE)
+ if(!target || !message)
return
- var/datum/chat_payload/payload = client_history[sequence]
- if(payload.resends > CHAT_RELIABILITY_MAX_RESENDS)
- return // we tried but byond said no
+ if(!istext(message))
+ stack_trace("to_chat called with invalid input type")
+ return
- payload.resends += 1
- send_payload_to_client(client, client_history[sequence])
- /*
- SSblackbox.record_feedback(
- "nested tally",
- "chat_resend_byond_version",
- 1,
- list(
- "[client.byond_version]",
- "[client.byond_build]",
- ),
- )
- */
+ // Currently to_chat(world, ...) gets sent individually to each client. Consider.
+ if(target == world)
+ target = GLOB.clients
+
+ //Some macros remain in the string even after parsing and fuck up the eventual output
+ var/original_message = message
+ message = replacetext(message, "\n", "
")
+ message = replacetext(message, "\improper", "")
+ message = replacetext(message, "\proper", "")
+
+ if(isnull(time))
+ time = world.time
+
+ var/list/messageStruct = list("time" = time, "message" = message);
+
+ if(islist(target))
+ for(var/I in target)
+ var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible
+
+ if(!C || !C.chatOutput)
+ continue // No client? No care.
+ else if(C.chatOutput.broken)
+ DIRECT_OUTPUT(C, original_message)
+ continue
+ else if(!C.chatOutput.loaded)
+ continue // If not loaded yet, do nothing and history-sending on load will get it.
+
+ LAZYINITLIST(msg_queue[C])
+ msg_queue[C][++msg_queue[C].len] = messageStruct
+ else
+ var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible
+
+ if(!C || !C.chatOutput)
+ return // No client? No care.
+ else if(C.chatOutput.broken)
+ DIRECT_OUTPUT(C, original_message)
+ return
+ else if(!C.chatOutput.loaded)
+ return // If not loaded yet, do nothing and history-sending on load will get it.
+
+ LAZYINITLIST(msg_queue[C])
+ msg_queue[C][++msg_queue[C].len] = messageStruct
diff --git a/code/controllers/subsystems/ping.dm b/code/controllers/subsystems/ping.dm
deleted file mode 100644
index 00e3effe02..0000000000
--- a/code/controllers/subsystems/ping.dm
+++ /dev/null
@@ -1,44 +0,0 @@
-/*!
- * Copyright (c) 2022 Aleksej Komarov
- * SPDX-License-Identifier: MIT
- */
-
-SUBSYSTEM_DEF(ping)
- name = "Ping"
- priority = FIRE_PRIORITY_PING
- // init_stage = INITSTAGE_EARLY
- wait = 4 SECONDS
- flags = SS_NO_INIT
- runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
- var/list/currentrun = list()
-
-/datum/controller/subsystem/ping/stat_entry()
- ..("P:[GLOB.clients.len]")
-
-/datum/controller/subsystem/ping/fire(resumed = FALSE)
- // Prepare the new batch of clients
- if (!resumed)
- src.currentrun = GLOB.clients.Copy()
-
- // De-reference the list for sanic speeds
- var/list/currentrun = src.currentrun
-
- while (currentrun.len)
- var/client/client = currentrun[currentrun.len]
- currentrun.len--
-
- if(!client.is_preference_enabled(/datum/client_preference/vchat_enable))
- winset(client, "output", "on-show=&is-disabled=0&is-visible=1")
- winset(client, "browseroutput", "is-disabled=1;is-visible=0")
- client.tgui_panel.oldchat = TRUE
-
- if (client?.tgui_panel?.is_ready())
- // Send a soft ping
- client.tgui_panel.window.send_message("ping/soft", list(
- // Slightly less than the subsystem timer (somewhat arbitrary)
- // to prevent incoming pings from resetting the afk state
- "afk" = client.is_afk(3.5 SECONDS),
- ))
-
- if (MC_TICK_CHECK)
- return
diff --git a/code/controllers/subsystems/tgui.dm b/code/controllers/subsystems/tgui.dm
index 578e3c486a..51459ccfc5 100644
--- a/code/controllers/subsystems/tgui.dm
+++ b/code/controllers/subsystems/tgui.dm
@@ -2,7 +2,6 @@
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
-
/**
* tgui subsystem
*
@@ -38,7 +37,7 @@ SUBSYSTEM_DEF(tgui)
/datum/controller/subsystem/tgui/stat_entry()
..("P:[all_uis.len]")
-/datum/controller/subsystem/tgui/fire(resumed = FALSE)
+/datum/controller/subsystem/tgui/fire(resumed = 0)
if(!resumed)
src.current_run = all_uis.Copy()
// Cache for sanic speed (lists are references anyways)
@@ -47,8 +46,8 @@ SUBSYSTEM_DEF(tgui)
var/datum/tgui/ui = current_run[current_run.len]
current_run.len--
// TODO: Move user/src_object check to process()
- if(ui?.user && ui.src_object)
- ui.process(wait * 0.1)
+ if(ui && ui.user && ui.src_object)
+ ui.process()
else
ui.close(0)
if(MC_TICK_CHECK)
@@ -87,8 +86,6 @@ SUBSYSTEM_DEF(tgui)
window_found = TRUE
break
if(!window_found)
- log_tgui(user, "Error: Pool exhausted",
- context = "SStgui/request_pooled_window")
return null
return window
@@ -100,7 +97,6 @@ SUBSYSTEM_DEF(tgui)
* required user mob
*/
/datum/controller/subsystem/tgui/proc/force_close_all_windows(mob/user)
- log_tgui(user, context = "SStgui/force_close_all_windows")
if(user.client)
user.client.tgui_windows = list()
for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT)
@@ -116,7 +112,6 @@ SUBSYSTEM_DEF(tgui)
* required window_id string
*/
/datum/controller/subsystem/tgui/proc/force_close_window(mob/user, window_id)
- log_tgui(user, context = "SStgui/force_close_window")
// Close all tgui datums based on window_id.
for(var/datum/tgui/ui in user.tgui_open_uis)
if(ui.window && ui.window.id == window_id)
@@ -126,23 +121,22 @@ SUBSYSTEM_DEF(tgui)
// Close window directly just to be sure.
user << browse(null, "window=[window_id]")
-/**
- * public
- *
- * Try to find an instance of a UI, and push an update to it.
- *
- * required user mob The mob who opened/is using the UI.
- * required src_object datum The object/datum which owns the UI.
- * optional ui datum/tgui The UI to be updated, if it exists.
- * optional force_open bool If the UI should be re-opened instead of updated.
- *
- * return datum/tgui The found UI.
- */
+ /**
+ * public
+ *
+ * Get a open UI given a user, src_object, and ui_key and try to update it with data.
+ *
+ * required user mob The mob who opened/is using the UI.
+ * required src_object datum The object/datum which owns the UI.
+ * required ui_key string The ui_key of the UI.
+ *
+ * return datum/tgui The found UI.
+ **/
/datum/controller/subsystem/tgui/proc/try_update_ui(
mob/user,
datum/src_object,
datum/tgui/ui)
- // Look up a UI if it wasn't passed
+ // Look up a UI if it wasn't passed.
if(isnull(ui))
ui = get_open_ui(user, src_object)
// Couldn't find a UI.
@@ -158,16 +152,17 @@ SUBSYSTEM_DEF(tgui)
ui.send_update()
return ui
-/**
- * public
- *
- * Get a open UI given a user and src_object.
- *
- * required user mob The mob who opened/is using the UI.
- * required src_object datum The object/datum which owns the UI.
- *
- * return datum/tgui The found UI.
- */
+ /**
+ * private
+ *
+ * Get a open UI given a user, src_object, and ui_key.
+ *
+ * required user mob The mob who opened/is using the UI.
+ * required src_object datum The object/datum which owns the UI.
+ * required ui_key string The ui_key of the UI.
+ *
+ * return datum/tgui The found UI.
+ **/
/datum/controller/subsystem/tgui/proc/get_open_ui(mob/user, datum/src_object)
// No UIs opened for this src_object
if(!LAZYLEN(src_object?.open_uis))
@@ -176,57 +171,56 @@ SUBSYSTEM_DEF(tgui)
// Make sure we have the right user
if(ui.user == user)
return ui
- return null
+ return null // Couldn't find a UI!
-/**
- * public
- *
- * Update all UIs attached to src_object.
- *
- * required src_object datum The object/datum which owns the UIs.
- *
- * return int The number of UIs updated.
- */
+ /**
+ * private
+ *
+ * Update all UIs attached to src_object.
+ *
+ * required src_object datum The object/datum which owns the UIs.
+ *
+ * return int The number of UIs updated.
+ **/
/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object)
// No UIs opened for this src_object
if(!LAZYLEN(src_object?.open_uis))
return 0
var/count = 0
for(var/datum/tgui/ui in src_object.open_uis)
- // Check if UI is valid.
- if(ui?.src_object && ui.user && ui.src_object.tgui_host(ui.user))
+ // Check the UI is valid.
+ if(ui && ui.src_object && ui.user && ui.src_object.tgui_host(ui.user))
INVOKE_ASYNC(ui, TYPE_PROC_REF(/datum/tgui, process), wait * 0.1, TRUE)
- count++
+ count++ // Count each UI we update.
return count
-/**
- * public
- *
- * Close all UIs attached to src_object.
- *
- * required src_object datum The object/datum which owns the UIs.
- *
- * return int The number of UIs closed.
- */
+ /**
+ * private
+ *
+ * Close all UIs attached to src_object.
+ *
+ * required src_object datum The object/datum which owns the UIs.
+ *
+ * return int The number of UIs closed.
+ **/
/datum/controller/subsystem/tgui/proc/close_uis(datum/src_object)
// No UIs opened for this src_object
if(!LAZYLEN(src_object?.open_uis))
return 0
var/count = 0
for(var/datum/tgui/ui in src_object.open_uis)
- // Check if UI is valid.
- if(ui?.src_object && ui.user && ui.src_object.tgui_host(ui.user))
- ui.close()
- count++
+ if(ui && ui.src_object && ui.user && ui.src_object.tgui_host(ui.user)) // Check the UI is valid.
+ ui.close() // Close the UI.
+ count++ // Count each UI we close.
return count
-/**
- * public
- *
- * Close all UIs regardless of their attachment to src_object.
- *
- * return int The number of UIs closed.
- */
+ /**
+ * private
+ *
+ * Close all UIs regardless of their attachment to src_object.
+ *
+ * return int The number of UIs closed.
+ **/
/datum/controller/subsystem/tgui/proc/close_all_uis()
var/count = 0
for(var/datum/tgui/ui in all_uis)
@@ -236,67 +230,67 @@ SUBSYSTEM_DEF(tgui)
count++
return count
-/**
- * public
- *
- * Update all UIs belonging to a user.
- *
- * required user mob The mob who opened/is using the UI.
- * optional src_object datum If provided, only update UIs belonging this src_object.
- *
- * return int The number of UIs updated.
- */
+ /**
+ * private
+ *
+ * Update all UIs belonging to a user.
+ *
+ * required user mob The mob who opened/is using the UI.
+ * optional src_object datum If provided, only update UIs belonging this src_object.
+ *
+ * return int The number of UIs updated.
+ **/
/datum/controller/subsystem/tgui/proc/update_user_uis(mob/user, datum/src_object)
var/count = 0
if(length(user?.tgui_open_uis) == 0)
return count
for(var/datum/tgui/ui in user.tgui_open_uis)
if(isnull(src_object) || ui.src_object == src_object)
- ui.process(wait * 0.1, force = 1)
+ ui.process(force = 1)
count++
return count
-/**
- * public
- *
- * Close all UIs belonging to a user.
- *
- * required user mob The mob who opened/is using the UI.
- * optional src_object datum If provided, only close UIs belonging this src_object.
- *
- * return int The number of UIs closed.
- */
-/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object)
+ /**
+ * private
+ *
+ * Close all UIs belonging to a user.
+ *
+ * required user mob The mob who opened/is using the UI.
+ * optional src_object datum If provided, only close UIs belonging this src_object.
+ *
+ * return int The number of UIs closed.
+ **/
+/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object, logout = FALSE)
var/count = 0
if(length(user?.tgui_open_uis) == 0)
return count
for(var/datum/tgui/ui in user.tgui_open_uis)
if(isnull(src_object) || ui.src_object == src_object)
- ui.close()
+ ui.close(logout = logout)
count++
return count
-/**
- * private
- *
- * Add a UI to the list of open UIs.
- *
- * required ui datum/tgui The UI to be added.
- */
+ /**
+ * private
+ *
+ * Add a UI to the list of open UIs.
+ *
+ * required ui datum/tgui The UI to be added.
+ **/
/datum/controller/subsystem/tgui/proc/on_open(datum/tgui/ui)
ui.user?.tgui_open_uis |= ui
LAZYOR(ui.src_object.open_uis, ui)
all_uis |= ui
-/**
- * private
- *
- * Remove a UI from the list of open UIs.
- *
- * required ui datum/tgui The UI to be removed.
- *
- * return bool If the UI was removed or not.
- */
+ /**
+ * private
+ *
+ * Remove a UI from the list of open UIs.
+ *
+ * required ui datum/tgui The UI to be removed.
+ *
+ * return bool If the UI was removed or not.
+ **/
/datum/controller/subsystem/tgui/proc/on_close(datum/tgui/ui)
// Remove it from the list of processing UIs.
all_uis -= ui
@@ -308,28 +302,28 @@ SUBSYSTEM_DEF(tgui)
LAZYREMOVE(ui.src_object.open_uis, ui)
return TRUE
-/**
- * private
- *
- * Handle client logout, by closing all their UIs.
- *
- * required user mob The mob which logged out.
- *
- * return int The number of UIs closed.
- */
+ /**
+ * private
+ *
+ * Handle client logout, by closing all their UIs.
+ *
+ * required user mob The mob which logged out.
+ *
+ * return int The number of UIs closed.
+ **/
/datum/controller/subsystem/tgui/proc/on_logout(mob/user)
- close_user_uis(user)
+ return close_user_uis(user, logout = TRUE)
-/**
- * private
- *
- * Handle clients switching mobs, by transferring their UIs.
- *
- * required user source The client's original mob.
- * required user target The client's new mob.
- *
- * return bool If the UIs were transferred.
- */
+ /**
+ * private
+ *
+ * Handle clients switching mobs, by transferring their UIs.
+ *
+ * required user source The client's original mob.
+ * required user target The client's new mob.
+ *
+ * return bool If the UIs were transferred.
+ **/
/datum/controller/subsystem/tgui/proc/on_transfer(mob/source, mob/target)
// The old mob had no open UIs.
if(length(source?.tgui_open_uis) == 0)
diff --git a/code/datums/chat_payload.dm b/code/datums/chat_payload.dm
deleted file mode 100644
index fd35bbc4ee..0000000000
--- a/code/datums/chat_payload.dm
+++ /dev/null
@@ -1,16 +0,0 @@
-/// Stores information about a chat payload
-/datum/chat_payload
- /// Sequence number of this payload
- var/sequence = 0
- /// Message we are sending
- var/list/content
- /// Resend count
- var/resends = 0
-
-/// Converts the chat payload into a JSON string
-/datum/chat_payload/proc/into_message()
- return "{\"sequence\":[sequence],\"content\":[json_encode(content)]}"
-
-/// Returns an HTML-encoded message from our contents.
-/datum/chat_payload/proc/get_content_as_html()
- return message_to_html(content)
diff --git a/code/datums/underwear/bottom.dm b/code/datums/underwear/bottom.dm
index d32d7952c1..358fe20104 100644
--- a/code/datums/underwear/bottom.dm
+++ b/code/datums/underwear/bottom.dm
@@ -95,14 +95,4 @@
/datum/category_item/underwear/bottom/onepiece
name = "Swimming One Piece"
icon_state = "onepiece"
- has_color = TRUE
-
-/datum/category_item/underwear/top/onepiece_alt
- name = "Swimming One Piece, Alt"
- icon_state = "swim_onepiece"
- has_color = TRUE
-
-/datum/category_item/underwear/top/onepiece_strapless
- name = "Swimming One Piece, Strapless"
- icon_state = "swim_strapless_onepiece"
- has_color = TRUE
+ has_color = TRUE
\ No newline at end of file
diff --git a/code/datums/underwear/socks.dm b/code/datums/underwear/socks.dm
index e06782b8d2..ac29b579d1 100644
--- a/code/datums/underwear/socks.dm
+++ b/code/datums/underwear/socks.dm
@@ -208,8 +208,4 @@
/datum/category_item/underwear/socks/stirrup_thigh_black
name = "Black Stirrup Stockings"
icon_state = "leggings-stir-black"
- has_color = TRUE
-
-/datum/category_item/underwear/socks/stirrup_pantyhose
- name = "Pantyhose, stirrup"
- icon_state = "pantyhose-stir"
+ has_color = TRUE
\ No newline at end of file
diff --git a/code/datums/underwear/top.dm b/code/datums/underwear/top.dm
index 336bebd1cc..5af7870f04 100644
--- a/code/datums/underwear/top.dm
+++ b/code/datums/underwear/top.dm
@@ -51,20 +51,10 @@
name = "Fishnet top"
icon_state = "fishnet_body"
-/datum/category_item/underwear/top/fishnet_base_alt
- name = "Fishnet top, alt"
- icon_state = "fishnet_body_alt"
- has_color = TRUE
-
/datum/category_item/underwear/top/fishnet_sleeves
name = "Fishnet with sleeves"
icon_state = "fishnet_sleeves"
-/datum/category_item/underwear/top/fishnet_sleeves_alt
- name = "Fishnet with sleeves, alt"
- icon_state = "fishnet_sleeves_alt"
- has_color = TRUE
-
/datum/category_item/underwear/top/fishnet_gloves
name = "Fishnet with gloves"
icon_state = "fishnet_gloves"
@@ -105,4 +95,4 @@
/datum/category_item/underwear/top/swimtop
name = "Swimming Top"
icon_state = "swimtop"
- has_color = TRUE
+ has_color = TRUE
\ No newline at end of file
diff --git a/code/datums/underwear/undershirts.dm b/code/datums/underwear/undershirts.dm
index 6611092b38..2c32ad8e76 100644
--- a/code/datums/underwear/undershirts.dm
+++ b/code/datums/underwear/undershirts.dm
@@ -189,38 +189,13 @@
icon_state = "pinkblack_tshirt"
/datum/category_item/underwear/undershirt/turtle
- name = "Turtleneck, Old"
- icon_state = "turtleneck_old"
- has_color = TRUE
-
-/datum/category_item/underwear/undershirt/sleevelessturtle
- name = "Turtleneck, Sleeveless, Old"
- icon_state = "turtleneck_sleeveless_old"
- has_color = TRUE
-
-/datum/category_item/underwear/undershirt/turtleneck
name = "Turtleneck"
icon_state = "turtleneck"
has_color = TRUE
-/datum/category_item/underwear/undershirt/turtleneck_smooth
- name = "Turtleneck, Smooth"
- icon_state = "turtleneck_smooth"
- has_color = TRUE
-
-/datum/category_item/underwear/undershirt/turtlesleeveless
+/datum/category_item/underwear/undershirt/sleevelessturtle
name = "Turtleneck, Sleeveless"
- icon_state = "turtleneck_sleeveless"
- has_color = TRUE
-
-/datum/category_item/underwear/undershirt/leotardturtle
- name = "Leotard Turtleneck"
- icon_state = "leotard_turtleneck"
- has_color = TRUE
-
-/datum/category_item/underwear/undershirt/leotardturtlesleeveless
- name = "Leotard Turtleneck, Sleeveless"
- icon_state = "leotard_turtleneck_sleeveless"
+ icon_state = "sleevelessturtle"
has_color = TRUE
/datum/category_item/underwear/undershirt/dress_shirt_fem
@@ -251,4 +226,4 @@
/datum/category_item/underwear/undershirt/leotard
name = "Leotard"
icon_state = "leotard"
- has_color = TRUE
+ has_color = TRUE
\ No newline at end of file
diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm
index ad2e49e5c4..f5ea5d0cbf 100644
--- a/code/game/mecha/mecha_construction_paths.dm
+++ b/code/game/mecha/mecha_construction_paths.dm
@@ -374,7 +374,7 @@
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is adjusted"),
//17
- list("key"=IS_WIRECUTTER,
+ list("key"=/obj/item/weapon/tool/wirecutters,
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is added"),
//18
@@ -656,7 +656,7 @@
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is adjusted"),
//17
- list("key"=IS_WIRECUTTER,
+ list("key"=/obj/item/weapon/tool/wirecutters,
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is added"),
//18
@@ -919,7 +919,7 @@
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is adjusted"),
//12
- list("key"=IS_WIRECUTTER,
+ list("key"=/obj/item/weapon/tool/wirecutters,
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is added"),
//13
@@ -1159,7 +1159,7 @@
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is adjusted"),
//17
- list("key"=IS_WIRECUTTER,
+ list("key"=/obj/item/weapon/tool/wirecutters,
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is added"),
//18
@@ -1417,7 +1417,7 @@
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is adjusted"),
//11
- list("key"=IS_WIRECUTTER,
+ list("key"=/obj/item/weapon/tool/wirecutters,
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is added"),
//12
@@ -1650,7 +1650,7 @@
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is adjusted"),
//17
- list("key"=IS_WIRECUTTER,
+ list("key"=/obj/item/weapon/tool/wirecutters,
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is added"),
//18
@@ -1937,7 +1937,7 @@
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is adjusted"),
//19
- list("key"=IS_WIRECUTTER,
+ list("key"=/obj/item/weapon/tool/wirecutters,
"backkey"=IS_SCREWDRIVER,
"desc"="The wiring is added"),
//20
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 609822a756..5c0e31a4c6 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -226,7 +226,6 @@
/obj/item/attack_hand(mob/living/user as mob)
if (!user) return
- ..()
if(anchored)
to_chat(user, span("notice", "\The [src] won't budge, you can't pick it up!"))
return
@@ -1021,4 +1020,4 @@ Note: This proc can be overwritten to allow for different types of auto-alignmen
return
/obj/item/proc/get_welder()
- return
+ return
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm
index 42134cb638..6e4379367f 100644
--- a/code/game/objects/items/weapons/gift_wrappaper.dm
+++ b/code/game/objects/items/weapons/gift_wrappaper.dm
@@ -132,14 +132,13 @@
to_chat(user, "You MUST put the paper on a table!")
if (W.w_class < ITEMSIZE_LARGE)
var/obj/item/I = user.get_inactive_hand()
- if(I && I.has_tool_quality(TOOL_WIRECUTTER))
+ if(I.has_tool_quality(TOOL_WIRECUTTER))
var/a_used = 2 ** (src.w_class - 1)
if (src.amount < a_used)
to_chat(user, "You need more paper!")
return
else
if(istype(W, /obj/item/smallDelivery) || istype(W, /obj/item/weapon/gift)) //No gift wrapping gifts!
- to_chat(user, "You can't wrap something that's already wrapped!")
return
src.amount -= a_used
diff --git a/code/game/objects/items/weapons/tools/transforming.dm b/code/game/objects/items/weapons/tools/transforming.dm
index 9089a71423..41cf89a9c3 100644
--- a/code/game/objects/items/weapons/tools/transforming.dm
+++ b/code/game/objects/items/weapons/tools/transforming.dm
@@ -55,7 +55,6 @@
desc = initial(desc) + " It's fitted with a prying head."
icon_state = "jaws_pry"
usesound = 'sound/items/jaws_pry.ogg'
- pry = 1
tool_qualities = list(TOOL_CROWBAR)
if(user)
playsound(src, 'sound/items/change_jaws.ogg', 50, 1)
@@ -64,7 +63,6 @@
desc = initial(desc) + " It's fitted with a cutting head."
icon_state = "jaws_cutter"
usesound = 'sound/items/jaws_cut.ogg'
- pry = 0
tool_qualities = list(TOOL_WIRECUTTER)
if(user)
playsound(src, 'sound/items/change_jaws.ogg', 50, 1)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 2260f42fb9..e6ec740aa0 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -185,22 +185,22 @@
user.do_attack_animation(src)
shatter()
- else if (user.a_intent == I_HURT)
+ else if (usr.a_intent == I_HURT)
- if (istype(user,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = user
+ if (istype(usr,/mob/living/carbon/human))
+ var/mob/living/carbon/human/H = usr
if(H.species.can_shred(H))
attack_generic(H,25)
return
playsound(src, 'sound/effects/glassknock.ogg', 80, 1)
user.do_attack_animation(src)
- user.visible_message("\The [user] bangs against \the [src]!",
+ usr.visible_message("\The [usr] bangs against \the [src]!",
"You bang against \the [src]!",
"You hear a banging sound.")
else
playsound(src, 'sound/effects/glassknock.ogg', 80, 1)
- user.visible_message("[user.name] knocks on the [src.name].",
+ usr.visible_message("[usr.name] knocks on the [src.name].",
"You knock on the [src.name].",
"You hear a knocking sound.")
return
diff --git a/code/game/world.dm b/code/game/world.dm
index 9f08a33380..a6cbb73385 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -33,6 +33,7 @@
GLOB.timezoneOffset = get_timezone_offset()
callHook("startup")
+ init_vchat()
//Emergency Fix
load_mods()
//end-emergency fix
@@ -506,7 +507,7 @@ var/world_topic_spam_protect_time = world.timeofday
s += "[station_name()]";
s += " ("
- s += "" //Change this to wherever you want the hub to link to.
+ s += "" //Change this to wherever you want the hub to link to.
// s += "[game_version]"
s += "Default" //Replace this with something else. Or ever better, delete it and uncomment the game version.
s += ""
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index b9ec670640..8fdc8edc13 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -8,10 +8,7 @@ var/global/floorIsLava = 0
for(var/client/C in GLOB.admins)
if((R_ADMIN|R_MOD) & C.holder.rights)
- to_chat(C,
- type = MESSAGE_TYPE_ADMINLOG,
- html = msg,
- confidential = TRUE)
+ to_chat(C,msg)
/proc/msg_admin_attack(var/text) //Toggleable Attack Messages
var/rendered = ""
@@ -19,10 +16,7 @@ var/global/floorIsLava = 0
if((R_ADMIN|R_MOD) & C.holder.rights)
if(C.is_preference_enabled(/datum/client_preference/mod/show_attack_logs))
var/msg = rendered
- to_chat(C,
- type = MESSAGE_TYPE_ATTACKLOG,
- html = msg,
- confidential = TRUE)
+ to_chat(C,msg)
/proc/admin_notice(var/message, var/rights)
for(var/mob/M in mob_list)
diff --git a/code/modules/admin/verbs/modify_robot.dm b/code/modules/admin/verbs/modify_robot.dm
index 9413353cf7..2562d891b3 100644
--- a/code/modules/admin/verbs/modify_robot.dm
+++ b/code/modules/admin/verbs/modify_robot.dm
@@ -6,7 +6,7 @@
if(!check_rights(R_ADMIN))
return
- if(!istype(target) || !target.module)
+ if(!istype(target))
return
if(!target.module.modules)
@@ -45,7 +45,6 @@
robot.module.contents.Remove(add_item)
target.module.modules.Add(add_item)
target.module.contents.Add(add_item)
- target.hud_used.update_robot_modules_display()
to_chat(usr, "You added \"[add_item]\" to [target].")
if(istype(add_item, /obj/item/stack/))
var/obj/item/stack/item_with_synth = add_item
@@ -95,8 +94,6 @@
if(!istype(selected_module_module, /obj/item/))
break
to_chat(usr, "You removed \"[selected_module_module]\" from [target]")
- target.uneq_all()
- target.hud_used.update_robot_modules_display(TRUE)
target.module.emag.Remove(selected_module_module)
target.module.modules.Remove(selected_module_module)
target.module.contents.Remove(selected_module_module)
diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm
index ffac68a6f9..b2be689721 100644
--- a/code/modules/admin/verbs/pray.dm
+++ b/code/modules/admin/verbs/pray.dm
@@ -22,9 +22,9 @@
for(var/client/C in GLOB.admins)
if(R_ADMIN|R_EVENT & C.holder.rights)
if(C.is_preference_enabled(/datum/client_preference/admin/show_chat_prayers))
- to_chat(C, msg, type = MESSAGE_TYPE_PRAYER, confidential = TRUE)
+ to_chat(C,msg)
C << 'sound/effects/ding.ogg'
- to_chat(usr, "Your prayers have been received by the gods.", confidential = TRUE)
+ to_chat(usr, "Your prayers have been received by the gods.")
feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_pray(raw_msg, src)
diff --git a/code/modules/asset_cache/assets/chat.dm b/code/modules/asset_cache/assets/chat.dm
deleted file mode 100644
index eba0e5418e..0000000000
--- a/code/modules/asset_cache/assets/chat.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-/datum/asset/spritesheet/chat
- name = "chat"
diff --git a/code/modules/asset_cache/assets/tgui.dm b/code/modules/asset_cache/assets/tgui.dm
index 6446471a30..6874c24eea 100644
--- a/code/modules/asset_cache/assets/tgui.dm
+++ b/code/modules/asset_cache/assets/tgui.dm
@@ -5,9 +5,11 @@
"tgui.bundle.css" = file("tgui/public/tgui.bundle.css"),
)
+/* Comment will be removed in later part
/datum/asset/simple/tgui_panel
// keep_local_name = TRUE
assets = list(
"tgui-panel.bundle.js" = file("tgui/public/tgui-panel.bundle.js"),
"tgui-panel.bundle.css" = file("tgui/public/tgui-panel.bundle.css"),
)
+*/
diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm
index e3e23af110..a68740e965 100644
--- a/code/modules/client/client defines.dm
+++ b/code/modules/client/client defines.dm
@@ -41,10 +41,8 @@
var/datum/admins/deadmin_holder = null
var/buildmode = 0
- ///Contains the last message sent by this client - used to protect against copy-paste spamming.
- var/last_message = ""
- ///contins a number of how many times a message identical to last_message was sent.
- var/last_message_count = 0
+ var/last_message = "" //Contains the last message sent by this client - used to protect against copy-paste spamming.
+ var/last_message_count = 0 //contins a number of how many times a message identical to last_message was sent.
var/ircreplyamount = 0
var/entity_narrate_holder //Holds /datum/entity_narrate when using the relevant admin verbs.
@@ -58,7 +56,9 @@
var/area = null
var/time_died_as_mouse = null //when the client last died as a mouse
var/datum/tooltip/tooltips = null
+ var/datum/chatOutput/chatOutput
var/datum/volume_panel/volume_panel = null // Initialized by /client/verb/volume_panel()
+ var/chatOutputLoadedAt
var/seen_news = 0
var/adminhelped = 0
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index 1efa62c77c..ed652ad8ea 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -133,6 +133,7 @@
if("usr") hsrc = mob
if("prefs") return prefs.process_link(usr,href_list)
if("vars") return view_var_Topic(href,href_list,hsrc)
+ if("chat") return chatOutput.Topic(href, href_list)
switch(href_list["action"])
if("openLink")
@@ -167,10 +168,15 @@
return null
if(!config.guests_allowed && IsGuestKey(key))
- alert(src,"This server doesn't allow guest accounts to play. Please go to https://www.byond.com/ and register for a key.","Guest") // Not tgui_alert
+ alert(src,"This server doesn't allow guest accounts to play. Please go to http://www.byond.com/ and register for a key.","Guest") // Not tgui_alert
del(src)
return
+ chatOutput = new /datum/chatOutput(src) //veechat
+ chatOutput.send_resources()
+ spawn()
+ chatOutput.start()
+
//Only show this if they are put into a new_player mob. Otherwise, "what title screen?"
if(isnewplayer(src.mob))
to_chat(src, "If the title screen is black, resources are still downloading. Please be patient until the title screen appears.")
@@ -178,9 +184,6 @@
GLOB.clients += src
GLOB.directory[ckey] = src
- // Instantiate tgui panel
- tgui_panel = new(src, "browseroutput")
-
GLOB.ahelp_tickets.ClientLogin(src)
GLOB.mhelp_tickets.ClientLogin(src)
@@ -210,9 +213,6 @@
if(prefs)
prefs.selecting_slots = FALSE
- // Initialize tgui panel
- tgui_panel.initialize()
-
connection_time = world.time
connection_realtime = world.realtime
connection_timeofday = world.timeofday
@@ -484,11 +484,34 @@
return FALSE
return ..()
+/client/verb/reload_vchat()
+ set name = "Reload VChat"
+ set category = "OOC"
+
+ //Timing
+ if(src.chatOutputLoadedAt > (world.time - 10 SECONDS))
+ tgui_alert_async(src, "You can only try to reload VChat every 10 seconds at most.")
+ return
+
+ verbs -= /client/proc/vchat_export_log
+
+ //Log, disable
+ log_debug("[key_name(src)] reloaded VChat.")
+ winset(src, null, "outputwindow.htmloutput.is-visible=false;outputwindow.oldoutput.is-visible=false;outputwindow.chatloadlabel.is-visible=true")
+
+ //The hard way
+ qdel_null(src.chatOutput)
+ chatOutput = new /datum/chatOutput(src) //veechat
+ chatOutput.send_resources()
+ spawn()
+ chatOutput.start()
+
+
//This is for getipintel.net.
//You're welcome to replace this proc with your own that does your own cool stuff.
//Just set the client's ip_reputation var and make sure it makes sense with your config settings (higher numbers are worse results)
/client/proc/update_ip_reputation()
- var/request = "https://check.getipintel.net/check.php?ip=[address]&contact=[config.ipr_email]"
+ var/request = "http://check.getipintel.net/check.php?ip=[address]&contact=[config.ipr_email]"
var/http[] = world.Export(request)
/* Debug
diff --git a/code/modules/client/client procs_vr.dm b/code/modules/client/client procs_vr.dm
index 7cea3d5776..830521f20d 100644
--- a/code/modules/client/client procs_vr.dm
+++ b/code/modules/client/client procs_vr.dm
@@ -20,7 +20,7 @@
if(!config.ipr_email)
return -1
- var/request = "https://check.getipintel.net/check.php?ip=[address]&contact=[config.ipr_email]"
+ var/request = "http://check.getipintel.net/check.php?ip=[address]&contact=[config.ipr_email]"
var/http[] = world.Export(request)
if(!http || !islist(http)) //If we couldn't check, the service might be down, fail-safe.
@@ -74,7 +74,7 @@
if(!config.ipqualityscore_apikey)
return -1
- var/request = "https://www.ipqualityscore.com/api/json/ip/[config.ipqualityscore_apikey]/[address]?strictness=1&fast=true&byond_key=[key]"
+ var/request = "http://www.ipqualityscore.com/api/json/ip/[config.ipqualityscore_apikey]/[address]?strictness=1&fast=true&byond_key=[key]"
var/http[] = world.Export(request)
if(!http || !islist(http)) //If we couldn't check, the service might be down, fail-safe.
@@ -97,4 +97,4 @@
else
score = response["fraud_score"]
- return score/100 //To normalize with the 0.0 to 1.0 scores.
+ return score/100 //To normalize with the 0.0 to 1.0 scores.
\ No newline at end of file
diff --git a/code/modules/client/preference_setup/general/04_equipment.dm b/code/modules/client/preference_setup/general/04_equipment.dm
index 2e3e2ab7f4..af786e7d64 100644
--- a/code/modules/client/preference_setup/general/04_equipment.dm
+++ b/code/modules/client/preference_setup/general/04_equipment.dm
@@ -22,33 +22,6 @@
S["communicator_visibility"] << pref.communicator_visibility
S["ringtone"] << pref.ringtone
-var/global/list/valid_ringtones = list(
- "beep",
- "boom",
- "slip",
- "honk",
- "SKREE",
- "xeno",
- "spark",
- "rad",
- "servo",
- "buh-boop",
- "trombone",
- "whistle",
- "chirp",
- "slurp",
- "pwing",
- "clack",
- "bzzt",
- "chimes",
- "prbt",
- "bark",
- "bork",
- "roark",
- "chitter",
- "squish"
- )
-
// Moved from /datum/preferences/proc/copy_to()
/datum/category_item/player_setup_item/general/equipment/copy_to_mob(var/mob/living/carbon/human/character)
character.all_underwear.Cut()
@@ -178,15 +151,8 @@ var/global/list/valid_ringtones = list(
pref.communicator_visibility = !pref.communicator_visibility
return TOPIC_REFRESH
else if(href_list["set_ringtone"])
- var/choice = tgui_input_list(user, "Please select a ringtone. All of these choices come with an associated preset sound. Alternately, select \"Other\" to specify manually.", "Character Preference", valid_ringtones + "Other", pref.ringtone)
- if(!choice || !CanUseTopic(user))
- return TOPIC_NOACTION
- if(choice == "Other")
- var/raw_choice = sanitize(tgui_input_text(user, "Please enter a custom ringtone. If this doesn't match any of the other listed choices, your PDA will use the default (\"beep\") sound.", "Character Preference", null, 20), 20)
- if(raw_choice && CanUseTopic(user))
- pref.ringtone = raw_choice
- else
- pref.ringtone = choice
- return TOPIC_REFRESH
+ if(CanUseTopic(user))
+ pref.ringtone = sanitize(input(user, "Please enter a new ringtone.", "Character Preference") as null|text, 20)
+ return TOPIC_REFRESH
return ..()
diff --git a/code/modules/client/preference_setup/global/setting_datums.dm b/code/modules/client/preference_setup/global/setting_datums.dm
index fd1ebc2ebc..21f8037506 100644
--- a/code/modules/client/preference_setup/global/setting_datums.dm
+++ b/code/modules/client/preference_setup/global/setting_datums.dm
@@ -289,7 +289,7 @@ var/list/_client_preferences_by_type
key = "SOUND_INSTRUMENT"
/datum/client_preference/vchat_enable
- description = "Enable/Disable TGChat"
+ description = "Enable/Disable VChat"
key = "VCHAT_ENABLE"
enabled_description = "Enabled"
disabled_description = "Disabled"
diff --git a/code/modules/client/preference_setup/loadout/loadout_mask.dm b/code/modules/client/preference_setup/loadout/loadout_mask.dm
index de4aad90d2..3531cfff72 100644
--- a/code/modules/client/preference_setup/loadout/loadout_mask.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_mask.dm
@@ -76,7 +76,3 @@
/datum/gear/mask/lace/New()
gear_tweaks += gear_tweak_free_color_choice
-
-/datum/gear/mask/half
- display_name = "black half-mask"
- path = /obj/item/clothing/accessory/gaiter/half
diff --git a/code/modules/client/preference_setup/loadout/loadout_uniform.dm b/code/modules/client/preference_setup/loadout/loadout_uniform.dm
index 55f72d248d..e7ea6ce7e3 100644
--- a/code/modules/client/preference_setup/loadout/loadout_uniform.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_uniform.dm
@@ -497,10 +497,6 @@
)
gear_tweaks += new/datum/gear_tweak/path(cowboy_outfits)
-/datum/gear/uniform/hightrousers
- display_name = "high-waisted trousers"
- path = /obj/item/clothing/under/dress/hightrousers
-
/*
* 80s
*/
@@ -590,16 +586,3 @@
/datum/gear/uniform/fienddress
display_name = "fiendish dress"
path = /obj/item/clothing/under/fienddress
-
-//tabard dresses
-/datum/gear/uniform/tabarddress
- display_name = "tabard-dress selection"
- path = /obj/item/clothing/under/dress/tabard
-
-/datum/gear/uniform/tabarddress/New()
- ..()
- var/list/tabarddress = list(
- "white tabard-dress"=/obj/item/clothing/under/dress/tabard,
- "black tabard-dress"=/obj/item/clothing/under/dress/tabard/black
- )
- gear_tweaks += list(new/datum/gear_tweak/path(tabarddress))
diff --git a/code/modules/client/preference_setup/vore/07_traits.dm b/code/modules/client/preference_setup/vore/07_traits.dm
index 14b0775363..e89d12f2cc 100644
--- a/code/modules/client/preference_setup/vore/07_traits.dm
+++ b/code/modules/client/preference_setup/vore/07_traits.dm
@@ -5,7 +5,7 @@
#define ORGANICS 1
#define SYNTHETICS 2
-var/global/list/valid_bloodreagents = list("default","iron","copper","phoron","silver","gold","slimejelly") //allowlist-based so people don't make their blood restored by alcohol or something really silly. use reagent IDs!
+var/global/list/valid_bloodreagents = list("iron","copper","phoron","silver","gold","slimejelly") //allowlist-based so people don't make their blood restored by alcohol or something really silly. use reagent IDs!
/datum/preferences
var/custom_species // Custom species name, can't be changed due to it having been used in savefiles already.
@@ -258,8 +258,7 @@ var/global/list/valid_bloodreagents = list("default","iron","copper","phoron","s
//Any additional non-trait settings can be applied here
new_S.blood_color = pref.blood_color
- if(!(pref.blood_reagents == "default"))
- new_S.blood_reagents = pref.blood_reagents
+ new_S.blood_reagents = pref.blood_reagents
if(pref.species == SPECIES_CUSTOM)
//Statistics for this would be nice
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 810dab44bf..4603e8840c 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -48,7 +48,7 @@ var/list/preferences_datums = list()
var/bday_announce = FALSE //Public announcement for birthdays
var/spawnpoint = "Arrivals Shuttle" //where this character will spawn (0-2).
var/b_type = "A+" //blood type (not-chooseable)
- var/blood_reagents = "default" //blood restoration reagents
+ var/blood_reagents = "iron" //blood restoration reagents
var/backbag = 2 //backpack type
var/pdachoice = 1 //PDA type
var/h_style = "Bald" //Hair type
diff --git a/code/modules/client/preferences_toggle_procs.dm b/code/modules/client/preferences_toggle_procs.dm
index 8ce75698ba..454a5ec6ac 100644
--- a/code/modules/client/preferences_toggle_procs.dm
+++ b/code/modules/client/preferences_toggle_procs.dm
@@ -367,17 +367,17 @@
feedback_add_details("admin_verb","THInstm") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggle_vchat()
- set name = "Toggle TGChat"
+ set name = "Toggle VChat"
set category = "Preferences"
- set desc = "Toggles TGChat. Reloading TGChat and/or reconnecting required to affect changes."
+ set desc = "Toggles VChat. Reloading VChat and/or reconnecting required to affect changes."
var/pref_path = /datum/client_preference/vchat_enable
toggle_preference(pref_path)
SScharacter_setup.queue_preferences_save(prefs)
- to_chat(src, "You have toggled TGChat [is_preference_enabled(pref_path) ? "on" : "off"]. \
- You will have to reload TGChat and/or reconnect to the server for these changes to take place. \
- TGChat message persistence is not guaranteed if you change this again before the start of the next round.")
+ to_chat(src, "You have toggled VChat [is_preference_enabled(pref_path) ? "on" : "off"]. \
+ You will have to reload VChat and/or reconnect to the server for these changes to take place. \
+ VChat message persistence is not guaranteed if you change this again before the start of the next round.")
/client/verb/toggle_tgui_inputlock()
set name = "Toggle TGUI Input Lock"
diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm
index 759d17d892..f40deb8f6b 100644
--- a/code/modules/clothing/masks/miscellaneous.dm
+++ b/code/modules/clothing/masks/miscellaneous.dm
@@ -341,17 +341,7 @@
"X" = image(icon = src.icon, icon_state = "xmask"),
"Bugeyes" = image(icon = src.icon, icon_state = "bugmask"),
"Double" = image(icon = src.icon, icon_state = "doublemask"),
- "Mark" = image(icon = src.icon, icon_state = "markmask"),
- "Line" = image(icon = src.icon, icon_state = "linemask"),
- "Minus" = image(icon = src.icon, icon_state = "minusmask"),
- "Four" = image(icon = src.icon, icon_state = "fourmask"),
- "Diamond" = image(icon = src.icon, icon_state = "diamondmask"),
- "Cat" = image(icon = src.icon, icon_state = "catmask"),
- "Big Eyes" = image(icon = src.icon, icon_state = "bigeyemask"),
- "Good" = image(icon = src.icon, icon_state = "goodmask"),
- "Bad" = image(icon = src.icon, icon_state = "badmask"),
- "Happy" = image(icon = src.icon, icon_state = "happymask"),
- "Sad" = image(icon = src.icon, icon_state = "sadmask")
+ "Mark" = image(icon = src.icon, icon_state = "markmask")
)
/obj/item/clothing/mask/paper/attack_self(mob/user)
@@ -363,11 +353,7 @@
"Sleeping" ="sleepingmask", "Heart" = "heartmask", "Core" = "coremask",
"Plus" = "plusmask", "Square" ="squaremask", "Bullseye" = "bullseyemask",
"Vertical" = "verticalmask", "Horizontal" = "horizontalmask", "X" ="xmask",
- "Bugeyes" = "bugmask", "Double" = "doublemask", "Mark" = "markmask",
- "Line" = "linemask", "Minus" = "minusmask", "Four" = "fourmask",
- "Diamond" = "diamondmask", "Cat" = "catmask", "Big Eyes" = "bigeyemask",
- "Good" = "goodmask", "Bad" = "badmask", "Happy" = "happymask", "Sad" = "sadmask"
- )
+ "Bugeyes" = "bugmask", "Double" = "doublemask", "Mark" = "markmask")
var/choice = show_radial_menu(user, src, papermask_designs, custom_check = FALSE, radius = 36, require_near = TRUE)
@@ -419,4 +405,4 @@
desc = "100% synthetic \"Country Girls LLC.\" brand mouth wheat. Warning: not for actual consumption."
icon_state = "mouthwheat"
w_class = ITEMSIZE_SMALL
- body_parts_covered = 0
+ body_parts_covered = 0
\ No newline at end of file
diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm
index 8eefbcbcea..0c70e7d5f5 100644
--- a/code/modules/clothing/under/accessories/accessory.dm
+++ b/code/modules/clothing/under/accessories/accessory.dm
@@ -562,10 +562,6 @@
name = "white neck gaiter"
icon_state = "gaiter_snow"
-/obj/item/clothing/accessory/gaiter/half //functions like a gaiter
- name = "black half-mask"
- icon_state = "half_mask"
-
/*
* Pride Pins
*/
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index e55c8587ba..e378c8f195 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -614,16 +614,6 @@
desc = "Just looking at this makes you want to sing."
icon_state = "ysing"
-/obj/item/clothing/under/dress/tabard
- name = "white tabard-dress"
- desc = "A gold-trimmed white tabard-dress with a large V-shaped boob window. For when you want to show off your hips and look classy at the same time."
- icon_state = "white_tabard"
-
-/obj/item/clothing/under/dress/tabard/black
- name = "black tabard-dress"
- desc = "A gold-trimmed black tabard-dress with a large circular boob window. For when you want to show off your hips and look classy at the same time."
- icon_state = "black_tabard"
-
/*
* Wedding Stuff
*/
diff --git a/code/modules/clothing/under/shorts.dm b/code/modules/clothing/under/shorts.dm
index 18622cb4d8..d168ddc1eb 100644
--- a/code/modules/clothing/under/shorts.dm
+++ b/code/modules/clothing/under/shorts.dm
@@ -75,10 +75,6 @@
name = "black jeans short shorts"
icon_state = "black_shorts_f"
-/obj/item/clothing/under/shorts/black/ripped
- name = "black ripped shorts"
- icon_state = "black_shorts_ripped"
-
/obj/item/clothing/under/shorts/jeans/grey
name = "grey jeans shorts"
icon_state = "greyshorts"
diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm
index b3bb6d1655..6b2998c2b3 100644
--- a/code/modules/events/electrical_storm.dm
+++ b/code/modules/events/electrical_storm.dm
@@ -46,7 +46,7 @@
if(shield_gen.deal_shield_damage(30 * severity, SHIELD_DAMTYPE_EM) <= SHIELD_BREACHED_MINOR)
return
if(!valid_apcs.len)
- // log_debug("No valid APCs found for electrical storm event ship=[victim]!") // Let's not spam poor people with debug logs on (me)
+ log_debug("No valid APCs found for electrical storm event ship=[victim]!")
return
var/list/picked_apcs = list()
for(var/i=0, i< severity * 2, i++) // up to 2/4/6 APCs per tick depending on severity
diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm
index b084efe773..a8668e561a 100644
--- a/code/modules/events/radiation_storm.dm
+++ b/code/modules/events/radiation_storm.dm
@@ -34,8 +34,6 @@
SSradiation.z_radiate(locate(1, 1, z), radiation_level, 1)
for(var/mob/living/carbon/C in living_mob_list)
- if(!(C.z in using_map.station_levels) || C.isSynthetic() || isbelly(C.loc))
- continue
var/area/A = get_area(C)
if(!A)
continue
@@ -43,9 +41,7 @@
continue
if(istype(C,/mob/living/carbon/human))
var/mob/living/carbon/human/H = C
- var/chance = 5.0
- chance -= (chance / 100) * C.getarmor(null, "rad")
- if(prob(chance))
+ if(prob(5))
if (prob(75))
randmutb(H) // Applies bad mutation
domutcheck(H,null,MUTCHK_FORCED)
diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm
index 9ee08bf8a7..4918df39f0 100644
--- a/code/modules/mob/living/living_movement.dm
+++ b/code/modules/mob/living/living_movement.dm
@@ -276,8 +276,8 @@ default behaviour is:
is_shifted = FALSE
pixel_x = default_pixel_x
pixel_y = default_pixel_y
- layer = initial(layer)
- plane = initial(plane)
+ layer = MOB_LAYER
+ plane = MOB_PLANE
// End VOREstation edit
if(pulling) // we were pulling a thing and didn't lose it during our move.
diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm
index 978f8744c8..48d5b89cee 100644
--- a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm
+++ b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm
@@ -1,4 +1,4 @@
-/obj/item/weapon/melee/dogborg/jaws/big
+/obj/item/weapon/dogborg/jaws/big
name = "combat jaws"
icon = 'icons/mob/dogborg_vr.dmi'
icon_state = "jaws"
@@ -9,7 +9,7 @@
attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced")
w_class = ITEMSIZE_NORMAL
-/obj/item/weapon/melee/dogborg/jaws/small
+/obj/item/weapon/dogborg/jaws/small
name = "puppy jaws"
icon = 'icons/mob/dogborg_vr.dmi'
icon_state = "smalljaws"
@@ -21,7 +21,7 @@
w_class = ITEMSIZE_NORMAL
var/emagged = 0
-/obj/item/weapon/melee/dogborg/jaws/small/attack_self(mob/user)
+/obj/item/weapon/dogborg/jaws/small/attack_self(mob/user)
var/mob/living/silicon/robot/R = user
if(R.emagged || R.emag_items)
emagged = !emagged
@@ -48,7 +48,7 @@
update_icon()
// Baton chompers
-/obj/item/weapon/melee/borg_combat_shocker
+/obj/item/weapon/borg_combat_shocker
name = "combat shocker"
icon = 'icons/mob/dogborg_vr.dmi'
icon_state = "combatshocker"
@@ -61,7 +61,7 @@
var/charge_cost = 15
var/dogborg = FALSE
-/obj/item/weapon/melee/borg_combat_shocker/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
+/obj/item/weapon/borg_combat_shocker/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
if(isrobot(target))
return ..()
@@ -237,7 +237,6 @@
icon_state = "synthtongue"
hitsound = 'sound/effects/attackblob.ogg'
var/emagged = 0
- var/busy = 0 //prevents abuse and runtimes
/obj/item/device/robot_tongue/New()
..()
@@ -264,27 +263,21 @@
return
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
- if(busy)
- to_chat(user, "You are already licking something else.")
- return
if(user.client && (target in user.client.screen))
to_chat(user, "You need to take \the [target.name] off before cleaning it!")
return
else if(istype(target,/obj/item))
if(istype(target,/obj/item/trash))
user.visible_message("[user] nibbles away at \the [target.name].", "You begin to nibble away at \the [target.name]...")
- busy = 1
if(do_after (user, 50))
user.visible_message("[user] finishes eating \the [target.name].", "You finish eating \the [target.name].")
to_chat(user, "You finish off \the [target.name].")
qdel(target)
var/mob/living/silicon/robot/R = user
R.cell.charge += 250
- busy = 0
return
if(istype(target,/obj/item/weapon/cell))
user.visible_message("[user] begins cramming \the [target.name] down its throat.", "You begin cramming \the [target.name] down your throat...")
- busy = 1
if(do_after (user, 50))
user.visible_message("[user] finishes gulping down \the [target.name].", "You finish swallowing \the [target.name].")
to_chat(user, "You finish off \the [target.name], and gain some charge!")
@@ -292,7 +285,6 @@
var/obj/item/weapon/cell/C = target
R.cell.charge += C.charge / 3
qdel(target)
- busy = 0
return
else if(ishuman(target))
if(src.emagged)
@@ -348,13 +340,12 @@
recharge_time = 10 //Takes ten ticks to recharge a shot, so don't waste them all!
//cell_type = null //Same cell as a taser until edits are made.
-/obj/item/weapon/melee/combat_borgblade
+/obj/item/weapon/combat_borgblade
name = "energy blade"
icon = 'icons/mob/dogborg_vr.dmi'
icon_state = "swordtail"
desc = "A glowing dagger. It appears to be extremely sharp."
- force = 35 //Takes 3 hits to 100-0
- armor_penetration = 70
+ force = 20 //Takes 5 hits to 100-0
sharp = TRUE
edge = TRUE
throwforce = 0 //This shouldn't be thrown in the first place.
@@ -475,4 +466,4 @@
var/armor_soak = get_armor_soak(T, "melee")
T.apply_damage(20, HALLOSS,, armor_block, armor_soak)
if(prob(75)) //75% chance to stun for 5 seconds, really only going to be 4 bcus click cooldown+animation.
- T.apply_effect(5, WEAKEN, armor_block)
+ T.apply_effect(5, WEAKEN, armor_block)
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 8c235d87ab..438bc52a27 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -341,7 +341,6 @@
hands.icon_state = get_hud_module_icon()
feedback_inc("cyborg_[lowertext(modtype)]",1)
updatename()
- hud_used.update_robot_modules_display()
notify_ai(ROBOT_NOTIFICATION_NEW_MODULE, module.name)
/mob/living/silicon/robot/proc/update_braintype()
@@ -768,7 +767,6 @@
to_chat(usr, "You apply the upgrade to [src]!")
usr.drop_item()
U.loc = src
- hud_used.update_robot_modules_display()
else
to_chat(usr, "Upgrade error!")
@@ -806,13 +804,12 @@
/mob/living/silicon/robot/proc/module_reset()
transform_with_anim() //VOREStation edit: sprite animation
uneq_all()
- hud_used.update_robot_modules_display(TRUE)
modtype = initial(modtype)
hands.icon_state = get_hud_module_icon()
notify_ai(ROBOT_NOTIFICATION_MODULE_RESET, module.name)
module.Reset(src)
- module.Destroy()
+ qdel(module)
module = null
updatename("Default")
@@ -1377,7 +1374,6 @@
laws.show_laws(src)
to_chat(src, "ALERT: [user.real_name] is your new master. Obey your new laws and [TU.his] commands.")
update_icon()
- hud_used.update_robot_modules_display()
else
to_chat(user, "You fail to hack [src]'s interface.")
to_chat(src, "Hack attempt detected.")
diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station.dm b/code/modules/mob/living/silicon/robot/robot_modules/station.dm
index 2622ff4ae3..62a965d089 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm
@@ -760,10 +760,10 @@ var/global/list/robot_modules = list(
src.modules += new /obj/item/weapon/gun/energy/laser/mounted(src)
src.modules += new /obj/item/weapon/gun/energy/taser/mounted/cyborg/ertgun(src)
src.modules += new /obj/item/weapon/pickaxe/plasmacutter/borg(src)
- src.modules += new /obj/item/weapon/melee/combat_borgblade(src)
+ src.modules += new /obj/item/weapon/combat_borgblade(src)
src.modules += new /obj/item/borg/combat/shield(src)
src.modules += new /obj/item/borg/combat/mobility(src)
- src.modules += new /obj/item/weapon/melee/borg_combat_shocker(src)
+ src.modules += new /obj/item/weapon/borg_combat_shocker(src)
src.modules += new /obj/item/device/ticket_printer(src)
src.emag += new /obj/item/weapon/gun/energy/lasercannon/mounted(src)
diff --git a/code/modules/mob/living/silicon/robot/sprites/combat.dm b/code/modules/mob/living/silicon/robot/sprites/combat.dm
index a451a70e79..32c8b09fcc 100644
--- a/code/modules/mob/living/silicon/robot/sprites/combat.dm
+++ b/code/modules/mob/living/silicon/robot/sprites/combat.dm
@@ -101,11 +101,11 @@
..()
- var/obj/item/weapon/melee/combat_borgblade/CBB = locate() in module.modules
+ var/obj/item/weapon/combat_borgblade/CBB = locate() in module.modules
if(CBB)
CBB.name = "sword tail"
CBB.desc = "A glowing dagger normally attached to the end of a cyborg's tail. It appears to be extremely sharp."
- var/obj/item/weapon/melee/borg_combat_shocker/BCS = locate() in module.modules
+ var/obj/item/weapon/borg_combat_shocker/BCS = locate() in module.modules
if(BCS)
BCS.name = "combat jaws"
BCS.desc = "Shockingly chompy!"
@@ -132,4 +132,4 @@
sprite_hud_icon_state = "ert"
rest_sprite_options = list("Default")
has_eye_sprites = FALSE
- has_eye_light_sprites = TRUE
+ has_eye_light_sprites = TRUE
\ No newline at end of file
diff --git a/code/modules/mob/mob_grab_specials.dm b/code/modules/mob/mob_grab_specials.dm
index 4ac26e4e13..a7a9d45db7 100644
--- a/code/modules/mob/mob_grab_specials.dm
+++ b/code/modules/mob/mob_grab_specials.dm
@@ -1,3 +1,4 @@
+
/obj/item/weapon/grab/proc/inspect_organ(mob/living/carbon/human/H, mob/user, var/target_zone)
var/obj/item/organ/external/E = H.get_organ(target_zone)
@@ -162,12 +163,12 @@
if(can_eat)
var/mob/living/carbon/attacker = user
- user.visible_message("[user] is attempting to devour [target]!")
+ user.visible_message("[user] is attempting to devour [target]!")
if(can_eat == 2)
if(!do_mob(user, target)||!do_after(user, 30)) return
else
if(!do_mob(user, target)||!do_after(user, 70)) return
- user.visible_message("[user] devours [target]!")
+ user.visible_message("[user] devours [target]!")
target.loc = user
attacker.stomach_contents.Add(target)
- qdel(src)
+ qdel(src)
\ No newline at end of file
diff --git a/code/modules/mob/new_player/login.dm b/code/modules/mob/new_player/login.dm
index d2be34e921..1fe31e965d 100644
--- a/code/modules/mob/new_player/login.dm
+++ b/code/modules/mob/new_player/login.dm
@@ -86,7 +86,7 @@ var/obj/effect/lobby_image = new /obj/effect/lobby_image
tgui_alert_async(src, message, "BYOND Client Version Warning")
// So we can be more wordy and give links.
- to_chat(src, "Your client version has known issues. Please consider using a different version: https://www.byond.com/download/build/.")
+ to_chat(src, "Your client version has known issues. Please consider using a different version: http://www.byond.com/download/build/.")
var/chat_message = ""
if(config.suggested_byond_version)
chat_message += "We suggest using version [config.suggested_byond_version]."
diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm
index fdae1d2f36..feef4aef9b 100644
--- a/code/modules/mob/new_player/sprite_accessories.dm
+++ b/code/modules/mob/new_player/sprite_accessories.dm
@@ -234,48 +234,6 @@
species_allowed = list(SPECIES_HUMAN,SPECIES_PROMETHEAN,SPECIES_HUMAN_VATBORN,SPECIES_UNATHI)
flags = HAIR_TIEABLE
-/datum/sprite_accessory/hair/bobcutovereye
- name = "Bobcut Over Eye"
- icon_state = "hair_bobcutovereye1"
-
-/datum/sprite_accessory/hair/bobcutovereye2
- name = "Bobcut Over Eye 2"
- icon_state = "hair_bobcutovereye2"
-
-/datum/sprite_accessory/hair/bobcutovereye3
- name = "Bobcut Over Eye 3"
- icon_state = "hair_bobcutovereye3"
-
-/datum/sprite_accessory/hair/bonnie
- name = "Bonnie"
- icon_state = "hair_bonnie"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/bonniealt
- name = "Bonnie Alt"
- icon_state = "hair_bonniealt"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/bonnielong
- name = "Bonnie, Long"
- icon_state = "hair_bonnie_long"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/bonniealtlong
- name = "Bonnie Alt, Long"
- icon_state = "hair_bonniealt_long"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/bonnieshort
- name = "Bonnie, Short"
- icon_state = "hair_bonnie_short"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/bonniealtshort
- name = "Bonnie Alt, Short"
- icon_state = "hair_bonniealt_short"
- flags = HAIR_TIEABLE
-
/datum/sprite_accessory/hair/bowl
name = "Bowl"
icon_state = "hair_bowlcut"
@@ -449,10 +407,6 @@
name = "Dave"
icon_state = "hair_dave"
-/datum/sprite_accessory/hair/dawn
- name = "Dawn"
- icon_state = "hair_dawn"
-
/datum/sprite_accessory/hair/devillock
name = "Devil Lock"
icon_state = "hair_devilock"
@@ -490,10 +444,6 @@
icon_state = "hair_drillruru"
flags = HAIR_TIEABLE
-/datum/sprite_accessory/hair/eagle
- name = "Eagle"
- icon_state = "hair_eagle"
-
/datum/sprite_accessory/hair/elize
name = "Elize"
icon_state = "hair_elize"
@@ -563,11 +513,6 @@
gender = MALE
flags = HAIR_VERY_SHORT
-/datum/sprite_accessory/hair/falcon
- name = "Falcon"
- icon_state = "hair_falcon"
- flags = HAIR_TIEABLE
-
/datum/sprite_accessory/hair/familyman
name = "Family Man"
icon_state = "hair_thefamilyman"
@@ -610,15 +555,6 @@
name = "Flow Hair"
icon_state = "hair_f"
-/datum/sprite_accessory/hair/fluffy
- name = "Fluffy"
- icon_state = "hair_fluffy"
-
-/datum/sprite_accessory/hair/fluffylong
- name = "Fluffy, Long"
- icon_state = "hair_fluffy_long"
- flags = HAIR_TIEABLE
-
/datum/sprite_accessory/hair/longfringe
name = "Fringe Long"
icon_state = "hair_longfringe"
@@ -700,16 +636,6 @@
name = "Hitop"
icon_state = "hair_hitop"
-/datum/sprite_accessory/hair/hummingbird
- name = "Hummingbird"
- icon_state = "hair_hummingbird"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/inari
- name = "Inari"
- icon_state = "hair_inari"
- flags = HAIR_TIEABLE
-
/datum/sprite_accessory/hair/jade
name = "Jade"
icon_state = "hair_jade"
@@ -790,16 +716,6 @@
icon_state = "hair_hbraid"
flags = HAIR_TIEABLE
-/datum/sprite_accessory/hair/macaw
- name = "Macaw"
- icon_state = "hair_macaw"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/magpie
- name = "Magpie"
- icon_state = "hair_magpie"
- flags = HAIR_TIEABLE
-
/datum/sprite_accessory/hair/manbun
name = "Manbun"
icon_state = "hair_manbun"
@@ -900,21 +816,6 @@
name = "Overeye Very Short"
icon_state = "hair_veryshortovereye"
-/datum/sprite_accessory/hair/overear
- name = "Over Ear, Right"
- icon_state = "hair_overear1"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/overear2
- name = "Over Ear, Left"
- icon_state = "hair_overear2"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/owl
- name = "Owl"
- icon_state = "hair_owl"
- flags = HAIR_TIEABLE
-
/datum/sprite_accessory/hair/parted
name = "Parted"
icon_state = "hair_parted"
@@ -978,16 +879,6 @@
icon_state = "hair_spikyponytail"
flags = HAIR_TIEABLE
-/datum/sprite_accessory/hair/thinponytail
- name = "Ponytail Thin"
- icon_state = "hair_thinponytail"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/thinponytaillong
- name = "Ponytail Thin, Long"
- icon_state = "hair_thinponytail_long"
- flags = HAIR_TIEABLE
-
/datum/sprite_accessory/hair/poofy
name = "Poofy"
icon_state = "hair_poofy"
@@ -998,11 +889,6 @@
icon_state = "hair_poofy2"
flags = HAIR_TIEABLE
-/datum/sprite_accessory/hair/princess
- name = "Princess"
- icon_state = "hair_princess"
- flags = HAIR_TIEABLE
-
/datum/sprite_accessory/hair/proper
name = "Proper"
icon_state = "hair_proper"
@@ -1179,16 +1065,6 @@
icon_state = "hair_spikey"
species_allowed = list(SPECIES_HUMAN,SPECIES_PROMETHEAN,SPECIES_HUMAN_VATBORN,SPECIES_UNATHI)
-/datum/sprite_accessory/hair/starling
- name = "Starling"
- icon_state = "hair_starling"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/stork
- name = "Stork"
- icon_state = "hair_stork"
- flags = HAIR_TIEABLE
-
/datum/sprite_accessory/hair/straightlong
name = "Straight Long"
icon_state = "hair_straightlong"
@@ -1211,11 +1087,6 @@
icon_state = "hair_sweptfringe"
flags = HAIR_TIEABLE
-/datum/sprite_accessory/hair/taro
- name = "Taro"
- icon_state = "hair_taro"
- flags = HAIR_TIEABLE
-
/datum/sprite_accessory/hair/terezi
name = "Terezi"
icon_state = "hair_terezi"
@@ -1264,21 +1135,6 @@
icon_state = "hair_twintail"
flags = HAIR_TIEABLE
-/datum/sprite_accessory/hair/twintails
- name = "Twintails"
- icon_state = "hair_twintails"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/twintailslong
- name = "Twintails, Long"
- icon_state = "hair_twintails_long"
- flags = HAIR_TIEABLE
-
-/datum/sprite_accessory/hair/twintailsshort
- name = "Twintails, Short"
- icon_state = "hair_twintails_short"
- flags = HAIR_TIEABLE
-
/datum/sprite_accessory/hair/twinbob
name = "Twinbun Bob"
icon_state = "hair_bunbob"
diff --git a/code/modules/mob/new_player/sprite_accessories_tail.dm b/code/modules/mob/new_player/sprite_accessories_tail.dm
index a4f1e457f5..1821ffe6aa 100644
--- a/code/modules/mob/new_player/sprite_accessories_tail.dm
+++ b/code/modules/mob/new_player/sprite_accessories_tail.dm
@@ -380,54 +380,6 @@
do_colouration = 1
color_blend_mode = ICON_MULTIPLY
-/datum/sprite_accessory/tail/bigsnaketail
- name = "large snake tail (vwag)"
- desc = ""
- icon_state = "bigsnaketail"
- do_colouration = TRUE
- color_blend_mode = ICON_MULTIPLY
- ani_state = "bigsnaketail_w"
-
-/datum/sprite_accessory/tail/bigsnaketailstripes
- name = "large snake tail, striped (vwag)"
- desc = ""
- icon_state = "bigsnaketailstripes"
- extra_overlay = "bigsnaketailstripes-tips"
- do_colouration = TRUE
- color_blend_mode = ICON_MULTIPLY
- ani_state = "bigsnaketailstripes_w"
- extra_overlay_w = "bigsnaketailstripes-tips_w"
-
-/datum/sprite_accessory/tail/bigsnaketailstripes_alt
- name = "large snake tail, striped, alt (vwag)"
- desc = ""
- icon_state = "bigsnaketailstripesalt"
- extra_overlay = "bigsnaketailstripesalt-tips"
- do_colouration = TRUE
- color_blend_mode = ICON_MULTIPLY
- ani_state = "bigsnaketailstripesalt_w"
- extra_overlay_w = "bigsnaketailstripesalt-tips_w"
-
-/datum/sprite_accessory/tail/bigsnaketaildual
- name = "large snake tail, dual color (vwag)"
- desc = ""
- icon_state = "bigsnaketaildual"
- extra_overlay = "bigsnaketaildual-tips"
- do_colouration = TRUE
- color_blend_mode = ICON_MULTIPLY
- ani_state = "bigsnaketaildual_w"
- extra_overlay_w = "bigsnaketaildual-tips_w"
-
-/datum/sprite_accessory/tail/bigsnaketailunder
- name = "large snake tail, under (vwag)"
- desc = ""
- icon_state = "bigsnaketailunder"
- extra_overlay = "bigsnaketailunder-tips"
- do_colouration = TRUE
- color_blend_mode = ICON_MULTIPLY
- ani_state = "bigsnaketailunder_w"
- extra_overlay_w = "bigsnaketailunder-tips_w"
-
/datum/sprite_accessory/tail/vulpan_alt
name = "vulpkanin alt style, colorable"
desc = ""
@@ -1057,4 +1009,4 @@
extra_overlay = "zorgoia_fluff"
extra_overlay2 = "zorgoia_fluff_top"
do_colouration = 1
- color_blend_mode = ICON_MULTIPLY
+ color_blend_mode = ICON_MULTIPLY
\ No newline at end of file
diff --git a/code/modules/nifsoft/software/13_soulcatcher.dm b/code/modules/nifsoft/software/13_soulcatcher.dm
index 20172ac924..e6223a85a7 100644
--- a/code/modules/nifsoft/software/13_soulcatcher.dm
+++ b/code/modules/nifsoft/software/13_soulcatcher.dm
@@ -72,15 +72,11 @@
/datum/nifsoft/soulcatcher/proc/notify_into(var/message)
var/sound = nif.good_sound
- to_chat(nif.human,
- type = MESSAGE_TYPE_NIF,
- html = "\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] Soulcatcher displays, \"[message]\"")
+ to_chat(nif.human,"\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] Soulcatcher displays, \"[message]\"")
nif.human << sound
for(var/mob/living/carbon/brain/caught_soul/CS as anything in brainmobs)
- to_chat(CS,
- type = MESSAGE_TYPE_NIF,
- html = "\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] Soulcatcher displays, \"[message]\"")
+ to_chat(CS,"\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] Soulcatcher displays, \"[message]\"")
CS << sound
/datum/nifsoft/soulcatcher/proc/say_into(var/message, var/mob/living/sender, var/mob/eyeobj)
@@ -92,13 +88,9 @@
//Not AR Projecting
else
- to_chat(nif.human,
- type = MESSAGE_TYPE_NIF,
- html = "\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] speaks, \"[message]\"")
+ to_chat(nif.human,"\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] speaks, \"[message]\"")
for(var/mob/living/carbon/brain/caught_soul/CS as anything in brainmobs)
- to_chat(CS,
- type = MESSAGE_TYPE_NIF,
- html = "\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] speaks, \"[message]\"")
+ to_chat(CS,"\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] speaks, \"[message]\"")
log_nsay(message,nif.human.real_name,sender)
@@ -111,13 +103,9 @@
//Not AR Projecting
else
- to_chat(nif.human,
- type = MESSAGE_TYPE_NIF,
- html = "\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] [message]")
+ to_chat(nif.human,"\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] [message]")
for(var/mob/living/carbon/brain/caught_soul/CS as anything in brainmobs)
- to_chat(CS,
- type = MESSAGE_TYPE_NIF,
- html = "\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] [message]")
+ to_chat(CS,"\[\icon[nif.big_icon][bicon(nif.big_icon)]NIF\] [sender_name] [message]")
log_nme(message,nif.human.real_name,sender)
diff --git a/code/modules/tgchat/README.md b/code/modules/tgchat/README.md
deleted file mode 100644
index 71acb47c45..0000000000
--- a/code/modules/tgchat/README.md
+++ /dev/null
@@ -1,30 +0,0 @@
-## /TG/ Chat
-
-/TG/ Chat, which will be referred to as TgChat from this point onwards, is a system in which we can send messages to clients in a controlled and semi-reliable manner. The standard way of sending messages to BYOND clients simply dumps whatever you output to them directly into their chat window, however BYOND allows us to load our own code on the client to change this behaviour in a way that allows us to do some pretty neat things.
-
-### Message Format
-
-TgChat handles sending messages from the server to the client through the use of JSON payloads, of which the format will change depending on the type of message and the intended client endpoint. An example of the payload for chat messages is as follows:
-```json
-{
- "sequence": 0,
- "content": {
- "type": ". . .", // ?optional
- "text": ". . .", // ?optional !atleast-one
- "html": ". . .", // ?optional !atleast-one
- "avoidHighlighting": 0 // ?optional
- },
-}
-```
-
-### Reliability
-
-In the past there have been issues where BYOND will silently and without reason lose a message we sent to the client, to detect this and recover from it seamlessly TgChat also has a baked in reliability layer. This reliability layer is very primitive, and simply keeps track of received sequence numbers. Should the client receive an unexpected sequence number TgChat asks the server to resend any missing packets.
-
-### Ping System
-
-TgChat supports a round trip time ping measurement, which is displayed to the client so they can know how long it takes for their commands and inputs to reach the server. This is done by sending the client a ping request, `ping/soft`, which tells the client to send a ping to the server. When the server receives said ping it sends a reply, `ping/reply`, to the client with a payload containing the current DateTime which the client can reference against the initial ping request.
-
-### Chat Tabs, Local Storage, and Highlighting
-
-To make organizing and managing chat easier and more functional for both players and admins, TgChat has the ability to filter out messages based on their primary tag, such as individual departmental radios, to a dedicated chat tab for easier reading and comprehension. These tabs can also be configured to highlist messages based on a simple keyword search. You can set a multitude of different keywords to search for and they will be highlighting for instant alerting of the client. Said tabs, highlighting rules, and your chat history will persist thanks to use of local storage on the client. Using local storage TgChat can ensure that your preferences are saved and maintained between client restarts and switching between other /TG/ servers. Local Storage is also used to keep your chat history aswell, should you need to scroll through your chat logs.
diff --git a/code/modules/tgchat/_legacy.dm b/code/modules/tgchat/_legacy.dm
deleted file mode 100644
index fe01936540..0000000000
--- a/code/modules/tgchat/_legacy.dm
+++ /dev/null
@@ -1,48 +0,0 @@
-/// Old VChat Code Stuff
-
-/* Old bicon code
-/proc/expire_bicon_cache(key)
- if(GLOB.bicon_cache[key])
- GLOB.bicon_cache -= key
- return TRUE
- return FALSE
-
-GLOBAL_LIST_EMPTY(bicon_cache) // Cache of the tag results, not the icons
-*/
-
-/proc/bicon(var/obj, var/use_class = 1, var/custom_classes = "")
- return icon2base64html(obj, custom_classes)
-
- /* Old bicon code
- var/class = use_class ? "class='icon misc [custom_classes]'" : null
- if(!obj)
- return
-
- // Try to avoid passing bicon an /icon directly. It is better to pass it an atom so it can cache.
- if(isicon(obj)) // Passed an icon directly, nothing to cache-key on, as icon refs get reused *often*
- return "
"
-
- // Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with.
- var/atom/A = obj
- var/key
- var/changes_often = ishuman(A) || isobserver(A) // If this ends up with more, move it into a proc or var on atom.
-
- if(changes_often)
- key = "\ref[A]"
- else
- key = "[istype(A.icon, /icon) ? "\ref[A.icon]" : A.icon]:[A.icon_state]"
-
- var/base64 = GLOB.bicon_cache[key]
- // Non-human atom, no cache
- if(!base64) // Doesn't exist, make it.
- base64 = icon2base64(A.examine_icon(), key)
- GLOB.bicon_cache[key] = base64
- if(changes_often)
- addtimer(CALLBACK(GLOBAL_PROC, .proc/expire_bicon_cache, key), 50 SECONDS, TIMER_UNIQUE)
-
- // May add a class to the img tag created by bicon
- if(use_class)
- class = "class='icon [A.icon_state] [custom_classes]'"
-
- return "
"
- */
diff --git a/code/modules/tgchat/message.dm b/code/modules/tgchat/message.dm
deleted file mode 100644
index 69d3a6faf5..0000000000
--- a/code/modules/tgchat/message.dm
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * Message-related procs
- *
- * Message format (/list):
- * - type - Message type, must be one of defines in `code/__DEFINES/chat.dm`
- * - text - Plain message text
- * - html - HTML message text
- * - Optional metadata, can be any key/value pair.
- *
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
- */
-
-/proc/message_to_html(message)
- // Here it is possible to add a switch statement
- // to custom-handle various message types.
- return message["html"] || message["text"]
diff --git a/code/modules/tgchat/to_chat.dm b/code/modules/tgchat/to_chat.dm
deleted file mode 100644
index ae434b36f1..0000000000
--- a/code/modules/tgchat/to_chat.dm
+++ /dev/null
@@ -1,85 +0,0 @@
-/*!
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
- */
-
-/**
- * Circumvents the message queue and sends the message
- * to the recipient (target) as soon as possible.
- */
-/proc/to_chat_immediate(
- target,
- html,
- type = null,
- text = null,
- avoid_highlighting = FALSE,
- // FIXME: These flags are now pointless and have no effect
- handle_whitespace = TRUE,
- trailing_newline = TRUE,
- confidential = FALSE
-)
- // Useful where the integer 0 is the entire message. Use case is enabling to_chat(target, some_boolean) while preventing to_chat(target, "")
- html = "[html]"
- text = "[text]"
-
- if(!target)
- return
- if(!html && !text)
- CRASH("Empty or null string in to_chat proc call.")
- if(target == world)
- target = GLOB.clients
-
- // Build a message
- var/message = list()
- if(type) message["type"] = type
- if(text) message["text"] = text
- if(html) message["html"] = html
- if(avoid_highlighting) message["avoidHighlighting"] = avoid_highlighting
-
- // send it immediately
- SSchat.send_immediate(target, message)
-
-/**
- * Sends the message to the recipient (target).
- *
- * Recommended way to write to_chat calls:
- * ```
- * to_chat(client,
- * type = MESSAGE_TYPE_INFO,
- * html = "You have found [object]")
- * ```
- */
-/proc/to_chat(
- target,
- html,
- type = null,
- text = null,
- avoid_highlighting = FALSE,
- // FIXME: These flags are now pointless and have no effect
- handle_whitespace = TRUE,
- trailing_newline = TRUE,
- confidential = FALSE
-)
- //if(isnull(Master) || !SSchat?.initialized || !MC_RUNNING(SSchat.init_stage))
- if(isnull(Master) || !SSchat?.subsystem_initialized)
- to_chat_immediate(target, html, type, text, avoid_highlighting)
- return
-
- // Useful where the integer 0 is the entire message. Use case is enabling to_chat(target, some_boolean) while preventing to_chat(target, "")
- html = "[html]"
- text = "[text]"
-
- if(!target)
- return
- if(!html && !text)
- CRASH("Empty or null string in to_chat proc call.")
- if(target == world)
- target = GLOB.clients
-
- // Build a message
- var/message = list()
- if(type) message["type"] = type
- if(text) message["text"] = text
- if(html) message["html"] = html
- if(avoid_highlighting) message["avoidHighlighting"] = avoid_highlighting
- SSchat.queue(target, message)
diff --git a/code/modules/tgui/tgui_window.dm b/code/modules/tgui/tgui_window.dm
index 73dfdf2803..180e18a518 100644
--- a/code/modules/tgui/tgui_window.dm
+++ b/code/modules/tgui/tgui_window.dm
@@ -380,8 +380,6 @@
// Resend the assets
for(var/asset in sent_assets)
send_asset(asset)
- if("chat/resend")
- SSchat.handle_resend(client, payload)
/datum/tgui_window/vv_edit_var(var_name, var_value)
return var_name != NAMEOF(src, id) && ..()
diff --git a/code/modules/tgui_panel/audio.dm b/code/modules/tgui_panel/audio.dm
deleted file mode 100644
index 32ecd93ab8..0000000000
--- a/code/modules/tgui_panel/audio.dm
+++ /dev/null
@@ -1,42 +0,0 @@
-/*!
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
- */
-
-/// Admin music volume, from 0 to 1.
-/client/var/admin_music_volume = 1
-
-/**
- * public
- *
- * Sends music data to the browser.
- *
- * Optional settings:
- * - pitch: the playback rate
- * - start: the start time of the sound
- * - end: when the musics stops playing
- *
- * required url string Must be an https URL.
- * optional extra_data list Optional settings.
- */
-/datum/tgui_panel/proc/play_music(url, extra_data)
- if(!is_ready())
- return
- if(!findtext(url, GLOB.is_http_protocol))
- return
- var/list/payload = list()
- if(length(extra_data) > 0)
- for(var/key in extra_data)
- payload[key] = extra_data[key]
- payload["url"] = url
- window.send_message("audio/playMusic", payload)
-
-/**
- * public
- *
- * Stops playing music through the browser.
- */
-/datum/tgui_panel/proc/stop_music()
- if(!is_ready())
- return
- window.send_message("audio/stopMusic")
diff --git a/code/modules/tgui_panel/external.dm b/code/modules/tgui_panel/external.dm
deleted file mode 100644
index a4ce4444ca..0000000000
--- a/code/modules/tgui_panel/external.dm
+++ /dev/null
@@ -1,45 +0,0 @@
-/*!
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
- */
-
-/client/var/datum/tgui_panel/tgui_panel
-
-/**
- * tgui panel / chat troubleshooting verb
- */
-/client/verb/fix_tgui_panel()
- set name = "Fix chat"
- set category = "OOC"
- var/action
- log_tgui(src, "Started fixing.", context = "verb/fix_tgui_panel")
-
- nuke_chat()
-
- // Failed to fix, using tgalert as fallback
- action = tgalert(src, "Did that work?", "", "Yes", "No, switch to old ui")
- if (action == "No, switch to old ui")
- winset(src, "output", "on-show=&is-disabled=0&is-visible=1")
- winset(src, "browseroutput", "is-disabled=1;is-visible=0")
- log_tgui(src, "Failed to fix.", context = "verb/fix_tgui_panel")
-
-/client/proc/nuke_chat()
- // Catch all solution (kick the whole thing in the pants)
- winset(src, "output", "on-show=&is-disabled=0&is-visible=1")
- winset(src, "browseroutput", "is-disabled=1;is-visible=0")
- if(!tgui_panel || !istype(tgui_panel))
- log_tgui(src, "tgui_panel datum is missing",
- context = "verb/fix_tgui_panel")
- tgui_panel = new(src)
- tgui_panel.initialize(force = TRUE)
- // Force show the panel to see if there are any errors
- winset(src, "output", "is-disabled=1&is-visible=0")
- winset(src, "browseroutput", "is-disabled=0;is-visible=1")
-
-/client/verb/refresh_tgui()
- set name = "Refresh TGUI"
- set category = "OOC"
-
- for(var/window_id in tgui_windows)
- var/datum/tgui_window/window = tgui_windows[window_id]
- window.reinitialize()
diff --git a/code/modules/tgui_panel/telemetry.dm b/code/modules/tgui_panel/telemetry.dm
deleted file mode 100644
index 4dabcbb01a..0000000000
--- a/code/modules/tgui_panel/telemetry.dm
+++ /dev/null
@@ -1,146 +0,0 @@
-/*!
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
- */
-
-/**
- * Maximum number of connection records allowed to analyze.
- * Should match the value set in the browser.
- */
-#define TGUI_TELEMETRY_MAX_CONNECTIONS 5
-
-/**
- * Maximum time allocated for sending a telemetry packet.
- */
-#define TGUI_TELEMETRY_RESPONSE_WINDOW (30 SECONDS)
-
-/// Time of telemetry request
-/datum/tgui_panel/var/telemetry_requested_at
-/// Time of telemetry analysis completion
-/datum/tgui_panel/var/telemetry_analyzed_at
-/// List of previous client connections
-/datum/tgui_panel/var/list/telemetry_connections
-
-/**
- * private
- *
- * Requests some telemetry from the client.
- */
-/datum/tgui_panel/proc/request_telemetry()
- telemetry_requested_at = world.time
- telemetry_analyzed_at = null
- window.send_message("telemetry/request", list(
- "limits" = list(
- "connections" = TGUI_TELEMETRY_MAX_CONNECTIONS,
- ),
- ))
-
-/**
- * private
- *
- * Analyzes a telemetry packet.
- *
- * Is currently only useful for detecting ban evasion attempts.
- */
-/datum/tgui_panel/proc/analyze_telemetry(payload)
- if(world.time > telemetry_requested_at + TGUI_TELEMETRY_RESPONSE_WINDOW)
- message_admins("[key_name(client)] sent telemetry outside of the allocated time window.")
- return
- if(telemetry_analyzed_at)
- message_admins("[key_name(client)] sent telemetry more than once.")
- return
- telemetry_analyzed_at = world.time
- if(!payload)
- return
- telemetry_connections = payload["connections"]
- var/len = length(telemetry_connections)
- if(len == 0)
- return
- if(len > TGUI_TELEMETRY_MAX_CONNECTIONS)
- message_admins("[key_name(client)] was kicked for sending a huge telemetry payload")
- qdel(client)
- return
-
- var/ckey = client?.ckey
- if (!ckey)
- return
-
- /* FIXME: Stuff we dont have > Can be reimplemented later on
- var/list/all_known_alts = GLOB.known_alts.load_known_alts()
- var/list/our_known_alts = list()
-
- for (var/known_alt in all_known_alts)
- if (known_alt[1] == ckey)
- our_known_alts += known_alt[2]
- else if (known_alt[2] == ckey)
- our_known_alts += known_alt[1]
-
- var/list/found
-
- var/list/query_data = list()
-
- for(var/i in 1 to len)
- if(QDELETED(client))
- // He got cleaned up before we were done
- return
- var/list/row = telemetry_connections[i]
-
- // Check for a malformed history object
- if (!row || row.len < 3 || (!row["ckey"] || !row["address"] || !row["computer_id"]))
- return
-
- if (!isnull(GLOB.round_id))
- query_data += list(list(
- "telemetry_ckey" = row["ckey"],
- "address" = row["address"],
- "computer_id" = row["computer_id"],
- ))
-
- if (row["ckey"] in our_known_alts)
- continue
-
- if (world.IsBanned(row["ckey"], row["address"], row["computer_id"], real_bans_only = TRUE))
- found = row
- break
-
- CHECK_TICK
-
- // This fucker has a history of playing on a banned account.
- if(found)
- var/msg = "[key_name(client)] has a banned account in connection history! (Matched: [found["ckey"]], [found["address"]], [found["computer_id"]])"
- message_admins(msg)
- send2tgs_adminless_only("Banned-user", msg)
- log_admin_private(msg)
- log_suspicious_login(msg, access_log_mirror = FALSE)
-
- // Only log them all at the end, since it's not as important as reporting an evader
- for (var/list/one_query as anything in query_data)
- var/datum/db_query/query = SSdbcore.NewQuery({"
- INSERT INTO [format_table_name("telemetry_connections")] (
- ckey,
- telemetry_ckey,
- address,
- computer_id,
- first_round_id,
- latest_round_id
- ) VALUES(
- :ckey,
- :telemetry_ckey,
- INET_ATON(:address),
- :computer_id,
- :round_id,
- :round_id
- ) ON DUPLICATE KEY UPDATE latest_round_id = :round_id
- "}, list(
- "ckey" = ckey,
- "telemetry_ckey" = one_query["telemetry_ckey"],
- "address" = one_query["address"],
- "computer_id" = one_query["computer_id"],
- "round_id" = GLOB.round_id,
- ))
- query.Execute()
- qdel(query)
- */
-
-#undef TGUI_TELEMETRY_MAX_CONNECTIONS
-#undef TGUI_TELEMETRY_RESPONSE_WINDOW
diff --git a/code/modules/tgui_panel/tgui_panel.dm b/code/modules/tgui_panel/tgui_panel.dm
deleted file mode 100644
index ffb31cd788..0000000000
--- a/code/modules/tgui_panel/tgui_panel.dm
+++ /dev/null
@@ -1,102 +0,0 @@
-/*!
- * Copyright (c) 2020 Aleksej Komarov
- * SPDX-License-Identifier: MIT
- */
-
-/**
- * tgui_panel datum
- * Hosts tgchat and other nice features.
- */
-/datum/tgui_panel
- var/client/client
- var/datum/tgui_window/window
- var/broken = FALSE
- var/initialized_at
- var/oldchat = FALSE
-
-/datum/tgui_panel/New(client/client, id)
- src.client = client
- window = new(client, id)
- window.subscribe(src, PROC_REF(on_message))
-
-/datum/tgui_panel/Del()
- window.unsubscribe(src)
- window.close()
- return ..()
-
-/**
- * public
- *
- * TRUE if panel is initialized and ready to receive messages.
- */
-/datum/tgui_panel/proc/is_ready()
- return !broken && window.is_ready()
-
-/**
- * public
- *
- * Initializes tgui panel.
- */
-/datum/tgui_panel/proc/initialize(force = FALSE)
- set waitfor = FALSE
- // Minimal sleep to defer initialization to after client constructor
- sleep(1 TICKS)
- initialized_at = world.time
- // Perform a clean initialization
- window.initialize(
- strict_mode = TRUE,
- assets = list(
- get_asset_datum(/datum/asset/simple/tgui_panel),
- ))
- window.send_asset(get_asset_datum(/datum/asset/simple/fontawesome))
- window.send_asset(get_asset_datum(/datum/asset/simple/tgfont))
- window.send_asset(get_asset_datum(/datum/asset/spritesheet/chat))
- // Other setup
- request_telemetry()
- addtimer(CALLBACK(src, PROC_REF(on_initialize_timed_out)), 5 SECONDS)
-
-/**
- * private
- *
- * Called when initialization has timed out.
- */
-/datum/tgui_panel/proc/on_initialize_timed_out()
- // Currently does nothing but sending a message to old chat.
- // SEND_TEXT(client, "Failed to load fancy chat, click HERE to attempt to reload it.")
-
-/**
- * private
- *
- * Callback for handling incoming tgui messages.
- */
-/datum/tgui_panel/proc/on_message(type, payload)
- if(type == "ready")
- broken = FALSE
- window.send_message("update", list(
- "config" = list(
- "client" = list(
- "ckey" = client.ckey,
- "address" = client.address,
- "computer_id" = client.computer_id,
- ),
- "window" = list(
- "fancy" = FALSE,
- "locked" = FALSE,
- ),
- ),
- ))
- return TRUE
- if(type == "audio/setAdminMusicVolume")
- client.admin_music_volume = payload["volume"]
- return TRUE
- if(type == "telemetry")
- analyze_telemetry(payload)
- return TRUE
-
-/**
- * public
- *
- * Sends a round restart notification.
- */
-/datum/tgui_panel/proc/send_roundrestart()
- window.send_message("roundrestart")
diff --git a/code/modules/vchat/css/ss13styles.css b/code/modules/vchat/css/ss13styles.css
index 08cea0956a..0b0f14425c 100644
--- a/code/modules/vchat/css/ss13styles.css
+++ b/code/modules/vchat/css/ss13styles.css
@@ -129,7 +129,6 @@ body.inverted {
.emote {color: #000000;}
.inverted .emote {color: #FFFFFF;}
.alert {color: #ff0000;}
-.valert {color: #ff0000;}
h1.alert, h2.alert {color: #000000;}
/* VOREStation Add Start */
.nif {}
@@ -148,16 +147,12 @@ h1.alert, h2.alert {color: #000000;}
.critical {color: #ff0000; font-weight: bold; font-size: 150%;}
.danger {color: #ff0000; font-weight: bold;}
-.vdanger {color: #ff0000; font-weight: bold;}
.warning {color: #ff0000; font-style: italic;}
-.vwarning {color: #ff0000; font-style: italic;}
.rose {color: #ff5050;}
.info {color: #0000CC;}
.inverted .info {color: #6060c9;} /* Dark mode */
.notice {color: #000099;}
.inverted .notice {color: #6060c9;} /* Dark mode */
-.vnotice {color: #000099;}
-.inverted .vnotice {color: #6060c9;} /* Dark mode */
.alium {color: #00ff00;}
.cult {color: #800080; font-weight: bold; font-style: italic;}
diff --git a/code/modules/vchat/js/vchat.js b/code/modules/vchat/js/vchat.js
index 414f047891..9b9f9b6dba 100644
--- a/code/modules/vchat/js/vchat.js
+++ b/code/modules/vchat/js/vchat.js
@@ -176,14 +176,6 @@ function start_vue() {
required: false,
admin: false
},
- {
- matches: ".valert, .vwarning, .vnotice, .vdanger",
- becomes: "vc_vore_message",
- pretty: "Vore Messages",
- tooltip: "Vore Messages",
- required: false,
- admin: false
- },
{
matches: ".filter_deadsay, .deadsay",
becomes: "vc_deadchat",
diff --git a/code/modules/vchat/js/vchat.min.js b/code/modules/vchat/js/vchat.min.js
index 16b7753747..4a220ec820 100644
--- a/code/modules/vchat/js/vchat.min.js
+++ b/code/modules/vchat/js/vchat.min.js
@@ -1 +1 @@
-!function(){var e=console.log;console.log=function(t){send_debug(t),e.apply(console,arguments)};var t=console.error;console.error=function(e){send_debug(e),t.apply(console,arguments)},window.onerror=function(e,t,s,a,n){var o="";return n&&n.stack&&(o=n.stack),send_debug(e+" ("+t+"@"+s+":"+a+") "+n+"|UA: "+navigator.userAgent+"|Stack: "+o),!0}}();var vueapp,vchat_opts={msBeforeDropped:3e4,cookiePrefix:"vst-",alwaysShow:["vc_looc","vc_system"],vchatTabsVer:1},DARKMODE_COLORS={buttonBgColor:"#40628a",buttonTextColor:"#FFFFFF",windowBgColor:"#272727",highlightColor:"#009900",tabTextColor:"#FFFFFF",tabBackgroundColor:"#272727"},LIGHTMODE_COLORS={buttonBgColor:"none",buttonTextColor:"#000000",windowBgColor:"none",highlightColor:"#007700",tabTextColor:"#000000",tabBackgroundColor:"none"},set_storage=set_cookie,get_storage=get_cookie,domparser=new DOMParser;storageAvailable("localStorage")&&(set_storage=set_localstorage,get_storage=get_localstorage);var vchat_state={ready:!1,byond_ip:null,byond_cid:null,byond_ckey:null,lastPingReceived:0,latency_sent:0,lastId:0};function start_vchat(){start_vue(),vchat_state.ready=!0,push_Topic("done_loading"),push_Topic_showingnum(this.showingnum),doWinset("htmloutput",{"is-visible":!0}),doWinset("oldoutput",{"is-visible":!1}),doWinset("chatloadlabel",{"is-visible":!1}),setInterval(check_ping,vchat_opts.msBeforeDropped),send_debug("VChat Loaded!")}function start_vue(){vueapp=new Vue({el:"#app",data:{messages:[],shown_messages:[],unshown_messages:0,archived_messages:[],tabs:[{name:"Main",categories:[],immutable:!0,active:!0}],unread_messages:{},editing:!1,paused:!1,latency:0,reconnecting:!1,ext_styles:"",is_admin:!1,inverted:!1,crushing:3,animated:!1,fontsize:.9,lineheight:130,showingnum:200,type_table:[{matches:".filter_say, .say, .emote, .emotesubtle",becomes:"vc_localchat",pretty:"Local Chat",tooltip:"In-character local messages (say, emote, etc)",required:!1,admin:!1},{matches:".filter_radio, .alert, .syndradio, .centradio, .airadio, .entradio, .comradio, .secradio, .engradio, .medradio, .sciradio, .supradio, .srvradio, .expradio, .radio, .deptradio, .newscaster",becomes:"vc_radio",pretty:"Radio Comms",tooltip:"All departments of radio messages",required:!1,admin:!1},{matches:".filter_notice, .notice:not(.pm), .adminnotice, .info, .sinister, .cult",becomes:"vc_info",pretty:"Notices",tooltip:"Non-urgent messages from the game and items",required:!1,admin:!1},{matches:".filter_warning, .warning:not(.pm), .critical, .userdanger, .italics",becomes:"vc_warnings",pretty:"Warnings",tooltip:"Urgent messages from the game and items",required:!1,admin:!1},{matches:".valert, .vwarning, .vnotice, .vdanger",becomes:"vc_vore_message",pretty:"Vore Messages",tooltip:"Vore Messages",required:!1,admin:!1},{matches:".filter_deadsay, .deadsay",becomes:"vc_deadchat",pretty:"Deadchat",tooltip:"All of deadchat",required:!1,admin:!1},{matches:".filter_pray",becomes:"vc_pray",pretty:"Pray",tooltip:"Prayer messages",required:!1,admin:!1},{matches:".ooc, .filter_ooc",becomes:"vc_globalooc",pretty:"Global OOC",tooltip:"The bluewall of global OOC messages",required:!1,admin:!1},{matches:".nif",becomes:"vc_nif",pretty:"NIF Messages",tooltip:"Messages from the NIF itself and people inside",required:!1,admin:!1},{matches:".psay, .pemote",becomes:"vc_pmessage",pretty:"Pred/Prey Messages",tooltip:"Messages from / to absorbed or dominated prey",required:!1,admin:!1},{matches:".mentor_channel, .mentor",becomes:"vc_mentor",pretty:"Mentor messages",tooltip:"Mentorchat and mentor pms",required:!1,admin:!1},{matches:".filter_pm, .pm",becomes:"vc_adminpm",pretty:"Admin PMs",tooltip:"Messages to/from admins ('adminhelps')",required:!1,admin:!1},{matches:".filter_ASAY, .admin_channel",becomes:"vc_adminchat",pretty:"Admin Chat",tooltip:"ASAY messages",required:!1,admin:!0},{matches:".filter_MSAY, .mod_channel",becomes:"vc_modchat",pretty:"Mod Chat",tooltip:"MSAY messages",required:!1,admin:!0},{matches:".filter_ESAY, .event_channel",becomes:"vc_eventchat",pretty:"Event Chat",tooltip:"ESAY messages",required:!1,admin:!0},{matches:".filter_combat, .danger",becomes:"vc_combat",pretty:"Combat Logs",tooltip:"Urist McTraitor has stabbed you with a knife!",required:!1,admin:!1},{matches:".filter_adminlogs, .log_message",becomes:"vc_adminlogs",pretty:"Admin Logs",tooltip:"ADMIN LOG: Urist McAdmin has jumped to coordinates X, Y, Z",required:!1,admin:!0},{matches:".filter_attacklogs",becomes:"vc_attacklogs",pretty:"Attack Logs",tooltip:"Urist McTraitor has shot John Doe",required:!1,admin:!0},{matches:".filter_debuglogs",becomes:"vc_debuglogs",pretty:"Debug Logs",tooltip:"DEBUG: SSPlanets subsystem Recover().",required:!1,admin:!0},{matches:".looc",becomes:"vc_looc",pretty:"Local OOC",tooltip:"Local OOC messages, always enabled",required:!0},{matches:".rlooc",becomes:"vc_rlooc",pretty:"Remote LOOC",tooltip:"Remote LOOC messages",required:!1,admin:!0},{matches:".boldannounce, .filter_system",becomes:"vc_system",pretty:"System Messages",tooltip:"Messages from your client, always enabled",required:!0},{matches:".unsorted",becomes:"vc_unsorted",pretty:"Unsorted",tooltip:"Messages that don't have any filters.",required:!1,admin:!1}]},mounted:function(){this.load_settings();var e=new XMLHttpRequest;e.open("GET","ss13styles.css"),e.onreadystatechange=(function(){this.ext_styles=e.responseText}).bind(this),e.send()},updated:function(){this.editing||this.paused||window.scrollTo(0,document.getElementById("messagebox").scrollHeight)},watch:{reconnecting:function(e,t){!0==e&&!1==t?this.internal_message("Your client has lost connection to the server, or there is severe lag. Your client will reconnect if possible."):!1==e&&!0==t&&this.internal_message("Your client has reconnected to the server.")},inverted:function(e){set_storage("darkmode",e),e?(document.body.classList.add("inverted"),switch_ui_mode(DARKMODE_COLORS)):(document.body.classList.remove("inverted"),switch_ui_mode(LIGHTMODE_COLORS))},crushing:function(e){set_storage("crushing",e)},animated:function(e){set_storage("animated",e)},fontsize:function(e,t){if(isNaN(e)){this.fontsize=t;return}e<.2?this.fontsize=.2:e>5&&(this.fontsize=5),set_storage("fontsize",e)},lineheight:function(e,t){if(!isFinite(e)){this.lineheight=t;return}e<100?this.lineheight=100:e>200&&(this.lineheight=200),set_storage("lineheight",e)},showingnum:function(e,t){if(!isFinite(e)){this.showingnum=t;return}(e=Math.floor(e))<50?this.showingnum=50:e>2e3&&(this.showingnum=2e3),set_storage("showingnum",this.showingnum),push_Topic_showingnum(this.showingnum),this.attempt_archive()},current_categories:function(e,t){e.length&&this.apply_filter(e)}},computed:{active_tab:function(){return this.tabs.find(function(e){return e.active})},ping_classes:function(){return this.latency?"?"==this.latency?"grey":this.latency<0?"red":this.latency<=200?"green":this.latency<=400?"yellow":"grey":this.reconnecting?"red":"green"},current_categories:function(){return this.active_tab==this.tabs[0]?[]:this.active_tab.categories.concat(vchat_opts.alwaysShow)}},methods:{load_settings:function(){this.inverted=get_storage("darkmode",!1),this.crushing=get_storage("crushing",3),this.animated=get_storage("animated",!1),this.fontsize=get_storage("fontsize",.9),this.lineheight=get_storage("lineheight",130),this.showingnum=get_storage("showingnum",200),isNaN(this.crushing)&&(this.crushing=3),isNaN(this.fontsize)&&(this.fontsize=.9),this.load_tabs()},load_tabs:function(){var e=get_storage("tabs");if(e){var t=JSON.parse(e);if(!t.version||!t.tabs){this.internal_message("There was a problem loading your tabs. Any new ones you make will be saved, however.");return}if(!t.version==vchat_opts.vchatTabsVer){this.internal_message("Your saved tabs are for an older version of VChat and must be recreated, sorry.");return}this.tabs.push.apply(this.tabs,t.tabs)}},save_tabs:function(){var e={version:vchat_opts.vchatTabsVer,tabs:[]};this.tabs.forEach(function(t){if(!t.immutable){var s=t.name,a=[];t.categories.forEach(function(e){a.push(e)}),e.tabs.push({name:s,categories:a,immutable:!1,active:!1})}}),set_storage("tabs",JSON.stringify(e))},switchtab:function(e){e!=this.active_tab&&(this.active_tab.active=!1,e.active=!0,e.categories.forEach(function(e){this.unread_messages[e]=0},this),this.apply_filter(this.current_categories))},editmode:function(){this.editing=!this.editing,this.save_tabs()},pause:function(){this.paused=!this.paused},newtab:function(){this.tabs.push({name:"New Tab",categories:[],immutable:!1,active:!1}),this.switchtab(this.tabs[this.tabs.length-1])},renametab:function(){if(!this.active_tab.immutable){var e=this.active_tab,t=window.prompt("Type the desired tab name:",e.name);null!==t&&""!==t&&null!==e&&(e.name=t)}},deltab:function(e){e||(e=this.active_tab),!e.immutable&&(this.switchtab(this.tabs[0]),this.tabs.splice(this.tabs.indexOf(e),1))},movetab:function(e,t){if(e&&!e.immutable){var s=this.tabs.indexOf(e);this.tabs.splice(s+t,0,this.tabs.splice(s,1)[0])}},tab_unread_count:function(e){var t=0,s=this.unread_messages;return e.categories.find(function(e){s[e]&&(t+=s[e])}),t},tab_unread_categories:function(e){var t=!1,s=this.unread_messages;return e.categories.find(function(e){if(s[e])return t=!0,!0}),{red:t,grey:!t}},attempt_archive:function(){if(this.messages.length>this.showingnum){var e=this.messages.splice(0,20);Array.prototype.push.apply(this.archived_messages,e)}},apply_filter:function(e){this.shown_messages.splice(0),this.unshown_messages=0,this.messages.forEach(function(t){e.indexOf(t.category)>-1&&this.shown_messages.push(t)},this),this.archived_messages.forEach(function(t){e.indexOf(t.category)>-1&&this.unshown_messages++},this)},add_message:function(e){let t={time:e.time,category:"error",content:e.message,repeats:1};if(t.category=this.get_category(t.content),"vc_unsorted"==t.category&&(t.content=""+t.content+""),this.crushing){let s=this.messages.slice(-this.crushing);for(let a=s.length-1;a>=0;a--){let n=s[a];n.content==t.content&&(t.repeats+=n.repeats,this.messages.splice(this.messages.indexOf(n),1))}}t.content=t.content.replace(/(\b(https?):\/\/[\-A-Z0-9+&@#\/%?=~_|!:,.;]*[\-A-Z0-9+&@#\/%=~_|])/img,'$1'),this.current_categories.length&&0>this.current_categories.indexOf(t.category)?(isNaN(this.unread_messages[t.category])&&(this.unread_messages[t.category]=0),this.unread_messages[t.category]+=1):this.current_categories.length&&this.shown_messages.push(t),t.id=++vchat_state.lastId,this.attempt_archive(),this.messages.push(t)},internal_message:function(e){let t={time:this.messages.length?this.messages.slice(-1).time+1:0,category:"vc_system",content:"[VChat Internal] "+e+""};t.id=++vchat_state.lastId,this.messages.push(t)},on_mouseup:function(e){let t=e.target;"getSelection"in window&&!1===window.getSelection().isCollapsed||t&&("INPUT"===t.tagName||"TEXTAREA"===t.tagName)||(focusMapWindow(),e.preventDefault(),e.target.click())},click_message:function(e){let t=e.target;if("A"===t.tagName){e.stopPropagation(),e.preventDefault?e.preventDefault():e.returnValue=!1;var s=t.getAttribute("href");"?"==s[0]||s.length>=8&&"byond://"==s.substring(0,8)?window.location=s:window.location="byond://?action=openLink&link="+encodeURIComponent(s)}},get_category:function(e){if(!vchat_state.ready){push_Topic("not_ready");return}let t=domparser.parseFromString(e,"text/html").querySelector("span"),s="vc_unsorted";return t&&this.type_table.find(function(e){if(t.msMatchesSelector(e.matches))return s=e.becomes,!0}),s},save_chatlog:function(){var e="