From d287835d1427a4a9b7a9f448676d046e5d51318d Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 18 Jan 2020 21:29:27 -0800 Subject: [PATCH 01/30] Made quirk blacklisting antag-sided --- code/datums/traits/_quirk.dm | 1 + code/datums/traits/negative.dm | 13 +++---------- code/modules/antagonists/_common/antag_datum.dm | 10 ++++++++++ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/code/datums/traits/_quirk.dm b/code/datums/traits/_quirk.dm index 12e34b0c90..d73fa3c825 100644 --- a/code/datums/traits/_quirk.dm +++ b/code/datums/traits/_quirk.dm @@ -8,6 +8,7 @@ var/gain_text var/lose_text var/medical_record_text //This text will appear on medical records for the trait. Not yet implemented + var/antag_removal_text // Text will be given to the quirk holder if they get an antag that has it blacklisted. var/mood_quirk = FALSE //if true, this quirk affects mood and is unavailable if moodlets are disabled var/mob_trait //if applicable, apply and remove this mob trait var/mob/living/quirk_holder diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index c5217d8e4b..d556d02ebb 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -6,6 +6,7 @@ value = -2 gain_text = "You feel your vigor slowly fading away." lose_text = "You feel vigorous again." + antag_removal_text = "Your antagonistic nature has removed your blood deficiency." medical_record_text = "Patient requires regular treatment for blood loss due to low production of blood." /datum/quirk/blooddeficiency/on_process() @@ -188,11 +189,7 @@ gain_text = "You feel repulsed by the thought of violence!" lose_text = "You think you can defend yourself again." medical_record_text = "Patient is unusually pacifistic and cannot bring themselves to cause physical harm." - -/datum/quirk/nonviolent/on_process() - if(quirk_holder.mind && LAZYLEN(quirk_holder.mind.antag_datums)) - to_chat(quirk_holder, "Your antagonistic nature has caused you to renounce your pacifism.") - qdel(src) + antag_removal_text = "Your antagonistic nature has caused you to renounce your pacifism." /datum/quirk/paraplegic name = "Paraplegic" @@ -355,6 +352,7 @@ gain_text = "You find yourself unable to speak!" lose_text = "You feel a growing strength in your vocal chords." medical_record_text = "Functionally mute, patient is unable to use their voice in any capacity." + antag_removal_text = "Your antagonistic nature has caused your voice to be heard." var/datum/brain_trauma/severe/mute/mute /datum/quirk/mute/add() @@ -366,11 +364,6 @@ var/mob/living/carbon/human/H = quirk_holder H?.cure_trauma_type(mute, TRAUMA_RESILIENCE_ABSOLUTE) -/datum/quirk/mute/on_process() - if(quirk_holder.mind && LAZYLEN(quirk_holder.mind.antag_datums)) - to_chat(quirk_holder, "Your antagonistic nature has caused your voice to be heard.") - qdel(src) - /datum/quirk/unstable name = "Unstable" desc = "Due to past troubles, you are unable to recover your sanity if you lose it. Be very careful managing your mood!" diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index 1894d8c7ae..064ae9043e 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -20,6 +20,7 @@ GLOBAL_LIST_EMPTY(antagonists) var/show_in_antagpanel = TRUE //This will hide adding this antag type in antag panel, use only for internal subtypes that shouldn't be added directly but still show if possessed by mind var/antagpanel_category = "Uncategorized" //Antagpanel will display these together, REQUIRED var/show_name_in_check_antagonists = FALSE //Will append antagonist name in admin listings - use for categories that share more than one antag type + var/list/quirk_blacklist = list("Pacifist","Mute") // Quirks that will be removed upon gaining this antag. Pacifist and mute are default. /datum/antagonist/New() GLOB.antagonists += src @@ -70,6 +71,7 @@ GLOBAL_LIST_EMPTY(antagonists) greet() apply_innate_effects() give_antag_moodies() + remove_blacklisted_quirks() if(is_banned(owner.current) && replace_banned) replace_banned_player() @@ -117,6 +119,14 @@ GLOBAL_LIST_EMPTY(antagonists) return SEND_SIGNAL(owner.current, COMSIG_CLEAR_MOOD_EVENT, "antag_moodlet") +/datum/antagonist/proc/remove_blacklisted_quirks() + for(var/q in owner.roundstart_quirks) + var/datum/quirk/Q = q + if(Q.name in quirk_blacklist) + if(Q.antag_removal_text) + to_chat(owner, "[Q.antag_removal_text]") + owner.remove_quirk(Q.type) + //Returns the team antagonist belongs to if any. /datum/antagonist/proc/get_team() return From e1cf63e0ac1663ffb3079581f2d3bc1491fe02f5 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 18 Jan 2020 21:32:42 -0800 Subject: [PATCH 02/30] Greentext tweaked --- code/game/gamemodes/objective.dm | 7 ++++--- code/modules/admin/antag_panel.dm | 4 ++-- code/modules/antagonists/_common/antag_datum.dm | 2 +- code/modules/antagonists/_common/antag_team.dm | 11 +++++++---- code/modules/antagonists/brother/brother.dm | 13 ++++++++----- code/modules/antagonists/changeling/changeling.dm | 11 +++++++---- code/modules/antagonists/traitor/datum_traitor.dm | 11 +++++++---- code/modules/antagonists/valentines/valentine.dm | 2 +- code/modules/antagonists/wizard/wizard.dm | 2 +- 9 files changed, 38 insertions(+), 25 deletions(-) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index f99fe5c3e4..4c82046e07 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -9,9 +9,10 @@ GLOBAL_LIST_EMPTY(objectives) var/explanation_text = "Nothing" //What that person is supposed to do. var/team_explanation_text //For when there are multiple owners. var/datum/mind/target = null //If they are focused on a particular person. - var/target_amount = 0 //If they are focused on a particular number. Steal objectives have their own counter. - var/completed = 0 //currently only used for custom objectives. - var/martyr_compatible = 0 //If the objective is compatible with martyr objective, i.e. if you can still do it while dead. + var/target_amount = FALSE //If they are focused on a particular number. Steal objectives have their own counter. + var/completed = FALSE //currently only used for custom objectives. + var/completable = TRUE //Whether this objective shows greentext when completed + var/martyr_compatible = FALSE //If the objective is compatible with martyr objective, i.e. if you can still do it while dead. /datum/objective/New(var/text) GLOB.objectives += src // CITADEL EDIT FOR CRYOPODS diff --git a/code/modules/admin/antag_panel.dm b/code/modules/admin/antag_panel.dm index 1672310567..ffb086a18d 100644 --- a/code/modules/admin/antag_panel.dm +++ b/code/modules/admin/antag_panel.dm @@ -47,7 +47,7 @@ GLOBAL_VAR(antag_prototypes) else var/obj_count = 1 for(var/datum/objective/objective in objectives) - result += "[obj_count]: [objective.explanation_text] Edit Delete [objective.completed ? "Mark as incomplete" : "Mark as complete"]
" + result += "[obj_count]: [objective.explanation_text] Edit Delete [objective.completed ? "Mark as incomplete" : "Mark as complete"]
" obj_count++ result += "Add objective
" result += "Announce objectives
" @@ -214,4 +214,4 @@ GLOBAL_VAR(antag_prototypes) var/datum/browser/panel = new(usr, "traitorpanel", "", 600, 600) panel.set_content(out) panel.open() - return \ No newline at end of file + return diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index 064ae9043e..4587a3c8ab 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -144,7 +144,7 @@ GLOBAL_LIST_EMPTY(antagonists) if(objectives.len) report += printobjectives(objectives) for(var/datum/objective/objective in objectives) - if(!objective.check_completion()) + if(objective.completable && !objective.check_completion()) objectives_complete = FALSE break diff --git a/code/modules/antagonists/_common/antag_team.dm b/code/modules/antagonists/_common/antag_team.dm index 486b5b0414..b376287f7a 100644 --- a/code/modules/antagonists/_common/antag_team.dm +++ b/code/modules/antagonists/_common/antag_team.dm @@ -36,11 +36,14 @@ var/win = TRUE var/objective_count = 1 for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - report += "Objective #[objective_count]: [objective.explanation_text] Success!" + if(objective.completable) + if(objective.check_completion()) + report += "Objective #[objective_count]: [objective.explanation_text] Success!" + else + report += "Objective #[objective_count]: [objective.explanation_text] Fail." + win = FALSE else - report += "Objective #[objective_count]: [objective.explanation_text] Fail." - win = FALSE + report += "Objective #[objective_count]: [objective.explanation_text]" objective_count++ if(win) report += "The [name] was successful!" diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm index 7c589bb3ab..1388ba745c 100644 --- a/code/modules/antagonists/brother/brother.dm +++ b/code/modules/antagonists/brother/brother.dm @@ -108,13 +108,16 @@ var/win = TRUE var/objective_count = 1 for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - parts += "Objective #[objective_count]: [objective.explanation_text] Success!" + if(objective.completable) + if(objective.check_completion()) + report += "Objective #[objective_count]: [objective.explanation_text] Success!" + else + report += "Objective #[objective_count]: [objective.explanation_text] Fail." + win = FALSE else - parts += "Objective #[objective_count]: [objective.explanation_text] Fail." - win = FALSE + report += "Objective #[objective_count]: [objective.explanation_text]" objective_count++ - if(win) +if(win) parts += "The blood brothers were successful!" else parts += "The blood brothers have failed!" diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index 0d68660d9d..e76c0ed054 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -552,11 +552,14 @@ if(objectives.len) var/count = 1 for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - parts += "Objective #[count]: [objective.explanation_text] Success!" + if(objective.completable) + if(objective.check_completion()) + report += "Objective #[count]: [objective.explanation_text] Success!" + else + report += "Objective #[count]: [objective.explanation_text] Fail." + win = FALSE else - parts += "Objective #[count]: [objective.explanation_text] Fail." - changelingwin = 0 + report += "Objective #[count]: [objective.explanation_text]" count++ if(changelingwin) diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 595ce5bb90..25fe24b605 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -369,11 +369,14 @@ if(objectives.len)//If the traitor had no objectives, don't need to process this. var/count = 1 for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - objectives_text += "
Objective #[count]: [objective.explanation_text] Success!" + if(objective.completable) + if(objective.check_completion()) + report += "Objective #[count]: [objective.explanation_text] Success!" + else + report += "Objective #[count]: [objective.explanation_text] Fail." + traitorwin = FALSE else - objectives_text += "
Objective #[count]: [objective.explanation_text] Fail." - traitorwin = FALSE + report += "Objective #[count]: [objective.explanation_text]" count++ if(uplink_true) diff --git a/code/modules/antagonists/valentines/valentine.dm b/code/modules/antagonists/valentines/valentine.dm index 19c08f3076..d3bcdf0c04 100644 --- a/code/modules/antagonists/valentines/valentine.dm +++ b/code/modules/antagonists/valentines/valentine.dm @@ -35,7 +35,7 @@ var/objectives_complete = TRUE if(objectives.len) for(var/datum/objective/objective in objectives) - if(!objective.check_completion()) + if(objective.completable && !objective.check_completion()) objectives_complete = FALSE break diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm index a88eb1e42a..d89d6a2744 100644 --- a/code/modules/antagonists/wizard/wizard.dm +++ b/code/modules/antagonists/wizard/wizard.dm @@ -62,7 +62,7 @@ /datum/antagonist/wizard/proc/create_objectives() var/datum/objective/new_objective = new("Cause as much creative mayhem as you can aboard the station! The more outlandish your methods of achieving this, the better! Make sure there's a decent amount of crew alive to tell of your tale.") - new_objective.completed = TRUE //So they can greentext without admin intervention. + new_objective.completable = FALSE new_objective.owner = owner objectives += new_objective From 5eba760aa8b37d600ef7445127d3ca43af1efe73 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 18 Jan 2020 22:07:54 -0800 Subject: [PATCH 03/30] Reworked survivalist --- code/game/gamemodes/objective.dm | 61 +++++++++---------- .../antagonists/survivalist/survivalist.dm | 7 ++- .../spells/spell_types/rightandwrong.dm | 13 ++++ 3 files changed, 47 insertions(+), 34 deletions(-) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 4c82046e07..bb18b89678 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -787,40 +787,10 @@ GLOBAL_LIST_EMPTY(possible_items_special) /datum/objective/destroy/internal var/stolen = FALSE //Have we already eliminated this target? -/datum/objective/steal_five_of_type - name = "steal five of" - explanation_text = "Steal at least five items!" - var/list/wanted_items = list(/obj/item) - -/datum/objective/steal_five_of_type/New() - ..() - wanted_items = typecacheof(wanted_items) - -/datum/objective/steal_five_of_type/summon_guns - name = "steal guns" - explanation_text = "Steal at least five guns!" - wanted_items = list(/obj/item/gun) - -/datum/objective/steal_five_of_type/summon_magic - name = "steal magic" - explanation_text = "Steal at least five magical artefacts!" - wanted_items = list(/obj/item/spellbook, /obj/item/gun/magic, /obj/item/clothing/suit/space/hardsuit/wizard, /obj/item/scrying, /obj/item/antag_spawner/contract, /obj/item/necromantic_stone) - -/datum/objective/steal_five_of_type/check_completion() - var/list/datum/mind/owners = get_owners() - var/stolen_count = 0 - for(var/datum/mind/M in owners) - if(!isliving(M.current)) - continue - var/list/all_items = M.current.GetAllContents() //this should get things in cheesewheels, books, etc. - for(var/obj/I in all_items) //Check for wanted items - if(is_type_in_typecache(I, wanted_items)) - stolen_count++ - return stolen_count >= 5 - //Created by admin tools /datum/objective/custom name = "custom" + completable = FALSE /datum/objective/custom/admin_edit(mob/admin) var/expl = stripped_input(admin, "Custom objective:", "Objective", explanation_text) @@ -998,4 +968,33 @@ GLOBAL_LIST_EMPTY(possible_items_special) command_staff_only = TRUE +/datum/objective/horde + name = "horde" + var/obj/item/horded_item = null +/datum/objective/horde/get_target() + return horded_item + +/datum/objective/horde/proc/set_target(obj/item/I) + if(item) + horded_item = I + explanation_text = "Keep [I] on your person at all costs." + return horded_item + else + explanation_text = "Free objective" + return + +/datum/objective/horde/check_completion() + var/list/datum/mind/owners = get_owners() + if(!horded_item) + return TRUE + for(var/datum/mind/M in owners) + if(!isliving(M.current)) + continue + + var/list/all_items = M.current.GetAllContents() //this should get things in cheesewheels, books, etc. + + for(var/obj/I in all_items) //Check for items + if(I == horded_item) + return TRUE + return FALSE diff --git a/code/modules/antagonists/survivalist/survivalist.dm b/code/modules/antagonists/survivalist/survivalist.dm index 4e0184b7b6..5334bb0f41 100644 --- a/code/modules/antagonists/survivalist/survivalist.dm +++ b/code/modules/antagonists/survivalist/survivalist.dm @@ -2,6 +2,7 @@ name = "Survivalist" show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE + blacklisted_quirks = list("Pacifist") // mutes are allowed var/greet_message = "" /datum/antagonist/survivalist/proc/forge_objectives() @@ -19,7 +20,7 @@ owner.announce_objectives() /datum/antagonist/survivalist/guns - greet_message = "Your own safety matters above all else, and the only way to ensure your safety is to stockpile weapons! Grab as many guns as possible, by any means necessary. Kill anyone who gets in your way." + greet_message = "Your own safety matters above all else, and the only way to ensure your safety is to stockpile weapons! Grab as many guns as possible, and don't let anyone take them!" /datum/antagonist/survivalist/guns/forge_objectives() var/datum/objective/steal_five_of_type/summon_guns/guns = new @@ -29,10 +30,10 @@ /datum/antagonist/survivalist/magic name = "Amateur Magician" - greet_message = "Grow your newfound talent! Grab as many magical artefacts as possible, by any means necessary. Kill anyone who gets in your way." + greet_message = "This magic stuff is... so powerful. You want more. More! They want your power. They can't have it! Don't let them have it!" /datum/antagonist/survivalist/magic/forge_objectives() var/datum/objective/steal_five_of_type/summon_magic/magic = new magic.owner = owner objectives += magic - ..() \ No newline at end of file + ..() diff --git a/code/modules/spells/spell_types/rightandwrong.dm b/code/modules/spells/spell_types/rightandwrong.dm index e5e856c630..b73929fc44 100644 --- a/code/modules/spells/spell_types/rightandwrong.dm +++ b/code/modules/spells/spell_types/rightandwrong.dm @@ -102,6 +102,12 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE) var/gun_type = pick(GLOB.summoned_guns) var/obj/item/gun/G = new gun_type(get_turf(H)) G.unlock() + var/datum/antagonist/survalist/guns/our_antag_datum = has_antag_datum(/datum/antagonist/survivalist/guns) + if(our_antag_datum) + var/datum/objective/horde_item/O = new() + O.owner = H + O.set_target(G) + our_antag_datum.objectives += O playsound(get_turf(H),'sound/magic/summon_guns.ogg', 50, 1) var/in_hand = H.put_in_hands(G) // not always successful @@ -128,6 +134,13 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE) var/obj/item/M = new magic_type(get_turf(H)) playsound(get_turf(H),'sound/magic/summon_magic.ogg', 50, 1) + var/datum/antagonist/survalist/magic/our_antag_datum = has_antag_datum(/datum/antagonist/survivalist/magic) + if(our_antag_datum) + var/datum/objective/horde_item/O = new() + O.owner = H + O.set_target(M) + our_antag_datum.objectives += O + var/in_hand = H.put_in_hands(M) to_chat(H, "\A [M] appears [in_hand ? "in your hand" : "at your feet"]!") From 06c66617e6c6cebfd58ad1c9f5638b2a44cf25c4 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 19 Jan 2020 18:58:10 -0800 Subject: [PATCH 04/30] m o r e traitor objectives --- code/__HELPERS/roundend.dm | 6 +- code/controllers/subsystem/ticker.dm | 2 + code/datums/traits/negative.dm | 3 + code/game/gamemodes/objective.dm | 88 ++++++++++++++- code/game/gamemodes/objective_sabotage.dm | 106 ++++++++++++++++++ code/modules/admin/antag_panel.dm | 2 +- .../antagonists/traitor/datum_traitor.dm | 28 +++-- 7 files changed, 223 insertions(+), 12 deletions(-) create mode 100644 code/game/gamemodes/objective_sabotage.dm diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 49825bcb50..5102eb4802 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -3,6 +3,9 @@ #define POPCOUNT_SHUTTLE_ESCAPEES "shuttle_escapees" //Emergency shuttle only. /datum/controller/subsystem/ticker/proc/gather_roundend_feedback() + var/datum/station_state/end_state = new /datum/station_state() + end_state.count() + station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100) gather_antag_data() record_nuke_disk_location() var/json_file = file("[GLOB.log_directory]/round_end_data.json") @@ -71,9 +74,6 @@ mob_data += list("name" = m.name, "typepath" = m.type) var/pos = length(file_data["[escaped]"]["[category]"]) + 1 file_data["[escaped]"]["[category]"]["[pos]"] = mob_data - var/datum/station_state/end_state = new /datum/station_state() - end_state.count() - var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100) file_data["additional data"]["station integrity"] = station_integrity WRITE_FILE(json_file, json_encode(file_data)) SSblackbox.record_feedback("nested tally", "round_end_stats", num_survivors, list("survivors", "total")) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index c9562bcfd1..ceb003210e 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -68,6 +68,8 @@ SUBSYSTEM_DEF(ticker) var/modevoted = FALSE //Have we sent a vote for the gamemode? + var/station_integrity = 100 // stored at roundend for use in some antag goals + /datum/controller/subsystem/ticker/Initialize(timeofday) load_mode() diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index d556d02ebb..f1d394ee2e 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -39,6 +39,8 @@ var/obj/item/heirloom var/where +GLOBAL_LIST_EMPTY(family_heirlooms) + /datum/quirk/family_heirloom/on_spawn() var/mob/living/carbon/human/H = quirk_holder var/obj/item/heirloom_type @@ -77,6 +79,7 @@ /obj/item/lighter, /obj/item/dice/d20) heirloom = new heirloom_type(get_turf(quirk_holder)) + GLOB.family_heirlooms += heirloom var/list/slots = list( "in your left pocket" = SLOT_L_STORE, "in your right pocket" = SLOT_R_STORE, diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index bb18b89678..4b7eebb5b9 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -366,6 +366,28 @@ GLOBAL_LIST_EMPTY(objectives) return FALSE return TRUE +/datum/objective/breakout + name = "breakout" + martyr_compatible = 1 + var/target_role_type = 0 + var/human_check = TRUE + +/datum/objective/breakout/check_completion() + return !target || considered_escaped(target, enforce_human = human_check) + +/datum/objective/breakout/find_target_by_role(role, role_type=0, invert=0) + if(!invert) + target_role_type = role_type + ..() + return target + +/datum/objective/breakout/update_explanation_text() + ..() + if(target && target.current) + explanation_text = "Make sure [target.name], the [!target_role_type ? target.assigned_role : target.special_role] escapes on the shuttle or an escape pod alive and without being in custody." + else + explanation_text = "Free Objective" + /datum/objective/escape/escape_with_identity name = "escape with identity" var/target_real_name // Has to be stored because the target's real_name can change over the course of the round @@ -583,7 +605,6 @@ GLOBAL_LIST_EMPTY(possible_items_special) explanation_text = "Do not give up or lose [targetinfo.name]." steal_target = targetinfo.targetitem - /datum/objective/download name = "download" @@ -998,3 +1019,68 @@ GLOBAL_LIST_EMPTY(possible_items_special) if(I == horded_item) return TRUE return FALSE + +/datum/objective/horde/heirloom + name = "steal heirloom" + +/datum/objective/horde/heirloom/proc/find_target() + set_target(pick(GLOB.family_heirlooms)) + +GLOBAL_LIST_EMPTY(possible_sabotages) +// For saboteurs. Go in and cause some trouble somewhere. Not necessarily breaking things, just sufficiently troublemaking. +/datum/objective/sabotage + name = "sabotage" + var/datum/sabotage_objective/targetinfo = null //composition > inheritance. + +/datum/objective/sabotage/get_target() + return targetinfo.sabotage_type + +/datum/objective/sabotage/New() + ..() + if(!GLOB.possible_sabotages.len)//Only need to fill the list when it's needed. + for(var/I in subtypesof(/datum/sabotage_objective)) + new I + +/datum/objective/sabotage/find_target() + var/list/datum/mind/owners = get_owners() + var/approved_targets = list() + check_sabotages: + for(var/datum/sabotage_objective/possible_sabotage in GLOB.possible_sabotages) + if(!is_unique_objective(possible_sabotage.sabotage_type) || possible_sabotage.check_conditions()) + continue + for(var/datum/mind/M in owners) + if(M.current.mind.assigned_role in possible_sabotage.excludefromjob) + continue check_sabotages + approved_targets += possible_sabotage + return set_target(safepick(approved_targets)) + +/datum/objective/sabotage/proc/set_target(datum/sabotage_objective/sabo) + if(sabo) + targetinfo = sabo + explanation_text = "[targetinfo.name]" + give_special_equipment(targetinfo.special_equipment) + return sabo + else + explanation_text = "Free objective" + return + +/datum/objective/sabotage/check_completion() + return targetinfo.check_conditions() + +/datum/objective/flavor + name = "Flavor" + completable = FALSE + +/datum/objective/flavor/proc/forge_objective() + +/datum/objective/flavor/traitor/forge_objective() + explanation_text = pickweight( + "Teach the heads of staff a lesson they will never forget." = 1, + "Show Nanotrasen the utility of a pure oxygen atmosphere." = 2, + "The Donk Corporation has hired you with the task to maim the crew in whatever way you can. Strain the resources of medical staff, and create a hostile working enviroment for human resources." = 3, + "The Waffle Corporation has given you the task to create the biggest prank the station's security force has seen! Harass security, and don't stop while you can still honk!" = 4, + "Kill one of the station's beloved pets. Make a show of it." = 3, + "Get illegal technology spread through the station." = 3, + "Slow down the process of research as much as possible." = (owner.assigned_role in list("Research Director", "Scientist", "Roboticist") ? 6 : 0), + "Channel your inner rat. Cut wires throughout the station" = (owner.assigned_role in list("Station Engineer", "Atmos Technician", "Assistant") ? 6 : 0), + ) diff --git a/code/game/gamemodes/objective_sabotage.dm b/code/game/gamemodes/objective_sabotage.dm new file mode 100644 index 0000000000..0ede317626 --- /dev/null +++ b/code/game/gamemodes/objective_sabotage.dm @@ -0,0 +1,106 @@ +/datum/sabotage_objective + var/name = "Free Objective" + var/sabotage_type = "nothing" + var/special_equipment = list() + var/list/excludefromjob = list() + +/datum/sabotage_objective/New() + ..() + if(sabotage_type!="nothing") + GLOB.possible_sabotages += src + +/datum/sabotage_objective/proc/check_conditions() + return TRUE + +/datum/sabotage_objective/processing + var/won = FALSE + +/datum/sabotage_objective/processing/New() + ..() + START_PROCESSING(SSprocessing, src) + +/datum/sabotage_objective/processing/proc/check_condition_processing() + return TRUE + +/datum/sabotage_objective/processing/process() + won = check_condition_processing() + if(won) + STOP_PROCESSING(SSprocessing,src) + +/datum/sabotage_objective/processing/power_sink + name = "Drain at least 1 gigajoule of power using a power sink." + sabotage_type = "powersink" + special_equipment = list(/obj/item/powersink) + var/sink_found = FALSE + var/count = 0 + +/datum/sabotage_objective/processing/power_sink/check_condition_processing() + count += 1 + if(count==10 || sink_found) // doesn't need to fire that often unless a sink exists + var/sink_found_this_time = FALSE + for(var/datum/powernet/PN in GLOB.powernets) + for(var/obj/item/powersink/sink in PN.nodes) + sink_found_this_time = TRUE + if(sink.power_drained>1e9) + return TRUE + sink_found = sink_found_this_time + count = 0 + return FALSE + +/obj/item/paper/guides/antag/supermatter_sabotage + info = "Ways to sabotage a supermatter:
\ +
    \ +
  • Set the air alarm's operating mode to anything that isn't 'draught' (yes, anything, though 'off' works best). Or just smash the air alarm, that works too.
  • \ +
  • Wrench a pipe (the junction to the cold loop is most effective, but some setups will robust through this no issue; best to try for multiple)
  • \ +
  • Pump in as much carbon dioxide, oxygen, plasma or tritium as you can find (this will likely also cause a singularity or tesla delamination, so watch out!)
  • \ +
  • Unset the filters on the cooling loop, or, perhaps more insidious, set them to oxygen/plasma.
  • \ +
  • Deactivate the digital valve that sends the exhaust gases to space (note: only works on box station; others you must unwrench).
  • \ +
  • There are many other ways; be creative!
  • \ +
