mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-01 20:42:08 +00:00
## About The Pull Request HackMD: https://hackmd.io/RE9uRwSYSjCch17-OQ4pjQ?view Feedback link: https://tgstation13.org/phpBB/viewtopic.php?f=10&t=33972 Adds a Coroner job to the game, they work in the Medical department and have their office in the Morgue. I was inspired to make this after I had played my first round on Paradise and messed around in there. The analyzer is copied from there (https://github.com/ParadiseSS13/Paradise/pull/20957), and their jumpsuit is also mostly stolen from it (i just copied the color scheme onto our own suits). Coroners can perform autopsies on people to see their stats, like this  They have access to Medbay, and on lowpop will get Pharmacy (to make their own formaldehyde). They also have their own Secure Morgue access for their office (doubles as a surgery room because they are edgelords or whatever) and the secure morgue trays. Secure Morgue trays spawn with their beepers off and is only accessible by them, the CMO, and HoS. It's used to morgue Antagonists. Security's own morgue trays have been removed. The job in action https://cdn.discordapp.com/attachments/950489581151735849/1102297675669442570/2023-04-30_14-16-06.mp4 ### Surgery changes Autopsies are a Surgery, and I tried to intertwine this with the Dissection surgery. Dissections and Autopsies both require the Autopsy scanner to perform them, however you can only perform one on any given body. Dissections are for experiments, Autopsies is for the paper of information. Dissected bodies now also give a ~20% surgery speed boost, this was added at the request of Fikou as a way to encourage Doctors to let the Coroner do their job before reviving a body. I also remember the Medical skill, which allowed Doctors to do surgery faster on people, and I hope that this can do something like that WITHOUT adding the potential for exploiting, which led to the skill's downfall. ### Morgue Improvements Morgue trays are no longer named with pens, they instead will steal the name of the last bodybag to be put in them. Morgue trays are also removed from Brig Medical areas and Robotics, now they have to bring their corpses to the Morgue where the Coroner can keep track and ensure records are properly updated. ### Sprite credits I can't fit it all in the Changelog, so this is who made what McRamon - Autopsy scanner Tattax - Table clock sprites and in-hands CoiledLamb - Coroner jumpsuits & labcoats (inhand, on sprite, and their respective alternatives) - Coroner gloves - CoronerDrobe (the vending machine) ## Why It's Good For The Game This is mostly explained in the hackmd, but the goal of this is: 1. Increase the use of the Medical Records console. 2. Add a new and interesting way for Detectives to uncover mysteries. 3. Add a more RP-flavored role in Medical that still has mechanics tied behind it. ## Changelog 🆑 JohnFulpWillard, sprites by McRamon, tattax, and Lamb add: The Coroner, a new Medical role revolving around dead corpses and autopsies. add: The Coroner's Autopsy Scanner, used for discovering the cause for someone's death, listing their wounds, the causes of them, their reagents, and diseases (including stealth ones!) qol: Morgue Trays are now named after the bodybags inside of them. balance: The morgue now has 'Secure' morgue trays which by default don't beep. balance: Security Medical area and Robotics no longer have their own morgue trays. balance: Dissected bodies now have faster surgery speed. Autopsies also count as dissections, however they're mutually exclusive. /🆑 --------- Co-authored-by: Fikou <23585223+Fikou@users.noreply.github.com>
260 lines
12 KiB
Plaintext
260 lines
12 KiB
Plaintext
//Hulk turns your skin green, makes you strong, and allows you to shrug off stun effect.
|
|
/datum/mutation/human/hulk
|
|
name = "Hulk"
|
|
desc = "A poorly understood genome that causes the holder's muscles to expand, inhibit speech and gives the person a bad skin condition."
|
|
quality = POSITIVE
|
|
locked = TRUE
|
|
difficulty = 16
|
|
text_gain_indication = "<span class='notice'>Your muscles hurt!</span>"
|
|
species_allowed = list(SPECIES_HUMAN) //no skeleton/lizard hulk
|
|
health_req = 25
|
|
instability = 40
|
|
var/scream_delay = 50
|
|
var/last_scream = 0
|
|
/// List of traits to add/remove when someone gets this mutation.
|
|
var/static/list/mutation_traits = list(
|
|
TRAIT_CHUNKYFINGERS,
|
|
TRAIT_HULK,
|
|
TRAIT_IGNOREDAMAGESLOWDOWN,
|
|
TRAIT_PUSHIMMUNE,
|
|
TRAIT_STUNIMMUNE,
|
|
)
|
|
|
|
|
|
/datum/mutation/human/hulk/on_acquiring(mob/living/carbon/human/owner)
|
|
if(..())
|
|
return
|
|
owner.add_traits(mutation_traits, GENETIC_MUTATION)
|
|
for(var/obj/item/bodypart/part as anything in owner.bodyparts)
|
|
part.variable_color = "#00aa00"
|
|
owner.update_body_parts()
|
|
owner.add_mood_event("hulk", /datum/mood_event/hulk)
|
|
RegisterSignal(owner, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand))
|
|
RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(handle_speech))
|
|
RegisterSignal(owner, COMSIG_MOB_CLICKON, PROC_REF(check_swing))
|
|
|
|
/datum/mutation/human/hulk/proc/on_attack_hand(mob/living/carbon/human/source, atom/target, proximity, modifiers)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!proximity)
|
|
return
|
|
if(!source.combat_mode || LAZYACCESS(modifiers, RIGHT_CLICK))
|
|
return
|
|
if(target.attack_hulk(owner))
|
|
if(world.time > (last_scream + scream_delay))
|
|
last_scream = world.time
|
|
INVOKE_ASYNC(src, PROC_REF(scream_attack), source)
|
|
log_combat(source, target, "punched", "hulk powers")
|
|
source.do_attack_animation(target, ATTACK_EFFECT_SMASH)
|
|
source.changeNext_move(CLICK_CD_MELEE)
|
|
|
|
return COMPONENT_CANCEL_ATTACK_CHAIN
|
|
|
|
/datum/mutation/human/hulk/proc/scream_attack(mob/living/carbon/human/source)
|
|
source.say("WAAAAAAAAAAAAAAGH!", forced="hulk")
|
|
|
|
/**
|
|
*Checks damage of a hulk's arm and applies bone wounds as necessary.
|
|
*
|
|
*Called by specific atoms being attacked, such as walls. If an atom
|
|
*does not call this proc, than punching that atom will not cause
|
|
*arm breaking (even if the atom deals recoil damage to hulks).
|
|
*Arguments:
|
|
*arg1 is the arm to evaluate damage of and possibly break.
|
|
*/
|
|
/datum/mutation/human/hulk/proc/break_an_arm(obj/item/bodypart/arm)
|
|
switch(arm.brute_dam)
|
|
if(45 to 50)
|
|
arm.force_wound_upwards(/datum/wound/blunt/critical, wound_source = "hulk smashing")
|
|
if(41 to 45)
|
|
arm.force_wound_upwards(/datum/wound/blunt/severe, wound_source = "hulk smashing")
|
|
if(35 to 41)
|
|
arm.force_wound_upwards(/datum/wound/blunt/moderate, wound_source = "hulk smashing")
|
|
|
|
/datum/mutation/human/hulk/on_life(seconds_per_tick, times_fired)
|
|
if(owner.health < owner.crit_threshold)
|
|
on_losing(owner)
|
|
to_chat(owner, span_danger("You suddenly feel very weak."))
|
|
|
|
/datum/mutation/human/hulk/on_losing(mob/living/carbon/human/owner)
|
|
if(..())
|
|
return
|
|
owner.remove_traits(mutation_traits, GENETIC_MUTATION)
|
|
for(var/obj/item/bodypart/part as anything in owner.bodyparts)
|
|
part.variable_color = null
|
|
owner.update_body_parts()
|
|
owner.clear_mood_event("hulk")
|
|
UnregisterSignal(owner, COMSIG_HUMAN_EARLY_UNARMED_ATTACK)
|
|
UnregisterSignal(owner, COMSIG_MOB_SAY)
|
|
UnregisterSignal(owner, COMSIG_MOB_CLICKON)
|
|
|
|
/datum/mutation/human/hulk/proc/handle_speech(datum/source, list/speech_args)
|
|
SIGNAL_HANDLER
|
|
|
|
var/message = speech_args[SPEECH_MESSAGE]
|
|
if(message)
|
|
message = "[replacetext(message, ".", "!")]!!"
|
|
speech_args[SPEECH_MESSAGE] = message
|
|
|
|
// the reason we don't just uppertext(message) in this proc is so that our hulk speech
|
|
// can uppercase all other speech moidifiers after they are done (by returning COMPONENT_UPPERCASE_SPEECH)
|
|
return COMPONENT_UPPERCASE_SPEECH
|
|
|
|
/// How many steps it takes to throw the mob
|
|
#define HULK_TAILTHROW_STEPS 28
|
|
|
|
/// Run a barrage of checks to see if any given click is actually able to swing
|
|
/datum/mutation/human/hulk/proc/check_swing(mob/living/carbon/human/user, atom/clicked_atom, list/modifiers)
|
|
SIGNAL_HANDLER
|
|
|
|
/// Basically, we only proceed if we're in throw mode with a tailed carbon in our grasp with at least a neck grab and we're not restrained in some way
|
|
if(LAZYACCESS(modifiers, ALT_CLICK) || LAZYACCESS(modifiers, SHIFT_CLICK) || LAZYACCESS(modifiers, CTRL_CLICK) || LAZYACCESS(modifiers, MIDDLE_CLICK))
|
|
return
|
|
if(!user.throw_mode || user.get_active_held_item() || user.zone_selected != BODY_ZONE_PRECISE_GROIN)
|
|
return
|
|
if(user.grab_state < GRAB_NECK || !iscarbon(user.pulling) || user.buckled || user.incapacitated())
|
|
return
|
|
|
|
var/mob/living/carbon/possible_throwable = user.pulling
|
|
if(!possible_throwable.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL))
|
|
return
|
|
|
|
if(ishuman(possible_throwable))
|
|
var/mob/living/carbon/human/human_throwable = possible_throwable
|
|
if(human_throwable.wear_suit && (human_throwable.wear_suit.flags_inv & HIDEJUMPSUIT))
|
|
to_chat(user, span_warning("You can't reach [human_throwable]'s tail through [human_throwable.p_their()] [human_throwable.wear_suit.name]!"))
|
|
return
|
|
|
|
user.face_atom(clicked_atom)
|
|
INVOKE_ASYNC(src, PROC_REF(setup_swing), user, possible_throwable)
|
|
return(COMSIG_MOB_CANCEL_CLICKON)
|
|
|
|
/// Do a short 2 second do_after before starting the actual swing
|
|
/datum/mutation/human/hulk/proc/setup_swing(mob/living/carbon/human/the_hulk, mob/living/carbon/yeeted_person)
|
|
var/original_dir = the_hulk.dir // so no matter if the hulk tries to mess up their direction, they always face where they started when they throw
|
|
|
|
yeeted_person.forceMove(the_hulk.loc)
|
|
yeeted_person.setDir(get_dir(yeeted_person, the_hulk))
|
|
|
|
log_combat(the_hulk, yeeted_person, "has started swinging by tail")
|
|
yeeted_person.Stun(2 SECONDS)
|
|
yeeted_person.visible_message(span_danger("[the_hulk] starts grasping [yeeted_person] by the tail..."), \
|
|
span_userdanger("[the_hulk] begins grasping your tail!"), span_hear("You hear aggressive shuffling!"), null, the_hulk)
|
|
to_chat(the_hulk, span_danger("You start grasping [yeeted_person] by the tail..."))
|
|
|
|
if(!do_after(the_hulk, 2 SECONDS, yeeted_person))
|
|
yeeted_person.visible_message(span_danger("[yeeted_person] breaks free of [the_hulk]'s grasp!"), \
|
|
span_userdanger("You break free from [the_hulk]'s grasp!"), span_hear("You hear aggressive shuffling!"), null, the_hulk)
|
|
to_chat(the_hulk, span_danger("You lose your grasp on [yeeted_person]'s tail!"))
|
|
return
|
|
|
|
// we're officially a-go!
|
|
yeeted_person.Paralyze(8 SECONDS)
|
|
yeeted_person.visible_message(span_danger("[the_hulk] starts spinning [yeeted_person] around by [yeeted_person.p_their()] tail!"), \
|
|
span_userdanger("[the_hulk] starts spinning you around by your tail!"), span_hear("You hear wooshing sounds!"), null, the_hulk)
|
|
to_chat(the_hulk, span_danger("You start spinning [yeeted_person] around by [yeeted_person.p_their()] tail!"))
|
|
the_hulk.emote("scream")
|
|
yeeted_person.emote("scream")
|
|
swing_loop(the_hulk, yeeted_person, 0, original_dir)
|
|
|
|
/**
|
|
* Does the animations for the hulk swing loop
|
|
*
|
|
* This code is based in part on the wrestling swing code ported from goon, see [code/datums/martial/wrestling.dm]
|
|
* credit to: cogwerks, pistoleer, spyguy, angriestibm, marquesas, and stuntwaffle.
|
|
* For each step of the swinging, with the delay getting shorter along the way. Checks to see we still have them in our grasp at each step.
|
|
*/
|
|
/datum/mutation/human/hulk/proc/swing_loop(mob/living/carbon/human/the_hulk, mob/living/carbon/yeeted_person, step, original_dir)
|
|
if(!yeeted_person || !the_hulk || the_hulk.incapacitated())
|
|
return
|
|
if(get_dist(the_hulk, yeeted_person) > 1 || !isturf(the_hulk.loc) || !isturf(yeeted_person.loc))
|
|
to_chat(the_hulk, span_warning("You lose your grasp on [yeeted_person]!"))
|
|
return
|
|
|
|
var/delay = 5
|
|
switch (step)
|
|
if(24 to INFINITY)
|
|
delay = 0.1
|
|
if(20 to 23)
|
|
delay = 0.5
|
|
if(16 to 19)
|
|
delay = 1
|
|
if(13 to 15)
|
|
delay = 2
|
|
if(8 to 12)
|
|
delay = 3
|
|
if(4 to 7)
|
|
delay = 3.5
|
|
if(0 to 3)
|
|
delay = 4
|
|
|
|
the_hulk.setDir(turn(the_hulk.dir, 90))
|
|
var/turf/current_spin_turf = yeeted_person.loc
|
|
var/turf/intermediate_spin_turf = get_step(yeeted_person, the_hulk.dir) // the diagonal
|
|
var/turf/next_spin_turf = get_step(the_hulk, the_hulk.dir)
|
|
var/direction = get_dir(current_spin_turf, intermediate_spin_turf)
|
|
|
|
if((isturf(current_spin_turf) && current_spin_turf.Exit(yeeted_person, direction)) && (isturf(next_spin_turf) && next_spin_turf.Enter(yeeted_person)))
|
|
yeeted_person.forceMove(next_spin_turf)
|
|
yeeted_person.face_atom(the_hulk)
|
|
|
|
var/list/collateral_check = intermediate_spin_turf.contents + next_spin_turf.contents // check the cardinal and the diagonal tiles we swung past
|
|
var/turf/collat_throw_target = get_edge_target_turf(yeeted_person, get_dir(current_spin_turf, next_spin_turf)) // what direction we're swinging
|
|
|
|
for(var/mob/living/collateral_mob in collateral_check)
|
|
if(!collateral_mob.density || collateral_mob == yeeted_person)
|
|
continue
|
|
|
|
yeeted_person.adjustBruteLoss(step*0.5)
|
|
playsound(collateral_mob,'sound/weapons/punch1.ogg',50,TRUE)
|
|
log_combat(the_hulk, collateral_mob, "has smacked with tail swing victim")
|
|
log_combat(the_hulk, yeeted_person, "has smacked this person into someone while tail swinging") // i have no idea how to better word this
|
|
|
|
if(collateral_mob == the_hulk) // if the hulk moves wrong and crosses himself
|
|
the_hulk.visible_message(span_warning("[the_hulk] smacks [the_hulk.p_them()]self with [yeeted_person]!"), span_userdanger("You end up smacking [yeeted_person] into yourself!"), ignored_mobs = yeeted_person)
|
|
to_chat(yeeted_person, span_userdanger("[the_hulk] smacks you into [the_hulk.p_them()]self, turning you free!"))
|
|
the_hulk.adjustBruteLoss(step)
|
|
return
|
|
|
|
yeeted_person.visible_message(span_warning("[the_hulk] swings [yeeted_person] directly into [collateral_mob], sending [collateral_mob.p_them()] flying!"), \
|
|
span_userdanger("You're smacked into [collateral_mob]!"), ignored_mobs = collateral_mob)
|
|
to_chat(collateral_mob, span_userdanger("[the_hulk] swings [yeeted_person] directly into you, sending you flying!"))
|
|
|
|
collateral_mob.adjustBruteLoss(step*0.5)
|
|
collateral_mob.throw_at(collat_throw_target, round(step * 0.25) + 1, round(step * 0.25) + 1)
|
|
step -= 5
|
|
delay += 5
|
|
|
|
step++
|
|
if(step >= HULK_TAILTHROW_STEPS)
|
|
finish_swing(the_hulk, yeeted_person, original_dir)
|
|
else if(step < 0)
|
|
the_hulk.visible_message(span_danger("[the_hulk] loses [the_hulk.p_their()] momentum on [yeeted_person]!"), span_warning("You lose your momentum on swinging [yeeted_person]!"), ignored_mobs = yeeted_person)
|
|
to_chat(yeeted_person, span_userdanger("[the_hulk] loses [the_hulk.p_their()] momentum and lets go of you!"))
|
|
else
|
|
addtimer(CALLBACK(src, PROC_REF(swing_loop), the_hulk, yeeted_person, step, original_dir), delay)
|
|
|
|
/// Time to toss the victim at high speed
|
|
/datum/mutation/human/hulk/proc/finish_swing(mob/living/carbon/human/the_hulk, mob/living/carbon/yeeted_person, original_dir)
|
|
if(!yeeted_person || !the_hulk || the_hulk.incapacitated())
|
|
return
|
|
if(get_dist(the_hulk, yeeted_person) > 1 || !isturf(the_hulk.loc) || !isturf(yeeted_person.loc))
|
|
to_chat(the_hulk, span_warning("You lose your grasp on [yeeted_person]!"))
|
|
return
|
|
|
|
the_hulk.setDir(original_dir)
|
|
yeeted_person.forceMove(the_hulk.loc) // Maybe this will help with the wallthrowing bug.
|
|
yeeted_person.visible_message(span_danger("[the_hulk] throws [yeeted_person]!"), \
|
|
span_userdanger("You're thrown by [the_hulk]!"), span_hear("You hear aggressive shuffling and a loud thud!"), null, the_hulk)
|
|
to_chat(the_hulk, span_danger("You throw [yeeted_person]!"))
|
|
playsound(the_hulk.loc, SFX_SWING_HIT, 50, TRUE)
|
|
var/turf/T = get_edge_target_turf(the_hulk, the_hulk.dir)
|
|
if(!isturf(T))
|
|
return
|
|
if(!yeeted_person.stat)
|
|
yeeted_person.emote("scream")
|
|
yeeted_person.throw_at(T, 10, 6, the_hulk, TRUE, TRUE)
|
|
log_combat(the_hulk, yeeted_person, "has thrown by tail")
|
|
|
|
#undef HULK_TAILTHROW_STEPS
|