mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
Recovered Crew | Medical+Cargo Respawns (#87072)
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com> Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
This commit is contained in:
@@ -123,6 +123,14 @@
|
||||
#define JOB_CENTCOM_SPECIAL_OFFICER "Special Ops Officer"
|
||||
#define JOB_CENTCOM_PRIVATE_SECURITY "Private Security Force"
|
||||
|
||||
//Lost crew
|
||||
#define JOB_LOSTCREW_ENGINEER "Visiting Engineer"
|
||||
#define JOB_LOSTCREW_MEDICAL "Visiting Doctor"
|
||||
#define JOB_LOSTCREW_SECURITY "Visiting Officer"
|
||||
#define JOB_LOSTCREW_SCIENCE "Visiting Scientist"
|
||||
#define JOB_LOSTCREW_CARGO "Visiting Technician"
|
||||
#define JOB_LOSTCREW_CIVILLIAN "Visiting Civillian"
|
||||
|
||||
#define JOB_GROUP_ENGINEERS list( \
|
||||
JOB_STATION_ENGINEER, \
|
||||
JOB_ATMOSPHERIC_TECHNICIAN, \
|
||||
|
||||
@@ -84,6 +84,8 @@
|
||||
#define ROLE_SYNDICATE_MEDBORG "Syndicate Medical Cyborg"
|
||||
#define ROLE_SYNDICATE_ASSAULTBORG "Syndicate Assault Cyborg"
|
||||
|
||||
#define ROLE_RECOVERED_CREW "Recovered Crew"
|
||||
|
||||
//Spawner roles
|
||||
#define ROLE_ANCIENT_CREW "Ancient Crew"
|
||||
#define ROLE_ASHWALKER "Ash Walker"
|
||||
@@ -167,6 +169,7 @@ GLOBAL_LIST_INIT(special_roles, list(
|
||||
ROLE_GLITCH = 0,
|
||||
ROLE_PAI = 0,
|
||||
ROLE_SENTIENCE = 0,
|
||||
ROLE_RECOVERED_CREW = 0,
|
||||
))
|
||||
|
||||
//Job defines for what happens when you fail to qualify for any job during job selection
|
||||
|
||||
@@ -69,6 +69,9 @@ When using time2text(), please use "DDD" to find the weekday. Refrain from using
|
||||
|
||||
#define HOURS MINUTES*60
|
||||
|
||||
#define DAYS HOURS*24
|
||||
#define YEARS DAYS*365 //fuck leap days, they were removed in 2069
|
||||
|
||||
#define TICKS *world.tick_lag
|
||||
|
||||
#define DS2TICKS(DS) ((DS)/world.tick_lag)
|
||||
|
||||
@@ -1352,5 +1352,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
|
||||
///A "fake" effect that should not be subject to normal effect removal methods (like the effect remover component)
|
||||
#define TRAIT_ILLUSORY_EFFECT "illusory_effect"
|
||||
/// Gives a little examine to their body that they can be revived with a soul
|
||||
#define TRAIT_GHOSTROLE_ON_REVIVE "ghostrole_on_revive"
|
||||
|
||||
// END TRAIT DEFINES
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#define POLL_IGNORE_STALKER "stalker"
|
||||
#define POLL_IGNORE_SYNDICATE "syndicate"
|
||||
#define POLL_IGNORE_VENUSHUMANTRAP "venus_human_trap"
|
||||
#define POLL_IGNORE_RECOVERED_CREW "recovered_crew"
|
||||
|
||||
GLOBAL_LIST_INIT(poll_ignore_desc, list(
|
||||
POLL_IGNORE_ACADEMY_WIZARD = "Academy Wizard Defender",
|
||||
@@ -74,6 +75,7 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list(
|
||||
POLL_IGNORE_STALKER = "Stalker",
|
||||
POLL_IGNORE_SYNDICATE = "Syndicate",
|
||||
POLL_IGNORE_VENUSHUMANTRAP = "Venus Human Traps",
|
||||
POLL_IGNORE_RECOVERED_CREW = "recovered_crew",
|
||||
))
|
||||
GLOBAL_LIST_INIT(poll_ignore, init_poll_ignore())
|
||||
|
||||
|
||||
@@ -564,6 +564,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_SPEECH_BOOSTER" = TRAIT_SPEECH_BOOSTER,
|
||||
"TRAIT_MINING_PARRYING" = TRAIT_MINING_PARRYING,
|
||||
"TRAIT_ILLUSORY_EFFECT" = TRAIT_ILLUSORY_EFFECT,
|
||||
"TRAIT_GHOSTROLE_ON_REVIVE" = TRAIT_GHOSTROLE_ON_REVIVE,
|
||||
"TRAIT_IGNORE_FIRE_PROTECTION" = TRAIT_IGNORE_FIRE_PROTECTION,
|
||||
"TRAIT_LEFT_EYE_SCAR" = TRAIT_LEFT_EYE_SCAR,
|
||||
"TRAIT_RIGHT_EYE_SCAR" = TRAIT_RIGHT_EYE_SCAR,
|
||||
|
||||
@@ -261,7 +261,7 @@
|
||||
candidates -= player
|
||||
else if(is_centcom_level(player.z))
|
||||
candidates -= player // We don't autotator people in CentCom
|
||||
else if(player.mind && (player.mind.special_role || player.mind.antag_datums?.len > 0))
|
||||
else if(player.mind && (player.mind.special_role || player.mind.can_roll_midround()))
|
||||
candidates -= player // We don't autotator people with roles already
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_living/autotraitor/execute()
|
||||
@@ -310,7 +310,7 @@
|
||||
continue
|
||||
if(isnull(player.mind))
|
||||
continue
|
||||
if(player.mind.special_role || length(player.mind.antag_datums))
|
||||
if(player.mind.special_role || player.mind.can_roll_midround())
|
||||
continue
|
||||
candidates += player
|
||||
|
||||
@@ -479,7 +479,7 @@
|
||||
candidates -= player
|
||||
continue
|
||||
|
||||
if(player.mind && (player.mind.special_role || length(player.mind.antag_datums) > 0))
|
||||
if(player.mind && (player.mind.special_role || player.mind.can_roll_midround()))
|
||||
candidates -= player
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_living/blob_infection/execute()
|
||||
|
||||
@@ -30,3 +30,8 @@
|
||||
icon_state = "bags"
|
||||
draw_color = COLOR_WEBSAFE_DARK_GRAY
|
||||
layers = EXTERNAL_ADJACENT
|
||||
|
||||
///PENDING eyes drawn on the face
|
||||
/datum/bodypart_overlay/simple/soul_pending_eyes
|
||||
icon_state = "soul_pending_eyes"
|
||||
layers = EXTERNAL_FRONT
|
||||
|
||||
119
code/datums/components/ghostrole_on_revive.dm
Normal file
119
code/datums/components/ghostrole_on_revive.dm
Normal file
@@ -0,0 +1,119 @@
|
||||
/// Proc ghosts to enter the body when it get's revived
|
||||
/datum/component/ghostrole_on_revive
|
||||
/// If revived and no ghosts, just die again?
|
||||
var/refuse_revival_if_failed
|
||||
/// Callback for when the mob is revived and has their body occupied by a ghost
|
||||
var/datum/callback/on_succesful_revive
|
||||
|
||||
/datum/component/ghostrole_on_revive/Initialize(refuse_revival_if_failed, on_succesful_revive)
|
||||
. = ..()
|
||||
|
||||
src.refuse_revival_if_failed = refuse_revival_if_failed
|
||||
src.on_succesful_revive = on_succesful_revive
|
||||
|
||||
ADD_TRAIT(parent, TRAIT_GHOSTROLE_ON_REVIVE, REF(src)) //for adding an alternate examination
|
||||
|
||||
if(ismob(parent))
|
||||
prepare_mob(parent)
|
||||
return
|
||||
|
||||
if(!istype(parent, /obj/item/organ/internal/brain))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
var/obj/item/organ/internal/brain/brein = parent
|
||||
if(brein.owner)
|
||||
prepare_mob(brein.owner)
|
||||
else
|
||||
prepare_brain(brein)
|
||||
|
||||
/// Give the appropriate signals, and watch for organ removal
|
||||
/datum/component/ghostrole_on_revive/proc/prepare_mob(mob/living/liver)
|
||||
RegisterSignal(liver, COMSIG_LIVING_REVIVE, PROC_REF(on_revive))
|
||||
ADD_TRAIT(liver, TRAIT_GHOSTROLE_ON_REVIVE, REF(src))
|
||||
liver.med_hud_set_status()
|
||||
|
||||
if(iscarbon(liver))
|
||||
var/mob/living/carbon/carbon = liver
|
||||
var/obj/item/organ/brain = carbon.get_organ_by_type(/obj/item/organ/internal/brain)
|
||||
if(brain)
|
||||
RegisterSignal(brain, COMSIG_ORGAN_REMOVED, PROC_REF(on_remove))
|
||||
|
||||
/datum/component/ghostrole_on_revive/proc/on_remove(obj/item/organ/brain, mob/living/old_owner)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
REMOVE_TRAIT(old_owner, TRAIT_GHOSTROLE_ON_REVIVE, REF(src))
|
||||
// we might have some lingering blinking eyes
|
||||
var/obj/item/bodypart/head/head = old_owner?.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(head)
|
||||
var/soul_eyes = locate(/datum/bodypart_overlay/simple/soul_pending_eyes) in head.bodypart_overlays
|
||||
if(soul_eyes)
|
||||
head.remove_bodypart_overlay(soul_eyes)
|
||||
|
||||
prepare_brain(brain)
|
||||
|
||||
/datum/component/ghostrole_on_revive/proc/prepare_brain(obj/item/organ/brein)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
RegisterSignal(brein, COMSIG_ORGAN_IMPLANTED, PROC_REF(prepare_mob_from_brain))
|
||||
UnregisterSignal(brein, COMSIG_ORGAN_REMOVED)
|
||||
|
||||
/datum/component/ghostrole_on_revive/proc/prepare_mob_from_brain(obj/item/organ/internal/brain/brein, mob/living/owner)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
UnregisterSignal(brein, COMSIG_ORGAN_IMPLANTED)
|
||||
prepare_mob(owner)
|
||||
|
||||
/datum/component/ghostrole_on_revive/proc/on_revive(mob/living/aliver)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
INVOKE_ASYNC(src, PROC_REF(poll_ghosts), aliver)
|
||||
|
||||
/datum/component/ghostrole_on_revive/proc/poll_ghosts(mob/living/aliver)
|
||||
var/soul_eyes
|
||||
var/obj/item/bodypart/head
|
||||
// adds soulful SOUL PENDING eyes to indicate what's happening to observers
|
||||
|
||||
var/mob/living/carbon/human/hewmon
|
||||
if(ishuman(aliver))
|
||||
hewmon = aliver
|
||||
head = hewmon.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(head)
|
||||
soul_eyes = new /datum/bodypart_overlay/simple/soul_pending_eyes ()
|
||||
head.add_bodypart_overlay(soul_eyes)
|
||||
hewmon.update_body_parts()
|
||||
|
||||
var/mob/dead/observer/chosen_one = SSpolling.poll_ghosts_for_target(
|
||||
question = "Would you like to play as a recovered crewmember?",
|
||||
role = null,
|
||||
check_jobban = ROLE_RECOVERED_CREW,
|
||||
poll_time = 15 SECONDS,
|
||||
checked_target = aliver,
|
||||
ignore_category = POLL_IGNORE_RECOVERED_CREW,
|
||||
alert_pic = aliver,
|
||||
role_name_text = "recovered crew",
|
||||
)
|
||||
if(head)
|
||||
head.remove_bodypart_overlay(soul_eyes)
|
||||
hewmon?.update_body_parts()
|
||||
|
||||
if(!isobserver(chosen_one))
|
||||
if(refuse_revival_if_failed)
|
||||
aliver.death()
|
||||
aliver.visible_message(span_deadsay("[aliver.name]'s soul is struggling to return!"))
|
||||
else
|
||||
aliver.key = chosen_one.key
|
||||
on_succesful_revive?.Invoke(aliver)
|
||||
qdel(src)
|
||||
|
||||
/datum/component/ghostrole_on_revive/Destroy(force)
|
||||
REMOVE_TRAIT(parent, TRAIT_GHOSTROLE_ON_REVIVE, REF(src))
|
||||
|
||||
var/mob/living/living
|
||||
if(isliving(parent))
|
||||
living = parent
|
||||
else if(istype(parent, /obj/item/organ/internal/brain))
|
||||
var/obj/item/organ/internal/brain/brain = parent
|
||||
living = brain.owner
|
||||
living?.med_hud_set_status()
|
||||
|
||||
. = ..()
|
||||
@@ -1,24 +1,36 @@
|
||||
/**
|
||||
* ## DANGEROUS SURGICAL REMOVAL ELEMENT
|
||||
* ## DANGEROUS ORGAN REMOVAL ELEMENT
|
||||
*
|
||||
* Makes the organ explode when removed surgically.
|
||||
* Makes the organ explode when removed (potentially surgically!).
|
||||
* That's about it.
|
||||
*/
|
||||
/datum/element/dangerous_surgical_removal
|
||||
/datum/element/dangerous_organ_removal
|
||||
element_flags = ELEMENT_BESPOKE
|
||||
argument_hash_start_idx = 2
|
||||
|
||||
/datum/element/dangerous_surgical_removal/Attach(datum/target)
|
||||
/// whether the removal needs to be surgical for it to explode. If you're adding more modes, just pass the signal directly instead
|
||||
var/surgical
|
||||
|
||||
/datum/element/dangerous_organ_removal/Attach(datum/target, surgical = FALSE)
|
||||
. = ..()
|
||||
if(!isorgan(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
RegisterSignal(target, COMSIG_ORGAN_SURGICALLY_REMOVED, PROC_REF(on_surgical_removal))
|
||||
|
||||
/datum/element/dangerous_surgical_removal/Detach(datum/source)
|
||||
src.surgical = surgical
|
||||
|
||||
if(surgical)
|
||||
RegisterSignal(target, COMSIG_ORGAN_SURGICALLY_REMOVED, PROC_REF(on_removal))
|
||||
else
|
||||
RegisterSignal(target, COMSIG_ORGAN_REMOVED, PROC_REF(on_removal))
|
||||
|
||||
/datum/element/dangerous_organ_removal/Detach(datum/source)
|
||||
. = ..()
|
||||
UnregisterSignal(source, COMSIG_ORGAN_SURGICALLY_REMOVED)
|
||||
|
||||
/datum/element/dangerous_surgical_removal/proc/on_surgical_removal(obj/item/organ/source, mob/living/user, mob/living/carbon/old_owner, target_zone, obj/item/tool)
|
||||
UnregisterSignal(source, list(COMSIG_ORGAN_SURGICALLY_REMOVED, COMSIG_ORGAN_REMOVED))
|
||||
|
||||
/datum/element/dangerous_organ_removal/proc/on_removal(obj/item/organ/source, mob/living/user, mob/living/carbon/old_owner, target_zone, obj/item/tool)
|
||||
SIGNAL_HANDLER
|
||||
if(source.organ_flags & (ORGAN_FAILING|ORGAN_EMP))
|
||||
if(surgical && source.organ_flags & (ORGAN_FAILING|ORGAN_EMP))
|
||||
return
|
||||
if(user?.Adjacent(source))
|
||||
source.audible_message("[source] explodes on [user]'s face!")
|
||||
|
||||
@@ -540,6 +540,13 @@
|
||||
var/datum/addiction/affected_addiction = SSaddiction.all_addictions[type]
|
||||
return affected_addiction.on_lose_addiction_points(src)
|
||||
|
||||
/// Whether or not we can roll for midrounds, specifically checking if we have any major antag datums that should block it
|
||||
/datum/mind/proc/can_roll_midround()
|
||||
for(var/datum/antagonist/antag as anything in antag_datums)
|
||||
if(antag.block_midrounds)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/// Setter for the assigned_role job datum.
|
||||
/datum/mind/proc/set_assigned_role(datum/job/new_role)
|
||||
|
||||
@@ -204,6 +204,8 @@ Medical HUD! Basic mode needs suit sensors on.
|
||||
else if(stat == DEAD || (HAS_TRAIT(src, TRAIT_FAKEDEATH)))
|
||||
if(HAS_TRAIT(src, TRAIT_MIND_TEMPORARILY_GONE) || can_defib_client())
|
||||
holder.icon_state = "huddefib"
|
||||
else if(HAS_TRAIT(src, TRAIT_GHOSTROLE_ON_REVIVE))
|
||||
holder.icon_state = "hudghost"
|
||||
else
|
||||
holder.icon_state = "huddead"
|
||||
else
|
||||
|
||||
@@ -63,6 +63,8 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
var/hardcore_random_bonus = FALSE
|
||||
/// A path to the audio stinger that plays upon gaining this datum.
|
||||
var/stinger_sound
|
||||
/// Whether this antag datum blocks rolling new antag datums
|
||||
var/block_midrounds = TRUE
|
||||
|
||||
//ANTAG UI
|
||||
|
||||
|
||||
@@ -191,3 +191,12 @@
|
||||
contains = list(/obj/item/organ/internal/cyberimp/arm/strongarm = 2)
|
||||
crate_name = "Strong-Arm implant crate"
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/medical/lost_crew
|
||||
name = "Recovered NT Employee corpse"
|
||||
desc = "We don't have the accomodations to bring them back, could we send them to you? Please revive and employ them. \
|
||||
The price is a downpayment, we will reimburse the medical budget once our employee has been alive again for a bit."
|
||||
cost = CARGO_CRATE_VALUE * 5
|
||||
contains = list(/obj/structure/closet/body_bag/lost_crew/with_body)
|
||||
crate_name = "body freezer"
|
||||
crate_type = /obj/structure/closet/crate/secure/freezer
|
||||
|
||||
@@ -132,6 +132,8 @@
|
||||
/// Minimal character age for this job
|
||||
var/required_character_age
|
||||
|
||||
/// If set, look for a policy with this instead of the job title
|
||||
var/policy_override
|
||||
|
||||
/datum/job/New()
|
||||
. = ..()
|
||||
@@ -304,7 +306,7 @@
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
var/list/info = list()
|
||||
info += "<b>You are the [title].</b>\n"
|
||||
var/related_policy = get_policy(title)
|
||||
var/related_policy = get_policy(policy_override || title)
|
||||
var/radio_info = get_radio_information()
|
||||
if(related_policy)
|
||||
info += related_policy
|
||||
|
||||
50
code/modules/lost_crew/body_bags.dm
Normal file
50
code/modules/lost_crew/body_bags.dm
Normal file
@@ -0,0 +1,50 @@
|
||||
/obj/item/bodybag/lost_crew
|
||||
name = "long-term body bag"
|
||||
desc = "A folded bag designed for the long-term storage and transportation of cadavers."
|
||||
unfoldedbag_path = /obj/structure/closet/body_bag/lost_crew
|
||||
icon_state = "bodybag_lost_folded"
|
||||
|
||||
/obj/structure/closet/body_bag/lost_crew
|
||||
name = "long-term body bag"
|
||||
desc = "A plastic bag designed for the long-term storage and transportation of cadavers."
|
||||
|
||||
icon_state = "bodybag_lost"
|
||||
|
||||
foldedbag_path = /obj/item/bodybag/lost_crew
|
||||
|
||||
/// Filled with one body. If folded, gives the parent type so we dont make infinite corpses
|
||||
/obj/structure/closet/body_bag/lost_crew/with_body
|
||||
/// Whether or not we spawn a paper with everything thats happened to the body
|
||||
var/debug = FALSE
|
||||
|
||||
/obj/structure/closet/body_bag/lost_crew/with_body/PopulateContents()
|
||||
var/list/recovered_items = list()
|
||||
var/list/protected_items = list()
|
||||
var/list/lost_crew_data = list()
|
||||
var/mob/living/corpse = GLOB.lost_crew_manager.create_lost_crew(revivable = TRUE, recovered_items = recovered_items, protected_items = protected_items, body_data = lost_crew_data)
|
||||
corpse.mind_initialize()
|
||||
corpse.forceMove(src)
|
||||
|
||||
// Drop stuff like dropped limbs and organs with them in the bag
|
||||
for(var/obj/object in recovered_items)
|
||||
object.forceMove(src)
|
||||
|
||||
// Spawn a mind lockbox with job stuffs for them to work with when they return
|
||||
if(protected_items.len && corpse.mind)
|
||||
var/obj/item/storage/lockbox/mind/box = new(src)
|
||||
box.mind = corpse.mind
|
||||
for(var/obj/object in protected_items)
|
||||
object.forceMove(box)
|
||||
|
||||
process_data(lost_crew_data)
|
||||
|
||||
/obj/structure/closet/body_bag/lost_crew/with_body/proc/process_data(list/crew_data)
|
||||
if(!debug)
|
||||
return
|
||||
|
||||
var/obj/item/paper/paper = new(src)
|
||||
paper.add_raw_text(english_list(crew_data), advanced_html = TRUE)
|
||||
|
||||
/// Subtype for debugging damage types
|
||||
/obj/structure/closet/body_bag/lost_crew/with_body/debug
|
||||
debug = TRUE
|
||||
139
code/modules/lost_crew/character/_assignment.dm
Normal file
139
code/modules/lost_crew/character/_assignment.dm
Normal file
@@ -0,0 +1,139 @@
|
||||
/// Possible assignments corpses can have, both for flavor and to push them towards contributing to the round
|
||||
/datum/corpse_assignment
|
||||
/// Message we send to the player upon revival concerning their job
|
||||
var/job_lore
|
||||
/// Gear to give to the crewie in a special locked box
|
||||
var/list/job_stuffs
|
||||
/// Trim on the ID we give to the revived person (no trim = no id)
|
||||
var/datum/id_trim/trim
|
||||
/// Job datum to apply to the human
|
||||
var/datum/job/job_datum
|
||||
|
||||
/datum/corpse_assignment/proc/apply_assignment(mob/living/carbon/human/working_dead, list/job_gear, list/datum/callback/on_revive_and_player_occupancy)
|
||||
if(!job_gear)
|
||||
return
|
||||
|
||||
for(var/item in job_stuffs)
|
||||
job_gear += new item ()
|
||||
job_gear += job_stuffs
|
||||
|
||||
if(job_datum)
|
||||
on_revive_and_player_occupancy += CALLBACK(src, PROC_REF(assign_job), working_dead) //this needs to happen once the body has been succesfully occupied and revived
|
||||
|
||||
if(trim)
|
||||
var/obj/item/card/id/advanced/card = new()
|
||||
card.registered_name = working_dead.name
|
||||
card.registered_age = working_dead.age
|
||||
SSid_access.apply_trim_to_card(card, trim)
|
||||
job_gear += card
|
||||
|
||||
/datum/corpse_assignment/proc/assign_job(mob/living/carbon/human/working_undead)
|
||||
working_undead.mind.set_assigned_role_with_greeting(new job_datum (), working_undead.client)
|
||||
|
||||
/datum/corpse_assignment/engineer
|
||||
job_lore = "I was employed as an engineer"
|
||||
job_stuffs = list(/obj/item/clothing/under/rank/engineering/engineer)
|
||||
trim = /datum/id_trim/job/visiting_engineer
|
||||
job_datum = /datum/job/recovered_crew/engineer
|
||||
|
||||
/datum/id_trim/job/visiting_engineer
|
||||
assignment = JOB_LOSTCREW_ENGINEER
|
||||
trim_state = "trim_stationengineer"
|
||||
department_color = COLOR_ENGINEERING_ORANGE
|
||||
subdepartment_color = COLOR_ENGINEERING_ORANGE
|
||||
sechud_icon_state = SECHUD_STATION_ENGINEER
|
||||
minimal_access = list(
|
||||
ACCESS_CONSTRUCTION,
|
||||
ACCESS_EXTERNAL_AIRLOCKS,
|
||||
ACCESS_MAINT_TUNNELS,
|
||||
)
|
||||
|
||||
/datum/corpse_assignment/medical
|
||||
job_lore = "I was employed as a doctor"
|
||||
job_stuffs = list(/obj/item/clothing/under/rank/medical/doctor)
|
||||
trim = /datum/id_trim/job/visiting_doctor
|
||||
job_datum = /datum/job/recovered_crew/doctor
|
||||
|
||||
/datum/id_trim/job/visiting_doctor
|
||||
assignment = JOB_LOSTCREW_MEDICAL
|
||||
trim_state = "trim_medicaldoctor"
|
||||
department_color = COLOR_MEDICAL_BLUE
|
||||
subdepartment_color = COLOR_MEDICAL_BLUE
|
||||
sechud_icon_state = SECHUD_MEDICAL_DOCTOR
|
||||
|
||||
minimal_access = list(
|
||||
ACCESS_MEDICAL,
|
||||
)
|
||||
|
||||
/datum/corpse_assignment/security
|
||||
job_lore = "I was employed as security"
|
||||
job_stuffs = list(/obj/item/clothing/under/rank/security/officer)
|
||||
trim = /datum/id_trim/job/visiting_security
|
||||
job_datum = /datum/job/recovered_crew/security
|
||||
|
||||
/datum/corpse_assignment/security/apply_assignment(mob/living/carbon/human/working_dead, list/job_gear)
|
||||
. = ..()
|
||||
|
||||
var/obj/item/implant/mindshield/shield = new()
|
||||
shield.implant(working_dead)
|
||||
|
||||
/datum/id_trim/job/visiting_security
|
||||
assignment = JOB_LOSTCREW_SECURITY
|
||||
trim_state = "trim_securityofficer"
|
||||
department_color = COLOR_SECURITY_RED
|
||||
subdepartment_color = COLOR_SECURITY_RED
|
||||
sechud_icon_state = SECHUD_SECURITY_OFFICER
|
||||
|
||||
minimal_access = list(
|
||||
ACCESS_BRIG_ENTRANCE,
|
||||
)
|
||||
|
||||
/datum/corpse_assignment/science
|
||||
job_lore = "I was employed as a scientist"
|
||||
job_stuffs = list(/obj/item/clothing/under/rank/rnd/scientist)
|
||||
trim = /datum/id_trim/job/visiting_scientist
|
||||
job_datum = /datum/job/recovered_crew/scientist
|
||||
|
||||
/datum/id_trim/job/visiting_scientist
|
||||
assignment = JOB_LOSTCREW_SCIENCE
|
||||
trim_state = "trim_scientist"
|
||||
department_color = COLOR_SCIENCE_PINK
|
||||
subdepartment_color = COLOR_SCIENCE_PINK
|
||||
sechud_icon_state = SECHUD_SCIENTIST
|
||||
minimal_access = list(
|
||||
ACCESS_AUX_BASE,
|
||||
ACCESS_SCIENCE,
|
||||
)
|
||||
|
||||
/datum/corpse_assignment/cargo
|
||||
job_lore = "I was employed as a technician"
|
||||
job_stuffs = list(/obj/item/clothing/under/rank/cargo/tech)
|
||||
trim = /datum/id_trim/job/visiting_technician
|
||||
job_datum = /datum/job/recovered_crew/cargo
|
||||
|
||||
/datum/id_trim/job/visiting_technician
|
||||
assignment = JOB_LOSTCREW_CARGO
|
||||
trim_state = "trim_cargotechnician"
|
||||
department_color = COLOR_CARGO_BROWN
|
||||
subdepartment_color = COLOR_CARGO_BROWN
|
||||
sechud_icon_state = SECHUD_CARGO_TECHNICIAN
|
||||
minimal_access = list(
|
||||
ACCESS_CARGO,
|
||||
ACCESS_MAINT_TUNNELS,
|
||||
)
|
||||
|
||||
/datum/corpse_assignment/civillian
|
||||
job_lore = "I was employed as a civllian"
|
||||
job_stuffs = list(/obj/item/clothing/under/color/grey)
|
||||
trim = /datum/id_trim/job/visiting_civillian
|
||||
job_datum = /datum/job/recovered_crew/civillian
|
||||
|
||||
/datum/id_trim/job/visiting_civillian
|
||||
assignment = JOB_LOSTCREW_CIVILLIAN
|
||||
trim_state = "trim_assistant"
|
||||
sechud_icon_state = SECHUD_ASSISTANT
|
||||
minimal_access = list()
|
||||
extra_access = list(
|
||||
ACCESS_MAINT_TUNNELS,
|
||||
ACCESS_SERVICE,
|
||||
)
|
||||
44
code/modules/lost_crew/character/_character.dm
Normal file
44
code/modules/lost_crew/character/_character.dm
Normal file
@@ -0,0 +1,44 @@
|
||||
/// Datum for controlling the base character, such as species, scarring, styles, augments etc
|
||||
/datum/corpse_character
|
||||
/// Species type to spawn with
|
||||
var/datum/species/species_type = /datum/species/human
|
||||
|
||||
/datum/corpse_character/proc/apply_character(mob/living/carbon/human/fashionable_corpse, list/saved_objects, list/datum/callback/on_revive_and_player_occupancy)
|
||||
fashionable_corpse.set_species(species_type)
|
||||
fashionable_corpse.fully_replace_character_name(fashionable_corpse.real_name, fashionable_corpse.generate_random_mob_name())
|
||||
|
||||
/// Not really all roundstart species, but plasmaman is a bit too flamboyant and felinids aren't interesting
|
||||
/datum/corpse_character/mostly_roundstart
|
||||
var/list/possible_species = list(
|
||||
/datum/species/human = 10,
|
||||
/datum/species/lizard = 2,
|
||||
/datum/species/ethereal = 1,
|
||||
/datum/species/moth = 1,
|
||||
)
|
||||
|
||||
/datum/corpse_character/mostly_roundstart/apply_character(mob/living/carbon/human/fashionable_corpse, list/saved_objects, list/datum/callback/on_revive_and_player_occupancy)
|
||||
species_type = pick_weight(possible_species)
|
||||
..()
|
||||
|
||||
/datum/corpse_character/human
|
||||
species_type = /datum/species/human
|
||||
|
||||
/// used by the morgue trays to spawn bodies (obeying three different configs???????????????????? yes please daddy give me more config for benign features)
|
||||
/datum/corpse_character/morgue
|
||||
|
||||
/datum/corpse_character/morgue/apply_character(mob/living/carbon/human/fashionable_corpse, list/saved_objects, list/datum/callback/on_revive_and_player_occupancy)
|
||||
var/use_species = !(CONFIG_GET(flag/morgue_cadaver_disable_nonhumans))
|
||||
var/species_probability = CONFIG_GET(number/morgue_cadaver_other_species_probability) * use_species
|
||||
var/override_species = CONFIG_GET(string/morgue_cadaver_override_species)
|
||||
|
||||
if(override_species)
|
||||
species_type = GLOB.species_list[override_species]
|
||||
|
||||
else if(prob(species_probability))
|
||||
species_type = GLOB.species_list[pick(get_selectable_species())]
|
||||
|
||||
if(!species_type)
|
||||
stack_trace("failed to spawn cadaver with species ID [species_type]") //if it's invalid they'll just be a human, so no need to worry too much aside from yelling at the server owner lol.
|
||||
species_type = initial(species_type)
|
||||
|
||||
return ..()
|
||||
33
code/modules/lost_crew/character/job_datums.dm
Normal file
33
code/modules/lost_crew/character/job_datums.dm
Normal file
@@ -0,0 +1,33 @@
|
||||
/datum/job/recovered_crew
|
||||
policy_override = "Recovered Crew"
|
||||
faction = FACTION_STATION
|
||||
|
||||
/datum/job/recovered_crew/doctor
|
||||
title = JOB_LOSTCREW_MEDICAL
|
||||
department_head = list(JOB_CHIEF_MEDICAL_OFFICER)
|
||||
supervisors = SUPERVISOR_CMO
|
||||
|
||||
/datum/job/recovered_crew/engineer
|
||||
title = JOB_LOSTCREW_ENGINEER
|
||||
department_head = list(JOB_CHIEF_ENGINEER)
|
||||
supervisors = SUPERVISOR_CE
|
||||
|
||||
/datum/job/recovered_crew/security
|
||||
title = JOB_LOSTCREW_SECURITY
|
||||
department_head = list(JOB_HEAD_OF_SECURITY)
|
||||
supervisors = SUPERVISOR_HOS
|
||||
|
||||
/datum/job/recovered_crew/cargo
|
||||
title = JOB_LOSTCREW_CARGO
|
||||
department_head = list(JOB_QUARTERMASTER)
|
||||
supervisors = SUPERVISOR_QM
|
||||
|
||||
/datum/job/recovered_crew/scientist
|
||||
title = JOB_LOSTCREW_SCIENCE
|
||||
department_head = list(JOB_RESEARCH_DIRECTOR)
|
||||
supervisors = SUPERVISOR_RD
|
||||
|
||||
/datum/job/recovered_crew/civillian
|
||||
title = JOB_LOSTCREW_CIVILLIAN
|
||||
department_head = list(JOB_HEAD_OF_PERSONNEL)
|
||||
supervisors = SUPERVISOR_HOP
|
||||
110
code/modules/lost_crew/damages/_damages.dm
Normal file
110
code/modules/lost_crew/damages/_damages.dm
Normal file
@@ -0,0 +1,110 @@
|
||||
// Unique damage types we can apply for blacklisting, so we dont remove all organs twice etc
|
||||
#define CORPSE_DAMAGE_ORGAN_DECAY "organ decay"
|
||||
#define CORPSE_DAMAGE_ORGAN_LOSS "organ loss"
|
||||
#define CORPSE_DAMAGE_LIMB_LOSS "limb loss"
|
||||
|
||||
/// The main style controller for new dead bodies! Determines the character, lore, possible causes of death, decay and every other modifier!
|
||||
/datum/corpse_damage_class
|
||||
/// Message sent to the recovered crew, constructed from the different death lores
|
||||
var/list/death_lore = list()
|
||||
/// Lore we give on revival, this is the first line
|
||||
var/area_lore = "I was doing something"
|
||||
/// Weight given to this class. Setting this is all that's needed for it to be rollable
|
||||
var/weight
|
||||
/// Different character archetypes we can spawn
|
||||
var/list/possible_character_types
|
||||
/// Assignments that can be given to the corpse
|
||||
var/list/possible_character_assignments
|
||||
/// Whatever killed us
|
||||
var/list/possible_causes_of_death
|
||||
/// Goddamn space vultures stealing my organs
|
||||
var/list/post_mortem_effects
|
||||
/// A random decay we apply. Defined here so we can vary it (i.e. a spaced body has less decay than one in a warm jungle)
|
||||
var/list/decays = list(/datum/corpse_damage/post_mortem/organ_decay)
|
||||
/// When healthscanned, this is the minimum time that shows
|
||||
var/lore_death_time_min = 1 DAYS
|
||||
/// When healthscanned, this is the maximum time that shows
|
||||
var/lore_death_time_max = 5 YEARS
|
||||
|
||||
/// Generate and apply a possible character (species etc)
|
||||
/datum/corpse_damage_class/proc/apply_character(mob/living/carbon/human/fashion_corpse, list/protected_objects, list/datum/callback/on_revive_and_player_occupancy, list/body_data)
|
||||
var/datum/corpse_character/character = pick_weight(possible_character_types)
|
||||
character = new character()
|
||||
character.apply_character(fashion_corpse, protected_objects, on_revive_and_player_occupancy)
|
||||
|
||||
var/datum/corpse_assignment/assignment = pick_weight(possible_character_assignments)
|
||||
if(assignment)
|
||||
assignment = new assignment()
|
||||
assignment.apply_assignment(fashion_corpse, protected_objects, on_revive_and_player_occupancy)
|
||||
|
||||
death_lore += assignment?.job_lore
|
||||
|
||||
body_data += character.type
|
||||
body_data += assignment?.type
|
||||
|
||||
/// Set up injuries
|
||||
/datum/corpse_damage_class/proc/apply_injuries(mob/living/carbon/human/victim, list/saved_objects, list/datum/callback/on_revive_and_player_occupancy, list/body_data)
|
||||
var/datum/corpse_damage/cause_of_death/cause_of_death = pick_damage_type(possible_causes_of_death)
|
||||
cause_of_death.apply_to_body(victim, rand(), saved_objects, on_revive_and_player_occupancy)
|
||||
|
||||
var/datum/corpse_damage/post_mortem = pick_damage_type(post_mortem_effects)
|
||||
post_mortem?.apply_to_body(victim, rand(), saved_objects, on_revive_and_player_occupancy)
|
||||
|
||||
var/datum/corpse_damage/decay = pick_damage_type(decays)
|
||||
decay?.apply_to_body(victim, rand(), saved_objects, on_revive_and_player_occupancy)
|
||||
|
||||
// Simulate bloodloss by dragging/moving
|
||||
victim.blood_volume = max(victim.blood_volume - victim.bleedDragAmount() * rand(20, 100), 0)
|
||||
set_death_date(victim)
|
||||
|
||||
body_data += cause_of_death.type
|
||||
body_data += post_mortem?.type
|
||||
body_data += decay.type
|
||||
|
||||
death_lore += area_lore + " " + cause_of_death.cause_of_death
|
||||
|
||||
/// Wrapped pickweight so we can have a bit more controle over how we pick our rules
|
||||
/datum/corpse_damage_class/proc/pick_damage_type(list/damages, list/used_damage_types)
|
||||
var/list/possible_damages = list()
|
||||
|
||||
for(var/datum/corpse_damage/damage as anything in damages)
|
||||
if(isdatum(damage) && damage.damage_type && (damage.damage_type in used_damage_types))
|
||||
continue
|
||||
possible_damages[damage] = damages[damage]
|
||||
|
||||
var/datum/corpse_damage/chosen = pick_weight(possible_damages)
|
||||
if(!ispath(chosen)) //can also be null for some variants
|
||||
return null
|
||||
|
||||
chosen = new chosen()
|
||||
|
||||
if(chosen.damage_type)
|
||||
used_damage_types += chosen.damage_type
|
||||
return chosen
|
||||
|
||||
/// Soulfully give a date of death for health analyzers
|
||||
/datum/corpse_damage_class/proc/set_death_date(mob/living/carbon/body)
|
||||
var/died_how_long_ago = rand(lore_death_time_min, lore_death_time_max)
|
||||
body.timeofdeath = world.time - died_how_long_ago
|
||||
|
||||
var/death_real_time = world.realtime - died_how_long_ago
|
||||
var/current_date = time2text(death_real_time, "DD Month")
|
||||
var/current_year = text2num(time2text(death_real_time, "YYYY")) + STATION_YEAR_OFFSET
|
||||
body.station_timestamp_timeofdeath = "[current_date] [current_year]"
|
||||
|
||||
/// Main corpse damage type that's used to apply damages to a body
|
||||
/datum/corpse_damage
|
||||
/// When given, automatically blacklist corpse_damages with the same damage_type flag to avoid stuff like being delimbed twice (dragon ate me AND I got space vultures???)
|
||||
var/damage_type
|
||||
|
||||
/// Tear IT UPPP!!! Apply any damages to the body that we need to
|
||||
/datum/corpse_damage/proc/apply_to_body(mob/living/carbon/human/body, severity, list/storage)
|
||||
return
|
||||
|
||||
/// This is the reason we died
|
||||
/datum/corpse_damage/cause_of_death
|
||||
/// I was in x, [when I ....]
|
||||
var/cause_of_death = "when I tripped and died."
|
||||
|
||||
/// Some post mortem damages from space vultures
|
||||
/datum/corpse_damage/post_mortem
|
||||
36
code/modules/lost_crew/damages/accident.dm
Normal file
36
code/modules/lost_crew/damages/accident.dm
Normal file
@@ -0,0 +1,36 @@
|
||||
/datum/corpse_damage/cause_of_death/plasmafire
|
||||
cause_of_death = "when I got caught in a plasmafire!"
|
||||
/// The max tox damage we deal
|
||||
var/tox_damage_max = 40
|
||||
/// Guaranteed burn damage
|
||||
var/burn_damage_base = 100
|
||||
/// Burn damage that fluctuates with severity
|
||||
var/burn_damage_max = 100
|
||||
|
||||
/datum/corpse_damage/cause_of_death/plasmafire/apply_to_body(mob/living/carbon/human/body, severity, list/storage, list/datum/callback/on_revive_and_player_occupancy)
|
||||
body.apply_damage(burn_damage_base + burn_damage_max * severity, BURN, wound_bonus = 100 * severity, spread_damage = TRUE)
|
||||
body.apply_damage(tox_damage_max * severity, TOX)
|
||||
|
||||
/datum/corpse_damage/cause_of_death/explosion
|
||||
cause_of_death = "when I noticed a bomb!"
|
||||
|
||||
/// The explosion severity
|
||||
var/severity = EXPLODE_HEAVY
|
||||
/// The maximum amount of explosions we can proc
|
||||
var/explosion_count_max = 4
|
||||
|
||||
/datum/corpse_damage/cause_of_death/explosion/apply_to_body(mob/living/carbon/human/body, severity, list/storage, list/datum/callback/on_revive_and_player_occupancy)
|
||||
for(var/i in 1 to max(round(explosion_count_max * severity), 1))
|
||||
body.ex_act(EXPLODE_HEAVY)
|
||||
|
||||
/datum/corpse_damage/cause_of_death/spaced
|
||||
cause_of_death = "when I got spaced!"
|
||||
/// Guaranteed brute and burn damage
|
||||
var/base_damage = 90
|
||||
/// Damage influenced by the severity
|
||||
var/damage_max = 100
|
||||
|
||||
/datum/corpse_damage/cause_of_death/spaced/apply_to_body(mob/living/carbon/human/body, severity, list/storage, list/datum/callback/on_revive_and_player_occupancy)
|
||||
body.apply_damage(base_damage + damage_max * (severity * rand(80, 120) * 0.01), BURN, spread_damage = TRUE)
|
||||
body.apply_damage(base_damage + damage_max * (severity * rand(80, 120) * 0.01), BRUTE, spread_damage = TRUE)
|
||||
body.set_coretemperature(TCMB)
|
||||
23
code/modules/lost_crew/damages/decay.dm
Normal file
23
code/modules/lost_crew/damages/decay.dm
Normal file
@@ -0,0 +1,23 @@
|
||||
/// We simulate decay on bodies. This is always used, but severity can differ (though tending to the more severe)
|
||||
/datum/corpse_damage/post_mortem/organ_decay
|
||||
damage_type = CORPSE_DAMAGE_ORGAN_DECAY
|
||||
/// The max amount of decay we can apply to organs, scaled by severity
|
||||
var/max_decay_time = 40 MINUTES
|
||||
|
||||
/datum/corpse_damage/post_mortem/organ_decay/apply_to_body(mob/living/carbon/human/body, severity, list/sorage, list/datum/callback/on_revive_and_player_occupancy)
|
||||
if(!body.organs)
|
||||
return FALSE
|
||||
|
||||
// * 0.5 because life ticks happen about every 2 seconds (we really need a way to get the current life tickspeed)
|
||||
var/decay_ticks = max_decay_time * severity * 0.5
|
||||
|
||||
for(var/obj/item/organ/internal/internal in body.organs)
|
||||
internal.apply_organ_damage(decay_ticks * internal.decay_factor)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/corpse_damage/post_mortem/organ_decay/light
|
||||
max_decay_time = 15 MINUTES
|
||||
|
||||
/datum/corpse_damage/post_mortem/organ_decay/heavy
|
||||
max_decay_time = 48 HOURS
|
||||
45
code/modules/lost_crew/damages/melee.dm
Normal file
45
code/modules/lost_crew/damages/melee.dm
Normal file
@@ -0,0 +1,45 @@
|
||||
/// Simulates a melee attack with a specified weapon
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon
|
||||
/// The weapon with which we hit
|
||||
var/obj/item/weapon
|
||||
/// The minimal amount of hits
|
||||
var/min_hits = 5
|
||||
/// The maximum amount of hits
|
||||
var/max_hits = 15
|
||||
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon/apply_to_body(mob/living/carbon/human/body, severity, list/storage, list/datum/callback/on_revive_and_player_occupancy)
|
||||
weapon = get_weapon(body)
|
||||
|
||||
var/hits = ((max_hits - min_hits) * severity + min_hits)
|
||||
for(var/i in 1 to hits)
|
||||
weapon.attack(body, body) //needs an attacker, no reason it cant be the body as well
|
||||
body.zone_selected = pick(GLOB.all_body_zones)
|
||||
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon/proc/get_weapon(mob/living/carbon/human/body)
|
||||
return new weapon(null)
|
||||
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon/esword
|
||||
weapon = /obj/item/melee/energy/sword
|
||||
cause_of_death = "when I was attacked by a filthy traitor!"
|
||||
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon/esword/get_weapon(mob/living/carbon/human/body)
|
||||
. = ..()
|
||||
|
||||
var/obj/item/melee/energy/sword/esword = .
|
||||
|
||||
esword.attack_self() //need to activate it
|
||||
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon/changeling
|
||||
weapon = /obj/item/melee/arm_blade
|
||||
cause_of_death = "when I was attacked by a terrifying changeling!"
|
||||
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon/toolbox
|
||||
cause_of_death = "when some worthless assistant toolboxed me!"
|
||||
weapon = /obj/item/storage/toolbox
|
||||
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon/heretic
|
||||
cause_of_death = "when a flipping heretic attacked me!"
|
||||
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon/heretic/get_weapon(mob/living/carbon/human/body)
|
||||
var/obj/item/melee/sickly_blade/blade = pick(subtypesof(/obj/item/melee/sickly_blade)) //pick a random blade, can be a bunch of fun stuff
|
||||
return new blade (null)
|
||||
47
code/modules/lost_crew/damages/post_mortem.dm
Normal file
47
code/modules/lost_crew/damages/post_mortem.dm
Normal file
@@ -0,0 +1,47 @@
|
||||
/// Damn space vultures man! At least they dont go for the brain
|
||||
/datum/corpse_damage/post_mortem/organ_loss
|
||||
damage_type = CORPSE_DAMAGE_ORGAN_LOSS
|
||||
|
||||
/// Chance that the organ is stored and delivered with the body
|
||||
var/organ_save_chance = 20
|
||||
/// Minimum organs we can lose
|
||||
var/min_organs = 2
|
||||
/// Maximum organs we can lose
|
||||
var/max_organs = 8
|
||||
|
||||
/datum/corpse_damage/post_mortem/organ_loss/apply_to_body(mob/living/carbon/human/body, severity, list/saved_movables, list/datum/callback/on_revive_and_player_occupancy)
|
||||
var/organs_to_take = round(min_organs + (max_organs - min_organs) * severity)
|
||||
var/list/organs_we_can_take = body.organs - body.get_organ_slot(ORGAN_SLOT_BRAIN)
|
||||
|
||||
for(var/i in 1 to organs_to_take)
|
||||
var/obj/organ = pick(organs_we_can_take)
|
||||
if(prob(organ_save_chance) && saved_movables) //if lucky, we can save the organ and have it be delivered with the body
|
||||
organ.moveToNullspace()
|
||||
saved_movables += organ
|
||||
else
|
||||
qdel(organ)
|
||||
|
||||
/// Damn space vultures man! At least they dont go for the chest or head, or they do but we don't get to see those bodies :O
|
||||
/datum/corpse_damage/post_mortem/limb_loss
|
||||
damage_type = CORPSE_DAMAGE_LIMB_LOSS
|
||||
|
||||
/// Chance that the limb is stored and delivered with the body
|
||||
var/limb_save_chance = 20
|
||||
/// Min limbs we can lose
|
||||
var/min_limbs = 1
|
||||
/// Max limbs we can lose
|
||||
var/max_limbs = 4
|
||||
|
||||
/datum/corpse_damage/post_mortem/limb_loss/apply_to_body(mob/living/carbon/human/body, severity, list/saved_movables, list/datum/callback/on_revive_and_player_occupancy)
|
||||
var/limbs_to_take = round(min_limbs + (max_limbs - min_limbs) * severity)
|
||||
var/list/limbs_we_can_take = body.bodyparts - body.get_bodypart(BODY_ZONE_HEAD) - body.get_bodypart(BODY_ZONE_CHEST)
|
||||
|
||||
if(!limbs_we_can_take.len)
|
||||
return
|
||||
for(var/i in 1 to limbs_to_take)
|
||||
var/obj/limb = pick(limbs_we_can_take)
|
||||
if(prob(limb_save_chance) && saved_movables)
|
||||
limb.moveToNullspace()
|
||||
saved_movables += limb
|
||||
else
|
||||
qdel(limb)
|
||||
46
code/modules/lost_crew/damages/scenarios.dm
Normal file
46
code/modules/lost_crew/damages/scenarios.dm
Normal file
@@ -0,0 +1,46 @@
|
||||
/// Default scenario, with normal species, assignments and damages etc
|
||||
/datum/corpse_damage_class/station
|
||||
area_lore = "I was working in a space station"
|
||||
weight = 10
|
||||
possible_character_types = list(/datum/corpse_character/mostly_roundstart = 1)
|
||||
possible_character_assignments = list(
|
||||
/datum/corpse_assignment/engineer = 1,
|
||||
/datum/corpse_assignment/medical = 1,
|
||||
/datum/corpse_assignment/security = 1,
|
||||
/datum/corpse_assignment/science = 1,
|
||||
/datum/corpse_assignment/cargo = 1,
|
||||
/datum/corpse_assignment/civillian = 1,
|
||||
)
|
||||
|
||||
possible_causes_of_death = list(
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon/esword = 1,
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon/changeling = 1,
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon/toolbox = 1,
|
||||
/datum/corpse_damage/cause_of_death/melee_weapon/heretic = 1,
|
||||
/datum/corpse_damage/cause_of_death/explosion = 1,
|
||||
/datum/corpse_damage/cause_of_death/plasmafire = 1,
|
||||
)
|
||||
|
||||
post_mortem_effects = list(
|
||||
/datum/corpse_damage/post_mortem/limb_loss = 5,
|
||||
/datum/corpse_damage/post_mortem/organ_loss = 5,
|
||||
null = 1,
|
||||
)
|
||||
|
||||
decays = list(
|
||||
/datum/corpse_damage/post_mortem/organ_decay = 3,
|
||||
/datum/corpse_damage/post_mortem/organ_decay/light = 1,
|
||||
/datum/corpse_damage/post_mortem/organ_decay/heavy = 1,
|
||||
)
|
||||
|
||||
/// Less decay, spread burn and brute damage
|
||||
/datum/corpse_damage_class/station/spaced
|
||||
weight = 2
|
||||
possible_causes_of_death = list(/datum/corpse_damage/cause_of_death/spaced = 1)
|
||||
decays = list(/datum/corpse_damage/post_mortem/organ_decay/light = 1)
|
||||
|
||||
/// Human morgue body
|
||||
/datum/corpse_damage_class/station/morgue
|
||||
weight = 0
|
||||
possible_character_types = list(/datum/corpse_character/morgue = 1)
|
||||
possible_character_assignments = list()
|
||||
136
code/modules/lost_crew/lost_crew_manager.dm
Normal file
136
code/modules/lost_crew/lost_crew_manager.dm
Normal file
@@ -0,0 +1,136 @@
|
||||
/// Manager for the lost crew bodies, for spawning and granting rewards
|
||||
GLOBAL_DATUM_INIT(lost_crew_manager, /datum/lost_crew_manager, new)
|
||||
|
||||
/// Handles procs and timers for the lost crew bodies
|
||||
/datum/lost_crew_manager
|
||||
/// How many credits we reward the medical budget on a succesful revive
|
||||
var/credits_on_succes = /datum/supply_pack/medical/lost_crew::cost + CARGO_CRATE_VALUE * 2
|
||||
/// How long after succesful revival we check to see if theyre still alive, and give rewards
|
||||
var/succes_check_time = 3 MINUTES
|
||||
/// How much the revived crew start with on their cards
|
||||
var/starting_funds = 100
|
||||
|
||||
/**
|
||||
* Creates a body with random background and injuries
|
||||
*
|
||||
* Arguments:
|
||||
* * revivable - Whether or not we can be revived to grand a ghost controle
|
||||
* * forced_class - To force a specific damage class for some specific lore reason
|
||||
* * recovered_items - Items recovered, such as some organs, dropped directly with the body
|
||||
* * protected_items - Items that can only be recovered by the revived player
|
||||
* * body_data - Debug data we can use to get a readout of what has been done
|
||||
*/
|
||||
/datum/lost_crew_manager/proc/create_lost_crew(revivable = TRUE, datum/corpse_damage_class/forced_class, list/recovered_items, list/protected_items, list/body_data = list())
|
||||
var/mob/living/carbon/human/new_body = new(null)
|
||||
new_body.death()
|
||||
|
||||
var/static/list/scenarios = list()
|
||||
if(!scenarios.len)
|
||||
var/list/types = subtypesof(/datum/corpse_damage_class)
|
||||
for(var/datum/corpse_damage_class/scenario as anything in types)
|
||||
scenarios[scenario] = initial(scenario.weight)
|
||||
|
||||
var/list/datum/callback/on_revive_and_player_occupancy = list()
|
||||
|
||||
var/datum/corpse_damage_class/scenario = forced_class || pick_weight(scenarios)
|
||||
scenario = new scenario ()
|
||||
|
||||
scenario.apply_character(new_body, protected_items, on_revive_and_player_occupancy, body_data)
|
||||
scenario.apply_injuries(new_body, recovered_items, on_revive_and_player_occupancy, body_data)
|
||||
scenario.death_lore += "I should get a formalized assignment!"
|
||||
|
||||
. = new_body
|
||||
// so bodies can also be used for runes, morgue, etc
|
||||
if(!revivable)
|
||||
return
|
||||
|
||||
//it's not necessary since we dont spawn the body until we open the bodybag, but why not be nice for once
|
||||
new_body.reagents.add_reagent(/datum/reagent/toxin/formaldehyde, 5)
|
||||
|
||||
if(!recovered_items)
|
||||
return
|
||||
|
||||
var/obj/item/paper/paper = new()
|
||||
recovered_items += paper
|
||||
|
||||
if(!HAS_TRAIT(new_body, TRAIT_HUSK))
|
||||
paper.name = "DO NOT REMOVE BRAIN"
|
||||
paper.add_raw_text("Body swapping is not covered by medical insurance for unhusked bodies. Chemical brain explosives have been administered to enforce stipend.")
|
||||
var/obj/item/organ/internal/brain/boombrain = new_body.get_organ_by_type(/obj/item/organ/internal/brain)
|
||||
//I swear to fuck I will explode you. you're not clever
|
||||
//everyone thought of this, but I am the fool for having any faith
|
||||
//in people actually wanting to play the job in an interesting manner
|
||||
//instead of just taking the easiest way out and learning nothing
|
||||
//(no one abused it yet but I am already getting pinged by people who think they've broken the system when really I just expected better of them)
|
||||
boombrain.AddElement(/datum/element/dangerous_organ_removal)
|
||||
else
|
||||
paper.name = "BODYSWAPPING PERMITTED"
|
||||
paper.add_raw_text("Body swapping is covered by medical insurance in case of husking and a lack of skill in the practictioner.")
|
||||
|
||||
var/obj/item/organ/internal/brain/hersens = new_body.get_organ_by_type(/obj/item/organ/internal/brain)
|
||||
hersens.AddComponent(
|
||||
/datum/component/ghostrole_on_revive, \
|
||||
/* refuse_revival_if_failed = */ TRUE, \
|
||||
/*on_revival = */ CALLBACK(src, PROC_REF(on_succesful_revive), hersens, scenario.death_lore, on_revive_and_player_occupancy) \
|
||||
)
|
||||
|
||||
/// Set a timer for awarding succes and drop some awesome deathlore
|
||||
/datum/lost_crew_manager/proc/on_succesful_revive(obj/item/organ/internal/brain/brain, list/death_lore, list/datum/callback/on_revive_and_player_occupancy)
|
||||
var/mob/living/carbon/human/owner = brain.owner
|
||||
|
||||
owner.mind.add_antag_datum(/datum/antagonist/recovered_crew) //for tracking mostly
|
||||
|
||||
var/datum/bank_account/bank_account = new(owner.real_name, owner.mind.assigned_role, owner.dna.species.payday_modifier)
|
||||
bank_account.adjust_money(starting_funds, "[starting_funds]cr given to [owner.name] as starting fund.")
|
||||
owner.account_id = bank_account.account_id
|
||||
bank_account.replaceable = FALSE
|
||||
|
||||
owner.add_mob_memory(/datum/memory/key/account, remembered_id = owner.account_id)
|
||||
|
||||
death_lore += "My account number was [owner.account_id]."
|
||||
|
||||
brain.RemoveElement(/datum/element/dangerous_organ_removal)
|
||||
|
||||
// Drop the sick ass death lore and give them an indicator of who they were and what they can do
|
||||
for(var/i in 1 to death_lore.len)
|
||||
addtimer(CALLBACK(src, GLOBAL_PROC_REF(to_chat), owner, span_boldnotice(death_lore[i])), 10 SECONDS + 2 SECONDS * i)
|
||||
|
||||
addtimer(CALLBACK(src, PROC_REF(award_succes), owner.mind, death_lore), succes_check_time)
|
||||
|
||||
// Run any callbacks our characters or damages may have placed for some effects for when the player is revived
|
||||
for(var/datum/callback/callback as anything in on_revive_and_player_occupancy)
|
||||
callback.Invoke()
|
||||
|
||||
/// Give medbay a happy announcement and put some money into their budget
|
||||
/datum/lost_crew_manager/proc/award_succes(datum/mind/revived_mind, list/death_lore)
|
||||
var/obj/item/radio/headset/radio = new /obj/item/radio/headset/silicon/ai(revived_mind.current) //radio cant be in nullspace or brit shakes
|
||||
radio.set_frequency(FREQ_MEDICAL)
|
||||
radio.name = "Medical Announcer"
|
||||
|
||||
// i am incredibly disappointed in you
|
||||
if(revived_mind.current.stat == DEAD)
|
||||
radio.talk_into(radio, "Sensors indicate lifesigns of [revived_mind.name] have seized. Please inform their family of your failure.", RADIO_CHANNEL_MEDICAL)
|
||||
return
|
||||
|
||||
// You are a credit to society
|
||||
radio.talk_into(radio, "Sensors indicate continued survival of [revived_mind.name]. Well done, [credits_on_succes]cr has been transferred to the medical budget.", RADIO_CHANNEL_MEDICAL)
|
||||
|
||||
var/datum/bank_account/medical_budget = SSeconomy.get_dep_account(ACCOUNT_MED)
|
||||
medical_budget.adjust_money(credits_on_succes)
|
||||
qdel(radio)
|
||||
|
||||
/// A box for recovered items that can only be opened by the new crewmember
|
||||
/obj/item/storage/lockbox/mind
|
||||
name = "mind lockbox"
|
||||
desc = "A locked box, openable only by one mind."
|
||||
|
||||
/// The mind needed to unlock the box
|
||||
var/datum/mind/mind
|
||||
|
||||
/obj/item/storage/lockbox/mind/attack_self(mob/user, modifiers)
|
||||
. = ..()
|
||||
|
||||
if(user.mind == mind)
|
||||
atom_storage.locked = STORAGE_NOT_LOCKED
|
||||
balloon_alert(user, atom_storage.locked ? "locked" : "unlocked")
|
||||
update_appearance()
|
||||
9
code/modules/lost_crew/recovered_crew.dm
Normal file
9
code/modules/lost_crew/recovered_crew.dm
Normal file
@@ -0,0 +1,9 @@
|
||||
/// Revived crew ready to serve once more! Only here for tracking/admin reasons, otherwise hidden
|
||||
/datum/antagonist/recovered_crew
|
||||
name = "\improper Recovered Crew"
|
||||
show_in_antagpanel = TRUE
|
||||
job_rank = ROLE_RECOVERED_CREW
|
||||
show_name_in_check_antagonists = TRUE
|
||||
show_to_ghosts = FALSE
|
||||
silent = TRUE
|
||||
block_midrounds = FALSE
|
||||
@@ -874,11 +874,8 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_atoms_ontop)
|
||||
var/admin_spawned
|
||||
///number of bodies to spawn
|
||||
var/bodycount = 3
|
||||
/// These species IDs will be barred from spawning if morgue_cadaver_disable_nonhumans is disabled (In the future, we can also dehardcode this)
|
||||
var/list/blacklisted_from_rng_placement = list(
|
||||
SPECIES_ETHEREAL, // they revive on death which is bad juju
|
||||
SPECIES_HUMAN, // already have a 50% chance of being selected
|
||||
)
|
||||
/// Corpse type we spawn thats always human
|
||||
var/datum/corpse_damage_class/morgue_body_class = /datum/corpse_damage_class/station/morgue
|
||||
|
||||
/obj/effect/mapping_helpers/dead_body_placer/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -906,57 +903,16 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_atoms_ontop)
|
||||
|
||||
var/reuse_trays = (numtrays < bodycount) //are we going to spawn more trays than bodies?
|
||||
|
||||
var/use_species = !(CONFIG_GET(flag/morgue_cadaver_disable_nonhumans))
|
||||
var/species_probability = CONFIG_GET(number/morgue_cadaver_other_species_probability)
|
||||
var/override_species = CONFIG_GET(string/morgue_cadaver_override_species)
|
||||
var/list/usable_races
|
||||
if(use_species)
|
||||
var/list/temp_list = get_selectable_species()
|
||||
usable_races = temp_list.Copy()
|
||||
LAZYREMOVE(usable_races, blacklisted_from_rng_placement)
|
||||
if(!LAZYLEN(usable_races))
|
||||
notice("morgue_cadaver_disable_nonhumans. There are no valid roundstart nonhuman races enabled. Defaulting to humans only!")
|
||||
if(override_species)
|
||||
warning("morgue_cadaver_override_species BEING OVERRIDEN since morgue_cadaver_disable_nonhumans is disabled.")
|
||||
else if(override_species)
|
||||
LAZYADD(usable_races, override_species)
|
||||
|
||||
var/guaranteed_human_spawned = FALSE
|
||||
for (var/i in 1 to bodycount)
|
||||
var/obj/structure/bodycontainer/morgue/morgue_tray = reuse_trays ? pick(trays) : pick_n_take(trays)
|
||||
var/obj/structure/closet/body_bag/body_bag = new(morgue_tray.loc)
|
||||
var/mob/living/carbon/human/new_human = new(morgue_tray.loc)
|
||||
|
||||
var/species_to_pick
|
||||
|
||||
if(guaranteed_human_spawned && use_species)
|
||||
if(LAZYLEN(usable_races))
|
||||
if(!isnum(species_probability))
|
||||
species_probability = 50
|
||||
stack_trace("WARNING: morgue_cadaver_other_species_probability CONFIG SET TO 0% WHEN SPAWNING. DEFAULTING TO [species_probability]%.")
|
||||
if(prob(species_probability))
|
||||
species_to_pick = pick(usable_races)
|
||||
var/datum/species/new_human_species = GLOB.species_list[species_to_pick]
|
||||
if(new_human_species)
|
||||
new_human.set_species(new_human_species)
|
||||
new_human.fully_replace_character_name(new_human.real_name, new_human.generate_random_mob_name())
|
||||
else
|
||||
stack_trace("failed to spawn cadaver with species ID [species_to_pick]") //if it's invalid they'll just be a human, so no need to worry too much aside from yelling at the server owner lol.
|
||||
else
|
||||
guaranteed_human_spawned = TRUE
|
||||
var/mob/living/carbon/human/new_human = GLOB.lost_crew_manager.create_lost_crew(revivable = FALSE, forced_class = morgue_body_class)
|
||||
|
||||
body_bag.insert(new_human, TRUE)
|
||||
body_bag.close()
|
||||
body_bag.handle_tag("[new_human.real_name][species_to_pick ? " - [capitalize(species_to_pick)]" : " - Human"]")
|
||||
body_bag.handle_tag("[new_human.real_name][new_human.dna?.species ? " - [new_human.dna.species.name]" : " - Human"]")
|
||||
body_bag.forceMove(morgue_tray)
|
||||
|
||||
new_human.death() //here lies the mans, rip in pepperoni.
|
||||
for (var/obj/item/organ/internal/part in new_human.organs) //randomly remove organs from each body, set those we keep to be in stasis
|
||||
if (prob(40))
|
||||
qdel(part)
|
||||
else
|
||||
part.organ_flags |= ORGAN_FROZEN
|
||||
|
||||
morgue_tray.update_appearance()
|
||||
|
||||
qdel(src)
|
||||
|
||||
@@ -244,7 +244,7 @@
|
||||
|
||||
/mob/living/carbon/on_fall()
|
||||
. = ..()
|
||||
loc.handle_fall(src)//it's loc so it doesn't call the mob's handle_fall which does nothing
|
||||
loc?.handle_fall(src)//it's loc so it doesn't call the mob's handle_fall which does nothing
|
||||
|
||||
/mob/living/carbon/resist_buckle()
|
||||
if(!HAS_TRAIT(src, TRAIT_RESTRAINED))
|
||||
|
||||
@@ -239,9 +239,12 @@
|
||||
if(CONSCIOUS)
|
||||
if(HAS_TRAIT(src, TRAIT_DUMB))
|
||||
. += "[t_He] [t_has] a stupid expression on [t_his] face."
|
||||
if(get_organ_by_type(/obj/item/organ/internal/brain) && isnull(ai_controller))
|
||||
var/obj/item/organ/internal/brain/brain = get_organ_by_type(/obj/item/organ/internal/brain)
|
||||
if(brain && isnull(ai_controller))
|
||||
var/npc_message = ""
|
||||
if(!key)
|
||||
if(HAS_TRAIT(brain, TRAIT_GHOSTROLE_ON_REVIVE))
|
||||
npc_message = "Soul is pending..."
|
||||
else if(!key)
|
||||
npc_message = "[t_He] [t_is] totally catatonic. The stresses of life in deep-space must have been too much for [t_him]. Any recovery is unlikely."
|
||||
else if(!client)
|
||||
npc_message ="[t_He] [t_has] a blank, absent-minded stare and appears completely unresponsive to anything. [t_He] may snap out of it soon."
|
||||
@@ -317,7 +320,10 @@
|
||||
var/t_his = p_their()
|
||||
var/t_is = p_are()
|
||||
//This checks to see if the body is revivable
|
||||
if(get_organ_by_type(/obj/item/organ/internal/brain) && (client || HAS_TRAIT(src, TRAIT_MIND_TEMPORARILY_GONE) || (ghost?.can_reenter_corpse && ghost?.client)))
|
||||
var/obj/item/organ/brain = get_organ_by_type(/obj/item/organ/internal/brain)
|
||||
if(brain && HAS_TRAIT(brain, TRAIT_GHOSTROLE_ON_REVIVE))
|
||||
return span_deadsay("[t_He] [t_is] limp and unresponsive; but [t_his] soul might yet come back...")
|
||||
if(brain && (client || HAS_TRAIT(src, TRAIT_MIND_TEMPORARILY_GONE) || (ghost?.can_reenter_corpse && ghost?.client)))
|
||||
return span_deadsay("[t_He] [t_is] limp and unresponsive; there are no signs of life...")
|
||||
else
|
||||
return span_deadsay("[t_He] [t_is] limp and unresponsive; there are no signs of life and [t_his] soul has departed...")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/// List of roundstart races' their species_id's
|
||||
GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
///List of all roundstart languages by path except common
|
||||
GLOBAL_LIST_EMPTY(uncommon_roundstart_languages)
|
||||
@@ -192,7 +193,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
|
||||
|
||||
return ..()
|
||||
|
||||
/// Gets a list of all species available to choose in roundstart.
|
||||
/// Gets a list of all species id's available to choose in roundstart.
|
||||
/proc/get_selectable_species()
|
||||
RETURN_TYPE(/list)
|
||||
|
||||
|
||||
@@ -251,6 +251,8 @@
|
||||
|
||||
owner = null
|
||||
|
||||
QDEL_LAZYLIST(scars)
|
||||
|
||||
for(var/atom/movable/movable in contents)
|
||||
qdel(movable)
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
if(org_zone != BODY_ZONE_CHEST)
|
||||
continue
|
||||
organ.Remove(chest_owner)
|
||||
if(chest_owner.loc)
|
||||
organ.forceMove(chest_owner.loc)
|
||||
. += organ
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* * typepath The typepath of the organ to get
|
||||
*/
|
||||
/mob/proc/get_organ_by_type(typepath)
|
||||
RETURN_TYPE(/obj/item/organ)
|
||||
return
|
||||
|
||||
/**
|
||||
|
||||
@@ -285,7 +285,7 @@
|
||||
//surplus organs are so awful that they explode when removed, unless failing
|
||||
/obj/item/organ/internal/heart/cybernetic/surplus/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/dangerous_surgical_removal)
|
||||
AddElement(/datum/element/dangerous_organ_removal, /*surgical = */ TRUE)
|
||||
|
||||
/obj/item/organ/internal/heart/freedom
|
||||
name = "heart of freedom"
|
||||
|
||||
@@ -270,7 +270,7 @@
|
||||
//surplus organs are so awful that they explode when removed, unless failing
|
||||
/obj/item/organ/internal/liver/cybernetic/surplus/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/dangerous_surgical_removal)
|
||||
AddElement(/datum/element/dangerous_organ_removal, /*surgical = */ TRUE)
|
||||
|
||||
#undef LIVER_DEFAULT_TOX_TOLERANCE
|
||||
#undef LIVER_DEFAULT_TOX_RESISTANCE
|
||||
|
||||
@@ -945,7 +945,7 @@
|
||||
//surplus organs are so awful that they explode when removed, unless failing
|
||||
/obj/item/organ/internal/lungs/cybernetic/surplus/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/dangerous_surgical_removal)
|
||||
AddElement(/datum/element/dangerous_organ_removal, /*surgical = */ TRUE)
|
||||
|
||||
/obj/item/organ/internal/lungs/lavaland
|
||||
name = "blackened frilled lungs" // blackened from necropolis exposure
|
||||
|
||||
@@ -323,6 +323,6 @@
|
||||
//surplus organs are so awful that they explode when removed, unless failing
|
||||
/obj/item/organ/internal/stomach/cybernetic/surplus/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/dangerous_surgical_removal)
|
||||
AddElement(/datum/element/dangerous_organ_removal, /*surgical = */ TRUE)
|
||||
|
||||
#undef STOMACH_METABOLISM_CONSTANT
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
var/list/all_closets = subtypesof(/obj/structure/closet)
|
||||
//Supply pods. They are sent, crashed, opened and never closed again. They also cause exceptions in nullspace.
|
||||
all_closets -= typesof(/obj/structure/closet/supplypod)
|
||||
/// these bitches spawn specially crafted humans with gear and moving organs being shuffled around through the whole process
|
||||
all_closets -= typesof(/obj/structure/closet/body_bag/lost_crew/with_body)
|
||||
|
||||
for(var/closet_type in all_closets)
|
||||
var/obj/structure/closet/closet = allocate(closet_type)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.8 KiB |
@@ -1128,6 +1128,7 @@
|
||||
#include "code\datums\components\gas_leaker.dm"
|
||||
#include "code\datums\components\geiger_sound.dm"
|
||||
#include "code\datums\components\ghost_direct_control.dm"
|
||||
#include "code\datums\components\ghostrole_on_revive.dm"
|
||||
#include "code\datums\components\glass_passer.dm"
|
||||
#include "code\datums\components\gps.dm"
|
||||
#include "code\datums\components\grillable.dm"
|
||||
@@ -4577,6 +4578,18 @@
|
||||
#include "code\modules\lootpanel\search_object.dm"
|
||||
#include "code\modules\lootpanel\ss_looting.dm"
|
||||
#include "code\modules\lootpanel\ui.dm"
|
||||
#include "code\modules\lost_crew\body_bags.dm"
|
||||
#include "code\modules\lost_crew\lost_crew_manager.dm"
|
||||
#include "code\modules\lost_crew\recovered_crew.dm"
|
||||
#include "code\modules\lost_crew\character\_assignment.dm"
|
||||
#include "code\modules\lost_crew\character\_character.dm"
|
||||
#include "code\modules\lost_crew\character\job_datums.dm"
|
||||
#include "code\modules\lost_crew\damages\_damages.dm"
|
||||
#include "code\modules\lost_crew\damages\accident.dm"
|
||||
#include "code\modules\lost_crew\damages\decay.dm"
|
||||
#include "code\modules\lost_crew\damages\melee.dm"
|
||||
#include "code\modules\lost_crew\damages\post_mortem.dm"
|
||||
#include "code\modules\lost_crew\damages\scenarios.dm"
|
||||
#include "code\modules\mafia\_defines.dm"
|
||||
#include "code\modules\mafia\controller.dm"
|
||||
#include "code\modules\mafia\controller_ui.dm"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
export type Antagonist = {
|
||||
// the antag_flag, made lowercase, and with non-alphanumerics removed.
|
||||
// or from non_ruleset_antagonists
|
||||
key: string;
|
||||
|
||||
name: string;
|
||||
|
||||
Reference in New Issue
Block a user