mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 13:10:02 +01:00
Fixes human skeleton pirates, Refactors ghost spawns (#94138)
## About The Pull Request `create_from_ghost` can be called from stuff like... dynamic executing a ruleset, so putting a sleep/user input within it causes problems So I refactored ghost spawns a fair bit, creating a clear delineation between where you can and can't put user input ## Changelog 🆑 Melbert fix: Pirates will no longer randomly spawn as human fix: Servant Golems have numbered names again refactor: Refactored ghost spawns (like spider eggs or pirate spawners), report any oddities /🆑
This commit is contained in:
@@ -59,15 +59,15 @@
|
||||
outfit = /datum/outfit/job/assistant
|
||||
icon_state = "corpsegreytider"
|
||||
|
||||
/obj/effect/mob_spawn/corpse/human/assistant/beesease_infection/special(mob/living/spawned_mob, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/corpse/human/assistant/beesease_infection/special(mob/living/spawned_mob, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_mob.ForceContractDisease(new /datum/disease/beesease)
|
||||
|
||||
/obj/effect/mob_spawn/corpse/human/assistant/brainrot_infection/special(mob/living/spawned_mob, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/corpse/human/assistant/brainrot_infection/special(mob/living/spawned_mob, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_mob.ForceContractDisease(new /datum/disease/brainrot)
|
||||
|
||||
/obj/effect/mob_spawn/corpse/human/assistant/spanishflu_infection/special(mob/living/spawned_mob, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/corpse/human/assistant/spanishflu_infection/special(mob/living/spawned_mob, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_mob.ForceContractDisease(new /datum/disease/fluspanish)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
burn_damage = 1000
|
||||
mob_species = /datum/species/skeleton
|
||||
|
||||
/obj/effect/mob_spawn/corpse/human/charredskeleton/special(mob/living/carbon/human/spawned_human, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/corpse/human/charredskeleton/special(mob/living/carbon/human/spawned_human, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_human.color = "#454545"
|
||||
spawned_human.gender = NEUTER
|
||||
@@ -34,7 +34,7 @@
|
||||
outfit = select_outfit()
|
||||
return ..()
|
||||
|
||||
/obj/effect/mob_spawn/corpse/human/legioninfested/special(mob/living/carbon/human/spawned_human, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/corpse/human/legioninfested/special(mob/living/carbon/human/spawned_human, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
var/obj/item/organ/legion_tumour/cancer = new()
|
||||
cancer.Insert(spawned_human, special = TRUE, movement_flags = DELETE_IF_REPLACED)
|
||||
@@ -75,7 +75,7 @@
|
||||
/// Corpse spawner used by dwarf legions to make small corpses
|
||||
/obj/effect/mob_spawn/corpse/human/legioninfested/dwarf
|
||||
|
||||
/obj/effect/mob_spawn/corpse/human/legioninfested/dwarf/special(mob/living/carbon/human/spawned_human, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/corpse/human/legioninfested/dwarf/special(mob/living/carbon/human/spawned_human, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_human.dna.add_mutation(/datum/mutation/dwarfism, MUTATION_SOURCE_MUTATOR)
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
/obj/effect/mob_spawn/corpse/human/legioninfested/skeleton/select_outfit()
|
||||
return null
|
||||
|
||||
/obj/effect/mob_spawn/corpse/human/legioninfested/skeleton/special(mob/living/carbon/human/spawned_human, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/corpse/human/legioninfested/skeleton/special(mob/living/carbon/human/spawned_human, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_human.gender = NEUTER
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
brute_damage = 0
|
||||
burn_damage = 1000
|
||||
|
||||
/obj/effect/mob_spawn/corpse/human/legioninfested/skeleton/charred/special(mob/living/carbon/human/spawned_human, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/corpse/human/legioninfested/skeleton/charred/special(mob/living/carbon/human/spawned_human, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_human.color = "#454545"
|
||||
spawned_human.AddComponent(/datum/component/storm_hating)
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
outfit = /datum/outfit/centcom/centcom_intern/unarmed
|
||||
mob_name = "Nameless Intern"
|
||||
|
||||
/obj/effect/mob_spawn/corpse/human/intern/special(mob/living/carbon/human/spawned_human, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/corpse/human/intern/special(mob/living/carbon/human/spawned_human, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_human.gender = MALE //we're making it canon babies
|
||||
spawned_human.update_body()
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
/obj/effect/mob_spawn/corpse/ai
|
||||
mob_type = /mob/living/silicon/ai/spawned
|
||||
|
||||
/obj/effect/mob_spawn/corpse/ai/create(mob/user, newname)
|
||||
/obj/effect/mob_spawn/corpse/ai/create(mob/user, newname, apply_prefs)
|
||||
var/ai_already_present = locate(/mob/living/silicon/ai) in loc
|
||||
if(ai_already_present)
|
||||
return
|
||||
. = ..()
|
||||
return CANCEL_SPAWN
|
||||
return ..()
|
||||
|
||||
/obj/effect/mob_spawn/corpse/ai/special(mob/living/silicon/ai/spawned/dead_ai, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/corpse/ai/special(mob/living/silicon/ai/spawned/dead_ai, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
dead_ai.name = src.name
|
||||
dead_ai.real_name = src.name
|
||||
@@ -24,7 +24,7 @@
|
||||
///the color of the slime you're spawning.
|
||||
var/slime_species = /datum/slime_type/grey
|
||||
|
||||
/obj/effect/mob_spawn/corpse/slime/special(mob/living/basic/slime/spawned_slime, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/corpse/slime/special(mob/living/basic/slime/spawned_slime, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_slime.set_slime_type(slime_species)
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
//mostly for unit tests to not get alarmed (which by all means it should because this is a mess)
|
||||
mob_type = /obj/item/clothing/mask/facehugger
|
||||
|
||||
/obj/effect/mob_spawn/corpse/facehugger/create(mob/user)
|
||||
/obj/effect/mob_spawn/corpse/facehugger/create(mob/user, newname, apply_prefs)
|
||||
var/obj/item/clothing/mask/facehugger/spawned_facehugger = new mob_type(loc)
|
||||
spawned_facehugger.Die()
|
||||
qdel(src)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
flavour_text = "Walk this mortal plane and terrorize all living adventurers who dare cross your path."
|
||||
spawner_job_path = /datum/job/skeleton
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/skeleton/special(mob/living/new_spawn, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/ghost_role/human/skeleton/special(mob/living/new_spawn, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
to_chat(new_spawn, "<b>You have this horrible lurching feeling deep down that your binding to this world will fail if you abandon this zone... Were you reanimated to protect something?</b>")
|
||||
new_spawn.AddComponent(/datum/component/stationstuck, PUNISHMENT_MURDER, "You experience a feeling like a stressed twine being pulled until it snaps. Then, merciful nothing.")
|
||||
@@ -30,7 +30,7 @@
|
||||
you_are_text = "By unknown powers, your rotting remains have been resurrected!"
|
||||
flavour_text = "Walk this mortal plane and terrorize all living adventurers who dare cross your path."
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/zombie/special(mob/living/new_spawn, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/ghost_role/human/zombie/special(mob/living/new_spawn, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
to_chat(new_spawn, "<b>You have this horrible lurching feeling deep down that your binding to this world will fail if you abandon this zone... Were you reanimated to protect something?</b>")
|
||||
new_spawn.AddComponent(/datum/component/stationstuck, PUNISHMENT_MURDER, "You experience a feeling like a stressed twine being pulled until it snaps. Then, merciful nothing.")
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
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
|
||||
allow_custom_character = GHOSTROLE_TAKE_PREFS_APPEARANCE
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/fugitive/special(mob/living/carbon/human/spawned_human, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/ghost_role/human/fugitive/special(mob/living/carbon/human/spawned_human, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
var/datum/antagonist/fugitive_hunter/fughunter = new
|
||||
fughunter.backstory = back_story
|
||||
|
||||
@@ -32,14 +32,7 @@
|
||||
notify_flags = NOTIFY_CATEGORY_NOFLASH,
|
||||
)
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/golem/name_mob(mob/living/spawned_mob, forced_name)
|
||||
if(forced_name || !iscarbon(spawned_mob))
|
||||
return ..()
|
||||
|
||||
forced_name = generate_random_name_species_based(spawned_mob.gender, TRUE, species_type = /datum/species/golem)
|
||||
return ..()
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/golem/special(mob/living/new_spawn, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/ghost_role/human/golem/special(mob/living/new_spawn, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
if(is_path_in_list(initial_type, GLOB.golem_stack_food_directory))
|
||||
var/datum/golem_food_buff/initial_buff = GLOB.golem_stack_food_directory[initial_type]
|
||||
@@ -73,7 +66,7 @@
|
||||
desc = "A humanoid shape, empty, lifeless, and full of potential."
|
||||
prompt_name = "a free golem"
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/golem/adamantine/special(mob/living/new_spawn, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/ghost_role/human/golem/adamantine/special(mob/living/new_spawn, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
if(!ishuman(new_spawn))
|
||||
return
|
||||
@@ -110,8 +103,6 @@
|
||||
to_chat(new_spawn, span_userdanger("Serve [real_owner.real_name], and assist [real_owner.p_them()] in completing [real_owner.p_their()] goals at any cost."))
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/golem/servant/name_mob(mob/living/spawned_mob, forced_name)
|
||||
if(forced_name || !iscarbon(spawned_mob))
|
||||
return ..()
|
||||
if(owner_ref?.resolve())
|
||||
forced_name = "Golem ([rand(1,999)])"
|
||||
return ..()
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
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
|
||||
allow_custom_character = GHOSTROLE_TAKE_PREFS_APPEARANCE
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/beach/lifeguard
|
||||
you_are_text = "You're a spunky lifeguard!"
|
||||
@@ -89,7 +89,7 @@
|
||||
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)
|
||||
/obj/effect/mob_spawn/ghost_role/human/beach/lifeguard/special(mob/living/carbon/human/lifeguard, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
lifeguard.gender = FEMALE
|
||||
lifeguard.update_body()
|
||||
@@ -237,7 +237,7 @@
|
||||
to_chat(user, span_warning("You have exhausted your usefulness to the Necropolis."))
|
||||
return FALSE
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/ash_walker/special(mob/living/carbon/human/spawned_human, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/ghost_role/human/ash_walker/special(mob/living/carbon/human/spawned_human, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_human.fully_replace_character_name(null, spawned_human.generate_random_mob_name(TRUE))
|
||||
to_chat(spawned_human, "<b>Drag the corpses of men and beasts to your nest. It will absorb them to create more of your kind. Invade the strange structure of the outsiders if you must. Do not cause unnecessary destruction, as littering the wastes with ugly wreckage is certain to not gain you favor. Glory to the Necropolis!</b>")
|
||||
@@ -290,7 +290,7 @@
|
||||
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)
|
||||
/obj/effect/mob_spawn/ghost_role/human/lavaland_syndicate/special(mob/living/new_spawn, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
new_spawn.grant_language(/datum/language/codespeak, source = LANGUAGE_MIND)
|
||||
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
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
|
||||
allow_custom_character = GHOSTROLE_TAKE_PREFS_APPEARANCE
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/oldstation/create_from_ghost(mob/dead/user)
|
||||
/obj/effect/mob_spawn/ghost_role/human/oldstation/create(mob/mob_possessor, newname, apply_prefs)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
notify_ghosts(
|
||||
"Someone just woke up on Charlie Station! Why not join them and help out?",
|
||||
source = ., //the spawned mob
|
||||
|
||||
@@ -139,8 +139,9 @@
|
||||
if(!silent)
|
||||
to_chat(user, span_warning("\The [src] is not ready to hatch yet!"))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/spider/special(mob/living/basic/spider/spawned_mob, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/ghost_role/spider/special(mob/living/basic/spider/spawned_mob, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
if (isspider(spawned_mob))
|
||||
spawned_mob.directive = directive
|
||||
@@ -197,21 +198,12 @@
|
||||
)
|
||||
flash_window = TRUE
|
||||
|
||||
/**
|
||||
* Makes a ghost into a spider based on the type of egg cluster.
|
||||
*
|
||||
* Allows a ghost to get a prompt to use the egg cluster to become a spider.
|
||||
*
|
||||
* Arguments:
|
||||
* * user - The ghost attempting to become a spider
|
||||
* * newname - If set, renames the mob to this name
|
||||
*/
|
||||
/obj/effect/mob_spawn/ghost_role/spider/create(mob/user, newname)
|
||||
/obj/effect/mob_spawn/ghost_role/spider/pre_ghost_take(mob/dead/observer/user)
|
||||
var/chosen_spider = length(potentialspawns) > 1 ? get_radial_choice(user) : potentialspawns[1]
|
||||
if(QDELETED(src) || QDELETED(user) || isnull(chosen_spider))
|
||||
if(isnull(chosen_spider))
|
||||
return FALSE
|
||||
mob_type = chosen_spider
|
||||
return ..()
|
||||
return TRUE
|
||||
|
||||
/// Pick a spider type from a radial menu
|
||||
/obj/effect/mob_spawn/ghost_role/spider/proc/get_radial_choice(mob/user)
|
||||
|
||||
@@ -12,7 +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
|
||||
allow_custom_character = GHOSTROLE_TAKE_PREFS_APPEARANCE
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/prisoner_transport/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -25,7 +25,7 @@
|
||||
new /obj/structure/fluff/empty_sleeper/syndicate(get_turf(src))
|
||||
return ..()
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/prisoner_transport/special(mob/living/carbon/human/spawned_human, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/ghost_role/human/prisoner_transport/special(mob/living/carbon/human/spawned_human, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_human.fully_replace_character_name(null, "NTP #LL-0[rand(111,999)]") //Nanotrasen Prisoner #Lavaland-(numbers)
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
new/obj/structure/fluff/empty_sleeper(get_turf(src))
|
||||
return ..()
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/human/exile/special(mob/living/new_spawn, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/ghost_role/human/exile/special(mob/living/new_spawn, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
new_spawn.fully_replace_character_name(null,"Wish Granter's Victim ([rand(1,999)])")
|
||||
var/wish = rand(1,4)
|
||||
@@ -192,7 +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
|
||||
allow_custom_character = GHOSTROLE_TAKE_PREFS_APPEARANCE
|
||||
|
||||
//space doctor, a rat with cancer, and bessie from an old removed lavaland ruin.
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
icon = 'icons/obj/machines/sleeper.dmi'
|
||||
icon_state = "sleeper"
|
||||
|
||||
/obj/effect/mob_spawn/cow/special(mob/living/spawned_mob, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/cow/special(mob/living/spawned_mob, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
gender = FEMALE
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
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)
|
||||
/obj/effect/mob_spawn/ghost_role/human/syndicatespace/special(mob/living/new_spawn, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
new_spawn.grant_language(/datum/language/codespeak, source = LANGUAGE_MIND)
|
||||
var/datum/job/spawn_job = SSjob.get_job_type(spawner_job_path)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
if(flower_bud.trait_flags & SPACEVINE_COLD_RESISTANT)
|
||||
spawned_human_trap.unsuitable_cold_damage = 0
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/venus_human_trap/special(mob/living/spawned_mob, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/ghost_role/venus_human_trap/special(mob/living/spawned_mob, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_mob.mind.add_antag_datum(/datum/antagonist/venus_human_trap)
|
||||
|
||||
@@ -54,3 +54,4 @@
|
||||
if(!silent)
|
||||
to_chat(user, span_warning("\The [src] has not borne fruit yet!"))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -44,16 +44,36 @@
|
||||
QDEL_NULL(outfit)
|
||||
return ..()
|
||||
|
||||
/// Creates whatever mob the spawner makes. Return FALSE if we want to exit from here without doing that, returning NULL will be logged to admins.
|
||||
/obj/effect/mob_spawn/proc/create(mob/mob_possessor, newname)
|
||||
/**
|
||||
* Creates whatever mob the spawner makes.
|
||||
*
|
||||
* * mob_possessor - The ghost/mob that is possessing this mob, if applicable
|
||||
* * newname - A forced name for the mob, if applicable
|
||||
* * apply_prefs - Whether we should apply the possessor's preferences to the mob, if applicable
|
||||
*
|
||||
* Returns
|
||||
* - the created mob
|
||||
* - CANCEL_SPAWN if the spawn process should be stopped
|
||||
* - null if the spawn failed (and something went wrong)
|
||||
*/
|
||||
/obj/effect/mob_spawn/proc/create(mob/mob_possessor, newname, apply_prefs)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
var/mob/living/spawned_mob = new mob_type(get_turf(src)) //living mobs only
|
||||
special(spawned_mob, mob_possessor, apply_prefs)
|
||||
name_mob(spawned_mob, newname)
|
||||
special(spawned_mob, mob_possessor)
|
||||
equip(spawned_mob)
|
||||
spawned_mob_ref = WEAKREF(spawned_mob)
|
||||
return spawned_mob
|
||||
|
||||
/obj/effect/mob_spawn/proc/special(mob/living/spawned_mob, mob/mob_possessor)
|
||||
/**
|
||||
* Any special behavior that needs to be done to the mob after it's created but before it's equipped.
|
||||
*
|
||||
* * spawned_mob - The mob that was created
|
||||
* * mob_possessor - The ghost/mob that is possessing this mob, if applicable
|
||||
* * apply_prefs - Whether we should apply the possessor's preferences to the mob, if applicable
|
||||
*/
|
||||
/obj/effect/mob_spawn/proc/special(mob/living/spawned_mob, mob/mob_possessor, apply_prefs)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(faction)
|
||||
spawned_mob.faction = faction
|
||||
@@ -111,9 +131,6 @@
|
||||
var/uses = 1
|
||||
/// Does the spawner delete itself when it runs out of uses?
|
||||
var/deletes_on_zero_uses_left = TRUE
|
||||
/// 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
|
||||
|
||||
@@ -154,51 +171,64 @@
|
||||
|
||||
//ATTACK GHOST IGNORING PARENT RETURN VALUE
|
||||
/obj/effect/mob_spawn/ghost_role/attack_ghost(mob/dead/observer/user)
|
||||
if(!SSticker.HasRoundStarted() || !loc)
|
||||
if(!SSticker.HasRoundStarted() || isnull(loc) || QDELETED(src))
|
||||
return
|
||||
|
||||
// We don't open the prompt more than once at a time.
|
||||
// Lazylist of the ckeys that currently are trying to access any spawner, so that they can't try to spawn more than once (in case there's sleeps).
|
||||
var/static/list/ckeys_trying_to_spawn
|
||||
if(LAZYFIND(ckeys_trying_to_spawn, user.ckey))
|
||||
return
|
||||
if(uses <= 0 && !infinite_use)
|
||||
to_chat(user, span_warning("This spawner is out of charges!"))
|
||||
return FALSE
|
||||
if(!can_ghost_take(user))
|
||||
return FALSE
|
||||
|
||||
uses -= 1 // Remove a use EARLY to account for sleep / inputs
|
||||
var/user_ckey = user.ckey // Just in case shenanigans happen, we always want to remove it from the list.
|
||||
LAZYADD(ckeys_trying_to_spawn, user_ckey)
|
||||
|
||||
var/prompt_fail = FALSE
|
||||
var/apply_prefs = FALSE
|
||||
if(prompt_ghost)
|
||||
var/prompt = "Become [prompt_name]?"
|
||||
if(!temp_body && user.can_reenter_corpse && user.mind)
|
||||
prompt += " (Warning, You can no longer be revived!)"
|
||||
var/ghost_role = tgui_alert(usr, prompt, buttons = list("Yes", "No"), timeout = 10 SECONDS)
|
||||
if(ghost_role != "Yes" || !loc || QDELETED(user))
|
||||
LAZYREMOVE(ckeys_trying_to_spawn, user_ckey)
|
||||
return
|
||||
prompt_fail = tgui_alert(user, prompt, buttons = list("Yes", "No"), timeout = 10 SECONDS) != "Yes"
|
||||
|
||||
if(!(GLOB.ghost_role_flags & GHOSTROLE_SPAWNER) && !(flags_1 & ADMIN_SPAWNED_1))
|
||||
to_chat(user, span_warning("An admin has temporarily disabled non-admin ghost roles!"))
|
||||
LAZYREMOVE(ckeys_trying_to_spawn, user_ckey)
|
||||
return
|
||||
if(uses <= 0 && !infinite_use) //just in case
|
||||
to_chat(user, span_warning("This spawner is out of charges!"))
|
||||
LAZYREMOVE(ckeys_trying_to_spawn, user_ckey)
|
||||
return
|
||||
var/species_pref = user.client.prefs.read_preference(/datum/preference/choiced/species) || /datum/species/human
|
||||
if(!prompt_fail && user.started_as_observer && allow_custom_character && (GLOB.species_prototypes[species_pref].inherent_respiration_type & RESPIRATION_OXYGEN))
|
||||
var/static_prompt = "Because you haven't taken a role so far, you may spawn in as \
|
||||
[((allow_custom_character & GHOSTROLE_TAKE_PREFS_SPECIES) || species_pref == /datum/species/human) ? "" : "a human version of"] \
|
||||
your customized character with a random name. Would you like to?"
|
||||
apply_prefs = tgui_alert(user, static_prompt, "Custom Character", list("Yes", "No"), 10 SECONDS) == "Yes"
|
||||
|
||||
if(!prompt_fail && !pre_ghost_take(user))
|
||||
prompt_fail = TRUE
|
||||
|
||||
if(prompt_fail || !can_ghost_take(user) || !create_from_ghost(user, apply_prefs, subtract_uses = FALSE))
|
||||
uses += 1
|
||||
LAZYREMOVE(ckeys_trying_to_spawn, user_ckey)
|
||||
|
||||
/// Allows for modifications before the ghost is turned into a mob.
|
||||
/// You can put sleeps or inputs in here, sanity checking is done for you after this proc returns.
|
||||
/// Returning FALSE will cancel the spawn process.
|
||||
/obj/effect/mob_spawn/ghost_role/proc/pre_ghost_take(mob/dead/observer/user)
|
||||
return TRUE
|
||||
|
||||
/// Checks if a ghost can take this ghost role.
|
||||
/obj/effect/mob_spawn/ghost_role/proc/can_ghost_take(mob/dead/observer/user)
|
||||
if(is_banned_from(user.ckey, role_ban))
|
||||
to_chat(user, span_warning("You are banned from this role!"))
|
||||
LAZYREMOVE(ckeys_trying_to_spawn, user_ckey)
|
||||
return
|
||||
if(!allow_spawn(user, silent = FALSE))
|
||||
LAZYREMOVE(ckeys_trying_to_spawn, user_ckey)
|
||||
return
|
||||
return FALL_STOP_INTERCEPTING
|
||||
if(!(GLOB.ghost_role_flags & GHOSTROLE_SPAWNER) && !(flags_1 & ADMIN_SPAWNED_1))
|
||||
to_chat(user, span_warning("An admin has temporarily disabled non-admin ghost roles!"))
|
||||
return FALSE
|
||||
if(QDELETED(src) || QDELETED(user))
|
||||
LAZYREMOVE(ckeys_trying_to_spawn, user_ckey)
|
||||
return
|
||||
|
||||
if(uses <= 0 && !infinite_use) // Just in case something took longer than it should've and we got here after the uses went below zero.
|
||||
to_chat(user, span_warning("This spawner is out of charges!"))
|
||||
LAZYREMOVE(ckeys_trying_to_spawn, user_ckey)
|
||||
return
|
||||
|
||||
create_from_ghost(user)
|
||||
return FALSE
|
||||
if(!allow_spawn(user, silent = FALSE))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Uses a use and creates a mob from a passed ghost
|
||||
@@ -207,61 +237,53 @@
|
||||
*
|
||||
* If you are manually forcing a player into this mob spawn,
|
||||
* you should be using this and not directly calling [proc/create].
|
||||
*
|
||||
* * * user - The ghost/mob that is possessing this mob
|
||||
* * * apply_prefs - Whether we should apply the possessor's preferences to the mob
|
||||
* * * subtract_uses - Whether to subtract a use from the spawner.
|
||||
* Set to FALSE if you want to handle uses manually elsewhere.
|
||||
*/
|
||||
/obj/effect/mob_spawn/ghost_role/proc/create_from_ghost(mob/dead/observer/user)
|
||||
/obj/effect/mob_spawn/ghost_role/proc/create_from_ghost(mob/dead/observer/user, apply_prefs, subtract_uses = TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
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.
|
||||
|
||||
user.log_message("became a [prompt_name].", LOG_GAME)
|
||||
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.
|
||||
|
||||
if(!created)
|
||||
uses += 1 // Refund use because we didn't actually spawn anything
|
||||
|
||||
if(isnull(created)) // If we explicitly return FALSE instead of just not returning a mob, we don't want to spam the admins
|
||||
CRASH("An instance of [type] didn't return anything when creating a mob, this might be broken!")
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_GHOSTROLE_SPAWNED, created)
|
||||
check_uses() // Now we check if the spawner should delete itself or not
|
||||
var/mob/created = create(user, apply_prefs = apply_prefs)
|
||||
if(ismob(created))
|
||||
SEND_SIGNAL(src, COMSIG_GHOSTROLE_SPAWNED, created)
|
||||
if(subtract_uses)
|
||||
uses -= 1
|
||||
check_uses()
|
||||
else if(isnull(created)) // null instead of explicit CANCEL_SPAWN means something went wrong
|
||||
CRASH("An instance of [type] didn't return anything when creating a mob, this might be broken!")
|
||||
|
||||
return created
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/create(mob/mob_possessor, newname)
|
||||
/obj/effect/mob_spawn/ghost_role/create(mob/mob_possessor, newname, apply_prefs)
|
||||
if(!mob_possessor.key) // This is in the scenario that the server is somehow lagging, or someone fucked up their code, and we try to spawn the same person in twice. We'll simply not spawn anything and CRASH(), so that we report what happened.
|
||||
CRASH("Attempted to create an instance of [type] with a mob that had no ckey attached to it, which isn't supported by ghost role spawners!")
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/effect/mob_spawn/ghost_role/special(mob/living/spawned_mob, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/ghost_role/special(mob/living/spawned_mob, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
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.client && apply_prefs && allow_custom_character && ishuman(spawned_mob))
|
||||
var/mob/living/carbon/human/spawned_human = spawned_mob
|
||||
if(allow_custom_character & GHOSTROLE_TAKE_PREFS_APPEARANCE)
|
||||
mob_possessor.client.prefs.apply_prefs_to(spawned_human, icon_updates = TRUE, do_not_apply = typesof(/datum/preference/name, /datum/preference/choiced/species))
|
||||
if(allow_custom_character & GHOSTROLE_TAKE_PREFS_SPECIES)
|
||||
spawned_human.set_species(mob_possessor.client.prefs.read_preference(/datum/preference/choiced/species))
|
||||
spawned_human.fully_replace_character_name(spawned_human.real_name, spawned_human.generate_random_mob_name())
|
||||
if(mob_possessor.mind)
|
||||
mob_possessor.mind.transfer_to(spawned_mob, force_key_move = TRUE)
|
||||
else
|
||||
spawned_mob.PossessByPlayer(mob_possessor.key)
|
||||
|
||||
var/datum/mind/spawned_mind = spawned_mob.mind
|
||||
if(spawned_mind)
|
||||
spawned_mob.mind.set_assigned_role_with_greeting(SSjob.get_job_type(spawner_job_path))
|
||||
@@ -314,7 +336,7 @@
|
||||
if(mapload || (SSticker && SSticker.current_state > GAME_STATE_SETTING_UP))
|
||||
INVOKE_ASYNC(src, PROC_REF(create))
|
||||
|
||||
/obj/effect/mob_spawn/corpse/special(mob/living/spawned_mob, mob/mob_possessor)
|
||||
/obj/effect/mob_spawn/corpse/special(mob/living/spawned_mob, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
spawned_mob.death(TRUE)
|
||||
spawned_mob.adjustOxyLoss(oxy_damage)
|
||||
@@ -323,7 +345,7 @@
|
||||
if (corpse_description)
|
||||
spawned_mob.AddComponent(/datum/component/temporary_description, corpse_description, naive_corpse_description)
|
||||
|
||||
/obj/effect/mob_spawn/corpse/create(mob/mob_possessor, newname)
|
||||
/obj/effect/mob_spawn/corpse/create(mob/mob_possessor, newname, apply_prefs)
|
||||
. = ..()
|
||||
qdel(src)
|
||||
|
||||
@@ -343,7 +365,7 @@
|
||||
///husks the corpse if true.
|
||||
var/husk = FALSE
|
||||
|
||||
/obj/effect/mob_spawn/corpse/human/special(mob/living/carbon/human/spawned_human)
|
||||
/obj/effect/mob_spawn/corpse/human/special(mob/living/carbon/human/spawned_human, mob/mob_possessor, apply_prefs)
|
||||
. = ..()
|
||||
if(husk)
|
||||
spawned_human.Drain()
|
||||
|
||||
Reference in New Issue
Block a user