Merge remote-tracking branch 'upstream/master' into ambitioncheck
This commit is contained in:
@@ -348,6 +348,8 @@
|
||||
|
||||
/datum/config_entry/flag/dynamic_config_enabled
|
||||
|
||||
/datum/config_entry/flag/station_name_needs_approval
|
||||
|
||||
//ambition end
|
||||
config_entry_value = 5
|
||||
/datum/config_entry/number/max_ambitions // Maximum number of ambitions a mind can store.
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
/datum/config_entry/flag/log_access // log login/logout
|
||||
config_entry_value = TRUE
|
||||
|
||||
/// Config entry which special logging of failed logins under suspicious circumstances.
|
||||
/datum/config_entry/flag/log_suspicious_login
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/flag/log_say // log client say
|
||||
config_entry_value = TRUE
|
||||
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -14,6 +14,9 @@ SUBSYSTEM_DEF(atoms)
|
||||
|
||||
var/list/BadInitializeCalls = list()
|
||||
|
||||
/// Atoms that will be deleted once the subsystem is initialized
|
||||
var/list/queued_deletions = list()
|
||||
|
||||
initialized = INITIALIZATION_INSSATOMS
|
||||
|
||||
/datum/controller/subsystem/atoms/Initialize(timeofday)
|
||||
@@ -62,6 +65,12 @@ SUBSYSTEM_DEF(atoms)
|
||||
testing("Late initialized [late_loaders.len] atoms")
|
||||
late_loaders.Cut()
|
||||
|
||||
for (var/queued_deletion in queued_deletions)
|
||||
qdel(queued_deletion)
|
||||
|
||||
testing("[queued_deletions.len] atoms were queued for deletion.")
|
||||
queued_deletions.Cut()
|
||||
|
||||
/// Init this specific atom
|
||||
/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments)
|
||||
var/the_type = A.type
|
||||
@@ -151,6 +160,14 @@ SUBSYSTEM_DEF(atoms)
|
||||
if(fails & BAD_INIT_SLEPT)
|
||||
. += "- Slept during Initialize()\n"
|
||||
|
||||
/// Prepares an atom to be deleted once the atoms SS is initialized.
|
||||
/datum/controller/subsystem/atoms/proc/prepare_deletion(atom/target)
|
||||
if (initialized == INITIALIZATION_INNEW_REGULAR)
|
||||
// Atoms SS has already completed, just kill it now.
|
||||
qdel(target)
|
||||
else
|
||||
queued_deletions += WEAKREF(target)
|
||||
|
||||
/datum/controller/subsystem/atoms/Shutdown()
|
||||
var/initlog = InitLog()
|
||||
if(initlog)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -603,8 +603,10 @@ SUBSYSTEM_DEF(ticker)
|
||||
news_message = "The burst of energy released near [station_name()] has been confirmed as merely a test of a new weapon. However, due to an unexpected mechanical error, their communications system has been knocked offline."
|
||||
if(SHUTTLE_HIJACK)
|
||||
news_message = "During routine evacuation procedures, the emergency shuttle of [station_name()] had its navigation protocols corrupted and went off course, but was recovered shortly after."
|
||||
if(GANG_VICTORY)
|
||||
news_message = "Company officials reaffirmed that sudden deployments of special forces are not in any way connected to rumors of [station_name()] being covered in graffiti."
|
||||
if(GANG_OPERATING)
|
||||
news_message = "The company would like to state that any rumors of criminal organizing on board stations such as [station_name()] are falsehoods, and not to be emulated."
|
||||
if(GANG_DESTROYED)
|
||||
news_message = "The crew of [station_name()] would like to thank the Spinward Stellar Coalition Police Department for quickly resolving a minor terror threat to the station."
|
||||
|
||||
if(SSblackbox.first_death)
|
||||
var/list/ded = SSblackbox.first_death
|
||||
|
||||
Reference in New Issue
Block a user