break it real good

This commit is contained in:
Letter N
2020-12-23 18:58:02 +08:00
parent 47a3afff54
commit 35edf3589b
11 changed files with 160 additions and 63 deletions

View File

@@ -69,3 +69,7 @@
#ifdef TRAVISTESTING
#define TESTING
#endif
// A reasonable number of maximum overlays an object needs
// If you think you need more, rethink it
#define MAX_ATOM_OVERLAYS 100

View File

@@ -287,6 +287,21 @@
speed = 1.4
layer = 3
/obj/screen/parallax_layer/random
blend_mode = BLEND_OVERLAY
speed = 3
layer = 3
/obj/screen/parallax_layer/random/space_gas
icon_state = "space_gas"
/obj/screen/parallax_layer/random/space_gas/Initialize(mapload, view)
. = ..()
src.add_atom_colour(SSparallax.random_parallax_color, ADMIN_COLOUR_PRIORITY)
/obj/screen/parallax_layer/random/asteroids
icon_state = "asteroids"
/obj/screen/parallax_layer/planet
icon_state = "planet"
blend_mode = BLEND_OVERLAY
@@ -295,11 +310,11 @@
layer = 30
/obj/screen/parallax_layer/planet/update_status(mob/M)
var/turf/T = get_turf(M)
if(is_station_level(T.z))
invisibility = 0
else
invisibility = INVISIBILITY_ABSTRACT
var/client/C = M.client
var/turf/posobj = get_turf(C.eye)
if(!posobj)
return
invisibility = is_station_level(posobj.z) ? 0 : INVISIBILITY_ABSTRACT
/obj/screen/parallax_layer/planet/update_o()
return //Shit wont move
return //Shit won't move

View File

@@ -48,9 +48,16 @@ SUBSYSTEM_DEF(overlays)
for (var/thing in queue)
count++
if(thing)
STAT_START_STOPWATCH
var/atom/A = thing
if(A.overlays.len >= MAX_ATOM_OVERLAYS)
//Break it real GOOD
stack_trace("Too many overlays on [A.type] - [A.overlays.len], refusing to update and cutting")
A.overlays.Cut()
continue
STAT_START_STOPWATCH
COMPILE_OVERLAYS(A)
UNSETEMPTY(A.add_overlays)
UNSETEMPTY(A.remove_overlays)
STAT_STOP_STOPWATCH
STAT_LOG_ENTRY(stats, A.type)
if(mc_check)
@@ -117,9 +124,8 @@ SUBSYSTEM_DEF(overlays)
#define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.queue += src;
/atom/proc/cut_overlays()
LAZYINITLIST(remove_overlays)
LAZYINITLIST(add_overlays)
remove_overlays = overlays.Copy()
add_overlays.Cut()
add_overlays = null
//If not already queued for work and there are overlays to remove
if(NOT_QUEUED_ALREADY && remove_overlays.len)
@@ -129,7 +135,7 @@ SUBSYSTEM_DEF(overlays)
if(!overlays)
return
overlays = build_appearance_list(overlays)
LAZYINITLIST(add_overlays) //always initialized after this point
LAZYINITLIST(add_overlays)
LAZYINITLIST(remove_overlays)
var/a_len = add_overlays.len
var/r_len = remove_overlays.len
@@ -140,8 +146,9 @@ SUBSYSTEM_DEF(overlays)
var/fr_len = remove_overlays.len
//If not already queued and there is work to be done
if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len))
if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len ))
QUEUE_FOR_COMPILE
UNSETEMPTY(add_overlays)
/atom/proc/add_overlay(list/overlays)
if(!overlays)

View File

