diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index cc1b474c49..4304af77f3 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -184,7 +184,7 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
#define BODY_ZONE_PRECISE_R_FOOT "r_foot"
//We will round to this value in damage calculations.
-#define DAMAGE_PRECISION 0.1
+#define DAMAGE_PRECISION 0.01
//items total mass, used to calculate their attacks' stamina costs. If not defined, the cost will be (w_class * 1.25)
#define TOTAL_MASS_TINY_ITEM 1.25
@@ -202,4 +202,4 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
#define BULLET_ACT_HIT "HIT" //It's a successful hit, whatever that means in the context of the thing it's hitting.
#define BULLET_ACT_BLOCK "BLOCK" //It's a blocked hit, whatever that means in the context of the thing it's hitting.
#define BULLET_ACT_FORCE_PIERCE "PIERCE" //It pierces through the object regardless of the bullet being piercing by default.
-#define BULLET_ACT_TURF "TURF" //It hit us but it should hit something on the same turf too. Usually used for turfs.
\ No newline at end of file
+#define BULLET_ACT_TURF "TURF" //It hit us but it should hit something on the same turf too. Usually used for turfs.
diff --git a/code/__DEFINES/configuration.dm b/code/__DEFINES/configuration.dm
index 3034876e36..6b70eb1e0f 100644
--- a/code/__DEFINES/configuration.dm
+++ b/code/__DEFINES/configuration.dm
@@ -1,6 +1,7 @@
//config files
#define CONFIG_GET(X) global.config.Get(/datum/config_entry/##X)
#define CONFIG_SET(X, Y) global.config.Set(/datum/config_entry/##X, ##Y)
+#define CONFIG_GET_ENTRY(X) global.config.GetEntryDatum(/datum/config_entry/##X)
#define CONFIG_MAPS_FILE "maps.txt"
diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm
index d5e3f828b8..28a04c2a51 100644
--- a/code/__DEFINES/role_preferences.dm
+++ b/code/__DEFINES/role_preferences.dm
@@ -37,7 +37,7 @@
#define ROLE_GANG "gangster"
#define ROLE_BLOODSUCKER "bloodsucker"
//#define ROLE_MONSTERHUNTER "monster hunter" Disabled for now
-
+#define ROLE_GHOSTCAFE "ghostcafe"
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
//(in game days played) to play that role
diff --git a/code/__HELPERS/areas.dm b/code/__HELPERS/areas.dm
index 4b52187e13..3b1496bae0 100644
--- a/code/__HELPERS/areas.dm
+++ b/code/__HELPERS/areas.dm
@@ -1,5 +1,81 @@
#define BP_MAX_ROOM_SIZE 300
+//Repopulates sortedAreas list
+/proc/repopulate_sorted_areas()
+ GLOB.sortedAreas = list()
+
+ for(var/area/A in world)
+ GLOB.sortedAreas.Add(A)
+
+ sortTim(GLOB.sortedAreas, /proc/cmp_name_asc)
+
+/area/proc/addSorted()
+ GLOB.sortedAreas.Add(src)
+ sortTim(GLOB.sortedAreas, /proc/cmp_name_asc)
+
+//Takes: Area type as a text string from a variable.
+//Returns: Instance for the area in the world.
+/proc/get_area_instance_from_text(areatext)
+ if(istext(areatext))
+ areatext = text2path(areatext)
+ return GLOB.areas_by_type[areatext]
+
+//Takes: Area type as text string or as typepath OR an instance of the area.
+//Returns: A list of all areas of that type in the world.
+/proc/get_areas(areatype, subtypes=TRUE)
+ if(istext(areatype))
+ areatype = text2path(areatype)
+ else if(isarea(areatype))
+ var/area/areatemp = areatype
+ areatype = areatemp.type
+ else if(!ispath(areatype))
+ return null
+
+ var/list/areas = list()
+ if(subtypes)
+ var/list/cache = typecacheof(areatype)
+ for(var/V in GLOB.sortedAreas)
+ var/area/A = V
+ if(cache[A.type])
+ areas += V
+ else
+ for(var/V in GLOB.sortedAreas)
+ var/area/A = V
+ if(A.type == areatype)
+ areas += V
+ return areas
+
+//Takes: Area type as text string or as typepath OR an instance of the area.
+//Returns: A list of all turfs in areas of that type of that type in the world.
+/proc/get_area_turfs(areatype, target_z = 0, subtypes=FALSE)
+ if(istext(areatype))
+ areatype = text2path(areatype)
+ else if(isarea(areatype))
+ var/area/areatemp = areatype
+ areatype = areatemp.type
+ else if(!ispath(areatype))
+ return null
+
+ var/list/turfs = list()
+ if(subtypes)
+ var/list/cache = typecacheof(areatype)
+ for(var/V in GLOB.sortedAreas)
+ var/area/A = V
+ if(!cache[A.type])
+ continue
+ for(var/turf/T in A)
+ if(target_z == 0 || target_z == T.z)
+ turfs += T
+ else
+ for(var/V in GLOB.sortedAreas)
+ var/area/A = V
+ if(A.type != areatype)
+ continue
+ for(var/turf/T in A)
+ if(target_z == 0 || target_z == T.z)
+ turfs += T
+ return turfs
+
// Gets an atmos isolated contained space
// Returns an associative list of turf|dirs pairs
// The dirs are connected turfs in the same space
@@ -103,4 +179,60 @@
to_chat(creator, "You have created a new area, named [newA.name]. It is now weather proof, and constructing an APC will allow it to be powered.")
return TRUE
+
+/**
+ * Returns the base area the target is located in if there is one.
+ * Alternatively, returns the area as is.
+ */
+/proc/get_base_area(atom/target)
+ var/area/A = get_area(target)
+ if(A?.base_area)
+ return A.base_area
+ return A
+
+/**
+ * Returns either null, or a list containing every sub area associated with our base area.
+ * If include_base is TRUE, the base area will also be added to the return list.
+ */
+/proc/get_sub_areas(atom/target, include_base = TRUE)
+ var/area/A = get_area(target)
+ if(!A)
+ return
+ . = list()
+ if(A.base_area)
+ A = A.base_area
+ if(include_base)
+ . += A
+ if(A.sub_areas)
+ . += A.sub_areas
+
+/**
+ * Proc used for purposes similar to get_areas_turfs(), but aimed to include associated areas.
+ * Only accepts area instances and paths for the first arg, no text strings.
+ * Returns a list of all turfs found in the sub areas (including the base's if include_base is TRUE)
+ * and located in a z level matching target_z, or anywhere if target_z is 0
+ */
+
+/proc/get_sub_areas_turfs(area/A, target_z = 0, include_base = TRUE)
+ var/list/contents = get_sub_areas_contents(A, include_base)
+ . = list()
+ for(var/turf/T in contents)
+ if(target_z == 0 || target_z == T.z)
+ . += T
+/**
+ * Simple proc that returns a sum of all contents from every sub area,
+ * Think of the above but for all contents, not just turfs, and without target z.
+ */
+
+/proc/get_sub_areas_contents(area/A, include_base = TRUE)
+ if(ispath(A))
+ A = GLOB.areas_by_type[A]
+ if(!A)
+ return
+ if(A.base_area)
+ A = A.base_area
+ . = list(A.contents)
+ for(var/i in A.sub_areas)
+ . += A.sub_areas[i].contents
+
#undef BP_MAX_ROOM_SIZE
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index ca4b913369..59bf210853 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -8,8 +8,8 @@
#define Z_TURFS(ZLEVEL) block(locate(1,1,ZLEVEL), locate(world.maxx, world.maxy, ZLEVEL))
#define CULT_POLL_WAIT 2400
-/proc/get_area_name(atom/X, format_text = FALSE)
- var/area/A = isarea(X) ? X : get_area(X)
+/proc/get_area_name(atom/X, format_text = FALSE, get_base_area = FALSE)
+ var/area/A = get_base_area ? get_base_area(X) : get_area(X)
if(!A)
return null
return format_text ? format_text(A.name) : A.name
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index e916b2532a..8b86ce691d 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -566,82 +566,6 @@ Turf and target are separate in case you want to teleport some distance from a t
else
return 0
-//Repopulates sortedAreas list
-/proc/repopulate_sorted_areas()
- GLOB.sortedAreas = list()
-
- for(var/area/A in world)
- GLOB.sortedAreas.Add(A)
-
- sortTim(GLOB.sortedAreas, /proc/cmp_name_asc)
-
-/area/proc/addSorted()
- GLOB.sortedAreas.Add(src)
- sortTim(GLOB.sortedAreas, /proc/cmp_name_asc)
-
-//Takes: Area type as a text string from a variable.
-//Returns: Instance for the area in the world.
-/proc/get_area_instance_from_text(areatext)
- if(istext(areatext))
- areatext = text2path(areatext)
- return GLOB.areas_by_type[areatext]
-
-//Takes: Area type as text string or as typepath OR an instance of the area.
-//Returns: A list of all areas of that type in the world.
-/proc/get_areas(areatype, subtypes=TRUE)
- if(istext(areatype))
- areatype = text2path(areatype)
- else if(isarea(areatype))
- var/area/areatemp = areatype
- areatype = areatemp.type
- else if(!ispath(areatype))
- return null
-
- var/list/areas = list()
- if(subtypes)
- var/list/cache = typecacheof(areatype)
- for(var/V in GLOB.sortedAreas)
- var/area/A = V
- if(cache[A.type])
- areas += V
- else
- for(var/V in GLOB.sortedAreas)
- var/area/A = V
- if(A.type == areatype)
- areas += V
- return areas
-
-//Takes: Area type as text string or as typepath OR an instance of the area.
-//Returns: A list of all turfs in areas of that type of that type in the world.
-/proc/get_area_turfs(areatype, target_z = 0, subtypes=FALSE)
- if(istext(areatype))
- areatype = text2path(areatype)
- else if(isarea(areatype))
- var/area/areatemp = areatype
- areatype = areatemp.type
- else if(!ispath(areatype))
- return null
-
- var/list/turfs = list()
- if(subtypes)
- var/list/cache = typecacheof(areatype)
- for(var/V in GLOB.sortedAreas)
- var/area/A = V
- if(!cache[A.type])
- continue
- for(var/turf/T in A)
- if(target_z == 0 || target_z == T.z)
- turfs += T
- else
- for(var/V in GLOB.sortedAreas)
- var/area/A = V
- if(A.type != areatype)
- continue
- for(var/turf/T in A)
- if(target_z == 0 || target_z == T.z)
- turfs += T
- return turfs
-
/proc/get_cardinal_dir(atom/A, atom/B)
var/dx = abs(B.x - A.x)
var/dy = abs(B.y - A.y)
diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm
index 4ce0ccf361..ad1f869057 100644
--- a/code/controllers/configuration/configuration.dm
+++ b/code/controllers/configuration/configuration.dm
@@ -193,6 +193,13 @@
stat("[name]:", statclick)
/datum/controller/configuration/proc/Get(entry_type)
+ var/datum/config_entry/E = GetEntryDatum(entry_type)
+ if((E.protection & CONFIG_ENTRY_HIDDEN) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
+ log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]")
+ return
+ return E.config_entry_value
+
+/datum/controller/configuration/proc/GetEntryDatum(entry_type)
var/datum/config_entry/E = entry_type
var/entry_is_abstract = initial(E.abstract_type) == entry_type
if(entry_is_abstract)
@@ -200,10 +207,7 @@
E = entries_by_type[entry_type]
if(!E)
CRASH("Missing config entry for [entry_type]!")
- if((E.protection & CONFIG_ENTRY_HIDDEN) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
- log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]")
- return
- return E.config_entry_value
+ return E
/datum/controller/configuration/proc/Set(entry_type, new_val)
var/datum/config_entry/E = entry_type
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
index 6efc9eab12..a3bc47ac91 100644
--- a/code/controllers/configuration/entries/game_options.dm
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -249,6 +249,18 @@
/datum/config_entry/number/movedelay/walk_delay
+/datum/config_entry/number/movedelay/sprint_speed_increase
+ config_entry_value = 1
+
+/datum/config_entry/number/movedelay/sprint_buffer_max
+ config_entry_value = 42
+
+/datum/config_entry/number/movedelay/sprint_stamina_cost
+ config_entry_value = 0.7
+
+/datum/config_entry/number/movedelay/sprint_buffer_regen_per_ds
+ config_entry_value = 0.3
+
/////////////////////////////////////////////////Outdated move delay
/datum/config_entry/number/outdated_movedelay
deprecated_by = /datum/config_entry/keyed_list/multiplicative_movespeed
diff --git a/code/datums/components/virtual_reality.dm b/code/datums/components/virtual_reality.dm
index 2f0405af2e..63e4f4f092 100644
--- a/code/datums/components/virtual_reality.dm
+++ b/code/datums/components/virtual_reality.dm
@@ -229,7 +229,7 @@
UnregisterSignal(mastermind, COMSIG_PRE_MIND_TRANSFER)
mastermind = null
if(cleanup)
- var/obj/effect/vr_clean_master/cleanbot = locate() in get_area(M)
+ var/obj/effect/vr_clean_master/cleanbot = locate() in get_base_area(M)
if(cleanbot)
LAZYOR(cleanbot.corpse_party, M)
qdel(src)
diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm
index 230a074bb1..71a5bcb99e 100644
--- a/code/datums/diseases/wizarditis.dm
+++ b/code/datums/diseases/wizarditis.dm
@@ -94,7 +94,7 @@ STI KALY - blind
var/area/thearea = pick(theareas)
var/list/L = list()
- for(var/turf/T in get_area_turfs(thearea.type))
+ for(var/turf/T in thearea)
if(T.z != affected_mob.z)
continue
if(T.name == "space")
diff --git a/code/datums/elements/dusts_on_leaving_area.dm b/code/datums/elements/dusts_on_leaving_area.dm
new file mode 100644
index 0000000000..9527e1fd3a
--- /dev/null
+++ b/code/datums/elements/dusts_on_leaving_area.dm
@@ -0,0 +1,28 @@
+/datum/element/dusts_on_leaving_area
+ element_flags = ELEMENT_DETACH | ELEMENT_BESPOKE
+ id_arg_index = 2
+ var/list/attached_mobs = list()
+ var/list/area_types = list()
+
+/datum/element/dusts_on_leaving_area/Attach(datum/target,types)
+ . = ..()
+ if(!ismob(target))
+ return ELEMENT_INCOMPATIBLE
+ attached_mobs += target
+ area_types = types
+ START_PROCESSING(SSprocessing,src)
+
+/datum/element/dusts_on_leaving_area/Detach(mob/M)
+ . = ..()
+ if(M in attached_mobs)
+ attached_mobs -= M
+ if(!attached_mobs.len)
+ STOP_PROCESSING(SSprocessing,src)
+
+/datum/element/dusts_on_leaving_area/process()
+ for(var/m in attached_mobs)
+ var/mob/M = m
+ var/area/A = get_area(M)
+ if(!(A.type in area_types))
+ M.dust(force = TRUE)
+ Detach(M)
diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm
index a3b666dcc6..01b9facbb8 100644
--- a/code/datums/weather/weather.dm
+++ b/code/datums/weather/weather.dm
@@ -50,7 +50,10 @@
stage = STARTUP_STAGE
var/list/affectareas = list()
for(var/V in get_areas(area_type))
- affectareas += V
+ var/area/A = V
+ affectareas |= A
+ if(A.sub_areas)
+ affectareas |= A.sub_areas
for(var/V in protected_areas)
affectareas -= get_areas(V)
for(var/V in affectareas)
diff --git a/code/datums/wires/airalarm.dm b/code/datums/wires/airalarm.dm
index 6eb4dc04db..0c4715e27e 100644
--- a/code/datums/wires/airalarm.dm
+++ b/code/datums/wires/airalarm.dm
@@ -46,7 +46,7 @@
A.mode = 1 // AALARM_MODE_SCRUB
A.apply_mode()
if(WIRE_ALARM) // Clear alarms.
- var/area/AA = get_area(A)
+ var/area/AA = get_base_area(A)
if(AA.atmosalert(0, holder))
A.post_alert(0)
A.update_icon()
@@ -68,7 +68,7 @@
A.mode = 3 // AALARM_MODE_PANIC
A.apply_mode()
if(WIRE_ALARM) // Post alarm.
- var/area/AA = get_area(A)
+ var/area/AA = get_base_area(A)
if(AA.atmosalert(2, holder))
A.post_alert(2)
A.update_icon()
\ No newline at end of file
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 2d256aad27..99b8165306 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -63,6 +63,15 @@
var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default?
var/list/canSmoothWithAreas //typecache to limit the areas that atoms in this area can smooth with
+/**
+ * These two vars allow for multiple unique areas to be linked to a master area
+ * and share some functionalities such as APC powernet nodes, fire alarms etc, without sacrificing
+ * their own flags, statuses, variables and more snowflakes.
+ * Friendly reminder: no map edited areas.
+ */
+ var/list/area/sub_areas //list of typepaths of the areas you wish to link here, will be replaced with a list of references on mapload.
+ var/area/base_area //The area we wish to use in place of src for certain actions such as APC area linking.
+
var/nightshift_public_area = NIGHTSHIFT_AREA_NONE //considered a public area for nightshift
/*Adding a wizard area teleport list because motherfucking lag -- Urist*/
@@ -123,10 +132,35 @@ GLOBAL_LIST_EMPTY(teleportlocs)
reg_in_areas_in_z()
+ //so far I'm only implementing it on mapped unique areas, it's easier this way.
+ if(unique && sub_areas)
+ if(type in sub_areas)
+ WARNING("\"[src]\" typepath found inside its own sub-areas list, please make sure it doesn't share its parent type initial sub-areas value.")
+ sub_areas = null
+ else
+ var/paths = sub_areas.Copy()
+ sub_areas = null
+ for(var/type in paths)
+ var/area/A = GLOB.areas_by_type[type]
+ if(!A) //By chance an area not loaded in the current world, no warning report.
+ continue
+ if(A == src)
+ WARNING("\"[src]\" area a attempted to link with itself.")
+ continue
+ if(A.base_area)
+ WARNING("[src] attempted to link with [A] while the latter is already linked to another area ([A.base_area]).")
+ continue
+ LAZYADD(sub_areas, A)
+ A.base_area = src
+ else if(LAZYLEN(sub_areas))
+ WARNING("sub-areas are currently not supported for non-unique areas such as [src].")
+ sub_areas = null
+
return INITIALIZE_HINT_LATELOAD
/area/LateInitialize()
- power_change() // all machines set to current power level, also updates icon
+ if(!base_area) //we don't want to run it twice.
+ power_change() // all machines set to current power level, also updates icon
/area/proc/reg_in_areas_in_z()
if(contents.len)
@@ -149,6 +183,19 @@ GLOBAL_LIST_EMPTY(teleportlocs)
/area/Destroy()
if(GLOB.areas_by_type[type] == src)
GLOB.areas_by_type[type] = null
+ if(base_area)
+ LAZYREMOVE(base_area, src)
+ base_area = null
+ if(sub_areas)
+ for(var/i in sub_areas)
+ var/area/A = i
+ A.base_area = null
+ sub_areas -= A
+ if(A.requires_power)
+ A.power_light = FALSE
+ A.power_equip = FALSE
+ A.power_environ = FALSE
+ INVOKE_ASYNC(A, .proc/power_change)
STOP_PROCESSING(SSobj, src)
return ..()
@@ -214,9 +261,12 @@ GLOBAL_LIST_EMPTY(teleportlocs)
var/datum/computer_file/program/alarm_monitor/p = item
p.cancelAlarm("Atmosphere", src, source)
- src.atmosalm = danger_level
- return 1
- return 0
+ atmosalm = danger_level
+ for(var/i in sub_areas)
+ var/area/A = i
+ A.atmosalm = danger_level
+ return TRUE
+ return FALSE
/area/proc/ModifyFiredoors(opening)
if(firedoors)
@@ -241,11 +291,8 @@ GLOBAL_LIST_EMPTY(teleportlocs)
return
if (!fire)
- set_fire_alarm_effect()
+ set_fire_alarm_effects(TRUE)
ModifyFiredoors(FALSE)
- for(var/item in firealarms)
- var/obj/machinery/firealarm/F = item
- F.update_icon()
for (var/item in GLOB.alert_consoles)
var/obj/machinery/computer/station_alert/a = item
@@ -264,11 +311,8 @@ GLOBAL_LIST_EMPTY(teleportlocs)
/area/proc/firereset(obj/source)
if (fire)
- unset_fire_alarm_effects()
+ set_fire_alarm_effects(FALSE)
ModifyFiredoors(TRUE)
- for(var/item in firealarms)
- var/obj/machinery/firealarm/F = item
- F.update_icon()
for (var/item in GLOB.silicon_mobs)
var/mob/living/silicon/aiPlayer = item
@@ -300,9 +344,9 @@ GLOBAL_LIST_EMPTY(teleportlocs)
return
//Trigger alarm effect
- set_fire_alarm_effect()
+ set_fire_alarm_effects(TRUE)
//Lockdown airlocks
- for(var/obj/machinery/door/DOOR in src)
+ for(var/obj/machinery/door/DOOR in get_sub_areas_contents(src))
close_and_lock_door(DOOR)
for (var/i in GLOB.silicon_mobs)
@@ -311,23 +355,20 @@ GLOBAL_LIST_EMPTY(teleportlocs)
//Cancel silicon alert after 1 minute
addtimer(CALLBACK(SILICON, /mob/living/silicon.proc/cancelAlarm,"Burglar",src,trigger), 600)
-/area/proc/set_fire_alarm_effect()
- fire = TRUE
+/area/proc/set_fire_alarm_effects(boolean)
+ fire = boolean
+ for(var/i in sub_areas)
+ var/area/A = i
+ A.fire = boolean
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
for(var/alarm in firealarms)
var/obj/machinery/firealarm/F = alarm
F.update_fire_light(fire)
- for(var/obj/machinery/light/L in src)
+ F.update_icon()
+ for(var/obj/machinery/light/L in get_sub_areas_contents(src))
L.update()
-/area/proc/unset_fire_alarm_effects()
- fire = FALSE
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- for(var/alarm in firealarms)
- var/obj/machinery/firealarm/F = alarm
- F.update_fire_light(fire)
- for(var/obj/machinery/light/L in src)
- L.update()
+/area/proc/updateicon()
/**
* Update the icon state of the area
*
@@ -380,26 +421,35 @@ GLOBAL_LIST_EMPTY(teleportlocs)
/area/proc/power_change()
for(var/obj/machinery/M in src) // for each machine in the area
M.power_change() // reverify power status (to update icons etc.)
+ if(sub_areas)
+ for(var/i in sub_areas)
+ var/area/A = i
+ A.power_light = power_light
+ A.power_equip = power_equip
+ A.power_environ = power_environ
+ INVOKE_ASYNC(A, .proc/power_change)
update_icon()
/area/proc/usage(chan)
- var/used = 0
switch(chan)
if(LIGHT)
- used += used_light
+ . += used_light
if(EQUIP)
- used += used_equip
+ . += used_equip
if(ENVIRON)
- used += used_environ
+ . += used_environ
if(TOTAL)
- used += used_light + used_equip + used_environ
+ . += used_light + used_equip + used_environ
if(STATIC_EQUIP)
- used += static_equip
+ . += static_equip
if(STATIC_LIGHT)
- used += static_light
+ . += static_light
if(STATIC_ENVIRON)
- used += static_environ
- return used
+ . += static_environ
+ if(sub_areas)
+ for(var/i in sub_areas)
+ var/area/A = i
+ . += A.usage(chan)
/area/proc/addStaticPower(value, powerchannel)
switch(powerchannel)
@@ -414,6 +464,10 @@ GLOBAL_LIST_EMPTY(teleportlocs)
used_equip = 0
used_light = 0
used_environ = 0
+ if(sub_areas)
+ for(var/i in sub_areas)
+ var/area/A = i
+ A.clear_usage()
/area/proc/use_power(amount, chan)
diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm
index d010da465e..b296ba7273 100644
--- a/code/game/gamemodes/events.dm
+++ b/code/game/gamemodes/events.dm
@@ -12,7 +12,7 @@
var/list/skipped_areas = list(/area/engine/engineering, /area/engine/supermatter, /area/engine/atmospherics_engine, /area/ai_monitored/turret_protected/ai)
for(var/area/A in world)
- if( !A.requires_power || A.always_unpowered )
+ if( !A.requires_power || A.always_unpowered || A.base_area)
continue
var/skip = 0
@@ -61,8 +61,9 @@
S.output_attempt = 1
S.update_icon()
S.power_change()
+
for(var/area/A in world)
- if(!istype(A, /area/space) && !istype(A, /area/shuttle) && !istype(A, /area/arrival))
+ if(!istype(A, /area/space) && !istype(A, /area/shuttle) && !istype(A, /area/arrival) && !A.always_unpowered && !A.base_area)
A.power_light = TRUE
A.power_equip = TRUE
A.power_environ = TRUE
diff --git a/code/game/gamemodes/gangs/dominator.dm b/code/game/gamemodes/gangs/dominator.dm
index 8c1272dcbd..db060a6539 100644
--- a/code/game/gamemodes/gangs/dominator.dm
+++ b/code/game/gamemodes/gangs/dominator.dm
@@ -101,7 +101,7 @@
playsound(loc, 'sound/items/timer.ogg', 10, 0)
if(!warned && (time_remaining < 180))
warned = TRUE
- var/area/domloc = get_area(loc)
+ var/area/domloc = get_base_area(loc)
gang.message_gangtools("Less than 3 minutes remains in hostile takeover. Defend your dominator at [domloc.map_name]!")
for(var/G in GLOB.gangs)
var/datum/team/gang/tempgang = G
@@ -179,7 +179,7 @@
if((tempgang.domination_time != NOT_DOMINATING) || !tempgang.dom_attempts || !in_range(src, user) || !isturf(loc))
return 0
- var/area/A = get_area(loc)
+ var/area/A = get_base_area(loc)
var/locname = A.map_name
gang = tempgang
diff --git a/code/game/gamemodes/gangs/gang_decals.dm b/code/game/gamemodes/gangs/gang_decals.dm
index 6e5cb58891..7aaed769d9 100644
--- a/code/game/gamemodes/gangs/gang_decals.dm
+++ b/code/game/gamemodes/gangs/gang_decals.dm
@@ -19,7 +19,7 @@
return INITIALIZE_HINT_QDEL
gang = G
var/newcolor = G.color
- var/area/territory = get_area(src)
+ var/area/territory = get_base_area(src)
icon_state = G.name
G.new_territories |= list(territory.type = territory.name)
//If this isn't tagged by a specific gangster there's no bonus income.
@@ -27,7 +27,7 @@
/obj/effect/decal/cleanable/crayon/gang/Destroy()
if(gang)
- var/area/territory = get_area(src)
+ var/area/territory = get_base_area(src)
gang.territories -= territory.type
gang.new_territories -= territory.type
gang.lost_territories |= list(territory.type = territory.name)
diff --git a/code/game/gamemodes/gangs/gang_items.dm b/code/game/gamemodes/gangs/gang_items.dm
index 2e9ca4dcc0..688af3beea 100644
--- a/code/game/gamemodes/gangs/gang_items.dm
+++ b/code/game/gamemodes/gangs/gang_items.dm
@@ -401,7 +401,7 @@ datum/gang_item/equipment/gangsheild
return "This device requires a 5x5 area clear of walls to FUNCTION. (Estimated Takeover Time: [round(gang.determine_domination_time()/60,0.1)] minutes)"
/datum/gang_item/equipment/dominator/purchase(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
- var/area/userarea = get_area(user)
+ var/area/userarea = get_base_area(user)
if(!(userarea.type in gang.territories|gang.new_territories))
to_chat(user,"The dominator can be spawned only on territory controlled by your gang!")
return FALSE
diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm
index fc6cac785a..991577e123 100644
--- a/code/game/machinery/cell_charger.dm
+++ b/code/game/machinery/cell_charger.dm
@@ -46,7 +46,7 @@
var/area/a = loc.loc // Gets our locations location, like a dream within a dream
if(!isarea(a))
return
- if(a.power_equip == 0) // There's no APC in this area, don't try to cheat power!
+ if(!a.powered(EQUIP)) // There's no APC in this area, don't try to cheat power!
to_chat(user, "[src] blinks red as you try to insert the cell!")
return
if(!user.transferItemToLoc(W,src))
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index ad0f372530..9db98b8314 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -288,9 +288,10 @@
return
operating = TRUE
-
do_animate("closing")
layer = closingLayer
+ if(!safe)
+ crush()
sleep(5)
density = TRUE
sleep(5)
@@ -302,8 +303,6 @@
update_freelook_sight()
if(safe)
CheckForMobs()
- else
- crush()
return 1
/obj/machinery/door/proc/CheckForMobs()
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index f5bf8c8a1b..cb133978b2 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -44,7 +44,7 @@
/obj/machinery/door/firedoor/proc/CalculateAffectingAreas()
remove_from_areas()
- affecting_areas = get_adjacent_open_areas(src) | get_area(src)
+ affecting_areas = get_adjacent_open_areas(src) | get_base_area(src)
for(var/I in affecting_areas)
var/area/A = I
LAZYADD(A.firedoors, src)
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index 1ef3fc0a74..0e2363cb6a 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -44,7 +44,7 @@
pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
update_icon()
- myarea = get_area(src)
+ myarea = get_base_area(src)
LAZYADD(myarea.firealarms, src)
/obj/machinery/firealarm/Destroy()
@@ -124,7 +124,7 @@
if(!is_operational() || (last_alarm+FIREALARM_COOLDOWN > world.time))
return
last_alarm = world.time
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
A.firealert(src)
playsound(loc, 'goon/sound/machinery/FireAlarm.ogg', 75)
if(user)
@@ -133,7 +133,7 @@
/obj/machinery/firealarm/proc/reset(mob/user)
if(!is_operational())
return
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
A.firereset(src)
if(user)
log_game("[user] reset a fire alarm at [COORD(src)]")
@@ -142,7 +142,7 @@
if(buildstage != 2)
return ..()
add_fingerprint(user)
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
if(A.fire)
reset(user)
else
@@ -322,7 +322,7 @@
/obj/machinery/firealarm/partyalarm/reset()
if (stat & (NOPOWER|BROKEN))
return
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
if (!A || !A.party)
return
A.party = FALSE
@@ -331,7 +331,7 @@
/obj/machinery/firealarm/partyalarm/alarm()
if (stat & (NOPOWER|BROKEN))
return
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
if (!A || A.party || A.name == "Space")
return
A.party = TRUE
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index 2211397f3e..f777c893f8 100755
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -70,7 +70,7 @@
//Checks to make sure he's not in space doing it, and that the area got proper power.
var/area/a = get_area(src)
- if(!isarea(a) || a.power_equip == 0)
+ if(!a || !a.powered(EQUIP))
to_chat(user, "[src] blinks red as you try to insert [G].")
return 1
diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm
index fdb620cc67..5a907804ce 100644
--- a/code/game/mecha/equipment/tools/other_tools.dm
+++ b/code/game/mecha/equipment/tools/other_tools.dm
@@ -283,7 +283,7 @@
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_charge()
if(equip_ready) //disabled
return
- var/area/A = get_area(chassis)
+ var/area/A = get_base_area(chassis)
var/pow_chan = get_power_channel(A)
if(pow_chan)
return 1000 //making magic
@@ -328,7 +328,7 @@
occupant_message("No powercell detected.")
return
if(cur_charge < chassis.cell.maxcharge)
- var/area/A = get_area(chassis)
+ var/area/A = get_base_area(chassis)
if(A)
var/pow_chan
for(var/c in list(EQUIP,ENVIRON,LIGHT))
diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm
index aabf9acafa..38a1a6089e 100644
--- a/code/game/objects/effects/effect_system/effects_foam.dm
+++ b/code/game/objects/effects/effect_system/effects_foam.dm
@@ -126,7 +126,7 @@
T.PlaceOnTop(/turf/open/floor/plating/foam, flags = CHANGETURF_INHERIT_AIR)
for(var/direction in GLOB.cardinals)
var/turf/cardinal_turf = get_step(T, direction)
- if(get_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf!
+ if(get_base_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf!
new/obj/structure/foamedmetal(T)
break
flick("[icon_state]-disolve", src)
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index 8f09827bd2..3d63f4a553 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -456,7 +456,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
if(!SSmapping.station_room_templates[t])
log_world("Station room spawner placed at ([T.x], [T.y], [T.z]) has invalid ruin name of \"[t]\" in its list")
templates -= t
- template_name = pickweight(templates)
+ template_name = pickweightAllowZero(templates)
if(!template_name)
GLOB.stationroom_landmarks -= src
qdel(src)
@@ -485,4 +485,4 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
// Landmark for the mining station
/obj/effect/landmark/stationroom/lavaland/station
templates = list("Public Mining Base" = 3)
- icon = 'icons/rooms/Lavaland/Mining.dmi'
\ No newline at end of file
+ icon = 'icons/rooms/Lavaland/Mining.dmi'
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index 143354b496..cb77a58769 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -427,7 +427,7 @@
/obj/item/toy/crayon/proc/can_claim_for_gang(mob/user, atom/target)
// Check area validity.
// Reject space, player-created areas, and non-station z-levels.
- var/area/A = get_area(target)
+ var/area/A = get_base_area(target)
if(!A || (!is_station_level(A.z)) || !A.valid_territory)
to_chat(user, "[A] is unsuitable for tagging.")
return FALSE
@@ -461,7 +461,7 @@
qdel(old_marking)
var/datum/antagonist/gang/G = user.mind.has_antag_datum(/datum/antagonist/gang)
- var/area/territory = get_area(target)
+ var/area/territory = get_base_area(target)
new /obj/effect/decal/cleanable/crayon/gang(target,G.gang,"graffiti",0,user) // Heres the gang tag.
to_chat(user, "You tagged [territory] for your gang!")
diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm
index 5b9a764925..fcd1f80a4f 100644
--- a/code/game/objects/structures/ai_core.dm
+++ b/code/game/objects/structures/ai_core.dm
@@ -52,7 +52,7 @@
var/area/A = get_area(src)
if(!A.blob_allowed)
return FALSE
- if(!A.power_equip)
+ if(!A.powered(EQUIP))
return FALSE
if(!SSmapping.level_trait(T.z,ZTRAIT_STATION))
return FALSE
diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm
index 053512a256..b72a4b816e 100644
--- a/code/game/objects/structures/barsigns.dm
+++ b/code/game/objects/structures/barsigns.dm
@@ -305,7 +305,7 @@
/datum/barsign/meow_mix
name = "Meow Mix"
- icon = "meow_mix"
+ icon = "Meow Mix"
desc = "No, we don't serve catnip, officer!"
/datum/barsign/hiddensigns
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index 8c25a2ca5c..70533df0ad 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -80,7 +80,7 @@
/obj/structure/displaycase/proc/trigger_alarm()
//Activate Anti-theft
if(alert)
- var/area/alarmed = get_area(src)
+ var/area/alarmed = get_base_area(src)
alarmed.burglaralert(src)
playsound(src, 'sound/effects/alert.ogg', 50, 1)
diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm
index 92fb13c947..3ba9fea006 100644
--- a/code/game/objects/structures/ghost_role_spawners.dm
+++ b/code/game/objects/structures/ghost_role_spawners.dm
@@ -619,7 +619,7 @@
assignedrole = "Ghost Cafe Visitor"
flavour_text = "Is this what life after death is like?"
skip_reentry_check = TRUE
- banType = "ghostcafe"
+ banType = ROLE_GHOSTCAFE
/datum/action/toggle_dead_chat_mob
icon_icon = 'icons/mob/mob.dmi'
@@ -642,12 +642,14 @@
/obj/effect/mob_spawn/human/ghostcafe/special(mob/living/carbon/human/new_spawn)
if(new_spawn.client)
new_spawn.client.prefs.copy_to(new_spawn)
+ var/area/A = get_area(src)
var/datum/outfit/O = new /datum/outfit/ghostcafe()
O.equip(new_spawn, FALSE, new_spawn.client)
SSjob.equip_loadout(null, new_spawn, FALSE)
SSquirks.AssignQuirks(new_spawn, new_spawn.client, TRUE, TRUE, null, FALSE, new_spawn)
new_spawn.AddElement(/datum/element/ghost_role_eligibility)
new_spawn.AddElement(/datum/element/dusts_on_catatonia)
+ new_spawn.AddElement(/datum/element/dusts_on_leaving_area,list(A.type,/area/hilbertshotel))
ADD_TRAIT(new_spawn, TRAIT_SIXTHSENSE, GHOSTROLE_TRAIT)
ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
ADD_TRAIT(new_spawn,TRAIT_PACIFISM,GHOSTROLE_TRAIT)
diff --git a/code/modules/VR/vr_sleeper.dm b/code/modules/VR/vr_sleeper.dm
index 7cda24d98b..b62c17832a 100644
--- a/code/modules/VR/vr_sleeper.dm
+++ b/code/modules/VR/vr_sleeper.dm
@@ -222,18 +222,23 @@
/obj/effect/vr_clean_master/Initialize()
. = ..()
- vr_area = get_area(src)
- addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES)
+ vr_area = get_base_area(src)
+ if(!vr_area)
+ return INITIALIZE_HINT_QDEL
+ addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES, TIMER_LOOP)
/obj/effect/vr_clean_master/proc/clean_up()
- if (vr_area)
- for (var/obj/item/ammo_casing/casing in vr_area)
- qdel(casing)
- for(var/obj/effect/decal/cleanable/C in vr_area)
- qdel(C)
- for (var/A in corpse_party)
- var/mob/M = A
- if(M && M.stat == DEAD && get_area(M) == vr_area)
- qdel(M)
- corpse_party -= M
- addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES)
+ if (!vr_area)
+ qdel(src)
+ return
+ var/list/contents = get_sub_areas_contents(src)
+ for (var/obj/item/ammo_casing/casing in contents)
+ qdel(casing)
+ for(var/obj/effect/decal/cleanable/C in contents)
+ qdel(C)
+ for (var/A in corpse_party)
+ var/mob/M = A
+ if(!QDELETED(M) && (M in contents) && M.stat == DEAD)
+ qdel(M)
+ corpse_party -= M
+ addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES)
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index c66927b856..c76ecb52f5 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -845,7 +845,11 @@
dat += "
Lavaland | "
else
dat += "Lavaland | "
-
+ // Ghost cafe
+ if(jobban_isbanned(M,ROLE_GHOSTCAFE))
+ dat += "Lavaland | "
+ else
+ dat += "Lavaland | "
dat += ""
//Antagonist (Orange)
@@ -2878,6 +2882,8 @@
return
if(SSdbcore.Connect())
var/datum/DBQuery/query_get_mentor = SSdbcore.NewQuery("SELECT id FROM [format_table_name("mentor")] WHERE ckey = '[ckey]'")
+ if(!query_get_mentor.warn_execute())
+ return
if(query_get_mentor.NextRow())
to_chat(usr, "[ckey] is already a mentor.")
return
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index f08112939a..ad2eeb7289 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -541,7 +541,9 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
var/list/areas_all = list()
var/list/areas_with_APC = list()
var/list/areas_with_multiple_APCs = list()
+ var/list/sub_areas_APC = list()
var/list/areas_with_air_alarm = list()
+ var/list/sub_areas_air_alarm = list()
var/list/areas_with_RC = list()
var/list/areas_with_light = list()
var/list/areas_with_LS = list()
@@ -578,6 +580,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(!A)
dat += "Skipped over [APC] in invalid location, [APC.loc]."
continue
+ LAZYSET(sub_areas_APC, A.type, get_sub_areas(A, FALSE))
if(!(A.type in areas_with_APC))
areas_with_APC.Add(A.type)
else if(A.type in areas_all)
@@ -585,10 +588,11 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
CHECK_TICK
for(var/obj/machinery/airalarm/AA in GLOB.machines)
- var/area/A = get_area(AA)
+ var/area/A = get_base_area(AA)
if(!A) //Make sure the target isn't inside an object, which results in runtimes.
dat += "Skipped over [AA] in invalid location, [AA.loc].
"
continue
+ LAZYSET(sub_areas_air_alarm, A.type, get_sub_areas(A, FALSE))
if(!(A.type in areas_with_air_alarm))
areas_with_air_alarm.Add(A.type)
CHECK_TICK
@@ -638,8 +642,8 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
areas_with_camera.Add(A.type)
CHECK_TICK
- var/list/areas_without_APC = areas_all - areas_with_APC
- var/list/areas_without_air_alarm = areas_all - areas_with_air_alarm
+ var/list/areas_without_APC = areas_all - (areas_with_APC + flatten_list(sub_areas_APC))
+ var/list/areas_without_air_alarm = areas_all - (areas_with_air_alarm + flatten_list(sub_areas_air_alarm))
var/list/areas_without_RC = areas_all - areas_with_RC
var/list/areas_without_light = areas_all - areas_with_light
var/list/areas_without_LS = areas_all - areas_with_LS
@@ -656,12 +660,18 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
dat += "AREAS WITH MULTIPLE APCS:
"
for(var/areatype in areas_with_multiple_APCs)
dat += "[areatype]
"
+ if(sub_areas_APC[areatype])
+ dat += " SUB-AREAS:
"
+ dat += jointext(sub_areas_APC[areatype], "
")
CHECK_TICK
if(areas_without_air_alarm.len)
dat += "AREAS WITHOUT AN AIR ALARM:
"
for(var/areatype in areas_without_air_alarm)
dat += "[areatype]
"
+ if(sub_areas_air_alarm[areatype])
+ dat += " SUB-AREAS:
"
+ dat += jointext(sub_areas_air_alarm[areatype], "
")
CHECK_TICK
if(areas_without_RC.len)
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index e49368016b..95063aadf6 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -207,7 +207,7 @@
pixel_y = (dir & 3)? (dir == 1 ? -24 : 24) : 0
if(name == initial(name))
- name = "[get_area_name(src)] Air Alarm"
+ name = "[get_area_name(src, get_base_area = TRUE)] Air Alarm"
power_change()
set_frequency(frequency)
@@ -250,7 +250,7 @@
"danger_level" = danger_level,
)
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
data["atmos_alarm"] = A.atmosalm
data["fire_alarm"] = A.fire
@@ -386,7 +386,7 @@
send_signal(device_id, list("checks" = text2num(params["val"])^2), usr)
. = TRUE
if("set_external_pressure", "set_internal_pressure")
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
var/target = input("New target pressure:", name, A.air_vent_info[device_id][(action == "set_external_pressure" ? "external" : "internal")]) as num|null
if(!isnull(target) && !..())
send_signal(device_id, list("[action]" = target), usr)
@@ -420,12 +420,12 @@
apply_mode()
. = TRUE
if("alarm")
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
if(A.atmosalert(2, src))
post_alert(2)
. = TRUE
if("reset")
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
if(A.atmosalert(0, src))
post_alert(0)
. = TRUE
@@ -456,7 +456,7 @@
return 0
/obj/machinery/airalarm/proc/refresh_all()
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
for(var/id_tag in A.air_vent_names)
var/list/I = A.air_vent_info[id_tag]
if(I && I["timestamp"] + AALARM_REPORT_TIMEOUT / 2 > world.time)
@@ -507,7 +507,7 @@
return "Flood"
/obj/machinery/airalarm/proc/apply_mode()
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
switch(mode)
if(AALARM_MODE_SCRUBBING)
for(var/device_id in A.air_scrub_names)
@@ -645,7 +645,7 @@
icon_state = "alarm1"
var/overlay_state = AALARM_OVERLAY_OFF
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
switch(max(danger_level, A.atmosalm))
if(0)
add_overlay(AALARM_OVERLAY_GREEN)
@@ -715,7 +715,7 @@
return
var/datum/signal/alert_signal = new(list(
- "zone" = get_area_name(src),
+ "zone" = get_area_name(src, get_base_area = TRUE),
"type" = "Atmospheric"
))
if(alert_level==2)
@@ -728,7 +728,7 @@
frequency.post_signal(src, alert_signal, range = -1)
/obj/machinery/airalarm/proc/apply_danger_level()
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
var/new_area_danger_level = 0
for(var/obj/machinery/airalarm/AA in A)
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm
index 5835912cd3..bc58ef158f 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm
@@ -5,6 +5,7 @@
icon_state = "relief_valve-t-map"
can_unwrench = TRUE
construction_type = /obj/item/pipe/binary
+ interaction_flags_machine = INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE
var/opened = FALSE
var/open_pressure = ONE_ATMOSPHERE * 3
var/close_pressure = ONE_ATMOSPHERE
@@ -50,9 +51,11 @@
if(!is_operational())
return
- var/datum/gas_mixture/air_contents = airs[1]
- var/our_pressure = air_contents.return_pressure()
- if(opened && our_pressure < close_pressure)
+ var/datum/gas_mixture/air_one = airs[1]
+ var/datum/gas_mixture/air_two = airs[2]
+ var/air_one_pressure = air_one.return_pressure()
+ var/our_pressure = abs(air_one_pressure - air_two.return_pressure())
+ if(opened && air_one_pressure < close_pressure)
close()
else if(!opened && our_pressure >= open_pressure)
open()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm b/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm
index 9da9e49e01..4b6a4a4c10 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm
@@ -4,6 +4,7 @@
icon = 'icons/obj/atmospherics/components/relief_valve.dmi'
icon_state = "relief_valve-e-map"
can_unwrench = TRUE
+ interaction_flags_machine = INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE
var/opened = FALSE
var/open_pressure = ONE_ATMOSPHERE * 3
var/close_pressure = ONE_ATMOSPHERE
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
index 3cbf1b4d0e..f2f2329661 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
@@ -38,7 +38,7 @@
id_tag = assign_uid_vents()
/obj/machinery/atmospherics/components/unary/vent_pump/Destroy()
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
if (A)
A.air_vent_names -= id_tag
A.air_vent_info -= id_tag
@@ -155,7 +155,7 @@
"sigtype" = "status"
))
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
if(!A.air_vent_names[id_tag])
name = "\improper [A.name] vent pump #[A.air_vent_names.len + 1]"
A.air_vent_names[id_tag] = name
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
index 22cd9d7fca..10eac9c717 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
@@ -39,7 +39,7 @@
filter_types += gas_id2path(f)
/obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy()
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
if (A)
A.air_scrub_names -= id_tag
A.air_scrub_info -= id_tag
@@ -112,7 +112,7 @@
"sigtype" = "status"
))
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
if(!A.air_scrub_names[id_tag])
name = "\improper [A.name] air scrubber #[A.air_scrub_names.len + 1]"
A.air_scrub_names[id_tag] = name
diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm
index e8704b4c40..e0cf903465 100644
--- a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm
+++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm
@@ -1,6 +1,6 @@
//3-Way Manifold
/obj/machinery/atmospherics/pipe/heat_exchanging/manifold
- icon_state = "manifold"
+ icon_state = "manifold-2"
name = "pipe manifold"
desc = "A manifold composed of regular pipes."
diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm
index bd4e716357..8ceef76a06 100644
--- a/code/modules/awaymissions/capture_the_flag.dm
+++ b/code/modules/awaymissions/capture_the_flag.dm
@@ -7,8 +7,6 @@
#define AMMO_DROP_LIFETIME 300
#define CTF_REQUIRED_PLAYERS 4
-
-
/obj/item/twohanded/ctf
name = "banner"
icon = 'icons/obj/items_and_weapons.dmi'
@@ -210,7 +208,6 @@
toggle_all_ctf(user)
return
-
people_who_want_to_play |= user.ckey
var/num = people_who_want_to_play.len
var/remaining = CTF_REQUIRED_PLAYERS - num
@@ -438,9 +435,9 @@
. = FALSE
if(istype(target, /obj/structure/barricade/security/ctf))
. = TRUE
- if(ishuman(target))
- var/mob/living/carbon/human/H = target
- if(istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/shielded/ctf))
+ if(isliving(target))
+ var/mob/living/H = target
+ if((RED_TEAM in H.faction) || (BLUE_TEAM in H.faction))
. = TRUE
// RED TEAM GUNS
diff --git a/code/modules/clothing/suits/cloaks.dm b/code/modules/clothing/suits/cloaks.dm
index b8287c7f4c..7d56fbe6dd 100644
--- a/code/modules/clothing/suits/cloaks.dm
+++ b/code/modules/clothing/suits/cloaks.dm
@@ -81,7 +81,7 @@
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- resistance_flags = FIRE_PROOF | ACID_PROOF
+ resistance_flags = FIRE_PROOF | ACID_PROOF | GOLIATH_RESISTANCE
/obj/item/clothing/head/hooded/cloakhood/drake
name = "drake helm"
@@ -90,4 +90,4 @@
armor = list("melee" = 70, "bullet" = 30, "laser" = 50, "energy" = 40, "bomb" = 70, "bio" = 60, "rad" = 50, "fire" = 100, "acid" = 100)
heat_protection = HEAD
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- resistance_flags = FIRE_PROOF | ACID_PROOF
+ resistance_flags = FIRE_PROOF | ACID_PROOF | GOLIATH_RESISTANCE
diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm
index 33b9dffaf0..e83f67f796 100644
--- a/code/modules/mob/living/carbon/monkey/life.dm
+++ b/code/modules/mob/living/carbon/monkey/life.dm
@@ -30,6 +30,9 @@
/mob/living/carbon/monkey/handle_mutations_and_radiation()
if(radiation)
+ if(radiation > RAD_MOB_MUTATE && prob((radiation - RAD_MOB_MUTATE) / 25))
+ gorillize()
+ return
if(radiation > RAD_MOB_KNOCKDOWN && prob(RAD_MOB_KNOCKDOWN_PROB))
if(!IsKnockdown())
emote("collapse")
@@ -41,10 +44,6 @@
randmutb()
emote("gasp")
domutcheck()
-
- if(radiation > RAD_MOB_MUTATE * 2 && prob(50))
- gorillize()
- return
if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB))
vomit(10, TRUE)
return ..()
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 15a04235cc..1147042c8c 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -53,11 +53,11 @@
if(NONE)
return FALSE
if(POWER_REQ_ALL)
- return !T || !A || ((!A.power_equip || isspaceturf(T)) && !is_type_in_list(loc, list(/obj/item, /obj/mecha)))
+ return !T || !A || ((!A.powered(EQUIP) || isspaceturf(T)) && !is_type_in_list(loc, list(/obj/item, /obj/mecha)))
if(POWER_REQ_CLOCKCULT)
for(var/obj/effect/clockwork/sigil/transmission/ST in range(src, SIGIL_ACCESS_RANGE))
return FALSE
- return !T || !A || (!istype(T, /turf/open/floor/clockwork) && (!A.power_equip || isspaceturf(T)) && !is_type_in_list(loc, list(/obj/item, /obj/mecha)))
+ return !T || !A || (!istype(T, /turf/open/floor/clockwork) && (!A.powered(EQUIP) || isspaceturf(T)) && !is_type_in_list(loc, list(/obj/item, /obj/mecha)))
/mob/living/silicon/ai/updatehealth()
if(status_flags & GODMODE)
@@ -100,7 +100,7 @@
sleep(50)
var/turf/T = get_turf(src)
var/area/AIarea = get_area(src)
- if(AIarea && AIarea.power_equip)
+ if(AIarea && AIarea.powered(EQUIP))
if(!isspaceturf(T))
ai_restore_power()
return
@@ -120,7 +120,7 @@
var/PRP //like ERP with the code, at least this stuff is no more 4x sametext
for (PRP=1, PRP<=4, PRP++)
T = get_turf(src)
- AIarea = get_area(src)
+ AIarea = get_base_area(src)
if(AIarea)
for (var/obj/machinery/power/apc/APC in AIarea)
if (!(APC.stat & BROKEN))
@@ -134,7 +134,7 @@
to_chat(src, "Lost connection with the APC!")
aiRestorePowerRoutine = POWER_RESTORATION_SEARCH_APC
return
- if(AIarea.power_equip)
+ if(AIarea.powered(EQUIP))
if(!isspaceturf(T))
ai_restore_power()
return
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 71465f23f9..65ee6a69f2 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -479,31 +479,33 @@ Difficulty: Very Hard
NewTerrainTables = /obj/structure/table/abductor
/obj/machinery/anomalous_crystal/theme_warp/ActivationReaction(mob/user, method)
- if(..())
- var/area/A = get_area(src)
- if(!A.outdoors && !(A in affected_targets))
- for(var/atom/Stuff in A)
- if(isturf(Stuff))
- var/turf/T = Stuff
- if((isspaceturf(T) || isfloorturf(T)) && NewTerrainFloors)
- var/turf/open/O = T.ChangeTurf(NewTerrainFloors, flags = CHANGETURF_INHERIT_AIR)
- if(prob(florachance) && NewFlora.len && !is_blocked_turf(O, TRUE))
- var/atom/Picked = pick(NewFlora)
- new Picked(O)
- continue
- if(iswallturf(T) && NewTerrainWalls)
- T.ChangeTurf(NewTerrainWalls)
- continue
- if(istype(Stuff, /obj/structure/chair) && NewTerrainChairs)
- var/obj/structure/chair/Original = Stuff
- var/obj/structure/chair/C = new NewTerrainChairs(Original.loc)
- C.setDir(Original.dir)
- qdel(Stuff)
- continue
- if(istype(Stuff, /obj/structure/table) && NewTerrainTables)
- new NewTerrainTables(Stuff.loc)
- continue
- affected_targets += A
+ . = ..()
+ if(!.)
+ return
+ for(var/i in get_sub_areas(src))
+ var/area/A = i
+ if(A.outdoors || (A in affected_targets))
+ continue
+ affected_targets += A
+ for(var/stuff in A)
+ var/atom/target = stuff
+ if(isturf(target))
+ var/turf/T = target
+ if((isspaceturf(T) || isfloorturf(T)) && NewTerrainFloors)
+ var/turf/open/O = T.ChangeTurf(NewTerrainFloors, flags = CHANGETURF_INHERIT_AIR)
+ if(NewFlora.len && prob(florachance) && !is_blocked_turf(O, TRUE))
+ var/atom/Picked = pick(NewFlora)
+ new Picked(O)
+ else if(iswallturf(T) && NewTerrainWalls)
+ T.ChangeTurf(NewTerrainWalls)
+ else if(NewTerrainChairs && istype(target, /obj/structure/chair))
+ var/obj/structure/chair/Original = target
+ var/obj/structure/chair/C = new NewTerrainChairs(Original.loc)
+ C.setDir(Original.dir)
+ qdel(target)
+ else if(NewTerrainTables && istype(target, /obj/structure/table))
+ new NewTerrainTables(target.loc)
+ qdel(target)
/obj/machinery/anomalous_crystal/emitter //Generates a projectile when interacted with
observer_desc = "This crystal generates a projectile when activated."
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
index 49b56d0950..43ce940d57 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
@@ -170,7 +170,7 @@ Difficulty: Medium
to_chat(user, "The staff is still recharging!")
return
- var/area/user_area = get_area(user)
+ var/area/user_area = get_base_area(user)
var/turf/user_turf = get_turf(user)
if(!user_area || !user_turf || (user_area.type in excluded_areas))
to_chat(user, "Something is preventing you from using the staff here.")
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index b7cbcdb9d8..78294e988d 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -56,6 +56,8 @@
integrity_failure = 50
var/damage_deflection = 10
resistance_flags = FIRE_PROOF
+ armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 100, "bomb" = 30, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 50)
+ req_access = list(ACCESS_ENGINE_EQUIP)
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON
var/lon_range = 1.5
@@ -148,12 +150,40 @@
if(terminal)
terminal.connect_to_network()
-/obj/machinery/power/apc/New(turf/loc, var/ndir, var/building=0)
- if (!req_access)
- req_access = list(ACCESS_ENGINE_EQUIP)
- if (!armor)
- armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 100, "bomb" = 30, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 50)
- ..()
+/obj/machinery/power/apc/Initialize(mapload, ndir, building = FALSE)
+ . = ..()
+ var/area/A = get_base_area(src)
+ if(!building)
+ has_electronics = APC_ELECTRONICS_SECURED
+ // is starting with a power cell installed, create it and set its charge level
+ if(cell_type)
+ cell = new cell_type
+ cell.charge = start_charge * cell.maxcharge / 100 // (convert percentage to actual value)
+
+ //if area isn't specified use current
+ if(areastring)
+ area = get_area_instance_from_text(areastring)
+ if(!area)
+ area = A
+ stack_trace("Bad areastring path for [src], [src.areastring]")
+ else if(isarea(A) && !areastring)
+ area = A
+ if(auto_name)
+ name = "\improper [A.name] APC"
+ update_icon()
+
+ make_terminal()
+ update_nightshift_auth_requirement()
+
+ else
+ area = A
+ opened = APC_COVER_OPENED
+ operating = FALSE
+ name = "\improper [A.name] APC"
+ stat |= MAINT
+ update_icon()
+ addtimer(CALLBACK(src, .proc/update), 5)
+
GLOB.apcs_list += src
wires = new /datum/wires/apc(src)
@@ -164,9 +194,6 @@
src.tdir = dir // to fix Vars bug
setDir(SOUTH)
- if(auto_name)
- name = "\improper [get_area(src)] APC"
-
switch(tdir)
if(NORTH)
pixel_y = 23
@@ -176,14 +203,6 @@
pixel_x = 24
if(WEST)
pixel_x = -25
- if (building)
- area = get_area(src)
- opened = APC_COVER_OPENED
- operating = FALSE
- name = "[area.name] APC"
- stat |= MAINT
- src.update_icon()
- addtimer(CALLBACK(src, .proc/update), 5)
/obj/machinery/power/apc/Destroy()
GLOB.apcs_list -= src
@@ -217,33 +236,6 @@
terminal.setDir(tdir)
terminal.master = src
-/obj/machinery/power/apc/Initialize(mapload)
- . = ..()
- if(!mapload)
- return
- has_electronics = APC_ELECTRONICS_SECURED
- // is starting with a power cell installed, create it and set its charge level
- if(cell_type)
- cell = new cell_type
- cell.charge = start_charge * cell.maxcharge / 100 // (convert percentage to actual value)
-
- var/area/A = src.loc.loc
-
- //if area isn't specified use current
- if(areastring)
- src.area = get_area_instance_from_text(areastring)
- if(!src.area)
- src.area = A
- stack_trace("Bad areastring path for [src], [src.areastring]")
- else if(isarea(A) && src.areastring == null)
- src.area = A
- update_icon()
-
- make_terminal()
- update_nightshift_auth_requirement()
-
- addtimer(CALLBACK(src, .proc/update), 5)
-
/obj/machinery/power/apc/examine(mob/user)
. = ..()
if(stat & BROKEN)
@@ -1432,7 +1424,7 @@
return
for(var/A in GLOB.ai_list)
var/mob/living/silicon/ai/I = A
- if(get_area(I) == area)
+ if(get_base_area(I) == area)
return
failure_timer = max(failure_timer, round(duration))
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 903f63e22c..5343256c8e 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -294,7 +294,7 @@
cut_overlays()
switch(status) // set icon_states
if(LIGHT_OK)
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
if(emergency_mode || (A && A.fire))
icon_state = "[base_state]_emergency"
else
@@ -323,7 +323,7 @@
var/CO = bulb_colour
if(color)
CO = color
- var/area/A = get_area(src)
+ var/area/A = get_base_area(src)
if (A && A.fire)
CO = bulb_emergency_colour
else if (nightshift_enabled)
diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm
index d2d3d60066..fba526edbd 100644
--- a/code/modules/power/power.dm
+++ b/code/modules/power/power.dm
@@ -382,6 +382,7 @@
return null
/area/proc/get_apc()
+ var/target = base_area ? base_area : src
for(var/obj/machinery/power/apc/APC in GLOB.apcs_list)
- if(APC.area == src)
+ if(APC.area == target)
return APC
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index ecd906f2a9..1495ff61ba 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -374,14 +374,18 @@
desc = "Decreases the cooldown of a kinetic accelerator. Not rated for minebot use."
modifier = 2.5
minebot_upgrade = FALSE
+ var/decreased
/obj/item/borg/upgrade/modkit/cooldown/install(obj/item/gun/energy/kinetic_accelerator/KA, mob/user)
. = ..()
if(.)
- KA.overheat_time -= modifier
+ var/old = KA.overheat_time
+ KA.overheat_time = max(0, KA.overheat_time - modifier)
+ decreased = old - KA.overheat_time
+
/obj/item/borg/upgrade/modkit/cooldown/uninstall(obj/item/gun/energy/kinetic_accelerator/KA)
- KA.overheat_time += modifier
+ KA.overheat_time += decreased
..()
/obj/item/borg/upgrade/modkit/cooldown/minebot
diff --git a/code/modules/research/xenobiology/crossbreeding/consuming.dm b/code/modules/research/xenobiology/crossbreeding/consuming.dm
index 0e8bf1e11f..af37a70232 100644
--- a/code/modules/research/xenobiology/crossbreeding/consuming.dm
+++ b/code/modules/research/xenobiology/crossbreeding/consuming.dm
@@ -212,7 +212,7 @@ Consuming extracts:
taste = "sugar and starlight"
/obj/item/slime_cookie/bluespace/do_effect(mob/living/M, mob/user)
- var/list/L = get_area_turfs(get_area(get_turf(M)))
+ var/list/L = get_sub_areas_turfs(get_area(M))
var/turf/target
while (L.len && !target)
var/I = rand(1, L.len)
diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm
index dc721506a5..8648e46cb9 100644
--- a/code/modules/ruins/spaceruin_code/hilbertshotel.dm
+++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm
@@ -12,6 +12,7 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
var/datum/map_template/hilbertshotel/lore/hotelRoomTempLore
var/list/activeRooms = list()
var/list/storedRooms = list()
+ var/list/checked_in_ckeys = list()
var/storageTurf
//Lore Stuff
var/ruinSpawned = FALSE
@@ -44,7 +45,7 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
/obj/item/hilbertshotel/proc/promptAndCheckIn(mob/user)
var/chosenRoomNumber = input(user, "What number room will you be checking into?", "Room Number") as null|num
- if(!chosenRoomNumber)
+ if(!chosenRoomNumber || !user.CanReach(src))
return
if(chosenRoomNumber > SHORT_REAL_LIMIT)
to_chat(user, "You have to check out the first [SHORT_REAL_LIMIT] rooms before you can go to a higher numbered one!")
@@ -52,8 +53,8 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
if((chosenRoomNumber < 1) || (chosenRoomNumber != round(chosenRoomNumber)))
to_chat(user, "That is not a valid room number!")
return
- if(ismob(loc))
- if(user == loc) //Not always the same as user
+ if(!isturf(loc))
+ if((loc == user) || (loc.loc == user) || (loc.loc in user.contents) || (loc in user.GetAllContents(type))) //short circuit, first three checks are cheaper and covers almost all cases (loc.loc covers hotel in box in backpack).
forceMove(get_turf(user))
if(!storageTurf) //Blame subsystems for not allowing this to be in Initialize
if(!GLOB.hhStorageTurf)
@@ -63,13 +64,13 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
GLOB.hhStorageTurf = locate(storageReservation.bottom_left_coords[1]+1, storageReservation.bottom_left_coords[2]+1, storageReservation.bottom_left_coords[3])
else
storageTurf = GLOB.hhStorageTurf
+ checked_in_ckeys |= user.ckey //if anything below runtimes, guess you're outta luck!
if(tryActiveRoom(chosenRoomNumber, user))
return
if(tryStoredRoom(chosenRoomNumber, user))
return
sendToNewRoom(chosenRoomNumber, user)
-
/obj/item/hilbertshotel/proc/tryActiveRoom(var/roomNumber, var/mob/user)
if(activeRooms["[roomNumber]"])
var/datum/turf_reservation/roomReservation = activeRooms["[roomNumber]"]
@@ -102,6 +103,7 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
else
return FALSE
+/// This is a BLOCKING OPERATION. Note the room load call, and the block reservation calls.
/obj/item/hilbertshotel/proc/sendToNewRoom(var/roomNumber, var/mob/user)
var/datum/turf_reservation/roomReservation = SSmapping.RequestBlockReservation(hotelRoomTemp.width, hotelRoomTemp.height)
if(ruinSpawned)
@@ -200,7 +202,6 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
name = "Hilbert's Hotel Storage"
mappath = '_maps/templates/hilbertshotelstorage.dmm'
-
//Turfs and Areas
/turf/closed/indestructible/hotelwall
name = "hotel wall"
@@ -359,6 +360,7 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
. = ..()
if(ismob(AM))
var/mob/M = AM
+ parentSphere?.checked_in_ckeys -= M.ckey
if(M.mind)
var/stillPopulated = FALSE
var/list/currentLivingMobs = GetAllContents(/mob/living) //Got to catch anyone hiding in anything
diff --git a/code/modules/vore/eating/belly_obj.dm b/code/modules/vore/eating/belly_obj.dm
index ad54c8a0c8..f88f6bd6e8 100644
--- a/code/modules/vore/eating/belly_obj.dm
+++ b/code/modules/vore/eating/belly_obj.dm
@@ -1,4 +1,5 @@
-//#define VORE_SOUND_FALLOFF 0.05
+#define VORE_SOUND_FALLOFF 0.1
+#define VORE_SOUND_RANGE 3
//
// Belly system 2.0, now using objects instead of datums because EH at datums.
@@ -164,7 +165,12 @@
. = ..()
// Called whenever an atom enters this belly
-/obj/belly/Entered(var/atom/movable/thing,var/atom/OldLoc)
+/obj/belly/Entered(atom/movable/thing, atom/OldLoc)
+ . = ..()
+ var/mob/living/L //for chat messages and blindness
+ if(isliving(thing))
+ L = thing
+ L.become_blind("belly_[REF(src)]")
if(OldLoc in contents)
return //Someone dropping something (or being stripdigested)
@@ -175,7 +181,7 @@
if(vore_sound && !recent_sound)
if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, owner))
+ for(var/mob/living/H in get_hearers_in_view(VORE_SOUND_RANGE, owner))
if(!H.client || !(H.client.prefs.cit_toggles & EATING_NOISES))
continue
LAZYADD(hearing_mobs, H)
@@ -189,11 +195,14 @@
SEND_SOUND(H,eating)
recent_sound = TRUE
- //Messages if it's a mob
- if(isliving(thing))
- var/mob/living/M = thing
- if(desc)
- to_chat(M, "[desc]")
+ if(L && desc)
+ to_chat(L, "[desc]")
+
+/obj/belly/Exited(atom/movable/AM, atom/newloc)
+ . = ..()
+ if(isliving(AM))
+ var/mob/living/L = AM
+ L.cure_blind("belly_[REF(src)]")
// Release all contents of this belly into the owning mob's location.
// If that location is another mob, contents are transferred into whichever of its bellies the owning mob is in.
@@ -214,7 +223,6 @@
continue
L.absorbed = FALSE
L.stop_sound_channel(CHANNEL_PREYLOOP)
- L.cure_blind("belly_[REF(src)]")
SEND_SIGNAL(OW, COMSIG_CLEAR_MOOD_EVENT, "fedpred", /datum/mood_event/fedpred)
SEND_SIGNAL(L, COMSIG_CLEAR_MOOD_EVENT, "fedprey", /datum/mood_event/fedprey)
SEND_SIGNAL(OW, COMSIG_ADD_MOOD_EVENT, "emptypred", /datum/mood_event/emptypred)
@@ -229,7 +237,7 @@
if(release_sound && !recent_sound)
if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, owner))
+ for(var/mob/living/H in get_hearers_in_view(VORE_SOUND_RANGE, owner))
if(!H.client || !(H.client.prefs.cit_toggles & EATING_NOISES))
continue
LAZYADD(hearing_mobs, H)
@@ -237,7 +245,7 @@
for(var/mob/living/H in hearing_mobs)
if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
var/sound/releasement = GLOB.pred_release_sounds[release_sound]
- SEND_SOUND(H,releasement)
+ H.playsound_local(owner.loc, releasement, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF)
else if(H && H in contents && H.client)
var/sound/releasement = GLOB.prey_release_sounds[release_sound]
SEND_SOUND(H,releasement)
@@ -262,7 +270,6 @@
var/mob/living/OW = owner
if(ML.client)
ML.stop_sound_channel(CHANNEL_PREYLOOP) //Stop the internal loop, it'll restart if the isbelly check on next tick anyway
- ML.cure_blind("belly_[REF(src)]")
SEND_SIGNAL(OW, COMSIG_CLEAR_MOOD_EVENT, "fedpred", /datum/mood_event/fedpred)
SEND_SIGNAL(ML, COMSIG_CLEAR_MOOD_EVENT, "fedprey", /datum/mood_event/fedprey)
SEND_SIGNAL(OW, COMSIG_ADD_MOOD_EVENT, "emptypred", /datum/mood_event/emptypred)
@@ -294,7 +301,7 @@
for(var/mob/living/H in hearing_mobs)
if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
var/sound/releasement = GLOB.pred_release_sounds[release_sound]
- SEND_SOUND(H,releasement)
+ H.playsound_local(owner.loc, releasement, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF)
else if(H && H in contents && H.client)
var/sound/releasement = GLOB.prey_release_sounds[release_sound]
SEND_SOUND(H,releasement)
@@ -325,7 +332,6 @@
for(var/mob/living/M in contents)
M.updateVRPanel()
- M.become_blind("belly_[REF(src)]")
// Setup the autotransfer checks if needed
if(transferlocation != null && autotransferchance > 0)
@@ -345,13 +351,11 @@
if(!(content in src) || !istype(target))
return
content.forceMove(target)
- for(var/mob/living/M in contents)
- M.cure_blind("belly_[REF(src)]")
-// target.nom_mob(content, target.owner)
+
if(vore_sound && !recent_sound && !silent)
if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, owner))
+ for(var/mob/living/H in get_hearers_in_view(VORE_SOUND_RANGE, owner))
if(!H.client || !(H.client.prefs.cit_toggles & EATING_NOISES))
continue
LAZYADD(hearing_mobs, H)
@@ -359,7 +363,7 @@
for(var/mob/living/H in hearing_mobs)
if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
var/sound/eating = GLOB.pred_vore_sounds[vore_sound]
- SEND_SOUND(H,eating)
+ H.playsound_local(owner.loc, eating, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF)
else if(H && H in contents && H.client)
var/sound/eating = GLOB.prey_vore_sounds[vore_sound]
SEND_SOUND(H,eating)
@@ -576,7 +580,7 @@
var/sound/struggle_rustle = sound(get_sfx("rustle"))
LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, owner))
+ for(var/mob/living/H in get_hearers_in_view(VORE_SOUND_RANGE, owner))
if(!H.client || !(H.client.prefs.cit_toggles & EATING_NOISES))
continue
LAZYADD(hearing_mobs, H)
@@ -584,14 +588,14 @@
if(is_wet)
for(var/mob/living/H in hearing_mobs)
if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
- SEND_SOUND(H,pred_struggle_snuggle)
+ H.playsound_local(owner.loc, pred_struggle_snuggle, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF)
else if(H && H in contents && H.client)
SEND_SOUND(H,prey_struggle_snuggle)
else
for(var/mob/living/H in hearing_mobs)
if(H && H.client)
- SEND_SOUND(H, struggle_rustle)
+ H.playsound_local(owner.loc, struggle_rustle, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF)
for(var/mob/living/H in hearing_mobs)
if(H && H.client && (isturf(H.loc)))
diff --git a/code/modules/vore/eating/bellymodes.dm b/code/modules/vore/eating/bellymodes.dm
index 0ecaf49abc..6942a2d5a9 100644
--- a/code/modules/vore/eating/bellymodes.dm
+++ b/code/modules/vore/eating/bellymodes.dm
@@ -18,7 +18,8 @@
return SSBELLIES_PROCESSED
next_process = times_fired + (6 SECONDS/wait) //Set up our next process time.
- var/to_update = FALSE
+ var/play_sound //Potential sound to play at the end to avoid code duplication.
+ var/to_update = FALSE //Did anything update worthy happen?
/////////////////////////// Auto-Emotes ///////////////////////////
if(contents.len && next_emote <= times_fired)
@@ -40,7 +41,7 @@
if(M.client.prefs.cit_toggles & DIGESTION_NOISES)
var/sound/preyloop = sound('sound/vore/prey/loop.ogg')
M.playsound_local(get_turf(src),preyloop, 80,0, channel = CHANNEL_PREYLOOP)
- M.next_preyloop = (world.time + 51 SECONDS)
+ M.next_preyloop = (world.time + 52 SECONDS)
/////////////////////////// Exit Early ////////////////////////////
@@ -71,18 +72,9 @@
for (var/mob/living/M in contents)
if(prob(25))
- if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
- LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, owner))
- if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
- continue
- LAZYADD(hearing_mobs, H)
- last_hearcheck = world.time
- for(var/mob/living/H in hearing_mobs)
- if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
- SEND_SOUND(H,pred_digest)
- else if(H && H in contents && H.client)
- SEND_SOUND(H,prey_digest)
+ if(M && M.client && M.client.prefs.cit_toggles & DIGESTION_NOISES)
+ SEND_SOUND(M,prey_digest)
+ play_sound = pick(pred_digest)
//Pref protection!
if (!M.digestable || M.absorbed)
@@ -108,18 +100,9 @@
M.visible_message("You watch as [owner]'s form loses its additions.")
owner.nutrition += 400 // so eating dead mobs gives you *something*.
- if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
- LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, owner))
- if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
- continue
- LAZYADD(hearing_mobs, H)
- last_hearcheck = world.time
- for(var/mob/living/H in hearing_mobs)
- if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
- SEND_SOUND(H,pred_death)
- else if(H && H in contents && H.client)
- SEND_SOUND(H,prey_death)
+ play_sound = pick(pred_death)
+ if(M && M.client && M.client.prefs.cit_toggles & DIGESTION_NOISES)
+ SEND_SOUND(M,prey_death)
M.stop_sound_channel(CHANNEL_PREYLOOP)
digestion_death(M)
owner.update_icons()
@@ -142,19 +125,9 @@
if(digest_mode == DM_HEAL)
for (var/mob/living/M in contents)
if(prob(25))
- if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
- LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, owner))
- if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
- continue
- LAZYADD(hearing_mobs, H)
- last_hearcheck = world.time
- for(var/mob/living/H in hearing_mobs)
- if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
- SEND_SOUND(H,pred_digest)
- else if(H && H in contents && H.client)
- SEND_SOUND(H,prey_digest)
-
+ if(M && M.client && M.client.prefs.cit_toggles & DIGESTION_NOISES)
+ SEND_SOUND(M,prey_digest)
+ play_sound = pick(pred_digest)
if(M.stat != DEAD)
if(owner.nutrition >= NUTRITION_LEVEL_STARVING && (M.health < M.maxHealth))
M.adjustBruteLoss(-3)
@@ -165,18 +138,10 @@
//for when you just want people to squelch around
if(digest_mode == DM_NOISY)
if(prob(35))
- if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
- LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, owner))
- if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
- continue
- LAZYADD(hearing_mobs, H)
- last_hearcheck = world.time
- for(var/mob/living/H in hearing_mobs)
- if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
- SEND_SOUND(H,pred_digest)
- else if(H && H in contents && H.client)
- SEND_SOUND(H,prey_digest)
+ for(var/mob/M in contents)
+ if(M && M.client && M.client.prefs.cit_toggles & DIGESTION_NOISES)
+ SEND_SOUND(M,prey_digest)
+ play_sound = pick(pred_digest)
//////////////////////////// DM_ABSORB ////////////////////////////
@@ -185,18 +150,9 @@
for (var/mob/living/M in contents)
if(prob(10))//Less often than gurgles. People might leave this on forever.
- if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
- LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, owner))
- if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
- continue
- LAZYADD(hearing_mobs, H)
- last_hearcheck = world.time
- for(var/mob/living/H in hearing_mobs)
- if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
- SEND_SOUND(H,pred_digest)
- else if(H && H in contents && H.client)
- SEND_SOUND(H,prey_digest)
+ if(M && M.client && M.client.prefs.cit_toggles & DIGESTION_NOISES)
+ SEND_SOUND(M,prey_digest)
+ play_sound = pick(pred_digest)
if(M.absorbed)
continue
@@ -262,18 +218,9 @@
to_chat(owner, "[digest_alert_owner]")
to_chat(M, "[digest_alert_prey]")
M.visible_message("You watch as [owner]'s guts loudly rumble as it finishes off a meal.")
- if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
- LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, owner))
- if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
- continue
- LAZYADD(hearing_mobs, H)
- last_hearcheck = world.time
- for(var/mob/living/H in hearing_mobs)
- if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
- SEND_SOUND(H,pred_death)
- else if(H && H in contents && H.client)
- SEND_SOUND(H,prey_death)
+ play_sound = pick(pred_death)
+ if(M && M.client && M.client.prefs.cit_toggles & DIGESTION_NOISES)
+ SEND_SOUND(M,prey_death)
M.spill_organs(FALSE,TRUE,TRUE)
M.stop_sound_channel(CHANNEL_PREYLOOP)
digestion_death(M)
@@ -293,6 +240,19 @@
if(istype(T,/obj/item/reagent_containers/food) || istype(T,/obj/item/organ))
digest_item(T)
+/////////////////////////// Make any noise ///////////////////////////
+ if(play_sound)
+ if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
+ LAZYCLEARLIST(hearing_mobs)
+ for(var/mob/M in hearers(VORE_SOUND_RANGE, owner))
+ if(!M.client || !(M.client.prefs.cit_toggles & DIGESTION_NOISES))
+ continue
+ LAZYADD(hearing_mobs, M)
+ last_hearcheck = world.time
+ for(var/mob/M in hearing_mobs) //so we don't fill the whole room with the sound effect
+ if(M && M.client && (isturf(M.loc) || (M.loc != src.contents))) //to avoid people on the inside getting the outside sounds and their direct sounds + built in sound pref check
+ M.playsound_local(owner.loc, play_sound, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF)
+ //these are all external sound triggers now, so it's ok.
if(to_update)
for(var/mob/living/M in contents)
if(M.client)
diff --git a/html/changelogs/AutoChangeLog-pr-10466.yml b/html/changelogs/AutoChangeLog-pr-10466.yml
new file mode 100644
index 0000000000..ac9d94a677
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10466.yml
@@ -0,0 +1,4 @@
+author: "kevinz000"
+delete-after: True
+changes:
+ - balance: "monkies gorrilize easier now"
diff --git a/html/changelogs/AutoChangeLog-pr-10688.yml b/html/changelogs/AutoChangeLog-pr-10688.yml
new file mode 100644
index 0000000000..e648139889
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10688.yml
@@ -0,0 +1,4 @@
+author: "kevinz000"
+delete-after: True
+changes:
+ - bugfix: "hilbert hotel is now less of an exploity mess"
diff --git a/html/changelogs/AutoChangeLog-pr-10691.yml b/html/changelogs/AutoChangeLog-pr-10691.yml
new file mode 100644
index 0000000000..31eecae15e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10691.yml
@@ -0,0 +1,4 @@
+author: "Seris02"
+delete-after: True
+changes:
+ - bugfix: "probably fixes the make mentor button"
diff --git a/html/changelogs/AutoChangeLog-pr-10698.yml b/html/changelogs/AutoChangeLog-pr-10698.yml
new file mode 100644
index 0000000000..f08e006058
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10698.yml
@@ -0,0 +1,4 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - tweak: "Ghost cafe mobs are super duper attached to the ghost cafe."
diff --git a/html/changelogs/AutoChangeLog-pr-10703.yml b/html/changelogs/AutoChangeLog-pr-10703.yml
new file mode 100644
index 0000000000..106c95f430
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10703.yml
@@ -0,0 +1,4 @@
+author: "Hatterhat"
+delete-after: True
+changes:
+ - tweak: "Ash Drake armor now has goliath resistance, same as the Exo-suit."
diff --git a/html/changelogs/AutoChangeLog-pr-10711.yml b/html/changelogs/AutoChangeLog-pr-10711.yml
new file mode 100644
index 0000000000..cf4d287b66
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10711.yml
@@ -0,0 +1,4 @@
+author: "kevinz000"
+delete-after: True
+changes:
+ - balance: "Doorcrushes are once again instant."
diff --git a/html/changelogs/AutoChangeLog-pr-10717.yml b/html/changelogs/AutoChangeLog-pr-10717.yml
new file mode 100644
index 0000000000..fd9fea8d52
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10717.yml
@@ -0,0 +1,4 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - bugfix: "Meow Mix bar sign works"
diff --git a/html/changelogs/AutoChangeLog-pr-10718.yml b/html/changelogs/AutoChangeLog-pr-10718.yml
new file mode 100644
index 0000000000..c61959b81c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10718.yml
@@ -0,0 +1,4 @@
+author: "r4d6"
+delete-after: True
+changes:
+ - bugfix: "fixed a sprite"
diff --git a/html/changelogs/AutoChangeLog-pr-10722.yml b/html/changelogs/AutoChangeLog-pr-10722.yml
new file mode 100644
index 0000000000..bfecf9a76d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-10722.yml
@@ -0,0 +1,4 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - bugfix: "Fixed a few relief valve behaviors"
diff --git a/icons/turf/areas.dmi b/icons/turf/areas.dmi
index fe60cf6c0d..aad3e78590 100644
Binary files a/icons/turf/areas.dmi and b/icons/turf/areas.dmi differ
diff --git a/modular_citadel/code/modules/mob/living/carbon/human/human_movement.dm b/modular_citadel/code/modules/mob/living/carbon/human/human_movement.dm
index 0b6903c9fe..bd43d96ba4 100644
--- a/modular_citadel/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/modular_citadel/code/modules/mob/living/carbon/human/human_movement.dm
@@ -12,8 +12,11 @@
/mob/living/carbon/human/movement_delay()
. = 0
- if(!resting && m_intent == MOVE_INTENT_RUN && !sprinting)
- . += 1
+ if(!resting && m_intent == MOVE_INTENT_RUN && sprinting)
+ var/static/datum/config_entry/number/movedelay/sprint_speed_increase/SSI
+ if(!SSI)
+ SSI = CONFIG_GET_ENTRY(number/movedelay/sprint_speed_increase)
+ . -= SSI.config_entry_value
if(wrongdirmovedelay)
. += 1
. += ..()
diff --git a/modular_citadel/code/modules/mob/living/living.dm b/modular_citadel/code/modules/mob/living/living.dm
index 513a80cae0..0caf548196 100644
--- a/modular_citadel/code/modules/mob/living/living.dm
+++ b/modular_citadel/code/modules/mob/living/living.dm
@@ -17,6 +17,12 @@
var/sprint_stamina_cost = 0.70 //stamina loss per tile while insufficient sprint buffer.
//---End
+/mob/living/update_config_movespeed()
+ . = ..()
+ sprint_buffer_max = CONFIG_GET(number/movedelay/sprint_buffer_max)
+ sprint_buffer_regen_ds = CONFIG_GET(number/movedelay/sprint_buffer_regen_per_ds)
+ sprint_stamina_cost = CONFIG_GET(number/movedelay/sprint_stamina_cost)
+
/mob/living/movement_delay(ignorewalk = 0)
. = ..()
if(resting)
diff --git a/tgstation.dme b/tgstation.dme
index e7e0c1029d..6124017180 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -475,6 +475,7 @@
#include "code\datums\elements\_element.dm"
#include "code\datums\elements\cleaning.dm"
#include "code\datums\elements\dusts_on_catatonia.dm"
+#include "code\datums\elements\dusts_on_leaving_area.dm"
#include "code\datums\elements\earhealing.dm"
#include "code\datums\elements\ghost_role_eligibility.dm"
#include "code\datums\elements\wuv.dm"