Merge branch 'master' into abductor-update
This commit is contained in:
@@ -34,7 +34,7 @@
|
||||
if(_directory)
|
||||
directory = _directory
|
||||
if(entries)
|
||||
CRASH("[THIS_PROC_TYPE_WEIRD] called more than once!")
|
||||
CRASH("/datum/controller/configuration/Load() called more than once!")
|
||||
InitEntries()
|
||||
LoadModes()
|
||||
if(fexists("[directory]/config.txt") && LoadEntries("config.txt") <= 1)
|
||||
|
||||
@@ -139,6 +139,14 @@
|
||||
min_val = 0
|
||||
max_val = 1
|
||||
|
||||
/datum/config_entry/number/suicide_reenter_round_timer
|
||||
config_entry_value = 30
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/roundstart_suicide_time_limit
|
||||
config_entry_value = 30
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/shuttle_refuel_delay
|
||||
config_entry_value = 12000
|
||||
min_val = 0
|
||||
|
||||
@@ -141,6 +141,11 @@
|
||||
/datum/config_entry/flag/load_legacy_ranks_only //Loads admin ranks only from legacy admin_ranks.txt, while enabled ranks are mirrored to the database
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/flag/mentors_mobname_only
|
||||
|
||||
/datum/config_entry/flag/mentor_legacy_system //Defines whether the server uses the legacy mentor system with mentors.txt or the SQL system
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/string/hostedby
|
||||
|
||||
/datum/config_entry/flag/norespawn
|
||||
|
||||
@@ -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
|
||||
@@ -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//
|
||||
|
||||
@@ -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
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)),
|
||||
@@ -166,7 +166,7 @@ SUBSYSTEM_DEF(traumas)
|
||||
|
||||
"syndicate" = typecacheof(list(/obj/item/stack/tile/mineral/plastitanium, /obj/machinery/computer/shuttle/syndicate, /obj/machinery/computer/shuttle/syndicate/recall, /obj/machinery/computer/shuttle/syndicate/drop_pod, /obj/machinery/computer/camera_advanced/shuttle_docker/syndicate, /obj/machinery/recharge_station,
|
||||
/obj/machinery/porta_turret/syndicate, /obj/structure/closet/syndicate, /obj/machinery/suit_storage_unit/syndicate, /obj/item/clothing/under/syndicate, /obj/item/folder/syndicate, /obj/item/documents/syndicate, /obj/item/clothing/glasses/phantomthief/syndicate, /obj/item/antag_spawner/nuke_ops, /obj/item/storage/box/syndicate,
|
||||
/obj/structure/fluff/empty_sleeper/syndicate, /obj/item/implant/radio/syndicate, /obj/item/clothing/head/helmet/space/syndicate, /obj/machinery/nuclearbomb/syndicate, /obj/item/grenade/syndieminibomb, /obj/item/storage/backpack/duffelbag/syndie, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver/syndie,
|
||||
/obj/structure/fluff/empty_sleeper/syndicate, /obj/item/implant/radio/syndicate, /obj/item/clothing/head/helmet/space/syndicate, /obj/machinery/nuclearbomb/syndicate, /obj/item/grenade/syndieminibomb, /obj/item/storage/backpack/duffelbag/syndie, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver,
|
||||
/obj/item/gun/ballistic/automatic/shotgun/bulldog, /obj/item/gun/ballistic/automatic/c20r, /obj/item/gun/ballistic/automatic/m90, /obj/item/gun/ballistic/automatic/l6_saw, /obj/item/storage/belt/grenade/full, /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate, /obj/item/gun/energy/kinetic_accelerator/crossbow,
|
||||
/obj/item/melee/transforming/energy/sword/saber, /obj/item/twohanded/dualsaber, /obj/item/melee/powerfist, /obj/item/storage/box/syndie_kit, /obj/item/grenade/spawnergrenade/manhacks, /obj/item/grenade/chem_grenade/bioterrorfoam, /obj/item/reagent_containers/spray/chemsprayer/bioterror, /obj/item/ammo_box/magazine/m10mm,
|
||||
/obj/item/ammo_box/magazine/pistolm9mm, /obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/m12g, /obj/item/ammo_box/magazine/mm195x129, /obj/item/antag_spawner/nuke_ops, /obj/mecha/combat/gygax/dark, /obj/mecha/combat/marauder/mauler, /obj/item/soap/syndie, /obj/item/gun/syringe/syndicate, /obj/item/cartridge/virus/syndicate,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user