@@ -7,13 +7,21 @@ SUBSYSTEM_DEF(parallax)
var/list/currentrun
var/planet_x_offset = 128
var/planet_y_offset = 128
var/random_layer
var/random_parallax_color
/datum/controller/subsystem/parallax/Initialize(timeofday)
//These are cached per client so needs to be done asap so people joining at roundstart do not miss these.
/datum/controller/subsystem/parallax/PreInit()
. = ..()
if(prob(70)) //70% chance to pick a special extra layer
random_layer = pick(/obj/screen/parallax_layer/random/space_gas, /obj/screen/parallax_layer/random/asteroids)
random_parallax_color = pick(COLOR_TEAL, COLOR_GREEN, COLOR_SILVER, COLOR_YELLOW, COLOR_CYAN, COLOR_ORANGE, COLOR_PURPLE)//Special color for random_layer1. Has to be done here so everyone sees the same color.
planet_y_offset = rand(100, 160)
planet_x_offset = rand(100, 160)
/datum/controller/subsystem/parallax/fire(resumed = 0)
/datum/controller/subsystem/parallax/fire(resumed = FALSE)
if (!resumed)
src.currentrun = GLOB.clients.Copy()
@@ -21,24 +29,27 @@ SUBSYSTEM_DEF(parallax)
var/list/currentrun = src.currentrun
while(length(currentrun))
var/client/C = currentrun[currentrun.len]
var/client/processing_client = currentrun[currentrun.len]
currentrun.len--
if (!C || !C.eye)
if (QDELETED(processing_client) || !processing_client.eye)
if (MC_TICK_CHECK)
return
continue
var/atom/movable/A = C.eye
if(!istype(A))
continue
for (A; isloc(A.loc) && !isturf(A.loc); A = A.loc);
if(A != C.movingmob)
if(C.movingmob != null)
C.movingmob.client_mobs_in_contents -= C.mob
UNSETEMPTY(C.movingmob.client_mobs_in_contents)
LAZYINITLIST(A.client_mobs_in_contents)
A.client_mobs_in_contents += C.mob
C.movingmob = A
var/atom/movable/movable_eye = processing_client.eye
if(!istype(movable_eye))
continue
for (movable_eye; isloc(movable_eye.loc) && !isturf(movable_eye.loc); movable_eye = movable_eye.loc);
if(movable_eye == processing_client.movingmob)
if (MC_TICK_CHECK)
return
continue
if(!isnull(processing_client.movingmob))
LAZYREMOVE(processing_client.movingmob.client_mobs_in_contents, processing_client.mob)
LAZYADD(movable_eye.client_mobs_in_contents, processing_client.mob)
processing_client.movingmob = movable_eye
if (MC_TICK_CHECK)
return
currentrun = null

View File

@@ -18,7 +18,7 @@ SUBSYSTEM_DEF(pathfinder)
var/free
var/list/flow
/datum/flowcache/New(var/n)
/datum/flowcache/New(n)
. = ..()
lcount = n
run = 0

View File

@@ -43,6 +43,7 @@ SUBSYSTEM_DEF(persistence)
LoadAntagReputation()
LoadRandomizedRecipes()
LoadPanicBunker()
LoadPaintings()
return ..()
/datum/controller/subsystem/persistence/proc/LoadSatchels()

View File

