diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm
index 820283423e..6175e0aa3e 100644
--- a/code/__defines/gamemode.dm
+++ b/code/__defines/gamemode.dm
@@ -40,11 +40,12 @@
//VOREStation Add
#define BE_LOSTDRONE 0x10000
#define BE_MAINTPRED 0x20000
-#define BE_MORPH 0x40000
-#define BE_CORGI 0x80000
-#define BE_CURSEDSWORD 0x100000
-#define BE_SURVIVOR 0x200000
-#define BE_EVENT 0x400000
+#define BE_MAINTLURKER 0x40000
+#define BE_MORPH 0x80000
+#define BE_CORGI 0x100000
+#define BE_CURSEDSWORD 0x200000
+#define BE_SURVIVOR 0x400000
+#define BE_EVENT 0x800000
//VOREStation Add End
var/list/be_special_flags = list(
@@ -67,6 +68,7 @@ var/list/be_special_flags = list(
//VOREStation Add
"Lost Drone" = BE_LOSTDRONE,
"Maint Pred" = BE_MAINTPRED,
+ "Stowaway" = BE_MAINTLURKER, // CHOMPEdit
"Morph" = BE_MORPH,
"Corgi" = BE_CORGI,
"Cursed Sword" = BE_CURSEDSWORD,
diff --git a/code/__defines/jobs.dm b/code/__defines/jobs.dm
index 497c2a17ed..5ded971296 100644
--- a/code/__defines/jobs.dm
+++ b/code/__defines/jobs.dm
@@ -443,3 +443,4 @@
#define JOB_XENOMORPH "Xenomorph"
#define JOB_BORER "Borer"
#define JOB_EMERGENCY_RESPONSE_TEAM "Emergency Response Team"
+#define JOB_MAINT_LURKER "Maintenance Lurker"
diff --git a/code/datums/ghost_query_vr.dm b/code/datums/ghost_query_vr.dm
index 75356029be..8f29b14bb3 100644
--- a/code/datums/ghost_query_vr.dm
+++ b/code/datums/ghost_query_vr.dm
@@ -7,5 +7,11 @@
/datum/ghost_query/maints_pred
role_name = "Maintenance Predator"
be_special_flag = BE_MAINTPRED
- question = "It appears a predatory critter is lurking in the maintenance. Do you want to play as it? ((You get to choose type of critter. Expect to be treated as vore predator.))"
- cutoff_number = 1
\ No newline at end of file
+ question = "It appears a predatory critter is lurking in maintenance. Do you want to play as it? ((You get to choose type of critter. Expect to be treated as vore predator.))"
+ cutoff_number = 1
+
+/datum/ghost_query/maints_lurker
+ role_name = "Maintenance Lurker"
+ be_special_flag = BE_MAINTLURKER
+ question = "It appears a strange individual is lurking in maintenance. Do you want to play as them? ((You can spawn as your currently loaded character slot. Expect to be treated as vore predator.))"
+ cutoff_number = 1
diff --git a/code/datums/outfits/misc.dm b/code/datums/outfits/misc.dm
index ef36b85038..13620cbf9a 100644
--- a/code/datums/outfits/misc.dm
+++ b/code/datums/outfits/misc.dm
@@ -63,4 +63,16 @@
/decl/hierarchy/outfit/zaddat
name = "Zaddat Suit"
suit = /obj/item/clothing/suit/space/void/zaddat/
- mask = /obj/item/clothing/mask/gas/zaddat
\ No newline at end of file
+ mask = /obj/item/clothing/mask/gas/zaddat
+
+/decl/hierarchy/outfit/maint_lurker
+ name = "Maintenance Lurker Outfit"
+ id_slot = slot_wear_id
+ id_type = /obj/item/card/id/civilian/lurker
+ pda_slot = slot_belt
+ pda_type = /obj/item/pda
+ id_pda_assignment = "NO DATA"
+
+ headset = /obj/item/radio/headset
+ headset_alt = /obj/item/radio/headset/alt
+ headset_earbud = /obj/item/radio/headset/earbud
diff --git a/code/game/jobs/job/special.dm b/code/game/jobs/job/special.dm
index 1cdce5e991..d60f2f85bc 100644
--- a/code/game/jobs/job/special.dm
+++ b/code/game/jobs/job/special.dm
@@ -158,3 +158,25 @@
else
return list(access_entertainment, access_tomfoolery, access_mime)
*/ //CHOMPEDIT: END remove Mime/clown defines (These are alt titles of Entertainer on our codebase)
+
+/obj/item/card/id/civilian/lurker
+ desc = "A rather old and scuffed-looking ID. It seems legit, but something also seems very off somehow. Say, what's the issue/expiry date..?"
+ assignment = "NO DATA"
+ rank = JOB_MAINT_LURKER
+
+/datum/job/maint_lurker
+ title = JOB_MAINT_LURKER
+ departments = list(DEPARTMENT_CIVILIAN)
+ faction = FACTION_STATION
+ total_positions = -1
+ spawn_positions = -1
+ supervisors = "nobody save your own common sense and good judgement, though Security may get upset if you're not careful"
+ selection_color = "#515151"
+ account_allowed = FALSE //let's not give the game away by creating accounts that someone might stumble across
+ job_description = "You are a maintenance lurker! You shouldn't be able to see this description anyway! Go prank the CMO or eat the RD's hat or something instead of looking at this."
+ whitelist_only = 1
+ latejoin_only = 1
+ requestable = FALSE
+ outfit_type = /decl/hierarchy/outfit/maint_lurker
+ access = list(access_maint_tunnels)
+ minimal_access = list(access_maint_tunnels)
diff --git a/code/game/objects/items/weapons/id cards/id_stacks.dm b/code/game/objects/items/weapons/id cards/id_stacks.dm
index 3158d93a9b..1e0f49133e 100644
--- a/code/game/objects/items/weapons/id cards/id_stacks.dm
+++ b/code/game/objects/items/weapons/id cards/id_stacks.dm
@@ -336,3 +336,9 @@
/obj/item/card/id/syndicate/officer
name = "Syndicate Officer ID"
initial_sprite_stack = list("base-stamp-dark", "top-syndicate", "stamp-s", "pips-gold", "stripe-gold")
+
+//Special
+
+/obj/item/card/id/civilian/lurker
+ name = "Outdated ID"
+ initial_sprite_stack = list("base-stamp", "stamp-silhouette", "top-olive", "digested")
diff --git a/code/game/objects/structures/ghost_pods/event_vr.dm b/code/game/objects/structures/ghost_pods/event_vr.dm
index f2106354aa..bc297c0559 100644
--- a/code/game/objects/structures/ghost_pods/event_vr.dm
+++ b/code/game/objects/structures/ghost_pods/event_vr.dm
@@ -125,7 +125,7 @@
//newPred.movement_cooldown = 0 // The "needless artificial speed cap" exists for a reason
if(M.mind)
M.mind.transfer_to(newPred)
- to_chat(M, span_notice("You are [newPred], somehow having gotten aboard the station in search of food. \
+ to_chat(M, span_notice("You are " + span_bold(newPred) + ", somehow having gotten aboard the station in search of food. \
You are wary of environment around you, but you do feel rather peckish. Stick around dark, secluded places to avoid danger or, \
if you are cute enough, try to make friends with this place's inhabitants."))
to_chat(M, span_critical("Please be advised, this role is NOT AN ANTAGONIST."))
@@ -163,7 +163,7 @@
newMorph.init_vore() //CHOMPedit: On-demand belly loading.
if(M.mind)
M.mind.transfer_to(newMorph)
- to_chat(M, span_notice("You are a Morph, somehow having gotten aboard the station in your wandering. \
+ to_chat(M, span_notice("You are a " + span_bold("Morph") + ", somehow having gotten aboard the station in your wandering. \
You are wary of environment around you, but your primal hunger still calls for you to find prey. Seek a convincing disguise, \
using your amorphous form to traverse vents to find and consume weak prey."))
to_chat(M, span_notice("You can use shift + click on objects to disguise yourself as them, but your strikes are nearly useless when you are disguised. \
@@ -191,3 +191,82 @@
..()
if(!(src in active_ghost_pods))
active_ghost_pods += src
+
+/obj/structure/ghost_pod/ghost_activated/maint_lurker
+ name = "strange maintenance hole"
+ desc = "This is my hole! It was made for me!"
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "tunnel_hole"
+ icon_state_opened = "tunnel_hole"
+ density = FALSE
+ ghost_query_type = /datum/ghost_query/maints_lurker
+ anchored = TRUE
+ invisibility = INVISIBILITY_OBSERVER
+ spawn_active = TRUE
+
+//override the standard attack_ghost proc for custom messages
+/obj/structure/ghost_pod/ghost_activated/maint_lurker/attack_ghost(var/mob/observer/dead/user)
+ if(jobban_isbanned(user, JOB_GHOSTROLES))
+ to_chat(user, span_warning("You cannot use this spawnpoint because you are banned from playing ghost roles."))
+ return
+
+ //No whitelist
+ if(!is_alien_whitelisted(user, GLOB.all_species[user.client.prefs.species]))
+ to_chat(user, span_warning("You cannot use this spawnpoint to spawn as a species you are not whitelisted for!"))
+ return
+
+ //No OOC notes/FT
+ if(not_has_ooc_text(user))
+ //to_chat(user, span_warning("You must have proper out-of-character notes and flavor text configured for your current character slot to use this spawnpoint."))
+ return
+
+ var/choice = tgui_alert(user, "Using this spawner will spawn you as your currently loaded character slot in a special role. It should not be used with characters you regularly play on station. Are you absolutely sure you wish to continue?", "Stowaway Spawner", list("Yes", "No")) // CHOMPEdit
+
+ if(!choice || choice == "No")
+ return
+
+ create_occupant(user)
+
+/obj/structure/ghost_pod/ghost_activated/maint_lurker/create_occupant(var/mob/M)
+ ..()
+
+ var/picked_ckey = M.ckey
+ var/picked_slot = M.client.prefs.default_slot
+
+ var/mob/living/carbon/human/new_character = new(src.loc)
+ if(!new_character)
+ to_chat(M, span_warning("Something went wrong and spawning failed. Please check your character slot doesn't have any obvious errors, then either try again or send an adminhelp!"))
+ reset_ghostpod()
+ return
+ log_and_message_admins("successfully used a Maintenance Lurker spawnpoint and became their loaded character.")
+
+ M.client.prefs.copy_to(new_character)
+ new_character.dna.ResetUIFrom(new_character)
+ new_character.sync_organ_dna()
+ new_character.key = M.key
+ new_character.mind.loaded_from_ckey = picked_ckey
+ new_character.mind.loaded_from_slot = picked_slot
+
+ job_master.EquipRank(new_character, JOB_MAINT_LURKER, 1)
+
+ for(var/lang in new_character.client.prefs.alternate_languages)
+ var/datum/language/chosen_language = GLOB.all_languages[lang]
+ if(chosen_language)
+ if(is_lang_whitelisted(src,chosen_language) || (new_character.species && (chosen_language.name in new_character.species.secondary_langs)))
+ new_character.add_language(lang)
+
+ new_character.regenerate_icons()
+
+ new_character.update_transform()
+
+ to_chat(new_character, span_notice("You are a " + span_bold(JOB_MAINT_LURKER) + ", a loose end... you have no special advantages compared to the rest of the crew, so be cautious! You have spawned with an ID that will allow you free access to maintenance areas along with any of your chosen loadout items that are not role restricted, and can make use of anything you can find in maintenance."))
+ to_chat(new_character, span_critical("Please be advised, this role is " + span_bold("NOT AN ANTAGONIST.")))
+ to_chat(new_character, span_notice("Whoever or whatever your chosen character slot is, your role is to facilitate roleplay focused around that character; this role is not free license to attack and murder people without provocation or explicit out-of-character consent. You should probably be cautious around high-traffic and highly sensitive areas (e.g. Telecomms) as Security personnel would be well within their rights to treat you as a trespasser. That said, good luck!"))
+
+ new_character.visible_message(span_warning("[new_character] appears to crawl out of somewhere."))
+ qdel(src)
+
+/obj/structure/ghost_pod/ghost_activated/maint_lurker/Initialize()
+ ..()
+ if(!(src in active_ghost_pods))
+ active_ghost_pods += src
diff --git a/code/modules/client/preference_setup/antagonism/02_candidacy.dm b/code/modules/client/preference_setup/antagonism/02_candidacy.dm
index 1d6546f6fc..d3113373c9 100644
--- a/code/modules/client/preference_setup/antagonism/02_candidacy.dm
+++ b/code/modules/client/preference_setup/antagonism/02_candidacy.dm
@@ -21,10 +21,11 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set
//VOREStation Add
"lost drone" = 1, // 16
"maint pred" = 1, // 17
- "morph" = 1, // 18
- "corgi" = 1, // 19
- "cursed sword" = 1, // 20
- "Ship Survivor" = 1, // 21
+ "stowaway" = 1, // 18 // CHOMPEdit
+ "morph" = 1, // 19
+ "corgi" = 1, // 20
+ "cursed sword" = 1, // 21
+ "Ship Survivor" = 1, // 22
//VOREStation Add End
)
diff --git a/code/modules/events/maint_lurker.dm b/code/modules/events/maint_lurker.dm
new file mode 100644
index 0000000000..e82950fefb
--- /dev/null
+++ b/code/modules/events/maint_lurker.dm
@@ -0,0 +1,22 @@
+/datum/event/maintenance_lurker
+ startWhen = 1
+ endWhen = 30
+
+/datum/event/maintenance_lurker/start()
+
+ var/obj/effect/landmark/spawnspot = null
+ var/list/possibleSpawnspots = list()
+ for(var/obj/effect/landmark/L in landmarks_list)
+ if(L.name == "maint_pred")
+ possibleSpawnspots += L
+ if(possibleSpawnspots.len)
+ spawnspot = pick(possibleSpawnspots)
+ else
+ kill() // To prevent fake announcements
+ return
+
+ if(!spawnspot)
+ kill() // To prevent fake announcements
+ return
+
+ new /obj/structure/ghost_pod/ghost_activated/maint_lurker(get_turf(spawnspot))
diff --git a/maps/groundbase/groundbase_events.dm b/maps/groundbase/groundbase_events.dm
index 905ce89875..e12d41100d 100644
--- a/maps/groundbase/groundbase_events.dm
+++ b/maps/groundbase/groundbase_events.dm
@@ -70,6 +70,7 @@
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Drone Pod Drop", /datum/event/drone_pod_drop, 40, list(ASSIGNMENT_SCIENTIST = 40), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/morph_spawn, 75, list(ASSIGNMENT_ANY = 5), 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Predator", /datum/event/maintenance_predator, 100, list(ASSIGNMENT_ANY = 5), 0),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Lurker", /datum/event/maintenance_lurker, 100, list(ASSIGNMENT_ANY = 5), 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Roaming Wildlife", /datum/event/roaming_wildlife, 20, list(ASSIGNMENT_SECURITY = 20, ASSIGNMENT_MEDICAL = 5), min_jobs = list(ASSIGNMENT_SECURITY = 2)),
)
add_disabled_events(list(
diff --git a/maps/stellar_delight/stellar_delight_events.dm b/maps/stellar_delight/stellar_delight_events.dm
index 9511d67a04..d524b2bfcd 100644
--- a/maps/stellar_delight/stellar_delight_events.dm
+++ b/maps/stellar_delight/stellar_delight_events.dm
@@ -86,6 +86,7 @@
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Drone Pod Drop", /datum/event/drone_pod_drop, 40, list(ASSIGNMENT_SCIENTIST = 40), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/morph_spawn, 75, list(ASSIGNMENT_ANY = 5), 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Predator", /datum/event/maintenance_predator, 100, list(ASSIGNMENT_ANY = 5), 0),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Lurker", /datum/event/maintenance_lurker, 100, list(ASSIGNMENT_ANY = 5), 0),
)
add_disabled_events(list(
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Appendicitis", /datum/event/spontaneous_appendicitis, 0, list(ASSIGNMENT_MEDICAL = 30), 1),
diff --git a/maps/tether/tether_events.dm b/maps/tether/tether_events.dm
index 5ed863881a..543e6002f0 100644
--- a/maps/tether/tether_events.dm
+++ b/maps/tether/tether_events.dm
@@ -86,6 +86,7 @@
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Drone Pod Drop", /datum/event/drone_pod_drop, 40, list(ASSIGNMENT_SCIENTIST = 40), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/morph_spawn, 75, list(ASSIGNMENT_ANY = 5), 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Predator", /datum/event/maintenance_predator, 100, list(ASSIGNMENT_ANY = 5), 0),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Lurker", /datum/event/maintenance_lurker, 100, list(ASSIGNMENT_ANY = 5), 0),
)
add_disabled_events(list(
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Appendicitis", /datum/event/spontaneous_appendicitis, 0, list(ASSIGNMENT_MEDICAL = 30), 1),
diff --git a/modular_chomp/code/modules/event/event_container_ch.dm b/modular_chomp/code/modules/event/event_container_ch.dm
index 46906bd9e9..70a5eb74c0 100644
--- a/modular_chomp/code/modules/event/event_container_ch.dm
+++ b/modular_chomp/code/modules/event/event_container_ch.dm
@@ -87,6 +87,7 @@
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Ion Storm", /datum/event/ionstorm, -125, list(ASSIGNMENT_AI = 80, ASSIGNMENT_CYBORG = 50, ASSIGNMENT_ENGINEER = 15, ASSIGNMENT_SCIENTIST = 5), min_jobs = list(ASSIGNMENT_CYBORG = 3)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Jellyfish School", /datum/event/jellyfish_migration, 5, list(ASSIGNMENT_ANY = 1, ASSIGNMENT_SECURITY = 5, ASSIGNMENT_MEDICAL = 3), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Predator", /datum/event/maintenance_predator, 75, list(ASSIGNMENT_SECURITY = 25, ASSIGNMENT_SCIENTIST = 10), 1),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Lurker", /datum/event/maintenance_lurker, 100, list(ASSIGNMENT_ANY = 5), 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meaty Ore Shower", /datum/event/meteor_wave/meatyores, -50, list(ASSIGNMENT_ENGINEER = 45), 1, min_jobs = list(ASSIGNMENT_ENGINEER = 2)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meteor Shower", /datum/event/meteor_wave, -50, list(ASSIGNMENT_ENGINEER = 45), 1, min_jobs = list(ASSIGNMENT_ENGINEER = 2)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/morph_spawn, 75, list(ASSIGNMENT_ANY = 5), 0),
diff --git a/vorestation.dme b/vorestation.dme
index 60da402f84..017bafb781 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -2590,6 +2590,7 @@
#include "code\modules\events\infestation.dm"
#include "code\modules\events\ion_storm.dm"
#include "code\modules\events\jellyfish_migration.dm"
+#include "code\modules\events\maint_lurker.dm"
#include "code\modules\events\maintenance_predator_vr.dm"
#include "code\modules\events\meteor_strike_vr.dm"
#include "code\modules\events\meteors.dm"