mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 17:52:36 +00:00
Dullahan Fixes (#78938)
## About The Pull Request Let's see if these can be like 50% playable by Halloween Fixes #70890 (mostly) Also one half of #71020 but does not close it because they still cannot hear audible messages There was a list of issues in #70890 which are largely fixed by this, but some of them were not _bugs_. Anything which is simply an obvious consequence of "not having a head or being able to wear anything on your head" isn't and cannot be fixed, because this species doesn't have a head. That means that all of these things are still true: ``` Dullahans have no radio Can't get spaceproofed because without the helmet you still take pressure damage Can't wear modsuits Can't wear sunglasses or HUDs Can't wear clown mask ``` The issue causing everything _else_ is that when we sever the head, we remove the brain. Removing the brain removes the traits `TRAIT_ADVANCEDTOOLUSER, TRAIT_LITERATE, TRAIT_CAN_STRIP`. Without these three traits, Dullahans are blocked from several important actions. Easy fix: Make these properties of the dullahan species independent of whether they have a brain or not. Clearly they can do these things without brains, on account of not having them. Additionally I gave dullahans their own head subtype which preserves internal organs, because their brains and eyes were decaying and giving them brain trauma and blindness. Finally, I changed a few things from checks in `spec_life` to signal responses, because `spec_life` checks for "did I gain a head recently?" are gross. ## Changelog 🆑 fix: Dullahans can read, strip people, and utilise tools. fix: Dullahan brains and eyes will not decay while inside their living severed head. /🆑 --------- Co-authored-by: san7890 <the@san7890.com>
This commit is contained in:
@@ -122,6 +122,8 @@
|
||||
|
||||
// /mob/living/carbon/human signals
|
||||
|
||||
///Applied preferences to a human
|
||||
#define COMSIG_HUMAN_PREFS_APPLIED "human_prefs_applied"
|
||||
///Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted)
|
||||
#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit"
|
||||
///Whenever EquipRanked is called, called after job is set
|
||||
|
||||
@@ -509,6 +509,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
character.icon_render_keys = list()
|
||||
character.update_body(is_creating = TRUE)
|
||||
|
||||
SEND_SIGNAL(character, COMSIG_HUMAN_PREFS_APPLIED)
|
||||
|
||||
/// Returns whether the parent mob should have the random hardcore settings enabled. Assumes it has a mind.
|
||||
/datum/preferences/proc/should_be_random_hardcore(datum/job/job, datum/mind/mind)
|
||||
|
||||
@@ -6,6 +6,17 @@
|
||||
TRAIT_NOBREATH,
|
||||
TRAIT_NOHUNGER,
|
||||
TRAIT_USES_SKINTONES,
|
||||
TRAIT_ADVANCEDTOOLUSER, // Normally applied by brain but we don't have one
|
||||
TRAIT_LITERATE,
|
||||
TRAIT_CAN_STRIP,
|
||||
)
|
||||
bodypart_overrides = list(
|
||||
BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left,
|
||||
BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right,
|
||||
BODY_ZONE_HEAD = /obj/item/bodypart/head/dullahan,
|
||||
BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left,
|
||||
BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right,
|
||||
BODY_ZONE_CHEST = /obj/item/bodypart/chest,
|
||||
)
|
||||
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
|
||||
mutant_bodyparts = list("wings" = "None")
|
||||
@@ -20,11 +31,9 @@
|
||||
|
||||
/// The dullahan relay that's associated with the owner, used to handle many things such as talking and hearing.
|
||||
var/obj/item/dullahan_relay/my_head
|
||||
|
||||
/// Did our owner's first client connection get handled yet? Useful for when some proc needs to be called once we're sure that a client has moved into our owner, like for Dullahans.
|
||||
var/owner_first_client_connection_handled = FALSE
|
||||
|
||||
|
||||
/datum/species/dullahan/check_roundstart_eligible()
|
||||
if(check_holidays(HALLOWEEN))
|
||||
return TRUE
|
||||
@@ -33,62 +42,59 @@
|
||||
/datum/species/dullahan/on_species_gain(mob/living/carbon/human/human, datum/species/old_species)
|
||||
. = ..()
|
||||
human.lose_hearing_sensitivity(TRAIT_GENERIC)
|
||||
RegisterSignal(human, COMSIG_CARBON_ATTACH_LIMB, PROC_REF(on_gained_part))
|
||||
|
||||
var/obj/item/bodypart/head/head = human.get_bodypart(BODY_ZONE_HEAD)
|
||||
head?.drop_limb()
|
||||
if(QDELETED(head)) //drop_limb() deletes the limb if no drop location exists and character setup dummies are located in nullspace.
|
||||
return
|
||||
my_head = new /obj/item/dullahan_relay(head, human)
|
||||
human.put_in_hands(head)
|
||||
|
||||
if(head)
|
||||
head.drop_limb()
|
||||
|
||||
if(!QDELETED(head)) //drop_limb() deletes the limb if no drop location exists and character setup dummies are located in nullspace.
|
||||
head.throwforce = 25
|
||||
my_head = new /obj/item/dullahan_relay(head, human)
|
||||
human.put_in_hands(head)
|
||||
head.show_organs_on_examine = FALSE
|
||||
head.speech_span = null // so we don't look roboty when talking through it
|
||||
|
||||
// We want to give the head some boring old eyes just so it doesn't look too jank on the head sprite.
|
||||
head.eyes = new /obj/item/organ/internal/eyes(head)
|
||||
head.eyes.eye_color_left = human.eye_color_left
|
||||
head.eyes.eye_color_right = human.eye_color_right
|
||||
human.update_body()
|
||||
head.update_icon_dropped()
|
||||
|
||||
// We want to give the head some boring old eyes just so it doesn't look too jank on the head sprite.
|
||||
head.eyes = new /obj/item/organ/internal/eyes(head)
|
||||
head.eyes.eye_color_left = human.eye_color_left
|
||||
head.eyes.eye_color_right = human.eye_color_right
|
||||
human.update_body()
|
||||
head.update_icon_dropped()
|
||||
human.set_safe_hunger_level()
|
||||
RegisterSignal(head, COMSIG_QDELETING, PROC_REF(on_head_destroyed))
|
||||
|
||||
/// If we gained a new body part, it had better not be a head
|
||||
/datum/species/dullahan/proc/on_gained_part(mob/living/carbon/human/dullahan, obj/item/bodypart/part)
|
||||
SIGNAL_HANDLER
|
||||
if (part.body_zone != BODY_ZONE_HEAD)
|
||||
return
|
||||
my_head = null
|
||||
dullahan.investigate_log("has been gibbed by having an illegal head put on [dullahan.p_their()] shoulders.", INVESTIGATE_DEATHS)
|
||||
dullahan.gib(DROP_ALL_REMAINS) // Yeah so giving them a head on their body is really not a good idea, so their original head will remain but uh, good luck fixing it after that.
|
||||
|
||||
/// If our head is destroyed, so are we
|
||||
/datum/species/dullahan/proc/on_head_destroyed()
|
||||
SIGNAL_HANDLER
|
||||
var/mob/living/human = my_head?.owner
|
||||
if (QDELETED(human))
|
||||
return // guess we already died
|
||||
my_head = null
|
||||
human.investigate_log("has been gibbed by the loss of [human.p_their()] head.", INVESTIGATE_DEATHS)
|
||||
human.gib(DROP_ALL_REMAINS)
|
||||
|
||||
/datum/species/dullahan/on_species_loss(mob/living/carbon/human/human)
|
||||
. = ..()
|
||||
|
||||
if(my_head)
|
||||
var/obj/item/bodypart/head/detached_head = my_head.loc
|
||||
UnregisterSignal(detached_head, COMSIG_QDELETING)
|
||||
my_head.owner = null
|
||||
QDEL_NULL(my_head)
|
||||
if(detached_head)
|
||||
qdel(detached_head)
|
||||
|
||||
UnregisterSignal(human, COMSIG_CARBON_ATTACH_LIMB)
|
||||
human.regenerate_limb(BODY_ZONE_HEAD, FALSE)
|
||||
human.become_hearing_sensitive()
|
||||
prevent_perspective_change = FALSE
|
||||
human.reset_perspective(human)
|
||||
|
||||
/datum/species/dullahan/spec_life(mob/living/carbon/human/human, seconds_per_tick, times_fired)
|
||||
. = ..()
|
||||
if(QDELETED(my_head))
|
||||
my_head = null
|
||||
human.investigate_log("has been gibbed by the loss of [human.p_their()] head.", INVESTIGATE_DEATHS)
|
||||
human.gib(DROP_ALL_REMAINS)
|
||||
return
|
||||
|
||||
if(my_head.loc.name != human.real_name && istype(my_head.loc, /obj/item/bodypart/head))
|
||||
var/obj/item/bodypart/head/detached_head = my_head.loc
|
||||
detached_head.real_name = human.real_name
|
||||
detached_head.name = human.real_name
|
||||
detached_head.brain.name = "[human.name]'s brain"
|
||||
|
||||
var/obj/item/bodypart/head/illegal_head = human.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(illegal_head)
|
||||
my_head = null
|
||||
human.investigate_log("has been gibbed by having an illegal head put on [human.p_their()] shoulders.", INVESTIGATE_DEATHS)
|
||||
human.gib(DROP_ALL_REMAINS) // Yeah so giving them a head on their body is really not a good idea, so their original head will remain but uh, good luck fixing it after that.
|
||||
|
||||
/datum/species/dullahan/proc/update_vision_perspective(mob/living/carbon/human/human)
|
||||
var/obj/item/organ/internal/eyes/eyes = human.get_organ_slot(ORGAN_SLOT_EYES)
|
||||
if(eyes)
|
||||
@@ -212,11 +218,15 @@
|
||||
. = ..()
|
||||
if(!new_owner)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
var/obj/item/bodypart/head/detached_head = loc
|
||||
if (!istype(detached_head))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
owner = new_owner
|
||||
START_PROCESSING(SSobj, src)
|
||||
RegisterSignal(owner, COMSIG_CLICK_SHIFT, PROC_REF(examinate_check))
|
||||
RegisterSignal(owner, COMSIG_CARBON_REGENERATE_LIMBS, PROC_REF(unlist_head))
|
||||
RegisterSignal(owner, COMSIG_LIVING_REVIVE, PROC_REF(retrieve_head))
|
||||
RegisterSignal(owner, COMSIG_HUMAN_PREFS_APPLIED, PROC_REF(update_prefs_name))
|
||||
become_hearing_sensitive(ROUNDSTART_TRAIT)
|
||||
|
||||
/obj/item/dullahan_relay/Destroy()
|
||||
@@ -225,9 +235,20 @@
|
||||
return ..()
|
||||
|
||||
/obj/item/dullahan_relay/process()
|
||||
if(!istype(loc, /obj/item/bodypart/head) || QDELETED(owner))
|
||||
. = PROCESS_KILL
|
||||
qdel(src)
|
||||
if(istype(loc, /obj/item/bodypart/head) && !QDELETED(owner))
|
||||
return
|
||||
qdel(src)
|
||||
return PROCESS_KILL
|
||||
|
||||
/// Updates our names after applying name prefs
|
||||
/obj/item/dullahan_relay/proc/update_prefs_name(mob/living/carbon/human/wearer)
|
||||
SIGNAL_HANDLER
|
||||
var/obj/item/bodypart/head/detached_head = loc
|
||||
if (!istype(detached_head))
|
||||
return // It's so over
|
||||
detached_head.real_name = wearer.real_name
|
||||
detached_head.name = wearer.real_name
|
||||
detached_head.brain.name = "[wearer.name]'s brain"
|
||||
|
||||
/obj/item/dullahan_relay/proc/examinate_check(mob/user, atom/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -387,6 +387,25 @@
|
||||
burn_modifier = 1.25
|
||||
speed_modifier = 0.75 //big fungus big fungus
|
||||
|
||||
/// Dullahan head preserves organs inside it
|
||||
/obj/item/bodypart/head/dullahan
|
||||
throwforce = 25 // It's also a potent weapon
|
||||
show_organs_on_examine = FALSE
|
||||
speech_span = null
|
||||
|
||||
/obj/item/bodypart/head/dullahan/Entered(obj/item/organ/arrived, atom/old_loc, list/atom/old_locs)
|
||||
. = ..()
|
||||
if (!isorgan(arrived))
|
||||
return
|
||||
arrived.organ_flags |= ORGAN_FROZEN
|
||||
|
||||
/obj/item/bodypart/head/dullahan/Exited(obj/item/organ/gone, direction)
|
||||
. = ..()
|
||||
if (!isorgan(gone))
|
||||
return
|
||||
gone.organ_flags &= ~ORGAN_FROZEN
|
||||
|
||||
|
||||
//GOLEM
|
||||
/obj/item/bodypart/head/golem
|
||||
icon = 'icons/mob/human/species/golems.dmi'
|
||||
|
||||
Reference in New Issue
Block a user