Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into Ghommie-cit265
This commit is contained in:
@@ -211,3 +211,27 @@
|
||||
|
||||
/datum/config_entry/keyed_list/vv_edit_var(var_name, var_value)
|
||||
return var_name != "splitter" && ..()
|
||||
|
||||
//snowflake for donator things being on one line smh
|
||||
/datum/config_entry/multi_keyed_flag
|
||||
vv_VAS = FALSE
|
||||
abstract_type = /datum/config_entry/multi_keyed_flag
|
||||
config_entry_value = list()
|
||||
var/delimiter = "|"
|
||||
|
||||
/datum/config_entry/multi_keyed_flag/vv_edit_var(var_name, var_value)
|
||||
if(var_name == NAMEOF(src, delimiter))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/config_entry/multi_keyed_flag/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
str_val = trim(str_val)
|
||||
var/list/keys = splittext(str_val, delimiter)
|
||||
for(var/i in keys)
|
||||
config_entry_value[process_key(i)] = TRUE
|
||||
return length(keys)? TRUE : FALSE
|
||||
|
||||
/datum/config_entry/multi_keyed_flag/proc/process_key(key)
|
||||
return trim(key)
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
/datum/config_entry/keyed_list/donator_group
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_FLAG
|
||||
abstract_type = /datum/config_entry/keyed_list/donator_group
|
||||
/datum/config_entry/multi_keyed_flag/donator_group
|
||||
abstract_type = /datum/config_entry/multi_keyed_flag/donator_group
|
||||
|
||||
//If we're in the middle of a config load, only do the regeneration afterwards to prevent this from wasting a massive amount of CPU for list regenerations.
|
||||
/datum/config_entry/keyed_list/donator_group/ValidateAndSet(str_val, during_load)
|
||||
/datum/config_entry/multi_keyed_flag/donator_group/ValidateAndSet(str_val, during_load)
|
||||
. = ..()
|
||||
if(. && during_load)
|
||||
if(. && !during_load)
|
||||
regenerate_donator_grouping_list()
|
||||
|
||||
/datum/config_entry/keyed_list/donator_group/OnPostload()
|
||||
/datum/config_entry/multi_keyed_flag/donator_group/process_key(key)
|
||||
return ckey(key)
|
||||
|
||||
/datum/config_entry/multi_keyed_flag/donator_group/OnPostload()
|
||||
. = ..()
|
||||
regenerate_donator_grouping_list()
|
||||
|
||||
//This is kinda weird in that the config entries are defined here but all the handling/calculations are in __HELPERS/donator_groupings.dm
|
||||
|
||||
/datum/config_entry/keyed_list/donator_group/tier_1_donators
|
||||
/datum/config_entry/multi_keyed_flag/donator_group/tier_1_donators
|
||||
|
||||
/datum/config_entry/keyed_list/donator_group/tier_2_donators
|
||||
/datum/config_entry/multi_keyed_flag/donator_group/tier_2_donators
|
||||
|
||||
/datum/config_entry/keyed_list/donator_group/tier_3_donators
|
||||
/datum/config_entry/multi_keyed_flag/donator_group/tier_3_donators
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/datum/config_entry/flag/dynamic_voting
|
||||
|
||||
/datum/config_entry/number/dynamic_high_pop_limit
|
||||
config_entry_value = 55
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_pop_per_requirement
|
||||
config_entry_value = 6
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_midround_delay_min
|
||||
config_entry_value = 15
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_midround_delay_max
|
||||
config_entry_value = 35
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_latejoin_delay_min
|
||||
config_entry_value = 5
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_latejoin_delay_max
|
||||
config_entry_value = 25
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_first_midround_delay_min
|
||||
config_entry_value = 20
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_first_midround_delay_max
|
||||
config_entry_value = 40
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_first_latejoin_delay_min
|
||||
config_entry_value = 10
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_first_latejoin_delay_max
|
||||
config_entry_value = 30
|
||||
min_val = 1
|
||||
|
||||
|
||||
/datum/config_entry/keyed_list/dynamic_cost
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_NUM
|
||||
|
||||
/datum/config_entry/keyed_list/dynamic_weight
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_NUM
|
||||
|
||||
/datum/config_entry/keyed_list/dynamic_requirements
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_NUM_LIST
|
||||
|
||||
/datum/config_entry/keyed_list/dynamic_high_population_requirement
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_NUM
|
||||
|
||||
/datum/config_entry/number_list/dynamic_second_rule_requirements
|
||||
|
||||
/datum/config_entry/number_list/dynamic_third_rule_requirements
|
||||
|
||||
/datum/config_entry/number/dynamic_second_rule_high_pop_requirement
|
||||
config_entry_value = 50
|
||||
|
||||
/datum/config_entry/number/dynamic_third_rule_high_pop_requirement
|
||||
config_entry_value = 70
|
||||
|
||||
/datum/config_entry/number_list/dynamic_hijack_requirements
|
||||
|
||||
/datum/config_entry/number/dynamic_hijack_high_population_requirement
|
||||
config_entry_value = 25
|
||||
|
||||
/datum/config_entry/number/dynamic_hijack_cost
|
||||
config_entry_value = 5
|
||||
|
||||
/datum/config_entry/number/dynamic_glorious_death_cost
|
||||
config_entry_value = 5
|
||||
|
||||
/datum/config_entry/number/dynamic_assassinate_cost
|
||||
config_entry_value = 2
|
||||
|
||||
/datum/config_entry/number/dynamic_warops_requirement
|
||||
config_entry_value = 60
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/dynamic_warops_cost
|
||||
config_entry_value = 10
|
||||
min_val = 0
|
||||
@@ -379,43 +379,3 @@
|
||||
/datum/config_entry/number/auto_transfer_delay
|
||||
config_entry_value = 72000
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/dynamic_high_pop_limit
|
||||
config_entry_value = 55
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_pop_per_requirement
|
||||
config_entry_value = 6
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_midround_delay_min
|
||||
config_entry_value = 15
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_midround_delay_max
|
||||
config_entry_value = 35
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_latejoin_delay_min
|
||||
config_entry_value = 5
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/number/dynamic_latejoin_delay_max
|
||||
config_entry_value = 25
|
||||
min_val = 1
|
||||
|
||||
/datum/config_entry/keyed_list/dynamic_cost
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_NUM
|
||||
|
||||
/datum/config_entry/keyed_list/dynamic_weight
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_NUM
|
||||
|
||||
/datum/config_entry/keyed_list/dynamic_requirements
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_NUM_LIST
|
||||
|
||||
/datum/config_entry/keyed_list/dynamic_high_population_requirement
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_NUM
|
||||
|
||||
@@ -29,6 +29,7 @@ SUBSYSTEM_DEF(chat)
|
||||
target = GLOB.clients
|
||||
|
||||
//Some macros remain in the string even after parsing and fuck up the eventual output
|
||||
var/original_message = message
|
||||
message = replacetext(message, "\improper", "")
|
||||
message = replacetext(message, "\proper", "")
|
||||
if(handle_whitespace)
|
||||
@@ -45,6 +46,12 @@ SUBSYSTEM_DEF(chat)
|
||||
for(var/I in target)
|
||||
var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible
|
||||
|
||||
if(!C)
|
||||
return
|
||||
|
||||
//Send it to the old style output window.
|
||||
SEND_TEXT(C, original_message)
|
||||
|
||||
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
|
||||
continue
|
||||
|
||||
@@ -57,6 +64,12 @@ SUBSYSTEM_DEF(chat)
|
||||
else
|
||||
var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible
|
||||
|
||||
if(!C)
|
||||
return
|
||||
|
||||
//Send it to the old style output window.
|
||||
SEND_TEXT(C, original_message)
|
||||
|
||||
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
|
||||
return
|
||||
|
||||
|
||||
@@ -1,6 +1,27 @@
|
||||
SUBSYSTEM_DEF(dcs)
|
||||
PROCESSING_SUBSYSTEM_DEF(dcs)
|
||||
name = "Datum Component System"
|
||||
flags = SS_NO_INIT | SS_NO_FIRE
|
||||
flags = SS_NO_INIT
|
||||
var/list/elements_by_type = list()
|
||||
|
||||
/datum/controller/subsystem/dcs/Recover()
|
||||
/datum/controller/subsystem/processing/dcs/Recover()
|
||||
comp_lookup = SSdcs.comp_lookup
|
||||
|
||||
/datum/controller/subsystem/processing/dcs/proc/GetElement(datum/element/eletype, ...)
|
||||
var/element_id = eletype
|
||||
|
||||
if(initial(eletype.element_flags) & ELEMENT_BESPOKE)
|
||||
var/list/fullid = list("[eletype]")
|
||||
for(var/i in initial(eletype.id_arg_index) to length(args))
|
||||
var/argument = args[i]
|
||||
if(istext(argument) || isnum(argument))
|
||||
fullid += "[argument]"
|
||||
else
|
||||
fullid += "[REF(argument)]"
|
||||
element_id = fullid.Join("&")
|
||||
|
||||
. = elements_by_type[element_id]
|
||||
if(.)
|
||||
return
|
||||
if(!ispath(eletype, /datum/element))
|
||||
CRASH("Attempted to instantiate [eletype] as a /datum/element")
|
||||
. = elements_by_type[element_id] = new eletype
|
||||
@@ -98,7 +98,7 @@ SUBSYSTEM_DEF(garbage)
|
||||
state = SS_RUNNING
|
||||
break
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/controller/subsystem/garbage/proc/HandleQueue(level = GC_QUEUE_CHECK)
|
||||
@@ -266,8 +266,8 @@ SUBSYSTEM_DEF(garbage)
|
||||
D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
|
||||
var/start_time = world.time
|
||||
var/start_tick = world.tick_usage
|
||||
SEND_SIGNAL(D, COMSIG_PARENT_QDELETING, force) // Let the (remaining) components know about the result of Destroy
|
||||
var/hint = D.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up.
|
||||
SEND_SIGNAL(D, COMSIG_PARENT_QDELETED, force, hint) // Let the (remaining) components know about the result of Destroy
|
||||
if(world.time != start_time)
|
||||
I.slept_destroy++
|
||||
else
|
||||
|
||||
@@ -444,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(reservation_ready["[z]"] && !clearing_reserved_turfs)
|
||||
UNTIL((!z || reservation_ready["[z]"]) && !clearing_reserved_turfs)
|
||||
var/datum/turf_reservation/reserve = new type
|
||||
if(turf_type_override)
|
||||
reserve.turf_type = turf_type_override
|
||||
|
||||
@@ -12,6 +12,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/list/obj/structure/chisel_message/chisel_messages = list()
|
||||
var/list/saved_messages = list()
|
||||
var/list/saved_modes = list(1,2,3)
|
||||
var/list/saved_threat_levels = list(1,1,1)
|
||||
var/list/saved_maps
|
||||
var/list/saved_trophies = list()
|
||||
var/list/spawned_objects = list()
|
||||
@@ -27,6 +28,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
LoadChiselMessages()
|
||||
LoadTrophies()
|
||||
LoadRecentModes()
|
||||
LoadRecentThreats()
|
||||
LoadRecentMaps()
|
||||
LoadPhotoPersistence()
|
||||
if(CONFIG_GET(flag/use_antag_rep))
|
||||
@@ -166,6 +168,15 @@ SUBSYSTEM_DEF(persistence)
|
||||
return
|
||||
saved_modes = json["data"]
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadRecentThreats()
|
||||
var/json_file = file("data/RecentThreatLevels.json")
|
||||
if(!fexists(json_file))
|
||||
return
|
||||
var/list/json = json_decode(file2text(json_file))
|
||||
if(!json)
|
||||
return
|
||||
saved_threat_levels = json["data"]
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
|
||||
var/json_file = file("data/RecentMaps.json")
|
||||
if(!fexists(json_file))
|
||||
@@ -216,6 +227,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
CollectSecretSatchels()
|
||||
CollectTrophies()
|
||||
CollectRoundtype()
|
||||
CollectThreatLevel()
|
||||
RecordMaps()
|
||||
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
|
||||
if(CONFIG_GET(flag/use_antag_rep))
|
||||
@@ -372,6 +384,18 @@ SUBSYSTEM_DEF(persistence)
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/CollectThreatLevel()
|
||||
if(istype(SSticker.mode, /datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
saved_threat_levels[3] = saved_threat_levels[2]
|
||||
saved_threat_levels[2] = saved_threat_levels [1]
|
||||
saved_threat_levels[1] = mode.threat_level
|
||||
var/json_file = file("data/RecentThreatLevels.json")
|
||||
var/list/file_data = list()
|
||||
file_data["data"] = saved_threat_levels
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/RecordMaps()
|
||||
saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]")
|
||||
var/json_file = file("data/RecentMaps.json")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -479,7 +479,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
if(SSticker.timeLeft < 900)
|
||||
SSticker.timeLeft = 900
|
||||
SSticker.modevoted = TRUE
|
||||
SSvote.initiate_vote("roundtype","server",TRUE)
|
||||
var/dynamic = CONFIG_GET(flag/dynamic_voting)
|
||||
SSvote.initiate_vote(dynamic ? "dynamic" : "roundtype","server",TRUE)
|
||||
|
||||
/datum/controller/subsystem/ticker/Recover()
|
||||
current_state = SSticker.current_state
|
||||
|
||||
@@ -87,7 +87,7 @@ SUBSYSTEM_DEF(traumas)
|
||||
"skeletons" = typecacheof(list(/obj/item/organ/tongue/bone, /obj/item/clothing/suit/armor/bone, /obj/item/stack/sheet/bone,
|
||||
/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton,
|
||||
/obj/effect/decal/remains/human)),
|
||||
"conspiracies" = typecacheof(list(/obj/item/clothing/under/rank/captain, /obj/item/clothing/under/rank/head_of_security,
|
||||
"conspiracies" = typecacheof(list(/obj/item/clothing/under/rank/captain, /obj/item/clothing/under/rank/head_of_security,
|
||||
/obj/item/clothing/under/rank/chief_engineer, /obj/item/clothing/under/rank/chief_medical_officer,
|
||||
/obj/item/clothing/under/rank/head_of_personnel, /obj/item/clothing/under/rank/research_director,
|
||||
/obj/item/clothing/under/rank/head_of_security/grey, /obj/item/clothing/under/rank/head_of_security/alt,
|
||||
|
||||
@@ -29,8 +29,8 @@ SUBSYSTEM_DEF(vis_overlays)
|
||||
return
|
||||
|
||||
//the "thing" var can be anything with vis_contents which includes images
|
||||
/datum/controller/subsystem/vis_overlays/proc/add_vis_overlay(atom/movable/thing, icon, iconstate, layer, plane, dir, alpha=255)
|
||||
. = "[icon]|[iconstate]|[layer]|[plane]|[dir]|[alpha]"
|
||||
/datum/controller/subsystem/vis_overlays/proc/add_vis_overlay(atom/movable/thing, icon, iconstate, layer, plane, dir, alpha = 255, add_appearance_flags = NONE)
|
||||
. = "[icon]|[iconstate]|[layer]|[plane]|[dir]|[alpha]|[add_appearance_flags]"
|
||||
var/obj/effect/overlay/vis/overlay = vis_overlay_cache[.]
|
||||
if(!overlay)
|
||||
overlay = new
|
||||
@@ -40,6 +40,7 @@ SUBSYSTEM_DEF(vis_overlays)
|
||||
overlay.plane = plane
|
||||
overlay.dir = dir
|
||||
overlay.alpha = alpha
|
||||
overlay.appearance_flags |= add_appearance_flags
|
||||
vis_overlay_cache[.] = overlay
|
||||
else
|
||||
overlay.unused = 0
|
||||
@@ -64,10 +65,12 @@ SUBSYSTEM_DEF(vis_overlays)
|
||||
UnregisterSignal(thing, COMSIG_ATOM_DIR_CHANGE)
|
||||
|
||||
/datum/controller/subsystem/vis_overlays/proc/rotate_vis_overlay(atom/thing, old_dir, new_dir)
|
||||
if(old_dir == new_dir)
|
||||
return
|
||||
var/rotation = dir2angle(old_dir) - dir2angle(new_dir)
|
||||
var/list/overlays_to_remove = list()
|
||||
for(var/i in thing.managed_vis_overlays)
|
||||
var/obj/effect/overlay/vis/overlay = i
|
||||
add_vis_overlay(thing, overlay.icon, overlay.icon_state, overlay.layer, overlay.plane, turn(overlay.dir, rotation))
|
||||
add_vis_overlay(thing, overlay.icon, overlay.icon_state, overlay.layer, overlay.plane, turn(overlay.dir, rotation), overlay.alpha, overlay.appearance_flags)
|
||||
overlays_to_remove += overlay
|
||||
remove_vis_overlay(thing, overlays_to_remove)
|
||||
|
||||
@@ -87,7 +87,7 @@ SUBSYSTEM_DEF(vote)
|
||||
/datum/controller/subsystem/vote/proc/announce_result()
|
||||
var/list/winners = get_result()
|
||||
var/text
|
||||
var/was_roundtype_vote = mode == "roundtype"
|
||||
var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic"
|
||||
if(winners.len > 0)
|
||||
if(question)
|
||||
text += "<b>[question]</b>"
|
||||
@@ -124,6 +124,9 @@ SUBSYSTEM_DEF(vote)
|
||||
message_admins(admintext)
|
||||
return .
|
||||
|
||||
#define PEACE "calm"
|
||||
#define CHAOS "chaotic"
|
||||
|
||||
/datum/controller/subsystem/vote/proc/result()
|
||||
. = announce_result()
|
||||
var/restart = 0
|
||||
@@ -146,6 +149,36 @@ SUBSYSTEM_DEF(vote)
|
||||
restart = 1
|
||||
else
|
||||
GLOB.master_mode = .
|
||||
if("dynamic")
|
||||
if(SSticker.current_state > GAME_STATE_PREGAME)//Don't change the mode if the round already started.
|
||||
return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.")
|
||||
GLOB.master_mode = "dynamic"
|
||||
if("extended" in choices)
|
||||
if(. == "extended")
|
||||
GLOB.dynamic_forced_extended = TRUE // we still do the rest of the stuff
|
||||
choices[PEACE] += choices["extended"]
|
||||
var/mean = 0
|
||||
var/voters = 0
|
||||
for(var/client/c in GLOB.clients)
|
||||
var/vote = c.prefs.preferred_chaos
|
||||
if(vote)
|
||||
voters += 1
|
||||
switch(vote)
|
||||
if(CHAOS_NONE)
|
||||
mean -= 0.1
|
||||
if(CHAOS_LOW)
|
||||
mean -= 0.05
|
||||
if(CHAOS_HIGH)
|
||||
mean += 0.05
|
||||
if(CHAOS_MAX)
|
||||
mean += 0.1
|
||||
mean/=voters
|
||||
if(voted.len != 0)
|
||||
mean += (choices[PEACE]*-1+choices[CHAOS])/voted.len
|
||||
GLOB.dynamic_curve_centre = mean*20
|
||||
GLOB.dynamic_curve_width = CLAMP(2-abs(mean*5),0.5,4)
|
||||
to_chat(world,"<span class='boldannounce'>Dynamic curve centre set to [GLOB.dynamic_curve_centre] and width set to [GLOB.dynamic_curve_width].</span>")
|
||||
log_admin("Dynamic curve centre set to [GLOB.dynamic_curve_centre] and width set to [GLOB.dynamic_curve_width]")
|
||||
if("map")
|
||||
var/datum/map_config/VM = config.maplist[.]
|
||||
message_admins("The map has been voted for and will change to: [VM.map_name]")
|
||||
@@ -223,6 +256,12 @@ SUBSYSTEM_DEF(vote)
|
||||
choices |= M
|
||||
if("roundtype") //CIT CHANGE - adds the roundstart secret/extended vote
|
||||
choices.Add("secret", "extended")
|
||||
if("dynamic")
|
||||
var/saved_threats = SSpersistence.saved_threat_levels
|
||||
if((saved_threats[1]+saved_threats[2]+saved_threats[3])>150)
|
||||
choices.Add("extended",PEACE,CHAOS)
|
||||
else
|
||||
choices.Add(PEACE,CHAOS)
|
||||
if("custom")
|
||||
question = stripped_input(usr,"What is the vote for?")
|
||||
if(!question)
|
||||
@@ -379,4 +418,7 @@ SUBSYSTEM_DEF(vote)
|
||||
else if(owner.ckey)
|
||||
var/datum/player_details/P = GLOB.player_details[owner.ckey]
|
||||
if(P)
|
||||
P.player_actions -= src
|
||||
P.player_actions -= src
|
||||
|
||||
#undef PEACE
|
||||
#undef CHAOS
|
||||
|
||||
Reference in New Issue
Block a user