diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 8e59106d98..fb7a29c907 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -534,10 +534,12 @@ return parts.Join() -/proc/printobjectives(datum/mind/ply) +/proc/printobjectives(list/objectives) + if(!objectives || !objectives.len) + return var/list/objective_parts = list() var/count = 1 - for(var/datum/objective/objective in ply.objectives) + for(var/datum/objective/objective in objectives) if(objective.check_completion()) objective_parts += "Objective #[count]: [objective.explanation_text] Success!" else diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 68efe93254..5cf03e2684 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -41,8 +41,6 @@ var/special_role var/list/restricted_roles = list() - var/list/datum/objective/objectives = list() - var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button. var/linglink @@ -360,13 +358,15 @@ output += memory + var/list/all_objectives = list() for(var/datum/antagonist/A in antag_datums) output += A.antag_memory + all_objectives |= A.objectives - if(objectives.len) + if(all_objectives.len) output += "Objectives:" var/obj_count = 1 - for(var/datum/objective/objective in objectives) + for(var/datum/objective/objective in all_objectives) output += "
Objective #[obj_count++]: [objective.explanation_text]" var/list/datum/mind/other_owners = objective.get_owners() - src if(other_owners.len) @@ -377,7 +377,7 @@ if(window) recipient << browse(output,"window=memory") - else if(objectives.len || memory) + else if(all_objectives.len || memory) to_chat(recipient, "[output]") /datum/mind/Topic(href, href_list) @@ -408,34 +408,24 @@ memory = new_memo else if (href_list["obj_edit"] || href_list["obj_add"]) - var/datum/objective/objective - var/objective_pos + var/objective_pos //Edited objectives need to keep same order in antag objective list var/def_value - var/datum/antagonist/target_antag + var/datum/objective/old_objective //The old objective we're replacing/editing + var/datum/objective/new_objective //New objective we're be adding - if (href_list["obj_edit"]) - objective = locate(href_list["obj_edit"]) - if (!objective) + if(href_list["obj_edit"]) + for(var/datum/antagonist/A in antag_datums) + old_objective = locate(href_list["obj_edit"]) in A.objectives + if(old_objective) + target_antag = A + objective_pos = A.objectives.Find(old_objective) + break + if(!old_objective) + to_chat(usr,"Invalid objective.") return - for(var/datum/antagonist/A in antag_datums) - if(objective in A.objectives) - target_antag = A - objective_pos = A.objectives.Find(objective) - break - - if(!target_antag) //Shouldn't happen anymore - stack_trace("objective without antagonist found") - objective_pos = objectives.Find(objective) - - //Text strings are easy to manipulate. Revised for simplicity. - var/temp_obj_type = "[objective.type]"//Convert path into a text string. - def_value = copytext(temp_obj_type, 19)//Convert last part of path into an objective keyword. - if(!def_value)//If it's a custom objective, it will be an empty string. - def_value = "custom" else - //We're adding this objective if(href_list["target_antag"]) var/datum/antagonist/X = locate(href_list["target_antag"]) in antag_datums if(X) @@ -447,7 +437,7 @@ if(1) target_antag = antag_datums[1] else - var/datum/antagonist/target = input("Which antagonist gets the objective:", "Antagonist", def_value) as null|anything in antag_datums + "(new custom antag)" + var/datum/antagonist/target = input("Which antagonist gets the objective:", "Antagonist", "(new custom antag)") as null|anything in antag_datums + "(new custom antag)" if (QDELETED(target)) return else if(target == "(new custom antag)") @@ -455,149 +445,88 @@ else target_antag = target - var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "maroon", "debrain", "protect", "destroy", "prevent", "hijack", "escape", "survive", "martyr", "steal", "download", "nuclear", "capture", "absorb", "custom") - if (!new_obj_type) + var/static/list/choices + if(!choices) + choices = list() + + var/list/allowed_types = list( + /datum/objective/assassinate, + /datum/objective/maroon, + /datum/objective/debrain, + /datum/objective/protect, + /datum/objective/destroy, + /datum/objective/hijack, + /datum/objective/escape, + /datum/objective/survive, + /datum/objective/martyr, + /datum/objective/steal, + /datum/objective/download, + /datum/objective/nuclear, + /datum/objective/capture, + /datum/objective/absorb, + /datum/objective/custom + ) + + for(var/T in allowed_types) + var/datum/objective/X = T + choices[initial(X.name)] = T + + if(old_objective) + if(old_objective.name in choices) + def_value = old_objective.name + + var/selected_type = input("Select objective type:", "Objective type", def_value) as null|anything in choices + selected_type = choices[selected_type] + if (!selected_type) return - var/datum/objective/new_objective = null + if(!old_objective) + //Add new one + new_objective = new selected_type + new_objective.owner = src + new_objective.admin_edit(usr) + target_antag.objectives += new_objective - switch (new_obj_type) - if ("assassinate","protect","debrain","maroon") - var/list/possible_targets = list("Free objective") - for(var/datum/mind/possible_target in SSticker.minds) - if ((possible_target != src) && ishuman(possible_target.current)) - possible_targets += possible_target.current - - var/mob/def_target = null - var/list/objective_list = typecacheof(list(/datum/objective/assassinate, /datum/objective/protect, /datum/objective/debrain, /datum/objective/maroon)) - if (is_type_in_typecache(objective, objective_list) && objective.target) - def_target = objective.target.current - - var/mob/new_target = input("Select target:", "Objective target", def_target) as null|anything in possible_targets - if (!new_target) - return - - var/objective_path = text2path("/datum/objective/[new_obj_type]") - if (new_target == "Free objective") - new_objective = new objective_path - new_objective.owner = src - new_objective.target = null - new_objective.explanation_text = "Free objective" - else - new_objective = new objective_path - new_objective.owner = src - new_objective.target = new_target.mind - //Will display as special role if the target is set as MODE. Ninjas/commandos/nuke ops. - new_objective.update_explanation_text() - - if ("destroy") - var/list/possible_targets = active_ais(1) - if(possible_targets.len) - var/mob/new_target = input("Select target:", "Objective target") as null|anything in possible_targets - new_objective = new /datum/objective/destroy - new_objective.target = new_target.mind - new_objective.owner = src - new_objective.update_explanation_text() - else - to_chat(usr, "No active AIs with minds") - - if ("prevent") - new_objective = new /datum/objective/block - new_objective.owner = src - - if ("hijack") - new_objective = new /datum/objective/hijack - new_objective.owner = src - - if ("escape") - new_objective = new /datum/objective/escape - new_objective.owner = src - - if ("survive") - new_objective = new /datum/objective/survive - new_objective.owner = src - - if("martyr") - new_objective = new /datum/objective/martyr - new_objective.owner = src - - if ("nuclear") - new_objective = new /datum/objective/nuclear - new_objective.owner = src - - if ("steal") - if (!istype(objective, /datum/objective/steal)) - new_objective = new /datum/objective/steal - new_objective.owner = src - else - new_objective = objective - var/datum/objective/steal/steal = new_objective - if (!steal.select_target()) - return - - if("download","capture","absorb") - var/def_num - if(objective&&objective.type==text2path("/datum/objective/[new_obj_type]")) - def_num = objective.target_amount - - var/target_number = input("Input target number:", "Objective", def_num) as num | null - if (isnull(target_number))//Ordinarily, you wouldn't need isnull. In this case, the value may already exist. - return - - switch(new_obj_type) - if("download") - new_objective = new /datum/objective/download - new_objective.explanation_text = "Download [target_number] research node\s." - if("capture") - new_objective = new /datum/objective/capture - new_objective.explanation_text = "Capture [target_number] lifeforms with an energy net. Live, rare specimens are worth more." - if("absorb") - new_objective = new /datum/objective/absorb - new_objective.explanation_text = "Absorb [target_number] compatible genomes." - new_objective.owner = src - new_objective.target_amount = target_number - - if ("custom") - var/expl = stripped_input(usr, "Custom objective:", "Objective", objective ? objective.explanation_text : "") - if (!expl) - return - new_objective = new /datum/objective - new_objective.owner = src - new_objective.explanation_text = expl - - if (!new_objective) - return - - if (objective) - if(target_antag) - target_antag.objectives -= objective - objectives -= objective - target_antag.objectives.Insert(objective_pos, new_objective) - message_admins("[key_name_admin(usr)] edited [current]'s objective to [new_objective.explanation_text]") - log_admin("[key_name(usr)] edited [current]'s objective to [new_objective.explanation_text]") - else - if(target_antag) - target_antag.objectives += new_objective - objectives += new_objective message_admins("[key_name_admin(usr)] added a new objective for [current]: [new_objective.explanation_text]") log_admin("[key_name(usr)] added a new objective for [current]: [new_objective.explanation_text]") + else + if(old_objective.type == selected_type) + //Edit the old + old_objective.admin_edit(usr) + new_objective = old_objective + else + //Replace the old + new_objective = new selected_type + new_objective.owner = src + new_objective.admin_edit(usr) + target_antag.objectives -= old_objective + target_antag.objectives.Insert(objective_pos, new_objective) + message_admins("[key_name_admin(usr)] edited [current]'s objective to [new_objective.explanation_text]") + log_admin("[key_name(usr)] edited [current]'s objective to [new_objective.explanation_text]") else if (href_list["obj_delete"]) - var/datum/objective/objective = locate(href_list["obj_delete"]) - if(!istype(objective)) - return + var/datum/objective/objective for(var/datum/antagonist/A in antag_datums) - if(objective in A.objectives) - A.objectives -= objective + objective = locate(href_list["obj_delete"]) in A.objectives + if(istype(objective)) break - objectives -= objective + if(!objective) + to_chat(usr,"Invalid objective.") + return + //qdel(objective) Needs cleaning objective destroys 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 = locate(href_list["obj_completed"]) - if(!istype(objective)) + var/datum/objective/objective + for(var/datum/antagonist/A in antag_datums) + objective = locate(href_list["obj_completed"]) in A.objectives + if(istype(objective)) + objective = objective + break + if(!objective) + 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]") @@ -652,10 +581,16 @@ usr = current traitor_panel() +/datum/mind/proc/get_all_objectives() + var/list/all_objectives = list() + for(var/datum/antagonist/A in antag_datums) + all_objectives |= A.objectives + return all_objectives + /datum/mind/proc/announce_objectives() var/obj_count = 1 to_chat(current, "Your current objectives:") - for(var/objective in objectives) + for(var/objective in get_all_objectives()) var/datum/objective/O = objective to_chat(current, "Objective #[obj_count]: [O.explanation_text]") obj_count++ diff --git a/code/game/gamemodes/devil/devil agent/devil_agent.dm b/code/game/gamemodes/devil/devil agent/devil_agent.dm index ec09bfc739..789cff5c8f 100644 --- a/code/game/gamemodes/devil/devil agent/devil_agent.dm +++ b/code/game/gamemodes/devil/devil agent/devil_agent.dm @@ -34,11 +34,12 @@ //If you override this method, have it return the number of objectives added. if(devil_target_list.len && devil_target_list[devil]) // Is a double agent var/datum/mind/target_mind = devil_target_list[devil] + var/datum/antagonist/devil/D = target_mind.has_antag_datum(/datum/antagonist/devil) var/datum/objective/devil/outsell/outsellobjective = new outsellobjective.owner = devil outsellobjective.target = target_mind outsellobjective.update_explanation_text() - devil.objectives += outsellobjective + D.objectives += outsellobjective return 1 return 0 diff --git a/code/game/gamemodes/devil/game_mode.dm b/code/game/gamemodes/devil/game_mode.dm index 2255766e74..208a24f3e5 100644 --- a/code/game/gamemodes/devil/game_mode.dm +++ b/code/game/gamemodes/devil/game_mode.dm @@ -4,11 +4,12 @@ /datum/game_mode/proc/add_devil_objectives(datum/mind/devil_mind, quantity) var/list/validtypes = list(/datum/objective/devil/soulquantity, /datum/objective/devil/soulquality, /datum/objective/devil/sintouch, /datum/objective/devil/buy_target) + var/datum/antagonist/devil/D = devil_mind.has_antag_datum(/datum/antagonist/devil) for(var/i = 1 to quantity) var/type = pick(validtypes) var/datum/objective/devil/objective = new type(null) objective.owner = devil_mind - devil_mind.objectives += objective + D.objectives += objective if(!istype(objective, /datum/objective/devil/buy_target)) validtypes -= type //prevent duplicate objectives, EXCEPT for buy_target. else diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index f6b1def645..f99fe5c3e4 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -4,7 +4,8 @@ GLOBAL_LIST_EMPTY(objectives) /datum/objective var/datum/mind/owner //The primary owner of the objective. !!SOMEWHAT DEPRECATED!! Prefer using 'team' for new code. - var/datum/team/team //An alternative to 'owner': a team. Use this when writing new code. + var/datum/team/team //An alternative to 'owner': a team. Use this when writing new code. + var/name = "generic objective" //Name for admin prompts 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. @@ -22,6 +23,32 @@ GLOBAL_LIST_EMPTY(objectives) if(owner) . += owner +/datum/objective/proc/admin_edit(mob/admin) + return + +//Shared by few objective types +/datum/objective/proc/admin_simple_target_pick(mob/admin) + var/list/possible_targets = list("Free objective") + var/def_value + for(var/datum/mind/possible_target in SSticker.minds) + if ((possible_target != src) && ishuman(possible_target.current)) + possible_targets += possible_target.current + + + if(target && target.current) + def_value = target.current + + var/mob/new_target = input(admin,"Select target:", "Objective target", def_value) as null|anything in possible_targets + if (!new_target) + return + + if (new_target == "Free objective") + target = null + else + target = new_target.mind + + update_explanation_text() + /datum/objective/proc/considered_escaped(datum/mind/M) if(!considered_alive(M)) return FALSE @@ -42,7 +69,7 @@ GLOBAL_LIST_EMPTY(objectives) /datum/objective/proc/is_unique_objective(possible_target) var/list/datum/mind/owners = get_owners() for(var/datum/mind/M in owners) - for(var/datum/objective/O in M.objectives) + for(var/datum/objective/O in M.get_all_objectives()) //This scope is debatable, probably should be passed in by caller. if(istype(O, type) && O.get_target() == possible_target) return FALSE return TRUE @@ -122,6 +149,7 @@ GLOBAL_LIST_EMPTY(objectives) H.equip_in_one_of_slots(O, slots) /datum/objective/assassinate + name = "assasinate" var/target_role_type=0 martyr_compatible = 1 @@ -141,6 +169,9 @@ GLOBAL_LIST_EMPTY(objectives) else explanation_text = "Free Objective" +/datum/objective/assassinate/admin_edit(mob/admin) + admin_simple_target_pick(admin) + /datum/objective/assassinate/internal var/stolen = 0 //Have we already eliminated this target? @@ -150,6 +181,7 @@ GLOBAL_LIST_EMPTY(objectives) explanation_text = "Assassinate [target.name], who was obliterated" /datum/objective/mutiny + name = "mutiny" var/target_role_type=0 martyr_compatible = 1 @@ -173,6 +205,7 @@ GLOBAL_LIST_EMPTY(objectives) explanation_text = "Free Objective" /datum/objective/maroon + name = "maroon" var/target_role_type=0 martyr_compatible = 1 @@ -191,7 +224,11 @@ GLOBAL_LIST_EMPTY(objectives) else explanation_text = "Free Objective" +/datum/objective/maroon/admin_edit(mob/admin) + admin_simple_target_pick(admin) + /datum/objective/debrain + name = "debrain" var/target_role_type=0 /datum/objective/debrain/find_target_by_role(role, role_type=0, invert=0) @@ -222,7 +259,11 @@ GLOBAL_LIST_EMPTY(objectives) else explanation_text = "Free Objective" +/datum/objective/debrain/admin_edit(mob/admin) + admin_simple_target_pick(admin) + /datum/objective/protect//The opposite of killing a dude. + name = "protect" martyr_compatible = 1 var/target_role_type = 0 var/human_check = TRUE @@ -243,10 +284,15 @@ GLOBAL_LIST_EMPTY(objectives) else explanation_text = "Free Objective" +/datum/objective/protect/admin_edit(mob/admin) + admin_simple_target_pick(admin) + /datum/objective/protect/nonhuman + name = "protect nonhuman" human_check = FALSE /datum/objective/hijack + name = "hijack" explanation_text = "Hijack the shuttle to ensure no loyalist Nanotrasen crew escape alive and out of custody." team_explanation_text = "Hijack the shuttle to ensure no loyalist Nanotrasen crew escape alive and out of custody. Leave no team member behind." martyr_compatible = 0 //Technically you won't get both anyway. @@ -261,6 +307,7 @@ GLOBAL_LIST_EMPTY(objectives) return SSshuttle.emergency.is_hijacked() /datum/objective/block + name = "no organics on shuttle" explanation_text = "Do not allow any organic lifeforms to escape on the shuttle alive." martyr_compatible = 1 @@ -274,6 +321,7 @@ GLOBAL_LIST_EMPTY(objectives) return TRUE /datum/objective/purge + name = "no mutants on shuttle" explanation_text = "Ensure no mutant humanoid species are present aboard the escape shuttle." martyr_compatible = 1 @@ -288,6 +336,7 @@ GLOBAL_LIST_EMPTY(objectives) return TRUE /datum/objective/robot_army + name = "robot army" explanation_text = "Have at least eight active cyborgs synced to you." martyr_compatible = 0 @@ -304,6 +353,7 @@ GLOBAL_LIST_EMPTY(objectives) return counter >= 8 /datum/objective/escape + name = "escape" explanation_text = "Escape on the shuttle or an escape pod alive and without being in custody." team_explanation_text = "Have all members of your team escape on a shuttle or pod alive, without being in custody." @@ -316,6 +366,7 @@ GLOBAL_LIST_EMPTY(objectives) return TRUE /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 var/target_missing_id @@ -351,7 +402,11 @@ GLOBAL_LIST_EMPTY(objectives) return TRUE return FALSE +/datum/objective/escape/escape_with_identity/admin_edit(mob/admin) + admin_simple_target_pick(admin) + /datum/objective/survive + name = "survive" explanation_text = "Stay alive until the end." /datum/objective/survive/check_completion() @@ -362,6 +417,7 @@ GLOBAL_LIST_EMPTY(objectives) return TRUE /datum/objective/survive/exist //Like survive, but works for silicons and zombies and such. + name = "survive nonhuman" /datum/objective/survive/exist/check_completion() var/list/datum/mind/owners = get_owners() @@ -371,6 +427,7 @@ GLOBAL_LIST_EMPTY(objectives) return TRUE /datum/objective/martyr + name = "martyr" explanation_text = "Die a glorious death." /datum/objective/martyr/check_completion() @@ -383,6 +440,7 @@ GLOBAL_LIST_EMPTY(objectives) return TRUE /datum/objective/nuclear + name = "nuclear" explanation_text = "Destroy the station with a nuclear device." martyr_compatible = 1 @@ -393,6 +451,7 @@ GLOBAL_LIST_EMPTY(objectives) GLOBAL_LIST_EMPTY(possible_items) /datum/objective/steal + name = "steal" var/datum/objective_item/targetinfo = null //Save the chosen item datum so we can access it later. var/obj/item/steal_target = null //Needed for custom objectives (they're just items, not datums). martyr_compatible = 0 @@ -430,18 +489,19 @@ GLOBAL_LIST_EMPTY(possible_items) explanation_text = "Free objective" return -/datum/objective/steal/proc/select_target() //For admins setting objectives manually. +/datum/objective/steal/admin_edit(mob/admin) var/list/possible_items_all = GLOB.possible_items+"custom" - var/new_target = input("Select target:", "Objective target", steal_target) as null|anything in possible_items_all + var/new_target = input(admin,"Select target:", "Objective target", steal_target) as null|anything in possible_items_all if (!new_target) return if (new_target == "custom") //Can set custom items. - var/obj/item/custom_target = input("Select type:","Type") as null|anything in typesof(/obj/item) - if (!custom_target) + var/custom_path = input(admin,"Search for target item type:","Type") as null|text + if (!custom_path) return + var/obj/item/custom_target = pick_closest_path(custom_path, make_types_fancy(subtypesof(/obj/item))) var/custom_name = initial(custom_target.name) - custom_name = stripped_input("Enter target name:", "Objective target", custom_name) + custom_name = stripped_input(admin,"Enter target name:", "Objective target", custom_name) if (!custom_name) return steal_target = custom_target @@ -449,7 +509,6 @@ GLOBAL_LIST_EMPTY(possible_items) else set_target(new_target) - return steal_target /datum/objective/steal/check_completion() var/list/datum/mind/owners = get_owners() @@ -476,6 +535,7 @@ GLOBAL_LIST_EMPTY(possible_items) GLOBAL_LIST_EMPTY(possible_items_special) /datum/objective/steal/special //ninjas are so special they get their own subtype good for them + name = "steal special" /datum/objective/steal/special/New() ..() @@ -487,8 +547,12 @@ GLOBAL_LIST_EMPTY(possible_items_special) return set_target(pick(GLOB.possible_items_special)) /datum/objective/steal/exchange + name = "exchange" martyr_compatible = 0 +/datum/objective/steal/exchange/admin_edit(mob/admin) + return + /datum/objective/steal/exchange/proc/set_faction(faction,otheragent) target = otheragent if(faction == "red") @@ -508,6 +572,7 @@ GLOBAL_LIST_EMPTY(possible_items_special) /datum/objective/steal/exchange/backstab + name = "prevent exchange" /datum/objective/steal/exchange/backstab/set_faction(faction) if(faction == "red") @@ -519,12 +584,17 @@ GLOBAL_LIST_EMPTY(possible_items_special) /datum/objective/download + name = "download" /datum/objective/download/proc/gen_amount_goal() target_amount = rand(20,40) - explanation_text = "Download [target_amount] research node\s." + update_explanation_text() return target_amount +/datum/objective/download/update_explanation_text() + ..() + explanation_text = "Download [target_amount] research node\s." + /datum/objective/download/check_completion() var/datum/techweb/checking = new var/list/datum/mind/owners = get_owners() @@ -541,13 +611,24 @@ GLOBAL_LIST_EMPTY(possible_items_special) TD.stored_research.copy_research_to(checking) return checking.researched_nodes.len >= target_amount +/datum/objective/download/admin_edit(mob/admin) + var/count = input(admin,"How many nodes ?","Nodes",target_amount) as num|null + if(count) + target_amount = count + update_explanation_text() + /datum/objective/capture + name = "capture" var/captured_amount = 0 /datum/objective/capture/proc/gen_amount_goal() - target_amount = rand(5,10) - explanation_text = "Capture [target_amount] lifeform\s with an energy net. Live, rare specimens are worth more." - return target_amount + target_amount = rand(5,10) + explanation_text = "Capture [target_amount] lifeform\s with an energy net. Live, rare specimens are worth more." + return target_amount + +/datum/objective/capture/update_explanation_text() + . = ..() + explanation_text = "Capture [target_amount] lifeform\s with an energy net. Live, rare specimens are worth more." /datum/objective/capture/check_completion()//Basically runs through all the mobs in the area to determine how much they are worth. /*var/area/centcom/holding/A = GLOB.areas_by_type[/area/centcom/holding] @@ -576,10 +657,16 @@ GLOBAL_LIST_EMPTY(possible_items_special) captured_amount+=2*/ //Removed in favour of adding points on capture, in energy_net_nets.dm return captured_amount >= target_amount +/datum/objective/capture/admin_edit(mob/admin) + var/count = input(admin,"How many mobs to capture ?","capture",target_amount) as num|null + if(count) + target_amount = count + update_explanation_text() //Changeling Objectives /datum/objective/absorb + name = "absorb" /datum/objective/absorb/proc/gen_amount_goal(lowbound = 4, highbound = 6) target_amount = rand (lowbound,highbound) @@ -595,9 +682,19 @@ GLOBAL_LIST_EMPTY(possible_items_special) n_p ++ target_amount = min(target_amount, n_p) - explanation_text = "Extract [target_amount] compatible genome\s." + update_explanation_text() return target_amount +/datum/objective/absorb/update_explanation_text() + . = ..() + explanation_text = "Extract [target_amount] compatible genome\s." + +/datum/objective/absorb/admin_edit(mob/admin) + var/count = input(admin,"How many people to absorb?","absorb",target_amount) as num|null + if(count) + target_amount = count + update_explanation_text() + /datum/objective/absorb/check_completion() var/list/datum/mind/owners = get_owners() var/absorbedcount = 0 @@ -611,6 +708,7 @@ GLOBAL_LIST_EMPTY(possible_items_special) return absorbedcount >= target_amount /datum/objective/absorb_most + name = "absorb most" explanation_text = "Extract more compatible genomes than any other Changeling." /datum/objective/absorb_most/check_completion() @@ -631,6 +729,7 @@ GLOBAL_LIST_EMPTY(possible_items_special) return TRUE /datum/objective/absorb_changeling + name = "absorb changeling" explanation_text = "Absorb another Changeling." /datum/objective/absorb_changeling/check_completion() @@ -653,6 +752,7 @@ GLOBAL_LIST_EMPTY(possible_items_special) //End Changeling Objectives /datum/objective/destroy + name = "destroy AI" martyr_compatible = 1 /datum/objective/destroy/find_target() @@ -674,10 +774,20 @@ GLOBAL_LIST_EMPTY(possible_items_special) else explanation_text = "Free Objective" +/datum/objective/destroy/admin_edit(mob/admin) + var/list/possible_targets = active_ais(1) + if(possible_targets.len) + var/mob/new_target = input(admin,"Select target:", "Objective target") as null|anything in possible_targets + target = new_target.mind + else + to_chat(admin, "No active AIs with minds") + update_explanation_text() + /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) @@ -686,10 +796,12 @@ GLOBAL_LIST_EMPTY(possible_items_special) 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) @@ -705,6 +817,14 @@ GLOBAL_LIST_EMPTY(possible_items_special) stolen_count++ return stolen_count >= 5 +//Created by admin tools +/datum/objective/custom + name = "custom" + +/datum/objective/custom/admin_edit(mob/admin) + var/expl = stripped_input(admin, "Custom objective:", "Objective", explanation_text) + if(expl) + explanation_text = expl //////////////////////////////// // Changeling team objectives // diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index e358f10346..4d252f1a46 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -370,16 +370,14 @@ O.find_target() O.update_explanation_text() if(!(O.target)) - O.owner.objectives -= O qdel(O) - if(mob_occupant.mind && mob_occupant.mind.assigned_role) + if(mob_occupant.mind) //Handle job slot/tater cleanup. - var/job = mob_occupant.mind.assigned_role - SSjob.FreeRole(job) - if(mob_occupant.mind.objectives.len) - mob_occupant.mind.objectives.Cut() - mob_occupant.mind.special_role = null + if(mob_occupant.mind.assigned_role) + var/job = mob_occupant.mind.assigned_role + SSjob.FreeRole(job) + mob_occupant.mind.special_role = null // Delete them from datacore. diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index 42719e28bd..1894d8c7ae 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -96,7 +96,6 @@ GLOBAL_LIST_EMPTY(antagonists) LAZYREMOVE(owner.antag_datums, src) if(!silent && owner.current) farewell() - owner.objectives -= objectives var/datum/team/team = get_team() if(team) team.remove_member(owner) @@ -132,14 +131,14 @@ GLOBAL_LIST_EMPTY(antagonists) report += printplayer(owner) var/objectives_complete = TRUE - if(owner.objectives.len) - report += printobjectives(owner) - for(var/datum/objective/objective in owner.objectives) + if(objectives.len) + report += printobjectives(objectives) + for(var/datum/objective/objective in objectives) if(!objective.check_completion()) objectives_complete = FALSE break - if(owner.objectives.len == 0 || objectives_complete) + if(objectives.len == 0 || objectives_complete) report += "The [name] was successful!" else report += "The [name] has failed!" @@ -216,25 +215,6 @@ GLOBAL_LIST_EMPTY(antagonists) return antag_memory = new_memo -//This datum will autofill the name with special_role -//Used as placeholder for minor antagonists, please create proper datums for these -/datum/antagonist/auto_custom - show_in_antagpanel = FALSE - antagpanel_category = "Other" - show_name_in_check_antagonists = TRUE - -/datum/antagonist/auto_custom/on_gain() - ..() - name = owner.special_role - //Add all objectives not already owned by other datums to this one. - var/list/already_registered_objectives = list() - for(var/datum/antagonist/A in owner.antag_datums) - if(A == src) - continue - else - already_registered_objectives |= A.objectives - objectives = owner.objectives - already_registered_objectives - //This one is created by admin tools for custom objectives /datum/antagonist/custom antagpanel_category = "Custom" diff --git a/code/modules/antagonists/blob/blob.dm b/code/modules/antagonists/blob/blob.dm index 964bc99311..3d6db983dc 100644 --- a/code/modules/antagonists/blob/blob.dm +++ b/code/modules/antagonists/blob/blob.dm @@ -30,7 +30,6 @@ var/datum/objective/blob_takeover/main = new main.owner = owner objectives += main - owner.objectives |= objectives /datum/antagonist/blob/apply_innate_effects(mob/living/mob_override) if(!isovermind(owner.current)) diff --git a/code/modules/antagonists/blood_contract/blood_contract.dm b/code/modules/antagonists/blood_contract/blood_contract.dm new file mode 100644 index 0000000000..4e7238647e --- /dev/null +++ b/code/modules/antagonists/blood_contract/blood_contract.dm @@ -0,0 +1,33 @@ + +/datum/antagonist/blood_contract + name = "Blood Contract Target" + show_in_roundend = FALSE + show_in_antagpanel = FALSE + +/datum/antagonist/blood_contract/on_gain() + . = ..() + give_objective() + start_the_hunt() + +/datum/antagonist/blood_contract/proc/give_objective() + var/datum/objective/survive/survive = new + survive.owner = owner + objectives += survive + +/datum/antagonist/blood_contract/greet() + . = ..() + to_chat(owner, "You've been marked for death! Don't let the demons get you! KILL THEM ALL!") + +/datum/antagonist/blood_contract/proc/start_the_hunt() + var/mob/living/carbon/human/H = owner.current + if(!istype(H)) + return + H.add_atom_colour("#FF0000", ADMIN_COLOUR_PRIORITY) + var/obj/effect/mine/pickup/bloodbath/B = new(H) + INVOKE_ASYNC(B, /obj/effect/mine/pickup/bloodbath/.proc/mineEffect, H) //could use moving out from the mine + + for(var/mob/living/carbon/human/P in GLOB.player_list) + if(P == H) + continue + to_chat(P, "You have an overwhelming desire to kill [H]. [H.p_theyve(TRUE)] been marked red! Whoever [H.p_they()] [H.p_were()], friend or foe, go kill [H.p_them()]!") + P.put_in_hands(new /obj/item/kitchen/knife/butcher(P), TRUE) diff --git a/code/modules/antagonists/brainwashing/brainwashing.dm b/code/modules/antagonists/brainwashing/brainwashing.dm index f1cff2bff4..491ee9d2e5 100644 --- a/code/modules/antagonists/brainwashing/brainwashing.dm +++ b/code/modules/antagonists/brainwashing/brainwashing.dm @@ -9,7 +9,6 @@ for(var/O in directives) var/datum/objective/brainwashing/objective = new(O) B.objectives += objective - M.objectives += objective B.greet() else B = new() @@ -32,10 +31,6 @@ antagpanel_category = "Other" show_name_in_check_antagonists = TRUE -/datum/antagonist/brainwashed/on_gain() - owner.objectives |= objectives - . = ..() - /datum/antagonist/brainwashed/greet() to_chat(owner, "Your mind reels as it begins focusing on a single purpose...") to_chat(owner, "Follow the Directives, at any cost!") diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm index f63e81acbf..7c589bb3ab 100644 --- a/code/modules/antagonists/brother/brother.dm +++ b/code/modules/antagonists/brother/brother.dm @@ -20,7 +20,6 @@ /datum/antagonist/brother/on_gain() SSticker.mode.brothers += owner objectives += team.objectives - owner.objectives += objectives owner.special_role = special_role finalize_brother() return ..() diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index b6e3d66c35..0d68660d9d 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -459,8 +459,6 @@ objectives += identity_theft escape_objective_possible = FALSE - owner.objectives |= objectives - /datum/antagonist/changeling/proc/update_changeling_icons_added() var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_CHANGELING] hud.join_hud(owner.current) diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm index 47cf2abf3f..9989058d43 100644 --- a/code/modules/antagonists/cult/cult.dm +++ b/code/modules/antagonists/cult/cult.dm @@ -35,7 +35,6 @@ /datum/antagonist/cult/proc/add_objectives() objectives |= cult_team.objectives - owner.objectives |= objectives /datum/antagonist/cult/Destroy() QDEL_NULL(communion) diff --git a/code/modules/antagonists/devil/devil.dm b/code/modules/antagonists/devil/devil.dm index dc649025d2..2e38734b6f 100644 --- a/code/modules/antagonists/devil/devil.dm +++ b/code/modules/antagonists/devil/devil.dm @@ -549,7 +549,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", var/list/parts = list() parts += printplayer(owner) parts += printdevilinfo() - parts += printobjectives(owner) + parts += printobjectives(objectives) return parts.Join("
") //A simple super light weight datum for the codex gigas. diff --git a/code/modules/antagonists/devil/imp/imp.dm b/code/modules/antagonists/devil/imp/imp.dm index da51a5d698..fa5263059a 100644 --- a/code/modules/antagonists/devil/imp/imp.dm +++ b/code/modules/antagonists/devil/imp/imp.dm @@ -57,3 +57,18 @@ visible_message("[src] screams in agony as it sublimates into a sulfurous smoke.") ghostize() qdel(src) + +/datum/antagonist/imp + name = "Imp" + antagpanel_category = "Devil" + show_in_roundend = FALSE + +/datum/antagonist/imp/on_gain() + . = ..() + give_objectives() + +/datum/antagonist/imp/proc/give_objectives() + var/datum/objective/newobjective = new + newobjective.explanation_text = "Try to get a promotion to a higher devilic rank." + newobjective.owner = owner + objectives += newobjective \ No newline at end of file diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm index afe439f02c..df761ac183 100644 --- a/code/modules/antagonists/devil/true_devil/_true_devil.dm +++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm @@ -147,13 +147,8 @@ if(ascended || user.mind.soulOwner == src.mind) var/mob/living/simple_animal/imp/S = new(get_turf(loc)) user.transfer_ckey(S, FALSE) - S.mind.assigned_role = "Imp" - S.mind.special_role = "Imp" - var/datum/objective/newobjective = new - newobjective.explanation_text = "Try to get a promotion to a higher devilic rank." - S.mind.objectives += newobjective - to_chat(S, S.playstyle_string) - to_chat(S, "Objective #[1]: [newobjective.explanation_text]") + var/datum/antagonist/imp/A = new() + S.mind.add_antag_datum(A) else return ..() diff --git a/code/modules/antagonists/disease/disease_datum.dm b/code/modules/antagonists/disease/disease_datum.dm index eb0feac0a2..1aef9ceba6 100644 --- a/code/modules/antagonists/disease/disease_datum.dm +++ b/code/modules/antagonists/disease/disease_datum.dm @@ -10,12 +10,10 @@ var/datum/objective/O = new /datum/objective/disease_infect() O.owner = owner objectives += O - owner.objectives += O O = new /datum/objective/disease_infect_centcom() O.owner = owner objectives += O - owner.objectives += O . = ..() diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm index bb24af4f7a..5968c7643a 100644 --- a/code/modules/antagonists/ert/ert.dm +++ b/code/modules/antagonists/ert/ert.dm @@ -113,7 +113,6 @@ /datum/antagonist/ert/proc/forge_objectives() if(ert_team) objectives |= ert_team.objectives - owner.objectives |= objectives /datum/antagonist/ert/proc/equipERT() var/mob/living/carbon/human/H = owner.current diff --git a/code/modules/antagonists/greentext/greentext.dm b/code/modules/antagonists/greentext/greentext.dm index ffaab71aca..13a3c2a07a 100644 --- a/code/modules/antagonists/greentext/greentext.dm +++ b/code/modules/antagonists/greentext/greentext.dm @@ -8,7 +8,6 @@ O.completed = TRUE //YES! O.owner = owner objectives += O - owner.objectives += objectives /datum/antagonist/greentext/on_gain() forge_objectives() diff --git a/code/modules/antagonists/highlander/highlander.dm b/code/modules/antagonists/highlander/highlander.dm index 51e8d9a13b..49635356ac 100644 --- a/code/modules/antagonists/highlander/highlander.dm +++ b/code/modules/antagonists/highlander/highlander.dm @@ -24,8 +24,6 @@ hijack_objective.owner = owner objectives += hijack_objective - owner.objectives |= objectives - /datum/antagonist/highlander/on_gain() forge_objectives() owner.special_role = "highlander" diff --git a/code/modules/antagonists/magic_servant/magic_servant.dm b/code/modules/antagonists/magic_servant/magic_servant.dm new file mode 100644 index 0000000000..31b51f59f6 --- /dev/null +++ b/code/modules/antagonists/magic_servant/magic_servant.dm @@ -0,0 +1,9 @@ +/datum/antagonist/magic_servant + name = "Magic Servant" + show_in_roundend = FALSE + show_in_antagpanel = FALSE + +/datum/antagonist/magic_servant/proc/setup_master(mob/M) + var/datum/objective/O = new("Serve [M.real_name].") + O.owner = owner + objectives |= O \ No newline at end of file diff --git a/code/modules/antagonists/monkey/monkey.dm b/code/modules/antagonists/monkey/monkey.dm index 9ce28eb60d..e480eb8674 100644 --- a/code/modules/antagonists/monkey/monkey.dm +++ b/code/modules/antagonists/monkey/monkey.dm @@ -63,7 +63,6 @@ /datum/antagonist/monkey/proc/forge_objectives() objectives |= monkey_team.objectives - owner.objectives |= objectives /datum/antagonist/monkey/admin_remove(mob/admin) var/mob/living/carbon/monkey/M = owner.current diff --git a/code/modules/antagonists/ninja/ninja.dm b/code/modules/antagonists/ninja/ninja.dm index a8bce90f1c..52e13bdc69 100644 --- a/code/modules/antagonists/ninja/ninja.dm +++ b/code/modules/antagonists/ninja/ninja.dm @@ -96,7 +96,6 @@ var/datum/objective/O = new /datum/objective/survive() O.owner = owner objectives += O - owner.objectives |= objectives /proc/remove_ninja(mob/living/L) if(!L || !L.mind) diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm index 800448c02f..4604439fc8 100644 --- a/code/modules/antagonists/nukeop/nukeop.dm +++ b/code/modules/antagonists/nukeop/nukeop.dm @@ -87,7 +87,7 @@ /datum/antagonist/nukeop/proc/forge_objectives() if(nuke_team) - owner.objectives |= nuke_team.objectives + objectives |= nuke_team.objectives /datum/antagonist/nukeop/proc/move_to_spawnpoint() var/team_number = 1 diff --git a/code/modules/antagonists/official/official.dm b/code/modules/antagonists/official/official.dm index 26de196cb4..9165a99d42 100644 --- a/code/modules/antagonists/official/official.dm +++ b/code/modules/antagonists/official/official.dm @@ -36,8 +36,6 @@ missionobj.completed = 1 mission = missionobj objectives |= mission - owner.objectives |= objectives - /datum/antagonist/official/on_gain() forge_objectives() diff --git a/code/modules/antagonists/overthrow/overthrow.dm b/code/modules/antagonists/overthrow/overthrow.dm index 075b9f13bc..c8b253793e 100644 --- a/code/modules/antagonists/overthrow/overthrow.dm +++ b/code/modules/antagonists/overthrow/overthrow.dm @@ -26,7 +26,6 @@ // Sets objectives, equips all antags with the storage implant. /datum/antagonist/overthrow/on_gain() objectives += team.objectives - owner.objectives += objectives ..() owner.announce_objectives() equip_overthrow() @@ -34,7 +33,6 @@ /datum/antagonist/overthrow/on_removal() owner.special_role = null - owner.objectives -= objectives ..() // Creates the overthrow team, or sets it. The objectives are static for all the team members. diff --git a/code/modules/antagonists/overthrow/overthrow_team.dm b/code/modules/antagonists/overthrow/overthrow_team.dm index 7f5d010013..a22f08d45c 100644 --- a/code/modules/antagonists/overthrow/overthrow_team.dm +++ b/code/modules/antagonists/overthrow/overthrow_team.dm @@ -35,7 +35,9 @@ objectives += heads_obj for(var/i in members) var/datum/mind/M = i - M.objectives += heads_obj + var/datum/antagonist/overthrow/O = M.has_antag_datum(/datum/antagonist/overthrow) + if(O) + O.objectives += heads_obj heads_obj.find_targets() addtimer(CALLBACK(src,.proc/update_objectives),OBJECTIVE_UPDATING_TIME,TIMER_UNIQUE) diff --git a/code/modules/antagonists/pirate/pirate.dm b/code/modules/antagonists/pirate/pirate.dm index 96830562e9..ff33477909 100644 --- a/code/modules/antagonists/pirate/pirate.dm +++ b/code/modules/antagonists/pirate/pirate.dm @@ -31,12 +31,7 @@ /datum/antagonist/pirate/on_gain() if(crew) - owner.objectives |= crew.objectives - . = ..() - -/datum/antagonist/pirate/on_removal() - if(crew) - owner.objectives -= crew.objectives + objectives |= crew.objectives . = ..() /datum/team/pirate @@ -53,7 +48,9 @@ getbooty.update_explanation_text() objectives += getbooty for(var/datum/mind/M in members) - M.objectives |= objectives + var/datum/antagonist/pirate/P = M.has_antag_datum(/datum/antagonist/pirate) + if(P) + P.objectives |= objectives /datum/objective/loot diff --git a/code/modules/antagonists/revenant/revenant_antag.dm b/code/modules/antagonists/revenant/revenant_antag.dm index 476db96fb8..8d99edf26e 100644 --- a/code/modules/antagonists/revenant/revenant_antag.dm +++ b/code/modules/antagonists/revenant/revenant_antag.dm @@ -14,8 +14,6 @@ objective2.owner = owner objectives += objective2 - owner.objectives |= objectives - /datum/antagonist/revenant/on_gain() forge_objectives() . = ..() diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm index e10d83ffb7..fef7061488 100644 --- a/code/modules/antagonists/revolution/revolution.dm +++ b/code/modules/antagonists/revolution/revolution.dm @@ -66,10 +66,10 @@ return rev_team /datum/antagonist/rev/proc/create_objectives() - owner.objectives |= rev_team.objectives + objectives |= rev_team.objectives /datum/antagonist/rev/proc/remove_objectives() - owner.objectives -= rev_team.objectives + objectives -= rev_team.objectives //Bump up to head_rev /datum/antagonist/rev/proc/promote() @@ -265,7 +265,8 @@ new_target.update_explanation_text() objectives += new_target for(var/datum/mind/M in members) - M.objectives |= objectives + var/datum/antagonist/rev/R = M.has_antag_datum(/datum/antagonist/rev) + R.objectives |= objectives addtimer(CALLBACK(src,.proc/update_objectives),HEAD_UPDATE_PERIOD,TIMER_UNIQUE) diff --git a/code/modules/antagonists/santa/santa.dm b/code/modules/antagonists/santa/santa.dm new file mode 100644 index 0000000000..bf42188cf6 --- /dev/null +++ b/code/modules/antagonists/santa/santa.dm @@ -0,0 +1,29 @@ +/datum/antagonist/santa + name = "Santa" + show_in_antagpanel = FALSE + +/datum/antagonist/santa/on_gain() + . = ..() + give_equipment() + give_objective() + +/datum/antagonist/santa/greet() + . = ..() + to_chat(owner, "You are Santa! Your objective is to bring joy to the people on this station. You can conjure more presents using a spell, and there are several presents in your bag.") + +/datum/antagonist/santa/proc/give_equipment() + var/mob/living/carbon/human/H = owner.current + if(istype(H)) + H.equipOutfit(/datum/outfit/santa) + + owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/presents) + var/obj/effect/proc_holder/spell/targeted/area_teleport/teleport/telespell = new + telespell.clothes_req = 0 //santa robes aren't actually magical. + owner.AddSpell(telespell) //does the station have chimneys? WHO KNOWS! + +/datum/antagonist/santa/proc/give_objective() + var/datum/objective/santa_objective = new() + santa_objective.explanation_text = "Bring joy and presents to the station!" + santa_objective.completed = 1 //lets cut our santas some slack. + santa_objective.owner = owner + objectives |= santa_objective \ No newline at end of file diff --git a/code/modules/antagonists/slaughter/slaughter_antag.dm b/code/modules/antagonists/slaughter/slaughter_antag.dm index 54bfc19acf..a018603cf1 100644 --- a/code/modules/antagonists/slaughter/slaughter_antag.dm +++ b/code/modules/antagonists/slaughter/slaughter_antag.dm @@ -26,8 +26,6 @@ new_objective2.explanation_text = "[objective_verb] everyone[summoner ? " else while you're at it":""]." objectives += new_objective2 - owner.objectives |= objectives - /datum/antagonist/slaughter/laughter name = "Laughter demon" objective_verb = "Hug and Tickle" \ No newline at end of file diff --git a/code/modules/antagonists/survivalist/survivalist.dm b/code/modules/antagonists/survivalist/survivalist.dm index 93a2170dab..4e0184b7b6 100644 --- a/code/modules/antagonists/survivalist/survivalist.dm +++ b/code/modules/antagonists/survivalist/survivalist.dm @@ -8,7 +8,6 @@ var/datum/objective/survive/survive = new survive.owner = owner objectives += survive - owner.objectives |= objectives /datum/antagonist/survivalist/on_gain() owner.special_role = "survivalist" diff --git a/code/modules/antagonists/traitor/IAA/internal_affairs.dm b/code/modules/antagonists/traitor/IAA/internal_affairs.dm index f2e6566e8f..b05750305a 100644 --- a/code/modules/antagonists/traitor/IAA/internal_affairs.dm +++ b/code/modules/antagonists/traitor/IAA/internal_affairs.dm @@ -78,15 +78,14 @@ scan_target = null if(owner) if(owner.mind) - if(owner.mind.objectives) - for(var/datum/objective/objective_ in owner.mind.objectives) - if(!is_internal_objective(objective_)) - continue - var/datum/objective/assassinate/internal/objective = objective_ - var/mob/current = objective.target.current - if(current&¤t.stat!=DEAD) - scan_target = current - break + for(var/datum/objective/objective_ in owner.mind.get_all_objectives()) + if(!is_internal_objective(objective_)) + continue + var/datum/objective/assassinate/internal/objective = objective_ + var/mob/current = objective.target.current + if(current&¤t.stat!=DEAD) + scan_target = current + break /datum/status_effect/agent_pinpointer/tick() if(!owner) @@ -100,9 +99,9 @@ return (istype(O, /datum/objective/assassinate/internal)||istype(O, /datum/objective/destroy/internal)) /datum/antagonist/traitor/proc/replace_escape_objective() - if(!owner||!owner.objectives) + if(!owner || !objectives.len) return - for (var/objective_ in owner.objectives) + for (var/objective_ in objectives) if(!(istype(objective_, /datum/objective/escape)||istype(objective_, /datum/objective/survive))) continue remove_objective(objective_) @@ -112,9 +111,9 @@ add_objective(martyr_objective) /datum/antagonist/traitor/proc/reinstate_escape_objective() - if(!owner||!owner.objectives) + if(!owner||!objectives.len) return - for (var/objective_ in owner.objectives) + for (var/objective_ in objectives) if(!istype(objective_, /datum/objective/martyr)) continue remove_objective(objective_) @@ -131,7 +130,7 @@ return to_chat(owner.current, " Target eliminated: [victim.name]") LAZYINITLIST(targets_stolen) - for(var/objective_ in victim.objectives) + for(var/objective_ in victim.get_all_objectives()) if(istype(objective_, /datum/objective/assassinate/internal)) var/datum/objective/assassinate/internal/objective = objective_ if(objective.target==owner) @@ -159,7 +158,7 @@ var/status_text = objective.check_completion() ? "neutralised" : "active" to_chat(owner.current, " New target added to database: [objective.target.name] ([status_text]) ") last_man_standing = TRUE - for(var/objective_ in owner.objectives) + for(var/objective_ in objectives) if(!is_internal_objective(objective_)) continue var/datum/objective/assassinate/internal/objective = objective_ @@ -175,7 +174,7 @@ /datum/antagonist/traitor/internal_affairs/proc/iaa_process() if(owner&&owner.current&&owner.current.stat!=DEAD) - for(var/objective_ in owner.objectives) + for(var/objective_ in objectives) if(!is_internal_objective(objective_)) continue var/datum/objective/assassinate/internal/objective = objective_ diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index e43c2f6254..5dfc08b6cf 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -55,12 +55,10 @@ owner.special_role = null ..() -/datum/antagonist/traitor/proc/add_objective(var/datum/objective/O) - owner.objectives += O +/datum/antagonist/traitor/proc/add_objective(datum/objective/O) objectives += O -/datum/antagonist/traitor/proc/remove_objective(var/datum/objective/O) - owner.objectives -= O +/datum/antagonist/traitor/proc/remove_objective(datum/objective/O) objectives -= O /datum/antagonist/traitor/proc/forge_traitor_objectives() @@ -89,7 +87,7 @@ forge_single_objective() if(is_hijacker && objective_count <= toa) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount - if (!(locate(/datum/objective/hijack) in owner.objectives)) + if (!(locate(/datum/objective/hijack) in objectives)) var/datum/objective/hijack/hijack_objective = new hijack_objective.owner = owner add_objective(hijack_objective) @@ -97,7 +95,7 @@ var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead. - for(var/datum/objective/O in owner.objectives) + for(var/datum/objective/O in objectives) if(!O.martyr_compatible) martyr_compatibility = 0 break @@ -109,7 +107,7 @@ return else - if(!(locate(/datum/objective/escape) in owner.objectives)) + if(!(locate(/datum/objective/escape) in objectives)) var/datum/objective/escape/escape_objective = new escape_objective.owner = owner add_objective(escape_objective) @@ -159,7 +157,7 @@ kill_objective.find_target() add_objective(kill_objective) else - if(prob(15) && !(locate(/datum/objective/download) in owner.objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist"))) + 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() diff --git a/code/modules/antagonists/valentines/heartbreaker.dm b/code/modules/antagonists/valentines/heartbreaker.dm index 4f228910d7..b78e8d574f 100644 --- a/code/modules/antagonists/valentines/heartbreaker.dm +++ b/code/modules/antagonists/valentines/heartbreaker.dm @@ -9,7 +9,6 @@ var/datum/objective/martyr/normiesgetout = new normiesgetout.owner = owner objectives += normiesgetout - owner.objectives += objectives /datum/antagonist/heartbreaker/on_gain() forge_objectives() diff --git a/code/modules/antagonists/valentines/valentine.dm b/code/modules/antagonists/valentines/valentine.dm index 21e54374a4..19c08f3076 100644 --- a/code/modules/antagonists/valentines/valentine.dm +++ b/code/modules/antagonists/valentines/valentine.dm @@ -12,7 +12,6 @@ protect_objective.human_check = FALSE protect_objective.explanation_text = "Protect [date.name], your date." objectives += protect_objective - owner.objectives += objectives /datum/antagonist/valentine/on_gain() forge_objectives() @@ -34,8 +33,8 @@ //Squashed up a bit /datum/antagonist/valentine/roundend_report() var/objectives_complete = TRUE - if(owner.objectives.len) - for(var/datum/objective/objective in owner.objectives) + if(objectives.len) + for(var/datum/objective/objective in objectives) if(!objective.check_completion()) objectives_complete = FALSE break @@ -51,8 +50,8 @@ /datum/antagonist/valentine/chem/roundend_report() var/objectives_complete = TRUE - if(owner.objectives.len) - for(var/datum/objective/objective in owner.objectives) + if(objectives.len) + for(var/datum/objective/objective in objectives) if(!objective.check_completion()) objectives_complete = FALSE break diff --git a/code/modules/antagonists/wishgranter/wishgranter.dm b/code/modules/antagonists/wishgranter/wishgranter.dm index 318de51eb4..21cab26d1e 100644 --- a/code/modules/antagonists/wishgranter/wishgranter.dm +++ b/code/modules/antagonists/wishgranter/wishgranter.dm @@ -8,7 +8,6 @@ var/datum/objective/hijack/hijack = new hijack.owner = owner objectives += hijack - owner.objectives |= objectives /datum/antagonist/wishgranter/on_gain() owner.special_role = "Avatar of the Wish Granter" diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm index 8a20a81555..89324f0691 100644 --- a/code/modules/antagonists/wizard/wizard.dm +++ b/code/modules/antagonists/wizard/wizard.dm @@ -57,19 +57,19 @@ if(!GLOB.wizardstart.len) SSjob.SendToLateJoin(owner.current) to_chat(owner, "HOT INSERTION, GO GO GO") - owner.current.forceMove(pick(GLOB.wizardstart)) + else + 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.completed = TRUE //So they can greentext without admin intervention. new_objective.owner = owner objectives += new_objective - var/datum/objective/escape/escape_objective = new - escape_objective.owner = owner - objectives += escape_objective - - for(var/datum/objective/O in objectives) - owner.objectives += O + if (!(locate(/datum/objective/escape) in objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = owner + objectives += escape_objective /datum/antagonist/wizard/on_removal() unregister() @@ -183,7 +183,6 @@ new_objective.owner = owner new_objective.target = master new_objective.explanation_text = "Protect [master.current.real_name], the wizard." - owner.objectives += new_objective objectives += new_objective //Random event wizard @@ -251,7 +250,6 @@ /datum/antagonist/wizard/academy/create_objectives() var/datum/objective/new_objective = new("Protect Wizard Academy from the intruders") new_objective.owner = owner - owner.objectives += new_objective objectives += new_objective //Solo wizard report diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index 2631491350..a0927a2578 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -17,6 +17,7 @@ var/faction = null var/permanent = FALSE //If true, the spawner will not disappear upon running out of uses. var/random = FALSE //Don't set a name or gender, just go random + var/antagonist_type var/objectives = null var/uses = 1 //how many times can we spawn from it. set to -1 for infinite. var/brute_damage = 0 @@ -111,9 +112,16 @@ if(show_flavour) to_chat(M, "[flavour_text]") var/datum/mind/MM = M.mind + var/datum/antagonist/A + if(antagonist_type) + A = MM.add_antag_datum(antagonist_type) if(objectives) + if(!A) + A = MM.add_antag_datum(/datum/antagonist/custom) for(var/objective in objectives) - MM.objectives += new/datum/objective(objective) + var/datum/objective/O = new/datum/objective(objective) + O.owner = MM + A.objectives += O if(assignedrole) M.mind.assigned_role = assignedrole special(M, name) diff --git a/code/modules/awaymissions/mission_code/Academy.dm b/code/modules/awaymissions/mission_code/Academy.dm index b7b21bbb9b..77cdf8441b 100644 --- a/code/modules/awaymissions/mission_code/Academy.dm +++ b/code/modules/awaymissions/mission_code/Academy.dm @@ -264,8 +264,9 @@ var/mob/living/carbon/human/H = new(drop_location()) H.equipOutfit(/datum/outfit/butler) var/datum/mind/servant_mind = new /datum/mind() - var/datum/objective/O = new("Serve [user.real_name].") - servant_mind.objectives += O + var/datum/antagonist/magic_servant/A = new + servant_mind.add_antag_datum(A) + A.setup_master(user) servant_mind.transfer_to(H) var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [user.real_name] Servant?", ROLE_WIZARD, null, ROLE_WIZARD, 50, H) diff --git a/code/modules/events/holiday/xmas.dm b/code/modules/events/holiday/xmas.dm index 5f9873c387..65d96ad150 100644 --- a/code/modules/events/holiday/xmas.dm +++ b/code/modules/events/holiday/xmas.dm @@ -79,17 +79,5 @@ santa = new /mob/living/carbon/human(pick(GLOB.blobstart)) C.transfer_ckey(santa, FALSE) - santa.equipOutfit(/datum/outfit/santa) - santa.update_icons() - - var/datum/objective/santa_objective = new() - santa_objective.explanation_text = "Bring joy and presents to the station!" - santa_objective.completed = 1 //lets cut our santas some slack. - santa_objective.owner = santa.mind - santa.mind.objectives += santa_objective - santa.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/presents) - var/obj/effect/proc_holder/spell/targeted/area_teleport/teleport/telespell = new(santa) - telespell.clothes_req = 0 //santa robes aren't actually magical. - santa.mind.AddSpell(telespell) //does the station have chimneys? WHO KNOWS! - - to_chat(santa, "You are Santa! Your objective is to bring joy to the people on this station. You can conjure more presents using a spell, and there are several presents in your bag.") + var/datum/antagonist/santa/A = new + santa.mind.add_antag_datum(A) diff --git a/code/modules/events/wizard/greentext.dm b/code/modules/events/wizard/greentext.dm index 356e83757f..82e72df3b9 100644 --- a/code/modules/events/wizard/greentext.dm +++ b/code/modules/events/wizard/greentext.dm @@ -40,7 +40,8 @@ /obj/item/greentext/equipped(mob/living/user as mob) to_chat(user, "So long as you leave this place with greentext in hand you know will be happy...") - if(user.mind && user.mind.objectives.len > 0) + var/list/other_objectives = user.mind.get_all_objectives() + if(user.mind && other_objectives.len > 0) to_chat(user, "... so long as you still perform your other objectives that is!") new_holder = user if(!last_holder) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index e146f1686a..fde856c4fb 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -1022,21 +1022,10 @@ message_admins("[ADMIN_LOOKUPFLW(L)] has been marked for death by [ADMIN_LOOKUPFLW(user)]!") - var/datum/objective/survive/survive = new - survive.owner = L.mind - L.mind.objectives += survive + var/datum/antagonist/blood_contract/A = new + L.mind.add_antag_datum(A) + log_combat(user, L, "took out a blood contract on", src) - to_chat(L, "You've been marked for death! Don't let the demons get you! KILL THEM ALL!") - L.add_atom_colour("#FF0000", ADMIN_COLOUR_PRIORITY) - var/obj/effect/mine/pickup/bloodbath/B = new(L) - INVOKE_ASYNC(B, /obj/effect/mine/pickup/bloodbath/.proc/mineEffect, L) - - for(var/mob/living/carbon/human/H in GLOB.player_list) - if(H == L) - continue - to_chat(H, "You have an overwhelming desire to kill [L]. [L.p_theyve(TRUE)] been marked red! Whoever [L.p_they()] [L.p_were()], friend or foe, go kill [L.p_them()]!") - H.put_in_hands(new /obj/item/kitchen/knife/butcher(H), TRUE) - qdel(src) //Colossus diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 618baf245f..f790d15d2d 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -864,7 +864,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) replace_identification_name(oldname,newname) for(var/datum/mind/T in SSticker.minds) - for(var/datum/objective/obj in T.objectives) + for(var/datum/objective/obj in T.get_all_objectives()) // Only update if this player is a target if(obj.target && obj.target.current && obj.target.current.real_name == name) obj.update_explanation_text() diff --git a/tgstation.dme b/tgstation.dme index 0ab92d863d..06ec977f1c 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -1204,6 +1204,7 @@ #include "code\modules\antagonists\blob\blob\blobs\node.dm" #include "code\modules\antagonists\blob\blob\blobs\resource.dm" #include "code\modules\antagonists\blob\blob\blobs\shield.dm" +#include "code\modules\antagonists\blood_contract\blood_contract.dm" #include "code\modules\antagonists\brainwashing\brainwashing.dm" #include "code\modules\antagonists\brother\brother.dm" #include "code\modules\antagonists\changeling\cellular_emporium.dm" @@ -1314,6 +1315,7 @@ #include "code\modules\antagonists\greentext\greentext.dm" #include "code\modules\antagonists\greybois\greybois.dm" #include "code\modules\antagonists\highlander\highlander.dm" +#include "code\modules\antagonists\magic_servant\magic_servant.dm" #include "code\modules\antagonists\monkey\monkey.dm" #include "code\modules\antagonists\morph\morph.dm" #include "code\modules\antagonists\morph\morph_antag.dm" @@ -1335,6 +1337,7 @@ #include "code\modules\antagonists\revenant\revenant_blight.dm" #include "code\modules\antagonists\revenant\revenant_spawn_event.dm" #include "code\modules\antagonists\revolution\revolution.dm" +#include "code\modules\antagonists\santa\santa.dm" #include "code\modules\antagonists\separatist\separatist.dm" #include "code\modules\antagonists\slaughter\slaughter.dm" #include "code\modules\antagonists\slaughter\slaughter_antag.dm"