diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 29413b6ae00..c8984671fce 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -589,16 +589,14 @@ GLOBAL_LIST_EMPTY(possible_items) if(!dupe_search_range) dupe_search_range = get_owners() var/approved_targets = list() - check_items: - for(var/datum/objective_item/possible_item in GLOB.possible_items) - if(possible_item.objective_type != OBJECTIVE_ITEM_TYPE_NORMAL) - continue - if(!is_unique_objective(possible_item.targetitem,dupe_search_range)) - continue - for(var/datum/mind/M in owners) - if(M.current.mind.assigned_role.title in possible_item.excludefromjob) - continue check_items - approved_targets += possible_item + for(var/datum/objective_item/possible_item in GLOB.possible_items) + if(!possible_item.valid_objective_for(owners, require_owner = FALSE)) + continue + if(possible_item.objective_type != OBJECTIVE_ITEM_TYPE_NORMAL) + continue + if(!is_unique_objective(possible_item.targetitem,dupe_search_range)) + continue + approved_targets += possible_item if (length(approved_targets)) return set_target(pick(approved_targets)) return set_target(null) @@ -649,7 +647,7 @@ GLOBAL_LIST_EMPTY(possible_items) if(istype(I, steal_target)) if(!targetinfo) //If there's no targetinfo, then that means it was a custom objective. At this point, we know you have the item, so return 1. return TRUE - else if(targetinfo.check_special_completion(I))//Returns 1 by default. Items with special checks will return 1 if the conditions are fulfilled. + else if(targetinfo.check_special_completion(I))//Returns true by default. Items with special checks will return true if the conditions are fulfilled. return TRUE if(targetinfo && (I.type in targetinfo.altitems)) //Ok, so you don't have the item. Do you have an alternative, at least? @@ -657,19 +655,6 @@ GLOBAL_LIST_EMPTY(possible_items) return TRUE return FALSE -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() - ..() - if(!GLOB.possible_items_special.len) - for(var/I in subtypesof(/datum/objective_item/special) + subtypesof(/datum/objective_item/stack)) - new I - -/datum/objective/steal/special/find_target(dupe_search_range, list/blacklist) - return set_target(pick(GLOB.possible_items_special)) - /datum/objective/capture name = "capture" admin_grantable = TRUE diff --git a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm index 897d057eff6..a4b79591737 100644 --- a/code/game/gamemodes/objective_items.dm +++ b/code/game/gamemodes/objective_items.dm @@ -2,26 +2,55 @@ //Contains the target item datums for Steal objectives. /datum/objective_item + /// How the item is described in the objective var/name = "A silly bike horn! Honk!" + /// Typepath of item var/targetitem = /obj/item/bikehorn - var/list/valid_containers = list() // Valid containers that the target item can be in. - var/difficulty = 9001 //vaguely how hard it is to do this objective - var/list/excludefromjob = list() //If you don't want a job to get a certain objective (no captain stealing his own medal, etcetc) - var/list/altitems = list() //Items which can serve as an alternative to the objective (darn you blueprints) + /// Valid containers that the target item can be in. + var/list/valid_containers = list() + /// Who CARES if this item goes missing (no stealing unguarded items), often similar but not identical to the next list + var/list/item_owner = list() + /// Jobs which cannot generate this objective (no stealing your own stuff) + var/list/excludefromjob = list() + /// List of additional items which also count, for things like blueprints + var/list/altitems = list() + /// Items to provide to people in order to allow them to acquire the target var/list/special_equipment = list() + /// Defines in which contexts the item can be given as an objective var/objective_type = OBJECTIVE_ITEM_TYPE_NORMAL /// Whether this item exists on the station map at the start of a round. var/exists_on_map = FALSE -/datum/objective_item/proc/check_special_completion() //for objectives with special checks (is that slime extract unused? does that intellicard have an ai in it? etcetc) - return 1 - -/datum/objective_item/proc/TargetExists() +/// For objectives with special checks (does that intellicard have an ai in it? etcetc) +/datum/objective_item/proc/check_special_completion() return TRUE +/// Takes a list of minds and returns true if this is a valid objective to give to a team of these minds +/datum/objective_item/proc/valid_objective_for(list/potential_thieves, require_owner = FALSE) + if(!target_exists() || (require_owner && !owner_exists())) + return FALSE + for (var/datum/mind/possible_thief as anything in potential_thieves) + var/datum/job/role = possible_thief.assigned_role + if(role.title in excludefromjob) + return FALSE + return TRUE + +/// Returns true if the target item exists +/datum/objective_item/proc/target_exists() + return (exists_on_map) ? length(GLOB.steal_item_handler.objectives_by_path[targetitem]) : TRUE + +/// Returns true if one of the item's owners exists somewhere +/datum/objective_item/proc/owner_exists() + if (!length(item_owner)) + return TRUE + for (var/mob/living/player as anything in GLOB.player_list) + if ((player.mind?.assigned_role.title in item_owner) && player.stat != DEAD && !is_centcom_level(player.z)) + return TRUE + return FALSE + /datum/objective_item/steal/New() - ..() - if(TargetExists()) + . = ..() + if(target_exists()) GLOB.possible_items += src else qdel(src) @@ -34,47 +63,56 @@ /datum/objective_item/steal/low_risk objective_type = OBJECTIVE_ITEM_TYPE_TRAITOR -/datum/objective_item/steal/low_risk/aicard - targetitem = /obj/item/aicard - name = "an intelliCard" - excludefromjob = list( - JOB_CAPTAIN, - JOB_CHIEF_ENGINEER, - JOB_RESEARCH_DIRECTOR, - JOB_CHIEF_MEDICAL_OFFICER, - JOB_HEAD_OF_SECURITY, - JOB_STATION_ENGINEER, - JOB_SCIENTIST, - JOB_ATMOSPHERIC_TECHNICIAN, - ) - exists_on_map = TRUE - -/obj/item/aicard/add_stealing_item_objective() - ADD_STEAL_ITEM(src, /obj/item/aicard) - // Unique-ish low risk objectives /datum/objective_item/steal/low_risk/bartender_shotgun name = "the bartender's shotgun" targetitem = /obj/item/gun/ballistic/shotgun/doublebarrel excludefromjob = list(JOB_BARTENDER) + item_owner = list(JOB_BARTENDER) exists_on_map = TRUE /obj/item/gun/ballistic/shotgun/doublebarrel/add_stealing_item_objective() ADD_STEAL_ITEM(src, /obj/item/gun/ballistic/shotgun/doublebarrel) +// No item owner, list would be so long as to be functionally useless and they're in two very disparate locations on most maps /datum/objective_item/steal/low_risk/fireaxe name = "a fire axe" targetitem = /obj/item/fireaxe - excludefromjob = list(JOB_CHIEF_ENGINEER,JOB_STATION_ENGINEER,JOB_ATMOSPHERIC_TECHNICIAN) + excludefromjob = list( + JOB_ATMOSPHERIC_TECHNICIAN, + JOB_CAPTAIN, + JOB_CHIEF_ENGINEER, + JOB_CHIEF_MEDICAL_OFFICER, + JOB_HEAD_OF_PERSONNEL, + JOB_HEAD_OF_SECURITY, + JOB_QUARTERMASTER, + JOB_RESEARCH_DIRECTOR, + JOB_STATION_ENGINEER, + ) exists_on_map = TRUE /obj/item/fireaxe/add_stealing_item_objective() ADD_STEAL_ITEM(src, /obj/item/fireaxe) +/datum/objective_item/steal/low_risk/big_crowbar + name = "a mech removal tool" + targetitem = /obj/item/crowbar/mechremoval + excludefromjob = list( + JOB_RESEARCH_DIRECTOR, + JOB_SCIENTIST, + JOB_ROBOTICIST, + ) + item_owner = list(JOB_ROBOTICIST) + exists_on_map = TRUE + +/obj/item/crowbar/mechremoval/add_stealing_item_objective() + ADD_STEAL_ITEM(src, /obj/item/crowbar/mechremoval) + /datum/objective_item/steal/low_risk/nullrod name = "the chaplain's null rod" targetitem = /obj/item/nullrod excludefromjob = list(JOB_CHAPLAIN) + item_owner = list(JOB_CHAPLAIN) exists_on_map = TRUE /obj/item/nullrod/add_stealing_item_objective() @@ -84,32 +122,24 @@ name = "the clown's shoes" targetitem = /obj/item/clothing/shoes/clown_shoes excludefromjob = list(JOB_CLOWN, JOB_CARGO_TECHNICIAN, JOB_QUARTERMASTER) - -/datum/objective_item/steal/low_risk/clown_shoes/TargetExists() - for(var/mob/player as anything in GLOB.player_list) - if(player.stat == DEAD) - continue - if(player.job != JOB_CLOWN) - continue - if(is_centcom_level(player.z)) - continue - return TRUE - return FALSE + item_owner = list(JOB_CLOWN) /datum/objective_item/steal/low_risk/cargo_budget name = "cargo's departmental budget" targetitem = /obj/item/card/id/departmental_budget/car excludefromjob = list(JOB_QUARTERMASTER, JOB_CARGO_TECHNICIAN) + item_owner = list(JOB_QUARTERMASTER) exists_on_map = TRUE /obj/item/card/id/departmental_budget/car/add_stealing_item_objective() ADD_STEAL_ITEM(src, /obj/item/card/id/departmental_budget/car) // High risk steal objectives + +// Will always generate even with no Captain due to its security and temptation to use it /datum/objective_item/steal/caplaser name = "the captain's antique laser gun" targetitem = /obj/item/gun/energy/laser/captain - difficulty = 5 excludefromjob = list(JOB_CAPTAIN) exists_on_map = TRUE @@ -119,8 +149,8 @@ /datum/objective_item/steal/hoslaser name = "the head of security's personal laser gun" targetitem = /obj/item/gun/energy/e_gun/hos - difficulty = 10 excludefromjob = list(JOB_HEAD_OF_SECURITY) + item_owner = list(JOB_HEAD_OF_SECURITY) exists_on_map = TRUE /obj/item/gun/energy/e_gun/hos/add_stealing_item_objective() @@ -129,8 +159,8 @@ /datum/objective_item/steal/handtele name = "a hand teleporter" targetitem = /obj/item/hand_tele - difficulty = 5 excludefromjob = list(JOB_CAPTAIN, JOB_RESEARCH_DIRECTOR, JOB_HEAD_OF_PERSONNEL) + item_owner = list(JOB_CAPTAIN, JOB_RESEARCH_DIRECTOR) exists_on_map = TRUE /obj/item/hand_tele/add_stealing_item_objective() @@ -139,8 +169,8 @@ /datum/objective_item/steal/jetpack name = "the Captain's jetpack" targetitem = /obj/item/tank/jetpack/oxygen/captain - difficulty = 5 excludefromjob = list(JOB_CAPTAIN) + item_owner = list(JOB_CAPTAIN) exists_on_map = TRUE /obj/item/tank/jetpack/oxygen/captain/add_stealing_item_objective() @@ -149,8 +179,8 @@ /datum/objective_item/steal/magboots name = "the chief engineer's advanced magnetic boots" targetitem = /obj/item/clothing/shoes/magboots/advance - difficulty = 5 excludefromjob = list(JOB_CHIEF_ENGINEER) + item_owner = list(JOB_CHIEF_ENGINEER) exists_on_map = TRUE /obj/item/clothing/shoes/magboots/advance/add_stealing_item_objective() @@ -159,8 +189,8 @@ /datum/objective_item/steal/capmedal name = "the medal of captaincy" targetitem = /obj/item/clothing/accessory/medal/gold/captain - difficulty = 5 excludefromjob = list(JOB_CAPTAIN) + item_owner = list(JOB_CAPTAIN) exists_on_map = TRUE /obj/item/clothing/accessory/medal/gold/captain/add_stealing_item_objective() @@ -169,8 +199,8 @@ /datum/objective_item/steal/hypo name = "the hypospray" targetitem = /obj/item/reagent_containers/hypospray/cmo - difficulty = 5 excludefromjob = list(JOB_CHIEF_MEDICAL_OFFICER) + item_owner = list(JOB_CHIEF_MEDICAL_OFFICER) exists_on_map = TRUE /obj/item/reagent_containers/hypospray/cmo/add_stealing_item_objective() @@ -179,7 +209,6 @@ /datum/objective_item/steal/nukedisc name = "the nuclear authentication disk" targetitem = /obj/item/disk/nuclear - difficulty = 5 excludefromjob = list(JOB_CAPTAIN) /datum/objective_item/steal/nukedisc/check_special_completion(obj/item/disk/nuclear/N) @@ -188,8 +217,8 @@ /datum/objective_item/steal/reflector name = "a reflector trenchcoat" targetitem = /obj/item/clothing/suit/hooded/ablative - difficulty = 3 excludefromjob = list(JOB_HEAD_OF_SECURITY, JOB_WARDEN) + item_owner = list(JOB_HEAD_OF_SECURITY) exists_on_map = TRUE /obj/item/clothing/suit/hooded/ablative/add_stealing_item_objective() @@ -198,8 +227,8 @@ /datum/objective_item/steal/reactive name = "the reactive teleport armor" targetitem = /obj/item/clothing/suit/armor/reactive/teleport - difficulty = 5 excludefromjob = list(JOB_RESEARCH_DIRECTOR) + item_owner = list(JOB_RESEARCH_DIRECTOR) exists_on_map = TRUE /obj/item/clothing/suit/armor/reactive/teleport/add_stealing_item_objective() @@ -208,7 +237,6 @@ /datum/objective_item/steal/documents name = "any set of secret documents of any organization" targetitem = /obj/item/documents - difficulty = 5 exists_on_map = TRUE /obj/item/documents/add_stealing_item_objective() @@ -218,7 +246,6 @@ name = "the heavily radioactive plutonium core from the onboard self-destruct" valid_containers = list(/obj/item/nuke_core_container) targetitem = /obj/item/nuke_core - difficulty = 15 exists_on_map = TRUE /obj/item/nuke_core/add_stealing_item_objective() @@ -231,8 +258,8 @@ /datum/objective_item/steal/hdd_extraction name = "the source code for Project Goon from the master R&D server mainframe" targetitem = /obj/item/computer_disk/hdd_theft - difficulty = 10 excludefromjob = list(JOB_RESEARCH_DIRECTOR, JOB_SCIENTIST, JOB_ROBOTICIST, JOB_GENETICIST) + item_owner = list(JOB_RESEARCH_DIRECTOR, JOB_SCIENTIST) exists_on_map = TRUE /obj/item/computer_disk/hdd_theft/add_stealing_item_objective() @@ -247,37 +274,18 @@ name = "a sliver of a supermatter crystal" targetitem = /obj/item/nuke_core/supermatter_sliver valid_containers = list(/obj/item/nuke_core_container/supermatter) - difficulty = 15 /datum/objective_item/steal/supermatter/New() special_equipment += /obj/item/storage/box/syndie_kit/supermatter ..() -/datum/objective_item/steal/supermatter/TargetExists() +/datum/objective_item/steal/supermatter/target_exists() return GLOB.main_supermatter_engine != null -//Items with special checks! -/datum/objective_item/steal/plasma - name = "28 moles of plasma (full tank)" - targetitem = /obj/item/tank - difficulty = 3 - excludefromjob = list( - JOB_CHIEF_ENGINEER, JOB_STATION_ENGINEER, JOB_ATMOSPHERIC_TECHNICIAN, - JOB_RESEARCH_DIRECTOR, JOB_SCIENTIST, JOB_ROBOTICIST, - ) - -/datum/objective_item/steal/plasma/check_special_completion(obj/item/tank/T) - var/target_amount = text2num(name) - var/found_amount = 0 - var/datum/gas_mixture/mix = T.return_air() - found_amount += mix.gases[/datum/gas/plasma] ? mix.gases[/datum/gas/plasma][MOLES] : 0 - return found_amount >= target_amount - - +// Doesn't need item_owner = (JOB_AI) because this handily functions as a murder objective if there isn't one /datum/objective_item/steal/functionalai name = "a functional AI" targetitem = /obj/item/aicard - difficulty = 20 //beyond the impossible /datum/objective_item/steal/functionalai/New() . = ..() @@ -304,8 +312,8 @@ /datum/objective_item/steal/blueprints name = "the station blueprints" targetitem = /obj/item/areaeditor/blueprints - difficulty = 10 excludefromjob = list(JOB_CHIEF_ENGINEER) + item_owner = list(JOB_CHIEF_ENGINEER) altitems = list(/obj/item/photo) exists_on_map = TRUE @@ -321,118 +329,13 @@ return TRUE return FALSE -/datum/objective_item/steal/slime - name = "an unused sample of slime extract" - targetitem = /obj/item/slime_extract - difficulty = 3 - excludefromjob = list(JOB_RESEARCH_DIRECTOR, JOB_SCIENTIST) - -/datum/objective_item/steal/slime/check_special_completion(obj/item/slime_extract/E) - if(E.Uses > 0) - return 1 - return 0 - /datum/objective_item/steal/blackbox name = "the Blackbox" targetitem = /obj/item/blackbox - difficulty = 10 excludefromjob = list(JOB_CHIEF_ENGINEER, JOB_STATION_ENGINEER, JOB_ATMOSPHERIC_TECHNICIAN) exists_on_map = TRUE /obj/item/blackbox/add_stealing_item_objective() ADD_STEAL_ITEM(src, /obj/item/blackbox) -//Unique Objectives -/datum/objective_item/special/New() - ..() - if(TargetExists()) - GLOB.possible_items_special += src - else - qdel(src) - -/datum/objective_item/special/Destroy() - GLOB.possible_items_special -= src - return ..() - -//Old ninja objectives. -/datum/objective_item/special/pinpointer - name = "the captain's pinpointer" - targetitem = /obj/item/pinpointer/nuke - difficulty = 10 - exists_on_map = TRUE - -/obj/item/pinpointer/nuke/add_stealing_item_objective() - ADD_STEAL_ITEM(src, /obj/item/pinpointer/nuke) - -/datum/objective_item/special/aegun - name = "an advanced energy gun" - targetitem = /obj/item/gun/energy/e_gun/nuclear - difficulty = 10 - -/datum/objective_item/special/ddrill - name = "a diamond drill" - targetitem = /obj/item/pickaxe/drill/diamonddrill - difficulty = 10 - -/datum/objective_item/special/boh - name = "a bag of holding" - targetitem = /obj/item/storage/backpack/holding - difficulty = 10 - -/datum/objective_item/special/hypercell - name = "a hyper-capacity power cell" - targetitem = /obj/item/stock_parts/cell/hyper - difficulty = 5 - -/datum/objective_item/special/laserpointer - name = "a laser pointer" - targetitem = /obj/item/laser_pointer - difficulty = 5 - -/datum/objective_item/special/corgimeat - name = "a piece of corgi meat" - targetitem = /obj/item/food/meat/slab/corgi - difficulty = 5 - -/datum/objective_item/stack/New() - ..() - if(TargetExists()) - GLOB.possible_items_special += src - else - qdel(src) - -/datum/objective_item/stack/Destroy() - GLOB.possible_items_special -= src - return ..() - -//Stack objectives get their own subtype -/datum/objective_item/stack - name = "5 cardboard" - targetitem = /obj/item/stack/sheet/cardboard - difficulty = 9001 - - -/datum/objective_item/stack/check_special_completion(obj/item/stack/S) - var/target_amount = text2num(name) - var/found_amount = 0 - - if(istype(S, targetitem)) - found_amount = S.amount - return found_amount >= target_amount - -/datum/objective_item/stack/diamond - name = "10 diamonds" - targetitem = /obj/item/stack/sheet/mineral/diamond - difficulty = 10 - -/datum/objective_item/stack/gold - name = "50 gold bars" - targetitem = /obj/item/stack/sheet/mineral/gold - difficulty = 15 - -/datum/objective_item/stack/uranium - name = "25 refined uranium bars" - targetitem = /obj/item/stack/sheet/mineral/uranium - difficulty = 10 - #undef ADD_STEAL_ITEM diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 74b353db012..ced0306e3e8 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -288,7 +288,6 @@ /obj/structure/closet/crate/goldcrate/populate_contents_immediate() . = ..() - // /datum/objective_item/stack/gold for(var/i in 1 to 3) new /obj/item/stack/sheet/mineral/gold(src, 1, FALSE) diff --git a/code/modules/antagonists/traitor/objectives/destroy_item.dm b/code/modules/antagonists/traitor/objectives/destroy_item.dm index f0831461d6e..14ce84f72a3 100644 --- a/code/modules/antagonists/traitor/objectives/destroy_item.dm +++ b/code/modules/antagonists/traitor/objectives/destroy_item.dm @@ -25,6 +25,7 @@ possible_items = list( /datum/objective_item/steal/low_risk/bartender_shotgun, /datum/objective_item/steal/low_risk/fireaxe, + /datum/objective_item/steal/low_risk/big_crowbar, /datum/objective_item/steal/low_risk/nullrod, ) @@ -38,22 +39,14 @@ ) /datum/traitor_objective/destroy_item/generate_objective(datum/mind/generating_for, list/possible_duplicates) - var/datum/job/role = generating_for.assigned_role for(var/datum/traitor_objective/destroy_item/objective as anything in possible_duplicates) possible_items -= objective.target_item.type while(length(possible_items)) var/datum/objective_item/steal/target = pick_n_take(possible_items) target = new target() - if(!target.TargetExists()) + if(!target.valid_objective_for(list(generating_for), require_owner = TRUE)) qdel(target) continue - if(role.title in target.excludefromjob) - qdel(target) - continue - if(target.exists_on_map) - var/list/items = GLOB.steal_item_handler.objectives_by_path[target.targetitem] - if(!length(items)) - continue target_item = target break if(!target_item) diff --git a/code/modules/antagonists/traitor/objectives/steal.dm b/code/modules/antagonists/traitor/objectives/steal.dm index c2fdbb461d7..ed3f7a090fc 100644 --- a/code/modules/antagonists/traitor/objectives/steal.dm +++ b/code/modules/antagonists/traitor/objectives/steal.dm @@ -2,12 +2,8 @@ name = "Steal Item" objectives = list( list( - list( - /datum/traitor_objective/steal_item/low_risk = 1, - /datum/traitor_objective/destroy_item/low_risk = 1, - ) = 1, - /datum/traitor_objective/steal_item/low_risk_cap = 1, - + /datum/traitor_objective/steal_item/low_risk = 1, + /datum/traitor_objective/destroy_item/low_risk = 1, ) = 1, /datum/traitor_objective/steal_item/somewhat_risky = 1, list( @@ -77,17 +73,6 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new()) abstract_type = /datum/traitor_objective/steal_item -/datum/traitor_objective/steal_item/low_risk_cap - progression_minimum = 5 MINUTES - progression_maximum = 20 MINUTES - - progression_reward = list(5 MINUTES, 10 MINUTES) - telecrystal_reward = 0 - minutes_per_telecrystal = 6 - possible_items = list( - /datum/objective_item/steal/low_risk/aicard, - ) - /datum/traitor_objective/steal_item/low_risk progression_minimum = 10 MINUTES progression_maximum = 35 MINUTES @@ -152,22 +137,14 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new()) return ..() /datum/traitor_objective/steal_item/generate_objective(datum/mind/generating_for, list/possible_duplicates) - var/datum/job/role = generating_for.assigned_role for(var/datum/traitor_objective/steal_item/objective as anything in possible_duplicates) possible_items -= objective.target_item.type while(length(possible_items)) var/datum/objective_item/steal/target = pick_n_take(possible_items) target = new target() - if(!target.TargetExists()) + if(!target.valid_objective_for(list(generating_for), require_owner = TRUE)) qdel(target) continue - if(role.title in target.excludefromjob) - qdel(target) - continue - if(target.exists_on_map) - var/list/items = GLOB.steal_item_handler.objectives_by_path[target.targetitem] - if(!length(items)) - continue target_item = target break if(!target_item)