Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into super-special-awesome-dynamic

This commit is contained in:
Putnam
2019-11-14 22:31:48 -08:00
385 changed files with 31577 additions and 134898 deletions
@@ -0,0 +1,35 @@
SUBSYSTEM_DEF(adjacent_air)
name = "Atmos Adjacency"
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
wait = 10
priority = FIRE_PRIORITY_ATMOS_ADJACENCY
var/list/queue = list()
/datum/controller/subsystem/adjacent_air/stat_entry()
#ifdef TESTING
..("P:[length(queue)], S:[GLOB.atmos_adjacent_savings[1]], T:[GLOB.atmos_adjacent_savings[2]]")
#else
..("P:[length(queue)]")
#endif
/datum/controller/subsystem/adjacent_air/Initialize()
while(length(queue))
fire(mc_check = FALSE)
return ..()
/datum/controller/subsystem/adjacent_air/fire(resumed = FALSE, mc_check = TRUE)
var/list/queue = src.queue
while (length(queue))
var/turf/currT = queue[1]
queue.Cut(1,2)
currT.ImmediateCalculateAdjacentTurfs()
if(mc_check)
if(MC_TICK_CHECK)
break
else
CHECK_TICK
+40
View File
@@ -658,6 +658,46 @@ SUBSYSTEM_DEF(job)
message_admins(msg)
CRASH(msg)
/datum/controller/subsystem/job/proc/equip_loadout(mob/dead/new_player/N, mob/living/M, equipbackpackstuff)
var/mob/the_mob = N
if(!the_mob)
the_mob = M // cause this doesn't get assigned if player is a latejoiner
if(the_mob.client && the_mob.client.prefs && (the_mob.client.prefs.chosen_gear && the_mob.client.prefs.chosen_gear.len))
if(!ishuman(M))//no silicons allowed
return
for(var/i in the_mob.client.prefs.chosen_gear)
var/datum/gear/G = i
G = GLOB.loadout_items[slot_to_string(initial(G.category))][initial(G.name)]
if(!G)
continue
var/permitted = TRUE
if(G.restricted_roles && G.restricted_roles.len && !(M.mind.assigned_role in G.restricted_roles))
permitted = FALSE
if(G.donoritem && !G.donator_ckey_check(the_mob.client.ckey))
permitted = FALSE
if(!equipbackpackstuff && G.category == SLOT_IN_BACKPACK)//snowflake check since plopping stuff in the backpack doesnt work for pre-job equip loadout stuffs
permitted = FALSE
if(equipbackpackstuff && G.category != SLOT_IN_BACKPACK)//ditto
permitted = FALSE
if(!permitted)
continue
var/obj/item/I = new G.path
if(!M.equip_to_slot_if_possible(I, G.category, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // If the job's dresscode compliant, try to put it in its slot, first
if(iscarbon(M))
var/mob/living/carbon/C = M
var/obj/item/storage/backpack/B = C.back
if(!B || !SEND_SIGNAL(B, COMSIG_TRY_STORAGE_INSERT, I, null, TRUE, TRUE)) // Otherwise, try to put it in the backpack, for carbons.
I.forceMove(get_turf(C))
else if(!M.equip_to_slot_if_possible(I, SLOT_IN_BACKPACK, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // Otherwise, try to put it in the backpack
I.forceMove(get_turf(M)) // If everything fails, just put it on the floor under the mob.
/datum/controller/subsystem/job/proc/FreeRole(rank)
if(!rank)
return
var/datum/job/job = GetJob(rank)
if(!job)
return FALSE
job.current_positions = max(0, job.current_positions - 1)
///////////////////////////////////
//Keeps track of all living heads//
+27 -15
View File
@@ -14,6 +14,7 @@ SUBSYSTEM_DEF(mapping)
var/list/ruins_templates = list()
var/list/space_ruins_templates = list()
var/list/lava_ruins_templates = list()
var/datum/space_level/isolated_ruins_z //Created on demand during ruin loading.
var/list/shuttle_templates = list()
var/list/shelter_templates = list()
@@ -25,6 +26,7 @@ SUBSYSTEM_DEF(mapping)
var/list/datum/turf_reservations //list of turf reservations
var/list/used_turfs = list() //list of turf = datum/turf_reservation
var/list/reservation_ready = list()
var/clearing_reserved_turfs = FALSE
// Z-manager stuff
@@ -95,7 +97,7 @@ SUBSYSTEM_DEF(mapping)
// Set up Z-level transitions.
setup_map_transitions()
generate_station_area_list()
initialize_reserved_level()
initialize_reserved_level(transit.z_value)
return ..()
/* Nuke threats, for making the blue tiles on the station go RED
@@ -442,7 +444,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
GLOB.the_gateway.wait = world.time
/datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override, border_type_override)
UNTIL(initialized && !clearing_reserved_turfs)
UNTIL(reservation_ready["[z]"] && !clearing_reserved_turfs)
var/datum/turf_reservation/reserve = new type
if(turf_type_override)
reserve.turf_type = turf_type_override
@@ -454,8 +456,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
return reserve
//If we didn't return at this point, theres a good chance we ran out of room on the exisiting reserved z levels, so lets try a new one
num_of_res_levels += 1
var/newReserved = add_new_zlevel("Transit/Reserved [num_of_res_levels]", list(ZTRAIT_RESERVED = TRUE))
if(reserve.Reserve(width, height, newReserved))
var/datum/space_level/newReserved = add_new_zlevel("Transit/Reserved [num_of_res_levels]", list(ZTRAIT_RESERVED = TRUE))
initialize_reserved_level(newReserved.z_value)
if(reserve.Reserve(width, height, newReserved.z_value))
return reserve
else
if(!level_trait(z, ZTRAIT_RESERVED))
@@ -467,19 +470,22 @@ GLOBAL_LIST_EMPTY(the_station_areas)
QDEL_NULL(reserve)
//This is not for wiping reserved levels, use wipe_reservations() for that.
/datum/controller/subsystem/mapping/proc/initialize_reserved_level()
/datum/controller/subsystem/mapping/proc/initialize_reserved_level(z)
UNTIL(!clearing_reserved_turfs) //regardless, lets add a check just in case.
clearing_reserved_turfs = TRUE //This operation will likely clear any existing reservations, so lets make sure nothing tries to make one while we're doing it.
for(var/i in levels_by_trait(ZTRAIT_RESERVED))
var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,i))
var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,i))
var/block = block(A, B)
for(var/t in block)
// No need to empty() these, because it's world init and they're
// already /turf/open/space/basic.
var/turf/T = t
T.flags_1 |= UNUSED_RESERVATION_TURF_1
unused_turfs["[i]"] = block
if(!level_trait(z,ZTRAIT_RESERVED))
clearing_reserved_turfs = FALSE
CRASH("Invalid z level prepared for reservations.")
var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,z))
var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,z))
var/block = block(A, B)
for(var/t in block)
// No need to empty() these, because it's world init and they're
// already /turf/open/space/basic.
var/turf/T = t
T.flags_1 |= UNUSED_RESERVATION_TURF_1
unused_turfs["[z]"] = block
reservation_ready["[z]"] = TRUE
clearing_reserved_turfs = FALSE
/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs)
@@ -513,3 +519,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
for(var/B in areas)
var/area/A = B
A.reg_in_areas_in_z()
/datum/controller/subsystem/mapping/proc/get_isolated_ruin_z()
if(!isolated_ruins_z)
isolated_ruins_z = add_new_zlevel("Isolated Ruins/Reserved", list(ZTRAIT_RESERVED = TRUE, ZTRAIT_ISOLATED_RUINS = TRUE))
initialize_reserved_level(isolated_ruins_z.z_value)
return isolated_ruins_z.z_value
+6
View File
@@ -69,6 +69,10 @@ SUBSYSTEM_DEF(pai)
candidate.comments = copytext(sanitize(candidate.comments),1,MAX_MESSAGE_LEN)
if("submit")
if(isobserver(usr))
var/mob/dead/observer/O = usr
if(!O.can_reenter_round())
return FALSE
if(candidate)
candidate.ready = 1
for(var/obj/item/paicard/p in pai_card_list)
@@ -148,6 +152,8 @@ SUBSYSTEM_DEF(pai)
continue
if(!(ROLE_PAI in G.client.prefs.be_special))
continue
if(!G.can_reenter_round()) // this should use notify_ghosts() instead one day.
return FALSE
to_chat(G, "<span class='ghostalert'>[user] is requesting a pAI personality! Use the pAI button to submit yourself as one.</span>")
addtimer(CALLBACK(src, .proc/spam_again), spam_delay)
var/list/available = list()
+205 -10
View File
@@ -4,24 +4,32 @@ SUBSYSTEM_DEF(research)
priority = FIRE_PRIORITY_RESEARCH
wait = 10
init_order = INIT_ORDER_RESEARCH
//TECHWEB STATIC
var/list/techweb_nodes = list() //associative id = node datum
var/list/techweb_designs = list() //associative id = node datum
var/list/datum/techweb/techwebs = list()
var/datum/techweb/science/science_tech
var/datum/techweb/admin/admin_tech
var/datum/techweb_node/error_node/error_node //These two are what you get if a node/design is deleted and somehow still stored in a console.
var/datum/design/error_design/error_design
//ERROR LOGGING
var/list/invalid_design_ids = list() //associative id = number of times
var/list/invalid_node_ids = list() //associative id = number of times
var/list/invalid_node_boost = list() //associative id = error message
var/list/obj/machinery/rnd/server/servers = list()
var/datum/techweb/science/science_tech
var/datum/techweb/admin/admin_tech
var/list/techweb_nodes = list() //associative id = node datum
var/list/techweb_categories = list() //category name = list(node.id = node)
var/list/techweb_designs = list() //associative id = node datum
var/list/techweb_nodes_starting = list() //associative id = node datum
var/list/techweb_nodes_starting = list() //associative id = TRUE
var/list/techweb_categories = list() //category name = list(node.id = TRUE)
var/list/techweb_boost_items = list() //associative double-layer path = list(id = list(point_type = point_discount))
var/list/techweb_nodes_hidden = list() //Nodes that should be hidden by default.
var/list/techweb_nodes_hidden = list() //Node ids that should be hidden by default.
var/list/techweb_point_items = list( //path = list(point type = value)
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 2500),
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 5000), // Cit three more anomalys anomalys
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 7500),
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 10000),
// - Slime Extracts! -
// - Slime Extracts! -
/obj/item/slime_extract/grey = list(TECHWEB_POINT_TYPE_GENERIC = 500), // Adds in slime core deconing
/obj/item/slime_extract/metal = list(TECHWEB_POINT_TYPE_GENERIC = 750),
/obj/item/slime_extract/purple = list(TECHWEB_POINT_TYPE_GENERIC = 750),
@@ -294,6 +302,8 @@ SUBSYSTEM_DEF(research)
science_tech = new /datum/techweb/science
admin_tech = new /datum/techweb/admin
autosort_categories()
error_design = new
error_node = new
return ..()
/datum/controller/subsystem/research/fire()
@@ -330,6 +340,191 @@ SUBSYSTEM_DEF(research)
for(var/i in techweb_nodes)
var/datum/techweb_node/I = techweb_nodes[i]
if(techweb_categories[I.category])
techweb_categories[I.category][I.id] = I
techweb_categories[I.category][I.id] = TRUE
else
techweb_categories[I.category] = list(I.id = I)
techweb_categories[I.category] = list(I.id = TRUE)
/datum/controller/subsystem/research/proc/techweb_node_by_id(id)
return techweb_nodes[id] || error_node
/datum/controller/subsystem/research/proc/techweb_design_by_id(id)
return techweb_designs[id] || error_design
/datum/controller/subsystem/research/proc/on_design_deletion(datum/design/D)
for(var/i in techweb_nodes)
var/datum/techweb_node/TN = techwebs[i]
TN.on_design_deletion(TN)
for(var/i in techwebs)
var/datum/techweb/T = i
T.recalculate_nodes(TRUE)
/datum/controller/subsystem/research/proc/on_node_deletion(datum/techweb_node/TN)
for(var/i in techweb_nodes)
var/datum/techweb_node/TN2 = techwebs[i]
TN2.on_node_deletion(TN)
for(var/i in techwebs)
var/datum/techweb/T = i
T.recalculate_nodes(TRUE)
/datum/controller/subsystem/research/proc/initialize_all_techweb_nodes(clearall = FALSE)
if(islist(techweb_nodes) && clearall)
QDEL_LIST(techweb_nodes)
if(islist(techweb_nodes_starting && clearall))
techweb_nodes_starting.Cut()
var/list/returned = list()
for(var/path in subtypesof(/datum/techweb_node))
var/datum/techweb_node/TN = path
if(isnull(initial(TN.id)))
continue
TN = new path
if(returned[initial(TN.id)])
stack_trace("WARNING: Techweb node ID clash with ID [initial(TN.id)] detected! Path: [path]")
errored_datums[TN] = initial(TN.id)
continue
returned[initial(TN.id)] = TN
if(TN.starting_node)
techweb_nodes_starting[TN.id] = TRUE
for(var/id in techweb_nodes)
var/datum/techweb_node/TN = techweb_nodes[id]
TN.Initialize()
techweb_nodes = returned
if (!verify_techweb_nodes()) //Verify all nodes have ids and such.
stack_trace("Invalid techweb nodes detected")
calculate_techweb_nodes()
calculate_techweb_boost_list()
if (!verify_techweb_nodes()) //Verify nodes and designs have been crosslinked properly.
CRASH("Invalid techweb nodes detected")
/datum/controller/subsystem/research/proc/initialize_all_techweb_designs(clearall = FALSE)
if(islist(techweb_designs) && clearall)
QDEL_LIST(techweb_designs)
var/list/returned = list()
for(var/path in subtypesof(/datum/design))
var/datum/design/DN = path
if(isnull(initial(DN.id)))
stack_trace("WARNING: Design with null ID detected. Build path: [initial(DN.build_path)]")
continue
else if(initial(DN.id) == DESIGN_ID_IGNORE)
continue
DN = new path
if(returned[initial(DN.id)])
stack_trace("WARNING: Design ID clash with ID [initial(DN.id)] detected! Path: [path]")
errored_datums[DN] = initial(DN.id)
continue
returned[initial(DN.id)] = DN
techweb_designs = returned
verify_techweb_designs()
/datum/controller/subsystem/research/proc/verify_techweb_nodes()
. = TRUE
for(var/n in techweb_nodes)
var/datum/techweb_node/N = techweb_nodes[n]
if(!istype(N))
WARNING("Invalid research node with ID [n] detected and removed.")
techweb_nodes -= n
research_node_id_error(n)
. = FALSE
for(var/p in N.prereq_ids)
var/datum/techweb_node/P = techweb_nodes[p]
if(!istype(P))
WARNING("Invalid research prerequisite node with ID [p] detected in node [N.display_name]\[[N.id]\] removed.")
N.prereq_ids -= p
research_node_id_error(p)
. = FALSE
for(var/d in N.design_ids)
var/datum/design/D = techweb_designs[d]
if(!istype(D))
WARNING("Invalid research design with ID [d] detected in node [N.display_name]\[[N.id]\] removed.")
N.design_ids -= d
design_id_error(d)
. = FALSE
for(var/u in N.unlock_ids)
var/datum/techweb_node/U = techweb_nodes[u]
if(!istype(U))
WARNING("Invalid research unlock node with ID [u] detected in node [N.display_name]\[[N.id]\] removed.")
N.unlock_ids -= u
research_node_id_error(u)
. = FALSE
for(var/p in N.boost_item_paths)
if(!ispath(p))
N.boost_item_paths -= p
WARNING("[p] is not a valid path.")
node_boost_error(N.id, "[p] is not a valid path.")
. = FALSE
var/list/points = N.boost_item_paths[p]
if(islist(points))
for(var/i in points)
if(!isnum(points[i]))
WARNING("[points[i]] is not a valid number.")
node_boost_error(N.id, "[points[i]] is not a valid number.")
. = FALSE
else if(!point_types[i])
WARNING("[i] is not a valid point type.")
node_boost_error(N.id, "[i] is not a valid point type.")
. = FALSE
else if(!isnull(points))
N.boost_item_paths -= p
node_boost_error(N.id, "No valid list.")
WARNING("No valid list.")
. = FALSE
CHECK_TICK
/datum/controller/subsystem/research/proc/verify_techweb_designs()
for(var/d in techweb_designs)
var/datum/design/D = techweb_designs[d]
if(!istype(D))
stack_trace("WARNING: Invalid research design with ID [d] detected and removed.")
techweb_designs -= d
CHECK_TICK
/datum/controller/subsystem/research/proc/research_node_id_error(id)
if(invalid_node_ids[id])
invalid_node_ids[id]++
else
invalid_node_ids[id] = 1
/datum/controller/subsystem/research/proc/design_id_error(id)
if(invalid_design_ids[id])
invalid_design_ids[id]++
else
invalid_design_ids[id] = 1
/datum/controller/subsystem/research/proc/calculate_techweb_nodes()
for(var/design_id in techweb_designs)
var/datum/design/D = techweb_designs[design_id]
D.unlocked_by.Cut()
for(var/node_id in techweb_nodes)
var/datum/techweb_node/node = techweb_nodes[node_id]
node.unlock_ids = list()
for(var/i in node.design_ids)
var/datum/design/D = techweb_designs[i]
node.design_ids[i] = TRUE
D.unlocked_by += node.id
if(node.hidden)
techweb_nodes_hidden[node.id] = TRUE
CHECK_TICK
generate_techweb_unlock_linking()
/datum/controller/subsystem/research/proc/generate_techweb_unlock_linking()
for(var/node_id in techweb_nodes) //Clear all unlock links to avoid duplication.
var/datum/techweb_node/node = techweb_nodes[node_id]
node.unlock_ids = list()
for(var/node_id in techweb_nodes)
var/datum/techweb_node/node = techweb_nodes[node_id]
for(var/prereq_id in node.prereq_ids)
var/datum/techweb_node/prereq_node = techweb_node_by_id(prereq_id)
prereq_node.unlock_ids[node.id] = node
/datum/controller/subsystem/research/proc/calculate_techweb_boost_list(clearall = FALSE)
if(clearall)
techweb_boost_items = list()
for(var/node_id in techweb_nodes)
var/datum/techweb_node/node = techweb_nodes[node_id]
for(var/path in node.boost_item_paths)
if(!ispath(path))
continue
if(length(techweb_boost_items[path]))
techweb_boost_items[path][node.id] = node.boost_item_paths[path]
else
techweb_boost_items[path] = list(node.id = node.boost_item_paths[path])
CHECK_TICK
+8
View File
@@ -638,3 +638,11 @@ SUBSYSTEM_DEF(shuttle)
C.update_hidden_docking_ports(remove_images, add_images)
QDEL_LIST(remove_images)
/datum/controller/subsystem/shuttle/proc/autoEnd() //CIT CHANGE - allows shift to end after 2 hours have passed.
if((world.realtime - SSshuttle.realtimeofstart) > auto_call && EMERGENCY_IDLE_OR_RECALLED) //2 hours
SSshuttle.emergency.request(silent = TRUE)
priority_announce("The shift has come to an end and the shuttle called. [seclevel2num(get_security_level()) == SEC_LEVEL_RED ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [emergency.timeLeft(600)] minutes.", null, "shuttlecalled", "Priority")
log_game("Round time limit reached. Shuttle has been auto-called.")
message_admins("Round time limit reached. Shuttle called.")
emergencyNoRecall = TRUE
+5
View File
@@ -147,6 +147,11 @@ SUBSYSTEM_DEF(throwing)
if (callback)
callback.Invoke()
if(!thrownthing.zfalling) // I don't think you can zfall while thrown but hey, just in case.
var/turf/T = get_turf(thrownthing)
if(T && thrownthing.has_gravity(T))
T.zFall(thrownthing)
qdel(src)
/datum/thrownthing/proc/hit_atom(atom/A)
+1 -1
View File
@@ -40,7 +40,7 @@ SUBSYSTEM_DEF(traumas)
"cats" = strings(PHOBIA_FILE, "cats"),
"syndicate"= strings(PHOBIA_FILE, "syndicate"),
"eye" = strings(PHOBIA_FILE, "eye")
)
)
phobia_mobs = list("spiders" = typecacheof(list(/mob/living/simple_animal/hostile/poison/giant_spider)),
"security" = typecacheof(list(/mob/living/simple_animal/bot/secbot, /mob/living/simple_animal/bot/ed209)),
+7 -7
View File
@@ -74,10 +74,10 @@ SUBSYSTEM_DEF(weather)
next_hit_by_zlevel["[z]"] = null
/datum/controller/subsystem/weather/proc/get_weather(z, area/active_area)
var/datum/weather/A
for(var/V in processing)
var/datum/weather/W = V
if((z in W.impacted_z_levels) && W.area_type == active_area.type)
A = W
break
return A
var/datum/weather/A
for(var/V in processing)
var/datum/weather/W = V
if((z in W.impacted_z_levels) && W.area_type == active_area.type)
A = W
break
return A