diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 304a08224ec..08d6a99f019 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -57,6 +57,7 @@
#define TRAIT_PARALYSIS_R_ARM "para-r-arm"
#define TRAIT_PARALYSIS_L_LEG "para-l-leg"
#define TRAIT_PARALYSIS_R_LEG "para-r-leg"
+#define TRAIT_DISK_VERIFIER "disk-verifier"
#define TRAIT_NOMOBSWAP "no-mob-swap"
#define TRAIT_XRAY_VISION "xray_vision"
@@ -91,6 +92,7 @@
#define SPECIES_TRAIT "species"
#define ORGAN_TRAIT "organ"
#define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention
+#define JOB_TRAIT "job"
// unique trait sources, still defines
#define STATUE_MUTE "statue"
@@ -104,3 +106,5 @@
#define EYES_COVERED "eyes_covered"
#define CULT_EYES "cult_eyes"
#define SCRYING_ORB "scrying-orb"
+#define NUKEOP_TRAIT "nuke-op"
+#define DEATHSQUAD_TRAIT "deathsquad"
diff --git a/code/datums/traits.dm b/code/datums/traits.dm
index c105865b11e..15715c3c888 100644
--- a/code/datums/traits.dm
+++ b/code/datums/traits.dm
@@ -1,16 +1,16 @@
/datum/proc/add_trait(trait, source)
LAZYINITLIST(status_traits)
-
+
if(!status_traits[trait])
status_traits[trait] = list(source)
else
status_traits[trait] |= list(source)
-
+
/datum/proc/remove_trait(trait, list/sources, force)
if(!status_traits)
return //nothing to remove
-
+
if(!status_traits[trait])
return
@@ -33,11 +33,11 @@
if(!LAZYLEN(status_traits[trait]))
status_traits -= trait
-
+
/datum/proc/has_trait(trait, list/sources)
if(!status_traits)
return FALSE //well of course it doesn't have the trait
-
+
if(!status_traits[trait])
return FALSE
@@ -51,11 +51,11 @@
return TRUE
else if(LAZYLEN(status_traits[trait]))
return TRUE
-
+
/datum/proc/remove_all_traits(remove_species_traits = FALSE, remove_organ_traits = FALSE, remove_quirks = FALSE)
if(!status_traits)
return //nothing to remove
-
+
var/list/blacklisted_sources = list()
if(!remove_species_traits)
blacklisted_sources += SPECIES_TRAIT
@@ -72,4 +72,4 @@
break
if(!skip)
remove_trait(kebab, null, TRUE)
- CHECK_TICK
\ No newline at end of file
+ CHECK_TICK
diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm
index 76dc6983471..5f069b99066 100644
--- a/code/modules/antagonists/ert/ert.dm
+++ b/code/modules/antagonists/ert/ert.dm
@@ -34,6 +34,12 @@
. = ..()
name_source = GLOB.commando_names
+/datum/antagonist/ert/deathsquad/apply_innate_effects(mob/living/mob_override)
+ owner.add_trait(TRAIT_DISK_VERIFIER, DEATHSQUAD_TRAIT)
+
+/datum/antagonist/ert/deathsquad/remove_innate_effects(mob/living/mob_override)
+ owner.remove_trait(TRAIT_DISK_VERIFIER, DEATHSQUAD_TRAIT)
+
/datum/antagonist/ert/security // kinda handled by the base template but here for completion
/datum/antagonist/ert/security/red
diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
index dd9114a0664..fe136774b4a 100644
--- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
+++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
@@ -600,10 +600,7 @@ This is here to make the tiles around the station mininuke change when it's arme
if(!fake)
return
- var/ghost = isobserver(user)
- var/captain = user.mind && user.mind.assigned_role == "Captain"
- var/nukie = user.mind && user.mind.has_antag_datum(/datum/antagonist/nukeop)
- if(ghost || captain || nukie)
+ if(isobserver(user) || user.has_trait(TRAIT_DISK_VERIFIER) || (user.mind && user.mind.has_trait(TRAIT_DISK_VERIFIER)))
to_chat(user, "The serial numbers on [src] are incorrect.")
/obj/item/disk/nuclear/attackby(obj/item/I, mob/living/user, params)
@@ -642,3 +639,7 @@ This is here to make the tiles around the station mininuke change when it's arme
/obj/item/disk/nuclear/fake
fake = TRUE
+
+/obj/item/disk/nuclear/fake/obvious
+ name = "cheap plastic imitation of the nuclear authentication disk"
+ desc = "How anyone could mistake this for the real thing is beyond you."
diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm
index 942af1bb47f..b391a1c7a10 100644
--- a/code/modules/antagonists/nukeop/nukeop.dm
+++ b/code/modules/antagonists/nukeop/nukeop.dm
@@ -23,10 +23,12 @@
/datum/antagonist/nukeop/apply_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_synd_icons_added(M)
+ owner.add_trait(TRAIT_DISK_VERIFIER, NUKEOP_TRAIT)
/datum/antagonist/nukeop/remove_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_synd_icons_removed(M)
+ owner.remove_trait(TRAIT_DISK_VERIFIER, NUKEOP_TRAIT)
/datum/antagonist/nukeop/proc/equip_op()
if(!ishuman(owner.current))
@@ -42,7 +44,6 @@
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0)
to_chat(owner, "You are a [nuke_team ? nuke_team.syndicate_name : "syndicate"] agent!")
owner.announce_objectives()
- return
/datum/antagonist/nukeop/on_gain()
give_alias()
diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm
index da617deb458..b56a31fc79b 100755
--- a/code/modules/jobs/job_types/captain.dm
+++ b/code/modules/jobs/job_types/captain.dm
@@ -26,6 +26,9 @@ Captain
/datum/job/captain/get_access()
return get_all_accesses()
+/datum/job/captain/after_spawn(mob/living/H, mob/M, latejoin = FALSE)
+ H.mind.add_trait(TRAIT_DISK_VERIFIER, JOB_TRAIT)
+
/datum/job/captain/announce(mob/living/carbon/human/H)
..()
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, .proc/minor_announce, "Captain [H.real_name] on deck!"))