diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index 892e781fb5e..b9feeaa1124 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -77,6 +77,7 @@
var/traitor_scaling_coeff = 6 //how much does the amount of players get divided by to determine traitors
var/changeling_scaling_coeff = 7 //how much does the amount of players get divided by to determine changelings
+ var/traitor_objectives_amount = 2
var/protect_roles_from_antagonist = 0// If security and such can be traitor/cult/other
var/allow_latejoin_antagonists = 0 // If late-joining players can be traitor/changeling
var/continuous_round_rev = 0 // Gamemodes which end instantly will instead keep on going until the round ends by escape shuttle or nuke.
@@ -345,6 +346,8 @@
config.traitor_scaling_coeff = text2num(value)
if("changeling_scaling_coeff")
config.changeling_scaling_coeff = text2num(value)
+ if("traitor_objectives_amount")
+ config.traitor_objectives_amount = text2num(value)
if("probability")
var/prob_pos = findtext(value, " ")
var/prob_name = null
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index f29f7b9d1d2..5007a845681 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -13,10 +13,19 @@ datum/objective/New(var/text)
datum/objective/proc/check_completion()
return completed
+datum/objective/proc/is_unique_objective(possible_target)
+ for(var/datum/objective/assassinate/O in owner.objectives)
+ if(O.get_target() == possible_target)
+ return 0
+ return 1
+
+datum/objective/proc/get_target()
+ return target
+
datum/objective/proc/find_target()
var/list/possible_targets = list()
for(var/datum/mind/possible_target in ticker.minds)
- if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != 2))
+ if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != 2) && is_unique_objective(possible_target))
possible_targets += possible_target
if(possible_targets.len > 0)
target = pick(possible_targets)
@@ -255,21 +264,32 @@ datum/objective/steal
var/obj/item/steal_target = null //Needed for custom objectives (they're just items, not datums).
dangerrating = 5 //Overridden by the individual item's difficulty, but defaults to 5 for custom objectives.
+datum/objective/steal/get_target()
+ return steal_target
+
datum/objective/steal/New()
..()
if(!possible_items.len)//Only need to fill the list when it's needed.
init_subtypes(/datum/objective_item/steal,possible_items)
datum/objective/steal/find_target()
- return set_target(pick(possible_items))
+ var/approved_targets = list()
+ for(var/datum/objective_item/possible_item in possible_items)
+ if(is_unique_objective(possible_item.targetitem))
+ approved_targets += possible_item
+ return set_target(safepick(possible_items))
datum/objective/steal/proc/set_target(var/datum/objective_item/item)
- targetinfo = item
+ if(item)
+ targetinfo = item
- steal_target = targetinfo.targetitem
- explanation_text = "Steal [targetinfo.name]."
- dangerrating = targetinfo.difficulty
- return steal_target
+ steal_target = targetinfo.targetitem
+ explanation_text = "Steal [targetinfo.name]."
+ dangerrating = targetinfo.difficulty
+ return steal_target
+ else
+ explanation_text = "Free objective"
+ return
datum/objective/steal/proc/select_target() //For admins setting objectives manually.
var/list/possible_items_all = possible_items+"custom"
@@ -292,7 +312,7 @@ datum/objective/steal/proc/select_target() //For admins setting objectives manua
return steal_target
datum/objective/steal/check_completion()
- if(!steal_target || !owner.current) return 0
+ if(!steal_target) return 1
if(!isliving(owner.current)) return 0
var/list/all_items = owner.current.GetAllContents() //this should get things in cheesewheels, books, etc.
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index 7e30c214854..cf23fd6fccd 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -116,16 +116,17 @@
assign_exchange_role(exchange_red,"red")
assign_exchange_role(exchange_blue,"blue")
else
- if(prob(50))
- var/datum/objective/assassinate/kill_objective = new
- kill_objective.owner = traitor
- kill_objective.find_target()
- traitor.objectives += kill_objective
- else
- var/datum/objective/steal/steal_objective = new
- steal_objective.owner = traitor
- steal_objective.find_target()
- traitor.objectives += steal_objective
+ for(var/i = 0, i < config.traitor_objectives_amount, i++)
+ if(prob(50))
+ var/datum/objective/assassinate/kill_objective = new
+ kill_objective.owner = traitor
+ kill_objective.find_target()
+ traitor.objectives += kill_objective
+ else
+ var/datum/objective/steal/steal_objective = new
+ steal_objective.owner = traitor
+ steal_objective.find_target()
+ traitor.objectives += steal_objective
if(prob(90))
if (!(locate(/datum/objective/escape) in traitor.objectives))
diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm
index 26bd773e80b..a8c3c48f01e 100644
--- a/code/game/mecha/equipment/tools/tools.dm
+++ b/code/game/mecha/equipment/tools/tools.dm
@@ -112,10 +112,10 @@
ore.Move(ore_box)
else if(target.loc == C)
log_message("Drilled through [target]")
- if(ismob(target))
- var/mob/M = target
- add_logs(chassis.occupant, M, "attacked", object="[name]", addition="(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])")
- target.ex_act(2)
+ if(isliving(target))
+ drill_mob(target, chassis.occupant)
+ else
+ target.ex_act(2)
return 1
can_attach(obj/mecha/M as obj)
@@ -124,6 +124,20 @@
return 1
return 0
+/obj/item/mecha_parts/mecha_equipment/tool/drill/proc/drill_mob(mob/living/target, mob/user, var/drill_damage=80)
+ target.visible_message("[chassis] drills [target] with the [src].\
+ [chassis] drills [target] with the [src].")
+ add_logs(user, target, "attacked", object="[name]", addition="(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ var/obj/item/organ/limb/affecting = H.get_organ("chest")
+ affecting.take_damage(drill_damage)
+ H.update_damage_overlays(0)
+ else
+ target.take_organ_damage(drill_damage)
+ target.Paralyse(10)
+ target.updatehealth()
+
/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill
name = "diamond-tipped exosuit drill"
desc = "Equipment for engineering and combat exosuits. This is an upgraded version of the drill that'll pierce the heavens!"
@@ -172,10 +186,10 @@
ore.Move(ore_box)
else if(target.loc == C)
log_message("Drilled through [target]")
- if(ismob(target))
- var/mob/M = target
- add_logs(chassis.occupant, M, "attacked", object="[name]", addition="(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])")
- target.ex_act(2)
+ if(isliving(target))
+ drill_mob(target, chassis.occupant, 120)
+ else
+ target.ex_act(2)
return 1
can_attach(obj/mecha/M as obj)
diff --git a/config/game_options.txt b/config/game_options.txt
index 9ba5daa2914..d250d80c56d 100644
--- a/config/game_options.txt
+++ b/config/game_options.txt
@@ -114,6 +114,10 @@ SHUTTLE_REFUEL_DELAY 12000
TRAITOR_SCALING_COEFF 6
CHANGELING_SCALING_COEFF 7
+# The number of objectives traitors get.
+# Not including escaping/hijacking.
+TRAITOR_OBJECTIVES_AMOUNT 2
+
## Uncomment to prohibit jobs that start with loyalty
## implants from being most antagonists.
#PROTECT_ROLES_FROM_ANTAGONIST
@@ -192,4 +196,4 @@ DEFAULT_LAWS 1
## Uncomment to allow certain species to have custom colors
-#MUTANT_COLORS
\ No newline at end of file
+#MUTANT_COLORS