@@ -18,7 +18,7 @@ SUBSYSTEM_DEF(profiler)
if(CONFIG_GET(flag/auto_profile))
StartProfiling()
else
StopProfiling() //Stop the early start from world/New
StopProfiling() //Stop the early start profiler
return ..()
/datum/controller/subsystem/profiler/fire()
@@ -31,12 +31,23 @@ SUBSYSTEM_DEF(profiler)
return ..()
/datum/controller/subsystem/profiler/proc/StartProfiling()
#if DM_BUILD < 1506
stack_trace("Auto profiling unsupported on this byond version")
CONFIG_SET(flag/auto_profile, FALSE)
#else
world.Profile(PROFILE_START)
#endif
/datum/controller/subsystem/profiler/proc/StopProfiling()
#if DM_BUILD >= 1506
world.Profile(PROFILE_STOP)
#endif
/datum/controller/subsystem/profiler/proc/DumpFile()
#if DM_BUILD < 1506
stack_trace("Auto profiling unsupported on this byond version")
CONFIG_SET(flag/auto_profile, FALSE)
#else
var/timer = TICK_USAGE_REAL
var/current_profile_data = world.Profile(PROFILE_REFRESH,format="json")
fetch_cost = MC_AVERAGE(fetch_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
@@ -49,3 +60,4 @@ SUBSYSTEM_DEF(profiler)
timer = TICK_USAGE_REAL
WRITE_FILE(json_file, current_profile_data)
write_cost = MC_AVERAGE(write_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
#endif

View File

@@ -1,6 +1,7 @@
PROCESSING_SUBSYSTEM_DEF(radiation)
name = "Radiation"
flags = SS_NO_INIT | SS_BACKGROUND
wait = 1 SECONDS
var/list/warned_atoms = list()
@@ -13,5 +14,5 @@ PROCESSING_SUBSYSTEM_DEF(radiation)
warned_atoms[ref] = TRUE
var/atom/master = contamination.parent
SSblackbox.record_feedback("tally", "contaminated", 1, master.type)
var/msg = "has become contamintaed with enough radiation to contaminate other objects. || Source: [contamination.source] || Strength: [contamination.strength]"
var/msg = "has become contaminated with enough radiation to contaminate other objects. || Source: [contamination.source] || Strength: [contamination.strength]"
master.investigate_log(msg, INVESTIGATE_RADIATION)

View File

@@ -5,34 +5,48 @@ SUBSYSTEM_DEF(sounds)
flags = SS_NO_FIRE
init_order = INIT_ORDER_SOUNDS
var/static/using_channels_max = CHANNEL_HIGHEST_AVAILABLE //BYOND max channels
/// Amount of channels to reserve for random usage rather than reservations being allowed to reserve all channels. Also a nice safeguard for when someone screws up.
var/static/random_channels_min = 50
// Hey uh these two needs to be initialized fast because the whole "things get deleted before init" thing.
/// Assoc list, "[channel]" = either the datum using it or TRUE for an unsafe-reserved (datumless reservation) channel
var/list/using_channels = list()
/// Assoc list, `"[channel]" =` either the datum using it or TRUE for an unsafe-reserved (datumless reservation) channel
var/list/using_channels
/// Assoc list datum = list(channel1, channel2, ...) for what channels something reserved.
var/list/using_channels_by_datum = list()
/// List of all available channels with associations set to TRUE for fast lookups/allocation.
var/list/available_channels
var/list/using_channels_by_datum
// Special datastructure for fast channel management
/// List of all channels as numbers
var/list/channel_list
/// Associative list of all reserved channels associated to their position. `"[channel_number]" =` index as number
var/list/reserved_channels
/// lower iteration position - Incremented and looped to get "random" sound channels for normal sounds. The channel at this index is returned when asking for a random channel.
var/channel_random_low
/// higher reserve position - decremented and incremented to reserve sound channels, anything above this is reserved. The channel at this index is the highest unreserved channel.
var/channel_reserve_high
/datum/controller/subsystem/sounds/Initialize()
setup_available_channels()
return ..()
/datum/controller/subsystem/sounds/proc/setup_available_channels()
available_channels = list()
channel_list = list()
reserved_channels = list()
using_channels = list()
using_channels_by_datum = list()
for(var/i in 1 to using_channels_max)
available_channels[num2text(i)] = TRUE
channel_list += i
channel_random_low = 1
channel_reserve_high = length(channel_list)
/// Removes a channel from using list.
/datum/controller/subsystem/sounds/proc/free_sound_channel(channel)
channel = num2text(channel)
var/using = using_channels[channel]
using_channels -= channel
if(using)
var/text_channel = num2text(channel)
var/using = using_channels[text_channel]
using_channels -= text_channel
if(using != TRUE) // datum channel
using_channels_by_datum[using] -= channel
if(!length(using_channels_by_datum[using]))
using_channels_by_datum -= using
available_channels[channel] = TRUE
free_channel(channel)
/// Frees all the channels a datum is using.
/datum/controller/subsystem/sounds/proc/free_datum_channels(datum/D)
@@ -40,8 +54,8 @@ SUBSYSTEM_DEF(sounds)
if(!L)
return
for(var/channel in L)
using_channels -= channel
available_channels[channel] = TRUE
using_channels -= num2text(channel)
free_channel(channel)
using_channels_by_datum -= D
/// Frees all datumless channels
@@ -50,42 +64,72 @@ SUBSYSTEM_DEF(sounds)
/// NO AUTOMATIC CLEANUP - If you use this, you better manually free it later! Returns an integer for channel.
/datum/controller/subsystem/sounds/proc/reserve_sound_channel_datumless()
var/channel = random_available_channel_text()
if(!channel) //oh no..
. = reserve_channel()
if(!.) //oh no..
return FALSE
available_channels -= channel
using_channels[channel] = DATUMLESS
var/text_channel = num2text(.)
using_channels[text_channel] = DATUMLESS
LAZYINITLIST(using_channels_by_datum[DATUMLESS])
using_channels_by_datum[DATUMLESS] += channel
return text2num(channel)
using_channels_by_datum[DATUMLESS] += .
/// Reserves a channel for a datum. Automatic cleanup only when the datum is deleted. Returns an integer for channel.
/datum/controller/subsystem/sounds/proc/reserve_sound_channel(datum/D)
if(!D) //i don't like typechecks but someone will fuck it up
CRASH("Attempted to reserve sound channel without datum using the managed proc.")
var/channel = random_available_channel_text()
if(!channel)
.= reserve_channel()
if(!.)
return FALSE
available_channels -= channel
using_channels[channel] = D
var/text_channel = num2text(.)
using_channels[text_channel] = D
LAZYINITLIST(using_channels_by_datum[D])
using_channels_by_datum[D] += channel
return text2num(channel)
using_channels_by_datum[D] += .
/**
* Reserves a channel and updates the datastructure. Private proc.
*/
/datum/controller/subsystem/sounds/proc/reserve_channel()
PRIVATE_PROC(TRUE)
if(channel_reserve_high <= random_channels_min) // out of channels
return
var/channel = channel_list[channel_reserve_high]
reserved_channels[num2text(channel)] = channel_reserve_high--
return channel
/**
* Frees a channel and updates the datastructure. Private proc.
*/
/datum/controller/subsystem/sounds/proc/free_channel(number)
PRIVATE_PROC(TRUE)
var/text_channel = num2text(number)
var/index = reserved_channels[text_channel]
if(!index)
CRASH("Attempted to (internally) free a channel that wasn't reserved.")
reserved_channels -= text_channel
// push reserve index up, which makes it now on a channel that is reserved
channel_reserve_high++
// swap the reserved channel wtih the unreserved channel so the reserve index is now on an unoccupied channel and the freed channel is next to be used.
channel_list.Swap(channel_reserve_high, index)
// now, an existing reserved channel will likely (exception: unreserving last reserved channel) be at index
// get it, and update position.
var/text_reserved = num2text(channel_list[index])
if(!reserved_channels[text_reserved]) //if it isn't already reserved make sure we don't accidently mistakenly put it on reserved list!
return
reserved_channels[text_reserved] = index
/// Random available channel, returns text.
/datum/controller/subsystem/sounds/proc/random_available_channel_text()
return pick(available_channels)
if(channel_random_low > channel_reserve_high)
channel_random_low = 1
. = "[channel_list[channel_random_low++]]"
/// Random available channel, returns number
/datum/controller/subsystem/sounds/proc/random_available_channel()
return text2num(pick(available_channels))
/// If a channel is available
/datum/controller/subsystem/sounds/proc/is_channel_available(channel)
return available_channels[num2text(channel)]
if(channel_random_low > channel_reserve_high)
channel_random_low = 1
. = channel_list[channel_random_low++]
/// How many channels we have left.
/datum/controller/subsystem/sounds/proc/available_channels_left()
return length(available_channels)
return length(channel_list) - random_channels_min
#undef DATUMLESS

View File

@@ -13,7 +13,7 @@ SUBSYSTEM_DEF(spacedrift)
return ..()
/datum/controller/subsystem/spacedrift/fire(resumed = 0)
/datum/controller/subsystem/spacedrift/fire(resumed = FALSE)
if (!resumed)
src.currentrun = processing.Copy()
@@ -47,6 +47,7 @@ SUBSYSTEM_DEF(spacedrift)
var/old_dir = AM.dir
var/old_loc = AM.loc
AM.inertia_moving = TRUE
AM.set_glide_size(DELAY_TO_GLIDE_SIZE(AM.inertia_move_delay))
step(AM, AM.inertia_dir)
AM.inertia_moving = FALSE
AM.inertia_next_move = world.time + AM.inertia_move_delay

View File

@@ -203,3 +203,4 @@ SUBSYSTEM_DEF(statpanels)
set hidden = TRUE
statbrowser_ready = TRUE
init_verbs()