Facehuggers dont sleep people + muzzle code exorcism (#83721)

## About The Pull Request

Facehuggers dont make people fall asleep, instead making them unable if
on (already was in), and muffling speech
Xenomorphs still have decent tools to stun people in melee thats stuff
for another pr

muzzle is now an element and also just makes you talk like
word word word -> mmmmf mmmf mf
COMPLETELY evaporates BLOCKS_SPEECH flag

## Why It's Good For The Game

Being instantly sent to sleep by a facehugger thrown the hunter that
materialized from a vent then getting dragged to their goon cave where
you spend 2 minutes to get gibbed so someone else but you can play antag
is just extremely unfun
This should allow you to survive if youre quick enough after getting
hugged instead of being forced to get gibbed, allowing cooler xenomorph
combat (you could try fistfighting the dude or something idk)
This commit is contained in:
jimmyl
2024-07-01 17:50:19 +02:00
committed by GitHub
parent fe7da20ea3
commit cd2dda91ee
16 changed files with 109 additions and 46 deletions
@@ -155,7 +155,7 @@
///Mob is trying to open the wires of a target [/atom], from /datum/wires/interactable(): (atom/target)
#define COMSIG_TRY_WIRES_INTERACT "try_wires_interact"
#define COMPONENT_CANT_INTERACT_WIRES (1<<0)
///Mob is trying to emote, from /datum/emote/proc/run_emote(): (key, params, type_override, intentional)
///Mob is trying to emote, from /datum/emote/proc/run_emote(): (key, params, type_override, intentional, emote)
#define COMSIG_MOB_PRE_EMOTED "mob_pre_emoted"
#define COMPONENT_CANT_EMOTE (1<<0)
#define COMSIG_MOB_EMOTED(emote_key) "mob_emoted_[emote_key]"
+6 -8
View File
@@ -75,20 +75,18 @@
#define DANGEROUS_OBJECT (1<<10)
/// Clothes that use large icons, for applying the proper overlays like blood
#define LARGE_WORN_ICON (1<<11)
/// Clothes that block speech (i.e the muzzle). Can be applied to any clothing piece.
#define BLOCKS_SPEECH (1<<12)
/// prevents from placing on plasmaman helmet or modsuit hat holder
#define STACKABLE_HELMET_EXEMPT (1<<13)
#define STACKABLE_HELMET_EXEMPT (1<<12)
/// Prevents plasmamen from igniting when wearing this
#define PLASMAMAN_PREVENT_IGNITION (1<<14)
#define PLASMAMAN_PREVENT_IGNITION (1<<13)
/// Usable as casting clothes by wizards (matters for suits, glasses and headwear)
#define CASTING_CLOTHES (1<<15)
#define CASTING_CLOTHES (1<<14)
///Moths can't eat the clothing that has this flag.
#define INEDIBLE_CLOTHING (1<<16)
#define INEDIBLE_CLOTHING (1<<15)
/// Headgear/helmet allows internals
#define HEADINTERNALS (1<<17)
#define HEADINTERNALS (1<<16)
/// Prevents masks from getting adjusted from enabling internals
#define INTERNALS_ADJUST_EXEMPT (1<<18)
#define INTERNALS_ADJUST_EXEMPT (1<<17)
/// Integrity defines for clothing (not flags but close enough)
#define CLOTHING_PRISTINE 0 // We have no damage on the clothing
-1
View File
@@ -83,7 +83,6 @@ DEFINE_BITFIELD(car_traits, list(
DEFINE_BITFIELD(clothing_flags, list(
"ANTI_TINFOIL_MANEUVER" = ANTI_TINFOIL_MANEUVER,
"BLOCKS_SPEECH" = BLOCKS_SPEECH,
"BLOCK_GAS_SMOKE_EFFECT" = BLOCK_GAS_SMOKE_EFFECT,
"CASTING_CLOTHES" = CASTING_CLOTHES,
"GAS_FILTERING" = GAS_FILTERING,
+4
View File
@@ -23,6 +23,10 @@
/datum/component/knockoff/RegisterWithParent()
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equipped))
RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_dropped))
var/atom/movable/atom_parent = parent
var/mob/living/as_mob = atom_parent.loc
if(ismob(as_mob))
on_equipped(atom_parent, as_mob, as_mob.get_slot_by_item(atom_parent)) // lie a little
/datum/component/knockoff/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
+48
View File
@@ -0,0 +1,48 @@
/datum/element/muffles_speech
/datum/element/muffles_speech/Attach(datum/target)
. = ..()
if(!isitem(target))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_ITEM_EQUIPPED, PROC_REF(equipped))
RegisterSignal(target, COMSIG_ITEM_DROPPED, PROC_REF(dropped))
/datum/element/muffles_speech/Detach(datum/source)
. = ..()
UnregisterSignal(source, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
/datum/element/muffles_speech/proc/equipped(obj/item/source, mob/user, slot)
SIGNAL_HANDLER
if(source.slot_flags & slot)
RegisterSignal(user, COMSIG_MOB_SAY, PROC_REF(muzzle_talk))
RegisterSignal(user, COMSIG_MOB_PRE_EMOTED, PROC_REF(emote_override))
/datum/element/muffles_speech/proc/dropped(obj/item/source, mob/user)
SIGNAL_HANDLER
UnregisterSignal(user, list(COMSIG_MOB_PRE_EMOTED, COMSIG_MOB_SAY))
/datum/element/muffles_speech/proc/emote_override(mob/living/source, key, params, type_override, intentional, datum/emote/emote)
SIGNAL_HANDLER
if(!emote.hands_use_check && (emote.emote_type & EMOTE_AUDIBLE))
source.audible_message("makes a [pick("strong ", "weak ", "")]noise.", audible_message_flags = EMOTE_MESSAGE|ALWAYS_SHOW_SELF_MESSAGE)
return COMPONENT_CANT_EMOTE
return NONE
/datum/element/muffles_speech/proc/muzzle_talk(datum/source, list/speech_args)
SIGNAL_HANDLER
var/spoken_message = speech_args[SPEECH_MESSAGE]
if(spoken_message)
var/list/words = splittext(spoken_message, " ")
var/yell_suffix = copytext(spoken_message, findtext(spoken_message, "!"))
spoken_message = ""
for(var/ind = 1 to length(words))
var/new_word = ""
for(var/i = 1 to length(words[ind]) + rand(-1,1))
new_word += "m"
new_word += "f"
words[ind] = yell_suffix ? uppertext(new_word) : new_word
spoken_message = "[jointext(words, " ")][yell_suffix]"
speech_args[SPEECH_MESSAGE] = spoken_message
+2 -8
View File
@@ -38,8 +38,6 @@
var/emote_type = EMOTE_VISIBLE
/// Checks if the mob can use its hands before performing the emote.
var/hands_use_check = FALSE
/// Will only work if the emote is EMOTE_AUDIBLE.
var/muzzle_ignore = FALSE
/// Types that are allowed to use that emote.
var/list/mob_type_allowed_typecache = /mob
/// Types that are NOT allowed to use that emote.
@@ -90,7 +88,7 @@
/datum/emote/proc/run_emote(mob/user, params, type_override, intentional = FALSE)
if(!can_run_emote(user, TRUE, intentional))
return FALSE
if(SEND_SIGNAL(user, COMSIG_MOB_PRE_EMOTED, key, params, type_override, intentional) & COMPONENT_CANT_EMOTE)
if(SEND_SIGNAL(user, COMSIG_MOB_PRE_EMOTED, key, params, type_override, intentional, src) & COMPONENT_CANT_EMOTE)
return TRUE // We don't return FALSE because the error output would be incorrect, provide your own if necessary.
var/msg = select_message_type(user, message, intentional)
if(params && message_param)
@@ -259,8 +257,6 @@
return .
var/mob/living/living_user = user
if(!muzzle_ignore && user.is_muzzled() && emote_type & EMOTE_AUDIBLE)
return "makes a [pick("strong ", "weak ", "")]noise."
if(HAS_MIND_TRAIT(user, TRAIT_MIMING) && message_mime)
. = message_mime
if(isalienadult(user) && message_alien)
@@ -338,9 +334,7 @@
* Returns a bool about whether or not the user should play a sound when performing the emote.
*/
/datum/emote/proc/should_play_sound(mob/user, intentional = FALSE)
if(emote_type & EMOTE_AUDIBLE && !muzzle_ignore)
if(user.is_muzzled())
return FALSE
if(emote_type & EMOTE_AUDIBLE && !hands_use_check)
if(HAS_TRAIT(user, TRAIT_MUTE))
return FALSE
if(ishuman(user))
+6 -3
View File
@@ -5,11 +5,14 @@
inhand_icon_state = "blindfold"
lefthand_file = 'icons/mob/inhands/clothing/glasses_lefthand.dmi'
righthand_file = 'icons/mob/inhands/clothing/glasses_righthand.dmi'
clothing_flags = BLOCKS_SPEECH
flags_cover = MASKCOVERSMOUTH
w_class = WEIGHT_CLASS_SMALL
equip_delay_other = 20
/obj/item/clothing/mask/muzzle/Initialize(mapload)
. = ..()
AddElement(/datum/element/muffles_speech)
/obj/item/clothing/mask/muzzle/attack_paw(mob/user, list/modifiers)
if(iscarbon(user))
var/mob/living/carbon/carbon_user = user
@@ -26,7 +29,7 @@
lefthand_file = 'icons/mob/inhands/clothing/masks_lefthand.dmi'
righthand_file = 'icons/mob/inhands/clothing/masks_righthand.dmi'
body_parts_covered = NONE
clothing_flags = MASKINTERNALS | BLOCKS_SPEECH
clothing_flags = MASKINTERNALS
armor_type = /datum/armor/muzzle_breath
equip_delay_other = 25 // my sprite has 4 straps, a-la a head harness. takes a while to equip, longer than a muzzle
@@ -37,7 +40,7 @@
worn_icon_state = "tape_piece_worn"
inhand_icon_state = null
w_class = WEIGHT_CLASS_TINY
clothing_flags = INEDIBLE_CLOTHING|BLOCKS_SPEECH
clothing_flags = INEDIBLE_CLOTHING
equip_delay_other = 40
strip_delay = 40
greyscale_config = /datum/greyscale_config/tape_piece
@@ -251,7 +251,8 @@ Doesn't work on other aliens/AI.*/
plasma_cost = 50
/datum/action/cooldown/alien/acid/neurotoxin/IsAvailable(feedback = FALSE)
if(owner.is_muzzled())
var/mob/living/carbon/as_carbon = owner
if(istype(as_carbon) && as_carbon.is_mouth_covered(ITEM_SLOT_MASK))
return FALSE
if(!isturf(owner.loc))
return FALSE
@@ -76,6 +76,7 @@
return pick (list("xltrails_1", "xltrails2"))
else
return pick (list("xttrails_1", "xttrails2"))
/*----------------------------------------
Proc: AddInfectionImages()
Des: Gives the client of the alien an image on each infected mob.
@@ -24,6 +24,7 @@
layer = MOB_LAYER
max_integrity = 100
item_flags = XENOMORPH_HOLDABLE
slowdown = 2
var/stat = CONSCIOUS //UNCONSCIOUS is the idle state in this case
var/sterile = FALSE
@@ -39,6 +40,7 @@
)
AddElement(/datum/element/connect_loc, loc_connections)
AddElement(/datum/element/atmos_sensitive, mapload)
AddElement(/datum/element/muffles_speech)
RegisterSignal(src, COMSIG_LIVING_TRYING_TO_PULL, PROC_REF(react_to_mob))
@@ -122,7 +124,7 @@
/obj/item/clothing/mask/facehugger/proc/valid_to_attach(mob/living/hit_mob)
// valid targets: carbons except aliens and devils
// facehugger state early exit checks
// facehugger state early exit checks (Note: Melbert does not want dead people to be huggable)
if(stat != CONSCIOUS)
return FALSE
if(attached)
@@ -171,9 +173,12 @@
log_combat(target, src, "was facehugged by")
return TRUE // time for a smoke
/obj/item/clothing/mask/facehugger/proc/Attach(mob/living/M)
if(!valid_to_attach(M))
/obj/item/clothing/mask/facehugger/proc/Attach(mob/living/victim)
if(!valid_to_attach(victim))
return
if(victim.stat < UNCONSCIOUS) //sorry bro you gotta be awake
victim.say("AAAA!!") //triggers muffled speech and also visual feedback i guess
// early returns and validity checks done: attach.
attached++
//ensure we detach once we no longer need to be attached
@@ -181,12 +186,12 @@
if(!sterile)
M.take_bodypart_damage(strength,0) //done here so that humans in helmets take damage
M.Unconscious(MAX_IMPREGNATION_TIME/0.3) //something like 25 ticks = 20 seconds with the default settings
victim.take_bodypart_damage(strength,0) //done here so that humans in helmets take damage
if(real && !sterile)
victim.Knockdown(5 SECONDS)
GoIdle() //so it doesn't jump the people that tear it off
addtimer(CALLBACK(src, PROC_REF(Impregnate), M), rand(MIN_IMPREGNATION_TIME, MAX_IMPREGNATION_TIME))
addtimer(CALLBACK(src, PROC_REF(Impregnate), victim), rand(MIN_IMPREGNATION_TIME, MAX_IMPREGNATION_TIME))
/obj/item/clothing/mask/facehugger/proc/detach()
attached = 0
@@ -249,6 +254,29 @@
visible_message(span_danger("[src] curls up into a ball!"))
// chest maybe because getting slammed in the chest would knock it off your face while dead
AddComponent(/datum/component/knockoff, knockoff_chance = 40, target_zones = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST), slots_knockoffable = slot_flags)
/obj/item/clothing/mask/facehugger/allow_attack_hand_drop(mob/living/carbon/human/user)
if(!real || sterile || user.get_organ_by_type(/obj/item/organ/internal/body_egg/alien_embryo))
return ..()
if(istype(user) && ishuman(loc) && stat != DEAD)
if(user == loc && user.get_item_by_slot(slot_flags) == src)
to_chat(user, span_userdanger("[src] is latched on too tight! Get help or wait for it to let go!"))
return FALSE
return ..()
/obj/item/clothing/mask/facehugger/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params)
var/mob/living/carbon/human/wearer = loc
if(!istype(wearer) || user != wearer)
return
if(!real || sterile || user.get_organ_by_type(/obj/item/organ/internal/body_egg/alien_embryo))
return ..()
if(wearer.get_item_by_slot(slot_flags) == src && stat != DEAD)
to_chat(user, span_userdanger("[src] is latched on too tight! Get help or wait for it to let go!"))
return
return ..()
/proc/CanHug(mob/living/M)
if(!istype(M))
return FALSE
@@ -268,6 +296,7 @@
name = "Lamarr"
desc = "The Research Director's pet, a domesticated and debeaked xenomorph facehugger. Friendly, but may still try to couple with your head."
sterile = TRUE
slowdown = 1.5 //lamarr is too fat after being fed in captivity to effectively slow people down or something
/obj/item/clothing/mask/facehugger/dead
icon_state = "facehugger_dead"
@@ -287,6 +316,7 @@
real = FALSE
sterile = TRUE
tint = 3 //Makes it feel more authentic when it latches on
slowdown = 0
/obj/item/clothing/mask/facehugger/toy/Die()
return
-7
View File
@@ -228,13 +228,6 @@
. = ..()
loc.handle_fall(src)//it's loc so it doesn't call the mob's handle_fall which does nothing
/mob/living/carbon/is_muzzled()
for (var/obj/item/clothing/clothing in get_equipped_items())
if(clothing.clothing_flags & BLOCKS_SPEECH)
return TRUE
return FALSE
/mob/living/carbon/resist_buckle()
if(!HAS_TRAIT(src, TRAIT_RESTRAINED))
buckled.user_unbuckle_mob(src, src)
-2
View File
@@ -20,7 +20,6 @@
key = "clap"
key_third_person = "claps"
message = "claps."
muzzle_ignore = TRUE
hands_use_check = TRUE
emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE
audio_cooldown = 5 SECONDS
@@ -185,7 +184,6 @@
message_param = "snaps their fingers at %t."
emote_type = EMOTE_AUDIBLE | EMOTE_VISIBLE
hands_use_check = TRUE
muzzle_ignore = TRUE
/datum/emote/living/carbon/snap/get_sound(mob/living/user)
if(ishuman(user))
+1 -1
View File
@@ -411,7 +411,7 @@
if(!user.get_bodypart(BODY_ZONE_HEAD))
return FALSE
if(user.is_muzzled() || user.is_mouth_covered(ITEM_SLOT_MASK))
if(user.is_mouth_covered(ITEM_SLOT_MASK))
to_chat(user, span_warning("You can't bite with your mouth covered!"))
return FALSE
-4
View File
@@ -805,10 +805,6 @@
set category = null
return
///Is the mob muzzled (default false)
/mob/proc/is_muzzled()
return FALSE
/// Adds this list to the output to the stat browser
/mob/proc/get_status_tab_items()
. = list("") //we want to offset unique stuff from standard stuff
-3
View File
@@ -106,9 +106,6 @@
if(!allow_mimes && HAS_MIND_TRAIT(src, TRAIT_MIMING))
return FALSE
if(is_muzzled())
return FALSE
return ..()
///Speak as a dead person (ghost etc)
+1
View File
@@ -1473,6 +1473,7 @@
#include "code\datums\elements\move_force_on_death.dm"
#include "code\datums\elements\movement_turf_changer.dm"
#include "code\datums\elements\movetype_handler.dm"
#include "code\datums\elements\muffles_speech.dm"
#include "code\datums\elements\nerfed_pulling.dm"
#include "code\datums\elements\noisy_movement.dm"
#include "code\datums\elements\noticable_organ.dm"