diff --git a/.github/workflows/autochangelog.yml b/.github/workflows/autochangelog.yml
index cb6ecabe46..c9c628fa29 100644
--- a/.github/workflows/autochangelog.yml
+++ b/.github/workflows/autochangelog.yml
@@ -11,7 +11,7 @@ env:
jobs:
autochangelog:
name: Autochangelog
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
if: github.event.pull_request.merged == true
steps:
- uses: /actions/checkout@v3
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c531d1ffd9..4dcbd75275 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -10,7 +10,7 @@ env:
jobs:
file_tests:
name: Run Linters
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Ensure +x on CI directory
@@ -36,7 +36,7 @@ jobs:
dreamchecker:
name: DreamChecker
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
@@ -57,14 +57,14 @@ jobs:
~/dreamchecker > ${GITHUB_WORKSPACE}/output-annotations.txt 2>&1
- name: Annotate Linter
- uses: yogstation13/DreamAnnotate@v1
+ uses: yogstation13/DreamAnnotate@v2
if: always()
with:
outputFile: output-annotations.txt
unit_tests:
name: Integration Tests
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Ensure +x on CI directory
diff --git a/.github/workflows/render_nanomaps.yml b/.github/workflows/render_nanomaps.yml
index d6f2622041..62076dca06 100644
--- a/.github/workflows/render_nanomaps.yml
+++ b/.github/workflows/render_nanomaps.yml
@@ -19,7 +19,7 @@ jobs:
pull-requests: write # to create pull requests (repo-sync/pull-request)
name: 'Generate NanoMaps'
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
steps:
- name: Clone
uses: actions/checkout@v3
diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm
index e67d2ad3ac..73ce3f01e8 100644
--- a/code/ZAS/Fire.dm
+++ b/code/ZAS/Fire.dm
@@ -170,7 +170,7 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin
continue
//Spread the fire.
- if(prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && my_tile.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, my_tile, 0,0))
+ if(prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && my_tile.CanPass(src, enemy_tile, 0,0) && enemy_tile.CanPass(src, my_tile, 0,0))
enemy_tile.create_fire(firelevel)
else
diff --git a/code/__defines/belly_modes_vr.dm b/code/__defines/belly_modes_vr.dm
index 2d8f714fc4..7ac58ddf6b 100644
--- a/code/__defines/belly_modes_vr.dm
+++ b/code/__defines/belly_modes_vr.dm
@@ -21,6 +21,7 @@
#define DM_FLAG_AFFECTWORN 0x10
#define DM_FLAG_JAMSENSORS 0x20
#define DM_FLAG_FORCEPSAY 0x40
+#define DM_FLAG_SLOWBODY 0x80 //CHOMPAdd
//Item related modes
#define IM_HOLD "Hold"
diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm
index ed22966cbe..abaab99885 100644
--- a/code/__defines/chemistry.dm
+++ b/code/__defines/chemistry.dm
@@ -54,8 +54,9 @@ var/list/cheartstopper = list("potassium_chloride") // Thi
#define MAX_PILL_SPRITE 24 //max icon state of the pill sprites
#define MAX_BOTTLE_SPRITE 4 //max icon state of the pill sprites
+#define MAX_PATCH_SPRITE 4 //max icon state of the patch sprites, CHOMPedit
#define MAX_MULTI_AMOUNT 20 // Max number of pills/patches that can be made at once
#define MAX_UNITS_PER_PILL 60 // Max amount of units in a pill
#define MAX_UNITS_PER_PATCH 60 // Max amount of units in a patch
#define MAX_UNITS_PER_BOTTLE 60 // Max amount of units in a bottle (it's volume)
-#define MAX_CUSTOM_NAME_LEN 64 // Max length of a custom pill/condiment/whatever
\ No newline at end of file
+#define MAX_CUSTOM_NAME_LEN 64 // Max length of a custom pill/condiment/whatever
diff --git a/code/__defines/input.dm b/code/__defines/input.dm
index cbc703935a..16afe5a2f3 100644
--- a/code/__defines/input.dm
+++ b/code/__defines/input.dm
@@ -10,7 +10,7 @@
// Combine the held WASD and arrow keys together (OR) into byond N/S/E/W dir
#define MOVEMENT_KEYS_TO_DIR(MK) ((((MK)>>4)|(MK))&(ALL_CARDINALS))
-// Bitflags for pressed modifier keys.
+// Bitflags for pressed modifier keys.
// Values chosen specifically to not conflict with dir bitfield, in case we want to smoosh them together.
#define CTRL_KEY (1<<8)
#define SHIFT_KEY (1<<9)
diff --git a/code/__defines/misc_ch.dm b/code/__defines/misc_ch.dm
index 0ea4cec334..126c925bba 100644
--- a/code/__defines/misc_ch.dm
+++ b/code/__defines/misc_ch.dm
@@ -1,3 +1,8 @@
+//Department defines
+#define DEPARTMENT_NONCREW "Non crew"
+
+//Job defines
+#define JOB_OUTSIDER "Outsider"
//Material defines
#define MAT_CARPET "red carpet"
@@ -8,4 +13,4 @@
#define MAT_CARPET_SILVERBLUE "silver blue carpet"
#define MAT_CARPET_PINK "pink carpet"
#define MAT_CARPET_PURPLE "purple carpet"
-#define MAT_CARPET_ORANGE "orange carpet"
\ No newline at end of file
+#define MAT_CARPET_ORANGE "orange carpet"
diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm
index cb30162b73..0a8b333956 100644
--- a/code/__defines/subsystems.dm
+++ b/code/__defines/subsystems.dm
@@ -119,26 +119,3 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define FIRE_PRIORITY_CHAT 400
#define FIRE_PRIORITY_OVERLAYS 500
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
-
-// Macro defining the actual code applying our overlays lists to the BYOND overlays list. (I guess a macro for speed)
-// TODO - I don't really like the location of this macro define. Consider it. ~Leshana
-#define COMPILE_OVERLAYS(A)\
- do {\
- var/list/oo = A.our_overlays;\
- var/list/po = A.priority_overlays;\
- if(LAZYLEN(po)){\
- if(LAZYLEN(oo)){\
- A.overlays = oo + po;\
- }\
- else{\
- A.overlays = po;\
- }\
- }\
- else if(LAZYLEN(oo)){\
- A.overlays = oo;\
- }\
- else{\
- A.overlays.Cut();\
- }\
- A.flags &= ~OVERLAY_QUEUED;\
- } while (FALSE)
diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm
index e2bc37d93c..5e77b4b09c 100644
--- a/code/_helpers/text.dm
+++ b/code/_helpers/text.dm
@@ -54,7 +54,9 @@
input = copytext(input,1,max_length)
if(extra)
- input = replace_characters(input, list("\n"=" ","\t"=" "))
+ var/temp_input = replace_characters(input, list("\n"=" ","\t"=" "))//one character is replaced by two
+ if(length(input) < (length(temp_input) - 6))//6 is the number of linebreaks allowed per message
+ input = replace_characters(temp_input,list(" "=" "))//replace again, this time the double spaces with single ones
if(encode)
// The below \ escapes have a space inserted to attempt to enable CI auto-checking of span class usage. Please do not remove the space.
diff --git a/code/_helpers/type2type.dm b/code/_helpers/type2type.dm
index 700bbbfc57..e21d973b1b 100644
--- a/code/_helpers/type2type.dm
+++ b/code/_helpers/type2type.dm
@@ -98,12 +98,18 @@
if(!direction)
return ""
var/list/dirs = list()
- if(direction & NORTH) dirs += "NORTH"
- if(direction & SOUTH) dirs += "SOUTH"
- if(direction & EAST) dirs += "EAST"
- if(direction & WEST) dirs += "WEST"
- if(direction & UP) dirs += "UP"
- if(direction & DOWN) dirs += "DOWN"
+ if(direction & NORTH)
+ dirs += "NORTH"
+ if(direction & SOUTH)
+ dirs += "SOUTH"
+ if(direction & EAST)
+ dirs += "EAST"
+ if(direction & WEST)
+ dirs += "WEST"
+ if(direction & UP)
+ dirs += "UP"
+ if(direction & DOWN)
+ dirs += "DOWN"
return dirs.Join(" ")
// Converts an angle (degrees) into an ss13 direction
@@ -287,21 +293,122 @@
return strtype
return copytext(strtype, delim_pos)
+// Concatenates a list of strings into a single string. A seperator may optionally be provided.
+/proc/list2text(list/ls, sep)
+ if (ls.len <= 1) // Early-out code for empty or singleton lists.
+ return ls.len ? ls[1] : ""
+
+ var/l = ls.len // Made local for sanic speed.
+ var/i = 0 // Incremented every time a list index is accessed.
+
+ if (sep != null)
+ // Macros expand to long argument lists like so: sep, ls[++i], sep, ls[++i], sep, ls[++i], etc...
+ #define S1 sep, ls[++i]
+ #define S4 S1, S1, S1, S1
+ #define S16 S4, S4, S4, S4
+ #define S64 S16, S16, S16, S16
+
+ . = "[ls[++i]]" // Make sure the initial element is converted to text.
+
+ // Having the small concatenations come before the large ones boosted speed by an average of at least 5%.
+ if (l-1 & 0x01) // 'i' will always be 1 here.
+ . = text("[][][]", ., S1) // Append 1 element if the remaining elements are not a multiple of 2.
+ if (l-i & 0x02)
+ . = text("[][][][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4.
+ if (l-i & 0x04)
+ . = text("[][][][][][][][][]", ., S4) // And so on....
+ if (l-i & 0x08)
+ . = text("[][][][][][][][][][][][][][][][][]", ., S4, S4)
+ if (l-i & 0x10)
+ . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16)
+ if (l-i & 0x20)
+ . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16)
+ if (l-i & 0x40)
+ . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64)
+ while (l > i) // Chomp through the rest of the list, 128 elements at a time.
+ . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
+
+ #undef S64
+ #undef S16
+ #undef S4
+ #undef S1
+ else
+ // Macros expand to long argument lists like so: ls[++i], ls[++i], ls[++i], etc...
+ #define S1 ls[++i]
+ #define S4 S1, S1, S1, S1
+ #define S16 S4, S4, S4, S4
+ #define S64 S16, S16, S16, S16
+
+ . = "[ls[++i]]" // Make sure the initial element is converted to text.
+
+ if (l-1 & 0x01) // 'i' will always be 1 here.
+ . += S1 // Append 1 element if the remaining elements are not a multiple of 2.
+ if (l-i & 0x02)
+ . = text("[][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4.
+ if (l-i & 0x04)
+ . = text("[][][][][]", ., S4) // And so on...
+ if (l-i & 0x08)
+ . = text("[][][][][][][][][]", ., S4, S4)
+ if (l-i & 0x10)
+ . = text("[][][][][][][][][][][][][][][][][]", ., S16)
+ if (l-i & 0x20)
+ . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16)
+ if (l-i & 0x40)
+ . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64)
+ while (l > i) // Chomp through the rest of the list, 128 elements at a time.
+ . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
+ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
+
+ #undef S64
+ #undef S16
+ #undef S4
+ #undef S1
+
+// Converts a string into a list by splitting the string at each delimiter found. (discarding the seperator)
+/proc/text2list(text, delimiter="\n")
+ var/delim_len = length(delimiter)
+ if (delim_len < 1)
+ return list(text)
+
+ . = list()
+ var/last_found = 1
+ var/found
+
+ do
+ found = findtext(text, delimiter, last_found, 0)
+ . += copytext(text, last_found, found)
+ last_found = found + delim_len
+ while (found)
+
/proc/type2parent(child)
var/string_type = "[child]"
var/last_slash = findlasttext(string_type, "/")
- if(last_slash == 1)
- switch(child)
- if(/datum)
- return null
- if(/obj || /mob)
- return /atom/movable
- if(/area || /turf)
- return /atom
- else
- return /datum
+ if (last_slash != 1)
+ return text2path(copytext(string_type, 1, last_slash))
+ switch (child)
+ if (/datum)
+ return null
+ if (/obj, /mob)
+ return /atom/movable
+ if (/area, /turf)
+ return /atom
+ else
+ return /datum
- return text2path(copytext(string_type, 1, last_slash))
//checks if a file exists and contains text
//returns text as a string if these conditions are met
@@ -315,4 +422,4 @@
error("File not found ([filename])")
catch(var/exception/E)
if(error_on_invalid_return)
- error("Exception when loading file as string: [E]")
\ No newline at end of file
+ error("Exception when loading file as string: [E]")
diff --git a/code/controllers/subsystems/overlays.dm b/code/controllers/subsystems/overlays.dm
index 92400e495b..25dbfbd62a 100644
--- a/code/controllers/subsystems/overlays.dm
+++ b/code/controllers/subsystems/overlays.dm
@@ -1,176 +1,149 @@
SUBSYSTEM_DEF(overlays)
name = "Overlay"
flags = SS_TICKER
- wait = 1
+ wait = 1 // SS_TICKER - Ticks
priority = FIRE_PRIORITY_OVERLAYS
init_order = INIT_ORDER_OVERLAY
- var/list/queue // Queue of atoms needing overlay compiling (TODO-VERIFY!)
- var/list/stats
- var/list/overlay_icon_state_caches // Cache thing
- var/list/overlay_icon_cache // Cache thing
+ /// The queue of atoms that need overlay updates.
+ var/static/tmp/list/queue = list()
- var/static/image/stringbro
- var/static/image/iconbro
- var/static/image/appearance_bro
+ /// A list([icon] = list([state] = [appearance], ...), ...) cache of appearances.
+ var/static/tmp/list/state_cache = list()
-/datum/controller/subsystem/overlays/PreInit()
- overlay_icon_state_caches = list()
- overlay_icon_cache = list()
- queue = list()
- stats = list()
+ /// A list([icon] = [appearance], ...) cache of appearances.
+ var/static/tmp/list/icon_cache = list()
- stringbro = new()
- iconbro = new()
- appearance_bro = new()
+ /// The number of appearances currently cached.
+ var/static/tmp/cache_size = 0
-/datum/controller/subsystem/overlays/Initialize()
- fire(mc_check = FALSE)
+
+/datum/controller/subsystem/overlays/Recover()
+ queue.Cut()
+ state_cache.Cut()
+ icon_cache.Cut()
+ cache_size = 0
+ for (var/atom/atom)
+ atom.flags &= ~OVERLAY_QUEUED
+ CHECK_TICK
+
+
+/datum/controller/subsystem/overlays/Initialize(timeofday)
+ fire(FALSE, TRUE)
..()
/datum/controller/subsystem/overlays/stat_entry()
- ..("Ov:[length(queue)]")
+ ..("Queued Atoms: [queue.len], Cache Size: [cache_size]")
-/datum/controller/subsystem/overlays/Shutdown()
- text2file(render_stats(stats), "[log_path]-overlay.log")
-
-/datum/controller/subsystem/overlays/Recover()
- overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches
- overlay_icon_cache = SSoverlays.overlay_icon_cache
- queue = SSoverlays.queue
-
-
-/datum/controller/subsystem/overlays/fire(resumed = FALSE, mc_check = TRUE)
- var/list/queue = src.queue
- var/static/count = 0
- if (count)
- var/c = count
- count = 0 //so if we runtime on the Cut, we don't try again.
- queue.Cut(1,c+1)
-
- for (var/thing in queue)
- count++
- if(thing)
- STAT_START_STOPWATCH
- var/atom/A = thing
- COMPILE_OVERLAYS(A)
- STAT_STOP_STOPWATCH
- STAT_LOG_ENTRY(stats, A.type)
- if(mc_check)
- if(MC_TICK_CHECK)
- break
- else
+/datum/controller/subsystem/overlays/fire(resumed, no_mc_tick)
+ var/count = 1
+ for (var/atom/atom as anything in queue)
+ ++count
+ atom?.UpdateOverlays()
+ if (no_mc_tick)
CHECK_TICK
+ else if (MC_TICK_CHECK)
+ queue.Cut(1, count)
+ return
+ queue.Cut()
- if (count)
- queue.Cut(1,count+1)
- count = 0
-/proc/iconstate2appearance(icon, iconstate)
- // var/static/image/stringbro = new() // Moved to be superglobal due to BYOND insane init order stupidness.
- var/list/icon_states_cache = SSoverlays.overlay_icon_state_caches
- var/list/cached_icon = icon_states_cache[icon]
- if (cached_icon)
- var/cached_appearance = cached_icon["[iconstate]"]
- if (cached_appearance)
- return cached_appearance
- SSoverlays.stringbro.icon = icon
- SSoverlays.stringbro.icon_state = iconstate
- if (!cached_icon) //not using the macro to save an associated lookup
- cached_icon = list()
- icon_states_cache[icon] = cached_icon
- var/cached_appearance = SSoverlays.stringbro.appearance
- cached_icon["[iconstate]"] = cached_appearance
- return cached_appearance
+/datum/controller/subsystem/overlays/proc/GetStateAppearance(icon, state)
+ var/list/subcache = state_cache[icon]
+ if (!subcache)
+ subcache = list()
+ state_cache[icon] = subcache
+ if (!subcache[state])
+ var/image/image = new (icon, null, state)
+ subcache[state] = image.appearance
+ ++cache_size
+ return subcache[state]
-/proc/icon2appearance(icon)
- // var/static/image/iconbro = new() // Moved to be superglobal due to BYOND insane init order stupidness.
- var/list/icon_cache = SSoverlays.overlay_icon_cache
- . = icon_cache[icon]
- if (!.)
- SSoverlays.iconbro.icon = icon
- . = SSoverlays.iconbro.appearance
- icon_cache[icon] = .
-/atom/proc/build_appearance_list(old_overlays)
- // var/static/image/appearance_bro = new() // Moved to be superglobal due to BYOND insane init order stupidness.
- var/list/new_overlays = list()
- if (!islist(old_overlays))
- old_overlays = list(old_overlays)
- for (var/overlay in old_overlays)
- if(!overlay)
+/datum/controller/subsystem/overlays/proc/GetIconAppearance(icon)
+ if (!icon_cache[icon])
+ var/image/image = new (icon)
+ icon_cache[icon] = image.appearance
+ ++cache_size
+ return icon_cache[icon]
+
+
+/datum/controller/subsystem/overlays/proc/GetAppearanceList(atom/subject, list/sources)
+ if (!sources)
+ return list()
+ if (!islist(sources))
+ sources = list(sources)
+ var/list/result = list()
+ var/icon/icon = subject.icon
+ for (var/atom/entry as anything in sources)
+ if (!entry)
continue
- if (istext(overlay))
- new_overlays += iconstate2appearance(icon, overlay)
- else if(isicon(overlay))
- new_overlays += icon2appearance(overlay)
+ else if (istext(entry))
+ result += GetStateAppearance(icon, entry)
+ else if (isicon(entry))
+ result += GetIconAppearance(entry)
else
- if(isloc(overlay))
- var/atom/A = overlay
- if (A.flags & OVERLAY_QUEUED)
- COMPILE_OVERLAYS(A)
- SSoverlays.appearance_bro.appearance = overlay //this works for images and atoms too!
- if(!ispath(overlay))
- var/image/I = overlay
- SSoverlays.appearance_bro.dir = I.dir
- new_overlays += SSoverlays.appearance_bro.appearance
- return new_overlays
+ if (isloc(entry))
+ if (entry.flags & OVERLAY_QUEUED)
+ entry.ImmediateOverlayUpdate()
+ if (!ispath(entry))
+ result += entry.appearance
+ else
+ var/image/image = entry
+ result += image.appearance
+ return result
-#define NOT_QUEUED_ALREADY (!(flags & OVERLAY_QUEUED))
-#define QUEUE_FOR_COMPILE flags |= OVERLAY_QUEUED; SSoverlays.queue += src;
-/**
- * Cut all of atom's normal overlays. Usually leaves "priority" overlays untouched.
- *
- * @param priority If true, also will cut priority overlays.
- */
-/atom/proc/cut_overlays(priority = FALSE)
- var/list/cached_overlays = our_overlays
- var/list/cached_priority = priority_overlays
-
- var/need_compile = FALSE
-
- if(LAZYLEN(cached_overlays)) //don't queue empty lists, don't cut priority overlays
- cached_overlays.Cut() //clear regular overlays
- need_compile = TRUE
-
- if(priority && LAZYLEN(cached_priority))
- cached_priority.Cut()
- need_compile = TRUE
-
- if(NOT_QUEUED_ALREADY && need_compile)
- QUEUE_FOR_COMPILE
-
-/**
- * Removes specific overlay(s) from the atom. Usually does not remove them from "priority" overlays.
- *
- * @param overlays The overlays to removed, type can be anything that is allowed for add_overlay().
- * @param priority If true, also will remove them from the "priority" overlays.
- */
-/atom/proc/cut_overlay(list/overlays, priority)
- if(!overlays)
+/// Enqueues the atom for an overlay update if not already queued
+/atom/proc/QueueOverlayUpdate()
+ if (flags & OVERLAY_QUEUED)
return
+ SSoverlays.queue += src
+ flags |= OVERLAY_QUEUED
- overlays = build_appearance_list(overlays)
- var/list/cached_overlays = our_overlays //sanic
- var/list/cached_priority = priority_overlays
- var/init_o_len = LAZYLEN(cached_overlays)
- var/init_p_len = LAZYLEN(cached_priority) //starter pokemon
+/// Builds the atom's overlay state from caches
+/atom/proc/UpdateOverlays()
+ if (gc_destroyed)
+ if (length(overlays))
+ overlays.Cut()
+ return
+ flags &= ~OVERLAY_QUEUED
+ if (length(priority_overlays))
+ if (length(our_overlays))
+ overlays = priority_overlays + our_overlays
+ else
+ overlays = priority_overlays
+ else if (length(our_overlays))
+ overlays = our_overlays
+ else
+ overlays.Cut()
- LAZYREMOVE(cached_overlays, overlays)
- if(priority)
- LAZYREMOVE(cached_priority, overlays)
- if(NOT_QUEUED_ALREADY && ((init_o_len != LAZYLEN(cached_overlays)) || (init_p_len != LAZYLEN(cached_priority))))
- QUEUE_FOR_COMPILE
+/// Immediately runs an overlay update and dequeues the atom
+/atom/proc/ImmediateOverlayUpdate()
+ SSoverlays.queue -= src
+ UpdateOverlays()
+
+
+/// Clears the atom's overlay cache(s) and queues an update if needed
+/atom/proc/cut_overlays(priority)
+ if (priority)
+ if (!length(priority_overlays))
+ return
+ priority_overlays.Cut()
+ QueueOverlayUpdate()
+ else if (length(our_overlays))
+ our_overlays.Cut()
+ QueueOverlayUpdate()
+
/**
* Adds specific overlay(s) to the atom.
* It is designed so any of the types allowed to be added to /atom/overlays can be added here too. More details below.
*
- * @param overlays The overlay(s) to add. These may be
+ * @param add The overlay(s) to add. These may be
* - A string: In which case it is treated as an icon_state of the atom's icon.
* - An icon: It is treated as an icon.
* - An atom: Its own overlays are compiled and then it's appearance is added. (Meaning its current apperance is frozen).
@@ -179,30 +152,46 @@ SUBSYSTEM_DEF(overlays)
* - Or a list containing any of the above.
* @param priority The overlays are added to the "priority" list istead of the normal one.
*/
-/atom/proc/add_overlay(list/overlays, priority = FALSE)
- if(!overlays)
+/atom/proc/add_overlay(list/add, priority)
+ if (!add)
return
-
- overlays = build_appearance_list(overlays)
-
- LAZYINITLIST(our_overlays) //always initialized after this point
- LAZYINITLIST(priority_overlays)
-
- var/list/cached_overlays = our_overlays //sanic
- var/list/cached_priority = priority_overlays
- var/init_o_len = cached_overlays.len
- var/init_p_len = cached_priority.len //starter pokemon
- var/need_compile
-
- if(priority)
- cached_priority += overlays //or in the image. Can we use [image] = image?
- need_compile = init_p_len != cached_priority.len
+ add = SSoverlays.GetAppearanceList(src, add)
+ if (!length(add))
+ return
+ if (priority)
+ if (priority_overlays)
+ priority_overlays += add
+ else
+ priority_overlays = add
+ else if (our_overlays)
+ our_overlays += add
else
- cached_overlays += overlays
- need_compile = init_o_len != cached_overlays.len
+ our_overlays = add
+ QueueOverlayUpdate()
+
+
+/**
+ * Removes specific overlay(s) from the atom. Usually does not remove them from "priority" overlays.
+ *
+ * @param overlays The overlays to removed, type can be anything that is allowed for add_overlay().
+ * @param priority If true, also will remove them from the "priority" overlays.
+ */
+/atom/proc/cut_overlay(list/cut, priority)
+ if (!cut)
+ return
+ cut = SSoverlays.GetAppearanceList(src, cut)
+ if (!length(cut))
+ return
+ var/update
+ if (priority && length(priority_overlays))
+ priority_overlays -= cut
+ update = TRUE
+ if (length(our_overlays))
+ our_overlays -= cut
+ update = TRUE
+ if (update)
+ QueueOverlayUpdate()
- if(NOT_QUEUED_ALREADY && need_compile) //have we caught more pokemon?
- QUEUE_FOR_COMPILE
/**
* Copy the overlays from another atom, either replacing all of ours or appending to our existing overlays.
@@ -211,22 +200,21 @@ SUBSYSTEM_DEF(overlays)
* @param other The atom to copy overlays from.
* @param cut_old If true, all of our overlays will be *replaced* by the other's. If other is null, that means cutting all ours.
*/
-/atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom
- if(!other)
- if(cut_old)
+/atom/proc/copy_overlays(atom/other, cut)
+ if (!other)
+ if (cut)
cut_overlays()
return
+ if (!length(other.our_overlays))
+ if (cut)
+ cut_overlays()
+ return
+ if (cut || !length(our_overlays))
+ our_overlays = other.our_overlays.Copy()
+ else
+ our_overlays |= other.our_overlays
+ QueueOverlayUpdate()
- var/list/cached_other = other.our_overlays
- if(cached_other)
- if(cut_old || !LAZYLEN(our_overlays))
- our_overlays = cached_other.Copy()
- else
- our_overlays |= cached_other
- if(NOT_QUEUED_ALREADY)
- QUEUE_FOR_COMPILE
- else if(cut_old)
- cut_overlays()
/**
* Returns a list of overlays that the target atom has
@@ -236,37 +224,32 @@ SUBSYSTEM_DEF(overlays)
*/
/proc/get_overlays(atom/other, priority, special)
var/list/including = list()
- if(!other)
+ if (!other)
return including
-
- for(var/image/I as anything in other.our_overlays)
- if(!special && I.plane > 0)
+ for (var/image/I as anything in other.our_overlays)
+ if (!special && I.plane > 0)
continue
including += I
-
- if(!priority)
+ if (!priority)
return including
-
- for(var/image/I as anything in other.priority_overlays)
- if(!special && I.plane > 0)
+ for (var/image/I as anything in other.priority_overlays)
+ if (!special && I.plane > 0)
continue
including += I
-
return including
-#undef NOT_QUEUED_ALREADY
-#undef QUEUE_FOR_COMPILE
-
-//TODO: Better solution for these?
/image/proc/add_overlay(x)
overlays += x
+
/image/proc/cut_overlay(x)
overlays -= x
+
/image/proc/cut_overlays(x)
overlays.Cut()
+
/image/proc/copy_overlays(atom/other, cut_old)
if(!other)
if(cut_old)
diff --git a/code/controllers/subsystems/transcore_vr.dm b/code/controllers/subsystems/transcore_vr.dm
index 6bffac865d..81364db733 100644
--- a/code/controllers/subsystems/transcore_vr.dm
+++ b/code/controllers/subsystems/transcore_vr.dm
@@ -74,9 +74,13 @@ SUBSYSTEM_DEF(transcore)
//In a human
BITSET(H.hud_updateflag, BACKUP_HUD)
- if(H == imp.imp_in && H.mind && H.stat < DEAD)
- db.m_backup(H.mind,H.nif)
- persist_nif_data(H)
+ if(H == imp.imp_in && H.stat < DEAD) //CHOMPEdit Start
+ if(H.mind)
+ db.m_backup(H.mind,H.nif)
+ persist_nif_data(H)
+ else if(H.vr_link && H.vr_link.mind)
+ db.m_backup(H.vr_link.mind,H.nif)
+ persist_nif_data(H) //CHOMPEdit End
if(MC_TICK_CHECK)
return
diff --git a/code/datums/components/material_container.dm b/code/datums/components/material_container.dm
index fbad2752ee..2b0c74e269 100644
--- a/code/datums/components/material_container.dm
+++ b/code/datums/components/material_container.dm
@@ -152,6 +152,11 @@
to_chat(user, "[parent] cannot contain [material].")
return
+ // Our sheet had no material. Whoops.
+ if(!matter_per_sheet)
+ to_chat(user, "[S] does not contain any matter acceptable by [parent].")
+ return
+
// If we can't fit the material for one sheet, we're full.
if(!has_space(matter_per_sheet))
to_chat(user, "[parent] is full. Please remove materials from [parent] in order to insert more.")
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index a3627ada9b..4c53798f81 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -339,18 +339,7 @@ var/global/list/PDA_Manifest = list()
var/datum/job/J = SSjob.get_job(H.mind.assigned_role)
hidden = J?.offmap_spawn
- /* Note: Due to cached_character_icon, a number of emergent properties occur due to the initialization
- * order of readied-up vs latejoiners. Namely, latejoiners will get a uniform in their datacore picture, but readied-up will
- * not. This is due to the fact that SSticker calls data_core.manifest_inject() inside of ticker/proc/create_characters(),
- * but does not equip them until ticker/proc/equip_characters(), which is called later. So, this proc is literally called before
- * they ever get their equipment, and so it can't get a picture of them in their equipment.
- * Latejoiners do not have this problem, because /mob/new_player/proc/AttemptLateSpawn calls EquipRank() before it calls
- * this proc, which means that they're already clothed by the time they get their picture taken here.
- * The COMPILE_OVERLAYS() here is just to bypass SSoverlays taking for-fucking-ever to update the mob, since we're about to
- * take a picture of them, we want all the overlays.
- */
- COMPILE_OVERLAYS(H)
- SSoverlays.queue -= H
+ H.ImmediateOverlayUpdate()
var/id = generate_record_id()
//General Record
diff --git a/code/datums/looping_sounds/machinery_sounds.dm b/code/datums/looping_sounds/machinery_sounds.dm
index 0330811428..d7011dd094 100644
--- a/code/datums/looping_sounds/machinery_sounds.dm
+++ b/code/datums/looping_sounds/machinery_sounds.dm
@@ -80,7 +80,7 @@
/datum/looping_sound/cerealmaker
start_sound = 'sound/machines/kitchen/cerealmaker/cerealmaker-start.ogg'
- start_length = 10
+ start_length = 10
mid_sounds = list('sound/machines/kitchen/cerealmaker/cerealmaker-mid1.ogg'=10)
mid_length = 60
end_sound = 'sound/machines/kitchen/cerealmaker/cerealmaker-stop.ogg'
@@ -104,4 +104,14 @@
mid_length = 70
end_sound = 'sound/machines/air_pump/airpumpshutdown.ogg'
volume = 15
- pref_check = /datum/client_preference/air_pump_noise
\ No newline at end of file
+ pref_check = /datum/client_preference/air_pump_noise
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/datum/looping_sound/vehicle_engine
+ start_sound = 'sound/machines/vehicle/engine_start.ogg'
+ start_length = 2
+ mid_sounds = list('sound/machines/vehicle/engine_mid.ogg'=1)
+ mid_length = 6
+ end_sound = 'sound/machines/vehicle/engine_end.ogg'
+ volume = 20
diff --git a/code/datums/riding.dm b/code/datums/riding.dm
index 9dd32dcd93..ec5afff5d5 100644
--- a/code/datums/riding.dm
+++ b/code/datums/riding.dm
@@ -225,3 +225,28 @@
/datum/riding/boat/get_offsets(pass_index) // list(dir = x, y, layer)
return list("[NORTH]" = list(1, 2), "[SOUTH]" = list(1, 2), "[EAST]" = list(1, 2), "[WEST]" = list(1, 2))
+
+/datum/riding/snowmobile
+ only_one_driver = TRUE // Keep your hands to yourself back there!
+
+/datum/riding/snowmobile/get_offsets(pass_index) // list(dir = x, y, layer)
+ var/H = 3 // Horizontal seperation.
+ var/V = 2 // Vertical seperation.
+ var/O = 2 // Vertical offset.
+ switch(pass_index)
+ if(1) // Person on front.
+ return list(
+ "[NORTH]" = list( 0, O+V, MOB_LAYER),
+ "[SOUTH]" = list( 0, O, ABOVE_MOB_LAYER),
+ "[EAST]" = list( H, O, MOB_LAYER),
+ "[WEST]" = list(-H, O, MOB_LAYER)
+ )
+ if(2) // Person on back.
+ return list(
+ "[NORTH]" = list( 0, O, ABOVE_MOB_LAYER),
+ "[SOUTH]" = list( 0, O+V, MOB_LAYER),
+ "[EAST]" = list(-H, O, MOB_LAYER),
+ "[WEST]" = list( H, O, MOB_LAYER)
+ )
+ else
+ return null // This will runtime, but we want that since this is out of bounds.
diff --git a/code/datums/roundstats/roundstats.dm b/code/datums/roundstats/roundstats.dm
index 2fc1950bb6..0c25b83838 100644
--- a/code/datums/roundstats/roundstats.dm
+++ b/code/datums/roundstats/roundstats.dm
@@ -25,6 +25,8 @@ GLOBAL_VAR_INIT(prey_eaten_roundstat, 0) //VOREStation Edit - Obviously
GLOBAL_VAR_INIT(prey_absorbed_roundstat, 0) //VOREStation Edit - Obviously
GLOBAL_VAR_INIT(prey_digested_roundstat, 0) //VOREStation Edit - Obviously
GLOBAL_VAR_INIT(items_digested_roundstat, 0) //VOREStation Edit - Obviously
+var/global/list/security_printer_tickets = list() //VOREStation Edit
+
/hook/roundend/proc/RoundTrivia()//bazinga
var/list/valid_stats_list = list() //This is to be populated with the good shit
@@ -54,6 +56,22 @@ GLOBAL_VAR_INIT(items_digested_roundstat, 0) //VOREStation Edit - Obviously
else if(GLOB.disposals_flush_shift_roundstat > 40)
valid_stats_list.Add("The disposal system flushed a whole [GLOB.disposals_flush_shift_roundstat] times for this shift. We should really invest in waste treatement.")
+ //VOREStation add Start - Ticket time!
+ if(security_printer_tickets.len)
+ valid_stats_list.Add("[security_printer_tickets.len] unique security tickets were issued today!
Examples include:")
+ var/good_num = 5
+ var/ourticket
+ while(good_num > 0)
+ ourticket = null
+ if(security_printer_tickets.len)
+ ourticket = pick(security_printer_tickets)
+ security_printer_tickets -= ourticket
+ if(ourticket)
+ valid_stats_list.Add("-\"[ourticket]\"")
+ good_num--
+ else
+ good_num = 0
+
//VOREStation Add Start - Vore stats lets gooooo
if(GLOB.prey_eaten_roundstat > 0)
valid_stats_list.Add("A total of [GLOB.prey_eaten_roundstat] individuals were eaten today!")
diff --git a/code/datums/supplypacks/hydroponics_vr.dm b/code/datums/supplypacks/hydroponics_vr.dm
index 7476fdd29b..fa912852e7 100644
--- a/code/datums/supplypacks/hydroponics_vr.dm
+++ b/code/datums/supplypacks/hydroponics_vr.dm
@@ -70,4 +70,10 @@
name = "Jerboa crate"
cost = 10
containertype = /obj/structure/largecrate/animal/jerboa
- containername = "Jerboa crate"
\ No newline at end of file
+ containername = "Jerboa crate"
+
+/datum/supply_pack/hydro/tits
+ name = "A pair of great tits"
+ cost = 10
+ containertype = /obj/structure/largecrate/tits
+ containername = "A pair of great tits"
diff --git a/code/datums/supplypacks/misc_vr.dm b/code/datums/supplypacks/misc_vr.dm
index dbe2143e03..8118ff0ab1 100644
--- a/code/datums/supplypacks/misc_vr.dm
+++ b/code/datums/supplypacks/misc_vr.dm
@@ -161,3 +161,18 @@
cost = 300
containertype = /obj/structure/closet/crate
containername = "cordless jukebox speakers crate"
+
+/datum/supply_pack/misc/explorer_headsets
+ name = "shortwave-capable headsets (x4)"
+ contains = list(
+ /obj/item/device/radio/headset/explorer = 4
+ )
+ cost = 20
+ containertype = /obj/structure/closet/crate/secure/gear
+ containername = "exploration radio headsets crate"
+ access = list(
+ access_explorer,
+ access_eva,
+ access_pilot
+ )
+ one_access = TRUE
diff --git a/code/datums/supplypacks/security.dm b/code/datums/supplypacks/security.dm
index 5c4ddf1a6a..fc8d9b373b 100644
--- a/code/datums/supplypacks/security.dm
+++ b/code/datums/supplypacks/security.dm
@@ -444,7 +444,8 @@
/obj/item/weapon/storage/belt/security = 3,
/obj/item/clothing/glasses/sunglasses/sechud = 3,
/obj/item/device/radio/headset/headset_sec/alt = 3,
- /obj/item/clothing/suit/storage/hooded/wintercoat/security = 3
+ /obj/item/clothing/suit/storage/hooded/wintercoat/security = 3,
+ /obj/item/clothing/glasses/sunglasses/sechud/tactical_sec_vis = 3
)
cost = 10
containertype = /obj/structure/closet/crate/nanothreads
diff --git a/code/datums/underwear/socks.dm b/code/datums/underwear/socks.dm
index e1fe7e07f2..16465cfb61 100644
--- a/code/datums/underwear/socks.dm
+++ b/code/datums/underwear/socks.dm
@@ -60,4 +60,128 @@
/datum/category_item/underwear/socks/leggings
name = "Leggings"
- icon_state = "leggings"
\ No newline at end of file
+ icon_state = "leggings"
+
+
+
+//NEW SOCKS BELOW HERE
+/datum/category_item/underwear/socks/white_norm
+ name = "White Socks"
+ icon_state = "white_norm"
+ has_color = TRUE
+
+/datum/category_item/underwear/socks/white_short
+ name = "Short White Socks"
+ icon_state = "white_short"
+ has_color = TRUE
+
+/datum/category_item/underwear/socks/white_knee
+ name = "White Knee Socks"
+ icon_state = "white_knee"
+ has_color = TRUE
+
+/datum/category_item/underwear/socks/white_thigh
+ name = "White Thigh Socks"
+ icon_state = "white_thigh"
+ has_color = TRUE
+
+/datum/category_item/underwear/socks/black_norm
+ name = "Black Socks"
+ icon_state = "black_norm"
+
+/datum/category_item/underwear/socks/black_short
+ name = "Short Black Socks"
+ icon_state = "black_short"
+
+/datum/category_item/underwear/socks/black_knee
+ name = "Black Knee Socks"
+ icon_state = "black_knee"
+
+/datum/category_item/underwear/socks/black_thigh
+ name = "Black Thigh Socks"
+ icon_state = "black_thigh"
+
+/datum/category_item/underwear/socks/assblastusa_knee
+ name = "Striped Patriotic Knee Socks"
+ icon_state = "assblastusa_knee"
+
+/datum/category_item/underwear/socks/assblastusa_thigh
+ name = "Striped Patriotic Thigh Socks"
+ icon_state = "assblastusa_thigh"
+
+/datum/category_item/underwear/socks/uk_knee
+ name = "United Kingdom Knee Socks"
+ icon_state = "uk_knee"
+
+/datum/category_item/underwear/socks/uk_thigh
+ name = "United Kingdom Thigh Socks"
+ icon_state = "uk_thigh"
+
+/datum/category_item/underwear/socks/commie_knee
+ name = "Yellow and Red Striped Knee Socks"
+ icon_state = "commie_knee"
+
+/datum/category_item/underwear/socks/commie_thigh
+ name = "Yellow and Red Striped Thigh Socks"
+ icon_state = "commie_thigh"
+
+/datum/category_item/underwear/socks/stockings_lpink
+ name = "Light Pink Stockings"
+ icon_state = "stockings_lpink"
+
+/datum/category_item/underwear/socks/stockings_purple
+ name = "Purple Stockings"
+ icon_state = "stockings_purple"
+
+/datum/category_item/underwear/socks/stockings_green
+ name = "Green Stockings"
+ icon_state = "stockings_green"
+
+/datum/category_item/underwear/socks/stockings_cyan
+ name = "Cyan Stockings"
+ icon_state = "stockings_cyan"
+
+/datum/category_item/underwear/socks/stockings_orange
+ name = "Orange Stockings"
+ icon_state = "stockings_orange"
+
+/datum/category_item/underwear/socks/stockings_yellow
+ name = "Yellow Stockings"
+ icon_state = "stockings_yellow"
+
+/datum/category_item/underwear/socks/stockings_dpink
+ name = "Dark Pink Stockings"
+ icon_state = "stockings_dpink"
+
+/datum/category_item/underwear/socks/stockings_blue
+ name = "Blue Stockings"
+ icon_state = "stockings_blue"
+
+/datum/category_item/underwear/socks/bee_thigh
+ name = "Bee Thigh Socks"
+ icon_state = "bee_thigh"
+
+/datum/category_item/underwear/socks/bee_knee
+ name = "Bee Knee Socks" //You do not know how much I want to make a 'bee's knees' pun.
+ icon_state = "bee_knee"
+
+/datum/category_item/underwear/socks/thocks
+ name = "Thocks"
+ icon_state = "thocks"
+ has_color = TRUE
+
+/datum/category_item/underwear/socks/ace_thigh
+ name = "Ace Pride Thigh Socks"
+ icon_state = "ace_thigh"
+
+/datum/category_item/underwear/socks/ace_knee
+ name = "Ace Pride Knee Socks"
+ icon_state = "ace_knee"
+
+/datum/category_item/underwear/socks/trans_knee
+ name = "Trans Pride Knee Socks"
+ icon_state = "trans_knee"
+
+/datum/category_item/underwear/socks/trans_thigh
+ name = "Trans Pride Thigh Socks"
+ icon_state = "trans_thigh"
diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index 99fc8efcf1..116a17c67e 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -29,9 +29,9 @@
/obj/item/weapon/soap
name = "soap"
- desc = "A cheap bar of soap. Doesn't smell."
+ desc = "A cheap bar of soap. Smells of lye."
gender = PLURAL
- icon = 'icons/obj/items.dmi'
+ icon = 'icons/obj/soap.dmi'
icon_state = "soap"
flags = NOCONDUCT
w_class = ITEMSIZE_SMALL
@@ -39,9 +39,15 @@
throwforce = 0
throw_speed = 4
throw_range = 20
+ var/randomize = TRUE
+ var/square_chance = 10
+
+/obj/item/weapon/soap/Initialize()
+ if(randomize && prob(square_chance))
+ icon_state = "[icon_state]-alt"
/obj/item/weapon/soap/nanotrasen
- desc = "A NanoTrasen-brand bar of soap. Smells of phoron."
+ desc = "A NanoTrasen-brand bar of soap. Smells of phoron, a years-old marketing gimmick."
icon_state = "soapnt"
/obj/item/weapon/soap/deluxe
@@ -55,6 +61,82 @@
desc = "An untrustworthy bar of soap. Smells of fear."
icon_state = "soapsyndie"
+/obj/item/weapon/soap/space_soap
+ desc = "Smells like hot metal and walnuts."
+ icon_state = "space_soap"
+
+/obj/item/weapon/soap/water_soap
+ desc = "Smells like chlorine."
+ icon_state = "water_soap"
+
+/obj/item/weapon/soap/fire_soap
+ desc = "Smells like a campfire."
+ icon_state = "fire_soap"
+
+/obj/item/weapon/soap/rainbow_soap
+ desc = "Smells sickly sweet."
+ icon_state = "rainbow_soap"
+
+/obj/item/weapon/soap/diamond_soap
+ desc = "Smells like saffron and vanilla."
+ icon_state = "diamond_soap"
+
+/obj/item/weapon/soap/uranium_soap
+ desc = "Smells not great... Not terrible."
+ icon_state = "uranium_soap"
+
+/obj/item/weapon/soap/silver_soap
+ desc = "Smells like birch and amaranth."
+ icon_state = "silver_soap"
+
+/obj/item/weapon/soap/brown_soap
+ desc = "Smells like cinnamon and cognac."
+ icon_state = "brown_soap"
+
+/obj/item/weapon/soap/white_soap
+ desc = "Smells like nutmeg and oats."
+ icon_state = "white_soap"
+
+/obj/item/weapon/soap/grey_soap
+ desc = "Smells like bergamot and lilies."
+ icon_state = "grey_soap"
+
+/obj/item/weapon/soap/pink_soap
+ desc = "Smells like bubblegum."
+ icon_state = "pink_soap"
+
+/obj/item/weapon/soap/purple_soap
+ desc = "Smells like lavender."
+ icon_state = "purple_soap"
+
+/obj/item/weapon/soap/blue_soap
+ desc = "Smells like cardamom."
+ icon_state = "blue_soap"
+
+/obj/item/weapon/soap/cyan_soap
+ desc = "Smells like bluebells and peaches."
+ icon_state = "cyan_soap"
+
+/obj/item/weapon/soap/green_soap
+ desc = "Smells like a freshly mowed lawn."
+ icon_state = "green_soap"
+
+/obj/item/weapon/soap/yellow_soap
+ desc = "Smells like citron and ginger."
+ icon_state = "yellow_soap"
+
+/obj/item/weapon/soap/orange_soap
+ desc = "Smells like oranges and dark chocolate."
+ icon_state = "orange_soap"
+
+/obj/item/weapon/soap/red_soap
+ desc = "Smells like cherries."
+ icon_state = "red_soap"
+
+/obj/item/weapon/soap/golden_soap
+ desc = "Smells like honey."
+ icon_state = "golden_soap"
+
/obj/item/weapon/bikehorn
name = "bike horn"
desc = "A horn off of a bicycle."
@@ -397,6 +479,7 @@
continue
remove_from_storage(B, T)
+
/obj/item/weapon/stock_parts
name = "stock part"
desc = "What?"
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 29c937afd6..a17be310bd 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -639,4 +639,4 @@
return selfimage
/atom/movable/proc/get_cell()
- return
+ return
\ No newline at end of file
diff --git a/code/game/gamemodes/events/holidays/Holidays.dm b/code/game/gamemodes/events/holidays/Holidays.dm
index c04d6408b6..9c156a50bd 100644
--- a/code/game/gamemodes/events/holidays/Holidays.dm
+++ b/code/game/gamemodes/events/holidays/Holidays.dm
@@ -22,7 +22,7 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
Holiday = list() // reset our switch now so we can recycle it as our Holiday name
- var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year
+ //var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year - unused currently but can be used for floating dates
var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
@@ -36,56 +36,63 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
Holiday["New Years's Day"] = "The day of the new solar year on Sol."
if(12)
Holiday["Vertalliq-Qerr"] = "Vertalliq-Qerr, translated to mean 'Festival of the Royals', is a \
- Skrell holiday that celebrates the Qerr-Katish and all they have provided for the rest of Skrell society, \
+ skrellian holiday that celebrates the Qerr-Katish and all they have provided for the rest of skrellian society, \
it often features colourful displays and skilled performers take this time to show off some of their more \
- fancy displays."
+ elaborate displays."
+ if(14)
+ Holiday["Lohri"] = "A human festival traditionally celebrating the end of winter on the Indian subcontinent. \
+ The holiday is now celebrated independently of seasons in many colonies with large populations of Indian \
+ descent. Traditions include the burning of bonfires, dancing, and door-to-door singing in exchange for treats."
+ if(30)
+ Holiday["Lunar New Year"] = "Originally the new year on the ancient lunisolar calendar, the Lunar New Year is \
+ celebrated with a wide variety of east Asian traditions with roots in Chinese, Japanese, Korean, Vietnamese, \
+ Tibetan, Mongolian, and Ryukyu cultures. Elaborate parades, performances, dances and meals are usual staples."
if(2) //Feb
switch(DD)
if(2)
- Holiday["Groundhog Day"] = "An unoffical holiday based on ancient folklore that originated on Earth, \
- that involves the worship of an almighty groundhog, that could control the weather based on if it casted a shadow."
+ Holiday["Groundhog Day"] = "An unoffical holiday based on medieval folklore that originated on Earth, \
+ that involves the reverence of a prophetic animal - traditionally a badger, fox or groundhog - that was \
+ said to be able to predict, or even control the changing of the seasons."
if(14)
- Holiday["Valentine's Day"] = "An old holiday that revolves around romance and love."
+ Holiday["Valentine's Day"] = "A human holiday that revolves around expressions of romance and love. \
+ In particular, the exchanging of gifts, letters and cards is traditional."
+ if(15)
+ Holiday["Lantern Festival"] = "A human holiday with origins in Chinese new year celebrations. Participants \
+ carry or hang elaborate paper lanterns that are thought to bring good luck. Today, electric lights are often used \
+ in environments where open flames would be hazardous or non-functional."
if(17)
Holiday["Random Acts of Kindness Day"] = "An unoffical holiday that challenges everyone to perform \
- acts of kindness to their friends, co-workers, and strangers, for no reason."
+ acts of kindness to their friends, co-workers, and strangers, with no strings attached."
if(3) //Mar
switch(DD)
if(3)
- Holiday["Qixm-tes"] = "Qixm-tes, or 'Day of mourning', is a Skrell holiday where Skrell gather at places \
- of worship and sing a song of mourning for all those who have died in service to their empire."
+ Holiday["Qixm-tes"] = "Qixm-tes, or 'Day of mourning', is a skrellian holiday where skrell gather at places \
+ of worship and sing a song of mourning for all those who have died in service to their kingdoms."
if(14)
Holiday["Pi Day"] = "An unoffical holiday celebrating the mathematical constant Pi. It is celebrated on \
March 14th, as the digits form 3 14, the first three significant digits of Pi. Observance of Pi Day generally \
involve eating (or throwing) pie, due to a pun. Pies also tend to be round, and thus relatable to Pi."
if(17)
- Holiday["St. Patrick's Day"] = "An old holiday originating from Earth, Sol, celebrating the color green, \
- shamrocks, attending parades, and drinking alcohol."
+ Holiday["St. Patrick's Day"] = "A holiday originating on Earth, celebrating a popular version of Irish culture. \
+ Traditions include elaborate parades, wearing of the colour green, and drinking alcohol."
+ if(18)
+ Holiday["Holi"] = "Also known as the Festival of Colours, a human Hindu festival celebrating divine love and the \
+ triumph of good over evil. Traditionally a bonfire is lit overnight, followed by the free-for-all smearing of \
+ celebrants with colourful pigments, and the forgiveness of past wrongs."
if(27)
- if(YY == 16)
- Holiday["Easter"] = ""
- if(31)
- if(YY == 13)
- Holiday["Easter"] = ""
+ Holiday["Easter"] = "A Earth springtime festival variously celebrating rebirth and the beginning of the planting \
+ season. Traditionally celebrated with the painting and exchange of eggs, sometimes made from chocolate. \
+ The holiday's date was standardized in the 22nd century."
if(4) //Apr
switch(DD)
if(1)
- Holiday["April Fool's Day"] = "An old holiday that endevours one to pull pranks and spread hoaxes on their friends."
- if(YY == 18)
- Holiday["Easter"] = ""
- if(8)
- if(YY == 15)
- Holiday["Easter"] = ""
- if(16)
- if(YY == 17) //Easter can go die for all of this copypasta.
- Holiday["Easter"] = ""
-
- if(20)
- if(YY == 14)
- Holiday["Easter"] = ""
+ Holiday["April Fool's Day"] = "A human holiday that endevours one to pull pranks and spread hoaxes on their friends."
+ if(5)
+ Holiday["First Day of Passover"] = "The first of eight days of a human holiday celebrating the exodus of ancient Jewish people \
+ from slavery, and of the spring harvest. The most well-known tradition is the Sedar meal. The date was standardized in the 22nd century."
if(22)
Holiday["Earth Day"] = "A holiday of enviromentalism, that originated on it's namesake, Earth."
@@ -100,7 +107,7 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
Observance of this day varies throughout human space, but most common traditions are the act of bringing flowers to graves,\
attending parades, and the wearing of poppies (either paper or real) in one's clothing."
if(28)
- Holiday["Jiql-tes"] = "A Skrellian holiday that translates to 'Day of Celebration', Skrell communities \
+ Holiday["Jiql-tes"] = "A skrellian holiday that translates to 'Day of Celebration', skrell communities \
gather for a grand feast and give gifts to friends and close relatives."
if(6) //Jun
@@ -113,7 +120,11 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
and to thank blood donors for their voluntary, life-saving gifts of blood."
if(20)
Holiday["Civil Servant's Day"] = "Civil Servant's Day is a holiday observed in SCG member states that honors civil servants everywhere,\
-+ (especially those who are members of the armed forces and the emergency services), or have been or have been civil servants in the past."
+ (especially those who are members of the armed forces and the emergency services), or have been or have been civil servants in the past."
+/* if(25)
+ Holiday["Merhyat Njarha"] = "A Njarir'Akhan tajaran tradition translating to \"Harmony of the House\", in which Njarjirii citizens pay \
+ homage to their ruling house and their ancestors. Traditions include large communal meals and dances hosted by the ruling house, \
+ and the intensive upkeep of community spaces."*/
if(7) //Jul
switch(DD)
@@ -126,36 +137,43 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
if(8) //Aug
switch(DD)
-// if(10)
-// Holiday["S'randarr's Day"] = "A Tajaran holiday that occurs on the longest day of the year in summer,
-// on Ahdomai. It is named after the Tajaran deity of Light, and huge celebrations are common."
-//VOREStation Add - Of course we need this.
- if(8)
- Holiday["Vore Day"] = "A holiday representing the innate desire in all/most/some/a few of us to devour each other or be devoured. \
- That's probably why you're here, isn't it? Get to it, then!"
-//VOREStation Add End.
-
+ if(11)
+ Holiday["Tajaran Contact Day"] = "The anniversary of first contact between SolGov and the tajaran species, widely observed\
+ throughout tajaran and human space. Marks the date that in 2513, a human exploration team investigating electromagnetic \
+ emissions from the Meralar system made radio contact with the tajaran scientific outpost that had broadcast them."
+ if(20)
+ Holiday["Obon"] = "An ancient Earth holiday originating in east Asia, for the honouring of one's ancestral spirits. \
+ Traditions include the maintenance of grave sites and memorials, and community traditional dance performances."
if(27)
Holiday["Forgiveness Day"] = "A time to forgive and be forgiven."
if(9) //Sep
switch(DD)
if(17)
- Holiday["Qill-xamr"] = "Translated to 'Night of the dead', it is a Skrell holiday where Skrell \
+ Holiday["Qill-xamr"] = "Translated to 'Night of the dead', it is a skrellian holiday where skrell \
communities hold parties in order to remember loved ones who passed, unlike Qixm-tes, this applies to everyone \
and is a joyful celebration."
if(19)
- Holiday["Talk-Like-a-Pirate Day"] = "Ahoy, matey! Tis unoffical holiday be celebratin' the jolly \
- good humor of speakin' like the pirates of old."
+ Holiday["Talk-Like-a-Pirate Day"] = "Ahoy, matey! It be the unoffical holiday celebratin' the salty \
+ sea humor of speakin' like the pirates of old."
+ if(20)
+ Holiday["Rosh Hashanah"] = "An old human holiday that marks the traditional Hebrew new year."
if(28)
Holiday["Stupid-Questions Day"] = "Known as Ask A Stupid Question Day, it is an unoffical holiday \
created by teachers in Sol, very long ago, to encourage students to ask more questions in the classroom."
if(10) //Oct
switch(DD)
+ if(9)
+ Holiday["Lief Eriksson Day"] = "A day commemorating Norse explorer Lief Eriksson, an early Scandinavian cultural figure \
+ who is thought to have been the first European to set foot in North America."
if(16)
Holiday["Boss' Day"] = "Boss' Day has traditionally been a day for employees to thank their bosses for the difficult work that they do \
throughout the year. This day was created for the purpose of strengthening the bond between employer and employee."
+ if(21)
+ Holiday["First Day of Diwali"] = "An ancient Hindu, Jain and Sikh festival lasting five days, celebrating victory of light over darkness, good over \
+ evil, and knowledge over ignorance. It is celebrated by the wearing of your finest clothes, decorating with oil lamps and rangolis, \
+ fireworks, and gift-giving. Electric lights are often used in modern times where oil lamps would be hazardous or inoperable."
if(31)
Holiday["Halloween"] = "Originating from Earth, Halloween is also known as All Saints' Eve, and \
is celebrated by some by attending costume parties, trick-or-treating, carving faces in pumpkins, or visiting \
@@ -163,6 +181,10 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
if(11) //Nov
switch(DD)
+ if(1)
+ Holiday["Day of the Dead"] = "An old human holiday celebrating the lives of deceased friends and family members, \
+ by means of good humour and joyful parties. Offerings are often left at altars to the dead, and exchanging gifts \
+ among the living is not uncommon."
if(13)
Holiday["Kindness Day"] = "Kindness Day is an unofficial holiday to highlight good deeds in the \
community, focusing on the positive power and the common thread of kindness which binds humanity and \
@@ -182,16 +204,17 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
if(10)
Holiday["Human-Rights Day"] = "An old holiday created by an intergovernmental organization known back than as the United Nations, \
human rights were not recognized globally at the time, and the holiday was made in honor of the Universal Declaration of Human Rights. \
- These days, SolGov ensures that past efforts were not in vein, and continues to honor this holiday across the galaxy."
+ These days, SolGov ensures that past efforts were not in vein, and continues to honor this holiday across the galaxy as a historical \
+ reminder."
if(22)
- Holiday["Vertalliq-qixim"] = "A Skrellian holiday that celebrates the Skrell's first landing on one of \
- their moons. It's often celebrated with grand festivals."
+ Holiday["Vertalliq-qixim"] = "A skrellian holiday that celebrates the skrell's first landing on one of \
+ their moons. It's often celebrated with grand festivals."
if(24)
Holiday["Christmas Eve"] = "The eve of Christmas, an old holiday from Earth that mainly involves gift \
giving, decorating, family reunions, and a fat red human breaking into people's homes to steal milk and cookies."
if(25)
Holiday["Christmas"] = "Christmas is a very old holiday that originated in Earth, Sol. It was a \
- religious holiday for the Christian religion, which would later form Unitarianism. Nowdays, the holiday is celebrated \
+ religious holiday for the Christian religion, which would later form Unitarianism. Nowadays, the holiday is celebrated \
generally by giving gifts, symbolic decoration, and reuniting with one's family. It also features a mythical fat \
red human, known as Santa, who broke into people's homes to loot cookies and milk."
if(31)
diff --git a/code/game/jobs/job/civilian_vr.dm b/code/game/jobs/job/civilian_vr.dm
index e33bbf11d9..9c5de6d54b 100644
--- a/code/game/jobs/job/civilian_vr.dm
+++ b/code/game/jobs/job/civilian_vr.dm
@@ -30,7 +30,7 @@
spawn_positions = 2
pto_type = PTO_CIVILIAN
alt_titles = list("Hydroponicist" = /datum/alt_title/hydroponicist, "Cultivator" = /datum/alt_title/cultivator, "Farmer" = /datum/alt_title/farmer,
- "Gardener" = /datum/alt_title/gardener, "Florist" = /datum/alt_title/florsit)
+ "Gardener" = /datum/alt_title/gardener, "Florist" = /datum/alt_title/florsit, "Rancher" = /datum/alt_title/rancher)
/datum/alt_title/hydroponicist
title = "Hydroponicist"
@@ -45,6 +45,10 @@
title = "Florist"
title_blurb = "A Florist may be less professional than their counterparts, and are more likely to tend to the public gardens if they aren't needed elsewhere."
+/datum/alt_title/rancher
+ title = "Rancher"
+ title_blurb = "A Rancher is tasked with the care, feeding, raising, and harvesting of livestock."
+
/datum/job/qm
pto_type = PTO_CARGO
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index 509572aa98..b0e678298b 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -147,7 +147,7 @@
var/mob/living/carbon/human/dummy/mannequin/mannequin = get_mannequin("#job_icon")
dress_mannequin(mannequin)
mannequin.dir = SOUTH
- COMPILE_OVERLAYS(mannequin)
+ mannequin.ImmediateOverlayUpdate()
var/icon/preview_icon = getFlatIcon(mannequin)
preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser.
@@ -174,6 +174,10 @@
//return (brain_type && LAZYACCESS(ideal_age_by_species, brain_type)) || LAZYACCESS(ideal_age_by_species, brain_type) || ideal_character_age //VOREStation Removal
/datum/job/proc/is_species_banned(species_name, brain_type)
+ // CHOMPEdit begin -- Shadekin cannot be any crew position
+ if(species_name == SPECIES_SHADEKIN)
+ return TRUE
+ // CHOMPEdit end
return FALSE // VOREStation Edit - Any species can be any job.
/* VOREStation Removal
if(banned_job_species == null)
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index 570fbf32ab..63f8a702e0 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -657,8 +657,7 @@ var/global/datum/controller/occupations/job_master
var/obj/belly/vore_spawn_gut
var/mob/living/prey_to_nomph
- var/datum/job/J = SSjob.get_job(rank)
- fail_deadly = J?.offmap_spawn
+ //CHOMPEdit - Remove fail_deadly addition on offmap_spawn
//Spawn them at their preferred one
if(C && C.prefs.spawnpoint)
@@ -804,7 +803,8 @@ var/global/datum/controller/occupations/job_master
.["msg"] = spawnpos.msg
.["channel"] = spawnpos.announce_channel
else
- if(fail_deadly)
+ var/datum/job/J = SSjob.get_job(rank)
+ if(fail_deadly || J?.offmap_spawn)
to_chat(C, "Your chosen spawnpoint ([spawnpos.display_name]) is unavailable for your chosen job. Please correct your spawn point choice.")
return
to_chat(C, "Your chosen spawnpoint ([spawnpos.display_name]) is unavailable for your chosen job. Spawning you at the Arrivals shuttle instead.")
diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm
index 3c949ba66d..e71f4eb72b 100644
--- a/code/game/jobs/jobs.dm
+++ b/code/game/jobs/jobs.dm
@@ -51,6 +51,8 @@ var/const/ASSISTANT =(1<<11)
var/const/BRIDGE =(1<<12)
var/const/ENTERTAINER =(1<<13) //VOREStation Add
+var/const/OTHER =(1<<10) //CHOMPStation Add
+var/const/NONCREW =(1<<0) //CHOMPStation Add
/* // CHOMPedit: Comment out Talon positions, we don't have that here.
//VOREStation Add
var/const/TALON =(1<<3)
diff --git a/code/game/machinery/casino_ch.dm b/code/game/machinery/casino_ch.dm
index 13c65bc335..e892d1218b 100644
--- a/code/game/machinery/casino_ch.dm
+++ b/code/game/machinery/casino_ch.dm
@@ -277,7 +277,7 @@
"sodawater", "lemon_lime", "sugar", "orangejuice", "limejuice", "watermelonjuice", "thirteenloko", "grapesoda",
"coffee", "cafe_latte", "soy_latte", "hot_coco", "milk", "cream", "tea", "ice", "orangejuice", "lemonjuice",
"limejuice", "berryjuice", "mint", "lemon_lime", "sugar", "orangejuice", "limejuice", "sodawater",
- "tonic", "beer", "kahlua", "whiskey", "wine", "vodka", "gin", "rum", "tequilla", "vermouth", "cognac",
+ "tonic", "beer", "kahlua", "whiskey", "redwine", "vodka", "gin", "rum", "tequilla", "vermouth", "cognac",
"ale", "mead", "bitters", "champagne", "singulo", "doctorsdelight", "nothing", "banana", "honey", "egg",
"coco", "cherryjelly", "carrotjuice", "applejuice", "tomatojuice", "peanutbutter", "soymilk", "grenadine", "gingerale", "roy_rogers",
"patron", "goldschlager", "gelatin", "melonliquor", "bluecuracao", "thirteenloko", "deadrum", "sake", "acidspit",
diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm
index 4efec263f8..1d45a3e508 100644
--- a/code/game/machinery/computer/Operating.dm
+++ b/code/game/machinery/computer/Operating.dm
@@ -184,7 +184,7 @@
/obj/machinery/computer/operating/proc/build_surgery_list(mob/user)
if(!istype(victim))
return null
-
+
. = list()
for(var/limb in victim.organs_by_name)
@@ -281,6 +281,7 @@
/datum/surgery_step/cavity,
/datum/surgery_step/limb,
/datum/surgery_step/brainstem,
+ /datum/surgery_step/generic/ripper,
)
good_surgeries = surgery_steps
for(var/datum/surgery_step/S in good_surgeries)
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 3b8d179cfa..3ae04b718b 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -526,12 +526,14 @@
//VOREStation Edit Start
var/depart_announce = TRUE
+ var/departing_job = to_despawn.mind.role_alt_title
+
if(istype(to_despawn, /mob/living/dominated_brain))
depart_announce = FALSE
if(depart_announce)
- announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]", announce_channel, using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE))
+ announce.autosay("[to_despawn.real_name][departing_job ? ", [departing_job], " : " "][on_store_message]", "[on_store_name]", announce_channel, using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE))
visible_message("\The [initial(name)] [on_store_visible_message_1] [to_despawn.real_name] [on_store_visible_message_2]", 3)
//VOREStation Edit End
diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index 44459d1b96..67fc80168a 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -84,6 +84,16 @@
R.adjustBruteLoss(-weld_rate)
if(wire_rate && R.getFireLoss() && cell.checked_use(wire_power_use * wire_rate * CELLRATE))
R.adjustFireLoss(-wire_rate)
+
+ //VOREStation Add Start
+ else if(ispAI(occupant))
+ var/mob/living/silicon/pai/P = occupant
+
+ if(P.nutrition < 400)
+ P.nutrition = min(P.nutrition+10, 400)
+ cell.use(7000/450*10)
+ //VOREStation Add End
+
else if(ishuman(occupant))
var/mob/living/carbon/human/H = occupant
@@ -258,6 +268,21 @@
occupant = R
update_icon()
return 1
+
+ //VOREStation Add Start
+ else if(istype(L, /mob/living/silicon/pai))
+ var/mob/living/silicon/pai/P = L
+
+ if(P.incapacitated())
+ return
+
+ add_fingerprint(P)
+ P.reset_view(src)
+ P.forceMove(src)
+ occupant = P
+ update_icon()
+ return 1
+ //VOREStation Add End
else if(istype(L, /mob/living/carbon/human))
var/mob/living/carbon/human/H = L
diff --git a/code/game/machinery/virtual_reality/vr_console.dm b/code/game/machinery/virtual_reality/vr_console.dm
index 81df6d934b..b66bc2dff8 100644
--- a/code/game/machinery/virtual_reality/vr_console.dm
+++ b/code/game/machinery/virtual_reality/vr_console.dm
@@ -23,6 +23,7 @@
active_power_usage = 200
light_color = "#FF0000"
+
/obj/machinery/vr_sleeper/Initialize()
. = ..()
default_apply_parts()
@@ -246,14 +247,14 @@
avatar.shapeshifter_change_shape(occupant.species.name)
avatar.forceMove(get_turf(S)) // Put the mob on the landmark, instead of inside it
-
+//CHOMPedit start VR fix
occupant.enter_vr(avatar)
//Yes, I am using a aheal just so your markings transfer over, I could not get .prefs.copy_to working. This is very stupid, and I can't be assed to rewrite this. Too bad!
avatar.revive()
- avatar.revive()
+ avatar.species.equip_survival_gear(avatar)
avatar.verbs += /mob/living/carbon/human/proc/exit_vr //ahealing removes the prommie verbs and the VR verbs, giving it back
- avatar.Sleeping(1)
+//CHOMPedit end
// Prompt for username after they've enterred the body.
var/newname = sanitize(tgui_input_text(avatar, "You are entering virtual reality. Your username is currently [src.name]. Would you like to change it to something else?", "Name change", null, MAX_NAME_LEN), MAX_NAME_LEN)
if (newname)
diff --git a/code/game/objects/effects/bump_teleporter.dm b/code/game/objects/effects/bump_teleporter.dm
index 0286622705..581aeea16f 100644
--- a/code/game/objects/effects/bump_teleporter.dm
+++ b/code/game/objects/effects/bump_teleporter.dm
@@ -23,12 +23,12 @@ var/list/obj/effect/bump_teleporter/BUMP_TELEPORTERS = list()
if(!ismob(user))
//user.loc = src.loc //Stop at teleporter location
return
-
+ var/mob/M = user //VOREStation edit
if(!id_target)
//user.loc = src.loc //Stop at teleporter location, there is nowhere to teleport to.
return
for(var/obj/effect/bump_teleporter/BT in BUMP_TELEPORTERS)
if(BT.id == src.id_target)
- usr.loc = BT.loc //Teleport to location with correct id.
- return
\ No newline at end of file
+ M.forceMove(BT.loc) //Teleport to location with correct id. //VOREStation Edit
+ return
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index da675f6828..7c88ab8ad3 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -42,6 +42,10 @@
latejoin_gatewaystation += loc
delete_me = 1
return
+ if("JoinLateSifPlains")
+ latejoin_plainspath += loc
+ delete_me = 1
+ return
//CHOMPEdit End
if("JoinLateElevator")
latejoin_elevator += loc
diff --git a/code/game/objects/effects/map_effects/portal.dm b/code/game/objects/effects/map_effects/portal.dm
index ede5cbdaca..f07ba99767 100644
--- a/code/game/objects/effects/map_effects/portal.dm
+++ b/code/game/objects/effects/map_effects/portal.dm
@@ -51,7 +51,7 @@ when portals are shortly lived, or when portals are made to be obvious with spec
plane = TURF_PLANE
layer = ABOVE_TURF_LAYER
appearance_flags = NONE
-
+
var/obj/effect/map_effect/portal/counterpart = null // The portal line or master that this is connected to, on the 'other side'.
// Information used to apply `pixel_[x|y]` offsets so that the visuals line up.
@@ -71,8 +71,8 @@ when portals are shortly lived, or when portals are made to be obvious with spec
// Called when something touches the portal, and usually teleports them to the other side.
/obj/effect/map_effect/portal/Crossed(atom/movable/AM)
- if(AM.is_incorporeal())
- return
+ /*if(AM.is_incorporeal())
+ return CHOMPEdit: This is why phased critters couldn't enter z transits */
..()
if(!AM)
return
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 749797c433..89b0bc2e87 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -96,7 +96,7 @@
explode(M)
if(istype(M, /mob/living/))
- if(!M.hovering)
+ if(!M.hovering) //CHOMPedit: let's not make wings ignore mines because we use those here.
explode(M)
/obj/effect/mine/attackby(obj/item/W as obj, mob/living/user as mob)
@@ -398,6 +398,6 @@
// This tells AI mobs to not be dumb and step on mines willingly.
/obj/item/weapon/mine/is_safe_to_step(mob/living/L)
- if(!L.hovering)
+ if(!L.hovering) //CHOMPedit: Let's not trivialize mines.
return FALSE
return ..()
diff --git a/code/game/objects/effects/step_triggers.dm b/code/game/objects/effects/step_triggers.dm
index 56cc000dc9..9b66d1b3c1 100644
--- a/code/game/objects/effects/step_triggers.dm
+++ b/code/game/objects/effects/step_triggers.dm
@@ -13,13 +13,11 @@
return 0
/obj/effect/step_trigger/Crossed(atom/movable/H as mob|obj)
- if(H.is_incorporeal())
- return
+ if((istype(H, /mob/observer) && !affect_ghosts) || (!istype(H, /mob/observer) && H.is_incorporeal() && !affect_ghosts))
+ return //CHOMPEdit: Fixing some step trigger stuff to coincide with incorporeal check changes
..()
if(!H)
return
- if(istype(H, /mob/observer) && !affect_ghosts)
- return
Trigger(H)
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index b2bd8757f3..8c3a5b0551 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -98,10 +98,10 @@
new /obj/effect/decal/cleanable/crayon(target,colour,shadeColour,drawtype)
to_chat(user, "You finish drawing.")
+ var/msg = "[user.client.key] ([user]) has drawn [drawtype] (with [src]) at [target.x],[target.y],[target.z]."
if(config.log_graffiti)
- var/msg = "[user.client.key] ([user]) has drawn [drawtype] (with [src]) at [target.x],[target.y],[target.z]."
message_admins(msg)
- log_game(msg)
+ log_game(msg) //We will log it anyways.
target.add_fingerprint(user) // Adds their fingerprints to the floor the crayon is drawn on.
if(uses)
@@ -211,4 +211,4 @@
..()
/obj/item/weapon/pen/crayon/attack_self(var/mob/user)
- return
\ No newline at end of file
+ return
diff --git a/code/game/objects/items/devices/ticket_printer.dm b/code/game/objects/items/devices/ticket_printer.dm
new file mode 100644
index 0000000000..8817c7ec87
--- /dev/null
+++ b/code/game/objects/items/devices/ticket_printer.dm
@@ -0,0 +1,58 @@
+/obj/item/device/ticket_printer
+ name = "ticket printer"
+ desc = "It prints security citations!"
+ icon = 'icons/obj/device_vr.dmi'
+ icon_state = "sec_ticket_printer"
+ var/print_cooldown = 1 MINUTE
+ var/last_print
+
+/obj/item/device/ticket_printer/attack_self(mob/user)
+ . = ..()
+ if(last_print + print_cooldown <= world.time)
+ print_a_ticket(user)
+ else
+ to_chat(user, "\The [src] is not ready to print another ticket yet.")
+
+/obj/item/device/ticket_printer/proc/print_a_ticket(mob/user)
+
+ var/ticket_name = sanitize(tgui_input_text(user, "The Name of the person you are issuing the ticket to.", "Name", max_length = 100))
+ if(length(ticket_name) > 100)
+ tgui_alert_async(usr, "Entered name too long. 100 character limit.","Error")
+ return
+ if(!ticket_name)
+ return
+ var/details = sanitize(tgui_input_text(user, "What is the ticket for? Avoid entering personally identifiable information in this section. This information should not be used to harrass or otherwise make the person feel uncomfortable. (Max length: 200)", "Ticket Details", max_length = 200))
+ if(length(details) > 200)
+ tgui_alert_async(usr, "Entered details too long. 200 character limit.","Error")
+ return
+ if(!details)
+ return
+
+ var/turf/our_turf = get_turf(user)
+
+ var/final = "
