diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 6eb6d523cdc..868cb3b3da4 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -706,12 +706,6 @@
return
switch(new_obj_type)
- if("download")
- new_objective = new /datum/objective/download
- new_objective.explanation_text = "Download [target_number] research levels."
- if("capture")
- new_objective = new /datum/objective/capture
- new_objective.explanation_text = "Accumulate [target_number] capture points."
if("absorb")
new_objective = new /datum/objective/absorb
new_objective.explanation_text = "Absorb [target_number] compatible genomes."
diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm
index aa498e817f7..04f9738745d 100644
--- a/code/game/gamemodes/miniantags/abduction/abduction.dm
+++ b/code/game/gamemodes/miniantags/abduction/abduction.dm
@@ -50,7 +50,7 @@
team_names[team_number] = "Mothership [pick(GLOB.possible_changeling_IDs)]" //TODO Ensure unique and actual alieny names
//Team Objective
var/datum/objective/experiment/team_objective = new
- team_objective.team = team_number
+ team_objective.abductor_team = team_number
team_objectives[team_number] = team_objective
//Team Members
@@ -238,7 +238,7 @@
// OBJECTIVES
/datum/objective/experiment
target_amount = 6
- var/team
+ var/abductor_team
/datum/objective/stay_hidden
@@ -251,13 +251,12 @@
explanation_text = "Experiment on [target_amount] humans."
/datum/objective/experiment/check_completion()
- var/ab_team = team
- if(owner)
- if(!owner.current || !ishuman(owner.current))
- return FALSE
- var/mob/living/carbon/human/H = owner.current
- if(!isabductor(H))
+ var/ab_team = abductor_team
+ var/list/owners = get_owners()
+ for(var/datum/mind/M in owners)
+ if(!M.current || !ishuman(M.current) || !isabductor(M.current))
return FALSE
+ var/mob/living/carbon/human/H = M.current
var/datum/species/abductor/S = H.dna.species
ab_team = S.team
for(var/obj/machinery/abductor/experiment/E in GLOB.machines)
diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm
index 1f6ee4b1fd3..e576920c2a2 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant.dm
@@ -322,15 +322,15 @@
..()
/datum/objective/revenant/check_completion()
- if(!owner || !istype(owner.current, /mob/living/simple_animal/revenant))
- return 0
- var/mob/living/simple_animal/revenant/R = owner.current
- if(!R || R.stat == DEAD)
- return 0
- var/essence_stolen = R.essence_accumulated
- if(essence_stolen < targetAmount)
- return 0
- return 1
+ var/total_essence = 0
+ for(var/datum/mind/M in get_owners())
+ if(!istype(M.current, /mob/living/simple_animal/revenant) || QDELETED(M.current))
+ continue
+ var/mob/living/simple_animal/revenant/R = M.current
+ total_essence += R.essence_accumulated
+ if(total_essence >= targetAmount)
+ return FALSE
+ return TRUE
/datum/objective/revenantFluff
diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
index 962d44076bd..795e49ebe1f 100644
--- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm
+++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
@@ -344,15 +344,15 @@
..()
/datum/objective/slaughter/check_completion()
- if(!isslaughterdemon(owner.current) || !owner.current)
- return 0
- var/mob/living/simple_animal/slaughter/R = owner.current
- if(!R || R.stat == DEAD)
- return 0
- var/deathCount = R.devoured
- if(deathCount < targetKill)
- return 0
- return 1
+ var/kill_count = 0
+ for(var/datum/mind/M in get_owners())
+ if(!isslaughterdemon(M.current) || QDELETED(M.current))
+ continue
+ var/mob/living/simple_animal/slaughter/R = M.current
+ kill_count += R.devoured
+ if(kill_count >= targetKill)
+ return TRUE
+ return FALSE
/datum/objective/demonFluff
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index 85a3a4461e6..20d8d8463f9 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -3,14 +3,20 @@ GLOBAL_LIST_EMPTY(all_objectives)
GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective) - /datum/theft_objective/steal - /datum/theft_objective/number - /datum/theft_objective/unique))
/datum/objective
- /// Mind who owns the objective.
- var/datum/mind/owner = null
+ /**
+ * Owner of the objective.
+ * Note that it's fine to set this directly, but when needing to check completion of the objective or otherwise check conditions on the owner of the objective,
+ * always use `get_owners()`, and check against ALL the owners. `get_owners()` accounts for objectives that may be team based and therefore have multiple owners.
+ */
+ var/datum/mind/owner
+ /// The target of the objective.
+ var/datum/mind/target
+ /// The team the objective belongs to, if any.
+ var/datum/team/team
/// What the owner is supposed to do to complete the objective.
var/explanation_text = "Nothing"
/// If the objective should have `find_target()` called for it.
var/needs_target = TRUE
- /// The target of the objective.
- var/datum/mind/target = null
/// If they are focused on a particular number. Steal objectives have their own counter.
var/target_amount = 0
/// If the objective has been completed.
@@ -18,18 +24,33 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
/// If the objective is compatible with martyr objective, i.e. if you can still do it while dead.
var/martyr_compatible = FALSE
-/datum/objective/New(text)
+/datum/objective/New(text, datum/team/team_to_join)
GLOB.all_objectives += src
if(text)
explanation_text = text
+ if(team_to_join)
+ team = team_to_join
/datum/objective/Destroy()
GLOB.all_objectives -= src
+ owner = null
+ target = null
+ team = null
return ..()
/datum/objective/proc/check_completion()
return completed
+/**
+ * Get all owners of the objective, including ones from the objective's team, if it has one.
+ *
+ * Use this over directly referencing `owner` in most cases.
+ */
+/datum/objective/proc/get_owners()
+ . = length(team?.members) ? team.members.Copy() : list()
+ if(owner)
+ . += owner
+
/datum/proc/is_invalid_target(datum/mind/possible_target) // Originally an Objective proc. Changed to a datum proc to allow for the proc to be run on minds, before the objective is created
if(!ishuman(possible_target.current))
return TARGET_INVALID_NOT_HUMAN
@@ -47,10 +68,11 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
return TARGET_INVALID_EVENT
/datum/objective/is_invalid_target(datum/mind/possible_target)
- if(possible_target == owner)
- return TARGET_INVALID_IS_OWNER
- if(possible_target in owner.targets)
- return TARGET_INVALID_IS_TARGET
+ for(var/datum/mind/M in get_owners())
+ if(possible_target == M)
+ return TARGET_INVALID_IS_OWNER
+ if(possible_target in M.targets)
+ return TARGET_INVALID_IS_TARGET
return ..()
@@ -72,22 +94,25 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
* Called when the objective's target goes to cryo.
*/
/datum/objective/proc/on_target_cryo()
- if(owner?.current)
- to_chat(owner.current, "
You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!")
- SEND_SOUND(owner.current, sound('sound/ambience/alarm4.ogg'))
+ var/list/owners = get_owners()
+ for(var/datum/mind/M in owners)
+ to_chat(M.current, "
You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!")
+ SEND_SOUND(M.current, sound('sound/ambience/alarm4.ogg'))
target = null
- INVOKE_ASYNC(src, PROC_REF(post_target_cryo))
+ INVOKE_ASYNC(src, PROC_REF(post_target_cryo), owners)
/**
* Called a tick after when the objective's target goes to cryo.
*/
-/datum/objective/proc/post_target_cryo()
+/datum/objective/proc/post_target_cryo(list/owners)
find_target()
if(!target)
+ for(var/datum/mind/M in owners)
+ M.remove_objective(src)
GLOB.all_objectives -= src
- owner?.objectives -= src
qdel(src)
- owner?.announce_objectives()
+ for(var/datum/mind/M in owners)
+ M.announce_objectives()
/datum/objective/assassinate
martyr_compatible = 1
@@ -103,13 +128,13 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
/datum/objective/assassinate/check_completion()
if(target && target.current)
if(target.current.stat == DEAD)
- return 1
+ return TRUE
if(issilicon(target.current) || isbrain(target.current)) //Borgs/brains/AIs count as dead for traitor objectives. --NeoFite
- return 1
+ return TRUE
if(!target.current.ckey)
- return 1
- return 0
- return 1
+ return TRUE
+ return FALSE
+ return TRUE
/datum/objective/mutiny
@@ -126,12 +151,12 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
/datum/objective/mutiny/check_completion()
if(target && target.current)
if(target.current.stat == DEAD || !ishuman(target.current) || !target.current.ckey || !target.current.client)
- return 1
+ return TRUE
var/turf/T = get_turf(target.current)
if(T && !is_station_level(T.z)) //If they leave the station they count as dead for this
- return 1
- return 0
- return 1
+ return TRUE
+ return FALSE
+ return TRUE
/datum/objective/mutiny/on_target_cryo()
// We don't want revs to get objectives that aren't for heads of staff. Letting
@@ -152,18 +177,18 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
/datum/objective/maroon/check_completion()
if(target && target.current)
if(target.current.stat == DEAD)
- return 1
+ return TRUE
if(!target.current.ckey)
- return 1
+ return TRUE
if(issilicon(target.current))
- return 1
+ return TRUE
if(isbrain(target.current))
- return 1
+ return TRUE
var/turf/T = get_turf(target.current)
if(is_admin_level(T.z))
- return 0
- return 1
- return 1
+ return FALSE
+ return TRUE
+ return TRUE
/datum/objective/debrain //I want braaaainssss
@@ -179,18 +204,16 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
/datum/objective/debrain/check_completion()
- if(!target)//If it's a free objective.
- return 1
- if(!owner.current || owner.current.stat == DEAD)
- return 0
+ if(!target) // If it's a free objective.
+ return TRUE
if(!target.current || !isbrain(target.current))
- return 0
- var/atom/A = target.current
- while(A.loc) //check to see if the brainmob is on our person
- A = A.loc
- if(A == owner.current)
- return 1
- return 0
+ return FALSE
+ for(var/datum/mind/M in get_owners())
+ if(QDELETED(M.current) || M.current.stat == DEAD)
+ continue // Maybe someone who's alive has the brain.
+ if(target.current in M.current.GetAllContents())
+ return TRUE
+ return FALSE
/datum/objective/protect //The opposite of killing a dude.
@@ -206,20 +229,21 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
/datum/objective/protect/check_completion()
if(!target) //If it's a free objective.
- return 1
+ return TRUE
if(target.current)
if(target.current.stat == DEAD)
- return 0
+ return FALSE
if(issilicon(target.current))
- return 0
+ return FALSE
if(isbrain(target.current))
- return 0
- return 1
- return 0
+ return FALSE
+ return TRUE
+ return FALSE
/datum/objective/protect/mindslave //subytpe for mindslave implants
needs_target = FALSE // To be clear, this objective should have a target, but it will always be manually set to the mindslaver through the mindslave antag datum.
+// This objective should only be given to a single owner. We can use `owner` and not `get_owners()`.
/datum/objective/protect/mindslave/on_target_cryo()
if(owner?.current)
SEND_SOUND(owner.current, sound('sound/ambience/alarm4.ogg'))
@@ -237,17 +261,11 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
needs_target = FALSE
/datum/objective/hijack/check_completion()
- if(!owner.current || owner.current.stat)
- return 0
if(SSshuttle.emergency.mode < SHUTTLE_ENDGAME)
- return 0
- if(issilicon(owner.current))
- return 0
-
- var/area/A = get_area(owner.current)
- if(SSshuttle.emergency.areaInstance != A)
- return 0
-
+ return FALSE
+ for(var/datum/mind/M in get_owners())
+ if(QDELETED(M.current) || M.current.stat != CONSCIOUS || issilicon(M.current) || get_area(M.current) != SSshuttle.emergency.areaInstance)
+ return FALSE
return SSshuttle.emergency.is_hijacked()
/datum/objective/hijackclone
@@ -255,11 +273,11 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
martyr_compatible = 0
needs_target = FALSE
+// This objective should only be given to a single owner, because the "copies" can only copy one person.
+// We're fine to use `owner` instead of `get_owners()`.
/datum/objective/hijackclone/check_completion()
- if(!owner.current)
- return 0
- if(SSshuttle.emergency.mode < SHUTTLE_ENDGAME)
- return 0
+ if(SSshuttle.emergency.mode < SHUTTLE_ENDGAME || !owner.current)
+ return FALSE
var/area/A = SSshuttle.emergency.areaInstance
@@ -270,7 +288,7 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
continue
if(get_area(player) == A)
if(player.real_name != owner.current.real_name && !istype(get_turf(player.mind.current), /turf/simulated/floor/mineral/plastitanium/red/brig))
- return 0
+ return FALSE
for(var/mob/living/player in GLOB.player_list) //Make sure at least one of you is onboard
if(player.mind && player.mind != owner)
@@ -279,8 +297,8 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
continue
if(get_area(player) == A)
if(player.real_name == owner.current.real_name && !istype(get_turf(player.mind.current), /turf/simulated/floor/mineral/plastitanium/red/brig))
- return 1
- return 0
+ return TRUE
+ return FALSE
/datum/objective/block
explanation_text = "Hijack the shuttle with no loyalist Nanotrasen crew on board and free. \
@@ -290,17 +308,15 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
needs_target = FALSE
/datum/objective/block/check_completion()
- if(!issilicon(owner.current))
- return FALSE
+ for(var/datum/mind/M in get_owners())
+ if(!M.current || !issilicon(M.current))
+ return FALSE
if(SSticker.mode.station_was_nuked)
return TRUE
if(SSshuttle.emergency.mode < SHUTTLE_ENDGAME)
return FALSE
- if(!owner.current)
- return FALSE
if(!SSshuttle.emergency.is_hijacked(TRUE))
return FALSE
-
return TRUE
/datum/objective/escape
@@ -308,29 +324,27 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
needs_target = FALSE
/datum/objective/escape/check_completion()
- if(issilicon(owner.current))
- return 0
- if(isbrain(owner.current))
- return 0
- if(!owner.current || owner.current.stat == DEAD)
- return 0
- if(SSticker.force_ending) //This one isn't their fault, so lets just assume good faith
- return 1
- if(SSticker.mode.station_was_nuked) //If they escaped the blast somehow, let them win
- return 1
+ var/list/owners = get_owners()
+ for(var/datum/mind/M in owners)
+ // These are mandatory conditions, they should come before the freebie conditions below.
+ if(QDELETED(M.current) || M.current.stat == DEAD || issilicon(M.current) || isbrain(M.current))
+ return FALSE
+
+ if(SSticker.force_ending) // This one isn't their fault, so lets just assume good faith.
+ return TRUE
+ if(SSticker.mode.station_was_nuked) // If they escaped the blast somehow, let them win.
+ return TRUE
if(SSshuttle.emergency.mode < SHUTTLE_ENDGAME)
- return 0
- var/turf/location = get_turf(owner.current)
- if(!location)
- return 0
+ return FALSE
- if(istype(location, /turf/simulated/floor/mineral/plastitanium/red/brig)) // Fails traitors if they are in the shuttle brig -- Polymorph
- return 0
+ for(var/datum/mind/M in owners)
+ var/turf/location = get_turf(M.current)
+ if(istype(location, /turf/simulated/floor/mineral/plastitanium/red/brig))
+ return FALSE
+ if(!location.onCentcom() && !location.onSyndieBase())
+ return FALSE
- if(location.onCentcom() || location.onSyndieBase())
- return 1
-
- return 0
+ return TRUE
/datum/objective/escape/escape_with_identity
@@ -351,28 +365,32 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
else
explanation_text = "Free Objective"
+// This objective should only be given to a single owner since only 1 person can have the ID card of the target.
+// We're fine to use `owner` instead of `get_owners()`.
/datum/objective/escape/escape_with_identity/check_completion()
if(!target_real_name)
- return 1
+ return TRUE
if(!ishuman(owner.current))
- return 0
+ return FALSE
var/mob/living/carbon/human/H = owner.current
if(..())
if(H.dna.real_name == target_real_name)
- if(H.get_id_name()== target_real_name)
- return 1
- return 0
+ if(H.get_id_name() == target_real_name)
+ return TRUE
+ return FALSE
/datum/objective/die
explanation_text = "Die a glorious death."
needs_target = FALSE
/datum/objective/die/check_completion()
- if(!owner.current || owner.current.stat == DEAD || isbrain(owner.current))
- return 1
- if(issilicon(owner.current) && !owner.is_original_mob(owner.current))
- return 1
- return 0
+ for(var/datum/mind/M in get_owners())
+ if(QDELETED(M.current) || M.current.stat == DEAD || isbrain(M.current))
+ continue
+ if(issilicon(M.current) && !M.is_original_mob(M.current))
+ continue
+ return FALSE // Some owner didn't meet the above criteria.
+ return TRUE
@@ -381,11 +399,12 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
needs_target = FALSE
/datum/objective/survive/check_completion()
- if(!owner.current || owner.current.stat == DEAD || isbrain(owner.current))
- return 0 //Brains no longer win survive objectives. --NEO
- if(issilicon(owner.current) && !owner.is_original_mob(owner.current))
- return 0
- return 1
+ for(var/datum/mind/M in get_owners())
+ if(QDELETED(M.current) || M.current.stat == DEAD || isbrain(M.current))
+ return FALSE
+ if(issilicon(M.current) && !M.is_original_mob(M.current))
+ return FALSE
+ return TRUE
/datum/objective/nuclear
explanation_text = "Destroy the station with a nuclear device."
@@ -405,9 +424,12 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
while(!steal_target && length(potential))
var/thefttype = pick_n_take(potential)
var/datum/theft_objective/O = new thefttype
- if(owner.assigned_role in O.protected_jobs)
- continue
- if(O in owner.targets)
+ var/has_invalid_owner = FALSE
+ for(var/datum/mind/M in get_owners())
+ if((M.assigned_role in O.protected_jobs) || (O in M.targets))
+ has_invalid_owner = TRUE
+ break
+ if(has_invalid_owner)
continue
if(O.flags & 2) // THEFT_FLAG_UNIQUE
continue
@@ -445,21 +467,17 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
/datum/objective/steal/check_completion()
if(!steal_target)
- return 1 // Free Objective
+ return TRUE // Free Objective
- if(!owner.current)
- return FALSE
-
- var/list/all_items = owner.current.GetAllContents()
-
- for(var/obj/I in all_items)
- if(istype(I, steal_target.typepath))
- return steal_target.check_special_completion(I)
- if(I.type in steal_target.altitems)
- return steal_target.check_special_completion(I)
+ for(var/datum/mind/M in get_owners())
+ if(!M.current)
+ continue
+ for(var/obj/I in M.current.GetAllContents())
+ if((istype(I, steal_target.typepath) || (I.type in steal_target.altitems)) && steal_target.check_special_completion(I))
+ return TRUE
+ return FALSE
/datum/objective/steal/proc/give_kit(obj/item/item_path)
- var/mob/living/carbon/human/mob = owner.current
var/I = new item_path
var/list/slots = list(
"backpack" = slot_in_backpack,
@@ -468,65 +486,15 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
"left hand" = slot_l_hand,
"right hand" = slot_r_hand,
)
- var/where = mob.equip_in_one_of_slots(I, slots)
- if(where)
- to_chat(mob, "
In your [where] is a box containing items and instructions to help you with your steal objective.
")
- else
- to_chat(mob, "Unfortunately, you weren't able to get a stealing kit. This is very bad and you should adminhelp immediately (press F1).")
- message_admins("[ADMIN_LOOKUPFLW(mob)] Failed to spawn with their [item_path] theft kit.")
- qdel(I)
-
-/datum/objective/steal/exchange
- martyr_compatible = 0
- needs_target = FALSE
-
-/datum/objective/steal/exchange/proc/set_faction(faction, otheragent)
- target = otheragent
- var/datum/theft_objective/unique/targetinfo
- if(faction == "red")
- targetinfo = new /datum/theft_objective/unique/docs_blue
- else if(faction == "blue")
- targetinfo = new /datum/theft_objective/unique/docs_red
- explanation_text = "Acquire [targetinfo.name] held by [target.current.real_name], the [target.assigned_role] and syndicate agent"
- steal_target = targetinfo
-
-/datum/objective/steal/exchange/backstab
-/datum/objective/steal/exchange/backstab/set_faction(faction)
- var/datum/theft_objective/unique/targetinfo
- if(faction == "red")
- targetinfo = new /datum/theft_objective/unique/docs_red
- else if(faction == "blue")
- targetinfo = new /datum/theft_objective/unique/docs_blue
- explanation_text = "Do not give up or lose [targetinfo.name]."
- steal_target = targetinfo
-
-/datum/objective/download
- needs_target = FALSE
-
-/datum/objective/download/proc/gen_amount_goal()
- target_amount = rand(10,20)
- explanation_text = "Download [target_amount] research levels."
- return target_amount
-
-
-/datum/objective/download/check_completion()
- return 0
-
-
-
-/datum/objective/capture
- needs_target = FALSE
-
-/datum/objective/capture/proc/gen_amount_goal()
- target_amount = rand(5,10)
- explanation_text = "Accumulate [target_amount] capture points."
- return target_amount
-
-
-/datum/objective/capture/check_completion()//Basically runs through all the mobs in the area to determine how much they are worth.
- return 0
-
-
+ for(var/datum/mind/M in get_owners())
+ var/mob/living/carbon/human/H = M.current
+ var/where = H.equip_in_one_of_slots(I, slots)
+ if(where)
+ to_chat(H, "
In your [where] is a box containing items and instructions to help you with your steal objective.
")
+ else
+ to_chat(H, "Unfortunately, you weren't able to get a stealing kit. This is very bad and you should adminhelp immediately (press F1).")
+ message_admins("[ADMIN_LOOKUPFLW(H)] Failed to spawn with their [item_path] theft kit.")
+ qdel(I)
/datum/objective/absorb
@@ -538,7 +506,7 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
var/n_p = 1 //autowin
if(SSticker.current_state == GAME_STATE_SETTING_UP)
for(var/mob/new_player/P in GLOB.player_list)
- if(P.client && P.ready && P.mind != owner)
+ if(P.client && P.ready && !(P.mind in get_owners()))
if(P.client.prefs && (P.client.prefs.active_character.species == "Machine")) // Special check for species that can't be absorbed. No better solution.
continue
n_p++
@@ -546,7 +514,7 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
for(var/mob/living/carbon/human/P in GLOB.player_list)
if(HAS_TRAIT(P, TRAIT_GENELESS))
continue
- if(P.client && !(P.mind in SSticker.mode.changelings) && P.mind!=owner)
+ if(P.client && !(P.mind in SSticker.mode.changelings) && !(P.mind in get_owners()))
n_p++
target_amount = min(target_amount, n_p)
@@ -554,9 +522,10 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
return target_amount
/datum/objective/absorb/check_completion()
- var/datum/antagonist/changeling/cling = owner?.has_antag_datum(/datum/antagonist/changeling)
- if(cling?.absorbed_dna && (cling.absorbed_count >= target_amount))
- return TRUE
+ for(var/datum/mind/M in get_owners())
+ var/datum/antagonist/changeling/cling = M?.has_antag_datum(/datum/antagonist/changeling)
+ if(cling?.absorbed_dna && (cling.absorbed_count >= target_amount))
+ return TRUE
return FALSE
/datum/objective/destroy
@@ -577,9 +546,9 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
/datum/objective/destroy/check_completion()
if(target && target.current)
if(target.current.stat == DEAD || is_away_level(target.current.z) || !target.current.ckey)
- return 1
- return 0
- return 1
+ return TRUE
+ return FALSE
+ return TRUE
/datum/objective/steal_five_of_type
explanation_text = "Steal at least five items!"
@@ -592,9 +561,12 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
/datum/objective/steal_five_of_type/check_completion()
var/stolen_count = 0
- if(!isliving(owner.current))
- return FALSE
- var/list/all_items = owner.current.GetAllContents() //this should get things in cheesewheels, books, etc.
+ var/list/owners = get_owners()
+ var/list/all_items = list()
+ for(var/datum/mind/M in owners)
+ if(!isliving(M.current))
+ continue
+ all_items += M.current.GetAllContents() //this should get things in cheesewheels, books, etc.
for(var/obj/I in all_items) //Check for wanted items
if(is_type_in_typecache(I, wanted_items))
stolen_count++
@@ -614,9 +586,12 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
/datum/objective/steal_five_of_type/summon_magic/check_completion()
var/stolen_count = 0
- if(!isliving(owner.current))
- return FALSE
- var/list/all_items = owner.current.GetAllContents() //this should get things in cheesewheels, books, etc.
+ var/list/owners = get_owners()
+ var/list/all_items = list()
+ for(var/datum/mind/M in owners)
+ if(!isliving(M.current))
+ continue
+ all_items += M.current.GetAllContents() //this should get things in cheesewheels, books, etc.
for(var/obj/I in all_items) //Check for wanted items
if(istype(I, /obj/item/spellbook) && !istype(I, /obj/item/spellbook/oneuse))
var/obj/item/spellbook/spellbook = I
@@ -644,11 +619,12 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
return target_amount
/datum/objective/blood/check_completion()
- var/datum/antagonist/vampire/V = owner.has_antag_datum(/datum/antagonist/vampire)
- if(V.bloodtotal >= target_amount)
- return TRUE
- else
- return FALSE
+ for(var/datum/mind/M in get_owners())
+ var/datum/antagonist/vampire/V = M.has_antag_datum(/datum/antagonist/vampire)
+ if(V.bloodtotal >= target_amount)
+ return TRUE
+ else
+ return FALSE
// Traders