You can spawn in as your static when taking a ghost role (#93809)

## About The Pull Request

When take a ghost role from a ghost role sleeper, if you became a ghost
by observing you will be offered the opportunity to spawn in as your
static. Obviously if you joined the round normally or have already
spawned in as a ghost role you won't be prompted. No cloning yourself
allowed.

Not every ghost role allows this, and you won't get the prompt if your
static is a race that breathes plasma (basically just those purple
skeletons) because that opens up a giant can of worms. However, you
_will_ get the prompt if you are playing as any other race. (I'm pretty
sure every ghost role has power for ethereals besides ashwalkers but
that's not one of the ghost roles that lets you spawn as your static for
super obvious reasons)

Some ghost roles, like pirates, will allow you to spawn in as your
static but overwrite your name.

## Why It's Good For The Game

Felinid comms agent felinid comms agent felinid comms agent felinid
comms agent felinid comms agent felinid comms agent felinid comms agent
felinid comms agent felinid comms agent felinid comms agent felinid
comms agent felinid comms agent felinid comms agent felinid comms agent

## Changelog
🆑
add: You may now spawn in as your static when picking a ghost role
/🆑

---------

Co-authored-by: Fghj240 <fakeemail@notrealemail.com>
This commit is contained in:
Fghj240
2025-11-13 22:33:16 -07:00
committed by GitHub
co-authored by Fghj240
parent 51997797d1
commit c3d08e5da9
9 changed files with 56 additions and 2 deletions
@@ -6,6 +6,7 @@
flavour_text = "Write me some god damn flavor text!" //the flavor text will be the backstory argument called on the antagonist's greet, see hunter.dm for details
show_flavor = FALSE
var/back_story = "error"
allow_custom_character = GHOSTROLE_ALLOW_OTHER
/obj/effect/mob_spawn/ghost_role/human/fugitive/special(mob/living/carbon/human/spawned_human, mob/mob_possessor)
. = ..()
@@ -14,6 +14,7 @@
the hostile creatures, and the ash drakes swooping down from the cloudless skies, all you can wish for is the feel of soft grass between your toes and \
the fresh air of Earth. These thoughts are dispelled by yet another recollection of how you got here... "
spawner_job_path = /datum/job/hermit
allow_custom_character = ALL
/obj/effect/mob_spawn/ghost_role/human/hermit/Initialize(mapload)
. = ..()
@@ -79,12 +80,14 @@
flavour_text = "Ch'yea. You came here, like, on spring break, hopin' to pick up some bangin' hot chicks, y'knaw?"
spawner_job_path = /datum/job/beach_bum
outfit = /datum/outfit/beachbum
allow_custom_character = GHOSTROLE_ALLOW_OTHER
/obj/effect/mob_spawn/ghost_role/human/beach/lifeguard
you_are_text = "You're a spunky lifeguard!"
flavour_text = "It's up to you to make sure nobody drowns or gets eaten by sharks and stuff."
name = "lifeguard sleeper"
outfit = /datum/outfit/beachbum/lifeguard
allow_custom_character = NONE
/obj/effect/mob_spawn/ghost_role/human/beach/lifeguard/special(mob/living/carbon/human/lifeguard, mob/mob_possessor)
. = ..()
@@ -119,6 +122,7 @@
flavour_text = "Time to mix drinks and change lives. Smoking space drugs makes it easier to understand your patrons' odd dialect."
spawner_job_path = /datum/job/space_bartender
outfit = /datum/outfit/spacebartender
allow_custom_character = ALL
/datum/outfit/spacebartender
name = "Space Bartender"
@@ -284,6 +288,7 @@
outfit = /datum/outfit/lavaland_syndicate
spawner_job_path = /datum/job/lavaland_syndicate
deletes_on_zero_uses_left = FALSE
allow_custom_character = ALL
/obj/effect/mob_spawn/ghost_role/human/lavaland_syndicate/special(mob/living/new_spawn, mob/mob_possessor)
. = ..()
@@ -14,6 +14,7 @@
important_text = "Work as a team with your fellow survivors and do not abandon them."
outfit = /datum/outfit/oldeng
spawner_job_path = /datum/job/ancient_crew
allow_custom_character = GHOSTROLE_ALLOW_OTHER
/obj/effect/mob_spawn/ghost_role/human/oldstation/create_from_ghost(mob/dead/user)
. = ..()
@@ -102,6 +103,7 @@
outfit = /datum/outfit/syndicate_empty/battlecruiser
spawner_job_path = /datum/job/battlecruiser_crew
uses = 4
allow_custom_character = ALL
/// The antag team to apply the player to
var/datum/team/antag_team
@@ -191,6 +193,7 @@
important_text = "Work as a team with your fellow actors and the director to make entertainment for the masses."
outfit = /datum/outfit/actor
spawner_job_path = /datum/job/ghost_role
allow_custom_character = ALL
/datum/outfit/actor
name = "Actor"
@@ -215,6 +218,7 @@
important_text = "Work as a team with your fellow actors and the director to make entertainment for the masses."
outfit = /datum/outfit/actor/director
spawner_job_path = /datum/job/ghost_role
allow_custom_character = ALL
/datum/outfit/actor/director
name = "Director"
@@ -12,6 +12,7 @@
though fate has other plans for you."
flavour_text = "Good. It seems as though your ship crashed. You remember that you were convicted of "
spawner_job_path = /datum/job/escaped_prisoner
allow_custom_character = GHOSTROLE_ALLOW_OTHER
/obj/effect/mob_spawn/ghost_role/human/prisoner_transport/Initialize(mapload)
. = ..()
@@ -50,6 +51,7 @@
flavour_text = "Cater to visiting guests with your fellow staff, advertise the hotel, and make sure the manager doesn't fire you. Remember, the customer is always right!"
important_text = "Do NOT leave the hotel, as that is grounds for contract termination."
spawner_job_path = /datum/job/hotel_staff
allow_custom_character = ALL
/datum/outfit/hotelstaff
name = "Hotel Staff"
@@ -94,6 +96,7 @@
flavour_text = "You have awoken, without instruction. Death to Nanotrasen! If there are some clues around as to what you're supposed to be doing, you best follow those."
outfit = /datum/outfit/syndicate_empty
spawner_job_path = /datum/job/space_syndicate
allow_custom_character = ALL
/datum/outfit/syndicate_empty
name = "Syndicate Operative Empty"
@@ -119,6 +122,7 @@
flavour_text = "Hang out at the bar and chat with your buddies. Feel free to hop back in the cryogenics when you're done chatting."
outfit = /datum/outfit/cryobartender
spawner_job_path = /datum/job/space_bar_patron
allow_custom_character = ALL
/obj/effect/mob_spawn/ghost_role/human/space_bar_patron/attack_hand(mob/user, list/modifiers)
var/despawn = tgui_alert(usr, "Return to cryosleep? (Warning, Your mob will be deleted!)", null, list("Yes", "No"))
@@ -178,6 +182,7 @@
you_are_text = "You are a Nanotrasen Private Security Officer!"
flavour_text = "If higher command has an assignment for you, it's best you follow that. Otherwise, death to The Syndicate."
outfit = /datum/outfit/nanotrasensoldier
allow_custom_character = ALL
/obj/effect/mob_spawn/ghost_role/human/commander
name = "sleeper"
@@ -187,6 +192,7 @@
you_are_text = "You are a Nanotrasen Commander!"
flavour_text = "Upper-crusty of Nanotrasen. You should be given the respect you're owed."
outfit = /datum/outfit/nanotrasencommander
allow_custom_character = GHOSTROLE_ALLOW_OTHER
//space doctor, a rat with cancer, and bessie from an old removed lavaland ruin.
@@ -199,6 +205,7 @@
flavour_text = "It's your job- no, your duty as a doctor, to care and heal those in need."
outfit = /datum/outfit/job/doctor
spawner_job_path = /datum/job/space_doctor
allow_custom_character = ALL
/obj/effect/mob_spawn/ghost_role/human/doctor/alive/equip(mob/living/carbon/human/doctor)
. = ..()
@@ -244,6 +251,7 @@
flavour_text = "Monitor Nanotrasen communications and record information. All intruders should be disposed of \
swiftly to assure no gathered information is stolen or lost. Try not to wander too far from the outpost as the \
caves can be a deadly place even for a trained operative such as yourself."
allow_custom_character = ALL
/datum/outfit/snowsyndie
name = "Syndicate Snow Operative"
@@ -269,6 +277,7 @@
important_text = "Obey orders given by your captain. DO NOT let the ship fall into enemy hands."
outfit = /datum/outfit/syndicatespace/syndicrew
spawner_job_path = /datum/job/syndicate_cybersun
allow_custom_character = ALL
/obj/effect/mob_spawn/ghost_role/human/syndicatespace/special(mob/living/new_spawn, mob/mob_possessor)
. = ..()
@@ -286,6 +295,7 @@
important_text = "Protect the ship and secret documents in your backpack with your own life."
outfit = /datum/outfit/syndicatespace/syndicaptain
spawner_job_path = /datum/job/syndicate_cybersun_captain
allow_custom_character = ALL
/obj/effect/mob_spawn/ghost_role/human/syndicatespace/captain/Destroy()
new /obj/structure/fluff/empty_sleeper/syndicate/captain(get_turf(src))
+20 -2
View File
@@ -114,6 +114,8 @@
/// A list of the ckeys that currently are trying to access this spawner, so that they can't try to spawn more than once (in case there's sleeps).
/// Static because you only really want to be able to spawn in one spawner at a time, obviously.
var/static/list/ckeys_trying_to_spawn
///bitflag that determines if players can spawn in as their statics
var/allow_custom_character = NONE
////descriptions
@@ -206,7 +208,7 @@
* If you are manually forcing a player into this mob spawn,
* you should be using this and not directly calling [proc/create].
*/
/obj/effect/mob_spawn/ghost_role/proc/create_from_ghost(mob/dead/user)
/obj/effect/mob_spawn/ghost_role/proc/create_from_ghost(mob/dead/observer/user)
ASSERT(istype(user))
var/user_ckey = user.ckey // We need to do it before everything else, because after the create() the ckey will already have been transferred.
@@ -214,6 +216,15 @@
uses -= 1 // Remove a use before trying to spawn to prevent strangeness like the spawner trying to spawn more mobs than it should be able to
if(!temp_body)
user.mind = null // dissassociate mind, don't let it follow us to the next life
var/species_pref = user.client.prefs.read_preference(/datum/preference/choiced/species)
var/datum/species/user_species = GLOB.species_prototypes[species_pref]
if(user_species.inherent_respiration_type == RESPIRATION_PLASMA) // Stupid flammable skeletons...
user.started_as_observer = null
else if(user.started_as_observer && allow_custom_character)
var/static_prompt = "Because you haven't taken a role so far, you may spawn in as [(allow_custom_character & GHOSTROLE_ALLOW_SPECIES || user_species == /datum/species/human) ? "" : "a human version of"] your customized character with a random name. Would you like to?"
var/static_prompt_result = tgui_alert(user, static_prompt, "Custom Character", list("Yes", "No"), 10 SECONDS)
if(static_prompt_result != "Yes")
user.started_as_observer = null
var/created = create(user)
LAZYREMOVE(ckeys_trying_to_spawn, user_ckey) // We do this AFTER the create() so that we're basically sure that the user won't be in their ghost body anymore, so they can't click on the spawner again.
@@ -239,6 +250,14 @@
/obj/effect/mob_spawn/ghost_role/special(mob/living/spawned_mob, mob/mob_possessor)
. = ..()
if(mob_possessor)
var/mob/dead/observer/observer_possessor = mob_possessor
if(observer_possessor.started_as_observer)
var/old_name = spawned_mob.real_name
if(allow_custom_character & GHOSTROLE_ALLOW_OTHER)
mob_possessor.client.prefs.safe_transfer_prefs_to(spawned_mob)
spawned_mob.fully_replace_character_name(newname = old_name)
if(!(allow_custom_character & GHOSTROLE_ALLOW_SPECIES || ishumanbasic(spawned_mob)))
spawned_mob.set_species(/datum/species/human)
if(mob_possessor.mind)
mob_possessor.mind.transfer_to(spawned_mob, force_key_move = TRUE)
else
@@ -247,7 +266,6 @@
if(spawned_mind)
spawned_mob.mind.set_assigned_role_with_greeting(SSjob.get_job_type(spawner_job_path))
spawned_mind.name = spawned_mob.real_name
if(show_flavor)
var/output_message = span_infoplain("<span class='big bold'>[you_are_text]</span>")
if(flavour_text != "")