Limit theft/destroy secondary objectives to items which at least one person cares about (#73731)

## About The Pull Request

This PR adds a new field `item_owner` to `datum/objective_item` and
populates it for most objective items.
The function of this field is that the objective will fail to generate
if there isn't at least one player in the game with one of those roles.
This limits theft objectives to targets which are likely to be carried
around, missed if they become absent, or at least vaguely have someone
standing close to.
This has only been applied toprogression traitor secondary objectives. 

While doing this I also culled a number of deprecated or tedious
objectives which we didn't use any more, such as every "steal a stack of
x" objective. And the plasma tank one. And the slime core one.
I also deleted any which nobody would miss, chiefly "an empty AI card".
There's plenty of those things and if one vanished nobody would notice
let alone be inconvenienced.
If anyone ever wants to bring them back for soul reasons it will be
retained in the commit history, that's what git is for.

The list is actually not particularly long now, so if people have good
ideas for more things to add to expand it again... well they could have
done that any time in the past 10 years but they can still do it now as
long as it isn't to fill it back up with things nobody will miss if they
are gone.
For myself, I added the robotics lab mech crowbar to the list as it
fulfils most of the criteria of "fire axe" but with the benefit of there
only being one on most maps.

I also removed the `difficulty` var which was undocumented, not set for
most objectives (all "low risk" objectives had a default difficulty of
`9001`), and unused.

Also I think this is my 100th PR so you have to be nice to me.

## Why It's Good For The Game

Traitor objectives (and antagonist objectives in general) should:
- Present you with a somewhat engaging task
- Encourage you to interact with at least one other player (at least by
"attempting to sneak past them")
- Move the state of the round forward in some way, usually by creating
inconvenience for at least one other person

Many current progression traitor objectives do not meet all (and some
perhaps not even any) of the above criteria and I am planning on making
a series of changes in order to address this. Expect to see this
paragraph copied/pasted into some other PRs probably.

This one is the simplest: Stealing an item from someone who literally
isn't in the game does not antagonise anyone. So we won't ask anyone to
do it.

## Changelog

🆑
balance: Traitor secondary objectives to steal or destroy an item are
now associated with a particular "owner" or "victim" and won't generate
themselves if nobody would actually be victimised by the crime.
add: Traitors can sometimes be tasked with stealing and destroying the
roboticist's big crowbar, if there is one
/🆑
This commit is contained in:
Jacquerel
2023-03-07 23:29:16 +00:00
committed by GitHub
parent b3523f211d
commit 4aef8a4cd5
5 changed files with 97 additions and 240 deletions
+9 -24
View File
@@ -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
+83 -180
View File
@@ -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
@@ -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)
@@ -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)
@@ -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)