Merge branch 'master' into familyport

This commit is contained in:
keronshb
2022-02-11 14:04:57 -05:00
1209 changed files with 276175 additions and 55667 deletions
+6 -1
View File
@@ -116,6 +116,11 @@ SUBSYSTEM_DEF(air)
/datum/controller/subsystem/air/proc/auxtools_update_reactions()
/datum/controller/subsystem/air/proc/add_reaction(datum/gas_reaction/r)
gas_reactions += r
sortTim(gas_reactions, /proc/cmp_gas_reaction)
auxtools_update_reactions()
/proc/reset_all_air()
SSair.can_fire = 0
message_admins("Air reset begun.")
@@ -405,7 +410,7 @@ SUBSYSTEM_DEF(air)
eq_cooldown += (1-delay_threshold) * (cost_equalize / total_thread_time) * 2
if(eq_cooldown > 0.5)
equalize_enabled = FALSE
excited_group_pressure_goal = max(0,excited_group_pressure_goal_target * (1 - delay_threshold))
excited_group_pressure_goal = max(0,excited_group_pressure_goal_target * delay_threshold)
/datum/controller/subsystem/air/proc/process_turfs(resumed = 0)
+47 -13
View File
@@ -1,33 +1,67 @@
#define COMMUNICATION_COOLDOWN 300
#define COMMUNICATION_COOLDOWN_AI 300
#define COMMUNICATION_COOLDOWN (30 SECONDS)
#define COMMUNICATION_COOLDOWN_AI (30 SECONDS)
#define COMMUNICATION_COOLDOWN_MEETING (5 MINUTES)
SUBSYSTEM_DEF(communications)
name = "Communications"
flags = SS_NO_INIT | SS_NO_FIRE
var/silicon_message_cooldown
var/nonsilicon_message_cooldown
COOLDOWN_DECLARE(silicon_message_cooldown)
COOLDOWN_DECLARE(nonsilicon_message_cooldown)
COOLDOWN_DECLARE(emergency_meeting_cooldown)
/datum/controller/subsystem/communications/proc/can_announce(mob/living/user, is_silicon)
if(is_silicon && silicon_message_cooldown > world.time)
. = FALSE
else if(!is_silicon && nonsilicon_message_cooldown > world.time)
. = FALSE
if(is_silicon && COOLDOWN_FINISHED(src, silicon_message_cooldown))
return TRUE
else if(!is_silicon && COOLDOWN_FINISHED(src, nonsilicon_message_cooldown))
return TRUE
else
. = TRUE
return FALSE
/datum/controller/subsystem/communications/proc/make_announcement(mob/living/user, is_silicon, input)
if(!can_announce(user, is_silicon))
return FALSE
if(is_silicon)
minor_announce(html_decode(input),"[user.name] Announces:")
silicon_message_cooldown = world.time + COMMUNICATION_COOLDOWN_AI
COOLDOWN_START(src, silicon_message_cooldown, COMMUNICATION_COOLDOWN_AI)
else
priority_announce(html_decode(user.treat_message(input)), null, 'sound/misc/announce.ogg', "Captain")
nonsilicon_message_cooldown = world.time + COMMUNICATION_COOLDOWN
priority_announce(html_decode(user.treat_message(input)), null, 'sound/misc/announce.ogg', "Captain", has_important_message = TRUE)
COOLDOWN_START(src, nonsilicon_message_cooldown, COMMUNICATION_COOLDOWN)
user.log_talk(input, LOG_SAY, tag="priority announcement")
message_admins("[ADMIN_LOOKUPFLW(user)] has made a priority announcement.")
/**
* Check if a mob can call an emergency meeting
*
* Should only really happen during april fools.
* Checks to see that it's been at least 5 minutes since the last emergency meeting call.
* Arguments:
* * user - Mob who called the meeting
*/
/datum/controller/subsystem/communications/proc/can_make_emergency_meeting(mob/living/user)
if(!(SSevents.holidays && SSevents.holidays[APRIL_FOOLS]))
return FALSE
else if(COOLDOWN_FINISHED(src, emergency_meeting_cooldown))
return TRUE
else
return FALSE
/**
* Call an emergency meeting
*
* Communications subsystem wrapper for the call_emergency_meeting world proc.
* Checks to make sure the proc can be called, and handles
* relevant logging and timing. See that proc definition for more detail.
* Arguments:
* * user - Mob who called the meeting
*/
/datum/controller/subsystem/communications/proc/emergency_meeting(mob/living/user)
if(!can_make_emergency_meeting(user))
return FALSE
call_emergency_meeting(user, get_area(user))
COOLDOWN_START(src, emergency_meeting_cooldown, COMMUNICATION_COOLDOWN_MEETING)
message_admins("[ADMIN_LOOKUPFLW(user)] has called an emergency meeting.")
/datum/controller/subsystem/communications/proc/send_message(datum/comm_message/sending,print = TRUE,unique = FALSE)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
@@ -40,7 +74,7 @@ SUBSYSTEM_DEF(communications)
var/obj/item/paper/P = new /obj/item/paper(C.loc)
P.name = "paper - '[sending.title]'"
P.info = sending.content
P.update_icon()
P.update_appearance()
#undef COMMUNICATION_COOLDOWN
#undef COMMUNICATION_COOLDOWN_AI
+74 -35
View File
@@ -5,21 +5,6 @@ SUBSYSTEM_DEF(parallax)
priority = FIRE_PRIORITY_PARALLAX
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun
var/planet_x_offset = 128
var/planet_y_offset = 128
var/random_layer
var/random_parallax_color
//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(/atom/movable/screen/parallax_layer/random/space_gas, /atom/movable/screen/parallax_layer/random/asteroids)
random_parallax_color = pick(COLOR_TEAL, COLOR_GREEN, COLOR_YELLOW, COLOR_CYAN, COLOR_ORANGE, COLOR_PURPLE)//Special color for random_layer1. Has to be done here so everyone sees the same color. [COLOR_SILVER]
planet_y_offset = rand(100, 160)
planet_x_offset = rand(100, 160)
/datum/controller/subsystem/parallax/fire(resumed = FALSE)
if (!resumed)
@@ -28,28 +13,82 @@ SUBSYSTEM_DEF(parallax)
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(length(currentrun))
var/client/processing_client = currentrun[currentrun.len]
currentrun.len--
if (QDELETED(processing_client) || !processing_client.eye)
if(times_fired % 5) // lazy tick
while(length(currentrun))
var/client/processing_client = currentrun[currentrun.len]
currentrun.len--
if (QDELETED(processing_client) || !processing_client.eye)
if (MC_TICK_CHECK)
return
continue
processing_client.parallax_holder?.Update()
if (MC_TICK_CHECK)
return
continue
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)
else // full tick
while(length(currentrun))
var/client/processing_client = currentrun[currentrun.len]
currentrun.len--
if (QDELETED(processing_client) || !processing_client.eye)
if (MC_TICK_CHECK)
return
continue
processing_client.parallax_holder?.Update(TRUE)
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
/**
* Gets parallax type for zlevel.
*/
/datum/controller/subsystem/parallax/proc/get_parallax_type(z)
return /datum/parallax/space
/**
* Gets parallax for zlevel.
*/
/datum/controller/subsystem/parallax/proc/get_parallax_datum(z)
var/datum_type = get_parallax_type(z)
return new datum_type
/**
* Gets parallax added vis contents for zlevel
*/
/datum/controller/subsystem/parallax/proc/get_parallax_vis_contents(z)
return list()
/**
* Gets parallax motion for a zlevel
*
* Returns null or list(speed, dir deg clockwise from north, windup, turnrate)
* THE RETURNED LIST MUST BE A 4-TUPLE, OR PARALLAX WILL CRASH.
* DO NOT SCREW WITH THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
*
* This will override area motion
*/
/datum/controller/subsystem/parallax/proc/get_parallax_motion(z)
return null
/**
* updates all parallax for clients on a z
*/
/datum/controller/subsystem/parallax/proc/update_clients_on_z(z)
for(var/client/C in GLOB.clients)
if(C.mob.z == z)
C.parallax_holder?.Update()
/**
* resets all parallax for clients on a z
*/
/datum/controller/subsystem/parallax/proc/reset_clients_on_z(z)
for(var/client/C in GLOB.clients)
if(C.mob.z == z)
C.parallax_holder?.Reset()
/**
* updates motion of all clients on z
*/
/datum/controller/subsystem/parallax/proc/update_z_motion(z)
for(var/client/C in GLOB.clients)
if(C.mob.z == z)
C.parallax_holder?.UpdateMotion()
@@ -17,7 +17,6 @@ SUBSYSTEM_DEF(processing)
/datum/controller/subsystem/processing/fire(resumed = FALSE)
if (!resumed)
currentrun = processing.Copy()
var/delta_time = (flags & SS_TICKER)? (wait * world.tick_lag * 0.1) : (wait * 0.1)
//cache for sanic speed (lists are references anyways)
var/list/current_run = currentrun
@@ -26,7 +25,7 @@ SUBSYSTEM_DEF(processing)
current_run.len--
if(QDELETED(thing))
processing -= thing
else if(thing.process(delta_time) == PROCESS_KILL)
else if(thing.process(wait * 0.1) == PROCESS_KILL)
// fully stop so that a future START_PROCESSING will work
STOP_PROCESSING(src, thing)
if (MC_TICK_CHECK)
@@ -47,5 +46,5 @@ SUBSYSTEM_DEF(processing)
* If you override this do not call parent, as it will return PROCESS_KILL. This is done to prevent objects that dont override process() from staying in the processing list
*/
/datum/proc/process(delta_time)
SHOULD_NOT_SLEEP(TRUE)
set waitfor = FALSE
return PROCESS_KILL
@@ -48,6 +48,13 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
cli.prefs.save_character()
if (!silent && LAZYLEN(cut))
to_chat(to_chat_target || user, "<span class='boldwarning'>Some quirks have been cut from your character because of these quirks conflicting with your job assignment: [english_list(cut)].</span>")
var/mob/living/carbon/human/H = user
if(istype(H) && H.dna?.species)
var/datum/species/S = H.dna.species
if(S.remove_blacklisted_quirks(H))
to_chat(to_chat_target || user, "<span class='boldwarning'>Some quirks have been cut from your character due to them conflicting with your species: [english_list(S.removed_quirks)]</span>")
/datum/controller/subsystem/processing/quirks/proc/quirk_path_by_name(name)
return quirks[name]
+7 -1
View File
@@ -343,10 +343,16 @@ SUBSYSTEM_DEF(research)
break //Just need one to work.
if (!isnull(last_income))
var/income_time_difference = world.time - last_income
science_tech.last_bitcoins = bitcoins // Doesn't take tick drift into account
for(var/i in bitcoins)
bitcoins[i] *= income_time_difference / 10
science_tech.add_point_list(bitcoins)
var/list/income = science_tech.commit_income()
for(var/i in income)
var/old_weighted = science_tech.last_bitcoins[i] * (1 MINUTES - income_time_difference)
var/new_weighted = income[i] * income_time_difference
science_tech.last_bitcoins[i] = (old_weighted + new_weighted) / (1 MINUTES)
else
science_tech.last_bitcoins = bitcoins.Copy()
last_income = world.time
/datum/controller/subsystem/research/proc/calculate_server_coefficient() //Diminishing returns.
+3 -1
View File
@@ -513,7 +513,9 @@ SUBSYSTEM_DEF(shuttle)
if(!midpoint)
return FALSE
var/area/shuttle/transit/A = new()
A.parallax_movedir = travel_dir
A.parallax_moving = TRUE
A.parallax_move_angle = dir2angle(travel_dir)
A.parallax_move_speed = M.parallax_speed
A.contents = proposal.reserved_turfs
var/obj/docking_port/stationary/transit/new_transit_dock = new(midpoint)
new_transit_dock.reserved_area = proposal
@@ -0,0 +1,3 @@
PROCESSING_SUBSYSTEM_DEF(sound_loops)
name = "Sound Loops"
priority = FIRE_PRIORITY_SOUND_LOOPS
+6 -6
View File
@@ -4,7 +4,7 @@ SUBSYSTEM_DEF(sounds)
name = "Sounds"
flags = SS_NO_FIRE
init_order = INIT_ORDER_SOUNDS
var/static/using_channels_max = CHANNEL_HIGHEST_AVAILABLE //BYOND max channels
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
@@ -42,7 +42,7 @@ SUBSYSTEM_DEF(sounds)
var/text_channel = num2text(channel)
var/using = using_channels[text_channel]
using_channels -= text_channel
if(using != TRUE) // datum channel
if(using != TRUE) // datum channel
using_channels_by_datum[using] -= channel
if(!length(using_channels_by_datum[using]))
using_channels_by_datum -= using
@@ -65,7 +65,7 @@ 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()
. = reserve_channel()
if(!.) //oh no..
if(!.) //oh no..
return FALSE
var/text_channel = num2text(.)
using_channels[text_channel] = DATUMLESS
@@ -74,7 +74,7 @@ SUBSYSTEM_DEF(sounds)
/// 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
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.")
.= reserve_channel()
if(!.)
@@ -89,7 +89,7 @@ SUBSYSTEM_DEF(sounds)
*/
/datum/controller/subsystem/sounds/proc/reserve_channel()
PRIVATE_PROC(TRUE)
if(channel_reserve_high <= random_channels_min) // out of channels
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--
@@ -112,7 +112,7 @@ SUBSYSTEM_DEF(sounds)
// 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!
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