diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 82633fdc70..f67f095a4f 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,6 +1,3 @@
-[Feature Freeze!]: # We are currently not considering any balance or antagonist oriented pull requests. Full details, as well as ways to bypass this freeze, are available here https://github.com/tgstation/tgstation/pull/28223
-
-
[Changelogs]: # (Please make a changelog if you're adding, removing or changing content that'll affect players. This includes, but is not limited to, new features, sprites, sounds; balance changes; map edits and important fixes)
[]: # (See here for how to easily make a changelog: https://github.com/tgstation/tgstation/wiki/Changelogs. An example changelog has been provided below. Please edit or remove)
diff --git a/SQL/database_changelog.txt.rej b/SQL/database_changelog.txt.rej
new file mode 100644
index 0000000000..1b201ec4aa
--- /dev/null
+++ b/SQL/database_changelog.txt.rej
@@ -0,0 +1,15 @@
+diff a/SQL/database_changelog.txt b/SQL/database_changelog.txt (rejected hunks)
+@@ -1,10 +1,10 @@
+ Any time you make a change to the schema files, remember to increment the database schema version. Generally increment the minor number, major should be reserved for significant changes to the schema. Both values go up to 255.
+
+-The latest database version is 3.1; The query to update the schema revision table is:
++The latest database version is 3.0; The query to update the schema revision table is:
+
+-UPDATE `schema_revision` SET major = 3, minor = 1 LIMIT 1;
++INSERT INTO `schema_revision` (`major`, `minor`) VALUES (3, 0);
+ or
+-UPDATE `SS13_schema_revision` SET major = 3, minor = 1 LIMIT 1;
++INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (3, 0);
+
+ ----------------------------------------------------
+
diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index bf4263ffe6..c89e4e0422 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -60788,9 +60788,6 @@
/turf/open/floor/plasteel,
/area/science/robotics/lab)
"cHY" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 3e19f173a4..72f9a75ebd 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -7457,9 +7457,6 @@
/turf/open/floor/plating,
/area/maintenance/port/fore)
"aqr" = (
-/turf/open/floor/plating{
- icon_state = "panelscorched"
- },
/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -112682,9 +112679,6 @@
/turf/open/floor/plating,
/area/engine/atmospherics_engine)
"ept" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
/obj/effect/turf_decal/stripes/line{
dir = 9
},
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index 60495dcf55..020a963662 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -5039,7 +5039,6 @@
name = "Detective Privacy Blast door"
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plating,
/area/security/detectives_office)
"aix" = (
@@ -32004,7 +32003,6 @@
"bcM" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel/vault{
dir = 5
},
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index 4cc0b5c158..b4b78673a1 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -49675,7 +49675,7 @@
/turf/open/floor/plating,
/area/maintenance/department/engine)
"cdF" = (
-/obj/structure/closet/secure_closet/miner,
+/obj/structure/closet/secure_closet/miner/unlocked,
/turf/open/floor/plating,
/area/shuttle/auxillary_base)
"cdG" = (
diff --git a/apc_repair.dmi b/apc_repair.dmi
new file mode 100644
index 0000000000..6e861eef61
Binary files /dev/null and b/apc_repair.dmi differ
diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm
index 82d030bf08..24e10a24d1 100644
--- a/code/__DEFINES/logging.dm
+++ b/code/__DEFINES/logging.dm
@@ -1,15 +1,16 @@
//Investigate logging defines
-#define INVESTIGATE_ATMOS "atmos"
-#define INVESTIGATE_BOTANY "botany"
-#define INVESTIGATE_CARGO "cargo"
-#define INVESTIGATE_EXPERIMENTOR "experimentor"
-#define INVESTIGATE_GRAVITY "gravity"
-#define INVESTIGATE_RECORDS "records"
-#define INVESTIGATE_SINGULO "singulo"
-#define INVESTIGATE_SUPERMATTER "supermatter"
-#define INVESTIGATE_TELESCI "telesci"
-#define INVESTIGATE_WIRES "wires"
+#define INVESTIGATE_ATMOS "atmos"
+#define INVESTIGATE_BOTANY "botany"
+#define INVESTIGATE_CARGO "cargo"
+#define INVESTIGATE_EXPERIMENTOR "experimentor"
+#define INVESTIGATE_GRAVITY "gravity"
+#define INVESTIGATE_RECORDS "records"
+#define INVESTIGATE_SINGULO "singulo"
+#define INVESTIGATE_SUPERMATTER "supermatter"
+#define INVESTIGATE_TELESCI "telesci"
+#define INVESTIGATE_WIRES "wires"
#define INVESTIGATE_PORTAL "portals"
+#define INVESTIGATE_HALLUCINATIONS "hallucinations"
//Individual logging defines
#define INDIVIDUAL_ATTACK_LOG "Attack log"
diff --git a/code/__DEFINES/logging.dm.rej b/code/__DEFINES/logging.dm.rej
new file mode 100644
index 0000000000..6a7a358a9c
--- /dev/null
+++ b/code/__DEFINES/logging.dm.rej
@@ -0,0 +1,9 @@
+diff a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm (rejected hunks)
+@@ -9,6 +9,7 @@
+ #define INVESTIGATE_SUPERMATTER "supermatter"
+ #define INVESTIGATE_TELESCI "telesci"
+ #define INVESTIGATE_WIRES "wires"
++#define INVESTIGATE_HALLUCINATIONS "hallucinations"
+
+ //Individual logging defines
+ #define INDIVIDUAL_ATTACK_LOG "Attack log"
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 6a932ead4a..4342766be7 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -8,7 +8,7 @@
//You can use these defines to get the typepath of the currently running proc/verb (yes procs + verbs are objects)
/* eg:
/mob/living/carbon/human/death()
- world << THIS_PROC_TYPE_STR //You can only output the string versions
+ to_chat(world, THIS_PROC_TYPE_STR) //You can only output the string versions
Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a string with () (eg: the _WITH_ARGS defines) to make it look nicer)
*/
#define THIS_PROC_TYPE .....
@@ -350,6 +350,7 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
//debug printing macros
#define debug_world(msg) if (GLOB.Debug2) to_chat(world, "DEBUG: [msg]")
+#define debug_usr(msg) if (GLOB.Debug2&&usr) to_chat(usr, "DEBUG: [msg]")
#define debug_admins(msg) if (GLOB.Debug2) to_chat(GLOB.admins, "DEBUG: [msg]")
#define debug_world_log(msg) if (GLOB.Debug2) log_world("DEBUG: [msg]")
diff --git a/code/__DEFINES/server_tools.dm b/code/__DEFINES/server_tools.dm
index 4624c5914f..a4afa58a87 100644
--- a/code/__DEFINES/server_tools.dm
+++ b/code/__DEFINES/server_tools.dm
@@ -4,6 +4,9 @@
#define IRC_STATUS_THROTTLE 5
+#define PR_ANNOUNCEMENTS_PER_ROUND 5 //The number of unique PR announcements allowed per round
+ //This makes sure that a single person can only spam 3 reopens and 3 closes before being ignored
+
//keep these in sync with TGS3
#define SERVICE_WORLD_PARAM "server_service"
#define SERVICE_PR_TEST_JSON "..\\..\\prtestjob.json"
@@ -17,7 +20,7 @@
#define SERVICE_CMD_NAME_CHECK "namecheck"
#define SERVICE_CMD_ADMIN_WHO "adminwho"
-//#define SERVICE_CMD_PARAM_KEY //defined in __compile_options.dm
+#define SERVICE_CMD_PARAM_KEY "serviceCommsKey"
#define SERVICE_CMD_PARAM_COMMAND "command"
#define SERVICE_CMD_PARAM_MESSAGE "message"
#define SERVICE_CMD_PARAM_TARGET "target"
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index 9c64fb8b74..9646f03252 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -320,7 +320,7 @@
return r
// Returns the key based on the index
-#define KEYBYINDEX(L, index) (((index <= L:len) && (index > 0)) ? L[index] : null)
+#define KEYBYINDEX(L, index) (((index <= length(L)) && (index > 0)) ? L[index] : null)
/proc/count_by_type(list/L, type)
var/i = 0
@@ -468,7 +468,7 @@
. |= key_list[key]
//Picks from the list, with some safeties, and returns the "default" arg if it fails
-#define DEFAULTPICK(L, default) ((islist(L) && L:len) ? pick(L) : default)
+#define DEFAULTPICK(L, default) ((islist(L) && length(L)) ? pick(L) : default)
#define LAZYINITLIST(L) if (!L) L = list()
#define UNSETEMPTY(L) if (L && !L.len) L = null
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!L.len) { L = null; } }
diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm
index 2dd2e42129..05b6aa1a15 100644
--- a/code/__HELPERS/_logging.dm
+++ b/code/__HELPERS/_logging.dm
@@ -1,3 +1,10 @@
+//wrapper macros for easier grepping
+#define DIRECT_OUTPUT(A, B) A << B
+#define SEND_IMAGE(target, image) DIRECT_OUTPUT(target, image)
+#define SEND_SOUND(target, sound) DIRECT_OUTPUT(target, sound)
+#define SEND_TEXT(target, text) DIRECT_OUTPUT(target, text)
+#define WRITE_FILE(file, text) DIRECT_OUTPUT(file, text)
+
//print a warning message to world.log
#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [src] usr: [usr].")
/proc/warning(msg)
@@ -20,13 +27,13 @@
/proc/log_admin(text)
GLOB.admin_log.Add(text)
if (config.log_admin)
- GLOB.world_game_log << "\[[time_stamp()]]ADMIN: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]ADMIN: [text]")
//Items using this proc are stripped from public logs - use with caution
/proc/log_admin_private(text)
GLOB.admin_log.Add(text)
if (config.log_admin)
- GLOB.world_game_log << "\[[time_stamp()]]ADMINPRIVATE: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]ADMINPRIVATE: [text]")
/proc/log_adminsay(text)
if (config.log_adminchat)
@@ -38,65 +45,65 @@
/proc/log_game(text)
if (config.log_game)
- GLOB.world_game_log << "\[[time_stamp()]]GAME: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]GAME: [text]")
/proc/log_vote(text)
if (config.log_vote)
- GLOB.world_game_log << "\[[time_stamp()]]VOTE: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]VOTE: [text]")
/proc/log_access(text)
if (config.log_access)
- GLOB.world_game_log << "\[[time_stamp()]]ACCESS: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]ACCESS: [text]")
/proc/log_say(text)
if (config.log_say)
- GLOB.world_game_log << "\[[time_stamp()]]SAY: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]SAY: [text]")
/proc/log_prayer(text)
if (config.log_prayer)
- GLOB.world_game_log << "\[[time_stamp()]]PRAY: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]PRAY: [text]")
/proc/log_law(text)
if (config.log_law)
- GLOB.world_game_log << "\[[time_stamp()]]LAW: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]LAW: [text]")
/proc/log_ooc(text)
if (config.log_ooc)
- GLOB.world_game_log << "\[[time_stamp()]]OOC: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]OOC: [text]")
/proc/log_whisper(text)
if (config.log_whisper)
- GLOB.world_game_log << "\[[time_stamp()]]WHISPER: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]WHISPER: [text]")
/proc/log_emote(text)
if (config.log_emote)
- GLOB.world_game_log << "\[[time_stamp()]]EMOTE: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]EMOTE: [text]")
/proc/log_attack(text)
if (config.log_attack)
- GLOB.world_attack_log << "\[[time_stamp()]]ATTACK: [text]"
+ WRITE_FILE(GLOB.world_attack_log, "\[[time_stamp()]]ATTACK: [text]")
/proc/log_pda(text)
if (config.log_pda)
- GLOB.world_game_log << "\[[time_stamp()]]PDA: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]PDA: [text]")
/proc/log_comment(text)
if (config.log_pda)
//reusing the PDA option because I really don't think news comments are worth a config option
- GLOB.world_game_log << "\[[time_stamp()]]COMMENT: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]COMMENT: [text]")
/proc/log_chat(text)
if (config.log_pda)
- GLOB.world_game_log << "\[[time_stamp()]]CHAT: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]CHAT: [text]")
/proc/log_sql(text)
if(config.sql_enabled)
- GLOB.world_game_log << "\[[time_stamp()]]SQL: [text]"
+ WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]SQL: [text]")
//This replaces world.log so it displays both in DD and the file
/proc/log_world(text)
- GLOB.world_runtime_log << text
- world.log << text
+ WRITE_FILE(GLOB.world_runtime_log, text)
+ SEND_TEXT(world.log, text)
// Helper procs for building detailed log lines
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index d150e86f45..9b1507771a 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -418,7 +418,7 @@
/proc/showCandidatePollWindow(mob/M, poll_time, Question, list/candidates, ignore_category, time_passed, flashwindow = TRUE)
set waitfor = 0
- M << 'sound/misc/notice2.ogg' //Alerting them to their consideration
+ SEND_SOUND(M, 'sound/misc/notice2.ogg') //Alerting them to their consideration
if(flashwindow)
window_flash(M.client)
switch(ignore_category ? askuser(M,Question,"Please answer in [poll_time/10] seconds!","Yes","No","Never for this round", StealFocus=0, Timeout=poll_time) : askuser(M,Question,"Please answer in [poll_time/10] seconds!","Yes","No", StealFocus=0, Timeout=poll_time))
@@ -426,7 +426,7 @@
to_chat(M, "Choice registered: Yes.")
if(time_passed + poll_time <= world.time)
to_chat(M, "Sorry, you answered too late to be considered!")
- M << 'sound/machines/buzz-sigh.ogg'
+ SEND_SOUND(M, 'sound/machines/buzz-sigh.ogg')
candidates -= M
else
candidates += M
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index 04ea69a43f..b245b1f146 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -167,7 +167,7 @@ mob
Output_Icon()
set name = "2. Output Icon"
- to_chat(src, "Icon is: [bicon(getFlatIcon(src))]")
+ to_chat(src, "Icon is: [icon2base64html(getFlatIcon(src))]")
Label_Icon()
set name = "3. Label Icon"
@@ -712,7 +712,8 @@ The _flatIcons list is a cache for generated icon files.
if(!current)
curIndex++ //Try the next layer
continue
- currentLayer = current:layer
+ var/image/I = current
+ currentLayer = I.layer
if(currentLayer<0) // Special case for FLY_LAYER
if(currentLayer <= -1000) return flat
if(pSet == 0) // Underlay
@@ -747,22 +748,22 @@ The _flatIcons list is a cache for generated icon files.
// Dimensions of overlay being added
var/{addX1;addX2;addY1;addY2}
- for(var/I in layers)
-
- if(I:alpha == 0)
+ for(var/V in layers)
+ var/image/I = V
+ if(I.alpha == 0)
continue
if(I == copy) // 'I' is an /image based on the object being flattened.
curblend = BLEND_OVERLAY
- add = icon(I:icon, I:icon_state, I:dir)
+ add = icon(I.icon, I.icon_state, I.dir)
else // 'I' is an appearance object.
add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend)
// Find the new dimensions of the flat icon to fit the added overlay
- addX1 = min(flatX1, I:pixel_x+1)
- addX2 = max(flatX2, I:pixel_x+add.Width())
- addY1 = min(flatY1, I:pixel_y+1)
- addY2 = max(flatY2, I:pixel_y+add.Height())
+ addX1 = min(flatX1, I.pixel_x+1)
+ addX2 = max(flatX2, I.pixel_x+add.Width())
+ addY1 = min(flatY1, I.pixel_y+1)
+ addY2 = max(flatY2, I.pixel_y+add.Height())
if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2)
// Resize the flattened icon so the new icon fits
@@ -771,7 +772,7 @@ The _flatIcons list is a cache for generated icon files.
flatY1=addY1;flatY2=addY2
// Blend the overlay into the flattened icon
- flat.Blend(add, blendMode2iconMode(curblend), I:pixel_x + 2 - flatX1, I:pixel_y + 2 - flatY1)
+ flat.Blend(add, blendMode2iconMode(curblend), I.pixel_x + 2 - flatX1, I.pixel_y + 2 - flatY1)
if(A.color)
flat.Blend(A.color, ICON_MULTIPLY)
@@ -782,10 +783,11 @@ The _flatIcons list is a cache for generated icon files.
/proc/getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N
var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A.
- for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it.
- if(I:layer>A.layer)
+ for(var/V in A.overlays)//For every image in overlays. var/image/I will not work, don't try it.
+ var/image/I = V
+ if(I.layer>A.layer)
continue//If layer is greater than what we need, skip it.
- var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects.
+ var/icon/image_overlay = new(I.icon,I.icon_state)//Blend only works with icon objects.
//Also, icons cannot directly set icon_state. Slower than changing variables but whatever.
alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay.
return alpha_mask//And now return the mask.
@@ -993,3 +995,110 @@ GLOBAL_LIST_EMPTY(friendly_animal_types)
#undef FROZEN_RED_COLOR
#undef FROZEN_GREEN_COLOR
#undef FROZEN_BLUE_COLOR
+
+
+//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, iconKey = "misc")
+ if (!isicon(icon))
+ return FALSE
+ WRITE_FILE(GLOB.iconCache[iconKey], icon)
+ var/iconData = GLOB.iconCache.ExportText(iconKey)
+ var/list/partial = splittext(iconData, "{")
+ return replacetext(copytext(partial[2], 3, -5), "\n", "")
+
+/proc/icon2html(thing, target, icon_state, dir, frame = 1, moving = FALSE)
+ if (!thing)
+ return
+
+ var/key
+ var/icon/I = thing
+ if (!target)
+ return
+ if (target == world)
+ target = GLOB.clients
+
+ var/list/targets
+ if (!islist(target))
+ targets = list(target)
+ else
+ targets = target
+ if (!targets.len)
+ return
+ if (!isicon(I))
+ if (isfile(thing)) //special snowflake
+ var/name = sanitize_filename("[generate_asset_name(thing)].png")
+ register_asset(name, thing)
+ for (var/thing2 in targets)
+ send_asset(thing2, key, FALSE)
+ return "
"
+ var/atom/A = thing
+ if (isnull(dir))
+ dir = A.dir
+ if (isnull(icon_state))
+ icon_state = A.icon_state
+ I = A.icon
+ if (ishuman(thing)) // Shitty workaround for a BYOND issue.
+ var/icon/temp = I
+ I = icon()
+ I.Insert(temp, dir = SOUTH)
+ dir = SOUTH
+ else
+ if (isnull(dir))
+ dir = SOUTH
+ if (isnull(icon_state))
+ icon_state = ""
+
+ I = icon(I, icon_state, dir, frame, moving)
+
+ key = "[generate_asset_name(I)].png"
+ register_asset(key, I)
+ for (var/thing2 in targets)
+ send_asset(thing2, key, FALSE)
+
+ return "
"
+
+/proc/icon2base64html(thing)
+ if (!thing)
+ return
+ var/static/list/bicon_cache = list()
+ if (isicon(thing))
+ var/icon/I = thing
+ var/icon_base64 = icon2base64(I)
+
+ if (I.Height() > world.icon_size || I.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(I)
+
+
+ return "
"
+
+ // Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with.
+ var/atom/A = thing
+ var/key = "[istype(A.icon, /icon) ? "\ref[A.icon]" : A.icon]:[A.icon_state]"
+
+
+ if (!bicon_cache[key]) // Doesn't exist, make it.
+ var/icon/I = icon(A.icon, A.icon_state, SOUTH, 1)
+ if (ishuman(thing)) // Shitty workaround for a BYOND issue.
+ var/icon/temp = I
+ I = icon()
+ I.Insert(temp, dir = SOUTH)
+
+ bicon_cache[key] = icon2base64(I, key)
+
+ 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)
+ if (!thing)
+ return
+
+ if (isicon(thing))
+ return icon2html(thing, target)
+
+ var/icon/I = getFlatIcon(thing)
+ return icon2html(I, target)
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 924f8daf08..cb64f3fb22 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -1,6 +1,3 @@
-//wrapper macro for sending images that makes grepping easy
-#define SEND_IMAGE(target, image) target << image
-
/proc/random_blood_type()
return pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm
index 70bb8b2db6..a617437ac3 100644
--- a/code/__HELPERS/priority_announce.dm
+++ b/code/__HELPERS/priority_announce.dm
@@ -24,11 +24,12 @@
announcement += "
[html_encode(text)]
"
announcement += "
"
+ var/s = sound(sound)
for(var/mob/M in GLOB.player_list)
if(!isnewplayer(M) && M.can_hear())
to_chat(M, announcement)
if(M.client.prefs.toggles & SOUND_ANNOUNCEMENTS)
- M << sound(sound)
+ SEND_SOUND(M, s)
/proc/print_command_report(text = "", title = null, announce=TRUE)
if(!title)
@@ -55,6 +56,6 @@
to_chat(M, "[title]
[message]
")
if(M.client.prefs.toggles & SOUND_ANNOUNCEMENTS)
if(alert)
- M << sound('sound/misc/notice1.ogg')
+ SEND_SOUND(M, sound('sound/misc/notice1.ogg'))
else
- M << sound('sound/misc/notice2.ogg')
+ SEND_SOUND(M, sound('sound/misc/notice2.ogg'))
diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm
index cd5d0c6af5..53691d122e 100644
--- a/code/__HELPERS/text.dm
+++ b/code/__HELPERS/text.dm
@@ -45,6 +45,9 @@
index = findtext(t, char, index+1)
return t
+/proc/sanitize_filename(t)
+ return sanitize_simple(t, list("\n"="", "\t"="", "/"="", "\\"="", "?"="", "%"="", "*"="", ":"="", "|"="", "\""="", "<"="", ">"=""))
+
//Runs byond's sanitization proc along-side sanitize_simple
/proc/sanitize(t,list/repl_chars = null)
return html_encode(sanitize_simple(t,repl_chars))
@@ -553,14 +556,14 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
var/list/tosend = list()
tosend["data"] = finalized
- log << json_encode(tosend)
+ WRITE_FILE(log, json_encode(tosend))
//Used for applying byonds text macros to strings that are loaded at runtime
/proc/apply_text_macros(string)
var/next_backslash = findtext(string, "\\")
if(!next_backslash)
return string
-
+
var/leng = length(string)
var/next_space = findtext(string, " ", next_backslash + 1)
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index aab766f9e4..8cb34e23b5 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -289,7 +289,7 @@ Turf and target are separate in case you want to teleport some distance from a t
var/list/pois = list()
for(var/mob/M in mobs)
if(skip_mindless && (!M.mind && !M.ckey))
- if(!isbot(M) && !istype(M, /mob/camera/))
+ if(!isbot(M) && !istype(M, /mob/camera) && !ismegafauna(M))
continue
if(M.client && M.client.holder && M.client.holder.fakekey) //stealthmins
continue
@@ -845,11 +845,11 @@ GLOBAL_LIST_INIT(WALLITEMS_INVERSE, typecacheof(list(
/obj/proc/atmosanalyzer_scan(datum/gas_mixture/air_contents, mob/user, obj/target = src)
var/obj/icon = target
- user.visible_message("[user] has used the analyzer on [bicon(icon)] [target].", "You use the analyzer on [bicon(icon)] [target].")
+ user.visible_message("[user] has used the analyzer on [icon2html(icon, viewers(src))] [target].", "You use the analyzer on [icon2html(icon, user)] [target].")
var/pressure = air_contents.return_pressure()
var/total_moles = air_contents.total_moles()
- to_chat(user, "Results of analysis of [bicon(icon)] [target].")
+ to_chat(user, "Results of analysis of [icon2html(icon, user)] [target].")
if(total_moles>0)
to_chat(user, "Pressure: [round(pressure,0.1)] kPa")
diff --git a/code/_compile_options.dm b/code/_compile_options.dm
index 964c956eca..a669f1b4f5 100644
--- a/code/_compile_options.dm
+++ b/code/_compile_options.dm
@@ -69,8 +69,6 @@
#error You need version 511 or higher
#endif
- #define SERVICE_CMD_PARAM_KEY "serviceCommsKey"
-
//Update this whenever the db schema changes
//make sure you add an update to the schema_version stable in the db changelog
#define DB_MAJOR_VERSION 3
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index c32c481291..abf2c1f937 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -275,7 +275,7 @@
if(M.config_tag)
if(!(M.config_tag in modes)) // ensure each mode is added only once
- GLOB.config_error_log << "Adding game mode [M.name] ([M.config_tag]) to configuration."
+ WRITE_FILE(GLOB.config_error_log, "Adding game mode [M.name] ([M.config_tag]) to configuration.")
modes += M.config_tag
mode_names[M.config_tag] = M.name
probabilities[M.config_tag] = M.probability
@@ -548,7 +548,7 @@
if("irc_announce_new_game")
irc_announce_new_game = TRUE
else
- GLOB.config_error_log << "Unknown setting in configuration: '[name]'"
+ WRITE_FILE(GLOB.config_error_log, "Unknown setting in configuration: '[name]'")
else if(type == "game_options")
switch(name)
@@ -611,13 +611,13 @@
if(mode_name in modes)
continuous[mode_name] = 1
else
- GLOB.config_error_log << "Unknown continuous configuration definition: [mode_name]."
+ WRITE_FILE(GLOB.config_error_log, "Unknown continuous configuration definition: [mode_name].")
if("midround_antag")
var/mode_name = lowertext(value)
if(mode_name in modes)
midround_antag[mode_name] = 1
else
- GLOB.config_error_log << "Unknown midround antagonist configuration definition: [mode_name]."
+ WRITE_FILE(GLOB.config_error_log, "Unknown midround antagonist configuration definition: [mode_name].")
if("midround_antag_time_check")
midround_antag_time_check = text2num(value)
if("midround_antag_life_check")
@@ -633,9 +633,9 @@
if(mode_name in modes)
min_pop[mode_name] = text2num(mode_value)
else
- GLOB.config_error_log << "Unknown minimum population configuration definition: [mode_name]."
+ WRITE_FILE(GLOB.config_error_log, "Unknown minimum population configuration definition: [mode_name].")
else
- GLOB.config_error_log << "Incorrect minimum population configuration definition: [mode_name] [mode_value]."
+ WRITE_FILE(GLOB.config_error_log, "Incorrect minimum population configuration definition: [mode_name] [mode_value].")
if("max_pop")
var/pop_pos = findtext(value, " ")
var/mode_name = null
@@ -647,9 +647,9 @@
if(mode_name in modes)
max_pop[mode_name] = text2num(mode_value)
else
- GLOB.config_error_log << "Unknown maximum population configuration definition: [mode_name]."
+ WRITE_FILE(GLOB.config_error_log, "Unknown maximum population configuration definition: [mode_name].")
else
- GLOB.config_error_log << "Incorrect maximum population configuration definition: [mode_name] [mode_value]."
+ WRITE_FILE(GLOB.config_error_log, "Incorrect maximum population configuration definition: [mode_name] [mode_value].")
if("shuttle_refuel_delay")
shuttle_refuel_delay = text2num(value)
if("show_game_type_odds")
@@ -677,9 +677,9 @@
if(prob_name in modes)
probabilities[prob_name] = text2num(prob_value)
else
- GLOB.config_error_log << "Unknown game mode probability configuration definition: [prob_name]."
+ WRITE_FILE(GLOB.config_error_log, "Unknown game mode probability configuration definition: [prob_name].")
else
- GLOB.config_error_log << "Incorrect probability configuration definition: [prob_name] [prob_value]."
+ WRITE_FILE(GLOB.config_error_log, "Incorrect probability configuration definition: [prob_name] [prob_value].")
if("protect_roles_from_antagonist")
protect_roles_from_antagonist = 1
@@ -726,7 +726,7 @@
// Value is in the form "LAWID,NUMBER"
var/list/L = splittext(value, ",")
if(L.len != 2)
- GLOB.config_error_log << "Invalid LAW_WEIGHT: " + t
+ WRITE_FILE(GLOB.config_error_log, "Invalid LAW_WEIGHT: " + t)
continue
var/lawid = L[1]
var/weight = text2num(L[2])
@@ -781,7 +781,7 @@
if("mice_roundstart")
mice_roundstart = text2num(value)
else
- GLOB.config_error_log << "Unknown setting in configuration: '[name]'"
+ WRITE_FILE(GLOB.config_error_log, "Unknown setting in configuration: '[name]'")
else if(type == "policies")
policies[name] = value
@@ -839,7 +839,7 @@
if ("disabled")
currentmap = null
else
- GLOB.config_error_log << "Unknown command in map vote config: '[command]'"
+ WRITE_FILE(GLOB.config_error_log, "Unknown command in map vote config: '[command]'")
/datum/configuration/proc/loadsql(filename)
@@ -883,7 +883,7 @@
if("feedback_tableprefix")
global.sqlfdbktableprefix = value
else
- GLOB.config_error_log << "Unknown setting in configuration: '[name]'"
+ WRITE_FILE(GLOB.config_error_log, "Unknown setting in configuration: '[name]'")
/datum/configuration/proc/pick_mode(mode_name)
// I wish I didn't have to instance the game modes in order to look up
diff --git a/code/controllers/subsystem/assets.dm b/code/controllers/subsystem/assets.dm
index 607b142c59..fd27c9424f 100644
--- a/code/controllers/subsystem/assets.dm
+++ b/code/controllers/subsystem/assets.dm
@@ -3,12 +3,15 @@ SUBSYSTEM_DEF(assets)
init_order = INIT_ORDER_ASSETS
flags = SS_NO_FIRE
var/list/cache = list()
+ var/list/preload = list()
/datum/controller/subsystem/assets/Initialize(timeofday)
for(var/type in typesof(/datum/asset) - list(/datum/asset, /datum/asset/simple))
var/datum/asset/A = new type()
A.register()
+ preload = cache.Copy() //don't preload assets generated during the round
+
for(var/client/C in GLOB.clients)
- addtimer(CALLBACK(GLOBAL_PROC, .proc/getFilesSlow, C, cache, FALSE), 10)
+ addtimer(CALLBACK(GLOBAL_PROC, .proc/getFilesSlow, C, preload, FALSE), 10)
..()
diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm
index afa77b0207..3344afcaaa 100644
--- a/code/controllers/subsystem/blackbox.dm
+++ b/code/controllers/subsystem/blackbox.dm
@@ -250,7 +250,7 @@ SUBSYSTEM_DEF(blackbox)
return 0
return value
-/datum/feedback_variable/proc/get_variable()
+/datum/feedback_variable/proc/get_variable()
return variable
/datum/feedback_variable/proc/set_details(text)
@@ -260,12 +260,12 @@ SUBSYSTEM_DEF(blackbox)
/datum/feedback_variable/proc/add_details(text)
if (istext(text))
if (!details)
- details = text
+ details = "\"[text]\""
else
- details += " [text]"
+ details += " | \"[text]\""
-/datum/feedback_variable/proc/get_details()
+/datum/feedback_variable/proc/get_details()
return details
/datum/feedback_variable/proc/get_parsed()
- return list(variable,value,details)
+ return list(variable,value,details)
\ No newline at end of file
diff --git a/code/controllers/subsystem/pai.dm b/code/controllers/subsystem/pai.dm
index e5e83c85fc..2a1a04e21d 100644
--- a/code/controllers/subsystem/pai.dm
+++ b/code/controllers/subsystem/pai.dm
@@ -149,7 +149,6 @@ SUBSYSTEM_DEF(pai)
continue
if(!(ROLE_PAI in G.client.prefs.be_special))
continue
- //G << 'sound/misc/server-ready.ogg' //Alerting them to their consideration
to_chat(G, "[user] is requesting a pAI personality! Use the pAI button to submit yourself as one.")
addtimer(CALLBACK(src, .proc/spam_again), spam_delay)
var/list/available = list()
diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm
index f4eebe95be..a0dc7c526d 100644
--- a/code/controllers/subsystem/persistence.dm
+++ b/code/controllers/subsystem/persistence.dm
@@ -49,7 +49,7 @@ SUBSYSTEM_DEF(persistence)
satchel_string = pick_n_take(expanded_old_satchels)
old_secret_satchels = jointext(expanded_old_satchels,"#")
- secret_satchels[SSmapping.config.map_name] << old_secret_satchels
+ WRITE_FILE(secret_satchels[SSmapping.config.map_name], old_secret_satchels)
var/list/chosen_satchel = splittext(satchel_string,"|")
if(!chosen_satchel || isemptylist(chosen_satchel) || chosen_satchel.len != 3) //Malformed
@@ -171,7 +171,7 @@ SUBSYSTEM_DEF(persistence)
if(isemptylist(savable_obj))
continue
old_secret_satchels += "[F.x]|[F.y]|[pick(savable_obj)]#"
- secret_satchels[SSmapping.config.map_name] << old_secret_satchels
+ WRITE_FILE(secret_satchels[SSmapping.config.map_name], old_secret_satchels)
/datum/controller/subsystem/persistence/proc/CollectChiselMessages()
var/savefile/chisel_messages_sav = new /savefile("data/npc_saves/ChiselMessages.sav")
@@ -181,14 +181,14 @@ SUBSYSTEM_DEF(persistence)
log_world("Saved [saved_messages.len] engraved messages on map [SSmapping.config.map_name]")
- chisel_messages_sav[SSmapping.config.map_name] << json_encode(saved_messages)
+ WRITE_FILE(chisel_messages_sav[SSmapping.config.map_name], json_encode(saved_messages))
/datum/controller/subsystem/persistence/proc/SaveChiselMessage(obj/structure/chisel_message/M)
saved_messages += list(M.pack()) // dm eats one list
/datum/controller/subsystem/persistence/proc/CollectTrophies()
- trophy_sav << json_encode(saved_trophies)
+ WRITE_FILE(trophy_sav, json_encode(saved_trophies))
/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T)
if(!T.added_roundstart && T.showpiece)
diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm
index 8aff552076..d88d788d37 100644
--- a/code/controllers/subsystem/shuttle.dm
+++ b/code/controllers/subsystem/shuttle.dm
@@ -101,8 +101,6 @@ SUBSYSTEM_DEF(shuttle)
T.color = "#00ffff"
#endif
- //world.log << "[transit_turfs.len] transit turfs registered"
-
/datum/controller/subsystem/shuttle/fire()
for(var/thing in mobile)
if(!thing)
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index d897b290d4..e07d2db001 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -225,7 +225,7 @@ SUBSYSTEM_DEF(ticker)
round_start_time = world.time
to_chat(world, "Welcome to [station_name()], enjoy your stay!")
- world << sound('sound/ai/welcome.ogg')
+ SEND_SOUND(world, sound('sound/ai/welcome.ogg'))
current_state = GAME_STATE_PLAYING
Master.SetRunLevel(RUNLEVEL_GAME)
@@ -300,7 +300,7 @@ SUBSYSTEM_DEF(ticker)
if("nuclear emergency") //Nuke wasn't on station when it blew up
flick("intro_nuke",cinematic)
sleep(35)
- world << sound('sound/effects/explosionfar.ogg')
+ SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
station_explosion_detonation(bomb)
flick("station_intact_fade_red",cinematic)
cinematic.icon_state = "summary_nukefail"
@@ -308,12 +308,12 @@ SUBSYSTEM_DEF(ticker)
cinematic.icon_state = null
flick("intro_cult",cinematic)
sleep(25)
- world << sound('sound/magic/enter_blood.ogg')
+ SEND_SOUND(world, sound('sound/magic/enter_blood.ogg'))
sleep(28)
- world << sound('sound/machines/terminal_off.ogg')
+ SEND_SOUND(world, sound('sound/machines/terminal_off.ogg'))
sleep(20)
flick("station_corrupted",cinematic)
- world << sound('sound/effects/ghost.ogg')
+ SEND_SOUND(world, sound('sound/effects/ghost.ogg'))
actually_blew_up = FALSE
if("gang war") //Gang Domination (just show the override screen)
cinematic.icon_state = "intro_malf_still"
@@ -323,19 +323,19 @@ SUBSYSTEM_DEF(ticker)
if("fake") //The round isn't over, we're just freaking people out for fun
flick("intro_nuke",cinematic)
sleep(35)
- world << sound('sound/items/bikehorn.ogg')
+ SEND_SOUND(world, sound('sound/items/bikehorn.ogg'))
flick("summary_selfdes",cinematic)
actually_blew_up = FALSE
else
flick("intro_nuke",cinematic)
sleep(35)
- world << sound('sound/effects/explosionfar.ogg')
+ SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
station_explosion_detonation(bomb)
if(NUKE_MISS_STATION || NUKE_SYNDICATE_BASE) //nuke was nowhere nearby //TODO: a really distant explosion animation
sleep(50)
- world << sound('sound/effects/explosionfar.ogg')
+ SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
station_explosion_detonation(bomb)
actually_blew_up = station_missed == NUKE_SYNDICATE_BASE //don't kill everyone on station if it detonated off station
else //station was destroyed
@@ -346,42 +346,42 @@ SUBSYSTEM_DEF(ticker)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red",cinematic)
- world << sound('sound/effects/explosionfar.ogg')
+ SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
station_explosion_detonation(bomb)
cinematic.icon_state = "summary_nukewin"
if("AI malfunction") //Malf (screen,explosion,summary)
flick("intro_malf",cinematic)
sleep(76)
flick("station_explode_fade_red",cinematic)
- world << sound('sound/effects/explosionfar.ogg')
+ SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
station_explosion_detonation(bomb) //TODO: If we ever decide to actually detonate the vault bomb
cinematic.icon_state = "summary_malf"
if("blob") //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red",cinematic)
- world << sound('sound/effects/explosionfar.ogg')
+ SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
station_explosion_detonation(bomb) //TODO: no idea what this case could be
cinematic.icon_state = "summary_selfdes"
if("cult") //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red",cinematic)
- world << sound('sound/effects/explosionfar.ogg')
+ SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
station_explosion_detonation(bomb) //TODO: no idea what this case could be
cinematic.icon_state = "summary_cult"
if("no_core") //Nuke failed to detonate as it had no core
flick("intro_nuke",cinematic)
sleep(35)
flick("station_intact",cinematic)
- world << sound('sound/ambience/signal.ogg')
+ SEND_SOUND(world, sound('sound/ambience/signal.ogg'))
addtimer(CALLBACK(src, .proc/finish_cinematic, null, FALSE), 100)
return //Faster exit, since nothing happened
else //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red", cinematic)
- world << sound('sound/effects/explosionfar.ogg')
+ SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
station_explosion_detonation(bomb)
cinematic.icon_state = "summary_selfdes"
//If its actually the end of the round, wait for it to end.
@@ -636,7 +636,7 @@ SUBSYSTEM_DEF(ticker)
if(living_player_count() < config.hard_popcap)
if(next_in_line && next_in_line.client)
to_chat(next_in_line, "A slot has opened! You have approximately 20 seconds to join. \>\>Join Game\<\<")
- next_in_line << sound('sound/misc/notice1.ogg')
+ SEND_SOUND(next_in_line, sound('sound/misc/notice1.ogg'))
next_in_line.LateChoices()
return
queued_players -= next_in_line //Client disconnected, remove he
@@ -804,7 +804,7 @@ SUBSYSTEM_DEF(ticker)
/datum/controller/subsystem/ticker/proc/save_mode(the_mode)
var/F = file("data/mode.txt")
fdel(F)
- F << the_mode
+ WRITE_FILE(F, the_mode)
/datum/controller/subsystem/ticker/proc/SetRoundEndSound(the_sound)
set waitfor = FALSE
@@ -858,4 +858,4 @@ SUBSYSTEM_DEF(ticker)
'sound/roundend/disappointed.ogg'\
)
- world << sound(round_end_sound)
+ SEND_SOUND(world, sound(round_end_sound))
diff --git a/code/controllers/subsystem/title.dm b/code/controllers/subsystem/title.dm
index 6c5466d8d9..a0bcb5feec 100644
--- a/code/controllers/subsystem/title.dm
+++ b/code/controllers/subsystem/title.dm
@@ -53,7 +53,7 @@ SUBSYSTEM_DEF(title)
/datum/controller/subsystem/title/Shutdown()
if(file_path)
var/F = file("data/previous_title.dat")
- F << file_path
+ WRITE_FILE(F, file_path)
for(var/thing in GLOB.clients)
if(!thing)
diff --git a/code/datums/action.dm b/code/datums/action.dm
index 16fbeb8462..ecaa70387b 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -169,7 +169,7 @@
/datum/action/item_action/toggle_firemode
name = "Toggle Firemode"
-
+
/datum/action/item_action/rcl
name = "Change Cable Color"
button_icon_state = "rcl_rainbow"
@@ -490,7 +490,8 @@
var/obj/effect/proc_holder/spell/S = target
S.action = src
name = S.name
- icon_icon = S.action_icon
+ desc = S.desc
+ button_icon = S.action_icon
button_icon_state = S.action_icon_state
background_icon_state = S.action_background_icon_state
button.name = name
diff --git a/code/datums/antagonists/devil.dm b/code/datums/antagonists/devil.dm
index c8f00d1995..077fb94e52 100644
--- a/code/datums/antagonists/devil.dm
+++ b/code/datums/antagonists/devil.dm
@@ -280,7 +280,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
if(!D)
return
to_chat(world, "\"SLOTH, WRATH, GLUTTONY, ACEDIA, ENVY, GREED, PRIDE! FIRES OF HELL AWAKEN!!\"")
- world << 'sound/hallucinations/veryfar_noise.ogg'
+ SEND_SOUND(world, sound('sound/hallucinations/veryfar_noise.ogg'))
give_appropriate_spells()
D.convert_to_archdevil()
if(istype(D.loc, /obj/effect/dummy/slaughter/))
diff --git a/code/datums/antagonists/ninja.dm b/code/datums/antagonists/ninja.dm
index 6948740687..4efb17f154 100644
--- a/code/datums/antagonists/ninja.dm
+++ b/code/datums/antagonists/ninja.dm
@@ -141,7 +141,7 @@
/datum/antagonist/ninja/greet()
- owner.current << sound('sound/effects/ninja_greeting.ogg')
+ SEND_SOUND(owner.current, sound('sound/effects/ninja_greeting.ogg'))
to_chat(owner.current, "I am an elite mercenary assassin of the mighty Spider Clan. A SPACE NINJA!")
to_chat(owner.current, "Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by right clicking on it, to use abilities like stealth)!")
to_chat(owner.current, "Officially, [helping_station?"Nanotrasen":"The Syndicate"] are my employer.")
diff --git a/code/datums/callback.dm b/code/datums/callback.dm
index 1b5c25fe18..624fed58a6 100644
--- a/code/datums/callback.dm
+++ b/code/datums/callback.dm
@@ -100,3 +100,57 @@
if (object == GLOBAL_PROC)
return call(delegate)(arglist(calling_arguments))
return call(object, delegate)(arglist(calling_arguments))
+
+
+/datum/callback_select
+ var/list/finished
+ var/pendingcount
+ var/total
+
+/datum/callback_select/New(count, savereturns)
+ total = count
+ if (savereturns)
+ finished = new(count)
+
+
+/datum/callback_select/proc/invoke_callback(index, datum/callback/callback, list/callback_args, savereturn = TRUE)
+ set waitfor = FALSE
+ if (!callback || !istype(callback))
+ //This check only exists because the alternative is callback_select would block forever if given invalid data
+ CRASH("invalid callback passed to invoke_callback")
+ if (!length(callback_args))
+ callback_args = list()
+ pendingcount++
+ var/rtn = callback.Invoke(arglist(callback_args))
+ pendingcount--
+ if (savereturn)
+ finished[index] = rtn
+
+
+
+
+//runs a list of callbacks asynchronously, returning once all of them return.
+//callbacks can be repeated.
+//callbacks-args is a optional list of argument lists, in the same order as the callbacks,
+// the inner lists will be sent to the callbacks when invoked() as additional args.
+//can optionly save and return a list of return values, in the same order as the original list of callbacks
+//resolution is the number of byond ticks between checks.
+/proc/callback_select(list/callbacks, list/callback_args, savereturns = TRUE, resolution = 1)
+ if (!callbacks)
+ return
+ var/count = length(callbacks)
+ if (!count)
+ return
+ if (!callback_args)
+ callback_args = list()
+
+ callback_args.len = count
+
+ var/datum/callback_select/CS = new(count, savereturns)
+ for (var/i in 1 to count)
+ CS.invoke_callback(i, callbacks[i], callback_args[i], savereturns)
+
+ while(CS.pendingcount)
+ sleep(resolution*world.tick_lag)
+ return CS.finished
+
diff --git a/code/datums/callback.dm.rej b/code/datums/callback.dm.rej
new file mode 100644
index 0000000000..14faac8412
--- /dev/null
+++ b/code/datums/callback.dm.rej
@@ -0,0 +1,62 @@
+diff a/code/datums/callback.dm b/code/datums/callback.dm (rejected hunks)
+@@ -100,60 +100,3 @@
+ if (object == GLOBAL_PROC)
+ return call(delegate)(arglist(calling_arguments))
+ return call(object, delegate)(arglist(calling_arguments))
+-
+-
+-/datum/callback_select
+- var/list/finished
+- var/pendingcount
+- var/total
+-
+-/datum/callback_select/New(count, savereturns)
+- total = count
+- if (savereturns)
+- finished = new(count)
+-
+-
+-/datum/callback_select/proc/invoke_callback(index, datum/callback/callback, list/callback_args, savereturn = TRUE)
+- set waitfor = FALSE
+- if (!callback || !istype(callback))
+- //This check only exists because the alternative is callback_select would block forever if given invalid data
+- CRASH("invalid callback passed to invoke_callback")
+- if (!length(callback_args))
+- callback_args = list()
+- pendingcount++
+- debug_usr("calling callback")
+- var/rtn = callback.Invoke(arglist(callback_args))
+- debug_usr("callback returned")
+- pendingcount--
+- if (savereturn)
+- finished[index] = rtn
+-
+-
+-
+-
+-//runs a list of callbacks asynchronously, returning once all of them return.
+-//callbacks can be repeated.
+-//callbacks-args is a optional list of argument lists, in the same order as the callbacks,
+-// the inner lists will be sent to the callbacks when invoked() as additional args.
+-//can optionly save and return a list of return values, in the same order as the original list of callbacks
+-//resolution is the number of byond ticks between checks.
+-/proc/callback_select(list/callbacks, list/callback_args, savereturns = TRUE, resolution = 1)
+- if (!callbacks)
+- return
+- var/count = length(callbacks)
+- if (!count)
+- return
+- if (!callback_args)
+- callback_args = list()
+-
+- callback_args.len = count
+-
+- var/datum/callback_select/CS = new(count, savereturns)
+- for (var/i in 1 to count)
+- CS.invoke_callback(i, callbacks[i], callback_args[i], savereturns)
+- debug_usr("starting callbacks: [CS.pendingcount]")
+- while(CS.pendingcount)
+- debug_usr("callbacks: [CS.pendingcount]")
+- sleep(resolution*world.tick_lag)
+- return CS.finished
+-
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index e519cf6af3..87c6ad7334 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -929,6 +929,26 @@
manipulate_organs(C)
href_list["datumrefresh"] = href_list["editorgans"]
+ else if(href_list["hallucinate"])
+ if(!check_rights(0))
+ return
+
+ var/mob/living/carbon/C = locate(href_list["hallucinate"]) in GLOB.mob_list
+ if(!istype(C))
+ to_chat(usr, "This can only be done to instances of type /mob/living/carbon")
+ return
+
+ var/list/hallucinations = subtypesof(/datum/hallucination)
+ var/result = input(usr, "Choose the hallucination to apply","Send Hallucination") as null|anything in hallucinations
+ if(!usr)
+ return
+ if(QDELETED(C))
+ to_chat(usr, "Mob doesn't exist anymore")
+ return
+
+ if(result)
+ new result(C, TRUE)
+
else if(href_list["makehuman"])
if(!check_rights(R_SPAWN))
return
diff --git a/code/datums/diseases/advance/symptoms/hallucigen.dm b/code/datums/diseases/advance/symptoms/hallucigen.dm
index f913d49573..9bfd5b0baf 100644
--- a/code/datums/diseases/advance/symptoms/hallucigen.dm
+++ b/code/datums/diseases/advance/symptoms/hallucigen.dm
@@ -59,4 +59,4 @@ Bonus
else
if(prob(base_message_chance))
to_chat(M, "[pick("Oh, your head...", "Your head pounds.", "They're everywhere! Run!", "Something in the shadows...")]")
- M.hallucination += (15 * power)
+ M.hallucination += (45 * power)
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 7017149d53..d943e417e5 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -805,11 +805,11 @@
possible_targets += possible_target.current
var/mob/def_target = null
- var/objective_list[] = list(/datum/objective/assassinate, /datum/objective/protect, /datum/objective/debrain, /datum/objective/maroon)
- if (objective&&(objective.type in objective_list) && objective:target)
- def_target = objective:target.current
+ var/list/objective_list = typecacheof(list(/datum/objective/assassinate, /datum/objective/protect, /datum/objective/debrain, /datum/objective/maroon))
+ if (is_type_in_typecache(objective, objective_list) && objective.target)
+ def_target = objective.target.current
- var/new_target = input("Select target:", "Objective target", def_target) as null|anything in possible_targets
+ var/mob/new_target = input("Select target:", "Objective target", def_target) as null|anything in possible_targets
if (!new_target)
return
@@ -817,12 +817,12 @@
if (new_target == "Free objective")
new_objective = new objective_path
new_objective.owner = src
- new_objective:target = null
+ new_objective.target = null
new_objective.explanation_text = "Free objective"
else
new_objective = new objective_path
new_objective.owner = src
- new_objective:target = new_target:mind
+ new_objective.target = new_target.mind
//Will display as special role if the target is set as MODE. Ninjas/commandos/nuke ops.
new_objective.update_explanation_text()
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index 485ca00515..c15ede7b3e 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -37,7 +37,7 @@
icon_state = "shadow_mend"
/datum/status_effect/void_price/tick()
- owner << sound('sound/magic/summon_karp.ogg', volume = 25)
+ SEND_SOUND(owner, sound('sound/magic/summon_karp.ogg', volume = 25))
owner.adjustBruteLoss(3)
@@ -247,7 +247,7 @@
for(var/datum/mind/B in SSticker.mode.cult)
if(isliving(B.current))
var/mob/living/M = B.current
- M << 'sound/hallucinations/veryfar_noise.ogg'
+ SEND_SOUND(M, sound('sound/hallucinations/veryfar_noise.ogg'))
to_chat(M, "The Cult's Master, [owner], has fallen in \the [A]!")
/datum/status_effect/cult_master/tick()
diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm
index 7b43bf6396..f4f2fc089c 100644
--- a/code/datums/weather/weather.dm
+++ b/code/datums/weather/weather.dm
@@ -69,7 +69,7 @@
if(telegraph_message)
to_chat(M, telegraph_message)
if(telegraph_sound)
- M << sound(telegraph_sound)
+ SEND_SOUND(M, sound(telegraph_sound))
addtimer(CALLBACK(src, .proc/start), telegraph_duration)
/datum/weather/proc/start()
@@ -83,7 +83,7 @@
if(weather_message)
to_chat(M, weather_message)
if(weather_sound)
- M << sound(weather_sound)
+ SEND_SOUND(M, sound(weather_sound))
START_PROCESSING(SSweather, src)
addtimer(CALLBACK(src, .proc/wind_down), weather_duration)
@@ -98,7 +98,7 @@
if(end_message)
to_chat(M, end_message)
if(end_sound)
- M << sound(end_sound)
+ SEND_SOUND(M, sound(end_sound))
STOP_PROCESSING(SSweather, src)
addtimer(CALLBACK(src, .proc/end), end_duration)
diff --git a/code/datums/wires/mulebot.dm b/code/datums/wires/mulebot.dm
index 00b2dd10b8..9aa2ca81e8 100644
--- a/code/datums/wires/mulebot.dm
+++ b/code/datums/wires/mulebot.dm
@@ -20,12 +20,12 @@
var/mob/living/simple_animal/bot/mulebot/M = holder
switch(wire)
if(WIRE_POWER1, WIRE_POWER2)
- holder.visible_message("[bicon(M)] The charge light flickers.")
+ holder.visible_message("[icon2html(M, viewers(holder))] The charge light flickers.")
if(WIRE_AVOIDANCE)
- holder.visible_message("[bicon(M)] The external warning lights flash briefly.")
+ holder.visible_message("[icon2html(M, viewers(holder))] The external warning lights flash briefly.")
if(WIRE_LOADCHECK)
- holder.visible_message("[bicon(M)] The load platform clunks.")
+ holder.visible_message("[icon2html(M, viewers(holder))] The load platform clunks.")
if(WIRE_MOTOR1, WIRE_MOTOR2)
- holder.visible_message("[bicon(M)] The drive motor whines briefly.")
+ holder.visible_message("[icon2html(M, viewers(holder))] The drive motor whines briefly.")
else
- holder.visible_message("[bicon(M)] You hear a radio crackle.")
\ No newline at end of file
+ holder.visible_message("[icon2html(M, viewers(holder))] You hear a radio crackle.")
\ No newline at end of file
diff --git a/code/datums/wires/particle_accelerator.dm b/code/datums/wires/particle_accelerator.dm
index 436b8be3ec..d38147f1ec 100644
--- a/code/datums/wires/particle_accelerator.dm
+++ b/code/datums/wires/particle_accelerator.dm
@@ -25,7 +25,7 @@
if(WIRE_INTERFACE)
C.interface_control = !C.interface_control
if(WIRE_LIMIT)
- C.visible_message("[bicon(C)][C] makes a large whirring noise.")
+ C.visible_message("[icon2html(C, viewers(holder))][C] makes a large whirring noise.")
/datum/wires/particle_accelerator/control_box/on_cut(wire, mend)
var/obj/machinery/particle_accelerator/control_box/C = holder
diff --git a/code/datums/wires/syndicatebomb.dm b/code/datums/wires/syndicatebomb.dm
index 78acc42eb0..043110f5d3 100644
--- a/code/datums/wires/syndicatebomb.dm
+++ b/code/datums/wires/syndicatebomb.dm
@@ -19,21 +19,21 @@
switch(wire)
if(WIRE_BOOM)
if(B.active)
- holder.visible_message("[bicon(B)] An alarm sounds! It's go-")
+ holder.visible_message("[icon2html(B, viewers(holder))] An alarm sounds! It's go-")
B.explode_now = TRUE
tell_admins(B)
if(WIRE_UNBOLT)
- holder.visible_message("[bicon(B)] The bolts spin in place for a moment.")
+ holder.visible_message("[icon2html(B, viewers(holder))] The bolts spin in place for a moment.")
if(WIRE_DELAY)
if(B.delayedbig)
- holder.visible_message("[bicon(B)] The bomb has already been delayed.")
+ holder.visible_message("[icon2html(B, viewers(holder))] The bomb has already been delayed.")
else
- holder.visible_message("[bicon(B)] The bomb chirps.")
+ holder.visible_message("[icon2html(B, viewers(holder))] The bomb chirps.")
playsound(B, 'sound/machines/chime.ogg', 30, 1)
B.detonation_timer += 300
B.delayedbig = TRUE
if(WIRE_PROCEED)
- holder.visible_message("[bicon(B)] The bomb buzzes ominously!")
+ holder.visible_message("[icon2html(B, viewers(holder))] The bomb buzzes ominously!")
playsound(B, 'sound/machines/buzz-sigh.ogg', 30, 1)
var/seconds = B.seconds_remaining()
if(seconds >= 61) // Long fuse bombs can suddenly become more dangerous if you tinker with them.
@@ -44,13 +44,13 @@
B.detonation_timer = world.time + 100
if(WIRE_ACTIVATE)
if(!B.active && !B.defused)
- holder.visible_message("[bicon(B)] You hear the bomb start ticking!")
+ holder.visible_message("[icon2html(B, viewers(holder))] You hear the bomb start ticking!")
B.activate()
B.update_icon()
else if(B.delayedlittle)
- holder.visible_message("[bicon(B)] Nothing happens.")
+ holder.visible_message("[icon2html(B, viewers(holder))] Nothing happens.")
else
- holder.visible_message("[bicon(B)] The bomb seems to hesitate for a moment.")
+ holder.visible_message("[icon2html(B, viewers(holder))] The bomb seems to hesitate for a moment.")
B.detonation_timer += 100
B.delayedlittle = TRUE
@@ -62,24 +62,24 @@
B.defused = FALSE // Cutting and mending all the wires of an inactive bomb will thus cure any sabotage.
else
if(B.active)
- holder.visible_message("[bicon(B)] An alarm sounds! It's go-")
+ holder.visible_message("[icon2html(B, viewers(holder))] An alarm sounds! It's go-")
B.explode_now = TRUE
tell_admins(B)
else
B.defused = TRUE
if(WIRE_UNBOLT)
if(!mend && B.anchored)
- holder.visible_message("[bicon(B)] The bolts lift out of the ground!")
+ holder.visible_message("[icon2html(B, viewers(holder))] The bolts lift out of the ground!")
playsound(B, 'sound/effects/stealthoff.ogg', 30, 1)
B.anchored = FALSE
if(WIRE_PROCEED)
if(!mend && B.active)
- holder.visible_message("[bicon(B)] An alarm sounds! It's go-")
+ holder.visible_message("[icon2html(B, viewers(holder))] An alarm sounds! It's go-")
B.explode_now = TRUE
tell_admins(B)
if(WIRE_ACTIVATE)
if(!mend && B.active)
- holder.visible_message("[bicon(B)] The timer stops! The bomb has been defused!")
+ holder.visible_message("[icon2html(B, viewers(holder))] The timer stops! The bomb has been defused!")
B.active = FALSE
B.defused = TRUE
B.update_icon()
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 1b8d25aa51..218cb59f41 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -439,7 +439,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
// Ambience goes down here -- make sure to list each area separately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
if(L.client && !L.client.ambience_playing && L.client.prefs.toggles & SOUND_SHIP_AMBIENCE)
L.client.ambience_playing = 1
- L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_BUZZ)
+ SEND_SOUND(L, sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_BUZZ))
if(!(L.client && (L.client.prefs.toggles & SOUND_AMBIENCE)))
return //General ambience check is below the ship ambience so one can play without the other
@@ -448,7 +448,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
var/sound = pick(ambientsounds)
if(!L.client.played)
- L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE)
+ SEND_SOUND(L, sound(sound, repeat = 0, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE))
L.client.played = 1
sleep(600) //ewww - this is very very bad
if(L.&& L.client)
diff --git a/code/game/area/areas.dm.rej b/code/game/area/areas.dm.rej
new file mode 100644
index 0000000000..3c097d1229
--- /dev/null
+++ b/code/game/area/areas.dm.rej
@@ -0,0 +1,10 @@
+diff a/code/game/area/areas.dm b/code/game/area/areas.dm (rejected hunks)
+@@ -432,7 +432,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
+ // Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
+ if(L.client && !L.client.ambience_playing && L.client.prefs.toggles & SOUND_SHIP_AMBIENCE)
+ L.client.ambience_playing = 1
+- L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_BUZZ)
++ SEND_SOUND(L, sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_BUZZ))
+
+ if(!(L.client && (L.client.prefs.toggles & SOUND_AMBIENCE)))
+ return //General ambience check is below the ship ambience so one can play without the other
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 6a00f26ffc..d931f808b8 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -270,7 +270,7 @@
f_name = "a "
f_name += "blood-stained [name]!"
- to_chat(user, "[bicon(src)] That's [f_name]")
+ to_chat(user, "[icon2html(src, user)] That's [f_name]")
if(desc)
to_chat(user, desc)
diff --git a/code/game/communications.dm b/code/game/communications.dm
index 66bb91ef59..19c3f87460 100644
--- a/code/game/communications.dm
+++ b/code/game/communications.dm
@@ -292,7 +292,7 @@ GLOBAL_VAR_INIT(RADIO_MAGNETS, "9")
/datum/signal/proc/debug_print()
if (source)
- . = "signal = {source = '[source]' ([source:x],[source:y],[source:z])\n"
+ . = "signal = {source = '[source]' [COORD(source)]\n"
else
. = "signal = {source = '[source]' ()\n"
for (var/i in data)
diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm
index 8da7cb3169..8a6d0063b9 100644
--- a/code/game/gamemodes/antag_spawner.dm
+++ b/code/game/gamemodes/antag_spawner.dm
@@ -110,7 +110,7 @@
SSticker.mode.apprentices += M.mind
M.mind.special_role = "apprentice"
SSticker.mode.update_wiz_icons_added(M.mind)
- M << sound('sound/effects/magic.ogg')
+ SEND_SOUND(M, sound('sound/effects/magic.ogg'))
var/newname = copytext(sanitize(input(M, "You are [wizard_name]'s apprentice. Would you like to change your name to something else?", "Name change", randomname) as null|text),1,MAX_NAME_LEN)
if (!newname)
newname = randomname
diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm
index deef4367e0..f6bf8539e0 100644
--- a/code/game/gamemodes/blob/powers.dm
+++ b/code/game/gamemodes/blob/powers.dm
@@ -171,8 +171,8 @@
if(candidates.len) //if we got at least one candidate, they're a blobbernaut now.
var/client/C = pick(candidates)
blobber.key = C.key
- blobber << 'sound/effects/blobattack.ogg'
- blobber << 'sound/effects/attackblob.ogg'
+ SEND_SOUND(blobber, sound('sound/effects/blobattack.ogg'))
+ SEND_SOUND(blobber, sound('sound/effects/attackblob.ogg'))
to_chat(blobber, "You are a blobbernaut!")
to_chat(blobber, "You are powerful, hard to kill, and slowly regenerate near nodes and cores, but will slowly die if not near the blob or if the factory that made you is killed.")
to_chat(blobber, "You can communicate with other blobbernauts and GLOB.overminds via :b")
diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm
index 0c216f1c38..f6cdd64bb6 100644
--- a/code/game/gamemodes/blob/theblob.dm
+++ b/code/game/gamemodes/blob/theblob.dm
@@ -24,6 +24,7 @@
M.changeNext_move(CLICK_CD_MELEE)
var/a = pick("gently stroke", "nuzzle", "affectionatly pet", "cuddle")
M.visible_message("[M] [a]s [src]!", "You [a] [src]!")
+ to_chat(overmind, "[M] [a]s you!")
playsound(src, 'sound/effects/blobattack.ogg', 50, 1) //SQUISH SQUISH
@@ -235,7 +236,7 @@
if(istype(I, /obj/item/device/analyzer))
user.changeNext_move(CLICK_CD_MELEE)
to_chat(user, "The analyzer beeps once, then reports:
")
- user << 'sound/machines/ping.ogg'
+ SEND_SOUND(user, sound('sound/machines/ping.ogg'))
chemeffectreport(user)
typereport(user)
else
diff --git a/code/game/gamemodes/changeling/powers/shriek.dm b/code/game/gamemodes/changeling/powers/shriek.dm
index 099d991062..7afce8aa27 100644
--- a/code/game/gamemodes/changeling/powers/shriek.dm
+++ b/code/game/gamemodes/changeling/powers/shriek.dm
@@ -16,10 +16,10 @@
C.confused += 25
C.Jitter(50)
else
- C << sound('sound/effects/screech.ogg')
+ SEND_SOUND(C, sound('sound/effects/screech.ogg'))
if(issilicon(M))
- M << sound('sound/weapons/flash.ogg')
+ SEND_SOUND(M, sound('sound/weapons/flash.ogg'))
M.Knockdown(rand(100,200))
for(var/obj/machinery/light/L in range(4, user))
diff --git a/code/game/gamemodes/clock_cult/clock_mobs.dm b/code/game/gamemodes/clock_cult/clock_mobs.dm
index 97a68fd321..abeb183ab0 100644
--- a/code/game/gamemodes/clock_cult/clock_mobs.dm
+++ b/code/game/gamemodes/clock_cult/clock_mobs.dm
@@ -38,7 +38,7 @@
/mob/living/simple_animal/hostile/clockwork/examine(mob/user)
var/t_He = p_they(TRUE)
var/t_s = p_s()
- var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n"
+ var/msg = "*---------*\nThis is [icon2html(src, user)] \a [src]!\n"
msg += "[desc]\n"
if(health < maxHealth)
msg += ""
diff --git a/code/game/gamemodes/clock_cult/clock_scripture.dm b/code/game/gamemodes/clock_cult/clock_scripture.dm
index 4a1ca367ce..382aaec10d 100644
--- a/code/game/gamemodes/clock_cult/clock_scripture.dm
+++ b/code/game/gamemodes/clock_cult/clock_scripture.dm
@@ -150,7 +150,7 @@ Judgement: 12 servants, 5 caches, 300 CV, and any existing AIs are converted or
if(prob(ratvarian_prob))
message = text2ratvar(message)
to_chat(invoker, "\"[message]\"")
- invoker << 'sound/magic/clockwork/invoke_general.ogg'
+ SEND_SOUND(invoker, sound('sound/magic/clockwork/invoke_general.ogg'))
return TRUE
/datum/clockwork_scripture/proc/check_offstation_penalty()
diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm
index a7fb90d253..647b47e7fa 100644
--- a/code/game/gamemodes/cult/cult_comms.dm
+++ b/code/game/gamemodes/cult/cult_comms.dm
@@ -103,13 +103,13 @@
if(B.current)
B.current.update_action_buttons_icon()
if(!B.current.incapacitated())
- B.current << 'sound/hallucinations/im_here1.ogg'
+ SEND_SOUND(B.current, 'sound/hallucinations/im_here1.ogg')
to_chat(B.current, "Acolyte [Nominee] has asserted that they are worthy of leading the cult. A vote will be called shortly.")
sleep(100)
var/list/asked_cultists = list()
for(var/datum/mind/B in SSticker.mode.cult)
if(B.current && B.current != Nominee && !B.current.incapacitated())
- B.current << 'sound/magic/exit_blood.ogg'
+ SEND_SOUND(B.current, 'sound/magic/exit_blood.ogg')
asked_cultists += B.current
var/list/yes_voters = pollCandidates("[Nominee] seeks to lead your cult, do you support [Nominee.p_them()]?", poll_time = 300, group = asked_cultists)
if(QDELETED(Nominee) || Nominee.incapacitated())
@@ -280,7 +280,7 @@
for(var/datum/mind/B in SSticker.mode.cult)
if(B.current && B.current.stat != DEAD && B.current.client)
to_chat(B.current, "Master [ranged_ability_user] has marked [GLOB.blood_target] in the [A.name] as the cult's top priority, get there immediately!")
- B.current << pick(sound('sound/hallucinations/over_here2.ogg',0,1,75), sound('sound/hallucinations/over_here3.ogg',0,1,75))
+ SEND_SOUND(B.current, sound(pick('sound/hallucinations/over_here2.ogg','sound/hallucinations/over_here3.ogg'),0,1,75))
B.current.client.images += GLOB.blood_target_image
attached_action.owner.update_action_buttons_icon()
remove_ranged_ability("The marking rite is complete! It will last for 90 seconds.")
@@ -324,7 +324,7 @@
return FALSE
if(cooldown > world.time)
if(!PM.active)
- owner << "You need to wait [round((cooldown - world.time) * 0.1)] seconds before you can pulse again!"
+ to_chat(owner, "You need to wait [round((cooldown - world.time) * 0.1)] seconds before you can pulse again!")
return FALSE
return ..()
@@ -367,7 +367,7 @@
if(!attached_action.throwing)
attached_action.throwing = TRUE
attached_action.throwee = target
- ranged_ability_user << 'sound/weapons/thudswoosh.ogg'
+ SEND_SOUND(ranged_ability_user, sound('sound/weapons/thudswoosh.ogg'))
to_chat(ranged_ability_user,"You reach through the veil with your mind's eye and seize [target]!")
return
else
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 918398154c..d472bb7d5a 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -161,11 +161,15 @@
/obj/item/weapon/sharpener/cult
name = "eldritch whetstone"
desc = "A block, empowered by dark magic. Sharp weapons will be enhanced when used on the stone."
+ icon_state = "cult_sharpener"
used = 0
increment = 5
max = 40
prefix = "darkened"
+/obj/item/weapon/sharpener/cult/update_icon()
+ icon_state = "cult_sharpener[used ? "_used" : ""]"
+
/obj/item/clothing/suit/hooded/cultrobes/cult_shield
name = "empowered cultist armor"
desc = "Empowered garb which creates a powerful shield around the user."
@@ -391,7 +395,7 @@
if(!iscultist(user))
to_chat(user, "That doesn't seem to do anything useful.")
return
-
+
if(istype(A, /obj/item))
var/list/cultists = list()
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 69b730d574..4c80f53b94 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -538,7 +538,7 @@ structure_check() searches for nearby cultist structures required for the invoca
mob_to_revive = input(user, "Choose a cultist to revive.", "Cultist to Revive") as null|anything in potential_revive_mobs
else
mob_to_revive = potential_revive_mobs[1]
- if(!src || QDELETED(src) || rune_in_use || !validness_checks(mob_to_revive, user))
+ if(QDELETED(src) || !validness_checks(mob_to_revive, user))
rune_in_use = FALSE
return
if(user.name == "Herbert West")
diff --git a/code/game/gamemodes/cult/supply.dm b/code/game/gamemodes/cult/supply.dm
index 71b8c941b1..23270c3d6c 100644
--- a/code/game/gamemodes/cult/supply.dm
+++ b/code/game/gamemodes/cult/supply.dm
@@ -29,7 +29,6 @@
return 0
/obj/item/weapon/paper/talisman/supply/Topic(href, href_list)
- world.log << "[usr], [href], [href_list]"
if(QDELETED(src) || usr.incapacitated() || !in_range(src, usr))
return
diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm
index e8b77c1172..c5b94d983f 100644
--- a/code/game/gamemodes/cult/talisman.dm
+++ b/code/game/gamemodes/cult/talisman.dm
@@ -270,7 +270,7 @@
if(target.use(25))
new /obj/structure/constructshell(T)
to_chat(user, "The talisman clings to the metal and twists it into a construct shell!")
- user << sound('sound/effects/magic.ogg',0,1,25)
+ SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
invoke(user, 1)
qdel(src)
else
@@ -281,7 +281,7 @@
new /obj/item/stack/sheet/runed_metal(T,quantity)
target.use(quantity)
to_chat(user, "The talisman clings to the plasteel, transforming it into runed metal!")
- user << sound('sound/effects/magic.ogg',0,1,25)
+ SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
invoke(user, 1)
if(uses <= 0)
qdel(src)
diff --git a/code/game/gamemodes/devil/true_devil/_true_devil.dm b/code/game/gamemodes/devil/true_devil/_true_devil.dm
index 1a0cfcd231..090b926dbf 100644
--- a/code/game/gamemodes/devil/true_devil/_true_devil.dm
+++ b/code/game/gamemodes/devil/true_devil/_true_devil.dm
@@ -61,15 +61,15 @@
/mob/living/carbon/true_devil/examine(mob/user)
- var/msg = "*---------*\nThis is [bicon(src)] [src]!\n"
+ var/msg = "*---------*\nThis is [icon2html(src, user)] [src]!\n"
//Left hand items
for(var/obj/item/I in held_items)
if(!(I.flags & ABSTRACT))
if(I.blood_DNA)
- msg += "It is holding [bicon(I)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n"
+ msg += "It is holding [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n"
else
- msg += "It is holding [bicon(I)] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n"
+ msg += "It is holding [icon2html(I, user)] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n"
//Braindead
if(!client && stat != DEAD)
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 2a0cd230d5..790319e362 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -120,7 +120,7 @@
var/list/datum/game_mode/runnable_modes = config.get_runnable_midround_modes(living_crew.len)
var/list/datum/game_mode/usable_modes = list()
for(var/datum/game_mode/G in runnable_modes)
- if(G.reroll_friendly)
+ if(G.reroll_friendly && living_crew >= G.required_players)
usable_modes += G
else
qdel(G)
diff --git a/code/game/gamemodes/gang/gang_datum.dm b/code/game/gamemodes/gang/gang_datum.dm
index ba18ad7578..b7b20a7311 100644
--- a/code/game/gamemodes/gang/gang_datum.dm
+++ b/code/game/gamemodes/gang/gang_datum.dm
@@ -191,7 +191,7 @@
var/mob/living/mob = get(tool.loc, /mob/living)
if(mob && mob.mind && mob.stat == CONSCIOUS)
if(mob.mind.gang_datum == src)
- to_chat(mob, "[bicon(tool)] [message]")
+ to_chat(mob, "[icon2html(tool, mob)] [message]")
return
diff --git a/code/game/gamemodes/gang/gang_pen.dm b/code/game/gamemodes/gang/gang_pen.dm
index 4357f31e83..e52db2ec5f 100644
--- a/code/game/gamemodes/gang/gang_pen.dm
+++ b/code/game/gamemodes/gang/gang_pen.dm
@@ -66,4 +66,4 @@
cooldown = 0
icon_state = "pen"
var/mob/M = get(src, /mob)
- to_chat(M, "[bicon(src)] [src][(src.loc == M)?(""):(" in your [src.loc]")] vibrates softly. It is ready to be used again.")
+ to_chat(M, "[icon2html(src, M)] [src][(src.loc == M)?(""):(" in your [src.loc]")] vibrates softly. It is ready to be used again.")
diff --git a/code/game/gamemodes/gang/recaller.dm b/code/game/gamemodes/gang/recaller.dm
index 601a1f1c0d..0be52e6033 100644
--- a/code/game/gamemodes/gang/recaller.dm
+++ b/code/game/gamemodes/gang/recaller.dm
@@ -110,7 +110,7 @@
if(!message || !can_use(user))
return
if(user.z > 2)
- to_chat(user, "[bicon(src)]Error: Station out of range.")
+ to_chat(user, "[icon2html(src, user)]Error: Station out of range.")
return
var/list/members = list()
members += gang.gangsters
@@ -179,35 +179,35 @@
gang.message_gangtools("[usr] is attempting to recall the emergency shuttle.")
recalling = 1
- to_chat(loc, "[bicon(src)]Generating shuttle recall order with codes retrieved from last call signal...")
+ to_chat(loc, "[icon2html(src, loc)]Generating shuttle recall order with codes retrieved from last call signal...")
sleep(rand(100,300))
if(SSshuttle.emergency.mode != SHUTTLE_CALL) //Shuttle can only be recalled when it's moving to the station
- to_chat(user, "[bicon(src)]Emergency shuttle cannot be recalled at this time.")
+ to_chat(user, "[icon2html(src, user)]Emergency shuttle cannot be recalled at this time.")
recalling = 0
return 0
- to_chat(loc, "[bicon(src)]Shuttle recall order generated. Accessing station long-range communication arrays...")
+ to_chat(loc, "[icon2html(src, loc)]Shuttle recall order generated. Accessing station long-range communication arrays...")
sleep(rand(100,300))
if(!gang.dom_attempts)
- to_chat(user, "[bicon(src)]Error: Unable to access communication arrays. Firewall has logged our signature and is blocking all further attempts.")
+ to_chat(user, "[icon2html(src, user)]Error: Unable to access communication arrays. Firewall has logged our signature and is blocking all further attempts.")
recalling = 0
return 0
var/turf/userturf = get_turf(user)
if(userturf.z != ZLEVEL_STATION) //Shuttle can only be recalled while on station
- to_chat(user, "[\bicon(src)]Error: Device out of range of station communication arrays.")
+ to_chat(user, "[icon2html(src, user)]Error: Device out of range of station communication arrays.")
recalling = 0
return 0
var/datum/station_state/end_state = new /datum/station_state()
end_state.count()
if((100 * GLOB.start_state.score(end_state)) < 80) //Shuttle cannot be recalled if the station is too damaged
- to_chat(user, "[bicon(src)]Error: Station communication systems compromised. Unable to establish connection.")
+ to_chat(user, "[icon2html(src, user)]Error: Station communication systems compromised. Unable to establish connection.")
recalling = 0
return 0
- to_chat(loc, "[bicon(src)]Comm arrays accessed. Broadcasting recall signal...")
+ to_chat(loc, "[icon2html(src, loc)]Comm arrays accessed. Broadcasting recall signal...")
sleep(rand(100,300))
@@ -220,7 +220,7 @@
gang.recalls -= 1
return 1
- to_chat(loc, "[bicon(src)]No response recieved. Emergency shuttle cannot be recalled at this time.")
+ to_chat(loc, "[icon2html(src, loc)]No response recieved. Emergency shuttle cannot be recalled at this time.")
return 0
/obj/item/device/gangtool/proc/can_use(mob/living/carbon/human/user)
diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm
index 8c8108962e..5bc162ee8f 100644
--- a/code/game/gamemodes/malfunction/Malf_Modules.dm
+++ b/code/game/gamemodes/malfunction/Malf_Modules.dm
@@ -375,8 +375,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
minor_announce("[key] SECONDS UNTIL DOOMSDAY DEVICE ACTIVATION!", "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4", TRUE)
/obj/machinery/doomsday_device/proc/detonate(z_level = ZLEVEL_STATION)
- for(var/mob/M in GLOB.player_list)
- M << 'sound/machines/alarm.ogg'
+ sound_to_playing_players('sound/machines/alarm.ogg')
sleep(100)
for(var/mob/living/L in GLOB.mob_list)
var/turf/T = get_turf(L)
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
index 68ed9abd35..c24ab53ef5 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
@@ -654,7 +654,7 @@
to_chat(M, "[link] [rendered]")
/mob/living/simple_animal/hostile/swarmer/proc/ContactSwarmers()
- var/message = input(src, "Announce to other swarmers", "Swarmer contact")
+ var/message = stripped_input(src, "Announce to other swarmers", "Swarmer contact")
// TODO get swarmers their own colour rather than just boldtext
if(message)
swarmer_chat(message)
diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm
index dcd2ef2673..af27833d15 100644
--- a/code/game/gamemodes/miniantags/morph/morph.dm
+++ b/code/game/gamemodes/miniantags/morph/morph.dm
@@ -224,7 +224,7 @@
player_mind.special_role = "Morph"
SSticker.mode.traitors |= player_mind
to_chat(S, S.playstyle_string)
- S << 'sound/magic/mutate.ogg'
+ SEND_SOUND(S, sound('sound/magic/mutate.ogg'))
message_admins("[key_name_admin(S)] has been made into a morph by an event.")
log_game("[key_name(S)] was spawned as a morph by an event.")
spawned_mobs += S
diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm
index afbc597c29..e16c21e2e2 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant.dm
@@ -74,7 +74,7 @@
generated_objectives_and_spells = TRUE
mind.remove_all_antag()
mind.wipe_memory()
- src << 'sound/effects/ghost.ogg'
+ SEND_SOUND(src, sound('sound/effects/ghost.ogg'))
var/datum/objective/revenant/objective = new
objective.owner = mind
mind.objectives += objective
diff --git a/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm b/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm
index e9b417de1a..bcb2218fe6 100644
--- a/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm
+++ b/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm
@@ -42,7 +42,7 @@
SSticker.mode.traitors |= player_mind
to_chat(S, S.playstyle_string)
to_chat(S, "You are currently not currently in the same plane of existence as the station. Blood Crawl near a blood pool to manifest.")
- S << 'sound/magic/demon_dies.ogg'
+ SEND_SOUND(S, 'sound/magic/demon_dies.ogg')
message_admins("[key_name_admin(S)] has been made into a slaughter demon by an event.")
log_game("[key_name(S)] was spawned as a slaughter demon by an event.")
spawned_mobs += S
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index 759c5f4454..16fb1f601d 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -288,7 +288,7 @@
text += "
"
text += "(Syndicates used [TC_uses] TC) [purchases]"
if(TC_uses == 0 && station_was_nuked && !are_operatives_dead())
- text += "[bicon(icon('icons/badass.dmi', "badass"))]"
+ text += "[icon2html('icons/badass.dmi', world, "badass")]"
to_chat(world, text)
return 1
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 755f6dd0c9..d36cab4881 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -421,8 +421,7 @@
yes_code = FALSE
safety = TRUE
update_icon()
- for(var/mob/M in GLOB.player_list)
- M << 'sound/machines/alarm.ogg'
+ sound_to_playing_players('sound/machines/alarm.ogg')
if(SSticker && SSticker.mode)
SSticker.mode.explosion_in_progress = 1
sleep(100)
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index 3e6cca1ac5..3b91816ee9 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -124,7 +124,7 @@
text += " (used [TC_uses] TC) [purchases]"
if(TC_uses==0 && traitorwin)
var/static/icon/badass = icon('icons/badass.dmi', "badass")
- text += "[bicon(badass)]"
+ text += "[icon2html(badass, world)]"
text += objectives
diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm
index 5f65c2a96d..6f1ae8e1dd 100644
--- a/code/game/gamemodes/wizard/artefact.dm
+++ b/code/game/gamemodes/wizard/artefact.dm
@@ -476,7 +476,7 @@
GiveHint(target)
else if(istype(I, /obj/item/weapon/bikehorn))
to_chat(target, "HONK")
- target << 'sound/items/airhorn.ogg'
+ SEND_SOUND(target, 'sound/items/airhorn.ogg')
target.adjustEarDamage(0,3)
GiveHint(target)
cooldown = world.time +cooldown_time
diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm
index 1e72707e86..2fe15a99d8 100644
--- a/code/game/machinery/cell_charger.dm
+++ b/code/game/machinery/cell_charger.dm
@@ -2,7 +2,7 @@
name = "cell charger"
desc = "It charges power cells."
icon = 'icons/obj/power.dmi'
- icon_state = "ccharger0"
+ icon_state = "ccharger"
anchored = TRUE
use_power = IDLE_POWER_USE
idle_power_usage = 5
@@ -12,19 +12,16 @@
var/chargelevel = -1
/obj/machinery/cell_charger/proc/updateicon()
- icon_state = "ccharger[charging ? 1 : 0]"
+ cut_overlays()
- if(charging && !(stat & (BROKEN|NOPOWER)))
- var/newlevel = round(charging.percent() * 4 / 100)
-
- if(chargelevel != newlevel)
- chargelevel = newlevel
-
- cut_overlays()
- add_overlay("ccharger-o[newlevel]")
-
- else
- cut_overlays()
+ if(charging)
+ add_overlay(image(charging.icon, charging.icon_state))
+ add_overlay("ccharger-on")
+ if(!(stat & (BROKEN|NOPOWER)))
+ var/newlevel = round(charging.percent() * 4 / 100)
+ if(chargelevel != newlevel)
+ chargelevel = newlevel
+ add_overlay("ccharger-o[newlevel]")
/obj/machinery/cell_charger/examine(mob/user)
..()
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 06c4cce2bc..9fdcea6aaf 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -403,7 +403,7 @@
flash_color(mob_occupant, flash_color="#960000", flash_time=100)
to_chat(mob_occupant, "Agony blazes across your consciousness as your body is torn apart.
Is this what dying is like? Yes it is.")
playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 50, 0)
- mob_occupant << sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)
+ SEND_SOUND(mob_occupant, sound('sound/hallucinations/veryfar_noise.ogg',0,1,50))
QDEL_IN(mob_occupant, 40)
/obj/machinery/clonepod/relaymove(mob/user)
diff --git a/code/game/machinery/computer/apc_control.dm b/code/game/machinery/computer/apc_control.dm
index bc5c8cbfa7..134c28571e 100644
--- a/code/game/machinery/computer/apc_control.dm
+++ b/code/game/machinery/computer/apc_control.dm
@@ -116,24 +116,24 @@
authenticated = FALSE
auth_id = "\[NULL\]"
if(href_list["restore_logging"])
- to_chat(usr, "[bicon(src)] Logging functionality restored from backup data.")
+ to_chat(usr, "[icon2html(src, usr)] Logging functionality restored from backup data.")
emagged = FALSE
LAZYADD(logs, "-=- Logging restored to full functionality at this point -=-")
if(href_list["access_apc"])
playsound(src, "terminal_type", 50, 0)
var/obj/machinery/power/apc/APC = locate(href_list["access_apc"]) in GLOB.apcs_list
if(!APC || APC.aidisabled || APC.panel_open || QDELETED(APC))
- to_chat(usr, "[bicon(src)] APC does not return interface request. Remote access may be disabled.")
+ to_chat(usr, "[icon2html(src, usr)] APC does not return interface request. Remote access may be disabled.")
return
if(active_apc)
- to_chat(usr, "[bicon(src)] Disconnected from [active_apc].")
+ to_chat(usr, "[icon2html(src, usr)] Disconnected from [active_apc].")
active_apc.say("Remote access canceled. Interface locked.")
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, 0)
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0)
active_apc.locked = TRUE
active_apc.update_icon()
active_apc = null
- to_chat(usr, "[bicon(src)] Connected to APC in [APC.area]. Interface request sent.")
+ to_chat(usr, "[icon2html(src, usr)] Connected to APC in [APC.area]. Interface request sent.")
log_activity("remotely accessed APC in [APC.area]")
APC.interact(usr, GLOB.not_incapacitated_state)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index a54ab19907..7330f2d072 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -473,7 +473,6 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
if ("reg")
if (authenticated)
var/t2 = modify
- //var/t1 = input(usr, "What name?", "ID computer", null) as text
if ((authenticated && modify == t2 && (in_range(src, usr) || issilicon(usr)) && isturf(loc)))
var/newName = reject_bad_name(href_list["reg"])
if(newName)
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index ce6430d75c..75a73a5067 100755
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -89,7 +89,7 @@
playsound(src, 'sound/machines/terminal_alert.ogg', 25, 0)
if(prob(25))
for(var/mob/living/silicon/ai/AI in active_ais())
- AI << sound('sound/machines/terminal_alert.ogg', volume = 10) //Very quiet for balance reasons
+ SEND_SOUND(AI, sound('sound/machines/terminal_alert.ogg', volume = 10)) //Very quiet for balance reasons
if("logout")
authenticated = 0
playsound(src, 'sound/machines/terminal_off.ogg', 50, 0)
diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm
index 26a7d3b729..f71066f8dd 100644
--- a/code/game/machinery/computer/message.dm
+++ b/code/game/machinery/computer/message.dm
@@ -309,7 +309,7 @@
message = noserver
else
if(auth)
- var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
+ var/dkey = trim(stripped_input(usr, "Please enter the decryption key."))
if(dkey && dkey != "")
if(src.linkedServer.decryptkey == dkey)
var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):"))
@@ -414,10 +414,10 @@
customrecepient.tnote += "← From [customsender] ([customjob]):
[custommessage]
"
if (!customrecepient.silent)
playsound(customrecepient.loc, 'sound/machines/twobeep.ogg', 50, 1)
- customrecepient.audible_message("[bicon(customrecepient)] *[customrecepient.ttone]*", null, 3)
+ customrecepient.audible_message("[icon2html(customrecepient, viewers(customrecepient))] *[customrecepient.ttone]*", null, 3)
if( customrecepient.loc && ishuman(customrecepient.loc) )
var/mob/living/carbon/human/H = customrecepient.loc
- to_chat(H, "[bicon(customrecepient)] Message from [customsender] ([customjob]), \"[custommessage]\" (Reply)")
+ to_chat(H, "[icon2html(customrecepient, viewers(H))] Message from [customsender] ([customjob]), \"[custommessage]\" (Reply)")
log_talk(usr,"[key_name(usr)] (PDA: [customsender]) sent \"[custommessage]\" to [customrecepient.owner]",LOGPDA)
customrecepient.cut_overlays()
customrecepient.add_overlay(mutable_appearance('icons/obj/pda.dmi', "pda-r"))
@@ -427,10 +427,10 @@
customrecepient.tnote += "← From [PDARec.owner] ([customjob]):
[custommessage]
"
if (!customrecepient.silent)
playsound(customrecepient.loc, 'sound/machines/twobeep.ogg', 50, 1)
- customrecepient.audible_message("[bicon(customrecepient)] *[customrecepient.ttone]*", null, 3)
+ customrecepient.audible_message("[icon2html(customrecepient, viewers(customrecepient))] *[customrecepient.ttone]*", null, 3)
if( customrecepient.loc && ishuman(customrecepient.loc) )
var/mob/living/carbon/human/H = customrecepient.loc
- to_chat(H, "[bicon(customrecepient)] Message from [PDARec.owner] ([customjob]), \"[custommessage]\" (Reply)")
+ to_chat(H, "[icon2html(customrecepient, H)] Message from [PDARec.owner] ([customjob]), \"[custommessage]\" (Reply)")
log_talk(usr,"[key_name(usr)] (PDA: [PDARec.owner]) sent \"[custommessage]\" to [customrecepient.owner]",LOGPDA)
customrecepient.cut_overlays()
customrecepient.add_overlay(mutable_appearance('icons/obj/pda.dmi', "pda-r"))
diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm
index 60ac43cb41..3f18cc29e9 100644
--- a/code/game/machinery/computer/pod.dm
+++ b/code/game/machinery/computer/pod.dm
@@ -21,7 +21,7 @@
return
if(!connected)
- viewers(null, null) << "Cannot locate mass driver connector. Cancelling firing sequence!"
+ say("Cannot locate mass driver connector. Cancelling firing sequence!")
return
for(var/obj/machinery/door/poddoor/M in range(range, src))
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 624d853808..94047727bc 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -233,9 +233,13 @@
return
else /*if(src.justzap)*/
return
- else if(user.hallucination > 50 && ishuman(user) && prob(10) && src.operating == FALSE)
- hallucinate_shock(user)
- return
+ else if(user.hallucinating() && ishuman(user) && prob(4) && !operating)
+ var/mob/living/carbon/human/H = user
+ if(H.gloves)
+ var/obj/item/clothing/gloves/G = H.gloves
+ if(G.siemens_coefficient)//not insulated
+ hallucinate_shock(H)
+ return
if (cyclelinkedairlock)
if (!shuttledocked && !emergency && !cyclelinkedairlock.shuttledocked && !cyclelinkedairlock.emergency && allowed(user))
if(cyclelinkedairlock.operating)
diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm
index a3f2424a9a..a0086b7258 100644
--- a/code/game/machinery/doors/airlock_types.dm
+++ b/code/game/machinery/doors/airlock_types.dm
@@ -390,7 +390,7 @@
new /obj/effect/temp_visual/cult/sac(loc)
var/atom/throwtarget
throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
- L << pick(sound('sound/hallucinations/turn_around1.ogg',0,1,50), sound('sound/hallucinations/turn_around2.ogg',0,1,50))
+ SEND_SOUND(L, sound(pick('sound/hallucinations/turn_around1.ogg','sound/hallucinations/turn_around2.ogg'),0,1,50))
flash_color(L, flash_color="#960000", flash_time=20)
L.Knockdown(40)
L.throw_at(throwtarget, 5, 1,src)
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index f5958843fc..cf51158356 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -439,7 +439,7 @@ Class Procs:
/obj/machinery/proc/display_parts(mob/user)
to_chat(user, "Following parts detected in the machine:")
for(var/obj/item/C in component_parts)
- to_chat(user, "[bicon(C)] [C.name]")
+ to_chat(user, "[icon2html(C, user)] [C.name]")
/obj/machinery/examine(mob/user)
..()
diff --git a/code/game/machinery/overview.dm b/code/game/machinery/overview.dm
index ffcb36678a..545414577e 100644
--- a/code/game/machinery/overview.dm
+++ b/code/game/machinery/overview.dm
@@ -96,7 +96,8 @@
colour2 = rgb(255,128,0)
if(ismob(AM))
- if(AM:client)
+ var/mob/M = AM
+ if(M.client)
colour = rgb(255,0,0)
else
colour = rgb(255,128,128)
@@ -146,7 +147,7 @@
var/icon/I2 = imap[2+(ix + icx*iy)*2]
- //to_chat(world, "icon: [bicon(I)]")
+ //to_chat(world, "icon: [icon2html(I, world)]")
I.DrawBox(colour, rx, ry, rx+1, ry+1)
@@ -163,7 +164,7 @@
H.screen_loc = "[5 + i%icx],[6+ round(i/icx)]"
- //to_chat(world, "[bicon(I)] at [H.screen_loc]")
+ //to_chat(world, "[icon2html(I, world)] at [H.screen_loc]")
H.name = (i==0)?"maprefresh":"map"
@@ -242,7 +243,8 @@
colour = rgb(255,255,0)
if(ismob(AM))
- if(AM:client)
+ var/mob/M = AM
+ if(M.client)
colour = rgb(255,0,0)
else
colour = rgb(255,128,128)
@@ -274,7 +276,7 @@
var/icon/I = imap[1+(ix + icx*iy)]
- //to_chat(world, "icon: [bicon(I)]")
+ //to_chat(world, "icon: [icon2html(I, world)]")
I.DrawBox(colour, rx, ry, rx, ry)
@@ -289,7 +291,7 @@
H.screen_loc = "[5 + i%icx],[6+ round(i/icx)]"
- //to_chat(world, "[bicon(I)] at [H.screen_loc]")
+ //to_chat(world, "[icon2html(I, world)] at [H.screen_loc]")
H.name = (i==0)?"maprefresh":"map"
diff --git a/code/game/machinery/robot_fabricator.dm b/code/game/machinery/robot_fabricator.dm
index 2183ec6448..20fd729304 100644
--- a/code/game/machinery/robot_fabricator.dm
+++ b/code/game/machinery/robot_fabricator.dm
@@ -11,31 +11,29 @@
idle_power_usage = 20
active_power_usage = 5000
-/obj/machinery/robotic_fabricator/attackby(obj/item/O, mob/user, params)
+/obj/machinery/robotic_fabricator/attackby(obj/item/O, mob/living/user, params)
if (istype(O, /obj/item/stack/sheet/metal))
- if (src.metal_amount < 150000)
- var/count = 0
- src.add_overlay("fab-load-metal")
- spawn(15)
- if(O)
- if(!O:amount)
- return
- while(metal_amount < 150000 && O:amount)
- src.metal_amount += O:materials[MAT_METAL] /*O:height * O:width * O:length * 100000*/
- O:amount--
- count++
-
- if (O:amount < 1)
- qdel(O)
-
- to_chat(user, "You insert [count] metal sheet\s into \the [src].")
- cut_overlay("fab-load-metal")
- updateDialog()
+ if (metal_amount < 150000)
+ add_overlay("fab-load-metal")
+ addtimer(CALLBACK(src, .proc/FinishLoadingMetal, O, user), 15)
else
to_chat(user, "\The [src] is full.")
else
return ..()
+/obj/machinery/robotic_fabricator/proc/FinishLoadingMetal(obj/item/stack/sheet/metal/M, mob/living/user)
+ cut_overlay("fab-load-metal")
+ if(QDELETED(M) || QDELETED(user))
+ return
+ var/count = 0
+ while(metal_amount < 150000 && !QDELETED(M))
+ metal_amount += M.materials[MAT_METAL]
+ M.use(1)
+ count++
+
+ to_chat(user, "You insert [count] metal sheet\s into \the [src].")
+ updateDialog()
+
/obj/machinery/robotic_fabricator/power_change()
if (powered())
stat &= ~NOPOWER
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index a7d857844a..c857ddaf16 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -10,9 +10,9 @@
max_integrity = 200 //The shield can only take so much beating (prevents perma-prisons)
CanAtmosPass = ATMOS_PASS_DENSITY
-/obj/structure/emergency_shield/New()
- src.setDir(pick(1,2,3,4))
- ..()
+/obj/structure/emergency_shield/Initialize()
+ . = ..()
+ setDir(pick(GLOB.cardinals))
air_update_turf(1)
/obj/structure/emergency_shield/Destroy()
diff --git a/code/game/machinery/shieldgen.dm.rej b/code/game/machinery/shieldgen.dm.rej
new file mode 100644
index 0000000000..12ce2d21dc
--- /dev/null
+++ b/code/game/machinery/shieldgen.dm.rej
@@ -0,0 +1,10 @@
+diff a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm (rejected hunks)
+@@ -12,7 +12,7 @@
+
+ /obj/structure/emergency_shield/Initialize()
+ . = ..()
+- setDir(pick(1,2,3,4))
++ setDir(pick(GLOB.cardinals))
+ air_update_turf(1)
+
+ /obj/structure/emergency_shield/Destroy()
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index 655483a255..56c4038a76 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -210,14 +210,14 @@
var/new_timer = input(user, "Please set the timer.", "Timer", "[timer_set]") as num
if(in_range(src, user) && isliving(user)) //No running off and setting bombs from across the station
timer_set = Clamp(new_timer, minimum_timer, maximum_timer)
- src.loc.visible_message("[bicon(src)] timer set for [timer_set] seconds.")
+ src.loc.visible_message("[icon2html(src, viewers(src))] timer set for [timer_set] seconds.")
if(alert(user,"Would you like to start the countdown now?",,"Yes","No") == "Yes" && in_range(src, user) && isliving(user))
if(defused || active)
if(defused)
- src.loc.visible_message("[bicon(src)] Device error: User intervention required.")
+ src.loc.visible_message("[icon2html(src, viewers(src))] Device error: User intervention required.")
return
else
- src.loc.visible_message("[bicon(src)] [timer_set] seconds until detonation, please clear the area.")
+ src.loc.visible_message("[icon2html(src, viewers(loc))] [timer_set] seconds until detonation, please clear the area.")
activate()
update_icon()
add_fingerprint(user)
@@ -333,7 +333,7 @@
var/obj/machinery/syndicatebomb/holder = loc
if(istype(holder))
attempts++
- holder.loc.visible_message("[bicon(holder)] Alert: Bomb has detonated. Your score is now [defusals] for [attempts]. Resetting wires...")
+ holder.loc.visible_message("[icon2html(holder, viewers(holder))] Alert: Bomb has detonated. Your score is now [defusals] for [attempts]. Resetting wires...")
reset()
else
qdel(src)
@@ -343,7 +343,7 @@
if(istype(holder))
attempts++
defusals++
- holder.loc.visible_message("[bicon(holder)] Alert: Bomb has been defused. Your score is now [defusals] for [attempts]! Resetting wires in 5 seconds...")
+ holder.loc.visible_message("[icon2html(holder, viewers(holder))] Alert: Bomb has been defused. Your score is now [defusals] for [attempts]! Resetting wires in 5 seconds...")
sleep(50) //Just in case someone is trying to remove the bomb core this gives them a little window to crowbar it out
if(istype(holder))
reset()
diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm
index 4fdf06b530..1e7c2b9f20 100644
--- a/code/game/mecha/equipment/mecha_equipment.dm
+++ b/code/game/mecha/equipment/mecha_equipment.dm
@@ -37,10 +37,7 @@
src.update_chassis_page()
chassis.occupant_message("The [src] is destroyed!")
chassis.log_append_to_last("[src] is destroyed.",1)
- if(istype(src, /obj/item/mecha_parts/mecha_equipment/weapon))
- chassis.occupant << sound('sound/mecha/weapdestr.ogg',volume=50)
- else
- chassis.occupant << sound('sound/mecha/critdestr.ogg',volume=50)
+ SEND_SOUND(chassis.occupant, sound(istype(src, /obj/item/mecha_parts/mecha_equipment/weapon) ? 'sound/mecha/weapdestr.ogg' : 'sound/mecha/critdestr.ogg', volume=50))
chassis = null
return ..()
@@ -139,7 +136,7 @@
/obj/item/mecha_parts/mecha_equipment/proc/occupant_message(message)
if(chassis)
- chassis.occupant_message("[bicon(src)] [message]")
+ chassis.occupant_message("[icon2html(src, chassis.occupant)] [message]")
return
/obj/item/mecha_parts/mecha_equipment/proc/log_message(message)
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 5564cd2c0a..28f2b0fb18 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -262,7 +262,7 @@
if(equipment && equipment.len)
to_chat(user, "It's equipped with:")
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
- to_chat(user, "[bicon(ME)] [ME]")
+ to_chat(user, "[icon2html(ME, user)] [ME]")
//processing internal damage, temperature, air regulation, alert updates, lights power use.
/obj/mecha/process()
@@ -596,7 +596,7 @@
/obj/mecha/proc/setInternalDamage(int_dam_flag)
internal_damage |= int_dam_flag
log_append_to_last("Internal damage of type [int_dam_flag].",1)
- occupant << sound('sound/machines/warning-buzzer.ogg',wait=0)
+ SEND_SOUND(occupant, sound('sound/machines/warning-buzzer.ogg',wait=0))
diag_hud_set_mechstat()
return
@@ -636,7 +636,7 @@
var/can_control_mech = 0
for(var/obj/item/mecha_parts/mecha_tracking/ai_control/A in trackers)
can_control_mech = 1
- to_chat(user, "[bicon(src)] Status of [name]:\n[A.get_mecha_info()]")
+ to_chat(user, "[icon2html(src, user)] Status of [name]:\n[A.get_mecha_info()]")
break
if(!can_control_mech)
to_chat(user, "You cannot control exosuits without AI control beacons installed.")
@@ -707,14 +707,14 @@
icon_state = initial(icon_state)
playsound(src, 'sound/machines/windowdoor.ogg', 50, 1)
if(!internal_damage)
- occupant << sound('sound/mecha/nominal.ogg',volume=50)
+ SEND_SOUND(occupant, sound('sound/mecha/nominal.ogg',volume=50))
AI.cancel_camera()
AI.controlled_mech = src
AI.remote_control = src
AI.canmove = 1 //Much easier than adding AI checks! Be sure to set this back to 0 if you decide to allow an AI to leave a mech somehow.
AI.can_shunt = 0 //ONE AI ENTERS. NO AI LEAVES.
- to_chat(AI, "[AI.can_dominate_mechs ? "Takeover of [name] complete! You are now loaded onto the onboard computer. Do not attempt to leave the station sector!" \
- : "You have been uploaded to a mech's onboard computer."]")
+ to_chat(AI, AI.can_dominate_mechs ? "Takeover of [name] complete! You are now loaded onto the onboard computer. Do not attempt to leave the station sector!" :\
+ "You have been uploaded to a mech's onboard computer.")
to_chat(AI, "Use Middle-Mouse to activate mech functions and equipment. Click normally for AI interactions.")
if(interaction == AI_TRANS_FROM_CARD)
GrantActions(AI, FALSE) //No eject/return to core action for AI uploaded by card
@@ -860,7 +860,7 @@
setDir(dir_in)
playsound(src, 'sound/machines/windowdoor.ogg', 50, 1)
if(!internal_damage)
- occupant << sound('sound/mecha/nominal.ogg',volume=50)
+ SEND_SOUND(occupant, sound('sound/mecha/nominal.ogg',volume=50))
return 1
else
return 0
@@ -914,7 +914,7 @@
setDir(dir_in)
log_message("[mmi_as_oc] moved in as pilot.")
if(!internal_damage)
- occupant << sound('sound/mecha/nominal.ogg',volume=50)
+ SEND_SOUND(occupant, sound('sound/mecha/nominal.ogg',volume=50))
GrantActions(brainmob)
return TRUE
@@ -1004,7 +1004,7 @@
/obj/mecha/proc/occupant_message(message as text)
if(message)
if(occupant && occupant.client)
- to_chat(occupant, "[bicon(src)] [message]")
+ to_chat(occupant, "[icon2html(src, occupant)] [message]")
return
/obj/mecha/proc/log_message(message as text,red=null)
diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm
index 050498d8f1..4102ba914b 100644
--- a/code/game/mecha/mecha_actions.dm
+++ b/code/game/mecha/mecha_actions.dm
@@ -242,7 +242,7 @@
chassis.occupant_message("Zoom mode [chassis.zoom_mode?"en":"dis"]abled.")
if(chassis.zoom_mode)
owner.client.change_view(12)
- owner << sound('sound/mecha/imag_enh.ogg',volume=50)
+ SEND_SOUND(owner, sound('sound/mecha/imag_enh.ogg',volume=50))
else
owner.client.change_view(world.view) //world.view - default mob view size
UpdateButtonIcon()
diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm
index 5127aa2285..72a721911f 100644
--- a/code/game/objects/effects/decals/cleanable/humans.dm
+++ b/code/game/objects/effects/decals/cleanable/humans.dm
@@ -169,7 +169,7 @@
. += "You recognise the footprints as belonging to:\n"
for(var/shoe in shoe_types)
var/obj/item/clothing/shoes/S = shoe
- . += "some [initial(S.name)] [bicon(initial(S.icon))]\n"
+ . += "some [initial(S.name)] [icon2html(initial(S.icon), user)]\n"
to_chat(user, .)
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index c9b524836f..80b291e571 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -22,7 +22,7 @@
/obj/effect/mine/proc/triggermine(mob/victim)
if(triggered)
return
- visible_message("[victim] sets off [bicon(src)] [src]!")
+ visible_message("[victim] sets off [icon2html(src, viewers(src))] [src]!")
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
@@ -121,13 +121,13 @@
if(!victim.client || !istype(victim))
return
to_chat(victim, "RIP AND TEAR")
- victim << 'sound/misc/e1m1.ogg'
+ SEND_SOUND(victim, sound('sound/misc/e1m1.ogg'))
var/old_color = victim.client.color
var/red_splash = list(1,0,0,0.8,0.2,0, 0.8,0,0.2,0.1,0,0)
var/pure_red = list(0,0,0,0,0,0,0,0,0,1,0,0)
spawn(0)
- new /obj/effect/hallucination/delusion(victim.loc,victim,"demon",duration,0)
+ new /datum/hallucination/delusion(victim, TRUE, "demon",duration,0)
var/obj/item/weapon/twohanded/required/chainsaw/doomslayer/chainsaw = new(victim.loc)
chainsaw.flags |= NODROP
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index bca1ccce81..9097d8add4 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -558,7 +558,7 @@ GLOBAL_LIST_EMPTY(PDAs)
if (!silent)
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
- audible_message("[bicon(src)] *[ttone]*", null, 3)
+ audible_message("[icon2html(src, hearers(src))] *[ttone]*", null, 3)
//Search for holder of the PDA.
var/mob/living/L = null
if(loc && isliving(loc))
@@ -575,7 +575,7 @@ GLOBAL_LIST_EMPTY(PDAs)
hrefstart = ""
hrefend = ""
- to_chat(L, "[\bicon(src)] Message from [hrefstart][source.owner] ([source.ownjob])[hrefend], \"[msg.message]\"[msg.get_photo_ref()] (Reply)")
+ to_chat(L, "[icon2html(src)] Message from [hrefstart][source.owner] ([source.ownjob])[hrefend], \"[msg.message]\"[msg.get_photo_ref()] (Reply)")
update_icon()
add_overlay(icon_alert)
diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm
index e5bca7eeac..f32f707204 100644
--- a/code/game/objects/items/devices/geiger_counter.dm
+++ b/code/game/objects/items/devices/geiger_counter.dm
@@ -88,27 +88,27 @@
if(isliving(loc))
var/mob/living/M = loc
if(!emagged)
- to_chat(M, "[bicon(src)] RADIATION PULSE DETECTED.")
- to_chat(M, "[bicon(src)] Severity: [amount]")
+ to_chat(M, "[icon2html(src, M)] RADIATION PULSE DETECTED.")
+ to_chat(M, "[icon2html(src, M)] Severity: [amount]")
else
- to_chat(M, "[bicon(src)] !@%$AT!(N P!LS! D/TEC?ED.")
- to_chat(M, "[bicon(src)] &!F2rity: <=[amount]#1")
+ to_chat(M, "[icon2html(src, M)] !@%$AT!(N P!LS! D/TEC?ED.")
+ to_chat(M, "[icon2html(src, M)] &!F2rity: <=[amount]#1")
update_icon()
/obj/item/device/geiger_counter/attack_self(mob/user)
scanning = !scanning
update_icon()
- to_chat(user, "[bicon(src)] You switch [scanning ? "on" : "off"] [src].")
+ to_chat(user, "[icon2html(src, user)] You switch [scanning ? "on" : "off"] [src].")
/obj/item/device/geiger_counter/attack(mob/living/M, mob/user)
if(user.a_intent == INTENT_HELP)
if(!emagged)
user.visible_message("[user] scans [M] with [src].", "You scan [M]'s radiation levels with [src]...")
if(!M.radiation)
- to_chat(user, "[bicon(src)] Radiation levels within normal boundaries.")
+ to_chat(user, "[icon2html(src, user)] Radiation levels within normal boundaries.")
return 1
else
- to_chat(user, "[bicon(src)] Subject is irradiated. Radiation levels: [M.radiation].")
+ to_chat(user, "[icon2html(src, user)] Subject is irradiated. Radiation levels: [M.radiation].")
return 1
else
user.visible_message("[user] scans [M] with [src].", "You project [src]'s stored radiation into [M]'s body!")
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 3d7e575215..ae84bd2f2c 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -147,7 +147,7 @@ MASS SPECTROMETER
if (M.getCloneLoss())
to_chat(user, "\tSubject appears to have [M.getCloneLoss() > 30 ? "severe" : "minor"] cellular damage.")
if (M.reagents && M.reagents.get_reagent_amount("epinephrine"))
- to_chat(user, "\tBloodstream analysis located [M.reagents:get_reagent_amount("epinephrine")] units of rejuvenation chemicals.")
+ to_chat(user, "\tBloodstream analysis located [M.reagents.get_reagent_amount("epinephrine")] units of rejuvenation chemicals.")
if (M.getBrainLoss() >= 100 || !M.getorgan(/obj/item/organ/brain))
to_chat(user, "\tSubject brain function is non-existent.")
else if (M.getBrainLoss() >= 60)
diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm
index c21ff386bd..4663e2142a 100644
--- a/code/game/objects/items/devices/transfer_valve.dm
+++ b/code/game/objects/items/devices/transfer_valve.dm
@@ -8,7 +8,7 @@
desc = "Regulates the transfer of air between two tanks"
var/obj/item/weapon/tank/tank_one
var/obj/item/weapon/tank/tank_two
- var/obj/item/device/attached_device
+ var/obj/item/device/assembly/attached_device
var/mob/attacher = null
var/valve_open = FALSE
var/toggle = 1
@@ -99,8 +99,8 @@
toggle_valve()
else if(attached_device)
if(href_list["rem_device"])
- attached_device.loc = get_turf(src)
- attached_device:holder = null
+ attached_device.forceMove(get_turf(src))
+ attached_device.holder = null
attached_device = null
update_icon()
if(href_list["device"])
diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm
index 285225d6f1..1bd66b6a38 100644
--- a/code/game/objects/items/stacks/sheets/leather.dm
+++ b/code/game/objects/items/stacks/sheets/leather.dm
@@ -12,7 +12,7 @@
novariants = FALSE
GLOBAL_LIST_INIT(human_recipes, list( \
- new/datum/stack_recipe("bloated human costume", /obj/item/clothing/suit/hooded/bloated_human, 5, on_floor = 1), \
+ new/datum/stack_recipe("bloated human costume", /obj/item/clothing/suit/hooded/bloated_human, 5), \
))
/obj/item/stack/sheet/animalhide/human/Initialize(mapload, new_amount, merge = TRUE)
@@ -33,7 +33,7 @@ GLOBAL_LIST_INIT(human_recipes, list( \
icon_state = "sheet-corgi"
GLOBAL_LIST_INIT(corgi_recipes, list ( \
- new/datum/stack_recipe("corgi costume", /obj/item/clothing/suit/hooded/ian_costume, 3, on_floor = 1), \
+ new/datum/stack_recipe("corgi costume", /obj/item/clothing/suit/hooded/ian_costume, 3), \
))
/obj/item/stack/sheet/animalhide/corgi/Initialize(mapload, new_amount, merge = TRUE)
@@ -53,8 +53,8 @@ GLOBAL_LIST_INIT(corgi_recipes, list ( \
icon_state = "sheet-monkey"
GLOBAL_LIST_INIT(monkey_recipes, list ( \
- new/datum/stack_recipe("monkey mask", /obj/item/clothing/mask/gas/monkeymask, 1, on_floor = 1), \
- new/datum/stack_recipe("monkey suit", /obj/item/clothing/suit/monkeysuit, 2, on_floor = 1), \
+ new/datum/stack_recipe("monkey mask", /obj/item/clothing/mask/gas/monkeymask, 1), \
+ new/datum/stack_recipe("monkey suit", /obj/item/clothing/suit/monkeysuit, 2), \
))
/obj/item/stack/sheet/animalhide/monkey/Initialize(mapload, new_amount, merge = TRUE)
@@ -74,8 +74,8 @@ GLOBAL_LIST_INIT(monkey_recipes, list ( \
icon_state = "sheet-xeno"
GLOBAL_LIST_INIT(xeno_recipes, list ( \
- new/datum/stack_recipe("alien helmet", /obj/item/clothing/head/xenos, 1, on_floor = 1), \
- new/datum/stack_recipe("alien suit", /obj/item/clothing/suit/xenos, 2, on_floor = 1), \
+ new/datum/stack_recipe("alien helmet", /obj/item/clothing/head/xenos, 1), \
+ new/datum/stack_recipe("alien suit", /obj/item/clothing/suit/xenos, 2), \
))
/obj/item/stack/sheet/animalhide/xeno/Initialize(mapload, new_amount, merge = TRUE)
@@ -161,7 +161,7 @@ GLOBAL_LIST_INIT(leather_recipes, list ( \
GLOBAL_LIST_INIT(sinew_recipes, list ( \
- new/datum/stack_recipe("sinew restraints", /obj/item/weapon/restraints/handcuffs/sinew, 1, on_floor = 1), \
+ new/datum/stack_recipe("sinew restraints", /obj/item/weapon/restraints/handcuffs/sinew, 1), \
))
/obj/item/stack/sheet/sinew/Initialize(mapload, new_amount, merge = TRUE)
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 348c6620cd..daaadeb797 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -527,7 +527,7 @@
return list(pick(messages))
/obj/item/toy/talking/proc/toy_talk(mob/user, message)
- user.loc.visible_message("[bicon(src)] [message]")
+ user.loc.visible_message("[icon2html(src, viewers(user.loc))] [message]")
if(chattering)
chatter(message, phomeme, user)
@@ -1082,7 +1082,7 @@
user.visible_message("[user] pulls back the string on [src].")
icon_state = "[initial(icon_state)]_used"
sleep(5)
- audible_message("[bicon(src)] Hiss!")
+ audible_message("[icon2html(src, viewers(src))] Hiss!")
var/list/possible_sounds = list('sound/voice/hiss1.ogg', 'sound/voice/hiss2.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss4.ogg')
var/chosen_sound = pick(possible_sounds)
playsound(get_turf(src), chosen_sound, 50, 1)
diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm
index 6f2310303b..66e3e0317f 100644
--- a/code/game/objects/items/weapons/AI_modules.dm
+++ b/code/game/objects/items/weapons/AI_modules.dm
@@ -525,7 +525,7 @@ AI MODULES
laws[1] = generate_ion_law()
to_chat(user, "You press the button on [src].")
playsound(user, 'sound/machines/click.ogg', 20, 1)
- src.loc.visible_message("[bicon(src)] [laws[1]]")
+ src.loc.visible_message("[icon2html(src, viewers(loc))] [laws[1]]")
/******************** Mother Drone ******************/
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index 3f89e593d5..e4a69dfab7 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -106,7 +106,7 @@
update_label()
/obj/item/weapon/card/id/attack_self(mob/user)
- user.visible_message("[user] shows you: [bicon(src)] [src.name].", \
+ user.visible_message("[user] shows you: [icon2html(src, viewers(user))] [src.name].", \
"You show \the [src.name].")
src.add_fingerprint(user)
return
diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm
index 0e6d6cc66f..1829538a01 100755
--- a/code/game/objects/items/weapons/flamethrower.dm
+++ b/code/game/objects/items/weapons/flamethrower.dm
@@ -26,6 +26,7 @@
var/create_full = FALSE
var/create_with_tank = FALSE
var/igniter_type = /obj/item/device/assembly/igniter
+ trigger_guard = TRIGGER_GUARD_NORMAL
/obj/item/weapon/flamethrower/Destroy()
if(weldtool)
@@ -69,12 +70,7 @@
if(flag)
return // too close
if(ishuman(user))
- var/mob/living/carbon/human/H = user
- if(H.dna.check_mutation(HULK))
- to_chat(user, "Your meaty finger is much too large for the trigger guard!")
- return
- if(NOGUNS in H.dna.species.species_traits)
- to_chat(user, "Your fingers don't fit in the trigger guard!")
+ if(!can_trigger_gun(user))
return
if(user && user.get_active_held_item() == src) // Make sure our user is still holding us
var/turf/target_turf = get_turf(target)
diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm
index 238022d209..8e1cf3301e 100644
--- a/code/game/objects/items/weapons/holy_weapons.dm
+++ b/code/game/objects/items/weapons/holy_weapons.dm
@@ -320,6 +320,8 @@
desc = "Particularly twisted dieties grant gifts of dubious value."
icon_state = "arm_blade"
item_state = "arm_blade"
+ lefthand_file = 'icons/mob/inhands/antag/changeling_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi'
flags = ABSTRACT | NODROP
w_class = WEIGHT_CLASS_HUGE
sharpness = IS_SHARP
diff --git a/code/game/objects/items/weapons/pneumaticCannon.dm b/code/game/objects/items/weapons/pneumaticCannon.dm
index d2f5714d5e..ab61e7b916 100644
--- a/code/game/objects/items/weapons/pneumaticCannon.dm
+++ b/code/game/objects/items/weapons/pneumaticCannon.dm
@@ -26,6 +26,7 @@
var/fire_mode = PCANNON_FIREALL
var/automatic = FALSE
var/clumsyCheck = TRUE
+ trigger_guard = TRIGGER_GUARD_NORMAL
/obj/item/weapon/pneumatic_cannon/CanItemAutoclick()
return automatic
@@ -37,10 +38,10 @@
out += "You'll need to get closer to see any more."
return
for(var/obj/item/I in loadedItems)
- out += "[bicon(I)] It has \the [I] loaded."
+ out += "[icon2html(I, user)] It has \the [I] loaded."
CHECK_TICK
if(tank)
- out += "[bicon(tank)] It has \the [tank] mounted onto it."
+ out += "[icon2html(tank, user)] It has \the [tank] mounted onto it."
to_chat(user, out.Join("
"))
/obj/item/weapon/pneumatic_cannon/attackby(obj/item/weapon/W, mob/user, params)
@@ -108,11 +109,7 @@
if(!istype(user) && !target)
return
var/discharge = 0
- if(user.dna.check_mutation(HULK))
- to_chat(user, "Your meaty finger is much too large for the trigger guard!")
- return
- if(NOGUNS in user.dna.species.species_traits)
- to_chat(user, "Your fingers don't fit in the trigger guard!")
+ if(!can_trigger_gun(user))
return
if(!loadedItems || !loadedWeightClass)
to_chat(user, "\The [src] has nothing loaded.")
diff --git a/code/game/objects/items/weapons/powerfist.dm b/code/game/objects/items/weapons/powerfist.dm
index 256cdc0433..77d7784852 100644
--- a/code/game/objects/items/weapons/powerfist.dm
+++ b/code/game/objects/items/weapons/powerfist.dm
@@ -26,7 +26,7 @@
to_chat(user, "You'll need to get closer to see any more.")
return
if(tank)
- to_chat(user, "[bicon(tank)] It has \the [tank] mounted onto it.")
+ to_chat(user, "[icon2html(tank, user)] It has \the [tank] mounted onto it.")
/obj/item/weapon/melee/powerfist/attackby(obj/item/weapon/W, mob/user, params)
diff --git a/code/game/objects/items/weapons/sharpener.dm b/code/game/objects/items/weapons/sharpener.dm
index ace66060af..881832b5bb 100644
--- a/code/game/objects/items/weapons/sharpener.dm
+++ b/code/game/objects/items/weapons/sharpener.dm
@@ -12,31 +12,31 @@
/obj/item/weapon/sharpener/attackby(obj/item/I, mob/user, params)
if(used)
- to_chat(user, "The sharpening block is too worn to use again.")
+ to_chat(user, "The sharpening block is too worn to use again!")
return
if(I.force >= max || I.throwforce >= max)//no esword sharpening
- to_chat(user, "[I] is much too powerful to sharpen further.")
+ to_chat(user, "[I] is much too powerful to sharpen further!")
return
if(requires_sharpness && !I.sharpness)
- to_chat(user, "You can only sharpen items that are already sharp, such as knives.")
+ to_chat(user, "You can only sharpen items that are already sharp, such as knives!")
return
if(istype(I, /obj/item/weapon/melee/transforming/energy))
- to_chat(user, "You don't think \the [I] will be the thing getting modified if you use it on \the [src].")
+ to_chat(user, "You don't think \the [I] will be the thing getting modified if you use it on \the [src]!")
return
if(istype(I, /obj/item/weapon/twohanded))//some twohanded items should still be sharpenable, but handle force differently. therefore i need this stuff
var/obj/item/weapon/twohanded/TH = I
if(TH.force_wielded >= max)
- to_chat(user, "[TH] is much too powerful to sharpen further.")
+ to_chat(user, "[TH] is much too powerful to sharpen further!")
return
if(TH.wielded)
- to_chat(user, "[TH] must be unwielded before it can be sharpened.")
+ to_chat(user, "[TH] must be unwielded before it can be sharpened!")
return
if(TH.force_wielded > initial(TH.force_wielded))
- to_chat(user, "[TH] has already been refined before. It cannot be sharpened further.")
+ to_chat(user, "[TH] has already been refined before. It cannot be sharpened further!")
return
TH.force_wielded = Clamp(TH.force_wielded + increment, 0, max)//wieldforce is increased since normal force wont stay
if(I.force > initial(I.force))
- to_chat(user, "[I] has already been refined before. It cannot be sharpened further.")
+ to_chat(user, "[I] has already been refined before. It cannot be sharpened further!")
return
user.visible_message("[user] sharpens [I] with [src]!", "You sharpen [I], making it much more deadly than before.")
I.sharpness = IS_SHARP_ACCURATE
@@ -46,6 +46,7 @@
name = "worn out [name]"
desc = "[desc] At least, it used to."
used = 1
+ update_icon()
/obj/item/weapon/sharpener/super
name = "super whetstone"
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index bb723ffb33..53bfe5d64c 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -1,4 +1,5 @@
/obj/item/weapon
+ var/trigger_guard = TRIGGER_GUARD_NONE
/obj/item/weapon/banhammer
desc = "A banhammer"
@@ -584,3 +585,8 @@
throwforce = 0
flags = DROPDEL | ABSTRACT
attack_verb = list("bopped")
+
+/obj/item/weapon/proc/can_trigger_gun(mob/living/user)
+ if(!user.can_use_guns(src))
+ return FALSE
+ return TRUE
\ No newline at end of file
diff --git a/code/game/objects/structures/fireaxe.dm b/code/game/objects/structures/fireaxe.dm
index 24e70059af..bfd3dea037 100644
--- a/code/game/objects/structures/fireaxe.dm
+++ b/code/game/objects/structures/fireaxe.dm
@@ -12,8 +12,8 @@
max_integrity = 150
integrity_failure = 50
-/obj/structure/fireaxecabinet/New()
- ..()
+/obj/structure/fireaxecabinet/Initialize()
+ . = ..()
update_icon()
/obj/structure/fireaxecabinet/Destroy()
diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm
index e478ff5d92..d141f71b7a 100644
--- a/code/game/objects/structures/flora.dm
+++ b/code/game/objects/structures/flora.dm
@@ -1,12 +1,13 @@
/obj/structure/flora
resistance_flags = FLAMMABLE
+ obj_integrity = 150
max_integrity = 150
- anchored = TRUE
+ anchored = 1
//trees
/obj/structure/flora/tree
name = "tree"
- density = TRUE
+ density = 1
pixel_x = -16
layer = FLY_LAYER
var/cut = FALSE
@@ -25,7 +26,7 @@
playsound(get_turf(src), 'sound/effects/meteorimpact.ogg', 100 , 0, 0)
icon = 'icons/obj/flora/pinetrees.dmi'
icon_state = "tree_stump"
- density = FALSE
+ density = 0
pixel_x = -16
name += " stump"
cut = TRUE
@@ -45,14 +46,14 @@
/obj/structure/flora/tree/pine/Initialize()
icon_state = "pine_[rand(1, 3)]"
- ..()
+ . = ..()
/obj/structure/flora/tree/pine/xmas
name = "xmas tree"
icon_state = "pine_c"
/obj/structure/flora/tree/pine/xmas/Initialize()
- ..()
+ . = ..()
icon_state = "pine_c"
/obj/structure/flora/tree/dead
@@ -64,7 +65,7 @@
icon_state = "palm1"
/obj/structure/flora/tree/palm/Initialize()
- ..()
+ . = ..()
icon_state = pick("palm1","palm2")
pixel_x = 0
@@ -76,7 +77,7 @@
/obj/structure/flora/tree/dead/Initialize()
icon_state = "tree_[rand(1, 6)]"
- ..()
+ . = ..()
/obj/structure/flora/tree/jungle
name = "tree"
@@ -88,12 +89,7 @@
/obj/structure/flora/tree/jungle/Initialize()
icon_state = "[icon_state][rand(1, 6)]"
- ..()
-
-/obj/structure/flora/tree/jungle/small
- pixel_y = 0
- pixel_x = -32
- icon = 'icons/obj/flora/jungletreesmall.dmi'
+ . = ..()
//grass
/obj/structure/flora/grass
@@ -106,7 +102,7 @@
/obj/structure/flora/grass/brown/Initialize()
icon_state = "snowgrass[rand(1, 3)]bb"
- ..()
+ . = ..()
/obj/structure/flora/grass/green
@@ -114,14 +110,14 @@
/obj/structure/flora/grass/green/Initialize()
icon_state = "snowgrass[rand(1, 3)]gb"
- ..()
+ . = ..()
/obj/structure/flora/grass/both
icon_state = "snowgrassall1"
/obj/structure/flora/grass/both/Initialize()
icon_state = "snowgrassall[rand(1, 3)]"
- ..()
+ . = ..()
//bushes
@@ -129,11 +125,11 @@
name = "bush"
icon = 'icons/obj/flora/snowflora.dmi'
icon_state = "snowbush1"
- anchored = TRUE
+ anchored = 1
/obj/structure/flora/bush/Initialize()
icon_state = "snowbush[rand(1, 6)]"
- ..()
+ . = ..()
//newbushes
@@ -145,112 +141,112 @@
/obj/structure/flora/ausbushes/Initialize()
if(icon_state == "firstbush_1")
icon_state = "firstbush_[rand(1, 4)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/reedbush
icon_state = "reedbush_1"
/obj/structure/flora/ausbushes/reedbush/Initialize()
icon_state = "reedbush_[rand(1, 4)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/leafybush
icon_state = "leafybush_1"
/obj/structure/flora/ausbushes/leafybush/Initialize()
icon_state = "leafybush_[rand(1, 3)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/palebush
icon_state = "palebush_1"
/obj/structure/flora/ausbushes/palebush/Initialize()
icon_state = "palebush_[rand(1, 4)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/stalkybush
icon_state = "stalkybush_1"
/obj/structure/flora/ausbushes/stalkybush/Initialize()
icon_state = "stalkybush_[rand(1, 3)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/grassybush
icon_state = "grassybush_1"
/obj/structure/flora/ausbushes/grassybush/Initialize()
icon_state = "grassybush_[rand(1, 4)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/fernybush
icon_state = "fernybush_1"
/obj/structure/flora/ausbushes/fernybush/Initialize()
icon_state = "fernybush_[rand(1, 3)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/sunnybush
icon_state = "sunnybush_1"
/obj/structure/flora/ausbushes/sunnybush/Initialize()
icon_state = "sunnybush_[rand(1, 3)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/genericbush
icon_state = "genericbush_1"
/obj/structure/flora/ausbushes/genericbush/Initialize()
icon_state = "genericbush_[rand(1, 4)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/pointybush
icon_state = "pointybush_1"
/obj/structure/flora/ausbushes/pointybush/Initialize()
icon_state = "pointybush_[rand(1, 4)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/lavendergrass
icon_state = "lavendergrass_1"
/obj/structure/flora/ausbushes/lavendergrass/Initialize()
icon_state = "lavendergrass_[rand(1, 4)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/ywflowers
icon_state = "ywflowers_1"
/obj/structure/flora/ausbushes/ywflowers/Initialize()
icon_state = "ywflowers_[rand(1, 3)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/brflowers
icon_state = "brflowers_1"
/obj/structure/flora/ausbushes/brflowers/Initialize()
icon_state = "brflowers_[rand(1, 3)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/ppflowers
icon_state = "ppflowers_1"
/obj/structure/flora/ausbushes/ppflowers/Initialize()
icon_state = "ppflowers_[rand(1, 3)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/sparsegrass
icon_state = "sparsegrass_1"
/obj/structure/flora/ausbushes/sparsegrass/Initialize()
icon_state = "sparsegrass_[rand(1, 3)]"
- ..()
+ . = ..()
/obj/structure/flora/ausbushes/fullgrass
icon_state = "fullgrass_1"
/obj/structure/flora/ausbushes/fullgrass/Initialize()
icon_state = "fullgrass_[rand(1, 3)]"
- ..()
+ . = ..()
/obj/item/weapon/twohanded/required/kirbyplants
name = "potted plant"
@@ -308,10 +304,10 @@
desc = "A volcanic rock"
icon = 'icons/obj/flora/rocks.dmi'
resistance_flags = FIRE_PROOF
- density = TRUE
+ density = 1
/obj/structure/flora/rock/Initialize()
- ..()
+ . = ..()
icon_state = "[icon_state][rand(1,3)]"
/obj/structure/flora/rock/pile
@@ -319,7 +315,7 @@
desc = "A pile of rocks"
/obj/structure/flora/rock/pile/Initialize()
- ..()
+ . = ..()
icon_state = "[icon_state][rand(1,3)]"
//Jungle grass
@@ -333,7 +329,7 @@
/obj/structure/flora/grass/jungle/Initialize()
icon_state = "[icon_state][rand(1, 5)]"
- ..()
+ . = ..()
/obj/structure/flora/grass/jungle/b
icon_state = "grassb"
@@ -348,7 +344,7 @@
density = FALSE
/obj/structure/flora/rock/jungle/Initialize()
- ..()
+ . = ..()
icon_state = "[initial(icon_state)][rand(1,5)]"
@@ -361,7 +357,7 @@
/obj/structure/flora/junglebush/Initialize()
icon_state = "[icon_state][rand(1, 3)]"
- ..()
+ . = ..()
/obj/structure/flora/junglebush/b
icon_state = "bushb"
diff --git a/code/game/objects/structures/flora.dm.rej b/code/game/objects/structures/flora.dm.rej
new file mode 100644
index 0000000000..8257ec2122
--- /dev/null
+++ b/code/game/objects/structures/flora.dm.rej
@@ -0,0 +1,28 @@
+diff a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm (rejected hunks)
+@@ -89,7 +89,7 @@
+
+ /obj/structure/flora/tree/jungle/Initialize()
+ icon_state = "[icon_state][rand(1, 6)]"
+- ..()
++ . = ..()
+
+ //grass
+ /obj/structure/flora/grass
+@@ -307,7 +307,7 @@
+ density = 1
+
+ /obj/structure/flora/rock/Initialize()
+- ..()
++ . = ..()
+ icon_state = "[icon_state][rand(1,3)]"
+
+ /obj/structure/flora/rock/pile
+@@ -381,5 +381,5 @@
+ pixel_y = -16
+
+ /obj/structure/flora/rock/pile/largejungle/Initialize()
+- ..()
+- icon_state = "[initial(icon_state)][rand(1,3)]"
+\ No newline at end of file
++ . = ..()
++ icon_state = "[initial(icon_state)][rand(1,3)]"
diff --git a/code/game/objects/structures/manned_turret.dm b/code/game/objects/structures/manned_turret.dm
index 323927af77..7448aa128f 100644
--- a/code/game/objects/structures/manned_turret.dm
+++ b/code/game/objects/structures/manned_turret.dm
@@ -85,7 +85,7 @@
calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(controller, C.mouseParams)
/obj/machinery/manned_turret/proc/direction_track(mob/user, atom/targeted)
- if(user.stat != CONSCIOUS)
+ if(user.incapacitated())
return
setDir(get_dir(src,targeted))
user.setDir(dir)
@@ -125,7 +125,7 @@
/obj/machinery/manned_turret/proc/checkfire(atom/targeted_atom, mob/user)
target = targeted_atom
- if(target == user || target == get_turf(src))
+ if(target == user || user.incapacitated() || target == get_turf(src))
return
if(world.time < cooldown)
if(!warned && world.time > (cooldown - cooldown_duration + rate_of_fire*number_of_shots)) // To capture the window where one is done firing
@@ -143,6 +143,8 @@
addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper, user), i*rate_of_fire)
/obj/machinery/manned_turret/proc/fire_helper(mob/user)
+ if(user.incapacitated())
+ return
update_positioning() //REFRESH MOUSE TRACKING!!
var/turf/targets_from = get_turf(src)
if(QDELETED(target))
diff --git a/code/game/sound.dm b/code/game/sound.dm
index c728071e50..ff35915b08 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -78,7 +78,7 @@
S.y = 1
S.falloff = (falloff ? falloff : FALLOFF_SOUNDS)
- src << S
+ SEND_SOUND(src, S)
/proc/sound_to_playing_players(sound, volume = 100, vary)
sound = get_sfx(sound)
@@ -94,13 +94,13 @@
next_channel = 1
/mob/proc/stop_sound_channel(chan)
- src << sound(null, repeat = 0, wait = 0, channel = chan)
+ SEND_SOUND(src, sound(null, repeat = 0, wait = 0, channel = chan))
/client/proc/playtitlemusic()
UNTIL(SSticker.login_music) //wait for SSticker init to set the login music
if(prefs && (prefs.toggles & SOUND_LOBBY))
- src << sound(SSticker.login_music, repeat = 0, wait = 0, volume = 85, channel = CHANNEL_LOBBYMUSIC) // MAD JAMS
+ SEND_SOUND(src, sound(SSticker.login_music, repeat = 0, wait = 0, volume = 85, channel = CHANNEL_LOBBYMUSIC) // MAD JAMS)
/proc/get_rand_frequency()
return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs.
@@ -175,7 +175,3 @@
'sound/vore/prey/death_07.ogg','sound/vore/prey/death_08.ogg','sound/vore/prey/death_09.ogg',
'sound/vore/prey/death_10.ogg')
return soundin
-
-/proc/playsound_global(file, repeat = 0, wait, channel, volume)
- for(var/V in GLOB.clients)
- V << sound(file, repeat, wait, channel, volume)
diff --git a/code/game/sound.dm.rej b/code/game/sound.dm.rej
new file mode 100644
index 0000000000..003c8b9975
--- /dev/null
+++ b/code/game/sound.dm.rej
@@ -0,0 +1,9 @@
+diff a/code/game/sound.dm b/code/game/sound.dm (rejected hunks)
+@@ -145,7 +145,3 @@
+ if ("can_open")
+ soundin = pick('sound/effects/can_open1.ogg', 'sound/effects/can_open2.ogg', 'sound/effects/can_open3.ogg')
+ return soundin
+-
+-/proc/playsound_global(file, repeat = 0, wait, channel, volume)
+- for(var/V in GLOB.clients)
+- V << sound(file, repeat, wait, channel, volume)
diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm
index 82ff907a04..a990530056 100644
--- a/code/game/turfs/open.dm
+++ b/code/game/turfs/open.dm
@@ -18,6 +18,7 @@
var/sound
/turf/open/indestructible/sound/Entered(var/mob/AM)
+ ..()
if(istype(AM))
playsound(src,sound,50,1)
diff --git a/code/game/turfs/simulated/chasm.dm b/code/game/turfs/simulated/chasm.dm
index 968e782984..a51240c969 100644
--- a/code/game/turfs/simulated/chasm.dm
+++ b/code/game/turfs/simulated/chasm.dm
@@ -22,6 +22,7 @@
return
/turf/open/chasm/Entered(atom/movable/AM)
+ ..()
START_PROCESSING(SSobj, src)
drop_stuff(AM)
diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm
index c7e6973c4d..b877fa9eac 100644
--- a/code/game/turfs/space/transit.dm
+++ b/code/game/turfs/space/transit.dm
@@ -25,6 +25,7 @@
dir = EAST
/turf/open/space/transit/Entered(atom/movable/AM, atom/OldLoc)
+ ..()
if(!locate(/obj/structure/lattice) in src)
throw_atom(AM)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index b204406d05..4342d12714 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -160,6 +160,7 @@
return TRUE //Nothing found to block so return success!
/turf/Entered(atom/movable/AM)
+ ..()
if(explosion_level && AM.ex_check(explosion_id))
AM.ex_act(explosion_level)
diff --git a/code/game/world.dm b/code/game/world.dm
new file mode 100644
index 0000000000..f5b45a46ca
--- /dev/null
+++ b/code/game/world.dm
@@ -0,0 +1,292 @@
+/world/New()
+ log_world("World loaded at [time_stamp()]")
+
+ SetupExternalRSC()
+
+ GLOB.config_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = file("data/logs/config_error.log") //temporary file used to record errors with loading config, moved to log directory once logging is set bl
+
+ make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
+
+ config = new
+
+ CheckSchemaVersion()
+ SetRoundID()
+
+ SetupLogs()
+
+ if(!RunningService()) //tgs2 support
+ GLOB.revdata.DownloadPRDetails()
+
+ load_motd()
+ load_admins()
+ LoadVerbs(/datum/verbs/menu)
+ if(config.usewhitelist)
+ load_whitelist()
+ LoadBans()
+
+ GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
+
+ Master.Initialize(10, FALSE)
+
+ if(config.irc_announce_new_game)
+ IRCBroadcast("New round starting on [SSmapping.config.map_name]!")
+
+/world/proc/SetupExternalRSC()
+#if (PRELOAD_RSC == 0)
+ external_rsc_urls = world.file2list("config/external_rsc_urls.txt","\n")
+ var/i=1
+ while(i<=external_rsc_urls.len)
+ if(external_rsc_urls[i])
+ i++
+ else
+ external_rsc_urls.Cut(i,i+1)
+#endif
+
+/world/proc/CheckSchemaVersion()
+ if(config.sql_enabled)
+ if(SSdbcore.Connect())
+ log_world("Database connection established.")
+ var/datum/DBQuery/query_db_version = SSdbcore.NewQuery("SELECT major, minor FROM [format_table_name("schema_revision")] ORDER BY date DESC LIMIT 1")
+ query_db_version.Execute()
+ if(query_db_version.NextRow())
+ var/db_major = text2num(query_db_version.item[1])
+ var/db_minor = text2num(query_db_version.item[2])
+ if(db_major < DB_MAJOR_VERSION || db_minor < DB_MINOR_VERSION)
+ message_admins("Database schema ([db_major].[db_minor]) is behind latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors")
+ log_sql("Database schema ([db_major].[db_minor]) is behind latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors")
+ else
+ message_admins("Could not get schema version from database")
+ else
+ log_world("Your server failed to establish a connection with the database.")
+
+/world/proc/SetRoundID()
+ if(config.sql_enabled)
+ if(SSdbcore.Connect())
+ var/datum/DBQuery/query_round_start = SSdbcore.NewQuery("INSERT INTO [format_table_name("round")] (start_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]')")
+ query_round_start.Execute()
+ var/datum/DBQuery/query_round_last_id = SSdbcore.NewQuery("SELECT LAST_INSERT_ID()")
+ query_round_last_id.Execute()
+ if(query_round_last_id.NextRow())
+ GLOB.round_id = query_round_last_id.item[1]
+
+/world/proc/SetupLogs()
+ GLOB.log_directory = "data/logs/[time2text(world.realtime, "YYYY/MM/DD")]/round-"
+ if(GLOB.round_id)
+ GLOB.log_directory += "[GLOB.round_id]"
+ else
+ GLOB.log_directory += "[replacetext(time_stamp(), ":", ".")]"
+ GLOB.world_game_log = file("[GLOB.log_directory]/game.log")
+ GLOB.world_attack_log = file("[GLOB.log_directory]/attack.log")
+ GLOB.world_runtime_log = file("[GLOB.log_directory]/runtime.log")
+ GLOB.world_href_log = file("[GLOB.log_directory]/hrefs.html")
+ WRITE_FILE(GLOB.world_game_log, "\n\nStarting up round ID [GLOB.round_id]. [time_stamp()]\n---------------------")
+ WRITE_FILE(GLOB.world_attack_log, "\n\nStarting up round ID [GLOB.round_id]. [time_stamp()]\n---------------------")
+ WRITE_FILE(GLOB.world_runtime_log, "\n\nStarting up round ID [GLOB.round_id]. [time_stamp()]\n---------------------")
+ GLOB.changelog_hash = md5('html/changelog.html') //used for telling if the changelog has changed recently
+ if(fexists(GLOB.config_error_log))
+ fcopy(GLOB.config_error_log, "[GLOB.log_directory]/config_error.log")
+ fdel(GLOB.config_error_log)
+
+ if(GLOB.round_id)
+ log_game("Round ID: [GLOB.round_id]")
+
+/world/Topic(T, addr, master, key)
+ var/list/input = params2list(T)
+
+ var/pinging = ("ping" in input)
+ var/playing = ("players" in input)
+
+ if(!pinging && !playing && config && config.log_world_topic)
+ WRITE_FILE(GLOB.world_game_log, "TOPIC: \"[T]\", from:[addr], master:[master], key:[key]")
+
+ if(input[SERVICE_CMD_PARAM_KEY])
+ return ServiceCommand(input)
+ var/key_valid = (global.comms_allowed && input["key"] == global.comms_key)
+
+ if(pinging)
+ var/x = 1
+ for (var/client/C in GLOB.clients)
+ x++
+ return x
+
+ else if(playing)
+ var/n = 0
+ for(var/mob/M in GLOB.player_list)
+ if(M.client)
+ n++
+ return n
+
+ else if("ircstatus" in input) //tgs2 support
+ var/static/last_irc_status = 0
+ if(world.time - last_irc_status < 50)
+ return
+ var/list/adm = get_admin_counts()
+ var/list/allmins = adm["total"]
+ var/status = "Admins: [allmins.len] (Active: [english_list(adm["present"])] AFK: [english_list(adm["afk"])] Stealth: [english_list(adm["stealth"])] Skipped: [english_list(adm["noflags"])]). "
+ status += "Players: [GLOB.clients.len] (Active: [get_active_player_count(0,1,0)]). Mode: [SSticker.mode.name]."
+ send2irc("Status", status)
+ last_irc_status = world.time
+
+ else if("status" in input)
+ var/list/s = list()
+ s["version"] = GLOB.game_version
+ s["mode"] = GLOB.master_mode
+ s["respawn"] = config ? GLOB.abandon_allowed : 0
+ s["enter"] = GLOB.enter_allowed
+ s["vote"] = config.allow_vote_mode
+ s["ai"] = config.allow_ai
+ s["host"] = host ? host : null
+ s["active_players"] = get_active_player_count()
+ s["players"] = GLOB.clients.len
+ s["revision"] = GLOB.revdata.commit
+ s["revision_date"] = GLOB.revdata.date
+
+ var/list/adm = get_admin_counts()
+ var/list/presentmins = adm["present"]
+ var/list/afkmins = adm["afk"]
+ s["admins"] = presentmins.len + afkmins.len //equivalent to the info gotten from adminwho
+ s["gamestate"] = SSticker.current_state
+
+ s["map_name"] = SSmapping.config.map_name
+
+ if(key_valid && SSticker.HasRoundStarted())
+ s["real_mode"] = SSticker.mode.name
+ // Key-authed callers may know the truth behind the "secret"
+
+ s["security_level"] = get_security_level()
+ s["round_duration"] = SSticker ? round((world.time-SSticker.round_start_time)/10) : 0
+ // Amount of world's ticks in seconds, useful for calculating round duration
+
+ if(SSshuttle && SSshuttle.emergency)
+ s["shuttle_mode"] = SSshuttle.emergency.mode
+ // Shuttle status, see /__DEFINES/stat.dm
+ s["shuttle_timer"] = SSshuttle.emergency.timeLeft()
+ // Shuttle timer, in seconds
+
+ return list2params(s)
+
+ else if("announce" in input)
+ if(!key_valid)
+ return "Bad Key"
+ else
+ AnnouncePR(input["announce"], json_decode(input["payload"]))
+
+ else if("crossmessage" in input)
+ if(!key_valid)
+ return
+ else
+ if(input["crossmessage"] == "Ahelp")
+ relay_msg_admins("HELP: [input["source"]] [input["message_sender"]]: [input["message"]]")
+ if(input["crossmessage"] == "Comms_Console")
+ minor_announce(input["message"], "Incoming message from [input["message_sender"]]")
+ for(var/obj/machinery/computer/communications/CM in GLOB.machines)
+ CM.overrideCooldown()
+ if(input["crossmessage"] == "News_Report")
+ minor_announce(input["message"], "Breaking Update From [input["message_sender"]]")
+
+ else if("adminmsg" in input) //tgs2 support
+ if(!key_valid)
+ return "Bad Key"
+ else
+ return IrcPm(input["adminmsg"],input["msg"],input["sender"])
+
+ else if("namecheck" in input) //tgs2 support
+ if(!key_valid)
+ return "Bad Key"
+ else
+ log_admin("IRC Name Check: [input["sender"]] on [input["namecheck"]]")
+ message_admins("IRC name checking on [input["namecheck"]] from [input["sender"]]")
+ return keywords_lookup(input["namecheck"],1)
+ else if("adminwho" in input) //tgs2 support
+ if(!key_valid)
+ return "Bad Key"
+ else
+ return ircadminwho()
+ else if("server_hop" in input)
+ show_server_hop_transfer_screen(input["server_hop"])
+
+/world/proc/AnnouncePR(announcement, list/payload)
+ var/static/list/PRcounts = list() //PR id -> number of times announced this round
+ var/id = "[payload["pull_request"]["id"]]"
+ if(!PRcounts[id])
+ PRcounts[id] = 1
+ else
+ ++PRcounts[id]
+ if(PRcounts[id] > PR_ANNOUNCEMENTS_PER_ROUND)
+ return
+
+ var/final_composed = "PR: [announcement]"
+ for(var/client/C in GLOB.clients)
+ C.AnnouncePR(final_composed)
+
+/world/Reboot(reason = 0, fast_track = FALSE)
+ ServiceReboot() //handles alternative actions if necessary
+ if (reason || fast_track) //special reboot, do none of the normal stuff
+ if (usr)
+ log_admin("[key_name(usr)] Has requested an immediate world restart via client side debugging tools")
+ message_admins("[key_name_admin(usr)] Has requested an immediate world restart via client side debugging tools")
+ to_chat(world, "Rebooting World immediately due to host request")
+ else
+ to_chat(world, "Rebooting world...")
+ Master.Shutdown() //run SS shutdowns
+ log_world("World rebooted at [time_stamp()]")
+ ..()
+
+/world/proc/load_motd()
+ GLOB.join_motd = file2text("config/motd.txt") + "
" + GLOB.revdata.GetTestMergeInfo()
+
+/world/proc/update_status()
+ var/s = ""
+
+ if (config && config.server_name)
+ s += "[config.server_name] — "
+
+ s += "[station_name()]";
+ s += " ("
+ s += "" //Change this to wherever you want the hub to link to.
+ s += "Default" //Replace this with something else. Or ever better, delete it and uncomment the game version.
+ s += ""
+ s += ")"
+
+ var/list/features = list()
+
+ if(GLOB.master_mode)
+ features += GLOB.master_mode
+
+ if (!GLOB.enter_allowed)
+ features += "closed"
+
+ features += GLOB.abandon_allowed ? "respawn" : "no respawn"
+
+ if (config && config.allow_vote_mode)
+ features += "vote"
+
+ if (config && config.allow_ai)
+ features += "AI allowed"
+
+ var/n = 0
+ for (var/mob/M in GLOB.player_list)
+ if (M.client)
+ n++
+
+ if (n > 1)
+ features += "~[n] players"
+ else if (n > 0)
+ features += "~[n] player"
+
+ if (!host && config && config.hostedby)
+ features += "hosted by [config.hostedby]"
+
+ if (features)
+ s += ": [jointext(features, ", ")]"
+
+ status = s
+
+/world/proc/update_hub_visibility(new_visibility)
+ if(new_visibility == GLOB.hub_visibility)
+ return
+ GLOB.hub_visibility = new_visibility
+ if(GLOB.hub_visibility)
+ hub_password = "kMZy3U5jJHSiBQjr"
+ else
+ hub_password = "SORRYNOPASSWORD"
diff --git a/code/modules/admin/DB_ban/functions.dm b/code/modules/admin/DB_ban/functions.dm
index 23bf656b8c..e580b306b3 100644
--- a/code/modules/admin/DB_ban/functions.dm
+++ b/code/modules/admin/DB_ban/functions.dm
@@ -83,10 +83,10 @@
var/a_computerid
var/a_ip
- if(src.owner && istype(src.owner, /client))
- a_ckey = src.owner:ckey
- a_computerid = src.owner:computer_id
- a_ip = src.owner:address
+ if(istype(owner))
+ a_ckey = owner.ckey
+ a_computerid = owner.computer_id
+ a_ip = owner.address
if(blockselfban)
if(a_ckey == ckey)
@@ -309,12 +309,12 @@
to_chat(usr, "Database update failed due to multiple bans having the same ID. Contact the database admin.")
return
- if(!src.owner || !istype(src.owner, /client))
+ if(!istype(owner))
return
- var/unban_ckey = src.owner:ckey
- var/unban_computerid = src.owner:computer_id
- var/unban_ip = src.owner:address
+ var/unban_ckey = owner.ckey
+ var/unban_computerid = owner.computer_id
+ var/unban_ip = owner.address
var/sql_update = "UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = INET_ATON('[unban_ip]') WHERE id = [id]"
var/datum/DBQuery/query_unban = SSdbcore.NewQuery(sql_update)
diff --git a/code/modules/admin/NewBan.dm b/code/modules/admin/NewBan.dm
index 1ff2360923..5ea980a91d 100644
--- a/code/modules/admin/NewBan.dm
+++ b/code/modules/admin/NewBan.dm
@@ -109,14 +109,14 @@ GLOBAL_PROTECT(Banlist)
else
GLOB.Banlist.dir.Add("[ckey][computerid]")
GLOB.Banlist.cd = "/base/[ckey][computerid]"
- GLOB.Banlist["key"] << ckey
- GLOB.Banlist["id"] << computerid
- GLOB.Banlist["ip"] << address
- GLOB.Banlist["reason"] << reason
- GLOB.Banlist["bannedby"] << bannedby
- GLOB.Banlist["temp"] << temp
+ WRITE_FILE(GLOB.Banlist["key"], ckey)
+ WRITE_FILE(GLOB.Banlist["id"], computerid)
+ WRITE_FILE(GLOB.Banlist["ip"], address)
+ WRITE_FILE(GLOB.Banlist["reason"], reason)
+ WRITE_FILE(GLOB.Banlist["bannedby"], bannedby)
+ WRITE_FILE(GLOB.Banlist["temp"], temp)
if (temp)
- GLOB.Banlist["minutes"] << bantimestamp
+ WRITE_FILE(GLOB.Banlist["minutes"], bantimestamp)
if(!temp)
create_message("note", ckey, bannedby, "Permanently banned - [reason]", null, null, 0, 0)
else
@@ -211,17 +211,17 @@ GLOBAL_PROTECT(Banlist)
GLOB.Banlist.cd = "/base"
GLOB.Banlist.dir.Add("trash[i]trashid[i]")
GLOB.Banlist.cd = "/base/trash[i]trashid[i]"
- GLOB.Banlist["key"] << "trash[i]"
+ WRITE_FILE(GLOB.Banlist["key"], "trash[i]")
else
GLOB.Banlist.cd = "/base"
GLOB.Banlist.dir.Add("[last]trashid[i]")
GLOB.Banlist.cd = "/base/[last]trashid[i]"
- GLOB.Banlist["key"] << last
- GLOB.Banlist["id"] << "trashid[i]"
- GLOB.Banlist["reason"] << "Trashban[i]."
- GLOB.Banlist["temp"] << a
- GLOB.Banlist["minutes"] << GLOB.CMinutes + rand(1,2000)
- GLOB.Banlist["bannedby"] << "trashmin"
+ WRITE_FILE(GLOB.Banlist["key"], last)
+ WRITE_FILE(GLOB.Banlist["id"], "trashid[i]")
+ WRITE_FILE(GLOB.Banlist["reason"], "Trashban[i].")
+ WRITE_FILE(GLOB.Banlist["temp"], a)
+ WRITE_FILE(GLOB.Banlist["minutes"], GLOB.CMinutes + rand(1,2000))
+ WRITE_FILE(GLOB.Banlist["bannedby"], "trashmin")
last = "trash[i]"
GLOB.Banlist.cd = "/base"
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 7c20421d3c..5943e753a0 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -595,7 +595,7 @@
log_admin("[key_name(usr)] delayed the round start.")
else
to_chat(world, "The game will start in [newtime] seconds.")
- world << 'sound/ai/attention.ogg'
+ SEND_SOUND(world, sound('sound/ai/attention.ogg'))
log_admin("[key_name(usr)] set the pre-game delay to [newtime] seconds.")
SSblackbox.add_details("admin_verb","Delay Game Start") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm
index 54feb11532..2ca0593e8d 100644
--- a/code/modules/admin/admin_investigate.dm
+++ b/code/modules/admin/admin_investigate.dm
@@ -5,7 +5,7 @@
F << "[time_stamp()] \ref[src] ([x],[y],[z]) || [src] [message]
"
-/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY) )
+/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS) )
set name = "Investigate"
set category = "Admin"
if(!holder)
diff --git a/code/modules/admin/admin_investigate.dm.rej b/code/modules/admin/admin_investigate.dm.rej
new file mode 100644
index 0000000000..d58adb0f78
--- /dev/null
+++ b/code/modules/admin/admin_investigate.dm.rej
@@ -0,0 +1 @@
+garbage
\ No newline at end of file
diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm
index 73c2d8067e..828fbb2e91 100644
--- a/code/modules/admin/admin_ranks.dm
+++ b/code/modules/admin/admin_ranks.dm
@@ -142,7 +142,7 @@ GLOBAL_PROTECT(admin_ranks)
else
if(!SSdbcore.Connect())
log_world("Failed to connect to database in load_admin_ranks(). Reverting to legacy system.")
- GLOB.world_game_log << "Failed to connect to database in load_admin_ranks(). Reverting to legacy system."
+ WRITE_FILE(GLOB.world_game_log, "Failed to connect to database in load_admin_ranks(). Reverting to legacy system.")
config.admin_legacy_system = 1
load_admin_ranks()
return
@@ -220,7 +220,7 @@ GLOBAL_PROTECT(admin_ranks)
else
if(!SSdbcore.Connect())
log_world("Failed to connect to database in load_admins(). Reverting to legacy system.")
- GLOB.world_game_log << "Failed to connect to database in load_admins(). Reverting to legacy system."
+ WRITE_FILE(GLOB.world_game_log, "Failed to connect to database in load_admins(). Reverting to legacy system.")
config.admin_legacy_system = 1
load_admins()
return
diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm
index c3185c7b21..04a4b7877a 100644
--- a/code/modules/admin/secrets.dm
+++ b/code/modules/admin/secrets.dm
@@ -390,7 +390,7 @@
SSblackbox.add_details("admin_secrets_fun_used","Chinese Cartoons")
message_admins("[key_name_admin(usr)] made everything kawaii.")
for(var/mob/living/carbon/human/H in GLOB.mob_list)
- H << sound('sound/ai/animes.ogg')
+ SEND_SOUND(H, sound('sound/ai/animes.ogg'))
if(H.dna.species.id == "human")
if(H.dna.features["tail_human"] == "None" || H.dna.features["ears"] == "None")
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 818b0d6f09..ac047429c8 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -6,7 +6,7 @@
log_admin("[key_name(usr)] tried to use the admin panel without authorization.")
return
if(href_list["ahelp"])
- if(!check_rights(R_ADMIN))
+ if(!check_rights(R_ADMIN, TRUE))
return
var/ahelp_ref = href_list["ahelp"]
@@ -506,10 +506,10 @@
ban_unban_log_save("[key_name(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]")
message_admins("[key_name_admin(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]")
GLOB.Banlist.cd = "/base/[banfolder]"
- GLOB.Banlist["reason"] << reason
- GLOB.Banlist["temp"] << temp
- GLOB.Banlist["minutes"] << minutes
- GLOB.Banlist["bannedby"] << usr.ckey
+ WRITE_FILE(GLOB.Banlist["reason"], reason)
+ WRITE_FILE(GLOB.Banlist["temp"], temp)
+ WRITE_FILE(GLOB.Banlist["minutes"], minutes)
+ WRITE_FILE(GLOB.Banlist["bannedby"], usr.ckey)
GLOB.Banlist.cd = "/base"
SSblackbox.inc("ban_edit",1)
unbanpanel()
@@ -1697,7 +1697,7 @@
message_admins("[key_name(H)] got their cookie, spawned by [key_name(src.owner)].")
SSblackbox.inc("admin_cookies_spawned",1)
to_chat(H, "Your prayers have been answered!! You received the best cookie!")
- H << 'sound/effects/pray_chaplain.ogg'
+ SEND_SOUND(H, sound('sound/effects/pray_chaplain.ogg'))
else if(href_list["adminsmite"])
if(!check_rights(R_ADMIN|R_FUN))
diff --git a/code/modules/admin/verbs/BrokenInhands.dm b/code/modules/admin/verbs/BrokenInhands.dm
index 89eccf285d..732ae9e91c 100644
--- a/code/modules/admin/verbs/BrokenInhands.dm
+++ b/code/modules/admin/verbs/BrokenInhands.dm
@@ -28,7 +28,7 @@
if(text)
var/F = file("broken_icons.txt")
fdel(F)
- F << text
+ WRITE_FILE(F, text)
to_chat(world, "Completely successfully and written to [F]")
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index 44755c46fc..b19c736e14 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -259,7 +259,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
//send this msg to all admins
for(var/client/X in GLOB.admins)
if(X.prefs.toggles & SOUND_ADMINHELP)
- X << 'sound/effects/adminhelp.ogg'
+ SEND_SOUND(X, sound('sound/effects/adminhelp.ogg'))
window_flash(X, ignorepref = TRUE)
to_chat(X, admin_msg)
@@ -347,7 +347,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(initiator)
initiator.giveadminhelpverb()
- initiator << 'sound/effects/adminhelp.ogg'
+ SEND_SOUND(initiator, sound('sound/effects/adminhelp.ogg'))
to_chat(initiator, "- AdminHelp Rejected! -")
to_chat(initiator, "Your admin help was rejected. The adminhelp verb has been returned to you so that you may try again.")
diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm
index 7f4dd3ebb9..ec1091bb3c 100644
--- a/code/modules/admin/verbs/adminjump.dm
+++ b/code/modules/admin/verbs/adminjump.dm
@@ -84,11 +84,11 @@
var/list/keys = list()
for(var/mob/M in GLOB.player_list)
keys += M.client
- var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys)
+ var/client/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys)
if(!selection)
to_chat(src, "No keys found.")
return
- var/mob/M = selection:mob
+ var/mob/M = selection.mob
log_admin("[key_name(usr)] jumped to [key_name(M)]")
message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]")
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index 31fb08da36..db29021463 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -167,7 +167,7 @@
//play the recieving admin the adminhelp sound (if they have them enabled)
if(recipient.prefs.toggles & SOUND_ADMINHELP)
- recipient << 'sound/effects/adminhelp.ogg'
+ SEND_SOUND(recipient, sound('sound/effects/adminhelp.ogg'))
else
if(holder) //sender is an admin but recipient is not. Do BIG RED TEXT
@@ -182,7 +182,7 @@
admin_ticket_log(recipient, "PM From [key_name_admin(src)]: [keywordparsedmsg]")
//always play non-admin recipients the adminhelp sound
- recipient << 'sound/effects/adminhelp.ogg'
+ SEND_SOUND(recipient, sound('sound/effects/adminhelp.ogg'))
//AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn
if(config.popup_admin_pm)
@@ -301,7 +301,7 @@
window_flash(C, ignorepref = TRUE)
//always play non-admin recipients the adminhelp sound
- C << 'sound/effects/adminhelp.ogg'
+ SEND_SOUND(C, 'sound/effects/adminhelp.ogg')
C.ircreplyamount = IRCREPLYCOUNT
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index c69628c625..66438d1fac 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -316,10 +316,8 @@ GLOBAL_PROTECT(AdminProcCallCount)
alert("Wait until the game starts")
return
if(ishuman(M))
- log_admin("[key_name(src)] has alienized [M.key].")
- spawn(0)
- M:Alienize()
- SSblackbox.add_details("admin_verb","Make Alien") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ INVOKE_ASYNC(M, /mob/living/carbon/human/proc/Alienize)
+ SSblackbox.add_details("admin_verb","Make Alien") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] made [key_name(M)] into an alien.")
message_admins("[key_name_admin(usr)] made [key_name(M)] into an alien.")
else
@@ -333,10 +331,8 @@ GLOBAL_PROTECT(AdminProcCallCount)
alert("Wait until the game starts")
return
if(ishuman(M))
- log_admin("[key_name(src)] has slimeized [M.key].")
- spawn(0)
- M:slimeize()
- SSblackbox.add_details("admin_verb","Make Slime") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ INVOKE_ASYNC(M, /mob/living/carbon/human/proc/slimeize)
+ SSblackbox.add_details("admin_verb","Make Slime") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] made [key_name(M)] into a slime.")
message_admins("[key_name_admin(usr)] made [key_name(M)] into a slime.")
else
@@ -461,12 +457,14 @@ GLOBAL_PROTECT(AdminProcCallCount)
if(worn)
if(istype(worn, /obj/item/device/pda))
- worn:id = id
- id.loc = worn
+ var/obj/item/device/pda/PDA = worn
+ PDA.id = id
+ id.forceMove(PDA)
else if(istype(worn, /obj/item/weapon/storage/wallet))
- worn:front_id = id
- id.loc = worn
- worn.update_icon()
+ var/obj/item/weapon/storage/wallet/W = worn
+ W.front_id = id
+ id.forceMove(W)
+ W.update_icon()
else
H.equip_to_slot(id,slot_wear_id)
diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm
index 15b619f653..a4482154d8 100644
--- a/code/modules/admin/verbs/diagnostics.dm
+++ b/code/modules/admin/verbs/diagnostics.dm
@@ -78,8 +78,9 @@
continue
output += " [filters[filter]]: [f.len]
"
for (var/device in f)
- if (isobj(device))
- output += " [device] ([device:x],[device:y],[device:z] in area [get_area(device:loc)])
"
+ if (istype(device, /atom))
+ var/atom/A = device
+ output += " [device] ([A.x],[A.y],[A.z] in area [get_area(device)])
"
else
output += " [device]
"
diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm
index eb4c3a5f10..2bac326710 100644
--- a/code/modules/admin/verbs/playsound.dm
+++ b/code/modules/admin/verbs/playsound.dm
@@ -30,7 +30,7 @@
for(var/mob/M in GLOB.player_list)
if(M.client.prefs.toggles & SOUND_MIDI)
- M << admin_sound
+ SEND_SOUND(M, admin_sound)
SSblackbox.add_details("admin_verb","Play Global Sound") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -68,5 +68,5 @@
message_admins("[key_name_admin(src)] stopped all currently playing sounds.")
for(var/mob/M in GLOB.player_list)
if(M.client)
- M << sound(null)
+ SEND_SOUND(M, sound(null))
SSblackbox.add_details("admin_verb","Stop All Playing Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm
index 1b2fa82e20..bbe1c48b6a 100644
--- a/code/modules/admin/verbs/pray.dm
+++ b/code/modules/admin/verbs/pray.dm
@@ -33,14 +33,14 @@
prayer_type = "CULTIST PRAYER"
deity = "Nar-Sie"
- msg = "[bicon(cross)][prayer_type][deity ? " (to [deity])" : ""]: [ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]: [msg]"
+ msg = "[icon2html(cross, GLOB.admins)][prayer_type][deity ? " (to [deity])" : ""]: [ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]: [msg]"
for(var/client/C in GLOB.admins)
if(C.prefs.chat_toggles & CHAT_PRAYER)
to_chat(C, msg)
if(C.prefs.toggles & SOUND_PRAYERS)
if(usr.job == "Chaplain")
- C << 'sound/effects/pray.ogg'
+ SEND_SOUND(C, sound('sound/effects/pray.ogg'))
to_chat(usr, "Your prayers have been received by the gods.")
SSblackbox.add_details("admin_verb","Prayer") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm
index 2853fefcbf..6cd8efdd1d 100644
--- a/code/modules/assembly/bomb.dm
+++ b/code/modules/assembly/bomb.dm
@@ -44,7 +44,8 @@
qdel(src)
return
- if((istype(W, /obj/item/weapon/weldingtool) && W:welding))
+ var/obj/item/weapon/weldingtool/WT = W
+ if((istype(WT) && WT.welding))
if(!status)
status = TRUE
GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
@@ -63,7 +64,7 @@
return
/obj/item/device/onetankbomb/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here.
- visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
+ visible_message("[icon2html(src, viewers(src))] *beep* *beep*", "*beep* *beep*")
sleep(10)
if(!src)
return
diff --git a/code/modules/assembly/health.dm b/code/modules/assembly/health.dm
index b454cbacfb..180cb55db6 100644
--- a/code/modules/assembly/health.dm
+++ b/code/modules/assembly/health.dm
@@ -59,7 +59,7 @@
health_scan = M.health
if(health_scan <= alarm_health)
pulse()
- audible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
+ audible_message("[icon2html(src, hearers(src))] *beep* *beep*", "*beep* *beep*")
toggle_scan()
return
return
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index be1659546f..c196e984a2 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -99,7 +99,7 @@
if(!secured || !on || next_activate > world.time)
return FALSE
pulse(0)
- audible_message("[bicon(src)] *beep* *beep*", null, 3)
+ audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 3)
next_activate = world.time + 30
/obj/item/device/assembly/infra/interact(mob/user)//TODO: change this this to the wire control panel
diff --git a/code/modules/assembly/proximity.dm b/code/modules/assembly/proximity.dm
index 9cf534f975..556979070d 100644
--- a/code/modules/assembly/proximity.dm
+++ b/code/modules/assembly/proximity.dm
@@ -56,7 +56,7 @@
if(!secured || next_activate > world.time)
return 0
pulse(0)
- audible_message("[bicon(src)] *beep* *beep*", null, 3)
+ audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 3)
next_activate = world.time + 30
diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm
index b3f25ac8cf..7c8efb14d5 100644
--- a/code/modules/assembly/signaler.dm
+++ b/code/modules/assembly/signaler.dm
@@ -143,7 +143,7 @@ Code:
if(!(src.wires & WIRE_RADIO_RECEIVE))
return 0
pulse(1)
- audible_message("[bicon(src)] *beep* *beep*", null, 1)
+ audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 1)
return
diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm
index 8938ecbe9d..9a959bc544 100644
--- a/code/modules/assembly/timer.dm
+++ b/code/modules/assembly/timer.dm
@@ -45,7 +45,7 @@
if(!secured || next_activate > world.time)
return FALSE
pulse(0)
- audible_message("[bicon(src)] *beep* *beep*", null, 3)
+ audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 3)
if(loop)
timing = 1
update_icon()
diff --git a/code/modules/atmospherics/machinery/portable/canister.dm b/code/modules/atmospherics/machinery/portable/canister.dm
index d733dfc3fb..a45536430a 100644
--- a/code/modules/atmospherics/machinery/portable/canister.dm
+++ b/code/modules/atmospherics/machinery/portable/canister.dm
@@ -189,8 +189,9 @@
#define CONNECTED 2
#define EMPTY 4
#define LOW 8
-#define FULL 16
-#define DANGER 32
+#define MEDIUM 16
+#define FULL 32
+#define DANGER 64
/obj/machinery/portable_atmospherics/canister/update_icon()
if(stat & BROKEN)
cut_overlays()
@@ -207,9 +208,11 @@
var/pressure = air_contents.return_pressure()
if(pressure < 10)
update |= EMPTY
- else if(pressure < ONE_ATMOSPHERE)
+ else if(pressure < 5 * ONE_ATMOSPHERE)
update |= LOW
- else if(pressure < 15 * ONE_ATMOSPHERE)
+ else if(pressure < 10 * ONE_ATMOSPHERE)
+ update |= MEDIUM
+ else if(pressure < 40 * ONE_ATMOSPHERE)
update |= FULL
else
update |= DANGER
@@ -222,9 +225,9 @@
add_overlay("can-open")
if(update & CONNECTED)
add_overlay("can-connector")
- if(update & EMPTY)
+ if(update & LOW)
add_overlay("can-o0")
- else if(update & LOW)
+ else if(update & MEDIUM)
add_overlay("can-o1")
else if(update & FULL)
add_overlay("can-o2")
@@ -234,6 +237,7 @@
#undef CONNECTED
#undef EMPTY
#undef LOW
+#undef MEDIUM
#undef FULL
#undef DANGER
diff --git a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm
index 15117c1cbb..7926cfc34d 100644
--- a/code/modules/cargo/console.dm
+++ b/code/modules/cargo/console.dm
@@ -145,7 +145,7 @@
var/reason = ""
if(requestonly)
- reason = input("Reason:", name, "") as text|null
+ reason = stripped_input("Reason:", name, "")
if(isnull(reason) || ..())
return
diff --git a/code/modules/cargo/console.dm.rej b/code/modules/cargo/console.dm.rej
new file mode 100644
index 0000000000..e8798f179a
--- /dev/null
+++ b/code/modules/cargo/console.dm.rej
@@ -0,0 +1,10 @@
+diff a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm (rejected hunks)
+@@ -145,7 +145,7 @@
+
+ var/reason = ""
+ if(requestonly)
+- reason = stripped_input("Reason:", name, "") as text|null
++ reason = stripped_input("Reason:", name, "")
+ if(isnull(reason) || ..())
+ return
+
diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm
index 81fecc6dda..4f576dd3e7 100644
--- a/code/modules/client/asset_cache.dm
+++ b/code/modules/client/asset_cache.dm
@@ -138,6 +138,13 @@ You can set verify to TRUE if you want send() to sleep until the client has the
/proc/register_asset(var/asset_name, var/asset)
SSassets.cache[asset_name] = asset
+//Generated names do not include file extention.
+//Used mainly for code that deals with assets in a generic way
+//The same asset will always lead to the same asset name
+/proc/generate_asset_name(var/file)
+ return "asset.[md5(fcopy_rsc(file))]"
+
+
//These datums are used to populate the asset cache, the proc "register()" does this.
//all of our asset datums, used for referring to these later
@@ -170,6 +177,33 @@ GLOBAL_LIST_EMPTY(asset_datums)
send_asset_list(client,assets,verify)
+//Generates assets based on iconstates of a single icon
+/datum/asset/simple/icon_states
+ var/icon
+ var/direction = SOUTH
+ var/frame = 1
+ var/movement_states = FALSE
+
+ var/prefix = "default" //asset_name = "[prefix].[icon_state_name].png"
+ var/generic_icon_names = FALSE //generate icon filenames using generate_asset_name() instead the above format
+
+ verify = FALSE
+
+/datum/asset/simple/icon_states/register()
+ for(var/icon_state_name in icon_states(icon))
+ var/asset = icon(icon, icon_state_name, direction, frame, movement_states)
+ if (!asset)
+ continue
+ asset = fcopy_rsc(asset) //dedupe
+ var/asset_name = sanitize_filename("[prefix].[icon_state_name].png")
+ if (generic_icon_names)
+ asset_name = "[generate_asset_name(asset)].png"
+
+ assets[asset_name] = asset
+
+ ..()
+
+
//DEFINITIONS FOR ASSET DATUMS START HERE.
/datum/asset/simple/tgui
@@ -306,3 +340,14 @@ GLOBAL_LIST_EMPTY(asset_datums)
for(var/path in typesof(/datum/html_interface))
var/datum/html_interface/hi = new path()
hi.registerResources()
+
+//this exists purely to avoid meta by pre-loading all language icons.
+/datum/asset/language/register()
+ for(var/path in typesof(/datum/language))
+ set waitfor = FALSE
+ var/datum/language/L = new path ()
+ L.get_icon()
+
+/datum/asset/simple/icon_states/emojis
+ icon = 'icons/emoji.dmi'
+ generic_icon_names = TRUE
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index b4a879e5fe..637c3e2bec 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -75,7 +75,6 @@
//Logs all hrefs, except chat pings
if(!(href_list["_src_"] == "chat" && href_list["proc"] == "ping" && LAZYLEN(href_list) == 2))
WRITE_FILE(GLOB.world_href_log, "[time_stamp(show_ds = TRUE)] [src] (usr:[usr]) || [hsrc ? "[hsrc] " : ""][href]
")
-
// Admin PM
if(href_list["priv_msg"])
cmd_admin_pm(href_list["priv_msg"],null)
@@ -643,7 +642,7 @@ GLOBAL_LIST(external_rsc_urls)
)
spawn (10) //removing this spawn causes all clients to not get verbs.
//Precache the client with all other assets slowly, so as to not block other browse() calls
- getFilesSlow(src, SSassets.cache, register_asset = FALSE)
+ getFilesSlow(src, SSassets.preload, register_asset = FALSE)
//Hook, override it to run code when dir changes
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index f846f52625..244afc69f3 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -226,34 +226,34 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
return 0
S.cd = "/"
- S["version"] << SAVEFILE_VERSION_MAX //updates (or failing that the sanity checks) will ensure data is not invalid at load. Assume up-to-date
+ WRITE_FILE(S["version"] , SAVEFILE_VERSION_MAX) //updates (or failing that the sanity checks) will ensure data is not invalid at load. Assume up-to-date
//general preferences
- S["ooccolor"] << ooccolor
- S["lastchangelog"] << lastchangelog
- S["UI_style"] << UI_style
- S["hotkeys"] << hotkeys
- S["tgui_fancy"] << tgui_fancy
- S["tgui_lock"] << tgui_lock
- S["windowflash"] << windowflashing
- S["be_special"] << be_special
- S["default_slot"] << default_slot
- S["toggles"] << toggles
- S["chat_toggles"] << chat_toggles
- S["ghost_form"] << ghost_form
- S["ghost_orbit"] << ghost_orbit
- S["ghost_accs"] << ghost_accs
- S["ghost_others"] << ghost_others
- S["preferred_map"] << preferred_map
- S["ignoring"] << ignoring
- S["ghost_hud"] << ghost_hud
- S["inquisitive_ghost"] << inquisitive_ghost
- S["uses_glasses_colour"]<< uses_glasses_colour
- S["clientfps"] << clientfps
- S["parallax"] << parallax
- S["menuoptions"] << menuoptions
- S["enable_tips"] << enable_tips
- S["tip_delay"] << tip_delay
+ WRITE_FILE(S["ooccolor"], ooccolor)
+ WRITE_FILE(S["lastchangelog"], lastchangelog)
+ WRITE_FILE(S["UI_style"], UI_style)
+ WRITE_FILE(S["hotkeys"], hotkeys)
+ WRITE_FILE(S["tgui_fancy"], tgui_fancy)
+ WRITE_FILE(S["tgui_lock"], tgui_lock)
+ WRITE_FILE(S["windowflash"], windowflashing)
+ WRITE_FILE(S["be_special"], be_special)
+ WRITE_FILE(S["default_slot"], default_slot)
+ WRITE_FILE(S["toggles"], toggles)
+ WRITE_FILE(S["chat_toggles"], chat_toggles)
+ WRITE_FILE(S["ghost_form"], ghost_form)
+ WRITE_FILE(S["ghost_orbit"], ghost_orbit)
+ WRITE_FILE(S["ghost_accs"], ghost_accs)
+ WRITE_FILE(S["ghost_others"], ghost_others)
+ WRITE_FILE(S["preferred_map"], preferred_map)
+ WRITE_FILE(S["ignoring"], ignoring)
+ WRITE_FILE(S["ghost_hud"], ghost_hud)
+ WRITE_FILE(S["inquisitive_ghost"], inquisitive_ghost)
+ WRITE_FILE(S["uses_glasses_colour"], uses_glasses_colour)
+ WRITE_FILE(S["clientfps"], clientfps)
+ WRITE_FILE(S["parallax"], parallax)
+ WRITE_FILE(S["menuoptions"], menuoptions)
+ WRITE_FILE(S["enable_tips"], enable_tips)
+ WRITE_FILE(S["tip_delay"], tip_delay)
//citadel code
S["arousable"] << arousable
@@ -273,7 +273,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
slot = sanitize_integer(slot, 1, max_save_slots, initial(default_slot))
if(slot != default_slot)
default_slot = slot
- S["default_slot"] << slot
+ WRITE_FILE(S["default_slot"] , slot)
S.cd = "/character[slot]"
var/needs_update = savefile_needs_update(S)
@@ -292,7 +292,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
pref_species = new rando_race()
if(!S["features["mcolor"]"] || S["features["mcolor"]"] == "#000")
- S["features["mcolor"]"] << "#FFF"
+ WRITE_FILE(S["features["mcolor"]"] , "#FFF")
//Character
S["OOC_Notes"] >> metadata
@@ -470,53 +470,53 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["version"] << SAVEFILE_VERSION_MAX //load_character will sanitize any bad data, so assume up-to-date.
//Character
- S["OOC_Notes"] << metadata
- S["real_name"] << real_name
- S["name_is_always_random"] << be_random_name
- S["body_is_always_random"] << be_random_body
- S["gender"] << gender
- S["age"] << age
- S["hair_color"] << hair_color
- S["facial_hair_color"] << facial_hair_color
- S["eye_color"] << eye_color
- S["skin_tone"] << skin_tone
- S["hair_style_name"] << hair_style
- S["facial_style_name"] << facial_hair_style
- S["underwear"] << underwear
- S["undershirt"] << undershirt
- S["socks"] << socks
- S["backbag"] << backbag
- S["uplink_loc"] << uplink_spawn_loc
- S["species"] << pref_species.id
- S["feature_mcolor"] << features["mcolor"]
- S["feature_lizard_tail"] << features["tail_lizard"]
- S["feature_human_tail"] << features["tail_human"]
- S["feature_lizard_snout"] << features["snout"]
- S["feature_lizard_horns"] << features["horns"]
- S["feature_human_ears"] << features["ears"]
- S["feature_lizard_frills"] << features["frills"]
- S["feature_lizard_spines"] << features["spines"]
- S["feature_lizard_body_markings"] << features["body_markings"]
- S["feature_lizard_legs"] << features["legs"]
- S["clown_name"] << custom_names["clown"]
- S["mime_name"] << custom_names["mime"]
- S["ai_name"] << custom_names["ai"]
- S["cyborg_name"] << custom_names["cyborg"]
- S["religion_name"] << custom_names["religion"]
- S["deity_name"] << custom_names["deity"]
- S["prefered_security_department"] << prefered_security_department
+ WRITE_FILE(S["OOC_Notes"] , metadata)
+ WRITE_FILE(S["real_name"] , real_name)
+ WRITE_FILE(S["name_is_always_random"] , be_random_name)
+ WRITE_FILE(S["body_is_always_random"] , be_random_body)
+ WRITE_FILE(S["gender"] , gender)
+ WRITE_FILE(S["age"] , age)
+ WRITE_FILE(S["hair_color"] , hair_color)
+ WRITE_FILE(S["facial_hair_color"] , facial_hair_color)
+ WRITE_FILE(S["eye_color"] , eye_color)
+ WRITE_FILE(S["skin_tone"] , skin_tone)
+ WRITE_FILE(S["hair_style_name"] , hair_style)
+ WRITE_FILE(S["facial_style_name"] , facial_hair_style)
+ WRITE_FILE(S["underwear"] , underwear)
+ WRITE_FILE(S["undershirt"] , undershirt)
+ WRITE_FILE(S["socks"] , socks)
+ WRITE_FILE(S["backbag"] , backbag)
+ WRITE_FILE(S["uplink_loc"] , uplink_spawn_loc)
+ WRITE_FILE(S["species"] , pref_species.id)
+ WRITE_FILE(S["feature_mcolor"] , features["mcolor"])
+ WRITE_FILE(S["feature_lizard_tail"] , features["tail_lizard"])
+ WRITE_FILE(S["feature_human_tail"] , features["tail_human"])
+ WRITE_FILE(S["feature_lizard_snout"] , features["snout"])
+ WRITE_FILE(S["feature_lizard_horns"] , features["horns"])
+ WRITE_FILE(S["feature_human_ears"] , features["ears"])
+ WRITE_FILE(S["feature_lizard_frills"] , features["frills"])
+ WRITE_FILE(S["feature_lizard_spines"] , features["spines"])
+ WRITE_FILE(S["feature_lizard_body_markings"] , features["body_markings"])
+ WRITE_FILE(S["feature_lizard_legs"] , features["legs"])
+ WRITE_FILE(S["clown_name"] , custom_names["clown"])
+ WRITE_FILE(S["mime_name"] , custom_names["mime"])
+ WRITE_FILE(S["ai_name"] , custom_names["ai"])
+ WRITE_FILE(S["cyborg_name"] , custom_names["cyborg"])
+ WRITE_FILE(S["religion_name"] , custom_names["religion"])
+ WRITE_FILE(S["deity_name"] , custom_names["deity"])
+ WRITE_FILE(S["prefered_security_department"] , prefered_security_department)
//Jobs
- S["joblessrole"] << joblessrole
- S["job_civilian_high"] << job_civilian_high
- S["job_civilian_med"] << job_civilian_med
- S["job_civilian_low"] << job_civilian_low
- S["job_medsci_high"] << job_medsci_high
- S["job_medsci_med"] << job_medsci_med
- S["job_medsci_low"] << job_medsci_low
- S["job_engsec_high"] << job_engsec_high
- S["job_engsec_med"] << job_engsec_med
- S["job_engsec_low"] << job_engsec_low
+ WRITE_FILE(S["joblessrole"] , joblessrole)
+ WRITE_FILE(S["job_civilian_high"] , job_civilian_high)
+ WRITE_FILE(S["job_civilian_med"] , job_civilian_med)
+ WRITE_FILE(S["job_civilian_low"] , job_civilian_low)
+ WRITE_FILE(S["job_medsci_high"] , job_medsci_high)
+ WRITE_FILE(S["job_medsci_med"] , job_medsci_med)
+ WRITE_FILE(S["job_medsci_low"] , job_medsci_low)
+ WRITE_FILE(S["job_engsec_high"] , job_engsec_high)
+ WRITE_FILE(S["job_engsec_med"] , job_engsec_med)
+ WRITE_FILE(S["job_engsec_low"] , job_engsec_low)
//Citadel
S["feature_exhibitionist"] << features["exhibitionist"]
diff --git a/code/modules/client/preferences_savefile.dm.rej b/code/modules/client/preferences_savefile.dm.rej
new file mode 100644
index 0000000000..3cdbf2cd44
--- /dev/null
+++ b/code/modules/client/preferences_savefile.dm.rej
@@ -0,0 +1,10 @@
+diff a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm (rejected hunks)
+@@ -193,7 +193,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
+ return 0
+ S.cd = "/"
+
+- WRITE_FILE(S["version"] , SAVEFILE_VERSION_MAX //updates (or failing that the sanity checks) will ensure data is not invalid at load. Assume up-to-date)
++ WRITE_FILE(S["version"] , SAVEFILE_VERSION_MAX) //updates (or failing that the sanity checks) will ensure data is not invalid at load. Assume up-to-date
+
+ //general preferences
+ WRITE_FILE(S["ooccolor"], ooccolor)
diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm
index d56b6e0619..1d04964a8b 100644
--- a/code/modules/client/preferences_toggles.dm
+++ b/code/modules/client/preferences_toggles.dm
@@ -229,7 +229,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggleprayersounds)()
set name = "Stop Sounds"
set category = "Preferences"
set desc = "Stop Current Sounds"
- usr << sound(null)
+ SEND_SOUND(usr, sound(null))
SSblackbox.add_details("preferences_verb","Stop Self Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm
index aeb1a7fdcf..cd0f893fa6 100644
--- a/code/modules/client/verbs/ooc.dm
+++ b/code/modules/client/verbs/ooc.dm
@@ -55,7 +55,7 @@
var/keyname = key
if(prefs.unlock_content)
if(prefs.toggles & MEMBER_PUBLIC)
- keyname = "[bicon(icon('icons/member_content.dmi', "blag"))][keyname]"
+ keyname = "[icon2html('icons/member_content.dmi', world, "blag")][keyname]"
for(var/client/C in GLOB.clients)
if(C.prefs.chat_toggles & CHAT_OOC)
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index bd6ffe5f67..bf34ee9f18 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -253,6 +253,7 @@ BLIND // can't see anything
slot_flags = SLOT_HEAD
var/blockTracking = 0 //For AI tracking
var/can_toggle = null
+ dynamic_hair_suffix = "+generic"
/obj/item/clothing/head/Initialize()
. = ..()
diff --git a/code/modules/clothing/head/collectable.dm b/code/modules/clothing/head/collectable.dm
index 8ec8d00c77..67ce9ea370 100644
--- a/code/modules/clothing/head/collectable.dm
+++ b/code/modules/clothing/head/collectable.dm
@@ -14,6 +14,7 @@
name = "collectable slime cap!"
desc = "It just latches right in place!"
icon_state = "slime"
+ dynamic_hair_suffix = ""
/obj/item/clothing/head/collectable/xenom
name = "collectable xenomorph helmet!"
@@ -25,6 +26,7 @@
desc = "A rare chef's hat meant for hat collectors!"
icon_state = "chef"
item_state = "chef"
+ dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/chef
@@ -53,6 +55,7 @@
name = "collectable police officer's hat"
desc = "A collectable police officer's Hat. This hat emphasizes that you are THE LAW."
icon_state = "policehelm"
+ dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/warden
@@ -95,6 +98,7 @@
desc = "The fur feels... a bit too realistic."
icon_state = "kitty"
item_state = "kitty"
+ dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/kitty
@@ -103,6 +107,7 @@
desc = "Not as lucky as the feet!"
icon_state = "bunny"
item_state = "bunny"
+ dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/rabbit
@@ -125,6 +130,7 @@
name = "collectable HoS hat"
desc = "Now you too can beat prisoners, set silly sentences, and arrest for no reason!"
icon_state = "hoscap"
+ dynamic_hair_suffix = ""
/obj/item/clothing/head/collectable/HoP
name = "collectable HoP hat"
@@ -138,6 +144,7 @@
icon_state = "thunderdome"
item_state = "thunderdome"
resistance_flags = 0
+ flags_inv = HIDEHAIR
/obj/item/clothing/head/collectable/swat
name = "collectable SWAT helmet"
@@ -145,3 +152,4 @@
icon_state = "swat"
item_state = "swat"
resistance_flags = 0
+ flags_inv = HIDEHAIR
diff --git a/code/modules/clothing/head/collectable.dm.rej b/code/modules/clothing/head/collectable.dm.rej
new file mode 100644
index 0000000000..82a9962cb8
--- /dev/null
+++ b/code/modules/clothing/head/collectable.dm.rej
@@ -0,0 +1,9 @@
+diff a/code/modules/clothing/head/collectable.dm b/code/modules/clothing/head/collectable.dm (rejected hunks)
+@@ -4,7 +4,6 @@
+ /obj/item/clothing/head/collectable
+ name = "collectable hat"
+ desc = "A rare collectable hat."
+- dynamic_hair_suffix = "+detective"
+
+
+ /obj/item/clothing/head/collectable/petehat
diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm
index 28fe8cacfb..6eefb458ed 100644
--- a/code/modules/clothing/head/hardhat.dm
+++ b/code/modules/clothing/head/hardhat.dm
@@ -10,6 +10,7 @@
flags_inv = 0
actions_types = list(/datum/action/item_action/toggle_helmet_light)
resistance_flags = FIRE_PROOF
+ dynamic_hair_suffix = "+generic"
dog_fashion = /datum/dog_fashion/head
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index f100df4366..24d8049ac7 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -12,6 +12,7 @@
strip_delay = 60
resistance_flags = 0
flags_cover = HEADCOVERSEYES
+ flags_inv = HIDEHAIR
dog_fashion = /datum/dog_fashion/head/helmet
diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm
index 23b3da72ef..6a127f571b 100644
--- a/code/modules/clothing/head/jobs.dm
+++ b/code/modules/clothing/head/jobs.dm
@@ -7,6 +7,7 @@
desc = "The commander in chef's head wear."
strip_delay = 10
equip_delay_other = 10
+ dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/chef
/obj/item/clothing/head/chefhat/suicide_act(mob/user)
@@ -62,6 +63,7 @@
item_state = "cage"
worn_x_dimension = 64
worn_y_dimension = 64
+ dynamic_hair_suffix = ""
/obj/item/clothing/head/witchunter_hat
@@ -99,6 +101,7 @@
desc = "A beret, a mime's favorite headwear."
icon_state = "beret"
dog_fashion = /datum/dog_fashion/head/beret
+ dynamic_hair_suffix = ""
/obj/item/clothing/head/beret/black
name = "black beret"
@@ -118,6 +121,7 @@
icon_state = "hoscap"
armor = list(melee = 40, bullet = 30, laser = 25, energy = 10, bomb = 25, bio = 10, rad = 0, fire = 50, acid = 60)
strip_delay = 80
+ dynamic_hair_suffix = ""
/obj/item/clothing/head/HoS/syndicate
name = "syndicate cap"
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 2c972ccc70..959c28d45e 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -1,287 +1,290 @@
-
-
-/obj/item/clothing/head/centhat
- name = "\improper CentCom hat"
- icon_state = "centcom"
- desc = "It's good to be emperor."
- item_state = "that"
- flags_inv = 0
- armor = list(melee = 30, bullet = 15, laser = 30, energy = 10, bomb = 25, bio = 0, rad = 0, fire = 50, acid = 50)
- strip_delay = 80
-
-/obj/item/clothing/head/powdered_wig
- name = "powdered wig"
- desc = "A powdered wig."
- icon_state = "pwig"
- item_state = "pwig"
-
-/obj/item/clothing/head/that
- name = "top-hat"
- desc = "It's an amish looking hat."
- icon_state = "tophat"
- item_state = "that"
- dog_fashion = /datum/dog_fashion/head
- throwforce = 1
-
-/obj/item/clothing/head/canada
- name = "striped red tophat"
- desc = "it smells like fresh donut holes / il sent comme des trous de beignets frais"
- icon_state = "canada"
- item_state = "canada"
-
-/obj/item/clothing/head/redcoat
- name = "redcoat's hat"
- icon_state = "redcoat"
- desc = "'I guess it's a redhead.'"
-
-/obj/item/clothing/head/mailman
- name = "mailman's hat"
- icon_state = "mailman"
- desc = "'Right-on-time' mail service head wear."
-
-/obj/item/clothing/head/plaguedoctorhat
- name = "plague doctor's hat"
- desc = "These were once used by plague doctors. They're pretty much useless."
- icon_state = "plaguedoctor"
- permeability_coefficient = 0.01
-
-/obj/item/clothing/head/hasturhood
- name = "hastur's hood"
- desc = "It's unspeakably stylish."
- icon_state = "hasturhood"
- flags_inv = HIDEHAIR
- flags_cover = HEADCOVERSEYES
-
-/obj/item/clothing/head/nursehat
- name = "nurse's hat"
- desc = "It allows quick identification of trained medical personnel."
- icon_state = "nursehat"
-
- dog_fashion = /datum/dog_fashion/head/nurse
-
-/obj/item/clothing/head/syndicatefake
- name = "black space-helmet replica"
- icon_state = "syndicate-helm-black-red"
- item_state = "syndicate-helm-black-red"
- desc = "A plastic replica of a Syndicate agent's space helmet. You'll look just like a real murderous Syndicate agent in this! This is a toy, it is not made for use in space!"
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
-
-/obj/item/clothing/head/cueball
- name = "cueball helmet"
- desc = "A large, featureless white orb meant to be worn on your head. How do you even see out of this thing?"
- icon_state = "cueball"
- item_state="cueball"
- flags_cover = HEADCOVERSEYES|HEADCOVERSMOUTH
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
-
-/obj/item/clothing/head/snowman
- name = "Snowman Head"
- desc = "A ball of white styrofoam. So festive."
- icon_state = "snowman_h"
- item_state = "snowman_h"
- flags_cover = HEADCOVERSEYES
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
-
-/obj/item/clothing/head/justice
- name = "justice hat"
- desc = "Fight for what's righteous!"
- icon_state = "justicered"
- item_state = "justicered"
- flags_inv = HIDEHAIR|HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR
- flags_cover = HEADCOVERSEYES
-
-/obj/item/clothing/head/justice/blue
- icon_state = "justiceblue"
- item_state = "justiceblue"
-
-/obj/item/clothing/head/justice/yellow
- icon_state = "justiceyellow"
- item_state = "justiceyellow"
-
-/obj/item/clothing/head/justice/green
- icon_state = "justicegreen"
- item_state = "justicegreen"
-
-/obj/item/clothing/head/justice/pink
- icon_state = "justicepink"
- item_state = "justicepink"
-
-/obj/item/clothing/head/rabbitears
- name = "rabbit ears"
- desc = "Wearing these makes you look useless, and only good for your sex appeal."
- icon_state = "bunny"
-
- dog_fashion = /datum/dog_fashion/head/rabbit
-
-
-/obj/item/clothing/head/flatcap
- name = "flat cap"
- desc = "A working man's cap."
- icon_state = "flat_cap"
- item_state = "detective"
-
-/obj/item/clothing/head/pirate
- name = "pirate hat"
- desc = "Yarr."
- icon_state = "pirate"
- item_state = "pirate"
- dog_fashion = /datum/dog_fashion/head/pirate
-
-/obj/item/clothing/head/pirate/captain
- icon_state = "hgpiratecap"
- item_state = "hgpiratecap"
-
-/obj/item/clothing/head/bandana
- name = "pirate bandana"
- desc = "Yarr."
- icon_state = "bandana"
- item_state = "bandana"
-
-/obj/item/clothing/head/bowler
- name = "bowler-hat"
- desc = "Gentleman, elite aboard!"
- icon_state = "bowler"
- item_state = "bowler"
-
-/obj/item/clothing/head/witchwig
- name = "witch costume wig"
- desc = "Eeeee~heheheheheheh!"
- icon_state = "witch"
- item_state = "witch"
- flags_inv = HIDEHAIR
-
-/obj/item/clothing/head/chicken
- name = "chicken suit head"
- desc = "Bkaw!"
- icon_state = "chickenhead"
- item_state = "chickensuit"
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
-
-/obj/item/clothing/head/griffin
- name = "griffon head"
- desc = "Why not 'eagle head'? Who knows."
- icon_state = "griffinhat"
- item_state = "griffinhat"
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
-
-/obj/item/clothing/head/bearpelt
- name = "bear pelt hat"
- desc = "Fuzzy."
- icon_state = "bearpelt"
- item_state = "bearpelt"
-
-/obj/item/clothing/head/xenos
- name = "xenos helmet"
- icon_state = "xenos"
- item_state = "xenos_helm"
- desc = "A helmet made out of chitinous alien hide."
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
-
-/obj/item/clothing/head/fedora
- name = "fedora"
- icon_state = "fedora"
- item_state = "fedora"
- armor = list(melee = 25, bullet = 5, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0, fire = 30, acid = 50)
- desc = "A really cool hat if you're a mobster. A really lame hat if you're not."
- dynamic_hair_suffix = "+detective"
- pockets = /obj/item/weapon/storage/internal/pocket/small
-
-/obj/item/clothing/head/fedora/suicide_act(mob/user)
- if(user.gender == FEMALE)
- return 0
- var/mob/living/carbon/human/H = user
- user.visible_message("[user] is donning [src]! It looks like they're trying to be nice to girls.")
- user.say("M'lady.")
- sleep(10)
- H.facial_hair_style = "Neckbeard"
- return(BRUTELOSS)
-
-/obj/item/clothing/head/sombrero
- name = "sombrero"
- icon_state = "sombrero"
- item_state = "sombrero"
- desc = "You can practically taste the fiesta."
- flags_inv = HIDEHAIR
-
- dog_fashion = /datum/dog_fashion/head/sombrero
-
-/obj/item/clothing/head/sombrero/green
- name = "green sombrero"
- icon_state = "greensombrero"
- item_state = "greensombrero"
- desc = "As elegant as a dancing cactus."
- flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
- dog_fashion = null
-
-/obj/item/clothing/head/sombrero/shamebrero
- name = "shamebrero"
- icon_state = "shamebrero"
- item_state = "shamebrero"
- desc = "Once it's on, it never comes off."
- flags = NODROP
- dog_fashion = null
-
-/obj/item/clothing/head/cone
- desc = "This cone is trying to warn you of something!"
- name = "warning cone"
- icon = 'icons/obj/janitor.dmi'
- icon_state = "cone"
- item_state = "cone"
- force = 1
- throwforce = 3
- throw_speed = 2
- throw_range = 5
- w_class = WEIGHT_CLASS_SMALL
- attack_verb = list("warned", "cautioned", "smashed")
- resistance_flags = 0
-
-/obj/item/clothing/head/santa
- name = "santa hat"
- desc = "On the first day of christmas my employer gave to me!"
- icon_state = "santahatnorm"
- item_state = "that"
- cold_protection = HEAD
- min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
- dog_fashion = /datum/dog_fashion/head/santa
-
-/obj/item/clothing/head/jester
- name = "jester hat"
+/obj/item/clothing/head/centhat
+ name = "\improper Centcom hat"
+ icon_state = "centcom"
+ desc = "It's good to be emperor."
+ item_state = "that"
+ flags_inv = 0
+ armor = list(melee = 30, bullet = 15, laser = 30, energy = 10, bomb = 25, bio = 0, rad = 0, fire = 50, acid = 50)
+ strip_delay = 80
+
+/obj/item/clothing/head/powdered_wig
+ name = "powdered wig"
+ desc = "A powdered wig."
+ icon_state = "pwig"
+ item_state = "pwig"
+
+/obj/item/clothing/head/that
+ name = "top-hat"
+ desc = "It's an amish looking hat."
+ icon_state = "tophat"
+ item_state = "that"
+ dog_fashion = /datum/dog_fashion/head
+ throwforce = 1
+
+/obj/item/clothing/head/canada
+ name = "striped red tophat"
+ desc = "it smells like fresh donut holes / il sent comme des trous de beignets frais"
+ icon_state = "canada"
+ item_state = "canada"
+
+/obj/item/clothing/head/redcoat
+ name = "redcoat's hat"
+ icon_state = "redcoat"
+ desc = "'I guess it's a redhead.'"
+
+/obj/item/clothing/head/mailman
+ name = "mailman's hat"
+ icon_state = "mailman"
+ desc = "'Right-on-time' mail service head wear."
+
+/obj/item/clothing/head/plaguedoctorhat
+ name = "plague doctor's hat"
+ desc = "These were once used by plague doctors. They're pretty much useless."
+ icon_state = "plaguedoctor"
+ permeability_coefficient = 0.01
+
+/obj/item/clothing/head/hasturhood
+ name = "hastur's hood"
+ desc = "It's unspeakably stylish."
+ icon_state = "hasturhood"
+ flags_inv = HIDEHAIR
+ flags_cover = HEADCOVERSEYES
+
+/obj/item/clothing/head/nursehat
+ name = "nurse's hat"
+ desc = "It allows quick identification of trained medical personnel."
+ icon_state = "nursehat"
+ dynamic_hair_suffix = ""
+
+ dog_fashion = /datum/dog_fashion/head/nurse
+
+/obj/item/clothing/head/syndicatefake
+ name = "black space-helmet replica"
+ icon_state = "syndicate-helm-black-red"
+ item_state = "syndicate-helm-black-red"
+ desc = "A plastic replica of a Syndicate agent's space helmet. You'll look just like a real murderous Syndicate agent in this! This is a toy, it is not made for use in space!"
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
+
+/obj/item/clothing/head/cueball
+ name = "cueball helmet"
+ desc = "A large, featureless white orb meant to be worn on your head. How do you even see out of this thing?"
+ icon_state = "cueball"
+ item_state="cueball"
+ flags_cover = HEADCOVERSEYES|HEADCOVERSMOUTH
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
+
+/obj/item/clothing/head/snowman
+ name = "Snowman Head"
+ desc = "A ball of white styrofoam. So festive."
+ icon_state = "snowman_h"
+ item_state = "snowman_h"
+ flags_cover = HEADCOVERSEYES
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
+
+/obj/item/clothing/head/justice
+ name = "justice hat"
+ desc = "Fight for what's righteous!"
+ icon_state = "justicered"
+ item_state = "justicered"
+ flags_inv = HIDEHAIR|HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR
+ flags_cover = HEADCOVERSEYES
+
+/obj/item/clothing/head/justice/blue
+ icon_state = "justiceblue"
+ item_state = "justiceblue"
+
+/obj/item/clothing/head/justice/yellow
+ icon_state = "justiceyellow"
+ item_state = "justiceyellow"
+
+/obj/item/clothing/head/justice/green
+ icon_state = "justicegreen"
+ item_state = "justicegreen"
+
+/obj/item/clothing/head/justice/pink
+ icon_state = "justicepink"
+ item_state = "justicepink"
+
+/obj/item/clothing/head/rabbitears
+ name = "rabbit ears"
+ desc = "Wearing these makes you look useless, and only good for your sex appeal."
+ icon_state = "bunny"
+ dynamic_hair_suffix = ""
+
+ dog_fashion = /datum/dog_fashion/head/rabbit
+
+
+/obj/item/clothing/head/flatcap
+ name = "flat cap"
+ desc = "A working man's cap."
+ icon_state = "flat_cap"
+ item_state = "detective"
+
+/obj/item/clothing/head/pirate
+ name = "pirate hat"
+ desc = "Yarr."
+ icon_state = "pirate"
+ item_state = "pirate"
+ dog_fashion = /datum/dog_fashion/head/pirate
+
+/obj/item/clothing/head/pirate/captain
+ icon_state = "hgpiratecap"
+ item_state = "hgpiratecap"
+
+/obj/item/clothing/head/bandana
+ name = "pirate bandana"
+ desc = "Yarr."
+ icon_state = "bandana"
+ item_state = "bandana"
+ dynamic_hair_suffix = ""
+
+/obj/item/clothing/head/bowler
+ name = "bowler-hat"
+ desc = "Gentleman, elite aboard!"
+ icon_state = "bowler"
+ item_state = "bowler"
+ dynamic_hair_suffix = ""
+
+/obj/item/clothing/head/witchwig
+ name = "witch costume wig"
+ desc = "Eeeee~heheheheheheh!"
+ icon_state = "witch"
+ item_state = "witch"
+ flags_inv = HIDEHAIR
+
+/obj/item/clothing/head/chicken
+ name = "chicken suit head"
+ desc = "Bkaw!"
+ icon_state = "chickenhead"
+ item_state = "chickensuit"
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
+
+/obj/item/clothing/head/griffin
+ name = "griffon head"
+ desc = "Why not 'eagle head'? Who knows."
+ icon_state = "griffinhat"
+ item_state = "griffinhat"
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
+
+/obj/item/clothing/head/bearpelt
+ name = "bear pelt hat"
+ desc = "Fuzzy."
+ icon_state = "bearpelt"
+ item_state = "bearpelt"
+
+/obj/item/clothing/head/xenos
+ name = "xenos helmet"
+ icon_state = "xenos"
+ item_state = "xenos_helm"
+ desc = "A helmet made out of chitinous alien hide."
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
+
+/obj/item/clothing/head/fedora
+ name = "fedora"
+ icon_state = "fedora"
+ item_state = "fedora"
+ armor = list(melee = 25, bullet = 5, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0, fire = 30, acid = 50)
+ desc = "A really cool hat if you're a mobster. A really lame hat if you're not."
+ pockets = /obj/item/weapon/storage/internal/pocket/small
+
+/obj/item/clothing/head/fedora/suicide_act(mob/user)
+ if(user.gender == FEMALE)
+ return 0
+ var/mob/living/carbon/human/H = user
+ user.visible_message("[user] is donning [src]! It looks like they're trying to be nice to girls.")
+ user.say("M'lady.")
+ sleep(10)
+ H.facial_hair_style = "Neckbeard"
+ return(BRUTELOSS)
+
+/obj/item/clothing/head/sombrero
+ name = "sombrero"
+ icon_state = "sombrero"
+ item_state = "sombrero"
+ desc = "You can practically taste the fiesta."
+ flags_inv = HIDEHAIR
+
+ dog_fashion = /datum/dog_fashion/head/sombrero
+
+/obj/item/clothing/head/sombrero/green
+ name = "green sombrero"
+ icon_state = "greensombrero"
+ item_state = "greensombrero"
+ desc = "As elegant as a dancing cactus."
+ flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
+ dog_fashion = null
+
+/obj/item/clothing/head/sombrero/shamebrero
+ name = "shamebrero"
+ icon_state = "shamebrero"
+ item_state = "shamebrero"
+ desc = "Once it's on, it never comes off."
+ flags = NODROP
+ dog_fashion = null
+
+/obj/item/clothing/head/cone
+ desc = "This cone is trying to warn you of something!"
+ name = "warning cone"
+ icon = 'icons/obj/janitor.dmi'
+ icon_state = "cone"
+ item_state = "cone"
+ force = 1
+ throwforce = 3
+ throw_speed = 2
+ throw_range = 5
+ w_class = WEIGHT_CLASS_SMALL
+ attack_verb = list("warned", "cautioned", "smashed")
+ resistance_flags = 0
+
+/obj/item/clothing/head/santa
+ name = "santa hat"
+ desc = "On the first day of christmas my employer gave to me!"
+ icon_state = "santahatnorm"
+ item_state = "that"
+ cold_protection = HEAD
+ min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
+ dog_fashion = /datum/dog_fashion/head/santa
+
+/obj/item/clothing/head/jester
+ name = "jester hat"
desc = "A hat with bells, to add some merriness to the suit."
- icon_state = "jester_hat"
-
-/obj/item/clothing/head/rice_hat
- name = "rice hat"
- desc = "Welcome to the rice fields, motherfucker."
- icon_state = "rice_hat"
-
-/obj/item/clothing/head/lizard
- name = "lizardskin cloche hat"
- desc = "How many lizards died to make this hat? Not enough."
- icon_state = "lizard"
-
-/obj/item/clothing/head/papersack
- name = "paper sack hat"
- desc = "A paper sack with crude holes cut out for eyes. Useful for hiding one's identity or ugliness."
- icon_state = "papersack"
- flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
-
-/obj/item/clothing/head/papersack/smiley
- name = "paper sack hat"
- desc = "A paper sack with crude holes cut out for eyes and a sketchy smile drawn on the front. Not creepy at all."
- icon_state = "papersack_smile"
- flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
-
-/obj/item/clothing/head/crown
- name = "crown"
- desc = "A crown fit for a king, a petty king maybe."
- icon_state = "crown"
- armor = list(melee = 15, bullet = 0, laser = 0,energy = 15, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
- resistance_flags = FIRE_PROOF
-
-/obj/item/clothing/head/crown/fancy
- name = "magnificent crown"
- desc = "A crown worn by only the highest emperors of the land."
- icon_state = "fancycrown"
+ icon_state = "jester_hat"
+ dynamic_hair_suffix = ""
+
+/obj/item/clothing/head/rice_hat
+ name = "rice hat"
+ desc = "Welcome to the rice fields, motherfucker."
+ icon_state = "rice_hat"
+
+/obj/item/clothing/head/lizard
+ name = "lizardskin cloche hat"
+ desc = "How many lizards died to make this hat? Not enough."
+ icon_state = "lizard"
+
+/obj/item/clothing/head/papersack
+ name = "paper sack hat"
+ desc = "A paper sack with crude holes cut out for eyes. Useful for hiding one's identity or ugliness."
+ icon_state = "papersack"
+ flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
+
+/obj/item/clothing/head/papersack/smiley
+ name = "paper sack hat"
+ desc = "A paper sack with crude holes cut out for eyes and a sketchy smile drawn on the front. Not creepy at all."
+ icon_state = "papersack_smile"
+ flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
+
+/obj/item/clothing/head/crown
+ name = "crown"
+ desc = "A crown fit for a king, a petty king maybe."
+ icon_state = "crown"
+ armor = list(melee = 15, bullet = 0, laser = 0,energy = 15, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
+ resistance_flags = FIRE_PROOF
+ dynamic_hair_suffix = ""
+
+/obj/item/clothing/head/crown/fancy
+ name = "magnificent crown"
+ desc = "A crown worn by only the highest emperors of the land."
+ icon_state = "fancycrown"
/obj/item/clothing/head/scarecrow_hat
name = "scarecrow hat"
@@ -297,4 +300,5 @@
/obj/item/clothing/head/jester/alt
name = "jester hat"
desc = "A hat with bells, to add some merriness to the suit."
- icon_state = "jester_hat2"
\ No newline at end of file
+ icon_state = "jester_hat2"
+ dynamic_hair_suffix = ""
diff --git a/code/modules/clothing/head/misc.dm.rej b/code/modules/clothing/head/misc.dm.rej
new file mode 100644
index 0000000000..df85f74b20
--- /dev/null
+++ b/code/modules/clothing/head/misc.dm.rej
@@ -0,0 +1,16 @@
+diff a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm (rejected hunks)
+@@ -250,7 +250,7 @@
+ name = "jester hat"
+ desc = "A hat with bells, to add some merriness to the suit."
+ icon_state = "jester_hat"
+- dynamic_hair_suffix = "null"
++ dynamic_hair_suffix = ""
+
+ /obj/item/clothing/head/rice_hat
+ name = "rice hat"
+@@ -302,4 +302,4 @@
+ name = "jester hat"
+ desc = "A hat with bells, to add some merriness to the suit."
+ icon_state = "jester_hat2"
+- dynamic_hair_suffix = "null"
++ dynamic_hair_suffix = ""
diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm
index 4c14fc0422..d15c7dd5f4 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -125,6 +125,7 @@
desc = "A pair of kitty ears. Meow!"
icon_state = "kitty"
color = "#999999"
+ dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/kitty
@@ -150,6 +151,7 @@
flags_inv = 0
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
brightness_on = 1 //luminosity when on
+ dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/reindeer
diff --git a/code/modules/clothing/outfits/standard.dm b/code/modules/clothing/outfits/standard.dm
index 66b62d3a67..abdb42d5b3 100644
--- a/code/modules/clothing/outfits/standard.dm
+++ b/code/modules/clothing/outfits/standard.dm
@@ -338,7 +338,7 @@
name = "Death Commando"
uniform = /obj/item/clothing/under/color/green
- suit = /obj/item/clothing/suit/space/hardsuit/shielded/swat
+ suit = /obj/item/clothing/suit/space/hardsuit/deathsquad
shoes = /obj/item/clothing/shoes/combat/swat
gloves = /obj/item/clothing/gloves/combat
mask = /obj/item/clothing/mask/gas/sechailer/swat
diff --git a/code/modules/clothing/spacesuits/flightsuit.dm b/code/modules/clothing/spacesuits/flightsuit.dm
index 9888be0494..e0d2907ae8 100644
--- a/code/modules/clothing/spacesuits/flightsuit.dm
+++ b/code/modules/clothing/spacesuits/flightsuit.dm
@@ -138,7 +138,7 @@
targ = mob_override
if(!istype(targ))
return
- to_chat(targ, "[bicon(src)]|[message]")
+ to_chat(targ, "[icon2html(src, targ)]|[message]")
/obj/item/device/flightpack/proc/sync_processing(datum/controller/subsystem/processing/flightpacks/FPS)
processing_mode = FPS.flightsuit_processing
@@ -924,7 +924,7 @@
targ = loc
if(!istype(targ))
return
- to_chat(targ, "[bicon(src)]|[message]")
+ to_chat(targ, "[icon2html(src, targ)]|[message]")
/obj/item/clothing/suit/space/hardsuit/flightsuit/examine(mob/user)
..()
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 00f622b751..7f8be87a2e 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -47,7 +47,7 @@
/obj/item/clothing/head/helmet/space/hardsuit/proc/display_visor_message(var/msg)
var/mob/wearer = loc
if(msg && ishuman(wearer))
- wearer.show_message("[bicon(src)][msg]", 1)
+ wearer.show_message("[icon2html(src, wearer)][msg]", 1)
/obj/item/clothing/head/helmet/space/hardsuit/rad_act(severity)
..()
@@ -200,7 +200,7 @@
item_color = "mining"
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
resistance_flags = FIRE_PROOF
- heat_protection = CHEST|GROIN|LEGS|ARMS
+ heat_protection = HEAD
armor = list(melee = 30, bullet = 5, laser = 10, energy = 5, bomb = 50, bio = 100, rad = 50, fire = 50, acid = 75)
brightness_on = 7
allowed = list(/obj/item/device/flashlight, /obj/item/weapon/tank/internals, /obj/item/weapon/resonator, /obj/item/device/mining_scanner, /obj/item/device/t_scanner/adv_mining_scanner, /obj/item/weapon/gun/energy/kinetic_accelerator)
@@ -216,6 +216,7 @@
armor = list(melee = 30, bullet = 5, laser = 10, energy = 5, bomb = 50, bio = 100, rad = 50, fire = 50, acid = 75)
allowed = list(/obj/item/device/flashlight, /obj/item/weapon/tank/internals, /obj/item/weapon/storage/bag/ore, /obj/item/weapon/pickaxe)
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/mining
+ heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
//Syndicate hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/syndi
diff --git a/code/modules/detectivework/detective_work.dm b/code/modules/detectivework/detective_work.dm
index 1ab499fcb5..6c91fee8c5 100644
--- a/code/modules/detectivework/detective_work.dm
+++ b/code/modules/detectivework/detective_work.dm
@@ -17,19 +17,16 @@
if(M.wear_suit)
fibertext = "Material from \a [M.wear_suit]."
if(prob(10*item_multiplier) && !(fibertext in suit_fibers))
- //world.log << "Added fibertext: [fibertext]"
suit_fibers += fibertext
if(!(M.wear_suit.body_parts_covered & CHEST))
if(M.w_uniform)
fibertext = "Fibers from \a [M.w_uniform]."
if(prob(12*item_multiplier) && !(fibertext in suit_fibers)) //Wearing a suit means less of the uniform exposed.
- //world.log << "Added fibertext: [fibertext]"
suit_fibers += fibertext
if(!(M.wear_suit.body_parts_covered & HANDS))
if(M.gloves)
fibertext = "Material from a pair of [M.gloves.name]."
if(prob(20*item_multiplier) && !(fibertext in suit_fibers))
- //world.log << "Added fibertext: [fibertext]"
suit_fibers += fibertext
else if(M.w_uniform)
fibertext = "Fibers from \a [M.w_uniform]."
@@ -39,12 +36,10 @@
if(M.gloves)
fibertext = "Material from a pair of [M.gloves.name]."
if(prob(20*item_multiplier) && !(fibertext in suit_fibers))
- //world.log << "Added fibertext: [fibertext]"
suit_fibers += "Material from a pair of [M.gloves.name]."
else if(M.gloves)
fibertext = "Material from a pair of [M.gloves.name]."
if(prob(20*item_multiplier) && !(fibertext in suit_fibers))
- //world.log << "Added fibertext: [fibertext]"
suit_fibers += "Material from a pair of [M.gloves.name]."
diff --git a/code/modules/emoji/emoji_parse.dm b/code/modules/emoji/emoji_parse.dm
index 5ecadbe09c..58f261f8cc 100644
--- a/code/modules/emoji/emoji_parse.dm
+++ b/code/modules/emoji/emoji_parse.dm
@@ -16,7 +16,7 @@
if(search)
emoji = lowertext(copytext(text, pos+1, search))
if(emoji in emojis)
- parsed += bicon(icon('icons/emoji.dmi', emoji))
+ parsed += icon2html('icons/emoji.dmi', world, emoji)
pos = search + 1
else
parsed += copytext(text, pos, search)
diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm
index e2cce14db3..93605ea78a 100644
--- a/code/modules/error_handler/error_handler.dm
+++ b/code/modules/error_handler/error_handler.dm
@@ -55,7 +55,7 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
var/skipcount = abs(error_cooldown[erroruid]) - 1
error_cooldown[erroruid] = 0
if(skipcount > 0)
- world.log << "\[[time_stamp()]] Skipped [skipcount] runtimes in [E.file],[E.line]."
+ SEND_TEXT(world.log, "\[[time_stamp()]] Skipped [skipcount] runtimes in [E.file],[E.line].")
GLOB.error_cache.log_error(E, skip_count = skipcount)
error_last_seen[erroruid] = world.time
@@ -92,9 +92,9 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
if(GLOB.error_cache)
GLOB.error_cache.log_error(E, desclines)
- world.log << "\[[time_stamp()]] Runtime in [E.file],[E.line]: [E]"
+ SEND_TEXT(world.log, "\[[time_stamp()]] Runtime in [E.file],[E.line]: [E]")
for(var/line in desclines)
- world.log << line
+ SEND_TEXT(world.log, line)
/* This logs the runtime in the old format */
diff --git a/code/modules/events/holiday/halloween.dm b/code/modules/events/holiday/halloween.dm
index 8f634003f5..1386995c28 100644
--- a/code/modules/events/holiday/halloween.dm
+++ b/code/modules/events/holiday/halloween.dm
@@ -70,7 +70,7 @@
if(!H.client || !istype(H))
return
to_chat(H, "Honk...")
- H << 'sound/spookoween/scary_clown_appear.ogg'
+ SEND_SOUND(H, sound('sound/spookoween/scary_clown_appear.ogg'))
var/turf/T = get_turf(H)
if(T)
new /obj/effect/hallucination/simple/clown(T, H, 50)
diff --git a/code/modules/events/portal_storm.dm b/code/modules/events/portal_storm.dm
index 888b87cc02..9658d8b144 100644
--- a/code/modules/events/portal_storm.dm
+++ b/code/modules/events/portal_storm.dm
@@ -68,11 +68,11 @@
/datum/round_event/portal_storm/announce()
set waitfor = 0
- playsound_global('sound/magic/lightning_chargeup.ogg', repeat=0, channel=1, volume=100)
+ sound_to_playing_players('sound/magic/lightning_chargeup.ogg')
sleep(80)
priority_announce("Massive bluespace anomaly detected en route to [station_name()]. Brace for impact.")
sleep(20)
- playsound_global('sound/magic/lightningbolt.ogg', repeat=0, channel=1, volume=100)
+ sound_to_playing_players('sound/magic/lightningbolt.ogg')
/datum/round_event/portal_storm/tick()
spawn_effects()
diff --git a/code/modules/events/wizard/fakeexplosion.dm b/code/modules/events/wizard/fakeexplosion.dm
index f6ffab2da8..3dee4a1f49 100644
--- a/code/modules/events/wizard/fakeexplosion.dm
+++ b/code/modules/events/wizard/fakeexplosion.dm
@@ -6,6 +6,5 @@
earliest_start = 0
/datum/round_event/wizard/fake_explosion/start()
- for(var/mob/M in GLOB.player_list)
- M << 'sound/machines/alarm.ogg'
+ sound_to_playing_players('sound/machines/alarm.ogg')
addtimer(CALLBACK(SSticker, /datum/controller/subsystem/ticker/.proc/station_explosion_cinematic, 1, "fake"), 100) //:o)
\ No newline at end of file
diff --git a/code/modules/events/wizard/imposter.dm b/code/modules/events/wizard/imposter.dm
index ffec648771..1ba052c4c0 100644
--- a/code/modules/events/wizard/imposter.dm
+++ b/code/modules/events/wizard/imposter.dm
@@ -55,4 +55,4 @@
I.log_message("Is an imposter!", INDIVIDUAL_ATTACK_LOG)
to_chat(I, "You are an imposter! Trick and confuse the crew to misdirect malice from your handsome original!")
- I << sound('sound/effects/magic.ogg')
+ SEND_SOUND(I, sound('sound/effects/magic.ogg'))
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index c1b0a387e4..2b8fe4b064 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -11,51 +11,83 @@ Gunshots/explosions/opening doors/less rare audio (done)
*/
+#define HAL_LINES_FILE "hallucination.json"
+
/mob/living/carbon
var/image/halimage
var/image/halbody
var/obj/halitem
var/hal_screwyhud = SCREWYHUD_NONE
- var/handling_hal = 0
+ var/next_hallucination = 0
+
+GLOBAL_LIST_INIT(hallucinations_minor, list(
+ /datum/hallucination/sounds,
+ /datum/hallucination/bolts,
+ /datum/hallucination/whispers,
+ /datum/hallucination/message,
+ /datum/hallucination/hudscrew))
+
+GLOBAL_LIST_INIT(hallucinations_medium, list(
+ /datum/hallucination/fake_alert,
+ /datum/hallucination/items,
+ /datum/hallucination/items_other,
+ /datum/hallucination/dangerflash,
+ /datum/hallucination/bolts,
+ /datum/hallucination/fake_flood,
+ /datum/hallucination/husks,
+ /datum/hallucination/battle,
+ /datum/hallucination/fire,
+ /datum/hallucination/self_delusion))
+
+GLOBAL_LIST_INIT(hallucinations_major, list(
+ /datum/hallucination/fakeattacker,
+ /datum/hallucination/death,
+ /datum/hallucination/xeno_attack,
+ /datum/hallucination/singularity_scare,
+ /datum/hallucination/delusion,
+ /datum/hallucination/oh_yeah))
/mob/living/carbon/proc/handle_hallucinations()
- if(handling_hal)
+ if(world.time < next_hallucination)
return
- //Least obvious
- var/list/minor = list("sounds"=25,"bolts_minor"=5,"whispers"=15,"message"=10,"hudscrew"=15)
- //Something's wrong here
- var/list/medium = list("fake_alert"=15,"items"=10,"items_other"=10,"dangerflash"=10,"bolts"=5,"flood"=5,"husks"=10,"battle"=15,"self_delusion"=10)
- //AAAAH
- var/list/major = list("fake"=20,"death"=10,"xeno"=10,"singulo"=10,"borer"=10,"delusion"=20,"koolaid"=10)
+ if(hallucination)
+ var/list/current = GLOB.hallucinations_minor
+ if(prob(25) && hallucination > 100)
+ current = GLOB.hallucinations_medium
+ else if(prob(10) && hallucination > 200)
+ current = GLOB.hallucinations_major
+ var/halpick = pick(current)
+ new halpick(src, FALSE)
- handling_hal = 1
- while(hallucination > 20)
- sleep(rand(200,500)/(hallucination/25))
- if(prob(20))
- continue
- var/list/current = list()
- switch(rand(100))
- if(1 to 50)
- current = minor
- if(51 to 85)
- current = medium
- if(86 to 100)
- current = major
+/mob/living/carbon/proc/set_screwyhud(hud_type)
+ hal_screwyhud = hud_type
+ update_health_hud()
- var/halpick = pickweight(current)
+/datum/hallucination
+ var/mob/living/carbon/target
+ var/cost = 5 //affects the amount of hallucination reduced, and cooldown until the next hallucination
+ var/feedback_details //extra info for investigate
- hallucinate(halpick)
- handling_hal = 0
+/datum/hallucination/New(mob/living/carbon/T, forced = TRUE)
+ set waitfor = 0
+ target = T
+ if(!forced)
+ target.hallucination = max(0, target.hallucination - cost)
+ target.next_hallucination = world.time + (rand(cost * 0.5, cost * 3) * 10)
+
+/datum/hallucination/proc/wake_and_restore()
+ target.set_screwyhud(SCREWYHUD_NONE)
+ target.SetSleeping(0)
+
+/datum/hallucination/Destroy()
+ target.investigate_log("was afflicted with a hallucination of type [type]. [feedback_details]", INVESTIGATE_HALLUCINATIONS)
+ return ..()
/obj/effect/hallucination
invisibility = INVISIBILITY_OBSERVER
var/mob/living/carbon/target = null
-/obj/effect/hallucination/proc/wake_and_restore()
- target.hal_screwyhud = SCREWYHUD_NONE
- target.SetSleeping(0)
-
/obj/effect/hallucination/simple
var/image_icon = 'icons/mob/alien.dmi'
var/image_state = "alienh_pounce"
@@ -64,13 +96,14 @@ Gunshots/explosions/opening doors/less rare audio (done)
var/col_mod = null
var/image/current_image = null
var/image_layer = MOB_LAYER
- var/active = 1 //qdelery
+ var/active = TRUE //qdelery
/obj/effect/hallucination/simple/Initialize(mapload, var/mob/living/carbon/T)
..()
target = T
current_image = GetImage()
- if(target.client) target.client.images |= current_image
+ if(target.client)
+ target.client.images |= current_image
/obj/effect/hallucination/simple/proc/GetImage()
var/image/I = image(image_icon,src,image_state,image_layer,dir=src.dir)
@@ -82,10 +115,12 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/hallucination/simple/proc/Show(update=1)
if(active)
- if(target.client) target.client.images.Remove(current_image)
+ if(target.client)
+ target.client.images.Remove(current_image)
if(update)
current_image = GetImage()
- if(target.client) target.client.images |= current_image
+ if(target.client)
+ target.client.images |= current_image
/obj/effect/hallucination/simple/update_icon(new_state,new_icon,new_px=0,new_py=0)
image_state = new_state
@@ -101,36 +136,39 @@ Gunshots/explosions/opening doors/less rare audio (done)
Show()
/obj/effect/hallucination/simple/Destroy()
- if(target.client) target.client.images.Remove(current_image)
- active = 0
+ if(target.client)
+ target.client.images.Remove(current_image)
+ active = FALSE
return ..()
#define FAKE_FLOOD_EXPAND_TIME 20
#define FAKE_FLOOD_MAX_RADIUS 10
-/obj/effect/hallucination/fake_flood
+/datum/hallucination/fake_flood
//Plasma starts flooding from the nearby vent
+ var/turf/center
var/list/flood_images = list()
var/list/turf/flood_turfs = list()
var/image_icon = 'icons/effects/tile_effects.dmi'
var/image_state = "plasma"
var/radius = 0
var/next_expand = 0
+ cost = 25
-/obj/effect/hallucination/fake_flood/Initialize(mapload, var/mob/living/carbon/T)
+/datum/hallucination/fake_flood/New(mob/living/carbon/T, forced = TRUE)
..()
- target = T
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target))
if(!U.welded)
- src.loc = U.loc
+ center = get_turf(U)
break
- flood_images += image(image_icon,src,image_state,MOB_LAYER)
- flood_turfs += get_turf(src.loc)
+ feedback_details += "Vent Coords: [center.x],[center.y],[center.z]"
+ flood_images += image(image_icon,center,image_state,MOB_LAYER)
+ flood_turfs += center
if(target.client) target.client.images |= flood_images
next_expand = world.time + FAKE_FLOOD_EXPAND_TIME
START_PROCESSING(SSobj, src)
-/obj/effect/hallucination/fake_flood/process()
+/datum/hallucination/fake_flood/process()
if(next_expand <= world.time)
radius++
if(radius > FAKE_FLOOD_MAX_RADIUS)
@@ -138,10 +176,10 @@ Gunshots/explosions/opening doors/less rare audio (done)
return
Expand()
if((get_turf(target) in flood_turfs) && !target.internal)
- target.hallucinate("fake_alert", "tox_in_air")
+ new /datum/hallucination/fake_alert(target, TRUE, "tox_in_air")
next_expand = world.time + FAKE_FLOOD_EXPAND_TIME
-/obj/effect/hallucination/fake_flood/proc/Expand()
+/datum/hallucination/fake_flood/proc/Expand()
for(var/turf/FT in flood_turfs)
for(var/dir in GLOB.cardinals)
var/turf/T = get_step(FT, dir)
@@ -152,7 +190,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
if(target.client)
target.client.images |= flood_images
-/obj/effect/hallucination/fake_flood/Destroy()
+/datum/hallucination/fake_flood/Destroy()
STOP_PROCESSING(SSobj, src)
qdel(flood_turfs)
flood_turfs = list()
@@ -167,7 +205,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
image_icon = 'icons/mob/alien.dmi'
image_state = "alienh_pounce"
-/obj/effect/hallucination/simple/xeno/Initialize(mapload, var/mob/living/carbon/T)
+/obj/effect/hallucination/simple/xeno/Initialize(mapload, mob/living/carbon/T)
..()
name = "alien hunter ([rand(1, 1000)])"
@@ -177,18 +215,19 @@ Gunshots/explosions/opening doors/less rare audio (done)
target.Knockdown(100)
target.visible_message("[target] flails around wildly.","[name] pounces on you!")
-/obj/effect/hallucination/xeno_attack
+/datum/hallucination/xeno_attack
//Xeno crawls from nearby vent,jumps at you, and goes back in
var/obj/machinery/atmospherics/components/unary/vent_pump/pump = null
var/obj/effect/hallucination/simple/xeno/xeno = null
+ cost = 25
-/obj/effect/hallucination/xeno_attack/Initialize(mapload, var/mob/living/carbon/T)
+/datum/hallucination/xeno_attack/New(mob/living/carbon/T, forced = TRUE)
..()
- target = T
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target))
if(!U.welded)
pump = U
break
+ feedback_details += "Vent Coords: [pump.x],[pump.y],[pump.z]"
if(pump)
xeno = new(pump.loc,target)
sleep(10)
@@ -200,7 +239,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
sleep(10)
var/xeno_name = xeno.name
to_chat(target, "[xeno_name] begins climbing into the ventilation system...")
- sleep(10)
+ sleep(30)
qdel(xeno)
to_chat(target, "[xeno_name] scrambles into the ventilation ducts!")
qdel(src)
@@ -209,7 +248,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
image_icon = 'icons/mob/animal.dmi'
image_state = "clown"
-/obj/effect/hallucination/simple/clown/Initialize(mapload, var/mob/living/carbon/T,duration)
+/obj/effect/hallucination/simple/clown/Initialize(mapload, mob/living/carbon/T, duration)
..(loc, T)
name = pick(GLOB.clown_names)
QDEL_IN(src,duration)
@@ -217,59 +256,27 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/hallucination/simple/clown/scary
image_state = "scary_clown"
-/obj/effect/hallucination/simple/borer
- image_icon = 'icons/mob/borer.dmi'
- image_state = "brainslug"
-
-/obj/effect/hallucination/borer
- //A borer unconsciouss you and crawls in your ear
- var/obj/machinery/atmospherics/components/unary/vent_pump/pump = null
- var/obj/effect/hallucination/simple/borer/borer = null
-
-/obj/effect/hallucination/borer/Initialize(mapload, var/mob/living/carbon/T)
- ..()
- target = T
- for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target))
- if(!U.welded)
- pump = U
- break
- if(pump)
- borer = new(pump.loc,target)
- for(var/i=0, i<11, i++)
- walk_to(borer, get_step(borer, get_cardinal_dir(borer, T)))
- if(borer.Adjacent(T))
- to_chat(T, "You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing.")
- T.Stun(80)
- sleep(50)
- qdel(borer)
- sleep(rand(60, 90))
- to_chat(T, "Primary [rand(1000,9999)] states: [pick("Hello","Hi","You're my slave now!","Don't try to get rid of me...")]")
- break
- sleep(4)
- if(!QDELETED(borer))
- qdel(borer)
- qdel(src)
-
/obj/effect/hallucination/simple/bubblegum
name = "Bubblegum"
image_icon = 'icons/mob/lavaland/96x96megafauna.dmi'
image_state = "bubblegum"
px = -32
-/obj/effect/hallucination/oh_yeah
+/datum/hallucination/oh_yeah
var/obj/effect/hallucination/simple/bubblegum/bubblegum
var/image/fakebroken
var/image/fakerune
+ cost = 75
-/obj/effect/hallucination/oh_yeah/Initialize(mapload, var/mob/living/carbon/T)
+/datum/hallucination/oh_yeah/New(mob/living/carbon/T, forced = TRUE)
. = ..()
- target = T
var/turf/closed/wall/wall
for(var/turf/closed/wall/W in range(7,target))
wall = W
break
if(!wall)
return INITIALIZE_HINT_QDEL
+ feedback_details += "Source: [wall.x],[wall.y],[wall.z]"
fakebroken = image('icons/turf/floors.dmi', wall, "plating", layer = TURF_LAYER)
var/turf/landing = get_turf(target)
@@ -283,7 +290,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
bubblegum = new(wall, target)
addtimer(CALLBACK(src, .proc/bubble_attack, landing), 10)
-/obj/effect/hallucination/oh_yeah/proc/bubble_attack(turf/landing)
+/datum/hallucination/oh_yeah/proc/bubble_attack(turf/landing)
var/charged = FALSE //only get hit once
while(get_turf(bubblegum) != landing && target && target.stat != DEAD)
bubblegum.forceMove(get_step_towards(bubblegum, landing))
@@ -301,7 +308,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
sleep(30)
qdel(src)
-/obj/effect/hallucination/oh_yeah/Destroy()
+/datum/hallucination/oh_yeah/Destroy()
if(target.client)
target.client.images.Remove(fakebroken)
target.client.images.Remove(fakerune)
@@ -310,23 +317,24 @@ Gunshots/explosions/opening doors/less rare audio (done)
QDEL_NULL(bubblegum)
return ..()
-/obj/effect/hallucination/singularity_scare
+/datum/hallucination/singularity_scare
//Singularity moving towards you.
//todo Hide where it moved with fake space images
var/obj/effect/hallucination/simple/singularity/s = null
+ cost = 75
-/obj/effect/hallucination/singularity_scare/Initialize(mapload, var/mob/living/carbon/T)
+/datum/hallucination/singularity_scare/New(mob/living/carbon/T, forced = TRUE)
..()
- target = T
var/turf/start = get_turf(T)
var/screen_border = pick(SOUTH,EAST,WEST,NORTH)
- for(var/i = 0,i<11,i++)
+ for(var/i in 1 to 13)
start = get_step(start,screen_border)
+ feedback_details += "Source: [start.x],[start.y],[start.z]"
s = new(start,target)
s.parent = src
- for(var/i = 0,i<11,i++)
- sleep(5)
- s.loc = get_step(get_turf(s),get_dir(s,target))
+ for(var/i in 1 to 13)
+ sleep(10)
+ s.forceMove(get_step(get_turf(s),get_dir(s,target)))
s.Show()
s.Eat()
qdel(s)
@@ -337,64 +345,72 @@ Gunshots/explosions/opening doors/less rare audio (done)
image_layer = MASSIVE_OBJ_LAYER
px = -96
py = -96
- var/obj/effect/hallucination/singularity_scare/parent
+ var/datum/hallucination/singularity_scare/parent
/obj/effect/hallucination/simple/singularity/proc/Eat(atom/OldLoc, Dir)
var/target_dist = get_dist(src,target)
if(target_dist<=3) //"Eaten"
- target.hal_screwyhud = SCREWYHUD_CRIT
+ target.set_screwyhud(SCREWYHUD_DEAD)
target.SetUnconscious(160)
- addtimer(CALLBACK(parent, .proc/wake_and_restore), rand(30, 50))
+ addtimer(CALLBACK(parent, /datum/hallucination/.proc/wake_and_restore), rand(30, 50))
-/obj/effect/hallucination/battle
+/datum/hallucination/battle
+ cost = 15
-/obj/effect/hallucination/battle/Initialize(mapload, var/mob/living/carbon/T)
+/datum/hallucination/battle/New(mob/living/carbon/T, forced = TRUE, battle_type)
..()
- target = T
var/hits = rand(3,6)
- switch(rand(1,5))
- if(1) //Laser fight
- for(var/i=0,i...wabbajack...wabbajack...")
- target.playsound_local(target,'sound/magic/staff_change.ogg', 50, 1, -1)
+ if(wabbajack)
+ to_chat(target, "...wabbajack...wabbajack...")
+ target.playsound_local(target,'sound/magic/staff_change.ogg', 50, 1)
delusion = A
target.client.images |= A
QDEL_IN(src, duration)
-/obj/effect/hallucination/self_delusion/Destroy()
+/datum/hallucination/self_delusion/Destroy()
if(target.client)
target.client.images.Remove(delusion)
return ..()
-/obj/effect/hallucination/fakeattacker/Initialize(mapload, var/mob/living/carbon/T)
+/datum/hallucination/fakeattacker/New(mob/living/carbon/T, forced = TRUE)
..()
- target = T
var/mob/living/carbon/human/clone = null
var/clone_weapon = null
@@ -523,6 +541,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
if(H.stat || H.lying)
continue
clone = H
+ feedback_details += "Clone of: [H.real_name]"
break
if(!clone)
@@ -604,7 +623,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
for(var/mob/O in oviewers(world.view , my_target))
to_chat(O, "[my_target] stumbles around.")
-/obj/effect/fake_attacker/Initialize(mapload, var/mob/living/carbon/T)
+/obj/effect/fake_attacker/Initialize(mapload, mob/living/carbon/T)
..()
my_target = T
QDEL_IN(src, 300)
@@ -651,7 +670,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
if(!locate(/obj/effect/overlay) in my_target.loc)
fake_blood(my_target)
else
- my_target.playsound_local(my_target, pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'), 25, 1, -1)
+ my_target.playsound_local(my_target, pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'), 25, 1)
my_target.show_message("[src.name] has punched [my_target]!", 1)
my_target.staminaloss += 30
if(prob(33))
@@ -674,14 +693,15 @@ Gunshots/explosions/opening doors/less rare audio (done)
QDEL_IN(O, 300)
-/obj/effect/hallucination/bolts
+/datum/hallucination/bolts
var/list/doors = list()
+ cost = 25
-/obj/effect/hallucination/bolts/Initialize(mapload, var/mob/living/carbon/T,var/door_number=-1) //-1 for severe, 1-2 for subtle
+/datum/hallucination/bolts/New(mob/living/carbon/T, forced, door_number=-1) //-1 for severe, 1-2 for subtle
..()
- target = T
var/image/I = null
var/count = 0
+ feedback_details += "Door amount: [door_number]"
for(var/obj/machinery/door/airlock/A in range(7, target))
if(count>door_number && door_number>0)
break
@@ -700,13 +720,30 @@ Gunshots/explosions/opening doors/less rare audio (done)
sleep(rand(6,12))
qdel(src)
-/obj/effect/hallucination/whispers
+/datum/hallucination/whispers
+ cost = 15
-/obj/effect/hallucination/whispers/Initialize(mapload, var/mob/living/carbon/T)
+/datum/hallucination/whispers/New(mob/living/carbon/T, forced = TRUE)
..()
- target = T
- var/speak_messages = list("I'm watching you...","[target.first_name()]!","Get out!","Kchck-Chkck? Kchchck!","Did you hear that?","What did you do ?","Why?","Give me that!","HELP!!","EI NATH!!", "RUN!!", "Kill me!","O bidai nabora se'sma!", "[text2ratvar("Divinity, grant...")]")
- var/radio_messages = list("Xenos!","Singularity loose!","Comms down!","They are arming the nuke!","They butchered Ian!","H-help!","[pick("Cult", "Wizard", "Ling", "Ops", "Revenant", "Murderer", "Harm", "I hear flashing", "Help")] in [pick(GLOB.teleportlocs)][prob(50)?"!":"!!"]","Where's [target.first_name()]?","Call the shuttle!","AI rogue!!")
+ var/speak_messages = list("[pick_list_replacements(HAL_LINES_FILE, "suspicion")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "greetings")][target.first_name()]!",\
+ "[pick_list_replacements(HAL_LINES_FILE, "getout")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "weird")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "didyouhearthat")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "imatraitor")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "doubt")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "aggressive")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "help")]!!",\
+ "[pick_list_replacements(HAL_LINES_FILE, "escape")]",\
+ "I'm infected, [pick_list_replacements(HAL_LINES_FILE, "infection_advice")]!")
+
+ var/radio_messages = list("Set [target.first_name()] to arrest!",\
+ "[pick_list_replacements(HAL_LINES_FILE, "people")] is [pick_list_replacements(HAL_LINES_FILE, "accusations")]!",\
+ "Help!",\
+ "[pick_list_replacements(HAL_LINES_FILE, "threat")] in [pick_list_replacements(HAL_LINES_FILE, "location")][prob(50)?"!":"!!"]",\
+ "Where's [target.first_name()]?"\
+ ,"[pick("C","Ai, c","Someone c","Rec")]all the shuttle!"\
+ ,"AI [pick("rogue", "is dead")]!!")
var/list/mob/living/carbon/people = list()
var/list/mob/living/carbon/person = null
@@ -722,7 +759,9 @@ Gunshots/explosions/opening doors/less rare audio (done)
people += H
if(person) //Basic talk
var/image/speech_overlay = image('icons/mob/talk.dmi', person, "default0", layer = ABOVE_MOB_LAYER)
- to_chat(target, target.compose_message(person,understood_language,pick(speak_messages),null,person.get_spans()))
+ var/message = target.compose_message(person,understood_language,pick(speak_messages),null,person.get_spans())
+ feedback_details += "Type: Talk, Source: [person.real_name], Message: [message]"
+ to_chat(target, message)
if(target.client)
target.client.images |= speech_overlay
sleep(30)
@@ -732,312 +771,381 @@ Gunshots/explosions/opening doors/less rare audio (done)
for(var/mob/living/carbon/human/H in GLOB.living_mob_list)
humans += H
person = pick(humans)
- to_chat(target, target.compose_message(person,understood_language,pick(radio_messages),"1459",person.get_spans()))
+ var/message = target.compose_message(person,understood_language,pick(radio_messages),"1459",person.get_spans())
+ feedback_details += "Type: Radio, Source: [person.real_name], Message: [message]"
+ to_chat(target, message)
qdel(src)
-/obj/effect/hallucination/message
+/datum/hallucination/message
+ cost = 15
-/obj/effect/hallucination/message/Initialize(mapload, var/mob/living/carbon/T)
+/datum/hallucination/message/New(mob/living/carbon/T, forced = TRUE)
..()
- target = T
var/chosen = pick("The light burns you!", \
"You don't feel like yourself.", \
- "Unknown has punched [target]!", \
"You hear something squeezing through the ducts...", \
"You hear a distant scream.", \
"You feel invincible, nothing can hurt you!", \
"You feel a tiny prick!", \
"[target] sneezes.", \
- "You feel faint.", \
- "You hear a strange, alien voice in your head...[pick("Hiss","Ssss")]", \
- "You can see...everything!")
+ //The truth, revealed
+ "You're hallucinating.", \
+ //Direct advice
+ "[pick_list_replacements(HAL_LINES_FILE, "advice")]")
+ feedback_details += "Message: [chosen]"
to_chat(target, chosen)
qdel(src)
-/mob/living/carbon/proc/hallucinate(hal_type, specific) // specific is used to specify a particular hallucination
- set waitfor = 0
- switch(hal_type)
- if("xeno")
- new /obj/effect/hallucination/xeno_attack(src.loc,src)
- if("borer")
- new /obj/effect/hallucination/borer(src.loc,src)
- if("singulo")
- new /obj/effect/hallucination/singularity_scare(src.loc,src)
- if("koolaid")
- new /obj/effect/hallucination/oh_yeah(src.loc,src)
- if("battle")
- new /obj/effect/hallucination/battle(src.loc,src)
- if("flood")
- new /obj/effect/hallucination/fake_flood(src.loc,src)
- if("delusion")
- new /obj/effect/hallucination/delusion(src.loc,src)
- if("self_delusion")
- new /obj/effect/hallucination/self_delusion(src.loc,src)
- if("fake")
- new /obj/effect/hallucination/fakeattacker(src.loc,src)
- if("bolts")
- new /obj/effect/hallucination/bolts(src.loc,src)
- if("bolts_minor")
- new /obj/effect/hallucination/bolts(src.loc,src,rand(1,2))
- if("whispers")
- new /obj/effect/hallucination/whispers(src.loc,src)
- if("message")
- new /obj/effect/hallucination/message(src.loc,src)
- if("items_other")
- new /obj/effect/hallucination/items_other(src.loc,src)
- if("sounds")
- //Strange audio
- switch(rand(1,20))
- if(1) playsound_local(null,'sound/machines/airlock.ogg', 15, 1)
- if(2)
- if(prob(50)) playsound_local(null,'sound/effects/explosion1.ogg', 50, 1)
- else playsound_local(null, 'sound/effects/explosion2.ogg', 50, 1)
- if(3) playsound_local(null, 'sound/effects/explosionfar.ogg', 50, 1)
- if(4) playsound_local(null, pick('sound/effects/glassbr1.ogg','sound/effects/glassbr2.ogg','sound/effects/glassbr3.ogg'), 50, 1)
- if(5)
- playsound_local(null, 'sound/weapons/ring.ogg', 35)
- sleep(15)
- playsound_local(null, 'sound/weapons/ring.ogg', 35)
- sleep(15)
- playsound_local(null, 'sound/weapons/ring.ogg', 35)
- if(6) playsound_local(null, 'sound/magic/summon_guns.ogg', 50, 1)
- if(7) playsound_local(null, 'sound/machines/alarm.ogg', 100, 0)
- if(8) playsound_local(null, 'sound/voice/bfreeze.ogg', 35, 0)
- if(9)
- //To make it more realistic, I added two gunshots (enough to kill)
- playsound_local(null, 'sound/weapons/gunshot.ogg', 25, 1)
- spawn(rand(10,30))
- playsound_local(null, 'sound/weapons/gunshot.ogg', 25, 1)
- sleep(rand(5,10))
- playsound_local(null, sound(get_sfx("bodyfall"), 25), 25, 1)
- if(10) playsound_local(null, 'sound/effects/pray_chaplain.ogg', 50)
- if(11)
- //Same as above, but with tasers.
- playsound_local(null, 'sound/weapons/taser.ogg', 25, 1)
- spawn(rand(10,30))
- playsound_local(null, 'sound/weapons/taser.ogg', 25, 1)
- sleep(rand(5,10))
- playsound_local(null, sound(get_sfx("bodyfall"), 25), 25, 1)
- //Rare audio
- if(12)
- //These sounds are (mostly) taken from Hidden: Source
- var/list/creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/heart_beat.ogg', 'sound/effects/screech.ogg',\
- 'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\
- 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\
- 'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\
- 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg')
- playsound_local(null, pick(creepyasssounds), 50, 1)
- if(13)
- playsound_local(null, 'sound/effects/ratvar_rises.ogg', 100)
- sleep(150)
- playsound_local(null, 'sound/effects/ratvar_reveal.ogg', 100)
- if(14)
- to_chat(src, "Priority Announcement
")
- to_chat(src, "
The Emergency Shuttle has docked with the station. You have 3 minutes to board the Emergency Shuttle.
")
- playsound_local(null, 'sound/ai/shuttledock.ogg', 100)
- //Deconstructing a wall
- if(15)
- playsound_local(null, 'sound/items/welder.ogg', 15, 1)
- sleep(105)
- playsound_local(null, 'sound/items/welder2.ogg', 15, 1)
- sleep(15)
- playsound_local(null, 'sound/items/ratchet.ogg', 15, 1)
- //Hacking a door
- if(16)
- playsound_local(null, 'sound/items/screwdriver.ogg', 15, 1)
- sleep(rand(10,30))
- for(var/i = rand(1,3), i>0, i--)
- playsound_local(null, 'sound/weapons/empty.ogg', 15, 1)
- sleep(rand(10,30))
- playsound_local(null, 'sound/machines/airlockforced.ogg', 15, 1)
- if(17)
- playsound_local(null, 'sound/weapons/saberon.ogg',35,1)
- if(18)
- to_chat(src, "Biohazard Alert
")
- to_chat(src, "
Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.
")
- playsound_local(null, 'sound/ai/outbreak5.ogg')
- if(19) //Tesla loose!
- playsound_local(null, 'sound/magic/lightningbolt.ogg', 35, 1)
- sleep(20)
- playsound_local(null, 'sound/magic/lightningbolt.ogg', 65, 1)
- sleep(20)
- playsound_local(null, 'sound/magic/lightningbolt.ogg', 100, 1)
- if(20) //AI is doomsdaying!
- to_chat(src, "Anomaly Alert
")
- to_chat(src, "
Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.
")
- playsound_local(null, 'sound/ai/aimalf.ogg', 100)
- if("hudscrew")
- //Screwy HUD
- //to_chat(src, "Screwy HUD")
- hal_screwyhud = pick(SCREWYHUD_NONE,SCREWYHUD_CRIT,SCREWYHUD_DEAD,SCREWYHUD_HEALTHY)
- sleep(rand(100,250))
- hal_screwyhud = 0
+/datum/hallucination/sounds
+ cost = 15
- if("fake_alert")
- var/alert_type = pick("not_enough_oxy","not_enough_tox","not_enough_co2","too_much_oxy","too_much_co2","too_much_tox","newlaw","nutrition","charge","weightless","fire","locked","hacked","temp","pressure")
- if(specific)
- alert_type = specific
- switch(alert_type)
- if("not_enough_oxy")
- throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy, override = TRUE)
- if("not_enough_tox")
- throw_alert("not_enough_tox", /obj/screen/alert/not_enough_tox, override = TRUE)
- if("not_enough_co2")
- throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2, override = TRUE)
- if("too_much_oxy")
- throw_alert("too_much_oxy", /obj/screen/alert/too_much_oxy, override = TRUE)
- if("too_much_co2")
- throw_alert("too_much_co2", /obj/screen/alert/too_much_co2, override = TRUE)
- if("too_much_tox")
- throw_alert("too_much_tox", /obj/screen/alert/too_much_tox, override = TRUE)
- if("nutrition")
- if(prob(50))
- throw_alert("nutrition", /obj/screen/alert/fat, override = TRUE)
- else
- throw_alert("nutrition", /obj/screen/alert/starving, override = TRUE)
- if("weightless")
- throw_alert("weightless", /obj/screen/alert/weightless, override = TRUE)
- if("fire")
- throw_alert("fire", /obj/screen/alert/fire, override = TRUE)
- if("temp")
- if(prob(50))
- throw_alert("temp", /obj/screen/alert/hot, 3, override = TRUE)
- else
- throw_alert("temp", /obj/screen/alert/cold, 3, override = TRUE)
- if("pressure")
- if(prob(50))
- throw_alert("pressure", /obj/screen/alert/highpressure, 2, override = TRUE)
- else
- throw_alert("pressure", /obj/screen/alert/lowpressure, 2, override = TRUE)
- //BEEP BOOP I AM A ROBOT
- if("newlaw")
- throw_alert("newlaw", /obj/screen/alert/newlaw, override = TRUE)
- if("locked")
- throw_alert("locked", /obj/screen/alert/locked, override = TRUE)
- if("hacked")
- throw_alert("hacked", /obj/screen/alert/hacked, override = TRUE)
- if("charge")
- throw_alert("charge", /obj/screen/alert/emptycell, override = TRUE)
- sleep(rand(100,200))
- clear_alert(alert_type, clear_override = TRUE)
-
- if("items")
- //Strange items
- //to_chat(src, "Traitor Items")
- if(!halitem)
- halitem = new
- var/obj/item/l_hand = get_item_for_held_index(1)
- var/obj/item/r_hand = get_item_for_held_index(2)
- var/l = ui_hand_position(get_held_index_of_item(l_hand))
- var/r = ui_hand_position(get_held_index_of_item(r_hand))
- var/list/slots_free = list(l,r)
- if(l_hand) slots_free -= l
- if(r_hand) slots_free -= r
- if(ishuman(src))
- var/mob/living/carbon/human/H = src
- if(!H.belt) slots_free += ui_belt
- if(!H.l_store) slots_free += ui_storage1
- if(!H.r_store) slots_free += ui_storage2
- if(slots_free.len)
- halitem.screen_loc = pick(slots_free)
- halitem.layer = ABOVE_HUD_LAYER
- halitem.plane = ABOVE_HUD_PLANE
- switch(rand(1,6))
- if(1) //revolver
- halitem.icon = 'icons/obj/guns/projectile.dmi'
- halitem.icon_state = "revolver"
- halitem.name = "Revolver"
- if(2) //c4
- halitem.icon = 'icons/obj/grenade.dmi'
- halitem.icon_state = "plastic-explosive0"
- halitem.name = "Mysterious Package"
- if(prob(25))
- halitem.icon_state = "c4small_1"
- if(3) //sword
- halitem.icon = 'icons/obj/weapons.dmi'
- halitem.icon_state = "sword1"
- halitem.name = "Sword"
- if(4) //stun baton
- halitem.icon = 'icons/obj/weapons.dmi'
- halitem.icon_state = "stunbaton"
- halitem.name = "Stun Baton"
- if(5) //emag
- halitem.icon = 'icons/obj/card.dmi'
- halitem.icon_state = "emag"
- halitem.name = "Cryptographic Sequencer"
- if(6) //flashbang
- halitem.icon = 'icons/obj/grenade.dmi'
- halitem.icon_state = "flashbang1"
- halitem.name = "Flashbang"
- if(client) client.screen += halitem
- QDEL_IN(halitem, rand(100, 250))
- if("dangerflash")
- //Flashes of danger
- //to_chat(src, "Danger Flash")
- if(!halimage)
- var/list/possible_points = list()
- for(var/turf/open/floor/F in view(src,world.view))
- possible_points += F
- if(possible_points.len)
- var/turf/open/floor/target = pick(possible_points)
-
- switch(rand(1,4))
- if(1)
- //to_chat(src, "Space")
- halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER)
- if(2)
- //to_chat(src, "Lava")
- halimage = image('icons/turf/floors/lava.dmi',target,"smooth",TURF_LAYER)
- if(3)
- //to_chat(src, "Chasm")
- halimage = image('icons/turf/floors/Chasms.dmi',target,"smooth",TURF_LAYER)
- if(4)
- //to_chat(src, "C4")
- halimage = image('icons/obj/grenade.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01)
-
-
- if(client) client.images += halimage
- sleep(rand(40,60)) //Only seen for a brief moment.
- if(client) client.images -= halimage
- halimage = null
- if("death")
- //Fake death
- hal_screwyhud = SCREWYHUD_DEAD
- SetUnconscious(400)
- var/area/area = get_area(src)
- to_chat(src, "[mind.name] has died at [area.name].")
+/datum/hallucination/sounds/New(mob/living/carbon/T, forced = TRUE, sound_type)
+ ..()
+ if(!sound_type)
+ sound_type = pick("airlock","explosion","far_explosion","glass","phone","summon_guns","alarm","beepsky","hallelujah","creepy","ratvar","shuttle_dock",
+ "wall_decon","door_hack","esword","blob_alert","tesla","malf_ai")
+ feedback_details += "Type: [sound_type]"
+ //Strange audio
+ switch(sound_type)
+ if("airlock")
+ target.playsound_local(null,'sound/machines/airlock.ogg', 15, 1)
+ if("explosion")
if(prob(50))
- var/list/dead_people = list()
- for(var/mob/dead/observer/G in GLOB.player_list)
- dead_people += G
- var/mob/dead/observer/fakemob = pick(dead_people)
- if(fakemob)
- sleep(rand(30, 60))
- to_chat(src, "DEAD: [fakemob.name] says, \"[pick("rip","welcome [first_name()]","you too?","is the AI malf?",\
- "i[prob(50)?" fucking":""] hate [pick("blood cult", "clock cult", "revenants", "abductors","double agents","viruses","badmins","you")]")]\"")
- sleep(rand(50,70))
- hal_screwyhud = SCREWYHUD_NONE
- SetSleeping(0)
- if("husks")
- if(!halbody)
- var/list/possible_points = list()
- for(var/turf/open/floor/F in view(src,world.view))
- possible_points += F
- if(possible_points.len)
- var/turf/open/floor/target = pick(possible_points)
- switch(rand(1,4))
- if(1)
- var/image/body = image('icons/mob/human.dmi',target,"husk",TURF_LAYER)
- var/matrix/M = matrix()
- M.Turn(90)
- body.transform = M
- halbody = body
- if(2,3)
- halbody = image('icons/mob/human.dmi',target,"husk",TURF_LAYER)
- if(4)
- halbody = image('icons/mob/alien.dmi',target,"alienother",TURF_LAYER)
+ target.playsound_local(null,'sound/effects/explosion1.ogg', 50, 1)
+ else
+ target.playsound_local(null, 'sound/effects/explosion2.ogg', 50, 1)
+ if("far_explosion")
+ target.playsound_local(null, 'sound/effects/explosionfar.ogg', 50, 1)
+ if("glass")
+ target.playsound_local(null, pick('sound/effects/glassbr1.ogg','sound/effects/glassbr2.ogg','sound/effects/glassbr3.ogg'), 50, 1)
+ if("phone")
+ target.playsound_local(null, 'sound/weapons/ring.ogg', 35)
+ sleep(15)
+ target.playsound_local(null, 'sound/weapons/ring.ogg', 35)
+ sleep(15)
+ target.playsound_local(null, 'sound/weapons/ring.ogg', 35)
+ if("summon_guns")
+ target.playsound_local(null, 'sound/magic/summon_guns.ogg', 50, 1)
+ if("alarm")
+ target.playsound_local(null, 'sound/machines/alarm.ogg', 100, 0)
+ if("beepsky")
+ target.playsound_local(null, 'sound/voice/bfreeze.ogg', 35, 0)
+ if("hallelujah")
+ target.playsound_local(null, 'sound/effects/pray_chaplain.ogg', 50)
+ //Rare audio
+ if("creepy")
+ //These sounds are (mostly) taken from Hidden: Source
+ var/static/list/hallucinations_creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/heart_beat.ogg', 'sound/effects/screech.ogg',\
+ 'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\
+ 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\
+ 'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\
+ 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg')
+ target.playsound_local(null, pick(hallucinations_creepyasssounds), 50, 1)
+ if("ratvar")
+ target.playsound_local(null, 'sound/effects/ratvar_rises.ogg', 100)
+ sleep(150)
+ target.playsound_local(null, 'sound/effects/ratvar_reveal.ogg', 100)
+ if("shuttle_dock")
+ to_chat(target, "Priority Announcement
")
+ to_chat(target, "
The Emergency Shuttle has docked with the station. You have 3 minutes to board the Emergency Shuttle.
")
+ target.playsound_local(null, 'sound/ai/shuttledock.ogg', 100)
+ //Deconstructing a wall
+ if("wall_decon")
+ target.playsound_local(null, 'sound/items/welder.ogg', 15, 1)
+ sleep(105)
+ target.playsound_local(null, 'sound/items/welder2.ogg', 15, 1)
+ sleep(15)
+ target.playsound_local(null, 'sound/items/ratchet.ogg', 15, 1)
+ //Hacking a door
+ if("door_hack")
+ target.playsound_local(null, 'sound/items/screwdriver.ogg', 15, 1)
+ sleep(rand(10,30))
+ for(var/i = rand(1,3), i>0, i--)
+ target.playsound_local(null, 'sound/weapons/empty.ogg', 15, 1)
+ sleep(rand(10,30))
+ target.playsound_local(null, 'sound/machines/airlockforced.ogg', 15, 1)
+ if("esword")
+ target.playsound_local(null, 'sound/weapons/saberon.ogg',35,1)
+ if("blob_alert")
+ to_chat(target, "Biohazard Alert
")
+ to_chat(target, "
Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.
")
+ target.playsound_local(null, 'sound/ai/outbreak5.ogg', 100, 0)
+ if("tesla") //Tesla loose!
+ target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 35, 1)
+ sleep(20)
+ target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 65, 1)
+ sleep(20)
+ target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 100, 1)
+ if("malf_ai") //AI is doomsdaying!
+ to_chat(target, "Anomaly Alert
")
+ to_chat(target, "
Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.
")
+ target.playsound_local(null, 'sound/ai/aimalf.ogg', 100, 0)
+ qdel(src)
+
+/datum/hallucination/hudscrew
+ cost = 10
+
+/datum/hallucination/hudscrew/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ //Screwy HUD
+ target.set_screwyhud(pick(SCREWYHUD_CRIT,SCREWYHUD_DEAD,SCREWYHUD_HEALTHY))
+ feedback_details += "Type: [target.hal_screwyhud]"
+ sleep(rand(100,250))
+ target.set_screwyhud(SCREWYHUD_NONE)
+ qdel(src)
+
+/datum/hallucination/fake_alert
+ cost = 15
+
+/datum/hallucination/fake_alert/New(mob/living/carbon/T, forced = TRUE, specific, duration = 150)
+ ..()
+ var/alert_type = pick("not_enough_oxy","not_enough_tox","not_enough_co2","too_much_oxy","too_much_co2","too_much_tox","newlaw","nutrition","charge","weightless","fire","locked","hacked","temphot","tempcold","pressure")
+ if(specific)
+ alert_type = specific
+ feedback_details += "Type: [alert_type]"
+ switch(alert_type)
+ if("oxy")
+ target.throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy, override = TRUE)
+ if("not_enough_tox")
+ target.throw_alert("not_enough_tox", /obj/screen/alert/not_enough_tox, override = TRUE)
+ if("not_enough_co2")
+ target.throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2, override = TRUE)
+ if("too_much_oxy")
+ target.throw_alert("too_much_oxy", /obj/screen/alert/too_much_oxy, override = TRUE)
+ if("too_much_co2")
+ target.throw_alert("too_much_co2", /obj/screen/alert/too_much_co2, override = TRUE)
+ if("tox_in_air")
+ target.throw_alert("too_much_tox", /obj/screen/alert/too_much_tox, override = TRUE)
+ if("nutrition")
+ if(prob(50))
+ target.throw_alert("nutrition", /obj/screen/alert/fat, override = TRUE)
+ else
+ target.throw_alert("nutrition", /obj/screen/alert/starving, override = TRUE)
+ if("weightless")
+ target.throw_alert("weightless", /obj/screen/alert/weightless, override = TRUE)
+ if("fire")
+ target.throw_alert("fire", /obj/screen/alert/fire, override = TRUE)
+ if("temphot")
+ target.throw_alert("temp", /obj/screen/alert/hot, 3, override = TRUE)
+ if("tempcold")
+ target.throw_alert("temp", /obj/screen/alert/cold, 3, override = TRUE)
+ if("pressure")
+ if(prob(50))
+ target.throw_alert("pressure", /obj/screen/alert/highpressure, 2, override = TRUE)
+ else
+ target.throw_alert("pressure", /obj/screen/alert/lowpressure, 2, override = TRUE)
+ //BEEP BOOP I AM A ROBOT
+ if("newlaw")
+ target.throw_alert("newlaw", /obj/screen/alert/newlaw, override = TRUE)
+ if("locked")
+ target.throw_alert("locked", /obj/screen/alert/locked, override = TRUE)
+ if("hacked")
+ target.throw_alert("hacked", /obj/screen/alert/hacked, override = TRUE)
+ if("charge")
+ target.throw_alert("charge",/obj/screen/alert/emptycell, override = TRUE)
+ sleep(duration)
+ target.clear_alert(alert_type, clear_override = TRUE)
+ qdel(src)
+
+/datum/hallucination/items
+ cost = 15
+
+/datum/hallucination/items/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ //Strange items
+ if(!target.halitem)
+ target.halitem = new
+ var/obj/item/l_hand = target.get_item_for_held_index(1)
+ var/obj/item/r_hand = target.get_item_for_held_index(2)
+ var/l = ui_hand_position(target.get_held_index_of_item(l_hand))
+ var/r = ui_hand_position(target.get_held_index_of_item(r_hand))
+ var/list/slots_free = list(l,r)
+ if(l_hand) slots_free -= l
+ if(r_hand) slots_free -= r
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ if(!H.belt) slots_free += ui_belt
+ if(!H.l_store) slots_free += ui_storage1
+ if(!H.r_store) slots_free += ui_storage2
+ if(slots_free.len)
+ target.halitem.screen_loc = pick(slots_free)
+ target.halitem.layer = ABOVE_HUD_LAYER
+ target.halitem.plane = ABOVE_HUD_PLANE
+ switch(rand(1,6))
+ if(1) //revolver
+ target.halitem.icon = 'icons/obj/guns/projectile.dmi'
+ target.halitem.icon_state = "revolver"
+ target.halitem.name = "Revolver"
+ if(2) //c4
+ target.halitem.icon = 'icons/obj/grenade.dmi'
+ target.halitem.icon_state = "plastic-explosive0"
+ target.halitem.name = "C4"
+ if(prob(25))
+ target.halitem.icon_state = "plasticx40"
+ if(3) //sword
+ target.halitem.icon = 'icons/obj/weapons.dmi'
+ target.halitem.icon_state = "sword0"
+ target.halitem.name = "Energy Sword"
+ if(4) //stun baton
+ target.halitem.icon = 'icons/obj/weapons.dmi'
+ target.halitem.icon_state = "stunbaton"
+ target.halitem.name = "Stun Baton"
+ if(5) //emag
+ target.halitem.icon = 'icons/obj/card.dmi'
+ target.halitem.icon_state = "emag"
+ target.halitem.name = "Cryptographic Sequencer"
+ if(6) //flashbang
+ target.halitem.icon = 'icons/obj/grenade.dmi'
+ target.halitem.icon_state = "flashbang1"
+ target.halitem.name = "Flashbang"
+ feedback_details += "Type: [target.halitem.name]"
+ if(target.client) target.client.screen += target.halitem
+ QDEL_IN(target.halitem, rand(150, 350))
+ qdel(src)
+
+/datum/hallucination/dangerflash
+ cost = 15
+
+/datum/hallucination/dangerflash/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ //Flashes of danger
+ if(!target.halimage)
+ var/list/possible_points = list()
+ for(var/turf/open/floor/F in view(target,world.view))
+ possible_points += F
+ if(possible_points.len)
+ var/turf/open/floor/danger_point = pick(possible_points)
+
+ switch(rand(1,5))
+ if(1)
+ target.halimage = image('icons/turf/space.dmi',danger_point,"[rand(1,25)]",TURF_LAYER)
+ if(2)
+ target.halimage = image('icons/turf/floors/lava.dmi',danger_point,"smooth",TURF_LAYER)
+ if(3)
+ target.halimage = image('icons/turf/floors/Chasms.dmi',danger_point,"smooth",TURF_LAYER)
+ if(4)
+ target.halimage = image('icons/effects/effects.dmi',danger_point,"anom",OBJ_LAYER+0.01)
+ if(5)
+ target.halimage = image('icons/effects/effects.dmi',danger_point,"electricity2",OBJ_LAYER+0.01)
+
+
+ if(target.client)
+ target.client.images += target.halimage
+ sleep(rand(200,450))
+ if(target.client)
+ target.client.images -= target.halimage
+ QDEL_NULL(target.halimage)
+ qdel(src)
+
+/datum/hallucination/death
+ cost = 40
+
+/datum/hallucination/death/New(mob/living/carbon/T, forced = TRUE)
+ set waitfor = 0
+ ..()
+ target.set_screwyhud(SCREWYHUD_DEAD)
+ target.Knockdown(300)
+ target.silent += 10
+ var/area/area = get_area(target)
+ to_chat(target, "[target.mind.name] has died at [area.name].")
+ if(prob(50))
+ var/mob/fakemob
+ var/list/dead_people = list()
+ for(var/mob/dead/observer/G in GLOB.player_list)
+ dead_people += G
+ if(LAZYLEN(dead_people))
+ fakemob = pick(dead_people)
+ else
+ fakemob = target //ever been so lonely you had to haunt yourself?
+ if(fakemob)
+ sleep(rand(20, 50))
+ to_chat(target, "DEAD: [fakemob.name] says, \"[pick("rip","hey [target.first_name()]","you too?","is the AI rogue?",\
+ "i[prob(50)?" fucking":""] hate [pick("blood cult", "clock cult", "revenants", "abductors","double agents","viruses","badmins","you")]")]\"")
+ sleep(rand(70,90))
+ target.set_screwyhud(SCREWYHUD_NONE)
+ target.SetKnockdown(0)
+ target.silent = 0
+ qdel(src)
+
+/datum/hallucination/fire
+ cost = 25
+
+/datum/hallucination/fire/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ var/image/fire_overlay = image('icons/mob/OnFire.dmi', target, "Standing", ABOVE_MOB_LAYER)
+ if(target.client)
+ target.client.images += fire_overlay
+ to_chat(target, "You're set on fire!")
+ target.throw_alert("fire", /obj/screen/alert/fire, override = TRUE)
+ sleep(20)
+ target.throw_alert("temp", /obj/screen/alert/hot, 1, override = TRUE)
+ sleep(30)
+ target.clear_alert("temp", clear_override = TRUE)
+ target.throw_alert("temp", /obj/screen/alert/hot, 2, override = TRUE)
+ sleep(30)
+ target.clear_alert("temp", clear_override = TRUE)
+ target.throw_alert("temp", /obj/screen/alert/hot, 3, override = TRUE)
+ for(var/i in 1 to rand(5, 10))
+ target.adjustStaminaLoss(15)
+ sleep(25)
+ target.clear_alert("fire", clear_override = TRUE)
+ target.clear_alert("temp", clear_override = TRUE)
+ if(target.client)
+ target.client.images -= fire_overlay
+ QDEL_NULL(fire_overlay)
+ qdel(src)
+
+/datum/hallucination/husks
+ cost = 20
+
+/datum/hallucination/husks/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ if(!target.halbody)
+ var/list/possible_points = list()
+ for(var/turf/open/floor/F in view(target,world.view))
+ possible_points += F
+ if(possible_points.len)
+ var/turf/open/floor/husk_point = pick(possible_points)
+ switch(rand(1,4))
+ if(1)
+ var/image/body = image('icons/mob/human.dmi',husk_point,"husk",TURF_LAYER)
+ var/matrix/M = matrix()
+ M.Turn(90)
+ body.transform = M
+ target.halbody = body
+ if(2,3)
+ target.halbody = image('icons/mob/human.dmi',husk_point,"husk",TURF_LAYER)
+ if(4)
+ target.halbody = image('icons/mob/alien.dmi',husk_point,"alienother",TURF_LAYER)
+
+ if(target.client)
+ target.client.images += target.halbody
+ sleep(rand(30,50)) //Only seen for a brief moment.
+ if(target.client)
+ target.client.images -= target.halbody
+ QDEL_NULL(target.halbody)
+ qdel(src)
+
+//hallucination projectile code in code/modules/projectiles/projectile/special.dm
+/datum/hallucination/stray_bullet
+ cost = 15
+
+/datum/hallucination/stray_bullet/New(mob/living/carbon/C, forced = TRUE)
+ ..()
+ var/list/turf/startlocs = list()
+ for(var/turf/open/T in view(world.view+1,target)-view(world.view,target))
+ startlocs += T
+ var/turf/start = pick(startlocs)
+ var/proj_type = pick(subtypesof(/obj/item/projectile/hallucination))
+ feedback_details += "Type: [proj_type]"
+ var/obj/item/projectile/hallucination/H = new proj_type(start)
+ target.playsound_local(start, H.hal_fire_sound, 60, 1)
+ H.hal_target = target
+ H.current = start
+ H.starting = start
+ H.yo = target.y - start.y
+ H.xo = target.x - start.x
+ H.original = target
+ H.fire()
+ qdel(src)
- if(client) client.images += halbody
- spawn(rand(30,50)) //Only seen for a brief moment.
- if(client) client.images -= halbody
- halbody = null
diff --git a/code/modules/flufftext/Hallucination.dm.rej b/code/modules/flufftext/Hallucination.dm.rej
new file mode 100644
index 0000000000..2b8fe4b064
--- /dev/null
+++ b/code/modules/flufftext/Hallucination.dm.rej
@@ -0,0 +1,1151 @@
+/*
+Ideas for the subtle effects of hallucination:
+
+Light up oxygen/plasma indicators (done)
+Cause health to look critical/dead, even when standing (done)
+Characters silently watching you
+Brief flashes of fire/space/bombs/c4/dangerous shit (done)
+Items that are rare/traitorous/don't exist appearing in your inventory slots (done)
+Strange audio (should be rare) (done)
+Gunshots/explosions/opening doors/less rare audio (done)
+
+*/
+
+#define HAL_LINES_FILE "hallucination.json"
+
+/mob/living/carbon
+ var/image/halimage
+ var/image/halbody
+ var/obj/halitem
+ var/hal_screwyhud = SCREWYHUD_NONE
+ var/next_hallucination = 0
+
+GLOBAL_LIST_INIT(hallucinations_minor, list(
+ /datum/hallucination/sounds,
+ /datum/hallucination/bolts,
+ /datum/hallucination/whispers,
+ /datum/hallucination/message,
+ /datum/hallucination/hudscrew))
+
+GLOBAL_LIST_INIT(hallucinations_medium, list(
+ /datum/hallucination/fake_alert,
+ /datum/hallucination/items,
+ /datum/hallucination/items_other,
+ /datum/hallucination/dangerflash,
+ /datum/hallucination/bolts,
+ /datum/hallucination/fake_flood,
+ /datum/hallucination/husks,
+ /datum/hallucination/battle,
+ /datum/hallucination/fire,
+ /datum/hallucination/self_delusion))
+
+GLOBAL_LIST_INIT(hallucinations_major, list(
+ /datum/hallucination/fakeattacker,
+ /datum/hallucination/death,
+ /datum/hallucination/xeno_attack,
+ /datum/hallucination/singularity_scare,
+ /datum/hallucination/delusion,
+ /datum/hallucination/oh_yeah))
+
+/mob/living/carbon/proc/handle_hallucinations()
+ if(world.time < next_hallucination)
+ return
+
+ if(hallucination)
+ var/list/current = GLOB.hallucinations_minor
+ if(prob(25) && hallucination > 100)
+ current = GLOB.hallucinations_medium
+ else if(prob(10) && hallucination > 200)
+ current = GLOB.hallucinations_major
+ var/halpick = pick(current)
+ new halpick(src, FALSE)
+
+/mob/living/carbon/proc/set_screwyhud(hud_type)
+ hal_screwyhud = hud_type
+ update_health_hud()
+
+/datum/hallucination
+ var/mob/living/carbon/target
+ var/cost = 5 //affects the amount of hallucination reduced, and cooldown until the next hallucination
+ var/feedback_details //extra info for investigate
+
+/datum/hallucination/New(mob/living/carbon/T, forced = TRUE)
+ set waitfor = 0
+ target = T
+ if(!forced)
+ target.hallucination = max(0, target.hallucination - cost)
+ target.next_hallucination = world.time + (rand(cost * 0.5, cost * 3) * 10)
+
+/datum/hallucination/proc/wake_and_restore()
+ target.set_screwyhud(SCREWYHUD_NONE)
+ target.SetSleeping(0)
+
+/datum/hallucination/Destroy()
+ target.investigate_log("was afflicted with a hallucination of type [type]. [feedback_details]", INVESTIGATE_HALLUCINATIONS)
+ return ..()
+
+/obj/effect/hallucination
+ invisibility = INVISIBILITY_OBSERVER
+ var/mob/living/carbon/target = null
+
+/obj/effect/hallucination/simple
+ var/image_icon = 'icons/mob/alien.dmi'
+ var/image_state = "alienh_pounce"
+ var/px = 0
+ var/py = 0
+ var/col_mod = null
+ var/image/current_image = null
+ var/image_layer = MOB_LAYER
+ var/active = TRUE //qdelery
+
+/obj/effect/hallucination/simple/Initialize(mapload, var/mob/living/carbon/T)
+ ..()
+ target = T
+ current_image = GetImage()
+ if(target.client)
+ target.client.images |= current_image
+
+/obj/effect/hallucination/simple/proc/GetImage()
+ var/image/I = image(image_icon,src,image_state,image_layer,dir=src.dir)
+ I.pixel_x = px
+ I.pixel_y = py
+ if(col_mod)
+ I.color = col_mod
+ return I
+
+/obj/effect/hallucination/simple/proc/Show(update=1)
+ if(active)
+ if(target.client)
+ target.client.images.Remove(current_image)
+ if(update)
+ current_image = GetImage()
+ if(target.client)
+ target.client.images |= current_image
+
+/obj/effect/hallucination/simple/update_icon(new_state,new_icon,new_px=0,new_py=0)
+ image_state = new_state
+ if(new_icon)
+ image_icon = new_icon
+ else
+ image_icon = initial(image_icon)
+ px = new_px
+ py = new_py
+ Show()
+
+/obj/effect/hallucination/simple/Moved(atom/OldLoc, Dir)
+ Show()
+
+/obj/effect/hallucination/simple/Destroy()
+ if(target.client)
+ target.client.images.Remove(current_image)
+ active = FALSE
+ return ..()
+
+#define FAKE_FLOOD_EXPAND_TIME 20
+#define FAKE_FLOOD_MAX_RADIUS 10
+
+/datum/hallucination/fake_flood
+ //Plasma starts flooding from the nearby vent
+ var/turf/center
+ var/list/flood_images = list()
+ var/list/turf/flood_turfs = list()
+ var/image_icon = 'icons/effects/tile_effects.dmi'
+ var/image_state = "plasma"
+ var/radius = 0
+ var/next_expand = 0
+ cost = 25
+
+/datum/hallucination/fake_flood/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target))
+ if(!U.welded)
+ center = get_turf(U)
+ break
+ feedback_details += "Vent Coords: [center.x],[center.y],[center.z]"
+ flood_images += image(image_icon,center,image_state,MOB_LAYER)
+ flood_turfs += center
+ if(target.client) target.client.images |= flood_images
+ next_expand = world.time + FAKE_FLOOD_EXPAND_TIME
+ START_PROCESSING(SSobj, src)
+
+/datum/hallucination/fake_flood/process()
+ if(next_expand <= world.time)
+ radius++
+ if(radius > FAKE_FLOOD_MAX_RADIUS)
+ qdel(src)
+ return
+ Expand()
+ if((get_turf(target) in flood_turfs) && !target.internal)
+ new /datum/hallucination/fake_alert(target, TRUE, "tox_in_air")
+ next_expand = world.time + FAKE_FLOOD_EXPAND_TIME
+
+/datum/hallucination/fake_flood/proc/Expand()
+ for(var/turf/FT in flood_turfs)
+ for(var/dir in GLOB.cardinals)
+ var/turf/T = get_step(FT, dir)
+ if((T in flood_turfs) || !FT.CanAtmosPass(T))
+ continue
+ flood_images += image(image_icon,T,image_state,MOB_LAYER)
+ flood_turfs += T
+ if(target.client)
+ target.client.images |= flood_images
+
+/datum/hallucination/fake_flood/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ qdel(flood_turfs)
+ flood_turfs = list()
+ if(target.client)
+ target.client.images.Remove(flood_images)
+ target = null
+ qdel(flood_images)
+ flood_images = list()
+ return ..()
+
+/obj/effect/hallucination/simple/xeno
+ image_icon = 'icons/mob/alien.dmi'
+ image_state = "alienh_pounce"
+
+/obj/effect/hallucination/simple/xeno/Initialize(mapload, mob/living/carbon/T)
+ ..()
+ name = "alien hunter ([rand(1, 1000)])"
+
+/obj/effect/hallucination/simple/xeno/throw_impact(A)
+ update_icon("alienh_pounce")
+ if(A == target && target.stat!=DEAD)
+ target.Knockdown(100)
+ target.visible_message("[target] flails around wildly.","[name] pounces on you!")
+
+/datum/hallucination/xeno_attack
+ //Xeno crawls from nearby vent,jumps at you, and goes back in
+ var/obj/machinery/atmospherics/components/unary/vent_pump/pump = null
+ var/obj/effect/hallucination/simple/xeno/xeno = null
+ cost = 25
+
+/datum/hallucination/xeno_attack/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target))
+ if(!U.welded)
+ pump = U
+ break
+ feedback_details += "Vent Coords: [pump.x],[pump.y],[pump.z]"
+ if(pump)
+ xeno = new(pump.loc,target)
+ sleep(10)
+ xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
+ xeno.throw_at(target,7,1, spin = 0, diagonals_first = 1)
+ sleep(10)
+ xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
+ xeno.throw_at(pump,7,1, spin = 0, diagonals_first = 1)
+ sleep(10)
+ var/xeno_name = xeno.name
+ to_chat(target, "[xeno_name] begins climbing into the ventilation system...")
+ sleep(30)
+ qdel(xeno)
+ to_chat(target, "[xeno_name] scrambles into the ventilation ducts!")
+ qdel(src)
+
+/obj/effect/hallucination/simple/clown
+ image_icon = 'icons/mob/animal.dmi'
+ image_state = "clown"
+
+/obj/effect/hallucination/simple/clown/Initialize(mapload, mob/living/carbon/T, duration)
+ ..(loc, T)
+ name = pick(GLOB.clown_names)
+ QDEL_IN(src,duration)
+
+/obj/effect/hallucination/simple/clown/scary
+ image_state = "scary_clown"
+
+/obj/effect/hallucination/simple/bubblegum
+ name = "Bubblegum"
+ image_icon = 'icons/mob/lavaland/96x96megafauna.dmi'
+ image_state = "bubblegum"
+ px = -32
+
+/datum/hallucination/oh_yeah
+ var/obj/effect/hallucination/simple/bubblegum/bubblegum
+ var/image/fakebroken
+ var/image/fakerune
+ cost = 75
+
+/datum/hallucination/oh_yeah/New(mob/living/carbon/T, forced = TRUE)
+ . = ..()
+ var/turf/closed/wall/wall
+ for(var/turf/closed/wall/W in range(7,target))
+ wall = W
+ break
+ if(!wall)
+ return INITIALIZE_HINT_QDEL
+ feedback_details += "Source: [wall.x],[wall.y],[wall.z]"
+
+ fakebroken = image('icons/turf/floors.dmi', wall, "plating", layer = TURF_LAYER)
+ var/turf/landing = get_turf(target)
+ var/turf/landing_image_turf = get_step(landing, SOUTHWEST) //the icon is 3x3
+ fakerune = image('icons/effects/96x96.dmi', landing_image_turf, "landing", layer = ABOVE_OPEN_TURF_LAYER)
+ fakebroken.override = TRUE
+ if(target.client)
+ target.client.images |= fakebroken
+ target.client.images |= fakerune
+ target.playsound_local(wall,'sound/effects/meteorimpact.ogg', 150, 1)
+ bubblegum = new(wall, target)
+ addtimer(CALLBACK(src, .proc/bubble_attack, landing), 10)
+
+/datum/hallucination/oh_yeah/proc/bubble_attack(turf/landing)
+ var/charged = FALSE //only get hit once
+ while(get_turf(bubblegum) != landing && target && target.stat != DEAD)
+ bubblegum.forceMove(get_step_towards(bubblegum, landing))
+ bubblegum.setDir(get_dir(bubblegum, landing))
+ target.playsound_local(get_turf(bubblegum), 'sound/effects/meteorimpact.ogg', 150, 1)
+ shake_camera(target, 2, 1)
+ if(bubblegum.Adjacent(target) && !charged)
+ charged = TRUE
+ target.Knockdown(80)
+ target.adjustStaminaLoss(40)
+ step_away(target, bubblegum)
+ shake_camera(target, 4, 3)
+ target.visible_message("[target] jumps backwards, falling on the ground!","[bubblegum] slams into you!")
+ sleep(2)
+ sleep(30)
+ qdel(src)
+
+/datum/hallucination/oh_yeah/Destroy()
+ if(target.client)
+ target.client.images.Remove(fakebroken)
+ target.client.images.Remove(fakerune)
+ QDEL_NULL(fakebroken)
+ QDEL_NULL(fakerune)
+ QDEL_NULL(bubblegum)
+ return ..()
+
+/datum/hallucination/singularity_scare
+ //Singularity moving towards you.
+ //todo Hide where it moved with fake space images
+ var/obj/effect/hallucination/simple/singularity/s = null
+ cost = 75
+
+/datum/hallucination/singularity_scare/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ var/turf/start = get_turf(T)
+ var/screen_border = pick(SOUTH,EAST,WEST,NORTH)
+ for(var/i in 1 to 13)
+ start = get_step(start,screen_border)
+ feedback_details += "Source: [start.x],[start.y],[start.z]"
+ s = new(start,target)
+ s.parent = src
+ for(var/i in 1 to 13)
+ sleep(10)
+ s.forceMove(get_step(get_turf(s),get_dir(s,target)))
+ s.Show()
+ s.Eat()
+ qdel(s)
+
+/obj/effect/hallucination/simple/singularity
+ image_icon = 'icons/effects/224x224.dmi'
+ image_state = "singularity_s7"
+ image_layer = MASSIVE_OBJ_LAYER
+ px = -96
+ py = -96
+ var/datum/hallucination/singularity_scare/parent
+
+/obj/effect/hallucination/simple/singularity/proc/Eat(atom/OldLoc, Dir)
+ var/target_dist = get_dist(src,target)
+ if(target_dist<=3) //"Eaten"
+ target.set_screwyhud(SCREWYHUD_DEAD)
+ target.SetUnconscious(160)
+ addtimer(CALLBACK(parent, /datum/hallucination/.proc/wake_and_restore), rand(30, 50))
+
+/datum/hallucination/battle
+ cost = 15
+
+/datum/hallucination/battle/New(mob/living/carbon/T, forced = TRUE, battle_type)
+ ..()
+ var/hits = rand(3,6)
+ if(!battle_type)
+ battle_type = pick("laser","esword","gun","stunprod","bomb")
+ feedback_details += "Type: [battle_type]"
+ switch(battle_type)
+ if("laser") //Laser fight
+ for(var/i in 1 to hits)
+ target.playsound_local(null, 'sound/weapons/laser.ogg', 25, 1)
+ if(prob(50))
+ addtimer(CALLBACK(target, /mob/.proc/playsound_local, null, 'sound/weapons/sear.ogg', 25, 1), rand(10,20))
+ else
+ addtimer(CALLBACK(target, /mob/.proc/playsound_local, null, 'sound/weapons/effects/searwall.ogg', 25, 1), rand(10,20))
+ sleep(rand(CLICK_CD_RANGE, CLICK_CD_RANGE + 8))
+ target.playsound_local(null, get_sfx("bodyfall"), 25, 1)
+ if("esword") //Esword fight
+ target.playsound_local(null, 'sound/weapons/saberon.ogg',15, 1)
+ for(var/i=0,i...wabbajack...wabbajack...")
+ target.playsound_local(target,'sound/magic/staff_change.ogg', 50, 1)
+ delusion = A
+ target.client.images |= A
+ QDEL_IN(src, duration)
+
+/datum/hallucination/self_delusion/Destroy()
+ if(target.client)
+ target.client.images.Remove(delusion)
+ return ..()
+
+/datum/hallucination/fakeattacker/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ var/mob/living/carbon/human/clone = null
+ var/clone_weapon = null
+
+ for(var/mob/living/carbon/human/H in GLOB.living_mob_list)
+ if(H.stat || H.lying)
+ continue
+ clone = H
+ feedback_details += "Clone of: [H.real_name]"
+ break
+
+ if(!clone)
+ return
+
+ var/static/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/ballistic, /obj/item/ammo_box/a357,\
+ /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow, /obj/item/weapon/melee/transforming/energy/sword/saber,\
+ /obj/item/weapon/storage/box/syndicate, /obj/item/weapon/storage/box/emps,\
+ /obj/item/weapon/cartridge/virus/syndicate, /obj/item/clothing/under/chameleon,\
+ /obj/item/clothing/shoes/chameleon, /obj/item/weapon/card/id/syndicate,\
+ /obj/item/clothing/mask/chameleon, /obj/item/clothing/glasses/thermal,\
+ /obj/item/device/chameleon, /obj/item/weapon/card/emag, /obj/item/weapon/grenade/plastic/x4,\
+ /obj/item/weapon/storage/toolbox/syndicate, /obj/item/weapon/aiModule,\
+ /obj/item/device/radio/headset/syndicate, /obj/item/weapon/grenade/plastic/c4,\
+ /obj/item/device/powersink, /obj/item/weapon/storage/box/syndie_kit,\
+ /obj/item/toy/syndicateballoon, /obj/item/weapon/gun/energy/laser/captain,\
+ /obj/item/weapon/hand_tele, /obj/item/weapon/construction/rcd, /obj/item/weapon/tank/jetpack,\
+ /obj/item/clothing/under/rank/captain, /obj/item/device/aicard,\
+ /obj/item/clothing/shoes/magboots, /obj/item/areaeditor/blueprints, /obj/item/weapon/disk/nuclear,\
+ /obj/item/clothing/suit/space/nasavoid, /obj/item/weapon/tank)
+
+ var/obj/effect/fake_attacker/F = new/obj/effect/fake_attacker(get_turf(target),target)
+
+ for(var/obj/item/I in clone.held_items)
+ if(!(locate(I) in non_fakeattack_weapons))
+ clone_weapon = I.name
+ F.weap = I
+
+ F.name = clone.name
+ F.my_target = target
+ F.weapon_name = clone_weapon
+
+ F.left = image(clone,dir = WEST)
+ F.right = image(clone,dir = EAST)
+ F.up = image(clone,dir = NORTH)
+ F.down = image(clone,dir = SOUTH)
+
+ F.updateimage()
+ qdel(src)
+
+/obj/effect/fake_attacker
+ icon = null
+ icon_state = null
+ name = ""
+ desc = ""
+ density = FALSE
+ anchored = TRUE
+ opacity = 0
+ var/mob/living/carbon/human/my_target = null
+ var/weapon_name = null
+ var/obj/item/weap = null
+ var/image/stand_icon = null
+ var/image/currentimage = null
+ var/icon/base = null
+ var/skin_tone
+ var/mob/living/clone = null
+ var/image/left
+ var/image/right
+ var/image/up
+ var/collapse
+ var/image/down
+
+ max_integrity = 100
+
+/obj/effect/fake_attacker/attackby(obj/item/weapon/P, mob/living/user, params)
+ step_away(src,my_target,2)
+ user.changeNext_move(CLICK_CD_MELEE)
+ user.do_attack_animation(src)
+ my_target.playsound_local(src, P.hitsound, 1)
+ my_target.visible_message("[my_target] flails around wildly.", \
+ "[my_target] has attacked [src]!")
+
+ obj_integrity -= P.force
+
+/obj/effect/fake_attacker/Crossed(mob/M, somenumber)
+ if(M == my_target)
+ step_away(src,my_target,2)
+ if(prob(30))
+ for(var/mob/O in oviewers(world.view , my_target))
+ to_chat(O, "[my_target] stumbles around.")
+
+/obj/effect/fake_attacker/Initialize(mapload, mob/living/carbon/T)
+ ..()
+ my_target = T
+ QDEL_IN(src, 300)
+ step_away(src,my_target,2)
+ INVOKE_ASYNC(src, .proc/attack_loop)
+
+
+/obj/effect/fake_attacker/proc/updateimage()
+// del src.currentimage
+ if(src.dir == NORTH)
+ del src.currentimage
+ src.currentimage = new /image(up,src)
+ else if(src.dir == SOUTH)
+ del src.currentimage
+ src.currentimage = new /image(down,src)
+ else if(src.dir == EAST)
+ del src.currentimage
+ src.currentimage = new /image(right,src)
+ else if(src.dir == WEST)
+ del src.currentimage
+ src.currentimage = new /image(left,src)
+ SEND_IMAGE(my_target, currentimage)
+
+
+/obj/effect/fake_attacker/proc/attack_loop()
+ while(1)
+ sleep(rand(5,10))
+ if(obj_integrity < 0 || my_target.stat)
+ collapse()
+ continue
+ if(get_dist(src,my_target) > 1)
+ src.setDir(get_dir(src,my_target))
+ step_towards(src,my_target)
+ updateimage()
+ else
+ if(prob(15))
+ if(weapon_name)
+ my_target.playsound_local(my_target, weap.hitsound, weap.get_clamped_volume(), 1)
+ my_target.show_message("[src.name] has attacked [my_target] with [weapon_name]!", 1)
+ my_target.staminaloss += 30
+ if(prob(20))
+ my_target.blur_eyes(3)
+ if(prob(33))
+ if(!locate(/obj/effect/overlay) in my_target.loc)
+ fake_blood(my_target)
+ else
+ my_target.playsound_local(my_target, pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'), 25, 1)
+ my_target.show_message("[src.name] has punched [my_target]!", 1)
+ my_target.staminaloss += 30
+ if(prob(33))
+ if(!locate(/obj/effect/overlay) in my_target.loc)
+ fake_blood(my_target)
+
+ if(prob(15))
+ step_away(src,my_target,2)
+
+/obj/effect/fake_attacker/proc/collapse()
+ collapse = 1
+ updateimage()
+ qdel(src)
+
+/obj/effect/fake_attacker/proc/fake_blood(mob/target)
+ var/obj/effect/overlay/O = new/obj/effect/overlay(target.loc)
+ O.name = "blood"
+ var/image/I = image('icons/effects/blood.dmi',O,"floor[rand(1,7)]",O.dir,1)
+ SEND_IMAGE(target, I)
+ QDEL_IN(O, 300)
+
+
+/datum/hallucination/bolts
+ var/list/doors = list()
+ cost = 25
+
+/datum/hallucination/bolts/New(mob/living/carbon/T, forced, door_number=-1) //-1 for severe, 1-2 for subtle
+ ..()
+ var/image/I = null
+ var/count = 0
+ feedback_details += "Door amount: [door_number]"
+ for(var/obj/machinery/door/airlock/A in range(7, target))
+ if(count>door_number && door_number>0)
+ break
+ count++
+ I = image(A.overlays_file, get_turf(A), "lights_bolts",layer=A.layer+0.1)
+ doors += I
+ if(target.client)
+ target.client.images |= I
+ target.playsound_local(get_turf(A), 'sound/machines/boltsdown.ogg',30,0,3)
+ sleep(rand(6,12))
+ sleep(100)
+ for(var/image/B in doors)
+ if(target.client)
+ target.client.images.Remove(B)
+ target.playsound_local(get_turf(B), 'sound/machines/boltsup.ogg',30,0,3)
+ sleep(rand(6,12))
+ qdel(src)
+
+/datum/hallucination/whispers
+ cost = 15
+
+/datum/hallucination/whispers/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ var/speak_messages = list("[pick_list_replacements(HAL_LINES_FILE, "suspicion")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "greetings")][target.first_name()]!",\
+ "[pick_list_replacements(HAL_LINES_FILE, "getout")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "weird")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "didyouhearthat")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "imatraitor")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "doubt")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "aggressive")]",\
+ "[pick_list_replacements(HAL_LINES_FILE, "help")]!!",\
+ "[pick_list_replacements(HAL_LINES_FILE, "escape")]",\
+ "I'm infected, [pick_list_replacements(HAL_LINES_FILE, "infection_advice")]!")
+
+ var/radio_messages = list("Set [target.first_name()] to arrest!",\
+ "[pick_list_replacements(HAL_LINES_FILE, "people")] is [pick_list_replacements(HAL_LINES_FILE, "accusations")]!",\
+ "Help!",\
+ "[pick_list_replacements(HAL_LINES_FILE, "threat")] in [pick_list_replacements(HAL_LINES_FILE, "location")][prob(50)?"!":"!!"]",\
+ "Where's [target.first_name()]?"\
+ ,"[pick("C","Ai, c","Someone c","Rec")]all the shuttle!"\
+ ,"AI [pick("rogue", "is dead")]!!")
+
+ var/list/mob/living/carbon/people = list()
+ var/list/mob/living/carbon/person = null
+ var/datum/language/understood_language = target.get_random_understood_language()
+ for(var/mob/living/carbon/H in view(target))
+ if(H == target)
+ continue
+ if(!person)
+ person = H
+ else
+ if(get_dist(target,H)The light burns you!", \
+ "You don't feel like yourself.", \
+ "You hear something squeezing through the ducts...", \
+ "You hear a distant scream.", \
+ "You feel invincible, nothing can hurt you!", \
+ "You feel a tiny prick!", \
+ "[target] sneezes.", \
+ //The truth, revealed
+ "You're hallucinating.", \
+ //Direct advice
+ "[pick_list_replacements(HAL_LINES_FILE, "advice")]")
+ feedback_details += "Message: [chosen]"
+ to_chat(target, chosen)
+ qdel(src)
+
+/datum/hallucination/sounds
+ cost = 15
+
+/datum/hallucination/sounds/New(mob/living/carbon/T, forced = TRUE, sound_type)
+ ..()
+ if(!sound_type)
+ sound_type = pick("airlock","explosion","far_explosion","glass","phone","summon_guns","alarm","beepsky","hallelujah","creepy","ratvar","shuttle_dock",
+ "wall_decon","door_hack","esword","blob_alert","tesla","malf_ai")
+ feedback_details += "Type: [sound_type]"
+ //Strange audio
+ switch(sound_type)
+ if("airlock")
+ target.playsound_local(null,'sound/machines/airlock.ogg', 15, 1)
+ if("explosion")
+ if(prob(50))
+ target.playsound_local(null,'sound/effects/explosion1.ogg', 50, 1)
+ else
+ target.playsound_local(null, 'sound/effects/explosion2.ogg', 50, 1)
+ if("far_explosion")
+ target.playsound_local(null, 'sound/effects/explosionfar.ogg', 50, 1)
+ if("glass")
+ target.playsound_local(null, pick('sound/effects/glassbr1.ogg','sound/effects/glassbr2.ogg','sound/effects/glassbr3.ogg'), 50, 1)
+ if("phone")
+ target.playsound_local(null, 'sound/weapons/ring.ogg', 35)
+ sleep(15)
+ target.playsound_local(null, 'sound/weapons/ring.ogg', 35)
+ sleep(15)
+ target.playsound_local(null, 'sound/weapons/ring.ogg', 35)
+ if("summon_guns")
+ target.playsound_local(null, 'sound/magic/summon_guns.ogg', 50, 1)
+ if("alarm")
+ target.playsound_local(null, 'sound/machines/alarm.ogg', 100, 0)
+ if("beepsky")
+ target.playsound_local(null, 'sound/voice/bfreeze.ogg', 35, 0)
+ if("hallelujah")
+ target.playsound_local(null, 'sound/effects/pray_chaplain.ogg', 50)
+ //Rare audio
+ if("creepy")
+ //These sounds are (mostly) taken from Hidden: Source
+ var/static/list/hallucinations_creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/heart_beat.ogg', 'sound/effects/screech.ogg',\
+ 'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\
+ 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\
+ 'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\
+ 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg')
+ target.playsound_local(null, pick(hallucinations_creepyasssounds), 50, 1)
+ if("ratvar")
+ target.playsound_local(null, 'sound/effects/ratvar_rises.ogg', 100)
+ sleep(150)
+ target.playsound_local(null, 'sound/effects/ratvar_reveal.ogg', 100)
+ if("shuttle_dock")
+ to_chat(target, "Priority Announcement
")
+ to_chat(target, "
The Emergency Shuttle has docked with the station. You have 3 minutes to board the Emergency Shuttle.
")
+ target.playsound_local(null, 'sound/ai/shuttledock.ogg', 100)
+ //Deconstructing a wall
+ if("wall_decon")
+ target.playsound_local(null, 'sound/items/welder.ogg', 15, 1)
+ sleep(105)
+ target.playsound_local(null, 'sound/items/welder2.ogg', 15, 1)
+ sleep(15)
+ target.playsound_local(null, 'sound/items/ratchet.ogg', 15, 1)
+ //Hacking a door
+ if("door_hack")
+ target.playsound_local(null, 'sound/items/screwdriver.ogg', 15, 1)
+ sleep(rand(10,30))
+ for(var/i = rand(1,3), i>0, i--)
+ target.playsound_local(null, 'sound/weapons/empty.ogg', 15, 1)
+ sleep(rand(10,30))
+ target.playsound_local(null, 'sound/machines/airlockforced.ogg', 15, 1)
+ if("esword")
+ target.playsound_local(null, 'sound/weapons/saberon.ogg',35,1)
+ if("blob_alert")
+ to_chat(target, "Biohazard Alert
")
+ to_chat(target, "
Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.
")
+ target.playsound_local(null, 'sound/ai/outbreak5.ogg', 100, 0)
+ if("tesla") //Tesla loose!
+ target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 35, 1)
+ sleep(20)
+ target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 65, 1)
+ sleep(20)
+ target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 100, 1)
+ if("malf_ai") //AI is doomsdaying!
+ to_chat(target, "Anomaly Alert
")
+ to_chat(target, "
Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.
")
+ target.playsound_local(null, 'sound/ai/aimalf.ogg', 100, 0)
+ qdel(src)
+
+/datum/hallucination/hudscrew
+ cost = 10
+
+/datum/hallucination/hudscrew/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ //Screwy HUD
+ target.set_screwyhud(pick(SCREWYHUD_CRIT,SCREWYHUD_DEAD,SCREWYHUD_HEALTHY))
+ feedback_details += "Type: [target.hal_screwyhud]"
+ sleep(rand(100,250))
+ target.set_screwyhud(SCREWYHUD_NONE)
+ qdel(src)
+
+/datum/hallucination/fake_alert
+ cost = 15
+
+/datum/hallucination/fake_alert/New(mob/living/carbon/T, forced = TRUE, specific, duration = 150)
+ ..()
+ var/alert_type = pick("not_enough_oxy","not_enough_tox","not_enough_co2","too_much_oxy","too_much_co2","too_much_tox","newlaw","nutrition","charge","weightless","fire","locked","hacked","temphot","tempcold","pressure")
+ if(specific)
+ alert_type = specific
+ feedback_details += "Type: [alert_type]"
+ switch(alert_type)
+ if("oxy")
+ target.throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy, override = TRUE)
+ if("not_enough_tox")
+ target.throw_alert("not_enough_tox", /obj/screen/alert/not_enough_tox, override = TRUE)
+ if("not_enough_co2")
+ target.throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2, override = TRUE)
+ if("too_much_oxy")
+ target.throw_alert("too_much_oxy", /obj/screen/alert/too_much_oxy, override = TRUE)
+ if("too_much_co2")
+ target.throw_alert("too_much_co2", /obj/screen/alert/too_much_co2, override = TRUE)
+ if("tox_in_air")
+ target.throw_alert("too_much_tox", /obj/screen/alert/too_much_tox, override = TRUE)
+ if("nutrition")
+ if(prob(50))
+ target.throw_alert("nutrition", /obj/screen/alert/fat, override = TRUE)
+ else
+ target.throw_alert("nutrition", /obj/screen/alert/starving, override = TRUE)
+ if("weightless")
+ target.throw_alert("weightless", /obj/screen/alert/weightless, override = TRUE)
+ if("fire")
+ target.throw_alert("fire", /obj/screen/alert/fire, override = TRUE)
+ if("temphot")
+ target.throw_alert("temp", /obj/screen/alert/hot, 3, override = TRUE)
+ if("tempcold")
+ target.throw_alert("temp", /obj/screen/alert/cold, 3, override = TRUE)
+ if("pressure")
+ if(prob(50))
+ target.throw_alert("pressure", /obj/screen/alert/highpressure, 2, override = TRUE)
+ else
+ target.throw_alert("pressure", /obj/screen/alert/lowpressure, 2, override = TRUE)
+ //BEEP BOOP I AM A ROBOT
+ if("newlaw")
+ target.throw_alert("newlaw", /obj/screen/alert/newlaw, override = TRUE)
+ if("locked")
+ target.throw_alert("locked", /obj/screen/alert/locked, override = TRUE)
+ if("hacked")
+ target.throw_alert("hacked", /obj/screen/alert/hacked, override = TRUE)
+ if("charge")
+ target.throw_alert("charge",/obj/screen/alert/emptycell, override = TRUE)
+ sleep(duration)
+ target.clear_alert(alert_type, clear_override = TRUE)
+ qdel(src)
+
+/datum/hallucination/items
+ cost = 15
+
+/datum/hallucination/items/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ //Strange items
+ if(!target.halitem)
+ target.halitem = new
+ var/obj/item/l_hand = target.get_item_for_held_index(1)
+ var/obj/item/r_hand = target.get_item_for_held_index(2)
+ var/l = ui_hand_position(target.get_held_index_of_item(l_hand))
+ var/r = ui_hand_position(target.get_held_index_of_item(r_hand))
+ var/list/slots_free = list(l,r)
+ if(l_hand) slots_free -= l
+ if(r_hand) slots_free -= r
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ if(!H.belt) slots_free += ui_belt
+ if(!H.l_store) slots_free += ui_storage1
+ if(!H.r_store) slots_free += ui_storage2
+ if(slots_free.len)
+ target.halitem.screen_loc = pick(slots_free)
+ target.halitem.layer = ABOVE_HUD_LAYER
+ target.halitem.plane = ABOVE_HUD_PLANE
+ switch(rand(1,6))
+ if(1) //revolver
+ target.halitem.icon = 'icons/obj/guns/projectile.dmi'
+ target.halitem.icon_state = "revolver"
+ target.halitem.name = "Revolver"
+ if(2) //c4
+ target.halitem.icon = 'icons/obj/grenade.dmi'
+ target.halitem.icon_state = "plastic-explosive0"
+ target.halitem.name = "C4"
+ if(prob(25))
+ target.halitem.icon_state = "plasticx40"
+ if(3) //sword
+ target.halitem.icon = 'icons/obj/weapons.dmi'
+ target.halitem.icon_state = "sword0"
+ target.halitem.name = "Energy Sword"
+ if(4) //stun baton
+ target.halitem.icon = 'icons/obj/weapons.dmi'
+ target.halitem.icon_state = "stunbaton"
+ target.halitem.name = "Stun Baton"
+ if(5) //emag
+ target.halitem.icon = 'icons/obj/card.dmi'
+ target.halitem.icon_state = "emag"
+ target.halitem.name = "Cryptographic Sequencer"
+ if(6) //flashbang
+ target.halitem.icon = 'icons/obj/grenade.dmi'
+ target.halitem.icon_state = "flashbang1"
+ target.halitem.name = "Flashbang"
+ feedback_details += "Type: [target.halitem.name]"
+ if(target.client) target.client.screen += target.halitem
+ QDEL_IN(target.halitem, rand(150, 350))
+ qdel(src)
+
+/datum/hallucination/dangerflash
+ cost = 15
+
+/datum/hallucination/dangerflash/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ //Flashes of danger
+ if(!target.halimage)
+ var/list/possible_points = list()
+ for(var/turf/open/floor/F in view(target,world.view))
+ possible_points += F
+ if(possible_points.len)
+ var/turf/open/floor/danger_point = pick(possible_points)
+
+ switch(rand(1,5))
+ if(1)
+ target.halimage = image('icons/turf/space.dmi',danger_point,"[rand(1,25)]",TURF_LAYER)
+ if(2)
+ target.halimage = image('icons/turf/floors/lava.dmi',danger_point,"smooth",TURF_LAYER)
+ if(3)
+ target.halimage = image('icons/turf/floors/Chasms.dmi',danger_point,"smooth",TURF_LAYER)
+ if(4)
+ target.halimage = image('icons/effects/effects.dmi',danger_point,"anom",OBJ_LAYER+0.01)
+ if(5)
+ target.halimage = image('icons/effects/effects.dmi',danger_point,"electricity2",OBJ_LAYER+0.01)
+
+
+ if(target.client)
+ target.client.images += target.halimage
+ sleep(rand(200,450))
+ if(target.client)
+ target.client.images -= target.halimage
+ QDEL_NULL(target.halimage)
+ qdel(src)
+
+/datum/hallucination/death
+ cost = 40
+
+/datum/hallucination/death/New(mob/living/carbon/T, forced = TRUE)
+ set waitfor = 0
+ ..()
+ target.set_screwyhud(SCREWYHUD_DEAD)
+ target.Knockdown(300)
+ target.silent += 10
+ var/area/area = get_area(target)
+ to_chat(target, "[target.mind.name] has died at [area.name].")
+ if(prob(50))
+ var/mob/fakemob
+ var/list/dead_people = list()
+ for(var/mob/dead/observer/G in GLOB.player_list)
+ dead_people += G
+ if(LAZYLEN(dead_people))
+ fakemob = pick(dead_people)
+ else
+ fakemob = target //ever been so lonely you had to haunt yourself?
+ if(fakemob)
+ sleep(rand(20, 50))
+ to_chat(target, "DEAD: [fakemob.name] says, \"[pick("rip","hey [target.first_name()]","you too?","is the AI rogue?",\
+ "i[prob(50)?" fucking":""] hate [pick("blood cult", "clock cult", "revenants", "abductors","double agents","viruses","badmins","you")]")]\"")
+ sleep(rand(70,90))
+ target.set_screwyhud(SCREWYHUD_NONE)
+ target.SetKnockdown(0)
+ target.silent = 0
+ qdel(src)
+
+/datum/hallucination/fire
+ cost = 25
+
+/datum/hallucination/fire/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ var/image/fire_overlay = image('icons/mob/OnFire.dmi', target, "Standing", ABOVE_MOB_LAYER)
+ if(target.client)
+ target.client.images += fire_overlay
+ to_chat(target, "You're set on fire!")
+ target.throw_alert("fire", /obj/screen/alert/fire, override = TRUE)
+ sleep(20)
+ target.throw_alert("temp", /obj/screen/alert/hot, 1, override = TRUE)
+ sleep(30)
+ target.clear_alert("temp", clear_override = TRUE)
+ target.throw_alert("temp", /obj/screen/alert/hot, 2, override = TRUE)
+ sleep(30)
+ target.clear_alert("temp", clear_override = TRUE)
+ target.throw_alert("temp", /obj/screen/alert/hot, 3, override = TRUE)
+ for(var/i in 1 to rand(5, 10))
+ target.adjustStaminaLoss(15)
+ sleep(25)
+ target.clear_alert("fire", clear_override = TRUE)
+ target.clear_alert("temp", clear_override = TRUE)
+ if(target.client)
+ target.client.images -= fire_overlay
+ QDEL_NULL(fire_overlay)
+ qdel(src)
+
+/datum/hallucination/husks
+ cost = 20
+
+/datum/hallucination/husks/New(mob/living/carbon/T, forced = TRUE)
+ ..()
+ if(!target.halbody)
+ var/list/possible_points = list()
+ for(var/turf/open/floor/F in view(target,world.view))
+ possible_points += F
+ if(possible_points.len)
+ var/turf/open/floor/husk_point = pick(possible_points)
+ switch(rand(1,4))
+ if(1)
+ var/image/body = image('icons/mob/human.dmi',husk_point,"husk",TURF_LAYER)
+ var/matrix/M = matrix()
+ M.Turn(90)
+ body.transform = M
+ target.halbody = body
+ if(2,3)
+ target.halbody = image('icons/mob/human.dmi',husk_point,"husk",TURF_LAYER)
+ if(4)
+ target.halbody = image('icons/mob/alien.dmi',husk_point,"alienother",TURF_LAYER)
+
+ if(target.client)
+ target.client.images += target.halbody
+ sleep(rand(30,50)) //Only seen for a brief moment.
+ if(target.client)
+ target.client.images -= target.halbody
+ QDEL_NULL(target.halbody)
+ qdel(src)
+
+//hallucination projectile code in code/modules/projectiles/projectile/special.dm
+/datum/hallucination/stray_bullet
+ cost = 15
+
+/datum/hallucination/stray_bullet/New(mob/living/carbon/C, forced = TRUE)
+ ..()
+ var/list/turf/startlocs = list()
+ for(var/turf/open/T in view(world.view+1,target)-view(world.view,target))
+ startlocs += T
+ var/turf/start = pick(startlocs)
+ var/proj_type = pick(subtypesof(/obj/item/projectile/hallucination))
+ feedback_details += "Type: [proj_type]"
+ var/obj/item/projectile/hallucination/H = new proj_type(start)
+ target.playsound_local(start, H.hal_fire_sound, 60, 1)
+ H.hal_target = target
+ H.current = start
+ H.starting = start
+ H.yo = target.y - start.y
+ H.xo = target.x - start.x
+ H.original = target
+ H.fire()
+ qdel(src)
+
diff --git a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm
index b5c02946e7..f519892dda 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm
@@ -97,7 +97,7 @@
var/obj/item/weapon/reagent_containers/food/snacks/icecream/I = O
if(!I.ice_creamed)
if(product_types[dispense_flavour] > 0)
- src.visible_message("[bicon(src)] [user] scoops delicious [flavour_name] ice cream into [I].")
+ visible_message("[icon2html(src, viewers(src))] [user] scoops delicious [flavour_name] ice cream into [I].")
product_types[dispense_flavour] -= 1
I.add_ice_cream(flavour_name)
// if(beaker)
diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm
index cde68b86e2..54c2154b42 100644
--- a/code/modules/food_and_drinks/pizzabox.dm
+++ b/code/modules/food_and_drinks/pizzabox.dm
@@ -101,7 +101,7 @@
return
open = !open
if(open && !bomb_defused)
- audible_message("[bicon(src)] *beep*")
+ audible_message("[icon2html(src, hearers(src))] *beep*")
bomb_active = TRUE
START_PROCESSING(SSobj, src)
update_icon()
diff --git a/code/modules/goonchat/browserOutput.dm b/code/modules/goonchat/browserOutput.dm
index 7b236ea56f..85770f618a 100644
--- a/code/modules/goonchat/browserOutput.dm
+++ b/code/modules/goonchat/browserOutput.dm
@@ -100,7 +100,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
sendClientData()
//do not convert to to_chat()
- owner << {"If you can see this, update byond."}
+ SEND_TEXT(owner, "If you can see this, update byond.")
pingLoop()
@@ -152,7 +152,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
if (found.len > 0)
//TODO: add a new evasion ban for the CURRENT client details, using the matched row details
message_admins("[key_name(src.owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])")
- log_admin_private("[key_name(src.owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])")
+ log_admin_private("[key_name(owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])")
cookieSent = TRUE
@@ -165,58 +165,6 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
log_world("\[[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]\] Client: [(src.owner.key ? src.owner.key : src.owner)] triggered JS error: [error]")
//Global chat procs
-
-//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, iconKey = "misc")
- if (!isicon(icon))
- return FALSE
- GLOB.iconCache[iconKey] << icon
- var/iconData = GLOB.iconCache.ExportText(iconKey)
- var/list/partial = splittext(iconData, "{")
- return replacetext(copytext(partial[2], 3, -5), "\n", "")
-
-/proc/bicon(thing)
- if (!thing)
- return
- var/static/list/bicon_cache = list()
- if (isicon(thing))
- var/icon/I = thing
- var/icon_md5 = md5(I)
- if (!bicon_cache[icon_md5]) // Doesn't exist yet, make it.
- I = icon(I) //copy it
- I.Scale(16,16) //scale it
- bicon_cache[icon_md5] = icon2base64(thing) //base64 it
- return "
"
-
- // Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with.
- var/atom/A = thing
- var/key = "[istype(A.icon, /icon) ? "\ref[A.icon]" : A.icon]:[A.icon_state]"
-
-
- if (!bicon_cache[key]) // Doesn't exist, make it.
- var/icon/I = icon(A.icon, A.icon_state, SOUTH, 1)
- I.Scale(16,16)
- if (ishuman(thing)) // Shitty workaround for a BYOND issue.
- var/icon/temp = I
- I = icon()
- I.Insert(temp, dir = SOUTH)
- bicon_cache[key] = icon2base64(I, key)
-
- return "
"
-
-//Costlier version of bicon() that uses getFlatIcon() to account for overlays, underlays, etc. Use with extreme moderation, ESPECIALLY on mobs.
-/proc/costly_bicon(thing)
- if (!thing)
- return
-
- if (isicon(thing))
- return bicon(thing)
-
- var/icon/I = getFlatIcon(thing)
- return bicon(I)
-
/proc/to_chat(target, message)
if(!target)
return
@@ -224,7 +172,6 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
//Ok so I did my best but I accept that some calls to this will be for shit like sound and images
//It stands that we PROBABLY don't want to output those to the browser output so just handle them here
if (istype(message, /image) || istype(message, /sound) || istype(target, /savefile))
- target << message
CRASH("Invalid message! [message]")
if(!istext(message))
@@ -255,7 +202,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
continue
//Send it to the old style output window.
- C << original_message
+ SEND_TEXT(C, original_message)
if(!C.chatOutput || C.chatOutput.broken) // A player who hasn't updated his skin file.
continue
diff --git a/code/modules/goonchat/browserOutput.dm.rej b/code/modules/goonchat/browserOutput.dm.rej
new file mode 100644
index 0000000000..231def1c9a
--- /dev/null
+++ b/code/modules/goonchat/browserOutput.dm.rej
@@ -0,0 +1,137 @@
+diff a/code/modules/goonchat/browserOutput.dm b/code/modules/goonchat/browserOutput.dm (rejected hunks)
+@@ -166,135 +166,6 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
+
+ //Global chat procs
+
+-//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, iconKey = "misc")
+- if (!isicon(icon))
+- return FALSE
+- WRITE_FILE(GLOB.iconCache[iconKey], icon)
+- var/iconData = GLOB.iconCache.ExportText(iconKey)
+- var/list/partial = splittext(iconData, "{")
+- return replacetext(copytext(partial[2], 3, -5), "\n", "")
+-
+-/proc/icon2html(thing, target, icon_state, dir, frame = 1, moving)
+- if (!thing)
+- return
+- var/static/datum/callback/CB = CALLBACK(GLOBAL_PROC, .proc/send_asset)
+-
+- var/key
+- var/icon/I = thing
+- if (!target)
+- return
+- if (target == world)
+- target = GLOB.clients
+-
+- var/list/targets
+- if (!islist(target))
+- targets = list(target)
+- else
+- targets = target
+- if (!targets.len)
+- return
+- debug_usr("start")
+- if (!isicon(I))
+- debug_usr("not icon")
+- if (isfile(thing)) //special snowflake
+- debug_usr("file")
+- var/name = sanitize_filename("bicon.[thing]")
+- debug_usr("file:[name]")
+- register_asset(name, thing)
+- var/list/callbacks
+- var/list/callback_args = list()
+- for (var/thing2 in targets)
+- callbacks += CB
+- callback_args[++callback_args.len] = list(thing2, name, TRUE)
+- callback_select(callbacks, callback_args, savereturns = FALSE)
+- return "
"
+- debug_usr("not file")
+- var/atom/A
+- if (isnull(dir))
+- dir = A.dir
+- if (isnull(icon_state))
+- icon_state = A.icon_state
+- I = A.icon
+- if (ishuman(thing)) // Shitty workaround for a BYOND issue.
+- debug_usr("human")
+- var/icon/temp = I
+- I = icon()
+- I.Insert(temp, dir = SOUTH)
+- dir = SOUTH
+- else
+- debug_usr("icon")
+- if (isnull(dir))
+- dir = SOUTH
+- if (isnull(icon_state))
+- icon_state = ""
+-
+- I = icon(I, icon_state, dir, frame)
+-
+- key = sanitize_filename("bicon.[md5(icon2base64(I))].[icon_state].[dir].png")
+- debug_usr("key:[key]")
+- register_asset(key, I)
+- var/list/callbacks = list()
+- var/list/callback_args = list()
+- for (var/thing2 in targets)
+- callbacks += CB
+- callback_args[++callback_args.len] = list(thing2, key, TRUE)
+-
+- callback_select(callbacks, callback_args, savereturns = FALSE)
+- return "
"
+-
+-/proc/icon2base64html(thing)
+- if (!thing)
+- return
+- var/static/list/bicon_cache = list()
+- if (isicon(thing))
+- var/icon/I = thing
+- var/icon_base64 = icon2base64(I)
+-
+- if (I.Height() > world.icon_size || I.Width() > world.icon_size)
+- var/icon_md5 = md5(icon_base64)
+- debug_admins(icon_md5)
+- icon_base64 = bicon_cache[icon_md5]
+- if (!icon_base64) // Doesn't exist yet, make it.
+- I = icon(I)
+- I.Scale(world.icon_size, world.icon_size)
+- bicon_cache[icon_md5] = icon_base64 = icon2base64(I)
+-
+-
+- return "
"
+-
+- // Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with.
+- var/atom/A = thing
+- var/key = "[istype(A.icon, /icon) ? "\ref[A.icon]" : A.icon]:[A.icon_state]"
+-
+-
+- if (!bicon_cache[key]) // Doesn't exist, make it.
+- var/icon/I = icon(A.icon, A.icon_state, SOUTH, 1)
+- if (ishuman(thing)) // Shitty workaround for a BYOND issue.
+- var/icon/temp = I
+- I = icon()
+- I.Insert(temp, dir = SOUTH)
+-
+- if (I.Height() > world.icon_size || I.Width() > world.icon_size)
+- I.Scale(world.icon_size, world.icon_size)
+-
+- bicon_cache[key] = icon2base64(I, key)
+-
+- 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)
+- if (!thing)
+- return
+-
+- if (isicon(thing))
+- return icon2html(thing, target)
+-
+- var/icon/I = getFlatIcon(thing)
+- return icon2html(I, target)
+-
+ /proc/to_chat(target, message)
+ if(!target)
+ return
diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css
index ea4c169f0e..7c42972a10 100644
--- a/code/modules/goonchat/browserassets/css/browserOutput.css
+++ b/code/modules/goonchat/browserassets/css/browserOutput.css
@@ -28,10 +28,14 @@ img {
margin: 0;
padding: 0;
line-height: 1;
+ -ms-interpolation-mode: nearest-neighbor;
+ image-rendering: pixelated;
}
img.icon {
- width: 16px;
- height: 16px;
+ height: 1em;
+ min-height: 16px;
+ width: auto;
+ vertical-align: bottom;
}
a {color: #0000ff;}
@@ -357,7 +361,6 @@ h1.alert, h2.alert {color: #000000;}
.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
-BIG IMG.icon {width: 32px; height: 32px;}
.memo {color: #638500; text-align: center;}
.memoedit {text-align: center; font-size: 16px;}
diff --git a/code/modules/goonchat/browserassets/js/browserOutput.js b/code/modules/goonchat/browserassets/js/browserOutput.js
index 59b152ab3b..e6e0c1d6fa 100644
--- a/code/modules/goonchat/browserassets/js/browserOutput.js
+++ b/code/modules/goonchat/browserassets/js/browserOutput.js
@@ -29,6 +29,8 @@ var opts = {
'messageLimit': 2053, //A limit...for the messages...
'scrollSnapTolerance': 10, //If within x pixels of bottom
'clickTolerance': 10, //Keep focus if outside x pixels of mousedown position on mouseup
+ 'imageRetryDelay': 50, //how long between attempts to reload images (in ms)
+ 'imageRetryLimit': 50, //how many attempts should we make?
'popups': 0, //Amount of popups opened ever
'wasd': false, //Is the user in wasd mode?
'chatMode': 'default', //The mode the chat is in
@@ -146,6 +148,23 @@ function highlightTerms(el) {
el.innerHTML = newText;
}
}
+
+function iconError(E) {
+ var that = this;
+ setTimeout(function() {
+ var attempts = $(that).data('reload_attempts');
+ if (typeof attempts === 'undefined' || !attempts) {
+ attempts = 1;
+ }
+ if (attempts > opts.imageRetryLimit)
+ return;
+ var src = that.src;
+ that.src = null;
+ that.src = src+'#'+attempts;
+ $(that).data('reload_attempts', ++attempts);
+ }, opts.imageRetryDelay);
+}
+
//Send a message to the client
function output(message, flag) {
if (typeof message === 'undefined') {
@@ -271,7 +290,7 @@ function output(message, flag) {
entry.innerHTML = message.trim();
$messages[0].appendChild(entry);
-
+ $(entry).find("img.icon").error(iconError);
//Actually do the snap
if (!filteredOut && atBottom) {
$('body,html').scrollTop($messages.outerHeight());
@@ -861,7 +880,11 @@ $(function() {
$messages.empty();
opts.messageCount = 0;
});
-
+
+ $('img.icon').error(iconError);
+
+
+
/*****************************************
*
diff --git a/code/modules/goonchat/jsErrorHandler.dm b/code/modules/goonchat/jsErrorHandler.dm
index 67ea5faca3..ce257ce660 100644
--- a/code/modules/goonchat/jsErrorHandler.dm
+++ b/code/modules/goonchat/jsErrorHandler.dm
@@ -32,7 +32,7 @@
CRASH("Debug Error Handling encountered an error! This is highly ironic! File: '[fileName]' has exceeded the filesize limit of: [src.logFileLimit] bytes")
message = "\[[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]\] Client: \[[C && C.key ? C.key : "Unknown Client"]\] triggered: [message]"
- logFile << message
+ WRITE_FILE(logFile, message)
return 1
/datum/debugFileOutput/proc/clear(fileName)
diff --git a/code/modules/hydroponics/grown/chili.dm b/code/modules/hydroponics/grown/chili.dm
index 7707a4d438..66bd823a89 100644
--- a/code/modules/hydroponics/grown/chili.dm
+++ b/code/modules/hydroponics/grown/chili.dm
@@ -71,21 +71,21 @@
name = "ghost chili"
desc = "It seems to be vibrating gently."
icon_state = "ghostchilipepper"
- var/mob/held_mob
+ var/mob/living/carbon/human/held_mob
filling_color = "#F8F8FF"
bitesize_mod = 4
origin_tech = "biotech=4;magnets=5"
/obj/item/weapon/reagent_containers/food/snacks/grown/ghost_chili/attack_hand(mob/user)
..()
- if( ismob(src.loc) )
- held_mob = src.loc
+ if( ismob(loc) )
+ held_mob = loc
START_PROCESSING(SSobj, src)
/obj/item/weapon/reagent_containers/food/snacks/grown/ghost_chili/process()
- if(held_mob && src.loc == held_mob)
+ if(held_mob && loc == held_mob)
if(held_mob.is_holding(src))
- if(hasvar(held_mob,"gloves") && held_mob:gloves)
+ if(istype(held_mob) && held_mob.gloves)
return
held_mob.bodytemperature += 15 * TEMPERATURE_DAMAGE_COEFFICIENT
if(prob(10))
diff --git a/code/modules/language/language.dm b/code/modules/language/language.dm
index 2ad7f0549c..8b51429bd3 100644
--- a/code/modules/language/language.dm
+++ b/code/modules/language/language.dm
@@ -35,7 +35,7 @@
return TRUE
/datum/language/proc/get_icon()
- return "[bicon(icon(icon, icon_state))]"
+ return "[icon2html(icon, world, icon_state)]"
/datum/language/proc/get_random_name(gender, name_count=2, syllable_count=4, syllable_divisor=2)
if(!syllables || !syllables.len)
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index a1251381b4..06845ba0cb 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -284,7 +284,7 @@
L.adjustBruteLoss(bonus_value)
/obj/item/crusher_trophy/tail_spike/proc/pushback(mob/living/target, mob/living/user)
- if(!target.anchored || ismegafauna(target)) //megafauna will always be pushed
+ if(!QDELETED(target) && !QDELETED(user) && (!target.anchored || ismegafauna(target))) //megafauna will always be pushed
step(target, get_dir(user, target))
//bubblegum
diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm
index 25aa9fb8e8..8029cc1416 100644
--- a/code/modules/mining/minebot.dm
+++ b/code/modules/mining/minebot.dm
@@ -170,6 +170,7 @@
/datum/action/innate/minedrone
check_flags = AB_CHECK_CONSCIOUS
+ icon_icon = 'icons/mob/actions/actions_mecha.dmi'
background_icon_state = "bg_default"
/datum/action/innate/minedrone/toggle_light
diff --git a/code/modules/mob/dead/new_player/sprite_accessories_Citadel.dm b/code/modules/mob/dead/new_player/sprite_accessories_Citadel.dm
index 9808923e33..0b21852a8e 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories_Citadel.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories_Citadel.dm
@@ -464,7 +464,6 @@
/datum/sprite_accessory/mam_tails/rabbit
name = "Rabbit"
icon_state = "rabbit"
- color_src = 0
icon = 'icons/mob/mam_bodyparts.dmi'
/datum/sprite_accessory/mam_ears/rabbit
@@ -595,6 +594,13 @@
extra2 = 1
icon = 'icons/mob/mam_body_markings.dmi'
+ /datum/sprite_accessory/mam_body_markings/xeno
+ name = "Xeno"
+ icon_state = "xeno"
+ color_src = MUTCOLORS2
+ extra_color_src = MUTCOLORS3
+ gender_specific = 1
+
/******************************************
************ Taur Bodies ******************
*******************************************/
@@ -673,49 +679,67 @@
//Xeno Dorsal Tubes
/datum/sprite_accessory/xeno_dorsal
- icon = 'icons/mob/exotic_bodyparts.dmi'
- color_src = 0
+ icon = 'icons/mob/xeno_parts_greyscale.dmi'
/datum/sprite_accessory/xeno_dorsal/none
name = "None"
-/datum/sprite_accessory/xeno_dorsal/normal
- name = "Dorsal Tubes"
- icon_state = "dortubes"
+/datum/sprite_accessory/xeno_dorsal/standard
+ name = "Standard"
+ icon_state = "standard"
+ icon = 'icons/mob/xeno_parts_greyscale.dmi'
+
+/datum/sprite_accessory/xeno_dorsal/royal
+ name = "Royal"
+ icon_state = "royal"
+ icon = 'icons/mob/xeno_parts_greyscale.dmi'
+
+/datum/sprite_accessory/xeno_dorsal/down
+ name = "Dorsal Down"
+ icon_state = "down"
+ icon = 'icons/mob/xeno_parts_greyscale.dmi'
//Xeno Tail
/datum/sprite_accessory/xeno_tail
- icon = 'icons/mob/exotic_bodyparts.dmi'
- color_src = 0
+ icon = 'icons/mob/xeno_parts_greyscale.dmi'
/datum/sprite_accessory/xeno_tail/none
name = "None"
-/datum/sprite_accessory/xeno_tail/normal
+/datum/sprite_accessory/xeno_tail/standard
name = "Xenomorph Tail"
icon_state = "xeno"
+ icon = 'icons/mob/xeno_parts_greyscale.dmi'
//Xeno Caste Heads
//unused as of October 3, 2016
/datum/sprite_accessory/xeno_head
- icon = 'icons/mob/exotic_bodyparts.dmi'
- color_src = 0
+ icon = 'icons/mob/xeno_parts_greyscale.dmi'
/datum/sprite_accessory/xeno_head/none
name = "None"
+/datum/sprite_accessory/xeno_head/standard
+ name = "Standard"
+ icon_state = "standard"
+ icon = 'icons/mob/xeno_parts_greyscale.dmi'
-/datum/sprite_accessory/xeno_head/hunter
- name = "Hunter"
- icon_state = "hunter"
-/datum/sprite_accessory/xeno_head/drone
- name = "Drone"
- icon_state = "drone"
+/datum/sprite_accessory/xeno_head/royal
+ name = "royal"
+ icon_state = "royal"
+ icon = 'icons/mob/xeno_parts_greyscale.dmi'
+
+/datum/sprite_accessory/xeno_head/hollywood
+ name = "hollywood"
+ icon_state = "hollywood"
+ icon = 'icons/mob/xeno_parts_greyscale.dmi'
+
+/datum/sprite_accessory/xeno_head/warrior
+ name = "warrior"
+ icon_state = "warrior"
+ icon = 'icons/mob/xeno_parts_greyscale.dmi'
-/datum/sprite_accessory/xeno_head/sentinel
- name = "Sentinel"
- icon_state = "sentinel"
/*
//Slimecoon Parts
/datum/sprite_accessory/slimecoon_ears
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 2ede4c360e..da769c23cb 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -351,7 +351,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
source.plane = old_plane
to_chat(src, "(Click to re-enter)")
if(sound)
- src << sound(sound)
+ SEND_SOUND(src, sound(sound))
/mob/dead/observer/proc/dead_tele()
set category = "Ghost"
diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
index 86ea3d64e9..01626c5694 100644
--- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
+++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm
@@ -87,7 +87,7 @@
var/atom/xeno_loc = get_turf(owner)
var/mob/living/carbon/alien/larva/new_xeno = new(xeno_loc)
new_xeno.key = ghost.key
- new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100) //To get the player's attention
+ SEND_SOUND(new_xeno, sound('sound/voice/hiss5.ogg',0,0,0,100)) //To get the player's attention
new_xeno.canmove = 0 //so we don't move during the bursting animation
new_xeno.notransform = 1
new_xeno.invisibility = INVISIBILITY_MAXIMUM
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 91a178ca36..feef638fdc 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -51,9 +51,10 @@
var/obj/item/item_in_hand = src.get_active_held_item()
if(item_in_hand) //this segment checks if the item in your hand is twohanded.
- if(istype(item_in_hand, /obj/item/weapon/twohanded))
- if(item_in_hand:wielded == 1)
- to_chat(usr, "Your other hand is too busy holding the [item_in_hand.name]")
+ var/obj/item/weapon/twohanded/TH = item_in_hand
+ if(istype(TH))
+ if(TH.wielded == 1)
+ to_chat(usr, "Your other hand is too busy holding [TH]")
return
var/oindex = active_hand_index
active_hand_index = held_index
@@ -170,6 +171,7 @@
if(thrown_thing)
visible_message("[src] has thrown [thrown_thing].")
+ add_logs(src, thrown_thing, "has thrown")
newtonian_move(get_dir(target, src))
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src)
@@ -240,6 +242,12 @@
/mob/living/carbon/is_muzzled()
return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle))
+/mob/living/carbon/hallucinating()
+ if(hallucination)
+ return TRUE
+ else
+ return FALSE
+
/mob/living/carbon/resist_buckle()
if(restrained())
changeNext_move(CLICK_CD_BREAKOUT)
@@ -812,3 +820,4 @@
.["Make AI"] = "?_src_=vars;makeai=\ref[src]"
.["Modify bodypart"] = "?_src_=vars;editbodypart=\ref[src]"
.["Modify organs"] = "?_src_=vars;editorgans=\ref[src]"
+ .["Hallucinate"] = "?_src_=vars;hallucinate=\ref[src]"
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 8bf10c39ba..dcc2655e9a 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -337,7 +337,7 @@
// you need earmuffs, inacusiate, or replacement
else if(ears.ear_damage >= 5)
to_chat(src, "Your ears start to ring!")
- src << sound('sound/weapons/flash_ring.ogg',0,1,0,250)
+ SEND_SOUND(src, sound('sound/weapons/flash_ring.ogg',0,1,0,250))
return effect_amount //how soundbanged we are
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index ebc349cefc..e30556db30 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -6,26 +6,26 @@
var/t_has = p_have()
var/t_is = p_are()
- var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n"
+ var/msg = "*---------*\nThis is [icon2html(src, user)] \a [src]!\n"
if (handcuffed)
- msg += "[t_He] [t_is] [bicon(handcuffed)] handcuffed!\n"
+ msg += "[t_He] [t_is] [icon2html(handcuffed, user)] handcuffed!\n"
if (head)
- msg += "[t_He] [t_is] wearing [bicon(head)] \a [src.head] on [t_his] head. \n"
+ msg += "[t_He] [t_is] wearing [icon2html(head, user)] \a [src.head] on [t_his] head. \n"
if (wear_mask)
- msg += "[t_He] [t_is] wearing [bicon(wear_mask)] \a [src.wear_mask] on [t_his] face.\n"
+ msg += "[t_He] [t_is] wearing [icon2html(wear_mask, user)] \a [src.wear_mask] on [t_his] face.\n"
if (wear_neck)
- msg += "[t_He] [t_is] wearing [bicon(wear_neck)] \a [src.wear_neck] around [t_his] neck.\n"
+ msg += "[t_He] [t_is] wearing [icon2html(wear_neck, user)] \a [src.wear_neck] around [t_his] neck.\n"
for(var/obj/item/I in held_items)
if(!(I.flags & ABSTRACT))
if(I.blood_DNA)
- msg += "[t_He] [t_is] holding [bicon(I)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in [t_his] [get_held_index_name(get_held_index_of_item(I))]!\n"
+ msg += "[t_He] [t_is] holding [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in [t_his] [get_held_index_name(get_held_index_of_item(I))]!\n"
else
- msg += "[t_He] [t_is] holding [bicon(I)] \a [I] in [t_his] [get_held_index_name(get_held_index_of_item(I))].\n"
+ msg += "[t_He] [t_is] holding [icon2html(I, user)] \a [I] in [t_his] [get_held_index_name(get_held_index_of_item(I))].\n"
if (back)
- msg += "[t_He] [t_has] [bicon(back)] \a [src.back] on [t_his] back.\n"
+ msg += "[t_He] [t_has] [icon2html(back, user)] \a [src.back] on [t_his] back.\n"
var/appears_dead = 0
if (stat == DEAD)
appears_dead = 1
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 94732a349d..c2bec849e2 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -19,55 +19,55 @@
if(istype(w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = w_uniform
if(U.attached_accessory)
- accessory_msg += " with [bicon(U.attached_accessory)] \a [U.attached_accessory]"
+ accessory_msg += " with [icon2html(U.attached_accessory, user)] \a [U.attached_accessory]"
if(w_uniform.blood_DNA)
- msg += "[t_He] [t_is] wearing \icon[w_uniform] [w_uniform.gender==PLURAL?"some":"a"] blood-stained [w_uniform.name][accessory_msg]!\n"
+ msg += "[t_He] [t_is] wearing [icon2html(w_uniform, user)] [w_uniform.gender==PLURAL?"some":"a"] blood-stained [w_uniform.name][accessory_msg]!\n"
else
- msg += "[t_He] [t_is] wearing [bicon(w_uniform)] \a [w_uniform][accessory_msg].\n"
+ msg += "[t_He] [t_is] wearing [icon2html(w_uniform, user)] \a [w_uniform][accessory_msg].\n"
//head
if(head)
if(head.blood_DNA)
- msg += "[t_He] [t_is] wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] blood-stained [head.name] on [t_his] head!\n"
+ msg += "[t_He] [t_is] wearing [icon2html(head, user)] [head.gender==PLURAL?"some":"a"] blood-stained [head.name] on [t_his] head!\n"
else
- msg += "[t_He] [t_is] wearing [bicon(head)] \a [head] on [t_his] head.\n"
+ msg += "[t_He] [t_is] wearing [icon2html(head, user)] \a [head] on [t_his] head.\n"
//suit/armor
if(wear_suit)
if(wear_suit.blood_DNA)
- msg += "[t_He] [t_is] wearing [bicon(wear_suit)] [wear_suit.gender==PLURAL?"some":"a"] blood-stained [wear_suit.name]!\n"
+ msg += "[t_He] [t_is] wearing [icon2html(wear_suit, user)] [wear_suit.gender==PLURAL?"some":"a"] blood-stained [wear_suit.name]!\n"
else
- msg += "[t_He] [t_is] wearing [bicon(wear_suit)] \a [wear_suit].\n"
+ msg += "[t_He] [t_is] wearing [icon2html(wear_suit, user)] \a [wear_suit].\n"
//suit/armor storage
if(s_store)
if(s_store.blood_DNA)
- msg += "[t_He] [t_is] carrying [bicon(s_store)] [s_store.gender==PLURAL?"some":"a"] blood-stained [s_store.name] on [t_his] [wear_suit.name]!\n"
+ msg += "[t_He] [t_is] carrying [icon2html(s_store, user)] [s_store.gender==PLURAL?"some":"a"] blood-stained [s_store.name] on [t_his] [wear_suit.name]!\n"
else
- msg += "[t_He] [t_is] carrying [bicon(s_store)] \a [s_store] on [t_his] [wear_suit.name].\n"
+ msg += "[t_He] [t_is] carrying [icon2html(s_store, user)] \a [s_store] on [t_his] [wear_suit.name].\n"
//back
if(back)
if(back.blood_DNA)
- msg += "[t_He] [t_has] [bicon(back)] [back.gender==PLURAL?"some":"a"] blood-stained [back] on [t_his] back.\n"
+ msg += "[t_He] [t_has] [icon2html(back, user)] [back.gender==PLURAL?"some":"a"] blood-stained [back] on [t_his] back.\n"
else
- msg += "[t_He] [t_has] [bicon(back)] \a [back] on [t_his] back.\n"
+ msg += "[t_He] [t_has] [icon2html(back, user)] \a [back] on [t_his] back.\n"
//Hands
for(var/obj/item/I in held_items)
if(!(I.flags & ABSTRACT))
if(I.blood_DNA)
- msg += "[t_He] [t_is] holding [bicon(I)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in [t_his] [get_held_index_name(get_held_index_of_item(I))]!\n"
+ msg += "[t_He] [t_is] holding [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in [t_his] [get_held_index_name(get_held_index_of_item(I))]!\n"
else
- msg += "[t_He] [t_is] holding [bicon(I)] \a [I] in [t_his] [get_held_index_name(get_held_index_of_item(I))].\n"
+ msg += "[t_He] [t_is] holding [icon2html(I, user)] \a [I] in [t_his] [get_held_index_name(get_held_index_of_item(I))].\n"
//gloves
if(gloves && !(slot_gloves in obscured))
if(gloves.blood_DNA)
- msg += "[t_He] [t_has] [bicon(gloves)] [gloves.gender==PLURAL?"some":"a"] blood-stained [gloves.name] on [t_his] hands!\n"
+ msg += "[t_He] [t_has] [icon2html(gloves, user)] [gloves.gender==PLURAL?"some":"a"] blood-stained [gloves.name] on [t_his] hands!\n"
else
- msg += "[t_He] [t_has] [bicon(gloves)] \a [gloves] on [t_his] hands.\n"
+ msg += "[t_He] [t_has] [icon2html(gloves, user)] \a [gloves] on [t_his] hands.\n"
else if(blood_DNA)
var/hand_number = get_num_arms()
if(hand_number)
@@ -78,48 +78,48 @@
//handcuffed?
if(handcuffed)
if(istype(handcuffed, /obj/item/weapon/restraints/handcuffs/cable))
- msg += "[t_He] [t_is] [bicon(handcuffed)] restrained with cable!\n"
+ msg += "[t_He] [t_is] [icon2html(handcuffed, user)] restrained with cable!\n"
else
- msg += "[t_He] [t_is] [bicon(handcuffed)] handcuffed!\n"
+ msg += "[t_He] [t_is] [icon2html(handcuffed, user)] handcuffed!\n"
//belt
if(belt)
if(belt.blood_DNA)
- msg += "[t_He] [t_has] [bicon(belt)] [belt.gender==PLURAL?"some":"a"] blood-stained [belt.name] about [t_his] waist!\n"
+ msg += "[t_He] [t_has] [icon2html(belt, user)] [belt.gender==PLURAL?"some":"a"] blood-stained [belt.name] about [t_his] waist!\n"
else
- msg += "[t_He] [t_has] [bicon(belt)] \a [belt] about [t_his] waist.\n"
+ msg += "[t_He] [t_has] [icon2html(belt, user)] \a [belt] about [t_his] waist.\n"
//shoes
if(shoes && !(slot_shoes in obscured))
if(shoes.blood_DNA)
- msg += "[t_He] [t_is] wearing [bicon(shoes)] [shoes.gender==PLURAL?"some":"a"] blood-stained [shoes.name] on [t_his] feet!\n"
+ msg += "[t_He] [t_is] wearing [icon2html(shoes, user)] [shoes.gender==PLURAL?"some":"a"] blood-stained [shoes.name] on [t_his] feet!\n"
else
- msg += "[t_He] [t_is] wearing [bicon(shoes)] \a [shoes] on [t_his] feet.\n"
+ msg += "[t_He] [t_is] wearing [icon2html(shoes, user)] \a [shoes] on [t_his] feet.\n"
//mask
if(wear_mask && !(slot_wear_mask in obscured))
if(wear_mask.blood_DNA)
- msg += "[t_He] [t_has] [bicon(wear_mask)] [wear_mask.gender==PLURAL?"some":"a"] blood-stained [wear_mask.name] on [t_his] face!\n"
+ msg += "[t_He] [t_has] [icon2html(wear_mask, user)] [wear_mask.gender==PLURAL?"some":"a"] blood-stained [wear_mask.name] on [t_his] face!\n"
else
- msg += "[t_He] [t_has] [bicon(wear_mask)] \a [wear_mask] on [t_his] face.\n"
+ msg += "[t_He] [t_has] [icon2html(wear_mask, user)] \a [wear_mask] on [t_his] face.\n"
if (wear_neck && !(slot_neck in obscured))
- msg += "[t_He] [t_is] wearing [bicon(wear_neck)] \a [src.wear_neck] around [t_his] neck.\n"
+ msg += "[t_He] [t_is] wearing [icon2html(wear_neck, user)] \a [src.wear_neck] around [t_his] neck.\n"
//eyes
if(glasses && !(slot_glasses in obscured))
if(glasses.blood_DNA)
- msg += "[t_He] [t_has] [bicon(glasses)] [glasses.gender==PLURAL?"some":"a"] blood-stained [glasses] covering [t_his] eyes!\n"
+ msg += "[t_He] [t_has] [icon2html(glasses, user)] [glasses.gender==PLURAL?"some":"a"] blood-stained [glasses] covering [t_his] eyes!\n"
else
- msg += "[t_He] [t_has] [bicon(glasses)] \a [glasses] covering [t_his] eyes.\n"
+ msg += "[t_He] [t_has] [icon2html(glasses, user)] \a [glasses] covering [t_his] eyes.\n"
//ears
if(ears && !(slot_ears in obscured))
- msg += "[t_He] [t_has] [bicon(ears)] \a [ears] on [t_his] ears.\n"
+ msg += "[t_He] [t_has] [icon2html(ears, user)] \a [ears] on [t_his] ears.\n"
//ID
if(wear_id)
- msg += "[t_He] [t_is] wearing [bicon(wear_id)] \a [wear_id].\n"
+ msg += "[t_He] [t_is] wearing [icon2html(wear_id, user)] \a [wear_id].\n"
//Jitters
switch(jitteriness)
@@ -164,7 +164,7 @@
var/obj/item/bodypart/BP = X
missing -= BP.body_zone
for(var/obj/item/I in BP.embedded_objects)
- msg += "[t_He] [t_has] \a [bicon(I)] [I] embedded in [t_his] [BP.name]!\n"
+ msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!\n"
//stores missing limbs
var/l_limbs_missing = 0
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index 69b581995b..3dacc2f444 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -143,7 +143,7 @@
var/protection = (prot["head"] + prot["arms"] + prot["feet"] + prot["legs"] + prot["groin"] + prot["chest"] + prot["hands"])/7
return protection
-/mob/living/carbon/human/can_use_guns(var/obj/item/weapon/gun/G)
+/mob/living/carbon/human/can_use_guns(var/obj/item/weapon/G)
. = ..()
if(G.trigger_guard == TRIGGER_GUARD_NORMAL)
diff --git a/code/modules/mob/living/carbon/human/interactive.dm b/code/modules/mob/living/carbon/human/interactive.dm
index e439f8ef9e..2ed81b9f88 100644
--- a/code/modules/mob/living/carbon/human/interactive.dm
+++ b/code/modules/mob/living/carbon/human/interactive.dm
@@ -97,7 +97,7 @@
if(voice_saved)
return
var/savefile/S = new /savefile("data/npc_saves/snpc.sav")
- S["knownStrings"] << knownStrings
+ WRITE_FILE(S["knownStrings"], knownStrings)
//botPool funcs
/mob/living/carbon/human/interactive/proc/takeDelegate(mob/living/carbon/human/interactive/from,doReset=TRUE)
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index d9f1acf879..da99954f29 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -63,6 +63,7 @@
return list(
head,
wear_mask,
+ wear_neck,
glasses,
ears,
)
@@ -171,7 +172,7 @@
dropItemToGround(belt)
w_uniform = null
update_suit_sensors()
- if(!QDELETED(src))
+ if(!QDELETED(src))
update_inv_w_uniform()
else if(I == gloves)
gloves = null
diff --git a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
index d612a4f061..32d6a89494 100644
--- a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
@@ -79,6 +79,28 @@ datum/species/mammal
return TRUE
//HERBIVOROUS//
+//Alien//
+/datum/species/xeno
+ // A cloning mistake, crossing human and xenomorph DNA
+ name = "xeno"
+ id = "xeno"
+ say_mod = "hisses"
+ default_color = "00FF00"
+ species_traits = list(MUTCOLORS,LIPS,DIGITIGRADE,PIERCEIMMUNE)
+ mutant_bodyparts = list("xenotail", "xenohead", "xenodorsal", "taur","mam_body_markings")
+ default_features = list("xenotail"="xeno","xenohead"="standard","xenodorsal"="standard","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None","mam_body_markings" = "xeno")
+ heatmod = 1.3
+ attack_verb = "slash"
+ attack_sound = 'sound/weapons/slash.ogg'
+ miss_sound = 'sound/weapons/slashmiss.ogg'
+ meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno
+ skinned_type = /obj/item/stack/sheet/animalhide/xeno
+ exotic_bloodtype = "L"
+ damage_overlay_type = "xeno"
+ roundstart = 1
+
+//Praise the Omnissiah, A challange worthy of my skills - HS
+
//EXOTIC//
//These races will likely include lots of downsides and upsides. Keep them relatively balanced.//
/*
@@ -217,4 +239,4 @@ datum/species/guilmon
attack_verb = "claw"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
- roundstart = 1
\ No newline at end of file
+ roundstart = 1
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 72c65ae471..c52d9862ad 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -378,8 +378,7 @@
adjust_drugginess(-1)
if(hallucination)
- spawn handle_hallucinations()
- hallucination = max(hallucination-2,0)
+ handle_hallucinations()
//used in human and monkey handle_environment()
/mob/living/carbon/proc/natural_bodytemperature_stabilization()
diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm
index f57a48b5c6..9ed0a74d31 100644
--- a/code/modules/mob/living/carbon/monkey/monkey.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey.dm
@@ -140,7 +140,7 @@
return 0
return 1
-/mob/living/carbon/monkey/can_use_guns(var/obj/item/weapon/gun/G)
+/mob/living/carbon/monkey/can_use_guns(var/obj/item/weapon/G)
return 1
/mob/living/carbon/monkey/angry
diff --git a/code/modules/mob/living/carbon/monkey/punpun.dm b/code/modules/mob/living/carbon/monkey/punpun.dm
index 901f2ceabc..b56028634f 100644
--- a/code/modules/mob/living/carbon/monkey/punpun.dm
+++ b/code/modules/mob/living/carbon/monkey/punpun.dm
@@ -51,23 +51,23 @@
/mob/living/carbon/monkey/punpun/proc/Write_Memory(dead, gibbed)
var/savefile/S = new /savefile("data/npc_saves/Punpun.sav")
if(gibbed)
- S["ancestor_name"] << null
- S["ancestor_chain"] << 1
- S["relic_hat"] << null
- S["relic_mask"] << null
+ WRITE_FILE(S["ancestor_name"], null)
+ WRITE_FILE(S["ancestor_chain"], 1)
+ WRITE_FILE(S["relic_hat"], null)
+ WRITE_FILE(S["relic_mask"], null)
return
if(dead)
- S["ancestor_name"] << ancestor_name
- S["ancestor_chain"] << ancestor_chain + 1
+ WRITE_FILE(S["ancestor_name"], ancestor_name)
+ WRITE_FILE(S["ancestor_chain"], ancestor_chain + 1)
if(!ancestor_name) //new monkey name this round
- S["ancestor_name"] << name
+ WRITE_FILE(S["ancestor_name"], name)
if(head)
- S["relic_hat"] << head.type
+ WRITE_FILE(S["relic_hat"], head.type)
else
- S["relic_hat"] << null
+ WRITE_FILE(S["relic_hat"], null)
if(wear_mask)
- S["relic_mask"] << wear_mask.type
+ WRITE_FILE(S["relic_mask"], wear_mask.type)
else
- S["relic_mask"] << null
+ WRITE_FILE(S["relic_mask"], null)
if(!dead)
memory_saved = 1
diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm
index 8bdcf30f66..ff37b85800 100644
--- a/code/modules/mob/living/emote.dm
+++ b/code/modules/mob/living/emote.dm
@@ -326,7 +326,7 @@
/datum/emote/living/surrender
key = "surrender"
key_third_person = "surrenders"
- message = "puts their hands on their head and falls to the ground, they surrender%s!"
+ message = "puts their hands on their head and falls to the ground, they surrender!"
emote_type = EMOTE_AUDIBLE
/datum/emote/living/surrender/run_emote(mob/user, params)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index b58fb0ec13..9684e44ac9 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -550,6 +550,7 @@
if(!restrained(ignore_grab = 1) && pulledby)
visible_message("[src] resists against [pulledby]'s grip!")
resist_grab()
+ add_logs(pulledby, src, "resisted grab")
return
//unbuckling yourself
@@ -587,6 +588,7 @@
if(pulledby.grab_state)
if(prob(30/pulledby.grab_state))
visible_message("[src] has broken free of [pulledby]'s grip!")
+ add_logs(pulledby, src, "broke grab")
pulledby.stop_pulling()
return 0
if(moving_resist && client) //we resisted by trying to move
@@ -795,7 +797,7 @@
else
to_chat(src, "You don't have the dexterity to do this!")
return
-/mob/living/proc/can_use_guns(var/obj/item/weapon/gun/G)
+/mob/living/proc/can_use_guns(var/obj/item/weapon/G)
if (G.trigger_guard != TRIGGER_GUARD_ALLOW_ALL && !IsAdvancedToolUser())
to_chat(src, "You don't have the dexterity to do this!")
return 0
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 0c693b4749..01dca7f00e 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -89,7 +89,7 @@
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
apply_damage(I.throwforce, dtype, zone, armor)
if(I.thrownby)
- add_logs(I.thrownby, src, "hit", I)
+ add_logs(I.thrownby, src, "threw and hit", I)
else
return 1
else
@@ -150,6 +150,7 @@
var/grab_upgrade_time = 30
visible_message("[user] starts to tighten [user.p_their()] grip on [src]!", \
"[user] starts to tighten [user.p_their()] grip on you!")
+ add_logs(user, src, "attempted to strangle", addition="grab")
if(!do_mob(user, src, grab_upgrade_time))
return 0
if(!user.pulling || user.pulling != src || user.grab_state != old_grab_state || user.a_intent != INTENT_GRAB)
@@ -157,18 +158,20 @@
user.grab_state++
switch(user.grab_state)
if(GRAB_AGGRESSIVE)
- add_logs(user, src, "grabbed", addition="aggressively")
+ add_logs(user, src, "grabbed", addition="aggressive grab")
visible_message("[user] has grabbed [src] aggressively!", \
"[user] has grabbed [src] aggressively!")
drop_all_held_items()
stop_pulling()
if(GRAB_NECK)
+ add_logs(user, src, "grabbed", addition="neck grab")
visible_message("[user] has grabbed [src] by the neck!",\
"[user] has grabbed you by the neck!")
update_canmove() //we fall down
if(!buckled && !density)
Move(user.loc)
if(GRAB_KILL)
+ add_logs(user, src, "strangled", addition="grab")
visible_message("[user] is strangling [src]!", \
"[user] is strangling you!")
update_canmove() //we fall down
@@ -316,7 +319,7 @@
GLOB.cult_narsie.souls += 1
if((GLOB.cult_narsie.souls == GLOB.cult_narsie.soul_goal) && (GLOB.cult_narsie.resolved == FALSE))
GLOB.cult_narsie.resolved = TRUE
- world << sound('sound/machines/alarm.ogg')
+ sound_to_playing_players('sound/machines/alarm.ogg')
addtimer(CALLBACK(GLOBAL_PROC, .proc/cult_ending_helper, 1), 120)
addtimer(CALLBACK(GLOBAL_PROC, .proc/ending_helper), 270)
if(client)
diff --git a/code/modules/mob/living/silicon/ai/examine.dm b/code/modules/mob/living/silicon/ai/examine.dm
index b19e866378..3af95cec4c 100644
--- a/code/modules/mob/living/silicon/ai/examine.dm
+++ b/code/modules/mob/living/silicon/ai/examine.dm
@@ -1,5 +1,5 @@
/mob/living/silicon/ai/examine(mob/user)
- var/msg = "*---------*\nThis is [bicon(src)] [src]!\n"
+ var/msg = "*---------*\nThis is [icon2html(src, user)] [src]!\n"
if (stat == DEAD)
msg += "It appears to be powered-down.\n"
else
diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm
index 2e800f7de0..f0e079b594 100644
--- a/code/modules/mob/living/silicon/ai/say.dm
+++ b/code/modules/mob/living/silicon/ai/say.dm
@@ -163,9 +163,9 @@
if(M.client && M.can_hear() && (M.client.prefs.toggles & SOUND_ANNOUNCEMENTS))
var/turf/T = get_turf(M)
if(T.z == z_level)
- M << voice
+ SEND_SOUND(M, voice)
else
- only_listener << voice
+ SEND_SOUND(only_listener, voice)
return 1
return 0
diff --git a/code/modules/mob/living/silicon/pai/personality.dm b/code/modules/mob/living/silicon/pai/personality.dm
index 869009f255..4b2bc45118 100644
--- a/code/modules/mob/living/silicon/pai/personality.dm
+++ b/code/modules/mob/living/silicon/pai/personality.dm
@@ -17,12 +17,12 @@
var/savefile/F = new /savefile(src.savefile_path(user))
- F["name"] << src.name
- F["description"] << src.description
- F["role"] << src.role
- F["comments"] << src.comments
+ WRITE_FILE(F["name"], name)
+ WRITE_FILE(F["description"], description)
+ WRITE_FILE(F["role"], role)
+ WRITE_FILE(F["comments"], comments)
- F["version"] << 1
+ WRITE_FILE(F["version"], 1)
return 1
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
index 77874ad403..f0c50e17f1 100644
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -173,7 +173,7 @@
if(href_list["send"])
sradio.send_signal("ACTIVATE")
- audible_message("[bicon(src)] *beep* *beep*")
+ audible_message("[icon2html(src, world)] *beep* *beep*")
if(href_list["freq"])
@@ -619,7 +619,8 @@
src.paiInterface()
if(hackprogress >= 100)
src.hackprogress = 0
- src.cable.machine:open()
+ var/obj/machinery/door/D = cable.machine
+ D.open()
sleep(50) // Update every 5 seconds
// Digital Messenger
diff --git a/code/modules/mob/living/silicon/robot/examine.dm b/code/modules/mob/living/silicon/robot/examine.dm
index 7f232e20f4..788a8f4255 100644
--- a/code/modules/mob/living/silicon/robot/examine.dm
+++ b/code/modules/mob/living/silicon/robot/examine.dm
@@ -1,11 +1,11 @@
/mob/living/silicon/robot/examine(mob/user)
- var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n"
+ var/msg = "*---------*\nThis is [icon2html(src, user)] \a [src]!\n"
if(desc)
msg += "[desc]\n"
var/obj/act_module = get_active_held_item()
if(act_module)
- msg += "It is holding [bicon(act_module)] \a [act_module].\n"
+ msg += "It is holding [icon2html(act_module, user)] \a [act_module].\n"
msg += ""
if (src.getBruteLoss())
if (src.getBruteLoss() < maxHealth*0.5)
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index 59cb793b27..3c963ca820 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -469,7 +469,7 @@ Pass a positive integer as an argument to override a bot's default speed.
var/area/end_area = get_area(waypoint)
if(client) //Player bots instead get a location command from the AI
- to_chat(src, "Priority waypoint set by [bicon(caller)] [caller]. Proceed to [end_area.name]<\b>.")
+ to_chat(src, "Priority waypoint set by [icon2html(caller, src)] [caller]. Proceed to [end_area.name]<\b>.")
//For giving the bot temporary all-access.
var/obj/item/weapon/card/id/all_access = new /obj/item/weapon/card/id
@@ -485,7 +485,7 @@ Pass a positive integer as an argument to override a bot's default speed.
turn_on() //Saves the AI the hassle of having to activate a bot manually.
access_card = all_access //Give the bot all-access while under the AI's command.
if(message)
- to_chat(calling_ai, "[bicon(src)] [name] called to [end_area.name]. [path.len-1] meters to destination.")
+ to_chat(calling_ai, "[icon2html(src, calling_ai)] [name] called to [end_area.name]. [path.len-1] meters to destination.")
pathset = 1
mode = BOT_RESPONDING
tries = 0
@@ -500,7 +500,7 @@ Pass a positive integer as an argument to override a bot's default speed.
var/success = bot_move(ai_waypoint, 3)
if(!success)
if(calling_ai)
- to_chat(calling_ai, "[bicon(src)] [get_turf(src) == ai_waypoint ? "[src] successfully arrived to waypoint." : "[src] failed to reach waypoint."]")
+ to_chat(calling_ai, "[icon2html(src, calling_ai)] [get_turf(src) == ai_waypoint ? "[src] successfully arrived to waypoint." : "[src] failed to reach waypoint."]")
calling_ai = null
bot_reset()
diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm
index e8936a2863..74005e84dd 100644
--- a/code/modules/mob/living/simple_animal/bot/mulebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm
@@ -596,7 +596,7 @@
if(pathset) //The AI called us here, so notify it of our arrival.
loaddir = dir //The MULE will attempt to load a crate in whatever direction the MULE is "facing".
if(calling_ai)
- to_chat(calling_ai, "[bicon(src)] [src] wirelessly plays a chiming sound!")
+ to_chat(calling_ai, "[icon2html(src, calling_ai)] [src] wirelessly plays a chiming sound!")
playsound(calling_ai, 'sound/machines/chime.ogg',40, 0)
calling_ai = null
radio_channel = "AI Private" //Report on AI Private instead if the AI is controlling us.
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index 74f855bf8c..e0993c6ce5 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -50,7 +50,7 @@
/mob/living/simple_animal/hostile/construct/examine(mob/user)
var/t_He = p_they(TRUE)
var/t_s = p_s()
- var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n"
+ var/msg = "*---------*\nThis is [icon2html(src, user)] \a [src]!\n"
msg += "[desc]\n"
if(health < maxHealth)
msg += ""
diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm
index ef0b35cdc3..62e0fb8fdd 100644
--- a/code/modules/mob/living/simple_animal/friendly/cat.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cat.dm
@@ -130,7 +130,7 @@
family[C.type] += 1
else
family[C.type] = 1
- S["family"] << family
+ WRITE_FILE(S["family"], family)
memory_saved = 1
/mob/living/simple_animal/pet/cat/Runtime/proc/Deploy_The_Cats()
diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm
index f80defb32d..58d497293a 100644
--- a/code/modules/mob/living/simple_animal/friendly/dog.dm
+++ b/code/modules/mob/living/simple_animal/friendly/dog.dm
@@ -344,14 +344,14 @@
/mob/living/simple_animal/pet/dog/corgi/Ian/proc/Write_Memory(dead)
var/savefile/S = new /savefile("data/npc_saves/Ian.sav")
if(!dead)
- S["age"] << age + 1
+ WRITE_FILE(S["age"], age + 1)
if((age + 1) > record_age)
- S["record_age"] << record_age + 1
+ WRITE_FILE(S["record_age"], record_age + 1)
if(inventory_head)
- S["saved_head"] << inventory_head.type
+ WRITE_FILE(S["saved_head"], inventory_head.type)
else
- S["age"] << 0
- S["saved_head"] << null
+ WRITE_FILE(S["age"], 0)
+ WRITE_FILE(S["saved_head"], null)
memory_saved = 1
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index db347cc203..b37d5079d7 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -171,29 +171,29 @@
/mob/living/simple_animal/drone/examine(mob/user)
- var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n"
+ var/msg = "*---------*\nThis is [icon2html(src, user)] \a [src]!\n"
//Hands
for(var/obj/item/I in held_items)
if(!(I.flags & ABSTRACT))
if(I.blood_DNA)
- msg += "It has [bicon(I)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n"
+ msg += "It has [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n"
else
- msg += "It has [bicon(I)] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n"
+ msg += "It has [icon2html(I, user)] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n"
//Internal storage
if(internal_storage && !(internal_storage.flags&ABSTRACT))
if(internal_storage.blood_DNA)
- msg += "It is holding [bicon(internal_storage)] [internal_storage.gender==PLURAL?"some":"a"] blood-stained [internal_storage.name] in its internal storage!\n"
+ msg += "It is holding [icon2html(internal_storage, user)] [internal_storage.gender==PLURAL?"some":"a"] blood-stained [internal_storage.name] in its internal storage!\n"
else
- msg += "It is holding [bicon(internal_storage)] \a [internal_storage] in its internal storage.\n"
+ msg += "It is holding [icon2html(internal_storage, user)] \a [internal_storage] in its internal storage.\n"
//Cosmetic hat - provides no function other than looks
if(head && !(head.flags&ABSTRACT))
if(head.blood_DNA)
- msg += "It is wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] blood-stained [head.name] on its head!\n"
+ msg += "It is wearing [icon2html(head, user)] [head.gender==PLURAL?"some":"a"] blood-stained [head.name] on its head!\n"
else
- msg += "It is wearing [bicon(head)] \a [head] on its head.\n"
+ msg += "It is wearing [icon2html(head, user)] \a [head] on its head.\n"
//Braindead
if(!client && stat != DEAD)
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
index c984194805..51d28df31b 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
@@ -176,7 +176,7 @@
else
..()
-/mob/living/simple_animal/drone/cogscarab/can_use_guns(obj/item/weapon/gun/G)
+/mob/living/simple_animal/drone/cogscarab/can_use_guns(obj/item/weapon/G)
return GLOB.ratvar_awakens
/mob/living/simple_animal/drone/cogscarab/get_armor_effectiveness()
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index 207bda2c2c..75a1759e1d 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -57,7 +57,7 @@
if( ishuman(AM) )
if(!stat)
var/mob/M = AM
- to_chat(M, "[bicon(src)] Squeek!")
+ to_chat(M, "[icon2html(src, M)] Squeek!")
playsound(src, 'sound/effects/mousesqueek.ogg', 100, 1)
..()
diff --git a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm
index 5fe0ccaade..02754e0121 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm
@@ -26,21 +26,21 @@
/mob/living/simple_animal/hostile/guardian/dextrous/examine(mob/user)
if(dextrous)
- var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n"
+ var/msg = "*---------*\nThis is [icon2html(src)] \a [src]!\n"
msg += "[desc]\n"
for(var/obj/item/I in held_items)
if(!(I.flags & ABSTRACT))
if(I.blood_DNA)
- msg += "It has [bicon(I)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n"
+ msg += "It has [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!\n"
else
- msg += "It has [bicon(I)] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n"
+ msg += "It has [icon2html(I, user)] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n"
if(internal_storage && !(internal_storage.flags&ABSTRACT))
if(internal_storage.blood_DNA)
- msg += "It is holding [bicon(internal_storage)] [internal_storage.gender==PLURAL?"some":"a"] blood-stained [internal_storage.name] in its internal storage!\n"
+ msg += "It is holding [icon2html(internal_storage, user)] [internal_storage.gender==PLURAL?"some":"a"] blood-stained [internal_storage.name] in its internal storage!\n"
else
- msg += "It is holding [bicon(internal_storage)] \a [internal_storage] in its internal storage.\n"
+ msg += "It is holding [icon2html(internal_storage, user)] \a [internal_storage] in its internal storage.\n"
msg += "*---------*"
to_chat(user, msg)
else
diff --git a/code/modules/mob/living/simple_animal/guardian/types/fire.dm b/code/modules/mob/living/simple_animal/guardian/types/fire.dm
index b0a8ba5215..8f456abc53 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/fire.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/fire.dm
@@ -21,7 +21,7 @@
/mob/living/simple_animal/hostile/guardian/fire/AttackingTarget()
. = ..()
if(. && ishuman(target) && target != summoner)
- new /obj/effect/hallucination/delusion(target.loc,target,"custom",200,0, icon_state,icon)
+ new /datum/hallucination/delusion(target,TRUE,"custom",200,0, icon_state,icon)
/mob/living/simple_animal/hostile/guardian/fire/Crossed(AM as mob|obj)
..()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index 6cebdd9500..6b528651f4 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -283,7 +283,7 @@ Difficulty: Very Hard
for(var/obj/O in (contents-component_parts))
stored_items += O.type
- S["stored_items"] << stored_items
+ WRITE_FILE(S["stored_items"], stored_items)
memory_saved = TRUE
/obj/machinery/smartfridge/black_box/proc/ReadMemory()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index 11c59a2d28..0ca966df35 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -57,6 +57,7 @@ Difficulty: Hard
ranged_cooldown_time = 40
aggro_vision_range = 21 //so it can see to one side of the arena to the other
loot = list(/obj/item/weapon/hierophant_club)
+ crusher_loot = list(/obj/item/weapon/hierophant_club)
wander = FALSE
var/burst_range = 3 //range on burst aoe
var/beam_range = 5 //range on cross blast beams
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index 86bbcfdc45..6be40e0d43 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -936,10 +936,10 @@
/mob/living/simple_animal/parrot/Poly/proc/Write_Memory()
var/savefile/S = new /savefile("data/npc_saves/Poly.sav")
if(islist(speech_buffer))
- S["phrases"] << speech_buffer
- S["roundssurvived"] << rounds_survived
- S["longestsurvival"] << longest_survival
- S["longestdeathstreak"] << longest_deathstreak
+ WRITE_FILE(S["phrases"], speech_buffer)
+ WRITE_FILE(S["roundssurvived"], rounds_survived)
+ WRITE_FILE(S["longestsurvival"], longest_survival)
+ WRITE_FILE(S["longestdeathstreak"], longest_deathstreak)
memory_saved = 1
/mob/living/simple_animal/parrot/Poly/ghost
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 236b36dafd..0e7d7a157e 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -347,7 +347,7 @@
/mob/living/simple_animal/slime/examine(mob/user)
- var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n"
+ var/msg = "*---------*\nThis is [icon2html(src, user)] \a [src]!\n"
if (src.stat == DEAD)
msg += "It is limp and unresponsive.\n"
else
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 26b22d964e..d612611ea6 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -327,6 +327,7 @@
if(AM.pulledby)
if(!supress_message)
visible_message("[src] has pulled [AM] from [AM.pulledby]'s grip.")
+ add_logs(AM, AM.pulledby, "pulled from", src)
AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once.
pulling = AM
@@ -337,6 +338,7 @@
if(ismob(AM))
var/mob/M = AM
+ add_logs(src, M, "grabbed", addition="passive grab")
if(!supress_message)
visible_message("[src] has grabbed [M] passively!")
if(!iscarbon(src))
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index a704c2e43f..999779c7e3 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -325,6 +325,9 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
return B.eye_blind
return 0
+/mob/proc/hallucinating()
+ return FALSE
+
/proc/is_special_character(mob/M) // returns 1 for special characters and 2 for heroes of gamemode //moved out of admins.dm because things other than admin procs were calling this.
if(!SSticker.HasRoundStarted())
return 0
@@ -384,7 +387,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
if(O.client)
to_chat(O, "[message][(enter_link) ? " [enter_link]" : ""]")
if(ghost_sound)
- O << sound(ghost_sound)
+ SEND_SOUND(O, sound(ghost_sound))
if(flashwindow)
window_flash(O.client)
if(source)
diff --git a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
index f200fbf747..10a6deb63d 100644
--- a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
+++ b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
@@ -110,7 +110,7 @@
if(!channel)
return
var/mob/living/user = usr
- var/logname = input(user,"Enter desired logfile name (.log) or leave blank to cancel:")
+ var/logname = stripped_input(user,"Enter desired logfile name (.log) or leave blank to cancel:")
if(!logname || !channel)
return 1
var/datum/computer_file/data/logfile = new/datum/computer_file/data/logfile()
diff --git a/code/modules/ninja/suit/suit_initialisation.dm b/code/modules/ninja/suit/suit_initialisation.dm
index b723ade381..5fb3fe8a62 100644
--- a/code/modules/ninja/suit/suit_initialisation.dm
+++ b/code/modules/ninja/suit/suit_initialisation.dm
@@ -70,7 +70,7 @@
addtimer(CALLBACK(src, .proc/deinitialize_three, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_three(delay, mob/living/carbon/human/U)
- to_chat(U, "Logging off, [U:real_name]. Shutting down SpiderOS.")
+ to_chat(U, "Logging off, [U.real_name]. Shutting down SpiderOS.")
addtimer(CALLBACK(src, .proc/deinitialize_four, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_four(delay, mob/living/carbon/human/U)
diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm
index b1896f930a..4755f3d64a 100644
--- a/code/modules/paperwork/photography.dm
+++ b/code/modules/paperwork/photography.dm
@@ -222,8 +222,9 @@
var/offX = 32 * (A.x - center.x) + A.pixel_x + 33
var/offY = 32 * (A.y - center.y) + A.pixel_y + 33
if(ismovableatom(A))
- offX += A:step_x
- offY += A:step_y
+ var/atom/movable/AM = A
+ offX += AM.step_x
+ offY += AM.step_y
res.Blend(img, blendMode2iconMode(A.blend_mode), offX, offY)
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index e36c639eb9..d01516e312 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -120,8 +120,8 @@
if(auto_name)
name = "\improper [get_area(src)] APC"
- pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 24 : -24)
- pixel_y = (src.tdir & 3)? (src.tdir ==1 ? 24 : -24) : 0
+ pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 26 : -27)
+ pixel_y = (src.tdir & 3)? (src.tdir == 1 ? 25 : -25) : 0
if (building)
area = get_area(src)
opened = 1
@@ -892,7 +892,7 @@
transfer_in_progress = TRUE
user.visible_message("[user] slots [card] into [src]...", "Transfer process initiated. Sending request for AI approval...")
playsound(src, 'sound/machines/click.ogg', 50, 1)
- occupier << sound('sound/misc/notice2.ogg') //To alert the AI that someone's trying to card them if they're tabbed out
+ SEND_SOUND(occupier, sound('sound/misc/notice2.ogg')) //To alert the AI that someone's trying to card them if they're tabbed out
if(alert(occupier, "[user] is attempting to transfer you to \a [card.name]. Do you consent to this?", "APC Transfer", "Yes - Transfer Me", "No - Keep Me Here") == "No - Keep Me Here")
to_chat(user, "AI denied transfer request. Process terminated.")
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1)
@@ -986,9 +986,6 @@
else
main_status = 2
- //if(debug)
- // world.log << "Status: [main_status] - Excess: [excess] - Last Equip: [lastused_equip] - Last Light: [lastused_light] - Longterm: [longtermpower]"
-
if(cell && !shorted)
// draw power from cell as before to power the area
var/cellused = min(cell.charge, GLOB.CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell
diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm
index b0d07e88d5..f130e7be11 100644
--- a/code/modules/power/power.dm
+++ b/code/modules/power/power.dm
@@ -216,7 +216,6 @@
//remove the old powernet and replace it with a new one throughout the network.
/proc/propagate_network(obj/O, datum/powernet/PN)
- //world.log << "propagating new network"
var/list/worklist = list()
var/list/found_machines = list()
var/index = 1
diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm
index 90c33bb6b3..df969d869e 100644
--- a/code/modules/power/singularity/narsie.dm
+++ b/code/modules/power/singularity/narsie.dm
@@ -71,7 +71,7 @@
sleep(1150)
if(resolved == FALSE)
resolved = TRUE
- world << sound('sound/machines/alarm.ogg')
+ sound_to_playing_players('sound/machines/alarm.ogg')
addtimer(CALLBACK(GLOBAL_PROC, .proc/cult_ending_helper), 120)
addtimer(CALLBACK(GLOBAL_PROC, .proc/ending_helper), 220)
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 07190b102c..1b65da86ab 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -26,7 +26,7 @@
var/last_failed_movement = 0//Will not move in the same dir if it couldnt before, will help with the getting stuck on fields thing
var/last_warning
var/consumedSupermatter = 0 //If the singularity has eaten a supermatter shard and can go to stage six
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF
dangerous_possession = TRUE
/obj/singularity/Initialize(mapload, starting_energy = 50)
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index 816cd97874..f635d8e227 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -219,7 +219,7 @@
var/turf/T = get_turf(src)
for(var/mob/M in GLOB.mob_list)
if(M.z == z)
- M << 'sound/magic/charge.ogg'
+ SEND_SOUND(M, 'sound/magic/charge.ogg')
to_chat(M, "You feel reality distort for a moment...")
if(combined_gas > MOLE_PENALTY_THRESHOLD)
investigate_log("has collapsed into a singularity.", INVESTIGATE_SUPERMATTER)
@@ -457,7 +457,7 @@
visible_message("[src] is consumed by the singularity!")
for(var/mob/M in GLOB.mob_list)
if(M.z == z)
- M << 'sound/effects/supermatter.ogg' //everyone goan know bout this
+ SEND_SOUND(M, 'sound/effects/supermatter.ogg') //everyone goan know bout this
to_chat(M, "A horrible screeching fills your ears, and a wave of dread washes over you...")
qdel(src)
return gain
diff --git a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
index 24b75a3a9a..6fdcccd43f 100644
--- a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
+++ b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
@@ -37,16 +37,12 @@
/datum/mapGeneratorModule/bottomLayer/massdelete/leave_turfs
deleteturfs = FALSE
-/datum/mapGeneratorModule/bottomLayer/massdelete/leave_turfs/New()
- ..()
- ignore_typecache = typecacheof(list(/turf))
-
/datum/mapGeneratorModule/bottomLayer/massdelete/regeneration_delete
deleteturfs = FALSE
/datum/mapGeneratorModule/bottomLayer/massdelete/regeneration_delete/New()
..()
- ignore_typecache = typecacheof(list(/mob, /turf))
+ ignore_typecache = typecacheof(list(/mob))
//Only places atoms/turfs on area borders
/datum/mapGeneratorModule/border
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 156a5ee81e..d5109a2c0c 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -27,7 +27,7 @@
var/recoil = 0 //boom boom shake the room
var/clumsy_check = 1
var/obj/item/ammo_casing/chambered = null
- var/trigger_guard = TRIGGER_GUARD_NORMAL //trigger guard on the weapon, hulks can't fire them with their big meaty fingers
+ trigger_guard = TRIGGER_GUARD_NORMAL //trigger guard on the weapon, hulks can't fire them with their big meaty fingers
var/sawn_desc = null //description change if weapon is sawn-off
var/sawn_state = SAWN_INTACT
var/burst_size = 1 //how large a burst is
@@ -188,12 +188,10 @@
-/obj/item/weapon/gun/proc/can_trigger_gun(var/mob/living/user)
-
- if(!handle_pins(user) || !user.can_use_guns(src))
- return 0
-
- return 1
+/obj/item/weapon/gun/can_trigger_gun(mob/living/user)
+ . = ..()
+ if(!handle_pins(user))
+ return FALSE
/obj/item/weapon/gun/proc/handle_pins(mob/living/user)
if(pin)
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index 54e0ed7e12..f7aedb00fc 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -356,7 +356,7 @@
/obj/item/projectile/bullet/saw/hollow
damage = 60
- armour_penetration = -10
+ armour_penetration = -60
/obj/item/projectile/bullet/saw/ap
damage = 40
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index 4b1d5af6c4..5a8f49f45a 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -387,3 +387,232 @@
var/obj/effect/ebeam/B = b
animate(B, alpha = 0, time = 32)
return ..()
+
+/obj/item/projectile/hallucination
+ name = "bullet"
+ icon = null
+ icon_state = null
+ hitsound = ""
+ suppressed = TRUE
+ ricochets_max = 0
+ ricochet_chance = 0
+ damage = 0
+ nodamage = TRUE
+ projectile_type = /obj/item/projectile/hallucination
+ log_override = TRUE
+ var/hal_icon_state
+ var/image/fake_icon
+ var/mob/living/carbon/hal_target
+ var/hal_fire_sound
+ var/hal_hitsound
+ var/hal_hitsound_wall
+ var/hal_impact_effect
+ var/hal_impact_effect_wall
+ var/hit_duration
+ var/hit_duration_wall
+
+/obj/item/projectile/hallucination/fire()
+ ..()
+ fake_icon = image('icons/obj/projectiles.dmi', src, hal_icon_state, ABOVE_MOB_LAYER)
+ if(hal_target.client)
+ hal_target.client.images += fake_icon
+
+/obj/item/projectile/hallucination/Destroy()
+ if(hal_target.client)
+ hal_target.client.images -= fake_icon
+ QDEL_NULL(fake_icon)
+ return ..()
+
+/obj/item/projectile/hallucination/Collide(atom/A)
+ if(!ismob(A))
+ if(hal_hitsound_wall)
+ hal_target.playsound_local(loc, hal_hitsound_wall, 40, 1)
+ if(hal_impact_effect_wall)
+ spawn_hit(A, TRUE)
+ else if(A == hal_target)
+ if(hal_hitsound)
+ hal_target.playsound_local(A, hal_hitsound, 100, 1)
+ target_on_hit(A)
+ qdel(src)
+ return TRUE
+
+/obj/item/projectile/hallucination/proc/target_on_hit(mob/M)
+ if(M == hal_target)
+ to_chat(hal_target, "[M] is hit by \a [src] in the chest!")
+ hal_apply_effect()
+ else if(M in view(hal_target))
+ to_chat(hal_target, "[M] is hit by \a [src] in the chest!!")
+ if(damage_type == BRUTE)
+ var/splatter_dir = dir
+ if(starting)
+ splatter_dir = get_dir(starting, get_turf(M))
+ spawn_blood(M, splatter_dir)
+ else if(hal_impact_effect)
+ spawn_hit(M, FALSE)
+
+/obj/item/projectile/hallucination/proc/spawn_blood(mob/M, set_dir)
+ set waitfor = 0
+ if(!hal_target.client)
+ return
+
+ var/splatter_icon_state
+ if(set_dir in GLOB.diagonals)
+ splatter_icon_state = "splatter[pick(1, 2, 6)]"
+ else
+ splatter_icon_state = "splatter[pick(3, 4, 5)]"
+
+ var/image/blood = image('icons/effects/blood.dmi', M, splatter_icon_state, ABOVE_MOB_LAYER)
+ var/target_pixel_x = 0
+ var/target_pixel_y = 0
+ switch(set_dir)
+ if(NORTH)
+ target_pixel_y = 16
+ if(SOUTH)
+ target_pixel_y = -16
+ layer = ABOVE_MOB_LAYER
+ if(EAST)
+ target_pixel_x = 16
+ if(WEST)
+ target_pixel_x = -16
+ if(NORTHEAST)
+ target_pixel_x = 16
+ target_pixel_y = 16
+ if(NORTHWEST)
+ target_pixel_x = -16
+ target_pixel_y = 16
+ if(SOUTHEAST)
+ target_pixel_x = 16
+ target_pixel_y = -16
+ layer = ABOVE_MOB_LAYER
+ if(SOUTHWEST)
+ target_pixel_x = -16
+ target_pixel_y = -16
+ layer = ABOVE_MOB_LAYER
+ hal_target.client.images += blood
+ animate(blood, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = 5)
+ sleep(5)
+ hal_target.client.images -= blood
+ qdel(blood)
+
+/obj/item/projectile/hallucination/proc/spawn_hit(atom/A, is_wall)
+ set waitfor = 0
+ if(!hal_target.client)
+ return
+
+ var/image/hit_effect = image('icons/effects/blood.dmi', A, is_wall ? hal_impact_effect_wall : hal_impact_effect, ABOVE_MOB_LAYER)
+ hit_effect.pixel_x = A.pixel_x + rand(-4,4)
+ hit_effect.pixel_y = A.pixel_y + rand(-4,4)
+ hal_target.client.images += hit_effect
+ sleep(is_wall ? hit_duration_wall : hit_duration)
+ hal_target.client.images -= hit_effect
+ qdel(hit_effect)
+
+
+/obj/item/projectile/hallucination/proc/hal_apply_effect()
+ return
+
+/obj/item/projectile/hallucination/bullet
+ name = "bullet"
+ hal_icon_state = "bullet"
+ hal_fire_sound = "gunshot"
+ hal_hitsound = 'sound/weapons/pierce.ogg'
+ hal_hitsound_wall = "ricochet"
+ hal_impact_effect = "impact_bullet"
+ hal_impact_effect_wall = "impact_bullet"
+ hit_duration = 5
+ hit_duration_wall = 5
+
+/obj/item/projectile/hallucination/bullet/hal_apply_effect()
+ hal_target.adjustStaminaLoss(60)
+
+/obj/item/projectile/hallucination/laser
+ name = "laser"
+ damage_type = BURN
+ hal_icon_state = "laser"
+ hal_fire_sound = 'sound/weapons/laser.ogg'
+ hal_hitsound = 'sound/weapons/sear.ogg'
+ hal_hitsound_wall = 'sound/weapons/effects/searwall.ogg'
+ hal_impact_effect = "impact_laser"
+ hal_impact_effect_wall = "impact_laser_wall"
+ hit_duration = 4
+ hit_duration_wall = 10
+ pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
+
+/obj/item/projectile/hallucination/laser/hal_apply_effect()
+ hal_target.adjustStaminaLoss(20)
+ hal_target.blur_eyes(2)
+
+/obj/item/projectile/hallucination/taser
+ name = "electrode"
+ damage_type = BURN
+ hal_icon_state = "spark"
+ color = "#FFFF00"
+ hal_fire_sound = 'sound/weapons/taser.ogg'
+ hal_hitsound = 'sound/weapons/taserhit.ogg'
+ hal_hitsound_wall = null
+ hal_impact_effect = null
+ hal_impact_effect_wall = null
+
+/obj/item/projectile/hallucination/taser/hal_apply_effect()
+ hal_target.Knockdown(100)
+ hal_target.stuttering += 20
+ if(hal_target.dna && hal_target.dna.check_mutation(HULK))
+ hal_target.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
+ else if(hal_target.status_flags & CANKNOCKDOWN)
+ addtimer(CALLBACK(hal_target, /mob/living/carbon.proc/do_jitter_animation, 20), 5)
+
+/obj/item/projectile/hallucination/disabler
+ name = "disabler beam"
+ damage_type = STAMINA
+ hal_icon_state = "omnilaser"
+ hal_fire_sound = 'sound/weapons/taser2.ogg'
+ hal_hitsound = 'sound/weapons/tap.ogg'
+ hal_hitsound_wall = 'sound/weapons/effects/searwall.ogg'
+ hal_impact_effect = "impact_laser_blue"
+ hal_impact_effect_wall = null
+ hit_duration = 4
+ pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
+
+/obj/item/projectile/hallucination/disabler/hal_apply_effect()
+ hal_target.adjustStaminaLoss(25)
+
+/obj/item/projectile/hallucination/ebow
+ name = "bolt"
+ damage_type = TOX
+ hal_icon_state = "cbbolt"
+ hal_fire_sound = 'sound/weapons/genhit.ogg'
+ hal_hitsound = null
+ hal_hitsound_wall = null
+ hal_impact_effect = null
+ hal_impact_effect_wall = null
+
+/obj/item/projectile/hallucination/ebow/hal_apply_effect()
+ hal_target.Knockdown(100)
+ hal_target.stuttering += 5
+ hal_target.adjustStaminaLoss(8)
+
+/obj/item/projectile/hallucination/change
+ name = "bolt of change"
+ damage_type = BURN
+ hal_icon_state = "ice_1"
+ hal_fire_sound = 'sound/magic/staff_change.ogg'
+ hal_hitsound = null
+ hal_hitsound_wall = null
+ hal_impact_effect = null
+ hal_impact_effect_wall = null
+
+/obj/item/projectile/hallucination/change/hal_apply_effect()
+ new /datum/hallucination/self_delusion(hal_target, TRUE, wabbajack = FALSE)
+
+/obj/item/projectile/hallucination/death
+ name = "bolt of death"
+ damage_type = BURN
+ hal_icon_state = "pulse1_bl"
+ hal_fire_sound = 'sound/magic/wandodeath.ogg'
+ hal_hitsound = null
+ hal_hitsound_wall = null
+ hal_impact_effect = null
+ hal_impact_effect_wall = null
+
+/obj/item/projectile/hallucination/death/hal_apply_effect()
+ new /datum/hallucination/death(hal_target, TRUE)
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index 8d2bd6002f..a062d5c614 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -401,19 +401,21 @@
add_reagent(P, cached_results[P]*multiplier, null, chem_temp)
var/list/seen = viewers(4, get_turf(my_atom))
+ var/iconhtml = icon2html(cached_my_atom, seen)
if(cached_my_atom)
if(!ismob(cached_my_atom)) // No bubbling mobs
if(C.mix_sound)
playsound(get_turf(cached_my_atom), C.mix_sound, 80, 1)
+
for(var/mob/M in seen)
- to_chat(M, "[bicon(my_atom)] [C.mix_message]")
+ to_chat(M, "[iconhtml] [C.mix_message]")
if(istype(cached_my_atom, /obj/item/slime_extract))
var/obj/item/slime_extract/ME2 = my_atom
ME2.Uses--
if(ME2.Uses <= 0) // give the notification that the slime core is dead
for(var/mob/M in seen)
- to_chat(M, "[bicon(my_atom)] \The [my_atom]'s power is consumed in the reaction.")
+ to_chat(M, "[iconhtml] \The [my_atom]'s power is consumed in the reaction.")
ME2.name = "used slime extract"
ME2.desc = "This extract has been used up."
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index 27cad406fa..3811512a02 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -101,9 +101,11 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "chem_dispenser", name, 550, 550, master_ui, state)
+ if(user.hallucinating())
+ ui.set_autoupdate(FALSE) //to not ruin the immersion by constantly changing the fake chemicals
ui.open()
-/obj/machinery/chem_dispenser/ui_data()
+/obj/machinery/chem_dispenser/ui_data(mob/user)
var/data = list()
data["amount"] = amount
data["energy"] = cell.charge ? cell.charge * powerefficiency : "0" //To prevent NaN in the UI.
@@ -128,10 +130,16 @@
data["beakerTransferAmounts"] = null
var chemicals[0]
+ var/is_hallucinating = FALSE
+ if(user.hallucinating())
+ is_hallucinating = TRUE
for(var/re in dispensable_reagents)
var/datum/reagent/temp = GLOB.chemical_reagents_list[re]
if(temp)
- chemicals.Add(list(list("title" = temp.name, "id" = temp.id)))
+ var/chemname = temp.name
+ if(is_hallucinating && prob(5))
+ chemname = "[pick_list_replacements("hallucination.json", "chemicals")]"
+ chemicals.Add(list(list("title" = chemname, "id" = temp.id)))
data["chemicals"] = chemicals
return data
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index 1fae98e2f3..72001d5ca9 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -390,7 +390,7 @@
T.MakeSlippery(min_wet_time = 10, wet_time_to_add = reac_volume*2)
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T)
if(hotspot)
- var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles() )
+ var/datum/gas_mixture/lowertemp = T.remove_air(T.air.total_moles())
lowertemp.temperature = max( min(lowertemp.temperature-2000,lowertemp.temperature / 2) ,0)
lowertemp.react()
T.assume_air(lowertemp)
diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
index dc361467a7..dcafef247b 100644
--- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
+++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
@@ -140,7 +140,7 @@
name = "Meth explosion"
id = "methboom1"
results = list("methboom1" = 1)
- required_temp = 380 //slightly above the meth mix time.
+ required_temp = 420 //high enough to not blow up in the meth syringes
required_reagents = list("methamphetamine" = 1)
strengthdiv = 6
modifier = 1
@@ -154,7 +154,7 @@
/datum/chemical_reaction/reagent_explosion/methsplosion/methboom2
required_reagents = list("diethylamine" = 1, "iodine" = 1, "phosphorus" = 1, "hydrogen" = 1) //diethylamine is often left over from mixing the ephedrine.
- required_temp = 300 //room temperature, chilling it even a little will prevent the explosion
+ required_temp = 420
results = list("methboom1" = 4) // this is ugly. Sorry goof.
/datum/chemical_reaction/sorium
diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm
index 0d0a4f7695..4388d6bcbe 100644
--- a/code/modules/recycling/conveyor2.dm
+++ b/code/modules/recycling/conveyor2.dm
@@ -341,7 +341,7 @@
found = 1
break
if(!found)
- to_chat(user, "[bicon(src)]The conveyor switch did not detect any linked conveyor belts in range.")
+ to_chat(user, "[icon2html(src, user)]The conveyor switch did not detect any linked conveyor belts in range.")
return
var/obj/machinery/conveyor_switch/NC = new/obj/machinery/conveyor_switch(A, id)
transfer_fingerprints_to(NC)
diff --git a/code/modules/server_tools/server_tools.dm b/code/modules/server_tools/server_tools.dm
index d6a98ad2e5..be8c80ac24 100644
--- a/code/modules/server_tools/server_tools.dm
+++ b/code/modules/server_tools/server_tools.dm
@@ -73,7 +73,7 @@ GLOBAL_PROTECT(reboot_mode)
if(rtod - last_irc_status < IRC_STATUS_THROTTLE)
return
last_irc_status = rtod
- return "[GLOB.clients.len] players on [SSmapping.config.map_name], Mode: [GLOB.master_mode]; Round [SSticker.HasRoundStarted() ? (SSticker.IsRoundInProgress() ? "Active" : "Finishing") : "Starting"] -- [config.server ? config.server : "[world.internet_address]:[world.port]"]"
+ return "[GLOB.round_id ? "Round #[GLOB.round_id]: " : ""][GLOB.clients.len] players on [SSmapping.config.map_name], Mode: [GLOB.master_mode]; Round [SSticker.HasRoundStarted() ? (SSticker.IsRoundInProgress() ? "Active" : "Finishing") : "Starting"] -- [config.server ? config.server : "[world.internet_address]:[world.port]"]"
if(SERVICE_CMD_ADMIN_MSG)
return IrcPm(params[SERVICE_CMD_PARAM_TARGET], params[SERVICE_CMD_PARAM_MESSAGE], params[SERVICE_CMD_PARAM_SENDER])
diff --git a/code/modules/spells/spell_types/knock.dm b/code/modules/spells/spell_types/knock.dm
index b68491d15d..bbb2b3877f 100644
--- a/code/modules/spells/spell_types/knock.dm
+++ b/code/modules/spells/spell_types/knock.dm
@@ -13,7 +13,7 @@
action_icon_state = "knock"
/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets,mob/user = usr)
- user << sound('sound/magic/knock.ogg')
+ SEND_SOUND(user, sound('sound/magic/knock.ogg'))
for(var/turf/T in targets)
for(var/obj/machinery/door/door in T.contents)
INVOKE_ASYNC(src, .proc/open_door, door)
diff --git a/code/modules/spells/spell_types/mind_transfer.dm b/code/modules/spells/spell_types/mind_transfer.dm
index fafb8afde6..023af548d0 100644
--- a/code/modules/spells/spell_types/mind_transfer.dm
+++ b/code/modules/spells/spell_types/mind_transfer.dm
@@ -75,5 +75,5 @@ Also, you never added distance checking after target is selected. I've went ahea
//Here we knock both mobs out for a time.
caster.Unconscious(unconscious_amount_caster)
victim.Unconscious(unconscious_amount_victim)
- caster << sound('sound/magic/mandswap.ogg')
- victim << sound('sound/magic/mandswap.ogg')// only the caster and victim hear the sounds, that way no one knows for sure if the swap happened
+ SEND_SOUND(caster, sound('sound/magic/mandswap.ogg'))
+ SEND_SOUND(victim, sound('sound/magic/mandswap.ogg'))// only the caster and victim hear the sounds, that way no one knows for sure if the swap happened
diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm
index ff44804e75..0f5f1de91d 100644
--- a/code/modules/surgery/organs/vocal_cords.dm
+++ b/code/modules/surgery/organs/vocal_cords.dm
@@ -290,9 +290,8 @@
//HALLUCINATE
else if((findtext(message, hallucinate_words)))
cooldown = COOLDOWN_MEME
- for(var/V in listeners)
- var/mob/living/L = V
- new /obj/effect/hallucination/delusion(get_turf(L),L,null,150 * power_multiplier,0)
+ for(var/mob/living/carbon/C in listeners)
+ new /datum/hallucination/delusion(C, TRUE, null,150 * power_multiplier,0)
//WAKE UP
else if((findtext(message, wakeup_words)))
diff --git a/code/modules/uplink/uplink_item.dm b/code/modules/uplink/uplink_item.dm
index 7b455b7d80..b04ebe6643 100644
--- a/code/modules/uplink/uplink_item.dm
+++ b/code/modules/uplink/uplink_item.dm
@@ -110,10 +110,10 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
var/obj/item/weapon/storage/box/B = A
if(istype(B) && B.contents.len > 0)
for(var/obj/item/I in B)
- U.purchase_log += "[bicon(I)]"
+ U.purchase_log += "[icon2base64html(I)]"
else
if(purchase_log_vis)
- U.purchase_log += "[bicon(A)]"
+ U.purchase_log += "[icon2base64html(A)]"
if(limited_stock > 0)
limited_stock -= 1
@@ -1394,7 +1394,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
continue
crate_value -= I.cost
new I.item(C)
- U.purchase_log += "[bicon(I.item)]"
+ U.purchase_log += "[icon2base64html(I.item)]"
SSblackbox.add_details("traitor_uplink_items_bought", "[name]|[cost]")
return C
diff --git a/code/modules/vehicles/bicycle.dm b/code/modules/vehicles/bicycle.dm
index 2d9b3c8258..cd93196b69 100644
--- a/code/modules/vehicles/bicycle.dm
+++ b/code/modules/vehicles/bicycle.dm
@@ -13,7 +13,7 @@
/obj/vehicle/bicycle/buckle_mob(mob/living/M, force = 0, check_loc = 1)
if(prob(easter_egg_chance) || (SSevents.holidays && SSevents.holidays[APRIL_FOOLS]))
- M << sound(pick(bike_music), repeat = 1, wait = 0, volume = 80, channel = CHANNEL_BICYCLE)
+ SEND_SOUND(M, sound(pick(bike_music), repeat = 1, wait = 0, volume = 80, channel = CHANNEL_BICYCLE))
. = ..()
/obj/vehicle/bicycle/unbuckle_mob(mob/living/buckled_mob,force = 0)
diff --git a/code/world.dm b/code/world.dm
index 5ef7491f45..955d19c6c4 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -1,3 +1,7 @@
+
+//This file is just for the necessary /world definition
+//Try looking in game/world.dm
+
/world
mob = /mob/dead/new_player
turf = /turf/open/space/basic
@@ -10,299 +14,3 @@
#ifdef GC_FAILURE_HARD_LOOKUP
loop_checks = FALSE
#endif
-
-/world/New()
- log_world("World loaded at [time_stamp()]")
-
- SetupExternalRSC()
-
- GLOB.config_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = file("data/logs/config_error.log") //temporary file used to record errors with loading config, moved to log directory once logging is set bl
-
- make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
-
- config = new
-
- CheckSchemaVersion()
- SetRoundID()
-
- SetupLogs()
-
- if(!RunningService()) //tgs2 support
- GLOB.revdata.DownloadPRDetails()
-
- load_motd()
- load_admins()
- LoadVerbs(/datum/verbs/menu)
- if(config.usewhitelist)
- load_whitelist()
- LoadBans()
-
- GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
-
- Master.Initialize(10, FALSE)
-
- if(config.irc_announce_new_game)
- IRCBroadcast("New round starting on [SSmapping.config.map_name]!")
-
-/world/proc/SetupExternalRSC()
-#if (PRELOAD_RSC == 0)
- external_rsc_urls = world.file2list("config/external_rsc_urls.txt","\n")
- var/i=1
- while(i<=external_rsc_urls.len)
- if(external_rsc_urls[i])
- i++
- else
- external_rsc_urls.Cut(i,i+1)
-#endif
-
-/world/proc/CheckSchemaVersion()
- if(config.sql_enabled)
- if(SSdbcore.Connect())
- log_world("Database connection established.")
- var/datum/DBQuery/db_version = SSdbcore.NewQuery("SELECT major, minor FROM [format_table_name("schema_version")]")
- db_version.Execute()
- if(db_version.NextRow())
- var/db_major = db_version.item[1]
- var/db_minor = db_version.item[2]
- if(db_major < DB_MAJOR_VERSION || db_minor < DB_MINOR_VERSION)
- message_admins("db schema ([db_major].[db_minor]) is behind latest tg schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors")
- log_sql("db schema ([db_major].[db_minor]) is behind latest tg schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors")
- else
- message_admins("Could not get schema version from db")
- else
- log_world("Your server failed to establish a connection with the database.")
-
-/world/proc/SetRoundID()
- if(config.sql_enabled)
- if(SSdbcore.Connect())
- var/datum/DBQuery/query_round_start = SSdbcore.NewQuery("INSERT INTO [format_table_name("round")] (start_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]')")
- query_round_start.Execute()
- var/datum/DBQuery/query_round_last_id = SSdbcore.NewQuery("SELECT LAST_INSERT_ID()")
- query_round_last_id.Execute()
- if(query_round_last_id.NextRow())
- GLOB.round_id = query_round_last_id.item[1]
-
-/world/proc/SetupLogs()
- GLOB.log_directory = "data/logs/[time2text(world.realtime, "YYYY/MM/DD")]/round-"
- if(GLOB.round_id)
- GLOB.log_directory += "[GLOB.round_id]"
- else
- GLOB.log_directory += "[replacetext(time_stamp(), ":", ".")]"
- GLOB.world_game_log = file("[GLOB.log_directory]/game.log")
- GLOB.world_attack_log = file("[GLOB.log_directory]/attack.log")
- GLOB.world_runtime_log = file("[GLOB.log_directory]/runtime.log")
- GLOB.world_href_log = file("[GLOB.log_directory]/hrefs.html")
- GLOB.world_game_log << "\n\nStarting up round ID [GLOB.round_id]. [time_stamp()]\n---------------------"
- GLOB.world_attack_log << "\n\nStarting up round ID [GLOB.round_id]. [time_stamp()]\n---------------------"
- GLOB.world_runtime_log << "\n\nStarting up round ID [GLOB.round_id]. [time_stamp()]\n---------------------"
- GLOB.changelog_hash = md5('html/changelog.html') //used for telling if the changelog has changed recently
- if(fexists(GLOB.config_error_log))
- fcopy(GLOB.config_error_log, "[GLOB.log_directory]/config_error.log")
- fdel(GLOB.config_error_log)
-
- if(GLOB.round_id)
- log_game("Round ID: [GLOB.round_id]")
-
-/world/Topic(T, addr, master, key)
- var/list/input = params2list(T)
-
- var/pinging = ("ping" in input)
- var/playing = ("players" in input)
-
- if(!pinging && !playing && config && config.log_world_topic)
- GLOB.world_game_log << "TOPIC: \"[T]\", from:[addr], master:[master], key:[key]"
-
- if(input[SERVICE_CMD_PARAM_KEY])
- return ServiceCommand(input)
- var/key_valid = (global.comms_allowed && input["key"] == global.comms_key)
-
- if(pinging)
- var/x = 1
- for (var/client/C in GLOB.clients)
- x++
- return x
-
- else if(playing)
- var/n = 0
- for(var/mob/M in GLOB.player_list)
- if(M.client)
- n++
- return n
-
- else if("ircstatus" in input) //tgs2 support
- var/static/last_irc_status = 0
- if(world.time - last_irc_status < 50)
- return
- var/list/adm = get_admin_counts()
- var/list/allmins = adm["total"]
- var/status = "Admins: [allmins.len] (Active: [english_list(adm["present"])] AFK: [english_list(adm["afk"])] Stealth: [english_list(adm["stealth"])] Skipped: [english_list(adm["noflags"])]). "
- status += "Players: [GLOB.clients.len] (Active: [get_active_player_count(0,1,0)]). Mode: [SSticker.mode.name]."
- send2irc("Status", status)
- last_irc_status = world.time
-
- else if("status" in input)
- var/list/s = list()
- s["version"] = GLOB.game_version
- s["mode"] = GLOB.master_mode
- s["respawn"] = config ? GLOB.abandon_allowed : 0
- s["enter"] = GLOB.enter_allowed
- s["vote"] = config.allow_vote_mode
- s["ai"] = config.allow_ai
- s["host"] = host ? host : null
- s["active_players"] = get_active_player_count()
- s["players"] = GLOB.clients.len
- s["revision"] = GLOB.revdata.commit
- s["revision_date"] = GLOB.revdata.date
-
- var/list/adm = get_admin_counts()
- var/list/presentmins = adm["present"]
- var/list/afkmins = adm["afk"]
- s["admins"] = presentmins.len + afkmins.len //equivalent to the info gotten from adminwho
- s["gamestate"] = SSticker.current_state
-
- s["map_name"] = SSmapping.config.map_name
-
- if(key_valid && SSticker.HasRoundStarted())
- s["real_mode"] = SSticker.mode.name
- // Key-authed callers may know the truth behind the "secret"
-
- s["security_level"] = get_security_level()
- s["round_duration"] = SSticker ? round((world.time-SSticker.round_start_time)/10) : 0
- // Amount of world's ticks in seconds, useful for calculating round duration
-
- if(SSshuttle && SSshuttle.emergency)
- s["shuttle_mode"] = SSshuttle.emergency.mode
- // Shuttle status, see /__DEFINES/stat.dm
- s["shuttle_timer"] = SSshuttle.emergency.timeLeft()
- // Shuttle timer, in seconds
-
- return list2params(s)
-
- else if("announce" in input)
- if(!key_valid)
- return "Bad Key"
- else
- AnnouncePR(input["announce"], json_decode(input["payload"]))
-
- else if("crossmessage" in input)
- if(!key_valid)
- return
- else
- if(input["crossmessage"] == "Ahelp")
- relay_msg_admins("HELP: [input["source"]] [input["message_sender"]]: [input["message"]]")
- if(input["crossmessage"] == "Comms_Console")
- minor_announce(input["message"], "Incoming message from [input["message_sender"]]")
- for(var/obj/machinery/computer/communications/CM in GLOB.machines)
- CM.overrideCooldown()
- if(input["crossmessage"] == "News_Report")
- minor_announce(input["message"], "Breaking Update From [input["message_sender"]]")
-
- else if("adminmsg" in input) //tgs2 support
- if(!key_valid)
- return "Bad Key"
- else
- return IrcPm(input["adminmsg"],input["msg"],input["sender"])
-
- else if("namecheck" in input) //tgs2 support
- if(!key_valid)
- return "Bad Key"
- else
- log_admin("IRC Name Check: [input["sender"]] on [input["namecheck"]]")
- message_admins("IRC name checking on [input["namecheck"]] from [input["sender"]]")
- return keywords_lookup(input["namecheck"],1)
- else if("adminwho" in input) //tgs2 support
- if(!key_valid)
- return "Bad Key"
- else
- return ircadminwho()
- else if("server_hop" in input)
- show_server_hop_transfer_screen(input["server_hop"])
-
-#define PR_ANNOUNCEMENTS_PER_ROUND 5 //The number of unique PR announcements allowed per round
- //This makes sure that a single person can only spam 3 reopens and 3 closes before being ignored
-
-/world/proc/AnnouncePR(announcement, list/payload)
- var/static/list/PRcounts = list() //PR id -> number of times announced this round
- var/id = "[payload["pull_request"]["id"]]"
- if(!PRcounts[id])
- PRcounts[id] = 1
- else
- ++PRcounts[id]
- if(PRcounts[id] > PR_ANNOUNCEMENTS_PER_ROUND)
- return
-
- var/final_composed = "PR: [announcement]"
- for(var/client/C in GLOB.clients)
- C.AnnouncePR(final_composed)
-
-/world/Reboot(reason = 0, fast_track = FALSE)
- ServiceReboot() //handles alternative actions if necessary
- if (reason || fast_track) //special reboot, do none of the normal stuff
- if (usr)
- log_admin("[key_name(usr)] Has requested an immediate world restart via client side debugging tools")
- message_admins("[key_name_admin(usr)] Has requested an immediate world restart via client side debugging tools")
- to_chat(world, "Rebooting World immediately due to host request")
- else
- to_chat(world, "Rebooting world...")
- Master.Shutdown() //run SS shutdowns
- log_world("World rebooted at [time_stamp()]")
- ..()
-
-/world/proc/load_motd()
- GLOB.join_motd = file2text("config/motd.txt") + "
" + GLOB.revdata.GetTestMergeInfo()
-
-/world/proc/update_status()
- var/s = ""
-
- if (config && config.server_name)
- s += "[config.server_name] — "
-
- s += "[station_name()]";
- s += " ("
- s += "" //Change this to wherever you want the hub to link to.
- s += "Default" //Replace this with something else. Or ever better, delete it and uncomment the game version.
- s += ""
- s += ")"
-
- var/list/features = list()
-
- if(GLOB.master_mode)
- features += GLOB.master_mode
-
- if (!GLOB.enter_allowed)
- features += "closed"
-
- features += GLOB.abandon_allowed ? "respawn" : "no respawn"
-
- if (config && config.allow_vote_mode)
- features += "vote"
-
- if (config && config.allow_ai)
- features += "AI allowed"
-
- var/n = 0
- for (var/mob/M in GLOB.player_list)
- if (M.client)
- n++
-
- if (n > 1)
- features += "~[n] players"
- else if (n > 0)
- features += "~[n] player"
-
- if (!host && config && config.hostedby)
- features += "hosted by [config.hostedby]"
-
- if (features)
- s += ": [jointext(features, ", ")]"
-
- status = s
-
-/world/proc/update_hub_visibility(new_visibility)
- if(new_visibility == GLOB.hub_visibility)
- return
- GLOB.hub_visibility = new_visibility
- if(GLOB.hub_visibility)
- hub_password = "kMZy3U5jJHSiBQjr"
- else
- hub_password = "SORRYNOPASSWORD"
diff --git a/code/world.dm.rej b/code/world.dm.rej
new file mode 100644
index 0000000000..e82c17e503
--- /dev/null
+++ b/code/world.dm.rej
@@ -0,0 +1,301 @@
+diff a/code/world.dm b/code/world.dm (rejected hunks)
+@@ -10,299 +13,3 @@
+ #ifdef GC_FAILURE_HARD_LOOKUP
+ loop_checks = FALSE
+ #endif
+-
+-/world/New()
+- log_world("World loaded at [time_stamp()]")
+-
+- SetupExternalRSC()
+-
+- GLOB.config_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = file("data/logs/config_error.log") //temporary file used to record errors with loading config, moved to log directory once logging is set bl
+-
+- make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
+-
+- config = new
+-
+- CheckSchemaVersion()
+- SetRoundID()
+-
+- SetupLogs()
+-
+- if(!RunningService()) //tgs2 support
+- GLOB.revdata.DownloadPRDetails()
+-
+- load_motd()
+- load_admins()
+- LoadVerbs(/datum/verbs/menu)
+- if(config.usewhitelist)
+- load_whitelist()
+- LoadBans()
+-
+- GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
+-
+- Master.Initialize(10, FALSE)
+-
+- if(config.irc_announce_new_game)
+- IRCBroadcast("New round starting on [SSmapping.config.map_name]!")
+-
+-/world/proc/SetupExternalRSC()
+-#if (PRELOAD_RSC == 0)
+- external_rsc_urls = world.file2list("config/external_rsc_urls.txt","\n")
+- var/i=1
+- while(i<=external_rsc_urls.len)
+- if(external_rsc_urls[i])
+- i++
+- else
+- external_rsc_urls.Cut(i,i+1)
+-#endif
+-
+-/world/proc/CheckSchemaVersion()
+- if(config.sql_enabled)
+- if(SSdbcore.Connect())
+- log_world("Database connection established.")
+- var/datum/DBQuery/query_db_version = SSdbcore.NewQuery("SELECT major, minor FROM [format_table_name("schema_revision")] ORDER BY date DESC LIMIT 1")
+- query_db_version.Execute()
+- if(query_db_version.NextRow())
+- var/db_major = text2num(query_db_version.item[1])
+- var/db_minor = text2num(query_db_version.item[2])
+- if(db_major < DB_MAJOR_VERSION || db_minor < DB_MINOR_VERSION)
+- message_admins("Database schema ([db_major].[db_minor]) is behind latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors")
+- log_sql("Database schema ([db_major].[db_minor]) is behind latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors")
+- else
+- message_admins("Could not get schema version from database")
+- else
+- log_world("Your server failed to establish a connection with the database.")
+-
+-/world/proc/SetRoundID()
+- if(config.sql_enabled)
+- if(SSdbcore.Connect())
+- var/datum/DBQuery/query_round_start = SSdbcore.NewQuery("INSERT INTO [format_table_name("round")] (start_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]')")
+- query_round_start.Execute()
+- var/datum/DBQuery/query_round_last_id = SSdbcore.NewQuery("SELECT LAST_INSERT_ID()")
+- query_round_last_id.Execute()
+- if(query_round_last_id.NextRow())
+- GLOB.round_id = query_round_last_id.item[1]
+-
+-/world/proc/SetupLogs()
+- GLOB.log_directory = "data/logs/[time2text(world.realtime, "YYYY/MM/DD")]/round-"
+- if(GLOB.round_id)
+- GLOB.log_directory += "[GLOB.round_id]"
+- else
+- GLOB.log_directory += "[replacetext(time_stamp(), ":", ".")]"
+- GLOB.world_game_log = file("[GLOB.log_directory]/game.log")
+- GLOB.world_attack_log = file("[GLOB.log_directory]/attack.log")
+- GLOB.world_runtime_log = file("[GLOB.log_directory]/runtime.log")
+- GLOB.world_href_log = file("[GLOB.log_directory]/hrefs.html")
+- GLOB.world_game_log << "\n\nStarting up round ID [GLOB.round_id]. [time_stamp()]\n---------------------"
+- GLOB.world_attack_log << "\n\nStarting up round ID [GLOB.round_id]. [time_stamp()]\n---------------------"
+- GLOB.world_runtime_log << "\n\nStarting up round ID [GLOB.round_id]. [time_stamp()]\n---------------------"
+- GLOB.changelog_hash = md5('html/changelog.html') //used for telling if the changelog has changed recently
+- if(fexists(GLOB.config_error_log))
+- fcopy(GLOB.config_error_log, "[GLOB.log_directory]/config_error.log")
+- fdel(GLOB.config_error_log)
+-
+- if(GLOB.round_id)
+- log_game("Round ID: [GLOB.round_id]")
+-
+-/world/Topic(T, addr, master, key)
+- var/list/input = params2list(T)
+-
+- var/pinging = ("ping" in input)
+- var/playing = ("players" in input)
+-
+- if(!pinging && !playing && config && config.log_world_topic)
+- GLOB.world_game_log << "TOPIC: \"[T]\", from:[addr], master:[master], key:[key]"
+-
+- if(input[SERVICE_CMD_PARAM_KEY])
+- return ServiceCommand(input)
+- var/key_valid = (global.comms_allowed && input["key"] == global.comms_key)
+-
+- if(pinging)
+- var/x = 1
+- for (var/client/C in GLOB.clients)
+- x++
+- return x
+-
+- else if(playing)
+- var/n = 0
+- for(var/mob/M in GLOB.player_list)
+- if(M.client)
+- n++
+- return n
+-
+- else if("ircstatus" in input) //tgs2 support
+- var/static/last_irc_status = 0
+- if(world.time - last_irc_status < 50)
+- return
+- var/list/adm = get_admin_counts()
+- var/list/allmins = adm["total"]
+- var/status = "Admins: [allmins.len] (Active: [english_list(adm["present"])] AFK: [english_list(adm["afk"])] Stealth: [english_list(adm["stealth"])] Skipped: [english_list(adm["noflags"])]). "
+- status += "Players: [GLOB.clients.len] (Active: [get_active_player_count(0,1,0)]). Mode: [SSticker.mode.name]."
+- send2irc("Status", status)
+- last_irc_status = world.time
+-
+- else if("status" in input)
+- var/list/s = list()
+- s["version"] = GLOB.game_version
+- s["mode"] = GLOB.master_mode
+- s["respawn"] = config ? GLOB.abandon_allowed : 0
+- s["enter"] = GLOB.enter_allowed
+- s["vote"] = config.allow_vote_mode
+- s["ai"] = config.allow_ai
+- s["host"] = host ? host : null
+- s["active_players"] = get_active_player_count()
+- s["players"] = GLOB.clients.len
+- s["revision"] = GLOB.revdata.commit
+- s["revision_date"] = GLOB.revdata.date
+-
+- var/list/adm = get_admin_counts()
+- var/list/presentmins = adm["present"]
+- var/list/afkmins = adm["afk"]
+- s["admins"] = presentmins.len + afkmins.len //equivalent to the info gotten from adminwho
+- s["gamestate"] = SSticker.current_state
+-
+- s["map_name"] = SSmapping.config.map_name
+-
+- if(key_valid && SSticker.HasRoundStarted())
+- s["real_mode"] = SSticker.mode.name
+- // Key-authed callers may know the truth behind the "secret"
+-
+- s["security_level"] = get_security_level()
+- s["round_duration"] = SSticker ? round((world.time-SSticker.round_start_time)/10) : 0
+- // Amount of world's ticks in seconds, useful for calculating round duration
+-
+- if(SSshuttle && SSshuttle.emergency)
+- s["shuttle_mode"] = SSshuttle.emergency.mode
+- // Shuttle status, see /__DEFINES/stat.dm
+- s["shuttle_timer"] = SSshuttle.emergency.timeLeft()
+- // Shuttle timer, in seconds
+-
+- return list2params(s)
+-
+- else if("announce" in input)
+- if(!key_valid)
+- return "Bad Key"
+- else
+- AnnouncePR(input["announce"], json_decode(input["payload"]))
+-
+- else if("crossmessage" in input)
+- if(!key_valid)
+- return
+- else
+- if(input["crossmessage"] == "Ahelp")
+- relay_msg_admins("HELP: [input["source"]] [input["message_sender"]]: [input["message"]]")
+- if(input["crossmessage"] == "Comms_Console")
+- minor_announce(input["message"], "Incoming message from [input["message_sender"]]")
+- for(var/obj/machinery/computer/communications/CM in GLOB.machines)
+- CM.overrideCooldown()
+- if(input["crossmessage"] == "News_Report")
+- minor_announce(input["message"], "Breaking Update From [input["message_sender"]]")
+-
+- else if("adminmsg" in input) //tgs2 support
+- if(!key_valid)
+- return "Bad Key"
+- else
+- return IrcPm(input["adminmsg"],input["msg"],input["sender"])
+-
+- else if("namecheck" in input) //tgs2 support
+- if(!key_valid)
+- return "Bad Key"
+- else
+- log_admin("IRC Name Check: [input["sender"]] on [input["namecheck"]]")
+- message_admins("IRC name checking on [input["namecheck"]] from [input["sender"]]")
+- return keywords_lookup(input["namecheck"],1)
+- else if("adminwho" in input) //tgs2 support
+- if(!key_valid)
+- return "Bad Key"
+- else
+- return ircadminwho()
+- else if("server_hop" in input)
+- show_server_hop_transfer_screen(input["server_hop"])
+-
+-#define PR_ANNOUNCEMENTS_PER_ROUND 5 //The number of unique PR announcements allowed per round
+- //This makes sure that a single person can only spam 3 reopens and 3 closes before being ignored
+-
+-/world/proc/AnnouncePR(announcement, list/payload)
+- var/static/list/PRcounts = list() //PR id -> number of times announced this round
+- var/id = "[payload["pull_request"]["id"]]"
+- if(!PRcounts[id])
+- PRcounts[id] = 1
+- else
+- ++PRcounts[id]
+- if(PRcounts[id] > PR_ANNOUNCEMENTS_PER_ROUND)
+- return
+-
+- var/final_composed = "PR: [announcement]"
+- for(var/client/C in GLOB.clients)
+- C.AnnouncePR(final_composed)
+-
+-/world/Reboot(reason = 0, fast_track = FALSE)
+- ServiceReboot() //handles alternative actions if necessary
+- if (reason || fast_track) //special reboot, do none of the normal stuff
+- if (usr)
+- log_admin("[key_name(usr)] Has requested an immediate world restart via client side debugging tools")
+- message_admins("[key_name_admin(usr)] Has requested an immediate world restart via client side debugging tools")
+- to_chat(world, "Rebooting World immediately due to host request")
+- else
+- to_chat(world, "Rebooting world...")
+- Master.Shutdown() //run SS shutdowns
+- log_world("World rebooted at [time_stamp()]")
+- ..()
+-
+-/world/proc/load_motd()
+- GLOB.join_motd = file2text("config/motd.txt") + "
" + GLOB.revdata.GetTestMergeInfo()
+-
+-/world/proc/update_status()
+- var/s = ""
+-
+- if (config && config.server_name)
+- s += "[config.server_name] — "
+-
+- s += "[station_name()]";
+- s += " ("
+- s += "" //Change this to wherever you want the hub to link to.
+- s += "Default" //Replace this with something else. Or ever better, delete it and uncomment the game version.
+- s += ""
+- s += ")"
+-
+- var/list/features = list()
+-
+- if(GLOB.master_mode)
+- features += GLOB.master_mode
+-
+- if (!GLOB.enter_allowed)
+- features += "closed"
+-
+- features += GLOB.abandon_allowed ? "respawn" : "no respawn"
+-
+- if (config && config.allow_vote_mode)
+- features += "vote"
+-
+- if (config && config.allow_ai)
+- features += "AI allowed"
+-
+- var/n = 0
+- for (var/mob/M in GLOB.player_list)
+- if (M.client)
+- n++
+-
+- if (n > 1)
+- features += "~[n] players"
+- else if (n > 0)
+- features += "~[n] player"
+-
+- if (!host && config && config.hostedby)
+- features += "hosted by [config.hostedby]"
+-
+- if (features)
+- s += ": [jointext(features, ", ")]"
+-
+- status = s
+-
+-/world/proc/update_hub_visibility(new_visibility)
+- if(new_visibility == GLOB.hub_visibility)
+- return
+- GLOB.hub_visibility = new_visibility
+- if(GLOB.hub_visibility)
+- hub_password = "kMZy3U5jJHSiBQjr"
+- else
+- hub_password = "SORRYNOPASSWORD"
diff --git a/html/changelogs/AutoChangeLog-pr-2231.yml b/html/changelogs/AutoChangeLog-pr-2231.yml
new file mode 100644
index 0000000000..c25b4b2b49
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2231.yml
@@ -0,0 +1,4 @@
+author: "Xhuis"
+delete-after: True
+changes:
+ - tweak: "Spell action buttons now have their description in a tooltip."
diff --git a/html/changelogs/AutoChangeLog-pr-2278.yml b/html/changelogs/AutoChangeLog-pr-2278.yml
new file mode 100644
index 0000000000..111ae24812
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2278.yml
@@ -0,0 +1,4 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - bugfix: "Fixed hair sticking through headgear."
diff --git a/html/changelogs/AutoChangeLog-pr-2346.yml b/html/changelogs/AutoChangeLog-pr-2346.yml
new file mode 100644
index 0000000000..c42300a173
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2346.yml
@@ -0,0 +1,4 @@
+author: "More Robust Than You"
+delete-after: True
+changes:
+ - tweak: "The wiki button now asks what page you want to be taken to"
diff --git a/html/changelogs/AutoChangeLog-pr-2350.yml b/html/changelogs/AutoChangeLog-pr-2350.yml
new file mode 100644
index 0000000000..07e0f51b62
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2350.yml
@@ -0,0 +1,4 @@
+author: "Xhuis"
+delete-after: True
+changes:
+ - bugfix: "Minebots no longer lack icons for their action buttons."
diff --git a/html/changelogs/AutoChangeLog-pr-2356.yml b/html/changelogs/AutoChangeLog-pr-2356.yml
new file mode 100644
index 0000000000..218da24865
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2356.yml
@@ -0,0 +1,4 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - imageadd: "Adds icon_states to the unused and used Eldritch whetstones. Sprites by Fury McFlurry."
diff --git a/html/changelogs/AutoChangeLog-pr-2359.yml b/html/changelogs/AutoChangeLog-pr-2359.yml
new file mode 100644
index 0000000000..8455963dc6
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2359.yml
@@ -0,0 +1,4 @@
+author: "Joan"
+delete-after: True
+changes:
+ - imageadd: "Ported CEV-Eris's APC sprites."
diff --git a/html/changelogs/AutoChangeLog-pr-2363.yml b/html/changelogs/AutoChangeLog-pr-2363.yml
new file mode 100644
index 0000000000..e8f5b574ae
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2363.yml
@@ -0,0 +1,4 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - tweak: "Canisters don't flash red lights anymore when empty."
diff --git a/html/changelogs/AutoChangeLog-pr-2371.yml b/html/changelogs/AutoChangeLog-pr-2371.yml
new file mode 100644
index 0000000000..ec1810b8a6
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2371.yml
@@ -0,0 +1,4 @@
+author: "Xhuis"
+delete-after: True
+changes:
+ - bugfix: "The Resurrect Cultist rune now works as intended."
diff --git a/html/changelogs/AutoChangeLog-pr-2376.yml b/html/changelogs/AutoChangeLog-pr-2376.yml
new file mode 100644
index 0000000000..1d1a2007b5
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2376.yml
@@ -0,0 +1,4 @@
+author: "ShizCalev"
+delete-after: True
+changes:
+ - bugfix: "The Singularity, Tesla energy ball, tears in the fabric of reality, and Narsie will no longer be frozen by freon."
diff --git a/html/changelogs/AutoChangeLog-pr-2377.yml b/html/changelogs/AutoChangeLog-pr-2377.yml
new file mode 100644
index 0000000000..4996a03563
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2377.yml
@@ -0,0 +1,4 @@
+author: "More Robust Than You"
+delete-after: True
+changes:
+ - bugfix: "Fixes mining hardsuit heat_protection"
diff --git a/html/changelogs/AutoChangeLog-pr-2399.yml b/html/changelogs/AutoChangeLog-pr-2399.yml
new file mode 100644
index 0000000000..2d162a5edf
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2399.yml
@@ -0,0 +1,4 @@
+author: "More Robust Than You"
+delete-after: True
+changes:
+ - rscadd: "Blobs can now sense when they're being cuddled!"
diff --git a/html/changelogs/AutoChangeLog-pr-2402.yml b/html/changelogs/AutoChangeLog-pr-2402.yml
new file mode 100644
index 0000000000..0ef97907fd
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2402.yml
@@ -0,0 +1,5 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - imageadd: "Nanotrasen redesigned the area power controllers!"
+ - imageadd: "Thanks Xhuis for the contrast tweak on APCs"
diff --git a/html/changelogs/AutoChangeLog-pr-2408.yml b/html/changelogs/AutoChangeLog-pr-2408.yml
new file mode 100644
index 0000000000..92f33a9292
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-2408.yml
@@ -0,0 +1,4 @@
+author: "Xhuis"
+delete-after: True
+changes:
+ - soundadd: "The station's explosion now uses a new (or old) sound."
diff --git a/icons/mob/hair_extensions.dmi b/icons/mob/hair_extensions.dmi
index bd2adda94b..5a4ee36157 100644
Binary files a/icons/mob/hair_extensions.dmi and b/icons/mob/hair_extensions.dmi differ
diff --git a/icons/mob/human_parts_greyscale.dmi b/icons/mob/human_parts_greyscale.dmi
index 968e12949b..a06f490fa7 100644
Binary files a/icons/mob/human_parts_greyscale.dmi and b/icons/mob/human_parts_greyscale.dmi differ
diff --git a/icons/mob/inhands/equipment/custodial_lefthand.dmi b/icons/mob/inhands/equipment/custodial_lefthand.dmi
index 80c77cf8df..b099ee1524 100644
Binary files a/icons/mob/inhands/equipment/custodial_lefthand.dmi and b/icons/mob/inhands/equipment/custodial_lefthand.dmi differ
diff --git a/icons/mob/inhands/equipment/custodial_righthand.dmi b/icons/mob/inhands/equipment/custodial_righthand.dmi
index fb64834ce9..8e0174150a 100644
Binary files a/icons/mob/inhands/equipment/custodial_righthand.dmi and b/icons/mob/inhands/equipment/custodial_righthand.dmi differ
diff --git a/icons/mob/mam_body_markings.dmi b/icons/mob/mam_body_markings.dmi
index a50181340d..737fa15c42 100644
Binary files a/icons/mob/mam_body_markings.dmi and b/icons/mob/mam_body_markings.dmi differ
diff --git a/icons/mob/xeno_parts_greyscale.dmi b/icons/mob/xeno_parts_greyscale.dmi
new file mode 100644
index 0000000000..44456309a7
Binary files /dev/null and b/icons/mob/xeno_parts_greyscale.dmi differ
diff --git a/icons/obj/kitchen.dmi b/icons/obj/kitchen.dmi
index a8f7708c46..87b2b46a2b 100644
Binary files a/icons/obj/kitchen.dmi and b/icons/obj/kitchen.dmi differ
diff --git a/icons/obj/machines/telecomms.dmi b/icons/obj/machines/telecomms.dmi
index 7f5f05e3af..4a6988f88e 100644
Binary files a/icons/obj/machines/telecomms.dmi and b/icons/obj/machines/telecomms.dmi differ
diff --git a/icons/obj/power.dmi b/icons/obj/power.dmi
index f3b2233283..e1604715ac 100644
Binary files a/icons/obj/power.dmi and b/icons/obj/power.dmi differ
diff --git a/icons/obj/wallframe.dmi b/icons/obj/wallframe.dmi
index 0e416cac77..70149901e3 100644
Binary files a/icons/obj/wallframe.dmi and b/icons/obj/wallframe.dmi differ
diff --git a/interface/interface.dm b/interface/interface.dm
index 253738064b..9ee5309585 100644
--- a/interface/interface.dm
+++ b/interface/interface.dm
@@ -1,12 +1,14 @@
//Please use mob or src (not usr) in these procs. This way they can be called in the same fashion as procs.
-/client/verb/wiki()
+/client/verb/wiki(query as text)
set name = "wiki"
- set desc = "Visit the wiki."
+ set desc = "Type what you want to know about. This will open the wiki in your web browser. Type nothing to go to the main page."
set hidden = 1
if(config.wikiurl)
- if(alert("This will open the wiki in your browser. Are you sure?",,"Yes","No")=="No")
- return
- src << link(config.wikiurl)
+ if(query)
+ var/output = config.wikiurl + "/index.php?title=Special%3ASearch&profile=default&search=" + query
+ src << link(output)
+ else if (query != null)
+ src << link(config.wikiurl)
else
to_chat(src, "The wiki URL is not set in the server configuration.")
return
diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm
index 6f38560b92..8576be384b 100644
--- a/interface/stylesheet.dm
+++ b/interface/stylesheet.dm
@@ -151,7 +151,7 @@ h1.alert, h2.alert {color: #000000;}
.clown {color: #FF69Bf; font-size: 3; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
-BIG IMG.icon {width: 32px; height: 32px;}
+.icon {height: 1em; width: auto;}
.memo {color: #638500; text-align: center;}
.memoedit {text-align: center; font-size: 2;}
diff --git a/power.dmi b/power.dmi
new file mode 100644
index 0000000000..d0066b96de
Binary files /dev/null and b/power.dmi differ
diff --git a/sound/effects/explosion_distant.ogg b/sound/effects/explosion_distant.ogg
new file mode 100644
index 0000000000..d9976c51fe
Binary files /dev/null and b/sound/effects/explosion_distant.ogg differ
diff --git a/strings/brain_damage_lines.json b/strings/brain_damage_lines.json
index ce3e726dbc..af040d5ba0 100644
--- a/strings/brain_damage_lines.json
+++ b/strings/brain_damage_lines.json
@@ -1,17 +1,17 @@
{
"brain_damage": [
- "IM A PONY NEEEEEEIIIIIIIIIGH",
+ "@pick(semicolon)IM A PONY NEEEEEEIIIIIIIIIGH",
"without oxigen blob don't evoluate?",
- "CAPTAINS A COMDOM",
- "@pick(faggot_traitor) @pick(george) @pick(mellens) is grifing me HALP!!!",
+ "@pick(semicolon)CAPTAINS A COMDOM",
+ "@pick(semicolon)@pick(faggot_traitor) @pick(george) @pick(mellens) is grifing me HALP!!!",
"can u give me @pick(mutations)?",
"THe saiyans screwed",
"Bi is THE BEST OF BOTH WORLDS>",
- "I WANNA PET TEH monkeyS",
+ "@pick(semicolon)I WANNA PET TEH monkeyS",
"stop grifing me!!!!",
"SOTP IT#",
"shiggey diggey!!",
- "A PIRATE APPEAR",
+ "@pick(semicolon)A PIRATE APPEAR",
"FUS RO DAH",
"fucking 4rries!",
"stat me",
@@ -136,7 +136,8 @@
"random_gibberish": [
"g",
"squid",
- "r"
+ "r",
+ "carbon dioxide"
],
"y_replacements": [
@@ -171,6 +172,19 @@
"abdoocters"
],
+ "bug": [
+ "",
+ "IS TIS A BUG??",
+ "SI IST A BUGG/",
+ "BUG!!!"
+ ],
+
+ "semicolon": [
+ "",
+ ";",
+ ".h"
+ ],
+
"roles": [
"heds",
"ceptin",
diff --git a/strings/brain_damage_lines.json.rej b/strings/brain_damage_lines.json.rej
new file mode 100644
index 0000000000..6d8e1cdb62
--- /dev/null
+++ b/strings/brain_damage_lines.json.rej
@@ -0,0 +1,10 @@
+diff a/strings/brain_damage_lines.json b/strings/brain_damage_lines.json (rejected hunks)
+@@ -131,7 +131,7 @@
+ "",
+ "IS TIS A BUG??",
+ "SI IST A BUGG/",
+- "BUG!!!"
++ "BUG!!!"
+ ],
+
+ "semicolon": [
diff --git a/strings/hallucination.json b/strings/hallucination.json
new file mode 100644
index 0000000000..b28c70db4a
--- /dev/null
+++ b/strings/hallucination.json
@@ -0,0 +1,229 @@
+{
+ "suspicion": [
+ "I'm watching you...",
+ "I know what you're doing",
+ "What are you hiding?",
+ "I saw that"
+ ],
+
+ "greetings": [
+ "",
+ "Hey, ",
+ "Hi ",
+ "Hello ",
+ "Wait, ",
+ "It's "
+ ],
+
+ "getout": [
+ "Get out",
+ "Get out!",
+ "Go away",
+ "Fuck off",
+ "OUT!",
+ "Out!"
+ ],
+
+ "weird": [
+ "Kchck-Chkck? Kchchck!",
+ "Kchckchk...",
+ "EEEeeeeEEEE",
+ "khhhhh",
+ "#@§*&£",
+ "H**p m*",
+ "H-hhhhh..."
+ ],
+
+ "didyouhearthat": [
+ "Did you hear that?",
+ "Did you see that?",
+ "What was that?"
+ ],
+
+ "imatraitor": [
+ "Hail Ratvar",
+ "Hail Nar'Sie",
+ "Hey, i've got some TC left, want something?",
+ "Viva!",
+ "I'll spare you if you don't tell anybody about me",
+ "Hey, are you a traitor too?",
+ "You're my target, but @pick(excuses)",
+ "Are you mr. @pick(ling_names)?"
+ ],
+
+ "excuses": [
+ "i like you, so i'll spare you",
+ "i don't really feel like following objectives today",
+ "i'm not robust enough to fight you",
+ "who cares",
+ "i'll kill you later"
+ ]
+
+ "ling_names": [
+ "Alpha",
+ "Beta",
+ "Gamma",
+ "Delta",
+ "Epsilon",
+ "Eta",
+ "Theta",
+ "Lambda",
+ "Mu",
+ "Xi",
+ "Rho",
+ "Sigma",
+ "Tau",
+ "Upsilon",
+ "Phi",
+ "Psi",
+ "Omega"
+ ]
+
+ "doubt": [
+ "Why?",
+ "What?",
+ "Wait, what?",
+ "Wait",
+ "Hold on",
+ "Uh..."
+ ],
+
+ "aggressive": [
+ "Give me that!",
+ "I'm going to kill you!",
+ "Fuck you!"
+ ],
+
+ "help": [
+ "HELP",
+ "HELP ME",
+ "HELP HIM",
+ "HELP HER",
+ "HELP THEM",
+ "HELP US",
+ "HELP YOURSELF"
+ ],
+
+ "escape": [
+ "RUN!!",
+ "They're behind me!",
+ "It's here!",
+ "Follow me!",
+ "Follow me"
+ ]
+
+ "infection_advice": [
+ "stay away",
+ "don't get close",
+ "be careful",
+ "help me",
+ "kill me"
+ ]
+
+ "people": [
+ "Captain",
+ "Hos",
+ "Cmo",
+ "Rd",
+ "Ce",
+ "Hop",
+ "Janitor",
+ "AI",
+ "Viro",
+ "Qm",
+ "[target.first_name()]"
+ ]
+
+ "accusations": [
+ "rogue",
+ "cult",
+ "a cultist",
+ "clockcult",
+ "a clock cultist",
+ "a revhead",
+ "a rev",
+ "a gang leader",
+ "a gangster",
+ "a traitor",
+ "a tator",
+ "a ling",
+ "a changeling"
+ ]
+
+ "threat": [
+ "Cult",
+ "Wizard",
+ "Blob",
+ "Ling",
+ "Ops",
+ "Swarmers",
+ "Revenant",
+ "Traitor",
+ "Harm",
+ "I hear flashing",
+ "Help"
+ ]
+
+ "location": [
+ "bridge",
+ "armory",
+ "sec",
+ "security",
+ "science",
+ "engineering",
+ "cargo",
+ "medbay",
+ "atmos",
+ "maint",
+ "hops office",
+ "captains office",
+ "chapel",
+ "library",
+ "tool storage",
+ "botany",
+ "kitchen",
+ "the ai sat"
+ ]
+
+ "advice": [
+ "Hmm...not sure about that.",
+ "Yes. You're doing the right thing.",
+ "No. Stop what you're doing.",
+ "You should be wary of that person.",
+ "Trust that person.",
+ "That person wants to kill you.",
+ "Kill that person. You know who.",
+ "You should go somewhere else. Quickly.",
+ "Good luck. You'll need it.",
+ "You have my permission. Do it."
+ ]
+
+ "chemicals": [
+ "Ooze",
+ "Fire",
+ "Earth",
+ "Lightning",
+ "Air",
+ "Magic",
+ "Spiders",
+ "Button",
+ "Surprise",
+ "Happiness",
+ "Despair",
+ "Blood",
+ "Awesome",
+ "Infinity",
+ "Electronics",
+ "Time",
+ "Space",
+ "Pain",
+ "Guts",
+ "Life",
+ "Death",
+ "Phlebotinium",
+ "Mana",
+ "Energy",
+ "?????"
+ ]
+
+}
diff --git a/tgstation.dme b/tgstation.dme
index 23ffe1fef1..1475d2335c 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -375,6 +375,7 @@
#include "code\game\shuttle_engines.dm"
#include "code\game\skincmd.dm"
#include "code\game\sound.dm"
+#include "code\game\world.dm"
#include "code\game\area\ai_monitored.dm"
#include "code\game\area\areas.dm"
#include "code\game\area\Space_Station_13_areas.dm"
diff --git a/tools/ColonCatcher/2015-10-25-colon_operator_log.txt b/tools/ColonCatcher/2015-10-25-colon_operator_log.txt
deleted file mode 100644
index f8908a0fda..0000000000
--- a/tools/ColonCatcher/2015-10-25-colon_operator_log.txt
+++ /dev/null
@@ -1,434 +0,0 @@
-..code\world.dm Lines: 27, 28, 98?, 102?, 119?, 149?, 230? Total Colons: 7
-..code\ATMOSPHERICS\atmospherics.dm Lines: 213? Total Colons: 1
-..code\ATMOSPHERICS\components\binary_devices\dp_vent_pump.dm Lines: 137? Total Colons: 1
-..code\ATMOSPHERICS\components\binary_devices\passive_gate.dm Lines: 134?, 163? Total Colons: 2
-..code\ATMOSPHERICS\components\binary_devices\pump.dm Lines: 43?, 139?, 167? Total Colons: 3
-..code\ATMOSPHERICS\components\binary_devices\valve.dm Lines: 25?, 33?, 38? Total Colons: 3
-..code\ATMOSPHERICS\components\binary_devices\volume_pump.dm Lines: 42?, 136?, 163? Total Colons: 3
-..code\ATMOSPHERICS\components\trinary_devices\filter.dm Lines: 66?, 69?, 214? Total Colons: 3
-..code\ATMOSPHERICS\components\trinary_devices\mixer.dm Lines: 36?, 39?, 151? Total Colons: 3
-..code\ATMOSPHERICS\components\unary_devices\cryo.dm Lines: 152?, 187?, 189, 190, 312?, 313? Total Colons: 7
-..code\ATMOSPHERICS\components\unary_devices\Freezer.dm Lines: 82?, 205? Total Colons: 2
-..code\ATMOSPHERICS\components\unary_devices\vent_pump.dm Lines: 175?, 196?, 197?, 228? Total Colons: 4
-..code\ATMOSPHERICS\components\unary_devices\vent_scrubber.dm Lines: 140?, 141? Total Colons: 2
-..code\ATMOSPHERICS\pipes\manifold.dm Lines: 28? Total Colons: 1
-..code\ATMOSPHERICS\pipes\manifold4w.dm Lines: 19? Total Colons: 1
-..code\ATMOSPHERICS\pipes\pipes.dm Lines: 30?, 32?, 33?, 34?, 43? Total Colons: 5
-..code\ATMOSPHERICS\pipes\heat_exchange\manifold.dm Lines: 25?, 51? Total Colons: 2
-..code\controllers\subsystem\air.dm Lines: 100 Total Colons: 1
-..code\controllers\subsystem\bots.dm Lines: 18, 20 Total Colons: 2
-..code\controllers\subsystem\diseases.dm Lines: 18 Total Colons: 1
-..code\controllers\subsystem\events.dm Lines: 41, 199?, 200? Total Colons: 3
-..code\controllers\subsystem\jobs.dm Lines: 370? Total Colons: 1
-..code\controllers\subsystem\machines.dm Lines: 41, 42, 43 Total Colons: 3
-..code\controllers\subsystem\mobs.dm Lines: 20 Total Colons: 1
-..code\controllers\subsystem\objects.dm Lines: 37 Total Colons: 1
-..code\controllers\subsystem\shuttles.dm Lines: 251?, 253, 261?, 262?, 284, 285 Total Colons: 6
-..code\controllers\subsystem\ticker.dm Lines: 382?, 405? Total Colons: 4
-..code\controllers\subsystem\voting.dm Lines: 203?, 211? Total Colons: 2
-..code\controllers\subsystem\shuttles\emergency.dm Lines: 52?, 65? Total Colons: 4
-..code\controllers\subsystem\shuttles\supply.dm Lines: 97, 316?, 347?, 488?, 505? Total Colons: 10
-..code\datums\browser.dm Lines: 79? Total Colons: 1
-..code\datums\datacore.dm Lines: 91?, 127?, 132?, 137?, 142?, 147?, 152?, 157?, 163?, 169?, 259? Total Colons: 23
-..code\datums\datumvars.dm Lines: 57?, 93 Total Colons: 3
-..code\datums\material_container.dm Lines: 194? Total Colons: 1
-..code\datums\mind.dm Lines: 228?, 229?, 290?, 581?, 633, 634, 643, 648, 720?, 1243, 1244, 1245 Total Colons: 13
-..code\datums\mutations.dm Lines: 34?, 135?, 329? Total Colons: 3
-..code\datums\recipe.dm Lines: 52?, 114?, 115? Total Colons: 3
-..code\datums\diseases\_disease.dm Lines: 125? Total Colons: 1
-..code\datums\helper_datums\teleport.dm Lines: 63?, 64?, 74?, 75? Total Colons: 4
-..code\datums\helper_datums\topic_input.dm Lines: 23?, 27?, 31?, 35?, 42?, 46?, 50?, 56?, 60? Total Colons: 9
-..code\datums\spells\dumbfire.dm Lines: 43 Total Colons: 1
-..code\datums\spells\knock.dm Lines: 21 Total Colons: 1
-..code\datums\spells\projectile.dm Lines: 35 Total Colons: 1
-..code\datums\wires\airlock.dm Lines: 37?, 38?, 39?, 40?, 41?, 42?, 43? Total Colons: 7
-..code\datums\wires\alarm.dm Lines: 21? Total Colons: 3
-..code\datums\wires\apc.dm Lines: 13? Total Colons: 3
-..code\datums\wires\autolathe.dm Lines: 13? Total Colons: 3
-..code\datums\wires\particle_accelerator.dm Lines: 50? Total Colons: 1
-..code\datums\wires\pizza_bomb.dm Lines: 45?, 46? Total Colons: 2
-..code\datums\wires\robot.dm Lines: 16?, 17?, 18? Total Colons: 4
-..code\datums\wires\r_n_d.dm Lines: 48?, 49?, 50? Total Colons: 3
-..code\datums\wires\syndicatebomb.dm Lines: 46?, 75? Total Colons: 2
-..code\datums\wires\vending.dm Lines: 28?, 29?, 30?, 31? Total Colons: 4
-..code\datums\wires\wires.dm Lines: 119?, 121? Total Colons: 2
-..code\game\atoms.dm Lines: 297? Total Colons: 1
-..code\game\atoms_movable.dm Lines: 181?, 182?, 216? Total Colons: 3
-..code\game\communications.dm Lines: 288 Total Colons: 3
-..code\game\data_huds.dm Lines: 35? Total Colons: 1
-..code\game\dna.dm Lines: 231? Total Colons: 1
-..code\game\say.dm Lines: 45?, 49? Total Colons: 2
-..code\game\sound.dm Lines: 72? Total Colons: 1
-..code\game\gamemodes\antag_spawner.dm Lines: 103, 104 Total Colons: 3
-..code\game\gamemodes\objective.dm Lines: 84?, 112?, 139?, 172?, 201?, 433, 806 Total Colons: 7
-..code\game\gamemodes\abduction\abduction_gear.dm Lines: 159? Total Colons: 1
-..code\game\gamemodes\abduction\machinery\experiment.dm Lines: 41?, 107? Total Colons: 2
-..code\game\gamemodes\blob\blob_finish.dm Lines: 47? Total Colons: 1
-..code\game\gamemodes\blob\blob_report.dm Lines: 64, 70, 76, 85 Total Colons: 4
-..code\game\gamemodes\changeling\evolution_menu.dm Lines: 59? Total Colons: 3
-..code\game\gamemodes\changeling\powers\adrenaline.dm Lines: 12? Total Colons: 1
-..code\game\gamemodes\changeling\powers\mutations.dm Lines: 83? Total Colons: 1
-..code\game\gamemodes\cult\cult.dm Lines: 44? Total Colons: 1
-..code\game\gamemodes\cult\runes.dm Lines: 705?, 706? Total Colons: 2
-..code\game\gamemodes\gang\dominator.dm Lines: 101?, 187? Total Colons: 2
-..code\game\gamemodes\gang\gang.dm Lines: 261?, 266? Total Colons: 2
-..code\game\gamemodes\gang\gang_datum.dm Lines: 43?, 53?, 121? Total Colons: 3
-..code\game\gamemodes\gang\gang_pen.dm Lines: 59? Total Colons: 1
-..code\game\gamemodes\gang\recaller.dm Lines: 48?, 51? Total Colons: 4
-..code\game\gamemodes\malfunction\malfunction.dm Lines: 63, 64, 65, 185, 188, 189, 192, 204, 205, 216, 218, 219, 221, 233, 234 Total Colons: 15
-..code\game\gamemodes\meteor\meteors.dm Lines: 177? Total Colons: 2
-..code\game\gamemodes\nuclear\nuclearbomb.dm Lines: 197?, 212?, 215?, 217?, 220?, 222?, 265?, 359, 359?, 360, 365, 383? Total Colons: 25
-..code\game\gamemodes\revolution\revolution.dm Lines: 265?, 266?, 286? Total Colons: 3
-..code\game\gamemodes\shadowling\shadowling.dm Lines: 304? Total Colons: 1
-..code\game\gamemodes\traitor\traitor.dm Lines: 335? Total Colons: 1
-..code\game\gamemodes\wizard\artefact.dm Lines: 148? Total Colons: 1
-..code\game\gamemodes\wizard\rightandwrong.dm Lines: 9?, 10?, 11? Total Colons: 3
-..code\game\gamemodes\wizard\soulstone.dm Lines: 123, 195 Total Colons: 2
-..code\game\gamemodes\wizard\spellbook.dm Lines: 93?, 512?, 533? Total Colons: 3
-..code\game\gamemodes\wizard\wizard.dm Lines: 183?, 258, 261, 264, 278? Total Colons: 5
-..code\game\machinery\airlock_control.dm Lines: 59?, 60? Total Colons: 2
-..code\game\machinery\ai_slipper.dm Lines: 39?, 67, 77?, 93? Total Colons: 5
-..code\game\machinery\alarm.dm Lines: 134?, 135?, 730?, 742?, 895?, 934?, 1056?, 1071?, 1127?, 1128? Total Colons: 16
-..code\game\machinery\announcement_system.dm Lines: 45?, 47?, 136?, 137? Total Colons: 4
-..code\game\machinery\atmo_control.dm Lines: 273?, 284?, 396? Total Colons: 3
-..code\game\machinery\autolathe.dm Lines: 139?, 178?, 187?, 295?, 322?, 336?, 345? Total Colons: 10
-..code\game\machinery\Beacon.dm Lines: 31? Total Colons: 1
-..code\game\machinery\buttons.dm Lines: 22?, 23? Total Colons: 4
-..code\game\machinery\cell_charger.dm Lines: 15?, 31?, 64? Total Colons: 4
-..code\game\machinery\cloning.dm Lines: 88?, 92? Total Colons: 2
-..code\game\machinery\constructable_frame.dm Lines: 48?, 90?, 94?, 99?, 102?, 475? Total Colons: 8
-..code\game\machinery\deployable.dm Lines: 92 Total Colons: 1
-..code\game\machinery\dna_scanner.dm Lines: 44?, 48?, 57? Total Colons: 3
-..code\game\machinery\droneDispenser.dm Lines: 190? Total Colons: 1
-..code\game\machinery\iv_drip.dm Lines: 192?, 200?, 210? Total Colons: 3
-..code\game\machinery\lightswitch.dm Lines: 41? Total Colons: 1
-..code\game\machinery\machinery.dm Lines: 372?, 375? Total Colons: 2
-..code\game\machinery\magnet.dm Lines: 53?, 275?, 279? Total Colons: 3
-..code\game\machinery\navbeacon.dm Lines: 63?, 84?, 92?, 122?, 130? Total Colons: 6
-..code\game\machinery\newscaster.dm Lines: 205?, 206?, 291?, 304?, 311?, 318?, 319?, 372, 391?, 409?, 420?, 423, 424?, 430?, 431?, 436, 460?, 465?, 486, 614?, 724?, 727?, 922 Total Colons: 27
-..code\game\machinery\overview.dm Lines: 98, 167?, 243, 292? Total Colons: 4
-..code\game\machinery\portable_turret.dm Lines: 162?, 164?, 169?, 170?, 171?, 172?, 173?, 183?, 285?, 862?, 864?, 869?, 870?, 871?, 872?, 873?, 877?, 889?, 891?, 896?, 897?, 898?, 899?, 900?, 910?, 968?, 1049?, 1085, 1097?, 1098? Total Colons: 32
-..code\game\machinery\recharger.dm Lines: 19? Total Colons: 1
-..code\game\machinery\rechargestation.dm Lines: 122?, 124? Total Colons: 2
-..code\game\machinery\recycler.dm Lines: 43?, 44?, 45?, 84? Total Colons: 4
-..code\game\machinery\requests_console.dm Lines: 201?, 202?, 212?, 213? Total Colons: 4
-..code\game\machinery\robot_fabricator.dm Lines: 21, 23, 24, 25, 28 Total Colons: 5
-..code\game\machinery\shieldgen.dm Lines: 247?, 261?, 263?, 441? Total Colons: 4
-..code\game\machinery\Sleeper.dm Lines: 142?, 156?, 162? Total Colons: 4
-..code\game\machinery\slotmachine.dm Lines: 219?, 265?, 271? Total Colons: 3
-..code\game\machinery\spaceheater.dm Lines: 33?, 35?, 37?, 69?, 89?, 107? Total Colons: 9
-..code\game\machinery\status_display.dm Lines: 167 Total Colons: 4
-..code\game\machinery\suit_storage_unit.dm Lines: 199?, 200?, 212?, 215?, 218?, 221?, 227?, 231?, 232?, 519? Total Colons: 12
-..code\game\machinery\syndicatebeacon.dm Lines: 151? Total Colons: 1
-..code\game\machinery\syndicatebomb.dm Lines: 22?, 53?, 77?, 323?, 326? Total Colons: 6
-..code\game\machinery\teleporter.dm Lines: 69?, 442? Total Colons: 3
-..code\game\machinery\turrets.dm Lines: 542?, 578, 590?, 591? Total Colons: 6
-..code\game\machinery\vending.dm Lines: 248?, 323? Total Colons: 2
-..code\game\machinery\atmoalter\canister.dm Lines: 248, 289?, 290?, 291?, 292?, 295?, 297? Total Colons: 7
-..code\game\machinery\atmoalter\pump.dm Lines: 109? Total Colons: 3
-..code\game\machinery\atmoalter\scrubber.dm Lines: 127?, 203? Total Colons: 3
-..code\game\machinery\bots\bots.dm Lines: 244?, 337?, 338?, 340?, 416?, 481? Total Colons: 6
-..code\game\machinery\bots\cleanbot.dm Lines: 84?, 85?, 87?, 88?, 109? Total Colons: 6
-..code\game\machinery\bots\ed209bot.dm Lines: 107?, 109?, 115?, 116?, 117?, 118?, 119?, 120?, 155?, 258?, 456? Total Colons: 12
-..code\game\machinery\bots\floorbot.dm Lines: 104?, 105?, 107?, 109?, 110?, 111?, 112?, 113?, 114?, 115?, 116?, 147?, 360? Total Colons: 13
-..code\game\machinery\bots\medbot.dm Lines: 147?, 148?, 154?, 171?, 173?, 174?, 175?, 176?, 177?, 231?, 320?, 532? Total Colons: 12
-..code\game\machinery\bots\mulebot.dm Lines: 99?, 147?, 187?, 209?, 210?, 211?, 225?, 226?, 227?, 228?, 249?, 282?, 346?, 354?, 363?, 535? Total Colons: 17
-..code\game\machinery\bots\secbot.dm Lines: 97?, 99?, 104?, 105?, 106?, 107?, 108?, 109?, 142?, 222? Total Colons: 11
-..code\game\machinery\camera\camera.dm Lines: 141?, 151?, 152? Total Colons: 3
-..code\game\machinery\camera\tracking.dm Lines: 19?, 83? Total Colons: 2
-..code\game\machinery\computer\arcade.dm Lines: 860?, 862?, 863?, 871? Total Colons: 6
-..code\game\machinery\computer\camera.dm Lines: 56? Total Colons: 1
-..code\game\machinery\computer\camera_advanced.dm Lines: 154? Total Colons: 1
-..code\game\machinery\computer\card.dm Lines: 148?, 164?, 209?, 364?, 372?, 390? Total Colons: 6
-..code\game\machinery\computer\cloning.dm Lines: 146? Total Colons: 1
-..code\game\machinery\computer\communications.dm Lines: 106, 148?, 272?, 428?, 429?, 430, 453?, 468?, 531?, 532?, 533, 554? Total Colons: 12
-..code\game\machinery\computer\crew.dm Lines: 153?, 158?, 169? Total Colons: 3
-..code\game\machinery\computer\dna_console.dm Lines: 94?, 139?, 141?, 143?, 181? Total Colons: 5
-..code\game\machinery\computer\medical.dm Lines: 40?, 46, 153? Total Colons: 4
-..code\game\machinery\computer\message.dm Lines: 73?, 76?, 131?, 150? Total Colons: 4
-..code\game\machinery\computer\Operating.dm Lines: 50? Total Colons: 1
-..code\game\machinery\computer\pod.dm Lines: 56? Total Colons: 2
-..code\game\machinery\computer\robot.dm Lines: 65?, 107?, 109?, 110?, 112?, 114? Total Colons: 6
-..code\game\machinery\computer\security.dm Lines: 49?, 62, 117, 130, 275, 285 Total Colons: 7
-..code\game\machinery\computer\shuttle.dm Lines: 24, 25, 28, 30, 33, 34, 47, 48, 60 Total Colons: 9
-..code\game\machinery\computer\station_alert.dm Lines: 73? Total Colons: 1
-..code\game\machinery\doors\airlock.dm Lines: 790?, 791?, 800?, 801?, 809?, 877, 888 Total Colons: 7
-..code\game\machinery\doors\airlock_electronics.dm Lines: 81 Total Colons: 1
-..code\game\machinery\doors\brigdoors.dm Lines: 123?, 158?, 247 Total Colons: 7
-..code\game\machinery\doors\firedoor.dm Lines: 49?, 69 Total Colons: 2
-..code\game\machinery\doors\windowdoor.dm Lines: 188?, 200, 276? Total Colons: 3
-..code\game\machinery\embedded_controller\access_controller.dm Lines: 295?, 297? Total Colons: 2
-..code\game\machinery\embedded_controller\airlock_controller.dm Lines: 258?, 259?, 260?, 261? Total Colons: 4
-..code\game\machinery\pipe\construction.dm Lines: 134?, 162? Total Colons: 2
-..code\game\machinery\telecomms\machine_interactions.dm Lines: 57?, 64?, 159?, 160?, 161?, 184?, 220? Total Colons: 7
-..code\game\mecha\mecha.dm Lines: 561?, 582?, 838?, 843?, 935?, 936?, 937?, 986?, 987? Total Colons: 11
-..code\game\mecha\mecha_control_console.dm Lines: 72? Total Colons: 1
-..code\game\mecha\mecha_topic.dm Lines: 33?, 34?, 36?, 40?, 90?, 164?, 168?, 190?, 197? Total Colons: 21
-..code\game\mecha\mecha_wreckage.dm Lines: 25?, 42? Total Colons: 2
-..code\game\mecha\mech_fabricator.dm Lines: 120?, 132?, 237? Total Colons: 6
-..code\game\mecha\combat\combat.dm Lines: 65?, 67? Total Colons: 3
-..code\game\mecha\combat\durand.dm Lines: 38?, 50? Total Colons: 2
-..code\game\mecha\combat\gygax.dm Lines: 69?, 74?, 105? Total Colons: 3
-..code\game\mecha\combat\honker.dm Lines: 32?, 33?, 35? Total Colons: 14
-..code\game\mecha\combat\marauder.dm Lines: 70?, 158?, 160? Total Colons: 5
-..code\game\mecha\combat\phazon.dm Lines: 39?, 97?, 98? Total Colons: 3
-..code\game\mecha\equipment\mecha_equipment.dm Lines: 57? Total Colons: 3
-..code\game\mecha\equipment\tools\medical_tools.dm Lines: 96, 96?, 129?, 249?, 333?, 366, 370?, 371? Total Colons: 20
-..code\game\mecha\equipment\tools\mining_tools.dm Lines: 40, 51 Total Colons: 2
-..code\game\mecha\equipment\tools\other_tools.dm Lines: 132?, 160?, 182?, 222?, 328?, 406, 406?, 446? Total Colons: 10
-..code\game\mecha\equipment\tools\work_tools.dm Lines: 329?, 350?, 351?, 368, 368? Total Colons: 7
-..code\game\mecha\equipment\weapons\weapons.dm Lines: 208? Total Colons: 1
-..code\game\mecha\working\ripley.dm Lines: 53?, 55? Total Colons: 2
-..code\game\objects\explosion.dm Lines: 11?, 12?, 68? Total Colons: 5
-..code\game\objects\items.dm Lines: 213? Total Colons: 1
-..code\game\objects\items\candle.dm Lines: 23? Total Colons: 1
-..code\game\objects\items\crayons.dm Lines: 117, 171?, 172?, 173?, 210? Total Colons: 5
-..code\game\objects\items\toys.dm Lines: 133?, 187?, 234?, 452?, 471? Total Colons: 6
-..code\game\objects\items\devices\aicard.dm Lines: 83?, 85?, 129?, 138? Total Colons: 4
-..code\game\objects\items\devices\flashlight.dm Lines: 60? Total Colons: 2
-..code\game\objects\items\devices\geiger_counter.dm Lines: 93? Total Colons: 1
-..code\game\objects\items\devices\paicard.dm Lines: 40?, 41? Total Colons: 2
-..code\game\objects\items\devices\scanners.dm Lines: 123?, 137?, 139?, 141?, 143?, 147?, 149, 164?, 212?, 396? Total Colons: 11
-..code\game\objects\items\devices\taperecorder.dm Lines: 28?, 97, 117, 142 Total Colons: 4
-..code\game\objects\items\devices\transfer_valve.dm Lines: 69?, 102 Total Colons: 6
-..code\game\objects\items\devices\PDA\cart.dm Lines: 241, 245, 275, 292?, 293?, 294, 348?, 424, 435, 473?, 499?, 533?, 546?, 557?, 585, 594, 601, 605, 606, 609, 610, 611, 612, 631, 642?, 649?, 702?, 703?, 705?, 706?, 707?, 708?, 709?, 711, 712, 713, 716, 717, 718 Total Colons: 44
-..code\game\objects\items\devices\PDA\PDA.dm Lines: 298?, 299?, 330?, 356?, 358?, 360?, 364?, 378?, 382?, 383?, 388, 390, 392, 618, 619, 631, 632, 692, 693, 918, 1010?, 1036, 1039, 1131?, 1143? Total Colons: 25
-..code\game\objects\items\devices\radio\electropack.dm Lines: 129? Total Colons: 1
-..code\game\objects\items\devices\radio\radio.dm Lines: 136?, 137, 137?, 138, 138?, 139, 140, 141, 143, 144, 146, 147?, 148, 148?, 149, 150, 151, 153, 154, 155 Total Colons: 22
-..code\game\objects\items\robot\robot_parts.dm Lines: 137, 143, 150, 258?, 259?, 261?, 262?, 263?, 264? Total Colons: 11
-..code\game\objects\items\robot\robot_upgrades.dm Lines: 250? Total Colons: 1
-..code\game\objects\items\stacks\sheets\glass.dm Lines: 303? Total Colons: 1
-..code\game\objects\items\weapons\AI_modules.dm Lines: 37?, 72?, 73?, 74? Total Colons: 4
-..code\game\objects\items\weapons\cards_ids.dm Lines: 115?, 118?, 148? Total Colons: 6
-..code\game\objects\items\weapons\cigs_lighters.dm Lines: 479?, 496? Total Colons: 2
-..code\game\objects\items\weapons\cosmetics.dm Lines: 36?, 54? Total Colons: 2
-..code\game\objects\items\weapons\defib.dm Lines: 470?, 485?, 487?, 489?, 491?, 508?, 527?, 530? Total Colons: 8
-..code\game\objects\items\weapons\explosives.dm Lines: 57? Total Colons: 1
-..code\game\objects\items\weapons\extinguisher.dm Lines: 45?, 46? Total Colons: 2
-..code\game\objects\items\weapons\flamethrower.dm Lines: 90?, 128? Total Colons: 2
-..code\game\objects\items\weapons\handcuffs.dm Lines: 208? Total Colons: 1
-..code\game\objects\items\weapons\RCD.dm Lines: 500, 505 Total Colons: 4
-..code\game\objects\items\weapons\singularityhammer.dm Lines: 42 Total Colons: 1
-..code\game\objects\items\weapons\stunbaton.dm Lines: 94? Total Colons: 1
-..code\game\objects\items\weapons\grenades\chem_grenade.dm Lines: 60? Total Colons: 1
-..code\game\objects\items\weapons\grenades\grenade.dm Lines: 49? Total Colons: 1
-..code\game\objects\items\weapons\implants\implantchair.dm Lines: 46?, 47?, 49? Total Colons: 5
-..code\game\objects\items\weapons\implants\implantpad.dm Lines: 56 Total Colons: 1
-..code\game\objects\items\weapons\storage\book.dm Lines: 180 Total Colons: 1
-..code\game\objects\items\weapons\storage\fancy.dm Lines: 39? Total Colons: 1
-..code\game\objects\items\weapons\storage\secure.dm Lines: 32?, 39?, 84? Total Colons: 3
-..code\game\objects\items\weapons\storage\storage.dm Lines: 177? Total Colons: 1
-..code\game\objects\items\weapons\tanks\jetpack.dm Lines: 26?, 44?, 151? Total Colons: 3
-..code\game\objects\items\weapons\tanks\tanks.dm Lines: 121?, 122? Total Colons: 2
-..code\game\objects\items\weapons\tanks\watertank.dm Lines: 177?, 178? Total Colons: 2
-..code\game\objects\structures\ai_core.dm Lines: 212?, 213? Total Colons: 2
-..code\game\objects\structures\displaycase.dm Lines: 119?, 128?, 130? Total Colons: 3
-..code\game\objects\structures\fireaxe.dm Lines: 129? Total Colons: 1
-..code\game\objects\structures\grille.dm Lines: 148?, 149? Total Colons: 2
-..code\game\objects\structures\musician.dm Lines: 50?, 130?, 132? Total Colons: 3
-..code\game\objects\structures\safe.dm Lines: 78?, 98?, 104?, 188? Total Colons: 4
-..code\game\objects\structures\tank_dispenser.dm Lines: 43?, 44? Total Colons: 2
-..code\game\objects\structures\watercloset.dm Lines: 51?, 54? Total Colons: 3
-..code\game\objects\structures\windoor_assembly.dm Lines: 50? Total Colons: 1
-..code\game\objects\structures\window.dm Lines: 197?, 199?, 201?, 206?, 207?, 211?, 215?, 218?, 222?, 223?, 425? Total Colons: 11
-..code\game\objects\structures\beds_chairs\bed.dm Lines: 129? Total Colons: 1
-..code\game\objects\structures\crates_lockers\closets.dm Lines: 66?, 234?, 241?, 243?, 392? Total Colons: 6
-..code\game\objects\structures\transit_tubes\station.dm Lines: 130? Total Colons: 1
-..code\game\objects\structures\transit_tubes\transit_tube_construction.dm Lines: 41?, 43? Total Colons: 2
-..code\game\turfs\turf.dm Lines: 137, 248?, 250? Total Colons: 4
-..code\game\turfs\space\space.dm Lines: 114?, 125? Total Colons: 2
-..code\game\verbs\ooc.dm Lines: 44?, 53?, 55?, 57?, 69? Total Colons: 6
-..code\LINDA\LINDA_turf_tile.dm Lines: 458?, 463? Total Colons: 2
-..code\modules\admin\admin.dm Lines: 30?, 62?, 63?, 64?, 65?, 66?, 67?, 122, 129, 141, 192?, 205?, 212?, 246, 262?, 277?, 288?, 292, 293?, 300?, 301?, 306, 334?, 352, 415?, 442?, 550?, 551?, 676?, 677?, 696? Total Colons: 35
-..code\modules\admin\admin_verbs.dm Lines: 441?, 442? Total Colons: 2
-..code\modules\admin\create_poll.dm Lines: 25?, 26?, 94?, 95? Total Colons: 4
-..code\modules\admin\newbanjob.dm Lines: 216? Total Colons: 2
-..code\modules\admin\player_panel.dm Lines: 111?, 113?, 119?, 123?, 129?, 155?, 160?, 166?, 181?, 186?, 195?, 207?, 219?, 228?, 240?, 249?, 258?, 269?, 284?, 297? Total Colons: 36
-..code\modules\admin\sql_notes.dm Lines: 153 Total Colons: 2
-..code\modules\admin\topic.dm Lines: 299?, 310?, 341?, 348?, 349?, 447?, 986?, 1559?, 1561?, 1589?, 1796?, 1797?, 1798?, 1800?, 1982?, 2093?, 2096?, 2101?, 2102? Total Colons: 21
-..code\modules\admin\DB ban\functions.dm Lines: 93, 94, 95, 127?, 131?, 304, 305, 306, 441? Total Colons: 20
-..code\modules\admin\verbs\adminjump.dm Lines: 91, 127 Total Colons: 2
-..code\modules\admin\verbs\deadsay.dm Lines: 24? Total Colons: 1
-..code\modules\admin\verbs\debug.dm Lines: 82?, 86?, 89?, 112?, 116?, 289, 306, 498, 501 Total Colons: 9
-..code\modules\admin\verbs\diagnostics.dm Lines: 15?, 81 Total Colons: 5
-..code\modules\admin\verbs\massmodvar.dm Lines: 132 Total Colons: 1
-..code\modules\admin\verbs\modifyvariables.dm Lines: 542 Total Colons: 1
-..code\modules\admin\verbs\one_click_antag.dm Lines: 333?, 478?, 481?, 484?, 487?, 490?, 493?, 496?, 517? Total Colons: 9
-..code\modules\admin\verbs\panicbunker.dm Lines: 10?, 11? Total Colons: 2
-..code\modules\admin\verbs\randomverbs.dm Lines: 38?, 114?, 116?, 117?, 189?, 212?, 409?, 448?, 721?, 722?, 799, 804, 810, 816, 822, 828, 834, 840, 846, 852, 858, 864, 870, 876, 882, 888, 894, 900 Total Colons: 28
-..code\modules\assembly\bomb.dm Lines: 44 Total Colons: 1
-..code\modules\assembly\doorcontrol.dm Lines: 62? Total Colons: 1
-..code\modules\assembly\health.dm Lines: 77? Total Colons: 1
-..code\modules\assembly\infrared.dm Lines: 24?, 110? Total Colons: 3
-..code\modules\assembly\mousetrap.dm Lines: 30?, 127? Total Colons: 2
-..code\modules\assembly\proximity.dm Lines: 26?, 109?, 110? Total Colons: 3
-..code\modules\assembly\signaler.dm Lines: 142? Total Colons: 1
-..code\modules\assembly\timer.dm Lines: 75? Total Colons: 1
-..code\modules\assembly\voice.dm Lines: 32? Total Colons: 1
-..code\modules\awaymissions\maploader\reader.dm Lines: 262? Total Colons: 1
-..code\modules\awaymissions\maploader\swapmaps.dm Lines: 152, 153, 154, 161?, 162?, 163?, 343?, 356?, 362?, 385? Total Colons: 19
-..code\modules\client\client procs.dm Lines: 36, 36?, 177? Total Colons: 3
-..code\modules\client\preferences.dm Lines: 129?, 130?, 151?, 161?, 166?, 186?, 335?, 336?, 337?, 338?, 339?, 340?, 341?, 342?, 343?, 349?, 350?, 353?, 356?, 397?, 523? Total Colons: 21
-..code\modules\client\preferences_toggles.dm Lines: 7?, 16?, 25?, 34?, 43?, 54?, 64?, 74?, 83?, 92?, 113?, 122?, 172?, 226?, 235?, 259? Total Colons: 16
-..code\modules\clothing\clothing.dm Lines: 357? Total Colons: 1
-..code\modules\clothing\glasses\engine_goggles.dm Lines: 83?, 108? Total Colons: 2
-..code\modules\clothing\head\helmet.dm Lines: 240? Total Colons: 1
-..code\modules\clothing\head\soft_caps.dm Lines: 45? Total Colons: 1
-..code\modules\clothing\masks\gasmask.dm Lines: 66? Total Colons: 1
-..code\modules\clothing\masks\miscellaneous.dm Lines: 56? Total Colons: 1
-..code\modules\clothing\shoes\bananashoes.dm Lines: 59?, 65? Total Colons: 3
-..code\modules\clothing\shoes\magboots.dm Lines: 32?, 41? Total Colons: 2
-..code\modules\clothing\spacesuits\chronosuit.dm Lines: 146, 151, 152, 153, 158, 172, 175, 176, 177 Total Colons: 9
-..code\modules\crafting\table.dm Lines: 15, 59, 113, 126, 143, 167 Total Colons: 6
-..code\modules\detectivework\detective_work.dm Lines: 16? Total Colons: 1
-..code\modules\events\event.dm Lines: 37 Total Colons: 2
-..code\modules\events\shuttle_loan.dm Lines: 195, 196 Total Colons: 2
-..code\modules\flufftext\Hallucination.dm Lines: 47?, 49?, 51? Total Colons: 3
-..code\modules\food&drinks\food\customizables.dm Lines: 37? Total Colons: 1
-..code\modules\food&drinks\kitchen machinery\gibber.dm Lines: 165? Total Colons: 1
-..code\modules\food&drinks\kitchen machinery\monkeyrecycler.dm Lines: 72? Total Colons: 1
-..code\modules\food&drinks\kitchen machinery\processor.dm Lines: 198? Total Colons: 1
-..code\modules\games\cards.dm Lines: 177?, 211?, 225? Total Colons: 3
-..code\modules\holiday\easter.dm Lines: 77? Total Colons: 1
-..code\modules\html_interface\html_interface.dm Lines: 292? Total Colons: 1
-..code\modules\hydroponics\grown.dm Lines: 704 Total Colons: 1
-..code\modules\hydroponics\growninedible.dm Lines: 71, 194? Total Colons: 2
-..code\modules\hydroponics\hydroponics.dm Lines: 642?, 836? Total Colons: 2
-..code\modules\hydroponics\seeds.dm Lines: 1377?, 1378? Total Colons: 2
-..code\modules\library\lib_items.dm Lines: 186? Total Colons: 1
-..code\modules\library\lib_machines.dm Lines: 519 Total Colons: 1
-..code\modules\lighting\lighting_system.dm Lines: 254 Total Colons: 1
-..code\modules\mob\inventory.dm Lines: 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 170 Total Colons: 22
-..code\modules\mob\login.dm Lines: 6? Total Colons: 1
-..code\modules\mob\mob.dm Lines: 329?, 599?, 690, 756? Total Colons: 5
-..code\modules\mob\mob_helpers.dm Lines: 485? Total Colons: 2
-..code\modules\mob\transform_procs.dm Lines: 295 Total Colons: 1
-..code\modules\mob\dead\observer\observer.dm Lines: 285? Total Colons: 1
-..code\modules\mob\living\living.dm Lines: 181?, 359?, 402 Total Colons: 3
-..code\modules\mob\living\say.dm Lines: 116? Total Colons: 1
-..code\modules\mob\living\carbon\carbon.dm Lines: 114, 286?, 288?, 291?, 310?, 311?, 322?, 323?, 566? Total Colons: 12
-..code\modules\mob\living\carbon\life.dm Lines: 468? Total Colons: 1
-..code\modules\mob\living\carbon\alien\humanoid\emote.dm Lines: 60? Total Colons: 1
-..code\modules\mob\living\carbon\alien\humanoid\humanoid.dm Lines: 93? Total Colons: 2
-..code\modules\mob\living\carbon\alien\humanoid\caste\hunter.dm Lines: 43?, 46? Total Colons: 2
-..code\modules\mob\living\carbon\alien\larva\emote.dm Lines: 79? Total Colons: 1
-..code\modules\mob\living\carbon\brain\MMI.dm Lines: 131?, 132? Total Colons: 2
-..code\modules\mob\living\carbon\human\examine.dm Lines: 48?, 55?, 62?, 69?, 76?, 83?, 90?, 97?, 115?, 122?, 129?, 136? Total Colons: 12
-..code\modules\mob\living\carbon\human\human.dm Lines: 87?, 96?, 192?, 194?, 196?, 200?, 205?, 210?, 215?, 219?, 221?, 223?, 231?, 236?, 241?, 248?, 250?, 252?, 253?, 254?, 324?, 325?, 341?, 563?, 734? Total Colons: 26
-..code\modules\mob\living\carbon\human\human_attackalien.dm Lines: 10? Total Colons: 1
-..code\modules\mob\living\carbon\human\inventory.dm Lines: 223?, 234?, 238?, 246?, 250?, 254? Total Colons: 6
-..code\modules\mob\living\carbon\human\species.dm Lines: 115?, 117?, 126?, 329?, 673? Total Colons: 5
-..code\modules\mob\living\carbon\human\update_icons.dm Lines: 112?, 186?, 479? Total Colons: 4
-..code\modules\mob\living\carbon\human\whisper.dm Lines: 43? Total Colons: 1
-..code\modules\mob\living\carbon\monkey\emote.dm Lines: 60? Total Colons: 1
-..code\modules\mob\living\silicon\silicon.dm Lines: 129, 324? Total Colons: 2
-..code\modules\mob\living\silicon\ai\ai.dm Lines: 255?, 280?, 281?, 341?, 530?, 532?, 585?, 593? Total Colons: 9
-..code\modules\mob\living\silicon\ai\life.dm Lines: 73, 75, 78, 80, 96, 97, 121, 145, 150, 166 Total Colons: 10
-..code\modules\mob\living\silicon\ai\say.dm Lines: 15? Total Colons: 2
-..code\modules\mob\living\silicon\ai\freelook\eye.dm Lines: 106? Total Colons: 1
-..code\modules\mob\living\silicon\pai\pai.dm Lines: 161, 181 Total Colons: 2
-..code\modules\mob\living\silicon\pai\software.dm Lines: 220?, 277?, 279?, 281?, 317?, 410?, 415?, 422?, 434, 434?, 435, 436, 436?, 437, 437?, 438, 438?, 439, 439?, 440, 442, 443, 444, 445, 446, 550, 557? Total Colons: 29
-..code\modules\mob\living\silicon\robot\examine.dm Lines: 29?, 31? Total Colons: 2
-..code\modules\mob\living\silicon\robot\inventory.dm Lines: 54, 62, 70 Total Colons: 3
-..code\modules\mob\living\silicon\robot\laws.dm Lines: 47? Total Colons: 1
-..code\modules\mob\living\silicon\robot\life.dm Lines: 173, 175, 177 Total Colons: 3
-..code\modules\mob\living\silicon\robot\robot.dm Lines: 259?, 393?, 492?, 545?, 806?, 1034? Total Colons: 8
-..code\modules\mob\living\simple_animal\parrot.dm Lines: 412?, 414? Total Colons: 2
-..code\modules\mob\living\simple_animal\worm.dm Lines: 74? Total Colons: 1
-..code\modules\mob\living\simple_animal\friendly\drone\interaction.dm Lines: 103? Total Colons: 2
-..code\modules\mob\living\simple_animal\friendly\drone\verbs.dm Lines: 25? Total Colons: 1
-..code\modules\mob\living\simple_animal\friendly\drone\_drone.dm Lines: 123?, 130?, 137?, 144? Total Colons: 4
-..code\modules\mob\living\simple_animal\hostile\hostile.dm Lines: 255, 256 Total Colons: 4
-..code\modules\mob\living\simple_animal\morph\morph.dm Lines: 183? Total Colons: 1
-..code\modules\mob\living\simple_animal\slime\death.dm Lines: 15? Total Colons: 1
-..code\modules\mob\living\simple_animal\slime\life.dm Lines: 190? Total Colons: 1
-..code\modules\mob\living\simple_animal\slime\powers.dm Lines: 75? Total Colons: 1
-..code\modules\mob\living\simple_animal\slime\slime.dm Lines: 79?, 80?, 90? Total Colons: 3
-..code\modules\mob\new_player\new_player.dm Lines: 27, 29, 44?, 69?, 73? Total Colons: 5
-..code\modules\mob\new_player\poll.dm Lines: 12?, 29?, 478? Total Colons: 3
-..code\modules\nano\JSON Reader.dm Lines: 71 Total Colons: 2
-..code\modules\nano\nanoui.dm Lines: 304? Total Colons: 1
-..code\modules\ninja\admin_ninja_verbs.dm Lines: 30, 32 Total Colons: 2
-..code\modules\ninja\ninja_event.dm Lines: 141? Total Colons: 1
-..code\modules\ninja\suit\gloves.dm Lines: 80?, 87? Total Colons: 2
-..code\modules\ninja\suit\mask.dm Lines: 116?, 129?, 132?, 139? Total Colons: 4
-..code\modules\ninja\suit\ninjaDrainAct.dm Lines: 128?, 159? Total Colons: 2
-..code\modules\ninja\suit\suit.dm Lines: 75?, 79?, 116?, 172? Total Colons: 4
-..code\modules\ninja\suit\suit_attackby.dm Lines: 10?, 12?, 19? Total Colons: 3
-..code\modules\ninja\suit\suit_initialisation.dm Lines: 84 Total Colons: 1
-..code\modules\ninja\suit\n_suit_verbs\energy_net_nets.dm Lines: 64, 65, 112?, 131 Total Colons: 4
-..code\modules\ninja\suit\n_suit_verbs\ninja_stars.dm Lines: 12? Total Colons: 1
-..code\modules\paperwork\filingcabinet.dm Lines: 57? Total Colons: 1
-..code\modules\paperwork\folders.dm Lines: 43? Total Colons: 1
-..code\modules\paperwork\paper.dm Lines: 86? Total Colons: 1
-..code\modules\paperwork\paperbin.dm Lines: 97? Total Colons: 1
-..code\modules\paperwork\photocopier.dm Lines: 123?, 264?, 268? Total Colons: 5
-..code\modules\paperwork\photography.dm Lines: 66?, 67?, 79?, 183, 184, 189, 190, 217, 217?, 219, 219? Total Colons: 14
-..code\modules\power\apc.dm Lines: 128?, 129?, 133, 148, 199?, 201?, 202?, 262?, 454?, 469?, 474, 647, 647?, 664?, 671?, 715?, 838, 839, 840, 1184, 1221? Total Colons: 25
-..code\modules\power\cable.dm Lines: 108?, 293?, 564? Total Colons: 3
-..code\modules\power\generator.dm Lines: 117? Total Colons: 2
-..code\modules\power\gravitygenerator.dm Lines: 230?, 250?, 258?, 264?, 279?, 280?, 287? Total Colons: 7
-..code\modules\power\lighting.dm Lines: 261?, 440? Total Colons: 2
-..code\modules\power\port_gen.dm Lines: 89?, 273? Total Colons: 2
-..code\modules\power\smes.dm Lines: 57, 419? Total Colons: 4
-..code\modules\power\solar.dm Lines: 388?, 391? Total Colons: 2
-..code\modules\power\turbine.dm Lines: 308?, 365?, 367?, 369? Total Colons: 5
-..code\modules\power\antimatter\control.dm Lines: 267? Total Colons: 1
-..code\modules\power\antimatter\shielding.dm Lines: 119 Total Colons: 1
-..code\modules\power\singularity\collector.dm Lines: 44?, 45?, 46?, 98? Total Colons: 6
-..code\modules\power\singularity\emitter.dm Lines: 252? Total Colons: 1
-..code\modules\power\singularity\singularity.dm Lines: 117?, 236? Total Colons: 2
-..code\modules\power\singularity\particle_accelerator\particle.dm Lines: 42 Total Colons: 1
-..code\modules\power\singularity\particle_accelerator\particle_accelerator.dm Lines: 364 Total Colons: 1
-..code\modules\power\singularity\particle_accelerator\particle_control.dm Lines: 215?, 216?, 217? Total Colons: 6
-..code\modules\procedural mapping\mapGenerator.dm Lines: 153? Total Colons: 1
-..code\modules\projectiles\ammunition.dm Lines: 29?, 30?, 155? Total Colons: 3
-..code\modules\projectiles\gun.dm Lines: 108?, 110?, 310? Total Colons: 3
-..code\modules\projectiles\ammunition\magazines.dm Lines: 173? Total Colons: 1
-..code\modules\projectiles\guns\magic\wand.dm Lines: 25? Total Colons: 1
-..code\modules\projectiles\guns\projectile\automatic.dm Lines: 28?, 109?, 127?, 160?, 165?, 250? Total Colons: 11
-..code\modules\projectiles\guns\projectile\launchers.dm Lines: 49? Total Colons: 1
-..code\modules\projectiles\guns\projectile\pistol.dm Lines: 15?, 36? Total Colons: 3
-..code\modules\projectiles\guns\projectile\shotgun.dm Lines: 30?, 63?, 114?, 282? Total Colons: 4
-..code\modules\projectiles\guns\projectile\toy.dm Lines: 33? Total Colons: 1
-..code\modules\reagents\Chemistry-Machinery.dm Lines: 85?, 89, 90, 97, 330?, 350?, 367?, 368?, 512?, 551?, 665?, 705?, 708?, 788, 867?, 910?, 1248?, 1286?, 1508?, 1510?, 1511?, 1512? Total Colons: 24
-..code\modules\reagents\Chemistry-Recipes.dm Lines: 46? Total Colons: 1
-..code\modules\reagents\reagent_containers.dm Lines: 64? Total Colons: 1
-..code\modules\reagents\Chemistry-Reagents\Consumable-Reagents\Food-Reagents.dm Lines: 331 Total Colons: 2
-..code\modules\reagents\reagent_containers\spray.dm Lines: 97?, 98?, 99?, 177? Total Colons: 4
-..code\modules\recycling\disposal-construction.dm Lines: 86?, 91? Total Colons: 2
-..code\modules\recycling\disposal-structures.dm Lines: 240? Total Colons: 1
-..code\modules\recycling\disposal-unit.dm Lines: 82? Total Colons: 1
-..code\modules\recycling\sortingmachinery.dm Lines: 217? Total Colons: 1
-..code\modules\research\experimentor.dm Lines: 253? Total Colons: 1
-..code\modules\research\message_server.dm Lines: 130? Total Colons: 2
-..code\modules\shuttle\shuttle.dm Lines: 266?, 270?, 515?, 522?, 547?, 564? Total Colons: 8
-..code\modules\surgery\organs\augments_internal.dm Lines: 33?, 76?, 77?, 94? Total Colons: 4
-..code\modules\telesci\telesci_computer.dm Lines: 46?, 122?, 269? Total Colons: 4
-..code\modules\tooltip\tooltip.dm Lines: 90? Total Colons: 1
-..code\modules\vehicles\VehicleBase.dm Lines: 101?, 103?, 105?, 107? Total Colons: 4
-..code\modules\vehicles\VehicleClickInteractions.dm Lines: 128?, 157?, 186?, 214?, 252?, 254?, 257?, 259?, 262?, 264?, 267?, 269?, 272?, 274? Total Colons: 14
-..code\modules\vehicles\VehicleDefense.dm Lines: 31? Total Colons: 1
-..code\orphaned procs\dbcore.dm Lines: 79? Total Colons: 5
-..code\orphaned procs\statistics.dm Lines: 63, 64, 98, 99 Total Colons: 4
-..code\_onclick\other_mobs.dm Lines: 89 Total Colons: 1
-..code\_onclick\hud\action.dm Lines: 184? Total Colons: 1
-..code\_onclick\hud\alien.dm Lines: 90? Total Colons: 1
-..code\_onclick\hud\alien_larva.dm Lines: 16? Total Colons: 1
-..code\_onclick\hud\human.dm Lines: 59? Total Colons: 1
-..code\_onclick\hud\monkey.dm Lines: 17? Total Colons: 1
-..code\__DATASTRUCTURES\priority_queue.dm Lines: 33? Total Colons: 1
-..code\__DATASTRUCTURES\stacks.dm Lines: 29? Total Colons: 1
-..code\__HELPERS\game.dm Lines: 216? Total Colons: 1
-..code\__HELPERS\icons.dm Lines: 216?, 233?, 386?, 389?, 392?, 425?, 439?, 456?, 526?, 557?, 559?, 601?, 607?, 635?, 636?, 637?, 638?, 715, 752, 757, 762, 763, 764, 765, 774, 786, 787, 809?, 828?, 839? Total Colons: 38
-..code\__HELPERS\icon_smoothing.dm Lines: 176?, 178? Total Colons: 2
-..code\__HELPERS\lists.dm Lines: 201?, 206?, 214? Total Colons: 3
-..code\__HELPERS\maths.dm Lines: 13?, 18?, 35?, 39? Total Colons: 4
-..code\__HELPERS\mobs.dm Lines: 137?, 139?, 140? Total Colons: 11
-..code\__HELPERS\names.dm Lines: 63?, 174? Total Colons: 3
-..code\__HELPERS\sanitize_values.dm Lines: 34? Total Colons: 1
-..code\__HELPERS\text.dm Lines: 157?, 350? Total Colons: 2
-..code\__HELPERS\type2type.dm Lines: 68?, 143?, 381? Total Colons: 5
-..code\__HELPERS\unsorted.dm Lines: 41?, 573, 904, 991? Total Colons: 4
-..code\__HELPERS\sorts\__main.dm Lines: 2?, 57?, 391, 491, 585? Total Colons: 5
-433/1564 files have colons in them
\ No newline at end of file