mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-20 12:35:33 +01:00
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:
@@ -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]"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user