" + +/datum/sabotage_objective/processing/supermatter + name = "Sabotage the supermatter so that it goes under 50% integrity." + sabotage_type = "supermatter" + special_equipment = list(/obj/item/paper/guides/antag/supermatter_sabotage) + var/list/supermatters = list() + excludefromjob = list("Chief Engineer", "Station Engineer", "Atmospheric Technician") + +/datum/sabotage_objective/processing/supermatter/check_condition_processing() + if(!supermatters.len) + supermatters = list() + for(var/obj/machinery/power/supermatter_crystal/S in GLOB.machines) + // Delaminating, not within coverage, not on a tile. + if (!isturf(S.loc) || !(is_station_level(S.z) || is_mining_level(S.z))) + continue + supermatters.Add(S) + for(var/obj/machinery/power/supermatter_crystal/S in supermatters) + if(S.get_integrity() < 50) + return TRUE + return FALSE + +/datum/sabotage_objective/station_integrity + name = "Make sure the station is at less than 80% integrity by the end. Smash walls, windows etc. to reach this goal." + sabotage_type = "integrity" + +/datum/sabotage_objective/station_integrity/check_conditions() + return SSticker.station_integrity < 80 + +/datum/sabotage_objective/cloner + name = "Destroy all Nanotrasen cloning machines." + sabotage_type = "cloner" + +/datum/sabotage_objective/cloner/check_conditions() + return !(locate(/obj/machinery/clonepod) in GLOB.machines) + +/datum/sabotage_objective/ai_law + name = "Upload a hacked law to the AI." + sabotage_type = "ailaw" + special_equipment = list(/obj/item/aiModule/syndicate) + excludefromjob = list("Chief Engineer","Research Director","Head of Personnel","Captain","Chief Medical Officer","Head Of Security") + +/datum/sabotage_objective/ai_law/check_conditions() + for (var/i in GLOB.ai_list) + var/mob/living/silicon/ai/aiPlayer = i + if(aiPlayer.mind && length(aiPlayer.laws.hacked)) + return TRUE + return FALSE diff --git a/code/modules/admin/antag_panel.dm b/code/modules/admin/antag_panel.dm index ffb086a18d..19e53b09b4 100644 --- a/code/modules/admin/antag_panel.dm +++ b/code/modules/admin/antag_panel.dm @@ -47,7 +47,7 @@ GLOBAL_VAR(antag_prototypes) else var/obj_count = 1 for(var/datum/objective/objective in objectives) - result += "[obj_count]: [objective.explanation_text] Edit Delete [objective.completed ? "Mark as incomplete" : "Mark as complete"]
" + result += "[obj_count]: [objective.explanation_text] Edit Delete [objective.completed ? "Mark as incomplete" : "Mark as complete"]
" obj_count++ result += "Add objective
" result += "Announce objectives
" diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 25fe24b605..62fdf56b71 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -77,19 +77,23 @@ 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.storyteller.flags & NO_ASSASSIN) - is_hijacker = FALSE + 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(10) && mode.threat_level > CONFIG_GET(number/dynamic_hijack_high_population_requirement)) + 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(10) && (mode.threat_level >= CONFIG_GET(number_list/dynamic_hijack_requirements)[indice_pop])) + 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(20) + 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) @@ -170,7 +174,7 @@ if(istype(SSticker.mode,/datum/game_mode/dynamic)) mode = SSticker.mode is_dynamic = TRUE - assassin_prob = mode.threat_level*(2/3) + assassin_prob = max(0,mode.threat_level-20) if(prob(assassin_prob)) if(is_dynamic) var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost) @@ -198,11 +202,21 @@ download_objective.owner = owner download_objective.gen_amount_goal() add_objective(download_objective) - else + else if(prob(40)) var/datum/objective/steal/steal_objective = new steal_objective.owner = owner steal_objective.find_target() add_objective(steal_objective) + else if(prob(40)) + var/datum/objective/sabotage/sabotage_objective = new + sabotage_objective.owner = owner + sabotage_objective.find_target() + add_objective(sabotage_objective) + else + 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 From 8e674817a9995beebaccf192b6464e7c8d07ecf8 Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 20 Jan 2020 00:30:18 -0800 Subject: [PATCH 05/30] errors --- code/game/gamemodes/objective.dm | 4 ++-- code/modules/antagonists/_common/antag_datum.dm | 16 +++++++++------- code/modules/antagonists/brother/brother.dm | 8 ++++---- .../modules/antagonists/changeling/changeling.dm | 8 ++++---- .../antagonists/survivalist/survivalist.dm | 12 ------------ .../modules/antagonists/traitor/datum_traitor.dm | 6 +++--- code/modules/spells/spell_types/rightandwrong.dm | 10 +++++----- tgstation.dme | 1 + 8 files changed, 28 insertions(+), 37 deletions(-) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 4b7eebb5b9..ff5649f5fd 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -997,7 +997,7 @@ GLOBAL_LIST_EMPTY(possible_items_special) return horded_item /datum/objective/horde/proc/set_target(obj/item/I) - if(item) + if(I) horded_item = I explanation_text = "Keep [I] on your person at all costs." return horded_item @@ -1023,7 +1023,7 @@ GLOBAL_LIST_EMPTY(possible_items_special) /datum/objective/horde/heirloom name = "steal heirloom" -/datum/objective/horde/heirloom/proc/find_target() +/datum/objective/horde/heirloom/find_target() set_target(pick(GLOB.family_heirlooms)) GLOBAL_LIST_EMPTY(possible_sabotages) diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index 4587a3c8ab..eafe4f4ec7 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -20,7 +20,7 @@ GLOBAL_LIST_EMPTY(antagonists) var/show_in_antagpanel = TRUE //This will hide adding this antag type in antag panel, use only for internal subtypes that shouldn't be added directly but still show if possessed by mind var/antagpanel_category = "Uncategorized" //Antagpanel will display these together, REQUIRED var/show_name_in_check_antagonists = FALSE //Will append antagonist name in admin listings - use for categories that share more than one antag type - var/list/quirk_blacklist = list("Pacifist","Mute") // Quirks that will be removed upon gaining this antag. Pacifist and mute are default. + var/list/blacklisted_quirks = list("Pacifist","Mute") // Quirks that will be removed upon gaining this antag. Pacifist and mute are default. /datum/antagonist/New() GLOB.antagonists += src @@ -120,12 +120,14 @@ GLOBAL_LIST_EMPTY(antagonists) SEND_SIGNAL(owner.current, COMSIG_CLEAR_MOOD_EVENT, "antag_moodlet") /datum/antagonist/proc/remove_blacklisted_quirks() - for(var/q in owner.roundstart_quirks) - var/datum/quirk/Q = q - if(Q.name in quirk_blacklist) - if(Q.antag_removal_text) - to_chat(owner, "[Q.antag_removal_text]") - owner.remove_quirk(Q.type) + var/mob/living/L = owner + if(istype(L)) + for(var/q in L.roundstart_quirks) + var/datum/quirk/Q = q + if(Q.name in blacklisted_quirks) + if(Q.antag_removal_text) + to_chat(L, "[Q.antag_removal_text]") + L.remove_quirk(Q.type) //Returns the team antagonist belongs to if any. /datum/antagonist/proc/get_team() diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm index 1388ba745c..22a343fb5f 100644 --- a/code/modules/antagonists/brother/brother.dm +++ b/code/modules/antagonists/brother/brother.dm @@ -110,14 +110,14 @@ for(var/datum/objective/objective in objectives) if(objective.completable) if(objective.check_completion()) - report += "Objective #[objective_count]: [objective.explanation_text] Success!" + parts += "Objective #[objective_count]: [objective.explanation_text] Success!" else - report += "Objective #[objective_count]: [objective.explanation_text] Fail." + parts += "Objective #[objective_count]: [objective.explanation_text] Fail." win = FALSE else - report += "Objective #[objective_count]: [objective.explanation_text]" + parts += "Objective #[objective_count]: [objective.explanation_text]" objective_count++ -if(win) + if(win) parts += "The blood brothers were successful!" else parts += "The blood brothers have failed!" diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index e76c0ed054..7d702ac25d 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -554,12 +554,12 @@ for(var/datum/objective/objective in objectives) if(objective.completable) if(objective.check_completion()) - report += "Objective #[count]: [objective.explanation_text] Success!" + parts += "Objective #[count]: [objective.explanation_text] Success!" else - report += "Objective #[count]: [objective.explanation_text] Fail." - win = FALSE + parts += "Objective #[count]: [objective.explanation_text] Fail." + changelingwin = FALSE else - report += "Objective #[count]: [objective.explanation_text]" + parts += "Objective #[count]: [objective.explanation_text]" count++ if(changelingwin) diff --git a/code/modules/antagonists/survivalist/survivalist.dm b/code/modules/antagonists/survivalist/survivalist.dm index 5334bb0f41..1b870ec389 100644 --- a/code/modules/antagonists/survivalist/survivalist.dm +++ b/code/modules/antagonists/survivalist/survivalist.dm @@ -22,18 +22,6 @@ /datum/antagonist/survivalist/guns greet_message = "Your own safety matters above all else, and the only way to ensure your safety is to stockpile weapons! Grab as many guns as possible, and don't let anyone take them!" -/datum/antagonist/survivalist/guns/forge_objectives() - var/datum/objective/steal_five_of_type/summon_guns/guns = new - guns.owner = owner - objectives += guns - ..() - /datum/antagonist/survivalist/magic name = "Amateur Magician" greet_message = "This magic stuff is... so powerful. You want more. More! They want your power. They can't have it! Don't let them have it!" - -/datum/antagonist/survivalist/magic/forge_objectives() - var/datum/objective/steal_five_of_type/summon_magic/magic = new - magic.owner = owner - objectives += magic - ..() diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 62fdf56b71..3385991116 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -385,12 +385,12 @@ for(var/datum/objective/objective in objectives) if(objective.completable) if(objective.check_completion()) - report += "Objective #[count]: [objective.explanation_text] Success!" + objectives_text += "Objective #[count]: [objective.explanation_text] Success!" else - report += "Objective #[count]: [objective.explanation_text] Fail." + objectives_text += "Objective #[count]: [objective.explanation_text] Fail." traitorwin = FALSE else - report += "Objective #[count]: [objective.explanation_text]" + objectives_text += "Objective #[count]: [objective.explanation_text]" count++ if(uplink_true) diff --git a/code/modules/spells/spell_types/rightandwrong.dm b/code/modules/spells/spell_types/rightandwrong.dm index b73929fc44..996e2e3168 100644 --- a/code/modules/spells/spell_types/rightandwrong.dm +++ b/code/modules/spells/spell_types/rightandwrong.dm @@ -102,9 +102,9 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE) var/gun_type = pick(GLOB.summoned_guns) var/obj/item/gun/G = new gun_type(get_turf(H)) G.unlock() - var/datum/antagonist/survalist/guns/our_antag_datum = has_antag_datum(/datum/antagonist/survivalist/guns) + var/datum/antagonist/survivalist/guns/our_antag_datum = H.mind.has_antag_datum(/datum/antagonist/survivalist/guns) if(our_antag_datum) - var/datum/objective/horde_item/O = new() + var/datum/objective/horde/O = new() O.owner = H O.set_target(G) our_antag_datum.objectives += O @@ -134,9 +134,9 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE) var/obj/item/M = new magic_type(get_turf(H)) playsound(get_turf(H),'sound/magic/summon_magic.ogg', 50, 1) - var/datum/antagonist/survalist/magic/our_antag_datum = has_antag_datum(/datum/antagonist/survivalist/magic) - if(our_antag_datum) - var/datum/objective/horde_item/O = new() + var/datum/antagonist/survivalist/magic/our_antag_datum = H.mind.has_antag_datum(/datum/antagonist/survivalist/magic) + if(istype(our_antag_datum)) + var/datum/objective/horde/O = new() O.owner = H O.set_target(M) our_antag_datum.objectives += O diff --git a/tgstation.dme b/tgstation.dme index 1c7d5112e7..1e881df6a7 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -567,6 +567,7 @@ #include "code\game\gamemodes\game_mode.dm" #include "code\game\gamemodes\objective.dm" #include "code\game\gamemodes\objective_items.dm" +#include "code\game\gamemodes\objective_sabotage.dm" #include "code\game\gamemodes\bloodsucker\bloodsucker.dm" #include "code\game\gamemodes\bloodsucker\hunter.dm" #include "code\game\gamemodes\brother\traitor_bro.dm" From 67c2fdca52151b9d9407612efaed9aea2ff1a427 Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 20 Jan 2020 01:20:42 -0800 Subject: [PATCH 06/30] more flavor objectives --- code/game/gamemodes/objective.dm | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index ff5649f5fd..cbee7a79ef 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1077,10 +1077,11 @@ GLOBAL_LIST_EMPTY(possible_sabotages) explanation_text = pickweight( "Teach the heads of staff a lesson they will never forget." = 1, "Show Nanotrasen the utility of a pure oxygen atmosphere." = 2, - "The Donk Corporation has hired you with the task to maim the crew in whatever way you can. Strain the resources of medical staff, and create a hostile working enviroment for human resources." = 3, - "The Waffle Corporation has given you the task to create the biggest prank the station's security force has seen! Harass security, and don't stop while you can still honk!" = 4, - "Kill one of the station's beloved pets. Make a show of it." = 3, + "Waffle Co. wants you! That’s right, YOU! To cause as much humerous 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!" = 2, + "Kill one of the station's beloved pets. Make a show of it, though you don't have to reveal yourself." = 3, "Get illegal technology spread through the station." = 3, "Slow down the process of research as much as possible." = (owner.assigned_role in list("Research Director", "Scientist", "Roboticist") ? 6 : 0), - "Channel your inner rat. Cut wires throughout the station" = (owner.assigned_role in list("Station Engineer", "Atmos Technician", "Assistant") ? 6 : 0), + "Channel your inner rat. Cut wires throughout the station." = (owner.assigned_role in list("Station Engineer", "Atmos Technician", "Assistant") ? 6 : 0), + "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." = 2, + "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." = 2 ) From dfaa3bf15cc96df4f8343a5002d34ab810c1ed9c Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 20 Jan 2020 03:46:44 -0800 Subject: [PATCH 07/30] Added another flavor obj, "horde" to "hoard" --- code/game/gamemodes/objective.dm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index cbee7a79ef..bd8baf17db 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1077,11 +1077,12 @@ GLOBAL_LIST_EMPTY(possible_sabotages) explanation_text = pickweight( "Teach the heads of staff a lesson they will never forget." = 1, "Show Nanotrasen the utility of a pure oxygen atmosphere." = 2, - "Waffle Co. wants you! That’s right, YOU! To cause as much humerous 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!" = 2, + "Waffle Co. wants you! That’s right, 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!" = 1, "Kill one of the station's beloved pets. Make a show of it, though you don't have to reveal yourself." = 3, "Get illegal technology spread through the station." = 3, "Slow down the process of research as much as possible." = (owner.assigned_role in list("Research Director", "Scientist", "Roboticist") ? 6 : 0), "Channel your inner rat. Cut wires throughout the station." = (owner.assigned_role in list("Station Engineer", "Atmos Technician", "Assistant") ? 6 : 0), "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." = 2, - "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." = 2 + "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." = 1, + "Steal as many shoes as possible. Lay broken glass everywhere." = 2 ) From 815b4f033dff14be2a60c67e05641f65cdc1bca6 Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 20 Jan 2020 04:13:54 -0800 Subject: [PATCH 08/30] made flavor things a game option + more hoard --- .../configuration/entries/game_options.dm | 6 +++ code/datums/mind.dm | 3 +- code/game/gamemodes/objective.dm | 48 +++++++++---------- .../antagonists/traitor/datum_traitor.dm | 1 - .../spells/spell_types/rightandwrong.dm | 4 +- config/game_options.txt | 11 +++++ 6 files changed, 43 insertions(+), 30 deletions(-) diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index aeca31ebd2..cf5e0f7db1 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -408,3 +408,9 @@ /datum/config_entry/number/dropped_modes config_entry_value = 3 + +/datum/config_entry/keyed_list/flavor_objective_traitor + key_mode = KEY_MODE_TEXT + value_mode = VALUE_MODE_NUM + splitter = "=" + lowercase = FALSE diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 464ea37d02..c25f5d5199 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -471,7 +471,8 @@ /datum/objective/nuclear, /datum/objective/capture, /datum/objective/absorb, - /datum/objective/custom + /datum/objective/custom, + /datum/objective/flavor/traitor ) for(var/T in allowed_types) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index bd8baf17db..5b3e6a1164 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -989,25 +989,25 @@ GLOBAL_LIST_EMPTY(possible_items_special) command_staff_only = TRUE -/datum/objective/horde - name = "horde" - var/obj/item/horded_item = null +/datum/objective/hoard + name = "hoard" + var/obj/item/hoarded_item = null -/datum/objective/horde/get_target() - return horded_item +/datum/objective/hoard/get_target() + return hoarded_item -/datum/objective/horde/proc/set_target(obj/item/I) +/datum/objective/hoard/proc/set_target(obj/item/I) if(I) - horded_item = I + hoarded_item = I explanation_text = "Keep [I] on your person at all costs." - return horded_item + return hoarded_item else explanation_text = "Free objective" return -/datum/objective/horde/check_completion() +/datum/objective/hoard/check_completion() var/list/datum/mind/owners = get_owners() - if(!horded_item) + if(!hoarded_item) return TRUE for(var/datum/mind/M in owners) if(!isliving(M.current)) @@ -1016,14 +1016,14 @@ GLOBAL_LIST_EMPTY(possible_items_special) var/list/all_items = M.current.GetAllContents() //this should get things in cheesewheels, books, etc. for(var/obj/I in all_items) //Check for items - if(I == horded_item) + if(I == hoarded_item) return TRUE return FALSE -/datum/objective/horde/heirloom +/datum/objective/hoard/heirloom name = "steal heirloom" -/datum/objective/horde/heirloom/find_target() +/datum/objective/hoard/heirloom/find_target() set_target(pick(GLOB.family_heirlooms)) GLOBAL_LIST_EMPTY(possible_sabotages) @@ -1068,21 +1068,17 @@ GLOBAL_LIST_EMPTY(possible_sabotages) return targetinfo.check_conditions() /datum/objective/flavor - name = "Flavor" + name = "flavor" completable = FALSE +/datum/objective/flavor/New() + ..() + forge_objective() + /datum/objective/flavor/proc/forge_objective() +/datum/objective/flavor/traitor + name = "traitor flavor" + /datum/objective/flavor/traitor/forge_objective() - explanation_text = pickweight( - "Teach the heads of staff a lesson they will never forget." = 1, - "Show Nanotrasen the utility of a pure oxygen atmosphere." = 2, - "Waffle Co. wants you! That’s right, 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!" = 1, - "Kill one of the station's beloved pets. Make a show of it, though you don't have to reveal yourself." = 3, - "Get illegal technology spread through the station." = 3, - "Slow down the process of research as much as possible." = (owner.assigned_role in list("Research Director", "Scientist", "Roboticist") ? 6 : 0), - "Channel your inner rat. Cut wires throughout the station." = (owner.assigned_role in list("Station Engineer", "Atmos Technician", "Assistant") ? 6 : 0), - "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." = 2, - "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." = 1, - "Steal as many shoes as possible. Lay broken glass everywhere." = 2 - ) + explanation_text = pickweight(CONFIG_GET(keyed_list/flavor_objective_traitor)) diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 3385991116..e0044d8c23 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -215,7 +215,6 @@ else 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() diff --git a/code/modules/spells/spell_types/rightandwrong.dm b/code/modules/spells/spell_types/rightandwrong.dm index 996e2e3168..ea131fb996 100644 --- a/code/modules/spells/spell_types/rightandwrong.dm +++ b/code/modules/spells/spell_types/rightandwrong.dm @@ -104,7 +104,7 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE) G.unlock() var/datum/antagonist/survivalist/guns/our_antag_datum = H.mind.has_antag_datum(/datum/antagonist/survivalist/guns) if(our_antag_datum) - var/datum/objective/horde/O = new() + var/datum/objective/hoard/O = new() O.owner = H O.set_target(G) our_antag_datum.objectives += O @@ -136,7 +136,7 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE) var/datum/antagonist/survivalist/magic/our_antag_datum = H.mind.has_antag_datum(/datum/antagonist/survivalist/magic) if(istype(our_antag_datum)) - var/datum/objective/horde/O = new() + var/datum/objective/hoard/O = new() O.owner = H O.set_target(M) our_antag_datum.objectives += O diff --git a/config/game_options.txt b/config/game_options.txt index b8b89de17c..5d1f871058 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -597,3 +597,14 @@ MODETIER_VOTING ## Number of modes dropped by the modetier vote during mode selection, after vote. DROPPED_MODES 3 + +FLAVOR_OBJECTIVE_TRAITOR Teach the heads of staff a lesson they will never forget.=1 +FLAVOR_OBJECTIVE_TRAITOR Show Nanotrasen the utility of a pure oxygen atmosphere.=2 +FLAVOR_OBJECTIVE_TRAITOR Waffle Co. wants you! That’s right, 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!=1 +FLAVOR_OBJECTIVE_TRAITOR Kill one of the station's beloved pets. Make a show of it, though you don't have to reveal yourself.=3 +FLAVOR_OBJECTIVE_TRAITOR Get illegal technology spread through the station.=3 +FLAVOR_OBJECTIVE_TRAITOR Slow down the process of research as much as possible." = (owner.assigned_role in list("Research Director", "Scientist", "Roboticist") ? 6 : 0), +FLAVOR_OBJECTIVE_TRAITOR Channel your inner rat. Cut wires throughout the station." = (owner.assigned_role in list("Station Engineer", "Atmos Technician", "Assistant") ? 6 : 0), +FLAVOR_OBJECTIVE_TRAITOR 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.=2 +FLAVOR_OBJECTIVE_TRAITOR 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.=1 +FLAVOR_OBJECTIVE_TRAITOR Steal as many shoes as possible. Lay broken glass everywhere." = 2 From 847b3c0a09234044531119ea2b98ca2c8cc8c0ef Mon Sep 17 00:00:00 2001 From: Putnam Date: Fri, 24 Jan 2020 10:46:07 -0800 Subject: [PATCH 09/30] Fixed flavor objectives and added more. --- .../configuration/entries/game_options.dm | 6 ---- code/datums/mind.dm | 3 +- code/game/gamemodes/objective.dm | 31 ++++++++++++++++--- code/modules/antagonists/ninja/ninja.dm | 21 +++++-------- .../antagonists/traitor/datum_traitor.dm | 1 + code/modules/antagonists/wizard/wizard.dm | 5 +-- config/game_options.txt | 11 ------- strings/flavor_objectives/ninja_helping.txt | 6 ++++ strings/flavor_objectives/ninja_syndie.txt | 5 +++ strings/flavor_objectives/traitor.txt | 9 ++++++ .../flavor_objectives/traitor/assistant.txt | 0 .../flavor_objectives/traitor/engineering.txt | 0 strings/flavor_objectives/traitor/medical.txt | 0 strings/flavor_objectives/traitor/science.txt | 1 + strings/flavor_objectives/wizard.txt | 4 +++ 15 files changed, 63 insertions(+), 40 deletions(-) create mode 100644 strings/flavor_objectives/ninja_helping.txt create mode 100644 strings/flavor_objectives/ninja_syndie.txt create mode 100644 strings/flavor_objectives/traitor.txt create mode 100644 strings/flavor_objectives/traitor/assistant.txt create mode 100644 strings/flavor_objectives/traitor/engineering.txt create mode 100644 strings/flavor_objectives/traitor/medical.txt create mode 100644 strings/flavor_objectives/traitor/science.txt create mode 100644 strings/flavor_objectives/wizard.txt diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index cf5e0f7db1..aeca31ebd2 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -408,9 +408,3 @@ /datum/config_entry/number/dropped_modes config_entry_value = 3 - -/datum/config_entry/keyed_list/flavor_objective_traitor - key_mode = KEY_MODE_TEXT - value_mode = VALUE_MODE_NUM - splitter = "=" - lowercase = FALSE diff --git a/code/datums/mind.dm b/code/datums/mind.dm index c25f5d5199..464ea37d02 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -471,8 +471,7 @@ /datum/objective/nuclear, /datum/objective/capture, /datum/objective/absorb, - /datum/objective/custom, - /datum/objective/flavor/traitor + /datum/objective/custom ) for(var/T in allowed_types) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 5b3e6a1164..11933c2717 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1070,15 +1070,36 @@ GLOBAL_LIST_EMPTY(possible_sabotages) /datum/objective/flavor name = "flavor" completable = FALSE + var/flavor_file -/datum/objective/flavor/New() - ..() - forge_objective() +/datum/objective/flavor/proc/get_flavor_list() + return world.file2list(flavor_file) /datum/objective/flavor/proc/forge_objective() + var/flavor_list = get_flavor_list() + explanation_text = pick(flavor_list) /datum/objective/flavor/traitor name = "traitor flavor" + flavor_file = "strings/flavor_objectives/traitor.txt" -/datum/objective/flavor/traitor/forge_objective() - explanation_text = pickweight(CONFIG_GET(keyed_list/flavor_objective_traitor)) +/datum/objective/flavor/traitor/get_flavor_list() + . = ..() + switch(owner.assigned_role) + if("Station Engineer", "Atmospheric Technician") + . += world.file2list("strings/flavor_objectives/traitor/engineering.txt") + if("Medical Doctor","Chemist","Virologist","Geneticist") + . += world.file2list("strings/flavor_objectives/traitor/medical.txt") + if("Scientist","Roboticist","Geneticist") + . += world.file2list("strings/flavor_objectives/traitor/science.txt") + if("Assistant") + . += world.file2list("strings/flavor_objectives/traitor/assistant.txt") + +/datum/objective/flavor/ninja_helping + flavor_file = "strings/flavor_objectives/ninja_helping.txt" + +/datum/objective/flavor/ninja_syndie + flavor_file = "strings/flavor_objectives/ninja_syndie.txt" + +/datum/objective/flavor/wizard + flavor_file = "strings/flavor_objectives/wizard.txt" diff --git a/code/modules/antagonists/ninja/ninja.dm b/code/modules/antagonists/ninja/ninja.dm index 52e13bdc69..fe83e2fb2b 100644 --- a/code/modules/antagonists/ninja/ninja.dm +++ b/code/modules/antagonists/ninja/ninja.dm @@ -73,23 +73,16 @@ O.target = M O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm." objectives += O - if(4) //debrain/capture - if(!possible_targets.len) continue - var/selected = rand(1,possible_targets.len) - var/datum/mind/M = possible_targets[selected] - var/is_bad_guy = possible_targets[M] - possible_targets.Cut(selected,selected+1) - - if(is_bad_guy ^ helping_station) //debrain (good-ninja + bad-guy or bad-ninja + good-guy) - var/datum/objective/debrain/O = new /datum/objective/debrain() + if(4) //flavor + if(helping_station) + var/datum/objective/flavor/ninja_helping/O = new /datum/objective/flavor/ninja_helping O.owner = owner - O.target = M - O.explanation_text = "Steal the brain of [M.current.real_name]." + O.forge_objective() objectives += O - else //capture - var/datum/objective/capture/O = new /datum/objective/capture() + else + var/datum/objective/flavor/ninja_syndie/O = new /datum/objective/flavor/ninja_helping O.owner = owner - O.gen_amount_goal() + O.forge_objective() objectives += O else break diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index e0044d8c23..3385991116 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -215,6 +215,7 @@ else 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() diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm index d89d6a2744..cc3cde79e4 100644 --- a/code/modules/antagonists/wizard/wizard.dm +++ b/code/modules/antagonists/wizard/wizard.dm @@ -61,9 +61,9 @@ owner.current.forceMove(pick(GLOB.wizardstart)) /datum/antagonist/wizard/proc/create_objectives() - var/datum/objective/new_objective = new("Cause as much creative mayhem as you can aboard the station! The more outlandish your methods of achieving this, the better! Make sure there's a decent amount of crew alive to tell of your tale.") - new_objective.completable = FALSE + var/datum/objective/flavor/wizard/new_objective = new new_objective.owner = owner + new_objective.forge_objective() objectives += new_objective if (!(locate(/datum/objective/escape) in objectives)) @@ -94,6 +94,7 @@ to_chat(owner, "You are the Space Wizard!") to_chat(owner, "The Space Wizards Federation has given you the following tasks:") owner.announce_objectives() + to_chat(owner, "These are merely guidelines! The federation are your masters, but you forge your own path!") to_chat(owner, "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.") to_chat(owner, "The spellbook is bound to you, and others cannot use it.") to_chat(owner, "In your pockets you will find a teleport scroll. Use it as needed.") diff --git a/config/game_options.txt b/config/game_options.txt index 5d1f871058..b8b89de17c 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -597,14 +597,3 @@ MODETIER_VOTING ## Number of modes dropped by the modetier vote during mode selection, after vote. DROPPED_MODES 3 - -FLAVOR_OBJECTIVE_TRAITOR Teach the heads of staff a lesson they will never forget.=1 -FLAVOR_OBJECTIVE_TRAITOR Show Nanotrasen the utility of a pure oxygen atmosphere.=2 -FLAVOR_OBJECTIVE_TRAITOR Waffle Co. wants you! That’s right, 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!=1 -FLAVOR_OBJECTIVE_TRAITOR Kill one of the station's beloved pets. Make a show of it, though you don't have to reveal yourself.=3 -FLAVOR_OBJECTIVE_TRAITOR Get illegal technology spread through the station.=3 -FLAVOR_OBJECTIVE_TRAITOR Slow down the process of research as much as possible." = (owner.assigned_role in list("Research Director", "Scientist", "Roboticist") ? 6 : 0), -FLAVOR_OBJECTIVE_TRAITOR Channel your inner rat. Cut wires throughout the station." = (owner.assigned_role in list("Station Engineer", "Atmos Technician", "Assistant") ? 6 : 0), -FLAVOR_OBJECTIVE_TRAITOR 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.=2 -FLAVOR_OBJECTIVE_TRAITOR 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.=1 -FLAVOR_OBJECTIVE_TRAITOR Steal as many shoes as possible. Lay broken glass everywhere." = 2 diff --git a/strings/flavor_objectives/ninja_helping.txt b/strings/flavor_objectives/ninja_helping.txt new file mode 100644 index 0000000000..1280939b5c --- /dev/null +++ b/strings/flavor_objectives/ninja_helping.txt @@ -0,0 +1,6 @@ +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/ninja_syndie.txt b/strings/flavor_objectives/ninja_syndie.txt new file mode 100644 index 0000000000..4527c693f4 --- /dev/null +++ b/strings/flavor_objectives/ninja_syndie.txt @@ -0,0 +1,5 @@ +The Gorlex Marauders want you to teach the heads of staff a lesson they will never forget. +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! +The Tiger Cooperative want you to kill one of the station's beloved pets. Make a show of it, though you don't have to reveal yourself. +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. \ No newline at end of file diff --git a/strings/flavor_objectives/traitor.txt b/strings/flavor_objectives/traitor.txt new file mode 100644 index 0000000000..fcbbc588e9 --- /dev/null +++ b/strings/flavor_objectives/traitor.txt @@ -0,0 +1,9 @@ +The Gorlex Marauders want you to teach the heads of staff a lesson they will never forget. +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 want you to channel your inner rat. Cut wires throughout 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 diff --git a/strings/flavor_objectives/traitor/assistant.txt b/strings/flavor_objectives/traitor/assistant.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/strings/flavor_objectives/traitor/engineering.txt b/strings/flavor_objectives/traitor/engineering.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/strings/flavor_objectives/traitor/medical.txt b/strings/flavor_objectives/traitor/medical.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/strings/flavor_objectives/traitor/science.txt b/strings/flavor_objectives/traitor/science.txt new file mode 100644 index 0000000000..6367e78da2 --- /dev/null +++ b/strings/flavor_objectives/traitor/science.txt @@ -0,0 +1 @@ +The Tiger Cooperative want you to slow down the process of research as much as possible. \ No newline at end of file diff --git a/strings/flavor_objectives/wizard.txt b/strings/flavor_objectives/wizard.txt new file mode 100644 index 0000000000..e65a6052bc --- /dev/null +++ b/strings/flavor_objectives/wizard.txt @@ -0,0 +1,4 @@ +Cause as much creative mayhem as you can aboard the station! The more outlandish your methods of achieving this, the better! Make sure there's a decent amount of crew alive to tell of your tale. +The Wizard Federation have sent you to take over the station by force. Kill the captain and take their place. The magocracy starts now. +You are the slipperiest wizard there ever was. Be loud, cause a ruckus, start a manhunt, and keep it going for as long as you can. +The crew must be shown the wonders of magic. Do some tricks for them. If they stop moving, that means they're in awe. \ No newline at end of file From c58b4daa35e28a26728e9f6aeb7dbbec5d0ed430 Mon Sep 17 00:00:00 2001 From: Putnam Date: Fri, 24 Jan 2020 11:58:58 -0800 Subject: [PATCH 10/30] collectors too this doesn't compile but like. it's a draft --- code/game/gamemodes/objective.dm | 30 ++++++++++++++++++- code/game/objects/items/cards_ids.dm | 5 +++- code/game/objects/items/storage/book.dm | 3 ++ .../antagonists/collector/collector.dm | 19 ++++++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 code/modules/antagonists/collector/collector.dm diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 11933c2717..fa302eeca8 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -999,7 +999,7 @@ GLOBAL_LIST_EMPTY(possible_items_special) /datum/objective/hoard/proc/set_target(obj/item/I) if(I) hoarded_item = I - explanation_text = "Keep [I] on your person at all costs." + explanation_text = "Keep [I] on your person at all times." return hoarded_item else explanation_text = "Free objective" @@ -1026,6 +1026,34 @@ GLOBAL_LIST_EMPTY(possible_items_special) /datum/objective/hoard/heirloom/find_target() set_target(pick(GLOB.family_heirlooms)) +GLOBAL_LIST_EMPTY(traitor_contraband) + +GLOBAL_LIST_EMPTY(cult_contraband) + +/datum/objective/hoard/collector + name = "Hoard contraband" + +/datum/objective/collector/New() + ..() + if(!GLOB.traitor_contraband.len)//Only need to fill the list when it's needed. + GLOB.traitor_contraband = list(/obj/item/card/emag/empty,/obj/item/clothing/glasses/phantomthief,/obj/item/storage/book/bible/syndicate/empty,/obj/item/clothing/gloves/chameleon/broken) + if(!GLOB.cult_contraband.len) + GLOB.cult_contraband = list(/obj/item/clockwork/slab,/obj/item/clockwork/component/belligerent_eye,/obj/item/clockwork/component/belligerent_eye/lens_gem,/obj/item/restraints/legcuffs/bola/cult,/obj/item/shuttle_curse,/obj/item/cult_shift) + +/datum/objective/hoard/collector/find_target() + var/obj/item/I + if(prob(50)) + I = new pick_and_take(GLOB.traitor_contraband) + else + I = new pick_and_take(GLOB.cult_contraband) + I.forceMove(get_turf(owner)) + if(ishuman(owner)) + var/mob/living/carbon/human/H = owner + H.equip_in_one_of_slots(I, list("backpack" = SLOT_IN_BACKPACK)) + hoarded_item = I + + + GLOBAL_LIST_EMPTY(possible_sabotages) // For saboteurs. Go in and cause some trouble somewhere. Not necessarily breaking things, just sufficiently troublemaking. /datum/objective/sabotage diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 48dac6a08b..5ec989ab73 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -128,6 +128,9 @@ return . = ..() +/obj/item/card/emag/empty + uses = 0 + /obj/item/emagrecharge name = "electromagnet charging device" desc = "A small cell with two prongs lazily jabbed into it. It looks like it's made for charging the small batteries found in electromagnetic devices, sadly this can't be recharged like a normal cell." @@ -541,4 +544,4 @@ update_label("John Doe", "Clowny") id_color = "#0000FF" /obj/item/card/id/knight/captain - id_color = "#FFD700" \ No newline at end of file + id_color = "#FFD700" diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm index e47021c1f6..2762be8edf 100644 --- a/code/game/objects/items/storage/book.dm +++ b/code/game/objects/items/storage/book.dm @@ -244,3 +244,6 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", /obj/item/storage/book/bible/syndicate/add_blood_DNA(list/blood_dna) return FALSE + +/obj/item/storage/book/bible/syndicate/empty + uses = 0 diff --git a/code/modules/antagonists/collector/collector.dm b/code/modules/antagonists/collector/collector.dm new file mode 100644 index 0000000000..0e7a3a52e7 --- /dev/null +++ b/code/modules/antagonists/collector/collector.dm @@ -0,0 +1,19 @@ +/datum/antagonist/collector + name = "Contraband Collector" + show_in_antagpanel = FALSE + show_name_in_check_antagonists = FALSE + blacklisted_quirks = list() // no blacklist, these guys are harmless + +/datum/antagonist/collector/proc/forge_objectives() + var/datum/objective/hoard/collector/O = new + O.owner = owner + O.find_target() + objectives += O + +/datum/antagonist/collector/on_gain() + forge_objectives() + . = ..() + +/datum/antagonist/collector/greet() + to_chat(owner, "You are a contraband collector!") + owner.announce_objectives() From 37777c4cc7a3a73f54a557fe0b97eddb9f93c32a Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 25 Jan 2020 13:37:40 -0800 Subject: [PATCH 11/30] Removed the wirecutting one --- code/game/gamemodes/objective.dm | 2 +- strings/flavor_objectives/traitor.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index fa302eeca8..e01ff61229 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1043,7 +1043,7 @@ GLOBAL_LIST_EMPTY(cult_contraband) /datum/objective/hoard/collector/find_target() var/obj/item/I if(prob(50)) - I = new pick_and_take(GLOB.traitor_contraband) + I = new pick_and_take(GLOB.traitor_contraband) // always unique unless it's run out, in which case we refill it anyway else I = new pick_and_take(GLOB.cult_contraband) I.forceMove(get_turf(owner)) diff --git a/strings/flavor_objectives/traitor.txt b/strings/flavor_objectives/traitor.txt index fcbbc588e9..6d54c8ed9d 100644 --- a/strings/flavor_objectives/traitor.txt +++ b/strings/flavor_objectives/traitor.txt @@ -3,7 +3,6 @@ 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 want you to channel your inner rat. Cut wires throughout 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 233aeaa456918827bd5336946024cc57f3257a2e Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 26 Jan 2020 19:03:09 -0800 Subject: [PATCH 12/30] removed some suggested bad possible contraband --- code/game/gamemodes/objective.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index e01ff61229..7105e45ddd 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1036,9 +1036,9 @@ GLOBAL_LIST_EMPTY(cult_contraband) /datum/objective/collector/New() ..() if(!GLOB.traitor_contraband.len)//Only need to fill the list when it's needed. - GLOB.traitor_contraband = list(/obj/item/card/emag/empty,/obj/item/clothing/glasses/phantomthief,/obj/item/storage/book/bible/syndicate/empty,/obj/item/clothing/gloves/chameleon/broken) + GLOB.traitor_contraband = list(/obj/item/card/emag/empty,/obj/item/clothing/glasses/phantomthief,/obj/item/clothing/gloves/chameleon/broken) if(!GLOB.cult_contraband.len) - GLOB.cult_contraband = list(/obj/item/clockwork/slab,/obj/item/clockwork/component/belligerent_eye,/obj/item/clockwork/component/belligerent_eye/lens_gem,/obj/item/restraints/legcuffs/bola/cult,/obj/item/shuttle_curse,/obj/item/cult_shift) + GLOB.cult_contraband = list(/obj/item/clockwork/slab,/obj/item/clockwork/component/belligerent_eye,/obj/item/clockwork/component/belligerent_eye/lens_gem,/obj/item/shuttle_curse,/obj/item/cult_shift) /datum/objective/hoard/collector/find_target() var/obj/item/I From 8df9a051ec672edffa2a900d43a8147526c5c19e Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 27 Jan 2020 19:09:04 -0800 Subject: [PATCH 13/30] it compiles now, ready for testmerge probs --- code/game/gamemodes/objective.dm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 7105e45ddd..b22e12291b 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1042,10 +1042,12 @@ GLOBAL_LIST_EMPTY(cult_contraband) /datum/objective/hoard/collector/find_target() var/obj/item/I + var/I_type if(prob(50)) - I = new pick_and_take(GLOB.traitor_contraband) // always unique unless it's run out, in which case we refill it anyway + I_type = pick_n_take(GLOB.traitor_contraband) // always unique unless it's run out, in which case we refill it anyway else - I = new pick_and_take(GLOB.cult_contraband) + I_type = pick_n_take(GLOB.cult_contraband) + I = new I_type I.forceMove(get_turf(owner)) if(ishuman(owner)) var/mob/living/carbon/human/H = owner From d358913bde7e754204b5ddd37ae42bb1f5245302 Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 28 Jan 2020 17:26:32 -0800 Subject: [PATCH 14/30] linter is right, whoops --- 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 b22e12291b..a9c9e227df 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -373,7 +373,7 @@ GLOBAL_LIST_EMPTY(objectives) var/human_check = TRUE /datum/objective/breakout/check_completion() - return !target || considered_escaped(target, enforce_human = human_check) + return !target || considered_escaped(target) /datum/objective/breakout/find_target_by_role(role, role_type=0, invert=0) if(!invert) From 29e0ac52c43bc5f8ff51506f9f09dfc6abb0470f Mon Sep 17 00:00:00 2001 From: Putnam Date: Fri, 31 Jan 2020 11:52:05 -0800 Subject: [PATCH 15/30] fuzzy objectives --- code/__HELPERS/roundend.dm | 9 +++++++- code/game/gamemodes/objective_sabotage.dm | 21 ++++++++++--------- .../modules/antagonists/_common/antag_team.dm | 7 +++++-- code/modules/antagonists/brother/brother.dm | 7 +++++-- .../antagonists/changeling/changeling.dm | 11 +++++++--- code/modules/antagonists/cult/cult.dm | 9 +++++--- .../antagonists/disease/disease_datum.dm | 11 ++++++---- .../antagonists/traitor/datum_traitor.dm | 11 ++++++---- code/modules/antagonists/wizard/wizard.dm | 11 ++++++---- interface/stylesheet.dm | 1 + 10 files changed, 65 insertions(+), 33 deletions(-) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 5102eb4802..906f60d65b 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -111,7 +111,14 @@ if(A.objectives.len) for(var/datum/objective/O in A.objectives) - var/result = O.check_completion() ? "SUCCESS" : "FAIL" + var/result = "UNKNOWN" + var/actual_result = O.check_completion() + if(actual_result >= 1) + result = "SUCCESS" + else if(actual_result <= 0) + result = "FAIL" + else + result = "[actual_result*100]%" antag_info["objectives"] += list(list("objective_type"=O.type,"text"=O.explanation_text,"result"=result)) SSblackbox.record_feedback("associative", "antagonists", 1, antag_info) diff --git a/code/game/gamemodes/objective_sabotage.dm b/code/game/gamemodes/objective_sabotage.dm index 0ede317626..467983a346 100644 --- a/code/game/gamemodes/objective_sabotage.dm +++ b/code/game/gamemodes/objective_sabotage.dm @@ -20,13 +20,16 @@ START_PROCESSING(SSprocessing, src) /datum/sabotage_objective/processing/proc/check_condition_processing() - return TRUE + return 100 /datum/sabotage_objective/processing/process() - won = check_condition_processing() - if(won) + check_condition_processing() + if(won >= 100) STOP_PROCESSING(SSprocessing,src) +/datum/sabotage_objective/processing/check_conditions() + return won + /datum/sabotage_objective/processing/power_sink name = "Drain at least 1 gigajoule of power using a power sink." sabotage_type = "powersink" @@ -41,8 +44,7 @@ for(var/datum/powernet/PN in GLOB.powernets) for(var/obj/item/powersink/sink in PN.nodes) sink_found_this_time = TRUE - if(sink.power_drained>1e9) - return TRUE + won = max(won,sink.power_drained/1e9) sink_found = sink_found_this_time count = 0 return FALSE @@ -59,7 +61,7 @@ " /datum/sabotage_objective/processing/supermatter - name = "Sabotage the supermatter so that it goes under 50% integrity." + name = "Sabotage the supermatter so that it goes under 50% integrity. If it is delaminated, you will fail." sabotage_type = "supermatter" special_equipment = list(/obj/item/paper/guides/antag/supermatter_sabotage) var/list/supermatters = list() @@ -73,9 +75,8 @@ if (!isturf(S.loc) || !(is_station_level(S.z) || is_mining_level(S.z))) continue supermatters.Add(S) - for(var/obj/machinery/power/supermatter_crystal/S in supermatters) - if(S.get_integrity() < 50) - return TRUE + for(var/obj/machinery/power/supermatter_crystal/S in supermatters) // you can win this with a wishgranter... lol. + won = max(1-((S.get_integrity()-50)/50),won) return FALSE /datum/sabotage_objective/station_integrity @@ -83,7 +84,7 @@ sabotage_type = "integrity" /datum/sabotage_objective/station_integrity/check_conditions() - return SSticker.station_integrity < 80 + return 100/(100-max(SSticker.station_integrity,80)) /datum/sabotage_objective/cloner name = "Destroy all Nanotrasen cloning machines." diff --git a/code/modules/antagonists/_common/antag_team.dm b/code/modules/antagonists/_common/antag_team.dm index b376287f7a..027abc7c94 100644 --- a/code/modules/antagonists/_common/antag_team.dm +++ b/code/modules/antagonists/_common/antag_team.dm @@ -37,11 +37,14 @@ var/objective_count = 1 for(var/datum/objective/objective in objectives) if(objective.completable) - if(objective.check_completion()) + var/completion = objective.check_completion() + if(completion >= 1) report += "Objective #[objective_count]: [objective.explanation_text] Success!" - else + else if(completion <= 0) report += "Objective #[objective_count]: [objective.explanation_text] Fail." win = FALSE + else + report += "Objective #[objective_count]: [objective.explanation_text] [completion*100]%" else report += "Objective #[objective_count]: [objective.explanation_text]" objective_count++ diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm index 22a343fb5f..2292006da1 100644 --- a/code/modules/antagonists/brother/brother.dm +++ b/code/modules/antagonists/brother/brother.dm @@ -109,11 +109,14 @@ var/objective_count = 1 for(var/datum/objective/objective in objectives) if(objective.completable) - if(objective.check_completion()) + var/completion = objective.check_completion() + if(completion >= 1) parts += "Objective #[objective_count]: [objective.explanation_text] Success!" - else + else if(completion <= 0) parts += "Objective #[objective_count]: [objective.explanation_text] Fail." win = FALSE + else + parts += "Objective #[objective_count]: [objective.explanation_text] [completion*100]%" else parts += "Objective #[objective_count]: [objective.explanation_text]" objective_count++ diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index 7d702ac25d..a81c409233 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -54,8 +54,10 @@ var/honorific if(owner.current.gender == FEMALE) honorific = "Ms." - else + else if(owner.current.gender == MALE) honorific = "Mr." + else + honorific = "Mx." if(GLOB.possible_changeling_IDs.len) changelingID = pick(GLOB.possible_changeling_IDs) GLOB.possible_changeling_IDs -= changelingID @@ -553,11 +555,14 @@ var/count = 1 for(var/datum/objective/objective in objectives) if(objective.completable) - if(objective.check_completion()) + var/completion = objective.check_completion() + if(completion >= 1) parts += "Objective #[count]: [objective.explanation_text] Success!" - else + else if(completion <= 0) parts += "Objective #[count]: [objective.explanation_text] Fail." changelingwin = FALSE + else + parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" else parts += "Objective #[count]: [objective.explanation_text]" count++ diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm index df2383f892..6f9cf78514 100644 --- a/code/modules/antagonists/cult/cult.dm +++ b/code/modules/antagonists/cult/cult.dm @@ -425,10 +425,13 @@ parts += "The cultists' objectives were:" var/count = 1 for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - parts += "Objective #[count]: [objective.explanation_text] Success!" + var/completion = objective.check_completion() + if(completion >= 1) + parts += "Objective #[count]: [objective.explanation_text] Success!" + else if(completion <= 0) + parts += "Objective #[count]: [objective.explanation_text] Fail." else - parts += "Objective #[count]: [objective.explanation_text] Fail." + parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" count++ if(members.len) diff --git a/code/modules/antagonists/disease/disease_datum.dm b/code/modules/antagonists/disease/disease_datum.dm index 1aef9ceba6..3d3de3bab2 100644 --- a/code/modules/antagonists/disease/disease_datum.dm +++ b/code/modules/antagonists/disease/disease_datum.dm @@ -44,11 +44,14 @@ var/objectives_text = "" var/count = 1 for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - objectives_text += "
Objective #[count]: [objective.explanation_text] Success!" - else - objectives_text += "
Objective #[count]: [objective.explanation_text] Fail." + var/completion = objective.check_completion() + if(completion >= 1) + result += "Objective #[count]: [objective.explanation_text] Success!" + else if(completion <= 0) + result += "Objective #[count]: [objective.explanation_text] Fail." win = FALSE + else + result += "Objective #[count]: [objective.explanation_text] [completion*100]%" count++ result += objectives_text diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 3385991116..01d3dd5694 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -384,11 +384,14 @@ var/count = 1 for(var/datum/objective/objective in objectives) if(objective.completable) - if(objective.check_completion()) - objectives_text += "Objective #[count]: [objective.explanation_text] Success!" - else - objectives_text += "Objective #[count]: [objective.explanation_text] Fail." + var/completion = objective.check_completion() + if(completion >= 1) + result += "Objective #[count]: [objective.explanation_text] Success!" + else if(completion <= 0) + result += "Objective #[count]: [objective.explanation_text] Fail." traitorwin = FALSE + else + result += "Objective #[count]: [objective.explanation_text] [completion*100]%" else objectives_text += "Objective #[count]: [objective.explanation_text]" count++ diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm index cc3cde79e4..3fd0d3263c 100644 --- a/code/modules/antagonists/wizard/wizard.dm +++ b/code/modules/antagonists/wizard/wizard.dm @@ -266,11 +266,14 @@ var/count = 1 var/wizardwin = 1 for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - parts += "Objective #[count]: [objective.explanation_text] Success!" - else + var/completion = objective.check_completion() + if(completion >= 1) + parts += "Objective #[count]: [objective.explanation_text] Success!" + else if(completion <= 0) parts += "Objective #[count]: [objective.explanation_text] Fail." - wizardwin = 0 + wizardwin = FALSE + else + parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" count++ if(wizardwin) diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm index 6ee9e6e824..9f3d8911ec 100644 --- a/interface/stylesheet.dm +++ b/interface/stylesheet.dm @@ -151,6 +151,7 @@ h1.alert, h2.alert {color: #000000;} .extremelybig {font-size: 5;} .greentext {color: #00FF00; font-size: 3;} .redtext {color: #FF0000; font-size: 3;} +.yellowtext {color: #FFCC00; font-size: 3;} .clown {color: #FF69Bf; font-size: 3; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;} .his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;} .spooky {color: #FF9100;} From 809f57a15d37fe2fb894214ea6b44d499f96c864 Mon Sep 17 00:00:00 2001 From: Putnam Date: Fri, 31 Jan 2020 12:25:19 -0800 Subject: [PATCH 16/30] also added kill-once objectives --- code/datums/mind.dm | 1 + code/game/gamemodes/objective.dm | 24 +++++++++++++++++++ code/modules/antagonists/ninja/ninja.dm | 4 ++-- .../antagonists/traitor/datum_traitor.dm | 13 ++++++---- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 464ea37d02..628e698ae0 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -458,6 +458,7 @@ var/list/allowed_types = list( /datum/objective/assassinate, + /datum/objective/assassinate/once, /datum/objective/maroon, /datum/objective/debrain, /datum/objective/protect, diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index a9c9e227df..d7ee749f34 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -173,6 +173,30 @@ GLOBAL_LIST_EMPTY(objectives) /datum/objective/assassinate/admin_edit(mob/admin) admin_simple_target_pick(admin) +/datum/objective/assassinate/once + name = "kill once" + var/won = FALSE + +/datum/objective/assassinate/once/update_explanation_text() + ..() + if(target && target.current) + explanation_text = "Kill [target.name], the [!target_role_type ? target.assigned_role : target.special_role]. You only need to kill [target.p_them()] once; if they come back, you've still succeeded." + else + explanation_text = "Free Objective" + +/datum/objective/assassinate/once/find_target_by_role() + . = ..() + if(.) + START_PROCESSING(SSprocessing,src) + +/datum/objective/assassinate/once/check_completion() + return won || ..() + +/datum/objective/assassinate/once/process() + won = check_completion() + if(won) + STOP_PROCESSING(SSprocessing,src) + /datum/objective/assassinate/internal var/stolen = 0 //Have we already eliminated this target? diff --git a/code/modules/antagonists/ninja/ninja.dm b/code/modules/antagonists/ninja/ninja.dm index fe83e2fb2b..42412709fa 100644 --- a/code/modules/antagonists/ninja/ninja.dm +++ b/code/modules/antagonists/ninja/ninja.dm @@ -62,10 +62,10 @@ possible_targets.Cut(index,index+1) if(is_bad_guy ^ helping_station) //kill (good-ninja + bad-guy or bad-ninja + good-guy) - var/datum/objective/assassinate/O = new /datum/objective/assassinate() + var/datum/objective/assassinate/once/O = new /datum/objective/assassinate() O.owner = owner O.target = M - O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]." + O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]. You may let [M.p_they()] live, if they come back from death." objectives += O else //protect var/datum/objective/protect/O = new /datum/objective/protect() diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 01d3dd5694..f584b6c149 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -191,28 +191,33 @@ maroon_objective.owner = owner maroon_objective.find_target() add_objective(maroon_objective) - else + else if(prob(30)) 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)) + else if(prob(33)) // cum. not counting download: 33%. yes, i do know 33/33 won't be equal and that i want 33/50 for that var/datum/objective/steal/steal_objective = new steal_objective.owner = owner steal_objective.find_target() add_objective(steal_objective) - else if(prob(40)) + else if(prob(33)) // cum. not counting download: 22.11% var/datum/objective/sabotage/sabotage_objective = new sabotage_objective.owner = owner sabotage_objective.find_target() add_objective(sabotage_objective) - else + else // cum. not counting download: 44.89% var/datum/objective/flavor/traitor/flavor_objective = new flavor_objective.owner = owner flavor_objective.forge_objective() From 425f532f767bff16d66a986dea91e05ea8f0e93b Mon Sep 17 00:00:00 2001 From: Putnam Date: Fri, 31 Jan 2020 13:12:50 -0800 Subject: [PATCH 17/30] WHOOPS --- 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 d7ee749f34..1fdb621866 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -184,7 +184,7 @@ GLOBAL_LIST_EMPTY(objectives) else explanation_text = "Free Objective" -/datum/objective/assassinate/once/find_target_by_role() +/datum/objective/assassinate/once/find_target_by_role(role, role_type=0, invert=0) . = ..() if(.) START_PROCESSING(SSprocessing,src) From 3d9e84a3f8a9c5cfe1c160e17bf3be0ee7ef1901 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 1 Feb 2020 00:23:45 -0800 Subject: [PATCH 18/30] Tweaks and fixes --- code/__HELPERS/roundend.dm | 12 +++++++++--- code/game/gamemodes/objective_sabotage.dm | 2 +- code/modules/antagonists/cult/cult.dm | 15 +++++++++------ .../antagonists/disease/disease_datum.dm | 17 ++++++++++------- code/modules/antagonists/wizard/wizard.dm | 17 ++++++++++------- 5 files changed, 39 insertions(+), 24 deletions(-) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 906f60d65b..535f1154e7 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -557,10 +557,16 @@ var/list/objective_parts = list() var/count = 1 for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - objective_parts += "Objective #[count]: [objective.explanation_text] Success!" + if(objective.completable) + var/completion = objective.check_completion() + if(completion >= 1) + objective_parts += "Objective #[count]: [objective.explanation_text] Success!" + else if(completion <= 0) + objective_parts += "Objective #[count]: [objective.explanation_text] Fail." + else + objective_parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - objective_parts += "Objective #[count]: [objective.explanation_text] Fail." + objective_parts += "Objective #[count]: [objective.explanation_text]" count++ return objective_parts.Join("
") diff --git a/code/game/gamemodes/objective_sabotage.dm b/code/game/gamemodes/objective_sabotage.dm index 467983a346..248524f1d2 100644 --- a/code/game/gamemodes/objective_sabotage.dm +++ b/code/game/gamemodes/objective_sabotage.dm @@ -84,7 +84,7 @@ sabotage_type = "integrity" /datum/sabotage_objective/station_integrity/check_conditions() - return 100/(100-max(SSticker.station_integrity,80)) + return 5-(max(SSticker.station_integrity*4,320)/80) /datum/sabotage_objective/cloner name = "Destroy all Nanotrasen cloning machines." diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm index 6f9cf78514..2b6c24f8dc 100644 --- a/code/modules/antagonists/cult/cult.dm +++ b/code/modules/antagonists/cult/cult.dm @@ -425,13 +425,16 @@ parts += "The cultists' objectives were:" var/count = 1 for(var/datum/objective/objective in objectives) - var/completion = objective.check_completion() - if(completion >= 1) - parts += "Objective #[count]: [objective.explanation_text] Success!" - else if(completion <= 0) - parts += "Objective #[count]: [objective.explanation_text] Fail." + if(objective.completable) + var/completion = objective.check_completion() + if(completion >= 1) + parts += "Objective #[count]: [objective.explanation_text] Success!" + else if(completion <= 0) + parts += "Objective #[count]: [objective.explanation_text] Fail." + else + parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" + parts += "Objective #[count]: [objective.explanation_text]" count++ if(members.len) diff --git a/code/modules/antagonists/disease/disease_datum.dm b/code/modules/antagonists/disease/disease_datum.dm index 3d3de3bab2..3c7de589d9 100644 --- a/code/modules/antagonists/disease/disease_datum.dm +++ b/code/modules/antagonists/disease/disease_datum.dm @@ -44,14 +44,17 @@ var/objectives_text = "" var/count = 1 for(var/datum/objective/objective in objectives) - var/completion = objective.check_completion() - if(completion >= 1) - result += "Objective #[count]: [objective.explanation_text] Success!" - else if(completion <= 0) - result += "Objective #[count]: [objective.explanation_text] Fail." - win = FALSE + if(objective.completable) + var/completion = objective.check_completion() + if(completion >= 1) + result += "Objective #[count]: [objective.explanation_text] Success!" + else if(completion <= 0) + result += "Objective #[count]: [objective.explanation_text] Fail." + win = FALSE + else + result += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - result += "Objective #[count]: [objective.explanation_text] [completion*100]%" + result += "Objective #[count]: [objective.explanation_text]" count++ result += objectives_text diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm index 3fd0d3263c..c5e365d4eb 100644 --- a/code/modules/antagonists/wizard/wizard.dm +++ b/code/modules/antagonists/wizard/wizard.dm @@ -266,14 +266,17 @@ var/count = 1 var/wizardwin = 1 for(var/datum/objective/objective in objectives) - var/completion = objective.check_completion() - if(completion >= 1) - parts += "Objective #[count]: [objective.explanation_text] Success!" - else if(completion <= 0) - parts += "Objective #[count]: [objective.explanation_text] Fail." - wizardwin = FALSE + if(objective.completable) + var/completion = objective.check_completion() + if(completion >= 1) + parts += "Objective #[count]: [objective.explanation_text] Success!" + else if(completion <= 0) + parts += "Objective #[count]: [objective.explanation_text] Fail." + wizardwin = FALSE + else + parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" + parts += "Objective #[count]: [objective.explanation_text]" count++ if(wizardwin) From 847e6382c0b53f958dc10bc723b3073384079a0f Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 1 Feb 2020 00:32:08 -0800 Subject: [PATCH 19/30] fixes some quirk stuff --- code/controllers/subsystem/processing/quirks.dm | 6 +++--- code/modules/antagonists/_common/antag_datum.dm | 12 ++++++------ code/modules/antagonists/survivalist/survivalist.dm | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/code/controllers/subsystem/processing/quirks.dm b/code/controllers/subsystem/processing/quirks.dm index a52bcf4607..10655981e5 100644 --- a/code/controllers/subsystem/processing/quirks.dm +++ b/code/controllers/subsystem/processing/quirks.dm @@ -35,7 +35,7 @@ PROCESSING_SUBSYSTEM_DEF(quirks) var/list/my_quirks = cli.prefs.all_quirks.Copy() var/list/cut if(job?.blacklisted_quirks) - cut = filter_quirks(my_quirks, job) + cut = filter_quirks(my_quirks, job.blacklisted_quirks) for(var/V in my_quirks) var/datum/quirk/Q = quirks[V] if(Q) @@ -63,11 +63,11 @@ PROCESSING_SUBSYSTEM_DEF(quirks) for(var/i in quirk_names) . += quirk_points_by_name(i) -/datum/controller/subsystem/processing/quirks/proc/filter_quirks(list/our_quirks, datum/job/job) +/datum/controller/subsystem/processing/quirks/proc/filter_quirks(list/our_quirks, list/blacklisted_quirks) var/list/cut = list() var/list/banned_names = list() var/pointscut = 0 - for(var/i in job.blacklisted_quirks) + for(var/i in blacklisted_quirks) var/name = quirk_name_by_path(i) if(name) banned_names += name diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index eafe4f4ec7..5921b465e2 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -20,7 +20,7 @@ GLOBAL_LIST_EMPTY(antagonists) var/show_in_antagpanel = TRUE //This will hide adding this antag type in antag panel, use only for internal subtypes that shouldn't be added directly but still show if possessed by mind var/antagpanel_category = "Uncategorized" //Antagpanel will display these together, REQUIRED var/show_name_in_check_antagonists = FALSE //Will append antagonist name in admin listings - use for categories that share more than one antag type - var/list/blacklisted_quirks = list("Pacifist","Mute") // Quirks that will be removed upon gaining this antag. Pacifist and mute are default. + var/list/blacklisted_quirks = list(/datum/quirk/nonviolent,/datum/quirk/mute) // Quirks that will be removed upon gaining this antag. Pacifist and mute are default. /datum/antagonist/New() GLOB.antagonists += src @@ -122,12 +122,12 @@ GLOBAL_LIST_EMPTY(antagonists) /datum/antagonist/proc/remove_blacklisted_quirks() var/mob/living/L = owner if(istype(L)) - for(var/q in L.roundstart_quirks) + var/list/cut = list() + cut = SSquirks.filter_quirks(L.roundstart_quirks,blacklisted_quirks) + for(var/q in cut) var/datum/quirk/Q = q - if(Q.name in blacklisted_quirks) - if(Q.antag_removal_text) - to_chat(L, "[Q.antag_removal_text]") - L.remove_quirk(Q.type) + if(Q.antag_removal_text) + to_chat(L, "[Q.antag_removal_text]") //Returns the team antagonist belongs to if any. /datum/antagonist/proc/get_team() diff --git a/code/modules/antagonists/survivalist/survivalist.dm b/code/modules/antagonists/survivalist/survivalist.dm index 1b870ec389..0b66e8cb23 100644 --- a/code/modules/antagonists/survivalist/survivalist.dm +++ b/code/modules/antagonists/survivalist/survivalist.dm @@ -2,7 +2,7 @@ name = "Survivalist" show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE - blacklisted_quirks = list("Pacifist") // mutes are allowed + blacklisted_quirks = list(/datum/quirk/nonviolent) // mutes are allowed var/greet_message = "" /datum/antagonist/survivalist/proc/forge_objectives() From 7e3ea27ff46e0e51c09194ace0a106509a1590d8 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 1 Feb 2020 00:42:25 -0800 Subject: [PATCH 20/30] dumb formatting. dumb dumb. --- code/modules/antagonists/traitor/datum_traitor.dm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index f584b6c149..830555e9a2 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -207,17 +207,17 @@ download_objective.owner = owner download_objective.gen_amount_goal() add_objective(download_objective) - else if(prob(33)) // cum. not counting download: 33%. yes, i do know 33/33 won't be equal and that i want 33/50 for that + 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(33)) // cum. not counting download: 22.11% + 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: 44.89% + else // cum. not counting download: 40% var/datum/objective/flavor/traitor/flavor_objective = new flavor_objective.owner = owner flavor_objective.forge_objective() @@ -391,12 +391,12 @@ if(objective.completable) var/completion = objective.check_completion() if(completion >= 1) - result += "Objective #[count]: [objective.explanation_text] Success!" + objectives_text += "Objective #[count]: [objective.explanation_text] Success!" else if(completion <= 0) - result += "Objective #[count]: [objective.explanation_text] Fail." + objectives_text += "Objective #[count]: [objective.explanation_text] Fail." traitorwin = FALSE else - result += "Objective #[count]: [objective.explanation_text] [completion*100]%" + objectives_text += "Objective #[count]: [objective.explanation_text] [completion*100]%" else objectives_text += "Objective #[count]: [objective.explanation_text]" count++ From 50a53c6558f156de3bd827bb05e190928425826a Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 1 Feb 2020 00:47:44 -0800 Subject: [PATCH 21/30] aaand a formatting oddity --- 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 1fdb621866..db6d0a6672 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -180,7 +180,7 @@ GLOBAL_LIST_EMPTY(objectives) /datum/objective/assassinate/once/update_explanation_text() ..() if(target && target.current) - explanation_text = "Kill [target.name], the [!target_role_type ? target.assigned_role : target.special_role]. You only need to kill [target.p_them()] once; if they come back, you've still succeeded." + explanation_text = "Kill [target.name], the [!target_role_type ? target.assigned_role : target.special_role]. You only need to kill them once; if they come back, you've still succeeded." else explanation_text = "Free Objective" From d6d01d848cd6c6e78f40698d3e85fafe473c3bf8 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 1 Feb 2020 06:01:54 -0800 Subject: [PATCH 22/30] --- code/__HELPERS/roundend.dm | 2 +- code/datums/mind.dm | 8 ++++---- code/game/gamemodes/objective.dm | 3 +++ code/modules/antagonists/_common/antag_team.dm | 2 +- code/modules/antagonists/bloodsucker/datum_bloodsucker.dm | 2 +- code/modules/antagonists/brother/brother.dm | 2 +- code/modules/antagonists/changeling/changeling.dm | 2 +- code/modules/antagonists/cult/cult.dm | 2 +- code/modules/antagonists/disease/disease_datum.dm | 2 +- code/modules/antagonists/traitor/datum_traitor.dm | 2 +- code/modules/antagonists/wizard/wizard.dm | 2 +- 11 files changed, 16 insertions(+), 13 deletions(-) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 535f1154e7..c42d60c88f 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -566,7 +566,7 @@ else objective_parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - objective_parts += "Objective #[count]: [objective.explanation_text]" + objective_parts += "Objective #[count]: [objective.explanation_text]" count++ return objective_parts.Join("
") diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 628e698ae0..aa1a2ed55f 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -374,7 +374,7 @@ output += "Objectives:" var/obj_count = 1 for(var/datum/objective/objective in all_objectives) - output += "
Objective #[obj_count++]: [objective.explanation_text]" + output += "
Objective #[obj_count++]: [objective.explanation_text]" var/list/datum/mind/other_owners = objective.get_owners() - src if(other_owners.len) output += "
    " @@ -523,8 +523,8 @@ to_chat(usr,"Invalid objective.") return qdel(objective) //TODO: Needs cleaning objective destroys (whatever that means) - message_admins("[key_name_admin(usr)] removed an objective for [current]: [objective.explanation_text]") - log_admin("[key_name(usr)] removed an objective for [current]: [objective.explanation_text]") + message_admins("[key_name_admin(usr)] removed an objective for [current]: [objective.explanation_text]") + log_admin("[key_name(usr)] removed an objective for [current]: [objective.explanation_text]") else if(href_list["obj_completed"]) var/datum/objective/objective @@ -537,7 +537,7 @@ to_chat(usr,"Invalid objective.") return objective.completed = !objective.completed - log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective.explanation_text]") + log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective.explanation_text]") else if (href_list["silicon"]) switch(href_list["silicon"]) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index db6d0a6672..c044680302 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1157,3 +1157,6 @@ GLOBAL_LIST_EMPTY(possible_sabotages) /datum/objective/flavor/wizard flavor_file = "strings/flavor_objectives/wizard.txt" + +/datum/objective/flavor/bloodsucker + flavor_file = "strings/flavor_objectives/bloodsucker.txt" diff --git a/code/modules/antagonists/_common/antag_team.dm b/code/modules/antagonists/_common/antag_team.dm index 027abc7c94..958a50460c 100644 --- a/code/modules/antagonists/_common/antag_team.dm +++ b/code/modules/antagonists/_common/antag_team.dm @@ -46,7 +46,7 @@ else report += "Objective #[objective_count]: [objective.explanation_text] [completion*100]%" else - report += "Objective #[objective_count]: [objective.explanation_text]" + report += "Objective #[objective_count]: [objective.explanation_text]" objective_count++ if(win) report += "The [name] was successful!" diff --git a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm index 844b523135..a768978583 100644 --- a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm +++ b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm @@ -372,7 +372,7 @@ datum/antagonist/bloodsucker/proc/SpendRank() protege_objective.generate_objective() add_objective(protege_objective) - if (rand(0,1) == 0) + if (prob(50)) // Heart Thief Objective var/datum/objective/bloodsucker/heartthief/heartthief_objective = new heartthief_objective.owner = owner diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm index 2292006da1..7d2bd45827 100644 --- a/code/modules/antagonists/brother/brother.dm +++ b/code/modules/antagonists/brother/brother.dm @@ -118,7 +118,7 @@ else parts += "Objective #[objective_count]: [objective.explanation_text] [completion*100]%" else - parts += "Objective #[objective_count]: [objective.explanation_text]" + parts += "Objective #[objective_count]: [objective.explanation_text]" objective_count++ if(win) parts += "The blood brothers were successful!" diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index a81c409233..7afe336319 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -564,7 +564,7 @@ else parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - parts += "Objective #[count]: [objective.explanation_text]" + parts += "Objective #[count]: [objective.explanation_text]" count++ if(changelingwin) diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm index 2b6c24f8dc..278746db5a 100644 --- a/code/modules/antagonists/cult/cult.dm +++ b/code/modules/antagonists/cult/cult.dm @@ -434,7 +434,7 @@ else parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - parts += "Objective #[count]: [objective.explanation_text]" + parts += "Objective #[count]: [objective.explanation_text]" count++ if(members.len) diff --git a/code/modules/antagonists/disease/disease_datum.dm b/code/modules/antagonists/disease/disease_datum.dm index 3c7de589d9..b118aeb308 100644 --- a/code/modules/antagonists/disease/disease_datum.dm +++ b/code/modules/antagonists/disease/disease_datum.dm @@ -54,7 +54,7 @@ else result += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - result += "Objective #[count]: [objective.explanation_text]" + result += "Objective #[count]: [objective.explanation_text]" count++ result += objectives_text diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 830555e9a2..480264297e 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -398,7 +398,7 @@ else objectives_text += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - objectives_text += "Objective #[count]: [objective.explanation_text]" + objectives_text += "Objective #[count]: [objective.explanation_text]" count++ if(uplink_true) diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm index c5e365d4eb..42b09abf38 100644 --- a/code/modules/antagonists/wizard/wizard.dm +++ b/code/modules/antagonists/wizard/wizard.dm @@ -276,7 +276,7 @@ else parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - parts += "Objective #[count]: [objective.explanation_text]" + parts += "Objective #[count]: [objective.explanation_text]" count++ if(wizardwin) From e812844c704606c69d4480e760a70f72753f0b3e Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 1 Feb 2020 21:05:27 -0800 Subject: [PATCH 23/30] Revert "" This reverts commit d6d01d848cd6c6e78f40698d3e85fafe473c3bf8. --- code/__HELPERS/roundend.dm | 2 +- code/datums/mind.dm | 8 ++++---- code/game/gamemodes/objective.dm | 3 --- code/modules/antagonists/_common/antag_team.dm | 2 +- code/modules/antagonists/bloodsucker/datum_bloodsucker.dm | 2 +- code/modules/antagonists/brother/brother.dm | 2 +- code/modules/antagonists/changeling/changeling.dm | 2 +- code/modules/antagonists/cult/cult.dm | 2 +- code/modules/antagonists/disease/disease_datum.dm | 2 +- code/modules/antagonists/traitor/datum_traitor.dm | 2 +- code/modules/antagonists/wizard/wizard.dm | 2 +- 11 files changed, 13 insertions(+), 16 deletions(-) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index c42d60c88f..535f1154e7 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -566,7 +566,7 @@ else objective_parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - objective_parts += "Objective #[count]: [objective.explanation_text]" + objective_parts += "Objective #[count]: [objective.explanation_text]" count++ return objective_parts.Join("
    ") diff --git a/code/datums/mind.dm b/code/datums/mind.dm index aa1a2ed55f..628e698ae0 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -374,7 +374,7 @@ output += "Objectives:" var/obj_count = 1 for(var/datum/objective/objective in all_objectives) - output += "
    Objective #[obj_count++]: [objective.explanation_text]" + output += "
    Objective #[obj_count++]: [objective.explanation_text]" var/list/datum/mind/other_owners = objective.get_owners() - src if(other_owners.len) output += "
      " @@ -523,8 +523,8 @@ to_chat(usr,"Invalid objective.") return qdel(objective) //TODO: Needs cleaning objective destroys (whatever that means) - message_admins("[key_name_admin(usr)] removed an objective for [current]: [objective.explanation_text]") - log_admin("[key_name(usr)] removed an objective for [current]: [objective.explanation_text]") + message_admins("[key_name_admin(usr)] removed an objective for [current]: [objective.explanation_text]") + log_admin("[key_name(usr)] removed an objective for [current]: [objective.explanation_text]") else if(href_list["obj_completed"]) var/datum/objective/objective @@ -537,7 +537,7 @@ to_chat(usr,"Invalid objective.") return objective.completed = !objective.completed - log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective.explanation_text]") + log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective.explanation_text]") else if (href_list["silicon"]) switch(href_list["silicon"]) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index c044680302..db6d0a6672 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1157,6 +1157,3 @@ GLOBAL_LIST_EMPTY(possible_sabotages) /datum/objective/flavor/wizard flavor_file = "strings/flavor_objectives/wizard.txt" - -/datum/objective/flavor/bloodsucker - flavor_file = "strings/flavor_objectives/bloodsucker.txt" diff --git a/code/modules/antagonists/_common/antag_team.dm b/code/modules/antagonists/_common/antag_team.dm index 958a50460c..027abc7c94 100644 --- a/code/modules/antagonists/_common/antag_team.dm +++ b/code/modules/antagonists/_common/antag_team.dm @@ -46,7 +46,7 @@ else report += "Objective #[objective_count]: [objective.explanation_text] [completion*100]%" else - report += "Objective #[objective_count]: [objective.explanation_text]" + report += "Objective #[objective_count]: [objective.explanation_text]" objective_count++ if(win) report += "The [name] was successful!" diff --git a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm index a768978583..844b523135 100644 --- a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm +++ b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm @@ -372,7 +372,7 @@ datum/antagonist/bloodsucker/proc/SpendRank() protege_objective.generate_objective() add_objective(protege_objective) - if (prob(50)) + if (rand(0,1) == 0) // Heart Thief Objective var/datum/objective/bloodsucker/heartthief/heartthief_objective = new heartthief_objective.owner = owner diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm index 7d2bd45827..2292006da1 100644 --- a/code/modules/antagonists/brother/brother.dm +++ b/code/modules/antagonists/brother/brother.dm @@ -118,7 +118,7 @@ else parts += "Objective #[objective_count]: [objective.explanation_text] [completion*100]%" else - parts += "Objective #[objective_count]: [objective.explanation_text]" + parts += "Objective #[objective_count]: [objective.explanation_text]" objective_count++ if(win) parts += "The blood brothers were successful!" diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index 7afe336319..a81c409233 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -564,7 +564,7 @@ else parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - parts += "Objective #[count]: [objective.explanation_text]" + parts += "Objective #[count]: [objective.explanation_text]" count++ if(changelingwin) diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm index 278746db5a..2b6c24f8dc 100644 --- a/code/modules/antagonists/cult/cult.dm +++ b/code/modules/antagonists/cult/cult.dm @@ -434,7 +434,7 @@ else parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - parts += "Objective #[count]: [objective.explanation_text]" + parts += "Objective #[count]: [objective.explanation_text]" count++ if(members.len) diff --git a/code/modules/antagonists/disease/disease_datum.dm b/code/modules/antagonists/disease/disease_datum.dm index b118aeb308..3c7de589d9 100644 --- a/code/modules/antagonists/disease/disease_datum.dm +++ b/code/modules/antagonists/disease/disease_datum.dm @@ -54,7 +54,7 @@ else result += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - result += "Objective #[count]: [objective.explanation_text]" + result += "Objective #[count]: [objective.explanation_text]" count++ result += objectives_text diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 480264297e..830555e9a2 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -398,7 +398,7 @@ else objectives_text += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - objectives_text += "Objective #[count]: [objective.explanation_text]" + objectives_text += "Objective #[count]: [objective.explanation_text]" count++ if(uplink_true) diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm index 42b09abf38..c5e365d4eb 100644 --- a/code/modules/antagonists/wizard/wizard.dm +++ b/code/modules/antagonists/wizard/wizard.dm @@ -276,7 +276,7 @@ else parts += "Objective #[count]: [objective.explanation_text] [completion*100]%" else - parts += "Objective #[count]: [objective.explanation_text]" + parts += "Objective #[count]: [objective.explanation_text]" count++ if(wizardwin) From dd63e8cf84798b4df6e00d4dc9c2455ce42c7766 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sat, 1 Feb 2020 21:07:21 -0800 Subject: [PATCH 24/30] oofies --- code/modules/antagonists/traitor/datum_traitor.dm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 830555e9a2..3180c1b305 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -391,14 +391,14 @@ if(objective.completable) var/completion = objective.check_completion() if(completion >= 1) - objectives_text += "Objective #[count]: [objective.explanation_text] Success!" + objectives_text += "
      Objective #[count]: [objective.explanation_text] Success!" else if(completion <= 0) - objectives_text += "Objective #[count]: [objective.explanation_text] Fail." + objectives_text += "
      Objective #[count]: [objective.explanation_text] Fail." traitorwin = FALSE else - objectives_text += "Objective #[count]: [objective.explanation_text] [completion*100]%" + objectives_text += "
      Objective #[count]: [objective.explanation_text] [completion*100]%" else - objectives_text += "Objective #[count]: [objective.explanation_text]" + objectives_text += "
      Objective #[count]: [objective.explanation_text]" count++ if(uplink_true) From 52432ed0a760909eda17878d91321fd8d13a98e8 Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 3 Feb 2020 07:12:27 -0800 Subject: [PATCH 25/30] too many dynamic changes for my sanity --- code/__DEFINES/dynamic.dm | 1 + code/__DEFINES/role_preferences.dm | 1 + code/__DEFINES/vote.dm | 1 + .../configuration/configuration.dm | 23 +++++++ .../configuration/entries/dynamic.dm | 4 ++ code/controllers/subsystem/persistence.dm | 7 +-- code/controllers/subsystem/vote.dm | 61 +++++++++++------- code/game/gamemodes/dynamic/dynamic.dm | 15 ++++- .../dynamic/dynamic_rulesets_latejoin.dm | 30 +++++++-- .../dynamic/dynamic_rulesets_midround.dm | 2 +- .../gamemodes/dynamic/dynamic_storytellers.dm | 62 ++++++++++++++----- config/dynamic_config.txt | 14 +++++ tgstation.dme | 1 + 13 files changed, 170 insertions(+), 52 deletions(-) diff --git a/code/__DEFINES/dynamic.dm b/code/__DEFINES/dynamic.dm index 45c1ba9cb2..0d57961f48 100644 --- a/code/__DEFINES/dynamic.dm +++ b/code/__DEFINES/dynamic.dm @@ -5,6 +5,7 @@ #define NO_ASSASSIN (1<<0) #define WAROPS_ALWAYS_ALLOWED (1<<1) +#define USE_PREF_WEIGHTS (1<<2) #define ONLY_RULESET (1<<0) #define HIGHLANDER_RULESET (1<<1) diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 28a04c2a51..7fabb74157 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -38,6 +38,7 @@ #define ROLE_BLOODSUCKER "bloodsucker" //#define ROLE_MONSTERHUNTER "monster hunter" Disabled for now #define ROLE_GHOSTCAFE "ghostcafe" +#define ROLE_MINOR_ANTAG "minorantag" //Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR. //The gamemode specific ones are just so the gamemodes can query whether a player is old enough //(in game days played) to play that role diff --git a/code/__DEFINES/vote.dm b/code/__DEFINES/vote.dm index 8fb2e6deab..6553447029 100644 --- a/code/__DEFINES/vote.dm +++ b/code/__DEFINES/vote.dm @@ -2,5 +2,6 @@ #define APPROVAL_VOTING 1 #define RANKED_CHOICE_VOTING 2 #define SCORE_VOTING 3 +#define MAJORITY_JUDGEMENT_VOTING 4 GLOBAL_LIST_INIT(vote_score_options,list("Bad","Poor","Acceptable","Good","Great")) diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index 79d125f608..974a0c0e88 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -364,6 +364,29 @@ runnable_modes[M] = final_weight return runnable_modes +/datum/controller/configuration/proc/get_runnable_storytellers() + var/list/datum/dynamic_storyteller/runnable_storytellers = new + var/list/probabilities = Get(/datum/config_entry/keyed_list/storyteller_weight) + var/list/repeated_mode_adjust = Get(/datum/config_entry/number_list/repeated_mode_adjust) + for(var/T in storyteller_cache) + var/datum/dynamic_storyteller/S = T + var/config_tag = initial(S.config_tag) + var/final_weight = initial(S.weight) + if(probabilities[config_tag]<=0) + continue + final_weight = probabilities[config_tag] + if(SSpersistence.saved_storytellers.len == 3 && repeated_mode_adjust.len == 3) + var/name = initial(S.name) + var/recent_round = min(SSpersistence.saved_storytellers.Find(name),3) + var/adjustment = 0 + while(recent_round) + adjustment += repeated_mode_adjust[recent_round] + recent_round = SSpersistence.saved_modes.Find(name,recent_round+1,0) + final_weight *= ((100-adjustment)/100) + runnable_storytellers[S] = final_weight + return runnable_storytellers + + /datum/controller/configuration/proc/get_runnable_midround_modes(crew) var/list/datum/game_mode/runnable_modes = new var/list/probabilities = Get(/datum/config_entry/keyed_list/probability) diff --git a/code/controllers/configuration/entries/dynamic.dm b/code/controllers/configuration/entries/dynamic.dm index 7f3e16d57e..4c03de4678 100644 --- a/code/controllers/configuration/entries/dynamic.dm +++ b/code/controllers/configuration/entries/dynamic.dm @@ -88,3 +88,7 @@ /datum/config_entry/number/dynamic_warops_cost config_entry_value = 10 min_val = 0 + +/datum/config_entry/keyed_list/storyteller_weight + key_mode = KEY_MODE_TEXT + value_mode = VALUE_MODE_NUM diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm index e43c8f21a2..eecee740c9 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence.dm @@ -13,7 +13,7 @@ SUBSYSTEM_DEF(persistence) var/list/saved_messages = list() var/list/saved_modes = list(1,2,3) var/list/saved_dynamic_rules = list(list(),list(),list()) - var/list/saved_storytellers = list("foo","bar","baz","foo again","bar again") + var/list/saved_storytellers = list("foo","bar","baz") var/list/saved_maps var/list/saved_trophies = list() var/list/spawned_objects = list() @@ -190,6 +190,7 @@ SUBSYSTEM_DEF(persistence) if(!json) return saved_storytellers = json["data"] + saved_storytellers.len = 3 /datum/controller/subsystem/persistence/proc/LoadRecentMaps() var/json_file = file("data/RecentMaps.json") @@ -411,9 +412,7 @@ SUBSYSTEM_DEF(persistence) WRITE_FILE(json_file, json_encode(file_data)) /datum/controller/subsystem/persistence/proc/CollectStoryteller(var/datum/game_mode/dynamic/mode) - saved_storytellers.len = 5 - saved_storytellers[5] = saved_storytellers[4] - saved_storytellers[4] = saved_storytellers[3] + saved_storytellers.len = 3 saved_storytellers[3] = saved_storytellers[2] saved_storytellers[2] = saved_storytellers[1] saved_storytellers[1] = mode.storyteller.name diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index c67a1620f1..67fc1cf237 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -197,11 +197,16 @@ SUBSYSTEM_DEF(vote) for(var/choice in choices) if("[choice]" in this_vote && "[choice]" in scores_by_choice) sorted_insert(scores_by_choice["[choice]"],this_vote["[choice]"],/proc/cmp_numeric_asc) - var/middle_score = round(GLOB.vote_score_options.len/2,1) + var/min_score = 100 + var/max_score = -100 for(var/score_name in scores_by_choice) var/list/score = scores_by_choice[score_name] for(var/S in score) - scores[score_name] += S-middle_score + scores[score_name] += S + max_score=max(max_score,scores[score_name]) + min_score=min(min_score,scores[score_name]) + for(var/score_name in scores) // normalize the scores from 0-1 + scores[score_name] = (scores[score_name]-min_score)/(max_score-min_score) SSblackbox.record_feedback("nested tally","voting",scores[score_name],list(blackbox_text,"Total scores",score_name)) @@ -217,16 +222,20 @@ SUBSYSTEM_DEF(vote) if(vote_system == RANKED_CHOICE_VOTING) calculate_condorcet_votes(vote_title_text) if(vote_system == SCORE_VOTING) - calculate_majority_judgement_vote(vote_title_text) calculate_scores(vote_title_text) + if(vote_system == MAJORITY_JUDGEMENT_VOTING) + calculate_majority_judgement_vote(vote_title_text) // nothing uses this at the moment var/list/winners = get_result() var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic" if(winners.len > 0) if(was_roundtype_vote) stored_gamemode_votes = list() - if(!obfuscated && vote_system == RANKED_CHOICE_VOTING) - text += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!" - if(mode == "mode tiers") + if(!obfuscated) + if(vote_system == RANKED_CHOICE_VOTING) + text += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!" + if(vote_system == MAJORITY_JUDGEMENT_VOTING) + text += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!" + if(vote_system == SCORE_VOTING) for(var/score_name in scores) var/score = scores[score_name] if(!score) @@ -266,13 +275,18 @@ SUBSYSTEM_DEF(vote) SSblackbox.record_feedback("nested tally","voting",1,list(vote_title_text,"[j]\th",choices[myvote[j]])) if(obfuscated) //CIT CHANGE - adds obfuscated votes. this messages admins with the vote's true results var/admintext = "Obfuscated results" - if(vote_system == RANKED_CHOICE_VOTING) - admintext += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!" - else if(vote_system == SCORE_VOTING) - admintext += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!" - for(var/i=1,i<=choices.len,i++) - var/votes = choices[choices[i]] - admintext += "\n[choices[i]]: [votes]" + if(vote_system != SCORE_VOTING) + if(vote_system == RANKED_CHOICE_VOTING) + admintext += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!" + else if(vote_system == MAJORITY_JUDGEMENT_VOTING) + admintext += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!" + for(var/i=1,i<=choices.len,i++) + var/votes = choices[choices[i]] + admintext += "\n[choices[i]]: [votes]" + else + for(var/i=1,i<=scores.len,i++) + var/score = scores[scores[i]] + admintext += "\n[scores[i]]: [score]" message_admins(admintext) return . @@ -323,7 +337,11 @@ SUBSYSTEM_DEF(vote) log_admin("Gamemode has been voted for and switched to: [GLOB.master_mode].") else GLOB.master_mode = "dynamic" - var/datum/dynamic_storyteller/S = config.pick_storyteller(.) + var/list/runnable_storytellers = config.get_runnable_storytellers() + for(var/T in runnable_storytellers) + var/datum/dynamic_storyteller/S = T + runnable_storytellers[S] *= scores[initial(S.name)] + var/datum/dynamic_storyteller/S = pickweightAllowZero(runnable_storytellers) GLOB.dynamic_storyteller_type = S if("map") var/datum/map_config/VM = config.maplist[.] @@ -444,11 +462,8 @@ SUBSYSTEM_DEF(vote) if("dynamic") for(var/T in config.storyteller_cache) var/datum/dynamic_storyteller/S = T - var/recent_rounds = 0 - for(var/i in 1 to SSpersistence.saved_storytellers.len) - if(SSpersistence.saved_storytellers[i] == initial(S.name)) - recent_rounds++ - if(recent_rounds < initial(S.weight)) + var/list/probabilities = CONFIG_GET(keyed_list/storyteller_weight) + if(probabilities[initial(S.config_tag)] > 0) choices.Add(initial(S.name)) choice_descs.Add(initial(S.desc)) choices.Add("Secret") @@ -516,7 +531,7 @@ SUBSYSTEM_DEF(vote) . += "

      Vote any number of choices.

      " if(RANKED_CHOICE_VOTING) . += "

      Vote by order of preference. Revoting will demote to the bottom. 1 is your favorite, and higher numbers are worse.

      " - if(SCORE_VOTING) + if(SCORE_VOTING,MAJORITY_JUDGEMENT_VOTING) . += "

      Grade the candidates by how much you like them.

      " . += "

      No-votes have no power--your opinion is only heard if you vote!

      " . += "Time Left: [DisplayTimeText(end_time-world.time)]
        " @@ -553,7 +568,7 @@ SUBSYSTEM_DEF(vote) . += "(Saved!)" . += "(Load vote from save)" . += "(Reset votes)" - if(SCORE_VOTING) + if(SCORE_VOTING,MAJORITY_JUDGEMENT_VOTING) var/list/myvote = voted[C.ckey] for(var/i=1,i<=choices.len,i++) . += "
      • [choices[i]]" @@ -656,7 +671,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = SSpersistence.saved_votes[usr.ckey][mode] if(islist(voted[usr.ckey])) var/malformed = FALSE - if(vote_system == SCORE_VOTING) + if(vote_system == SCORE_VOTING || vote_system == MAJORITY_JUDGEMENT_VOTING) for(var/thing in voted[usr.ckey]) if(!(thing in choices)) malformed = TRUE @@ -670,7 +685,7 @@ SUBSYSTEM_DEF(vote) to_chat(usr,"Your saved vote was malformed! Start over!") voted -= usr.ckey else - if(vote_system == SCORE_VOTING) + if(vote_system == SCORE_VOTING || vote_system == MAJORITY_JUDGEMENT_VOTING) submit_vote(round(text2num(href_list["vote"])),round(text2num(href_list["score"]))) else submit_vote(round(text2num(href_list["vote"]))) diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 821c819664..6fe52b0f8d 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -239,12 +239,20 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, null) . += "Peaceful Waypoint
        " . += "Your station orbits deep within controlled, core-sector systems and serves as a waypoint for routine traffic through Nanotrasen's trade empire. Due to the combination of high security, interstellar traffic, and low strategic value, it makes any direct threat of violence unlikely. Your primary enemies will be incompetence and bored crewmen: try to organize team-building events to keep staffers interested and productive. However, even deep in our territory there may be subversive elements, especially for such a high-value target as your station. Keep an eye out, but don't expect much trouble." set_security_level(SEC_LEVEL_GREEN) + for(var/T in subtypesof(/datum/station_goal)) + var/datum/station_goal/G = new T + if(!(G in station_goals)) + station_goals += G if(21 to 79) var/perc_green = 100-round(100*((threat_level-21)/(79-21))) if(prob(perc_green)) . += "Core Territory
        " . += "Your station orbits within reliably mundane, secure space. Although Nanotrasen has a firm grip on security in your region, the valuable resources and strategic position aboard your station make it a potential target for infiltrations. Monitor crew for non-loyal behavior, but expect a relatively tame shift free of large-scale destruction. We expect great things from your station." set_security_level(SEC_LEVEL_GREEN) + for(var/T in subtypesof(/datum/station_goal)) + var/datum/station_goal/G = new T + if(!(G in station_goals)) + station_goals += G else if(prob(perc_green)) . += "Contested System
        " . += "Your station's orbit passes along the edge of Nanotrasen's sphere of influence. While subversive elements remain the most likely threat against your station, hostile organizations are bolder here, where our grip is weaker. Exercise increased caution against elite Syndicate strike forces, or Executives forbid, some kind of ill-conceived unionizing attempt." @@ -273,7 +281,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, null) if(GLOB.security_level >= SEC_LEVEL_BLUE) priority_announce("A summary has been copied and printed to all communications consoles.", "Security level elevated.", "intercept") else - priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no likely threats to [station_name()]. Have a secure shift!", "Security Report", "commandreport") + priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no likely threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", "commandreport") // Yes, this is copy pasted from game_mode /datum/game_mode/dynamic/check_finished(force_ending) @@ -346,7 +354,8 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, null) generate_threat() storyteller.start_injection_cooldowns() - + SSevents.frequency_lower = storyteller.event_frequency_lower // 6 minutes by default + SSevents.frequency_upper = storyteller.event_frequency_upper // 20 minutes by default log_game("DYNAMIC: Dynamic Mode initialized with a Threat Level of... [threat_level]!") initial_threat_level = threat_level return TRUE @@ -395,7 +404,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, null) /datum/game_mode/dynamic/post_setup(report) update_playercounts() - + for(var/datum/dynamic_ruleset/roundstart/rule in executed_rules) addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_roundstart_rule, rule), rule.delay) ..() diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm index f4e9971a05..f6755057e2 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm @@ -47,6 +47,8 @@ assigned += M.mind M.mind.special_role = antag_flag M.mind.add_antag_datum(antag_datum) + log_admin("[M.name] was made into a [name] by dynamic.") + message_admins("[M.name] was made into a [name] by dynamic.") return TRUE ////////////////////////////////////////////// @@ -72,12 +74,6 @@ property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1) always_max_weight = TRUE -/datum/dynamic_ruleset/latejoin/infiltrator/execute() - . = ..() - for(var/datum/mind/M in assigned) - log_admin("[M.name] was made into a traitor by dynamic.") - message_admins("[M.name] was made into a traitor by dynamic.") - ////////////////////////////////////////////// // // // REVOLUTIONARY PROVOCATEUR // @@ -225,3 +221,25 @@ log_admin("[M.name] was made into a bloodsucker by dynamic.") message_admins("[M.name] was made into a bloodsucker by dynamic.") return TRUE + +////////////////////////////////////////////// +// // +// COLLECTOR // +// // +////////////////////////////////////////////// + +/datum/dynamic_ruleset/latejoin/collector + name = "Contraband Collector" + config_tag = "latejoin_collector" + antag_datum = /datum/antagonist/collector + antag_flag = ROLE_MINOR_ANTAG + restricted_roles = list("AI", "Cyborg") + protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") + required_candidates = 1 + weight = 5 + cost = 1 + requirements = list(10,10,10,10,10,10,10,10,10,10) + high_population_requirement = 10 + repeatable = TRUE + flags = TRAITOR_RULESET + property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 2) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 92a02f5920..abd560171e 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -494,7 +494,7 @@ high_population_requirement = 50 repeatable_weight_decrease = 2 repeatable = TRUE - property_weights = list("story_potential" = 1, "trust" = 1, "extended" = 1, "valid" = 2, "integrity" = 2) + 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() diff --git a/code/game/gamemodes/dynamic/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm index afa6ed8ba7..303c436f99 100644 --- a/code/game/gamemodes/dynamic/dynamic_storytellers.dm +++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm @@ -1,5 +1,6 @@ /datum/dynamic_storyteller var/name = "none" + var/config_tag = null var/desc = "A coder's idiocy." var/list/property_weights = list() var/curve_centre = 0 @@ -7,6 +8,8 @@ var/forced_threat_level = -1 var/flags = 0 var/weight = 3 // how many rounds need to have been recently played for this storyteller to be left out of the vote + var/event_frequency_lower = 6 MINUTES + var/event_frequency_upper = 20 MINUTES var/datum/game_mode/dynamic/mode = null /** @@ -20,14 +23,6 @@ Property weights are: "conversion" -- Basically a bool. Conversion antags, well, convert. It's its own class for a good reason. */ -/datum/dynamic_storyteller/New() - ..() - if (istype(SSticker.mode, /datum/game_mode/dynamic)) - mode = SSticker.mode - GLOB.dynamic_curve_centre = curve_centre - GLOB.dynamic_curve_width = curve_width - GLOB.dynamic_forced_threat_level = forced_threat_level - /datum/dynamic_storyteller/proc/start_injection_cooldowns() var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_latejoin_delay_max + GLOB.dynamic_first_latejoin_delay_min) mode.latejoin_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_first_latejoin_delay_min, GLOB.dynamic_first_latejoin_delay_max)) + world.time @@ -42,7 +37,28 @@ Property weights are: return /datum/dynamic_storyteller/proc/on_start() - return + if (istype(SSticker.mode, /datum/game_mode/dynamic)) + mode = SSticker.mode + GLOB.dynamic_curve_centre = curve_centre + GLOB.dynamic_curve_width = curve_width + if(flags & USE_PREF_WEIGHTS) + var/voters = 0 + var/mean = 0 + for(var/client/c in GLOB.clients) + var/vote = c.prefs.preferred_chaos + if(vote) + voters += 1 + switch(vote) + if(CHAOS_NONE) + mean -= 5 + if(CHAOS_LOW) + mean -= 2.5 + if(CHAOS_HIGH) + mean += 2.5 + if(CHAOS_MAX) + mean += 5 + GLOB.dynamic_curve_centre += (mean/voters) + GLOB.dynamic_forced_threat_level = forced_threat_level /datum/dynamic_storyteller/proc/get_midround_cooldown() var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_midround_delay_max + GLOB.dynamic_midround_delay_min) @@ -154,12 +170,15 @@ Property weights are: /datum/dynamic_storyteller/cowabunga name = "Chaotic" + config_tag = "chaotic" curve_centre = 10 desc = "Chaos: high. Variation: high. Likely antags: clock cult, revs, wizard." property_weights = list("extended" = -1, "chaos" = 10) - weight = 2 + weight = 1 + event_frequency_lower = 2 MINUTES + event_frequency_upper = 10 MINUTES flags = WAROPS_ALWAYS_ALLOWED - var/refund_cooldown + var/refund_cooldown = 0 /datum/dynamic_storyteller/cowabunga/get_midround_cooldown() return ..() / 4 @@ -169,12 +188,13 @@ Property weights are: /datum/dynamic_storyteller/cowabunga/do_process() if(refund_cooldown < world.time) - mode.refund_threat(10) - mode.log_threat("Cowabunga it is. Refunded 10 threat. Threat is now [mode.threat].") - refund_cooldown = world.time + 300 SECONDS + mode.refund_threat(20) + mode.log_threat("Cowabunga it is. Refunded 20 threat. Threat is now [mode.threat].") + refund_cooldown = world.time + 600 SECONDS /datum/dynamic_storyteller/team name = "Teamwork" + config_tag = "teamwork" desc = "Chaos: high. Variation: low. Likely antags: nukies, clockwork cult, wizard, blob, xenomorph." curve_centre = 2 curve_width = 1.5 @@ -187,6 +207,7 @@ Property weights are: /datum/dynamic_storyteller/conversion name = "Conversion" + config_tag = "conversion" desc = "Chaos: high. Variation: medium. Likely antags: cults, bloodsuckers, revs." curve_centre = 3 curve_width = 1 @@ -196,24 +217,33 @@ Property weights are: /datum/dynamic_storyteller/classic name = "Random" + config_tag = "random" desc = "Chaos: varies. Variation: highest. No special weights attached." weight = 6 + flags = USE_PREF_WEIGHTS curve_width = 4 /datum/dynamic_storyteller/memes name = "Story" + config_tag = "story" desc = "Chaos: varies. Variation: high. Likely antags: abductors, nukies, wizard, traitor." + weight = 4 + flags = USE_PREF_WEIGHTS curve_width = 4 property_weights = list("story_potential" = 10) /datum/dynamic_storyteller/suspicion name = "Intrigue" + config_tag = "intrigue" desc = "Chaos: low. Variation: high. Likely antags: traitor, bloodsucker. Rare: revs, blood cult." + weight = 4 + flags = USE_PREF_WEIGHTS curve_width = 4 property_weights = list("trust" = -5) /datum/dynamic_storyteller/liteextended name = "Calm" + config_tag = "calm" desc = "Chaos: low. Variation: medium. Likely antags: bloodsuckers, traitors, sentient disease, revenant." curve_centre = -5 curve_width = 0.5 @@ -226,10 +256,12 @@ Property weights are: /datum/dynamic_storyteller/extended name = "Extended" + config_tag = "extended" desc = "Chaos: none. Variation: none. Likely antags: none." curve_centre = -20 - weight = 2 + weight = 0 curve_width = 0.5 /datum/dynamic_storyteller/extended/on_start() + ..() GLOB.dynamic_forced_extended = TRUE diff --git a/config/dynamic_config.txt b/config/dynamic_config.txt index 2ddebdf37a..25bc763d0b 100644 --- a/config/dynamic_config.txt +++ b/config/dynamic_config.txt @@ -1,3 +1,13 @@ +## Dynamic storytellers weights: how likely each storyteller is to show up. This is adjusted by voting and recency. +STORYTELLER_WEIGHT CHAOTIC 2 +STORYTELLER_WEIGHT TEAMWORK 4 +STORYTELLER_WEIGHT CONVERSION 2 +STORYTELLER_WEIGHT RANDOM 6 +STORYTELLER_WEIGHT INTRIGUE 6 +STORYTELLER_WEIGHT STORY 6 +STORYTELLER_WEIGHT CALM 6 +STORYTELLER_WEIGHT EXTENDED 0 + ## Injection delays: how long (in minutes) will pass before a midround or latejoin antag is injected. DYNAMIC_MIDROUND_DELAY_MIN 5 DYNAMIC_MIDROUND_DELAY_MAX 15 @@ -92,6 +102,7 @@ DYNAMIC_WEIGHT RADIATION_STORM 1 DYNAMIC_WEIGHT LATEJOIN_TRAITOR 7 DYNAMIC_WEIGHT LATEJOIN_REVOLUTION 2 DYNAMIC_WEIGHT LATEJOIN_BLOODSUCKER 4 +DYNAMIC_WEIGHT LATEJOIN_COLLECTOR 5 ## Threat cost. This is decreased from the mode's threat when the rule is executed. DYNAMIC_COST TRAITOR 10 @@ -153,6 +164,7 @@ DYNAMIC_COST RADIATION_STORM 3 DYNAMIC_COST LATEJOIN_TRAITOR 5 DYNAMIC_COST LATEJOIN_REVOLUTION 20 DYNAMIC_COST LATEJOIN_BLOODSUCKER 10 +DYNAMIC_COST LATEJOIN_COLLECTOR 1 ## Rule will not be generated with threat levels below requirement at a pop value. Pop values are determined by dynamic's pop-per-requirement. ## By default it's 0-8, 9-17, 18-26, 27-35, 36-44, 45-53, 54-60, 61-69, 70-78, 79+. @@ -210,6 +222,7 @@ DYNAMIC_REQUIREMENTS RADIATION_STORM 5 5 5 5 5 5 5 5 5 5 DYNAMIC_REQUIREMENTS LATEJOIN_TRAITOR 40 30 20 15 15 15 15 15 15 15 DYNAMIC_REQUIREMENTS LATEJOIN_REVOLUTION 101 101 70 40 40 40 40 40 40 40 DYNAMIC_REQUIREMENTS LATEJOIN_BLOODSUCKER 40 30 20 15 15 15 15 15 15 15 +DYNAMIC_REQUIREMENTS LATEJOIN_COLLECTOR 10 10 10 10 10 10 10 10 10 10 ## An alternative, static requirement used instead when pop is over mode's high_pop_limit. DYNAMIC_HIGH_POPULATION_REQUIREMENT TRAITOR 50 @@ -267,6 +280,7 @@ DYNAMIC_HIGH_POPULATION_REQUIREMENT RADIATION_STORM 5 DYNAMIC_HIGH_POPULATION_REQUIREMENT LATEJOIN_TRAITOR 15 DYNAMIC_HIGH_POPULATION_REQUIREMENT LATEJOIN_REVOLUTION 50 DYNAMIC_HIGH_POPULATION_REQUIREMENT LATEJOIN_BLOODSUCKER 15 +DYNAMIC_HIGH_POPULATION_REQUIREMENT LATEJOIN_COLLECTOR 10 ## Dynamic traitor stuff diff --git a/tgstation.dme b/tgstation.dme index 476f20cfe3..8552cbb7bc 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -1391,6 +1391,7 @@ #include "code\modules\antagonists\clockcult\clock_structures\traps\brass_skewer.dm" #include "code\modules\antagonists\clockcult\clock_structures\traps\power_null.dm" #include "code\modules\antagonists\clockcult\clock_structures\traps\steam_vent.dm" +#include "code\modules\antagonists\collector\collector.dm" #include "code\modules\antagonists\cult\blood_magic.dm" #include "code\modules\antagonists\cult\cult.dm" #include "code\modules\antagonists\cult\cult_comms.dm" From 72c1f60af776d996d0ff051e4a1bca8aa58278bb Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 3 Feb 2020 08:10:34 -0800 Subject: [PATCH 26/30] and now the voting works --- code/controllers/subsystem/vote.dm | 54 ++++++++++++------------------ 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 67fc1cf237..49f1f3f851 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -188,24 +188,19 @@ SUBSYSTEM_DEF(vote) choices[score_name]++ /datum/controller/subsystem/vote/proc/calculate_scores(var/blackbox_text) - var/list/scores_by_choice = list() for(var/choice in choices) - scores_by_choice += "[choice]" - scores_by_choice["[choice]"] = list() + scores += "[choice]" + scores["[choice]"] = 0 for(var/ckey in voted) var/list/this_vote = voted[ckey] - for(var/choice in choices) - if("[choice]" in this_vote && "[choice]" in scores_by_choice) - sorted_insert(scores_by_choice["[choice]"],this_vote["[choice]"],/proc/cmp_numeric_asc) + for(var/choice in this_vote) + scores["[choice]"] += this_vote["[choice]"] var/min_score = 100 var/max_score = -100 - for(var/score_name in scores_by_choice) - var/list/score = scores_by_choice[score_name] - for(var/S in score) - scores[score_name] += S + for(var/score_name in scores) // normalize the scores from 0-1 max_score=max(max_score,scores[score_name]) min_score=min(min_score,scores[score_name]) - for(var/score_name in scores) // normalize the scores from 0-1 + for(var/score_name in scores) scores[score_name] = (scores[score_name]-min_score)/(max_score-min_score) SSblackbox.record_feedback("nested tally","voting",scores[score_name],list(blackbox_text,"Total scores",score_name)) @@ -235,12 +230,6 @@ SUBSYSTEM_DEF(vote) text += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!" if(vote_system == MAJORITY_JUDGEMENT_VOTING) text += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!" - if(vote_system == SCORE_VOTING) - for(var/score_name in scores) - var/score = scores[score_name] - if(!score) - score = 0 - text = "\n[score_name]: [obfuscated ? "???" : score]" else for(var/i=1,i<=choices.len,i++) var/votes = choices[choices[i]] @@ -258,6 +247,15 @@ SUBSYSTEM_DEF(vote) text += "\nVote Result: [obfuscated ? "???" : .]" //CIT CHANGE - adds obfuscated votes else text += "\nDid not vote: [GLOB.clients.len-voted.len]" + else if(vote_system == SCORE_VOTING) + for(var/score_name in scores) + var/score = scores[score_name] + if(!score) + score = 0 + if(was_roundtype_vote) + stored_gamemode_votes[score_name] = score + text = "\n[score_name]: [obfuscated ? "???" : score]" + . = 1 else text += "Vote Result: Inconclusive - No Votes!" log_vote(text) @@ -330,19 +328,13 @@ SUBSYSTEM_DEF(vote) if("dynamic") if(SSticker.current_state > GAME_STATE_PREGAME)//Don't change the mode if the round already started. return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.") - if(. == "Secret") - GLOB.master_mode = "secret" - SSticker.save_mode(.) - message_admins("The gamemode has been voted for, and has been changed to: [GLOB.master_mode]") - log_admin("Gamemode has been voted for and switched to: [GLOB.master_mode].") - else - GLOB.master_mode = "dynamic" - var/list/runnable_storytellers = config.get_runnable_storytellers() - for(var/T in runnable_storytellers) - var/datum/dynamic_storyteller/S = T - runnable_storytellers[S] *= scores[initial(S.name)] - var/datum/dynamic_storyteller/S = pickweightAllowZero(runnable_storytellers) - GLOB.dynamic_storyteller_type = S + GLOB.master_mode = "dynamic" + var/list/runnable_storytellers = config.get_runnable_storytellers() + for(var/T in runnable_storytellers) + var/datum/dynamic_storyteller/S = T + runnable_storytellers[S] *= scores[initial(S.name)] + var/datum/dynamic_storyteller/S = pickweightAllowZero(runnable_storytellers) + GLOB.dynamic_storyteller_type = S if("map") var/datum/map_config/VM = config.maplist[.] message_admins("The map has been voted for and will change to: [VM.map_name]") @@ -466,8 +458,6 @@ SUBSYSTEM_DEF(vote) if(probabilities[initial(S.config_tag)] > 0) choices.Add(initial(S.name)) choice_descs.Add(initial(S.desc)) - choices.Add("Secret") - choice_descs.Add("Standard secret. Switches mode if it wins.") if("custom") question = stripped_input(usr,"What is the vote for?") if(!question) From 88ce25a09b17c1d0f9bf1d6275815e34b4204656 Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 3 Feb 2020 08:10:45 -0800 Subject: [PATCH 27/30] hopefully fixing the once-assassin --- code/game/gamemodes/objective.dm | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index c713c71b49..459ff2f3d6 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -181,14 +181,10 @@ GLOBAL_LIST_EMPTY(objectives) ..() if(target && target.current) explanation_text = "Kill [target.name], the [!target_role_type ? target.assigned_role : target.special_role]. You only need to kill them once; if they come back, you've still succeeded." + START_PROCESSING(SSprocessing,src) else explanation_text = "Free Objective" -/datum/objective/assassinate/once/find_target_by_role(role, role_type=0, invert=0) - . = ..() - if(.) - START_PROCESSING(SSprocessing,src) - /datum/objective/assassinate/once/check_completion() return won || ..() From e4e5b651e69e2321ac97b5d89809bed02d405be8 Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 3 Feb 2020 08:11:03 -0800 Subject: [PATCH 28/30] making permassassin scale with dynamic --- code/modules/antagonists/traitor/datum_traitor.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 3180c1b305..1c7ee48f71 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -191,7 +191,7 @@ maroon_objective.owner = owner maroon_objective.find_target() add_objective(maroon_objective) - else if(prob(30)) + else if(prob(max(0,assassin_prob-20))) var/datum/objective/assassinate/kill_objective = new kill_objective.owner = owner kill_objective.find_target() From aabd0b9e7936b20ceee3454f6bd782c0298ab671 Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 3 Feb 2020 08:18:49 -0800 Subject: [PATCH 29/30] fixing quirk removal (whoops) --- code/modules/antagonists/_common/antag_datum.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index f019858319..0c05afb155 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -128,6 +128,7 @@ GLOBAL_LIST_EMPTY(antagonists) var/datum/quirk/Q = q if(Q.antag_removal_text) to_chat(L, "[Q.antag_removal_text]") + L.remove_quirk(Q.type) //Returns the team antagonist belongs to if any. /datum/antagonist/proc/get_team() From a67902ee32a885d84f20f36aeadfabcf9d7c78eb Mon Sep 17 00:00:00 2001 From: Putnam Date: Tue, 4 Feb 2020 12:43:59 -0800 Subject: [PATCH 30/30] Also added instant runoff and renamed schulze. yak shaving --- code/__DEFINES/vote.dm | 3 ++- code/controllers/subsystem/vote.dm | 40 +++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/code/__DEFINES/vote.dm b/code/__DEFINES/vote.dm index 6553447029..b83ea7b8f6 100644 --- a/code/__DEFINES/vote.dm +++ b/code/__DEFINES/vote.dm @@ -1,7 +1,8 @@ #define PLURALITY_VOTING 0 #define APPROVAL_VOTING 1 -#define RANKED_CHOICE_VOTING 2 +#define SCHULZE_VOTING 2 #define SCORE_VOTING 3 #define MAJORITY_JUDGEMENT_VOTING 4 +#define INSTANT_RUNOFF_VOTING 5 GLOBAL_LIST_INIT(vote_score_options,list("Bad","Poor","Acceptable","Good","Great")) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 49f1f3f851..2a7c4401f3 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -204,6 +204,28 @@ SUBSYSTEM_DEF(vote) scores[score_name] = (scores[score_name]-min_score)/(max_score-min_score) SSblackbox.record_feedback("nested tally","voting",scores[score_name],list(blackbox_text,"Total scores",score_name)) +/datum/controller/subsystem/vote/proc/get_runoff_results(var/blackbox_text) + var/already_lost_runoff = list() + var/list/cur_choices = choices.Copy() + for(var/ckey in voted) + choices[choices[voted[ckey][1]]]++ // jesus christ how horrifying + for(var/_this_var_unused_ignore_it in 1 to choices.len) // if it takes more than this something REALLY wrong happened + for(var/ckey in voted) + cur_choices[cur_choices[voted[ckey][1]]]++ // jesus christ how horrifying + var/least_vote = 100000 + var/least_voted + for(var/i in 1 to cur_choices.len) + var/option = cur_choices[i] + if(cur_choices[option] > voted.len/2) + return list(option) + else if(cur_choices[option] < least_vote && !(option in already_lost_runoff)) + least_vote = cur_choices[option] + least_voted = i + already_lost_runoff += cur_choices[least_voted] + for(var/ckey in voted) + voted[ckey] -= least_voted + for(var/option in cur_choices) + cur_choices[option] = 0 /datum/controller/subsystem/vote/proc/announce_result() var/vote_title_text @@ -214,19 +236,19 @@ SUBSYSTEM_DEF(vote) else text += "[capitalize(mode)] Vote" vote_title_text = "[capitalize(mode)] Vote" - if(vote_system == RANKED_CHOICE_VOTING) + if(vote_system == SCHULZE_VOTING) calculate_condorcet_votes(vote_title_text) if(vote_system == SCORE_VOTING) calculate_scores(vote_title_text) if(vote_system == MAJORITY_JUDGEMENT_VOTING) calculate_majority_judgement_vote(vote_title_text) // nothing uses this at the moment - var/list/winners = get_result() + var/list/winners = vote_system == INSTANT_RUNOFF_VOTING ? get_runoff_results() : get_result() var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic" if(winners.len > 0) if(was_roundtype_vote) stored_gamemode_votes = list() if(!obfuscated) - if(vote_system == RANKED_CHOICE_VOTING) + if(vote_system == SCHULZE_VOTING) text += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!" if(vote_system == MAJORITY_JUDGEMENT_VOTING) text += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!" @@ -265,7 +287,7 @@ SUBSYSTEM_DEF(vote) if(APPROVAL_VOTING,PLURALITY_VOTING) for(var/i=1,i<=choices.len,i++) SSblackbox.record_feedback("nested tally","voting",choices[choices[i]],list(vote_title_text,choices[i])) - if(RANKED_CHOICE_VOTING) + if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING) for(var/i=1,i<=voted.len,i++) var/list/myvote = voted[voted[i]] if(islist(myvote)) @@ -274,7 +296,7 @@ SUBSYSTEM_DEF(vote) if(obfuscated) //CIT CHANGE - adds obfuscated votes. this messages admins with the vote's true results var/admintext = "Obfuscated results" if(vote_system != SCORE_VOTING) - if(vote_system == RANKED_CHOICE_VOTING) + if(vote_system == SCHULZE_VOTING) admintext += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!" else if(vote_system == MAJORITY_JUDGEMENT_VOTING) admintext += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!" @@ -385,7 +407,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = list(vote) choices[choices[vote]]++ return vote - if(RANKED_CHOICE_VOTING) + if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING) if(usr.ckey in voted) if(vote in voted[usr.ckey]) voted[usr.ckey] -= vote @@ -394,7 +416,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = list() voted[usr.ckey] += vote saved -= usr.ckey - if(SCORE_VOTING) + if(SCORE_VOTING,MAJORITY_JUDGEMENT_VOTING) if(!(usr.ckey in voted)) voted += usr.ckey voted[usr.ckey] = list() @@ -519,7 +541,7 @@ SUBSYSTEM_DEF(vote) . += "

        Vote one.

        " if(APPROVAL_VOTING) . += "

        Vote any number of choices.

        " - if(RANKED_CHOICE_VOTING) + if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING) . += "

        Vote by order of preference. Revoting will demote to the bottom. 1 is your favorite, and higher numbers are worse.

        " if(SCORE_VOTING,MAJORITY_JUDGEMENT_VOTING) . += "

        Grade the candidates by how much you like them.

        " @@ -541,7 +563,7 @@ SUBSYSTEM_DEF(vote) if(choice_descs.len >= i) . += "
      • [choice_descs[i]]
      • " . += "

      " - if(RANKED_CHOICE_VOTING) + if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING) var/list/myvote = voted[C.ckey] for(var/i=1,i<=choices.len,i++) var/vote = (islist(myvote) ? (myvote.Find(i)) : 0)