diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 6c2460cd1f9..bc590cf10d5 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -115,7 +115,7 @@ GLOBAL_LIST_INIT(turfs_pass_meteor, typecacheof(list( //Human sub-species #define isabductor(A) (is_species(A, /datum/species/abductor)) -#define isspirit(A) (is_species(A, /datum/species/spirit)) +#define isghostspecies(A) (is_species(A, /datum/species/ghost)) #define isgolem(A) (is_species(A, /datum/species/golem)) #define islizard(A) (is_species(A, /datum/species/lizard)) #define isashwalker(A) (is_species(A, /datum/species/lizard/ashwalker)) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 22c9819c7ae..7cdd886694d 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -177,7 +177,6 @@ #define SPECIES_HUMAN "human" #define SPECIES_JELLYPERSON "jelly" #define SPECIES_SLIMEPERSON "slime" -#define SPECIES_SPIRIT "spirit" #define SPECIES_LUMINESCENT "luminescent" #define SPECIES_STARGAZER "stargazer" #define SPECIES_LIZARD "lizard" diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm index a77131e73ce..418a4b8e509 100644 --- a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm +++ b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm @@ -333,6 +333,14 @@ new /obj/effect/decal/cleanable/blood/gibs/old(src) new /obj/item/book/granter/crafting_recipe/boneyard_notes(src) +/obj/structure/closet/crate/grave/skeleton + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + affect_mood = TRUE + +/obj/structure/closet/crate/grave/skeleton/PopulateContents() + . = ..() + new /mob/living/carbon/human/species/skeleton(src) + //***Fluff items for lore/intrigue /obj/item/paper/crumpled/muddy/fluff/elephant_graveyard name = "posted warning" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 9792d645ebb..79da995c053 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1115,11 +1115,8 @@ /mob/living/carbon/human/species/lizard/silverscale race = /datum/species/lizard/silverscale -/mob/living/carbon/human/species/spirit - race = /datum/species/spirit - /mob/living/carbon/human/species/ghost - race = /datum/species/spirit/ghost + race = /datum/species/ghost /mob/living/carbon/human/species/ethereal race = /datum/species/ethereal diff --git a/code/modules/mob/living/carbon/human/species_types/ghost.dm b/code/modules/mob/living/carbon/human/species_types/ghost.dm index 7e54ce26196..e1653c9f3b4 100644 --- a/code/modules/mob/living/carbon/human/species_types/ghost.dm +++ b/code/modules/mob/living/carbon/human/species_types/ghost.dm @@ -1,22 +1,23 @@ ///Spirit mob that lacks legs but still roams the station as part of the unliving. -/datum/species/spirit - name = "Spirit" - id = SPECIES_SPIRIT +/datum/species/ghost + name = "Ghost" + id = SPECIES_GHOST inherent_traits = list( TRAIT_GENELESS, + TRAIT_MOVE_FLYING, TRAIT_NEVER_WOUNDED, TRAIT_NOBLOOD, TRAIT_NODISMEMBER, TRAIT_NO_DNA_COPY, + TRAIT_NO_FLOATING_ANIM, TRAIT_NO_PLASMA_TRANSFORM, TRAIT_NO_UNDERWEAR, + TRAIT_RESISTLOWPRESSURE, TRAIT_UNHUSKABLE, - TRAIT_NO_FLOATING_ANIM, - TRAIT_MOVE_FLYING, ) - inherent_biotypes = MOB_SPIRIT | MOB_UNDEAD + inherent_biotypes = MOB_HUMANOID | MOB_SPIRIT | MOB_UNDEAD no_equip_flags = ITEM_SLOT_FEET - changesource_flags = MIRROR_BADMIN | WABBAJACK | SLIME_EXTRACT + changesource_flags = MIRROR_BADMIN | WABBAJACK | SLIME_EXTRACT | MIRROR_PRIDE | MIRROR_MAGIC sexes = FALSE meat = /obj/item/ectoplasm @@ -32,34 +33,45 @@ bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/ghost, - BODY_ZONE_CHEST = /obj/item/bodypart/chest/ghost/spirit, + BODY_ZONE_CHEST = /obj/item/bodypart/chest/ghost, BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/ghost, BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/ghost, ) - ///Boolean on whether this species type is available at roundstart during halloween, used to deny subtypes. - var/halloween_exclusive = TRUE + ///Innate passthrough ability given to ghosts that allows them to phase but drops their stuff. + var/datum/action/innate/toggle_passthrough/passthrough_ability -/datum/species/spirit/check_roundstart_eligible() - if(check_holidays(HALLOWEEN) && halloween_exclusive) +/datum/species/ghost/check_roundstart_eligible() + if(check_holidays(HALLOWEEN)) return TRUE return ..() -/datum/species/spirit/get_physical_attributes() - return "Spirits are the spiritual remains of long-passed entities. They lack legs, can fly, but still eat, breathe, hear and see." +/datum/species/ghost/on_species_gain(mob/living/carbon/human/new_ghost, datum/species/old_species, pref_load, regenerate_icons) + . = ..() + passthrough_ability = new(src) + passthrough_ability.Grant(new_ghost) -/datum/species/spirit/get_species_description() +/datum/species/ghost/on_species_loss(mob/living/carbon/human/former_ghost, datum/species/new_species, pref_load) + QDEL_NULL(passthrough_ability) + return ..() + +/datum/species/ghost/get_physical_attributes() + return "Ghosts are the spiritual remains of long-passed entities. They lack legs, can fly, and phase through walls, \ + but still eat, breathe, hear and see." + +/datum/species/ghost/get_species_description() return "Spirits are spirits of long-dead creatures whom, for one reason or another, still roam around." -/datum/species/spirit/get_species_lore() +/datum/species/ghost/get_species_lore() return list( - "Spirits are the non-physical remains that linger onto their mortal coil. \ - They still need their protein and organs to keep themselves \"alive\", \ - which leads to many of them still believing they are still part of the living, \ - whether or not they are is a very open-ended debate between philosophers.", + "Ghosts are one of the spookiest creatures known in the galaxy. \ + While they still need their protein to sustain themselves, they are able to control their own bodies, \ + going through walls and getting rid of all their posessions at will. \ + Most knowledge known about them is kept secret by Nanotrasen's top Chaplains, who are keen \ + to keep it private.", ) -/datum/species/spirit/create_pref_unique_perks() +/datum/species/ghost/create_pref_unique_perks() var/list/to_add = list() to_add += list(list( @@ -69,6 +81,14 @@ SPECIES_PERK_DESC = "Ghosts lack legs and float, preventing you from falling into holes in the ground.", )) + to_add += list(list( + SPECIES_PERK_TYPE = SPECIES_NEUTRAL_PERK, + SPECIES_PERK_ICON = "ghost", + SPECIES_PERK_NAME = "Incorporeal", + SPECIES_PERK_DESC = "Ghost carry their tombstones with them and are directly tied to it. \ + dropping the tombstone will allow you to phase through solid matter, but leaves you vulnerable.", + )) + to_add += list(list( SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, SPECIES_PERK_ICON = "shoe-prints", @@ -78,102 +98,35 @@ return to_add -/** - * Ghost subtype - * This is the type of ghost that can actually phase through walls, - * exclusive to magic mirrors & admins, as roundstart-ability to phase anywhere - * is not something that is generally fun to play against. - */ -/datum/species/spirit/ghost - name = "Ghost" - id = SPECIES_GHOST - inherent_traits = list( - TRAIT_GENELESS, - TRAIT_NEVER_WOUNDED, - TRAIT_NOBLOOD, - TRAIT_NODISMEMBER, - TRAIT_NO_DNA_COPY, - TRAIT_NO_PLASMA_TRANSFORM, - TRAIT_NO_UNDERWEAR, - TRAIT_UNHUSKABLE, - TRAIT_NO_FLOATING_ANIM, - TRAIT_MOVE_FLYING, - //ghost-unique - TRAIT_SEE_BLESSED_TILES, - ) - //they have a different chest. - bodypart_overrides = list( - BODY_ZONE_HEAD = /obj/item/bodypart/head/ghost, - BODY_ZONE_CHEST = /obj/item/bodypart/chest/ghost, - BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/ghost, - BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/ghost, - ) - changesource_flags = MIRROR_BADMIN | MIRROR_PRIDE | MIRROR_MAGIC - halloween_exclusive = FALSE - - ///Innate passthrough ability given to ghosts that allows them to phase but drops their stuff. - var/datum/action/innate/toggle_passthrough/passthrough_ability - -/datum/species/spirit/ghost/get_physical_attributes() - return "Ghosts are the spiritual remains of long-passed entities. They lack legs, can fly, can choose at will to become incorporeal, \ - but still eat, breathe, hear and see." - -/datum/species/spirit/ghost/get_species_lore() - return list( - "Ghosts are one of the spookiest creatures known in the galaxy. \ - While they still need their protein to sustain themselves, they are able to control their own bodies, \ - going through walls and getting rid of all their posessions at will. \ - Most knowledge known about them is kept secret by Nanotrasen's top Chaplains, who are keen \ - to keep it private.", - ) - -/datum/species/spirit/ghost/on_species_gain(mob/living/carbon/human/new_ghost, datum/species/old_species, pref_load, regenerate_icons) - . = ..() - passthrough_ability = new(src) - passthrough_ability.Grant(new_ghost) - for(var/datum/atom_hud/alternate_appearance/basic/blessed_aware/blessed_hud in GLOB.active_alternate_appearances) - blessed_hud.check_hud(new_ghost) - -/datum/species/spirit/ghost/on_species_loss(mob/living/carbon/human/former_ghost, datum/species/new_species, pref_load) - . = ..() - QDEL_NULL(passthrough_ability) - //this has to be called after parent so inherent traits is cleared before we update our HUDs - for(var/datum/atom_hud/alternate_appearance/basic/blessed_aware/blessed_hud in GLOB.active_alternate_appearances) - blessed_hud.check_hud(former_ghost) - -/datum/species/spirit/ghost/create_pref_unique_perks() - var/list/to_add = ..() - - to_add += list(list( - SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, - SPECIES_PERK_ICON = "ghost", - SPECIES_PERK_NAME = "Incorporeal", - SPECIES_PERK_DESC = "Ghost are able to control their body to the extent where you can willingly make yourself able \ - to phase through anything, including your own equipment.", - )) - - return to_add - /** * Passthrough ability * * Ghost innate ability that allows them to enter ghost mode, - * which gives them the phasing ability, but makes them drop everything - * and completely unable to wear anything. + * which gives them the phasing ability, but makes them unable to use anything, + * and they will be tied to a tombstone that, if dug up, will kill them and turn them + * into a skeleton. */ /datum/action/innate/toggle_passthrough name = "Toggle passthrough" - desc = "Toggles your ability to phase through everything, including your gear and any incompatible organs/limbs." + desc = "Toggles phasing through everything, including your hands. You are tied to your tombstone while this is active. \ + At least you know how to keep your clothes on." button_icon = 'icons/hud/actions.dmi' button_icon_state = "ghost" + ///Grave that appears when we're passing through, which we are also tied to. + var/obj/structure/closet/crate/grave/skeleton/grave + /datum/action/innate/toggle_passthrough/Grant(mob/grant_to) . = ..() - RegisterSignal(grant_to, COMSIG_CARBON_POST_ATTACH_LIMB, PROC_REF(on_new_limb)) + grave = new() + //contents are initialized when the grave is robbed as that's when the crate is opened for the first time. + RegisterSignal(grave, COMSIG_CLOSET_CONTENTS_INITIALIZED, PROC_REF(on_grave_robbed)) + RegisterSignal(grave, COMSIG_CLOSET_POST_OPEN, PROC_REF(post_grave_robbed)) /datum/action/innate/toggle_passthrough/Remove(mob/remove_from) - swap_mode(force_off = TRUE) - UnregisterSignal(remove_from, COMSIG_CARBON_POST_ATTACH_LIMB) + if(!QDELING(remove_from)) + swap_mode(force_off = TRUE) + QDEL_NULL(grave) return ..() /datum/action/innate/toggle_passthrough/Activate() @@ -182,30 +135,6 @@ return swap_mode() -/datum/action/innate/toggle_passthrough/IsAvailable(feedback) - if(!isliving(owner)) - return FALSE - var/mob/living/living_owner = owner - if(living_owner.has_reagent(/datum/reagent/water/holywater)) - return FALSE - //technically you can trap a ghost by blessing them as theyre phasing, - //but they can still be dragged out. - if(locate(/obj/effect/blessing) in get_turf(owner)) - return FALSE - var/obj/item/bodypart/chest/their_chest = living_owner.get_bodypart(BODY_ZONE_CHEST) - if(!their_chest || !(their_chest.bodytype & BODYTYPE_GHOST)) - return FALSE - return ..() - -///Called when the owner of this action gets a new limb, if it isn't a ghost-limb -///the action will turn itself off, and you'll lose said limb if you try using this action again. -/datum/action/innate/toggle_passthrough/proc/on_new_limb(mob/source, obj/item/bodypart/new_part, special) - SIGNAL_HANDLER - if(!iscarbon(owner)) - return - if(!(new_part.bodytype & BODYTYPE_GHOST)) - swap_mode(force_off = TRUE) - ///Swaps the mode, allowing us to phase through stuff but drops everything. Optional 'force_off' arg to prevent being able to turn it on. /datum/action/innate/toggle_passthrough/proc/swap_mode(force_off) //we can only turn off, early return if we're trying to turn it on instead. @@ -213,17 +142,9 @@ return var/mob/living/carbon/carbon_owner = owner - var/datum/species/carbon_species = carbon_owner.dna.species - - //drop any limbs & organs that can't phase, now that you're phasing. - for(var/obj/item/bodypart/bodypart as anything in carbon_owner.bodyparts) - if(!(bodypart.bodytype & BODYTYPE_GHOST)) - bodypart.drop_limb(special = FALSE, dismembered = FALSE, move_to_floor = TRUE) - for(var/obj/item/organ/organ as anything in carbon_owner.organs) - if(!(organ.organ_flags & ORGAN_GHOST)) - organ.Remove(owner, special = FALSE) - if(HAS_TRAIT_FROM(carbon_owner, TRAIT_NO_FLOATING_ANIM, SPECIES_TRAIT)) + grave.forceMove(get_turf(carbon_owner)) + carbon_owner.AddComponent(/datum/component/leash, grave, distance = 7) REMOVE_TRAIT(carbon_owner, TRAIT_NO_FLOATING_ANIM, SPECIES_TRAIT) carbon_owner.add_traits(list( TRAIT_MOVE_PHASING, @@ -232,10 +153,11 @@ TRAIT_HANDS_BLOCKED, //MOBILITY_USE | MOBILITY_PICKUP | MOBILITY_STORAGE TRAIT_PULL_BLOCKED, //MOBILITY_PULL TRAIT_UI_BLOCKED, //MOBILITY_UI - ), SPECIES_TRAIT) - carbon_species.update_no_equip_flags(carbon_owner, ALL) - RegisterSignal(carbon_owner, COMSIG_MOB_CLIENT_PRE_LIVING_MOVE, PROC_REF(attempt_move)) + ), SPECIES_TRAIT) else + qdel(carbon_owner.GetComponent(/datum/component/leash)) + carbon_owner.forceMove(get_turf(grave)) + grave.moveToNullspace() ADD_TRAIT(carbon_owner, TRAIT_NO_FLOATING_ANIM, SPECIES_TRAIT) carbon_owner.remove_traits(list( TRAIT_MOVE_PHASING, @@ -244,13 +166,16 @@ TRAIT_HANDS_BLOCKED, TRAIT_PULL_BLOCKED, TRAIT_UI_BLOCKED, - ), SPECIES_TRAIT) - carbon_species.update_no_equip_flags(carbon_owner, initial(carbon_species.no_equip_flags)) - UnregisterSignal(carbon_owner, COMSIG_MOB_CLIENT_PRE_LIVING_MOVE) + ), SPECIES_TRAIT) -///Called when attempting to move to a new tile while the action is active, returns to cancel moving. -/datum/action/innate/toggle_passthrough/proc/attempt_move(mob/source, new_loc, direct) +///Called when the contents are made, which means the grave has been 'opened', therefore robbed. +/datum/action/innate/toggle_passthrough/proc/on_grave_robbed(obj/structure/closet/crate/grave/skeleton/source) SIGNAL_HANDLER - if(locate(/obj/effect/blessing) in new_loc) - to_chat(source, span_warning("Holy energies block your path!")) - return COMSIG_MOB_CLIENT_BLOCK_PRE_LIVING_MOVE + var/mob/living/carbon/human/species/skeleton/skeletons_in_the_closet = locate() in source.contents + owner.mind.transfer_to(skeletons_in_the_closet, force_key_move = TRUE) + skeletons_in_the_closet.death(gibbed = FALSE) + +///Called AFTER the contents have been spit out, which means the owner is now in the skeleton. Let's clean up. +/datum/action/innate/toggle_passthrough/proc/post_grave_robbed(obj/structure/closet/crate/grave/skeleton/source) + SIGNAL_HANDLER + qdel(owner) diff --git a/code/modules/photography/photos/photo.dm b/code/modules/photography/photos/photo.dm index 450746c71a2..9c76e499a60 100644 --- a/code/modules/photography/photos/photo.dm +++ b/code/modules/photography/photos/photo.dm @@ -53,7 +53,7 @@ if(!seen) P.mobs_seen -= seen_ref continue - if(!isobserver(seen) && !isspirit(seen)) + if(!isobserver(seen) && !isghostspecies(seen)) continue set_custom_materials(list(/datum/material/hauntium =SHEET_MATERIAL_AMOUNT)) grind_results = list(/datum/reagent/hauntium = 20) diff --git a/code/modules/surgery/bodyparts/species_parts/ghost_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/ghost_bodyparts.dm index adeaa04067c..765dd8d465b 100644 --- a/code/modules/surgery/bodyparts/species_parts/ghost_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/ghost_bodyparts.dm @@ -3,7 +3,7 @@ icon_static = 'icons/mob/human/species/ghost.dmi' icon_state = "ghost_head" biological_state = BIO_FLESH - bodytype = BODYTYPE_GHOST + bodytype = BODYTYPE_ORGANIC|BODYTYPE_GHOST limb_id = SPECIES_GHOST is_dimorphic = FALSE should_draw_greyscale = FALSE @@ -18,24 +18,19 @@ icon_state = "ghost_chest" biological_state = BIO_FLESH acceptable_bodyshape = BODYTYPE_GHOST - bodytype = BODYTYPE_GHOST + bodytype = BODYTYPE_ORGANIC|BODYTYPE_GHOST limb_id = SPECIES_GHOST is_dimorphic = FALSE should_draw_greyscale = FALSE dmg_overlay_type = null wing_types = null -//slightly different sprite meant to differentiate spirit from ghost. -/obj/item/bodypart/chest/ghost/spirit - icon_state = "spirit_chest" - limb_id = SPECIES_SPIRIT - /obj/item/bodypart/arm/left/ghost icon = 'icons/mob/human/species/ghost.dmi' icon_static = 'icons/mob/human/species/ghost.dmi' icon_state = "ghost_l_arm" biological_state = BIO_FLESH|BIO_JOINTED - bodytype = BODYTYPE_GHOST + bodytype = BODYTYPE_ORGANIC|BODYTYPE_GHOST limb_id = SPECIES_GHOST should_draw_greyscale = FALSE dmg_overlay_type = null @@ -45,7 +40,7 @@ icon_static = 'icons/mob/human/species/ghost.dmi' icon_state = "ghost_r_arm" biological_state = BIO_FLESH|BIO_JOINTED - bodytype = BODYTYPE_GHOST + bodytype = BODYTYPE_ORGANIC|BODYTYPE_GHOST limb_id = SPECIES_GHOST should_draw_greyscale = FALSE dmg_overlay_type = null diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_spirit.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_ghost.png similarity index 100% rename from code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_spirit.png rename to code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_ghost.png diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_spirit_ghost.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_spirit_ghost.png deleted file mode 100644 index c43c67f12a8..00000000000 Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_spirit_ghost.png and /dev/null differ diff --git a/icons/mob/human/species/ghost.dmi b/icons/mob/human/species/ghost.dmi index 42185e3db54..f22d3fc386c 100644 Binary files a/icons/mob/human/species/ghost.dmi and b/icons/mob/human/species/ghost.dmi differ