Runtime map now loads in ~11 seconds instead of ~40, sped up various other things (#19957)

Runtime map now has a bunch of new areas / items with often-tested
stuffs, and some hard-to-put-at-runtime stuffs.
Runtime map jobs now are positioned to make it faster to reach the
aforementioned often-tested stuffs.
Runtime map doesn't generate an overmap anymore by default, which speeds
up the process.
Runtime map now loads in ~11 seconds instead of ~40 seconds as it was
before.
Updated the maploader to be faster in parsing maps.
Bapi is not engaged anymore if we're only measuring the map size, which
speeds up the process.
In fastboot we do not generate the codexes anymore, which speeds up the
process.
In fastboot and if exoplanets and away sites are not enabled, we do not
parse the map templates anymore, which speeds up the process.
Updated the icon smoothing to be faster.
Optimized cargo area code.
Other optimizations.
This commit is contained in:
Fluffy
2024-10-06 21:31:01 +00:00
committed by GitHub
parent 9636363e60
commit b8902e2e16
124 changed files with 1238 additions and 134598 deletions
+1 -1
View File
@@ -74,6 +74,7 @@
#include "code\__DEFINES\hud.dm"
#include "code\__DEFINES\hydroponics.dm"
#include "code\__DEFINES\icon_layering.dm"
#include "code\__DEFINES\icon_smoothing.dm"
#include "code\__DEFINES\important_recursive_contents.dm"
#include "code\__DEFINES\inventory.dm"
#include "code\__DEFINES\is_helpers.dm"
@@ -3602,7 +3603,6 @@
#include "code\modules\spell_system\spells\spell_list\self\generic\shift.dm"
#include "code\modules\submaps\_submap.dm"
#include "code\modules\submaps\submap_archetype.dm"
#include "code\modules\submaps\submap_landmark.dm"
#include "code\modules\supermatter\setup_supermatter.dm"
#include "code\modules\supermatter\supermatter.dm"
#include "code\modules\surgery\_defines.dm"
+1 -2
View File
@@ -1,5 +1,4 @@
#define Clamp(x, low, high) max(low, min(high, x))
#define CLAMP01(x) (Clamp(x, 0, 1))
#define CLAMP01(x) (clamp(x, 0, 1))
#define JOINTEXT(X) jointext(X, null)
#define list_find(L, needle, LIMITS...) L.Find(needle, LIMITS)
+34
View File
@@ -0,0 +1,34 @@
/* smoothing_flags */
///Do not smooth
#define SMOOTH_FALSE BITFLAG(0)
///Smooths with exact specified types or just itself
#define SMOOTH_TRUE BITFLAG(1)
///Smooths with all subtypes of specified types or just itself (this value can replace SMOOTH_TRUE)
#define SMOOTH_MORE BITFLAG(2)
///If atom should smooth diagonally, this should be present in 'smooth' var
#define SMOOTH_DIAGONAL BITFLAG(3)
///Atom will smooth with the borders of the map
#define SMOOTH_BORDER BITFLAG(4)
///Atom is currently queued to smooth.
#define SMOOTH_QUEUED BITFLAG(5)
///Don't clear the atom's icon_state on smooth.
#define SMOOTH_NO_CLEAR_ICON BITFLAG(6)
///Add underlays, detached from diagonal smoothing.
#define SMOOTH_UNDERLAYS BITFLAG(7)
#define USES_SMOOTHING (SMOOTH_TRUE|SMOOTH_MORE)
//Redefinitions of the diagonal directions so they can be stored in one var without conflicts
#define N_NORTH 2
#define N_SOUTH 4
#define N_EAST 16
#define N_WEST 256
#define N_NORTHEAST 32
#define N_NORTHWEST 512
#define N_SOUTHEAST 64
#define N_SOUTHWEST 1024
#define QUEUE_SMOOTH(thing_to_queue) if(thing_to_queue.smoothing_flags & USES_SMOOTHING){SSicon_smooth.add_to_queue(thing_to_queue)}
#define QUEUE_SMOOTH_NEIGHBORS(thing_to_queue) for(var/atom/atom_neighbor as anything in orange(1, thing_to_queue)) {QUEUE_SMOOTH(atom_neighbor)}
+5
View File
@@ -19,6 +19,11 @@
// Real modulus that handles decimals
#define MODULUS(x, y) ( (x) - FLOOR(x, y))
// Similar to clamp but the bottom rolls around to the top and vice versa. min is inclusive, max is exclusive
#define WRAP(val, min, max) clamp(( min == max ? min : (val) - (round(((val) - (min))/((max) - (min))) * ((max) - (min))) ),min,max)
#define ATAN2(x, y) ( !(x) && !(y) ? 0 : (y) >= 0 ? arccos((x) / sqrt((x)*(x) + (y)*(y))) : -arccos((x) / sqrt((x)*(x) + (y)*(y))) )
// Will filter out extra rotations and negative rotations
+1 -1
View File
@@ -85,7 +85,7 @@
var/static/notch = 0
// its importaint this code can handle md5filepath sleeping instead of hard blocking, if it's converted to use rust_g.
var/filename = "tmp/md5asfile.[world.realtime].[world.timeofday].[world.time].[world.tick_usage].[notch]"
notch = Wrap(notch+1, 0, 2**15)
notch = WRAP(notch+1, 0, 2**15)
fcopy(file, filename)
. = md5filepath(filename)
fdel(filename)
+60 -147
View File
@@ -21,42 +21,6 @@
not set properly, the underlay will default to regular floor plating.
*/
//Redefinitions of the diagonal directions so they can be stored in one var without conflicts
#define N_NORTH 2
#define N_SOUTH 4
#define N_EAST 16
#define N_WEST 256
#define N_NORTHEAST 32
#define N_NORTHWEST 512
#define N_SOUTHEAST 64
#define N_SOUTHWEST 1024
/* smoothing_flags */
///Do not smooth
#define SMOOTH_FALSE BITFLAG(0)
///Smooths with exact specified types or just itself
#define SMOOTH_TRUE BITFLAG(1)
///Smooths with all subtypes of specified types or just itself (this value can replace SMOOTH_TRUE)
#define SMOOTH_MORE BITFLAG(2)
///If atom should smooth diagonally, this should be present in 'smooth' var
#define SMOOTH_DIAGONAL BITFLAG(3)
///Atom will smooth with the borders of the map
#define SMOOTH_BORDER BITFLAG(4)
///Atom is currently queued to smooth.
#define SMOOTH_QUEUED BITFLAG(5)
///Don't clear the atom's icon_state on smooth.
#define SMOOTH_NO_CLEAR_ICON BITFLAG(6)
///Add underlays, detached from diagonal smoothing.
#define SMOOTH_UNDERLAYS BITFLAG(7)
/* smoothing_hints */
///Don't draw the 'F' state. Useful with SMOOTH_NO_CLEAR_ICON.
@@ -173,24 +137,24 @@
return ..()
///Do not use, use SSicon_smooth.add_to_queue(atom)
/proc/smooth_icon(atom/A)
///Do not use, use QUEUE_SMOOTH(atom)
/atom/proc/smooth_icon()
SHOULD_NOT_SLEEP(TRUE)
if(!A || !A.smoothing_flags)
if(QDELETED(src))
return
A.smoothing_flags &= ~SMOOTH_QUEUED
if (!A.z)
if(!smoothing_flags)
return
if(QDELETED(A))
if (!z)
return
A.atom_flags |= ATOM_FLAG_HTML_USE_INITIAL_ICON
if((A.smoothing_flags & SMOOTH_TRUE) || (A.smoothing_flags & SMOOTH_MORE))
var/adjacencies = A.calculate_adjacencies()
smoothing_flags &= ~SMOOTH_QUEUED
atom_flags |= ATOM_FLAG_HTML_USE_INITIAL_ICON
if((smoothing_flags & (SMOOTH_TRUE|SMOOTH_MORE)))
var/adjacencies = calculate_adjacencies()
if(A.smoothing_flags & SMOOTH_DIAGONAL)
A.diagonal_smooth(adjacencies)
if(smoothing_flags & SMOOTH_DIAGONAL)
diagonal_smooth(adjacencies)
else
A.cardinal_smooth(adjacencies)
cardinal_smooth(adjacencies)
/atom/proc/diagonal_smooth(adjacencies)
SHOULD_NOT_SLEEP(TRUE)
@@ -222,7 +186,7 @@
return adjacencies
/turf/diagonal_smooth(adjacencies)
adjacencies = reverse_ndir(..())
adjacencies = REVERSE_DIR(..())
if (smooth_underlays && adjacencies)
// This should be a mutable_appearance, but we're still on 510.
// Alas.
@@ -284,6 +248,22 @@
underlays = U
#define ndir_to_initial(RET, ndir)\
switch(ndir){\
if(N_NORTH){\
RET = "n";\
}\
if(N_SOUTH){\
RET = "s";\
}\
if(N_EAST){\
RET = "e";\
}\
if(N_WEST){\
RET = "w";\
}\
}
//Blend atoms
/atom/proc/handle_blending(adjacencies, var/list/dir_mods, var/overlay_layer = 3)
SHOULD_NOT_SLEEP(TRUE)
@@ -292,89 +272,83 @@
var/walls_found = 0 //Bitfield of the directions of walls we've found.
for(var/adjacency in list(N_NORTH, N_EAST, N_SOUTH, N_WEST))
if(adjacencies & adjacency)
var/turf/T = get_step(src, reverse_ndir(adjacency))
var/turf/T = get_step(src, REVERSE_DIR(adjacency))
if(is_type_in_list(T, can_blend_with))
if(attach_overlay)
AddOverlays("[reverse_ndir(adjacency)]_[attach_overlay]", overlay_layer)
AddOverlays("[REVERSE_DIR(adjacency)]_[attach_overlay]", overlay_layer)
walls_found |= adjacency
dir_mods["[adjacency]"] = "-[blend_overlay]"
for(var/adjacency in list(N_NORTH, N_SOUTH))
for(var/diagonal in list(N_WEST, N_EAST))
var/prefix = ndir_to_initial(adjacency)
var/suffix = ndir_to_initial(adjacency)
//This shit is done to avoid checking twice, since the value is the same
var/prefix
ndir_to_initial(prefix, adjacency)
var/suffix = prefix
var/has_adjacency = walls_found & adjacency
var/has_diagonal = walls_found & diagonal
if(((adjacencies & adjacency) && (adjacencies && diagonal)) && (has_adjacency || has_diagonal))
dir_mods["[adjacency][diagonal]"] = "-[prefix][walls_found & adjacency ? "wall" : "win"]-[suffix][walls_found & diagonal ? "wall" : "win"]"
dir_mods["[adjacency][diagonal]"] = "-[prefix][has_adjacency ? "wall" : "win"]-[suffix][has_diagonal ? "wall" : "win"]"
if(attach_overlay)
AddOverlays("[prefix][suffix]_[attach_overlay]", overlay_layer)
return dir_mods
/proc/ndir_to_initial(var/ndir)
switch(ndir)
if(N_NORTH)
return "n"
if(N_SOUTH)
return "s"
if(N_EAST)
return "e"
if(N_WEST)
return "w"
#undef ndir_to_initial
/atom/proc/cardinal_smooth(adjacencies, var/list/dir_mods)
/atom/proc/cardinal_smooth(adjacencies)
SHOULD_NOT_SLEEP(TRUE)
//NW CORNER
var/nw = "1-i"
if((adjacencies & N_NORTH) && (adjacencies & N_WEST))
if(adjacencies & N_NORTHWEST)
nw = "1-f" + LAZYACCESS(dir_mods, "[N_NORTH][N_WEST][N_NORTHWEST]")
nw = "1-f"
else
nw = "1-nw" + LAZYACCESS(dir_mods, "[N_NORTH][N_WEST]")
nw = "1-nw"
else
if(adjacencies & N_NORTH)
nw = "1-n" + LAZYACCESS(dir_mods, "[N_NORTH]")
nw = "1-n"
else if(adjacencies & N_WEST)
nw = "1-w" + LAZYACCESS(dir_mods, "[N_WEST]")
nw = "1-w"
//NE CORNER
var/ne = "2-i"
if((adjacencies & N_NORTH) && (adjacencies & N_EAST))
if(adjacencies & N_NORTHEAST)
ne = "2-f" + LAZYACCESS(dir_mods, "[N_NORTH][N_EAST][N_NORTHEAST]")
ne = "2-f"
else
ne = "2-ne" + LAZYACCESS(dir_mods, "[N_NORTH][N_EAST]")
ne = "2-ne"
else
if(adjacencies & N_NORTH)
ne = "2-n" + LAZYACCESS(dir_mods, "[N_NORTH]")
ne = "2-n"
else if(adjacencies & N_EAST)
ne = "2-e" + LAZYACCESS(dir_mods, "[N_EAST]")
ne = "2-e"
//SW CORNER
var/sw = "3-i"
if((adjacencies & N_SOUTH) && (adjacencies & N_WEST))
if(adjacencies & N_SOUTHWEST)
sw = "3-f" + LAZYACCESS(dir_mods, "[N_SOUTH][N_WEST][N_SOUTHWEST]")
sw = "3-f"
else
sw = "3-sw" + LAZYACCESS(dir_mods, "[N_SOUTH][N_WEST]")
sw = "3-sw"
else
if(adjacencies & N_SOUTH)
sw = "3-s" + LAZYACCESS(dir_mods, "[N_SOUTH]")
sw = "3-s"
else if(adjacencies & N_WEST)
sw = "3-w" + LAZYACCESS(dir_mods, "[N_WEST]")
sw = "3-w"
//SE CORNER
var/se = "4-i"
if((adjacencies & N_SOUTH) && (adjacencies & N_EAST))
if(adjacencies & N_SOUTHEAST)
se = "4-f" + LAZYACCESS(dir_mods, "[N_SOUTH][N_EAST][N_SOUTHEAST]")
se = "4-f"
else
se = "4-se" + LAZYACCESS(dir_mods, "[N_SOUTH][N_EAST]")
se = "4-se"
else
if(adjacencies & N_SOUTH)
se = "4-s" + LAZYACCESS(dir_mods, "[N_SOUTH]")
se = "4-s"
else if(adjacencies & N_EAST)
se = "4-e" + LAZYACCESS(dir_mods, "[N_EAST]")
se = "4-e"
var/list/New
var/list/Old
@@ -525,35 +499,14 @@
return A && A.type == source.type ? A : null
//Icon smoothing helpers
/proc/smooth_zlevel(var/zlevel, now = FALSE)
/proc/smooth_zlevel(var/zlevel)
SHOULD_NOT_SLEEP(TRUE)
for(var/V in Z_TURFS(zlevel))
var/turf/T = V
for(var/turf/T as anything in Z_TURFS(zlevel))
QUEUE_SMOOTH(T)
//There's no use in smoothing turfs that have been deleted
if(QDELETED(T))
continue
if(T.smoothing_flags)
if(now)
smooth_icon(T)
else
SSicon_smooth.add_to_queue(T)
for(var/R in T)
var/atom/A = R
//There's no use in smoothing deleted things
if(QDELETED(A))
continue
if(A.smoothing_flags)
if(now)
smooth_icon(A)
else
SSicon_smooth.add_to_queue(A)
for(var/atom/movable/movable_to_smooth as anything in T)
QUEUE_SMOOTH(movable_to_smooth)
/atom/proc/clear_smooth_overlays()
SHOULD_NOT_SLEEP(TRUE)
@@ -578,43 +531,3 @@
bottom_right_corner = se
O += se
AddOverlays(O)
/proc/reverse_ndir(ndir)
SHOULD_NOT_SLEEP(TRUE)
SHOULD_BE_PURE(TRUE)
switch(ndir)
if(N_NORTH)
return NORTH
if(N_SOUTH)
return SOUTH
if(N_WEST)
return WEST
if(N_EAST)
return EAST
if(N_NORTHWEST)
return NORTHWEST
if(N_NORTHEAST)
return NORTHEAST
if(N_SOUTHEAST)
return SOUTHEAST
if(N_SOUTHWEST)
return SOUTHWEST
if(N_NORTH|N_WEST)
return NORTHWEST
if(N_NORTH|N_EAST)
return NORTHEAST
if(N_SOUTH|N_WEST)
return SOUTHWEST
if(N_SOUTH|N_EAST)
return SOUTHEAST
if(N_NORTH|N_WEST|N_NORTHWEST)
return NORTHWEST
if(N_NORTH|N_EAST|N_NORTHEAST)
return NORTHEAST
if(N_SOUTH|N_WEST|N_SOUTHWEST)
return SOUTHWEST
if(N_SOUTH|N_EAST|N_SOUTHEAST)
return SOUTHEAST
else
return 0
+3 -3
View File
@@ -820,9 +820,9 @@ world
if (!value) return color
var/list/RGB = ReadRGB(color)
RGB[1] = Clamp(RGB[1]+value,0,255)
RGB[2] = Clamp(RGB[2]+value,0,255)
RGB[3] = Clamp(RGB[3]+value,0,255)
RGB[1] = clamp(RGB[1]+value,0,255)
RGB[2] = clamp(RGB[2]+value,0,255)
RGB[3] = clamp(RGB[3]+value,0,255)
return rgb(RGB[1],RGB[2],RGB[3])
/proc/sort_atoms_by_layer(var/list/atoms)
-6
View File
@@ -19,12 +19,6 @@
// round() acts like floor(x, 1) by default but can't handle other values
#define FLOOR_FLOAT(x, y) ( round((x) / (y)) * (y) )
// min is inclusive, max is exclusive
/proc/Wrap(val, min, max)
var/d = max - min
var/t = FLOOR((val - min) / d, 1)
return val - (t * d)
/proc/Default(a, b)
return a ? a : b
+2 -2
View File
@@ -9,5 +9,5 @@
. = params2list(params)
return list("icon-x" = Clamp(text2num(.["icon-x"]), 0, lim_x),
"icon-y" = Clamp(text2num(.["icon-y"]), 0, lim_y))
return list("icon-x" = clamp(text2num(.["icon-x"]), 0, lim_x),
"icon-y" = clamp(text2num(.["icon-y"]), 0, lim_y))
+26
View File
@@ -335,6 +335,24 @@
return copytext_char(text, 1, i + 1)
return ""
//Returns a string with reserved characters and spaces after the first and last letters removed
//Like trim(), but very slightly faster. worth it for niche usecases
/proc/trim_reduced(text)
var/starting_coord = 1
var/text_len = length(text)
for (var/i in 1 to text_len)
if (text2ascii(text, i) > 32)
starting_coord = i
break
for (var/i = text_len, i >= starting_coord, i--)
if (text2ascii(text, i) > 32)
return copytext(text, starting_coord, i + 1)
if(starting_coord > 1)
return copytext(text, starting_coord)
return ""
//Returns a string with reserved characters and spaces before the first word and after the last word removed.
/proc/trim(text)
return trim_left(trim_right(text))
@@ -776,6 +794,14 @@
if(rest)
. += .(rest)
/proc/deep_string_equals(A, B)
if (length(A) != length(B))
return FALSE
for (var/i = 1 to length(A))
if (text2ascii(A, i) != text2ascii(B, i))
return FALSE
return TRUE
/proc/replacemany(text, list/replacements)
if (!LAZYLEN(replacements))
return text
+2 -2
View File
@@ -158,7 +158,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
var/angle_per_element = round(zone / page_choices.len)
for(var/i in 1 to elements.len)
var/atom/movable/screen/radial/E = elements[i]
var/angle = Wrap(starting_angle + (i - 1) * angle_per_element,0,360)
var/angle = WRAP(starting_angle + (i - 1) * angle_per_element,0,360)
if(i > page_choices.len)
HideElement(E)
else
@@ -248,7 +248,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
/datum/radial_menu/proc/next_page()
if(pages > 1)
current_page = Wrap(current_page + 1,1,pages+1)
current_page = WRAP(current_page + 1,1,pages+1)
update_screen_objects()
/datum/radial_menu/proc/show_to(mob/M)
+2 -2
View File
@@ -91,9 +91,9 @@ avoid code duplication. This includes items that may sometimes act as a standard
/obj/item/proc/get_clamped_volume()
if(w_class)
if(force)
return Clamp((force + w_class) * 4, 30, 100)// Add the item's force to its weight class and multiply by 4, then clamp the value between 30 and 100
return clamp((force + w_class) * 4, 30, 100)// Add the item's force to its weight class and multiply by 4, then clamp the value between 30 and 100
else
return Clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
return clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
/**
* Called from [/mob/living/proc/attackby] (usually)
+3 -3
View File
@@ -56,7 +56,7 @@ SUBSYSTEM_DEF(icon_smooth)
continue
if((smoothing_atom.flags_1 & INITIALIZED_1) && !(smoothing_atom.icon_update_queued))
smooth_icon(smoothing_atom)
smoothing_atom.smooth_icon()
else
deferred += smoothing_atom
@@ -78,7 +78,7 @@ SUBSYSTEM_DEF(icon_smooth)
/datum/controller/subsystem/icon_smooth/Initialize()
for (var/zlevel = 1 to world.maxz)
smooth_zlevel(zlevel, FALSE)
smooth_zlevel(zlevel)
if (GLOB.config.fastboot)
LOG_DEBUG("icon_smoothing: Skipping prebake, fastboot enabled.")
@@ -94,7 +94,7 @@ SUBSYSTEM_DEF(icon_smooth)
if(QDELETED(smoothing_atom) || !(smoothing_atom.smoothing_flags & SMOOTH_QUEUED) || !smoothing_atom.z)
continue
smooth_icon(smoothing_atom)
smoothing_atom.smooth_icon()
CHECK_TICK
@@ -263,6 +263,7 @@ SUBSYSTEM_DEF(atlas)
. = "sccv_horizon"
/datum/controller/subsystem/atlas/proc/load_map_meta()
SHOULD_NOT_SLEEP(TRUE)
// This needs to be done after current_map is set, but before mapload.
admin_departments = list(
@@ -278,10 +279,8 @@ SUBSYSTEM_DEF(atlas)
for (var/thing in mapload_callbacks)
var/datum/callback/cb = thing
cb.InvokeAsync()
CHECK_TICK
mapload_callbacks.Cut()
mapload_callbacks = null
/datum/controller/subsystem/atlas/proc/OnMapload(datum/callback/callback)
if (!istype(callback))
@@ -290,11 +289,15 @@ SUBSYSTEM_DEF(atlas)
mapload_callbacks += callback
/datum/controller/subsystem/atlas/proc/setup_spawnpoints()
SHOULD_NOT_SLEEP(TRUE)
for (var/type in current_map.spawn_types)
var/datum/spawnpoint/S = new type
spawn_locations[S.display_name] = S
/datum/controller/subsystem/atlas/proc/InitializeSectors()
SHOULD_NOT_SLEEP(TRUE)
for (var/type in subtypesof(/datum/space_sector))
var/datum/space_sector/space_sector = new type()
@@ -12,9 +12,15 @@ SUBSYSTEM_DEF(codex)
var/list/chemistry_codex_ignored_result_path = list(/singleton/reagent/drink, /singleton/reagent/alcohol)
/datum/controller/subsystem/codex/Initialize()
generate_cooking_codex()
generate_chemistry_codex()
log_subsystem_codex("SScodex: [cooking_codex_data.len] cooking recipes; [chemistry_codex_data.len] chemistry recipes.")
//We don't build the codex in fastboot, it's slow and kind of pointless for tests
if(GLOB.config.fastboot)
log_subsystem_codex("SScodex: Fastboot detected, skipping codex generation.")
else
generate_cooking_codex()
generate_chemistry_codex()
log_subsystem_codex("SScodex: [length(cooking_codex_data)] cooking recipes; [length(chemistry_codex_data)] chemistry recipes.")
return SS_INIT_SUCCESS
/datum/controller/subsystem/codex/proc/generate_cooking_codex()
@@ -24,6 +24,41 @@ SUBSYSTEM_DEF(holomap)
/// List of all `/obj/effect/landmark/minimap_poi`.
var/list/obj/effect/landmark/minimap_poi/pois = list()
/*#############################################
Typecaches used for map icon generation
#############################################*/
var/static/list/mineral_wall_tcache = typecacheof(list(
/turf/simulated/mineral,
/turf/unsimulated/mineral,
))
var/static/list/mineral_floor_tcache = typecacheof(list(
/turf/unsimulated/floor/asteroid,
/turf/simulated/mineral,
/turf/simulated/floor/exoplanet,
))
var/static/list/hull_tcache = typecacheof(list(
/turf/simulated/wall,
/turf/simulated/floor,
/turf/unsimulated/wall,
/turf/unsimulated/floor,
))
var/static/list/rock_tcache = typecacheof(list(
/turf/simulated/mineral,
/turf/unsimulated/floor/asteroid,
/turf/simulated/open
))
var/static/list/obstacle_tcache = typecacheof(list(
/turf/simulated/wall,
/turf/unsimulated/mineral,
/turf/unsimulated/wall
))
var/static/list/path_tcache = typecacheof(list(
/turf/simulated/floor,
/turf/unsimulated/floor
)) - typecacheof(/turf/unsimulated/floor/asteroid)
/datum/controller/subsystem/holomap/Initialize()
generate_all_minimaps()
LOG_DEBUG("SSholomap: [minimaps.len] maps.")
@@ -40,6 +75,7 @@ SUBSYSTEM_DEF(holomap)
generate_minimap(z)
generate_minimap_area_colored(z)
generate_minimap_scan(z)
CHECK_TICK
/datum/controller/subsystem/holomap/proc/generate_minimap(zlevel = 1)
// Sanity checks - Better to generate a helpful error message now than have DrawBox() runtime
@@ -49,40 +85,19 @@ SUBSYSTEM_DEF(holomap)
if(world.maxy > canvas.Height())
CRASH("Minimap for z=[zlevel] : world.maxy ([world.maxy]) must be <= [canvas.Height()]")
var/list/rock_tcache = typecacheof(list(
/turf/simulated/mineral,
/turf/unsimulated/floor/asteroid,
/turf/simulated/open
))
var/list/obstacle_tcache = typecacheof(list(
/turf/simulated/wall,
/turf/unsimulated/mineral,
/turf/unsimulated/wall
))
var/list/path_tcache = typecacheof(list(
/turf/simulated/floor,
/turf/unsimulated/floor
)) - typecacheof(/turf/unsimulated/floor/asteroid)
var/turf/T
var/area/A
var/Ttype
for (var/thing in Z_TURFS(zlevel))
T = thing
A = T.loc
Ttype = T.type
for(var/turf/T as anything in Z_TURFS(zlevel))
var/area/A = T.loc
var/Ttype = T.type
if (A.area_flags & AREA_FLAG_HIDE_FROM_HOLOMAP)
continue
if (rock_tcache[Ttype])
continue
if (obstacle_tcache[Ttype] || (T.contents.len && locate(/obj/structure/grille, T)))
if (obstacle_tcache[Ttype] || (length(T.contents) && locate(/obj/structure/grille, T)))
canvas.DrawBox(HOLOMAP_OBSTACLE + "DD", T.x, T.y)
else if(path_tcache[Ttype] || (T.contents.len && locate(/obj/structure/lattice/catwalk, T)))
else if(path_tcache[Ttype] || (length(T.contents) && locate(/obj/structure/lattice/catwalk, T)))
canvas.DrawBox(HOLOMAP_PATH + "DD", T.x, T.y)
CHECK_TICK
minimaps[zlevel] = canvas
minimaps_base64[zlevel] = icon2base64(canvas)
@@ -94,11 +109,9 @@ SUBSYSTEM_DEF(holomap)
if(world.maxy > canvas.Height())
crash_with("Minimap for z=[zlevel] : world.maxy ([world.maxy]) must be <= [canvas.Height()]")
var/turf/T
var/area/A
for (var/thing in Z_TURFS(zlevel))
T = thing
A = T.loc
for (var/turf/T as anything in Z_TURFS(zlevel))
var/area/A = T.loc
if (A.area_flags & AREA_FLAG_HIDE_FROM_HOLOMAP)
continue
if (A.holomap_color)
@@ -121,27 +134,8 @@ SUBSYSTEM_DEF(holomap)
if(world.maxy > canvas.Height())
CRASH("Minimap for z=[zlevel] : world.maxy ([world.maxy]) must be <= [canvas.Height()]")
var/list/mineral_wall_tcache = typecacheof(list(
/turf/simulated/mineral,
/turf/unsimulated/mineral,
))
var/list/mineral_floor_tcache = typecacheof(list(
/turf/unsimulated/floor/asteroid,
/turf/simulated/mineral,
/turf/simulated/floor/exoplanet,
))
var/list/hull_tcache = typecacheof(list(
/turf/simulated/wall,
/turf/simulated/floor,
/turf/unsimulated/wall,
/turf/unsimulated/floor,
))
var/turf/T
var/Ttype
for (var/thing in Z_TURFS(zlevel))
T = thing
Ttype = T.type
for(var/turf/T as anything in Z_TURFS(zlevel))
var/Ttype = T.type
if (mineral_wall_tcache[Ttype])
canvas.DrawBox(HOLOMAP_MINERAL_WALL, T.x, T.y)
@@ -150,6 +144,4 @@ SUBSYSTEM_DEF(holomap)
else if(hull_tcache[Ttype])
canvas.DrawBox(HOLOMAP_OBSTACLE, T.x, T.y)
CHECK_TICK
minimaps_scan_base64[zlevel] = icon2base64(canvas)
+8 -7
View File
@@ -8,7 +8,6 @@ SUBSYSTEM_DEF(mapping)
var/list/exoplanet_ruins_templates = list()
var/list/away_sites_templates = list()
var/list/submaps = list()
var/list/submap_archetypes = list()
var/list/used_turfs = list() //list of turf = datum/turf_reservation -- Currently unused
@@ -30,13 +29,15 @@ SUBSYSTEM_DEF(mapping)
var/adding_new_zlevel = FALSE
/datum/controller/subsystem/mapping/Initialize(timeofday)
// Load templates and build away sites.
preloadTemplates()
for(var/atype in subtypesof(/singleton/submap_archetype))
submap_archetypes[atype] = new atype
//If we're in fastboot and not spawning exoplanets or awaysites
//this is different from TG and Bay, which always preload, but it saves a lot of time for us
//so we'll do it this way and hope for the best
if(!GLOB.config.fastboot || GLOB.config.exoplanets["enable_loading"] || GLOB.config.awaysites["enable_loading"])
// Load templates and build away sites.
preloadTemplates()
SSatlas.current_map.build_away_sites()
SSatlas.current_map.build_exoplanets()
SSatlas.current_map.build_away_sites()
SSatlas.current_map.build_exoplanets()
return SS_INIT_SUCCESS
+1 -1
View File
@@ -82,7 +82,7 @@
return min(armor_values[key], 100)
/datum/component/armor/proc/set_value(key, newval)
armor_values[key] = Clamp(newval, 0, 100)
armor_values[key] = clamp(newval, 0, 100)
// There is a disconnect between legacy damage and armor code. This here helps bridge the gap.
/proc/get_armor_key(damage_type, damage_flags)
+2 -2
View File
@@ -159,7 +159,7 @@
return replacetext(text, "ORIGIN", origin)
/datum/trader/proc/print_trading_items(var/num)
num = Clamp(num,1,trading_items.len)
num = clamp(num,1,trading_items.len)
if(trading_items[num])
var/atom/movable/M = trading_items[num]
return "[initial(M.name)]"
@@ -192,7 +192,7 @@
/datum/trader/proc/offer_items_for_trade(var/list/offers, var/num, var/turf/location, var/mob/user)
if(!offers || !offers.len)
return TRADER_NOT_ENOUGH
num = Clamp(num, 1, trading_items.len)
num = clamp(num, 1, trading_items.len)
var/offer_worth = 0
for(var/item in offers)
var/atom/movable/offer = item
+2
View File
@@ -43,6 +43,8 @@
var/simulated = 1 // Filter for actions. Used by lighting overlays.
var/fluorescent // Shows up under a UV light.
var/explosion_resistance
/// Chemistry.
var/datum/reagents/reagents = null
var/list/reagents_to_add
+1 -1
View File
@@ -30,7 +30,7 @@
/datum/game_mode/meteor/proc/set_meteor_severity(value)
meteor_severity = Clamp(value, 0, maximal_severity)
meteor_severity = clamp(value, 0, maximal_severity)
/datum/game_mode/meteor/proc/set_meteor_wave_delay(value)
meteor_wave_delay = max(10 SECONDS, value)
@@ -262,7 +262,7 @@
if (vampire.blood_usable < 10)
vampire.frenzy += 2
else if (vampire.frenzy > 0)
vampire.frenzy = max(0, vampire.frenzy -= Clamp(vampire.blood_usable * 0.1, 1, 10))
vampire.frenzy = max(0, vampire.frenzy -= clamp(vampire.blood_usable * 0.1, 1, 10))
vampire.frenzy = round(min(vampire.frenzy, 450))
+2 -2
View File
@@ -829,10 +829,10 @@ pixel_x = 10;
var/min_temperature = max(selected[2] - T0C, MIN_TEMPERATURE)
var/input_temperature = tgui_input_number(usr, "What temperature would you like the system to mantain?", "Thermostat Controls", target_temperature - T0C, max_temperature, min_temperature)
if(isnum(input_temperature))
var/temp = Clamp(input_temperature, min_temperature, max_temperature)
var/temp = clamp(input_temperature, min_temperature, max_temperature)
if(input_temperature > max_temperature || input_temperature < min_temperature)
to_chat(usr, "Temperature must be between [min_temperature]C and [max_temperature]C. Target temperature clamped to [temp]C.")
target_temperature = Clamp(input_temperature + T0C, selected[2], selected[3])
target_temperature = clamp(input_temperature + T0C, selected[2], selected[3])
else
to_chat(usr, "Error, input not recognised. Temperature unchanged.")
+1 -1
View File
@@ -146,7 +146,7 @@
. = TRUE
update_icon()
if(action=="setVolume")
volume_rate = Clamp(text2num(params["targetVolume"]), minrate, maxrate)
volume_rate = clamp(text2num(params["targetVolume"]), minrate, maxrate)
. = TRUE
update_icon()
+1 -1
View File
@@ -230,7 +230,7 @@
if(!isnum(input_time))
return
time = Clamp(input_time SECONDS, 1, 600)
time = clamp(input_time SECONDS, 1, 600)
if("start_timer")
src.timing = 1
+2 -2
View File
@@ -260,7 +260,7 @@ var/bomb_set
if (href_list["time"])
var/time = text2num(href_list["time"])
timeleft += time
timeleft = Clamp(timeleft, 120, 600)
timeleft = clamp(timeleft, 120, 600)
if (href_list["timer"])
if (timing == -1)
SSnanoui.update_uis(src)
@@ -323,7 +323,7 @@ var/bomb_set
bomb_set--
timing = 0
timeleft = Clamp(timeleft, 120, 600)
timeleft = clamp(timeleft, 120, 600)
update_icon()
/obj/machinery/nuclearbomb/ex_act(severity)
@@ -180,10 +180,14 @@
amount = 0
var/list/drips
/obj/effect/decal/cleanable/blood/drip/Initialize()
. = ..()
/obj/effect/decal/cleanable/blood/drip/New()
..()
drips = list(icon_state)
/obj/effect/decal/cleanable/blood/drip/Destroy()
drips = null
. = ..()
/obj/effect/decal/cleanable/blood/writing
icon_state = "tracks"
desc = "It looks like a writing in blood."
-18
View File
@@ -31,21 +31,3 @@
d.epicenter = T
d.rec_pow = power
SSexplosives.queue(d)
/atom
var/explosion_resistance
/turf/space
explosion_resistance = 3
/turf/simulated/open
explosion_resistance = 3
/turf/simulated/floor
explosion_resistance = 1
/turf/simulated/mineral
explosion_resistance = 2
/turf/simulated/wall
explosion_resistance = 10
+2 -2
View File
@@ -443,9 +443,9 @@
/obj/item/proc/get_volume_by_throwforce_and_or_w_class()
if(throwforce && w_class)
return Clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
return clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
else if(w_class)
return Clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
return clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
else
return 0
+1 -1
View File
@@ -136,7 +136,7 @@
if(parts)
new parts(loc)
if (smoothing_flags)
SSicon_smooth.add_to_queue_neighbors(src)
QUEUE_SMOOTH_NEIGHBORS(src)
return ..()
/obj/structure/closet/airbubble/toggle(mob/user as mob)
+3 -3
View File
@@ -10,11 +10,11 @@
/obj/effect/decal/cleanable/draftingchalk/Initialize(mapload)
. = ..()
if (mapload)
SSicon_smooth.add_to_queue(src)
QUEUE_SMOOTH(src)
else
smooth_icon(src)
smooth_icon()
for (var/obj/effect/decal/cleanable/draftingchalk/C in orange(1, src))
smooth_icon(C)
C.smooth_icon()
/obj/item/pen/drafting
name = "white drafting chalk"
@@ -38,7 +38,7 @@
/obj/item/plastique/attack_self(mob/user as mob)
var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num
if(user.get_active_hand() == src)
newtime = Clamp(newtime, 10, 60000)
newtime = clamp(newtime, 10, 60000)
timer = newtime
to_chat(user, SPAN_NOTICE("Timer set for [timer] seconds."))
@@ -147,7 +147,7 @@
/obj/item/plastique/dirty/attack_self(mob/user as mob)
var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num
if(user.get_active_hand() == src)
newtime = Clamp(newtime, 300, 60000)
newtime = clamp(newtime, 300, 60000)
timer = newtime
to_chat(user, SPAN_NOTICE("Timer set for [timer] seconds."))
@@ -224,7 +224,7 @@
if(!pressure)
return
throw_amount += pressure
throw_amount = Clamp(50, throw_amount, 5000)
throw_amount = clamp(50, throw_amount, 5000)
if(ismob(user))
to_chat(user, SPAN_NOTICE("Pressure has been adjusted to [throw_amount] kPa."))
@@ -452,7 +452,7 @@
/obj/item/material/twohanded/chainsaw/proc/RemoveFuel(var/amount = 1)
if(reagents && istype(reagents))
amount *= fuel_cost
reagents.remove_reagent(fuel_type, Clamp(amount,0,REAGENT_VOLUME(reagents, fuel_type)))
reagents.remove_reagent(fuel_type, clamp(amount,0,REAGENT_VOLUME(reagents, fuel_type)))
if(REAGENT_VOLUME(reagents, fuel_type) <= 0)
PowerDown()
else
+1 -1
View File
@@ -31,7 +31,7 @@
if(do_mob(user, M, 3 SECONDS))
user.visible_message(SPAN_NOTICE("\The [user] dries \the [M] off with \the [src]."))
playsound(M, 'sound/weapons/towelwipe.ogg', 25, 1)
M.adjust_fire_stacks(-Clamp(M.fire_stacks,-1.5,1.5))
M.adjust_fire_stacks(-clamp(M.fire_stacks,-1.5,1.5))
return
. = ..()
+3 -3
View File
@@ -25,15 +25,15 @@
if(climbable)
verbs += /obj/structure/proc/climb_on
if (smoothing_flags)
SSicon_smooth.add_to_queue(src)
SSicon_smooth.add_to_queue_neighbors(src)
QUEUE_SMOOTH(src)
QUEUE_SMOOTH_NEIGHBORS(src)
/obj/structure/Destroy()
if(parts)
new parts(loc)
if (smoothing_flags)
SSicon_smooth.remove_from_queues(src)
SSicon_smooth.add_to_queue_neighbors(src)
QUEUE_SMOOTH_NEIGHBORS(src)
climbers = null
@@ -261,7 +261,7 @@
/obj/structure/barricade/proc/update_health(damage, nomessage)
health -= damage
health = Clamp(health, 0, maxhealth)
health = clamp(health, 0, maxhealth)
if(!health)
if(!nomessage)
@@ -138,8 +138,8 @@
F2.flag_item = flag_item
//Requeue the area for smoothing, just in case
SSicon_smooth.add_to_queue(src)
SSicon_smooth.add_to_queue_neighbors(src)
QUEUE_SMOOTH(src)
QUEUE_SMOOTH_NEIGHBORS(src)
/obj/structure/sign/flag/New(loc, var/newdir, var/linked_flag_path, var/deploy, var/icon_file, var/item_flag_path)
. = ..()
+2 -2
View File
@@ -105,8 +105,8 @@
if(attacking_item.use_tool(src, user, 5, volume = 50))
anchored = !anchored
to_chat(user, SPAN_NOTICE("You [anchored ? "" : "un"]anchor [src]."))
SSicon_smooth.add_to_queue(src)
SSicon_smooth.add_to_queue_neighbors(src)
QUEUE_SMOOTH(src)
QUEUE_SMOOTH_NEIGHBORS(src)
else
..()
+4 -4
View File
@@ -57,7 +57,7 @@
. += SPAN_NOTICE("There is a thick layer of silicate covering it.")
/obj/structure/window/proc/update_nearby_icons()
SSicon_smooth.add_to_queue_neighbors(src)
QUEUE_SMOOTH_NEIGHBORS(src)
/obj/structure/window/update_icon()
if(!full)
@@ -65,7 +65,7 @@
layer = ABOVE_HUMAN_LAYER
else
layer = SIDE_WINDOW_LAYER
SSicon_smooth.add_to_queue(src)
QUEUE_SMOOTH(src)
/obj/structure/window/proc/take_damage(var/damage = 0, var/sound_effect = 1, message = TRUE)
var/initialhealth = health
@@ -802,10 +802,10 @@
return ..(adjacencies, dir_mods)
/obj/structure/window_frame/proc/update_nearby_icons()
SSicon_smooth.add_to_queue_neighbors(src)
QUEUE_SMOOTH_NEIGHBORS(src)
/obj/structure/window_frame/update_icon()
SSicon_smooth.add_to_queue(src)
QUEUE_SMOOTH(src)
// Indestructible Reinforced Window
/obj/structure/window/full/reinforced/indestructible/attack_hand()
+2
View File
@@ -5,6 +5,8 @@
icon_state = "plating"
is_outside = OUTSIDE_AREA
explosion_resistance = 1
// Damage to flooring.
var/broken
var/burnt
+1 -1
View File
@@ -105,7 +105,7 @@
AddOverlays(overlays_to_add, ATOM_ICON_CACHE_PROTECTED)
UNSETEMPTY(reinforcement_images)
SSicon_smooth.add_to_queue(src)
QUEUE_SMOOTH(src)
if(smoothing_flags & SMOOTH_UNDERLAYS)
get_underlays(cached_adjacency)
+2
View File
@@ -24,6 +24,8 @@
/obj/machinery/door/airlock
)
explosion_resistance = 10
var/damage = 0
var/damage_overlay = 0
var/global/damage_overlays[16]
+2
View File
@@ -17,6 +17,8 @@
permit_ao = FALSE
z_eventually_space = TRUE
turf_flags = TURF_FLAG_BACKGROUND
explosion_resistance = 3
var/use_space_appearance = TRUE
var/use_starlight = TRUE
+1 -1
View File
@@ -104,7 +104,7 @@
luminosity = 1
if (smoothing_flags)
SSicon_smooth.add_to_queue(src)
QUEUE_SMOOTH(src)
if (light_range && light_power)
update_light()
+2 -2
View File
@@ -19,9 +19,9 @@
above.update_mimic()
if(queue_neighbors)
SSicon_smooth.add_to_queue_neighbors(src)
QUEUE_SMOOTH_NEIGHBORS(src)
else if(smoothing_flags && !(smoothing_flags & SMOOTH_QUEUED)) // we check here because proc overhead
SSicon_smooth.add_to_queue(src)
QUEUE_SMOOTH(src)
if (SSatlas.current_map.use_overmap)
var/obj/effect/overmap/visitable/sector/exoplanet/E = GLOB.map_sectors["[z]"]
+2
View File
@@ -277,6 +277,8 @@ var/list/world_api_rate_limit = list()
GLOB.config.load("config/age_restrictions.txt", "age_restrictions")
/world/proc/update_status()
SHOULD_NOT_SLEEP(TRUE)
var/list/s = list()
if (GLOB.config && GLOB.config.server_name)
+1 -1
View File
@@ -103,7 +103,7 @@
if("change_supplied_law_position")
var/new_position = input(usr, "Enter new supplied law position between 1 and [MAX_SUPPLIED_LAW_NUMBER], inclusive. Inherent laws at the same index as a supplied law will not be stated.", "Law Position", supplied_law_position) as num|null
if(isnum(new_position) && state.can_use_topic(src, usr))
supplied_law_position = Clamp(new_position, 1, MAX_SUPPLIED_LAW_NUMBER)
supplied_law_position = clamp(new_position, 1, MAX_SUPPLIED_LAW_NUMBER)
return TRUE
if("edit_law")
+4
View File
@@ -422,3 +422,7 @@ var/global/movement_disabled_exception //This is the client that calls the proc,
firelock_increment += 1
if(firelock_increment > 1)
to_chat(usr, "Double firedoor [F] at ([F.x],[F.y],[F.z]) in [T.loc].")
#ifdef TESTING
GLOBAL_LIST_EMPTY(dirty_vars)
#endif
@@ -135,6 +135,7 @@
/// When SSAtlas chooses us as the current sector, this function is called, which will set us up to start processing
/datum/space_sector/proc/setup_current_sector()
SHOULD_CALL_PARENT(TRUE)
SHOULD_NOT_SLEEP(TRUE)
if(SSatlas.current_map.ports_of_call && length(SSatlas.current_sector.scheduled_port_visits))
var/current_day_index = GLOB.all_days.Find(time2text(world.realtime, "Day"))
+22 -24
View File
@@ -91,11 +91,10 @@ var/list/global/random_stock_large = list()
admin_notice(SPAN_DANGER("Cargo Stock generation completed in [round(0.1*(world.timeofday-start_time),0.1)] seconds."), R_DEBUG)
/datum/cargospawner
var/list/containers = list()
var/list/tables = list()
var/list/turf/simulated/floor/warehouseturfs = list()
var/list/obj/structure/closet/crate/containers = list()
var/list/obj/structure/table/tables = list()
var/list/full_containers = list()//Used to hold references to crates we filled up
var/area/warehouse
var/list/warehouseturfs = list()
var/list/infest_mobs_moderate = list(
/mob/living/simple_animal/bee/standalone = 1,
@@ -112,19 +111,18 @@ var/list/global/random_stock_large = list()
/datum/cargospawner/New()
//First lets get the reference to our warehouse
for(var/areapath in typesof(SSatlas.current_map.warehouse_basearea))
warehouse = locate(areapath)
if (warehouse)
for (var/turf/simulated/floor/T in warehouse)
warehouseturfs += T
for (var/obj/structure/closet/crate/C in warehouse)
containers |= C
for (var/obj/structure/table/B in warehouse)
if(B.no_cargo)
continue
tables |= B
for(var/atom/A in locate(areapath))
if(istype(A, /turf/simulated/floor))
warehouseturfs += A
else if(istype(A, /obj/structure/closet/crate))
containers |= A
else if(istype(A, /obj/structure/table))
var/obj/structure/table/B = A
if(!B.no_cargo)
tables |= B
/datum/cargospawner/proc/start()
if (!SSatlas.current_map.warehouse_basearea || !warehouse || !warehouseturfs.len)
if (!SSatlas.current_map.warehouse_basearea || !length(warehouseturfs))
admin_notice(SPAN_DANGER("ERROR: Cargo spawner failed to locate warehouse. Terminating."), R_DEBUG)
qdel(src)
return
@@ -157,7 +155,7 @@ var/list/global/random_stock_large = list()
var/minweight = 1000000000 //We will distribute items somewhat evenly among crates
//by selecting the least-filled one for each spawn
for (var/obj/structure/closet/crate/C in containers)
for (var/obj/structure/closet/crate/C as anything in containers)
if (C.stored_weight() < minweight && C.stored_weight() < C.storage_capacity)
minweight = C.stored_weight()
emptiest = C
@@ -202,18 +200,18 @@ var/list/global/random_stock_large = list()
#define INFEST_PROB_SEVERE 3//Severe is once per round, not per crate
/datum/cargospawner/proc/handle_infestation()
for (var/obj/O in containers)
for (var/obj/structure/closet/crate/C as anything in containers)
if(prob(INFEST_PROB_MODERATE))
var/ctype = pickweight(infest_mobs_moderate)
new ctype(O)
msg_admin_attack("Common cargo warehouse critter [ctype] spawned inside [O.name] coords (<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[O.x];Y=[O.y];Z=[O.z]'>JMP</a>)")
new ctype(C)
msg_admin_attack("Common cargo warehouse critter [ctype] spawned inside [C.name] coords (<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[C.x];Y=[C.y];Z=[C.z]'>JMP</a>)")
//This is checked only once per round. ~3% chance to spawn a scary monster infesting the warehouse
if (prob(INFEST_PROB_SEVERE))
//Find a tile to spawn the thing
var/list/turfs = list()
var/turf/T
for (var/turf/t in warehouseturfs)
for (var/turf/t as anything in warehouseturfs)
T = t//Failsafe incase none are clear
if (turf_clear(T))
turfs |= t
@@ -228,11 +226,11 @@ var/list/global/random_stock_large = list()
return
/datum/cargospawner/proc/shuffle_items()
for (var/obj/O in containers)
O.contents = shuffle(O.contents)
for (var/obj/structure/closet/crate/C as anything in containers)
C.contents = shuffle(C.contents)
for (var/obj/a in tables)
var/turf/T = get_turf(a)
for (var/obj/structure/table/table as anything in tables)
var/turf/T = get_turf(table)
T.contents = shuffle(T.contents)
GLOBAL_LIST_EMPTY_TYPED(large_stock_markers, /obj/effect/large_stock_marker)
+1 -1
View File
@@ -619,7 +619,7 @@ var/list/localhost_addresses = list(
var/static/next_external_rsc = 0
var/list/external_rsc_urls = GLOB.config.external_rsc_urls
if(length(external_rsc_urls))
next_external_rsc = Wrap(next_external_rsc+1, 1, external_rsc_urls.len+1)
next_external_rsc = WRAP(next_external_rsc+1, 1, external_rsc_urls.len+1)
preload_rsc = external_rsc_urls[next_external_rsc]
#endif
@@ -173,7 +173,7 @@
version_message += "\nThis server does not currently support client side fps. You can set now for when it does."
var/new_fps = input(user, "Choose your desired fps.[version_message]\n(0 = synced with server tick rate (currently:[world.fps]))", "Global Preference") as num|null
if (isnum(new_fps) && CanUseTopic(user))
pref.clientfps = Clamp(new_fps, 0, 1000)
pref.clientfps = clamp(new_fps, 0, 1000)
var/mob/target_mob = preference_mob()
if(target_mob && target_mob.client)
@@ -91,7 +91,7 @@ Alpha adjustment
/datum/gear_tweak/alpha/get_metadata(var/user, var/metadata, var/title = "Character Preference")
var/selected_alpha = tgui_input_number(user, "Choose a color.", title, 255)
selected_alpha = Clamp(selected_alpha, 0, 255)
selected_alpha = clamp(selected_alpha, 0, 255)
return selected_alpha
/datum/gear_tweak/alpha/tweak_item(var/obj/item/item, var/metadata, var/mob/living/carbon/human/H)
@@ -153,7 +153,7 @@
var/temp_scale = 0
if(temperature > min_temp)
if(temperature >= optimal_temp)
temp_scale = Clamp(1 - ((optimal_temp - temperature) / optimal_temp), 0, 1)
temp_scale = clamp(1 - ((optimal_temp - temperature) / optimal_temp), 0, 1)
else
temp_scale = temperature / optimal_temp
//If we're between min and optimal this will yield a value in the range 0.7 to 1
@@ -52,7 +52,7 @@
if (reagents && reagents.total_volume)
var/ratio = reagents.total_volume / size
scale = sqrt(ratio) //Scaling factor is square root of desired area
scale = Clamp(scale, min_scale, max_scale)
scale = clamp(scale, min_scale, max_scale)
else
scale = min_scale
w_class = round(initial(w_class) * scale)
@@ -83,7 +83,7 @@
for(var/obj/item/reagent_containers/cooking_container/CC in contents)
var/image/pan_overlay
if(CC.appliancetype == FRYER)
pan_overlay = image('icons/obj/machinery/cooking_machines.dmi', "basket[Clamp(length(pans)+1, 1, 2)]")
pan_overlay = image('icons/obj/machinery/cooking_machines.dmi', "basket[clamp(length(pans)+1, 1, 2)]")
pan_overlay.color = CC.color
pans += pan_overlay
if(isemptylist(pans))
@@ -42,7 +42,7 @@
var/pan_number = 0
for(var/obj/item/reagent_containers/cooking_container/CC in contents)
var/pan_icon_state
var/pan_position_number = Clamp((pan_number)+1, 1, 4)
var/pan_position_number = clamp((pan_number)+1, 1, 4)
var/list/positions = pan_positions[pan_position_number]
switch(CC.appliancetype)
if(SKILLET)
@@ -48,7 +48,7 @@
update_icon()
/obj/item/csi_marker/update_icon()
icon_state = "card[Clamp(number,1,7)]"
icon_state = "card[clamp(number,1,7)]"
/obj/item/csi_marker/n1
number = 1
+1 -1
View File
@@ -84,7 +84,7 @@
if(use_check_and_message(user,USE_FORCE_SRC_IN_USER))
return 0
amount = round(Clamp(amount, 0, src.worth))
amount = round(clamp(amount, 0, src.worth))
if(amount==0) return 0
src.worth -= amount
@@ -154,7 +154,7 @@
if(!age)
age = rand(35, 50)
M.age = Clamp(age, 21, 65)
M.age = clamp(age, 21, 65)
if(has_idris_account)
SSeconomy.create_and_assign_account(M, null, rand(idris_account_min, idris_account_max), is_idris_account_public)
@@ -75,7 +75,7 @@
/obj/item/mech_component/proc/update_health()
total_damage = brute_damage + burn_damage
if(total_damage > max_damage) total_damage = max_damage
damage_state = Clamp(round((total_damage/max_damage) * 4), MECH_COMPONENT_DAMAGE_UNDAMAGED, MECH_COMPONENT_DAMAGE_DAMAGED_TOTAL)
damage_state = clamp(round((total_damage/max_damage) * 4), MECH_COMPONENT_DAMAGE_UNDAMAGED, MECH_COMPONENT_DAMAGE_DAMAGED_TOTAL)
/obj/item/mech_component/proc/ready_to_install()
return 1
@@ -306,7 +306,7 @@
/obj/item/mecha_equipment/shield/proc/stop_damage(var/damage)
var/difference = damage - charge
charge = Clamp(charge - damage, 0, max_charge)
charge = clamp(charge - damage, 0, max_charge)
last_recharge = world.time
@@ -358,7 +358,7 @@
if((world.time - last_recharge) < cooldown)
return
var/actual_required_power = Clamp(max_charge - charge, 0, charging_rate)
var/actual_required_power = clamp(max_charge - charge, 0, charging_rate)
owner.use_cell_power(actual_required_power)
/obj/item/mecha_equipment/shield/get_hardpoint_status_value()
@@ -186,7 +186,7 @@
if(bee_count < 1)
return
severity = Clamp(severity, 0, 1)
severity = clamp(severity, 0, 1)
var/bees_to_release = bee_count * severity
bees_to_release = round(bees_to_release, 1)
bee_count -= bees_to_release
@@ -288,7 +288,7 @@
/obj/item/integrated_circuit/input/advanced_locator/on_data_written()
var/rad = get_pin_data(IC_INPUT, 2)
if(isnum(rad))
rad = Clamp(rad, 0, 7)
rad = clamp(rad, 0, 7)
radius = rad
/obj/item/integrated_circuit/input/advanced_locator/do_work()
@@ -847,8 +847,8 @@
activate_pin(3)
return
var/turf/T = get_turf(assembly)
var/target_x = Clamp(get_pin_data(IC_INPUT, 1), 0, world.maxx)
var/target_y = Clamp(get_pin_data(IC_INPUT, 2), 0, world.maxy)
var/target_x = clamp(get_pin_data(IC_INPUT, 1), 0, world.maxx)
var/target_y = clamp(get_pin_data(IC_INPUT, 2), 0, world.maxy)
var/turf/A = locate(target_x, target_y, T.z)
set_pin_data(IC_OUTPUT, 1, null)
if(!A || !(A in view(T)))
@@ -927,7 +927,7 @@
var/rad = get_pin_data(IC_INPUT, 2)
if(isnum(rad))
rad = Clamp(rad, 0, 8)
rad = clamp(rad, 0, 8)
radius = rad
/obj/item/integrated_circuit/input/advanced_locator_list/do_work()
@@ -306,7 +306,7 @@
return
A.forceMove(get_turf(src))
A.throw_at(T, round(Clamp(sqrt(target_x.data*target_x.data+target_y.data*target_y.data),0,8),1), 3, assembly)
A.throw_at(T, round(clamp(sqrt(target_x.data*target_x.data+target_y.data*target_y.data),0,8),1), 3, assembly)
/obj/item/integrated_circuit/manipulation/shocker
name = "shocker circuit"
@@ -325,7 +325,7 @@
/obj/item/integrated_circuit/manipulation/shocker/on_data_written()
var/s = get_pin_data(IC_INPUT, 2)
power_draw_per_use = Clamp(s,0,20)*8
power_draw_per_use = clamp(s,0,20)*8
/obj/item/integrated_circuit/manipulation/shocker/do_work()
..()
@@ -341,6 +341,6 @@
else
to_chat(M, SPAN_DANGER("You feel a sharp shock from the [src]!"))
spark(get_turf(M), 3, 1)
M.stun_effect_act(0, Clamp(get_pin_data(IC_INPUT, 2),0,20), null)
M.stun_effect_act(0, clamp(get_pin_data(IC_INPUT, 2),0,20), null)
shocktime = world.time
return
@@ -95,7 +95,7 @@
var/brightness = get_pin_data(IC_INPUT, 2)
if(new_color && isnum(brightness))
brightness = Clamp(brightness, 0, 6)
brightness = clamp(brightness, 0, 6)
light_rgb = new_color
light_brightness = brightness
@@ -45,7 +45,7 @@
else
direc = 1
if(isnum(new_amount))
new_amount = Clamp(new_amount, 0, volume)
new_amount = clamp(new_amount, 0, volume)
transfer_amount = new_amount
/obj/item/integrated_circuit/reagent/injector/do_work()
@@ -94,7 +94,7 @@
if(!TS.Adjacent(TT))
activate_pin(3)
return
var/tramount = Clamp(min(transfer_amount, REAGENTS_FREE_SPACE(reagents)), 0, reagents.maximum_volume)
var/tramount = clamp(min(transfer_amount, REAGENTS_FREE_SPACE(reagents)), 0, reagents.maximum_volume)
if(ismob(target))//Blood!
if(istype(target, /mob/living/carbon))
var/mob/living/carbon/T = target
@@ -158,7 +158,7 @@
else
direc = 1
if(isnum(new_amount))
new_amount = Clamp(new_amount, 0, 50)
new_amount = clamp(new_amount, 0, 50)
transfer_amount = new_amount
/obj/item/integrated_circuit/reagent/pump/do_work()
@@ -283,7 +283,7 @@
else
direc = 1
if(isnum(new_amount))
new_amount = Clamp(new_amount, 0, 50)
new_amount = clamp(new_amount, 0, 50)
transfer_amount = new_amount
/obj/item/integrated_circuit/reagent/filter/do_work()
@@ -57,8 +57,8 @@
activate_pin(3)
return
var/turf/T = get_turf(assembly)
var/target_x = Clamp(get_pin_data(IC_INPUT, 1), 0, world.maxx)
var/target_y = Clamp(get_pin_data(IC_INPUT, 2), 0, world.maxy)
var/target_x = clamp(get_pin_data(IC_INPUT, 1), 0, world.maxx)
var/target_y = clamp(get_pin_data(IC_INPUT, 2), 0, world.maxy)
var/turf/A = locate(target_x, target_y, T.z)
set_pin_data(IC_OUTPUT, 1, null)
if(!A||A==T)
-4
View File
@@ -1,7 +1,3 @@
/obj/effect/landmark/map_load_mark
name = "map loader landmark"
var/list/templates //list of template types to pick from
//Clears walls
/obj/effect/landmark/clear
name = "clear turf"
+11 -33
View File
@@ -20,7 +20,6 @@
var/loaded = 0 // Times loaded this round
var/static/dmm_suite/maploader = new
var/list/shuttles_to_initialise = list()
var/list/subtemplates_to_spawn
var/base_turf_for_zs = null
var/accessibility_weight = 0
var/template_flags = TEMPLATE_FLAG_ALLOW_DUPLICATES
@@ -42,7 +41,7 @@
/datum/map_template/proc/preload_size(path)
var/list/bounds = list(1.#INF, 1.#INF, 1.#INF, -1.#INF, -1.#INF, -1.#INF)
var/datum/map_load_metadata/M = maploader.load_map(file(mappath), 1, 1, cropMap=FALSE, measureOnly=TRUE)
var/datum/map_load_metadata/M = maploader.load_map_impl(file(mappath), 1, 1, cropMap=FALSE, measureOnly=TRUE, no_changeturf=TRUE)
if(M)
bounds = extend_bounds_if_needed(bounds, M.bounds)
else
@@ -96,7 +95,6 @@
//initialize things that are normally initialized after map load
init_atoms(atoms_to_initialise)
init_shuttles(shuttle_state)
after_load(initial_z)
for(var/light_z = initial_z to world.maxz)
create_lighting_overlays_zlevel(light_z)
log_game("Z-level [name] loaded at [x], [y], [world.maxz]")
@@ -129,25 +127,18 @@
for(var/atom/A as anything in atoms)
if(isnull(A) || (A.flags_1 & INITIALIZED_1))
atoms -= A
continue
if(istype(A, /turf))
else if(istype(A, /turf))
turfs += A
continue
if(istype(A, /obj/structure/cable))
else if(istype(A, /obj/structure/cable))
cables += A
continue
if(istype(A,/obj/effect/landmark/map_load_mark))
LAZYADD(subtemplates_to_spawn, A)
continue
//Not mutually exclusive anymore section, no continue here, keep checking
if(istype(A, /obj/machinery/atmospherics))
atmos_machines += A
//Not mutually exclusive anymore section, pay close attention!
if(istype(A, /obj/machinery))
machines += A
if(istype(A, /obj/machinery/power/apc))
apcs += A
if(istype(A, /obj/machinery/atmospherics))
atmos_machines += A
else if(istype(A, /obj/machinery/power/apc))
apcs += A
var/notsuspended
if(!SSmachinery.can_fire)
@@ -161,16 +152,13 @@
if(notsuspended)
SSmachinery.can_fire = TRUE
for (var/i in apcs)
var/obj/machinery/power/apc/apc = i
for (var/obj/machinery/power/apc/apc as anything in apcs)
apc.update() // map-loading areas and APCs is weird, okay
for (var/i in machines)
var/obj/machinery/machine = i
for (var/obj/machinery/machine as anything in machines)
machine.power_change()
for (var/i in turfs)
var/turf/T = i
for (var/turf/T as anything in turfs)
T.post_change(FALSE)
if(template_flags & TEMPLATE_FLAG_NO_RUINS)
T.turf_flags |= TURF_NORUINS
@@ -225,13 +213,3 @@
for (var/max_bound in list(MAP_MAXX, MAP_MAXY, MAP_MAXZ))
bounds_to_combine[max_bound] = max(existing_bounds[max_bound], new_bounds[max_bound])
return bounds_to_combine
/datum/map_template/proc/after_load(z)
for(var/obj/effect/landmark/map_load_mark/mark in subtemplates_to_spawn)
subtemplates_to_spawn -= mark
if(LAZYLEN(mark.templates))
var/template = pick(mark.templates)
var/datum/map_template/M = new template()
M.load(get_turf(mark), TRUE)
qdel(mark)
LAZYCLEARLIST(subtemplates_to_spawn)
+147 -129
View File
@@ -12,16 +12,16 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
/dmm_suite
// /"([a-zA-Z]+)" = \(((?:.|\n)*?)\)\n(?!\t)|\((\d+),(\d+),(\d+)\) = \{"([a-zA-Z\n]*)"\}/g
var/static/regex/dmmRegex = new/regex({""(\[a-zA-Z]+)" = \\(((?:.|\n)*?)\\)\n(?!\t)|\\((\\d+),(\\d+),(\\d+)\\) = \\{"(\[a-zA-Z\n]*)"\\}"}, "g")
var/static/regex/dmmRegex = new(@'"([a-zA-Z]+)" = (?:\(\n|\()((?:.|\n)*?)\)\n(?!\t)|\((\d+),(\d+),(\d+)\) = \{"([a-zA-Z\n]*)"\}', "g")
// /^[\s\n]+"?|"?[\s\n]+$|^"|"$/g
var/static/regex/trimQuotesRegex = new/regex({"^\[\\s\n]+"?|"?\[\\s\n]+$|^"|"$"}, "g")
// /^[\s\n]+|[\s\n]+$/
var/static/regex/trimRegex = new/regex("^\[\\s\n]+|\[\\s\n]+$", "g")
var/static/list/modelCache = list()
var/static/space_key
#ifdef TESTING
var/static/turfsSkipped
#endif
//text trimming (both directions) helper macro
#define TRIM_TEXT(text) (replacetext_char(text, trimRegex, ""))
/**
* Construct the model map and control the loading process
@@ -33,34 +33,42 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
* 2) Read the map line by line, parsing the result (using parse_grid)
*
*/
// dmm_files: A list of .dmm files to load (Required).
// z_offset: A number representing the z-level on which to start loading the map (Optional).
// cropMap: When true, the map will be cropped to fit the existing world dimensions (Optional).
// measureOnly: When true, no changes will be made to the world (Optional).
// no_changeturf: When true, turf/AfterChange won't be called on loaded turfs
/dmm_suite/load_map(dmm_file as file, x_offset as num, y_offset as num, z_offset as num, cropMap as num, measureOnly as num, no_changeturf as num, lower_crop_x as num, lower_crop_y as num, upper_crop_x as num, upper_crop_y as num)
//How I wish for RAII
Master.StartLoadingMap()
space_key = null
#ifdef TESTING
turfsSkipped = 0
#endif
. = load_map_impl(dmm_file, x_offset, y_offset, z_offset, cropMap, measureOnly, no_changeturf, lower_crop_x, upper_crop_x, lower_crop_y, upper_crop_y)
#ifdef TESTING
if(turfsSkipped)
testing("Skipped loading [turfsSkipped] default turfs")
#endif
Master.StopLoadingMap()
/dmm_suite/proc/load_map_impl(dmm_file, x_offset, y_offset, z_offset, cropMap, measureOnly, no_changeturf, x_lower = -INFINITY, x_upper = INFINITY, y_lower = -INFINITY, y_upper = INFINITY)
var/tfile = dmm_file//the map file we're creating
/*#### WARNING AURORA SNOWFLAKE SECTION ####*/
if(isfile(tfile))
// name/path of dmm file, new var so as to not rename the `tfile` var
// to maybe maintain compatibility with other codebases
var/tfilepath = "[tfile]"
tfile = null
// use bapi to read, parse, process, mapmanip etc
// this will "crash"/stacktrace on fail
tfile = bapi_read_dmm_file(tfilepath)
// if bapi for whatever reason fails and returns null
// Except when measuring; i don't give a shit about bapi when measuring the map size,
// if you're changing the map size from bapi you're stupid and deserve it not to work,
// and i'm not slowing down the whole initialization by a third just for this possibility
if(!measureOnly)
tfile = bapi_read_dmm_file(tfilepath)
// if bapi for whatever reason fails and returns null, or we're measuring
// try to load it the old dm way instead
if(!tfile)
tfile = file2text(tfilepath)
/*#### END AURORA SNOWFLAKE SECTION ####*/
if(!x_offset)
x_offset = 1
if(!y_offset)
@@ -73,32 +81,36 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
var/key_len = 0
var/stored_index = 1
var/list/atoms_to_initialise = list()
var/has_expanded_world_maxx = FALSE
var/has_expanded_world_maxy = FALSE
while(dmmRegex.Find(tfile, stored_index))
var/list/regexOutput
while(findtext(tfile, dmmRegex, stored_index))
stored_index = dmmRegex.next
// Datum var lookup is expensive, this isn't
regexOutput = dmmRegex.group
// "aa" = (/type{vars=blah})
if(dmmRegex.group[1]) // Model
var/key = dmmRegex.group[1]
if(regexOutput[1]) // Model
var/key = regexOutput[1]
if(grid_models[key]) // Duplicate model keys are ignored in DMMs
continue
if(key_len != length(key))
if(!key_len)
key_len = length(key)
else
throw EXCEPTION("Inconsistant key length in DMM")
CRASH("Inconsistent key length in DMM")
if(!measureOnly)
grid_models[key] = dmmRegex.group[2]
grid_models[key] = regexOutput[2]
// (1,1,1) = {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
else if(dmmRegex.group[3]) // Coords
else if(regexOutput[3]) // Coords
if(!key_len)
throw EXCEPTION("Coords before model definition in DMM")
CRASH("Coords before model definition in DMM")
var/curr_x = text2num(dmmRegex.group[3])
var/curr_x = text2num(regexOutput[3])
if(curr_x < x_lower || curr_x > x_upper)
continue
@@ -106,11 +118,11 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
var/xcrdStart = curr_x + x_offset - 1
//position of the currently processed square
var/xcrd
var/ycrd = text2num(dmmRegex.group[4]) + y_offset - 1
var/zcrd = text2num(dmmRegex.group[5]) + z_offset - 1
var/ycrd = text2num(regexOutput[4]) + y_offset - 1
var/zcrd = text2num(regexOutput[5]) + z_offset - 1
var/zexpansion = zcrd > world.maxz
if(zexpansion && !measureOnly) // don't actually expand the world if we're only measuring bounds
if(zexpansion && !measureOnly) // don't actually expand the world if we're only measuring bounds
if(cropMap)
continue
else
@@ -119,39 +131,42 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
if(!no_changeturf)
WARNING("Z-level expansion occurred without no_changeturf set, this may cause problems when /turf/post_change is called.")
bounds[MAP_MINX] = min(bounds[MAP_MINX], Clamp(xcrdStart, x_lower, x_upper))
bounds[MAP_MINX] = min(bounds[MAP_MINX], clamp(xcrdStart, x_lower, x_upper))
bounds[MAP_MINZ] = min(bounds[MAP_MINZ], zcrd)
bounds[MAP_MAXZ] = max(bounds[MAP_MAXZ], zcrd)
var/list/gridLines = splittext(dmmRegex.group[6], "\n")
var/list/gridLines = splittext(regexOutput[6], "\n")
var/leadingBlanks = 0
while(leadingBlanks < gridLines.len && gridLines[++leadingBlanks] == "")
while(leadingBlanks < length(gridLines) && gridLines[++leadingBlanks] == "")
if(leadingBlanks > 1)
gridLines.Cut(1, leadingBlanks) // Remove all leading blank lines.
if(!gridLines.len) // Skip it if only blank lines exist.
if(!length(gridLines)) // Skip it if only blank lines exist.
continue
if(gridLines.len && gridLines[gridLines.len] == "")
gridLines.Cut(gridLines.len) // Remove only one blank line at the end.
if(gridLines[length(gridLines)] == "")
gridLines.Cut(length(gridLines)) // Remove only one blank line at the end.
bounds[MAP_MINY] = min(bounds[MAP_MINY], Clamp(ycrd, y_lower, y_upper))
ycrd += gridLines.len - 1 // Start at the top and work down
bounds[MAP_MINY] = min(bounds[MAP_MINY], clamp(ycrd, y_lower, y_upper))
ycrd += length(gridLines) - 1 // Start at the top and work down
if(!cropMap && ycrd > world.maxy)
if(!measureOnly)
world.maxy = ycrd // Expand Y here. X is expanded in the loop below
has_expanded_world_maxy = TRUE
bounds[MAP_MAXY] = max(bounds[MAP_MAXY], Clamp(ycrd, y_lower, y_upper))
bounds[MAP_MAXY] = max(bounds[MAP_MAXY], clamp(ycrd, y_lower, y_upper))
else
bounds[MAP_MAXY] = max(bounds[MAP_MAXY], Clamp(min(ycrd, world.maxy), y_lower, y_upper))
bounds[MAP_MAXY] = max(bounds[MAP_MAXY], clamp(min(ycrd, world.maxy), y_lower, y_upper))
var/maxx = xcrdStart
if(measureOnly)
for(var/line in gridLines)
maxx = max(maxx, xcrdStart + length(line) / key_len - 1)
else
//turn off base new Initialization until the whole thing is loaded
SSatoms.map_loader_begin(REF(src))
for(var/line in gridLines)
if((ycrd - y_offset + 1) < y_lower || (ycrd - y_offset + 1) > y_upper) //Reverse operation and check if it is out of bounds of cropping.
--ycrd
@@ -174,20 +189,20 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
var/no_afterchange = no_changeturf || zexpansion
if(!no_afterchange || (model_key != space_key))
if(!grid_models[model_key])
throw EXCEPTION("Undefined model key in DMM.")
CRASH("Undefined model key in DMM.")
var/datum/grid_load_metadata/M = parse_grid(grid_models[model_key], model_key, xcrd, ycrd, zcrd, no_changeturf || zexpansion)
if (M)
atoms_to_initialise += M.atoms_to_initialise
#ifdef TESTING
else
++turfsSkipped
#endif
CHECK_TICK
// CHECK_TICK
maxx = max(maxx, xcrd)
++xcrd
--ycrd
bounds[MAP_MAXX] = Clamp(max(bounds[MAP_MAXX], cropMap ? min(maxx, world.maxx) : maxx), x_lower, x_upper)
//Restore initialization to the previous value
SSatoms.map_loader_stop(REF(src))
bounds[MAP_MAXX] = clamp(max(bounds[MAP_MAXX], cropMap ? min(maxx, world.maxx) : maxx), x_lower, x_upper)
CHECK_TICK
@@ -208,11 +223,6 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
M.atoms_to_initialise = atoms_to_initialise
return M
/datum/grid_load_metadata
var/list/atoms_to_initialise
var/list/atoms_to_delete
/**
* Fill a given tile with its area/turf/objects/mobs
* Variable model is one full map line (e.g /turf/unsimulated/wall{icon_state = "rock"}, /area/mine/explored)
@@ -230,7 +240,15 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
* 4) Instanciates the atom with its variables
*
*/
/datum/grid_load_metadata
var/list/atoms_to_initialise
var/list/atoms_to_delete
/dmm_suite/proc/parse_grid(model as text, model_key as text, xcrd as num,ycrd as num,zcrd as num, no_changeturf as num)
//This should only ever be called by load_map_impl() after announcing the map is being loaded to SSatoms
PRIVATE_PROC(TRUE)
/*Method parse_grid()
- Accepts a text string containing a comma separated list of type paths of the
same construction as those contained in a .dmm file, and instantiates them.
@@ -260,16 +278,19 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
//finding next member (e.g /turf/unsimulated/wall{icon_state = "rock"} or /area/mine/explored)
dpos = find_next_delimiter_position(model, old_position, ",", "{", "}") //find next delimiter (comma here) that's not within {...}
var/full_def = trim_text(copytext(model, old_position, dpos)) //full definition, e.g : /obj/foo/bar{variables=derp}
var/full_def = TRIM_TEXT(copytext(model, old_position, dpos)) //full definition, e.g : /obj/foo/bar{variables=derp}
var/variables_start = findtext(full_def, "{")
var/path_str = trim_text(copytext(full_def, 1, variables_start))
var/atom_def = text2path(path_str) //path definition, e.g /obj/foo/bar
var/atom_def = text2path(TRIM_TEXT(copytext(full_def, 1, variables_start))) //path definition, e.g /obj/foo/bar
old_position = dpos + 1
if(!atom_def) // Skip the item if the path does not exist. Fix your crap, mappers!
crash_with("Invalid type in map. [path_str]")
continue
#ifdef UNIT_TEST
log_error("Couldn't find atom path specified in map: [full_def]")
#endif
if (dpos == 0)
break
else
continue
members += atom_def
@@ -279,8 +300,8 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
if(variables_start)//if there's any variable
full_def = copytext(full_def,variables_start+1,length(full_def))//removing the last '}'
fields = readlist(full_def, ";")
if(fields.len)
if(!trim(fields[fields.len]))
if(length(fields))
if(!trimtext(fields[length(fields)]))
--fields.len
for(var/I in fields)
var/value = fields[I]
@@ -303,7 +324,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
// 5. and the members are world.turf and world.area
// Basically, if we find an entry like this: "XXX" = (/turf/default, /area/default)
// We can skip calling this proc every time we see XXX
if(no_changeturf && !space_key && members.len == 2 && members_attributes.len == 2 && length(members_attributes[1]) == 0 && length(members_attributes[2]) == 0 && (world.area in members) && (world.turf in members))
if(no_changeturf && !space_key && length(members) == 2 && length(members_attributes) == 2 && length(members_attributes[1]) == 0 && length(members_attributes[2]) == 0 && (world.area in members) && (world.turf in members))
space_key = model_key
return
@@ -315,14 +336,12 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
//since we've switched off autoinitialisation, record atoms to initialise later
var/list/atoms_to_initialise = list()
//turn off base new Initialization until the whole thing is loaded
SSatoms.map_loader_begin(text_ref(src))
//The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
var/turf/crds = locate(xcrd,ycrd,zcrd)
//first instance the /area and remove it from the members list
index = members.len
index = length(members)
if(members[index] != /area/template_noop)
var/atype = members[index]
var/atom/instance = GLOB.areas_by_type[atype]
@@ -353,18 +372,14 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
if(T)
//if others /turf are presents, simulates the underlays piling effect
index = first_turf_index + 1
while(index <= members.len - 1) // Last item is an /area
var/underlay = T.appearance
while(index <= length(members) - 1) // Last item is an /area
T = instance_atom(members[index],members_attributes[index],crds,no_changeturf)//instance new turf
T.underlays += underlay
index++
atoms_to_initialise += T
//finally instance all remainings objects/mobs
for(index in 1 to first_turf_index-1)
atoms_to_initialise += instance_atom(members[index],members_attributes[index],crds,no_changeturf)
//Restore initialization to the previous value
SSatoms.map_loader_stop(text_ref(src))
var/datum/grid_load_metadata/M = new
M.atoms_to_initialise = atoms_to_initialise
@@ -390,22 +405,13 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
//custom CHECK_TICK here because we don't want things created while we're sleeping to not initialize
if(TICK_CHECK)
SSatoms.map_loader_stop(text_ref(src))
SSatoms.map_loader_stop(REF(src))
stoplag()
SSatoms.map_loader_begin(text_ref(src))
SSatoms.map_loader_begin(REF(src))
/dmm_suite/proc/create_atom(path, crds)
// Doing this async is impossible, as we must return the ref.
return new path (crds)
//text trimming (both directions) helper proc
//optionally removes quotes before and after the text (for variable name)
/dmm_suite/proc/trim_text(what as text,trim_quotes=0)
if(trim_quotes)
return trimQuotesRegex.Replace(what, "")
else
return trimRegex.Replace(what, "")
set waitfor = FALSE
. = new path (crds)
//find the position of the next delimiter,skipping whatever is comprised between opening_escape and closing_escape
//returns 0 if reached the last delimiter
@@ -421,70 +427,73 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
return next_delimiter
/dmm_suite/proc/readlistitem(text as text, is_key = FALSE)
//Check for string
if(findtext(text,"\"",1,2))
. = copytext(text,2,findtext(text,"\"",3,0))
//Check for number
// Keys cannot safely be numbers. This implementation will return null if
// an assoc key is a number.
else if(!is_key && isnum(text2num(text)))
. = text2num(text)
//Check for null
else if(text == "null")
. = null
//Check for list
else if(copytext(text,1,6) == "list(")
. = readlist(copytext(text,6,length(text)))
//Check for file
else if(copytext(text,1,2) == "'")
. = file(copytext(text,2,length(text)))
//Check for path
else if(ispath(text2path(text)))
. = text2path(text)
// Associative keys are fed in without quotation marks.
// So if none of the other cases apply, return simply the string that was given.
// This case is also triggered for item values. So I guess we're also looking for text.
else if(is_key || istext(text))
. = text
//build a list from variables in text form (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
//return the filled list
/dmm_suite/proc/readlist(text as text, delimiter=",")
var/list/to_return = list()
. = list()
if (!text)
return
var/position
var/old_position = 1
var/list_index = 1
do
//find next delimiter that is not within "..."
while(position != 0)
// find next delimiter that is not within "..."
position = find_next_delimiter_position(text,old_position,delimiter)
//check if this is a simple variable (as in list(var1, var2)) or an associative one (as in list(var1="foo",var2=7))
// check if this is a simple variable (as in list(var1, var2)) or an associative one (as in list(var1="foo",var2=7))
var/equal_position = findtext(text,"=",old_position, position)
var/trim_left = TRIM_TEXT(copytext(text,old_position,(equal_position ? equal_position : position)))
var/left_constant = parse_constant(trim_left)
if(position)
old_position = position + length(text[position])
if(!left_constant) // damn newlines man. Exists to provide behavior consistency with the above loop. not a major cost becuase this path is cold
continue
var/trim_left = trim_text(copytext(text,old_position,(equal_position ? equal_position : position)),1)//the name of the variable, must trim quotes to build a BYOND compliant associatives list
old_position = position + 1
if(equal_position && !isnum(left_constant))
// Associative var, so do the association.
// Note that numbers cannot be keys - the RHS is dropped if so.
var/trim_right = TRIM_TEXT(copytext(text, equal_position + length(text[equal_position]), position))
var/right_constant = parse_constant(trim_right)
.[left_constant] = right_constant
else // simple var
. += list(left_constant)
if(equal_position) //associative var, so do the association
var/trim_right = trim_text(copytext(text,equal_position+1,position))//the content of the variable
trim_left = readlistitem(trim_left, TRUE) // Assoc vars can be anything that isn't a num!
to_return[trim_left] = readlistitem(trim_right)
list_index++
else if (length(trim_left)) //simple var
to_return.len++
to_return[list_index++] = readlistitem(trim_left)
/dmm_suite/proc/parse_constant(text)
// number
var/num = text2num(text)
if(isnum(num))
return num
while(position != 0)
// string
if(text[1] == "\"")
// insert implied locate \" and length("\"") here
// It's a minimal timesave but it is a timesave
// Safe becuase we're guarenteed trimmed constants
return copytext(text, 2, -1)
return to_return
// list
if(copytext(text, 1, 6) == "list(")//6 == length("list(") + 1
return readlist(copytext(text, 6, -1))
// typepath
var/path = text2path(text)
if(ispath(path))
return path
// file
if(text[1] == "'")
return file(copytext_char(text, 2, -1))
// null
if(text == "null")
return null
// not parsed:
// - pops: /obj{name="foo"}
// - new(), newlist(), icon(), matrix(), sound()
// fallback: string
return text
/dmm_suite/Destroy()
..()
@@ -507,12 +516,19 @@ GLOBAL_LIST_INIT(_preloader_path, null)
GLOB._preloader_path = path
/dmm_suite/preloader/proc/load(atom/what)
GLOB.use_preloader = FALSE
var/list/attributes = src.attributes
for(var/attribute in attributes)
var/value = attributes[attribute]
if(islist(value))
value = deepCopyList(value)
value = deep_copy_list(value)
#ifdef TESTING
if(what.vars[attribute] == value)
var/message = "<font color=green>[what.type]</font> at [AREACOORD(what)] - <b>VAR:</b> <font color=red>[attribute] = [isnull(value) ? "null" : (isnum(value) ? value : "\"[value]\"")]</font>"
log_mapping("DIRTY VAR: [message]")
GLOB.dirty_vars += message
#endif
what.vars[attribute] = value
GLOB.use_preloader = FALSE
/area/template_noop
name = "Area Passthrough"
@@ -521,3 +537,5 @@ GLOBAL_LIST_INIT(_preloader_path, null)
/turf/template_noop
name = "Turf Passthrough"
icon_state = "noop"
#undef TRIM_TEXT
+1 -1
View File
@@ -51,7 +51,7 @@
var/mob/living/M = AM
M.Weaken(2)
to_chat(M, SPAN_DANGER("You're thrown back by a mystical force!"))
AM.throw_at(throwtarget, ((Clamp((5 - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, 5))), 1)
AM.throw_at(throwtarget, ((clamp((5 - (clamp(distfromcaster - 2, 0, distfromcaster))), 3, 5))), 1)
log_and_message_admins("used tornado sweep(Plasma Fist)", "[A]")
return
+1 -1
View File
@@ -46,7 +46,7 @@
A.spin(10,1)
M.Weaken(3)
A.visible_message(M, SPAN_DANGER("[A] swiftly leg sweeps [M]!"))
AM.throw_at(sweeptarget, ((Clamp((1 - (Clamp(distfromcaster - 2, 0, distfromcaster))), 1, 1))), 1)
AM.throw_at(sweeptarget, ((clamp((1 - (clamp(distfromcaster - 2, 0, distfromcaster))), 1, 1))), 1)
/datum/martial_art/sol_combat/proc/quick_choke(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)//is actually lung punch
A.do_attack_animation(D)
+1 -1
View File
@@ -201,7 +201,7 @@
scrolled = 1
if("left")
scrolled = -1
var/new_merchant = Clamp(current_merchant + scrolled, 1, SStrade.traders.len)
var/new_merchant = clamp(current_merchant + scrolled, 1, SStrade.traders.len)
if(new_merchant != current_merchant)
hailed_merchant = 0
last_comms = null
+2 -2
View File
@@ -479,7 +479,7 @@ GLOBAL_LIST_EMPTY_TYPED(alloy_data, /datum/alloy)
//Compressing materials
else if(ores_processing[metal] & SMELTER_MODE_COMPRESSING && O.compresses_to)
var/can_make = Clamp(ores_stored[metal], 0, ROUND_UP(sheets_per_second*seconds_per_tick) - sheets)
var/can_make = clamp(ores_stored[metal], 0, ROUND_UP(sheets_per_second*seconds_per_tick) - sheets)
if(can_make % 2 > 0)
can_make--
@@ -499,7 +499,7 @@ GLOBAL_LIST_EMPTY_TYPED(alloy_data, /datum/alloy)
//Smelting materials
else if(ores_processing[metal] & SMELTER_MODE_SMELTING && O.smelts_to)
var/can_make = Clamp(ores_stored[metal], 0, ROUND_UP(sheets_per_second*seconds_per_tick) - sheets)
var/can_make = clamp(ores_stored[metal], 0, ROUND_UP(sheets_per_second*seconds_per_tick) - sheets)
var/material/M = SSmaterials.get_material_by_name(O.smelts_to)
if(!istype(M) || !can_make || ores_stored[metal] < 1)
+4 -2
View File
@@ -38,6 +38,8 @@ var/list/mineral_can_smooth_with = list(
density = TRUE
blocks_air = TRUE
temperature = T0C
explosion_resistance = 2
var/mined_turf = /turf/unsimulated/floor/asteroid/ash/rocky
var/ore/mineral
var/mined_ore = 0
@@ -127,7 +129,7 @@ var/list/mineral_can_smooth_with = list(
if(1.0)
mined_ore = 2 //some of the stuff gets blown up
GetDrilled()
SSicon_smooth.add_to_queue_neighbors(src)
QUEUE_SMOOTH_NEIGHBORS(src)
/turf/simulated/mineral/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
SHOULD_CALL_PARENT(FALSE) //Fucking snowflake stack of procs
@@ -1003,5 +1005,5 @@ var/list/asteroid_floor_smooth = list(
/turf/simulated/mineral/Destroy()
clear_ore_effects()
SSicon_smooth.add_to_queue_neighbors(src)
QUEUE_SMOOTH_NEIGHBORS(src)
. = ..()
@@ -94,7 +94,7 @@ Exercise Verbs
stamina_loss += 2
if(get_shock() > 10)
stamina_loss += 3
var/nut_factor = max_nutrition ? Clamp(nutrition / max_nutrition, 0, 1) : 1
var/nut_factor = max_nutrition ? clamp(nutrition / max_nutrition, 0, 1) : 1
if(nut_factor <= CREW_NUTRITION_HUNGRY)
stamina_loss += 2
if(on_knees)
@@ -1049,8 +1049,8 @@
return
timevomit = max(timevomit, 5)
timevomit = Clamp(timevomit, 1, 10)
level = Clamp(level, 1, 3)
timevomit = clamp(timevomit, 1, 10)
level = clamp(level, 1, 3)
lastpuke = TRUE
to_chat(src, SPAN_WARNING("You feel nauseous..."))
@@ -327,13 +327,13 @@
if(M.stamina <= disarm_cost)
to_chat(M, SPAN_DANGER("You're too tired to disarm someone!"))
return FALSE
M.stamina = Clamp(M.stamina - disarm_cost, 0, M.max_stamina) // attempting to knock something out of someone's hands, or pushing them over, is exhausting!
M.stamina = clamp(M.stamina - disarm_cost, 0, M.max_stamina) // attempting to knock something out of someone's hands, or pushing them over, is exhausting!
else if(M.max_stamina <= 0)
disarm_cost = M.max_nutrition / 6
if(M.nutrition <= disarm_cost)
to_chat(M, SPAN_DANGER("You don't have enough power to disarm someone!"))
return FALSE
M.nutrition = Clamp(M.nutrition - disarm_cost, 0, M.max_nutrition)
M.nutrition = clamp(M.nutrition - disarm_cost, 0, M.max_nutrition)
M.attack_log += "\[[time_stamp()]\] <span class='warning'>Disarmed [src.name] ([src.ckey])</span>"
src.attack_log += "\[[time_stamp()]\] <font color='orange'>Has been disarmed by [M.name] ([M.ckey])</font>"
@@ -125,7 +125,7 @@
if(.) //We moved
handle_leg_damage()
var/turf/T = loc
var/turf/T = get_turf(loc)
var/footsound
var/top_layer = 0
if(istype(T))
+5 -5
View File
@@ -114,7 +114,7 @@
if(zone_exposure >= 1)
return 1
pressure_adjustment_coefficient = max(pressure_adjustment_coefficient, zone_exposure)
pressure_adjustment_coefficient = Clamp(pressure_adjustment_coefficient, 0, 1) // So it isn't less than 0 or larger than 1.
pressure_adjustment_coefficient = clamp(pressure_adjustment_coefficient, 0, 1) // So it isn't less than 0 or larger than 1.
return pressure_adjustment_coefficient
@@ -212,7 +212,7 @@
if(gene.is_active(src))
gene.OnMobLife(src)
total_radiation = Clamp(total_radiation,0,100)
total_radiation = clamp(total_radiation,0,100)
if (total_radiation)
if(src.is_diona())
@@ -983,7 +983,7 @@
//Update hunger and thirst UI less often, its not important
if((life_tick % 3 == 0))
if(nutrition_icon)
var/nut_factor = max_nutrition ? Clamp(nutrition / max_nutrition, 0, 1) : 1
var/nut_factor = max_nutrition ? clamp(nutrition / max_nutrition, 0, 1) : 1
var/nut_icon = 5 //5 to 0, with 5 being lowest, 0 being highest
if(nut_factor >= CREW_NUTRITION_OVEREATEN)
nut_icon = 0
@@ -1000,7 +1000,7 @@
nutrition_icon.icon_state = new_val
if(hydration_icon)
var/hyd_factor = max_hydration ? Clamp(hydration / max_hydration, 0, 1) : 1
var/hyd_factor = max_hydration ? clamp(hydration / max_hydration, 0, 1) : 1
var/hyd_icon = 5
if(hyd_factor >= CREW_HYDRATION_OVERHYDRATED)
hyd_icon = 0
@@ -1019,7 +1019,7 @@
if(isSynthetic())
var/obj/item/organ/internal/cell/IC = internal_organs_by_name[BP_CELL]
if(istype(IC) && IC.is_usable())
var/chargeNum = Clamp(Ceiling(IC.percent()/25), 0, 4) //0-100 maps to 0-4, but give it a paranoid clamp just in case.
var/chargeNum = clamp(Ceiling(IC.percent()/25), 0, 4) //0-100 maps to 0-4, but give it a paranoid clamp just in case.
cells.icon_state = "charge[chargeNum]"
else
cells.icon_state = "charge-empty"
@@ -655,7 +655,7 @@
prescriptions += 7
if(H.equipment_prescription)
prescriptions -= H.equipment_prescription
return Clamp(prescriptions, 0, 7)
return clamp(prescriptions, 0, 7)
// pre_move is set to TRUE when the mob checks whether it's even possible to move, so resources aren't drained until after the move completes
// once the mob moves and its loc actually changes, the pre_move is set to FALSE and all the proper resources are drained
@@ -32,7 +32,7 @@
/datum/unarmed_attack/claws/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
var/obj/item/organ/external/affecting = target.get_organ(zone)
attack_damage = Clamp(attack_damage, 1, 5)
attack_damage = clamp(attack_damage, 1, 5)
if(target == user)
user.visible_message(SPAN_DANGER("[user] [pick(attack_verb)] [user.get_pronoun("himself")] in the [affecting.name]!"))
@@ -193,7 +193,7 @@ GLOBAL_LIST_EMPTY(sparring_attack_cache)
var/organ = affecting.name
attack_damage = Clamp(attack_damage, 1, 5) // We expect damage input of 1 to 5 for this proc. But we leave this check juuust in case.
attack_damage = clamp(attack_damage, 1, 5) // We expect damage input of 1 to 5 for this proc. But we leave this check juuust in case.
if(target == user)
user.visible_message(SPAN_DANGER("[user] [pick(attack_verb)] [user.get_pronoun("himself")] in the [organ]!"))
@@ -286,7 +286,7 @@ GLOBAL_LIST_EMPTY(sparring_attack_cache)
var/organ = affecting.name
attack_damage = Clamp(attack_damage, 1, 5)
attack_damage = clamp(attack_damage, 1, 5)
switch(attack_damage)
if(1 to 2) user.visible_message(SPAN_DANGER("[user] threw [target] a glancing [pick(attack_noun)] to the [organ]!")) //it's not that they're kicking lightly, it's that the kick didn't quite connect
@@ -334,7 +334,7 @@ GLOBAL_LIST_EMPTY(sparring_attack_cache)
var/obj/item/clothing/shoes = user.shoes
attack_damage = Clamp(attack_damage, 1, 5)
attack_damage = clamp(attack_damage, 1, 5)
switch(attack_damage)
if(1 to 4) user.visible_message(SPAN_DANGER("[pick("[user] stomped on", "[user] slammed [user.get_pronoun("his")] [shoes ? copytext(shoes.name, 1, -1) : "foot"] down onto")] [target]'s [organ]!"))
@@ -145,7 +145,7 @@
return toxloss
/mob/living/carbon/slime/adjustToxLoss(var/amount)
toxloss = Clamp(toxloss + amount, 0, maxHealth)
toxloss = clamp(toxloss + amount, 0, maxHealth)
/mob/living/carbon/slime/setToxLoss(var/amount)
adjustToxLoss(amount-getToxLoss())
+1 -1
View File
@@ -282,7 +282,7 @@ default behaviour is:
/mob/living/proc/adjustBruteLoss(var/amount)
if (status_flags & GODMODE)
return
health = Clamp(health - amount, 0, maxHealth)
health = clamp(health - amount, 0, maxHealth)
/mob/living/proc/getOxyLoss()
return 0
+1 -1
View File
@@ -403,7 +403,7 @@
return
/mob/living/proc/adjust_fire_stacks(var/add_fire_stacks)
fire_stacks = Clamp(fire_stacks + add_fire_stacks, FIRE_MIN_STACKS, FIRE_MAX_STACKS)
fire_stacks = clamp(fire_stacks + add_fire_stacks, FIRE_MIN_STACKS, FIRE_MAX_STACKS)
return fire_stacks
@@ -39,7 +39,7 @@
installed = -1
/datum/robot_component/proc/get_damage(var/type)
return Clamp(brute_damage + electronics_damage,0,max_damage)
return clamp(brute_damage + electronics_damage,0,max_damage)
/datum/robot_component/proc/take_damage(brute, electronics, damage_flags)
if(installed != 1)
@@ -11,7 +11,7 @@
for(var/V in components)
var/datum/robot_component/C = components[V]
if(C.installed)
amount += Clamp(C.brute_damage, 0, C.max_damage)
amount += clamp(C.brute_damage, 0, C.max_damage)
else if(C.installed == -1)
amount += C.max_damage / 2
return amount
@@ -21,7 +21,7 @@
for(var/V in components)
var/datum/robot_component/C = components[V]
if(C.installed)
amount += Clamp(C.electronics_damage, 0, C.max_damage)
amount += clamp(C.electronics_damage, 0, C.max_damage)
else if(C.installed == -1)
amount += C.max_damage / 2
return amount
+1 -1
View File
@@ -9,7 +9,7 @@
. = TRUE
message = Gibberish(message, C.max_damage / C.get_damage())
else
var/damaged = 100 - (Clamp(health, 0, maxHealth) / maxHealth) * 100
var/damaged = 100 - (clamp(health, 0, maxHealth) / maxHealth) * 100
if(damaged > 40)
. = TRUE
message = Gibberish(message, damaged - 10)
+1 -1
View File
@@ -58,7 +58,7 @@
var/armor = 100 * affecting.get_blocked_ratio(target, DAMAGE_BRUTE, damage = 30)
if(armor < 70)
to_chat(target, SPAN_DANGER("You feel extreme pain!"))
affecting.adjustHalLoss(Clamp(0, 60 - affecting.getHalLoss(), 30)) //up to 60 halloss
affecting.adjustHalLoss(clamp(0, 60 - affecting.getHalLoss(), 30)) //up to 60 halloss
/obj/item/grab/proc/attack_eye(mob/living/carbon/human/target, mob/living/carbon/human/attacker)
if(!istype(attacker))
@@ -121,7 +121,7 @@
var/account_name = params["name"]
var/starting_funds = max(params["funds"], 0)
starting_funds = Clamp(starting_funds, 0, SSeconomy.station_account.money) // Not authorized to put the station in debt.
starting_funds = clamp(starting_funds, 0, SSeconomy.station_account.money) // Not authorized to put the station in debt.
starting_funds = min(starting_funds, FUND_CAP) // Not authorized to give more than the fund cap.
SSeconomy.create_account(account_name, starting_funds, src)
@@ -92,7 +92,7 @@
if("change_supplied_law_position")
var/new_position = input(usr, "Enter new supplied law position between 1 and [MAX_SUPPLIED_LAW_NUMBER], inclusive. Inherent laws at the same index as a supplied law will not be stated.", "Law Position", supplied_law_position) as num|null
if(isnum(new_position) && !computer.use_check_and_message(usr))
supplied_law_position = Clamp(new_position, 1, MAX_SUPPLIED_LAW_NUMBER)
supplied_law_position = clamp(new_position, 1, MAX_SUPPLIED_LAW_NUMBER)
return TRUE
if("edit_law")
@@ -22,7 +22,7 @@
return TRUE
if(action == "brightness" && computer.flashlight)
var/new_brightness = Clamp(0, params["new_brightness"]/10, 1)
var/new_brightness = clamp(0, params["new_brightness"]/10, 1)
computer.flashlight.tweak_brightness(new_brightness)
. = TRUE
@@ -61,7 +61,7 @@
data["battery"] = computer.battery_module ? list("rating" = computer.battery_module.battery_rating, "percent" = computer.battery_module.battery.percent()) : null
if(computer.flashlight)
var/brightness = Clamp(0, round(computer.flashlight.power, 0.1) * 10, 10)
var/brightness = clamp(0, round(computer.flashlight.power, 0.1) * 10, 10)
data["brightness"] = brightness
return data
@@ -21,6 +21,6 @@
parent_computer.set_light(initial(parent_computer.light_range), initial(parent_computer.light_power), flashlight_color)
/obj/item/computer_hardware/flashlight/proc/tweak_brightness(var/new_power)
. = power = Clamp(0, new_power, 1)
. = power = clamp(0, new_power, 1)
if(parent_computer && enabled)
parent_computer.set_light(range, power, flashlight_color)
+1
View File
@@ -12,6 +12,7 @@
is_hole = TRUE
roof_type = null
footstep_sound = null
explosion_resistance = 3
z_flags = ZM_MIMIC_DEFAULTS | ZM_MIMIC_OVERWRITE | ZM_MIMIC_NO_AO | ZM_ALLOW_ATMOS
turf_flags = TURF_FLAG_BACKGROUND
pathing_pass_method = TURF_PATHING_PASS_NO //You'll fall down most likely, unless no gravity, but not worth the processing just for this special case
+2 -2
View File
@@ -57,7 +57,7 @@
pulse_mod++
if(owner.status_flags & FAKEDEATH)
pulse = Clamp(PULSE_NONE + pulse_mod, PULSE_NONE, PULSE_2FAST) //pretend that we're dead. unlike actual death, can be inflienced by meds
pulse = clamp(PULSE_NONE + pulse_mod, PULSE_NONE, PULSE_2FAST) //pretend that we're dead. unlike actual death, can be inflienced by meds
return
//If heart is stopped, it isn't going to restart itself randomly.
@@ -74,7 +74,7 @@
return
// Pulse normally shouldn't go above PULSE_2FAST
pulse = Clamp(PULSE_NORM + pulse_mod, PULSE_SLOW, PULSE_2FAST)
pulse = clamp(PULSE_NORM + pulse_mod, PULSE_SLOW, PULSE_2FAST)
// If fibrillation, then it can be PULSE_THREADY
var/fibrillation = oxy <= BLOOD_VOLUME_SURVIVE || (prob(30) && owner.shock_stage > 120)
+1 -1
View File
@@ -232,7 +232,7 @@
if(toxins_pp > safe_toxins_max)
var/ratio = (poison/safe_toxins_max) * 10
if(reagents)
reagents.add_reagent(/singleton/reagent/toxin, Clamp(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE))
reagents.add_reagent(/singleton/reagent/toxin, clamp(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE))
breath.adjust_gas(poison_type, -poison/6, update = 0) //update after
owner.phoron_alert = max(owner.phoron_alert, 1)
else
+1 -1
View File
@@ -419,7 +419,7 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
if(!(status & ORGAN_ASSISTED))
return //We check earlier, but just to make sure.
surge_damage = Clamp(0, surge + surge_damage, MAXIMUM_SURGE_DAMAGE) //We want X seconds at most of hampered movement or what have you.
surge_damage = clamp(0, surge + surge_damage, MAXIMUM_SURGE_DAMAGE) //We want X seconds at most of hampered movement or what have you.
surge_time = world.time
/obj/item/organ/proc/removed(var/mob/living/carbon/human/target,var/mob/living/user)

Some files were not shown because too many files have changed in this diff Show More