Files
Tim b153a3cc55 Fix holodeck organ and bodyparts behavior (#95967)
## About The Pull Request
- Fixes #95963

Holodeck mobs would not have their organs, body parts, and contents set
as holographic objects. This means you could cut off their limbs or
remove their organs, and it would be considered a "real" object. This
would ignore the holodeck boundaries, changing the simulation, or
turning it offline, which should have caused the object to disappear.

Also, I added some checks so that the bioscrambler activity requires the
mob, organ, or body part to not be holographic.

## Why It's Good For The Game
Holodeck should disappear and behave properly. 

## Changelog
🆑
fix: Fix holodeck mob organs and body parts not disappearing. Any
holodeck mob organs and body parts can also no longer be bioscrambled.
/🆑
2026-05-17 08:43:07 +02:00

140 lines
4.2 KiB
Plaintext

/*
The holodeck activates these shortly after the program loads,
and deactivates them immediately before changing or disabling the holodeck.
These remove snowflake code for special holodeck functions.
*/
/obj/effect/holodeck_effect
icon = 'icons/hud/screen_gen.dmi'
icon_state = "x2"
invisibility = INVISIBILITY_ABSTRACT
/obj/effect/holodeck_effect/proc/activate(obj/machinery/computer/holodeck/HC)
return
/obj/effect/holodeck_effect/proc/deactivate(obj/machinery/computer/holodeck/HC)
qdel(src)
return
// Called by the holodeck computer as long as the program is running
/obj/effect/holodeck_effect/proc/tick(obj/machinery/computer/holodeck/HC)
return
/obj/effect/holodeck_effect/proc/safety(active)
return
// Generates a holodeck-tracked card deck
/obj/effect/holodeck_effect/cards
icon = 'icons/obj/toys/playing_cards.dmi'
icon_state = "deck_syndicate_full"
/obj/effect/holodeck_effect/cards/activate(obj/machinery/computer/holodeck/holodeck)
var/obj/item/toy/cards/deck/syndicate/holographic/deck = new(loc, holodeck)
deck.flags_1 |= HOLOGRAM_1
return deck
/obj/effect/holodeck_effect/sparks/activate(obj/machinery/computer/holodeck/HC)
var/turf/T = get_turf(src)
if(T)
do_sparks(3, TRUE, T)
T.temperature = 5000 //Why? not quite sure to be honest with you
T.hotspot_expose(50000,50000,1)
/obj/effect/holodeck_effect/random_book
/obj/effect/holodeck_effect/random_book/activate(obj/machinery/computer/holodeck/father_holodeck)
var/newtype = get_random_manual()
var/obj/item/book/manual/to_spawn = new newtype(loc)
to_spawn.flags_1 |= HOLOGRAM_1
to_spawn.obj_flags |= NO_DEBRIS_AFTER_DECONSTRUCTION
return to_spawn
/obj/effect/holodeck_effect/mobspawner
var/mobtype = /mob/living/basic/carp/holographic
var/mob/our_mob = null
/obj/effect/holodeck_effect/mobspawner/activate(obj/machinery/computer/holodeck/HC)
. = list()
if(islist(mobtype))
mobtype = pick(mobtype)
our_mob = new mobtype(loc)
our_mob.flags_1 |= HOLOGRAM_1
. += our_mob
for(var/atom/holo_atom as anything in our_mob.contents)
holo_atom.flags_1 |= HOLOGRAM_1
. += holo_atom
if(iscarbon(our_mob))
var/mob/living/carbon/holo_carbon_mob = our_mob
for(var/obj/item/organ/holo_organ as anything in holo_carbon_mob.organs)
holo_organ.flags_1 |= HOLOGRAM_1
. += holo_organ
// these vars are not really standardized but all would theoretically create stuff on death
our_mob.add_traits(list(TRAIT_PERMANENTLY_MORTAL, TRAIT_NO_BLOOD_OVERLAY, TRAIT_NOBLOOD, TRAIT_NOHUNGER, TRAIT_SPAWNED_MOB), INNATE_TRAIT)
RegisterSignal(our_mob, COMSIG_QDELETING, PROC_REF(handle_mob_delete))
return .
/obj/effect/holodeck_effect/mobspawner/deactivate(obj/machinery/computer/holodeck/HC)
if(our_mob)
for(var/atom/holo_atom as anything in our_mob.contents)
if(holo_atom.flags_1 & HOLOGRAM_1)
HC.derez(holo_atom)
if(iscarbon(our_mob))
var/mob/living/carbon/holo_carbon_mob = our_mob
for(var/obj/item/organ/holo_organ as anything in holo_carbon_mob.organs)
if(holo_organ.flags_1 & HOLOGRAM_1)
HC.derez(holo_organ)
HC.derez(our_mob)
qdel(src)
/obj/effect/holodeck_effect/mobspawner/proc/handle_mob_delete(datum/source)
SIGNAL_HANDLER
our_mob = null
/obj/effect/holodeck_effect/mobspawner/pet
/obj/effect/holodeck_effect/mobspawner/pet/Initialize(mapload)
. = ..()
mobtype = list(
/mob/living/basic/butterfly,
/mob/living/basic/chick/permanent,
/mob/living/basic/pet/fox/docile,
/mob/living/basic/rabbit,
)
mobtype += pick(
/mob/living/basic/pet/dog/corgi,
/mob/living/basic/pet/dog/corgi/puppy,
/mob/living/basic/pet/dog/pug,
)
mobtype += pick(
/mob/living/basic/pet/cat,
/mob/living/basic/pet/cat/kitten,
)
/obj/effect/holodeck_effect/mobspawner/bee
mobtype = /mob/living/basic/bee/toxin
/obj/effect/holodeck_effect/mobspawner/monkey
mobtype = /mob/living/carbon/human/species/monkey
/obj/effect/holodeck_effect/mobspawner/penguin
mobtype = /mob/living/basic/pet/penguin/emperor/neuter
/obj/effect/holodeck_effect/mobspawner/penguin/Initialize(mapload)
if(prob(1))
mobtype = /mob/living/basic/pet/penguin/emperor/shamebrero/neuter
return ..()
/obj/effect/holodeck_effect/mobspawner/penguin_baby
mobtype = /mob/living/basic/pet/penguin/baby/permanent
/obj/effect/holodeck_effect/mobspawner/crab/jon
mobtype = /mob/living/basic/crab/jon