From ebac066b2f003c0e37961db1a5226384cf910c4e Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 25 Feb 2020 16:10:23 -0800 Subject: [PATCH 01/61] lets add traitor classes --- code/datums/mind.dm | 14 +- .../modules/antagonists/traitor/classes/ai.dm | 70 ++++++++++ .../antagonists/traitor/classes/gorlex.dm | 25 ++++ .../antagonists/traitor/classes/human.dm | 131 ++++++++++++++++++ .../traitor/classes/traitor_class.dm | 35 +++++ .../antagonists/traitor/datum_traitor.dm | 90 +++++------- strings/flavor_objectives/ninja_helping.txt | 1 - strings/flavor_objectives/traitor.txt | 1 - 8 files changed, 306 insertions(+), 61 deletions(-) create mode 100644 code/modules/antagonists/traitor/classes/ai.dm create mode 100644 code/modules/antagonists/traitor/classes/gorlex.dm create mode 100644 code/modules/antagonists/traitor/classes/human.dm create mode 100644 code/modules/antagonists/traitor/classes/traitor_class.dm diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 61d467a20d..5cde9c5115 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -257,9 +257,11 @@ remove_rev() SSticker.mode.update_cult_icons_removed(src) -/datum/mind/proc/equip_traitor(employer = "The Syndicate", silent = FALSE, datum/antagonist/uplink_owner) +/datum/mind/proc/equip_traitor(traitor_class, silent = FALSE, datum/antagonist/uplink_owner) if(!current) return + if(!traitor_class) + traitor_class = GLOB.traitor_classes[BASIC_TRAITOR] var/mob/living/carbon/human/traitor_mob = current if (!istype(traitor_mob)) return @@ -307,21 +309,21 @@ if (!uplink_loc) if(!silent) - to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.") + to_chat(traitor_mob, "Unfortunately, [traitor_class.employer] wasn't able to get you an Uplink.") . = 0 else . = uplink_loc - var/datum/component/uplink/U = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key) + var/datum/component/uplink/U = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key,traitor_class) if(!U) CRASH("Uplink creation failed.") U.setup_unlock_code() if(!silent) if(uplink_loc == R) - to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(U.unlock_code)] to unlock its hidden features.") + to_chat(traitor_mob, "[traitor_class.employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(U.unlock_code)] to unlock its hidden features.") else if(uplink_loc == PDA) - to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[U.unlock_code]\" into the ringtone select to unlock its hidden features.") + to_chat(traitor_mob, "[traitor_class.employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[U.unlock_code]\" into the ringtone select to unlock its hidden features.") else if(uplink_loc == P) - to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [U.unlock_code] from its starting position to unlock its hidden features.") + to_chat(traitor_mob, "[traitor_class.employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [U.unlock_code] from its starting position to unlock its hidden features.") if(uplink_owner) uplink_owner.antag_memory += U.unlock_note + "
" diff --git a/code/modules/antagonists/traitor/classes/ai.dm b/code/modules/antagonists/traitor/classes/ai.dm new file mode 100644 index 0000000000..60d7dcdeba --- /dev/null +++ b/code/modules/antagonists/traitor/classes/ai.dm @@ -0,0 +1,70 @@ +#define TRAITOR_AI /datum/traitor_class/ai + +/datum/traitor_class/ai // this one is special, so has no weight + name = "Malfunctioning AI" + +/datum/traitor_class/ai/forge_objectives(/datum/antagonist/traitor/T) + var/objective_count = 0 + + if(prob(30)) + objective_count += forge_single_objective() + + for(var/i = objective_count, i < CONFIG_GET(number/traitor_objectives_amount), i++) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = owner + kill_objective.find_target() + T.add_objective(kill_objective) + + var/datum/objective/survive/exist/exist_objective = new + exist_objective.owner = owner + T.add_objective(exist_objective) + +/datum/traitor_class/ai/forge_single_objective(/datum/antagonist/traitor/T) + .=1 + var/special_pick = rand(1,4) + switch(special_pick) + if(1) + var/datum/objective/block/block_objective = new + block_objective.owner = owner + T.add_objective(block_objective) + if(2) + var/datum/objective/purge/purge_objective = new + purge_objective.owner = owner + T.add_objective(purge_objective) + if(3) + var/datum/objective/robot_army/robot_objective = new + robot_objective.owner = owner + T.add_objective(robot_objective) + if(4) //Protect and strand a target + var/datum/objective/protect/yandere_one = new + yandere_one.owner = owner + T.add_objective(yandere_one) + yandere_one.find_target() + var/datum/objective/maroon/yandere_two = new + yandere_two.owner = owner + yandere_two.target = yandere_one.target + yandere_two.update_explanation_text() // normally called in find_target() + T.add_objective(yandere_two) + .=2 + +/datum/traitor_class/ai/on_removal(/datum/antagonist/traitor/T) + var/mob/living/silicon/ai/A = T.owner.current + A.set_zeroth_law("") + A.verbs -= /mob/living/silicon/ai/proc/choose_modules + A.malf_picker.remove_malf_verbs(A) + qdel(A.malf_picker) + + +/datum/traitor_class/ai/apply_innate_effects(mob/living/M) + var/mob/living/silicon/ai/A = M + A.hack_software = TRUE + +/datum/traitor_class/ai/remove_innate_effects(mob/living/M) + var/mob/living/silicon/ai/A = M + A.hack_software = FALSE + +/datum/traitor_class/ai/finalize_objectives(/datum/antagonist/traitor/T) + T.add_law_zero() + T.owner.current.playsound_local(get_turf(T.owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE) + T.owner.current.grant_language(/datum/language/codespeak) + return FALSE diff --git a/code/modules/antagonists/traitor/classes/gorlex.dm b/code/modules/antagonists/traitor/classes/gorlex.dm new file mode 100644 index 0000000000..1089d7ef50 --- /dev/null +++ b/code/modules/antagonists/traitor/classes/gorlex.dm @@ -0,0 +1,25 @@ +/datum/traitor_class/human/gorlex + name = "Gorlex Marauders" + employer = "Gorlex Marauders" + weight = 2 + chaos = 20 + TC = 30 + +/datum/traitor_class/proc/forge_objectives(/datum/antagonist/traitor/T) + // Like the old forge_human_objectives. Makes all the objectives for this traitor class. + +/datum/traitor_class/proc/forge_single_objective(/datum/antagonist/traitor/T) + // As forge_single_objective. + +/datum/traitor_class/proc/on_removal(/datum/antagonist/traitor/T) + // What this does to the antag datum on removal. Called before proper removal, obviously. + +/datum/traitor_class/proc/apply_innate_effects(mob/living/M) + // What innate effects it should have. See: AI. + +/datum/traitor_class/proc/remove_innate_effects(mob/living/M) + // Cleaning up the innate effects. + +/datum/traitor_class/proc/finalize_traitor(/datum/antagonist/traitor/T) + // Finalization. Return TRUE if should play standard traitor sound/equip, return FALSE if both are special case + return TRUE diff --git a/code/modules/antagonists/traitor/classes/human.dm b/code/modules/antagonists/traitor/classes/human.dm new file mode 100644 index 0000000000..1f7b64d4f5 --- /dev/null +++ b/code/modules/antagonists/traitor/classes/human.dm @@ -0,0 +1,131 @@ +#define BASIC_TRAITOR /datum/traitor_class/human + +/datum/traitor_class/human + name = "Traitor" + chaos = 1 + +/datum/traitor_class/human/forge_objectives(/datum/antagonist/traitor/T) + var/is_hijacker = FALSE + var/datum/game_mode/dynamic/mode + var/is_dynamic = FALSE + var/hijack_prob = 0 + if(istype(SSticker.mode,/datum/game_mode/dynamic)) + mode = SSticker.mode + is_dynamic = TRUE + if(mode.threat >= CONFIG_GET(number/dynamic_hijack_cost)) + hijack_prob = CLAMP(mode.threat_level-50,0,20) + if(GLOB.joined_player_list.len>=GLOB.dynamic_high_pop_limit) + is_hijacker = (prob(hijack_prob) && mode.threat_level > CONFIG_GET(number/dynamic_hijack_high_population_requirement)) + else + var/indice_pop = min(10,round(GLOB.joined_player_list.len/mode.pop_per_requirement)+1) + is_hijacker = (prob(hijack_prob) && (mode.threat_level >= CONFIG_GET(number_list/dynamic_hijack_requirements)[indice_pop])) + if(mode.storyteller.flags & NO_ASSASSIN) + is_hijacker = FALSE + else if (GLOB.joined_player_list.len >= 30) // Less murderboning on lowpop thanks + hijack_prob = 10 + is_hijacker = prob(10) + var/martyr_chance = prob(hijack_prob*2) + var/objective_count = is_hijacker //Hijacking counts towards number of objectives + if(!SSticker.mode.exchange_blue && SSticker.mode.traitors.len >= 8) //Set up an exchange if there are enough traitors + if(!SSticker.mode.exchange_red) + SSticker.mode.exchange_red = T.owner + else + SSticker.mode.exchange_blue = T.owner + assign_exchange_role(SSticker.mode.exchange_red) + assign_exchange_role(SSticker.mode.exchange_blue) + objective_count += 1 //Exchange counts towards number of objectives + var/toa = CONFIG_GET(number/traitor_objectives_amount) + for(var/i = objective_count, i < toa, i++) + forge_single_objective(T) + + if(is_hijacker && objective_count <= toa) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount + if (!(locate(/datum/objective/hijack) in objectives)) + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = T.owner + T.add_objective(hijack_objective) + if(is_dynamic) + var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost) + mode.spend_threat(threat_spent) + mode.log_threat("[owner.name] spent [threat_spent] on hijack.") + return + + + var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead. + for(var/datum/objective/O in objectives) + if(!O.martyr_compatible) + martyr_compatibility = 0 + break + + if(martyr_compatibility && martyr_chance) + var/datum/objective/martyr/martyr_objective = new + martyr_objective.owner = T.owner + T.add_objective(martyr_objective) + if(is_dynamic) + var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost) + mode.spend_threat(threat_spent) + mode.log_threat("[owner.name] spent [threat_spent] on glorious death.") + return + + else + if(!(locate(/datum/objective/escape) in objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = owner + T.add_objective(escape_objective) + return + +/datum/traitor_class/human/forge_single_objective(/datum/antagonist/traitor/T) + .=1 + var/assassin_prob = 50 + var/is_dynamic = FALSE + var/datum/game_mode/dynamic/mode + if(istype(SSticker.mode,/datum/game_mode/dynamic)) + mode = SSticker.mode + is_dynamic = TRUE + assassin_prob = max(0,mode.threat_level-20) + if(prob(assassin_prob)) + if(is_dynamic) + var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost) + mode.spend_threat(threat_spent) + mode.log_threat("[T.owner.name] spent [threat_spent] on an assassination target.") + var/list/active_ais = active_ais() + if(active_ais.len && prob(100/GLOB.joined_player_list.len)) + var/datum/objective/destroy/destroy_objective = new + destroy_objective.owner = T.owner + destroy_objective.find_target() + T.add_objective(destroy_objective) + else if(prob(30) || (is_dynamic && (mode.storyteller.flags & NO_ASSASSIN))) + var/datum/objective/maroon/maroon_objective = new + maroon_objective.owner = T.owner + maroon_objective.find_target() + T.add_objective(maroon_objective) + else if(prob(max(0,assassin_prob-20))) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = T.owner + kill_objective.find_target() + T.add_objective(kill_objective) + else + var/datum/objective/assassinate/once/kill_objective = new + kill_objective.owner = T.owner + kill_objective.find_target() + T.add_objective(kill_objective) + else + if(prob(15) && !(locate(/datum/objective/download) in objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist"))) + var/datum/objective/download/download_objective = new + download_objective.owner = T.owner + download_objective.gen_amount_goal() + T.add_objective(download_objective) + else if(prob(40)) // cum. not counting download: 40%. + var/datum/objective/steal/steal_objective = new + steal_objective.owner = T.owner + steal_objective.find_target() + T.add_objective(steal_objective) + else if(prob(100/3)) // cum. not counting download: 20%. + var/datum/objective/sabotage/sabotage_objective = new + sabotage_objective.owner = T.owner + sabotage_objective.find_target() + T.add_objective(sabotage_objective) + else // cum. not counting download: 40% + var/datum/objective/flavor/traitor/flavor_objective = new + flavor_objective.owner = T.owner + flavor_objective.forge_objective() + T.add_objective(flavor_objective) diff --git a/code/modules/antagonists/traitor/classes/traitor_class.dm b/code/modules/antagonists/traitor/classes/traitor_class.dm new file mode 100644 index 0000000000..8107fa5af9 --- /dev/null +++ b/code/modules/antagonists/traitor/classes/traitor_class.dm @@ -0,0 +1,35 @@ +GLOBAL_LIST_EMPTY(traitor_classes) + +/datum/traitor_class + var/name = "Bad Coders Ltd." + var/employer = "The Syndicate" + var/weight = 0 + var/chaos = 0 + var/TC = 20 + +/datum/traitor_class/New() + ..() + if(src.type in traitor_classes) + qdel(src) + else + traitor_classes += src.type + traitor_classes[src.type] = src + +/datum/traitor_class/proc/forge_objectives(/datum/antagonist/traitor/T) + // Like the old forge_human_objectives. Makes all the objectives for this traitor class. + +/datum/traitor_class/proc/forge_single_objective(/datum/antagonist/traitor/T) + // As forge_single_objective. + +/datum/traitor_class/proc/on_removal(/datum/antagonist/traitor/T) + // What this does to the antag datum on removal. Called before proper removal, obviously. + +/datum/traitor_class/proc/apply_innate_effects(mob/living/M) + // What innate effects it should have. See: AI. + +/datum/traitor_class/proc/remove_innate_effects(mob/living/M) + // Cleaning up the innate effects. + +/datum/traitor_class/proc/finalize_traitor(/datum/antagonist/traitor/T) + // Finalization. Return TRUE if should play standard traitor sound/equip, return FALSE if both are special case + return TRUE diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 1c7ee48f71..da35d1ffdc 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -1,5 +1,4 @@ #define TRAITOR_HUMAN "human" -#define TRAITOR_AI "AI" /datum/antagonist/traitor name = "Traitor" @@ -12,21 +11,42 @@ var/give_objectives = TRUE var/should_give_codewords = TRUE var/should_equip = TRUE - var/traitor_kind = TRAITOR_HUMAN //Set on initial assignment + var/datum/traitor_class/traitor_kind = TRAITOR_HUMAN //Set on initial assignment can_hijack = HIJACK_HIJACKER +/datum/antagonist/traitor/New() + ..() + if(!GLOB.traitor_classes.len)//Only need to fill the list when it's needed. + for(var/I in subtypesof(/datum/traitor_class)) + new I + +/datum/antagonist/traitor/proc/set_traitor_kind(var/kind) + traitor_kind = traitor_classes[kind] + /datum/antagonist/traitor/on_gain() if(owner.current && isAI(owner.current)) - traitor_kind = TRAITOR_AI - + set_traitor_kind(TRAITOR_AI) + else + var/chaos_weight = 0 + if(istype(SSticker.mode,/datum/game_mode/dynamic)) + var/datum/game_mode/dynamic/mode = SSticker.mode + chaos_weight = (mode.threat - 50)/50 + var/list/weights = list() + for(var/C in traitor_classes) + var/datum/traitor_class/class = C + var/weight = class.weight/(1+NUM_E**(-chaos_weight*class.chaos)) // just a logistic function + weights[C] = weight + set_traitor_kind(pickweightAllowZero(weights)) + traitor_kind.weight /= 2 // less likely this round SSticker.mode.traitors += owner owner.special_role = special_role if(give_objectives) - forge_traitor_objectives() - finalize_traitor() + traitor_kind.forge_objectives(src) + traitor_kind.finalize_traitor(src) ..() /datum/antagonist/traitor/apply_innate_effects() + traitor_kind.apply_innate_effects(src) if(owner.assigned_role == "Clown") var/mob/living/carbon/human/traitor_mob = owner.current if(traitor_mob && istype(traitor_mob)) @@ -35,6 +55,7 @@ traitor_mob.dna.remove_mutation(CLOWNMUT) /datum/antagonist/traitor/remove_innate_effects() + traitor_kind.remove_innate_effects(src) if(owner.assigned_role == "Clown") var/mob/living/carbon/human/traitor_mob = owner.current if(traitor_mob && istype(traitor_mob)) @@ -42,12 +63,7 @@ /datum/antagonist/traitor/on_removal() //Remove malf powers. - if(traitor_kind == TRAITOR_AI && owner.current && isAI(owner.current)) - var/mob/living/silicon/ai/A = owner.current - A.set_zeroth_law("") - A.verbs -= /mob/living/silicon/ai/proc/choose_modules - A.malf_picker.remove_malf_verbs(A) - qdel(A.malf_picker) + traitor_kind.on_removal(src) SSticker.mode.traitors -= owner if(!silent && owner.current) to_chat(owner.current," You are no longer the [special_role]! ") @@ -67,6 +83,7 @@ objectives -= O /datum/antagonist/traitor/proc/forge_traitor_objectives() + traitor_kind.forge_objectives(src) switch(traitor_kind) if(TRAITOR_AI) forge_ai_objectives() @@ -142,30 +159,6 @@ add_objective(escape_objective) return -/datum/antagonist/traitor/proc/forge_ai_objectives() - var/objective_count = 0 - - if(prob(30)) - objective_count += forge_single_objective() - - for(var/i = objective_count, i < CONFIG_GET(number/traitor_objectives_amount), i++) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = owner - kill_objective.find_target() - add_objective(kill_objective) - - var/datum/objective/survive/exist/exist_objective = new - exist_objective.owner = owner - add_objective(exist_objective) - - -/datum/antagonist/traitor/proc/forge_single_objective() - switch(traitor_kind) - if(TRAITOR_AI) - return forge_single_AI_objective() - else - return forge_single_human_objective() - /datum/antagonist/traitor/proc/forge_single_human_objective() //Returns how many objectives are added .=1 var/assassin_prob = 50 @@ -268,32 +261,24 @@ set_antag_hud(owner.current, null) /datum/antagonist/traitor/proc/finalize_traitor() - switch(traitor_kind) - if(TRAITOR_AI) - add_law_zero() - owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE) - owner.current.grant_language(/datum/language/codespeak) - if(TRAITOR_HUMAN) - if(should_equip) - equip(silent) - owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE) + var/should_base_finalize = traitor_kind.finalize_traitor(src) + if(should_base_finalize) + if(should_equip) + equip(silent) + owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE) /datum/antagonist/traitor/apply_innate_effects(mob/living/mob_override) . = ..() update_traitor_icons_added() var/mob/M = mob_override || owner.current - if(isAI(M) && traitor_kind == TRAITOR_AI) - var/mob/living/silicon/ai/A = M - A.hack_software = TRUE + traitor_kind.apply_innate_effects(M) RegisterSignal(M, COMSIG_MOVABLE_HEAR, .proc/handle_hearing) /datum/antagonist/traitor/remove_innate_effects(mob/living/mob_override) . = ..() update_traitor_icons_removed() var/mob/M = mob_override || owner.current - if(isAI(M) && traitor_kind == TRAITOR_AI) - var/mob/living/silicon/ai/A = M - A.hack_software = FALSE + traitor_kind.remove_innate_effects(M) UnregisterSignal(M, COMSIG_MOVABLE_HEAR) /datum/antagonist/traitor/proc/give_codewords() @@ -324,8 +309,7 @@ killer.add_malf_picker() /datum/antagonist/traitor/proc/equip(var/silent = FALSE) - if(traitor_kind == TRAITOR_HUMAN) - owner.equip_traitor(employer, silent, src) + owner.equip_traitor(traitor_kind, silent, src) /datum/antagonist/traitor/proc/assign_exchange_role() //set faction diff --git a/strings/flavor_objectives/ninja_helping.txt b/strings/flavor_objectives/ninja_helping.txt index 1280939b5c..4cca9a2234 100644 --- a/strings/flavor_objectives/ninja_helping.txt +++ b/strings/flavor_objectives/ninja_helping.txt @@ -1,6 +1,5 @@ Nanotrasen want to make sure that their employees are on the up-and-up. Try to find any blackmail you can. Increase productivity however you can. -You are a security ninja. Answer to the Head of Security, and follow space law. You are a cargo ninja. Answer to the Quartermaster, and do what they say. Nanotrasen want you to ensure maximum morale. Protect the members of the crew who are on break. Ensure that all the paperwork is being done. \ No newline at end of file diff --git a/strings/flavor_objectives/traitor.txt b/strings/flavor_objectives/traitor.txt index 6d54c8ed9d..1a08b6cac1 100644 --- a/strings/flavor_objectives/traitor.txt +++ b/strings/flavor_objectives/traitor.txt @@ -2,7 +2,6 @@ The Gorlex Marauders want you to teach the heads of staff a lesson they will nev Show Nanotrasen the utility of a 40% oxygen atmosphere. Waffle Co. wants you To cause as much humorous terrorism against Nanotrasen as possible! How? We don’t care as long as it’s entertaining! Be as creative and exciting as possible when carrying out your dirty deeds. Have fun! Kill one of the station's beloved pets. Make a show of it, though you don't have to reveal yourself. -The Tiger Cooperative want you to get their illegal technology spread through the station. The Animal Rights Consortium needs you to save the innocent non-humanoid creatures aboard Citadel Station by any means necessary. Use your best judgement to decide whether an animal or xenobiological is abused, but if they are, ensure the abuser is punished. Avoid killing too many people if possible, and if you do harm any creatures, you will be terminated upon extraction. Donk Co. wants ransom money, and you are going to get it. Your goal is to kidnap and crewmember you can get your hands on and hold them hostage until you get something of significant value. Try to work out the best deal you can. Remember that Higher Value Targets are generally going to get a better deal so try to prioritize heads of staff if possible. We do not approve of mindless killing of Nanotrasen employees, so don’t do it. The Gorlex Marauders want you to steal as many shoes as possible. Lay broken glass everywhere. \ No newline at end of file From f344af633f69242a6e92b12aaeae2bfd66802d07 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 29 Feb 2020 23:29:24 -0800 Subject: [PATCH 02/61] finalized. --- code/__DEFINES/antagonists.dm | 3 + code/datums/components/uplink.dm | 8 +- code/datums/mind.dm | 4 +- .../traitor/IAA/internal_affairs.dm | 8 - .../modules/antagonists/traitor/classes/ai.dm | 24 ++- .../antagonists/traitor/classes/assassin.dm | 37 ++++ .../antagonists/traitor/classes/gimmick.dm | 12 ++ .../antagonists/traitor/classes/gorlex.dm | 25 --- .../antagonists/traitor/classes/hijack.dm | 15 ++ .../antagonists/traitor/classes/human.dm | 79 ++------ .../antagonists/traitor/classes/martyr.dm | 15 ++ .../antagonists/traitor/classes/subterfuge.dm | 40 ++++ .../traitor/classes/traitor_class.dm | 19 +- .../antagonists/traitor/datum_traitor.dm | 178 ++---------------- code/modules/uplink/uplink_items.dm | 5 +- tgstation.dme | 8 + 16 files changed, 192 insertions(+), 288 deletions(-) create mode 100644 code/modules/antagonists/traitor/classes/assassin.dm create mode 100644 code/modules/antagonists/traitor/classes/gimmick.dm delete mode 100644 code/modules/antagonists/traitor/classes/gorlex.dm create mode 100644 code/modules/antagonists/traitor/classes/hijack.dm create mode 100644 code/modules/antagonists/traitor/classes/martyr.dm create mode 100644 code/modules/antagonists/traitor/classes/subterfuge.dm diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index cabcc0a17d..9084e60ce2 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -1,3 +1,6 @@ +#define TRAITOR_HUMAN /datum/traitor_class/human +#define TRAITOR_AI /datum/traitor_class/ai + #define NUKE_RESULT_FLUKE 0 #define NUKE_RESULT_NUKE_WIN 1 #define NUKE_RESULT_CREW_WIN 2 diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index a8e03946b6..e73465d785 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -28,7 +28,7 @@ GLOBAL_LIST_EMPTY(uplinks) var/compact_mode = FALSE var/debug = FALSE -/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate) +/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate, datum/traitor_class/traitor_class) if(!isitem(parent)) return COMPONENT_INCOMPATIBLE @@ -47,7 +47,11 @@ GLOBAL_LIST_EMPTY(uplinks) RegisterSignal(parent, COMSIG_PEN_ROTATED, .proc/pen_rotation) GLOB.uplinks += src - uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted) + var/list/filters = list() + if(istype(traitor_class)) + filters = traitor_class.uplink_filters + starting_tc = traitor_class.TC + uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted, filters) if(_owner) owner = _owner diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 5cde9c5115..16870b3f75 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -257,11 +257,11 @@ remove_rev() SSticker.mode.update_cult_icons_removed(src) -/datum/mind/proc/equip_traitor(traitor_class, silent = FALSE, datum/antagonist/uplink_owner) +/datum/mind/proc/equip_traitor(datum/traitor_class/traitor_class, silent = FALSE, datum/antagonist/uplink_owner) if(!current) return if(!traitor_class) - traitor_class = GLOB.traitor_classes[BASIC_TRAITOR] + traitor_class = GLOB.traitor_classes[TRAITOR_HUMAN] var/mob/living/carbon/human/traitor_mob = current if (!istype(traitor_mob)) return diff --git a/code/modules/antagonists/traitor/IAA/internal_affairs.dm b/code/modules/antagonists/traitor/IAA/internal_affairs.dm index caf2f644df..f6ee056865 100644 --- a/code/modules/antagonists/traitor/IAA/internal_affairs.dm +++ b/code/modules/antagonists/traitor/IAA/internal_affairs.dm @@ -215,14 +215,6 @@ kill_objective.target = target_mind kill_objective.update_explanation_text() add_objective(kill_objective) - - //Optional traitor objective - if(prob(PROB_ACTUAL_TRAITOR)) - employer = "The Syndicate" - owner.special_role = TRAITOR_AGENT_ROLE - special_role = TRAITOR_AGENT_ROLE - syndicate = TRUE - forge_single_objective() return /datum/antagonist/traitor/internal_affairs/forge_traitor_objectives() diff --git a/code/modules/antagonists/traitor/classes/ai.dm b/code/modules/antagonists/traitor/classes/ai.dm index 60d7dcdeba..fac1efeb49 100644 --- a/code/modules/antagonists/traitor/classes/ai.dm +++ b/code/modules/antagonists/traitor/classes/ai.dm @@ -1,9 +1,7 @@ -#define TRAITOR_AI /datum/traitor_class/ai - /datum/traitor_class/ai // this one is special, so has no weight name = "Malfunctioning AI" -/datum/traitor_class/ai/forge_objectives(/datum/antagonist/traitor/T) +/datum/traitor_class/ai/forge_objectives(datum/antagonist/traitor/T) var/objective_count = 0 if(prob(30)) @@ -11,43 +9,43 @@ for(var/i = objective_count, i < CONFIG_GET(number/traitor_objectives_amount), i++) var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = owner + kill_objective.owner = T.owner kill_objective.find_target() T.add_objective(kill_objective) var/datum/objective/survive/exist/exist_objective = new - exist_objective.owner = owner + exist_objective.owner = T.owner T.add_objective(exist_objective) -/datum/traitor_class/ai/forge_single_objective(/datum/antagonist/traitor/T) +/datum/traitor_class/ai/forge_single_objective(datum/antagonist/traitor/T) .=1 var/special_pick = rand(1,4) switch(special_pick) if(1) var/datum/objective/block/block_objective = new - block_objective.owner = owner + block_objective.owner = T.owner T.add_objective(block_objective) if(2) var/datum/objective/purge/purge_objective = new - purge_objective.owner = owner + purge_objective.owner = T.owner T.add_objective(purge_objective) if(3) var/datum/objective/robot_army/robot_objective = new - robot_objective.owner = owner + robot_objective.owner = T.owner T.add_objective(robot_objective) if(4) //Protect and strand a target var/datum/objective/protect/yandere_one = new - yandere_one.owner = owner + yandere_one.owner = T.owner T.add_objective(yandere_one) yandere_one.find_target() var/datum/objective/maroon/yandere_two = new - yandere_two.owner = owner + yandere_two.owner = T.owner yandere_two.target = yandere_one.target yandere_two.update_explanation_text() // normally called in find_target() T.add_objective(yandere_two) .=2 -/datum/traitor_class/ai/on_removal(/datum/antagonist/traitor/T) +/datum/traitor_class/ai/on_removal(datum/antagonist/traitor/T) var/mob/living/silicon/ai/A = T.owner.current A.set_zeroth_law("") A.verbs -= /mob/living/silicon/ai/proc/choose_modules @@ -63,7 +61,7 @@ var/mob/living/silicon/ai/A = M A.hack_software = FALSE -/datum/traitor_class/ai/finalize_objectives(/datum/antagonist/traitor/T) +/datum/traitor_class/ai/finalize_traitor(datum/antagonist/traitor/T) T.add_law_zero() T.owner.current.playsound_local(get_turf(T.owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE) T.owner.current.grant_language(/datum/language/codespeak) diff --git a/code/modules/antagonists/traitor/classes/assassin.dm b/code/modules/antagonists/traitor/classes/assassin.dm new file mode 100644 index 0000000000..ca192aff5a --- /dev/null +++ b/code/modules/antagonists/traitor/classes/assassin.dm @@ -0,0 +1,37 @@ +/datum/traitor_class/human/assassin + name = "Donk Co Operative" + employer = "Donk Corporation" + weight = 4 + chaos = 1 + cost = 2 + +/datum/traitor_class/human/assassin/forge_single_objective(datum/antagonist/traitor/T) + .=1 + var/permakill_prob = 20 + var/is_dynamic = FALSE + var/datum/game_mode/dynamic/mode + if(istype(SSticker.mode,/datum/game_mode/dynamic)) + mode = SSticker.mode + is_dynamic = TRUE + permakill_prob = max(0,mode.threat_level-50) + var/list/active_ais = active_ais() + if(active_ais.len && prob(100/GLOB.joined_player_list.len)) + var/datum/objective/destroy/destroy_objective = new + destroy_objective.owner = T.owner + destroy_objective.find_target() + T.add_objective(destroy_objective) + else if(prob(30) || (is_dynamic && (mode.storyteller.flags & NO_ASSASSIN))) + var/datum/objective/maroon/maroon_objective = new + maroon_objective.owner = T.owner + maroon_objective.find_target() + T.add_objective(maroon_objective) + else if(prob(permakill_prob)) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = T.owner + kill_objective.find_target() + T.add_objective(kill_objective) + else + var/datum/objective/assassinate/once/kill_objective = new + kill_objective.owner = T.owner + kill_objective.find_target() + T.add_objective(kill_objective) diff --git a/code/modules/antagonists/traitor/classes/gimmick.dm b/code/modules/antagonists/traitor/classes/gimmick.dm new file mode 100644 index 0000000000..12f9674140 --- /dev/null +++ b/code/modules/antagonists/traitor/classes/gimmick.dm @@ -0,0 +1,12 @@ +/datum/traitor_class/human/gimmick + name = "Waffle Co Agent" + employer = "Waffle Company" + weight = 4 + chaos = 0 + +/datum/traitor_class/human/gimmick/forge_objectives(datum/antagonist/traitor/T) + var/datum/objective/escape/O = new + O.explanation_text = "You have no goals! Whatever you can do do antagonize Nanotrasen, do it! The gimmickier, the better! Make sure to escape alive, though!" + O.owner = T.owner + T.add_objective(O) + return diff --git a/code/modules/antagonists/traitor/classes/gorlex.dm b/code/modules/antagonists/traitor/classes/gorlex.dm deleted file mode 100644 index 1089d7ef50..0000000000 --- a/code/modules/antagonists/traitor/classes/gorlex.dm +++ /dev/null @@ -1,25 +0,0 @@ -/datum/traitor_class/human/gorlex - name = "Gorlex Marauders" - employer = "Gorlex Marauders" - weight = 2 - chaos = 20 - TC = 30 - -/datum/traitor_class/proc/forge_objectives(/datum/antagonist/traitor/T) - // Like the old forge_human_objectives. Makes all the objectives for this traitor class. - -/datum/traitor_class/proc/forge_single_objective(/datum/antagonist/traitor/T) - // As forge_single_objective. - -/datum/traitor_class/proc/on_removal(/datum/antagonist/traitor/T) - // What this does to the antag datum on removal. Called before proper removal, obviously. - -/datum/traitor_class/proc/apply_innate_effects(mob/living/M) - // What innate effects it should have. See: AI. - -/datum/traitor_class/proc/remove_innate_effects(mob/living/M) - // Cleaning up the innate effects. - -/datum/traitor_class/proc/finalize_traitor(/datum/antagonist/traitor/T) - // Finalization. Return TRUE if should play standard traitor sound/equip, return FALSE if both are special case - return TRUE diff --git a/code/modules/antagonists/traitor/classes/hijack.dm b/code/modules/antagonists/traitor/classes/hijack.dm new file mode 100644 index 0000000000..0ed716c3cd --- /dev/null +++ b/code/modules/antagonists/traitor/classes/hijack.dm @@ -0,0 +1,15 @@ +/datum/traitor_class/human/martyr + name = "Gorlex Marauder" + employer = "The Gorlex Marauders" + weight = 2 + chaos = 5 + cost = 5 + TC = 30 + uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit) + +/datum/traitor_class/human/hijack/forge_objectives(datum/antagonist/traitor/T) + var/datum/objective/hijack/O = new + O.explanation_text = "The Gorlex Marauders are letting you do what you want, with one condition: the shuttle must be hijacked." + O.owner = T.owner + T.add_objective(O) + return diff --git a/code/modules/antagonists/traitor/classes/human.dm b/code/modules/antagonists/traitor/classes/human.dm index 1f7b64d4f5..4e096390c0 100644 --- a/code/modules/antagonists/traitor/classes/human.dm +++ b/code/modules/antagonists/traitor/classes/human.dm @@ -1,79 +1,27 @@ -#define BASIC_TRAITOR /datum/traitor_class/human - /datum/traitor_class/human - name = "Traitor" - chaos = 1 + name = "Syndicate Agent" + chaos = 0 -/datum/traitor_class/human/forge_objectives(/datum/antagonist/traitor/T) - var/is_hijacker = FALSE - var/datum/game_mode/dynamic/mode - var/is_dynamic = FALSE - var/hijack_prob = 0 - if(istype(SSticker.mode,/datum/game_mode/dynamic)) - mode = SSticker.mode - is_dynamic = TRUE - if(mode.threat >= CONFIG_GET(number/dynamic_hijack_cost)) - hijack_prob = CLAMP(mode.threat_level-50,0,20) - if(GLOB.joined_player_list.len>=GLOB.dynamic_high_pop_limit) - is_hijacker = (prob(hijack_prob) && mode.threat_level > CONFIG_GET(number/dynamic_hijack_high_population_requirement)) - else - var/indice_pop = min(10,round(GLOB.joined_player_list.len/mode.pop_per_requirement)+1) - is_hijacker = (prob(hijack_prob) && (mode.threat_level >= CONFIG_GET(number_list/dynamic_hijack_requirements)[indice_pop])) - if(mode.storyteller.flags & NO_ASSASSIN) - is_hijacker = FALSE - else if (GLOB.joined_player_list.len >= 30) // Less murderboning on lowpop thanks - hijack_prob = 10 - is_hijacker = prob(10) - var/martyr_chance = prob(hijack_prob*2) - var/objective_count = is_hijacker //Hijacking counts towards number of objectives +/datum/traitor_class/human/forge_objectives(datum/antagonist/traitor/T) + var/objective_count = 0 //Hijacking counts towards number of objectives if(!SSticker.mode.exchange_blue && SSticker.mode.traitors.len >= 8) //Set up an exchange if there are enough traitors if(!SSticker.mode.exchange_red) SSticker.mode.exchange_red = T.owner else SSticker.mode.exchange_blue = T.owner - assign_exchange_role(SSticker.mode.exchange_red) - assign_exchange_role(SSticker.mode.exchange_blue) + T.assign_exchange_role(SSticker.mode.exchange_red) + T.assign_exchange_role(SSticker.mode.exchange_blue) objective_count += 1 //Exchange counts towards number of objectives var/toa = CONFIG_GET(number/traitor_objectives_amount) for(var/i = objective_count, i < toa, i++) forge_single_objective(T) - - if(is_hijacker && objective_count <= toa) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount - if (!(locate(/datum/objective/hijack) in objectives)) - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = T.owner - T.add_objective(hijack_objective) - if(is_dynamic) - var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost) - mode.spend_threat(threat_spent) - mode.log_threat("[owner.name] spent [threat_spent] on hijack.") - return - - - var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead. - for(var/datum/objective/O in objectives) - if(!O.martyr_compatible) - martyr_compatibility = 0 - break - - if(martyr_compatibility && martyr_chance) - var/datum/objective/martyr/martyr_objective = new - martyr_objective.owner = T.owner - T.add_objective(martyr_objective) - if(is_dynamic) - var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost) - mode.spend_threat(threat_spent) - mode.log_threat("[owner.name] spent [threat_spent] on glorious death.") + if(!(locate(/datum/objective/escape) in T.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = T.owner + T.add_objective(escape_objective) return - else - if(!(locate(/datum/objective/escape) in objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = owner - T.add_objective(escape_objective) - return - -/datum/traitor_class/human/forge_single_objective(/datum/antagonist/traitor/T) +/datum/traitor_class/human/forge_single_objective(datum/antagonist/traitor/T) .=1 var/assassin_prob = 50 var/is_dynamic = FALSE @@ -109,7 +57,7 @@ kill_objective.find_target() T.add_objective(kill_objective) else - if(prob(15) && !(locate(/datum/objective/download) in objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist"))) + if(prob(15) && !(locate(/datum/objective/download) in T.objectives) && !(T.owner.assigned_role in list("Research Director", "Scientist", "Roboticist"))) var/datum/objective/download/download_objective = new download_objective.owner = T.owner download_objective.gen_amount_goal() @@ -129,3 +77,6 @@ flavor_objective.owner = T.owner flavor_objective.forge_objective() T.add_objective(flavor_objective) + +/datum/traitor_class/human/greet(datum/antagonist/traitor/T) + to_chat(T.owner.current, "You are under contract with [employer]. They have given you your objectives.") diff --git a/code/modules/antagonists/traitor/classes/martyr.dm b/code/modules/antagonists/traitor/classes/martyr.dm new file mode 100644 index 0000000000..c934c38417 --- /dev/null +++ b/code/modules/antagonists/traitor/classes/martyr.dm @@ -0,0 +1,15 @@ +/datum/traitor_class/human/martyr + name = "Tiger Cooperative Agent" + employer = "The Tiger Cooperative" + weight = 2 + chaos = 5 + cost = 5 + TC = 30 + uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit) + +/datum/traitor_class/human/martyr/forge_objectives(datum/antagonist/traitor/T) + var/datum/objective/martyr/O = new + O.explanation_text = "The tiger cooperative have given you free reign. You may do as you wish, as long as you die a glorious death!" + O.owner = T.owner + T.add_objective(O) + return diff --git a/code/modules/antagonists/traitor/classes/subterfuge.dm b/code/modules/antagonists/traitor/classes/subterfuge.dm new file mode 100644 index 0000000000..2b4716e67e --- /dev/null +++ b/code/modules/antagonists/traitor/classes/subterfuge.dm @@ -0,0 +1,40 @@ +/datum/traitor_class/human/subterfuge + name = "MI13 Operative" + employer = "MI13" + weight = 4 + chaos = -5 + +/datum/traitor_class/human/subterfuge/forge_single_objective(datum/antagonist/traitor/T) + .=1 + var/assassin_prob = 20 + var/is_dynamic = FALSE + var/datum/game_mode/dynamic/mode + if(istype(SSticker.mode,/datum/game_mode/dynamic)) + mode = SSticker.mode + is_dynamic = TRUE + assassin_prob = max(0,mode.threat_level-50) + if(prob(assassin_prob)) + if(is_dynamic) + var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost) + mode.spend_threat(threat_spent) + mode.log_threat("[T.owner.name] spent [threat_spent] on an assassination target.") + var/datum/objective/maroon/maroon_objective = new + maroon_objective.owner = T.owner + maroon_objective.find_target() + T.add_objective(maroon_objective) + else + if(prob(15) && !(locate(/datum/objective/download) in T.objectives) && !(T.owner.assigned_role in list("Research Director", "Scientist", "Roboticist"))) + var/datum/objective/download/download_objective = new + download_objective.owner = T.owner + download_objective.gen_amount_goal() + T.add_objective(download_objective) + else if(prob(70)) // cum. not counting download: 40%. + var/datum/objective/steal/steal_objective = new + steal_objective.owner = T.owner + steal_objective.find_target() + T.add_objective(steal_objective) + else + var/datum/objective/sabotage/sabotage_objective = new + sabotage_objective.owner = T.owner + sabotage_objective.find_target() + T.add_objective(sabotage_objective) diff --git a/code/modules/antagonists/traitor/classes/traitor_class.dm b/code/modules/antagonists/traitor/classes/traitor_class.dm index 8107fa5af9..3df9dec929 100644 --- a/code/modules/antagonists/traitor/classes/traitor_class.dm +++ b/code/modules/antagonists/traitor/classes/traitor_class.dm @@ -5,23 +5,25 @@ GLOBAL_LIST_EMPTY(traitor_classes) var/employer = "The Syndicate" var/weight = 0 var/chaos = 0 + var/cost = 0 var/TC = 20 + var/list/uplink_filters /datum/traitor_class/New() ..() - if(src.type in traitor_classes) + if(src.type in GLOB.traitor_classes) qdel(src) else - traitor_classes += src.type - traitor_classes[src.type] = src + GLOB.traitor_classes += src.type + GLOB.traitor_classes[src.type] = src -/datum/traitor_class/proc/forge_objectives(/datum/antagonist/traitor/T) +/datum/traitor_class/proc/forge_objectives(datum/antagonist/traitor/T) // Like the old forge_human_objectives. Makes all the objectives for this traitor class. -/datum/traitor_class/proc/forge_single_objective(/datum/antagonist/traitor/T) +/datum/traitor_class/proc/forge_single_objective(datum/antagonist/traitor/T) // As forge_single_objective. -/datum/traitor_class/proc/on_removal(/datum/antagonist/traitor/T) +/datum/traitor_class/proc/on_removal(datum/antagonist/traitor/T) // What this does to the antag datum on removal. Called before proper removal, obviously. /datum/traitor_class/proc/apply_innate_effects(mob/living/M) @@ -30,6 +32,9 @@ GLOBAL_LIST_EMPTY(traitor_classes) /datum/traitor_class/proc/remove_innate_effects(mob/living/M) // Cleaning up the innate effects. -/datum/traitor_class/proc/finalize_traitor(/datum/antagonist/traitor/T) +/datum/traitor_class/proc/greet(datum/antagonist/traitor/T) + // Message upon creation. Not necessary, but can be useful. + +/datum/traitor_class/proc/finalize_traitor(datum/antagonist/traitor/T) // Finalization. Return TRUE if should play standard traitor sound/equip, return FALSE if both are special case return TRUE diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index da35d1ffdc..fcaa0f2211 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -1,5 +1,3 @@ -#define TRAITOR_HUMAN "human" - /datum/antagonist/traitor name = "Traitor" roundend_category = "traitors" @@ -11,7 +9,7 @@ var/give_objectives = TRUE var/should_give_codewords = TRUE var/should_equip = TRUE - var/datum/traitor_class/traitor_kind = TRAITOR_HUMAN //Set on initial assignment + var/datum/traitor_class/traitor_kind can_hijack = HIJACK_HIJACKER /datum/antagonist/traitor/New() @@ -21,7 +19,12 @@ new I /datum/antagonist/traitor/proc/set_traitor_kind(var/kind) - traitor_kind = traitor_classes[kind] + traitor_kind = GLOB.traitor_classes[kind] + if(istype(SSticker.mode, /datum/game_mode/dynamic)) + var/datum/game_mode/dynamic/mode = SSticker.mode + if(traitor_kind.cost) + mode.spend_threat(traitor_kind.cost) + mode.log_threat("[traitor_kind.cost] was spent due to [owner.name] being a [traitor_kind.name].") /datum/antagonist/traitor/on_gain() if(owner.current && isAI(owner.current)) @@ -32,10 +35,13 @@ var/datum/game_mode/dynamic/mode = SSticker.mode chaos_weight = (mode.threat - 50)/50 var/list/weights = list() - for(var/C in traitor_classes) - var/datum/traitor_class/class = C + for(var/C in GLOB.traitor_classes) + var/datum/traitor_class/class = GLOB.traitor_classes[C] var/weight = class.weight/(1+NUM_E**(-chaos_weight*class.chaos)) // just a logistic function weights[C] = weight + var/choice = pickweightAllowZero(weights) + if(!choice) + choice = GLOB.traitor_classes[TRAITOR_HUMAN] set_traitor_kind(pickweightAllowZero(weights)) traitor_kind.weight /= 2 // less likely this round SSticker.mode.traitors += owner @@ -84,168 +90,10 @@ /datum/antagonist/traitor/proc/forge_traitor_objectives() traitor_kind.forge_objectives(src) - switch(traitor_kind) - if(TRAITOR_AI) - forge_ai_objectives() - else - forge_human_objectives() - -/datum/antagonist/traitor/proc/forge_human_objectives() - var/is_hijacker = FALSE - var/datum/game_mode/dynamic/mode - var/is_dynamic = FALSE - var/hijack_prob = 0 - if(istype(SSticker.mode,/datum/game_mode/dynamic)) - mode = SSticker.mode - is_dynamic = TRUE - if(mode.threat >= CONFIG_GET(number/dynamic_hijack_cost)) - hijack_prob = CLAMP(mode.threat_level-50,0,20) - if(GLOB.joined_player_list.len>=GLOB.dynamic_high_pop_limit) - is_hijacker = (prob(hijack_prob) && mode.threat_level > CONFIG_GET(number/dynamic_hijack_high_population_requirement)) - else - var/indice_pop = min(10,round(GLOB.joined_player_list.len/mode.pop_per_requirement)+1) - is_hijacker = (prob(hijack_prob) && (mode.threat_level >= CONFIG_GET(number_list/dynamic_hijack_requirements)[indice_pop])) - if(mode.storyteller.flags & NO_ASSASSIN) - is_hijacker = FALSE - else if (GLOB.joined_player_list.len >= 30) // Less murderboning on lowpop thanks - hijack_prob = 10 - is_hijacker = prob(10) - var/martyr_chance = prob(hijack_prob*2) - var/objective_count = is_hijacker //Hijacking counts towards number of objectives - if(!SSticker.mode.exchange_blue && SSticker.mode.traitors.len >= 8) //Set up an exchange if there are enough traitors - if(!SSticker.mode.exchange_red) - SSticker.mode.exchange_red = owner - else - SSticker.mode.exchange_blue = owner - assign_exchange_role(SSticker.mode.exchange_red) - assign_exchange_role(SSticker.mode.exchange_blue) - objective_count += 1 //Exchange counts towards number of objectives - var/toa = CONFIG_GET(number/traitor_objectives_amount) - for(var/i = objective_count, i < toa, i++) - forge_single_objective() - - if(is_hijacker && objective_count <= toa) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount - if (!(locate(/datum/objective/hijack) in objectives)) - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = owner - add_objective(hijack_objective) - if(is_dynamic) - var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost) - mode.spend_threat(threat_spent) - mode.log_threat("[owner.name] spent [threat_spent] on hijack.") - return - - - var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead. - for(var/datum/objective/O in objectives) - if(!O.martyr_compatible) - martyr_compatibility = 0 - break - - if(martyr_compatibility && martyr_chance) - var/datum/objective/martyr/martyr_objective = new - martyr_objective.owner = owner - add_objective(martyr_objective) - if(is_dynamic) - var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost) - mode.spend_threat(threat_spent) - mode.log_threat("[owner.name] spent [threat_spent] on glorious death.") - return - - else - if(!(locate(/datum/objective/escape) in objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = owner - add_objective(escape_objective) - return - -/datum/antagonist/traitor/proc/forge_single_human_objective() //Returns how many objectives are added - .=1 - var/assassin_prob = 50 - var/is_dynamic = FALSE - var/datum/game_mode/dynamic/mode - if(istype(SSticker.mode,/datum/game_mode/dynamic)) - mode = SSticker.mode - is_dynamic = TRUE - assassin_prob = max(0,mode.threat_level-20) - if(prob(assassin_prob)) - if(is_dynamic) - var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost) - mode.spend_threat(threat_spent) - mode.log_threat("[owner.name] spent [threat_spent] on an assassination target.") - var/list/active_ais = active_ais() - if(active_ais.len && prob(100/GLOB.joined_player_list.len)) - var/datum/objective/destroy/destroy_objective = new - destroy_objective.owner = owner - destroy_objective.find_target() - add_objective(destroy_objective) - else if(prob(30) || (is_dynamic && (mode.storyteller.flags & NO_ASSASSIN))) - var/datum/objective/maroon/maroon_objective = new - maroon_objective.owner = owner - maroon_objective.find_target() - add_objective(maroon_objective) - else if(prob(max(0,assassin_prob-20))) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = owner - kill_objective.find_target() - add_objective(kill_objective) - else - var/datum/objective/assassinate/once/kill_objective = new - kill_objective.owner = owner - kill_objective.find_target() - add_objective(kill_objective) - else - if(prob(15) && !(locate(/datum/objective/download) in objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist"))) - var/datum/objective/download/download_objective = new - download_objective.owner = owner - download_objective.gen_amount_goal() - add_objective(download_objective) - else if(prob(40)) // cum. not counting download: 40%. - var/datum/objective/steal/steal_objective = new - steal_objective.owner = owner - steal_objective.find_target() - add_objective(steal_objective) - else if(prob(100/3)) // cum. not counting download: 20%. - var/datum/objective/sabotage/sabotage_objective = new - sabotage_objective.owner = owner - sabotage_objective.find_target() - add_objective(sabotage_objective) - else // cum. not counting download: 40% - var/datum/objective/flavor/traitor/flavor_objective = new - flavor_objective.owner = owner - flavor_objective.forge_objective() - add_objective(flavor_objective) - -/datum/antagonist/traitor/proc/forge_single_AI_objective() - .=1 - var/special_pick = rand(1,4) - switch(special_pick) - if(1) - var/datum/objective/block/block_objective = new - block_objective.owner = owner - add_objective(block_objective) - if(2) - var/datum/objective/purge/purge_objective = new - purge_objective.owner = owner - add_objective(purge_objective) - if(3) - var/datum/objective/robot_army/robot_objective = new - robot_objective.owner = owner - add_objective(robot_objective) - if(4) //Protect and strand a target - var/datum/objective/protect/yandere_one = new - yandere_one.owner = owner - add_objective(yandere_one) - yandere_one.find_target() - var/datum/objective/maroon/yandere_two = new - yandere_two.owner = owner - yandere_two.target = yandere_one.target - yandere_two.update_explanation_text() // normally called in find_target() - add_objective(yandere_two) - .=2 /datum/antagonist/traitor/greet() to_chat(owner.current, "You are the [owner.special_role].") + traitor_kind.greet(src) owner.announce_objectives() if(should_give_codewords) give_codewords() diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index 52f6efd3df..bbfa186a48 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -1,4 +1,4 @@ -/proc/get_uplink_items(datum/game_mode/gamemode, allow_sales = TRUE, allow_restricted = TRUE) +/proc/get_uplink_items(datum/game_mode/gamemode, allow_sales = TRUE, allow_restricted = TRUE, other_filter = list()) var/list/filtered_uplink_items = GLOB.uplink_categories.Copy() // list of uplink categories without associated values. var/list/sale_items = list() @@ -18,7 +18,8 @@ continue if (I.restricted && !allow_restricted) continue - + if (I.type in other_filter) + continue LAZYSET(filtered_uplink_items[I.category], I.name, I) if(I.limited_stock < 0 && !I.cant_discount && I.item && I.cost > 1) diff --git a/tgstation.dme b/tgstation.dme index 0b7ad871c3..83ddb4d336 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -1453,6 +1453,14 @@ #include "code\modules\antagonists\swarmer\swarmer.dm" #include "code\modules\antagonists\swarmer\swarmer_event.dm" #include "code\modules\antagonists\traitor\datum_traitor.dm" +#include "code\modules\antagonists\traitor\classes\ai.dm" +#include "code\modules\antagonists\traitor\classes\assassin.dm" +#include "code\modules\antagonists\traitor\classes\gimmick.dm" +#include "code\modules\antagonists\traitor\classes\hijack.dm" +#include "code\modules\antagonists\traitor\classes\human.dm" +#include "code\modules\antagonists\traitor\classes\martyr.dm" +#include "code\modules\antagonists\traitor\classes\subterfuge.dm" +#include "code\modules\antagonists\traitor\classes\traitor_class.dm" #include "code\modules\antagonists\traitor\equipment\Malf_Modules.dm" #include "code\modules\antagonists\traitor\IAA\internal_affairs.dm" #include "code\modules\antagonists\valentines\heartbreaker.dm" From 56ab702fa542fb0f3b7ac0b4d4b0f20c36385762 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 1 Mar 2020 00:02:16 -0800 Subject: [PATCH 03/61] but how --- code/modules/antagonists/traitor/datum_traitor.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 576569b8ba..e2a5c0046a 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -10,7 +10,6 @@ var/should_give_codewords = TRUE var/should_equip = TRUE var/datum/traitor_class/traitor_kind - var/traitor_kind = TRAITOR_HUMAN //Set on initial assignment can_hijack = HIJACK_HIJACKER hijack_speed = 0.5 //10 seconds per hijack stage by default From 6e7406a51a5f7cfa8f7efdaa70138259c940748d Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 1 Mar 2020 00:03:00 -0800 Subject: [PATCH 04/61] what --- code/modules/antagonists/traitor/datum_traitor.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index e2a5c0046a..16e7e71eac 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -10,7 +10,6 @@ var/should_give_codewords = TRUE var/should_equip = TRUE var/datum/traitor_class/traitor_kind - can_hijack = HIJACK_HIJACKER hijack_speed = 0.5 //10 seconds per hijack stage by default /datum/antagonist/traitor/New() From 7a5366f5dd1b0ddc4a2ef65a932e5a71a667f23d Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 1 Mar 2020 00:03:12 -0800 Subject: [PATCH 05/61] come to think of it a "cooperative", huh --- code/modules/antagonists/traitor/classes/martyr.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/antagonists/traitor/classes/martyr.dm b/code/modules/antagonists/traitor/classes/martyr.dm index c934c38417..24da190057 100644 --- a/code/modules/antagonists/traitor/classes/martyr.dm +++ b/code/modules/antagonists/traitor/classes/martyr.dm @@ -1,5 +1,5 @@ /datum/traitor_class/human/martyr - name = "Tiger Cooperative Agent" + name = "Tiger Cooperator" employer = "The Tiger Cooperative" weight = 2 chaos = 5 From 3059e482785625b1f84618dae0ce1d15256e5d88 Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 3 Mar 2020 16:46:41 -0800 Subject: [PATCH 06/61] Removed 30TC thing from martyr/hijack --- code/modules/antagonists/traitor/classes/hijack.dm | 3 +-- code/modules/antagonists/traitor/classes/martyr.dm | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/code/modules/antagonists/traitor/classes/hijack.dm b/code/modules/antagonists/traitor/classes/hijack.dm index 0ed716c3cd..d6b4fa3f26 100644 --- a/code/modules/antagonists/traitor/classes/hijack.dm +++ b/code/modules/antagonists/traitor/classes/hijack.dm @@ -1,10 +1,9 @@ -/datum/traitor_class/human/martyr +/datum/traitor_class/human/hijack name = "Gorlex Marauder" employer = "The Gorlex Marauders" weight = 2 chaos = 5 cost = 5 - TC = 30 uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit) /datum/traitor_class/human/hijack/forge_objectives(datum/antagonist/traitor/T) diff --git a/code/modules/antagonists/traitor/classes/martyr.dm b/code/modules/antagonists/traitor/classes/martyr.dm index 24da190057..13d0e73a41 100644 --- a/code/modules/antagonists/traitor/classes/martyr.dm +++ b/code/modules/antagonists/traitor/classes/martyr.dm @@ -4,7 +4,6 @@ weight = 2 chaos = 5 cost = 5 - TC = 30 uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit) /datum/traitor_class/human/martyr/forge_objectives(datum/antagonist/traitor/T) From 436e781ec94930e55cb9838dcdb18e424fb33eda Mon Sep 17 00:00:00 2001 From: Putnam Date: Fri, 6 Mar 2020 15:37:59 -0800 Subject: [PATCH 07/61] Removed assassin-only, made subterfuge more likely to assassinate --- .../antagonists/traitor/classes/assassin.dm | 2 +- .../antagonists/traitor/classes/subterfuge.dm | 22 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/code/modules/antagonists/traitor/classes/assassin.dm b/code/modules/antagonists/traitor/classes/assassin.dm index ca192aff5a..0c1d950f57 100644 --- a/code/modules/antagonists/traitor/classes/assassin.dm +++ b/code/modules/antagonists/traitor/classes/assassin.dm @@ -1,7 +1,7 @@ /datum/traitor_class/human/assassin name = "Donk Co Operative" employer = "Donk Corporation" - weight = 4 + weight = 0 chaos = 1 cost = 2 diff --git a/code/modules/antagonists/traitor/classes/subterfuge.dm b/code/modules/antagonists/traitor/classes/subterfuge.dm index 2b4716e67e..8e97a6a2ba 100644 --- a/code/modules/antagonists/traitor/classes/subterfuge.dm +++ b/code/modules/antagonists/traitor/classes/subterfuge.dm @@ -6,22 +6,24 @@ /datum/traitor_class/human/subterfuge/forge_single_objective(datum/antagonist/traitor/T) .=1 - var/assassin_prob = 20 + var/assassin_prob = 30 var/is_dynamic = FALSE var/datum/game_mode/dynamic/mode if(istype(SSticker.mode,/datum/game_mode/dynamic)) mode = SSticker.mode is_dynamic = TRUE - assassin_prob = max(0,mode.threat_level-50) + assassin_prob = max(0,mode.threat_level-40) if(prob(assassin_prob)) - if(is_dynamic) - var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost) - mode.spend_threat(threat_spent) - mode.log_threat("[T.owner.name] spent [threat_spent] on an assassination target.") - var/datum/objective/maroon/maroon_objective = new - maroon_objective.owner = T.owner - maroon_objective.find_target() - T.add_objective(maroon_objective) + if(prob(assassin_prob)) + var/datum/objective/assassinate/once/kill_objective = new + kill_objective.owner = T.owner + kill_objective.find_target() + T.add_objective(kill_objective) + else + var/datum/objective/maroon/maroon_objective = new + maroon_objective.owner = T.owner + maroon_objective.find_target() + T.add_objective(maroon_objective) else if(prob(15) && !(locate(/datum/objective/download) in T.objectives) && !(T.owner.assigned_role in list("Research Director", "Scientist", "Roboticist"))) var/datum/objective/download/download_objective = new From 182e98192cd67ae9b63adb767dff5a13631cb280 Mon Sep 17 00:00:00 2001 From: Putnam Date: Fri, 6 Mar 2020 17:01:43 -0800 Subject: [PATCH 08/61] no longer uses that var --- code/modules/antagonists/traitor/classes/subterfuge.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/modules/antagonists/traitor/classes/subterfuge.dm b/code/modules/antagonists/traitor/classes/subterfuge.dm index 8e97a6a2ba..834ef72fe8 100644 --- a/code/modules/antagonists/traitor/classes/subterfuge.dm +++ b/code/modules/antagonists/traitor/classes/subterfuge.dm @@ -7,11 +7,9 @@ /datum/traitor_class/human/subterfuge/forge_single_objective(datum/antagonist/traitor/T) .=1 var/assassin_prob = 30 - var/is_dynamic = FALSE var/datum/game_mode/dynamic/mode if(istype(SSticker.mode,/datum/game_mode/dynamic)) mode = SSticker.mode - is_dynamic = TRUE assassin_prob = max(0,mode.threat_level-40) if(prob(assassin_prob)) if(prob(assassin_prob)) From 1c37b95c0b749ae03940f53bec2de84768bc932c Mon Sep 17 00:00:00 2001 From: Putnam Date: Fri, 6 Mar 2020 17:21:30 -0800 Subject: [PATCH 09/61] renamed "gimmick" to "freeform" --- .../antagonists/traitor/classes/{gimmick.dm => freeform.dm} | 4 ++-- tgstation.dme | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename code/modules/antagonists/traitor/classes/{gimmick.dm => freeform.dm} (73%) diff --git a/code/modules/antagonists/traitor/classes/gimmick.dm b/code/modules/antagonists/traitor/classes/freeform.dm similarity index 73% rename from code/modules/antagonists/traitor/classes/gimmick.dm rename to code/modules/antagonists/traitor/classes/freeform.dm index 12f9674140..08fc7416bd 100644 --- a/code/modules/antagonists/traitor/classes/gimmick.dm +++ b/code/modules/antagonists/traitor/classes/freeform.dm @@ -1,10 +1,10 @@ -/datum/traitor_class/human/gimmick +/datum/traitor_class/human/freeform name = "Waffle Co Agent" employer = "Waffle Company" weight = 4 chaos = 0 -/datum/traitor_class/human/gimmick/forge_objectives(datum/antagonist/traitor/T) +/datum/traitor_class/human/freeform/forge_objectives(datum/antagonist/traitor/T) var/datum/objective/escape/O = new O.explanation_text = "You have no goals! Whatever you can do do antagonize Nanotrasen, do it! The gimmickier, the better! Make sure to escape alive, though!" O.owner = T.owner diff --git a/tgstation.dme b/tgstation.dme index f8d349720b..4d3439472a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1474,7 +1474,7 @@ #include "code\modules\antagonists\traitor\datum_traitor.dm" #include "code\modules\antagonists\traitor\classes\ai.dm" #include "code\modules\antagonists\traitor\classes\assassin.dm" -#include "code\modules\antagonists\traitor\classes\gimmick.dm" +#include "code\modules\antagonists\traitor\classes\freeform.dm" #include "code\modules\antagonists\traitor\classes\hijack.dm" #include "code\modules\antagonists\traitor\classes\human.dm" #include "code\modules\antagonists\traitor\classes\martyr.dm" From 39527ae4a73136c42bbd00c96b565efe578d64c8 Mon Sep 17 00:00:00 2001 From: Putnam Date: Fri, 6 Mar 2020 17:21:41 -0800 Subject: [PATCH 10/61] prevented hijack/martyr from being contractors --- code/modules/antagonists/traitor/classes/hijack.dm | 2 +- code/modules/antagonists/traitor/classes/martyr.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/antagonists/traitor/classes/hijack.dm b/code/modules/antagonists/traitor/classes/hijack.dm index d6b4fa3f26..5390bfca25 100644 --- a/code/modules/antagonists/traitor/classes/hijack.dm +++ b/code/modules/antagonists/traitor/classes/hijack.dm @@ -4,7 +4,7 @@ weight = 2 chaos = 5 cost = 5 - uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit) + uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit,/datum/uplink_item/bundles_TC/contract_kit) /datum/traitor_class/human/hijack/forge_objectives(datum/antagonist/traitor/T) var/datum/objective/hijack/O = new diff --git a/code/modules/antagonists/traitor/classes/martyr.dm b/code/modules/antagonists/traitor/classes/martyr.dm index 13d0e73a41..78f8bf9b0c 100644 --- a/code/modules/antagonists/traitor/classes/martyr.dm +++ b/code/modules/antagonists/traitor/classes/martyr.dm @@ -4,7 +4,7 @@ weight = 2 chaos = 5 cost = 5 - uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit) + uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit,/datum/uplink_item/bundles_TC/contract_kit) /datum/traitor_class/human/martyr/forge_objectives(datum/antagonist/traitor/T) var/datum/objective/martyr/O = new From f670d09a88dfa8e40978e609aa1ec287c141b602 Mon Sep 17 00:00:00 2001 From: Putnam Date: Fri, 6 Mar 2020 21:39:38 -0800 Subject: [PATCH 11/61] Made IAA work again (whoops) --- code/modules/antagonists/traitor/IAA/internal_affairs.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/antagonists/traitor/IAA/internal_affairs.dm b/code/modules/antagonists/traitor/IAA/internal_affairs.dm index f6ee056865..19144d67c9 100644 --- a/code/modules/antagonists/traitor/IAA/internal_affairs.dm +++ b/code/modules/antagonists/traitor/IAA/internal_affairs.dm @@ -120,7 +120,7 @@ /datum/antagonist/traitor/internal_affairs/reinstate_escape_objective() ..() - var/objtype = traitor_kind == TRAITOR_HUMAN ? /datum/objective/escape : /datum/objective/survive + var/objtype = !istype(traitor_kind,TRAITOR_AI) ? /datum/objective/escape : /datum/objective/survive var/datum/objective/escape_objective = new objtype escape_objective.owner = owner add_objective(escape_objective) @@ -220,7 +220,7 @@ /datum/antagonist/traitor/internal_affairs/forge_traitor_objectives() forge_iaa_objectives() - var/objtype = traitor_kind == TRAITOR_HUMAN ? /datum/objective/escape : /datum/objective/survive + var/objtype = !istype(traitor_kind,TRAITOR_AI) ? /datum/objective/escape : /datum/objective/survive var/datum/objective/escape_objective = new objtype escape_objective.owner = owner add_objective(escape_objective) From 023d1d6d979232f4609d139849f4a5956c04c0c3 Mon Sep 17 00:00:00 2001 From: Putnam Date: Fri, 6 Mar 2020 21:40:44 -0800 Subject: [PATCH 12/61] Tweaked weights a bunch --- code/__DEFINES/antagonists.dm | 2 +- code/modules/antagonists/traitor/classes/freeform.dm | 2 +- code/modules/antagonists/traitor/classes/hijack.dm | 2 +- code/modules/antagonists/traitor/classes/martyr.dm | 2 +- code/modules/antagonists/traitor/classes/subterfuge.dm | 2 +- code/modules/antagonists/traitor/datum_traitor.dm | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index ba1b509d2c..33472ba789 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -1,4 +1,4 @@ -#define TRAITOR_HUMAN /datum/traitor_class/human +#define TRAITOR_HUMAN /datum/traitor_class/human/freeform #define TRAITOR_AI /datum/traitor_class/ai #define NUKE_RESULT_FLUKE 0 diff --git a/code/modules/antagonists/traitor/classes/freeform.dm b/code/modules/antagonists/traitor/classes/freeform.dm index 08fc7416bd..f84eadb9f6 100644 --- a/code/modules/antagonists/traitor/classes/freeform.dm +++ b/code/modules/antagonists/traitor/classes/freeform.dm @@ -1,7 +1,7 @@ /datum/traitor_class/human/freeform name = "Waffle Co Agent" employer = "Waffle Company" - weight = 4 + weight = 16 chaos = 0 /datum/traitor_class/human/freeform/forge_objectives(datum/antagonist/traitor/T) diff --git a/code/modules/antagonists/traitor/classes/hijack.dm b/code/modules/antagonists/traitor/classes/hijack.dm index 5390bfca25..e61abae465 100644 --- a/code/modules/antagonists/traitor/classes/hijack.dm +++ b/code/modules/antagonists/traitor/classes/hijack.dm @@ -1,7 +1,7 @@ /datum/traitor_class/human/hijack name = "Gorlex Marauder" employer = "The Gorlex Marauders" - weight = 2 + weight = 1 chaos = 5 cost = 5 uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit,/datum/uplink_item/bundles_TC/contract_kit) diff --git a/code/modules/antagonists/traitor/classes/martyr.dm b/code/modules/antagonists/traitor/classes/martyr.dm index 78f8bf9b0c..fa0ee600b4 100644 --- a/code/modules/antagonists/traitor/classes/martyr.dm +++ b/code/modules/antagonists/traitor/classes/martyr.dm @@ -1,7 +1,7 @@ /datum/traitor_class/human/martyr name = "Tiger Cooperator" employer = "The Tiger Cooperative" - weight = 2 + weight = 1 chaos = 5 cost = 5 uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit,/datum/uplink_item/bundles_TC/contract_kit) diff --git a/code/modules/antagonists/traitor/classes/subterfuge.dm b/code/modules/antagonists/traitor/classes/subterfuge.dm index 834ef72fe8..ae43f11fe7 100644 --- a/code/modules/antagonists/traitor/classes/subterfuge.dm +++ b/code/modules/antagonists/traitor/classes/subterfuge.dm @@ -1,7 +1,7 @@ /datum/traitor_class/human/subterfuge name = "MI13 Operative" employer = "MI13" - weight = 4 + weight = 20 chaos = -5 /datum/traitor_class/human/subterfuge/forge_single_objective(datum/antagonist/traitor/T) diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 875a6c688c..8c41a31785 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -38,13 +38,13 @@ var/list/weights = list() for(var/C in GLOB.traitor_classes) var/datum/traitor_class/class = GLOB.traitor_classes[C] - var/weight = class.weight/(1+NUM_E**(-chaos_weight*class.chaos)) // just a logistic function + var/weight = (1.5*class.weight)/(0.5+NUM_E**(-chaos_weight*class.chaos)) // just a logistic function weights[C] = weight var/choice = pickweightAllowZero(weights) if(!choice) choice = GLOB.traitor_classes[TRAITOR_HUMAN] set_traitor_kind(pickweightAllowZero(weights)) - traitor_kind.weight /= 2 // less likely this round + traitor_kind.weight *= 0.8 // less likely this round SSticker.mode.traitors += owner owner.special_role = special_role if(give_objectives) From eacdc3b43821589d3bf8857297ac6c8ab724a256 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 8 Mar 2020 14:05:04 -0700 Subject: [PATCH 13/61] Let gorlex marauders contract, and made them hijack 2x as fast as other traitors --- code/modules/antagonists/traitor/classes/hijack.dm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/modules/antagonists/traitor/classes/hijack.dm b/code/modules/antagonists/traitor/classes/hijack.dm index e61abae465..3f6b83a0ad 100644 --- a/code/modules/antagonists/traitor/classes/hijack.dm +++ b/code/modules/antagonists/traitor/classes/hijack.dm @@ -4,7 +4,7 @@ weight = 1 chaos = 5 cost = 5 - uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit,/datum/uplink_item/bundles_TC/contract_kit) + uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit) /datum/traitor_class/human/hijack/forge_objectives(datum/antagonist/traitor/T) var/datum/objective/hijack/O = new @@ -12,3 +12,6 @@ O.owner = T.owner T.add_objective(O) return + +/datum/traitor_class/human/hijack/finalize_traitor(datum/antagonist/traitor/T) + T.hijack_speed=1 From f19647acc795dcd3b02894610f1ff50d549a617b Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 9 Mar 2020 18:47:06 -0700 Subject: [PATCH 14/61] Fixed uplinks not being given to traitors. Always remember to follow your code VERY CLOSELY or garbage like this happens. finalize_traitor calls traitor_kind.finalize_traitor(); that's how I intended it to happen. Instead, I foolishly wrote "traitor_kind.finalize_traitor()" in the on_gain() proc. I didn't notice for a LONG time, because... well, it's supposed to call finalize_traitor(), just not that one. The pitfalls of working with old code. --- code/modules/antagonists/traitor/classes/hijack.dm | 1 + code/modules/antagonists/traitor/datum_traitor.dm | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/antagonists/traitor/classes/hijack.dm b/code/modules/antagonists/traitor/classes/hijack.dm index 3f6b83a0ad..89c3d60a12 100644 --- a/code/modules/antagonists/traitor/classes/hijack.dm +++ b/code/modules/antagonists/traitor/classes/hijack.dm @@ -15,3 +15,4 @@ /datum/traitor_class/human/hijack/finalize_traitor(datum/antagonist/traitor/T) T.hijack_speed=1 + return TRUE diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 8c41a31785..3324f1e756 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -49,7 +49,7 @@ owner.special_role = special_role if(give_objectives) traitor_kind.forge_objectives(src) - traitor_kind.finalize_traitor(src) + finalize_traitor() ..() /datum/antagonist/traitor/apply_innate_effects() From 5a18d143a92e2df6b2bd6c2877c51d9d3596de73 Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 9 Mar 2020 18:47:42 -0700 Subject: [PATCH 15/61] Removed extraneous apply_innate_effects This one was caused by the hear proc overhaul. --- .../antagonists/traitor/datum_traitor.dm | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 3324f1e756..a9dee81a6c 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -52,22 +52,6 @@ finalize_traitor() ..() -/datum/antagonist/traitor/apply_innate_effects() - traitor_kind.apply_innate_effects(src) - if(owner.assigned_role == "Clown") - var/mob/living/carbon/human/traitor_mob = owner.current - if(traitor_mob && istype(traitor_mob)) - if(!silent) - to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") - traitor_mob.dna.remove_mutation(CLOWNMUT) - -/datum/antagonist/traitor/remove_innate_effects() - traitor_kind.remove_innate_effects(src) - if(owner.assigned_role == "Clown") - var/mob/living/carbon/human/traitor_mob = owner.current - if(traitor_mob && istype(traitor_mob)) - traitor_mob.dna.add_mutation(CLOWNMUT) - /datum/antagonist/traitor/on_removal() //Remove malf powers. traitor_kind.on_removal(src) @@ -111,8 +95,7 @@ set_antag_hud(owner.current, null) /datum/antagonist/traitor/proc/finalize_traitor() - var/should_base_finalize = traitor_kind.finalize_traitor(src) - if(should_base_finalize) + if(traitor_kind.finalize_traitor(src)) if(should_equip) equip(silent) owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE) @@ -122,6 +105,12 @@ update_traitor_icons_added() var/mob/M = mob_override || owner.current traitor_kind.apply_innate_effects(M) + if(owner.assigned_role == "Clown") + var/mob/living/carbon/human/H = M + if(istype(H)) + if(!silent) + to_chat(H, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") + H.dna.remove_mutation(CLOWNMUT) RegisterSignal(M, COMSIG_MOVABLE_HEAR, .proc/handle_hearing) /datum/antagonist/traitor/remove_innate_effects(mob/living/mob_override) @@ -129,6 +118,10 @@ update_traitor_icons_removed() var/mob/M = mob_override || owner.current traitor_kind.remove_innate_effects(M) + if(owner.assigned_role == "Clown") + var/mob/living/carbon/human/H = M + if(istype(H)) + H.dna.add_mutation(CLOWNMUT) UnregisterSignal(M, COMSIG_MOVABLE_HEAR) /datum/antagonist/traitor/proc/give_codewords() From 9e61d9cfb724d3040e61438cfb4966747ae5acfb Mon Sep 17 00:00:00 2001 From: MrJWhit <48370570+MrJWhit@users.noreply.github.com> Date: Wed, 11 Mar 2020 16:53:12 -0400 Subject: [PATCH 16/61] Update KiloStation.dmm asdf --- _maps/map_files/KiloStation/KiloStation.dmm | 248 ++++---------------- 1 file changed, 51 insertions(+), 197 deletions(-) diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm index a04260249a..73386e6e1e 100644 --- a/_maps/map_files/KiloStation/KiloStation.dmm +++ b/_maps/map_files/KiloStation/KiloStation.dmm @@ -2284,7 +2284,6 @@ /area/maintenance/port/aft) "aea" = ( /obj/structure/bed, -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/cobweb, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/blood/old, @@ -2646,7 +2645,6 @@ /turf/open/floor/plasteel/dark, /area/security/courtroom) "aeN" = ( -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/cobweb, /obj/structure/closet/firecloset, @@ -2859,7 +2857,6 @@ /obj/structure/closet/secure_closet/injection{ name = "Justice Injections" }, -/obj/effect/turf_decal/bot, /obj/machinery/atmospherics/components/unary/vent_pump/on, /obj/machinery/button/door{ id = "SecJusticeChamber"; @@ -3423,7 +3420,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/bot, /turf/open/floor/plasteel/dark, /area/security/warden) "afS" = ( @@ -3431,7 +3427,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/open/floor/plasteel/dark, /area/security/warden) @@ -3839,7 +3834,6 @@ /turf/open/floor/plasteel/dark, /area/science/xenobiology) "agw" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet/emcloset, /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/open/floor/plating, @@ -3895,7 +3889,6 @@ }, /area/maintenance/starboard/fore) "agC" = ( -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/structure/closet, /obj/item/cardboard_cutout{ @@ -4204,7 +4197,6 @@ /area/security/execution/education) "ahe" = ( /obj/effect/landmark/secequipment, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -4213,7 +4205,6 @@ /area/security/main) "ahf" = ( /obj/effect/landmark/secequipment, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -4977,7 +4968,6 @@ /turf/open/floor/plasteel/showroomfloor, /area/science/server) "ail" = ( -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/structure/closet/emcloset, /turf/open/floor/plating, @@ -5336,7 +5326,6 @@ /area/security/main) "aiM" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, /obj/structure/closet{ name = "chapel locker" }, @@ -5448,7 +5437,6 @@ /obj/effect/turf_decal/tile/neutral, /obj/effect/decal/cleanable/blood/old, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/box/corners, /turf/open/floor/plasteel/dark, /area/maintenance/port/fore) "aiW" = ( @@ -5597,9 +5585,6 @@ dir = 8 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/box/corners{ - dir = 8 - }, /turf/open/floor/plasteel/dark, /area/maintenance/port/fore) "aji" = ( @@ -5774,7 +5759,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/effect/turf_decal/bot, /turf/open/floor/plasteel/dark, /area/security/warden) "ajv" = ( @@ -6032,7 +6016,6 @@ /area/maintenance/port/aft) "ajU" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, /obj/structure/closet/emcloset, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -6556,7 +6539,6 @@ "akU" = ( /obj/structure/closet/crate/coffin, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -6617,7 +6599,6 @@ /obj/machinery/light{ dir = 1 }, -/obj/effect/turf_decal/box, /obj/structure/extinguisher_cabinet{ pixel_x = -26 }, @@ -6635,7 +6616,6 @@ "akZ" = ( /obj/structure/closet/crate/coffin, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, @@ -6968,12 +6948,9 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/security/armory) "alw" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, /obj/effect/decal/cleanable/blood/old, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/box/corners{ +/obj/effect/turf_decal/tile/neutral{ dir = 4 }, /turf/open/floor/plasteel/dark, @@ -7040,7 +7017,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/machinery/status_display/evac{ pixel_y = 32 }, @@ -7127,11 +7103,8 @@ /turf/open/floor/plasteel/showroomfloor, /area/security/brig) "alH" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/box/corners{ +/obj/effect/turf_decal/tile/neutral{ dir = 1 }, /turf/open/floor/plasteel/dark, @@ -7228,7 +7201,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel/dark, /area/ai_monitored/security/armory) "alQ" = ( @@ -8034,7 +8006,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/dark, /area/security/warden) @@ -8299,7 +8270,6 @@ /area/space/nearstation) "anI" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, /obj/structure/closet{ name = "bible locker" }, @@ -8616,7 +8586,6 @@ /area/space/nearstation) "aog" = ( /obj/effect/landmark/secequipment, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -9298,7 +9267,6 @@ }, /area/ai_monitored/turret_protected/ai) "apo" = ( -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/structure/closet{ name = "science locker" @@ -9353,7 +9321,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small, /turf/open/floor/plasteel/dark, @@ -9399,7 +9366,6 @@ }, /obj/effect/turf_decal/delivery, /obj/structure/closet/crate/engineering, -/obj/item/hand_tele, /turf/open/floor/plasteel/dark, /area/teleporter) "apw" = ( @@ -9560,7 +9526,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/item/gun/energy/e_gun/advtaser, /turf/open/floor/plasteel/dark, /area/security/brig) @@ -9586,11 +9551,8 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/structure/rack, -/obj/item/storage/toolbox/emergency, -/obj/item/wrench, -/obj/item/stack/packageWrap, -/obj/item/hand_labeler, +/obj/structure/table, +/obj/item/hand_tele, /turf/open/floor/plasteel/dark, /area/teleporter) "apL" = ( @@ -9697,7 +9659,6 @@ /area/bridge) "apU" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, /obj/structure/closet/firecloset, /turf/open/floor/plating, /area/maintenance/port/fore) @@ -9715,7 +9676,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer1{ dir = 8 @@ -11430,7 +11390,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/structure/cable{ icon_state = "1-2" }, @@ -12746,7 +12705,6 @@ /turf/open/floor/plating, /area/crew_quarters/heads/hop) "auH" = ( -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/structure/closet/firecloset, /turf/open/floor/plating, @@ -13040,7 +12998,6 @@ /turf/open/floor/plasteel/dark, /area/maintenance/port/fore) "avm" = ( -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/structure/closet/emcloset, /turf/open/floor/plating, @@ -13665,7 +13622,6 @@ /turf/open/floor/plating, /area/maintenance/port/fore) "awf" = ( -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/item/storage/backpack/cultpack{ pixel_x = 4; @@ -13709,7 +13665,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/item/gun/energy/e_gun/advtaser, /turf/open/floor/plasteel/dark, @@ -14536,7 +14491,6 @@ /turf/open/floor/grass, /area/medical/genetics) "axD" = ( -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/structure/closet{ name = "skirt closet" @@ -14899,7 +14853,6 @@ /area/engine/break_room) "ayl" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, /obj/structure/closet/l3closet/virology, /turf/open/floor/plating, /area/maintenance/starboard) @@ -16498,7 +16451,6 @@ /area/science/robotics/lab) "aAG" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, /obj/structure/closet, /obj/item/storage/backpack/duffelbag{ pixel_y = 4 @@ -16835,12 +16787,10 @@ /area/engine/engineering) "aBh" = ( /obj/structure/closet/secure_closet/RD, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, /obj/effect/turf_decal/tile/neutral, -/obj/item/gun/energy/e_gun/mini, /obj/structure/extinguisher_cabinet{ pixel_y = 28 }, @@ -17956,7 +17906,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/delivery, /obj/machinery/light{ dir = 1 }, @@ -19296,7 +19245,6 @@ /turf/open/floor/engine/vacuum, /area/engine/atmos) "aFg" = ( -/obj/effect/turf_decal/delivery, /obj/structure/closet/radiation, /obj/item/clothing/glasses/meson, /obj/machinery/power/apc/highcap/ten_k{ @@ -19527,7 +19475,6 @@ name = "Labor Shuttle Dock APC"; pixel_x = -26 }, -/obj/effect/turf_decal/bot, /obj/structure/closet/secure_closet/evidence, /turf/open/floor/plasteel/dark, /area/security/processing) @@ -19590,7 +19537,6 @@ /area/maintenance/starboard) "aFF" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, /obj/structure/closet/emcloset, /turf/open/floor/plating, /area/maintenance/starboard) @@ -20044,7 +19990,6 @@ /obj/effect/turf_decal/tile/yellow, /obj/machinery/portable_atmospherics/scrubber, /obj/machinery/atmospherics/components/unary/portables_connector/visible, -/obj/effect/turf_decal/box, /turf/open/floor/plasteel/showroomfloor, /area/engine/atmos) "aGx" = ( @@ -20543,7 +20488,6 @@ "aHv" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/closet/secure_closet/exile, -/obj/effect/turf_decal/bot, /obj/machinery/light_switch{ pixel_y = -24 }, @@ -20985,7 +20929,6 @@ /turf/open/floor/plating, /area/maintenance/port/fore) "aId" = ( -/obj/effect/turf_decal/delivery, /obj/structure/closet/secure_closet/CMO, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ @@ -20998,7 +20941,6 @@ /obj/structure/extinguisher_cabinet{ pixel_x = -26 }, -/obj/item/gun/energy/e_gun/mini, /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/cmo) "aIe" = ( @@ -23366,7 +23308,6 @@ /turf/open/floor/plasteel/showroomfloor, /area/science/mixing) "aLT" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet, /obj/item/clothing/under/rank/bartender/purple{ pixel_x = 4; @@ -23545,7 +23486,6 @@ /area/science/mixing/chamber) "aMh" = ( /obj/structure/closet/secure_closet/security/engine, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -23983,7 +23923,6 @@ /area/storage/tech) "aMK" = ( /obj/effect/landmark/secequipment, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -24086,21 +24025,11 @@ }, /area/hallway/primary/fore) "aMV" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ +/obj/effect/turf_decal/loading_area{ dir = 1 }, -/obj/effect/turf_decal/tile/yellow, -/obj/machinery/portable_atmospherics/pump, -/obj/machinery/atmospherics/components/unary/portables_connector/visible, -/obj/effect/turf_decal/box, -/turf/open/floor/plasteel/showroomfloor, -/area/engine/atmos) +/turf/closed/wall/r_wall, +/area/maintenance/port/aft) "aMW" = ( /obj/structure/reflector/single/anchored{ dir = 9 @@ -24374,7 +24303,6 @@ "aNs" = ( /obj/structure/closet/cardboard, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -25158,7 +25086,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/turf_decal/bot, /obj/structure/sign/warning/securearea{ name = "EMERGENCY STORAGE"; pixel_y = -32 @@ -25963,7 +25890,6 @@ /obj/structure/closet/secure_closet/medical3, /obj/item/storage/belt/medical, /obj/item/clothing/neck/stethoscope, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, @@ -26298,7 +26224,6 @@ /obj/structure/closet/secure_closet/medical3, /obj/item/storage/belt/medical, /obj/item/clothing/neck/stethoscope, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, @@ -27142,7 +27067,6 @@ pixel_x = -24; pixel_y = 24 }, -/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel/dark, /area/security/checkpoint/science/research) "aRA" = ( @@ -27370,7 +27294,6 @@ /turf/open/floor/plasteel/dark, /area/medical/chemistry) "aRP" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet{ name = "medical locker" }, @@ -27652,7 +27575,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/delivery, /obj/item/radio/intercom{ pixel_y = 22 }, @@ -31346,7 +31268,6 @@ /turf/open/floor/plasteel/dark, /area/science/mixing) "aXB" = ( -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -33468,7 +33389,6 @@ /area/science/mixing) "baT" = ( /obj/structure/closet/secure_closet/security/med, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -34857,7 +34777,6 @@ /turf/open/floor/plating, /area/maintenance/central) "bcZ" = ( -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -35287,7 +35206,6 @@ /turf/open/floor/engine, /area/science/xenobiology) "bdE" = ( -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/structure/closet{ name = "kitchen closet" @@ -36156,7 +36074,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/turf_decal/bot, /obj/structure/closet/firecloset, /turf/open/floor/plasteel/dark, /area/hallway/primary/starboard) @@ -36305,7 +36222,6 @@ /area/maintenance/port) "bfc" = ( /obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/effect/turf_decal/bot, /obj/structure/closet/l3closet, /turf/open/floor/plasteel/dark, /area/maintenance/port) @@ -36467,7 +36383,6 @@ /obj/structure/cable{ icon_state = "0-2" }, -/obj/effect/turf_decal/box, /obj/machinery/light{ dir = 1 }, @@ -38196,7 +38111,6 @@ /turf/open/floor/plating, /area/maintenance/port) "bib" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet/l3closet, /turf/open/floor/plasteel/dark, /area/maintenance/port) @@ -38400,7 +38314,6 @@ /area/medical/virology) "biq" = ( /obj/structure/closet/wardrobe/miner, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -38458,7 +38371,6 @@ /turf/open/floor/plasteel/dark, /area/quartermaster/miningoffice) "biu" = ( -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -38902,7 +38814,6 @@ /area/quartermaster/qm) "bja" = ( /obj/structure/closet/secure_closet/quartermaster, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -39184,7 +39095,6 @@ /area/quartermaster/office) "bju" = ( /obj/structure/closet/secure_closet/miner, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -39196,7 +39106,6 @@ /area/quartermaster/miningoffice) "bjv" = ( /obj/structure/closet/secure_closet/miner, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -40003,7 +39912,6 @@ /area/security/checkpoint/supply) "bkK" = ( /obj/structure/closet/secure_closet/miner, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -41261,8 +41169,12 @@ /turf/open/floor/plasteel/dark, /area/hallway/primary/aft) "bmA" = ( -/obj/machinery/smartfridge, -/turf/closed/wall, +/obj/structure/table/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Serving Hatch" + }, +/turf/open/floor/plating, /area/crew_quarters/kitchen) "bmB" = ( /obj/machinery/status_display/evac, @@ -41325,7 +41237,6 @@ /turf/open/floor/plasteel/dark, /area/hydroponics) "bmH" = ( -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -41465,7 +41376,6 @@ id = "kitchen_2"; name = "Hallway Hatch" }, -/obj/structure/window/reinforced, /turf/open/floor/plating, /area/crew_quarters/kitchen) "bmT" = ( @@ -41663,7 +41573,6 @@ "bnk" = ( /obj/structure/disposalpipe/segment, /obj/structure/closet/wardrobe/white, -/obj/effect/turf_decal/bot, /turf/open/floor/plasteel/dark, /area/crew_quarters/locker) "bnl" = ( @@ -41762,7 +41671,6 @@ /turf/open/floor/grass, /area/hydroponics) "bnr" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet/secure_closet/personal, /obj/item/storage/backpack, /obj/item/storage/backpack/satchel, @@ -42556,7 +42464,6 @@ /turf/open/floor/plating, /area/maintenance/central) "boz" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet/secure_closet/hydroponics, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -42721,7 +42628,6 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/kitchen) "boJ" = ( -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -42801,7 +42707,6 @@ "boO" = ( /obj/structure/disposalpipe/segment, /obj/structure/closet/wardrobe/grey, -/obj/effect/turf_decal/bot, /obj/machinery/light{ dir = 8 }, @@ -42841,7 +42746,6 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/kitchen) "boR" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet/secure_closet/personal, /obj/item/storage/backpack, /obj/item/storage/backpack/satchel, @@ -42970,7 +42874,6 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/kitchen) "bpc" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet/firecloset, /turf/open/floor/plating, /area/maintenance/port) @@ -43138,7 +43041,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/effect/turf_decal/delivery, /obj/structure/closet/firecloset, /turf/open/floor/plasteel/dark, /area/hallway/primary/port) @@ -43448,7 +43350,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/effect/turf_decal/delivery, /obj/structure/closet/emcloset, /turf/open/floor/plasteel/dark, /area/hallway/primary/port) @@ -44133,7 +44034,6 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/kitchen) "bqQ" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet/secure_closet/hydroponics, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -45527,7 +45427,6 @@ /area/crew_quarters/bar) "bsV" = ( /obj/structure/closet/secure_closet/security/cargo, -/obj/effect/turf_decal/delivery, /obj/item/crowbar, /obj/item/book/manual/wiki/security_space_law, /obj/effect/turf_decal/tile/neutral, @@ -47528,7 +47427,6 @@ }, /area/hallway/primary/port) "bwg" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet, /obj/item/stack/rods/ten, /obj/item/stock_parts/matter_bin, @@ -49072,7 +48970,6 @@ dir = 8 }, /obj/structure/closet/secure_closet/captains, -/obj/effect/turf_decal/delivery, /obj/machinery/airalarm{ dir = 8; pixel_x = 24 @@ -49082,7 +48979,6 @@ "byF" = ( /obj/structure/closet/secure_closet/engineering_personal, /obj/item/clothing/suit/hooded/wintercoat/engineering, -/obj/effect/turf_decal/delivery, /obj/machinery/newscaster{ pixel_y = 30 }, @@ -49364,7 +49260,6 @@ "byZ" = ( /obj/structure/disposalpipe/segment, /obj/structure/closet/wardrobe/black, -/obj/effect/turf_decal/bot, /obj/item/clothing/under/trendy_fit, /obj/item/clothing/under/trendy_fit, /turf/open/floor/plasteel/dark, @@ -49536,7 +49431,6 @@ /turf/open/floor/plating, /area/ai_monitored/turret_protected/ai_upload) "bzn" = ( -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -52750,7 +52644,6 @@ dir = 1 }, /obj/structure/closet/secure_closet/hop, -/obj/effect/turf_decal/bot, /obj/machinery/airalarm{ dir = 4; pixel_x = -22 @@ -53093,7 +52986,6 @@ dir = 1 }, /obj/structure/closet/firecloset, -/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel/dark, /area/hallway/primary/aft) "bEM" = ( @@ -54624,7 +54516,6 @@ dir = 1 }, /obj/structure/closet/emcloset, -/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel/dark, /area/hallway/primary/aft) "bHn" = ( @@ -56582,10 +56473,6 @@ pixel_x = -4; pixel_y = 4 }, -/obj/item/megaphone{ - pixel_x = 4; - pixel_y = 4 - }, /obj/item/pen, /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/effect/turf_decal/tile/neutral{ @@ -56669,7 +56556,6 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/structure/sink{ dir = 8; pixel_x = -12; @@ -56682,7 +56568,6 @@ dir = 1 }, /obj/effect/decal/cleanable/cobweb, -/obj/effect/decal/cleanable/blood/gibs/limb, /obj/machinery/atmospherics/components/unary/vent_pump/on, /turf/open/floor/plasteel/showroomfloor, /area/security/prison) @@ -56745,7 +56630,6 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/machinery/door_timer{ id = "Cell 3"; name = "Cell 3"; @@ -56765,7 +56649,6 @@ /turf/open/floor/plasteel/dark, /area/security/warden) "bKA" = ( -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/structure/closet{ name = "detective closet" @@ -56828,7 +56711,6 @@ /area/crew_quarters/locker) "bKD" = ( /obj/structure/closet/boxinggloves, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, @@ -56867,7 +56749,6 @@ /area/crew_quarters/toilet/restrooms) "bKH" = ( /obj/structure/closet/masks, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, @@ -56939,7 +56820,6 @@ /area/maintenance/port/aft) "bKN" = ( /obj/structure/closet/athletic_mixed, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, @@ -56957,7 +56837,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/turf_decal/bot, /obj/structure/closet/emcloset, /obj/structure/sign/warning/securearea{ name = "EMERGENCY STORAGE"; @@ -57772,7 +57651,6 @@ }, /obj/effect/decal/cleanable/blood/old, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/remains/human, /obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/machinery/airalarm{ dir = 1; @@ -58252,12 +58130,12 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "bMz" = ( -/obj/machinery/computer/prisoner, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, /obj/effect/turf_decal/bot, +/obj/machinery/computer/prisoner, /turf/open/floor/plasteel/dark, /area/security/prison) "bMA" = ( @@ -59029,7 +58907,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/machinery/light/small{ dir = 8 }, @@ -59911,7 +59788,6 @@ "bPa" = ( /obj/structure/flora/ausbushes/ywflowers, /obj/effect/decal/cleanable/blood/old, -/mob/living/simple_animal/butterfly, /turf/open/floor/grass, /area/security/prison) "bPb" = ( @@ -60030,7 +59906,6 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/structure/sink{ dir = 8; pixel_x = -12; @@ -61759,7 +61634,6 @@ /obj/structure/closet/secure_closet/brig{ name = "Prisoner Locker" }, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -61781,7 +61655,6 @@ /area/hallway/secondary/exit/departure_lounge) "bRG" = ( /obj/structure/closet/secure_closet/warden, -/obj/effect/turf_decal/delivery, /obj/machinery/power/apc/highcap/five_k{ areastring = "/area/security/warden"; dir = 8; @@ -61818,7 +61691,6 @@ /obj/structure/closet/secure_closet/brig{ name = "Prisoner Locker" }, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -61842,7 +61714,6 @@ /obj/structure/closet/secure_closet/brig{ name = "Prisoner Locker" }, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -62701,7 +62572,6 @@ /obj/structure/closet/l3closet/security, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, @@ -62750,7 +62620,6 @@ "bTa" = ( /obj/structure/closet/secure_closet/evidence, /obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/bot, /obj/machinery/light/small{ dir = 1 }, @@ -63117,7 +62986,6 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/structure/sink{ dir = 8; pixel_x = -12; @@ -63195,7 +63063,6 @@ /turf/open/floor/plasteel/showroomfloor, /area/security/prison) "bTL" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet{ name = "security locker" }, @@ -63673,7 +63540,6 @@ }, /area/hallway/primary/aft) "bUB" = ( -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -64158,8 +64024,6 @@ dir = 4 }, /obj/effect/turf_decal/tile/neutral, -/obj/effect/decal/cleanable/blood/old, -/obj/effect/decal/cleanable/blood/gibs/limb, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -64492,7 +64356,6 @@ "bVP" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/closet/bombcloset/security, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, @@ -64845,7 +64708,6 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/machinery/door_timer{ id = "Cell 6"; name = "Cell 6"; @@ -64896,7 +64758,6 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/machinery/door_timer{ id = "Cell 5"; name = "Cell 5"; @@ -64915,7 +64776,6 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/machinery/door_timer{ id = "Cell 4"; name = "Cell 4"; @@ -65068,7 +64928,6 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/machinery/door_timer{ id = "Cell 2"; name = "Cell 2"; @@ -65093,7 +64952,6 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/machinery/door_timer{ id = "Cell 1"; name = "Cell 1"; @@ -67208,7 +67066,6 @@ /turf/open/floor/plasteel/dark/corner, /area/hallway/primary/starboard) "bZL" = ( -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -67288,7 +67145,6 @@ "bZQ" = ( /obj/structure/closet/l3closet/janitor, /obj/structure/window/reinforced, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -68259,8 +68115,6 @@ /area/maintenance/starboard) "cbo" = ( /obj/structure/closet/secure_closet/engineering_chief, -/obj/effect/turf_decal/delivery, -/obj/item/gun/energy/e_gun/mini, /obj/structure/extinguisher_cabinet{ pixel_x = 24 }, @@ -68965,7 +68819,7 @@ /area/maintenance/starboard) "ccv" = ( /obj/structure/sign/warning/securearea, -/turf/closed/wall, +/turf/closed/wall/r_wall, /area/security/main) "ccw" = ( /obj/effect/turf_decal/tile/yellow{ @@ -69011,7 +68865,6 @@ /turf/closed/mineral/random/labormineral, /area/space/nearstation) "ccB" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet/firecloset, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/dark, @@ -69644,7 +69497,6 @@ }, /obj/effect/turf_decal/tile/red, /obj/structure/closet/secure_closet/engineering_electrical, -/obj/effect/turf_decal/box, /turf/open/floor/plasteel, /area/engine/break_room) "cdO" = ( @@ -70940,7 +70792,6 @@ /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/red, /obj/structure/closet/secure_closet/engineering_welding, -/obj/effect/turf_decal/box, /turf/open/floor/plasteel, /area/engine/break_room) "cfI" = ( @@ -71072,7 +70923,6 @@ /turf/closed/wall/r_wall/rust, /area/ai_monitored/storage/satellite) "cgb" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet/emcloset, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/dark, @@ -71177,7 +71027,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/crew_quarters/heads/hos) "cgq" = ( @@ -71591,7 +71440,6 @@ "cgW" = ( /obj/structure/closet/secure_closet/engineering_personal, /obj/item/clothing/suit/hooded/wintercoat/engineering, -/obj/effect/turf_decal/delivery, /obj/machinery/light{ dir = 1 }, @@ -71618,7 +71466,6 @@ "cgY" = ( /obj/structure/closet/crate/coffin, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -74485,7 +74332,6 @@ }, /area/maintenance/starboard) "clB" = ( -/obj/effect/turf_decal/delivery, /obj/structure/closet/radiation, /obj/item/clothing/glasses/meson, /turf/open/floor/plasteel/dark, @@ -74690,13 +74536,11 @@ /turf/closed/wall/r_wall, /area/engine/gravity_generator) "clV" = ( -/obj/effect/turf_decal/delivery, /obj/structure/closet/radiation, /obj/item/clothing/glasses/meson, /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) "clW" = ( -/obj/effect/turf_decal/delivery, /obj/structure/closet/radiation, /obj/item/clothing/glasses/meson, /obj/machinery/power/apc{ @@ -75556,7 +75400,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/machinery/firealarm{ dir = 4; @@ -78861,6 +78704,9 @@ }, /obj/structure/barricade/wooden/crude, /obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/loading_area{ + dir = 1 + }, /turf/open/floor/plasteel/dark, /area/maintenance/port/fore) "ctj" = ( @@ -80488,6 +80334,9 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, +/obj/effect/turf_decal/loading_area{ + dir = 1 + }, /turf/open/floor/plasteel/dark, /area/maintenance/port/fore) "cwh" = ( @@ -80500,6 +80349,9 @@ icon_state = "1-2" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/loading_area{ + dir = 1 + }, /turf/open/floor/plasteel/dark, /area/maintenance/port/fore) "cwi" = ( @@ -80885,6 +80737,9 @@ }, /obj/structure/barricade/wooden/crude, /obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/loading_area{ + dir = 1 + }, /turf/open/floor/plasteel/dark, /area/maintenance/port/fore) "cwR" = ( @@ -80893,7 +80748,6 @@ }, /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, /obj/structure/closet, /obj/item/stack/packageWrap, /obj/item/storage/bag/trash, @@ -81247,7 +81101,6 @@ }, /area/maintenance/port/fore) "cxL" = ( -/obj/effect/turf_decal/bot, /obj/structure/closet{ name = "engineering locker" }, @@ -81526,6 +81379,9 @@ "cyu" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/barricade/wooden/crude, +/obj/effect/turf_decal/loading_area{ + dir = 1 + }, /turf/open/floor/plating{ icon_state = "platingdmg3" }, @@ -81558,7 +81414,6 @@ /turf/closed/wall, /area/maintenance/port/aft) "cyz" = ( -/obj/effect/turf_decal/bot, /obj/structure/rack, /obj/item/crowbar/red, /obj/item/restraints/handcuffs, @@ -82027,7 +81882,6 @@ /obj/structure/closet/crate/coffin, /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, @@ -82044,6 +81898,9 @@ /obj/structure/cable{ icon_state = "1-2" }, +/obj/effect/turf_decal/loading_area{ + dir = 1 + }, /turf/open/floor/plasteel/dark, /area/maintenance/port/fore) "czL" = ( @@ -82053,6 +81910,9 @@ /obj/structure/barricade/wooden/crude, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1, +/obj/effect/turf_decal/loading_area{ + dir = 1 + }, /turf/open/floor/plasteel/dark, /area/maintenance/port/fore) "czP" = ( @@ -82186,7 +82046,6 @@ "cAi" = ( /obj/structure/closet/crate/coffin, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -82204,7 +82063,6 @@ "cAk" = ( /obj/structure/closet/crate/coffin, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, @@ -82219,7 +82077,6 @@ /turf/open/floor/plasteel/dark, /area/chapel/office) "cAo" = ( -/obj/effect/turf_decal/bot, /obj/structure/frame/computer{ anchored = 1 }, @@ -82234,7 +82091,6 @@ /turf/closed/wall/rust, /area/chapel/office) "cAq" = ( -/obj/effect/turf_decal/bot, /obj/structure/frame/computer{ anchored = 1 }, @@ -82553,7 +82409,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/machinery/light{ dir = 8 }, @@ -82902,7 +82757,6 @@ "cCr" = ( /obj/effect/decal/cleanable/cobweb, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -82931,7 +82785,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/item/clothing/gloves/color/white, /obj/item/clothing/under/maid{ @@ -83807,7 +83660,6 @@ "cEB" = ( /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -85018,8 +84870,10 @@ }, /area/maintenance/aft) "cIe" = ( -/obj/machinery/door/airlock/maintenance{ - name = "xenobiology maintenance"; +/obj/machinery/door/airlock/research{ + glass = 1; + name = "Slime Euthanization Chamber"; + opacity = 0; req_access_txt = "55" }, /turf/open/floor/plasteel/dark, @@ -86190,7 +86044,6 @@ /obj/machinery/light/small{ dir = 1 }, -/obj/effect/turf_decal/bot, /turf/open/floor/plating, /area/maintenance/starboard/aft) "cKY" = ( @@ -87349,10 +87202,6 @@ "dis" = ( /turf/closed/wall/r_wall/rust, /area/bridge) -"dww" = ( -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating/asteroid/airless, -/area/space/nearstation) "dxq" = ( /obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral{ @@ -88060,8 +87909,13 @@ /turf/closed/wall/rust, /area/crew_quarters/heads/hor) "nJw" = ( -/obj/machinery/smartfridge, -/turf/closed/wall/rust, +/obj/structure/table/reinforced, +/obj/machinery/door/firedoor, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Serving Hatch" + }, +/turf/open/floor/plating, /area/crew_quarters/kitchen) "nNA" = ( /turf/closed/wall/rust, @@ -106127,10 +105981,10 @@ cDB cfb aey ajx +aMV +ajx +ajx ajx -ajd -ajd -ajd anZ cmt cko @@ -118204,7 +118058,7 @@ bGJ cdr bGG awu -aMV +cgF chz ciA aGl From f5d2a048332e12691aa726fd77bd909b3ca8694b Mon Sep 17 00:00:00 2001 From: keronshb Date: Wed, 11 Mar 2020 17:33:27 -0400 Subject: [PATCH 17/61] Ports Blob Buffs Ports blob buffs from TG --- code/__DEFINES/antagonists.dm | 5 +++-- .../antagonists/blob/blob/blobs/shield.dm | 2 +- code/modules/antagonists/blob/blob/powers.dm | 19 ++++++++++--------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index 7a3f872666..145055206c 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -74,6 +74,7 @@ #define MARTIALART_HUNTER "hunter-fu" //Blob -/// blob gets a free reroll every X time -#define BLOB_REROLL_TIME 2400 +#define BLOB_REROLL_TIME 2400 // blob gets a free reroll every X time +#define BLOB_SPREAD_COST 4 +#define BLOB_ATTACK_REFUND 2 //blob refunds this much if it attacks and doesn't spread #define BLOB_REFLECTOR_COST 15 \ No newline at end of file diff --git a/code/modules/antagonists/blob/blob/blobs/shield.dm b/code/modules/antagonists/blob/blob/blobs/shield.dm index 481c5e6c8d..bc4e517ced 100644 --- a/code/modules/antagonists/blob/blob/blobs/shield.dm +++ b/code/modules/antagonists/blob/blob/blobs/shield.dm @@ -47,7 +47,7 @@ icon_state = "blob_glow" flags_1 = CHECK_RICOCHET_1 point_return = 8 - max_integrity = 50 + max_integrity = 100 brute_resist = 1 explosion_block = 2 diff --git a/code/modules/antagonists/blob/blob/powers.dm b/code/modules/antagonists/blob/blob/powers.dm index 641019ef33..947a12fabc 100644 --- a/code/modules/antagonists/blob/blob/powers.dm +++ b/code/modules/antagonists/blob/blob/powers.dm @@ -120,13 +120,13 @@ /mob/camera/blob/proc/create_shield(turf/T) var/obj/structure/blob/shield/S = locate(/obj/structure/blob/shield) in T if(S) - if(!can_buy(15)) + if(!can_buy(BLOB_REFLECTOR_COST)) return if(S.obj_integrity < S.max_integrity * 0.5) add_points(BLOB_REFLECTOR_COST) to_chat(src, "This shield blob is too damaged to be modified properly!") return - to_chat(src, "You secrete a reflective ooze over the shield blob, allowing it to reflect projectiles at the cost of reduced intregrity.") + to_chat(src, "You secrete a reflective ooze over the shield blob, allowing it to reflect projectiles at the cost of reduced integrity.") S.change_to(/obj/structure/blob/shield/reflective, src) else createSpecial(15, /obj/structure/blob/shield, 0, 0, T) @@ -247,8 +247,8 @@ /mob/camera/blob/verb/expand_blob_power() set category = "Blob" - set name = "Expand/Attack Blob (4)" - set desc = "Attempts to create a new blob in this tile. If the tile isn't clear, instead attacks it, damaging mobs and objects." + set name = "Expand/Attack Blob ([BLOB_SPREAD_COST])" + set desc = "Attempts to create a new blob in this tile. If the tile isn't clear, instead attacks it, damaging mobs and objects and refunding [BLOB_ATTACK_REFUND] points." var/turf/T = get_turf(src) expand_blob(T) @@ -261,7 +261,7 @@ if(!possibleblobs.len) to_chat(src, "There is no blob adjacent to the target tile!") return - if(can_buy(4)) + if(can_buy(BLOB_SPREAD_COST)) var/attacksuccess = FALSE for(var/mob/living/L in T) if(ROLE_BLOB in L.faction) //no friendly/dead fire @@ -271,11 +271,11 @@ blobstrain.attack_living(L) var/obj/structure/blob/B = locate() in T if(B) - if(attacksuccess) //if we successfully attacked a turf with a blob on it, don't refund shit + if(attacksuccess) //if we successfully attacked a turf with a blob on it, only give an attack refund B.blob_attack_animation(T, src) else to_chat(src, "There is a blob there!") - add_points(4) //otherwise, refund all of the cost + add_points(BLOB_SPREAD_COST) //otherwise, refund all of the cost else var/list/cardinalblobs = list() var/list/diagonalblobs = list() @@ -288,14 +288,15 @@ var/obj/structure/blob/OB if(cardinalblobs.len) OB = pick(cardinalblobs) - OB.expand(T, src) + if(!OB.expand(T, src)) + add_points(BLOB_ATTACK_REFUND) //assume it's attacked SOMETHING, possibly a structure else OB = pick(diagonalblobs) if(attacksuccess) OB.blob_attack_animation(T, src) playsound(OB, 'sound/effects/splat.ogg', 50, 1) else - add_points(4) //if we're attacking diagonally and didn't hit anything, refund + add_points(BLOB_SPREAD_COST) //if we're attacking diagonally and didn't hit anything, refund if(attacksuccess) last_attack = world.time + CLICK_CD_MELEE else From 148e935c4144efd455596ad4069c05c8cb9f0718 Mon Sep 17 00:00:00 2001 From: keronshb Date: Wed, 11 Mar 2020 17:39:08 -0400 Subject: [PATCH 18/61] Fixes jump to node ports this fix too --- code/modules/antagonists/blob/blob/powers.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/antagonists/blob/blob/powers.dm b/code/modules/antagonists/blob/blob/powers.dm index 947a12fabc..73d0c97476 100644 --- a/code/modules/antagonists/blob/blob/powers.dm +++ b/code/modules/antagonists/blob/blob/powers.dm @@ -71,7 +71,7 @@ var/list/nodes = list() for(var/i in 1 to GLOB.blob_nodes.len) var/obj/structure/blob/node/B = GLOB.blob_nodes[i] - nodes["Blob Node #[i] ([B.overmind ? "[B.overmind.blobstrain.name]":"No Strain"])"] = B + nodes["Blob Node #[i] ([get_area_name(B)])"] = B var/node_name = input(src, "Choose a node to jump to.", "Node Jump") in nodes var/obj/structure/blob/node/chosen_node = nodes[node_name] if(chosen_node) From 0876a1eef65451b8cf7ff47159b8bff0439f76da Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 12 Mar 2020 18:22:26 +0100 Subject: [PATCH 19/61] Porting datum components system updates. --- code/__DEFINES/dcs/flags.dm | 41 +++ code/__DEFINES/dcs/helpers.dm | 16 ++ .../{components.dm => dcs/signals.dm} | 38 --- code/controllers/subsystem/dcs.dm | 50 +++- code/datums/components/README.md | 130 +-------- code/datums/components/_component.dm | 264 +++++++++++++++--- code/datums/components/fantasy/_fantasy.dm | 17 +- code/datums/components/nanites.dm | 4 +- code/datums/components/orbiter.dm | 6 +- code/datums/components/radioactive.dm | 4 +- code/datums/components/remote_materials.dm | 20 +- code/datums/components/stationloving.dm | 8 +- code/datums/components/thermite.dm | 4 +- code/datums/components/wet_floor.dm | 4 +- code/datums/datum.dm | 53 +++- code/datums/elements/_element.dm | 26 +- code/datums/elements/mob_holder.dm | 14 +- code/datums/materials/basemats.dm | 4 +- code/game/machinery/autolathe.dm | 9 +- code/game/machinery/toylathe.dm | 7 +- code/game/mecha/mech_fabricator.dm | 16 +- .../objects/structures/windoor_assembly.dm | 9 +- code/modules/assembly/infrared.dm | 9 +- .../subtypes/manipulation.dm | 19 +- .../mapping_helpers/_mapping_helpers.dm | 2 +- code/modules/mining/machine_silo.dm | 22 +- .../mob/living/carbon/monkey/monkey.dm | 2 +- .../mob/living/silicon/pai/pai_shell.dm | 3 +- .../living/simple_animal/friendly/lizard.dm | 2 +- .../nanites/nanite_cloud_controller.dm | 6 +- tgstation.dme | 4 +- 31 files changed, 504 insertions(+), 309 deletions(-) create mode 100644 code/__DEFINES/dcs/flags.dm create mode 100644 code/__DEFINES/dcs/helpers.dm rename code/__DEFINES/{components.dm => dcs/signals.dm} (94%) diff --git a/code/__DEFINES/dcs/flags.dm b/code/__DEFINES/dcs/flags.dm new file mode 100644 index 0000000000..128c9f1938 --- /dev/null +++ b/code/__DEFINES/dcs/flags.dm @@ -0,0 +1,41 @@ +/// Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. +/// `parent` must not be modified if this is to be returned. +/// This will be noted in the runtime logs +#define COMPONENT_INCOMPATIBLE 1 +/// Returned in PostTransfer to prevent transfer, similar to `COMPONENT_INCOMPATIBLE` +#define COMPONENT_NOTRANSFER 2 + +/// Return value to cancel attaching +#define ELEMENT_INCOMPATIBLE 1 + +// /datum/element flags +/// Causes the detach proc to be called when the host object is being deleted +#define ELEMENT_DETACH (1 << 0) +/** + * Only elements created with the same arguments given after `id_arg_index` share an element instance + * The arguments are the same when the text and number values are the same and all other values have the same ref + */ +#define ELEMENT_BESPOKE (1 << 1) + +// How multiple components of the exact same type are handled in the same datum +/// old component is deleted (default) +#define COMPONENT_DUPE_HIGHLANDER 0 +/// duplicates allowed +#define COMPONENT_DUPE_ALLOWED 1 +/// new component is deleted +#define COMPONENT_DUPE_UNIQUE 2 +/// old component is given the initialization args of the new +#define COMPONENT_DUPE_UNIQUE_PASSARGS 4 +/// each component of the same type is consulted as to whether the duplicate should be allowed +#define COMPONENT_DUPE_SELECTIVE 5 + +//Redirection component init flags +#define REDIRECT_TRANSFER_WITH_TURF 1 + +//Arch +#define ARCH_PROB "probability" //Probability for each item +#define ARCH_MAXDROP "max_drop_amount" //each item's max drop amount + +//Ouch my toes! +#define CALTROP_BYPASS_SHOES 1 +#define CALTROP_IGNORE_WALKERS 2 diff --git a/code/__DEFINES/dcs/helpers.dm b/code/__DEFINES/dcs/helpers.dm new file mode 100644 index 0000000000..b13530cdf7 --- /dev/null +++ b/code/__DEFINES/dcs/helpers.dm @@ -0,0 +1,16 @@ +/// Used to trigger signals and call procs registered for that signal +/// The datum hosting the signal is automaticaly added as the first argument +/// Returns a bitfield gathered from all registered procs +/// Arguments given here are packaged in a list and given to _SendSignal +#define SEND_SIGNAL(target, sigtype, arguments...) ( !target.comp_lookup || !target.comp_lookup[sigtype] ? NONE : target._SendSignal(sigtype, list(target, ##arguments)) ) + +#define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) ) + +/// A wrapper for _AddElement that allows us to pretend we're using normal named arguments +#define AddElement(arguments...) _AddElement(list(##arguments)) + +/// A wrapper for _RemoveElement that allows us to pretend we're using normal named arguments +#define RemoveElement(arguments...) _RemoveElement(list(##arguments)) + +/// A wrapper for _AddComponent that allows us to pretend we're using normal named arguments +#define AddComponent(arguments...) _AddComponent(list(##arguments)) \ No newline at end of file diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/dcs/signals.dm similarity index 94% rename from code/__DEFINES/components.dm rename to code/__DEFINES/dcs/signals.dm index 3b01e3b9d4..c4e57154c2 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -1,28 +1,3 @@ -#define SEND_SIGNAL(target, sigtype, arguments...) ( !target.comp_lookup || !target.comp_lookup[sigtype] ? NONE : target._SendSignal(sigtype, list(target, ##arguments)) ) - -#define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) ) - -#define COMPONENT_INCOMPATIBLE 1 -#define COMPONENT_NOTRANSFER 2 - -#define ELEMENT_INCOMPATIBLE 1 // Return value to cancel attaching - -// /datum/element flags -/// Causes the detach proc to be called when the host object is being deleted -#define ELEMENT_DETACH (1 << 0) -/** - * Only elements created with the same arguments given after `id_arg_index` share an element instance - * The arguments are the same when the text and number values are the same and all other values have the same ref - */ -#define ELEMENT_BESPOKE (1 << 1) - -// How multiple components of the exact same type are handled in the same datum - -#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default) -#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed -#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted -#define COMPONENT_DUPE_UNIQUE_PASSARGS 4 //old component is given the initialization args of the new - // All signals. Format: // When the signal is called: (signal arguments) // All signals send the source datum of the signal as the first argument @@ -359,19 +334,6 @@ #define COMSIG_ACTION_TRIGGER "action_trigger" //from base of datum/action/proc/Trigger(): (datum/action) #define COMPONENT_ACTION_BLOCK_TRIGGER 1 -/*******Non-Signal Component Related Defines*******/ - -//Redirection component init flags -#define REDIRECT_TRANSFER_WITH_TURF 1 - -//Arch -#define ARCH_PROB "probability" //Probability for each item -#define ARCH_MAXDROP "max_drop_amount" //each item's max drop amount - -//Ouch my toes! -#define CALTROP_BYPASS_SHOES 1 -#define CALTROP_IGNORE_WALKERS 2 - //Xenobio hotkeys #define COMSIG_XENO_SLIME_CLICK_CTRL "xeno_slime_click_ctrl" //from slime CtrlClickOn(): (/mob) #define COMSIG_XENO_SLIME_CLICK_ALT "xeno_slime_click_alt" //from slime AltClickOn(): (/mob) diff --git a/code/controllers/subsystem/dcs.dm b/code/controllers/subsystem/dcs.dm index faf95fd319..8b068e5d67 100644 --- a/code/controllers/subsystem/dcs.dm +++ b/code/controllers/subsystem/dcs.dm @@ -1,27 +1,53 @@ PROCESSING_SUBSYSTEM_DEF(dcs) name = "Datum Component System" flags = SS_NO_INIT + var/list/elements_by_type = list() /datum/controller/subsystem/processing/dcs/Recover() comp_lookup = SSdcs.comp_lookup -/datum/controller/subsystem/processing/dcs/proc/GetElement(datum/element/eletype, ...) +/datum/controller/subsystem/processing/dcs/proc/GetElement(list/arguments) + var/datum/element/eletype = arguments[1] var/element_id = eletype + if(!ispath(eletype, /datum/element)) + CRASH("Attempted to instantiate [eletype] as a /datum/element") + 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("&") + element_id = GetIdFromArguments(arguments) . = 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 \ No newline at end of file + . = elements_by_type[element_id] = new eletype + +/**** + * Generates an id for bespoke elements when given the argument list + * Generating the id here is a bit complex because we need to support named arguments + * Named arguments can appear in any order and we need them to appear after ordered arguments + * We assume that no one will pass in a named argument with a value of null + **/ +/datum/controller/subsystem/processing/dcs/proc/GetIdFromArguments(list/arguments) + var/datum/element/eletype = arguments[1] + var/list/fullid = list("[eletype]") + var/list/named_arguments = list() + for(var/i in initial(eletype.id_arg_index) to length(arguments)) + var/key = arguments[i] + var/value + if(istext(key)) + value = arguments[key] + if(!(istext(key) || isnum(key))) + key = REF(key) + key = "[key]" // Key is stringified so numbers dont break things + if(!isnull(value)) + if(!(istext(value) || isnum(value))) + value = REF(value) + named_arguments["[key]"] = value + else + fullid += "[key]" + + if(length(named_arguments)) + named_arguments = sortList(named_arguments) + fullid += named_arguments + return list2params(fullid) diff --git a/code/datums/components/README.md b/code/datums/components/README.md index 05ce057721..509630bb0a 100644 --- a/code/datums/components/README.md +++ b/code/datums/components/README.md @@ -4,132 +4,6 @@ Loosely adapted from /vg/. This is an entity component system for adding behaviours to datums when inheritance doesn't quite cut it. By using signals and events instead of direct inheritance, you can inject behaviours without hacky overloads. It requires a different method of thinking, but is not hard to use correctly. If a behaviour can have application across more than one thing. Make it generic, make it a component. Atom/mob/obj event? Give it a signal, and forward it's arguments with a `SendSignal()` call. Now every component that want's to can also know about this happening. -### In the code +See [this thread](https://tgstation13.org/phpBB/viewtopic.php?f=5&t=22674) for an introduction to the system as a whole. -#### Slippery things - -At the time of this writing, every object that is slippery overrides atom/Crossed does some checks, then slips the mob. Instead of all those Crossed overrides they could add a slippery component to all these objects. And have the checks in one proc that is run by the Crossed event - -#### Powercells - -A lot of objects have powercells. The `get_cell()` proc was added to give generic access to the cell var if it had one. This is just a specific use case of `GetComponent()` - -#### Radios - -The radio object as it is should not exist, given that more things use the _concept_ of radios rather than the object itself. The actual function of the radio can exist in a component which all the things that use it (Request consoles, actual radios, the SM shard) can add to themselves. - -#### Standos - -Stands have a lot of procs which mimic mob procs. Rather than inserting hooks for all these procs in overrides, the same can be accomplished with signals - -## API - -### Defines - -1. `COMPONENT_INCOMPATIBLE` Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. `parent` must not be modified if this is to be returned. This will be noted in the runtime logs - -### Vars - -1. `/datum/var/list/datum_components` (private) - * Lazy associated list of type -> component/list of components. -1. `/datum/var/list/comp_lookup` (private) - * Lazy associated list of signal -> registree/list of registrees -1. `/datum/var/list/signal_procs` (private) - * Associated lazy list of signals -> `/datum/callback`s that will be run when the parent datum receives that signal -1. `/datum/var/signal_enabled` (protected, boolean) - * If the datum is signal enabled. If not, it will not react to signals - * `FALSE` by default, set to `TRUE` when a signal is registered -1. `/datum/component/var/dupe_mode` (protected, enum) - * How duplicate component types are handled when added to the datum. - * `COMPONENT_DUPE_HIGHLANDER` (default): Old component will be deleted, new component will first have `/datum/component/proc/InheritComponent(datum/component/old, FALSE)` on it - * `COMPONENT_DUPE_ALLOWED`: The components will be treated as separate, `GetComponent()` will return the first added - * `COMPONENT_DUPE_UNIQUE`: New component will be deleted, old component will first have `/datum/component/proc/InheritComponent(datum/component/new, TRUE)` on it - * `COMPONENT_DUPE_UNIQUE_PASSARGS`: New component will never exist and instead its initialization arguments will be passed on to the old component. -1. `/datum/component/var/dupe_type` (protected, type) - * Definition of a duplicate component type - * `null` means exact match on `type` (default) - * Any other type means that and all subtypes -1. `/datum/component/var/datum/parent` (protected, read-only) - * The datum this component belongs to - * Never `null` in child procs -1. `report_signal_origin` (protected, boolean) - * If `TRUE`, will invoke the callback when signalled with the signal type as the first argument. - * `FALSE` by default. - -### Procs - -1. `/datum/proc/GetComponent(component_type(type)) -> datum/component?` (public, final) - * Returns a reference to a component of component_type if it exists in the datum, null otherwise -1. `/datum/proc/GetComponents(component_type(type)) -> list` (public, final) - * Returns a list of references to all components of component_type that exist in the datum -1. `/datum/proc/GetExactComponent(component_type(type)) -> datum/component?` (public, final) - * Returns a reference to a component whose type MATCHES component_type if that component exists in the datum, null otherwise -1. `GET_COMPONENT(varname, component_type)` OR `GET_COMPONENT_FROM(varname, component_type, src)` - * Shorthand for `var/component_type/varname = src.GetComponent(component_type)` -1. `SEND_SIGNAL(target, sigtype, ...)` (public, final) - * Use to send signals to target datum - * Extra arguments are to be specified in the signal definition - * Returns a bitflag with signal specific information assembled from all activated components - * Arguments are packaged in a list and handed off to _SendSignal() -1. `/datum/proc/AddComponent(component_type(type), ...) -> datum/component` (public, final) - * Creates an instance of `component_type` in the datum and passes `...` to its `Initialize()` call - * Sends the `COMSIG_COMPONENT_ADDED` signal to the datum - * All components a datum owns are deleted with the datum - * Returns the component that was created. Or the old component in a dupe situation where `COMPONENT_DUPE_UNIQUE` was set - * If this tries to add an component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it - * Properly handles duplicate situations based on the `dupe_mode` var -1. `/datum/proc/LoadComponent(component_type(type), ...) -> datum/component` (public, final) - * Equivalent to calling `GetComponent(component_type)` where, if the result would be `null`, returns `AddComponent(component_type, ...)` instead -1. `/datum/proc/ComponentActivated(datum/component/C)` (abstract, async) - * Called on a component's `parent` after a signal received causes it to activate. `src` is the parameter - * Will only be called if a component's callback returns `TRUE` -1. `/datum/proc/TakeComponent(datum/component/C)` (public, final) - * Properly transfers ownership of a component from one datum to another - * Signals `COMSIG_COMPONENT_REMOVING` on the parent - * Called on the datum you want to own the component with another datum's component -1. `/datum/proc/_SendSignal(signal, list/arguments)` (private, final) - * Handles most of the actual signaling procedure - * Will runtime if used on datums with an empty component list -1. `/datum/proc/RegisterSignal(datum/target, signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final) - * If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments - * Makes the datum listen for the specified `signal` on it's `parent` datum. - * When that signal is received `proc_ref` will be called on the component, along with associated arguments - * Example proc ref: `.proc/OnEvent` - * If a previous registration is overwritten by the call, a runtime occurs. Setting `override` to TRUE prevents this - * These callbacks run asyncronously - * Returning `TRUE` from these callbacks will trigger a `TRUE` return from the `SendSignal()` that initiated it -1. `/datum/component/New(datum/parent, ...)` (private, final) - * Runs internal setup for the component - * Extra arguments are passed to `Initialize()` -1. `/datum/component/Initialize(...)` (abstract, no-sleep) - * Called by `New()` with the same argments excluding `parent` - * Component does not exist in `parent`'s `datum_components` list yet, although `parent` is set and may be used - * Signals will not be received while this function is running - * Component may be deleted after this function completes without being attached - * Do not call `qdel(src)` from this function -1. `/datum/component/Destroy(force(bool), silent(bool))` (virtual, no-sleep) - * Sends the `COMSIG_COMPONENT_REMOVING` signal to the parent datum if the `parent` isn't being qdeleted - * Properly removes the component from `parent` and cleans up references - * Setting `force` makes it not check for and remove the component from the parent - * Setting `silent` deletes the component without sending a `COMSIG_COMPONENT_REMOVING` signal -1. `/datum/component/proc/InheritComponent(datum/component/C, i_am_original(boolean))` (abstract, no-sleep) - * Called on a component when a component of the same type was added to the same parent - * See `/datum/component/var/dupe_mode` - * `C`'s type will always be the same of the called component -1. `/datum/component/proc/AfterComponentActivated()` (abstract, async) - * Called on a component that was activated after it's `parent`'s `ComponentActivated()` is called -1. `/datum/component/proc/OnTransfer(datum/new_parent)` (abstract, no-sleep) - * Called before `new_parent` is assigned to `parent` in `TakeComponent()` - * Allows the component to react to ownership transfers -1. `/datum/component/proc/_RemoveFromParent()` (private, final) - * Clears `parent` and removes the component from it's component list -1. `/datum/component/proc/_JoinParent` (private, final) - * Tries to add the component to it's `parent`s `datum_components` list -1. `/datum/component/proc/RegisterWithParent` (abstract, no-sleep) - * Used to register the signals that should be on the `parent` object - * Use this if you plan on the component transfering between parents -1. `/datum/component/proc/UnregisterFromParent` (abstract, no-sleep) - * Counterpart to `RegisterWithParent()` - * Used to unregister the signals that should only be on the `parent` object - -### See/Define signals and their arguments in __DEFINES\components.dm +### See/Define signals and their arguments in [__DEFINES\components.dm](..\..\__DEFINES\components.dm) diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index 0baf7d7d1b..7f7440daf4 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -1,21 +1,71 @@ +/** + * # Component + * + * The component datum + * + * A component should be a single standalone unit + * of functionality, that works by receiving signals from it's parent + * object to provide some single functionality (i.e a slippery component) + * that makes the object it's attached to cause people to slip over. + * Useful when you want shared behaviour independent of type inheritance + */ /datum/component + /// Defines how duplicate existing components are handled when added to a datum + /// See `COMPONENT_DUPE_*` definitions for available options var/dupe_mode = COMPONENT_DUPE_HIGHLANDER + + /// The type to check for duplication + /// `null` means exact match on `type` (default) + /// Any other type means that and all subtypes var/dupe_type + + /// The datum this components belongs to var/datum/parent - //only set to true if you are able to properly transfer this component - //At a minimum RegisterWithParent and UnregisterFromParent should be used - //Make sure you also implement PostTransfer for any post transfer handling + + /// Only set to true if you are able to properly transfer this component + /// At a minimum RegisterWithParent and UnregisterFromParent should be used + /// Make sure you also implement PostTransfer for any post transfer handling var/can_transfer = FALSE -/datum/component/New(datum/P, ...) - parent = P - var/list/arguments = args.Copy(2) +/** + * Create a new component. + * Additional arguments are passed to `Initialize()` + * + * Arguments: + * * datum/P the parent datum this component reacts to signals from + */ +/datum/component/New(list/raw_args) + parent = raw_args[1] + var/list/arguments = raw_args.Copy(2) if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE) qdel(src, TRUE, TRUE) - CRASH("Incompatible [type] assigned to a [P.type]! args: [json_encode(arguments)]") + CRASH("Incompatible [type] assigned to a [parent.type]! args: [json_encode(arguments)]") - _JoinParent(P) + _JoinParent(parent) +/** + * Called during component creation with the same arguments as in new excluding parent. + * Do not call `qdel(src)` from this function, `return COMPONENT_INCOMPATIBLE` instead + */ +/datum/component/proc/Initialize(...) + return + +/** + * Properly removes the component from `parent` and cleans up references + * Setting `force` makes it not check for and remove the component from the parent + * Setting `silent` deletes the component without sending a `COMSIG_COMPONENT_REMOVING` signal + */ +/datum/component/Destroy(force=FALSE, silent=FALSE) + if(!force && parent) + _RemoveFromParent() + if(!silent) + SEND_SIGNAL(parent, COMSIG_COMPONENT_REMOVING, src) + parent = null + return ..() + +/** + * Internal proc to handle behaviour of components when joining a parent + */ /datum/component/proc/_JoinParent() var/datum/P = parent //lazy init the parent's dc list @@ -51,21 +101,9 @@ RegisterWithParent() -// If you want/expect to be moving the component around between parents, use this to register on the parent for signals -/datum/component/proc/RegisterWithParent() - SEND_SIGNAL(src, COMSIG_COMPONENT_REGISTER_PARENT) //CITADEL EDIT - -/datum/component/proc/Initialize(...) - return - -/datum/component/Destroy(force=FALSE, silent=FALSE) - if(!force && parent) - _RemoveFromParent() - if(!silent) - SEND_SIGNAL(parent, COMSIG_COMPONENT_REMOVING, src) - parent = null - return ..() - +/** + * Internal proc to handle behaviour when being removed from a parent + */ /datum/component/proc/_RemoveFromParent() var/datum/P = parent var/list/dc = P.datum_components @@ -84,9 +122,38 @@ UnregisterFromParent() -/datum/component/proc/UnregisterFromParent() - SEND_SIGNAL(src, COMSIG_COMPONENT_UNREGISTER_PARENT) //CITADEL EDIT +/** + * Register the component with the parent object + * + * Use this proc to register with your parent object + * Overridable proc that's called when added to a new parent + */ +/datum/component/proc/RegisterWithParent() + return +/** + * Unregister from our parent object + * + * Use this proc to unregister from your parent object + * Overridable proc that's called when removed from a parent + * * + */ +/datum/component/proc/UnregisterFromParent() + return + +/** + * Register to listen for a signal from the passed in target + * + * This sets up a listening relationship such that when the target object emits a signal + * the source datum this proc is called upon, will recieve a callback to the given proctype + * Return values from procs registered must be a bitfield + * + * Arguments: + * * datum/target The target to listen for signals from + * * sig_type_or_types Either a string signal name, or a list of signal names (strings) + * * proctype The proc to call back when the signal is emitted + * * override If a previous registration exists you must explicitly set this + */ /datum/proc/RegisterSignal(datum/target, sig_type_or_types, proctype, override = FALSE) if(QDELETED(src) || QDELETED(target)) return @@ -119,6 +186,16 @@ signal_enabled = TRUE +/** + * Stop listening to a given signal from target + * + * Breaks the relationship between target and source datum, removing the callback when the signal fires + * Doesn't care if a registration exists or not + * + * Arguments: + * * datum/target Datum to stop listening to signals from + * * sig_typeor_types Signal string key or list of signal keys to stop listening to specifically + */ /datum/proc/UnregisterSignal(datum/target, sig_type_or_types) var/list/lookup = target.comp_lookup if(!signal_procs || !signal_procs[target] || !lookup) @@ -126,6 +203,8 @@ if(!islist(sig_type_or_types)) sig_type_or_types = list(sig_type_or_types) for(var/sig in sig_type_or_types) + if(!signal_procs[target][sig]) + continue switch(length(lookup[sig])) if(2) lookup[sig] = (lookup[sig]-src)[1] @@ -148,15 +227,47 @@ if(!signal_procs[target].len) signal_procs -= target +/** + * Called on a component when a component of the same type was added to the same parent + * See `/datum/component/var/dupe_mode` + * `C`'s type will always be the same of the called component + */ /datum/component/proc/InheritComponent(datum/component/C, i_am_original) return + +/** + * Called on a component when a component of the same type was added to the same parent with COMPONENT_DUPE_SELECTIVE + * See `/datum/component/var/dupe_mode` + * `C`'s type will always be the same of the called component + * return TRUE if you are absorbing the component, otherwise FALSE if you are fine having it exist as a duplicate component + */ +/datum/component/proc/CheckDupeComponent(datum/component/C, ...) + return + + +/** + * Callback Just before this component is transferred + * + * Use this to do any special cleanup you might need to do before being deregged from an object + * + */ /datum/component/proc/PreTransfer() return +/** + * Callback Just after a component is transferred + * + * Use this to do any special setup you need to do after being moved to a new object + * Do not call `qdel(src)` from this function, `return COMPONENT_INCOMPATIBLE` instead + * + */ /datum/component/proc/PostTransfer() return COMPONENT_INCOMPATIBLE //Do not support transfer by default as you must properly support it +/** + * Internal proc to create a list of our type and all parent types + */ /datum/component/proc/_GetInverseTypeList(our_type = type) //we can do this one simple trick var/current_type = parent_type @@ -166,6 +277,11 @@ current_type = type2parent(current_type) . += current_type +/** + * Internal proc to handle most all of the signaling procedure + * Will runtime if used on datums with an empty component list + * Use the `SEND_SIGNAL` define instead + */ /datum/proc/_SendSignal(sigtype, list/arguments) var/target = comp_lookup[sigtype] if(!length(target)) @@ -183,9 +299,16 @@ . |= CallAsync(C, proctype, arguments) // The type arg is casted so initial works, you shouldn't be passing a real instance into this +/** + * Return any component assigned to this datum of the given type + * This will throw an error if it's possible to have more than one component of that type on the parent + * + * Arguments: + * * datum/component/c_type The typepath of the component you want to get a reference to + */ /datum/proc/GetComponent(datum/component/c_type) RETURN_TYPE(c_type) - if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED) + if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED || initial(c_type.dupe_mode) == COMPONENT_DUPE_SELECTIVE) stack_trace("GetComponent was called to get a component of which multiple copies could be on an object. This can easily break and should be changed. Type: \[[c_type]\]") var/list/dc = datum_components if(!dc) @@ -194,7 +317,18 @@ if(length(.)) return .[1] -/datum/proc/GetExactComponent(c_type) +// The type arg is casted so initial works, you shouldn't be passing a real instance into this +/** + * Return any component assigned to this datum of the exact given type + * This will throw an error if it's possible to have more than one component of that type on the parent + * + * Arguments: + * * datum/component/c_type The typepath of the component you want to get a reference to + */ +/datum/proc/GetExactComponent(datum/component/c_type) + RETURN_TYPE(c_type) + if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED || initial(c_type.dupe_mode) == COMPONENT_DUPE_SELECTIVE) + stack_trace("GetComponent was called to get a component of which multiple copies could be on an object. This can easily break and should be changed. Type: \[[c_type]\]") var/list/dc = datum_components if(!dc) return null @@ -206,6 +340,12 @@ return C return null +/** + * Get all components of a given type that are attached to this datum + * + * Arguments: + * * c_type The component type path + */ /datum/proc/GetComponents(c_type) var/list/dc = datum_components if(!dc) @@ -214,7 +354,15 @@ if(!length(.)) return list(.) -/datum/proc/AddComponent(new_type, ...) +/** + * Creates an instance of `new_type` in the datum and attaches to it as parent + * Sends the `COMSIG_COMPONENT_ADDED` signal to the datum + * Returns the component that was created. Or the old component in a dupe situation where `COMPONENT_DUPE_UNIQUE` was set + * If this tries to add an component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it + * Properly handles duplicate situations based on the `dupe_mode` var + */ +/datum/proc/_AddComponent(list/raw_args) + var/new_type = raw_args[1] var/datum/component/nt = new_type var/dm = initial(nt.dupe_mode) var/dt = initial(nt.dupe_type) @@ -229,7 +377,7 @@ new_comp = nt nt = new_comp.type - args[1] = src + raw_args[1] = src if(dm != COMPONENT_DUPE_ALLOWED) if(!dt) @@ -240,37 +388,62 @@ switch(dm) if(COMPONENT_DUPE_UNIQUE) if(!new_comp) - new_comp = new nt(arglist(args)) + new_comp = new nt(raw_args) if(!QDELETED(new_comp)) old_comp.InheritComponent(new_comp, TRUE) QDEL_NULL(new_comp) if(COMPONENT_DUPE_HIGHLANDER) if(!new_comp) - new_comp = new nt(arglist(args)) + new_comp = new nt(raw_args) if(!QDELETED(new_comp)) new_comp.InheritComponent(old_comp, FALSE) QDEL_NULL(old_comp) if(COMPONENT_DUPE_UNIQUE_PASSARGS) if(!new_comp) - var/list/arguments = args.Copy(2) - old_comp.InheritComponent(null, TRUE, arguments) + var/list/arguments = raw_args.Copy(2) + arguments.Insert(1, null, TRUE) + old_comp.InheritComponent(arglist(arguments)) else old_comp.InheritComponent(new_comp, TRUE) + if(COMPONENT_DUPE_SELECTIVE) + var/list/arguments = raw_args.Copy() + arguments[1] = new_comp + var/make_new_component = TRUE + for(var/i in GetComponents(new_type)) + var/datum/component/C = i + if(C.CheckDupeComponent(arglist(arguments))) + make_new_component = FALSE + QDEL_NULL(new_comp) + break + if(!new_comp && make_new_component) + new_comp = new nt(raw_args) else if(!new_comp) - new_comp = new nt(arglist(args)) // There's a valid dupe mode but there's no old component, act like normal + new_comp = new nt(raw_args) // There's a valid dupe mode but there's no old component, act like normal else if(!new_comp) - new_comp = new nt(arglist(args)) // Dupes are allowed, act like normal + new_comp = new nt(raw_args) // Dupes are allowed, act like normal if(!old_comp && !QDELETED(new_comp)) // Nothing related to duplicate components happened and the new component is healthy SEND_SIGNAL(src, COMSIG_COMPONENT_ADDED, new_comp) return new_comp return old_comp +/** + * Get existing component of type, or create it and return a reference to it + * + * Use this if the item needs to exist at the time of this call, but may not have been created before now + * + * Arguments: + * * component_type The typepath of the component to create or return + * * ... additional arguments to be passed when creating the component if it does not exist + */ /datum/proc/LoadComponent(component_type, ...) . = GetComponent(component_type) if(!.) - return AddComponent(arglist(args)) + return _AddComponent(args) +/** + * Removes the component from parent, ends up with a null parent + */ /datum/component/proc/RemoveComponent() if(!parent) return @@ -280,6 +453,14 @@ parent = null SEND_SIGNAL(old_parent, COMSIG_COMPONENT_REMOVING, src) +/** + * Transfer this component to another parent + * + * Component is taken from source datum + * + * Arguments: + * * datum/component/target Target datum to transfer to + */ /datum/proc/TakeComponent(datum/component/target) if(!target || target.parent == src) return @@ -296,6 +477,14 @@ if(target == AddComponent(target)) target._JoinParent() +/** + * Transfer all components to target + * + * All components from source datum are taken + * + * Arguments: + * * /datum/target the target to move the components to + */ /datum/proc/TransferComponents(datum/target) var/list/dc = datum_components if(!dc) @@ -310,5 +499,8 @@ if(C.can_transfer) target.TakeComponent(comps) +/** + * Return the object that is the host of any UI's that this component has + */ /datum/component/ui_host() return parent diff --git a/code/datums/components/fantasy/_fantasy.dm b/code/datums/components/fantasy/_fantasy.dm index 9e8493b6f4..a203264fae 100644 --- a/code/datums/components/fantasy/_fantasy.dm +++ b/code/datums/components/fantasy/_fantasy.dm @@ -30,26 +30,23 @@ return ..() /datum/component/fantasy/RegisterWithParent() - . = ..() var/obj/item/master = parent originalName = master.name modify() /datum/component/fantasy/UnregisterFromParent() - . = ..() unmodify() -/datum/component/fantasy/InheritComponent(datum/component/fantasy/newComp, original, list/arguments) +/datum/component/fantasy/InheritComponent(datum/component/fantasy/newComp, original, quality, list/affixes, canFail, announce) unmodify() if(newComp) - quality += newComp.quality - canFail = newComp.canFail - announce = newComp.announce + src.quality += newComp.quality + src.canFail = newComp.canFail + src.announce = newComp.announce else - arguments.len = 5 // This is done to replicate what happens when an arglist smaller than the necessary arguments is given - quality += arguments[1] - canFail = arguments[4] || canFail - announce = arguments[5] || announce + src.quality += quality + src.canFail = canFail || src.canFail + src.announce = announce || src.announce modify() /datum/component/fantasy/proc/randomQuality() diff --git a/code/datums/components/nanites.dm b/code/datums/components/nanites.dm index 49b2e437d4..7aacb745b6 100644 --- a/code/datums/components/nanites.dm +++ b/code/datums/components/nanites.dm @@ -101,11 +101,11 @@ host_mob = null return ..() -/datum/component/nanites/InheritComponent(datum/component/nanites/new_nanites, i_am_original, list/arguments) +/datum/component/nanites/InheritComponent(datum/component/nanites/new_nanites, i_am_original, amount, cloud) if(new_nanites) adjust_nanites(null, new_nanites.nanite_volume) else - adjust_nanites(null, arguments[1]) //just add to the nanite volume + adjust_nanites(null, amount) //just add to the nanite volume /datum/component/nanites/process() adjust_nanites(null, regen_rate) diff --git a/code/datums/components/orbiter.dm b/code/datums/components/orbiter.dm index 05174c196b..2be22d01e5 100644 --- a/code/datums/components/orbiter.dm +++ b/code/datums/components/orbiter.dm @@ -41,9 +41,9 @@ orbiters = null return ..() -/datum/component/orbiter/InheritComponent(datum/component/orbiter/newcomp, original, list/arguments) - if(arguments) - begin_orbit(arglist(arguments)) +/datum/component/orbiter/InheritComponent(datum/component/orbiter/newcomp, original, atom/movable/orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation) + if(!newcomp) + begin_orbit(arglist(args.Copy(3))) return // The following only happens on component transfers orbiters += newcomp.orbiters diff --git a/code/datums/components/radioactive.dm b/code/datums/components/radioactive.dm index 240eed7747..2853f800f5 100644 --- a/code/datums/components/radioactive.dm +++ b/code/datums/components/radioactive.dm @@ -47,7 +47,7 @@ if(strength <= RAD_BACKGROUND_RADIATION) return PROCESS_KILL -/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original, list/arguments) +/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original, _strength, _source, _half_life, _can_contaminate) if(!i_am_original) return if(!hl3_release_date) // Permanently radioactive things don't get to grow stronger @@ -56,7 +56,7 @@ var/datum/component/radioactive/other = C strength = max(strength, other.strength) else - strength = max(strength, arguments[1]) + strength = max(strength, _strength) /datum/component/radioactive/proc/rad_examine(datum/source, mob/user, list/examine_list) var/atom/master = parent diff --git a/code/datums/components/remote_materials.dm b/code/datums/components/remote_materials.dm index 245e89bd0c..ca62a70ee5 100644 --- a/code/datums/components/remote_materials.dm +++ b/code/datums/components/remote_materials.dm @@ -53,11 +53,21 @@ handles linking back and forth. /datum/component/remote_materials/proc/_MakeLocal() silo = null - mat_container = parent.AddComponent(/datum/component/material_container, - list(/datum/material/iron, /datum/material/glass, /datum/material/silver, /datum/material/gold, /datum/material/diamond, /datum/material/plasma, /datum/material/uranium, /datum/material/bananium, /datum/material/titanium, /datum/material/bluespace, /datum/material/plastic), - local_size, - FALSE, - /obj/item/stack) + var/static/list/allowed_mats = list( + /datum/material/iron, + /datum/material/glass, + /datum/material/silver, + /datum/material/gold, + /datum/material/diamond, + /datum/material/plasma, + /datum/material/uranium, + /datum/material/bananium, + /datum/material/titanium, + /datum/material/bluespace, + /datum/material/plastic, + ) + + mat_container = parent.AddComponent(/datum/component/material_container, allowed_mats, local_size, allowed_types=/obj/item/stack) /datum/component/remote_materials/proc/set_local_size(size) local_size = size diff --git a/code/datums/components/stationloving.dm b/code/datums/components/stationloving.dm index 91928656e1..13267e74c3 100644 --- a/code/datums/components/stationloving.dm +++ b/code/datums/components/stationloving.dm @@ -15,13 +15,13 @@ src.allow_death = allow_death check_in_bounds() // Just in case something is being created outside of station/centcom -/datum/component/stationloving/InheritComponent(datum/component/stationloving/newc, original, list/arguments) +/datum/component/stationloving/InheritComponent(datum/component/stationloving/newc, original, inform_admins, allow_death) if (original) - if (istype(newc)) + if (newc) inform_admins = newc.inform_admins allow_death = newc.allow_death - else if (LAZYLEN(arguments)) - inform_admins = arguments[1] + else + inform_admins = inform_admins /datum/component/stationloving/proc/relocate() var/targetturf = find_safe_turf() diff --git a/code/datums/components/thermite.dm b/code/datums/components/thermite.dm index 916b3ed3b2..53323f1e3f 100644 --- a/code/datums/components/thermite.dm +++ b/code/datums/components/thermite.dm @@ -43,13 +43,13 @@ master.cut_overlay(overlay) return ..() -/datum/component/thermite/InheritComponent(datum/component/thermite/newC, i_am_original, list/arguments) +/datum/component/thermite/InheritComponent(datum/component/thermite/newC, i_am_original, _amount) if(!i_am_original) return if(newC) amount += newC.amount else - amount += arguments[1] + amount += _amount /datum/component/thermite/proc/thermite_melt(mob/user) var/turf/master = parent diff --git a/code/datums/components/wet_floor.dm b/code/datums/components/wet_floor.dm index 550ff95324..20f2c1bbb5 100644 --- a/code/datums/components/wet_floor.dm +++ b/code/datums/components/wet_floor.dm @@ -12,9 +12,9 @@ var/permanent = FALSE var/last_process = 0 -/datum/component/wet_floor/InheritComponent(datum/newcomp, orig, argslist) +/datum/component/wet_floor/InheritComponent(datum/newcomp, orig, strength, duration_minimum, duration_add, duration_maximum, _permanent) if(!newcomp) //We are getting passed the arguments of a would-be new component, but not a new component - add_wet(arglist(argslist)) + add_wet(arglist(args.Copy(3))) else //We are being passed in a full blown component var/datum/component/wet_floor/WF = newcomp //Lets make an assumption if(WF.gc()) //See if it's even valid, still. Also does LAZYLEN and stuff for us. diff --git a/code/datums/datum.dm b/code/datums/datum.dm index 34e4e7ac14..a856f2392d 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -1,12 +1,42 @@ +/** + * The absolute base class for everything + * + * A datum instantiated has no physical world prescence, use an atom if you want something + * that actually lives in the world + * + * Be very mindful about adding variables to this class, they are inherited by every single + * thing in the entire game, and so you can easily cause memory usage to rise a lot with careless + * use of variables at this level + */ /datum + /** + * Tick count time when this object was destroyed. + * + * If this is non zero then the object has been garbage collected and is awaiting either + * a hard del by the GC subsystme, or to be autocollected (if it has no references) + */ var/gc_destroyed //Time when this object was destroyed. - var/list/active_timers //for SStimer - var/list/datum_components //for /datum/components + + /// Active timers with this datum as the target + var/list/active_timers + /// Status traits attached to this datum var/list/status_traits + /// Components attached to this datum + /// Lazy associated list in the structure of `type:component/list of components` + var/list/datum_components + /// Any datum registered to receive signals from this datum is in this list + /// Lazy associated list in the structure of `signal:registree/list of registrees` var/list/comp_lookup //it used to be for looking up components which had registered a signal but now anything can register + /// Lazy associated list in the structure of `signals:proctype` that are run when the datum receives that signal var/list/list/datum/callback/signal_procs + /// Is this datum capable of sending signals? + /// Set to true when a signal has been registered var/signal_enabled = FALSE + + /// Datum level flags var/datum_flags = NONE + + /// A weak reference to another datum var/datum/weakref/weak_reference #ifdef TESTING @@ -18,9 +48,22 @@ var/list/cached_vars #endif -// Default implementation of clean-up code. -// This should be overridden to remove all references pointing to the object being destroyed. -// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE. +/** + * Default implementation of clean-up code. + * + * This should be overridden to remove all references pointing to the object being destroyed, if + * you do override it, make sure to call the parent and return it's return value by default + * + * Return an appropriate QDEL_HINT to modify handling of your deletion; + * in most cases this is QDEL_HINT_QUEUE. + * + * The base case is responsible for doing the following + * * Erasing timers pointing to this datum + * * Erasing compenents on this datum + * * Notifying datums listening to signals from this datum that we are going away + * + * Returns QDEL_HINT_QUEUE + */ /datum/proc/Destroy(force=FALSE, ...) tag = null datum_flags &= ~DF_USE_TAG //In case something tries to REF us diff --git a/code/datums/elements/_element.dm b/code/datums/elements/_element.dm index 17e2b12232..f74dcd0b6e 100644 --- a/code/datums/elements/_element.dm +++ b/code/datums/elements/_element.dm @@ -1,4 +1,11 @@ +/** + * A holder for simple behaviour that can be attached to many different types + * + * Only one element of each type is instanced during game init. + * Otherwise acts basically like a lightweight component. + */ /datum/element + /// Option flags for element behaviour var/element_flags = NONE /** * The index of the first attach argument to consider for duplicate elements @@ -7,13 +14,17 @@ */ var/id_arg_index = INFINITY +/// Activates the functionality defined by the element on the given target datum /datum/element/proc/Attach(datum/target) + SHOULD_CALL_PARENT(1) if(type == /datum/element) return ELEMENT_INCOMPATIBLE if(element_flags & ELEMENT_DETACH) RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/Detach, override = TRUE) +/// Deactivates the functionality defines by the element on the given datum /datum/element/proc/Detach(datum/source, force) + SHOULD_CALL_PARENT(1) UnregisterSignal(source, COMSIG_PARENT_QDELETING) /datum/element/Destroy(force) @@ -24,16 +35,17 @@ //DATUM PROCS -/datum/proc/AddElement(eletype, ...) - var/datum/element/ele = SSdcs.GetElement(arglist(args)) - args[1] = src - if(ele.Attach(arglist(args)) == ELEMENT_INCOMPATIBLE) - CRASH("Incompatible [eletype] assigned to a [type]! args: [json_encode(args)]") +/// Finds the singleton for the element type given and attaches it to src +/datum/proc/_AddElement(list/arguments) + var/datum/element/ele = SSdcs.GetElement(arguments) + arguments[1] = src + if(ele.Attach(arglist(arguments)) == ELEMENT_INCOMPATIBLE) + CRASH("Incompatible [arguments[1]] assigned to a [type]! args: [json_encode(args)]") /** * Finds the singleton for the element type given and detaches it from src * You only need additional arguments beyond the type if you're using ELEMENT_BESPOKE */ -/datum/proc/RemoveElement(eletype, ...) - var/datum/element/ele = SSdcs.GetElement(arglist(args)) +/datum/proc/_RemoveElement(list/arguments) + var/datum/element/ele = SSdcs.GetElement(arguments) ele.Detach(src) diff --git a/code/datums/elements/mob_holder.dm b/code/datums/elements/mob_holder.dm index 18fa60a508..3cd5367f65 100644 --- a/code/datums/elements/mob_holder.dm +++ b/code/datums/elements/mob_holder.dm @@ -8,18 +8,18 @@ var/inv_slots var/proctype //if present, will be invoked on headwear generation. -/datum/element/mob_holder/Attach(datum/target, _worn_state, _alt_worn, _right_hand, _left_hand, _inv_slots = NONE, _proctype) +/datum/element/mob_holder/Attach(datum/target, worn_state, alt_worn, right_hand, left_hand, inv_slots = NONE, proctype) . = ..() if(!isliving(target)) return ELEMENT_INCOMPATIBLE - worn_state = _worn_state - alt_worn = _alt_worn - right_hand = _right_hand - left_hand = _left_hand - inv_slots = _inv_slots - proctype = _proctype + src.worn_state = worn_state + src.alt_worn = alt_worn + src.right_hand = right_hand + src.left_hand = left_hand + src.inv_slots = inv_slots + src.proctype = proctype RegisterSignal(target, COMSIG_CLICK_ALT, .proc/mob_try_pickup) RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/on_examine) diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index 6511950c87..c006f97bff 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -93,12 +93,12 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/plasma/on_applied(atom/source, amount, material_flags) . = ..() if(ismovableatom(source)) - source.AddElement(/datum/element/firestacker) + source.AddElement(/datum/element/firestacker, amount=1) source.AddComponent(/datum/component/explodable, 0, 0, amount / 2500, amount / 1250) /datum/material/plasma/on_removed(atom/source, material_flags) . = ..() - source.RemoveElement(/datum/element/firestacker) + source.RemoveElement(/datum/element/firestacker, amount=1) qdel(source.GetComponent(/datum/component/explodable)) ///Can cause bluespace effects on use. (Teleportation) (Not yet implemented) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index b74e4303e5..6fa7fa30c0 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -47,8 +47,8 @@ ) /obj/machinery/autolathe/Initialize() - AddComponent(/datum/component/material_container, - list(/datum/material/iron, + var/static/list/allowed_types = list( + /datum/material/iron, /datum/material/glass, /datum/material/gold, /datum/material/silver, @@ -62,10 +62,9 @@ /datum/material/plastic, /datum/material/adamantine, /datum/material/mythril - ), - 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert)) + ) + AddComponent(/datum/component/material_container, allowed_types, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert)) . = ..() - wires = new /datum/wires/autolathe(src) stored_research = new /datum/techweb/specialized/autounlocking/autolathe matching_designs = list() diff --git a/code/game/machinery/toylathe.dm b/code/game/machinery/toylathe.dm index 87ab3cadd8..c679f3f983 100644 --- a/code/game/machinery/toylathe.dm +++ b/code/game/machinery/toylathe.dm @@ -46,7 +46,12 @@ ) /obj/machinery/autoylathe/Initialize() - AddComponent(/datum/component/material_container, list(/datum/material/iron, /datum/material/glass, /datum/material/plastic), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert)) + var/static/list/allowed_materials = list( + /datum/material/iron, + /datum/material/glass, + /datum/material/plastic + ) + AddComponent(/datum/component/material_container, allowed_materials, 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert)) . = ..() wires = new /datum/wires/autoylathe(src) diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index f9b8f31bca..2ebb2f6ded 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -35,9 +35,19 @@ ) /obj/machinery/mecha_part_fabricator/Initialize() - var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, - list(/datum/material/iron, /datum/material/glass, /datum/material/silver, /datum/material/gold, /datum/material/diamond, /datum/material/plasma, /datum/material/uranium, /datum/material/bananium, /datum/material/titanium, /datum/material/bluespace), 0, - TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) + var/static/list/allowed_types = list( + /datum/material/iron, + /datum/material/glass, + /datum/material/silver, + /datum/material/gold, + /datum/material/diamond, + /datum/material/plasma, + /datum/material/uranium, + /datum/material/bananium, + /datum/material/titanium, + /datum/material/bluespace + ) + var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, allowed_types, 0, TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) materials.precise_insertion = TRUE stored_research = new return ..() diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index 531367585e..04c3909696 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -315,13 +315,8 @@ /obj/structure/windoor_assembly/ComponentInitialize() . = ..() - AddComponent( - /datum/component/simple_rotation, - ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS, - null, - CALLBACK(src, .proc/can_be_rotated), - CALLBACK(src,.proc/after_rotation) - ) + var/static/rotation_flags = ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS + AddComponent(/datum/component/simple_rotation, rotation_flags, can_be_rotated=CALLBACK(src, .proc/can_be_rotated), after_rotation=CALLBACK(src,.proc/after_rotation)) /obj/structure/windoor_assembly/proc/can_be_rotated(mob/user,rotation_type) if(anchored) diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index be13df2070..33c6d46045 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -20,13 +20,8 @@ /obj/item/assembly/infra/ComponentInitialize() . = ..() - AddComponent( - /datum/component/simple_rotation, - ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_FLIP | ROTATION_VERBS, - null, - null, - CALLBACK(src,.proc/after_rotation) - ) + var/static/rotation_flags = ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_FLIP | ROTATION_VERBS + AddComponent(/datum/component/simple_rotation, rotation_flags, after_rotation=CALLBACK(src,.proc/after_rotation)) /obj/item/assembly/infra/proc/after_rotation() refreshBeam() diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm index 3183a6d0e6..d1cd852651 100644 --- a/code/modules/integrated_electronics/subtypes/manipulation.dm +++ b/code/modules/integrated_electronics/subtypes/manipulation.dm @@ -402,11 +402,22 @@ power_draw_per_use = 40 ext_cooldown = 1 cooldown_per_use = 10 - var/list/mtypes = list(/datum/material/iron, /datum/material/glass, /datum/material/silver, /datum/material/gold, /datum/material/diamond, /datum/material/uranium, /datum/material/plasma, /datum/material/bluespace, /datum/material/bananium, /datum/material/titanium, /datum/material/plastic) + var/static/list/mtypes = list( + /datum/material/iron, + /datum/material/glass, + /datum/material/silver, + /datum/material/gold, + /datum/material/diamond, + /datum/material/uranium, + /datum/material/plasma, + /datum/material/bluespace, + /datum/material/bananium, + /datum/material/titanium, + /datum/material/plastic + ) -/obj/item/integrated_circuit/manipulation/matman/Initialize() - var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, - mtypes, 100000, FALSE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) +/obj/item/integrated_circuit/manipulation/matman/ComponentInitialize() + var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, mtypes, 100000, FALSE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) materials.precise_insertion = TRUE .=..() diff --git a/code/modules/mapping/mapping_helpers/_mapping_helpers.dm b/code/modules/mapping/mapping_helpers/_mapping_helpers.dm index 99184b1c3e..4de16ba350 100644 --- a/code/modules/mapping/mapping_helpers/_mapping_helpers.dm +++ b/code/modules/mapping/mapping_helpers/_mapping_helpers.dm @@ -97,7 +97,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) if(target_type && !istype(A,target_type)) continue var/cargs = build_args() - A.AddComponent(arglist(cargs)) + A._AddComponent(cargs) qdel(src) return diff --git a/code/modules/mining/machine_silo.dm b/code/modules/mining/machine_silo.dm index c0eba668f1..c0356dd1ab 100644 --- a/code/modules/mining/machine_silo.dm +++ b/code/modules/mining/machine_silo.dm @@ -15,14 +15,20 @@ GLOBAL_LIST_EMPTY(silo_access_logs) /obj/machinery/ore_silo/Initialize(mapload) . = ..() - AddComponent(/datum/component/material_container, - list(/datum/material/iron, /datum/material/glass, /datum/material/silver, /datum/material/gold, /datum/material/diamond, /datum/material/plasma, /datum/material/uranium, /datum/material/bananium, /datum/material/titanium, /datum/material/bluespace, /datum/material/plastic), - INFINITY, - FALSE, - /obj/item/stack, - null, - null, - TRUE) + var/static/list/materials_list = list( + /datum/material/iron, + /datum/material/glass, + /datum/material/silver, + /datum/material/gold, + /datum/material/diamond, + /datum/material/plasma, + /datum/material/uranium, + /datum/material/bananium, + /datum/material/titanium, + /datum/material/bluespace, + /datum/material/plastic, + ) + AddComponent(/datum/component/material_container, materials_list, INFINITY, allowed_types=/obj/item/stack, _disable_attackby=TRUE) if (!GLOB.ore_silo_default && mapload && is_station_level(z)) GLOB.ore_silo_default = src diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index e48fc722cd..86b9826c12 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -43,7 +43,7 @@ /mob/living/carbon/monkey/ComponentInitialize() . = ..() - AddElement(/datum/element/mob_holder, "monkey", null, null, null, ITEM_SLOT_HEAD) + AddElement(/datum/element/mob_holder, worn_state = "monkey", inv_slots = ITEM_SLOT_HEAD) /mob/living/carbon/monkey/Destroy() diff --git a/code/modules/mob/living/silicon/pai/pai_shell.dm b/code/modules/mob/living/silicon/pai/pai_shell.dm index c6710141f9..63fb82082f 100644 --- a/code/modules/mob/living/silicon/pai/pai_shell.dm +++ b/code/modules/mob/living/silicon/pai/pai_shell.dm @@ -97,8 +97,7 @@ resist_a_rest(FALSE, TRUE) update_icon() if(possible_chassis[old_chassis]) - var/datum/element/mob_holder/M = SSdcs.GetElement(/datum/element/mob_holder, old_chassis, 'icons/mob/pai_item_head.dmi', 'icons/mob/pai_item_rh.dmi', 'icons/mob/pai_item_lh.dmi', ITEM_SLOT_HEAD) - M.Detach(src) + RemoveElement(/datum/element/mob_holder, old_chassis, 'icons/mob/pai_item_head.dmi', 'icons/mob/pai_item_rh.dmi', 'icons/mob/pai_item_lh.dmi', ITEM_SLOT_HEAD) if(possible_chassis[chassis]) AddElement(/datum/element/mob_holder, chassis, 'icons/mob/pai_item_head.dmi', 'icons/mob/pai_item_rh.dmi', 'icons/mob/pai_item_lh.dmi', ITEM_SLOT_HEAD) to_chat(src, "You switch your holochassis projection composite to [chassis]") diff --git a/code/modules/mob/living/simple_animal/friendly/lizard.dm b/code/modules/mob/living/simple_animal/friendly/lizard.dm index dbcaed1ba2..9ae46f29e5 100644 --- a/code/modules/mob/living/simple_animal/friendly/lizard.dm +++ b/code/modules/mob/living/simple_animal/friendly/lizard.dm @@ -26,7 +26,7 @@ /mob/living/simple_animal/hostile/lizard/ComponentInitialize() . = ..() - AddElement(/datum/element/mob_holder, "lizard", null, null, null, ITEM_SLOT_HEAD) //you can hold lizards now. + AddElement(/datum/element/mob_holder, worn_state = "lizard", inv_slots = ITEM_SLOT_HEAD) //you can hold lizards now. /mob/living/simple_animal/hostile/lizard/CanAttack(atom/the_target)//Can we actually attack a possible target? if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it diff --git a/code/modules/research/nanites/nanite_cloud_controller.dm b/code/modules/research/nanites/nanite_cloud_controller.dm index 0731d3067c..439d0c5750 100644 --- a/code/modules/research/nanites/nanite_cloud_controller.dm +++ b/code/modules/research/nanites/nanite_cloud_controller.dm @@ -48,7 +48,7 @@ return var/datum/nanite_cloud_backup/backup = new(src) - var/datum/component/nanites/cloud_copy = new(backup) + var/datum/component/nanites/cloud_copy = backup.AddComponent(/datum/component/nanites) backup.cloud_id = cloud_id backup.nanites = cloud_copy investigate_log("[key_name(user)] created a new nanite cloud backup with id #[cloud_id]", INVESTIGATE_NANITES) @@ -213,7 +213,7 @@ var/datum/component/nanites/nanites = backup.nanites var/datum/nanite_program/P = nanites.programs[text2num(params["program_id"])] var/datum/nanite_rule/rule = rule_template.make_rule(P) - + investigate_log("[key_name(usr)] added rule [rule.display()] to program [P.name] in cloud #[current_view]", INVESTIGATE_NANITES) . = TRUE if("remove_rule") @@ -224,7 +224,7 @@ var/datum/nanite_program/P = nanites.programs[text2num(params["program_id"])] var/datum/nanite_rule/rule = P.rules[text2num(params["rule_id"])] rule.remove() - + investigate_log("[key_name(usr)] removed rule [rule.display()] from program [P.name] in cloud #[current_view]", INVESTIGATE_NANITES) . = TRUE diff --git a/tgstation.dme b/tgstation.dme index e54b2626d3..21f9f98d65 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -36,7 +36,6 @@ #include "code\__DEFINES\clockcult.dm" #include "code\__DEFINES\colors.dm" #include "code\__DEFINES\combat.dm" -#include "code\__DEFINES\components.dm" #include "code\__DEFINES\configuration.dm" #include "code\__DEFINES\construction.dm" #include "code\__DEFINES\contracts.dm" @@ -118,6 +117,9 @@ #include "code\__DEFINES\vv.dm" #include "code\__DEFINES\wall_dents.dm" #include "code\__DEFINES\wires.dm" +#include "code\__DEFINES\dcs\flags.dm" +#include "code\__DEFINES\dcs\helpers.dm" +#include "code\__DEFINES\dcs\signals.dm" #include "code\__HELPERS\_cit_helpers.dm" #include "code\__HELPERS\_lists.dm" #include "code\__HELPERS\_logging.dm" From 663a849afeeb005134560a47362bd59ca1c292aa Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 12 Mar 2020 21:02:34 +0100 Subject: [PATCH 20/61] Makes the autotransfer subsystem a bit more optional. --- code/controllers/configuration/entries/general.dm | 6 ++++-- code/controllers/subsystem/autotransfer.dm | 15 ++++++++++++--- code/datums/elements/ghost_role_eligibility.dm | 7 ++++--- code/modules/mob/dead/observer/observer.dm | 14 ++++++++------ config/config.txt | 3 ++- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index 5d18337a9f..76bee768f4 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -82,7 +82,9 @@ config_entry_value = 600 min_val = 0 -/datum/config_entry/number/vote_autotransfer_initial //length of time before the first autotransfer vote is called (deciseconds, default 2 hours) +/// Length of time before the first autotransfer vote is called (deciseconds, default 2 hours) +/// Set to 0 to disable the subsystem altogether. +/datum/config_entry/number/vote_autotransfer_initial config_entry_value = 72000 min_val = 0 @@ -90,7 +92,7 @@ config_entry_value = 18000 min_val = 0 -/datum/config_entry/number/vote_autotransfer_maximum // maximum extensions until the round autoends +/datum/config_entry/number/vote_autotransfer_maximum // maximum extensions until the round autoends, set to 0 to disable. config_entry_value = 4 min_val = 0 diff --git a/code/controllers/subsystem/autotransfer.dm b/code/controllers/subsystem/autotransfer.dm index 2f4eac6197..ce44b25fcc 100644 --- a/code/controllers/subsystem/autotransfer.dm +++ b/code/controllers/subsystem/autotransfer.dm @@ -7,18 +7,27 @@ SUBSYSTEM_DEF(autotransfer) var/targettime var/voteinterval var/maxvotes - var/curvotes + var/curvotes = 0 /datum/controller/subsystem/autotransfer/Initialize(timeofday) + var/init_vote = CONFIG_GET(number/vote_autotransfer_initial) + if(init_vote == 0) //Autotransfer voting disabled. + can_fire = FALSE + return ..() starttime = world.time - targettime = starttime + CONFIG_GET(number/vote_autotransfer_initial) + targettime = starttime + init_vote voteinterval = CONFIG_GET(number/vote_autotransfer_interval) maxvotes = CONFIG_GET(number/vote_autotransfer_maximum) curvotes = 0 return ..() +/datum/controller/subsystem/autotransfer/Recover() + starttime = SSautotransfer.starttime + voteinterval = SSautotransfer.voteinterval + curvotes = SSautotransfer.curvotes + /datum/controller/subsystem/autotransfer/fire() - if(maxvotes > curvotes) + if(!maxvotes || maxvotes > curvotes) if(world.time > targettime) SSvote.initiate_vote("transfer","server") targettime = targettime + voteinterval diff --git a/code/datums/elements/ghost_role_eligibility.dm b/code/datums/elements/ghost_role_eligibility.dm index ab87d7f1d2..bdfc6f8f1d 100644 --- a/code/datums/elements/ghost_role_eligibility.dm +++ b/code/datums/elements/ghost_role_eligibility.dm @@ -17,9 +17,10 @@ penalty += roundstart_quit_limit - world.time if(penalty) penalty += world.realtime - var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes - if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime) - penalty = CANT_REENTER_ROUND + if(SSautotransfer.can_fire && SSautotransfer.max_votes) + var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes + if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime) + penalty = CANT_REENTER_ROUND if(!(M.ckey in timeouts)) timeouts += M.ckey timeouts[M.ckey] = 0 diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 87c8598541..ac0f7f9f08 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -292,9 +292,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) MINUTES if(world.time < roundstart_quit_limit) penalty += roundstart_quit_limit - world.time - var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes - if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime) - penalty = CANT_REENTER_ROUND + if(SSautotransfer.can_fire && SSautotransfer.max_votes) + var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes + if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime) + penalty = CANT_REENTER_ROUND if(SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, (stat == DEAD) ? TRUE : FALSE, FALSE, (stat == DEAD)? penalty : 0, (stat == DEAD)? TRUE : FALSE) & COMPONENT_BLOCK_GHOSTING) return @@ -327,9 +328,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) MINUTES if(world.time < roundstart_quit_limit) penalty += roundstart_quit_limit - world.time - var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes - if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime) - penalty = CANT_REENTER_ROUND + if(SSautotransfer.can_fire && SSautotransfer.max_votes) + var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes + if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime) + penalty = CANT_REENTER_ROUND var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst alive you won't be able to re-enter this round [penalty ? "or play ghost roles [penalty == CANT_REENTER_ROUND ? "until the round is over" : "for the next [DisplayTimeText(penalty)]"]" : ""]! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") if(response != "Ghost") diff --git a/config/config.txt b/config/config.txt index 1d987070dd..7ec5354128 100644 --- a/config/config.txt +++ b/config/config.txt @@ -185,12 +185,13 @@ VOTE_DELAY 6000 VOTE_PERIOD 600 ## autovote initial delay (deciseconds) before first automatic transfer vote call (default 120 minutes) +## Set to 0 to disable the subsystem altogether. VOTE_AUTOTRANSFER_INITIAL 72000 ## autovote delay (deciseconds) before sequential automatic transfer votes are called (default 30 minutes) VOTE_AUTOTRANSFER_INTERVAL 18000 -## autovote maximum votes until automatic transfer call (default 4) +## autovote maximum votes until automatic transfer call, set to 0 to disable. (default 4) VOTE_AUTOTRANSFER_MAXIMUM 4 ## prevents dead players from voting or starting votes From 0602e728c0d4bcbe784b71c65c4c321a00d74000 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 12 Mar 2020 21:15:12 +0100 Subject: [PATCH 21/61] Doesn't delete the old auto transfer behavior. --- .../configuration/entries/general.dm | 10 +++++++--- code/controllers/subsystem/autotransfer.dm | 17 +++++++++++------ config/config.txt | 4 +++- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index 76bee768f4..a1f8f098d3 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -88,13 +88,17 @@ config_entry_value = 72000 min_val = 0 -/datum/config_entry/number/vote_autotransfer_interval //length of time to wait before subsequent autotransfer votes (deciseconds, default 30 minutes) +///length of time to wait before subsequent autotransfer votes (deciseconds, default 30 minutes) +/datum/config_entry/number/vote_autotransfer_interval config_entry_value = 18000 min_val = 0 -/datum/config_entry/number/vote_autotransfer_maximum // maximum extensions until the round autoends, set to 0 to disable. +/// maximum extensions until the round autoends. +/// Set to 0 to force automatic crew transfer after the 'vote_autotransfer_initial' elapsed. +/// Set to -1 to disable the maximum extensions cap. +/datum/config_entry/number/vote_autotransfer_maximum config_entry_value = 4 - min_val = 0 + min_val = -1 /datum/config_entry/flag/default_no_vote // vote does not default to nochange/norestart diff --git a/code/controllers/subsystem/autotransfer.dm b/code/controllers/subsystem/autotransfer.dm index ce44b25fcc..d37430bcdd 100644 --- a/code/controllers/subsystem/autotransfer.dm +++ b/code/controllers/subsystem/autotransfer.dm @@ -1,3 +1,5 @@ +#define NO_MAXVOTES_CAP -1 + SUBSYSTEM_DEF(autotransfer) name = "Autotransfer Vote" flags = SS_KEEP_TIMING | SS_BACKGROUND @@ -11,7 +13,7 @@ SUBSYSTEM_DEF(autotransfer) /datum/controller/subsystem/autotransfer/Initialize(timeofday) var/init_vote = CONFIG_GET(number/vote_autotransfer_initial) - if(init_vote == 0) //Autotransfer voting disabled. + if(!init_vote) //Autotransfer voting disabled. can_fire = FALSE return ..() starttime = world.time @@ -27,10 +29,13 @@ SUBSYSTEM_DEF(autotransfer) curvotes = SSautotransfer.curvotes /datum/controller/subsystem/autotransfer/fire() - if(!maxvotes || maxvotes > curvotes) - if(world.time > targettime) - SSvote.initiate_vote("transfer","server") - targettime = targettime + voteinterval - curvotes += 1 + if(world.time < targettime) + return + if(maxvotes == NO_MAXVOTES_CAP || maxvotes > curvotes) + SSvote.initiate_vote("transfer","server") + targettime = targettime + voteinterval + curvotes++ else SSshuttle.autoEnd() + +#undef NO_MAXVOTES_CAP \ No newline at end of file diff --git a/config/config.txt b/config/config.txt index 7ec5354128..306d1d9a6d 100644 --- a/config/config.txt +++ b/config/config.txt @@ -191,7 +191,9 @@ VOTE_AUTOTRANSFER_INITIAL 72000 ## autovote delay (deciseconds) before sequential automatic transfer votes are called (default 30 minutes) VOTE_AUTOTRANSFER_INTERVAL 18000 -## autovote maximum votes until automatic transfer call, set to 0 to disable. (default 4) +## autovote maximum votes until automatic transfer call. (default 4) +## Set to 0 to force automatic crew transfer after the 'vote_autotransfer_initial' elapsed. +## Set to -1 to disable the maximum votes cap. VOTE_AUTOTRANSFER_MAXIMUM 4 ## prevents dead players from voting or starting votes From d1b39b65903970e030e8c74fea692ed33f466860 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 12 Mar 2020 21:22:39 +0100 Subject: [PATCH 22/61] . --- code/controllers/subsystem/autotransfer.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/controllers/subsystem/autotransfer.dm b/code/controllers/subsystem/autotransfer.dm index d37430bcdd..ece203abba 100644 --- a/code/controllers/subsystem/autotransfer.dm +++ b/code/controllers/subsystem/autotransfer.dm @@ -20,7 +20,6 @@ SUBSYSTEM_DEF(autotransfer) targettime = starttime + init_vote voteinterval = CONFIG_GET(number/vote_autotransfer_interval) maxvotes = CONFIG_GET(number/vote_autotransfer_maximum) - curvotes = 0 return ..() /datum/controller/subsystem/autotransfer/Recover() From da5b2930330c2dd98b8ac5ec403bd7ba517757d8 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 12 Mar 2020 21:31:17 +0100 Subject: [PATCH 23/61] underscores. --- code/datums/elements/ghost_role_eligibility.dm | 2 +- code/modules/mob/dead/observer/observer.dm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/datums/elements/ghost_role_eligibility.dm b/code/datums/elements/ghost_role_eligibility.dm index bdfc6f8f1d..d04cf36138 100644 --- a/code/datums/elements/ghost_role_eligibility.dm +++ b/code/datums/elements/ghost_role_eligibility.dm @@ -17,7 +17,7 @@ penalty += roundstart_quit_limit - world.time if(penalty) penalty += world.realtime - if(SSautotransfer.can_fire && SSautotransfer.max_votes) + if(SSautotransfer.can_fire && SSautotransfer.maxvotes) var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime) penalty = CANT_REENTER_ROUND diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index ac0f7f9f08..c201f437e4 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -292,7 +292,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) MINUTES if(world.time < roundstart_quit_limit) penalty += roundstart_quit_limit - world.time - if(SSautotransfer.can_fire && SSautotransfer.max_votes) + if(SSautotransfer.can_fire && SSautotransfer.maxvotes) var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime) penalty = CANT_REENTER_ROUND @@ -328,7 +328,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) MINUTES if(world.time < roundstart_quit_limit) penalty += roundstart_quit_limit - world.time - if(SSautotransfer.can_fire && SSautotransfer.max_votes) + if(SSautotransfer.can_fire && SSautotransfer.maxvotes) var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime) penalty = CANT_REENTER_ROUND From ae94083dbeecfe97c8d4091ce2c32384f10bae5e Mon Sep 17 00:00:00 2001 From: Putnam Date: Thu, 12 Mar 2020 14:59:04 -0700 Subject: [PATCH 24/61] Added more explanation to hijack. --- code/modules/antagonists/traitor/classes/hijack.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/antagonists/traitor/classes/hijack.dm b/code/modules/antagonists/traitor/classes/hijack.dm index 89c3d60a12..bee87f94b1 100644 --- a/code/modules/antagonists/traitor/classes/hijack.dm +++ b/code/modules/antagonists/traitor/classes/hijack.dm @@ -8,7 +8,7 @@ /datum/traitor_class/human/hijack/forge_objectives(datum/antagonist/traitor/T) var/datum/objective/hijack/O = new - O.explanation_text = "The Gorlex Marauders are letting you do what you want, with one condition: the shuttle must be hijacked." + O.explanation_text = "The Gorlex Marauders are letting you do what you want, with one condition: the shuttle must be hijacked by hacking its navigational protocols through the control console (alt click emergency shuttle console)." O.owner = T.owner T.add_objective(O) return From b1a94f7667eaa881513983fba31800a819bcd319 Mon Sep 17 00:00:00 2001 From: Putnam Date: Thu, 12 Mar 2020 15:05:53 -0700 Subject: [PATCH 25/61] Made hijack, martyr more common --- code/modules/antagonists/traitor/classes/hijack.dm | 2 +- code/modules/antagonists/traitor/classes/martyr.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/antagonists/traitor/classes/hijack.dm b/code/modules/antagonists/traitor/classes/hijack.dm index bee87f94b1..e89eda1dcf 100644 --- a/code/modules/antagonists/traitor/classes/hijack.dm +++ b/code/modules/antagonists/traitor/classes/hijack.dm @@ -1,7 +1,7 @@ /datum/traitor_class/human/hijack name = "Gorlex Marauder" employer = "The Gorlex Marauders" - weight = 1 + weight = 3 chaos = 5 cost = 5 uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit) diff --git a/code/modules/antagonists/traitor/classes/martyr.dm b/code/modules/antagonists/traitor/classes/martyr.dm index fa0ee600b4..78f8bf9b0c 100644 --- a/code/modules/antagonists/traitor/classes/martyr.dm +++ b/code/modules/antagonists/traitor/classes/martyr.dm @@ -1,7 +1,7 @@ /datum/traitor_class/human/martyr name = "Tiger Cooperator" employer = "The Tiger Cooperative" - weight = 1 + weight = 2 chaos = 5 cost = 5 uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit,/datum/uplink_item/bundles_TC/contract_kit) From f5ec7f5b654c957a7e74fbd5579a9d077788d183 Mon Sep 17 00:00:00 2001 From: ZeroMan Date: Thu, 12 Mar 2020 20:47:35 -0400 Subject: [PATCH 26/61] it works it works --- code/modules/clothing/masks/miscellaneous.dm | 24 +++++++++++++++ code/modules/clothing/neck/_neck.dm | 32 ++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index 84990f9660..c743f26363 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -247,6 +247,30 @@ /obj/item/clothing/mask/bandana/attack_self(mob/user) adjustmask(user) +/obj/item/clothing/mask/bandana/AltClick(mob/user) + . = ..() + if(iscarbon(user)) + var/mob/living/carbon/C = user + if((C.get_item_by_slot(SLOT_HEAD == src)) || (C.get_item_by_slot(SLOT_WEAR_MASK) == src)) + to_chat(user, "You can't tie [src] while wearing it!") + return + if(slot_flags & ITEM_SLOT_HEAD) + to_chat(user, "You must undo [src] before you can tie it into a neckerchief!") + else + if(user.is_holding(src)) + var/obj/item/clothing/neck/neckerchief/nk = new(src) + nk.name = "[name] neckerchief" + nk.desc = "[desc] It's tied up like a neckerchief." + nk.icon_state = icon_state + nk.sourceBandanaType = src.type + var/currentHandIndex = user.get_held_index_of_item(src) + user.transferItemToLoc(src, null) + user.put_in_hand(nk, currentHandIndex) + user.visible_message("You tie [src] up like a neckerchief.", "[user] ties [src] up like a neckerchief.") + qdel(src) + else + to_chat(user, "You must be holding [src] in order to tie it!") + /obj/item/clothing/mask/bandana/red name = "red bandana" desc = "A fine red bandana with nanotech lining." diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index 2b43460257..f24d90f7fe 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -291,3 +291,35 @@ icon = 'icons/obj/clothing/neck.dmi' icon_state = "bling" item_color = "bling" + +////////////////////////////////// +//VERY SUPER BADASS NECKERCHIEFS// +////////////////////////////////// +obj/item/clothing/neck/neckerchief + icon = 'icons/obj/clothing/masks.dmi' //In order to reuse the bandana sprite + w_class = WEIGHT_CLASS_TINY + var/sourceBandanaType + +/obj/item/clothing/neck/neckerchief/worn_overlays(isinhands) + . = ..() + if(!isinhands) + var/mutable_appearance/realOverlay = mutable_appearance('icons/mob/mask.dmi', icon_state) + realOverlay.pixel_y = -3 + . += realOverlay + +/obj/item/clothing/neck/neckerchief/AltClick(mob/user) + . = ..() + if(iscarbon(user)) + var/mob/living/carbon/C = user + if(C.get_item_by_slot(SLOT_NECK) == src) + to_chat(user, "You can't untie [src] while wearing it!") + return + if(user.is_holding(src)) + var/obj/item/clothing/mask/bandana/newBand = new sourceBandanaType(user) + var/currentHandIndex = user.get_held_index_of_item(src) + var/oldName = src.name + qdel(src) + user.put_in_hand(newBand, currentHandIndex) + user.visible_message("You untie [oldName] back into a [newBand.name]", "[user] unties [oldName] back into a [newBand.name]") + else + to_chat(user, "You must be holding [src] in order to untie it!") From 3fa39fd7abc2ddb93300b3a8b3afcdc3af4e0507 Mon Sep 17 00:00:00 2001 From: ZeroMan Date: Thu, 12 Mar 2020 20:57:41 -0400 Subject: [PATCH 27/61] i hate my ocd --- code/modules/clothing/neck/_neck.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index f24d90f7fe..530af7777d 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -295,6 +295,7 @@ ////////////////////////////////// //VERY SUPER BADASS NECKERCHIEFS// ////////////////////////////////// + obj/item/clothing/neck/neckerchief icon = 'icons/obj/clothing/masks.dmi' //In order to reuse the bandana sprite w_class = WEIGHT_CLASS_TINY From 0ca58b5ed85ede8254db113fef7263866f9875eb Mon Sep 17 00:00:00 2001 From: Lin Date: Fri, 13 Mar 2020 04:19:20 +0000 Subject: [PATCH 28/61] why though --- code/game/objects/items/storage/firstaid.dm | 8 -------- 1 file changed, 8 deletions(-) diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm index 0ff20f16c5..c9c686414d 100644 --- a/code/game/objects/items/storage/firstaid.dm +++ b/code/game/objects/items/storage/firstaid.dm @@ -525,14 +525,6 @@ desc = "A kit containing a Deluxe hypospray and Vials." icon_state = "tactical-mini" -/obj/item/storage/hypospraykit/cmo/ComponentInitialize() - . = ..() - var/datum/component/storage/STR = GetComponent(/datum/component/storage) - STR.max_items = 6 - STR.can_hold = typecacheof(list( - /obj/item/hypospray/mkii, - /obj/item/reagent_containers/glass/bottle/vial)) - /obj/item/storage/hypospraykit/cmo/PopulateContents() if(empty) return From 49c0aba205fa98234ef5db86293fcfcd17aac1a1 Mon Sep 17 00:00:00 2001 From: necromanceranne Date: Sat, 14 Mar 2020 04:25:12 +1100 Subject: [PATCH 29/61] bleeding out from a toolbox smack is not cool gamers --- code/_onclick/item_attack.dm | 6 +----- code/modules/mob/living/carbon/carbon_defense.dm | 3 ++- code/modules/mob/living/carbon/human/species.dm | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index cba53eb4a5..2fa2a8e85f 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -125,11 +125,7 @@ if(prob(33)) I.add_mob_blood(src) var/turf/location = get_turf(src) - if(iscarbon(src)) - var/mob/living/carbon/C = src - C.bleed(totitemdamage) - else - add_splatter_floor(location) + add_splatter_floor(location) if(totitemdamage >= 10 && get_dist(user, src) <= 1) //people with TK won't get smeared with blood user.add_mob_blood(src) return TRUE //successful attack diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 5bbc6d6a64..ad8837e149 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -104,7 +104,8 @@ var/basebloodychance = affecting.brute_dam + totitemdamage if(prob(basebloodychance)) I.add_mob_blood(src) - bleed(totitemdamage) + var/turf/location = get_turf(src) + add_splatter_floor(location) if(totitemdamage >= 10 && get_dist(user, src) <= 1) //people with TK won't get smeared with blood user.add_mob_blood(src) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 85a7a09d5c..ad98a4500d 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1712,7 +1712,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) bloody = 1 var/turf/location = H.loc if(istype(location)) - H.bleed(totitemdamage) + H.add_splatter_floor(location) if(get_dist(user, H) <= 1) //people with TK won't get smeared with blood user.add_mob_blood(H) From 487c18cb7ea7e1d55dfdc38594f277dd2ba8312c Mon Sep 17 00:00:00 2001 From: Trilbyspaceclone <30435998+Trilbyspaceclone@users.noreply.github.com> Date: Fri, 13 Mar 2020 14:20:28 -0400 Subject: [PATCH 30/61] Update misc.dm --- code/modules/cargo/packs/misc.dm | 57 ++++++++++---------------------- 1 file changed, 18 insertions(+), 39 deletions(-) diff --git a/code/modules/cargo/packs/misc.dm b/code/modules/cargo/packs/misc.dm index d9c9794bd8..80d6f76910 100644 --- a/code/modules/cargo/packs/misc.dm +++ b/code/modules/cargo/packs/misc.dm @@ -89,32 +89,17 @@ /datum/supply_pack/misc/paper_work name = "Freelance Paper work" - desc = "The Nanotrasen Primary Bureaucratic Database Intelligence (PDBI) reports that the station has not completed its funding and grant paperwork this solar cycle. In order to gain further funding, your station is required to fill out (20) ten of these forms or no additional capital will be disbursed. We have sent you ten copies of the following form and we expect every one to be up to Nanotrasen Standards." // Disbursement. It's not a typo, look it up. - cost = 700 // Net of 0 credits but makes (120 x 20 = 2400) + desc = "The Nanotrasen Primary Bureaucratic Database Intelligence (PDBI) reports that the station has not completed its funding and grant paperwork this solar cycle. In order to gain further funding, your station is required to fill out (10) ten of these forms or no additional capital will be disbursed. We have sent you ten copies of the following form and we expect every one to be up to Nanotrasen Standards." // Disbursement. It's not a typo, look it up. + cost = 700 // Net of 0 credits but makes (120 x 10 = 1200) contains = list(/obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, - /obj/item/folder/paperwork, /obj/item/pen/fountain ) crate_name = "Paperwork" +/datum/supply_pack/misc/paper_work/generate() + . = ..() + for(var/i in 1 to 9) + new /obj/item/folder/paperwork(.) ////////////////////////////////////////////////////////////////////////////// //////////////////////////////// Entertainment /////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -123,16 +108,14 @@ name = "Bedsheet Crate (R)" desc = "Snuggle up in some sweet sheets with this assorted bedsheet crate. Each set comes with eight random bedsheets for your slumbering pleasure!" cost = 2000 - contains = list(/obj/item/bedsheet/random, - /obj/item/bedsheet/random, - /obj/item/bedsheet/random, - /obj/item/bedsheet/random, - /obj/item/bedsheet/random, - /obj/item/bedsheet/random, - /obj/item/bedsheet/random, - /obj/item/bedsheet/random) //I'm lazy, and I copy paste stuff. + contains = list(/obj/item/bedsheet/random) crate_name = "random bedsheet crate" +/datum/supply_pack/misc/randombedsheets/generate() + . = ..() + for(var/i in 1 to 7) + new /obj/item/bedsheet/random(.) + /datum/supply_pack/misc/coloredsheets name = "Bedsheet Crate (C)" desc = "Give your night life a splash of color with this crate filled with bedsheets! Contains a total of nine different-colored sheets." @@ -208,13 +191,14 @@ name = "Dueling Pistols" desc = "Resolve all your quarrels with some nonlethal fun." cost = 2000 - contains = list(/obj/item/storage/lockbox/dueling/hugbox/stamina, - /obj/item/storage/lockbox/dueling/hugbox/stamina, - /obj/item/storage/lockbox/dueling/hugbox/stamina, - /obj/item/storage/lockbox/dueling/hugbox/stamina, - /obj/item/storage/lockbox/dueling/hugbox/stamina) + contains = list(/obj/item/storage/lockbox/dueling/hugbox/stamina) crate_name = "dueling pistols" +/datum/supply_pack/misc/dueling_stam/generate() + . = ..() + for(var/i in 1 to 3) + new /obj/item/storage/lockbox/dueling/hugbox/stamina(.) + /datum/supply_pack/misc/dueling_lethal name = "Lethal Dueling Pistols" desc = "Settle your differences the true spaceman way." @@ -240,12 +224,7 @@ cost = 12000 var/num_contained = 3 contains = list(/obj/item/ammo_box/a357, - /obj/item/ammo_box/a357, - /obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/pistolm9mm, - /obj/item/ammo_box/magazine/pistolm9mm, - /obj/item/ammo_box/magazine/pistolm9mm, - /obj/item/ammo_box/magazine/m45/kitchengun, /obj/item/ammo_box/magazine/m45/kitchengun) crate_name = "crate" From 888f67c4bc98d4789b32ba3c010004d23a3cadd7 Mon Sep 17 00:00:00 2001 From: Trilbyspaceclone <30435998+Trilbyspaceclone@users.noreply.github.com> Date: Fri, 13 Mar 2020 18:21:12 -0400 Subject: [PATCH 31/61] Update borghydro.dm --- code/modules/reagents/reagent_containers/borghydro.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index 73d0c5eafa..170ff64138 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -28,7 +28,7 @@ Borg Hypospray var/list/datum/reagents/reagent_list = list() var/list/reagent_ids = list(/datum/reagent/medicine/dexalin, /datum/reagent/medicine/kelotane, /datum/reagent/medicine/bicaridine, /datum/reagent/medicine/antitoxin, - /datum/reagent/medicine/epinephrine, /datum/reagent/medicine/spaceacillin, /datum/reagent/medicine/salglu_solution, /datum/reagent/medicine/insulin) + /datum/reagent/medicine/epinephrine, /datum/reagent/medicine/spaceacillin, /datum/reagent/medicine/salglu_solution, /datum/reagent/medicine/insulin, /datum/reagent/medicine/potass_iodide) var/accepts_reagent_upgrades = TRUE //If upgrades can increase number of reagents dispensed. var/list/modes = list() //Basically the inverse of reagent_ids. Instead of having numbers as "keys" and strings as values it has strings as keys and numbers as values. //Used as list for input() in shakers. @@ -164,7 +164,7 @@ Borg Hypospray icon_state = "borghypo_s" charge_cost = 20 recharge_time = 2 - reagent_ids = list(/datum/reagent/medicine/syndicate_nanites, /datum/reagent/medicine/potass_iodide, /datum/reagent/medicine/morphine, /datum/reagent/medicine/insulin) + reagent_ids = list(/datum/reagent/medicine/syndicate_nanites, /datum/reagent/medicine/prussian_blue, /datum/reagent/medicine/morphine, /datum/reagent/medicine/insulin) bypass_protection = 1 accepts_reagent_upgrades = FALSE @@ -261,5 +261,5 @@ Borg Shaker /obj/item/reagent_containers/borghypo/epi name = "Stabilizer injector" desc = "An advanced chemical synthesizer and injection system, designed to stabilize patients." - reagent_ids = list(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/insulin) + reagent_ids = list(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/insulin, /datum/reagent/medicine/potass_iodide) accepts_reagent_upgrades = FALSE From 6993dfde2aca001378cf94f817d690a21d0b744b Mon Sep 17 00:00:00 2001 From: Trilbyspaceclone <30435998+Trilbyspaceclone@users.noreply.github.com> Date: Fri, 13 Mar 2020 18:29:46 -0400 Subject: [PATCH 32/61] Now stocked at your local robotics --- code/game/objects/items/robot/robot_upgrades.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 56af03139a..28a93a7a83 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -462,7 +462,7 @@ desc = "An upgrade to the Medical module's hypospray, containing \ stronger versions of existing chemicals." additional_reagents = list(/datum/reagent/medicine/oxandrolone, /datum/reagent/medicine/sal_acid, - /datum/reagent/medicine/rezadone, /datum/reagent/medicine/pen_acid) + /datum/reagent/medicine/rezadone, /datum/reagent/medicine/pen_acid, /datum/reagent/medicine/prussian_blue) /obj/item/borg/upgrade/piercing_hypospray name = "cyborg piercing hypospray" From 888cdbeaf64bee10c036616b03cea5450f5812a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Mar 2020 23:43:45 +0000 Subject: [PATCH 33/61] Bump minimist from 1.2.0 to 1.2.2 in /tgui Bumps [minimist](https://github.com/substack/minimist) from 1.2.0 to 1.2.2. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.0...1.2.2) Signed-off-by: dependabot[bot] --- tgui/package-lock.json | 6 +++--- tgui/package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tgui/package-lock.json b/tgui/package-lock.json index 470e5c2d23..d2567aba36 100644 --- a/tgui/package-lock.json +++ b/tgui/package-lock.json @@ -5480,9 +5480,9 @@ } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-rIqbOrKb8GJmx/5bc2M0QchhUouMXSpd1RTclXsB41JdL+VtnojfaJR+h7F9k18/4kHUsBFgk80Uk+q569vjPA==" }, "mixin-deep": { "version": "1.3.2", diff --git a/tgui/package.json b/tgui/package.json index dd81c3b318..85d47ecfe7 100644 --- a/tgui/package.json +++ b/tgui/package.json @@ -35,7 +35,7 @@ "html5shiv": "3.7.3", "ie8": "0.8.1", "lodash": "^4.17.15", - "minimist": "1.2.0", + "minimist": "1.2.2", "paths-js": "0.4.10", "pleeease-filters": "2.0.0", "postcss": "7.0.18", From d9dc91db1aa99931e5d95146d28ddc01ed1a0efa Mon Sep 17 00:00:00 2001 From: Putnam3145 Date: Fri, 13 Mar 2020 18:49:25 -0700 Subject: [PATCH 34/61] More dynamic fixes (#11451) * Fixed wizard, malf AI * changed memes typename to story * Fixed a bunch of really weird execute/ready confusion * Added dynamic requirement to wands. --- .../dynamic/dynamic_rulesets_midround.dm | 25 ++++++++++++------- .../gamemodes/dynamic/dynamic_storytellers.dm | 2 +- .../antagonists/wizard/equipment/spellbook.dm | 2 ++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index a2639a7ece..36b81afc26 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -273,10 +273,14 @@ var/ion_announce = 33 var/removeDontImproveChance = 10 +/datum/dynamic_ruleset/midround/malf/ready() + if(!candidates || !candidates.len) + return FALSE + return ..() + /datum/dynamic_ruleset/midround/malf/trim_candidates() ..() - living_players = candidates[CURRENT_LIVING_PLAYERS] - for(var/mob/living/player in candidates) + for(var/mob/living/player in living_players) if(!isAI(player)) candidates -= player continue @@ -287,8 +291,6 @@ candidates -= player /datum/dynamic_ruleset/midround/malf/execute() - if(!candidates || !candidates.len) - return FALSE var/mob/living/silicon/ai/M = pick_n_take(candidates) assigned += M.mind var/datum/antagonist/traitor/AI = new @@ -337,6 +339,7 @@ /datum/dynamic_ruleset/midround/from_ghosts/wizard/finish_setup(mob/new_character, index) ..() new_character.forceMove(pick(GLOB.wizardstart)) + wizard = new_character.mind /datum/dynamic_ruleset/midround/from_ghosts/wizard/rule_process() // i can literally copy this from are_special_antags_dead it's great if(isliving(wizard.current) && wizard.current.stat!=DEAD) @@ -447,9 +450,7 @@ property_weights = list("story_potential" = -1, "trust" = 1, "chaos" = 2, "extended" = -2, "valid" = 2) var/list/vents = list() -/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/execute() - // 50% chance of being incremented by one - required_candidates += prob(50) +/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/ready() for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in GLOB.machines) if(QDELETED(temp_vent)) continue @@ -463,6 +464,12 @@ vents += temp_vent if(!vents.len) return FALSE + return ..() + + +/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/execute() + // 50% chance of being incremented by one + required_candidates += prob(50) . = ..() /datum/dynamic_ruleset/midround/from_ghosts/xenomorph/generate_ruleset_body(mob/applicant) @@ -497,7 +504,7 @@ property_weights = list("story_potential" = 1, "trust" = 1, "extended" = 1, "valid" = 2, "integrity" = 1) var/list/spawn_locs = list() -/datum/dynamic_ruleset/midround/from_ghosts/nightmare/execute() +/datum/dynamic_ruleset/midround/from_ghosts/nightmare/ready() for(var/X in GLOB.xeno_spawn) var/turf/T = X var/light_amount = T.get_lumcount() @@ -505,7 +512,7 @@ spawn_locs += T if(!spawn_locs.len) return FALSE - . = ..() + return ..() /datum/dynamic_ruleset/midround/from_ghosts/nightmare/generate_ruleset_body(mob/applicant) var/datum/mind/player_mind = new /datum/mind(applicant.key) diff --git a/code/game/gamemodes/dynamic/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm index dec7b921db..d25416a4d1 100644 --- a/code/game/gamemodes/dynamic/dynamic_storytellers.dm +++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm @@ -232,7 +232,7 @@ Property weights are: pop_antag_ratio = 7 flags = USE_PREF_WEIGHTS -/datum/dynamic_storyteller/memes +/datum/dynamic_storyteller/story name = "Story" config_tag = "story" desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies." diff --git a/code/modules/antagonists/wizard/equipment/spellbook.dm b/code/modules/antagonists/wizard/equipment/spellbook.dm index 70cb29e7a3..5ef3f24bd6 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook.dm @@ -375,6 +375,8 @@ desc = "A collection of wands that allow for a wide variety of utility. Wands have a limited number of charges, so be conservative in use. Comes in a handy belt." item_path = /obj/item/storage/belt/wands/full category = "Defensive" + dynamic_requirement = 60 + dynamic_cost = 10 /datum/spellbook_entry/item/armor name = "Mastercrafted Armor Set" From c8922547de6e076a7367ecdcc0f111d0d335b0ae Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Fri, 13 Mar 2020 20:49:28 -0500 Subject: [PATCH 35/61] Automatic changelog generation for PR #11451 [ci skip] --- html/changelogs/AutoChangeLog-pr-11451.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11451.yml diff --git a/html/changelogs/AutoChangeLog-pr-11451.yml b/html/changelogs/AutoChangeLog-pr-11451.yml new file mode 100644 index 0000000000..bc3acb86ea --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11451.yml @@ -0,0 +1,4 @@ +author: "Putnam3145" +delete-after: True +changes: + - bugfix: "More dynamic fixes" From a2592483b549de5358b1cbb420394ed6212ab98f Mon Sep 17 00:00:00 2001 From: Kraseo Date: Sat, 14 Mar 2020 13:07:13 +0100 Subject: [PATCH 36/61] hey did you know there's not one, not two, but three tiles on roid7.dmm that don't have /area/ruin/space but rather /area/ruin/unpowered? yeah i'm angry too --- code/game/gamemodes/objective.dm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index a4b1f68265..b0092d8d67 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1163,12 +1163,16 @@ GLOBAL_LIST_EMPTY(possible_sabotages) var/payout = 0 var/payout_bonus = 0 var/area/dropoff = null + var/static/list/blacklisted_areas = typecacheof(list(/area/ai_monitored/turret_protected, + /area/solar/, + /area/ruin/, //thank you station space ruins + /area/science/test_area/)) /datum/objective/contract/proc/generate_dropoff() // Generate a random valid area on the station that the dropoff will happen. var/found = FALSE while(!found) var/area/dropoff_area = pick(GLOB.sortedAreas) - if(dropoff_area && is_station_level(dropoff_area.z) && !dropoff_area.outdoors && !istype(dropoff_area, /area/shuttle/)) + if(dropoff_area && is_station_level(dropoff_area.z) && !dropoff_area.outdoors && !is_type_in_typecache(dropoff_area, blacklisted_areas)) dropoff = dropoff_area found = TRUE From 3f44882c1ac662091a4b0abc610fa3e24474ca14 Mon Sep 17 00:00:00 2001 From: Kraseo Date: Sat, 14 Mar 2020 13:13:26 +0100 Subject: [PATCH 37/61] FUCK --- code/game/gamemodes/objective.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index b0092d8d67..192153535d 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1166,7 +1166,8 @@ GLOBAL_LIST_EMPTY(possible_sabotages) var/static/list/blacklisted_areas = typecacheof(list(/area/ai_monitored/turret_protected, /area/solar/, /area/ruin/, //thank you station space ruins - /area/science/test_area/)) + /area/science/test_area/, + /area/shuttle)) /datum/objective/contract/proc/generate_dropoff() // Generate a random valid area on the station that the dropoff will happen. var/found = FALSE From f8a365490bbdca6f4ae72354364db8403ea2dce1 Mon Sep 17 00:00:00 2001 From: Kraseo Date: Sat, 14 Mar 2020 13:15:09 +0100 Subject: [PATCH 38/61] =?UTF-8?q?FUCK=C2=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/game/gamemodes/objective.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 192153535d..b42b41aba4 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1167,7 +1167,7 @@ GLOBAL_LIST_EMPTY(possible_sabotages) /area/solar/, /area/ruin/, //thank you station space ruins /area/science/test_area/, - /area/shuttle)) + /area/shuttle/)) /datum/objective/contract/proc/generate_dropoff() // Generate a random valid area on the station that the dropoff will happen. var/found = FALSE From 09afc316732762fd2d333463d15968ea99205b7a Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sat, 14 Mar 2020 11:09:14 -0500 Subject: [PATCH 39/61] Automatic changelog generation for PR #11448 [ci skip] --- html/changelogs/AutoChangeLog-pr-11448.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11448.yml diff --git a/html/changelogs/AutoChangeLog-pr-11448.yml b/html/changelogs/AutoChangeLog-pr-11448.yml new file mode 100644 index 0000000000..de94aa1e0d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11448.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "The autotransfer subsystem is slightly more modulable now." From 46edd143e7eef572036660b81c8330f026b5defe Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sat, 14 Mar 2020 11:09:53 -0500 Subject: [PATCH 40/61] Automatic changelog generation for PR #11447 [ci skip] --- html/changelogs/AutoChangeLog-pr-11447.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11447.yml diff --git a/html/changelogs/AutoChangeLog-pr-11447.yml b/html/changelogs/AutoChangeLog-pr-11447.yml new file mode 100644 index 0000000000..4ada92210c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11447.yml @@ -0,0 +1,4 @@ +author: "spookydonut" +delete-after: True +changes: + - code_imp: "adds selective duplicate component mode" From a858316bdbef72a5d740433fe1be474667dc968a Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sat, 14 Mar 2020 11:10:57 -0500 Subject: [PATCH 41/61] Automatic changelog generation for PR #11437 [ci skip] --- html/changelogs/AutoChangeLog-pr-11437.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11437.yml diff --git a/html/changelogs/AutoChangeLog-pr-11437.yml b/html/changelogs/AutoChangeLog-pr-11437.yml new file mode 100644 index 0000000000..4bb865e6f9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11437.yml @@ -0,0 +1,8 @@ +author: "keronshb" +delete-after: True +changes: + - balance: "blobs now receive a 50% cost refund on attacks that don't spread" + - balance: "reflector blobs are considerably tougher" + - bugfix: "fixed an integrity" + - bugfix: "attempting to turn a damaged strong blob into a reflector blob now refunds points" + - bugfix: "also fixes blob node camera jump (from another PR)" From fe915189e4ca029c01b73ee8c4ae57a69872791a Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sat, 14 Mar 2020 11:11:15 -0500 Subject: [PATCH 42/61] Automatic changelog generation for PR #11436 [ci skip] --- html/changelogs/AutoChangeLog-pr-11436.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11436.yml diff --git a/html/changelogs/AutoChangeLog-pr-11436.yml b/html/changelogs/AutoChangeLog-pr-11436.yml new file mode 100644 index 0000000000..26ddaa7f69 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11436.yml @@ -0,0 +1,4 @@ +author: "MrJWhit" +delete-after: True +changes: + - tweak: "Removed egun in every head locker, replaces RPD with air pump in science, fixes a computer in sec, moves hand teleporter, and removes decals under lockers." From 3cc584a040404ce482df46c5f9b529f5385053ff Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sat, 14 Mar 2020 11:11:41 -0500 Subject: [PATCH 43/61] Automatic changelog generation for PR #11453 [ci skip] --- html/changelogs/AutoChangeLog-pr-11453.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11453.yml diff --git a/html/changelogs/AutoChangeLog-pr-11453.yml b/html/changelogs/AutoChangeLog-pr-11453.yml new file mode 100644 index 0000000000..0113ea3dd6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11453.yml @@ -0,0 +1,4 @@ +author: "necromanceranne" +delete-after: True +changes: + - bugfix: "Bleeding out all your blood from getting love tapped by a toolbox." From e343dde291efa8426e0b5ad782ec8857682ce38d Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sat, 14 Mar 2020 11:12:00 -0500 Subject: [PATCH 44/61] Automatic changelog generation for PR #11452 [ci skip] --- html/changelogs/AutoChangeLog-pr-11452.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11452.yml diff --git a/html/changelogs/AutoChangeLog-pr-11452.yml b/html/changelogs/AutoChangeLog-pr-11452.yml new file mode 100644 index 0000000000..8ec140d5b0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11452.yml @@ -0,0 +1,4 @@ +author: "Linzolle" +delete-after: True +changes: + - tweak: "cmo hypokit now holds the same amount of items as normal kits" From cda2ace252871b0904c5d36f3d7da23ceb4bf152 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sat, 14 Mar 2020 11:12:15 -0500 Subject: [PATCH 45/61] Automatic changelog generation for PR #11450 [ci skip] --- html/changelogs/AutoChangeLog-pr-11450.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11450.yml diff --git a/html/changelogs/AutoChangeLog-pr-11450.yml b/html/changelogs/AutoChangeLog-pr-11450.yml new file mode 100644 index 0000000000..748c1f94c2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11450.yml @@ -0,0 +1,4 @@ +author: "zeroisthebiggay" +delete-after: True +changes: + - rscadd: "Space Fashion has discovered a new way to wear bandannas. With some simple minor adjustments and ties, bandannas can be made into fashionable neckerchiefs!" From 06d641b46a7a853394b7345371abd819a0cf30ff Mon Sep 17 00:00:00 2001 From: Ghom <42542238+Ghommie@users.noreply.github.com> Date: Sat, 14 Mar 2020 21:19:09 +0100 Subject: [PATCH 46/61] Webedit fixing electrocute_act stuns. --- code/modules/mob/living/carbon/carbon_defense.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 646e41f94c..8bd1a35e07 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -264,11 +264,11 @@ jitteriness += 1000 //High numbers for violent convulsions do_jitter_animation(jitteriness) stuttering += 2 - if((!(flags & SHOCK_TESLA) || siemens_coeff > 0.5) && (flags & SHOCK_NOSTUN)) + if((!(flags & SHOCK_TESLA) || siemens_coeff > 0.5) && !(flags & SHOCK_NOSTUN)) Stun(40) spawn(20) jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less - if((!(flags & SHOCK_TESLA) || siemens_coeff > 0.5) && (flags & SHOCK_NOSTUN)) + if((!(flags & SHOCK_TESLA) || siemens_coeff > 0.5) && !(flags & SHOCK_NOSTUN)) DefaultCombatKnockdown(60) return shock_damage From e73e1b03eced2ea4f36b0a6b6f7a1932c66e4e84 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sat, 14 Mar 2020 15:14:57 -0700 Subject: [PATCH 47/61] Revert "Stunbaton disarm mode also works on disarm intent now" (#11446) --- code/game/objects/items/stunbaton.dm | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index 3079c3cad9..78ba6d4f5f 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -25,7 +25,7 @@ /obj/item/melee/baton/examine(mob/user) . = ..() - . += "Right click attack while in combat mode or attack while in disarm intent to disarm instead of stun." + . += "Right click attack while in combat mode to disarm instead of stun." /obj/item/melee/baton/get_cell() . = cell @@ -149,8 +149,6 @@ //return TRUE to interrupt attack chain. /obj/item/melee/baton/proc/common_baton_melee(mob/M, mob/living/user, disarming = FALSE) - if(user.a_intent == INTENT_DISARM) - disarming = TRUE //override if they're in disarm intent. if(iscyborg(M) || !isliving(M)) //can't baton cyborgs return FALSE if(status && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) From d34d46f00da4d76e0fa05ad064db8d3f4b61954c Mon Sep 17 00:00:00 2001 From: Kraseo Date: Sun, 15 Mar 2020 04:03:50 +0100 Subject: [PATCH 48/61] i think you're a thief cause you stole my heart, stole my heart, trapped my soul like azura's star (#11461) --- .../bloodsucker/bloodsucker_objectives.dm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_objectives.dm b/code/modules/antagonists/bloodsucker/bloodsucker_objectives.dm index a2a0238df1..0c80ce0dee 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_objectives.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_objectives.dm @@ -43,7 +43,7 @@ // EXPLANATION /datum/objective/bloodsucker/lair/update_explanation_text() - explanation_text = "Create a lair by claiming a coffin, and protect it until the end of the shift"// Make sure to keep it safe!" + explanation_text = "Create a lair by claiming a coffin, and protect it until the end of the shift."// Make sure to keep it safe!" // WIN CONDITIONS? /datum/objective/bloodsucker/lair/check_completion() @@ -228,7 +228,7 @@ if (SC && SC.lastgen > 0 && SC.connected_panels.len > 0 && SC.connected_tracker) return FALSE return TRUE -*/ +*/ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -250,15 +250,15 @@ // WIN CONDITIONS? /datum/objective/bloodsucker/heartthief/check_completion() // -Must have a body. - if (!owner.current) + if(!owner.current) return FALSE // Taken from /steal in objective.dm var/list/all_items = owner.current.GetAllContents() // Includes items inside other items. var/itemcount = FALSE for(var/obj/I in all_items) //Check for items - if(I == /obj/item/organ/heart) - itemcount ++ - if (itemcount >= target_amount) // Got the right amount? + if(istype(I, /obj/item/organ/heart/)) + itemcount++ + if(itemcount >= target_amount) // Got the right amount? return TRUE return FALSE From 83b34a053b413637345ab443bf9b84925aed51ed Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sat, 14 Mar 2020 22:03:53 -0500 Subject: [PATCH 49/61] Automatic changelog generation for PR #11461 [ci skip] --- html/changelogs/AutoChangeLog-pr-11461.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11461.yml diff --git a/html/changelogs/AutoChangeLog-pr-11461.yml b/html/changelogs/AutoChangeLog-pr-11461.yml new file mode 100644 index 0000000000..547a2c58e1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11461.yml @@ -0,0 +1,4 @@ +author: "Kraseo" +delete-after: True +changes: + - bugfix: "Bloodsucker heart theft objective now completes successfully." From 52e20cdadf8471a3d96a02c0e823dc3c130d9ed1 Mon Sep 17 00:00:00 2001 From: Putnam3145 Date: Sat, 14 Mar 2020 20:04:05 -0700 Subject: [PATCH 50/61] Made server votes not subject to the cooldown (#11464) --- code/controllers/subsystem/vote.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index ac0acfb61d..e7e5754f6b 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -443,7 +443,7 @@ SUBSYSTEM_DEF(vote) var/admin = FALSE var/ckey = ckey(initiator_key) - if(GLOB.admin_datums[ckey]) + if(GLOB.admin_datums[ckey] || initiator_key == "server") admin = TRUE if(next_allowed_time > world.time && !admin) From b66614635c54cec30f6b2405586764dfe6ec100e Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sat, 14 Mar 2020 22:04:08 -0500 Subject: [PATCH 51/61] Automatic changelog generation for PR #11464 [ci skip] --- html/changelogs/AutoChangeLog-pr-11464.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11464.yml diff --git a/html/changelogs/AutoChangeLog-pr-11464.yml b/html/changelogs/AutoChangeLog-pr-11464.yml new file mode 100644 index 0000000000..cc59b44a30 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11464.yml @@ -0,0 +1,4 @@ +author: "Putnam3145" +delete-after: True +changes: + - bugfix: "Server-run votes aren't subject to vote cooldown" From bee11a2ee516548e36c76ecef7dff02e13b01b31 Mon Sep 17 00:00:00 2001 From: Kraseo Date: Sun, 15 Mar 2020 04:04:35 +0100 Subject: [PATCH 52/61] no i am not testing if mice can chew wires if they're in a stomach now shut the fuck up (#11460) --- code/modules/mob/living/simple_animal/friendly/mouse.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index c5a4fa6e1e..370442d4c4 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -64,7 +64,7 @@ ..() /mob/living/simple_animal/mouse/handle_automated_action() - if(isbelly(loc)) + if(!isturf(loc)) return if(prob(chew_probability)) @@ -76,7 +76,7 @@ visible_message("[src] chews through the [C]. It's toast!") playsound(src, 'sound/effects/sparks2.ogg', 100, 1) C.deconstruct() - death(toast=1) + death(toast=TRUE) else C.deconstruct() visible_message("[src] chews through the [C].") From fe886fed4700dc486199d7195eb4cb3941c79b16 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sat, 14 Mar 2020 22:04:38 -0500 Subject: [PATCH 53/61] Automatic changelog generation for PR #11460 [ci skip] --- html/changelogs/AutoChangeLog-pr-11460.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11460.yml diff --git a/html/changelogs/AutoChangeLog-pr-11460.yml b/html/changelogs/AutoChangeLog-pr-11460.yml new file mode 100644 index 0000000000..1c8fb3e3fa --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11460.yml @@ -0,0 +1,4 @@ +author: "Kraseo" +delete-after: True +changes: + - bugfix: "Mice don't chew on wires anymore while they're on your person." From bfd001d1652ed4d8420441423c0651f7f9addf92 Mon Sep 17 00:00:00 2001 From: Seris02 <49109742+Seris02@users.noreply.github.com> Date: Sun, 15 Mar 2020 11:04:50 +0800 Subject: [PATCH 54/61] quirk fixes (#11466) --- code/controllers/subsystem/processing/quirks.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/controllers/subsystem/processing/quirks.dm b/code/controllers/subsystem/processing/quirks.dm index 10655981e5..5aeaf43bab 100644 --- a/code/controllers/subsystem/processing/quirks.dm +++ b/code/controllers/subsystem/processing/quirks.dm @@ -85,7 +85,7 @@ PROCESSING_SUBSYSTEM_DEF(quirks) our_quirks -= i cut += i pointscut += quirk_points_by_name(i) - if (pointscut >= 0) //with how it works, it needs to be above zero, not below, as points for positive is positive, and negative is negative, we only want it to break if it's above zero, ie. we cut more positive than negative + if (pointscut >= 0) break /* //Code to automatically reduce positive quirks until balance is even. var/points_used = total_points(our_quirks) @@ -102,7 +102,7 @@ PROCESSING_SUBSYSTEM_DEF(quirks) */ //Nah, let's null all non-neutrals out. - if (pointscut != 0)// only if the pointscutting didn't work. + if (pointscut < 0)// only if the pointscutting didn't work. if(cut.len) for(var/i in our_quirks) if(quirk_points_by_name(i) != 0) From 59be47b911bb842bd308a8ae70a0a523d887dcce Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sat, 14 Mar 2020 22:04:53 -0500 Subject: [PATCH 55/61] Automatic changelog generation for PR #11466 [ci skip] --- html/changelogs/AutoChangeLog-pr-11466.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11466.yml diff --git a/html/changelogs/AutoChangeLog-pr-11466.yml b/html/changelogs/AutoChangeLog-pr-11466.yml new file mode 100644 index 0000000000..c5d60c84c2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11466.yml @@ -0,0 +1,4 @@ +author: "Seris02" +delete-after: True +changes: + - bugfix: "quirk blacklist fixing" From 23e9ecf97cd7527256de93f78058541669be3998 Mon Sep 17 00:00:00 2001 From: bunny232 Date: Sat, 14 Mar 2020 23:05:04 -0400 Subject: [PATCH 56/61] Update BoxStation.dmm (#11456) --- _maps/map_files/BoxStation/BoxStation.dmm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 1d57752822..3e569c22f6 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -260,6 +260,11 @@ /obj/structure/chair/stool, /turf/open/floor/plasteel, /area/security/prison) +"aaK" = ( +/obj/structure/table/wood, +/mob/living/simple_animal/pet/fox/Renault, +/turf/open/floor/carpet, +/area/crew_quarters/heads/captain) "aaN" = ( /obj/structure/chair/sofa/right, /turf/open/floor/plasteel, @@ -21528,10 +21533,6 @@ /obj/structure/table, /turf/open/floor/wood, /area/bridge/meeting_room) -"bbZ" = ( -/obj/structure/table/wood, -/turf/open/floor/carpet, -/area/crew_quarters/heads/captain) "bca" = ( /turf/open/floor/carpet, /area/bridge/meeting_room) @@ -90412,7 +90413,7 @@ aYo aZV bao baP -bbZ +aaK bcP cBo bgS From ad46096384825780abd57a862616ef3c4c6e217e Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sat, 14 Mar 2020 22:05:06 -0500 Subject: [PATCH 57/61] Automatic changelog generation for PR #11456 [ci skip] --- html/changelogs/AutoChangeLog-pr-11456.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11456.yml diff --git a/html/changelogs/AutoChangeLog-pr-11456.yml b/html/changelogs/AutoChangeLog-pr-11456.yml new file mode 100644 index 0000000000..b5a9353d33 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11456.yml @@ -0,0 +1,4 @@ +author: "bunny232" +delete-after: True +changes: + - rscadd: "Box station captain office now has a standard issue renault" From 3c5f382f62c5b362f1801362db78a6f3599267c8 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 15 Mar 2020 00:11:24 -0500 Subject: [PATCH 58/61] Automatic changelog generation for PR #11467 [ci skip] --- html/changelogs/AutoChangeLog-pr-11467.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11467.yml diff --git a/html/changelogs/AutoChangeLog-pr-11467.yml b/html/changelogs/AutoChangeLog-pr-11467.yml new file mode 100644 index 0000000000..5b59fc2e7b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11467.yml @@ -0,0 +1,4 @@ +author: "Kraseo" +delete-after: True +changes: + - tweak: "Blacklists turret protected areas, the toxins test range, asteroid ruins, and solars from being valid dropoff locations for contracts." From 46d05053fd35f0476bb2ed585e5a7b06562bc6f1 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 15 Mar 2020 00:21:34 -0500 Subject: [PATCH 59/61] Automatic changelog generation for PR #11458 [ci skip] --- html/changelogs/AutoChangeLog-pr-11458.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11458.yml diff --git a/html/changelogs/AutoChangeLog-pr-11458.yml b/html/changelogs/AutoChangeLog-pr-11458.yml new file mode 100644 index 0000000000..14e8d7d650 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11458.yml @@ -0,0 +1,5 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - rscadd: "Potass Iodide has been fitted into standered borgs as well as medical ones. Upgraded hypos now have Prussian Blue as well." + - tweak: "Syndi borgs Potass Iodide has been swapped for Prussian Blue" From f91d30dae5bb815ff615244d12f69d97b250e730 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 15 Mar 2020 00:22:18 -0500 Subject: [PATCH 60/61] Automatic changelog generation for PR #11455 [ci skip] --- html/changelogs/AutoChangeLog-pr-11455.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11455.yml diff --git a/html/changelogs/AutoChangeLog-pr-11455.yml b/html/changelogs/AutoChangeLog-pr-11455.yml new file mode 100644 index 0000000000..a54556673e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11455.yml @@ -0,0 +1,5 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - tweak: "Number of paper work in the crate \"freelance paperwork\" is half" + - code_imp: "A few cases were something their is unneeded copy past replaced with many 1 in spawns" From 685485acf99a944d77e7120b46af2e5bd90cec4f Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 15 Mar 2020 03:35:34 -0500 Subject: [PATCH 61/61] Automatic changelog generation for PR #11290 [ci skip] --- html/changelogs/AutoChangeLog-pr-11290.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-11290.yml diff --git a/html/changelogs/AutoChangeLog-pr-11290.yml b/html/changelogs/AutoChangeLog-pr-11290.yml new file mode 100644 index 0000000000..726a8ee797 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11290.yml @@ -0,0 +1,4 @@ +author: "Putnam3145" +delete-after: True +changes: + - rscadd: "Traitor classes for traitors: a new way for traitors to have objectives assigned."