From 18d5630b0ca73c31c83748581e99b7246fc57857 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:48:13 -0700 Subject: [PATCH 001/158] some more recipes and pref sanity --- code/modules/client/preferences.dm | 9 +++++++++ .../chewing/recipes/fried_rice.dm | 18 ++++++++++++++++++ monkestation/code/modules/client/verbs.dm | 2 ++ monkestation/code/modules/mob/login.dm | 2 ++ 4 files changed, 31 insertions(+) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 0dfff4d73fe8..4ff5d791bba0 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -87,6 +87,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) /// If set to TRUE, will update character_profiles on the next ui_data tick. var/tainted_character_profiles = FALSE + ///have we finished loading + var/loaded = FALSE /datum/preferences/Destroy(force) QDEL_NULL(character_preview_view) @@ -129,8 +131,15 @@ GLOBAL_LIST_EMPTY(preferences_datums) parent.set_macros() if(!loaded_preferences_successfully) + stack_trace("[parent]'s preferences failed to load! Attempting a reload of preferences.") + if(load_preferences()) + if(load_character()) + return + stack_trace("[parent]'s preferences failed to load a second time! This means their keybindings and other non character settings may be lost.") + message_admins("[parent]'s prefs failed to load twice! Their keybindings and tokens may have been lost please check on this.") save_preferences() save_character() //let's save this new random character so it doesn't keep generating new ones. + loaded = TRUE /datum/preferences/ui_interact(mob/user, datum/tgui/ui) // There used to be code here that readded the preview view if you "rejoined" diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/fried_rice.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/fried_rice.dm index bc3c2d2c35ae..f21996d94c5e 100644 --- a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/fried_rice.dm +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/fried_rice.dm @@ -15,3 +15,21 @@ list(CHEWIN_ADD_REAGENT, /datum/reagent/consumable/soysauce, 3, base=3), list(CHEWIN_USE_STOVE, J_HI, 5 SECONDS , finish_text = "You can smell fried rice!"), ) + +/datum/chewin_cooking/recipe/ikareis + cooking_container = PAN + food_category = CAT_STOVETOP + product_type = /obj/item/food/salad/ikareis + recipe_guide = "Add boiled rice to pan, some squid ink, add vegetables and sausage, cook for 20 seconds on high." + step_builder = list( + list(CHEWIN_ADD_ITEM, /obj/item/food/boiledrice, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/canned/squid_ink, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/bell_pepper, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/sausage, qmod=0.5), + + list(CHEWIN_ADD_ITEM_OPTIONAL, /obj/item/food/onion_slice, qmod=0.5), + list(CHEWIN_ADD_ITEM_OPTIONAL, /obj/item/food/pineappleslice, qmod=0.5, prod_desc = "Extra sweet!"), + list(CHEWIN_ADD_ITEM_OPTIONAL, /obj/item/food/grown/chili, qmod=0.5, prod_desc = "Extra spicy!"), + + list(CHEWIN_USE_STOVE, J_HI, 20 SECONDS , finish_text = "You can smell ikareis!"), + ) diff --git a/monkestation/code/modules/client/verbs.dm b/monkestation/code/modules/client/verbs.dm index 663221f424bf..eb48d39188c2 100644 --- a/monkestation/code/modules/client/verbs.dm +++ b/monkestation/code/modules/client/verbs.dm @@ -19,6 +19,8 @@ GLOBAL_LIST_INIT(antag_token_config, load_antag_token_config()) to_chat(src, span_notice("NOTE: You will be spawned where ever your ghost is when approved, so becareful where you are.")) if(!client_token_holder) + if(!client.prefs?.loaded) + CRASH("Tried to load client_token's before prefs were loaded how the fuck?") client_token_holder = new(src) var/tier = tgui_input_list(src, "High: [client_token_holder.total_high_threat_tokens] | \ diff --git a/monkestation/code/modules/mob/login.dm b/monkestation/code/modules/mob/login.dm index 9f7768fb04b8..0c20722e48d1 100644 --- a/monkestation/code/modules/mob/login.dm +++ b/monkestation/code/modules/mob/login.dm @@ -10,4 +10,6 @@ client?.twitch = new(client) if(QDELETED(client?.client_token_holder)) + if(!client?.prefs.loaded) + CRASH("Tried to load client_token's on a logging in mob but prefs haven't loaded.") client?.client_token_holder = new(client) From 61b44015cca6c74ccbb7f27db41b71de854b17f9 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:58:40 -0700 Subject: [PATCH 002/158] Update particle.dm --- monkestation/code/modules/blood_for_the_blood_gods/particle.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm index a74415bfeb8a..8744c87400c1 100644 --- a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm @@ -19,6 +19,8 @@ return FALSE /obj/effect/decal/cleanable/blood/particle/proc/start_movement(movement_angle) + if(QDELETED(src)) + return var/datum/component/movable_physics/movable_physics = GetComponent(/datum/component/movable_physics) if(!movable_physics) movable_physics = initialize_physics() From f9941c73c490c98692a6bccd29773d6389f78d38 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:59:02 -0700 Subject: [PATCH 003/158] Update verbs.dm --- monkestation/code/modules/client/verbs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/client/verbs.dm b/monkestation/code/modules/client/verbs.dm index eb48d39188c2..96840a67dec4 100644 --- a/monkestation/code/modules/client/verbs.dm +++ b/monkestation/code/modules/client/verbs.dm @@ -19,7 +19,7 @@ GLOBAL_LIST_INIT(antag_token_config, load_antag_token_config()) to_chat(src, span_notice("NOTE: You will be spawned where ever your ghost is when approved, so becareful where you are.")) if(!client_token_holder) - if(!client.prefs?.loaded) + if(!prefs?.loaded) CRASH("Tried to load client_token's before prefs were loaded how the fuck?") client_token_holder = new(src) From ad475d60b90adaa9d5a39159bc7d506692fc9789 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:59:47 -0700 Subject: [PATCH 004/158] Update preferences.dm --- code/modules/client/preferences.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 4ff5d791bba0..4a0de8b85be7 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -123,6 +123,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/loaded_preferences_successfully = load_preferences() if(loaded_preferences_successfully) if(load_character()) + loaded = TRUE return //we couldn't load character data so just randomize the character appearance + name randomise_appearance_prefs() //let's create a random character then - rather than a fat, bald and naked man. @@ -134,6 +135,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) stack_trace("[parent]'s preferences failed to load! Attempting a reload of preferences.") if(load_preferences()) if(load_character()) + loaded = TRUE return stack_trace("[parent]'s preferences failed to load a second time! This means their keybindings and other non character settings may be lost.") message_admins("[parent]'s prefs failed to load twice! Their keybindings and tokens may have been lost please check on this.") From 88bc5bc7290e92ccc85ec944212cf9e0cc7969a5 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 9 Sep 2024 21:05:11 -0700 Subject: [PATCH 005/158] some ranching fixes --- code/modules/mob/living/living.dm | 4 ++-- .../modules/ranching/chickens/_chicken.dm | 4 +++- .../code/modules/ranching/chickens/_egg.dm | 5 ++-- .../ranching/chickens/ai/chicken_subtrees.dm | 2 +- .../modules/ranching/chickens/tier1/glass.dm | 24 +++++++++++++++++++ .../code/modules/ranching/mutations/tier1.dm | 2 +- 6 files changed, 34 insertions(+), 7 deletions(-) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 1fec8e44db44..d487b8191266 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -246,7 +246,7 @@ visible_message("[src] bounces off \the [O]!") var/atom/throw_target = get_edge_target_turf(src, turn(get_dir(O, src), rand(-1,1) * 45)) playsound(src, 'monkestation/sound/effects/boing1.ogg', 50) - src.throw_at(throw_target, 20, 3, force = 0) + src.throw_at(throw_target, 20, 3, force = 0, gentle = TRUE) return //Called when we bump onto an obj @@ -255,7 +255,7 @@ visible_message("[src] bounces off \the [T]!") var/atom/throw_target = get_edge_target_turf(src, turn(get_dir(T, src), rand(-1,1) * 45)) playsound(src, 'monkestation/sound/effects/boing1.ogg', 50) - src.throw_at(throw_target, 20, 3, force = 0) + src.throw_at(throw_target, 20, 3, force = 0, gentle = TRUE) return //Called when we want to push an atom/movable diff --git a/monkestation/code/modules/ranching/chickens/_chicken.dm b/monkestation/code/modules/ranching/chickens/_chicken.dm index b4e93613c419..8ebdacd3ced3 100644 --- a/monkestation/code/modules/ranching/chickens/_chicken.dm +++ b/monkestation/code/modules/ranching/chickens/_chicken.dm @@ -268,7 +268,9 @@ for(var/mob/living/basic/animals in view(1, src)) animal_count ++ if(animal_count >= overcrowding) - adjust_happiness(-1) + eggs_fertile = FALSE + else + eggs_fertile = TRUE if(!stat && prob(3) && current_feed_amount > 0) current_feed_amount-- diff --git a/monkestation/code/modules/ranching/chickens/_egg.dm b/monkestation/code/modules/ranching/chickens/_egg.dm index 1bd01210ae21..b083575671e6 100644 --- a/monkestation/code/modules/ranching/chickens/_egg.dm +++ b/monkestation/code/modules/ranching/chickens/_egg.dm @@ -73,8 +73,9 @@ birthed.grown_type = layer_hen_type //if no possible mutations default to layer hen type if(birthed.grown_type == /mob/living/basic/chicken/glass) - for(var/list_item in src.reagents.reagent_list) - birthed.glass_egg_reagent.Add(list_item) + for(var/datum/reagent/list_reagent as anything in src.reagents.reagent_list) + birthed.glass_egg_reagent |= list_reagent.type + birthed.glass_egg_reagent[list_reagent.type] = list_reagent.volume if(birthed.grown_type == /mob/living/basic/chicken/stone) birthed.production_type = src.production_type diff --git a/monkestation/code/modules/ranching/chickens/ai/chicken_subtrees.dm b/monkestation/code/modules/ranching/chickens/ai/chicken_subtrees.dm index fbeae2f09650..e88127dfc9bb 100644 --- a/monkestation/code/modules/ranching/chickens/ai/chicken_subtrees.dm +++ b/monkestation/code/modules/ranching/chickens/ai/chicken_subtrees.dm @@ -53,7 +53,7 @@ var/list/viable_conversions = list() for(var/mob/living/basic/chicken/found_chicken in view(4, living_pawn.loc)) - if(!istype(found_chicken, /mob/living/basic/chicken/rev_raptor) || !istype(found_chicken, /mob/living/basic/chicken/raptor) || !istype(found_chicken, /mob/living/basic/chicken/rev_raptor)) + if(!istype(found_chicken, /mob/living/basic/chicken/rev_raptor) && !istype(found_chicken, /mob/living/basic/chicken/raptor) && !istype(found_chicken, /mob/living/basic/chicken/rev_raptor)) viable_conversions |= found_chicken if(!length(viable_conversions)) return diff --git a/monkestation/code/modules/ranching/chickens/tier1/glass.dm b/monkestation/code/modules/ranching/chickens/tier1/glass.dm index e5951e76fecb..22edf4c96079 100644 --- a/monkestation/code/modules/ranching/chickens/tier1/glass.dm +++ b/monkestation/code/modules/ranching/chickens/tier1/glass.dm @@ -7,6 +7,7 @@ liked_foods = list(/obj/item/food/grown/rice = 2) book_desc = "Fragile as glass, but produces the chemical injected into its egg overtime." + /obj/item/food/egg/glass name = "Glass Egg" food_reagents = list() @@ -14,3 +15,26 @@ icon_state = "glass" layer_hen_type = /mob/living/basic/chicken/glass + +/obj/item/food/egg/glass/Initialize(mapload) + . = ..() + START_PROCESSING(SSobj, src) + +/obj/item/food/egg/glass/process(seconds_per_tick) + if(!length(glass_egg_reagents)) // this causes only second gen to work + return + + var/amount_left = max_volume - reagents.total_volume + + var/amount_to_add = min(amount_left, max_volume * 0.1) + + var/minimum_injection = 0 + for(var/datum/reagent/listed as anything in glass_egg_reagents) + minimum_injection += glass_egg_reagents[listed] * 0.1 + + var/multiplier = 1 + if(minimum_injection < amount_to_add) + multiplier = minimum_injection / amount_to_add + + for(var/datum/reagent/listed_reagent as anything in glass_egg_reagents) + reagents.add_reagent(listed_reagent, glass_egg_reagents[listed_reagent] * multiplier) diff --git a/monkestation/code/modules/ranching/mutations/tier1.dm b/monkestation/code/modules/ranching/mutations/tier1.dm index 5d9710e76167..af24317dac17 100644 --- a/monkestation/code/modules/ranching/mutations/tier1.dm +++ b/monkestation/code/modules/ranching/mutations/tier1.dm @@ -58,6 +58,6 @@ /datum/mutation/ranching/chicken/clown chicken_type = /mob/living/basic/chicken/clown egg_type = /obj/item/food/egg/clown - player_job = "Clown" + food_requirements = list(/obj/item/food/grown/banana) can_come_from_string = "White Chicken" From 4d4a6efb70bebccf4f4a276320a23e2da629a958 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 9 Sep 2024 21:20:34 -0700 Subject: [PATCH 006/158] more tweaks --- .../code/modules/ranching/chickens/_chick.dm | 3 ++- .../modules/ranching/chickens/tier1/glass.dm | 20 ++++++++++++++++++ monkestation/icons/obj/ranching/eggs.dmi | Bin 10050 -> 10131 bytes 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/monkestation/code/modules/ranching/chickens/_chick.dm b/monkestation/code/modules/ranching/chickens/_chick.dm index c450a31d3e87..4076454531b9 100644 --- a/monkestation/code/modules/ranching/chickens/_chick.dm +++ b/monkestation/code/modules/ranching/chickens/_chick.dm @@ -92,7 +92,8 @@ if(istype(new_chicken, /mob/living/basic/chicken/glass)) for(var/list_item in glass_egg_reagent) - new_chicken.glass_egg_reagents.Add(list_item) + new_chicken.glass_egg_reagents |= list_item + new_chicken.glass_egg_reagents[list_item] = glass_egg_reagent[list_item] if(istype(new_chicken, /mob/living/basic/chicken/stone)) if(production_type) diff --git a/monkestation/code/modules/ranching/chickens/tier1/glass.dm b/monkestation/code/modules/ranching/chickens/tier1/glass.dm index 22edf4c96079..9d6edc03bfb1 100644 --- a/monkestation/code/modules/ranching/chickens/tier1/glass.dm +++ b/monkestation/code/modules/ranching/chickens/tier1/glass.dm @@ -15,6 +15,7 @@ icon_state = "glass" layer_hen_type = /mob/living/basic/chicken/glass + reagent_flags = DRAWABLE /obj/item/food/egg/glass/Initialize(mapload) . = ..() @@ -38,3 +39,22 @@ for(var/datum/reagent/listed_reagent as anything in glass_egg_reagents) reagents.add_reagent(listed_reagent, glass_egg_reagents[listed_reagent] * multiplier) + + update_appearance() + +/obj/item/food/egg/glass/update_overlays() + . = ..() + var/amount_left = max_volume - reagents.total_volume + var/datum/mutable_appearance/MA = mutable_appearance(icon, "glass-filling", layer, src) + switch(amount_left) + if(5 to INFINITY) + MA.icon_state = "glass-filling" + if(3 to 4.99) + MA.icon_state = "glass-filling-75" + if(2 to 2.99) + MA.icon_state = "glass-filling-50" + if(0 to 1.99) + MA.icon_state = "glass-filling-25" + MA.color = mix_color_from_reagents(reagents.reagent_list) + . += MA + diff --git a/monkestation/icons/obj/ranching/eggs.dmi b/monkestation/icons/obj/ranching/eggs.dmi index 714af45d0a5fb13a1c360d7be7b73cb552363b42..37aff01871d30b14bbc51b337a7d60864983b6fe 100644 GIT binary patch literal 10131 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 literal 10050 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 E7lD*MHUIzs From 929687175b86c4864f8a01cabf1e36118b5aabb6 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:49:04 -0700 Subject: [PATCH 007/158] the medicalling --- code/__DEFINES/~monkestation/blood_datums.dm | 21 + .../~monkestation-helpers/blood_datums.dm | 13 + code/_globalvars/bitfields.dm | 1 + code/datums/components/bloodysoles.dm | 215 +++++----- code/datums/components/cleaner.dm | 14 +- code/datums/components/cult_ritual_item.dm | 2 +- code/datums/dna.dm | 17 +- code/datums/elements/decals/blood.dm | 4 + code/datums/quirks/_quirk.dm | 6 +- code/datums/quirks/negative_quirks.dm | 50 ++- code/datums/records/manifest.dm | 4 +- code/datums/status_effects/debuffs/debuffs.dm | 7 +- code/datums/status_effects/wound_effects.dm | 3 + code/datums/wounds/bones.dm | 14 +- code/datums/wounds/loss.dm | 2 +- code/datums/wounds/pierce.dm | 4 +- code/game/atoms.dm | 21 +- code/game/machinery/computer/dna_console.dm | 6 +- .../machinery/computer/operating_computer.dm | 7 +- .../machinery/computer/records/medical.dm | 2 +- code/game/machinery/medical_kiosk.dm | 2 +- code/game/objects/effects/decals/cleanable.dm | 50 ++- .../effects/decals/cleanable/aliens.dm | 11 +- .../effects/decals/cleanable/humans.dm | 249 ++++++++---- .../effects/decals/cleanable/robots.dm | 25 +- .../objects/effects/spawners/gibspawner.dm | 2 +- .../temporary_visuals/miscellaneous.dm | 3 - .../items/devices/scanners/health_analyzer.dm | 29 +- code/game/objects/items/dna_injector.dm | 6 +- .../items/stacks/sheets/sheet_types.dm | 1 + code/game/objects/items/weaponry.dm | 21 + code/game/turfs/closed/walls.dm | 13 +- code/modules/admin/create_mob.dm | 2 +- code/modules/admin/verbs/list_exposer.dm | 2 +- .../abductor/equipment/glands/blood.dm | 2 +- code/modules/antagonists/brother/brother.dm | 8 +- code/modules/antagonists/cult/blood_magic.dm | 33 +- .../sacrifice_knowledge/sacrifice_buff.dm | 2 +- code/modules/antagonists/obsessed/obsessed.dm | 4 +- code/modules/clothing/clothing.dm | 20 + code/modules/clothing/gloves/_gloves.dm | 5 +- code/modules/clothing/head/_head.dm | 7 +- code/modules/clothing/masks/_masks.dm | 6 +- code/modules/clothing/neck/_neck.dm | 6 +- code/modules/clothing/shoes/_shoes.dm | 6 +- code/modules/clothing/suits/_suits.dm | 4 +- code/modules/clothing/under/_under.dm | 3 +- code/modules/detectivework/scanner.dm | 2 +- code/modules/forensics/forensics_helpers.dm | 11 +- code/modules/hydroponics/grown/replicapod.dm | 2 +- code/modules/hydroponics/seeds.dm | 2 +- code/modules/mob/inventory.dm | 2 +- .../living/basic/bots/cleanbot/cleanbot.dm | 2 - .../basic/space_fauna/demon/demon_items.dm | 6 + code/modules/mob/living/blood.dm | 254 ++++-------- code/modules/mob/living/brain/brain.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 4 + .../mob/living/carbon/carbon_movement.dm | 37 +- .../mob/living/carbon/carbon_update_icons.dm | 4 +- .../mob/living/carbon/human/_species.dm | 94 ++--- code/modules/mob/living/carbon/human/dummy.dm | 2 +- code/modules/mob/living/carbon/human/human.dm | 10 - .../living/carbon/human/human_update_icons.dm | 3 +- .../carbon/human/species_types/jellypeople.dm | 58 ++- .../human/species_types/lizardpeople.dm | 14 +- .../carbon/human/species_types/podpeople.dm | 14 +- .../carbon/human/species_types/snail.dm | 11 +- .../carbon/human/species_types/vampire.dm | 8 +- code/modules/mob/living/carbon/life.dm | 2 +- code/modules/mob/living/damage_procs.dm | 16 +- code/modules/mob/living/living.dm | 59 ++- .../hostile/megafauna/bubblegum.dm | 12 + code/modules/projectiles/projectile.dm | 5 +- .../chemistry/reagents/medicine_reagents.dm | 4 +- .../chemistry/reagents/other_reagents.dm | 69 ++-- .../reagents/reagent_containers/blood_pack.dm | 68 ++-- .../spells/spell_types/jaunt/bloodcrawl.dm | 2 +- code/modules/surgery/bodyparts/_bodyparts.dm | 8 +- .../surgery/bodyparts/dismemberment.dm | 8 + code/modules/unit_tests/bloody_footprints.dm | 11 +- .../mecha/equipment/tools/mining_tools.dm | 6 +- icons/effects/blood.dmi | Bin 191871 -> 175305 bytes icons/effects/footprints.dmi | Bin 3962 -> 4537 bytes icons/mob/effects/dam_mob.dmi | Bin 16182 -> 16007 bytes .../code/game/machinery/computer/cloning.dm | 2 +- .../code/game/machinery/exp_cloner.dm | 2 +- .../abductor/equipment/glands/blood.dm | 15 - .../code/modules/blood_datum/blood.dm | 327 ++++++++++++++++ .../blood_datum/components/limbless_aid.dm | 130 +++++++ .../blood_datum/elements/easy_ignite.dm | 97 +++++ .../modules/blood_datum/forensics_helpers.dm | 36 ++ .../blood_datum/icons/melee_lefthand.dmi | Bin 0 -> 531 bytes .../blood_datum/icons/melee_righthand.dmi | Bin 0 -> 536 bytes .../code/modules/blood_datum/icons/staff.dmi | Bin 0 -> 479 bytes .../blood_datum/icons/status_display.dmi | Bin 0 -> 1541 bytes .../code/modules/blood_datum/items/crutch.dm | 21 + .../operating_table_additions.dm | 72 ++++ .../blood_datum/vital_monitor/vital_reader.dm | 368 ++++++++++++++++++ .../blood_for_the_blood_gods/particle.dm | 19 +- .../slasher/abilities/blood_walk.dm | 11 - .../slasher/abilities/recall_machette.dm | 10 - .../structures/bloodsucker_objects.dm | 2 +- .../modules/mob/living/carbon/human/human.dm | 3 + .../carbon/human/species_type/arachnid.dm | 1 + .../carbon/human/species_type/ethereal.dm | 12 +- .../carbon/human/species_type/floran.dm | 14 +- .../modules/ranching/chickens/tier1/glass.dm | 4 +- .../reagents/reagent_containers/blood_pack.dm | 3 +- .../modules/slimecore/slime_traits/cleaner.dm | 2 - .../smithing/ipcs/body/base_bodyparts.dm | 12 +- .../ipcs/reagents/medical_supplies.dm | 3 +- .../code/modules/smithing/ipcs/species.dm | 2 +- .../modules/smithing/oozelings/species.dm | 8 +- .../virology/immune_systems/_immune_system.dm | 2 +- tgstation.dme | 10 +- 115 files changed, 1951 insertions(+), 984 deletions(-) create mode 100644 code/__DEFINES/~monkestation/blood_datums.dm create mode 100644 code/__HELPERS/~monkestation-helpers/blood_datums.dm delete mode 100644 monkestation/code/modules/antagonists/abductor/equipment/glands/blood.dm create mode 100644 monkestation/code/modules/blood_datum/blood.dm create mode 100644 monkestation/code/modules/blood_datum/components/limbless_aid.dm create mode 100644 monkestation/code/modules/blood_datum/elements/easy_ignite.dm create mode 100644 monkestation/code/modules/blood_datum/forensics_helpers.dm create mode 100644 monkestation/code/modules/blood_datum/icons/melee_lefthand.dmi create mode 100644 monkestation/code/modules/blood_datum/icons/melee_righthand.dmi create mode 100644 monkestation/code/modules/blood_datum/icons/staff.dmi create mode 100644 monkestation/code/modules/blood_datum/icons/status_display.dmi create mode 100644 monkestation/code/modules/blood_datum/items/crutch.dm create mode 100644 monkestation/code/modules/blood_datum/vital_monitor/operating_table_additions.dm create mode 100644 monkestation/code/modules/blood_datum/vital_monitor/vital_reader.dm diff --git a/code/__DEFINES/~monkestation/blood_datums.dm b/code/__DEFINES/~monkestation/blood_datums.dm new file mode 100644 index 000000000000..e1f906a8b103 --- /dev/null +++ b/code/__DEFINES/~monkestation/blood_datums.dm @@ -0,0 +1,21 @@ +#define COMSIG_HUMAN_ON_HANDLE_BLOOD "human_on_handle_blood" + #define HANDLE_BLOOD_HANDLED (1<<0) + #define HANDLE_BLOOD_NO_NUTRITION_DRAIN (1<<1) + #define HANDLE_BLOOD_NO_EFFECTS (1<<2) + +#define COLOR_BLOOD "#c90000" + +/// Modifier used in math involving bloodiness, so the above values can be adjusted easily +#define BLOOD_PER_UNIT_MODIFIER 0.5 + +/// from /datum/status_effect/limp/proc/check_step() +#define COMSIG_CARBON_LIMPING "mob_limp_check" + #define COMPONENT_CANCEL_LIMP (1<<0) + +/// Mob can walk despite having two disabled/missing legs so long as they have two of this trait. +/// Kind of jank, refactor at a later day when I can think of a better solution. +/// Just be sure to call update_limbless_locomotion() after applying / removal +#define TRAIT_NO_LEG_AID "no_leg_aid" + +/// Updating a mob's movespeed when lacking limbs. (list/modifiers) +#define COMSIG_LIVING_LIMBLESS_MOVESPEED_UPDATE "living_get_movespeed_modifiers" diff --git a/code/__HELPERS/~monkestation-helpers/blood_datums.dm b/code/__HELPERS/~monkestation-helpers/blood_datums.dm new file mode 100644 index 000000000000..7e74ac55592d --- /dev/null +++ b/code/__HELPERS/~monkestation-helpers/blood_datums.dm @@ -0,0 +1,13 @@ +/proc/random_human_blood_type() + var/static/list/human_blood_type_weights = list( + /datum/blood_type/crew/human/o_minus = 4, + /datum/blood_type/crew/human/o_plus = 36, + /datum/blood_type/crew/human/a_minus = 28, + /datum/blood_type/crew/human/a_plus = 3, + /datum/blood_type/crew/human/b_minus = 20, + /datum/blood_type/crew/human/b_plus = 1, + /datum/blood_type/crew/human/ab_minus = 5, + /datum/blood_type/crew/human/ab_plus = 1 + ) + + return pick_weight(human_blood_type_weights) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index fb117fadab69..b4051cb172b4 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -438,6 +438,7 @@ DEFINE_BITFIELD(organ_flags, list( "ORGAN_EDIBLE" = ORGAN_EDIBLE, "ORGAN_SYNTHETIC_EMP" = ORGAN_SYNTHETIC_EMP, "ORGAN_UNREMOVABLE" = ORGAN_UNREMOVABLE, + "ORGAN_HIDDEN" = ORGAN_HIDDEN, //Monkestation edit: BLOOD_DATUMS, how was this forgotten )) DEFINE_BITFIELD(respiration_type, list( diff --git a/code/datums/components/bloodysoles.dm b/code/datums/components/bloodysoles.dm index 0d950031f229..0e7635d9174b 100644 --- a/code/datums/components/bloodysoles.dm +++ b/code/datums/components/bloodysoles.dm @@ -3,35 +3,44 @@ * Component for clothing items that can pick up blood from decals and spread it around everywhere when walking, such as shoes or suits with integrated shoes. */ /datum/component/bloodysoles + /* /// The type of the last grub pool we stepped in, used to decide the type of footprints to make var/last_blood_state = BLOOD_STATE_NOT_BLOODY /// How much of each grubby type we have on our feet var/list/bloody_shoes = list(BLOOD_STATE_HUMAN = 0,BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0) + */ //Monkestation removal: BLOOD_DATUMS + + // Monkestation Addition: BLOOD_DATUMS + /// What percentage of the bloodiness is deposited on the ground per step + var/blood_dropped_per_step = 3 + /// Bloodiness on our clothines + VAR_FINAL/total_bloodiness = 0 + // Monkestation Addition: BLOOD_DATUMS /// The ITEM_SLOT_* slot the item is equipped on, if it is. var/equipped_slot - /// The parent item but casted into atom type for easier use. - var/atom/parent_atom - /// Either the mob carrying the item, or the mob itself for the /feet component subtype - var/mob/living/carbon/wielder + VAR_FINAL/mob/living/carbon/wielder /// The world.time when we last picked up blood - var/last_pickup + VAR_FINAL/last_pickup var/footprint_sprite = FOOTPRINT_SPRITE_SHOES /datum/component/bloodysoles/Initialize() if(!isclothing(parent)) return COMPONENT_INCOMPATIBLE - parent_atom = parent RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip)) RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_drop)) RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(on_clean)) +/datum/component/bloodysoles/Destroy() + wielder = null + return ..() + /** * Unregisters from the wielder if necessary */ @@ -55,63 +64,52 @@ var/obj/item/parent_item = parent parent_item.update_slot_icon() - -/datum/component/bloodysoles/proc/reset_bloody_shoes() - bloody_shoes = list(BLOOD_STATE_HUMAN = 0, BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0) - on_changed_bloody_shoes(BLOOD_STATE_NOT_BLOODY) - -///lowers bloody_shoes[index] by adjust_by -/datum/component/bloodysoles/proc/adjust_bloody_shoes(index, adjust_by) - bloody_shoes[index] = max(bloody_shoes[index] - adjust_by, 0) - on_changed_bloody_shoes() - -/datum/component/bloodysoles/proc/set_bloody_shoes(index, new_value) - bloody_shoes[index] = new_value - on_changed_bloody_shoes(index) - ///called whenever the value of bloody_soles changes -/datum/component/bloodysoles/proc/on_changed_bloody_shoes(index) - if(index && index != last_blood_state) - last_blood_state = index +/datum/component/bloodysoles/proc/change_blood_amount(some_amount) + total_bloodiness = clamp(round(total_bloodiness + some_amount, 0.1), 0, BLOOD_ITEM_MAX) if(!wielder) return - if(bloody_shoes[index] <= BLOOD_FOOTPRINTS_MIN * 2)//need twice that amount to make footprints + if(total_bloodiness <= BLOOD_FOOTPRINTS_MIN * 2)//need twice that amount to make footprints UnregisterSignal(wielder, COMSIG_MOVABLE_MOVED) else RegisterSignal(wielder, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved), override = TRUE) + update_icon() /** * Run to equally share the blood between us and a decal */ /datum/component/bloodysoles/proc/share_blood(obj/effect/decal/cleanable/pool) // Share the blood between our boots and the blood pool - var/total_bloodiness = pool.bloodiness + bloody_shoes[pool.blood_state] - - // We can however be limited by how much blood we can hold - var/new_our_bloodiness = min(BLOOD_ITEM_MAX, total_bloodiness / 2) - - set_bloody_shoes(pool.blood_state, new_our_bloodiness) - pool.bloodiness = total_bloodiness - new_our_bloodiness // Give the pool the remaining blood incase we were limited + var/new_total_bloodiness = min(BLOOD_ITEM_MAX, pool.bloodiness + total_bloodiness / 2) + if(new_total_bloodiness == total_bloodiness || new_total_bloodiness == 0) + return - if(HAS_TRAIT(wielder, TRAIT_LIGHT_STEP)) //the character is agile enough to don't mess their clothing and hands just from one blood splatter at floor - return TRUE + var/delta = new_total_bloodiness - total_bloodiness + pool.adjust_bloodiness(-1 * delta) + change_blood_amount(delta) + var/atom/parent_atom = parent parent_atom.add_blood_DNA(GET_ATOM_BLOOD_DNA(pool)) - update_icon() /** - * Find a blood decal on a turf that matches our last_blood_state + * Adds blood to an existing (or new) footprint */ -/datum/component/bloodysoles/proc/find_pool_by_blood_state(turf/turfLoc, typeFilter = null, footprint_sprite) - for(var/obj/effect/decal/cleanable/blood/pool in turfLoc) - if(pool.blood_state == last_blood_state && pool.footprint_sprite == footprint_sprite && (!typeFilter || istype(pool, typeFilter))) - return pool +/datum/component/bloodysoles/proc/add_blood_to_footprint(obj/effect/decal/cleanable/blood/footprints/footprint, bloodiness_to_add, exiting = FALSE) + var/atom/atom_parent = parent + add_parent_to_footprint(footprint) + footprint.adjust_bloodiness(bloodiness_to_add) + footprint.add_blood_DNA(GET_ATOM_BLOOD_DNA(atom_parent)) + if(exiting) + footprint.exited_dirs |= wielder.dir + else + footprint.entered_dirs |= wielder.dir + footprint.update_appearance() /** * Adds the parent type to the footprint's shoe_types var */ -/datum/component/bloodysoles/proc/add_parent_to_footprint(obj/effect/decal/cleanable/blood/footprints/FP) - FP.shoe_types |= parent.type +/datum/component/bloodysoles/proc/add_parent_to_footprint(obj/effect/decal/cleanable/blood/footprints/footprint) + footprint.shoe_types |= parent.type /** * Called when the parent item is equipped by someone @@ -130,7 +128,7 @@ equipped_slot = slot wielder = equipper - if(bloody_shoes[last_blood_state] > BLOOD_FOOTPRINTS_MIN * 2) + if(total_bloodiness > BLOOD_FOOTPRINTS_MIN * 2) RegisterSignal(wielder, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) RegisterSignal(wielder, COMSIG_STEP_ON_BLOOD, PROC_REF(on_step_blood)) @@ -149,61 +147,51 @@ * * Used to make bloody footprints on the ground */ -/datum/component/bloodysoles/proc/on_moved(datum/source, OldLoc, Dir, Forced) +/datum/component/bloodysoles/proc/on_moved(datum/source, atom/old_loc, Dir, Forced) SIGNAL_HANDLER - if(bloody_shoes[last_blood_state] == 0) + if(total_bloodiness <= 0) return if(QDELETED(wielder) || is_obscured()) return if(wielder.body_position == LYING_DOWN || !wielder.has_gravity(wielder.loc)) return - var/half_our_blood = bloody_shoes[last_blood_state] / 2 - var/footprint_sprite = wielder.get_footprint_sprite() + var/atom/parent_atom = parent + var/blood_used = round(total_bloodiness / 3, 0.01) + // Add footprints in old loc if we have enough cream - if(half_our_blood >= BLOOD_FOOTPRINTS_MIN) - var/turf/oldLocTurf = get_turf(OldLoc) - var/obj/effect/decal/cleanable/blood/footprints/oldLocFP = find_pool_by_blood_state(oldLocTurf, /obj/effect/decal/cleanable/blood/footprints, footprint_sprite) - if(oldLocFP) - // Footprints found in the tile we left, add us to it - add_parent_to_footprint(oldLocFP) - if (!(oldLocFP.exited_dirs & wielder.dir)) - oldLocFP.exited_dirs |= wielder.dir - oldLocFP.update_appearance() - else if(find_pool_by_blood_state(oldLocTurf, footprint_sprite = footprint_sprite)) - // No footprints in the tile we left, but there was some other blood pool there. Add exit footprints on it - adjust_bloody_shoes(last_blood_state, half_our_blood) - update_icon() + if(blood_used >= BLOOD_FOOTPRINTS_MIN) + var/turf/old_loc_turf = get_turf(old_loc) + var/obj/effect/decal/cleanable/blood/footprints/old_loc_prints = locate() in old_loc_turf + if(old_loc_prints) + add_blood_to_footprint(old_loc_prints, 0, TRUE) // Add no actual blood, just update sprite - oldLocFP = new(oldLocTurf, footprint_sprite) - if(!QDELETED(oldLocFP)) ///prints merged - oldLocFP.blood_state = last_blood_state - oldLocFP.exited_dirs |= wielder.dir - add_parent_to_footprint(oldLocFP) - oldLocFP.bloodiness = half_our_blood - oldLocFP.add_blood_DNA(GET_ATOM_BLOOD_DNA(parent_atom)) - oldLocFP.update_appearance() + else if(locate(/obj/effect/decal/cleanable/blood) in old_loc_turf) + // No footprints in the tile we left, but there was some other blood pool there. Add exit footprints on it + change_blood_amount(-1 * blood_used) + old_loc_prints = new(old_loc_turf) + if(!QDELETED(old_loc_prints)) // prints merged + add_blood_to_footprint(old_loc_prints, blood_used, TRUE) - half_our_blood = bloody_shoes[last_blood_state] / 2 + blood_used = round(total_bloodiness / 3, 0.01) // If we picked up the blood on this tick in on_step_blood, don't make footprints at the same place if(last_pickup && last_pickup == world.time) return // Create new footprints - if(half_our_blood >= BLOOD_FOOTPRINTS_MIN) - adjust_bloody_shoes(last_blood_state, half_our_blood) - update_icon() + if(blood_used >= BLOOD_FOOTPRINTS_MIN) + var/turf/new_loc_turf = get_turf(parent_atom) + var/obj/effect/decal/cleanable/blood/footprints/new_loc_prints = locate() in new_loc_turf + if(new_loc_prints) + add_blood_to_footprint(new_loc_prints, 0, FALSE) // Add no actual blood, just update sprite - var/obj/effect/decal/cleanable/blood/footprints/FP = new(get_turf(parent_atom), footprint_sprite) - if(!QDELETED(FP)) ///prints merged - FP.blood_state = last_blood_state - FP.entered_dirs |= wielder.dir - add_parent_to_footprint(FP) - FP.bloodiness = half_our_blood - FP.add_blood_DNA(GET_ATOM_BLOOD_DNA(parent_atom)) - FP.update_appearance() + else + change_blood_amount(-1 * blood_used) + new_loc_prints = new(new_loc_turf) + if(!QDELETED(new_loc_prints)) // prints merged + add_blood_to_footprint(new_loc_prints, blood_used, FALSE) /** @@ -214,20 +202,16 @@ /datum/component/bloodysoles/proc/on_step_blood(datum/source, obj/effect/decal/cleanable/pool) SIGNAL_HANDLER - if(QDELETED(wielder) || is_obscured()) + if(QDELETED(wielder) || is_obscured() || !wielder.has_gravity(wielder.loc)) + return + /// The character is agile enough to not mess their clothing and hands just from one blood splatter at floor + if(HAS_TRAIT(wielder, TRAIT_LIGHT_STEP)) + return + // Don't share from other feetprints, not super realistic but I think it ruins the effect a bit + if(istype(pool, /obj/effect/decal/cleanable/blood/footprints)) return - - if(istype(pool, /obj/effect/decal/cleanable/blood/footprints) && pool.blood_state == last_blood_state) - // The pool we stepped in was actually footprints with the same type - var/obj/effect/decal/cleanable/blood/footprints/pool_FP = pool - add_parent_to_footprint(pool_FP) - if((bloody_shoes[last_blood_state] / 2) >= BLOOD_FOOTPRINTS_MIN && !(pool_FP.entered_dirs & wielder.dir)) - // If our feet are bloody enough, add an entered dir - pool_FP.entered_dirs |= wielder.dir - pool_FP.update_appearance() share_blood(pool) - last_pickup = world.time /** @@ -236,10 +220,10 @@ /datum/component/bloodysoles/proc/on_clean(datum/source, clean_types) SIGNAL_HANDLER - if(!(clean_types & CLEAN_TYPE_BLOOD) || last_blood_state == BLOOD_STATE_NOT_BLOODY) + if(!(clean_types & CLEAN_TYPE_BLOOD)) return NONE - reset_bloody_shoes() + total_bloodiness = 0 update_icon() return COMPONENT_CLEANED @@ -248,12 +232,12 @@ * Like its parent but can be applied to carbon mobs instead of clothing items */ /datum/component/bloodysoles/feet + equipped_slot = ITEM_SLOT_FEET var/static/mutable_appearance/bloody_feet /datum/component/bloodysoles/feet/Initialize() if(!iscarbon(parent)) return COMPONENT_INCOMPATIBLE - parent_atom = parent wielder = parent if(footprint_sprite) src.footprint_sprite = footprint_sprite @@ -266,29 +250,26 @@ RegisterSignal(parent, COMSIG_CARBON_EQUIP_SHOECOVER, PROC_REF(equip_shoecover)) /datum/component/bloodysoles/feet/update_icon() - if(ishuman(wielder)) - var/mob/living/carbon/human/human = wielder - if(NOBLOODOVERLAY in human.dna.species.species_traits) - return - if(bloody_shoes[BLOOD_STATE_HUMAN] > 0 && !is_obscured()) - human.remove_overlay(SHOES_LAYER) - human.overlays_standing[SHOES_LAYER] = bloody_feet - human.apply_overlay(SHOES_LAYER) - else - human.update_worn_shoes() + if(!ishuman(wielder)) + return + wielder.remove_overlay(SHOES_LAYER) + if(total_bloodiness > 0 && !is_obscured()) + bloody_feet.color = wielder.get_blood_dna_color() + wielder.overlays_standing[SHOES_LAYER] = bloody_feet + wielder.apply_overlay(SHOES_LAYER) + else + wielder.update_worn_shoes() -/datum/component/bloodysoles/feet/add_parent_to_footprint(obj/effect/decal/cleanable/blood/footprints/FP) +/datum/component/bloodysoles/feet/add_parent_to_footprint(obj/effect/decal/cleanable/blood/footprints/footprint) if(!ishuman(wielder)) - FP.species_types |= "unknown" + footprint.species_types |= "unknown" return // Find any leg of our human and add that to the footprint, instead of the default which is to just add the human type - for(var/X in wielder.bodyparts) - var/obj/item/bodypart/affecting = X - if(affecting.body_part == LEG_RIGHT || affecting.body_part == LEG_LEFT) - if(!affecting.bodypart_disabled) - FP.species_types |= affecting.limb_id - break + for(var/obj/item/bodypart/affecting as anything in wielder.bodyparts) + if(!affecting.bodypart_disabled && (affecting.body_part == LEG_RIGHT || affecting.body_part == LEG_LEFT)) + footprint.species_types |= affecting.limb_id + break /datum/component/bloodysoles/feet/is_obscured() @@ -297,16 +278,12 @@ return wielder.check_obscured_slots(TRUE) & ITEM_SLOT_FEET /datum/component/bloodysoles/feet/on_moved(datum/source, OldLoc, Dir, Forced) - if(wielder.num_legs < 2) - return - - ..() + if(wielder.num_legs >= 2) + return ..() /datum/component/bloodysoles/feet/on_step_blood(datum/source, obj/effect/decal/cleanable/pool) - if(wielder.num_legs < 2) - return - - ..() + if(wielder.num_legs >= 2) + return ..() /datum/component/bloodysoles/feet/proc/unequip_shoecover(datum/source) SIGNAL_HANDLER diff --git a/code/datums/components/cleaner.dm b/code/datums/components/cleaner.dm index 874af94cc50e..eff8531afafc 100644 --- a/code/datums/components/cleaner.dm +++ b/code/datums/components/cleaner.dm @@ -96,8 +96,8 @@ ADD_TRAIT(target, TRAIT_CURRENTLY_CLEANING, REF(src)) // We need to update our planes on overlay changes RegisterSignal(target, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(cleaning_target_moved)) - var/mutable_appearance/low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, target, GAME_PLANE) - var/mutable_appearance/high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, target, ABOVE_GAME_PLANE) + var/mutable_appearance/low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, target, GAME_PLANE, appearance_flags = RESET_COLOR) // Monkestation edit BLOOD_DATUM + var/mutable_appearance/high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, target, ABOVE_GAME_PLANE, appearance_flags = RESET_COLOR) // Monkestation edit BLOOD_DATUM if(target.plane > low_bubble.plane) //check if the higher overlay is necessary target.add_overlay(high_bubble) else if(target.plane == low_bubble.plane) @@ -140,16 +140,18 @@ REMOVE_TRAIT(target, TRAIT_CURRENTLY_CLEANING, REF(src)) /datum/component/cleaner/proc/cleaning_target_moved(atom/movable/source, turf/old_turf, turf/new_turf, same_z_layer) + SIGNAL_HANDLER + if(same_z_layer) return // First, get rid of the old overlay - var/mutable_appearance/old_low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, old_turf, GAME_PLANE) - var/mutable_appearance/old_high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, old_turf, ABOVE_GAME_PLANE) + var/mutable_appearance/old_low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, old_turf, GAME_PLANE, appearance_flags = RESET_COLOR) // NON-MODULE CHANGE + var/mutable_appearance/old_high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, old_turf, ABOVE_GAME_PLANE, appearance_flags = RESET_COLOR) // NON-MODULE CHANGE source.cut_overlay(old_low_bubble) source.cut_overlay(old_high_bubble) // Now, add the new one - var/mutable_appearance/new_low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, new_turf, GAME_PLANE) - var/mutable_appearance/new_high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, new_turf, ABOVE_GAME_PLANE) + var/mutable_appearance/new_low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, new_turf, GAME_PLANE, appearance_flags = RESET_COLOR) // NON-MODULE CHANGE + var/mutable_appearance/new_high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", FLOOR_CLEAN_LAYER, new_turf, ABOVE_GAME_PLANE, appearance_flags = RESET_COLOR) // NON-MODULE CHANGE source.add_overlay(new_low_bubble) source.add_overlay(new_high_bubble) diff --git a/code/datums/components/cult_ritual_item.dm b/code/datums/components/cult_ritual_item.dm index 584d9c0f5267..8d2e9fc133e0 100644 --- a/code/datums/components/cult_ritual_item.dm +++ b/code/datums/components/cult_ritual_item.dm @@ -303,7 +303,7 @@ span_cult("You [cultist.blood_volume ? "slice open your arm and ":""]begin drawing a sigil of the Geometer.") ) - if(cultist.blood_volume) + if(!HAS_TRAIT(cultist, TRAIT_NOBLOOD)) // Monkestation Edit: BLOOD_DATUM cultist.apply_damage(initial(rune_to_scribe.scribe_damage), BRUTE, pick(GLOB.arm_zones), wound_bonus = CANT_WOUND) // *cuts arm* *bone explodes* ever have one of those days? var/scribe_mod = initial(rune_to_scribe.scribe_delay) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index a40c0097eb10..6a4b152ddb84 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -53,7 +53,10 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) var/unique_enzymes ///Stores the hashed values of traits such as skin tones, hair style, and gender var/unique_identity - var/blood_type + /// So humans have a variety of blood types while other species do not + /// This tracks JUST human blood type. Might seem a bit bias but everyone is a human under their scales and feathers. + /// Essentially only exists so humans have their same blood type swapping from human -> non-human -> human. + var/datum/blood_type/crew/human/human_blood_type ///The type of mutant race the player is if applicable (i.e. potato-man) var/datum/species/species = new /datum/species/human ///first value is mutant color @@ -103,7 +106,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) return destination.dna.unique_enzymes = unique_enzymes destination.dna.unique_identity = unique_identity - destination.dna.blood_type = blood_type + destination.dna.human_blood_type = human_blood_type destination.dna.unique_features = unique_features destination.dna.features = features.Copy() destination.dna.real_name = real_name @@ -120,7 +123,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) new_dna.default_mutation_genes = default_mutation_genes new_dna.unique_identity = unique_identity new_dna.unique_features = unique_features - new_dna.blood_type = blood_type + new_dna.human_blood_type = human_blood_type new_dna.features = features.Copy() //if the new DNA has a holder, transform them immediately, otherwise save it if(new_dna.holder) @@ -393,7 +396,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) && real_name == target_dna.real_name \ && species.type == target_dna.species.type \ && compare_list(features, target_dna.features) \ - && blood_type == target_dna.blood_type \ + && human_blood_type == target_dna.human_blood_type \ ) return TRUE @@ -431,9 +434,9 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) unique_enzymes = generate_unique_enzymes() unique_features = generate_unique_features() -/datum/dna/proc/initialize_dna(newblood_type, skip_index = FALSE) +/datum/dna/proc/initialize_dna(newblood_type = random_human_blood_type(), skip_index = FALSE) if(newblood_type) - blood_type = newblood_type + human_blood_type = newblood_type unique_enzymes = generate_unique_enzymes() unique_identity = generate_unique_identity() if(!skip_index) //I hate this @@ -543,7 +546,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) dna.generate_unique_enzymes() if(newblood_type) - dna.blood_type = newblood_type + dna.human_blood_type = newblood_type if(unique_identity) dna.unique_identity = unique_identity diff --git a/code/datums/elements/decals/blood.dm b/code/datums/elements/decals/blood.dm index 889ebb12904b..cd679b80003d 100644 --- a/code/datums/elements/decals/blood.dm +++ b/code/datums/elements/decals/blood.dm @@ -38,6 +38,10 @@ blood_splatter_appearances[index] = pic return TRUE +/datum/element/decal/blood/apply_overlay(obj/item/source, list/overlay_list) + pic.color = source.get_blood_dna_color() || COLOR_BLOOD + return ..() + /datum/element/decal/blood/proc/get_examine_name(datum/source, mob/user, list/override) SIGNAL_HANDLER diff --git a/code/datums/quirks/_quirk.dm b/code/datums/quirks/_quirk.dm index 2b55f0932f04..3c18ddad816d 100644 --- a/code/datums/quirks/_quirk.dm +++ b/code/datums/quirks/_quirk.dm @@ -32,7 +32,7 @@ /// A list of items people can receive from mail who have this quirk enabled /// The base weight for the each quirk's mail goodies list to be selected is 5 /// then the item selected is determined by pick(selected_quirk.mail_goodies) - var/mail_goodies = list() + var/list/mail_goodies = list() //Monkestation Edit BLOOD_DATUM: Why? this is already a list all this does is mess confuse us. /datum/quirk/Destroy() if(quirk_holder) @@ -147,7 +147,7 @@ /// Otherwise, it runs once on the next COMSIG_MOB_LOGIN. /datum/quirk/proc/post_add() return - + /// return additional data that should be remembered by cloning /datum/quirk/proc/clone_data() return @@ -155,7 +155,7 @@ /// create the quirk from clone data /datum/quirk/proc/on_clone(data) return - + /// Subtype quirk that has some bonus logic to spawn items for the player. /datum/quirk/item_quirk /// Lazylist of strings describing where all the quirk items have been spawned. diff --git a/code/datums/quirks/negative_quirks.dm b/code/datums/quirks/negative_quirks.dm index a2528c8c9d92..cb22e6e0118e 100644 --- a/code/datums/quirks/negative_quirks.dm +++ b/code/datums/quirks/negative_quirks.dm @@ -69,31 +69,43 @@ var/min_blood = BLOOD_VOLUME_SAFE - 25 // just barely survivable without treatment /datum/quirk/blooddeficiency/post_add() - if(!ishuman(quirk_holder)) - return + update_mail() - // for making sure the roundstart species has the right blood pack sent to them - var/mob/living/carbon/human/carbon_target = quirk_holder - carbon_target.dna.species.update_quirk_mail_goodies(carbon_target, src) - -/** - * Makes the mob lose blood from having the blood deficiency quirk, if possible - * - * Arguments: - * * seconds_per_tick - */ -/datum/quirk/blooddeficiency/proc/lose_blood(seconds_per_tick) - if(quirk_holder.stat == DEAD) +/datum/quirk/blooddeficiency/add(client/client_source) + . = ..() + RegisterSignal(quirk_holder, COMSIG_HUMAN_ON_HANDLE_BLOOD, PROC_REF(lose_blood)) + RegisterSignal(quirk_holder, COMSIG_SPECIES_GAIN, PROC_REF(update_mail)) + +/datum/quirk/blooddeficiency/remove() + . = ..() + UnregisterSignal(quirk_holder, COMSIG_HUMAN_ON_HANDLE_BLOOD) + UnregisterSignal(quirk_holder, COMSIG_SPECIES_GAIN) + +/datum/quirk/blooddeficiency/proc/lose_blood(mob/living/carbon/human/draining, seconds_per_tick, times_fired) + SIGNAL_HANDLER + if(quirk_holder.stat == DEAD || quirk_holder.blood_volume <= min_blood) return - var/mob/living/carbon/human/carbon_target = quirk_holder - if(HAS_TRAIT(carbon_target, TRAIT_NOBLOOD) && isnull(carbon_target.dna.species.exotic_blood)) //can't lose blood if your species doesn't have any + // Ensures that we don't reduce total blood volume below min_blood. + draining.blood_volume = max(min_blood, draining.blood_volume - draining.dna.species.blood_deficiency_drain_rate * seconds_per_tick) + +/datum/quirk/blooddeficiency/proc/update_mail(datum/source, datum/species/new_species, datum/species/old_species) + SIGNAL_HANDLER + + mail_goodies.Cut() + + var/datum/blood_type/new_type = quirk_holder.get_blood_type() + if(isnull(new_type)) return - if (carbon_target.blood_volume <= min_blood) + if(istype(new_type, /datum/blood_type/crew/human)) + mail_goodies += /obj/item/reagent_containers/blood/o_minus return - // Ensures that we don't reduce total blood volume below min_blood. - carbon_target.blood_volume = max(min_blood, carbon_target.blood_volume - carbon_target.dna.species.blood_deficiency_drain_rate * seconds_per_tick) + + for(var/obj/item/reagent_containers/blood/blood_bag as anything in typesof(/obj/item/reagent_containers/blood)) + if(initial(blood_bag.blood_type) == new_type.type) + mail_goodies += blood_bag + break /datum/quirk/item_quirk/blindness name = "Blind" diff --git a/code/datums/records/manifest.dm b/code/datums/records/manifest.dm index 3bd91072ab8f..786d94ef0f9c 100644 --- a/code/datums/records/manifest.dm +++ b/code/datums/records/manifest.dm @@ -113,7 +113,7 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new) var/datum/record/locked/lockfile = new( age = person.age, - blood_type = person.dna.blood_type, + blood_type = "[person.get_blood_type() || "None"]", character_appearance = character_appearance, dna_string = person.dna.unique_enzymes, fingerprint = md5(person.dna.unique_identity), @@ -130,7 +130,7 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new) var/datum/record/crew/crewfile = new ( age = person.age, - blood_type = person.dna.blood_type, + blood_type = "[person.get_blood_type() || "None"]", character_appearance = character_appearance, dna_string = person.dna.unique_enzymes, fingerprint = md5(person.dna.unique_identity), diff --git a/code/datums/status_effects/debuffs/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm index d1d29681131c..b3933ece3169 100644 --- a/code/datums/status_effects/debuffs/debuffs.dm +++ b/code/datums/status_effects/debuffs/debuffs.dm @@ -365,11 +365,10 @@ /datum/status_effect/stacking/saw_bleed/threshold_cross_effect() owner.adjustBruteLoss(bleed_damage) - var/turf/T = get_turf(owner) - new /obj/effect/temp_visual/bleed/explode(T) + new /obj/effect/temp_visual/bleed/explode(owner.loc) for(var/d in GLOB.alldirs) - new /obj/effect/temp_visual/dir_setting/bloodsplatter(T, d) - playsound(T, SFX_DESECRATION, 100, TRUE, -1) + owner.do_splatter_effect(d) + playsound(owner, SFX_DESECRATION, 100, TRUE, -1) /datum/status_effect/stacking/saw_bleed/bloodletting id = "bloodletting" diff --git a/code/datums/status_effects/wound_effects.dm b/code/datums/status_effects/wound_effects.dm index ed0b7b555e46..f44e71de8db7 100644 --- a/code/datums/status_effects/wound_effects.dm +++ b/code/datums/status_effects/wound_effects.dm @@ -70,6 +70,9 @@ if(!owner.client || owner.body_position == LYING_DOWN || !owner.has_gravity() || (owner.movement_type & FLYING) || forced || owner.buckled) return + if(SEND_SIGNAL(owner, COMSIG_CARBON_LIMPING, (next_leg || right || left)) & COMPONENT_CANCEL_LIMP) + return + // less limping while we have determination still var/determined_mod = owner.has_status_effect(/datum/status_effect/determined) ? 0.5 : 1 diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index 1b63e5a4a2a4..de8858e5932d 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -135,12 +135,10 @@ /datum/wound/blunt/bone/receive_damage(wounding_type, wounding_dmg, wound_bonus) if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE) return - if(ishuman(victim)) - var/mob/living/carbon/human/human_victim = victim - if(HAS_TRAIT(human_victim, TRAIT_NOBLOOD)) - return + if(HAS_TRAIT(victim, TRAIT_NOBLOOD)) + return - if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume && prob(internal_bleeding_chance + wounding_dmg)) + if(limb.body_zone == BODY_ZONE_CHEST && prob(internal_bleeding_chance + wounding_dmg)) var/blood_bled = rand(1, wounding_dmg * (severity == WOUND_SEVERITY_CRITICAL ? 2 : 1.5)) // 12 brute toolbox can cause up to 18/24 bleeding with a severe/critical chest wound switch(blood_bled) if(1 to 6) @@ -150,13 +148,13 @@ victim.bleed(blood_bled, TRUE) if(14 to 19) victim.visible_message("Blood spews out of [victim]'s mouth from the blow to [victim.p_their()] chest!", span_danger("You spit out a string of blood from the blow to your chest!"), vision_distance=COMBAT_MESSAGE_RANGE) - new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir, COLOR_DARK_RED) + victim.do_splatter_effect(victim.dir) victim.bleed(blood_bled) victim.blood_particles(amount = 1) if(20 to INFINITY) victim.visible_message(span_danger("Blood spurts out of [victim]'s mouth from the blow to [victim.p_their()] chest!"), span_danger("You choke up on a spray of blood from the blow to your chest!"), vision_distance=COMBAT_MESSAGE_RANGE) victim.bleed(blood_bled) - new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir, COLOR_DARK_RED) + victim.do_splatter_effect(victim.dir) victim.add_splatter_floor(get_step(victim.loc, victim.dir)) victim.blood_particles(amount = 3) @@ -500,6 +498,6 @@ if(limb.body_zone == BODY_ZONE_HEAD) . += "Cranial Trauma Detected: Patient will suffer random bouts of [severity == WOUND_SEVERITY_SEVERE ? "mild" : "severe"] brain traumas until bone is repaired." - else if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume) + else if(limb.body_zone == BODY_ZONE_CHEST && !HAS_TRAIT(victim, TRAIT_NOBLOOD)) . += "Ribcage Trauma Detected: Further trauma to chest is likely to worsen internal bleeding until bone is repaired." . += "" diff --git a/code/datums/wounds/loss.dm b/code/datums/wounds/loss.dm index bcad804eba68..d8d0aad5e80e 100644 --- a/code/datums/wounds/loss.dm +++ b/code/datums/wounds/loss.dm @@ -48,7 +48,7 @@ set_limb(dismembered_part) second_wind() log_wound(victim, src) - if(dismembered_part.can_bleed() && wounding_type != WOUND_BURN && victim.blood_volume) + if(dismembered_part.can_bleed() && wounding_type != WOUND_BURN) victim.spray_blood(attack_direction, severity) victim.blood_particles(amount = rand(3, 6), angle = 0, min_deviation = 0, max_deviation = 360) dismembered_part.dismember(wounding_type == WOUND_BURN ? BURN : BRUTE, wounding_type = wounding_type) diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index 4deb88361768..80897c47364f 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -48,12 +48,12 @@ victim.bleed(blood_bled, TRUE) if(14 to 19) victim.visible_message("A small stream of blood spurts from the hole in [victim]'s [limb.plaintext_zone]!", span_danger("You spit out a string of blood from the blow to your [limb.plaintext_zone]!"), vision_distance=COMBAT_MESSAGE_RANGE) - new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir, COLOR_DARK_RED) + victim.do_splatter_effect(victim.dir) victim.bleed(blood_bled) if(20 to INFINITY) victim.visible_message(span_danger("A spray of blood streams from the gash in [victim]'s [limb.plaintext_zone]!"), span_danger("You choke up on a spray of blood from the blow to your [limb.plaintext_zone]!"), vision_distance=COMBAT_MESSAGE_RANGE) victim.bleed(blood_bled) - new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir, COLOR_DARK_RED) + victim.do_splatter_effect(victim.dir) victim.add_splatter_floor(get_step(victim.loc, victim.dir)) /datum/wound/pierce/bleed/get_bleed_rate_of_change() diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 95ba030e198a..d95c5ad012af 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1042,20 +1042,19 @@ ///returns the mob's dna info as a list, to be inserted in an object's blood_DNA list /mob/living/proc/get_blood_dna_list() - if(get_blood_id() != /datum/reagent/blood) - return - return list("ANIMAL DNA" = "Y-") + var/datum/blood_type/blood = get_blood_type() + if(!isnull(blood)) + return list("UNKNOWN DNA" = blood.type) + return null ///Get the mobs dna list /mob/living/carbon/get_blood_dna_list() - if(get_blood_id() != /datum/reagent/blood) - return - var/list/blood_dna = list() - if(dna) - blood_dna[dna.unique_enzymes] = dna.blood_type - else - blood_dna["UNKNOWN DNA"] = "X*" - return blood_dna + if(isnull(dna)) // Xenos + return ..() + var/datum/blood_type/blood = get_blood_type() + if(isnull(blood)) // Skeletons? + return null + return list("[dna.unique_enzymes]" = blood.type) /mob/living/carbon/alien/get_blood_dna_list() return list("UNKNOWN DNA" = "X*") diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index 932444e63a8f..bd28bed8a6dd 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -1229,7 +1229,7 @@ "UE"=scanner_occupant.dna.unique_enzymes, "UF"=scanner_occupant.dna.unique_features, "name"=scanner_occupant.real_name, - "blood_type"=scanner_occupant.dna.blood_type) + "blood_type"="[GLOB.blood_types[scanner_occupant.dna.human_blood_type]]") return @@ -1719,7 +1719,7 @@ scanner_occupant.real_name = buffer_slot["name"] scanner_occupant.name = buffer_slot["name"] scanner_occupant.dna.unique_enzymes = buffer_slot["UE"] - scanner_occupant.dna.blood_type = buffer_slot["blood_type"] + scanner_occupant.dna.human_blood_type = blood_name_to_blood_type(buffer_slot["blood_type"]) scanner_occupant.apply_status_effect(/datum/status_effect/genetic_damage, damage_increase) scanner_occupant.domutcheck() return TRUE @@ -1737,7 +1737,7 @@ scanner_occupant.real_name = buffer_slot["name"] scanner_occupant.name = buffer_slot["name"] scanner_occupant.dna.unique_enzymes = buffer_slot["UE"] - scanner_occupant.dna.blood_type = buffer_slot["blood_type"] + scanner_occupant.dna.human_blood_type = blood_name_to_blood_type(buffer_slot["blood_type"]) scanner_occupant.apply_status_effect(/datum/status_effect/genetic_damage, damage_increase) scanner_occupant.domutcheck() return TRUE diff --git a/code/game/machinery/computer/operating_computer.dm b/code/game/machinery/computer/operating_computer.dm index 093c96bf57ec..83692a8af26a 100644 --- a/code/game/machinery/computer/operating_computer.dm +++ b/code/game/machinery/computer/operating_computer.dm @@ -138,12 +138,7 @@ data["patient"]["health"] = patient.health // check here to see if the patient has standard blood reagent, or special blood (like how ethereals bleed liquid electricity) to show the proper name in the computer - var/blood_id = patient.get_blood_id() - if(blood_id == /datum/reagent/blood) - data["patient"]["blood_type"] = patient.dna?.blood_type - else - var/datum/reagent/special_blood = GLOB.chemical_reagents_list[blood_id] - data["patient"]["blood_type"] = special_blood ? special_blood.name : blood_id + data["patient"]["blood_type"] = "[patient.get_blood_type() || "None"]" data["patient"]["maxHealth"] = patient.maxHealth data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD diff --git a/code/game/machinery/computer/records/medical.dm b/code/game/machinery/computer/records/medical.dm index 362c8468aa6f..88f68d9c474a 100644 --- a/code/game/machinery/computer/records/medical.dm +++ b/code/game/machinery/computer/records/medical.dm @@ -140,7 +140,7 @@ return FALSE target.age = 18 - target.blood_type = pick(list("A+", "A-", "B+", "B-", "O+", "O-", "AB+", "AB-")) + target.blood_type = "[GLOB.blood_types[random_human_blood_type()]]" target.dna_string = "Unknown" target.gender = "Unknown" target.major_disabilities = "" diff --git a/code/game/machinery/medical_kiosk.dm b/code/game/machinery/medical_kiosk.dm index d42d4844a0e1..9ccacd777f2e 100644 --- a/code/game/machinery/medical_kiosk.dm +++ b/code/game/machinery/medical_kiosk.dm @@ -211,7 +211,7 @@ var/bleed_status = "Patient is not currently bleeding." var/blood_status = " Patient either has no blood, or does not require it to function." var/blood_percent = round((patient.blood_volume / BLOOD_VOLUME_NORMAL)*100) - var/blood_type = patient.dna.blood_type + var/blood_type = "[patient.get_blood_type() || "None"]" var/blood_warning = " " for(var/thing in patient.diseases) //Disease Information diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 966f668d5eb7..5466f4992a34 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -43,7 +43,7 @@ for(var/datum/disease/D in diseases) if(D.spread_flags & (DISEASE_SPREAD_BLOOD)) src.diseases |= D - + AddElement(/datum/element/beauty, beauty) var/turf/T = get_turf(src) @@ -53,6 +53,8 @@ COMSIG_ATOM_ENTERED = PROC_REF(on_entered), ) AddElement(/datum/element/connect_loc, loc_connections) + if(bloodiness) + update_appearance() /obj/effect/decal/cleanable/Destroy() var/turf/T = get_turf(src) @@ -99,7 +101,7 @@ //This is on /cleanable because fuck this ancient mess /obj/effect/decal/cleanable/proc/on_entered(datum/source, atom/movable/AM) SIGNAL_HANDLER - if(iscarbon(AM) && blood_state && bloodiness >= 40) + if(iscarbon(AM) && bloodiness >= 40) SEND_SIGNAL(AM, COMSIG_STEP_ON_BLOOD, src) update_appearance() @@ -114,27 +116,35 @@ * Checks if this decal is a valid decal that can be blood crawled in. */ /obj/effect/decal/cleanable/proc/can_bloodcrawl_in() - if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY)) - return bloodiness - - return FALSE - -/** - * Gets the color associated with the any blood present on this decal. If there is no blood, returns null. - */ -/obj/effect/decal/cleanable/proc/get_blood_color() - switch(blood_state) - if(BLOOD_STATE_HUMAN) - return rgb(149, 10, 10) - if(BLOOD_STATE_XENO) - return rgb(43, 186, 0) - if(BLOOD_STATE_OIL) - return rgb(22, 22, 22) - - return null + return decal_reagent == /datum/reagent/blood /obj/effect/decal/cleanable/proc/handle_merge_decal(obj/effect/decal/cleanable/merger) if(!merger) return if(merger.reagents && reagents) reagents.trans_to(merger, reagents.total_volume) + +/// Increments or decrements the bloodiness value +/obj/effect/decal/cleanable/proc/adjust_bloodiness(by_amount) + if(by_amount == 0) + return FALSE + if(QDELING(src)) + return FALSE + + bloodiness = clamp((bloodiness + by_amount), 0, BLOOD_POOL_MAX) + update_appearance() + return TRUE + +/// Called before attempting to scoop up reagents from this decal to only load reagents when necessary +/obj/effect/decal/cleanable/proc/lazy_init_reagents() + return + +#ifdef TESTING +/obj/effect/decal/cleanable/update_overlays() + . = ..() + if(bloodiness) + var/mutable_appearance/blah_text = new() + blah_text.maptext = MAPTEXT_TINY_UNICODE("[bloodiness]") + blah_text.appearance_flags |= (KEEP_APART|RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM) + . += blah_text +#endif diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm index 6da917e8aab9..8083249d742d 100644 --- a/code/game/objects/effects/decals/cleanable/aliens.dm +++ b/code/game/objects/effects/decals/cleanable/aliens.dm @@ -7,13 +7,14 @@ icon_state = "xfloor1" random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7") bloodiness = BLOOD_AMOUNT_PER_DECAL - blood_state = BLOOD_STATE_XENO beauty = -250 clean_type = CLEAN_TYPE_BLOOD + decal_reagent = /datum/blood_type/xenomorph::reagent_type + reagent_amount = 15 /obj/effect/decal/cleanable/xenoblood/Initialize(mapload) . = ..() - add_blood_DNA(list("UNKNOWN DNA" = "X*")) + add_blood_DNA(list("UNKNOWN DNA" = /datum/blood_type/xenomorph)) /obj/effect/decal/cleanable/xenoblood/xsplatter random_icon_states = list("xgibbl1", "xgibbl2", "xgibbl3", "xgibbl4", "xgibbl5") @@ -100,10 +101,6 @@ icon_state = "xgiblarvatorso" random_icon_states = list("xgiblarvahead", "xgiblarvatorso") -/obj/effect/decal/cleanable/blood/xtracks +/obj/effect/decal/cleanable/xenoblood/xtracks icon_state = "xtracks" random_icon_states = null - -/obj/effect/decal/cleanable/blood/xtracks/Initialize(mapload) - . = ..() - add_blood_DNA(list("Unknown DNA" = "X*")) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 08715536511e..c1ea447f78a6 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -1,6 +1,6 @@ /obj/effect/decal/cleanable/blood name = "blood" - desc = "It's red and gooey. Perhaps it's the chef's cooking?" + desc = "It's weird and gooey. Perhaps it's the chef's cooking?" icon = 'icons/effects/blood.dmi' icon_state = "floor1" random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7") @@ -8,64 +8,141 @@ bloodiness = BLOOD_AMOUNT_PER_DECAL beauty = -100 clean_type = CLEAN_TYPE_BLOOD - var/should_dry = TRUE - var/dryname = "dried blood" //when the blood lasts long enough, it becomes dry and gets a new name - var/drydesc = "Looks like it's been here a while. Eew." //as above - var/drytime = 0 + decal_reagent = /datum/reagent/blood + bloodiness = BLOOD_AMOUNT_PER_DECAL + color = COLOR_BLOOD + appearance_flags = parent_type::appearance_flags | KEEP_TOGETHER + /// Can this blood dry out? + var/can_dry = TRUE + /// Is this blood dried out? + var/dried = FALSE + + /// The "base name" of the blood, IE the "pool of" in "pool of blood" + var/base_name = "pool of" + /// When dried, this is prefixed to the name + var/dry_prefix = "dried" + /// When dried, this becomes the desc of the blood + var/dry_desc = "Looks like it's been here a while. Eew." + + /// How long it takes to dry out + var/drying_time = 5 MINUTES + /// The process to drying out, recorded in deciseconds + var/drying_progress = 0 + /// Color matrix applied to dried blood via filter to make it look dried + var/static/list/blood_dry_filter_matrix = list( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + -0.75, -0.75, -0.75, 0, + ) var/count = 0 var/footprint_sprite = null /obj/effect/decal/cleanable/blood/Initialize(mapload) . = ..() - if(!should_dry) - return - if(bloodiness) - start_drying() - else - dry() - -/obj/effect/decal/cleanable/blood/process() - if(world.time > drytime) - dry() + START_PROCESSING(SSblood_drying, src) + if(color && can_dry && !dried) + update_blood_drying_effect() /obj/effect/decal/cleanable/blood/Destroy() - STOP_PROCESSING(SSobj, src) + STOP_PROCESSING(SSblood_drying, src) return ..() -/obj/effect/decal/cleanable/blood/proc/get_timer() - drytime = world.time + 3 MINUTES +#define DRY_FILTER_KEY "dry_effect" + +/obj/effect/decal/cleanable/blood/proc/update_blood_drying_effect() + if(!can_dry) + remove_filter(DRY_FILTER_KEY) // I GUESS + return + + var/existing_filter = get_filter(DRY_FILTER_KEY) + if(dried) + if(existing_filter) + animate(existing_filter) // just stop existing animations and force it to the end state + return + add_filter(DRY_FILTER_KEY, 2, color_matrix_filter(blood_dry_filter_matrix)) + return + + if(existing_filter) + remove_filter(DRY_FILTER_KEY) + + add_filter(DRY_FILTER_KEY, 2, color_matrix_filter()) + transition_filter(DRY_FILTER_KEY, color_matrix_filter(blood_dry_filter_matrix), drying_time - drying_progress) -/obj/effect/decal/cleanable/blood/proc/start_drying() - get_timer() - START_PROCESSING(SSobj, src) +#undef DRY_FILTER_KEY + +/obj/effect/decal/cleanable/blood/proc/get_blood_string() + var/list/all_dna = GET_ATOM_BLOOD_DNA(src) + var/list/all_blood_names = list() + for(var/dna_sample in all_dna) + var/datum/blood_type/blood = GLOB.blood_types[all_dna[dna_sample]] + all_blood_names |= lowertext(initial(blood.reagent_type.name)) + return english_list(all_blood_names) + +/obj/effect/decal/cleanable/blood/process(seconds_per_tick) + if(dried || !can_dry) + return PROCESS_KILL + + adjust_bloodiness(-0.4 * BLOOD_PER_UNIT_MODIFIER * seconds_per_tick) + drying_progress += (seconds_per_tick * 1 SECONDS) + if(drying_progress >= drying_time + SSblood_drying.wait) // Do it next tick when we're done + dry() + +/obj/effect/decal/cleanable/blood/update_name(updates) + . = ..() + name = initial(name) + if(base_name) + name = "[base_name] [get_blood_string()]" + if(dried && dry_prefix) + name = "[dry_prefix] [name]" + +/obj/effect/decal/cleanable/blood/update_desc(updates) + . = ..() + desc = initial(desc) + if(dried && dry_desc) + desc = dry_desc ///This is what actually "dries" the blood. Returns true if it's all out of blood to dry, and false otherwise /obj/effect/decal/cleanable/blood/proc/dry() - if(bloodiness > 20) - bloodiness -= BLOOD_AMOUNT_PER_DECAL - get_timer() + dried = TRUE + reagents?.clear_reagents() + update_appearance() + update_blood_drying_effect() + STOP_PROCESSING(SSblood_drying, src) + return TRUE + +/obj/effect/decal/cleanable/blood/lazy_init_reagents() + var/list/all_dna = GET_ATOM_BLOOD_DNA(src) + var/list/reagents_to_add = list() + for(var/dna_sample in all_dna) + var/datum/blood_type/blood = GLOB.blood_types[all_dna[dna_sample]] + reagents_to_add += blood.reagent_type + + var/num_reagents = length(reagents_to_add) + for(var/reagent_type in reagents_to_add) + reagents.add_reagent(reagent_type, round((bloodiness * 0.2 * BLOOD_PER_UNIT_MODIFIER) / num_reagents, CHEMICAL_VOLUME_ROUNDING)) + +/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/merger) + if(merger.dried) // New blood will lie on dry blood return FALSE - else - name = dryname - desc = drydesc - bloodiness = 0 - color = COLOR_GRAY //not all blood splatters have their own sprites... It still looks pretty nice - STOP_PROCESSING(SSobj, src) - return TRUE - -/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C) - C.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) - if (bloodiness) - C.bloodiness = min((C.bloodiness + bloodiness), BLOOD_AMOUNT_PER_DECAL) return ..() +/obj/effect/decal/cleanable/blood/handle_merge_decal(obj/effect/decal/cleanable/blood/merger) + . = ..() + merger.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + merger.adjust_bloodiness(bloodiness) + merger.drying_progress -= (bloodiness * BLOOD_PER_UNIT_MODIFIER) // goes negative = takes longer to dry + merger.update_blood_drying_effect() + /obj/effect/decal/cleanable/blood/old bloodiness = 0 icon_state = "floor1-old" /obj/effect/decal/cleanable/blood/old/Initialize(mapload, list/datum/disease/diseases) - add_blood_DNA(list("Non-human DNA" = random_blood_type())) // Needs to happen before ..() + add_blood_DNA(list("UNKNOWN DNA" = random_human_blood_type())) . = ..() + dry() /obj/effect/decal/cleanable/blood/splatter icon_state = "gibbl1" @@ -83,19 +160,18 @@ desc = "They look like tracks left by wheels." random_icon_states = null beauty = -50 - dryname = "dried tracks" - drydesc = "Some old bloody tracks left by wheels. Machines are evil, perhaps." + base_name = "" + dry_desc = "Some old bloody tracks left by wheels. Machines are evil, perhaps." -/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose - name = "blood" - icon = 'icons/effects/blood.dmi' +/obj/effect/decal/cleanable/blood/trail_holder + name = "trail of blood" desc = "Your instincts say you shouldn't be following these." beauty = -50 + icon_state = null + random_icon_states = null + base_name = "trail of" var/list/existing_dirs = list() -/obj/effect/decal/cleanable/trail_holder/can_bloodcrawl_in() - return TRUE - /obj/effect/decal/cleanable/blood/gibs name = "gibs" desc = "They look bloody and gruesome." @@ -107,8 +183,9 @@ mergeable_decal = FALSE turf_loc_check = FALSE - dryname = "rotting gibs" - drydesc = "They look bloody and gruesome while some terrible smell fills the air." + base_name = "" + dry_prefix = "rotting" + dry_desc = "They look bloody and gruesome while some terrible smell fills the air." decal_reagent = /datum/reagent/consumable/liquidgibs reagent_amount = 5 ///Information about the diseases our streaking spawns @@ -122,6 +199,10 @@ LAZYNULL(streak_diseases) return ..() + +/obj/effect/decal/cleanable/blood/gibs/get_blood_string() + return "" + /obj/effect/decal/cleanable/blood/gibs/replace_decal(obj/effect/decal/cleanable/C) return FALSE //Never fail to place us @@ -203,29 +284,25 @@ desc = "Space Jesus, why didn't anyone clean this up? They smell terrible." icon_state = "gib1-old" bloodiness = 0 - should_dry = FALSE - dryname = "old rotting gibs" - drydesc = "Space Jesus, why didn't anyone clean this up? They smell terrible." + dry_prefix = "" + dry_desc = "" /obj/effect/decal/cleanable/blood/gibs/old/Initialize(mapload, list/datum/disease/diseases) + add_blood_DNA(list("UNKNOWN DNA" = random_human_blood_type())) . = ..() - setDir(pick(1,2,4,8)) - add_blood_DNA(list("Non-human DNA" = random_blood_type())) + setDir(pick(GLOB.cardinals)) AddElement(/datum/element/swabable, CELL_LINE_TABLE_SLUDGE, CELL_VIRUS_TABLE_GENERIC, rand(2,4), 10) dry() /obj/effect/decal/cleanable/blood/drip name = "drips of blood" - desc = "It's red." + desc = "A spattering." icon_state = "drip5" //using drip5 since the others tend to blend in with pipes & wires. random_icon_states = list("drip1","drip2","drip3","drip4","drip5") - bloodiness = 0 - var/drips = 1 - dryname = "drips of blood" - drydesc = "It's red." - -/obj/effect/decal/cleanable/blood/drip/can_bloodcrawl_in() - return TRUE + bloodiness = BLOOD_AMOUNT_PER_DECAL * 0.2 * BLOOD_PER_UNIT_MODIFIER + base_name = "drips of" + dry_desc = "A dried spattering." + drying_time = 1 MINUTES //BLOODY FOOTPRINTS @@ -235,7 +312,9 @@ icon = 'icons/effects/footprints.dmi' icon_state = "blood_shoes_enter" random_icon_states = null - blood_state = BLOOD_STATE_HUMAN //the icon state to load images from + bloodiness = 0 // set based on the bloodiness of the foot + base_name = "" + dry_desc = "HMM... SOMEONE WAS HERE!" var/entered_dirs = 0 var/exited_dirs = 0 @@ -245,9 +324,6 @@ /// List of species that have made footprints here. var/list/species_types = list() - dryname = "dried footprints" - drydesc = "HMM... SOMEONE WAS HERE!" - /obj/effect/decal/cleanable/blood/footprints/Initialize(mapload, footprint_sprite) src.footprint_sprite = footprint_sprite . = ..() @@ -256,6 +332,10 @@ entered_dirs |= dir //Keep the same appearance as in the map editor update_appearance(mapload ? (ALL) : (UPDATE_NAME | UPDATE_DESC)) + +/obj/effect/decal/cleanable/blood/footprints/get_blood_string() + return "" + //Rotate all of the footprint directions too /obj/effect/decal/cleanable/blood/footprints/setDir(newdir) if(dir == newdir) @@ -284,7 +364,7 @@ name = "footprints" if(FOOTPRINT_SPRITE_PAWS) name = "pawprints" - dryname = "dried [name]" + base_name = "dried [name]" return ..() /obj/effect/decal/cleanable/blood/footprints/update_desc(updates) @@ -293,7 +373,7 @@ /obj/effect/decal/cleanable/blood/footprints/update_icon() . = ..() - alpha = min(BLOODY_FOOTPRINT_BASE_ALPHA + (255 - BLOODY_FOOTPRINT_BASE_ALPHA) * bloodiness / (BLOOD_ITEM_MAX / 2), 255) + alpha = min(BLOODY_FOOTPRINT_BASE_ALPHA + (255 - BLOODY_FOOTPRINT_BASE_ALPHA) * bloodiness / ((BLOOD_ITEM_MAX * BLOOD_PER_UNIT_MODIFIER) / 2), 255) //Cache of bloody footprint images //Key: @@ -303,17 +383,23 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) /obj/effect/decal/cleanable/blood/footprints/update_overlays() . = ..() + var/icon_state_to_use = "blood" + if(SPECIES_MONKEY in species_types) + icon_state_to_use += "paw" + else if(BODYPART_ID_DIGITIGRADE in species_types) + icon_state_to_use += "claw" + for(var/Ddir in GLOB.cardinals) if(entered_dirs & Ddir) - var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["entered-[footprint_sprite]-[blood_state]-[Ddir]"] + var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["entered-[icon_state_to_use]-[Ddir]"] if(!bloodstep_overlay) - GLOB.bloody_footprints_cache["entered-[footprint_sprite]-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]_[footprint_sprite]_enter", dir = Ddir) + GLOB.bloody_footprints_cache["entered-[icon_state_to_use]-[Ddir]"] = bloodstep_overlay = image(icon, "[icon_state_to_use]1", dir = Ddir) . += bloodstep_overlay if(exited_dirs & Ddir) - var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["exited-[footprint_sprite]-[blood_state]-[Ddir]"] + var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["exited-[icon_state_to_use]-[Ddir]"] if(!bloodstep_overlay) - GLOB.bloody_footprints_cache["exited-[footprint_sprite]-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]_[footprint_sprite]_exit", dir = Ddir) + GLOB.bloody_footprints_cache["exited-[icon_state_to_use]-[Ddir]"] = bloodstep_overlay = image(icon, "[icon_state_to_use]2", dir = Ddir) . += bloodstep_overlay @@ -340,21 +426,15 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) else . += "[icon2html('icons/mob/species/human/bodyparts.dmi', user, "[species]_l_leg")] Some [species] feet." -/obj/effect/decal/cleanable/blood/footprints/replace_decal(obj/effect/decal/cleanable/blood/blood_decal) - if(blood_state != blood_decal.blood_state || footprint_sprite != blood_decal.footprint_sprite) //We only replace footprints of the same type as us - return FALSE - return ..() - -/obj/effect/decal/cleanable/blood/footprints/can_bloodcrawl_in() - if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY)) - return TRUE - return FALSE - /obj/effect/decal/cleanable/blood/hitsplatter name = "blood splatter" pass_flags = PASSTABLE | PASSGRILLE icon_state = "hitsplatter1" random_icon_states = list("hitsplatter1", "hitsplatter2", "hitsplatter3") + + base_name = "" + can_dry = FALSE // No point + /// The turf we just came from, so we can back up when we hit a wall var/turf/prev_loc /// The cached info about the blood @@ -368,8 +448,9 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) /// Type of squirt decals we should try to create when moving var/line_type = /obj/effect/decal/cleanable/blood/line -/obj/effect/decal/cleanable/blood/hitsplatter/Initialize(mapload, splatter_strength) +/obj/effect/decal/cleanable/blood/hitsplatter/Initialize(mapload, splatter_strength, blood_color = COLOR_BLOOD) . = ..() + color = blood_color prev_loc = loc //Just so we are sure prev_loc exists if(splatter_strength) src.splatter_strength = splatter_strength @@ -419,9 +500,11 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) if(line_type && isturf(loc)) var/obj/effect/decal/cleanable/line = locate(line_type) in loc if(line) + line.color = color line.add_blood_DNA(blood_dna_info) else line = new line_type(loc, get_dir(prev_loc, loc)) + line.color = color line.add_blood_DNA(blood_dna_info) line.alpha = 0 animate(line, alpha = initial(line.alpha), time = 2) @@ -454,6 +537,8 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) var/obj/effect/decal/cleanable/blood/splatter/over_window/final_splatter = new(prev_loc) final_splatter.pixel_x = (dir == EAST ? 32 : (dir == WEST ? -32 : 0)) final_splatter.pixel_y = (dir == NORTH ? 32 : (dir == SOUTH ? -32 : 0)) + final_splatter.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + final_splatter.add_blood_DNA(blood_dna_info) else // This will only happen if prev_loc is not even a turf, which is highly unlikely. abstract_move(bumped_atom) qdel(src) @@ -463,6 +548,8 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) if(!the_window.fulltile) return var/obj/effect/decal/cleanable/blood/splatter/over_window/final_splatter = new + final_splatter.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + final_splatter.add_blood_DNA(blood_dna_info) final_splatter.forceMove(the_window) the_window.vis_contents += final_splatter the_window.bloodied = TRUE diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm index d3af1e2846b0..4ba60142f57e 100644 --- a/code/game/objects/effects/decals/cleanable/robots.dm +++ b/code/game/objects/effects/decals/cleanable/robots.dm @@ -7,7 +7,6 @@ icon_state = "gib1" layer = LOW_OBJ_LAYER random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7") - blood_state = BLOOD_STATE_OIL bloodiness = BLOOD_AMOUNT_PER_DECAL mergeable_decal = FALSE beauty = -50 @@ -16,6 +15,7 @@ /obj/effect/decal/cleanable/robot_debris/Initialize(mapload) . = ..() RegisterSignal(src, COMSIG_MOVABLE_PIPE_EJECTING, PROC_REF(on_pipe_eject)) + add_blood_DNA(list("UNKNOWN DNA" = /datum/blood_type/oil)) /obj/effect/decal/cleanable/robot_debris/proc/streak(list/directions, mapload=FALSE) var/direction = pick(directions) @@ -76,29 +76,16 @@ icon = 'icons/mob/silicon/robots.dmi' icon_state = "floor1" random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7") - blood_state = BLOOD_STATE_OIL - bloodiness = BLOOD_AMOUNT_PER_DECAL + bloodiness = BLOOD_AMOUNT_PER_DECAL * 2 beauty = -100 clean_type = CLEAN_TYPE_BLOOD decal_reagent = /datum/reagent/fuel/oil reagent_amount = 30 -/obj/effect/decal/cleanable/oil/attackby(obj/item/I, mob/living/user) - var/attacked_by_hot_thing = I.get_temperature() - if(attacked_by_hot_thing) - user.visible_message(span_warning("[user] tries to ignite [src] with [I]!"), span_warning("You try to ignite [src] with [I].")) - log_combat(user, src, (attacked_by_hot_thing < 480) ? "tried to ignite" : "ignited", I) - fire_act(attacked_by_hot_thing) - return - return ..() - -/obj/effect/decal/cleanable/oil/fire_act(exposed_temperature, exposed_volume) - if(exposed_temperature < 480) - return - visible_message(span_danger("[src] catches fire!")) - var/turf/T = get_turf(src) - qdel(src) - new /obj/effect/hotspot(T) +/obj/effect/decal/cleanable/oil/Initialize(mapload, list/datum/disease/diseases) + . = ..() + AddElement(/datum/element/easy_ignite) + add_blood_DNA(list("UNKNOWN DNA" = /datum/blood_type/oil)) /obj/effect/decal/cleanable/oil/streak icon_state = "streak1" diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm index 86dd2bac70bf..20ca27dbdd16 100644 --- a/code/game/objects/effects/spawners/gibspawner.dm +++ b/code/game/objects/effects/spawners/gibspawner.dm @@ -39,7 +39,7 @@ dna_to_add = temp_mob.get_blood_dna_list() qdel(temp_mob) else - dna_to_add = list("Non-human DNA" = random_blood_type()) //else, generate a random bloodtype for it. + dna_to_add = list("UNKNOWN DNA" = random_human_blood_type()) //else, generate a random bloodtype for it. for(var/i in 1 to gibtypes.len) diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index d03cfea3f178..168a3f9b0883 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -73,9 +73,6 @@ target_pixel_y = 8 animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration) -/obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter - splatter_type = "xsplatter" - /obj/effect/temp_visual/dir_setting/speedbike_trail name = "speedbike trails" icon_state = "ion_fade" diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index 0ef37ba652a6..b6ce3135c571 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -374,23 +374,20 @@ " // divs do not need extra linebreak */ // Blood Level - if(target.has_dna()) - var/mob/living/carbon/carbontarget = target - var/blood_id = carbontarget.get_blood_id() - if(blood_id) - if(carbontarget.is_bleeding()) + // NON-MODULE CHANGE + if(target.has_dna() && target.get_blood_type()) + if(iscarbon(target)) + var/mob/living/carbon/bleeder = target + if(bleeder.is_bleeding()) render_list += "Subject is bleeding!\n" - var/blood_percent = round((carbontarget.blood_volume / BLOOD_VOLUME_NORMAL) * 100) - var/blood_type = carbontarget.dna.blood_type - if(blood_id != /datum/reagent/blood) // special blood substance - var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id] - blood_type = R ? R.name : blood_id - if(carbontarget.blood_volume <= BLOOD_VOLUME_SAFE && carbontarget.blood_volume > BLOOD_VOLUME_OKAY) - render_list += "Blood level: LOW [blood_percent] %, [carbontarget.blood_volume] cl, [span_info("type: [blood_type]")]\n" - else if(carbontarget.blood_volume <= BLOOD_VOLUME_OKAY) - render_list += "Blood level: CRITICAL [blood_percent] %, [carbontarget.blood_volume] cl, [span_info("type: [blood_type]")]\n" - else - render_list += "Blood level: [blood_percent] %, [carbontarget.blood_volume] cl, type: [blood_type]\n" + var/blood_percent = round((target.blood_volume / BLOOD_VOLUME_NORMAL) * 100) + var/blood_type = "[target.get_blood_type() || "None"]" + if(target.blood_volume <= BLOOD_VOLUME_SAFE && target.blood_volume > BLOOD_VOLUME_OKAY) + render_list += "Blood level: LOW [blood_percent] %, [target.blood_volume] cl, [span_info("type: [blood_type]")]\n" + else if(target.blood_volume <= BLOOD_VOLUME_OKAY) + render_list += "Blood level: CRITICAL [blood_percent] %, [target.blood_volume] cl, [span_info("type: [blood_type]")]\n" + else + render_list += "Blood level: [blood_percent] %, [target.blood_volume] cl, type: [blood_type]\n" // Cybernetics if(iscarbon(target)) diff --git a/code/game/objects/items/dna_injector.dm b/code/game/objects/items/dna_injector.dm index 9bf31fa4158b..2b4b24787326 100644 --- a/code/game/objects/items/dna_injector.dm +++ b/code/game/objects/items/dna_injector.dm @@ -57,7 +57,7 @@ target.real_name = fields["name"] target.dna.unique_enzymes = fields["UE"] target.name = target.real_name - target.dna.blood_type = fields["blood_type"] + target.dna.human_blood_type = blood_name_to_blood_type(fields["blood_type"]) if(fields["UI"]) //UI+UE target.dna.unique_identity = merge_text(target.dna.unique_identity, fields["UI"]) if(fields["UF"]) @@ -131,11 +131,11 @@ if(!target.dna.previous["UE"]) target.dna.previous["UE"] = target.dna.unique_enzymes if(!target.dna.previous["blood_type"]) - target.dna.previous["blood_type"] = target.dna.blood_type + target.dna.previous["blood_type"] = "[initial(target.dna.human_blood_type.name)]" target.real_name = fields["name"] target.dna.unique_enzymes = fields["UE"] target.name = target.real_name - target.dna.blood_type = fields["blood_type"] + target.dna.human_blood_type = blood_name_to_blood_type(fields["blood_type"]) target.dna.temporary_mutations[UE_CHANGED] = endtime if(fields["UI"]) //UI+UE if(!target.dna.previous["UI"]) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 517a05a58ee7..32bb9ef266a4 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -338,6 +338,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ new/datum/stack_recipe("ore box", /obj/structure/ore_box, 4, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_CONTAINERS),\ new/datum/stack_recipe("wooden crate", /obj/structure/closet/crate/wooden, 6, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE),\ new/datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 1.5 SECONDS, check_density = FALSE, category = CAT_WEAPON_MELEE),\ + new/datum/stack_recipe("wooden crutch", /obj/item/cane/crutch/wood, 5, time = 1.5 SECONDS, check_density = FALSE, category = CAT_WEAPON_MELEE),\ new/datum/stack_recipe("loom", /obj/structure/loom, 10, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_TOOLS), \ new/datum/stack_recipe("mortar", /obj/item/reagent_containers/cup/mortar, 3, category = CAT_CHEMISTRY), \ new/datum/stack_recipe("firebrand", /obj/item/match/firebrand, 2, time = 10 SECONDS, category = CAT_TOOLS), \ diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 5e0e5b1c4092..90d2e616de9a 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -493,6 +493,21 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 0.5) attack_verb_continuous = list("bludgeons", "whacks", "disciplines", "thrashes") attack_verb_simple = list("bludgeon", "whack", "discipline", "thrash") + /// Only exists so the white cane doesn't spawn with its "effects" while unextended + var/start_with_effects = TRUE + +/obj/item/cane/Initialize(mapload) + . = ..() + if(start_with_effects) + add_effects() + +/obj/item/cane/proc/add_effects() + ADD_TRAIT(src, TRAIT_BLIND_TOOL, INNATE_TRAIT) + AddComponent(/datum/component/limbless_aid) + +/obj/item/cane/proc/remove_effects() + REMOVE_TRAIT(src, TRAIT_BLIND_TOOL, INNATE_TRAIT) + qdel(GetComponent(/datum/component/limbless_aid)) /obj/item/cane/white name = "white cane" @@ -504,6 +519,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 force = 1 w_class = WEIGHT_CLASS_SMALL custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 6) + start_with_effects = FALSE /obj/item/cane/white/Initialize(mapload) . = ..() @@ -527,6 +543,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/cane/white/proc/on_transform(obj/item/source, mob/user, active) SIGNAL_HANDLER + if(active) + add_effects() + else + remove_effects() + if(user) balloon_alert(user, active ? "extended" : "collapsed") playsound(src, 'sound/weapons/batonextend.ogg', 50, TRUE) diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index 793447312b94..cafd9556fc4a 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -63,20 +63,29 @@ ADD_TRAIT(src, TRAIT_UNDENSE, LEANING_TRAIT) ADD_TRAIT(src, TRAIT_EXPANDED_FOV, LEANING_TRAIT) + ADD_TRAIT(src, TRAIT_NO_LEG_AID, LEANING_TRAIT) visible_message(span_notice("[src] leans against \the [wall]!"), \ span_notice("You lean against \the [wall]!")) - RegisterSignals(src, list(COMSIG_MOB_CLIENT_PRE_MOVE, COMSIG_HUMAN_DISARM_HIT, COMSIG_LIVING_GET_PULLED, COMSIG_MOVABLE_TELEPORTING, COMSIG_ATOM_DIR_CHANGE), PROC_REF(stop_leaning)) + RegisterSignals(src, list(COMSIG_MOB_CLIENT_PRE_MOVE, COMSIG_HUMAN_DISARM_HIT, COMSIG_LIVING_GET_PULLED, COMSIG_MOVABLE_TELEPORTING, COMSIG_LIVING_RESIST), PROC_REF(stop_leaning)) + RegisterSignal(src, COMSIG_ATOM_DIR_CHANGE, PROC_REF(stop_leaning_dir)) update_fov() is_leaning = TRUE + update_limbless_locomotion() + +/mob/living/carbon/proc/stop_leaning_dir(datum/source, old_dir, new_dir) + SIGNAL_HANDLER + if(new_dir != old_dir) + stop_leaning() /mob/living/carbon/proc/stop_leaning() SIGNAL_HANDLER - UnregisterSignal(src, list(COMSIG_MOB_CLIENT_PRE_MOVE, COMSIG_HUMAN_DISARM_HIT, COMSIG_LIVING_GET_PULLED, COMSIG_MOVABLE_TELEPORTING, COMSIG_ATOM_DIR_CHANGE)) + UnregisterSignal(src, list(COMSIG_MOB_CLIENT_PRE_MOVE, COMSIG_HUMAN_DISARM_HIT, COMSIG_LIVING_GET_PULLED, COMSIG_MOVABLE_TELEPORTING, COMSIG_ATOM_DIR_CHANGE, COMSIG_LIVING_RESIST)) is_leaning = FALSE pixel_y = base_pixel_y + body_position_pixel_x_offset pixel_x = base_pixel_y + body_position_pixel_y_offset REMOVE_TRAIT(src, TRAIT_UNDENSE, LEANING_TRAIT) REMOVE_TRAIT(src, TRAIT_EXPANDED_FOV, LEANING_TRAIT) + REMOVE_TRAIT(src, TRAIT_NO_LEG_AID, LEANING_TRAIT) update_fov() /turf/closed/wall/Initialize(mapload) diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index 77fe81fdb7e9..33d902e84b4e 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -26,7 +26,7 @@ human.eye_color_left = random_eye_color human.eye_color_right = random_eye_color - human.dna.blood_type = random_blood_type() + human.dna.human_blood_type = random_human_blood_type() human.dna.features["mcolor"] = "#[random_color()]" human.dna.species.randomize_active_underwear_only(human) diff --git a/code/modules/admin/verbs/list_exposer.dm b/code/modules/admin/verbs/list_exposer.dm index 851bd901c1e5..c2c48963051e 100644 --- a/code/modules/admin/verbs/list_exposer.dm +++ b/code/modules/admin/verbs/list_exposer.dm @@ -33,7 +33,7 @@ for(var/entry in GLOB.human_list) var/mob/living/carbon/human/subject = entry if(subject.ckey) - data += "[subject][subject.dna.unique_enzymes][subject.dna.blood_type]" + data += "[subject][subject.dna.unique_enzymes][subject.get_blood_type()]" data += "" usr << browse(data, "window=DNA;size=440x410") diff --git a/code/modules/antagonists/abductor/equipment/glands/blood.dm b/code/modules/antagonists/abductor/equipment/glands/blood.dm index 40c2b3c4d726..8a6b43a7baf2 100644 --- a/code/modules/antagonists/abductor/equipment/glands/blood.dm +++ b/code/modules/antagonists/abductor/equipment/glands/blood.dm @@ -15,4 +15,4 @@ var/mob/living/carbon/human/H = owner var/datum/species/species = H.dna.species to_chat(H, span_warning("You feel your blood heat up for a moment.")) - species.exotic_blood = get_random_reagent_id() + species.exotic_bloodtype = pick(subtypesof(/datum/blood_type)) diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm index 611f190ce8d4..1d4ca52b0902 100644 --- a/code/modules/antagonists/brother/brother.dm +++ b/code/modules/antagonists/brother/brother.dm @@ -123,11 +123,15 @@ brother2.set_species(/datum/species/moth) var/icon/brother1_icon = render_preview_outfit(/datum/outfit/job/quartermaster, brother1) - brother1_icon.Blend(icon('icons/effects/blood.dmi', "maskblood"), ICON_OVERLAY) + var/icon/blood1_icon = icon('icons/effects/blood.dmi', "maskblood") + blood1_icon.Blend(COLOR_BLOOD, ICON_MULTIPLY) + brother1_icon.Blend(blood1_icon, ICON_OVERLAY) brother1_icon.Shift(WEST, 8) var/icon/brother2_icon = render_preview_outfit(/datum/outfit/job/scientist/consistent, brother2) - brother2_icon.Blend(icon('icons/effects/blood.dmi', "uniformblood"), ICON_OVERLAY) + var/icon/blood2_icon = icon('icons/effects/blood.dmi', "uniformblood") + blood2_icon.Blend(COLOR_BLOOD, ICON_MULTIPLY) + brother2_icon.Blend(blood2_icon, ICON_OVERLAY) brother2_icon.Shift(EAST, 8) var/icon/final_icon = brother1_icon diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index 1acb4fff68a0..35d85efb4edf 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -762,30 +762,25 @@ uses = 0 playsound(get_turf(M), 'sound/magic/staff_healing.ogg', 25) user.Beam(M, icon_state="sendbeam", time = 1 SECONDS) - if(istype(target, /obj/effect/decal/cleanable/blood)) + if(istype(target, /obj/effect/decal/cleanable/blood) || isturf(target)) blood_draw(target, user) ..() /obj/item/melee/blood_magic/manipulator/proc/blood_draw(atom/target, mob/living/carbon/human/user) - var/temp = 0 - var/turf/T = get_turf(target) - if(T) - for(var/obj/effect/decal/cleanable/blood/B in view(T, 2)) - if(B.blood_state == BLOOD_STATE_HUMAN) - if(B.bloodiness == 100) //Bonus for "pristine" bloodpools, also to prevent cheese with footprint spam - temp += 30 - else - temp += max((B.bloodiness**2)/800,1) - new /obj/effect/temp_visual/cult/turf/floor(get_turf(B)) - qdel(B) - for(var/obj/effect/decal/cleanable/trail_holder/TH in view(T, 2)) - qdel(TH) - if(temp) - user.Beam(T,icon_state="drainbeam", time = 15) + var/blood_to_gain = 0 + var/turf/our_turf = get_turf(target) + if(our_turf) + for(var/obj/effect/decal/cleanable/blood/blood_around_us in range(our_turf,2)) + if(blood_around_us.decal_reagent == /datum/reagent/blood) + blood_to_gain += max(blood_around_us.bloodiness * 0.12 * BLOOD_PER_UNIT_MODIFIER, 1) + new /obj/effect/temp_visual/cult/turf/floor(get_turf(blood_around_us)) + qdel(blood_around_us) + if(blood_to_gain) + user.Beam(our_turf,icon_state="drainbeam", time = 15) new /obj/effect/temp_visual/cult/sparks(get_turf(user)) - playsound(T, 'sound/magic/enter_blood.ogg', 50) - to_chat(user, span_cultitalic("Your blood rite has gained [round(temp)] charge\s from blood sources around you!")) - uses += max(1, round(temp)) + playsound(our_turf, 'sound/magic/enter_blood.ogg', 50) + to_chat(user, span_cultitalic("Your blood rite has gained [round(blood_to_gain)] charge\s from blood sources around you!")) + uses += max(1, round(blood_to_gain)) /obj/item/melee/blood_magic/manipulator/attack_self(mob/living/user) if(IS_CULTIST(user)) diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm index 7a03bace1050..f82b9b829533 100644 --- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm +++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm @@ -86,7 +86,7 @@ * Slow and stop any blood loss the owner's experiencing. */ /datum/status_effect/unholy_determination/proc/adjust_bleed_wounds() - if(!iscarbon(owner) || !owner.blood_volume) + if(HAS_TRAIT(owner, TRAIT_NOBLOOD)) return if(owner.blood_volume < BLOOD_VOLUME_NORMAL) diff --git a/code/modules/antagonists/obsessed/obsessed.dm b/code/modules/antagonists/obsessed/obsessed.dm index 585867d5767b..d58f9b8a82be 100644 --- a/code/modules/antagonists/obsessed/obsessed.dm +++ b/code/modules/antagonists/obsessed/obsessed.dm @@ -41,7 +41,9 @@ victim_dummy.update_body_parts() var/icon/obsessed_icon = render_preview_outfit(preview_outfit) - obsessed_icon.Blend(icon('icons/effects/blood.dmi', "uniformblood"), ICON_OVERLAY) + var/icon/blood_icon = icon('icons/effects/blood.dmi', "uniformblood") + blood_icon.Blend(COLOR_BLOOD, ICON_MULTIPLY) + obsessed_icon.Blend(blood_icon, ICON_OVERLAY) var/icon/final_icon = finish_preview_icon(obsessed_icon) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 46995388a78c..b4fb08e2cd75 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -43,6 +43,9 @@ /// How many zones (body parts, not precise) we have disabled so far, for naming purposes var/zones_disabled + /// If supplied, this is what overlay is used when applying blood effects when worn + var/blood_overlay_type = "" + /// A lazily initiated "food" version of the clothing for moths. // This intentionally does not use the edible component, for a few reasons. // 1. Effectively everything that wants something edible, from now and into the future, @@ -591,3 +594,20 @@ BLIND // can't see anything /obj/item/clothing/remove_fantasy_bonuses(bonus) set_armor(get_armor().generate_new_with_modifiers(list(ARMOR_ALL = -bonus))) return ..() + +/obj/item/clothing/proc/appears_bloody() + return GET_ATOM_BLOOD_DNA_LENGTH(src) && can_be_bloody && !(item_flags & NO_BLOOD_ON_ITEM) + +/obj/item/clothing/worn_overlays(mutable_appearance/standing, isinhands, icon_file) + . = ..() + if(isinhands) + return + + if(blood_overlay_type && appears_bloody()) + var/mutable_appearance/blood_overlay + if(clothing_flags & LARGE_WORN_ICON) + blood_overlay = mutable_appearance('icons/effects/64x64.dmi', "[blood_overlay_type]blood_large") + else + blood_overlay = mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood") + blood_overlay.color = get_blood_dna_color() + . += blood_overlay diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index 3f5503ca0eed..ec842866a6e6 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -16,6 +16,7 @@ attack_verb_simple = list("challenge") strip_delay = 20 equip_delay_other = 40 + blood_overlay_type = "glove" // Path variable. If defined, will produced the type through interaction with wirecutters. var/cut_type = null /// Used for handling bloody gloves leaving behind bloodstains on objects. Will be decremented whenever a bloodstain is left behind, and be incremented when the gloves become bloody. @@ -41,13 +42,11 @@ /obj/item/clothing/gloves/worn_overlays(mutable_appearance/standing, isinhands = FALSE) . = ..() - if(!isinhands) + if(isinhands) return if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedgloves") - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - . += mutable_appearance('icons/effects/blood.dmi', "bloodyhands") /obj/item/clothing/gloves/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) ..() diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm index a67d65b5139d..7693776c7abc 100644 --- a/code/modules/clothing/head/_head.dm +++ b/code/modules/clothing/head/_head.dm @@ -6,6 +6,7 @@ righthand_file = 'icons/mob/inhands/clothing/hats_righthand.dmi' body_parts_covered = HEAD slot_flags = ITEM_SLOT_HEAD + blood_overlay_type = "helmetblood" ///Special throw_impact for hats to frisbee hats at people to place them on their heads/attempt to de-hat them. /obj/item/clothing/head/throw_impact(atom/hit_atom, datum/thrownthing/thrownthing) @@ -64,12 +65,6 @@ if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedhelmet") - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - if(clothing_flags & LARGE_WORN_ICON) - . += mutable_appearance('icons/effects/64x64.dmi', "helmetblood_large") - else - . += mutable_appearance('icons/effects/blood.dmi', "helmetblood") - if(!(flags_inv & HIDEHAIR)) if(ismob(loc)) diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index df868a09db20..e760afdc616a 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -7,6 +7,7 @@ slot_flags = ITEM_SLOT_MASK strip_delay = 40 equip_delay_other = 40 + blood_overlay_type = "mask" supports_variations_flags = CLOTHING_SNOUTED_VARIATION var/modifies_speech = FALSE var/mask_adjusted = FALSE @@ -55,8 +56,9 @@ if(body_parts_covered & HEAD) if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedmask") - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - . += mutable_appearance('icons/effects/blood.dmi', "maskblood") + +/obj/item/clothing/mask/appears_bloody() + return ..() && (body_parts_covered & HEAD) /obj/item/clothing/mask/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) ..() diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index d4d5379c6e3c..8431673288a6 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -5,6 +5,7 @@ slot_flags = ITEM_SLOT_NECK strip_delay = 40 equip_delay_other = 40 + blood_overlay_type = "mask" /obj/item/clothing/neck/worn_overlays(mutable_appearance/standing, isinhands = FALSE) . = ..() @@ -14,8 +15,9 @@ if(body_parts_covered & HEAD) if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedmask") - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - . += mutable_appearance('icons/effects/blood.dmi', "maskblood") + +/obj/item/clothing/neck/appears_bloody() + return ..() && (body_parts_covered & HEAD) /obj/item/clothing/neck/bowtie name = "bow tie" diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index c4e8f9133175..68de16d25337 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -13,6 +13,7 @@ armor_type = /datum/armor/clothing_shoes slowdown = SHOES_SLOWDOWN strip_delay = 1 SECONDS + blood_overlay_type = "shoe" var/offset = 0 var/equipped_before_drop = FALSE ///Whether these shoes have laces that can be tied/untied @@ -53,11 +54,6 @@ if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedshoe") - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - if(clothing_flags & LARGE_WORN_ICON) - . += mutable_appearance('icons/effects/64x64.dmi', "shoeblood_large") - else - . += mutable_appearance('icons/effects/blood.dmi', "shoeblood") /obj/item/clothing/shoes/examine(mob/user) . = ..() diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm index 0e9efa5b3fb9..8630f573f31e 100644 --- a/code/modules/clothing/suits/_suits.dm +++ b/code/modules/clothing/suits/_suits.dm @@ -14,7 +14,7 @@ drop_sound = 'sound/items/handling/cloth_drop.ogg' pickup_sound = 'sound/items/handling/cloth_pickup.ogg' slot_flags = ITEM_SLOT_OCLOTHING - var/blood_overlay_type = "suit" + blood_overlay_type = "suit" limb_integrity = 0 // disabled for most exo-suits var/suittoggled = FALSE // sec duster toggling and more supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION @@ -30,8 +30,6 @@ if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damaged[blood_overlay_type]") - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - . += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood") var/mob/living/carbon/human/wearer = loc if(!ishuman(wearer) || !wearer.w_uniform) diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index 9b6b70f9dd7c..2e5cae08d5da 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -11,6 +11,7 @@ drop_sound = 'sound/items/handling/cloth_drop.ogg' pickup_sound = 'sound/items/handling/cloth_pickup.ogg' limb_integrity = 30 + blood_overlay_type = "uniform" /// Has this undersuit been freshly laundered and, as such, imparts a mood bonus for wearing var/freshly_laundered = FALSE @@ -88,8 +89,6 @@ if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damageduniform") - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - . += mutable_appearance('icons/effects/blood.dmi', "uniformblood") if(accessory_overlay) . += accessory_overlay diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm index 47734b398ab8..7da9153548ad 100644 --- a/code/modules/detectivework/scanner.dm +++ b/code/modules/detectivework/scanner.dm @@ -169,7 +169,7 @@ for(var/bloodtype in blood) LAZYADD(det_data[DETSCAN_CATEGORY_BLOOD], \ - "Type: [blood[bloodtype]] DNA (UE): [bloodtype]") + "Type: [GLOB.blood_types[blood[bloodtype]]] DNA (UE): [bloodtype]") // sends it off to be modified by the items SEND_SIGNAL(scanned_atom, COMSIG_DETECTIVE_SCANNED, user, det_data) diff --git a/code/modules/forensics/forensics_helpers.dm b/code/modules/forensics/forensics_helpers.dm index 081d6f25d4f1..6b837b711a43 100644 --- a/code/modules/forensics/forensics_helpers.dm +++ b/code/modules/forensics/forensics_helpers.dm @@ -67,13 +67,13 @@ return FALSE /obj/add_blood_DNA(list/blood_DNA_to_add) - . = ..() if (isnull(blood_DNA_to_add)) - return . + return FALSE if (forensics) forensics.inherit_new(blood_DNA = blood_DNA_to_add) else forensics = new(src, blood_DNA = blood_DNA_to_add) + cached_blood_dna_color = null return TRUE /obj/item/add_blood_DNA(list/blood_DNA_to_add) @@ -82,8 +82,10 @@ return ..() /obj/item/clothing/gloves/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) - transfer_blood = rand(2, 4) - return ..() + . = ..() + if(.) + transfer_blood = rand(2, 4) + return . /turf/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) var/obj/effect/decal/cleanable/blood/splatter/blood_splatter = locate() in src @@ -109,6 +111,7 @@ forensics = new(src) forensics.inherit_new(blood_DNA = blood_DNA_to_add) blood_in_hands = rand(2, 4) + cached_blood_dna_color = null update_worn_gloves() return TRUE diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index be51fe2d9e98..788ce008c295 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -208,6 +208,6 @@ most_plentiful_reagent.Cut() most_plentiful_reagent[reagent] = reagents_add[reagent] - podman.dna.species.exotic_blood = most_plentiful_reagent[1] + //podman.dna.species.exotic_blood = most_plentiful_reagent[1] //Monkestation edit BLOOD_DATUM: This needs to be looked into investigate_log("[key_name(mind)] cloned as a podman via [src] in [parent]", INVESTIGATE_BOTANY) return result diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index e5f2a15b6f81..64232a63aad5 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -342,7 +342,7 @@ var/amount = max(1, round((edible_vol)*(potency/100) * reagent_overflow_mod, 1)) //the plant will always have at least 1u of each of the reagents in its reagent production traits var/list/data if(rid == /datum/reagent/blood) // Hack to make blood in plants always O- - data = list("blood_type" = "O-") + data = list("blood_type" = /datum/blood_type/crew/human/o_minus) if(istype(grown_edible) && (rid == /datum/reagent/consumable/nutriment || rid == /datum/reagent/consumable/nutriment/vitamin)) data = grown_edible.tastes // apple tastes of apple. T.reagents.add_reagent(rid, amount, data) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index d6a9075abf80..3e8254563d6c 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -187,7 +187,7 @@ return FALSE //nonliving mobs don't have hands /mob/living/put_in_hand_check(obj/item/I) - if(istype(I) && (((mobility_flags & MOBILITY_PICKUP) || ((stat >= SOFT_CRIT && (stat != DEAD && stat != UNCONSCIOUS)))) || (I.item_flags & ABSTRACT)) \ + if(istype(I) && (((mobility_flags & MOBILITY_PICKUP) || ((stat >= SOFT_CRIT && (stat != DEAD && stat != UNCONSCIOUS && stat != HARD_CRIT)))) || (I.item_flags & ABSTRACT)) \ && !(SEND_SIGNAL(src, COMSIG_LIVING_TRY_PUT_IN_HAND, I) & COMPONENT_LIVING_CANT_PUT_IN_HAND)) return TRUE return FALSE diff --git a/code/modules/mob/living/basic/bots/cleanbot/cleanbot.dm b/code/modules/mob/living/basic/bots/cleanbot/cleanbot.dm index 5da570369f17..2cdf99b9d2ed 100644 --- a/code/modules/mob/living/basic/bots/cleanbot/cleanbot.dm +++ b/code/modules/mob/living/basic/bots/cleanbot/cleanbot.dm @@ -98,9 +98,7 @@ )) ///blood we can clean var/static/list/cleanable_blood = typecacheof(list( - /obj/effect/decal/cleanable/xenoblood, /obj/effect/decal/cleanable/blood, - /obj/effect/decal/cleanable/trail_holder, )) ///pests we hunt var/static/list/huntable_pests = typecacheof(list( diff --git a/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm b/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm index 8cdd7a6cf53f..804aba100d8b 100644 --- a/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm +++ b/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm @@ -54,3 +54,9 @@ icon = 'icons/obj/medical/organs/organs.dmi' icon_state = "innards" random_icon_states = null + base_name = "" + can_dry = FALSE + +/obj/effect/decal/cleanable/blood/innards/Initialize(mapload, list/datum/disease/diseases) + . = ..() + add_blood_DNA(list("DEMON BLOOD" = /datum/blood_type/animal)) diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 4c9635ef9742..74c65fe4fccb 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -7,46 +7,53 @@ // Takes care blood loss and regeneration /mob/living/carbon/human/handle_blood(seconds_per_tick, times_fired) - if(HAS_TRAIT(src, TRAIT_NOBLOOD) || (HAS_TRAIT(src, TRAIT_FAKEDEATH))) + if(HAS_TRAIT(src, TRAIT_NOBLOOD) || HAS_TRAIT(src, TRAIT_FAKEDEATH)) return - if(bodytemperature < BLOOD_STOP_TEMP || (HAS_TRAIT(src, TRAIT_HUSK))) //cold or husked people do not pump the blood. + if(bodytemperature < BLOOD_STOP_TEMP || HAS_TRAIT(src, TRAIT_HUSK)) //cold or husked people do not pump the blood. return - //Blood regeneration if there is some space - if(blood_volume < BLOOD_VOLUME_NORMAL && !HAS_TRAIT(src, TRAIT_NOHUNGER)) - var/nutrition_ratio = 0 - switch(nutrition) - if(0 to NUTRITION_LEVEL_STARVING) - nutrition_ratio = 0.2 - if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY) - nutrition_ratio = 0.4 - if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED) - nutrition_ratio = 0.6 - if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED) - nutrition_ratio = 0.8 - else - nutrition_ratio = 1 - if(satiety > 80) - nutrition_ratio *= 1.25 - adjust_nutrition(-nutrition_ratio * HUNGER_FACTOR * seconds_per_tick) - blood_volume = min(blood_volume + (BLOOD_REGEN_FACTOR * nutrition_ratio * seconds_per_tick), BLOOD_VOLUME_NORMAL) - - // we call lose_blood() here rather than quirk/process() to make sure that the blood loss happens in sync with life() - if(HAS_TRAIT(src, TRAIT_BLOOD_DEFICIENCY)) - var/datum/quirk/blooddeficiency/blooddeficiency = get_quirk(/datum/quirk/blooddeficiency) - if(!isnull(blooddeficiency)) - blooddeficiency.lose_blood(seconds_per_tick) + var/sigreturn = SEND_SIGNAL(src, COMSIG_HUMAN_ON_HANDLE_BLOOD, seconds_per_tick, times_fired) + if(sigreturn & HANDLE_BLOOD_HANDLED) + return + + if(!(sigreturn & HANDLE_BLOOD_NO_NUTRITION_DRAIN)) + if(blood_volume < BLOOD_VOLUME_NORMAL && !HAS_TRAIT(src, TRAIT_NOHUNGER)) + var/nutrition_ratio = 0 + switch(nutrition) + if(0 to NUTRITION_LEVEL_STARVING) + nutrition_ratio = 0.2 + if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY) + nutrition_ratio = 0.4 + if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED) + nutrition_ratio = 0.6 + if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED) + nutrition_ratio = 0.8 + else + nutrition_ratio = 1 + if(satiety > 80) + nutrition_ratio *= 1.25 + adjust_nutrition(-nutrition_ratio * HUNGER_FACTOR * seconds_per_tick) + blood_volume = min(blood_volume + (BLOOD_REGEN_FACTOR * nutrition_ratio * seconds_per_tick), BLOOD_VOLUME_NORMAL) + + // // we call lose_blood() here rather than quirk/process() to make sure that the blood loss happens in sync with life() + // if(HAS_TRAIT(src, TRAIT_BLOOD_DEFICIENCY)) + // var/datum/quirk/blooddeficiency/blooddeficiency = get_quirk(/datum/quirk/blooddeficiency) + // if(!isnull(blooddeficiency)) + // blooddeficiency.lose_blood(seconds_per_tick) //Effects of bloodloss - var/word = pick("dizzy","woozy","faint") - if(!HAS_TRAIT(src, TRAIT_NO_BLOODLOSS_DAMAGE)) //monkestation addition + if(!(sigreturn & HANDLE_BLOOD_NO_EFFECTS)) + var/word = pick("dizzy","woozy","faint") switch(blood_volume) - if(BLOOD_VOLUME_EXCESS to BLOOD_VOLUME_MAX_LETHAL) + if(BLOOD_VOLUME_MAX_LETHAL to INFINITY) if(SPT_PROB(7.5, seconds_per_tick)) to_chat(src, span_userdanger("Blood starts to tear your skin apart. You're going to burst!")) investigate_log("has been gibbed by having too much blood.", INVESTIGATE_DEATHS) inflate_gib() + if(BLOOD_VOLUME_EXCESS to BLOOD_VOLUME_MAX_LETHAL) + if(SPT_PROB(5, seconds_per_tick)) + to_chat(src, span_warning("You feel your skin swelling.")) if(BLOOD_VOLUME_MAXIMUM to BLOOD_VOLUME_EXCESS) if(SPT_PROB(5, seconds_per_tick)) to_chat(src, span_warning("You feel terribly bloated.")) @@ -93,7 +100,7 @@ //Makes a blood drop, leaking amt units of blood from the mob /mob/living/carbon/proc/bleed(amt, no_visual = FALSE) - if(!blood_volume || (status_flags & GODMODE) || HAS_TRAIT(src, TRAIT_NOBLOOD)) + if((status_flags & GODMODE) || HAS_TRAIT(src, TRAIT_NOBLOOD)) return blood_volume = max(blood_volume - amt, 0) @@ -107,7 +114,7 @@ /// A helper to see how much blood we're losing per tick /mob/living/carbon/proc/get_bleed_rate() - if(!blood_volume || HAS_TRAIT(src, TRAIT_NOBLOOD)) + if(HAS_TRAIT(src, TRAIT_NOBLOOD)) return 0 var/bleed_amt = 0 for(var/X in bodyparts) @@ -116,7 +123,8 @@ return bleed_amt /mob/living/carbon/human/get_bleed_rate() - return ..() * physiology.bleed_mod + . = ..() + . *= physiology.bleed_mod /** * bleed_warn() is used to for carbons with an active client to occasionally receive messages warning them about their bleeding status (if applicable) @@ -126,7 +134,7 @@ * * forced- */ /mob/living/carbon/proc/bleed_warn(bleed_amt = 0, forced = FALSE) - if(!blood_volume || !client) + if(!client || HAS_TRAIT(src, TRAIT_NOBLOOD)) return if(!COOLDOWN_FINISHED(src, bleeding_message_cd) && !forced) return @@ -177,10 +185,6 @@ to_chat(src, span_warning("[bleeding_severity][rate_of_change]")) COOLDOWN_START(src, bleeding_message_cd, next_cooldown) -/mob/living/carbon/human/bleed_warn(bleed_amt = 0, forced = FALSE) - if(!HAS_TRAIT(src, TRAIT_NOBLOOD)) - return ..() - /mob/living/proc/restore_blood() blood_volume = initial(blood_volume) @@ -196,7 +200,8 @@ //Gets blood from mob to a container or other mob, preserving all data in it. /mob/living/proc/transfer_blood_to(atom/movable/AM, amount, forced) - if(!blood_volume || !AM.reagents) + var/datum/blood_type/blood = get_blood_type() + if(isnull(blood) || !AM.reagents) return FALSE if(blood_volume < BLOOD_VOLUME_BAD && !forced) return FALSE @@ -204,35 +209,12 @@ if(blood_volume < amount) amount = blood_volume - var/blood_id = get_blood_id() - if(!blood_id) - return FALSE - blood_volume -= amount - var/list/blood_data = get_blood_data(blood_id) - - if(iscarbon(AM)) - var/mob/living/carbon/C = AM - if(blood_id == C.get_blood_id())//both mobs have the same blood substance - if(blood_id == /datum/reagent/blood) //normal blood - if(blood_data["viruses"]) - for(var/thing in blood_data["viruses"]) - var/datum/disease/advanced/D = thing - if((D.spread_flags & DISEASE_SPREAD_SPECIAL) || (D.spread_flags & DISEASE_SPREAD_NON_CONTAGIOUS)) - continue - C.infect_disease(D, TRUE, "Infected [key_name(C)] (Infected Blood 100% Infection)") - if(!(blood_data["blood_type"] in get_safe_blood(C.dna.blood_type))) - C.reagents.add_reagent(/datum/reagent/toxin, amount * 0.5) - return TRUE - - C.blood_volume = min(C.blood_volume + round(amount, 0.1), BLOOD_VOLUME_MAX_LETHAL) - return TRUE - - AM.reagents.add_reagent(blood_id, amount, blood_data, bodytemperature) + AM.reagents.add_reagent(blood.reagent_type, amount, blood.get_blood_data(src), bodytemperature) return TRUE - +/* /mob/living/proc/get_blood_data(blood_id) return @@ -276,129 +258,46 @@ var/datum/quirk/T = V blood_data["quirks"] += T.type return blood_data +*/ -//get the id of the substance this mob use as blood. -/mob/proc/get_blood_id() - return +/mob/living/proc/get_blood_type() + RETURN_TYPE(/datum/blood_type) + if(HAS_TRAIT(src, TRAIT_NOBLOOD)) + return null + return GLOB.blood_types[/datum/blood_type/animal] -/mob/living/simple_animal/get_blood_id() - if(blood_volume) - return /datum/reagent/blood +/mob/living/silicon/get_blood_type() + return GLOB.blood_types[/datum/blood_type/oil] -/mob/living/carbon/human/get_blood_id() - if(HAS_TRAIT(src, TRAIT_HUSK)) - return - if(check_holidays(APRIL_FOOLS) && is_clown_job(mind?.assigned_role)) - return /datum/reagent/colorful_reagent - if(dna.species.exotic_blood) - return dna.species.exotic_blood - else if(HAS_TRAIT(src, TRAIT_NOBLOOD)) - return - return /datum/reagent/blood - -// This is has more potential uses, and is probably faster than the old proc. -/proc/get_safe_blood(bloodtype) - . = list() - if(!bloodtype) - return +/mob/living/simple_animal/bot/get_blood_type() + return GLOB.blood_types[/datum/blood_type/oil] - var/static/list/bloodtypes_safe = list( - "A-" = list("A-", "O-"), - "A+" = list("A-", "A+", "O-", "O+"), - "B-" = list("B-", "O-"), - "B+" = list("B-", "B+", "O-", "O+"), - "AB-" = list("A-", "B-", "O-", "AB-"), - "AB+" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+"), - "O-" = list("O-"), - "O+" = list("O-", "O+"), - "L" = list("L"), - "U" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+", "L", "U") - ) - - var/safe = bloodtypes_safe[bloodtype] - if(safe) - . = safe +/mob/living/basic/bot/get_blood_type() + return GLOB.blood_types[/datum/blood_type/oil] -//to add a splatter of blood or other mob liquid. -/mob/living/proc/add_splatter_floor(turf/splattered, small_drip) - if((get_blood_id() != /datum/reagent/blood) || HAS_TRAIT(src, TRAIT_NOBLOOD)) - return - if(!splattered) - splattered = get_turf(src) - if(isclosedturf(splattered) || (isgroundlessturf(splattered) && !GET_TURF_BELOW(splattered))) - return +/mob/living/carbon/alien/get_blood_type() + if(HAS_TRAIT(src, TRAIT_HUSK) || HAS_TRAIT(src, TRAIT_NOBLOOD)) + return null + return GLOB.blood_types[/datum/blood_type/xenomorph] - var/datum/reagent/blood_type = get_blood_id() - var/list/temp_blood_DNA - if(small_drip) - if(!QDELETED(splattered.liquids)) - var/list/blood_drop = list(get_blood_id() = 0.1) - splattered.add_liquid_list(blood_drop, FALSE, 300) - return - // Only a certain number of drips (or one large splatter) can be on a given turf. - var/obj/effect/decal/cleanable/blood/drip/drop = locate() in splattered - if(drop) - if(drop.drips < 5) - splattered?.pollute_turf(/datum/pollutant/metallic_scent, 5) - drop.drips++ - drop.add_overlay(pick(drop.random_icon_states)) - drop.transfer_mob_blood_dna(src) - return - else - temp_blood_DNA = GET_ATOM_BLOOD_DNA(drop) //we transfer the dna from the drip to the splatter - qdel(drop)//the drip is replaced by a bigger splatter - else - splattered?.pollute_turf(/datum/pollutant/metallic_scent, 5) - drop = new(splattered, get_static_viruses()) - drop.transfer_mob_blood_dna(src) - return +/mob/living/carbon/human/get_blood_type() + if(HAS_TRAIT(src, TRAIT_HUSK) || isnull(dna) || HAS_TRAIT(src, TRAIT_NOBLOOD)) + return null + if(check_holidays(APRIL_FOOLS) && is_clown_job(mind?.assigned_role)) + return GLOB.blood_types[/datum/blood_type/clown] + if(dna.species.exotic_bloodtype) + return GLOB.blood_types[dna.species.exotic_bloodtype] + return GLOB.blood_types[dna.human_blood_type] +//to add a splatter of blood or other mob liquid. +/mob/living/proc/add_splatter_floor(turf/blood_turf = get_turf(src), small_drip) // Create a bit of metallic pollution, as that's how blood smells - splattered.pollute_turf(/datum/pollutant/metallic_scent, 30) + blood_turf.pollute_turf(/datum/pollutant/metallic_scent, 30) // TODO Move to blood_datum + return get_blood_type()?.make_blood_splatter(src, blood_turf, small_drip) - // Find a blood decal or create a new one. - var/obj/effect/decal/cleanable/blood/B = locate() in splattered - if(!B) - B = new /obj/effect/decal/cleanable/blood/splatter(splattered, get_static_viruses()) - if(QDELETED(B)) //Give it up - return - B.bloodiness = min((B.bloodiness + BLOOD_AMOUNT_PER_DECAL), BLOOD_POOL_MAX) - B.transfer_mob_blood_dna(src) //give blood info to the blood decal. - if(temp_blood_DNA) - B.add_blood_DNA(temp_blood_DNA) - - if(B.count < 10 ) - if(blood_type) - B.color = initial(blood_type.color) - B.count ++ - B.transfer_mob_blood_dna(src) - B.transfer_mob_blood_dna(src) //give blood info to the blood decal. - if(temp_blood_DNA) - B.add_blood_DNA(temp_blood_DNA) - - if(B.count > 9) - qdel(B) - var/list/blood_large = list(get_blood_id() = 20) - splattered.add_liquid_list(blood_large, FALSE, 300) - -/mob/living/carbon/human/add_splatter_floor(turf/T, small_drip) - if(!HAS_TRAIT(src, TRAIT_NOBLOOD)) - ..() - -/mob/living/carbon/alien/add_splatter_floor(turf/T, small_drip) - if(!T) - T = get_turf(src) - var/obj/effect/decal/cleanable/xenoblood/B = locate() in T.contents - if(!B) - B = new(T) - B.add_blood_DNA(list("UNKNOWN DNA" = "X*")) - -/mob/living/silicon/robot/add_splatter_floor(turf/T, small_drip) - if(!T) - T = get_turf(src) - var/obj/effect/decal/cleanable/oil/B = locate() in T.contents - if(!B) - B = new(T) +/mob/living/proc/do_splatter_effect(splat_dir = pick(GLOB.cardinals)) + var/obj/effect/temp_visual/dir_setting/bloodsplatter/splatter = new(get_turf(src), splat_dir, get_blood_type()?.color) + splatter.color = get_blood_type()?.color /** * This proc is a helper for spraying blood for things like slashing/piercing wounds and dismemberment. @@ -425,6 +324,7 @@ return for(var/i in 1 to amount) var/obj/effect/decal/cleanable/blood/particle/droplet = new(loc) + droplet.color = get_blood_type()?.color droplet.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) droplet.pixel_z = rand(min_pixel_z, max_pixel_z) droplet.start_movement(angle + rand(min_deviation, max_deviation)) diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm index 3dc911e206f9..3b4b834e67d9 100644 --- a/code/modules/mob/living/brain/brain.dm +++ b/code/modules/mob/living/brain/brain.dm @@ -10,7 +10,7 @@ /mob/living/brain/Initialize(mapload) . = ..() create_dna(src) - stored_dna.initialize_dna(random_blood_type()) + stored_dna.initialize_dna() if(isturf(loc)) //not spawned in an MMI or brain organ (most likely adminspawned) var/obj/item/organ/internal/brain/OB = new(loc) //we create a new brain organ for it. OB.brainmob = src diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 8ed56358f71e..5a0325146bbd 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1224,12 +1224,16 @@ /// if any of our bodyparts are bleeding /mob/living/carbon/proc/is_bleeding() + if(HAS_TRAIT(src, TRAIT_NOBLOOD)) + return FALSE for(var/obj/item/bodypart/part as anything in bodyparts) if(part.get_modified_bleed_rate()) return TRUE /// get our total bleedrate /mob/living/carbon/proc/get_total_bleed_rate() + if(HAS_TRAIT(src, TRAIT_NOBLOOD)) + return 0 var/total_bleed_rate = 0 for(var/obj/item/bodypart/part as anything in bodyparts) total_bleed_rate += part.get_modified_bleed_rate() diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm index b6e0615ab77f..dd32d275108b 100644 --- a/code/modules/mob/living/carbon/carbon_movement.dm +++ b/code/modules/mob/living/carbon/carbon_movement.dm @@ -17,52 +17,23 @@ adjust_nutrition(-(HUNGER_FACTOR) * 0.1) -/mob/living/carbon/set_usable_legs(new_value) - . = ..() - if(isnull(.)) - return - if(. == 0) - if(usable_legs != 0) //From having no usable legs to having some. - REMOVE_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - else if(usable_legs == 0 && !(movement_type & (FLYING | FLOATING))) //From having usable legs to no longer having them. - ADD_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - if(!usable_hands) - ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - - /mob/living/carbon/set_usable_hands(new_value) . = ..() if(isnull(.)) return if(. == 0) REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, LACKING_MANIPULATION_APPENDAGES_TRAIT) - if(usable_hands != 0) //From having no usable hands to having some. - REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) else if(usable_hands == 0 && default_num_hands > 0) //From having usable hands to no longer having them. ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, LACKING_MANIPULATION_APPENDAGES_TRAIT) - if(!usable_legs && !(movement_type & (FLYING | FLOATING))) - ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) /mob/living/carbon/on_movement_type_flag_enabled(datum/source, flag, old_movement_type) . = ..() if(movement_type & (FLYING | FLOATING) && !(old_movement_type & (FLYING | FLOATING))) - remove_movespeed_modifier(/datum/movespeed_modifier/limbless) - remove_traits(list(TRAIT_FLOORED, TRAIT_IMMOBILIZED), LACKING_LOCOMOTION_APPENDAGES_TRAIT) + update_limbless_locomotion() + update_limbless_movespeed_mod() /mob/living/carbon/on_movement_type_flag_disabled(datum/source, flag, old_movement_type) . = ..() if(old_movement_type & (FLYING | FLOATING) && !(movement_type & (FLYING | FLOATING))) - var/limbless_slowdown = 0 - if(usable_legs < default_num_legs) - limbless_slowdown += (default_num_legs - usable_legs) * 3 - if(!usable_legs) - ADD_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - if(usable_hands < default_num_hands) - limbless_slowdown += (default_num_hands - usable_hands) * 3 - if(!usable_hands) - ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - if(limbless_slowdown) - add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/limbless, multiplicative_slowdown = limbless_slowdown) - else - remove_movespeed_modifier(/datum/movespeed_modifier/limbless) + update_limbless_locomotion() + update_limbless_movespeed_mod() diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index 2485d23eabef..1cc850789f0b 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -299,7 +299,9 @@ if(isnull(damage_overlay) && (iter_part.brutestate || iter_part.burnstate)) damage_overlay = mutable_appearance('icons/mob/effects/dam_mob.dmi', "blank", -DAMAGE_LAYER, appearance_flags = KEEP_TOGETHER) if(iter_part.brutestate) - damage_overlay.add_overlay("[iter_part.dmg_overlay_type]_[iter_part.body_zone]_[iter_part.brutestate]0") //we're adding icon_states of the base image as overlays + var/image/brute_overlay = image('icons/mob/effects/dam_mob.dmi', "[iter_part.dmg_overlay_type]_[iter_part.body_zone]_[iter_part.brutestate]0") + brute_overlay.color = iter_part.damage_color + damage_overlay.add_overlay(brute_overlay) //we're adding icon_states of the base image as overlays //we're adding icon_states of the base image as overlays if(iter_part.burnstate) damage_overlay.add_overlay("[iter_part.dmg_overlay_type]_[iter_part.body_zone]_0[iter_part.burnstate]") diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index a979550ce806..f5b8cd5c7b89 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -65,10 +65,8 @@ GLOBAL_LIST_EMPTY(features_by_species) var/digitigrade_customization = DIGITIGRADE_NEVER ///Does the species use skintones or not? As of now only used by humans. var/use_skintones = FALSE - ///If your race bleeds something other than bog standard blood, change this to reagent id. For example, ethereals bleed liquid electricity. - var/datum/reagent/exotic_blood - ///If your race uses a non standard bloodtype (A+, O-, AB-, etc). For example, lizards have L type blood. - var/exotic_bloodtype = "" + /// If your race uses a non standard bloodtype (typepath) + var/datum/blood_type/exotic_bloodtype ///The rate at which blood is passively drained by having the blood deficiency quirk. Some races such as slimepeople can regen their blood at different rates so this is to account for that var/blood_deficiency_drain_rate = BLOOD_REGEN_FACTOR + BLOOD_DEFICIENCY_MODIFIER // slightly above the regen rate so it slowly drains instead of regenerates. ///What the species drops when gibbed by a gibber machine. @@ -539,14 +537,6 @@ GLOBAL_LIST_EMPTY(features_by_species) INVOKE_ASYNC(src, PROC_REF(worn_items_fit_body_check), C, TRUE) - //Assigns exotic blood type if the species has one - if(exotic_bloodtype && C.dna.blood_type != exotic_bloodtype) - C.dna.blood_type = exotic_bloodtype - //Otherwise, check if the previous species had an exotic bloodtype and we do not have one and assign a random blood type - //(why the fuck is blood type not tied to a fucking DNA block?) - else if(old_species.exotic_bloodtype && !exotic_bloodtype) - C.dna.blood_type = random_blood_type() - if(ishuman(C)) var/mob/living/carbon/human/human = C for(var/obj/item/organ/external/organ_path as anything in external_organs) @@ -598,7 +588,7 @@ GLOBAL_LIST_EMPTY(features_by_species) /datum/species/proc/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) SHOULD_CALL_PARENT(TRUE) if(C.dna.species.exotic_bloodtype) - C.dna.blood_type = random_blood_type() + C.dna.human_blood_type = random_human_blood_type() if(NOMOUTH in species_traits) for(var/obj/item/bodypart/head/head in C.bodyparts) head.mouth = TRUE @@ -629,45 +619,6 @@ GLOBAL_LIST_EMPTY(features_by_species) SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src) -/** - * Proc called when mail goodies need to be updated for this species. - * - * Updates the mail goodies if that is required. e.g. for the blood deficiency quirk, which sends bloodbags to quirk holders, update the sent bloodpack to match the species' exotic blood. - * This is currently only used for the blood deficiency quirk but more can be added as needed. - * Arguments: - * * mob/living/carbon/human/recipient - the mob receiving the mail goodies - */ -/datum/species/proc/update_mail_goodies(mob/living/carbon/human/recipient) - update_quirk_mail_goodies(recipient, recipient.get_quirk(/datum/quirk/blooddeficiency)) - -/** - * Updates the mail goodies of a specific quirk. - * - * Updates the mail goodies belonging to a specific quirk. - * Add implementation as needed for each individual species. The base species proc should give the species the 'default' version of whatever mail goodies are required. - * Arguments: - * * mob/living/carbon/human/recipient - the mob receiving the mail goodies - * * datum/quirk/quirk - the quirk to update the mail goodies of. Use get_quirk(datum/quirk/some_quirk) to get the actual mob's quirk to pass. - * * list/mail_goodies - a list of mail goodies. Generally speaking you should not be using this argument on the initial function call. You should instead add to the species' implementation of this proc. - */ -/datum/species/proc/update_quirk_mail_goodies(mob/living/carbon/human/recipient, datum/quirk/quirk, list/mail_goodies) - if(isnull(quirk)) - return - if(length(mail_goodies)) - quirk.mail_goodies = mail_goodies - return - if(istype(quirk, /datum/quirk/blooddeficiency)) - if(HAS_TRAIT(recipient, TRAIT_NOBLOOD) && isnull(recipient.dna.species.exotic_blood)) // no blood packs should be sent in this case (like if a mob transforms into a plasmaman) - quirk.mail_goodies = list() - return - - - // The default case if no species implementation exists. Set quirk's mail_goodies to initial. - var/datum/quirk/readable_quirk = new quirk.type - quirk.mail_goodies = readable_quirk.mail_goodies - qdel(readable_quirk) // We have to do it this way because initial will not work on lists in this version of DM - return - /** * Handles the body of a human * @@ -1137,18 +1088,26 @@ GLOBAL_LIST_EMPTY(features_by_species) * Return True to not run the normal metabolism effects. * NOTE: If you return TRUE, that reagent will not be removed liike normal! You must handle it manually. */ -/datum/species/proc/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) +/datum/species/proc/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) SHOULD_CALL_PARENT(TRUE) - if(chem.type == exotic_blood) - H.blood_volume = min(H.blood_volume + round(chem.volume, 0.1), BLOOD_VOLUME_MAXIMUM) - H.reagents.del_reagent(chem.type) - return TRUE + // Cringe but blood handles this on its own + // This also has problems of its own but that's better fixed later I think + if(!istype(chem, /datum/reagent/blood)) + var/datum/blood_type/blood = affected.get_blood_type() + if(chem.type == blood?.reagent_type) + affected.blood_volume = min(affected.blood_volume + round(chem.volume, 0.1), BLOOD_VOLUME_MAXIMUM) + affected.reagents.del_reagent(chem.type) + return TRUE + if(chem.type == blood?.restoration_chem && affected.blood_volume < BLOOD_VOLUME_NORMAL) + affected.blood_volume += 0.25 * seconds_per_tick + affected.reagents.remove_reagent(chem.type, chem.metabolization_rate * seconds_per_tick) + return TRUE //This handles dumping unprocessable reagents. var/dump_reagent = TRUE - if((chem.process_flags & SYNTHETIC) && (H.dna.species.reagent_tag & PROCESS_SYNTHETIC)) //SYNTHETIC-oriented reagents require PROCESS_SYNTHETIC + if((chem.process_flags & SYNTHETIC) && (affected.dna.species.reagent_tag & PROCESS_SYNTHETIC)) //SYNTHETIC-oriented reagents require PROCESS_SYNTHETIC dump_reagent = FALSE - if((chem.process_flags & ORGANIC) && (H.dna.species.reagent_tag & PROCESS_ORGANIC)) //ORGANIC-oriented reagents require PROCESS_ORGANIC + if((chem.process_flags & ORGANIC) && (affected.dna.species.reagent_tag & PROCESS_ORGANIC)) //ORGANIC-oriented reagents require PROCESS_ORGANIC dump_reagent = FALSE if(dump_reagent) chem.holder.remove_reagent(chem.type, chem.metabolization_rate) @@ -1156,8 +1115,8 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!chem.overdosed && chem.overdose_threshold && chem.volume >= chem.overdose_threshold) chem.overdosed = TRUE - chem.overdose_start(H) - H.log_message("has started overdosing on [chem.name] at [chem.volume] units.", LOG_GAME) + chem.overdose_start(affected) + affected.log_message("has started overdosing on [chem.name] at [chem.volume] units.", LOG_GAME) /** * Equip the outfit required for life. Replaces items currently worn. @@ -2158,22 +2117,13 @@ GLOBAL_LIST_EMPTY(features_by_species) SPECIES_PERK_DESC = "[plural_form] do not have blood.", )) - // Otherwise, check if their exotic blood is a valid typepath - else if(ispath(exotic_blood)) - to_add += list(list( - SPECIES_PERK_TYPE = SPECIES_NEUTRAL_PERK, - SPECIES_PERK_ICON = "tint", - SPECIES_PERK_NAME = initial(exotic_blood.name), - SPECIES_PERK_DESC = "[name] blood is [initial(exotic_blood.name)], which can make recieving medical treatment harder.", - )) - // Otherwise otherwise, see if they have an exotic bloodtype set else if(exotic_bloodtype) to_add += list(list( SPECIES_PERK_TYPE = SPECIES_NEUTRAL_PERK, SPECIES_PERK_ICON = "tint", - SPECIES_PERK_NAME = "Exotic Blood", - SPECIES_PERK_DESC = "[plural_form] have \"[exotic_bloodtype]\" type blood, which can make recieving medical treatment harder.", + SPECIES_PERK_NAME = initial(exotic_bloodtype.name), + SPECIES_PERK_DESC = "[name] blood is [initial(exotic_bloodtype.name)], which can make recieving medical treatment", )) return to_add diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index fb6762f4863f..3a5fd1e55c6f 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -94,7 +94,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) return /proc/create_consistent_human_dna(mob/living/carbon/human/target) - target.dna.initialize_dna(skip_index = TRUE) + target.dna.initialize_dna(/datum/blood_type/crew/human/o_plus, skip_index = TRUE) target.dna.features["body_markings"] = "None" target.dna.features["ears"] = "None" target.dna.features["ethcolor"] = COLOR_WHITE diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index c67ff29b4e13..6a3a3552851b 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -928,16 +928,6 @@ return FALSE return ..() -/mob/living/carbon/human/is_bleeding() - if(HAS_TRAIT(src, TRAIT_NOBLOOD)) - return FALSE - return ..() - -/mob/living/carbon/human/get_total_bleed_rate() - if(HAS_TRAIT(src, TRAIT_NOBLOOD)) - return FALSE - return ..() - /mob/living/carbon/human/get_exp_list(minutes) . = ..() diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index ec7f482ae1d9..c3ee8c1eda32 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -177,7 +177,8 @@ There are several things that need to be remembered: if(isnull(gloves)) if(blood_in_hands && num_hands > 0) // When byond gives us filters that respect dirs we can just use an alpha mask for this but until then, two icons weeeee - var/mutable_appearance/hands_combined = mutable_appearance(layer = -GLOVES_LAYER, appearance_flags = KEEP_TOGETHER) + var/mutable_appearance/hands_combined = mutable_appearance(layer = -GLOVES_LAYER) + hands_combined.color = get_blood_dna_color() if(has_left_hand(check_disabled = FALSE)) hands_combined.overlays += mutable_appearance('icons/effects/blood.dmi', "bloodyhands_left") if(has_right_hand(check_disabled = FALSE)) diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index fc2719f8f7b5..ad7e3f870f1e 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -16,14 +16,13 @@ inherent_traits = list( TRAIT_CAN_USE_FLIGHT_POTION, TRAIT_TOXINLOVER, - TRAIT_NOBLOOD, ) mutanttongue = /obj/item/organ/internal/tongue/jelly mutantlungs = /obj/item/organ/internal/lungs/slime mutanteyes = /obj/item/organ/internal/eyes/jelly mutantheart = null meat = /obj/item/food/meat/slab/human/mutant/slime - exotic_blood = /datum/reagent/toxin/slimejelly + exotic_bloodtype = /datum/blood_type/slime blood_deficiency_drain_rate = JELLY_REGEN_RATE + BLOOD_DEFICIENCY_MODIFIER var/datum/action/innate/regenerate_limbs/regenerate_limbs liked_food = MEAT | BUGS @@ -55,53 +54,50 @@ if(ishuman(new_jellyperson)) regenerate_limbs = new regenerate_limbs.Grant(new_jellyperson) - update_mail_goodies(new_jellyperson) new_jellyperson.AddElement(/datum/element/soft_landing) + RegisterSignal(new_jellyperson, COMSIG_HUMAN_ON_HANDLE_BLOOD, PROC_REF(slime_blood)) /datum/species/jelly/on_species_loss(mob/living/carbon/former_jellyperson, datum/species/new_species, pref_load) if(regenerate_limbs) regenerate_limbs.Remove(former_jellyperson) former_jellyperson.RemoveElement(/datum/element/soft_landing) + UnregisterSignal(former_jellyperson, COMSIG_HUMAN_ON_HANDLE_BLOOD) return ..() -/datum/species/jelly/update_quirk_mail_goodies(mob/living/carbon/human/recipient, datum/quirk/quirk, list/mail_goodies = list()) - if(istype(quirk, /datum/quirk/blooddeficiency)) - mail_goodies += list( - /obj/item/reagent_containers/blood/toxin - ) - return ..() +/datum/species/jelly/proc/slime_blood(mob/living/carbon/human/slime, seconds_per_tick, times_fired) + SIGNAL_HANDLER -/datum/species/jelly/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) - if(H.stat == DEAD) //can't farm slime jelly from a dead slime/jelly person indefinitely - return + if(slime.stat == DEAD) + return NONE - if(!H.blood_volume) - H.blood_volume += JELLY_REGEN_RATE_EMPTY * seconds_per_tick - H.adjustBruteLoss(2.5 * seconds_per_tick) - to_chat(H, span_danger("You feel empty!")) + . = HANDLE_BLOOD_NO_NUTRITION_DRAIN|HANDLE_BLOOD_NO_EFFECTS - if(H.blood_volume < BLOOD_VOLUME_NORMAL) - if(H.nutrition >= NUTRITION_LEVEL_STARVING) - H.blood_volume += JELLY_REGEN_RATE * seconds_per_tick - if(H.blood_volume <= BLOOD_VOLUME_LOSE_NUTRITION) // don't lose nutrition if we are above a certain threshold, otherwise slimes on IV drips will still lose nutrition - H.adjust_nutrition(-1.25 * seconds_per_tick) + if(slime.blood_volume <= 0) + slime.blood_volume += JELLY_REGEN_RATE_EMPTY * seconds_per_tick + slime.adjustBruteLoss(2.5 * seconds_per_tick) + to_chat(slime, span_danger("You feel empty!")) - // we call lose_blood() here rather than quirk/process() to make sure that the blood loss happens in sync with life() - if(HAS_TRAIT(H, TRAIT_BLOOD_DEFICIENCY)) - var/datum/quirk/blooddeficiency/blooddeficiency = H.get_quirk(/datum/quirk/blooddeficiency) + if(slime.blood_volume < BLOOD_VOLUME_NORMAL) + if(slime.nutrition >= NUTRITION_LEVEL_STARVING) + slime.blood_volume += JELLY_REGEN_RATE * seconds_per_tick + if(slime.blood_volume <= BLOOD_VOLUME_LOSE_NUTRITION) // don't lose nutrition if we are above a certain threshold, otherwise slimes on IV drips will still lose nutrition + slime.adjust_nutrition(-1.25 * seconds_per_tick) + + if(HAS_TRAIT(slime, TRAIT_BLOOD_DEFICIENCY)) + var/datum/quirk/blooddeficiency/blooddeficiency = slime.get_quirk(/datum/quirk/blooddeficiency) if(!isnull(blooddeficiency)) blooddeficiency.lose_blood(seconds_per_tick) - if(H.blood_volume < BLOOD_VOLUME_OKAY) + if(slime.blood_volume < BLOOD_VOLUME_OKAY) if(SPT_PROB(2.5, seconds_per_tick)) - to_chat(H, span_danger("You feel drained!")) + to_chat(slime, span_danger("You feel drained!")) - if(H.blood_volume < BLOOD_VOLUME_BAD) - Cannibalize_Body(H) + if(slime.blood_volume < BLOOD_VOLUME_BAD) + Cannibalize_Body(slime) - if(regenerate_limbs) - regenerate_limbs.build_all_button_icons() + regenerate_limbs?.build_all_button_icons(UPDATE_BUTTON_STATUS) + return . /datum/species/jelly/proc/Cannibalize_Body(mob/living/carbon/human/H) var/list/limbs_to_consume = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) - H.get_missing_limbs() @@ -126,7 +122,7 @@ SPECIES_PERK_TYPE = SPECIES_NEUTRAL_PERK, SPECIES_PERK_ICON = "tint", SPECIES_PERK_NAME = "Jelly Blood", - SPECIES_PERK_DESC = "[plural_form] don't have blood, but instead have toxic [initial(exotic_blood.name)]! \ + SPECIES_PERK_DESC = "[plural_form] don't have blood, but instead have toxic-to-humans Jelly! \ Jelly is extremely important, as losing it will cause you to lose limbs. Having low jelly will make medical treatment very difficult.", )) diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index a122cbb6f292..0423d940adcb 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -29,7 +29,7 @@ species_cookie = /obj/item/food/meat/slab meat = /obj/item/food/meat/slab/human/mutant/lizard skinned_type = /obj/item/stack/sheet/animalhide/lizard - exotic_bloodtype = "L" + exotic_bloodtype = /datum/blood_type/crew/lizard disliked_food = GRAIN | DAIRY | CLOTH | GROSS liked_food = GORE | MEAT | SEAFOOD | NUTS | BUGS inert_mutation = /datum/mutation/human/firebreath @@ -54,18 +54,6 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/lizard, ) -/datum/species/lizard/on_species_gain(mob/living/carbon/new_lizard, datum/species/old_species, pref_load) - . = ..() - if(ishuman(new_lizard)) - update_mail_goodies(new_lizard) - -/datum/species/lizard/update_quirk_mail_goodies(mob/living/carbon/human/recipient, datum/quirk/quirk, list/mail_goodies = list()) - if(istype(quirk, /datum/quirk/blooddeficiency)) - mail_goodies += list( - /obj/item/reagent_containers/blood/lizard - ) - return ..() - /// Lizards are cold blooded and do not stabilize body temperature naturally /datum/species/lizard/body_temperature_core(mob/living/carbon/human/humi, seconds_per_tick, times_fired) return diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index c451d48110b0..31f2c81c6ab4 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -19,7 +19,7 @@ heatmod = 1.5 payday_modifier = 0.75 meat = /obj/item/food/meat/slab/human/mutant/plant - exotic_blood = /datum/reagent/water + exotic_bloodtype = /datum/blood_type/water disliked_food = MEAT | DAIRY | SEAFOOD | BUGS liked_food = VEGETABLES | FRUIT | GRAIN changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT @@ -36,18 +36,6 @@ ass_image = 'icons/ass/asspodperson.png' -/datum/species/pod/on_species_gain(mob/living/carbon/new_podperson, datum/species/old_species, pref_load) - . = ..() - if(ishuman(new_podperson)) - update_mail_goodies(new_podperson) - -/datum/species/pod/update_quirk_mail_goodies(mob/living/carbon/human/recipient, datum/quirk/quirk, list/mail_goodies = list()) - if(istype(quirk, /datum/quirk/blooddeficiency)) - mail_goodies += list( - /obj/item/reagent_containers/blood/podperson - ) - return ..() - /datum/species/pod/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) if(H.stat == DEAD) return diff --git a/code/modules/mob/living/carbon/human/species_types/snail.dm b/code/modules/mob/living/carbon/human/species_types/snail.dm index 6dc24addcf86..0c66cd7bbe6e 100644 --- a/code/modules/mob/living/carbon/human/species_types/snail.dm +++ b/code/modules/mob/living/carbon/human/species_types/snail.dm @@ -18,7 +18,7 @@ mutanteyes = /obj/item/organ/internal/eyes/snail mutanttongue = /obj/item/organ/internal/tongue/snail - exotic_blood = /datum/reagent/lube + exotic_bloodtype = /datum/blood_type/snail bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/snail, @@ -44,8 +44,6 @@ if(new_snailperson.dropItemToGround(bag)) //returns TRUE even if its null new_snailperson.equip_to_slot_or_del(new /obj/item/storage/backpack/snail(new_snailperson), ITEM_SLOT_BACK) new_snailperson.AddElement(/datum/element/snailcrawl) - if(ishuman(new_snailperson)) - update_mail_goodies(new_snailperson) /datum/species/snail/on_species_loss(mob/living/carbon/former_snailperson, datum/species/new_species, pref_load) . = ..() @@ -56,13 +54,6 @@ former_snailperson.temporarilyRemoveItemFromInventory(bag, TRUE) qdel(bag) -/datum/species/snail/update_quirk_mail_goodies(mob/living/carbon/human/recipient, datum/quirk/quirk, list/mail_goodies = list()) - if(istype(quirk, /datum/quirk/blooddeficiency)) - mail_goodies += list( - /obj/item/reagent_containers/blood/snail - ) - return ..() - /obj/item/storage/backpack/snail name = "snail shell" desc = "Worn by snails as armor and storage compartment." diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index 72f06a970033..a7711da1a8cd 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -20,7 +20,7 @@ inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutant_bodyparts = list("wings" = "None") changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN - exotic_bloodtype = "U" + exotic_bloodtype = /datum/blood_type/universal blood_deficiency_drain_rate = BLOOD_DEFICIENCY_MODIFIER // vampires already passively lose blood, so this just makes them lose it slightly more quickly when they have blood deficiency. use_skintones = TRUE mutantheart = /obj/item/organ/internal/heart/vampire @@ -165,8 +165,8 @@ if(victim.stat == DEAD) to_chat(H, span_warning("You need a living victim!")) return - if(!victim.blood_volume || (victim.dna && (HAS_TRAIT(victim, TRAIT_NOBLOOD) || victim.dna.species.exotic_blood))) - to_chat(H, span_warning("[victim] doesn't have blood!")) + if(!istype(victim.get_blood_type(), /datum/blood_type/crew/human)) + to_chat(H, span_warning("[victim] doesn't have valid blood!")) return COOLDOWN_START(V, drain_cooldown, 3 SECONDS) if(victim.can_block_magic(MAGIC_RESISTANCE_HOLY, charge_cost = 0)) @@ -186,7 +186,7 @@ playsound(H, 'sound/items/drink.ogg', 30, TRUE, -2) victim.blood_volume = clamp(victim.blood_volume - drained_blood, 0, BLOOD_VOLUME_MAXIMUM) H.blood_volume = clamp(H.blood_volume + drained_blood, 0, BLOOD_VOLUME_MAXIMUM) - if(!victim.blood_volume) + if(victim.blood_volume <= 0) to_chat(H, span_notice("You finish off [victim]'s blood supply.")) /obj/item/organ/internal/heart/vampire diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 93f4391e3b34..446f666cf0bf 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -559,7 +559,7 @@ dna.unique_enzymes = dna.previous["UE"] dna.previous.Remove("UE") if(dna.previous["blood_type"]) - dna.blood_type = dna.previous["blood_type"] + dna.human_blood_type = blood_name_to_blood_type(dna.previous["blood_type"]) dna.previous.Remove("blood_type") dna.temporary_mutations.Remove(mut) continue diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 9793371343fa..5453ee265380 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -70,7 +70,7 @@ update_damage_overlays() damage_dealt = actual_hit.get_damage() - delta // Unfortunately bodypart receive_damage doesn't return damage dealt so we do it manually else - damage_dealt = adjustBruteLoss(damage_amount, forced = forced) + damage_dealt = -1 * adjustBruteLoss(damage_amount, forced = forced) if(BURN) if(isbodypart(def_zone)) var/obj/item/bodypart/actual_hit = def_zone @@ -86,19 +86,19 @@ damage_source = attacking_item, )) update_damage_overlays() - damage_dealt = delta - actual_hit.get_damage() // See above + damage_dealt = actual_hit.get_damage() - delta // See above else - damage_dealt = adjustFireLoss(damage_amount, forced = forced) + damage_dealt = -1 * adjustFireLoss(damage_amount, forced = forced) if(TOX) - damage_dealt = adjustToxLoss(damage_amount, forced = forced) + damage_dealt = -1 * adjustToxLoss(damage_amount, forced = forced) if(OXY) - damage_dealt = adjustOxyLoss(damage_amount, forced = forced) + damage_dealt = -1 * adjustOxyLoss(damage_amount, forced = forced) if(CLONE) - damage_dealt = adjustCloneLoss(damage_amount, forced = forced) + damage_dealt = -1 * adjustCloneLoss(damage_amount, forced = forced) if(STAMINA) - damage_dealt = stamina.adjust(-damage) + damage_dealt = -1 * stamina.adjust(-damage) if(BRAIN) - damage_dealt = adjustOrganLoss(ORGAN_SLOT_BRAIN, damage_amount) + damage_dealt = -1 * adjustOrganLoss(ORGAN_SLOT_BRAIN, damage_amount) SEND_SIGNAL(src, COMSIG_MOB_AFTER_APPLY_DAMAGE, damage_dealt, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) return damage_dealt diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index d487b8191266..72e23dd32788 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -17,6 +17,8 @@ update_fov() gravity_setup() voice_type = pick(voice_type2sound) //monkestation edit + if(!blood_volume) + ADD_TRAIT(src, TRAIT_NOBLOOD, INNATE_TRAIT) /mob/living/prepare_huds() ..() @@ -524,7 +526,7 @@ * * IGNORE_GRAB - mob that is agressively grabbed is not considered incapacitated **/ /mob/living/incapacitated(flags) - if((flags & IGNORE_CRIT) && ((stat >= SOFT_CRIT && (stat != DEAD && stat != UNCONSCIOUS)) && !src.pulledby)) + if((flags & IGNORE_CRIT) && ((stat >= SOFT_CRIT && (stat != DEAD && stat != UNCONSCIOUS && stat != HARD_CRIT)) && !src.pulledby)) return FALSE if(HAS_TRAIT(src, TRAIT_INCAPACITATED)) @@ -1019,10 +1021,10 @@ return /mob/living/proc/makeTrail(turf/target_turf, turf/start, direction) - if(!has_gravity() || !isturf(start) || !blood_volume) + if(!has_gravity() || !isturf(start) || HAS_TRAIT(src, TRAIT_NOBLOOD)) return - var/blood_exists = locate(/obj/effect/decal/cleanable/trail_holder) in start + var/blood_exists = locate(/obj/effect/decal/cleanable/blood/trail_holder) in start var/trail_type = getTrail() if(!trail_type) @@ -1044,18 +1046,18 @@ if((newdir in GLOB.cardinals) && (prob(50))) newdir = turn(get_dir(target_turf, start), 180) if(!blood_exists) - new /obj/effect/decal/cleanable/trail_holder(start, get_static_viruses()) + new /obj/effect/decal/cleanable/blood/trail_holder(start, get_static_viruses()) - for(var/obj/effect/decal/cleanable/trail_holder/TH in start) + for(var/obj/effect/decal/cleanable/blood/trail_holder/TH in start) if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled) TH.existing_dirs += newdir TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir)) TH.transfer_mob_blood_dna(src) -/mob/living/carbon/human/makeTrail(turf/T) - if(HAS_TRAIT(src, TRAIT_NOBLOOD) || !is_bleeding() || HAS_TRAIT(src, TRAIT_NOBLOOD)) +/mob/living/carbon/human/makeTrail(turf/target_turf, turf/start, direction) + if(!is_bleeding()) return - ..() + return ..() ///Returns how much blood we're losing from being dragged a tile, from [/mob/living/proc/makeTrail] /mob/living/proc/bleedDragAmount() @@ -2255,27 +2257,38 @@ GLOBAL_LIST_EMPTY(fire_appearances) stack_trace("[src] had set_usable_legs() called on them with a negative value!") new_value = 0 - . = usable_legs + var/old_value = usable_legs usable_legs = new_value - if(new_value > .) // Gained leg usage. + update_limbless_locomotion() + update_limbless_movespeed_mod() + + return old_value + +/// Updates whether the mob is floored or immobilized based on how many limbs they have or are missing. +/mob/living/proc/update_limbless_locomotion() + if(usable_legs > 0 || (movement_type & (FLYING|FLOATING)) || COUNT_TRAIT_SOURCES(src, TRAIT_NO_LEG_AID) >= 2) REMOVE_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - else if(!(movement_type & (FLYING | FLOATING))) //Lost leg usage, not flying. - if(!usable_legs) - ADD_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - if(!usable_hands) - ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) + return + ADD_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) + if(usable_hands == 0) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) +/// Updates the mob's movespeed based on how many limbs they have or are missing. +/mob/living/proc/update_limbless_movespeed_mod() if(usable_legs < default_num_legs) var/limbless_slowdown = (default_num_legs - usable_legs) * 3 if(!usable_legs && usable_hands < default_num_hands) limbless_slowdown += (default_num_hands - usable_hands) * 3 + var/list/slowdown_mods = list() + SEND_SIGNAL(src, COMSIG_LIVING_LIMBLESS_MOVESPEED_UPDATE, slowdown_mods) + for(var/num in slowdown_mods) + limbless_slowdown *= num add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/limbless, multiplicative_slowdown = limbless_slowdown) else remove_movespeed_modifier(/datum/movespeed_modifier/limbless) - ///Proc to modify the value of num_hands and hook behavior associated to this event. /mob/living/proc/set_num_hands(new_value) if(num_hands == new_value) @@ -2288,14 +2301,18 @@ GLOBAL_LIST_EMPTY(fire_appearances) /mob/living/proc/set_usable_hands(new_value) if(usable_hands == new_value) return - . = usable_hands + if(new_value < 0) // Sanity check + stack_trace("[src] had set_usable_hands() called on them with a negative value!") + new_value = 0 + + var/old_value = usable_hands usable_hands = new_value - if(new_value > .) // Gained hand usage. - REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - else if(!(movement_type & (FLYING | FLOATING)) && !usable_hands && !usable_legs) //Lost a hand, not flying, no hands left, no legs. - ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) + if(usable_legs < default_num_legs) + update_limbless_locomotion() + update_limbless_movespeed_mod() + return old_value /// Whether or not this mob will escape from storages while being picked up/held. /mob/living/proc/will_escape_storage() diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index ec90fa9fa7bb..7a6750309572 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -356,6 +356,12 @@ Difficulty: Hard /obj/effect/decal/cleanable/blood/bubblegum bloodiness = 0 + base_name = "" + can_dry = FALSE + +/obj/effect/decal/cleanable/blood/bubblegum/Initialize(mapload, list/datum/disease/diseases) + . = ..() + add_blood_DNA(list("DEMON BLOOD" = /datum/blood_type/animal)) /obj/effect/decal/cleanable/blood/bubblegum/can_bloodcrawl_in() return TRUE @@ -365,6 +371,12 @@ Difficulty: Hard desc = "Thick, splattered blood." random_icon_states = list("gib3", "gib5", "gib6") bloodiness = 20 + base_name = "" + can_dry = FALSE + +/obj/effect/decal/cleanable/blood/gibs/bubblegum/Initialize(mapload, list/datum/disease/diseases) + . = ..() + add_blood_DNA(list("DEMON BLOOD" = /datum/blood_type/animal)) /obj/effect/decal/cleanable/blood/gibs/bubblegum/can_bloodcrawl_in() return TRUE diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 28166514b241..77a695647a86 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -311,10 +311,7 @@ var/splatter_dir = dir if(starting) splatter_dir = get_dir(starting, target_turf) - if(isalien(living_target)) - new /obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter(target_turf, splatter_dir) - else - new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_turf, splatter_dir) + living_target.do_splatter_effect(splatter_dir) if(prob(damage)) living_target.blood_particles(amount = rand(1, 1 + round(damage/20, 1)), angle = src.Angle) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index f7dd0808abba..3127f3db80e2 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -1551,7 +1551,7 @@ /datum/reagent/medicine/coagulant/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() - if(!affected_mob.blood_volume || !affected_mob.all_wounds) + if(HAS_TRAIT(affected_mob, TRAIT_NOBLOOD) || !LAZYLEN(affected_mob.all_wounds)) return var/datum/wound/bloodiest_wound @@ -1572,7 +1572,7 @@ /datum/reagent/medicine/coagulant/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired) . = ..() - if(!affected_mob.blood_volume) + if(!HAS_TRAIT(affected_mob, TRAIT_NOBLOOD)) return if(SPT_PROB(7.5, seconds_per_tick)) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 257a184a2278..6c09b960c9da 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1,21 +1,24 @@ /datum/reagent/blood data = list( - "viruses"=null, - "blood_DNA"=null, - "blood_type"=null, - "resistances"=null, - "trace_chem"=null, - "mind"=null, - "ckey"=null, - "gender"=null, - "real_name"=null, - "cloneable"=null, - "factions"=null, - "quirks"=null, + // Actually Relevant + "viruses" = null, // Refernces to virus datums in this blood + "blood_DNA" = null, // DNA of the guy who the blood came from + "blood_type" = null, // /datum/blood_type of the blood + "resistances" = null, // Viruses the blood is vaccinated against "immunity" = null, + // Unused? (but cool) + "trace_chem" = null, // Param list of all chems in the blood at the time the sample was taken (type to volume) + // Used for podperson shit + "mind" = null, // Ref to the mind of the guy who the blood came from + "ckey" = null, // Ckey of the guy who the blood came from + "gender" = null, // Gender of the guy when the blood was taken + "real_name" = null, // Real name of the guy when the blood was taken + "cloneable" = null, // Tracks if the guy who the blood came from suicided or not + "factions" = null, // Factions the guy who the blood came from was in + "quirks" = null, // Quirk typepaths of the guy who the blood came from had ) name = "Blood" - color = "#9e0101" // rgb: 200, 0, 0 + color = COLOR_BLOOD metabolization_rate = 12.5 * REAGENTS_METABOLISM //fast rate so it disappears fast. taste_description = "iron" taste_mult = 1.3 @@ -24,6 +27,7 @@ default_container = /obj/item/reagent_containers/blood opacity = 230 turf_exposure = TRUE + chemical_flags = REAGENT_IGNORE_STASIS|REAGENT_DEAD_PROCESS /datum/glass_style/shot_glass/blood required_drink_type = /datum/reagent/blood @@ -37,33 +41,30 @@ /datum/reagent/blood/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=0) . = ..() - if(data && data["viruses"]) - for(var/thing in data["viruses"]) - var/datum/disease/strain = thing - - if(istype(strain, /datum/disease/advanced)) - var/datum/disease/advanced/advanced = strain - if(methods & (INJECT|INGEST|PATCH)) - exposed_mob.infect_disease(advanced, TRUE, "(Contact, splashed with infected blood)") - if((methods & (TOUCH | VAPOR)) && (advanced.spread_flags & DISEASE_SPREAD_BLOOD)) - if(exposed_mob.check_bodypart_bleeding(BODY_ZONE_EVERYTHING)) - exposed_mob.infect_disease(advanced, notes="(Blood, splashed with infected blood)") - - if(iscarbon(exposed_mob)) - var/mob/living/carbon/exposed_carbon = exposed_mob - if(exposed_carbon.get_blood_id() == type && ((methods & INJECT) || ((methods & INGEST) && exposed_carbon.dna && exposed_carbon.dna.species && (DRINKSBLOOD in exposed_carbon.dna.species.species_traits)))) - if(!data || !(data["blood_type"] in get_safe_blood(exposed_carbon.dna.blood_type))) - exposed_carbon.reagents.add_reagent(/datum/reagent/toxin, reac_volume * 0.5) - else - exposed_carbon.blood_volume = min(exposed_carbon.blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM) + for(var/datum/disease/strain as anything in data?["viruses"]) + if(istype(strain, /datum/disease/advanced)) + var/datum/disease/advanced/advanced = strain + if(methods & (INJECT|INGEST|PATCH)) + exposed_mob.infect_disease(advanced, TRUE, "(Contact, splashed with infected blood)") + if((methods & (TOUCH | VAPOR)) && (advanced.spread_flags & DISEASE_SPREAD_BLOOD)) + if(exposed_mob.check_bodypart_bleeding(BODY_ZONE_EVERYTHING)) + exposed_mob.infect_disease(advanced, notes="(Blood, splashed with infected blood)") + + var/datum/blood_type/blood = exposed_mob.get_blood_type() + if(blood?.reagent_type == type && ((methods & INJECT) || ((methods & INGEST)))) + if(data["blood_type"] in blood.compatible_types) + exposed_mob.blood_volume = min(exposed_mob.blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM) + else + exposed_mob.reagents.add_reagent(/datum/reagent/toxin, reac_volume * 0.5) - exposed_carbon.reagents.remove_reagent(type, reac_volume) // Because we don't want blood to just lie around in the patient's blood, makes no sense. + exposed_mob.reagents.remove_reagent(type, reac_volume) // Because we don't want blood to just lie around in the patient's blood, makes no sense. /datum/reagent/blood/on_new(list/data) . = ..() if(istype(data)) SetViruses(src, data) + color = GLOB.blood_types[data["blood_type"]]?.color || COLOR_BLOOD /datum/reagent/blood/on_merge(list/mix_data) if(data && mix_data) @@ -273,7 +274,7 @@ /datum/reagent/water/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() - if(affected_mob.blood_volume) + if(!HAS_TRAIT(affected_mob, TRAIT_NOBLOOD)) affected_mob.blood_volume += 0.1 * REM * seconds_per_tick // water is good for you! /datum/reagent/water/salt diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm index 1274a3bb91e1..067c9cf1e464 100644 --- a/code/modules/reagents/reagent_containers/blood_pack.dm +++ b/code/modules/reagents/reagent_containers/blood_pack.dm @@ -5,85 +5,84 @@ icon_state = "bloodpack" volume = 200 var/blood_type = null - var/unique_blood = null var/labelled = FALSE fill_icon_thresholds = list(10, 20, 30, 40, 50, 60, 70, 80, 90, 100) /obj/item/reagent_containers/blood/Initialize(mapload, vol) . = ..() - if(blood_type != null) - reagents.add_reagent(unique_blood ? unique_blood : /datum/reagent/blood, 200, list("viruses"=null,"blood_DNA"=null,"blood_type"=blood_type,"resistances"=null,"trace_chem"=null)) + if(!isnull(blood_type)) + var/datum/blood_type/blood = GLOB.blood_types[blood_type] + reagents.add_reagent(blood.reagent_type, 200, list("viruses" = null,"blood_DNA" = null,"blood_type" = blood_type, "resistances" = null, "trace_chem" = null)) update_appearance() /// Handles updating the container when the reagents change. /obj/item/reagent_containers/blood/on_reagent_change(datum/reagents/holder, ...) - var/datum/reagent/blood/new_reagent = holder.has_reagent(/datum/reagent/blood) - if(new_reagent && new_reagent.data && new_reagent.data["blood_type"]) - blood_type = new_reagent.data["blood_type"] - else if(holder.has_reagent(/datum/reagent/consumable/liquidelectricity)) - blood_type = "LE" - else if(holder.has_reagent(/datum/reagent/lube)) - blood_type = "S" - else if(holder.has_reagent(/datum/reagent/water)) - blood_type = "H2O" - else if(holder.has_reagent(/datum/reagent/toxin/slimejelly)) - blood_type = "TOX" - else if(holder.has_reagent(/datum/reagent/toxin/slimeooze)) - blood_type = "OOZE" + blood_type = null + + var/datum/reagent/master_reagent = holder.get_master_reagent() + if(istype(master_reagent, /datum/reagent/blood)) + blood_type = master_reagent.data?["blood_type"] + else - blood_type = null + for(var/blood_type in GLOB.blood_types) + var/datum/blood_type/blood = GLOB.blood_types[blood_type] + if(blood.reagent_type == master_reagent.type) + blood_type = blood_type + break + return ..() /obj/item/reagent_containers/blood/update_name(updates) . = ..() if(labelled) return - name = "blood pack[blood_type ? " - [blood_type]" : null]" + var/datum/blood_type/blood = GLOB.blood_types[blood_type] + name = "blood pack[blood ? " - [blood.name]" : null]" /obj/item/reagent_containers/blood/random icon_state = "random_bloodpack" /obj/item/reagent_containers/blood/random/Initialize(mapload, vol) icon_state = "bloodpack" - blood_type = pick("A+", "A-", "B+", "B-", "O+", "O-", "L") + blood_type = pick(subtypesof(/datum/blood_type/crew) - /datum/blood_type/crew/human) return ..() /obj/item/reagent_containers/blood/a_plus - blood_type = "A+" + blood_type = /datum/blood_type/crew/human/a_plus /obj/item/reagent_containers/blood/a_minus - blood_type = "A-" + blood_type = /datum/blood_type/crew/human/a_minus /obj/item/reagent_containers/blood/b_plus - blood_type = "B+" + blood_type = /datum/blood_type/crew/human/b_plus /obj/item/reagent_containers/blood/b_minus - blood_type = "B-" + blood_type = /datum/blood_type/crew/human/b_minus /obj/item/reagent_containers/blood/o_plus - blood_type = "O+" + blood_type = /datum/blood_type/crew/human/o_plus /obj/item/reagent_containers/blood/o_minus - blood_type = "O-" + blood_type = /datum/blood_type/crew/human/o_minus /obj/item/reagent_containers/blood/lizard - blood_type = "L" + blood_type = /datum/blood_type/crew/lizard /obj/item/reagent_containers/blood/ethereal - blood_type = "LE" - unique_blood = /datum/reagent/consumable/liquidelectricity + blood_type = /datum/blood_type/crew/ethereal + +/obj/item/reagent_containers/blood/skrell + blood_type = /datum/blood_type/crew/skrell /obj/item/reagent_containers/blood/snail - blood_type = "S" - unique_blood = /datum/reagent/lube + blood_type = /datum/blood_type/snail /obj/item/reagent_containers/blood/snail/examine() . = ..() . += span_notice("It's a bit slimy... The label indicates that this is meant for snails.") /obj/item/reagent_containers/blood/podperson - blood_type = "H2O" - unique_blood = /datum/reagent/water + blood_type = /datum/blood_type/water /obj/item/reagent_containers/blood/podperson/examine() . = ..() @@ -91,15 +90,14 @@ // for slimepeople /obj/item/reagent_containers/blood/toxin - blood_type = "TOX" - unique_blood = /datum/reagent/toxin/slimejelly + blood_type = /datum/blood_type/slime /obj/item/reagent_containers/blood/toxin/examine() . = ..() . += span_notice("There is a toxin warning on the label. This is for slimepeople.") /obj/item/reagent_containers/blood/universal - blood_type = "U" + blood_type = /datum/blood_type/universal /obj/item/reagent_containers/blood/attackby(obj/item/tool, mob/user, params) if (istype(tool, /obj/item/pen) || istype(tool, /obj/item/toy/crayon)) diff --git a/code/modules/spells/spell_types/jaunt/bloodcrawl.dm b/code/modules/spells/spell_types/jaunt/bloodcrawl.dm index 836bfd98dca4..0afb21953152 100644 --- a/code/modules/spells/spell_types/jaunt/bloodcrawl.dm +++ b/code/modules/spells/spell_types/jaunt/bloodcrawl.dm @@ -144,7 +144,7 @@ // Make the mob have the color of the blood pool it came out of var/obj/effect/decal/cleanable/came_from = locate() in landing_turf - var/new_color = came_from?.get_blood_color() + var/new_color = came_from?.get_blood_dna_color() if(!new_color) return diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 5178752d63af..764ac9e05367 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -105,6 +105,8 @@ var/should_draw_greyscale = TRUE ///An "override" color that can be applied to ANY limb, greyscale or not. var/variable_color = "" + /// Color of the damage overlay + var/damage_color = COLOR_BLOOD var/px_x = 0 var/px_y = 0 @@ -893,6 +895,8 @@ else draw_color = null + damage_color = owner?.get_blood_type()?.color || COLOR_BLOOD + if(!is_creating || !owner) return @@ -951,7 +955,9 @@ image_dir = SOUTH if(dmg_overlay_type) if(brutestate) - . += image('icons/mob/effects/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_[brutestate]0", -DAMAGE_LAYER, image_dir) + var/image/bruteimage = image('icons/mob/effects/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_[brutestate]0", -DAMAGE_LAYER, image_dir) + bruteimage.color = damage_color + . += bruteimage if(burnstate) . += image('icons/mob/effects/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_0[burnstate]", -DAMAGE_LAYER, image_dir) diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 6991a2bdd46a..d732da816693 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -253,6 +253,14 @@ arm_owner.dropItemToGround(arm_owner.gloves, TRUE, violent = violent) arm_owner.update_worn_gloves() //to remove the bloody hands overlay +/obj/item/bodypart/arm/try_attach_limb(mob/living/carbon/new_arm_owner, special = FALSE) + . = ..() + + if(!.) + return + + new_arm_owner.update_worn_gloves() + /obj/item/bodypart/leg/drop_limb(special, dismembered, violent) if(owner && !special) if(owner.legcuffed) diff --git a/code/modules/unit_tests/bloody_footprints.dm b/code/modules/unit_tests/bloody_footprints.dm index 76b86590861e..2a786414fa20 100644 --- a/code/modules/unit_tests/bloody_footprints.dm +++ b/code/modules/unit_tests/bloody_footprints.dm @@ -21,9 +21,8 @@ blood_master.forceMove(run_loc_floor_bottom_left) var/datum/component/bloodysoles/soles = holds_blood.GetComponent(/datum/component/bloodysoles) - var/blood_type = pool.blood_state - TEST_ASSERT(soles.bloody_shoes[blood_type], "Shoes didn't become stained after stepping in a pool of [blood_type]") + TEST_ASSERT(soles.total_bloodiness, "Shoes didn't become stained after stepping in a pool of blood") //The bloody soles component handles the order of stepping on blood/stepping on a bloody tile in a constranating way //Which means it needs to check and see if any time has passed between steps, so it can be sure the player is stepping onto a new tile (that should become bloody) @@ -39,10 +38,9 @@ var/footprint_total = 0 for(var/obj/effect/decal/cleanable/blood/footprints/print_set in move_to) - if(print_set.blood_state == blood_type) - footprint_total += 1 + footprint_total += 1 - TEST_ASSERT(footprint_total, "The floor didn't get covered in [blood_type] after being walked over") + TEST_ASSERT(footprint_total, "The floor didn't get covered in blood after being walked over") soles.last_pickup -= 1 @@ -54,8 +52,7 @@ footprint_total = 0 for(var/obj/effect/decal/cleanable/blood/footprints/print_set in move_to) - if(print_set.blood_state == blood_type) - footprint_total += 1 + footprint_total += 1 TEST_ASSERT(footprint_total, "The floor somehow lost its footprints after being walked over") TEST_ASSERT_EQUAL(footprint_total, 1, "The floor had more than one set of footprints in it, something is fucked") diff --git a/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm b/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm index cadccb6fe86c..0e147ec37665 100644 --- a/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm @@ -130,11 +130,7 @@ target.apply_damage(10, BRUTE, BODY_ZONE_CHEST, target.run_armor_check(target_part, MELEE)) //blood splatters - var/splatter_dir = get_dir(chassis, target) - if(isalien(target)) - new /obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter(target.drop_location(), splatter_dir, COLOR_DARK_PURPLE) - else - new /obj/effect/temp_visual/dir_setting/bloodsplatter(target.drop_location(), splatter_dir, COLOR_DARK_RED) + target.do_splatter_effect(get_dir(chassis, target)) //organs go everywhere if(target_part && prob(10 * drill_level)) diff --git a/icons/effects/blood.dmi b/icons/effects/blood.dmi index 9bf25b8de2bbf9546e8feaa08eb4c4fe488a487d..3d8e46c3837fda9f224f0b573df0f1332cfc372a 100644 GIT binary patch literal 175305 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⪚`7_t^H@{DXhic6#-PO5! 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

*=R7n`fC9wh0@-sZ@` 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 a35FfoUeYMn+U$eCug6Lnk4hiB2>n0J4Wx|# diff --git a/icons/effects/footprints.dmi b/icons/effects/footprints.dmi index a00c6a0f780dbb69645897e1687dee69be1e2106..8cefa901bc23c5d7daf273117ce3b7cf162c95a2 100644 GIT binary patch literal 4537 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 Uup({v&;S4c07*qoM6N<$f-kzDegFUf diff --git a/icons/mob/effects/dam_mob.dmi b/icons/mob/effects/dam_mob.dmi index 6390a1b34d645bd75ca6e89c1189056de263e546..51883685fb4cb111909d02171c21a5f5f463b62e 100644 GIT binary patch literal 16007 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 literal 16182 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 ^Y5;0lWc$DZY2?631hy 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 will allow you to walk despite having two missing or disabled legs.") + examine_list += span_info("Resisting will brace you, allowing you to stand on one support, \ + despite having two missing or disabled legs. Moving will cancel this effect.") + +/datum/component/limbless_aid/proc/on_equip(obj/item/source, mob/living/user, slot) + SIGNAL_HANDLER + + if(!(slot & required_slot)) + return + + add_support(user) + +/datum/component/limbless_aid/proc/add_support(mob/living/user) + ADD_TRAIT(user, TRAIT_NO_LEG_AID, "[REF(src)]_aid") + RegisterSignal(user, COMSIG_LIVING_LIMBLESS_MOVESPEED_UPDATE, PROC_REF(modify_movespeed), override = TRUE) + RegisterSignal(user, COMSIG_CARBON_LIMPING, PROC_REF(limp_check), override = TRUE) + RegisterSignal(user, COMSIG_LIVING_RESIST, PROC_REF(self_brace), override = TRUE) + user.update_limbless_locomotion() + user.update_limbless_movespeed_mod() + +/datum/component/limbless_aid/proc/on_drop(obj/item/source, mob/living/user) + SIGNAL_HANDLER + + lose_support(user) + +/datum/component/limbless_aid/proc/lose_support(mob/living/user) + REMOVE_TRAIT(user, TRAIT_NO_LEG_AID, "[REF(src)]_aid") + un_self_brace(user) + UnregisterSignal(user, COMSIG_LIVING_LIMBLESS_MOVESPEED_UPDATE) + UnregisterSignal(user, COMSIG_CARBON_LIMPING) + UnregisterSignal(user, COMSIG_LIVING_RESIST) + user.update_limbless_locomotion() + user.update_limbless_movespeed_mod() + +/datum/component/limbless_aid/proc/modify_movespeed(mob/living/source, list/modifiers) + SIGNAL_HANDLER + + var/obj/item/bodypart/leg = get_braced_leg(source) + if(isnull(leg) || leg.bodypart_disabled) + modifiers += movespeed_mod + +/datum/component/limbless_aid/proc/limp_check(mob/living/source, obj/item/bodypart/next_leg) + SIGNAL_HANDLER + + var/obj/item/bodypart/leg = get_braced_leg(source) + if(isnull(leg) || leg == next_leg) + return COMPONENT_CANCEL_LIMP + +#define IS_RIGHT_ARM(index) (index % 2 == 0) + +/// Checks what side the item is equipped on +/datum/component/limbless_aid/proc/get_braced_leg(mob/living/who) + if(required_slot & ITEM_SLOT_HANDS) + // note this is backwards intentionally: + // right arm braces the left leg, and left arm braces right leg + var/side = IS_RIGHT_ARM(who.get_held_index_of_item(parent)) ? BODY_ZONE_L_LEG : BODY_ZONE_R_LEG + return who.get_bodypart(side) + + return null // unimplemented + +#undef IS_RIGHT_ARM + +/datum/component/limbless_aid/proc/self_brace(mob/living/source) + SIGNAL_HANDLER + + INVOKE_ASYNC(src, PROC_REF(self_brace_async), source) + +/datum/component/limbless_aid/proc/un_self_brace(mob/living/source) + REMOVE_TRAIT(source, TRAIT_NO_LEG_AID, "[REF(src)]_brace") + UnregisterSignal(source, COMSIG_MOVABLE_MOVED) + +/datum/component/limbless_aid/proc/self_brace_async(mob/living/source) + if((required_slot & ITEM_SLOT_HANDS) && parent != source.get_active_held_item()) + return + if(HAS_TRAIT_FROM(source, TRAIT_NO_LEG_AID, "[REF(src)]_brace")) + return + if(DOING_INTERACTION_WITH_TARGET(source, source)) + return + // lying down is a lot harder to get up from + if(!do_after(source, (source.body_position == LYING_DOWN ? 2.4 SECONDS : 0.8 SECONDS), source)) + return + + source.balloon_alert(source, "braced") + ADD_TRAIT(source, TRAIT_NO_LEG_AID, "[REF(src)]_brace") + RegisterSignal(source, COMSIG_MOVABLE_MOVED, PROC_REF(brace_moved)) + source.update_limbless_locomotion() + +/datum/component/limbless_aid/proc/brace_moved(mob/living/source, atom/old_loc) + SIGNAL_HANDLER + + if(source.loc == old_loc) + return + + un_self_brace(source) + source.update_limbless_locomotion() diff --git a/monkestation/code/modules/blood_datum/elements/easy_ignite.dm b/monkestation/code/modules/blood_datum/elements/easy_ignite.dm new file mode 100644 index 000000000000..15416cf05e68 --- /dev/null +++ b/monkestation/code/modules/blood_datum/elements/easy_ignite.dm @@ -0,0 +1,97 @@ +/datum/element/easy_ignite + element_flags = ELEMENT_DETACH_ON_HOST_DESTROY|ELEMENT_BESPOKE // because turfs + argument_hash_start_idx = 2 + /// Temp required for ignition + var/required_temp = 450 + +/datum/element/easy_ignite/Attach(datum/target, required_temp = 450) + . = ..() + if(!isatom(target) || isarea(target)) + return ELEMENT_INCOMPATIBLE + + src.required_temp = required_temp + RegisterSignal(target, COMSIG_ATOM_ATTACKBY, PROC_REF(attackby_react)) + RegisterSignal(target, COMSIG_ATOM_FIRE_ACT, PROC_REF(flame_react)) + RegisterSignal(target, COMSIG_ATOM_BULLET_ACT, PROC_REF(projectile_react)) + RegisterSignal(target, COMSIG_ATOM_TOOL_ACT(TOOL_WELDER), PROC_REF(welder_react)) + if(isturf(target)) + RegisterSignal(target, COMSIG_TURF_EXPOSE, PROC_REF(hotspots_react)) + +/datum/element/easy_ignite/Detach(datum/source, ...) + . = ..() + UnregisterSignal(source, COMSIG_ATOM_ATTACKBY) + UnregisterSignal(source, COMSIG_ATOM_FIRE_ACT) + UnregisterSignal(source, COMSIG_ATOM_BULLET_ACT) + UnregisterSignal(source, COMSIG_ATOM_TOOL_ACT(TOOL_WELDER)) + if(isturf(source)) + UnregisterSignal(source, COMSIG_TURF_EXPOSE) + +/datum/element/easy_ignite/proc/ignite(atom/igniting, mob/user) + var/delete_after = TRUE + + igniting.visible_message(span_warning("[igniting] ignite[igniting.p_s()]!"), span_warning("You ignite into flames!")) + new /obj/effect/hotspot(isturf(igniting) ? igniting : igniting.loc) + + if(isturf(igniting)) + var/turf/parent_turf = igniting + parent_turf.ScrapeAway(1, CHANGETURF_INHERIT_AIR) + delete_after = FALSE + + // Logging-related + var/log_message = "ignited [igniting]" + if(user) + user.log_message(log_message, LOG_ATTACK, log_globally = FALSE)//only individual log + + else + log_message = "[key_name(user)] " + log_message + " by fire" + log_attack(log_message) + + if(delete_after && !QDELETED(igniting)) + qdel(igniting) + +/datum/element/easy_ignite/proc/flame_react(obj/item/source, exposed_temperature, exposed_volume) + SIGNAL_HANDLER + + if(exposed_temperature > required_temp) + ignite(source) + +/datum/element/easy_ignite/proc/hotspots_react(obj/item/source, air, exposed_temperature) + SIGNAL_HANDLER + + if(exposed_temperature > required_temp) + ignite(source) + +/datum/element/easy_ignite/proc/attackby_react(obj/item/source, mob/user, obj/item/tool, modifiers) + SIGNAL_HANDLER + + if(tool.get_temperature() && item_ignition(source, tool, user)) + ignite(source, user) + return FALSE + +/datum/element/easy_ignite/proc/projectile_react(obj/item/source, obj/projectile/shot) + SIGNAL_HANDLER + + if(shot.damage_type == BURN && shot.damage > 0) + ignite(source, shot.firer) + +/datum/element/easy_ignite/proc/welder_react(obj/item/source, mob/user, obj/item/tool) + SIGNAL_HANDLER + + if(tool.get_temperature() && item_ignition(source, tool, user)) + ignite(source, user) + return FALSE + +/datum/element/easy_ignite/proc/item_ignition(obj/item/source, obj/item/tool, mob/user) + if(tool.get_temperature() >= required_temp) + source.visible_message( + span_warning("[user] ignites [source] with [tool]!"), + span_warning("You ignite [source] with [tool]!"), + ) + ignite(source, user) + return TRUE + + source.visible_message( + span_warning("[user] tries to ignite [source] with [tool]!"), + span_warning("You try to ignite [source] with [tool], but it's not hot enough!"), + ) + return FALSE diff --git a/monkestation/code/modules/blood_datum/forensics_helpers.dm b/monkestation/code/modules/blood_datum/forensics_helpers.dm new file mode 100644 index 000000000000..6d6c5353cf22 --- /dev/null +++ b/monkestation/code/modules/blood_datum/forensics_helpers.dm @@ -0,0 +1,36 @@ +/atom + /// Cached mixed color of all blood DNA on us + VAR_PROTECTED/cached_blood_dna_color + +/atom/proc/get_blood_dna_color() + if(cached_blood_dna_color) + return cached_blood_dna_color + + var/list/colors = list() + var/list/all_dna = GET_ATOM_BLOOD_DNA(src) + for(var/dna_sample in all_dna) + var/datum/blood_type/blood = GLOB.blood_types[all_dna[dna_sample]] + colors += blood.color + + var/final_color = pop(colors) + for(var/color in colors) + final_color = BlendRGB(final_color, color, 0.5) + cached_blood_dna_color = final_color + return final_color + +/obj/effect/decal/cleanable/blood/drip/get_blood_dna_color() + var/list/all_dna = GET_ATOM_BLOOD_DNA(src) + return GLOB.blood_types[all_dna[all_dna[1]]]?.color + +/obj/effect/decal/cleanable/blood/add_blood_DNA(list/blood_DNA_to_add) + var/first_dna = GET_ATOM_BLOOD_DNA_LENGTH(src) + if(!..()) + return FALSE + + color = get_blood_dna_color() + // Imperfect, ends up with some blood types being double-set-up, but harmless (for now) + for(var/new_blood in blood_DNA_to_add) + var/datum/blood_type/blood = GLOB.blood_types[blood_DNA_to_add[new_blood]] + blood.set_up_blood(src, first_dna == 0) + update_appearance() + return TRUE diff --git a/monkestation/code/modules/blood_datum/icons/melee_lefthand.dmi b/monkestation/code/modules/blood_datum/icons/melee_lefthand.dmi new file mode 100644 index 0000000000000000000000000000000000000000..62675c5968d2f382e4d4b690d73bf071732ba3ff GIT binary patch literal 531 zcmV+u0_^>XP)E%^Wd0USw0K~z|U?Uk_+f-n?@0Toml&Itl8;OPR4 z;0TOB1>V_MQaXYo*jc!o7MzLi{f0!*!@GQqAG!DE5edQb9F76tza31>>SUQ&!WYs7 zE+H&8t&G-Yfi!C+NX-HXR1E9|gc!dtx&1fc2uSpTmd`9hj(Of{sKr6^CP}#9yBO zY#V^*sgAg@>~Y!Kwy?e@c(!O}>~1jAUiJ}~YcKyJV7+Ma$6LP*)9#Yzy>NZ8S#K0W VA!s$L&e#9|002ovPDHLkV1jfh;JW|- literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/blood_datum/icons/melee_righthand.dmi b/monkestation/code/modules/blood_datum/icons/melee_righthand.dmi new file mode 100644 index 0000000000000000000000000000000000000000..47b673a6f322d566b1dfead6aef201cfcb3211c8 GIT binary patch literal 536 zcmV+z0_XjSP)V=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRL zOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5DY>Y$Bsn8KH#J3xi!&v&s2HS^i!-e#F*g;& zHpEa`o}Z6Xt+Ilvp9|O>03x?3Zesf_`2YX`9!W$&R9J=WmN5>3KoCU{6S1IBPq1(T z5-zYu;0RRKR%l^CNy!m73Z0FIveCe7{_HXd0ZjH+&dh%^vtbp3z{_hz?VOI&v_@xP z2jVxjND!ddV4sulr!*h>=VXU4fk2WDpD)G^@C@Um(J@4Rk~JJ~BbufbjRDPC#6W?8 zg0*ZA&=}CHMPWd(mJ9u0~hBR0{n;g_1Ycer#av(QrUiL7=+x zE0vRz-x2PtA|>W{)#&0yAPMz<>R4|E3oXcs+%Ha3k)GAQ<7E*jmFmfX*8J2OvIlPeb=}sGSa~_)S8~ aP5A%?S1*3+yS_C50000fFDZ*Bkpc$`yKaB_9`^iy#0_2eo`Eh^5;&r`5fFwryM z;w;ZhDainGjE%TBGg33tGfE(w;*!LYR3K9+xu~=xIU_zdHARVwGbOXA7$|7S#hF%= zn41b=qbn`X&&R1&S;5uM1?&z0A)_g1Z$G130002uNklKU69h9>AFl_$M-(Vu|_SCQ6|JMur<~a@C zrl)|K+HGz41URm`Fwlb4kOiFy3mSICiKe3q#!~Stm`a7?4G|?m5Ka&W0?3t;LbQA- z^5viyx2VD$r4R}XW*MXci|w3%_TFaz9$;l=_$;9txe@F}?EDO7$BHPG0Kzz90L}H0 zcE5XN0F?vp>O}#lvjT4lM=8voD$b`l?fcDVpptB8R|EB(He!Q`mBFSeBGVDyc@Gk- VE#3QsF=hY&002ovPDHLkV1nb5%l!ZV literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/blood_datum/icons/status_display.dmi b/monkestation/code/modules/blood_datum/icons/status_display.dmi new file mode 100644 index 0000000000000000000000000000000000000000..4c245723bfa33ed8c28b34696c0584cb17c604df GIT binary patch literal 1541 zcmV+g2KxDlP)V=-0C=3Ol)-MpAPk1j;VGi_8ci!n+U~H+)N1NseTB$roPtVV z0jHGJ*0a z{55bMJO+1WMz5sC8Ou6pUC1n0)>|0x>VI*UT#^#w0J>3)!XuHje`3K7gqbTDm_X~8Zi5T`&T1*#}eO@WpaXhnh66zCxdS#+-vs19jV@c!u+aVv}JyIj*N zhz$i#X)bSCc#4g8neMEfb`_MG9%7Taj;Zk<8vnDgRv8m{3KN-CG5KspebVNvlSN^r zTai0})>21Kkyo_){l(Zk-|jb;U-JXS6KJ8^9>n4R00cEjL_t(|obBC>R^nC^22d2O zR%yp-XtaI*_pCn%t1b7O43}^d*n2H?)_hk8Um}7W<6;3&<0{a4+s?t&^|I(%!_}^? zLmIC2UhvJ$a{2yt^Ks06yt}#C9KbgUu6MOu-WDyF3LfH@f{*O#?)LV+;P&=T!2|qS zwD>Ie{{CUF_l6Zb#AOux`1ly5izuyh83nIat00Z*ucYAC1wZ_@*Tbv|ZfF7pM+eui zb*oi;h-MdD`T3#t1rNSy<%LHnc%+6EycqWo&I;e zi_fpyeJ=>MFP=}{EQsk4QH|7P*d3USu7~2 z{oC(d_P5`=?A)1McJ9nBJ9lQ6ojbG3&Yjt1=gyq&XxbDGt_j~kKx^h(0RR9100000 zfJ5XnN2ggaQ&XvLyaDQDz;*P${hrJhr}M-4d~iPh8_f6C-u~^nByaX5G?nA`Z0|w< z000000000008T5LZ}qqBHw%*7cq;$^000000000$y_Y2avzYXKAAaWR>+8^s===D> zCZ0$0t*hs_;kUm^4fmV3lGn{!?ql2guMfrieL*(Ak2dT|MT%@^ATlNIjG?N-|q@nQr-i@^70Iq^n3nwB1h?WSi!aV zfE`f!64)NVhuue1I8MK(DY$kA^nGw2HI`!*99-bk^YJKnWJfBv`n!1ReDcPAoZ9qp zaE)Uf!Hd?<#Hw=u000000DyUG{i^Gk=dI@k&OL8F`En`wRA;;9o;TlsbI-T)t)=_v zO&(uCnkO4L^Slr8p?fIa0iPeDeBL`?cN_NRy9$a|5MRKceAFFKxr35|stVlQ?n1$f z6XnTo@g%<>^!7J@oH*$B*plCa>*LGc-B0e#`vKcmH6J|j zXF{{j0RR910002yt@W#}Xa1`0H0C0z<`%-ahvu43{-l#L$>dEkxzpOQX44Lx-AZS_ zw#i|6b4MsJE2z4_n(4^qcK2W90>eD}`~mrxYou are too far away to read the display.") + +/obj/machinery/computer/vitals_reader/Initialize(mapload, obj/item/circuitboard/C) + . = ..() + register_context() + +/obj/machinery/computer/vitals_reader/Destroy() + unset_patient() + return ..() + +/obj/machinery/computer/vitals_reader/add_context(atom/source, list/context, obj/item/held_item, mob/user) + if(!isnull(held_item)) + return NONE + + context[SCREENTIP_CONTEXT_LMB] = "Toggle readout" + if(isAI(user)) + context[SCREENTIP_CONTEXT_SHIFT_LMB] = "Examine vitals" + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/computer/vitals_reader/AIShiftClick(mob/user) + // Lets AIs perform healthscans on people indirectly (they can't examine) + if(is_operational && !isnull(patient)) + healthscan(user, patient, advanced = advanced) + +#define LOWER_BAR_OFFSET -3 + +/// Returns overlays to be used when active but without a patient detected +/obj/machinery/computer/vitals_reader/proc/get_scanning_overlays() + return list( + construct_overlay("unknown"), + construct_overlay("scanning"), + ) + +/** + * Returns all overlays to be shown when a simple / basic animal patient is detected + * + * * hp_color - color being used for general, overrall health + */ +/obj/machinery/computer/vitals_reader/proc/get_simple_mob_overlays(hp_color) + return list( + construct_overlay("mob", hp_color), + construct_overlay("blood", COLOR_GRAY), + construct_overlay("bar9", COLOR_GRAY), + construct_overlay("bar9", COLOR_GRAY, LOWER_BAR_OFFSET), + ) + +/** + * Returns all overlays to be shown when a humanoid patient is detected + * + * * hp_color - color being used for general, overrall health + */ +/obj/machinery/computer/vitals_reader/proc/get_humanoid_overlays(hp_color) + var/list/returned_overlays = list() + + for(var/body_zone in BODY_ZONES_ALL) + var/obj/item/bodypart/real_part = patient.get_bodypart(body_zone) + var/bodypart_color = isnull(real_part) ? COLOR_GRAY : percent_to_color((real_part.brute_dam + real_part.burn_dam) / real_part.max_damage) + returned_overlays += construct_overlay("human_[body_zone]", bodypart_color) + + if(HAS_TRAIT(patient, TRAIT_NOBLOOD)) + returned_overlays += construct_overlay("blood", COLOR_GRAY) + else + var/blood_color = "#a51919" + switch((patient.blood_volume - BLOOD_VOLUME_SURVIVE) / (BLOOD_VOLUME_NORMAL - BLOOD_VOLUME_SURVIVE)) + if(-INFINITY to 0.2) + blood_color = "#a1a1a1" + if(0.2 to 0.4) + blood_color = "#a18282" + if(0.4 to 0.6) + blood_color = "#a16363" + if(0.6 to 0.8) + blood_color = "#a14444" + if(0.8 to INFINITY) + blood_color = "#a51919" + + returned_overlays += construct_overlay("blood", blood_color) + + if(HAS_TRAIT(patient, TRAIT_NOBREATH)) + returned_overlays += construct_overlay("bar9", COLOR_GRAY) + else + var/oxy_percent = patient.getOxyLoss() / patient.maxHealth + returned_overlays += construct_overlay(percent_to_bar(oxy_percent), "#2A72AA") + + if(HAS_TRAIT(patient, TRAIT_TOXIMMUNE)) + returned_overlays += construct_overlay("bar9", COLOR_GRAY, LOWER_BAR_OFFSET) + else + var/tox_percent = patient.getToxLoss() / patient.maxHealth + returned_overlays += construct_overlay(percent_to_bar(tox_percent), "#5d9c11", LOWER_BAR_OFFSET) + + return returned_overlays + +/obj/machinery/computer/vitals_reader/update_overlays() + . = ..() + if(!active) + return + + if(isnull(patient)) + . += get_scanning_overlays() + + else + var/ekg_icon_state = "ekg" + var/resp_icon_state = (patient.losebreath || HAS_TRAIT(patient, TRAIT_NOBREATH)) ? "resp_flat" : "resp" + if(!patient.appears_alive()) + ekg_icon_state = "ekg_flat" + resp_icon_state = "resp_flat" + else if(ishuman(patient)) + var/mob/living/carbon/human/human_patient = patient + switch(human_patient.get_pretend_heart_rate()) + if(0) + ekg_icon_state = "ekg_flat" + resp_icon_state = "resp_flat" + if(100 to INFINITY) + ekg_icon_state = "ekg_fast" + + var/hp_color = percent_to_color((patient.maxHealth - patient.health) / patient.maxHealth) + . += construct_overlay(ekg_icon_state, hp_color) + . += construct_overlay(resp_icon_state, "#00f7ff") + + if(ishuman(patient)) + . += get_humanoid_overlays(hp_color) + else + . += get_simple_mob_overlays(hp_color) + + . += emissive_appearance(icon, "outline", src, alpha = src.alpha) + +/// Converts a percentage to a color +/obj/machinery/computer/vitals_reader/proc/percent_to_color(percent) + if(percent == 0) + return "#2A72AA" + + switch(percent) + if(0 to 0.125) + return "#A6BD00" + if(0.125 to 0.25) + return "#BDA600" + if(0.25 to 0.375) + return "#BD7E00" + if(0.375 to 0.5) + return "#BD4200" + + return "#BD0600" + +/// Converts a percentage to a bar icon state +/obj/machinery/computer/vitals_reader/proc/percent_to_bar(percent) + if(percent >= 1) + return "bar9" + if(percent <= 0) + return "bar1" + + switch(percent) + if(0 to 0.125) + return "bar1" + if(0.125 to 0.25) + return "bar2" + if(0.25 to 0.375) + return "bar3" + if(0.375 to 0.5) + return "bar4" + if(0.5 to 0.625) + return "bar5" + if(0.625 to 0.75) + return "bar6" + if(0.75 to 0.875) + return "bar7" + if(0.875 to 1) + return "bar8" + + return "bar9" // ?? + +/** + * Helper to construct an overlay for the vitals display + * + * * state_to_use - icon state to use, required + * * color_to_use - color to use, optional + * * y_offset - offset to apply to the y position of the overlay, defaults to 0 + */ +/obj/machinery/computer/vitals_reader/proc/construct_overlay(state_to_use, color_to_use, y_offset = 0) + var/mutable_appearance/overlay = mutable_appearance(icon, state_to_use, alpha = src.alpha) + overlay.appearance_flags |= RESET_COLOR + overlay.color = color_to_use + overlay.pixel_z += 32 + overlay.pixel_y += -32 + y_offset + return overlay + +#undef LOWER_BAR_OFFSET + +/obj/machinery/computer/vitals_reader/interact(mob/user, special_state) + . = ..() + if(.) + return . + if(!is_operational) + return . + + toggle_active() + balloon_alert(user, "readout [active ? "" : "de"]activated") + playsound(src, 'sound/machines/click.ogg', 50) + return TRUE + +/obj/machinery/computer/vitals_reader/on_set_is_operational(old_value) + if(!is_operational && active) + toggle_active() + +/// Toggles whether the display is active or not +/obj/machinery/computer/vitals_reader/proc/toggle_active() + if(active) + active = FALSE + update_use_power(NO_POWER_USE) + unset_patient() + else + active = TRUE + update_use_power(IDLE_POWER_USE) + find_active_patient() + update_appearance(UPDATE_OVERLAYS) + +/** + * Recursively checks all nearby machines to find a patient to track. + * + * This can (and should be) signal driven in the future, but machines don't have a set_occupant proc yet, + * so this will do for the moment. + * + * * scan_attempts - number of times this has been called, used to prevent infinite loops + */ +/obj/machinery/computer/vitals_reader/proc/find_active_patient(scan_attempts = 0) + if(!active || !isnull(patient) || QDELETED(src)) + return + + for(var/obj/machinery/nearby_thing in view(3, src)) + if(!is_type_in_typecache(nearby_thing, connectable_typecache)) + continue + + var/mob/living/patient = nearby_thing.occupant + if(istype(nearby_thing, /obj/machinery/computer/operating)) + var/obj/machinery/computer/operating/op = nearby_thing + patient = op.table?.patient + + if(!istype(patient) || !(patient.mob_biotypes & MOB_ORGANIC)) + continue + + set_patient(patient) + return + + if(scan_attempts > 12) + toggle_active() + return + + addtimer(CALLBACK(src, PROC_REF(find_active_patient), scan_attempts + 1), 5 SECONDS) + +/// Sets the passed mob as the active patient +/// If there is already a patient, it will be unset first. +/obj/machinery/computer/vitals_reader/proc/set_patient(mob/living/new_patient) + if(!isnull(patient)) + unset_patient() + + patient = new_patient + RegisterSignals(patient, list( + COMSIG_QDELETING, + COMSIG_MOVABLE_MOVED + ), PROC_REF(unset_patient)) + RegisterSignals(patient, list( + COMSIG_CARBON_POST_REMOVE_LIMB, + COMSIG_CARBON_POST_ATTACH_LIMB, + COMSIG_LIVING_HEALTH_UPDATE, + ), PROC_REF(update_overlay_on_signal)) + update_appearance(UPDATE_OVERLAYS) + +/// Unset the current patient. +/obj/machinery/computer/vitals_reader/proc/unset_patient(...) + SIGNAL_HANDLER + if(isnull(patient)) + return + + UnregisterSignal(patient, list( + COMSIG_QDELETING, + COMSIG_MOVABLE_MOVED, + COMSIG_CARBON_POST_REMOVE_LIMB, + COMSIG_CARBON_POST_ATTACH_LIMB, + COMSIG_LIVING_HEALTH_UPDATE, + )) + + patient = null + if(QDELING(src)) + return + + update_appearance(UPDATE_OVERLAYS) + if(active) + find_active_patient() + +/// Signal proc to update the display when a signal is received. +/obj/machinery/computer/vitals_reader/proc/update_overlay_on_signal(...) + SIGNAL_HANDLER + update_appearance(UPDATE_OVERLAYS) diff --git a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm index 8744c87400c1..b58d3a2ab523 100644 --- a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm @@ -5,7 +5,6 @@ random_icon_states = list("drip1","drip2","drip3","drip4","drip5") plane = GAME_PLANE layer = BELOW_MOB_LAYER - should_dry = FALSE bloodiness = BLOOD_AMOUNT_PER_DECAL * 0.2 mergeable_decal = FALSE /// Splatter type we create when we bounce on the floor @@ -45,14 +44,16 @@ return var/obj/effect/decal/cleanable/splatter if(!ispath(splatter_type_floor, /obj/effect/decal/cleanable/blood/splatter/stacking)) - splatter = new splatter_type_floor(loc) + splatter = new splatter_type_floor(loc, blood_color = color) + splatter.color = color if(messy_splatter) splatter.pixel_x = src.pixel_x splatter.pixel_y = src.pixel_y else var/obj/effect/decal/cleanable/blood/splatter/stacking/stacker = locate(splatter_type_floor) in loc if(!stacker) - stacker = new splatter_type_floor(loc) + stacker = new splatter_type_floor(loc, blood_color = color) + stacker.color = color if(messy_splatter && length(stacker.splat_overlays)) var/mutable_appearance/existing_appearance = stacker.splat_overlays[1] existing_appearance.pixel_x = src.pixel_x @@ -60,7 +61,8 @@ stacker.bloodiness = src.bloodiness stacker.update_appearance(UPDATE_ICON) else - var/obj/effect/decal/cleanable/blood/splatter/stacking/other_splatter = new splatter_type_floor() + var/obj/effect/decal/cleanable/blood/splatter/stacking/other_splatter = new splatter_type_floor(blood_color = color) + other_splatter.color = color if(messy_splatter && length(other_splatter.splat_overlays)) var/mutable_appearance/existing_appearance = other_splatter.splat_overlays[1] existing_appearance.pixel_x = src.pixel_x @@ -83,6 +85,7 @@ var/dir_to_wall = get_dir(src, bumped_atom) final_splatter.pixel_x = (dir_to_wall & EAST ? world.icon_size : (dir_to_wall & WEST ? -world.icon_size : 0)) final_splatter.pixel_y = (dir_to_wall & NORTH ? world.icon_size : (dir_to_wall & SOUTH ? -world.icon_size : 0)) + final_splatter.color = color var/list/blood_dna = GET_ATOM_BLOOD_DNA(src) if(blood_dna) final_splatter.add_blood_DNA(blood_dna) @@ -96,6 +99,7 @@ return var/obj/effect/decal/cleanable/blood/splatter/over_window/final_splatter = new splatter_type_wall() final_splatter.forceMove(the_window) + final_splatter.color = color the_window.vis_contents += final_splatter the_window.bloodied = TRUE qdel(src) @@ -107,7 +111,8 @@ /// Listing containing overlays of all the splatters we've merged with var/list/splat_overlays = list() -/obj/effect/decal/cleanable/blood/splatter/stacking/Initialize(mapload) +/obj/effect/decal/cleanable/blood/splatter/stacking/Initialize(mapload, blood_color = COLOR_BLOOD) + color = blood_color . = ..() var/mutable_appearance/our_appearance = mutable_appearance(src.icon, src.icon_state) our_appearance.color = src.color @@ -141,8 +146,8 @@ desc = "Raining blood, from a lacerated sky, bleeding its horror!" icon_state = "line" random_icon_states = null - dryname = "dried blood line" - drydesc = "Creating my structure - Now I shall reign in blood!" + base_name = "dried blood line" + dry_desc = "Creating my structure - Now I shall reign in blood!" /obj/effect/decal/cleanable/blood/line/Initialize(mapload, direction) if(!isnull(direction)) diff --git a/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/blood_walk.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/blood_walk.dm index e846a42139a0..f07316b9eec7 100644 --- a/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/blood_walk.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/blood_walk.dm @@ -36,17 +36,6 @@ /datum/status_effect/blood_trial/proc/on_move(atom/movable/mover, turf/old_loc) var/turf/oldLocTurf = get_turf(old_loc) - if(prob(5)) - for(var/mob/living/carbon/human/human in view(7, oldLocTurf)) - if(human == owner) - continue - human.emote("scream") - human.stamina.adjust(-5) - human.Shake(duration = 3 SECONDS) - human.emote("cries blood") - var/turf/turf = get_turf(human) - var/list/blood_drop = list(human.get_blood_id() = 3) - turf.add_liquid_list(blood_drop, FALSE, 300) var/obj/effect/decal/cleanable/blood/footprints/oldLocFP = find_pool_by_blood_state(oldLocTurf, /obj/effect/decal/cleanable/blood/footprints) if(oldLocFP) diff --git a/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/recall_machette.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/recall_machette.dm index f5c53dfdbf66..9e0a5eef5f15 100644 --- a/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/recall_machette.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/recall_machette.dm @@ -67,11 +67,6 @@ user.emote("scream") living_user.adjustBruteLoss(force) to_chat(user, span_warning("You scream out in pain as you hold the [src]!")) - if(ishuman(user)) - var/mob/living/carbon/human/human = user - var/turf/turf = get_turf(user) - var/list/blood_drop = list(human.get_blood_id() = 3) - turf.add_liquid_list(blood_drop, FALSE, 300) return FALSE . = ..() @@ -83,10 +78,5 @@ user.emote("scream") living_user.adjustBruteLoss(force) to_chat(user, span_warning("You scream out in pain as you hold the [src]!")) - if(ishuman(user)) - var/mob/living/carbon/human/human = user - var/turf/turf = get_turf(user) - var/list/blood_drop = list(human.get_blood_id() = 3) - turf.add_liquid_list(blood_drop, FALSE, 300) return FALSE . = ..() diff --git a/monkestation/code/modules/bloodsuckers/structures/bloodsucker_objects.dm b/monkestation/code/modules/bloodsuckers/structures/bloodsucker_objects.dm index c71f94b02d54..92d09ee4fcf5 100644 --- a/monkestation/code/modules/bloodsuckers/structures/bloodsucker_objects.dm +++ b/monkestation/code/modules/bloodsuckers/structures/bloodsucker_objects.dm @@ -41,7 +41,7 @@ ///Bloodbag of Bloodsucker blood (used by Vassals only) /obj/item/reagent_containers/blood/o_minus/bloodsucker name = "blood pack" - unique_blood = /datum/reagent/blood/bloodsucker + blood_type = /datum/blood_type/crew/bloodsucker /obj/item/reagent_containers/blood/o_minus/bloodsucker/examine(mob/user) . = ..() diff --git a/monkestation/code/modules/mob/living/carbon/human/human.dm b/monkestation/code/modules/mob/living/carbon/human/human.dm index 531d405af991..cf07660451b1 100644 --- a/monkestation/code/modules/mob/living/carbon/human/human.dm +++ b/monkestation/code/modules/mob/living/carbon/human/human.dm @@ -1,2 +1,5 @@ /mob/living/carbon/human/species/arachnid race = /datum/species/arachnid + +/mob/living/carbon/human/species/ipc + race = /datum/species/ipc diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm index 0ceef81fbf51..dab89eb3c2ca 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm @@ -17,6 +17,7 @@ species_language_holder = /datum/language_holder/fly mutanttongue = /obj/item/organ/internal/tongue/arachnid mutanteyes = /obj/item/organ/internal/eyes/night_vision/arachnid + exotic_bloodtype = /datum/blood_type/spider speedmod = -0.1 inherent_factions = list(FACTION_SPIDER) bodypart_overrides = list( diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm index d97fcac41e35..72a502501443 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm @@ -10,8 +10,8 @@ external_organs = list( /obj/item/organ/external/ethereal_horns = "None", /obj/item/organ/external/tail/ethereal = "None") - exotic_blood = /datum/reagent/consumable/liquidelectricity //Liquid Electricity. fuck you think of something better gamer - exotic_bloodtype = "LE" + exotic_bloodtype = /datum/blood_type/crew/ethereal + siemens_coeff = 0.5 //They thrive on energy brutemod = 1.25 //They're weak to punches payday_modifier = 1 @@ -77,7 +77,6 @@ ethereal_light = ethereal.mob_light(light_type = /obj/effect/dummy/lighting_obj/moblight/species) spec_updatehealth(ethereal) new_ethereal.set_safe_hunger_level() - update_mail_goodies(ethereal) var/obj/item/organ/internal/heart/ethereal/ethereal_heart = new_ethereal.get_organ_slot(ORGAN_SLOT_HEART) ethereal_heart.ethereal_color = default_color @@ -94,13 +93,6 @@ QDEL_NULL(ethereal_light) return ..() -/datum/species/ethereal/update_quirk_mail_goodies(mob/living/carbon/human/recipient, datum/quirk/quirk, list/mail_goodies = list()) - if(istype(quirk, /datum/quirk/blooddeficiency)) - mail_goodies += list( - /obj/item/reagent_containers/blood/ethereal - ) - return ..() - /datum/species/ethereal/random_name(gender,unique,lastname) if(unique) return random_unique_ethereal_name() diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm index d2a3701ff5c2..029dff3be48a 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm @@ -25,7 +25,7 @@ coldmod = 1.5 //Same as lizard people speedmod = -0.1 //Same as arachnids meat = /obj/item/food/meat/slab/human/mutant/plant - exotic_blood = /datum/reagent/water + exotic_bloodtype = /datum/blood_type/water // disliked_food = VEGETABLES | FRUIT | GRAIN liked_food = MEAT | BUGS | GORE changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT @@ -57,18 +57,6 @@ H.adjustToxLoss(-0.25 * seconds_per_tick) H.adjustOxyLoss(-0.25 * seconds_per_tick) -/datum/species/floran/on_species_gain(mob/living/carbon/new_floran, datum/species/old_species, pref_load) - . = ..() - if(ishuman(new_floran)) - update_mail_goodies(new_floran) - -/datum/species/floran/update_quirk_mail_goodies(mob/living/carbon/human/recipient, datum/quirk/quirk, list/mail_goodies = list()) - if(istype(quirk, /datum/quirk/blooddeficiency)) - mail_goodies += list( - /obj/item/reagent_containers/blood/podperson - ) - return ..() - /datum/species/floran/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) if(chem.type == /datum/reagent/toxin/plantbgone) H.adjustToxLoss(3 * REM * seconds_per_tick) diff --git a/monkestation/code/modules/ranching/chickens/tier1/glass.dm b/monkestation/code/modules/ranching/chickens/tier1/glass.dm index 9d6edc03bfb1..6bcc751dc698 100644 --- a/monkestation/code/modules/ranching/chickens/tier1/glass.dm +++ b/monkestation/code/modules/ranching/chickens/tier1/glass.dm @@ -15,10 +15,10 @@ icon_state = "glass" layer_hen_type = /mob/living/basic/chicken/glass - reagent_flags = DRAWABLE /obj/item/food/egg/glass/Initialize(mapload) . = ..() + reagents.flags |= DRAWABLE START_PROCESSING(SSobj, src) /obj/item/food/egg/glass/process(seconds_per_tick) @@ -45,7 +45,7 @@ /obj/item/food/egg/glass/update_overlays() . = ..() var/amount_left = max_volume - reagents.total_volume - var/datum/mutable_appearance/MA = mutable_appearance(icon, "glass-filling", layer, src) + var/mutable_appearance/MA = mutable_appearance(icon, "glass-filling", layer, src) switch(amount_left) if(5 to INFINITY) MA.icon_state = "glass-filling" diff --git a/monkestation/code/modules/reagents/reagent_containers/blood_pack.dm b/monkestation/code/modules/reagents/reagent_containers/blood_pack.dm index 9106c7946aa6..bfa7cfd60d36 100644 --- a/monkestation/code/modules/reagents/reagent_containers/blood_pack.dm +++ b/monkestation/code/modules/reagents/reagent_containers/blood_pack.dm @@ -1,6 +1,5 @@ /obj/item/reagent_containers/blood/slime - blood_type = "OOZE" - unique_blood = /datum/reagent/toxin/slimeooze + blood_type = /datum/blood_type/slime /obj/item/reagent_containers/blood/slime/examine() .= ..() diff --git a/monkestation/code/modules/slimecore/slime_traits/cleaner.dm b/monkestation/code/modules/slimecore/slime_traits/cleaner.dm index 10c238c0567e..87501d1a0e17 100644 --- a/monkestation/code/modules/slimecore/slime_traits/cleaner.dm +++ b/monkestation/code/modules/slimecore/slime_traits/cleaner.dm @@ -28,9 +28,7 @@ )) ///blood we can clean var/static/list/cleanable_blood = typecacheof(list( - /obj/effect/decal/cleanable/xenoblood, /obj/effect/decal/cleanable/blood, - /obj/effect/decal/cleanable/trail_holder, )) ///pests we hunt var/static/list/huntable_pests = typecacheof(list( diff --git a/monkestation/code/modules/smithing/ipcs/body/base_bodyparts.dm b/monkestation/code/modules/smithing/ipcs/body/base_bodyparts.dm index dfcf48856c9c..18af9178621e 100644 --- a/monkestation/code/modules/smithing/ipcs/body/base_bodyparts.dm +++ b/monkestation/code/modules/smithing/ipcs/body/base_bodyparts.dm @@ -6,7 +6,7 @@ icon_state = "synth_head" is_dimorphic = FALSE should_draw_greyscale = FALSE - biological_state = BIO_ROBOTIC + biological_state = BIO_ROBOTIC | BIO_BLOODED bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC head_flags = HEAD_HAIR | HEAD_LIPS | HEAD_EYECOLOR | HEAD_LIPS @@ -21,7 +21,7 @@ icon_state = "synth_chest" is_dimorphic = FALSE should_draw_greyscale = FALSE - biological_state = BIO_ROBOTIC + biological_state = BIO_ROBOTIC | BIO_BLOODED bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC body_damage_coeff = 1 //IPC Chest at default ///Monkestation Edit @@ -37,7 +37,7 @@ limb_id = "synth" icon_state = "synth_l_arm" should_draw_greyscale = FALSE - biological_state = BIO_ROBOTIC | BIO_JOINTED + biological_state = BIO_ROBOTIC | BIO_JOINTED | BIO_BLOODED bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC body_damage_coeff = 1.1 //IPC's Limbs Should Dismember Easier //Monkestation Edit @@ -52,7 +52,7 @@ limb_id = "synth" icon_state = "synth_r_arm" should_draw_greyscale = FALSE - biological_state = BIO_ROBOTIC | BIO_JOINTED + biological_state = BIO_ROBOTIC | BIO_JOINTED | BIO_BLOODED bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC body_damage_coeff = 1.1 //IPC's Limbs Should Dismember Easier //Monkestation Edit @@ -67,7 +67,7 @@ limb_id = "synth" icon_state = "synth_l_leg" should_draw_greyscale = FALSE - biological_state = BIO_ROBOTIC | BIO_JOINTED + biological_state = BIO_ROBOTIC | BIO_JOINTED | BIO_BLOODED bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC dmg_overlay_type = "synth" @@ -79,7 +79,7 @@ limb_id = "synth" icon_state = "synth_r_leg" should_draw_greyscale = FALSE - biological_state = BIO_ROBOTIC | BIO_JOINTED + biological_state = BIO_ROBOTIC | BIO_JOINTED | BIO_BLOODED bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC body_damage_coeff = 1.1 //IPC's Limbs Should Dismember Easier //Monkestation Edit diff --git a/monkestation/code/modules/smithing/ipcs/reagents/medical_supplies.dm b/monkestation/code/modules/smithing/ipcs/reagents/medical_supplies.dm index 0259ff6dccf8..0597d7132a6e 100644 --- a/monkestation/code/modules/smithing/ipcs/reagents/medical_supplies.dm +++ b/monkestation/code/modules/smithing/ipcs/reagents/medical_supplies.dm @@ -1,7 +1,6 @@ // I cannot wait to get rid of this. This is so many levels of awful wrapped into one. /obj/item/reagent_containers/blood/oil - blood_type = "Oil" - unique_blood = /datum/reagent/fuel/oil + blood_type = /datum/blood_type/oil /obj/item/reagent_containers/pill/liquid_solder name = "liquid solder pill" diff --git a/monkestation/code/modules/smithing/ipcs/species.dm b/monkestation/code/modules/smithing/ipcs/species.dm index 00af82672889..27d9b6b383a7 100644 --- a/monkestation/code/modules/smithing/ipcs/species.dm +++ b/monkestation/code/modules/smithing/ipcs/species.dm @@ -59,7 +59,7 @@ mutantheart = /obj/item/organ/internal/heart/synth mutantliver = /obj/item/organ/internal/liver/synth mutantappendix = null - exotic_blood = /datum/reagent/fuel/oil + exotic_bloodtype = /datum/blood_type/oil bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/robot/ipc, diff --git a/monkestation/code/modules/smithing/oozelings/species.dm b/monkestation/code/modules/smithing/oozelings/species.dm index ad0e7ada02dc..c4b76e482a6d 100644 --- a/monkestation/code/modules/smithing/oozelings/species.dm +++ b/monkestation/code/modules/smithing/oozelings/species.dm @@ -30,7 +30,7 @@ ) meat = /obj/item/food/meat/slab/human/mutant/slime - exotic_blood = /datum/reagent/toxin/slimeooze + exotic_bloodtype = /datum/blood_type/slime burnmod = 0.6 // = 3/5x generic burn damage coldmod = 6 // = 3x cold damage heatmod = 0.5 // = 1/4x heat damage @@ -273,12 +273,6 @@ SPECIES_PERK_NAME = "incombustible", SPECIES_PERK_DESC = "[plural_form] cannot be set aflame.", ), - list( - SPECIES_PERK_TYPE = SPECIES_NEUTRAL_PERK, - SPECIES_PERK_ICON = "tint", - SPECIES_PERK_NAME = initial(exotic_blood.name), - SPECIES_PERK_DESC = "[name] blood is [initial(exotic_blood.name)], which can make recieving medical treatment harder.", - ), list( SPECIES_PERK_TYPE = SPECIES_NEUTRAL_PERK, SPECIES_PERK_ICON = "wind", diff --git a/monkestation/code/modules/virology/immune_systems/_immune_system.dm b/monkestation/code/modules/virology/immune_systems/_immune_system.dm index 13901bb1662f..db38ba1c9ea9 100644 --- a/monkestation/code/modules/virology/immune_systems/_immune_system.dm +++ b/monkestation/code/modules/virology/immune_systems/_immune_system.dm @@ -41,7 +41,7 @@ antibodies[antibody] = rand(10, 30) * boost if(antibody in GLOB.blood_antigens) antibodies[antibody] = rand(10, 20) * boost - var/blood_type = host.has_dna()?.blood_type + var/blood_type = host.has_dna()?.human_blood_type if(blood_type) switch(antibody) if(ANTIGEN_O) diff --git a/tgstation.dme b/tgstation.dme index 7140b7485cc9..d8e442085934 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -405,6 +405,7 @@ #include "code\__DEFINES\~monkestation\atmospherics.dm" #include "code\__DEFINES\~monkestation\atom_hud.dm" #include "code\__DEFINES\~monkestation\blackboard.dm" +#include "code\__DEFINES\~monkestation\blood_datums.dm" #include "code\__DEFINES\~monkestation\blueshift.dm" #include "code\__DEFINES\~monkestation\botany.dm" #include "code\__DEFINES\~monkestation\cargo.dm" @@ -584,6 +585,7 @@ #include "code\__HELPERS\~monkestation-helpers\announcements.dm" #include "code\__HELPERS\~monkestation-helpers\antags.dm" #include "code\__HELPERS\~monkestation-helpers\atoms.dm" +#include "code\__HELPERS\~monkestation-helpers\blood_datums.dm" #include "code\__HELPERS\~monkestation-helpers\clients.dm" #include "code\__HELPERS\~monkestation-helpers\cmp.dm" #include "code\__HELPERS\~monkestation-helpers\icon_smoothing.dm" @@ -5996,7 +5998,6 @@ #include "monkestation\code\modules\antagonists\_common\antag_hud.dm" #include "monkestation\code\modules\antagonists\abductor\abductor.dm" #include "monkestation\code\modules\antagonists\abductor\equipment\gear\abductor_items.dm" -#include "monkestation\code\modules\antagonists\abductor\equipment\glands\blood.dm" #include "monkestation\code\modules\antagonists\abductor\equipment\glands\plasma.dm" #include "monkestation\code\modules\antagonists\abductor\equipment\glands\slime.dm" #include "monkestation\code\modules\antagonists\abductor\equipment\glands\trauma.dm" @@ -6278,6 +6279,13 @@ #include "monkestation\code\modules\ballpit\ballpit.dm" #include "monkestation\code\modules\bitrunners\code\ability_disks.dm" #include "monkestation\code\modules\bitrunners\code\combat_gear_disks.dm" +#include "monkestation\code\modules\blood_datum\blood.dm" +#include "monkestation\code\modules\blood_datum\forensics_helpers.dm" +#include "monkestation\code\modules\blood_datum\components\limbless_aid.dm" +#include "monkestation\code\modules\blood_datum\elements\easy_ignite.dm" +#include "monkestation\code\modules\blood_datum\items\crutch.dm" +#include "monkestation\code\modules\blood_datum\vital_monitor\operating_table_additions.dm" +#include "monkestation\code\modules\blood_datum\vital_monitor\vital_reader.dm" #include "monkestation\code\modules\blood_for_the_blood_gods\fly_away.dm" #include "monkestation\code\modules\blood_for_the_blood_gods\particle.dm" #include "monkestation\code\modules\blood_for_the_blood_gods\slasher\__base_slasher_additions.dm" From d77a73667de0cea84316966fba941b4859d5d739 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 10 Sep 2024 19:40:55 -0700 Subject: [PATCH 008/158] new stuff --- .../machinery/porta_turret/portable_turret.dm | 2 +- .../projectiles/projectile/energy/stun.dm | 37 ++- code/modules/research/techweb/all_nodes.dm | 3 + .../mecha/equipment/weapons/weapons.dm | 1 + .../code/modules/blood_datum/designs.dm | 46 +++ .../code/modules/blood_datum/icons/beam.dmi | Bin 0 -> 348 bytes .../code/modules/blood_datum/stunning.dm | 290 ++++++++++++++++++ .../blood_datum/vital_monitor/vital_reader.dm | 112 ++++++- .../virology/machines/floor_health_scanner.dm | 12 +- tgstation.dme | 2 + 10 files changed, 475 insertions(+), 30 deletions(-) create mode 100644 monkestation/code/modules/blood_datum/designs.dm create mode 100644 monkestation/code/modules/blood_datum/icons/beam.dmi create mode 100644 monkestation/code/modules/blood_datum/stunning.dm diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index bfbd2400b287..6bc716fac9b5 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -466,7 +466,7 @@ DEFINE_BITFIELD(turret_flags, list( else if(iscarbon(A)) var/mob/living/carbon/C = A //If not emagged, only target carbons that can use items - if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || !(C.mobility_flags & MOBILITY_USE))) + if(mode != TURRET_LETHAL && (!(C.mobility_flags & MOBILITY_USE) || HAS_TRAIT(C, TRAIT_INCAPACITATED))) continue //If emagged, target all but dead carbons diff --git a/code/modules/projectiles/projectile/energy/stun.dm b/code/modules/projectiles/projectile/energy/stun.dm index 7f36bf437ed6..8c28138be38b 100644 --- a/code/modules/projectiles/projectile/energy/stun.dm +++ b/code/modules/projectiles/projectile/energy/stun.dm @@ -2,28 +2,41 @@ name = "electrode" icon_state = "spark" color = "#FFFF00" + /* paralyze = 10 SECONDS stutter = 10 SECONDS jitter = 40 SECONDS + */ hitsound = 'sound/weapons/taserhit.ogg' - range = 7 + range = 5 tracer_type = /obj/effect/projectile/tracer/stun muzzle_type = /obj/effect/projectile/muzzle/stun impact_type = /obj/effect/projectile/impact/stun /obj/projectile/energy/electrode/on_hit(atom/target, blocked = 0, pierce_hit) . = ..() - if(!ismob(target) || blocked >= 100) //Fully blocked by mob or collided with dense object - burst into sparks! - do_sparks(1, TRUE, src) - else if(iscarbon(target)) - var/mob/living/carbon/C = target - C.add_mood_event("tased", /datum/mood_event/tased) - SEND_SIGNAL(C, COMSIG_LIVING_MINOR_SHOCK) - if(C.dna && C.dna.check_mutation(/datum/mutation/human/hulk)) - C.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk") - else if(!C.check_stun_immunity(CANKNOCKDOWN)) - addtimer(CALLBACK(C, TYPE_PROC_REF(/mob/living/carbon, do_jitter_animation), 20), 5) + if(pierce_hit) + return . + do_sparks(1, TRUE, src) + if(. == BULLET_ACT_BLOCK || !isliving(target) || blocked >= 100) + visible_message(span_warning("The electrodes fail to shock [target], and fall to the ground.")) + return . + + var/mob/living/tased = target + if(HAS_TRAIT(target, TRAIT_HULK)) + tased.say(pick( + ";RAAAAAAAARGH!", + ";HNNNNNNNNNGGGGGGH!", + ";GWAAAAAAAARRRHHH!", + "NNNNNNNNGGGGGGGGHH!", + ";AAAAAAARRRGH!", + ), forced = "hulk") + if(tased.apply_status_effect(/datum/status_effect/tased, fired_from, firer)) + return . + visible_message(span_warning("The electrodes fail to shock [target], and fall to the ground.")) + return BULLET_ACT_BLOCK + /obj/projectile/energy/electrode/on_range() //to ensure the bolt sparks when it reaches the end of its range if it didn't hit a target yet do_sparks(1, TRUE, src) - ..() + return ..() diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 4a818a53e8dc..0c6331987fb1 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -437,6 +437,8 @@ "diseaseanalyzer", "centrifuge", "path_data", + "scanning_pad", + "vitals_monitor", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) discount_experiments = list(/datum/experiment/dissection/human = 1000) @@ -459,6 +461,7 @@ "plasmarefiller", "smoke_machine", "sleeper", + "vitals_monitor_advanced", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) discount_experiments = list(/datum/experiment/scanning/random/material/meat = 2000, diff --git a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm index 3d8cc1d02044..9a503c6cf240 100644 --- a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm +++ b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm @@ -58,6 +58,7 @@ var/obj/projectile/projectile_obj = new projectile(get_turf(src)) projectile_obj.log_override = TRUE //we log being fired ourselves a little further down. projectile_obj.firer = chassis + projectile_obj.fired_from = src projectile_obj.preparePixelProjectile(target, source, modifiers, spread) if(source.client && isliving(source)) //dont want it to happen from syndie mecha npc mobs, they do direct fire anyways var/mob/living/shooter = source diff --git a/monkestation/code/modules/blood_datum/designs.dm b/monkestation/code/modules/blood_datum/designs.dm new file mode 100644 index 000000000000..0da2fcfefdd1 --- /dev/null +++ b/monkestation/code/modules/blood_datum/designs.dm @@ -0,0 +1,46 @@ +/datum/design/vitals_monitor + name = "Vitals Monitor" + desc = "A wall mounted computer that displays the vitals of a patient nearby. \ + Links to stasis beds, operating tables, and other machines that can hold patients \ + such as cryo cells, sleepers, and more." + id = "vitals_monitor" + build_type = PROTOLATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 4, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, + /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT * 0.5, + ) + build_path = /obj/item/wallframe/status_display/vitals + category = list(RND_CATEGORY_COMPUTER + RND_SUBCATEGORY_COMPUTER_MEDICAL) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL + +/datum/design/vitals_monitor/advanced + name = "Advanced Vitals Monitor" + desc = "An updated vitals display which performs a more detailed scan of the patient than the basic display." + id = "vitals_monitor_advanced" + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 4, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, + /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT, + /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT * 0.5, + ) + build_path = /obj/item/wallframe/status_display/vitals/advanced + +/datum/design/board/vital_floor_scanner + name = "Vitals Scanning Pad" + desc = "The circuit board for a vitals scanning pad." + id = "scanning_pad" + build_path = /obj/item/circuitboard/machine/vital_floor_scanner + category = list( + RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_MEDICAL + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL + +/obj/item/circuitboard/machine/vital_floor_scanner + name = "\improper Vitals Scanning Pad" + greyscale_colors = CIRCUIT_COLOR_MEDICAL + build_path = /obj/machinery/health_scanner_floor + req_components = list( + /obj/item/stack/cable_coil = 5, + /datum/stock_part/scanning_module = 1, + ) diff --git a/monkestation/code/modules/blood_datum/icons/beam.dmi b/monkestation/code/modules/blood_datum/icons/beam.dmi new file mode 100644 index 0000000000000000000000000000000000000000..2ac3e0da83fa0a117365913cce27a4d7455ef8f0 GIT binary patch literal 348 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-uK)l47Zqjr{~w6{v&<{V z1Bx@21o;IsI6S+N2IN##g+!FNq!uR^WfqiV<^$y`=BW0b=5sI*U^stw{fz?AkGpnp z2(tfMcyX!kg(Y_d>euf$dnPq0XII^f4YKSOCo7Zr*KG7M7MLEmrg;i0hi}@|Ki%mk zMGO}8rj>9!Zm rqKU2b`wj}_z4`N-voogPAXi*Lgks_|h1YX|ZeZ|q^>bP0l+XkK0^f~Q literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/blood_datum/stunning.dm b/monkestation/code/modules/blood_datum/stunning.dm new file mode 100644 index 000000000000..a4a81799d8dd --- /dev/null +++ b/monkestation/code/modules/blood_datum/stunning.dm @@ -0,0 +1,290 @@ + +#define COMSIG_BEAM_ENTERED "beam_entered" + +/// Status effect tracking being tased by someone! +/datum/status_effect/tased + id = "being_tased" + status_type = STATUS_EFFECT_MULTIPLE + alert_type = /atom/movable/screen/alert/status_effect/tazed + tick_interval = 0.25 SECONDS + on_remove_on_mob_delete = TRUE + /// What atom is tasing us? + var/atom/taser + /// What atom is using the atom tasing us? Sometimes the same as the taser, such as with turrets. + var/atom/firer + /// The beam datum representing the taser electrodes + var/datum/beam/tase_line + +/datum/status_effect/tased/on_creation(mob/living/new_owner, atom/fired_from, atom/firer) + if(isnull(fired_from) || isnull(firer) || !can_tase_with(fired_from)) + qdel(src) + return + + if(new_owner.has_status_effect(type) != src) + alert_type = null + + . = ..() + if(!.) + return + + set_taser(fired_from) + set_firer(firer) + +/// Checks if the passed atom is captable of being used to tase someone +/datum/status_effect/tased/proc/can_tase_with(atom/with_what) + if(istype(with_what, /obj/item/gun/energy)) + var/obj/item/gun/energy/taser_gun = with_what + if(isnull(taser_gun.cell)) + return FALSE + + else if(istype(with_what, /obj/machinery)) + var/obj/machinery/taser_machine = with_what + if(!taser_machine.is_operational) + return FALSE + + return TRUE + +/// Actually does the tasing with the passed atom +/// Returns TRUE if the tasing was successful, FALSE if it failed +/datum/status_effect/tased/proc/do_tase_with(atom/with_what, seconds_between_ticks) + if(!can_see(taser, owner, 5)) + return FALSE + if(istype(with_what, /obj/item/gun/energy)) + var/obj/item/gun/energy/taser_gun = with_what + if(!taser_gun.cell?.use(60 * seconds_between_ticks)) + return FALSE + taser_gun.update_appearance() + return TRUE + + if(istype(taser, /obj/machinery)) + var/obj/machinery/taser_machine = taser + if(!taser_machine.is_operational) + return FALSE + // We can't measure the output of this but if we use too much power the area will depower -> depower the machine -> stop taze next tick + taser_machine.use_power(60 * seconds_between_ticks) + return TRUE + + if(istype(taser, /obj/item/mecha_parts/mecha_equipment)) + var/obj/item/mecha_parts/mecha_equipment/taser_equipment = taser + if(!taser_equipment.chassis \ + || !taser_equipment.activated \ + || taser_equipment.get_integrity() <= 1 \ + || taser_equipment.chassis.is_currently_ejecting \ + || taser_equipment.chassis.equipment_disabled \ + || !taser_equipment.chassis.use_power(60 * seconds_between_ticks)) + return FALSE + return TRUE + + return TRUE + +/datum/status_effect/tased/on_apply() + if(issilicon(owner) \ + || istype(owner, /mob/living/basic/bot) \ + || istype(owner, /mob/living/simple_animal/bot) \ + || HAS_TRAIT(owner, TRAIT_PIERCEIMMUNE)) + return FALSE + + RegisterSignal(owner, COMSIG_LIVING_RESIST, PROC_REF(try_remove_taser)) + SEND_SIGNAL(owner, COMSIG_LIVING_MINOR_SHOCK) + owner.add_mood_event("tased", /datum/mood_event/tased) + owner.add_movespeed_modifier(/datum/movespeed_modifier/being_tased) + if(owner.pain_controller?.pain_modifier > 0.5) + owner.pain_emote("scream") + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.force_say() + return TRUE + +/datum/status_effect/tased/on_remove() + if(istype(taser, /obj/machinery/porta_turret)) + var/obj/machinery/porta_turret/taser_turret = taser + taser_turret.manual_control = initial(taser_turret.manual_control) + taser_turret.always_up = initial(taser_turret.always_up) + taser_turret.check_should_process() + else if(istype(taser, /obj/machinery/power/emitter)) + var/obj/machinery/power/emitter/taser_emitter = taser + taser_emitter.manual = initial(taser_emitter.manual) + + var/mob/living/mob_firer = firer + if(istype(mob_firer)) + mob_firer.remove_movespeed_modifier(/datum/movespeed_modifier/tasing_someone) + + owner.remove_movespeed_modifier(/datum/movespeed_modifier/being_tased) + if(!QDELING(owner)) + owner.adjust_jitter_up_to(10 SECONDS, 1 MINUTES) + + taser = null + firer = null + QDEL_NULL(tase_line) + +/datum/status_effect/tased/tick(seconds_between_ticks) + if(!do_tase_with(taser, seconds_between_ticks)) + end_tase() + return + if(owner.check_stun_immunity(CANSTUN|CANKNOCKDOWN)) + return + // You are damp, that's bad when you're being tased + if(owner.fire_stacks < 0) + owner.apply_damage(max(1, owner.fire_stacks * -0.5 * seconds_between_ticks), FIRE, spread_damage = TRUE) + if(SPT_PROB(25, seconds_between_ticks)) + do_sparks(1, FALSE, owner) + + owner.set_stutter_if_lower(10 SECONDS) + owner.set_jitter_if_lower(20 SECONDS) + owner.cause_pain(BODY_ZONES_ALL, 2 * seconds_between_ticks, BURN) + owner.apply_damage(120 * seconds_between_ticks * (owner.pain_controller?.pain_modifier || 1), STAMINA) + if(owner.stat <= SOFT_CRIT) + owner.do_jitter_animation(INFINITY) // maximum POWER + +/// Sets the passed atom as the "taser" +/datum/status_effect/tased/proc/set_taser(atom/new_taser) + taser = new_taser + RegisterSignals(taser, list(COMSIG_QDELETING, COMSIG_ITEM_DROPPED, COMSIG_ITEM_EQUIPPED), PROC_REF(end_tase)) + RegisterSignal(taser, COMSIG_GUN_TRY_FIRE, PROC_REF(block_firing)) + if(istype(taser, /obj/machinery/porta_turret)) + var/obj/machinery/porta_turret/taser_turret = taser + taser_turret.manual_control = TRUE + taser_turret.always_up = TRUE + else if(istype(taser, /obj/machinery/power/emitter)) + var/obj/machinery/power/emitter/taser_emitter = taser + taser_emitter.manual = TRUE + +/// Sets the passed atom as the person operating the taser, the "firer" +/datum/status_effect/tased/proc/set_firer(atom/new_firer) + firer = new_firer + if(taser != firer) // Turrets, notably, are both + RegisterSignal(firer, COMSIG_QDELETING, PROC_REF(end_tase)) + + // RegisterSignals(firer, list(COMSIG_MOB_SWAP_HANDS), PROC_REF(end_tase)) + RegisterSignal(firer, COMSIG_MOB_CLICKON, PROC_REF(user_cancel_tase)) + + // Ensures AI mobs or turrets don't tase players until they run out of power + var/mob/living/mob_firer = new_firer + if(!istype(mob_firer) || isnull(mob_firer.client)) + // If multiple things are tasing the same mob, give up sooner, so they can select a new target potentially + addtimer(CALLBACK(src, PROC_REF(end_tase)), (owner.has_status_effect(type) != src) ? 2 SECONDS : 8 SECONDS) + if(istype(mob_firer)) + mob_firer.add_movespeed_modifier(/datum/movespeed_modifier/tasing_someone) + + tase_line = firer.Beam( + BeamTarget = owner, + icon = 'monkestation/code/modules/blood_datum/icons/beam.dmi', + icon_state = "electrodes", + maxdistance = 6, + beam_type = /obj/effect/ebeam/react_to_entry/electrodes, + ) + RegisterSignal(tase_line, COMSIG_BEAM_ENTERED, PROC_REF(disrupt_tase)) + RegisterSignal(tase_line, COMSIG_QDELETING, PROC_REF(end_tase)) + tase_line.RegisterSignal(owner, COMSIG_LIVING_SET_BODY_POSITION, TYPE_PROC_REF(/datum/beam, redrawing)) + +/datum/status_effect/tased/proc/block_firing(...) + SIGNAL_HANDLER + return COMPONENT_CANCEL_GUN_FIRE + +/datum/status_effect/tased/proc/user_cancel_tase(mob/living/source, atom/clicked_on, modifiers) + SIGNAL_HANDLER + if(clicked_on != owner) + return NONE + if(LAZYACCESS(modifiers, SHIFT_CLICK)) + return NONE + end_tase() + return COMSIG_MOB_CANCEL_CLICKON + +/datum/status_effect/tased/proc/end_tase(...) + SIGNAL_HANDLER + if(QDELING(src)) + return + owner.visible_message( + span_warning("The electrodes stop shocking [owner], and fall to the ground."), + span_notice("The electrodes stop shocking you, and fall to the ground."), + ) + qdel(src) + +/datum/status_effect/tased/proc/try_remove_taser(datum/source) + SIGNAL_HANDLER + INVOKE_ASYNC(src, PROC_REF(try_remove_taser_async), source) + +/datum/status_effect/tased/proc/try_remove_taser_async() + owner.visible_message( + span_warning("[owner] tries to remove the electrodes!"), + span_notice("You try to remove the electrodes!"), + ) + // If embedding was less... difficult to work with, I would make tasers rely on an embedded object to handle this + if(!do_after(src, 5 SECONDS, src, extra_checks = CALLBACK(src, PROC_REF(try_remove_taser_checks)), interaction_key = "tazed")) + return + owner.visible_message( + span_warning("[owner] removes the electrodes from [owner.p_their()] body!"), + span_notice("You remove the electrodes!"), + ) + end_tase() + +/datum/status_effect/tased/proc/try_remove_taser_checks() + return !QDELETED(src) + +/datum/status_effect/tased/proc/disrupt_tase(datum/beam/source, obj/effect/ebeam/beam_effect, atom/movable/entering) + SIGNAL_HANDLER + + if(!isliving(entering) || entering == taser || entering == firer || entering == owner) + return + if(entering.pass_flags & (PASSMOB|PASSGRILLE|PASSTABLE)) + return + var/mob/living/disruptor = entering + if(disruptor.body_position == LYING_DOWN) + return + disruptor.visible_message( + span_warning("[disruptor] gets tangled in the electrodes!"), + span_warning("You get tangled in the electrodes!"), + ) + disruptor.apply_damage(90, STAMINA) + disruptor.Knockdown(5 SECONDS) + disruptor.adjust_jitter_up_to(10 SECONDS, 30 SECONDS) + qdel(src) + +/// Screen alert for being tased, clicking does a resist (like being on fire or w/e) +/atom/movable/screen/alert/status_effect/tazed + name = "Tased!" + desc = "Taser electrodes are shocking you! You can resist to try to remove them." + icon_state = "stun" + +/atom/movable/screen/alert/status_effect/tazed/Click(location, control, params) + . = ..() + if(!.) + return + var/mob/living/clicker = usr + clicker.resist() + +/// Beam subtype which sends a signal to the beam itself when someone walks inside it +/obj/effect/ebeam/react_to_entry + +/obj/effect/ebeam/react_to_entry/Initialize(mapload, beam_owner) + . = ..() + if(isnull(owner)) + return + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered), + COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON = PROC_REF(on_entered), + ) + AddElement(/datum/element/connect_loc, loc_connections) + // Technically the beam is entering the mob but we'll count it + for(var/thing in loc) + on_entered(src, thing) + +/obj/effect/ebeam/react_to_entry/proc/on_entered(datum/source, atom/movable/entering) + SIGNAL_HANDLER + SEND_SIGNAL(owner, COMSIG_BEAM_ENTERED, src, entering) + +/obj/effect/ebeam/react_to_entry/electrodes + name = "electrodes" + light_system = OVERLAY_LIGHT + light_on = TRUE + light_color = COLOR_YELLOW + light_power = 1 + light_outer_range = 1.5 + +/datum/movespeed_modifier/tasing_someone + multiplicative_slowdown = 2 + +/datum/movespeed_modifier/being_tased + multiplicative_slowdown = 4 + +#undef COMSIG_BEAM_ENTERED diff --git a/monkestation/code/modules/blood_datum/vital_monitor/vital_reader.dm b/monkestation/code/modules/blood_datum/vital_monitor/vital_reader.dm index 43f72ae51efc..2a47aab83218 100644 --- a/monkestation/code/modules/blood_datum/vital_monitor/vital_reader.dm +++ b/monkestation/code/modules/blood_datum/vital_monitor/vital_reader.dm @@ -1,8 +1,25 @@ /obj/item/wallframe/status_display/vitals name = "vitals display frame" - desc = "Used to build vitals displays. Secure on a wall nearby a stasis bed or operating table." + desc = "Used to build vitals displays. Secure on a wall nearby a stasis bed, operating table, \ + or another machine that can hold patients such as cryo cells or sleepers." + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 4, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, + /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT * 0.5, + ) result_path = /obj/machinery/computer/vitals_reader +/obj/item/wallframe/status_display/vitals/advanced + name = "advanced vitals display frame" + desc = "Used to build advanced vitals displays. Performs a more detailed scan of the patient than the basic display." + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 4, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, + /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT, + /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT * 0.5, + ) + result_path = /obj/machinery/computer/vitals_reader/advanced + /// A wall mounted screen that showcases the vitals of a patient nearby. /obj/machinery/computer/vitals_reader name = "vitals display" @@ -16,12 +33,16 @@ layer = ABOVE_WINDOW_LAYER interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_REQUIRES_DEXTERITY interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON - use_power = NO_POWER_USE + use_power = IDLE_POWER_USE + idle_power_usage = 0 + active_power_usage = BASE_MACHINE_IDLE_CONSUMPTION icon_keyboard = null icon_screen = null /// Whether we perform an advanced scan on examine or not, currently admin only var/advanced = FALSE + /// Typepath to spawn when deconstructed + var/frame = /obj/item/wallframe/status_display/vitals /// Whether we are on or off VAR_FINAL/active = FALSE /// Reference to the mob that is being tracked / scanned @@ -38,16 +59,53 @@ /obj/machinery/implantchair, /obj/machinery/sleeper, /obj/machinery/stasis, + /obj/machinery/health_scanner_floor, )) MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader, 32) +/obj/machinery/computer/vitals_reader/advanced + name = "advanced vitals display" + desc = "A small screen that displays the vitals of a patient. \ + Performs a more detailed scan of the patient than the basic display." + frame = /obj/item/wallframe/status_display/vitals/advanced + advanced = TRUE + +MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader/advanced, 32) + +/obj/machinery/computer/vitals_reader/no_hand + name = "automatic vitals display" + desc = "A small screen that displays the vitals of a patient. \ + It has no button to toggle it manually." + interaction_flags_atom = NONE + interaction_flags_machine = NONE + +MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader/no_hand, 32) + +/obj/machinery/computer/vitals_reader/Initialize(mapload, obj/item/circuitboard/C) + . = ..() + register_context() + +/obj/machinery/computer/vitals_reader/Destroy() + unset_patient() + return ..() + +/obj/machinery/computer/vitals_reader/attackby(obj/item/weapon, mob/living/user, params) + if(!istype(user) || (user.istate & ISTATE_HARM)) + return ..() + if((interaction_flags_atom & INTERACT_ATOM_ATTACK_HAND) && (weapon.item_flags & SURGICAL_TOOL)) + // You can flick it on while doing surgery + return interact(user) + return ..() + /obj/machinery/computer/vitals_reader/wrench_act(mob/living/user, obj/item/tool) + if(flags_1 & NODECONSTRUCT_1) + return FALSE if(user.istate & ISTATE_HARM) return FALSE + balloon_alert(user, "detaching...") if(tool.use_tool(src, user, 6 SECONDS, volume = 50)) playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE) - balloon_alert(user, "detached") deconstruct(TRUE) return TRUE @@ -56,7 +114,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader, 32) return var/atom/drop_loc = drop_location() if(disassembled) - new /obj/item/wallframe/status_display/vitals(drop_loc) + new frame(drop_loc) else new /obj/item/stack/sheet/iron(drop_loc, 2) new /obj/item/shard(drop_loc) @@ -65,12 +123,14 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader, 32) /obj/machinery/computer/vitals_reader/examine(mob/user) . = ..() - if(!is_operational) + if(!is_operational || !active || user.is_blind()) return if(isnull(patient)) . += span_notice("The display is currently scanning for a patient.") - else if(!issilicon(user) && (HAS_TRAIT(user, TRAIT_DUMB) || !user.can_read(src, silent = TRUE))) + else if(!issilicon(user) && !isobserver(user) && get_dist(patient, user) > 2) + . += span_notice("You are too far away to read the display.") + else if(HAS_TRAIT(user, TRAIT_DUMB) || !user.can_read(src, reading_check_flags = READING_CHECK_LITERACY, silent = TRUE)) . += span_warning("You try to comprehend the display, but it's too complex for you to understand.") else if(get_dist(patient, user) <= 2 || isobserver(user) || issilicon(user)) . += healthscan(user, patient, advanced = advanced, tochat = FALSE) @@ -86,11 +146,12 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader, 32) return ..() /obj/machinery/computer/vitals_reader/add_context(atom/source, list/context, obj/item/held_item, mob/user) - if(!isnull(held_item)) - return NONE - - context[SCREENTIP_CONTEXT_LMB] = "Toggle readout" - if(isAI(user)) + if(isnull(held_item) || (held_item.item_flags & SURGICAL_TOOL)) + if(interaction_flags_atom & INTERACT_ATOM_ATTACK_HAND) + context[SCREENTIP_CONTEXT_LMB] = "Toggle readout" + else if(held_item.tool_behaviour == TOOL_WRENCH) + context[SCREENTIP_CONTEXT_LMB] = "Detach" + if(!isnull(patient)) context[SCREENTIP_CONTEXT_SHIFT_LMB] = "Examine vitals" return CONTEXTUAL_SCREENTIP_SET @@ -168,7 +229,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader, 32) /obj/machinery/computer/vitals_reader/update_overlays() . = ..() - if(!active) + if(!active || !is_operational) return if(isnull(patient)) @@ -202,6 +263,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader, 32) /// Converts a percentage to a color /obj/machinery/computer/vitals_reader/proc/percent_to_color(percent) + if(machine_stat & (EMPED|EMAGGED|BROKEN)) + percent = rand(1, 100) * 0.01 if(percent == 0) return "#2A72AA" @@ -219,6 +282,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader, 32) /// Converts a percentage to a bar icon state /obj/machinery/computer/vitals_reader/proc/percent_to_bar(percent) + if(machine_stat & (EMPED|EMAGGED|BROKEN)) + percent = rand(1, 100) * 0.01 if(percent >= 1) return "bar9" if(percent <= 0) @@ -274,18 +339,22 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader, 32) return TRUE /obj/machinery/computer/vitals_reader/on_set_is_operational(old_value) - if(!is_operational && active) + if(is_operational) + return + if(active) toggle_active() + return + update_appearance(UPDATE_OVERLAYS) /// Toggles whether the display is active or not /obj/machinery/computer/vitals_reader/proc/toggle_active() if(active) active = FALSE - update_use_power(NO_POWER_USE) + update_use_power(IDLE_POWER_USE) unset_patient() else active = TRUE - update_use_power(IDLE_POWER_USE) + update_use_power(ACTIVE_POWER_USE) find_active_patient() update_appearance(UPDATE_OVERLAYS) @@ -310,7 +379,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader, 32) var/obj/machinery/computer/operating/op = nearby_thing patient = op.table?.patient - if(!istype(patient) || !(patient.mob_biotypes & MOB_ORGANIC)) + if(!istype(patient) || (patient.mob_biotypes & MOB_ROBOTIC)) continue set_patient(patient) @@ -366,3 +435,14 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader, 32) /obj/machinery/computer/vitals_reader/proc/update_overlay_on_signal(...) SIGNAL_HANDLER update_appearance(UPDATE_OVERLAYS) + +/obj/machinery/vitals_reader/emp_act(severity) + . = ..() + if(. & EMP_PROTECT_SELF) + return + + set_machine_stat(machine_stat | EMPED) + addtimer(CALLBACK(src, PROC_REF(fix_emp)), (severity == EMP_HEAVY ? 150 SECONDS : 75 SECONDS)) + +/obj/machinery/vitals_reader/proc/fix_emp() + set_machine_stat(machine_stat & ~EMPED) diff --git a/monkestation/code/modules/virology/machines/floor_health_scanner.dm b/monkestation/code/modules/virology/machines/floor_health_scanner.dm index 939b1009bc9a..ceab3c6ee25d 100644 --- a/monkestation/code/modules/virology/machines/floor_health_scanner.dm +++ b/monkestation/code/modules/virology/machines/floor_health_scanner.dm @@ -1,9 +1,10 @@ /obj/machinery/health_scanner_floor - name = "floor scanner" + name = "Vitals Scanning Pad" desc = "Gives patients a brief medical overview by stepping on it." icon_state = "floor_scanner" icon = 'monkestation/code/modules/virology/icons/virology.dmi' + circuit = /obj/item/circuitboard/machine/vital_floor_scanner density = FALSE anchored = TRUE @@ -26,7 +27,9 @@ vis_contents += maptext_obj var/static/list/connections = list( + COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON = PROC_REF(on_entered), COMSIG_ATOM_ENTERED = PROC_REF(on_entered), + COMSIG_ATOM_EXITED = PROC_REF(on_exited), ) AddElement(/datum/element/connect_loc, connections) AddElement(/datum/element/elevation, 4) @@ -51,10 +54,17 @@ arrived.visual_masked_scan() maptext_obj.maptext = generate_maptext(arrived) + set_occupant(arrived) animate(maptext_obj, 0.25 SECONDS, maptext_y = 32, easing = BOUNCE_EASING) addtimer(CALLBACK(src, PROC_REF(clear_maptext)), 3 SECONDS) +/obj/machinery/health_scanner_floor/proc/on_exited(datum/source, atom/movable/departed) + SIGNAL_HANDLER + if(occupant != departed) + return + set_occupant(null) + /obj/machinery/health_scanner_floor/proc/clear_maptext() maptext_obj.maptext = null maptext_obj.maptext_y = 0 diff --git a/tgstation.dme b/tgstation.dme index d8e442085934..2544597586cb 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -6280,7 +6280,9 @@ #include "monkestation\code\modules\bitrunners\code\ability_disks.dm" #include "monkestation\code\modules\bitrunners\code\combat_gear_disks.dm" #include "monkestation\code\modules\blood_datum\blood.dm" +#include "monkestation\code\modules\blood_datum\designs.dm" #include "monkestation\code\modules\blood_datum\forensics_helpers.dm" +#include "monkestation\code\modules\blood_datum\stunning.dm" #include "monkestation\code\modules\blood_datum\components\limbless_aid.dm" #include "monkestation\code\modules\blood_datum\elements\easy_ignite.dm" #include "monkestation\code\modules\blood_datum\items\crutch.dm" From 0791500b31525ad8d5b178039cd25e114a93ef8a Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 10 Sep 2024 21:29:54 -0700 Subject: [PATCH 009/158] non lethals tweak --- code/modules/mob/living/carbon/human/human.dm | 2 +- code/modules/projectiles/projectile.dm | 8 +++ icons/hud/screen_alert.dmi | Bin 127741 -> 140664 bytes monkestation/code/datums/stamina_container.dm | 4 +- .../code/modules/blood_datum/debilitated.dm | 51 ++++++++++++++++++ tgstation.dme | 1 + 6 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 monkestation/code/modules/blood_datum/debilitated.dm diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 6a3a3552851b..6762a99880aa 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -915,7 +915,7 @@ /mob/living/carbon/human/pre_stamina_change(diff as num, forced) if(diff < 0) //Taking damage, not healing - return diff * physiology.stamina_mod + return diff * physiology.stamina_mod * physiology.temp_stamina_mod return diff /mob/living/carbon/human/adjust_nutrition(change) //Honestly FUCK the oldcoders for putting nutrition on /mob someone else can move it up because holy hell I'd have to fix SO many typechecks diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 77a695647a86..5a919f5d1656 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -262,6 +262,14 @@ // i know that this is probably more with wands and gun mods in mind, but it's a bit silly that the projectile on_hit signal doesn't ping the projectile itself. // maybe we care what the projectile thinks! See about combining these via args some time when it's not 5AM + if(stamina >= 10 && isliving(target)) + var/mob/living/living = target + var/datum/status_effect/stacking/debilitated/effect = living.has_status_effect(/datum/status_effect/stacking/debilitated) + if(effect) + effect.add_stacks(1) + else + living.apply_status_effect(/datum/status_effect/stacking/debilitated, 1) + var/hit_limb_zone if(isliving(target)) var/mob/living/L = target diff --git a/icons/hud/screen_alert.dmi b/icons/hud/screen_alert.dmi index f65f56e58c9678277b33c0ab1270c2e260bda4b0..33a1ef4d0288a4728f0047de3608ddf679b92d1e 100755 GIT binary patch literal 140664 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 eM~p-e!UTCyC^ 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 z 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 Z;J-Z`)jYQH8yWxr002ovPDHLkV1mRZbW#8S literal 127741 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%0Afn=5M`}nCIzZ+p;GJIt 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 E2W6fP+yDRo diff --git a/monkestation/code/datums/stamina_container.dm b/monkestation/code/datums/stamina_container.dm index 28a3c9aa76ce..29dd479f6fff 100644 --- a/monkestation/code/datums/stamina_container.dm +++ b/monkestation/code/datums/stamina_container.dm @@ -75,11 +75,13 @@ COOLDOWN_START(src, stamina_grace_period, time) ///Adjust stamina by an amount. -/datum/stamina_container/proc/adjust(amt as num, forced) +/datum/stamina_container/proc/adjust(amt as num, forced, base_modify = FALSE) if((!amt || !COOLDOWN_FINISHED(src, stamina_grace_period)) && !forced) return ///Our parent might want to fuck with these numbers var/modify = parent.pre_stamina_change(amt, forced) + if(base_modify) + modify = amt current = round(clamp(current + modify, 0, maximum), DAMAGE_PRECISION) update(1) if((amt < 0) && is_regenerating) diff --git a/monkestation/code/modules/blood_datum/debilitated.dm b/monkestation/code/modules/blood_datum/debilitated.dm new file mode 100644 index 000000000000..374b2079d24e --- /dev/null +++ b/monkestation/code/modules/blood_datum/debilitated.dm @@ -0,0 +1,51 @@ +/datum/physiology + ///our temp stamina mod + var/temp_stamina_mod = 1 + +/datum/status_effect/stacking/debilitated + id = "debilitated" + stacks = 0 + max_stacks = 10 + tick_interval = 10 SECONDS + delay_before_decay = 3 MINUTES + consumed_on_threshold = FALSE + alert_type = /atom/movable/screen/alert/status_effect/debilitated + status_type = STATUS_EFFECT_REFRESH + + ///our base stamina damage increase on stamina projectiles + var/base_increase = 10 + ///our increase per stack + var/per_stack_increase = 5 + ///our base stamina loss multiplier + var/loss_multiplier = 1 + ///our per stack increase to stamina loss + var/per_stack_multiplier_increase = 0.1 + ///our cached stamina_mod + var/cached_stamina + +/datum/status_effect/stacking/debilitated/on_apply() + . = ..() + if(ishuman(owner)) + var/mob/living/carbon/human/human = owner + cached_stamina = human.physiology.temp_stamina_mod + RegisterSignal(owner, COMSIG_ATOM_BULLET_ACT, PROC_REF(check_bullet)) + +/datum/status_effect/stacking/debilitated/add_stacks(stacks_added) + . = ..() + if(!ishuman(owner)) + return + var/mob/living/carbon/human/human = owner + human.physiology.temp_stamina_mod = loss_multiplier + (stacks * per_stack_multiplier_increase) + +/datum/status_effect/stacking/debilitated/proc/check_bullet(mob/living/carbon/human/source, obj/projectile/hitting_projectile, def_zone) + SIGNAL_HANDLER + + if(hitting_projectile.stamina < 10) + return + + source.stamina.adjust(-base_increase + (stacks * per_stack_increase), FALSE, TRUE) + +/atom/movable/screen/alert/status_effect/debilitated + icon_state = "debilitated" + name = "Debilitated" + desc = "You are taking extra stamina damage from incoming projectiles, and lose stamina faster." diff --git a/tgstation.dme b/tgstation.dme index 2544597586cb..54c68243be18 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -6280,6 +6280,7 @@ #include "monkestation\code\modules\bitrunners\code\ability_disks.dm" #include "monkestation\code\modules\bitrunners\code\combat_gear_disks.dm" #include "monkestation\code\modules\blood_datum\blood.dm" +#include "monkestation\code\modules\blood_datum\debilitated.dm" #include "monkestation\code\modules\blood_datum\designs.dm" #include "monkestation\code\modules\blood_datum\forensics_helpers.dm" #include "monkestation\code\modules\blood_datum\stunning.dm" From 6cac0c8cddb7ab7a6a13e36c235ab1367c4c54b2 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 10 Sep 2024 22:45:47 -0700 Subject: [PATCH 010/158] Update all_nodes.dm --- code/modules/research/techweb/all_nodes.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 0c6331987fb1..759c38a4af9b 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -425,6 +425,8 @@ "defibrillator", "genescanner", "healthanalyzer", + "scanning_pad", + "vitals_monitor", "antibodyscanner", "med_spray_bottle", "medical_kiosk", @@ -437,8 +439,6 @@ "diseaseanalyzer", "centrifuge", "path_data", - "scanning_pad", - "vitals_monitor", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) discount_experiments = list(/datum/experiment/dissection/human = 1000) @@ -450,6 +450,7 @@ prereq_ids = list("biotech") design_ids = list( "crewpinpointer", + "vitals_monitor_advanced", "defibrillator_compact", "harvester", "healthanalyzer_advanced", @@ -461,7 +462,6 @@ "plasmarefiller", "smoke_machine", "sleeper", - "vitals_monitor_advanced", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) discount_experiments = list(/datum/experiment/scanning/random/material/meat = 2000, From 4872f1bb4071bb7f10bffe4af8f7b95832021119 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 10 Sep 2024 23:00:20 -0700 Subject: [PATCH 011/158] tasers --- _maps/map_files/Blueshift/Blueshift.dmm | 3 +++ _maps/map_files/BoxStation/BoxStation.dmm | 3 +++ _maps/map_files/Deltastation/DeltaStation2.dmm | 3 +++ _maps/map_files/IceBoxStation/IceBoxStation.dmm | 3 +++ _maps/map_files/KiloStation/KiloStation.dmm | 3 +++ _maps/map_files/MetaStation/MetaStation.dmm | 3 +++ _maps/map_files/Ouroboros/Ouroboros.dmm | 3 +++ _maps/map_files/Voidraptor/VoidRaptor.dmm | 11 ++++------- _maps/map_files/tramstation/tramstation.dmm | 3 +++ code/game/objects/items/storage/holsters.dm | 4 ++++ code/modules/jobs/job_types/warden.dm | 2 +- 11 files changed, 33 insertions(+), 8 deletions(-) diff --git a/_maps/map_files/Blueshift/Blueshift.dmm b/_maps/map_files/Blueshift/Blueshift.dmm index 9c931e4eae42..4544d9086455 100644 --- a/_maps/map_files/Blueshift/Blueshift.dmm +++ b/_maps/map_files/Blueshift/Blueshift.dmm @@ -30529,6 +30529,9 @@ /obj/effect/turf_decal/trimline/red/line{ dir = 8 }, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, /turf/open/floor/iron/dark/textured, /area/station/ai_monitored/security/armory) "fRF" = ( diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 1f1bce7a8fde..3bb917e361f0 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -25533,6 +25533,9 @@ pixel_x = 3; pixel_y = -3 }, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) "iuJ" = ( diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index b70950e0f9ad..f2b271188f07 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -51905,6 +51905,9 @@ /obj/structure/window/reinforced/spawner/directional/east{ pixel_x = 3 }, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) "mnW" = ( diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 87f88a4b72be..e43aee34741b 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -2626,6 +2626,9 @@ /obj/item/gun/ballistic/automatic/pistol/paco/no_mag{ pixel_y = 0 }, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, /turf/open/floor/iron/dark/textured, /area/station/ai_monitored/security/armory/upper) "aSS" = ( diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm index 248775bfc7eb..5488102be019 100644 --- a/_maps/map_files/KiloStation/KiloStation.dmm +++ b/_maps/map_files/KiloStation/KiloStation.dmm @@ -17099,6 +17099,9 @@ /obj/structure/window/reinforced/spawner/directional/south, /obj/structure/window/reinforced/spawner/directional/west, /obj/effect/turf_decal/tile/neutral/anticorner/contrasted, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, /turf/open/floor/iron/dark/textured_large, /area/station/ai_monitored/security/armory) "fuX" = ( diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 775eb74f145f..8b922d729a98 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -28530,6 +28530,9 @@ /obj/item/gun/ballistic/automatic/pistol/paco/no_mag{ pixel_y = 6 }, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) "kaF" = ( diff --git a/_maps/map_files/Ouroboros/Ouroboros.dmm b/_maps/map_files/Ouroboros/Ouroboros.dmm index 0b7b079e0b61..a934ee2ddf1b 100644 --- a/_maps/map_files/Ouroboros/Ouroboros.dmm +++ b/_maps/map_files/Ouroboros/Ouroboros.dmm @@ -39418,6 +39418,9 @@ c_tag = "Security - Armory" }, /obj/effect/spawner/random/armory/disablers, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, /turf/open/floor/engine, /area/station/ai_monitored/security/armory) "lEB" = ( diff --git a/_maps/map_files/Voidraptor/VoidRaptor.dmm b/_maps/map_files/Voidraptor/VoidRaptor.dmm index a595bbd17597..87141de5b2e9 100644 --- a/_maps/map_files/Voidraptor/VoidRaptor.dmm +++ b/_maps/map_files/Voidraptor/VoidRaptor.dmm @@ -7068,7 +7068,6 @@ /turf/open/floor/engine, /area/station/science/ordnance/storage) "cfa" = ( -/obj/effect/decal/cleanable/blood/xtracks, /obj/machinery/door/window/brigdoor/left/directional/south{ name = "Secure Creature Pen"; req_access = list("xenobiology") @@ -44895,10 +44894,6 @@ /obj/effect/turf_decal/siding/wood, /turf/open/floor/wood/large, /area/station/security/courtroom) -"mIH" = ( -/obj/effect/decal/cleanable/blood/xtracks, -/turf/open/floor/engine, -/area/station/science/xenobiology) "mII" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 10 @@ -59279,6 +59274,9 @@ dir = 8 }, /obj/effect/turf_decal/delivery, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, /turf/open/floor/iron/dark/textured_large, /area/station/ai_monitored/security/armory) "qBR" = ( @@ -62888,7 +62886,6 @@ id = "Xtestlab"; name = "Test Chamber Blast Door" }, -/obj/effect/decal/cleanable/blood/xtracks, /obj/item/toy/toy_xeno, /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -105269,7 +105266,7 @@ kVR jRP abP nlj -mIH +uiw rCy cfa sYn diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 285de81e4303..e60a840321a5 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -41794,6 +41794,9 @@ }, /obj/structure/window/reinforced/spawner/directional/north, /obj/structure/window/reinforced/spawner/directional/south, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, +/obj/item/gun/energy/taser, /turf/open/floor/iron, /area/station/ai_monitored/security/armory) "mlW" = ( diff --git a/code/game/objects/items/storage/holsters.dm b/code/game/objects/items/storage/holsters.dm index 75f1e8b500b0..3c8fdb54e80c 100644 --- a/code/game/objects/items/storage/holsters.dm +++ b/code/game/objects/items/storage/holsters.dm @@ -26,6 +26,7 @@ /obj/item/gun/ballistic/revolver, /obj/item/gun/energy/e_gun/mini, /obj/item/gun/energy/disabler, + /obj/item/gun/energy/taser, /obj/item/gun/energy/dueling, /obj/item/food/grown/banana, /obj/item/gun/energy/laser/thermal, @@ -45,6 +46,7 @@ atom_storage.set_holdable(list( /obj/item/gun/energy/e_gun/mini, /obj/item/gun/energy/disabler, + /obj/item/gun/energy/taser, /obj/item/gun/energy/dueling, /obj/item/food/grown/banana, /obj/item/gun/energy/laser/thermal, @@ -102,6 +104,7 @@ /obj/item/ammo_box/magazine/toy/pistol, /obj/item/gun/energy/e_gun/mini, /obj/item/gun/energy/disabler, + /obj/item/gun/energy/taser, /obj/item/gun/energy/dueling, /obj/item/gun/energy/laser/thermal, /obj/item/gun/energy/laser/captain, @@ -179,6 +182,7 @@ /obj/item/gun/energy/recharge/ebow, /obj/item/gun/energy/e_gun/mini, /obj/item/gun/energy/disabler, + /obj/item/gun/energy/taser, /obj/item/gun/energy/dueling, /obj/item/gun/energy/laser/captain, /obj/item/gun/energy/e_gun/hos, diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm index 2179908c57d7..9e854555ce52 100644 --- a/code/modules/jobs/job_types/warden.dm +++ b/code/modules/jobs/job_types/warden.dm @@ -50,7 +50,7 @@ id_trim = /datum/id_trim/job/warden uniform = /obj/item/clothing/under/rank/security/warden suit = /obj/item/clothing/suit/armor/vest/warden/alt - suit_store = /obj/item/gun/energy/disabler + suit_store = /obj/item/gun/energy/taser backpack_contents = list( /obj/item/evidencebag = 1, ) From 007773a9abfacc2781a3603a169b64724030a09a Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 01:23:39 -0700 Subject: [PATCH 012/158] de-hardcodes sampler for blood_data --- .../code/modules/blood_datum/blood.dm | 72 +++++++++---------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/monkestation/code/modules/blood_datum/blood.dm b/monkestation/code/modules/blood_datum/blood.dm index f0d478624903..3cd58b6ac288 100644 --- a/monkestation/code/modules/blood_datum/blood.dm +++ b/monkestation/code/modules/blood_datum/blood.dm @@ -42,8 +42,41 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying) compatible_types |= type /// Gets data to pass to a reagent -/datum/blood_type/proc/get_blood_data(mob/living/sampled_from) - return null +/datum/blood_type/proc/get_blood_data(mob/living/sampler) + if(!iscarbon(sampler)) + return null + var/mob/living/carbon/sampled_from = sampler + + var/list/blood_data = list() + //set the blood data + blood_data["viruses"] = list() + + if(sampled_from.immune_system) + blood_data["immunity"] = sampled_from.immune_system.GetImmunity() + + for(var/datum/disease/disease as anything in sampled_from.diseases) + blood_data["viruses"] += disease.Copy() + + blood_data["blood_DNA"] = sampled_from.dna.unique_enzymes + blood_data["resistances"] = LAZYLISTDUPLICATE(sampled_from.disease_resistances) + + var/list/temp_chem = list() + for(var/datum/reagent/trace_chem as anything in sampled_from.reagents.reagent_list) + temp_chem[trace_chem.type] = trace_chem.volume + blood_data["trace_chem"] = list2params(temp_chem) + + blood_data["mind"] = sampled_from.mind || sampled_from.last_mind + blood_data["ckey"] = sampled_from.ckey || ckey(sampled_from.last_mind?.key) + blood_data["cloneable"] = !HAS_TRAIT_FROM(sampled_from, TRAIT_SUICIDED, REF(sampled_from)) + blood_data["blood_type"] = sampled_from.dna.human_blood_type + blood_data["gender"] = sampled_from.gender + blood_data["real_name"] = sampled_from.real_name + blood_data["features"] = sampled_from.dna.features + blood_data["factions"] = sampled_from.faction + blood_data["quirks"] = list() + for(var/datum/quirk/sample_quirk as anything in sampled_from.quirks) + blood_data["quirks"] += sample_quirk.type + return blood_data /** * Used to handle any unique facets of blood spawned of this blood type @@ -129,41 +162,6 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying) /// A base type for all blood used by humans (NOT humanoids), for organization's sake /datum/blood_type/crew/human -/datum/blood_type/crew/human/get_blood_data(mob/living/carbon/sampled_from) - if(!istype(sampled_from) || isnull(sampled_from.dna)) - return ..() - - var/list/blood_data = list() - //set the blood data - blood_data["viruses"] = list() - - if(sampled_from.immune_system) - blood_data["immunity"] = sampled_from.immune_system.GetImmunity() - - for(var/datum/disease/disease as anything in sampled_from.diseases) - blood_data["viruses"] += disease.Copy() - - blood_data["blood_DNA"] = sampled_from.dna.unique_enzymes - blood_data["resistances"] = LAZYLISTDUPLICATE(sampled_from.disease_resistances) - - var/list/temp_chem = list() - for(var/datum/reagent/trace_chem as anything in sampled_from.reagents.reagent_list) - temp_chem[trace_chem.type] = trace_chem.volume - blood_data["trace_chem"] = list2params(temp_chem) - - blood_data["mind"] = sampled_from.mind || sampled_from.last_mind - blood_data["ckey"] = sampled_from.ckey || ckey(sampled_from.last_mind?.key) - blood_data["cloneable"] = !HAS_TRAIT_FROM(sampled_from, TRAIT_SUICIDED, REF(sampled_from)) - blood_data["blood_type"] = sampled_from.dna.human_blood_type - blood_data["gender"] = sampled_from.gender - blood_data["real_name"] = sampled_from.real_name - blood_data["features"] = sampled_from.dna.features - blood_data["factions"] = sampled_from.faction - blood_data["quirks"] = list() - for(var/datum/quirk/sample_quirk as anything in sampled_from.quirks) - blood_data["quirks"] += sample_quirk.type - return blood_data - /datum/blood_type/crew/human/a_minus name = "A-" compatible_types = list( From bbb334e9d063e437359179ff0ff0b87805b5a26e Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 01:41:37 -0700 Subject: [PATCH 013/158] Update humans.dm --- code/game/objects/effects/decals/cleanable/humans.dm | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index c1ea447f78a6..f7fbd0418d44 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -356,17 +356,6 @@ update_appearance() return ..() -/obj/effect/decal/cleanable/blood/footprints/update_name(updates) - switch(footprint_sprite) - if(FOOTPRINT_SPRITE_CLAWS) - name = "clawprints" - if(FOOTPRINT_SPRITE_SHOES) - name = "footprints" - if(FOOTPRINT_SPRITE_PAWS) - name = "pawprints" - base_name = "dried [name]" - return ..() - /obj/effect/decal/cleanable/blood/footprints/update_desc(updates) desc = "WHOSE [uppertext(name)] ARE THESE?" return ..() From f57cf0538a324d7265e0a1b326db267ebef1decc Mon Sep 17 00:00:00 2001 From: Lucy Date: Wed, 11 Sep 2024 12:05:48 -0400 Subject: [PATCH 014/158] Fix this runtime that keeps getting spammed constantly --- .../code/modules/blood_datum/forensics_helpers.dm | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/monkestation/code/modules/blood_datum/forensics_helpers.dm b/monkestation/code/modules/blood_datum/forensics_helpers.dm index 6d6c5353cf22..3e7ee08b41e0 100644 --- a/monkestation/code/modules/blood_datum/forensics_helpers.dm +++ b/monkestation/code/modules/blood_datum/forensics_helpers.dm @@ -9,18 +9,19 @@ var/list/colors = list() var/list/all_dna = GET_ATOM_BLOOD_DNA(src) for(var/dna_sample in all_dna) - var/datum/blood_type/blood = GLOB.blood_types[all_dna[dna_sample]] - colors += blood.color - - var/final_color = pop(colors) - for(var/color in colors) - final_color = BlendRGB(final_color, color, 0.5) + colors += GLOB.blood_types[all_dna[dna_sample]]?.color + list_clear_nulls(colors) + var/final_color = COLOR_BLOOD + if(length(colors)) + final_color = pop(colors) + for(var/color in colors) + final_color = BlendRGB(final_color, color, 0.5) cached_blood_dna_color = final_color return final_color /obj/effect/decal/cleanable/blood/drip/get_blood_dna_color() var/list/all_dna = GET_ATOM_BLOOD_DNA(src) - return GLOB.blood_types[all_dna[all_dna[1]]]?.color + return GLOB.blood_types[all_dna[all_dna[1]]]?.color || COLOR_BLOOD /obj/effect/decal/cleanable/blood/add_blood_DNA(list/blood_DNA_to_add) var/first_dna = GET_ATOM_BLOOD_DNA_LENGTH(src) From d4e9b6ec6fb4652c73edf9f8b2a2814aa3c31159 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:41:58 -0700 Subject: [PATCH 015/158] Update ethereal.dm --- .../mob/living/carbon/human/species_type/ethereal.dm | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm index 72a502501443..d3a98c8af789 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm @@ -84,12 +84,14 @@ for(var/obj/item/bodypart/limb as anything in new_ethereal.bodyparts) if(limb.limb_id == SPECIES_ETHEREAL) limb.update_limb(is_creating = TRUE) + RegisterSignal(ethereal, COMSIG_HUMAN_ON_HANDLE_BLOOD, PROC_REF(blood)) /datum/species/ethereal/on_species_loss(mob/living/carbon/human/former_ethereal, datum/species/new_species, pref_load) UnregisterSignal(former_ethereal, COMSIG_ATOM_EMAG_ACT) UnregisterSignal(former_ethereal, COMSIG_ATOM_EMP_ACT) UnregisterSignal(former_ethereal, COMSIG_LIGHT_EATER_ACT) UnregisterSignal(former_ethereal, COMSIG_ATOM_AFTER_ATTACKEDBY) + UnregisterSignal(former_ethereal, COMSIG_HUMAN_ON_HANDLE_BLOOD) QDEL_NULL(ethereal_light) return ..() @@ -105,9 +107,14 @@ human_mob.dna.features["ethcolor"] = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)] -/datum/species/ethereal/spec_life(mob/living/carbon/human/ethereal, seconds_per_tick, times_fired) +/datum/species/ethereal/proc/slime_blood(mob/living/carbon/human/ethereal, seconds_per_tick, times_fired) + SIGNAL_HANDLER + if(ethereal.stat == DEAD) - return + return NONE + + . = HANDLE_BLOOD_NO_NUTRITION_DRAIN|HANDLE_BLOOD_NO_EFFECTS + adjust_charge(ethereal, -ETHEREAL_BLOOD_CHARGE_FACTOR * seconds_per_tick, TRUE) handle_charge(ethereal, seconds_per_tick, times_fired) From 8b5cb6f93021fcf181a8474833711603d09814a9 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:42:28 -0700 Subject: [PATCH 016/158] Update ethereal.dm --- .../modules/mob/living/carbon/human/species_type/ethereal.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm index d3a98c8af789..89f3222adf61 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm @@ -107,7 +107,7 @@ human_mob.dna.features["ethcolor"] = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)] -/datum/species/ethereal/proc/slime_blood(mob/living/carbon/human/ethereal, seconds_per_tick, times_fired) +/datum/species/ethereal/proc/blood(mob/living/carbon/human/ethereal, seconds_per_tick, times_fired) SIGNAL_HANDLER if(ethereal.stat == DEAD) From c7dc3ea22eb3e2c59c9cc74083edaab28e52b2dc Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:44:48 -0700 Subject: [PATCH 017/158] shit --- .../modules/mob/living/carbon/human/species_type/ethereal.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm index 89f3222adf61..b86eea4b080e 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm @@ -118,6 +118,8 @@ adjust_charge(ethereal, -ETHEREAL_BLOOD_CHARGE_FACTOR * seconds_per_tick, TRUE) handle_charge(ethereal, seconds_per_tick, times_fired) + return . + /datum/species/ethereal/proc/adjust_charge(mob/living/carbon/human/ethereal, amount, passive) if(passive) if(ethereal.blood_volume < ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE) //Do not apply the clamp if its below the passive reduction level(no infinite blood sorry) From ef309f01b6904b95df5461171b881be151987853 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:50:30 -0700 Subject: [PATCH 018/158] Update fryer_overhaul.dm --- .../code/modules/brewin_and_chewin/chewing/fryer_overhaul.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/fryer_overhaul.dm b/monkestation/code/modules/brewin_and_chewin/chewing/fryer_overhaul.dm index 9cdf1cd244ad..cdbda9067842 100644 --- a/monkestation/code/modules/brewin_and_chewin/chewing/fryer_overhaul.dm +++ b/monkestation/code/modules/brewin_and_chewin/chewing/fryer_overhaul.dm @@ -60,7 +60,7 @@ if(!basket) return for(var/obj/item/item as anything in basket.contents) - if(!QDELETED(item)) + if(!QDELETED(item) && !(item.type in GLOB.oilfry_blacklisted_items)) item.AddElement(/datum/element/fried_item, cook_time) if(user) basket.process_item(src, user, lower_quality_on_fail=CHEWIN_BASE_QUAL_REDUCTION, send_message=TRUE) From 051213e24a2c00b3916a708f04c37cd5ac4c52af Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:12:38 -0700 Subject: [PATCH 019/158] should be async --- .../modules/mob/living/carbon/human/species_type/ethereal.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm index b86eea4b080e..e959d149ab2b 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm @@ -115,8 +115,8 @@ . = HANDLE_BLOOD_NO_NUTRITION_DRAIN|HANDLE_BLOOD_NO_EFFECTS - adjust_charge(ethereal, -ETHEREAL_BLOOD_CHARGE_FACTOR * seconds_per_tick, TRUE) - handle_charge(ethereal, seconds_per_tick, times_fired) + INVOKE_ASYNC(src, adjust_charge(ethereal, -ETHEREAL_BLOOD_CHARGE_FACTOR * seconds_per_tick, TRUE)) + INVOKE_ASYNC(src, handle_charge(ethereal, seconds_per_tick, times_fired)) return . From 7ce76ecc34310e5c4d70146c3c68116dcb6c0de1 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:19:12 -0700 Subject: [PATCH 020/158] async's etheral blood and makes secondary state respect combat mode --- code/datums/interactions/intents.dm | 1 - .../modules/mob/living/carbon/human/species_type/ethereal.dm | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/code/datums/interactions/intents.dm b/code/datums/interactions/intents.dm index 493bff0f4dde..93076a7395c5 100644 --- a/code/datums/interactions/intents.dm +++ b/code/datums/interactions/intents.dm @@ -10,7 +10,6 @@ if(LAZYACCESS(modifiers, RIGHT_CLICK)) M.istate = ISTATE_SECONDARY - return switch (intent) if (INTENT_DISARM) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm index e959d149ab2b..99a7ab726aff 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm @@ -115,8 +115,8 @@ . = HANDLE_BLOOD_NO_NUTRITION_DRAIN|HANDLE_BLOOD_NO_EFFECTS - INVOKE_ASYNC(src, adjust_charge(ethereal, -ETHEREAL_BLOOD_CHARGE_FACTOR * seconds_per_tick, TRUE)) - INVOKE_ASYNC(src, handle_charge(ethereal, seconds_per_tick, times_fired)) + INVOKE_ASYNC(src, PROC_REF(adjust_charge), ethereal, -ETHEREAL_BLOOD_CHARGE_FACTOR * seconds_per_tick, TRUE) + INVOKE_ASYNC(src, PROC_REF(handle_charge), ethereal, seconds_per_tick, times_fired) return . From caf6d0e5d1c8a3619b23e2c533e9a1dee364a96a Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:58:39 -0700 Subject: [PATCH 021/158] whoops --- code/modules/mob/living/carbon/human/_species.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index f5b8cd5c7b89..3f05c7cc035c 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -519,6 +519,9 @@ GLOBAL_LIST_EMPTY(features_by_species) SHOULD_CALL_PARENT(TRUE) // Drop the items the new species can't wear SEND_SIGNAL(C, COMSIG_SPECIES_GAIN_PRE, src, old_species) + + if(C.dna.species.exotic_bloodtype) + C.dna.human_blood_type = exotic_bloodtype if((AGENDER in species_traits)) C.gender = PLURAL if(C.hud_used) From 11cae3e48369e6dd6df1821cb69d88f08520c1ed Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 18:09:31 -0700 Subject: [PATCH 022/158] some od tweaks --- .vscode/launch.json | 7 +++++++ code/controllers/master.dm | 2 ++ code/datums/wounds/_wounds.dm | 4 ++-- code/game/objects/items/crayons.dm | 4 ++-- code/game/objects/items/pet_carrier.dm | 4 ++-- code/modules/admin/permissionedit.dm | 2 +- code/modules/antagonists/blob/overmind.dm | 2 +- code/modules/antagonists/changeling/powers/fakedeath.dm | 2 +- code/modules/antagonists/heretic/knowledge/rust_lore.dm | 2 +- code/modules/antagonists/heretic/magic/ash_ascension.dm | 2 +- code/modules/antagonists/revolution/revolution.dm | 2 +- code/modules/client/verbs/ooc.dm | 2 +- code/modules/mob/dead/new_player/new_player.dm | 8 +++++--- code/modules/religion/sparring/sparring_contract.dm | 2 +- .../research/xenobiology/crossbreeding/_clothing.dm | 2 +- monkestation/code/modules/blueshift/items/badges.dm | 2 +- .../code/modules/brewin_and_chewin/brewing/bottles.dm | 2 +- tools/ci/od_lints.dm | 1 + 18 files changed, 32 insertions(+), 20 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index bf3a209531db..f41cbaa49440 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,6 +1,13 @@ { "version": "0.2.0", "configurations": [ + { + "type": "opendream", + "request": "launch", + "name": "OpenDream", + "preLaunchTask": "OpenDream: compile ${command:CurrentDME}", + "json_path": "${workspaceFolder}/${command:CurrentJson}" + }, { "type": "byond", "request": "launch", diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 5634f11b172c..25e6c813157e 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -234,6 +234,7 @@ GLOBAL_REAL(Master, /datum/controller/master) // Initialize subsystems. for (var/datum/controller/subsystem/subsystem in stage_sorted_subsystems[current_init_stage]) init_subsystem(subsystem) + #ifndef OPENDREAM if(world.system_type == MS_WINDOWS) var/ss_name = "[subsystem.name]" var/memory_summary = call_ext("memorystats", "get_memory_stats")() @@ -241,6 +242,7 @@ GLOBAL_REAL(Master, /datum/controller/master) var/string = "[ss_name] [memory_summary]" WRITE_FILE(file, string) + #endif CHECK_TICK current_initializing_subsystem = null diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm index e6fd7aabd20c..6a52753eef99 100644 --- a/code/datums/wounds/_wounds.dm +++ b/code/datums/wounds/_wounds.dm @@ -491,7 +491,7 @@ // check if we have a valid treatable tool if(potential_treater.tool_behaviour in treatable_tools) return TRUE - if(TOOL_CAUTERY in treatable_tools && potential_treater.get_temperature() && user == victim) // allow improvised cauterization on yourself without an aggro grab + if((TOOL_CAUTERY in treatable_tools) && potential_treater.get_temperature() && user == victim) // allow improvised cauterization on yourself without an aggro grab return TRUE // failing that, see if we're aggro grabbing them and if we have an item that works for aggro grabs only if(user.pulling == victim && user.grab_state >= GRAB_AGGRESSIVE && check_grab_treatments(potential_treater, user)) @@ -687,7 +687,7 @@ var/datum/wound_pregen_data/pregen_data = get_pregen_data() - if (WOUND_BLUNT in pregen_data.required_wounding_types && severity >= WOUND_SEVERITY_CRITICAL) + if ((WOUND_BLUNT in pregen_data.required_wounding_types) && severity >= WOUND_SEVERITY_CRITICAL) return WOUND_CRITICAL_BLUNT_DISMEMBER_BONUS // we only require mangled bone (T2 blunt), but if there's a critical blunt, we'll add 15% more /// Returns our pregen data, which is practically guaranteed to exist, so this proc can safely be used raw. diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 5e38a8be45da..b43e7c778a5c 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -351,7 +351,7 @@ . = TRUE if("select_stencil") var/stencil = params["item"] - if(stencil in all_drawables + randoms) + if(stencil in (all_drawables + randoms)) drawtype = stencil . = TRUE text_buffer = "" @@ -441,7 +441,7 @@ temp = "symbol" else if(drawing in drawings) temp = "drawing" - else if(drawing in graffiti|oriented) + else if(drawing in (graffiti|oriented)) temp = "graffiti" var/graf_rot diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm index b6bb9245449e..d938a619d46b 100644 --- a/code/game/objects/items/pet_carrier.dm +++ b/code/game/objects/items/pet_carrier.dm @@ -38,7 +38,7 @@ occupant_weight -= L.mob_size /obj/item/pet_carrier/handle_atom_del(atom/A) - if(A in occupants && isliving(A)) + if((A in occupants) && isliving(A)) var/mob/living/L = A occupants -= L occupant_weight -= L.mob_size @@ -180,7 +180,7 @@ add_occupant(target) /obj/item/pet_carrier/proc/add_occupant(mob/living/occupant) - if(occupant in occupants || !istype(occupant)) + if((occupant in occupants) || !istype(occupant)) return occupant.forceMove(src) occupants += occupant diff --git a/code/modules/admin/permissionedit.dm b/code/modules/admin/permissionedit.dm index 5544f90fb748..737afcbbb281 100644 --- a/code/modules/admin/permissionedit.dm +++ b/code/modules/admin/permissionedit.dm @@ -222,7 +222,7 @@ . = ckey(admin_key) if(!.) return FALSE - if(!admin_ckey && (. in GLOB.admin_datums+GLOB.deadmins)) + if(!admin_ckey && (. in (GLOB.admin_datums + GLOB.deadmins))) to_chat(usr, span_danger("[admin_key] is already an admin."), confidential = TRUE) return FALSE if(use_db) diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm index af4b9b466930..732f26945dbd 100644 --- a/code/modules/antagonists/blob/overmind.dm +++ b/code/modules/antagonists/blob/overmind.dm @@ -195,7 +195,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) if(isnull(guy_turf) || !is_station_level(guy_turf.z)) continue - if(live_guy in GLOB.overminds || (live_guy.pass_flags & PASSBLOB)) + if((live_guy in GLOB.overminds) || (live_guy.pass_flags & PASSBLOB)) continue var/area/blob_area = get_area(guy_turf) diff --git a/code/modules/antagonists/changeling/powers/fakedeath.dm b/code/modules/antagonists/changeling/powers/fakedeath.dm index ba29f7cf5cb7..e39880796518 100644 --- a/code/modules/antagonists/changeling/powers/fakedeath.dm +++ b/code/modules/antagonists/changeling/powers/fakedeath.dm @@ -121,7 +121,7 @@ return var/datum/antagonist/changeling/ling = user.mind?.has_antag_datum(/datum/antagonist/changeling) - if(QDELETED(ling) || !(src in ling.innate_powers + ling.purchased_powers)) // checking both innate and purchased for full coverage + if(QDELETED(ling) || !(src in (ling.innate_powers + ling.purchased_powers))) // checking both innate and purchased for full coverage return if(!HAS_TRAIT_FROM(user, TRAIT_DEATHCOMA, CHANGELING_TRAIT)) return diff --git a/code/modules/antagonists/heretic/knowledge/rust_lore.dm b/code/modules/antagonists/heretic/knowledge/rust_lore.dm index 63d503a8ed38..dbe9e4d77178 100644 --- a/code/modules/antagonists/heretic/knowledge/rust_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/rust_lore.dm @@ -378,7 +378,7 @@ max_dist = max(max_dist, get_dist(found_turf, centre) + 1) for(var/turf/nearby_turf as anything in spiral_range_turfs(max_dist, centre, FALSE)) - if(nearby_turf in rusted_turfs || is_type_in_typecache(nearby_turf, blacklisted_turfs)) + if((nearby_turf in rusted_turfs) || is_type_in_typecache(nearby_turf, blacklisted_turfs)) continue for(var/turf/line_turf as anything in get_line(nearby_turf, centre)) diff --git a/code/modules/antagonists/heretic/magic/ash_ascension.dm b/code/modules/antagonists/heretic/magic/ash_ascension.dm index 0de92c49c22e..7139d4e87204 100644 --- a/code/modules/antagonists/heretic/magic/ash_ascension.dm +++ b/code/modules/antagonists/heretic/magic/ash_ascension.dm @@ -148,7 +148,7 @@ if(L.can_block_magic()) L.visible_message(span_danger("The spell bounces off of [L]!"), span_danger("The spell bounces off of you!")) continue - if(L in hit_list || L == source) + if((L in hit_list) || L == source) continue hit_list += L L.adjustFireLoss(20) diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm index 85c7df3a7a3e..f43549932b46 100644 --- a/code/modules/antagonists/revolution/revolution.dm +++ b/code/modules/antagonists/revolution/revolution.dm @@ -541,7 +541,7 @@ if (!(player_mind.assigned_role.departments_bitflags & (DEPARTMENT_BITFLAG_SECURITY|DEPARTMENT_BITFLAG_COMMAND))) continue - if (player_mind in ex_revs + ex_headrevs) + if (player_mind in (ex_revs + ex_headrevs)) continue if (!istype(player)) diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index 9208c229e5b7..bc2b683882f2 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -55,7 +55,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") msg = emoji_parse(msg) - if(SSticker.HasRoundStarted() && (msg[1] in list(".",";",":","#") || findtext_char(msg, "say", 1, 5))) + if(SSticker.HasRoundStarted() && ((msg[1] in list(".",";",":","#")) || findtext_char(msg, "say", 1, 5))) if(tgui_alert(usr,"Your message \"[raw_msg]\" looks like it was meant for in game communication, say it in OOC?", "Meant for OOC?", list("Yes", "No")) != "Yes") return diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 18a4e63e6eda..11c84bb06776 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -285,9 +285,11 @@ if(QDELETED(src) || !client) return // Disconnected while checking for the appearance ban. if(!isAI(spawning_mob)) // Unfortunately there's still snowflake AI code out there. - mind.original_character_slot_index = client.prefs.default_slot - mind.transfer_to(spawning_mob) //won't transfer key since the mind is not active - mind.set_original_character(spawning_mob) + // transfer_to sets mind to null + var/datum/mind/preserved_mind = mind + preserved_mind.original_character_slot_index = client.prefs.default_slot + preserved_mind.transfer_to(spawning_mob) //won't transfer key since the mind is not active + preserved_mind.set_original_character(spawning_mob) client.init_verbs() . = spawning_mob new_character = . diff --git a/code/modules/religion/sparring/sparring_contract.dm b/code/modules/religion/sparring/sparring_contract.dm index 4f1f17e6837e..9238af61a397 100644 --- a/code/modules/religion/sparring/sparring_contract.dm +++ b/code/modules/religion/sparring/sparring_contract.dm @@ -84,7 +84,7 @@ if(!isnull(resolved)) resolved_opponents += resolved - if(user in resolved_opponents && params["stakes"] == STAKES_HOLY_MATCH) + if((user in resolved_opponents) && params["stakes"] == STAKES_HOLY_MATCH) to_chat(user, span_warning("This contract refuses to be signed up for a holy match by a previous holy match loser. Pick a different stake!")) //any updating of the terms should update the UI to display new terms diff --git a/code/modules/research/xenobiology/crossbreeding/_clothing.dm b/code/modules/research/xenobiology/crossbreeding/_clothing.dm index 4290f7a7a746..24439dc1b4f4 100644 --- a/code/modules/research/xenobiology/crossbreeding/_clothing.dm +++ b/code/modules/research/xenobiology/crossbreeding/_clothing.dm @@ -145,7 +145,7 @@ Slimecrossing Armor var/hit_reflect_chance = 40 /obj/item/clothing/suit/armor/heavy/adamantine/IsReflect(def_zone) - if(def_zone in list(BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) && prob(hit_reflect_chance)) + if((def_zone in list(BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)) && prob(hit_reflect_chance)) return TRUE else return FALSE diff --git a/monkestation/code/modules/blueshift/items/badges.dm b/monkestation/code/modules/blueshift/items/badges.dm index 50fc866d5fb6..940b1bb8a070 100644 --- a/monkestation/code/modules/blueshift/items/badges.dm +++ b/monkestation/code/modules/blueshift/items/badges.dm @@ -95,7 +95,7 @@ if(istype(object, /obj/item/card/id)) id_card = object - if(ACCESS_SECURITY in id_card.access || (obj_flags & EMAGGED)) + if((ACCESS_SECURITY in id_card.access) || (obj_flags & EMAGGED)) to_chat(user, "You imprint your ID details onto the badge.") set_name(user.real_name) badge_string = id_card.assignment diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/bottles.dm b/monkestation/code/modules/brewin_and_chewin/brewing/bottles.dm index bb7157e2ec16..e124d7800ed0 100644 --- a/monkestation/code/modules/brewin_and_chewin/brewing/bottles.dm +++ b/monkestation/code/modules/brewin_and_chewin/brewing/bottles.dm @@ -9,7 +9,7 @@ /obj/item/reagent_containers/cup/glass/bottle/small/brewing_bottle/afterattack(atom/target, mob/user, proximity_flag, click_parameters) . = ..() - if(target.type in typesof(/obj/item/reagent_containers/cup/glass) - typesof(/obj/item/reagent_containers/cup/glass/bottle)) + if(target.type in (typesof(/obj/item/reagent_containers/cup/glass) - typesof(/obj/item/reagent_containers/cup/glass/bottle))) if(glass_name) target.name = glass_name if(glass_desc) diff --git a/tools/ci/od_lints.dm b/tools/ci/od_lints.dm index e339f5acb2d7..ad231fe9c8da 100644 --- a/tools/ci/od_lints.dm +++ b/tools/ci/od_lints.dm @@ -31,3 +31,4 @@ #pragma UnsafeClientAccess disabled #pragma SuspiciousSwitchCase error #pragma AssignmentInConditional error +#pragma AmbiguousInOrder error From 74bf6db8a0151500151a03f2cd77858e2a8b5549 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 23:31:07 -0700 Subject: [PATCH 023/158] tweakin --- code/__DEFINES/DNA.dm | 7 +- code/__DEFINES/mobs.dm | 3 + .../traits/monkestation/declarations.dm | 1 + code/__DEFINES/~monkestation/chewin.dm | 9 +- code/__HELPERS/global_lists.dm | 4 + code/__HELPERS/mobs.dm | 16 ++ code/datums/dna.dm | 24 +++ code/modules/mob/living/carbon/carbon.dm | 7 + .../mob/living/carbon/human/_species.dm | 4 - .../carbon/human/species_types/golems.dm | 6 - .../carbon/human/species_types/mushpeople.dm | 1 - .../carbon/human/species_types/snail.dm | 1 - .../carbon/human/species_types/zombies.dm | 8 +- code/modules/movespeed/modifiers/innate.dm | 2 +- code/modules/surgery/bodyparts/_bodyparts.dm | 6 + .../surgery/bodyparts/dismemberment.dm | 6 + .../bodyparts/species_parts/misc_bodyparts.dm | 17 +++ .../clock_cult/mobs/clockwork_golem.dm | 1 - .../chewing/cooking_containers.dm | 4 +- .../modules/mob/living/carbon/human/human.dm | 6 + .../carbon/human/species_type/arachnid.dm | 1 - .../carbon/human/species_type/floran.dm | 1 - .../carbon/human/species_type/goblin.dm | 3 +- .../carbon/human/species_type/simian.dm | 1 - .../code/modules/ranching/satyr/species.dm | 1 - .../surgery/bodyparts/arachnid_bodyparts.dm | 2 + .../surgery/bodyparts/floran_bodyparts.dm | 2 + .../surgery/bodyparts/simian_bodyparts.dm | 2 + .../the_bird_inside_of_me/icons/armwings.dmi | Bin 0 -> 1354 bytes .../icons/ornithid_parts_greyscale.dmi | Bin 0 -> 927 bytes .../icons/ornithidfeatures.dmi | Bin 0 -> 613 bytes .../modules/the_bird_inside_of_me/language.dm | 9 ++ .../modules/the_bird_inside_of_me/organs.dm | 4 + .../modules/the_bird_inside_of_me/plummage.dm | 47 ++++++ .../modules/the_bird_inside_of_me/prefs.dm | 132 ++++++++++++++++ .../modules/the_bird_inside_of_me/species.dm | 144 ++++++++++++++++++ .../modules/the_bird_inside_of_me/tails.dm | 36 +++++ .../modules/the_bird_inside_of_me/wings.dm | 85 +++++++++++ .../the_wolf_inside_of_me/bodyparts.dm | 129 ++++++++++++++++ .../icons/mutant_bodyparts.dmi | Bin 0 -> 5374 bytes .../icons/werewolf_parts_greyscale.dmi | Bin 0 -> 1578 bytes .../modules/the_wolf_inside_of_me/organs.dm | 86 +++++++++++ .../modules/the_wolf_inside_of_me/species.dm | 74 +++++++++ tgstation.dme | 10 ++ .../tgui/interfaces/PersonalCrafting.tsx | 86 ++++++++--- 45 files changed, 936 insertions(+), 52 deletions(-) create mode 100644 monkestation/code/modules/the_bird_inside_of_me/icons/armwings.dmi create mode 100644 monkestation/code/modules/the_bird_inside_of_me/icons/ornithid_parts_greyscale.dmi create mode 100644 monkestation/code/modules/the_bird_inside_of_me/icons/ornithidfeatures.dmi create mode 100644 monkestation/code/modules/the_bird_inside_of_me/language.dm create mode 100644 monkestation/code/modules/the_bird_inside_of_me/organs.dm create mode 100644 monkestation/code/modules/the_bird_inside_of_me/plummage.dm create mode 100644 monkestation/code/modules/the_bird_inside_of_me/prefs.dm create mode 100644 monkestation/code/modules/the_bird_inside_of_me/species.dm create mode 100644 monkestation/code/modules/the_bird_inside_of_me/tails.dm create mode 100644 monkestation/code/modules/the_bird_inside_of_me/wings.dm create mode 100644 monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm create mode 100644 monkestation/code/modules/the_wolf_inside_of_me/icons/mutant_bodyparts.dmi create mode 100644 monkestation/code/modules/the_wolf_inside_of_me/icons/werewolf_parts_greyscale.dmi create mode 100644 monkestation/code/modules/the_wolf_inside_of_me/organs.dm create mode 100644 monkestation/code/modules/the_wolf_inside_of_me/species.dm diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index ed8b47ddadd7..a93b10eebd68 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -40,7 +40,7 @@ #define DNA_UNI_IDENTITY_BLOCKS 7 /// This number needs to equal the total number of DNA blocks -#define DNA_FEATURE_BLOCKS 16 +#define DNA_FEATURE_BLOCKS 20 #define DNA_MUTANT_COLOR_BLOCK 1 #define DNA_ETHEREAL_COLOR_BLOCK 2 @@ -58,6 +58,10 @@ #define DNA_MUSHROOM_CAPS_BLOCK 14 #define DNA_POD_HAIR_BLOCK 15 #define DNA_MUTANT_COLOR_SECONDARY 16 +#define DNA_ARM_WINGS_BLOCK 17 // NON-MODULE CHANGE +#define DNA_AVIAN_EARS_BLOCK 18 // NON-MODULE CHANGE +#define DNA_AVIAN_TAIL_BLOCK 19 // NON-MODULE CHANGE +#define DNA_FEATHER_COLOR_BLOCK 20 // NON-MODULE CHANGE #define DNA_SEQUENCE_LENGTH 4 #define DNA_MUTATION_BLOCKS 8 @@ -145,6 +149,7 @@ #define ORGAN_SLOT_EXTERNAL_ANIME_BOTTOM "anime_bottom" #define ORGAN_SLOT_EXTERNAL_FLORAN_LEAVES "floran_leaves" #define ORGAN_SLOT_EXTERNAL_FLUFF "fluff" +#define ORGAN_SLOT_EXTERNAL_FEATHERS "feathers" /// Xenomorph organ slots #define ORGAN_SLOT_XENO_ACIDGLAND "acid_gland" diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index fb0c39de245c..c0c31d3d2cc6 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -133,6 +133,9 @@ #define SPECIES_GOBLIN "goblin" //Monkestation Addition #define SPECIES_FLORAN "floran" //Monkestation Addition #define SPECIES_SATYR "satyr" //Monkestation Addition +#define SPECIES_WEREWOLF "werewolf" //Monkestation Addition +#define SPECIES_ORNITHID "ornithid" + // Like species IDs, but not specifically attached a species. #define BODYPART_ID_ALIEN "alien" #define BODYPART_ID_ROBOTIC "robotic" diff --git a/code/__DEFINES/traits/monkestation/declarations.dm b/code/__DEFINES/traits/monkestation/declarations.dm index 9d169df39be1..83f853963f2a 100644 --- a/code/__DEFINES/traits/monkestation/declarations.dm +++ b/code/__DEFINES/traits/monkestation/declarations.dm @@ -127,4 +127,5 @@ /// Has an item been enchanted by a clock cult Stargazer? #define TRAIT_STARGAZED "stargazed" +#define TRAIT_FEATHERED "feathers" // END TRAIT DEFINES diff --git a/code/__DEFINES/~monkestation/chewin.dm b/code/__DEFINES/~monkestation/chewin.dm index 980bcb76b964..75b635b5b9b4 100644 --- a/code/__DEFINES/~monkestation/chewin.dm +++ b/code/__DEFINES/~monkestation/chewin.dm @@ -64,21 +64,18 @@ #define PLATE "plate" #define CUTTING_BOARD "cutting board" #define PAN "pan" -#define POT "pot" -#define BOWL "bowl" +#define POT "cooking pot" +#define BOWL "mixing bowl" #define DF_BASKET "deep fryer basket" #define AF_BASKET "air fryer basket" #define OVEN "oven" -#define GRILL "grill" +#define GRILL "grill grate" //Stove temp settings. #define J_LO "Low" #define J_MED "Medium" #define J_HI "High" -//Just a catalog for the cooking catalog -#define CATALOG_COOKING "cooking" - //Burn times for cooking things on a stove. //Anything put on a stove for this long becomes a burned mess. #define CHEWIN_BURN_TIME_LOW 15 MINUTES diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index c6b4e280eed3..b9241abe78a7 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -52,6 +52,10 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/satyr_fluff, GLOB.satyr_fluff_list) //Monkestation Addition init_sprite_accessory_subtypes(/datum/sprite_accessory/satyr_tail, GLOB.satyr_tail_list) //Monkestation Addition init_sprite_accessory_subtypes(/datum/sprite_accessory/satyr_horns, GLOB.satyr_horns_list) //Monkestation Addition + init_sprite_accessory_subtypes(/datum/sprite_accessory/arm_wings, GLOB.arm_wings_list) //NON-MODULE CHANGE + init_sprite_accessory_subtypes(/datum/sprite_accessory/arm_wingsopen, GLOB.arm_wingsopen_list) //NON-MODULE CHANGE + init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/avian, GLOB.tails_list_avian) //NON-MODULE CHANGE + init_sprite_accessory_subtypes(/datum/sprite_accessory/plumage, GLOB.avian_ears_list) //NON-MODULE CHANGE /// Inits GLOB.species_list. Not using GLOBAL_LIST_INIT b/c it depends on GLOB.string_lists /proc/init_species_list() diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 32ee82b6d9f8..cf31c2fa754f 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -89,6 +89,10 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_markings, GLOB.moth_markings_list) if(!length(GLOB.pod_hair_list)) init_sprite_accessory_subtypes(/datum/sprite_accessory/pod_hair, GLOB.pod_hair_list) + if(!length(GLOB.pod_hair_list)) + init_sprite_accessory_subtypes(/datum/sprite_accessory/pod_hair, GLOB.pod_hair_list) + if(!length(GLOB.pod_hair_list)) + init_sprite_accessory_subtypes(/datum/sprite_accessory/pod_hair, GLOB.pod_hair_list) //Monkestation Addition Start if(!length(GLOB.ethereal_horns_list)) init_sprite_accessory_subtypes(/datum/sprite_accessory/ethereal_horns, GLOB.ethereal_horns_list) @@ -126,6 +130,14 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/satyr_tail, GLOB.satyr_tail_list) if(!GLOB.satyr_horns_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/satyr_horns, GLOB.satyr_horns_list) + if(!length(GLOB.arm_wings_list)) + init_sprite_accessory_subtypes(/datum/sprite_accessory/arm_wings, GLOB.arm_wings_list) + if(!length(GLOB.arm_wingsopen_list)) + init_sprite_accessory_subtypes(/datum/sprite_accessory/arm_wingsopen, GLOB.arm_wingsopen_list) + if(!length(GLOB.tails_list_avian)) + init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/avian, GLOB.tails_list_avian) + if(!length(GLOB.avian_ears_list)) + init_sprite_accessory_subtypes(/datum/sprite_accessory/plumage, GLOB.avian_ears_list) //Monkestation Addition End //For now we will always return none for tail_human and ears. | "For now" he says. @@ -167,6 +179,10 @@ "satyr_fluff" = pick(GLOB.satyr_fluff_list), //Monkestation Addition "satyr_tail" = pick(GLOB.satyr_tail_list), //Monkestation Addition "satyr_horns" = pick(GLOB.satyr_horns_list), //Monkestation Addition + "arm_wings" = pick(GLOB.arm_wings_list), + "ears_avian" = pick(GLOB.avian_ears_list), + "tail_avian" = pick(GLOB.tails_list_avian), + "feathers" = "#[pick("7F","FF")][pick("7F","FF")][pick("7F","FF")]", )) /proc/random_hairstyle(gender) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 6a4b152ddb84..935f68e9595a 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -229,6 +229,14 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) L[DNA_MUSHROOM_CAPS_BLOCK] = construct_block(GLOB.caps_list.Find(features["caps"]), GLOB.caps_list.len) if(features["pod_hair"]) L[DNA_POD_HAIR_BLOCK] = construct_block(GLOB.pod_hair_list.Find(features["pod_hair"]), GLOB.pod_hair_list.len) + if(features["arm_wings"]) // NON-MODULE CHANGE + L[DNA_ARM_WINGS_BLOCK] = construct_block(GLOB.arm_wings_list.Find(features["arm_wings"]), GLOB.arm_wings_list.len) + if(features["tail_avian"]) // NON-MODULE CHANGE + L[DNA_AVIAN_TAIL_BLOCK] = construct_block(GLOB.tails_list_avian.Find(features["tail_avian"]), GLOB.tails_list_avian.len) + if(features["ears_avian"]) // NON-MODULE CHANGE + L[DNA_AVIAN_EARS_BLOCK] = construct_block(GLOB.avian_ears_list.Find(features["ears_avian"]), GLOB.avian_ears_list.len) + if(features["feathers"]) // NON-MODULE CHANGE + L[DNA_FEATHER_COLOR_BLOCK] = sanitize_hexcolor(features["feathers"], include_crunch = FALSE) for(var/blocknum in 1 to DNA_FEATURE_BLOCKS) . += L[blocknum] || random_string(GET_UI_BLOCK_LEN(blocknum), GLOB.hex_characters) @@ -363,6 +371,14 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) set_uni_feature_block(blocknumber, construct_block(GLOB.caps_list.Find(features["caps"]), GLOB.caps_list.len)) if(DNA_POD_HAIR_BLOCK) set_uni_feature_block(blocknumber, construct_block(GLOB.pod_hair_list.Find(features["pod_hair"]), GLOB.pod_hair_list.len)) + if(DNA_ARM_WINGS_BLOCK) // NON-MODULE CHANGE + set_uni_feature_block(blocknumber, construct_block(GLOB.arm_wings_list.Find(features["arm_wings"]), GLOB.arm_wings_list.len)) + if(DNA_AVIAN_TAIL_BLOCK) // NON-MODULE CHANGE + set_uni_feature_block(blocknumber, construct_block(GLOB.tails_list_avian.Find(features["tail_avian"]), GLOB.tails_list_avian.len)) + if(DNA_AVIAN_EARS_BLOCK) // NON-MODULE CHANGE + set_uni_feature_block(blocknumber, construct_block(GLOB.avian_ears_list.Find(features["ears_avian"]), GLOB.avian_ears_list.len)) + if(DNA_FEATHER_COLOR_BLOCK) // NON-MODULE CHANGE + set_uni_feature_block(blocknumber, sanitize_hexcolor(features["feathers"], include_crunch = FALSE)) //Please use add_mutation or activate_mutation instead /datum/dna/proc/force_give(datum/mutation/human/human_mutation) @@ -640,6 +656,14 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) dna.features["caps"] = GLOB.caps_list[deconstruct_block(get_uni_feature_block(features, DNA_MUSHROOM_CAPS_BLOCK), GLOB.caps_list.len)] if(dna.features["pod_hair"]) dna.features["pod_hair"] = GLOB.pod_hair_list[deconstruct_block(get_uni_feature_block(features, DNA_POD_HAIR_BLOCK), GLOB.pod_hair_list.len)] + if(dna.features["arm_wings"]) // NON-MODULE CHANGE + dna.features["arm_wings"] = GLOB.arm_wings_list[deconstruct_block(get_uni_feature_block(features, DNA_ARM_WINGS_BLOCK), GLOB.arm_wings_list.len)] + if(dna.features["tail_avian"]) // NON-MODULE CHANGE + dna.features["tail_avian"] = GLOB.tails_list_avian[deconstruct_block(get_uni_feature_block(features, DNA_AVIAN_TAIL_BLOCK), GLOB.tails_list_avian.len)] + if(dna.features["ears_avian"]) // NON-MODULE CHANGE + dna.features["ears_avian"] = GLOB.avian_ears_list[deconstruct_block(get_uni_feature_block(features, DNA_AVIAN_EARS_BLOCK), GLOB.avian_ears_list.len)] + if(dna.features["feathers"]) // NON-MODULE CHANGE + dna.features["feathers"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_FEATHER_COLOR_BLOCK)) for(var/obj/item/organ/external/external_organ in organs) external_organ.mutate_feature(features, src) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 5a0325146bbd..8d6770947b0d 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1039,6 +1039,13 @@ set_usable_hands(usable_hands - 1) +///Updates the bodypart speed modifier based on our bodyparts. +/mob/living/carbon/proc/update_bodypart_speed_modifier() + var/final_modification = 0 + for(var/obj/item/bodypart/bodypart as anything in bodyparts) + final_modification += bodypart.speed_modifier + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/bodypart, TRUE, final_modification) + /mob/living/carbon/proc/create_internal_organs() for(var/obj/item/organ/internal/internal_organ in organs) internal_organ.Insert(src) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 3f05c7cc035c..cc6e107f313a 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -108,8 +108,6 @@ GLOBAL_LIST_EMPTY(features_by_species) ///List of external organs to generate like horns, frills, wings, etc. list(typepath of organ = "Round Beautiful BDSM Snout"). Still WIP var/list/external_organs = list() - ///Multiplier for the race's speed. Positive numbers make it move slower, negative numbers make it move faster. - var/speedmod = 0 ///Percentage modifier for overall defense of the race, or less defense, if it's negative. var/armor = 0 ///multiplier for brute damage @@ -571,7 +569,6 @@ GLOBAL_LIST_EMPTY(features_by_species) for(var/i in inherent_factions) C.faction += i //Using +=/-= for this in case you also gain the faction from a different source. - C.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, multiplicative_slowdown=speedmod) C.maxHealth = C.maxHealth * maxhealthmod SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species) @@ -617,7 +614,6 @@ GLOBAL_LIST_EMPTY(features_by_species) clear_tail_moodlets(C) - C.remove_movespeed_modifier(/datum/movespeed_modifier/species) C.maxHealth = C.maxHealth / maxhealthmod SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index f82fdd44d8b5..bb6a364807a2 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -23,7 +23,6 @@ mutantlungs = null inherent_biotypes = MOB_HUMANOID|MOB_MINERAL mutant_organs = list(/obj/item/organ/internal/adamantine_resonator) - speedmod = 2 payday_modifier = 0.75 armor = 55 siemens_coeff = 0 @@ -187,7 +186,6 @@ name = "Gold Golem" id = SPECIES_GOLEM_GOLD fixed_mut_color = "#cccc00" - speedmod = 1 armor = 25 //down from 55 meat = /obj/item/stack/ore/gold info_text = "As a Gold Golem, you are faster but less resistant than the average golem." @@ -220,7 +218,6 @@ id = SPECIES_GOLEM_PLASTEEL fixed_mut_color = "#bbbbbb" stunmod = 0.4 - speedmod = 4 //pretty fucking slow meat = /obj/item/stack/ore/iron info_text = "As a Plasteel Golem, you are slower, but harder to stun, and hit very hard when punching. You also magnetically attach to surfaces and so don't float without gravity and cannot have positions swapped with other beings." prefix = "Plasteel" @@ -293,7 +290,6 @@ fixed_mut_color = "#333333" meat = /obj/item/stack/sheet/mineral/abductor mutanttongue = /obj/item/organ/internal/tongue/abductor - speedmod = 1 //faster info_text = "As an Alloy Golem, you are made of advanced alien materials: you are faster and regenerate over time. You are, however, only able to be heard by other alloy golems." prefix = "Alien" special_names = list("Outsider", "Technology", "Watcher", "Stranger") //ominous and unknown @@ -760,7 +756,6 @@ inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID armor = 15 //feels no pain, but not too resistant burnmod = 2 // don't get burned - speedmod = 1 // not as heavy as stone prefix = "Cloth" special_names = null bodypart_overrides = list( @@ -1030,7 +1025,6 @@ armor = 25 burnmod = 1.25 heatmod = 2 - speedmod = 1.5 bodypart_overrides = list( BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/golem/cardboard, BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/golem/cardboard, diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm index 73c3657abae0..7a3bf8ef78f1 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -17,7 +17,6 @@ TRAIT_NOFLASH, ) inherent_factions = list(FACTION_MUSHROOM) - speedmod = 1.5 //faster than golems but not by much no_equip_flags = ITEM_SLOT_MASK | ITEM_SLOT_OCLOTHING | ITEM_SLOT_GLOVES | ITEM_SLOT_FEET | ITEM_SLOT_ICLOTHING diff --git a/code/modules/mob/living/carbon/human/species_types/snail.dm b/code/modules/mob/living/carbon/human/species_types/snail.dm index 0c66cd7bbe6e..f812610ffb42 100644 --- a/code/modules/mob/living/carbon/human/species_types/snail.dm +++ b/code/modules/mob/living/carbon/human/species_types/snail.dm @@ -11,7 +11,6 @@ coldmod = 0.5 //snails only come out when its cold and wet burnmod = 2 - speedmod = 6 siemens_coeff = 2 //snails are mostly water changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | RACE_SWAP sexes = FALSE //snails are hermaphrodites diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index b7f9b81de523..ee513f5feb03 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -4,7 +4,7 @@ // 1spooky name = "High-Functioning Zombie" id = SPECIES_ZOMBIE - sexes = 0 + sexes = FALSE meat = /obj/item/food/meat/slab/human/mutant/zombie mutanttongue = /obj/item/organ/internal/tongue/zombie species_traits = list( @@ -44,13 +44,14 @@ bodytemp_heat_damage_limit = FIRE_MINIMUM_TEMPERATURE_TO_EXIST // Take damage at fire temp bodytemp_cold_damage_limit = MINIMUM_TEMPERATURE_TO_MOVE // take damage below minimum movement temp + // Infectious zombies have slow legs bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/zombie, BODY_ZONE_CHEST = /obj/item/bodypart/chest/zombie, BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/zombie, BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/zombie, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/zombie, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/zombie + BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/zombie/infectious, + BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/zombie/infectious, ) /// Zombies do not stabilize body temperature they are the walking dead and are cold blooded @@ -86,7 +87,6 @@ id = SPECIES_ZOMBIE_INFECTIOUS examine_limb_id = SPECIES_ZOMBIE armor = 20 // 120 damage to KO a zombie, which kills it - speedmod = 1.6 mutanteyes = /obj/item/organ/internal/eyes/zombie mutantbrain = /obj/item/organ/internal/brain/zombie mutanttongue = /obj/item/organ/internal/tongue/zombie diff --git a/code/modules/movespeed/modifiers/innate.dm b/code/modules/movespeed/modifiers/innate.dm index 46fc82269eac..2a55b9db4d79 100644 --- a/code/modules/movespeed/modifiers/innate.dm +++ b/code/modules/movespeed/modifiers/innate.dm @@ -6,7 +6,7 @@ multiplicative_slowdown = 2 flags = IGNORE_NOSLOW -/datum/movespeed_modifier/species +/datum/movespeed_modifier/bodypart movetypes = ~FLYING variable = TRUE diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 764ac9e05367..9cd09928665a 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -66,6 +66,8 @@ var/list/embedded_objects = list() /// are we a hand? if so, which one! var/held_index = 0 + /// A speed modifier we apply to the owner when attached, if any. Positive numbers make it move slower, negative numbers make it move faster. + var/speed_modifier = 0 // Limb disabling variables ///Controls if the limb is disabled. TRUE means it is disabled (similar to being removed, but still present for the sake of targeted interactions). @@ -763,6 +765,8 @@ owner = new_owner var/needs_update_disabled = FALSE //Only really relevant if there's an owner if(old_owner) + if(speed_modifier) + old_owner.update_bodypart_speed_modifier() if(initial(can_be_disabled)) if(HAS_TRAIT(old_owner, TRAIT_NOLIMBDISABLE)) if(!owner || !HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) @@ -776,6 +780,8 @@ )) UnregisterSignal(old_owner, COMSIG_ATOM_RESTYLE) if(owner) + if(speed_modifier) + owner.update_bodypart_speed_modifier() if(initial(can_be_disabled)) if(HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) set_can_be_disabled(FALSE) diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index d732da816693..bec42b32b08c 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -77,6 +77,8 @@ //limb is out and about, it can't really be considered an implant bodypart_flags &= ~BODYPART_IMPLANTED owner.remove_bodypart(src) + if(speed_modifier) + owner.update_bodypart_speed_modifier() for(var/datum/wound/wound as anything in wounds) wound.remove_wound(TRUE) @@ -261,6 +263,7 @@ new_arm_owner.update_worn_gloves() + /obj/item/bodypart/leg/drop_limb(special, dismembered, violent) if(owner && !special) if(owner.legcuffed) @@ -340,6 +343,9 @@ hand.update_appearance() new_limb_owner.update_worn_gloves() + if(speed_modifier) + new_limb_owner.update_bodypart_speed_modifier() + LAZYREMOVE(new_limb_owner.body_zone_dismembered_by, body_zone) if(special) //non conventional limb attachment diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index 3522df549ea8..144a77d63e0f 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -23,9 +23,22 @@ /obj/item/bodypart/leg/left/snail limb_id = SPECIES_SNAIL unarmed_damage_high = 0.5 + speed_modifier = 3 //disgustingly slow + /obj/item/bodypart/leg/right/snail limb_id = SPECIES_SNAIL unarmed_damage_high = 0.5 + speed_modifier = 3 //disgustingly slow + +/obj/item/bodypart/leg/left/zombie/infectious + limb_id = SPECIES_ZOMBIE + should_draw_greyscale = FALSE + speed_modifier = 0.8 //braaaaains + +/obj/item/bodypart/leg/right/zombie/infectious + limb_id = SPECIES_ZOMBIE + should_draw_greyscale = FALSE + speed_modifier = 0.8 //braaaaains ///ABDUCTOR /obj/item/bodypart/head/abductor @@ -333,12 +346,14 @@ unarmed_damage_low = 15 unarmed_damage_high = 15 unarmed_stun_threshold = 14 + speed_modifier = 0.75 //big fungus big fungus /obj/item/bodypart/leg/right/mushroom limb_id = SPECIES_MUSHROOM unarmed_damage_low = 15 unarmed_damage_high = 15 unarmed_stun_threshold = 14 + speed_modifier = 0.75 //big fungus big fungus ///GOLEMS (i hate xenobio SO FUCKING MUCH) (from 2022: Yeah I fucking feel your pain brother) (2024: yeah this is shit) /obj/item/bodypart/head/golem @@ -408,6 +423,7 @@ unarmed_damage_low = 11 unarmed_damage_high = 11 unarmed_stun_threshold = 11 + speed_modifier = 1.5 /obj/item/bodypart/leg/right/golem biological_state = (BIO_BONE|BIO_JOINTED) @@ -417,6 +433,7 @@ unarmed_damage_low = 11 unarmed_damage_high = 11 unarmed_stun_threshold = 11 + speed_modifier = 1.5 ///CULT GOLEM /obj/item/bodypart/head/golem/cult diff --git a/monkestation/code/modules/antagonists/clock_cult/mobs/clockwork_golem.dm b/monkestation/code/modules/antagonists/clock_cult/mobs/clockwork_golem.dm index 4e9507d438eb..889d8f97d806 100644 --- a/monkestation/code/modules/antagonists/clock_cult/mobs/clockwork_golem.dm +++ b/monkestation/code/modules/antagonists/clock_cult/mobs/clockwork_golem.dm @@ -9,7 +9,6 @@ special_names = null examine_limb_id = SPECIES_GOLEM armor = 70 - speedmod = 0.2 ///ref to our turf_healing component, used for deletion on_species_loss() var/datum/component/turf_healing/mob_turf_healing diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/cooking_containers.dm b/monkestation/code/modules/brewin_and_chewin/chewing/cooking_containers.dm index 43500418a3bb..a53e907e1823 100644 --- a/monkestation/code/modules/brewin_and_chewin/chewing/cooking_containers.dm +++ b/monkestation/code/modules/brewin_and_chewin/chewing/cooking_containers.dm @@ -374,8 +374,8 @@ appliancetype = GRILL /obj/item/reagent_containers/cooking_container/bowl - name = "cooking bowl" - shortname = "cooking bowl" + name = "mixing bowl" + shortname = "mixing bowl" desc = "A bowl." icon_state = "bowl" diff --git a/monkestation/code/modules/mob/living/carbon/human/human.dm b/monkestation/code/modules/mob/living/carbon/human/human.dm index cf07660451b1..b04c84fb7637 100644 --- a/monkestation/code/modules/mob/living/carbon/human/human.dm +++ b/monkestation/code/modules/mob/living/carbon/human/human.dm @@ -3,3 +3,9 @@ /mob/living/carbon/human/species/ipc race = /datum/species/ipc + +/mob/living/carbon/human/species/werewolf + race = /datum/species/werewolf + +/mob/living/carbon/human/species/ornithid + race = /datum/species/ornithid diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm index dab89eb3c2ca..e8a03a1fb2e8 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm @@ -18,7 +18,6 @@ mutanttongue = /obj/item/organ/internal/tongue/arachnid mutanteyes = /obj/item/organ/internal/eyes/night_vision/arachnid exotic_bloodtype = /datum/blood_type/spider - speedmod = -0.1 inherent_factions = list(FACTION_SPIDER) bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/arachnid, diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm index 029dff3be48a..bf9255605321 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm @@ -23,7 +23,6 @@ burnmod = 1.8 heatmod = 0.67 //Same as lizard people coldmod = 1.5 //Same as lizard people - speedmod = -0.1 //Same as arachnids meat = /obj/item/food/meat/slab/human/mutant/plant exotic_bloodtype = /datum/blood_type/water // disliked_food = VEGETABLES | FRUIT | GRAIN diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm index a4dfb03b1d78..9615b19232b7 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm @@ -24,7 +24,6 @@ species_language_holder = /datum/language_holder/goblin maxhealthmod = 0.75 stunmod = 1.2 - speedmod = -0.25 payday_modifier = 1 bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/goblin, @@ -157,7 +156,9 @@ /obj/item/bodypart/leg/left/goblin icon_greyscale = 'monkestation/icons/mob/species/goblin/bodyparts.dmi' limb_id = SPECIES_GOBLIN + speed_modifier = -0.125 /obj/item/bodypart/leg/right/goblin icon_greyscale = 'monkestation/icons/mob/species/goblin/bodyparts.dmi' limb_id = SPECIES_GOBLIN + speed_modifier = -0.125 diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm index d3e17e50bb00..883c4f353c3c 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm @@ -31,7 +31,6 @@ species_language_holder = /datum/language_holder/monkey maxhealthmod = 0.85 //small = weak stunmod = 1.3 - speedmod = -0.1 //lil bit faster custom_worn_icons = list( LOADOUT_ITEM_SUIT = SIMIAN_SUIT_ICON, diff --git a/monkestation/code/modules/ranching/satyr/species.dm b/monkestation/code/modules/ranching/satyr/species.dm index fee044fc78f7..87dcee8580d5 100644 --- a/monkestation/code/modules/ranching/satyr/species.dm +++ b/monkestation/code/modules/ranching/satyr/species.dm @@ -31,7 +31,6 @@ disliked_food = MEAT | DAIRY maxhealthmod = 0.8 stunmod = 1.2 - //speedmod = 1 payday_modifier = 1 bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/satyr, diff --git a/monkestation/code/modules/surgery/bodyparts/arachnid_bodyparts.dm b/monkestation/code/modules/surgery/bodyparts/arachnid_bodyparts.dm index 6feabe23fc6d..d99fa22f0b83 100644 --- a/monkestation/code/modules/surgery/bodyparts/arachnid_bodyparts.dm +++ b/monkestation/code/modules/surgery/bodyparts/arachnid_bodyparts.dm @@ -28,7 +28,9 @@ /obj/item/bodypart/leg/left/arachnid icon_greyscale = 'monkestation/icons/mob/species/arachnid/bodyparts.dmi' limb_id = SPECIES_ARACHNIDS + speed_modifier = -0.05 /obj/item/bodypart/leg/right/arachnid icon_greyscale = 'monkestation/icons/mob/species/arachnid/bodyparts.dmi' limb_id = SPECIES_ARACHNIDS + speed_modifier = -0.05 diff --git a/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm b/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm index 353882d35acb..e4e3044bb0a4 100644 --- a/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm +++ b/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm @@ -32,7 +32,9 @@ /obj/item/bodypart/leg/left/floran icon_greyscale = 'monkestation/icons/mob/species/floran/bodyparts.dmi' limb_id = SPECIES_FLORAN + speed_modifier = -0.05 /obj/item/bodypart/leg/right/floran icon_greyscale = 'monkestation/icons/mob/species/floran/bodyparts.dmi' limb_id = SPECIES_FLORAN + speed_modifier = -0.05 diff --git a/monkestation/code/modules/surgery/bodyparts/simian_bodyparts.dm b/monkestation/code/modules/surgery/bodyparts/simian_bodyparts.dm index a4f869adb794..2d916935fb5c 100644 --- a/monkestation/code/modules/surgery/bodyparts/simian_bodyparts.dm +++ b/monkestation/code/modules/surgery/bodyparts/simian_bodyparts.dm @@ -43,6 +43,7 @@ limb_id = SPECIES_SIMIAN bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM footprint_sprite = FOOTPRINT_SPRITE_PAWS + speed_modifier = -0.05 /obj/item/bodypart/leg/right/simian icon_greyscale = 'monkestation/icons/mob/species/simian/bodyparts.dmi' @@ -53,3 +54,4 @@ footprint_sprite = FOOTPRINT_SPRITE_PAWS dmg_overlay_type = "monkey" + speed_modifier = -0.05 diff --git a/monkestation/code/modules/the_bird_inside_of_me/icons/armwings.dmi b/monkestation/code/modules/the_bird_inside_of_me/icons/armwings.dmi new file mode 100644 index 0000000000000000000000000000000000000000..e4b11ae2054bda16f0945ee2ad0c9a9364ac6b7e GIT binary patch literal 1354 zcmV-Q1-1H#P)005u_0{{R3dEt5<0000dP)t-s0002} z{r%?V=GocVzrVlF&(E)~ukrEmpP!$#wY8(8qq@4f%*@QZhP`e80004WQchCV=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRL zOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5DK|c`C^x=5GcUb3zaTX)zM!L)67aU!@NYaR8 zHw9WD&c1TTy=1oX;n000CXNkl{pwv?FP zUJH!bj`qy`ptEy%cV(q9Q->7Feo(swkm$-i4d=MzTe*gBq2+GN*Pga&NFg$tkU~s! z3UPfZ&>mxVcPR7OtxWj(&0z|6e#`igk++NjFP%bTCCyz8p?Fz~&{{_wR+xXCLi4M{ z=Opr*XxtYZzXm%u1J~9rgGoHh9A&-!3pr7#Uk)OSh=_=Y_@ObE1}~+-!!VQ|?Ec|b zyNevFs(a31ZY08tJWucVC9(0;rw+kwX156)RmS1c|(q4BF7qOh!=u4_kd z3bEg2I`!mF@NT6;NHt91@M=RUQaG(^ysA<6P*sN%qV*WSsaZm2bm_9)JmGzpa2To~ zN?aoW>|CiOoCgjz1*J9xyUSnngQ^+;L4vc+N46Oa97~nH`!@=kBikG$sBnd`a)d8O zotb*CMC`GKe_)*6L0e;cS5xNQQI{~_2k9T8J2y{`TOB~q4{k#rL_|bHL`3|bNZT)^ zYj=@j?g#n&Cp4}1mE8Yvf7tVbY`(>*@dModaevtJgKR#iYQ4SV{*U`Zl^Wlt`G!>? zUDT}GP*qY`eBF8_IqlbwzfMdm_llPLzZ9yOvr^%B@_tYv{EfxlUFH`0@uysVlA=>Px# M07*qoM6N<$f_lS<1poj5 literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/the_bird_inside_of_me/icons/ornithid_parts_greyscale.dmi b/monkestation/code/modules/the_bird_inside_of_me/icons/ornithid_parts_greyscale.dmi new file mode 100644 index 0000000000000000000000000000000000000000..7acbc9ed87a548ed9506ed5fb1614c09fc553554 GIT binary patch literal 927 zcmV;Q17Q4#P)B+$QSFoe*<-+*r2IHadq>k6(OnoX4OC=)Ym*zJ3KV)Zm`N%)&~Fp00000 z{Lk8|JiCUMSnKZHfVq7G)!iGo{R!N?f%?&eZUIzRR3G6BJK=`p(D!C+g`ab{w00000008iV8MmI_+mHOgYif-A zmirO6o|PM?7(b^5`R*MJ7`vL^o9c6?6L9aip$fch)%-u1eeWAK000000002Eo50Ze zh+Q=QgI7k=K-MnDHL%|u!3A~!000000001BC#^rbf`xB4Kic(O&a(d4Hse+Je)FUM z7~-#}ZL<X3bB@nPk6=j{UhN=WMSS1Ck7oS{qCwyFrxWCS-)?UpvwlBB zPe7_avx7(jgO@rOzeX{CSrd&J{Zk58?(_fv002ovPDHLkV1h)O BryBqO literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/the_bird_inside_of_me/icons/ornithidfeatures.dmi b/monkestation/code/modules/the_bird_inside_of_me/icons/ornithidfeatures.dmi new file mode 100644 index 0000000000000000000000000000000000000000..32ce5bb7de371955e8a814d726b098789f3324f4 GIT binary patch literal 613 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 literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/the_wolf_inside_of_me/icons/werewolf_parts_greyscale.dmi b/monkestation/code/modules/the_wolf_inside_of_me/icons/werewolf_parts_greyscale.dmi new file mode 100644 index 0000000000000000000000000000000000000000..677d2081622e98db6d4031b448e4c67e5bd3459c GIT binary patch literal 1578 zcmV+_2G#kAP)12@eAV2n?4^U;qFB0d!JMQvg8b*k%9#0G)bNSad{Xb7OL8aCB*J zZU6vyoRyJ53c@fDMc2tGhITJn-MWz$>B3$i1T*Ob(iSGcT)(YuMV#IL@ZN`EYPfax zet`DT>lbng%M4ez9FAI*;4*FH+-OA@M#`U(vdy@~svu)oqBn%rRa&{gX_vL~Y$x3F z=?ncNOxa9Q!T&F?u`Jk+GMo+BS#WO@@@yiGlKCHa4c*YbpSuD*ypwy|4C;6Q00kOJ zL_t(|ob6oAa^p4(mRPiBQ%LWk=m#iG_fFB8J$Jh=u#?IAKSSv>F#(W{tynwL>GI3P zfJl7&fgON9>bm>T-&t-=ZLZxtM7Zmd0b*kJuZF@hX*{eWFrD7@<8`?Ulc8d#h6&aX zSmT|g1W9HV0X--1F03I?h zC)qJKe-Hr1xjhisBJQ`GWQcm8eh#zq%hl4Kun)#-`o)9fL{D4xU>Weherl|C`>-Ja zphiZJzUfa_OMiyId3Ow1UefnqQ-at3C&Y`Cb8h87)sF#gZ;l_x4G1P6L~zR1c$}{DQfUU?j|jQ2&-xRE^3*kYDZ(iljAwl znUKmcMbor_=QxJPk||JPO|YnGrX7>W;(x8(KxELUWqp=_fE^s~0Z$+njVR)OO=Yl- zH_-3~buc)d_u7=iQ3EE87>oZk&GZ2V%_F%)Xh>iL=PZ@RmMOkZLzEREA{~)5DcaM( zYC*?FL_z8TO%RqOABo$AS$mpMr1;=gwT*?~hBqulJ2?r-k^~G94 zO8uD(Y-yrX9+?}a?-BEwP^-^=N}>$sPXn9OTk-#m`sdY_&`AZ=)Z+hJ^_eUlH#9Uf zG&KCg=qsPzu`4v!lpkPM{rF1Q|52;pazhmQ+XOBfl=iSnfVmyY-?7Z-b* zn~Ujt_WkVct-?;)>+99$OP~Axc*kP>rF>yeCU9?1?$U+c-LcH7E(F3}YG1Vi7%sgvad7f73v8FbZfUmW$>_InGwUGM-5ZI$? zgRbLBdzj5FPmDD*G&D3cG&D5)^w?iE80xtPSDyHhse7RF7Rep^YL@Iv)uZDg9yad> ze)@Wf%$1RDeDUjcZ}x*wD0Q(=-!$Xx1iEch+lcEWLAKD}b6AHJsSyktUSsJi>ke^R zcc1KI0xVrBPKD|Ll-Gs;=5a%UxzdArYWg_D8x;#$*4o&liLz} z{X0k%*uOR;cz!8V5WjCo(9qD((9qD3k>i}lSHf!+ei`%UYTz8M+f!Pe(~D(} { const RecipeContentCompact = ({ item, craftable, busy, mode }) => { const { act, data } = useBackend(); + + // Function to handle pushing steps (unchanged) + const specialSteps = [ + 'Optional Steps', + 'End Optional Steps', + 'Exclusive Optional Steps', + 'End Exclusive Optional Steps', + 'Optional Step', + 'End Optional Step', + ]; + + const groupedSteps: string[] = []; + let previousStep = ''; + let duplicateCount = 0; + + const pushStep = (step: string, count: number) => { + const stepText = count > 1 ? `${step} x${count}` : step; + groupedSteps.push(stepText); + }; + + item.steps?.forEach((step) => { + const trimmedStep = step.trim(); + if (trimmedStep === previousStep) { + duplicateCount++; + } else { + if (duplicateCount > 0) { + pushStep(previousStep, duplicateCount); + } + previousStep = trimmedStep; + duplicateCount = 1; + } + }); + + if (duplicateCount > 0) { + pushStep(previousStep, duplicateCount); + } + return (

@@ -665,27 +702,31 @@ const RecipeContentCompact = ({ item, craftable, busy, mode }) => { {item.name} - {Array.from( - Object.keys(item.reqs).map((atom_id) => { - const name = data.atom_data[(atom_id as any) - 1]?.name; - const is_reagent = - data.atom_data[(atom_id as any) - 1]?.is_reagent; - const amount = item.reqs[atom_id]; - return is_reagent - ? `${name}\xa0${amount}u` - : amount > 1 - ? `${name}\xa0${amount}x` - : name; - }), - ).join(', ')} + {Array.isArray(item.reqs) && + Object.keys(item.reqs).length > 0 && + Object.keys(item.reqs) + .map((atom_id) => { + const name = data.atom_data?.[(atom_id as any) - 1]?.name; + const is_reagent = + data.atom_data?.[(atom_id as any) - 1]?.is_reagent; + const amount = item.reqs[atom_id]; + return is_reagent + ? `${name}\xa0${amount}u` + : amount > 1 + ? `${name}\xa0${amount}x` + : name; + }) + .join(', ')} {item.chem_catalysts && + Object.keys(item.chem_catalysts).length > 0 && ', ' + Object.keys(item.chem_catalysts) .map((atom_id) => { - const name = data.atom_data[(atom_id as any) - 1]?.name; + const name = + data.atom_data?.[(atom_id as any) - 1]?.name; const is_reagent = - data.atom_data[(atom_id as any) - 1]?.is_reagent; + data.atom_data?.[(atom_id as any) - 1]?.is_reagent; const amount = item.chem_catalysts[atom_id]; return is_reagent ? `${name}\xa0${amount}u` @@ -696,19 +737,24 @@ const RecipeContentCompact = ({ item, craftable, busy, mode }) => { .join(', ')} {item.tool_paths && + item.tool_paths.length > 0 && ', ' + item.tool_paths - .map((item) => data.atom_data[(item as any) - 1]?.name) + .map((item) => data.atom_data?.[(item as any) - 1]?.name) .join(', ')} + {item.machinery && + item.machinery.length > 0 && ', ' + item.machinery - .map((item) => data.atom_data[(item as any) - 1]?.name) + .map((item) => data.atom_data?.[(item as any) - 1]?.name) .join(', ')} + {item.structures && + item.structures.length > 0 && ', ' + item.structures - .map((item) => data.atom_data[(item as any) - 1]?.name) + .map((item) => data.atom_data?.[(item as any) - 1]?.name) .join(', ')} @@ -746,8 +792,8 @@ const RecipeContentCompact = ({ item, craftable, busy, mode }) => { ) : ( item.steps && ( ( - {step} + content={groupedSteps.map((step, index) => ( + {step} ))} > From aca4c301e21a760b9b1286b5b961a80e256cc12b Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 23:47:14 -0700 Subject: [PATCH 024/158] Update _traits.dm --- code/_globalvars/traits/_traits.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 9a12635dcd6a..84fbad365f18 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -628,6 +628,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_T_RAY_VISIBLE" = TRAIT_T_RAY_VISIBLE, "TRAIT_UNCATCHABLE" = TRAIT_UNCATCHABLE, "TRAIT_WIELDED" = TRAIT_WIELDED, + "TRAIT_FEATHERED" = TRAIT_FEATHERED, /* "TRAIT_BAIT_UNCONSUMABLE" = TRAIT_BAIT_UNCONSUMABLE, */ /* "TRAIT_BAKEABLE" = TRAIT_BAKEABLE, */ /* "TRAIT_BYPASS_RANGED_ARMOR" = TRAIT_BYPASS_RANGED_ARMOR, */ From 5ebcaee67c81687502a27bd7a725e915574aad2f Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 23:48:41 -0700 Subject: [PATCH 025/158] changes --- code/__DEFINES/mobs.dm | 2 -- code/__DEFINES/~monkestation/mobs.dm | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index c0c31d3d2cc6..88588cc8a9e7 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -133,8 +133,6 @@ #define SPECIES_GOBLIN "goblin" //Monkestation Addition #define SPECIES_FLORAN "floran" //Monkestation Addition #define SPECIES_SATYR "satyr" //Monkestation Addition -#define SPECIES_WEREWOLF "werewolf" //Monkestation Addition -#define SPECIES_ORNITHID "ornithid" // Like species IDs, but not specifically attached a species. #define BODYPART_ID_ALIEN "alien" diff --git a/code/__DEFINES/~monkestation/mobs.dm b/code/__DEFINES/~monkestation/mobs.dm index 9f531dc4da76..708feee16e0b 100644 --- a/code/__DEFINES/~monkestation/mobs.dm +++ b/code/__DEFINES/~monkestation/mobs.dm @@ -1,5 +1,7 @@ #define SPECIES_ARACHNIDS "arachnid" #define SPECIES_DRACONIC_SKELETON "draconic_skeleton" +#define SPECIES_WEREWOLF "werewolf" //Monkestation Addition +#define SPECIES_ORNITHID "ornithid" GLOBAL_REAL_VAR(list/voice_type2sound = list( "1" = list( From 351e798284558f010deae067989d6fb5d5cf1e91 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 11 Sep 2024 23:50:05 -0700 Subject: [PATCH 026/158] Update mobs.dm --- code/__DEFINES/mobs.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 88588cc8a9e7..fb0c39de245c 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -133,7 +133,6 @@ #define SPECIES_GOBLIN "goblin" //Monkestation Addition #define SPECIES_FLORAN "floran" //Monkestation Addition #define SPECIES_SATYR "satyr" //Monkestation Addition - // Like species IDs, but not specifically attached a species. #define BODYPART_ID_ALIEN "alien" #define BODYPART_ID_ROBOTIC "robotic" From 7acbbd215734999b8af0d2b8bb65a33d3bb4954a Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 12 Sep 2024 01:26:08 -0700 Subject: [PATCH 027/158] Update species.dm --- monkestation/code/modules/the_bird_inside_of_me/species.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/monkestation/code/modules/the_bird_inside_of_me/species.dm b/monkestation/code/modules/the_bird_inside_of_me/species.dm index de9fdd78ca05..3589fdeeb919 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/species.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/species.dm @@ -36,6 +36,7 @@ GLOBAL_LIST_EMPTY(tails_list_avian) payday_modifier = 0.75 species_pain_mod = 1.20 // Fuck it, this will fill a niche that isn't implemented yet. changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT + digitigrade_customization = DIGITIGRADE_FORCED species_cookie = /obj/item/food/semki/healthy // humans get chocolate, lizards get meat. What do birds get? Seed. meat = /obj/item/food/meat/slab/chicken From 9bc08ebdc23f904aea598f22dbf33fe34bef49d1 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 12 Sep 2024 02:30:49 -0700 Subject: [PATCH 028/158] more fixes --- config/game_options.txt | 1 + .../modules/the_bird_inside_of_me/prefs.dm | 2 +- .../modules/the_bird_inside_of_me/species.dm | 9 +++- .../modules/the_bird_inside_of_me/wings.dm | 2 +- .../monkestation/ornithids.tsx | 51 +++++++++++++++++++ 5 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/monkestation/ornithids.tsx diff --git a/config/game_options.txt b/config/game_options.txt index 8e2d62c329b5..53afd9e5de0a 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -357,6 +357,7 @@ ROUNDSTART_RACES simian ROUNDSTART_RACES arachnid ROUNDSTART_RACES apid ROUNDSTART_RACES satyr +ROUNDSTART_RACES ornithid ## Races that are better than humans in some ways, but worse in others ROUNDSTART_RACES ethereal diff --git a/monkestation/code/modules/the_bird_inside_of_me/prefs.dm b/monkestation/code/modules/the_bird_inside_of_me/prefs.dm index 5b9ef033e298..d413c33d1c30 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/prefs.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/prefs.dm @@ -76,7 +76,7 @@ savefile_key = "feather_color" savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES - //relevant_inherent_trait = TRAIT_FEATHERED + relevant_species_trait = TRAIT_FEATHERED /datum/preference/color/feather_color/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["feathers"] = value diff --git a/monkestation/code/modules/the_bird_inside_of_me/species.dm b/monkestation/code/modules/the_bird_inside_of_me/species.dm index 3589fdeeb919..efb9900dd0d4 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/species.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/species.dm @@ -12,9 +12,9 @@ GLOBAL_LIST_EMPTY(tails_list_avian) id = SPECIES_ORNITHID species_traits = list( NO_UNDERWEAR, + TRAIT_FEATHERED, ) inherent_traits = list( - TRAIT_FEATHERED, TRAIT_LIGHT_DRINKER, TRAIT_TACKLING_WINGED_ATTACKER, TRAIT_USES_SKINTONES, @@ -76,12 +76,17 @@ GLOBAL_LIST_EMPTY(tails_list_avian) /obj/item/bodypart/leg/left/ornithid limb_id = SPECIES_ORNITHID + digitigrade_id = SPECIES_ORNITHID icon_greyscale = 'monkestation/code/modules/the_bird_inside_of_me/icons/ornithid_parts_greyscale.dmi' + bodytype = BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE + bodypart_traits = list(TRAIT_HARD_SOLES) /obj/item/bodypart/leg/right/ornithid limb_id = SPECIES_ORNITHID + digitigrade_id = SPECIES_ORNITHID icon_greyscale = 'monkestation/code/modules/the_bird_inside_of_me/icons/ornithid_parts_greyscale.dmi' - + bodytype = BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE + bodypart_traits = list(TRAIT_HARD_SOLES) // section for lore/perk descs /datum/species/ornithid/get_species_description() diff --git a/monkestation/code/modules/the_bird_inside_of_me/wings.dm b/monkestation/code/modules/the_bird_inside_of_me/wings.dm index 572685cdb3bb..3ca89711512c 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/wings.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/wings.dm @@ -63,7 +63,7 @@ /datum/bodypart_overlay/mutant/wings/functional/arm_wings feature_key = "arm_wings" - layers = EXTERNAL_FRONT | EXTERNAL_ADJACENT + layers = EXTERNAL_BEHIND | EXTERNAL_ADJACENT color_source = ORGAN_COLOR_OVERRIDE ///Feature render key for opened arm wings diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/monkestation/ornithids.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/monkestation/ornithids.tsx new file mode 100644 index 000000000000..c3a603e7afe2 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/monkestation/ornithids.tsx @@ -0,0 +1,51 @@ +import { + Feature, + FeatureChoiced, + FeatureColorInput, + FeatureDropdownInput, +} from '../../base'; + +export const feature_arm_wings: FeatureChoiced = { + name: 'Arm Wings', + small_supplemental: false, + component: FeatureDropdownInput, +}; + +export const feather_color: Feature = { + name: 'Feather Color', + small_supplemental: false, + description: + "The color of your character's feathers. \ + (Armwings, Plumage).", + component: FeatureColorInput, +}; + +export const feature_avian_tail: FeatureChoiced = { + name: 'Tail', + small_supplemental: false, + component: FeatureDropdownInput, +}; + +export const feature_avian_ears: FeatureChoiced = { + name: 'Plumage', + small_supplemental: false, + component: FeatureDropdownInput, +}; + +export const feature_satyr_horns: FeatureChoiced = { + name: 'Satyr Horns', + small_supplemental: false, + component: FeatureDropdownInput, +}; + +export const feature_satyr_fluff: FeatureChoiced = { + name: 'Satyr Fluff', + small_supplemental: false, + component: FeatureDropdownInput, +}; + +export const feature_satyr_tail: FeatureChoiced = { + name: 'Tail', + small_supplemental: false, + component: FeatureDropdownInput, +}; From c2a54bed03dd3cff9801c58fabc7aa78e4a9a06c Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:43:34 -0700 Subject: [PATCH 029/158] more tweaks --- code/__DEFINES/traits/monkestation/declarations.dm | 1 + code/_globalvars/traits/_traits.dm | 1 + code/modules/mob/living/carbon/human/inventory.dm | 4 +++- monkestation/code/modules/ranching/satyr/species.dm | 2 +- .../code/modules/the_bird_inside_of_me/species.dm | 10 ++++++++++ 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/code/__DEFINES/traits/monkestation/declarations.dm b/code/__DEFINES/traits/monkestation/declarations.dm index 83f853963f2a..1fd657d1dc97 100644 --- a/code/__DEFINES/traits/monkestation/declarations.dm +++ b/code/__DEFINES/traits/monkestation/declarations.dm @@ -128,4 +128,5 @@ #define TRAIT_STARGAZED "stargazed" #define TRAIT_FEATHERED "feathers" +#define TRAIT_NON_IMPORTANT_SHOE_BLOCK "shoe_block" // END TRAIT DEFINES diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 84fbad365f18..a46d2f19d8df 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -629,6 +629,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_UNCATCHABLE" = TRAIT_UNCATCHABLE, "TRAIT_WIELDED" = TRAIT_WIELDED, "TRAIT_FEATHERED" = TRAIT_FEATHERED, + "TRAIT_NON_IMPORTANT_SHOE_BLOCK" = TRAIT_NON_IMPORTANT_SHOE_BLOCK, /* "TRAIT_BAIT_UNCONSUMABLE" = TRAIT_BAIT_UNCONSUMABLE, */ /* "TRAIT_BAKEABLE" = TRAIT_BAKEABLE, */ /* "TRAIT_BYPASS_RANGED_ARMOR" = TRAIT_BYPASS_RANGED_ARMOR, */ diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index dba314b18424..dd773b11ffeb 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -1,7 +1,9 @@ /mob/living/carbon/human/can_equip(obj/item/equip_target, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, ignore_equipped = FALSE) if(SEND_SIGNAL(src, COMSIG_HUMAN_EQUIPPING_ITEM, equip_target, slot) == COMPONENT_BLOCK_EQUIP) return FALSE - + if((slot & ITEM_SLOT_FEET) && HAS_TRAIT(src, TRAIT_NON_IMPORTANT_SHOE_BLOCK)) + if(!istype(equip_target, /obj/item/clothing/shoes/mod)) + return FALSE return dna.species.can_equip(equip_target, slot, disable_warning, src, bypass_equip_delay_self, ignore_equipped) /mob/living/carbon/human/get_item_by_slot(slot_id) diff --git a/monkestation/code/modules/ranching/satyr/species.dm b/monkestation/code/modules/ranching/satyr/species.dm index 87dcee8580d5..e87e4d401e1f 100644 --- a/monkestation/code/modules/ranching/satyr/species.dm +++ b/monkestation/code/modules/ranching/satyr/species.dm @@ -3,12 +3,12 @@ plural_form = "Satyrs" id = SPECIES_SATYR changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN - no_equip_flags = ITEM_SLOT_FEET sexes = TRUE species_traits = list( NO_UNDERWEAR, ) inherent_traits = list( + TRAIT_NON_IMPORTANT_SHOE_BLOCK, TRAIT_ALCOHOL_TOLERANCE, TRAIT_HARD_SOLES ) diff --git a/monkestation/code/modules/the_bird_inside_of_me/species.dm b/monkestation/code/modules/the_bird_inside_of_me/species.dm index efb9900dd0d4..aee4d21f854d 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/species.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/species.dm @@ -14,7 +14,17 @@ GLOBAL_LIST_EMPTY(tails_list_avian) NO_UNDERWEAR, TRAIT_FEATHERED, ) + + special_step_sounds = list( + 'sound/effects/footstep/hardclaw1.ogg', + 'sound/effects/footstep/hardclaw2.ogg', + 'sound/effects/footstep/hardclaw3.ogg', + 'sound/effects/footstep/hardclaw4.ogg', + 'sound/effects/footstep/hardclaw1.ogg', + ) + inherent_traits = list( + TRAIT_NON_IMPORTANT_SHOE_BLOCK, TRAIT_LIGHT_DRINKER, TRAIT_TACKLING_WINGED_ATTACKER, TRAIT_USES_SKINTONES, From 554fbfe0c1e12ff13b0bcea533e491d406fa7c94 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:06:18 -0700 Subject: [PATCH 030/158] Update mod_control.dm --- code/modules/mod/mod_control.dm | 6 ------ 1 file changed, 6 deletions(-) diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index 85ddee1a08cd..56a372804c61 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -655,12 +655,6 @@ part.visor_flags_cover = category[SEALED_COVER] || NONE part.alternate_worn_layer = category[UNSEALED_LAYER] mod_parts[part] = part.alternate_worn_layer - if(!category[CAN_OVERSLOT]) - if(overslotting_parts[part]) - var/obj/item/overslot = overslotting_parts[part] - overslot.forceMove(drop_location()) - overslotting_parts -= part - continue overslotting_parts |= part wearer?.regenerate_icons() From d13df600f3c482c4763e236b48df5ec329cb38d2 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:16:33 -0700 Subject: [PATCH 031/158] Update cell.dm --- code/modules/power/cell.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 907254c741a1..4e527d351778 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -251,7 +251,7 @@ if(charge < CELL_POWER_DRAIN) to_chat(H, span_warning("[src] doesn't have enough power!")) return - if(stomach.crystal_charge > charge_limit) + if(user.blood_volume > charge_limit) to_chat(H, span_warning("Your charge is full!")) return to_chat(H, span_notice("You begin clumsily channeling power from [src] into your body.")) From 0b99e9f06be62f0c2d116b973cb1cedd7d00ac7e Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:21:00 -0700 Subject: [PATCH 032/158] Update cell.dm --- code/modules/power/cell.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 4e527d351778..7214f66af658 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -251,7 +251,7 @@ if(charge < CELL_POWER_DRAIN) to_chat(H, span_warning("[src] doesn't have enough power!")) return - if(user.blood_volume > charge_limit) + if(H.blood_volume > charge_limit) to_chat(H, span_warning("Your charge is full!")) return to_chat(H, span_notice("You begin clumsily channeling power from [src] into your body.")) From af24a2839df8101672f883fb393cfaf9659aceeb Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 12 Sep 2024 14:01:45 -0700 Subject: [PATCH 033/158] more changes --- .../organs/external/wings/functional_wings.dm | 2 ++ .../the_bird_inside_of_me/icons/armwings.dmi | Bin 1354 -> 2370 bytes .../modules/the_bird_inside_of_me/species.dm | 5 ++--- .../modules/the_bird_inside_of_me/wings.dm | 8 ++++++++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/code/modules/surgery/organs/external/wings/functional_wings.dm b/code/modules/surgery/organs/external/wings/functional_wings.dm index a7c2f0b52585..791eb4b06abb 100644 --- a/code/modules/surgery/organs/external/wings/functional_wings.dm +++ b/code/modules/surgery/organs/external/wings/functional_wings.dm @@ -105,11 +105,13 @@ if(!HAS_TRAIT_FROM(human, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT)) human.physiology.stun_mod *= 2 human.add_traits(list(TRAIT_NO_FLOATING_ANIM, TRAIT_MOVE_FLYING), SPECIES_FLIGHT_TRAIT) + DO_FLOATING_ANIM(human) passtable_on(human, SPECIES_TRAIT) open_wings() else human.physiology.stun_mod *= 0.5 human.remove_traits(list(TRAIT_NO_FLOATING_ANIM, TRAIT_MOVE_FLYING), SPECIES_FLIGHT_TRAIT) + STOP_FLOATING_ANIM(human) passtable_off(human, SPECIES_TRAIT) close_wings() human.update_body_parts() diff --git a/monkestation/code/modules/the_bird_inside_of_me/icons/armwings.dmi b/monkestation/code/modules/the_bird_inside_of_me/icons/armwings.dmi index e4b11ae2054bda16f0945ee2ad0c9a9364ac6b7e..3acf1208b7922630421bb85f408a9213b4b8170f 100644 GIT binary patch delta 2199 zcmV;I2x#}p3c?a4iBL{Q4GJ0x0000DNk~Le0002M0002M2m=5B0A&K4H2?qs8j&R{ zfBE_O`uh6x^z`!b^0TwE=jZ3n&d%iIFN0R`2YX^ z@bK`{)6<@wo|&1Mw6wJ9>gxOZ`{Ci?<>lq=?d|XH@9600z`($kmX_Pw+s4Mm>+9>j zzP{Gh*1f&Gs;a8k*x2La2NFp{ zK~#90?VS66(>4&mEm?L*lRjwErdtC8N=ULUfl*SR-57Ue^4wLZaw6AIyTKaDVxUq1avOludk0PSPzpnkkv)+s5P^(109_^vjFz}e zK5^0CgGqk`p#3BO6Pq(fPLp0aa;sgV@EfBY9cA)q1_VX`h9J*T4&-=?pebO7W>;8y z%O~?GW=s(i?_mhI2)GR<0?sM+nn?1`7<=XPlusiN5Q1p{+z8kdAUWVB0Zjp%1SCf% zSsEa>PKItFrR+){fw{5|9o1gDXZ@*Ts*WMA|Dh}8!FaMYo#^-8L96Too-hEZKAUJK2ttN9RUGg zL!d$<5LDl%lapdwWCUyqgyjHCg0ku|TRKD?VGD?RRCom78=8_WgtupoO;Di`!2X8> zfQBGG0$FGdL?r=D0VW5WBv9149KSY-(LaB^2!%($eM9lZBcN0*sMZVDpzI}_Vs5e- zPNFdV^u4S1ef;wbr~E7ts-IkigKO>ih0rsO;{^Jpye$ZVAP9mW2!bF8hZyE4L_Ybf z-s981!a=e6%RaMozUwRaV$W!g?~e-ymCavnU+RpdBcPo1z$jJz^<}E)xBNcym)U;@ zzFalT1SycSc3Qn2A5&`n8`HA+%k6VMFE-T0)D67hZK!+w3?=2hg@?U{PLwL(0M&26 z=h&KjEDckSO~g8*mmy8*?B(;rT}2nr1_e%l_Nj(HkTKBT&z*Jyc{or{7(ZnRA+R_*XM& zg5=CvTkAdSpLky3@N&&`3RNnm@9xtYu*Xix#%IOg{Wutn@cXHd=9 z;N#_dPa)wBl*k1^5ClOG1VIo4K{(&U)%P3BQHVTAnz~u8|Cm8%Tiy%`@EM;hb$BvJ1qKX;)g}+*R!+cxf0jXOun!bVwvZ#X#E$L zj}DhFGV+zyOxFr)!s=QZEz+m)|P)empFmTrOtAV z3qiF0xW$LY;q1n>et;H3(g)~xY32%u-6}aJNw-B z+SYd)bPZ~YOTE$n*bwxV7RkTpiq)@&qnqF=aC0D&z%XL=k1-I zBfmUY+1q$=)O@k=VE@+fd-&$J zw_8qoYk0eM8(H@5{fE{apB%W;`tbf8?2Fc~GqfbhdgflI`fdD5EBn|-J)`Y62e^-= zfAD4-g)dtFlihytTQM zD!j3b{^;Tyu$IlUH)zc2Jn=JL|Gl*~Xt&?O+x_^@zu@@4FH_4pUIAdo#p{0tH{t3h zBp+^qX8#|~vWUm&Q_(L7f*=TjAPBzW62#Q^D?v-!ZUqP|}d&imuEAPDD> Ze*pzLfkNVF0$Tt8002ovPDHLkV1ia)cEJDu delta 1176 zcmV;J1ZVrg63PlCiBL{Q4GJ0x0000DNk~Le0001>0001>1Oos70D0kh9smFUCy^y9 z6}*PMZU6uP0d!JMQvg8b*k%9#0H~8#0iA!wV}P=PtDg%vvH%1xj5P%G%54Au1RY64 zK~!jg?OCyM+c*#fNQoI)DhMe`bpgk?lSqQJ7aeNa=FOpa+#aV1g{{l(Bk1?DVfipQV|gm-w63q7)*;in15`W0cC&i zSe56(tifqP-D`WzUQwLX&^CcsFIJL{s)Tl^Z=kas;wQ(nW+BIFc3$`SF3xBJ*VvLo z{hSDl7^~@-z^Bxv0>qST*7IA;m zZ5LiqA;ro}MZ(75mc2rIP4oqAVx4~o@jnWe@|G8%@N$nM*%r2}-TG@WR!L~fAn?*D z++Nvc=F&I06sweOJCitrwnYdEXD%hprC22a!YLBE5eEw+@H-(Cxh*^c(i{h+gRd3R-{F;j;W%6?G01(4{< zJq_o$uHM{o+U-)1`X9XBC;eD5I7^)#kTq6POT&X3T2M#s`r8Wh-%U|?^su}=6 zg0s#?wiyi^OO?L+Hwv30+Z-jRaD}mQgfB;(nR>58?6HP_V4U7TTVs1yQ|8@KmoVT5 z=^vsyH&2dR9YD|zZbN?`L_|bHL`3|bNZT)^Yj=@j?g#n&Cp4}1mE8Yvf7tVbY`(>* z@dModaevtJgKR#iYQ4SV{*U`Zl^Wlt`G!>?UDT}GP*qY`eBF8_IqlbwzfMdm_llPL zzZ9yOv8uVG zzk5%;73)+r>hgY2BK(cT-s9D*v%xUsA9OL`13|(*k4QL@1|uROA|fKbH{8369IM9% zK4o(91wQTvCpP}cCydLV`J4~adp_h*+VwvcEcU7M@A*-3Tj3&po&e7n*F1rOjZd7!PtvsCgM{~EAfWsD7sg{( q_MSegF-XYq(Chq1!ib272=zD8lbXD&ng;0r0000 Date: Thu, 12 Sep 2024 21:27:52 -0700 Subject: [PATCH 034/158] ffs --- code/modules/mob/living/blood.dm | 8 ++++-- .../blood_for_the_blood_gods/particle.dm | 27 +++++++++++------- .../the_bird_inside_of_me/icons/armwings.dmi | Bin 2370 -> 3217 bytes 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 74c65fe4fccb..31ebc0d47544 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -309,9 +309,11 @@ * * splatter_strength: How many tiles it can go, and how many items it can pass over and dirty */ /mob/living/proc/spray_blood(splatter_direction, splatter_strength = 3) - if(!isturf(loc) || !blood_volume || HAS_TRAIT(src, TRAIT_NOBLOOD)) + if(QDELETED(src) || !isturf(loc) || QDELING(loc) || !blood_volume || HAS_TRAIT(src, TRAIT_NOBLOOD)) return var/obj/effect/decal/cleanable/blood/hitsplatter/our_splatter = new(loc) + if(QDELETED(our_splatter)) + return our_splatter.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) var/turf/targ = get_ranged_target_turf(src, splatter_direction, splatter_strength) our_splatter.fly_towards(targ, splatter_strength) @@ -320,10 +322,12 @@ * Helper proc for throwing blood particles around, similar to the spray_blood proc. */ /mob/living/proc/blood_particles(amount = rand(1, 3), angle = rand(0,360), min_deviation = -30, max_deviation = 30, min_pixel_z = 0, max_pixel_z = 6) - if(!isturf(loc) || !blood_volume ||HAS_TRAIT(src, TRAIT_NOBLOOD)) + if(QDELETED(src) || !isturf(loc) || QDELING(loc) || !blood_volume || HAS_TRAIT(src, TRAIT_NOBLOOD)) return for(var/i in 1 to amount) var/obj/effect/decal/cleanable/blood/particle/droplet = new(loc) + if(QDELETED(droplet)) // if they're deleting upon init, let's not waste any more time, any others will prolly just do the same thing + return droplet.color = get_blood_type()?.color droplet.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) droplet.pixel_z = rand(min_pixel_z, max_pixel_z) diff --git a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm index b58d3a2ab523..0d6522fb804e 100644 --- a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm @@ -14,20 +14,23 @@ /// Whether or not we transfer our pixel_x and pixel_y to the splatter, only works for floor splatters though var/messy_splatter = TRUE +/obj/effect/decal/cleanable/blood/particle/Initialize(mapload) + . = ..() + if(QDELETED(loc)) + return INITIALIZE_HINT_QDEL + /obj/effect/decal/cleanable/blood/particle/can_bloodcrawl_in() return FALSE /obj/effect/decal/cleanable/blood/particle/proc/start_movement(movement_angle) - if(QDELETED(src)) - return - var/datum/component/movable_physics/movable_physics = GetComponent(/datum/component/movable_physics) - if(!movable_physics) - movable_physics = initialize_physics() + var/datum/component/movable_physics/movable_physics = get_or_init_physics() if(!isnull(movement_angle)) - movable_physics.set_angle(movement_angle) + movable_physics?.set_angle(movement_angle) -/obj/effect/decal/cleanable/blood/particle/proc/initialize_physics() - return AddComponent(/datum/component/movable_physics, \ +/obj/effect/decal/cleanable/blood/particle/proc/get_or_init_physics() as /datum/component/movable_physics + if(QDELETED(src)) + return + return LoadComponent(/datum/component/movable_physics, \ horizontal_velocity = rand(3 * 100, 5.5 * 100) * 0.01, \ vertical_velocity = rand(4 * 100, 4.5 * 100) * 0.01, \ horizontal_friction = rand(0.05 * 100, 0.1 * 100) * 0.01, \ @@ -39,7 +42,9 @@ ) /obj/effect/decal/cleanable/blood/particle/proc/on_bounce() - if(!isturf(loc) || !splatter_type_floor) + if(QDELETED(src)) + return + else if(!isturf(loc) || QDELING(loc) || !splatter_type_floor) qdel(src) return var/obj/effect/decal/cleanable/splatter @@ -77,7 +82,7 @@ qdel(src) /obj/effect/decal/cleanable/blood/particle/proc/on_bump(atom/bumped_atom) - if(!isturf(loc) || !splatter_type_wall) + if(QDELETED(src) || !isturf(loc) || QDELING(loc) || QDELETED(bumped_atom) || !splatter_type_wall) return if(iswallturf(bumped_atom)) //Adjust pixel offset to make splatters appear on the wall @@ -126,8 +131,8 @@ update_appearance(UPDATE_ICON) /obj/effect/decal/cleanable/blood/splatter/stacking/Destroy() - . = ..() splat_overlays = null + return ..() /obj/effect/decal/cleanable/blood/splatter/stacking/update_overlays() . = ..() diff --git a/monkestation/code/modules/the_bird_inside_of_me/icons/armwings.dmi b/monkestation/code/modules/the_bird_inside_of_me/icons/armwings.dmi index 3acf1208b7922630421bb85f408a9213b4b8170f..d88ce46c24a077fca7a545f0f733eef3c8f07265 100644 GIT binary patch delta 2975 zcmZuzcU05K7Eb8G0xKm5Qbk1+BGE-8PeNIgCWImaK|lqOCcP8#i>T->9Z~6_qbP}j z5_+OiM36{XilHR*B48*9kOUs`&h9(!oHu{W+;7gDJ7>Oo=YIEtM4GJ1AJ$eTqQY{* zAP`8@%+%Nx1Oo4wV2}{+-s1bp@k*MC)GrJMgF>N@NF)M*@Wzk_4D8HdYkwXKwY9PX z8O#iM?g47_6~|EHTOsbj-hrXs0sbIRWNv9jr|<`@UoQ@Rakw9Ty153b@dEW;XaXT+ znT<6wPe*ZL*uTDtGwmDgniv_$syiANRAmV>eke8a;*HU%+PKaRDZVGQa95oKU7_>R zx)Cn!E;C*(@#%oarF8S>BMWgSZ8O@QW(9kMz$Ze4;$CXi*zkhSW|dg#v6Cz+*B>0# zoR0)|zGM7gDBeh7-Xo7uRljyK4eo}Aho6#-iG(imw|78WKRr`~*C;V%e?zu6C8apb z`OmzV%pnFysxnA*3D@In*k%{Nn)4`+E)VacAdoP^%os4d5}CV{7wb-~IoJla<#V@q zV`oy+=+x0$mRuTjwf?-7xr(jU`saP{>QgMeI^@(4X<)u%iwYUrTL*GHqoV?cUiv z-*WUJ0){SU>l8?V)@3zv1yYz5(WM)v_yjLruge8LHXM3XhUxY2=k^zmm)LsL!ZDmA zfgw)Mu&U}W9d`sj_qJqVVYkevx0}??S)YBpaoP)FU~f`UfIn3)^wyKNA8zO`T9D`p z{vvlGR`PkK<>0q!&^hi`Om1`XW7JDU%>sZPODBi;+2iD|Cc z;y?1R1N<;Icj59Bm8}upqbO_uk2cH=HPFTL2x&?L5#x+<=|@nA6>Ol@;Up$nGF5}D zDFmUprQZZ~@qLewTXSn03TQUn8sU++eBB>}=XaDLqp^#8wIXvfe3>HFUG3VgP(y#< zNk%0tCmrZ6D(93Uo5@sZmz@etUZu{r_1SzRYRVX*_prbf8WA|_O3t97BehI zfqHO^52gGfm$va1p&q`+t-!|!vHTG0(ru92-GMnSI6VxtdBC)7aB$180dz#_by;ox zNknXTGQ_1H9SUe$I?qFJ#7TyL>0_~_+)CY6ZC}`{tIj5MZOLZ_%vFkEBz`HMQFVOZ zs}kFTby|br>jx(T-V!f8GdOX;OhhNjLn11<-PWgw6gIOy&{SlDiE^oxMLA5BKyFej zRJ9SvE8Q{1f{oXpO5V3Ngd>wSIbj^Vf4BzrtjL^Cvbcab5uELmx#*vUwcLTnMhuoU zr`Z{e7}+7Gb^bm_t)PZVBGjb-@zxdl@=dhe?#(N_Z(<#wKGzGvhWG>?JSB*=j{nYJ zM@hp@f0V9zD)0>!RG9EUO@=CKoCx5-^BSjppeyFF1_cKlwB^IkpK8y2Jkx? z9`3?#>i*ikg-APT##M*(vQxZ9yme$}72aRLzQ9o<<--Grg zuzGrp|F9-b;oKxD9oaeBd=gSQmSH4Mgsdhx2NdwuQ5{zNTreZiCaL3!t{4sf1Z}^S zw_S;pwr*yaA4$%BVpb&lA*qhTq0;lOw0Z{kqSg92d5o(7GCOW$>1Cyl1qc0pbbPdd z!�g64O~p85e&?=x0x|Z3WK|-M;G&1rE^K?!^MKikHhsZjJt1V{|3vru_Q300llZ zveoJ1XU;2{lX*4x3?^9OjgXF2ej*a@#9sJV zPO)kd%LNcI+l6+`O;Ot%q}3KhDYo&;)A>l?LSok4LOn+IJHjQ3csNr=W_);DHxdy% z<@`}_hW4W>^8A*^N^3^{8^*jJT>FNa$M;Z-x#!6Ub_Iz&JltF@z@i|iVRl*qlO*&` z$NVh@fzsWa*+VEQepWmw^O$z3Cwg@va(#6Uh<-;9%THW5ohOENO39Z$zuM48rLdao zH8Ag3Jqe^QrV0&iEdTX*zc3rCc;;I|1i^v5kV9_@Xmb7%up&wd`fNhj*%>XgLtKdN zk1<}@+M*~gY94=n8uX3&%Kl}KgWycFlcB*Riq{Hp?%uiF_|AJ)! z&3o)qkd#kp;@kMgS=@UI>;&A945P!VrSWA;RX3Mls8q=w)Vg`)mj? zg#(%rRMrP=fj@~mV*dfIvOhQe&QcKQ_x4@qK&P*jiw?b*)6wID747f>ZW2ax>82@S zm$)=UdZOJ+8jPVr)|xuFmZ(xa*BC(kuzod7d30{*t77~Vd;w^ss3*kvQ7=FAc(}Mw zP)1!}Fi)c&_e1NAZ)eNj*kxK?I+U)H1Kp(FBf4L95+LH$&XLc}9~1V4fJT*@pVZ^$ zj?iKh4+Xf-r;f-O$Tsop?2b>3O+R_fs=E#LYn!`Y?iUO7!$AF_>6SsJV?d~~D{m72 z=A;Y@5pm`ckMlj9^7%J2DR1ZXIORu-P% zqDFQx&`~2_!%8q?VQ@oW?0Z&f?f+LmZz3qbt#CScI>1&k-p{?S2vkl|5&2sGObg@5 zs~OW~-1&qgf;?1(OwnrIYU<|ykfgG47`~0zY&73>zIMUHq?1~c=iS~Q>%YjJmhejZ zS9@v9*D*)w~C|ZcQ@o zrHHLiqxsUTo@Y1Gk^co_>$3wkuuXbK?G<+L5v9TE z8vZP545m*X1g%QqY5(cT_TNV9V{p0l>jlmjqh%IrZANVh1Ly-D`zT~~A4On{m@L*F z@Bje)kbO{XQXWDg;dJ%sa*ZTFRKviFwlFqM$-|}Ya=FW)pOKr=jihl+{rz%HtDFK3 X91xH_0{LeD^G>siR>pXv>v8`E^_|8{ delta 2122 zcmV-Q2(|Z-8Nw1FiBL{Q4GJ0x0000DNk~Le0002M0002M2m=5B0A&K4HIX3{48Om> z&(F`Vudng(@v%Vy0e_NCP455z00DGTPE!Ct=GbNc006jpR9JLGWpiV4X>fFDZ*Bkp zc$`yKaB_9`^iy#0_2eo`Eh^5;&r`5fFwryM;w;ZhDainGjE%TBGg33tGfE(w;*!LY zR3K9+H$Jf_H@-YGFTFUwAT=+(ptPvCG%>Fv-Yv-AFGPupGk+zss2F4#7iU^gVs0vk zZHQZYZhl^Vaz;^pZYt#l6ldfYk>L)67aU!@NYaR8Hw9WD&L+_Su;0^iO4HIR$?!2$ zBOW`I62c1V*xXw#-!0|QD( zvMzy9QlQ-!g@2Cm7?1H9d;S0a#*}<$qkFiPs&=^h-1jF-C+qHXI@>)vO%g#61VIq~ z2dG4+oWq3(Z403z|a#$&1pi%*H z8-Ub%2Tk@+3PX^QJ&`LAfs8l+T_y{Rmbgqlanav{Nd%z%BmfheGe=I7UO95BU8C?D zqa7V(@@WPHMgWE&&ruHKc#EJZV25T`SbNJS^C@Ob5fkrW2)GEi4JHE4DfXI3^3NE1 z<@A(KBYzMOf@uKU2-p-LIp8J%O#z$)Bu6J%8X&h$hHfFJnb91cX7Qm1d4U77lel}3 zaV~Xba!bniSd3BNrcvO)?6@ofin|8^2acB~lN)iE1K=9Q*f+gb9m3q0VczghCdykr zeUM?TBs?j?<-t9v>qZK6jK{2 z)=z7tHUJr^?-iYHR{(9Ivid$#K1Uq^0boO*LL(4V-=~w4Vq0VcYzlM~n8 zM1LJ&3y6DEcm&`ZnvyMqw`Yz`P@xgP{)YsBh9EuyS!fPKB>_zVCI_4(P}I5{zcz}| zKfMTrN5FkU@x>#cR4u613)i6RC7fbzvKdaIF#YtstM`5U^9-l_ED@@oT!n*c?fHe! zGmhf~`lY-r2!bF8f*=TjAP9#T<|sry`G2h5nr$T&uEYDj|&Ht z&0lU`>Wrl$pq%x1ddycu8%q3`00o*v|_X)5??0-XNP|eujj^`$OS>IOm_cV--)}l{-h_soy2v-LL6P};zVFIe51LAqhoGrdf&Ww6 zeCqqWmrdnt5k`dua#l~%!~UrU#SZx80OvqcJArLzVu@W{*8$E3JB3eib$?RbF7SXB zt-VJz8;Lt0EvzXBu)8t~H6z*m|^1IZgS5xwm%8p^!0 zC?Mb;ntg^Y8SRO8z(0h+4*Vws6s)UR+YYcQAliZ;2!bF8f*=TjAe=Sx1;>Xh6dXG& z`f1{aMeEnIv*x)H*V0VBuzwU{ndh)*{TG*y4wo-7@|D(1*9vRG>RLf$APZ}&XQ4l9 zXYBDI>#eVjj=yega3(C)mOGa?fy<@Na*Yc?wEpF6nLR$_@;6tGj;~&0*Kl#ObDisl zT<>gh4n*qL-5U$e9$dK5h1;;#AACFe-1gemcN=sKYKu#~(g4^H^naEX$-n4|)vt%6 zo8T&Nb2M~k7z{?YzIWQUhlA}q*objwXY7##3*(*67~3DK|L(o}yI_Ld`}giT?Ulvd zy&s(Rj}LxYCEK*q?X-L%(6R$jU$p-AUT>{CQ+}zt*4t}4^5xbI)7v^~ZuK8-><^F; z3y(&FfhkX7W0&(0ihoqJ{>J*_gRZj&y9bZg-B&2h&d*OC?jALNxqt9R>Mt_(eHS@pME4a zf^oZzuP!W|b{lWBX#JnI(Ob{a&4KG-fAcE5v5fxc;vBG+&9gUX%<4SxGhY9_wKizC z-@@Dd_|L!K_wg9};p!(OA8vwX{~yk>h{x$u(Ju&sAP9mW2*SyU zDvwuz^X@=geZK-k)%UAFRDHh!#MJjIK}3DO8bs9hD?v Date: Thu, 12 Sep 2024 21:28:44 -0700 Subject: [PATCH 035/158] Update _base.dm --- .../code/modules/can_spessmen_feel_pain/pain/_base.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm index f036f5a7afae..a6427897c245 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm @@ -14,9 +14,9 @@ /// Lazy Assoc list [zones] to [references to bodyparts], all the body parts we're tracking var/list/body_zones /// Natural amount of decay given to each limb per 5 ticks of process, increases over time - var/natural_pain_decay = -0.8 + var/natural_pain_decay = -0.2 /// The base amount of pain decay received. - var/base_pain_decay = -0.8 + var/base_pain_decay = -0.2 /// Counter to track pain decay. Pain decay is only done once every 5 ticks. var/natural_decay_counter = 0 /// Amount of shock building up from higher levels of pain From 5d3f9469e79f9f767930b5b8a0e059f4b6f144d3 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 12 Sep 2024 21:47:43 -0700 Subject: [PATCH 036/158] testing change --- .../signals/signals_mob/signals_mob_carbon.dm | 12 +- code/__DEFINES/traits/declarations.dm | 2 +- .../traits/monkestation/declarations.dm | 7 + code/__DEFINES/wounds.dm | 15 +- .../signals/signals_mob/signals_mob_main.dm | 7 + code/__DEFINES/~monkestation/living.dm | 29 + code/_globalvars/traits/_traits.dm | 5 +- code/_onclick/item_attack.dm | 2 +- code/datums/components/tackle.dm | 2 +- code/datums/mood.dm | 41 +- code/datums/mutations/hulk.dm | 12 +- code/datums/status_effects/debuffs/debuffs.dm | 7 +- .../status_effects/debuffs/strandling.dm | 11 +- code/datums/status_effects/wound_effects.dm | 91 ++- code/datums/wounds/_wound_static_data.dm | 9 +- code/datums/wounds/_wounds.dm | 52 +- code/datums/wounds/blunt.dm | 1 + code/datums/wounds/bones.dm | 304 +++++++--- code/datums/wounds/burns.dm | 19 +- code/datums/wounds/pierce.dm | 68 ++- code/datums/wounds/slash.dm | 15 +- code/game/atom_defense.dm | 10 +- .../items/devices/scanners/health_analyzer.dm | 8 +- code/game/objects/obj_defense.dm | 2 +- .../components/unary_devices/cryo.dm | 10 +- .../modules/mob/living/basic/basic_defense.dm | 2 +- .../mob/living/carbon/carbon_defense.dm | 30 +- .../mob/living/carbon/carbon_movement.dm | 3 +- .../mob/living/carbon/human/_species.dm | 23 +- code/modules/mob/living/carbon/human/death.dm | 63 +- code/modules/mob/living/carbon/human/human.dm | 11 +- code/modules/mob/living/carbon/human/life.dm | 36 +- code/modules/mob/living/carbon/life.dm | 446 +++------------ code/modules/mob/living/damage_procs.dm | 19 + code/modules/mob/living/init_signals.dm | 24 +- code/modules/mob/living/living_defense.dm | 52 +- code/modules/mob/living/living_defines.dm | 3 + code/modules/pai/pai.dm | 5 - .../modules/projectiles/ammunition/_firing.dm | 18 +- code/modules/projectiles/projectile.dm | 58 +- code/modules/projectiles/projectile/beams.dm | 3 + .../projectiles/projectile/bullets/lmg.dm | 6 + .../chemistry/reagents/toxin_reagents.dm | 4 +- code/modules/surgery/bodyparts/_bodyparts.dm | 24 +- code/modules/surgery/healing.dm | 6 +- code/modules/surgery/organs/_organ.dm | 38 +- code/modules/surgery/organs/appendix.dm | 12 +- code/modules/surgery/organs/ears.dm | 15 + code/modules/surgery/organs/eyes.dm | 27 + code/modules/surgery/organs/heart.dm | 38 +- code/modules/surgery/organs/lungs.dm | 127 ++++- code/modules/surgery/organs/organ_internal.dm | 4 +- code/modules/surgery/repair_puncture.dm | 10 +- code/modules/surgery/surgery.dm | 20 +- .../a_medical_day/internal_bleeding.dm | 46 ++ .../code/modules/a_medical_day/lungless.dm | 30 + .../code/modules/a_medical_day/surgery.dm | 121 ++++ .../code/modules/a_medical_day/thermics.dm | 94 +++ .../blood_datum/components/limbless_aid.dm | 14 +- .../can_spessmen_feel_pain/pain/_base.dm | 537 +++++++++++------- .../can_spessmen_feel_pain/pain/modifiers.dm | 9 - .../pain/status_effects/anesthetics.dm | 18 + .../cybernetics/augments/internal_implants.dm | 1 + tgstation.dme | 4 + 64 files changed, 1818 insertions(+), 924 deletions(-) create mode 100644 monkestation/code/modules/a_medical_day/internal_bleeding.dm create mode 100644 monkestation/code/modules/a_medical_day/lungless.dm create mode 100644 monkestation/code/modules/a_medical_day/surgery.dm create mode 100644 monkestation/code/modules/a_medical_day/thermics.dm diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm index d2b720057c4f..11f9d799c408 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -102,10 +102,14 @@ #define COMSIG_CARBON_SANITY_UPDATE "carbon_sanity_update" ///Called when a carbon attempts to breath, before the breath has actually occured #define COMSIG_CARBON_ATTEMPT_BREATHE "carbon_attempt_breathe" - // Prevents the breath - #define COMSIG_CARBON_BLOCK_BREATH (1 << 0) -///Called when a carbon breathes, before the breath has actually occured -#define COMSIG_CARBON_PRE_BREATHE "carbon_pre_breathe" + /// Prevents the breath entirely, which means they will neither suffocate nor regain oxyloss nor decay losebreath stacks + #define BREATHE_BLOCK_BREATH (1<<0) + /// Allow the breath but prevent inake, think losebreath + #define BREATHE_SKIP_BREATH (1<<1) +/// Called when a carbon breathes out (breath (the exhale)) +#define COMSIG_CARBON_BREATH_EXHALE "carbon_breath_exhale" + /// Return if the exhale was handled, or I guess to send the exhale into the void + #define BREATHE_EXHALE_HANDLED (1<<0) ///Called when a carbon updates their mood #define COMSIG_CARBON_MOOD_UPDATE "carbon_mood_update" ///Called when a carbon attempts to eat (eating) diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 6f5d4e3e78a3..834168e92379 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -543,7 +543,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /* #define TRAIT_UNHITTABLE_BY_PROJECTILES "unhittable_by_projectiles" */ /// Projectile with this trait will always hit the defined zone of a struck living mob. -/* #define TRAIT_ALWAYS_HIT_ZONE "always_hit_zone" */ +#define TRAIT_ALWAYS_HIT_ZONE "always_hit_zone" /// Mobs with this trait do care about a few grisly things, such as digging up graves. They also really do not like bringing people back to life or tending wounds, but love autopsies and amputations. #define TRAIT_MORBID "morbid" diff --git a/code/__DEFINES/traits/monkestation/declarations.dm b/code/__DEFINES/traits/monkestation/declarations.dm index 198bf93fc88e..ba88b26a1a04 100644 --- a/code/__DEFINES/traits/monkestation/declarations.dm +++ b/code/__DEFINES/traits/monkestation/declarations.dm @@ -131,4 +131,11 @@ #define TRAIT_FEATHERED "feathers" #define TRAIT_NON_IMPORTANT_SHOE_BLOCK "shoe_block" +/// Skip a breath once in every x breaths (where x is ticks between breaths) +#define TRAIT_LABOURED_BREATHING "laboured_breathing" +/// Blocks losebreath from accumulating from things such as heart attacks or choking +#define TRAIT_ASSISTED_BREATHING "assisted_breathing" +/// Stops organs from decaying while dead +#define TRAIT_NO_ORGAN_DECAY "no_organ_decay" + // END TRAIT DEFINES diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm index 815e60d0738e..6a108858bb1f 100644 --- a/code/__DEFINES/wounds.dm +++ b/code/__DEFINES/wounds.dm @@ -48,16 +48,13 @@ GLOBAL_LIST_INIT(wound_severities_chronological, list( // ~determination second wind defines -// How much determination reagent to add each time someone gains a new wound in [/datum/wound/proc/second_wind] -#define WOUND_DETERMINATION_MODERATE 1 -#define WOUND_DETERMINATION_SEVERE 2.5 -#define WOUND_DETERMINATION_CRITICAL 5 -#define WOUND_DETERMINATION_LOSS 7.5 +// How much determination to add each time someone gains a new wound in [/datum/wound/proc/second_wind] +#define WOUND_DETERMINATION_MODERATE (5 SECONDS) +#define WOUND_DETERMINATION_SEVERE (10 SECONDS) +#define WOUND_DETERMINATION_CRITICAL (20 SECONDS) +#define WOUND_DETERMINATION_LOSS (30 SECONDS) /// the max amount of determination you can have -#define WOUND_DETERMINATION_MAX 10 - -/// While someone has determination in their system, their bleed rate is slightly reduced -#define WOUND_DETERMINATION_BLEED_MOD 0.85 +#define WOUND_DETERMINATION_MAX (1 MINUTES) /// Wounds using this competition mode will remove any wounds of a greater severity than itself in a random wound roll. In most cases, you dont want to use this. #define WOUND_COMPETITION_OVERPOWER_GREATERS "wound_submit" diff --git a/code/__DEFINES/~monkestation/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/~monkestation/dcs/signals/signals_mob/signals_mob_main.dm index bfc0f361e4f4..46bff024c98c 100644 --- a/code/__DEFINES/~monkestation/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/~monkestation/dcs/signals/signals_mob/signals_mob_main.dm @@ -33,3 +33,10 @@ #define COMSIG_LIVING_TRACKER_REMOVED "tracker_removed" #define COMSIG_CLEAR_SEE "clear_see" + +/// Carbon is steppin +#define COMSIG_CARBON_STEP "carbon_step" +/// Carbon is steppin on a painful limb +#define COMSIG_CARBON_PAINED_STEP "carbon_pain_step" + /// Stop the pain from happening + #define STOP_PAIN (1<<0) diff --git a/code/__DEFINES/~monkestation/living.dm b/code/__DEFINES/~monkestation/living.dm index 06134c4aaffa..b79309b42d8d 100644 --- a/code/__DEFINES/~monkestation/living.dm +++ b/code/__DEFINES/~monkestation/living.dm @@ -6,3 +6,32 @@ #define COMSIG_LIVING_CAN_ALLOW_THROUGH "living_can_allow_through" /// Allow to movable atoms to pass through this living mob #define COMPONENT_LIVING_PASSABLE (1<<0) + +/// Checks if the value is "left" +/// Used primarily for hand or foot indexes +#define IS_RIGHT(value) (value % 2 == 0) +/// Checks if the value is "right" +/// Used primarily for hand or foot indexes +#define IS_LEFT(value) (value % 2 != 0) +/// Helper for picking between left or right when given a value +/// Used primarily for hand or foot indexes +#define SELECT_LEFT_OR_RIGHT(value, left, right) (IS_LEFT(value) ? left : right) + + +/// Calculates oxyloss cap +#define MAX_OXYLOSS(maxHealth) (maxHealth * 2) + +// Some source defines for pain and consciousness +// Consciousness ones are human readable because of laziness (they are shown in cause of death) +#define PAINSHOCK "neurological shock" +#define PAINCRIT "paincrit" +#define PAIN "pain" +#define HUNGER "starvation" +#define BRAIN_DAMAGE "brain damage" +#define BLOOD_LOSS "blood loss" +#define BLUNT_DAMAGE "blunt force trauma" +#define BURN_DAMAGE "severe burns" +#define OXY_DAMAGE "suffocation" +#define TOX_DAMAGE "toxic poisoning" + +#define SKIP_INTERNALS "skip_internals" diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 42ca11b2dd28..10eb361cab8b 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -631,6 +631,9 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_WIELDED" = TRAIT_WIELDED, "TRAIT_FEATHERED" = TRAIT_FEATHERED, "TRAIT_NON_IMPORTANT_SHOE_BLOCK" = TRAIT_NON_IMPORTANT_SHOE_BLOCK, + "TRAIT_LABOURED_BREATHING" = TRAIT_LABOURED_BREATHING, + "TRAIT_ASSISTED_BREATHING" = TRAIT_ASSISTED_BREATHING, + "TRAIT_NO_ORGAN_DECAY" = TRAIT_NO_ORGAN_DECAY, /* "TRAIT_BAIT_UNCONSUMABLE" = TRAIT_BAIT_UNCONSUMABLE, */ /* "TRAIT_BAKEABLE" = TRAIT_BAKEABLE, */ /* "TRAIT_BYPASS_RANGED_ARMOR" = TRAIT_BYPASS_RANGED_ARMOR, */ @@ -709,7 +712,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( /* "TRAIT_MODPC_INTERACTING_WITH_FRAME" = TRAIT_MODPC_INTERACTING_WITH_FRAME, */ ), /obj/projectile = list( - /* "TRAIT_ALWAYS_HIT_ZONE" = TRAIT_ALWAYS_HIT_ZONE, */ + "TRAIT_ALWAYS_HIT_ZONE" = TRAIT_ALWAYS_HIT_ZONE, ), /obj/structure = list( "TRAIT_RADSTORM_IMMUNE" = TRAIT_RADSTORM_IMMUNE, diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 539dcb585ab2..3f149ec80769 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -334,7 +334,7 @@ send_item_attack_message(attacking_item, user) if(!attacking_item.force) return FALSE - var/damage = attacking_item.force + var/damage = attacking_item.force * user.outgoing_damage_mod if(mob_biotypes & MOB_ROBOTIC) damage *= attacking_item.demolition_mod apply_damage(damage, attacking_item.damtype) diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index bfdd2ce481fb..fb98747d2ed3 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -411,7 +411,7 @@ playsound(user, 'sound/effects/blobattack.ogg', 60, TRUE) playsound(user, 'sound/effects/splat.ogg', 70, TRUE) playsound(user, 'sound/effects/wounds/crack2.ogg', 70, TRUE) - user.emote("scream") + user.pain_emote("scream") user.gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic) // oopsie indeed! shake_camera(user, 7, 7) user.flash_act(1, TRUE, TRUE, length = 4.5) diff --git a/code/datums/mood.dm b/code/datums/mood.dm index 850ab6f3b7d3..fb20799de3f9 100644 --- a/code/datums/mood.dm +++ b/code/datums/mood.dm @@ -305,6 +305,41 @@ /// Prints the users mood, sanity, and moodies to chat /datum/mood/proc/print_mood(mob/user) var/msg = "[span_info("My current mental status:")]\n" + + if(!HAS_TRAIT(src, TRAIT_NOHUNGER)) + msg += span_notice("My hunger: ") + var/nutrition = mob_parent.nutrition + switch(nutrition) + if(NUTRITION_LEVEL_FULL to INFINITY) + msg += span_info("I'm completely stuffed!\n") + if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL) + msg += span_info("I'm well fed!\n") + if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED) + msg += span_info("I'm not hungry.\n") + if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED) + msg += span_info("I could use a bite to eat.\n") + if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY) + msg += span_warning("I feel quite hungry.\n") + if(0 to NUTRITION_LEVEL_STARVING) + msg += span_boldwarning("I'm starving!\n") + + var/drunkness = mob_parent.get_timed_status_effect_duration(/datum/status_effect/inebriated) + if(drunkness >= 1) + msg += span_notice("My current drunkenness: ") + switch(drunkness) + if(1 to 10) + msg += span_info("I'm feeling a little tipsy.\n") + if(11 to 21) + msg += span_info("I'm feeling a bit drunk.\n") + if(21 to 41) + msg += span_info("I'm feeling quite drunk.\n") + if(41 to 61) + msg += span_info("I'm feeling very drunk.\n") + if(61 to 81) + msg += span_warning("I'm feeling like a mess.\n") + if(81 to INFINITY) + msg += span_boldwarning("I'm completely wasted.\n") + msg += span_notice("My current sanity: ") //Long term switch(sanity) if(SANITY_GREAT to INFINITY) @@ -345,6 +380,7 @@ if(mood_events.len) for(var/category in mood_events) var/datum/mood_event/event = mood_events[category] + msg += "• " switch(event.mood_change) if(-INFINITY to MOOD_SAD2) msg += span_boldwarning(event.description + "\n") @@ -359,7 +395,10 @@ if(MOOD_HAPPY2 to INFINITY) msg += span_boldnicegreen(event.description + "\n") else - msg += "[span_grey("I don't have much of a reaction to anything right now.")]\n" + msg += "• [span_grey("I don't have much of a reaction to anything right now.")]\n" + + if(LAZYLEN(mob_parent.quirks)) + msg += span_notice("You have these quirks: [mob_parent.get_quirk_string(FALSE, CAT_QUIRK_ALL)].") to_chat(user, examine_block(msg)) /// Updates the mob's moodies, if the area provides a mood bonus diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index c1b42564f593..43463e3c0a5a 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -15,7 +15,6 @@ var/list/mutation_traits = list( TRAIT_CHUNKYFINGERS, TRAIT_HULK, - TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_PUSHIMMUNE, TRAIT_STUNIMMUNE, ) @@ -32,6 +31,8 @@ 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)) + RegisterSignal(owner, COMSIG_MOB_STATCHANGE, PROC_REF(statchange)) + owner.add_movespeed_mod_immunities("hulk", /datum/movespeed_modifier/damage_slowdown) /datum/mutation/human/hulk/proc/on_attack_hand(mob/living/carbon/human/source, atom/target, proximity, modifiers) SIGNAL_HANDLER @@ -77,8 +78,9 @@ owner.cause_wound_of_type_and_severity(WOUND_BLUNT, arm, severity, wound_source = "hulk smashing") -/datum/mutation/human/hulk/on_life(seconds_per_tick, times_fired) - if(owner.health < owner.crit_threshold) +/datum/mutation/human/hulk/proc/statchange(mob/living/carbon/human/owner, stat, old_stat) + SIGNAL_HANDLER + if(stat >= UNCONSCIOUS) on_losing(owner) to_chat(owner, span_danger("You suddenly feel very weak.")) qdel(src) @@ -94,6 +96,8 @@ UnregisterSignal(owner, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) UnregisterSignal(owner, COMSIG_MOB_SAY) UnregisterSignal(owner, COMSIG_MOB_CLICKON) + UnregisterSignal(owner, COMSIG_MOB_STATCHANGE) + owner.remove_movespeed_mod_immunities("hulk", /datum/movespeed_modifier/damage_slowdown) /datum/mutation/human/hulk/proc/handle_speech(datum/source, list/speech_args) SIGNAL_HANDLER @@ -264,6 +268,7 @@ log_combat(the_hulk, yeeted_person, "has thrown by tail") /datum/mutation/human/hulk/wizardly + name = "Hulk (Magic)" species_allowed = null //yes skeleton/lizard hulk - note that species that dont have skintone changing (like skellies) get custom handling health_req = 0 instability = 0 @@ -271,7 +276,6 @@ /// List of traits to add/remove when someone gets this mutation. mutation_traits = list( TRAIT_HULK, - TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_PUSHIMMUNE, TRAIT_STUNIMMUNE, ) // no chunk diff --git a/code/datums/status_effects/debuffs/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm index b3933ece3169..fd268e730867 100644 --- a/code/datums/status_effects/debuffs/debuffs.dm +++ b/code/datums/status_effects/debuffs/debuffs.dm @@ -138,14 +138,19 @@ ADD_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_SLEEPIMMUNE), PROC_REF(on_owner_insomniac)) RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_SLEEPIMMUNE), PROC_REF(on_owner_sleepy)) + RegisterSignal(owner, COMSIG_LIVING_DEATH, PROC_REF(on_owner_death)) /datum/status_effect/incapacitating/sleeping/on_remove() - UnregisterSignal(owner, list(SIGNAL_ADDTRAIT(TRAIT_SLEEPIMMUNE), SIGNAL_REMOVETRAIT(TRAIT_SLEEPIMMUNE))) + UnregisterSignal(owner, list(SIGNAL_ADDTRAIT(TRAIT_SLEEPIMMUNE), SIGNAL_REMOVETRAIT(TRAIT_SLEEPIMMUNE), COMSIG_LIVING_DEATH)) if(!HAS_TRAIT(owner, TRAIT_SLEEPIMMUNE)) REMOVE_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) tick_interval = initial(tick_interval) return ..() +/datum/status_effect/incapacitating/sleeping/proc/on_owner_death(mob/living/source) + SIGNAL_HANDLER + qdel(src) + ///If the mob is sleeping and gain the TRAIT_SLEEPIMMUNE we remove the TRAIT_KNOCKEDOUT and stop the tick() from happening /datum/status_effect/incapacitating/sleeping/proc/on_owner_insomniac(mob/living/source) SIGNAL_HANDLER diff --git a/code/datums/status_effects/debuffs/strandling.dm b/code/datums/status_effects/debuffs/strandling.dm index 5465171df820..5fbf37e6f6f2 100644 --- a/code/datums/status_effects/debuffs/strandling.dm +++ b/code/datums/status_effects/debuffs/strandling.dm @@ -10,25 +10,22 @@ var/time_to_remove = 3.5 SECONDS /datum/status_effect/strandling/on_apply() - RegisterSignal(owner, COMSIG_CARBON_PRE_BREATHE, PROC_REF(on_breathe)) + RegisterSignal(owner, COMSIG_CARBON_ATTEMPT_BREATHE, PROC_REF(on_breathe)) RegisterSignal(owner, COMSIG_ATOM_TOOL_ACT(TOOL_WIRECUTTER), PROC_REF(on_cut)) RegisterSignal(owner, COMSIG_CARBON_PRE_MISC_HELP, PROC_REF(on_self_check)) return TRUE /datum/status_effect/strandling/on_remove() - UnregisterSignal(owner, list(COMSIG_CARBON_PRE_BREATHE, COMSIG_ATOM_TOOL_ACT(TOOL_WIRECUTTER), COMSIG_CARBON_PRE_MISC_HELP)) + UnregisterSignal(owner, list(COMSIG_CARBON_ATTEMPT_BREATHE, COMSIG_ATOM_TOOL_ACT(TOOL_WIRECUTTER), COMSIG_CARBON_PRE_MISC_HELP)) /datum/status_effect/strandling/get_examine_text() return span_warning("[owner.p_they(TRUE)] seem[owner.p_s()] to be being choked by some durathread strands. You may be able to cut them off.") -/// Signal proc for [COMSIG_CARBON_PRE_BREATHE], causes losebreath whenever we're trying to breathe +/// Signal proc for [COMSIG_CARBON_ATTEMPT_BREATHE], causes losebreath whenever we're trying to breathe /datum/status_effect/strandling/proc/on_breathe(mob/living/source) SIGNAL_HANDLER - if(source.get_organ_slot(ORGAN_SLOT_BREATHING_TUBE)) - return - - source.losebreath++ + return HAS_TRAIT(owner, TRAIT_ASSISTED_BREATHING) ? NONE : BREATHE_SKIP_BREATH /// Signal proc for [COMSIG_ATOM_TOOL_ACT] with [TOOL_WIRECUTTER], allowing wirecutters to remove the effect (from others / themself) /datum/status_effect/strandling/proc/on_cut(mob/living/source, mob/user, obj/item/tool) diff --git a/code/datums/status_effects/wound_effects.dm b/code/datums/status_effects/wound_effects.dm index f44e71de8db7..bef626d49154 100644 --- a/code/datums/status_effects/wound_effects.dm +++ b/code/datums/status_effects/wound_effects.dm @@ -1,29 +1,102 @@ // The shattered remnants of your broken limbs fill you with determination! -/atom/movable/screen/alert/status_effect/determined +/atom/movable/screen/alert/determined name = "Determined" desc = "The serious wounds you've sustained have put your body into fight-or-flight mode! Now's the time to look for an exit!" icon_state = "wounded" +/// While someone has determination in their system, their bleed rate is slightly reduced +#define WOUND_DETERMINATION_BLEED_MOD 0.85 + /datum/status_effect/determined id = "determined" - alert_type = /atom/movable/screen/alert/status_effect/determined remove_on_fullheal = TRUE + tick_interval = 2 SECONDS + alert_type = null + status_type = STATUS_EFFECT_REFRESH + /// World.time when the status effect was applied + var/start_time = 0 + +/datum/status_effect/determined/on_creation(mob/living/new_owner, set_duration = 5 SECONDS) + src.duration = min(WOUND_DETERMINATION_MAX, set_duration) + start_time = world.time + return ..() + +/datum/status_effect/determined/refresh(mob/living/new_owner, set_duration = 5 SECONDS) + duration = min(duration + set_duration, start_time + WOUND_DETERMINATION_MAX) + if(set_duration >= WOUND_DETERMINATION_SEVERE) + owner.throw_alert(id, /atom/movable/screen/alert/determined) /datum/status_effect/determined/on_apply() - . = ..() - owner.visible_message(span_danger("[owner]'s body tenses up noticeably, gritting against [owner.p_their()] pain!"), span_notice("Your senses sharpen as your body tenses up from the wounds you've sustained!"), \ - vision_distance=COMBAT_MESSAGE_RANGE) + if(owner.stat == DEAD) + return FALSE + owner.visible_message( + span_danger("[owner]'s body tenses up noticeably, gritting against [owner.p_their()] pain!"), + span_boldnotice("Your senses sharpen as your body tenses up from the wounds you've sustained!"), + vision_distance = COMBAT_MESSAGE_RANGE, + ) if(ishuman(owner)) var/mob/living/carbon/human/human_owner = owner human_owner.physiology.bleed_mod *= WOUND_DETERMINATION_BLEED_MOD + human_owner.set_pain_mod(id, 0.625) // 0.625 * 0.8 = 0.5 = numbness + ADD_TRAIT(owner, TRAIT_NO_PAIN_EFFECTS, TRAIT_STATUS_EFFECT(id)) + ADD_TRAIT(owner, TRAIT_ABATES_SHOCK, TRAIT_STATUS_EFFECT(id)) + if(duration >= WOUND_DETERMINATION_SEVERE) + owner.throw_alert(id, /atom/movable/screen/alert/determined) + return TRUE /datum/status_effect/determined/on_remove() - owner.visible_message(span_danger("[owner]'s body slackens noticeably!"), span_warning("Your adrenaline rush dies off, and the pain from your wounds come aching back in..."), vision_distance=COMBAT_MESSAGE_RANGE) + if(QDELING(owner)) + return + if(ishuman(owner)) var/mob/living/carbon/human/human_owner = owner human_owner.physiology.bleed_mod /= WOUND_DETERMINATION_BLEED_MOD - return ..() + human_owner.unset_pain_mod(id) + REMOVE_TRAIT(owner, TRAIT_NO_PAIN_EFFECTS, TRAIT_STATUS_EFFECT(id)) + REMOVE_TRAIT(owner, TRAIT_ABATES_SHOCK, TRAIT_STATUS_EFFECT(id)) + owner.clear_alert(id) + owner.apply_status_effect(/datum/status_effect/determination_crash) + +/datum/status_effect/determined/tick(seconds_between_ticks) + if(HAS_TRAIT(owner, TRAIT_STASIS) || owner.stat == DEAD || !iscarbon(owner)) + return + + var/mob/living/carbon/carbowner = owner + for(var/datum/wound/wound as anything in carbowner.all_wounds) + wound.limb?.heal_damage(0.2 * seconds_between_ticks, 0.2 * seconds_between_ticks) + +#undef WOUND_DETERMINATION_BLEED_MOD + +/datum/status_effect/determination_crash + id = "determination_crash" + alert_type = null + remove_on_fullheal = TRUE + tick_interval = -1 + duration = 10 SECONDS + +/datum/status_effect/determination_crash/on_apply() + if(owner.stat == DEAD) + return FALSE + + owner.visible_message( + span_danger("[owner]'s body slackens noticeably!"), + span_boldwarning("Your adrenaline rush dies off, and the pain from your wounds come aching back in..."), + vision_distance = COMBAT_MESSAGE_RANGE, + ) + owner.add_movespeed_modifier(/datum/movespeed_modifier/determination_crash) + owner.add_actionspeed_modifier(/datum/actionspeed_modifier/determination_crash) + return TRUE + +/datum/status_effect/determination_crash/on_remove() + owner.remove_movespeed_modifier(/datum/movespeed_modifier/determination_crash) + owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/determination_crash) + +/datum/movespeed_modifier/determination_crash + multiplicative_slowdown = 0.1 + +/datum/actionspeed_modifier/determination_crash + multiplicative_slowdown = 0.1 /datum/status_effect/limp id = "limp" @@ -74,7 +147,7 @@ return // less limping while we have determination still - var/determined_mod = owner.has_status_effect(/datum/status_effect/determined) ? 0.5 : 1 + var/determined_mod = owner.can_feel_pain(TRUE) ? 1 : 0.5 if(next_leg == left) if(prob(limp_chance_left * determined_mod)) @@ -189,6 +262,8 @@ /datum/status_effect/wound/blunt/bone // blunt +/datum/status_effect/wound/blunt/bone/rib_break + id = "rib_break" /datum/status_effect/wound/blunt/bone/moderate id = "disjoint" /datum/status_effect/wound/blunt/bone/severe diff --git a/code/datums/wounds/_wound_static_data.dm b/code/datums/wounds/_wound_static_data.dm index f996bb258c79..15aa2dd7afa7 100644 --- a/code/datums/wounds/_wound_static_data.dm +++ b/code/datums/wounds/_wound_static_data.dm @@ -86,7 +86,14 @@ * if we have a biotype mismatch, if the limb isnt in a viable zone, or if theres any duplicate wound types. * TRUE otherwise. */ -/datum/wound_pregen_data/proc/can_be_applied_to(obj/item/bodypart/limb, list/suggested_wounding_types = required_wounding_types, datum/wound/old_wound, random_roll = FALSE, duplicates_allowed = src.duplicates_allowed, care_about_existing_wounds = TRUE) +/datum/wound_pregen_data/proc/can_be_applied_to( + obj/item/bodypart/limb, + list/suggested_wounding_types = required_wounding_types, + datum/wound/old_wound, + random_roll = FALSE, + duplicates_allowed = src.duplicates_allowed, + care_about_existing_wounds = TRUE, +) SHOULD_BE_PURE(TRUE) if (!istype(limb) || !limb.owner) diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm index 6a52753eef99..4fbcee74e27d 100644 --- a/code/datums/wounds/_wounds.dm +++ b/code/datums/wounds/_wounds.dm @@ -19,10 +19,14 @@ /datum/wound /// What it's named var/name = "Wound" + /// Optional, what is the wound named when someone is checking themselves (IE, no scanner - just with their eyes and hands) + var/undiagnosed_name /// The description shown on the scanners var/desc = "" /// The basic treatment suggested by health analyzers var/treat_text = "" + /// Even more basic treatment + var/treat_text_short = "" /// What the limb looks like on a cursory examine var/examine_desc = "is badly hurt" @@ -204,7 +208,7 @@ if(severity == WOUND_SEVERITY_TRIVIAL) return - if(!silent && !demoted) + if(!silent && !demoted && occur_text) var/msg = span_danger("[victim]'s [limb.plaintext_zone] [occur_text]!") var/vis_dist = COMBAT_MESSAGE_RANGE @@ -440,13 +444,13 @@ /datum/wound/proc/second_wind() switch(severity) if(WOUND_SEVERITY_MODERATE) - victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_MODERATE) + victim.apply_status_effect(/datum/status_effect/determined, WOUND_DETERMINATION_MODERATE) if(WOUND_SEVERITY_SEVERE) - victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_SEVERE) + victim.apply_status_effect(/datum/status_effect/determined, WOUND_DETERMINATION_SEVERE) if(WOUND_SEVERITY_CRITICAL) - victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_CRITICAL) + victim.apply_status_effect(/datum/status_effect/determined, WOUND_DETERMINATION_CRITICAL) if(WOUND_SEVERITY_LOSS) - victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_LOSS) + victim.apply_status_effect(/datum/status_effect/determined, WOUND_DETERMINATION_LOSS) /** * try_treating() is an intercept run from [/mob/living/carbon/proc/attackby] right after surgeries but before anything else. Return TRUE here if the item is something that is relevant to treatment to take over the interaction. @@ -592,7 +596,7 @@ */ /datum/wound/proc/get_examine_description(mob/user) . = get_wound_description(user) - if(HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + if(. && HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) . += span_notice("\nThere is a holo-image next to the wound that seems to contain indications for treatment.") return . @@ -601,15 +605,29 @@ var/desc if ((wound_flags & ACCEPTS_GAUZE) && limb.current_gauze) - var/sling_condition = get_gauze_condition() - desc = "[victim.p_Their()] [limb.plaintext_zone] is [sling_condition] fastened in a sling of [limb.current_gauze.name]" - else + desc = "[victim.p_Their()] [limb.plaintext_zone] is [get_gauze_condition()] fastened in a sling of [limb.current_gauze.name]" + else if(examine_desc) desc = "[victim.p_Their()] [limb.plaintext_zone] [examine_desc]" + if(!desc) + return + desc = modify_desc_before_span(desc, user) return get_desc_intensity(desc) +/datum/wound/proc/get_self_check_description(mob/user) + // future todo : medical doctors can self-diagnose / don't use [undiagnosed_name] + switch(severity) + if(WOUND_SEVERITY_TRIVIAL) + return span_danger("It's suffering [a_or_from] [lowertext(undiagnosed_name || name)].") + if(WOUND_SEVERITY_MODERATE) + return span_warning("It's suffering [a_or_from] [lowertext(undiagnosed_name || name)].") + if(WOUND_SEVERITY_SEVERE) + return span_boldwarning("It's suffering [a_or_from] [lowertext(undiagnosed_name || name)]!") + if(WOUND_SEVERITY_CRITICAL) + return span_boldwarning("It's suffering [a_or_from] [lowertext(undiagnosed_name || name)]!!") + /// A hook proc used to modify desc before it is spanned via [get_desc_intensity]. Useful for inserting spans yourself. /datum/wound/proc/modify_desc_before_span(desc, mob/user) return desc @@ -637,10 +655,17 @@ return "[desc]." /datum/wound/proc/get_scanner_description(mob/user) - return "Type: [name]\nSeverity: [severity_text(simple = FALSE)]\nDescription: [desc]\nRecommended Treatment: [treat_text]" + return "Type: [name]\n\ + Severity: [severity_text(simple = FALSE)]\n\ + Description: [desc]\n\ + Recommended Treatment: [treat_text]" /datum/wound/proc/get_simple_scanner_description(mob/user) - return "[name] detected!\nRisk: [severity_text(simple = TRUE)]\nDescription: [simple_desc ? simple_desc : desc]\nTreatment Guide: [simple_treat_text]\nHomemade Remedies: [homemade_treat_text]" + return "[name] detected!\n\ + Risk: [severity_text(simple = TRUE)]\n\ + Description: [simple_desc ? simple_desc : desc]\n\ + Treatment Guide: [simple_treat_text]\n\ + Homemade Remedies: [homemade_treat_text]" /datum/wound/proc/severity_text(simple = FALSE) switch(severity) @@ -653,11 +678,6 @@ if(WOUND_SEVERITY_CRITICAL) return "Critical" + (simple ? "!!!" : "") -/// Returns TRUE if our limb is the head or chest, FALSE otherwise. -/// Essential in the sense of "we cannot live without it". -/datum/wound/proc/limb_essential() - return (limb.body_zone == BODY_ZONE_HEAD || limb.body_zone == BODY_ZONE_CHEST) - /// Getter proc for our scar_keyword, in case we might have some custom scar gen logic. /datum/wound/proc/get_scar_keyword(obj/item/bodypart/scarred_limb, add_to_scars) return scar_keyword diff --git a/code/datums/wounds/blunt.dm b/code/datums/wounds/blunt.dm index 219b7dd8805c..45fd29330733 100644 --- a/code/datums/wounds/blunt.dm +++ b/code/datums/wounds/blunt.dm @@ -1,3 +1,4 @@ /datum/wound/blunt name = "Blunt Wound" + undiagnosed_name = "Painful Bruising" sound_effect = 'sound/effects/wounds/crack1.ogg' diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index de8858e5932d..5d9e5f4f3368 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -36,6 +36,8 @@ var/trauma_cycle_cooldown /// If this is a chest wound and this is set, we have this chance to cough up blood when hit in the chest var/internal_bleeding_chance = 0 + /// Counts which tick we're on for footsteps + var/footstep_counter = 0 /* Overwriting of base procs @@ -53,7 +55,12 @@ I = victim.get_inactive_held_item() if(I && victim.dropItemToGround(I)) - victim.visible_message(span_danger("[victim] drops [I] in shock!"), span_warning("The force on your [limb.plaintext_zone] causes you to drop [I]!"), vision_distance=COMBAT_MESSAGE_RANGE) + victim.visible_message( + span_danger("[victim] drops [I] in shock!"), + span_boldwarning("The force on your [limb.plaintext_zone] causes you to drop [I]!"), + vision_distance = COMBAT_MESSAGE_RANGE, + + ) update_inefficiencies() return ..() @@ -62,8 +69,14 @@ if (victim) UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(victim, COMSIG_MOB_ITEM_ATTACK) + UnregisterSignal(victim, COMSIG_CARBON_STEP) + UnregisterSignal(victim, COMSIG_CARBON_ATTEMPT_BREATHE) if (new_victim) RegisterSignal(new_victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand)) + RegisterSignal(new_victim, COMSIG_MOB_ITEM_ATTACK, PROC_REF(weapon_attack_with_hurt_hand)) + RegisterSignal(new_victim, COMSIG_CARBON_STEP, PROC_REF(carbon_step)) + RegisterSignal(new_victim, COMSIG_CARBON_ATTEMPT_BREATHE, PROC_REF(breath)) return ..() @@ -107,56 +120,137 @@ if(!victim || !limb) qdel(src) return - to_chat(victim, span_green("Your [limb.plaintext_zone] has recovered from its [name]!")) + to_chat(victim, span_green("Your [limb.plaintext_zone] has recovered from its [undiagnosed_name || name]!")) remove_wound() /// If we're a human who's punching something with a broken arm, we might hurt ourselves doing so -/datum/wound/blunt/bone/proc/attack_with_hurt_hand(mob/M, atom/target, proximity) +/datum/wound/blunt/bone/proc/attack_with_hurt_hand(datum/source, atom/target, proximity) + if(!proximity || severity <= WOUND_SEVERITY_MODERATE) + return NONE + if(limb.body_zone != BODY_ZONE_CHEST && victim.get_active_hand() != limb) + return NONE + var/weapon = victim.get_active_held_item() + if(!weapon && ((victim.istate & ISTATE_HARM)|| !ismob(target))) + return NONE + + // With a severe or critical wound, you have a 15% or 30% chance to proc pain on hit + if(!prob((severity - 1) * 15)) + return NONE + + var/painless = !victim.can_feel_pain() || victim.has_status_effect(/datum/status_effect/determined) + // And you have a 70% or 50% chance to actually land the blow, respectively + if(prob(70 - 20 * (severity - 1))) + to_chat(victim, span_userdanger("The fracture in your [limb.plaintext_zone] [painless ? "jostles uncomfortably" : "shoots with pain"] as you strike [target]!")) + victim.apply_damage(8, BRUTE, limb) + return NONE + + victim.visible_message( + span_danger("[victim] weakly strikes [target] with [victim.p_their()] broken [limb.plaintext_zone], recoiling from pain!"), + span_userdanger("You [weapon ? "weakly" : "fail"] to strike [target] as the fracture in your [limb.plaintext_zone] [painless ? "jostles uncomfortably" : "lights up in unbearable pain"]!"), + vision_distance = COMBAT_MESSAGE_RANGE, + + ) + victim.Stun(0.5 SECONDS) + victim.apply_damage(10, BRUTE, limb) + victim.pain_emote(pick("wince", "grimace", "flinch")) + return COMPONENT_CANCEL_ATTACK_CHAIN + +/datum/wound/blunt/bone/proc/weapon_attack_with_hurt_hand(datum/source, mob/target, mob/user, params) SIGNAL_HANDLER - if(victim.get_active_hand() != limb || !(victim.istate & ISTATE_HARM) || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE) - return + return attack_with_hurt_hand(source, target, TRUE) - // With a severe or critical wound, you have a 15% or 30% chance to proc pain on hit - if(prob((severity - 1) * 15)) - // And you have a 70% or 50% chance to actually land the blow, respectively - if(prob(70 - 20 * (severity - 1))) - to_chat(victim, span_userdanger("The fracture in your [limb.plaintext_zone] shoots with pain as you strike [target]!")) - limb.receive_damage(brute=rand(1,5)) - else - victim.visible_message(span_danger("[victim] weakly strikes [target] with [victim.p_their()] broken [limb.plaintext_zone], recoiling from pain!"), \ - span_userdanger("You fail to strike [target] as the fracture in your [limb.plaintext_zone] lights up in unbearable pain!"), vision_distance=COMBAT_MESSAGE_RANGE) - INVOKE_ASYNC(victim, TYPE_PROC_REF(/mob, emote), "scream") - victim.Stun(0.5 SECONDS) - limb.receive_damage(brute=rand(3,7)) - return COMPONENT_CANCEL_ATTACK_CHAIN +/datum/wound/blunt/bone/proc/carbon_step(datum/source) + SIGNAL_HANDLER + if(limb.body_zone != BODY_ZONE_L_LEG && limb.body_zone != BODY_ZONE_R_LEG) + return + if(victim.body_position == LYING_DOWN || victim.buckled) // wheelchair = fine, being pulled = not fine + return + if(victim.has_status_effect(/datum/status_effect/determined)) + return + + footstep_counter += 1 + if(footstep_counter >= 8) + footstep_counter = 1 -/datum/wound/blunt/bone/receive_damage(wounding_type, wounding_dmg, wound_bonus) - if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE) + if((limb.current_gauze ? limb.current_gauze.splint_factor : 1) <= 0.75 || !victim.can_feel_pain()) + return + if(limb.body_zone == SELECT_LEFT_OR_RIGHT(footstep_counter, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) + return + var/mod = 1 + switch(victim.m_intent) + if(MOVE_INTENT_RUN) + mod = 1.5 + if(MOVE_INTENT_WALK) + mod = 1 + if(MOVE_INTENT_SPRINT) + mod = 2 + if(!prob(severity * mod * 20)) return - if(HAS_TRAIT(victim, TRAIT_NOBLOOD)) + if(SEND_SIGNAL(victim, COMSIG_CARBON_PAINED_STEP, limb, footstep_counter) & STOP_PAIN) return - if(limb.body_zone == BODY_ZONE_CHEST && prob(internal_bleeding_chance + wounding_dmg)) - var/blood_bled = rand(1, wounding_dmg * (severity == WOUND_SEVERITY_CRITICAL ? 2 : 1.5)) // 12 brute toolbox can cause up to 18/24 bleeding with a severe/critical chest wound - switch(blood_bled) - if(1 to 6) - victim.bleed(blood_bled, TRUE) - if(7 to 13) - victim.visible_message("A thin stream of blood drips from [victim]'s mouth from the blow to [victim.p_their()] chest.", span_danger("You cough up a bit of blood from the blow to your chest."), vision_distance=COMBAT_MESSAGE_RANGE) - victim.bleed(blood_bled, TRUE) - if(14 to 19) - victim.visible_message("Blood spews out of [victim]'s mouth from the blow to [victim.p_their()] chest!", span_danger("You spit out a string of blood from the blow to your chest!"), vision_distance=COMBAT_MESSAGE_RANGE) - victim.do_splatter_effect(victim.dir) - victim.bleed(blood_bled) - victim.blood_particles(amount = 1) - if(20 to INFINITY) - victim.visible_message(span_danger("Blood spurts out of [victim]'s mouth from the blow to [victim.p_their()] chest!"), span_danger("You choke up on a spray of blood from the blow to your chest!"), vision_distance=COMBAT_MESSAGE_RANGE) - victim.bleed(blood_bled) - victim.do_splatter_effect(victim.dir) - victim.add_splatter_floor(get_step(victim.loc, victim.dir)) - victim.blood_particles(amount = 3) + to_chat(victim, span_danger("Your [limb.plaintext_zone] [pick("aches", "pangs", "stings")] as you take a step!")) + victim.sharp_pain(limb.body_zone, severity * 6, BRUTE, 10 SECONDS) + + +/datum/wound/blunt/bone/proc/breath(...) + SIGNAL_HANDLER + + if(limb.body_zone != BODY_ZONE_CHEST) + return NONE + if(!victim.can_feel_pain() || (limb.current_gauze && limb.current_gauze.splint_factor <= 0.75)) + return NONE + var/pain_prob = min(75, 20 * severity * (victim.body_position == LYING_DOWN ? 1.5 : 1)) + if(!prob(pain_prob)) + return NONE + to_chat(victim, span_danger("You wince as you take a deep breath, feeling the pain in your ribs!")) + var/breath_prob = min(50, 15 * severity * (victim.body_position == LYING_DOWN ? 1.2 : 1)) + if(prob(breath_prob)) + victim.pain_emote("gasp") + . = BREATHE_SKIP_BREATH + else + victim.pain_emote("wince") + . = NONE + victim.sharp_pain(BODY_ZONE_CHEST, rand(5, 10), BRUTE, 10 SECONDS) + return . + +/datum/wound/blunt/bone/receive_damage(wounding_type, wounding_dmg, wound_bonus, attack_direction, damage_source) + if(victim.stat == DEAD || wounding_dmg < WOUND_MINIMUM_DAMAGE || wounding_type == WOUND_BURN) + return + if(limb.body_zone != BODY_ZONE_CHEST || !limb.can_bleed() || !prob(internal_bleeding_chance)) + return + if(limb.current_gauze?.splint_factor) + wounding_dmg *= (1 - limb.current_gauze.splint_factor) + var/blood_bled = sqrt(wounding_dmg) * (severity * 0.75) * pick(0.75, 1, 1.25) // melbert todo : push upstream + switch(blood_bled) + if(7 to 13) + victim.visible_message( + span_smalldanger("A thin stream of blood drips from [victim]'s mouth from the blow to [victim.p_their()] chest."), + span_danger("You cough up a bit of blood from the blow to your chest."), + vision_distance = COMBAT_MESSAGE_RANGE, + + ) + if(14 to 19) + victim.visible_message( + span_smalldanger("Blood spews out of [victim]'s mouth from the blow to [victim.p_their()] chest!"), + span_danger("You spit out a string of blood from the blow to your chest!"), + vision_distance = COMBAT_MESSAGE_RANGE, + + ) + if(20 to INFINITY) + victim.visible_message( + span_danger("Blood spurts out of [victim]'s mouth from the blow to [victim.p_their()] chest!"), + span_bolddanger("You choke up on a spray of blood from the blow to your chest!"), + vision_distance = COMBAT_MESSAGE_RANGE, + + ) + victim.bleed(blood_bled, TRUE) + if(blood_bled >= 14) + victim.do_splatter_effect(attack_direction) + victim.add_splatter_floor(get_step(victim.loc, victim.dir)) + victim.blood_particles(amount = 1 * round(blood_bled / 14, 1)) /datum/wound/blunt/bone/modify_desc_before_span(desc) . = ..() @@ -179,11 +273,54 @@ return ..() +/datum/wound_pregen_data/bone/rib_break + abstract = FALSE + wound_path_to_generate = /datum/wound/blunt/bone/rib_break + required_limb_biostate = BIO_BONE + threshold_minimum = 20 + viable_zones = list(BODY_ZONE_CHEST) + +/datum/wound/blunt/bone/rib_break + // You may notice higher severity bone wounds are fractures on their own + // So this one seems a bit out of place, seeing as it's a generic "rib fracture" when more specific ones exist + // This is here as the chest has no moderate wound (as it's not jointed, and can't dislocate) + // Flavor wise imagine it as one rib being broken rather than multiple + name = "Fractured Rib" + desc = "One of the patient's ribs has been fractured, causing sharp pain and difficulty breathing." + treat_text = "Repair surgically. In the event of an emergency, \ + one can also apply bone gel and surgical tape to the affected area to fix over time." + treat_text_short = "Repair surgically, or apply bone gel and surgical tape." + occur_text = "cracks and bruises" + examine_desc = "" + + severity = WOUND_SEVERITY_MODERATE + threshold_penalty = 20 + treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel) + status_effect_type = /datum/status_effect/wound/blunt/bone/rib_break + scar_keyword = "dislocate" + internal_bleeding_chance = 25 + wound_flags = (ACCEPTS_GAUZE | MANGLES_INTERIOR) + regen_ticks_needed = 180 // ticks every 2 seconds, 360 seconds, so roughly 6 minutes default + + simple_treat_text = "Bandaging the wound will reduce its impact until treated \ + surgically or via bone gel and surgical tape." + homemade_treat_text = "Bone gel and surgical tape may be applied directly to the wound, \ + though this is quite difficult for most people to do so individually \ + unless they've dosed themselves with one or more painkillers." + +/datum/wound/blunt/bone/rib_break/get_self_check_description(mob/user) + if(locate(/datum/wound/bleed_internal) in limb.wounds) + return null + return span_warning("It feels tense to the touch.") // same as IB! + /// Joint Dislocation (Moderate Blunt) /datum/wound/blunt/bone/moderate name = "Joint Dislocation" + undiagnosed_name = "Dislocation" desc = "Patient's limb has been unset from socket, causing pain and reduced motor function." - treat_text = "Recommended application of bonesetter to affected limb, though manual relocation by applying an aggressive grab to the patient and helpfully interacting with afflicted limb may suffice." + treat_text = "Apply Bonesetter to the affected limb. \ + Manual relocation by via an aggressive grab and a tight hug to the affected limb may also suffice." + treat_text_short = "Apply Bonesetter, or manually relocate the limb." examine_desc = "is awkwardly janked out of place" occur_text = "janks violently and becomes unseated" severity = WOUND_SEVERITY_MODERATE @@ -195,9 +332,12 @@ status_effect_type = /datum/status_effect/wound/blunt/bone/moderate scar_keyword = "dislocate" - simple_desc = "Patient's bone has been dislocated, causing limping or reduced dexterity." - simple_treat_text = "Bandaging the wound will reduce its impact until treated with a bonesetter. Most commonly, it is treated by aggressively grabbing someone and helpfully wrenching the limb in place, though there's room for malfeasance when doing this." - homemade_treat_text = "Besides bandaging and wrenching, bone setters can be printed in lathes and utilized on oneself at the cost of great pain. As a last resort, crushing the patient with a firelock has sometimes been noted to fix their dislocated limb." + simple_treat_text = "Bandaging the wound will reduce its impact until treated with a bonesetter. \ + Most commonly, it is treated by aggressively grabbing someone and helpfully wrenching the limb in place, \ + though there's room for malfeasance when doing this." + homemade_treat_text = "Besides bandaging and wrenching, bone setters \ + can be printed in lathes and utilized on oneself at the cost of great pain. \ + As a last resort, crushing the patient with a firelock has sometimes been noted to fix their dislocated limb." /datum/wound_pregen_data/bone/dislocate abstract = FALSE @@ -222,6 +362,9 @@ return ..() +/datum/wound/blunt/bone/moderate/get_self_check_description(mob/user) + return span_warning("It feels dislocated!") + /// Getting smushed in an airlock/firelock is a last-ditch attempt to try relocating your limb /datum/wound/blunt/bone/moderate/proc/door_crush() SIGNAL_HANDLER @@ -234,7 +377,7 @@ return FALSE if(user.grab_state == GRAB_PASSIVE) - to_chat(user, span_warning("You must have [victim] in an aggressive grab to manipulate [victim.p_their()] [lowertext(name)]!")) + to_chat(user, span_warning("You must have [victim] in an aggressive grab to manipulate [victim.p_their()] [lowertext(undiagnosed_name || name)]!")) return TRUE if(user.grab_state >= GRAB_AGGRESSIVE) @@ -256,13 +399,13 @@ if(prob(65)) user.visible_message(span_danger("[user] snaps [victim]'s dislocated [limb.plaintext_zone] back into place!"), span_notice("You snap [victim]'s dislocated [limb.plaintext_zone] back into place!"), ignored_mobs=victim) to_chat(victim, span_userdanger("[user] snaps your dislocated [limb.plaintext_zone] back into place!")) - victim.emote("scream") - limb.receive_damage(brute=20, wound_bonus=CANT_WOUND) + user.pain_emote("scream") + user.apply_damage(20, BRUTE, limb, wound_bonus = CANT_WOUND) qdel(src) else user.visible_message(span_danger("[user] wrenches [victim]'s dislocated [limb.plaintext_zone] around painfully!"), span_danger("You wrench [victim]'s dislocated [limb.plaintext_zone] around painfully!"), ignored_mobs=victim) to_chat(victim, span_userdanger("[user] wrenches your dislocated [limb.plaintext_zone] around painfully!")) - limb.receive_damage(brute=10, wound_bonus=CANT_WOUND) + user.apply_damage(10, BRUTE, limb, wound_bonus = CANT_WOUND) chiropractice(user) /// If someone is snapping our dislocated joint into a fracture by hand with an aggro grab and harm or disarm intent @@ -275,12 +418,12 @@ if(prob(65)) user.visible_message(span_danger("[user] snaps [victim]'s dislocated [limb.plaintext_zone] with a sickening crack!"), span_danger("You snap [victim]'s dislocated [limb.plaintext_zone] with a sickening crack!"), ignored_mobs=victim) to_chat(victim, span_userdanger("[user] snaps your dislocated [limb.plaintext_zone] with a sickening crack!")) - victim.emote("scream") - limb.receive_damage(brute=25, wound_bonus=30) + user.pain_emote("scream") + user.apply_damage(25, BRUTE, limb, wound_bonus = 30) else user.visible_message(span_danger("[user] wrenches [victim]'s dislocated [limb.plaintext_zone] around painfully!"), span_danger("You wrench [victim]'s dislocated [limb.plaintext_zone] around painfully!"), ignored_mobs=victim) to_chat(victim, span_userdanger("[user] wrenches your dislocated [limb.plaintext_zone] around painfully!")) - limb.receive_damage(brute=10, wound_bonus=CANT_WOUND) + user.apply_damage(10, BRUTE, limb, wound_bonus = CANT_WOUND) malpractice(user) @@ -306,7 +449,7 @@ user.visible_message(span_danger("[user] finishes resetting [victim]'s [limb.plaintext_zone]!"), span_nicegreen("You finish resetting [victim]'s [limb.plaintext_zone]!"), ignored_mobs=victim) to_chat(victim, span_userdanger("[user] resets your [limb.plaintext_zone]!")) - victim.emote("scream") + victim.pain_emote("scream") qdel(src) /* @@ -316,7 +459,9 @@ /datum/wound/blunt/bone/severe name = "Hairline Fracture" desc = "Patient's bone has suffered a crack in the foundation, causing serious pain and reduced limb functionality." - treat_text = "Recommended light surgical application of bone gel, though a sling of medical gauze will prevent worsening situation." + treat_text = "Repair surgically. In the event of an emergency, an application of bone gel over the affected area will fix over time. \ + A splint or sling of medical gauze can also be used to prevent the fracture from worsening." + treat_text_short = "Repair surgically, or apply bone gel. A splint or gauze sling can also be used." examine_desc = "appears grotesquely swollen, jagged bumps hinting at chips in the bone" occur_text = "sprays chips of bone and develops a nasty looking bruise" @@ -334,9 +479,11 @@ wound_flags = (ACCEPTS_GAUZE | MANGLES_INTERIOR) regen_ticks_needed = 120 // ticks every 2 seconds, 240 seconds, so roughly 4 minutes default - simple_desc = "Patient's bone has cracked in the middle, drastically reducing limb functionality." - simple_treat_text = "Bandaging the wound will reduce its impact until surgically treated with bone gel and surgical tape." - homemade_treat_text = "Bone gel and surgical tape may be applied directly to the wound, though this is quite difficult for most people to do so individually unless they've dosed themselves with one or more painkillers (Morphine and Miner's Salve have been known to help)" + simple_treat_text = "Bandaging the wound will reduce its impact until treated \ + surgically or via bone gel and surgical tape." + homemade_treat_text = "Bone gel and surgical tape may be applied directly to the wound, \ + though this is quite difficult for most people to do so individually \ + unless they've dosed themselves with one or more painkillers." /datum/wound_pregen_data/bone/hairline @@ -349,8 +496,12 @@ /// Compound Fracture (Critical Blunt) /datum/wound/blunt/bone/critical name = "Compound Fracture" - desc = "Patient's bones have suffered multiple gruesome fractures, causing significant pain and near uselessness of limb." - treat_text = "Immediate binding of affected limb, followed by surgical intervention ASAP." + undiagnosed_name = "Compound Fracture" // you can tell it's a compound fracture at a glance because of a skin breakage + desc = "Patient's bones have suffered multiple fractures, \ + couped with a break in the skin, causing significant pain and near uselessness of limb." + treat_text = "Immediately bind the affected limb with gauze or a splint. Repair surgically. \ + In the event of an emergency, bone gel and surgical tape can be applied to the affected area to fix over a long period of time." + treat_text_short = "Repair surgically, or apply bone gel and surgical tape. A splint or gauze sling should also be used." examine_desc = "is thoroughly pulped and cracked, exposing shards of bone to open air" occur_text = "cracks apart, exposing broken bones to open air" @@ -370,9 +521,12 @@ wound_flags = (ACCEPTS_GAUZE | MANGLES_INTERIOR) regen_ticks_needed = 240 // ticks every 2 seconds, 480 seconds, so roughly 8 minutes default - simple_desc = "Patient's bones have effectively shattered completely, causing total immobilization of the limb." - simple_treat_text = "Bandaging the wound will slightly reduce its impact until surgically treated with bone gel and surgical tape." - homemade_treat_text = "Although this is extremely difficult and slow to function, Bone gel and surgical tape may be applied directly to the wound, though this is nigh-impossible for most people to do so individually unless they've dosed themselves with one or more painkillers (Morphine and Miner's Salve have been known to help)" + simple_treat_text = "Bandaging the wound will slightly reduce its impact until treated \ + surgically or via bone gel and surgical tape." + homemade_treat_text = "Although this is extremely difficult and slow to function, \ + Bone gel and surgical tape may be applied directly to the wound, \ + though this is nigh-impossible for most people to do so individually \ + unless they've dosed themselves with one or more painkillers." /datum/wound_pregen_data/bone/compound abstract = FALSE @@ -404,13 +558,14 @@ return TRUE I.use(1) - victim.emote("scream") + victim.pain_emote("scream") if(user != victim) user.visible_message(span_notice("[user] finishes applying [I] to [victim]'s [limb.plaintext_zone], emitting a fizzing noise!"), span_notice("You finish applying [I] to [victim]'s [limb.plaintext_zone]!"), ignored_mobs=victim) to_chat(victim, span_userdanger("[user] finishes applying [I] to your [limb.plaintext_zone], and you can feel the bones exploding with pain as they begin melting and reforming!")) else if(!HAS_TRAIT(victim, TRAIT_ANALGESIA)) - if(prob(25 + (20 * (severity - 2)) - min(victim.get_drunk_amount(), 10))) // 25%/45% chance to fail self-applying with severe and critical wounds, modded by drunkenness + var/painkiller_bonus = 50 * (1 - (victim.pain_controller?.pain_modifier || 1)) + if(prob(25 + (20 * (severity - 2)) - painkiller_bonus)) // 25%/45% chance to fail self-applying with severe and critical wounds, modded by drunkenness victim.visible_message(span_danger("[victim] fails to finish applying [I] to [victim.p_their()] [limb.plaintext_zone], passing out from the pain!"), span_notice("You pass out from the pain of applying [I] to your [limb.plaintext_zone] before you can finish!")) victim.AdjustUnconscious(5 SECONDS) return TRUE @@ -483,21 +638,18 @@ . += "
" if(severity > WOUND_SEVERITY_MODERATE) - if((limb.biological_state & BIO_BONE) && !(limb.biological_state & BIO_FLESH)) - if(!gelled) - . += "Recommended Treatment: Apply bone gel directly to injured limb. Creatures of pure bone don't seem to mind bone gel application nearly as much as fleshed individuals. Surgical tape will also be unnecessary.\n" - else - . += "[span_notice("Note: Bone regeneration in effect. Bone is [round(regen_ticks_current*100/regen_ticks_needed)]% regenerated.")]\n" + if(!gelled) + . += "Recommended Treatment: \ + Operate where possible. In the event of emergency, apply bone gel directly to injured limb. \ + Creatures of pure bone don't seem to mind bone gel application nearly as much as fleshed individuals. \ + Surgical tape will also be unnecessary.\n" else - if(!gelled) - . += "Alternative Treatment: Apply bone gel directly to injured limb, then apply surgical tape to begin bone regeneration. This is both excruciatingly painful and slow, and only recommended in dire circumstances.\n" - else if(!taped) - . += "[span_notice("Continue Alternative Treatment: Apply surgical tape directly to injured limb to begin bone regeneration. Note, this is both excruciatingly painful and slow, though sleep or laying down will speed recovery.")]\n" - else - . += "[span_notice("Note: Bone regeneration in effect. Bone is [round(regen_ticks_current*100/regen_ticks_needed)]% regenerated.")]\n" + . += "[span_notice("Note: Bone regeneration in effect. Bone is [round(regen_ticks_current*100/regen_ticks_needed)]% regenerated.")]\n" if(limb.body_zone == BODY_ZONE_HEAD) - . += "Cranial Trauma Detected: Patient will suffer random bouts of [severity == WOUND_SEVERITY_SEVERE ? "mild" : "severe"] brain traumas until bone is repaired." + . += "Cranial Trauma Detected: \ + Patient will suffer random bouts of [severity == WOUND_SEVERITY_SEVERE ? "mild" : "severe"] brain traumas until bone is repaired." else if(limb.body_zone == BODY_ZONE_CHEST && !HAS_TRAIT(victim, TRAIT_NOBLOOD)) - . += "Ribcage Trauma Detected: Further trauma to chest is likely to worsen internal bleeding until bone is repaired." + . += "Ribcage Trauma Detected: \ + Further trauma to chest is likely to worsen internal bleeding until bone is repaired." . += "
" diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm index 483b47cce1fa..abd6bd763078 100644 --- a/code/datums/wounds/burns.dm +++ b/code/datums/wounds/burns.dm @@ -6,6 +6,7 @@ // TODO: well, a lot really, but specifically I want to add potential fusing of clothing/equipment on the affected area, and limb infections, though those may go in body part code /datum/wound/burn name = "Burn Wound" + undiagnosed_name = "Burns" a_or_from = "from" sound_effect = 'sound/effects/wounds/sizzle1.ogg' @@ -35,6 +36,11 @@ /// Once we reach infestation beyond WOUND_INFESTATION_SEPSIS, we get this many warnings before the limb is completely paralyzed (you'd have to ignore a really bad burn for a really long time for this to happen) var/strikes_to_lose_limb = 3 +/datum/wound/burn/flesh/severity_text(simple = FALSE) + if(infestation > WOUND_INFECTION_MODERATE) + return "Infected, [..()]" + return ..() + /datum/wound/burn/flesh/handle_process(seconds_per_tick, times_fired) if (!victim || HAS_TRAIT(victim, TRAIT_STASIS)) @@ -278,7 +284,8 @@ /datum/wound/burn/flesh/moderate name = "Second Degree Burns" desc = "Patient is suffering considerable burns with mild skin penetration, weakening limb integrity and increased burning sensations." - treat_text = "Recommended application of topical ointment or regenerative mesh to affected region." + treat_text = "Apply topical ointment or regenerative mesh to the wound." + treat_text_short = "Apply healing aid such as regenerative mesh." examine_desc = "is badly burned and breaking out in blisters" occur_text = "breaks out with violent red burns" severity = WOUND_SEVERITY_MODERATE @@ -302,7 +309,10 @@ /datum/wound/burn/flesh/severe name = "Third Degree Burns" desc = "Patient is suffering extreme burns with full skin penetration, creating serious risk of infection and greatly reduced limb integrity." - treat_text = "Recommended immediate disinfection and excision of any infected skin, followed by bandaging and ointment." + treat_text = "Swiftly apply healing aids such as Synthflesh or regenerative mesh to the wound. \ + Disinfect the wound and surgically debride any infected skin, and wrap in clean gauze / use ointment to prevent further infection. \ + If the limb has locked up, it must be amputated, augmented or treated with cryogenics." + treat_text_short = "Apply healing aid such as regenerative mesh or Synthflesh and disinfect / debride." examine_desc = "appears seriously charred, with aggressive red splotches" occur_text = "chars rapidly, exposing ruined tissue and spreading angry red burns" severity = WOUND_SEVERITY_SEVERE @@ -328,7 +338,10 @@ /datum/wound/burn/flesh/critical name = "Catastrophic Burns" desc = "Patient is suffering near complete loss of tissue and significantly charred muscle and bone, creating life-threatening risk of infection and negligible limb integrity." - treat_text = "Immediate surgical debriding of any infected skin, followed by potent tissue regeneration formula and bandaging." + treat_text = "Immediately apply healing aids such as Synthflesh or regenerative mesh to the wound. \ + Disinfect the wound and surgically debride any infected skin, and wrap in clean gauze / use ointment to prevent further infection. \ + If the limb has locked up, it must be amputated, augmented or treated with cryogenics." + treat_text_short = "Apply healing aid such as regenerative mesh or Synthflesh and disinfect / debride." examine_desc = "is a ruined mess of blanched bone, melted fat, and charred tissue" occur_text = "vaporizes as flesh, bone, and fat melt together in a horrifying mess" severity = WOUND_SEVERITY_CRITICAL diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index 80897c47364f..0a4a557404ab 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -3,6 +3,7 @@ Piercing wounds */ /datum/wound/pierce + undiagnosed_name = "Bleeding Wound" /datum/wound/pierce/bleed name = "Piercing Wound" @@ -34,28 +35,45 @@ return ..() -/datum/wound/pierce/bleed/receive_damage(wounding_type, wounding_dmg, wound_bonus) - if(QDELETED(victim) || victim.stat == DEAD || (wounding_dmg < 5) || !limb.can_bleed() || !victim.blood_volume || !prob(internal_bleeding_chance + wounding_dmg)) +datum/wound/pierce/bleed/receive_damage(wounding_type, wounding_dmg, wound_bonus, attack_direction, damage_source) + if(victim.stat == DEAD || (wounding_dmg < WOUND_MINIMUM_DAMAGE) || wounding_type == WOUND_BURN) return + if(!limb.can_bleed() || !prob(internal_bleeding_chance)) + return + if(limb.body_zone != BODY_ZONE_CHEST) + wounding_dmg *= 0.5 if(limb.current_gauze?.splint_factor) wounding_dmg *= (1 - limb.current_gauze.splint_factor) - var/blood_bled = rand(1, wounding_dmg * internal_bleeding_coefficient) // 12 brute toolbox can cause up to 15/18/21 bloodloss on mod/sev/crit + var/blood_bled = sqrt(wounding_dmg) * internal_bleeding_coefficient * pick(0.75, 1, 1.25, 1.5) switch(blood_bled) - if(1 to 6) - victim.bleed(blood_bled, TRUE) if(7 to 13) - victim.visible_message("Blood droplets fly from the hole in [victim]'s [limb.plaintext_zone].", span_danger("You cough up a bit of blood from the blow to your [limb.plaintext_zone]."), vision_distance=COMBAT_MESSAGE_RANGE) - victim.bleed(blood_bled, TRUE) + victim.visible_message( + span_smalldanger("Blood droplets fly from the hole in [victim]'s [limb.plaintext_zone]."), + span_danger("You cough up a bit of blood from the blow to your [limb.plaintext_zone]."), + vision_distance = COMBAT_MESSAGE_RANGE, + + ) if(14 to 19) - victim.visible_message("A small stream of blood spurts from the hole in [victim]'s [limb.plaintext_zone]!", span_danger("You spit out a string of blood from the blow to your [limb.plaintext_zone]!"), vision_distance=COMBAT_MESSAGE_RANGE) - victim.do_splatter_effect(victim.dir) - victim.bleed(blood_bled) + victim.visible_message( + span_smalldanger("A small stream of blood spurts from the hole in [victim]'s [limb.plaintext_zone]!"), + span_danger("You spit out a string of blood from the blow to your [limb.plaintext_zone]!"), + vision_distance = COMBAT_MESSAGE_RANGE, + + ) + if(20 to INFINITY) - victim.visible_message(span_danger("A spray of blood streams from the gash in [victim]'s [limb.plaintext_zone]!"), span_danger("You choke up on a spray of blood from the blow to your [limb.plaintext_zone]!"), vision_distance=COMBAT_MESSAGE_RANGE) - victim.bleed(blood_bled) - victim.do_splatter_effect(victim.dir) + victim.visible_message( + span_danger("A spray of blood streams from the gash in [victim]'s [limb.plaintext_zone]!"), + span_bolddanger("You choke up on a spray of blood from the blow to your [limb.plaintext_zone]!"), + vision_distance = COMBAT_MESSAGE_RANGE, + + ) victim.add_splatter_floor(get_step(victim.loc, victim.dir)) + victim.bleed(blood_bled, TRUE) + if(blood_bled >= 14) + victim.do_splatter_effect(attack_direction) + /datum/wound/pierce/bleed/get_bleed_rate_of_change() //basically if a species doesn't bleed, the wound is stagnant and will not heal on it's own (nor get worse) if(!limb.can_bleed()) @@ -76,7 +94,7 @@ if(victim.bodytemperature < (BODYTEMP_NORMAL - 10)) adjust_blood_flow(-0.1 * seconds_per_tick) if(SPT_PROB(2.5, seconds_per_tick)) - to_chat(victim, span_notice("You feel the [lowertext(name)] in your [limb.plaintext_zone] firming up from the cold!")) + to_chat(victim, span_notice("You feel the [lowertext(undiagnosed_name || name)] in your [limb.plaintext_zone] firming up from the cold!")) if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS)) adjust_blood_flow(0.25 * seconds_per_tick) // old heparin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first @@ -153,14 +171,15 @@ else user.visible_message(span_danger("[user] begins cauterizing [victim]'s [limb.plaintext_zone] with [I]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]...")) + playsound(user, 'sound/surgery/cautery1.ogg', 75, TRUE) if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) return TRUE + playsound(user, 'sound/surgery/cautery2.ogg', 75, TRUE) + var/bleeding_wording = (!limb.can_bleed() ? "holes" : "bleeding") user.visible_message(span_green("[user] cauterizes some of the [bleeding_wording] on [victim]."), span_green("You cauterize some of the [bleeding_wording] on [victim].")) - limb.receive_damage(burn = 2 + severity, wound_bonus = CANT_WOUND) - if(prob(30)) - victim.emote("scream") + victim.apply_damage(2 + severity, BURN, limb, wound_bonus = CANT_WOUND) var/blood_cauterized = (0.6 / (self_penalty_mult * improv_penalty_mult)) adjust_blood_flow(-blood_cauterized) @@ -190,7 +209,10 @@ /datum/wound/pierce/bleed/moderate name = "Minor Skin Breakage" desc = "Patient's skin has been broken open, causing severe bruising and minor internal bleeding in affected area." - treat_text = "Treat affected site with bandaging or exposure to extreme cold. In dire cases, brief exposure to vacuum may suffice." // space is cold in ss13, so it's like an ice pack! + treat_text = "Apply bandaging or suturing to the wound, make use of blood clotting agents, \ + cauterization, or in extreme circumstances, exposure to extreme cold or vaccuum. \ + Follow with food and a rest period." + treat_text_short = "Apply bandaging or suturing." examine_desc = "has a small, circular hole, gently bleeding" occur_text = "spurts out a thin stream of blood" sound_effect = 'sound/effects/wounds/pierce1.ogg' @@ -221,7 +243,10 @@ /datum/wound/pierce/bleed/severe name = "Open Puncture" desc = "Patient's internal tissue is penetrated, causing sizeable internal bleeding and reduced limb stability." - treat_text = "Repair punctures in skin by suture or cautery, extreme cold may also work." + treat_text = "Swiftly apply bandaging or suturing to the wound, make use of blood clotting agents or saline-glucose, \ + cauterization, or in extreme circumstances, exposure to extreme cold or vaccuum. \ + Follow with iron supplements and a rest period." + treat_text_short = "Apply bandaging, suturing, clotting agents, or cauterization." examine_desc = "is pierced clear through, with bits of tissue obscuring the open hole" occur_text = "looses a violent spray of blood, revealing a pierced wound" sound_effect = 'sound/effects/wounds/pierce2.ogg' @@ -251,7 +276,10 @@ /datum/wound/pierce/bleed/critical name = "Ruptured Cavity" desc = "Patient's internal tissue and circulatory system is shredded, causing significant internal bleeding and damage to internal organs." - treat_text = "Surgical repair of puncture wound, followed by supervised resanguination." + treat_text = "Immediately apply bandaging or suturing to the wound, make use of blood clotting agents or saline-glucose, \ + cauterization, or in extreme circumstances, exposure to extreme cold or vaccuum. \ + Follow with supervised resanguination." + treat_text_short = "Apply bandaging, suturing, clotting agents, or cauterization." examine_desc = "is ripped clear through, barely held together by exposed bone" occur_text = "blasts apart, sending chunks of viscera flying in all directions" sound_effect = 'sound/effects/wounds/pierce3.ogg' diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm index b0edc7f25074..5f39ab5164de 100644 --- a/code/datums/wounds/slash.dm +++ b/code/datums/wounds/slash.dm @@ -5,6 +5,7 @@ /datum/wound/slash name = "Slashing (Cut) Wound" + undiagnosed_name = "Cut" sound_effect = 'sound/weapons/slice.ogg' /datum/wound_pregen_data/flesh_slash @@ -317,7 +318,9 @@ /datum/wound/slash/flesh/moderate name = "Rough Abrasion" desc = "Patient's skin has been badly scraped, generating moderate blood loss." - treat_text = "Application of clean bandages or first-aid grade sutures, followed by food and rest." + treat_text = "Apply bandaging or suturing to the wound. \ + Follow up with food and a rest period." + treat_text_short = "Apply bandaging or suturing." examine_desc = "has an open cut" occur_text = "is cut open, slowly leaking blood" sound_effect = 'sound/effects/wounds/blood1.ogg' @@ -346,7 +349,10 @@ /datum/wound/slash/flesh/severe name = "Open Laceration" desc = "Patient's skin is ripped clean open, allowing significant blood loss." - treat_text = "Speedy application of first-aid grade sutures and clean bandages, followed by vitals monitoring to ensure recovery." + treat_text = "Swiftly apply bandaging or suturing to the wound, \ + or make use of blood clotting agents or cauterization. \ + Follow up with iron supplements or saline-glucose and a rest period." + treat_text_short = "Apply bandaging, suturing, clotting agents, or cauterization." examine_desc = "has a severe cut" occur_text = "is ripped open, veins spurting blood" sound_effect = 'sound/effects/wounds/blood2.ogg' @@ -376,7 +382,10 @@ /datum/wound/slash/flesh/critical name = "Weeping Avulsion" desc = "Patient's skin is completely torn open, along with significant loss of tissue. Extreme blood loss will lead to quick death without intervention." - treat_text = "Immediate bandaging and either suturing or cauterization, followed by supervised resanguination." + treat_text = "Immediately apply bandaging or suturing to the wound, \ + or make use of blood clotting agents or cauterization. \ + Follow up supervised resanguination." + treat_text_short = "Apply bandaging, suturing, clotting agents, or cauterization." examine_desc = "is carved down to the bone, spraying blood wildly" occur_text = "is torn open, spraying blood wildly" sound_effect = 'sound/effects/wounds/blood3.ogg' diff --git a/code/game/atom_defense.dm b/code/game/atom_defense.dm index ea9b8994bc78..169d0bf71a80 100644 --- a/code/game/atom_defense.dm +++ b/code/game/atom_defense.dm @@ -131,6 +131,10 @@ /// A cut-out proc for [/atom/proc/bullet_act] so living mobs can have their own armor behavior checks without causing issues with needing their own on_hit call /atom/proc/check_projectile_armor(def_zone, obj/projectile/impacting_projectile, is_silent) - if(uses_integrity) - return clamp(PENETRATE_ARMOUR(get_armor_rating(impacting_projectile.armor_flag), impacting_projectile.armour_penetration), 0, 100) - return 0 + if(!uses_integrity) + return 0 + + . = clamp(PENETRATE_ARMOUR(get_armor_rating(impacting_projectile.armor_flag), impacting_projectile.armour_penetration), 0, 100) + if(impacting_projectile.grazing) + . += 50 + return . diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index b6ce3135c571..655e7bcb6e4c 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -502,11 +502,9 @@ var/render_list = "" var/advised = FALSE - for(var/limb in patient.get_wounded_bodyparts()) - var/obj/item/bodypart/wounded_part = limb - render_list += "Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]" - for(var/limb_wound in wounded_part.wounds) - var/datum/wound/current_wound = limb_wound + for(var/obj/item/bodypart/wounded_part as anything in patient.get_wounded_bodyparts()) + render_list += "Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.plaintext_zone]" + for(var/datum/wound/current_wound as anything in wounded_part.wounds) render_list += "
[simple_scan ? current_wound.get_simple_scanner_description() : current_wound.get_scanner_description()]
\n" if (scanner.give_wound_treatment_bonus) ADD_TRAIT(current_wound, TRAIT_WOUND_SCANNED, ANALYZER_TRAIT) diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 66f7b9b07e90..f37d84088ed2 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -41,7 +41,7 @@ ) if(hitting_projectile.suppressed != SUPPRESSED_VERY) visible_message( - span_danger("[src] is hit by \a [hitting_projectile][damage_sustained ? "" : ", without leaving a mark"]!"), + span_danger("[src] is hit by \a [hitting_projectile.generic_name || hitting_projectile][damage_sustained ? "" : ", without leaving a mark"]!"), vision_distance = COMBAT_MESSAGE_RANGE, ) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 579c3fa62cec..97e7641b4e0e 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -145,7 +145,11 @@ SET_PLANE(occupant_vis, PLANE_TO_TRUE(occupant_vis.plane), new_turf) /obj/machinery/atmospherics/components/unary/cryo_cell/set_occupant(atom/movable/new_occupant) + if(occupant && isnull(new_occupant)) + REMOVE_TRAIT(occupant, TRAIT_ASSISTED_BREATHING, REF(src)) . = ..() + if(occupant && on) + ADD_TRAIT(occupant, TRAIT_ASSISTED_BREATHING, REF(src)) update_appearance() /obj/machinery/atmospherics/components/unary/cryo_cell/on_construction(mob/user) @@ -259,6 +263,10 @@ else update_use_power(IDLE_POWER_USE) update_appearance() + if(occupant) + ADD_TRAIT(occupant, TRAIT_ASSISTED_BREATHING, REF(src)) + else + REMOVE_TRAIT(occupant, TRAIT_ASSISTED_BREATHING, REF(src)) /obj/machinery/atmospherics/components/unary/cryo_cell/on_set_is_operational(old_value) if(old_value) //Turned off @@ -383,7 +391,7 @@ return air1.remove(air1.total_moles() * breath_percentage) /obj/machinery/atmospherics/components/unary/cryo_cell/assume_air(datum/gas_mixture/giver) - airs[1].merge(giver) + return airs[1].merge(giver) /obj/machinery/atmospherics/components/unary/cryo_cell/relaymove(mob/living/user, direction) if(message_cooldown <= world.time) diff --git a/code/modules/mob/living/basic/basic_defense.dm b/code/modules/mob/living/basic/basic_defense.dm index 27ff06b8bd41..e4b51033dfcd 100644 --- a/code/modules/mob/living/basic/basic_defense.dm +++ b/code/modules/mob/living/basic/basic_defense.dm @@ -128,7 +128,7 @@ return TRUE /mob/living/basic/check_projectile_armor(def_zone, obj/projectile/impacting_projectile, is_silent) - return 0 + return impacting_projectile.grazing ? 50 : 0 /mob/living/basic/ex_act(severity, target, origin) . = ..() diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 3b21192da75d..b0c04e8f2eb9 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -139,15 +139,13 @@ var/exterior_ready_to_dismember = (!has_exterior || ((mangled_state & BODYPART_MANGLED_EXTERIOR))) var/interior_ready_to_dismember = (!has_interior || ((mangled_state & BODYPART_MANGLED_INTERIOR))) - var/dismemberable = ((hit_bodypart.dismemberable_by_wound()) || hit_bodypart.dismemberable_by_total_damage()) + var/dismemberable = hit_bodypart.dismemberable_by_wound() || hit_bodypart.dismemberable_by_total_damage() if (dismemberable) - extra_wound_details = ", threatening to sever it entirely" - else if((has_interior && (has_exterior && exterior_ready_to_dismember) && I.get_sharpness())) - var/bone_text = hit_bodypart.get_internal_description() - extra_wound_details = ", [I.get_sharpness() == SHARP_EDGED ? "slicing" : "piercing"] through to the [bone_text]" - else if(has_exterior && ((has_interior && interior_ready_to_dismember) && I.get_sharpness())) - var/tissue_text = hit_bodypart.get_external_description() - extra_wound_details = ", [I.get_sharpness() == SHARP_EDGED ? "slicing" : "piercing"] at the remaining [tissue_text]" + extra_wound_details = hit_bodypart.get_soon_dismember_message() + else if(has_interior && (has_exterior && exterior_ready_to_dismember) && I.get_sharpness()) + extra_wound_details = ", [I.get_sharpness() == SHARP_EDGED ? "slicing" : "piercing"] through to the [hit_bodypart.get_internal_description()]" + else if(has_exterior && (has_interior && interior_ready_to_dismember) && I.get_sharpness()) + extra_wound_details = ", [I.get_sharpness() == SHARP_EDGED ? "slicing" : "piercing"] at the remaining [hit_bodypart.get_external_description()]" var/message_hit_area = "" if(hit_area) @@ -166,6 +164,18 @@ to_chat(user, span_danger("[attack_message_attacker]")) return TRUE +/mob/living/carbon/attack_animal(mob/living/simple_animal/user, list/modifiers) + . = ..() + if(. <= 0) + return + if(user.wound_bonus != CANT_WOUND) + return + // Snowflake mcsnowflake but mobs which can't wound should still capable of causing IB + var/obj/item/bodypart/affecting = get_bodypart(user.zone_selected) || get_bodypart(BODY_ZONE_CHEST) + var/ib_prob = . + rand(-10, 40) - getarmor(affecting, WOUND) + if(ib_prob < 45) + return + affecting.force_wound_upwards(/datum/wound/bleed_internal, wound_source = user) /mob/living/carbon/attack_drone(mob/living/basic/drone/user) return //so we don't call the carbon's attack_hand(). @@ -519,12 +529,12 @@ add_mood_event("hug", /datum/mood_event/bad_touch_bear_hug) // Let people know if they hugged someone really warm or really cold - if(helper.bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT || helper.has_status_effect(/datum/status_effect/bloodsucker_sol)) // monkestation edit: bloodsucker sol + if(helper.bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT) to_chat(src, span_warning("It feels like [helper] is over heating as [helper.p_they()] hug[helper.p_s()] you.")) else if(helper.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT) to_chat(src, span_warning("It feels like [helper] is freezing as [helper.p_they()] hug[helper.p_s()] you.")) - if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT || has_status_effect(/datum/status_effect/bloodsucker_sol)) // monkestation edit: bloodsucker sol + if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT) to_chat(helper, span_warning("It feels like [src] is over heating as you hug [p_them()].")) else if(bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT) to_chat(helper, span_warning("It feels like [src] is freezing as you hug [p_them()].")) diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm index dd32d275108b..5e3d48a57583 100644 --- a/code/modules/mob/living/carbon/carbon_movement.dm +++ b/code/modules/mob/living/carbon/carbon_movement.dm @@ -15,7 +15,8 @@ adjust_nutrition(-(HUNGER_FACTOR) * 0.05) if(m_intent == MOVE_INTENT_RUN) adjust_nutrition(-(HUNGER_FACTOR) * 0.1) - + if(!moving_diagonally) + SEND_SIGNAL(src, COMSIG_CARBON_STEP, NewLoc, direct) /mob/living/carbon/set_usable_hands(new_value) . = ..() diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index cc6e107f313a..bd0a75c88735 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -1599,36 +1599,29 @@ GLOBAL_LIST_EMPTY(features_by_species) // display alerts based on how hot it is // Can't be a switch due to http://www.byond.com/forum/post/2750423 if(bodytemp in bodytemp_heat_damage_limit to BODYTEMP_HEAT_WARNING_2) - humi.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 1) + humi.apply_status_effect(/datum/status_effect/thermia/hyper/one) else if(bodytemp in BODYTEMP_HEAT_WARNING_2 to BODYTEMP_HEAT_WARNING_3) - humi.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 2) + humi.apply_status_effect(/datum/status_effect/thermia/hyper/two) else - humi.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 3) + humi.apply_status_effect(/datum/status_effect/thermia/hyper/three) // Body temperature is too cold, and we do not have resist traits else if(bodytemp < bodytemp_cold_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTCOLD)) - // clear any hot moods and apply cold mood - humi.clear_mood_event("hot") - humi.add_mood_event("cold", /datum/mood_event/cold) - // Apply cold slow down - humi.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((bodytemp_cold_damage_limit - humi.bodytemperature) / COLD_SLOWDOWN_FACTOR)) + var/slowdown_mod = (bodytemp_cold_damage_limit - humi.bodytemperature) / COLD_SLOWDOWN_FACTOR // Display alerts based how cold it is // Can't be a switch due to http://www.byond.com/forum/post/2750423 if(bodytemp in BODYTEMP_COLD_WARNING_2 to bodytemp_cold_damage_limit) - humi.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1) + humi.apply_status_effect(/datum/status_effect/thermia/hypo/one, slowdown_mod) else if(bodytemp in BODYTEMP_COLD_WARNING_3 to BODYTEMP_COLD_WARNING_2) - humi.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 2) + humi.apply_status_effect(/datum/status_effect/thermia/hypo/two, slowdown_mod) else - humi.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3) + humi.apply_status_effect(/datum/status_effect/thermia/hypo/three, slowdown_mod) // We are not to hot or cold, remove status and moods // Optimization here, we check these things based off the old temperature to avoid unneeded work // We're not perfect about this, because it'd just add more work to the base case, and resistances are rare else if (old_bodytemp > bodytemp_heat_damage_limit || old_bodytemp < bodytemp_cold_damage_limit) - humi.clear_alert(ALERT_TEMPERATURE) - humi.remove_movespeed_modifier(/datum/movespeed_modifier/cold) - humi.clear_mood_event("cold") - humi.clear_mood_event("hot") + humi.remove_status_effect(/datum/status_effect/thermia) // Store the old bodytemp for future checking humi.old_bodytemperature = bodytemp diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 656684c4e15f..7f1950d5ac1d 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -21,7 +21,7 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift) else new /obj/effect/decal/remains/human(loc) -/mob/living/carbon/human/death(gibbed) +/mob/living/carbon/human/death(gibbed, cause_of_death = get_cause_of_death()) if(stat == DEAD) return stop_sound_channel(CHANNEL_HEARTBEAT) @@ -49,6 +49,67 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift) to_chat(src, span_warning("You have died. Barring complete bodyloss, you can in most cases be revived by other players. If you do not wish to be brought back, use the \"Do Not Resuscitate\" verb in the ghost tab.")) to_chat(src, span_greentext("You can no longer recall who was responsible for your death.")) // MONKESTATION EDIT: making an explicit request that someone review DA RULEZ. + var/death_block = "" + death_block += span_danger("
You have succumbed to [cause_of_death].
") + death_block += "
" + death_block += span_danger("Barring complete bodyloss, you can (in most cases) be revived by other players. \ + If you do not wish to be brought back, use the \"Do Not Resuscitate\" verb in the ghost tab.") + to_chat(src, examine_block(death_block)) + +/mob/living/carbon/human/proc/get_cause_of_death(probable_cause) + switch(probable_cause) + // This should all be refactored later it's a bit of a mess ngl + if(null, "revival_sickess", "anesthetics") + return "unknown causes" + + if(OXY_DAMAGE) + var/obj/item/organ/internal/lungs/lungs = get_organ_slot(ORGAN_SLOT_LUNGS) + if(isnull(lungs) || (lungs.organ_flags & ORGAN_FAILING)) + return "lung failure" + + if(!HAS_TRAIT(src, TRAIT_NOBLOOD) && blood_volume < BLOOD_VOLUME_BAD) + return BLOOD_LOSS + + if(TOX_DAMAGE) + var/obj/item/organ/internal/liver/liver = get_organ_slot(ORGAN_SLOT_LIVER) + if(isnull(liver) || (liver.organ_flags & ORGAN_FAILING)) + return "liver failure" + + var/datum/reagent/toxin/most_toxic + for(var/datum/reagent/toxin/poison in reagents?.reagent_list) + if(!most_toxic || most_toxic.toxpwr < poison.toxpwr) + most_toxic = poison + + if(most_toxic) + return "[lowertext(most_toxic.name)] poisoning" + + if("heart_attack") + return "cardiac arrest" + + if("drunk") + var/datum/reagent/consumable/ethanol/most_alcohol + for(var/datum/reagent/consumable/ethanol/alcohol in reagents?.reagent_list) + if(!most_alcohol || most_alcohol.boozepwr < alcohol.boozepwr) + most_alcohol = alcohol + + if(most_alcohol) + return "alcohol poisoning ([lowertext(most_alcohol.name)])" + + return "alcohol poisoning" + + if("thermia") + if(bodytemperature < get_body_temp_normal()) + return "hypothermia" + return "hyperthermia" + + else + if(findtext(probable_cause, "disease")) + return "disease" + if(findtext(probable_cause, "addiction")) + return "addiction" + + return probable_cause + /mob/living/carbon/human/proc/reagents_readout() var/readout = "Blood:" for(var/datum/reagent/reagent in reagents?.reagent_list) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 6762a99880aa..b9bd66482014 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -48,6 +48,8 @@ become_blind(NO_EYES) // Mobs cannot taste anything without a tongue; the tongue organ removes this on Insert ADD_TRAIT(src, TRAIT_AGEUSIA, NO_TONGUE_TRAIT) + // No lungs until you get lungs + apply_status_effect(/datum/status_effect/lungless) /mob/living/carbon/human/proc/setup_human_dna() //initialize dna. for spawned humans; overwritten by other code @@ -901,15 +903,14 @@ /mob/living/carbon/human/updatehealth() . = ..() dna?.species.spec_updatehealth(src) - if(HAS_TRAIT(src, TRAIT_IGNOREDAMAGESLOWDOWN)) - remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown) - remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying) - return + update_damage_movespeed() + +/mob/living/carbon/human/proc/update_damage_movespeed() var/health_deficiency = max((maxHealth - health), staminaloss) if(health_deficiency >= 40) add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, multiplicative_slowdown = health_deficiency / 75) add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, multiplicative_slowdown = health_deficiency / 25) - else + else if(LAZYACCESS(movespeed_modification, "[/datum/movespeed_modifier/damage_slowdown]")) remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown) remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 6ed3dd274433..8a5d6e94bdd1 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -71,37 +71,25 @@ return (occupied_space.contents_pressure_protection * ONE_ATMOSPHERE + (1 - occupied_space.contents_pressure_protection) * pressure) return pressure -/mob/living/carbon/human/breathe() - if(!HAS_TRAIT(src, TRAIT_NOBREATH)) - return ..() +/mob/living/carbon/human/check_breath(datum/gas_mixture/breath, skip_breath = FALSE) + var/obj/item/organ/internal/lungs/human_lungs = get_organ_slot(ORGAN_SLOT_LUNGS) + if(human_lungs) + return human_lungs.check_breath(breath, src, skip_breath) -/mob/living/carbon/human/check_breath(datum/gas_mixture/breath) - var/L = get_organ_slot(ORGAN_SLOT_LUNGS) + failed_last_breath = TRUE - if(!L) - if(health >= crit_threshold) - adjustOxyLoss(HUMAN_MAX_OXYLOSS + 1) - else if(!HAS_TRAIT(src, TRAIT_NOCRITDAMAGE)) - adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS) + var/datum/species/human_species = dna.species - failed_last_breath = TRUE - - var/datum/species/S = dna.species - - if(S.breathid == "o2") + switch(human_species.breathid) + if("o2") throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy) - else if(S.breathid == "plas") + if("plas") throw_alert(ALERT_NOT_ENOUGH_PLASMA, /atom/movable/screen/alert/not_enough_plas) - else if(S.breathid == "co2") + if("co2") throw_alert(ALERT_NOT_ENOUGH_CO2, /atom/movable/screen/alert/not_enough_co2) - else if(S.breathid == "n2") + if("n2") throw_alert(ALERT_NOT_ENOUGH_NITRO, /atom/movable/screen/alert/not_enough_nitro) - - return FALSE - else - if(istype(L, /obj/item/organ/internal/lungs)) - var/obj/item/organ/internal/lungs/lun = L - lun.check_breath(breath,src) + return FALSE /// Environment handlers for species /mob/living/carbon/human/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 446f666cf0bf..6494e1cf3974 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -53,109 +53,84 @@ // Start of a breath chain, calls [carbon/proc/breathe()] /mob/living/carbon/handle_breathing(seconds_per_tick, times_fired) + if(HAS_TRAIT(src, TRAIT_NOBREATH)) + return + var/next_breath = 4 - var/obj/item/organ/internal/lungs/L = get_organ_slot(ORGAN_SLOT_LUNGS) - var/obj/item/organ/internal/heart/H = get_organ_slot(ORGAN_SLOT_HEART) - if(L) - if(L.damage > L.high_threshold) - next_breath-- - if(H) - if(H.damage > H.high_threshold) - next_breath-- + var/obj/item/organ/internal/lungs/lungs = get_organ_slot(ORGAN_SLOT_LUNGS) + var/obj/item/organ/internal/heart/heart = get_organ_slot(ORGAN_SLOT_HEART) + if(lungs?.damage > lungs?.high_threshold) + next_breath -= 1 + if(heart?.damage > heart?.high_threshold) + next_breath -= 1 if((times_fired % next_breath) == 0 || failed_last_breath) - breathe(seconds_per_tick, times_fired) //Breathe per 4 ticks if healthy, down to 2 if our lungs or heart are damaged, unless suffocating + // Breathe per 4 ticks if healthy, down to 2 if our lungs or heart are damaged, unless suffocating + breathe(seconds_per_tick, times_fired, failed_last_breath ? 1 : next_breath) if(failed_last_breath) add_mood_event("suffocation", /datum/mood_event/suffocation) else clear_mood_event("suffocation") - else - if(isobj(loc)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src,0) - -// Second link in a breath chain, calls [carbon/proc/check_breath()] -/mob/living/carbon/proc/breathe(seconds_per_tick, times_fired) - var/obj/item/organ/internal/lungs = get_organ_slot(ORGAN_SLOT_LUNGS) - if(SEND_SIGNAL(src, COMSIG_CARBON_ATTEMPT_BREATHE) & COMSIG_CARBON_BLOCK_BREATH) - return + else if(isobj(loc)) + var/obj/location_as_object = loc + location_as_object.handle_internal_lifeform(src, 0) - SEND_SIGNAL(src, COMSIG_CARBON_PRE_BREATHE) +/mob/living/carbon/proc/breathe(seconds_per_tick, times_fired, next_breath = 4) + var/datum/gas_mixture/environment = loc?.return_air() + var/datum/gas_mixture/breath - var/datum/gas_mixture/environment - if(loc) - environment = loc.return_air() + if(!HAS_TRAIT(src, TRAIT_ASSISTED_BREATHING)) + if(stat == HARD_CRIT) + losebreath = max(losebreath, 1) + else if(HAS_TRAIT(src, TRAIT_LABOURED_BREATHING)) + losebreath += (1 / next_breath) - var/datum/gas_mixture/breath - if(!get_organ_slot(ORGAN_SLOT_BREATHING_TUBE)) - if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby?.grab_state >= GRAB_KILL) || (lungs?.organ_flags & ORGAN_FAILING)) - losebreath++ //You can't breath at all when in critical or when being choked, so you're going to miss a breath + if(losebreath < 1) + var/pre_sig_return = SEND_SIGNAL(src, COMSIG_CARBON_ATTEMPT_BREATHE, seconds_per_tick, times_fired) + if(pre_sig_return & BREATHE_BLOCK_BREATH) + return - else if(health <= crit_threshold) - losebreath += 0.25 //You're having trouble breathing in soft crit, so you'll miss a breath one in four times + if(pre_sig_return & BREATHE_SKIP_BREATH) + losebreath = max(losebreath, 1) - //Suffocate - if(losebreath >= 1) //You've missed a breath, take oxy damage - losebreath-- + // Suffocate + var/skip_breath = FALSE + if(losebreath >= 1) + losebreath -= 1 if(prob(10)) emote("gasp") if(isobj(loc)) var/obj/loc_as_obj = loc - loc_as_obj.handle_internal_lifeform(src,0) - else - //Breathe from internal + loc_as_obj.handle_internal_lifeform(src, 0) + skip_breath = TRUE + + // Breathe from internals or externals (name is misleading) + else if(internal || external) breath = get_breath_from_internal(BREATH_VOLUME) - if(isnull(breath)) //in case of 0 pressure internals - - if(isobj(loc)) //Breathe from loc as object - var/obj/loc_as_obj = loc - breath = loc_as_obj.handle_internal_lifeform(src, BREATH_VOLUME) - else if(isturf(loc)) //Breathe from loc as turf - breath_airborne_diseases() //monkestation edit - VIROLOGY - var/turf/our_turf = loc - if(our_turf.liquids && !HAS_TRAIT(src, TRAIT_NOBREATH) && ((body_position == LYING_DOWN && our_turf.liquids.liquid_state >= LIQUID_STATE_WAIST) || (body_position == STANDING_UP && our_turf.liquids.liquid_state >= LIQUID_STATE_FULLTILE))) - //Officially trying to breathe underwater - if(HAS_TRAIT(src, TRAIT_WATER_BREATHING)) - failed_last_breath = FALSE - clear_alert("not_enough_oxy") - return FALSE - adjustOxyLoss(3) - failed_last_breath = TRUE - if(oxyloss <= OXYGEN_DAMAGE_CHOKING_THRESHOLD && stat == CONSCIOUS) - to_chat(src, span_userdanger("You hold in your breath!")) - else - //Try and drink water - our_turf.liquids.liquid_group.transfer_to_atom(src, CHOKE_REAGENTS_INGEST_ON_BREATH_AMOUNT) - visible_message(span_warning("[src] chokes on water!"), span_userdanger("You're choking on water!")) - return FALSE - if(isopenturf(our_turf)) - var/turf/open/open_turf = our_turf - if(open_turf.pollution) - if(next_smell <= world.time) - next_smell = world.time + SMELL_COOLDOWN - open_turf.pollution.smell_act(src) - open_turf.pollution.breathe_act(src) - - var/breath_moles = 0 - if(environment) - breath_moles = environment.total_moles() * BREATH_PERCENTAGE - - breath = loc.remove_air(breath_moles) - else //Breathe from loc as obj again - if(isobj(loc)) - var/obj/loc_as_obj = loc - loc_as_obj.handle_internal_lifeform(src,0) - - check_breath(breath) + if(breath == SKIP_INTERNALS) //in case of 0 pressure internals + breath = get_breath_from_surroundings(environment, BREATH_VOLUME) + + else if(isobj(loc)) //Breathe from loc as obj again + var/obj/loc_as_obj = loc + loc_as_obj.handle_internal_lifeform(src, 0) + + // Breathe from air + else + breath = get_breath_from_surroundings(environment, BREATH_VOLUME) + + check_breath(breath, skip_breath) if(breath) - loc.assume_air(breath) + exhale_breath(breath) + +/mob/living/carbon/proc/exhale_breath(datum/gas_mixture/breath) + if(SEND_SIGNAL(src, COMSIG_CARBON_BREATH_EXHALE, breath) & BREATHE_EXHALE_HANDLED) + return + loc.assume_air(breath) /mob/living/carbon/proc/has_smoke_protection() - if(HAS_TRAIT(src, TRAIT_NOBREATH)) - return TRUE - return FALSE + return HAS_TRAIT(src, TRAIT_NOBREATH) /** * This proc tests if the lungs can breathe, if the mob can breathe a given gas mixture, and throws/clears gas alerts. @@ -166,276 +141,11 @@ * * Arguments: * * breath: A gas mixture to test, or null. + * * skip_breath: Used to differentiate between a failed breath and a lack of breath. + * A mob suffocating due to being in a vacuum may be treated differently than a mob suffocating due to lung failure. */ -/mob/living/carbon/proc/check_breath(datum/gas_mixture/breath) - . = TRUE - - if(status_flags & GODMODE) - failed_last_breath = FALSE - clear_alert(ALERT_NOT_ENOUGH_OXYGEN) - return - - if(HAS_TRAIT(src, TRAIT_NOBREATH)) - return - - // Breath may be null, so use a fallback "empty breath" for convenience. - if(!breath) - /// Fallback "empty breath" for convenience. - var/static/datum/gas_mixture/immutable/empty_breath = new(BREATH_VOLUME) - breath = empty_breath - - // Ensure gas volumes are present. - breath.assert_gases(/datum/gas/bz, /datum/gas/carbon_dioxide, /datum/gas/freon, /datum/gas/plasma, /datum/gas/pluoxium, /datum/gas/miasma, /datum/gas/nitrous_oxide, /datum/gas/nitrium, /datum/gas/oxygen) - - /// The list of gases in the breath. - var/list/breath_gases = breath.gases - /// Indicates if there are moles of gas in the breath. - var/has_moles = breath.total_moles() != 0 - - var/obj/item/organ/internal/lungs = get_organ_slot(ORGAN_SLOT_LUNGS) - // Indicates if lungs can breathe without gas. - var/can_breathe_vacuum = FALSE - if(lungs) - // Breathing with lungs. - // Check for vacuum-adapted lungs. - can_breathe_vacuum = HAS_TRAIT(lungs, TRAIT_SPACEBREATHING) - else - // Lungs are missing! Can't breathe. - // Simulates breathing zero moles of gas. - has_moles = FALSE - // Extra damage, let God sort ’em out! - adjustOxyLoss(2) - - /// Minimum O2 before suffocation. - var/safe_oxygen_min = 16 - /// Maximum CO2 before side-effects. - var/safe_co2_max = 10 - /// Maximum Plasma before side-effects. - var/safe_plas_max = 0.05 - /// Maximum Pluoxum before side-effects. - var/gas_stimulation_min = 0.002 // For Pluoxium - // Vars for N2O induced euphoria, stun, and sleep. - var/n2o_euphoria = EUPHORIA_LAST_FLAG - var/n2o_para_min = 1 - var/n2o_sleep_min = 5 - - // Partial pressures in our breath - // Main gases. - var/pluoxium_pp = 0 - var/o2_pp = 0 - var/plasma_pp = 0 - var/co2_pp = 0 - // Trace gases ordered alphabetically. - var/bz_pp = 0 - var/freon_pp = 0 - var/n2o_pp = 0 - var/nitrium_pp = 0 - var/miasma_pp = 0 - - // Check for moles of gas and handle partial pressures / special conditions. - if(has_moles) - // Breath has more than 0 moles of gas. - // Partial pressures of "main gases". - pluoxium_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/pluoxium][MOLES]) - o2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/oxygen][MOLES] + (8 * pluoxium_pp)) - plasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/plasma][MOLES]) - co2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/carbon_dioxide][MOLES]) - // Partial pressures of "trace" gases. - bz_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/bz][MOLES]) - freon_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/freon][MOLES]) - miasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/miasma][MOLES]) - n2o_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrous_oxide][MOLES]) - nitrium_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrium][MOLES]) - - // Breath has 0 moles of gas. - else if(can_breathe_vacuum) - // The mob can breathe anyways. What are you? Some bottom-feeding, scum-sucking algae eater? - failed_last_breath = FALSE - // Vacuum-adapted lungs regenerate oxyloss even when breathing nothing. - if(health >= crit_threshold) - adjustOxyLoss(-5) - else - // Can't breathe! Lungs are missing, and/or breath is empty. - . = FALSE - failed_last_breath = TRUE - - //-- PLUOXIUM --// - // Behaves like Oxygen with 8X efficacy, but metabolizes into a reagent. - if(pluoxium_pp) - // Inhale Pluoxium. Exhale nothing. - breath_gases[/datum/gas/pluoxium][MOLES] = 0 - // Metabolize to reagent. - if(pluoxium_pp > gas_stimulation_min) - var/existing = reagents.get_reagent_amount(/datum/reagent/pluoxium) - reagents.add_reagent(/datum/reagent/pluoxium, max(0, 1 - existing)) - - //-- OXYGEN --// - // Carbons need only Oxygen to breathe properly. - var/oxygen_used = 0 - // Minimum Oxygen effects. "Too little oxygen!" - if(!can_breathe_vacuum && (o2_pp < safe_oxygen_min)) - // Breathe insufficient amount of O2. - oxygen_used = handle_suffocation(o2_pp, safe_oxygen_min, breath_gases[/datum/gas/oxygen][MOLES]) - throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy) - else - // Enough oxygen to breathe. - failed_last_breath = FALSE - clear_alert(ALERT_NOT_ENOUGH_OXYGEN) - if(o2_pp) - // Inhale O2. - oxygen_used = breath_gases[/datum/gas/oxygen][MOLES] - // Heal mob if not in crit. - if(health >= crit_threshold) - adjustOxyLoss(-5) - // Exhale equivalent amount of CO2. - if(o2_pp) - breath_gases[/datum/gas/oxygen][MOLES] -= oxygen_used - breath_gases[/datum/gas/carbon_dioxide][MOLES] += oxygen_used - - //-- CARBON DIOXIDE --// - // Maximum CO2 effects. "Too much CO2!" - if(co2_pp > safe_co2_max) - // CO2 side-effects. - // Give the mob a chance to notice. - if(prob(20)) - emote("cough") - // If it's the first breath with too much CO2 in it, lets start a counter, then have them pass out after 12s or so. - if(!co2overloadtime) - co2overloadtime = world.time - else if((world.time - co2overloadtime) > 12 SECONDS) - throw_alert(ALERT_TOO_MUCH_CO2, /atom/movable/screen/alert/too_much_co2) - Unconscious(6 SECONDS) - // Lets hurt em a little, let them know we mean business. - adjustOxyLoss(3) - // They've been in here 30s now, start to kill them for their own good! - if((world.time - co2overloadtime) > 30 SECONDS) - adjustOxyLoss(8) - else - // Reset side-effects. - co2overloadtime = 0 - clear_alert(ALERT_TOO_MUCH_CO2) - - //-- PLASMA --// - // Maximum Plasma effects. "Too much Plasma!" - if(plasma_pp > safe_plas_max) - // Plasma side-effects. - var/ratio = (breath_gases[/datum/gas/plasma][MOLES] / safe_plas_max) * 10 - adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE)) - throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas) - else - // Reset side-effects. - clear_alert(ALERT_TOO_MUCH_PLASMA) - - //-- TRACES --// - // If there's some other funk in the air lets deal with it here. - - //-- BZ --// - // (Facepunch port of their Agent B) - if(bz_pp) - if(bz_pp > 1) - adjust_hallucinations(20 SECONDS) - else if(bz_pp > 0.01) - adjust_hallucinations(10 SECONDS) - - //-- FREON --// - if(freon_pp) - adjustFireLoss(freon_pp * 0.25) - - //-- MIASMA --// - if(!miasma_pp) - // Clear moodlet if no miasma at all. - clear_mood_event("smell") - else - // Miasma sickness - if(prob(1 * miasma_pp)) - var/virus_choice = pick(subtypesof(/datum/disease/advanced)- typesof(/datum/disease/advanced/premade)) - var/list/anti = list( - ANTIGEN_BLOOD = 1, - ANTIGEN_COMMON = 1, - ANTIGEN_RARE = 2, - ANTIGEN_ALIEN = 0, - ) - var/list/bad = list( - EFFECT_DANGER_HELPFUL = 0, - EFFECT_DANGER_FLAVOR = 1, - EFFECT_DANGER_ANNOYING = 2, - EFFECT_DANGER_HINDRANCE = 3, - EFFECT_DANGER_HARMFUL = 1, - EFFECT_DANGER_DEADLY = 0, - ) - var/datum/disease/advanced/new_disease = new virus_choice - new_disease.makerandom(list(50,90),list(50,100),anti,bad,src) - new_disease.carrier = TRUE - new_disease = new_disease.name - infect_disease(new_disease, TRUE, "Miasma Disease Infection [key_name(src)]") - // Miasma side-effects. - switch(miasma_pp) - if(0.25 to 5) - // At lower pp, give out a little warning - clear_mood_event("smell") - if(prob(5)) - to_chat(src, span_notice("There is an unpleasant smell in the air.")) - if(5 to 20) - //At somewhat higher pp, warning becomes more obvious - if(prob(15)) - to_chat(src, span_warning("You smell something horribly decayed inside this room.")) - add_mood_event("smell", /datum/mood_event/disgust/bad_smell) - if(15 to 30) - //Small chance to vomit. By now, people have internals on anyway - if(prob(5)) - to_chat(src, span_warning("The stench of rotting carcasses is unbearable!")) - add_mood_event("smell", /datum/mood_event/disgust/nauseating_stench) - vomit() - if(30 to INFINITY) - //Higher chance to vomit. Let the horror start - if(prob(25)) - to_chat(src, span_warning("The stench of rotting carcasses is unbearable!")) - add_mood_event("smell", /datum/mood_event/disgust/nauseating_stench) - vomit() - else - clear_mood_event("smell") - - //-- NITROUS OXIDE --// - if(n2o_pp > n2o_para_min) - // More N2O, more severe side-effects. Causes stun/sleep. - n2o_euphoria = EUPHORIA_ACTIVE - throw_alert(ALERT_TOO_MUCH_N2O, /atom/movable/screen/alert/too_much_n2o) - // give them one second of grace to wake up and run away a bit! - if(!HAS_TRAIT(src, TRAIT_SLEEPIMMUNE)) - Unconscious(6 SECONDS) - // Enough to make the mob sleep. - if(n2o_pp > n2o_sleep_min) - Sleeping(max(AmountSleeping() + 40, 200)) - else if(n2o_pp > 0.01) - // No alert for small amounts, but the mob randomly feels euphoric. - if(prob(20)) - n2o_euphoria = EUPHORIA_ACTIVE - emote(pick("giggle","laugh")) - else - n2o_euphoria = EUPHORIA_INACTIVE - else - // Reset side-effects, for zero or extremely small amounts of N2O. - n2o_euphoria = EUPHORIA_INACTIVE - clear_alert(ALERT_TOO_MUCH_N2O) - - //-- NITRIUM --// - if(nitrium_pp) - if(nitrium_pp > 0.5) - adjustFireLoss(nitrium_pp * 0.15) - if(nitrium_pp > 5) - adjustToxLoss(nitrium_pp * 0.05) - - // Handle chemical euphoria mood event, caused by N2O. - if (n2o_euphoria == EUPHORIA_ACTIVE) - add_mood_event("chemical_euphoria", /datum/mood_event/chemical_euphoria) - else if (n2o_euphoria == EUPHORIA_INACTIVE) - clear_mood_event("chemical_euphoria") - // Activate mood on first flag, remove on second, do nothing on third. - - if(has_moles) - handle_breath_temperature(breath) - - breath.garbage_collect() +/mob/living/carbon/proc/check_breath(datum/gas_mixture/breath, skip_breath = FALSE) + return /// Applies suffocation side-effects to a given Human, scaling based on ratio of required pressure VS "true" pressure. /// If pressure is greater than 0, the return value will represent the amount of gas successfully breathed. @@ -473,21 +183,45 @@ // The air you breathe out should match your body temperature breath.temperature = bodytemperature -/// Attempts to take a breath from the external or internal air tank. +/** + * Attempts to take a breath from the external or internal air tank. + * + * Return a gas mixture datum if a breath was taken + * Return null if there was no gas inside the tank or no gas was distributed + * Return SKIP_INTERNALS to skip using internals entirely and get a normal breath + */ /mob/living/carbon/proc/get_breath_from_internal(volume_needed) if(invalid_internals()) // Unexpectely lost breathing apparatus and ability to breathe from the internal air tank. cutoff_internals() - return + return SKIP_INTERNALS + if (external) . = external.remove_air_volume(volume_needed) else if (internal) . = internal.remove_air_volume(volume_needed) else // Return without taking a breath if there is no air tank. - return - // To differentiate between no internals and active, but empty internals. - return . || FALSE + stack_trace("get_breath_from_internal called on a mob without internals or externals") + return SKIP_INTERNALS + + return . + +/** + * Attempts to take a breath from the surroundings. + * + * Returns a gas mixture datum if a breath was taken. + * Returns null if there was no gas in the surroundings or no gas was distributed. + */ +/mob/living/carbon/proc/get_breath_from_surroundings(datum/gas_mixture/environment, volume_needed) + if(isobj(loc)) //Breathe from loc as object + var/obj/loc_as_obj = loc + . = loc_as_obj.handle_internal_lifeform(src, volume_needed) + + else if(isturf(loc)) //Breathe from loc as turf + . = loc.remove_air((environment?.total_moles() * BREATH_PERCENTAGE) || 0) + + return . /mob/living/carbon/proc/handle_blood(seconds_per_tick, times_fired) return @@ -498,8 +232,6 @@ /mob/living/carbon/proc/handle_organs(seconds_per_tick, times_fired) if(stat == DEAD) - if(reagents && (reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1) || reagents.has_reagent(/datum/reagent/cryostylane))) // No organ decay if the body contains formaldehyde. - return for(var/obj/item/organ/internal/organ in organs) // On-death is where organ decay is handled organ?.on_death(seconds_per_tick, times_fired) // organ can be null due to reagent metabolization causing organ shuffling diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 5453ee265380..1873a40f77c2 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -97,6 +97,25 @@ damage_dealt = -1 * adjustCloneLoss(damage_amount, forced = forced) if(STAMINA) damage_dealt = -1 * stamina.adjust(-damage) + if(PAIN) + if(pain_controller) + var/pre_pain = pain_controller.get_average_pain() + var/pain_amount = damage_amount + var/chosen_zone + if(spread_damage || isnull(def_zone)) + chosen_zone = BODY_ZONES_ALL + pain_amount /= 6 + else if(isbodypart(def_zone)) + var/obj/item/bodypart/actual_hit = def_zone + chosen_zone = actual_hit.body_zone + else + chosen_zone = check_zone(def_zone) + + sharp_pain(chosen_zone, pain_amount, STAMINA, 12.5 SECONDS, 0.8) + damage_dealt += pre_pain - pain_controller.get_average_pain() + damage_dealt += stamina?.adjust(-damage_amount * 0.25, forced = forced) + else + damage_dealt = -1 * stamina.adjust(-damage_amount, forced = forced) if(BRAIN) damage_dealt = -1 * adjustOrganLoss(ORGAN_SLOT_BRAIN, damage_amount) diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm index be431ccf31f8..9acd31e030f0 100644 --- a/code/modules/mob/living/init_signals.dm +++ b/code/modules/mob/living/init_signals.dm @@ -1,7 +1,6 @@ /// Called on [/mob/living/Initialize(mapload)], for the mob to register to relevant signals. /mob/living/proc/register_init_signals() - RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_KNOCKEDOUT), PROC_REF(on_knockedout_trait_gain)) - RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_KNOCKEDOUT), PROC_REF(on_knockedout_trait_loss)) + RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_KNOCKEDOUT), SIGNAL_REMOVETRAIT(TRAIT_KNOCKEDOUT)), PROC_REF(on_knockedout_trait)) RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_DEATHCOMA), PROC_REF(on_deathcoma_trait_gain)) RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_DEATHCOMA), PROC_REF(on_deathcoma_trait_loss)) @@ -63,17 +62,20 @@ ) AddElement(/datum/element/connect_loc, loc_connections) -/// Called when [TRAIT_KNOCKEDOUT] is added to the mob. -/mob/living/proc/on_knockedout_trait_gain(datum/source) +/// Called when [TRAIT_KNOCKEDOUT] is added or removed from the mob. +/mob/living/proc/on_knockedout_trait(datum/source) SIGNAL_HANDLER - if(stat < UNCONSCIOUS) - set_stat(UNCONSCIOUS) + if(HAS_TRAIT(src, TRAIT_KNOCKEDOUT)) + become_blind(UNCONSCIOUS_TRAIT) + set_pain_mod(PAIN_MOD_KOD, 0.8) + add_traits(list(TRAIT_HANDS_BLOCKED, TRAIT_IMMOBILIZED, TRAIT_INCAPACITATED, TRAIT_FLOORED), TRAIT_KNOCKEDOUT) + update_body() // Update eyelids -/// Called when [TRAIT_KNOCKEDOUT] is removed from the mob. -/mob/living/proc/on_knockedout_trait_loss(datum/source) - SIGNAL_HANDLER - if(stat <= UNCONSCIOUS) - update_stat() + else + cure_blind(UNCONSCIOUS_TRAIT) + unset_pain_mod(PAIN_MOD_KOD) + remove_traits(list(TRAIT_HANDS_BLOCKED, TRAIT_IMMOBILIZED, TRAIT_INCAPACITATED, TRAIT_FLOORED), TRAIT_KNOCKEDOUT) + update_body() // Update eyelids /// Called when [TRAIT_DEATHCOMA] is added to the mob. /mob/living/proc/on_deathcoma_trait_gain(datum/source) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index a6481e93ae01..f1794a6c97d6 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -100,21 +100,50 @@ // we need a second, silent armor check to actually know how much to reduce damage taken, as opposed to // on [/atom/proc/bullet_act] where it's just to pass it to the projectile's on_hit(). - var/armor_check = check_projectile_armor(def_zone, hitting_projectile, is_silent = TRUE) + var/armor_check = min(ARMOR_MAX_BLOCK, check_projectile_armor(def_zone, hitting_projectile, is_silent = TRUE)) - apply_damage( + var/damage_done = apply_damage( damage = hitting_projectile.damage, damagetype = hitting_projectile.damage_type, def_zone = def_zone, - blocked = min(ARMOR_MAX_BLOCK, armor_check), //cap damage reduction at 90% + blocked = armor_check, wound_bonus = hitting_projectile.wound_bonus, bare_wound_bonus = hitting_projectile.bare_wound_bonus, sharpness = hitting_projectile.sharpness, - attack_direction = get_dir(hitting_projectile.starting, src), + attack_direction = hitting_projectile.dir, ) + if(hitting_projectile.stamina) + apply_damage( + damage = hitting_projectile.stamina, + damagetype = STAMINA, + def_zone = def_zone, + blocked = armor_check, + attack_direction = hitting_projectile.dir, + ) + if(hitting_projectile.pain) + apply_damage( + damage = hitting_projectile.pain, + damagetype = PAIN, + def_zone = def_zone, + // blocked = armor_check, // Batons don't factor in armor, soooo we shouldn't? + attack_direction = hitting_projectile.dir, + ) + + var/extra_paralyze = 0 SECONDS + var/extra_knockdown = 0 SECONDS + if(hitting_projectile.damage_type == BRUTE && !hitting_projectile.grazing) + // melbert todo scale on pain of bodypart? + if(damage_done >= 60) + if(!IsParalyzed() && prob(damage_done)) + extra_paralyze += 0.8 SECONDS + extra_knockdown += 1.2 SECONDS + else if(damage_done >= 20) + if(!IsKnockdown() && prob(damage_done * 2)) + extra_knockdown += 0.8 SECONDS + apply_effects( stun = hitting_projectile.stun, - knockdown = hitting_projectile.knockdown, + knockdown = hitting_projectile.knockdown + extra_knockdown, unconscious = hitting_projectile.unconscious, slur = (mob_biotypes & MOB_ROBOTIC) ? 0 SECONDS : hitting_projectile.slur, // Don't want your cyborgs to slur from being ebow'd stutter = (mob_biotypes & MOB_ROBOTIC) ? 0 SECONDS : hitting_projectile.stutter, // Don't want your cyborgs to stutter from being tazed @@ -123,7 +152,7 @@ blocked = armor_check, stamina = hitting_projectile.stamina, jitter = (mob_biotypes & MOB_ROBOTIC) ? 0 SECONDS : hitting_projectile.jitter, // Cyborgs can jitter but not from being shot - paralyze = hitting_projectile.paralyze, + paralyze = hitting_projectile.paralyze + extra_paralyze, immobilize = hitting_projectile.immobilize, ) if(hitting_projectile.dismemberment) @@ -131,7 +160,16 @@ return BULLET_ACT_HIT /mob/living/check_projectile_armor(def_zone, obj/projectile/impacting_projectile, is_silent) - return run_armor_check(def_zone, impacting_projectile.armor_flag, "","",impacting_projectile.armour_penetration, "", is_silent, impacting_projectile.weak_against_armour) + . = run_armor_check( + def_zone = def_zone, + attack_flag = impacting_projectile.armor_flag, + armour_penetration = impacting_projectile.armour_penetration, + silent = is_silent, + weak_against_armour = impacting_projectile.weak_against_armour, + ) + if(impacting_projectile.grazing) + . += 50 + return . /mob/living/proc/check_projectile_dismemberment(obj/projectile/P, def_zone) return 0 diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index fc9ffb53cc45..63ea856f6117 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -21,6 +21,9 @@ ///Stamina damage, or exhaustion. You recover it slowly naturally, and are knocked down if it gets too high. Holodeck and hallucinations deal this. var/staminaloss = 0 + /// Modified applied to attacks with items or fists + var/outgoing_damage_mod = 1 + //Damage related vars, NOTE: THESE SHOULD ONLY BE MODIFIED BY PROCS ///Brutal damage caused by brute force (punching, being clubbed by a toolbox ect... this also accounts for pressure damage) var/bruteloss = 0 diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm index b7d6719cc0c3..35229887c86b 100644 --- a/code/modules/pai/pai.dm +++ b/code/modules/pai/pai.dm @@ -267,11 +267,6 @@ . = ..() update_stat() -/mob/living/silicon/pai/on_knockedout_trait_loss(datum/source) - . = ..() - set_stat(CONSCIOUS) - update_stat() - /** * Resolves the weakref of the pai's master. * If the master has been deleted, calls reset_software(). diff --git a/code/modules/projectiles/ammunition/_firing.dm b/code/modules/projectiles/ammunition/_firing.dm index c911da396b36..fc59c5911c35 100644 --- a/code/modules/projectiles/ammunition/_firing.dm +++ b/code/modules/projectiles/ammunition/_firing.dm @@ -1,3 +1,16 @@ + +/** + * Fires the bullet in this casing + * + * * target - what was clicked on (where the bullet will go) + * * user - who is firing the bullet + * * params - click params. like x, y, shift, etc + * * distro - how much the bullet will spread + * * quiet - if the bullet is suppressed + * * zone_override - optional, the zone the bullet will aim for. if not supplied, uses the user's selected zone + * * spread - how much the bullet will spread + * * fired_from - the object that fired the bullet + */ /obj/item/ammo_casing/proc/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread, atom/fired_from) distro += variance var/targloc = get_turf(target) @@ -44,10 +57,7 @@ loaded_projectile.firer = user loaded_projectile.fired_from = fired_from loaded_projectile.hit_prone_targets = (user.istate & ISTATE_HARM) - if (zone_override) - loaded_projectile.def_zone = zone_override - else - loaded_projectile.def_zone = user.zone_selected + loaded_projectile.def_zone = zone_override || user.zone_selected loaded_projectile.suppressed = quiet if(isgun(fired_from)) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 5a919f5d1656..3284edf8057e 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -16,12 +16,15 @@ blocks_emissive = EMISSIVE_BLOCK_GENERIC layer = MOB_LAYER plane = GAME_PLANE_FOV_HIDDEN + var/generic_name //The sound this plays on impact. var/hitsound = 'sound/weapons/pierce.ogg' var/hitsound_wall = "" resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF var/def_zone = "" //Aiming at + /// Set to TRUE if we're grazing, which affects the message / embed chance / damage / effects + var/grazing = FALSE var/atom/movable/firer = null//Who shot it var/datum/fired_from = null // the thing that the projectile was fired from (gun, turret, spell) var/suppressed = FALSE //Attack message @@ -171,6 +174,8 @@ var/drowsy = 0 SECONDS /// Jittering applied on projectile hit var/jitter = 0 SECONDS + /// Bonus pain, like stamina damage + var/pain = 0 /// Extra stamina damage applied on projectile hit (in addition to the main damage) var/stamina = 0 /// Stuttering applied on projectile hit @@ -230,17 +235,6 @@ SEND_SIGNAL(src, COMSIG_PROJECTILE_RANGE_OUT) qdel(src) -/// Returns the string form of the def_zone we have hit. -/mob/living/proc/check_hit_limb_zone_name(hit_zone) - if(has_limbs) - return hit_zone - -/mob/living/carbon/check_hit_limb_zone_name(hit_zone) - if(get_bodypart(hit_zone)) - return hit_zone - else //when a limb is missing the damage is actually passed to the chest - return BODY_ZONE_CHEST - /** * Called when the projectile hits something * @@ -270,13 +264,9 @@ else living.apply_status_effect(/datum/status_effect/stacking/debilitated, 1) - var/hit_limb_zone - if(isliving(target)) - var/mob/living/L = target - hit_limb_zone = L.check_hit_limb_zone_name(def_zone) if(fired_from) - SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_ON_HIT, firer, target, Angle, hit_limb_zone) - SEND_SIGNAL(src, COMSIG_PROJECTILE_SELF_ON_HIT, firer, target, Angle, hit_limb_zone) + SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_ON_HIT, firer, target, Angle, def_zone, blocked) + SEND_SIGNAL(src, COMSIG_PROJECTILE_SELF_ON_HIT, firer, target, Angle, def_zone, blocked) if(QDELETED(src)) // in case one of the above signals deleted the projectile for whatever reason return BULLET_ACT_BLOCK @@ -313,7 +303,7 @@ var/mob/living/living_target = target if(blocked != 100) // not completely blocked - var/obj/item/bodypart/hit_bodypart = living_target.get_bodypart(hit_limb_zone) + var/obj/item/bodypart/hit_bodypart = living_target.get_bodypart(def_zone) if (damage) if (living_target.blood_volume && damage_type == BRUTE && (isnull(hit_bodypart) || hit_bodypart.can_bleed())) var/splatter_dir = dir @@ -335,19 +325,22 @@ new impact_effect_type(target_turf, hitx, hity) var/organ_hit_text = "" - if(hit_limb_zone) - organ_hit_text = " in \the [parse_zone(hit_limb_zone)]" + if(def_zone) + organ_hit_text = " in \the [parse_zone(def_zone)]" if(suppressed == SUPPRESSED_VERY) playsound(loc, hitsound, 5, TRUE, -1) else if(suppressed) playsound(loc, hitsound, 5, TRUE, -1) - to_chat(living_target, span_userdanger("You're shot by \a [src][organ_hit_text]!")) + to_chat(living_target, span_userdanger("You're [grazing ? "grazed" : "hit"] by \a [generic_name || src][organ_hit_text]!")) else if(hitsound) - var/volume = vol_by_damage() - playsound(src, hitsound, volume, TRUE, -1) - living_target.visible_message(span_danger("[living_target] is hit by \a [src][organ_hit_text]!"), \ - span_userdanger("You're hit by \a [src][organ_hit_text]!"), null, COMBAT_MESSAGE_RANGE) + playsound(src, hitsound, vol_by_damage(), TRUE, -1) + living_target.visible_message( + span_danger("[living_target] is [grazing ? "grazed" : "hit"] by \a [generic_name || src][organ_hit_text]!"), + span_userdanger("You're [grazing ? "grazed" : "hit"] by \a [generic_name || src][organ_hit_text]!"), + span_hear("You hear a woosh."), + // vision_distance = COMBAT_MESSAGE_RANGE, + ) if(living_target.is_blind()) to_chat(living_target, span_userdanger("You feel something hit you[organ_hit_text]!")) @@ -478,8 +471,19 @@ store_hitscan_collision(point_cache) return TRUE - var/distance = get_dist(T, starting) // Get the distance between the turf shot from and the mob we hit and use that for the calculations. - def_zone = ran_zone(def_zone, max(100-(7*distance), 5)) //Lower accurancy/longer range tradeoff. 7 is a balanced number to use. + if(!HAS_TRAIT(src, TRAIT_ALWAYS_HIT_ZONE) && isliving(A)) + var/mob/living/who_is_shot = A + var/distance = decayedRange - range + var/hit_prob = max(100 - (7 * distance), 5) + if(who_is_shot.body_position == LYING_DOWN) + hit_prob *= 1.2 + // melbert todo : make people more skilled with weapons have a lower miss chance + if(!prob(hit_prob)) + def_zone = who_is_shot.get_random_valid_zone(def_zone, 0) // Lower accurancy/longer range tradeoff. 7 is a balanced number to use. + grazing = !prob(hit_prob) // jeez you missed twice? that's a graze + if(grazing) + wound_bonus = CANT_WOUND + bare_wound_bonus = CANT_WOUND return process_hit(T, select_target(T, A, A), A) // SELECT TARGET FIRST! diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 8d5d22da3cdc..207061c86396 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -21,6 +21,7 @@ /obj/projectile/beam/laser + generic_name = "laser beam" tracer_type = /obj/effect/projectile/tracer/laser muzzle_type = /obj/effect/projectile/muzzle/laser impact_type = /obj/effect/projectile/impact/laser @@ -77,6 +78,7 @@ /obj/projectile/beam/practice name = "practice laser" + generic_name = "practice laser beam" damage = 0 /obj/projectile/beam/scatter @@ -126,6 +128,7 @@ /obj/projectile/beam/pulse name = "pulse" + generic_name = "pulse beam" icon_state = "u_laser" damage = 50 impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser diff --git a/code/modules/projectiles/projectile/bullets/lmg.dm b/code/modules/projectiles/projectile/bullets/lmg.dm index f6081c7b070c..c6099105affb 100644 --- a/code/modules/projectiles/projectile/bullets/lmg.dm +++ b/code/modules/projectiles/projectile/bullets/lmg.dm @@ -1,27 +1,33 @@ // C3D (Borgs) /obj/projectile/bullet/c3d + generic_name = "bullet" damage = 20 // Mech LMG /obj/projectile/bullet/lmg + generic_name = "bullet" damage = 20 // Mech FNX-99 /obj/projectile/bullet/incendiary/fnx99 + generic_name = "bullet" damage = 20 // Turrets /obj/projectile/bullet/manned_turret + generic_name = "bullet" damage = 20 /obj/projectile/bullet/manned_turret/hmg + generic_name = "bullet" icon_state = "redtrac" /obj/projectile/bullet/syndicate_turret + generic_name = "bullet" damage = 20 // 7.12x82mm (SAW) diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index d7d309fe5e9d..1638e65e9696 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -212,7 +212,7 @@ /datum/reagent/toxin/lexorin/proc/block_breath(mob/living/source) SIGNAL_HANDLER - return COMSIG_CARBON_BLOCK_BREATH + return BREATHE_BLOCK_BREATH /datum/reagent/toxin/slimejelly name = "Slime Jelly" @@ -1306,7 +1306,7 @@ /datum/reagent/toxin/tetrodotoxin/proc/block_breath(mob/living/source) SIGNAL_HANDLER if(current_cycle >= 28) - return COMSIG_CARBON_BLOCK_BREATH + return BREATHE_BLOCK_BREATH /datum/reagent/toxin/radiomagnetic_disruptor // MONKESTATION ADDITION: NANITE REMOVAL CHEM name = "Radiomagnetic Disruptor" diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 9cd09928665a..b02dadcdb8d6 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -336,18 +336,12 @@ else is_disabled += " and" - check_list += "\t Your [name][is_disabled][self_aware ? " has " : " is "][status]." + check_list += "\tYour [name][is_disabled][self_aware ? " has " : " is "][status]." for(var/datum/wound/wound as anything in wounds) - switch(wound.severity) - if(WOUND_SEVERITY_TRIVIAL) - check_list += "\t [span_danger("Your [name] is suffering [wound.a_or_from] [lowertext(wound.name)].")]" - if(WOUND_SEVERITY_MODERATE) - check_list += "\t [span_warning("Your [name] is suffering [wound.a_or_from] [lowertext(wound.name)]!")]" - if(WOUND_SEVERITY_SEVERE) - check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [lowertext(wound.name)]!!")]" - if(WOUND_SEVERITY_CRITICAL) - check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [lowertext(wound.name)]!!!")]" + var/wound_desc = wound.get_self_check_description(src, examiner) + if(wound_desc) + check_list += "\t\t[wound_desc]" for(var/obj/item/embedded_thing in embedded_objects) var/stuck_word = embedded_thing.isEmbedHarmless() ? "stuck" : "embedded" @@ -1339,3 +1333,13 @@ return "metal" return "error" + +/// Returns what message is displayed when the bodypart is on the cusp of being dismembered. +/obj/item/bodypart/proc/get_soon_dismember_message() + return ", threatening to sever it entirely" + +/obj/item/bodypart/chest/get_soon_dismember_message() + return ", threatening to split it open" // we don't sever, we dump organs when "dismembered" + +/obj/item/bodypart/head/get_soon_dismember_message() + return ", threatening to split it open" // we don't sever, we cranial fissure when "dismembered" // we also don't dismember i think diff --git a/code/modules/surgery/healing.dm b/code/modules/surgery/healing.dm index 8ff8a5d78991..d0d21b82f4c1 100644 --- a/code/modules/surgery/healing.dm +++ b/code/modules/surgery/healing.dm @@ -159,7 +159,7 @@ var/estimated_remaining_steps = target.getBruteLoss() / brute_healed var/progress_text - if(locate(/obj/item/healthanalyzer) in user.held_items) + if(get_perfect_information(user, target)) progress_text = ". Remaining brute: [target.getBruteLoss()]" else switch(estimated_remaining_steps) @@ -224,7 +224,7 @@ var/estimated_remaining_steps = target.getFireLoss() / burn_healed var/progress_text - if(locate(/obj/item/healthanalyzer) in user.held_items) + if(get_perfect_information(user, target)) progress_text = ". Remaining burn: [target.getFireLoss()]" else switch(estimated_remaining_steps) @@ -292,7 +292,7 @@ var/progress_text - if(locate(/obj/item/healthanalyzer) in user.held_items) + if(get_perfect_information(user, target)) if(target.getBruteLoss()) progress_text = ". Remaining brute: [target.getBruteLoss()]" if(target.getFireLoss()) diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm index b9c959bb7dfa..51015e0692d8 100644 --- a/code/modules/surgery/organs/_organ.dm +++ b/code/modules/surgery/organs/_organ.dm @@ -415,18 +415,34 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) replacement.set_organ_damage(damage) /// Called by medical scanners to get a simple summary of how healthy the organ is. Returns an empty string if things are fine. -/obj/item/organ/proc/get_status_text() - var/status = "" +/obj/item/organ/proc/get_status_text(advanced, add_tooltips) + if(organ_flags & ORGAN_FAILING) + . = "Non-Functional" + if(add_tooltips) + . = span_tooltip("Repair or replace surgically.", .) + return . + if(owner.has_reagent(/datum/reagent/inverse/technetium)) - status = " organ is [round((damage/maxHealth)*100, 1)]% damaged." - else if(organ_flags & ORGAN_FAILING) - status = "Non-Functional" - else if(damage > high_threshold) - status = "Severely Damaged" - else if (damage > low_threshold) - status = "Mildly Damaged" - - return status + return "[round((damage/maxHealth)*100, 1)]% damaged" + if(damage > high_threshold) + . = "Severely Damaged" + if(add_tooltips && owner.stat != DEAD) + . = span_tooltip("[healing_factor ? "Treat with rest or use specialty medication." : "Repair surgically or use specialty medication."]", .) + return . + if(damage > low_threshold) + . = "Mildly Damaged" + if(add_tooltips && owner.stat != DEAD) + . = span_tooltip("[healing_factor ? "Treat with rest." : "Use specialty medication."]", .) + return . + +/// Determines if this organ is shown when a user has condensed scans enabled +/obj/item/organ/proc/show_on_condensed_scans() + // We don't need to show *most* damaged organs as they have no effects associated + return (organ_flags & (ORGAN_FAILING|ORGAN_VITAL)) + +/// Similar to get_status_text, but appends the text after the damage report, for additional status info +/obj/item/organ/proc/get_status_appendix(advanced, add_tooltips) + return /// Tries to replace the existing organ on the passed mob with this one, with special handling for replacing a brain without ghosting target /obj/item/organ/proc/replace_into(mob/living/carbon/new_owner) diff --git a/code/modules/surgery/organs/appendix.dm b/code/modules/surgery/organs/appendix.dm index 3562f29890c3..3452e9a5954f 100644 --- a/code/modules/surgery/organs/appendix.dm +++ b/code/modules/surgery/organs/appendix.dm @@ -89,11 +89,13 @@ ADD_TRAIT(organ_owner, TRAIT_DISEASELIKE_SEVERITY_MEDIUM, type) organ_owner.med_hud_set_status() -/obj/item/organ/internal/appendix/get_status_text() - if((!(organ_flags & ORGAN_FAILING)) && inflamation_stage) - return "Inflamed" - else - return ..() +/obj/item/organ/internal/appendix/get_status_text(advanced, add_tooltips) + if(!(organ_flags & ORGAN_FAILING) && inflamation_stage) + . = "Inflamed" + if(add_tooltips) + . = span_tooltip("Remove surgically.", .) + return . + return ..() #undef APPENDICITIS_PROB #undef INFLAMATION_ADVANCEMENT_PROB diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm index f191fb54d689..e0006710dcc3 100644 --- a/code/modules/surgery/organs/ears.dm +++ b/code/modules/surgery/organs/ears.dm @@ -28,6 +28,21 @@ // Multiplier for both long term and short term ear damage var/damage_multiplier = 1 +/obj/item/organ/internal/ears/get_status_appendix(advanced, add_tooltips) + if(owner.stat == DEAD) + return + if(advanced) + if(HAS_TRAIT_FROM(owner, TRAIT_DEAF, GENETIC_MUTATION)) + return "Subject is genetically deaf." + if(HAS_TRAIT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE)) + return "Subject is [(organ_flags & ORGAN_FAILING) ? "permanently": "temporarily"] deaf from ear damage." + if(HAS_TRAIT(owner, TRAIT_DEAF)) + return "Subject is deaf." + +/obj/item/organ/internal/ears/show_on_condensed_scans() + // Always show if we have an appendix + return ..() || (owner.stat != DEAD && HAS_TRAIT(owner, TRAIT_DEAF)) + /obj/item/organ/internal/ears/on_life(seconds_per_tick, times_fired) // only inform when things got worse, needs to happen before we heal if((damage > low_threshold && prev_damage < low_threshold) || (damage > high_threshold && prev_damage < high_threshold)) diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index c8006bd92dc0..016e76320210 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -114,6 +114,33 @@ #define OFFSET_X 1 #define OFFSET_Y 2 +/// Similar to get_status_text, but appends the text after the damage report, for additional status info +/obj/item/organ/internal/eyes/get_status_appendix(advanced, add_tooltips) + if(owner.stat == DEAD || HAS_TRAIT(owner, TRAIT_KNOCKEDOUT)) + return + if(owner.is_blind()) + if(advanced) + if(owner.is_blind_from(EYE_DAMAGE)) + return "Subject is blind from eye damage." + if(owner.is_blind_from(GENETIC_MUTATION)) + return "Subject is genetically blind." + if(owner.is_blind_from(QUIRK_TRAIT)) + return "Subject is permanently blind." + return "Subject is blind." + if(owner.is_nearsighted()) + if(advanced) + if(owner.is_nearsighted_from(EYE_DAMAGE)) + return "Subject is nearsighted from eye damage." + if(owner.is_nearsighted_from(GENETIC_MUTATION)) + return "Subject is genetically nearsighted." + if(owner.is_nearsighted_from(QUIRK_TRAIT)) + return "Subject is permanently nearsighted." + return "Subject is nearsighted." + +/obj/item/organ/internal/eyes/show_on_condensed_scans() + // Always show if we have an appendix + return ..() || (owner.stat != DEAD && !HAS_TRAIT(owner, TRAIT_KNOCKEDOUT) && (owner.is_blind() || owner.is_nearsighted())) + /// This proc generates a list of overlays that the eye should be displayed using for the given parent /obj/item/organ/internal/eyes/proc/generate_body_overlay(mob/living/carbon/human/parent) if(!istype(parent) || parent.get_organ_by_type(/obj/item/organ/internal/eyes) != src) diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index 6c317316fc97..29f266b1e556 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -59,6 +59,29 @@ beating = FALSE update_appearance() +/obj/item/organ/internal/heart/proc/get_heart_rate() + if(!beating) + return 0 + + var/base_amount = 0 + + if(owner.has_status_effect(/datum/status_effect/jitter)) + base_amount = 100 + rand(0, 25) + else if(owner.stat == SOFT_CRIT || owner.stat == HARD_CRIT) + base_amount = 60 + rand(-15, -10) + else + base_amount = 80 + rand(-10, 10) + base_amount += round(owner.getOxyLoss() / 5) + base_amount += ((BLOOD_VOLUME_NORMAL - owner.blood_volume) / 25) + base_amount += owner.pain_controller?.get_heartrate_modifier() + if(owner.has_status_effect(/datum/status_effect/determined)) // adrenaline + base_amount += 10 + + if(owner.has_reagent(/datum/reagent/consumable/coffee)) // funny + base_amount += 10 + + return round(base_amount * clamp(1.5 * ((maxHealth - damage) / maxHealth), 0.5, 1)) // heart damage puts a multiplier on it + /obj/item/organ/internal/heart/on_life(seconds_per_tick, times_fired) ..() @@ -75,6 +98,7 @@ beat = BEAT_SLOW owner.playsound_local(get_turf(owner), slowbeat, 40, 0, channel = CHANNEL_HEARTBEAT, use_reverb = FALSE) to_chat(owner, span_notice("You feel your heart slow down...")) + if(beat == BEAT_SLOW && owner.health > owner.crit_threshold) owner.stop_sound_channel(CHANNEL_HEARTBEAT) beat = BEAT_NONE @@ -88,12 +112,14 @@ owner.stop_sound_channel(CHANNEL_HEARTBEAT) beat = BEAT_NONE - if((organ_flags & ORGAN_FAILING) && owner.can_heartattack() && !(HAS_TRAIT(src, TRAIT_STABLEHEART))) //heart broke, stopped beating, death imminent... unless you have veins that pump blood without a heart - if(owner.stat == CONSCIOUS && beating) // monkestation edit: antispam - owner.visible_message(span_danger("[owner] clutches at [owner.p_their()] chest as if [owner.p_their()] heart is stopping!"), \ - span_userdanger("You feel a terrible pain in your chest, as if your heart has stopped!")) - owner.set_heartattack(TRUE) - failed = TRUE + if((organ_flags & ORGAN_FAILING) || !beating) //heart broke, stopped beating, death imminent... unless you have veins that pump blood without a heart + if(owner.can_heartattack() && !(HAS_TRAIT(src, TRAIT_STABLEHEART))) + if(owner.stat == CONSCIOUS && beating) // monkestation edit: antispam + owner.visible_message(span_danger("[owner] clutches at [owner.p_their()] chest as if [owner.p_their()] heart is stopping!"), \ + span_userdanger("You feel a terrible pain in your chest, as if your heart has stopped!")) + owner.set_heartattack(TRUE) + failed = TRUE + owner.adjust_pain_shock(1 * seconds_per_tick) /obj/item/organ/internal/heart/get_availability(datum/species/owner_species, mob/living/owner_mob) return owner_species.mutantheart diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index 31f69eeacacf..18b052f91ef5 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -164,6 +164,8 @@ receiver.clear_alert(ALERT_NOT_ENOUGH_NITRO) receiver.clear_alert(ALERT_NOT_ENOUGH_PLASMA) receiver.clear_alert(ALERT_NOT_ENOUGH_N2O) + receiver.remove_status_effect(/datum/status_effect/lungless) + RegisterSignal(receiver, COMSIG_CARBON_ATTEMPT_BREATHE, PROC_REF(block_breath)) /obj/item/organ/internal/lungs/Remove(mob/living/carbon/organ_owner, special) . = ..() @@ -177,6 +179,13 @@ call(src, on_loss)(organ_owner, dummy, last_partial_pressures[gas_id]) dummy.garbage_collect() + UnregisterSignal(organ_owner, COMSIG_CARBON_ATTEMPT_BREATHE) + if(!special) + organ_owner.apply_status_effect(/datum/status_effect/lungless) + +/obj/item/organ/internal/lungs/proc/block_breath(...) + SIGNAL_HANDLER + return (failed && !HAS_TRAIT(owner, TRAIT_ASSISTED_BREATHING)) ? BREATHE_SKIP_BREATH : NONE /** * Tells the lungs to pay attention to the passed in gas type @@ -531,14 +540,23 @@ if(!HAS_TRAIT(breather, TRAIT_SLEEPIMMUNE)) breather.Unconscious(6 SECONDS) // Enough to make the mob sleep. - if(n2o_pp > n2o_sleep_min) - breather.Sleeping(min(breather.AmountSleeping() + 100, 200)) + if(n2o_pp > n2o_sleep_min) + breather.Sleeping(min(breather.AmountSleeping() + 100, 200)) + // And apply anesthesia if it worked + if(HAS_TRAIT(breather, TRAIT_KNOCKEDOUT)) + breather.apply_status_effect(/datum/status_effect/grouped/anesthetic, /datum/gas/nitrous_oxide) /// N2O side-effects. "Too much N2O!" /obj/item/organ/internal/lungs/proc/safe_n2o(mob/living/carbon/breather, datum/gas_mixture/breath, old_n2o_pp) n2o_euphoria = EUPHORIA_INACTIVE breather.clear_alert(ALERT_TOO_MUCH_N2O) +/obj/item/organ/internal/lungs/check_damage_thresholds(mob/organ_owner) + // Don't give random feedback messages if you're suffocating + if(owner?.failed_last_breath) + return null + return ..() + // Breath in nitrium. It's helpful, but has nasty side effects /obj/item/organ/internal/lungs/proc/too_much_nitrium(mob/living/carbon/breather, datum/gas_mixture/breath, nitrium_pp, old_nitrium_pp) breathe_gas_volume(breath, /datum/gas/nitrium) @@ -590,25 +608,26 @@ * * breath: A gas mixture to test, or null. * * breather: A carbon mob that is using the lungs to breathe. */ -/obj/item/organ/internal/lungs/proc/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/breather) +/obj/item/organ/internal/lungs/proc/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/breather, skip_breath) if(breather.status_flags & GODMODE) breather.failed_last_breath = FALSE - breather.clear_alert(ALERT_NOT_ENOUGH_OXYGEN) return FALSE if(HAS_TRAIT(breather, TRAIT_NOBREATH)) return FALSE - // If the breath is falsy or "null", we can use the backup empty_breath. - if(!breath) + // If the breath is null, it's actually a failed breath + var/no_breath = isnull(breath) || skip_breath + if(no_breath) var/static/datum/gas_mixture/immutable/empty_breath = new(BREATH_VOLUME) breath = empty_breath // Indicates if there are moles of gas in the breath. - var/has_moles = breath.total_moles() != 0 - + var/num_moles = breath.total_moles() + var/not_low_pressure = num_moles > 0.01 || HAS_TRAIT(breather, TRAIT_RESISTLOWPRESSURE) + var/not_high_pressure = num_moles < 0.1 || HAS_TRAIT(breather, TRAIT_RESISTHIGHPRESSURE) // Check for moles of gas and handle partial pressures / special conditions. - if(has_moles) + if(num_moles > 0 && not_low_pressure && not_high_pressure) // Breath has more than 0 moles of gas. // Route gases through mask filter if breather is wearing one. if(istype(breather.wear_mask) && (breather.wear_mask.clothing_flags & GAS_FILTERING) && breather.wear_mask.has_filter) @@ -618,8 +637,28 @@ // The lungs can breathe anyways. What are you? Some bottom-feeding, scum-sucking algae eater? breather.failed_last_breath = FALSE // Vacuum-adapted lungs regenerate oxyloss even when breathing nothing. - if(breather.health >= breather.crit_threshold && breather.oxyloss) - breather.adjustOxyLoss(-5) + if(HAS_TRAIT(breather, TRAIT_NOBLOOD)) + breather.adjustOxyLoss(-4) + else + // Less blood so breaths give you less oxygen + breather.adjustOxyLoss(-1 * min(5, BLOOD_VOLUME_NORMAL / breather.blood_volume)) + + // We're in a low / high pressure environment, can't breathe, but trying to, so this hurts the lungs + // Unless it's cybernetic then it just doesn't care. Handwave magic whatever + else if(!skip_breath) + if(!failed) + // Lungs are poppin + if(damage >= 40 && damage <= 50 && breather.can_feel_pain()) + to_chat(breather, span_userdanger("You feel a stabbing pain in your chest!")) + else if(num_moles < 0.02) + to_chat(breather, span_boldwarning("You feel air rapidly exiting your lungs!")) + else if(num_moles > 0.1) + to_chat(breather, span_boldwarning("You feel air force itself into your lungs!")) + + breather.cause_pain(BODY_ZONE_CHEST, 10, BRUTE) + apply_organ_damage(15) + breather.failed_last_breath = TRUE + // Robot, don't care lol else // Can't breathe! breather.failed_last_breath = TRUE @@ -694,7 +733,7 @@ else if (old_euphoria && !new_euphoria) breather.clear_mood_event("chemical_euphoria") - if(has_moles) + if(num_moles > 0) handle_breath_temperature(breath, breather) // Merge breath_out into breath. They're kept seprerate before now to ensure stupid like, order of operations shit doesn't happen // But that time has passed @@ -731,14 +770,13 @@ // Give them a chance to notice something is wrong. if(prob(20)) suffocator.emote("gasp") + var/oxyloss = suffocator.getOxyLoss() + if(oxyloss >= 50) + // Suffocating = brain damage + suffocator.adjustOrganLoss(ORGAN_SLOT_BRAIN, (oxyloss / MAX_OXYLOSS(suffocator.maxHealth)) * 4, required_organtype = ORGAN_ORGANIC) // If mob is at critical health, check if they can be damaged further. - if(suffocator.health < suffocator.crit_threshold) - // Mob is immune to damage at critical health. - if(HAS_TRAIT(suffocator, TRAIT_NOCRITDAMAGE)) - return - // Reagents like Epinephrine stop suffocation at critical health. - if(suffocator.reagents.has_reagent(crit_stabilizing_reagent, needs_metabolizing = TRUE)) - return + if(suffocator.stat >= SOFT_CRIT && HAS_TRAIT(suffocator, TRAIT_NOCRITDAMAGE)) + return // Low pressure. if(breath_pp) var/ratio = safe_breath_min / breath_pp @@ -835,19 +873,48 @@ QDEL_IN(holder, breath_particle.lifespan) -/obj/item/organ/internal/lungs/on_life(seconds_per_tick, times_fired) +/obj/item/organ/internal/lungs/apply_organ_damage(damage_amount, maximum = maxHealth, required_organtype) . = ..() - if(failed && !(organ_flags & ORGAN_FAILING)) - failed = FALSE + if(!.) return - if(damage >= low_threshold) - var/do_i_cough = SPT_PROB((damage < high_threshold) ? 2.5 : 5, seconds_per_tick) // between : past high - if(do_i_cough) - owner.emote("cough") - if((organ_flags & ORGAN_FAILING) && owner.stat == CONSCIOUS && SPT_PROB(1, seconds_per_tick)) // monkestation edit: antispam - owner.visible_message(span_danger("[owner] grabs [owner.p_their()] throat, struggling for breath!"), span_userdanger("You suddenly feel like you can't breathe!")) + + if(organ_flags & ORGAN_FAILING) + if(!owner?.incapacitated()) + owner.visible_message( + span_danger("[owner] grabs [owner.p_their()] throat, struggling for breath!"), + span_userdanger("You suddenly feel like you can't breathe!"), + ) failed = TRUE + else if(failed) + failed = FALSE + +/obj/item/organ/internal/lungs/on_life(seconds_per_tick, times_fired) + . = ..() + if(damage < low_threshold) + return + + var/cough_prob = 2.5 + if(damage >= high_threshold) + cough_prob = 5 + + if(!SPT_PROB(cough_prob, seconds_per_tick)) // between : past high + return + + if(damage >= high_threshold && prob(33)) + owner.visible_message(span_danger("[owner] coughs up blood!"), span_userdanger("You cough up blood!")) + var/obj/item/covering = owner.is_mouth_covered() + if(covering) + covering.add_mob_blood(owner) + else if(isturf(owner.loc)) + owner.add_splatter_floor() + owner.apply_damage(3, BRUTE, BODY_ZONE_CHEST, wound_bonus = CANT_WOUND) + owner.bleed(round(damage / 8)) + playsound(owner, 'sound/effects/splat.ogg', 33, TRUE) + else + owner.emote(pick("weeze", "cough")) + owner.losebreath = min(owner.losebreath + round(damage / 100, 0.1), 4) + /obj/item/organ/internal/lungs/get_availability(datum/species/owner_species, mob/living/owner_mob) return owner_species.mutantlungs @@ -867,9 +934,9 @@ safe_plasma_max = 0 //We breathe this to gain POWER. -/obj/item/organ/internal/lungs/slime/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/breather_slime) +/obj/item/organ/internal/lungs/slime/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/breather_slime, skip_breath) . = ..() - if (breath?.gases[/datum/gas/plasma]) + if (breath?.gases[/datum/gas/plasma] && !skip_breath) var/plasma_pp = breath.get_breath_partial_pressure(breath.gases[/datum/gas/plasma][MOLES]) breather_slime.blood_volume += (0.2 * plasma_pp) // 10/s when breathing literally nothing but plasma, which will suffocate you. diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index a51ad9dd1fe4..69e102a1ac13 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -32,7 +32,7 @@ if((organ_flags & ORGAN_VITAL) && !special && !(organ_owner.status_flags & GODMODE)) if(organ_owner.stat != DEAD) organ_owner.investigate_log("has been killed by losing a vital organ ([src]).", INVESTIGATE_DEATHS) - organ_owner.death() + organ_owner.death(null, "losing your [name]") START_PROCESSING(SSobj, src) @@ -43,6 +43,8 @@ /obj/item/organ/internal/on_death(seconds_per_tick, times_fired) //runs decay when outside of a person if(organ_flags & (ORGAN_SYNTHETIC | ORGAN_FROZEN)) return + if(HAS_TRAIT(src, TRAIT_NO_ORGAN_DECAY) || (owner && HAS_TRAIT(owner, TRAIT_NO_ORGAN_DECAY))) + return apply_organ_damage(decay_factor * maxHealth * seconds_per_tick) /// Called once every life tick on every organ in a carbon's body diff --git a/code/modules/surgery/repair_puncture.dm b/code/modules/surgery/repair_puncture.dm index c61eeeaa8bdd..8097ad9490b3 100644 --- a/code/modules/surgery/repair_puncture.dm +++ b/code/modules/surgery/repair_puncture.dm @@ -26,14 +26,8 @@ /datum/surgery_step/close, ) -/datum/surgery/repair_puncture/can_start(mob/living/user, mob/living/carbon/target) - if(!istype(target)) - return FALSE - . = ..() - if(.) - var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected) - var/datum/wound/burn/flesh/pierce_wound = targeted_bodypart.get_wound_type(targetable_wound) - return(pierce_wound && pierce_wound.blood_flow > 0) +/datum/surgery/repair_puncture/is_valid_wound(datum/wound/wound) + return ..() && wound.blood_flow > 0 //SURGERY STEPS diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index 3f30cd9244a1..3f01d7fe981b 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -67,15 +67,28 @@ operated_bodypart = null return ..() +/datum/surgery/proc/is_valid_wound(datum/wound/wound) + return istype(wound, targetable_wound) /datum/surgery/proc/can_start(mob/user, mob/living/patient) //FALSE to not show in list - . = TRUE if(replaced_by == /datum/surgery) return FALSE + if(targetable_wound) + var/any_wound = FALSE + var/obj/item/bodypart/targeted_bodypart = patient.get_bodypart(user.zone_selected) + for(var/datum/wound/found_wound as anything in targeted_bodypart?.wounds) + if(is_valid_wound(found_wound)) + any_wound = TRUE + break + + if(!any_wound) + return FALSE + if(!requires_tech && !replaced_by) return TRUE + . = TRUE if(requires_tech) . = FALSE @@ -92,16 +105,15 @@ else return TRUE - var/turf/patient_turf = get_turf(patient) - //Get the relevant operating computer - var/obj/machinery/computer/operating/opcomputer = locate_operating_computer(patient_turf) + var/obj/machinery/computer/operating/opcomputer = locate_operating_computer(get_turf(patient)) if (isnull(opcomputer)) return . if(replaced_by in opcomputer.advanced_surgeries) return FALSE if(type in opcomputer.advanced_surgeries) return TRUE + return . /datum/surgery/proc/next_step(mob/living/user, modifiers) if(location != user.zone_selected) diff --git a/monkestation/code/modules/a_medical_day/internal_bleeding.dm b/monkestation/code/modules/a_medical_day/internal_bleeding.dm new file mode 100644 index 000000000000..e9126af8a9d2 --- /dev/null +++ b/monkestation/code/modules/a_medical_day/internal_bleeding.dm @@ -0,0 +1,46 @@ +/datum/wound_pregen_data/internal_bleeding + abstract = FALSE + wound_path_to_generate = /datum/wound/bleed_internal + ignore_cannot_bleed = FALSE + required_limb_biostate = BIO_BLOODED + required_wounding_types = list(WOUND_BLUNT, WOUND_SLASH, WOUND_PIERCE) + threshold_minimum = 45 + +/datum/wound/bleed_internal + name = "Internal Bleeding" + desc = "The patient is bleeding internally, causing severe pain and difficulty breathing." + treat_text = "Surgical repair of the affected vein is necessary." + treat_text_short = "Surgical repair required." + examine_desc = "" + scar_keyword = "" + severity = WOUND_SEVERITY_MODERATE + simple_treat_text = "Surgery." + homemade_treat_text = "Taking a blood clotting pill may help slow the bleeding, \ + or an iron supplement to help your body recover." + processes = TRUE + wound_flags = NONE + /// How much blood lost per life tick, gets modified by severity. + var/bleed_amount = 0.25 + /// Cooldown between when the wound can be allowed to worsen + COOLDOWN_DECLARE(worsen_cd) + +/datum/wound/bleed_internal/get_self_check_description(mob/user) + return span_warning("It feels tense to the touch.") // same as rib fracture! + +/datum/wound/bleed_internal/handle_process(seconds_per_tick, times_fired) + if(!victim || victim.stat == DEAD || HAS_TRAIT(victim, TRAIT_STASIS) || !victim.needs_heart()) + return + victim.bleed(bleed_amount * severity * seconds_per_tick) + +/datum/wound/bleed_internal/wound_injury(datum/wound/old_wound, attack_direction) + COOLDOWN_START(src, worsen_cd, 5 SECONDS) + +/datum/wound/bleed_internal/receive_damage(wounding_type, wounding_dmg, wound_bonus, attack_direction, damage_source) + if(wounding_type == WOUND_BURN || wound_bonus == CANT_WOUND) + return + if(!COOLDOWN_FINISHED(src, worsen_cd)) + return + if(wounding_dmg + wound_bonus + rand(-10, 30) - victim.getarmor(limb, WOUND) < 45) + return + severity = min(severity + 1, WOUND_SEVERITY_CRITICAL) + COOLDOWN_START(src, worsen_cd, 6 SECONDS) diff --git a/monkestation/code/modules/a_medical_day/lungless.dm b/monkestation/code/modules/a_medical_day/lungless.dm new file mode 100644 index 000000000000..3611d366aa00 --- /dev/null +++ b/monkestation/code/modules/a_medical_day/lungless.dm @@ -0,0 +1,30 @@ +/datum/status_effect/lungless + id = "no_lungs" + alert_type = null + duration = -1 + tick_interval = -1 + +/datum/status_effect/lungless/on_apply() + if(!iscarbon(owner)) + return FALSE + var/mob/living/carbon/carbon_owner = owner + if(isnull(carbon_owner.dna?.species?.mutantlungs)) + return FALSE + + RegisterSignal(owner, COMSIG_CARBON_ATTEMPT_BREATHE, PROC_REF(block_breath)) + RegisterSignal(owner, COMSIG_SPECIES_GAIN, PROC_REF(check_new_species)) + return TRUE + +/datum/status_effect/lungless/on_remove() + UnregisterSignal(owner, list(COMSIG_CARBON_ATTEMPT_BREATHE, COMSIG_SPECIES_GAIN)) + +/datum/status_effect/lungless/proc/block_breath(...) + SIGNAL_HANDLER + owner.apply_damage(HUMAN_MAX_OXYLOSS, OXY) + return BREATHE_SKIP_BREATH + +/datum/status_effect/lungless/proc/check_new_species(...) + SIGNAL_HANDLER + var/mob/living/carbon/carbon_owner = owner + if(isnull(carbon_owner.dna?.species?.mutantlungs)) + qdel(src) diff --git a/monkestation/code/modules/a_medical_day/surgery.dm b/monkestation/code/modules/a_medical_day/surgery.dm new file mode 100644 index 000000000000..90ca00ff3327 --- /dev/null +++ b/monkestation/code/modules/a_medical_day/surgery.dm @@ -0,0 +1,121 @@ +/datum/surgery_step/heal/proc/get_perfect_information(mob/user, mob/target) + if(issilicon(user)) + return TRUE + if(user.is_holding_item_of_type(/obj/item/healthanalyzer)) + return TRUE + for(var/obj/machinery/computer/puter in range(2, target)) + if(istype(puter, /obj/machinery/computer/operating)) + var/obj/machinery/computer/operating/op_comp = puter + if(op_comp.table?.patient == target) + return TRUE + if(istype(puter, /obj/machinery/computer/vitals_reader)) + var/obj/machinery/computer/vitals_reader/vr_comp = puter + if(vr_comp.patient == target) + return TRUE + // melbert todo : add modsuit health analyzer to this + return FALSE + +/datum/surgery/repair_broken_rib + name = "Repair fractured rib (hairline)" + surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB + targetable_wound = /datum/wound/blunt/bone/rib_break + possible_locs = list( + BODY_ZONE_CHEST, + ) + steps = list( + /datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/repair_bone_hairline, + /datum/surgery_step/close, + ) + +/// Repair internal bleeding +/datum/surgery/internal_bleeding + name = "Repair Internal Bleeding" + surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB + targetable_wound = /datum/wound/bleed_internal + target_mobtypes = list(/mob/living/carbon) + possible_locs = list( + BODY_ZONE_R_ARM, + BODY_ZONE_L_ARM, + BODY_ZONE_R_LEG, + BODY_ZONE_L_LEG, + BODY_ZONE_CHEST, + BODY_ZONE_HEAD, + ) + steps = list( + /datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/repair_veins, + /datum/surgery_step/close, + ) + +/datum/surgery_step/repair_veins + name = "repair arterial bleeding (hemostat/blood filter)" + implements = list( + TOOL_HEMOSTAT = 100, + TOOL_BLOODFILTER = 100, + TOOL_WIRECUTTER = 40, + /obj/item/stack/sticky_tape/surgical = 30, + /obj/item/stack/cable_coil = 10, + /obj/item/stack/sticky_tape = 10, + ) + preop_sound = 'sound/surgery/hemostat1.ogg' + success_sound = 'sound/surgery/organ2.ogg' + time = 6 SECONDS + repeatable = TRUE + pain_amount = 12 + +/datum/surgery_step/repair_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/in_where = "[target]'s [parse_zone(target_zone)]" + display_results( + user, + target, + span_notice("You begin repair the arteries in [in_where]..."), + span_notice("[user] begins to repair the arteries in [in_where] with [tool]."), + span_notice("[user] begins to repair the arteries in [in_where]."), + ) + display_pain( + target, + "You feel a horrible stabbing pain in your [parse_zone(target_zone)]!", + target_zone = target_zone, + ) + +/datum/surgery_step/repair_veins/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + var/in_where = "[target]'s [parse_zone(target_zone)]" + if((surgery.operated_wound?.severity - 1) <= WOUND_SEVERITY_TRIVIAL) + qdel(surgery.operated_wound) + display_results( + user, + target, + span_green("You've finishes repairing all the arterial damage in [in_where]."), + span_green("[user] finishes repaiing all the arterial damage in [in_where] with [tool]!"), + span_green("[user] finishes repaiing all the arterial damage in [in_where]!"), + ) + repeatable = FALSE + return ..() + + surgery.operated_wound.severity-- + display_results( + user, + target, + span_notice("You successfully repair some of the arteries in [in_where] with [tool]."), + span_notice("[user] successfully repairs some of the arteries in [in_where] with [tool]!"), + span_notice("[user] successfully repairs some of the arteries in [in_where]!"), + ) + target.apply_damage(3, BRUTE, surgery.operated_bodypart, wound_bonus = CANT_WOUND, attacking_item = tool) + return ..() + +/datum/surgery_step/repair_veins/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, fail_prob = 0) + var/in_where = "[target]'s [parse_zone(target_zone)]" + display_results( + user, + target, + span_warning("You tear some of the arteries in [in_where]!"), + span_warning("[user] tears some of the arteries in [in_where] with [tool]!"), + span_warning("[user] tears some of the arteries in [in_where]!"), + ) + target.apply_damage(rand(4, 8), BRUTE, surgery.operated_bodypart, wound_bonus = 10, sharpness = SHARP_EDGED, attacking_item = tool) + return FALSE diff --git a/monkestation/code/modules/a_medical_day/thermics.dm b/monkestation/code/modules/a_medical_day/thermics.dm new file mode 100644 index 000000000000..9c4af98dd405 --- /dev/null +++ b/monkestation/code/modules/a_medical_day/thermics.dm @@ -0,0 +1,94 @@ +/// Hypo and Hyperthermia status effects. +/datum/status_effect/thermia + id = "thermia" + alert_type = null + status_type = STATUS_EFFECT_REPLACE + tick_interval = 3 SECONDS + processing_speed = STATUS_EFFECT_NORMAL_PROCESS + /// Flat penalty of consciousness applied over time + var/consciousness_mod = 0 + var/max_consciousness_mod = 0 + var/datum/weakref/alert_ref + COOLDOWN_DECLARE(update_cd) + +/datum/status_effect/thermia/on_apply() + + give_alert() + COOLDOWN_START(src, update_cd, 6 SECONDS) + return TRUE + +/datum/status_effect/thermia/on_remove() + owner.clear_alert(ALERT_TEMPERATURE) + owner.clear_mood_event(id) + owner.remove_movespeed_modifier(/datum/movespeed_modifier/cold) + +/datum/status_effect/thermia/tick(seconds_between_ticks) + if(!COOLDOWN_FINISHED(src, update_cd)) + return + + owner.adjust_pain_shock(1 * (consciousness_mod * 0.1)) + + COOLDOWN_START(src, update_cd, 9 SECONDS) + +/// Manually applying alerts, rather than using the api for it, becuase we need to apply "severity" argument +/datum/status_effect/thermia/proc/give_alert() + return + +/datum/status_effect/thermia/hypo + var/slowdown_mod + +/datum/status_effect/thermia/hypo/on_creation(mob/living/new_owner, slowdown_mod = 1) + src.slowdown_mod = slowdown_mod + return ..() + +/datum/status_effect/thermia/hypo/on_apply() + . = ..() + owner.add_mood_event(id, /datum/mood_event/cold) + // Apply cold slow down + owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = slowdown_mod) + +/datum/status_effect/thermia/hypo/one + consciousness_mod = 5 + +/datum/status_effect/thermia/hypo/one/give_alert() + return owner.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1) + +/datum/status_effect/thermia/hypo/two + consciousness_mod = 10 + +/datum/status_effect/thermia/hypo/two/give_alert() + return owner.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 2) + +/datum/status_effect/thermia/hypo/three + consciousness_mod = 20 + max_consciousness_mod = 30 + +/datum/status_effect/thermia/hypo/three/give_alert() + return owner.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3) + +/datum/status_effect/thermia/hyper + +/datum/status_effect/thermia/hyper/on_apply() + . = ..() + owner.add_mood_event(id, /datum/mood_event/hot) + //Remove any slowdown from the cold. + owner.remove_movespeed_modifier(/datum/movespeed_modifier/cold) + +/datum/status_effect/thermia/hyper/one + consciousness_mod = 5 + +/datum/status_effect/thermia/hyper/one/give_alert() + return owner.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 1) + +/datum/status_effect/thermia/hyper/two + consciousness_mod = 10 + +/datum/status_effect/thermia/hyper/two/give_alert() + return owner.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 2) + +/datum/status_effect/thermia/hyper/three + consciousness_mod = 20 + max_consciousness_mod = 30 + +/datum/status_effect/thermia/hyper/three/give_alert() + return owner.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 3) diff --git a/monkestation/code/modules/blood_datum/components/limbless_aid.dm b/monkestation/code/modules/blood_datum/components/limbless_aid.dm index 9b035914afbb..95e10c382c5b 100644 --- a/monkestation/code/modules/blood_datum/components/limbless_aid.dm +++ b/monkestation/code/modules/blood_datum/components/limbless_aid.dm @@ -48,6 +48,7 @@ /datum/component/limbless_aid/proc/add_support(mob/living/user) ADD_TRAIT(user, TRAIT_NO_LEG_AID, "[REF(src)]_aid") RegisterSignal(user, COMSIG_LIVING_LIMBLESS_MOVESPEED_UPDATE, PROC_REF(modify_movespeed), override = TRUE) + RegisterSignal(user, COMSIG_CARBON_PAINED_STEP, PROC_REF(pain_step), override = TRUE) RegisterSignal(user, COMSIG_CARBON_LIMPING, PROC_REF(limp_check), override = TRUE) RegisterSignal(user, COMSIG_LIVING_RESIST, PROC_REF(self_brace), override = TRUE) user.update_limbless_locomotion() @@ -62,6 +63,7 @@ REMOVE_TRAIT(user, TRAIT_NO_LEG_AID, "[REF(src)]_aid") un_self_brace(user) UnregisterSignal(user, COMSIG_LIVING_LIMBLESS_MOVESPEED_UPDATE) + UnregisterSignal(user, COMSIG_CARBON_PAINED_STEP) UnregisterSignal(user, COMSIG_CARBON_LIMPING) UnregisterSignal(user, COMSIG_LIVING_RESIST) user.update_limbless_locomotion() @@ -74,6 +76,13 @@ if(isnull(leg) || leg.bodypart_disabled) modifiers += movespeed_mod +/datum/component/limbless_aid/proc/pain_step(mob/living/source, obj/item/affected_leg, footstep_count) + SIGNAL_HANDLER + + var/obj/item/bodypart/leg = get_braced_leg(source) + if(isnull(leg) || leg == affected_leg) + return STOP_PAIN + /datum/component/limbless_aid/proc/limp_check(mob/living/source, obj/item/bodypart/next_leg) SIGNAL_HANDLER @@ -81,19 +90,16 @@ if(isnull(leg) || leg == next_leg) return COMPONENT_CANCEL_LIMP -#define IS_RIGHT_ARM(index) (index % 2 == 0) - /// Checks what side the item is equipped on /datum/component/limbless_aid/proc/get_braced_leg(mob/living/who) if(required_slot & ITEM_SLOT_HANDS) // note this is backwards intentionally: // right arm braces the left leg, and left arm braces right leg - var/side = IS_RIGHT_ARM(who.get_held_index_of_item(parent)) ? BODY_ZONE_L_LEG : BODY_ZONE_R_LEG + var/side = IS_RIGHT(who.get_held_index_of_item(parent)) ? BODY_ZONE_L_LEG : BODY_ZONE_R_LEG return who.get_bodypart(side) return null // unimplemented -#undef IS_RIGHT_ARM /datum/component/limbless_aid/proc/self_brace(mob/living/source) SIGNAL_HANDLER diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm index a6427897c245..67e783f69ed4 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm @@ -14,18 +14,22 @@ /// Lazy Assoc list [zones] to [references to bodyparts], all the body parts we're tracking var/list/body_zones /// Natural amount of decay given to each limb per 5 ticks of process, increases over time - var/natural_pain_decay = -0.2 + var/natural_pain_decay = -0.8 /// The base amount of pain decay received. - var/base_pain_decay = -0.2 + var/base_pain_decay = -0.8 /// Counter to track pain decay. Pain decay is only done once every 5 ticks. var/natural_decay_counter = 0 /// Amount of shock building up from higher levels of pain /// When greater than current health, we go into shock var/shock_buildup = 0 + /// Tracks how many successful heart attack rolls in a row + VAR_FINAL/heart_attack_counter = 0 /// Cooldown to track the last time we lost pain. COOLDOWN_DECLARE(time_since_last_pain_loss) /// Cooldown to track last time we sent a pain message. COOLDOWN_DECLARE(time_since_last_pain_message) + /// Cooldown to track last time heart attack counter went up. + COOLDOWN_DECLARE(time_since_last_heart_attack_counter) #ifdef TESTING /// For testing. Does this pain datum print testing messages when it happens? @@ -84,11 +88,11 @@ RegisterSignal(parent, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(remove_all_pain)) RegisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(add_damage_pain)) RegisterSignal(parent, COMSIG_MOB_STATCHANGE, PROC_REF(on_parent_statchance)) - RegisterSignals(parent, list(COMSIG_LIVING_SET_BODY_POSITION, COMSIG_LIVING_SET_BUCKLED), PROC_REF(check_lying_pain_modifier)) RegisterSignals(parent, list(SIGNAL_ADDTRAIT(TRAIT_NO_PAIN_EFFECTS), SIGNAL_REMOVETRAIT(TRAIT_NO_PAIN_EFFECTS)), PROC_REF(refresh_pain_attributes)) - - if(ishuman(parent)) - RegisterSignal(parent, COMSIG_HUMAN_BURNING, PROC_REF(on_burn_tick)) + RegisterSignal(parent, COMSIG_LIVING_TREAT_MESSAGE, PROC_REF(handle_message)) + RegisterSignal(parent, COMSIG_HUMAN_BURNING, PROC_REF(on_burn_tick)) + RegisterSignal(parent, COMSIG_MOB_FIRED_GUN, PROC_REF(on_mob_fired_gun)) + RegisterSignal(parent, COMSIG_LIVING_REVIVE, PROC_REF(revived)) /** * Unregister all of our signals from our parent when we're done, if we have signals to unregister. @@ -102,9 +106,10 @@ COMSIG_HUMAN_BURNING, COMSIG_LIVING_HEALTHSCAN, COMSIG_LIVING_POST_FULLY_HEAL, - COMSIG_LIVING_SET_BODY_POSITION, - COMSIG_LIVING_SET_BUCKLED, + COMSIG_LIVING_REVIVE, + COMSIG_LIVING_TREAT_MESSAGE, COMSIG_MOB_APPLY_DAMAGE, + COMSIG_MOB_FIRED_GUN, COMSIG_MOB_STATCHANGE, SIGNAL_ADDTRAIT(TRAIT_NO_PAIN_EFFECTS), SIGNAL_REMOVETRAIT(TRAIT_NO_PAIN_EFFECTS), @@ -218,6 +223,14 @@ pain_modifier = 1 for(var/mod in pain_mods) pain_modifier *= pain_mods[mod] + // Throw alert if a drug specifically is numbing us + if(pain_modifier < 0.75) + for(var/datum/reagent/med as anything in parent.reagents.reagent_list) + if(med.pain_modifier <= 0.5) + parent.throw_alert("numbed", /atom/movable/screen/alert/numbed) + break + else + parent.clear_alert("numbed") return old_pain_mod != pain_modifier /** @@ -234,9 +247,9 @@ // No pain at all if(amount == 0) - return + return FALSE if(amount > 0 && (parent.status_flags & GODMODE)) - return + return FALSE for(var/zone in shuffle(def_zones)) var/adjusted_amount = round(amount, 0.01) @@ -244,18 +257,22 @@ if(isnull(adjusted_bodypart)) // it's valid - for if we're passed a zone we don't have continue + var/current_amount = adjusted_bodypart.pain + // Pain is negative (healing) if(adjusted_amount < 0) // Pain is negative and we're at min pain - if(adjusted_bodypart.pain <= adjusted_bodypart.min_pain) + if(current_amount <= adjusted_bodypart.min_pain) continue // Pain is negative and we're above soft cap, incraese the healing amount greatly - if(adjusted_bodypart.pain >= adjusted_bodypart.soft_max_pain) - adjusted_amount *= 3 + if(current_amount >= adjusted_bodypart.soft_max_pain) + adjusted_amount *= 2 * (current_amount / adjusted_bodypart.soft_max_pain) // Pain is positive (dealing) else - // Adjust incoming dealt pain by modifiers + // Pain is positive and we're at the soft cap, reduce the incoming pain + if(current_amount >= adjusted_bodypart.soft_max_pain) + adjusted_amount *= 0.75 * (adjusted_bodypart.soft_max_pain / current_amount) adjusted_amount = round(adjusted_amount * pain_modifier * adjusted_bodypart.bodypart_pain_modifier, 0.01) // Pain modifiers results in us taking 0 pain // (If someone adds a negative pain mod and causes "inverse pain" (which you shouldn't) this needs to go) @@ -271,7 +288,7 @@ #endif // Actually do the pain addition / subtraction here - adjusted_bodypart.pain = max(adjusted_bodypart.pain + adjusted_amount, adjusted_bodypart.min_pain) + adjusted_bodypart.pain = max(current_amount + adjusted_amount, adjusted_bodypart.min_pain) if(adjusted_amount > 0) INVOKE_ASYNC(src, PROC_REF(on_pain_gain), adjusted_bodypart, amount, dam_type) @@ -316,16 +333,18 @@ * affected_part - the bodypart that gained the pain * amount - amount of pain that was gained, post-[pain_modifier] applied */ -/datum/pain/proc/on_pain_gain(obj/item/bodypart/affected_part, amount, type) - affected_part.on_gain_pain_effects(amount) +/datum/pain/proc/on_pain_gain(obj/item/bodypart/affected_part, amount, dam_type) + affected_part.on_gain_pain_effects(amount, dam_type) refresh_pain_attributes() - SEND_SIGNAL(parent, COMSIG_CARBON_PAIN_GAINED, affected_part, amount, type) - COOLDOWN_START(src, time_since_last_pain_loss, 30 SECONDS) + SEND_SIGNAL(parent, COMSIG_CARBON_PAIN_GAINED, affected_part, amount, dam_type) + COOLDOWN_START(src, time_since_last_pain_loss, 60 SECONDS) + if(amount > PAIN_LIMB_MAX * 0.25) + parent.pain_emote("scream", 5 SECONDS) + parent.flash_pain_overlay(2) - if(amount > 12 && prob(25)) - do_pain_emote("scream", 5 SECONDS) - else if(amount > 6 && prob(10)) - do_pain_emote() + else if(amount > PAIN_LIMB_MAX * 0.1) + parent.pain_emote(pick("wince", "gasp", "grimace", "inhale_s", "exhale_s", "flinch"), 3 SECONDS) + parent.flash_pain_overlay(1) /** * Called when pain is lost, if the mob did not lose pain in the last 60 seconds. @@ -363,7 +382,7 @@ SIGNAL_HANDLER - if(damage <= 0 || (parent.status_flags & GODMODE)) + if(damage <= 2.5 || (parent.status_flags & GODMODE)) return if(isbodypart(def_zone)) var/obj/item/bodypart/targeted_part = def_zone @@ -375,12 +394,12 @@ // Attacks with a wound bonus add additional pain (usually, like 2-5) // (Note that if they also succeed in applying a wound, more pain comes from that) // Also, sharp attacks apply a smidge extra pain - var/pain = (2 * damage) + (0.1 * max(wound_bonus + bare_wound_bonus, 1)) * (sharpness ? 1.2 : 1) + var/pain = ((100 - blocked) / 100) * ((10 * damage) ** 0.66 + (0.2 * max(wound_bonus + bare_wound_bonus - parent.getarmor(def_zone, WOUND), 0))) * (sharpness ? 1.2 : 1) switch(damagetype) // Brute pain is dealt to the target zone // pain is just divided by a random number, for variance if(BRUTE) - pain *= (rand(60, 80) / 100) + pain *= pick(0.6, 0.7, 0.8) // Burn pain is dealt to the target zone // pain is lower for weaker burns, but scales up for more damaging burns @@ -442,33 +461,12 @@ // // Note: 99% of sources of oxydamage is done through adjustoxyloss, and as such doesn't go through this if(OXY) - if(HAS_TRAIT(parent, TRAIT_NOBREATH)) - return - def_zone = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST) - var/obj/item/organ/internal/lungs/our_lungs = source.get_organ_slot(ORGAN_SLOT_LUNGS) - if(our_lungs) - switch(our_lungs.damage) - if(20 to 50) - pain += 1 - if(50 to 80) - pain += 2 - if(80 to INFINITY) - pain += 3 - else - pain += 5 - - switch(parent.getOxyLoss()) - if(0 to 20) - pain = 0 - if(20 to 50) - pain += 1 - if(50 to INFINITY) - pain += 3 + return // No pain from stamina loss // In the future stamina can probably cause very sharp pain and replace stamcrit, // but the system will require much finer tuning before then - if(STAMINA) + if(STAMINA, PAIN) return // Head pain causes brain damage, so brain damage causes no pain (to prevent death spirals) @@ -551,120 +549,152 @@ // no-op if none of our bodyparts are in pain return - var/curr_pain = get_average_pain() - switch(curr_pain) - if(-INFINITY to 10) - shock_buildup = max(shock_buildup - 3, -30) // staying out of pain for a while gives you a small resiliency to shock (~1 minute) - - if(10 to 25) - shock_buildup = max(shock_buildup - 1, -30) - - if(25 to 40) - if(SPT_PROB(2, seconds_per_tick)) - do_pain_message(span_danger(pick("Everything aches.", "Everything feels sore."))) - - if(40 to 70) - if(!HAS_TRAIT(parent, TRAIT_NO_SHOCK_BUILDUP)) - shock_buildup += 1 + var/shock_mod = max(pain_modifier, 0.33) + if(HAS_TRAIT(parent, TRAIT_ABATES_SHOCK)) + shock_mod *= 0.5 + if(parent.health > 0) + shock_mod *= 0.25 + if(parent.health <= parent.maxHealth * -2 || (!HAS_TRAIT(parent, TRAIT_NOBLOOD) && parent.blood_volume < BLOOD_VOLUME_BAD)) + shock_mod *= 1.5 + if(parent.health <= parent.maxHealth * -4 || (!HAS_TRAIT(parent, TRAIT_NOBLOOD) && parent.blood_volume < BLOOD_VOLUME_SURVIVE)) + shock_mod *= 2 // stacks with above + var/curr_pain = get_total_pain() + if(curr_pain < PAIN_LIMB_MAX * 0.5) + parent.adjust_pain_shock(-3 * seconds_per_tick) // staying out of pain for a while gives you a small resiliency to shock (~1 minute) + else if(curr_pain < PAIN_LIMB_MAX) + parent.adjust_pain_shock(-1 * seconds_per_tick) + else if(curr_pain < PAIN_LIMB_MAX * 2) + if(shock_buildup <= 30) + parent.adjust_pain_shock(0.5 * shock_mod * seconds_per_tick) + else if(curr_pain < PAIN_LIMB_MAX * 4) + if(shock_buildup <= 65) + parent.adjust_pain_shock(1 * shock_mod * seconds_per_tick) + if(SPT_PROB(2, seconds_per_tick)) + do_pain_message(span_userdanger(pick("It hurts."))) + else + parent.adjust_pain_shock(clamp(round(0.5 * (curr_pain / PAIN_LIMB_MAX), 0.1), 1.5, 8) * shock_mod * seconds_per_tick) + if(SPT_PROB(2, seconds_per_tick)) + do_pain_message(span_userdanger(pick("Stop the pain!", "It hurts!"))) + + switch(shock_buildup) + if(10 to 60) + parent.adjust_bodytemperature(-5 * seconds_per_tick, parent.get_body_temp_cold_damage_limit() + 5) + if(60 to 120) if(SPT_PROB(2, seconds_per_tick)) - do_pain_message(span_bolddanger(pick("Everything hurts.", "Everything feels very sore.", "It hurts."))) - - if(70 to INFINITY) - if(!HAS_TRAIT(parent, TRAIT_NO_SHOCK_BUILDUP)) - shock_buildup += 3 + do_pain_message(span_bolddanger(pick("It hurts.", "You really need some painkillers."))) + if(SPT_PROB(4, seconds_per_tick)) + do_pain_message(span_warning(pick("You feel cold!", "You feel sweaty!"))) + parent.pain_emote("shiver", 3 SECONDS) + parent.adjust_bodytemperature(-10 * seconds_per_tick, parent.get_body_temp_cold_damage_limit() - 5) + if(120 to 180) if(SPT_PROB(2, seconds_per_tick)) - do_pain_message(span_userdanger(pick("Stop the pain!", "Everything hurts!"))) - - // If shock buildup exceeds our health + 30 ticks then well, we enter shock - // This means at 100 health you can be in moderate pain for 130 ticks / 260 seconds / ~4 minutes before falling into shock - if(shock_buildup >= (parent.health + 30) \ - && curr_pain >= 50 \ - && !HAS_TRAIT(parent, TRAIT_NO_SHOCK_BUILDUP) \ - && !is_undergoing_shock() \ - && !parent.undergoing_cardiac_arrest() \ - ) - parent.infect_disease_predefined(DISEASE_SHOCK, TRUE, "[ROUND_TIME()] Inflicted with Pain Shock [key_name(parent)]") - to_chat(parent, span_userdanger("You feel your body start to shut down!")) - if(parent.stat == CONSCIOUS && !parent.incapacitated(IGNORE_RESTRAINTS|IGNORE_GRAB) && !HAS_TRAIT(parent, TRAIT_NO_PAIN_EFFECTS)) - parent.visible_message(span_danger("[parent] grabs at their chest and stares into the distance as they go into shock!"), ignored_mobs = parent) - shock_buildup = -200 // requires another 200 ticks / 400 seconds / ~6 minutes of pain to go into shock again - return - - var/standard_effect_prob = (curr_pain * 0.05) - 0.75 // starts at 15, caps at 4.5 - var/rare_effect_prob = (curr_pain * 0.04) - 1.5 // starts at 40 - var/very_rare_effect_prob = (curr_pain * 0.03) - 2.25 // starts at 70 - - if(standard_effect_prob > 0) - if(!just_cant_feel_anything) - if(SPT_PROB(standard_effect_prob, seconds_per_tick)) - parent.adjust_stutter_up_to(10 SECONDS * pain_modifier, 30 SECONDS) - if(SPT_PROB(standard_effect_prob, seconds_per_tick)) - parent.adjust_jitter_up_to(20 SECONDS * pain_modifier, 60 SECONDS) - if(SPT_PROB(standard_effect_prob, seconds_per_tick)) - parent.adjust_dizzy_up_to(10 SECONDS * pain_modifier, 30 SECONDS) - if(curr_pain >= 70) - parent.adjust_confusion_up_to(8 SECONDS * pain_modifier, 24 SECONDS) - if(SPT_PROB(standard_effect_prob * 1.2, seconds_per_tick) && parent.stamina?.loss <= 80) - var/stam_taken = round((0.2 * curr_pain + 8) * pain_modifier) // 10 = 10, 100 = 28, good enough - if(just_cant_feel_anything) - parent.apply_damage(stam_taken * 1.2, STAMINA) - // First we apply damage, if that succeeds -> - // Check how much damage, if above a threshold -> - // Run a pain emote, if the pain emote succeeds as well -> - else if(parent.apply_damage(stam_taken, STAMINA) && stam_taken >= 15 && do_pain_emote(pick("wince", "gasp"))) - parent.visible_message(span_warning("[parent] doubles over in pain!")) - - if(rare_effect_prob > 0) - if(SPT_PROB(rare_effect_prob * 2, seconds_per_tick)) - var/list/options = list("wince", "whimper") - if(curr_pain >= 70) - options.Add("cry", "scream") - do_pain_emote(pick(options), 5 SECONDS) - if(SPT_PROB(rare_effect_prob, seconds_per_tick) && parent.body_position != LYING_DOWN && !just_cant_feel_anything) - parent.Knockdown(2 SECONDS * pain_modifier) - parent.visible_message(span_warning("[parent] collapses from pain!")) - if(SPT_PROB(rare_effect_prob, seconds_per_tick)) - var/obj/item/held_item = parent.get_active_held_item() - var/obj/item/bodypart/active_hand = parent.get_active_hand() - if(held_item && active_hand && parent.dropItemToGround(held_item)) - if(active_hand.bodytype & BODYTYPE_ROBOTIC) - to_chat(parent, span_danger("Your hand malfunctions, causing you to drop [held_item]!")) - parent.visible_message(span_warning("[parent]'s hand malfunctions, causing them to drop [held_item]!"), ignored_mobs = parent) - do_sparks(number = 1, source = parent) - else if(just_cant_feel_anything) - to_chat(parent, span_danger("Your hand spams and you drop [held_item]!")) - else - to_chat(parent, span_danger("Your fumble though the pain and drop [held_item]!")) - parent.visible_message(span_warning("[parent] fumbles around and drops [held_item]!"), ignored_mobs = parent) - do_pain_emote("gasp") - - if(very_rare_effect_prob > 0) - if(SPT_PROB(very_rare_effect_prob, seconds_per_tick)) - parent.vomit(50) - if(SPT_PROB(very_rare_effect_prob, seconds_per_tick) && !just_cant_feel_anything) - parent.adjust_confusion_up_to(8 SECONDS, 24 SECONDS) - - // Finally, handle pain decay over time - if(HAS_TRAIT(parent, TRAIT_STASIS) || parent.on_fire || parent.stat == DEAD) - return - - // Decay every 3 ticks / 6 seconds, or 1 ticks / 2 seconds if "sleeping" - var/every_x_ticks = HAS_TRAIT(parent, TRAIT_KNOCKEDOUT) ? 1 : 3 - - natural_decay_counter++ - if(natural_decay_counter % every_x_ticks != 0) - return + do_pain_message(span_userdanger(pick("Stop the pain!", "It hurts!", "You need painkillers now!"))) + if(SPT_PROB(4, seconds_per_tick)) + do_pain_message(span_warning("You feel freezing!")) + parent.pain_emote("shiver", 3 SECONDS) + parent.adjust_bodytemperature(-20 * seconds_per_tick, parent.get_body_temp_cold_damage_limit() - 20) + + if((shock_buildup >= 20 || curr_pain >= PAIN_LIMB_MAX) && !just_cant_feel_anything) + if(SPT_PROB(min(curr_pain / 5, 24), seconds_per_tick)) + parent.adjust_jitter_up_to(5 SECONDS * pain_modifier, 30 SECONDS) + if(SPT_PROB(min(curr_pain / 10, 12), seconds_per_tick)) + parent.adjust_dizzy_up_to(5 SECONDS * pain_modifier, 30 SECONDS) + if(SPT_PROB(min(curr_pain / 20, 6), seconds_per_tick)) // pain applies its own stutter + parent.adjust_stutter_up_to(5 SECONDS * pain_modifier, 30 SECONDS) + + if(shock_buildup >= 40 && parent.stat != HARD_CRIT) + if(SPT_PROB(shock_buildup / 60, seconds_per_tick)) + //parent.vomit(VOMIT_CATEGORY_KNOCKDOWN, lost_nutrition = 7.5) + parent.Knockdown(rand(3 SECONDS, 6 SECONDS)) + + if(shock_buildup >= 60 || curr_pain >= PAIN_CHEST_MAX) + if(SPT_PROB(shock_buildup / 20, seconds_per_tick) && !parent.IsParalyzed() && parent.Paralyze(rand(2 SECONDS, 8 SECONDS))) + parent.visible_message( + span_warning("[parent]'s body falls limp!"), + span_warning("Your body [just_cant_feel_anything ? "goes" : "falls"] limp!"), + + ) + if(SPT_PROB(shock_buildup / 20, seconds_per_tick)) + parent.adjust_confusion_up_to(8 SECONDS * pain_modifier, 24 SECONDS) + + if((shock_buildup >= 120 || curr_pain >= PAIN_CHEST_MAX * 2) && SPT_PROB(shock_buildup / 40, seconds_per_tick) && parent.stat != HARD_CRIT) + if(!parent.IsUnconscious() && parent.Unconscious(rand(4 SECONDS, 16 SECONDS))) + parent.visible_message( + span_warning("[parent] falls unconscious!"), + span_warning(pick("You black out!", "You feel like you're about to die!", "You lose consciousness!")), + + ) + + // This is death + if(shock_buildup >= 120 && !parent.undergoing_cardiac_arrest()) + var/heart_attack_prob = 0 + if(parent.health <= parent.maxHealth * -1) + heart_attack_prob += abs(parent.health + parent.maxHealth) * 0.1 + if(shock_buildup >= 180) + heart_attack_prob += (shock_buildup * 0.1) + if(SPT_PROB(min(20, heart_attack_prob), seconds_per_tick)) + if(!COOLDOWN_FINISHED(src, time_since_last_heart_attack_counter)) + parent.losebreath += 1 + else if(!parent.can_heartattack()) + parent.losebreath += 4 + else if(heart_attack_counter >= 3) + to_chat(parent, span_userdanger("Your heart stops!")) + if(!parent.incapacitated()) + parent.visible_message(span_danger("[parent] grabs at [parent.p_their()] chest!"), ignored_mobs = parent) + parent.set_heartattack(TRUE) + heart_attack_counter = -2 + else + COOLDOWN_START(src, time_since_last_heart_attack_counter, 6 SECONDS) + parent.losebreath += 1 + heart_attack_counter += 1 + switch(heart_attack_counter) + if(-INFINITY to 0) + pass() + if(1) + to_chat(parent, span_userdanger("You feel your heart beat irregularly.")) + if(2) + to_chat(parent, span_userdanger("You feel your heart skip a beat.")) + else + to_chat(parent, span_userdanger("You feel your body shutting down!")) + else + heart_attack_counter = 0 - natural_decay_counter = 0 - if(COOLDOWN_FINISHED(src, time_since_last_pain_loss) && parent.stat == CONSCIOUS) - // 0.16 per 10 seconds, ~0.1 per minute, 10 minutes for ~1 decay - natural_pain_decay = max(natural_pain_decay - 0.12, -4) - else - natural_pain_decay = base_pain_decay + // This is where "soft crit" is now + if(shock_buildup >= 90) + if(!HAS_TRAIT_FROM(parent, TRAIT_LABOURED_BREATHING, PAINSHOCK)) + ADD_TRAIT(parent, TRAIT_LABOURED_BREATHING, PAINSHOCK) + set_pain_modifier(PAINSHOCK, 1.2) + parent.apply_status_effect(/datum/status_effect/low_blood_pressure) + parent.add_traits(list(TRAIT_LABOURED_BREATHING), PAINSHOCK) - // modify our pain decay by our pain modifier (ex. 0.5 pain modifier = 2x natural pain decay, capped at ~3x) - var/pain_modified_decay = round(natural_pain_decay * (1 / max(pain_modifier, 0.33)), 0.01) - adjust_bodypart_pain(BODY_ZONES_ALL, pain_modified_decay) + else + if(HAS_TRAIT_FROM(parent, TRAIT_LABOURED_BREATHING, PAINSHOCK)) + unset_pain_modifier(PAINSHOCK) + parent.remove_status_effect(/datum/status_effect/low_blood_pressure) + parent.remove_traits(list(TRAIT_LABOURED_BREATHING), PAINSHOCK) + + // This is "pain crit", it's where stamcrit has moved and is also applied by extreme shock + if(curr_pain >= PAIN_LIMB_MAX * 3 || shock_buildup >= 150) + parent.adjust_jitter_up_to(5 SECONDS * pain_modifier, 60 SECONDS) + if(!HAS_TRAIT_FROM(parent, TRAIT_LABOURED_BREATHING, PAINCRIT)) + var/is_standing = parent.body_position == STANDING_UP + parent.add_traits(list(TRAIT_LABOURED_BREATHING, TRAIT_INCAPACITATED, TRAIT_IMMOBILIZED, TRAIT_FLOORED, TRAIT_HANDS_BLOCKED), PAINCRIT) + if(is_standing && parent.body_position != STANDING_UP) + parent.visible_message( + span_warning("[parent] collapses!"), + span_userdanger("You collapse, unable to stand!"), + + ) + else + parent.visible_message( + span_warning("[parent] slumps against the ground!"), + span_userdanger("You go limp, unable to get up!"), + + ) + + else if(HAS_TRAIT_FROM(parent, TRAIT_LABOURED_BREATHING, PAINCRIT)) + parent.Paralyze(2 SECONDS) + parent.remove_traits(list(TRAIT_LABOURED_BREATHING, TRAIT_INCAPACITATED, TRAIT_IMMOBILIZED, TRAIT_FLOORED, TRAIT_HANDS_BLOCKED), PAINCRIT) /** * Whenever we buckle to something or lie down, get a pain bodifier. @@ -698,48 +728,72 @@ // We can be liberal with this because when they're extinguished most of it will go away. parent.apply_status_effect(/datum/status_effect/pain_from_fire, clamp(parent.fire_stacks * 0.2, 0, 2)) -/** - * Apply or remove pain various modifiers from pain (mood, action speed, movement speed) based on the [average_pain]. - */ +/// Affect accuracy of fired guns while in pain. +/datum/pain/proc/on_mob_fired_gun(mob/living/carbon/human/user, obj/item/gun/gun_fired, target, params, zone_override, list/bonus_spread_values) + SIGNAL_HANDLER + var/obj/item/bodypart/shooting_with = user.get_active_hand() + var/obj/item/bodypart/chest = user.get_bodypart(BODY_ZONE_CHEST) + var/obj/item/bodypart/head = user.get_bodypart(BODY_ZONE_HEAD) + + var/penalty = 0 + // Basically averaging the pain of the shooting hand, chest, and head, with the hand being weighted more + penalty += shooting_with?.get_modified_pain() + penalty += chest?.get_modified_pain() * 0.5 + penalty += head?.get_modified_pain() * 0.5 + penalty /= 3 + // Then actually making it into the final value + penalty = floor(penalty / 5) + // Applying min and max + /* + bonus_spread_values[MIN_BONUS_SPREAD_INDEX] += penalty + bonus_spread_values[MAX_BONUS_SPREAD_INDEX] += penalty * 3 + */ + +/// Apply or remove pain various modifiers from pain (mood, action speed, movement speed) based on the [average_pain]. /datum/pain/proc/refresh_pain_attributes(...) SIGNAL_HANDLER - if(!parent.can_feel_pain()) - clear_pain_attributes() - return + var/avg_pain = get_average_pain() - switch(get_average_pain()) + // Pain is halved if you can't feel pain (but ignore pain modifier for now) + if(avg_pain && parent.stat != DEAD && !parent.can_feel_pain(TRUE)) + avg_pain *= 0.5 + + // Pain is set to 0 fully if you can't feel pain OR pain modifier <= 0.5 (numbness threshold) + if(avg_pain && (parent.stat == DEAD || !parent.can_feel_pain(FALSE))) + avg_pain = 0 + + switch(avg_pain) if(-INFINITY to 20) - clear_pain_attributes() + parent.mob_surgery_speed_mod = initial(parent.mob_surgery_speed_mod) + parent.outgoing_damage_mod = initial(parent.outgoing_damage_mod) + parent.remove_movespeed_modifier(MOVESPEED_ID_PAIN) + parent.remove_actionspeed_modifier(ACTIONSPEED_ID_PAIN) + parent.clear_mood_event(PAIN) if(20 to 40) parent.mob_surgery_speed_mod = 0.9 + parent.outgoing_damage_mod = 0.9 parent.add_movespeed_modifier(/datum/movespeed_modifier/pain/light) parent.add_actionspeed_modifier(/datum/actionspeed_modifier/pain/light) - parent.add_mood_event("pain", /datum/mood_event/light_pain) + parent.add_mood_event(PAIN, /datum/mood_event/light_pain) if(40 to 60) parent.mob_surgery_speed_mod = 0.75 + parent.outgoing_damage_mod = 0.75 parent.add_movespeed_modifier(/datum/movespeed_modifier/pain/medium) parent.add_actionspeed_modifier(/datum/actionspeed_modifier/pain/medium) - parent.add_mood_event("pain", /datum/mood_event/med_pain) + parent.add_mood_event(PAIN, /datum/mood_event/med_pain) if(60 to 80) parent.mob_surgery_speed_mod = 0.6 + parent.outgoing_damage_mod = 0.6 parent.add_movespeed_modifier(/datum/movespeed_modifier/pain/heavy) parent.add_actionspeed_modifier(/datum/actionspeed_modifier/pain/heavy) - parent.add_mood_event("pain", /datum/mood_event/heavy_pain) + parent.add_mood_event(PAIN, /datum/mood_event/heavy_pain) if(80 to INFINITY) parent.mob_surgery_speed_mod = 0.5 + parent.outgoing_damage_mod = 0.5 parent.add_movespeed_modifier(/datum/movespeed_modifier/pain/crippling) parent.add_actionspeed_modifier(/datum/actionspeed_modifier/pain/crippling) - parent.add_mood_event("pain", /datum/mood_event/crippling_pain) - -/** - * Clears all pain related attributes - */ -/datum/pain/proc/clear_pain_attributes() - parent.mob_surgery_speed_mod = initial(parent.mob_surgery_speed_mod) - parent.remove_movespeed_modifier(MOVESPEED_ID_PAIN) - parent.remove_actionspeed_modifier(ACTIONSPEED_ID_PAIN) - parent.clear_mood_event("pain") + parent.add_mood_event(PAIN, /datum/mood_event/crippling_pain) /** * Run a pain related emote, if a few checks are successful. @@ -758,7 +812,7 @@ if(parent.stat >= UNCONSCIOUS || parent.incapacitated(IGNORE_RESTRAINTS|IGNORE_GRAB)) return FALSE - parent.emote(emote) + INVOKE_ASYNC(parent, TYPE_PROC_REF(/mob, emote), emote) COOLDOWN_START(src, time_since_last_pain_message, cooldown) return TRUE @@ -803,13 +857,50 @@ total_pain += adjusted_bodypart.pain max_total_pain += adjusted_bodypart.soft_max_pain - return 100 * total_pain / max_total_pain + return round(100 * total_pain / max_total_pain, 0.01) -/** - * Returns a disease datum (Truthy value) if we are undergoing shock. - */ -/datum/pain/proc/is_undergoing_shock() - return locate(/datum/disease/advanced/premade/shock) in parent.diseases +/// Get the total pain of all bodyparts. +/datum/pain/proc/get_total_pain() + var/total_pain = 0 + for(var/zone in body_zones) + var/obj/item/bodypart/adjusted_bodypart = body_zones[zone] + total_pain += adjusted_bodypart.pain + + return total_pain + +/// Adds a custom stammer to people under the effects of pain. +/datum/pain/proc/handle_message(datum/source, list/message_args) + SIGNAL_HANDLER + + var/phrase = html_decode(message_args[TREAT_MESSAGE_MESSAGE]) + if(!length(phrase)) + return + + var/num_repeats = get_average_pain() * pain_modifier + if(HAS_TRAIT(parent, TRAIT_NO_PAIN_EFFECTS) && shock_buildup < 90) + num_repeats *= 0.5 + + num_repeats = floor(num_repeats / 20) + if(num_repeats <= 1) + return + var/static/regex/no_stammer = regex(@@[ ""''()[\]{}.!?,:;_`~-]@) + var/static/regex/half_stammer = regex(@@[aeiouAEIOU]@) + var/final_phrase = "" + var/original_char = "" + for(var/i = 1, i <= length(phrase), i += length(original_char)) + original_char = phrase[i] + if(no_stammer.Find(original_char)) + final_phrase += original_char + continue + if(half_stammer.Find(original_char)) + if(num_repeats <= 2) + final_phrase += original_char + continue + final_phrase += repeat_string(ceil(num_repeats / 2), original_char) + continue + final_phrase += repeat_string(num_repeats, original_char) + + message_args[TREAT_MESSAGE_MESSAGE] = sanitize(final_phrase) /** * Remove all pain, pain paralysis, side effects, etc. from our mob after we're fully healed by something (like an adminheal) @@ -844,6 +935,33 @@ else START_PROCESSING(SSpain, src) +/// When we are revived, reduced shock +/datum/pain/proc/revived(...) + SIGNAL_HANDLER + + shock_buildup /= 3 + +/// Used to get the effect of pain on the parent's heart rate. +/datum/pain/proc/get_heartrate_modifier() + var/base_amount = 0 + switch(get_average_pain()) // pain raises it a bit + if(25 to 50) + base_amount += 5 + if(50 to 75) + base_amount += 10 + if(75 to INFINITY) + base_amount += 15 + + switch(pain_modifier) // numbness lowers it a bit + if(0.25 to 0.5) + base_amount -= 15 + if(0.5 to 0.75) + base_amount -= 10 + if(0.75 to 1) + base_amount -= 5 + + return base_amount + /** * Signal proc for [COMSIG_LIVING_HEALTHSCAN] * Reports how much pain [parent] is sustaining to [user]. @@ -853,14 +971,18 @@ * the patient is encouraged to elaborate on which bodyparts hurt the most, and how much they hurt. * (To encourage a bit more interaction between the doctors.) */ -/datum/pain/proc/on_analyzed(datum/source, list/render_list, advanced, mob/user, mode) +/datum/pain/proc/on_analyzed(datum/source, list/render_list, advanced, mob/user, mode, tochat) SIGNAL_HANDLER + if(parent.stat == DEAD) + return + + var/in_shock = HAS_TRAIT_FROM(parent, TRAIT_LABOURED_BREATHING, PAINSHOCK) + var/amount = "" var/tip = "" - var/in_shock = !!is_undergoing_shock() - if(in_shock) - tip += span_bold("Neurogenic shock has begun and should be treated urgently. ") + var/amount_text = "" + var/shock_text = "" switch(get_average_pain()) if(5 to 15) @@ -883,11 +1005,24 @@ tip += span_bold("Alert: High potential of neurogenic shock. ") tip += "Treat wounds and abate pain with long rest, cryogenics, and heavy painkilling medication." - if(amount && tip) - render_list += "" - render_list += span_bold("Subject is experiencing [amount] pain. ") - render_list += tip - render_list += "\n" + if(!amount) + return + + amount_text = span_danger("Subject is experiencing [amount] pain.") + if(tochat && tip) + amount_text = span_tooltip(tip, amount_text) + + if(in_shock) + shock_text = span_bold("Neurogenic shock has begun and should be treated urgently.") + if(shock_text && tochat) + shock_text = span_tooltip("Provide immediate pain relief, epinephrine, and moderate body temperature. \ + [in_shock ? "Monitor closely for worsening condition or cardiac arrest. " : ""]Cryogenics may also aid in recovery.", shock_text) + + render_list += "" + if(shock_text) + render_list += "[shock_text] / " + render_list += amount_text + render_list += "\n" #ifdef TESTING debug_print_pain() @@ -940,3 +1075,13 @@ amount = clamp(amount, -200, 200) adjust_bodypart_pain(zone, amount) + + +/** + * Clears all pain related attributes + */ +/datum/pain/proc/clear_pain_attributes() + parent.mob_surgery_speed_mod = initial(parent.mob_surgery_speed_mod) + parent.remove_movespeed_modifier(MOVESPEED_ID_PAIN) + parent.remove_actionspeed_modifier(ACTIONSPEED_ID_PAIN) + parent.clear_mood_event("pain") diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/modifiers.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/modifiers.dm index 3d30c8f8348b..89b0510adb5d 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/modifiers.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/modifiers.dm @@ -114,12 +114,3 @@ var/mob/living/carbon/human/human_owner = owner human_owner.unset_pain_mod(id) return ..() - -// Reacting to all cases of gaining knocked out rather than just sleeping -/mob/living/on_knockedout_trait_gain(datum/source) - . = ..() - set_pain_mod(PAIN_MOD_KOD, 0.8) - -/mob/living/on_knockedout_trait_loss(datum/source) - . = ..() - unset_pain_mod(PAIN_MOD_KOD) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/anesthetics.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/anesthetics.dm index 03f24a52b8a0..22a82216fce5 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/anesthetics.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/anesthetics.dm @@ -2,6 +2,7 @@ /datum/status_effect/grouped/anesthetic id = "anesthetics" alert_type = /atom/movable/screen/alert/status_effect/anesthetics + var/applied_at = -1 /datum/status_effect/grouped/anesthetic/on_creation(mob/living/new_owner, source) if(!istype(get_area(new_owner), /area/station/medical)) @@ -13,10 +14,13 @@ /datum/status_effect/grouped/anesthetic/on_apply() . = ..() RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_KNOCKEDOUT), PROC_REF(try_removal)) + applied_at = world.time /datum/status_effect/grouped/anesthetic/on_remove() . = ..() UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_KNOCKEDOUT)) + if(!QDELETED(owner)) + owner.apply_status_effect(/datum/status_effect/anesthesia_grog, applied_at) /datum/status_effect/grouped/anesthetic/get_examine_text() return span_warning("[owner.p_Theyre()] out cold.") @@ -40,3 +44,17 @@ . = ..() if(HAS_TRAIT(breather, TRAIT_KNOCKEDOUT)) breather.apply_status_effect(/datum/status_effect/grouped/anesthetic, /datum/gas/nitrous_oxide) + +/datum/status_effect/anesthesia_grog + id = "anesthesia_grog" + duration = 4 MINUTES + alert_type = null + var/strength = 0 + +/datum/status_effect/anesthesia_grog/on_creation(mob/living/new_owner, anesthesia_appied_at) + strength = (world.time - anesthesia_appied_at > 1 MINUTES) ? 50 : 90 + return ..() + +/datum/status_effect/anesthesia_grog/on_apply() + to_chat(owner, span_warning("You feel[strength <= 90 ? " ":" a bit "]groggy...")) + return TRUE diff --git a/monkestation/code/modules/cybernetics/augments/internal_implants.dm b/monkestation/code/modules/cybernetics/augments/internal_implants.dm index 7d51e6e6977f..cc45596b866e 100644 --- a/monkestation/code/modules/cybernetics/augments/internal_implants.dm +++ b/monkestation/code/modules/cybernetics/augments/internal_implants.dm @@ -165,6 +165,7 @@ slot = ORGAN_SLOT_BREATHING_TUBE w_class = WEIGHT_CLASS_TINY encode_info = AUGMENT_NO_REQ + organ_traits = list(TRAIT_ASSISTED_BREATHING) /obj/item/organ/internal/cyberimp/mouth/breathing_tube/emp_act(severity) . = ..() diff --git a/tgstation.dme b/tgstation.dme index 2dbdf1a09058..73e4636efe59 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -5959,6 +5959,10 @@ #include "monkestation\code\game\turfs\open\water.dm" #include "monkestation\code\game\turfs\open\floor\misc_floor.dm" #include "monkestation\code\modules\_paperwork\paper_premade.dm" +#include "monkestation\code\modules\a_medical_day\internal_bleeding.dm" +#include "monkestation\code\modules\a_medical_day\lungless.dm" +#include "monkestation\code\modules\a_medical_day\surgery.dm" +#include "monkestation\code\modules\a_medical_day\thermics.dm" #include "monkestation\code\modules\a_ship_in_need_of_breaking\area.dm" #include "monkestation\code\modules\a_ship_in_need_of_breaking\scrap.dm" #include "monkestation\code\modules\a_ship_in_need_of_breaking\machines\console.dm" From c42196affd044060a6adab75b770c53e3f33b988 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 13 Sep 2024 00:08:51 -0700 Subject: [PATCH 037/158] Update health_analyzer.dm --- .../items/devices/scanners/health_analyzer.dm | 97 +++++++++++-------- 1 file changed, 54 insertions(+), 43 deletions(-) diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index 655e7bcb6e4c..e25b845bfe41 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -265,51 +265,62 @@ if(ishuman(target)) var/mob/living/carbon/human/humantarget = target - // Organ damage, missing organs - if(humantarget.organs && humantarget.organs.len) - var/render = FALSE - var/toReport = "Organs:\ - \ - \ - [advanced ? "" : ""]\ - " - - for(var/obj/item/organ/organ as anything in humantarget.organs) - var/status = organ.get_status_text() - if (status != "") + var/render = FALSE + var/toReport = "Organ status:\ + \ +
Organ:DmgStatus
\ + \ + \ + [advanced ? "" : ""]\ + \ + " + + var/list/missing_organs = list() + if(!humantarget.get_organ_slot(ORGAN_SLOT_BRAIN)) + missing_organs[ORGAN_SLOT_BRAIN] = "Brain" + if(!humantarget.needs_heart() && !humantarget.get_organ_slot(ORGAN_SLOT_HEART)) + missing_organs[ORGAN_SLOT_HEART] = "Heart" + if(!HAS_TRAIT_FROM(humantarget, TRAIT_NOBREATH, SPECIES_TRAIT) && !isnull(humantarget.dna.species.mutantlungs) && !humantarget.get_organ_slot(ORGAN_SLOT_LUNGS)) + missing_organs[ORGAN_SLOT_LUNGS] = "Lungs" + if(!HAS_TRAIT_FROM(humantarget, TRAIT_LIVERLESS_METABOLISM, SPECIES_TRAIT) && !isnull(humantarget.dna.species.mutantliver) && !humantarget.get_organ_slot(ORGAN_SLOT_LIVER)) + missing_organs[ORGAN_SLOT_LIVER] = "Liver" + if(!HAS_TRAIT_FROM(humantarget, TRAIT_NOHUNGER, SPECIES_TRAIT) && !isnull(humantarget.dna.species.mutantstomach) && !humantarget.get_organ_slot(ORGAN_SLOT_STOMACH)) + missing_organs[ORGAN_SLOT_STOMACH] ="Stomach" + if(!isnull(humantarget.dna.species.mutanttongue) && !humantarget.get_organ_slot(ORGAN_SLOT_TONGUE)) + missing_organs[ORGAN_SLOT_TONGUE] = "Tongue" + if(!isnull(humantarget.dna.species.mutantears) && !humantarget.get_organ_slot(ORGAN_SLOT_EARS)) + missing_organs[ORGAN_SLOT_EARS] = "Ears" + if(!isnull(humantarget.dna.species.mutantears) && !humantarget.get_organ_slot(ORGAN_SLOT_EYES)) + missing_organs[ORGAN_SLOT_EYES] = "Eyes" + + // Follow same order as in the organ_process_order so it's consistent across all humans + for(var/sorted_slot in GLOB.organ_process_order) + var/obj/item/organ/organ = humantarget.get_organ_slot(sorted_slot) + if(isnull(organ)) + if(missing_organs[sorted_slot]) render = TRUE - toReport += "\ - [advanced ? "" : ""]\ - " - - var/datum/species/the_dudes_species = humantarget.dna.species - var/missing_organs = list() - if(!humantarget.get_organ_slot(ORGAN_SLOT_BRAIN)) - missing_organs += "brain" - if(!HAS_TRAIT(humantarget, TRAIT_NOBLOOD) && !humantarget.get_organ_slot(ORGAN_SLOT_HEART)) - missing_organs += "heart" - if(!(TRAIT_NOBREATH in the_dudes_species.inherent_traits) && !humantarget.get_organ_slot(ORGAN_SLOT_LUNGS)) - missing_organs += "lungs" - if(!(TRAIT_NOMETABOLISM in the_dudes_species.inherent_traits) && !humantarget.get_organ_slot(ORGAN_SLOT_LIVER)) - missing_organs += "liver" - if(the_dudes_species.mutantstomach && !humantarget.get_organ_slot(ORGAN_SLOT_STOMACH)) - missing_organs += "stomach" - if(the_dudes_species.mutanttongue && !humantarget.get_organ_slot(ORGAN_SLOT_TONGUE)) - missing_organs += "tongue" - if(!humantarget.get_organ_slot(ORGAN_SLOT_EARS)) - missing_organs += "ears" - if(!humantarget.get_organ_slot(ORGAN_SLOT_EYES)) - missing_organs += "eyes" - - if(length(missing_organs)) + toReport += "\ + [advanced ? "" : ""]\ + " + continue + if(mode != SCANNER_VERBOSE && !organ.show_on_condensed_scans()) + continue + var/status = organ.get_status_text(advanced, tochat) + var/appendix = organ.get_status_appendix(advanced, tochat) + if(status || appendix) + status ||= "OK" // otherwise flawless organs have no status reported by default render = TRUE - for(var/organ in missing_organs) - toReport += "\ - [advanced ? "" : ""]\ - " - - if(render) - render_list += toReport + "
Organ:DmgStatus
[organ.name]:[CEILING(organ.damage,1)][status]
[missing_organs[sorted_slot]]:-Missing
[organ]:["-"]["Missing"]
" // tables do not need extra linebreak + toReport += "\ + [capitalize(organ.name)]:\ + [advanced ? "[organ.damage > 0 ? ceil(organ.damage) : "0"]" : ""]\ + [status]\ + " + if(appendix) + toReport += "↳ [appendix]" + + if(render) + render_list += "
" + render_list += toReport + "
" // tables do not need extra linebreak //Genetic stability if(advanced && humantarget.has_dna()) From c34611165be0a5ef1b66def3550ff12111f098b1 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 13 Sep 2024 12:17:18 -0700 Subject: [PATCH 038/158] nothing wrong here --- code/__DEFINES/atmospherics/atmos_core.dm | 14 +- .../atmospherics/atmos_mob_interaction.dm | 129 ++++--- .../signals/signals_mob/signals_mob_carbon.dm | 6 +- .../signals/signals_mob/signals_mob_living.dm | 8 + code/__DEFINES/mobs.dm | 43 +-- .../traits/monkestation/declarations.dm | 2 + code/__HELPERS/mobs.dm | 14 - code/_onclick/hud/alert.dm | 57 ++- code/datums/components/food/edible.dm | 2 +- code/datums/components/rot.dm | 21 +- .../datums/diseases/advance/symptoms/fever.dm | 12 +- .../elements/basic_body_temp_sensitive.dm | 71 ---- code/datums/martial/krav_maga.dm | 4 - .../mood_events/generic_negative_events.dm | 24 +- code/datums/mutations/hulk.dm | 4 + .../status_effects/_status_effect_helpers.dm | 2 +- code/datums/status_effects/buffs.dm | 8 +- .../status_effects/debuffs/fire_stacks.dm | 30 -- code/datums/status_effects/gas.dm | 4 +- code/datums/status_effects/stacking_effect.dm | 64 ++-- code/datums/voice_of_god_command.dm | 4 +- .../datums/weather/weather_types/ash_storm.dm | 2 +- .../weather/weather_types/void_storm.dm | 2 +- code/datums/wounds/pierce.dm | 2 +- .../anomalies/anomalies_pyroclastic.dm | 3 +- code/game/objects/items.dm | 10 +- code/game/objects/items/cigs_lighters.dm | 6 +- .../items/devices/scanners/health_analyzer.dm | 21 +- .../objects/items/grenades/syndieminibomb.dm | 4 +- code/game/objects/items/pillow.dm | 2 +- code/game/objects/items/religion.dm | 8 +- code/game/objects/items/storage/medkit.dm | 2 +- code/game/objects/structures/shower.dm | 18 +- code/game/objects/structures/traps.dm | 2 +- code/game/turfs/open/_open.dm | 12 +- .../changeling/powers/mutations.dm | 4 +- .../changeling/powers/void_adaption.dm | 4 +- code/modules/antagonists/cult/cult_items.dm | 8 +- .../sacrifice_knowledge/sacrifice_buff.dm | 20 +- .../heretic/status_effects/debuffs.dm | 6 +- code/modules/assembly/igniter.dm | 4 +- .../air_alarm/air_alarm_thresholds.dm | 8 +- .../gas_recipe_machines/crystallizer_items.dm | 1 - .../components/unary_devices/cryo.dm | 7 +- .../machinery/pipes/heat_exchange/he_pipes.dm | 2 +- .../awaymissions/mission_code/snowdin.dm | 2 +- code/modules/cargo/gondolapod.dm | 4 +- code/modules/clothing/gloves/bone.dm | 2 +- code/modules/clothing/gloves/botany.dm | 4 +- code/modules/clothing/gloves/color.dm | 8 +- code/modules/clothing/gloves/combat.dm | 4 +- code/modules/clothing/gloves/insulated.dm | 4 +- code/modules/clothing/gloves/plasmaman.dm | 4 +- code/modules/clothing/gloves/special.dm | 8 +- code/modules/clothing/gloves/tacklers.dm | 6 +- code/modules/clothing/head/hardhat.dm | 16 +- code/modules/clothing/head/hat.dm | 4 +- code/modules/clothing/head/helmet.dm | 22 +- code/modules/clothing/head/moth.dm | 2 +- code/modules/clothing/shoes/boots.dm | 4 +- code/modules/clothing/shoes/cult.dm | 4 +- code/modules/clothing/shoes/sneakers.dm | 4 +- .../clothing/spacesuits/_spacesuits.dm | 17 +- code/modules/clothing/suits/armor.dm | 48 +-- code/modules/clothing/suits/costume.dm | 14 +- code/modules/clothing/suits/jacket.dm | 6 +- code/modules/clothing/suits/jobs.dm | 8 +- code/modules/clothing/suits/moth.dm | 2 +- code/modules/clothing/suits/utility.dm | 20 +- code/modules/clothing/suits/wintercoats.dm | 4 +- code/modules/clothing/under/costume.dm | 2 +- .../clothing/under/jobs/civilian/curator.dm | 4 +- code/modules/clothing/under/miscellaneous.dm | 4 +- .../modules/hydroponics/unique_plant_genes.dm | 6 +- .../job_types/chaplain/chaplain_costumes.dm | 4 +- .../chaplain/chaplain_divine_archer.dm | 4 +- .../mapfluff/ruins/icemoonruin_code/wrath.dm | 4 +- .../modules/mining/equipment/explorer_gear.dm | 24 +- .../modules/mining/lavaland/megafauna_loot.dm | 8 +- code/modules/mining/lavaland/tendril_loot.dm | 12 +- code/modules/mob/living/basic/basic.dm | 56 +-- .../mob/living/basic/blob_minions/blob_mob.dm | 4 +- code/modules/mob/living/basic/bots/_bots.dm | 4 +- code/modules/mob/living/basic/clown/clown.dm | 4 +- .../basic/cult/constructs/_construct.dm | 4 +- .../living/basic/farm_animals/goat/_goat.dm | 2 +- .../mob/living/basic/farm_animals/rabbit.dm | 4 +- .../basic/guardian/guardian_types/gaseous.dm | 12 +- .../jungle/mega_arachnid/mega_arachnid.dm | 4 +- .../living/basic/jungle/seedling/seedling.dm | 4 +- .../living/basic/jungle/venus_human_trap.dm | 2 +- .../basic/lavaland/hivelord/hivelord.dm | 4 +- .../basic/lavaland/legion/legion_brood.dm | 4 +- .../mob/living/basic/lavaland/mining.dm | 4 +- .../mob/living/basic/minebots/minebot.dm | 2 +- .../mob/living/basic/pets/dog/corgi.dm | 4 +- .../mob/living/basic/space_fauna/ant.dm | 4 +- .../living/basic/space_fauna/bear/_bear.dm | 4 +- .../mob/living/basic/space_fauna/carp/carp.dm | 4 +- .../living/basic/space_fauna/demon/demon.dm | 4 +- .../basic/space_fauna/demon/demon_subtypes.dm | 2 +- .../basic/space_fauna/eyeball/_eyeball.dm | 4 +- .../living/basic/space_fauna/garden_gnome.dm | 4 +- .../basic/space_fauna/hivebot/_hivebot.dm | 2 +- .../living/basic/space_fauna/killer_tomato.dm | 4 +- .../living/basic/space_fauna/lightgeist.dm | 4 +- .../space_fauna/meteor_heart/meteor_heart.dm | 4 +- .../mob/living/basic/space_fauna/morph.dm | 2 +- .../basic/space_fauna/revenant/_revenant.dm | 4 +- .../basic/space_fauna/robot_customer.dm | 4 +- .../spider/giant_spider/giant_spiders.dm | 12 +- .../basic/space_fauna/supermatter_spider.dm | 4 +- .../wumborian_fugu/wumborian_fugu.dm | 4 +- code/modules/mob/living/basic/tree.dm | 4 +- .../mob/living/basic/trooper/syndicate.dm | 16 +- .../mob/living/basic/vermin/cockroach.dm | 4 +- .../modules/mob/living/basic/vermin/lizard.dm | 4 +- .../mob/living/carbon/alien/adult/life.dm | 18 - code/modules/mob/living/carbon/alien/alien.dm | 22 +- .../mob/living/carbon/alien/alien_defense.dm | 3 - .../mob/living/carbon/carbon_defense.dm | 8 +- .../mob/living/carbon/carbon_defines.dm | 5 - .../mob/living/carbon/carbon_update_icons.dm | 8 +- .../mob/living/carbon/human/_species.dm | 345 ++---------------- code/modules/mob/living/carbon/human/death.dm | 2 +- .../mob/living/carbon/human/examine.dm | 4 +- code/modules/mob/living/carbon/human/human.dm | 5 - .../mob/living/carbon/human/human_defense.dm | 22 +- .../mob/living/carbon/human/human_defines.dm | 9 +- code/modules/mob/living/carbon/human/life.dm | 208 +---------- .../human/species_types/lizardpeople.dm | 11 +- .../carbon/human/species_types/plasmamen.dm | 17 +- .../carbon/human/species_types/zombies.dm | 4 - code/modules/mob/living/carbon/life.dm | 156 +++----- code/modules/mob/living/life.dm | 55 ++- code/modules/mob/living/living.dm | 93 ++--- code/modules/mob/living/living_defines.dm | 30 +- .../mob/living/simple_animal/bot/bot.dm | 4 +- .../mob/living/simple_animal/friendly/cat.dm | 8 +- .../living/simple_animal/friendly/gondola.dm | 4 +- .../mob/living/simple_animal/hostile/alien.dm | 2 +- .../simple_animal/hostile/dark_wizard.dm | 4 +- .../hostile/jungle/_jungle_mobs.dm | 4 +- .../hostile/megafauna/_megafauna.dm | 4 +- .../mob/living/simple_animal/hostile/mimic.dm | 2 +- .../hostile/mining_mobs/mining_mobs.dm | 4 +- .../mob/living/simple_animal/hostile/ooze.dm | 6 +- .../living/simple_animal/hostile/pirate.dm | 4 +- .../living/simple_animal/hostile/zombie.dm | 2 +- .../mob/living/simple_animal/simple_animal.dm | 37 +- code/modules/mob/mob_defines.dm | 5 - code/modules/mob/status_procs.dm | 5 - code/modules/mod/mod_activation.dm | 8 +- code/modules/mod/mod_clothes.dm | 16 +- code/modules/mod/mod_control.dm | 2 - code/modules/mod/modules/modules_general.dm | 8 +- code/modules/power/lighting/light.dm | 2 +- .../projectile/bullets/revolver.dm | 6 +- .../projectiles/projectile/energy/thermal.dm | 16 +- .../projectile/special/temperature.dm | 32 +- .../reagents/cat2_medicine_reagents.dm | 26 +- .../reagents/drinks/alcohol_reagents.dm | 20 +- .../reagents/drinks/drink_reagents.dm | 54 +-- .../chemistry/reagents/food_reagents.dm | 57 ++- .../impure_medicine_reagents.dm | 52 ++- .../chemistry/reagents/medicine_reagents.dm | 21 +- .../reagents/pyrotechnic_reagents.dm | 10 +- .../chemistry/reagents/toxin_reagents.dm | 5 +- code/modules/religion/pyre_rites.dm | 1 - .../xenobiology/crossbreeding/_potions.dm | 1 - .../crossbreeding/_status_effects.dm | 38 +- .../xenobiology/crossbreeding/burning.dm | 7 +- .../xenobiology/crossbreeding/regenerative.dm | 1 - .../research/xenobiology/xenobiology.dm | 1 - .../spell_types/pointed/abyssal_gaze.dm | 5 +- code/modules/surgery/bodyparts/_bodyparts.dm | 4 + .../species_parts/lizard_bodyparts.dm | 1 + .../bodyparts/species_parts/misc_bodyparts.dm | 1 + .../organs/external/_external_organs.dm | 2 +- .../organs/external/wings/moth_wings.dm | 2 +- code/modules/surgery/organs/lungs.dm | 112 +++--- .../surgery/organs/stomach/_stomach.dm | 39 +- .../organs/stomach/stomach_ethereal.dm | 12 + .../mecha/equipment/tools/medical_tools.dm | 9 +- .../borers/code/mobs/cortical_borer.dm | 2 +- .../antagonists/clock_cult/items/clothing.dm | 4 +- .../clock_cult/mobs/clockwork_marauder.dm | 2 +- .../bloodsucker/bloodsucker_datum.dm | 2 +- .../bloodsucker/bloodsucker_overwrites.dm | 5 - .../modules/bloodsuckers/clans/venture.dm | 2 +- .../modules/blueshift/clothing/kahraman.dm | 8 +- .../modules/blueshift/clothing/nova_coats.dm | 12 +- .../modules/blueshift/clothing/nova_cowboy.dm | 2 +- .../modules/blueshift/clothing/nova_field.dm | 12 +- .../modules/blueshift/clothing/nova_heads.dm | 6 +- .../blueshift/clothing/nova_jackets.dm | 6 +- .../modules/blueshift/clothing/nova_misc.dm | 20 +- .../modules/blueshift/clothing/nova_neck.dm | 4 +- .../blueshift/clothing/nova_security.dm | 16 +- .../blueshift/clothing/nova_syndicate.dm | 4 +- .../code/modules/blueshift/mobs/misc_pets.dm | 4 +- .../modules/blueshift/reagents/deforest.dm | 4 +- .../can_spessmen_feel_pain/pain/_base.dm | 8 +- .../pain/pain_assistance_tools.dm | 23 +- .../pain/reagents/painkillers.dm | 8 +- .../can_spessmen_feel_pain/pain/shock.dm | 8 +- .../pain/status_effects/temp_pack.dm | 2 +- .../spacesuits/hardsuits/engineering.dm | 4 +- .../code/modules/clothing/suits/costume.dm | 8 +- .../modules/clothing/~donator/clothing.dm | 8 +- .../augments/arm_augments/unsorted.dm | 12 +- .../modules/donator/code/item/clothing.dm | 20 +- .../modules/ocean_content/mobs/fish_base.dm | 4 +- .../modules/ranching/chickens/tier2/cluwne.dm | 2 +- .../modules/ranching/chickens/tier2/snowy.dm | 4 +- .../nanites/nanite_programs/healing.dm | 4 +- .../nanites/nanite_programs/utility.dm | 4 +- .../modules/slimecore/mobs/_base_slime.dm | 6 +- .../code/modules/smithing/items/clothing.dm | 12 +- .../modules/temperature_overhaul/exposure.dm | 64 ++++ .../temperature_overhaul/homeostasis_level.dm | 135 +++++++ .../temperature_overhaul/living_procs.dm | 164 +++++++++ .../temperature_overhaul/temperature_proc.dm | 134 +++++++ .../virology/disease/symtoms/stage1.dm | 8 +- .../virology/disease/symtoms/stage2.dm | 8 +- tgstation.dme | 6 +- 226 files changed, 1739 insertions(+), 1913 deletions(-) delete mode 100644 code/datums/elements/basic_body_temp_sensitive.dm delete mode 100644 code/modules/mob/living/carbon/alien/adult/life.dm create mode 100644 monkestation/code/modules/temperature_overhaul/exposure.dm create mode 100644 monkestation/code/modules/temperature_overhaul/homeostasis_level.dm create mode 100644 monkestation/code/modules/temperature_overhaul/living_procs.dm create mode 100644 monkestation/code/modules/temperature_overhaul/temperature_proc.dm diff --git a/code/__DEFINES/atmospherics/atmos_core.dm b/code/__DEFINES/atmospherics/atmos_core.dm index 383e34f5c831..2544e9c95950 100644 --- a/code/__DEFINES/atmospherics/atmos_core.dm +++ b/code/__DEFINES/atmospherics/atmos_core.dm @@ -29,13 +29,13 @@ /// kPa #define ONE_ATMOSPHERE 101.325 /// -270.3degC -#define TCMB 2.7 +#define TCMB CELCIUS_TO_KELVIN(-270.3 CELCIUS) /// 0degC -#define T0C 273.15 +#define T0C CELCIUS_TO_KELVIN(0 CELCIUS) /// 20degC -#define T20C 293.15 +#define T20C CELCIUS_TO_KELVIN(20 CELCIUS) /// -14C - Temperature used for kitchen cold room, medical freezer, etc. -#define COLD_ROOM_TEMP 259.15 +#define COLD_ROOM_TEMP CELCIUS_TO_KELVIN(-14 CELCIUS) /** *I feel the need to document what happens here. Basically this is used @@ -128,11 +128,11 @@ //FIRE ///Minimum temperature for fire to move to the next turf (150 °C or 433 K) -#define FIRE_MINIMUM_TEMPERATURE_TO_SPREAD (150+T0C) +#define FIRE_MINIMUM_TEMPERATURE_TO_SPREAD CELCIUS_TO_KELVIN(150 CELCIUS) ///Minimum temperature for fire to exist on a turf (100 °C or 373 K) -#define FIRE_MINIMUM_TEMPERATURE_TO_EXIST (100+T0C) +#define FIRE_MINIMUM_TEMPERATURE_TO_EXIST CELCIUS_TO_KELVIN(100 CELCIUS) ///Minimum temperature for items on fire -#define BURNING_ITEM_MINIMUM_TEMPERATURE (150+T0C) +#define BURNING_ITEM_MINIMUM_TEMPERATURE CELCIUS_TO_KELVIN(150 CELCIUS) ///Multiplier for the temperature shared to other turfs #define FIRE_SPREAD_RADIOSITY_SCALE 0.85 ///Helper for small fires to grow diff --git a/code/__DEFINES/atmospherics/atmos_mob_interaction.dm b/code/__DEFINES/atmospherics/atmos_mob_interaction.dm index 26f13bc0522c..9418688d6d56 100644 --- a/code/__DEFINES/atmospherics/atmos_mob_interaction.dm +++ b/code/__DEFINES/atmospherics/atmos_mob_interaction.dm @@ -41,51 +41,80 @@ /// This is used in handle_temperature_damage() for humans, and in reagents that affect body temperature. Temperature damage is multiplied by this amount. #define TEMPERATURE_DAMAGE_COEFFICIENT 1.5 +/// Default maximum body temperature mobs can exist in before taking damage +#define NPC_DEFAULT_MAX_TEMP CELCIUS_TO_KELVIN(76.85 CELCIUS)// 350 KELVIN +/// Default minimum body temperature mobs can exist in before taking damage +#define NPC_DEFAULT_MIN_TEMP CELCIUS_TO_KELVIN(-23.15 CELCIUS)// 250 KELVIN + +// Helpers for temperature conversion +#define FAHRENHEIT_TO_KELVIN(x) (((x) + 459.67) * 5 / 9) +#define KELVIN_TO_FAHRENHEIT(x) (((x) * 9 / 5) - 459.67) +#define CELCIUS_TO_KELVIN(x) ((x) + 273.15) +#define KELVIN_TO_CELCIUS(x) ((x) - 273.15) +#define CELCIUS_TO_FAHRENHEIT(x) (((x) * 9 / 5) + 32) +#define FAHRENHEIT_TO_CELSIUS(x) (((x) - 32) * 5 / 9) + +// These defines do nothing but can be used to make the code more readable by indicating temperature units +#define CELCIUS * 1 +#define FAHRENHEIT * 1 +#define KELVIN * 1 + +/// Max change in temperature during natural body temperature stabilization +#define BODYTEMP_COOLING_MAX -30 KELVIN +/// Max change in temperature during natural body temperature stabilization +#define BODYTEMP_HEATING_MAX 30 KELVIN + +// These defines are DEFAULTS for most mobs +// Mobs can override these to have whatever they want +// That means in a lot of situations (namely mob code) you should not directly use these, +// and instead use the relevant mob vars UNLESS you intentionally are using defaults over reality + /// The natural temperature for a body -#define BODYTEMP_NORMAL 310.15 -/// This is the divisor which handles how much of the temperature difference between the current body temperature and 310.15K (optimal temperature) humans auto-regenerate each tick. The higher the number, the slower the recovery. This is applied each tick, so long as the mob is alive. -#define BODYTEMP_AUTORECOVERY_DIVISOR 28 -/// Minimum amount of kelvin moved toward 310K per tick. So long as abs(310.15 - bodytemp) is more than 50. -#define BODYTEMP_AUTORECOVERY_MINIMUM 3 -///Similar to the BODYTEMP_AUTORECOVERY_DIVISOR, but this is the divisor which is applied at the stage that follows autorecovery. This is the divisor which comes into play when the human's loc temperature is lower than their body temperature. Make it lower to lose bodytemp faster. -#define BODYTEMP_COLD_DIVISOR 15 -/// Similar to the BODYTEMP_AUTORECOVERY_DIVISOR, but this is the divisor which is applied at the stage that follows autorecovery. This is the divisor which comes into play when the human's loc temperature is higher than their body temperature. Make it lower to gain bodytemp faster. -#define BODYTEMP_HEAT_DIVISOR 15 -/// The maximum number of degrees that your body can cool in 1 tick, due to the environment, when in a cold area. -#define BODYTEMP_COOLING_MAX -30 -/// The maximum number of degrees that your body can heat up in 1 tick, due to the environment, when in a hot area. -#define BODYTEMP_HEATING_MAX 30 +#define BODYTEMP_NORMAL CELCIUS_TO_KELVIN(37 CELCIUS) +/// Beyond this point a mob is considered hyperthermic +#define HYPERTHERMIA (BODYTEMP_NORMAL + 10 CELCIUS) +/// Beyond this point a mob is considered hypothermic +#define HYPOTHERMIA (BODYTEMP_NORMAL - 10 CELCIUS) + /// The body temperature limit the human body can take before it starts taking damage from heat. /// This also affects how fast the body normalises it's temperature when hot. -/// 340k is about 66c, and rather high for a human. -#define BODYTEMP_HEAT_DAMAGE_LIMIT (BODYTEMP_NORMAL + 30) +#define BODYTEMP_HEAT_DAMAGE_LIMIT CELCIUS_TO_KELVIN(65 CELCIUS) /// The body temperature limit the human body can take before it starts taking damage from cold. /// This also affects how fast the body normalises it's temperature when cold. -/// 270k is about -3c, that is below freezing and would hurt over time. -#define BODYTEMP_COLD_DAMAGE_LIMIT (BODYTEMP_NORMAL - 40) -/// The body temperature limit the human body can take before it will take wound damage. -#define BODYTEMP_HEAT_WOUND_LIMIT (BODYTEMP_NORMAL + 90) // 400.5 k -/// The modifier on cold damage limit hulks get ontop of their regular limit -#define BODYTEMP_HULK_COLD_DAMAGE_LIMIT_MODIFIER 25 -/// The modifier on cold damage hulks get. -#define HULK_COLD_DAMAGE_MOD 2 +#define BODYTEMP_COLD_DAMAGE_LIMIT CELCIUS_TO_KELVIN(-0.5 CELCIUS) + +/// A temperature limit which is above the maximum lavaland temperature +#define BODYTEMP_HEAT_LAVALAND_SAFE (LAVALAND_MAX_TEMPERATURE + 5 KELVIN) +/// A temperature limit which is above the minimum icebox temperature +#define BODYTEMP_COLD_ICEBOX_SAFE (ICEBOX_MIN_TEMPERATURE - 5 KELVIN) -// Body temperature warning icons /// The temperature the red icon is displayed. -#define BODYTEMP_HEAT_WARNING_3 (BODYTEMP_HEAT_DAMAGE_LIMIT + 360) //+700k +#define BODYTEMP_HEAT_WARNING_3 (BODYTEMP_NORMAL + 23 CELCIUS) // CELCIUS_TO_KELVIN(60 CELCIUS) /// The temperature the orange icon is displayed. -#define BODYTEMP_HEAT_WARNING_2 (BODYTEMP_HEAT_DAMAGE_LIMIT + 120) //460K +#define BODYTEMP_HEAT_WARNING_2 (BODYTEMP_NORMAL + 13 CELCIUS) // CELCIUS_TO_KELVIN(50 CELCIUS) /// The temperature the yellow icon is displayed. -#define BODYTEMP_HEAT_WARNING_1 (BODYTEMP_HEAT_DAMAGE_LIMIT) //340K +#define BODYTEMP_HEAT_WARNING_1 (BODYTEMP_NORMAL + 3 CELCIUS) // CELCIUS_TO_KELVIN(40 CELCIUS) /// The temperature the light green icon is displayed. -#define BODYTEMP_COLD_WARNING_1 (BODYTEMP_COLD_DAMAGE_LIMIT) //270k +#define BODYTEMP_COLD_WARNING_1 (BODYTEMP_NORMAL - 7 CELCIUS) // CELCIUS_TO_KELVIN(30 CELCIUS) /// The temperature the cyan icon is displayed. -#define BODYTEMP_COLD_WARNING_2 (BODYTEMP_COLD_DAMAGE_LIMIT - 70) //200k +#define BODYTEMP_COLD_WARNING_2 (BODYTEMP_NORMAL - 17 CELCIUS) // CELCIUS_TO_KELVIN(20 CELCIUS) /// The temperature the blue icon is displayed. -#define BODYTEMP_COLD_WARNING_3 (BODYTEMP_COLD_DAMAGE_LIMIT - 150) //120k +#define BODYTEMP_COLD_WARNING_3 (BODYTEMP_NORMAL - 27 CELCIUS) // CELCIUS_TO_KELVIN(10 CELCIUS) -/// Beyond this temperature, being on fire will increase body temperature by less and less -#define BODYTEMP_FIRE_TEMP_SOFTCAP 1200 +// Ok defaults over + +/// Beyond this body temperature, being on fire will increase body temperature by less and less +#define BODYTEMP_FIRE_TEMP_SOFTCAP 600 KELVIN + +/// A warm drink will increase body temperature by this much +#define WARM_DRINK 0.5 KELVIN +/// A cold drink will decrease body temperature by this much +#define COLD_DRINK -0.5 KELVIN + +/// The modifier on cold damage limit hulks get ontop of their regular limit +#define BODYTEMP_HULK_COLD_DAMAGE_LIMIT_MODIFIER 25 KELVIN +/// The modifier on cold damage hulks get. +#define HULK_COLD_DAMAGE_MOD 2 /// The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE #define PRESSURE_DAMAGE_COEFFICIENT 2 @@ -100,41 +129,41 @@ //CLOTHES /// what min_cold_protection_temperature is set to for space-helmet quality headwear. MUST NOT BE 0. -#define SPACE_HELM_MIN_TEMP_PROTECT 2.0 +#define SPACE_HELM_MIN_TEMP_PROTECT 2.0 KELVIN /// Thermal insulation works both ways /Malkevin -#define SPACE_HELM_MAX_TEMP_PROTECT 1500 +#define SPACE_HELM_MAX_TEMP_PROTECT 1500 KELVIN /// what min_cold_protection_temperature is set to for space-suit quality jumpsuits or suits. MUST NOT BE 0. -#define SPACE_SUIT_MIN_TEMP_PROTECT 2.0 +#define SPACE_SUIT_MIN_TEMP_PROTECT 2.0 KELVIN /// The min cold protection of a space suit without the heater active -#define SPACE_SUIT_MIN_TEMP_PROTECT_OFF 72 -#define SPACE_SUIT_MAX_TEMP_PROTECT 1500 +#define SPACE_SUIT_MIN_TEMP_PROTECT_OFF 72 KELVIN +#define SPACE_SUIT_MAX_TEMP_PROTECT 1500 KELVIN /// Cold protection for firesuits -#define FIRE_SUIT_MIN_TEMP_PROTECT 60 +#define FIRE_SUIT_MIN_TEMP_PROTECT 60 KELVIN /// what max_heat_protection_temperature is set to for firesuit quality suits. MUST NOT BE 0. -#define FIRE_SUIT_MAX_TEMP_PROTECT 30000 +#define FIRE_SUIT_MAX_TEMP_PROTECT 30000 KELVIN /// Cold protection for fire helmets -#define FIRE_HELM_MIN_TEMP_PROTECT 60 +#define FIRE_HELM_MIN_TEMP_PROTECT 60 KELVIN /// for fire helmet quality items (red and white hardhats) -#define FIRE_HELM_MAX_TEMP_PROTECT 30000 +#define FIRE_HELM_MAX_TEMP_PROTECT 30000 KELVIN /// what max_heat_protection_temperature is set to for firesuit quality suits and helmets. MUST NOT BE 0. -#define FIRE_IMMUNITY_MAX_TEMP_PROTECT 35000 +#define FIRE_IMMUNITY_MAX_TEMP_PROTECT 35000 KELVIN /// For normal helmets -#define HELMET_MIN_TEMP_PROTECT 160 +#define HELMET_MIN_TEMP_PROTECT 160 KELVIN /// For normal helmets -#define HELMET_MAX_TEMP_PROTECT 600 +#define HELMET_MAX_TEMP_PROTECT 600 KELVIN /// For armor -#define ARMOR_MIN_TEMP_PROTECT 160 +#define ARMOR_MIN_TEMP_PROTECT 160 KELVIN /// For armor -#define ARMOR_MAX_TEMP_PROTECT 600 +#define ARMOR_MAX_TEMP_PROTECT 600 KELVIN /// For some gloves (black and) -#define GLOVES_MIN_TEMP_PROTECT 2.0 +#define GLOVES_MIN_TEMP_PROTECT 2.0 KELVIN /// For some gloves -#define GLOVES_MAX_TEMP_PROTECT 1500 +#define GLOVES_MAX_TEMP_PROTECT 1500 KELVIN /// For gloves -#define SHOES_MIN_TEMP_PROTECT 2.0 +#define SHOES_MIN_TEMP_PROTECT 2.0 KELVIN /// For gloves -#define SHOES_MAX_TEMP_PROTECT 1500 +#define SHOES_MAX_TEMP_PROTECT 1500 KELVIN diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm index 11f9d799c408..132cca0816ea 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -125,10 +125,12 @@ #define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" ///Whenever EquipRanked is called, called after job is set #define COMSIG_JOB_RECEIVED "job_received" -///from /mob/living/carbon/human/proc/set_coretemperature(): (oldvalue, newvalue) -#define COMSIG_HUMAN_CORETEMP_CHANGE "human_coretemp_change" ///from /datum/species/handle_fire. Called when the human is set on fire and burning clothes and stuff #define COMSIG_HUMAN_BURNING "human_burning" + /// Return to do no burn damage + #define BURNING_HANDLED (1<<0) + /// Return to skip protection check (ie, cause damage even if wearing fireproof clothing) + #define BURNING_SKIP_PROTECTION (1<<1) ///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity, modifiers) #define COMSIG_HUMAN_EARLY_UNARMED_ATTACK "human_early_unarmed_attack" ///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity, modifiers) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index 00dbeb79632f..4fdb0479fe34 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -221,3 +221,11 @@ #define COMSIG_MOB_LOST_CHAIN_TAIL "living_detached_chain_tail" /// Sent from a 'contract chain' button on a mob chain #define COMSIG_MOB_CHAIN_CONTRACT "living_chain_contracted" + +#define COMSIG_LIVING_BODY_TEMPERATURE_CHANGE "living_body_temperature_change" + +#define COMSIG_LIVING_HOMEOSTASIS "living_homeostasis" + /// Return to do no homeostasis at all + #define HOMEOSTASIS_HANDLED (1<<0) + /// Return to not reduce hunger at all + #define HOMEOSTASIS_NO_HUNGER (1<<1) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index fb0c39de245c..4c8c0010ce4e 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -28,7 +28,7 @@ #define BLOOD_DEFICIENCY_MODIFIER 0.025 /// Temperature at which blood loss and regen stops. [/mob/living/carbon/human/proc/handle_blood] -#define BLOOD_STOP_TEMP 225 +#define BLOOD_STOP_TEMP CELCIUS_TO_KELVIN(-48.15 CELCIUS) //Sizes of mobs, used by mob/living/var/mob_size #define MOB_SIZE_TINY 0 @@ -165,22 +165,13 @@ #define HUMAN_MAX_OXYLOSS 3 #define HUMAN_CRIT_MAX_OXYLOSS (SSMOBS_DT/3) -#define HEAT_DAMAGE_LEVEL_1 1 //Amount of damage applied when your body temperature just passes the 360.15k safety point -#define HEAT_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 400K point -#define HEAT_DAMAGE_LEVEL_3 4 //Amount of damage applied when your body temperature passes the 460K point and you are on fire +/// Damage recieved when past heat damage threshold. +/// Gets multiplied by 2x, 4x, 8x depending on how far past the threshold you are. +#define HEAT_DAMAGE 1 -#define COLD_DAMAGE_LEVEL_1 0.25 //Amount of damage applied when your body temperature just passes the 260.15k safety point -#define COLD_DAMAGE_LEVEL_2 0.75 //Amount of damage applied when your body temperature passes the 200K point -#define COLD_DAMAGE_LEVEL_3 1.5 //Amount of damage applied when your body temperature passes the 120K point - -//Note that gas heat damage is only applied once every FOUR ticks. -#define HEAT_GAS_DAMAGE_LEVEL_1 2 //Amount of damage applied when the current breath's temperature just passes the 360.15k safety point -#define HEAT_GAS_DAMAGE_LEVEL_2 4 //Amount of damage applied when the current breath's temperature passes the 400K point -#define HEAT_GAS_DAMAGE_LEVEL_3 8 //Amount of damage applied when the current breath's temperature passes the 1000K point - -#define COLD_GAS_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when the current breath's temperature just passes the 260.15k safety point -#define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point -#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point +/// Damage recieved when past cold damage threshold. +/// Gets multiplied by 2x, 4x, 8x depending on how far past the threshold you are. +#define COLD_DAMAGE 0.25 //Brain Damage defines #define BRAIN_DAMAGE_MILD 20 @@ -458,8 +449,19 @@ #define POCKET_STRIP_DELAY (4 SECONDS) //time taken to search somebody's pockets #define DOOR_CRUSH_DAMAGE 15 //the amount of damage that airlocks deal when they crush you -#define HUNGER_FACTOR 0.05 //factor at which mob nutrition decreases -#define ETHEREAL_CHARGE_FACTOR 0.8 //factor at which ethereal's charge decreases per second +/// Factor at which mob nutrition decreases +#define HUNGER_FACTOR 0.1 + +// These add up to 1 to roughly (VERY roughly) represent the proportion of hunger used by each system +/// What % of hunger is used by homeostasis +#define HOMEOSTASIS_HUNGER_MULTIPLIER 0.7 +/// What % of hunger is used by passive hunger +#define PASSIVE_HUNGER_MULTIPLIER 0.2 +/// What % of hunger is used by movement +#define MOVEMENT_HUNGER_MULTIPLIER 0.1 + +/// Factor at which ethereal's charge decreases per second +#define ETHEREAL_CHARGE_FACTOR 0.8 /// How much nutrition eating clothes as moth gives and drains #define CLOTHING_NUTRITION_GAIN 15 #define REAGENTS_METABOLISM 0.2 //How many units of reagent are consumed per second, by default. @@ -927,11 +929,6 @@ GLOBAL_LIST_INIT(layers_to_offset, list( #define HEALING_TOUCH_NOT_SELF "healing_touch_not_self" #define HEALING_TOUCH_SELF_ONLY "healing_touch_self_only" -/// Default minimum body temperature mobs can exist in before taking damage -#define NPC_DEFAULT_MIN_TEMP 250 -/// Default maximum body temperature mobs can exist in before taking damage -#define NPC_DEFAULT_MAX_TEMP 350 - // Flags for mobs which can't do certain things while someone is looking at them /// Flag which stops you from moving while observed #define NO_OBSERVED_MOVEMENT (1<<0) diff --git a/code/__DEFINES/traits/monkestation/declarations.dm b/code/__DEFINES/traits/monkestation/declarations.dm index ba88b26a1a04..abfbba8b811e 100644 --- a/code/__DEFINES/traits/monkestation/declarations.dm +++ b/code/__DEFINES/traits/monkestation/declarations.dm @@ -137,5 +137,7 @@ #define TRAIT_ASSISTED_BREATHING "assisted_breathing" /// Stops organs from decaying while dead #define TRAIT_NO_ORGAN_DECAY "no_organ_decay" +/// Mob does not homeostasize body temperature +#define TRAIT_COLD_BLOODED "cold_blooded" // END TRAIT DEFINES diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index cf31c2fa754f..496989a41431 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -633,20 +633,6 @@ GLOBAL_LIST_EMPTY(species_list) . = pick(ais) return . -/** - * Used to get the amount of change between two body temperatures - * - * When passed the difference between two temperatures returns the amount of change to temperature to apply. - * The change rate should be kept at a low value tween 0.16 and 0.02 for optimal results. - * vars: - * * temp_diff (required) The differance between two temperatures - * * change_rate (optional)(Default: 0.06) The rate of range multiplyer - */ -/proc/get_temp_change_amount(temp_diff, change_rate = 0.06) - if(temp_diff < 0) - return -(BODYTEMP_AUTORECOVERY_DIVISOR / 2) * log(1 - (temp_diff * change_rate)) - return (BODYTEMP_AUTORECOVERY_DIVISOR / 2) * log(1 + (temp_diff * change_rate)) - #define ISADVANCEDTOOLUSER(mob) (HAS_TRAIT(mob, TRAIT_ADVANCEDTOOLUSER) && !HAS_TRAIT(mob, TRAIT_DISCOORDINATED_TOOL_USER)) /// Gets the client of the mob, allowing for mocking of the client. diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index cedbeb28f2d7..dfaf007d661c 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -57,8 +57,7 @@ thealert.icon_state = "template" // We'll set the icon to the client's ui pref in reorganize_alerts() thealert.master = new_master else - thealert.icon_state = "[initial(thealert.icon_state)][severity]" - thealert.severity = severity + thealert.set_severity(severity) alerts[category] = thealert if(client && hud_used) @@ -120,6 +119,15 @@ /atom/movable/screen/alert/MouseExited() closeToolTip(usr) +/atom/movable/screen/alert/proc/set_severity(new_val) + if(severity == new_val) + return + severity = new_val + update_appearance() + +/atom/movable/screen/alert/update_icon_state() + . = ..() + icon_state = "[base_icon_state || initial(icon_state)][severity]" //Gas alerts // Gas alerts are continuously thrown/cleared by: @@ -213,15 +221,52 @@ icon_state = "gross3" /atom/movable/screen/alert/hot - name = "Too Hot" - desc = "You're flaming hot! Get somewhere cooler and take off any insulating clothing like a fire suit." + name = "Hot" icon_state = "hot" +/atom/movable/screen/alert/hot/update_name(updates) + . = ..() + switch(severity) + if(1) + name = "Warm" + if(2) + name = "Hot" + if(3) + name = "Flaming Hot" + +/atom/movable/screen/alert/hot/update_desc(updates) + . = ..() + switch(severity) + if(1) + desc = "It's pretty warm around here. You might not want to stick around for long, but it won't hurt you unless it gets hotter." + if(2) + desc = "You're getting pretty hot. You might want to find somewhere cooler soon, or take off any insulating clothing like a fire suit." + if(3) + desc = "You're flaming hot! Get somewhere cooler and take off any insulating clothing like a fire suit." + /atom/movable/screen/alert/cold - name = "Too Cold" - desc = "You're freezing cold! Get somewhere warmer and take off any insulating clothing like a space suit." + name = "Cold" icon_state = "cold" +/atom/movable/screen/alert/cold/update_name(updates) + . = ..() + switch(severity) + if(1) + name = "Chilly" + if(2) + name = "Cold" + if(3) + name = "Freezing" + +/atom/movable/screen/alert/cold/update_desc(updates) + . = ..() + switch(severity) + if(1) + desc = "You feel pretty chilly. You might not want to stick around for long, but it won't hurt you unless it gets colder." + if(2) + desc = "You're getting pretty cold. You might want to find somewhere warmer soon, or put on some insulating clothing like a space suit or winter coat." + if(3) + desc = "You're freezing cold! Get somewhere warmer and put on some insulating clothing like a space suit or winter coat." /atom/movable/screen/alert/lowpressure name = "Low Pressure" desc = "The air around you is hazardously thin. A space suit would protect you." diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index 33de3942ec3a..e2d21840182f 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -452,7 +452,7 @@ Behavior that's still missing from this component that original food items had t stack_trace("[eater] failed to bite [owner], because [owner] had no reagents.") return FALSE if(eater.satiety > -200) - eater.satiety -= junkiness + eater.adjust_satiety(-junkiness) playsound(eater.loc,'sound/items/eatfood.ogg', rand(10,50), TRUE) if(!owner.reagents.total_volume) return diff --git a/code/datums/components/rot.dm b/code/datums/components/rot.dm index 4dcb69a2e9eb..7898d252b5ca 100644 --- a/code/datums/components/rot.dm +++ b/code/datums/components/rot.dm @@ -42,20 +42,25 @@ AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections) RegisterSignal(parent, COMSIG_MOVABLE_BUMP, PROC_REF(rot_react)) if(isliving(parent)) + var/mob/living/living_parent = parent RegisterSignal(parent, COMSIG_LIVING_REVIVE, PROC_REF(react_to_revive)) //mobs stop this when they come to life RegisterSignal(parent, COMSIG_LIVING_GET_PULLED, PROC_REF(rot_react_touch)) + + RegisterSignal(parent, COMSIG_LIVING_BODY_TEMPERATURE_CHANGE, PROC_REF(check_for_temperature)) + check_for_temperature(parent, living_parent.bodytemperature, living_parent.bodytemperature) if(iscarbon(parent)) var/mob/living/carbon/carbon_parent = parent - RegisterSignals(carbon_parent.reagents, list(COMSIG_REAGENTS_ADD_REAGENT, + RegisterSignals(carbon_parent.reagents, list( + COMSIG_REAGENTS_ADD_REAGENT, + COMSIG_REAGENTS_DEL_REAGENT, COMSIG_REAGENTS_REM_REAGENT, - COMSIG_REAGENTS_DEL_REAGENT), PROC_REF(check_reagent)) - RegisterSignals(parent, list(SIGNAL_ADDTRAIT(TRAIT_HUSK), SIGNAL_REMOVETRAIT(TRAIT_HUSK)), PROC_REF(check_husk_trait)) + ), PROC_REF(check_reagent)) check_reagent(carbon_parent.reagents, null) - check_husk_trait(null) - if(ishuman(parent)) - var/mob/living/carbon/human/human_parent = parent - RegisterSignal(parent, COMSIG_HUMAN_CORETEMP_CHANGE, PROC_REF(check_for_temperature)) - check_for_temperature(null, 0, human_parent.coretemperature) + + RegisterSignals(parent, list( + SIGNAL_ADDTRAIT(TRAIT_HUSK), + SIGNAL_REMOVETRAIT(TRAIT_HUSK), + ), PROC_REF(check_husk_trait)) start_up(NONE) //If nothing's blocking it, start diff --git a/code/datums/diseases/advance/symptoms/fever.dm b/code/datums/diseases/advance/symptoms/fever.dm index 7fd6bf70d494..77e3b3121a88 100644 --- a/code/datums/diseases/advance/symptoms/fever.dm +++ b/code/datums/diseases/advance/symptoms/fever.dm @@ -26,6 +26,7 @@ "Resistance 5" = "Increases fever intensity, fever can overheat and harm the host.", "Resistance 10" = "Further increases fever intensity.", ) + var/heat_cap = 6 KELVIN /datum/symptom/fever/Start(datum/disease/advance/A) . = ..() @@ -57,12 +58,9 @@ * * datum/disease/advance/A The disease applying the symptom */ /datum/symptom/fever/proc/set_body_temp(mob/living/M, datum/disease/advance/A) - if(unsafe) // when unsafe the fever can cause heat damage - M.add_body_temperature_change(FEVER_CHANGE, 6 * power * A.stage) - else - // Get the max amount of change allowed before going over heat damage limit, then cap the maximum allowed temperature change from a safe fever to 5 under the heat damage limit - var/change_limit = max(M.get_body_temp_heat_damage_limit() - 5 - M.get_body_temp_normal(apply_change=FALSE), 0) - M.add_body_temperature_change(FEVER_CHANGE, min(6 * power * A.stage, change_limit)) + var/mob/living/affected = M + var/new_level = affected.standard_body_temperature + (heat_cap * power * A.stage) + affected.add_homeostasis_level(type, new_level, 0.25 KELVIN * power) /// Update the body temp change based on the new stage /datum/symptom/fever/on_stage_change(datum/disease/advance/A) @@ -74,6 +72,6 @@ /datum/symptom/fever/End(datum/disease/advance/A) var/mob/living/carbon/M = A.affected_mob if(M) - M.remove_body_temperature_change(FEVER_CHANGE) + M.remove_homeostasis_level(type) #undef FEVER_CHANGE diff --git a/code/datums/elements/basic_body_temp_sensitive.dm b/code/datums/elements/basic_body_temp_sensitive.dm deleted file mode 100644 index 8e11ed92575e..000000000000 --- a/code/datums/elements/basic_body_temp_sensitive.dm +++ /dev/null @@ -1,71 +0,0 @@ -/** - * When attached to a basic mob, it gives it the ability to be hurt by cold/hot body temperatures - */ -/datum/element/basic_body_temp_sensitive - element_flags = ELEMENT_BESPOKE - argument_hash_start_idx = 2 - - ///Min body temp - var/min_body_temp = 250 - ///Max body temp - var/max_body_temp = 350 - ////Damage when below min temp - var/cold_damage = 1 - ///Damage when above max temp - var/heat_damage = 1 - -/datum/element/basic_body_temp_sensitive/Attach(datum/target, min_body_temp, max_body_temp, cold_damage, heat_damage) - . = ..() - if(!isbasicmob(target)) - return ELEMENT_INCOMPATIBLE - - if(isnum(min_body_temp)) - src.min_body_temp = min_body_temp - - if(isnum(max_body_temp)) - src.max_body_temp = max_body_temp - - if(isnum(cold_damage)) - src.cold_damage = cold_damage - - if(isnum(heat_damage)) - src.heat_damage = heat_damage - - RegisterSignal(target, COMSIG_LIVING_LIFE, PROC_REF(on_life)) - -/datum/element/basic_body_temp_sensitive/Detach(datum/source) - if(source) - UnregisterSignal(source, COMSIG_LIVING_LIFE) - return ..() - - -/datum/element/basic_body_temp_sensitive/proc/on_life(datum/target, seconds_per_tick, times_fired) - SIGNAL_HANDLER - - var/mob/living/basic/basic_mob = target - var/gave_alert = FALSE - - if(basic_mob.bodytemperature < min_body_temp) - basic_mob.adjust_health(cold_damage * seconds_per_tick) - switch(cold_damage) - if(1 to 5) - basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1) - if(5 to 10) - basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 2) - if(10 to INFINITY) - basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3) - gave_alert = TRUE - - else if(basic_mob.bodytemperature > max_body_temp) - basic_mob.adjust_health(heat_damage * seconds_per_tick) - switch(heat_damage) - if(1 to 5) - basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 1) - if(5 to 10) - basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 2) - if(10 to INFINITY) - basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 3) - gave_alert = TRUE - - if(!gave_alert) - basic_mob.clear_alert(ALERT_TEMPERATURE) diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index efa76ca24cd7..452048b3c231 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -183,9 +183,7 @@ desc = "These gloves can teach you to perform Krav Maga using nanochips." icon_state = "fightgloves" greyscale_colors = "#c41e0d" - cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE @@ -196,9 +194,7 @@ greyscale_colors = "#2f2e31" siemens_coefficient = 0 strip_delay = 80 - cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE armor_type = /datum/armor/krav_maga_combatglovesplus diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index c22e940c990b..962c26c4936e 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -19,13 +19,29 @@ mood_change = -1 timeout = 2 MINUTES +/datum/mood_event/chilly + description = "I'm feeling a bit chilly." + mood_change = -2 + /datum/mood_event/cold - description = "It's way too cold in here." - mood_change = -5 + description = "It's way too cold." + mood_change = -3 + +/datum/mood_event/freezing + description = "It's freezing cold!" + mood_change = -6 + +/datum/mood_event/warm + description = "I'm feeling a bit warm." + mood_change = -2 /datum/mood_event/hot - description = "It's getting hot in here." - mood_change = -5 + description = "It's way too hot." + mood_change = -3 + +/datum/mood_event/overhot + description = "It's scorching hot!" + mood_change = -6 /datum/mood_event/creampie description = "I've been creamed. Tastes like pie flavor." diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index 43463e3c0a5a..c306ab7c4dfa 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -28,6 +28,8 @@ part.variable_color = "#00aa00" owner.update_body_parts() owner.add_mood_event("hulk", /datum/mood_event/hulk) + owner.physiology?.cold_mod *= HULK_COLD_DAMAGE_MOD + owner.bodytemp_cold_damage_limit += BODYTEMP_HULK_COLD_DAMAGE_LIMIT_MODIFIER 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)) @@ -93,6 +95,8 @@ part.variable_color = null owner.update_body_parts() owner.clear_mood_event("hulk") + owner.physiology?.cold_mod /= HULK_COLD_DAMAGE_MOD + owner.bodytemp_cold_damage_limit -= BODYTEMP_HULK_COLD_DAMAGE_LIMIT_MODIFIER UnregisterSignal(owner, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) UnregisterSignal(owner, COMSIG_MOB_SAY) UnregisterSignal(owner, COMSIG_MOB_CLICKON) diff --git a/code/datums/status_effects/_status_effect_helpers.dm b/code/datums/status_effects/_status_effect_helpers.dm index 0ee952200610..144a972da621 100644 --- a/code/datums/status_effects/_status_effect_helpers.dm +++ b/code/datums/status_effects/_status_effect_helpers.dm @@ -56,7 +56,7 @@ . = FALSE for(var/datum/status_effect/existing_effect as anything in status_effects) - if(existing_effect.id == initial(removed_effect.id) && existing_effect.before_remove(arguments)) + if(existing_effect.id == initial(removed_effect.id) && existing_effect.before_remove(arglist(arguments))) qdel(existing_effect) . = TRUE diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 2e9714fb2959..ee06eee43f13 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -335,11 +335,7 @@ ADD_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, STATUS_EFFECT_TRAIT) owner.adjustBruteLoss(-25) owner.adjustFireLoss(-25) - owner.fully_heal(HEAL_CC_STATUS) - owner.bodytemperature = owner.get_body_temp_normal() - if(ishuman(owner)) - var/mob/living/carbon/human/humi = owner - humi.set_coretemperature(humi.get_body_temp_normal()) + owner.fully_heal(HEAL_CC_STATUS|HEAL_TEMP) return TRUE /datum/status_effect/regenerative_core/on_remove() @@ -480,7 +476,7 @@ owner.adjustFireLoss(-2 * seconds_per_tick, updating_health = FALSE) owner.adjustOxyLoss(-4 * seconds_per_tick, updating_health = FALSE) owner.stamina.adjust(4 * seconds_per_tick) - owner.adjust_bodytemperature(BODYTEMP_NORMAL, 0, BODYTEMP_NORMAL) //Won't save you from the void of space, but it will stop you from freezing or suffocating in low pressure + owner.adjust_bodytemperature(INFINITY, max_temp = owner.standard_body_temperature) //Won't save you from the void of space, but it will stop you from freezing or suffocating in low pressure /atom/movable/screen/alert/status_effect/nest_sustenance diff --git a/code/datums/status_effects/debuffs/fire_stacks.dm b/code/datums/status_effects/debuffs/fire_stacks.dm index f2c014578adc..d00d0c348439 100644 --- a/code/datums/status_effects/debuffs/fire_stacks.dm +++ b/code/datums/status_effects/debuffs/fire_stacks.dm @@ -189,36 +189,6 @@ var/turf/location = get_turf(owner) location.hotspot_expose(700, 25 * seconds_per_tick, TRUE) -/** - * Used to deal damage to humans and count their protection. - * - * Arguments: - * - seconds_per_tick - * - times_fired - * - no_protection: When set to TRUE, fire will ignore any possible fire protection - * - */ - -/datum/status_effect/fire_handler/fire_stacks/proc/harm_human(seconds_per_tick, times_fired, no_protection = FALSE) - var/mob/living/carbon/human/victim = owner - var/thermal_protection = victim.get_thermal_protection() - - if(!no_protection) - if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT) - return - if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT) - victim.adjust_bodytemperature(5.5 * seconds_per_tick) - return - - var/amount_to_heat = (BODYTEMP_HEATING_MAX + (stacks * 12)) * 0.5 * seconds_per_tick - if(owner.bodytemperature > BODYTEMP_FIRE_TEMP_SOFTCAP) - // Apply dimishing returns upon temp beyond the soft cap - amount_to_heat = amount_to_heat ** (BODYTEMP_FIRE_TEMP_SOFTCAP / owner.bodytemperature) - - victim.adjust_bodytemperature(amount_to_heat) - victim.add_mood_event("on_fire", /datum/mood_event/on_fire) - victim.add_mob_memory(/datum/memory/was_burning) - /** * Handles mob ignition, should be the only way to set on_fire to TRUE * diff --git a/code/datums/status_effects/gas.dm b/code/datums/status_effects/gas.dm index cfa282732058..bf0822d879f8 100644 --- a/code/datums/status_effects/gas.dm +++ b/code/datums/status_effects/gas.dm @@ -24,7 +24,7 @@ /datum/status_effect/freon/tick() - if(can_melt && owner.bodytemperature >= owner.get_body_temp_normal()) + if(can_melt && owner.bodytemperature >= owner.standard_body_temperature - 2 KELVIN) qdel(src) /datum/status_effect/freon/proc/owner_resist() @@ -43,7 +43,7 @@ if(!owner.stat) to_chat(owner, span_notice("The cube melts!")) owner.cut_overlay(cube) - owner.adjust_bodytemperature(100) + owner.adjust_bodytemperature(50 KELVIN, max_temp = owner.standard_body_temperature - 5 KELVIN) UnregisterSignal(owner, COMSIG_LIVING_RESIST) REMOVE_TRAIT(owner, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id)) return ..() diff --git a/code/datums/status_effects/stacking_effect.dm b/code/datums/status_effects/stacking_effect.dm index 9896ef5ec707..63f68c8041dc 100644 --- a/code/datums/status_effects/stacking_effect.dm +++ b/code/datums/status_effects/stacking_effect.dm @@ -86,8 +86,11 @@ /datum/status_effect/stacking/proc/add_stacks(stacks_added) if(stacks_added > 0 && !can_gain_stacks()) return FALSE - owner.cut_overlay(status_overlay) - owner.underlays -= status_underlay + if(status_overlay) + owner.cut_overlay(status_overlay) + if(status_underlay) + owner.underlays -= status_underlay + stacks += stacks_added if(stacks > 0) if(stacks >= stack_threshold && !threshold_crossed) //threshold_crossed check prevents threshold effect from occuring if changing from above threshold to still above threshold @@ -101,10 +104,12 @@ if(stacks_added > 0) tick_interval += delay_before_decay //refreshes time until decay stacks = min(stacks, max_stacks) - status_overlay.icon_state = "[overlay_state][stacks]" - status_underlay.icon_state = "[underlay_state][stacks]" - owner.add_overlay(status_overlay) - owner.underlays += status_underlay + if(status_overlay) + status_overlay.icon_state = "[overlay_state][stacks]" + owner.add_overlay(status_overlay) + if(status_underlay) + status_underlay.icon_state = "[underlay_state][stacks]" + owner.underlays += status_underlay else fadeout_effect() qdel(src) //deletes status if stacks fall under one @@ -117,23 +122,34 @@ /datum/status_effect/stacking/on_apply() if(!can_have_status()) return FALSE - status_overlay = mutable_appearance(overlay_file, "[overlay_state][stacks]") - status_underlay = mutable_appearance(underlay_file, "[underlay_state][stacks]") - var/icon/I = icon(owner.icon, owner.icon_state, owner.dir) - var/icon_height = I.Height() - status_overlay.pixel_x = -owner.pixel_x - status_overlay.pixel_y = FLOOR(icon_height * 0.25, 1) - status_overlay.transform = matrix() * (icon_height/world.icon_size) //scale the status's overlay size based on the target's icon size - status_underlay.pixel_x = -owner.pixel_x - status_underlay.transform = matrix() * (icon_height/world.icon_size) * 3 - status_underlay.alpha = 40 - owner.add_overlay(status_overlay) - owner.underlays += status_underlay - return ..() - -/datum/status_effect/stacking/Destroy() - if(owner) + if(overlay_file || underlay_file) + if(overlay_file) + status_overlay = mutable_appearance(overlay_file, "[overlay_state][stacks]") + if(underlay_file) + status_underlay = mutable_appearance(underlay_file, "[underlay_state][stacks]") + + var/icon/I = icon(owner.icon, owner.icon_state, owner.dir) + var/icon_height = I.Height() + + if(status_overlay) + status_overlay.pixel_x = -owner.pixel_x + status_overlay.pixel_y = FLOOR(icon_height * 0.25, 1) + status_overlay.transform = matrix() * (icon_height/world.icon_size) //scale the status's overlay size based on the target's icon size + owner.add_overlay(status_overlay) + + if(status_underlay) + status_underlay.pixel_x = -owner.pixel_x + status_underlay.transform = matrix() * (icon_height/world.icon_size) * 3 + status_underlay.alpha = 40 + owner.underlays += status_underlay + + return TRUE + +/datum/status_effect/stacking/on_remove() + if(QDELETED(owner)) + return + if(status_overlay) owner.cut_overlay(status_overlay) + QDEL_NULL(status_overlay) + if(status_underlay) owner.underlays -= status_underlay - QDEL_NULL(status_overlay) - return ..() diff --git a/code/datums/voice_of_god_command.dm b/code/datums/voice_of_god_command.dm index 69f077ddd82b..2018f290f97f 100644 --- a/code/datums/voice_of_god_command.dm +++ b/code/datums/voice_of_god_command.dm @@ -225,7 +225,7 @@ GLOBAL_LIST_INIT(voice_of_god_commands, init_voice_of_god_commands()) /datum/voice_of_god_command/hot/execute(list/listeners, mob/living/user, power_multiplier = 1, message) for(var/mob/living/target as anything in listeners) - target.adjust_bodytemperature(50 * power_multiplier) + target.adjust_bodytemperature(5 KELVIN * power_multiplier) /// This command cools the listeners down like freezing water. /datum/voice_of_god_command/cold @@ -234,7 +234,7 @@ GLOBAL_LIST_INIT(voice_of_god_commands, init_voice_of_god_commands()) /datum/voice_of_god_command/cold/execute(list/listeners, mob/living/user, power_multiplier = 1, message) for(var/mob/living/target as anything in listeners) - target.adjust_bodytemperature(-50 * power_multiplier) + target.adjust_bodytemperature(-7.5 KELVIN * power_multiplier) /// This command throws the listeners away from the user. /datum/voice_of_god_command/repulse diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm index 1a5bd69d2a04..e10e39505bc0 100644 --- a/code/datums/weather/weather_types/ash_storm.dm +++ b/code/datums/weather/weather_types/ash_storm.dm @@ -66,7 +66,7 @@ if(!. || !ishuman(mob_to_check)) return var/mob/living/carbon/human/human_to_check = mob_to_check - if(human_to_check.get_thermal_protection() >= FIRE_IMMUNITY_MAX_TEMP_PROTECT) + if(human_to_check.get_insulation(FIRE_IMMUNITY_MAX_TEMP_PROTECT) >= 0.9) //potentially broken return FALSE /datum/weather/ash_storm/weather_act(mob/living/victim) diff --git a/code/datums/weather/weather_types/void_storm.dm b/code/datums/weather/weather_types/void_storm.dm index becfa9859a81..13dbd09cb523 100644 --- a/code/datums/weather/weather_types/void_storm.dm +++ b/code/datums/weather/weather_types/void_storm.dm @@ -36,7 +36,7 @@ victim.adjustFireLoss(1) victim.adjustOxyLoss(rand(1, 3)) victim.adjust_eye_blur(rand(0 SECONDS, 2 SECONDS)) - victim.adjust_bodytemperature(-30 * TEMPERATURE_DAMAGE_COEFFICIENT) + victim.adjust_bodytemperature(-4 KELVIN) // Goes through former_impacted_areas and sets the overlay of each back to the telegraph overlay, to indicate the ascended heretic is no longer in that area. /datum/weather/void_storm/update_areas() diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index 0a4a557404ab..0934a79d966c 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -91,7 +91,7 @@ datum/wound/pierce/bleed/receive_damage(wounding_type, wounding_dmg, wound_bonus set_blood_flow(min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW)) if(limb.can_bleed()) - if(victim.bodytemperature < (BODYTEMP_NORMAL - 10)) + if(!HAS_TRAIT(victim, TRAIT_RESISTCOLD) && victim.get_skin_temperature() < victim.bodytemp_cold_damage_limit) adjust_blood_flow(-0.1 * seconds_per_tick) if(SPT_PROB(2.5, seconds_per_tick)) to_chat(victim, span_notice("You feel the [lowertext(undiagnosed_name || name)] in your [limb.plaintext_zone] firming up from the cold!")) diff --git a/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm b/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm index 781fd0d5a471..e9378797509b 100644 --- a/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm +++ b/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm @@ -30,8 +30,7 @@ var/new_colour = pick(/datum/slime_color/red, /datum/slime_color/orange) var/mob/living/basic/slime/pyro = new(tile, new_colour) ADD_TRAIT(pyro, TRAIT_SLIME_RABID, "pyro") - pyro.maximum_survivable_temperature = INFINITY - pyro.apply_temperature_requirements() + pyro.bodytemp_heat_damage_limit = INFINITY var/mob/chosen_one = SSpolling.poll_ghosts_for_target(check_jobban = ROLE_SENTIENCE, poll_time = 10 SECONDS, checked_target = pyro, ignore_category = POLL_IGNORE_PYROSLIME, alert_pic = pyro, role_name_text = "pyroclastic anomaly slime") if(isnull(chosen_one)) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index ce8694270287..cd2ee2766e41 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -110,13 +110,11 @@ ///Whether spessmen with an ID with an age below AGE_MINOR (20 by default) can buy this item var/age_restricted = FALSE - ///flags which determine which body parts are protected from heat. [See here][HEAD] - var/heat_protection = 0 - ///flags which determine which body parts are protected from cold. [See here][HEAD] - var/cold_protection = 0 - ///Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. Keep at null to disable protection. Only protects areas set by heat_protection flags + /// Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. + /// Keep at null to disable protection. var/max_heat_protection_temperature - ///Set this variable to determine down to which temperature (IN KELVIN) the item protects against cold damage. 0 is NOT an acceptable number due to if(varname) tests!! Keep at null to disable protection. Only protects areas set by cold_protection flags + /// Set this variable to determine down to which temperature (IN KELVIN) the item protects against cold damage. + /// Keep at null to disable protection. var/min_cold_protection_temperature ///list of /datum/action's that this item has. diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 18c414f3033b..4c7a5ccee05e 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -937,12 +937,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM var/mob/living/carbon/human/human_user = user if(!istype(human_user) || HAS_TRAIT(human_user, TRAIT_RESISTHEAT) || HAS_TRAIT(human_user, TRAIT_RESISTHEATHANDS)) hand_protected = TRUE - else if(!istype(human_user.gloves, /obj/item/clothing/gloves)) - hand_protected = FALSE else - var/obj/item/clothing/gloves/gloves = human_user.gloves - if(gloves.max_heat_protection_temperature) - hand_protected = (gloves.max_heat_protection_temperature > 360) + hand_protected = human_user.gloves?.max_heat_protection_temperature > 360 if(hand_protected || prob(75)) user.visible_message( diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index e25b845bfe41..c4798da26418 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -341,18 +341,19 @@ || istype(humantarget.get_organ_slot(ORGAN_SLOT_EXTERNAL_WINGS), /obj/item/organ/external/wings/functional) render_list += "Species: [targetspecies.name][mutant ? "-derived mutant" : ""]\n" - var/core_temperature_message = "Core temperature: [round(humantarget.coretemperature-T0C, 0.1)] °C ([round(humantarget.coretemperature*1.8-459.67,0.1)] °F)" - if(humantarget.coretemperature >= humantarget.get_body_temp_heat_damage_limit()) - render_list += "☼ [core_temperature_message] ☼\n" - else if(humantarget.coretemperature <= humantarget.get_body_temp_cold_damage_limit()) - render_list += "❄ [core_temperature_message] ❄\n" - else - render_list += "[core_temperature_message]\n" + var/skin_temp = target.get_skin_temperature() + var/skin_temperature_message = "Skin temperature: [round(KELVIN_TO_CELCIUS(skin_temp), 0.1)] °C ([round(KELVIN_TO_FAHRENHEIT(skin_temp), 0.1)] °F)" + if(skin_temp >= target.bodytemp_heat_damage_limit) + render_list += "☼ [skin_temperature_message] ☼\n" + else if(skin_temp <= target.bodytemp_cold_damage_limit) + render_list += "❄ [skin_temperature_message] ❄\n" + else + render_list += "[skin_temperature_message]\n" - var/body_temperature_message = "Body temperature: [round(target.bodytemperature-T0C, 0.1)] °C ([round(target.bodytemperature*1.8-459.67,0.1)] °F)" - if(target.bodytemperature >= target.get_body_temp_heat_damage_limit()) + var/body_temperature_message = "Body temperature: [round(KELVIN_TO_CELCIUS(target.bodytemperature), 0.1)] °C ([round(KELVIN_TO_FAHRENHEIT(target.bodytemperature), 0.1)] °F)" + if(target.bodytemperature >= target.bodytemp_heat_damage_limit) render_list += "☼ [body_temperature_message] ☼\n" - else if(target.bodytemperature <= target.get_body_temp_cold_damage_limit()) + else if(target.bodytemperature <= target.bodytemp_cold_damage_limit) render_list += "❄ [body_temperature_message] ❄\n" else render_list += "[body_temperature_message]\n" diff --git a/code/game/objects/items/grenades/syndieminibomb.dm b/code/game/objects/items/grenades/syndieminibomb.dm index f7d63e2ed9fe..0044e996eb5e 100644 --- a/code/game/objects/items/grenades/syndieminibomb.dm +++ b/code/game/objects/items/grenades/syndieminibomb.dm @@ -60,7 +60,7 @@ var/rad_range = 4 var/rad_threshold = RAD_EXTREME_INSULATION var/stamina_damage = 30 - var/temp_adjust = -230 + var/temp_adjust = 230 /obj/item/grenade/gluon/detonate(mob/living/lanced_by) . = ..() @@ -74,5 +74,5 @@ floor.MakeSlippery(TURF_WET_PERMAFROST, 6 MINUTES) for(var/mob/living/carbon/victim in floor) victim.stamina.adjust(-stamina_damage) - victim.adjust_bodytemperature(temp_adjust) + victim.adjust_bodytemperature(victim.bodytemperature - temp_adjust, use_insulation = TRUE) qdel(src) diff --git a/code/game/objects/items/pillow.dm b/code/game/objects/items/pillow.dm index 4bd54aa2e541..fa8e46cf3e30 100644 --- a/code/game/objects/items/pillow.dm +++ b/code/game/objects/items/pillow.dm @@ -124,7 +124,7 @@ name = "pillow suit" desc = "Part man, part pillow. All CARNAGE!" body_parts_covered = CHEST|GROIN|ARMS|LEGS|FEET - cold_protection = CHEST|GROIN|ARMS|LEGS //a pillow suit must be hella warm + //a pillow suit must be hella warm allowed = list(/obj/item/pillow) //moar pillow carnage icon = 'icons/obj/pillow.dmi' worn_icon = 'icons/mob/clothing/suits/pillow.dmi' diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm index beda3ca18a39..037c0aeeee37 100644 --- a/code/game/objects/items/religion.dm +++ b/code/game/objects/items/religion.dm @@ -360,9 +360,9 @@ icon_state = "crusader" desc = "They're like gloves, but made of metal." siemens_coefficient = 0 - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT /obj/item/clothing/gloves/plate/red @@ -378,9 +378,9 @@ w_class = WEIGHT_CLASS_NORMAL armor_type = /datum/armor/shoes_plate clothing_traits = list(TRAIT_NO_SLIP_WATER) - cold_protection = FEET + min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT - heat_protection = FEET + max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT /datum/armor/shoes_plate diff --git a/code/game/objects/items/storage/medkit.dm b/code/game/objects/items/storage/medkit.dm index 9b5c734a3a95..2c83e9dfc054 100644 --- a/code/game/objects/items/storage/medkit.dm +++ b/code/game/objects/items/storage/medkit.dm @@ -717,7 +717,7 @@ user.visible_message(span_suicide("[user] is beating [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")) return BRUTELOSS user.visible_message(span_suicide("[user] is putting [user.p_their()] head inside the [src], it looks like [user.p_theyre()] trying to commit suicide!")) - user.adjust_bodytemperature(-300) + user.adjust_bodytemperature(-INFINITY, min_temp = CELCIUS_TO_KELVIN(10 CELCIUS)) user.apply_status_effect(/datum/status_effect/freon) return FIRELOSS diff --git a/code/game/objects/structures/shower.dm b/code/game/objects/structures/shower.dm index 8607ff3c6edf..8f2dd88e944d 100644 --- a/code/game/objects/structures/shower.dm +++ b/code/game/objects/structures/shower.dm @@ -328,17 +328,17 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16)) qdel(src) /obj/machinery/shower/proc/check_heat(mob/living/L) - var/mob/living/carbon/C = L - if(current_temperature == SHOWER_FREEZING) - if(iscarbon(L)) - C.adjust_bodytemperature(-80, 80) - to_chat(L, span_warning("[src] is freezing!")) + if(L.bodytemperature >= L.standard_body_temperature - 1 KELVIN) + to_chat(L, span_warning("[src] is freezing!")) + + L.adjust_bodytemperature(-0.5 KELVIN, min_temp = CELCIUS_TO_KELVIN(30)) + else if(current_temperature == SHOWER_BOILING) - if(iscarbon(L)) - C.adjust_bodytemperature(35, 0, 500) - L.adjustFireLoss(5) - to_chat(L, span_danger("[src] is searing!")) + if(L.bodytemperature <= L.standard_body_temperature + 1 KELVIN) + to_chat(L, span_warning("[src] is [pick("scalding", "searing")]!")) + L.adjust_bodytemperature(0.5 KELVIN, max_temp = CELCIUS_TO_KELVIN(40)) + L.apply_damage(6, BURN, spread_damage = TRUE) /obj/structure/showerframe diff --git a/code/game/objects/structures/traps.dm b/code/game/objects/structures/traps.dm index 9078bf10085f..a702aecdda51 100644 --- a/code/game/objects/structures/traps.dm +++ b/code/game/objects/structures/traps.dm @@ -202,7 +202,7 @@ /obj/structure/trap/chill/trap_effect(mob/living/victim) to_chat(victim, span_bolddanger("You're frozen solid!")) victim.Paralyze(2 SECONDS) - victim.adjust_bodytemperature(-300) + victim.adjust_bodytemperature(-T0C, use_insulation = TRUE) victim.apply_status_effect(/datum/status_effect/freon) diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm index 5210e90425cd..e2303cae2ca8 100644 --- a/code/game/turfs/open/_open.dm +++ b/code/game/turfs/open/_open.dm @@ -200,13 +200,13 @@ air_update_turf(FALSE, FALSE) /turf/open/proc/freeze_turf() - for(var/obj/I in contents) - if(!HAS_TRAIT(I, TRAIT_FROZEN) && !(I.resistance_flags & FREEZE_PROOF)) - I.AddElement(/datum/element/frozen) + for(var/obj/iced in contents) + if(!HAS_TRAIT(iced, TRAIT_FROZEN) && !(iced.resistance_flags & FREEZE_PROOF)) + iced.AddElement(/datum/element/frozen) - for(var/mob/living/L in contents) - if(L.bodytemperature <= 50) - L.apply_status_effect(/datum/status_effect/freon) + for(var/mob/living/freezer in src) + if(freezer.bodytemperature <= CELCIUS_TO_KELVIN(25 CELCIUS)) + freezer.apply_status_effect(/datum/status_effect/freon) MakeSlippery(TURF_WET_PERMAFROST, 50) return TRUE diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index 92ae8dae9f9f..77f3a8fe6db5 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -543,8 +543,8 @@ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS armor_type = /datum/armor/armor_changeling flags_inv = HIDEJUMPSUIT - cold_protection = 0 - heat_protection = 0 + max_heat_protection_temperature = null + min_cold_protection_temperature = null resistance_flags = FLAMMABLE //MONKESTATION ADDITION /datum/armor/armor_changeling diff --git a/code/modules/antagonists/changeling/powers/void_adaption.dm b/code/modules/antagonists/changeling/powers/void_adaption.dm index 76c0eeffc972..0bf4fc902b1f 100644 --- a/code/modules/antagonists/changeling/powers/void_adaption.dm +++ b/code/modules/antagonists/changeling/powers/void_adaption.dm @@ -34,11 +34,11 @@ var/datum/gas_mixture/environment = void_adapted.loc.return_air() if (!isnull(environment)) - var/vulnerable_temperature = void_adapted.get_body_temp_cold_damage_limit() + var/vulnerable_temperature = void_adapted.bodytemp_cold_damage_limit var/affected_temperature = environment.return_temperature() if (ishuman(void_adapted)) var/mob/living/carbon/human/special_boy = void_adapted - var/cold_protection = special_boy.get_cold_protection(affected_temperature) + var/cold_protection = special_boy.get_insulation(affected_temperature) vulnerable_temperature *= (1 - cold_protection) var/affected_pressure = special_boy.calculate_affecting_pressure(environment.return_pressure()) diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 4094842d5d1e..97c90bba4945 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -182,9 +182,9 @@ Striking a noncultist, however, will tear their flesh."} flags_inv = HIDEFACE|HIDEHAIR|HIDEEARS flags_cover = HEADCOVERSEYES armor_type = /datum/armor/hooded_cult_hoodie - cold_protection = HEAD + min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT /datum/armor/hooded_cult_hoodie @@ -208,9 +208,9 @@ Striking a noncultist, however, will tear their flesh."} allowed = list(/obj/item/tome, /obj/item/melee/cultblade) armor_type = /datum/armor/hooded_cultrobes flags_inv = HIDEJUMPSUIT - cold_protection = CHEST|GROIN|LEGS|ARMS + min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN|LEGS|ARMS + max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT hoodtype = /obj/item/clothing/head/hooded/cult_hoodie diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm index f82b9b829533..6faf49021266 100644 --- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm +++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_buff.dm @@ -20,10 +20,12 @@ /datum/status_effect/unholy_determination/on_apply() owner.add_traits(list(TRAIT_COAGULATING, TRAIT_NOCRITDAMAGE, TRAIT_NOSOFTCRIT), type) + owner.add_homeostasis_level(id, owner.standard_body_temperature, 10 KELVIN) return TRUE /datum/status_effect/unholy_determination/on_remove() owner.remove_traits(list(TRAIT_COAGULATING, TRAIT_NOCRITDAMAGE, TRAIT_NOSOFTCRIT), type) + owner.remove_homeostasis_level(id) /datum/status_effect/unholy_determination/tick() // The amount we heal of each damage type per tick. If we're missing legs we heal better because we can't dodge. @@ -49,7 +51,6 @@ playsound(owner, pick(GLOB.creepy_ambience), 50, TRUE) adjust_all_damages(healing_amount) - adjust_temperature() adjust_bleed_wounds() /* @@ -65,23 +66,6 @@ owner.adjustBruteLoss(-amount, FALSE) owner.adjustFireLoss(-amount) -/* - * Adjust the owner's temperature up or down to standard body temperatures. - */ -/datum/status_effect/unholy_determination/proc/adjust_temperature() - var/target_temp = owner.get_body_temp_normal(apply_change = FALSE) - if(owner.bodytemperature > target_temp) - owner.adjust_bodytemperature(-50 * TEMPERATURE_DAMAGE_COEFFICIENT, target_temp) - else if(owner.bodytemperature < (target_temp + 1)) - owner.adjust_bodytemperature(50 * TEMPERATURE_DAMAGE_COEFFICIENT, target_temp) - - if(ishuman(owner)) - var/mob/living/carbon/human/human_owner = owner - if(human_owner.coretemperature > target_temp) - human_owner.adjust_coretemperature(-50 * TEMPERATURE_DAMAGE_COEFFICIENT, target_temp) - else if(human_owner.coretemperature < (target_temp + 1)) - human_owner.adjust_coretemperature(50 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, target_temp) - /* * Slow and stop any blood loss the owner's experiencing. */ diff --git a/code/modules/antagonists/heretic/status_effects/debuffs.dm b/code/modules/antagonists/heretic/status_effects/debuffs.dm index 761af62876f6..1088f846525f 100644 --- a/code/modules/antagonists/heretic/status_effects/debuffs.dm +++ b/code/modules/antagonists/heretic/status_effects/debuffs.dm @@ -6,7 +6,7 @@ status_type = STATUS_EFFECT_REPLACE tick_interval = 0.5 SECONDS /// The amount the victim's body temperature changes each tick() in kelvin. Multiplied by TEMPERATURE_DAMAGE_COEFFICIENT. - var/cooling_per_tick = -14 + var/cooling_per_tick = -1 KELVIN /atom/movable/screen/alert/status_effect/void_chill name = "Void Chill" @@ -23,11 +23,11 @@ owner.remove_movespeed_modifier(/datum/movespeed_modifier/void_chill, update = TRUE) /datum/status_effect/void_chill/tick() - owner.adjust_bodytemperature(cooling_per_tick * TEMPERATURE_DAMAGE_COEFFICIENT) + owner.adjust_bodytemperature(cooling_per_tick) /datum/status_effect/void_chill/major duration = 10 SECONDS - cooling_per_tick = -20 + cooling_per_tick = -4 KELVIN /datum/status_effect/void_chill/lasting id = "lasting_void_chill" diff --git a/code/modules/assembly/igniter.dm b/code/modules/assembly/igniter.dm index 061de2a5f920..d2125499e6ce 100644 --- a/code/modules/assembly/igniter.dm +++ b/code/modules/assembly/igniter.dm @@ -1,5 +1,4 @@ #define EXPOSED_VOLUME 1000 -#define ROOM_TEMP 293 #define MIN_FREEZE_TEMP 50 #define MAX_FREEZE_TEMP 1000000 @@ -68,10 +67,9 @@ var/turf/location = get_turf(loc) if(location) var/datum/gas_mixture/enviro = location.return_air() - enviro.temperature = clamp(min(ROOM_TEMP, enviro.temperature*0.85),MIN_FREEZE_TEMP,MAX_FREEZE_TEMP) + enviro.temperature = clamp(min(T20C, enviro.temperature*0.85),MIN_FREEZE_TEMP,MAX_FREEZE_TEMP) sparks.start() #undef EXPOSED_VOLUME -#undef ROOM_TEMP #undef MIN_FREEZE_TEMP #undef MAX_FREEZE_TEMP diff --git a/code/modules/atmospherics/machinery/air_alarm/air_alarm_thresholds.dm b/code/modules/atmospherics/machinery/air_alarm/air_alarm_thresholds.dm index cfe74f13c346..bfb9b28441fa 100644 --- a/code/modules/atmospherics/machinery/air_alarm/air_alarm_thresholds.dm +++ b/code/modules/atmospherics/machinery/air_alarm/air_alarm_thresholds.dm @@ -93,10 +93,10 @@ hazard_max = HAZARD_HIGH_PRESSURE /datum/tlv/temperature - warning_min = BODYTEMP_COLD_WARNING_1+10 - hazard_min = BODYTEMP_COLD_WARNING_1 - warning_max = BODYTEMP_HEAT_WARNING_1-27 - hazard_max = BODYTEMP_HEAT_WARNING_1 + warning_min = BODYTEMP_COLD_DAMAGE_LIMIT + 10 CELCIUS + hazard_min = BODYTEMP_COLD_DAMAGE_LIMIT + warning_max = BODYTEMP_HEAT_DAMAGE_LIMIT - 10 CELCIUS + hazard_max = BODYTEMP_HEAT_DAMAGE_LIMIT /datum/tlv/cold_room_pressure warning_min = ONE_ATMOSPHERE * 0.9 diff --git a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm index d1ac81975c55..72d21d042c2f 100644 --- a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm +++ b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm @@ -33,7 +33,6 @@ worn_item.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) worn_item.add_atom_colour("#00fff7", FIXED_COLOUR_PRIORITY) worn_item.min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT - worn_item.cold_protection = worn_item.body_parts_covered worn_item.clothing_flags |= STOPSPRESSUREDAMAGE uses-- if(!uses) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 97e7641b4e0e..595e2fcdde46 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -359,7 +359,7 @@ if(ishuman(mob_occupant)) var/mob/living/carbon/human/H = mob_occupant - cold_protection = H.get_cold_protection(air1.temperature) + cold_protection = H.get_insulation(air1.temperature) if(abs(temperature_delta) > 1) var/air_heat_capacity = air1.heat_capacity() @@ -369,11 +369,6 @@ mob_occupant.adjust_bodytemperature(heat / heat_capacity, TCMB) air1.temperature = clamp(air1.temperature - heat / air_heat_capacity, TCMB, MAX_TEMPERATURE) - //lets have the core temp match the body temp in humans - if(ishuman(mob_occupant)) - var/mob/living/carbon/human/humi = mob_occupant - humi.adjust_coretemperature(humi.bodytemperature - humi.coretemperature) - air1.garbage_collect() diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm index fd43e315527b..f25838b8fa65 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm @@ -44,7 +44,7 @@ //Best guess-estimate of the total bodytemperature of all the mobs, since they share the same environment it's ~ok~ to guess like this var/avg_temp = (pipe_air.temperature * hc + (heat_source.bodytemperature * buckled_mobs.len) * 3500) / (hc + (buckled_mobs ? buckled_mobs.len * 3500 : 0)) for(var/mob/living/buckled_mob as anything in buckled_mobs) - buckled_mob.bodytemperature = avg_temp + buckled_mob.adjust_bodytemperature(avg_temp - heat_source.bodytemperature) pipe_air.temperature = avg_temp /obj/machinery/atmospherics/pipe/heat_exchanging/process(seconds_per_tick) diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm index 73da55ad2fe3..8c62a873ffea 100644 --- a/code/modules/awaymissions/mission_code/snowdin.dm +++ b/code/modules/awaymissions/mission_code/snowdin.dm @@ -376,7 +376,7 @@ name = "insulated tactical turtleneck" desc = "A nondescript and slightly suspicious-looking turtleneck with digital camouflage cargo pants. The interior has been padded with special insulation for both warmth and protection." armor_type = /datum/armor/syndicate_coldres - cold_protection = CHEST|GROIN|ARMS|LEGS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT /datum/armor/syndicate_coldres diff --git a/code/modules/cargo/gondolapod.dm b/code/modules/cargo/gondolapod.dm index f3dca7a3dca1..16da87d45c5b 100644 --- a/code/modules/cargo/gondolapod.dm +++ b/code/modules/cargo/gondolapod.dm @@ -18,8 +18,8 @@ loot = list(/obj/effect/decal/cleanable/blood/gibs, /obj/item/stack/sheet/animalhide/gondola = 2, /obj/item/food/meat/slab/gondola = 2) //Gondolas aren't affected by cold. atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - maxbodytemp = 1500 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 1500 maxHealth = 200 health = 200 del_on_death = TRUE diff --git a/code/modules/clothing/gloves/bone.dm b/code/modules/clothing/gloves/bone.dm index 2c75e642ff61..526913241d77 100644 --- a/code/modules/clothing/gloves/bone.dm +++ b/code/modules/clothing/gloves/bone.dm @@ -6,7 +6,7 @@ strip_delay = 40 equip_delay_other = 20 body_parts_covered = ARMS - cold_protection = ARMS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE diff --git a/code/modules/clothing/gloves/botany.dm b/code/modules/clothing/gloves/botany.dm index af94a6b7bb13..a3d09c8512be 100644 --- a/code/modules/clothing/gloves/botany.dm +++ b/code/modules/clothing/gloves/botany.dm @@ -4,9 +4,9 @@ icon_state = "leather" inhand_icon_state = null greyscale_colors = null - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE clothing_traits = list(TRAIT_PLANT_SAFE) diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index 6f302279531f..67f6172c1d15 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -3,9 +3,9 @@ name = "black gloves" icon_state = "black" greyscale_colors = "#2f2e31" - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE cut_type = /obj/item/clothing/gloves/fingerless @@ -17,7 +17,7 @@ greyscale_colors = "#2f2e31" strip_delay = 40 equip_delay_other = 20 - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT custom_price = PAYCHECK_CREW * 1.5 undyeable = TRUE @@ -82,7 +82,7 @@ name = "\proper Endotherm gloves" desc = "A pair of thick grey gloves, lined to protect the wearer from freezing cold." w_class = WEIGHT_CLASS_NORMAL - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT resistance_flags = NONE clothing_flags = THICKMATERIAL diff --git a/code/modules/clothing/gloves/combat.dm b/code/modules/clothing/gloves/combat.dm index e69813272d74..0ab32158c89f 100644 --- a/code/modules/clothing/gloves/combat.dm +++ b/code/modules/clothing/gloves/combat.dm @@ -5,9 +5,9 @@ greyscale_colors = "#2f2e31" siemens_coefficient = 0 strip_delay = 80 - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE armor_type = /datum/armor/gloves_combat diff --git a/code/modules/clothing/gloves/insulated.dm b/code/modules/clothing/gloves/insulated.dm index 89f33963af5d..2585c30278f8 100644 --- a/code/modules/clothing/gloves/insulated.dm +++ b/code/modules/clothing/gloves/insulated.dm @@ -114,8 +114,8 @@ inhand_icon_state = null greyscale_colors = null siemens_coefficient = 0 - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE diff --git a/code/modules/clothing/gloves/plasmaman.dm b/code/modules/clothing/gloves/plasmaman.dm index 0ca552773ec2..a5976df47a81 100644 --- a/code/modules/clothing/gloves/plasmaman.dm +++ b/code/modules/clothing/gloves/plasmaman.dm @@ -3,9 +3,9 @@ name = "plasma envirogloves" icon_state = "plasmaman" greyscale_colors = "#913b00" - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE armor_type = /datum/armor/color_plasmaman diff --git a/code/modules/clothing/gloves/special.dm b/code/modules/clothing/gloves/special.dm index 6ba1797ac02f..2c23539ee598 100644 --- a/code/modules/clothing/gloves/special.dm +++ b/code/modules/clothing/gloves/special.dm @@ -81,9 +81,9 @@ inhand_icon_state = null greyscale_colors = null siemens_coefficient = 0 - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT strip_delay = 60 armor_type = /datum/armor/captain_gloves @@ -139,9 +139,9 @@ name = "atmospheric extrication gloves" desc = "Heavy duty gloves for firefighters. These are thick, non-flammable and let you carry people faster." icon_state = "atmos" - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF siemens_coefficient = 0.3 diff --git a/code/modules/clothing/gloves/tacklers.dm b/code/modules/clothing/gloves/tacklers.dm index 888ecac39ee7..8b205c29b5d0 100644 --- a/code/modules/clothing/gloves/tacklers.dm +++ b/code/modules/clothing/gloves/tacklers.dm @@ -3,7 +3,7 @@ desc = "Special gloves that manipulate the blood vessels in the wearer's hands, granting them the ability to launch headfirst into walls." icon_state = "tackle" inhand_icon_state = null - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT resistance_flags = NONE custom_premium_price = PAYCHECK_COMMAND * 3.5 @@ -68,9 +68,9 @@ tackle_range = 5 skill_mod = 2 - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index 6d9105e51ff9..4d767bfc89e1 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -74,9 +74,9 @@ dog_fashion = null name = "firefighter helmet" clothing_flags = STOPSPRESSUREDAMAGE | PLASMAMAN_HELMET_EXEMPT - heat_protection = HEAD + max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT /obj/item/clothing/head/utility/hardhat/red/upgraded @@ -94,9 +94,9 @@ inhand_icon_state = null hat_type = "white" clothing_flags = STOPSPRESSUREDAMAGE | PLASMAMAN_HELMET_EXEMPT - heat_protection = HEAD + max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT dog_fashion = /datum/dog_fashion/head @@ -167,9 +167,9 @@ light_outer_range = 4 //Boss always takes the best stuff hat_type = "white" clothing_flags = STOPSPRESSUREDAMAGE | PLASMAMAN_HELMET_EXEMPT - heat_protection = HEAD + max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT /obj/item/clothing/head/utility/hardhat/welding/dblue @@ -185,9 +185,9 @@ name = "atmospheric firefighter helmet" desc = "A firefighter's helmet, able to keep the user cool in any situation. Comes with a light and a welding visor." clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | PLASMAMAN_HELMET_EXEMPT | HEADINTERNALS - heat_protection = HEAD + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF visor_flags_cover = NONE diff --git a/code/modules/clothing/head/hat.dm b/code/modules/clothing/head/hat.dm index 1bb3cae11d7b..408723b2d888 100644 --- a/code/modules/clothing/head/hat.dm +++ b/code/modules/clothing/head/hat.dm @@ -168,7 +168,7 @@ desc = "On the first day of christmas my employer gave to me!" icon_state = "santahatnorm" inhand_icon_state = "that" - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT dog_fashion = /datum/dog_fashion/head/santa @@ -272,7 +272,7 @@ icon_state = "ushankadown" inhand_icon_state = null flags_inv = HIDEEARS|HIDEHAIR - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT dog_fashion = /datum/dog_fashion/head/ushanka var/earflaps = TRUE diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 7e984c659e5e..f6b0bfb7e250 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -6,9 +6,9 @@ icon_state = "helmet" inhand_icon_state = "helmet" armor_type = /datum/armor/head_helmet - cold_protection = HEAD + min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT strip_delay = 60 clothing_flags = SNUG_FIT | PLASMAMAN_HELMET_EXEMPT @@ -243,9 +243,9 @@ icon_state = "swatsyndie" inhand_icon_state = "swatsyndie_helmet" armor_type = /datum/armor/helmet_swat - cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT clothing_flags = STOPSPRESSUREDAMAGE | PLASMAMAN_HELMET_EXEMPT strip_delay = 80 @@ -270,9 +270,9 @@ icon_state = "swat" inhand_icon_state = "swat_helmet" clothing_flags = PLASMAMAN_HELMET_EXEMPT | SNUG_FIT //monkestation edit - cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT flags_cover = HEADCOVERSEYES | PEPPERPROOF //monkestation edit @@ -287,9 +287,9 @@ icon_state = "thunderdome" inhand_icon_state = "thunderdome_helmet" armor_type = /datum/armor/helmet_thunderdome - cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT strip_delay = 80 dog_fashion = null @@ -305,8 +305,8 @@ acid = 90 /obj/item/clothing/head/helmet/thunderdome/holosuit - cold_protection = null - heat_protection = null + max_heat_protection_temperature = null + min_cold_protection_temperature = null armor_type = /datum/armor/thunderdome_holosuit /datum/armor/thunderdome_holosuit @@ -503,7 +503,7 @@ icon_state = "rus_ushanka" inhand_icon_state = "rus_ushanka" body_parts_covered = HEAD - cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT armor_type = /datum/armor/helmet_rus_ushanka diff --git a/code/modules/clothing/head/moth.dm b/code/modules/clothing/head/moth.dm index d91d58208c68..04ba774b5319 100644 --- a/code/modules/clothing/head/moth.dm +++ b/code/modules/clothing/head/moth.dm @@ -4,7 +4,7 @@ icon_state = "mothcap" icon = 'icons/obj/clothing/head/moth.dmi' worn_icon = 'icons/mob/clothing/head/moth.dmi' - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT flags_cover = HEADCOVERSEYES flags_inv = HIDEHAIR diff --git a/code/modules/clothing/shoes/boots.dm b/code/modules/clothing/shoes/boots.dm index 4b7c16292f76..4a73682e3a1a 100644 --- a/code/modules/clothing/shoes/boots.dm +++ b/code/modules/clothing/shoes/boots.dm @@ -75,9 +75,9 @@ icon_state = "winterboots" inhand_icon_state = null armor_type = /datum/armor/shoes_winterboots - cold_protection = FEET|LEGS + min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT - heat_protection = FEET|LEGS + max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT lace_time = 8 SECONDS diff --git a/code/modules/clothing/shoes/cult.dm b/code/modules/clothing/shoes/cult.dm index 80d03d3a09e2..a3e93631f04d 100644 --- a/code/modules/clothing/shoes/cult.dm +++ b/code/modules/clothing/shoes/cult.dm @@ -3,9 +3,9 @@ desc = "A pair of boots worn by the followers of Nar'Sie." icon_state = "cult" inhand_icon_state = null - cold_protection = FEET + min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT - heat_protection = FEET + max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT lace_time = 10 SECONDS diff --git a/code/modules/clothing/shoes/sneakers.dm b/code/modules/clothing/shoes/sneakers.dm index f07ea00c5089..2aa316cdfc7f 100644 --- a/code/modules/clothing/shoes/sneakers.dm +++ b/code/modules/clothing/shoes/sneakers.dm @@ -17,9 +17,9 @@ desc = "A pair of black shoes." custom_price = PAYCHECK_CREW - cold_protection = FEET + min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT - heat_protection = FEET + max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT /obj/item/clothing/shoes/sneakers/brown diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm index 32b50115c65c..2c2f141c6be4 100644 --- a/code/modules/clothing/spacesuits/_spacesuits.dm +++ b/code/modules/clothing/spacesuits/_spacesuits.dm @@ -13,9 +13,9 @@ armor_type = /datum/armor/helmet_space flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT clothing_traits = list(TRAIT_SNOWSTORM_IMMUNE) - cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT flash_protect = FLASH_PROTECTION_WELDER strip_delay = 50 @@ -49,9 +49,9 @@ slowdown = 1 armor_type = /datum/armor/suit_space flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS + min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT_OFF - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT strip_delay = 80 equip_delay_other = 80 @@ -121,7 +121,10 @@ // If we got here, it means thermals are on, the cell is in and the cell has // just had enough charge subtracted from it to power the thermal regulator - user.adjust_bodytemperature(get_temp_change_amount((temperature_setting - user.bodytemperature), 0.08 * seconds_per_tick)) + if(user.bodytemperature < temperature_setting) + user.adjust_bodytemperature((temperature_setting - user.bodytemperature) * 0.08 * seconds_per_tick, max_temp = temperature_setting) + else if(user.bodytemperature > temperature_setting) + user.adjust_bodytemperature((temperature_setting - user.bodytemperature) * 0.08 * seconds_per_tick, min_temp = temperature_setting) update_hud_icon(user) // Clean up the cell on destroy @@ -290,12 +293,12 @@ /obj/item/clothing/head/helmet/space/suicide_act(mob/living/carbon/user) var/datum/gas_mixture/environment = user.loc.return_air() - if(HAS_TRAIT(user, TRAIT_RESISTCOLD) || !environment || environment.return_temperature() >= user.get_body_temp_cold_damage_limit()) + if(HAS_TRAIT(user, TRAIT_RESISTCOLD) || !environment || environment.return_temperature() >= user.bodytemp_cold_damage_limit) user.visible_message(span_suicide("[user] is beating [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")) return BRUTELOSS user.say("You want proof? I'll give you proof! Here's proof of what'll happen to you if you stay here with your stuff!", forced = "space helmet suicide") user.visible_message(span_suicide("[user] is removing [user.p_their()] helmet to make a point! Yo, holy shit, [user.p_they()] dead!")) //the use of p_they() instead of p_their() here is intentional - user.adjust_bodytemperature(-300) + user.adjust_bodytemperature(-INFINITY, min_temp = CELCIUS_TO_KELVIN(-225 CELCIUS)) user.apply_status_effect(/datum/status_effect/freon) if(!ishuman(user)) return FIRELOSS diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index b6a8add54370..85de34946d4b 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -3,9 +3,9 @@ worn_icon = 'icons/mob/clothing/suits/armor.dmi' allowed = null body_parts_covered = CHEST - cold_protection = CHEST|GROIN + min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN + max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT strip_delay = 60 equip_delay_other = 40 @@ -71,9 +71,9 @@ clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS armor_type = /datum/armor/vest_marine - cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS + min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT_OFF - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + resistance_flags = FIRE_PROOF | ACID_PROOF /datum/armor/vest_marine @@ -146,8 +146,8 @@ inhand_icon_state = "greatcoat" body_parts_covered = CHEST|GROIN|ARMS|LEGS armor_type = /datum/armor/armor_hos - cold_protection = CHEST|GROIN|LEGS|ARMS - heat_protection = CHEST|GROIN|LEGS|ARMS + + strip_delay = 80 /datum/armor/armor_hos @@ -193,8 +193,8 @@ icon_state = "warden_alt" inhand_icon_state = "armor" body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS|HANDS - heat_protection = CHEST|GROIN|ARMS|HANDS + + strip_delay = 70 resistance_flags = FLAMMABLE dog_fashion = null @@ -210,8 +210,8 @@ icon_state = "leathercoat-sec" inhand_icon_state = "hostrench" body_parts_covered = CHEST|GROIN|ARMS|LEGS - cold_protection = CHEST|GROIN|LEGS|ARMS - heat_protection = CHEST|GROIN|LEGS|ARMS + + dog_fashion = null /obj/item/clothing/suit/armor/vest/capcarapace @@ -256,8 +256,8 @@ icon_state = "riot" inhand_icon_state = "swat_suit" body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + + armor_type = /datum/armor/armor_riot clothing_flags = BLOCKS_SHOVE_KNOCKDOWN strip_delay = 80 @@ -318,8 +318,8 @@ inhand_icon_state = "armor_reflec" blood_overlay_type = "armor" body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS - heat_protection = CHEST|GROIN|ARMS + + armor_type = /datum/armor/armor_laserproof resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF var/hit_reflect_chance = 50 @@ -358,9 +358,9 @@ strip_delay = 120 resistance_flags = FIRE_PROOF | ACID_PROOF clothing_flags = THICKMATERIAL - cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS + min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT_OFF - heat_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS + max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT slowdown = 0.5 //monkestation edit, 0.7 to 0.5 body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS @@ -404,8 +404,8 @@ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT clothing_flags = THICKMATERIAL - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + + armor_type = /datum/armor/armor_tdome /datum/armor/armor_tdome @@ -433,8 +433,8 @@ /obj/item/clothing/suit/armor/tdome/holosuit name = "thunderdome suit" armor_type = /datum/armor/tdome_holosuit - cold_protection = null - heat_protection = null + max_heat_protection_temperature = null + min_cold_protection_temperature = null /datum/armor/tdome_holosuit melee = 10 @@ -527,7 +527,7 @@ icon_state = "rus_coat" inhand_icon_state = null body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT armor_type = /datum/armor/vest_russian_coat dog_fashion = null @@ -551,8 +551,8 @@ material_flags = MATERIAL_EFFECTS | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS//Can change color and add prefix armor_type = /datum/armor/armor_elder_atmosian body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + + /obj/item/clothing/suit/armor/elder_atmosian/Initialize(mapload) . = ..() @@ -607,7 +607,7 @@ icon_state = "militia" inhand_icon_state = "b_suit" body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT armor_type = /datum/armor/coat_militia diff --git a/code/modules/clothing/suits/costume.dm b/code/modules/clothing/suits/costume.dm index eb99688de85e..7d1f5f52e462 100644 --- a/code/modules/clothing/suits/costume.dm +++ b/code/modules/clothing/suits/costume.dm @@ -246,7 +246,7 @@ worn_icon = 'icons/mob/clothing/suits/costume.dmi' inhand_icon_state = "labcoat" body_parts_covered = CHEST|GROIN|ARMS|LEGS|FEET - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT //Space carp like space, so you should too allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/gun/ballistic/rifle/boltaction/harpoon) hoodtype = /obj/item/clothing/head/hooded/carp_hood @@ -258,7 +258,7 @@ worn_icon = 'icons/mob/clothing/head/costume.dmi' icon_state = "carp_casual" body_parts_covered = HEAD - cold_protection = HEAD + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT flags_inv = HIDEHAIR|HIDEEARS @@ -280,9 +280,9 @@ armor_type = /datum/armor/carp_costume_spaceproof allowed = list(/obj/item/tank/internals, /obj/item/gun/ballistic/rifle/boltaction/harpoon) //I'm giving you a hint here flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT clothing_flags = STOPSPRESSUREDAMAGE|THICKMATERIAL body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS @@ -302,7 +302,7 @@ armor_type = /datum/armor/carp_hood_spaceproof flags_inv = HIDEEARS|HIDEHAIR|HIDEFACIALHAIR //facial hair will clip with the helm, this'll need a dynamic_fhair_suffix at some point. min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT clothing_flags = STOPSPRESSUREDAMAGE|THICKMATERIAL|SNUG_FIT|PLASMAMAN_HELMET_EXEMPT body_parts_covered = HEAD @@ -333,7 +333,7 @@ worn_icon = 'icons/mob/clothing/suits/costume.dmi' inhand_icon_state = "labcoat" body_parts_covered = CHEST|GROIN|ARMS|LEGS|FEET - //cold_protection = CHEST|GROIN|ARMS + // //min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT allowed = list() hoodtype = /obj/item/clothing/head/hooded/ian_hood @@ -346,7 +346,7 @@ worn_icon = 'icons/mob/clothing/head/costume.dmi' icon_state = "ian" body_parts_covered = HEAD - //cold_protection = HEAD + // //min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT flags_inv = HIDEHAIR|HIDEEARS diff --git a/code/modules/clothing/suits/jacket.dm b/code/modules/clothing/suits/jacket.dm index ae2cb14caa2c..4b8db2052995 100644 --- a/code/modules/clothing/suits/jacket.dm +++ b/code/modules/clothing/suits/jacket.dm @@ -12,7 +12,7 @@ /obj/item/storage/belt/holster, ) body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT species_exception = list(/datum/species/golem) @@ -41,7 +41,7 @@ desc = "Rated 10 out of 10 in Cosmo for best coat brand." icon_state = "fancy_coat" body_parts_covered = CHEST|GROIN|LEGS|ARMS - cold_protection = CHEST|GROIN|LEGS|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON greyscale_config = /datum/greyscale_config/fancy_coat @@ -87,7 +87,7 @@ icon_state = "puffervest" inhand_icon_state = "armor" body_parts_covered = CHEST|GROIN - cold_protection = CHEST|GROIN + armor_type = /datum/armor/puffer_vest /datum/armor/puffer_vest diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index fb05df7e26d3..264de3ba63f0 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -106,8 +106,8 @@ blood_overlay_type = "coat" body_parts_covered = CHEST|GROIN|ARMS armor_type = /datum/armor/jacket_det_suit - cold_protection = CHEST|GROIN|ARMS - heat_protection = CHEST|GROIN|ARMS + + /datum/armor/jacket_det_suit melee = 25 @@ -292,8 +292,8 @@ /obj/item/tank/internals, ) armor_type = /datum/armor/jacket_curator - cold_protection = CHEST|ARMS - heat_protection = CHEST|ARMS + + //Robotocist /datum/armor/jacket_curator diff --git a/code/modules/clothing/suits/moth.dm b/code/modules/clothing/suits/moth.dm index a3e789daa245..65b9572a0ebf 100644 --- a/code/modules/clothing/suits/moth.dm +++ b/code/modules/clothing/suits/moth.dm @@ -27,6 +27,6 @@ greyscale_config_worn = /datum/greyscale_config/mothcoat_winter_worn greyscale_colors = "#557979#795e55" body_parts_covered = CHEST|GROIN|ARMS|LEGS - cold_protection = CHEST|GROIN|ARMS|LEGS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index c867349f6564..7e3cd62ac77d 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -31,9 +31,9 @@ armor_type = /datum/armor/utility_fire flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT strip_delay = 60 equip_delay_other = 60 @@ -57,8 +57,8 @@ /obj/item/clothing/suit/utility/fire/firefighter icon_state = "firesuit" inhand_icon_state = "firefighter" - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS + + body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS /obj/item/clothing/suit/utility/fire/heavy @@ -74,8 +74,8 @@ icon_state = "atmos_firesuit" inhand_icon_state = "firefighter_atmos" max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS + + body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS flags_inv = HIDESHOES|HIDEJUMPSUIT @@ -90,9 +90,9 @@ armor_type = /datum/armor/utility_bomb_hood flags_inv = HIDEFACE|HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT - cold_protection = HEAD + min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT strip_delay = 70 equip_delay_other = 70 @@ -119,9 +119,9 @@ slowdown = 2 armor_type = /datum/armor/utility_bomb_suit flags_inv = HIDEJUMPSUIT - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT strip_delay = 70 equip_delay_other = 70 diff --git a/code/modules/clothing/suits/wintercoats.dm b/code/modules/clothing/suits/wintercoats.dm index d4461b8812f1..51a85dbac59d 100644 --- a/code/modules/clothing/suits/wintercoats.dm +++ b/code/modules/clothing/suits/wintercoats.dm @@ -7,7 +7,7 @@ worn_icon = 'icons/mob/clothing/suits/wintercoat.dmi' inhand_icon_state = "coatwinter" body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT allowed = list() armor_type = /datum/armor/hooded_wintercoat @@ -36,7 +36,7 @@ icon_state = "hood_winter" worn_icon = 'icons/mob/clothing/head/winterhood.dmi' body_parts_covered = HEAD - cold_protection = HEAD + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT flags_inv = HIDEHAIR|HIDEEARS armor_type = /datum/armor/hooded_winterhood diff --git a/code/modules/clothing/under/costume.dm b/code/modules/clothing/under/costume.dm index 16ad9ba6e9eb..5e54cd640a11 100644 --- a/code/modules/clothing/under/costume.dm +++ b/code/modules/clothing/under/costume.dm @@ -228,7 +228,7 @@ icon_state = "red_mech_suit" inhand_icon_state = null body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + female_sprite_flags = NO_FEMALE_UNIFORM alternate_worn_layer = GLOVES_LAYER //covers hands but gloves can go over it. This is how these things work in my head. can_adjust = FALSE diff --git a/code/modules/clothing/under/jobs/civilian/curator.dm b/code/modules/clothing/under/jobs/civilian/curator.dm index 1e459604e205..315c27675d6a 100644 --- a/code/modules/clothing/under/jobs/civilian/curator.dm +++ b/code/modules/clothing/under/jobs/civilian/curator.dm @@ -41,9 +41,9 @@ w_class = WEIGHT_CLASS_BULKY armor_type = /datum/armor/curator_nasa body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - cold_protection = CHEST | GROIN | LEGS | ARMS //Needs gloves and shoes with cold protection to be fully protected. + min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT can_adjust = FALSE resistance_flags = NONE diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 68749df3ed0b..fc3a0ce814af 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -50,9 +50,9 @@ desc = "A cybernetically enhanced jumpsuit used for administrative duties." body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS armor_type = /datum/armor/misc_adminsuit - cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS + min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT can_adjust = FALSE resistance_flags = FIRE_PROOF | ACID_PROOF diff --git a/code/modules/hydroponics/unique_plant_genes.dm b/code/modules/hydroponics/unique_plant_genes.dm index 61bde105bc9f..073573e70afc 100644 --- a/code/modules/hydroponics/unique_plant_genes.dm +++ b/code/modules/hydroponics/unique_plant_genes.dm @@ -303,8 +303,8 @@ stop_backfire_effect() return - our_mob.adjust_bodytemperature(7.5 * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick) - if(SPT_PROB(5, seconds_per_tick)) + our_mob.adjust_bodytemperature(0.5 KELVIN * seconds_per_tick) + if(!HAS_TRAIT(our_mob, TRAIT_RESISTHEAT) && SPT_PROB(5, seconds_per_tick)) to_chat(our_mob, span_warning("Your hand holding [our_plant] burns!")) /// Bluespace Tomato squashing on the user on backfire @@ -433,7 +433,7 @@ var/obj/item/seeds/our_seed = our_plant.get_plant_seed() var/mob/living/spawned_mob = new killer_plant(our_plant.drop_location()) var/health_mid_point = 150 - var/health_max_value = 40 + var/health_max_value = 40 spawned_mob.maxHealth += qp_sigmoid(health_mid_point, health_max_value, our_seed.endurance) spawned_mob.health = spawned_mob.maxHealth if(ishostile(spawned_mob)) diff --git a/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm b/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm index c0751b2e3d1b..669a038bbfa8 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm @@ -7,8 +7,8 @@ /obj/item/clothing/suit/chaplainsuit/armor body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + + armor_type = /datum/armor/chaplainsuit_armor clothing_flags = BLOCKS_SHOVE_KNOCKDOWN strip_delay = 80 diff --git a/code/modules/jobs/job_types/chaplain/chaplain_divine_archer.dm b/code/modules/jobs/job_types/chaplain/chaplain_divine_archer.dm index 48bdf25a22f2..d88fb2f35906 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_divine_archer.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_divine_archer.dm @@ -17,8 +17,8 @@ icon_state = "archercoat" inhand_icon_state = "archercoat" body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + + armor_type = /datum/armor/chaplainsuit_armor_weaker clothing_flags = BLOCKS_SHOVE_KNOCKDOWN strip_delay = 80 diff --git a/code/modules/mapfluff/ruins/icemoonruin_code/wrath.dm b/code/modules/mapfluff/ruins/icemoonruin_code/wrath.dm index f5db91dad016..ae25cf6f2f4b 100644 --- a/code/modules/mapfluff/ruins/icemoonruin_code/wrath.dm +++ b/code/modules/mapfluff/ruins/icemoonruin_code/wrath.dm @@ -3,9 +3,9 @@ desc = "These gloves allow the user to rip apart bodies with precision and ease." icon_state = "black" greyscale_colors = "#2f2e31" - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT /obj/item/clothing/gloves/butchering/Initialize(mapload) diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm index 65b80f0196d0..82cb1c63b97c 100644 --- a/code/modules/mining/equipment/explorer_gear.dm +++ b/code/modules/mining/equipment/explorer_gear.dm @@ -7,9 +7,9 @@ worn_icon = 'icons/mob/clothing/suits/utility.dmi' inhand_icon_state = null body_parts_covered = CHEST|GROIN|LEGS|ARMS - cold_protection = CHEST|GROIN|LEGS|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN|LEGS|ARMS + max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT hoodtype = /obj/item/clothing/head/hooded/explorer armor_type = /datum/armor/hooded_explorer @@ -43,9 +43,9 @@ icon_state = "explorer" body_parts_covered = HEAD flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT armor_type = /datum/armor/hooded_explorer resistance_flags = FIRE_PROOF @@ -198,9 +198,9 @@ armor_type = /datum/armor/cloak_drake hoodtype = /obj/item/clothing/head/hooded/cloakhood/drake body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF transparent_protection = HIDEGLOVES|HIDESUITSTORAGE|HIDEJUMPSUIT|HIDESHOES @@ -223,9 +223,9 @@ desc = "The skull of a dragon." armor_type = /datum/armor/cloakhood_drake clothing_flags = SNUG_FIT - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -256,9 +256,9 @@ armor_type = /datum/armor/cloak_godslayer clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL hoodtype = /obj/item/clothing/head/hooded/cloakhood/godslayer - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS resistance_flags = FIRE_PROOF | ACID_PROOF | FREEZE_PROOF @@ -289,9 +289,9 @@ desc = "The horns and skull of a wendigo, held together by the remaining icey energy of a demonic miner." armor_type = /datum/armor/cloakhood_godslayer clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT flash_protect = FLASH_PROTECTION_WELDER flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm index bd4ee168cb7d..5aa3d249b252 100644 --- a/code/modules/mining/lavaland/megafauna_loot.dm +++ b/code/modules/mining/lavaland/megafauna_loot.dm @@ -255,9 +255,9 @@ icon_state = "hostile_env" hoodtype = /obj/item/clothing/head/hooded/hostile_environment armor_type = /datum/armor/hooded_hostile_environment - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS clothing_flags = THICKMATERIAL @@ -300,9 +300,9 @@ icon_state = "hostile_env" w_class = WEIGHT_CLASS_NORMAL armor_type = /datum/armor/hooded_hostile_environment - cold_protection = HEAD + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT clothing_flags = SNUG_FIT|THICKMATERIAL resistance_flags = FIRE_PROOF|LAVA_PROOF|ACID_PROOF diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index 723d5300425f..35cc374c967b 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -615,9 +615,9 @@ toolspeed = 0.1 strip_delay = 40 equip_delay_other = 20 - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = LAVA_PROOF | FIRE_PROOF //they are from lavaland after all armor_type = /datum/armor/gloves_gauntlets @@ -664,9 +664,9 @@ worn_icon = 'icons/mob/clothing/suits/armor.dmi' hoodtype = /obj/item/clothing/head/hooded/berserker armor_type = /datum/armor/hooded_berserker - cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS resistance_flags = FIRE_PROOF @@ -711,9 +711,9 @@ worn_icon = 'icons/mob/clothing/head/helmet.dmi' armor_type = /datum/armor/hooded_berserker actions_types = list(/datum/action/item_action/berserk_mode) - cold_protection = HEAD + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF clothing_flags = SNUG_FIT|THICKMATERIAL diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm index 299a2c2856bc..89afd35417e7 100644 --- a/code/modules/mob/living/basic/basic.dm +++ b/code/modules/mob/living/basic/basic.dm @@ -91,10 +91,8 @@ ///This damage is taken when atmos doesn't fit all the requirements above. Set to 0 to avoid adding the atmos_requirements element. var/unsuitable_atmos_damage = 1 - ///Minimal body temperature without receiving damage - var/minimum_survivable_temperature = NPC_DEFAULT_MIN_TEMP - ///Maximal body temperature without receiving damage - var/maximum_survivable_temperature = NPC_DEFAULT_MAX_TEMP + bodytemp_cold_damage_limit = NPC_DEFAULT_MIN_TEMP + bodytemp_heat_damage_limit = NPC_DEFAULT_MAX_TEMP ///This damage is taken when the body temp is too cold. Set both this and unsuitable_heat_damage to 0 to avoid adding the basic_body_temp_sensitive element. var/unsuitable_cold_damage = 1 ///This damage is taken when the body temp is too hot. Set both this and unsuitable_cold_damage to 0 to avoid adding the basic_body_temp_sensitive element. @@ -120,7 +118,6 @@ speak_emote = string_list(speak_emote) apply_atmos_requirements() - apply_temperature_requirements() /// Ensures this mob can take atmospheric damage if it's supposed to /mob/living/basic/proc/apply_atmos_requirements() @@ -130,12 +127,36 @@ habitable_atmos = string_assoc_list(habitable_atmos) AddElement(/datum/element/atmos_requirements, habitable_atmos, unsuitable_atmos_damage) -/// Ensures this mob can take temperature damage if it's supposed to -/mob/living/basic/proc/apply_temperature_requirements() - if(unsuitable_cold_damage == 0 && unsuitable_heat_damage == 0) - return - AddElement(/datum/element/basic_body_temp_sensitive, minimum_survivable_temperature, maximum_survivable_temperature, unsuitable_cold_damage, unsuitable_heat_damage) +/mob/living/basic/body_temperature_damage(datum/gas_mixture/environment, seconds_per_tick, times_fired) + if((bodytemperature < bodytemp_cold_damage_limit) && unsuitable_cold_damage) + adjust_health(unsuitable_cold_damage * seconds_per_tick) + + if((bodytemperature > bodytemp_heat_damage_limit) && unsuitable_heat_damage) + adjust_health(unsuitable_heat_damage * seconds_per_tick) + +/mob/living/basic/body_temperature_alerts() + if((bodytemperature < bodytemp_cold_damage_limit) && unsuitable_cold_damage) + switch(unsuitable_cold_damage) + if(1 to 5) + throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1) + if(5 to 10) + throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 2) + if(10 to INFINITY) + throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3) + . = TRUE + + if((bodytemperature > bodytemp_heat_damage_limit) && unsuitable_heat_damage) + switch(unsuitable_heat_damage) + if(1 to 5) + throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 1) + if(5 to 10) + throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 2) + if(10 to INFINITY) + throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 3) + . = TRUE + if(!.) + clear_alert(ALERT_TEMPERATURE) /mob/living/basic/Life(seconds_per_tick = SSMOBS_DT, times_fired) . = ..() @@ -228,17 +249,11 @@ if(NAMEOF(src, habitable_atmos), NAMEOF(src, unsuitable_atmos_damage)) RemoveElement(/datum/element/atmos_requirements, habitable_atmos, unsuitable_atmos_damage) . = TRUE - if(NAMEOF(src, minimum_survivable_temperature), NAMEOF(src, maximum_survivable_temperature), NAMEOF(src, unsuitable_cold_damage), NAMEOF(src, unsuitable_heat_damage)) - RemoveElement(/datum/element/basic_body_temp_sensitive, minimum_survivable_temperature, maximum_survivable_temperature, unsuitable_cold_damage, unsuitable_heat_damage) - . = TRUE - . = ..() switch(vname) if(NAMEOF(src, habitable_atmos), NAMEOF(src, unsuitable_atmos_damage)) apply_atmos_requirements() - if(NAMEOF(src, minimum_survivable_temperature), NAMEOF(src, maximum_survivable_temperature), NAMEOF(src, unsuitable_cold_damage), NAMEOF(src, unsuitable_heat_damage)) - apply_temperature_requirements() if(NAMEOF(src, speed)) datum_flags |= DF_VAR_EDITED set_varspeed(vval) @@ -276,9 +291,6 @@ /mob/living/basic/on_stamina_update() set_varspeed(initial(speed) + (staminaloss * 0.06)) -/mob/living/basic/on_fire_stack(seconds_per_tick, times_fired, datum/status_effect/fire_handler/fire_stacks/fire_handler) - adjust_bodytemperature((maximum_survivable_temperature + (fire_handler.stacks * 12)) * 0.5 * seconds_per_tick) - /mob/living/basic/get_fire_overlay(stacks, on_fire) var/fire_icon = "generic_fire" if(!GLOB.fire_appearances[fire_icon]) @@ -306,9 +318,3 @@ SET_PLANE(held, ABOVE_HUD_PLANE, our_turf) held.screen_loc = ui_hand_position(index) client.screen |= held - -/mob/living/basic/get_body_temp_heat_damage_limit() - return maximum_survivable_temperature - -/mob/living/basic/get_body_temp_cold_damage_limit() - return minimum_survivable_temperature diff --git a/code/modules/mob/living/basic/blob_minions/blob_mob.dm b/code/modules/mob/living/basic/blob_minions/blob_mob.dm index 31eebb9394cb..2465b83e6786 100644 --- a/code/modules/mob/living/basic/blob_minions/blob_mob.dm +++ b/code/modules/mob/living/basic/blob_minions/blob_mob.dm @@ -11,8 +11,8 @@ bubble_icon = "blob" speak_emote = null habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = 0 - maximum_survivable_temperature = INFINITY + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = INFINITY lighting_cutoff_red = 20 lighting_cutoff_green = 40 lighting_cutoff_blue = 30 diff --git a/code/modules/mob/living/basic/bots/_bots.dm b/code/modules/mob/living/basic/bots/_bots.dm index e5584574ee3e..57b12d0d3a73 100644 --- a/code/modules/mob/living/basic/bots/_bots.dm +++ b/code/modules/mob/living/basic/bots/_bots.dm @@ -19,8 +19,8 @@ GLOBAL_LIST_INIT(command_strings, list( damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) hud_possible = list(DIAG_STAT_HUD, DIAG_BOT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_PATH_HUD = HUD_LIST_LIST) - maximum_survivable_temperature = INFINITY - minimum_survivable_temperature = 0 + bodytemp_heat_damage_limit = INFINITY + bodytemp_cold_damage_limit = -1 has_unlimited_silicon_privilege = TRUE sentience_type = SENTIENCE_ARTIFICIAL status_flags = NONE //no default canpush diff --git a/code/modules/mob/living/basic/clown/clown.dm b/code/modules/mob/living/basic/clown/clown.dm index ff5410fd0593..b65f43b18afc 100644 --- a/code/modules/mob/living/basic/clown/clown.dm +++ b/code/modules/mob/living/basic/clown/clown.dm @@ -23,8 +23,8 @@ basic_mob_flags = DEL_ON_DEATH initial_language_holder = /datum/language_holder/clown habitable_atmos = list("min_oxy" = 5, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = T0C - maximum_survivable_temperature = (T0C + 100) + bodytemp_cold_damage_limit = T0C + bodytemp_heat_damage_limit = (T0C + 100) unsuitable_atmos_damage = 10 unsuitable_heat_damage = 15 faction = list(FACTION_CLOWN) diff --git a/code/modules/mob/living/basic/cult/constructs/_construct.dm b/code/modules/mob/living/basic/cult/constructs/_construct.dm index 1cb7a68cb7da..162c6fe39df5 100644 --- a/code/modules/mob/living/basic/cult/constructs/_construct.dm +++ b/code/modules/mob/living/basic/cult/constructs/_construct.dm @@ -6,8 +6,8 @@ mob_biotypes = MOB_MINERAL faction = list(FACTION_CULT) unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 - maximum_survivable_temperature = INFINITY + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = INFINITY damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) pressure_resistance = 100 speed = 0 diff --git a/code/modules/mob/living/basic/farm_animals/goat/_goat.dm b/code/modules/mob/living/basic/farm_animals/goat/_goat.dm index 9c7046cccf7d..ea4e0f21c836 100644 --- a/code/modules/mob/living/basic/farm_animals/goat/_goat.dm +++ b/code/modules/mob/living/basic/farm_animals/goat/_goat.dm @@ -38,7 +38,7 @@ melee_damage_upper = 2 environment_smash = ENVIRONMENT_SMASH_NONE - minimum_survivable_temperature = COLD_ROOM_TEMP - 75 // enough so that they can survive the cold room spawn with plenty of room for comfort + bodytemp_cold_damage_limit = COLD_ROOM_TEMP - 75 // enough so that they can survive the cold room spawn with plenty of room for comfort blood_volume = BLOOD_VOLUME_NORMAL diff --git a/code/modules/mob/living/basic/farm_animals/rabbit.dm b/code/modules/mob/living/basic/farm_animals/rabbit.dm index 992a127e05f4..faaf13225096 100644 --- a/code/modules/mob/living/basic/farm_animals/rabbit.dm +++ b/code/modules/mob/living/basic/farm_animals/rabbit.dm @@ -102,8 +102,8 @@ icon_prefix = "space_rabbit" ai_controller = /datum/ai_controller/basic_controller/rabbit/easter/space unsuitable_atmos_damage = 0 // Zero because we are meant to survive in space. - minimum_survivable_temperature = 0 // Minimum Allowable Body Temp, zero because we are meant to survive in space and we have a fucking RABBIT SPACE MASK. - maximum_survivable_temperature = 1500 // Maximum Allowable Body Temp, 1500 because we might overheat and die in said RABBIT SPACE MASK. + bodytemp_cold_damage_limit = -1 // Minimum Allowable Body Temp, zero because we are meant to survive in space and we have a fucking RABBIT SPACE MASK. + bodytemp_heat_damage_limit = 1500 // Maximum Allowable Body Temp, 1500 because we might overheat and die in said RABBIT SPACE MASK. unsuitable_cold_damage = 0 // Zero because we are meant to survive in space. /datum/ai_controller/basic_controller/rabbit/easter/space diff --git a/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm b/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm index 1471a0976396..8cf9566b78f1 100644 --- a/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm +++ b/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm @@ -13,7 +13,7 @@ /// Ability we use to select gases var/datum/action/cooldown/mob_cooldown/expel_gas/gas /// Rate of temperature stabilization per second. - var/temp_stabilization_rate = 0.1 + var/temp_stabilization_rate = 1 KELVIN /mob/living/basic/guardian/gaseous/Initialize(mapload, theme) . = ..() @@ -34,11 +34,12 @@ if (QDELETED(src)) return RegisterSignal(summoner, COMSIG_LIVING_IGNITED, PROC_REF(on_summoner_ignited)) - RegisterSignal(summoner, COMSIG_LIVING_LIFE, PROC_REF(on_summoner_life)) + summoner.add_homeostasis_level(REF(src), summoner.standard_body_temperature, temp_stabilization_rate) /mob/living/basic/guardian/gaseous/cut_summoner(different_person) if (!isnull(summoner)) - UnregisterSignal(summoner, list(COMSIG_LIVING_IGNITED, COMSIG_LIVING_LIFE)) + UnregisterSignal(summoner, COMSIG_LIVING_IGNITED) + summoner.remove_homeostasis_level(REF(src)) return ..() /// Prevent our summoner from being on fire @@ -47,11 +48,6 @@ source.extinguish_mob() source.set_fire_stacks(0, remove_wet_stacks = FALSE) -/// Maintain our summoner at a stable body temperature -/mob/living/basic/guardian/gaseous/proc/on_summoner_life(mob/living/source, seconds_per_tick, times_fired) - SIGNAL_HANDLER - source.adjust_bodytemperature(get_temp_change_amount((summoner.get_body_temp_normal() - summoner.bodytemperature), temp_stabilization_rate * seconds_per_tick)) - /mob/living/basic/guardian/gaseous/melee_attack(atom/target, list/modifiers, ignore_cooldown) . = ..() if(!. || !isliving(target)) diff --git a/code/modules/mob/living/basic/jungle/mega_arachnid/mega_arachnid.dm b/code/modules/mob/living/basic/jungle/mega_arachnid/mega_arachnid.dm index bb109fdde61a..7c37a4009ce8 100644 --- a/code/modules/mob/living/basic/jungle/mega_arachnid/mega_arachnid.dm +++ b/code/modules/mob/living/basic/jungle/mega_arachnid/mega_arachnid.dm @@ -20,8 +20,8 @@ faction = list(FACTION_JUNGLE) obj_damage = 30 environment_smash = ENVIRONMENT_SMASH_WALLS - minimum_survivable_temperature = T0C - maximum_survivable_temperature = T0C + 450 + bodytemp_cold_damage_limit = T0C + bodytemp_heat_damage_limit = T0C + 450 status_flags = NONE lighting_cutoff_red = 5 lighting_cutoff_green = 20 diff --git a/code/modules/mob/living/basic/jungle/seedling/seedling.dm b/code/modules/mob/living/basic/jungle/seedling/seedling.dm index 0968ef6bc5b8..2727caa5461b 100644 --- a/code/modules/mob/living/basic/jungle/seedling/seedling.dm +++ b/code/modules/mob/living/basic/jungle/seedling/seedling.dm @@ -14,8 +14,8 @@ icon_living = "seedling" icon_dead = "seedling_dead" habitable_atmos = list("min_oxy" = 2, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 450 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 450 mob_biotypes = MOB_ORGANIC | MOB_PLANT maxHealth = 100 health = 100 diff --git a/code/modules/mob/living/basic/jungle/venus_human_trap.dm b/code/modules/mob/living/basic/jungle/venus_human_trap.dm index b8959ace2d06..6b4c49b8081a 100644 --- a/code/modules/mob/living/basic/jungle/venus_human_trap.dm +++ b/code/modules/mob/living/basic/jungle/venus_human_trap.dm @@ -141,7 +141,7 @@ obj_damage = 60 melee_damage_lower = 10 melee_damage_upper = 20 - minimum_survivable_temperature = 100 + bodytemp_cold_damage_limit = 100 istate = ISTATE_HARM|ISTATE_BLOCKING basic_mob_flags = DEL_ON_DEATH death_message = "collapses into bits of plant matter." diff --git a/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm b/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm index ea8267b74fb5..497a6e4e66e0 100644 --- a/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm +++ b/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm @@ -84,8 +84,8 @@ mob_biotypes = MOB_ORGANIC|MOB_BEAST faction = list(FACTION_MINING) unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 - maximum_survivable_temperature = INFINITY + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = INFINITY speed = 1.5 maxHealth = 1 health = 1 diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm b/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm index e066bac6a704..9b787caa12c8 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm @@ -13,8 +13,8 @@ mob_biotypes = MOB_ORGANIC|MOB_BEAST faction = list(FACTION_MINING) unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 - maximum_survivable_temperature = INFINITY + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = INFINITY friendly_verb_continuous = "chatters near" friendly_verb_simple = "chatter near" maxHealth = 1 diff --git a/code/modules/mob/living/basic/lavaland/mining.dm b/code/modules/mob/living/basic/lavaland/mining.dm index 825f36bed6b4..fac8cf66ee5e 100644 --- a/code/modules/mob/living/basic/lavaland/mining.dm +++ b/code/modules/mob/living/basic/lavaland/mining.dm @@ -6,8 +6,8 @@ mob_biotypes = MOB_ORGANIC|MOB_BEAST faction = list(FACTION_MINING) unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 - maximum_survivable_temperature = INFINITY + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = INFINITY // Pale purple, should be red enough to see stuff on lavaland lighting_cutoff_red = 25 lighting_cutoff_green = 15 diff --git a/code/modules/mob/living/basic/minebots/minebot.dm b/code/modules/mob/living/basic/minebots/minebot.dm index 6457239bdce8..b5de01f103fa 100644 --- a/code/modules/mob/living/basic/minebots/minebot.dm +++ b/code/modules/mob/living/basic/minebots/minebot.dm @@ -9,7 +9,7 @@ status_flags = CANSTUN|CANKNOCKDOWN|CANPUSH mouse_opacity = MOUSE_OPACITY_ICON habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = 0 + bodytemp_cold_damage_limit = -1 health = 125 maxHealth = 125 melee_damage_lower = 15 diff --git a/code/modules/mob/living/basic/pets/dog/corgi.dm b/code/modules/mob/living/basic/pets/dog/corgi.dm index 00b64ffef6f9..a651a93ed48b 100644 --- a/code/modules/mob/living/basic/pets/dog/corgi.dm +++ b/code/modules/mob/living/basic/pets/dog/corgi.dm @@ -555,8 +555,8 @@ can_be_shaved = FALSE held_state = "void_puppy" unsuitable_atmos_damage = 0 - minimum_survivable_temperature = TCMB - maximum_survivable_temperature = T0C + 40 + bodytemp_cold_damage_limit = TCMB + bodytemp_heat_damage_limit = T0C + 40 /mob/living/basic/pet/dog/corgi/puppy/void/Initialize(mapload) . = ..() diff --git a/code/modules/mob/living/basic/space_fauna/ant.dm b/code/modules/mob/living/basic/space_fauna/ant.dm index 27aa66cb0521..1e244345f309 100644 --- a/code/modules/mob/living/basic/space_fauna/ant.dm +++ b/code/modules/mob/living/basic/space_fauna/ant.dm @@ -30,8 +30,8 @@ health = 100 maxHealth = 100 light_outer_range = 1.5 // Bioluminescence! - minimum_survivable_temperature = T20C - 100 - maximum_survivable_temperature = T20C + 120 + bodytemp_cold_damage_limit = T20C - 100 + bodytemp_heat_damage_limit = T20C + 120 light_color = "#d43229" // The ants that comprise the giant ant still glow red despite the sludge. ai_controller = /datum/ai_controller/basic_controller/ant diff --git a/code/modules/mob/living/basic/space_fauna/bear/_bear.dm b/code/modules/mob/living/basic/space_fauna/bear/_bear.dm index cc34f271caca..5995844362a0 100644 --- a/code/modules/mob/living/basic/space_fauna/bear/_bear.dm +++ b/code/modules/mob/living/basic/space_fauna/bear/_bear.dm @@ -34,8 +34,8 @@ faction = list(FACTION_RUSSIAN) habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = TCMB - maximum_survivable_temperature = T0C + 1500 + bodytemp_cold_damage_limit = TCMB + bodytemp_heat_damage_limit = T0C + 1500 ai_controller = /datum/ai_controller/basic_controller/bear /// is the bear wearing a armor? var/armored = FALSE diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp.dm b/code/modules/mob/living/basic/space_fauna/carp/carp.dm index 24fb0b582642..b91d98a89af3 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp.dm @@ -42,8 +42,8 @@ greyscale_config = /datum/greyscale_config/carp ai_controller = /datum/ai_controller/basic_controller/carp habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 1500 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 1500 /// Cytology cells you can swab from this creature var/cell_line = CELL_LINE_TABLE_CARP diff --git a/code/modules/mob/living/basic/space_fauna/demon/demon.dm b/code/modules/mob/living/basic/space_fauna/demon/demon.dm index ece0e9d4ee72..b2956424aa20 100644 --- a/code/modules/mob/living/basic/space_fauna/demon/demon.dm +++ b/code/modules/mob/living/basic/space_fauna/demon/demon.dm @@ -36,8 +36,8 @@ death_sound = 'sound/magic/demon_dies.ogg' habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = T0C - 25 //Weak to cold - maximum_survivable_temperature = INFINITY + bodytemp_cold_damage_limit = T0C - 25 //Weak to cold + bodytemp_heat_damage_limit = INFINITY basic_mob_flags = DEL_ON_DEATH diff --git a/code/modules/mob/living/basic/space_fauna/demon/demon_subtypes.dm b/code/modules/mob/living/basic/space_fauna/demon/demon_subtypes.dm index e52eb09ac0b7..4d606df4a54e 100644 --- a/code/modules/mob/living/basic/space_fauna/demon/demon_subtypes.dm +++ b/code/modules/mob/living/basic/space_fauna/demon/demon_subtypes.dm @@ -8,7 +8,7 @@ icon_state = "slaughter_demon" icon_living = "slaughter_demon" - minimum_survivable_temperature = TCMB + bodytemp_cold_damage_limit = TCMB // slaughter demons are specifically intended to have low melee damage, but as they hit and build up their killstreak // their wound bonuses grow and grow higher. this is how they're able to efficiently kill and slaughter their victims. diff --git a/code/modules/mob/living/basic/space_fauna/eyeball/_eyeball.dm b/code/modules/mob/living/basic/space_fauna/eyeball/_eyeball.dm index 51fd2162baa6..ecf19bb392a4 100644 --- a/code/modules/mob/living/basic/space_fauna/eyeball/_eyeball.dm +++ b/code/modules/mob/living/basic/space_fauna/eyeball/_eyeball.dm @@ -31,8 +31,8 @@ speak_emote = list("telepathically cries") habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = T0C - maximum_survivable_temperature = T0C + 1500 + bodytemp_cold_damage_limit = T0C + bodytemp_heat_damage_limit = T0C + 1500 sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS lighting_cutoff_red = 40 diff --git a/code/modules/mob/living/basic/space_fauna/garden_gnome.dm b/code/modules/mob/living/basic/space_fauna/garden_gnome.dm index 40debc7622bc..485d74ab0c8d 100644 --- a/code/modules/mob/living/basic/space_fauna/garden_gnome.dm +++ b/code/modules/mob/living/basic/space_fauna/garden_gnome.dm @@ -22,8 +22,8 @@ speak_emote = list("announces") unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 500 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 500 faction = list(FACTION_GNOME) mob_size = MOB_SIZE_SMALL diff --git a/code/modules/mob/living/basic/space_fauna/hivebot/_hivebot.dm b/code/modules/mob/living/basic/space_fauna/hivebot/_hivebot.dm index 66191f7ccd96..855145200f4f 100644 --- a/code/modules/mob/living/basic/space_fauna/hivebot/_hivebot.dm +++ b/code/modules/mob/living/basic/space_fauna/hivebot/_hivebot.dm @@ -30,7 +30,7 @@ death_message = "blows apart!" habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = TCMB + bodytemp_cold_damage_limit = TCMB ai_controller = /datum/ai_controller/basic_controller/hivebot ///does this type do range attacks? var/ranged_attacker = FALSE diff --git a/code/modules/mob/living/basic/space_fauna/killer_tomato.dm b/code/modules/mob/living/basic/space_fauna/killer_tomato.dm index c859289b56d7..5f11453e2857 100644 --- a/code/modules/mob/living/basic/space_fauna/killer_tomato.dm +++ b/code/modules/mob/living/basic/space_fauna/killer_tomato.dm @@ -30,8 +30,8 @@ faction = list(FACTION_PLANTS) habitable_atmos = list("min_oxy" = 5, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = T0C - 130 - maximum_survivable_temperature = T0C + 230 + bodytemp_cold_damage_limit = T0C - 130 + bodytemp_heat_damage_limit = T0C + 230 gold_core_spawnable = HOSTILE_SPAWN ai_controller = /datum/ai_controller/basic_controller/killer_tomato diff --git a/code/modules/mob/living/basic/space_fauna/lightgeist.dm b/code/modules/mob/living/basic/space_fauna/lightgeist.dm index 7fa070ea8a76..fe83090c8c75 100644 --- a/code/modules/mob/living/basic/space_fauna/lightgeist.dm +++ b/code/modules/mob/living/basic/space_fauna/lightgeist.dm @@ -38,8 +38,8 @@ light_outer_range = 4 faction = list(FACTION_NEUTRAL) unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 1500 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 1500 obj_damage = 0 environment_smash = ENVIRONMENT_SMASH_NONE diff --git a/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm b/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm index 7aa8efc2ecf2..8b18f51e80c2 100644 --- a/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm +++ b/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm @@ -21,8 +21,8 @@ faction = list() ai_controller = /datum/ai_controller/basic_controller/meteor_heart habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 1500 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 1500 istate = ISTATE_HARM | ISTATE_BLOCKING move_resist = INFINITY // This mob IS the floor /// Action which sends a line of spikes chasing a player diff --git a/code/modules/mob/living/basic/space_fauna/morph.dm b/code/modules/mob/living/basic/space_fauna/morph.dm index 0cce48ba377e..bde2710b3a97 100644 --- a/code/modules/mob/living/basic/space_fauna/morph.dm +++ b/code/modules/mob/living/basic/space_fauna/morph.dm @@ -16,7 +16,7 @@ maxHealth = 150 health = 150 habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = TCMB + bodytemp_cold_damage_limit = TCMB obj_damage = 50 melee_damage_lower = 20 diff --git a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm index b3c6935c92ef..5c65704a39cc 100644 --- a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm +++ b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm @@ -34,8 +34,8 @@ unsuitable_atmos_damage = 0 damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) //I don't know how you'd apply those, but revenants no-sell them anyway. habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = 0 - maximum_survivable_temperature = INFINITY + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = INFINITY status_flags = NONE density = FALSE diff --git a/code/modules/mob/living/basic/space_fauna/robot_customer.dm b/code/modules/mob/living/basic/space_fauna/robot_customer.dm index e084e11f403c..e5c4a7dd0ead 100644 --- a/code/modules/mob/living/basic/space_fauna/robot_customer.dm +++ b/code/modules/mob/living/basic/space_fauna/robot_customer.dm @@ -15,8 +15,8 @@ sentience_type = SENTIENCE_ARTIFICIAL unsuitable_atmos_damage = 0 - minimum_survivable_temperature = TCMB - maximum_survivable_temperature = T0C + 1000 + bodytemp_cold_damage_limit = TCMB + bodytemp_heat_damage_limit = T0C + 1000 ai_controller = /datum/ai_controller/robot_customer diff --git a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spiders.dm b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spiders.dm index 92e27c4e3415..cb0340939573 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spiders.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spiders.dm @@ -386,8 +386,8 @@ /mob/living/basic/spider/giant/ice name = "giant ice spider" habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 1500 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 1500 color = rgb(114,228,250) gold_core_spawnable = NO_SPAWN menu_description = "Versatile ice spider variant for frontline combat with high health and damage. Immune to temperature damage." @@ -400,8 +400,8 @@ /mob/living/basic/spider/giant/nurse/ice name = "giant ice spider" habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 1500 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 1500 poison_type = /datum/reagent/consumable/frostoil color = rgb(114,228,250) menu_description = "Support ice spider variant specializing in healing their brethren and placing webbings very swiftly, but has very low amount of health and deals low damage. Immune to temperature damage." @@ -414,8 +414,8 @@ /mob/living/basic/spider/giant/hunter/ice name = "giant ice spider" habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 1500 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 1500 poison_type = /datum/reagent/consumable/frostoil color = rgb(114,228,250) gold_core_spawnable = NO_SPAWN diff --git a/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm b/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm index 02fd9ed1bcf1..d4b1a79ffece 100644 --- a/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm +++ b/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm @@ -20,8 +20,8 @@ maxHealth = 10 health = 10 - minimum_survivable_temperature = TCMB - maximum_survivable_temperature = T0C + 1250 + bodytemp_cold_damage_limit = TCMB + bodytemp_heat_damage_limit = T0C + 1250 habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) death_message = "falls to the ground, its shard dulling to a miserable grey!" diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm index d963bdf41016..0c01693190f9 100644 --- a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm +++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm @@ -42,8 +42,8 @@ lighting_cutoff_green = 10 lighting_cutoff_blue = 40 habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = 0 - maximum_survivable_temperature = INFINITY + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = INFINITY ai_controller = /datum/ai_controller/basic_controller/wumborian_fugu /// Ability used by the mob to become large, dangerous, and invulnerable var/datum/action/cooldown/fugu_expand/expand diff --git a/code/modules/mob/living/basic/tree.dm b/code/modules/mob/living/basic/tree.dm index 5d20a877e9f7..23a34a7c1264 100644 --- a/code/modules/mob/living/basic/tree.dm +++ b/code/modules/mob/living/basic/tree.dm @@ -36,8 +36,8 @@ habitable_atmos = list("min_oxy" = 2, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) unsuitable_atmos_damage = 2.5 - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 1200 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 1200 death_message = "is hacked into pieces!" diff --git a/code/modules/mob/living/basic/trooper/syndicate.dm b/code/modules/mob/living/basic/trooper/syndicate.dm index 2c6923a63f9a..f838e7650603 100644 --- a/code/modules/mob/living/basic/trooper/syndicate.dm +++ b/code/modules/mob/living/basic/trooper/syndicate.dm @@ -15,7 +15,7 @@ health = 170 loot = list(/obj/effect/gibspawner/human) unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 + bodytemp_cold_damage_limit = -1 mob_spawner = /obj/effect/mob_spawn/corpse/human/syndicatecommando /mob/living/basic/trooper/syndicate/space/Initialize(mapload) @@ -51,7 +51,7 @@ maxHealth = 170 health = 170 unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 + bodytemp_cold_damage_limit = -1 mob_spawner = /obj/effect/mob_spawn/corpse/human/syndicatecommando /mob/living/basic/trooper/syndicate/melee/space/Initialize(mapload) @@ -84,7 +84,7 @@ maxHealth = 170 health = 170 unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 + bodytemp_cold_damage_limit = -1 projectile_deflect_chance = 50 mob_spawner = /obj/effect/mob_spawn/corpse/human/syndicatecommando @@ -135,7 +135,7 @@ maxHealth = 170 health = 170 unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 + bodytemp_cold_damage_limit = -1 mob_spawner = /obj/effect/mob_spawn/corpse/human/syndicatecommando /mob/living/basic/trooper/syndicate/ranged/space/Initialize(mapload) @@ -167,7 +167,7 @@ maxHealth = 170 health = 170 unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 + bodytemp_cold_damage_limit = -1 mob_spawner = /obj/effect/mob_spawn/corpse/human/syndicatecommando /mob/living/basic/trooper/syndicate/ranged/smg/space/Initialize(mapload) @@ -193,7 +193,7 @@ maxHealth = 170 health = 170 unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 + bodytemp_cold_damage_limit = -1 speed = 1 mob_spawner = /obj/effect/mob_spawn/corpse/human/syndicatecommando @@ -220,8 +220,8 @@ mob_biotypes = MOB_ROBOTIC basic_mob_flags = DEL_ON_DEATH unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 700 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 700 unsuitable_cold_damage = 0 health = 25 maxHealth = 25 diff --git a/code/modules/mob/living/basic/vermin/cockroach.dm b/code/modules/mob/living/basic/vermin/cockroach.dm index c55b94cd0182..b4b10290f2d5 100644 --- a/code/modules/mob/living/basic/vermin/cockroach.dm +++ b/code/modules/mob/living/basic/vermin/cockroach.dm @@ -26,8 +26,8 @@ faction = list(FACTION_HOSTILE, FACTION_MAINT_CREATURES) unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 270 - maximum_survivable_temperature = INFINITY + bodytemp_cold_damage_limit = 270 + bodytemp_heat_damage_limit = INFINITY ai_controller = /datum/ai_controller/basic_controller/cockroach diff --git a/code/modules/mob/living/basic/vermin/lizard.dm b/code/modules/mob/living/basic/vermin/lizard.dm index 780ed6ee981e..350fca5c0046 100644 --- a/code/modules/mob/living/basic/vermin/lizard.dm +++ b/code/modules/mob/living/basic/vermin/lizard.dm @@ -71,8 +71,8 @@ icon_state = "lizard_space" icon_living = "lizard_space" unsuitable_atmos_damage = 0 - minimum_survivable_temperature = TCMB - maximum_survivable_temperature = T0C + 40 + bodytemp_cold_damage_limit = TCMB + bodytemp_heat_damage_limit = T0C + 40 /// Janitor's pet lizard. /mob/living/basic/lizard/wags_his_tail diff --git a/code/modules/mob/living/carbon/alien/adult/life.dm b/code/modules/mob/living/carbon/alien/adult/life.dm deleted file mode 100644 index 8aeb32ed657f..000000000000 --- a/code/modules/mob/living/carbon/alien/adult/life.dm +++ /dev/null @@ -1,18 +0,0 @@ - - -/mob/living/carbon/alien/adult/proc/adjust_body_temperature(current, loc_temp, boost) - var/temperature = current - var/difference = abs(current-loc_temp) //get difference - var/increments// = difference/10 //find how many increments apart they are - if(difference > 50) - increments = difference/5 - else - increments = difference/10 - var/change = increments*boost // Get the amount to change by (x per increment) - var/temp_change - if(current < loc_temp) - temperature = min(loc_temp, temperature+change) - else if(current > loc_temp) - temperature = max(loc_temp, temperature-change) - temp_change = (temperature - current) - return temp_change diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 44d0d4322f8b..a6b57e32ecb6 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -13,7 +13,8 @@ status_flags = CANUNCONSCIOUS|CANPUSH - heat_protection = 0.5 // minor heat insulation + temperature_insulation = 0.5 // minor heat insulation + bodytemp_heat_damage_limit = CELCIUS_TO_KELVIN(85 CELCIUS) var/leaping = FALSE gib_type = /obj/effect/decal/cleanable/xenoblood/xgibs @@ -45,24 +46,9 @@ /mob/living/carbon/alien/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null) // beepsky won't hunt aliums return -10 -/mob/living/carbon/alien/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) - // Run base mob body temperature proc before taking damage - // this balances body temp to the environment and natural stabilization - . = ..() - - if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT) - //Body temperature is too hot. +/mob/living/carbon/alien/body_temperature_alerts() + if(bodytemperature > bodytemp_heat_damage_limit) throw_alert(ALERT_XENO_FIRE, /atom/movable/screen/alert/alien_fire) - switch(bodytemperature) - if(360 to 400) - apply_damage(HEAT_DAMAGE_LEVEL_1 * seconds_per_tick, BURN) - if(400 to 460) - apply_damage(HEAT_DAMAGE_LEVEL_2 * seconds_per_tick, BURN) - if(460 to INFINITY) - if(on_fire) - apply_damage(HEAT_DAMAGE_LEVEL_3 * seconds_per_tick, BURN) - else - apply_damage(HEAT_DAMAGE_LEVEL_2 * seconds_per_tick, BURN) else clear_alert(ALERT_XENO_FIRE) diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index c7c65f4d684c..4172767adb3c 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -117,6 +117,3 @@ In all, this is a lot like the monkey code. /N /mob/living/carbon/alien/acid_act(acidpwr, acid_volume) return FALSE//aliens are immune to acid. - -/mob/living/carbon/alien/on_fire_stack(seconds_per_tick, times_fired, datum/status_effect/fire_handler/fire_stacks/fire_handler) - adjust_bodytemperature((BODYTEMP_HEATING_MAX + (fire_handler.stacks * 12)) * 0.5 * seconds_per_tick) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index b0c04e8f2eb9..0d50efac626b 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -529,14 +529,14 @@ add_mood_event("hug", /datum/mood_event/bad_touch_bear_hug) // Let people know if they hugged someone really warm or really cold - if(helper.bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT) + if(helper.bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT && !HAS_TRAIT(src, TRAIT_RESISTHEAT)) to_chat(src, span_warning("It feels like [helper] is over heating as [helper.p_they()] hug[helper.p_s()] you.")) - else if(helper.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT) + else if(helper.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !HAS_TRAIT(src, TRAIT_RESISTCOLD)) to_chat(src, span_warning("It feels like [helper] is freezing as [helper.p_they()] hug[helper.p_s()] you.")) - if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT) + if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT && !HAS_TRAIT(src, TRAIT_RESISTHEAT)) to_chat(helper, span_warning("It feels like [src] is over heating as you hug [p_them()].")) - else if(bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT) + else if(bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !HAS_TRAIT(src, TRAIT_RESISTCOLD)) to_chat(helper, span_warning("It feels like [src] is freezing as you hug [p_them()].")) if(HAS_TRAIT(helper, TRAIT_FRIENDLY)) diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 3e884ae3b476..772a98b4abc8 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -88,11 +88,6 @@ /// This number is also reset to 0 every tick of carbon Life(). Pain. var/damageoverlaytemp = 0 - /// Protection (insulation) from the heat, Value 0-1 corresponding to the percentage of protection - var/heat_protection = 0 // No heat protection - /// Protection (insulation) from the cold, Value 0-1 corresponding to the percentage of protection - var/cold_protection = 0 // No cold protection - /// Timer id of any transformation var/transformation_timer diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index 1cc850789f0b..3ba6279e862c 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -277,13 +277,13 @@ return hands /mob/living/carbon/get_fire_overlay(stacks, on_fire) - var/fire_icon = "[dna?.species.fire_overlay || "human"]_[stacks > MOB_BIG_FIRE_STACK_THRESHOLD ? "big_fire" : "small_fire"]" + var/fire_icon = "[dna?.species?.fire_overlay || "human"]_[stacks > MOB_BIG_FIRE_STACK_THRESHOLD ? "big_fire" : "small_fire"]" if(!GLOB.fire_appearances[fire_icon]) GLOB.fire_appearances[fire_icon] = mutable_appearance( - 'icons/mob/effects/onfire.dmi', - fire_icon, - -HIGHEST_LAYER, + icon = dna?.species?.fire_dmi || 'icons/mob/effects/onfire.dmi', + icon_state = fire_icon, + layer = -HIGHEST_LAYER, appearance_flags = RESET_COLOR, ) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index bd0a75c88735..8890ba61fa1b 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -119,17 +119,23 @@ GLOBAL_LIST_EMPTY(features_by_species) //Dictates which wing icons are allowed for a given species. If count is >1 a radial menu is used to choose between all icons in list var/list/wing_types = list(/obj/item/organ/external/wings/functional/angel) + // Do not READ these temperature related properties, use the living level ones instead + // These are deprecated and only exist to set in [/proc/on_species_gain] /// The natural temperature for a body - var/bodytemp_normal = BODYTEMP_NORMAL - /// Minimum amount of kelvin moved toward normal body temperature per tick. - var/bodytemp_autorecovery_min = BODYTEMP_AUTORECOVERY_MINIMUM + VAR_PROTECTED/bodytemp_normal = /mob/living/carbon/human::standard_body_temperature + /// Modifier to how fast/slow the body normalizes its temperature to the environment. + VAR_PROTECTED/temperature_normalization_speed = /mob/living/carbon/human::temperature_normalization_speed + /// Modifier to how fast/slow the body normalizes its temperature to standard temp + VAR_PROTECTED/temperature_homeostasis_speed = /mob/living/carbon/human::temperature_homeostasis_speed /// The body temperature limit the body can take before it starts taking damage from heat. - var/bodytemp_heat_damage_limit = BODYTEMP_HEAT_DAMAGE_LIMIT + VAR_PROTECTED/bodytemp_heat_damage_limit = /mob/living/carbon/human::bodytemp_heat_damage_limit /// The body temperature limit the body can take before it starts taking damage from cold. - var/bodytemp_cold_damage_limit = BODYTEMP_COLD_DAMAGE_LIMIT + VAR_PROTECTED/bodytemp_cold_damage_limit = /mob/living/carbon/human::bodytemp_cold_damage_limit /// The icon_state of the fire overlay added when sufficently ablaze and standing. see onfire.dmi - var/fire_overlay = "human" + var/fire_overlay + /// The icon of the fire overlay added when sufficently ablaze + var/fire_dmi ///Species-only traits. Can be found in [code/__DEFINES/DNA.dm] var/list/species_traits = list() @@ -513,7 +519,7 @@ GLOBAL_LIST_EMPTY(features_by_species) * * old_species - The species that the carbon used to be before becoming this race, used for regenerating organs. * * pref_load - Preferences to be loaded from character setup, loads in preferred mutant things like bodyparts, digilegs, skin color, etc. */ -/datum/species/proc/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) +/datum/species/proc/on_species_gain(mob/living/carbon/human/C, datum/species/old_species, pref_load) SHOULD_CALL_PARENT(TRUE) // Drop the items the new species can't wear SEND_SIGNAL(C, COMSIG_SPECIES_GAIN_PRE, src, old_species) @@ -530,6 +536,15 @@ GLOBAL_LIST_EMPTY(features_by_species) C.mob_biotypes = inherent_biotypes C.mob_respiration_type = inherent_respiration_type + C.standard_body_temperature = src.bodytemp_normal + C.bodytemperature = src.bodytemp_normal + C.bodytemp_heat_damage_limit = src.bodytemp_heat_damage_limit + C.bodytemp_cold_damage_limit = src.bodytemp_cold_damage_limit + C.temperature_normalization_speed = src.temperature_normalization_speed + C.temperature_homeostasis_speed = src.temperature_homeostasis_speed + + C.physiology?.cold_mod *= coldmod + C.physiology?.heat_mod *= heatmod if (old_species.type != type) replace_body(C, src) @@ -614,6 +629,9 @@ GLOBAL_LIST_EMPTY(features_by_species) clear_tail_moodlets(C) + C.physiology?.cold_mod /= coldmod + C.physiology?.heat_mod /= heatmod + C.maxHealth = C.maxHealth / maxhealthmod SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src) @@ -1466,319 +1484,6 @@ GLOBAL_LIST_EMPTY(features_by_species) return TRUE -////////////////////////// -// ENVIRONMENT HANDLERS // -////////////////////////// - -/** - * Environment handler for species - * - * vars: - * * environment (required) The environment gas mix - * * humi (required)(type: /mob/living/carbon/human) The mob we will target - */ -/datum/species/proc/handle_environment(mob/living/carbon/human/humi, datum/gas_mixture/environment, seconds_per_tick, times_fired) - handle_environment_pressure(humi, environment, seconds_per_tick, times_fired) - -/** - * Body temperature handler for species - * - * These procs manage body temp, bamage, and alerts - * Some of these will still fire when not alive to balance body temp to the room temp. - * vars: - * * humi (required)(type: /mob/living/carbon/human) The mob we will target - */ -/datum/species/proc/handle_body_temperature(mob/living/carbon/human/humi, seconds_per_tick, times_fired) - //when in a cryo unit we suspend all natural body regulation - if(istype(humi.loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) - return - - //Only stabilise core temp when alive and not in statis - if(humi.stat < DEAD && !HAS_TRAIT(humi, TRAIT_STASIS)) - body_temperature_core(humi, seconds_per_tick, times_fired) - - //These do run in statis - body_temperature_skin(humi, seconds_per_tick, times_fired) - body_temperature_alerts(humi, seconds_per_tick, times_fired) - - //Do not cause more damage in statis - if(!HAS_TRAIT(humi, TRAIT_STASIS)) - body_temperature_damage(humi, seconds_per_tick, times_fired) - -/** - * Used to stabilize the core temperature back to normal on living mobs - * - * The metabolisim heats up the core of the mob trying to keep it at the normal body temp - * vars: - * * humi (required) The mob we will stabilize - */ -/datum/species/proc/body_temperature_core(mob/living/carbon/human/humi, seconds_per_tick, times_fired) - var/natural_change = get_temp_change_amount(humi.get_body_temp_normal() - humi.coretemperature, 0.06 * seconds_per_tick) - humi.adjust_coretemperature(humi.metabolism_efficiency * natural_change) - -/** - * Used to normalize the skin temperature on living mobs - * - * The core temp effects the skin, then the enviroment effects the skin, then we refect that back to the core. - * This happens even when dead so bodies revert to room temp over time. - * vars: - * * humi (required) The mob we will targeting - * - seconds_per_tick: The amount of time that is considered as elapsing - * - times_fired: The number of times SSmobs has fired - */ -/datum/species/proc/body_temperature_skin(mob/living/carbon/human/humi, seconds_per_tick, times_fired) - - // change the core based on the skin temp - var/skin_core_diff = humi.bodytemperature - humi.coretemperature - // change rate of 0.04 per second to be slightly below area to skin change rate and still have a solid curve - var/skin_core_change = get_temp_change_amount(skin_core_diff, 0.04 * seconds_per_tick) - - humi.adjust_coretemperature(skin_core_change) - - // get the enviroment details of where the mob is standing - var/datum/gas_mixture/environment = humi.loc.return_air() - if(!environment) // if there is no environment (nullspace) drop out here. - return - - // Get the temperature of the environment for area - var/area_temp = humi.get_temperature(environment) - - // Get the insulation value based on the area's temp - var/thermal_protection = humi.get_insulation_protection(area_temp) - - // Changes to the skin temperature based on the area - var/area_skin_diff = area_temp - humi.bodytemperature - if(!humi.on_fire || area_skin_diff > 0) - // change rate of 0.05 as area temp has large impact on the surface - var/area_skin_change = get_temp_change_amount(area_skin_diff, 0.05 * seconds_per_tick) - - // We need to apply the thermal protection of the clothing when applying area to surface change - // If the core bodytemp goes over the normal body temp you are overheating and becom sweaty - // This will cause the insulation value of any clothing to reduced in effect (70% normal rating) - // we add 10 degree over normal body temp before triggering as thick insulation raises body temp - if(humi.get_body_temp_normal(apply_change=FALSE) + 10 < humi.coretemperature) - // we are overheating and sweaty insulation is not as good reducing thermal protection - area_skin_change = (1 - (thermal_protection * 0.7)) * area_skin_change - else - area_skin_change = (1 - thermal_protection) * area_skin_change - - humi.adjust_bodytemperature(area_skin_change) - - // Core to skin temp transfer, when not on fire - if(!humi.on_fire) - // Get the changes to the skin from the core temp - var/core_skin_diff = humi.coretemperature - humi.bodytemperature - // change rate of 0.045 to reflect temp back to the skin at the slight higher rate then core to skin - var/core_skin_change = (1 + thermal_protection) * get_temp_change_amount(core_skin_diff, 0.045 * seconds_per_tick) - - // We do not want to over shoot after using protection - if(core_skin_diff > 0) - core_skin_change = min(core_skin_change, core_skin_diff) - else - core_skin_change = max(core_skin_change, core_skin_diff) - - humi.adjust_bodytemperature(core_skin_change) - - -/** - * Used to set alerts and debuffs based on body temperature - * vars: - * * humi (required) The mob we will targeting - */ -/datum/species/proc/body_temperature_alerts(mob/living/carbon/human/humi) - var/old_bodytemp = humi.old_bodytemperature - var/bodytemp = humi.bodytemperature - // Body temperature is too hot, and we do not have resist traits - if(bodytemp > bodytemp_heat_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTHEAT)) - // Clear cold mood and apply hot mood - humi.clear_mood_event("cold") - humi.add_mood_event("hot", /datum/mood_event/hot) - - //Remove any slowdown from the cold. - humi.remove_movespeed_modifier(/datum/movespeed_modifier/cold) - // display alerts based on how hot it is - // Can't be a switch due to http://www.byond.com/forum/post/2750423 - if(bodytemp in bodytemp_heat_damage_limit to BODYTEMP_HEAT_WARNING_2) - humi.apply_status_effect(/datum/status_effect/thermia/hyper/one) - else if(bodytemp in BODYTEMP_HEAT_WARNING_2 to BODYTEMP_HEAT_WARNING_3) - humi.apply_status_effect(/datum/status_effect/thermia/hyper/two) - else - humi.apply_status_effect(/datum/status_effect/thermia/hyper/three) - - // Body temperature is too cold, and we do not have resist traits - else if(bodytemp < bodytemp_cold_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTCOLD)) - var/slowdown_mod = (bodytemp_cold_damage_limit - humi.bodytemperature) / COLD_SLOWDOWN_FACTOR - // Display alerts based how cold it is - // Can't be a switch due to http://www.byond.com/forum/post/2750423 - if(bodytemp in BODYTEMP_COLD_WARNING_2 to bodytemp_cold_damage_limit) - humi.apply_status_effect(/datum/status_effect/thermia/hypo/one, slowdown_mod) - else if(bodytemp in BODYTEMP_COLD_WARNING_3 to BODYTEMP_COLD_WARNING_2) - humi.apply_status_effect(/datum/status_effect/thermia/hypo/two, slowdown_mod) - else - humi.apply_status_effect(/datum/status_effect/thermia/hypo/three, slowdown_mod) - - // We are not to hot or cold, remove status and moods - // Optimization here, we check these things based off the old temperature to avoid unneeded work - // We're not perfect about this, because it'd just add more work to the base case, and resistances are rare - else if (old_bodytemp > bodytemp_heat_damage_limit || old_bodytemp < bodytemp_cold_damage_limit) - humi.remove_status_effect(/datum/status_effect/thermia) - - // Store the old bodytemp for future checking - humi.old_bodytemperature = bodytemp - -/** - * Used to apply wounds and damage based on core/body temp - * vars: - * * humi (required) The mob we will targeting - */ -/datum/species/proc/body_temperature_damage(mob/living/carbon/human/humi, seconds_per_tick, times_fired) - - //If the body temp is above the wound limit start adding exposure stacks - if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT) - humi.heat_exposure_stacks = min(humi.heat_exposure_stacks + (0.5 * seconds_per_tick), 40) - else //When below the wound limit, reduce the exposure stacks fast. - humi.heat_exposure_stacks = max(humi.heat_exposure_stacks - (2 * seconds_per_tick), 0) - - //when exposure stacks are greater then 10 + rand20 try to apply wounds and reset stacks - if(humi.heat_exposure_stacks > (10 + rand(0, 20))) - apply_burn_wounds(humi, seconds_per_tick, times_fired) - humi.heat_exposure_stacks = 0 - - // Body temperature is too hot, and we do not have resist traits - // Apply some burn damage to the body - if(humi.coretemperature > bodytemp_heat_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTHEAT)) - var/firemodifier = humi.fire_stacks / 50 - if (!humi.on_fire) // We are not on fire, reduce the modifier - firemodifier = min(firemodifier, 0) - - // this can go below 5 at log 2.5 - var/burn_damage = max(log(2 - firemodifier, (humi.coretemperature - humi.get_body_temp_normal(apply_change=FALSE))) - 5, 0) - - // Apply species and physiology modifiers to heat damage - burn_damage = burn_damage * heatmod * humi.physiology.heat_mod * 0.5 * seconds_per_tick - - // 40% for level 3 damage on humans to scream in pain - if (humi.stat < UNCONSCIOUS && (prob(burn_damage) * 10) / 4) - humi.emote("scream") - - // Apply the damage to all body parts - humi.apply_damage(burn_damage, BURN, spread_damage = TRUE) - - // Apply some burn / brute damage to the body (Dependent if the person is hulk or not) - var/is_hulk = HAS_TRAIT(humi, TRAIT_HULK) - - var/cold_damage_limit = bodytemp_cold_damage_limit + (is_hulk ? BODYTEMP_HULK_COLD_DAMAGE_LIMIT_MODIFIER : 0) - - if(humi.coretemperature < cold_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTCOLD)) - var/damage_type = is_hulk ? BRUTE : BURN // Why? - var/damage_mod = coldmod * humi.physiology.cold_mod * (is_hulk ? HULK_COLD_DAMAGE_MOD : 1) - // Can't be a switch due to http://www.byond.com/forum/post/2750423 - if(humi.coretemperature in 201 to cold_damage_limit) - humi.apply_damage(COLD_DAMAGE_LEVEL_1 * damage_mod * seconds_per_tick, damage_type) - else if(humi.coretemperature in 120 to 200) - humi.apply_damage(COLD_DAMAGE_LEVEL_2 * damage_mod * seconds_per_tick, damage_type) - else - humi.apply_damage(COLD_DAMAGE_LEVEL_3 * damage_mod * seconds_per_tick, damage_type) - -/** - * Used to apply burn wounds on random limbs - * - * This is called from body_temperature_damage when exposure to extream heat adds up and causes a wound. - * The wounds will increase in severity as the temperature increases. - * vars: - * * humi (required) The mob we will targeting - */ -/datum/species/proc/apply_burn_wounds(mob/living/carbon/human/humi, seconds_per_tick, times_fired) - // If we are resistant to heat exit - if(HAS_TRAIT(humi, TRAIT_RESISTHEAT)) - return - - // If our body temp is to low for a wound exit - if(humi.bodytemperature < BODYTEMP_HEAT_WOUND_LIMIT) - return - - // Lets pick a random body part and check for an existing burn - var/obj/item/bodypart/bodypart = pick(humi.bodyparts) - var/datum/wound/existing_burn - for (var/datum/wound/iterated_wound as anything in bodypart.wounds) - var/datum/wound_pregen_data/pregen_data = iterated_wound.get_pregen_data() - if (pregen_data.wound_series in GLOB.wounding_types_to_series[WOUND_BURN]) - existing_burn = iterated_wound - break - // If we have an existing burn try to upgrade it - var/severity - if(existing_burn) - switch(existing_burn.severity) - if(WOUND_SEVERITY_MODERATE) - if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT + 400) // 800k - severity = WOUND_SEVERITY_SEVERE - if(WOUND_SEVERITY_SEVERE) - if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT + 2800) // 3200k - severity = WOUND_SEVERITY_CRITICAL - else // If we have no burn apply the lowest level burn - severity = WOUND_SEVERITY_MODERATE - - humi.cause_wound_of_type_and_severity(WOUND_BURN, bodypart, severity, wound_source = "hot temperatures") - - // always take some burn damage - var/burn_damage = HEAT_DAMAGE_LEVEL_1 - if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT + 400) - burn_damage = HEAT_DAMAGE_LEVEL_2 - if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT + 2800) - burn_damage = HEAT_DAMAGE_LEVEL_3 - - humi.apply_damage(burn_damage * seconds_per_tick, BURN, bodypart) - -/// Handle the air pressure of the environment -/datum/species/proc/handle_environment_pressure(mob/living/carbon/human/H, datum/gas_mixture/environment, seconds_per_tick, times_fired) - var/pressure = environment.return_pressure() - var/adjusted_pressure = H.calculate_affecting_pressure(pressure) - - // Set alerts and apply damage based on the amount of pressure - switch(adjusted_pressure) - // Very high pressure, show an alert and take damage - if(HAZARD_HIGH_PRESSURE to INFINITY) - if(HAS_TRAIT(H, TRAIT_RESISTHIGHPRESSURE)) - H.clear_alert(ALERT_PRESSURE) - else - var/pressure_damage = min(((adjusted_pressure / HAZARD_HIGH_PRESSURE) - 1) * PRESSURE_DAMAGE_COEFFICIENT, MAX_HIGH_PRESSURE_DAMAGE) * H.physiology.pressure_mod * H.physiology.brute_mod * seconds_per_tick - H.adjustBruteLoss(pressure_damage, required_bodytype = BODYTYPE_ORGANIC) - H.throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/highpressure, 2) - - // High pressure, show an alert - if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE) - H.throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/highpressure, 1) - - // No pressure issues here clear pressure alerts - if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE) - H.clear_alert(ALERT_PRESSURE) - - // Low pressure here, show an alert - if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE) - // We have low pressure resit trait, clear alerts - if(HAS_TRAIT(H, TRAIT_RESISTLOWPRESSURE)) - H.clear_alert(ALERT_PRESSURE) - else - H.throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/lowpressure, 1) - - // Very low pressure, show an alert and take damage - else - // We have low pressure resit trait, clear alerts - if(HAS_TRAIT(H, TRAIT_RESISTLOWPRESSURE)) - H.clear_alert(ALERT_PRESSURE) - else - var/pressure_damage = LOW_PRESSURE_DAMAGE * H.physiology.pressure_mod * H.physiology.brute_mod * seconds_per_tick - H.adjustBruteLoss(pressure_damage, required_bodytype = BODYTYPE_ORGANIC) - H.throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/lowpressure, 2) - - -////////// -// FIRE // -////////// - -/datum/species/proc/handle_fire(mob/living/carbon/human/H, seconds_per_tick, times_fired, no_protection = FALSE) - return no_protection - //////////// // Stun // //////////// diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 7f1950d5ac1d..da1a93ed6802 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -98,7 +98,7 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift) return "alcohol poisoning" if("thermia") - if(bodytemperature < get_body_temp_normal()) + if(bodytemperature < standard_body_temperature) return "hypothermia" return "hyperthermia" diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 5b9cd941a310..a2f8a08f39f5 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -334,9 +334,9 @@ msg += "[t_He] appear[p_s()] to be staring off into space.\n" if (HAS_TRAIT(src, TRAIT_DEAF)) msg += "[t_He] appear[p_s()] to not be responding to noises.\n" - if (bodytemperature > dna.species.bodytemp_heat_damage_limit) + if (bodytemperature > bodytemp_heat_damage_limit) msg += "[t_He] [t_is] flushed and wheezing.\n" - if (bodytemperature < dna.species.bodytemp_cold_damage_limit) + if (bodytemperature < bodytemp_cold_damage_limit) msg += "[t_He] [t_is] shivering.\n" msg += "
" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b9bd66482014..f6440d911444 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -715,11 +715,6 @@ for(var/datum/mutation/human/existing_mutation in dna.mutations) if(existing_mutation.quality != POSITIVE) dna.remove_mutation(existing_mutation.name) - - if(heal_flags & HEAL_TEMP) - set_coretemperature(get_body_temp_normal(apply_change = FALSE)) - heat_exposure_stacks = 0 - return ..() /mob/living/carbon/human/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, vomit_type = VOMIT_TOXIC, harm = TRUE, force = FALSE, purge_ratio = 0.1) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index a51504d92cd9..93f4311d2976 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -900,9 +900,19 @@ burning.fire_act((stacks * 25 * seconds_per_tick)) //damage taken is reduced to 2% of this value by fire_act() /mob/living/carbon/human/on_fire_stack(seconds_per_tick, times_fired, datum/status_effect/fire_handler/fire_stacks/fire_handler) - SEND_SIGNAL(src, COMSIG_HUMAN_BURNING) - burn_clothing(seconds_per_tick, times_fired, fire_handler.stacks) - var/no_protection = FALSE - if(dna && dna.species) - no_protection = dna.species.handle_fire(src, seconds_per_tick, times_fired, no_protection) - fire_handler.harm_human(seconds_per_tick, times_fired, no_protection) + var/sigreturn = SEND_SIGNAL(src, COMSIG_HUMAN_BURNING) + if(sigreturn & BURNING_HANDLED) + return FALSE + + burn_clothing(seconds_per_tick, fire_handler.stacks) + if(!(sigreturn & BURNING_SKIP_PROTECTION)) + if(get_insulation(FIRE_IMMUNITY_MAX_TEMP_PROTECT) >= 0.9) + return FALSE + if(get_insulation(FIRE_SUIT_MAX_TEMP_PROTECT) >= 0.9) + return adjust_bodytemperature(0.5 KELVIN * seconds_per_tick) + + . = ..() + if(.) + add_mood_event("on_fire", /datum/mood_event/on_fire) + add_mob_memory(/datum/memory/was_burning) + return . diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 9c5a1a90bbb0..09e3634de601 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -13,6 +13,9 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID can_be_shoved_into = TRUE + bodytemp_cold_damage_limit = BODYTEMP_COLD_DAMAGE_LIMIT + bodytemp_heat_damage_limit = BODYTEMP_HEAT_DAMAGE_LIMIT + //Hair colour and style var/hair_color = "#000000" var/hairstyle = "Bald" @@ -80,12 +83,6 @@ /// How many "units of blood" we have on our hands var/blood_in_hands = 0 - /// The core temperature of the human compaired to the skin temp of the body - var/coretemperature = BODYTEMP_NORMAL - - ///Exposure to damaging heat levels increases stacks, stacks clean over time when temperatures are lower. Stack is consumed to add a wound. - var/heat_exposure_stacks = 0 - /// When an braindead player has their equipment fiddled with, we log that info here for when they come back so they know who took their ID while they were DC'd for 30 seconds var/list/afk_thefts diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 8a5d6e94bdd1..9f9a27e6adcf 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1,22 +1,7 @@ - -//NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick! - -// bitflags for the percentual amount of protection a piece of clothing which covers the body part offers. -// Used with human/proc/get_heat_protection() and human/proc/get_cold_protection() -// The values here should add up to 1. -// Hands and feet have 2.5%, arms and legs 7.5%, each of the torso parts has 15% and the head has 30% -#define THERMAL_PROTECTION_HEAD 0.3 -#define THERMAL_PROTECTION_CHEST 0.15 -#define THERMAL_PROTECTION_GROIN 0.15 -#define THERMAL_PROTECTION_LEG_LEFT 0.075 -#define THERMAL_PROTECTION_LEG_RIGHT 0.075 -#define THERMAL_PROTECTION_FOOT_LEFT 0.025 -#define THERMAL_PROTECTION_FOOT_RIGHT 0.025 -#define THERMAL_PROTECTION_ARM_LEFT 0.075 -#define THERMAL_PROTECTION_ARM_RIGHT 0.075 -#define THERMAL_PROTECTION_HAND_LEFT 0.025 -#define THERMAL_PROTECTION_HAND_RIGHT 0.025 +// NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. +// In which case it happens once per ONE TICK! +// So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick! /mob/living/carbon/human/Life(seconds_per_tick = SSMOBS_DT, times_fired) if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM)) @@ -26,9 +11,6 @@ if(QDELETED(src)) return FALSE - //Body temperature stability and damage - dna.species.handle_body_temperature(src, seconds_per_tick, times_fired) - if(!HAS_TRAIT(src, TRAIT_STASIS)) if(.) //not dead @@ -91,179 +73,6 @@ throw_alert(ALERT_NOT_ENOUGH_NITRO, /atom/movable/screen/alert/not_enough_nitro) return FALSE -/// Environment handlers for species -/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) - // If we are in a cryo bed do not process life functions - if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) - return - - dna.species.handle_environment(src, environment, seconds_per_tick, times_fired) - -/** - * Adjust the core temperature of a mob - * - * vars: - * * amount The amount of degrees to change body temperature by - * * min_temp (optional) The minimum body temperature after adjustment - * * max_temp (optional) The maximum body temperature after adjustment - */ -/mob/living/carbon/human/proc/adjust_coretemperature(amount, min_temp=0, max_temp=INFINITY) - set_coretemperature(clamp(coretemperature + amount, min_temp, max_temp)) - -/mob/living/carbon/human/proc/set_coretemperature(value) - SEND_SIGNAL(src, COMSIG_HUMAN_CORETEMP_CHANGE, coretemperature, value) - coretemperature = value - -/** - * get_body_temperature Returns the body temperature with any modifications applied - * - * This applies the result from proc/get_body_temp_normal_change() against the bodytemp_normal - * for the species and returns the result - * - * arguments: - * * apply_change (optional) Default True This applies the changes to body temperature normal - */ -/mob/living/carbon/human/get_body_temp_normal(apply_change=TRUE) - if(!apply_change) - return dna.species.bodytemp_normal - return dna.species.bodytemp_normal + get_body_temp_normal_change() - -/mob/living/carbon/human/get_body_temp_heat_damage_limit() - return dna.species.bodytemp_heat_damage_limit - -/mob/living/carbon/human/get_body_temp_cold_damage_limit() - return dna.species.bodytemp_cold_damage_limit - -/mob/living/carbon/human/proc/get_thermal_protection() - var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures - if(wear_suit) - if((wear_suit.heat_protection & CHEST) && (wear_suit.max_heat_protection_temperature >= FIRE_SUIT_MAX_TEMP_PROTECT)) - thermal_protection += (wear_suit.max_heat_protection_temperature * 0.7) - if(head) - if((head.heat_protection & HEAD) && (head.max_heat_protection_temperature >= FIRE_HELM_MAX_TEMP_PROTECT)) - thermal_protection += (head.max_heat_protection_temperature * THERMAL_PROTECTION_HEAD) - thermal_protection = round(thermal_protection) - return thermal_protection - -//END FIRE CODE - -//This proc returns a number made up of the flags for body parts which you are protected on. (such as HEAD, CHEST, GROIN, etc. See setup.dm for the full list) -/mob/living/carbon/human/proc/get_heat_protection_flags(temperature) //Temperature is the temperature you're being exposed to. - var/thermal_protection_flags = 0 - //Handle normal clothing - if(head) - if(head.max_heat_protection_temperature && head.max_heat_protection_temperature >= temperature) - thermal_protection_flags |= head.heat_protection - if(wear_suit) - if(wear_suit.max_heat_protection_temperature && wear_suit.max_heat_protection_temperature >= temperature) - thermal_protection_flags |= wear_suit.heat_protection - if(w_uniform) - if(w_uniform.max_heat_protection_temperature && w_uniform.max_heat_protection_temperature >= temperature) - thermal_protection_flags |= w_uniform.heat_protection - if(shoes) - if(shoes.max_heat_protection_temperature && shoes.max_heat_protection_temperature >= temperature) - thermal_protection_flags |= shoes.heat_protection - if(gloves) - if(gloves.max_heat_protection_temperature && gloves.max_heat_protection_temperature >= temperature) - thermal_protection_flags |= gloves.heat_protection - if(wear_mask) - if(wear_mask.max_heat_protection_temperature && wear_mask.max_heat_protection_temperature >= temperature) - thermal_protection_flags |= wear_mask.heat_protection - - return thermal_protection_flags - -/mob/living/carbon/human/get_heat_protection(temperature) - var/thermal_protection_flags = get_heat_protection_flags(temperature) - var/thermal_protection = heat_protection - - // Apply clothing items protection - if(thermal_protection_flags) - if(thermal_protection_flags & HEAD) - thermal_protection += THERMAL_PROTECTION_HEAD - if(thermal_protection_flags & CHEST) - thermal_protection += THERMAL_PROTECTION_CHEST - if(thermal_protection_flags & GROIN) - thermal_protection += THERMAL_PROTECTION_GROIN - if(thermal_protection_flags & LEG_LEFT) - thermal_protection += THERMAL_PROTECTION_LEG_LEFT - if(thermal_protection_flags & LEG_RIGHT) - thermal_protection += THERMAL_PROTECTION_LEG_RIGHT - if(thermal_protection_flags & FOOT_LEFT) - thermal_protection += THERMAL_PROTECTION_FOOT_LEFT - if(thermal_protection_flags & FOOT_RIGHT) - thermal_protection += THERMAL_PROTECTION_FOOT_RIGHT - if(thermal_protection_flags & ARM_LEFT) - thermal_protection += THERMAL_PROTECTION_ARM_LEFT - if(thermal_protection_flags & ARM_RIGHT) - thermal_protection += THERMAL_PROTECTION_ARM_RIGHT - if(thermal_protection_flags & HAND_LEFT) - thermal_protection += THERMAL_PROTECTION_HAND_LEFT - if(thermal_protection_flags & HAND_RIGHT) - thermal_protection += THERMAL_PROTECTION_HAND_RIGHT - - return min(1, thermal_protection) - -//See proc/get_heat_protection_flags(temperature) for the description of this proc. -/mob/living/carbon/human/proc/get_cold_protection_flags(temperature) - var/thermal_protection_flags = 0 - //Handle normal clothing - - if(head) - if(head.min_cold_protection_temperature && head.min_cold_protection_temperature <= temperature) - thermal_protection_flags |= head.cold_protection - if(wear_suit) - if(wear_suit.min_cold_protection_temperature && wear_suit.min_cold_protection_temperature <= temperature) - thermal_protection_flags |= wear_suit.cold_protection - if(w_uniform) - if(w_uniform.min_cold_protection_temperature && w_uniform.min_cold_protection_temperature <= temperature) - thermal_protection_flags |= w_uniform.cold_protection - if(shoes) - if(shoes.min_cold_protection_temperature && shoes.min_cold_protection_temperature <= temperature) - thermal_protection_flags |= shoes.cold_protection - if(gloves) - if(gloves.min_cold_protection_temperature && gloves.min_cold_protection_temperature <= temperature) - thermal_protection_flags |= gloves.cold_protection - if(wear_mask) - if(wear_mask.min_cold_protection_temperature && wear_mask.min_cold_protection_temperature <= temperature) - thermal_protection_flags |= wear_mask.cold_protection - - return thermal_protection_flags - -/mob/living/carbon/human/get_cold_protection(temperature) - // There is an occasional bug where the temperature is miscalculated in areas with small amounts of gas. - // This is necessary to ensure that does not affect this calculation. - // Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K. - temperature = max(temperature, 2.7) - var/thermal_protection_flags = get_cold_protection_flags(temperature) - var/thermal_protection = cold_protection - - // Apply clothing items protection - if(thermal_protection_flags) - if(thermal_protection_flags & HEAD) - thermal_protection += THERMAL_PROTECTION_HEAD - if(thermal_protection_flags & CHEST) - thermal_protection += THERMAL_PROTECTION_CHEST - if(thermal_protection_flags & GROIN) - thermal_protection += THERMAL_PROTECTION_GROIN - if(thermal_protection_flags & LEG_LEFT) - thermal_protection += THERMAL_PROTECTION_LEG_LEFT - if(thermal_protection_flags & LEG_RIGHT) - thermal_protection += THERMAL_PROTECTION_LEG_RIGHT - if(thermal_protection_flags & FOOT_LEFT) - thermal_protection += THERMAL_PROTECTION_FOOT_LEFT - if(thermal_protection_flags & FOOT_RIGHT) - thermal_protection += THERMAL_PROTECTION_FOOT_RIGHT - if(thermal_protection_flags & ARM_LEFT) - thermal_protection += THERMAL_PROTECTION_ARM_LEFT - if(thermal_protection_flags & ARM_RIGHT) - thermal_protection += THERMAL_PROTECTION_ARM_RIGHT - if(thermal_protection_flags & HAND_LEFT) - thermal_protection += THERMAL_PROTECTION_HAND_LEFT - if(thermal_protection_flags & HAND_RIGHT) - thermal_protection += THERMAL_PROTECTION_HAND_RIGHT - - return min(1, thermal_protection) - /mob/living/carbon/human/handle_random_events(seconds_per_tick, times_fired) //Puke if toxloss is too high if(stat) @@ -302,14 +111,3 @@ // Tissues die without blood circulation adjustBruteLoss(1 * seconds_per_tick) -#undef THERMAL_PROTECTION_HEAD -#undef THERMAL_PROTECTION_CHEST -#undef THERMAL_PROTECTION_GROIN -#undef THERMAL_PROTECTION_LEG_LEFT -#undef THERMAL_PROTECTION_LEG_RIGHT -#undef THERMAL_PROTECTION_FOOT_LEFT -#undef THERMAL_PROTECTION_FOOT_RIGHT -#undef THERMAL_PROTECTION_ARM_LEFT -#undef THERMAL_PROTECTION_ARM_RIGHT -#undef THERMAL_PROTECTION_HAND_LEFT -#undef THERMAL_PROTECTION_HAND_RIGHT diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 0423d940adcb..490487732c86 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -22,6 +22,7 @@ /obj/item/organ/external/tail/lizard = "Smooth", ) mutanttongue = /obj/item/organ/internal/tongue/lizard + mutantstomach = /obj/item/organ/internal/stomach/lizard coldmod = 1.5 heatmod = 0.67 payday_modifier = 0.75 @@ -40,6 +41,7 @@ mutanteyes = /obj/item/organ/internal/eyes/lizard // Lizards are coldblooded and can stand a greater temperature range than humans + bodytemp_normal = (BODYTEMP_NORMAL - 7.5) bodytemp_heat_damage_limit = (BODYTEMP_HEAT_DAMAGE_LIMIT + 20) // This puts lizards 10 above lavaland max heat for ash lizards. bodytemp_cold_damage_limit = (BODYTEMP_COLD_DAMAGE_LIMIT - 10) @@ -54,9 +56,12 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/lizard, ) -/// Lizards are cold blooded and do not stabilize body temperature naturally -/datum/species/lizard/body_temperature_core(mob/living/carbon/human/humi, seconds_per_tick, times_fired) - return +/datum/species/lizard/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) + . = ..() + // melbert todo : temp / integrate this into the coldblooded trait + // if you spawn on station is is expected you have already acclimated to the room temp (20c) (but give a little bit of leeway) + if(is_station_level(C.z)) + C.bodytemperature = CELCIUS_TO_KELVIN(22.5 CELCIUS) /datum/species/lizard/random_name(gender,unique,lastname) if(unique) diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index 46e772a71fcd..19f9f5c3d1d0 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -15,6 +15,7 @@ TRAIT_RESISTCOLD, TRAIT_NOBLOOD, TRAIT_NO_DNA_COPY, + TRAIT_RESISTLOWPRESSURE, ) inherent_biotypes = MOB_HUMANOID|MOB_MINERAL @@ -49,7 +50,7 @@ // Body temperature for Plasmen is much lower human as they can handle colder environments bodytemp_normal = (BODYTEMP_NORMAL - 40) // The minimum amount they stabilize per tick is reduced making hot areas harder to deal with - bodytemp_autorecovery_min = 2 + temperature_normalization_speed = /mob/living/carbon/human::temperature_normalization_speed * 0.5 // They are hurt at hot temps faster as it is harder to hold their form bodytemp_heat_damage_limit = (BODYTEMP_HEAT_DAMAGE_LIMIT - 20) // about 40C // This effects how fast body temp stabilizes, also if cold resit is lost on the mob @@ -121,10 +122,18 @@ H.update_appearance(UPDATE_OVERLAYS) -/datum/species/plasmaman/handle_fire(mob/living/carbon/human/H, seconds_per_tick, times_fired, no_protection = FALSE) - if(internal_fire) - no_protection = TRUE +/datum/species/plasmaman/proc/handle_fire(mob/living/carbon/human/H, seconds_per_tick) + SIGNAL_HANDLER + + return internal_fire ? BURNING_SKIP_PROTECTION : NONE + +/datum/species/plasmaman/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) + . = ..() + RegisterSignal(C, COMSIG_HUMAN_BURNING, PROC_REF(handle_fire)) + +/datum/species/plasmaman/on_species_loss(mob/living/carbon/C, datum/species/new_species, pref_save) . = ..() + UnregisterSignal(C, COMSIG_HUMAN_BURNING) /datum/species/plasmaman/pre_equip_species_outfit(datum/job/job, mob/living/carbon/human/equipping, visuals_only = FALSE) if(job?.plasmaman_outfit) diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index ee513f5feb03..9ff7894c614c 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -54,10 +54,6 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/zombie/infectious, ) -/// Zombies do not stabilize body temperature they are the walking dead and are cold blooded -/datum/species/zombie/body_temperature_core(mob/living/carbon/human/humi, seconds_per_tick, times_fired) - return - /datum/species/zombie/check_roundstart_eligible() if(check_holidays(HALLOWEEN)) return TRUE diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 6494e1cf3974..a5da401af333 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -313,92 +313,47 @@ reagents?.metabolize(src, seconds_per_tick, times_fired, can_overdose = TRUE, liverless = TRUE, dead = TRUE) // Your liver doesn't work while you're dead. /// Base carbon environment handler, adds natural stabilization -/mob/living/carbon/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) - var/areatemp = get_temperature(environment) - - if(stat != DEAD) // If you are dead your body does not stabilize naturally - natural_bodytemperature_stabilization(environment, seconds_per_tick, times_fired) - - if(!on_fire || areatemp > bodytemperature) // If we are not on fire or the area is hotter - adjust_bodytemperature((areatemp - bodytemperature), use_insulation=TRUE, use_steps=TRUE) +/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) + . = ..() + var/pressure = environment.return_pressure() + var/adjusted_pressure = calculate_affecting_pressure(pressure) + + // Set alerts and apply damage based on the amount of pressure + switch(adjusted_pressure) + // Very high pressure, show an alert and take damage + if(HAZARD_HIGH_PRESSURE to INFINITY) + if(HAS_TRAIT(src, TRAIT_RESISTHIGHPRESSURE)) + clear_alert(ALERT_PRESSURE) + else + var/pressure_damage = min(((adjusted_pressure / HAZARD_HIGH_PRESSURE) - 1) * PRESSURE_DAMAGE_COEFFICIENT, MAX_HIGH_PRESSURE_DAMAGE) * physiology.pressure_mod * physiology.brute_mod * seconds_per_tick + adjustBruteLoss(pressure_damage, required_bodytype = BODYTYPE_ORGANIC) + throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/highpressure, 2) + + // High pressure, show an alert + if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE) + throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/highpressure, 1) + + // No pressure issues here clear pressure alerts + if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE) + clear_alert(ALERT_PRESSURE) + + // Low pressure here, show an alert + if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE) + // We have low pressure resit trait, clear alerts + if(HAS_TRAIT(src, TRAIT_RESISTLOWPRESSURE)) + clear_alert(ALERT_PRESSURE) + else + throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/lowpressure, 1) -/** - * Used to stabilize the body temperature back to normal on living mobs - * - * Arguments: - * - [environemnt][/datum/gas_mixture]: The environment gas mix - * - seconds_per_tick: The amount of time that has elapsed since the last tick - * - times_fired: The number of times SSmobs has ticked - */ -/mob/living/carbon/proc/natural_bodytemperature_stabilization(datum/gas_mixture/environment, seconds_per_tick, times_fired) - var/areatemp = get_temperature(environment) - var/body_temperature_difference = get_body_temp_normal() - bodytemperature - var/natural_change = 0 - - // We are very cold, increase body temperature - if(bodytemperature <= BODYTEMP_COLD_DAMAGE_LIMIT) - natural_change = max((body_temperature_difference * metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR), \ - BODYTEMP_AUTORECOVERY_MINIMUM) - - // we are cold, reduce the minimum increment and do not jump over the difference - else if(bodytemperature > BODYTEMP_COLD_DAMAGE_LIMIT && bodytemperature < get_body_temp_normal()) - natural_change = max(body_temperature_difference * metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR, \ - min(body_temperature_difference, BODYTEMP_AUTORECOVERY_MINIMUM / 4)) - - // We are hot, reduce the minimum increment and do not jump below the difference - else if(bodytemperature > get_body_temp_normal() && bodytemperature <= BODYTEMP_HEAT_DAMAGE_LIMIT) - natural_change = min(body_temperature_difference * metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR, \ - max(body_temperature_difference, -(BODYTEMP_AUTORECOVERY_MINIMUM / 4))) - - // We are very hot, reduce the body temperature - else if(bodytemperature >= BODYTEMP_HEAT_DAMAGE_LIMIT) - natural_change = min((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), -BODYTEMP_AUTORECOVERY_MINIMUM) - - var/thermal_protection = 1 - get_insulation_protection(areatemp) // invert the protection - if(areatemp > bodytemperature) // It is hot here - if(bodytemperature < get_body_temp_normal()) - // Our bodytemp is below normal we are cold, insulation helps us retain body heat - // and will reduce the heat we lose to the environment - natural_change = (thermal_protection + 1) * natural_change + // Very low pressure, show an alert and take damage else - // Our bodytemp is above normal and sweating, insulation hinders out ability to reduce heat - // but will reduce the amount of heat we get from the environment - natural_change = (1 / (thermal_protection + 1)) * natural_change - else // It is cold here - if(!on_fire) // If on fire ignore ignore local temperature in cold areas - if(bodytemperature < get_body_temp_normal()) - // Our bodytemp is below normal, insulation helps us retain body heat - // and will reduce the heat we lose to the environment - natural_change = (thermal_protection + 1) * natural_change + // We have low pressure resit trait, clear alerts + if(HAS_TRAIT(src, TRAIT_RESISTLOWPRESSURE)) + clear_alert(ALERT_PRESSURE) else - // Our bodytemp is above normal and sweating, insulation hinders out ability to reduce heat - // but will reduce the amount of heat we get from the environment - natural_change = (1 / (thermal_protection + 1)) * natural_change - - // Apply the natural stabilization changes - adjust_bodytemperature(natural_change * seconds_per_tick) - -/** - * Get the insulation that is appropriate to the temperature you're being exposed to. - * All clothing, natural insulation, and traits are combined returning a single value. - * - * required temperature The Temperature that you're being exposed to - * - * return the percentage of protection as a value from 0 - 1 -**/ -/mob/living/carbon/proc/get_insulation_protection(temperature) - return (temperature > bodytemperature) ? get_heat_protection(temperature) : get_cold_protection(temperature) - -/// This returns the percentage of protection from heat as a value from 0 - 1 -/// temperature is the temperature you're being exposed to -/mob/living/carbon/proc/get_heat_protection(temperature) - return heat_protection - -/// This returns the percentage of protection from cold as a value from 0 - 1 -/// temperature is the temperature you're being exposed to -/mob/living/carbon/proc/get_cold_protection(temperature) - return cold_protection - + var/pressure_damage = LOW_PRESSURE_DAMAGE * physiology.pressure_mod * physiology.brute_mod * seconds_per_tick + adjustBruteLoss(pressure_damage, required_bodytype = BODYTYPE_ORGANIC) + throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/lowpressure, 2) /** * Have two mobs share body heat between each other. * Account for the insulation and max temperature change range for the mob @@ -409,39 +364,12 @@ /mob/living/carbon/proc/share_bodytemperature(mob/living/carbon/M) var/temp_diff = bodytemperature - M.bodytemperature if(temp_diff > 0) // you are warm share the heat of life - M.adjust_bodytemperature((temp_diff * 0.5), use_insulation=TRUE, use_steps=TRUE) // warm up the giver - adjust_bodytemperature((temp_diff * -0.5), use_insulation=TRUE, use_steps=TRUE) // cool down the reciver + M.adjust_bodytemperature((temp_diff * 0.5) * 0.075 KELVIN, use_insulation = TRUE) // warm up the giver + adjust_bodytemperature((temp_diff * -0.5) * 0.075 KELVIN, use_insulation = TRUE) // cool down the reciver else // they are warmer leech from them - adjust_bodytemperature((temp_diff * -0.5) , use_insulation=TRUE, use_steps=TRUE) // warm up the reciver - M.adjust_bodytemperature((temp_diff * 0.5), use_insulation=TRUE, use_steps=TRUE) // cool down the giver - -/** - * Adjust the body temperature of a mob - * expanded for carbon mobs allowing the use of insulation and change steps - * - * vars: - * * amount The amount of degrees to change body temperature by - * * min_temp (optional) The minimum body temperature after adjustment - * * max_temp (optional) The maximum body temperature after adjustment - * * use_insulation (optional) modifies the amount based on the amount of insulation the mob has - * * use_steps (optional) Use the body temp divisors and max change rates - * * capped (optional) default True used to cap step mode - */ -/mob/living/carbon/adjust_bodytemperature(amount, min_temp=0, max_temp=INFINITY, use_insulation=FALSE, use_steps=FALSE, capped=TRUE) - // apply insulation to the amount of change - if(use_insulation) - amount *= (1 - get_insulation_protection(bodytemperature + amount)) - - // Use the bodytemp divisors to get the change step, with max step size - if(use_steps) - amount = (amount > 0) ? (amount / BODYTEMP_HEAT_DIVISOR) : (amount / BODYTEMP_COLD_DIVISOR) - // Clamp the results to the min and max step size - if(capped) - amount = (amount > 0) ? min(amount, BODYTEMP_HEATING_MAX) : max(amount, BODYTEMP_COOLING_MAX) - - if(bodytemperature >= min_temp && bodytemperature <= max_temp) - bodytemperature = clamp(bodytemperature + amount, min_temp, max_temp) + adjust_bodytemperature((temp_diff * -0.5) * 0.075 KELVIN, use_insulation = TRUE) // warm up the reciver + M.adjust_bodytemperature((temp_diff * 0.5) * 0.075 KELVIN, use_insulation = TRUE) // cool down the giver /////////// diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index cda90a8e7316..a392f4667072 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -1,6 +1,3 @@ -/// This divisor controls how fast body temperature changes to match the environment -#define BODYTEMP_DIVISOR 16 - /** * Handles the biological and general over-time processes of the mob. * @@ -63,9 +60,15 @@ var/datum/gas_mixture/environment = loc.return_air() if(environment) handle_environment(environment, seconds_per_tick, times_fired) + body_temperature_damage(environment, seconds_per_tick, times_fired) + if(stat <= SOFT_CRIT && !on_fire) + temperature_homeostasis(seconds_per_tick, times_fired) handle_gravity(seconds_per_tick, times_fired) + if(stat != DEAD) + body_temperature_alerts() + handle_wounds(seconds_per_tick, times_fired) if(machine) @@ -90,20 +93,40 @@ /mob/living/proc/handle_random_events(seconds_per_tick, times_fired) return -// Base mob environment handler for body temperature +/** + * Handle this mob's interactions with the environment + * + * By default handles body temperature normalization to the area's temperature, + * but also handles pressure for many mobs + * + * Arguments: + * * environment: The gas mixture of the area the mob is in, will never be null + * * seconds_per_tick: The amount of time that has elapsed since this last fired. + * * times_fired: The number of times SSmobs has fired + */ /mob/living/proc/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) var/loc_temp = get_temperature(environment) var/temp_delta = loc_temp - bodytemperature + if(temp_delta == 0) + return + if(temp_delta < 0 && on_fire) // do not reduce body temp when on fire + return + + // Get the insulation value based on the area's temp + var/thermal_protection = get_insulation(loc_temp) + var/protection_modifier = 1 + if(bodytemperature > standard_body_temperature + 2 KELVIN) + // we are overheating and sweaty - insulation is not as good reducing thermal protection + protection_modifier = 0.7 - if(ismovable(loc)) - var/atom/movable/occupied_space = loc - temp_delta *= (1 - occupied_space.contents_thermal_insulation) + var/temp_sign = SIGN(temp_delta) + var/temp_change = temp_sign * (1 - (thermal_protection * protection_modifier)) * ((0.1 * max(1, abs(temp_delta))) ** 1.8) * temperature_normalization_speed + // Cap increase and decrease + temp_change = temp_change < 0 ? max(temp_change, BODYTEMP_COOLING_MAX) : min(temp_change, BODYTEMP_HEATING_MAX) + adjust_bodytemperature(temp_change * seconds_per_tick) // no use_insulation beacuse we account for it manually - if(temp_delta < 0) // it is cold here - if(!on_fire) // do not reduce body temp when on fire - adjust_bodytemperature(max(max(temp_delta / BODYTEMP_DIVISOR, BODYTEMP_COOLING_MAX) * seconds_per_tick, temp_delta)) - else // this is a hot place - adjust_bodytemperature(min(min(temp_delta / BODYTEMP_DIVISOR, BODYTEMP_HEATING_MAX) * seconds_per_tick, temp_delta)) +/mob/living/silicon/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) + return // Not yet /** * Get the fullness of the mob @@ -116,10 +139,8 @@ /mob/living/proc/get_fullness() var/fullness = nutrition // we add the nutrition value of what we're currently digesting - for(var/bile in reagents.reagent_list) - var/datum/reagent/consumable/bits = bile - if(bits) - fullness += bits.nutriment_factor * bits.volume / bits.metabolization_rate + for(var/datum/reagent/consumable/bits in reagents.reagent_list) + fullness += bits.nutriment_factor * bits.volume / bits.metabolization_rate return fullness /** @@ -153,5 +174,3 @@ var/grav_strength = gravity - GRAVITY_DAMAGE_THRESHOLD adjustBruteLoss(min(GRAVITY_DAMAGE_SCALING * grav_strength, GRAVITY_DAMAGE_MAXIMUM) * seconds_per_tick) - -#undef BODYTEMP_DIVISOR diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 72e23dd32788..2eab59136579 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -935,7 +935,8 @@ cure_husk() if(heal_flags & HEAL_TEMP) - bodytemperature = get_body_temp_normal(apply_change = FALSE) + bodytemperature = standard_body_temperature + body_temperature_alerts() if(heal_flags & HEAL_BLOOD) restore_blood() if(reagents && (heal_flags & HEAL_ALL_REAGENTS)) @@ -1242,16 +1243,23 @@ else if(!src.mob_negates_gravity()) step_towards(src,S) +/** + * Unsed in calculating what temperature our environment probably is. + * + * By default just returns the temperature of the turf we're on, + * but is slightly more complex if we're inside another movable (in which we average the temps of our body and the movable) + */ /mob/living/proc/get_temperature(datum/gas_mixture/environment) - var/loc_temp = environment ? environment.temperature : T0C + var/loc_temp = environment ? environment.return_temperature() : T0C if(isobj(loc)) - var/obj/oloc = loc - var/obj_temp = oloc.return_temperature() - if(obj_temp != null) + var/obj_temp = loc.return_temperature() + if(!isnull(obj_temp)) loc_temp = obj_temp + else if(isspaceturf(get_turf(src))) var/turf/heat_turf = get_turf(src) loc_temp = heat_turf.temperature + if(ismovable(loc)) var/atom/movable/occupied_space = loc loc_temp = ((1 - occupied_space.contents_thermal_insulation) * loc_temp) + (occupied_space.contents_thermal_insulation * bodytemperature) @@ -1697,16 +1705,19 @@ GLOBAL_LIST_EMPTY(fire_appearances) return null /** - * Handles effects happening when mob is on normal fire + * Called every life tick that a mob is on fire. * - * Vars: - * * seconds_per_tick - * * times_fired - * * fire_handler: Current fire status effect that called the proc + * Args: + * * seconds_per_tick: Seconds between each life tick + * * fire_handler: The fire handler status effect that is managing the fire stacks */ +/mob/living/proc/on_fire_stack(seconds_per_tick, datum/status_effect/fire_handler/fire_stacks/fire_handler) + var/amount_to_heat = 0.25 KELVIN * fire_handler.stacks * seconds_per_tick + if(bodytemperature > BODYTEMP_FIRE_TEMP_SOFTCAP) + // Apply dimishing returns upon temp beyond the soft cap + amount_to_heat = amount_to_heat ** (BODYTEMP_FIRE_TEMP_SOFTCAP / bodytemperature) -/mob/living/proc/on_fire_stack(seconds_per_tick, times_fired, datum/status_effect/fire_handler/fire_stacks/fire_handler) - return + return adjust_bodytemperature(amount_to_heat) //Mobs on Fire end @@ -1969,64 +1980,6 @@ GLOBAL_LIST_EMPTY(fire_appearances) update_transform() lying_prev = lying_angle - -/** - * add_body_temperature_change Adds modifications to the body temperature - * - * This collects all body temperature changes that the mob is experiencing to the list body_temp_changes - * the aggrogate result is used to derive the new body temperature for the mob - * - * arguments: - * * key_name (str) The unique key for this change, if it already exist it will be overridden - * * amount (int) The amount of change from the base body temperature - */ -/mob/living/proc/add_body_temperature_change(key_name, amount) - body_temp_changes["[key_name]"] = amount - -/** - * remove_body_temperature_change Removes the modifications to the body temperature - * - * This removes the recorded change to body temperature from the body_temp_changes list - * - * arguments: - * * key_name (str) The unique key for this change that will be removed - */ -/mob/living/proc/remove_body_temperature_change(key_name) - body_temp_changes -= key_name - -/** - * get_body_temp_normal_change Returns the aggregate change to body temperature - * - * This aggregates all the changes in the body_temp_changes list and returns the result - */ -/mob/living/proc/get_body_temp_normal_change() - var/total_change = 0 - if(body_temp_changes.len) - for(var/change in body_temp_changes) - total_change += body_temp_changes["[change]"] - return total_change - -/** - * get_body_temp_normal Returns the mobs normal body temperature with any modifications applied - * - * This applies the result from proc/get_body_temp_normal_change() against the BODYTEMP_NORMAL and returns the result - * - * arguments: - * * apply_change (optional) Default True This applies the changes to body temperature normal - */ -/mob/living/proc/get_body_temp_normal(apply_change=TRUE) - if(!apply_change) - return BODYTEMP_NORMAL - return BODYTEMP_NORMAL + get_body_temp_normal_change() - -///Returns the body temperature at which this mob will start taking heat damage. -/mob/living/proc/get_body_temp_heat_damage_limit() - return BODYTEMP_HEAT_DAMAGE_LIMIT - -///Returns the body temperature at which this mob will start taking cold damage. -/mob/living/proc/get_body_temp_cold_damage_limit() - return BODYTEMP_COLD_DAMAGE_LIMIT - ///Checks if the user is incapacitated or on cooldown. /mob/living/proc/can_look_up() return !(incapacitated(IGNORE_RESTRAINTS)) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 63ea856f6117..14b2f4b4fd2c 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -188,9 +188,6 @@ ///Whether the mob is slowed down when dragging another prone mob var/slowed_by_drag = TRUE - /// List of changes to body temperature, used by desease symtoms like fever - var/list/body_temp_changes = list() - //this stuff is here to make it simple for admins to mess with custom held sprites ///left hand icon for holding mobs var/icon/held_lh = 'icons/mob/inhands/pets_held_lh.dmi' @@ -229,3 +226,30 @@ var/datum/stamina_container/stamina /// What our current gravity state is. Used to avoid duplicate animates and such var/gravity_state = null + + /// Body temp we homeostasize to + var/standard_body_temperature = BODYTEMP_NORMAL + /// Temperature of our insides + var/bodytemperature = BODYTEMP_NORMAL + /// Lazylist of targets we homeostasize to + /// This allows multiple effects to add a different target to the list, which is averaged + /// (So you can have both a fever and a cold at the same time) + /// If empty just defaults to standard_body_temperature + var/list/homeostasis_targets + + /// How cold to start sustaining cold damage + var/bodytemp_cold_damage_limit = -1 // -1 = no cold damage ever + /// How hot to start sustaining heat damage + var/bodytemp_heat_damage_limit = INFINITY // INFINITY = no heat damage ever + + /// How fast the mob's temperature normalizes to their environment + var/temperature_normalization_speed = 0.1 + /// How fast the mob's temperature normalizes to their homeostasis + /// Also gets multiplied by metabolism_efficiency. + /// Note that more of this = more nutrition is consumed every life tick. + var/temperature_homeostasis_speed = 0.5 + /// Protection (insulation) from temperature changes, max 1 + var/temperature_insulation = 0 + + /// Whether we currently have temp alerts, minor optimization + VAR_PRIVATE/temp_alerts = FALSE diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 26f3ea537144..583311628a91 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -10,8 +10,8 @@ damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) hud_possible = list(DIAG_STAT_HUD, DIAG_BOT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_PATH_HUD = HUD_LIST_LIST) - maxbodytemp = INFINITY - minbodytemp = 0 + bodytemp_heat_damage_limit = INFINITY + bodytemp_cold_damage_limit = -1 has_unlimited_silicon_privilege = TRUE sentience_type = SENTIENCE_ARTIFICIAL status_flags = NONE //no default canpush diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index bd27c482caf0..d40f8513b8f8 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -15,8 +15,8 @@ pass_flags = PASSTABLE mob_size = MOB_SIZE_SMALL mob_biotypes = MOB_ORGANIC|MOB_BEAST - minbodytemp = 200 - maxbodytemp = 400 + bodytemp_cold_damage_limit = 200 + bodytemp_heat_damage_limit = 400 unsuitable_atmos_damage = 0.5 animal_species = /mob/living/simple_animal/pet/cat childtype = list(/mob/living/simple_animal/pet/cat/kitten = 1) @@ -59,8 +59,8 @@ icon_living = "spacecat" icon_dead = "spacecat_dead" unsuitable_atmos_damage = 0 - minbodytemp = TCMB - maxbodytemp = T0C + 40 + bodytemp_cold_damage_limit = TCMB + bodytemp_heat_damage_limit = T0C + 40 held_state = "spacecat" /mob/living/simple_animal/pet/cat/breadcat diff --git a/code/modules/mob/living/simple_animal/friendly/gondola.dm b/code/modules/mob/living/simple_animal/friendly/gondola.dm index 80e89dd08d75..fb7e16bdab36 100644 --- a/code/modules/mob/living/simple_animal/friendly/gondola.dm +++ b/code/modules/mob/living/simple_animal/friendly/gondola.dm @@ -23,8 +23,8 @@ loot = list(/obj/effect/decal/cleanable/blood/gibs, /obj/item/stack/sheet/animalhide/gondola = 1, /obj/item/food/meat/slab/gondola = 1) //Gondolas aren't affected by cold. atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - maxbodytemp = 1500 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 1500 maxHealth = 200 health = 200 del_on_death = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index a60ce8e9ca1c..0026868cdb70 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -26,7 +26,7 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) faction = list(ROLE_ALIEN) status_flags = CANPUSH - minbodytemp = 0 + bodytemp_cold_damage_limit = -1 unsuitable_heat_damage = 20 // Going for a dark purple here lighting_cutoff_red = 30 diff --git a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm index 9b1c85502497..84d3570bb022 100644 --- a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm @@ -27,8 +27,8 @@ faction = list(ROLE_WIZARD) footstep_type = FOOTSTEP_MOB_SHOE weather_immunities = list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE) - minbodytemp = 0 - maxbodytemp = INFINITY + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = INFINITY atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) loot = list(/obj/effect/decal/remains/human) del_on_death = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/_jungle_mobs.dm b/code/modules/mob/living/simple_animal/hostile/jungle/_jungle_mobs.dm index dd0d3de071d2..acd51b0f4053 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/_jungle_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/_jungle_mobs.dm @@ -4,8 +4,8 @@ faction = list(FACTION_JUNGLE) obj_damage = 30 environment_smash = ENVIRONMENT_SMASH_WALLS - minbodytemp = 0 - maxbodytemp = 450 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 450 response_harm_continuous = "strikes" response_harm_simple = "strike" status_flags = NONE diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm index 689e1391bfd6..7641650f259b 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm @@ -16,8 +16,8 @@ stat_attack = DEAD atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) damage_coeff = list(BRUTE = 1, BURN = 0.5, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) - minbodytemp = 0 - maxbodytemp = INFINITY + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = INFINITY vision_range = 5 aggro_vision_range = 18 move_force = MOVE_FORCE_OVERPOWERING diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index 10d21416f355..17cca2468595 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -25,7 +25,7 @@ taunt_chance = 30 atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 + bodytemp_cold_damage_limit = -1 faction = list(FACTION_MIMIC) move_to_delay = 9 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm index 242b178b82f2..63b19d5018fc 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm @@ -6,8 +6,8 @@ weather_immunities = list(TRAIT_LAVA_IMMUNE,TRAIT_ASHSTORM_IMMUNE) obj_damage = 30 environment_smash = ENVIRONMENT_SMASH_WALLS - minbodytemp = 0 - maxbodytemp = INFINITY + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = INFINITY unsuitable_heat_damage = 20 response_harm_continuous = "strikes" response_harm_simple = "strike" diff --git a/code/modules/mob/living/simple_animal/hostile/ooze.dm b/code/modules/mob/living/simple_animal/hostile/ooze.dm index 190db5f19ac8..784117757150 100644 --- a/code/modules/mob/living/simple_animal/hostile/ooze.dm +++ b/code/modules/mob/living/simple_animal/hostile/ooze.dm @@ -12,8 +12,8 @@ speak_emote = list("blorbles") atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) hud_type = /datum/hud/ooze - minbodytemp = 250 - maxbodytemp = INFINITY + bodytemp_cold_damage_limit = 250 + bodytemp_heat_damage_limit = INFINITY faction = list(FACTION_SLIME) melee_damage_lower = 10 melee_damage_upper = 10 @@ -175,7 +175,7 @@ ///Heat up the mob a little /datum/action/cooldown/metabolicboost/proc/HeatUp() var/mob/living/simple_animal/hostile/ooze/ooze = owner - ooze.adjust_bodytemperature(50) + ooze.adjust_bodytemperature(3.33 KELVIN) ///Remove the speed modifier and delete the timer for heating up /datum/action/cooldown/metabolicboost/proc/FinishSpeedup(timerid) diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm index eefac18f30c2..2a05df3d63d8 100644 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm @@ -57,7 +57,7 @@ /mob/living/simple_animal/hostile/pirate/melee/space name = "Space Pirate Swashbuckler" atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 + bodytemp_cold_damage_limit = -1 speed = 1 mob_spawner = /obj/effect/mob_spawn/corpse/human/pirate/melee/space @@ -81,7 +81,7 @@ /mob/living/simple_animal/hostile/pirate/ranged/space name = "Space Pirate Gunner" atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 + bodytemp_cold_damage_limit = -1 speed = 1 mob_spawner = /obj/effect/mob_spawn/corpse/human/pirate/ranged/space held_item = /obj/item/gun/energy/e_gun/lethal diff --git a/code/modules/mob/living/simple_animal/hostile/zombie.dm b/code/modules/mob/living/simple_animal/hostile/zombie.dm index c8c03989a595..b4c71f7cc4c1 100644 --- a/code/modules/mob/living/simple_animal/hostile/zombie.dm +++ b/code/modules/mob/living/simple_animal/hostile/zombie.dm @@ -17,7 +17,7 @@ attack_vis_effect = ATTACK_EFFECT_BITE istate = ISTATE_HARM|ISTATE_BLOCKING atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 + bodytemp_cold_damage_limit = -1 status_flags = CANPUSH death_message = "collapses, flesh gone in a pile of bones!" del_on_death = TRUE diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 0bb3664e5c02..e984ded97ff8 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -58,10 +58,8 @@ ///How much stamina the mob recovers per second var/stamina_recovery = 5 - ///Minimal body temperature without receiving damage - var/minbodytemp = NPC_DEFAULT_MIN_TEMP - ///Maximal body temperature without receiving damage - var/maxbodytemp = NPC_DEFAULT_MAX_TEMP + bodytemp_cold_damage_limit = NPC_DEFAULT_MIN_TEMP + bodytemp_heat_damage_limit = NPC_DEFAULT_MAX_TEMP ///This damage is taken when the body temp is too cold. var/unsuitable_cold_damage ///This damage is taken when the body temp is too hot. @@ -79,9 +77,6 @@ ///This damage is taken when atmos doesn't fit all the requirements above. var/unsuitable_atmos_damage = 1 - ///How fast the mob's temperature normalizes. The greater the value, the slower their temperature normalizes. Should always be greater than 0. - var/temperature_normalization_speed = 5 - //Defaults to zero so Ian can still be cuddly. Moved up the tree to living! This allows us to bypass some hardcoded stuff. melee_damage_lower = 0 melee_damage_upper = 0 @@ -343,20 +338,11 @@ /mob/living/simple_animal/proc/environment_temperature_is_safe(datum/gas_mixture/environment) . = TRUE var/areatemp = get_temperature(environment) - if((areatemp < minbodytemp) || (areatemp > maxbodytemp)) + if((areatemp < bodytemp_cold_damage_limit) || (areatemp > bodytemp_heat_damage_limit)) . = FALSE /mob/living/simple_animal/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) - var/atom/A = loc - if(isturf(A)) - var/areatemp = get_temperature(environment) - var/temp_delta = areatemp - bodytemperature - if(abs(temp_delta) > 5) - if(temp_delta < 0) - if(!on_fire) - adjust_bodytemperature(clamp(temp_delta * seconds_per_tick / temperature_normalization_speed, temp_delta, 0)) - else - adjust_bodytemperature(clamp(temp_delta * seconds_per_tick / temperature_normalization_speed, 0, temp_delta)) + . = ..() if(!environment_air_is_safe() && unsuitable_atmos_damage) adjustHealth(unsuitable_atmos_damage * seconds_per_tick) @@ -365,12 +351,16 @@ else clear_alert(ALERT_NOT_ENOUGH_OXYGEN) - handle_temperature_damage(seconds_per_tick, times_fired) -/mob/living/simple_animal/proc/handle_temperature_damage(seconds_per_tick, times_fired) - . = FALSE - if((bodytemperature < minbodytemp) && unsuitable_cold_damage) +/mob/living/simple_animal/body_temperature_damage(datum/gas_mixture/environment, seconds_per_tick, times_fired) + if((bodytemperature < bodytemp_cold_damage_limit) && unsuitable_cold_damage) adjustHealth(unsuitable_cold_damage * seconds_per_tick) + + if((bodytemperature > bodytemp_heat_damage_limit) && unsuitable_heat_damage) + adjustHealth(unsuitable_heat_damage * seconds_per_tick) + +/mob/living/simple_animal/body_temperature_alerts() + if((bodytemperature < bodytemp_cold_damage_limit) && unsuitable_cold_damage) switch(unsuitable_cold_damage) if(1 to 5) throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1) @@ -380,8 +370,7 @@ throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3) . = TRUE - if((bodytemperature > maxbodytemp) && unsuitable_heat_damage) - adjustHealth(unsuitable_heat_damage * seconds_per_tick) + if((bodytemperature > bodytemp_heat_damage_limit) && unsuitable_heat_damage) switch(unsuitable_heat_damage) if(1 to 5) throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 1) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 55e1dfebe38e..339acb74409a 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -99,11 +99,6 @@ */ var/name_archive //For admin things like possession - /// Default body temperature - var/bodytemperature = BODYTEMP_NORMAL //310.15K / 98.6F - /// Our body temperatue as of the last process, prevents pointless work when handling alerts - var/old_bodytemperature = 0 - /// Hunger level of the mob var/nutrition = NUTRITION_LEVEL_START_MIN // randomised in Initialize /// Satiation level of the mob diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm index 1dde25c7802f..9cbc06a5c366 100644 --- a/code/modules/mob/status_procs.dm +++ b/code/modules/mob/status_procs.dm @@ -8,11 +8,6 @@ /mob/proc/set_disgust(amount) return -///Adjust the body temperature of a mob, with min/max settings -/mob/proc/adjust_bodytemperature(amount,min_temp=0,max_temp=INFINITY) - if(bodytemperature >= min_temp && bodytemperature <= max_temp) - bodytemperature = clamp(bodytemperature + amount,min_temp,max_temp) - /// Sight here is the mob.sight var, which tells byond what to actually show to our client /// See [code\__DEFINES\sight.dm] for more details /mob/proc/set_sight(new_value) diff --git a/code/modules/mod/mod_activation.dm b/code/modules/mod/mod_activation.dm index 36563bbd96cb..871c0de140f9 100644 --- a/code/modules/mod/mod_activation.dm +++ b/code/modules/mod/mod_activation.dm @@ -195,16 +195,16 @@ part.clothing_flags |= part.visor_flags part.flags_inv |= part.visor_flags_inv part.flags_cover |= part.visor_flags_cover - part.heat_protection = initial(part.heat_protection) - part.cold_protection = initial(part.cold_protection) + part.min_cold_protection_temperature = theme.min_cold_protection_temperature + part.max_heat_protection_temperature = theme.max_heat_protection_temperature part.alternate_worn_layer = null else part.icon_state = "[skin]-[part.base_icon_state]" part.flags_cover &= ~part.visor_flags_cover part.flags_inv &= ~part.visor_flags_inv part.clothing_flags &= ~part.visor_flags - part.heat_protection = NONE - part.cold_protection = NONE + part.min_cold_protection_temperature = null + part.max_heat_protection_temperature = null part.alternate_worn_layer = mod_parts[part] if(part == boots) wearer.update_worn_shoes() diff --git a/code/modules/mod/mod_clothes.dm b/code/modules/mod/mod_clothes.dm index b9e09fd7bcaf..8bdcf3a6fb93 100644 --- a/code/modules/mod/mod_clothes.dm +++ b/code/modules/mod/mod_clothes.dm @@ -8,8 +8,8 @@ worn_icon_snouted = 'monkestation/icons/mob/mod.dmi' armor_type = /datum/armor/none body_parts_covered = HEAD - heat_protection = HEAD - cold_protection = HEAD + + item_flags = IMMUTABLE_SLOW supports_variations_flags = CLOTHING_SNOUTED_VARIATION clothing_traits = list(TRAIT_SNOWSTORM_IMMUNE) @@ -30,8 +30,8 @@ ) armor_type = /datum/armor/none body_parts_covered = CHEST|GROIN - heat_protection = CHEST|GROIN - cold_protection = CHEST|GROIN + + item_flags = IMMUTABLE_SLOW supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION clothing_traits = list(TRAIT_SNOWSTORM_IMMUNE) @@ -45,8 +45,8 @@ worn_icon = 'icons/mob/clothing/modsuit/mod_clothing.dmi' armor_type = /datum/armor/none body_parts_covered = HANDS|ARMS - heat_protection = HANDS|ARMS - cold_protection = HANDS|ARMS + + item_flags = IMMUTABLE_SLOW supports_variations_flags = NONE @@ -60,8 +60,8 @@ worn_icon_digitigrade = 'monkestation/icons/mob/mod.dmi' armor_type = /datum/armor/none body_parts_covered = FEET|LEGS - heat_protection = FEET|LEGS - cold_protection = FEET|LEGS + + item_flags = IMMUTABLE_SLOW item_flags = IGNORE_DIGITIGRADE can_be_tied = FALSE diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index 56a372804c61..14eaf71133e8 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -125,8 +125,6 @@ part.set_armor(theme.armor_type) part.resistance_flags = theme.resistance_flags part.flags_1 |= theme.atom_flags //flags like initialization or admin spawning are here, so we cant set, have to add - part.heat_protection = NONE - part.cold_protection = NONE part.max_heat_protection_temperature = theme.max_heat_protection_temperature part.min_cold_protection_temperature = theme.min_cold_protection_temperature part.siemens_coefficient = theme.siemens_coefficient diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index ea8e4409ee1b..f145e849ca3d 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -432,7 +432,7 @@ /// Minimum temperature we can set. var/min_temp = 293.15 /// Maximum temperature we can set. - var/max_temp = 318.15 + var/max_temp = T20C * 2.25 /obj/item/mod/module/thermal_regulator/get_configuration() . = ..() @@ -444,7 +444,11 @@ temperature_setting = clamp(value + T0C, min_temp, max_temp) /obj/item/mod/module/thermal_regulator/on_active_process(seconds_per_tick) - mod.wearer.adjust_bodytemperature(get_temp_change_amount((temperature_setting - mod.wearer.bodytemperature), 0.08 * seconds_per_tick)) + var/mob/living/user = mod.wearer + if(user.bodytemperature < temperature_setting) + user.adjust_bodytemperature((temperature_setting - user.bodytemperature) * 0.08 * seconds_per_tick, max_temp = temperature_setting) + else if(user.bodytemperature > temperature_setting) + user.adjust_bodytemperature((temperature_setting - user.bodytemperature) * 0.08 * seconds_per_tick, min_temp = temperature_setting) ///DNA Lock - Prevents people without the set DNA from activating the suit. /obj/item/mod/module/dna_lock diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm index 55b070e02fda..09c2e1fb2aa0 100644 --- a/code/modules/power/lighting/light.dm +++ b/code/modules/power/lighting/light.dm @@ -569,7 +569,7 @@ if(user.gloves) var/obj/item/clothing/gloves/electrician_gloves = user.gloves - if(electrician_gloves.max_heat_protection_temperature && electrician_gloves.max_heat_protection_temperature > 360) + if(electrician_gloves.max_heat_protection_temperature > 360) protected = TRUE else protected = TRUE diff --git a/code/modules/projectiles/projectile/bullets/revolver.dm b/code/modules/projectiles/projectile/bullets/revolver.dm index 7436ad2fa482..94c1ae407036 100644 --- a/code/modules/projectiles/projectile/bullets/revolver.dm +++ b/code/modules/projectiles/projectile/bullets/revolver.dm @@ -101,14 +101,16 @@ /obj/projectile/bullet/c38/iceblox //see /obj/projectile/temp for the original code name = ".38 Iceblox bullet" damage = 20 - var/temperature = 100 ricochets_max = 0 + /// How cold to chill the target down to + var/temperature = HYPOTHERMIA - 2 CELCIUS + /obj/projectile/bullet/c38/iceblox/on_hit(atom/target, blocked = 0, pierce_hit) . = ..() if(isliving(target)) var/mob/living/M = target - M.adjust_bodytemperature(((100-blocked)/100)*(temperature - M.bodytemperature)) + M.adjust_bodytemperature(0.34 * ((100-blocked) / 100) * (temperature - M.bodytemperature), use_insulation = TRUE) // .357 (Syndie Revolver) diff --git a/code/modules/projectiles/projectile/energy/thermal.dm b/code/modules/projectiles/projectile/energy/thermal.dm index 41efd21475c6..7409a008b05b 100644 --- a/code/modules/projectiles/projectile/energy/thermal.dm +++ b/code/modules/projectiles/projectile/energy/thermal.dm @@ -12,15 +12,15 @@ /obj/projectile/energy/inferno/on_hit(atom/target, blocked, pierce_hit) ..() - if(!ishuman(target)) + if(!isliving(target)) return - var/mob/living/carbon/cold_target = target + var/mob/living/cold_target = target var/how_cold_is_target = cold_target.bodytemperature - var/danger_zone = cold_target.dna.species.bodytemp_cold_damage_limit - 150 + var/danger_zone = cold_target.bodytemp_cold_damage_limit - 10 CELCIUS if(how_cold_is_target < danger_zone) explosion(cold_target, devastation_range = -1, heavy_impact_range = -1, light_impact_range = 2, flame_range = 3) //maybe stand back a bit - cold_target.bodytemperature = cold_target.dna.species.bodytemp_normal //avoids repeat explosions, maybe could be used to heat up again? + cold_target.adjust_bodytemperature(50 KELVIN, max_temp = cold_target.standard_body_temperature) //avoids repeat explosions, maybe could be used to heat up again? playsound(cold_target, 'sound/weapons/sear.ogg', 30, TRUE, -1) /obj/projectile/energy/cryo @@ -37,14 +37,14 @@ /obj/projectile/energy/cryo/on_hit(atom/target, blocked, pierce_hit) ..() - if(!ishuman(target)) + if(!isliving(target)) return - var/mob/living/carbon/hot_target = target + var/mob/living/hot_target = target var/how_hot_is_target = hot_target.bodytemperature - var/danger_zone = hot_target.dna.species.bodytemp_heat_damage_limit + 300 + var/danger_zone = hot_target.bodytemp_heat_damage_limit + 10 CELCIUS if(how_hot_is_target > danger_zone) hot_target.Knockdown(100) hot_target.apply_damage(20, BURN) - hot_target.bodytemperature = hot_target.dna.species.bodytemp_normal //avoids repeat knockdowns, maybe could be used to cool down again? + hot_target.adjust_bodytemperature(-50 KELVIN, min_temp = hot_target.standard_body_temperature) //avoids repeat knockdowns, maybe could be used to cool down again? playsound(hot_target, 'sound/weapons/sonic_jackhammer.ogg', 30, TRUE, -1) diff --git a/code/modules/projectiles/projectile/special/temperature.dm b/code/modules/projectiles/projectile/special/temperature.dm index 10c652b77b51..56c04108f099 100644 --- a/code/modules/projectiles/projectile/special/temperature.dm +++ b/code/modules/projectiles/projectile/special/temperature.dm @@ -4,34 +4,34 @@ damage = 0 damage_type = BURN armor_flag = ENERGY - var/temperature = -50 // reduce the body temperature by 50 points + /// What temp to trend the target towards + var/temperature = HYPOTHERMIA - 2 CELCIUS + /// How much temp per shot to apply + var/temperature_mod_per_shot = 0.25 /obj/projectile/temp/is_hostile_projectile() - return temperature != 0 // our damage is done by cooling or heating (casting to boolean here) + return BODYTEMP_NORMAL - temperature != 0 // our damage is done by cooling or heating (casting to boolean here) /obj/projectile/temp/on_hit(atom/target, blocked = 0, pierce_hit) . = ..() - if(iscarbon(target)) - var/mob/living/carbon/hit_mob = target - var/thermal_protection = 1 - hit_mob.get_insulation_protection(hit_mob.bodytemperature + temperature) - - // The new body temperature is adjusted by the bullet's effect temperature - // Reduce the amount of the effect temperature change based on the amount of insulation the mob is wearing - hit_mob.adjust_bodytemperature((thermal_protection * temperature) + temperature) - - else if(isliving(target)) - var/mob/living/L = target - // the new body temperature is adjusted by the bullet's effect temperature - L.adjust_bodytemperature((1 - blocked) * temperature) + if(isliving(target)) + var/mob/living/M = target + M.adjust_bodytemperature(temperature_mod_per_shot * ((100-blocked) / 100) * (temperature - M.bodytemperature), use_insulation = TRUE) /obj/projectile/temp/hot name = "heat beam" - temperature = 100 // Raise the body temp by 100 points + temperature = CELCIUS_TO_KELVIN(50 CELCIUS) // Raise the body temp by 100 points /obj/projectile/temp/cryo name = "cryo beam" range = 3 - temperature = -240 // Single slow shot reduces temp greatly + temperature_mod_per_shot = 1.5 // get this guy really chilly really fast + +/obj/projectile/temp/cryo/on_hit(atom/target, blocked, pierce_hit) + . = ..() + if(isopenturf(target)) + var/turf/open/T = target + T.freeze_turf() /obj/projectile/temp/cryo/on_range() var/turf/T = get_turf(src) diff --git a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm index b89ce7dc85e1..afcb401bbf77 100644 --- a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm @@ -204,34 +204,30 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/medicine/c2/hercuri/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) + . = ..() + var/fireheal = -1.25 if(affected_mob.getFireLoss() > 50) - affected_mob.adjustFireLoss(-2 * REM * seconds_per_tick * normalise_creation_purity(), FALSE, required_bodytype = affected_bodytype) - else - affected_mob.adjustFireLoss(-1.25 * REM * seconds_per_tick * normalise_creation_purity(), FALSE, required_bodytype = affected_bodytype) - affected_mob.adjust_bodytemperature(rand(-25,-5) * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, 50) - if(ishuman(affected_mob)) - var/mob/living/carbon/human/humi = affected_mob - humi.adjust_coretemperature(rand(-25,-5) * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, 50) - affected_mob.reagents?.chem_temp += (-10 * REM * seconds_per_tick) + fireheal = -2 + if(affected_mob.adjustFireLoss(fireheal * REM * seconds_per_tick * normalise_creation_purity(), updating_health = FALSE, required_bodytype = affected_bodytype)) + . = TRUE + + var/cooling = -1 KELVIN / rand(1, 5) + affected_mob.adjust_bodytemperature(cooling * REM * seconds_per_tick, min_temp = HYPOTHERMIA - 7 CELCIUS) + affected_mob.reagents?.expose_temperature(affected_mob.reagents.chem_temp - (10 * REM * seconds_per_tick)) affected_mob.adjust_fire_stacks(-1 * REM * seconds_per_tick) - ..() - . = TRUE /datum/reagent/medicine/c2/hercuri/expose_mob(mob/living/carbon/exposed_mob, methods=VAPOR, reac_volume) . = ..() if(!(methods & VAPOR)) return - exposed_mob.adjust_bodytemperature(-reac_volume * TEMPERATURE_DAMAGE_COEFFICIENT, 50) + exposed_mob.adjust_bodytemperature(-reac_volume * -0.33 KELVIN, min_temp = HYPOTHERMIA - 7 CELCIUS, use_insulation = TRUE) exposed_mob.adjust_fire_stacks(reac_volume / -2) if(reac_volume >= metabolization_rate) exposed_mob.extinguish_mob() /datum/reagent/medicine/c2/hercuri/overdose_process(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) - affected_mob.adjust_bodytemperature(-10 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, 50) //chilly chilly - if(ishuman(affected_mob)) - var/mob/living/carbon/human/humi = affected_mob - humi.adjust_coretemperature(-10 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, 50) + affected_mob.adjust_bodytemperature(-0.5 KELVIN * REM * seconds_per_tick, min_temp = HYPOTHERMIA - 7 CELCIUS) //chilly chilly ..() diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm index 79d9a191e845..3083c58a32b8 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm @@ -199,7 +199,7 @@ /datum/reagent/consumable/ethanol/thirteenloko/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) drinker.adjust_drowsiness(-14 SECONDS * REM * seconds_per_tick) drinker.AdjustSleeping(-40 * REM * seconds_per_tick) - drinker.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, drinker.get_body_temp_normal()) + drinker.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = drinker.standard_body_temperature) if(!HAS_TRAIT(drinker, TRAIT_ALCOHOL_TOLERANCE)) drinker.set_jitter_if_lower(10 SECONDS) ..() @@ -679,7 +679,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/ethanol/toxins_special/on_mob_life(mob/living/drinker, seconds_per_tick, times_fired) - drinker.adjust_bodytemperature(15 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, drinker.get_body_temp_normal() + 20) //310.15 is the normal bodytemp. + drinker.adjust_bodytemperature(WARM_DRINK * REM * seconds_per_tick, max_temp = drinker.standard_body_temperature + 4 KELVIN) //310.15 is the normal bodytemp. return ..() /datum/reagent/consumable/ethanol/beepsky_smash @@ -866,7 +866,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/ethanol/antifreeze/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) - drinker.adjust_bodytemperature(20 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, drinker.get_body_temp_normal() + 20) //310.15 is the normal bodytemp. + drinker.adjust_bodytemperature(2 * WARM_DRINK * REM * seconds_per_tick, max_temp = drinker.standard_body_temperature + 4 KELVIN) //310.15 is the normal bodytemp. return ..() /datum/reagent/consumable/ethanol/barefoot @@ -1047,7 +1047,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/ethanol/sbiten/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) - drinker.adjust_bodytemperature(50 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, BODYTEMP_HEAT_DAMAGE_LIMIT) //310.15 is the normal bodytemp. + drinker.adjust_bodytemperature(2.5 * WARM_DRINK * REM * seconds_per_tick, max_temp = drinker.standard_body_temperature + 8 KELVIN) //310.15 is the normal bodytemp. return ..() /datum/reagent/consumable/ethanol/red_mead @@ -1078,7 +1078,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/ethanol/iced_beer/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) - drinker.adjust_bodytemperature(-20 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, T0C) //310.15 is the normal bodytemp. + drinker.adjust_bodytemperature(2 * COLD_DRINK * REM * seconds_per_tick, min_temp = T0C) //310.15 is the normal bodytemp. return ..() /datum/reagent/consumable/ethanol/grog @@ -1608,7 +1608,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/ethanol/squirt_cider/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) - drinker.satiety += 5 * REM * seconds_per_tick //for context, vitamins give 15 satiety per second + drinker.adjust_satiety(5 * REM * seconds_per_tick) //for context, vitamins give 15 satiety per second ..() . = TRUE @@ -1632,7 +1632,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/ethanol/sugar_rush/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) - drinker.satiety -= 10 * REM * seconds_per_tick //junky as hell! a whole glass will keep you from being able to eat junk food + drinker.adjust_satiety(-10 * REM * seconds_per_tick)//junky as hell! a whole glass will keep you from being able to eat junk food ..() . = TRUE @@ -1670,7 +1670,7 @@ /datum/reagent/consumable/ethanol/peppermint_patty/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) drinker.apply_status_effect(/datum/status_effect/throat_soothed) - drinker.adjust_bodytemperature(5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, drinker.get_body_temp_normal()) + drinker.adjust_bodytemperature(WARM_DRINK * REM * seconds_per_tick, max_temp = drinker.standard_body_temperature) ..() /datum/reagent/consumable/ethanol/alexander @@ -2162,7 +2162,7 @@ /datum/reagent/consumable/ethanol/mauna_loa/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) // Heats the user up while the reagent is in the body. Occasionally makes you burst into flames. - drinker.adjust_bodytemperature(25 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick) + drinker.adjust_bodytemperature(2.5 * WARM_DRINK * REM * seconds_per_tick) if (SPT_PROB(2.5, seconds_per_tick)) drinker.adjust_fire_stacks(1) drinker.ignite_mob() @@ -2535,7 +2535,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/ethanol/gin_garden/on_mob_life(mob/living/carbon/doll, seconds_per_tick, times_fired) - doll.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, doll.get_body_temp_normal()) + doll.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = doll.standard_body_temperature) ..() /datum/reagent/consumable/ethanol/wine_voltaic diff --git a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm index ac83949dd483..c332365c9e21 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm @@ -250,7 +250,7 @@ affected_mob.adjust_drowsiness(-6 SECONDS * REM * seconds_per_tick) affected_mob.AdjustSleeping(-40 * REM * seconds_per_tick) //310.15 is the normal bodytemp. - affected_mob.adjust_bodytemperature(25 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(WARM_DRINK * REM * seconds_per_tick, max_temp = affected_mob.standard_body_temperature) if(holder.has_reagent(/datum/reagent/consumable/frostoil)) holder.remove_reagent(/datum/reagent/consumable/frostoil, 5 * REM * seconds_per_tick) ..() @@ -280,7 +280,7 @@ if(!to_chatted && helped) to_chat(affected_mob, span_notice("A calm, relaxed feeling suffuses you. Your wounds feel a little healthier.")) to_chatted = TRUE - affected_mob.adjust_bodytemperature(20 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() . = TRUE @@ -342,7 +342,7 @@ affected_mob.adjust_dizzy(-10 SECONDS * REM * seconds_per_tick) affected_mob.adjust_drowsiness(-6 SECONDS * REM * seconds_per_tick) affected_mob.AdjustSleeping(-40 * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(1.5 * COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) affected_mob.set_jitter_if_lower(10 SECONDS * REM * seconds_per_tick) ..() . = TRUE @@ -359,7 +359,7 @@ affected_mob.adjust_dizzy(-10 SECONDS * REM * seconds_per_tick) affected_mob.adjust_drowsiness(-6 SECONDS * REM * seconds_per_tick) affected_mob.AdjustSleeping(-60 * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-7 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) affected_mob.set_jitter_if_lower(10 SECONDS * REM * seconds_per_tick) affected_mob.adjustToxLoss(1 * REM * seconds_per_tick, FALSE, required_biotype = affected_biotype) ..() @@ -379,7 +379,7 @@ affected_mob.AdjustSleeping(-40 * REM * seconds_per_tick) if(affected_mob.getToxLoss() && SPT_PROB(10, seconds_per_tick)) affected_mob.adjustToxLoss(-1, FALSE, required_biotype = affected_biotype) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() . = TRUE @@ -392,7 +392,7 @@ /datum/reagent/consumable/space_cola/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) affected_mob.adjust_drowsiness(-10 SECONDS * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() /datum/reagent/consumable/roy_rogers @@ -406,7 +406,7 @@ /datum/reagent/consumable/roy_rogers/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) affected_mob.set_jitter_if_lower(12 SECONDS * REM * seconds_per_tick) affected_mob.adjust_drowsiness(-10 SECONDS * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) return ..() /datum/reagent/consumable/nuka_cola @@ -431,7 +431,7 @@ affected_mob.adjust_dizzy(3 SECONDS * REM * seconds_per_tick) affected_mob.remove_status_effect(/datum/status_effect/drowsiness) affected_mob.AdjustSleeping(-40 * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() . = TRUE @@ -492,7 +492,7 @@ affected_mob.adjust_dizzy(2 SECONDS * REM * seconds_per_tick) affected_mob.remove_status_effect(/datum/status_effect/drowsiness) affected_mob.AdjustSleeping(-40 * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() /datum/reagent/consumable/spacemountainwind @@ -505,7 +505,7 @@ /datum/reagent/consumable/spacemountainwind/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) affected_mob.adjust_drowsiness(-14 SECONDS * REM * seconds_per_tick) affected_mob.AdjustSleeping(-20 * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) affected_mob.set_jitter_if_lower(10 SECONDS * REM * seconds_per_tick) ..() . = TRUE @@ -519,7 +519,7 @@ /datum/reagent/consumable/dr_gibb/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) affected_mob.adjust_drowsiness(-12 SECONDS * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() /datum/reagent/consumable/space_up @@ -530,7 +530,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/space_up/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) - affected_mob.adjust_bodytemperature(-8 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(1.5 * COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() /datum/reagent/consumable/lemon_lime @@ -541,7 +541,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/lemon_lime/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) - affected_mob.adjust_bodytemperature(-8 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(1.5 * COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() /datum/reagent/consumable/pwr_game @@ -559,7 +559,7 @@ You feel as though a great secret of the universe has been made known to you...
") /datum/reagent/consumable/pwr_game/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) - affected_mob.adjust_bodytemperature(-8 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(1.5 * COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) if(SPT_PROB(5, seconds_per_tick)) affected_mob.mind?.adjust_experience(/datum/skill/gaming, 5) ..() @@ -572,7 +572,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/shamblers/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) - affected_mob.adjust_bodytemperature(-8 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(1.5 * COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() /datum/reagent/consumable/sodawater @@ -585,7 +585,7 @@ /datum/reagent/consumable/sodawater/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) affected_mob.adjust_dizzy(-10 SECONDS * REM * seconds_per_tick) affected_mob.adjust_drowsiness(-6 SECONDS * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() /datum/reagent/consumable/tonic @@ -599,7 +599,7 @@ affected_mob.adjust_dizzy(-10 SECONDS * REM * seconds_per_tick) affected_mob.adjust_drowsiness(-6 SECONDS * REM * seconds_per_tick) affected_mob.AdjustSleeping(-40 * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() . = TRUE @@ -634,7 +634,7 @@ affected_mob.adjust_dizzy(2 SECONDS * REM * seconds_per_tick) affected_mob.remove_status_effect(/datum/status_effect/drowsiness) affected_mob.AdjustSleeping(-40 * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() /datum/reagent/consumable/monkey_energy/on_mob_metabolize(mob/living/affected_mob) @@ -661,7 +661,7 @@ default_container = /obj/item/reagent_containers/cup/glass/ice /datum/reagent/consumable/ice/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() /datum/reagent/consumable/soy_latte @@ -677,7 +677,7 @@ affected_mob.adjust_dizzy(-10 SECONDS * REM * seconds_per_tick) affected_mob.adjust_drowsiness(-6 SECONDS * REM * seconds_per_tick) affected_mob.SetSleeping(0) - affected_mob.adjust_bodytemperature(5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(WARM_DRINK * REM * seconds_per_tick, max_temp = affected_mob.standard_body_temperature) affected_mob.set_jitter_if_lower(10 SECONDS * REM * seconds_per_tick) if(affected_mob.getBruteLoss() && SPT_PROB(10, seconds_per_tick)) affected_mob.heal_bodypart_damage(1,0) @@ -697,7 +697,7 @@ affected_mob.adjust_dizzy(-10 SECONDS * REM * seconds_per_tick) affected_mob.adjust_drowsiness(-12 SECONDS * REM * seconds_per_tick) affected_mob.SetSleeping(0) - affected_mob.adjust_bodytemperature(5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(WARM_DRINK * REM * seconds_per_tick, max_temp = affected_mob.standard_body_temperature) affected_mob.set_jitter_if_lower(10 SECONDS * REM * seconds_per_tick) if(affected_mob.getBruteLoss() && SPT_PROB(10, seconds_per_tick)) affected_mob.heal_bodypart_damage(1, 0) @@ -854,7 +854,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/grape_soda/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() /datum/reagent/consumable/milk/chocolate_milk @@ -874,7 +874,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/hot_coco/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) - affected_mob.adjust_bodytemperature(5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(WARM_DRINK * REM * seconds_per_tick, max_temp = affected_mob.standard_body_temperature) if(affected_mob.getBruteLoss() && SPT_PROB(10, seconds_per_tick)) affected_mob.heal_bodypart_damage(1, 0) . = TRUE @@ -892,7 +892,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/italian_coco/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) - affected_mob.adjust_bodytemperature(5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(WARM_DRINK * REM * seconds_per_tick, max_temp = affected_mob.standard_body_temperature) return ..() /datum/reagent/consumable/menthol @@ -945,7 +945,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/cream_soda/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) - affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) ..() /datum/reagent/consumable/sol_dry @@ -1035,7 +1035,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/agua_fresca/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) - affected_mob.adjust_bodytemperature(-8 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(1.5 * COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) if(affected_mob.getToxLoss() && SPT_PROB(10, seconds_per_tick)) affected_mob.adjustToxLoss(-0.5, FALSE, required_biotype = affected_biotype) return ..() @@ -1135,7 +1135,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/cucumberlemonade/on_mob_life(mob/living/carbon/doll, seconds_per_tick, times_fired) - doll.adjust_bodytemperature(-8 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, doll.get_body_temp_normal()) + doll.adjust_bodytemperature(1.5 * COLD_DRINK * REM * seconds_per_tick, min_temp = doll.standard_body_temperature) if(doll.getToxLoss() && SPT_PROB(10, seconds_per_tick)) doll.adjustToxLoss(-0.5, FALSE, required_biotype = affected_biotype) return ..() diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 4493b5c13971..ccbdcae8400a 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -120,8 +120,7 @@ burn_heal = 1 /datum/reagent/consumable/nutriment/vitamin/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) - if(M.satiety < MAX_SATIETY) - M.satiety += 30 * REM * seconds_per_tick + M.adjust_satiety(30 * REM * seconds_per_tick) . = ..() /// The basic resource of vat growing. @@ -281,28 +280,21 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/capsaicin/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + . = ..() + holder.remove_reagent(/datum/reagent/cryostylane, 5 * REM * seconds_per_tick) + var/heating = 0 switch(current_cycle) if(1 to 15) - heating = 5 - if(holder.has_reagent(/datum/reagent/cryostylane)) - holder.remove_reagent(/datum/reagent/cryostylane, 5 * REM * seconds_per_tick) - if(isslime(M)) - heating = rand(5, 20) + heating = 0.1 KELVIN if(15 to 25) - heating = 10 - if(isslime(M)) - heating = rand(10, 20) + heating = 0.33 KELVIN if(25 to 35) - heating = 15 - if(isslime(M)) - heating = rand(15, 20) + heating = 0.66 KELVIN if(35 to INFINITY) - heating = 20 - if(isslime(M)) - heating = rand(20, 25) - M.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick) - ..() + heating = 1.2 KELVIN + + M.adjust_bodytemperature(heating * REM * seconds_per_tick, max_temp = CELCIUS_TO_KELVIN(39 CELCIUS)) /datum/reagent/consumable/frostoil name = "Frost Oil" @@ -318,32 +310,25 @@ turf_exposure = TRUE /datum/reagent/consumable/frostoil/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + . = ..() + holder.remove_reagent(/datum/reagent/consumable/capsaicin, 5 * REM * seconds_per_tick) + var/cooling = 0 switch(current_cycle) if(1 to 15) - cooling = -10 - if(holder.has_reagent(/datum/reagent/consumable/capsaicin)) - holder.remove_reagent(/datum/reagent/consumable/capsaicin, 5 * REM * seconds_per_tick) - if(isslime(M)) - cooling = -rand(5, 20) + cooling = -0.1 KELVIN if(15 to 25) - cooling = -20 - if(isslime(M)) - cooling = -rand(10, 20) + cooling = -0.5 KELVIN if(25 to 35) - cooling = -30 + cooling = -1 KELVIN if(prob(1)) M.emote("shiver") - if(isslime(M)) - cooling = -rand(15, 20) if(35 to INFINITY) - cooling = -40 + cooling = -2 KELVIN if(prob(5)) M.emote("shiver") - if(isslime(M)) - cooling = -rand(20, 25) - M.adjust_bodytemperature(cooling * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, 50) - ..() + + M.adjust_bodytemperature(cooling * REM * seconds_per_tick, min_temp = CELCIUS_TO_KELVIN(36 CELCIUS)) /datum/reagent/consumable/frostoil/expose_turf(turf/exposed_turf, reac_volume) . = ..() @@ -590,7 +575,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/hot_ramen/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) - M.adjust_bodytemperature(10 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, 0, M.get_body_temp_normal()) + M.adjust_bodytemperature(0.2 KELVIN * REM * seconds_per_tick, 0, M.standard_body_temperature) ..() /datum/reagent/consumable/hell_ramen @@ -602,7 +587,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/hell_ramen/on_mob_life(mob/living/carbon/target_mob, seconds_per_tick, times_fired) - target_mob.adjust_bodytemperature(10 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick) + target_mob.adjust_bodytemperature(WARM_DRINK KELVIN * REM * seconds_per_tick, max_temp = CELCIUS_TO_KELVIN(45 CELCIUS)) ..() /datum/reagent/consumable/flour diff --git a/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm index b4d869631672..760e6269129a 100644 --- a/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm @@ -280,29 +280,21 @@ Basically, we fill the time between now and 2s from now with hands based off the /datum/reagent/inverse/hercuri/on_mob_life(mob/living/carbon/owner, seconds_per_tick, times_fired) . = ..() var/heating = rand(5, 25) * creation_purity * REM * seconds_per_tick - owner.reagents?.chem_temp += heating - owner.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT) - if(!ishuman(owner)) - return - var/mob/living/carbon/human/human = owner - human.adjust_coretemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT) + owner.reagents?.expose_temperature(owner.reagents.chem_temp + heating, 1) + owner.adjust_bodytemperature(heating * 0.2 KELVIN) /datum/reagent/inverse/hercuri/expose_mob(mob/living/carbon/exposed_mob, methods=VAPOR, reac_volume) . = ..() if(!(methods & VAPOR)) return - exposed_mob.adjust_bodytemperature(reac_volume * TEMPERATURE_DAMAGE_COEFFICIENT) + exposed_mob.adjust_bodytemperature(reac_volume * 0.33 KELVIN, use_insulation = TRUE) exposed_mob.adjust_fire_stacks(reac_volume / 2) /datum/reagent/inverse/hercuri/overdose_process(mob/living/carbon/owner, seconds_per_tick, times_fired) . = ..() owner.adjustOrganLoss(ORGAN_SLOT_LIVER, 2 * REM * seconds_per_tick, required_organtype = affected_organtype) //Makes it so you can't abuse it with pyroxadone very easily (liver dies from 25u unless it's fully upgraded) - var/heating = 10 * creation_purity * REM * seconds_per_tick * TEMPERATURE_DAMAGE_COEFFICIENT - owner.adjust_bodytemperature(heating) //hot hot - if(ishuman(owner)) - var/mob/living/carbon/human/human = owner - human.adjust_coretemperature(heating) + owner.adjust_bodytemperature(0.5 KELVIN * creation_purity * REM * seconds_per_tick) //hot hot /datum/reagent/inverse/healing/tirimol name = "Super Melatonin"//It's melatonin, but super! @@ -383,20 +375,20 @@ Basically, we fill the time between now and 2s from now with hands based off the apply_lung_levels(lungs) /datum/reagent/inverse/healing/convermol/proc/apply_lung_levels(obj/item/organ/internal/lungs/lungs) - cached_heat_level_1 = lungs.heat_level_1_threshold - cached_heat_level_2 = lungs.heat_level_2_threshold - cached_heat_level_3 = lungs.heat_level_3_threshold - cached_cold_level_1 = lungs.cold_level_1_threshold - cached_cold_level_2 = lungs.cold_level_2_threshold - cached_cold_level_3 = lungs.cold_level_3_threshold + cached_heat_level_1 = lungs.heat_level_warning_threshold + cached_heat_level_2 = lungs.heat_level_hazard_threshold + cached_heat_level_3 = lungs.heat_level_danger_threshold + cached_cold_level_1 = lungs.cold_level_warning_threshold + cached_cold_level_2 = lungs.cold_level_hazard_threshold + cached_cold_level_3 = lungs.cold_level_danger_threshold //Heat threshold is increased - lungs.heat_level_1_threshold *= creation_purity * 1.5 - lungs.heat_level_2_threshold *= creation_purity * 1.5 - lungs.heat_level_3_threshold *= creation_purity * 1.5 + lungs.heat_level_warning_threshold *= creation_purity * 1.5 + lungs.heat_level_hazard_threshold *= creation_purity * 1.5 + lungs.heat_level_danger_threshold *= creation_purity * 1.5 //Cold threshold is decreased - lungs.cold_level_1_threshold *= creation_purity * 0.5 - lungs.cold_level_2_threshold *= creation_purity * 0.5 - lungs.cold_level_3_threshold *= creation_purity * 0.5 + lungs.cold_level_warning_threshold *= creation_purity * 0.5 + lungs.cold_level_hazard_threshold *= creation_purity * 0.5 + lungs.cold_level_danger_threshold *= creation_purity * 0.5 /datum/reagent/inverse/healing/convermol/proc/on_removed_organ(mob/prev_owner, obj/item/organ/organ) SIGNAL_HANDLER @@ -406,12 +398,12 @@ Basically, we fill the time between now and 2s from now with hands based off the restore_lung_levels(lungs) /datum/reagent/inverse/healing/convermol/proc/restore_lung_levels(obj/item/organ/internal/lungs/lungs) - lungs.heat_level_1_threshold = cached_heat_level_1 - lungs.heat_level_2_threshold = cached_heat_level_2 - lungs.heat_level_3_threshold = cached_heat_level_3 - lungs.cold_level_1_threshold = cached_cold_level_1 - lungs.cold_level_2_threshold = cached_cold_level_2 - lungs.cold_level_3_threshold = cached_cold_level_3 + lungs.heat_level_warning_threshold = cached_heat_level_1 + lungs.heat_level_hazard_threshold = cached_heat_level_2 + lungs.heat_level_danger_threshold = cached_heat_level_3 + lungs.cold_level_warning_threshold = cached_cold_level_1 + lungs.cold_level_hazard_threshold = cached_cold_level_2 + lungs.cold_level_danger_threshold = cached_cold_level_3 /datum/reagent/inverse/healing/convermol/on_mob_delete(mob/living/owner) . = ..() diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 3127f3db80e2..dda83942232c 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -22,19 +22,14 @@ color = "#DB90C6" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED -/datum/reagent/medicine/leporazine/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) - var/target_temp = affected_mob.get_body_temp_normal(apply_change = FALSE) - if(affected_mob.bodytemperature > target_temp) - affected_mob.adjust_bodytemperature(-40 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, target_temp) - else if(affected_mob.bodytemperature < (target_temp + 1)) - affected_mob.adjust_bodytemperature(40 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, 0, target_temp) - if(ishuman(affected_mob)) - var/mob/living/carbon/human/affected_human = affected_mob - if(affected_human.coretemperature > target_temp) - affected_human.adjust_coretemperature(-40 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, target_temp) - else if(affected_human.coretemperature < (target_temp + 1)) - affected_human.adjust_coretemperature(40 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, 0, target_temp) - ..() +/datum/reagent/medicine/leporazine/on_mob_metabolize(mob/living/carbon/user) + . = ..() + user.add_homeostasis_level(type, user.standard_body_temperature, 1 KELVIN) + +/datum/reagent/medicine/leporazine/on_mob_end_metabolize(mob/living/carbon/user) + . = ..() + user.remove_homeostasis_level(type) + /datum/reagent/medicine/adminordrazine //An OP chemical for admins name = "Adminordrazine" diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm index 173d503cf547..74f000f2931b 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm @@ -245,10 +245,7 @@ metabolization_rate = 0.25 * REM//faster consumption when alive if(affected_mob.reagents.has_reagent(/datum/reagent/oxygen)) affected_mob.reagents.remove_reagent(/datum/reagent/oxygen, 0.5 * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-15 * REM * seconds_per_tick) - if(ishuman(affected_mob)) - var/mob/living/carbon/human/humi = affected_mob - humi.adjust_coretemperature(-15 * REM * seconds_per_tick) + affected_mob.adjust_bodytemperature(-1 KELVIN * REM * seconds_per_tick) ..() /datum/reagent/cryostylane/expose_turf(turf/exposed_turf, reac_volume) @@ -275,10 +272,7 @@ /datum/reagent/pyrosium/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) if(holder.has_reagent(/datum/reagent/oxygen)) holder.remove_reagent(/datum/reagent/oxygen, 0.5 * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(15 * REM * seconds_per_tick) - if(ishuman(affected_mob)) - var/mob/living/carbon/human/humi = affected_mob - humi.adjust_coretemperature(15 * REM * seconds_per_tick) + affected_mob.adjust_bodytemperature(1 KELVIN * REM * seconds_per_tick) ..() /datum/reagent/pyrosium/burn(datum/reagents/holder) diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 1638e65e9696..f7f2adfdaf02 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -163,10 +163,7 @@ if(holder.has_reagent(/datum/reagent/medicine/epinephrine)) holder.remove_reagent(/datum/reagent/medicine/epinephrine, 2 * REM * seconds_per_tick) affected_mob.adjustPlasma(20 * REM * seconds_per_tick) - affected_mob.adjust_bodytemperature(-7 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, affected_mob.get_body_temp_normal()) - if(ishuman(affected_mob)) - var/mob/living/carbon/human/humi = affected_mob - humi.adjust_coretemperature(-7 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + affected_mob.adjust_bodytemperature(COLD_DRINK * REM * seconds_per_tick, min_temp = affected_mob.standard_body_temperature) return ..() /datum/reagent/toxin/hot_ice/on_mob_metabolize(mob/living/carbon/affected_mob) diff --git a/code/modules/religion/pyre_rites.dm b/code/modules/religion/pyre_rites.dm index 28ef53968f9c..2a2b3c606ff8 100644 --- a/code/modules/religion/pyre_rites.dm +++ b/code/modules/religion/pyre_rites.dm @@ -3,7 +3,6 @@ /datum/religion_rites/fireproof/proc/apply_fireproof(obj/item/clothing/fireproofed) fireproofed.name = "unmelting [fireproofed.name]" fireproofed.max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT - fireproofed.heat_protection = chosen_clothing.body_parts_covered fireproofed.resistance_flags |= FIRE_PROOF /datum/religion_rites/fireproof diff --git a/code/modules/research/xenobiology/crossbreeding/_potions.dm b/code/modules/research/xenobiology/crossbreeding/_potions.dm index 1e6205dc8039..08c80609d7e4 100644 --- a/code/modules/research/xenobiology/crossbreeding/_potions.dm +++ b/code/modules/research/xenobiology/crossbreeding/_potions.dm @@ -129,7 +129,6 @@ Slimecrossing Potions C.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) C.add_atom_colour("#000080", FIXED_COLOUR_PRIORITY) C.min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT - C.cold_protection = C.body_parts_covered C.clothing_flags |= STOPSPRESSUREDAMAGE uses-- if(!uses) diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index 6c91d1a863d6..67c92ea362ca 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -213,13 +213,12 @@ return ..() /datum/status_effect/bonechill/tick() - if(prob(50)) - owner.adjustFireLoss(1) - owner.set_jitter_if_lower(6 SECONDS) - owner.adjust_bodytemperature(-10) - if(ishuman(owner)) - var/mob/living/carbon/human/humi = owner - humi.adjust_coretemperature(-10) + if(!prob(50)) + return + + owner.adjustFireLoss(1) + owner.set_jitter_if_lower(6 SECONDS) + owner.adjust_bodytemperature(-1 KELVIN) /datum/status_effect/bonechill/on_remove() owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/bonechill) @@ -234,7 +233,7 @@ alert_type = null /datum/status_effect/rebreathing/tick() - owner.adjustOxyLoss(-6, 0) //Just a bit more than normal breathing. + owner.adjustOxyLoss(-6) //Just a bit more than normal breathing. /////////////////////////////////////////////////////// //////////////////CONSUMING EXTRACTS/////////////////// @@ -247,12 +246,12 @@ duration = 100 /datum/status_effect/firecookie/on_apply() - ADD_TRAIT(owner, TRAIT_RESISTCOLD,"firecookie") - owner.adjust_bodytemperature(110) + ADD_TRAIT(owner, TRAIT_RESISTCOLD, id) + owner.adjust_bodytemperature(20 KELVIN) return ..() /datum/status_effect/firecookie/on_remove() - REMOVE_TRAIT(owner, TRAIT_RESISTCOLD,"firecookie") + REMOVE_TRAIT(owner, TRAIT_RESISTCOLD, id) /datum/status_effect/watercookie id = "watercookie" @@ -488,21 +487,12 @@ colour = "orange" /datum/status_effect/stabilized/orange/tick() - var/body_temp_target = owner.get_body_temp_normal(apply_change = FALSE) + owner.update_homeostasis_level(id, owner.standard_body_temperature, 0.5 KELVIN) - var/body_temp_actual = owner.bodytemperature - var/body_temp_offset = body_temp_target - body_temp_actual - body_temp_offset = clamp(body_temp_offset, -5, 5) - owner.adjust_bodytemperature(body_temp_offset) - if(ishuman(owner)) - var/mob/living/carbon/human/human = owner - var/core_temp_actual = human.coretemperature - var/core_temp_offset = body_temp_target - core_temp_actual - core_temp_offset = clamp(core_temp_offset, -5, 5) - human.adjust_coretemperature(core_temp_offset) - - return ..() +/datum/status_effect/stabilized/orange/on_remove() + . = ..() + owner.remove_homeostasis_level(id) /datum/status_effect/stabilized/purple id = "stabilizedpurple" diff --git a/code/modules/research/xenobiology/crossbreeding/burning.dm b/code/modules/research/xenobiology/crossbreeding/burning.dm index 4ccc9567271a..d33c314d6277 100644 --- a/code/modules/research/xenobiology/crossbreeding/burning.dm +++ b/code/modules/research/xenobiology/crossbreeding/burning.dm @@ -70,9 +70,10 @@ Burning extracts: for(var/turf/open/T in range(3, get_turf(user))) T.MakeSlippery(TURF_WET_PERMAFROST, min_wet_time = 10, wet_time_to_add = 5) for(var/mob/living/carbon/M in range(5, get_turf(user))) - if(M != user) - M.bodytemperature = BODYTEMP_COLD_DAMAGE_LIMIT + 10 //Not quite cold enough to hurt. - to_chat(M, span_danger("You feel a chill run down your spine, and the floor feels a bit slippery with frost...")) + if(M == user) + continue + M.adjust_bodytemperature(-INFINITY, min_temp = M.bodytemp_cold_damage_limit + 5 KELVIN) + to_chat(M, span_danger("You feel a chill run down your spine, and the floor feels a bit slippery with frost...")) ..() /obj/item/slimecross/burning/metal diff --git a/code/modules/research/xenobiology/crossbreeding/regenerative.dm b/code/modules/research/xenobiology/crossbreeding/regenerative.dm index 98821ff7176f..787af8195771 100644 --- a/code/modules/research/xenobiology/crossbreeding/regenerative.dm +++ b/code/modules/research/xenobiology/crossbreeding/regenerative.dm @@ -133,7 +133,6 @@ Regenerative extracts: C.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) C.add_atom_colour("#000080", FIXED_COLOUR_PRIORITY) C.max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT - C.heat_protection = C.body_parts_covered C.resistance_flags |= FIRE_PROOF /obj/item/slimecross/regenerative/silver diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index edc0b1313653..59842f960b5b 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -927,7 +927,6 @@ clothing.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) clothing.add_atom_colour("#000080", FIXED_COLOUR_PRIORITY) clothing.max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT - clothing.heat_protection = clothing.body_parts_covered clothing.resistance_flags |= FIRE_PROOF uses -- if(!uses) diff --git a/code/modules/spells/spell_types/pointed/abyssal_gaze.dm b/code/modules/spells/spell_types/pointed/abyssal_gaze.dm index a7336ef7834a..7a1d13275760 100644 --- a/code/modules/spells/spell_types/pointed/abyssal_gaze.dm +++ b/code/modules/spells/spell_types/pointed/abyssal_gaze.dm @@ -21,7 +21,7 @@ /// The duration of the blind on our target var/blind_duration = 4 SECONDS /// The amount of temperature we take from our target - var/amount_to_cool = 200 + var/amount_to_cool = CELCIUS_TO_KELVIN(10 CELCIUS) /datum/action/cooldown/spell/pointed/abyssal_gaze/is_valid_target(atom/cast_on) return iscarbon(cast_on) @@ -37,7 +37,4 @@ cast_on.playsound_local(get_turf(cast_on), 'sound/hallucinations/i_see_you1.ogg', 50, 1) owner.playsound_local(get_turf(owner), 'sound/effects/ghost2.ogg', 50, 1) cast_on.adjust_temp_blindness(blind_duration) - if(ishuman(cast_on)) - var/mob/living/carbon/human/human_cast_on = cast_on - human_cast_on.adjust_coretemperature(-amount_to_cool) cast_on.adjust_bodytemperature(-amount_to_cool) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index b02dadcdb8d6..9af1cccf4b79 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -759,6 +759,8 @@ owner = new_owner var/needs_update_disabled = FALSE //Only really relevant if there's an owner if(old_owner) + if(length(bodypart_traits)) + old_owner.remove_traits(bodypart_traits, bodypart_trait_source) if(speed_modifier) old_owner.update_bodypart_speed_modifier() if(initial(can_be_disabled)) @@ -774,6 +776,8 @@ )) UnregisterSignal(old_owner, COMSIG_ATOM_RESTYLE) if(owner) + if(length(bodypart_traits)) + owner.add_traits(bodypart_traits, bodypart_trait_source) if(speed_modifier) owner.update_bodypart_speed_modifier() if(initial(can_be_disabled)) diff --git a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm index 1b496fc3bd74..4abb67e9f77c 100644 --- a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm @@ -8,6 +8,7 @@ icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' limb_id = SPECIES_LIZARD is_dimorphic = FALSE + bodypart_traits = list(TRAIT_COLD_BLOODED) /obj/item/bodypart/arm/left/lizard icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index 144a77d63e0f..fa2674247416 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -170,6 +170,7 @@ limb_id = SPECIES_ZOMBIE is_dimorphic = FALSE should_draw_greyscale = FALSE + bodypart_traits = list(TRAIT_COLD_BLOODED) /obj/item/bodypart/arm/left/zombie limb_id = SPECIES_ZOMBIE diff --git a/code/modules/surgery/organs/external/_external_organs.dm b/code/modules/surgery/organs/external/_external_organs.dm index ecc1259e00e6..d3d3e6333e6f 100644 --- a/code/modules/surgery/organs/external/_external_organs.dm +++ b/code/modules/surgery/organs/external/_external_organs.dm @@ -284,7 +284,7 @@ /obj/item/organ/external/antennae/proc/try_burn_antennae(mob/living/carbon/human/human) SIGNAL_HANDLER - if(!burnt && human.bodytemperature >= 800 && human.fire_stacks > 0) //do not go into the extremely hot light. you will not survive + if(!burnt && human.get_skin_temperature() >= CELCIUS_TO_KELVIN(175 CELCIUS) && human.fire_stacks > 0) //do not go into the extremely hot light. you will not survive to_chat(human, span_danger("Your precious antennae burn to a crisp!")) burn_antennae() diff --git a/code/modules/surgery/organs/external/wings/moth_wings.dm b/code/modules/surgery/organs/external/wings/moth_wings.dm index f13b346ab075..9c2f7098d626 100644 --- a/code/modules/surgery/organs/external/wings/moth_wings.dm +++ b/code/modules/surgery/organs/external/wings/moth_wings.dm @@ -44,7 +44,7 @@ /obj/item/organ/external/wings/moth/proc/try_burn_wings(mob/living/carbon/human/human) SIGNAL_HANDLER - if(!burnt && human.bodytemperature >= 800 && human.fire_stacks > 0) //do not go into the extremely hot light. you will not survive + if(!burnt && human.get_skin_temperature() >= CELCIUS_TO_KELVIN(175 CELCIUS) && human.fire_stacks > 0) //do not go into the extremely hot light. you will not survive to_chat(human, span_danger("Your precious wings burn to a crisp!")) human.add_mood_event("burnt_wings", /datum/mood_event/burnt_wings) diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index 18b052f91ef5..a06c310b44e2 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -85,22 +85,30 @@ var/tritium_irradiation_probability_min = 10 var/tritium_irradiation_probability_max = 60 + /// Message displayed when breathing cold air var/cold_message = "your face freezing and an icicle forming" - var/cold_level_1_threshold = 260 - var/cold_level_2_threshold = 200 - var/cold_level_3_threshold = 120 - var/cold_level_1_damage = COLD_GAS_DAMAGE_LEVEL_1 //Keep in mind with gas damage levels, you can set these to be negative, if you want someone to heal, instead. - var/cold_level_2_damage = COLD_GAS_DAMAGE_LEVEL_2 - var/cold_level_3_damage = COLD_GAS_DAMAGE_LEVEL_3 + /// At this threshold, a cold breath displays a warning message + var/cold_level_warning_threshold = CELCIUS_TO_KELVIN(-13.15 CELCIUS) + /// At this threshold, a cold breath deals a minor amount of damage + var/cold_level_hazard_threshold = CELCIUS_TO_KELVIN(-73.15 CELCIUS) + /// At this threshold, a cold breath deals a moderate amount of damage + var/cold_level_danger_threshold = CELCIUS_TO_KELVIN(-153.15 CELCIUS) + /// Amount of damage dealt by a cold breath. Halved if at the hazard threshold + var/cold_level_damage = 3 + /// Type of damage dealt by a cold breath var/cold_damage_type = BURN + /// Message displayed when breathing hot air var/hot_message = "your face burning and a searing heat" - var/heat_level_1_threshold = 360 - var/heat_level_2_threshold = 400 - var/heat_level_3_threshold = 1000 - var/heat_level_1_damage = HEAT_GAS_DAMAGE_LEVEL_1 - var/heat_level_2_damage = HEAT_GAS_DAMAGE_LEVEL_2 - var/heat_level_3_damage = HEAT_GAS_DAMAGE_LEVEL_3 + /// At this threshold, a hot breath displays a warning message + var/heat_level_warning_threshold = CELCIUS_TO_KELVIN(86.85 CELCIUS) + /// At this threshold, a hot breath deals a minor amount of damage + var/heat_level_hazard_threshold = CELCIUS_TO_KELVIN(126.85 CELCIUS) + /// At this threshold, a hot breath deals a moderate amount of damage + var/heat_level_danger_threshold = CELCIUS_TO_KELVIN(726.85 CELCIUS) + /// Amount of damage dealt by a hot breath. Halved if at the hazard threshold + var/heat_level_damage = 8 + /// Type of damage dealt by a hot breath var/heat_damage_type = BURN var/crit_stabilizing_reagent = /datum/reagent/medicine/epinephrine @@ -792,47 +800,47 @@ /obj/item/organ/internal/lungs/proc/handle_breath_temperature(datum/gas_mixture/breath, mob/living/carbon/human/breather) // called by human/life, handles temperatures var/breath_temperature = breath.temperature - if(!HAS_TRAIT(breather, TRAIT_RESISTCOLD)) // COLD DAMAGE - var/cold_modifier = breather.dna.species.coldmod + if(breath_temperature < cold_level_warning_threshold && !HAS_TRAIT(breather, TRAIT_RESISTCOLD)) // COLD DAMAGE + var/cold_modifier = breather.physiology.cold_mod var/breath_effect_prob = 0 - if(breath_temperature < cold_level_3_threshold) - breather.apply_damage(cold_level_3_damage * cold_modifier, cold_damage_type, spread_damage = TRUE) + var/cold_message_prob = 0 + if(breath_temperature < cold_level_danger_threshold) + breather.apply_damage(cold_level_damage * cold_modifier, cold_damage_type, spread_damage = TRUE) breath_effect_prob = 100 - if(breath_temperature > cold_level_3_threshold && breath_temperature < cold_level_2_threshold) - breather.apply_damage(cold_level_2_damage * cold_modifier, cold_damage_type, spread_damage = TRUE) + cold_message_prob = 100 + else if(breath_temperature < cold_level_hazard_threshold) + breather.apply_damage(0.5 * cold_level_damage * cold_modifier, cold_damage_type, spread_damage = TRUE) + breath_effect_prob = 75 + cold_message_prob = 50 + else breath_effect_prob = 50 - if(breath_temperature > cold_level_2_threshold && breath_temperature < cold_level_1_threshold) - breather.apply_damage(cold_level_1_damage * cold_modifier, cold_damage_type, spread_damage = TRUE) - breath_effect_prob = 25 - if(breath_temperature < cold_level_1_threshold) - if(prob(sqrt(breath_effect_prob) * 4)) - to_chat(breather, span_warning("You feel [cold_message] in your [name]!")) - if(prob(50)) - breather.emote("shiver") - if(prob(breath_effect_prob)) - // Breathing into your mask, no particle. We can add fogged up glasses later - if(breather.is_mouth_covered()) - return - // Even though breathing via internals TECHNICALLY exhales into the environment, we'll still block it - if(breather.internal || breather.external) - return - emit_breath_particle(breather, /particles/fog/breath) - - if(!HAS_TRAIT(breather, TRAIT_RESISTHEAT)) // HEAT DAMAGE + cold_message_prob = 20 + if(prob(cold_message_prob)) + to_chat(breather, span_warning("You feel [cold_message] in your [name]!")) + if(prob(50)) + breather.emote("shiver") + if(prob(breath_effect_prob)) + // Breathing into your mask, no particle. We can add fogged up glasses later + if(breather.is_mouth_covered()) + return + // Even though breathing via internals TECHNICALLY exhales into the environment, we'll still block it + if(breather.internal || breather.external) + return + emit_breath_particle(breather, /particles/fog/breath) + + if(breath_temperature > heat_level_warning_threshold && !HAS_TRAIT(breather, TRAIT_RESISTHEAT)) // HEAT DAMAGE var/heat_modifier = breather.dna.species.heatmod var/heat_message_prob = 0 - if(breath_temperature > heat_level_1_threshold && breath_temperature < heat_level_2_threshold) - breather.apply_damage(heat_level_1_damage * heat_modifier, heat_damage_type, spread_damage = TRUE) + if(breath_temperature > heat_level_danger_threshold) + breather.apply_damage(heat_level_damage * heat_modifier, heat_damage_type, spread_damage = TRUE) heat_message_prob = 100 - if(breath_temperature > heat_level_2_threshold && breath_temperature < heat_level_3_threshold) - breather.apply_damage(heat_level_2_damage * heat_modifier, heat_damage_type, spread_damage = TRUE) + else if(breath_temperature > heat_level_hazard_threshold) + breather.apply_damage(0.5 * heat_level_damage * heat_modifier, heat_damage_type, spread_damage = TRUE) heat_message_prob = 50 - if(breath_temperature > heat_level_3_threshold) - breather.apply_damage(heat_level_3_damage * heat_modifier, heat_damage_type, spread_damage = TRUE) - heat_message_prob = 25 - if(breath_temperature > heat_level_1_threshold) - if(prob(sqrt(heat_message_prob) * 4)) - to_chat(breather, span_warning("You feel [hot_message] in your [name]!")) + else + heat_message_prob = 20 + if(prob(heat_message_prob)) + to_chat(breather, span_warning("You feel [hot_message] in your [name]!")) // The air you breathe out should match your body temperature breath.temperature = breather.bodytemperature @@ -968,9 +976,9 @@ safe_oxygen_min = 13 emp_vulnerability = 20 - cold_level_1_threshold = 200 - cold_level_2_threshold = 140 - cold_level_3_threshold = 100 + cold_level_warning_threshold = CELCIUS_TO_KELVIN(-73.15 CELCIUS) + cold_level_hazard_threshold = CELCIUS_TO_KELVIN(-133.15 CELCIUS) + cold_level_danger_threshold = CELCIUS_TO_KELVIN(-173.15 CELCIUS) /obj/item/organ/internal/lungs/cybernetic/emp_act(severity) . = ..() @@ -1047,9 +1055,9 @@ name = "aeration reticulum" desc = "These exotic lungs seem crunchier than most." icon_state = "lungs_ethereal" - heat_level_1_threshold = FIRE_MINIMUM_TEMPERATURE_TO_SPREAD // 150C or 433k, in line with ethereal max safe body temperature - heat_level_2_threshold = 473 - heat_level_3_threshold = 1073 + heat_level_warning_threshold = FIRE_MINIMUM_TEMPERATURE_TO_SPREAD // 150C or 433k, in line with ethereal max safe body temperature + heat_level_hazard_threshold = CELCIUS_TO_KELVIN(200 CELCIUS) + heat_level_danger_threshold = CELCIUS_TO_KELVIN(800 CELCIUS) /obj/item/organ/internal/lungs/ethereal/Initialize(mapload) . = ..() diff --git a/code/modules/surgery/organs/stomach/_stomach.dm b/code/modules/surgery/organs/stomach/_stomach.dm index 8e1d4a661fb2..f1e2db0e52b7 100644 --- a/code/modules/surgery/organs/stomach/_stomach.dm +++ b/code/modules/surgery/organs/stomach/_stomach.dm @@ -32,6 +32,11 @@ var/operated = FALSE //whether the stomach's been repaired with surgery and can be fixed again or not + /// Typecache of food we can eat that will never give us disease. + var/list/disease_free_foods + ///our hunger modifier + var/hunger_modifier = 1 + /obj/item/organ/internal/stomach/Initialize(mapload) . = ..() //None edible organs do not get a reagent holder by default @@ -139,23 +144,22 @@ // nutrition decrease and satiety if (human.nutrition > 0 && human.stat != DEAD) // THEY HUNGER - var/hunger_rate = HUNGER_FACTOR - if(human.mob_mood && human.mob_mood.sanity > SANITY_DISTURBED) + var/hunger_rate = HUNGER_FACTOR * PASSIVE_HUNGER_MULTIPLIER + if(human.mob_mood?.sanity > SANITY_DISTURBED) hunger_rate *= max(1 - 0.002 * human.mob_mood.sanity, 0.5) //0.85 to 0.75 // Whether we cap off our satiety or move it towards 0 - if(human.satiety > MAX_SATIETY) - human.satiety = MAX_SATIETY - else if(human.satiety > 0) - human.satiety-- - else if(human.satiety < -MAX_SATIETY) - human.satiety = -MAX_SATIETY + if(human.satiety > 0) + human.adjust_satiety(-1 * seconds_per_tick) + else if(human.satiety < 0) - human.satiety++ + human.adjust_satiety(1 * seconds_per_tick) if(SPT_PROB(round(-human.satiety/77), seconds_per_tick)) human.set_jitter_if_lower(10 SECONDS) - hunger_rate = 2 * HUNGER_FACTOR + hunger_rate *= 3 + + hunger_rate *= hunger_modifier hunger_rate *= human.physiology.hunger_mod - human.adjust_nutrition(-hunger_rate * seconds_per_tick) + human.adjust_nutrition(-1 * hunger_rate * seconds_per_tick) var/nutrition = human.nutrition if(nutrition > NUTRITION_LEVEL_FULL) @@ -336,5 +340,18 @@ if(prob(emp_vulnerability/severity)) //Chance of permanent effects organ_flags |= ORGAN_SYNTHETIC_EMP //Starts organ faliure - gonna need replacing soon. +// Lizard stomach to Let Them Eat Rat +/obj/item/organ/internal/stomach/lizard + name = "lizardperson stomach" + desc = "A stomach native to a Lizardperson of Tiziran... or maybe one of its colonies." + color = COLOR_VERY_DARK_LIME_GREEN + // Lizards don't homeostasize (they're cold blooded) so they get hungrier faster to offset that + // Even with this modifier, note they still get hungrier like 1.5x slower than humans + hunger_modifier = 2 + +/obj/item/organ/internal/stomach/lizard/Initialize(mapload) + . = ..() + var/static/list/rat_cache = typecacheof(/obj/item/food/deadmouse) + disease_free_foods = rat_cache #undef STOMACH_METABOLISM_CONSTANT diff --git a/code/modules/surgery/organs/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/stomach/stomach_ethereal.dm index 3c82f629cb51..32992762be33 100644 --- a/code/modules/surgery/organs/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/stomach/stomach_ethereal.dm @@ -19,11 +19,13 @@ . = ..() RegisterSignal(stomach_owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, PROC_REF(charge)) RegisterSignal(stomach_owner, COMSIG_LIVING_ELECTROCUTE_ACT, PROC_REF(on_electrocute)) + RegisterSignal(stomach_owner, COMSIG_LIVING_HOMEOSTASIS, PROC_REF(handle_temp)) /obj/item/organ/internal/stomach/ethereal/on_remove(mob/living/carbon/stomach_owner) . = ..() UnregisterSignal(stomach_owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT) UnregisterSignal(stomach_owner, COMSIG_LIVING_ELECTROCUTE_ACT) + UnregisterSignal(stomach_owner, COMSIG_LIVING_HOMEOSTASIS) stomach_owner.clear_mood_event("charge") stomach_owner.clear_alert(ALERT_ETHEREAL_CHARGE) stomach_owner.clear_alert(ALERT_ETHEREAL_OVERCHARGE) @@ -31,6 +33,16 @@ /obj/item/organ/internal/stomach/ethereal/handle_hunger_slowdown(mob/living/carbon/human/human) human.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/hunger, multiplicative_slowdown = (1.5 * (1 - crystal_charge / 100))) + +/obj/item/organ/internal/stomach/ethereal/proc/handle_temp(mob/living/carbon/human/human, natural_change, seconds_per_tick) + SIGNAL_HANDLER + + if(human.blood_volume < (ETHEREAL_CHARGE_LOWPOWER / 2)) + return HOMEOSTASIS_HANDLED + + adjust_charge(-1 * ETHEREAL_CHARGE_FACTOR * abs(natural_change) * seconds_per_tick) + return HOMEOSTASIS_NO_HUNGER + /obj/item/organ/internal/stomach/ethereal/proc/charge(datum/source, amount, repairs) SIGNAL_HANDLER if(!ishuman(owner)) diff --git a/code/modules/vehicles/mecha/equipment/tools/medical_tools.dm b/code/modules/vehicles/mecha/equipment/tools/medical_tools.dm index 84b224173a2e..e90720f2e150 100644 --- a/code/modules/vehicles/mecha/equipment/tools/medical_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/medical_tools.dm @@ -161,12 +161,11 @@ t1 = "*dead*" else t1 = "Unknown" - var/core_temp = "" - if(ishuman(patient)) - var/mob/living/carbon/human/humi = patient - core_temp = {"Body Temperature: [humi.bodytemperature-T0C]°C ([humi.bodytemperature*1.8-459.67]°F)
"} + var/skin_temp = patient.get_skin_temperature() + var/body_temp = patient.bodytemperature return {"Health: [patient.stat > 1 ? "[t1]" : "[patient.health]% ([t1])"]
- [core_temp] + Skin Temperature: [KELVIN_TO_CELCIUS(skin_temp)]°C ([KELVIN_TO_FAHRENHEIT(skin_temp)]°F)
+ Body Temperature: [KELVIN_TO_CELCIUS(body_temp)]°C ([KELVIN_TO_FAHRENHEIT(body_temp)]°F)
Body Temperature: [patient.bodytemperature-T0C]°C ([patient.bodytemperature*1.8-459.67]°F)
Brute Damage: [patient.getBruteLoss()]%
Respiratory Damage: [patient.getOxyLoss()]%
diff --git a/monkestation/code/modules/antagonists/borers/code/mobs/cortical_borer.dm b/monkestation/code/modules/antagonists/borers/code/mobs/cortical_borer.dm index 590317db46d4..73bf28e9e913 100644 --- a/monkestation/code/modules/antagonists/borers/code/mobs/cortical_borer.dm +++ b/monkestation/code/modules/antagonists/borers/code/mobs/cortical_borer.dm @@ -415,7 +415,7 @@ GLOBAL_LIST_INIT(borer_second_name, world.file2list("monkestation/code/modules/a /mob/living/basic/cortical_borer/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) var/loc_temp if(human_host) - loc_temp = human_host.coretemperature // set the local temp to that of the host's core temp + loc_temp = human_host.bodytemperature // set the local temp to that of the host's core temp else loc_temp = get_temperature(environment) var/temp_delta = loc_temp - bodytemperature diff --git a/monkestation/code/modules/antagonists/clock_cult/items/clothing.dm b/monkestation/code/modules/antagonists/clock_cult/items/clothing.dm index 43bd5f81b27e..ced2a2f676bc 100644 --- a/monkestation/code/modules/antagonists/clock_cult/items/clothing.dm +++ b/monkestation/code/modules/antagonists/clock_cult/items/clothing.dm @@ -514,9 +514,9 @@ icon_state = "clockwork_gauntlets" siemens_coefficient = 0 strip_delay = 8 SECONDS - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF armor_type = /datum/armor/gloves_clockwork diff --git a/monkestation/code/modules/antagonists/clock_cult/mobs/clockwork_marauder.dm b/monkestation/code/modules/antagonists/clock_cult/mobs/clockwork_marauder.dm index bb1e08ca1ba1..ca83e7193259 100644 --- a/monkestation/code/modules/antagonists/clock_cult/mobs/clockwork_marauder.dm +++ b/monkestation/code/modules/antagonists/clock_cult/mobs/clockwork_marauder.dm @@ -26,7 +26,7 @@ GLOBAL_LIST_EMPTY(clockwork_marauders) mob_size = MOB_SIZE_LARGE move_resist = MOVE_FORCE_OVERPOWERING unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 + bodytemp_cold_damage_limit = -1 obj_damage = 80 faction = list(FACTION_CLOCK) damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) diff --git a/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_datum.dm b/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_datum.dm index 36e8ea3347ca..151ca08ccbf2 100644 --- a/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_datum.dm +++ b/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_datum.dm @@ -95,7 +95,7 @@ TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_AGEUSIA, - TRAIT_COLDBLOODED, + TRAIT_COLD_BLOODED, TRAIT_VIRUSIMMUNE, TRAIT_TOXIMMUNE, TRAIT_HARDLY_WOUNDED, diff --git a/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_overwrites.dm b/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_overwrites.dm index 4b7131c9a119..578f90322e46 100644 --- a/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_overwrites.dm +++ b/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_overwrites.dm @@ -30,11 +30,6 @@ return return ..() -/mob/living/carbon/human/natural_bodytemperature_stabilization(datum/gas_mixture/environment, seconds_per_tick, times_fired) - // Return 0 as your natural temperature. Species proc handle_environment() will adjust your temperature based on this. - if(HAS_TRAIT(src, TRAIT_COLDBLOODED)) - return 0 - return ..() // Used when analyzing a Bloodsucker, Masquerade will hide brain traumas (Unless you're a Beefman) /mob/living/carbon/get_traumas() diff --git a/monkestation/code/modules/bloodsuckers/clans/venture.dm b/monkestation/code/modules/bloodsuckers/clans/venture.dm index 173e6bc7fe29..20cf06a6f0a5 100644 --- a/monkestation/code/modules/bloodsuckers/clans/venture.dm +++ b/monkestation/code/modules/bloodsuckers/clans/venture.dm @@ -60,7 +60,7 @@ vassaldatum.vassal_level++ switch(vassaldatum.vassal_level) if(2) - target.add_traits(list(TRAIT_COLDBLOODED, TRAIT_NOBREATH, TRAIT_AGEUSIA), BLOODSUCKER_TRAIT) + target.add_traits(list(TRAIT_COLD_BLOODED, TRAIT_NOBREATH, TRAIT_AGEUSIA), BLOODSUCKER_TRAIT) to_chat(target, span_notice("Your blood begins to feel cold, and as a mote of ash lands upon your tongue, you stop breathing...")) if(3) target.add_traits(list(TRAIT_NOCRITDAMAGE, TRAIT_NOSOFTCRIT), BLOODSUCKER_TRAIT) diff --git a/monkestation/code/modules/blueshift/clothing/kahraman.dm b/monkestation/code/modules/blueshift/clothing/kahraman.dm index b99237b4bb11..92c8eeb0d95c 100644 --- a/monkestation/code/modules/blueshift/clothing/kahraman.dm +++ b/monkestation/code/modules/blueshift/clothing/kahraman.dm @@ -277,9 +277,9 @@ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON worn_icon_state = "flak" body_parts_covered = CHEST - cold_protection = CHEST|GROIN + min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN + max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT armor_type = /datum/armor/colonist_armor resistance_flags = NONE @@ -361,9 +361,9 @@ worn_icon_state = "gloves" greyscale_colors = "#3a373e" siemens_coefficient = 0.25 // Doesn't insulate you entirely, but makes you a little more resistant - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE clothing_traits = list(TRAIT_QUICK_CARRY) diff --git a/monkestation/code/modules/blueshift/clothing/nova_coats.dm b/monkestation/code/modules/blueshift/clothing/nova_coats.dm index 04e73300acd3..bfd1707c4851 100644 --- a/monkestation/code/modules/blueshift/clothing/nova_coats.dm +++ b/monkestation/code/modules/blueshift/clothing/nova_coats.dm @@ -88,8 +88,8 @@ blood_overlay_type = "coat" body_parts_covered = CHEST|GROIN|LEGS|ARMS armor_type = /datum/armor/toggle_deckard - cold_protection = CHEST|GROIN|LEGS|ARMS - heat_protection = CHEST|GROIN|LEGS|ARMS + + /datum/armor/toggle_deckard melee = 25 @@ -145,8 +145,8 @@ desc = "\"You look like a good Joe.\"" icon_state = "bladerunner_neue" body_parts_covered = CHEST|GROIN|ARMS|LEGS - cold_protection = CHEST|GROIN|ARMS|LEGS - heat_protection = CHEST|ARMS|GROIN|LEGS + + icon = 'monkestation/code/modules/blueshift/icons/obj/clothing/suits.dmi' worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/suit.dmi' blood_overlay_type = "coat" @@ -158,7 +158,7 @@ icon = 'monkestation/code/modules/blueshift/icons/obj/clothing/suits/jacket.dmi' worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/suits/jacket.dmi' body_parts_covered = CHEST|ARMS - cold_protection = CHEST|ARMS + greyscale_config = /datum/greyscale_config/croptop greyscale_config_worn = /datum/greyscale_config/croptop/worn greyscale_colors = "#1d1b1b" @@ -229,7 +229,7 @@ greyscale_config_worn = /datum/greyscale_config/warm_coat/worn greyscale_colors = "#7a5f4f#d9cec7" flags_1 = IS_PLAYER_COLORABLE_1 - cold_protection = CHEST|GROIN|ARMS + body_parts_covered = CHEST|GROIN|ARMS min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON diff --git a/monkestation/code/modules/blueshift/clothing/nova_cowboy.dm b/monkestation/code/modules/blueshift/clothing/nova_cowboy.dm index 2f11d9d774ce..65afb157bbdb 100644 --- a/monkestation/code/modules/blueshift/clothing/nova_cowboy.dm +++ b/monkestation/code/modules/blueshift/clothing/nova_cowboy.dm @@ -42,7 +42,7 @@ greyscale_colors = "#c26934#8f89ae#774B2D" greyscale_config = /datum/greyscale_config/cowboy_flat_cowl greyscale_config_worn = /datum/greyscale_config/cowboy_flat_cowl/worn - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT flags_inv = HIDEHAIR diff --git a/monkestation/code/modules/blueshift/clothing/nova_field.dm b/monkestation/code/modules/blueshift/clothing/nova_field.dm index 92b22b3c07f6..49e1a81d53b7 100644 --- a/monkestation/code/modules/blueshift/clothing/nova_field.dm +++ b/monkestation/code/modules/blueshift/clothing/nova_field.dm @@ -87,9 +87,9 @@ icon_state = "exp_corps" icon = 'monkestation/code/modules/blueshift/icons/obj/clothing/gloves.dmi' worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/hands.dmi' - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF uses_advanced_reskins = FALSE @@ -114,9 +114,9 @@ icon = 'monkestation/code/modules/blueshift/icons/obj/clothing/gloves.dmi' worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/hands.dmi' worn_icon_state = "exp_corps" - cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT - heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF armor_type = /datum/armor/nitrile_expeditionary_corps @@ -152,8 +152,8 @@ icon_state = "exp_corps" body_parts_covered = CHEST|GROIN|ARMS armor_type = /datum/armor/vest_expeditionary_corps - cold_protection = CHEST|GROIN|ARMS - heat_protection = CHEST|GROIN|ARMS + + dog_fashion = null allowed = list( /obj/item/melee, diff --git a/monkestation/code/modules/blueshift/clothing/nova_heads.dm b/monkestation/code/modules/blueshift/clothing/nova_heads.dm index d0d49655c12e..0f13b9f231fd 100644 --- a/monkestation/code/modules/blueshift/clothing/nova_heads.dm +++ b/monkestation/code/modules/blueshift/clothing/nova_heads.dm @@ -117,9 +117,9 @@ desc = "Despite seeming like it's made of metal, it's actually a very cheap plastic.." armor_type = /datum/armor/imperial_ce clothing_flags = STOPSPRESSUREDAMAGE - heat_protection = HEAD + max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT icon_state = "impce" flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT @@ -175,7 +175,7 @@ worn_icon = 'monkestation/code/modules/blueshift/gags/icons/head/head.dmi' icon_state = "hood" body_parts_covered = HEAD - cold_protection = HEAD + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT flags_inv = HIDEEARS|HIDEHAIR flags_1 = IS_PLAYER_COLORABLE_1 diff --git a/monkestation/code/modules/blueshift/clothing/nova_jackets.dm b/monkestation/code/modules/blueshift/clothing/nova_jackets.dm index ab550ed6c8ee..b62a1580988c 100644 --- a/monkestation/code/modules/blueshift/clothing/nova_jackets.dm +++ b/monkestation/code/modules/blueshift/clothing/nova_jackets.dm @@ -7,7 +7,7 @@ icon_state = "bomberalt" allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/radio) body_parts_covered = CHEST|ARMS|GROIN - cold_protection = CHEST|ARMS|GROIN + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON toggle_noun = "zipper" @@ -88,8 +88,8 @@ desc = "A cozy and warm plaid flannel jacket. Praised by Lumberjacks and Truckers alike." icon_state = "flannel" body_parts_covered = CHEST|ARMS //Being a bit shorter, flannels dont cover quite as much as the rest of the woolen jackets (- GROIN) - cold_protection = CHEST|ARMS - heat_protection = CHEST|ARMS //As a plus side, they're more insulating, protecting a bit from the heat as well + + /obj/item/clothing/suit/toggle/jacket/flannel/red name = "red flannel jacket" diff --git a/monkestation/code/modules/blueshift/clothing/nova_misc.dm b/monkestation/code/modules/blueshift/clothing/nova_misc.dm index 41cd847c3ef5..d6940eee76c0 100644 --- a/monkestation/code/modules/blueshift/clothing/nova_misc.dm +++ b/monkestation/code/modules/blueshift/clothing/nova_misc.dm @@ -93,7 +93,7 @@ icon_state = "chi_korea_coat" supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT /obj/item/clothing/suit/modernwintercoatthing @@ -104,7 +104,7 @@ icon_state = "modern_winter" supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT /obj/item/clothing/suit/toggle/jacket/cardigan @@ -145,7 +145,7 @@ icon_state = "expensivecoat" supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT /obj/item/clothing/suit/brownbattlecoat @@ -156,7 +156,7 @@ icon_state = "battlecoat" supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT /obj/item/clothing/suit/brownfurrich @@ -167,7 +167,7 @@ icon_state = "winter_coat" supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT armor_type = /datum/armor/suit_brownfurrich @@ -197,7 +197,7 @@ icon_state = "fallsparka" supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT /obj/item/clothing/suit/british_officer @@ -208,7 +208,7 @@ icon_state = "british_officer" supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT armor_type = /datum/armor/suit_british_officer @@ -224,7 +224,7 @@ icon_state = "modern_winter" supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT /obj/item/clothing/suit/woolcoat @@ -245,7 +245,7 @@ icon_state = "soldier" supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT armor_type = /datum/armor/suit_gautumn @@ -263,7 +263,7 @@ icon_state = "autumn" supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT armor_type = /datum/armor/suit_autumn diff --git a/monkestation/code/modules/blueshift/clothing/nova_neck.dm b/monkestation/code/modules/blueshift/clothing/nova_neck.dm index e999df7ece5b..cf85b439c148 100644 --- a/monkestation/code/modules/blueshift/clothing/nova_neck.dm +++ b/monkestation/code/modules/blueshift/clothing/nova_neck.dm @@ -156,7 +156,7 @@ icon = 'monkestation/code/modules/blueshift/icons/obj/clothing/neck.dmi' worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/neck.dmi' icon_state = "cowboy_poncho" - heat_protection = CHEST + /obj/item/clothing/neck/cowboylea/Initialize(mapload) . = ..() @@ -171,7 +171,7 @@ greyscale_config_worn = /datum/greyscale_config/ranger_poncho/worn greyscale_colors = "#917A57#858585" //Roughly the same color as the original non-greyscale item was flags_1 = IS_PLAYER_COLORABLE_1 - heat_protection = CHEST + /obj/item/clothing/neck/ranger_poncho/Initialize(mapload) . = ..() diff --git a/monkestation/code/modules/blueshift/clothing/nova_security.dm b/monkestation/code/modules/blueshift/clothing/nova_security.dm index f2a4d1067b0e..c8ff04628539 100644 --- a/monkestation/code/modules/blueshift/clothing/nova_security.dm +++ b/monkestation/code/modules/blueshift/clothing/nova_security.dm @@ -278,8 +278,8 @@ icon_state = "peacekeeper_jacket" supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS - heat_protection = CHEST|GROIN|ARMS + + /obj/item/clothing/suit/armor/vest/peacekeeper/jacket/Initialize(mapload) . = ..() @@ -300,9 +300,9 @@ worn_icon_state = "peacekeeper" siemens_coefficient = 0.5 strip_delay = 20 - cold_protection = 0 + min_cold_protection_temperature = null - heat_protection = 0 + max_heat_protection_temperature = null resistance_flags = FLAMMABLE armor_type = /datum/armor/none @@ -358,9 +358,9 @@ worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/suit.dmi' icon_state = "cowboy_vest" body_parts_covered = CHEST|ARMS - cold_protection = CHEST|ARMS + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON - heat_protection = CHEST|ARMS + /obj/item/clothing/suit/jacket/det_suit/cowboyvest name = "blonde cowboy vest" @@ -369,9 +369,9 @@ worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/suit.dmi' icon_state = "cowboy_vest" body_parts_covered = CHEST|ARMS - cold_protection = CHEST|ARMS + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON - heat_protection = CHEST|ARMS + /obj/item/clothing/under/rank/security/detective/runner name = "runner sweater" diff --git a/monkestation/code/modules/blueshift/clothing/nova_syndicate.dm b/monkestation/code/modules/blueshift/clothing/nova_syndicate.dm index 9bb1a92ed1c6..158f2ebff0ac 100644 --- a/monkestation/code/modules/blueshift/clothing/nova_syndicate.dm +++ b/monkestation/code/modules/blueshift/clothing/nova_syndicate.dm @@ -199,7 +199,7 @@ name = "insulated tactical turtleneck skirt" desc = "A non-descript and slightly suspicious looking skirtleneck. The interior has been padded with special insulation for both warmth and protection." armor_type = /datum/armor/clothing_under/syndicate/coldres - cold_protection = CHEST|GROIN|ARMS|LEGS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT @@ -248,7 +248,7 @@ worn_icon = 'monkestation/code/modules/blueshift/icons/worn.dmi' icon_state = "syndievest_winter" body_parts_covered = CHEST|GROIN - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT resistance_flags = FIRE_PROOF diff --git a/monkestation/code/modules/blueshift/mobs/misc_pets.dm b/monkestation/code/modules/blueshift/mobs/misc_pets.dm index b25cb375f641..55bdd7d908f1 100644 --- a/monkestation/code/modules/blueshift/mobs/misc_pets.dm +++ b/monkestation/code/modules/blueshift/mobs/misc_pets.dm @@ -27,8 +27,8 @@ real_name = "Teshari" desc = "A timeless classic." unsuitable_atmos_damage = 0 - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 30000 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 30000 /mob/living/basic/lizard/tegu name = "tegu" diff --git a/monkestation/code/modules/blueshift/reagents/deforest.dm b/monkestation/code/modules/blueshift/reagents/deforest.dm index 556d1b96df25..1b5e073689cc 100644 --- a/monkestation/code/modules/blueshift/reagents/deforest.dm +++ b/monkestation/code/modules/blueshift/reagents/deforest.dm @@ -366,7 +366,7 @@ if(!ishuman(our_guy)) return var/mob/living/carbon/human/human = our_guy - human.adjust_coretemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT) + human.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT) else our_guy.adjustOrganLoss(ORGAN_SLOT_HEART, 0.1 * REM * seconds_per_tick) @@ -404,7 +404,7 @@ if(!ishuman(our_guy)) return var/mob/living/carbon/human/human = our_guy - human.adjust_coretemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT) + human.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT) else our_guy.adjustOrganLoss(ORGAN_SLOT_HEART, 1 * REM * seconds_per_tick, required_organtype = affected_organtype) our_guy.adjustToxLoss(1 * REM * seconds_per_tick, updating_health = FALSE, forced = TRUE, required_biotype = affected_biotype) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm index 67e783f69ed4..fa5fe7b28566 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm @@ -578,21 +578,21 @@ switch(shock_buildup) if(10 to 60) - parent.adjust_bodytemperature(-5 * seconds_per_tick, parent.get_body_temp_cold_damage_limit() + 5) + parent.adjust_bodytemperature(-5 * seconds_per_tick, min_temp = parent.bodytemp_cold_damage_limit + 5) if(60 to 120) if(SPT_PROB(2, seconds_per_tick)) do_pain_message(span_bolddanger(pick("It hurts.", "You really need some painkillers."))) if(SPT_PROB(4, seconds_per_tick)) do_pain_message(span_warning(pick("You feel cold!", "You feel sweaty!"))) parent.pain_emote("shiver", 3 SECONDS) - parent.adjust_bodytemperature(-10 * seconds_per_tick, parent.get_body_temp_cold_damage_limit() - 5) + parent.adjust_bodytemperature(-10 * seconds_per_tick, min_temp = parent.bodytemp_cold_damage_limit - 5) if(120 to 180) if(SPT_PROB(2, seconds_per_tick)) do_pain_message(span_userdanger(pick("Stop the pain!", "It hurts!", "You need painkillers now!"))) if(SPT_PROB(4, seconds_per_tick)) do_pain_message(span_warning("You feel freezing!")) parent.pain_emote("shiver", 3 SECONDS) - parent.adjust_bodytemperature(-20 * seconds_per_tick, parent.get_body_temp_cold_damage_limit() - 20) + parent.adjust_bodytemperature(-20 * seconds_per_tick, min_temp = parent.bodytemp_cold_damage_limit - 20) if((shock_buildup >= 20 || curr_pain >= PAIN_LIMB_MAX) && !just_cant_feel_anything) if(SPT_PROB(min(curr_pain / 5, 24), seconds_per_tick)) @@ -721,7 +721,7 @@ SIGNAL_HANDLER var/mob/living/carbon/human/human_parent = parent - if(human_parent.get_thermal_protection() >= FIRE_SUIT_MAX_TEMP_PROTECT) + if(human_parent.get_insulation(FIRE_SUIT_MAX_TEMP_PROTECT) >= 0.9) return // The more firestacks, the more pain we apply per burn tick, up to 2 per tick per bodypart. diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/pain_assistance_tools.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/pain_assistance_tools.dm index 57d8200e5b9c..7690e941a5ac 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/pain_assistance_tools.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/pain_assistance_tools.dm @@ -329,8 +329,8 @@ slot_flags = ITEM_SLOT_OCLOTHING body_parts_covered = CHEST resistance_flags = FIRE_PROOF - heat_protection = CHEST|GROIN|LEGS|ARMS - cold_protection = CHEST|GROIN|LEGS|ARMS + + max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT armor_type = /datum/armor/shock_blanket @@ -415,7 +415,7 @@ /obj/item/shock_blanket/proc/enable_protection(mob/living/source) if(istype(source) && !(datum_flags & DF_ISPROCESSING)) var/temp_change = "warmer" - if(source.bodytemperature > source.get_body_temp_normal(apply_change = FALSE)) + if(source.bodytemperature > source.standard_body_temperature) temp_change = "colder" to_chat(source, span_notice("You feel [temp_change] as [src] begins regulating your body temperature.")) @@ -429,7 +429,7 @@ if(istype(source) && (datum_flags & DF_ISPROCESSING)) var/temp_change = "freezing" - if(source.bodytemperature > source.get_body_temp_normal(apply_change = FALSE)) + if(source.bodytemperature > source.standard_body_temperature) temp_change = "hotter" to_chat(source, span_notice("You feel [temp_change] again as [src] stops regulating your body temperature.")) @@ -442,17 +442,10 @@ disable_protection() return - var/target_temp = wearer.get_body_temp_normal(apply_change = FALSE) - if(wearer.bodytemperature > target_temp) - wearer.adjust_bodytemperature(-8 * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, target_temp) - else if(wearer.bodytemperature < (target_temp + 1)) - wearer.adjust_bodytemperature(8 * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, target_temp) - if(ishuman(wearer)) - var/mob/living/carbon/human/human_wearer = wearer - if(human_wearer.coretemperature > target_temp) - human_wearer.adjust_coretemperature(-8 * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, target_temp) - else if(human_wearer.coretemperature < (target_temp + 1)) - human_wearer.adjust_coretemperature(8 * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, target_temp) + if(wearer.bodytemperature < wearer.standard_body_temperature) + wearer.adjust_bodytemperature(0.25 KELVIN * seconds_per_tick, max_temp = wearer.standard_body_temperature) + else if(wearer.bodytemperature > wearer.standard_body_temperature) + wearer.adjust_bodytemperature(-0.25 KELVIN * seconds_per_tick, min_temp = wearer.standard_body_temperature) /obj/item/shock_blanket/emergency desc = "An emergency variant shock blanket intended to be placed in medkits for field treatment. Faster to apply to patients, but more restrictive to movement." diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/painkillers.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/painkillers.dm index a217837a0e06..6572fc4984ed 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/painkillers.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/painkillers.dm @@ -179,7 +179,7 @@ M.cause_pain(BODY_ZONES_LIMBS, -0.16 * REM * seconds_per_tick) M.cause_pain(BODY_ZONE_CHEST, -0.32 * REM * seconds_per_tick) // Okay at fevers. - M.adjust_bodytemperature(-15 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, M.get_body_temp_normal()) + M.adjust_bodytemperature(-0.1 KELVIN * REM * seconds_per_tick, M.standard_body_temperature) if(M.disgust < DISGUST_LEVEL_VERYGROSS && SPT_PROB(66 * max(1 - creation_purity, 0.5), seconds_per_tick)) M.adjust_disgust(1.5 * REM * seconds_per_tick) @@ -191,7 +191,7 @@ return // On overdose, heat up the body... - M.adjust_bodytemperature(30 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick) + M.adjust_bodytemperature(0.5 KELVIN * REM * seconds_per_tick, max_temp = HYPERTHERMIA - 1 KELVIN) // Causes sickness... M.apply_damage(1 * REM * seconds_per_tick, TOX) if(M.disgust < 100 && SPT_PROB(100 * max(1 - creation_purity, 0.5), seconds_per_tick)) @@ -229,7 +229,7 @@ M.adjustToxLoss(-0.05 * REM * seconds_per_tick, FALSE) M.cause_pain(BODY_ZONES_ALL, -0.2 * REM * seconds_per_tick) // Not very good at treating fevers. - M.adjust_bodytemperature(-10 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, M.get_body_temp_normal()) + M.adjust_bodytemperature(-0.05 KELVIN * REM * seconds_per_tick, M.standard_body_temperature) // Causes liver damage - higher dosages causes more liver damage. M.adjustOrganLoss(ORGAN_SLOT_LIVER, volume / 30 * REM * seconds_per_tick) if(M.disgust < DISGUST_LEVEL_VERYGROSS && SPT_PROB(66 * max(1 - creation_purity, 0.5), seconds_per_tick)) @@ -273,7 +273,7 @@ // Causes flat liver damage. M.adjustOrganLoss(ORGAN_SLOT_LIVER, 0.25 * REM * seconds_per_tick) // Really good at treating fevers. - M.adjust_bodytemperature(-25 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, M.get_body_temp_normal()) + M.adjust_bodytemperature(-0.5 KELVIN * REM * seconds_per_tick, M.standard_body_temperature) // Causes more disgust the longer it's in someone... if(M.disgust < DISGUST_LEVEL_VERYGROSS && SPT_PROB(66 * max(1 - creation_purity, 0.5), seconds_per_tick)) M.adjust_disgust(min(current_cycle * 0.02, 2.4) * REM * seconds_per_tick) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm index 279d14a9262b..a7d79a4c70ab 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm @@ -45,7 +45,7 @@ var/conditions_fulfilled = 0 // Good: Body temperature is stable (not freezing, we don't care about heat) - if(affected_mob.bodytemperature > affected_mob.get_body_temp_cold_damage_limit()) + if(affected_mob.bodytemperature > affected_mob.bodytemp_cold_damage_limit) conditions_fulfilled += 1 // Good: Sleeping (or unconscious I guess) if(affected_mob.IsSleeping() || affected_mob.IsUnconscious()) @@ -147,7 +147,7 @@ if(SPT_PROB(6, seconds_per_tick)) to_chat(affected_mob, span_danger("You feel cold.")) affected_mob.pain_emote("shiver", 3 SECONDS) - affected_mob.adjust_bodytemperature(-5 * seconds_per_tick, affected_mob.get_body_temp_cold_damage_limit() + 5) // Not lethal + affected_mob.adjust_bodytemperature(-5 * seconds_per_tick, min = affected_mob.bodytemp_cold_damage_limit + 5) // Not lethal // decompensated (or progressive) - unable to maintain themselves // - mental issues @@ -180,7 +180,7 @@ if(SPT_PROB(8, seconds_per_tick)) to_chat(affected_mob, span_danger("You feel freezing!")) affected_mob.pain_emote("shiver", 3 SECONDS) - affected_mob.adjust_bodytemperature(-10 * seconds_per_tick, affected_mob.get_body_temp_cold_damage_limit() - 5) // uh oh + affected_mob.adjust_bodytemperature(-10 * seconds_per_tick, min = affected_mob.bodytemp_cold_damage_limit - 5) // uh oh // irreversible - point of no return, system failure // cardiac arrest @@ -204,4 +204,4 @@ affected_mob.losebreath += 10 else if(SPT_PROB(10, seconds_per_tick)) to_chat(affected_mob, span_userdanger(pick("You feel your heart skip a beat...", "You feel your body shutting down...", "You feel your heart beat irregularly..."))) - affected_mob.adjust_bodytemperature(-10 * seconds_per_tick, affected_mob.get_body_temp_cold_damage_limit() - 20) // welp + affected_mob.adjust_bodytemperature(-10 * seconds_per_tick, min = affected_mob.bodytemp_cold_damage_limit - 20) // welp diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/temp_pack.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/temp_pack.dm index bc5f230aff60..b0fe8a078a6d 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/temp_pack.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/temp_pack.dm @@ -79,7 +79,7 @@ return if(temperature_change) - owner.adjust_bodytemperature(temperature_change, human_owner.get_body_temp_cold_damage_limit() + 5, human_owner.get_body_temp_heat_damage_limit() - 5) + owner.adjust_bodytemperature(temperature_change, human_owner.bodytemp_cold_damage_limit + 5 KELVIN, human_owner.bodytemp_heat_damage_limit - 5 KELVIN) var/obj/item/bodypart/held_bodypart = human_owner.pain_controller.body_zones[targeted_zone] if(held_bodypart && prob(66)) human_owner.cause_pain(targeted_zone, -pain_heal_amount) diff --git a/monkestation/code/modules/clothing/spacesuits/hardsuits/engineering.dm b/monkestation/code/modules/clothing/spacesuits/hardsuits/engineering.dm index 0e641818c566..319dde7d11f5 100644 --- a/monkestation/code/modules/clothing/spacesuits/hardsuits/engineering.dm +++ b/monkestation/code/modules/clothing/spacesuits/hardsuits/engineering.dm @@ -40,7 +40,7 @@ icon_state = "hardsuit0-atmos" hardsuit_type = "atmos" armor_type = /datum/armor/hardsuit/atmos - heat_protection = HEAD //Uncomment to enable firesuit protection + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT /obj/item/clothing/suit/space/hardsuit/atmos @@ -48,7 +48,7 @@ desc = "A modified engineering hardsuit for work in a hazardous, low pressure environment. The radiation shielding plates were removed to allow for improved thermal protection instead." icon_state = "hardsuit-atmos" armor_type = /datum/armor/hardsuit/atmos - heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS //Uncomment to enable firesuit protection + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT helmettype = /obj/item/clothing/head/helmet/space/hardsuit/atmos diff --git a/monkestation/code/modules/clothing/suits/costume.dm b/monkestation/code/modules/clothing/suits/costume.dm index dc73f480703f..7e489332e347 100644 --- a/monkestation/code/modules/clothing/suits/costume.dm +++ b/monkestation/code/modules/clothing/suits/costume.dm @@ -111,9 +111,9 @@ worn_icon = 'monkestation/icons/mob/clothing/suit.dmi' inhand_icon_state = null body_parts_covered = CHEST|GROIN|LEGS|ARMS - cold_protection = CHEST|GROIN|LEGS|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN|LEGS|ARMS + max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT hoodtype = /obj/item/clothing/head/hooded/ashsuit armor_type = /datum/armor/hooded_ashsuit @@ -147,9 +147,9 @@ icon_state = "ashsuit" body_parts_covered = HEAD flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT armor_type = /datum/armor/hooded_explorer resistance_flags = FIRE_PROOF diff --git a/monkestation/code/modules/clothing/~donator/clothing.dm b/monkestation/code/modules/clothing/~donator/clothing.dm index aada29f2b240..57d0385dff60 100644 --- a/monkestation/code/modules/clothing/~donator/clothing.dm +++ b/monkestation/code/modules/clothing/~donator/clothing.dm @@ -127,7 +127,7 @@ inhand_icon_state = "hostrench" blood_overlay_type = "coat" body_parts_covered = CHEST|GROIN|LEGS|ARMS - cold_protection = CHEST|GROIN|LEGS|ARMS + supports_variations_flags = NONE // Donation reward for Thedragmeme @@ -292,7 +292,7 @@ icon_state = "avipilotup" inhand_icon_state = "rus_ushanka" flags_inv = HIDEEARS|HIDEHAIR - cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT //about as warm as an ushanka actions_types = list(/datum/action/item_action/adjust) supports_variations_flags = NONE @@ -664,7 +664,7 @@ worn_icon = 'monkestation/icons/donator/mob/clothing/suit.dmi' icon_state = "greycoat" body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT // Donation reward for Cherno_00 @@ -675,7 +675,7 @@ worn_icon = 'monkestation/icons/donator/mob/clothing/suit.dmi' icon_state = "chernocoat" body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT // Donation reward for GoldenAlpharex diff --git a/monkestation/code/modules/cybernetics/augments/arm_augments/unsorted.dm b/monkestation/code/modules/cybernetics/augments/arm_augments/unsorted.dm index cbd4105edbf9..633a8623ee4b 100644 --- a/monkestation/code/modules/cybernetics/augments/arm_augments/unsorted.dm +++ b/monkestation/code/modules/cybernetics/augments/arm_augments/unsorted.dm @@ -219,14 +219,14 @@ . = ..() if(!check_compatibility()) return - var/amt = BODYTEMP_NORMAL - owner.get_body_temp_normal() + var/amt = BODYTEMP_NORMAL - owner.standard_body_temperature if(amt == 0) return - owner.add_body_temperature_change("dermal_cooler_[zone]",clamp(amt,-1,0)) + owner.add_homeostasis_level(type, amt, 0.25 KELVIN) /obj/item/organ/internal/cyberimp/arm/cooler/Remove(mob/living/carbon/M, special) . = ..() - owner.remove_body_temperature_change("dermal_cooler_[zone]") + owner.remove_homeostasis_level(type) /obj/item/organ/internal/cyberimp/arm/heater name = "sub-dermal heater implant" @@ -241,11 +241,11 @@ . = ..() if(!check_compatibility()) return - var/amt = BODYTEMP_NORMAL - owner.get_body_temp_normal() + var/amt = BODYTEMP_NORMAL - owner.standard_body_temperature if(amt == 0) return - owner.add_body_temperature_change("dermal_heater_[zone]",clamp(amt,0,1)) + owner.add_homeostasis_level(type, amt, 0.25 KELVIN) /obj/item/organ/internal/cyberimp/arm/heater/Remove(mob/living/carbon/M, special) . = ..() - owner.remove_body_temperature_change("dermal_heater_[zone]") + owner.remove_homeostasis_level(type) diff --git a/monkestation/code/modules/donator/code/item/clothing.dm b/monkestation/code/modules/donator/code/item/clothing.dm index a651863ac9a4..03ed241b9c0e 100644 --- a/monkestation/code/modules/donator/code/item/clothing.dm +++ b/monkestation/code/modules/donator/code/item/clothing.dm @@ -41,7 +41,7 @@ worn_icon = 'monkestation/code/modules/donator/icons/mob/clothing.dmi' inhand_icon_state = "blahaj_costume" body_parts_covered = CHEST|GROIN|ARMS|LEGS|FEET - cold_protection = CHEST|GROIN|ARMS + allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/gun/ballistic/rifle/boltaction/harpoon) hoodtype = /obj/item/clothing/head/hooded/shark_hood inhand_icon_state = null @@ -53,7 +53,7 @@ worn_icon = 'monkestation/code/modules/donator/icons/mob/clothing.dmi' icon_state = "blahaj_hood" body_parts_covered = HEAD - cold_protection = HEAD + flags_inv = HIDEHAIR|HIDEEARS inhand_icon_state = null @@ -168,7 +168,7 @@ worn_icon = 'monkestation/code/modules/donator/icons/mob/clothing.dmi' icon_state = "aotcloak" body_parts_covered = CHEST|ARMS - cold_protection = CHEST|ARMS + allowed = list() armor_type = /datum/armor/hooded_wintercoat hoodtype = /obj/item/clothing/head/hooded/aotcloak @@ -206,7 +206,7 @@ worn_icon = 'monkestation/code/modules/donator/icons/mob/clothing.dmi' icon_state = "aotcloak_hood" body_parts_covered = HEAD - cold_protection = HEAD + flags_inv = HIDEHAIR|HIDEEARS armor_type = /datum/armor/hooded_winterhood @@ -251,7 +251,7 @@ icon_state = "coat_quilark" toggle_noun = "zipper" body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT /obj/item/clothing/suit/toggle/quilark/Initialize(mapload) @@ -283,7 +283,7 @@ worn_icon = 'monkestation/code/modules/donator/icons/mob/clothing.dmi' icon_state = "lambcloak" body_parts_covered = CHEST|ARMS - cold_protection = CHEST|ARMS + layer = NECK_LAYER /obj/item/clothing/suit/hooded/org_thirteen @@ -294,7 +294,7 @@ icon_state = "org_thirteen" inhand_icon_state = null body_parts_covered = CHEST|ARMS - cold_protection = CHEST|ARMS + allowed = list() armor_type = /datum/armor/hooded_wintercoat hoodtype = /obj/item/clothing/head/hooded/org_thirteen @@ -321,7 +321,7 @@ worn_icon = 'monkestation/code/modules/donator/icons/mob/clothing.dmi' icon_state = "org_thirteen_hood" body_parts_covered = HEAD - cold_protection = HEAD + flags_inv = HIDEHAIR|HIDEEARS armor_type = /datum/armor/hooded_winterhood @@ -424,7 +424,7 @@ name = "menacing jacket" desc = "There can only be one dragon." body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT /obj/item/clothing/mask/gas/bluedragon66_trenchbiomask @@ -485,7 +485,7 @@ name = "rainbow coat" desc = "Woah, it's a RAINBOW coat. How's it doing that?" body_parts_covered = CHEST|GROIN|ARMS - cold_protection = CHEST|GROIN|ARMS + armor_type = /datum/armor/hooded_wintercoat min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT /obj/item/clothing/suit/toggle/ophaq_rainbowcoat/Initialize(mapload) diff --git a/monkestation/code/modules/ocean_content/mobs/fish_base.dm b/monkestation/code/modules/ocean_content/mobs/fish_base.dm index 143807d61d86..13a3213f8b6a 100644 --- a/monkestation/code/modules/ocean_content/mobs/fish_base.dm +++ b/monkestation/code/modules/ocean_content/mobs/fish_base.dm @@ -12,8 +12,8 @@ speak_emote = list("glubs") habitable_atmos = list("min_oxy" = 2, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 1200 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 1200 ai_controller = /datum/ai_controller/basic_controller/fish diff --git a/monkestation/code/modules/ranching/chickens/tier2/cluwne.dm b/monkestation/code/modules/ranching/chickens/tier2/cluwne.dm index c195c8c06c7d..a80358cf5a68 100644 --- a/monkestation/code/modules/ranching/chickens/tier2/cluwne.dm +++ b/monkestation/code/modules/ranching/chickens/tier2/cluwne.dm @@ -3,7 +3,7 @@ breed_name_male = "huOnkHoNkHoeNK" breed_name_female = "huOnkHoNkHoeNK" - minimum_survivable_temperature = 0 + bodytemp_cold_damage_limit = -1 targeted_ability_planning_tree = /datum/ai_planning_subtree/targeted_mob_ability/min_range/chicken/clown diff --git a/monkestation/code/modules/ranching/chickens/tier2/snowy.dm b/monkestation/code/modules/ranching/chickens/tier2/snowy.dm index 57c179775e6d..b7e7f1f70462 100644 --- a/monkestation/code/modules/ranching/chickens/tier2/snowy.dm +++ b/monkestation/code/modules/ranching/chickens/tier2/snowy.dm @@ -3,8 +3,8 @@ breed_name = "Snow" egg_type = /obj/item/food/egg/snowy - minimum_survivable_temperature = 0 - maximum_survivable_temperature = 40 + bodytemp_cold_damage_limit = -1 + bodytemp_heat_damage_limit = 40 liked_foods = list(/obj/item/food/grown/icepepper = 4) book_desc = "These chickens require a sub-zero environment to live. They will melt if its not cold enough for them." diff --git a/monkestation/code/modules/research/nanites/nanite_programs/healing.dm b/monkestation/code/modules/research/nanites/nanite_programs/healing.dm index 1b6940de0948..a59afc7826b7 100644 --- a/monkestation/code/modules/research/nanites/nanite_programs/healing.dm +++ b/monkestation/code/modules/research/nanites/nanite_programs/healing.dm @@ -36,12 +36,12 @@ rogue_types = list(/datum/nanite_program/skin_decay) /datum/nanite_program/temperature/check_conditions() - if(host_mob.bodytemperature > (host_mob.get_body_temp_normal(apply_change=FALSE) - 30) && host_mob.bodytemperature < (host_mob.get_body_temp_normal(apply_change=FALSE) + 30)) + if(host_mob.bodytemperature > (host_mob.bodytemp_cold_damage_limit - 30) && host_mob.bodytemperature < (host_mob.bodytemp_heat_damage_limit)) return FALSE return ..() /datum/nanite_program/temperature/active_effect() - var/target_temp = host_mob.get_body_temp_normal(apply_change=FALSE) + var/target_temp = host_mob.standard_body_temperature if(host_mob.bodytemperature > target_temp) host_mob.adjust_bodytemperature(-40 * TEMPERATURE_DAMAGE_COEFFICIENT, target_temp) else if(host_mob.bodytemperature < (target_temp + 1)) diff --git a/monkestation/code/modules/research/nanites/nanite_programs/utility.dm b/monkestation/code/modules/research/nanites/nanite_programs/utility.dm index 484f7046f508..37f7c8146d96 100644 --- a/monkestation/code/modules/research/nanites/nanite_programs/utility.dm +++ b/monkestation/code/modules/research/nanites/nanite_programs/utility.dm @@ -108,7 +108,7 @@ update_research_speed() - host_mob.add_body_temperature_change(NANITE_RESEARCH_CHANGE, research_speed * 15) + host_mob.add_homeostasis_level(NANITE_RESEARCH_CHANGE, research_speed * 15, 0.25 KELVIN) use_rate = initial(use_rate) * research_speed current_research_bonus = use_rate SSresearch.science_tech.nanite_bonus += current_research_bonus @@ -120,7 +120,7 @@ /datum/nanite_program/research/disable_passive_effect() . = ..() SSresearch.science_tech.nanite_bonus -= current_research_bonus - host_mob.remove_body_temperature_change(NANITE_RESEARCH_CHANGE) + host_mob.remove_homeostasis_level(NANITE_RESEARCH_CHANGE) /datum/nanite_program/research/set_extra_setting(setting, value) . = ..() diff --git a/monkestation/code/modules/slimecore/mobs/_base_slime.dm b/monkestation/code/modules/slimecore/mobs/_base_slime.dm index b7794e979d73..5ff788113fb8 100644 --- a/monkestation/code/modules/slimecore/mobs/_base_slime.dm +++ b/monkestation/code/modules/slimecore/mobs/_base_slime.dm @@ -11,7 +11,7 @@ ai_controller = /datum/ai_controller/basic_controller/slime density = FALSE - maximum_survivable_temperature = 2000 + bodytemp_heat_damage_limit = 2000 pass_flags = PASSTABLE | PASSGRILLE gender = NEUTER @@ -38,8 +38,8 @@ can_be_held = TRUE - minimum_survivable_temperature = 100 - maximum_survivable_temperature = 600 + bodytemp_cold_damage_limit = 100 + bodytemp_heat_damage_limit = 600 // canstun and canknockdown don't affect slimes because they ignore stun and knockdown variables // for the sake of cleanliness, though, here they are. diff --git a/monkestation/code/modules/smithing/items/clothing.dm b/monkestation/code/modules/smithing/items/clothing.dm index 684b0bd34c65..b76e110d1084 100644 --- a/monkestation/code/modules/smithing/items/clothing.dm +++ b/monkestation/code/modules/smithing/items/clothing.dm @@ -108,9 +108,9 @@ icon_state = "cuirass" allowed = null body_parts_covered = CHEST - cold_protection = CHEST|GROIN + min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT - heat_protection = CHEST|GROIN + max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT strip_delay = 60 equip_delay_other = 40 @@ -131,9 +131,9 @@ icon = 'icons/obj/clothing/head/helmet.dmi' worn_icon = 'icons/mob/clothing/head/helmet.dmi' icon_state = "knight_green" - cold_protection = HEAD + min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT - heat_protection = HEAD + max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT strip_delay = 60 clothing_flags = SNUG_FIT | PLASMAMAN_HELMET_EXEMPT @@ -152,9 +152,9 @@ icon_state = "smithed_boots_inhand" worn_icon_state = "smithed_boots" inhand_icon_state = "jackboots" - cold_protection = FEET + min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT - heat_protection = FEET + max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT lefthand_file = 'icons/mob/inhands/clothing/shoes_lefthand.dmi' righthand_file = 'icons/mob/inhands/clothing/shoes_righthand.dmi' diff --git a/monkestation/code/modules/temperature_overhaul/exposure.dm b/monkestation/code/modules/temperature_overhaul/exposure.dm new file mode 100644 index 000000000000..d4b95448ef86 --- /dev/null +++ b/monkestation/code/modules/temperature_overhaul/exposure.dm @@ -0,0 +1,64 @@ +/// Ticking buff to overheated mobs that causes burn wounds +/datum/status_effect/stacking/heat_exposure + id = "heat_exposure" + status_type = STATUS_EFFECT_UNIQUE + remove_on_fullheal = TRUE + heal_flag_necessary = HEAL_TEMP + max_stacks = 40 + stack_threshold = 10 // added to in init + stack_decay = 0 // handled manually + + var/warned = TRUE + + /// How hot before we gain stacks rather than losing them + var/temp_threshold = -1 + +/datum/status_effect/stacking/heat_exposure/on_creation(mob/living/new_owner, stacks_to_apply, temp_threshold) + src.stack_threshold += rand(0, 20) + src.temp_threshold = temp_threshold + return ..() + +/datum/status_effect/stacking/heat_exposure/can_have_status() + return ishuman(owner) && !HAS_TRAIT(src, TRAIT_RESISTHEAT) + +/datum/status_effect/stacking/heat_exposure/can_gain_stacks() + return can_have_status() && owner.bodytemperature > temp_threshold + +/datum/status_effect/stacking/heat_exposure/tick(seconds_between_ticks) + if(owner.bodytemperature > temp_threshold) + add_stacks(0.5 * seconds_between_ticks) + else + add_stacks(-2 * seconds_between_ticks) + if(QDELETED(src)) // either we dropped off or we applied a wound + return + if(stacks >= max(stack_threshold - (10 + rand(-2, 5)), 8) && SPT_PROB(33, seconds_between_ticks) && !warned) + to_chat(owner, span_warning("You feel overheated!")) + warned = TRUE + return ..() + +/datum/status_effect/stacking/heat_exposure/stacks_consumed_effect() + var/mob/living/carbon/human/human_owner = owner + // Lets pick a random body part and check for an existing burn + var/obj/item/bodypart/bodypart = pick(human_owner.bodyparts) + var/datum/wound/existing_burn + for (var/datum/wound/iterated_wound as anything in bodypart.wounds) + var/datum/wound_pregen_data/pregen_data = iterated_wound.get_pregen_data() + if (pregen_data.wound_series in GLOB.wounding_types_to_series[WOUND_BURN]) + existing_burn = iterated_wound + break + + // If we have an existing burn try to upgrade it + var/severity = WOUND_SEVERITY_MODERATE + var/heat_damage = 2 * HEAT_DAMAGE * human_owner.physiology.heat_mod + if(human_owner.bodytemperature > temp_threshold * 8) + if(existing_burn?.severity < WOUND_SEVERITY_CRITICAL) + severity = WOUND_SEVERITY_CRITICAL + heat_damage *= 8 + + else if(human_owner.bodytemperature > temp_threshold * 2) + if(existing_burn?.severity < WOUND_SEVERITY_SEVERE) + severity = WOUND_SEVERITY_SEVERE + heat_damage *= 3 + + human_owner.cause_wound_of_type_and_severity(WOUND_BURN, bodypart, severity, wound_source = "hot temperatures") + human_owner.apply_damage(HEAT_DAMAGE, BURN, bodypart, wound_bonus = CANT_WOUND) diff --git a/monkestation/code/modules/temperature_overhaul/homeostasis_level.dm b/monkestation/code/modules/temperature_overhaul/homeostasis_level.dm new file mode 100644 index 000000000000..5495f18fe9c2 --- /dev/null +++ b/monkestation/code/modules/temperature_overhaul/homeostasis_level.dm @@ -0,0 +1,135 @@ +/** + * Changes the level to which the mob homeostasises to, while optionally providing a buff to the rate at which they do so. + * + * Additional buff to homeostasis rate does not affecte nutrition drain of homeostasis. + * + * Args + * * source: String key source of this effect + * * to_value: The target value to homeostasise to + * * delta_change: Optional, additional rate of change to the mob's body temperature + * * while_stasis: Optional, if delta change is supplied, it will tick while the mob is in stasis + * * while_dead: Optional, if delta change is supplied, it will tick while the mob is dead + * * update_species: Optional, if TRUE, and if the mob's species changes, we will update the target temp. to accomodate + * (via the difference in new species vs old species standard_body_temperature) + */ +/mob/living/proc/add_homeostasis_level( + source, + to_value, + delta_change = 0 KELVIN, + while_stasis = FALSE, + while_dead = FALSE, + update_species = TRUE +) + ASSERT(source) + ASSERT(to_value) + apply_status_effect(/datum/status_effect/homeostasis_level, source, to_value, delta_change, while_stasis, while_dead, update_species) + +/** + * Removes a source of homeostasis level change from a mob. + * + * Args + * * source: String key source to remove + */ +/mob/living/proc/remove_homeostasis_level( + source, +) + ASSERT(source) + remove_status_effect(/datum/status_effect/homeostasis_level, source) + +/** + * Updates an existing change to the mob's homeostasis levels + * + * Args + * * source: String key source to update + * * to_value: Change the level to homeostasise to + * * delta_change: Change the rate of change to the mob's body temperature + */ +/mob/living/proc/update_homeostasis_level( + source, + to_value, + delta_change = 0 KELVIN, +) + ASSERT(source) + ASSERT(to_value) + apply_status_effect(/datum/status_effect/homeostasis_level, source, to_value, delta_change) + +/** + * Attempts to stabilize a mob's body temperature to a set value. + */ +/datum/status_effect/homeostasis_level + id = "temp_change" + status_type = STATUS_EFFECT_MULTIPLE + tick_interval = 2 SECONDS + alert_type = null + var/source + var/to_value + var/delta_change + var/while_stasis + var/while_dead + var/update_species + +/datum/status_effect/homeostasis_level/on_creation( + mob/living/new_owner, + source, + to_value, + delta_change = 0 KELVIN, + while_stasis = FALSE, + while_dead = FALSE, + update_species = TRUE +) + src.source = source + src.to_value = to_value + src.delta_change = abs(delta_change) + src.while_stasis = while_stasis + src.while_dead = while_dead + src.update_species = update_species + + return ..() + +/datum/status_effect/homeostasis_level/on_apply() + if(isnull(src.source)) + stack_trace("Temperature change status effect applied without a source") + return FALSE + if(isnull(src.to_value)) + stack_trace("Temperature change status effect applied without a set temperature") + return FALSE + + for(var/datum/status_effect/homeostasis_level/effect in owner.status_effects) + if(effect.source == src.source) + effect.to_value = src.to_value + effect.delta_change = src.delta_change + LAZYSET(owner.homeostasis_targets, REF(effect), effect.to_value) + return FALSE + + RegisterSignal(owner, COMSIG_SPECIES_GAIN, PROC_REF(species_update)) + LAZYSET(owner.homeostasis_targets, REF(src), src.to_value) + return TRUE + +/datum/status_effect/homeostasis_level/before_remove(source) + return src.source == source + +/datum/status_effect/homeostasis_level/on_remove() + UnregisterSignal(owner, COMSIG_SPECIES_GAIN) + LAZYREMOVE(owner.homeostasis_targets, REF(src)) + +/datum/status_effect/homeostasis_level/tick(seconds_between_ticks) + if(!delta_change) + return + if(!while_stasis && HAS_TRAIT(owner, TRAIT_STASIS)) + return + if(!while_dead && owner.stat == DEAD) + return + + if(to_value < owner.standard_body_temperature) + owner.adjust_bodytemperature(-delta_change * seconds_between_ticks, min_temp = to_value) + + else + owner.adjust_bodytemperature(delta_change * seconds_between_ticks, max_temp = to_value) + +/datum/status_effect/homeostasis_level/proc/species_update(datum/source, datum/species/new_species, datum/species/old_species) + SIGNAL_HANDLER + + if(!update_species || isnull(new_species) || isnull(old_species) || new_species.type == old_species.type) + return + + to_value += UNLINT(new_species.bodytemp_normal - old_species.bodytemp_normal) diff --git a/monkestation/code/modules/temperature_overhaul/living_procs.dm b/monkestation/code/modules/temperature_overhaul/living_procs.dm new file mode 100644 index 000000000000..51eee8502d02 --- /dev/null +++ b/monkestation/code/modules/temperature_overhaul/living_procs.dm @@ -0,0 +1,164 @@ +/mob/living/proc/body_temperature_damage(datum/gas_mixture/environment, seconds_per_tick, times_fired) + if(bodytemperature > bodytemp_heat_damage_limit && !HAS_TRAIT(src, TRAIT_RESISTHEAT)) + var/heat_diff = bodytemp_heat_damage_limit - standard_body_temperature + var/heat_threshold_low = bodytemp_heat_damage_limit + heat_diff * 0.7 + var/heat_threshold_medium = bodytemp_heat_damage_limit + heat_diff * 1.25 + var/heat_threshold_high = bodytemp_heat_damage_limit + heat_diff * 2 + + var/firemodifier = round(fire_stacks, 1) * 0.05 + if (!on_fire) // We are not on fire, reduce the modifier + firemodifier = min(firemodifier, 0) // Note that wetstacks make us take less burn damage + + var/effective_temp = bodytemperature * (1 + firemodifier) + var/burn_damage = HEAT_DAMAGE + if(bodytemperature > heat_threshold_high) + burn_damage *= 8 + else if(bodytemperature > heat_threshold_medium) + burn_damage *= 4 + else if(bodytemperature > heat_threshold_low) + burn_damage *= 2 + + temperature_burns(burn_damage * seconds_per_tick, effective_temp, seconds_per_tick) + if(bodytemperature > heat_threshold_medium) + apply_status_effect(/datum/status_effect/stacking/heat_exposure, 1, heat_threshold_medium) + + // For cold damage, we cap at the threshold if you're dead + if(bodytemperature < bodytemp_cold_damage_limit && !HAS_TRAIT(src, TRAIT_RESISTCOLD) && (getFireLoss() < maxHealth || stat != DEAD)) + var/cold_diff = bodytemp_cold_damage_limit - standard_body_temperature + var/cold_threshold_low = bodytemp_cold_damage_limit + cold_diff * 1.2 + var/cold_threshold_medium = bodytemp_cold_damage_limit + cold_diff * 1.75 + var/cold_threshold_high = bodytemp_cold_damage_limit + cold_diff * 2 + + var/cold_damage = COLD_DAMAGE + if(bodytemperature > cold_threshold_low) + cold_damage *= 2 + else if(bodytemperature > cold_threshold_medium) + cold_damage *= 4 + else if(bodytemperature > cold_threshold_high) + cold_damage *= 8 + + temperature_cold_damage(cold_damage * seconds_per_tick, seconds_per_tick) + +/// Applies damage to the mob due to being too cold +/mob/living/proc/temperature_cold_damage(damage) + return apply_damage(damage, HAS_TRAIT(src, TRAIT_HULK) ? BRUTE : BURN, spread_damage = TRUE, wound_bonus = CANT_WOUND) + +/mob/living/carbon/human/temperature_cold_damage(damage) + damage *= physiology.cold_mod + return ..() + +/// Applies damage to the mob due to being too hot +/mob/living/proc/temperature_burns(damage, effective_temp) + return apply_damage(damage, BURN, spread_damage = TRUE, wound_bonus = CANT_WOUND) + +/mob/living/carbon/human/temperature_burns(damage, effective_temp) + damage *= physiology.heat_mod + return ..() + +/mob/living/proc/body_temperature_alerts() + // give out alerts based on how the skin feels, not how the body is + // this gives us an early warning system - since we tend to trend up/down to skin temperature - + // how we're going to be feeling soon if we don't change our environment + var/feels_like = get_skin_temperature() + + var/hot_diff = bodytemp_heat_damage_limit - standard_body_temperature + var/hot_threshold_low = standard_body_temperature + hot_diff * 0.2 + var/hot_threshold_medium = standard_body_temperature + hot_diff * 0.66 + var/hot_threshold_high = standard_body_temperature + hot_diff * 1.0 // should be the same as bodytemp_heat_damage_limit + // Body temperature is too hot, and we do not have resist traits + if(feels_like > hot_threshold_low && !HAS_TRAIT(src, TRAIT_RESISTHEAT)) + clear_mood_event("cold") + // Clear cold once we return to warm + remove_movespeed_modifier(/datum/movespeed_modifier/cold) + if(feels_like > hot_threshold_high) + throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 3) + add_mood_event("hot", /datum/mood_event/overhot) + else if(feels_like > hot_threshold_medium) + throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 2) + add_mood_event("hot", /datum/mood_event/hot) + else + throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 1) + add_mood_event("hot", /datum/mood_event/warm) + temp_alerts = TRUE + + var/cold_diff = bodytemp_cold_damage_limit - standard_body_temperature + var/cold_threshold_low = standard_body_temperature + cold_diff * 0.2 + var/cold_threshold_medium = standard_body_temperature + cold_diff * 0.66 + var/cold_threshold_high = standard_body_temperature + cold_diff * 1.0 // should be the same as bodytemp_cold_damage_limit + // Body temperature is too cold, and we do not have resist traits + if(feels_like < cold_threshold_low && !HAS_TRAIT(src, TRAIT_RESISTCOLD)) + clear_mood_event("hot") + // Only apply slowdown if the body is cold rather than the skin + if(bodytemperature < cold_threshold_medium) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((BODYTEMP_COLD_WARNING_2 - bodytemperature) / COLD_SLOWDOWN_FACTOR)) + if(feels_like < cold_threshold_high) + throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3) + add_mood_event("cold", /datum/mood_event/freezing) + else if(feels_like < cold_threshold_medium) + throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 2) + add_mood_event("cold", /datum/mood_event/cold) + else + throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1) + add_mood_event("cold", /datum/mood_event/chilly) + temp_alerts = TRUE + + // We are not to hot or cold, remove status and moods + if(temp_alerts && (feels_like < hot_threshold_low || HAS_TRAIT(src, TRAIT_RESISTHEAT)) && (feels_like > cold_threshold_low || HAS_TRAIT(src, TRAIT_RESISTCOLD))) + clear_alert(ALERT_TEMPERATURE) + if(bodytemperature > cold_threshold_medium) + remove_movespeed_modifier(/datum/movespeed_modifier/cold) + clear_mood_event("cold") + clear_mood_event("hot") + temp_alerts = FALSE + +/** + * Handles this mob internally managing its body temperature (sweating or generating heat) + * + * Arguments: + * * seconds_per_tick: The amount of time that has elapsed since this last fired. + * * times_fired: The number of times SSmobs has fired + */ +/mob/living/proc/temperature_homeostasis(seconds_per_tick, times_fired) + if(HAS_TRAIT(src, TRAIT_COLD_BLOODED)) + return + if(!HAS_TRAIT(src, TRAIT_NOHUNGER) && nutrition < (NUTRITION_LEVEL_STARVING / 3)) + return + + // find exactly what temperature we're aiming for + var/homeostasis_target + if(LAZYLEN(homeostasis_targets)) + for(var/source in homeostasis_targets) + homeostasis_target += homeostasis_targets[source] + homeostasis_target /= LAZYLEN(homeostasis_targets) + else + homeostasis_target = standard_body_temperature + + // Fun note: Because this scales by metabolism efficiency, being well fed boosts your homeostasis, and being poorly fed reduces it + var/natural_change = round((homeostasis_target - bodytemperature) * metabolism_efficiency * temperature_homeostasis_speed, 0.01) + if(natural_change == 0) + return + + // Cap increase and decrease (decreasing is harder) + natural_change = natural_change < 0 ? max(natural_change, BODYTEMP_COOLING_MAX / 8) : min(natural_change, BODYTEMP_HEATING_MAX / 6) + + var/sigreturn = SEND_SIGNAL(src, COMSIG_LIVING_HOMEOSTASIS, natural_change, seconds_per_tick) + if(sigreturn & HOMEOSTASIS_HANDLED) + return + + var/min = natural_change < 0 ? homeostasis_target : 0 + var/max = natural_change > 0 ? homeostasis_target : INFINITY + // calculates how much nutrition decay per kelvin of temperature change + // while having this scale may be confusing, it's to make sure that stepping into an extremely cold environment (space) + // doesn't immediately drain nutrition to zero in under a minute + // at 0.25 kelvin, nutrition_per_kelvin is 2.5. at 1, it's ~1.5, and at 4, it's 1. + var/nutrition_per_kelvin = round(2.5 / ((abs(natural_change) / 0.25) ** 0.33), 0.01) + + adjust_bodytemperature(natural_change * seconds_per_tick, min_temp = min, max_temp = max) // no use_insulation beacuse this is internal + if(!(sigreturn & HOMEOSTASIS_NO_HUNGER)) + adjust_nutrition(-1 * HOMEOSTASIS_HUNGER_MULTIPLIER * HUNGER_FACTOR * nutrition_per_kelvin * abs(natural_change) * seconds_per_tick) + +/mob/living/silicon/temperature_homeostasis(seconds_per_tick, times_fired) + return // Not yet + +/mob/proc/adjust_satiety(change) + satiety = clamp(satiety + change, -MAX_SATIETY, MAX_SATIETY) diff --git a/monkestation/code/modules/temperature_overhaul/temperature_proc.dm b/monkestation/code/modules/temperature_overhaul/temperature_proc.dm new file mode 100644 index 000000000000..bc30e669c945 --- /dev/null +++ b/monkestation/code/modules/temperature_overhaul/temperature_proc.dm @@ -0,0 +1,134 @@ +#define THERMAL_PROTECTION_HEAD 0.3 +#define THERMAL_PROTECTION_CHEST 0.2 +#define THERMAL_PROTECTION_GROIN 0.10 +#define THERMAL_PROTECTION_LEG (0.075 * 2) +#define THERMAL_PROTECTION_FOOT (0.025 * 2) +#define THERMAL_PROTECTION_ARM (0.075 * 2) +#define THERMAL_PROTECTION_HAND (0.025 * 2) + +/** + * Get the insulation that is appropriate to the temperature you're being exposed to. + * All clothing, natural insulation, and traits are combined returning a single value. + * + * Args + * * temperature - what temperature is being exposed to this mob? + * some articles of clothing are only effective within a certain temperature range + * + * returns the percentage of protection as a value from 0 - 1 +**/ +/mob/living/proc/get_insulation(temperature = T20C) + // There is an occasional bug where the temperature is miscalculated in areas with small amounts of gas. + // This is necessary to ensure that does not affect this calculation. + // Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K. + temperature = max(temperature, T0C) + + var/thermal_protection_flags = NONE + for(var/obj/item/worn in get_equipped_items()) + var/valid = FALSE + if(isnum(worn.max_heat_protection_temperature) && isnum(worn.min_cold_protection_temperature)) + valid = worn.max_heat_protection_temperature >= temperature && worn.min_cold_protection_temperature <= temperature + + else if (isnum(worn.max_heat_protection_temperature)) + valid = worn.max_heat_protection_temperature >= temperature + + else if (isnum(worn.min_cold_protection_temperature)) + valid = worn.min_cold_protection_temperature <= temperature + + if(valid) + thermal_protection_flags |= worn.body_parts_covered + + var/thermal_protection = temperature_insulation + if(thermal_protection_flags) + if(thermal_protection_flags & HEAD) + thermal_protection += THERMAL_PROTECTION_HEAD + if(thermal_protection_flags & CHEST) + thermal_protection += THERMAL_PROTECTION_CHEST + if(thermal_protection_flags & GROIN) + thermal_protection += THERMAL_PROTECTION_GROIN + if(thermal_protection_flags & LEGS) + thermal_protection += THERMAL_PROTECTION_LEG + if(thermal_protection_flags & FEET) + thermal_protection += THERMAL_PROTECTION_FOOT + if(thermal_protection_flags & ARMS) + thermal_protection += THERMAL_PROTECTION_ARM + if(thermal_protection_flags & HANDS) + thermal_protection += THERMAL_PROTECTION_HAND + + return min(1, thermal_protection) + +#undef THERMAL_PROTECTION_HEAD +#undef THERMAL_PROTECTION_CHEST +#undef THERMAL_PROTECTION_GROIN +#undef THERMAL_PROTECTION_LEG +#undef THERMAL_PROTECTION_FOOT +#undef THERMAL_PROTECTION_ARM +#undef THERMAL_PROTECTION_HAND + +/mob/living/proc/adjust_bodytemperature(amount = 0, min_temp = 0, max_temp = INFINITY, use_insulation = FALSE) + // apply insulation to the amount of change + if(use_insulation) + amount *= (1 - get_insulation(bodytemperature + amount)) + if(amount == 0) + return FALSE + amount = round(amount, 0.01) + + if(bodytemperature >= min_temp && bodytemperature <= max_temp) + var/old_temp = bodytemperature + bodytemperature = clamp(bodytemperature + amount, min_temp, max_temp) + SEND_SIGNAL(src, COMSIG_LIVING_BODY_TEMPERATURE_CHANGE, old_temp, bodytemperature) + // body_temperature_alerts() + +#ifdef TESTING + if(mind) + maptext_width = 128 + maptext_x = -16 + maptext_y = -12 + var/r_or_b = body_temperature - old_temp > 0 ? "red" : "blue" + maptext = MAPTEXT("Temp: [body_temperature]K ([amount]K)") +#endif + return TRUE + return FALSE + +// Robot bodytemp unimplemented for now. Add overheating later >:3 +/mob/living/silicon/adjust_bodytemperature(amount, min_temp, max_temp, use_insulation) + return + +/** + * Get the temperature of the skin of the mob + * + * This is a weighted average of the body temperature and the temperature of the air around the mob, + * plus some other modifiers + */ +/mob/living/proc/get_skin_temperature() + var/area_temperature = get_temperature(loc?.return_air()) + if(!(mob_biotypes & MOB_ORGANIC)) + // non-organic mobs likely don't feel or regulate temperature + // so we can just report the area temp... probably + // there's an argument to be made for putting the cold blooded check here + return round(area_temperature, 0.01) + + // calculate skin temp based on a weighted average of body temp and area temp + // (where area temp is modified by insulation) + var/body_weight = 2 + var/area_weight = 1 + get_insulation(area_temperature) + // total weight of / dividing by 3: two for bodytemp, one for areatemp (assuming 0 insulation) + // + // this gives 31.33 C for a standard human (37 C) in a 20 C room with no insulation + // and 34.33 C for a human with ~50% insulation (a winter coat) in the same room + // + // why do we convert to celcius? + // because i designed this equation around celcius and forgot i had to ultimately work in kelvin + // smaller numbers are easier to work with anyways. + var/skin_temp = (KELVIN_TO_CELCIUS(bodytemperature) * body_weight + KELVIN_TO_CELCIUS(area_temperature) * area_weight) / 3 + + if(!HAS_TRAIT(src, TRAIT_COLD_BLOODED)) + if(bodytemperature >= standard_body_temperature + 2 KELVIN) + skin_temp *= 1.1 // sweating + if(bodytemperature <= standard_body_temperature - 10 KELVIN) + skin_temp *= 0.8 // extremities are colder + + // and if we're on fire just add a flat amount of heat + if(on_fire) + skin_temp += KELVIN_TO_CELCIUS(fire_stacks ** 2 KELVIN) + + return round(CELCIUS_TO_KELVIN(skin_temp), 0.01) diff --git a/monkestation/code/modules/virology/disease/symtoms/stage1.dm b/monkestation/code/modules/virology/disease/symtoms/stage1.dm index 570c72e4c377..35080bc676a5 100644 --- a/monkestation/code/modules/virology/disease/symtoms/stage1.dm +++ b/monkestation/code/modules/virology/disease/symtoms/stage1.dm @@ -476,13 +476,13 @@ if(prob(5)) to_chat(M, span_notice("You feel yourself absorbing plasma inside and around you...")) - var/target_temp = M.get_body_temp_normal() + var/target_temp = M.standard_body_temperature if(M.bodytemperature > target_temp) - M.adjust_bodytemperature(-20 * temp_rate * TEMPERATURE_DAMAGE_COEFFICIENT, target_temp) + M.adjust_bodytemperature(-2 * temp_rate * TEMPERATURE_DAMAGE_COEFFICIENT, target_temp) if(prob(5)) to_chat(M, span_notice("You feel less hot.")) - else if(M.bodytemperature < (M.get_body_temp_normal() + 1)) - M.adjust_bodytemperature(20 * temp_rate * TEMPERATURE_DAMAGE_COEFFICIENT, 0, target_temp) + else if(M.bodytemperature < (M.standard_body_temperature + 1)) + M.adjust_bodytemperature(2 * temp_rate * TEMPERATURE_DAMAGE_COEFFICIENT, 0, target_temp) if(prob(5)) to_chat(M, span_notice("You feel warmer.")) diff --git a/monkestation/code/modules/virology/disease/symtoms/stage2.dm b/monkestation/code/modules/virology/disease/symtoms/stage2.dm index e00750ca7466..fff17b2a05a9 100644 --- a/monkestation/code/modules/virology/disease/symtoms/stage2.dm +++ b/monkestation/code/modules/virology/disease/symtoms/stage2.dm @@ -90,15 +90,13 @@ /datum/symptom/fridge/proc/set_body_temp(mob/living/mob) if(multiplier >= 3) // when unsafe the shivers can cause cold damage - mob.add_body_temperature_change("chills", -6 * power * multiplier) + mob.add_homeostasis_level(type, -6, 0.25 KELVIN * power) else - // Get the max amount of change allowed before going under cold damage limit, then cap the maximum allowed temperature change from safe chills to 5 over the cold damage limit - var/change_limit = min(mob.get_body_temp_cold_damage_limit() + 5 - mob.get_body_temp_normal(apply_change=FALSE), 0) - mob.add_body_temperature_change("chills", max(-6 * power * multiplier, change_limit)) + mob.add_homeostasis_level(type, -6 * power, 0.25 KELVIN * power) /datum/symptom/fridge/deactivate(mob/living/carbon/mob) if(mob) - mob.remove_body_temperature_change("chills") + mob.remove_homeostasis_level(type) /datum/symptom/hair name = "Hair Loss" diff --git a/tgstation.dme b/tgstation.dme index 73e4636efe59..902cba0461f7 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1362,7 +1362,6 @@ #include "code\datums\elements\attack_equip.dm" #include "code\datums\elements\backblast.dm" #include "code\datums\elements\bane.dm" -#include "code\datums\elements\basic_body_temp_sensitive.dm" #include "code\datums\elements\basic_eating.dm" #include "code\datums\elements\beauty.dm" #include "code\datums\elements\bed_tucking.dm" @@ -4605,7 +4604,6 @@ #include "code\modules\mob\living\carbon\alien\adult\adult_update_icons.dm" #include "code\modules\mob\living\carbon\alien\adult\alien_powers.dm" #include "code\modules\mob\living\carbon\alien\adult\death.dm" -#include "code\modules\mob\living\carbon\alien\adult\life.dm" #include "code\modules\mob\living\carbon\alien\adult\queen.dm" #include "code\modules\mob\living\carbon\alien\adult\caste\drone.dm" #include "code\modules\mob\living\carbon\alien\adult\caste\hunter.dm" @@ -7889,6 +7887,10 @@ #include "monkestation\code\modules\surgery\organs\internal\lungs.dm" #include "monkestation\code\modules\surgery\organs\internal\stomach.dm" #include "monkestation\code\modules\surgery\organs\internal\tongue.dm" +#include "monkestation\code\modules\temperature_overhaul\exposure.dm" +#include "monkestation\code\modules\temperature_overhaul\homeostasis_level.dm" +#include "monkestation\code\modules\temperature_overhaul\living_procs.dm" +#include "monkestation\code\modules\temperature_overhaul\temperature_proc.dm" #include "monkestation\code\modules\the_bird_inside_of_me\language.dm" #include "monkestation\code\modules\the_bird_inside_of_me\organs.dm" #include "monkestation\code\modules\the_bird_inside_of_me\plummage.dm" From 2a9f41d3892431f2cbc2c0a0daa468efbacb3478 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 13 Sep 2024 12:54:08 -0700 Subject: [PATCH 039/158] pain pain go away --- code/modules/surgery/organs/lungs.dm | 2 +- .../can_spessmen_feel_pain/pain/_base.dm | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index a06c310b44e2..577212d2ed49 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -909,7 +909,7 @@ if(!SPT_PROB(cough_prob, seconds_per_tick)) // between : past high return - if(damage >= high_threshold && prob(33)) + if((damage >= high_threshold) && prob(33)) owner.visible_message(span_danger("[owner] coughs up blood!"), span_userdanger("You cough up blood!")) var/obj/item/covering = owner.is_mouth_covered() if(covering) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm index fa5fe7b28566..b8fae434d267 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm @@ -696,6 +696,28 @@ parent.Paralyze(2 SECONDS) parent.remove_traits(list(TRAIT_LABOURED_BREATHING, TRAIT_INCAPACITATED, TRAIT_IMMOBILIZED, TRAIT_FLOORED, TRAIT_HANDS_BLOCKED), PAINCRIT) + // Finally, handle pain decay over time + if(parent.on_fire || parent.stat == DEAD) + return + + // Decay every 3 ticks / 6 seconds, or 1 ticks / 2 seconds if "sleeping" + var/every_x_ticks = HAS_TRAIT(parent, TRAIT_KNOCKEDOUT) ? 1 : 3 + + natural_decay_counter++ + if(natural_decay_counter % every_x_ticks != 0) + return + + natural_decay_counter = 0 + if(COOLDOWN_FINISHED(src, time_since_last_pain_loss) && parent.stat == CONSCIOUS) + // 0.16 per 10 seconds, ~0.1 per minute, 10 minutes for ~1 decay + natural_pain_decay = max(natural_pain_decay - 0.12, -4) + else + natural_pain_decay = base_pain_decay + + // modify our pain decay by our pain modifier (ex. 0.5 pain modifier = 2x natural pain decay, capped at ~3x) + var/pain_modified_decay = round(natural_pain_decay * (1 / max(pain_modifier, 0.33)), 0.01) + adjust_bodypart_pain(BODY_ZONES_ALL, pain_modified_decay) + /** * Whenever we buckle to something or lie down, get a pain bodifier. */ From ae08476a4355f9c7bb505eb453af11832ade179d Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 13 Sep 2024 14:49:40 -0700 Subject: [PATCH 040/158] lowered organ damage --- code/modules/surgery/organs/lungs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index 577212d2ed49..97b478722977 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -664,7 +664,7 @@ to_chat(breather, span_boldwarning("You feel air force itself into your lungs!")) breather.cause_pain(BODY_ZONE_CHEST, 10, BRUTE) - apply_organ_damage(15) + apply_organ_damage(5) breather.failed_last_breath = TRUE // Robot, don't care lol else From 14a2f0ccfd936324f243fcd773bfe51751809716 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 13 Sep 2024 15:49:04 -0700 Subject: [PATCH 041/158] tweaks --- .../atmospherics/atmos_mob_interaction.dm | 24 +++++-- .../objects/items/devices/chameleonproj.dm | 20 ++---- .../air_alarm/air_alarm_thresholds.dm | 8 +-- .../mob/living/carbon/human/human_defense.dm | 8 +-- .../human/species_types/lizardpeople.dm | 2 +- code/modules/mob/living/life.dm | 4 +- code/modules/mob/living/living.dm | 7 +- .../borers/code/mobs/cortical_borer.dm | 4 +- .../can_spessmen_feel_pain/pain/_base.dm | 16 ----- .../can_spessmen_feel_pain/pain/shock.dm | 2 +- .../pain/status_effects/fire_pain.dm | 42 ------------ .../temperature_overhaul/living_procs.dm | 64 ++++++++++--------- .../temperature_overhaul/temperature_proc.dm | 57 ++++++++--------- tgstation.dme | 1 - 14 files changed, 103 insertions(+), 156 deletions(-) delete mode 100644 monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/fire_pain.dm diff --git a/code/__DEFINES/atmospherics/atmos_mob_interaction.dm b/code/__DEFINES/atmospherics/atmos_mob_interaction.dm index 9418688d6d56..14552ebd1ef1 100644 --- a/code/__DEFINES/atmospherics/atmos_mob_interaction.dm +++ b/code/__DEFINES/atmospherics/atmos_mob_interaction.dm @@ -41,6 +41,12 @@ /// This is used in handle_temperature_damage() for humans, and in reagents that affect body temperature. Temperature damage is multiplied by this amount. #define TEMPERATURE_DAMAGE_COEFFICIENT 1.5 +// Defines the cap on fast your body normalizes to the environment +/// Max negative change in temperature during natural body temperature stabilization +#define BODYTEMP_ENVIRONMENT_COOLING_MAX -30 KELVIN // needs to be relatively high, as otherwise you will make space not deadly +/// Max positive change in temperature during natural body temperature stabilization +#define BODYTEMP_ENVIRONMENT_HEATING_MAX 20 KELVIN // should not be too high, as otherwise atmos meme fires will be extremely deadly + /// Default maximum body temperature mobs can exist in before taking damage #define NPC_DEFAULT_MAX_TEMP CELCIUS_TO_KELVIN(76.85 CELCIUS)// 350 KELVIN /// Default minimum body temperature mobs can exist in before taking damage @@ -60,9 +66,9 @@ #define KELVIN * 1 /// Max change in temperature during natural body temperature stabilization -#define BODYTEMP_COOLING_MAX -30 KELVIN +#define BODYTEMP_HOMEOSTASIS_COOLING_MAX (BODYTEMP_ENVIRONMENT_COOLING_MAX / 10) /// Max change in temperature during natural body temperature stabilization -#define BODYTEMP_HEATING_MAX 30 KELVIN +#define BODYTEMP_HOMEOSTASIS_HEATING_MAX (BODYTEMP_ENVIRONMENT_HEATING_MAX / 8) // These defines are DEFAULTS for most mobs // Mobs can override these to have whatever they want @@ -78,11 +84,14 @@ /// The body temperature limit the human body can take before it starts taking damage from heat. /// This also affects how fast the body normalises it's temperature when hot. -#define BODYTEMP_HEAT_DAMAGE_LIMIT CELCIUS_TO_KELVIN(65 CELCIUS) +#define BODYTEMP_HEAT_DAMAGE_LIMIT CELCIUS_TO_KELVIN(45 CELCIUS) /// The body temperature limit the human body can take before it starts taking damage from cold. /// This also affects how fast the body normalises it's temperature when cold. #define BODYTEMP_COLD_DAMAGE_LIMIT CELCIUS_TO_KELVIN(-0.5 CELCIUS) +/// The maximum temperature of Lavaland +#define LAVALAND_MAX_TEMPERATURE 350 + /// A temperature limit which is above the maximum lavaland temperature #define BODYTEMP_HEAT_LAVALAND_SAFE (LAVALAND_MAX_TEMPERATURE + 5 KELVIN) /// A temperature limit which is above the minimum icebox temperature @@ -106,10 +115,15 @@ /// Beyond this body temperature, being on fire will increase body temperature by less and less #define BODYTEMP_FIRE_TEMP_SOFTCAP 600 KELVIN +/// Amount of heating applied per fire stack per tick while on fire +#define HEAT_PER_FIRE_STACK 0.075 KELVIN +/// Amount of direct damage applied per fire stack per tick while on fire +#define BURN_DAMAGE_PER_FIRE_STACK 0.1 + /// A warm drink will increase body temperature by this much -#define WARM_DRINK 0.5 KELVIN +#define WARM_DRINK 0.25 KELVIN /// A cold drink will decrease body temperature by this much -#define COLD_DRINK -0.5 KELVIN +#define COLD_DRINK -0.25 KELVIN /// The modifier on cold damage limit hulks get ontop of their regular limit #define BODYTEMP_HULK_COLD_DAMAGE_LIMIT_MODIFIER 25 KELVIN diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index f5ef78a60c98..2ac05c111337 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -152,22 +152,10 @@ if(!isturf(loc) || isspaceturf(loc) || !direction) return //No magical movement! Trust me, this bad boy can do things like leap out of pipes if you're not careful - if(can_move < world.time) - var/amount - switch(user.bodytemperature) - if(300 to INFINITY) - amount = 10 - if(295 to 300) - amount = 13 - if(280 to 295) - amount = 16 - if(260 to 280) - amount = 20 - else - amount = 25 - - can_move = world.time + amount - try_step_multiz(direction) + if(can_move >= world.time) + return + can_move = world.time + 2 + (user.cached_multiplicative_slowdown * 4) // Fake movement speed calculating based on the mob's move speed + try_step_multiz(direction) return /obj/effect/dummy/chameleon/Destroy() diff --git a/code/modules/atmospherics/machinery/air_alarm/air_alarm_thresholds.dm b/code/modules/atmospherics/machinery/air_alarm/air_alarm_thresholds.dm index bfb9b28441fa..50e31fda1162 100644 --- a/code/modules/atmospherics/machinery/air_alarm/air_alarm_thresholds.dm +++ b/code/modules/atmospherics/machinery/air_alarm/air_alarm_thresholds.dm @@ -93,10 +93,10 @@ hazard_max = HAZARD_HIGH_PRESSURE /datum/tlv/temperature - warning_min = BODYTEMP_COLD_DAMAGE_LIMIT + 10 CELCIUS - hazard_min = BODYTEMP_COLD_DAMAGE_LIMIT - warning_max = BODYTEMP_HEAT_DAMAGE_LIMIT - 10 CELCIUS - hazard_max = BODYTEMP_HEAT_DAMAGE_LIMIT + warning_min = BODYTEMP_COLD_DAMAGE_LIMIT - 10 CELCIUS // some leeway as most humans sit comfortable above area temp + hazard_min = BODYTEMP_COLD_DAMAGE_LIMIT - 40 CELCIUS + warning_max = BODYTEMP_HEAT_DAMAGE_LIMIT + 5 CELCIUS // same + hazard_max = BODYTEMP_HEAT_DAMAGE_LIMIT + 20 CELCIUS /datum/tlv/cold_room_pressure warning_min = ONE_ATMOSPHERE * 0.9 diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 93f4311d2976..8b91fd1e1ebd 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -902,17 +902,17 @@ /mob/living/carbon/human/on_fire_stack(seconds_per_tick, times_fired, datum/status_effect/fire_handler/fire_stacks/fire_handler) var/sigreturn = SEND_SIGNAL(src, COMSIG_HUMAN_BURNING) if(sigreturn & BURNING_HANDLED) - return FALSE + return 0 burn_clothing(seconds_per_tick, fire_handler.stacks) if(!(sigreturn & BURNING_SKIP_PROTECTION)) if(get_insulation(FIRE_IMMUNITY_MAX_TEMP_PROTECT) >= 0.9) - return FALSE + return 0 if(get_insulation(FIRE_SUIT_MAX_TEMP_PROTECT) >= 0.9) - return adjust_bodytemperature(0.5 KELVIN * seconds_per_tick) + return adjust_bodytemperature(HEAT_PER_FIRE_STACK * 0.2 * fire_handler.stacks * seconds_per_tick) . = ..() - if(.) + if(. && !HAS_TRAIT(src, TRAIT_RESISTHEAT)) add_mood_event("on_fire", /datum/mood_event/on_fire) add_mob_memory(/datum/memory/was_burning) return . diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 490487732c86..a950beede9f7 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -42,7 +42,7 @@ mutanteyes = /obj/item/organ/internal/eyes/lizard // Lizards are coldblooded and can stand a greater temperature range than humans bodytemp_normal = (BODYTEMP_NORMAL - 7.5) - bodytemp_heat_damage_limit = (BODYTEMP_HEAT_DAMAGE_LIMIT + 20) // This puts lizards 10 above lavaland max heat for ash lizards. + bodytemp_heat_damage_limit = BODYTEMP_HEAT_LAVALAND_SAFE + 5 KELVIN // This puts lizards 10 above lavaland max heat for ash lizards. bodytemp_cold_damage_limit = (BODYTEMP_COLD_DAMAGE_LIMIT - 10) ass_image = 'icons/ass/asslizard.png' diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index a392f4667072..a9314df68dc7 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -62,6 +62,8 @@ handle_environment(environment, seconds_per_tick, times_fired) body_temperature_damage(environment, seconds_per_tick, times_fired) if(stat <= SOFT_CRIT && !on_fire) + if(!ishuman(src)) + return temperature_homeostasis(seconds_per_tick, times_fired) handle_gravity(seconds_per_tick, times_fired) @@ -122,7 +124,7 @@ var/temp_sign = SIGN(temp_delta) var/temp_change = temp_sign * (1 - (thermal_protection * protection_modifier)) * ((0.1 * max(1, abs(temp_delta))) ** 1.8) * temperature_normalization_speed // Cap increase and decrease - temp_change = temp_change < 0 ? max(temp_change, BODYTEMP_COOLING_MAX) : min(temp_change, BODYTEMP_HEATING_MAX) + temp_change = temp_change < 0 ? max(temp_change, BODYTEMP_HOMEOSTASIS_COOLING_MAX) : min(temp_change, BODYTEMP_HOMEOSTASIS_HEATING_MAX) adjust_bodytemperature(temp_change * seconds_per_tick) // no use_insulation beacuse we account for it manually /mob/living/silicon/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 2eab59136579..1082f702b498 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1712,12 +1712,15 @@ GLOBAL_LIST_EMPTY(fire_appearances) * * fire_handler: The fire handler status effect that is managing the fire stacks */ /mob/living/proc/on_fire_stack(seconds_per_tick, datum/status_effect/fire_handler/fire_stacks/fire_handler) - var/amount_to_heat = 0.25 KELVIN * fire_handler.stacks * seconds_per_tick + var/amount_to_heat = HEAT_PER_FIRE_STACK * fire_handler.stacks * seconds_per_tick + var/amount_to_burn = BURN_DAMAGE_PER_FIRE_STACK * fire_handler.stacks * seconds_per_tick if(bodytemperature > BODYTEMP_FIRE_TEMP_SOFTCAP) // Apply dimishing returns upon temp beyond the soft cap amount_to_heat = amount_to_heat ** (BODYTEMP_FIRE_TEMP_SOFTCAP / bodytemperature) - return adjust_bodytemperature(amount_to_heat) + var/direct_damage = (HAS_TRAIT(src, TRAIT_RESISTHEAT) || bodytemp_heat_damage_limit == INFINITY) ? 0 : temperature_burns(amount_to_burn) + var/temp_change = adjust_bodytemperature(amount_to_heat) + return temp_change + direct_damage //Mobs on Fire end diff --git a/monkestation/code/modules/antagonists/borers/code/mobs/cortical_borer.dm b/monkestation/code/modules/antagonists/borers/code/mobs/cortical_borer.dm index 73bf28e9e913..3ebfa95db0ee 100644 --- a/monkestation/code/modules/antagonists/borers/code/mobs/cortical_borer.dm +++ b/monkestation/code/modules/antagonists/borers/code/mobs/cortical_borer.dm @@ -426,9 +426,9 @@ GLOBAL_LIST_INIT(borer_second_name, world.file2list("monkestation/code/modules/a if(temp_delta < 0) // it is cold here if(!on_fire) // do not reduce body temp when on fire - adjust_bodytemperature(max(max(temp_delta / BODYTEMP_DIVISOR, BODYTEMP_COOLING_MAX) * seconds_per_tick, temp_delta)) + adjust_bodytemperature(max(max(temp_delta / BODYTEMP_DIVISOR, BODYTEMP_HOMEOSTASIS_COOLING_MAX) * seconds_per_tick, temp_delta)) else // this is a hot place - adjust_bodytemperature(min(min(temp_delta / BODYTEMP_DIVISOR, BODYTEMP_HEATING_MAX) * seconds_per_tick, temp_delta)) + adjust_bodytemperature(min(min(temp_delta / BODYTEMP_DIVISOR, BODYTEMP_HOMEOSTASIS_HEATING_MAX) * seconds_per_tick, temp_delta)) //leave the host, forced or not /mob/living/basic/cortical_borer/proc/leave_host() diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm index b8fae434d267..86b1f22f7431 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm @@ -90,7 +90,6 @@ RegisterSignal(parent, COMSIG_MOB_STATCHANGE, PROC_REF(on_parent_statchance)) RegisterSignals(parent, list(SIGNAL_ADDTRAIT(TRAIT_NO_PAIN_EFFECTS), SIGNAL_REMOVETRAIT(TRAIT_NO_PAIN_EFFECTS)), PROC_REF(refresh_pain_attributes)) RegisterSignal(parent, COMSIG_LIVING_TREAT_MESSAGE, PROC_REF(handle_message)) - RegisterSignal(parent, COMSIG_HUMAN_BURNING, PROC_REF(on_burn_tick)) RegisterSignal(parent, COMSIG_MOB_FIRED_GUN, PROC_REF(on_mob_fired_gun)) RegisterSignal(parent, COMSIG_LIVING_REVIVE, PROC_REF(revived)) @@ -103,7 +102,6 @@ COMSIG_CARBON_GAIN_WOUND, COMSIG_CARBON_LOSE_WOUND, COMSIG_CARBON_REMOVE_LIMB, - COMSIG_HUMAN_BURNING, COMSIG_LIVING_HEALTHSCAN, COMSIG_LIVING_POST_FULLY_HEAL, COMSIG_LIVING_REVIVE, @@ -736,20 +734,6 @@ else unset_pain_modifier(PAIN_MOD_LYING) -/** - * While actively burning, cause pain - */ -/datum/pain/proc/on_burn_tick(datum/source) - SIGNAL_HANDLER - - var/mob/living/carbon/human/human_parent = parent - if(human_parent.get_insulation(FIRE_SUIT_MAX_TEMP_PROTECT) >= 0.9) - return - - // The more firestacks, the more pain we apply per burn tick, up to 2 per tick per bodypart. - // We can be liberal with this because when they're extinguished most of it will go away. - parent.apply_status_effect(/datum/status_effect/pain_from_fire, clamp(parent.fire_stacks * 0.2, 0, 2)) - /// Affect accuracy of fired guns while in pain. /datum/pain/proc/on_mob_fired_gun(mob/living/carbon/human/user, obj/item/gun/gun_fired, target, params, zone_override, list/bonus_spread_values) SIGNAL_HANDLER diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm index a7d79a4c70ab..f17c917e388e 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm @@ -147,7 +147,7 @@ if(SPT_PROB(6, seconds_per_tick)) to_chat(affected_mob, span_danger("You feel cold.")) affected_mob.pain_emote("shiver", 3 SECONDS) - affected_mob.adjust_bodytemperature(-5 * seconds_per_tick, min = affected_mob.bodytemp_cold_damage_limit + 5) // Not lethal + affected_mob.adjust_bodytemperature(-5 * seconds_per_tick, min_temp = affected_mob.bodytemp_cold_damage_limit + 5) // Not lethal // decompensated (or progressive) - unable to maintain themselves // - mental issues diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/fire_pain.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/fire_pain.dm deleted file mode 100644 index b359a5a477b6..000000000000 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/fire_pain.dm +++ /dev/null @@ -1,42 +0,0 @@ -/// Handler for pain from fire. Goes up the longer you're on fire, largely goes away when extinguished -/datum/status_effect/pain_from_fire - id = "sharp_pain_from_fire" - status_type = STATUS_EFFECT_REFRESH - alert_type = null - remove_on_fullheal = TRUE - heal_flag_necessary = HEAL_ADMIN|HEAL_WOUNDS|HEAL_STATUS - - /// Amount of pain being given - var/pain_amount = 0 - -/datum/status_effect/pain_from_fire/on_creation(mob/living/new_owner, pain_amount = 0) - src.pain_amount = pain_amount - return ..() - -/datum/status_effect/pain_from_fire/refresh(mob/living/new_owner, added_pain_amount = 0) - if(added_pain_amount <= 0) - return - pain_amount += added_pain_amount - owner.cause_pain(BODY_ZONES_ALL, added_pain_amount, BURN) - -/datum/status_effect/pain_from_fire/on_apply() - if(isnull(owner.pain_controller) || pain_amount <= 0) - return FALSE - - RegisterSignal(owner, COMSIG_LIVING_EXTINGUISHED, PROC_REF(remove_on_signal)) - owner.cause_pain(BODY_ZONES_ALL, pain_amount, BURN) - return TRUE - -/datum/status_effect/pain_from_fire/on_remove() - if(QDELING(owner)) - return - UnregisterSignal(owner, COMSIG_LIVING_EXTINGUISHED) - owner.cause_pain(BODY_ZONES_ALL, -3 * pain_amount, BURN) - -/// When signalled, terminate. -/datum/status_effect/pain_from_fire/proc/remove_on_signal(datum/source) - SIGNAL_HANDLER - - if(QDELING(owner) || QDELING(src)) - return - qdel(src) diff --git a/monkestation/code/modules/temperature_overhaul/living_procs.dm b/monkestation/code/modules/temperature_overhaul/living_procs.dm index 51eee8502d02..a80e47146651 100644 --- a/monkestation/code/modules/temperature_overhaul/living_procs.dm +++ b/monkestation/code/modules/temperature_overhaul/living_procs.dm @@ -1,43 +1,46 @@ /mob/living/proc/body_temperature_damage(datum/gas_mixture/environment, seconds_per_tick, times_fired) if(bodytemperature > bodytemp_heat_damage_limit && !HAS_TRAIT(src, TRAIT_RESISTHEAT)) var/heat_diff = bodytemp_heat_damage_limit - standard_body_temperature - var/heat_threshold_low = bodytemp_heat_damage_limit + heat_diff * 0.7 + var/heat_threshold_low = bodytemp_heat_damage_limit + heat_diff * 0.75 var/heat_threshold_medium = bodytemp_heat_damage_limit + heat_diff * 1.25 var/heat_threshold_high = bodytemp_heat_damage_limit + heat_diff * 2 - var/firemodifier = round(fire_stacks, 1) * 0.05 + var/firemodifier = round(fire_stacks, 1) * 0.01 if (!on_fire) // We are not on fire, reduce the modifier firemodifier = min(firemodifier, 0) // Note that wetstacks make us take less burn damage - var/effective_temp = bodytemperature * (1 + firemodifier) + // convering back and forth so we can apply a multiplier from firestacks without sending temp to the moon + var/effective_temp = CELCIUS_TO_KELVIN(KELVIN_TO_CELCIUS(bodytemperature) * (1 + firemodifier)) var/burn_damage = HEAT_DAMAGE - if(bodytemperature > heat_threshold_high) + if(effective_temp > heat_threshold_high) burn_damage *= 8 - else if(bodytemperature > heat_threshold_medium) + else if(effective_temp > heat_threshold_medium) burn_damage *= 4 - else if(bodytemperature > heat_threshold_low) + else if(effective_temp > heat_threshold_low) burn_damage *= 2 - temperature_burns(burn_damage * seconds_per_tick, effective_temp, seconds_per_tick) - if(bodytemperature > heat_threshold_medium) + temperature_burns(burn_damage * seconds_per_tick) + if(effective_temp > heat_threshold_medium) apply_status_effect(/datum/status_effect/stacking/heat_exposure, 1, heat_threshold_medium) - // For cold damage, we cap at the threshold if you're dead + + // For cold damage, we cap at the threshold if you're dead if(bodytemperature < bodytemp_cold_damage_limit && !HAS_TRAIT(src, TRAIT_RESISTCOLD) && (getFireLoss() < maxHealth || stat != DEAD)) var/cold_diff = bodytemp_cold_damage_limit - standard_body_temperature var/cold_threshold_low = bodytemp_cold_damage_limit + cold_diff * 1.2 var/cold_threshold_medium = bodytemp_cold_damage_limit + cold_diff * 1.75 + // For cold damage, we cap at the threshold if you're dead var/cold_threshold_high = bodytemp_cold_damage_limit + cold_diff * 2 var/cold_damage = COLD_DAMAGE - if(bodytemperature > cold_threshold_low) - cold_damage *= 2 - else if(bodytemperature > cold_threshold_medium) - cold_damage *= 4 - else if(bodytemperature > cold_threshold_high) + if(bodytemperature < cold_threshold_high) cold_damage *= 8 + else if(bodytemperature < cold_threshold_medium) + cold_damage *= 4 + else if(bodytemperature < cold_threshold_low) + cold_damage *= 2 - temperature_cold_damage(cold_damage * seconds_per_tick, seconds_per_tick) + temperature_cold_damage(cold_damage * seconds_per_tick) /// Applies damage to the mob due to being too cold /mob/living/proc/temperature_cold_damage(damage) @@ -48,10 +51,10 @@ return ..() /// Applies damage to the mob due to being too hot -/mob/living/proc/temperature_burns(damage, effective_temp) +/mob/living/proc/temperature_burns(damage) return apply_damage(damage, BURN, spread_damage = TRUE, wound_bonus = CANT_WOUND) -/mob/living/carbon/human/temperature_burns(damage, effective_temp) +/mob/living/carbon/human/temperature_burns(damage) damage *= physiology.heat_mod return ..() @@ -62,9 +65,9 @@ var/feels_like = get_skin_temperature() var/hot_diff = bodytemp_heat_damage_limit - standard_body_temperature - var/hot_threshold_low = standard_body_temperature + hot_diff * 0.2 - var/hot_threshold_medium = standard_body_temperature + hot_diff * 0.66 - var/hot_threshold_high = standard_body_temperature + hot_diff * 1.0 // should be the same as bodytemp_heat_damage_limit + var/hot_threshold_low = bodytemp_heat_damage_limit - hot_diff * 0.5 + var/hot_threshold_medium = bodytemp_heat_damage_limit + var/hot_threshold_high = bodytemp_heat_damage_limit + hot_diff // Body temperature is too hot, and we do not have resist traits if(feels_like > hot_threshold_low && !HAS_TRAIT(src, TRAIT_RESISTHEAT)) clear_mood_event("cold") @@ -82,9 +85,9 @@ temp_alerts = TRUE var/cold_diff = bodytemp_cold_damage_limit - standard_body_temperature - var/cold_threshold_low = standard_body_temperature + cold_diff * 0.2 - var/cold_threshold_medium = standard_body_temperature + cold_diff * 0.66 - var/cold_threshold_high = standard_body_temperature + cold_diff * 1.0 // should be the same as bodytemp_cold_damage_limit + var/cold_threshold_low = bodytemp_cold_damage_limit - cold_diff * 0.5 + var/cold_threshold_medium = bodytemp_cold_damage_limit + var/cold_threshold_high = bodytemp_cold_damage_limit + cold_diff // Body temperature is too cold, and we do not have resist traits if(feels_like < cold_threshold_low && !HAS_TRAIT(src, TRAIT_RESISTCOLD)) clear_mood_event("hot") @@ -125,22 +128,21 @@ return // find exactly what temperature we're aiming for - var/homeostasis_target + var/homeostasis_target = standard_body_temperature if(LAZYLEN(homeostasis_targets)) + homeostasis_target = 0 for(var/source in homeostasis_targets) homeostasis_target += homeostasis_targets[source] homeostasis_target /= LAZYLEN(homeostasis_targets) - else - homeostasis_target = standard_body_temperature - // Fun note: Because this scales by metabolism efficiency, being well fed boosts your homeostasis, and being poorly fed reduces it - var/natural_change = round((homeostasis_target - bodytemperature) * metabolism_efficiency * temperature_homeostasis_speed, 0.01) + // temperature delta is capped, so you can't attempt to homeostaize from vacuum to standard temp in a second + var/temp_delta = (homeostasis_target - bodytemperature) + temp_delta = temp_delta < 0 ? max(temp_delta, BODYTEMP_HOMEOSTASIS_COOLING_MAX) : min(temp_delta, BODYTEMP_HOMEOSTASIS_HEATING_MAX) + // note: Because this scales by metabolism efficiency, being well fed boosts your homeostasis, and being poorly fed reduces it + var/natural_change = temp_delta * metabolism_efficiency * temperature_homeostasis_speed if(natural_change == 0) return - // Cap increase and decrease (decreasing is harder) - natural_change = natural_change < 0 ? max(natural_change, BODYTEMP_COOLING_MAX / 8) : min(natural_change, BODYTEMP_HEATING_MAX / 6) - var/sigreturn = SEND_SIGNAL(src, COMSIG_LIVING_HOMEOSTASIS, natural_change, seconds_per_tick) if(sigreturn & HOMEOSTASIS_HANDLED) return diff --git a/monkestation/code/modules/temperature_overhaul/temperature_proc.dm b/monkestation/code/modules/temperature_overhaul/temperature_proc.dm index bc30e669c945..3e5e441d76e8 100644 --- a/monkestation/code/modules/temperature_overhaul/temperature_proc.dm +++ b/monkestation/code/modules/temperature_overhaul/temperature_proc.dm @@ -72,22 +72,17 @@ return FALSE amount = round(amount, 0.01) + if(amount == 0) + return 0 + amount = round(amount, 0.01) + if(bodytemperature >= min_temp && bodytemperature <= max_temp) var/old_temp = bodytemperature bodytemperature = clamp(bodytemperature + amount, min_temp, max_temp) SEND_SIGNAL(src, COMSIG_LIVING_BODY_TEMPERATURE_CHANGE, old_temp, bodytemperature) // body_temperature_alerts() - -#ifdef TESTING - if(mind) - maptext_width = 128 - maptext_x = -16 - maptext_y = -12 - var/r_or_b = body_temperature - old_temp > 0 ? "red" : "blue" - maptext = MAPTEXT("Temp: [body_temperature]K ([amount]K)") -#endif - return TRUE - return FALSE + return bodytemperature - old_temp + return 0 // Robot bodytemp unimplemented for now. Add overheating later >:3 /mob/living/silicon/adjust_bodytemperature(amount, min_temp, max_temp, use_insulation) @@ -107,28 +102,30 @@ // there's an argument to be made for putting the cold blooded check here return round(area_temperature, 0.01) - // calculate skin temp based on a weighted average of body temp and area temp - // (where area temp is modified by insulation) - var/body_weight = 2 - var/area_weight = 1 + get_insulation(area_temperature) - // total weight of / dividing by 3: two for bodytemp, one for areatemp (assuming 0 insulation) - // - // this gives 31.33 C for a standard human (37 C) in a 20 C room with no insulation - // and 34.33 C for a human with ~50% insulation (a winter coat) in the same room - // - // why do we convert to celcius? - // because i designed this equation around celcius and forgot i had to ultimately work in kelvin - // smaller numbers are easier to work with anyways. - var/skin_temp = (KELVIN_TO_CELCIUS(bodytemperature) * body_weight + KELVIN_TO_CELCIUS(area_temperature) * area_weight) / 3 + // calculate skin temp based on a weight average between body temp and area temp plus a multiplier + // this weighting gives us about 34.4c for a 37c body temp in a 20c room which is about average + var/skin_temp = ((bodytemperature * 2 + area_temperature * 1) / 3) + // convert to kelvin before multiplying, otherwise we go to the moon + var/result = KELVIN_TO_CELCIUS(skin_temp) + var/multiplier = 1.1 + // factor in insulation, but to a far lesser degree + // wearing a winter coat in a room temp area will increase skin temp to about 38.3c + multiplier *= (1 + (get_insulation(area_temperature) * 0.25)) if(!HAS_TRAIT(src, TRAIT_COLD_BLOODED)) - if(bodytemperature >= standard_body_temperature + 2 KELVIN) - skin_temp *= 1.1 // sweating - if(bodytemperature <= standard_body_temperature - 10 KELVIN) - skin_temp *= 0.8 // extremities are colder + if(bodytemperature >= standard_body_temperature + 2 CELCIUS) + multiplier *= 1.1 // vasodilation / sweating + if(bodytemperature <= standard_body_temperature + ((bodytemp_cold_damage_limit - standard_body_temperature) * 0.5)) + multiplier *= 0.9 // vasoconstriction + + // reverse the effect of insulation if we're subzero + // (otherwise, wearing a coat makes you colder) + if(result < 0) + multiplier = 1 / multiplier + . = CELCIUS_TO_KELVIN(result * multiplier) // and if we're on fire just add a flat amount of heat if(on_fire) - skin_temp += KELVIN_TO_CELCIUS(fire_stacks ** 2 KELVIN) + . += fire_stacks ** 2 KELVIN - return round(CELCIUS_TO_KELVIN(skin_temp), 0.01) + return . diff --git a/tgstation.dme b/tgstation.dme index c96a5961c517..f2b8398aab1d 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -6774,7 +6774,6 @@ #include "monkestation\code\modules\can_spessmen_feel_pain\pain\reagents\painkiller_related.dm" #include "monkestation\code\modules\can_spessmen_feel_pain\pain\reagents\painkillers.dm" #include "monkestation\code\modules\can_spessmen_feel_pain\pain\status_effects\anesthetics.dm" -#include "monkestation\code\modules\can_spessmen_feel_pain\pain\status_effects\fire_pain.dm" #include "monkestation\code\modules\can_spessmen_feel_pain\pain\status_effects\low_blood_pressure.dm" #include "monkestation\code\modules\can_spessmen_feel_pain\pain\status_effects\min_pain.dm" #include "monkestation\code\modules\can_spessmen_feel_pain\pain\status_effects\pain_limp.dm" From d20b100cab88ae551eb1ea77eb339ba3a8fd197b Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 13 Sep 2024 18:41:25 -0700 Subject: [PATCH 042/158] adds crutches and temp packs to medical lathes --- code/modules/research/techweb/all_nodes.dm | 3 ++ .../can_spessmen_feel_pain/pain/designs.dm | 42 +++++++++++++++++++ tgstation.dme | 1 + 3 files changed, 46 insertions(+) create mode 100644 monkestation/code/modules/can_spessmen_feel_pain/pain/designs.dm diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 5ff85373d52a..110c67408576 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -439,6 +439,9 @@ "diseaseanalyzer", "centrifuge", "path_data", + "heat_pack", + "cold_pack", + "medical_crutch", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) discount_experiments = list(/datum/experiment/dissection/human = 1000) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/designs.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/designs.dm new file mode 100644 index 000000000000..27dfc0f3a4f9 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/designs.dm @@ -0,0 +1,42 @@ +/datum/design/crutch + name = "Medical Crutch" + id = "medical_crutch" + build_type = PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1, + ) + build_path = /obj/item/cane/crutch + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_TOOLS + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL + +/datum/design/heat_pack + name = "Heat Pack" + id = "heat_pack" + build_type = PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1, //eg for now its fine dont wanna force plastic for this + ) + build_path = /obj/item/temperature_pack/heat + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_TOOLS + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL + + +/datum/design/cold_pack + name = "Cold Pack" + id = "cold_pack" + build_type = PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1, //eg for now its fine dont wanna force plastic for this + ) + build_path = /obj/item/temperature_pack/cold + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_TOOLS + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL diff --git a/tgstation.dme b/tgstation.dme index f2b8398aab1d..533673e1ab62 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -6757,6 +6757,7 @@ #include "monkestation\code\modules\can_spessmen_feel_pain\elements\temperature_pack.dm" #include "monkestation\code\modules\can_spessmen_feel_pain\pain\_base.dm" #include "monkestation\code\modules\can_spessmen_feel_pain\pain\bodyparts.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\designs.dm" #include "monkestation\code\modules\can_spessmen_feel_pain\pain\effects.dm" #include "monkestation\code\modules\can_spessmen_feel_pain\pain\helpers.dm" #include "monkestation\code\modules\can_spessmen_feel_pain\pain\item_helpers.dm" From ea6e9c9d8f8e95b7aca486256694fd9b3bebd8cc Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 13 Sep 2024 19:59:08 -0700 Subject: [PATCH 043/158] more ornthid tweaks --- code/modules/instruments/songs/_song.dm | 2 + code/modules/instruments/songs/editor.dm | 15 +-- icons/mob/actions/actions_items.dmi | Bin 14839 -> 16225 bytes .../the_bird_inside_of_me/icons/armwings.dmi | Bin 3217 -> 7401 bytes .../modules/the_bird_inside_of_me/organs.dm | 114 ++++++++++++++++++ .../modules/the_bird_inside_of_me/wings.dm | 2 +- 6 files changed, 125 insertions(+), 8 deletions(-) diff --git a/code/modules/instruments/songs/_song.dm b/code/modules/instruments/songs/_song.dm index 3067bc8a426f..7922a4d35833 100644 --- a/code/modules/instruments/songs/_song.dm +++ b/code/modules/instruments/songs/_song.dm @@ -123,6 +123,8 @@ var/cached_exponential_dropoff = 1.045 ///////////////////////////////////////////////////////////////////////// var/mixing_channel = CHANNEL_INSTRUMENTS + ///care about distance? + var/cares_about_distance = TRUE /datum/song/New(atom/parent, list/instrument_ids, new_range) SSinstruments.on_song_new(src) diff --git a/code/modules/instruments/songs/editor.dm b/code/modules/instruments/songs/editor.dm index 6f4bdc060049..7297720afc46 100644 --- a/code/modules/instruments/songs/editor.dm +++ b/code/modules/instruments/songs/editor.dm @@ -115,10 +115,11 @@ updateDialog(usr) // make sure updates when complete /datum/song/Topic(href, href_list) - if(!usr.can_perform_action(parent, ALLOW_RESTING)) - usr << browse(null, "window=instrument") - usr.unset_machine() - return + if(cares_about_distance) + if(!usr.can_perform_action(parent, ALLOW_RESTING)) + usr << browse(null, "window=instrument") + usr.unset_machine() + return parent.add_fingerprint(usr) @@ -131,7 +132,7 @@ var/t = "" do t = html_encode(input(usr, "Please paste the entire song, formatted:", text("[]", name), t) as message) - if(!in_range(parent, usr)) + if(!in_range(parent, usr) && cares_about_distance) return if(length_char(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS) @@ -158,7 +159,7 @@ else if(href_list["newline"]) var/newline = tgui_input_text(usr, "Enter your line ", parent.name) - if(!newline || !in_range(parent, usr)) + if(!newline || (!in_range(parent, usr) && cares_about_distance)) return if(lines.len > MUSIC_MAXLINES) return @@ -175,7 +176,7 @@ else if(href_list["modifyline"]) var/num = round(text2num(href_list["modifyline"]),1) var/content = tgui_input_text(usr, "Enter your line ", parent.name, lines[num], MUSIC_MAXLINECHARS) - if(!content || !in_range(parent, usr)) + if(!content || (!in_range(parent, usr) && cares_about_distance)) return if(num > lines.len || num < 1) return diff --git a/icons/mob/actions/actions_items.dmi b/icons/mob/actions/actions_items.dmi index 9b357963e2678a7cbac744742835df0d5ef3041d..681e7da89d5f71317e663011d298449b59702920 100644 GIT binary patch literal 16225 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 diff --git a/monkestation/code/modules/the_bird_inside_of_me/icons/armwings.dmi b/monkestation/code/modules/the_bird_inside_of_me/icons/armwings.dmi index d88ce46c24a077fca7a545f0f733eef3c8f07265..dc03684bdd16d2d2df359385031951ccf76529b0 100644 GIT binary patch literal 7401 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 literal 3217 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 Date: Fri, 13 Sep 2024 20:05:39 -0700 Subject: [PATCH 044/158] Update species.dm --- monkestation/code/modules/smithing/ipcs/species.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/monkestation/code/modules/smithing/ipcs/species.dm b/monkestation/code/modules/smithing/ipcs/species.dm index 27d9b6b383a7..82ee2f84e9cc 100644 --- a/monkestation/code/modules/smithing/ipcs/species.dm +++ b/monkestation/code/modules/smithing/ipcs/species.dm @@ -70,6 +70,9 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/robot/ipc, ) + bodytemp_heat_damage_limit = CELCIUS_TO_KELVIN(450) + bodytemp_cold_damage_limit = CELCIUS_TO_KELVIN(-270) //they are practically immune to cold + brutemod = 1.5 coldmod = 1.2 heatmod = 2 // TWO TIMES DAMAGE FROM BEING TOO HOT?! WHAT?! No wonder lava is literal instant death for us. From fc5a6656183869d53578297c4bdefc64c2b0211e Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 13 Sep 2024 20:17:42 -0700 Subject: [PATCH 045/158] Update species.dm --- monkestation/code/modules/smithing/ipcs/species.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/smithing/ipcs/species.dm b/monkestation/code/modules/smithing/ipcs/species.dm index 82ee2f84e9cc..bef0ad2ba95a 100644 --- a/monkestation/code/modules/smithing/ipcs/species.dm +++ b/monkestation/code/modules/smithing/ipcs/species.dm @@ -71,7 +71,7 @@ ) bodytemp_heat_damage_limit = CELCIUS_TO_KELVIN(450) - bodytemp_cold_damage_limit = CELCIUS_TO_KELVIN(-270) //they are practically immune to cold + bodytemp_cold_damage_limit = CELCIUS_TO_KELVIN(-260) //they are practically immune to cold brutemod = 1.5 coldmod = 1.2 From 7ffd5b0972dc941aeb3135e291d3d7486caef48e Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 13 Sep 2024 22:31:58 -0700 Subject: [PATCH 046/158] Update temperature_proc.dm --- .../code/modules/temperature_overhaul/temperature_proc.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monkestation/code/modules/temperature_overhaul/temperature_proc.dm b/monkestation/code/modules/temperature_overhaul/temperature_proc.dm index 3e5e441d76e8..6aa07f576da1 100644 --- a/monkestation/code/modules/temperature_overhaul/temperature_proc.dm +++ b/monkestation/code/modules/temperature_overhaul/temperature_proc.dm @@ -96,7 +96,7 @@ */ /mob/living/proc/get_skin_temperature() var/area_temperature = get_temperature(loc?.return_air()) - if(!(mob_biotypes & MOB_ORGANIC)) + if(!(mob_biotypes & MOB_ORGANIC) && !isipc(src)) // non-organic mobs likely don't feel or regulate temperature // so we can just report the area temp... probably // there's an argument to be made for putting the cold blooded check here @@ -104,13 +104,13 @@ // calculate skin temp based on a weight average between body temp and area temp plus a multiplier // this weighting gives us about 34.4c for a 37c body temp in a 20c room which is about average - var/skin_temp = ((bodytemperature * 2 + area_temperature * 1) / 3) + var/area_weight = 1 - get_insulation(area_temperature) + var/skin_temp = ((bodytemperature * 2 + area_temperature * area_weight) / (3 - get_insulation(area_temperature))) // convert to kelvin before multiplying, otherwise we go to the moon var/result = KELVIN_TO_CELCIUS(skin_temp) var/multiplier = 1.1 // factor in insulation, but to a far lesser degree // wearing a winter coat in a room temp area will increase skin temp to about 38.3c - multiplier *= (1 + (get_insulation(area_temperature) * 0.25)) if(!HAS_TRAIT(src, TRAIT_COLD_BLOODED)) if(bodytemperature >= standard_body_temperature + 2 CELCIUS) From 3d27f1c59f2ac49cde28057ecaee48d02b7c0168 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 13 Sep 2024 22:38:09 -0700 Subject: [PATCH 047/158] Update healing.dm --- .../modules/research/nanites/nanite_programs/healing.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monkestation/code/modules/research/nanites/nanite_programs/healing.dm b/monkestation/code/modules/research/nanites/nanite_programs/healing.dm index a59afc7826b7..c8d7d35b8438 100644 --- a/monkestation/code/modules/research/nanites/nanite_programs/healing.dm +++ b/monkestation/code/modules/research/nanites/nanite_programs/healing.dm @@ -36,16 +36,16 @@ rogue_types = list(/datum/nanite_program/skin_decay) /datum/nanite_program/temperature/check_conditions() - if(host_mob.bodytemperature > (host_mob.bodytemp_cold_damage_limit - 30) && host_mob.bodytemperature < (host_mob.bodytemp_heat_damage_limit)) + if(host_mob.bodytemperature > (host_mob.bodytemp_cold_damage_limit) && host_mob.bodytemperature < (host_mob.bodytemp_heat_damage_limit)) return FALSE return ..() /datum/nanite_program/temperature/active_effect() var/target_temp = host_mob.standard_body_temperature if(host_mob.bodytemperature > target_temp) - host_mob.adjust_bodytemperature(-40 * TEMPERATURE_DAMAGE_COEFFICIENT, target_temp) + host_mob.adjust_bodytemperature(-2.5 KELVIN, target_temp) else if(host_mob.bodytemperature < (target_temp + 1)) - host_mob.adjust_bodytemperature(40 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, target_temp) + host_mob.adjust_bodytemperature(2.5 KELVIN, 0, target_temp) /datum/nanite_program/purging name = "Blood Purification" From f4f3857a8b136e2df9dcd2ac2462d90e28616c79 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 14 Sep 2024 11:43:07 -0700 Subject: [PATCH 048/158] cryopod tweaks lung pop tweaks --- .../components/unary_devices/cryo.dm | 6 ++++ code/modules/surgery/organs/lungs.dm | 34 ++++++++++++------- .../nanites/nanite_programs/utility.dm | 2 +- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 595e2fcdde46..12a7db4f5e99 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -147,9 +147,15 @@ /obj/machinery/atmospherics/components/unary/cryo_cell/set_occupant(atom/movable/new_occupant) if(occupant && isnull(new_occupant)) REMOVE_TRAIT(occupant, TRAIT_ASSISTED_BREATHING, REF(src)) + if(isliving(occupant)) + var/mob/living/living = occupant + living.bodytemp_cold_damage_limit += 270 KELVIN . = ..() if(occupant && on) ADD_TRAIT(occupant, TRAIT_ASSISTED_BREATHING, REF(src)) + if(isliving(occupant)) + var/mob/living/living = occupant + living.bodytemp_cold_damage_limit -= 270 KELVIN update_appearance() /obj/machinery/atmospherics/components/unary/cryo_cell/on_construction(mob/user) diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index 97b478722977..6ca49a0efdef 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -113,6 +113,9 @@ var/crit_stabilizing_reagent = /datum/reagent/medicine/epinephrine + ///our last lung pop adventure + var/lung_pop_tick = 0 + // assign the respiration_type /obj/item/organ/internal/lungs/Initialize(mapload) . = ..() @@ -267,6 +270,7 @@ // Note this can be redundant, because of the vacuum check. It is fail safe tho, so it's ok if(old_o2_pp < safe_oxygen_min) breather.failed_last_breath = FALSE + lung_pop_tick = 0 breather.clear_alert(ALERT_NOT_ENOUGH_OXYGEN) breathe_gas_volume(breath, /datum/gas/oxygen, /datum/gas/carbon_dioxide) @@ -644,6 +648,7 @@ else if(HAS_TRAIT(src, TRAIT_SPACEBREATHING)) // The lungs can breathe anyways. What are you? Some bottom-feeding, scum-sucking algae eater? breather.failed_last_breath = FALSE + lung_pop_tick = 0 // Vacuum-adapted lungs regenerate oxyloss even when breathing nothing. if(HAS_TRAIT(breather, TRAIT_NOBLOOD)) breather.adjustOxyLoss(-4) @@ -653,21 +658,24 @@ // We're in a low / high pressure environment, can't breathe, but trying to, so this hurts the lungs // Unless it's cybernetic then it just doesn't care. Handwave magic whatever - else if(!skip_breath) - if(!failed) - // Lungs are poppin - if(damage >= 40 && damage <= 50 && breather.can_feel_pain()) - to_chat(breather, span_userdanger("You feel a stabbing pain in your chest!")) - else if(num_moles < 0.02) - to_chat(breather, span_boldwarning("You feel air rapidly exiting your lungs!")) - else if(num_moles > 0.1) - to_chat(breather, span_boldwarning("You feel air force itself into your lungs!")) - - breather.cause_pain(BODY_ZONE_CHEST, 10, BRUTE) - apply_organ_damage(5) + else if(!skip_breath && !HAS_TRAIT(owner, TRAIT_ASSISTED_BREATHING)) + if(lung_pop_tick > 10) + lung_pop_tick = 0 + if(!failed) + // Lungs are poppin + if(damage >= 40 && damage <= 50 && breather.can_feel_pain()) + to_chat(breather, span_userdanger("You feel a stabbing pain in your chest!")) + else if(num_moles < 0.02) + to_chat(breather, span_boldwarning("You feel air rapidly exiting your lungs!")) + else if(num_moles > 0.1) + to_chat(breather, span_boldwarning("You feel air force itself into your lungs!")) + + breather.cause_pain(BODY_ZONE_CHEST, 10, BRUTE) + apply_organ_damage(5) breather.failed_last_breath = TRUE + lung_pop_tick++ // Robot, don't care lol - else + else if(!HAS_TRAIT(owner, TRAIT_ASSISTED_BREATHING)) // Can't breathe! breather.failed_last_breath = TRUE diff --git a/monkestation/code/modules/research/nanites/nanite_programs/utility.dm b/monkestation/code/modules/research/nanites/nanite_programs/utility.dm index 37f7c8146d96..b14ecd1431fc 100644 --- a/monkestation/code/modules/research/nanites/nanite_programs/utility.dm +++ b/monkestation/code/modules/research/nanites/nanite_programs/utility.dm @@ -108,7 +108,7 @@ update_research_speed() - host_mob.add_homeostasis_level(NANITE_RESEARCH_CHANGE, research_speed * 15, 0.25 KELVIN) + host_mob.add_homeostasis_level(NANITE_RESEARCH_CHANGE, host_mob.standard_body_temperature + research_speed * 15, 0.25 KELVIN) use_rate = initial(use_rate) * research_speed current_research_bonus = use_rate SSresearch.science_tech.nanite_bonus += current_research_bonus From b4710981e6d6e52625b08be6dd5a9575731f1a1b Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 14 Sep 2024 15:27:56 -0700 Subject: [PATCH 049/158] fixes --- code/modules/mob/living/carbon/life.dm | 2 ++ code/modules/mob/living/living.dm | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index a5da401af333..5c81b5f4e477 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -232,6 +232,8 @@ /mob/living/carbon/proc/handle_organs(seconds_per_tick, times_fired) if(stat == DEAD) + if(reagents && (reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1) || reagents.has_reagent(/datum/reagent/cryostylane))) // No organ decay if the body contains formaldehyde. + return for(var/obj/item/organ/internal/organ in organs) // On-death is where organ decay is handled organ?.on_death(seconds_per_tick, times_fired) // organ can be null due to reagent metabolization causing organ shuffling diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 1082f702b498..46eeb74175bd 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1711,7 +1711,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) * * seconds_per_tick: Seconds between each life tick * * fire_handler: The fire handler status effect that is managing the fire stacks */ -/mob/living/proc/on_fire_stack(seconds_per_tick, datum/status_effect/fire_handler/fire_stacks/fire_handler) +/mob/living/proc/on_fire_stack(seconds_per_tick, times_fired, datum/status_effect/fire_handler/fire_stacks/fire_handler) var/amount_to_heat = HEAT_PER_FIRE_STACK * fire_handler.stacks * seconds_per_tick var/amount_to_burn = BURN_DAMAGE_PER_FIRE_STACK * fire_handler.stacks * seconds_per_tick if(bodytemperature > BODYTEMP_FIRE_TEMP_SOFTCAP) From 5d6f16a608d147e7be519dcaf580552ab83a97ae Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 14 Sep 2024 16:21:18 -0700 Subject: [PATCH 050/158] whoopss --- monkestation/code/modules/the_bird_inside_of_me/organs.dm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/monkestation/code/modules/the_bird_inside_of_me/organs.dm b/monkestation/code/modules/the_bird_inside_of_me/organs.dm index 87daebed7745..b5de56fe2231 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/organs.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/organs.dm @@ -46,11 +46,12 @@ /datum/song/organ/updateDialog(mob/user) parent.ui_interact(user || usr) -/datum/song/organ/should_stop_playing(obj/item/organ/player) +/datum/song/organ/should_stop_playing(obj/player) . = ..() if(. == STOP_PLAYING || . == IGNORE_INSTRUMENT_CHECKS) return TRUE - var/mob/living/musician = player.owner + var/obj/item/organ/owner = parent + var/mob/living/musician = owner.?owner return musician?.stat <= UNCONSCIOUS /datum/song/do_hearcheck() @@ -58,7 +59,7 @@ last_hearcheck = world.time var/list/old = hearing_mobs.Copy() hearing_mobs.len = 0 - var/turf/source = get_turf(parent) + var/turf/source = get_turf(player.owner) for(var/mob/M in get_hearers_in_view(instrument_range, player.owner)) hearing_mobs[M] = get_dist(M, source) var/list/exited = old - hearing_mobs From 4154ec59815b9b2f8ea22f83e4c222ac89ab2359 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 14 Sep 2024 16:23:35 -0700 Subject: [PATCH 051/158] Update organs.dm --- monkestation/code/modules/the_bird_inside_of_me/organs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/the_bird_inside_of_me/organs.dm b/monkestation/code/modules/the_bird_inside_of_me/organs.dm index b5de56fe2231..25a506e1cd3d 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/organs.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/organs.dm @@ -51,7 +51,7 @@ if(. == STOP_PLAYING || . == IGNORE_INSTRUMENT_CHECKS) return TRUE var/obj/item/organ/owner = parent - var/mob/living/musician = owner.?owner + var/mob/living/musician = owner?.owner return musician?.stat <= UNCONSCIOUS /datum/song/do_hearcheck() From ea5fdf601d4dc6dc66e5a6686d869049a548db20 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 14 Sep 2024 16:35:31 -0700 Subject: [PATCH 052/158] base linter fixes --- code/_globalvars/traits/_traits.dm | 1 + code/game/objects/items/pillow.dm | 2 +- .../code/modules/can_spessmen_feel_pain/pain/shock.dm | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 10eb361cab8b..4c1755f50dec 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -503,6 +503,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_XENO_HOST" = TRAIT_XENO_HOST, "TRAIT_XENO_IMMUNE" = TRAIT_XENO_IMMUNE, "TRAIT_XRAY_VISION" = TRAIT_XRAY_VISION, + "TRAIT_COLD_BLOODED" = TRAIT_COLD_BLOODED, /* "TRAIT_ADAMANTINE_EXTRACT_ARMOR" = TRAIT_ADAMANTINE_EXTRACT_ARMOR, */ /* "TRAIT_ALWAYS_WANTED" = TRAIT_ALWAYS_WANTED, */ /* "TRAIT_ANOSMIA" = TRAIT_ANOSMIA, */ diff --git a/code/game/objects/items/pillow.dm b/code/game/objects/items/pillow.dm index fa8e46cf3e30..a6582d47fb22 100644 --- a/code/game/objects/items/pillow.dm +++ b/code/game/objects/items/pillow.dm @@ -124,7 +124,7 @@ name = "pillow suit" desc = "Part man, part pillow. All CARNAGE!" body_parts_covered = CHEST|GROIN|ARMS|LEGS|FEET - //a pillow suit must be hella warm + //a pillow suit must be hella warm allowed = list(/obj/item/pillow) //moar pillow carnage icon = 'icons/obj/pillow.dmi' worn_icon = 'icons/mob/clothing/suits/pillow.dmi' diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm index f17c917e388e..8c8e04577b9d 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm @@ -180,7 +180,7 @@ if(SPT_PROB(8, seconds_per_tick)) to_chat(affected_mob, span_danger("You feel freezing!")) affected_mob.pain_emote("shiver", 3 SECONDS) - affected_mob.adjust_bodytemperature(-10 * seconds_per_tick, min = affected_mob.bodytemp_cold_damage_limit - 5) // uh oh + affected_mob.adjust_bodytemperature(-10 * seconds_per_tick, min_temp = affected_mob.bodytemp_cold_damage_limit - 5) // uh oh // irreversible - point of no return, system failure // cardiac arrest @@ -204,4 +204,4 @@ affected_mob.losebreath += 10 else if(SPT_PROB(10, seconds_per_tick)) to_chat(affected_mob, span_userdanger(pick("You feel your heart skip a beat...", "You feel your body shutting down...", "You feel your heart beat irregularly..."))) - affected_mob.adjust_bodytemperature(-10 * seconds_per_tick, min = affected_mob.bodytemp_cold_damage_limit - 20) // welp + affected_mob.adjust_bodytemperature(-10 * seconds_per_tick, min_temp = affected_mob.bodytemp_cold_damage_limit - 20) // welp From 919d2b6db581903e0f8b22e1d8ad5a835c43c3c2 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 14 Sep 2024 16:39:26 -0700 Subject: [PATCH 053/158] whoops --- code/game/objects/effects/decals/cleanable/humans.dm | 2 +- monkestation/code/modules/the_bird_inside_of_me/organs.dm | 2 +- monkestation/code/modules/the_wolf_inside_of_me/organs.dm | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index f7fbd0418d44..b35331d79af1 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -39,7 +39,7 @@ var/count = 0 var/footprint_sprite = null -/obj/effect/decal/cleanable/blood/Initialize(mapload) +/obj/effect/decal/cleanable/blood/Initialize(mapload, blood_color = COLOR_BLOOD) . = ..() START_PROCESSING(SSblood_drying, src) if(color && can_dry && !dried) diff --git a/monkestation/code/modules/the_bird_inside_of_me/organs.dm b/monkestation/code/modules/the_bird_inside_of_me/organs.dm index 25a506e1cd3d..e13338e3f542 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/organs.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/organs.dm @@ -36,7 +36,7 @@ music = owner.AddComponent(/datum/component/particle_spewer/music_notes) /obj/item/organ/internal/tongue/ornithid/proc/stop_sound_particles() - qdel(owner.GetComponent(/datum/component/particle_spewer/music_notes)) + qdel(owner?.GetComponent(/datum/component/particle_spewer/music_notes)) music = null // subtype for organs, like ornithid tongues diff --git a/monkestation/code/modules/the_wolf_inside_of_me/organs.dm b/monkestation/code/modules/the_wolf_inside_of_me/organs.dm index 70bcdddf5eda..0f98a3d84e5f 100644 --- a/monkestation/code/modules/the_wolf_inside_of_me/organs.dm +++ b/monkestation/code/modules/the_wolf_inside_of_me/organs.dm @@ -33,7 +33,6 @@ name = "Beastly liver" desc = "A large monstrous liver." icon_state = "liver" - organ_traits = list(ORGAN_UNREMOVABLE) ///Var for brute healing via blood var/blood_brute_healing = 2.5 ///Var for burn healing via blood From 39adaa9d95d8f2c939d0e09b834f52f7ae1290f1 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 14 Sep 2024 16:49:02 -0700 Subject: [PATCH 054/158] Update stomach_ethereal.dm --- code/modules/surgery/organs/stomach/stomach_ethereal.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/surgery/organs/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/stomach/stomach_ethereal.dm index 32992762be33..fcf1cd4c5dd6 100644 --- a/code/modules/surgery/organs/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/stomach/stomach_ethereal.dm @@ -2,6 +2,7 @@ name = "biological battery" icon_state = "stomach-p" //Welp. At least it's more unique in functionaliy. desc = "A crystal-like organ that stores the electric charge of ethereals." + hunger_modifier = 0.5 //organ_traits = list(TRAIT_NOHUNGER) // We have our own hunger mechanic. //Monkestation Removal, we have our OWN hunger mechanic. ///basically satiety but electrical var/crystal_charge = ETHEREAL_CHARGE_FULL @@ -37,7 +38,7 @@ /obj/item/organ/internal/stomach/ethereal/proc/handle_temp(mob/living/carbon/human/human, natural_change, seconds_per_tick) SIGNAL_HANDLER - if(human.blood_volume < (ETHEREAL_CHARGE_LOWPOWER / 2)) + if(human.blood_volume < (ETHEREAL_CHARGE_ALMOSTFULL)) return HOMEOSTASIS_HANDLED adjust_charge(-1 * ETHEREAL_CHARGE_FACTOR * abs(natural_change) * seconds_per_tick) From c0994f80a491e85e909a3bef3fa08b768adc4805 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 14 Sep 2024 21:28:06 -0700 Subject: [PATCH 055/158] redoes some things --- .../effects/decals/cleanable/humans.dm | 16 ++- code/modules/forensics/forensics_helpers.dm | 1 + .../code/modules/blood_datum/blood.dm | 5 + .../blood_for_the_blood_gods/particle.dm | 2 + .../factory_type_beat/machinery/assembler.dm | 106 ++++++------------ 5 files changed, 60 insertions(+), 70 deletions(-) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index b35331d79af1..145e8bdffd82 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -38,6 +38,7 @@ ) var/count = 0 var/footprint_sprite = null + var/glows = FALSE /obj/effect/decal/cleanable/blood/Initialize(mapload, blood_color = COLOR_BLOOD) . = ..() @@ -51,6 +52,11 @@ #define DRY_FILTER_KEY "dry_effect" +/obj/effect/decal/cleanable/blood/update_overlays() + . = ..() + if(glows) + . += emissive_appearance(icon, icon_state, src) + /obj/effect/decal/cleanable/blood/proc/update_blood_drying_effect() if(!can_dry) remove_filter(DRY_FILTER_KEY) // I GUESS @@ -78,7 +84,7 @@ for(var/dna_sample in all_dna) var/datum/blood_type/blood = GLOB.blood_types[all_dna[dna_sample]] all_blood_names |= lowertext(initial(blood.reagent_type.name)) - return english_list(all_blood_names) + return english_list(all_blood_names, nothing_text = "blood") /obj/effect/decal/cleanable/blood/process(seconds_per_tick) if(dried || !can_dry) @@ -384,12 +390,20 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) if(!bloodstep_overlay) GLOB.bloody_footprints_cache["entered-[icon_state_to_use]-[Ddir]"] = bloodstep_overlay = image(icon, "[icon_state_to_use]1", dir = Ddir) . += bloodstep_overlay + if(glows) + var/mutable_appearance/glow = emissive_appearance(icon, "[icon_state_to_use]1") + glow.dir = Ddir + . += glow if(exited_dirs & Ddir) var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["exited-[icon_state_to_use]-[Ddir]"] if(!bloodstep_overlay) GLOB.bloody_footprints_cache["exited-[icon_state_to_use]-[Ddir]"] = bloodstep_overlay = image(icon, "[icon_state_to_use]2", dir = Ddir) . += bloodstep_overlay + if(glows) + var/mutable_appearance/glow = emissive_appearance(icon, "[icon_state_to_use]2") + glow.dir = Ddir + . += glow /obj/effect/decal/cleanable/blood/footprints/examine(mob/user) diff --git a/code/modules/forensics/forensics_helpers.dm b/code/modules/forensics/forensics_helpers.dm index 6b837b711a43..90624dc7491b 100644 --- a/code/modules/forensics/forensics_helpers.dm +++ b/code/modules/forensics/forensics_helpers.dm @@ -74,6 +74,7 @@ else forensics = new(src, blood_DNA = blood_DNA_to_add) cached_blood_dna_color = null + update_appearance() return TRUE /obj/item/add_blood_DNA(list/blood_DNA_to_add) diff --git a/monkestation/code/modules/blood_datum/blood.dm b/monkestation/code/modules/blood_datum/blood.dm index 3cd58b6ac288..b047f973ef81 100644 --- a/monkestation/code/modules/blood_datum/blood.dm +++ b/monkestation/code/modules/blood_datum/blood.dm @@ -29,6 +29,8 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying) var/name = "?" /// What color is blood decals spawned of this type var/color = COLOR_BLOOD + ///do we glow + var/glows = FALSE /// What blood types can this type receive from /// Itself is always included in this list var/list/compatible_types = list() @@ -234,8 +236,11 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying) name = "LE" color = "#97ee63" reagent_type = /datum/reagent/consumable/liquidelectricity + glows = TRUE /datum/blood_type/crew/ethereal/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat) + blood.glows = TRUE + blood.update_appearance() if(!new_splat) return blood.can_dry = FALSE diff --git a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm index 0d6522fb804e..86298652870e 100644 --- a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm @@ -123,6 +123,8 @@ our_appearance.color = src.color our_appearance.pixel_x = src.pixel_x our_appearance.pixel_y = src.pixel_y + if(glows) + our_appearance.plane = EMISSIVE_PLANE icon_state = null color = null pixel_x = 0 diff --git a/monkestation/code/modules/factory_type_beat/machinery/assembler.dm b/monkestation/code/modules/factory_type_beat/machinery/assembler.dm index 65c31219c962..b350951a2427 100644 --- a/monkestation/code/modules/factory_type_beat/machinery/assembler.dm +++ b/monkestation/code/modules/factory_type_beat/machinery/assembler.dm @@ -208,75 +208,43 @@ return var/list/requirements = chosen_recipe.reqs - var/list/Deletion = list() - var/list/stored_parts = list() - var/data - var/amt - var/insanity = 500 - main_loop: - insanity-- - if(insanity <= 0) - return - for(var/path_key in requirements) - amt = chosen_recipe.reqs?[path_key] - if(!amt)//since machinery & structures can have 0 aka CRAFTING_MACHINERY_USE - i.e. use it, don't consume it! - continue main_loop - if(ispath(path_key, /obj/item/stack)) - var/obj/item/stack/S - var/obj/item/stack/SD - while(amt > 0) - S = locate(path_key) in crafting_inventory - if(S.amount >= amt) - if(!locate(S.type) in Deletion) - SD = new S.type() - Deletion += SD - S.use(amt) - SD = locate(S.type) in Deletion - SD.amount += amt - continue main_loop - else - amt -= S.amount - if(!locate(S.type) in Deletion) - Deletion += S - else - data = S.amount - S = locate(S.type) in Deletion - S.add(data) - crafting_inventory -= S + var/list/parts = list() + + for(var/obj/item/req as anything in requirements) + for(var/obj/item/item as anything in crafting_inventory) + if(!istype(item, req)) + continue + if(isstack(item)) + var/obj/item/stack/stack = item + if(stack.amount == requirements[stack.merge_type]) + var/failed = TRUE + crafting_inventory -= item + for(var/obj/item/part as anything in chosen_recipe.parts) + if(!istype(item, part)) + continue + parts += item + failed = FALSE + if(failed) + qdel(item) + else if(stack.amount > requirements[item.type]) + for(var/obj/item/part as anything in chosen_recipe.parts) + if(!istype(item, part)) + continue + var/obj/item/stack/new_stack = new item + new_stack.amount = requirements[item.type] + parts += new_stack + stack.amount -= requirements[stack.merge_type] else - var/atom/movable/I - while(amt > 0) - I = locate(path_key) in crafting_inventory - Deletion += I - crafting_inventory -= I - amt-- - var/list/partlist = list(chosen_recipe.parts.len) - for(var/M in chosen_recipe.parts) - partlist[M] = chosen_recipe.parts[M] - for(var/part in chosen_recipe.parts) - if(isstack(part)) - var/obj/item/stack/ST = locate(part) in Deletion - if(ST.amount > partlist[part]) - ST.amount = partlist[part] - stored_parts += ST - Deletion -= ST - continue - else - while(partlist[part] > 0) - var/atom/movable/AM = locate(part) in Deletion - stored_parts += AM - Deletion -= AM - partlist[part] -= 1 - while(Deletion.len) - var/DL = Deletion[Deletion.len] - Deletion.Cut(Deletion.len) - if(istype(DL, /obj/item/storage)) - var/obj/item/storage/container = DL - container.emptyStorage() - else if(isstructure(DL)) - var/obj/structure/structure = DL - structure.dump_contents(structure.drop_location()) - qdel(DL) + var/failed = TRUE + crafting_inventory -= item + for(var/obj/item/part as anything in chosen_recipe.parts) + if(!istype(item, part)) + continue + parts += item + failed = FALSE + + if(failed) + qdel(item) var/atom/movable/I if(ispath(chosen_recipe.result, /obj/item/stack)) @@ -288,7 +256,7 @@ if(I.atom_storage && chosen_recipe.delete_contents) for(var/obj/item/thing in I) qdel(thing) - I.CheckParts(stored_parts, chosen_recipe) + I.CheckParts(parts, chosen_recipe) I.forceMove(drop_location()) crafting = FALSE From 47871e5c7e995d7ca8bb5304b6998da8c17bfab2 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 14 Sep 2024 21:56:02 -0700 Subject: [PATCH 056/158] better blood --- code/game/objects/effects/decals/cleanable/humans.dm | 12 +++--------- code/modules/mob/living/blood.dm | 4 ++-- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 145e8bdffd82..6dfceecfa2e3 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -39,6 +39,7 @@ var/count = 0 var/footprint_sprite = null var/glows = FALSE + var/handles_unique = FALSE /obj/effect/decal/cleanable/blood/Initialize(mapload, blood_color = COLOR_BLOOD) . = ..() @@ -54,7 +55,7 @@ /obj/effect/decal/cleanable/blood/update_overlays() . = ..() - if(glows) + if(glows && !handles_unique) . += emissive_appearance(icon, icon_state, src) /obj/effect/decal/cleanable/blood/proc/update_blood_drying_effect() @@ -321,6 +322,7 @@ bloodiness = 0 // set based on the bloodiness of the foot base_name = "" dry_desc = "HMM... SOMEONE WAS HERE!" + handles_unique = TRUE var/entered_dirs = 0 var/exited_dirs = 0 @@ -390,20 +392,12 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) if(!bloodstep_overlay) GLOB.bloody_footprints_cache["entered-[icon_state_to_use]-[Ddir]"] = bloodstep_overlay = image(icon, "[icon_state_to_use]1", dir = Ddir) . += bloodstep_overlay - if(glows) - var/mutable_appearance/glow = emissive_appearance(icon, "[icon_state_to_use]1") - glow.dir = Ddir - . += glow if(exited_dirs & Ddir) var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["exited-[icon_state_to_use]-[Ddir]"] if(!bloodstep_overlay) GLOB.bloody_footprints_cache["exited-[icon_state_to_use]-[Ddir]"] = bloodstep_overlay = image(icon, "[icon_state_to_use]2", dir = Ddir) . += bloodstep_overlay - if(glows) - var/mutable_appearance/glow = emissive_appearance(icon, "[icon_state_to_use]2") - glow.dir = Ddir - . += glow /obj/effect/decal/cleanable/blood/footprints/examine(mob/user) diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 31ebc0d47544..d84366ee2ecb 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -314,7 +314,7 @@ var/obj/effect/decal/cleanable/blood/hitsplatter/our_splatter = new(loc) if(QDELETED(our_splatter)) return - our_splatter.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + our_splatter.add_mob_blood(src) var/turf/targ = get_ranged_target_turf(src, splatter_direction, splatter_strength) our_splatter.fly_towards(targ, splatter_strength) @@ -329,7 +329,7 @@ if(QDELETED(droplet)) // if they're deleting upon init, let's not waste any more time, any others will prolly just do the same thing return droplet.color = get_blood_type()?.color - droplet.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + droplet.add_mob_blood(src) droplet.pixel_z = rand(min_pixel_z, max_pixel_z) droplet.start_movement(angle + rand(min_deviation, max_deviation)) From 9631e35428dcd09b9b478de545598c56fced6508 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 14 Sep 2024 22:10:52 -0700 Subject: [PATCH 057/158] fixes --- code/game/objects/effects/decals/cleanable/humans.dm | 3 +++ code/modules/mob/living/living.dm | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 6dfceecfa2e3..7d3151e7dd63 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -448,6 +448,7 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) /obj/effect/decal/cleanable/blood/hitsplatter/Initialize(mapload, splatter_strength, blood_color = COLOR_BLOOD) . = ..() color = blood_color + blood_dna_info = GET_ATOM_BLOOD_DNA(src) prev_loc = loc //Just so we are sure prev_loc exists if(splatter_strength) src.splatter_strength = splatter_strength @@ -455,6 +456,8 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) /obj/effect/decal/cleanable/blood/hitsplatter/Destroy() if(isturf(loc) && !skip) playsound(src, 'sound/effects/wounds/splatter.ogg', 60, TRUE, -1) + if(!length(blood_dna_info)) + blood_dna_info = GET_ATOM_BLOOD_DNA(src) if(blood_dna_info) loc.add_blood_DNA(blood_dna_info) return ..() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 46eeb74175bd..a7bcdfe649ab 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1047,13 +1047,16 @@ if((newdir in GLOB.cardinals) && (prob(50))) newdir = turn(get_dir(target_turf, start), 180) if(!blood_exists) - new /obj/effect/decal/cleanable/blood/trail_holder(start, get_static_viruses()) + var/obj/effect/decal/cleanable/blood/trail_holder/new_blood = new /obj/effect/decal/cleanable/blood/trail_holder(start, get_static_viruses()) + new_blood.add_mob_blood(src) + new_blood.update_appearance() for(var/obj/effect/decal/cleanable/blood/trail_holder/TH in start) if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled) TH.existing_dirs += newdir TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir)) - TH.transfer_mob_blood_dna(src) + TH.add_mob_blood(src) + TH.update_appearance() /mob/living/carbon/human/makeTrail(turf/target_turf, turf/start, direction) if(!is_bleeding()) From e8b4edf50369e1ee3b89ea77a5748e0ad04105a5 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 15 Sep 2024 00:28:56 -0700 Subject: [PATCH 058/158] fixes --- .../machinery/components/unary_devices/cryo.dm | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 12a7db4f5e99..ea42ded0de66 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -113,6 +113,7 @@ var/patient_dead = FALSE fair_market_price = 10 payment_department = ACCOUNT_MED + var/adjusted_occupant = FALSE /datum/armor/unary_cryo_cell @@ -147,13 +148,15 @@ /obj/machinery/atmospherics/components/unary/cryo_cell/set_occupant(atom/movable/new_occupant) if(occupant && isnull(new_occupant)) REMOVE_TRAIT(occupant, TRAIT_ASSISTED_BREATHING, REF(src)) - if(isliving(occupant)) + if(isliving(occupant) && adjusted_occupant) + adjusted_occupant = FALSE var/mob/living/living = occupant living.bodytemp_cold_damage_limit += 270 KELVIN . = ..() if(occupant && on) ADD_TRAIT(occupant, TRAIT_ASSISTED_BREATHING, REF(src)) - if(isliving(occupant)) + if(isliving(occupant) && !adjusted_occupant) + adjusted_occupant = TRUE var/mob/living/living = occupant living.bodytemp_cold_damage_limit -= 270 KELVIN update_appearance() @@ -274,6 +277,17 @@ else REMOVE_TRAIT(occupant, TRAIT_ASSISTED_BREATHING, REF(src)) + if(on) + if(isliving(occupant) && !adjusted_occupant) + adjusted_occupant = TRUE + var/mob/living/living = occupant + living.bodytemp_cold_damage_limit -= 270 KELVIN + else + if(isliving(occupant) && adjusted_occupant) + adjusted_occupant = FALSE + var/mob/living/living = occupant + living.bodytemp_cold_damage_limit += 270 KELVIN + /obj/machinery/atmospherics/components/unary/cryo_cell/on_set_is_operational(old_value) if(old_value) //Turned off set_on(FALSE) From f108ce0959af23f410108ffcb8e8815dce271058 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 15 Sep 2024 09:42:16 -0700 Subject: [PATCH 059/158] fixes --- .../code/modules/the_bird_inside_of_me/organs.dm | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/monkestation/code/modules/the_bird_inside_of_me/organs.dm b/monkestation/code/modules/the_bird_inside_of_me/organs.dm index e13338e3f542..7d944f719b3e 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/organs.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/organs.dm @@ -44,17 +44,16 @@ cares_about_distance = FALSE /datum/song/organ/updateDialog(mob/user) - parent.ui_interact(user || usr) + var/obj/item/organ/owner = parent + var/mob/living/musician = owner?.owner + parent.ui_interact(musician) /datum/song/organ/should_stop_playing(obj/player) - . = ..() - if(. == STOP_PLAYING || . == IGNORE_INSTRUMENT_CHECKS) - return TRUE var/obj/item/organ/owner = parent var/mob/living/musician = owner?.owner - return musician?.stat <= UNCONSCIOUS + return musician?.stat >= UNCONSCIOUS -/datum/song/do_hearcheck() +/datum/song/organ/do_hearcheck() var/obj/item/organ/player = parent last_hearcheck = world.time var/list/old = hearing_mobs.Copy() From 73cbb9327c74ece7e69ad7ae733d488bab30ba5e Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 15 Sep 2024 12:00:52 -0700 Subject: [PATCH 060/158] Update pierce.dm --- code/datums/wounds/pierce.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index 0934a79d966c..6cf219718900 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -35,7 +35,7 @@ return ..() -datum/wound/pierce/bleed/receive_damage(wounding_type, wounding_dmg, wound_bonus, attack_direction, damage_source) +/datum/wound/pierce/bleed/receive_damage(wounding_type, wounding_dmg, wound_bonus, attack_direction, damage_source) if(victim.stat == DEAD || (wounding_dmg < WOUND_MINIMUM_DAMAGE) || wounding_type == WOUND_BURN) return if(!limb.can_bleed() || !prob(internal_bleeding_chance)) From df7e9035768ac4fc92a0b924f7dac2166874214e Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 15 Sep 2024 12:37:22 -0700 Subject: [PATCH 061/158] fixes --- code/datums/wounds/pierce.dm | 8 -------- .../code/modules/a_medical_day/internal_bleeding.dm | 4 ++-- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index 6cf219718900..8de3685667d8 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -195,14 +195,6 @@ wound_series = WOUND_SERIES_FLESH_PUNCTURE_BLEED -/datum/wound_pregen_data/flesh_pierce - abstract = TRUE - - required_limb_biostate = (BIO_FLESH) - required_wounding_types = list(WOUND_PIERCE) - - wound_series = WOUND_SERIES_FLESH_PUNCTURE_BLEED - /datum/wound/pierce/get_limb_examine_description() return span_warning("The flesh on this limb appears badly perforated.") diff --git a/monkestation/code/modules/a_medical_day/internal_bleeding.dm b/monkestation/code/modules/a_medical_day/internal_bleeding.dm index e9126af8a9d2..b03a7d452a88 100644 --- a/monkestation/code/modules/a_medical_day/internal_bleeding.dm +++ b/monkestation/code/modules/a_medical_day/internal_bleeding.dm @@ -25,12 +25,12 @@ COOLDOWN_DECLARE(worsen_cd) /datum/wound/bleed_internal/get_self_check_description(mob/user) - return span_warning("It feels tense to the touch.") // same as rib fracture! + return span_warning("You can see dark bruising.") // same as rib fracture! /datum/wound/bleed_internal/handle_process(seconds_per_tick, times_fired) if(!victim || victim.stat == DEAD || HAS_TRAIT(victim, TRAIT_STASIS) || !victim.needs_heart()) return - victim.bleed(bleed_amount * severity * seconds_per_tick) + victim.bleed(min(bleed_amount * severity * seconds_per_tick, 3)) /datum/wound/bleed_internal/wound_injury(datum/wound/old_wound, attack_direction) COOLDOWN_START(src, worsen_cd, 5 SECONDS) From 0dab1f0bcc240e52b24fbb9eda3e4d897853bda7 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 15 Sep 2024 12:39:12 -0700 Subject: [PATCH 062/158] Update organs.dm --- monkestation/code/modules/the_bird_inside_of_me/organs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/the_bird_inside_of_me/organs.dm b/monkestation/code/modules/the_bird_inside_of_me/organs.dm index 7d944f719b3e..fffe88683d49 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/organs.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/organs.dm @@ -46,7 +46,7 @@ /datum/song/organ/updateDialog(mob/user) var/obj/item/organ/owner = parent var/mob/living/musician = owner?.owner - parent.ui_interact(musician) + ui_interact(musician) /datum/song/organ/should_stop_playing(obj/player) var/obj/item/organ/owner = parent From deb21111ca5610753e39cd4ba45e2d37c0334136 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 15 Sep 2024 18:59:59 -0700 Subject: [PATCH 063/158] Update _base.dm --- monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm index 86b1f22f7431..43f917a3340d 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm @@ -543,7 +543,7 @@ if(checked_bodypart.pain_feedback(seconds_per_tick, no_recent_pain)) COOLDOWN_START(src, time_since_last_pain_message, 12 SECONDS) - if(!has_pain) + if(!has_pain && (shock_buildup <= -30) && !HAS_TRAIT_FROM(parent, TRAIT_LABOURED_BREATHING, PAINSHOCK)) // no-op if none of our bodyparts are in pain return From 39e98ae343e6f8c68923eaf6e8ba38083d1fcc9c Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 15 Sep 2024 19:07:35 -0700 Subject: [PATCH 064/158] Update stacking_effect.dm --- code/datums/status_effects/stacking_effect.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/status_effects/stacking_effect.dm b/code/datums/status_effects/stacking_effect.dm index 63f68c8041dc..9a682000eb78 100644 --- a/code/datums/status_effects/stacking_effect.dm +++ b/code/datums/status_effects/stacking_effect.dm @@ -101,8 +101,8 @@ else if(stacks < stack_threshold && threshold_crossed) threshold_crossed = FALSE //resets threshold effect if we fall below threshold so threshold effect can trigger again on_threshold_drop() - if(stacks_added > 0) - tick_interval += delay_before_decay //refreshes time until decay + if((stacks_added > 0) && delay_before_decay) + tick_interval = world.time + delay_before_decay //refreshes time until decay stacks = min(stacks, max_stacks) if(status_overlay) status_overlay.icon_state = "[overlay_state][stacks]" From a07a69934ed49acae91ae2da14bb057e12b86b3b Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 15 Sep 2024 21:40:46 -0700 Subject: [PATCH 065/158] Update tongue.dm --- code/modules/surgery/organs/tongue.dm | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index f5359a46b6cc..9066ea29d58e 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -57,24 +57,7 @@ /obj/item/organ/internal/tongue/proc/get_possible_languages() RETURN_TYPE(/list) // This is the default list of languages most humans should be capable of speaking - return list( - /datum/language/common, - /datum/language/uncommon, - /datum/language/draconic, - /datum/language/codespeak, - /datum/language/monkey, - /datum/language/narsie, - /datum/language/beachbum, - /datum/language/aphasia, - /datum/language/piratespeak, - /datum/language/moffic, - /datum/language/sylvan, - /datum/language/shadowtongue, - /datum/language/terrum, - /datum/language/nekomimetic, - /datum/language/ratvar, //Monkestation Edit - /datum/language/goblin, //Monkestation Addition - ) + return subtypesof(/datum/language) /obj/item/organ/internal/tongue/proc/handle_speech(datum/source, list/speech_args) SIGNAL_HANDLER From 7bd4114a412d8041a80e9e15b4d6925ffd142e15 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:58:55 -0700 Subject: [PATCH 066/158] more fixes --- .../items/implants/implant_explosive.dm | 2 +- code/modules/mob/living/carbon/death.dm | 20 +++++++++---------- code/modules/mob/living/death.dm | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/code/game/objects/items/implants/implant_explosive.dm b/code/game/objects/items/implants/implant_explosive.dm index 528da0a40de6..9c3706355ee6 100644 --- a/code/game/objects/items/implants/implant_explosive.dm +++ b/code/game/objects/items/implants/implant_explosive.dm @@ -58,7 +58,7 @@ explosion(src, devastation_range = heavy, heavy_impact_range = medium, light_impact_range = weak, flame_range = weak, flash_range = weak, explosion_cause = src) if(imp_in) imp_in.investigate_log("has been gibbed by an explosive implant.", INVESTIGATE_DEATHS) - imp_in.gib(TRUE) + imp_in.gib(TRUE, safe_gib = FALSE) qdel(src) return timed_explosion() diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index ba629ae60144..3377f373c3ad 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -24,17 +24,17 @@ M.Scale(1.8, 1.2) animate(src, time = 40, transform = M, easing = SINE_EASING) -/mob/living/carbon/gib(no_brain, no_organs, no_bodyparts, safe_gib = FALSE) +/mob/living/carbon/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) add_memory_in_range(src, 7, /datum/memory/witness_gib, protagonist = src) - // if(safe_gib) // If you want to keep all the mob's items and not have them deleted MONKESTATION EDIT - for(var/obj/item/W in src) - dropItemToGround(W, violent = TRUE) - if(prob(50)) - step(W, pick(GLOB.alldirs)) - var/atom/Tsec = drop_location() - for(var/mob/M in src) - M.forceMove(Tsec) - visible_message(span_danger("[M] bursts out of [src]!")) + if(safe_gib) // If you want to keep all the mob's items and not have them deleted MONKESTATION EDIT + for(var/obj/item/W in src) + dropItemToGround(W, violent = TRUE) + if(prob(50)) + step(W, pick(GLOB.alldirs)) + var/atom/Tsec = drop_location() + for(var/mob/M in src) + M.forceMove(Tsec) + visible_message(span_danger("[M] bursts out of [src]!")) return ..() /mob/living/carbon/spill_organs(no_brain, no_organs, no_bodyparts) diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index a82cacfaf960..e82151f1251d 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -6,7 +6,7 @@ * * no_organs - Should the mob NOT drop organs? * * no_bodyparts - Should the mob NOT drop bodyparts? */ -/mob/living/proc/gib(no_brain, no_organs, no_bodyparts) +/mob/living/proc/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) var/prev_lying = lying_angle if(stat != DEAD) death(TRUE) From 6f3a163b9b60d41736a3375b5718fdc42d7095fb Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 16 Sep 2024 16:36:24 -0700 Subject: [PATCH 067/158] Update living_defense.dm --- code/modules/mob/living/living_defense.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index f1794a6c97d6..88e6dcbe6000 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -131,8 +131,7 @@ var/extra_paralyze = 0 SECONDS var/extra_knockdown = 0 SECONDS - if(hitting_projectile.damage_type == BRUTE && !hitting_projectile.grazing) - // melbert todo scale on pain of bodypart? + if(hitting_projectile.damage_type == BRUTE && !hitting_projectile.grazing && pain_controller.get_average_pain() > 50) if(damage_done >= 60) if(!IsParalyzed() && prob(damage_done)) extra_paralyze += 0.8 SECONDS From ad3031947c2e9cfffb86a6a58980533a2fb8dd62 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 16 Sep 2024 16:36:55 -0700 Subject: [PATCH 068/158] Update living_defense.dm --- code/modules/mob/living/living_defense.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 88e6dcbe6000..e7e0d11b58a7 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -131,7 +131,7 @@ var/extra_paralyze = 0 SECONDS var/extra_knockdown = 0 SECONDS - if(hitting_projectile.damage_type == BRUTE && !hitting_projectile.grazing && pain_controller.get_average_pain() > 50) + if(hitting_projectile.damage_type == BRUTE && !hitting_projectile.grazing && (pain_controller.get_average_pain() > 50)) if(damage_done >= 60) if(!IsParalyzed() && prob(damage_done)) extra_paralyze += 0.8 SECONDS From 32f0b6128aaf01268bc25b695446f8c0ebc337b5 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 16 Sep 2024 23:45:43 -0700 Subject: [PATCH 069/158] base nuking stuff --- .../signals/signals_mob/signals_mob_main.dm | 4 + code/__DEFINES/dcs/signals/signals_specie.dm | 3 + code/_globalvars/bitfields.dm | 69 ++++++++++ code/datums/components/food/edible.dm | 48 ++----- code/datums/quirks/neutral_quirks.dm | 129 +++++++----------- .../dna_infuser/organ_sets/fly_organs.dm | 3 + .../dna_infuser/organ_sets/rat_organs.dm | 48 +------ code/game/objects/items/food/pastries.dm | 6 +- code/modules/food_and_drinks/pizzabox.dm | 4 +- code/modules/mob/living/basic/basic.dm | 2 +- code/modules/mob/living/basic/drone/_drone.dm | 2 +- .../basic/farm_animals/gorilla/gorilla.dm | 2 +- .../mob/living/basic/guardian/guardian.dm | 2 +- .../mob/living/basic/pets/dog/corgi.dm | 2 +- code/modules/mob/living/basic/pets/pet.dm | 2 +- .../basic/space_fauna/revenant/_revenant.dm | 2 +- .../living/basic/space_fauna/statue/statue.dm | 2 +- code/modules/mob/living/brain/death.dm | 2 +- code/modules/mob/living/carbon/alien/alien.dm | 3 - .../mob/living/carbon/human/_species.dm | 31 ++--- code/modules/mob/living/carbon/human/human.dm | 7 + .../mob/living/carbon/human/human_helpers.dm | 4 - .../carbon/human/species_types/dullahan.dm | 1 + .../carbon/human/species_types/flypeople.dm | 11 +- .../carbon/human/species_types/golems.dm | 10 +- .../carbon/human/species_types/humans.dm | 2 - .../carbon/human/species_types/jellypeople.dm | 2 - .../human/species_types/lizardpeople.dm | 2 - .../carbon/human/species_types/monkeys.dm | 2 - .../carbon/human/species_types/mothmen.dm | 3 - .../carbon/human/species_types/mushpeople.dm | 12 +- .../carbon/human/species_types/plasmamen.dm | 46 +------ .../carbon/human/species_types/podpeople.dm | 6 +- .../carbon/human/species_types/skeletons.dm | 33 +---- .../carbon/human/species_types/snail.dm | 12 +- .../carbon/human/species_types/zombies.dm | 2 - .../mob/living/simple_animal/friendly/pet.dm | 2 +- .../hostile/megafauna/_megafauna.dm | 2 +- .../mob/living/simple_animal/simple_animal.dm | 2 +- code/modules/mob/living/taste.dm | 71 +++++++++- code/modules/mob/mob.dm | 5 + code/modules/mob/mob_helpers.dm | 5 - .../reagents/reagent_containers/cups/_cup.dm | 53 +++---- .../reagents/withdrawal/generic_addictions.dm | 20 ++- .../research/designs/limbgrower_designs.dm | 2 +- .../{liver.dm => internal/liver/_liver.dm} | 44 ++++-- .../organs/internal/liver/liver_plasmamen.dm | 25 ++++ .../organs/internal/liver/liver_skeleton.dm | 49 +++++++ .../{tongue.dm => internal/tongue/_tongue.dm} | 96 ++++++++++++- .../antagonists/clock_cult/mobs/eminence.dm | 2 +- .../modules/botany/species/apid/species.dm | 11 +- .../carbon/human/species_type/arachnid.dm | 4 +- .../carbon/human/species_type/ethereal.dm | 1 - .../carbon/human/species_type/floran.dm | 7 +- .../carbon/human/species_type/goblin.dm | 8 +- .../carbon/human/species_type/simian.dm | 2 - .../code/modules/ranching/satyr/species.dm | 9 +- .../modules/smithing/oozelings/species.dm | 2 +- .../modules/surgery/organs/internal/tongue.dm | 2 + .../modules/the_bird_inside_of_me/species.dm | 1 - .../modules/the_wolf_inside_of_me/organs.dm | 12 +- tgstation.dme | 6 +- 62 files changed, 574 insertions(+), 390 deletions(-) rename code/modules/surgery/organs/{liver.dm => internal/liver/_liver.dm} (87%) mode change 100755 => 100644 create mode 100644 code/modules/surgery/organs/internal/liver/liver_plasmamen.dm create mode 100644 code/modules/surgery/organs/internal/liver/liver_skeleton.dm rename code/modules/surgery/organs/{tongue.dm => internal/tongue/_tongue.dm} (85%) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index 51b79ec9eb10..d5753bf6e8b5 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -11,6 +11,10 @@ #define COMSIG_MOB_MIND_INITIALIZED "mob_mind_inited" ///from base of mob/set_stat(): (new_stat, old_stat) #define COMSIG_MOB_STATCHANGE "mob_statchange" +///from base of mob/reagent_check(): (datum/reagent/chem, seconds_per_tick, times_fired) +#define COMSIG_MOB_REAGENT_CHECK "mob_reagent_check" + ///stops the reagent check call + #define COMSIG_MOB_STOP_REAGENT_CHECK (1<<0) ///from base of mob/clickon(): (atom/A, params) #define COMSIG_MOB_CLICKON "mob_clickon" ///from base of mob/MiddleClickOn(): (atom/A) diff --git a/code/__DEFINES/dcs/signals/signals_specie.dm b/code/__DEFINES/dcs/signals/signals_specie.dm index 89239cf39dbc..1ff22aed90c6 100644 --- a/code/__DEFINES/dcs/signals/signals_specie.dm +++ b/code/__DEFINES/dcs/signals/signals_specie.dm @@ -5,3 +5,6 @@ #define COMSIG_SPECIES_LOSS "species_loss" ///from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species) called before anything is done to ensure passing of data #define COMSIG_SPECIES_GAIN_PRE "species_gain_pre" +///from datum/species/handle_chemical(): (datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) +#define COMSIG_SPECIES_HANDLE_CHEMICAL "species_handle_chemicals" + // same return values as COMSIG_MOB_STOP_REAGENT_CHECK diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index b4051cb172b4..4497da073e3e 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -270,6 +270,75 @@ DEFINE_BITFIELD(mob_respiration_type, list( "RESPIRATION_PLASMA" = RESPIRATION_PLASMA, )) +DEFINE_BITFIELD(liked_foodtypes, list( + "MEAT" = MEAT, + "VEGETABLES" = VEGETABLES, + "RAW" = RAW, + "JUNKFOOD" = JUNKFOOD, + "GRAIN" = GRAIN, + "FRUIT" = FRUIT, + "DAIRY" = DAIRY, + "FRIED" = FRIED, + "ALCOHOL" = ALCOHOL, + "SUGAR" = SUGAR, + "GROSS" = GROSS, + "TOXIC" = TOXIC, + "PINEAPPLE" = PINEAPPLE, + "BREAKFAST" = BREAKFAST, + "CLOTH" = CLOTH, + "NUTS" = NUTS, + "SEAFOOD" = SEAFOOD, + "ORANGES" = ORANGES, + "BUGS" = BUGS, + "GORE" = GORE, +)) + +DEFINE_BITFIELD(disliked_foodtypes, list( + "MEAT" = MEAT, + "VEGETABLES" = VEGETABLES, + "RAW" = RAW, + "JUNKFOOD" = JUNKFOOD, + "GRAIN" = GRAIN, + "FRUIT" = FRUIT, + "DAIRY" = DAIRY, + "FRIED" = FRIED, + "ALCOHOL" = ALCOHOL, + "SUGAR" = SUGAR, + "GROSS" = GROSS, + "TOXIC" = TOXIC, + "PINEAPPLE" = PINEAPPLE, + "BREAKFAST" = BREAKFAST, + "CLOTH" = CLOTH, + "NUTS" = NUTS, + "SEAFOOD" = SEAFOOD, + "ORANGES" = ORANGES, + "BUGS" = BUGS, + "GORE" = GORE, +)) + +DEFINE_BITFIELD(toxic_foodtypes, list( + "MEAT" = MEAT, + "VEGETABLES" = VEGETABLES, + "RAW" = RAW, + "JUNKFOOD" = JUNKFOOD, + "GRAIN" = GRAIN, + "FRUIT" = FRUIT, + "DAIRY" = DAIRY, + "FRIED" = FRIED, + "ALCOHOL" = ALCOHOL, + "SUGAR" = SUGAR, + "GROSS" = GROSS, + "TOXIC" = TOXIC, + "PINEAPPLE" = PINEAPPLE, + "BREAKFAST" = BREAKFAST, + "CLOTH" = CLOTH, + "NUTS" = NUTS, + "SEAFOOD" = SEAFOOD, + "ORANGES" = ORANGES, + "BUGS" = BUGS, + "GORE" = GORE, +)) + DEFINE_BITFIELD(mobility_flags, list( "MOVE" = MOBILITY_MOVE, "PICKUP" = MOBILITY_PICKUP, diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index e2d21840182f..a1726ca00b4e 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -511,57 +511,39 @@ Behavior that's still missing from this component that original food items had t return TRUE ///Check foodtypes to see if we should send a moodlet -/datum/component/edible/proc/checkLiked(fraction, mob/M) +/datum/component/edible/proc/checkLiked(fraction, mob/eater) if(last_check_time + 50 > world.time) return FALSE - if(!ishuman(M)) + if(!ishuman(eater)) return FALSE - var/mob/living/carbon/human/H = M + var/mob/living/carbon/human/gourmand = eater //Bruh this breakfast thing is cringe and shouldve been handled separately from food-types, remove this in the future (Actually, just kill foodtypes in general) if((foodtypes & BREAKFAST) && world.time - SSticker.round_start_time < STOP_SERVING_BREAKFAST) - H.add_mood_event("breakfast", /datum/mood_event/breakfast) + gourmand.add_mood_event("breakfast", /datum/mood_event/breakfast) last_check_time = world.time - if(HAS_TRAIT(H, TRAIT_AGEUSIA)) - if(foodtypes & H.dna.species.toxic_food) - to_chat(H, span_warning("You don't feel so good...")) - H.adjust_disgust(25 + 30 * fraction) - return // Don't care about the later checks if user has ageusia - var/food_taste_reaction if(check_liked) //Callback handling; use this as an override for special food like donuts - food_taste_reaction = check_liked.Invoke(fraction, H) + food_taste_reaction = check_liked.Invoke(fraction, gourmand) if(!food_taste_reaction) - if(foodtypes & H.dna.species.toxic_food) - food_taste_reaction = FOOD_TOXIC - else if(foodtypes & H.dna.species.disliked_food) - food_taste_reaction = FOOD_DISLIKED - else if(foodtypes & H.dna.species.liked_food) - food_taste_reaction = FOOD_LIKED - - if(HAS_TRAIT(parent, TRAIT_FOOD_SILVER)) // it's not real food - food_taste_reaction = isjellyperson(H) ? FOOD_LIKED : FOOD_TOXIC + food_taste_reaction = gourmand.get_food_taste_reaction(parent, foodtypes) switch(food_taste_reaction) if(FOOD_TOXIC) - to_chat(H,span_warning("What the hell was that thing?!")) - H.adjust_disgust(25 + 30 * fraction) - H.add_mood_event("toxic_food", /datum/mood_event/disgusting_food) + to_chat(gourmand,span_warning("What the hell was that thing?!")) + gourmand.adjust_disgust(25 + 30 * fraction) + gourmand.add_mood_event("toxic_food", /datum/mood_event/disgusting_food) if(FOOD_DISLIKED) - to_chat(H,span_notice("That didn't taste very good...")) - H.adjust_disgust(11 + 15 * fraction) - H.add_mood_event("gross_food", /datum/mood_event/gross_food) + to_chat(gourmand,span_notice("That didn't taste very good...")) + gourmand.adjust_disgust(11 + 15 * fraction) + gourmand.add_mood_event("gross_food", /datum/mood_event/gross_food) if(FOOD_LIKED) - to_chat(H,span_notice("I love this taste!")) - H.adjust_disgust(-5 + -2.5 * fraction) - H.add_mood_event("fav_food", /datum/mood_event/favorite_food) - if(istype(parent, /obj/item/food)) - var/obj/item/food/memorable_food = parent - if(memorable_food.venue_value >= FOOD_PRICE_EXOTIC) - H.add_mob_memory(/datum/memory/good_food, food = parent) + to_chat(gourmand,span_notice("I love this taste!")) + gourmand.adjust_disgust(-5 + -2.5 * fraction) + gourmand.add_mood_event("fav_food", /datum/mood_event/favorite_food) ///Delete the item when it is fully eaten /datum/component/edible/proc/On_Consume(mob/living/eater, mob/living/feeder) diff --git a/code/datums/quirks/neutral_quirks.dm b/code/datums/quirks/neutral_quirks.dm index 4bc4c2168ab0..126af15ec8be 100644 --- a/code/datums/quirks/neutral_quirks.dm +++ b/code/datums/quirks/neutral_quirks.dm @@ -68,26 +68,18 @@ mail_goodies = list(/obj/effect/spawner/random/food_or_drink/salad) /datum/quirk/vegetarian/add(client/client_source) - var/mob/living/carbon/human/human_holder = quirk_holder - var/datum/species/species = human_holder.dna.species - species.liked_food &= ~MEAT - species.disliked_food |= MEAT - RegisterSignal(human_holder, COMSIG_SPECIES_GAIN, PROC_REF(on_species_gain)) - -/datum/quirk/vegetarian/proc/on_species_gain(datum/source, datum/species/new_species, datum/species/old_species) - SIGNAL_HANDLER - new_species.liked_food &= ~MEAT - new_species.disliked_food |= MEAT + var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE) + if(!tongue) + return + tongue.liked_foodtypes &= ~MEAT + tongue.disliked_foodtypes |= MEAT /datum/quirk/vegetarian/remove() - var/mob/living/carbon/human/human_holder = quirk_holder - - var/datum/species/species = human_holder.dna.species - if(initial(species.liked_food) & MEAT) - species.liked_food |= MEAT - if(!(initial(species.disliked_food) & MEAT)) - species.disliked_food &= ~MEAT - UnregisterSignal(human_holder, COMSIG_SPECIES_GAIN) + var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE) + if(!tongue) + return + tongue.liked_foodtypes = initial(tongue.liked_foodtypes) + tongue.disliked_foodtypes = initial(tongue.disliked_foodtypes) /datum/quirk/snob name = "Snob" @@ -111,20 +103,16 @@ mail_goodies = list(/obj/item/food/pizzaslice/pineapple) /datum/quirk/pineapple_liker/add(client/client_source) - var/mob/living/carbon/human/human_holder = quirk_holder - var/datum/species/species = human_holder.dna.species - species.liked_food |= PINEAPPLE - RegisterSignal(human_holder, COMSIG_SPECIES_GAIN, PROC_REF(on_species_gain)) - -/datum/quirk/pineapple_liker/proc/on_species_gain(datum/source, datum/species/new_species, datum/species/old_species) - SIGNAL_HANDLER - new_species.liked_food |= PINEAPPLE + var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE) + if(!tongue) + return + tongue.liked_foodtypes |= PINEAPPLE /datum/quirk/pineapple_liker/remove() - var/mob/living/carbon/human/human_holder = quirk_holder - var/datum/species/species = human_holder.dna.species - species.liked_food &= ~PINEAPPLE - UnregisterSignal(human_holder, COMSIG_SPECIES_GAIN) + var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE) + if(!tongue) + return + tongue.liked_foodtypes = initial(tongue.liked_foodtypes) /datum/quirk/pineapple_hater name = "Ananas Aversion" @@ -143,20 +131,16 @@ ) /datum/quirk/pineapple_hater/add(client/client_source) - var/mob/living/carbon/human/human_holder = quirk_holder - var/datum/species/species = human_holder.dna.species - species.disliked_food |= PINEAPPLE - RegisterSignal(human_holder, COMSIG_SPECIES_GAIN, PROC_REF(on_species_gain)) - -/datum/quirk/pineapple_hater/proc/on_species_gain(datum/source, datum/species/new_species, datum/species/old_species) - SIGNAL_HANDLER - new_species.disliked_food |= PINEAPPLE + var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE) + if(!tongue) + return + tongue.disliked_foodtypes |= PINEAPPLE /datum/quirk/pineapple_hater/remove() - var/mob/living/carbon/human/human_holder = quirk_holder - var/datum/species/species = human_holder.dna.species - species.disliked_food &= ~PINEAPPLE - UnregisterSignal(human_holder, COMSIG_SPECIES_GAIN) + var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE) + if(!tongue) + return + tongue.disliked_foodtypes = initial(tongue.disliked_foodtypes) /datum/quirk/deviant_tastes name = "Deviant Tastes" @@ -169,25 +153,19 @@ mail_goodies = list(/obj/item/food/urinalcake, /obj/item/food/badrecipe) // Mhhhmmm yummy /datum/quirk/deviant_tastes/add(client/client_source) - var/mob/living/carbon/human/human_holder = quirk_holder - var/datum/species/species = human_holder.dna.species - var/liked = species.liked_food - species.liked_food = species.disliked_food - species.disliked_food = liked - RegisterSignal(human_holder, COMSIG_SPECIES_GAIN, PROC_REF(on_species_gain)) - -/datum/quirk/deviant_tastes/proc/on_species_gain(datum/source, datum/species/new_species, datum/species/old_species) - SIGNAL_HANDLER - var/liked = new_species.liked_food - new_species.liked_food = new_species.disliked_food - new_species.disliked_food = liked + var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE) + if(!tongue) + return + var/liked_foodtypes = tongue.liked_foodtypes + tongue.liked_foodtypes = tongue.disliked_foodtypes + tongue.disliked_foodtypes = liked_foodtypes /datum/quirk/deviant_tastes/remove() - var/mob/living/carbon/human/human_holder = quirk_holder - var/datum/species/species = human_holder.dna.species - species.liked_food = initial(species.liked_food) - species.disliked_food = initial(species.disliked_food) - UnregisterSignal(human_holder, COMSIG_SPECIES_GAIN) + var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE) + if(!tongue) + return + tongue.liked_foodtypes = initial(tongue.liked_foodtypes) + tongue.disliked_foodtypes = initial(tongue.disliked_foodtypes) /datum/quirk/heterochromatic name = "Heterochromatic" @@ -410,27 +388,22 @@ var/gaming_withdrawal_timer = TIMER_ID_NULL /datum/quirk/gamer/add(client/client_source) - // Gamer diet - var/mob/living/carbon/human/human_holder = quirk_holder - var/datum/species/species = human_holder.dna.species - species.liked_food = JUNKFOOD - RegisterSignal(human_holder, COMSIG_SPECIES_GAIN, PROC_REF(on_species_gain)) - RegisterSignal(human_holder, COMSIG_MOB_WON_VIDEOGAME, PROC_REF(won_game)) - RegisterSignal(human_holder, COMSIG_MOB_LOST_VIDEOGAME, PROC_REF(lost_game)) - RegisterSignal(human_holder, COMSIG_MOB_PLAYED_VIDEOGAME, PROC_REF(gamed)) - -/datum/quirk/gamer/proc/on_species_gain(datum/source, datum/species/new_species, datum/species/old_species) - SIGNAL_HANDLER - new_species.liked_food = JUNKFOOD + var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE) + if(tongue) + // Gamer diet + tongue.liked_foodtypes = JUNKFOOD + RegisterSignal(quirk_holder, COMSIG_MOB_WON_VIDEOGAME, PROC_REF(won_game)) + RegisterSignal(quirk_holder, COMSIG_MOB_LOST_VIDEOGAME, PROC_REF(lost_game)) + RegisterSignal(quirk_holder, COMSIG_MOB_PLAYED_VIDEOGAME, PROC_REF(gamed)) /datum/quirk/gamer/remove() - var/mob/living/carbon/human/human_holder = quirk_holder - var/datum/species/species = human_holder.dna.species - species.liked_food = initial(species.liked_food) - UnregisterSignal(human_holder, COMSIG_SPECIES_GAIN) - UnregisterSignal(human_holder, COMSIG_MOB_WON_VIDEOGAME) - UnregisterSignal(human_holder, COMSIG_MOB_LOST_VIDEOGAME) - UnregisterSignal(human_holder, COMSIG_MOB_PLAYED_VIDEOGAME) + var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE) + if(tongue) + tongue.liked_foodtypes = initial(tongue.liked_foodtypes) + UnregisterSignal(quirk_holder, COMSIG_MOB_WON_VIDEOGAME) + UnregisterSignal(quirk_holder, COMSIG_MOB_LOST_VIDEOGAME) + UnregisterSignal(quirk_holder, COMSIG_MOB_PLAYED_VIDEOGAME) + /datum/quirk/gamer/add_unique(client/client_source) // The gamer starts off quelled diff --git a/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm index 74d028d22c6f..1b915b22653d 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm @@ -37,6 +37,9 @@ icon = 'icons/obj/medical/organs/fly_organs.dmi' say_mod = "buzzes" taste_sensitivity = 25 // you eat vomit, this is a mercy + liked_foodtypes = GROSS | GORE // nasty ass + disliked_foodtypes = NONE + toxic_foodtypes = NONE // these fucks eat vomit, i am sure they can handle drinking bleach or whatever too modifies_speech = TRUE languages_native = list(/datum/language/buzzwords) diff --git a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm index ff9a96b7f397..5d088da77889 100644 --- a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm @@ -43,51 +43,13 @@ greyscale_config = /datum/greyscale_config/mutant_organ greyscale_colors = RAT_COLORS /// Multiplier of [physiology.hunger_mod]. - var/hunger_mod = 10 + hunger_modifier = 10 /obj/item/organ/internal/stomach/rat/Initialize(mapload) . = ..() AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/rat) AddElement(/datum/element/noticable_organ, "mouth is drooling excessively.", BODY_ZONE_PRECISE_MOUTH) -/obj/item/organ/internal/stomach/rat/on_insert(mob/living/carbon/receiver) - . = ..() - if(!ishuman(receiver)) - return - var/mob/living/carbon/human/human_holder = receiver - if(!human_holder.can_mutate()) - return - var/datum/species/species = human_holder.dna.species - //mmm, cheese. doesn't especially like anything else - species.liked_food = DAIRY - //but a rat can eat anything without issue - species.disliked_food = NONE - species.toxic_food = NONE - if(human_holder.physiology) - human_holder.physiology.hunger_mod *= hunger_mod - RegisterSignal(human_holder, COMSIG_SPECIES_GAIN, PROC_REF(on_species_gain)) - -/obj/item/organ/internal/stomach/rat/proc/on_species_gain(datum/source, datum/species/new_species, datum/species/old_species) - SIGNAL_HANDLER - new_species.liked_food = DAIRY - new_species.disliked_food = NONE - new_species.toxic_food = NONE - -/obj/item/organ/internal/stomach/rat/on_remove(mob/living/carbon/stomach_owner) - . = ..() - if(!ishuman(stomach_owner)) - return - var/mob/living/carbon/human/human_holder = stomach_owner - if(!human_holder.can_mutate()) - return - var/datum/species/species = human_holder.dna.species - species.liked_food = initial(species.liked_food) - species.disliked_food = initial(species.disliked_food) - species.toxic_food = initial(species.toxic_food) - if(human_holder.physiology) - human_holder.physiology.hunger_mod /= hunger_mod - UnregisterSignal(stomach_owner, COMSIG_SPECIES_GAIN) - /// makes you smaller, walk over tables, and take 1.5x damage /obj/item/organ/internal/heart/rat name = "mutated rat-heart" @@ -126,13 +88,15 @@ /obj/item/organ/internal/tongue/rat name = "mutated rat-tongue" desc = "Rat DNA infused into what was once a normal tongue." - say_mod = "squeaks" - modifies_speech = TRUE - icon = 'icons/obj/medical/organs/infuser_organs.dmi' icon_state = "tongue" + say_mod = "squeaks" + modifies_speech = TRUE greyscale_config = /datum/greyscale_config/mutant_organ greyscale_colors = RAT_COLORS + liked_foodtypes = DAIRY //mmm, cheese. doesn't especially like anything else + disliked_foodtypes = NONE //but a rat can eat anything without issue + toxic_foodtypes = NONE /obj/item/organ/internal/tongue/rat/Initialize(mapload) . = ..() diff --git a/code/game/objects/items/food/pastries.dm b/code/game/objects/items/food/pastries.dm index 94babd0cf901..aa88a9448bd4 100644 --- a/code/game/objects/items/food/pastries.dm +++ b/code/game/objects/items/food/pastries.dm @@ -45,10 +45,10 @@ /obj/item/food/muffin/moffin/examine(mob/user) . = ..() - if(!ishuman(user)) + if(!isliving(user)) return - var/mob/living/carbon/human/moffin_observer = user - if(moffin_observer.dna.species.liked_food & CLOTH) + var/mob/living/moffin_observer = user + if(moffin_observer.get_liked_foodtypes() & CLOTH) . += span_nicegreen("Ooh! It's even got bits of clothes on it! Yummy!") else . += span_warning("You're not too sure what's on top though...") diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm index 7c0b9b346d36..eb98bd58f39e 100644 --- a/code/modules/food_and_drinks/pizzabox.dm +++ b/code/modules/food_and_drinks/pizzabox.dm @@ -382,14 +382,14 @@ if(pizza.type != pizza_preferences[nommer.ckey]) QDEL_NULL(pizza) else - pizza.foodtypes = nommer.dna.species.liked_food //make sure it's our favourite + pizza.foodtypes = nommer.get_liked_foodtypes() //make sure it's our favourite return var/obj/item/food/pizza/favourite_pizza_type = pizza_preferences[nommer.ckey] pizza = new favourite_pizza_type boxtag_set = FALSE update_appearance() //update our boxtag to match our new pizza - pizza.foodtypes = nommer.dna.species.liked_food //it's our favorite! + pizza.foodtypes = nommer.get_liked_foodtypes() //it's our favorite! ///screentips for pizzaboxes /obj/item/pizzabox/add_context(atom/source, list/context, obj/item/held_item, mob/user) diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm index 89afd35417e7..c26c94456ff8 100644 --- a/code/modules/mob/living/basic/basic.dm +++ b/code/modules/mob/living/basic/basic.dm @@ -176,7 +176,7 @@ health = 0 look_dead() -/mob/living/basic/gib() +/mob/living/basic/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) if(butcher_results || guaranteed_butcher_results) var/list/butcher_loot = list() if(butcher_results) diff --git a/code/modules/mob/living/basic/drone/_drone.dm b/code/modules/mob/living/basic/drone/_drone.dm index 27c328617c4d..061ca478bc42 100644 --- a/code/modules/mob/living/basic/drone/_drone.dm +++ b/code/modules/mob/living/basic/drone/_drone.dm @@ -262,7 +262,7 @@ alert_drones(DRONE_NET_DISCONNECT) -/mob/living/basic/drone/gib() +/mob/living/basic/drone/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) dust() /mob/living/basic/drone/examine(mob/user) diff --git a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm index 637f5b283b81..ef0467871e50 100644 --- a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm +++ b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm @@ -95,7 +95,7 @@ else target.throw_at(get_edge_target_turf(target, dir), range = rand(1, 2), speed = 7, thrower = src) -/mob/living/basic/gorilla/gib() +/mob/living/basic/gorilla/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) var/mob/living/brain/gorilla_brain = new(drop_location()) gorilla_brain.name = real_name gorilla_brain.real_name = real_name diff --git a/code/modules/mob/living/basic/guardian/guardian.dm b/code/modules/mob/living/basic/guardian/guardian.dm index c84e9bca4525..40296207db3b 100644 --- a/code/modules/mob/living/basic/guardian/guardian.dm +++ b/code/modules/mob/living/basic/guardian/guardian.dm @@ -196,7 +196,7 @@ return TRUE -/mob/living/basic/guardian/gib() +/mob/living/basic/guardian/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) death(TRUE) /mob/living/basic/guardian/dust(just_ash, drop_items, force) diff --git a/code/modules/mob/living/basic/pets/dog/corgi.dm b/code/modules/mob/living/basic/pets/dog/corgi.dm index a651a93ed48b..cf6ef5203ee4 100644 --- a/code/modules/mob/living/basic/pets/dog/corgi.dm +++ b/code/modules/mob/living/basic/pets/dog/corgi.dm @@ -62,7 +62,7 @@ update_appearance(UPDATE_OVERLAYS) return ..() -/mob/living/basic/pet/dog/corgi/gib() +/mob/living/basic/pet/dog/corgi/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) if(inventory_head) inventory_head.forceMove(drop_location()) inventory_head = null diff --git a/code/modules/mob/living/basic/pets/pet.dm b/code/modules/mob/living/basic/pets/pet.dm index 6e8c87059e57..6940513250f8 100644 --- a/code/modules/mob/living/basic/pets/pet.dm +++ b/code/modules/mob/living/basic/pets/pet.dm @@ -54,7 +54,7 @@ . += mutable_appearance(icon, "[collar_icon_state][stat_tag]collar") . += mutable_appearance(icon, "[collar_icon_state][stat_tag]tag") -/mob/living/basic/pet/gib() +/mob/living/basic/pet/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) remove_collar(drop_location(), update_visuals = FALSE) return ..() diff --git a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm index 5c65704a39cc..4e8e6319640b 100644 --- a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm +++ b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm @@ -256,7 +256,7 @@ /mob/living/basic/revenant/dust(just_ash, drop_items, force) death() -/mob/living/basic/revenant/gib() +/mob/living/basic/revenant/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) death() /mob/living/basic/revenant/can_perform_action(atom/movable/target, action_bitflags) diff --git a/code/modules/mob/living/basic/space_fauna/statue/statue.dm b/code/modules/mob/living/basic/space_fauna/statue/statue.dm index f906044cdab6..7e56808c7cdf 100644 --- a/code/modules/mob/living/basic/space_fauna/statue/statue.dm +++ b/code/modules/mob/living/basic/space_fauna/statue/statue.dm @@ -89,7 +89,7 @@ // Turn to dust when gibbed -/mob/living/basic/statue/gib() +/mob/living/basic/statue/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) dust() // Statue powers diff --git a/code/modules/mob/living/brain/death.dm b/code/modules/mob/living/brain/death.dm index 60487aa0c359..6de222060c82 100644 --- a/code/modules/mob/living/brain/death.dm +++ b/code/modules/mob/living/brain/death.dm @@ -11,7 +11,7 @@ return ..() -/mob/living/brain/gib() +/mob/living/brain/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) if(container) qdel(container)//Gets rid of the MMI if there is one if(loc) diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index a6b57e32ecb6..497223b575ad 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -52,9 +52,6 @@ else clear_alert(ALERT_XENO_FIRE) -/mob/living/carbon/alien/reagent_check(datum/reagent/R, seconds_per_tick, times_fired) //can metabolize all reagents - return FALSE - /mob/living/carbon/alien/getTrail() if(getBruteLoss() < 200) return pick (list("xltrails_1", "xltrails2")) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 8890ba61fa1b..cc76e80dbc98 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -73,12 +73,6 @@ GLOBAL_LIST_EMPTY(features_by_species) var/meat = /obj/item/food/meat/slab/human ///What skin the species drops when gibbed by a gibber machine. var/skinned_type - ///Bitfield for food types that the species likes, giving them a mood boost. Lizards like meat, for example. - var/liked_food = NONE - ///Bitfield for food types that the species dislikes, giving them disgust. Humans hate raw food, for example. - var/disliked_food = GROSS - ///Bitfield for food types that the species absolutely hates, giving them even more disgust than disliked food. Meat is "toxic" to moths, for example. - var/toxic_food = TOXIC ///flags for inventory slots the race can't equip stuff to. Golems cannot wear jumpsuits, for example. var/no_equip_flags ///What languages this species can understand and say. Use a [language holder datum][/datum/language_holder] in this var. @@ -923,7 +917,10 @@ GLOBAL_LIST_EMPTY(features_by_species) return /datum/species/proc/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) - if(HAS_TRAIT(H, TRAIT_NOBREATH)) + SHOULD_CALL_PARENT(TRUE) + if(H.stat == DEAD) + return + if(HAS_TRAIT(H, TRAIT_NOBREATH) && (H.health < H.crit_threshold) && !HAS_TRAIT(H, TRAIT_NOCRITDAMAGE)) H.setOxyLoss(0) H.losebreath = 0 @@ -1105,7 +1102,7 @@ GLOBAL_LIST_EMPTY(features_by_species) * Return True to not run the normal metabolism effects. * NOTE: If you return TRUE, that reagent will not be removed liike normal! You must handle it manually. */ -/datum/species/proc/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) +/datum/species/proc/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) SHOULD_CALL_PARENT(TRUE) // Cringe but blood handles this on its own // This also has problems of its own but that's better fixed later I think @@ -1134,6 +1131,7 @@ GLOBAL_LIST_EMPTY(features_by_species) chem.overdosed = TRUE chem.overdose_start(affected) affected.log_message("has started overdosing on [chem.name] at [chem.volume] units.", LOG_GAME) + return SEND_SIGNAL(affected, COMSIG_SPECIES_HANDLE_CHEMICAL, chem, affected, seconds_per_tick, times_fired) /** * Equip the outfit required for life. Replaces items currently worn. @@ -1610,21 +1608,16 @@ GLOBAL_LIST_EMPTY(features_by_species) * Returns a list, or null if they have no diet. */ /datum/species/proc/get_species_diet() - if(TRAIT_NOHUNGER in inherent_traits) + if((TRAIT_NOHUNGER in inherent_traits) || !mutanttongue) return null - var/list/food_flags = FOOD_FLAGS + var/static/list/food_flags = FOOD_FLAGS + var/obj/item/organ/internal/tongue/fake_tongue = mutanttongue - if(HAS_TRAIT(src, TRAIT_FLESH_DESIRE)) - return list( - "liked_food" = bitfield_to_list(GORE | MEAT, food_flags), - "disliked_food" = null, - "toxic_food" = bitfield_to_list(VEGETABLES | DAIRY | FRUIT | FRIED, food_flags), - ) return list( - "liked_food" = bitfield_to_list(liked_food, food_flags), - "disliked_food" = bitfield_to_list(disliked_food, food_flags), - "toxic_food" = bitfield_to_list(toxic_food, food_flags), + "liked_food" = bitfield_to_list(initial(fake_tongue.liked_foodtypes), food_flags), + "disliked_food" = bitfield_to_list(initial(fake_tongue.disliked_foodtypes), food_flags), + "toxic_food" = bitfield_to_list(initial(fake_tongue.toxic_foodtypes), food_flags), ) /** diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index f6440d911444..423d1b817c38 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -895,6 +895,13 @@ return ..() + +/mob/living/carbon/human/reagent_check(datum/reagent/chem, seconds_per_tick, times_fired) + . = ..() + if(. & COMSIG_MOB_STOP_REAGENT_CHECK) + return + return dna.species.handle_chemical(chem, src, seconds_per_tick, times_fired) + /mob/living/carbon/human/updatehealth() . = ..() dna?.species.spec_updatehealth(src) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index de565725dbb6..a83190417216 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -110,10 +110,6 @@ //Check inventory slots return (wear_id?.GetID() || belt?.GetID()) -/mob/living/carbon/human/reagent_check(datum/reagent/R, seconds_per_tick, times_fired) - return dna.species.handle_chemicals(R, src, seconds_per_tick, times_fired) - // if it returns 0, it will run the usual on_mob_life for that reagent. otherwise, it will stop after running handle_chemicals for the species. - /mob/living/carbon/human/can_use_guns(obj/item/G) . = ..() if(G.trigger_guard == TRIGGER_GUARD_NORMAL) diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm index 5e1d4530228f..0c558c769737 100644 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm @@ -71,6 +71,7 @@ human.reset_perspective(human) /datum/species/dullahan/spec_life(mob/living/carbon/human/human, seconds_per_tick, times_fired) + . = ..() if(QDELETED(my_head)) my_head = null human.investigate_log("has been gibbed by the loss of [human.p_their()] head.", INVESTIGATE_DEATHS) diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm index 86897dec5cfb..bd9f1f05e664 100644 --- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm @@ -10,9 +10,6 @@ inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG meat = /obj/item/food/meat/slab/human/mutant/fly mutanteyes = /obj/item/organ/internal/eyes/fly - liked_food = GROSS | GORE - disliked_food = NONE - toxic_food = NONE changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_language_holder = /datum/language_holder/fly wing_types = list(/obj/item/organ/external/wings/functional/fly) @@ -43,6 +40,14 @@ . = ..() UnregisterSignal(C, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS) + +/datum/species/fly/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) + . = ..() + if(. & COMSIG_MOB_STOP_REAGENT_CHECK) + return + if(chem.type == /datum/reagent/toxin/pestkiller) + affected.adjustToxLoss(3 * REM * seconds_per_tick) + /datum/species/fly/proc/damage_weakness(datum/source, list/damage_mods, damage_amount, damagetype, def_zone, sharpness, attack_direction, obj/item/attacking_item) SIGNAL_HANDLER diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index bb6a364807a2..0f861a5cf633 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -297,6 +297,7 @@ //Regenerates because self-repairing super-advanced alien tech /datum/species/golem/alloy/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) + SHOULD_CALL_PARENT(FALSE) if(H.stat == DEAD) return H.heal_overall_damage(brute = 1 * seconds_per_tick, burn = 1 * seconds_per_tick, required_bodytype = BODYTYPE_ORGANIC) @@ -333,6 +334,7 @@ examine_limb_id = SPECIES_GOLEM /datum/species/golem/wood/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) + SHOULD_CALL_PARENT(FALSE) if(H.stat == DEAD) return var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing @@ -350,7 +352,7 @@ if(H.nutrition < NUTRITION_LEVEL_STARVING + 50) H.take_overall_damage(brute = 2, required_bodytype = BODYTYPE_ORGANIC) -/datum/species/golem/wood/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) +/datum/species/golem/wood/handle_chemical(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) if(chem.type == /datum/reagent/toxin/plantbgone) H.adjustToxLoss(3 * REM * seconds_per_tick) H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick) @@ -721,7 +723,7 @@ QDEL_NULL(dominate) return ..() -/datum/species/golem/runic/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) +/datum/species/golem/runic/handle_chemical(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) . = ..() if(istype(chem, /datum/reagent/water/holywater)) H.adjustFireLoss(4 * REM * seconds_per_tick) @@ -1131,8 +1133,6 @@ id = SPECIES_GOLEM_BONE prefix = "Bone" special_names = list("Head", "Broth", "Fracture", "Rattler", "Appetit") - liked_food = GROSS | MEAT | RAW | GORE - toxic_food = null inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutanttongue = /obj/item/organ/internal/tongue/bone mutantstomach = /obj/item/organ/internal/stomach/bone @@ -1183,7 +1183,7 @@ bonechill.Remove(C) ..() -/datum/species/golem/bone/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) +/datum/species/golem/bone/handle_chemical(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) . = ..() if(chem.type == /datum/reagent/toxin/bonehurtingjuice) H.stamina.adjust(-7.5 * REM * seconds_per_tick, 0) diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm index caeecface3f7..320c4d69a814 100644 --- a/code/modules/mob/living/carbon/human/species_types/humans.dm +++ b/code/modules/mob/living/carbon/human/species_types/humans.dm @@ -8,8 +8,6 @@ mutant_bodyparts = list("wings" = "None") use_skintones = TRUE skinned_type = /obj/item/stack/sheet/animalhide/human - disliked_food = GROSS | RAW | CLOTH | BUGS | GORE - liked_food = JUNKFOOD | FRIED changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT payday_modifier = 1 diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index fe0802a0953a..2fd895356cd5 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -25,8 +25,6 @@ exotic_bloodtype = /datum/blood_type/slime blood_deficiency_drain_rate = JELLY_REGEN_RATE + BLOOD_DEFICIENCY_MODIFIER var/datum/action/innate/regenerate_limbs/regenerate_limbs - liked_food = MEAT | BUGS - toxic_food = NONE coldmod = 6 // = 3x cold damage heatmod = 0.5 // = 1/4x heat damage burnmod = 0.5 // = 1/2x generic burn damage diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index cbf8c9c62b61..cd1432128d62 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -31,8 +31,6 @@ meat = /obj/item/food/meat/slab/human/mutant/lizard skinned_type = /obj/item/stack/sheet/animalhide/lizard exotic_bloodtype = /datum/blood_type/crew/lizard - disliked_food = GRAIN | DAIRY | CLOTH | GROSS - liked_food = GORE | MEAT | SEAFOOD | NUTS | BUGS inert_mutation = /datum/mutation/human/firebreath death_sound = 'sound/voice/lizard/deathsound.ogg' wing_types = list(/obj/item/organ/external/wings/functional/dragon) diff --git a/code/modules/mob/living/carbon/human/species_types/monkeys.dm b/code/modules/mob/living/carbon/human/species_types/monkeys.dm index 4810b185a43f..763feebd439b 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -25,8 +25,6 @@ ) no_equip_flags = ITEM_SLOT_OCLOTHING | ITEM_SLOT_GLOVES | ITEM_SLOT_FEET | ITEM_SLOT_SUITSTORE changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | ERT_SPAWN | SLIME_EXTRACT - liked_food = MEAT | FRUIT | BUGS - disliked_food = CLOTH sexes = FALSE species_language_holder = /datum/language_holder/monkey diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index 90cd1774596c..305ae13576c9 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -14,9 +14,6 @@ mutant_bodyparts = list("moth_markings" = "None") external_organs = list(/obj/item/organ/external/wings/moth = "Plain", /obj/item/organ/external/antennae = "Plain") meat = /obj/item/food/meat/slab/human/mutant/moth - liked_food = VEGETABLES | DAIRY | CLOTH - disliked_food = FRUIT | GROSS | BUGS | GORE - toxic_food = MEAT | RAW | SEAFOOD mutanttongue = /obj/item/organ/internal/tongue/moth mutanteyes = /obj/item/organ/internal/eyes/moth changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm index 7a3bf8ef78f1..5d30c93255cc 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -57,13 +57,13 @@ mush.remove(C) QDEL_NULL(mush) -/datum/species/mush/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) +/datum/species/mush/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) + . = ..() + if(. & COMSIG_MOB_STOP_REAGENT_CHECK) + return if(chem.type == /datum/reagent/toxin/plantbgone/weedkiller) - H.adjustToxLoss(3 * REM * seconds_per_tick) - H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick) - return TRUE - return ..() + affected.adjustToxLoss(3 * REM * seconds_per_tick) /datum/species/mush/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour) forced_colour = FALSE - ..() + return ..() diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index 19f9f5c3d1d0..4ca4dcaeed65 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -22,7 +22,7 @@ inherent_respiration_type = RESPIRATION_PLASMA mutantlungs = /obj/item/organ/internal/lungs/plasmaman mutanttongue = /obj/item/organ/internal/tongue/bone/plasmaman - mutantliver = /obj/item/organ/internal/liver/plasmaman + mutantliver = /obj/item/organ/internal/liver/bone/plasmaman mutantstomach = /obj/item/organ/internal/stomach/bone/plasmaman mutantappendix = null mutantheart = null @@ -31,8 +31,6 @@ brutemod = 1.5 payday_modifier = 0.75 breathid = "plas" - disliked_food = FRUIT | CLOTH - liked_food = VEGETABLES changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC species_cookie = /obj/item/reagent_containers/condiment/milk outfit_important_for_life = /datum/outfit/plasmaman @@ -73,6 +71,7 @@ C.set_safe_hunger_level() /datum/species/plasmaman/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) + . = ..() var/atmos_sealed = TRUE if(HAS_TRAIT(H, TRAIT_NOFIRE)) atmos_sealed = FALSE @@ -152,47 +151,6 @@ return randname -/datum/species/plasmaman/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) - . = ..() - if(istype(chem, /datum/reagent/toxin/plasma) || istype(chem, /datum/reagent/toxin/hot_ice)) - for(var/i in H.all_wounds) - var/datum/wound/iter_wound = i - iter_wound.on_xadone(4 * REM * seconds_per_tick) // plasmamen use plasma to reform their bones or whatever - return FALSE // do normal metabolism - - if(istype(chem, /datum/reagent/toxin/bonehurtingjuice)) - H.stamina.adjust(-7.5 * REM * seconds_per_tick, 0) - H.adjustBruteLoss(0.5 * REM * seconds_per_tick, 0) - if(SPT_PROB(10, seconds_per_tick)) - switch(rand(1, 3)) - if(1) - H.say(pick("oof.", "ouch.", "my bones.", "oof ouch.", "oof ouch my bones."), forced = /datum/reagent/toxin/bonehurtingjuice) - if(2) - H.manual_emote(pick("oofs silently.", "looks like [H.p_their()] bones hurt.", "grimaces, as though [H.p_their()] bones hurt.")) - if(3) - to_chat(H, span_warning("Your bones hurt!")) - if(chem.overdosed) - if(SPT_PROB(2, seconds_per_tick) && iscarbon(H)) //big oof - var/selected_part = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) //God help you if the same limb gets picked twice quickly. - var/obj/item/bodypart/bp = H.get_bodypart(selected_part) //We're so sorry skeletons, you're so misunderstood - if(bp) - playsound(H, get_sfx(SFX_DESECRATION), 50, TRUE, -1) //You just want to socialize - H.visible_message(span_warning("[H] rattles loudly and flails around!!"), span_danger("Your bones hurt so much that your missing muscles spasm!!")) - H.say("OOF!!", forced=/datum/reagent/toxin/bonehurtingjuice) - bp.receive_damage(200, 0, 0) //But I don't think we should - else - to_chat(H, span_warning("Your missing arm aches from wherever you left it.")) - H.emote("sigh") - H.reagents.remove_reagent(chem.type, chem.metabolization_rate * seconds_per_tick) - return TRUE - - if(istype(chem, /datum/reagent/gunpowder)) - H.set_timed_status_effect(15 SECONDS * seconds_per_tick, /datum/status_effect/drugginess) - if(H.get_timed_status_effect_duration(/datum/status_effect/hallucination) / 10 < chem.volume) - H.adjust_hallucinations(2.5 SECONDS * seconds_per_tick) - // Do normal metabolism - return FALSE - /datum/species/plasmaman/get_scream_sound(mob/living/carbon/human) return pick( 'sound/voice/plasmaman/plasmeme_scream_1.ogg', diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index 31f2c81c6ab4..dd3bf1b0cee0 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -12,6 +12,7 @@ external_organs = list( /obj/item/organ/external/pod_hair = "None", ) + mutanttongue = /obj/item/organ/internal/tongue/pod inherent_biotypes = MOB_ORGANIC | MOB_HUMANOID | MOB_PLANT inherent_factions = list(FACTION_PLANTS, FACTION_VINES) @@ -20,8 +21,6 @@ payday_modifier = 0.75 meat = /obj/item/food/meat/slab/human/mutant/plant exotic_bloodtype = /datum/blood_type/water - disliked_food = MEAT | DAIRY | SEAFOOD | BUGS - liked_food = VEGETABLES | FRUIT | GRAIN changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_language_holder = /datum/language_holder/plant @@ -37,6 +36,7 @@ ass_image = 'icons/ass/asspodperson.png' /datum/species/pod/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) + . = ..() if(H.stat == DEAD) return @@ -57,7 +57,7 @@ H.take_overall_damage(brute = 1 * seconds_per_tick, required_bodytype = BODYTYPE_ORGANIC) ..() -/datum/species/pod/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) +/datum/species/pod/handle_chemical(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) if(chem.type == /datum/reagent/toxin/plantbgone) H.adjustToxLoss(3 * REM * seconds_per_tick) H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick) diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm index 1c294c2579ff..dcc2cd4b64c3 100644 --- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm +++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm @@ -34,10 +34,8 @@ mutantstomach = /obj/item/organ/internal/stomach/bone mutantappendix = null mutantheart = null - mutantliver = null + mutantliver = /obj/item/organ/internal/liver/bone mutantlungs = null - disliked_food = NONE - liked_food = GROSS | MEAT | RAW | GORE wing_types = list(/obj/item/organ/external/wings/functional/skeleton) //They can technically be in an ERT changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN @@ -62,35 +60,6 @@ return TRUE return ..() -//Can still metabolize milk through meme magic -/datum/species/skeleton/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) - . = ..() - if(chem.type == /datum/reagent/toxin/bonehurtingjuice) - H.stamina.adjust(-7.5 * REM * seconds_per_tick, 0) - H.adjustBruteLoss(0.5 * REM * seconds_per_tick, 0) - if(SPT_PROB(10, seconds_per_tick)) - switch(rand(1, 3)) - if(1) - H.say(pick("oof.", "ouch.", "my bones.", "oof ouch.", "oof ouch my bones."), forced = /datum/reagent/toxin/bonehurtingjuice) - if(2) - H.manual_emote(pick("oofs silently.", "looks like [H.p_their()] bones hurt.", "grimaces, as though [H.p_their()] bones hurt.")) - if(3) - to_chat(H, span_warning("Your bones hurt!")) - if(chem.overdosed) - if(SPT_PROB(2, seconds_per_tick) && iscarbon(H)) //big oof - var/selected_part = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) //God help you if the same limb gets picked twice quickly. - var/obj/item/bodypart/bp = H.get_bodypart(selected_part) //We're so sorry skeletons, you're so misunderstood - if(bp) - playsound(H, get_sfx(SFX_DESECRATION), 50, TRUE, -1) //You just want to socialize - H.visible_message(span_warning("[H] rattles loudly and flails around!!"), span_danger("Your bones hurt so much that your missing muscles spasm!!")) - H.say("OOF!!", forced=/datum/reagent/toxin/bonehurtingjuice) - bp.receive_damage(200, 0, 0) //But I don't think we should - else - to_chat(H, span_warning("Your missing arm aches from wherever you left it.")) - H.emote("sigh") - H.reagents.remove_reagent(chem.type, chem.metabolization_rate * seconds_per_tick) - return TRUE - /datum/species/skeleton/get_species_description() return "A rattling skeleton! They descend upon Space Station 13 \ Every year to spook the crew! \"I've got a BONE to pick with you!\"" diff --git a/code/modules/mob/living/carbon/human/species_types/snail.dm b/code/modules/mob/living/carbon/human/species_types/snail.dm index f812610ffb42..a1cde44588bc 100644 --- a/code/modules/mob/living/carbon/human/species_types/snail.dm +++ b/code/modules/mob/living/carbon/human/species_types/snail.dm @@ -28,13 +28,15 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/snail ) -/datum/species/snail/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) +/datum/species/snail/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) . = ..() + if(. & COMSIG_MOB_STOP_REAGENT_CHECK) + return if(istype(chem,/datum/reagent/consumable/salt)) - H.adjustFireLoss(2 * REM * seconds_per_tick) - playsound(H, 'sound/weapons/sear.ogg', 30, TRUE) - H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick) - return TRUE + //playsound(affected, SFX_SEAR, 30, TRUE) + affected.adjustFireLoss(2 * REM * seconds_per_tick) + affected.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick) + return COMSIG_MOB_STOP_REAGENT_CHECK /datum/species/snail/on_species_gain(mob/living/carbon/new_snailperson, datum/species/old_species, pref_load) . = ..() diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index 9ff7894c614c..92f73fe32565 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -37,8 +37,6 @@ mutantlungs = null inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg') - disliked_food = NONE - liked_food = GROSS | MEAT | RAW | GORE changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | ERT_SPAWN bodytemp_normal = T0C // They have no natural body heat, the environment regulates body temp bodytemp_heat_damage_limit = FIRE_MINIMUM_TEMPERATURE_TO_EXIST // Take damage at fire temp diff --git a/code/modules/mob/living/simple_animal/friendly/pet.dm b/code/modules/mob/living/simple_animal/friendly/pet.dm index 2c509d799ee0..5b8e69277675 100644 --- a/code/modules/mob/living/simple_animal/friendly/pet.dm +++ b/code/modules/mob/living/simple_animal/friendly/pet.dm @@ -55,7 +55,7 @@ . += mutable_appearance(icon, "[collar_icon_state][stat_tag]collar") . += mutable_appearance(icon, "[collar_icon_state][stat_tag]tag") -/mob/living/simple_animal/pet/gib() +/mob/living/simple_animal/pet/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) . = ..() if(access_card) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm index 7641650f259b..0a5d062069d1 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm @@ -95,7 +95,7 @@ /mob/living/simple_animal/hostile/megafauna/proc/spawn_crusher_loot() loot = crusher_loot -/mob/living/simple_animal/hostile/megafauna/gib() +/mob/living/simple_animal/hostile/megafauna/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) if(health > 0) return diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index e984ded97ff8..9ff9a0cf3def 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -383,7 +383,7 @@ if(!.) clear_alert(ALERT_TEMPERATURE) -/mob/living/simple_animal/gib() +/mob/living/simple_animal/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) if(butcher_results || guaranteed_butcher_results) var/list/butcher = list() if(butcher_results) diff --git a/code/modules/mob/living/taste.dm b/code/modules/mob/living/taste.dm index fc8fcbb37176..b6edde37d1e4 100644 --- a/code/modules/mob/living/taste.dm +++ b/code/modules/mob/living/taste.dm @@ -21,7 +21,10 @@ // carbons without tongues normally have TRAIT_AGEUSIA but sensible fallback . = DEFAULT_TASTE_SENSITIVITY -// non destructively tastes a reagent container +/** + * Non destructively tastes a reagent container + * and gives feedback to the user. + **/ /mob/living/proc/taste(datum/reagents/from) if(HAS_TRAIT(src, TRAIT_AGEUSIA)) return @@ -43,4 +46,70 @@ last_taste_time = world.time last_taste_text = text_output +/** + * Gets food flags that this mob likes + **/ +/mob/living/proc/get_liked_foodtypes() + return NONE + +/mob/living/carbon/get_liked_foodtypes() + var/obj/item/organ/internal/tongue/tongue = get_organ_slot(ORGAN_SLOT_TONGUE) + // No tongue, no tastin' + if(!tongue?.sense_of_taste || HAS_TRAIT(src, TRAIT_AGEUSIA)) + return NONE + return tongue.liked_foodtypes + +/** + * Gets food flags that this mob dislikes + **/ +/mob/living/proc/get_disliked_foodtypes() + return NONE + +/mob/living/carbon/get_disliked_foodtypes() + var/obj/item/organ/internal/tongue/tongue = get_organ_slot(ORGAN_SLOT_TONGUE) + // No tongue, no tastin' + if(!tongue?.sense_of_taste || HAS_TRAIT(src, TRAIT_AGEUSIA)) + return NONE + return tongue.disliked_foodtypes + +/** + * Gets food flags that this mob hates + * Toxic food is the only category that ignores ageusia, KEEP IT LIKE THAT! + **/ +/mob/living/proc/get_toxic_foodtypes() + return TOXIC + +/mob/living/carbon/get_toxic_foodtypes() + var/obj/item/organ/internal/tongue/tongue = get_organ_slot(ORGAN_SLOT_TONGUE) + // No tongue, no tastin' + if(!tongue) + return TOXIC + return tongue.toxic_foodtypes + +/** + * Gets the food reaction a mob would normally have from the given food item, + * assuming that no check_liked callback was used in the edible component. + * + * Does not get called if the owner has ageusia. + **/ +/mob/living/proc/get_food_taste_reaction(obj/item/food, foodtypes) + var/food_taste_reaction + if(foodtypes & get_toxic_foodtypes()) + food_taste_reaction = FOOD_TOXIC + else if(foodtypes & get_disliked_foodtypes()) + food_taste_reaction = FOOD_DISLIKED + else if(foodtypes & get_liked_foodtypes()) + food_taste_reaction = FOOD_LIKED + return food_taste_reaction + +/mob/living/carbon/get_food_taste_reaction(obj/item/food, foodtypes) + var/obj/item/organ/internal/tongue/tongue = get_organ_slot(ORGAN_SLOT_TONGUE) + // No tongue, no tastin' + if(!tongue?.sense_of_taste || HAS_TRAIT(src, TRAIT_AGEUSIA)) + // i hate that i have to do this, but we want to ensure toxic food is still BAD + if(foodtypes & get_toxic_foodtypes()) + return FOOD_TOXIC + return + return tongue.get_food_taste_reaction(food, foodtypes) + #undef DEFAULT_TASTE_SENSITIVITY diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 1c70f7dd637a..ea0fee8f9dfb 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1443,6 +1443,11 @@ stat = new_stat SEND_SIGNAL(src, COMSIG_MOB_STATCHANGE, new_stat, .) +/// Proc used for custom metabolization of reagents, if any +/mob/proc/reagent_check(datum/reagent/chem, seconds_per_tick, times_fired) + SHOULD_CALL_PARENT(TRUE) + return SEND_SIGNAL(src, COMSIG_MOB_REAGENT_CHECK, chem, seconds_per_tick, times_fired) + /mob/vv_edit_var(var_name, var_value) switch(var_name) if(NAMEOF(src, control_object)) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 82fb0783c7fd..6a4382fc0939 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -240,11 +240,6 @@ // Else, return FALSE. return (faker && allow_fake_antags) - -/mob/proc/reagent_check(datum/reagent/R, seconds_per_tick, times_fired) // utilized in the species code - return TRUE - - /** * Fancy notifications for ghosts * diff --git a/code/modules/reagents/reagent_containers/cups/_cup.dm b/code/modules/reagents/reagent_containers/cups/_cup.dm index a51fa5bac242..4aad53d61f20 100644 --- a/code/modules/reagents/reagent_containers/cups/_cup.dm +++ b/code/modules/reagents/reagent_containers/cups/_cup.dm @@ -25,34 +25,37 @@ var/list/types = bitfield_to_list(drink_type, FOOD_FLAGS) . += span_notice("It is [lowertext(english_list(types))].") -/obj/item/reagent_containers/cup/proc/checkLiked(fraction, mob/M) - if(last_check_time + 50 >= world.time) - return - if(!ishuman(M)) - return - var/mob/living/carbon/human/H = M - if(HAS_TRAIT(H, TRAIT_AGEUSIA)) - if(drink_type & H.dna.species.toxic_food) - to_chat(H, span_warning("You don't feel so good...")) - H.adjust_disgust(25 + 30 * fraction) - else - if(drink_type & H.dna.species.toxic_food) - to_chat(H,span_warning("What the hell was that thing?!")) - H.adjust_disgust(25 + 30 * fraction) - H.add_mood_event("toxic_food", /datum/mood_event/disgusting_food) - else if(drink_type & H.dna.species.disliked_food) - to_chat(H,span_notice("That didn't taste very good...")) - H.adjust_disgust(11 + 15 * fraction) - H.add_mood_event("gross_food", /datum/mood_event/gross_food) - else if(drink_type & H.dna.species.liked_food) - to_chat(H,span_notice("I love this taste!")) - H.adjust_disgust(-5 + -2.5 * fraction) - H.add_mood_event("fav_food", /datum/mood_event/favorite_food) - +/** + * Checks if the mob actually liked drinking this cup. + * + * This is a bunch of copypaste from the edible component, consider reworking this to use it! + */ +/obj/item/reagent_containers/cup/proc/checkLiked(fraction, mob/eater) + if(last_check_time + 5 SECONDS > world.time) + return FALSE + if(!ishuman(eater)) + return FALSE + var/mob/living/carbon/human/gourmand = eater + //Bruh this breakfast thing is cringe and shouldve been handled separately from food-types, remove this in the future (Actually, just kill foodtypes in general) if((drink_type & BREAKFAST) && world.time - SSticker.round_start_time < STOP_SERVING_BREAKFAST) - H.add_mood_event("breakfast", /datum/mood_event/breakfast) + gourmand.add_mood_event("breakfast", /datum/mood_event/breakfast) last_check_time = world.time + var/food_taste_reaction = gourmand.get_food_taste_reaction(src, drink_type) + switch(food_taste_reaction) + if(FOOD_TOXIC) + to_chat(gourmand,span_warning("What the hell was that thing?!")) + gourmand.adjust_disgust(25 + 30 * fraction) + gourmand.add_mood_event("toxic_food", /datum/mood_event/disgusting_food) + if(FOOD_DISLIKED) + to_chat(gourmand,span_notice("That didn't taste very good...")) + gourmand.adjust_disgust(11 + 15 * fraction) + gourmand.add_mood_event("gross_food", /datum/mood_event/gross_food) + if(FOOD_LIKED) + to_chat(gourmand,span_notice("I love this taste!")) + gourmand.adjust_disgust(-5 + -2.5 * fraction) + gourmand.add_mood_event("fav_food", /datum/mood_event/favorite_food) + /obj/item/reagent_containers/cup/attack(mob/living/target_mob, mob/living/user, obj/target) if(!canconsume(target_mob, user)) return diff --git a/code/modules/reagents/withdrawal/generic_addictions.dm b/code/modules/reagents/withdrawal/generic_addictions.dm index 9e79ec350fec..8c048e52b0ae 100644 --- a/code/modules/reagents/withdrawal/generic_addictions.dm +++ b/code/modules/reagents/withdrawal/generic_addictions.dm @@ -112,9 +112,12 @@ affected_human.facial_hairstyle = "Beard (Full)" affected_human.update_body_parts() //Only like gross food - affected_human.dna?.species.liked_food = GROSS - affected_human.dna?.species.disliked_food = TOXIC // Toxic food won't kill you, but it doesn't taste good still. - affected_human.dna?.species.toxic_food = ~(GROSS | RAW | GORE | MEAT | BUGS | TOXIC | ALCOHOL) // Monke, you can eat raw rats and whatnot. + var/obj/item/organ/internal/tongue/tongue = affected_carbon.get_organ_slot(ORGAN_SLOT_TONGUE) + if(!tongue) + return + tongue.liked_foodtypes = GROSS + tongue.disliked_foodtypes = TOXIC + tongue.toxic_foodtypes = ~(GROSS | RAW | GORE | MEAT | BUGS | TOXIC | ALCOHOL) /datum/addiction/maintenance_drugs/withdrawal_enters_stage_3(mob/living/carbon/affected_carbon) . = ..() @@ -146,12 +149,15 @@ if(!ishuman(affected_carbon)) return var/mob/living/carbon/human/affected_human = affected_carbon - affected_human.dna?.species.liked_food = initial(affected_human.dna?.species.liked_food) - affected_human.dna?.species.disliked_food = initial(affected_human.dna?.species.disliked_food) - affected_human.dna?.species.toxic_food = initial(affected_human.dna?.species.toxic_food) + //restore tongue's tastes + var/obj/item/organ/internal/tongue/tongue = affected_carbon.get_organ_slot(ORGAN_SLOT_TONGUE) + if(tongue) + tongue.liked_foodtypes = initial(tongue.liked_foodtypes) + tongue.disliked_foodtypes = initial(tongue.disliked_foodtypes) + tongue.toxic_foodtypes = initial(tongue.toxic_foodtypes) REMOVE_TRAIT(affected_human, TRAIT_NIGHT_VISION, "maint_drug_addiction") var/obj/item/organ/internal/eyes/eyes = affected_human.get_organ_by_type(/obj/item/organ/internal/eyes) - eyes.refresh() + eyes?.refresh() ///Makes you a hypochondriac - I'd like to call it hypochondria, but "I could use some hypochondria" doesn't work /datum/addiction/medicine diff --git a/code/modules/research/designs/limbgrower_designs.dm b/code/modules/research/designs/limbgrower_designs.dm index f52621b09c82..916e8bf0467b 100644 --- a/code/modules/research/designs/limbgrower_designs.dm +++ b/code/modules/research/designs/limbgrower_designs.dm @@ -162,7 +162,7 @@ id = "plasmamanliver" build_type = LIMBGROWER reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10, /datum/reagent/toxin/plasma = 20) - build_path = /obj/item/organ/internal/liver/plasmaman + build_path = /obj/item/organ/internal/liver/bone/plasmaman category = list(SPECIES_PLASMAMAN) /datum/design/plasmaman_stomach diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/internal/liver/_liver.dm old mode 100755 new mode 100644 similarity index 87% rename from code/modules/surgery/organs/liver.dm rename to code/modules/surgery/organs/internal/liver/_liver.dm index eb9f78c05823..a30c71bcf8c6 --- a/code/modules/surgery/organs/liver.dm +++ b/code/modules/surgery/organs/internal/liver/_liver.dm @@ -33,6 +33,7 @@ // If the liver handles foods like a clown, it honks like a bike horn // Don't think about it too much. RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_COMEDY_METABOLISM), PROC_REF(on_add_comedy_metabolism)) + RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_COMEDY_METABOLISM), PROC_REF(on_remove_comedy_metabolism)) /* Signal handler for the liver gaining the TRAIT_COMEDY_METABOLISM trait * @@ -50,6 +51,35 @@ // Would that make the clown more or less likely to honk it AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 50, falloff_exponent = 20) +/* Signal handler for the liver losing the TRAIT_COMEDY_METABOLISM trait + * + * Basically just removes squeak component + */ +/obj/item/organ/internal/liver/proc/on_remove_comedy_metabolism() + SIGNAL_HANDLER + + qdel(GetComponent(/datum/component/squeak)) + +/// Registers COMSIG_MOB_REAGENT_CHECK from owner +/obj/item/organ/internal/liver/on_insert(mob/living/carbon/organ_owner, special) + . = ..() + RegisterSignal(organ_owner, COMSIG_SPECIES_HANDLE_CHEMICAL, PROC_REF(handle_chemical)) + +/// Unregisters COMSIG_MOB_REAGENT_CHECK from owner +/obj/item/organ/internal/liver/on_remove(mob/living/carbon/organ_owner, special) + . = ..() + UnregisterSignal(organ_owner, COMSIG_SPECIES_HANDLE_CHEMICAL) + +/** + * This proc can be overriden by liver subtypes so they can handle certain chemicals in special ways. + * Return null to continue running the normal on_mob_life() for that reagent. + * Return COMSIG_MOB_STOP_REAGENT_CHECK to not run the normal metabolism effects. + * + * NOTE: If you return COMSIG_MOB_STOP_REAGENT_CHECK, that reagent will not be removed like normal! You must handle it manually. + **/ +/obj/item/organ/internal/liver/proc/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) + SIGNAL_HANDLER + /obj/item/organ/internal/liver/examine(mob/user) . = ..() @@ -91,13 +121,15 @@ #define HAS_PAINFUL_TOXIN 2 /obj/item/organ/internal/liver/on_life(seconds_per_tick, times_fired) - var/mob/living/carbon/liver_owner = owner . = ..() //perform general on_life() + var/mob/living/carbon/liver_owner = owner if(!istype(liver_owner)) return - if(organ_flags & ORGAN_FAILING || HAS_TRAIT(liver_owner, TRAIT_NOMETABOLISM)) //If your liver is failing or you lack a metabolism then we use the liverless version of metabolize - liver_owner.reagents.metabolize(liver_owner, seconds_per_tick, times_fired, can_overdose=TRUE, liverless=TRUE) + //If your liver is failing, then we use the liverless version of metabolize + //We don't check for TRAIT_NOMETABOLISM here because we do want a functional liver if somehow we have one inserted + if(organ_flags & ORGAN_FAILING) + liver_owner.reagents.metabolize(liver_owner, seconds_per_tick, times_fired, can_overdose = TRUE, liverless = TRUE) return var/obj/belly = liver_owner.get_organ_slot(ORGAN_SLOT_STOMACH) @@ -201,12 +233,6 @@ /obj/item/organ/internal/liver/get_availability(datum/species/owner_species, mob/living/owner_mob) return owner_species.mutantliver -/obj/item/organ/internal/liver/plasmaman - name = "reagent processing crystal" - icon_state = "liver-p" - desc = "A large crystal that is somehow capable of metabolizing chemicals, these are found in plasmamen." - status = ORGAN_MINERAL - // alien livers can ignore up to 15u of toxins, but they take x3 liver damage /obj/item/organ/internal/liver/alien name = "alien liver" // doesnt matter for actual aliens because they dont take toxin damage diff --git a/code/modules/surgery/organs/internal/liver/liver_plasmamen.dm b/code/modules/surgery/organs/internal/liver/liver_plasmamen.dm new file mode 100644 index 000000000000..34dbec6ab612 --- /dev/null +++ b/code/modules/surgery/organs/internal/liver/liver_plasmamen.dm @@ -0,0 +1,25 @@ +/** + * Plasmaman liver + * Makes plasma and hot ice heal wounds, also makes gunpowder a hallucinogen. + **/ +/obj/item/organ/internal/liver/bone/plasmaman + name = "reagent processing crystal" + desc = "A large crystal that is somehow capable of metabolizing chemicals, these are found in plasmamen." + icon_state = "liver-p" + status = ORGAN_MINERAL + +/obj/item/organ/internal/liver/bone/plasmaman/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) + . = ..() + //parent returned COMSIG_MOB_STOP_REAGENT_CHECK or we are failing + if(. || (organ_flags & ORGAN_FAILING)) + return + // plasmamen use plasma to reform their bones or whatever + if(istype(chem, /datum/reagent/toxin/plasma) || istype(chem, /datum/reagent/toxin/hot_ice)) + for(var/datum/wound/iter_wound as anything in organ_owner.all_wounds) + iter_wound.on_xadone(4 * REM * seconds_per_tick) + return // Do normal metabolism + if(istype(chem, /datum/reagent/gunpowder)) + organ_owner.set_timed_status_effect(15 SECONDS * seconds_per_tick, /datum/status_effect/drugginess) + if(organ_owner.get_timed_status_effect_duration(/datum/status_effect/hallucination) / 10 < chem.volume) + organ_owner.adjust_hallucinations(2.5 SECONDS * seconds_per_tick) + return // Do normal metabolism diff --git a/code/modules/surgery/organs/internal/liver/liver_skeleton.dm b/code/modules/surgery/organs/internal/liver/liver_skeleton.dm new file mode 100644 index 000000000000..925eade7cbc1 --- /dev/null +++ b/code/modules/surgery/organs/internal/liver/liver_skeleton.dm @@ -0,0 +1,49 @@ +/** + * Bone liver + * Gives the owner liverless metabolism, makes them vulnerable to bone hurting juice and + * makes milk heal them through meme magic. + **/ +/obj/item/organ/internal/liver/bone + name = "mass of bones" + desc = "You have no idea what this strange ball of bones does." + icon_state = "liver-bone" + organ_traits = list(TRAIT_NOMETABOLISM) + +/obj/item/organ/internal/liver/bone/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) + . = ..() + //parent returned COMSIG_MOB_STOP_REAGENT_CHECK or we are failing + if(. || (organ_flags & ORGAN_FAILING)) + return + if(istype(chem, /datum/reagent/toxin/bonehurtingjuice)) + organ_owner.stamina?.adjust(7.5 * REM * seconds_per_tick, 0) + organ_owner.adjustBruteLoss(0.5 * REM * seconds_per_tick, 0) + if(SPT_PROB(10, seconds_per_tick)) + switch(rand(1, 3)) + if(1) + INVOKE_ASYNC(organ_owner, TYPE_PROC_REF(/atom/movable, say), pick("oof.", "ouch.", "my bones.", "oof ouch.", "oof ouch my bones."), forced = chem.type) + if(2) + organ_owner.manual_emote(pick("oofs silently.", "looks like [organ_owner.p_their()] bones hurt.", "grimaces, as though [organ_owner.p_their()] bones hurt.")) + if(3) + to_chat(organ_owner, span_warning("Your bones hurt!")) + if(chem.overdosed) + if(SPT_PROB(2, seconds_per_tick)) //big oof + var/selected_part = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) //God help you if the same limb gets picked twice quickly... + var/obj/item/bodypart/bodypart = organ_owner.get_bodypart(selected_part) //We're so sorry skeletons, you're so misunderstood + if(bodypart) + playsound(organ_owner, SFX_DESECRATION, 50, vary = TRUE) //You just want to socialize + organ_owner.visible_message(span_warning("[organ_owner] rattles loudly and flails around!!"), span_danger("Your bones hurt so much that your missing muscles spasm!!")) + INVOKE_ASYNC(organ_owner, TYPE_PROC_REF(/atom/movable, say), "OOF!!", forced = chem.type) + bodypart.receive_damage(brute = 200) //But I don't think we should + else + to_chat(organ_owner, span_warning("Your missing [parse_zone(selected_part)] aches from wherever you left it.")) + INVOKE_ASYNC(organ_owner, TYPE_PROC_REF(/mob, emote), "sigh") + organ_owner.reagents.remove_reagent(chem.type, chem.metabolization_rate * seconds_per_tick) + return COMSIG_MOB_STOP_REAGENT_CHECK // Stop metabolism + if(chem.type == /datum/reagent/consumable/milk) + if(chem.volume > 50) + organ_owner.reagents.remove_reagent(chem.type, (chem.volume - 50)) + to_chat(organ_owner, span_warning("The excess milk is dripping off your bones!")) + organ_owner.heal_bodypart_damage(2.5 * REM * seconds_per_tick) + for(var/datum/wound/iter_wound as anything in organ_owner.all_wounds) + iter_wound.on_xadone(1 * REM * seconds_per_tick) + return // Do normal metabolism diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm similarity index 85% rename from code/modules/surgery/organs/tongue.dm rename to code/modules/surgery/organs/internal/tongue/_tongue.dm index 9066ea29d58e..df2a931b2a55 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -34,6 +34,12 @@ /// Determines how "sensitive" this tongue is to tasting things, lower is more sensitive. /// See [/mob/living/proc/get_taste_sensitivity]. var/taste_sensitivity = 15 + /// Foodtypes this tongue likes + var/liked_foodtypes = JUNKFOOD | FRIED //human tastes are default + /// Foodtypes this tongue dislikes + var/disliked_foodtypes = GROSS | RAW | CLOTH | BUGS | GORE //human tastes are default + /// Foodtypes this tongue HATES + var/toxic_foodtypes = TOXIC //human tastes are default /// Whether this tongue modifies speech via signal var/modifies_speech = FALSE @@ -45,6 +51,16 @@ // this results in tongues with identical possible languages sharing a cached list instance languages_possible = string_list(get_possible_languages()) +/obj/item/organ/internal/tongue/examine(mob/user) + . = ..() + if(HAS_TRAIT(user, TRAIT_ENTRAILS_READER) || (user.mind && HAS_TRAIT(user.mind, TRAIT_ENTRAILS_READER)) || isobserver(user)) + if(liked_foodtypes) + . += span_info("This tongue has an affinity the taste of [english_list(bitfield_to_list(liked_foodtypes), FOOD_FLAGS_IC)].") + if(disliked_foodtypes) + . += span_info("This tongue has an aversion for taste of [english_list(bitfield_to_list(disliked_foodtypes), FOOD_FLAGS_IC)].") + if(toxic_foodtypes) + . += span_info("This tongue's physiology makes [english_list(bitfield_to_list(toxic_foodtypes), FOOD_FLAGS_IC)] toxic.") + /** * Used in setting up the "languages possible" list. * @@ -68,14 +84,29 @@ /obj/item/organ/internal/tongue/proc/modify_speech(datum/source, list/speech_args) return speech_args[SPEECH_MESSAGE] +/** + * Gets the food reaction a tongue would have from the food item, + * assuming that no check_liked callback was used in the edible component. + * + * Can be overriden by subtypes for more complex behavior. + * Does not get called if the owner has ageusia. + **/ +/obj/item/organ/internal/tongue/proc/get_food_taste_reaction(obj/item/food, foodtypes = NONE) + var/food_taste_reaction + if(foodtypes & toxic_foodtypes) + food_taste_reaction = FOOD_TOXIC + else if(foodtypes & disliked_foodtypes) + food_taste_reaction = FOOD_DISLIKED + else if(foodtypes & liked_foodtypes) + food_taste_reaction = FOOD_LIKED + return food_taste_reaction + /obj/item/organ/internal/tongue/Insert(mob/living/carbon/tongue_owner, special = FALSE, drop_if_replaced = TRUE) . = ..() if(!.) return - ADD_TRAIT(tongue_owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE) - if (modifies_speech) + if(modifies_speech) RegisterSignal(tongue_owner, COMSIG_MOB_SAY, PROC_REF(handle_speech)) - if(!(organ_flags & ORGAN_FAILING)) ADD_TRAIT(tongue_owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE) /* This could be slightly simpler, by making the removal of the @@ -84,18 +115,35 @@ * ageusia from having a non-tasting tongue. */ REMOVE_TRAIT(tongue_owner, TRAIT_AGEUSIA, NO_TONGUE_TRAIT) - if(!sense_of_taste) + if(!sense_of_taste || (organ_flags & ORGAN_FAILING)) ADD_TRAIT(tongue_owner, TRAIT_AGEUSIA, ORGAN_TRAIT) /obj/item/organ/internal/tongue/Remove(mob/living/carbon/tongue_owner, special = FALSE) . = ..() - REMOVE_TRAIT(tongue_owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE) temp_say_mod = "" UnregisterSignal(tongue_owner, COMSIG_MOB_SAY) + REMOVE_TRAIT(tongue_owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE) REMOVE_TRAIT(tongue_owner, TRAIT_AGEUSIA, ORGAN_TRAIT) // Carbons by default start with NO_TONGUE_TRAIT caused TRAIT_AGEUSIA ADD_TRAIT(tongue_owner, TRAIT_AGEUSIA, NO_TONGUE_TRAIT) + +/obj/item/organ/internal/tongue/apply_organ_damage(damage_amount, maximum, required_organtype) + . = ..() + if(!owner) + return + //tongues can't taste food when they are failing + if(sense_of_taste) + //tongues can't taste food when they are failing + if(organ_flags & ORGAN_FAILING) + ADD_TRAIT(owner, TRAIT_AGEUSIA, ORGAN_TRAIT) + else + REMOVE_TRAIT(owner, TRAIT_AGEUSIA, ORGAN_TRAIT) + if(organ_flags & ORGAN_FAILING) + ADD_TRAIT(owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE) + else + REMOVE_TRAIT(owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE) + /obj/item/organ/internal/tongue/could_speak_language(datum/language/language_path) return (language_path in languages_possible) @@ -110,6 +158,8 @@ taste_sensitivity = 10 // combined nose + tongue, extra sensitive modifies_speech = TRUE languages_native = list(/datum/language/draconic, /datum/language/ashtongue) + liked_foodtypes = GORE | MEAT | SEAFOOD | NUTS | BUGS + disliked_foodtypes = GRAIN | DAIRY | CLOTH | GROSS //MONKESTATION EDIT START @@ -281,6 +331,8 @@ say_mod = "moans" modifies_speech = TRUE taste_sensitivity = 32 + liked_foodtypes = GROSS | MEAT | RAW | GORE + disliked_foodtypes = NONE // List of english words that translate to zombie phrases GLOBAL_LIST_INIT(english_to_zombie, list()) @@ -373,6 +425,8 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) attack_verb_simple = list("bite", "chatter", "chomp", "enamel", "bone") sense_of_taste = FALSE modifies_speech = TRUE + liked_foodtypes = GROSS | MEAT | RAW | GORE | DAIRY //skeletons eat spooky shit... and dairy, of course + disliked_foodtypes = NONE var/chattering = FALSE var/phomeme_type = "sans" var/list/phomeme_types = list("sans", "papyrus") @@ -399,6 +453,8 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) desc = "Like animated skeletons, Plasmamen vibrate their teeth in order to produce speech." icon_state = "tongueplasma" modifies_speech = FALSE + liked_foodtypes = VEGETABLES + disliked_foodtypes = FRUIT | CLOTH /obj/item/organ/internal/tongue/robot name = "robotic voicebox" @@ -440,9 +496,13 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) icon_state = "electrotongue" say_mod = "crackles" taste_sensitivity = 10 // ethereal tongues function (very loosely) like a gas spectrometer: vaporising a small amount of the food and allowing it to pass to the nose, resulting in more sensitive taste + liked_foodtypes = NONE //no food is particularly liked by ethereals + disliked_foodtypes = GROSS + toxic_foodtypes = NONE //no food is particularly toxic to etherealsz attack_verb_continuous = list("shocks", "jolts", "zaps") attack_verb_simple = list("shock", "jolt", "zap") + // Ethereal tongues can speak all default + voltaic /obj/item/organ/internal/tongue/ethereal/get_possible_languages() return ..() + /datum/language/voltaic @@ -451,6 +511,8 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) name = "felinid tongue" desc = "A fleshy muscle mostly used for meowing." say_mod = "meows" + liked_foodtypes = SEAFOOD | ORANGES | BUGS | GORE + disliked_foodtypes = GROSS | CLOTH | RAW /obj/item/organ/internal/tongue/bananium name = "bananium tongue" @@ -465,16 +527,30 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) name = "jelly tongue" desc = "Ah... That's not the sound I expected it to make. Sounds like a Space Autumn Bird." say_mod = "chirps" + liked_foodtypes = MEAT | BUGS + disliked_foodtypes = GROSS + toxic_foodtypes = NONE + +/obj/item/organ/internal/tongue/jelly/get_food_taste_reaction(obj/item/food, foodtypes = NONE) + // a silver slime created this? what a delicacy! + if(HAS_TRAIT(food, TRAIT_FOOD_SILVER)) + return FOOD_LIKED + return ..() /obj/item/organ/internal/tongue/monkey name = "primitive tongue" desc = "For aggressively chimpering. And consuming bananas." say_mod = "chimpers" + liked_foodtypes = MEAT | FRUIT | BUGS + disliked_foodtypes = CLOTH /obj/item/organ/internal/tongue/moth name = "moth tongue" desc = "Moths don't have tongues. Someone get god on the phone, tell them I'm not happy." say_mod = "flutters" + liked_foodtypes = VEGETABLES | DAIRY | CLOTH + disliked_foodtypes = FRUIT | GROSS | BUGS | GORE + toxic_foodtypes = MEAT | RAW | SEAFOOD /obj/item/organ/internal/tongue/zombie name = "rotting tongue" @@ -484,7 +560,13 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) /obj/item/organ/internal/tongue/mush name = "mush-tongue-room" desc = "You poof with this. Got it?" - say_mod = "poofs" - icon = 'icons/obj/hydroponics/seeds.dmi' icon_state = "mycelium-angel" + say_mod = "poofs" + +/obj/item/organ/internal/tongue/pod + name = "pod tongue" + desc = "A plant-like organ used for speaking and eating." + say_mod = "whistles" + liked_foodtypes = VEGETABLES | FRUIT | GRAIN + disliked_foodtypes = GORE | MEAT | DAIRY | SEAFOOD | BUGS diff --git a/monkestation/code/modules/antagonists/clock_cult/mobs/eminence.dm b/monkestation/code/modules/antagonists/clock_cult/mobs/eminence.dm index 97621c5ea2c1..2623a847aabd 100644 --- a/monkestation/code/modules/antagonists/clock_cult/mobs/eminence.dm +++ b/monkestation/code/modules/antagonists/clock_cult/mobs/eminence.dm @@ -117,7 +117,7 @@ GLOBAL_DATUM(current_eminence, /mob/living/eminence) //set to the current eminen return FALSE . = ..() -/mob/living/eminence/gib(no_brain, no_organs, no_bodyparts) +/mob/living/eminence/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) return //eminence_act() stuff, might be a better way to do this diff --git a/monkestation/code/modules/botany/species/apid/species.dm b/monkestation/code/modules/botany/species/apid/species.dm index cd67ebf48993..0bdefef537be 100644 --- a/monkestation/code/modules/botany/species/apid/species.dm +++ b/monkestation/code/modules/botany/species/apid/species.dm @@ -50,13 +50,11 @@ inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG meat = /obj/item/food/meat/slab/human/mutant/apid - liked_food = VEGETABLES | MEAT | FRUIT - disliked_food = GROSS | BUGS | GORE - toxic_food = RAW | SEAFOOD changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT species_language_holder = /datum/language_holder/apid + mutanttongue = /obj/item/organ/internal/tongue/apid bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/apid, BODY_ZONE_CHEST = /obj/item/bodypart/chest/apid, @@ -148,3 +146,10 @@ #undef ui_honeydisplay #undef FORMAT_HONEY_CHARGES_TEXT + +/obj/item/organ/internal/tongue/apid + name = "apid tongue" + + liked_foodtypes = VEGETABLES | MEAT | FRUIT + disliked_foodtypes = GROSS | BUGS | GORE + toxic_foodtypes = RAW | SEAFOOD diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm index e8a03a1fb2e8..f2040f395aa4 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm @@ -12,8 +12,6 @@ /obj/item/organ/external/arachnid_appendages = "long", /obj/item/organ/external/chelicerae = "basic") meat = /obj/item/food/meat/slab/spider - disliked_food = NONE // Okay listen, i don't actually know what irl spiders don't like to eat and i'm pretty tired of looking for answers. - liked_food = GORE | MEAT | BUGS | GROSS species_language_holder = /datum/language_holder/fly mutanttongue = /obj/item/organ/internal/tongue/arachnid mutanteyes = /obj/item/organ/internal/eyes/night_vision/arachnid @@ -28,7 +26,7 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/arachnid, ) -/datum/species/arachnid/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) +/datum/species/arachnid/handle_chemical(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) if(chem.type == /datum/reagent/toxin/pestkiller) H.adjustToxLoss(3 * REM * seconds_per_tick) H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm index 99a7ab726aff..52cc32ebbec4 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm @@ -26,7 +26,6 @@ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_cookie = /obj/item/food/energybar species_language_holder = /datum/language_holder/ethereal - toxic_food = NONE // Body temperature for ethereals is much higher then humans as they like hotter environments bodytemp_normal = (BODYTEMP_NORMAL + 50) bodytemp_heat_damage_limit = FIRE_MINIMUM_TEMPERATURE_TO_SPREAD // about 150C diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm index bf9255605321..88dd68979bc3 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm @@ -25,8 +25,6 @@ coldmod = 1.5 //Same as lizard people meat = /obj/item/food/meat/slab/human/mutant/plant exotic_bloodtype = /datum/blood_type/water - // disliked_food = VEGETABLES | FRUIT | GRAIN - liked_food = MEAT | BUGS | GORE changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_language_holder = /datum/language_holder/plant @@ -38,12 +36,13 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/floran, BODY_ZONE_CHEST = /obj/item/bodypart/chest/floran, ) - mutanttongue = /obj/item/organ/internal/tongue/lizard + mutanttongue = /obj/item/organ/internal/tongue/pod mutanteyes = /obj/item/organ/internal/eyes/floran ass_image = 'icons/ass/asspodperson.png' /datum/species/floran/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) + . = ..() if(H.stat == DEAD) return @@ -56,7 +55,7 @@ H.adjustToxLoss(-0.25 * seconds_per_tick) H.adjustOxyLoss(-0.25 * seconds_per_tick) -/datum/species/floran/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) +/datum/species/floran/handle_chemical(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) if(chem.type == /datum/reagent/toxin/plantbgone) H.adjustToxLoss(3 * REM * seconds_per_tick) H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm index 9615b19232b7..d1865f5250b0 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm @@ -19,8 +19,7 @@ /obj/item/organ/external/goblin_ears = "long", ) meat = /obj/item/food/meat/steak - disliked_food = VEGETABLES - liked_food = GORE | MEAT | GROSS + mutanttongue = /obj/item/organ/internal/tongue/goblin species_language_holder = /datum/language_holder/goblin maxhealthmod = 0.75 stunmod = 1.2 @@ -162,3 +161,8 @@ icon_greyscale = 'monkestation/icons/mob/species/goblin/bodyparts.dmi' limb_id = SPECIES_GOBLIN speed_modifier = -0.125 + +/obj/item/organ/internal/tongue/goblin + name = "goblin tongue" + disliked_foodtypes = VEGETABLES + liked_foodtypes = GORE | MEAT | GROSS diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm index 883c4f353c3c..f4518359d3cb 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm @@ -24,8 +24,6 @@ changesource_flags = MIRROR_BADMIN | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN meat = /obj/item/food/meat/slab/monkey skinned_type = /obj/item/stack/sheet/animalhide/monkey - disliked_food = GROSS - liked_food = FRUIT | MEAT uses_fur = TRUE //deathsound = 'monkestation/sound/voice/simian/deathsound.ogg' species_language_holder = /datum/language_holder/monkey diff --git a/monkestation/code/modules/ranching/satyr/species.dm b/monkestation/code/modules/ranching/satyr/species.dm index e87e4d401e1f..22601b7ae999 100644 --- a/monkestation/code/modules/ranching/satyr/species.dm +++ b/monkestation/code/modules/ranching/satyr/species.dm @@ -27,8 +27,7 @@ /obj/item/organ/external/satyr_horns = "back", ) meat = /obj/item/food/meat/steak - liked_food = GROSS | VEGETABLES | FRUIT - disliked_food = MEAT | DAIRY + mutanttongue = /obj/item/organ/internal/tongue/satyr maxhealthmod = 0.8 stunmod = 1.2 payday_modifier = 1 @@ -96,3 +95,9 @@ if(headbutt) headbutt.Remove(C) qdel(headbutt) + +/obj/item/organ/internal/tongue/satyr + name = "satyr tongue" + + liked_foodtypes = GROSS | VEGETABLES | FRUIT + disliked_foodtypes = MEAT | DAIRY diff --git a/monkestation/code/modules/smithing/oozelings/species.dm b/monkestation/code/modules/smithing/oozelings/species.dm index 9db355f5ae15..0af2fbb5e4b3 100644 --- a/monkestation/code/modules/smithing/oozelings/species.dm +++ b/monkestation/code/modules/smithing/oozelings/species.dm @@ -207,7 +207,7 @@ /// CHEMICAL HANDLING /// Here's where slimes heal off plasma and where they hate drinking water. -/datum/species/oozeling/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/slime, seconds_per_tick, times_fired) +/datum/species/oozeling/handle_chemical(datum/reagent/chem, mob/living/carbon/human/slime, seconds_per_tick, times_fired) // slimes use plasma to fix wounds, and if they have enough blood, organs var/static/list/organs_we_mend = list( ORGAN_SLOT_BRAIN, diff --git a/monkestation/code/modules/surgery/organs/internal/tongue.dm b/monkestation/code/modules/surgery/organs/internal/tongue.dm index 684fd10d6ddb..434b75d41a8f 100644 --- a/monkestation/code/modules/surgery/organs/internal/tongue.dm +++ b/monkestation/code/modules/surgery/organs/internal/tongue.dm @@ -16,6 +16,8 @@ desc = "The tongue of an Arachnid. Mostly used for lying." say_mod = "chitters" modifies_speech = TRUE + disliked_foodtypes = NONE // Okay listen, i don't actually know what irl spiders don't like to eat and i'm pretty tired of looking for answers. + liked_foodtypes = GORE | MEAT | BUGS | GROSS /obj/item/organ/internal/tongue/arachnid/modify_speech(datum/source, list/speech_args) //This is flypeople speech var/static/regex/fly_buzz = new("z+", "g") diff --git a/monkestation/code/modules/the_bird_inside_of_me/species.dm b/monkestation/code/modules/the_bird_inside_of_me/species.dm index 0e3dd51e0f4e..60caede0983a 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/species.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/species.dm @@ -24,7 +24,6 @@ GLOBAL_LIST_EMPTY(tails_list_avian) ) inherent_traits = list( - TRAIT_NON_IMPORTANT_SHOE_BLOCK, TRAIT_LIGHT_DRINKER, TRAIT_TACKLING_WINGED_ATTACKER, TRAIT_USES_SKINTONES, diff --git a/monkestation/code/modules/the_wolf_inside_of_me/organs.dm b/monkestation/code/modules/the_wolf_inside_of_me/organs.dm index 0f98a3d84e5f..7a844a52e742 100644 --- a/monkestation/code/modules/the_wolf_inside_of_me/organs.dm +++ b/monkestation/code/modules/the_wolf_inside_of_me/organs.dm @@ -38,16 +38,16 @@ ///Var for burn healing via blood var/blood_burn_healing = 2.5 -/* + /obj/item/organ/internal/liver/werewolf/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) . = ..() - // parent returned COMSIG_MOB_STOP_REAGENT_CHECK or we are failing - //if((. & COMSIG_MOB_STOP_REAGENT_CHECK) || (organ_flags & ORGAN_FAILING)) - //return + //parent returned COMSIG_MOB_STOP_REAGENT_CHECK or we are failing + if((. & COMSIG_MOB_STOP_REAGENT_CHECK) || (organ_flags & ORGAN_FAILING)) + return if(istype(chem, /datum/reagent/silver)) - organ_owner.stamina?.adjust(7.5 * REM * seconds_per_tick, updating_stamina = TRUE) + organ_owner.stamina?.adjust(7.5 * REM * seconds_per_tick) organ_owner.adjustFireLoss(5.0 * REM * seconds_per_tick, updating_health = TRUE) -*/ + /obj/item/organ/internal/tongue/werewolf name = "wolf tongue" diff --git a/tgstation.dme b/tgstation.dme index 372e0ef007d7..6e0c7e9b7e71 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -5482,10 +5482,8 @@ #include "code\modules\surgery\organs\eyes.dm" #include "code\modules\surgery\organs\heart.dm" #include "code\modules\surgery\organs\helpers.dm" -#include "code\modules\surgery\organs\liver.dm" #include "code\modules\surgery\organs\lungs.dm" #include "code\modules\surgery\organs\organ_internal.dm" -#include "code\modules\surgery\organs\tongue.dm" #include "code\modules\surgery\organs\vocal_cords.dm" #include "code\modules\surgery\organs\external\_external_organs.dm" #include "code\modules\surgery\organs\external\restyling.dm" @@ -5494,6 +5492,10 @@ #include "code\modules\surgery\organs\external\wings\functional_wings.dm" #include "code\modules\surgery\organs\external\wings\moth_wings.dm" #include "code\modules\surgery\organs\external\wings\wings.dm" +#include "code\modules\surgery\organs\internal\liver\_liver.dm" +#include "code\modules\surgery\organs\internal\liver\liver_plasmamen.dm" +#include "code\modules\surgery\organs\internal\liver\liver_skeleton.dm" +#include "code\modules\surgery\organs\internal\tongue\_tongue.dm" #include "code\modules\surgery\organs\stomach\_stomach.dm" #include "code\modules\surgery\organs\stomach\stomach_ethereal.dm" #include "code\modules\tgchat\message.dm" From 60f2bc697d481a70a8c5ba3b88dc18a74da9e461 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 00:03:08 -0700 Subject: [PATCH 070/158] ethereal charge back to stomach --- .../organs/stomach/stomach_ethereal.dm | 159 ++++++++++-------- .../carbon/human/species_type/ethereal.dm | 95 ----------- .../code/modules/ranching/satyr/bodyparts.dm | 2 + .../modules/ranching/satyr/external_organs.dm | 12 ++ .../code/modules/ranching/satyr/species.dm | 48 +++--- 5 files changed, 128 insertions(+), 188 deletions(-) diff --git a/code/modules/surgery/organs/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/stomach/stomach_ethereal.dm index fcf1cd4c5dd6..9f29c370f9d7 100644 --- a/code/modules/surgery/organs/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/stomach/stomach_ethereal.dm @@ -9,24 +9,25 @@ ///used to keep ethereals from spam draining power sources var/drain_time = 0 -/* //Monkestation Removal /obj/item/organ/internal/stomach/ethereal/on_life(seconds_per_tick, times_fired) . = ..() adjust_charge(-ETHEREAL_CHARGE_FACTOR * seconds_per_tick) handle_charge(owner, seconds_per_tick, times_fired) -*/ + /obj/item/organ/internal/stomach/ethereal/on_insert(mob/living/carbon/stomach_owner) . = ..() RegisterSignal(stomach_owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, PROC_REF(charge)) RegisterSignal(stomach_owner, COMSIG_LIVING_ELECTROCUTE_ACT, PROC_REF(on_electrocute)) RegisterSignal(stomach_owner, COMSIG_LIVING_HOMEOSTASIS, PROC_REF(handle_temp)) + RegisterSignal(stomach_owner, COMSIG_HUMAN_ON_HANDLE_BLOOD, PROC_REF(blood)) /obj/item/organ/internal/stomach/ethereal/on_remove(mob/living/carbon/stomach_owner) . = ..() UnregisterSignal(stomach_owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT) UnregisterSignal(stomach_owner, COMSIG_LIVING_ELECTROCUTE_ACT) UnregisterSignal(stomach_owner, COMSIG_LIVING_HOMEOSTASIS) + UnregisterSignal(stomach_owner, COMSIG_HUMAN_ON_HANDLE_BLOOD) stomach_owner.clear_mood_event("charge") stomach_owner.clear_alert(ALERT_ETHEREAL_CHARGE) stomach_owner.clear_alert(ALERT_ETHEREAL_OVERCHARGE) @@ -44,6 +45,19 @@ adjust_charge(-1 * ETHEREAL_CHARGE_FACTOR * abs(natural_change) * seconds_per_tick) return HOMEOSTASIS_NO_HUNGER +/obj/item/organ/internal/stomach/ethereal/proc/blood(mob/living/carbon/human/ethereal, seconds_per_tick, times_fired) + SIGNAL_HANDLER + + if(ethereal.stat == DEAD) + return NONE + + . = HANDLE_BLOOD_NO_NUTRITION_DRAIN|HANDLE_BLOOD_NO_EFFECTS + + INVOKE_ASYNC(src, PROC_REF(adjust_charge),-ETHEREAL_BLOOD_CHARGE_FACTOR * seconds_per_tick, TRUE) + INVOKE_ASYNC(src, PROC_REF(handle_charge), ethereal, seconds_per_tick, times_fired) + + return . + /obj/item/organ/internal/stomach/ethereal/proc/charge(datum/source, amount, repairs) SIGNAL_HANDLER if(!ishuman(owner)) @@ -66,77 +80,86 @@ adjust_charge(shock_damage * siemens_coeff * 2) to_chat(owner, span_notice("You absorb some of the shock into your body!")) -/obj/item/organ/internal/stomach/ethereal/proc/adjust_charge(amount) +/obj/item/organ/internal/stomach/ethereal/proc/adjust_charge(amount, passive = FALSE) //crystal_charge = clamp(crystal_charge + amount, ETHEREAL_CHARGE_NONE, ETHEREAL_CHARGE_DANGEROUS) Monkestation Removal if(ishuman(owner)) - var/mob/living/carbon/human/human = owner - if(istype(human.dna.species, /datum/species/ethereal)) - var/datum/species/ethereal/species = human.dna.species - var/amount_adjusted = (BLOOD_VOLUME_NORMAL * amount)/ETHEREAL_CHARGE_FULL - species.adjust_charge(human, amount_adjusted, FALSE) - -/obj/item/organ/internal/stomach/ethereal/proc/handle_charge(mob/living/carbon/carbon, seconds_per_tick, times_fired) - switch(crystal_charge) - if(-INFINITY to ETHEREAL_CHARGE_NONE) - carbon.add_mood_event("charge", /datum/mood_event/decharged) - carbon.clear_alert("ethereal_overcharge") - carbon.throw_alert(ALERT_ETHEREAL_CHARGE, /atom/movable/screen/alert/emptycell/ethereal) - if(carbon.health > 50) - carbon.apply_damage(0.65, BURN, null, null, carbon) - if(ETHEREAL_CHARGE_NONE to ETHEREAL_CHARGE_LOWPOWER) - carbon.clear_alert("ethereal_overcharge") - carbon.add_mood_event("charge", /datum/mood_event/decharged) - carbon.throw_alert(ALERT_ETHEREAL_CHARGE, /atom/movable/screen/alert/lowcell/ethereal, 3) - if(carbon.health > 10.5) - carbon.apply_damage(0.325 * seconds_per_tick, TOX, null, null, carbon) - if(ETHEREAL_CHARGE_LOWPOWER to ETHEREAL_CHARGE_NORMAL) - carbon.clear_alert("ethereal_overcharge") - carbon.add_mood_event("charge", /datum/mood_event/lowpower) - carbon.throw_alert(ALERT_ETHEREAL_CHARGE, /atom/movable/screen/alert/lowcell/ethereal, 2) - carbon.blood_volume = min(carbon.blood_volume + (BLOOD_REGEN_FACTOR * 0.1 * seconds_per_tick), BLOOD_VOLUME_NORMAL) //worse than a starving human - if(ETHEREAL_CHARGE_ALMOSTFULL to ETHEREAL_CHARGE_FULL) - carbon.clear_alert("ethereal_overcharge") - carbon.clear_alert("ethereal_charge") - carbon.add_mood_event("charge", /datum/mood_event/charged) - carbon.blood_volume = min(carbon.blood_volume + (BLOOD_REGEN_FACTOR * 0.9 * seconds_per_tick), BLOOD_VOLUME_NORMAL) //slightly worse than a human (optimal nutrition+satiety gives 1.25) - if(ETHEREAL_CHARGE_FULL to ETHEREAL_CHARGE_OVERLOAD) - carbon.clear_alert("ethereal_charge") - carbon.add_mood_event("charge", /datum/mood_event/overcharged) - carbon.throw_alert(ALERT_ETHEREAL_OVERCHARGE, /atom/movable/screen/alert/ethereal_overcharge, 1) - carbon.apply_damage(0.2, TOX, null, null, carbon) - carbon.blood_volume = min(carbon.blood_volume + (BLOOD_REGEN_FACTOR * 1.6 * seconds_per_tick), BLOOD_VOLUME_NORMAL) //slightly better than a human, at the cost of toxic damage - if(ETHEREAL_CHARGE_OVERLOAD to ETHEREAL_CHARGE_DANGEROUS) - carbon.clear_alert("ethereal_charge") - carbon.add_mood_event("charge", /datum/mood_event/supercharged) - carbon.throw_alert(ALERT_ETHEREAL_OVERCHARGE, /atom/movable/screen/alert/ethereal_overcharge, 2) - carbon.apply_damage(0.325 * seconds_per_tick, TOX, null, null, carbon) - carbon.blood_volume = min(carbon.blood_volume + (BLOOD_REGEN_FACTOR * 2.6 * seconds_per_tick), BLOOD_VOLUME_NORMAL) //significantly better than a human, at the cost of high toxin damage and unsustainability due to discharge + var/mob/living/carbon/human/ethereal = owner + var/amount_adjusted = (BLOOD_VOLUME_NORMAL * amount)/ETHEREAL_CHARGE_FULL + if(passive) + if(ethereal.blood_volume < ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE) //Do not apply the clamp if its below the passive reduction level(no infinite blood sorry) + return + if(ethereal.blood_volume + amount_adjusted < ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE+1) + ethereal.blood_volume = ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE+1 //bottom them off here if the end result would be less than the stopping point. + ethereal.blood_volume = clamp(ethereal.blood_volume + amount_adjusted, ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE+1, ETHEREAL_BLOOD_CHARGE_DANGEROUS) + return + ethereal.blood_volume = clamp(ethereal.blood_volume + amount, ETHEREAL_BLOOD_CHARGE_NONE, ETHEREAL_BLOOD_CHARGE_DANGEROUS) + +/obj/item/organ/internal/stomach/ethereal/proc/handle_charge(mob/living/carbon/ethereal, seconds_per_tick, times_fired) + var/datum/species/species = ethereal.dna.species + species.brutemod = 1.15 + var/word = pick("like you can't breathe","your lungs locking up","extremely lethargic") + var/blood_volume = ethereal.blood_volume + if(HAS_TRAIT(ethereal, TRAIT_ETHEREAL_NO_OVERCHARGE)) + blood_volume = min(blood_volume, ETHEREAL_BLOOD_CHARGE_FULL) + switch(blood_volume) + if(-INFINITY to ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE) + ethereal.add_mood_event("charge", /datum/mood_event/decharged) + ethereal.clear_alert("ethereal_overcharge") + ethereal.throw_alert(ALERT_ETHEREAL_CHARGE, /atom/movable/screen/alert/emptycell/ethereal) + species.brutemod = 2 + if(SPT_PROB(7.5, seconds_per_tick)) + to_chat(src, span_warning("You feel [word].")) + ethereal.adjustOxyLoss(round(0.01 * (ETHEREAL_BLOOD_CHARGE_LOW - ethereal.blood_volume) * seconds_per_tick, 1)) + if(ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE to ETHEREAL_BLOOD_CHARGE_LOW) + ethereal.clear_alert("ethereal_overcharge") + ethereal.add_mood_event("charge", /datum/mood_event/decharged) + ethereal.throw_alert(ALERT_ETHEREAL_CHARGE, /atom/movable/screen/alert/lowcell/ethereal, 3) + species.brutemod = 1.5 + if(ethereal.health > 10.5) + ethereal.apply_damage(0.155 * seconds_per_tick, TOX, null, null, ethereal) + if(ETHEREAL_BLOOD_CHARGE_LOW to ETHEREAL_BLOOD_CHARGE_NORMAL) + ethereal.clear_alert("ethereal_overcharge") + ethereal.add_mood_event("charge", /datum/mood_event/lowpower) + ethereal.throw_alert(ALERT_ETHEREAL_CHARGE, /atom/movable/screen/alert/lowcell/ethereal, 2) + species.brutemod = 1.25 + if(ETHEREAL_BLOOD_CHARGE_ALMOSTFULL to ETHEREAL_BLOOD_CHARGE_FULL) + ethereal.clear_alert("ethereal_overcharge") + ethereal.clear_alert("ethereal_charge") + ethereal.add_mood_event("charge", /datum/mood_event/charged) + species.brutemod = 1 + if(ETHEREAL_BLOOD_CHARGE_FULL to ETHEREAL_BLOOD_CHARGE_OVERLOAD) + ethereal.clear_alert("ethereal_charge") + ethereal.add_mood_event("charge", /datum/mood_event/overcharged) + ethereal.throw_alert(ALERT_ETHEREAL_OVERCHARGE, /atom/movable/screen/alert/ethereal_overcharge, 1) + species.brutemod = 1.25 + if(ETHEREAL_BLOOD_CHARGE_OVERLOAD to ETHEREAL_BLOOD_CHARGE_DANGEROUS) + ethereal.clear_alert("ethereal_charge") + ethereal.add_mood_event("charge", /datum/mood_event/supercharged) + ethereal.throw_alert(ALERT_ETHEREAL_OVERCHARGE, /atom/movable/screen/alert/ethereal_overcharge, 2) + ethereal.apply_damage(0.2 * seconds_per_tick, TOX, null, null, ethereal) + species.brutemod = 1.5 if(SPT_PROB(5, seconds_per_tick)) // 5% each seacond for ethereals to explosively release excess energy if it reaches dangerous levels - discharge_process(carbon) + discharge_process(ethereal) else - owner.clear_mood_event("charge") - carbon.clear_alert(ALERT_ETHEREAL_CHARGE) - carbon.clear_alert(ALERT_ETHEREAL_OVERCHARGE) + ethereal.clear_mood_event("charge") + ethereal.clear_alert(ALERT_ETHEREAL_CHARGE) + ethereal.clear_alert(ALERT_ETHEREAL_OVERCHARGE) -/obj/item/organ/internal/stomach/ethereal/proc/discharge_process(mob/living/carbon/carbon) - to_chat(carbon, span_warning("You begin to lose control over your charge!")) - carbon.visible_message(span_danger("[carbon] begins to spark violently!")) +/obj/item/organ/internal/stomach/ethereal/proc/discharge_process(mob/living/carbon/ethereal) + to_chat(ethereal, span_warning("You begin to lose control over your charge!")) + ethereal.visible_message(span_danger("[ethereal] begins to spark violently!")) var/static/mutable_appearance/overcharge //shameless copycode from lightning spell overcharge = overcharge || mutable_appearance('icons/effects/effects.dmi', "electricity", EFFECTS_LAYER) - carbon.add_overlay(overcharge) - - if(do_after(carbon, 5 SECONDS, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_HELD_ITEM|IGNORE_INCAPACITATED))) - if(ishuman(carbon)) - var/mob/living/carbon/human/human = carbon - if(human.dna?.species) - //fixed_mut_color is also ethereal color (for some reason) - carbon.flash_lighting_fx(5, 7, human.dna.species.fixed_mut_color ? human.dna.species.fixed_mut_color : human.dna.features["mcolor"]) - - playsound(carbon, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) - carbon.cut_overlay(overcharge) - tesla_zap(carbon, 2, crystal_charge*2.5, ZAP_OBJ_DAMAGE | ZAP_LOW_POWER_GEN | ZAP_ALLOW_DUPLICATES) - adjust_charge(ETHEREAL_CHARGE_FULL - crystal_charge) - carbon.visible_message(span_danger("[carbon] violently discharges energy!"), span_warning("You violently discharge energy!")) - - carbon.Paralyze(100) + ethereal.add_overlay(overcharge) + + if(do_after(ethereal, 5 SECONDS, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_HELD_ITEM|IGNORE_INCAPACITATED))) + ethereal.flash_lighting_fx(5, 7, ethereal.dna.species.fixed_mut_color ? ethereal.dna.species.fixed_mut_color : ethereal.dna.features["mcolor"]) + + playsound(ethereal, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) + ethereal.cut_overlay(overcharge) + tesla_zap(ethereal, 2, ethereal.blood_volume*9, ZAP_OBJ_DAMAGE | ZAP_GENERATES_POWER | ZAP_ALLOW_DUPLICATES) + adjust_charge(ethereal, ETHEREAL_BLOOD_CHARGE_FULL - ethereal.blood_volume) + ethereal.visible_message(span_danger("[ethereal] violently discharges energy!"), span_warning("You violently discharge energy!")) + + ethereal.Paralyze(100) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm index 52cc32ebbec4..327d263b79c5 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm @@ -83,14 +83,12 @@ for(var/obj/item/bodypart/limb as anything in new_ethereal.bodyparts) if(limb.limb_id == SPECIES_ETHEREAL) limb.update_limb(is_creating = TRUE) - RegisterSignal(ethereal, COMSIG_HUMAN_ON_HANDLE_BLOOD, PROC_REF(blood)) /datum/species/ethereal/on_species_loss(mob/living/carbon/human/former_ethereal, datum/species/new_species, pref_load) UnregisterSignal(former_ethereal, COMSIG_ATOM_EMAG_ACT) UnregisterSignal(former_ethereal, COMSIG_ATOM_EMP_ACT) UnregisterSignal(former_ethereal, COMSIG_LIGHT_EATER_ACT) UnregisterSignal(former_ethereal, COMSIG_ATOM_AFTER_ATTACKEDBY) - UnregisterSignal(former_ethereal, COMSIG_HUMAN_ON_HANDLE_BLOOD) QDEL_NULL(ethereal_light) return ..() @@ -105,99 +103,6 @@ /datum/species/ethereal/randomize_features(mob/living/carbon/human/human_mob) human_mob.dna.features["ethcolor"] = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)] - -/datum/species/ethereal/proc/blood(mob/living/carbon/human/ethereal, seconds_per_tick, times_fired) - SIGNAL_HANDLER - - if(ethereal.stat == DEAD) - return NONE - - . = HANDLE_BLOOD_NO_NUTRITION_DRAIN|HANDLE_BLOOD_NO_EFFECTS - - INVOKE_ASYNC(src, PROC_REF(adjust_charge), ethereal, -ETHEREAL_BLOOD_CHARGE_FACTOR * seconds_per_tick, TRUE) - INVOKE_ASYNC(src, PROC_REF(handle_charge), ethereal, seconds_per_tick, times_fired) - - return . - -/datum/species/ethereal/proc/adjust_charge(mob/living/carbon/human/ethereal, amount, passive) - if(passive) - if(ethereal.blood_volume < ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE) //Do not apply the clamp if its below the passive reduction level(no infinite blood sorry) - return - if(ethereal.blood_volume + amount < ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE+1) - ethereal.blood_volume = ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE+1 //bottom them off here if the end result would be less than the stopping point. - ethereal.blood_volume = clamp(ethereal.blood_volume + amount, ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE+1, ETHEREAL_BLOOD_CHARGE_DANGEROUS) - return - ethereal.blood_volume = clamp(ethereal.blood_volume + amount, ETHEREAL_BLOOD_CHARGE_NONE, ETHEREAL_BLOOD_CHARGE_DANGEROUS) - -/datum/species/ethereal/proc/handle_charge(mob/living/carbon/human/ethereal, seconds_per_tick, times_fired) - brutemod = 1.15 - var/word = pick("like you can't breathe","your lungs locking up","extremely lethargic") - var/blood_volume = ethereal.blood_volume - if(HAS_TRAIT(ethereal, TRAIT_ETHEREAL_NO_OVERCHARGE)) - blood_volume = min(blood_volume, ETHEREAL_BLOOD_CHARGE_FULL) - switch(blood_volume) - if(-INFINITY to ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE) - ethereal.add_mood_event("charge", /datum/mood_event/decharged) - ethereal.clear_alert("ethereal_overcharge") - ethereal.throw_alert(ALERT_ETHEREAL_CHARGE, /atom/movable/screen/alert/emptycell/ethereal) - brutemod = 2 - if(SPT_PROB(7.5, seconds_per_tick)) - to_chat(src, span_warning("You feel [word].")) - ethereal.adjustOxyLoss(round(0.01 * (ETHEREAL_BLOOD_CHARGE_LOW - ethereal.blood_volume) * seconds_per_tick, 1)) - if(ETHEREAL_BLOOD_CHARGE_LOWEST_PASSIVE to ETHEREAL_BLOOD_CHARGE_LOW) - ethereal.clear_alert("ethereal_overcharge") - ethereal.add_mood_event("charge", /datum/mood_event/decharged) - ethereal.throw_alert(ALERT_ETHEREAL_CHARGE, /atom/movable/screen/alert/lowcell/ethereal, 3) - brutemod = 1.5 - if(ethereal.health > 10.5) - ethereal.apply_damage(0.155 * seconds_per_tick, TOX, null, null, ethereal) - if(ETHEREAL_BLOOD_CHARGE_LOW to ETHEREAL_BLOOD_CHARGE_NORMAL) - ethereal.clear_alert("ethereal_overcharge") - ethereal.add_mood_event("charge", /datum/mood_event/lowpower) - ethereal.throw_alert(ALERT_ETHEREAL_CHARGE, /atom/movable/screen/alert/lowcell/ethereal, 2) - brutemod = 1.25 - if(ETHEREAL_BLOOD_CHARGE_ALMOSTFULL to ETHEREAL_BLOOD_CHARGE_FULL) - ethereal.clear_alert("ethereal_overcharge") - ethereal.clear_alert("ethereal_charge") - ethereal.add_mood_event("charge", /datum/mood_event/charged) - brutemod = 1 - if(ETHEREAL_BLOOD_CHARGE_FULL to ETHEREAL_BLOOD_CHARGE_OVERLOAD) - ethereal.clear_alert("ethereal_charge") - ethereal.add_mood_event("charge", /datum/mood_event/overcharged) - ethereal.throw_alert(ALERT_ETHEREAL_OVERCHARGE, /atom/movable/screen/alert/ethereal_overcharge, 1) - brutemod = 1.25 - if(ETHEREAL_BLOOD_CHARGE_OVERLOAD to ETHEREAL_BLOOD_CHARGE_DANGEROUS) - ethereal.clear_alert("ethereal_charge") - ethereal.add_mood_event("charge", /datum/mood_event/supercharged) - ethereal.throw_alert(ALERT_ETHEREAL_OVERCHARGE, /atom/movable/screen/alert/ethereal_overcharge, 2) - ethereal.apply_damage(0.2 * seconds_per_tick, TOX, null, null, ethereal) - brutemod = 1.5 - if(SPT_PROB(5, seconds_per_tick)) // 5% each seacond for ethereals to explosively release excess energy if it reaches dangerous levels - discharge_process(ethereal) - else - ethereal.clear_mood_event("charge") - ethereal.clear_alert(ALERT_ETHEREAL_CHARGE) - ethereal.clear_alert(ALERT_ETHEREAL_OVERCHARGE) - -/datum/species/ethereal/proc/discharge_process(mob/living/carbon/human/ethereal) - to_chat(ethereal, span_warning("You begin to lose control over your charge!")) - ethereal.visible_message(span_danger("[ethereal] begins to spark violently!")) - - var/static/mutable_appearance/overcharge //shameless copycode from lightning spell - overcharge = overcharge || mutable_appearance('icons/effects/effects.dmi', "electricity", EFFECTS_LAYER) - ethereal.add_overlay(overcharge) - - if(do_after(ethereal, 5 SECONDS, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_HELD_ITEM|IGNORE_INCAPACITATED))) - ethereal.flash_lighting_fx(5, 7, ethereal.dna.species.fixed_mut_color ? ethereal.dna.species.fixed_mut_color : ethereal.dna.features["mcolor"]) - - playsound(ethereal, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) - ethereal.cut_overlay(overcharge) - tesla_zap(ethereal, 2, ethereal.blood_volume*9, ZAP_OBJ_DAMAGE | ZAP_GENERATES_POWER | ZAP_ALLOW_DUPLICATES) - adjust_charge(ethereal, ETHEREAL_BLOOD_CHARGE_FULL - ethereal.blood_volume) - ethereal.visible_message(span_danger("[ethereal] violently discharges energy!"), span_warning("You violently discharge energy!")) - - ethereal.Paralyze(100) - /datum/species/ethereal/spec_updatehealth(mob/living/carbon/human/ethereal) . = ..() if(!ethereal_light) diff --git a/monkestation/code/modules/ranching/satyr/bodyparts.dm b/monkestation/code/modules/ranching/satyr/bodyparts.dm index 7809f9185b58..a5f2241aa4b8 100644 --- a/monkestation/code/modules/ranching/satyr/bodyparts.dm +++ b/monkestation/code/modules/ranching/satyr/bodyparts.dm @@ -21,8 +21,10 @@ icon_greyscale = 'monkestation/code/modules/ranching/icons/bodyparts.dmi' limb_id = SPECIES_SATYR bodytype = BODYTYPE_DIGITIGRADE | BODYTYPE_ORGANIC + bodypart_traits = list(TRAIT_HARD_SOLES, TRAIT_NON_IMPORTANT_SHOE_BLOCK) /obj/item/bodypart/leg/right/satyr icon_greyscale = 'monkestation/code/modules/ranching/icons/bodyparts.dmi' limb_id = SPECIES_SATYR bodytype = BODYTYPE_DIGITIGRADE | BODYTYPE_ORGANIC + bodypart_traits = list(TRAIT_HARD_SOLES, TRAIT_NON_IMPORTANT_SHOE_BLOCK) diff --git a/monkestation/code/modules/ranching/satyr/external_organs.dm b/monkestation/code/modules/ranching/satyr/external_organs.dm index f49c443dd4d7..b90c3edfde32 100644 --- a/monkestation/code/modules/ranching/satyr/external_organs.dm +++ b/monkestation/code/modules/ranching/satyr/external_organs.dm @@ -10,6 +10,18 @@ use_mob_sprite_as_obj_sprite = TRUE bodypart_overlay = /datum/bodypart_overlay/mutant/satyr_fluff + var/datum/action/cooldown/mob_cooldown/dash/headbutt/headbutt + +/obj/item/organ/external/satyr_fluff/Insert(mob/living/carbon/receiver, special, drop_if_replaced) + . = ..() + headbutt = new + headbutt.Grant(receiver) + +/obj/item/organ/external/satyr_fluff/Remove(mob/living/carbon/organ_owner, special, moving) + . = ..() + if(headbutt) + headbutt.Remove(organ_owner) + qdel(headbutt) /datum/bodypart_overlay/mutant/satyr_fluff layers = EXTERNAL_ADJACENT //| EXTERNAL_FRONT diff --git a/monkestation/code/modules/ranching/satyr/species.dm b/monkestation/code/modules/ranching/satyr/species.dm index 22601b7ae999..61a8620bb960 100644 --- a/monkestation/code/modules/ranching/satyr/species.dm +++ b/monkestation/code/modules/ranching/satyr/species.dm @@ -7,11 +7,7 @@ species_traits = list( NO_UNDERWEAR, ) - inherent_traits = list( - TRAIT_NON_IMPORTANT_SHOE_BLOCK, - TRAIT_ALCOHOL_TOLERANCE, - TRAIT_HARD_SOLES - ) + special_step_sounds = list( 'sound/effects/footstep/hardclaw1.ogg', 'sound/effects/footstep/hardclaw2.ogg', @@ -28,9 +24,9 @@ ) meat = /obj/item/food/meat/steak mutanttongue = /obj/item/organ/internal/tongue/satyr + mutantliver = /obj/item/organ/internal/liver/satyr maxhealthmod = 0.8 stunmod = 1.2 - payday_modifier = 1 bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/satyr, BODY_ZONE_CHEST = /obj/item/bodypart/chest/satyr, @@ -40,8 +36,6 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/satyr, ) - var/datum/action/cooldown/mob_cooldown/dash/headbutt/headbutt - /datum/species/satyr/get_species_description() return "Mythical goat-people. The clacking of hooves and smell of beer follow them around." @@ -78,26 +72,30 @@ return to_add -/datum/species/satyr/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) - . = ..() - ADD_TRAIT(C, TRAIT_TIN_EATER, INNATE_TRAIT) - C.AddComponent(/datum/component/living_drunk) +/obj/item/organ/internal/tongue/satyr + name = "satyr tongue" - headbutt = new - headbutt.Grant(C) + liked_foodtypes = GROSS | VEGETABLES | FRUIT + disliked_foodtypes = MEAT | DAIRY -/datum/species/satyr/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) +/obj/item/organ/internal/tongue/satyr/Insert(mob/living/carbon/tongue_owner, special, drop_if_replaced) . = ..() - REMOVE_TRAIT(C, TRAIT_TIN_EATER, INNATE_TRAIT) - var/datum/component/living_drunk/drunk = C.GetComponent(/datum/component/living_drunk) - qdel(drunk) + ADD_TRAIT(tongue_owner, TRAIT_TIN_EATER, ORGAN_TRAIT) - if(headbutt) - headbutt.Remove(C) - qdel(headbutt) +/obj/item/organ/internal/tongue/satyr/Remove(mob/living/carbon/tongue_owner, special) + . = ..() + REMOVE_TRAIT(tongue_owner, TRAIT_TIN_EATER, ORGAN_TRAIT) -/obj/item/organ/internal/tongue/satyr - name = "satyr tongue" +/obj/item/organ/internal/liver/satyr + name = "satyr liver" + organ_traits = list(TRAIT_ALCOHOL_TOLERANCE) - liked_foodtypes = GROSS | VEGETABLES | FRUIT - disliked_foodtypes = MEAT | DAIRY + +/obj/item/organ/internal/liver/satyr/Insert(mob/living/carbon/receiver, special, drop_if_replaced) + . = ..() + receiver.AddComponent(/datum/component/living_drunk) + +/obj/item/organ/internal/liver/satyr/Remove(mob/living/carbon/organ_owner, special) + . = ..() + var/datum/component/living_drunk/drunk = organ_owner.GetComponent(/datum/component/living_drunk) + qdel(drunk) From 95b3be87df9473c61f31915d9343c67cf7c91993 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 00:37:55 -0700 Subject: [PATCH 071/158] blood hearts and slime changes --- .../carbon/human/species_types/jellypeople.dm | 115 +---------------- .../human/species_types/lizardpeople.dm | 1 + .../carbon/human/species_types/podpeople.dm | 1 + .../{heart.dm => internal/heart/_heart.dm} | 22 ++++ .../carbon/human/species_type/arachnid.dm | 1 + .../carbon/human/species_type/floran.dm | 1 + .../modules/smithing/oozelings/body/organs.dm | 122 ++++++++++++++++++ .../modules/smithing/oozelings/species.dm | 67 +--------- .../modules/surgery/organs/internal/tongue.dm | 12 -- tgstation.dme | 2 +- 10 files changed, 154 insertions(+), 190 deletions(-) rename code/modules/surgery/organs/{heart.dm => internal/heart/_heart.dm} (97%) diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 2fd895356cd5..a7e795232c50 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -1,10 +1,3 @@ -///The rate at which slimes regenerate their jelly normally -#define JELLY_REGEN_RATE 1.5 -///The rate at which slimes regenerate their jelly when they completely run out of it and start taking damage, usually after having cannibalized all their limbs already -#define JELLY_REGEN_RATE_EMPTY 2.5 -///The blood volume at which slimes begin to start losing nutrition -- so that IV drips can work for blood deficient slimes -#define BLOOD_VOLUME_LOSE_NUTRITION 550 - /datum/species/jelly // Entirely alien beings that seem to be made entirely out of gel. They have three eyes and a skeleton visible within them. name = "\improper Jellyperson" @@ -20,10 +13,11 @@ mutanttongue = /obj/item/organ/internal/tongue/jelly mutantlungs = /obj/item/organ/internal/lungs/slime mutanteyes = /obj/item/organ/internal/eyes/jelly - mutantheart = null + mutantheart = /obj/item/organ/internal/heart/slime + meat = /obj/item/food/meat/slab/human/mutant/slime exotic_bloodtype = /datum/blood_type/slime - blood_deficiency_drain_rate = JELLY_REGEN_RATE + BLOOD_DEFICIENCY_MODIFIER + blood_deficiency_drain_rate = 1.5 + BLOOD_DEFICIENCY_MODIFIER var/datum/action/innate/regenerate_limbs/regenerate_limbs coldmod = 6 // = 3x cold damage heatmod = 0.5 // = 1/4x heat damage @@ -49,68 +43,12 @@ /datum/species/jelly/on_species_gain(mob/living/carbon/new_jellyperson, datum/species/old_species, pref_load) . = ..() - if(ishuman(new_jellyperson)) - regenerate_limbs = new - regenerate_limbs.Grant(new_jellyperson) new_jellyperson.AddElement(/datum/element/soft_landing) - RegisterSignal(new_jellyperson, COMSIG_HUMAN_ON_HANDLE_BLOOD, PROC_REF(slime_blood)) /datum/species/jelly/on_species_loss(mob/living/carbon/former_jellyperson, datum/species/new_species, pref_load) - if(regenerate_limbs) - regenerate_limbs.Remove(former_jellyperson) former_jellyperson.RemoveElement(/datum/element/soft_landing) - UnregisterSignal(former_jellyperson, COMSIG_HUMAN_ON_HANDLE_BLOOD) - return ..() -/datum/species/jelly/proc/slime_blood(mob/living/carbon/human/slime, seconds_per_tick, times_fired) - SIGNAL_HANDLER - - if(slime.stat == DEAD) - return NONE - - . = HANDLE_BLOOD_NO_NUTRITION_DRAIN|HANDLE_BLOOD_NO_EFFECTS - - if(slime.blood_volume <= 0) - slime.blood_volume += JELLY_REGEN_RATE_EMPTY * seconds_per_tick - slime.adjustBruteLoss(2.5 * seconds_per_tick) - to_chat(slime, span_danger("You feel empty!")) - - if(slime.blood_volume < BLOOD_VOLUME_NORMAL) - if(slime.nutrition >= NUTRITION_LEVEL_STARVING) - slime.blood_volume += JELLY_REGEN_RATE * seconds_per_tick - if(slime.blood_volume <= BLOOD_VOLUME_LOSE_NUTRITION) // don't lose nutrition if we are above a certain threshold, otherwise slimes on IV drips will still lose nutrition - slime.adjust_nutrition(-1.25 * seconds_per_tick) - - if(HAS_TRAIT(slime, TRAIT_BLOOD_DEFICIENCY)) - var/datum/quirk/blooddeficiency/blooddeficiency = slime.get_quirk(/datum/quirk/blooddeficiency) - if(!isnull(blooddeficiency)) - blooddeficiency.lose_blood(seconds_per_tick) - - if(slime.blood_volume < BLOOD_VOLUME_OKAY) - if(SPT_PROB(2.5, seconds_per_tick)) - to_chat(slime, span_danger("You feel drained!")) - - if(slime.blood_volume < BLOOD_VOLUME_BAD) - Cannibalize_Body(slime) - - regenerate_limbs?.build_all_button_icons(UPDATE_BUTTON_STATUS) - return . - -/datum/species/jelly/proc/Cannibalize_Body(mob/living/carbon/human/H) - var/list/limbs_to_consume = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) - H.get_missing_limbs() - var/obj/item/bodypart/consumed_limb - if(!length(limbs_to_consume)) - H.losebreath++ - return - if(H.num_legs) //Legs go before arms - limbs_to_consume -= list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM) - consumed_limb = H.get_bodypart(pick(limbs_to_consume)) - consumed_limb.drop_limb() - to_chat(H, span_userdanger("Your [consumed_limb] is drawn back into your body, unable to maintain its shape!")) - qdel(consumed_limb) - H.blood_volume += 20 - // Slimes have both TRAIT_NOBLOOD and an exotic bloodtype set, so they need to be handled uniquely here. // They may not be roundstart but in the unlikely event they become one might as well not leave a glaring issue open. /datum/species/jelly/create_pref_blood_perks() @@ -126,47 +64,6 @@ return to_add -/datum/action/innate/regenerate_limbs - name = "Regenerate Limbs" - check_flags = AB_CHECK_CONSCIOUS - button_icon_state = "slimeheal" - button_icon = 'icons/mob/actions/actions_slime.dmi' - background_icon_state = "bg_alien" - overlay_icon_state = "bg_alien_border" - -/datum/action/innate/regenerate_limbs/IsAvailable(feedback = FALSE) - . = ..() - if(!.) - return - var/mob/living/carbon/human/H = owner - var/list/limbs_to_heal = H.get_missing_limbs() - if(!length(limbs_to_heal)) - return FALSE - if(H.blood_volume >= BLOOD_VOLUME_OKAY+40) - return TRUE - -/datum/action/innate/regenerate_limbs/Activate() - var/mob/living/carbon/human/H = owner - var/list/limbs_to_heal = H.get_missing_limbs() - if(!length(limbs_to_heal)) - to_chat(H, span_notice("You feel intact enough as it is.")) - return - to_chat(H, span_notice("You focus intently on your missing [length(limbs_to_heal) >= 2 ? "limbs" : "limb"]...")) - if(H.blood_volume >= 40*length(limbs_to_heal)+BLOOD_VOLUME_OKAY) - H.regenerate_limbs() - H.blood_volume -= 40*length(limbs_to_heal) - to_chat(H, span_notice("...and after a moment you finish reforming!")) - return - else if(H.blood_volume >= 40)//We can partially heal some limbs - while(H.blood_volume >= BLOOD_VOLUME_OKAY+40) - var/healed_limb = pick(limbs_to_heal) - H.regenerate_limb(healed_limb) - limbs_to_heal -= healed_limb - H.blood_volume -= 40 - to_chat(H, span_warning("...but there is not enough of you to fix everything! You must attain more mass to heal completely!")) - return - to_chat(H, span_warning("...but there is not enough of you to go around! You must attain more mass to heal!")) - ////////////////////////////////////////////////////////SLIMEPEOPLE/////////////////////////////////////////////////////////////////// //Slime people are able to split like slimes, retaining a single mind that can swap between bodies at will, even after death. @@ -244,7 +141,7 @@ else if(H.nutrition >= NUTRITION_LEVEL_WELL_FED) H.blood_volume += 1.5 * seconds_per_tick - if(H.blood_volume <= BLOOD_VOLUME_LOSE_NUTRITION) + if(H.blood_volume <= 550) H.adjust_nutrition(-1.25 * seconds_per_tick) ..() @@ -804,7 +701,3 @@ return FALSE return TRUE - -#undef JELLY_REGEN_RATE -#undef JELLY_REGEN_RATE_EMPTY -#undef BLOOD_VOLUME_LOSE_NUTRITION diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index cd1432128d62..7de49f6e07e0 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -23,6 +23,7 @@ ) mutanttongue = /obj/item/organ/internal/tongue/lizard mutantstomach = /obj/item/organ/internal/stomach/lizard + mutantheart = /obj/item/organ/internal/heart/lizard coldmod = 1.5 heatmod = 0.67 payday_modifier = 0.75 diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index dd3bf1b0cee0..dfbc138d7d7a 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -13,6 +13,7 @@ /obj/item/organ/external/pod_hair = "None", ) mutanttongue = /obj/item/organ/internal/tongue/pod + mutantheart = /obj/item/organ/internal/heart/pod inherent_biotypes = MOB_ORGANIC | MOB_HUMANOID | MOB_PLANT inherent_factions = list(FACTION_PLANTS, FACTION_VINES) diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm similarity index 97% rename from code/modules/surgery/organs/heart.dm rename to code/modules/surgery/organs/internal/heart/_heart.dm index 29f266b1e556..ce9995f6ed1b 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/internal/heart/_heart.dm @@ -23,12 +23,21 @@ var/failed = FALSE //to prevent constantly running failing code var/operated = FALSE //whether the heart's been operated on to fix some of its damages + var/datum/blood_type/heart_bloodtype + /obj/item/organ/internal/heart/update_icon_state() icon_state = "[base_icon_state]-[beating ? "on" : "off"]" return ..() +/obj/item/organ/internal/heart/Insert(mob/living/carbon/receiver, special, drop_if_replaced) + . = ..() + if(heart_bloodtype) + receiver.dna?.human_blood_type = heart_bloodtype + /obj/item/organ/internal/heart/Remove(mob/living/carbon/heartless, special = 0) . = ..() + if(heart_bloodtype) + heartless.dna?.human_blood_type = random_human_blood_type() if(!special) addtimer(CALLBACK(src, PROC_REF(stop_if_unowned)), 120) @@ -310,6 +319,7 @@ icon_state = "ethereal_heart" //Welp. At least it's more unique in functionaliy. visual = TRUE //This is used by the ethereal species for color desc = "A crystal-like organ that functions similarly to a heart for Ethereals. It can revive its owner." + heart_bloodtype = /datum/blood_type/crew/ethereal ///Cooldown for the next time we can crystalize COOLDOWN_DECLARE(crystalize_cooldown) @@ -557,3 +567,15 @@ // this qdeleted check is just for sanity. if(!QDELETED(src)) qdel(src) + +/obj/item/organ/internal/heart/lizard + name = "lizard heart" + heart_bloodtype = /datum/blood_type/crew/lizard + +/obj/item/organ/internal/heart/pod + name = "plant heart" + heart_bloodtype = /datum/blood_type/water + +/obj/item/organ/internal/heart/spider + name = "spider heart" + heart_bloodtype = /datum/blood_type/spider diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm index f2040f395aa4..ef370032bc5d 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm @@ -15,6 +15,7 @@ species_language_holder = /datum/language_holder/fly mutanttongue = /obj/item/organ/internal/tongue/arachnid mutanteyes = /obj/item/organ/internal/eyes/night_vision/arachnid + mutantheart = /obj/item/organ/internal/heart/spider exotic_bloodtype = /datum/blood_type/spider inherent_factions = list(FACTION_SPIDER) bodypart_overrides = list( diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm index 88dd68979bc3..7aa957093039 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm @@ -38,6 +38,7 @@ ) mutanttongue = /obj/item/organ/internal/tongue/pod mutanteyes = /obj/item/organ/internal/eyes/floran + mutantheart = /obj/item/organ/internal/heart/pod ass_image = 'icons/ass/asspodperson.png' diff --git a/monkestation/code/modules/smithing/oozelings/body/organs.dm b/monkestation/code/modules/smithing/oozelings/body/organs.dm index 0f5b242334d5..f3bf7094a344 100644 --- a/monkestation/code/modules/smithing/oozelings/body/organs.dm +++ b/monkestation/code/modules/smithing/oozelings/body/organs.dm @@ -33,6 +33,7 @@ name = "endoplasmic reticulum" zone = BODY_ZONE_CHEST organ_flags = ORGAN_UNREMOVABLE + organ_traits = list(TRAIT_TOXINLOVER) /obj/item/organ/internal/liver/slime/on_life(seconds_per_tick, times_fired) . = ..() @@ -289,3 +290,124 @@ drop_items_to_ground(new_body.drop_location()) return new_body + + +///The rate at which slimes regenerate their jelly normally +#define JELLY_REGEN_RATE 1.5 +///The rate at which slimes regenerate their jelly when they completely run out of it and start taking damage, usually after having cannibalized all their limbs already +#define JELLY_REGEN_RATE_EMPTY 2.5 +///The blood volume at which slimes begin to start losing nutrition -- so that IV drips can work for blood deficient slimes +#define BLOOD_VOLUME_LOSE_NUTRITION 550 + + +/obj/item/organ/internal/heart/slime + name = "slime heart" + + heart_bloodtype = /datum/blood_type/slime + var/datum/action/innate/regenerate_limbs/regenerate_limbs + +/obj/item/organ/internal/heart/slime/Insert(mob/living/carbon/receiver, special, drop_if_replaced) + . = ..() + regenerate_limbs = new + regenerate_limbs.Grant(receiver) + RegisterSignal(receiver, COMSIG_HUMAN_ON_HANDLE_BLOOD, PROC_REF(slime_blood)) + +/obj/item/organ/internal/heart/slime/Remove(mob/living/carbon/heartless, special) + . = ..() + if(regenerate_limbs) + regenerate_limbs.Remove(heartless) + qdel(regenerate_limbs) + UnregisterSignal(heartless, COMSIG_HUMAN_ON_HANDLE_BLOOD) + +/obj/item/organ/internal/heart/slime/proc/slime_blood(mob/living/carbon/human/slime, seconds_per_tick, times_fired) + SIGNAL_HANDLER + + if(slime.stat == DEAD) + return NONE + + . = HANDLE_BLOOD_NO_NUTRITION_DRAIN|HANDLE_BLOOD_NO_EFFECTS + + if(slime.blood_volume <= 0) + slime.blood_volume += JELLY_REGEN_RATE_EMPTY * seconds_per_tick + slime.adjustBruteLoss(2.5 * seconds_per_tick) + to_chat(slime, span_danger("You feel empty!")) + + if(slime.blood_volume < BLOOD_VOLUME_NORMAL) + if(slime.nutrition >= NUTRITION_LEVEL_STARVING) + slime.blood_volume += JELLY_REGEN_RATE * seconds_per_tick + if(slime.blood_volume <= BLOOD_VOLUME_LOSE_NUTRITION) // don't lose nutrition if we are above a certain threshold, otherwise slimes on IV drips will still lose nutrition + slime.adjust_nutrition(-1.25 * seconds_per_tick) + + if(HAS_TRAIT(slime, TRAIT_BLOOD_DEFICIENCY)) + var/datum/quirk/blooddeficiency/blooddeficiency = slime.get_quirk(/datum/quirk/blooddeficiency) + if(!isnull(blooddeficiency)) + blooddeficiency.lose_blood(seconds_per_tick) + + if(slime.blood_volume < BLOOD_VOLUME_OKAY) + if(SPT_PROB(2.5, seconds_per_tick)) + to_chat(slime, span_danger("You feel drained!")) + + if(slime.blood_volume < BLOOD_VOLUME_BAD) + Cannibalize_Body(slime) + + regenerate_limbs?.build_all_button_icons(UPDATE_BUTTON_STATUS) + return . + +/obj/item/organ/internal/heart/slime/proc/Cannibalize_Body(mob/living/carbon/human/H) + var/list/limbs_to_consume = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) - H.get_missing_limbs() + var/obj/item/bodypart/consumed_limb + if(!length(limbs_to_consume)) + H.losebreath++ + return + if(H.num_legs) //Legs go before arms + limbs_to_consume -= list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM) + consumed_limb = H.get_bodypart(pick(limbs_to_consume)) + consumed_limb.drop_limb() + to_chat(H, span_userdanger("Your [consumed_limb] is drawn back into your body, unable to maintain its shape!")) + qdel(consumed_limb) + H.blood_volume += 20 + +/datum/action/innate/regenerate_limbs + name = "Regenerate Limbs" + check_flags = AB_CHECK_CONSCIOUS + button_icon_state = "slimeheal" + button_icon = 'icons/mob/actions/actions_slime.dmi' + background_icon_state = "bg_alien" + overlay_icon_state = "bg_alien_border" + +/datum/action/innate/regenerate_limbs/IsAvailable(feedback = FALSE) + . = ..() + if(!.) + return + var/mob/living/carbon/human/H = owner + var/list/limbs_to_heal = H.get_missing_limbs() + if(!length(limbs_to_heal)) + return FALSE + if(H.blood_volume >= BLOOD_VOLUME_OKAY+40) + return TRUE + +/datum/action/innate/regenerate_limbs/Activate() + var/mob/living/carbon/human/H = owner + var/list/limbs_to_heal = H.get_missing_limbs() + if(!length(limbs_to_heal)) + to_chat(H, span_notice("You feel intact enough as it is.")) + return + to_chat(H, span_notice("You focus intently on your missing [length(limbs_to_heal) >= 2 ? "limbs" : "limb"]...")) + if(H.blood_volume >= 40*length(limbs_to_heal)+BLOOD_VOLUME_OKAY) + H.regenerate_limbs() + H.blood_volume -= 40*length(limbs_to_heal) + to_chat(H, span_notice("...and after a moment you finish reforming!")) + return + else if(H.blood_volume >= 40)//We can partially heal some limbs + while(H.blood_volume >= BLOOD_VOLUME_OKAY+40) + var/healed_limb = pick(limbs_to_heal) + H.regenerate_limb(healed_limb) + limbs_to_heal -= healed_limb + H.blood_volume -= 40 + to_chat(H, span_warning("...but there is not enough of you to fix everything! You must attain more mass to heal completely!")) + return + to_chat(H, span_warning("...but there is not enough of you to go around! You must attain more mass to heal!")) + +#undef JELLY_REGEN_RATE +#undef JELLY_REGEN_RATE_EMPTY +#undef BLOOD_VOLUME_LOSE_NUTRITION diff --git a/monkestation/code/modules/smithing/oozelings/species.dm b/monkestation/code/modules/smithing/oozelings/species.dm index 0af2fbb5e4b3..6b9fd24bfb3a 100644 --- a/monkestation/code/modules/smithing/oozelings/species.dm +++ b/monkestation/code/modules/smithing/oozelings/species.dm @@ -20,11 +20,10 @@ mutantears = /obj/item/organ/internal/ears/jelly mutantlungs = /obj/item/organ/internal/lungs/slime mutanttongue = /obj/item/organ/internal/tongue/jelly + mutantheart = /obj/item/organ/internal/heart/slime inherent_traits = list( TRAIT_CAN_USE_FLIGHT_POTION, - TRAIT_TOXINLOVER, - TRAIT_NOBLOOD, TRAIT_EASYDISMEMBER, TRAIT_NOFIRE, ) @@ -49,7 +48,6 @@ BODY_ZONE_CHEST = /obj/item/bodypart/chest/oozeling, ) - var/datum/action/innate/regenerate_limbs/regenerate_limbs var/datum/action/cooldown/spell/slime_washing/slime_washing var/datum/action/cooldown/spell/slime_hydrophobia/slime_hydrophobia var/datum/action/innate/core_signal/core_signal @@ -96,8 +94,6 @@ . = .(gender, TRUE, lastname, ++attempts) /datum/species/oozeling/on_species_loss(mob/living/carbon/C) - if(regenerate_limbs) - regenerate_limbs.Remove(C) if(slime_washing) slime_washing.Remove(C) if(slime_hydrophobia) @@ -110,8 +106,6 @@ /datum/species/oozeling/on_species_gain(mob/living/carbon/C, datum/species/old_species) ..() if(ishuman(C)) - regenerate_limbs = new - regenerate_limbs.Grant(C) slime_washing = new slime_washing.Grant(C) slime_hydrophobia = new @@ -144,65 +138,6 @@ to_chat(slime, span_warning("You can't pull your body together and regenerate with water inside it!")) slime.blood_volume -= 1 * seconds_per_tick - if(slime.blood_volume > BLOOD_VOLUME_NORMAL && healing) - if(HAS_TRAIT(slime, TRAIT_SLIME_HYDROPHOBIA)) - return - if(slime.stat != CONSCIOUS) - return - slime.heal_overall_damage(brute = 2 * seconds_per_tick, burn = 2 * seconds_per_tick, required_bodytype = BODYTYPE_ORGANIC) - slime.adjustOxyLoss(-1 * seconds_per_tick) - - if(!slime.blood_volume) - slime.blood_volume += 5 - slime.adjustBruteLoss(5) - to_chat(slime, span_danger("You feel empty!")) - - if(slime.nutrition >= NUTRITION_LEVEL_WELL_FED && slime.blood_volume <= 672) - if(slime.nutrition >= NUTRITION_LEVEL_ALMOST_FULL) - slime.adjust_nutrition(-5) - slime.blood_volume += 10 - else - slime.blood_volume += 8 - - if(slime.nutrition <= NUTRITION_LEVEL_HUNGRY) - if(slime.nutrition <= NUTRITION_LEVEL_STARVING) - slime.blood_volume -= 8 - if(prob(5)) - to_chat(slime, span_info("You're starving! Get some food!")) - else - if(prob(35)) - slime.blood_volume -= 2 - if(prob(5)) - to_chat(slime, span_danger("You're feeling pretty hungry...")) - - if(slime.blood_volume < BLOOD_VOLUME_OKAY && prob(5)) - to_chat(slime, span_danger("You feel drained!")) - if(slime.blood_volume < BLOOD_VOLUME_OKAY) - Cannibalize_Body(slime) - - if(slime.blood_volume < 0) - slime.blood_volume = 0 - -/datum/species/oozeling/proc/Cannibalize_Body(mob/living/carbon/human/slime) - if(HAS_TRAIT(slime, TRAIT_OOZELING_NO_CANNIBALIZE)) - return - var/list/limbs_to_consume = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) - slime.get_missing_limbs() - var/obj/item/bodypart/consumed_limb - - if(!length(limbs_to_consume)) - slime.losebreath++ - return - if(slime.num_legs) //Legs go before arms - limbs_to_consume -= list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM) - - consumed_limb = slime.get_bodypart(pick(limbs_to_consume)) - consumed_limb.drop_limb() - - to_chat(slime, span_userdanger("Your [consumed_limb] is drawn back into your body, unable to maintain its shape!")) - qdel(consumed_limb) - slime.blood_volume += 80 - slime.nutrition += 20 - /////// /// CHEMICAL HANDLING /// Here's where slimes heal off plasma and where they hate drinking water. diff --git a/monkestation/code/modules/surgery/organs/internal/tongue.dm b/monkestation/code/modules/surgery/organs/internal/tongue.dm index 434b75d41a8f..f649d5767ec4 100644 --- a/monkestation/code/modules/surgery/organs/internal/tongue.dm +++ b/monkestation/code/modules/surgery/organs/internal/tongue.dm @@ -32,15 +32,3 @@ /obj/item/organ/internal/tongue/arachnid/get_possible_languages() return ..() + /datum/language/buzzwords - -/obj/item/organ/internal/tongue/oozeling - name = "oozeling tongue" - desc = "A goopy organ that mimics the tongues of other carbon beings." - icon = 'monkestation/icons/obj/medical/organs/organs.dmi' - icon_state = "tongue_oozeling" - say_mod = "blurbles" - alpha = 200 - -// Oozeling tongues can speak all default + slime -/obj/item/organ/internal/tongue/oozeling/get_possible_languages() - return ..() + /datum/language/slime diff --git a/tgstation.dme b/tgstation.dme index 6e0c7e9b7e71..59663e6c06e0 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -5480,7 +5480,6 @@ #include "code\modules\surgery\organs\autosurgeon.dm" #include "code\modules\surgery\organs\ears.dm" #include "code\modules\surgery\organs\eyes.dm" -#include "code\modules\surgery\organs\heart.dm" #include "code\modules\surgery\organs\helpers.dm" #include "code\modules\surgery\organs\lungs.dm" #include "code\modules\surgery\organs\organ_internal.dm" @@ -5492,6 +5491,7 @@ #include "code\modules\surgery\organs\external\wings\functional_wings.dm" #include "code\modules\surgery\organs\external\wings\moth_wings.dm" #include "code\modules\surgery\organs\external\wings\wings.dm" +#include "code\modules\surgery\organs\internal\heart\_heart.dm" #include "code\modules\surgery\organs\internal\liver\_liver.dm" #include "code\modules\surgery\organs\internal\liver\liver_plasmamen.dm" #include "code\modules\surgery\organs\internal\liver\liver_skeleton.dm" From ff80bdfc8f573f67143e50ae50bbe2eb8868b21d Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 08:18:01 -0700 Subject: [PATCH 072/158] silver lizard --- .../mob/living/carbon/human/species_types/lizardpeople.dm | 1 + monkestation/code/modules/blood_datum/blood.dm | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 7de49f6e07e0..85c6a19e34eb 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -157,6 +157,7 @@ Lizard subspecies: SILVER SCALED mutantlungs = null species_language_holder = /datum/language_holder/lizard/silver mutanttongue = /obj/item/organ/internal/tongue/lizard/silver + exotic_bloodtype = /datum/blood_type/crew/lizard/silver armor = 10 //very light silvery scales soften blows changesource_flags = MIRROR_BADMIN | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN examine_limb_id = SPECIES_LIZARD diff --git a/monkestation/code/modules/blood_datum/blood.dm b/monkestation/code/modules/blood_datum/blood.dm index b047f973ef81..4a7e7fb8476e 100644 --- a/monkestation/code/modules/blood_datum/blood.dm +++ b/monkestation/code/modules/blood_datum/blood.dm @@ -226,6 +226,14 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying) /datum/blood_type/crew/lizard name = "L" color = "#047200" // Some species of lizards have mutated green blood due to biliverdin build up + compatible_types = list(/datum/blood_type/crew/lizard/silver) + +/datum/blood_type/crew/lizard/silver + color = "#ffffff63" + compatible_types = list(/datum/blood_type/crew/lizard) + +/datum/blood_type/crew/lizard/silver/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat) + blood.add_filter("silver_glint", 3, list("type" = "outline", "color" = "#c9c9c963", "size" = 1.5)) /datum/blood_type/crew/skrell name = "S" From 87c09d98509a0fb96d079f70a2a57e71aa3c7c17 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 11:11:29 -0700 Subject: [PATCH 073/158] tons of tweaks --- code/__DEFINES/combat.dm | 2 + code/__DEFINES/dcs/helpers.dm | 2 +- code/controllers/subsystem/dcs.dm | 9 +++ code/datums/elements/_element.dm | 4 ++ .../effects/decals/cleanable/humans.dm | 7 ++- code/modules/mining/lavaland/tendril_loot.dm | 3 +- .../mob/living/carbon/human/_species.dm | 7 --- .../carbon/human/species_types/abductors.dm | 1 - .../carbon/human/species_types/android.dm | 1 - .../carbon/human/species_types/flypeople.dm | 1 - .../carbon/human/species_types/jellypeople.dm | 11 ---- .../human/species_types/lizardpeople.dm | 9 +-- .../carbon/human/species_types/mothmen.dm | 1 - .../carbon/human/species_types/plasmamen.dm | 2 - .../carbon/human/species_types/podpeople.dm | 2 - .../carbon/human/species_types/skeletons.dm | 1 - code/modules/paperwork/photocopier.dm | 6 +- code/modules/surgery/bodyparts/_bodyparts.dm | 63 +++++++++++++++++++ code/modules/surgery/bodyparts/parts.dm | 2 + .../bodyparts/species_parts/android_parts.dm | 1 + .../species_parts/lizard_bodyparts.dm | 15 ++++- .../bodyparts/species_parts/misc_bodyparts.dm | 25 +++++++- .../bodyparts/species_parts/moth_bodyparts.dm | 1 + .../species_parts/plasmaman_bodyparts.dm | 1 + .../organs/stomach/stomach_ethereal.dm | 9 +-- .../carbon/human/species_type/ethereal.dm | 8 ++- .../carbon/human/species_type/floran.dm | 2 - .../smithing/oozelings/body/bodyparts.dm | 8 +++ .../modules/smithing/oozelings/species.dm | 2 - .../surgery/bodyparts/floran_bodyparts.dm | 1 + .../temperature_overhaul/temperature_proc.dm | 26 +++----- .../the_wolf_inside_of_me/bodyparts.dm | 2 +- 32 files changed, 163 insertions(+), 72 deletions(-) diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 25e86ab8f191..d6de977fecb6 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -273,6 +273,8 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define BODY_ZONE_L_LEG "l_leg" #define BODY_ZONE_R_LEG "r_leg" +#define TOTAL_BODYPART_COUNT 6 + GLOBAL_LIST_INIT(arm_zones, list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) #define BODY_ZONE_PRECISE_EYES "eyes" diff --git a/code/__DEFINES/dcs/helpers.dm b/code/__DEFINES/dcs/helpers.dm index 75d37aebf72f..3a245951da58 100644 --- a/code/__DEFINES/dcs/helpers.dm +++ b/code/__DEFINES/dcs/helpers.dm @@ -15,7 +15,7 @@ #define AddElement(arguments...) _AddElement(list(##arguments)) /// A wrapper for _RemoveElement that allows us to pretend we're using normal named arguments #define RemoveElement(arguments...) _RemoveElement(list(##arguments)) - +#define HasElement(source, type) _HasElement(source, type) /// A wrapper for _AddComponent that allows us to pretend we're using normal named arguments #define AddComponent(arguments...) _AddComponent(list(##arguments)) diff --git a/code/controllers/subsystem/dcs.dm b/code/controllers/subsystem/dcs.dm index 8e305d95699b..8dbd88e6231a 100644 --- a/code/controllers/subsystem/dcs.dm +++ b/code/controllers/subsystem/dcs.dm @@ -58,3 +58,12 @@ PROCESSING_SUBSYSTEM_DEF(dcs) fullid += named_arguments return list2params(fullid) + +/datum/controller/subsystem/processing/dcs/proc/_Has_Element(atom/checker, datum/element/element_id) + var/datum/element/eletype = elements_by_type[element_id] + if(!eletype) + return FALSE //not yet created simply return FALSE + + if(!(checker in eletype?._signal_procs)) //shitcode beware + return FALSE + return TRUE diff --git a/code/datums/elements/_element.dm b/code/datums/elements/_element.dm index ee1d5a9af9ac..7a6703d86195 100644 --- a/code/datums/elements/_element.dm +++ b/code/datums/elements/_element.dm @@ -57,6 +57,10 @@ if(ele.Attach(arglist(arguments)) == ELEMENT_INCOMPATIBLE) CRASH("Incompatible element [ele.type] was assigned to a [type]! args: [json_encode(args)]") +/// Finds the element and checks if the source is currently part of the element +/datum/proc/_HasElement(datum/source, datum/element/type) + return SSdcs._Has_Element(source, type) + /** * Finds the singleton for the element type given and detaches it from src * You only need additional arguments beyond the type if you're using [ELEMENT_BESPOKE] diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 7d3151e7dd63..5dace3a42a55 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -34,7 +34,7 @@ 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, - -0.75, -0.75, -0.75, 0, + -0.5, -0.75, -0.75, 0, ) var/count = 0 var/footprint_sprite = null @@ -51,6 +51,11 @@ STOP_PROCESSING(SSblood_drying, src) return ..() +/obj/effect/decal/cleanable/blood/on_entered(datum/source, atom/movable/AM) + if(dried) + return + return ..() + #define DRY_FILTER_KEY "dry_effect" /obj/effect/decal/cleanable/blood/update_overlays() diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index 35cc374c967b..60900a4f4b41 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -560,7 +560,8 @@ exposed_human.emote("scream") /datum/reagent/flightpotion/proc/get_wing_choice(mob/living/carbon/human/needs_wings) - var/list/wing_types = needs_wings.dna.species.wing_types.Copy() + var/obj/item/bodypart/chest/chest = needs_wings.get_bodypart(BODY_ZONE_CHEST) + var/list/wing_types = chest.wing_types.Copy() if(wing_types.len == 1 || !needs_wings.client) return wing_types[1] var/list/radial_wings = list() diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index cc76e80dbc98..88bf5d3e9b05 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -111,8 +111,6 @@ GLOBAL_LIST_EMPTY(features_by_species) //Used for metabolizing reagents. We're going to assume you're a meatbag unless you say otherwise. var/reagent_tag = PROCESS_ORGANIC - //Dictates which wing icons are allowed for a given species. If count is >1 a radial menu is used to choose between all icons in list - var/list/wing_types = list(/obj/item/organ/external/wings/functional/angel) // Do not READ these temperature related properties, use the living level ones instead // These are deprecated and only exist to set in [/proc/on_species_gain] /// The natural temperature for a body @@ -219,9 +217,6 @@ GLOBAL_LIST_EMPTY(features_by_species) ///Unique cookie given by admins through prayers var/species_cookie = /obj/item/food/cookie - ///For custom overrides for species ass images - var/icon/ass_image - /// List of family heirlooms this species can get with the family heirloom quirk. List of types. var/list/family_heirlooms @@ -260,8 +255,6 @@ GLOBAL_LIST_EMPTY(features_by_species) /datum/species/New() - wing_types = string_list(wing_types) - if(!plural_form) plural_form = "[name]\s" diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm index 7987df7b7fef..90f4953a8826 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -19,7 +19,6 @@ mutantheart = null mutantlungs = null changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT - ass_image = 'icons/ass/assgrey.png' bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/abductor, diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm index 99a3a852fc7a..054b4a489d64 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -49,7 +49,6 @@ mutantears = /obj/item/organ/internal/ears/cybernetic mutantbutt = /obj/item/organ/internal/butt/cyber species_language_holder = /datum/language_holder/synthetic - wing_types = list(/obj/item/organ/external/wings/functional/robotic) changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT reagent_tag = PROCESS_SYNTHETIC // They don't HAVE a liver, but if they did, they'd have synthetic chem processing. special_step_sounds = list('sound/effects/servostep.ogg') diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm index bd9f1f05e664..e8e60718584e 100644 --- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm @@ -12,7 +12,6 @@ mutanteyes = /obj/item/organ/internal/eyes/fly changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_language_holder = /datum/language_holder/fly - wing_types = list(/obj/item/organ/external/wings/functional/fly) payday_modifier = 0.75 mutanttongue = /obj/item/organ/internal/tongue/fly diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index a7e795232c50..5195ddb8dd96 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -18,7 +18,6 @@ meat = /obj/item/food/meat/slab/human/mutant/slime exotic_bloodtype = /datum/blood_type/slime blood_deficiency_drain_rate = 1.5 + BLOOD_DEFICIENCY_MODIFIER - var/datum/action/innate/regenerate_limbs/regenerate_limbs coldmod = 6 // = 3x cold damage heatmod = 0.5 // = 1/4x heat damage burnmod = 0.5 // = 1/2x generic burn damage @@ -26,8 +25,6 @@ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT inherent_factions = list(FACTION_SLIME) species_language_holder = /datum/language_holder/jelly - ass_image = 'icons/ass/assslime.png' - wing_types = list(/obj/item/organ/external/wings/functional/slime) hair_color = "mutcolor" hair_alpha = 150 facial_hair_alpha = 150 @@ -41,14 +38,6 @@ BODY_ZONE_CHEST = /obj/item/bodypart/chest/jelly, ) -/datum/species/jelly/on_species_gain(mob/living/carbon/new_jellyperson, datum/species/old_species, pref_load) - . = ..() - new_jellyperson.AddElement(/datum/element/soft_landing) - -/datum/species/jelly/on_species_loss(mob/living/carbon/former_jellyperson, datum/species/new_species, pref_load) - former_jellyperson.RemoveElement(/datum/element/soft_landing) - return ..() - // Slimes have both TRAIT_NOBLOOD and an exotic bloodtype set, so they need to be handled uniquely here. // They may not be roundstart but in the unlikely event they become one might as well not leave a glaring issue open. /datum/species/jelly/create_pref_blood_perks() diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 85c6a19e34eb..1cd333c24f9e 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -34,7 +34,6 @@ exotic_bloodtype = /datum/blood_type/crew/lizard inert_mutation = /datum/mutation/human/firebreath death_sound = 'sound/voice/lizard/deathsound.ogg' - wing_types = list(/obj/item/organ/external/wings/functional/dragon) species_language_holder = /datum/language_holder/lizard digitigrade_customization = DIGITIGRADE_FORCED //Monkestation Edit: OPTIONAL > FORCED @@ -44,8 +43,6 @@ bodytemp_heat_damage_limit = BODYTEMP_HEAT_LAVALAND_SAFE + 5 KELVIN // This puts lizards 10 above lavaland max heat for ash lizards. bodytemp_cold_damage_limit = (BODYTEMP_COLD_DAMAGE_LIMIT - 10) - ass_image = 'icons/ass/asslizard.png' - bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/lizard, BODY_ZONE_CHEST = /obj/item/bodypart/chest/lizard, @@ -114,7 +111,6 @@ Lizard subspecies: ASHWALKERS id = SPECIES_LIZARD_ASH mutantlungs = /obj/item/organ/internal/lungs/lavaland mutantbrain = /obj/item/organ/internal/brain/primitive - wing_types = list(/obj/item/organ/external/wings/functional/dragon) species_traits = list( MUTCOLORS, MUTCOLORS_SECONDARY, @@ -123,7 +119,6 @@ Lizard subspecies: ASHWALKERS inherent_traits = list( //TRAIT_LITERATE, TRAIT_VIRUSIMMUNE, - TRAIT_HARD_SOLES, //MONKESTATION ADDITION TRAIT_CAN_USE_FLIGHT_POTION, ) species_language_holder = /datum/language_holder/lizard/ash @@ -134,8 +129,8 @@ Lizard subspecies: ASHWALKERS BODY_ZONE_CHEST = /obj/item/bodypart/chest/lizard, BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/lizard/ashwalker, BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/lizard/ashwalker, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/lizard, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/lizard, + BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/lizard/ashwalker, + BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/lizard/ashwalker, ) /* diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index 305ae13576c9..291060630875 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -19,7 +19,6 @@ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT species_language_holder = /datum/language_holder/moth death_sound = 'sound/voice/moth/moth_death.ogg' - wing_types = list(/obj/item/organ/external/wings/functional/moth/megamoth, /obj/item/organ/external/wings/functional/moth/mothra) family_heirlooms = list(/obj/item/flashlight/lantern/heirloom_moth) bodypart_overrides = list( diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index 4ca4dcaeed65..bda9da25e501 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -54,8 +54,6 @@ // This effects how fast body temp stabilizes, also if cold resit is lost on the mob bodytemp_cold_damage_limit = (BODYTEMP_COLD_DAMAGE_LIMIT - 50) // about -50c - ass_image = 'icons/ass/assplasma.png' - outfit_override_registry = list( /datum/outfit/syndicate = /datum/outfit/syndicate/plasmaman, /datum/outfit/syndicate/full = /datum/outfit/syndicate/full/plasmaman, diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index dfbc138d7d7a..d9bd3358c4ef 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -34,8 +34,6 @@ BODY_ZONE_CHEST = /obj/item/bodypart/chest/pod, ) - ass_image = 'icons/ass/asspodperson.png' - /datum/species/pod/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) . = ..() if(H.stat == DEAD) diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm index dcc2cd4b64c3..c238a0bf0648 100644 --- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm +++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm @@ -36,7 +36,6 @@ mutantheart = null mutantliver = /obj/item/organ/internal/liver/bone mutantlungs = null - wing_types = list(/obj/item/organ/external/wings/functional/skeleton) //They can technically be in an ERT changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN species_cookie = /obj/item/reagent_containers/condiment/milk diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 713d2699a4c6..78391d77a03f 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -360,9 +360,9 @@ var/icon/temp_img if(ishuman(ass)) var/mob/living/carbon/human/H = ass - var/datum/species/spec = H.dna.species - if(spec.ass_image) - temp_img = icon(spec.ass_image) + var/obj/item/bodypart/chest/chest = H.get_bodypart(BODY_ZONE_CHEST) + if(chest.ass_image) + temp_img = icon(chest.ass_image) else temp_img = icon(ass.gender == FEMALE ? 'icons/ass/assfemale.png' : 'icons/ass/assmale.png') else if(isalienadult(ass)) //Xenos have their own asses, thanks to Pybro. diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 9af1cccf4b79..8898baf0e620 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -204,6 +204,11 @@ /// If false, no wound that can be applied to us can mangle our interior. Used for determining if we should use [hp_percent_to_dismemberable] instead of normal dismemberment. var/any_existing_wound_can_mangle_our_interior + ///an assoc list of type to % for limbs that share id's useful for traits or components we want to add that should require more than 1 limb being added + var/list/composition_effects + ///a list of different limb_ids that we share composition with + var/list/shared_composition + /obj/item/bodypart/apply_fantasy_bonuses(bonus) . = ..() unarmed_damage_low = modify_fantasy_variable("unarmed_damage_low", unarmed_damage_low, bonus, minimum = 1) @@ -775,6 +780,8 @@ SIGNAL_ADDTRAIT(TRAIT_NOBLOOD), )) UnregisterSignal(old_owner, COMSIG_ATOM_RESTYLE) + UnregisterSignal(old_owner, list(COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB)) + check_removal_composition(old_owner) if(owner) if(length(bodypart_traits)) owner.add_traits(bodypart_traits, bodypart_trait_source) @@ -789,11 +796,13 @@ // Bleeding stuff RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_NOBLOOD), PROC_REF(on_owner_nobleed_loss)) RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOBLOOD), PROC_REF(on_owner_nobleed_gain)) + RegisterSignal(owner, list(COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB), PROC_REF(reassess_body_composition)) if(needs_update_disabled) update_disabled() RegisterSignal(owner, COMSIG_ATOM_RESTYLE, PROC_REF(on_attempt_feature_restyle_mob)) + check_adding_composition(owner) refresh_bleed_rate() return old_owner @@ -803,6 +812,7 @@ return owner.remove_traits(bodypart_traits, bodypart_trait_source) + check_removal_composition(owner) ///Proc to change the value of the `can_be_disabled` variable and react to the event of its change. /obj/item/bodypart/proc/set_can_be_disabled(new_can_be_disabled) @@ -1347,3 +1357,56 @@ /obj/item/bodypart/head/get_soon_dismember_message() return ", threatening to split it open" // we don't sever, we cranial fissure when "dismembered" // we also don't dismember i think + +/obj/item/bodypart/proc/return_compoostion_precent(mob/living/carbon/checker) + var/matching_ids = 0 + for(var/obj/item/bodypart/bodypart as anything in checker.bodyparts) + if((bodypart.limb_id != limb_id) && !(bodypart.limb_id in shared_composition)) + continue + matching_ids++ + + return matching_ids / TOTAL_BODYPART_COUNT + +/obj/item/bodypart/proc/check_removal_composition(mob/living/carbon/remover) + var/precent = return_compoostion_precent(remover) + + for(var/item as anything in composition_effects) + if(composition_effects[item] < precent) + continue + if(!ispath(item)) + REMOVE_TRAIT(remover, item, BODYPART_TRAIT) + else + if(ispath(item, /datum/component)) + var/datum/component/component = remover.GetComponent(item) + if(component) + qdel(component) + else if(ispath(item, /datum/element)) + if(!HasElement(remover, item)) + continue + remover.RemoveElement(item) + +/obj/item/bodypart/proc/check_adding_composition(mob/living/carbon/adder) + var/precent = return_compoostion_precent(adder) + + for(var/item as anything in composition_effects) + if(composition_effects[item] > precent) + continue + if(!ispath(item)) + if(HAS_TRAIT_FROM(adder, item, BODYPART_TRAIT)) + continue + ADD_TRAIT(adder, item, BODYPART_TRAIT) + else + if(ispath(item, /datum/component)) + if(adder.GetComponent(item)) + continue + adder.AddComponent(item) + else if(ispath(item, /datum/element)) + if(HasElement(adder, item)) + continue + adder.AddElement(item) + +/obj/item/bodypart/proc/reassess_body_composition(mob/living/carbon/adder) + SIGNAL_HANDLER + + check_removal_composition(adder) //remove first + check_adding_composition(adder) //then diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index 500437797654..62629e9f805c 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -16,6 +16,8 @@ ///The bodytype(s) allowed to attach to this chest. var/acceptable_bodytype = BODYTYPE_HUMANOID + var/icon/ass_image + var/list/wing_types = list(/obj/item/organ/external/wings/functional/angel) var/obj/item/cavity_item /obj/item/bodypart/chest/can_dismember(obj/item/item) diff --git a/code/modules/surgery/bodyparts/species_parts/android_parts.dm b/code/modules/surgery/bodyparts/species_parts/android_parts.dm index b7a1f55bf43f..cd0f42392935 100644 --- a/code/modules/surgery/bodyparts/species_parts/android_parts.dm +++ b/code/modules/surgery/bodyparts/species_parts/android_parts.dm @@ -10,6 +10,7 @@ /obj/item/bodypart/chest/robot/android change_exempt_flags = null + wing_types = list(/obj/item/organ/external/wings/functional/robotic) /obj/item/bodypart/arm/left/robot/android change_exempt_flags = null diff --git a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm index 4abb67e9f77c..a63870319f20 100644 --- a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm @@ -3,12 +3,15 @@ limb_id = SPECIES_LIZARD is_dimorphic = FALSE head_flags = HEAD_HAIR| HEAD_EYESPRITES | HEAD_EYEHOLES | HEAD_DEBRAIN | HEAD_EYECOLOR + composition_effects = list(TRAIT_COLD_BLOODED = 0.5) /obj/item/bodypart/chest/lizard icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' limb_id = SPECIES_LIZARD is_dimorphic = FALSE - bodypart_traits = list(TRAIT_COLD_BLOODED) + ass_image = 'icons/ass/asslizard.png' + composition_effects = list(TRAIT_COLD_BLOODED = 0.5) + wing_types = list(/obj/item/organ/external/wings/functional/dragon) /obj/item/bodypart/arm/left/lizard icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' @@ -17,6 +20,7 @@ unarmed_attack_effect = ATTACK_EFFECT_CLAW unarmed_attack_sound = 'sound/weapons/slash.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + composition_effects = list(TRAIT_COLD_BLOODED = 0.5) /obj/item/bodypart/arm/right/lizard icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' @@ -25,6 +29,7 @@ unarmed_attack_effect = ATTACK_EFFECT_CLAW unarmed_attack_sound = 'sound/weapons/slash.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + composition_effects = list(TRAIT_COLD_BLOODED = 0.5) /obj/item/bodypart/arm/left/lizard/ashwalker bodypart_traits = list(TRAIT_CHUNKYFINGERS) @@ -38,6 +43,7 @@ can_be_digitigrade = TRUE digitigrade_id = "digitigrade" footprint_sprite = FOOTPRINT_SPRITE_CLAWS + composition_effects = list(TRAIT_COLD_BLOODED = 0.5) /obj/item/bodypart/leg/right/lizard icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' @@ -45,3 +51,10 @@ can_be_digitigrade = TRUE digitigrade_id = "digitigrade" footprint_sprite = FOOTPRINT_SPRITE_CLAWS + composition_effects = list(TRAIT_COLD_BLOODED = 0.5) + +/obj/item/bodypart/leg/right/lizard/ashwalker + bodypart_traits = list(TRAIT_HARD_SOLES) + +/obj/item/bodypart/leg/left/lizard/ashwalker + bodypart_traits = list(TRAIT_HARD_SOLES) diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index fa2674247416..493bd808f2da 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -51,6 +51,7 @@ limb_id = SPECIES_ABDUCTOR is_dimorphic = FALSE should_draw_greyscale = FALSE + ass_image = 'icons/ass/assgrey.png' /obj/item/bodypart/arm/left/abductor limb_id = SPECIES_ABDUCTOR @@ -77,32 +78,40 @@ is_dimorphic = TRUE dmg_overlay_type = null head_flags = HEAD_ALL_FEATURES + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/chest/jelly biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_JELLYPERSON is_dimorphic = TRUE dmg_overlay_type = null + composition_effects = list(/datum/element/soft_landing = 0.5) + ass_image = 'icons/ass/assslime.png' + wing_types = list(/obj/item/organ/external/wings/functional/slime) /obj/item/bodypart/arm/left/jelly biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/arm/right/jelly biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/leg/left/jelly biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/leg/right/jelly biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null + composition_effects = list(/datum/element/soft_landing = 0.5) ///SLIME /obj/item/bodypart/head/slime @@ -110,27 +119,33 @@ limb_id = SPECIES_SLIMEPERSON is_dimorphic = FALSE head_flags = HEAD_ALL_FEATURES + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/chest/slime biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_SLIMEPERSON is_dimorphic = TRUE + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/arm/left/slime biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_SLIMEPERSON + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/arm/right/slime biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_SLIMEPERSON + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/leg/left/slime biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_SLIMEPERSON + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/leg/right/slime biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_SLIMEPERSON + composition_effects = list(/datum/element/soft_landing = 0.5) ///LUMINESCENT /obj/item/bodypart/head/luminescent @@ -165,28 +180,33 @@ is_dimorphic = FALSE should_draw_greyscale = FALSE head_flags = HEAD_EYESPRITES | HEAD_DEBRAIN | HEAD_HAIR + composition_effects = list(TRAIT_COLD_BLOODED = 0.5) /obj/item/bodypart/chest/zombie limb_id = SPECIES_ZOMBIE is_dimorphic = FALSE should_draw_greyscale = FALSE - bodypart_traits = list(TRAIT_COLD_BLOODED) + composition_effects = list(TRAIT_COLD_BLOODED = 0.5) /obj/item/bodypart/arm/left/zombie limb_id = SPECIES_ZOMBIE should_draw_greyscale = FALSE + composition_effects = list(TRAIT_COLD_BLOODED = 0.5) /obj/item/bodypart/arm/right/zombie limb_id = SPECIES_ZOMBIE should_draw_greyscale = FALSE + composition_effects = list(TRAIT_COLD_BLOODED = 0.5) /obj/item/bodypart/leg/left/zombie limb_id = SPECIES_ZOMBIE should_draw_greyscale = FALSE + composition_effects = list(TRAIT_COLD_BLOODED = 0.5) /obj/item/bodypart/leg/right/zombie limb_id = SPECIES_ZOMBIE should_draw_greyscale = FALSE + composition_effects = list(TRAIT_COLD_BLOODED = 0.5) ///PODPEOPLE /obj/item/bodypart/head/pod @@ -196,6 +216,7 @@ /obj/item/bodypart/chest/pod limb_id = SPECIES_PODPERSON is_dimorphic = TRUE + ass_image = 'icons/ass/asspodperson.png' /obj/item/bodypart/arm/left/pod limb_id = SPECIES_PODPERSON @@ -228,6 +249,7 @@ limb_id = SPECIES_FLYPERSON is_dimorphic = TRUE should_draw_greyscale = FALSE + wing_types = list(/obj/item/organ/external/wings/functional/fly) /obj/item/bodypart/arm/left/fly limb_id = SPECIES_FLYPERSON @@ -294,6 +316,7 @@ is_dimorphic = FALSE should_draw_greyscale = FALSE dmg_overlay_type = null + wing_types = list(/obj/item/organ/external/wings/functional/skeleton) /obj/item/bodypart/arm/left/skeleton biological_state = (BIO_BONE|BIO_JOINTED) diff --git a/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm index f0fc78f83f0b..5c0de35b4571 100644 --- a/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm @@ -14,6 +14,7 @@ limb_id = SPECIES_MOTH is_dimorphic = TRUE should_draw_greyscale = FALSE + wing_types = list(/obj/item/organ/external/wings/functional/moth/megamoth, /obj/item/organ/external/wings/functional/moth/mothra) /obj/item/bodypart/arm/left/moth icon = 'icons/mob/species/moth/bodyparts.dmi' diff --git a/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm index fad07868ea04..350a9ca55118 100644 --- a/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm @@ -18,6 +18,7 @@ is_dimorphic = FALSE should_draw_greyscale = FALSE dmg_overlay_type = null + ass_image = 'icons/ass/assplasma.png' /obj/item/bodypart/arm/left/plasmaman icon = 'icons/mob/species/plasmaman/bodyparts.dmi' diff --git a/code/modules/surgery/organs/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/stomach/stomach_ethereal.dm index 9f29c370f9d7..fd0b0e1a2a40 100644 --- a/code/modules/surgery/organs/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/stomach/stomach_ethereal.dm @@ -11,7 +11,7 @@ /obj/item/organ/internal/stomach/ethereal/on_life(seconds_per_tick, times_fired) . = ..() - adjust_charge(-ETHEREAL_CHARGE_FACTOR * seconds_per_tick) + adjust_charge(-ETHEREAL_CHARGE_FACTOR * seconds_per_tick * 0.5) handle_charge(owner, seconds_per_tick, times_fired) @@ -39,10 +39,7 @@ /obj/item/organ/internal/stomach/ethereal/proc/handle_temp(mob/living/carbon/human/human, natural_change, seconds_per_tick) SIGNAL_HANDLER - if(human.blood_volume < (ETHEREAL_CHARGE_ALMOSTFULL)) - return HOMEOSTASIS_HANDLED - - adjust_charge(-1 * ETHEREAL_CHARGE_FACTOR * abs(natural_change) * seconds_per_tick) + adjust_charge(-1 * ETHEREAL_CHARGE_FACTOR * abs(natural_change) * seconds_per_tick * 0.05) return HOMEOSTASIS_NO_HUNGER /obj/item/organ/internal/stomach/ethereal/proc/blood(mob/living/carbon/human/ethereal, seconds_per_tick, times_fired) @@ -53,7 +50,7 @@ . = HANDLE_BLOOD_NO_NUTRITION_DRAIN|HANDLE_BLOOD_NO_EFFECTS - INVOKE_ASYNC(src, PROC_REF(adjust_charge),-ETHEREAL_BLOOD_CHARGE_FACTOR * seconds_per_tick, TRUE) + INVOKE_ASYNC(src, PROC_REF(adjust_charge),-ETHEREAL_BLOOD_CHARGE_FACTOR * seconds_per_tick * 0.1, TRUE) INVOKE_ASYNC(src, PROC_REF(handle_charge), ethereal, seconds_per_tick, times_fired) return . diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm index 327d263b79c5..2f7ded1d0389 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm @@ -12,6 +12,11 @@ /obj/item/organ/external/tail/ethereal = "None") exotic_bloodtype = /datum/blood_type/crew/ethereal + // Body temperature for ethereals is much higher then humans as they like hotter environments + bodytemp_normal = (BODYTEMP_NORMAL + 50) + temperature_homeostasis_speed = 3 + temperature_normalization_speed = 3 + siemens_coeff = 0.5 //They thrive on energy brutemod = 1.25 //They're weak to punches payday_modifier = 1 @@ -26,8 +31,7 @@ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_cookie = /obj/item/food/energybar species_language_holder = /datum/language_holder/ethereal - // Body temperature for ethereals is much higher then humans as they like hotter environments - bodytemp_normal = (BODYTEMP_NORMAL + 50) + bodytemp_heat_damage_limit = FIRE_MINIMUM_TEMPERATURE_TO_SPREAD // about 150C // Cold temperatures hurt faster as it is harder to move with out the heat energy bodytemp_cold_damage_limit = (T20C - 10) // about 10c diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm index 7aa957093039..5f4eee99a967 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm @@ -40,8 +40,6 @@ mutanteyes = /obj/item/organ/internal/eyes/floran mutantheart = /obj/item/organ/internal/heart/pod - ass_image = 'icons/ass/asspodperson.png' - /datum/species/floran/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) . = ..() if(H.stat == DEAD) diff --git a/monkestation/code/modules/smithing/oozelings/body/bodyparts.dm b/monkestation/code/modules/smithing/oozelings/body/bodyparts.dm index 8a34125875ff..605c58fad0e6 100644 --- a/monkestation/code/modules/smithing/oozelings/body/bodyparts.dm +++ b/monkestation/code/modules/smithing/oozelings/body/bodyparts.dm @@ -5,6 +5,7 @@ biological_state = BIO_INORGANIC dmg_overlay_type = null + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/chest/oozeling icon_greyscale = 'monkestation/icons/mob/species/oozeling/bodyparts.dmi' @@ -13,6 +14,9 @@ biological_state = BIO_INORGANIC dmg_overlay_type = null + composition_effects = list(/datum/element/soft_landing = 0.5) + ass_image = 'icons/ass/assslime.png' + wing_types = list(/obj/item/organ/external/wings/functional/slime) /obj/item/bodypart/arm/left/oozeling icon_greyscale = 'monkestation/icons/mob/species/oozeling/bodyparts.dmi' @@ -20,11 +24,13 @@ biological_state = BIO_INORGANIC dmg_overlay_type = null + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/arm/right/oozeling icon_greyscale = 'monkestation/icons/mob/species/oozeling/bodyparts.dmi' limb_id = SPECIES_OOZELING biological_state = BIO_INORGANIC + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/leg/left/oozeling icon_greyscale = 'monkestation/icons/mob/species/oozeling/bodyparts.dmi' @@ -32,6 +38,7 @@ biological_state = BIO_INORGANIC dmg_overlay_type = null + composition_effects = list(/datum/element/soft_landing = 0.5) /obj/item/bodypart/leg/right/oozeling icon_greyscale = 'monkestation/icons/mob/species/oozeling/bodyparts.dmi' @@ -39,3 +46,4 @@ biological_state = BIO_INORGANIC dmg_overlay_type = null + composition_effects = list(/datum/element/soft_landing = 0.5) diff --git a/monkestation/code/modules/smithing/oozelings/species.dm b/monkestation/code/modules/smithing/oozelings/species.dm index 6b9fd24bfb3a..7aa8ecdc3fa9 100644 --- a/monkestation/code/modules/smithing/oozelings/species.dm +++ b/monkestation/code/modules/smithing/oozelings/species.dm @@ -35,9 +35,7 @@ heatmod = 0.5 // = 1/4x heat damage inherent_factions = list(FACTION_SLIME) //an oozeling wont be eaten by their brethren species_language_holder = /datum/language_holder/oozeling - ass_image = 'icons/ass/assslime.png' //swimming_component = /datum/component/swimming/dissolve - wing_types = list(/obj/item/organ/external/wings/functional/slime) bodypart_overrides = list( BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/oozeling, diff --git a/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm b/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm index e4e3044bb0a4..a878fb01d8cc 100644 --- a/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm +++ b/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm @@ -8,6 +8,7 @@ icon_greyscale = 'monkestation/icons/mob/species/floran/bodyparts.dmi' limb_id = SPECIES_FLORAN is_dimorphic = TRUE + ass_image = 'icons/ass/asspodperson.png' /obj/item/bodypart/arm/left/floran icon_greyscale = 'monkestation/icons/mob/species/floran/bodyparts.dmi' diff --git a/monkestation/code/modules/temperature_overhaul/temperature_proc.dm b/monkestation/code/modules/temperature_overhaul/temperature_proc.dm index 6aa07f576da1..574604cb6247 100644 --- a/monkestation/code/modules/temperature_overhaul/temperature_proc.dm +++ b/monkestation/code/modules/temperature_overhaul/temperature_proc.dm @@ -104,26 +104,18 @@ // calculate skin temp based on a weight average between body temp and area temp plus a multiplier // this weighting gives us about 34.4c for a 37c body temp in a 20c room which is about average - var/area_weight = 1 - get_insulation(area_temperature) - var/skin_temp = ((bodytemperature * 2 + area_temperature * area_weight) / (3 - get_insulation(area_temperature))) - // convert to kelvin before multiplying, otherwise we go to the moon - var/result = KELVIN_TO_CELCIUS(skin_temp) - var/multiplier = 1.1 - // factor in insulation, but to a far lesser degree - // wearing a winter coat in a room temp area will increase skin temp to about 38.3c - - if(!HAS_TRAIT(src, TRAIT_COLD_BLOODED)) + var/insulation = get_insulation(area_temperature) + // converting to celcius as it's easier to work with / multiply on + var/skin_temp = 1.1 * ((KELVIN_TO_CELCIUS(bodytemperature) * 2 + KELVIN_TO_CELCIUS(area_temperature) * (1 - insulation)) / (3 - insulation)) + + if(temperature_homeostasis_speed != 0) // not cold blooded if(bodytemperature >= standard_body_temperature + 2 CELCIUS) - multiplier *= 1.1 // vasodilation / sweating + skin_temp *= 1.1 // vasodilation / sweating if(bodytemperature <= standard_body_temperature + ((bodytemp_cold_damage_limit - standard_body_temperature) * 0.5)) - multiplier *= 0.9 // vasoconstriction - - // reverse the effect of insulation if we're subzero - // (otherwise, wearing a coat makes you colder) - if(result < 0) - multiplier = 1 / multiplier + skin_temp *= 0.9 // vasoconstriction - . = CELCIUS_TO_KELVIN(result * multiplier) + // back to kelvin + . = CELCIUS_TO_KELVIN(skin_temp) // and if we're on fire just add a flat amount of heat if(on_fire) . += fire_stacks ** 2 KELVIN diff --git a/monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm b/monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm index e5c00dab506e..0a47f64e4b80 100644 --- a/monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm +++ b/monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm @@ -40,7 +40,7 @@ dmg_overlay_type = null biological_state = (BIO_FLESH|BIO_BLOODED) bodypart_traits = list(TRAIT_NO_JUMPSUIT, TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_PUSHIMMUNE, TRAIT_STUNIMMUNE) - //wing_types = NONE + wing_types = null /obj/item/bodypart/arm/left/werewolf limb_id = SPECIES_WEREWOLF From 64b5a798973098c82c151f1cb3911aca7a1ef247 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 11:34:22 -0700 Subject: [PATCH 074/158] Update species.dm --- monkestation/code/modules/smithing/ipcs/species.dm | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/monkestation/code/modules/smithing/ipcs/species.dm b/monkestation/code/modules/smithing/ipcs/species.dm index bef0ad2ba95a..91e2f74ffbb4 100644 --- a/monkestation/code/modules/smithing/ipcs/species.dm +++ b/monkestation/code/modules/smithing/ipcs/species.dm @@ -123,6 +123,17 @@ RegisterSignal(C, COMSIG_LIVING_DEATH, PROC_REF(bsod_death)) // screen displays bsod on death, if they have one RegisterSignal(C.reagents, COMSIG_REAGENTS_ADD_REAGENT, PROC_REF(will_it_blend)) + RegisterSignal(C, COMSIG_HUMAN_ON_HANDLE_BLOOD, PROC_REF(blood_handled)) + +/datum/species/ipc/proc/blood_handled(mob/living/carbon/human/slime, seconds_per_tick, times_fired) + SIGNAL_HANDLER + + if(slime.stat == DEAD) + return NONE + + if(slime.blood_volume >= BLOOD_VOLUME_OKAY) + + slime.adjustOxyLoss(-3) /datum/species/ipc/proc/will_it_blend(datum/reagents/holder, ...) var/mob/living/carbon/carbon = holder.my_atom From abf4c8932b71a8f06050e82fe86057071012f529 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 12:21:29 -0700 Subject: [PATCH 075/158] Update species.dm --- monkestation/code/modules/smithing/ipcs/species.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/monkestation/code/modules/smithing/ipcs/species.dm b/monkestation/code/modules/smithing/ipcs/species.dm index 91e2f74ffbb4..b5474d09eda4 100644 --- a/monkestation/code/modules/smithing/ipcs/species.dm +++ b/monkestation/code/modules/smithing/ipcs/species.dm @@ -131,7 +131,8 @@ if(slime.stat == DEAD) return NONE - if(slime.blood_volume >= BLOOD_VOLUME_OKAY) + if(slime.blood_volume < BLOOD_VOLUME_OKAY) + return NONE slime.adjustOxyLoss(-3) From 31139f058017115590064a1541a60bce9d5a90a5 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 12:31:40 -0700 Subject: [PATCH 076/158] Update species.dm --- monkestation/code/modules/smithing/oozelings/species.dm | 3 --- 1 file changed, 3 deletions(-) diff --git a/monkestation/code/modules/smithing/oozelings/species.dm b/monkestation/code/modules/smithing/oozelings/species.dm index 7aa8ecdc3fa9..07b0738d0822 100644 --- a/monkestation/code/modules/smithing/oozelings/species.dm +++ b/monkestation/code/modules/smithing/oozelings/species.dm @@ -120,8 +120,6 @@ if(slime.stat != CONSCIOUS) return - var/healing = TRUE - var/datum/status_effect/fire_handler/wet_stacks/wetness = locate() in slime.status_effects if(HAS_TRAIT(slime, TRAIT_SLIME_HYDROPHOBIA)) return @@ -131,7 +129,6 @@ slime.visible_message(span_danger("[slime]'s form begins to lose cohesion, seemingly diluting with the water!"), span_warning("The water starts to dilute your body, dry it off!")) if(istype(wetness) && wetness.stacks > (REGEN_WATER_STACKS)) - healing = FALSE if (SPT_PROB(25, seconds_per_tick)) to_chat(slime, span_warning("You can't pull your body together and regenerate with water inside it!")) slime.blood_volume -= 1 * seconds_per_tick From 2de04af41397b0d8f4069b75446a3a663b3e02dd Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 18:01:31 -0700 Subject: [PATCH 077/158] Update stomach_ethereal.dm --- code/modules/surgery/organs/stomach/stomach_ethereal.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/surgery/organs/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/stomach/stomach_ethereal.dm index fd0b0e1a2a40..50592dc64840 100644 --- a/code/modules/surgery/organs/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/stomach/stomach_ethereal.dm @@ -156,7 +156,7 @@ playsound(ethereal, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) ethereal.cut_overlay(overcharge) tesla_zap(ethereal, 2, ethereal.blood_volume*9, ZAP_OBJ_DAMAGE | ZAP_GENERATES_POWER | ZAP_ALLOW_DUPLICATES) - adjust_charge(ethereal, ETHEREAL_BLOOD_CHARGE_FULL - ethereal.blood_volume) + adjust_charge(ETHEREAL_BLOOD_CHARGE_FULL - ethereal.blood_volume) ethereal.visible_message(span_danger("[ethereal] violently discharges energy!"), span_warning("You violently discharge energy!")) ethereal.Paralyze(100) From 8fccd7fad7e7a173d46f8c4b4ac185d4e614981d Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:18:08 -0700 Subject: [PATCH 078/158] fixes --- code/__DEFINES/DNA.dm | 16 ++++----- code/__DEFINES/sprite_accessories.dm | 6 ++++ code/__DEFINES/traits/declarations.dm | 20 +++++++---- code/_globalvars/traits/_traits.dm | 1 - code/datums/components/bloodysoles.dm | 2 +- code/datums/dna.dm | 5 +++ code/datums/quirks/negative_quirks.dm | 2 +- code/game/objects/structures/dresser.dm | 4 +-- code/game/objects/structures/mirror.dm | 4 +-- .../abductor/equipment/glands/heal.dm | 2 +- .../antagonists/changeling/changeling.dm | 2 +- .../nightmare/nightmare_species.dm | 8 ++--- .../modules/client/preferences/_preference.dm | 11 ++++-- code/modules/client/preferences/clothing.dm | 12 +++++-- code/modules/client/preferences/skin_tone.dm | 15 +++----- code/modules/client/preferences/species.dm | 2 +- .../preferences/species_features/mutants.dm | 10 +++++- .../preferences/species_features/vampire.dm | 5 +-- .../client/preferences/underwear_color.dm | 2 +- code/modules/mining/lavaland/tendril_loot.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 2 +- .../mob/living/carbon/human/_species.dm | 34 ++++++------------ .../mob/living/carbon/human/examine.dm | 2 +- .../carbon/human/species_types/abductors.dm | 4 +-- .../carbon/human/species_types/android.dm | 11 +++--- .../carbon/human/species_types/dullahan.dm | 3 +- .../carbon/human/species_types/flypeople.dm | 1 - .../carbon/human/species_types/golems.dm | 25 ++++++------- .../carbon/human/species_types/humans.dm | 6 ++-- .../carbon/human/species_types/jellypeople.dm | 11 +++--- .../human/species_types/lizardpeople.dm | 15 ++++---- .../carbon/human/species_types/monkeys.dm | 10 +++--- .../carbon/human/species_types/mothmen.dm | 5 +-- .../carbon/human/species_types/mushpeople.dm | 7 ++-- .../carbon/human/species_types/plasmamen.dm | 4 +-- .../carbon/human/species_types/podpeople.dm | 4 +-- .../human/species_types/shadowpeople.dm | 1 - .../carbon/human/species_types/skeletons.dm | 13 +++---- .../carbon/human/species_types/snail.dm | 6 ++-- .../carbon/human/species_types/vampire.dm | 9 ++--- .../carbon/human/species_types/zombies.dm | 10 +++--- .../mob/living/carbon/human/status_procs.dm | 2 +- .../modules/mob/living/carbon/init_signals.dm | 9 +++-- code/modules/mob/living/carbon/life.dm | 2 +- .../chemistry/reagents/drug_reagents.dm | 14 ++------ .../chemistry/reagents/other_reagents.dm | 6 ++-- .../modules/spells/spell_types/self/mutate.dm | 4 +-- code/modules/surgery/bodyparts/_bodyparts.dm | 25 +++++-------- code/modules/surgery/limb_augmentation.dm | 2 +- .../surgery/organs/internal/liver/_liver.dm | 22 +++++------- .../organs/internal/liver/liver_skeleton.dm | 2 +- code/modules/zombie/items.dm | 2 +- config/config.txt | 2 +- .../code/game/machinery/computer/cloning.dm | 3 +- .../slasher/abilities/soul_steal.dm | 2 +- .../bloodsucker/bloodsucker_datum.dm | 8 ++--- .../modules/botany/species/apid/species.dm | 9 +---- .../preferences/species_features/ethereal.dm | 4 +-- .../species_features/secondary_mut_color.dm | 10 +++++- .../preferences/species_features/simians.dm | 4 +-- .../new_player/sprite_accessories/anime.dm | 8 ++--- .../sprite_accessories/arachnid_appendages.dm | 2 +- .../sprite_accessories/arachnid_chelicerae.dm | 2 +- .../sprite_accessories/ethereal_horns.dm | 2 +- .../sprite_accessories/ethereal_tail.dm | 2 +- .../sprite_accessories/floran_leaves.dm | 2 +- .../sprite_accessories/goblin_accessories.dm | 2 +- .../sprite_accessories/ipc_antenna.dm | 4 +-- .../sprite_accessories/ipc_chassis.dm | 2 +- .../sprite_accessories/multi_part.dm | 2 +- .../sprite_accessories/sock_color.dm | 2 +- .../new_player/sprite_accessories/tails.dm | 2 +- .../carbon/human/species_type/arachnid.dm | 4 +-- .../carbon/human/species_type/ethereal.dm | 7 ++-- .../carbon/human/species_type/floran.dm | 8 ++--- .../carbon/human/species_type/goblin.dm | 4 +-- .../carbon/human/species_type/simian.dm | 10 ++---- .../carbon/human/species_type/skeletons.dm | 10 +++--- .../modules/ranching/icons/satyr_tail.dmi | Bin 318 -> 319 bytes .../ranching/satyr/accessories/prefs.dm | 2 +- .../modules/ranching/satyr/external_organs.dm | 2 +- .../code/modules/ranching/satyr/species.dm | 7 ++-- .../code/modules/smithing/ipcs/species.dm | 10 ++---- .../modules/smithing/oozelings/species.dm | 6 ++-- .../organs/external/ethereal_accessories.dm | 2 +- .../the_bird_inside_of_me/icons/armwings.dmi | Bin 7401 -> 14979 bytes .../modules/the_bird_inside_of_me/prefs.dm | 2 +- .../modules/the_bird_inside_of_me/species.dm | 6 ++-- .../modules/the_wolf_inside_of_me/species.dm | 5 +-- monkestation/icons/mob/anime/anime_bottom.dmi | Bin 5747 -> 5713 bytes monkestation/icons/mob/anime/anime_head.dmi | Bin 1758 -> 1770 bytes .../icons/mob/anime/anime_head32x48.dmi | Bin 954 -> 958 bytes monkestation/icons/mob/anime/anime_middle.dmi | Bin 7710 -> 7828 bytes .../mob/species/ethereal/ethereal_horns.dmi | Bin 1817 -> 1605 bytes .../mob/species/ethereal/ethereal_tail.dmi | Bin 1417 -> 1470 bytes .../icons/mob/species/ipc/ipc_antennas.dmi | Bin 2906 -> 3184 bytes .../icons/mob/species/simian/tails.dmi | Bin 6609 -> 6657 bytes 97 files changed, 245 insertions(+), 318 deletions(-) diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index a93b10eebd68..894288b712ed 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -73,6 +73,7 @@ //species traits for mutantraces +/* #define MUTCOLORS 1 #define NOTRANSSTING 2 #define NOZOMBIE 3 @@ -83,24 +84,21 @@ #define MUTCOLORS_SECONDARY 8 #define SPECIES_FUR 9 #define SKINTONES 10 +*/ /// Use this if you want to change the race's color without the player being able to pick their own color. AKA special color shifting #define DYNCOLORS 7 #define AGENDER 8 -/// Do not draw eyes or eyeless overlay -#define NOEYESPRITES 9 ///If we have a limb-specific overlay sprite -#define HAS_MARKINGS 10 +#define HAS_MARKINGS 9 /// Do not draw blood overlay -#define NOBLOODOVERLAY 11 +#define NOBLOODOVERLAY 10 ///No augments, for monkeys in specific because they will turn into fucking freakazoids https://cdn.discordapp.com/attachments/326831214667235328/791313258912153640/102707682-fa7cad80-4294-11eb-8f13-8c689468aeb0.png -#define NOAUGMENTS 12 +#define NOAUGMENTS 11 ///will be assigned a universal vampire themed last name shared by their department. this is preferenced! -#define BLOOD_CLANS 13 +#define BLOOD_CLANS 12 -#define REVIVESBYHEALING 14 -#define NOHUSK 15 -#define NOMOUTH 16 +#define REVIVESBYHEALING 13 //organ slots #define ORGAN_SLOT_ADAMANTINE_RESONATOR "adamantine_resonator" diff --git a/code/__DEFINES/sprite_accessories.dm b/code/__DEFINES/sprite_accessories.dm index 9c9471130e6f..d4cfb7ca5d57 100644 --- a/code/__DEFINES/sprite_accessories.dm +++ b/code/__DEFINES/sprite_accessories.dm @@ -7,3 +7,9 @@ #define FACIAL_HAIR_COLOR "facial_hair_color" /// Color of the sprite accessory will match the owner's (left) eye color #define EYE_COLOR "eye_color" + +#define SKIN_COLOR "skin_color" + +#define MUTANT_COLOR_SECONDARY "mutant_color_secondary" + +#define ANIME_COLOR "anime_color" diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index b5f031f5d95b..db1506f1be9b 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -147,39 +147,44 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Species with this trait are genderless #define TRAIT_AGENDER "agender" /// Species with this trait have a blood clan mechanic -/* #define TRAIT_BLOOD_CLANS "blood_clans" */ +#define TRAIT_BLOOD_CLANS "blood_clans" +/// Species with this trait have markings (this SUCKS, remove this later in favor of bodypart overlays) +#define TRAIT_HAS_MARKINGS "has_markings" /// Species with this trait use skin tones for coloration #define TRAIT_USES_SKINTONES "uses_skintones" /// Species with this trait use mutant colors for coloration #define TRAIT_MUTANT_COLORS "mutcolors" +/// Species with this trait use mutant colors for coloration +#define TRAIT_MUTANT_COLORS_SECONDARY "mutcolors_secondary" /// Species with this trait have mutant colors that cannot be chosen by the player, nor altered ingame by external means #define TRAIT_FIXED_MUTANT_COLORS "fixed_mutcolors" /// Humans with this trait won't get bloody hands, nor bloody feet -/* #define TRAIT_NO_BLOOD_OVERLAY "no_blood_overlay" */ +#define TRAIT_NO_BLOOD_OVERLAY "no_blood_overlay" /// Humans with this trait cannot have underwear #define TRAIT_NO_UNDERWEAR "no_underwear" /// This carbon doesn't show an overlay when they have no brain -/* #define TRAIT_NO_DEBRAIN_OVERLAY "no_debrain_overlay" */ +#define TRAIT_FUR_COLORS "trait_fur_colors" /// Humans with this trait cannot get augmentation surgery #define TRAIT_NO_AUGMENTS "no_augments" /// This carbon doesn't get hungry #define TRAIT_NOHUNGER "no_hunger" /// This carbon doesn't metabolize reagents. -#define TRAIT_NOMETABOLISM "no_metabolism" /// This carbon doesn't bleed #define TRAIT_NOBLOOD "noblood" /// This just means that the carbon will always have functional liverless metabolism #define TRAIT_LIVERLESS_METABOLISM "liverless_metabolism" +/// Humans with this trait cannot be affected by changeling transformation stings +#define TRAIT_NO_TRANSFORMATION_STING "no_transformation_sting" /// This carbon can't be overdosed by chems -/* #define TRAIT_OVERDOSEIMMUNE "overdose_immune" */ +#define TRAIT_OVERDOSEIMMUNE "overdose_immune" /// Humans with this trait cannot be turned into zombies #define TRAIT_NO_ZOMBIFY "no_zombify" /// Carbons with this trait can't have their DNA copied by diseases nor changelings #define TRAIT_NO_DNA_COPY "no_dna_copy" /// Carbons with this trait cant have their dna scrambled by genetics or a disease retrovirus. -/* #define TRAIT_NO_DNA_SCRAMBLE "no_dna_scramble" */ +#define TRAIT_NO_DNA_SCRAMBLE "no_dna_scramble" /// Carbons with this trait can eat blood to regenerate their own blood volume, instead of injecting it -/* #define TRAIT_DRINKS_BLOOD "drinks_blood" */ +#define TRAIT_DRINKS_BLOOD "drinks_blood" /// Mob is immune to clone (cellular) damage #define TRAIT_NOCLONELOSS "no_cloneloss" /// Mob is immune to toxin damage @@ -196,6 +201,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_EASILY_WOUNDED "easy_limb_wound" #define TRAIT_HARDLY_WOUNDED "hard_limb_wound" #define TRAIT_NEVER_WOUNDED "never_wounded" +#define TRAIT_NO_HUSK "no_husk" /// Species with this trait have 50% extra chance of bleeding from piercing and slashing wounds /* #define TRAIT_EASYBLEED "easybleed" */ #define TRAIT_TOXINLOVER "toxinlover" diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 763f00fa9caa..dae0b5ee1fde 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -340,7 +340,6 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_NOHARDCRIT" = TRAIT_NOHARDCRIT, "TRAIT_NOHUNGER" = TRAIT_NOHUNGER, "TRAIT_NOLIMBDISABLE" = TRAIT_NOLIMBDISABLE, - "TRAIT_NOMETABOLISM" = TRAIT_NOMETABOLISM, "TRAIT_NOMOBSWAP" = TRAIT_NOMOBSWAP, "TRAIT_NOSELFIGNITION_HEAD_ONLY" = TRAIT_NOSELFIGNITION_HEAD_ONLY, "TRAIT_NOSOFTCRIT" = TRAIT_NOSOFTCRIT, diff --git a/code/datums/components/bloodysoles.dm b/code/datums/components/bloodysoles.dm index 0e7635d9174b..b2e98144d536 100644 --- a/code/datums/components/bloodysoles.dm +++ b/code/datums/components/bloodysoles.dm @@ -250,7 +250,7 @@ RegisterSignal(parent, COMSIG_CARBON_EQUIP_SHOECOVER, PROC_REF(equip_shoecover)) /datum/component/bloodysoles/feet/update_icon() - if(!ishuman(wielder)) + if(!ishuman(wielder) || HAS_TRAIT(wielder, TRAIT_NO_BLOOD_OVERLAY)) return wielder.remove_overlay(SHOES_LAYER) if(total_bloodiness > 0 && !is_obscured()) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 935f68e9595a..111b07f5f966 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -595,6 +595,11 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) if(!has_dna()) return + //Always plural gender if agender + if(HAS_TRAIT(src, TRAIT_AGENDER)) + gender = PLURAL + return + switch(deconstruct_block(get_uni_identity_block(dna.unique_identity, DNA_GENDER_BLOCK), 3)) if(G_MALE) gender = MALE diff --git a/code/datums/quirks/negative_quirks.dm b/code/datums/quirks/negative_quirks.dm index cb22e6e0118e..f10307b0fae2 100644 --- a/code/datums/quirks/negative_quirks.dm +++ b/code/datums/quirks/negative_quirks.dm @@ -874,7 +874,7 @@ quirk_holder.mind.remove_addiction_points(addiction_type, MAX_ADDICTION_POINTS) /datum/quirk/item_quirk/junkie/process(seconds_per_tick) - if(HAS_TRAIT(quirk_holder, TRAIT_NOMETABOLISM)) + if(HAS_TRAIT(quirk_holder, TRAIT_LIVERLESS_METABOLISM)) return var/mob/living/carbon/human/human_holder = quirk_holder if(world.time > next_process) diff --git a/code/game/objects/structures/dresser.dm b/code/game/objects/structures/dresser.dm index fcc62fb834f6..67e1c896bd25 100644 --- a/code/game/objects/structures/dresser.dm +++ b/code/game/objects/structures/dresser.dm @@ -31,8 +31,8 @@ return var/mob/living/carbon/human/dressing_human = user - if(dressing_human.dna && dressing_human.dna.species && (NO_UNDERWEAR in dressing_human.dna.species.species_traits)) - to_chat(user, span_warning("You are not capable of wearing underwear.")) + if(HAS_TRAIT(dressing_human, TRAIT_NO_UNDERWEAR)) + to_chat(dressing_human, span_warning("You are not capable of wearing underwear.")) return var/choice = tgui_input_list(user, "Underwear, Undershirt, or Socks?", "Changing", list("Underwear","Underwear Color","Undershirt","Socks", "Socks Color")) //MONKESTATION EDIT diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index fbf2ad8e2815..dfba667ce4b8 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -212,13 +212,13 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror, 28) var/datum/species/newrace = selectable_races[racechoice] amazed_human.set_species(newrace, icon_update = FALSE) - if(amazed_human.dna.species.use_skintones) + if(HAS_TRAIT(amazed_human, TRAIT_USES_SKINTONES)) var/new_s_tone = tgui_input_list(user, "Choose your skin tone", "Race change", GLOB.skin_tones) if(new_s_tone) amazed_human.skin_tone = new_s_tone amazed_human.dna.update_ui_block(DNA_SKIN_TONE_BLOCK) - if(MUTCOLORS in amazed_human.dna.species.species_traits) + else if(HAS_TRAIT(amazed_human, TRAIT_MUTANT_COLORS) && !HAS_TRAIT(amazed_human, TRAIT_FIXED_MUTANT_COLORS)) var/new_mutantcolor = tgui_color_picker(user, "Choose your skin color:", "Race change", amazed_human.dna.features["mcolor"]) if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return TRUE diff --git a/code/modules/antagonists/abductor/equipment/glands/heal.dm b/code/modules/antagonists/abductor/equipment/glands/heal.dm index 9be6245d91f0..90b6e9865a9c 100644 --- a/code/modules/antagonists/abductor/equipment/glands/heal.dm +++ b/code/modules/antagonists/abductor/equipment/glands/heal.dm @@ -27,7 +27,7 @@ return var/obj/item/organ/internal/liver/liver = owner.get_organ_slot(ORGAN_SLOT_LIVER) - if((!liver && !HAS_TRAIT(owner, TRAIT_NOMETABOLISM)) || (liver && ((liver.damage > liver.high_threshold) || (liver.organ_flags & ORGAN_SYNTHETIC)))) + if((!liver && !HAS_TRAIT(owner, TRAIT_LIVERLESS_METABOLISM)) || (liver && ((liver.damage > liver.high_threshold) || (liver.organ_flags & ORGAN_SYNTHETIC)))) replace_liver(liver) return diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index 11b913d4f8b1..33ed63b4ac7b 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -489,7 +489,7 @@ if(verbose) to_chat(user, span_warning("We already have this DNA in storage!")) return FALSE - if(NO_DNA_COPY in target.dna.species?.species_traits) + if(HAS_TRAIT(target, TRAIT_NO_DNA_COPY)) if(verbose) to_chat(user, span_warning("[target] is not compatible with our biology.")) return FALSE diff --git a/code/modules/antagonists/nightmare/nightmare_species.dm b/code/modules/antagonists/nightmare/nightmare_species.dm index 619d5bb79456..c2acb7703750 100644 --- a/code/modules/antagonists/nightmare/nightmare_species.dm +++ b/code/modules/antagonists/nightmare/nightmare_species.dm @@ -8,12 +8,10 @@ burnmod = 1.5 changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE no_equip_flags = ITEM_SLOT_MASK | ITEM_SLOT_OCLOTHING | ITEM_SLOT_GLOVES | ITEM_SLOT_FEET | ITEM_SLOT_ICLOTHING | ITEM_SLOT_SUITSTORE - species_traits = list( - NO_UNDERWEAR, - NO_DNA_COPY, - NOTRANSSTING, - ) inherent_traits = list( + TRAIT_NO_UNDERWEAR, + TRAIT_NO_DNA_COPY, + TRAIT_NO_TRANSFORMATION_STING, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, TRAIT_RESISTCOLD, diff --git a/code/modules/client/preferences/_preference.dm b/code/modules/client/preferences/_preference.dm index e6f260d9a2f6..14daab33bc1b 100644 --- a/code/modules/client/preferences/_preference.dm +++ b/code/modules/client/preferences/_preference.dm @@ -101,9 +101,9 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) /// will show the feature as selectable. var/relevant_mutant_bodypart = null - /// If the selected species has this in its /datum/species/species_traits, + /// If the selected species has this in its /datum/species/inherent_traits, /// will show the feature as selectable. - var/relevant_species_trait = null + var/relevant_inherent_trait = null /// If the selected species has this in its /datum/species/var/external_organs, /// will show the feature as selectable. @@ -317,7 +317,12 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) SHOULD_CALL_PARENT(TRUE) SHOULD_NOT_SLEEP(TRUE) - if (!isnull(relevant_mutant_bodypart) || !isnull(relevant_species_trait) || !isnull(relevant_external_organ)) + if ( \ + !isnull(relevant_mutant_bodypart) \ + || !isnull(relevant_inherent_trait) \ + || !isnull(relevant_external_organ) \ + || !isnull(relevant_head_flag) \ + ) var/species_type = preferences.read_preference(/datum/preference/choiced/species) var/datum/species/species = new species_type diff --git a/code/modules/client/preferences/clothing.dm b/code/modules/client/preferences/clothing.dm index c1bb5f4c3105..057987c871fb 100644 --- a/code/modules/client/preferences/clothing.dm +++ b/code/modules/client/preferences/clothing.dm @@ -92,7 +92,7 @@ var/species_type = preferences.read_preference(/datum/preference/choiced/species) var/datum/species/species = new species_type - return !(NO_UNDERWEAR in species.species_traits) + return !(TRAIT_NO_UNDERWEAR in species.inherent_traits) /datum/preference/choiced/socks/compile_constant_data() var/list/data = ..() @@ -136,6 +136,14 @@ /datum/preference/choiced/undershirt/apply_to_human(mob/living/carbon/human/target, value) target.undershirt = value +/datum/preference/choiced/undershirt/is_accessible(datum/preferences/preferences) + if (!..(preferences)) + return FALSE + + var/species_type = preferences.read_preference(/datum/preference/choiced/species) + var/datum/species/species = new species_type + return !(TRAIT_NO_UNDERWEAR in species.inherent_traits) + /// Underwear preference /datum/preference/choiced/underwear savefile_key = "underwear" @@ -156,7 +164,7 @@ var/species_type = preferences.read_preference(/datum/preference/choiced/species) var/datum/species/species = new species_type - return !(NO_UNDERWEAR in species.species_traits) + return !(TRAIT_NO_UNDERWEAR in species.inherent_traits) /datum/preference/choiced/underwear/compile_constant_data() var/list/data = ..() diff --git a/code/modules/client/preferences/skin_tone.dm b/code/modules/client/preferences/skin_tone.dm index 571dfc66b3b1..d2359f8ce694 100644 --- a/code/modules/client/preferences/skin_tone.dm +++ b/code/modules/client/preferences/skin_tone.dm @@ -1,7 +1,8 @@ /datum/preference/choiced/skin_tone - category = PREFERENCE_CATEGORY_SECONDARY_FEATURES - savefile_identifier = PREFERENCE_CHARACTER savefile_key = "skin_tone" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + relevant_inherent_trait = TRAIT_USES_SKINTONES /datum/preference/choiced/skin_tone/init_possible_values() return GLOB.skin_tones @@ -26,12 +27,4 @@ return data /datum/preference/choiced/skin_tone/apply_to_human(mob/living/carbon/human/target, value) - if(target.dna.species.use_skintones) - target.skin_tone = value - -/datum/preference/choiced/skin_tone/is_accessible(datum/preferences/preferences) - if (!..(preferences)) - return FALSE - - var/datum/species/species_type = preferences.read_preference(/datum/preference/choiced/species) - return initial(species_type.use_skintones) + target.skin_tone = value diff --git a/code/modules/client/preferences/species.dm b/code/modules/client/preferences/species.dm index 1aae0e58dbbc..f47dd4bf2866 100644 --- a/code/modules/client/preferences/species.dm +++ b/code/modules/client/preferences/species.dm @@ -40,7 +40,7 @@ data[species_id]["name"] = species.name data[species_id]["desc"] = species.get_species_description() data[species_id]["icon"] = sanitize_css_class_name(species.name) - data[species_id]["use_skintones"] = species.use_skintones + data[species_id]["use_skintones"] = (TRAIT_USES_SKINTONES in species.inherent_traits) data[species_id]["sexes"] = species.sexes data[species_id]["enabled_features"] = species.get_features() data[species_id]["perks"] = species.get_species_perks() diff --git a/code/modules/client/preferences/species_features/mutants.dm b/code/modules/client/preferences/species_features/mutants.dm index 44cefd7ef877..7ecf25d9abce 100644 --- a/code/modules/client/preferences/species_features/mutants.dm +++ b/code/modules/client/preferences/species_features/mutants.dm @@ -2,7 +2,15 @@ savefile_key = "feature_mcolor" savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SECONDARY_FEATURES - relevant_species_trait = MUTCOLORS + relevant_inherent_trait = TRAIT_MUTANT_COLORS + +/datum/preference/color/mutant_color/is_accessible(datum/preferences/preferences) + if (!..(preferences)) + return FALSE + + var/species_type = preferences.read_preference(/datum/preference/choiced/species) + var/datum/species/species = new species_type + return !(TRAIT_FIXED_MUTANT_COLORS in species.inherent_traits) /datum/preference/color/mutant_color/create_default_value() return sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]") diff --git a/code/modules/client/preferences/species_features/vampire.dm b/code/modules/client/preferences/species_features/vampire.dm index 1b05c2c3e12b..16eef0905276 100644 --- a/code/modules/client/preferences/species_features/vampire.dm +++ b/code/modules/client/preferences/species_features/vampire.dm @@ -5,7 +5,7 @@ priority = PREFERENCE_PRIORITY_NAME_MODIFICATIONS //this will be overwritten by names otherwise main_feature_name = "Vampire status" should_generate_icons = TRUE - relevant_species_trait = BLOOD_CLANS + relevant_inherent_trait = TRAIT_BLOOD_CLANS /datum/preference/choiced/vampire_status/create_default_value() return "Inoculated" //eh, have em try out the mechanic first @@ -22,9 +22,6 @@ GLOBAL_LIST_EMPTY(vampire_houses) /datum/preference/choiced/vampire_status/apply_to_human(mob/living/carbon/human/target, value) - if (!(relevant_species_trait in target.dna?.species.species_traits)) - return - if(value != "Inoculated") return diff --git a/code/modules/client/preferences/underwear_color.dm b/code/modules/client/preferences/underwear_color.dm index a005145d1735..3603729910a3 100644 --- a/code/modules/client/preferences/underwear_color.dm +++ b/code/modules/client/preferences/underwear_color.dm @@ -12,4 +12,4 @@ var/species_type = preferences.read_preference(/datum/preference/choiced/species) var/datum/species/species = new species_type - return !(NO_UNDERWEAR in species.species_traits) + return !(TRAIT_NO_UNDERWEAR in species.inherent_traits) diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index 60900a4f4b41..1475b2caf3fb 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -543,7 +543,7 @@ if(!ishuman(exposed_mob) || exposed_mob.stat == DEAD) return var/mob/living/carbon/human/exposed_human = exposed_mob - if(!HAS_TRAIT(exposed_human, TRAIT_CAN_USE_FLIGHT_POTION) || reac_volume < 5 || !exposed_human.dna) + if(reac_volume < 5 || !exposed_human.dna) if((methods & INGEST) && show_message) to_chat(exposed_human, span_notice("You feel nothing but a terrible aftertaste.")) return diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 8d6770947b0d..900a43d4d38c 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -884,7 +884,7 @@ return FALSE // And we can't heal them if they're missing their liver - if(!HAS_TRAIT(src, TRAIT_NOMETABOLISM) && !isnull(dna?.species.mutantliver) && !get_organ_slot(ORGAN_SLOT_LIVER)) + if(!HAS_TRAIT(src, TRAIT_LIVERLESS_METABOLISM) && !isnull(dna?.species.mutantliver) && !get_organ_slot(ORGAN_SLOT_LIVER)) return FALSE return ..() diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 88bf5d3e9b05..574f1e6695ca 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -63,8 +63,6 @@ GLOBAL_LIST_EMPTY(features_by_species) var/examine_limb_id ///Never, Optional, or Forced digi legs? var/digitigrade_customization = DIGITIGRADE_NEVER - ///Does the species use skintones or not? As of now only used by humans. - var/use_skintones = FALSE /// If your race uses a non standard bloodtype (typepath) var/datum/blood_type/exotic_bloodtype ///The rate at which blood is passively drained by having the blood deficiency quirk. Some races such as slimepeople can regen their blood at different rates so this is to account for that @@ -129,8 +127,6 @@ GLOBAL_LIST_EMPTY(features_by_species) /// The icon of the fire overlay added when sufficently ablaze var/fire_dmi - ///Species-only traits. Can be found in [code/__DEFINES/DNA.dm] - var/list/species_traits = list() ///Generic traits tied to having the species. var/list/inherent_traits = list() /// List of biotypes the mob belongs to. Used by diseases. @@ -142,8 +138,6 @@ GLOBAL_LIST_EMPTY(features_by_species) ///What gas does this species breathe? Used by suffocation screen alerts, most of actual gas breathing is handled by mutantlungs. See [life.dm][code/modules/mob/living/carbon/human/life.dm] var/breathid = "o2" - ///are we a furry little guy? - var/uses_fur = FALSE ///What anim to use for dusting var/dust_anim = "dust-h" ///What anim to use for gibbing @@ -196,7 +190,7 @@ GLOBAL_LIST_EMPTY(features_by_species) var/payday_modifier = 1.0 ///Base electrocution coefficient. Basically a multiplier for damage from electrocutions. var/siemens_coeff = 1 - ///To use MUTCOLOR with a fixed color that's independent of the mcolor feature in DNA. + ///To use TRAIT_MUTANT_COLORS with a fixed color that's independent of the mcolor feature in DNA. var/fixed_mut_color = "" ///A fixed hair color that's independent of the mcolor feature in DNA. var/fixed_hair_color = "" @@ -513,8 +507,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(C.dna.species.exotic_bloodtype) C.dna.human_blood_type = exotic_bloodtype - if((AGENDER in species_traits)) - C.gender = PLURAL + if(C.hud_used) C.hud_used.update_locked_slots() @@ -547,10 +540,6 @@ GLOBAL_LIST_EMPTY(features_by_species) var/obj/item/organ/external/new_organ = SSwardrobe.provide_type(organ_path) new_organ.Insert(human, special=TRUE, drop_if_replaced=FALSE) - if(NOMOUTH in species_traits) - for(var/obj/item/bodypart/head/head in C.bodyparts) - head.mouth = FALSE - if(length(inherent_traits)) C.add_traits(inherent_traits, SPECIES_TRAIT) @@ -561,7 +550,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(TRAIT_TOXIMMUNE in inherent_traits) C.setToxLoss(0, TRUE, TRUE) - if(TRAIT_NOMETABOLISM in inherent_traits) + if(TRAIT_LIVERLESS_METABOLISM in inherent_traits) C.reagents.end_metabolization(C, keep_liverless = TRUE) if(TRAIT_GENELESS in inherent_traits) @@ -591,9 +580,6 @@ GLOBAL_LIST_EMPTY(features_by_species) SHOULD_CALL_PARENT(TRUE) if(C.dna.species.exotic_bloodtype) C.dna.human_blood_type = random_human_blood_type() - if(NOMOUTH in species_traits) - for(var/obj/item/bodypart/head/head in C.bodyparts) - head.mouth = TRUE for(var/X in inherent_traits) REMOVE_TRAIT(C, X, SPECIES_TRAIT) for(var/obj/item/organ/external/organ in C.organs) @@ -652,7 +638,7 @@ GLOBAL_LIST_EMPTY(features_by_species) standing += eye_overlay // organic body markings - if(HAS_MARKINGS in species_traits) + if(HAS_TRAIT(species_human, TRAIT_HAS_MARKINGS)) var/obj/item/bodypart/chest/chest = species_human.get_bodypart(BODY_ZONE_CHEST) var/obj/item/bodypart/arm/right/right_arm = species_human.get_bodypart(BODY_ZONE_R_ARM) var/obj/item/bodypart/arm/left/left_arm = species_human.get_bodypart(BODY_ZONE_L_ARM) @@ -690,7 +676,7 @@ GLOBAL_LIST_EMPTY(features_by_species) standing += markings_l_leg_overlay //Underwear, Undershirts & Socks - if(!(NO_UNDERWEAR in species_traits)) + if(!HAS_TRAIT(species_human, TRAIT_NO_UNDERWEAR)) if(species_human.underwear && !(src.bodytype & BODYTYPE_DIGITIGRADE)) //MONKESTATION EDIT var/datum/sprite_accessory/underwear/underwear = GLOB.underwear_list[species_human.underwear] var/mutable_appearance/underwear_overlay @@ -812,14 +798,14 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!(HAS_TRAIT(source, TRAIT_HUSK))) if(!forced_colour) switch(accessory.color_src) - if(SKINTONES) + if(SKIN_COLOR) accessory_overlay.color = skintone2hex(source.skin_tone) - if(MUTCOLORS) + if(MUTANT_COLOR) if(fixed_mut_color) accessory_overlay.color = fixed_mut_color else accessory_overlay.color = source.dna.features["mcolor"] - if(MUTCOLORS_SECONDARY) + if(MUTANT_COLOR_SECONDARY) if(fixed_mut_color) accessory_overlay.color = fixed_mut_color else @@ -835,7 +821,7 @@ GLOBAL_LIST_EMPTY(features_by_species) accessory_overlay.color = source.facial_hair_color if(EYE_COLOR) accessory_overlay.color = source.eye_color_left - if(ANIME) + if(ANIME_COLOR) accessory_overlay.color = source.dna.features["animecolor"] else accessory_overlay.color = forced_colour @@ -1524,7 +1510,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if ( \ (preference.relevant_mutant_bodypart in mutant_bodyparts) \ - || (preference.relevant_species_trait in species_traits) \ + || (preference.relevant_inherent_trait in inherent_traits) \ || (preference.relevant_external_organ in external_organs) \ || (preference.relevant_head_flag && check_head_flags(preference.relevant_head_flag)) \ ) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index a2f8a08f39f5..cc17b653c182 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -242,7 +242,7 @@ msg += "[t_He] look[p_s()] extremely disgusted.\n" var/apparent_blood_volume = blood_volume - if((dna.species.use_skintones)&& skin_tone == "albino") + if(HAS_TRAIT(src, TRAIT_USES_SKINTONES) && (skin_tone == "albino")) apparent_blood_volume -= 150 // enough to knock you down one tier if(isethereal(src))//Monkestation Changes Start: if(appears_dead) diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm index 90f4953a8826..6aded5feab48 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -2,10 +2,8 @@ name = "Abductor" id = SPECIES_ABDUCTOR sexes = FALSE - species_traits = list( - NO_UNDERWEAR, - ) inherent_traits = list( + TRAIT_NO_UNDERWEAR, TRAIT_NOBREATH, TRAIT_NOHUNGER, TRAIT_VIRUSIMMUNE, diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm index 054b4a489d64..08ebb8f2ff68 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -1,14 +1,11 @@ /datum/species/android name = "Android" id = SPECIES_ANDROID - species_traits = list( - NO_DNA_COPY, - NOTRANSSTING, - NO_UNDERWEAR, - NOHUSK, - ) inherent_traits = list( - TRAIT_CAN_USE_FLIGHT_POTION, + TRAIT_NO_UNDERWEAR, + TRAIT_NO_DNA_COPY, + TRAIT_NO_TRANSFORMATION_STING, + TRAIT_NO_HUSK, TRAIT_GENELESS, TRAIT_LIMBATTACHMENT, TRAIT_NOBREATH, diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm index 0c558c769737..f37821843706 100644 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm @@ -1,14 +1,13 @@ /datum/species/dullahan name = "Dullahan" id = SPECIES_DULLAHAN - species_traits = list() inherent_traits = list( TRAIT_NOBREATH, TRAIT_NOHUNGER, + TRAIT_USES_SKINTONES, ) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutant_bodyparts = list("wings" = "None") - use_skintones = TRUE mutantbrain = /obj/item/organ/internal/brain/dullahan mutanteyes = /obj/item/organ/internal/eyes/dullahan mutanttongue = /obj/item/organ/internal/tongue/dullahan diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm index e8e60718584e..f50449e7091b 100644 --- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm @@ -3,7 +3,6 @@ plural_form = "Flypeople" id = SPECIES_FLYPERSON inherent_traits = list( - TRAIT_CAN_USE_FLIGHT_POTION, TRAIT_TACKLING_FRAIL_ATTACKER, TRAIT_ANTENNAE, ) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 0f861a5cf633..c6ea48eb04a6 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -2,13 +2,11 @@ // Animated beings of stone. They have increased defenses, and do not need to breathe. They're also slow as fuuuck. name = "Golem" id = SPECIES_GOLEM - species_traits = list( - NOTRANSSTING, - MUTCOLORS, - NO_UNDERWEAR, - NO_DNA_COPY, - ) inherent_traits = list( + TRAIT_NO_UNDERWEAR, + TRAIT_NO_DNA_COPY, + TRAIT_NO_TRANSFORMATION_STING, + TRAIT_NO_AUGMENTS, TRAIT_GENELESS, TRAIT_NOBREATH, TRAIT_NOBLOOD, @@ -656,8 +654,8 @@ id = SPECIES_GOLEM_CULT sexes = FALSE info_text = "As a Runic Golem, you possess eldritch powers granted by the Elder Goddess Nar'Sie." - species_traits = list(NO_UNDERWEAR,NOEYESPRITES) //no mutcolors inherent_traits = list( + TRAIT_NO_UNDERWEAR, TRAIT_GENELESS, TRAIT_NOBREATH, TRAIT_NODISMEMBER, @@ -740,8 +738,8 @@ sexes = FALSE info_text = "As a Cloth Golem, you are able to reform yourself after death, provided your remains aren't burned or destroyed. You are, of course, very flammable. \ Being made of cloth, your body is immune to spirits of the damned and runic golems. You are faster than that of other golems, but weaker and less resilient." - species_traits = list(NO_UNDERWEAR) //no mutcolors, and can burn inherent_traits = list( + TRAIT_NO_UNDERWEAR, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, TRAIT_GENELESS, @@ -1006,8 +1004,8 @@ prefix = "Cardboard" special_names = list("Box") info_text = "As a Cardboard Golem, you aren't very strong, but you are a bit quicker and can easily create more brethren by using cardboard on yourself. Cardboard makes a poor building material for tongues, so you'll have difficulty speaking." - species_traits = list(NO_UNDERWEAR,NOEYESPRITES) inherent_traits = list( + TRAIT_NO_UNDERWEAR, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, TRAIT_GENELESS, @@ -1097,9 +1095,9 @@ id = SPECIES_GOLEM_DURATHREAD prefix = "Durathread" special_names = list("Boll","Weave") - species_traits = list(NO_UNDERWEAR,NOEYESPRITES) fixed_mut_color = null inherent_traits = list( + TRAIT_NO_UNDERWEAR, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, TRAIT_GENELESS, @@ -1138,11 +1136,8 @@ mutantstomach = /obj/item/organ/internal/stomach/bone sexes = FALSE fixed_mut_color = null - species_traits = list( - NO_UNDERWEAR, - NOEYESPRITES, - ) inherent_traits = list( + TRAIT_NO_UNDERWEAR, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, TRAIT_FAKEDEATH, @@ -1255,8 +1250,8 @@ info_text = "As a Snow Golem, you are extremely vulnerable to burn damage, but you can generate snowballs and shoot cryokinetic beams. You will also turn to snow when dying, preventing any form of recovery." prefix = "Snow" special_names = list("Flake", "Blizzard", "Storm") - species_traits = list(NO_UNDERWEAR,NOEYESPRITES) //no mutcolors, no eye sprites inherent_traits = list( + TRAIT_NO_UNDERWEAR, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, TRAIT_GENELESS, diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm index 320c4d69a814..49014c12720f 100644 --- a/code/modules/mob/living/carbon/human/species_types/humans.dm +++ b/code/modules/mob/living/carbon/human/species_types/humans.dm @@ -1,12 +1,10 @@ /datum/species/human name = "\improper Human" id = SPECIES_HUMAN - species_traits = list() + mutant_bodyparts = list("wings" = "None") inherent_traits = list( - TRAIT_CAN_USE_FLIGHT_POTION, + TRAIT_USES_SKINTONES, ) - mutant_bodyparts = list("wings" = "None") - use_skintones = TRUE skinned_type = /obj/item/stack/sheet/animalhide/human changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT payday_modifier = 1 diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 5195ddb8dd96..2f0b6faaf09c 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -3,17 +3,14 @@ name = "\improper Jellyperson" plural_form = "Jellypeople" id = SPECIES_JELLYPERSON - species_traits = list( - MUTCOLORS, - ) inherent_traits = list( - TRAIT_CAN_USE_FLIGHT_POTION, - TRAIT_TOXINLOVER, + TRAIT_MUTANT_COLORS, ) mutanttongue = /obj/item/organ/internal/tongue/jelly mutantlungs = /obj/item/organ/internal/lungs/slime mutanteyes = /obj/item/organ/internal/eyes/jelly mutantheart = /obj/item/organ/internal/heart/slime + mutantliver = /obj/item/organ/internal/liver/slime meat = /obj/item/food/meat/slab/human/mutant/slime exotic_bloodtype = /datum/blood_type/slime @@ -61,7 +58,9 @@ name = "\improper Slimeperson" plural_form = "Slimepeople" id = SPECIES_SLIMEPERSON - species_traits = list(MUTCOLORS,) + inherent_traits = list( + TRAIT_MUTANT_COLORS, + ) hair_color = "mutcolor" hair_alpha = 150 facial_hair_alpha = 150 diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 1cd333c24f9e..ec1a9ef6aa3a 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -4,11 +4,10 @@ plural_form = "Lizardfolk" id = SPECIES_LIZARD visual_gender = FALSE - species_traits = list( - MUTCOLORS, - MUTCOLORS_SECONDARY, - ) inherent_traits = list( + TRAIT_MUTANT_COLORS, + TRAIT_MUTANT_COLORS_SECONDARY, + TRAIT_NO_UNDERWEAR, TRAIT_CAN_USE_FLIGHT_POTION, TRAIT_TACKLING_TAILED_DEFENDER, ) @@ -111,12 +110,10 @@ Lizard subspecies: ASHWALKERS id = SPECIES_LIZARD_ASH mutantlungs = /obj/item/organ/internal/lungs/lavaland mutantbrain = /obj/item/organ/internal/brain/primitive - species_traits = list( - MUTCOLORS, - MUTCOLORS_SECONDARY, - NO_UNDERWEAR, //MONKESTATION ADDITION: no more flesh clothes lol - ) inherent_traits = list( + TRAIT_MUTANT_COLORS, + TRAIT_MUTANT_COLORS_SECONDARY, + TRAIT_NO_UNDERWEAR, //TRAIT_LITERATE, TRAIT_VIRUSIMMUNE, TRAIT_CAN_USE_FLIGHT_POTION, diff --git a/code/modules/mob/living/carbon/human/species_types/monkeys.dm b/code/modules/mob/living/carbon/human/species_types/monkeys.dm index 763feebd439b..985ad7ce7114 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -12,13 +12,11 @@ skinned_type = /obj/item/stack/sheet/animalhide/monkey meat = /obj/item/food/meat/slab/monkey knife_butcher_results = list(/obj/item/food/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1) - species_traits = list( - NO_UNDERWEAR, - NOBLOODOVERLAY, - NOTRANSSTING, - NOAUGMENTS, - ) inherent_traits = list( + TRAIT_NO_UNDERWEAR, + TRAIT_NO_BLOOD_OVERLAY, + TRAIT_NO_TRANSFORMATION_STING, + TRAIT_NO_AUGMENTS, TRAIT_GUN_NATURAL, TRAIT_VENTCRAWLER_NUDE, TRAIT_WEAK_SOUL, diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index 291060630875..bf95b89e6968 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -2,11 +2,8 @@ name = "\improper Mothman" plural_form = "Mothmen" id = SPECIES_MOTH - species_traits = list( - HAS_MARKINGS, - ) inherent_traits = list( - TRAIT_CAN_USE_FLIGHT_POTION, + TRAIT_HAS_MARKINGS, TRAIT_TACKLING_WINGED_ATTACKER, TRAIT_ANTENNAE, ) diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm index 5d30c93255cc..e5e1bf25872c 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -8,11 +8,9 @@ fixed_mut_color = "#DBBF92" hair_color = "#FF4B19" //cap color, spot color uses eye color - species_traits = list( - MUTCOLORS, - NO_UNDERWEAR, - ) inherent_traits = list( + TRAIT_NO_UNDERWEAR, + TRAIT_MUTANT_COLORS, TRAIT_NOBREATH, TRAIT_NOFLASH, ) @@ -26,7 +24,6 @@ mutanttongue = /obj/item/organ/internal/tongue/mush mutanteyes = /obj/item/organ/internal/eyes/night_vision/mushroom mutantlungs = null - use_skintones = FALSE var/datum/martial_art/mushpunch/mush species_language_holder = /datum/language_holder/mushroom diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index bda9da25e501..554ed48c5a42 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -4,11 +4,9 @@ id = SPECIES_PLASMAMAN sexes = 0 meat = /obj/item/stack/sheet/mineral/plasma - species_traits = list( - NOTRANSSTING, - ) // plasmemes get hard to wound since they only need a severe bone wound to dismember, but unlike skellies, they can't pop their bones back into place inherent_traits = list( + TRAIT_NO_TRANSFORMATION_STING, TRAIT_GENELESS, TRAIT_HARDLY_WOUNDED, TRAIT_RADIMMUNE, diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index d9bd3358c4ef..1374f9abce24 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -3,10 +3,8 @@ name = "\improper Podperson" plural_form = "Podpeople" id = SPECIES_PODPERSON - species_traits = list( - MUTCOLORS, - ) inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_PLANT_SAFE, ) external_organs = list( diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index e7f1d9658e2f..d0ea71dac837 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -5,7 +5,6 @@ id = SPECIES_SHADOW sexes = 0 meat = /obj/item/food/meat/slab/human/mutant/shadow - species_traits = list() inherent_traits = list( TRAIT_NOBREATH, TRAIT_RADIMMUNE, diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm index c238a0bf0648..c7c1e2dc67c8 100644 --- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm +++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm @@ -4,21 +4,18 @@ id = SPECIES_SKELETON sexes = 0 meat = /obj/item/food/meat/slab/human/mutant/skeleton - species_traits = list( - NOTRANSSTING, - NO_DNA_COPY, - NO_UNDERWEAR, - NOHUSK, - ) inherent_traits = list( - TRAIT_CAN_USE_FLIGHT_POTION, + TRAIT_NO_HUSK, + TRAIT_NO_TRANSFORMATION_STING, + TRAIT_NO_UNDERWEAR, + TRAIT_NO_DNA_COPY, TRAIT_EASYDISMEMBER, TRAIT_FAKEDEATH, TRAIT_GENELESS, TRAIT_LIMBATTACHMENT, TRAIT_NOBREATH, TRAIT_NOCLONELOSS, - TRAIT_NOMETABOLISM, + TRAIT_LIVERLESS_METABOLISM, TRAIT_RADIMMUNE, TRAIT_PIERCEIMMUNE, TRAIT_RESISTCOLD, diff --git a/code/modules/mob/living/carbon/human/species_types/snail.dm b/code/modules/mob/living/carbon/human/species_types/snail.dm index a1cde44588bc..aa0e4d282bf6 100644 --- a/code/modules/mob/living/carbon/human/species_types/snail.dm +++ b/code/modules/mob/living/carbon/human/species_types/snail.dm @@ -1,11 +1,9 @@ /datum/species/snail name = "Snailperson" id = SPECIES_SNAIL - species_traits = list( - MUTCOLORS, - NO_UNDERWEAR, - ) inherent_traits = list( + TRAIT_MUTANT_COLORS, + TRAIT_NO_UNDERWEAR, TRAIT_NO_SLIP_ALL, ) diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index a7711da1a8cd..02fde964482e 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -7,22 +7,19 @@ /datum/species/vampire name = "Vampire" id = SPECIES_VAMPIRE - species_traits = list( - DRINKSBLOOD, - BLOOD_CLANS, - ) inherent_traits = list( + TRAIT_DRINKS_BLOOD, + TRAIT_BLOOD_CLANS, TRAIT_NOBREATH, TRAIT_NOHUNGER, TRAIT_NO_MIRROR_REFLECTION, - /*TRAIT_USES_SKINTONES,*/ //monkestation temp removal, we dont have this refactor yet + TRAIT_USES_SKINTONES ) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutant_bodyparts = list("wings" = "None") changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN exotic_bloodtype = /datum/blood_type/universal blood_deficiency_drain_rate = BLOOD_DEFICIENCY_MODIFIER // vampires already passively lose blood, so this just makes them lose it slightly more quickly when they have blood deficiency. - use_skintones = TRUE mutantheart = /obj/item/organ/internal/heart/vampire mutanttongue = /obj/item/organ/internal/tongue/vampire mutantstomach = null diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index 92f73fe32565..29147e95e4a2 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -7,12 +7,10 @@ sexes = FALSE meat = /obj/item/food/meat/slab/human/mutant/zombie mutanttongue = /obj/item/organ/internal/tongue/zombie - species_traits = list( - NOZOMBIE, - NOTRANSSTING, - ) inherent_traits = list( // SHARED WITH ALL ZOMBIES + TRAIT_NO_ZOMBIFY, + TRAIT_NO_TRANSFORMATION_STING, TRAIT_EASILY_WOUNDED, TRAIT_EASYDISMEMBER, TRAIT_FAKEDEATH, @@ -21,7 +19,7 @@ TRAIT_NOCLONELOSS, TRAIT_NODEATH, TRAIT_NOHUNGER, - TRAIT_NOMETABOLISM, + TRAIT_LIVERLESS_METABOLISM, TRAIT_RADIMMUNE, TRAIT_RESISTCOLD, TRAIT_RESISTHIGHPRESSURE, @@ -100,7 +98,7 @@ TRAIT_NOCLONELOSS, TRAIT_NODEATH, TRAIT_NOHUNGER, - TRAIT_NOMETABOLISM, + TRAIT_LIVERLESS_METABOLISM, TRAIT_RADIMMUNE, TRAIT_RESISTCOLD, TRAIT_RESISTHIGHPRESSURE, diff --git a/code/modules/mob/living/carbon/human/status_procs.dm b/code/modules/mob/living/carbon/human/status_procs.dm index acbb3c528c6f..238e434a2a85 100644 --- a/code/modules/mob/living/carbon/human/status_procs.dm +++ b/code/modules/mob/living/carbon/human/status_procs.dm @@ -32,7 +32,7 @@ update_body_parts() /mob/living/carbon/human/become_husk(source) - if(NOHUSK in dna.species.species_traits) //skeletons shouldn't be husks. + if(HAS_TRAIT(src, TRAIT_NO_HUSK)) //skeletons shouldn't be husks. cure_husk() return . = ..() diff --git a/code/modules/mob/living/carbon/init_signals.dm b/code/modules/mob/living/carbon/init_signals.dm index e3cc487eeb7d..79c54fed41a0 100644 --- a/code/modules/mob/living/carbon/init_signals.dm +++ b/code/modules/mob/living/carbon/init_signals.dm @@ -1,9 +1,12 @@ //Called on /mob/living/carbon/Initialize(mapload), for the carbon mobs to register relevant signals. /mob/living/carbon/register_init_signals() . = ..() + //Traits that register add and remove + RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_AGENDER), PROC_REF(on_agender_trait_gain)) + RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_AGENDER), PROC_REF(on_agender_trait_loss)) RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_NOBREATH), PROC_REF(on_nobreath_trait_gain)) - RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_NOMETABOLISM), PROC_REF(on_nometabolism_trait_gain)) + RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_LIVERLESS_METABOLISM), PROC_REF(on_liverless_metabolism_trait_gain)) RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_VIRUSIMMUNE), PROC_REF(on_virusimmune_trait_gain)) RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_TOXIMMUNE), PROC_REF(on_toximmune_trait_gain)) RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_GENELESS), PROC_REF(on_geneless_trait_gain)) @@ -64,11 +67,11 @@ clear_mood_event("smell") clear_mood_event("suffocation") /** - * On gain of TRAIT_NOMETABOLISM + * On gain of TRAIT_LIVERLESS_METABOLISM * * This will clear all moods related to addictions and stop metabolization. */ -/mob/living/carbon/proc/on_nometabolism_trait_gain(datum/source) +/mob/living/carbon/proc/on_liverless_metabolism_trait_gain(datum/source) SIGNAL_HANDLER for(var/addiction_type in subtypesof(/datum/addiction)) mind?.remove_addiction_points(addiction_type, MAX_ADDICTION_POINTS) //Remove the addiction! diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 5c81b5f4e477..e5f43d825981 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -421,7 +421,7 @@ reagents.end_metabolization(src, keep_liverless = TRUE) //Stops trait-based effects on reagents, to prevent permanent buffs reagents.metabolize(src, seconds_per_tick, times_fired, can_overdose=TRUE, liverless = TRUE) - if(HAS_TRAIT(src, TRAIT_STABLELIVER) || HAS_TRAIT(src, TRAIT_NOMETABOLISM)) + if(HAS_TRAIT(src, TRAIT_STABLELIVER) || HAS_TRAIT(src, TRAIT_LIVERLESS_METABOLISM)) return adjustToxLoss(0.6 * seconds_per_tick, TRUE, TRUE) diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index f77bbdec9b64..1ab4157d3484 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -700,16 +700,12 @@ return if(invisible_man.undergoing_liver_failure()) return - if(HAS_TRAIT(invisible_man, TRAIT_NOMETABOLISM)) + if(HAS_TRAIT(invisible_man, TRAIT_LIVERLESS_METABOLISM)) return if(invisible_man.has_status_effect(/datum/status_effect/grouped/stasis)) return - invisible_man.add_traits(list(TRAIT_INVISIBLE_MAN, TRAIT_HIDE_EXTERNAL_ORGANS), name) - - var/datum/dna/druggy_dna = invisible_man.has_dna() - if(druggy_dna?.species) - druggy_dna.species.species_traits += NOBLOODOVERLAY + invisible_man.add_traits(list(TRAIT_INVISIBLE_MAN, TRAIT_HIDE_EXTERNAL_ORGANS, TRAIT_NO_BLOOD_OVERLAY), name) invisible_man.update_body() invisible_man.remove_from_all_data_huds() @@ -719,14 +715,10 @@ . = ..() if(HAS_TRAIT(invisible_man, TRAIT_INVISIBLE_MAN)) invisible_man.add_to_all_human_data_huds() //Is this safe, what do you think, Floyd? - invisible_man.remove_traits(list(TRAIT_INVISIBLE_MAN, TRAIT_HIDE_EXTERNAL_ORGANS), name) + invisible_man.remove_traits(list(TRAIT_INVISIBLE_MAN, TRAIT_HIDE_EXTERNAL_ORGANS, TRAIT_NO_BLOOD_OVERLAY), name) to_chat(invisible_man, span_notice("As you sober up, opacity once again returns to your body meats.")) - var/datum/dna/druggy_dna = invisible_man.has_dna() - if(druggy_dna?.species) - druggy_dna.species.species_traits -= NOBLOODOVERLAY - invisible_man.update_body() invisible_man.sound_environment_override = NONE diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 6c09b960c9da..ee9f127c5de3 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -581,7 +581,7 @@ if ("albino") exposed_human.skin_tone = "caucasian1" - if(MUTCOLORS in exposed_human.dna.species.species_traits) //take current alien color and darken it slightly + if(HAS_TRAIT(exposed_human, TRAIT_MUTANT_COLORS)) //take current alien color and darken it slightly var/newcolor = "" var/string = exposed_human.dna.features["mcolor"] var/len = length(string) @@ -626,9 +626,9 @@ var/obj/item/bodypart/head/head = affected_human.get_bodypart(BODY_ZONE_HEAD) if(head) head.head_flags |= HEAD_HAIR //No hair? No problem! - if(affected_human.dna.species.use_skintones) + if(HAS_TRAIT(affected_human, TRAIT_USES_SKINTONES)) affected_human.skin_tone = "orange" - else if(MUTCOLORS in affected_human.dna.species.species_traits) //Aliens with custom colors simply get turned orange + else if(HAS_TRAIT(affected_human, TRAIT_MUTANT_COLORS)) //Aliens with custom colors simply get turned orange affected_human.dna.features["mcolor"] = "#ff8800" affected_human.update_body(is_creating = TRUE) if(SPT_PROB(3.5, seconds_per_tick)) diff --git a/code/modules/spells/spell_types/self/mutate.dm b/code/modules/spells/spell_types/self/mutate.dm index 59f8f6ddc37f..6f5040c6b5e7 100644 --- a/code/modules/spells/spell_types/self/mutate.dm +++ b/code/modules/spells/spell_types/self/mutate.dm @@ -51,8 +51,8 @@ /datum/action/cooldown/spell/apply_mutations/mutate/cast(mob/living/carbon/human/cast_on) ..() - /*if(HAS_TRAIT(cast_on, TRAIT_USES_SKINTONES) || HAS_TRAIT(cast_on, TRAIT_MUTANT_COLORS)) - return*/ //monkestation temp removal, we dont have this refactor yet + if(HAS_TRAIT(cast_on, TRAIT_USES_SKINTONES) || HAS_TRAIT(cast_on, TRAIT_MUTANT_COLORS)) + return//monkestation temp removal, we dont have this refactor yet // Our caster has a species that doesn't greenify when hulked, so we will do it manually. cast_on.add_atom_colour("#00FF00", TEMPORARY_COLOUR_PRIORITY) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 8898baf0e620..08c05f8fc436 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -113,12 +113,6 @@ var/px_x = 0 var/px_y = 0 - /** - * A copy of the original owner's species datum species_traits list (very hacky) - * It sucks that we have to do this, but due to MUTCOLORS and others, we have to. For now. - */ - - var/species_flags_list = list() ///the type of damage overlay (if any) to use when this bodypart is bruised/burned. var/dmg_overlay_type = "human" /// If we're bleeding, which icon are we displaying on this part @@ -653,7 +647,7 @@ if(burn) set_burn_dam(round(max(burn_dam - burn, 0), DAMAGE_PRECISION)) - if(owner.dna && owner.dna.species && (REVIVESBYHEALING in owner.dna.species.species_traits)) + if(HAS_TRAIT(owner, TRAIT_REVIVES_BY_HEALING)) if(owner.health > 0) owner.revive(0) owner.cure_husk(0) // If it has REVIVESBYHEALING, it probably can't be cloned. No husk cure. @@ -796,7 +790,7 @@ // Bleeding stuff RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_NOBLOOD), PROC_REF(on_owner_nobleed_loss)) RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOBLOOD), PROC_REF(on_owner_nobleed_gain)) - RegisterSignal(owner, list(COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB), PROC_REF(reassess_body_composition)) + RegisterSignals(owner, list(COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB), PROC_REF(reassess_body_composition)) if(needs_update_disabled) update_disabled() @@ -917,26 +911,23 @@ // There should technically to be an ishuman(owner) check here, but it is absent because no basetype carbons use bodyparts // No, xenos don't actually use bodyparts. Don't ask. var/mob/living/carbon/human/human_owner = owner - var/datum/species/owner_species = human_owner.dna.species - species_flags_list = owner_species.species_traits.Copy() limb_gender = (human_owner.physique == MALE) ? "m" : "f" - - if(owner_species.use_skintones) + if(HAS_TRAIT(human_owner, TRAIT_USES_SKINTONES)) skin_tone = human_owner.skin_tone - else + else if(HAS_TRAIT(human_owner, TRAIT_MUTANT_COLORS)) skin_tone = "" - - if(((MUTCOLORS in owner_species.species_traits) || (DYNCOLORS in owner_species.species_traits) || (SPECIES_FUR in owner_species.species_traits))) //Ethereal code. Motherfuckers. + var/datum/species/owner_species = human_owner.dna.species if(owner_species.fixed_mut_color) species_color = owner_species.fixed_mut_color else species_color = human_owner.dna.features["mcolor"] else - species_color = null + skin_tone = "" + species_color = "" draw_color = variable_color if(should_draw_greyscale) //Should the limb be colored? - draw_color ||= (species_color) || (skin_tone && skintone2hex(skin_tone)) + draw_color ||= species_color || (skin_tone ? skintone2hex(skin_tone) : null) recolor_external_organs() return TRUE diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm index 487ac25091ee..61fe34778817 100644 --- a/code/modules/surgery/limb_augmentation.dm +++ b/code/modules/surgery/limb_augmentation.dm @@ -14,7 +14,7 @@ /datum/surgery_step/replace_limb/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - if(NOAUGMENTS in target.dna.species.species_traits) + if(HAS_TRAIT(target, TRAIT_NO_AUGMENTS)) to_chat(user, span_warning("[target] cannot be augmented!")) return SURGERY_STEP_FAIL if(istype(tool, /obj/item/borg/apparatus/organ_storage) && istype(tool.contents[1], /obj/item/bodypart)) diff --git a/code/modules/surgery/organs/internal/liver/_liver.dm b/code/modules/surgery/organs/internal/liver/_liver.dm index a30c71bcf8c6..27e6a0756ff7 100644 --- a/code/modules/surgery/organs/internal/liver/_liver.dm +++ b/code/modules/surgery/organs/internal/liver/_liver.dm @@ -121,23 +121,19 @@ #define HAS_PAINFUL_TOXIN 2 /obj/item/organ/internal/liver/on_life(seconds_per_tick, times_fired) - . = ..() //perform general on_life() - var/mob/living/carbon/liver_owner = owner - - if(!istype(liver_owner)) - return + . = ..() //If your liver is failing, then we use the liverless version of metabolize - //We don't check for TRAIT_NOMETABOLISM here because we do want a functional liver if somehow we have one inserted + //We don't check for TRAIT_LIVERLESS_METABOLISM here because we do want a functional liver if somehow we have one inserted if(organ_flags & ORGAN_FAILING) - liver_owner.reagents.metabolize(liver_owner, seconds_per_tick, times_fired, can_overdose = TRUE, liverless = TRUE) + owner.reagents.metabolize(owner, seconds_per_tick, times_fired, can_overdose = TRUE, liverless = TRUE) return - var/obj/belly = liver_owner.get_organ_slot(ORGAN_SLOT_STOMACH) - var/list/cached_reagents = liver_owner.reagents.reagent_list + var/obj/belly = owner.get_organ_slot(ORGAN_SLOT_STOMACH) + var/list/cached_reagents = owner.reagents.reagent_list var/liver_damage = 0 var/provide_pain_message = HAS_NO_TOXIN - if(filterToxins && !HAS_TRAIT(liver_owner, TRAIT_TOXINLOVER)) + if(filterToxins && !HAS_TRAIT(owner, TRAIT_TOXINLOVER)) for(var/datum/reagent/toxin/toxin in cached_reagents) if(status != toxin.affected_organtype) //this particular toxin does not affect this type of organ continue @@ -151,17 +147,17 @@ if(provide_pain_message != HAS_PAINFUL_TOXIN) provide_pain_message = toxin.silent_toxin ? HAS_SILENT_TOXIN : HAS_PAINFUL_TOXIN - liver_owner.reagents.metabolize(liver_owner, seconds_per_tick, times_fired, can_overdose=TRUE) + owner.reagents.metabolize(owner, seconds_per_tick, times_fired, can_overdose=TRUE) if(liver_damage) apply_organ_damage(min(liver_damage * seconds_per_tick , MAX_TOXIN_LIVER_DAMAGE * seconds_per_tick)) if(provide_pain_message && damage > 10 && SPT_PROB(damage/6, seconds_per_tick)) //the higher the damage the higher the probability - to_chat(liver_owner, span_warning("You feel a dull pain in your abdomen.")) + to_chat(owner, span_warning("You feel a dull pain in your abdomen.")) /obj/item/organ/internal/liver/handle_failing_organs(seconds_per_tick) - if(HAS_TRAIT(owner, TRAIT_STABLELIVER) || HAS_TRAIT(owner, TRAIT_NOMETABOLISM)) + if(HAS_TRAIT(owner, TRAIT_STABLELIVER) || HAS_TRAIT(owner, TRAIT_LIVERLESS_METABOLISM)) return return ..() diff --git a/code/modules/surgery/organs/internal/liver/liver_skeleton.dm b/code/modules/surgery/organs/internal/liver/liver_skeleton.dm index 925eade7cbc1..532d1038fcfc 100644 --- a/code/modules/surgery/organs/internal/liver/liver_skeleton.dm +++ b/code/modules/surgery/organs/internal/liver/liver_skeleton.dm @@ -7,7 +7,7 @@ name = "mass of bones" desc = "You have no idea what this strange ball of bones does." icon_state = "liver-bone" - organ_traits = list(TRAIT_NOMETABOLISM) + organ_traits = list(TRAIT_LIVERLESS_METABOLISM) /obj/item/organ/internal/liver/bone/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) . = ..() diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm index 464bf9f3740c..f933f14854a7 100644 --- a/code/modules/zombie/items.dm +++ b/code/modules/zombie/items.dm @@ -29,7 +29,7 @@ if(!target.get_bodypart(BODY_ZONE_HEAD)) return - if((NOZOMBIE in target.dna.species.species_traits) || HAS_TRAIT(target, TRAIT_NO_ZOMBIFY)) + if(HAS_TRAIT(target, TRAIT_NO_ZOMBIFY)) // cannot infect any NOZOMBIE subspecies (such as high functioning // zombies) return diff --git a/config/config.txt b/config/config.txt index a15291b8953e..464b95aa5078 100644 --- a/config/config.txt +++ b/config/config.txt @@ -528,7 +528,7 @@ MOTD motd.txt ## The cache is assumed to be cleared by TGS recompiling, which deletes `tmp`. ## This should be disabled (through `CACHE_ASSETS 0`) on development, ## but enabled on production (the default). -CACHE_ASSETS 0 +CACHE_ASSETS 1 ## If this remains commented out, we will allow players to download their own preferences as a JSON file to do whatever they wish. ## This does require the game code to read (and only read) the /data folder where these files are stored, and then use the BYOND FTP Function to send the file to the client. diff --git a/monkestation/code/game/machinery/computer/cloning.dm b/monkestation/code/game/machinery/computer/cloning.dm index 041a93b84c15..12ce94de0135 100644 --- a/monkestation/code/game/machinery/computer/cloning.dm +++ b/monkestation/code/game/machinery/computer/cloning.dm @@ -529,11 +529,10 @@ if(ishuman(mob_occupant)) dna = C.has_dna() - var/mob/living/carbon/human/human_occupant = mob_occupant var/obj/item/card/id/I = C.get_idcard(TRUE) if(I) has_bank_account = I.registered_account - if(!istype(dna) || (NO_DNA_COPY in human_occupant.dna.species.species_traits)) + if(!istype(dna) || HAS_TRAIT(mob_occupant, TRAIT_NO_DNA_COPY)) scantemp = "Unable to locate valid genetic data." playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) return diff --git a/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/soul_steal.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/soul_steal.dm index 272978a07a84..b9e93cdfe460 100644 --- a/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/soul_steal.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/soul_steal.dm @@ -78,7 +78,7 @@ human_target.soul_sucked = TRUE - if(human_target.dna.species.use_skintones) // make them deathly white, afterall they dont have a soul anymore + if(HAS_TRAIT(human_target, TRAIT_USES_SKINTONES)) // make them deathly white, afterall they dont have a soul anymore human_target.skin_tone = "albino" human_target.dna.update_ui_block(DNA_SKIN_TONE_BLOCK) else // we dont discriminate, even skeletons can be white... (arent they already white?) diff --git a/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_datum.dm b/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_datum.dm index 151ca08ccbf2..9d9324824c16 100644 --- a/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_datum.dm +++ b/monkestation/code/modules/bloodsuckers/bloodsucker/bloodsucker_datum.dm @@ -246,7 +246,7 @@ if(old_body && ishuman(old_body)) var/mob/living/carbon/human/old_user = old_body var/datum/species/old_species = old_user.dna.species - old_species.species_traits -= DRINKSBLOOD + old_species.inherent_traits -= TRAIT_DRINKS_BLOOD //Keep track of what they were old_left_arm_unarmed_damage_low = old_left_arm.unarmed_damage_low old_left_arm_unarmed_damage_high = old_left_arm.unarmed_damage_high @@ -260,7 +260,7 @@ if(ishuman(new_body)) var/mob/living/carbon/human/new_user = new_body var/datum/species/new_species = new_user.dna.species - new_species.species_traits += DRINKSBLOOD + new_species.inherent_traits += TRAIT_DRINKS_BLOOD var/obj/item/bodypart/new_left_arm var/obj/item/bodypart/new_right_arm //Give old punch damage values @@ -408,7 +408,7 @@ var/datum/species/user_species = user.dna.species var/obj/item/bodypart/user_left_arm = user.get_bodypart(BODY_ZONE_L_ARM) var/obj/item/bodypart/user_right_arm = user.get_bodypart(BODY_ZONE_R_ARM) - user_species.species_traits += DRINKSBLOOD + user_species.inherent_traits += TRAIT_DRINKS_BLOOD user.dna?.remove_all_mutations() user_left_arm.unarmed_damage_low += 1 //lowest possible punch damage - 0 user_left_arm.unarmed_damage_high += 1 //highest possible punch damage - 9 @@ -450,7 +450,7 @@ if(ishuman(owner.current)) var/mob/living/carbon/human/user = owner.current var/datum/species/user_species = user.dna.species - user_species.species_traits -= DRINKSBLOOD + user_species.inherent_traits -= TRAIT_DRINKS_BLOOD // Remove all bloodsucker traits owner.current.remove_traits(bloodsucker_traits, BLOODSUCKER_TRAIT) // Update Health diff --git a/monkestation/code/modules/botany/species/apid/species.dm b/monkestation/code/modules/botany/species/apid/species.dm index 0bdefef537be..df8090e0e0a0 100644 --- a/monkestation/code/modules/botany/species/apid/species.dm +++ b/monkestation/code/modules/botany/species/apid/species.dm @@ -27,14 +27,6 @@ name = "\improper Apid" plural_form = "Apids" id = SPECIES_APID - species_traits = list(HAS_MARKINGS,) - - /* - mutant_bodyparts = list( - "apid_stripes" = "None", - "apid_headstripes" = "None", - ) - */ mutanteyes = /obj/item/organ/internal/eyes/apid @@ -46,6 +38,7 @@ inherent_traits = list( TRAIT_TACKLING_WINGED_ATTACKER, TRAIT_ANTENNAE, + TRAIT_HAS_MARKINGS, ) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG diff --git a/monkestation/code/modules/client/preferences/species_features/ethereal.dm b/monkestation/code/modules/client/preferences/species_features/ethereal.dm index d0b79ffe1e9a..1efe9542f789 100644 --- a/monkestation/code/modules/client/preferences/species_features/ethereal.dm +++ b/monkestation/code/modules/client/preferences/species_features/ethereal.dm @@ -9,7 +9,7 @@ return possible_values_for_sprite_accessory_list_for_body_part( GLOB.ethereal_horns_list, "ethereal_horns", - list("ADJ", "FRONT"), + list("FRONT"), ) /datum/preference/choiced/ethereal_horns/apply_to_human(mob/living/carbon/human/target, value) @@ -26,7 +26,7 @@ return possible_values_for_sprite_accessory_list_for_body_part( GLOB.ethereal_tail_list, "ethereal_tail", - list("BEHIND", "FRONT"), + list("BEHIND"), ) /datum/preference/choiced/ethereal_tail/apply_to_human(mob/living/carbon/human/target, value) diff --git a/monkestation/code/modules/client/preferences/species_features/secondary_mut_color.dm b/monkestation/code/modules/client/preferences/species_features/secondary_mut_color.dm index 1564e0e925e5..5dfb2a59e9eb 100644 --- a/monkestation/code/modules/client/preferences/species_features/secondary_mut_color.dm +++ b/monkestation/code/modules/client/preferences/species_features/secondary_mut_color.dm @@ -2,7 +2,15 @@ savefile_key = "feature_mcolor_secondary" savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SECONDARY_FEATURES - relevant_species_trait = MUTCOLORS_SECONDARY + relevant_inherent_trait = TRAIT_MUTANT_COLORS_SECONDARY + +/datum/preference/color/mutant_color_secondary/is_accessible(datum/preferences/preferences) + if (!..(preferences)) + return FALSE + + var/species_type = preferences.read_preference(/datum/preference/choiced/species) + var/datum/species/species = new species_type + return !(TRAIT_MUTANT_COLORS_SECONDARY in species.inherent_traits) /datum/preference/color/mutant_color_secondary/create_default_value() return sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]") diff --git a/monkestation/code/modules/client/preferences/species_features/simians.dm b/monkestation/code/modules/client/preferences/species_features/simians.dm index a4f27e181827..0f85e08f6d56 100644 --- a/monkestation/code/modules/client/preferences/species_features/simians.dm +++ b/monkestation/code/modules/client/preferences/species_features/simians.dm @@ -2,12 +2,12 @@ category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_identifier = PREFERENCE_CHARACTER savefile_key = "fur" - relevant_species_trait = SPECIES_FUR + relevant_inherent_trait = TRAIT_FUR_COLORS /datum/preference/color/fur_color/apply_to_human(mob/living/carbon/human/target, value) var/mob/user = usr var/datum/species/species_type = user?.client.prefs.read_preference(/datum/preference/choiced/species) - if(initial(species_type.uses_fur)) + if(TRAIT_FUR_COLORS in initial(species_type.inherent_traits)) target.dna.features["mcolor"] = value /datum/preference/choiced/simian_tail diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/anime.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/anime.dm index 6faea383a344..19657a190df7 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/anime.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/anime.dm @@ -1,11 +1,11 @@ ///ANIME ACCESSORIES GO HERE /datum/sprite_accessory/anime_head icon = 'monkestation/icons/mob/anime/anime_head.dmi' - color_src = ANIME + color_src = ANIME_COLOR /datum/sprite_accessory/anime_head/none name = "None" - icon_state = "None" + icon_state = "none" /datum/sprite_accessory/anime_head/pony name = "Pony Ears" @@ -70,7 +70,7 @@ /datum/sprite_accessory/anime_middle icon = 'monkestation/icons/mob/anime/anime_middle.dmi' - color_src = ANIME + color_src = ANIME_COLOR /datum/sprite_accessory/anime_middle/none name = "None" @@ -106,7 +106,7 @@ /datum/sprite_accessory/anime_bottom icon = 'monkestation/icons/mob/anime/anime_bottom.dmi' - color_src = ANIME + color_src = ANIME_COLOR /datum/sprite_accessory/anime_bottom/none name = "None" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_appendages.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_appendages.dm index 591efc167c78..b8b1ce15d9c0 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_appendages.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_appendages.dm @@ -1,6 +1,6 @@ /datum/sprite_accessory/arachnid_appendages icon = 'monkestation/icons/mob/species/arachnid/arachnid_appendages.dmi' - color_src = MUTCOLORS + color_src = MUTANT_COLOR /datum/sprite_accessory/arachnid_appendages/long name = "Long" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_chelicerae.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_chelicerae.dm index b7791913b753..91aff39dd5d4 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_chelicerae.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_chelicerae.dm @@ -1,6 +1,6 @@ /datum/sprite_accessory/arachnid_chelicerae icon = 'monkestation/icons/mob/species/arachnid/arachnid_chelicerae.dmi' - color_src = MUTCOLORS + color_src = MUTANT_COLOR /datum/sprite_accessory/arachnid_chelicerae/basic name = "Basic" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_horns.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_horns.dm index c5ed93a8a100..7c8bea62a121 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_horns.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_horns.dm @@ -1,6 +1,6 @@ /datum/sprite_accessory/ethereal_horns icon = 'monkestation/icons/mob/species/ethereal/ethereal_horns.dmi' - color_src = MUTCOLORS + color_src = MUTANT_COLOR /datum/sprite_accessory/ethereal_horns/none name = "None" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_tail.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_tail.dm index 5ccec9b8e836..467629e94648 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_tail.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_tail.dm @@ -1,6 +1,6 @@ /datum/sprite_accessory/tails/ethereal icon = 'monkestation/icons/mob/species/ethereal/ethereal_tail.dmi' - color_src = MUTCOLORS + color_src = MUTANT_COLOR /datum/sprite_accessory/tails/ethereal/none name = "None" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/floran_leaves.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/floran_leaves.dm index 6f7e85ee8fe1..b1a7daa17895 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/floran_leaves.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/floran_leaves.dm @@ -1,6 +1,6 @@ /datum/sprite_accessory/floran_leaves icon = 'monkestation/icons/mob/species/floran/floran_leaves.dmi' - color_src = MUTCOLORS_SECONDARY + color_src = MUTANT_COLOR_SECONDARY //Should be MUTCOLORS_SECONDARY, but while its not working it will be the inverse of MUTCOLORS /datum/sprite_accessory/floran_leaves/furnivour diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/goblin_accessories.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/goblin_accessories.dm index b0787c33c9be..abdcc93d8bb1 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/goblin_accessories.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/goblin_accessories.dm @@ -1,6 +1,6 @@ /datum/sprite_accessory/goblin_ears icon = 'monkestation/icons/mob/species/goblin/goblin_ears.dmi' - color_src = MUTCOLORS + color_src = MUTANT_COLOR /datum/sprite_accessory/goblin_ears/normal name = "Normal" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_antenna.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_antenna.dm index b1a9db5a0180..48e9f6b08042 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_antenna.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_antenna.dm @@ -1,10 +1,10 @@ /datum/sprite_accessory/ipc_antennas icon = 'monkestation/icons/mob/species/ipc/ipc_antennas.dmi' - color_src = MUTCOLORS + color_src = MUTANT_COLOR /datum/sprite_accessory/ipc_antennas/none name = "None" - icon_state = "None" + icon_state = "none" /datum/sprite_accessory/ipc_antennas/angled name = "Angled" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_chassis.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_chassis.dm index b2ccc3e5c1ab..a393b010cf57 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_chassis.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_chassis.dm @@ -5,7 +5,7 @@ /datum/sprite_accessory/ipc_chassis/mcgreyscale name = "Morpheus Cyberkinetics (Custom)" - color_src = MUTCOLORS + color_src = MUTANT_COLOR icon_state = "mcgipc" /datum/sprite_accessory/ipc_chassis/bishop_cyberkinetics diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/multi_part.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/multi_part.dm index 573439e85dc8..ee937f1f8373 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/multi_part.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/multi_part.dm @@ -5,7 +5,7 @@ var/list/external_slots = list() /datum/sprite_accessory/body_markings - color_src = MUTCOLORS_SECONDARY + color_src = MUTANT_COLOR_SECONDARY /datum/sprite_accessory/body_markings/light_belly name = "Light Belly" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/sock_color.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/sock_color.dm index 4e9b4b1a343d..9e63e1dfb69a 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/sock_color.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/sock_color.dm @@ -15,4 +15,4 @@ var/species_type = preferences.read_preference(/datum/preference/choiced/species) var/datum/species/species = new species_type - return !(NO_UNDERWEAR in species.species_traits) + return !(TRAIT_NO_UNDERWEAR in species.inherent_traits) diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/tails.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/tails.dm index 5a459b6b1758..55ec414d53cb 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/tails.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/tails.dm @@ -1,6 +1,6 @@ /datum/sprite_accessory/tails/monkey icon = 'monkestation/icons/mob/species/simian/tails.dmi' - color_src = SKINTONES + color_src = SKIN_COLOR /datum/sprite_accessory/tails/monkey/none name = "None" diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm index ef370032bc5d..29e5f5f1aa22 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm @@ -4,8 +4,8 @@ id = SPECIES_ARACHNIDS changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN visual_gender = FALSE - species_traits = list( - MUTCOLORS, + inherent_traits = list( + TRAIT_MUTANT_COLORS, ) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG external_organs = list( diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm index 2f7ded1d0389..feb8ca05560e 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm @@ -21,13 +21,12 @@ brutemod = 1.25 //They're weak to punches payday_modifier = 1 inherent_traits = list( + TRAIT_MUTANT_COLORS, + TRAIT_FIXED_MUTANT_COLORS, + TRAIT_NO_UNDERWEAR, TRAIT_NOHUNGER, TRAIT_NO_BLOODLOSS_DAMAGE, //we handle that species-side. ) - species_traits = list( - DYNCOLORS, - NO_UNDERWEAR, - ) changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_cookie = /obj/item/food/energybar species_language_holder = /datum/language_holder/ethereal diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm index 5f4eee99a967..9ef178f7d8af 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm @@ -3,12 +3,10 @@ plural_form = "Florans" id = SPECIES_FLORAN sexes = TRUE - species_traits = list( - MUTCOLORS, - MUTCOLORS_SECONDARY, - NO_UNDERWEAR, - ) inherent_traits = list( + TRAIT_MUTANT_COLORS, + TRAIT_MUTANT_COLORS_SECONDARY, + TRAIT_NO_UNDERWEAR, TRAIT_PLANT_SAFE, TRAIT_NO_JUMPSUIT, TRAIT_LIMBATTACHMENT, diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm index d1865f5250b0..17df0e9a18ca 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm @@ -4,10 +4,8 @@ id = SPECIES_GOBLIN changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN sexes = TRUE - species_traits = list( - MUTCOLORS, - ) inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_DWARF, TRAIT_QUICK_BUILD, TRAIT_EASILY_WOUNDED, diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm index f4518359d3cb..e994aef71159 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm @@ -5,26 +5,20 @@ bodytype = BODYTYPE_CUSTOM - species_traits = list( - NO_UNDERWEAR, - SPECIES_FUR, - SKINTONES, - ) inherent_traits = list( + TRAIT_FUR_COLORS, + TRAIT_NO_UNDERWEAR, TRAIT_VAULTING, TRAIT_KLEPTOMANIAC, TRAIT_MONKEYFRIEND ) - use_skintones = FALSE - inherent_biotypes = MOB_ORGANIC | MOB_HUMANOID mutanttongue = /obj/item/organ/internal/tongue/monkey changesource_flags = MIRROR_BADMIN | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN meat = /obj/item/food/meat/slab/monkey skinned_type = /obj/item/stack/sheet/animalhide/monkey - uses_fur = TRUE //deathsound = 'monkestation/sound/voice/simian/deathsound.ogg' species_language_holder = /datum/language_holder/monkey maxhealthmod = 0.85 //small = weak diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/skeletons.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/skeletons.dm index 7aec8942833f..2989d92ab723 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/skeletons.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/skeletons.dm @@ -10,13 +10,11 @@ id = SPECIES_DRACONIC_SKELETON sexes = 0 meat = /obj/item/food/meat/slab/human/mutant/skeleton - species_traits = list( - NOTRANSSTING, - NO_DNA_COPY, - NO_UNDERWEAR, - NOHUSK, - ) inherent_traits = list( + TRAIT_NO_TRANSFORMATION_STING, + TRAIT_NO_DNA_COPY, + TRAIT_NO_UNDERWEAR, + TRAIT_NO_HUSK, TRAIT_CAN_USE_FLIGHT_POTION, TRAIT_EASYDISMEMBER, TRAIT_FAKEDEATH, diff --git a/monkestation/code/modules/ranching/icons/satyr_tail.dmi b/monkestation/code/modules/ranching/icons/satyr_tail.dmi index 5a0a9e59a7ef69cf29e11bdcbefdaf84bef9d566..45db6b32ead13a0f43f8491e567c52fbdaf51d04 100644 GIT binary patch delta 64 zcmV-G0Kfmf0>1)~OaX5=agB&vy#_Xr$k=bQvE*k*= delta 63 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

uZ9Lv7h@<$xIWyF%|tE346ORE!Peeme*|l3zXAl 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 literal 7401 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 diff --git a/monkestation/code/modules/the_bird_inside_of_me/prefs.dm b/monkestation/code/modules/the_bird_inside_of_me/prefs.dm index d413c33d1c30..6a12a4bb364f 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/prefs.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/prefs.dm @@ -76,7 +76,7 @@ savefile_key = "feather_color" savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES - relevant_species_trait = TRAIT_FEATHERED + relevant_inherent_trait = TRAIT_FEATHERED /datum/preference/color/feather_color/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["feathers"] = value diff --git a/monkestation/code/modules/the_bird_inside_of_me/species.dm b/monkestation/code/modules/the_bird_inside_of_me/species.dm index 60caede0983a..4e625d37cf2c 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/species.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/species.dm @@ -10,10 +10,6 @@ GLOBAL_LIST_EMPTY(tails_list_avian) name = "\improper Ornithid" plural_form = "Ornithids" id = SPECIES_ORNITHID - species_traits = list( - NO_UNDERWEAR, - TRAIT_FEATHERED, - ) special_step_sounds = list( 'sound/effects/footstep/hardclaw1.ogg', @@ -24,6 +20,8 @@ GLOBAL_LIST_EMPTY(tails_list_avian) ) inherent_traits = list( + TRAIT_NO_UNDERWEAR, + TRAIT_FEATHERED, TRAIT_LIGHT_DRINKER, TRAIT_TACKLING_WINGED_ATTACKER, TRAIT_USES_SKINTONES, diff --git a/monkestation/code/modules/the_wolf_inside_of_me/species.dm b/monkestation/code/modules/the_wolf_inside_of_me/species.dm index 8dec8ab55282..7c32d766edb8 100644 --- a/monkestation/code/modules/the_wolf_inside_of_me/species.dm +++ b/monkestation/code/modules/the_wolf_inside_of_me/species.dm @@ -1,12 +1,9 @@ /datum/species/werewolf name = "werewolf" id = SPECIES_WEREWOLF - species_traits = list( - NO_UNDERWEAR, - ) inherent_traits = list( - TRAIT_USES_SKINTONES, TRAIT_NO_UNDERWEAR, + TRAIT_USES_SKINTONES, TRAIT_NO_AUGMENTS, TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_PUSHIMMUNE, diff --git a/monkestation/icons/mob/anime/anime_bottom.dmi b/monkestation/icons/mob/anime/anime_bottom.dmi index 870e13fc46dd7e29dea4d8aca813799e3cb7cac8..9da4a806305fdf63dbe1e84923ce4d62137dd919 100644 GIT binary patch literal 5713 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 literal 5747 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 G?BaiLP%s1l diff --git a/monkestation/icons/mob/anime/anime_head32x48.dmi b/monkestation/icons/mob/anime/anime_head32x48.dmi index 3237d345d156842624e325eae02a4ed4fc00b08a..19f55db54c719143a9efe73b67b8c9223ff7a849 100644 GIT binary patch delta 939 zcmV;c162IF2fha-iBL{Q4GJ0x0000DNk~Le000310002+1Oos703Erf_y7O^9+4#? zfBL!ew*UYD0d!JMQvg8b*k%9#0Ka-vSad{Xb7OL8aCB*JZU6vyoSo7=3&JoEfZ;j$ z6`|e5uffHov}y+xJJEN^0Z7xJ$|1i&l;E zY9`ByQ_1tcIuzDw=OILxQyT$$A*I0x^&3Wz(li3l4v!PT{=^Yk}V|p11>nqY@C!Ce~844 zgt|viF=u4VR9$$Ye4*UXzO#68Py%!LhjnUB@$AJBBH8<>X; zOmqX0dOi0m%U5?FkAGQt3mY(}^7oY<@1LOlBm1fX-wxXKr{0|&2LJ#70001h9_P)@ zRp9(B^6_?Rz1{&;vkHstGC1MVf0qr!>h%t|wZV;SpzJoVmJM9mAgO`De{HiKuYtj3 zv!*n#**+e(0lz$M14Zv0csyzYZezK82bNn4PU!7PHQ=87@*$-G+rF(I8}v@Ml=U9W z$$H89pMxfTG710y00000Ks#;yjHTY}j!~~=Z^L@2e+ljJSoV;5f!BR~NxS{447J8b zLw$7z)oUB>PU{=?EHlCQe-Hf-4yhM1N`ZENMERI-M=lW5}-Dw0+I%eQVjk^dhkVS07NR zd*;ew-kK6A-^j^+vZ}tIv~O6f$1~l)x@doABfqKSgiKXaFQox1##1j}t70Dfe}6fV z-v$^j#`-0Bw}D6?+>YGg!WU@`MCTEkcXv$QOZ}ESF&Y2>007|c`32d>P1)g+FnRz0 N002ovPDHLkV1iZVwekP} delta 935 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 literal 7710 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 diff --git a/monkestation/icons/mob/species/ethereal/ethereal_tail.dmi b/monkestation/icons/mob/species/ethereal/ethereal_tail.dmi index 3774c4c41b031be96ef88533cbe2ba355bf33a6e..abbd8f730602c03449793db0230107657322cba1 100644 GIT binary patch literal 1470 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 XLV;s*k#Jvk00000NkvXXu0mjfrNyeR diff --git a/monkestation/icons/mob/species/ipc/ipc_antennas.dmi b/monkestation/icons/mob/species/ipc/ipc_antennas.dmi index 5880237edf04b9c090594c542e0a56c9ec424ab0..63adaed38176394bde72aedde9d102d947b2193b 100644 GIT binary patch literal 3184 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 diff --git a/monkestation/icons/mob/species/simian/tails.dmi b/monkestation/icons/mob/species/simian/tails.dmi index 907cabbfd03f09b1f9001be0a473cff0568d12fd..67fa393fd1a7bd8e80706edc03af7f96fdb93a82 100644 GIT binary patch delta 6477 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 F`aijq+35fP delta 6428 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 Qeg&a3)Hl_u)NzXYAK751G5`Po From fe0e535b071ff492c197ae3e47c48e12aa785e8e Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:59:46 -0700 Subject: [PATCH 079/158] Update vampire.dm --- code/modules/client/preferences/species_features/vampire.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/modules/client/preferences/species_features/vampire.dm b/code/modules/client/preferences/species_features/vampire.dm index 16eef0905276..710dd37a1f28 100644 --- a/code/modules/client/preferences/species_features/vampire.dm +++ b/code/modules/client/preferences/species_features/vampire.dm @@ -22,6 +22,9 @@ GLOBAL_LIST_EMPTY(vampire_houses) /datum/preference/choiced/vampire_status/apply_to_human(mob/living/carbon/human/target, value) + if(!HAS_TRAIT(target, TRAIT_BLOOD_CLANS)) + return + if(value != "Inoculated") return From f29e6a7e153b67c410c02a001e119e777f78a1c7 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 21:21:27 -0700 Subject: [PATCH 080/158] fixes two --- code/modules/client/preferences.dm | 5 ++++- code/modules/surgery/bodyparts/parts.dm | 12 ++++++------ .../bodyparts/species_parts/misc_bodyparts.dm | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 4a0de8b85be7..bc57af9ec645 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -489,10 +489,13 @@ GLOBAL_LIST_EMPTY(preferences_datums) /datum/preferences/proc/apply_prefs_to(mob/living/carbon/human/character, icon_updates = TRUE) character.dna.features = list() + var/species_type = read_preference(/datum/preference/choiced/species) + var/datum/species/species = new species_type for (var/datum/preference/preference as anything in get_preferences_in_priority_order()) if (preference.savefile_identifier != PREFERENCE_CHARACTER) continue - + if(preference.relevant_inherent_trait && !(preference.relevant_inherent_trait in species.inherent_traits)) + continue preference.apply_to_human(character, read_preference(preference.type)) character.dna.real_name = character.real_name diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index 62629e9f805c..cd718d50d211 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -14,7 +14,7 @@ wound_resistance = 10 bodypart_trait_source = CHEST_TRAIT ///The bodytype(s) allowed to attach to this chest. - var/acceptable_bodytype = BODYTYPE_HUMANOID + var/acceptable_bodytype = BODYTYPE_HUMANOID | BODYTYPE_DIGITIGRADE var/icon/ass_image var/list/wing_types = list(/obj/item/organ/external/wings/functional/angel) @@ -55,12 +55,12 @@ icon_static = 'icons/mob/species/alien/bodyparts.dmi' icon_state = "alien_chest" limb_id = BODYPART_ID_ALIEN - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE is_dimorphic = FALSE should_draw_greyscale = FALSE bodypart_flags = BODYPART_UNREMOVABLE max_damage = 500 - acceptable_bodytype = BODYTYPE_HUMANOID + acceptable_bodytype = BODYTYPE_HUMANOID | BODYTYPE_DIGITIGRADE /obj/item/bodypart/chest/larva icon = 'icons/mob/species/alien/bodyparts.dmi' @@ -191,7 +191,7 @@ icon_static = 'icons/mob/species/alien/bodyparts.dmi' icon_state = "alien_l_arm" limb_id = BODYPART_ID_ALIEN - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE px_x = 0 px_y = 0 bodypart_flags = BODYPART_UNREMOVABLE @@ -294,7 +294,7 @@ icon_static = 'icons/mob/species/alien/bodyparts.dmi' icon_state = "alien_r_arm" limb_id = BODYPART_ID_ALIEN - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE px_x = 0 px_y = 0 bodypart_flags = BODYPART_UNREMOVABLE @@ -308,7 +308,7 @@ desc = "This item shouldn't exist. Talk about breaking a leg. Badum-Tss!" attack_verb_continuous = list("kicks", "stomps") attack_verb_simple = list("kick", "stomp") - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE max_damage = 50 body_damage_coeff = 0.75 can_be_disabled = TRUE diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index 493bd808f2da..c0a3db77a796 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -390,7 +390,7 @@ /obj/item/bodypart/chest/golem biological_state = BIO_BONE - acceptable_bodytype = BODYTYPE_ORGANIC + acceptable_bodytype = BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE bodytype = BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM is_dimorphic = TRUE From 74e56e8325ed31a30112fd6b718f5efa438cd594 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 21:44:57 -0700 Subject: [PATCH 081/158] Update _tongue.dm --- code/modules/surgery/organs/internal/tongue/_tongue.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/surgery/organs/internal/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm index df2a931b2a55..33e218ddcf6a 100644 --- a/code/modules/surgery/organs/internal/tongue/_tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -140,9 +140,9 @@ else REMOVE_TRAIT(owner, TRAIT_AGEUSIA, ORGAN_TRAIT) if(organ_flags & ORGAN_FAILING) - ADD_TRAIT(owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE) - else REMOVE_TRAIT(owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE) + else + ADD_TRAIT(owner, TRAIT_SPEAKS_CLEARLY, SPEAKING_FROM_TONGUE) /obj/item/organ/internal/tongue/could_speak_language(datum/language/language_path) return (language_path in languages_possible) From 8fdfbc92db22da9312632a441c8eb2202271e122 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 23:06:27 -0700 Subject: [PATCH 082/158] new giving component --- .../signals/signals_mob/signals_mob_main.dm | 4 ++ code/_onclick/hud/alert.dm | 11 ++-- code/datums/status_effects/neutral.dm | 13 +++-- code/modules/mob/living/carbon/inventory.dm | 14 +++-- .../blood_datum/components/item_receiver.dm | 56 +++++++++++++++++++ monkestation/code/modules/botany/potty.dm | 2 +- tgstation.dme | 1 + 7 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 monkestation/code/modules/blood_datum/components/item_receiver.dm diff --git a/code/__DEFINES/~monkestation/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/~monkestation/dcs/signals/signals_mob/signals_mob_main.dm index 46bff024c98c..969145aeec56 100644 --- a/code/__DEFINES/~monkestation/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/~monkestation/dcs/signals/signals_mob/signals_mob_main.dm @@ -40,3 +40,7 @@ #define COMSIG_CARBON_PAINED_STEP "carbon_pain_step" /// Stop the pain from happening #define STOP_PAIN (1<<0) + +#define COMSIG_LIVING_GIVE_ITEM_CHECK "living_give_item_check" + +#define COMSIG_LIVING_ITEM_OFFERED_PRECHECK "living_item_offer_precheck" diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 38d7a880e188..b4d62bf89221 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -374,7 +374,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." * * offerer - The person giving the alert and item * * receiving - The item being given by the offerer */ -/atom/movable/screen/alert/give/proc/setup(mob/living/carbon/taker, datum/status_effect/offering/offer) +/atom/movable/screen/alert/give/proc/setup(mob/living/taker, datum/status_effect/offering/offer) src.offer = offer var/mob/living/offerer = offer.owner @@ -415,12 +415,15 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." handle_transfer() /// An overrideable proc used simply to hand over the item when claimed, this is a proc so that high-fives can override them since nothing is actually transferred -/atom/movable/screen/alert/give/proc/handle_transfer() - var/mob/living/carbon/taker = owner +/atom/movable/screen/alert/give/proc/handle_transfer(visible_message = TRUE) + var/mob/living/taker = owner var/mob/living/offerer = offer.owner var/obj/item/receiving = offer.offered_item - taker.take(offerer, receiving) + if(!taker.take(offerer, receiving, visible_message)) + return FALSE + SEND_SIGNAL(offerer, COMSIG_CARBON_ITEM_GIVEN, taker, receiving) + return TRUE /atom/movable/screen/alert/give/highfive additional_desc_text = "Click this alert to slap it." diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index b9428e2d250b..c3d684560c26 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -163,7 +163,7 @@ /// The type of alert given to people when offered, in case you need to override some behavior (like for high-fives) var/give_alert_type = /atom/movable/screen/alert/give -/datum/status_effect/offering/on_creation(mob/living/new_owner, obj/item/offer, give_alert_override, mob/living/carbon/offered) +/datum/status_effect/offering/on_creation(mob/living/new_owner, obj/item/offer, give_alert_override, mob/living/offered) . = ..() if(!.) return @@ -171,11 +171,11 @@ if(give_alert_override) give_alert_type = give_alert_override - if(offered && is_taker_elligible(offered)) + if(offered && is_taker_elligible(offered, offer)) register_candidate(offered) else - for(var/mob/living/carbon/possible_taker in orange(1, owner)) - if(!is_taker_elligible(possible_taker)) + for(var/mob/living/possible_taker in orange(1, owner)) + if(!is_taker_elligible(possible_taker, offer)) continue register_candidate(possible_taker) @@ -202,6 +202,7 @@ LAZYADD(possible_takers, possible_candidate) RegisterSignal(possible_candidate, COMSIG_MOVABLE_MOVED, PROC_REF(check_taker_in_range)) G.setup(possible_candidate, src) + SEND_SIGNAL(possible_candidate, COMSIG_LIVING_GIVE_ITEM_CHECK, G, offered_item) /// Remove the alert and signals for the specified carbon mob. Automatically removes the status effect when we lost the last taker /datum/status_effect/offering/proc/remove_candidate(mob/living/carbon/removed_candidate) @@ -239,8 +240,8 @@ * * Returns `TRUE` if the taker is valid as a target for the offering. */ -/datum/status_effect/offering/proc/is_taker_elligible(mob/living/carbon/taker) - return owner.CanReach(taker) && !IS_DEAD_OR_INCAP(taker) && additional_taker_check(taker) +/datum/status_effect/offering/proc/is_taker_elligible(mob/living/carbon/taker, obj/item/offer) + return (owner.CanReach(taker) && !IS_DEAD_OR_INCAP(taker) && additional_taker_check(taker)) || SEND_SIGNAL(taker, COMSIG_LIVING_ITEM_OFFERED_PRECHECK, offer) /** * Additional checks added to `CanReach()` and `IS_DEAD_OR_INCAP()` in `is_taker_elligible()`. diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index 3e462fc976f2..a505943c521d 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -365,7 +365,7 @@ * * This handles creating an alert and adding an overlay to it */ -/mob/living/carbon/proc/give(mob/living/carbon/offered) +/mob/living/proc/give(mob/living/offered) if(has_status_effect(/datum/status_effect/offering)) to_chat(src, span_warning("You're already offering something!")) return @@ -400,7 +400,7 @@ to_chat(src, span_warning("You have to be beside [offered.p_them()]!")) return else - if(!(locate(/mob/living/carbon) in orange(1, src))) + if(!(locate(/mob/living) in orange(1, src))) to_chat(src, span_warning("There's nobody beside you to take it!")) return @@ -421,7 +421,7 @@ * * offerer - The person giving the original item * * I - The item being given by the offerer */ -/mob/living/carbon/proc/take(mob/living/carbon/offerer, obj/item/I) +/mob/living/proc/take(mob/living/carbon/offerer, obj/item/I, visible_message = TRUE) clear_alert("[offerer]") if(IS_DEAD_OR_INCAP(src)) to_chat(src, span_warning("You're unable to take anything in your current state!")) @@ -443,9 +443,13 @@ visible_message(span_notice("[offerer] tries to hand over [I] but it's stuck to them....")) return - visible_message(span_notice("[src] takes [I] from [offerer]."), \ - span_notice("You take [I] from [offerer].")) + if(visable_message) + visible_message(span_notice("[src] takes [I] from [offerer]."), \ + span_notice("You take [I] from [offerer].")) + else + to_chat(src, span_notice("You take [I] from [offerer].")) put_in_hands(I) + return TRUE ///Returns a list of all body_zones covered by clothing /mob/living/carbon/proc/get_covered_body_zones() diff --git a/monkestation/code/modules/blood_datum/components/item_receiver.dm b/monkestation/code/modules/blood_datum/components/item_receiver.dm new file mode 100644 index 000000000000..4cd8bd080bed --- /dev/null +++ b/monkestation/code/modules/blood_datum/components/item_receiver.dm @@ -0,0 +1,56 @@ +/datum/component/item_receiver + var/list/item_types = list() + var/take_message + +/datum/component/item_receiver/Initialize(list/types = list(), take_message) + . = ..() + var/mob/living/living_parent = parent + if(!living_parent.usable_hands) + return COMPONENT_INCOMPATIBLE + + item_types = types + src.take_message = take_message + +/datum/component/item_receiver/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_LIVING_ITEM_OFFERED_PRECHECK, PROC_REF(precheck_item)) + RegisterSignal(parent, COMSIG_LIVING_GIVE_ITEM_CHECK, PROC_REF(try_take_item)) + +/datum/component/item_receiver/UnregisterFromParent() + . = ..() + UnregisterSignal(parent, list(COMSIG_LIVING_ITEM_OFFERED_PRECHECK, COMSIG_LIVING_GIVE_ITEM_CHECK)) + +/datum/component/item_receiver/proc/precheck_item(datum/source, obj/item/offer) + if(!length(item_types)) + return TRUE + + for(var/item as anything in item_types) + if(istype(offer, item)) + return TRUE + + return FALSE + + +/datum/component/item_receiver/proc/try_take_item(datum/source, atom/movable/screen/alert/give/alert, obj/item/offer) + var/can_take = FALSE + for(var/item as anything in item_types) + if(istype(offer, item)) + can_take = TRUE + break + + if(!can_take) + return FALSE + + var/visible_message = TRUE + if(take_message) + visible_message = FALSE + + if(!alert.handle_transfer(visible_message)) + return FALSE + + if(take_message) + var/atom/movable/movable = parent + movable.visible_message(span_notice("[movable] [take_message] [offer]")) + + return TRUE + diff --git a/monkestation/code/modules/botany/potty.dm b/monkestation/code/modules/botany/potty.dm index e3d45f6149f0..5a1a5d39af38 100644 --- a/monkestation/code/modules/botany/potty.dm +++ b/monkestation/code/modules/botany/potty.dm @@ -26,7 +26,7 @@ /mob/living/basic/pet/potty/Initialize(mapload) . = ..() - + AddComponent(/datum/component/item_receiver, list(/obj/item/reagent_containers/cup/watering_can), "happily takes") AddComponent(/datum/component/plant_tray_overlay, icon, null, null, null, null, null, null, 3, 8) AddComponent(/datum/component/plant_growing) AddComponent(/datum/component/obeys_commands, pet_commands) diff --git a/tgstation.dme b/tgstation.dme index 59663e6c06e0..88e7617b862c 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -6328,6 +6328,7 @@ #include "monkestation\code\modules\blood_datum\designs.dm" #include "monkestation\code\modules\blood_datum\forensics_helpers.dm" #include "monkestation\code\modules\blood_datum\stunning.dm" +#include "monkestation\code\modules\blood_datum\components\item_receiver.dm" #include "monkestation\code\modules\blood_datum\components\limbless_aid.dm" #include "monkestation\code\modules\blood_datum\elements\easy_ignite.dm" #include "monkestation\code\modules\blood_datum\items\crutch.dm" From e3d72f54f46766fa97966c4312ae19e929722cd6 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 17 Sep 2024 23:10:13 -0700 Subject: [PATCH 083/158] web edits --- monkestation/code/modules/botany/potty.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/botany/potty.dm b/monkestation/code/modules/botany/potty.dm index 55246f26522f..9a82db572fb0 100644 --- a/monkestation/code/modules/botany/potty.dm +++ b/monkestation/code/modules/botany/potty.dm @@ -26,7 +26,7 @@ /mob/living/basic/pet/potty/Initialize(mapload) ..() - AddComponent(/datum/component/item_receiver, list(/obj/item/reagent_containers/cup/watering_can), "happily takes") + AddComponent(/datum/component/item_receiver, list(/obj/item/reagent_containers/cup/watering_can), "happily takes") AddComponent(/datum/component/plant_tray_overlay, icon, null, null, null, null, null, null, 3, 8) AddComponent(/datum/component/plant_growing) AddComponent(/datum/component/obeys_commands, pet_commands) From 1f25f010faf2dec3db88e38935b0e71ca2c68114 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:42:17 -0700 Subject: [PATCH 084/158] Update inventory.dm --- code/modules/mob/living/carbon/inventory.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index a505943c521d..a552c8a07974 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -443,7 +443,7 @@ visible_message(span_notice("[offerer] tries to hand over [I] but it's stuck to them....")) return - if(visable_message) + if(visible_message) visible_message(span_notice("[src] takes [I] from [offerer]."), \ span_notice("You take [I] from [offerer].")) else From d950ae1ca91b6c139e049ea0dcc399c950183c93 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:30:13 -0700 Subject: [PATCH 085/158] fixes --- code/modules/surgery/bodyparts/parts.dm | 12 ++++++------ .../bodyparts/species_parts/misc_bodyparts.dm | 2 +- .../code/modules/ranching/satyr/bodyparts.dm | 1 + .../code/modules/the_bird_inside_of_me/species.dm | 4 +++- .../code/modules/the_wolf_inside_of_me/bodyparts.dm | 1 + 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index cd718d50d211..62629e9f805c 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -14,7 +14,7 @@ wound_resistance = 10 bodypart_trait_source = CHEST_TRAIT ///The bodytype(s) allowed to attach to this chest. - var/acceptable_bodytype = BODYTYPE_HUMANOID | BODYTYPE_DIGITIGRADE + var/acceptable_bodytype = BODYTYPE_HUMANOID var/icon/ass_image var/list/wing_types = list(/obj/item/organ/external/wings/functional/angel) @@ -55,12 +55,12 @@ icon_static = 'icons/mob/species/alien/bodyparts.dmi' icon_state = "alien_chest" limb_id = BODYPART_ID_ALIEN - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC is_dimorphic = FALSE should_draw_greyscale = FALSE bodypart_flags = BODYPART_UNREMOVABLE max_damage = 500 - acceptable_bodytype = BODYTYPE_HUMANOID | BODYTYPE_DIGITIGRADE + acceptable_bodytype = BODYTYPE_HUMANOID /obj/item/bodypart/chest/larva icon = 'icons/mob/species/alien/bodyparts.dmi' @@ -191,7 +191,7 @@ icon_static = 'icons/mob/species/alien/bodyparts.dmi' icon_state = "alien_l_arm" limb_id = BODYPART_ID_ALIEN - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC px_x = 0 px_y = 0 bodypart_flags = BODYPART_UNREMOVABLE @@ -294,7 +294,7 @@ icon_static = 'icons/mob/species/alien/bodyparts.dmi' icon_state = "alien_r_arm" limb_id = BODYPART_ID_ALIEN - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ALIEN | BODYTYPE_ORGANIC px_x = 0 px_y = 0 bodypart_flags = BODYPART_UNREMOVABLE @@ -308,7 +308,7 @@ desc = "This item shouldn't exist. Talk about breaking a leg. Badum-Tss!" attack_verb_continuous = list("kicks", "stomps") attack_verb_simple = list("kick", "stomp") - bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC max_damage = 50 body_damage_coeff = 0.75 can_be_disabled = TRUE diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index c0a3db77a796..493bd808f2da 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -390,7 +390,7 @@ /obj/item/bodypart/chest/golem biological_state = BIO_BONE - acceptable_bodytype = BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE + acceptable_bodytype = BODYTYPE_ORGANIC bodytype = BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM is_dimorphic = TRUE diff --git a/monkestation/code/modules/ranching/satyr/bodyparts.dm b/monkestation/code/modules/ranching/satyr/bodyparts.dm index a5f2241aa4b8..49a646ae0f30 100644 --- a/monkestation/code/modules/ranching/satyr/bodyparts.dm +++ b/monkestation/code/modules/ranching/satyr/bodyparts.dm @@ -8,6 +8,7 @@ icon_greyscale = 'monkestation/code/modules/ranching/icons/bodyparts.dmi' limb_id = SPECIES_SATYR is_dimorphic = TRUE + acceptable_bodytype = BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE /obj/item/bodypart/arm/left/satyr icon_greyscale = 'monkestation/code/modules/ranching/icons/bodyparts.dmi' diff --git a/monkestation/code/modules/the_bird_inside_of_me/species.dm b/monkestation/code/modules/the_bird_inside_of_me/species.dm index 4e625d37cf2c..c8e33c9c0dee 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/species.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/species.dm @@ -38,7 +38,7 @@ GLOBAL_LIST_EMPTY(tails_list_avian) BODY_ZONE_HEAD = /obj/item/bodypart/head, // just because they are still *partially* human, or otherwise human resembling BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/ornithid, BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/ornithid, - BODY_ZONE_CHEST = /obj/item/bodypart/chest, + BODY_ZONE_CHEST = /obj/item/bodypart/chest/ornithid, ) species_pain_mod = 1.20 // Fuck it, this will fill a niche that isn't implemented yet. changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT @@ -79,6 +79,8 @@ GLOBAL_LIST_EMPTY(tails_list_avian) unarmed_attack_sound = 'sound/weapons/slice.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' +/obj/item/bodypart/chest/ornithid + acceptable_bodytype = BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE /obj/item/bodypart/leg/left/ornithid limb_id = SPECIES_ORNITHID diff --git a/monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm b/monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm index 0a47f64e4b80..f66e3d6be7b6 100644 --- a/monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm +++ b/monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm @@ -41,6 +41,7 @@ biological_state = (BIO_FLESH|BIO_BLOODED) bodypart_traits = list(TRAIT_NO_JUMPSUIT, TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_PUSHIMMUNE, TRAIT_STUNIMMUNE) wing_types = null + acceptable_bodytype = BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE /obj/item/bodypart/arm/left/werewolf limb_id = SPECIES_WEREWOLF From 220da36491b31fb298a04a7c2a82930033fcd3e5 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:39:31 -0700 Subject: [PATCH 086/158] Update _base.dm --- .../code/modules/virology/disease/base_disease_folder/_base.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/virology/disease/base_disease_folder/_base.dm b/monkestation/code/modules/virology/disease/base_disease_folder/_base.dm index fcb845a452ef..cd32a3929b1c 100644 --- a/monkestation/code/modules/virology/disease/base_disease_folder/_base.dm +++ b/monkestation/code/modules/virology/disease/base_disease_folder/_base.dm @@ -208,7 +208,7 @@ GLOBAL_LIST_INIT(virusDB, list()) e.run_effect(mob, src) //fever is a reaction of the body's immune system to the infection. The higher the antibody concentration (and the disease still not cured), the higher the fever - if (mob.bodytemperature < BODYTEMP_HEAT_DAMAGE_LIMIT)//but we won't go all the way to burning up just because of a fever, probably + if (mob.bodytemperature < mob.bodytemp_heat_damage_limit)//but we won't go all the way to burning up just because of a fever, probably var/fever = round((robustness / 100) * (immune_data[2] / 10) * (stage / max_stages)) switch (mob.mob_size) if (MOB_SIZE_TINY) From 4ec45ca035bbfe6833eae3884ca20061a5d63649 Mon Sep 17 00:00:00 2001 From: Lucy Date: Wed, 18 Sep 2024 20:30:28 -0400 Subject: [PATCH 087/158] fix some simple runtimes --- code/modules/mob/living/blood.dm | 2 +- code/modules/mob/living/living_defense.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index d84366ee2ecb..945ef89af5c0 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -292,7 +292,7 @@ //to add a splatter of blood or other mob liquid. /mob/living/proc/add_splatter_floor(turf/blood_turf = get_turf(src), small_drip) // Create a bit of metallic pollution, as that's how blood smells - blood_turf.pollute_turf(/datum/pollutant/metallic_scent, 30) // TODO Move to blood_datum + blood_turf?.pollute_turf(/datum/pollutant/metallic_scent, 30) // TODO Move to blood_datum return get_blood_type()?.make_blood_splatter(src, blood_turf, small_drip) /mob/living/proc/do_splatter_effect(splat_dir = pick(GLOB.cardinals)) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index e7e0d11b58a7..2594aaee786e 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -131,7 +131,7 @@ var/extra_paralyze = 0 SECONDS var/extra_knockdown = 0 SECONDS - if(hitting_projectile.damage_type == BRUTE && !hitting_projectile.grazing && (pain_controller.get_average_pain() > 50)) + if(hitting_projectile.damage_type == BRUTE && !hitting_projectile.grazing && (pain_controller?.get_average_pain() > 50)) if(damage_done >= 60) if(!IsParalyzed() && prob(damage_done)) extra_paralyze += 0.8 SECONDS From 68bba7af8de3f00496541e0b1f20102d81f83924 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:22:21 -0700 Subject: [PATCH 088/158] inverted --- code/datums/components/tackle.dm | 42 +------- code/game/atom_defense.dm | 5 + code/game/objects/obj_defense.dm | 96 ++++++++++++++++++- code/modules/mob/living/carbon/carbon.dm | 6 +- code/modules/projectiles/projectile.dm | 21 ++-- .../surgery/organs/internal/tongue/_tongue.dm | 7 ++ .../carbon/human/species_type/floran.dm | 2 +- .../storytellers/gamemode_subsystem.dm | 1 + 8 files changed, 124 insertions(+), 56 deletions(-) diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index fb98747d2ed3..9ccf58e71431 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -367,25 +367,12 @@ var/obj/machinery/vending/darth_vendor = hit darth_vendor.tilt(user, 100) return - else if(istype(hit, /obj/structure/window)) - var/obj/structure/window/W = hit - splatWindow(user, W) - if(QDELETED(W)) - return COMPONENT_MOVABLE_IMPACT_NEVERMIND - return - var/oopsie_mod = 0 var/danger_zone = (speed - 1) * 13 // for every extra speed we have over 1, take away 13 of the safest chance danger_zone = max(min(danger_zone, 100), 1) - if(ishuman(user)) - var/mob/living/carbon/human/S = user - var/head_slot = S.get_item_by_slot(ITEM_SLOT_HEAD) - var/suit_slot = S.get_item_by_slot(ITEM_SLOT_OCLOTHING) - if(head_slot && (istype(head_slot,/obj/item/clothing/head/helmet) || istype(head_slot,/obj/item/clothing/head/utility/hardhat))) - oopsie_mod -= 6 - if(suit_slot && (istype(suit_slot,/obj/item/clothing/suit/armor/riot))) - oopsie_mod -= 6 + oopsie_mod -= floor(user.getarmor(BODY_ZONE_HEAD, MELEE) * 0.18) + oopsie_mod -= floor(user.getarmor(BODY_ZONE_CHEST, MELEE) * 0.12) if(HAS_TRAIT(user, TRAIT_CLUMSY)) oopsie_mod += 6 //honk! @@ -476,31 +463,6 @@ QDEL_NULL(tackle_ref) UnregisterSignal(parent, COMSIG_MOVABLE_MOVED) -///A special case for splatting for handling windows -/datum/component/tackler/proc/splatWindow(mob/living/carbon/user, obj/structure/window/W) - playsound(user, 'sound/effects/Glasshit.ogg', 140, TRUE) - - if(W.type in list(/obj/structure/window, /obj/structure/window/fulltile, /obj/structure/window/unanchored, /obj/structure/window/fulltile/unanchored)) // boring unreinforced windows - for(var/i in 1 to speed) - var/obj/item/shard/shard = new /obj/item/shard(get_turf(user)) - shard.embedding = list(embed_chance = 100, ignore_throwspeed_threshold = TRUE, impact_pain_mult=3, pain_chance=5) - shard.updateEmbedding() - user.hitby(shard, skipcatch = TRUE, hitpush = FALSE) - shard.embedding = null - shard.updateEmbedding() - W.atom_destruction() - user.stamina.adjust(-10 * speed) - user.Paralyze(3 SECONDS) - user.visible_message(span_danger("[user] smacks into [W] and shatters it, shredding [user.p_them()]self with glass!"), span_userdanger("You smacks into [W] and shatter it, shredding yourself with glass!")) - - else - user.visible_message(span_danger("[user] smacks into [W] like a bug!"), span_userdanger("You smacks into [W] like a bug!")) - user.Paralyze(1 SECONDS) - user.Knockdown(3 SECONDS) - W.take_damage(30 * speed) - user.stamina.adjust(-10 * speed) - user.adjustBruteLoss(5 * speed) - /datum/component/tackler/proc/delayedSmash(obj/structure/window/W) if(W) W.atom_destruction() diff --git a/code/game/atom_defense.dm b/code/game/atom_defense.dm index 169d0bf71a80..43422bf2fcba 100644 --- a/code/game/atom_defense.dm +++ b/code/game/atom_defense.dm @@ -58,6 +58,11 @@ SHOULD_BE_PURE(TRUE) return atom_integrity +/// Similar to get_integrity, but returns the percentage as [0-1] instead. +/atom/proc/get_integrity_percentage() + SHOULD_BE_PURE(TRUE) + return round(atom_integrity / max_integrity, 0.01) + ///returns the damage value of the attack after processing the atom's various armor protections /atom/proc/run_atom_armor(damage_amount, damage_type, damage_flag = 0, attack_dir, armour_penetration = 0) if(!uses_integrity) diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index f37d84088ed2..cf51a4c983ae 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -1,7 +1,85 @@ /obj/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) - ..() - take_damage(AM.throwforce, BRUTE, MELEE, 1, get_dir(src, AM)) + . = ..() + if(QDELETED(src)) + return + hit_by_damage(AM, throwingdatum) + +/obj/proc/hit_by_damage(atom/movable/hitting_us, datum/thrownthing/throwingdatum) + var/base_dam = hitting_us.throwforce + if(isliving(hitting_us)) + var/mob/living/living_mob = hitting_us + var/speed_bonus = throwingdatum.speed - living_mob.throw_speed + if(speed_bonus > 0) + base_dam += (5 * speed_bonus) + base_dam += (5 * max(0, living_mob.mob_size - 1)) + if(isitem(hitting_us)) + var/obj/item/hit_item = hitting_us + base_dam += (5 * max(0, hit_item.w_class - 2)) + + // no armor penetration + take_damage(base_dam, BRUTE, MELEE, TRUE, get_dir(src, hitting_us), 0) + +/obj/structure/window/Initialize(mapload, direct) + . = ..() + +/obj/structure/window/Cross(atom/movable/crossed_atom) + . = ..() + if(.) + return . + if(!isliving(crossed_atom) || QDELETED(crossed_atom.throwing)) + return . + if(anchored && get_integrity_percentage() > 0.5) + return . + + var/turf/old_loc = loc + + take_damage(INFINITY, BRUTE, MELEE, TRUE, get_dir(src, crossed_atom), 0) + + if(!QDELETED(src)) + return . + + var/mob/living/defenestrated = crossed_atom + var/has_grille = locate(/obj/structure/grille) in old_loc + var/list/obj/item/shards = list() + for(var/obj/item/shard/shard in old_loc) + shards += shard + + for(var/zone in shuffle(BODY_ZONES_ALL)) + var/obj/item/bodypart/part = defenestrated.get_bodypart(zone) + if(!part) + continue + if(has_grille && prob(66)) + continue + + defenestrated.apply_damage(10, BRUTE, part, blocked = min(90, defenestrated.getarmor(part, MELEE)), sharpness = SHARP_POINTY, wound_bonus = 4, bare_wound_bonus = 8, attacking_item = (length(shards) ? shards[1] : "glass")) + if(prob(25 * length(shards)) && shards[1].tryEmbed(part, TRUE)) + shards -= shards[1] + + if(has_grille) + defenestrated.Paralyze(1 SECONDS) + defenestrated.Knockdown(2 SECONDS) + defenestrated.visible_message( + span_danger("[defenestrated] is thrown against [src], shattering it!"), + span_userdanger("You are thrown against [src], shattering it!"), + ) + + else + defenestrated.Paralyze(3 SECONDS) + defenestrated.Knockdown(6 SECONDS) + defenestrated.visible_message( + span_danger("[defenestrated] is thrown clean through [src]!"), + span_userdanger("You are thrown clean through [src]!"), + ) + + return TRUE + +/obj/structure/window/hit_by_damage(atom/movable/hitting_us, datum/thrownthing/throwingdatum) + if(reinf || !isliving(hitting_us)) + return ..() + + // take a lot of damage from being hit with a mob - so we can defenestrate + take_damage(max_integrity * min(0.75, (get_armor_rating(MELEE) / 100)), BRUTE, MELEE, TRUE, get_dir(src, hitting_us), 0) /obj/ex_act(severity, target) if(resistance_flags & INDESTRUCTIBLE) @@ -47,6 +125,20 @@ return damage_sustained > 0 ? BULLET_ACT_HIT : BULLET_ACT_BLOCK +/obj/structure/window/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit) + // don't smack the window and its grille same turf, ever + for(var/obj/structure/grille/grille in loc) + hitting_projectile.impacted[grille] = TRUE + + . = ..() + if(QDELETED(hitting_projectile) || . != BULLET_ACT_HIT) + return . + if(QDELETED(src) && prob(80)) + // right through the window! + return BULLET_ACT_FORCE_PIERCE + return . + + /obj/attack_hulk(mob/living/carbon/human/user) ..() if(density) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 900a43d4d38c..2ebae64002d9 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -78,8 +78,10 @@ take_bodypart_damage(10 + 5 * extra_speed, check_armor = TRUE, wound_bonus = extra_speed * 5) victim.Paralyze(2 SECONDS) Paralyze(2 SECONDS) - visible_message(span_danger("[src] crashes into [victim][extra_speed ? " really hard" : ""], knocking them both over!"),\ - span_userdanger("You violently crash into [victim][extra_speed ? " extra hard" : ""]!")) + visible_message( + span_danger("[src] crashes into [hit_atom][extra_speed ? " really hard" : ""]!"), + span_userdanger("You[extra_speed ? " violently" : ""] crash into [hit_atom][extra_speed ? " extra hard" : ""]!"), + ) playsound(src,'sound/weapons/punch1.ogg',50,TRUE) log_combat(src, victim, "crashed into") diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 97f144a1504b..c3f0a45e2aa4 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -281,18 +281,18 @@ hitx = target.pixel_x + rand(-8, 8) hity = target.pixel_y + rand(-8, 8) - if(damage > 0 && (damage_type == BRUTE || damage_type == BURN) && iswallturf(target_turf) && prob(75)) - var/turf/closed/wall/target_wall = target_turf - if(impact_effect_type && !hitscan) - new impact_effect_type(target_wall, hitx, hity) - - target_wall.add_dent(WALL_DENT_SHOT, hitx, hity) - - return BULLET_ACT_HIT + if((isturf(target) || (isobj(target) && target.density)) && hitsound_wall) + var/volume = clamp(vol_by_damage() + 20, 0, 100) + if(suppressed) + volume = 5 + playsound(loc, hitsound_wall, volume, TRUE, -1) if(!isliving(target)) if(impact_effect_type && !hitscan) new impact_effect_type(target_turf, hitx, hity) + if(damage > 0 && (damage_type == BRUTE || damage_type == BURN) && iswallturf(target_turf) && prob(75)) + var/turf/closed/wall/target_wall = target_turf + target_wall.add_dent(WALL_DENT_SHOT, hitx, hity) if(isturf(target) && hitsound_wall) var/volume = clamp(vol_by_damage() + 20, 0, 100) if(suppressed) @@ -333,8 +333,7 @@ playsound(loc, hitsound, 5, TRUE, -1) to_chat(living_target, span_userdanger("You're [grazing ? "grazed" : "hit"] by \a [generic_name || src][organ_hit_text]!")) else - if(hitsound) - playsound(src, hitsound, vol_by_damage(), TRUE, -1) + playsound(loc, hitsound, vol_by_damage(), TRUE, -1) living_target.visible_message( span_danger("[living_target] is [grazing ? "grazed" : "hit"] by \a [generic_name || src][organ_hit_text]!"), span_userdanger("You're [grazing ? "grazed" : "hit"] by \a [generic_name || src][organ_hit_text]!"), @@ -609,7 +608,7 @@ var/mob/target_mob = target if(faction_check(target_mob.faction, ignored_factions)) return FALSE - if(target.density || cross_failed) //This thing blocks projectiles, hit it regardless of layer/mob stuns/etc. + if((target.density && !target.IsObscured()) || cross_failed) //This thing blocks projectiles, hit it regardless of layer/mob stuns/etc. return TRUE if(!isliving(target)) if(isturf(target)) // non dense turfs diff --git a/code/modules/surgery/organs/internal/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm index 33e218ddcf6a..2296f773b946 100644 --- a/code/modules/surgery/organs/internal/tongue/_tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -570,3 +570,10 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) say_mod = "whistles" liked_foodtypes = VEGETABLES | FRUIT | GRAIN disliked_foodtypes = GORE | MEAT | DAIRY | SEAFOOD | BUGS + +/obj/item/organ/internal/tongue/floran + name = "floran tongue" + desc = "A plant-like organ used for speaking and eating." + say_mod = "whistles" + liked_foodtypes = GORE | MEAT | DAIRY | SEAFOOD | BUGS + disliked_foodtypes = VEGETABLES diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm index 9ef178f7d8af..de5ec1981334 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm @@ -34,7 +34,7 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/floran, BODY_ZONE_CHEST = /obj/item/bodypart/chest/floran, ) - mutanttongue = /obj/item/organ/internal/tongue/pod + mutanttongue = /obj/item/organ/internal/tongue/floran mutanteyes = /obj/item/organ/internal/eyes/floran mutantheart = /obj/item/organ/internal/heart/pod diff --git a/monkestation/code/modules/storytellers/gamemode_subsystem.dm b/monkestation/code/modules/storytellers/gamemode_subsystem.dm index 561149220487..3545e19aa0b1 100644 --- a/monkestation/code/modules/storytellers/gamemode_subsystem.dm +++ b/monkestation/code/modules/storytellers/gamemode_subsystem.dm @@ -9,6 +9,7 @@ SUBSYSTEM_DEF(gamemode) init_order = INIT_ORDER_GAMEMODE runlevels = RUNLEVEL_GAME flags = SS_BACKGROUND | SS_KEEP_TIMING + priority = 20 wait = 2 SECONDS /// List of our event tracks for fast access during for loops. From 96b5bbf5250680b68a1ae46a0b9f2be9a2b2149f Mon Sep 17 00:00:00 2001 From: ThePooba <81843097+ThePooba@users.noreply.github.com> Date: Thu, 19 Sep 2024 08:52:35 -0600 Subject: [PATCH 089/158] Update warden.dm Added sec time requirement to warden instead of 5 hours as crew --- code/modules/jobs/job_types/warden.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm index 13e2586d468d..6c7db7059193 100644 --- a/code/modules/jobs/job_types/warden.dm +++ b/code/modules/jobs/job_types/warden.dm @@ -10,9 +10,9 @@ spawn_positions = 1 supervisors = SUPERVISOR_HOS minimal_player_age = 7 - exp_requirements = 300 + exp_requirements = 600 //monkestation edit changed warden to require 10 hours as sec instead of 5 hours as crew exp_required_type = EXP_TYPE_CREW - exp_granted_type = EXP_TYPE_CREW + exp_required_type_department = EXP_TYPE_SECURITY config_tag = "WARDEN" outfit = /datum/outfit/job/warden From c206de11f4202021e18d67a38f7281c60077f917 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 19 Sep 2024 11:16:34 -0700 Subject: [PATCH 090/158] Update food_reagents.dm --- code/modules/reagents/chemistry/reagents/food_reagents.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index ccbdcae8400a..7f910fa837aa 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -328,7 +328,7 @@ if(prob(5)) M.emote("shiver") - M.adjust_bodytemperature(cooling * REM * seconds_per_tick, min_temp = CELCIUS_TO_KELVIN(36 CELCIUS)) + M.adjust_bodytemperature(cooling * REM * seconds_per_tick, min_temp = M.bodytemp_cold_damage_limit - 15 KELVIN) /datum/reagent/consumable/frostoil/expose_turf(turf/exposed_turf, reac_volume) . = ..() From 4ed82e65d00bebb3a8eef843f887b2dcf301a5cb Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 19 Sep 2024 21:58:39 -0700 Subject: [PATCH 091/158] fix --- .../code/modules/temperature_overhaul/temperature_proc.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/temperature_overhaul/temperature_proc.dm b/monkestation/code/modules/temperature_overhaul/temperature_proc.dm index 574604cb6247..fcf14ebea796 100644 --- a/monkestation/code/modules/temperature_overhaul/temperature_proc.dm +++ b/monkestation/code/modules/temperature_overhaul/temperature_proc.dm @@ -20,7 +20,7 @@ // There is an occasional bug where the temperature is miscalculated in areas with small amounts of gas. // This is necessary to ensure that does not affect this calculation. // Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K. - temperature = max(temperature, T0C) + temperature = max(temperature, TCMB) var/thermal_protection_flags = NONE for(var/obj/item/worn in get_equipped_items()) From a284420693ccce629ba6a06cd7177f900113cdef Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:39:03 -0700 Subject: [PATCH 092/158] basic changes --- code/__DEFINES/DNA.dm | 16 ---- code/__HELPERS/mobs.dm | 2 - .../bodypart_overlays/bodypart_overlay.dm | 4 + .../mutant_bodypart_overlay.dm | 39 +++++----- code/datums/dna.dm | 15 +--- code/datums/wounds/_wounds.dm | 13 +++- code/datums/wounds/bones.dm | 13 ---- code/datums/wounds/pierce.dm | 1 + code/datums/wounds/slash.dm | 2 +- code/game/objects/structures/mirror.dm | 6 +- code/modules/admin/create_mob.dm | 4 +- code/modules/client/preferences.dm | 3 +- .../modules/client/preferences/_preference.dm | 21 ++++- .../preferences/species_features/mutants.dm | 3 - code/modules/hydroponics/grown/replicapod.dm | 5 +- .../modules/mining/lavaland/megafauna_loot.dm | 3 +- .../mob/dead/new_player/sprite_accessories.dm | 16 +++- .../mob/living/carbon/human/_species.dm | 46 +++++------ code/modules/mob/living/carbon/human/dummy.dm | 6 +- .../carbon/human/species_types/jellypeople.dm | 12 +-- .../human/species_types/lizardpeople.dm | 8 +- .../chemistry/reagents/other_reagents.dm | 8 +- .../research/xenobiology/xenobiology.dm | 4 +- code/modules/surgery/bodyparts/_bodyparts.dm | 17 ++++- .../species_parts/ethereal_bodyparts.dm | 12 +++ .../species_parts/lizard_bodyparts.dm | 12 +++ .../bodyparts/species_parts/misc_bodyparts.dm | 76 +++++++++++++++++++ .../organs/stomach/stomach_ethereal.dm | 3 +- code/modules/tgui_input/color.dm | 4 + .../unit_tests/screenshot_humanoids.dm | 3 +- .../a_medical_day/internal_bleeding.dm | 2 + .../slasher/abilities/soul_steal.dm | 4 +- .../code/modules/blueshift/items/barber.dm | 7 -- .../modules/blueshift/wounds/muscle_wounds.dm | 11 --- .../species_features/secondary_mut_color.dm | 10 +-- .../preferences/species_features/simians.dm | 6 -- .../sprite_accessories/arachnid_appendages.dm | 3 +- .../sprite_accessories/arachnid_chelicerae.dm | 3 +- .../sprite_accessories/ethereal_horns.dm | 3 +- .../sprite_accessories/ethereal_tail.dm | 3 +- .../sprite_accessories/floran_leaves.dm | 4 +- .../sprite_accessories/goblin_accessories.dm | 3 +- .../sprite_accessories/ipc_antenna.dm | 3 +- .../sprite_accessories/ipc_chassis.dm | 3 +- .../sprite_accessories/multi_part.dm | 4 +- .../carbon/human/species_type/floran.dm | 3 + .../carbon/human/species_type/goblin.dm | 12 +++ .../carbon/human/species_type/simian.dm | 1 + .../smithing/oozelings/body/bodyparts.dm | 12 +++ .../modules/smithing/oozelings/body/organs.dm | 5 +- .../surgery/bodyparts/arachnid_bodyparts.dm | 12 +++ .../surgery/bodyparts/floran_bodyparts.dm | 12 +++ .../surgery/bodyparts/simian_bodyparts.dm | 16 +++- .../modules/the_bird_inside_of_me/plummage.dm | 4 +- .../modules/the_bird_inside_of_me/prefs.dm | 13 ++++ .../modules/the_bird_inside_of_me/species.dm | 1 + .../modules/the_bird_inside_of_me/tails.dm | 4 +- .../modules/the_bird_inside_of_me/wings.dm | 4 +- .../modules/the_fabled_dna_changes/dna.dm | 43 +++++++++++ .../_color_pallette.dm | 26 +++++++ .../generic_palette.dm | 23 ++++++ .../species_color_pallettes/ornithids.dm | 10 +++ tgstation.dme | 4 + .../tgui/interfaces/ColorPickerModal.tsx | 4 +- .../monkestation/ornithids.tsx | 9 +++ 65 files changed, 481 insertions(+), 183 deletions(-) create mode 100644 monkestation/code/modules/the_fabled_dna_changes/dna.dm create mode 100644 monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/_color_pallette.dm create mode 100644 monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/generic_palette.dm create mode 100644 monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/ornithids.dm diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 894288b712ed..f343ab8f7a6c 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -70,22 +70,6 @@ #define CLONER_FRESH_CLONE "fresh" #define CLONER_MATURE_CLONE "mature" - - -//species traits for mutantraces -/* -#define MUTCOLORS 1 -#define NOTRANSSTING 2 -#define NOZOMBIE 3 -#define NO_UNDERWEAR 4 -#define NO_DNA_COPY 5 -#define DRINKSBLOOD 6 -#define ANIME 7 -#define MUTCOLORS_SECONDARY 8 -#define SPECIES_FUR 9 -#define SKINTONES 10 -*/ - /// Use this if you want to change the race's color without the player being able to pick their own color. AKA special color shifting #define DYNCOLORS 7 #define AGENDER 8 diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 496989a41431..812c24f7fcc3 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -142,8 +142,6 @@ //For now we will always return none for tail_human and ears. | "For now" he says. return(list( - "mcolor" = "#[pick("7F","FF")][pick("7F","FF")][pick("7F","FF")]", - "mcolor_secondary" = "#[pick("7F","FF")][pick("7F","FF")][pick("7F","FF")]", "ethcolor" = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)], "tail_cat" = "None", "tail_lizard" = "Smooth", diff --git a/code/datums/bodypart_overlays/bodypart_overlay.dm b/code/datums/bodypart_overlays/bodypart_overlay.dm index 3173296a03e8..5e848ee54c21 100644 --- a/code/datums/bodypart_overlays/bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/bodypart_overlay.dm @@ -8,6 +8,10 @@ ///Key of the icon states of all the sprite_datums for easy caching var/cache_key = "" + ///our color palette + var/datum/color_palette/palette + ///our palette key + var/palette_key ///Wrapper for getting the proper image, colored and everything /datum/bodypart_overlay/proc/get_overlay(layer, obj/item/bodypart/limb) diff --git a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm index 0b52225359cb..737e66644d17 100644 --- a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm @@ -136,26 +136,25 @@ if(draw_color && !force) return FALSE - switch(color_source) - if(ORGAN_COLOR_OVERRIDE) - draw_color = override_color(ownerlimb.draw_color) - if(ORGAN_COLOR_INHERIT) - draw_color = ownerlimb.draw_color - if(ORGAN_COLOR_HAIR) - if(!ishuman(ownerlimb.owner)) - return - var/mob/living/carbon/human/human_owner = ownerlimb.owner - draw_color = human_owner.hair_color - if(ORGAN_COLOR_ANIME) - if(!ishuman(ownerlimb.owner)) - return - var/mob/living/carbon/human/human_owner = ownerlimb.owner - draw_color = human_owner.dna.features["animecolor"] - if(ORGAN_COLOR_MUTSECONDARY) - if(!ishuman(ownerlimb.owner)) - return - var/mob/living/carbon/human/human_owner = ownerlimb.owner - draw_color = human_owner.dna.features["mcolor_secondary"] + if(palette) + var/datum/color_palette/located = ownerlimb.owner.dna.color_palettes[palette] + draw_color = located.return_color(palette_key) + else + switch(color_source) + if(ORGAN_COLOR_OVERRIDE) + draw_color = override_color(ownerlimb.draw_color) + if(ORGAN_COLOR_INHERIT) + draw_color = ownerlimb.draw_color + if(ORGAN_COLOR_HAIR) + if(!ishuman(ownerlimb.owner)) + return + var/mob/living/carbon/human/human_owner = ownerlimb.owner + draw_color = human_owner.hair_color + if(ORGAN_COLOR_ANIME) + if(!ishuman(ownerlimb.owner)) + return + var/mob/living/carbon/human/human_owner = ownerlimb.owner + draw_color = human_owner.dna.features["animecolor"] return TRUE diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 111b07f5f966..9d2edf904b0d 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -20,7 +20,6 @@ GLOBAL_LIST_INIT(identity_block_lengths, list( * (commonly abbreviated with uf) and its blocks. Both ui and uf have a standard block length of 3 ASCII characters. */ GLOBAL_LIST_INIT(features_block_lengths, list( - "[DNA_MUTANT_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, "[DNA_ETHEREAL_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, )) @@ -111,6 +110,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) destination.dna.features = features.Copy() destination.dna.real_name = real_name destination.dna.temporary_mutations = temporary_mutations.Copy() + destination.dna.color_palettes = color_palettes.Copy() if(transfer_SE) destination.dna.mutation_index = mutation_index destination.dna.default_mutation_genes = default_mutation_genes @@ -125,6 +125,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) new_dna.unique_features = unique_features new_dna.human_blood_type = human_blood_type new_dna.features = features.Copy() + new_dna.color_palettes = color_palettes.Copy() //if the new DNA has a holder, transform them immediately, otherwise save it if(new_dna.holder) new_dna.holder.set_species(species.type, icon_update = 0) @@ -197,10 +198,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) . = "" var/list/L = new /list(DNA_FEATURE_BLOCKS) - if(features["mcolor"]) - L[DNA_MUTANT_COLOR_BLOCK] = sanitize_hexcolor(features["mcolor"], include_crunch = FALSE) - if(features["mcolor_secondary"]) - L[DNA_MUTANT_COLOR_SECONDARY] = sanitize_hexcolor(features["mcolor_secondary"], include_crunch = FALSE) if(features["ethcolor"]) L[DNA_ETHEREAL_COLOR_BLOCK] = sanitize_hexcolor(features["ethcolor"], include_crunch = FALSE) if(features["body_markings"]) @@ -341,10 +338,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) if(!ishuman(holder)) CRASH("Non-human mobs shouldn't have DNA") switch(blocknumber) - if(DNA_MUTANT_COLOR_BLOCK) - set_uni_feature_block(blocknumber, sanitize_hexcolor(features["mcolor"], include_crunch = FALSE)) - if(DNA_MUTANT_COLOR_SECONDARY) - set_uni_feature_block(blocknumber, sanitize_hexcolor(features["mcolor_secondary"], include_crunch = FALSE)) if(DNA_ETHEREAL_COLOR_BLOCK) set_uni_feature_block(blocknumber, sanitize_hexcolor(features["ethcolor"], include_crunch = FALSE)) if(DNA_LIZARD_MARKINGS_BLOCK) @@ -625,10 +618,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) else hairstyle = GLOB.hairstyles_list[deconstruct_block(get_uni_identity_block(structure, DNA_HAIRSTYLE_BLOCK), GLOB.hairstyles_list.len)] var/features = dna.unique_features - if(dna.features["mcolor"]) - dna.features["mcolor"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_MUTANT_COLOR_BLOCK)) - if(dna.features["mcolor_secondary"]) - dna.features["mcolor_secondary"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_MUTANT_COLOR_SECONDARY)) if(dna.features["ethcolor"]) dna.features["ethcolor"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_ETHEREAL_COLOR_BLOCK)) if(dna.features["body_markings"]) diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm index 4fbcee74e27d..53f50fddb0e4 100644 --- a/code/datums/wounds/_wounds.dm +++ b/code/datums/wounds/_wounds.dm @@ -116,6 +116,11 @@ /// The actionspeed modifier we will use in case we are on the arms and have a interaction penalty. Qdelled on destroy. var/datum/actionspeed_modifier/wound_interaction_inefficiency/actionspeed_mod + /// If we did the gel + surgical tape healing method for fractures, how many ticks does it take to heal by default + var/regen_ticks_needed + /// Our current counter for gel + surgical tape regeneration + var/regen_ticks_current + /datum/wound/New() . = ..() @@ -519,7 +524,13 @@ /// If var/processing is TRUE, this is run on each life tick /datum/wound/proc/handle_process(seconds_per_tick, times_fired) - return + SHOULD_CALL_PARENT(TRUE) + if(regen_ticks_current > regen_ticks_needed) + if(!victim || !limb) + qdel(src) + return + to_chat(victim, span_green("Your [limb.plaintext_zone] has recovered from its [undiagnosed_name || name]!")) + remove_wound() /// For use in do_after callback checks /datum/wound/proc/still_exists() diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index 5d9e5f4f3368..cc53993907c2 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -22,10 +22,6 @@ var/gelled /// Have we been taped? var/taped - /// If we did the gel + surgical tape healing method for fractures, how many ticks does it take to heal by default - var/regen_ticks_needed - /// Our current counter for gel + surgical tape regeneration - var/regen_ticks_current /// If we suffer severe head booboos, we can get brain traumas tied to them var/datum/brain_trauma/active_trauma /// What brain trauma group, if any, we can draw from for head wounds @@ -116,13 +112,6 @@ if(prob(33)) to_chat(victim, span_danger("You feel a sharp pain in your body as your bones are reforming!")) - if(regen_ticks_current > regen_ticks_needed) - if(!victim || !limb) - qdel(src) - return - to_chat(victim, span_green("Your [limb.plaintext_zone] has recovered from its [undiagnosed_name || name]!")) - remove_wound() - /// If we're a human who's punching something with a broken arm, we might hurt ourselves doing so /datum/wound/blunt/bone/proc/attack_with_hurt_hand(datum/source, atom/target, proximity) if(!proximity || severity <= WOUND_SEVERITY_MODERATE) @@ -643,8 +632,6 @@ Operate where possible. In the event of emergency, apply bone gel directly to injured limb. \ Creatures of pure bone don't seem to mind bone gel application nearly as much as fleshed individuals. \ Surgical tape will also be unnecessary.\n" - else - . += "[span_notice("Note: Bone regeneration in effect. Bone is [round(regen_ticks_current*100/regen_ticks_needed)]% regenerated.")]\n" if(limb.body_zone == BODY_ZONE_HEAD) . += "Cranial Trauma Detected: \ diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index 8de3685667d8..33b734a46e48 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -85,6 +85,7 @@ return BLOOD_FLOW_STEADY /datum/wound/pierce/bleed/handle_process(seconds_per_tick, times_fired) + . = ..() if (QDELETED(victim) || HAS_TRAIT(victim, TRAIT_STASIS)) return diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm index 5f39ab5164de..5c36bfdfcd37 100644 --- a/code/datums/wounds/slash.dm +++ b/code/datums/wounds/slash.dm @@ -135,7 +135,7 @@ return BLOOD_FLOW_INCREASING /datum/wound/slash/flesh/handle_process(seconds_per_tick, times_fired) - + . = ..() if (!victim || HAS_TRAIT(victim, TRAIT_STASIS)) return diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index dfba667ce4b8..2556f5397500 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -219,15 +219,15 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror, 28) amazed_human.dna.update_ui_block(DNA_SKIN_TONE_BLOCK) else if(HAS_TRAIT(amazed_human, TRAIT_MUTANT_COLORS) && !HAS_TRAIT(amazed_human, TRAIT_FIXED_MUTANT_COLORS)) - var/new_mutantcolor = tgui_color_picker(user, "Choose your skin color:", "Race change", amazed_human.dna.features["mcolor"]) + var/datum/color_palette/generic_colors/palette = amazed_human.dna.color_palettes[/datum/color_palette/generic_colors] + var/new_mutantcolor = tgui_color_picker(user, "Choose your skin color:", "Race change", palette.mutant_color) if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return TRUE if(new_mutantcolor) var/temp_hsv = RGBtoHSV(new_mutantcolor) if(ReadHSV(temp_hsv)[3] >= ReadHSV("#7F7F7F")[3]) // mutantcolors must be bright - amazed_human.dna.features["mcolor"] = sanitize_hexcolor(new_mutantcolor) - amazed_human.dna.update_uf_block(DNA_MUTANT_COLOR_BLOCK) + palette.mutant_color = sanitize_hexcolor(new_mutantcolor) else to_chat(amazed_human, span_notice("Invalid color. Your color is not bright enough.")) diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index 33d902e84b4e..8ca8d01352a9 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -27,7 +27,9 @@ human.eye_color_right = random_eye_color human.dna.human_blood_type = random_human_blood_type() - human.dna.features["mcolor"] = "#[random_color()]" + var/datum/color_palette/generic_colors/palette = human.dna.color_palettes[/datum/color_palette/generic_colors] + palette.mutant_color = "#[random_color()]" + palette.mutant_color_secondary = "#[random_color()]" human.dna.species.randomize_active_underwear_only(human) for(var/datum/species/species_path as anything in subtypesof(/datum/species)) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index bc57af9ec645..861c8bff8cff 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -301,7 +301,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) default_value || COLOR_WHITE, ) - if (!new_color) + if (!new_color && !requested_preference.allows_nulls) return FALSE if (!update_preference(requested_preference, new_color)) @@ -488,6 +488,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) /// Applies the given preferences to a human mob. /datum/preferences/proc/apply_prefs_to(mob/living/carbon/human/character, icon_updates = TRUE) character.dna.features = list() + character.dna.apply_color_palettes(src) var/species_type = read_preference(/datum/preference/choiced/species) var/datum/species/species = new species_type diff --git a/code/modules/client/preferences/_preference.dm b/code/modules/client/preferences/_preference.dm index 14daab33bc1b..c952c22f96ac 100644 --- a/code/modules/client/preferences/_preference.dm +++ b/code/modules/client/preferences/_preference.dm @@ -113,6 +113,11 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) /// will show the feature as selectable. --species nuking var/relevant_head_flag = null + ///do we allow null inputs + var/allows_nulls = FALSE + ///are we defaulted to null + var/default_null = FALSE + /// Called on the saved input when retrieving. /// Also called by the value sent from the user through UI. Do not trust it. /// Input is the value inside the savefile, output is to tell other code @@ -206,6 +211,8 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) /datum/preference/proc/apply_to_human(mob/living/carbon/human/target, value) SHOULD_NOT_SLEEP(TRUE) SHOULD_CALL_PARENT(FALSE) + if(istype(src, /datum/preference/color)) + return //colors are handled through a palette datum CRASH("`apply_to_human()` was not implemented for [type]!") /// Returns which savefile to use for a given savefile identifier @@ -439,16 +446,24 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) abstract_type = /datum/preference/color /datum/preference/color/deserialize(input, datum/preferences/preferences) - return sanitize_hexcolor(input) + if(!allows_nulls || input) + return sanitize_hexcolor(input) + return null /datum/preference/color/create_default_value() + if(default_null) + return null return random_color() /datum/preference/color/serialize(input) - return sanitize_hexcolor(input) + if(!allows_nulls || input) + return sanitize_hexcolor(input) + return null /datum/preference/color/is_valid(value) - return findtext(value, GLOB.is_color) + if(!allows_nulls || value) + return findtext(value, GLOB.is_color) + return TRUE /// Takes an assoc list of names to /datum/sprite_accessory and returns a value /// fit for `/datum/preference/init_possible_values()` diff --git a/code/modules/client/preferences/species_features/mutants.dm b/code/modules/client/preferences/species_features/mutants.dm index 7ecf25d9abce..eee8b54e6b61 100644 --- a/code/modules/client/preferences/species_features/mutants.dm +++ b/code/modules/client/preferences/species_features/mutants.dm @@ -15,9 +15,6 @@ /datum/preference/color/mutant_color/create_default_value() return sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]") -/datum/preference/color/mutant_color/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["mcolor"] = value - /datum/preference/color/mutant_color/is_valid(value) if (!..(value)) return FALSE diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index 788ce008c295..5a2c84b026af 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -191,8 +191,9 @@ podman.ckey = ckey_holder podman.gender = blood_gender podman.faction |= factions - if(!features["mcolor"]) - features["mcolor"] = "#59CE00" + var/datum/color_palette/generic_colors/palette = podman.dna.color_palettes[/datum/color_palette/generic_colors] + if(!palette.mutant_color) + palette.mutant_color = "#59CE00" if(!features["pod_hair"]) features["pod_hair"] = pick(GLOB.pod_hair_list) diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm index 5aa3d249b252..a6c30b990a8e 100644 --- a/code/modules/mining/lavaland/megafauna_loot.dm +++ b/code/modules/mining/lavaland/megafauna_loot.dm @@ -735,8 +735,9 @@ switch(random) if(1) to_chat(user, span_danger("Your appearance morphs to that of a very small humanoid ash dragon! You get to look like a freak without the cool abilities.")) + var/datum/color_palette/generic_colors/located = consumer.dna.color_palettes[/datum/color_palette/generic_colors] + located.mutant_color = "#A02720" consumer.dna.features = list( - "mcolor" = "#A02720", "tail_lizard" = "Dark Tiger", "tail_human" = "None", "snout" = "Sharp", diff --git a/code/modules/mob/dead/new_player/sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories.dm index 08608f33a042..c30a3b14f9c5 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories.dm @@ -81,6 +81,10 @@ /// Should this sprite block emissives? var/em_block = FALSE + var/datum/color_palette/palette + var/palette_key + var/fallback_key + /datum/sprite_accessory/blank name = "None" icon_state = "None" @@ -1780,7 +1784,8 @@ MONKESTATION EDIT name = "Cat" icon = 'icons/mob/species/human/cat_features.dmi' icon_state = "default" - color_src = HAIR_COLOR + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /datum/sprite_accessory/tails/monkey name = "Monkey" @@ -1891,15 +1896,17 @@ MONKESTATION EDIT name = "Cat" icon_state = "cat" hasinner = TRUE - color_src = HAIR_COLOR + palette = /datum/color_palette/generic_colors + palette_key = "hair_color" /datum/sprite_accessory/ears/fox icon = 'icons/mob/species/human/fox_features.dmi' name = "Fox" icon_state = "fox" hasinner = TRUE - color_src = HAIR_COLOR locked = TRUE + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /datum/sprite_accessory/wings/none name = "None" @@ -2092,8 +2099,9 @@ MONKESTATION EDIT /datum/sprite_accessory/caps icon = 'icons/mob/species/mush_cap.dmi' - color_src = HAIR_COLOR em_block = TRUE + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /datum/sprite_accessory/caps/round name = "Round" diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 574f1e6695ca..fec90fc2ebae 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -242,6 +242,8 @@ GLOBAL_LIST_EMPTY(features_by_species) var/list/custom_worn_icons = list() ///Override of the eyes icon file, used for Vox and maybe more in the future - The future is now, with Teshari using it too var/eyes_icon + ///our color palette + var/datum/color_palette/color_palette /////////// // PROCS // @@ -797,32 +799,26 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!(HAS_TRAIT(source, TRAIT_HUSK))) if(!forced_colour) - switch(accessory.color_src) - if(SKIN_COLOR) - accessory_overlay.color = skintone2hex(source.skin_tone) - if(MUTANT_COLOR) - if(fixed_mut_color) - accessory_overlay.color = fixed_mut_color - else - accessory_overlay.color = source.dna.features["mcolor"] - if(MUTANT_COLOR_SECONDARY) - if(fixed_mut_color) - accessory_overlay.color = fixed_mut_color - else - accessory_overlay.color = source.dna.features["mcolor_secondary"] - if(HAIR_COLOR) + if(accessory.palette) + var/key = accessory.palette_key + var/datum/color_palette/located = source.dna.color_palettes[accessory.palette] + if(accessory.palette_key == HAIR_COLOR) if(hair_color == "mutcolor") - accessory_overlay.color = source.dna.features["mcolor"] - else if(hair_color == "fixedmutcolor") - accessory_overlay.color = fixed_mut_color - else - accessory_overlay.color = source.hair_color - if(FACIAL_HAIR_COLOR) - accessory_overlay.color = source.facial_hair_color - if(EYE_COLOR) - accessory_overlay.color = source.eye_color_left - if(ANIME_COLOR) - accessory_overlay.color = source.dna.features["animecolor"] + key = MUTANT_COLOR + if(!located) + accessory_overlay.color = initial(accessory.palette.default_color) + else + accessory_overlay.color = located.return_color(key, accessory.fallback_key) + else + switch(accessory.color_src) + if(SKIN_COLOR) + accessory_overlay.color = skintone2hex(source.skin_tone) + if(FACIAL_HAIR_COLOR) + accessory_overlay.color = source.facial_hair_color + if(EYE_COLOR) + accessory_overlay.color = source.eye_color_left + if(ANIME_COLOR) + accessory_overlay.color = source.dna.features["animecolor"] else accessory_overlay.color = forced_colour standing += accessory_overlay diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index 3a5fd1e55c6f..caf1afacd9de 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -100,8 +100,6 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) target.dna.features["ethcolor"] = COLOR_WHITE target.dna.features["frills"] = "None" target.dna.features["horns"] = "None" - target.dna.features["mcolor"] = COLOR_VIBRANT_LIME - target.dna.features["mcolor_secondary"] = COLOR_VIBRANT_LIME target.dna.features["moth_antennae"] = "Plain" target.dna.features["moth_markings"] = "None" target.dna.features["moth_wings"] = "Plain" @@ -127,6 +125,10 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) target.dna.features["satyr_tail"] = "Short" //Monkestation Addition target.dna.features["satyr_horns"] = "Back" //Monkestation Addition + var/datum/color_palette/generic_colors/palette = target.dna.color_palettes[/datum/color_palette/generic_colors] + palette.mutant_color = COLOR_VIBRANT_LIME + palette.mutant_color_secondary = COLOR_VIBRANT_LIME + /// Provides a dummy that is consistently bald, white, naked, etc. /mob/living/carbon/human/dummy/consistent diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 2f0b6faaf09c..c59ca37b37e1 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -22,7 +22,7 @@ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT inherent_factions = list(FACTION_SLIME) species_language_holder = /datum/language_holder/jelly - hair_color = "mutcolor" + hair_color = "mutant_color" hair_alpha = 150 facial_hair_alpha = 150 @@ -181,8 +181,8 @@ spare.underwear = "Nude" H.dna.transfer_identity(spare, transfer_SE=1) - spare.dna.features["mcolor"] = "#[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]" - spare.dna.update_uf_block(DNA_MUTANT_COLOR_BLOCK) + var/datum/color_palette/generic_colors/palette = spare.dna.color_palettes[/datum/color_palette/generic_colors] + palette.mutant_color = "#[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]" spare.real_name = spare.dna.real_name spare.name = spare.dna.real_name spare.updateappearance(mutcolor_update=1) @@ -256,7 +256,8 @@ continue var/list/L = list() - L["htmlcolor"] = body.dna.features["mcolor"] + var/datum/color_palette/generic_colors/palette = body.dna.color_palettes[/datum/color_palette/generic_colors] + L["htmlcolor"] = palette?.mutant_color L["area"] = get_area_name(body, TRUE) var/stat = "error" switch(body.stat) @@ -425,7 +426,8 @@ /datum/species/jelly/luminescent/proc/update_glow(mob/living/carbon/human/glowie, intensity) if(intensity) glow_intensity = intensity - glow.set_light_range_power_color(glow_intensity, glow_intensity, glowie.dna.features["mcolor"]) + var/datum/color_palette/generic_colors/palette = glowie.dna.color_palettes[/datum/color_palette/generic_colors] + glow.set_light_range_power_color(glow_intensity, glow_intensity, palette.return_color(MUTANT_COLOR)) /datum/action/innate/integrate_extract name = "Integrate Extract" diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index ec1a9ef6aa3a..5fcaf6000f77 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -162,10 +162,11 @@ Lizard subspecies: SILVER SCALED /datum/species/lizard/silverscale/on_species_gain(mob/living/carbon/new_silverscale, datum/species/old_species, pref_load) var/mob/living/carbon/human/silverscale = new_silverscale - old_mutcolor = new_silverscale.dna.features["mcolor"] + var/datum/color_palette/generic_colors/palette = new_silverscale.dna.color_palettes[/datum/color_palette/generic_colors] + old_mutcolor = palette.return_color(MUTANT_COLOR) old_eye_color_left = silverscale.eye_color_left old_eye_color_right = silverscale.eye_color_right - new_silverscale.dna.features["mcolor"] = "#eeeeee" + palette.mutant_color = "#eeeeee" silverscale.eye_color_left = "#0000a0" silverscale.eye_color_right = "#0000a0" ..() @@ -173,7 +174,8 @@ Lizard subspecies: SILVER SCALED /datum/species/lizard/silverscale/on_species_loss(mob/living/carbon/old_silverscale, datum/species/new_species, pref_load) var/mob/living/carbon/human/was_silverscale = old_silverscale - was_silverscale.dna.features["mcolor"] = old_mutcolor + var/datum/color_palette/generic_colors/palette = was_silverscale.dna.color_palettes[/datum/color_palette/generic_colors] + palette.mutant_color = old_mutcolor was_silverscale.eye_color_left = old_eye_color_left was_silverscale.eye_color_right = old_eye_color_right diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index ee9f127c5de3..17ec5771f854 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -583,7 +583,8 @@ if(HAS_TRAIT(exposed_human, TRAIT_MUTANT_COLORS)) //take current alien color and darken it slightly var/newcolor = "" - var/string = exposed_human.dna.features["mcolor"] + var/datum/color_palette/generic_colors/located = exposed_human.dna.color_palettes[/datum/color_palette/generic_colors] + var/string = located.return_color(MUTANT_COLOR) var/len = length(string) var/char = "" var/ascii = 0 @@ -606,7 +607,7 @@ else break if(ReadHSV(newcolor)[3] >= ReadHSV("#7F7F7F")[3]) - exposed_human.dna.features["mcolor"] = newcolor + located.mutant_color = newcolor exposed_human.update_body(is_creating = TRUE) if((methods & INGEST) && show_message) @@ -629,7 +630,8 @@ if(HAS_TRAIT(affected_human, TRAIT_USES_SKINTONES)) affected_human.skin_tone = "orange" else if(HAS_TRAIT(affected_human, TRAIT_MUTANT_COLORS)) //Aliens with custom colors simply get turned orange - affected_human.dna.features["mcolor"] = "#ff8800" + var/datum/color_palette/generic_colors/located = affected_human.dna.color_palettes[/datum/color_palette/generic_colors] + located.mutant_color = "#ff8800" affected_human.update_body(is_creating = TRUE) if(SPT_PROB(3.5, seconds_per_tick)) if(affected_human.w_uniform) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 59842f960b5b..2e9610dba099 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -596,8 +596,8 @@ /obj/item/slime_extract/rainbow/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type) switch(activation_type) if(SLIME_ACTIVATE_MINOR) - user.dna.features["mcolor"] = "#[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]" - user.dna.update_uf_block(DNA_MUTANT_COLOR_BLOCK) + var/datum/color_palette/generic_colors/located = user.dna.color_palettes[/datum/color_palette/generic_colors] + located.mutant_color = "#[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]" user.updateappearance(mutcolor_update=1) species.update_glow(user) to_chat(user, span_notice("You feel different...")) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 08c05f8fc436..b59a030b5eb7 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -202,6 +202,9 @@ var/list/composition_effects ///a list of different limb_ids that we share composition with var/list/shared_composition + ///this is our color palette we pull colors from + var/datum/color_palette/palette + var/palette_key /obj/item/bodypart/apply_fantasy_bonuses(bonus) . = ..() @@ -916,11 +919,17 @@ skin_tone = human_owner.skin_tone else if(HAS_TRAIT(human_owner, TRAIT_MUTANT_COLORS)) skin_tone = "" - var/datum/species/owner_species = human_owner.dna.species - if(owner_species.fixed_mut_color) - species_color = owner_species.fixed_mut_color + if(palette) + var/datum/color_palette/located = human_owner.dna.color_palettes[palette] + if(!located) + species_color = initial(palette.default_color) + species_color = located.return_color(palette_key) else - species_color = human_owner.dna.features["mcolor"] + var/datum/species/owner_species = human_owner.dna.species + if(owner_species.fixed_mut_color) + species_color = owner_species.fixed_mut_color + else + CRASH("Forgot to move something to new color_palette system [src]") else skin_tone = "" species_color = "" diff --git a/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm index 06db450e5dd2..a5fcb4d18cfc 100644 --- a/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm @@ -6,6 +6,8 @@ attack_type = BURN // bish buzz unarmed_attack_sound = 'sound/weapons/etherealhit.ogg' unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/head/ethereal/update_limb(dropping_limb, is_creating) . = ..() @@ -20,6 +22,8 @@ limb_id = SPECIES_ETHEREAL is_dimorphic = FALSE dmg_overlay_type = null + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/chest/ethereal/update_limb(dropping_limb, is_creating) . = ..() @@ -36,6 +40,8 @@ unarmed_attack_verb = "burn" unarmed_attack_sound = 'sound/weapons/etherealhit.ogg' unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/ethereal/update_limb(dropping_limb, is_creating) . = ..() @@ -52,6 +58,8 @@ unarmed_attack_verb = "burn" unarmed_attack_sound = 'sound/weapons/etherealhit.ogg' unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/right/ethereal/update_limb(dropping_limb, is_creating) . = ..() @@ -68,6 +76,8 @@ attack_type = BURN // bish buzz unarmed_attack_sound = 'sound/weapons/etherealhit.ogg' unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/left/ethereal/update_limb(dropping_limb, is_creating) . = ..() @@ -83,6 +93,8 @@ attack_type = BURN // bish buzz unarmed_attack_sound = 'sound/weapons/etherealhit.ogg' unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/ethereal/update_limb(dropping_limb, is_creating) . = ..() diff --git a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm index a63870319f20..f54ba67b82fb 100644 --- a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm @@ -4,6 +4,8 @@ is_dimorphic = FALSE head_flags = HEAD_HAIR| HEAD_EYESPRITES | HEAD_EYEHOLES | HEAD_DEBRAIN | HEAD_EYECOLOR composition_effects = list(TRAIT_COLD_BLOODED = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/chest/lizard icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' @@ -12,6 +14,8 @@ ass_image = 'icons/ass/asslizard.png' composition_effects = list(TRAIT_COLD_BLOODED = 0.5) wing_types = list(/obj/item/organ/external/wings/functional/dragon) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/lizard icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' @@ -21,6 +25,8 @@ unarmed_attack_sound = 'sound/weapons/slash.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' composition_effects = list(TRAIT_COLD_BLOODED = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/right/lizard icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' @@ -30,6 +36,8 @@ unarmed_attack_sound = 'sound/weapons/slash.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' composition_effects = list(TRAIT_COLD_BLOODED = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/lizard/ashwalker bodypart_traits = list(TRAIT_CHUNKYFINGERS) @@ -44,6 +52,8 @@ digitigrade_id = "digitigrade" footprint_sprite = FOOTPRINT_SPRITE_CLAWS composition_effects = list(TRAIT_COLD_BLOODED = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/lizard icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' @@ -52,6 +62,8 @@ digitigrade_id = "digitigrade" footprint_sprite = FOOTPRINT_SPRITE_CLAWS composition_effects = list(TRAIT_COLD_BLOODED = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/lizard/ashwalker bodypart_traits = list(TRAIT_HARD_SOLES) diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index 493bd808f2da..3a4342cfd3c7 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -3,42 +3,58 @@ limb_id = SPECIES_SNAIL is_dimorphic = FALSE head_flags = HEAD_EYESPRITES|HEAD_DEBRAIN + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/chest/snail limb_id = SPECIES_SNAIL is_dimorphic = FALSE + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/snail limb_id = SPECIES_SNAIL unarmed_attack_verb = "slap" unarmed_attack_effect = ATTACK_EFFECT_DISARM unarmed_damage_high = 0.5 //snails are soft and squishy + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/right/snail limb_id = SPECIES_SNAIL unarmed_attack_verb = "slap" unarmed_attack_effect = ATTACK_EFFECT_DISARM unarmed_damage_high = 0.5 + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/left/snail limb_id = SPECIES_SNAIL unarmed_damage_high = 0.5 speed_modifier = 3 //disgustingly slow + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/snail limb_id = SPECIES_SNAIL unarmed_damage_high = 0.5 speed_modifier = 3 //disgustingly slow + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/left/zombie/infectious limb_id = SPECIES_ZOMBIE should_draw_greyscale = FALSE speed_modifier = 0.8 //braaaaains + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/zombie/infectious limb_id = SPECIES_ZOMBIE should_draw_greyscale = FALSE speed_modifier = 0.8 //braaaaains + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR ///ABDUCTOR /obj/item/bodypart/head/abductor @@ -79,6 +95,8 @@ dmg_overlay_type = null head_flags = HEAD_ALL_FEATURES composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/chest/jelly biological_state = (BIO_FLESH|BIO_BLOODED) @@ -88,30 +106,40 @@ composition_effects = list(/datum/element/soft_landing = 0.5) ass_image = 'icons/ass/assslime.png' wing_types = list(/obj/item/organ/external/wings/functional/slime) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/jelly biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/right/jelly biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/left/jelly biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/jelly biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR ///SLIME /obj/item/bodypart/head/slime @@ -120,59 +148,83 @@ is_dimorphic = FALSE head_flags = HEAD_ALL_FEATURES composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/chest/slime biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_SLIMEPERSON is_dimorphic = TRUE composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/slime biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_SLIMEPERSON composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/right/slime biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_SLIMEPERSON composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/left/slime biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_SLIMEPERSON composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/slime biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_SLIMEPERSON composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR ///LUMINESCENT /obj/item/bodypart/head/luminescent biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_LUMINESCENT is_dimorphic = TRUE + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/chest/luminescent biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_LUMINESCENT is_dimorphic = TRUE + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/luminescent biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_LUMINESCENT + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/right/luminescent biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_LUMINESCENT + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/left/luminescent biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_LUMINESCENT + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/luminescent biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_LUMINESCENT + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR ///ZOMBIE /obj/item/bodypart/head/zombie @@ -212,11 +264,15 @@ /obj/item/bodypart/head/pod limb_id = SPECIES_PODPERSON is_dimorphic = TRUE + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/chest/pod limb_id = SPECIES_PODPERSON is_dimorphic = TRUE ass_image = 'icons/ass/asspodperson.png' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/pod limb_id = SPECIES_PODPERSON @@ -224,6 +280,8 @@ unarmed_attack_effect = ATTACK_EFFECT_CLAW unarmed_attack_sound = 'sound/weapons/slice.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/right/pod limb_id = SPECIES_PODPERSON @@ -231,12 +289,18 @@ unarmed_attack_effect = ATTACK_EFFECT_CLAW unarmed_attack_sound = 'sound/weapons/slice.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/left/pod limb_id = SPECIES_PODPERSON + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/pod limb_id = SPECIES_PODPERSON + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR ///FLY /obj/item/bodypart/head/fly @@ -347,23 +411,31 @@ limb_id = SPECIES_MUSHROOM is_dimorphic = TRUE head_flags = NONE + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/chest/mushroom limb_id = SPECIES_MUSHROOM is_dimorphic = TRUE bodypart_traits = list(TRAIT_NO_JUMPSUIT) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/mushroom limb_id = SPECIES_MUSHROOM unarmed_damage_low = 8 unarmed_damage_high = 8 unarmed_stun_threshold = 14 + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/right/mushroom limb_id = SPECIES_MUSHROOM unarmed_damage_low = 8 unarmed_damage_high = 8 unarmed_stun_threshold = 14 + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/left/mushroom limb_id = SPECIES_MUSHROOM @@ -371,6 +443,8 @@ unarmed_damage_high = 15 unarmed_stun_threshold = 14 speed_modifier = 0.75 //big fungus big fungus + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/mushroom limb_id = SPECIES_MUSHROOM @@ -378,6 +452,8 @@ unarmed_damage_high = 15 unarmed_stun_threshold = 14 speed_modifier = 0.75 //big fungus big fungus + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR ///GOLEMS (i hate xenobio SO FUCKING MUCH) (from 2022: Yeah I fucking feel your pain brother) (2024: yeah this is shit) /obj/item/bodypart/head/golem diff --git a/code/modules/surgery/organs/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/stomach/stomach_ethereal.dm index 50592dc64840..b70d476949fa 100644 --- a/code/modules/surgery/organs/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/stomach/stomach_ethereal.dm @@ -151,7 +151,8 @@ ethereal.add_overlay(overcharge) if(do_after(ethereal, 5 SECONDS, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_HELD_ITEM|IGNORE_INCAPACITATED))) - ethereal.flash_lighting_fx(5, 7, ethereal.dna.species.fixed_mut_color ? ethereal.dna.species.fixed_mut_color : ethereal.dna.features["mcolor"]) + var/datum/color_palette/generic_colors/located = ethereal.dna.color_palettes[/datum/color_palette/generic_colors] + ethereal.flash_lighting_fx(5, 7, ethereal.dna.species.fixed_mut_color ? ethereal.dna.species.fixed_mut_color : located.return_color(MUTANT_COLOR)) playsound(ethereal, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) ethereal.cut_overlay(overcharge) diff --git a/code/modules/tgui_input/color.dm b/code/modules/tgui_input/color.dm index fe161b2e6a92..fcc3f80d9c99 100644 --- a/code/modules/tgui_input/color.dm +++ b/code/modules/tgui_input/color.dm @@ -118,6 +118,10 @@ closed = TRUE SStgui.close_uis(src) return TRUE + if("null") + set_choice(null) + SStgui.close_uis(src) + return TRUE /datum/tgui_color_picker/proc/set_choice(choice) src.choice = choice diff --git a/code/modules/unit_tests/screenshot_humanoids.dm b/code/modules/unit_tests/screenshot_humanoids.dm index a0e7abc1633e..cab447f9ea3f 100644 --- a/code/modules/unit_tests/screenshot_humanoids.dm +++ b/code/modules/unit_tests/screenshot_humanoids.dm @@ -4,7 +4,8 @@ /datum/unit_test/screenshot_humanoids/Run() // Test lizards as their own thing so we can get more coverage on their features var/mob/living/carbon/human/lizard = allocate(/mob/living/carbon/human/dummy/consistent) - lizard.dna.features["mcolor"] = "#099" + var/datum/color_palette/generic_colors/located = lizard.dna.color_palettes[/datum/color_palette/generic_colors] + located.mutant_color = "#099" lizard.dna.features["tail_lizard"] = "Light Tiger" lizard.dna.features["snout"] = "Sharp + Light" lizard.dna.features["horns"] = "Simple" diff --git a/monkestation/code/modules/a_medical_day/internal_bleeding.dm b/monkestation/code/modules/a_medical_day/internal_bleeding.dm index b03a7d452a88..ea622ccaf5a2 100644 --- a/monkestation/code/modules/a_medical_day/internal_bleeding.dm +++ b/monkestation/code/modules/a_medical_day/internal_bleeding.dm @@ -19,6 +19,7 @@ or an iron supplement to help your body recover." processes = TRUE wound_flags = NONE + regen_ticks_needed = 120 //around 4 minutes /// How much blood lost per life tick, gets modified by severity. var/bleed_amount = 0.25 /// Cooldown between when the wound can be allowed to worsen @@ -28,6 +29,7 @@ return span_warning("You can see dark bruising.") // same as rib fracture! /datum/wound/bleed_internal/handle_process(seconds_per_tick, times_fired) + . = ..() if(!victim || victim.stat == DEAD || HAS_TRAIT(victim, TRAIT_STASIS) || !victim.needs_heart()) return victim.bleed(min(bleed_amount * severity * seconds_per_tick, 3)) diff --git a/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/soul_steal.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/soul_steal.dm index b9e93cdfe460..95af858a2fa4 100644 --- a/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/soul_steal.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/soul_steal.dm @@ -82,8 +82,8 @@ human_target.skin_tone = "albino" human_target.dna.update_ui_block(DNA_SKIN_TONE_BLOCK) else // we dont discriminate, even skeletons can be white... (arent they already white?) - human_target.dna.features["mcolor"] = "#FFFFFF" - human_target.dna.update_uf_block(DNA_MUTANT_COLOR_BLOCK) + var/datum/color_palette/generic_colors/located = human_target.dna.color_palettes[/datum/color_palette/generic_colors] + located.mutant_color = "#FFFFFF" human_target.update_body(is_creating = TRUE) diff --git a/monkestation/code/modules/blueshift/items/barber.dm b/monkestation/code/modules/blueshift/items/barber.dm index 3448f9bd87a9..293f0dd70a58 100644 --- a/monkestation/code/modules/blueshift/items/barber.dm +++ b/monkestation/code/modules/blueshift/items/barber.dm @@ -407,13 +407,6 @@ visible_message(span_notice("[user] starts to masterfully paint [target_human]!")) if(do_after(user, 20 SECONDS, target_human)) - switch(selected_mutant_color) - if("One") - target_human.dna.features["mcolor"] = selected_color - if("Two") - target_human.dna.features["mcolor1"] = selected_color - if("Three") - target_human.dna.features["mcolor2"] = selected_color target_human.regenerate_icons() item_use_power(power_use_amount, user) diff --git a/monkestation/code/modules/blueshift/wounds/muscle_wounds.dm b/monkestation/code/modules/blueshift/wounds/muscle_wounds.dm index 70df1ab6b097..fbb8da9e9982 100644 --- a/monkestation/code/modules/blueshift/wounds/muscle_wounds.dm +++ b/monkestation/code/modules/blueshift/wounds/muscle_wounds.dm @@ -9,10 +9,6 @@ wound_flags = (ACCEPTS_GAUZE) processes = TRUE - /// How much do we need to regen. Will regen faster if we're splinted and or laying down - var/regen_ticks_needed - /// Our current counter for healing - var/regen_ticks_current = 0 can_scar = FALSE @@ -70,13 +66,6 @@ if(limb.current_gauze) regen_ticks_current += (1-limb.current_gauze.splint_factor) - if(regen_ticks_current > regen_ticks_needed) - if(!victim || !limb) - qdel(src) - return - to_chat(victim, span_green("Your [parse_zone(limb.body_zone)] has regenerated its muscle!")) - remove_wound() - /// If we're a human who's punching something with a broken arm, we might hurt ourselves doing so /datum/wound/muscle/proc/attack_with_hurt_hand(mob/M, atom/target, proximity) SIGNAL_HANDLER diff --git a/monkestation/code/modules/client/preferences/species_features/secondary_mut_color.dm b/monkestation/code/modules/client/preferences/species_features/secondary_mut_color.dm index 5dfb2a59e9eb..f9303e14049b 100644 --- a/monkestation/code/modules/client/preferences/species_features/secondary_mut_color.dm +++ b/monkestation/code/modules/client/preferences/species_features/secondary_mut_color.dm @@ -3,6 +3,8 @@ savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SECONDARY_FEATURES relevant_inherent_trait = TRAIT_MUTANT_COLORS_SECONDARY + default_null = TRUE + allows_nulls = TRUE /datum/preference/color/mutant_color_secondary/is_accessible(datum/preferences/preferences) if (!..(preferences)) @@ -10,13 +12,7 @@ var/species_type = preferences.read_preference(/datum/preference/choiced/species) var/datum/species/species = new species_type - return !(TRAIT_MUTANT_COLORS_SECONDARY in species.inherent_traits) - -/datum/preference/color/mutant_color_secondary/create_default_value() - return sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]") - -/datum/preference/color/mutant_color_secondary/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["mcolor_secondary"] = value + return (TRAIT_MUTANT_COLORS_SECONDARY in species.inherent_traits) /datum/preference/color/mutant_color_secondary/is_valid(value) if (!..(value)) diff --git a/monkestation/code/modules/client/preferences/species_features/simians.dm b/monkestation/code/modules/client/preferences/species_features/simians.dm index 0f85e08f6d56..39f63cf97aec 100644 --- a/monkestation/code/modules/client/preferences/species_features/simians.dm +++ b/monkestation/code/modules/client/preferences/species_features/simians.dm @@ -4,12 +4,6 @@ savefile_key = "fur" relevant_inherent_trait = TRAIT_FUR_COLORS -/datum/preference/color/fur_color/apply_to_human(mob/living/carbon/human/target, value) - var/mob/user = usr - var/datum/species/species_type = user?.client.prefs.read_preference(/datum/preference/choiced/species) - if(TRAIT_FUR_COLORS in initial(species_type.inherent_traits)) - target.dna.features["mcolor"] = value - /datum/preference/choiced/simian_tail savefile_key = "feature_tail_monkey" savefile_identifier = PREFERENCE_CHARACTER diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_appendages.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_appendages.dm index b8b1ce15d9c0..ce030464fdc0 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_appendages.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_appendages.dm @@ -1,6 +1,7 @@ /datum/sprite_accessory/arachnid_appendages icon = 'monkestation/icons/mob/species/arachnid/arachnid_appendages.dmi' - color_src = MUTANT_COLOR + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /datum/sprite_accessory/arachnid_appendages/long name = "Long" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_chelicerae.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_chelicerae.dm index 91aff39dd5d4..a2b375b81124 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_chelicerae.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/arachnid_chelicerae.dm @@ -1,6 +1,7 @@ /datum/sprite_accessory/arachnid_chelicerae icon = 'monkestation/icons/mob/species/arachnid/arachnid_chelicerae.dmi' - color_src = MUTANT_COLOR + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /datum/sprite_accessory/arachnid_chelicerae/basic name = "Basic" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_horns.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_horns.dm index 7c8bea62a121..a1a1a95bcedb 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_horns.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_horns.dm @@ -1,6 +1,7 @@ /datum/sprite_accessory/ethereal_horns icon = 'monkestation/icons/mob/species/ethereal/ethereal_horns.dmi' - color_src = MUTANT_COLOR + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /datum/sprite_accessory/ethereal_horns/none name = "None" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_tail.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_tail.dm index 467629e94648..846f89cb8491 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_tail.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ethereal_tail.dm @@ -1,6 +1,7 @@ /datum/sprite_accessory/tails/ethereal icon = 'monkestation/icons/mob/species/ethereal/ethereal_tail.dmi' - color_src = MUTANT_COLOR + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /datum/sprite_accessory/tails/ethereal/none name = "None" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/floran_leaves.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/floran_leaves.dm index b1a7daa17895..efad9524773c 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/floran_leaves.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/floran_leaves.dm @@ -1,6 +1,8 @@ /datum/sprite_accessory/floran_leaves icon = 'monkestation/icons/mob/species/floran/floran_leaves.dmi' - color_src = MUTANT_COLOR_SECONDARY + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR_SECONDARY + fallback_key = MUTANT_COLOR //Should be MUTCOLORS_SECONDARY, but while its not working it will be the inverse of MUTCOLORS /datum/sprite_accessory/floran_leaves/furnivour diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/goblin_accessories.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/goblin_accessories.dm index abdcc93d8bb1..1019ce177f89 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/goblin_accessories.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/goblin_accessories.dm @@ -1,6 +1,7 @@ /datum/sprite_accessory/goblin_ears icon = 'monkestation/icons/mob/species/goblin/goblin_ears.dmi' - color_src = MUTANT_COLOR + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /datum/sprite_accessory/goblin_ears/normal name = "Normal" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_antenna.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_antenna.dm index 48e9f6b08042..0c80627538d1 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_antenna.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_antenna.dm @@ -1,6 +1,7 @@ /datum/sprite_accessory/ipc_antennas icon = 'monkestation/icons/mob/species/ipc/ipc_antennas.dmi' - color_src = MUTANT_COLOR + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /datum/sprite_accessory/ipc_antennas/none name = "None" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_chassis.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_chassis.dm index a393b010cf57..ebf898886a06 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_chassis.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/ipc_chassis.dm @@ -5,8 +5,9 @@ /datum/sprite_accessory/ipc_chassis/mcgreyscale name = "Morpheus Cyberkinetics (Custom)" - color_src = MUTANT_COLOR icon_state = "mcgipc" + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /datum/sprite_accessory/ipc_chassis/bishop_cyberkinetics name = "Bishop Cyberkinetics" diff --git a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/multi_part.dm b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/multi_part.dm index ee937f1f8373..698d2068cafa 100644 --- a/monkestation/code/modules/mob/dead/new_player/sprite_accessories/multi_part.dm +++ b/monkestation/code/modules/mob/dead/new_player/sprite_accessories/multi_part.dm @@ -5,7 +5,9 @@ var/list/external_slots = list() /datum/sprite_accessory/body_markings - color_src = MUTANT_COLOR_SECONDARY + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR_SECONDARY + fallback_key = MUTANT_COLOR /datum/sprite_accessory/body_markings/light_belly name = "Light Belly" diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm index de5ec1981334..112bd5faf94b 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm @@ -143,3 +143,6 @@ /datum/bodypart_overlay/mutant/floran_leaves layers = EXTERNAL_ADJACENT feature_key = "floran_leaves" + + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR_SECONDARY diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm index 17df0e9a18ca..5734136255b8 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm @@ -136,29 +136,41 @@ icon_greyscale = 'monkestation/icons/mob/species/goblin/bodyparts.dmi' limb_id = SPECIES_GOBLIN is_dimorphic = FALSE + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/chest/goblin icon_greyscale = 'monkestation/icons/mob/species/goblin/bodyparts.dmi' limb_id = SPECIES_GOBLIN is_dimorphic = TRUE + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/goblin icon_greyscale = 'monkestation/icons/mob/species/goblin/bodyparts.dmi' limb_id = SPECIES_GOBLIN + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/right/goblin icon_greyscale = 'monkestation/icons/mob/species/goblin/bodyparts.dmi' limb_id = SPECIES_GOBLIN + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/left/goblin icon_greyscale = 'monkestation/icons/mob/species/goblin/bodyparts.dmi' limb_id = SPECIES_GOBLIN speed_modifier = -0.125 + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/goblin icon_greyscale = 'monkestation/icons/mob/species/goblin/bodyparts.dmi' limb_id = SPECIES_GOBLIN speed_modifier = -0.125 + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/organ/internal/tongue/goblin name = "goblin tongue" diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm index e994aef71159..83ce4cc210ee 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm @@ -7,6 +7,7 @@ inherent_traits = list( TRAIT_FUR_COLORS, + TRAIT_MUTANT_COLORS, TRAIT_NO_UNDERWEAR, TRAIT_VAULTING, TRAIT_KLEPTOMANIAC, diff --git a/monkestation/code/modules/smithing/oozelings/body/bodyparts.dm b/monkestation/code/modules/smithing/oozelings/body/bodyparts.dm index 605c58fad0e6..914ea7107d00 100644 --- a/monkestation/code/modules/smithing/oozelings/body/bodyparts.dm +++ b/monkestation/code/modules/smithing/oozelings/body/bodyparts.dm @@ -6,6 +6,8 @@ dmg_overlay_type = null composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/chest/oozeling icon_greyscale = 'monkestation/icons/mob/species/oozeling/bodyparts.dmi' @@ -17,6 +19,8 @@ composition_effects = list(/datum/element/soft_landing = 0.5) ass_image = 'icons/ass/assslime.png' wing_types = list(/obj/item/organ/external/wings/functional/slime) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/oozeling icon_greyscale = 'monkestation/icons/mob/species/oozeling/bodyparts.dmi' @@ -25,12 +29,16 @@ dmg_overlay_type = null composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/right/oozeling icon_greyscale = 'monkestation/icons/mob/species/oozeling/bodyparts.dmi' limb_id = SPECIES_OOZELING biological_state = BIO_INORGANIC composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/left/oozeling icon_greyscale = 'monkestation/icons/mob/species/oozeling/bodyparts.dmi' @@ -39,6 +47,8 @@ dmg_overlay_type = null composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/oozeling icon_greyscale = 'monkestation/icons/mob/species/oozeling/bodyparts.dmi' @@ -47,3 +57,5 @@ dmg_overlay_type = null composition_effects = list(/datum/element/soft_landing = 0.5) + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR diff --git a/monkestation/code/modules/smithing/oozelings/body/organs.dm b/monkestation/code/modules/smithing/oozelings/body/organs.dm index f3bf7094a344..39af37a185a4 100644 --- a/monkestation/code/modules/smithing/oozelings/body/organs.dm +++ b/monkestation/code/modules/smithing/oozelings/body/organs.dm @@ -114,7 +114,8 @@ /obj/item/organ/internal/brain/slime/proc/colorize() if(isoozeling(owner)) - core_color = owner.dna.features["mcolor"] + var/datum/color_palette/generic_colors/located = owner.dna.color_palettes[/datum/color_palette/generic_colors] + core_color = located.return_color(MUTANT_COLOR) add_atom_colour(core_color, FIXED_COLOUR_PRIORITY) /obj/item/organ/internal/brain/slime/proc/on_stat_change(mob/living/victim, new_stat, turf/loc_override) @@ -256,8 +257,6 @@ new_body.undershirt = "Nude" new_body.socks = "Nude" stored_dna.transfer_identity(new_body, transfer_SE = TRUE) - new_body.dna.features["mcolor"] = new_body.dna.features["mcolor"] - new_body.dna.update_uf_block(DNA_MUTANT_COLOR_BLOCK) new_body.real_name = new_body.dna.real_name new_body.name = new_body.dna.real_name new_body.updateappearance(mutcolor_update = TRUE) diff --git a/monkestation/code/modules/surgery/bodyparts/arachnid_bodyparts.dm b/monkestation/code/modules/surgery/bodyparts/arachnid_bodyparts.dm index d99fa22f0b83..39de5000e5dd 100644 --- a/monkestation/code/modules/surgery/bodyparts/arachnid_bodyparts.dm +++ b/monkestation/code/modules/surgery/bodyparts/arachnid_bodyparts.dm @@ -3,11 +3,15 @@ limb_id = SPECIES_ARACHNIDS is_dimorphic = FALSE head_flags = HEAD_EYESPRITES | HEAD_EYEHOLES | HEAD_DEBRAIN | HEAD_EYECOLOR + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/chest/arachnid icon_greyscale = 'monkestation/icons/mob/species/arachnid/bodyparts.dmi' limb_id = SPECIES_ARACHNIDS is_dimorphic = FALSE + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/arachnid icon_greyscale = 'monkestation/icons/mob/species/arachnid/bodyparts.dmi' @@ -16,6 +20,8 @@ unarmed_attack_effect = ATTACK_EFFECT_CLAW unarmed_attack_sound = 'sound/weapons/slash.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/right/arachnid icon_greyscale = 'monkestation/icons/mob/species/arachnid/bodyparts.dmi' @@ -24,13 +30,19 @@ unarmed_attack_effect = ATTACK_EFFECT_CLAW unarmed_attack_sound = 'sound/weapons/slash.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/left/arachnid icon_greyscale = 'monkestation/icons/mob/species/arachnid/bodyparts.dmi' limb_id = SPECIES_ARACHNIDS speed_modifier = -0.05 + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/arachnid icon_greyscale = 'monkestation/icons/mob/species/arachnid/bodyparts.dmi' limb_id = SPECIES_ARACHNIDS speed_modifier = -0.05 + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR diff --git a/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm b/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm index a878fb01d8cc..e76f64d6dc5d 100644 --- a/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm +++ b/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm @@ -3,12 +3,16 @@ limb_id = SPECIES_FLORAN is_dimorphic = FALSE head_flags = HEAD_EYESPRITES | HEAD_EYEHOLES | HEAD_DEBRAIN + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/chest/floran icon_greyscale = 'monkestation/icons/mob/species/floran/bodyparts.dmi' limb_id = SPECIES_FLORAN is_dimorphic = TRUE ass_image = 'icons/ass/asspodperson.png' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/floran icon_greyscale = 'monkestation/icons/mob/species/floran/bodyparts.dmi' @@ -19,6 +23,8 @@ unarmed_attack_effect = ATTACK_EFFECT_CLAW unarmed_attack_sound = 'sound/weapons/slice.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/arm/right/floran icon_greyscale = 'monkestation/icons/mob/species/floran/bodyparts.dmi' @@ -29,13 +35,19 @@ unarmed_attack_effect = ATTACK_EFFECT_CLAW unarmed_attack_sound = 'sound/weapons/slice.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/left/floran icon_greyscale = 'monkestation/icons/mob/species/floran/bodyparts.dmi' limb_id = SPECIES_FLORAN speed_modifier = -0.05 + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR /obj/item/bodypart/leg/right/floran icon_greyscale = 'monkestation/icons/mob/species/floran/bodyparts.dmi' limb_id = SPECIES_FLORAN speed_modifier = -0.05 + palette = /datum/color_palette/generic_colors + palette_key = MUTANT_COLOR diff --git a/monkestation/code/modules/surgery/bodyparts/simian_bodyparts.dm b/monkestation/code/modules/surgery/bodyparts/simian_bodyparts.dm index 2d916935fb5c..23da5d9671bb 100644 --- a/monkestation/code/modules/surgery/bodyparts/simian_bodyparts.dm +++ b/monkestation/code/modules/surgery/bodyparts/simian_bodyparts.dm @@ -7,6 +7,8 @@ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM head_flags = HEAD_EYESPRITES | HEAD_EYEHOLES | HEAD_DEBRAIN | HEAD_EYECOLOR dmg_overlay_type = "monkey" + palette = /datum/color_palette/generic_colors + palette_key = "fur_color" /obj/item/bodypart/chest/simian icon_greyscale = 'monkestation/icons/mob/species/simian/bodyparts.dmi' @@ -15,8 +17,9 @@ limb_id = SPECIES_SIMIAN is_dimorphic = FALSE bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM - dmg_overlay_type = "monkey" + palette = /datum/color_palette/generic_colors + palette_key = "fur_color" /obj/item/bodypart/arm/left/simian icon_greyscale = 'monkestation/icons/mob/species/simian/bodyparts.dmi' @@ -24,8 +27,9 @@ husk_type = "simian" limb_id = SPECIES_SIMIAN bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM - dmg_overlay_type = "monkey" + palette = /datum/color_palette/generic_colors + palette_key = "fur_color" /obj/item/bodypart/arm/right/simian icon_greyscale = 'monkestation/icons/mob/species/simian/bodyparts.dmi' @@ -33,8 +37,9 @@ husk_type = "simian" limb_id = SPECIES_SIMIAN bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM - dmg_overlay_type = "monkey" + palette = /datum/color_palette/generic_colors + palette_key = "fur_color" /obj/item/bodypart/leg/left/simian icon_greyscale = 'monkestation/icons/mob/species/simian/bodyparts.dmi' @@ -44,6 +49,8 @@ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM footprint_sprite = FOOTPRINT_SPRITE_PAWS speed_modifier = -0.05 + palette = /datum/color_palette/generic_colors + palette_key = "fur_color" /obj/item/bodypart/leg/right/simian icon_greyscale = 'monkestation/icons/mob/species/simian/bodyparts.dmi' @@ -52,6 +59,7 @@ limb_id = SPECIES_SIMIAN bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM footprint_sprite = FOOTPRINT_SPRITE_PAWS - dmg_overlay_type = "monkey" speed_modifier = -0.05 + palette = /datum/color_palette/generic_colors + palette_key = "fur_color" diff --git a/monkestation/code/modules/the_bird_inside_of_me/plummage.dm b/monkestation/code/modules/the_bird_inside_of_me/plummage.dm index 4a15e25e608a..5dbbb71c18b2 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/plummage.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/plummage.dm @@ -23,9 +23,11 @@ feature_key = "ears_avian" layers = EXTERNAL_FRONT color_source = ORGAN_COLOR_OVERRIDE + palette = /datum/color_palette/ornithids /datum/bodypart_overlay/mutant/plumage/inherit_color(obj/item/bodypart/ownerlimb, force) - draw_color = ownerlimb?.owner?.dna?.features["feathers"] || "#FFFFFF" + var/datum/color_palette/located = ownerlimb?.owner?.dna?.color_palettes[palette] + draw_color = located?.return_color("feather_main") || "#FFFFFF" return TRUE /datum/bodypart_overlay/mutant/plumage/get_global_feature_list() diff --git a/monkestation/code/modules/the_bird_inside_of_me/prefs.dm b/monkestation/code/modules/the_bird_inside_of_me/prefs.dm index 6a12a4bb364f..3314df661b25 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/prefs.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/prefs.dm @@ -81,6 +81,14 @@ /datum/preference/color/feather_color/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["feathers"] = value +/datum/preference/color/feather_color_secondary + savefile_key = "feather_color_secondary" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + relevant_inherent_trait = TRAIT_FEATHERED + allows_nulls = TRUE + default_null = TRUE + #define X_TAIL_CROP 16 #define Y_TAIL_CROP 5 @@ -93,6 +101,11 @@ relevant_external_organ = /obj/item/organ/external/tail/avian should_generate_icons = TRUE +/datum/preference/choiced/tail_avian/compile_constant_data() + var/list/data = ..() + data[SUPPLEMENTAL_FEATURE_KEY] = "feather_color_secondary" + return data + /datum/preference/choiced/tail_avian/init_possible_values() return possible_values_for_sprite_accessory_list_for_body_part( GLOB.tails_list_avian, diff --git a/monkestation/code/modules/the_bird_inside_of_me/species.dm b/monkestation/code/modules/the_bird_inside_of_me/species.dm index c8e33c9c0dee..1bee036b0a0f 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/species.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/species.dm @@ -50,6 +50,7 @@ GLOBAL_LIST_EMPTY(tails_list_avian) inert_mutation = /datum/mutation/human/dwarfism species_language_holder = /datum/language_holder/yangyu // doing this because yangyu is really just, mostly unused otherwise. + color_palette = /datum/color_palette/ornithids /datum/species/ornithid/randomize_features(mob/living/carbon/human_mob) human_mob.dna.features["feathers"] = "#[random_color()]" diff --git a/monkestation/code/modules/the_bird_inside_of_me/tails.dm b/monkestation/code/modules/the_bird_inside_of_me/tails.dm index 511ea9447db5..3d55cd12f292 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/tails.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/tails.dm @@ -13,12 +13,14 @@ feature_key = "tail_avian" layers = EXTERNAL_BEHIND | EXTERNAL_FRONT color_source = ORGAN_COLOR_OVERRIDE + palette = /datum/color_palette/ornithids /datum/bodypart_overlay/mutant/tail/avian/get_global_feature_list() return GLOB.tails_list_avian /datum/bodypart_overlay/mutant/tail/avian/inherit_color(obj/item/bodypart/ownerlimb, force) - draw_color = ownerlimb?.owner?.dna?.features["feathers"] || "#FFFFFF" + var/datum/color_palette/located = ownerlimb?.owner?.dna?.color_palettes[palette] + draw_color = located?.return_color("feather_secondary", "feather_main") || "#FFFFFF" return TRUE diff --git a/monkestation/code/modules/the_bird_inside_of_me/wings.dm b/monkestation/code/modules/the_bird_inside_of_me/wings.dm index ce0d46153a58..230b3a1c5c04 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/wings.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/wings.dm @@ -76,9 +76,11 @@ ///Feature render key for opened arm wings open_feature_key = "arm_wingsopen" + palette = /datum/color_palette/ornithids /datum/bodypart_overlay/mutant/wings/functional/arm_wings/inherit_color(obj/item/bodypart/ownerlimb, force) // overriding inherit_color directly because "override_color" for some unspeakable reason gets passed fuck all - draw_color = ownerlimb?.owner?.dna?.features["feathers"] || "#FFFFFF" + var/datum/color_palette/located = ownerlimb?.owner?.dna?.color_palettes[palette] + draw_color = located?.return_color("feather_main") || "#FFFFFF" return TRUE /datum/bodypart_overlay/mutant/wings/functional/arm_wings/get_global_feature_list() diff --git a/monkestation/code/modules/the_fabled_dna_changes/dna.dm b/monkestation/code/modules/the_fabled_dna_changes/dna.dm new file mode 100644 index 000000000000..2d8feda81e63 --- /dev/null +++ b/monkestation/code/modules/the_fabled_dna_changes/dna.dm @@ -0,0 +1,43 @@ +/datum/dna + ///this is our list of color palettes we care about + ///this is typically just for species + var/list/color_palettes + +/datum/dna/New(mob/living/new_holder) + . = ..() + for(var/datum/species/listed_species as anything in typesof(/datum/species)) + if(!initial(listed_species.color_palette)) + continue + var/datum/species/created = new listed_species + color_palettes = list() + color_palettes += created.color_palette + var/datum/color_palette/new_palette = new created.color_palette + if(holder.client?.prefs) + new_palette.apply_prefs(holder.client.prefs) + color_palettes[created.color_palette] = new_palette + + var/static/list/generic_colors = list(/datum/color_palette/generic_colors) + for(var/datum/color_palette/palette as anything in generic_colors) + color_palettes += palette + var/datum/color_palette/new_palette = new palette + if(holder.client?.prefs) + new_palette.apply_prefs(holder.client.prefs) + color_palettes[palette] = new_palette + +/datum/dna/proc/apply_color_palettes(datum/preferences/applied) + for(var/datum/species/listed_species as anything in typesof(/datum/species)) + if(!initial(listed_species.color_palette)) + continue + var/datum/species/created = new listed_species + color_palettes = list() + color_palettes += created.color_palette + var/datum/color_palette/new_palette = new created.color_palette + new_palette.apply_prefs(applied) + color_palettes[created.color_palette] = new_palette + + var/static/list/generic_colors = list(/datum/color_palette/generic_colors) + for(var/datum/color_palette/palette as anything in generic_colors) + color_palettes += palette + var/datum/color_palette/new_palette = new palette + new_palette.apply_prefs(applied) + color_palettes[palette] = new_palette diff --git a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/_color_pallette.dm b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/_color_pallette.dm new file mode 100644 index 000000000000..b5e294153d09 --- /dev/null +++ b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/_color_pallette.dm @@ -0,0 +1,26 @@ +/datum/color_palette + var/default_color = "#FFFFFF" + +///override this if you need to check if the color can be applied +/datum/color_palette/proc/is_viable_color(color) + return TRUE + +///this is where we apply colors to our palette from our prefs +/datum/color_palette/proc/apply_prefs(datum/preferences/incoming) + CRASH("Please Override apply_prefs on your color palette") + +///this takes 2 inputs varname and mainvar. mainvar is optional but if varname is null trys to return maincolor +/datum/color_palette/proc/return_color(varname, mainvar) + if(!varname && !mainvar) + return default_color + + var/retrieved_var = vars[varname] + if(!retrieved_var) + if(mainvar) + retrieved_var = vars[mainvar] + if(retrieved_var) + return retrieved_var + stack_trace("return_color called with a bad varname.") + return default_color + + return retrieved_var diff --git a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/generic_palette.dm b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/generic_palette.dm new file mode 100644 index 000000000000..6bb163e3cdea --- /dev/null +++ b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/generic_palette.dm @@ -0,0 +1,23 @@ +/datum/color_palette/generic_colors + var/hair_color + var/facial_hair_color + + var/hair_gradient_color + var/facial_hair_gradient_color + + //this is temporary until we move everything over to per species coloring + var/mutant_color + var/mutant_color_secondary + var/fur_color + +/datum/color_palette/generic_colors/apply_prefs(datum/preferences/incoming) + hair_color = incoming.read_preference(/datum/preference/color/hair_color) + facial_hair_color = incoming.read_preference(/datum/preference/color/facial_hair_color) + + facial_hair_gradient_color = incoming.read_preference(/datum/preference/color/facial_hair_gradient) + hair_gradient_color = incoming.read_preference(/datum/preference/color/hair_gradient) + + mutant_color = incoming.read_preference(/datum/preference/color/mutant_color) + mutant_color_secondary = incoming.read_preference(/datum/preference/color/mutant_color_secondary) + + fur_color = incoming.read_preference(/datum/preference/color/fur_color) diff --git a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/ornithids.dm b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/ornithids.dm new file mode 100644 index 000000000000..08c0dc79c0a8 --- /dev/null +++ b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/ornithids.dm @@ -0,0 +1,10 @@ +/datum/color_palette/ornithids + default_color = COLOR_AMETHYST + + var/feather_main + var/feather_secondary + var/feather_tri + +/datum/color_palette/ornithids/apply_prefs(datum/preferences/incoming) + feather_main = incoming.read_preference(/datum/preference/color/feather_color) + feather_secondary = incoming.read_preference(/datum/preference/color/feather_color_secondary) diff --git a/tgstation.dme b/tgstation.dme index 5487dbecce54..5669b751a3d4 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -7919,6 +7919,10 @@ #include "monkestation\code\modules\the_bird_inside_of_me\species.dm" #include "monkestation\code\modules\the_bird_inside_of_me\tails.dm" #include "monkestation\code\modules\the_bird_inside_of_me\wings.dm" +#include "monkestation\code\modules\the_fabled_dna_changes\dna.dm" +#include "monkestation\code\modules\the_fabled_dna_changes\species_color_pallettes\_color_pallette.dm" +#include "monkestation\code\modules\the_fabled_dna_changes\species_color_pallettes\generic_palette.dm" +#include "monkestation\code\modules\the_fabled_dna_changes\species_color_pallettes\ornithids.dm" #include "monkestation\code\modules\the_wolf_inside_of_me\bodyparts.dm" #include "monkestation\code\modules\the_wolf_inside_of_me\organs.dm" #include "monkestation\code\modules\the_wolf_inside_of_me\species.dm" diff --git a/tgui/packages/tgui/interfaces/ColorPickerModal.tsx b/tgui/packages/tgui/interfaces/ColorPickerModal.tsx index ff7a79706dec..75e5082f0f36 100644 --- a/tgui/packages/tgui/interfaces/ColorPickerModal.tsx +++ b/tgui/packages/tgui/interfaces/ColorPickerModal.tsx @@ -9,6 +9,7 @@ import { useBackend, useLocalState } from '../backend'; import { Autofocus, Box, + Button, Flex, Section, Stack, @@ -45,7 +46,7 @@ type ColorPickerData = { }; export const ColorPickerModal = (_) => { - const { data } = useBackend(); + const { act, data } = useBackend(); const { timeout, message, @@ -84,6 +85,7 @@ export const ColorPickerModal = (_) => { + diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/monkestation/ornithids.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/monkestation/ornithids.tsx index c3a603e7afe2..7ab041058601 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/monkestation/ornithids.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/monkestation/ornithids.tsx @@ -20,6 +20,15 @@ export const feather_color: Feature = { component: FeatureColorInput, }; +export const feather_color_secondary: Feature = { + name: 'Feather Color Secondary', + small_supplemental: false, + description: + "The color of your character's feathers. \ + (Armwings, Plumage).", + component: FeatureColorInput, +}; + export const feature_avian_tail: FeatureChoiced = { name: 'Tail', small_supplemental: false, From ba37b48ca8cb4421a613f959a057622fa07ba569 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 20 Sep 2024 17:22:49 -0700 Subject: [PATCH 093/158] Update _base.dm --- .../code/modules/virology/disease/base_disease_folder/_base.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/virology/disease/base_disease_folder/_base.dm b/monkestation/code/modules/virology/disease/base_disease_folder/_base.dm index cd32a3929b1c..7223a5f4e577 100644 --- a/monkestation/code/modules/virology/disease/base_disease_folder/_base.dm +++ b/monkestation/code/modules/virology/disease/base_disease_folder/_base.dm @@ -208,7 +208,7 @@ GLOBAL_LIST_INIT(virusDB, list()) e.run_effect(mob, src) //fever is a reaction of the body's immune system to the infection. The higher the antibody concentration (and the disease still not cured), the higher the fever - if (mob.bodytemperature < mob.bodytemp_heat_damage_limit)//but we won't go all the way to burning up just because of a fever, probably + if (mob.bodytemperature < mob.bodytemp_heat_damage_limit - 15)//but we won't go all the way to burning up just because of a fever, probably var/fever = round((robustness / 100) * (immune_data[2] / 10) * (stage / max_stages)) switch (mob.mob_size) if (MOB_SIZE_TINY) From bd4a48e2724a0c8d4466ac509d0eb8068efc88c7 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 20 Sep 2024 17:31:11 -0700 Subject: [PATCH 094/158] Update particle.dm --- .../code/modules/blood_for_the_blood_gods/particle.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm index 1a0885fe5605..95a8d6696fc0 100644 --- a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm @@ -48,7 +48,7 @@ return var/obj/effect/decal/cleanable/splatter if(!ispath(splatter_type_floor, /obj/effect/decal/cleanable/blood/splatter/stacking)) - splatter = new splatter_type_floor(loc, blood_color = color) + splatter = new splatter_type_floor(loc) splatter.color = color if(messy_splatter) splatter.pixel_x = src.pixel_x @@ -56,7 +56,7 @@ else var/obj/effect/decal/cleanable/blood/splatter/stacking/stacker = locate(splatter_type_floor) in loc if(!stacker) - stacker = new splatter_type_floor(loc, blood_color = color) + stacker = new splatter_type_floor(loc) stacker.color = color if(messy_splatter && length(stacker.splat_overlays)) var/mutable_appearance/existing_appearance = stacker.splat_overlays[1] From d7f10493741008dc978c177d68f0807de90f8b1e Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 20 Sep 2024 23:09:34 -0700 Subject: [PATCH 095/158] adds support for arbitrary amounts of color zones on mutant overlays --- .../bodypart_overlays/bodypart_overlay.dm | 4 + .../mutant_bodypart_overlay.dm | 31 +---- .../mob/dead/new_player/sprite_accessories.dm | 3 +- .../the_bird_inside_of_me/icons/armwings.dmi | Bin 14979 -> 15125 bytes .../modules/the_bird_inside_of_me/plummage.dm | 7 +- .../modules/the_bird_inside_of_me/prefs.dm | 29 +++- .../modules/the_bird_inside_of_me/tails.dm | 8 +- .../modules/the_bird_inside_of_me/wings.dm | 16 ++- .../multi_colored_bodyoverlay.dm | 43 ++++++ .../generic_palette.dm | 12 -- .../species_color_pallettes/ornithids.dm | 7 + tgstation.dme | 1 + .../interfaces/PreferencesMenu/MainPage.tsx | 126 ++++++++++-------- .../monkestation/ornithids.tsx | 30 ++++- 14 files changed, 197 insertions(+), 120 deletions(-) create mode 100644 monkestation/code/modules/the_fabled_dna_changes/multi_colored_bodyoverlay.dm diff --git a/code/datums/bodypart_overlays/bodypart_overlay.dm b/code/datums/bodypart_overlays/bodypart_overlay.dm index 5e848ee54c21..365a9f73197e 100644 --- a/code/datums/bodypart_overlays/bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/bodypart_overlay.dm @@ -12,6 +12,10 @@ var/datum/color_palette/palette ///our palette key var/palette_key + ///our fallback key + var/fallback_key + ///list of palette keys to colors used if the accessory says it needs multiple colors + var/list/color_keys ///Wrapper for getting the proper image, colored and everything /datum/bodypart_overlay/proc/get_overlay(layer, obj/item/bodypart/limb) diff --git a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm index 737e66644d17..e5abf9f742ef 100644 --- a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm @@ -13,10 +13,6 @@ ///Take on the dna/preference from whoever we're gonna be inserted in var/imprint_on_next_insertion = TRUE -/datum/bodypart_overlay/mutant/get_overlay(layer, obj/item/bodypart/limb) - inherit_color(limb) // If draw_color is not set yet, go ahead and do that - return ..() - ///Completely random image and color generation (obeys what a player can choose from) /datum/bodypart_overlay/mutant/proc/randomize_appearance() randomize_sprite() @@ -53,27 +49,6 @@ /datum/bodypart_overlay/mutant/proc/get_base_icon_state() return sprite_datum.icon_state -///Get the image we need to draw on the person. Called from get_overlay() which is called from _bodyparts.dm. Limb can be null -/datum/bodypart_overlay/mutant/get_image(image_layer, obj/item/bodypart/limb) - if(!sprite_datum) - CRASH("Trying to call get_image() on [type] while it didn't have a sprite_datum. This shouldn't happen, report it as soon as possible.") - - var/gender = (limb?.limb_gender == FEMALE) ? "f" : "m" - var/list/icon_state_builder = list() - icon_state_builder += sprite_datum.gender_specific ? gender : "m" //Male is default because sprite accessories are so ancient they predate the concept of not hardcoding gender - icon_state_builder += feature_key - icon_state_builder += get_base_icon_state() - icon_state_builder += mutant_bodyparts_layertext(image_layer) - - var/finished_icon_state = icon_state_builder.Join("_") - - var/mutable_appearance/appearance = mutable_appearance(sprite_datum.icon, finished_icon_state, layer = image_layer) - - if(sprite_datum.center) - center_image(appearance, sprite_datum.dimension_x, sprite_datum.dimension_y) - - return appearance - ///Get the image we need to draw on the person. Called from get_overlay() which is called from _bodyparts.dm. Limb can be null /datum/bodypart_overlay/mutant/get_image_inner(image_layer, obj/item/bodypart/limb) if(!sprite_datum) @@ -98,10 +73,6 @@ return appearance -/datum/bodypart_overlay/mutant/color_image(image/overlay, layer, obj/item/bodypart/limb) - - overlay.color = sprite_datum.color_src ? draw_color : null - /datum/bodypart_overlay/mutant/added_to_limb(obj/item/bodypart/limb) inherit_color(limb) @@ -138,7 +109,7 @@ if(palette) var/datum/color_palette/located = ownerlimb.owner.dna.color_palettes[palette] - draw_color = located.return_color(palette_key) + draw_color = located.return_color(palette_key, fallback_key) else switch(color_source) if(ORGAN_COLOR_OVERRIDE) diff --git a/code/modules/mob/dead/new_player/sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories.dm index c30a3b14f9c5..1426e4648449 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories.dm @@ -84,6 +84,7 @@ var/datum/color_palette/palette var/palette_key var/fallback_key + var/list/layers /datum/sprite_accessory/blank name = "None" @@ -1897,7 +1898,7 @@ MONKESTATION EDIT icon_state = "cat" hasinner = TRUE palette = /datum/color_palette/generic_colors - palette_key = "hair_color" + palette_key = HAIR_COLOR /datum/sprite_accessory/ears/fox icon = 'icons/mob/species/human/fox_features.dmi' diff --git a/monkestation/code/modules/the_bird_inside_of_me/icons/armwings.dmi b/monkestation/code/modules/the_bird_inside_of_me/icons/armwings.dmi index 725bf36cc86bdf64f31986141b9cac67d184f4f1..52e17f5c7ed9897da83359bcc336b9fea188143c 100644 GIT binary patch literal 15125 zcmbt*1z3}9|Mmz$P(npeNks)o=}r+WQc4Aelyr9uMZls&7#;G^!U*XY2F(N{1`-no zqjM62v3=Kkp7;O%@_66l_;wr~Zuho(_kCTzIDhAP^3p(0hl%k5BLo6rx_wK_2m+ys z0ROCy(}5$^krgW71y``Kxv!SJkFB?pr>~QTI|LG#S^G}K9lZ zz+X~#qJ@qOM(=%aU+Ue?YKTD3jwtG6J!0X*&a50Sg6;Xjbn4l)hetii>$MI#Cm zZC&59LatAb)PFza7UNjG#d`JOFm(T1j=1`Ye%3X$$M03b#A5r-sQti5NFm-5ZTZu8 zZ=DZRkq^3SfBmcB)2}EGt$Sm~y*DgRrbii?*QN(NCULWLn=x_tzRJnoSP`?5rm=77qcd+#GBBP!X3A+!Py2vou{tw& zr=WQ!7kM#;2Ymz4+z-uVEqs6cq4o6>ABs~HHu*$Bxu!p{EQZO&QJ(|_pO~898AdYAOG>=hjU3dL0Ro)z9A%{&}mSbi9_7VI27@<;5CQ1 zP_;_?W6q;aVj41IJ{1-ch(gXn62J{yKK*HXyShvh4u_w5srA$EdH=lkug_5@MmZMV z6*@I|&OTc>K&8OpWo``bBWv%}-5i$g@?aB4g^A)ePU1bp#R+m;kXId-z(*vcrJtvz zo!7~q?(csi30}<4+d~!e3!T8Vd7F^O#!^=FhWp{r@N0B*bfKcd`qgK&@(nS1&n3t= z`f~^Ywxl|mc5u`CD39>Syu6F({OPeV_UP#7%?u2&aQ>TM{Or890-C$TT;vkGZ}c5@ zw7nf7X4P^W@e3fXNPD4X1IcxDbp|5r5>it6%0b&-M}2aXgPwuwFEAH5kTpp{@Lz}(0z24{#ZE5@ z?_*F?x{6115VLGaYiMV1r4bUpb>ev%g+>}$;7+-jyX6Q(b8xoB%+kl9l8%m>5PJUg zS{HO&zg0W22M0%3TCfy3xF2&Khq2O_i&rBP2C~I{dclGZz(_uK?Ym2C%Ld>B z_?5uoD(>>SYq!Gd;|Y)83kA9wHk8|uV$!D$Y3=Xn!_QlNjo}R+H#)x^|r{TSS77PLvvqWWo0OCY1AS-@L^r@5rmvoE#2sOK|9v?-L~458ZI>E%T#LGWr{iCOhAg!&jX z@i1MqvbOdZM3DV;9OJvbo&`dO+Yx1x$5R$&3S>K$M&vUu}LhA28zjXTL$KO-8F8^u_S4uA=%zSF4glbme znSRU#yvG|tJseKV_y(~%CM6{mr`-&KqhljE-zmN9ATm(u+@!bhu~AtZbTTFX6+sGC z?@A8|Iw=mKMz07Oy>JOU>GYnGTn}qlGw{~>Z7Z&oPFa$N=VP^#L1w7E+UeNd_Vx>7 zVPYb9U!kQ0m!%4vP@f1Vy3t3JmzOVZNf+fKF2lvyUuPHH*(SJ))8IqIwRj#S2_O8Z zb>UVc3G~!;*Acw9QYoAM4HS{>x3Dia)ZHWZ4hiiV0!@@BC01MCU#&| zh#|W2Q+{jmFf@YDJYN?Z%S;vI{s!(nH*=#b>lV-J-*`W+0z=F<5VoO9#C~L(NG5L?5Ij|tm8^~`?jQ4Yv#iKj6;K-zNhDxu86GT2wy6>XVY6PmxiFCP+NNsJ zMJWN{~eD* zjw9%USZUoGRpwulh0Wfz3wbT}CJW!GGJjs^^z_{TaYX_aLa9bLj3>n0+?*AB!EZLb z@ZyEoV4f%rcJ}99U;X$`zua%)u(seBax`XGW*6jkS4a3Jp5RlMen2@bovyB5g{{y}o2LkyYDw9ZVUHkQB(LP8vK5+6{Q zT(_g}z|qYOBcjY`-Sd9=&GuWOYUe?B;9+HkY| zr-cI}PfRp2fXzS=y zH8#E+8Zy*5)@0e1Mk0kTHpLYbT+!)+k&pKF(MVEMl7Rk!5prUET}(5NRWDPX>Zaj4 zbs;YeL$>*^FV7s0(j1?j-f0cRL0=ONn?t4gkrD{P-sDjp2>v4d92*#nHz_H}Q*oS$ zg#|kghiVrXefko^($SM7a4J^Y5>X7UZU~Kz$;#sXP+qRU{F_L?@6X2YdT#ydShiBX ze0qy(Bwmdq2>IEcCN(}Y)491>iM|vzjKRdCP`a54K6LFGkD#GjH}w%|l#12QyVyn) zeF6cAsvNipp`oGap7&6n8E)7E1m)T%^CX zIwAD|fxr^*3;Ua2Shz>YAR??30@k^Nk{O?~4*GFNX@0^Rug&!&EpBXdVY}kJc2^&O zQ;xVKwgnyhzVkYS0iqnb&zhf~4=!YUa?+*5FeD@d zJU_?H-2qm@Ql;Kp#KzN;HDG;811t{M-?9bxohzBDVHaQr!#UR_C4U_dOb-qYa-A;B z1Y()MHPXv=xKdWI3gnaAOdw5qVIE>&s4?tOKavL@09sr;oG1$CI)7dx&!GL0M{Cpx z4zXNgp-)Q;EEk^(Cf@-NjCv+`MU;*4*qb+R|=S!FOcM;jllV2GmBA=y83#7bqq58=~F6KSJzx5lDD)} z(Mmw$wB~UWlOeD}v9U}iPoDfqIy%g*Fs7gf&f%}Ks<3@#4! z-ywpPvU8DDkH+P&Cr{{e zU?c_AgGGL@eZPlvdKYqFansY5pcwq*K<*#IEi8b=+8s56&aTyCI*CN(85lVXtlBS- zeCN)cTimy|28q)PGJ#Sa_AoGBfZhTR*Xp;xcWN#EfYvma_%INqAOM|D_C@-Ofh5yPwvogY?inP0Mv1>(oS)a$p z&utSz?^01#cxkxk92b|CAe;B-#T$7ElJfE|W@jHSHqG4G0XXq9KnPZpVit14LG$=Y z7M1|wc+LbUdB4ymPW>2=+|h)3aPmp!SX*1$-f!QS!KXV?F0e61vA)#0E-yd+z4tA@ zyF8bBBPlWQRLk%0ciW=;aQ)}!!D57;U1)wXkUa|uXLN}K3=m(w_|G53 zt;Qy2OG{;2un|f2&zx@z`t2#=Fq5gU0B>JBq|s)6I_UIEt!cbb$vX(M`&S5LczC#N zCN>j~@4_2CvKRZLGe3;LiYYeq%ZTHk@IfZq|})EM!t{EVi)Vm^rX; zQ-s~;qpJwJ3qjT&Ra`1`De?GRyjMp+@6?oqZU%AYgbgVs6)A(mC|Kd^xglVQr{4)B z^_a(zUTSGxKFx3?sb@sFqO^4LLUd?&o_X#H0gmx4a` z6}z=emeHlL=4OUq3Sa2;!riDM0+r)XC{)UdEotoUGrG`0&bN8}9`S3P-BJ_AEqt|+ z=*r?tyZ35h;sGRPSoJ{)*EA}ty=CEI4!_c;)zuFxdVD%2CMGu(v)H!+x$fS*E7SMa zuv4Gsk1MBN@@46vTPgq+_=@!c2Oozr>Gj%z1*hQNX#)BrM9yQz*nPUmL~c1fEgmt! z?I9J{saN>4vo+pT_Jk$+6k}AWn%+4$Sn&y0_K3sQgry~?n-vY+tfNe3AC z8E6C2iVE{xY?X%RtISUVtnfnX(x7ztj}%XNi|I#(CMNP(%#weG`8`dNUrdCsl4g!G6tKgjF9ss9e^{pM>}c`H=2ix*2_$02uf5u;`7G|YT|&^!p5(^r zYMVnYAD!dNijF0Q^q}F;Kmf)_@6yrMzToggEQ3PN0G#rTxWd!DfY;Q^C@d^=Hf`Zb zEI0k@q@Jo7-D8n5Lx?H2fn!lO zi|I-c_h7HS+7azf>zlI6wAvcaS-7}Pd|aV5owJGvWkOvCv;w6NuQ$wN=(*msMQKuj zjl{9|$Y+tL=r3Lv_{wQ7dETz(0YDLbHQx!LR^6LLg@vWFoI2y$Xh;TGEJvX4E%#s# zz1AGPn1h1@giG&e?oREQIi10*v5S*}lgd(3kq*3kj{z{Cz)}!ZYz|fm-oI(n5uyB8 z2?hMj^HD)pVnfi?q!NY4bN>NingQ1Mu8eT#i>>{fEiFa^*vZOdrvm5&-82;U zXrM^tke4;sw^%Y*jvS3wfM^hyV`o0@ro@y7Rp;Pc{?$1+D! zb)v;iP=4G}?r4>|t&Ra(M_m}DkUt@9@40`2O3+^kVt_gu*G)eN#cr>yN4y>0oK#t! zOyq7$)@!E>VK{Nv#x7Bmg^F;h&5rrAGIc;H&BNrZdsjP}H`-1F;V{c{1BNG{)ho2y zGTp+|ZAZJ0CRg&()bN155TA!0U3sxt;E=`FEh}ICD173+G7o?eraN1?h>e{``72Q| z(a{M#b|Od-3L_9f*n3DCy^DxAC`rSBB3pUl{e5l&lTkPr7EGx!6XL_RdjuMS@D3<@ zHyxEgDWA!tp1=0@vGK95UlbG+%q}f0F@fcw!in>)6c9PX4Gj|B?DY24thOx;h?f}O zNfkdP4DV|;+%HezjBf4C5D9Q?Rj0Dv-l0Sex#DZ!K?dN6(y<_gmW@x4!xS4QSLkvox36{Ib+c{ zUH`P^%>U9Mpf$((g=g*vC6}5C!SO!Q-xlznm;IlZ+EkfOx86K@Us?((M}k`CS;>VGEh!5t1DmAc%NaoHmPn?(nP1Ggby@3DqJd=EJruUIlo9c`dx3-T z*rW<80cMFV3)p0Mf9Br3d(y$5jV6-&X{*EvX-wh)qS#`(6ZPwag4L zrtDxr0Lym!@@YRN3H^@09@V=~%*2euNvNMMtyp2&V0(9`;Q5EihA!&>PIeZrjZ#LQQ(y01tHZ|L^9>x>e;=|UIrYuEv??<}RS)XmYY}RJ7--*nyYz;o! zWA}Zl*wJF_oT}$|PyZa&TLIguJU!y3Gb3*NU79JvPaXo=jN&zD-7(0oEqPfvxknX% z=%ZXPCmwMgVz=KpbRWGF-9`S8nserL2Uox|JIQOHm{M`+9ojwc_LU2u#%ITb#;wxU z)YMccJ>>$8;p~#{Ls0%jL`6qMlJts1zc|4`$@W#W#5bj+q<}O`)GLbGl99g_PYDbV z%>fHgDacey(EUcg71QZr7YEfghkzE8`~{^nx(j=%)e|DVmO6rLr6l>s7FOt;W!=K* z^{9LL`eq)C-0@wfm}988d>wR$DOg59;ia}f5iyloR*0YdHDxRS1WS6M$>eF~n6eOI zux&-d8k7x|B3pGM*I5TwS4C{9&QYS_4qPC5PC_PV7Zw_7QKdM02DBpk9>dmCw)7{X zG*i>loewg#LCs}ljN%GV|M}CQ=RfWX@{J7ApfL0!1GdfHoJbRv-e7pHnHMd<0Z^UW*40s>0$L`Dy*QKaLbf#>U1{L4=a; zps-+mXR48cqlhfmVK^4wCnP_XIegH?BHjD<@5=~V#dVts8_@~m2uEH|85M+-F$<5*Q0opx2Mj=y=91+PH`{Y-wWZFrv z(Tq{g<{vDDs*2m~gBuy$jOBODcZop3-~&naJ~ z{{H=&4lEA@50Bq5A~7Ka1#fi*&(A;b$NXM^8w*|Ohd)d1o3|{Bzg1@G{aT?JZ72r6 z*=Vso?qWw;`$S>IZ%C5$K9+PEE=G(f^dsvfVE>l14af{tFdBsBjuaE!3EPE$@7|Ne zVY0ZwI!d;(vm$oPYI{AlUHk`7rZSWesvsH*6 zL&zzeu3eD}(x!VV>z(){H3T61jEoFXbQidJ7!DIl!SIry*u|2S;4fI1Y5%~>4x2b7 z4KVkB1^}`$tXf2&DMRUL(7+8<9sg%whCpYj$CZ|rzVcNR1uX`20Oyq3MZ+nxAMaj1 zt)ZAz5o8HQ2#|)iiiSV$U&wsdMF|WL&CQes0y<^ST&fC3xrRu=}27VNp?;TvS{a77XqXX2qI9C(zzgGc&dFlkSJ# zqvA{kQvjt&+`3GyJ6!4pD1gz{vtZkXm-r|f4CskDXuxqte}8r`R)A=5FX%gSV>>ln z`A|(&wZc4WlOalTw0f?1=0z1vwC2Toy1Fu9di@RaZ~A)-spH@%70B0Jyfly#vo!Qw)N6`Q&o*-KL2m%omxrSNWGJ~4_NeIdJ@O3HWiz4(U%2#&VC@<&I;FO> z)9%rMjRq9z_6J|p91ck$xDn_5&Qoz3`69q8}RouI!((TG9M4+tR1M5URSADrm62)CPdUncjUOtPC@nWgHxi0yQ+X?3% z=odkXj(#G8fz7D(;~0Ow`VO!nA!^@-QEIxpk_9qUXkE4@)^FW_%xJh`&EPo z@@Q-~*zpf~$J`~D!5A)umOKzRUd^Ppk^8}5v&2b;S3Y|)tB*kq^R<;#~Q5P><{oX~9skfRTL9!wgt%=Ay~ z0(huO+PB4CvT<^93JeYoj{Gxz^mPSaBS%Bo*e=_)Zf}b;dmP~J3MHS$-Tl-%zg;n^ z^Vg_YV@KxniXgo2y@go7s*EIg*P6l`Tug%r{4mA}`l>H;Q5Yk&Q~&0XsHE4%b!}1H zz}YywJ~U|9u;Y);q8FyeE;&;(yv}(D=AQ()XUvygXuBP6au<$uuby_-sE?xH^x9O| zLZH*#VJg6Xn3}a@0b=Q>!nH9oG@BRXQDxI~TC%x_X@G|zvV_7cbtf*;f~i5n4+t6Y z6iOJ(4CH7U^?z6(k{aNZW{NK+-U3A^&rULJ*%pvPI|XODB^jeMYkkrt`N)*Y#jG0c zuU-R|G#bY8-d0+;=0V28Pn2f!upc?*)r;|mB!KaFCQz9<*Z-^BTNpjFwhiJRie@6c zYjvH?EtcTgvOe`;A7SCPwtmNSH5MDrAy+~~F zC@yr8iSJ9ej8uG@b$@<6XD9PH z#wbYc0b=wv9~J{h%mrq_9?)n_z%+0ZoaOs>Bb4NlZ`0Mka&KNb_1ExHx*s5>p9A6t zG>$iJyGAU35Og!X-a?^Mpwp(RiBpEswp*&Ix5%BG*E#oi9yXR#Z`s9(^exNhHqx9c zD#vB$*K1b9zkJC6q^wXpO72C64Ujy6K2$RHB(yaGCihmB-syw>u(U;^_c1_KY_#t2 z0C-&+S@%$lQkv4#2D1ozk5mM6QU?~IPC`jY1HpFII>76F-QRBj!{c@T6j#~TpeUtK zCx|zIHDmtF5qTG`bH@g!^Z7*i@x&&j%-} zb;|b0Qq!*(>OBBN4;M20??gR8c%&+*V|D)hNf|aq8H>cyQd2}%@<2vTdu1S zc?QJ}Le91H)>ajx%z^-Br6-zIOeH6uom}Y7C0;nXGLgvX_o1pv0-|1ER1!3W$^glH z`VW`|_7=Yd2pB#7=4Lwkn(XHN(c=#-%QAZG5>O5<+BO1|t}&~xt81c^Xcurk^>R)U z%Aw3&p?uQO&Q9z6`SXSVu794rZfa`k`bC_LadZaM z%fFfiR1N~>HDSQ&_5y-!`ZgE#_kb%Hvn1qPL93-8eMwFkt?HEse>CK7r_0jEOA zKP;2ybGOdWpj6(>lxu+dS!Jh`N|x*7^*&^U0sg$d!dux4(rxbxj+u&g{AV9X#Q&IZ z9UH;}uIl=R#79M@ckoB3{(j>&%(W;Lm*w_#Op*+YHb&4N8oG<%6Z&5|9%y ze;TF|IbH4Cz)wyEOG2mjL(wm#G}QFM<4*MNguCw2OY@MWvdyWMID??zNzq1>qhA?mvIpE^a6J$9_AY$vS~C56Ca0j)>G3Qark) z{0FCRBokdOAWBP*Zy!^*hFKXI?q4$=*`Iw$v3OuL!g>e9{d3r9BR~u2W~r5Kj>`aJ zGT&r3F>+Ri#Jw%z@|tjeZ#kfP@W+n}{s93UKrzV(hyMn8 zz4@a@_!-GaAQgA*Y^<%l1W%wV8-D#c5nq(t9)#(`@{z};qy0yjxMl=-97Ah%{I|as zHYq)O0Ms|;F*KU{Yy%KXfkxlpbmKnI;$`II-R=DT4_V&ff0yNhWnj4^hqXfFsN0)n zkifv=qfR;}*OGN<F} zk4qtw4mY+Cu%i={VATRU$b9g{!#wV z@$mQ?{{*tuRRMu2Ao0eq@V>IC8vp(ZZ04D!ir4?>{^2)r)L=Yn#7&y9u`#ebn=bmB zUA!OOGG45kpv| zAdLYY^>EDUM)_B4?;z$^q2rjt!B@GY}m7q5&%Yt3NYXL-KBmauEm?Fq=~h z7(na?PKAQyrlr4*j>0UOd>JS<25?K@@+dx;sHmuvK08uvuqccltKDKCIO1v@yFd-5 zpHYoh?MXbU|L zYz>i-krXq<)cWG_i=KPymM58+-y4-sd<_-Zu-VVYDEk9P60d~s&(edhOl)b-0o|P? zoP^H-gwzR8Va$OTuY3VXz-2T9Z18-`Qi|DVJ7lH+FrezwG%tUS1tkXLFqUF|2*8BJ zfc%-AX$=VkFzyk>fU#UlTmxF=FxCoSom>q8SLdvwr}`L5Ph{BJEilIX|QsuK8zkkVXookMK0ZuOe z@FB32oI@rGKo+_XYXD}?*P^X%fUJFaM!*v|o%H9A%>rkIyw@++M+yupU3`3U-tHCDlB(jjIu++un70p~+D&x&t?u|eWQM4b_W7+~M}DBl z=FUG8PJRWvNPv$23|c&}K>`1e+Tp}N?n={&OLy$fN>g0GOi&lR@7J91A@H4a04JI< ze4!o`ub<%M&io+ox1#S7G8$F#R?rOAWlXM8;qF|V5-HPlH>BurKGfwYwuEmDzDsYt zmq)IFES$*x?c@OVRX<0yeVSaUj?)*9`G#8fi?|oL$Xlq} zgm9?FT){mxM4eMTcFO zq2%oy?LnR7{|Prq%E_4xUq$Xcn`$d*nR);14j_a;$sMW&Jl*`HxseJGgSnU>lKuCt z+BU+o{#&iv4zHOUW?A0#a6rw_`uO;0lJ+g@hpUgK4xRksdk118LZvtuqYBqjv$IV> zV@2VK#$xbzVsyuVEO1m!ry}#I)GPM?jNkE?TO^h4YpK(Zv;Db95=k+Sa5$V+LJdt> zYv_Y;CFUEAVf=@!G<=v54bhEvQ=b%ipE>g5)dph;&FNI#v96aAD^Hq}R9>8qm};({ z?DN59rlH)-Tj8MRf)gw1cJ#6 z=$&(&t!V~=Y>TtG6f4HCGzdrwWVof%h{BP)@^JARaCH7)XXOrXFBdwstpySMWTN1) z?Uea=MG+91cVj@#u=-kdfg=lkz{h`6o{P?45{)OcEY30L_#AETdCIRY1NoNXau;~NFMR~SB3PH; zpC!fqn(&%78P3~!O75?z2 zKSX&im+AA-c^QqF7k-dhL@&wcix2E=UzHWxK(kG+GsysM`D2K;wyUdSu>g`!D7}qU4~d-UY(#;g9NKs1`45^y%NDs@mbLUJpgP#s^v~ zq8Ar3YR-80%Mo39@%8Ta>*qHXh4|Vh@{++eU3nqw)ep}Ds+pv*zz>PdkNM2ljIk9H zKHTL&xa%b{Fg*jGx3MFx5n)75{Fq2l1(XY159T}ff zXOsUxh#S^BKN7Rw@-E~ZhWHj52?13dMR?T4s)n>`9IYlg-e85E zSwqLz5pfIl0UExZMfUVVbmI0rF>=U6_^u@EaN*8$3T&D;a@?^=6fbyE-3Vx8hp4+D zATEzrN6HD41zjV445j#c;}yZ*Zv6PJS7D_y2>lE97tm;~5Z!gk?CVy75BVD0LYgbw z9gXz|-Q;`CJbf?Vi{g|RX%c)bl_ z)Ij{NmvdLm2`~vj0KbLGoi@Tzb{*i%x;UxSFvQM-X?NN=I)gt9T>LcMWl&_WE}q+5 zI9M?UUclL@Y2B=`lPLkZN3U04^ch9hz1T3NkJb}jdqRo{mVhmbz9LXH?t$2~+N(Eh zye9Rxw}BdBQP!q1z_}@4J-L^Yf31K~_a&ZL-Nx0Gj~=Z52$2 z6fGNi0>80FEU7nEima*uunt0UrJc*b1R7NharVj|?bU?K%~M#e)=ToCp8#mNXb*KfUH68HK@lfkJ|GfR_kYrS z`0xR;8Gw+#<()4lD;xb^!ngaM8!wtMT02)g4A{>?57YWNZF^^DMs=*5QIV{=DX8^d zc}bh}kYab*i2UY@*VotLD2hC3gG^$PbDwhj0SuA|_;%6EUyzs(DA1>pdgK*NmrVg7 z4DK_};JEsc)wtmVgo@rH6p{)gYk97UHUgME;)r>Wi_fpu)f<&qhlle(T;*u{k*0`w z{noN|-E(s@v6cj#$26DE$CIPK%%&r`cjSCsyhWLb1J1vq2mJOPS_zFt=TsyJ4+Um4atW*#Pg!Z9^ zsy+llq)7OtBnQt7Bo=%IzYYQoO}$m^U)p&&dU!j!yFnoS83iBYs5?X$AFQpK$a*s= zG(FeVuMNNQt%Xr5J@n!Ahj(y6F}_8dIRWgV8U2k9=dX1NO#j7F5%OsJm$ajp?khfn z%i{Zg$aGDAJiOlUCDNU4kSU8K>Rlgo$-dfV-%9;VQ`4}#b=BM}RVGJv-B%9{XOulD z7@sS&9qlD%daMgf7qU=4O&(bl{Gum2)esXcbG&Ffq0M{^I?G8E!CFKAiesf#s9(Jz zBqmD6&!(Zc(KD_FmEZn7gxN6;|9j`egUAB5r5zCU4t>&cXvHDruwX|nzoNh(6MfyT z4Sg$sc(Una0&N$9f6{WDORL+;nq(~c3Y{Rpu<27#N!x$tU+UWOqJGj7qV z#DnCb??NS~ugG4=8Qr>JVp&zsb|Sf+xU{_3X|-Bq#r0S)?n@#hY-Va88mX5TigeIY z@%}UHR`T$T_h0YsOn*em@zYtl_(+!Yy2akirsFa#Y|0L7YBka^F=9F+Vve@`j~<0G zrlzKslsJyRBI+`7*%~?0ZXOj}DfqZCx2O#x2?nqyxUs_m(Hi~M*GI+k zj#jeUG@Ff)T{U(OR##ySSW`)jSVA-|NmpAQW`dm6S8NQZ>oz zF8#nLL>=vDV=YM*J37Kousg5>jq88T-0CYU!!)jkFW_;5X1@i1*62deiOz~=_FrTa&;EFc)QX}onG;SuD-@bS~ z=^?87ASCm#i;GK}n3krNmgDix!m-ab_U!nsxOhQoA_)6A1bV>&zDqVUrMk>%-C~^}$kHoC|{@pQ2mFoyI2vyuWT%m?ak!+<-Lu{W@41 z^83NRcz$}o>eEwDP@q`I@da;X3KMTq#w*}Yhg=oReALAlBt>) zIXRE_z0V?alrGvnFVq=?0>>1x(f5-txt2?+@Zq|i}-U8j2_Kx^8L9G;1RztcB1+_|adB}NZ}X$=$HRMtj&*WIIR{v`2+BZ49wZ%P zZ76%^Q##kFax0l9$usP=4P$IbDUr~fJ491)4VlJ7jEN~9KN3HoIGo*$kmsC2slFJ> z8b8+z17k-9jpY$*$xR#OGpg zpK^Nv0UH(~B}Oi=&gCimKMdtgk-1k3-+s&)%j@woMmnbD>GDUK$8(}P;W`Rf!``}0 z&mr^EZ-4&eiD(%J3JLkX#hv{gRhqgn0hn!^w)G4!Op5|-9{Z;2fb)uCi4gL>qG*j>!`@8nW> zPs^cfnM{n({se$+AL$^y&#G|E_Gaww{4pR8((KKS@cr`SMB^`N&5fk9;tj?hUqP%; zSkm45Xx|P%PE(Vu0ms0=kmi_{IIEcG-Hgj3s?grTJ&^~*}lynp@80;-SK zZeEV9>-X!d`qD-cECXON@+Z+%CZ-4XQe7V6pWTb~Rp)*4=8fwH=dy!F*_&tgileT0 zm@A=gy$a+DRKgeXD%#XXXlZHPnnM8|sL6?lus3V%qpSAx)$gol_{$xfn`d6i1Ms!b z@lR>}y#8l={e0kKQ7r}#%q7Mpcl?Ocl+8Xy4auMVFgeW*L7TM*g~(W0 zi27gzPdC4ZAvvEdIvjoVt@9a1Cvuf9nK_sODDgBQRg9jd`&!r*#yI?$eN-%@RBk4> zwukV7RAMqLX}oRIm4X;9iU-ZJn$ouEeM%m995%u?>_1Z?|Dj-suB>ipLERoGT3AZo z+x@L#jXvkti9z6w%GuMsYOgE=zleHbVZjKnJ?AnLMLYE5a08w#Fl{WiZFW0*{Q-7z zV&X%@3>sZ$`s4|9&3S3*ot1q~`C$IKx;o-J*{AOa+4ZULmanfbNIIUa!HHY)??RI8 zdK0+%tt~7Lji9DsIVML4?~V5jFW2JV&&l|0zj~Y^M7G&!VjXhBZLX={*{GP--nfZ% zRNmuS^D97^@cf{EULqTOqWk5`msd`;oBfj3ylw66N&vN^@tk5+bbw<#vNcB;0hK&{ z{P=)El5=Z3W|ESZ5}k(wuXyV1%~(=W@~FGKtc>tCcq(iR zKiBN{K$fE$ko<>uJbKohKB3#z%y<#QDHq6CX-ebl>^wCyb6NQn30>I42wVt6-Wd?n0!ppa zytM8YOYstrkN<`PIR}bHj_KQ&^uk-MXWKG|$H)1){EC!ecHQx}EO#pHy2ZFjsiKH6 zXJ>nJeha4)Ha!4L2&>= zxZ=h&I!<|@W81*uyUl;yKw6B7-4ziD6-Jz2PJTq@w=;j_gWKE`h-a6HR={rPyy{+R z9rF7#oT~zsSGeWy^5=0U2ZJr+`(DeGpT`BP0yl1ec~XfnH=jOOT}n`p-zC#A%DQ1a zN9o1N8JYQ_SbO%U)>QCye~R#%+FJ3-swy7vw#8o;g(ELXy3aF$^m^**s%6m{Y{vNJ zfi><|<4g5lO+Jr*wT3(aIQj~lv-dlOQ(*dJx0CKcsWAh7j}y-=*nfH2#rR8ES)CCl zxF5#TU@Jp`E0s-60>&mLT^$|D-Lj-+rlv(_M#YAz^4TU({kc6q@91fFdF-LVUi!j$ zq5PbT?-p}(bo7V9_SxClr#?Pcz%T#ZMI!BN`MB~{%%gw{BvUPpE&F}9PbOhllk;sq zL?<4*fd38V;v@!k5>qIFLoML6zAbrz2Xk~-YAVZzM>oz_B@vE|<@jS5zW#o|{U(9D&Cv#M?cZ;NTidR= ze+?TL82FggL_UBsjvL$GQ(H&j58=@+tS@zV~>t}GUP*8L7hb*AF;KwGf7wz z@Z{Ii)pWvZoXcCHb-+nEmUf?BFaR|9`SX24(6QSSXA2O(R{)&0*5{2miR%eooyDmQ zfukoWuu~?zlJS`;gJQ#Pwa$~@R#yufpxD4!bVrVHNi1@*{0+bkPjIt(#fBe(m+84W zr@%m?fsDw;&E87sKSJ?Cb5O#PZoeE#&JpJ;!jR$pBp05mZybeNPk2Dsfu*(0xbK;F zC&mUk=>|8h>SOCMR{hCm%U;N6vG3xxwY z@ij<~h=f(hkr8TrB%hgsBYNSE;5Q6L8X!nySQrt2ZEI)y5eLI-%*<_zi(Ei`-0rfo zvm=R!i16QTT>GG|B0$M4a{s>nqBG2woPwg(*muPPtTRP)OiV4{R@viUFYjb>#;Lv2 zxGo|hGOS;bLvJE@)w%K9Up9U%8zx_2;{!k#wYSu*luDh^oxr(tvbV&}l)>_!%7Onb zE(+P}>gz*V9EW%I26PAZrZ@MXCrE4jjOXd4R~5l_*zBKgFeIV2%pD>$I-u%{Tu~{p zzuj`l2S7-pp1Zp{0b>wQ|Ek*B0t;Mc3|-g6gmKQwvGf<1yGmGraS3-)@BPih-e;sO zEz)nf)>l+y>~E8`fsD|XQqlxC4U%!AJEjm2eU5%HKRd`POYk?Txx8Mfao6UiQxWf5 z#1JRs>FoPoC#}0A(4lp_pdKUq%s;R42*3>X+ko{^2G6A?jz`BhScLet8oVP*2@qa`Yh`wNex5+}zdK`c9cRMUIETfwWP(pb@<#ZLL!<^Cu?zaAU$uq1`5PZ9!N_NfnXwTNv@B=b(YR{5ZyB~tf1n}{4f*82|ZDQ zw1K#*Y;25eZEfZHL9T3V%?Z%U69gngC&ZOv0`bmjL?KiA&BlgfH$pElH8s_@-yAt|EJWICP*+!}$ra}fy6C}kpLN;Vl^%?&rdt*N_Olwr!b zp*S2g7?hB$FVoA)%3iA{aEvpk?rd!>f^&=n@N}?~2;a@I;y~q1&X_J&zi^~o; z>fIN<$1?Ekf&}%|BLAMRo+ek*s}s+HA6lon#ScC?MVO ztozgbbwE%HlR!}m>X-cU|8@5za0)7+8uvYCrh>+e+I+Tfo0CsKPCJmRPVNCS8*HJ zxC{6rYkU;pgx0?L15iYG0*VEaY-zqF2vixyd2>m<_PI3 zS4{9AZeU-$c#(^g_O@JL@Lq54>FIezE^A56#=d$;th^k)jt6Uz*Uar}O|q8+?#gfnX(u^zjl&Zv$#4Jn{YecU{4&AyUvYv}=a6 z4;3gRS)jOs>?Ig(4JINh`^9@3=&sh&)oU42FUj$^9eg|i;YGAY0Skh1m#`pT%F7A& z0cey80Q-309NTrmY?PF@zP@czwg?WHT3dJLs>D<@G)z@#5rTX;TjKI8C$vYY!cf50 z%d3h*b-A{!xA&oz{3M6$^+A&lpw zW#j@kL1ft2*g${~1V;~iaKI8H%-&am2*RE1cy9laTG96YpTeSOo7-z?CB^zXU{;UK zv0K4__57FOBr6&lS^5l25H9ZSb}wHtxPRRvZ$0@#O_-X=GRw|>VZ^V0-2u$YOFum$ zW6ax9T|OH;77X02g0?cyo71j(EZS?$WHvc_VdRUgwBJ$wm>;(wGURPwHh_UlP#yli zqnHvkZ-(3n2SxYS-45!8;M04+5-zi7%=2=}Tv=HOJbm)y$;o3pMCu6;~&OQ`(J3t<$Wu~)aOJ~ zBcB}8I;sTMo8o~Qs}*6*EEg6dQVA4jn;a5vJl**V8+v1oIAs>0dzi0B#t4 zK&3k3!047Q*?fme+3Qk^$8Tc&V#5$8m-+``?}$aX6%swEq4!cX)pS|*Um4cjrts_@ z&;;rjQ~(O6y*g>hYY!VO)C%0?Z2j&B%xzKG6g-)e1oOld?f&x73|b zzj6(^qglV{zF?wG^olsAucv>YaPI2wXQT3RAK_!4iI^SEIjTY|e{zJfPeQE!EyK`9 zT~AYiU?o(5K&!XHssBrZ_`cd+t)DWk0f3CUZ09-$D)ASH|#f zrAGGikK2D!YTpC@yHcx{!|(#~@y^Eq;V|>#$J?6;Z)a$sRj$(<6*9z0C=NqNp_k0I z_IHsVI9`QF$P69y9(to;DqA#ekRI`=Wr)UXuW?@!*qO{VmF!UML4DU9&U{Y8>sB2^cs&Fi{wYRAHO+Q{Sy&+aD ztRAvondztqE;c$kN}JsqC!Eylpdf)E-!hXg-ROK&M~yM<9mLG*ANctQFJEMi zQ)5rkII|57W&`=$NJ0#vZQ%(<#`qOh@t!Xzuub?-SLi3?`8!I&L0%F8A}#oR;4izq zndGt{R3=Nd*Cf;_5*gC;XH562OGDhvWq4@lfxL*oWT~4WQ>Phh!WsvYMDA=nlSsb; zYJ$3QYKrg>V%3H_(Gn#Dm-2U}-@G2W0E|*9{p+vYuluiO4$|~hKDY*mE5a{oOv&W+ zsaZ%~3k_WQJLo1C4sPuNUtu%a@WRrcu(?{usiTf)&x@w$=en)K!SV@vd!F4J>cxg$ zuHSfhdD9H+xSpH_b680|Yn%0M{qhzl?dv>z4=VKZ2=w8O4U-*%GL4Bi~%)gXm`dUmdliS3}vt@CXGmQ>MQf}CsKuW*3;HR@vyZXS!e;93a z=S>w(2SlJX%mf~F>4-RE01S9{Ffrn6K(TQkd( z;W8s*Q$pJmAZP`FuqY7r0{kfPEE0;W#(h!1&JSQ@phbauXY5CFTFwU}qquGgo5+Ul_+qcgYrseU98FqN$eprqaQL#Lefzo?+>#Y16?G!z@#ilm zvASr!0F)TCWBwA#Z!uysRJ#s@0AliR@)^lt2m-X#n!+lMk4fVup}C+NZ6UOFV!t86 zsxb0}A#x+aX_^pyZ!pf$wz3M+(t%8Ew$i&1bny>t#Sid=tmRb! zpwVe-YtJWLvr430(7u^O??$_qBh3W>;J6CMpVB|8ZB2i-Y5B^m+oYaQ%7aD=`3mO` z{ROBCZtfUL0*r4x;Rd&cNI6oV%w~?&UJw1z-i{IdPrJViqypCQ7tg52tkBIX{j-@= z$c0(&65ONmhIcQoLYy2=JNl?MmsO_h`+Itg&}ZU{ZjmSkB%W~s(R_HU`DVkgf&oCP z6&E|xa%K*Q|8dQOrn2UnDQ--iB0wuau>SU}v%>t6#8}c0isyt43Ni;J$8yp$9{x;~WDyw|WHZCCHXo)=jRRJ;p zAdX3P>(rED9U2;HF66zw+^hoxd#SOC7;7oMh>O#@WPJ1C^Yi(rn|yr8hqn5~j87|> zLoM%uh9A$nwyCL4c0&3*ulT&IB)l!Vf$0xOMzH_$+2uD~oB3A&IBpu;oxtA$e$6`K z1(mFf47KHCE)tWa>}dO;>d}aK8$nIiEV9I@A?x@*2XRwhic>pY7Cq|!r$DQMw7FF= zo^D^rnLlxKx_kGop1X^-^NrA#?^lgIs~^}So8m!(gq*YY#o`9P+Kme|g!q4tqYVh# z@M~_^zchw)d&(SLL1&W5`Z|TSzB%@skP5TS zz8qRXom)jeIzXN?f4_SAi~kv_K14j&#!pXrownHR&F=x}j)KQ2yMr=2{AV41?@)na z&oYGCT-VJ6k}a;$(MF)MlS+f-t%W;_d3wq$Asxs+8wVgo9p*xHue8Nd&~bpyyoOb# z;?1|;>9)$q8hwcQ92gZRhiU$fLf*L|JhzP`2Gl2jN2iXZi!Z`9c$WF@-fOhD2ynVU zzjv>g5jD+CwEo8k4UxiT4)Q*^9@^I`GUFjFE>5<%F&4v`e9ab0_PCa2|6OoaTAFe- zZ4Ib@0B|>1;>jb>3i^kJw=C4Ml4f^qYU`QenzV#coJ~cJWPCiYJ+f}_AOccg4Qok`?_JGOeQrz=D(Nv zwnBkQ_#gDX2hbb&zoGXt>@fvMC2b7n{Y);%OOFa%3oY_L-mjy1sVG=VeoJ^bXnN

uZ9Lv7h@<$xIWyF%|tE346ORE!Peeme*|l3zXAl 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 diff --git a/monkestation/code/modules/the_bird_inside_of_me/plummage.dm b/monkestation/code/modules/the_bird_inside_of_me/plummage.dm index 5dbbb71c18b2..6d06c789118d 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/plummage.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/plummage.dm @@ -24,11 +24,8 @@ layers = EXTERNAL_FRONT color_source = ORGAN_COLOR_OVERRIDE palette = /datum/color_palette/ornithids - -/datum/bodypart_overlay/mutant/plumage/inherit_color(obj/item/bodypart/ownerlimb, force) - var/datum/color_palette/located = ownerlimb?.owner?.dna?.color_palettes[palette] - draw_color = located?.return_color("feather_main") || "#FFFFFF" - return TRUE + palette_key = "plummage" + fallback_key = "feather_main" /datum/bodypart_overlay/mutant/plumage/get_global_feature_list() return GLOB.avian_ears_list diff --git a/monkestation/code/modules/the_bird_inside_of_me/prefs.dm b/monkestation/code/modules/the_bird_inside_of_me/prefs.dm index 3314df661b25..2eddde9bcc75 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/prefs.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/prefs.dm @@ -69,7 +69,7 @@ /datum/preference/choiced/ornithid_wings/compile_constant_data() var/list/data = ..() - data[SUPPLEMENTAL_FEATURE_KEY] = "feather_color" + data[SUPPLEMENTAL_FEATURE_KEY] = list("feather_color", "feather_color_secondary", "feather_color_tri") return data /datum/preference/color/feather_color @@ -78,9 +78,6 @@ category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES relevant_inherent_trait = TRAIT_FEATHERED -/datum/preference/color/feather_color/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["feathers"] = value - /datum/preference/color/feather_color_secondary savefile_key = "feather_color_secondary" savefile_identifier = PREFERENCE_CHARACTER @@ -89,6 +86,30 @@ allows_nulls = TRUE default_null = TRUE +/datum/preference/color/feather_color_tri + savefile_key = "feather_color_tri" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + relevant_inherent_trait = TRAIT_FEATHERED + allows_nulls = TRUE + default_null = TRUE + +/datum/preference/color/plummage_color + savefile_key = "plummage_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + relevant_inherent_trait = TRAIT_FEATHERED + allows_nulls = TRUE + default_null = TRUE + +/datum/preference/color/feather_tail_color + savefile_key = "feather_tail_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + relevant_inherent_trait = TRAIT_FEATHERED + allows_nulls = TRUE + default_null = TRUE + #define X_TAIL_CROP 16 #define Y_TAIL_CROP 5 diff --git a/monkestation/code/modules/the_bird_inside_of_me/tails.dm b/monkestation/code/modules/the_bird_inside_of_me/tails.dm index 3d55cd12f292..db38d91cbd21 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/tails.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/tails.dm @@ -14,16 +14,12 @@ layers = EXTERNAL_BEHIND | EXTERNAL_FRONT color_source = ORGAN_COLOR_OVERRIDE palette = /datum/color_palette/ornithids + palette_key = "tail" + fallback_key = "feather_main" /datum/bodypart_overlay/mutant/tail/avian/get_global_feature_list() return GLOB.tails_list_avian -/datum/bodypart_overlay/mutant/tail/avian/inherit_color(obj/item/bodypart/ownerlimb, force) - var/datum/color_palette/located = ownerlimb?.owner?.dna?.color_palettes[palette] - draw_color = located?.return_color("feather_secondary", "feather_main") || "#FFFFFF" - return TRUE - - /datum/sprite_accessory/tails/avian icon = 'monkestation/code/modules/the_bird_inside_of_me/icons/ornithidfeatures.dmi' diff --git a/monkestation/code/modules/the_bird_inside_of_me/wings.dm b/monkestation/code/modules/the_bird_inside_of_me/wings.dm index 230b3a1c5c04..346abdc10116 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/wings.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/wings.dm @@ -49,6 +49,11 @@ name = "Fluffy" icon_state = "fluffy" +/datum/sprite_accessory/arm_wings/tri_colored + name = "Tri-Colored Wings" + icon_state = "triple" + //layers = list("first" = "feather_main", "second" = "feather_secondary", "third" = "feather_tri") + /datum/sprite_accessory/arm_wings/pursuant name = "Pursuant" icon_state = "pursuant" @@ -69,6 +74,11 @@ name = "Fluffy" icon_state = "fluffy" +/datum/sprite_accessory/arm_wingsopen/tri_colored + name = "Tri-Colored Wings" + icon_state = "triple" + layers = list("first" = "feather_main", "second" = "feather_secondary", "third" = "feather_tri") + /datum/bodypart_overlay/mutant/wings/functional/arm_wings feature_key = "arm_wings" layers = EXTERNAL_BEHIND | EXTERNAL_ADJACENT | EXTERNAL_FRONT @@ -77,11 +87,7 @@ ///Feature render key for opened arm wings open_feature_key = "arm_wingsopen" palette = /datum/color_palette/ornithids - -/datum/bodypart_overlay/mutant/wings/functional/arm_wings/inherit_color(obj/item/bodypart/ownerlimb, force) // overriding inherit_color directly because "override_color" for some unspeakable reason gets passed fuck all - var/datum/color_palette/located = ownerlimb?.owner?.dna?.color_palettes[palette] - draw_color = located?.return_color("feather_main") || "#FFFFFF" - return TRUE + palette_key = "feather_main" /datum/bodypart_overlay/mutant/wings/functional/arm_wings/get_global_feature_list() if(wings_open) diff --git a/monkestation/code/modules/the_fabled_dna_changes/multi_colored_bodyoverlay.dm b/monkestation/code/modules/the_fabled_dna_changes/multi_colored_bodyoverlay.dm new file mode 100644 index 000000000000..e7f0f4ad838d --- /dev/null +++ b/monkestation/code/modules/the_fabled_dna_changes/multi_colored_bodyoverlay.dm @@ -0,0 +1,43 @@ +/datum/bodypart_overlay/mutant/get_overlay(layer, obj/item/bodypart/limb) + inherit_color(limb) + layer = bitflag_to_layer(layer) + if(sprite_datum.layers) + var/mutable_appearance/MA = mutable_appearance(layer = layer) + for(var/state in sprite_datum.layers) + var/mutable_appearance/returned = get_image(layer, limb, state) + color_image(returned, layer, limb, sprite_datum.layers[state]) + MA.overlays += returned + return MA + else + . = get_image(layer, limb) + color_image(., layer, limb) + +///Get the image we need to draw on the person. Called from get_overlay() which is called from _bodyparts.dm. Limb can be null +/datum/bodypart_overlay/mutant/get_image(image_layer, obj/item/bodypart/limb, layer_name) + if(!sprite_datum) + CRASH("Trying to call get_image() on [type] while it didn't have a sprite_datum. This shouldn't happen, report it as soon as possible.") + + var/gender = (limb?.limb_gender == FEMALE) ? "f" : "m" + var/list/icon_state_builder = list() + icon_state_builder += sprite_datum.gender_specific ? gender : "m" //Male is default because sprite accessories are so ancient they predate the concept of not hardcoding gender + if(layer_name) + icon_state_builder += layer_name + icon_state_builder += feature_key + icon_state_builder += get_base_icon_state() + icon_state_builder += mutant_bodyparts_layertext(image_layer) + + var/finished_icon_state = icon_state_builder.Join("_") + + var/mutable_appearance/appearance = mutable_appearance(sprite_datum.icon, finished_icon_state, layer = image_layer) + + if(sprite_datum.center) + center_image(appearance, sprite_datum.dimension_x, sprite_datum.dimension_y) + + return appearance + +/datum/bodypart_overlay/mutant/color_image(image/overlay, layer, obj/item/bodypart/limb, key_name) + if(!key_name) + overlay.color = sprite_datum.color_src ? draw_color : null + else + var/datum/color_palette/located = limb?.owner?.dna?.color_palettes[palette] + overlay.color = located.return_color(key_name, fallback_key) diff --git a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/generic_palette.dm b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/generic_palette.dm index 6bb163e3cdea..45534ff59750 100644 --- a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/generic_palette.dm +++ b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/generic_palette.dm @@ -1,23 +1,11 @@ /datum/color_palette/generic_colors var/hair_color - var/facial_hair_color - - var/hair_gradient_color - var/facial_hair_gradient_color - - //this is temporary until we move everything over to per species coloring var/mutant_color var/mutant_color_secondary var/fur_color /datum/color_palette/generic_colors/apply_prefs(datum/preferences/incoming) hair_color = incoming.read_preference(/datum/preference/color/hair_color) - facial_hair_color = incoming.read_preference(/datum/preference/color/facial_hair_color) - - facial_hair_gradient_color = incoming.read_preference(/datum/preference/color/facial_hair_gradient) - hair_gradient_color = incoming.read_preference(/datum/preference/color/hair_gradient) - mutant_color = incoming.read_preference(/datum/preference/color/mutant_color) mutant_color_secondary = incoming.read_preference(/datum/preference/color/mutant_color_secondary) - fur_color = incoming.read_preference(/datum/preference/color/fur_color) diff --git a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/ornithids.dm b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/ornithids.dm index 08c0dc79c0a8..4399251f874d 100644 --- a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/ornithids.dm +++ b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/ornithids.dm @@ -5,6 +5,13 @@ var/feather_secondary var/feather_tri + var/tail + var/plummage + /datum/color_palette/ornithids/apply_prefs(datum/preferences/incoming) feather_main = incoming.read_preference(/datum/preference/color/feather_color) feather_secondary = incoming.read_preference(/datum/preference/color/feather_color_secondary) + feather_tri = incoming.read_preference(/datum/preferences/color/feather_color_tri) + plummage = incoming.read_preference(/datum/preference/color/plummage_color) + tail = incoming.read_preference(/datum/preference/color/feather_tail_color) + diff --git a/tgstation.dme b/tgstation.dme index 8abd52da8051..af904eb8f9a7 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -7922,6 +7922,7 @@ #include "monkestation\code\modules\the_bird_inside_of_me\tails.dm" #include "monkestation\code\modules\the_bird_inside_of_me\wings.dm" #include "monkestation\code\modules\the_fabled_dna_changes\dna.dm" +#include "monkestation\code\modules\the_fabled_dna_changes\multi_colored_bodyoverlay.dm" #include "monkestation\code\modules\the_fabled_dna_changes\species_color_pallettes\_color_pallette.dm" #include "monkestation\code\modules\the_fabled_dna_changes\species_color_pallettes\generic_palette.dm" #include "monkestation\code\modules\the_fabled_dna_changes\species_color_pallettes\ornithids.dm" diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/MainPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/MainPage.tsx index d888bdf3d313..f15cbd6b51a4 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/MainPage.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/MainPage.tsx @@ -83,8 +83,8 @@ const ChoicedSelection = (props: { name: string; catalog: FeatureChoicedServerData; selected: string; - supplementalFeature?: string; - supplementalValue?: unknown; + supplementalFeatures?: string[]; // Now an array of features + supplementalValues?: unknown[]; // Now an array of values onClose: () => void; onSelect: (value: string) => void; searchText: string; @@ -94,8 +94,8 @@ const ChoicedSelection = (props: { const { catalog, - supplementalFeature, - supplementalValue, + supplementalFeatures = [], + supplementalValues = [], searchText, setSearchText, } = props; @@ -108,10 +108,6 @@ const ChoicedSelection = (props: { return name; }); - const use_small_supplemental = - supplementalFeature && - (features[supplementalFeature].small_supplemental === true || - features[supplementalFeature].small_supplemental === undefined); return ( - {supplementalFeature && use_small_supplemental && ( - - - - )} - + {/* Handle small supplemental features */} + {supplementalFeatures.map((feature, index) => { + const use_small_supplemental = + features[feature]?.small_supplemental ?? true; + return ( + use_small_supplemental && ( + + + + ) + ); + })} - {supplementalFeature && !use_small_supplemental && ( - <> - - - Select {features[supplementalFeature].name} + {/* Handle larger supplemental features */} + {supplementalFeatures.map((feature, index) => { + const use_small_supplemental = + features[feature]?.small_supplemental ?? true; + return ( + !use_small_supplemental && ( + + + + Select {features[feature].name} + + + + + - - - - - - )} + ) + ); + })} @@ -320,7 +329,7 @@ const GenderButton = (props: { const MainFeature = (props: { catalog: FeatureChoicedServerData & { name: string; - supplemental_feature?: string; + supplemental_feature?: string | string[]; // Allow string or array of strings }; currentValue: string; isOpen: boolean; @@ -343,11 +352,24 @@ const MainFeature = (props: { setRandomization, } = props; - const supplementalFeature = catalog.supplemental_feature; + // Normalize supplementalFeature to always be an array + const supplementalFeatures = Array.isArray(catalog.supplemental_feature) + ? catalog.supplemental_feature + : catalog.supplemental_feature + ? [catalog.supplemental_feature] + : []; + + const supplementalValues = supplementalFeatures.map((feature) => + feature + ? data.character_preferences.supplemental_features[feature] + : undefined, + ); + let [searchText, setSearchText] = useLocalState( catalog.name + '_choiced_search', '', ); + const handleCloseInternal = () => { handleClose(); setSearchText(''); @@ -365,13 +387,8 @@ const MainFeature = (props: { name={catalog.name} catalog={catalog} selected={currentValue} - supplementalFeature={supplementalFeature} - supplementalValue={ - supplementalFeature && - data.character_preferences.supplemental_features[ - supplementalFeature - ] - } + supplementalFeatures={supplementalFeatures} // Pass array of features + supplementalValues={supplementalValues} // Pass array of values onClose={handleCloseInternal} onSelect={handleSelect} searchText={searchText} @@ -418,7 +435,6 @@ const MainFeature = (props: { position: 'absolute', right: '1px', }, - onOpen: (event) => { // We're a button inside a button. // Did you know that's against the W3C standard? :) diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/monkestation/ornithids.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/monkestation/ornithids.tsx index 7ab041058601..9dac1222e5c6 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/monkestation/ornithids.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/monkestation/ornithids.tsx @@ -13,7 +13,7 @@ export const feature_arm_wings: FeatureChoiced = { export const feather_color: Feature = { name: 'Feather Color', - small_supplemental: false, + small_supplemental: true, description: "The color of your character's feathers. \ (Armwings, Plumage).", @@ -22,13 +22,39 @@ export const feather_color: Feature = { export const feather_color_secondary: Feature = { name: 'Feather Color Secondary', - small_supplemental: false, + small_supplemental: true, + description: + "The color of your character's feathers. \ + (Armwings, Plumage).", + component: FeatureColorInput, +}; + +export const feather_color_tri: Feature = { + name: 'Feather Color Tri', + small_supplemental: true, description: "The color of your character's feathers. \ (Armwings, Plumage).", component: FeatureColorInput, }; +export const feather_tail_color: Feature = { + name: 'Tail Color', + small_supplemental: false, + description: + "The color of your character's tail feathers. \ + (Armwings, Plumage).", + component: FeatureColorInput, +}; + +export const plummage_color: Feature = { + name: 'Plummage Color', + small_supplemental: false, + description: + "The color of your character's plummage. \ + (Armwings, Plumage).", + component: FeatureColorInput, +}; export const feature_avian_tail: FeatureChoiced = { name: 'Tail', small_supplemental: false, From 538a6599503100dba7f8d15cef39c7bda8467520 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 21 Sep 2024 00:00:31 -0700 Subject: [PATCH 096/158] Update fight_button.dm --- monkestation/code/modules/ghost_players/arena/fight_button.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monkestation/code/modules/ghost_players/arena/fight_button.dm b/monkestation/code/modules/ghost_players/arena/fight_button.dm index cd077bb3063e..357d9173a0c1 100644 --- a/monkestation/code/modules/ghost_players/arena/fight_button.dm +++ b/monkestation/code/modules/ghost_players/arena/fight_button.dm @@ -140,9 +140,9 @@ player_one.client.prefs.adjust_metacoins(player_one.ckey, payout, "Opponent left, reimbursed.") return - var/turf/player_one_spot = locate(148, 34, SSmapping.levels_by_trait(ZTRAIT_CENTCOM)[1]) + var/turf/player_one_spot = locate(138, 131, SSmapping.levels_by_trait(ZTRAIT_CENTCOM)[1]) prep_player(player_one, player_one_spot) - var/turf/player_two_spot = locate(164, 34, SSmapping.levels_by_trait(ZTRAIT_CENTCOM)[1]) + var/turf/player_two_spot = locate(154, 131, SSmapping.levels_by_trait(ZTRAIT_CENTCOM)[1]) prep_player(player_two, player_two_spot) /obj/structure/fight_button/proc/prep_player(mob/living/carbon/human/ghost/player, turf/move_to) From 34d1c30a573d4b42212eef5a52e4e2021302f7c4 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 21 Sep 2024 11:22:38 -0700 Subject: [PATCH 097/158] some more changes --- .../atmospherics/atmos_mob_interaction.dm | 3 ++- code/datums/atmosphere/planetary.dm | 4 ++-- code/modules/mob/living/life.dm | 17 +++++++++++------ .../temperature_overhaul/living_procs.dm | 10 +++++----- .../temperature_overhaul/temperature_proc.dm | 2 -- .../species_color_pallettes/_color_pallette.dm | 1 - .../species_color_pallettes/ornithids.dm | 2 +- 7 files changed, 21 insertions(+), 18 deletions(-) diff --git a/code/__DEFINES/atmospherics/atmos_mob_interaction.dm b/code/__DEFINES/atmospherics/atmos_mob_interaction.dm index 14552ebd1ef1..636eb201d6bf 100644 --- a/code/__DEFINES/atmospherics/atmos_mob_interaction.dm +++ b/code/__DEFINES/atmospherics/atmos_mob_interaction.dm @@ -90,7 +90,8 @@ #define BODYTEMP_COLD_DAMAGE_LIMIT CELCIUS_TO_KELVIN(-0.5 CELCIUS) /// The maximum temperature of Lavaland -#define LAVALAND_MAX_TEMPERATURE 350 +#define LAVALAND_MAX_TEMPERATURE CELCIUS_TO_KELVIN(76.85 CELCIUS)// 350 KELVIN +#define ICEBOX_MIN_TEMPERATURE CELCIUS_TO_KELVIN(-93.15 CELCIUS) /// A temperature limit which is above the maximum lavaland temperature #define BODYTEMP_HEAT_LAVALAND_SAFE (LAVALAND_MAX_TEMPERATURE + 5 KELVIN) diff --git a/code/datums/atmosphere/planetary.dm b/code/datums/atmosphere/planetary.dm index 3fa845b144cd..868658f04226 100644 --- a/code/datums/atmosphere/planetary.dm +++ b/code/datums/atmosphere/planetary.dm @@ -47,8 +47,8 @@ minimum_pressure = HAZARD_LOW_PRESSURE + 10 maximum_pressure = LAVALAND_EQUIPMENT_EFFECT_PRESSURE - 1 - minimum_temp = 180 - maximum_temp = 180 + minimum_temp = ICEBOX_MIN_TEMPERATURE + maximum_temp = ICEBOX_MIN_TEMPERATURE /datum/atmosphere/oshan id = OSHAN_DEFAULT_ATMOS diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index a9314df68dc7..a067831eac12 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -111,21 +111,26 @@ var/temp_delta = loc_temp - bodytemperature if(temp_delta == 0) return - if(temp_delta < 0 && on_fire) // do not reduce body temp when on fire + if(temp_delta < 0 && on_fire) return - // Get the insulation value based on the area's temp var/thermal_protection = get_insulation(loc_temp) var/protection_modifier = 1 if(bodytemperature > standard_body_temperature + 2 KELVIN) - // we are overheating and sweaty - insulation is not as good reducing thermal protection protection_modifier = 0.7 - var/temp_sign = SIGN(temp_delta) - var/temp_change = temp_sign * (1 - (thermal_protection * protection_modifier)) * ((0.1 * max(1, abs(temp_delta))) ** 1.8) * temperature_normalization_speed + // Calculate the equilibrium temperature considering insulation + var/equilibrium_temp = get_insulated_equilibrium_temperature(loc_temp, thermal_protection * protection_modifier) + + var/temp_change = (equilibrium_temp - bodytemperature) * temperature_normalization_speed * seconds_per_tick + // Cap increase and decrease temp_change = temp_change < 0 ? max(temp_change, BODYTEMP_HOMEOSTASIS_COOLING_MAX) : min(temp_change, BODYTEMP_HOMEOSTASIS_HEATING_MAX) - adjust_bodytemperature(temp_change * seconds_per_tick) // no use_insulation beacuse we account for it manually + + adjust_bodytemperature(temp_change * seconds_per_tick) // No use_insulation because we manually account for it + +/mob/living/proc/get_insulated_equilibrium_temperature(environment_temp, insulation) + return environment_temp + (standard_body_temperature - environment_temp) * insulation /mob/living/silicon/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) return // Not yet diff --git a/monkestation/code/modules/temperature_overhaul/living_procs.dm b/monkestation/code/modules/temperature_overhaul/living_procs.dm index a80e47146651..917430838e9a 100644 --- a/monkestation/code/modules/temperature_overhaul/living_procs.dm +++ b/monkestation/code/modules/temperature_overhaul/living_procs.dm @@ -91,9 +91,6 @@ // Body temperature is too cold, and we do not have resist traits if(feels_like < cold_threshold_low && !HAS_TRAIT(src, TRAIT_RESISTCOLD)) clear_mood_event("hot") - // Only apply slowdown if the body is cold rather than the skin - if(bodytemperature < cold_threshold_medium) - add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((BODYTEMP_COLD_WARNING_2 - bodytemperature) / COLD_SLOWDOWN_FACTOR)) if(feels_like < cold_threshold_high) throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3) add_mood_event("cold", /datum/mood_event/freezing) @@ -104,12 +101,15 @@ throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1) add_mood_event("cold", /datum/mood_event/chilly) temp_alerts = TRUE + // Only apply slowdown if the body is cold rather than the skin + if(bodytemperature < cold_threshold_medium && !HAS_TRAIT(src, TRAIT_RESISTCOLD)) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((cold_threshold_medium - bodytemperature) / COLD_SLOWDOWN_FACTOR)) + else if(LAZYACCESS(movespeed_modification, /datum/movespeed_modifier/cold)) + remove_movespeed_modifier(/datum/movespeed_modifier/cold) // We are not to hot or cold, remove status and moods if(temp_alerts && (feels_like < hot_threshold_low || HAS_TRAIT(src, TRAIT_RESISTHEAT)) && (feels_like > cold_threshold_low || HAS_TRAIT(src, TRAIT_RESISTCOLD))) clear_alert(ALERT_TEMPERATURE) - if(bodytemperature > cold_threshold_medium) - remove_movespeed_modifier(/datum/movespeed_modifier/cold) clear_mood_event("cold") clear_mood_event("hot") temp_alerts = FALSE diff --git a/monkestation/code/modules/temperature_overhaul/temperature_proc.dm b/monkestation/code/modules/temperature_overhaul/temperature_proc.dm index fcf14ebea796..87b53b0a0b63 100644 --- a/monkestation/code/modules/temperature_overhaul/temperature_proc.dm +++ b/monkestation/code/modules/temperature_overhaul/temperature_proc.dm @@ -70,8 +70,6 @@ amount *= (1 - get_insulation(bodytemperature + amount)) if(amount == 0) return FALSE - amount = round(amount, 0.01) - if(amount == 0) return 0 amount = round(amount, 0.01) diff --git a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/_color_pallette.dm b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/_color_pallette.dm index b5e294153d09..cf83f9a104b1 100644 --- a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/_color_pallette.dm +++ b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/_color_pallette.dm @@ -20,7 +20,6 @@ retrieved_var = vars[mainvar] if(retrieved_var) return retrieved_var - stack_trace("return_color called with a bad varname.") return default_color return retrieved_var diff --git a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/ornithids.dm b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/ornithids.dm index 4399251f874d..9e7d108562d2 100644 --- a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/ornithids.dm +++ b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/ornithids.dm @@ -11,7 +11,7 @@ /datum/color_palette/ornithids/apply_prefs(datum/preferences/incoming) feather_main = incoming.read_preference(/datum/preference/color/feather_color) feather_secondary = incoming.read_preference(/datum/preference/color/feather_color_secondary) - feather_tri = incoming.read_preference(/datum/preferences/color/feather_color_tri) + feather_tri = incoming.read_preference(/datum/preference/color/feather_color_tri) plummage = incoming.read_preference(/datum/preference/color/plummage_color) tail = incoming.read_preference(/datum/preference/color/feather_tail_color) From eeb9c6fa08cf2e203175e872d6feb6d7bd654210 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 21 Sep 2024 16:16:05 -0700 Subject: [PATCH 098/158] fixes --- code/__HELPERS/mobs.dm | 1 - code/datums/dna.dm | 6 ------ code/modules/antagonists/brother/brother.dm | 3 ++- .../preferences/species_features/ethereal.dm | 2 +- code/modules/mob/living/carbon/human/dummy.dm | 2 +- .../carbon/human/species_types/ethereal.dm | 5 +++-- .../species_parts/ethereal_bodyparts.dm | 12 ++++++------ .../carbon/human/species_type/ethereal.dm | 11 +++++++---- .../organs/external/ethereal_accessories.dm | 6 +++++- .../generic_palette.dm | 2 ++ .../mob/species/ethereal/ethereal_horns.dmi | Bin 1605 -> 1817 bytes 11 files changed, 27 insertions(+), 23 deletions(-) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 812c24f7fcc3..63c04295042f 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -142,7 +142,6 @@ //For now we will always return none for tail_human and ears. | "For now" he says. return(list( - "ethcolor" = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)], "tail_cat" = "None", "tail_lizard" = "Smooth", "wings" = "None", diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 9d2edf904b0d..208909a04ee8 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -198,8 +198,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) . = "" var/list/L = new /list(DNA_FEATURE_BLOCKS) - if(features["ethcolor"]) - L[DNA_ETHEREAL_COLOR_BLOCK] = sanitize_hexcolor(features["ethcolor"], include_crunch = FALSE) if(features["body_markings"]) L[DNA_LIZARD_MARKINGS_BLOCK] = construct_block(GLOB.body_markings_list.Find(features["body_markings"]), GLOB.body_markings_list.len) if(features["tail_cat"]) @@ -338,8 +336,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) if(!ishuman(holder)) CRASH("Non-human mobs shouldn't have DNA") switch(blocknumber) - if(DNA_ETHEREAL_COLOR_BLOCK) - set_uni_feature_block(blocknumber, sanitize_hexcolor(features["ethcolor"], include_crunch = FALSE)) if(DNA_LIZARD_MARKINGS_BLOCK) set_uni_feature_block(blocknumber, construct_block(GLOB.body_markings_list.Find(features["body_markings"]), GLOB.body_markings_list.len)) if(DNA_TAIL_BLOCK) @@ -618,8 +614,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) else hairstyle = GLOB.hairstyles_list[deconstruct_block(get_uni_identity_block(structure, DNA_HAIRSTYLE_BLOCK), GLOB.hairstyles_list.len)] var/features = dna.unique_features - if(dna.features["ethcolor"]) - dna.features["ethcolor"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_ETHEREAL_COLOR_BLOCK)) if(dna.features["body_markings"]) dna.features["body_markings"] = GLOB.body_markings_list[deconstruct_block(get_uni_feature_block(features, DNA_LIZARD_MARKINGS_BLOCK), GLOB.body_markings_list.len)] if(dna.features["snout"]) diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm index 51b6d0ad1c1f..bd8ebf0d8ef7 100644 --- a/code/modules/antagonists/brother/brother.dm +++ b/code/modules/antagonists/brother/brother.dm @@ -111,8 +111,9 @@ /datum/antagonist/brother/get_base_preview_icon() var/mob/living/carbon/human/dummy/consistent/brother1 = new var/mob/living/carbon/human/dummy/consistent/brother2 = new + var/datum/color_palette/generic_colors/located = brother1.dna.color_palettes[/datum/color_palette/generic_colors] - brother1.dna.features["ethcolor"] = GLOB.color_list_ethereal["Faint Red"] + located.ethereal_color = GLOB.color_list_ethereal["Faint Red"] brother1.set_species(/datum/species/ethereal) brother2.dna.features["moth_antennae"] = "Plain" diff --git a/code/modules/client/preferences/species_features/ethereal.dm b/code/modules/client/preferences/species_features/ethereal.dm index 56fe50895894..23db386c8de4 100644 --- a/code/modules/client/preferences/species_features/ethereal.dm +++ b/code/modules/client/preferences/species_features/ethereal.dm @@ -30,4 +30,4 @@ return values /datum/preference/choiced/ethereal_color/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["ethcolor"] = GLOB.color_list_ethereal[value] + return diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index caf1afacd9de..0a49e5957604 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -97,7 +97,6 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) target.dna.initialize_dna(/datum/blood_type/crew/human/o_plus, skip_index = TRUE) target.dna.features["body_markings"] = "None" target.dna.features["ears"] = "None" - target.dna.features["ethcolor"] = COLOR_WHITE target.dna.features["frills"] = "None" target.dna.features["horns"] = "None" target.dna.features["moth_antennae"] = "Plain" @@ -128,6 +127,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) var/datum/color_palette/generic_colors/palette = target.dna.color_palettes[/datum/color_palette/generic_colors] palette.mutant_color = COLOR_VIBRANT_LIME palette.mutant_color_secondary = COLOR_VIBRANT_LIME + palette.ethereal_color = COLOR_WHITE /// Provides a dummy that is consistently bald, white, naked, etc. /mob/living/carbon/human/dummy/consistent diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm index 49ddfc889e2c..4f6ef5a5ff0c 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -274,5 +274,6 @@ /datum/species/ethereal/lustrous/on_species_gain(mob/living/carbon/new_lustrous, datum/species/old_species, pref_load) ..() - default_color = new_lustrous.dna.features["ethcolor"] - new_lustrous.dna.features["ethcolor"] = GLOB.color_list_lustrous[pick(GLOB.color_list_lustrous)] //Picks one of 5 lustrous-specific colors. + var/datum/color_palette/generic_colors/palette = new_lustrous.dna.color_palettes[/datum/color_palette/generic_colors] + default_color = palette.ethereal_color + palette.ethereal_color = GLOB.color_list_lustrous[pick(GLOB.color_list_lustrous)] //Picks one of 5 lustrous-specific colors. diff --git a/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm index a5fcb4d18cfc..9d524cd75c2f 100644 --- a/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm @@ -7,7 +7,7 @@ unarmed_attack_sound = 'sound/weapons/etherealhit.ogg' unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' palette = /datum/color_palette/generic_colors - palette_key = MUTANT_COLOR + palette_key = "ethereal_color" /obj/item/bodypart/head/ethereal/update_limb(dropping_limb, is_creating) . = ..() @@ -23,7 +23,7 @@ is_dimorphic = FALSE dmg_overlay_type = null palette = /datum/color_palette/generic_colors - palette_key = MUTANT_COLOR + palette_key = "ethereal_color" /obj/item/bodypart/chest/ethereal/update_limb(dropping_limb, is_creating) . = ..() @@ -41,7 +41,7 @@ unarmed_attack_sound = 'sound/weapons/etherealhit.ogg' unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' palette = /datum/color_palette/generic_colors - palette_key = MUTANT_COLOR + palette_key = "ethereal_color" /obj/item/bodypart/arm/left/ethereal/update_limb(dropping_limb, is_creating) . = ..() @@ -59,7 +59,7 @@ unarmed_attack_sound = 'sound/weapons/etherealhit.ogg' unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' palette = /datum/color_palette/generic_colors - palette_key = MUTANT_COLOR + palette_key = "ethereal_color" /obj/item/bodypart/arm/right/ethereal/update_limb(dropping_limb, is_creating) . = ..() @@ -77,7 +77,7 @@ unarmed_attack_sound = 'sound/weapons/etherealhit.ogg' unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' palette = /datum/color_palette/generic_colors - palette_key = MUTANT_COLOR + palette_key = "ethereal_color" /obj/item/bodypart/leg/left/ethereal/update_limb(dropping_limb, is_creating) . = ..() @@ -94,7 +94,7 @@ unarmed_attack_sound = 'sound/weapons/etherealhit.ogg' unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' palette = /datum/color_palette/generic_colors - palette_key = MUTANT_COLOR + palette_key = "ethereal_color" /obj/item/bodypart/leg/right/ethereal/update_limb(dropping_limb, is_creating) . = ..() diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm index feb8ca05560e..2ede8b8cac04 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm @@ -68,7 +68,8 @@ if(!ishuman(new_ethereal)) return var/mob/living/carbon/human/ethereal = new_ethereal - default_color = ethereal.dna.features["ethcolor"] + var/datum/color_palette/generic_colors/palette = ethereal.dna.color_palettes[/datum/color_palette/generic_colors] + default_color = palette.ethereal_color r1 = GETREDPART(default_color) g1 = GETGREENPART(default_color) b1 = GETBLUEPART(default_color) @@ -104,14 +105,16 @@ return randname /datum/species/ethereal/randomize_features(mob/living/carbon/human/human_mob) - human_mob.dna.features["ethcolor"] = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)] + var/datum/color_palette/generic_colors/palette = human_mob.dna.color_palettes[/datum/color_palette/generic_colors] + palette.ethereal_color = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)] /datum/species/ethereal/spec_updatehealth(mob/living/carbon/human/ethereal) . = ..() + var/datum/color_palette/generic_colors/palette = ethereal.dna.color_palettes[/datum/color_palette/generic_colors] if(!ethereal_light) return - if(default_color != ethereal.dna.features["ethcolor"]) - var/new_color = ethereal.dna.features["ethcolor"] + if(default_color != palette.ethereal_color) + var/new_color = palette.ethereal_color r1 = GETREDPART(new_color) g1 = GETGREENPART(new_color) b1 = GETBLUEPART(new_color) diff --git a/monkestation/code/modules/surgery/organs/external/ethereal_accessories.dm b/monkestation/code/modules/surgery/organs/external/ethereal_accessories.dm index b9d4a7fbe8bd..f645ed3ed76f 100644 --- a/monkestation/code/modules/surgery/organs/external/ethereal_accessories.dm +++ b/monkestation/code/modules/surgery/organs/external/ethereal_accessories.dm @@ -12,8 +12,10 @@ bodypart_overlay = /datum/bodypart_overlay/mutant/ethereal_horns /datum/bodypart_overlay/mutant/ethereal_horns - layers = EXTERNAL_FRONT|EXTERNAL_BEHIND + layers = EXTERNAL_FRONT|EXTERNAL_ADJACENT feature_key = "ethereal_horns" + palette = /datum/color_palette/generic_colors + palette_key = "ethereal_color" /datum/bodypart_overlay/mutant/ethereal_horns/get_global_feature_list() return GLOB.ethereal_horns_list @@ -38,6 +40,8 @@ /datum/bodypart_overlay/mutant/tail/ethereal layers = EXTERNAL_FRONT|EXTERNAL_BEHIND feature_key = "ethereal_tail" + palette = /datum/color_palette/generic_colors + palette_key = "ethereal_color" /datum/bodypart_overlay/mutant/tail/ethereal/get_global_feature_list() return GLOB.ethereal_tail_list diff --git a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/generic_palette.dm b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/generic_palette.dm index 45534ff59750..eb948ad9fbc4 100644 --- a/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/generic_palette.dm +++ b/monkestation/code/modules/the_fabled_dna_changes/species_color_pallettes/generic_palette.dm @@ -3,9 +3,11 @@ var/mutant_color var/mutant_color_secondary var/fur_color + var/ethereal_color /datum/color_palette/generic_colors/apply_prefs(datum/preferences/incoming) hair_color = incoming.read_preference(/datum/preference/color/hair_color) mutant_color = incoming.read_preference(/datum/preference/color/mutant_color) mutant_color_secondary = incoming.read_preference(/datum/preference/color/mutant_color_secondary) fur_color = incoming.read_preference(/datum/preference/color/fur_color) + ethereal_color = GLOB.color_list_ethereal[incoming.read_preference(/datum/preference/choiced/ethereal_color)] diff --git a/monkestation/icons/mob/species/ethereal/ethereal_horns.dmi b/monkestation/icons/mob/species/ethereal/ethereal_horns.dmi index 8ab6b4e39f59b1b1a7b306ec245a407573ed0b5f..1016275aa9b51307d2310d6e1ae41a2ac60c057e 100644 GIT binary patch delta 1798 zcmY*ZX;>177R6U-&RCAysGqr%jnm@N;<%8ernxKRZst-hS-6ZFiVHASZloz{T0*EV zC6@s+36$Khrc@FgR}h}KXWrNSbMHC#&pqef?|zVZc06C%RO|2|003a@ zNbWjF@?d9=>m3~(ZM`GuITd2D*v&Qa0A|p-Y7V**@oui}0L$62umjLt09Hf{y8KAf zQt4QG1OI`^9~iH2%Di*_=O(QdR1@BC=ora%qOF-lnm4VP$7!ZlM_{8-=+K??s~s>; zzqcXl1Epv$Pb(;jStKvLc+Q&b3)ZwjMm<+KZk2whqPZTs$xgK9)bddhOns>MLp_zy`s2qZu|%DNiGOgluP+T7Ieb=z5PzT=O949 zvVPpusz~T;^Y$H%HqmcWbqcIZF zEr5GQ$Ud_8HxAOX4`ewGu}GO~WBA~OutMvj&}svzT!{k*Iv9w-KH?*jcDNi~Ncstp zf{eXB(HAY-UmV_&D;R(Mi&py$ql(sjw*8tY&cORP-fP=G?M#~NaxzocId)r)LNF%$ z8j2gvYhc>>Zb$Bc;VvNxJ&n1{O!tS0Ns0HYuN^H4r0W@Q4iL>SjXP%D-kMi6 zx#2WctYqGHCCjBpO zi|otv(ur9A@}2D-E|lL(ZZ@?V^%1aqpI6^jtwkS@3g< z-p^_2`YOGLbn85x#ak1Dk|FT{>JFbVxEaVwj*g3Kx!O|?GD7G5Whb&ZpHq%jT4{wO zGqZV-9s$AS-SvefW2tPq-WBmIP!K=K)(MNmQXO07S`%G}z_r@3tZ5Po$3x?YK=D1c zG0Zidbkaa0+yusN6NM!V4sF(!^!we2;=}p;@Z*C64^PZpIqAqSoKu!v(|3g1)1#KD zTyNbCB}D6z&ZZZTwvR(h z?#i&ptYKUilLWS6_3Zz-SL3d{F!C|SR@hl7W1;fh5&!@s(90*0k0Mv?n&eWPu1iK# z6W6Q0pklQ3c=*GV&o2c;#NwODycT7~Q8M$*_&E&7fl?;eK^gCjT%vvvE#vjdv;?>( zVIMO}wiXF=(8>^VQv@5{qiApqfup<>`O^KMBuQboOr+8JwsLgwq||rc6 zjo`WUDuWj&hgQJ}3vx@XM9oT+eWjBzU&+@#hD}O3S&**<=)KGM#Bq+vslxgF!3&gE k=xVf!;1MyB|CeMirzs(opMjp~ANfW)Tz9o0TnkG72e6NfGXMYp delta 1584 zcmYLJdpOez7@kWxsUwLe6w~E2JIzohnM*0R#O5-j5+g)nWG-|2NkjhxN_sZ^Sr_OA;jWQ``HcKNSOWe6@9EW~2sO~4xIBRi=A{pgL&I_iyc zq7~IjKE2j58_9Gt^;70s4`DSwUp-C7gTq7Blc)#n1<>Xz8hlkYrDw&70yAb@upcC# zawzxQ+%ow-hOq1Mk<^_dkFIUrWl@X%Jyoaa@+;4Q?%2@ajq!0Nl@TW>Cs0s1if6uo z^5SD}LGhbxg!IS)Uj?X`S3VcCVF)+Q;WmHsNonb@%qY4UlJc-(;eP9To8hL^ZSK$r z1kh6&1d%KmwmGuGeoyQ@x02r-*fhUt8Y9=lMWYqJG?zml>tyY$j=IL=3HUO!LSyCi zqpIUF$7dm#91B@(3uuD$fSv&_>QBS#8JMY=6>uubX3srH2mp#;&hRxeAdnIR0RxQY z#yb5)U?6vs@?IA&e#b0kP0`70a@&Qffw_mBx?zLce{BCqNl(#iNj)=h86HS~xg<`- zQaSE8s21+Rs)t_fG9Z#Ae&XCxyL5V#G+|OjV5INc@!{jBwd*u~dZf&Mux*$D0&zM1 zeCC(^+9cQ$94B6W(SvvI;HmtwB(~jL)oxI0K!-M!yX<1DGEJz)+gYZ?||;T?wVcikdk}@lvTYeB_z^WJ5W#ZV$uw zFsJYz1O_R_dG7qBTk1T+Z?g~}GJ9P+(j7lh+fZp770wD=%K3X(V>__->0Zl0J>@@0 zaS6yMouMP1ccHo?-kK#-jObRQL{HI!H=CS!vuY5w6n-@Hj@a~F|+DSAhsiev^^C! zQWuy(g4ujV2@f|+<)~$_ST?f1r0hctez3g zx~cDp=Tcuyy+42mk?P>b!-n4Sj@CP%(oSZtFIuH8kWR~e0%lb!YkJ`PYz3G==BI{H z2Dj9hKGvK+F0l-cbcri&ueVINvK(L<+JDE+Mp)5ZaJ*95 zBAmSfYa!=uE_{BSH*FVM>zDTJeivC#=PebtlZc@WzRskG(#|_$tHE&+YzOv2VTipY zkm&WITbHs9X$xO=D_sBu2PIq6&X7Tj9mn>ydi0i-5Jy|>O8%ilv4dPnbyRySrj^mAx! z_q)S*;8oPS;46s%dZ)9})h&*qpj7lVmYE)tF~>fr0nz&r;m z9UFhESGXB@Lu!uT3U9xNajn)D>@~b+nnPM~{MhvK%J%|act^ Date: Sat, 21 Sep 2024 17:11:54 -0700 Subject: [PATCH 099/158] fixes --- code/datums/components/butchering.dm | 2 +- code/modules/mob/living/carbon/death.dm | 30 +++++++++---------- code/modules/surgery/bodyparts/_bodyparts.dm | 3 ++ .../blood_for_the_blood_gods/particle.dm | 2 +- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm index 55e14ac851d3..08864d934cb9 100644 --- a/code/datums/components/butchering.dm +++ b/code/datums/components/butchering.dm @@ -150,7 +150,7 @@ butcher_callback?.Invoke(butcher, meat) meat.harvest(butcher) meat.log_message("has been butchered by [key_name(butcher)]", LOG_ATTACK) - meat.gib(FALSE, FALSE, TRUE) + meat.gib(FALSE, FALSE, FALSE, TRUE) ///Enables the butchering mechanic for the mob who has equipped us. /datum/component/butchering/proc/enable_butchering(datum/source) diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 3377f373c3ad..e192ff2d4046 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -45,27 +45,27 @@ if(no_brain || !istype(organ, /obj/item/organ/internal/brain)) qdel(organ) else //we're going to drop all bodyparts except chest, so the only organs that needs spilling are those inside it. - for(var/obj/item/organ/organs as anything in organs) - if(no_brain && istype(organs, /obj/item/organ/internal/brain)) - qdel(organs) //so the brain isn't transfered to the head when the head drops. + for(var/obj/item/organ/organ as anything in organs) + if(no_brain && istype(organ, /obj/item/organ/internal/brain)) + qdel(organ) //so the brain isn't transfered to the head when the head drops. continue - var/org_zone = check_zone(organs.zone) //both groin and chest organs. + var/org_zone = check_zone(organ.zone) //both groin and chest organs. if(org_zone != BODY_ZONE_CHEST) continue - organs.Remove(src) - organs.forceMove(Tsec) - organs.fly_away(Tsec, horizontal_multiplier = 2, vertical_multiplier = 1.2) + organs.Remove(organ) + organ.forceMove(Tsec) + organ.fly_away(Tsec, horizontal_multiplier = 2, vertical_multiplier = 1.2) else - for(var/obj/item/organ/organs as anything in organs) - if(no_brain && istype(organs, /obj/item/organ/internal/brain)) - qdel(organs) + for(var/obj/item/organ/organ as anything in organs) + if(no_brain && istype(organ, /obj/item/organ/internal/brain)) + qdel(organ) continue - if(no_organs && !istype(organs, /obj/item/organ/internal/brain)) - qdel(organs) + if(no_organs && !istype(organ, /obj/item/organ/internal/brain)) + qdel(organ) continue - organs.Remove(src) - organs.forceMove(Tsec) - organs.fly_away(Tsec, horizontal_multiplier = 2, vertical_multiplier = 1.2) + organs.Remove(organ) + organ.forceMove(Tsec) + organ.fly_away(Tsec, horizontal_multiplier = 2, vertical_multiplier = 1.2) /// Launches all bodyparts away from the mob. skip_head will keep the head attached. /mob/living/carbon/spread_bodyparts(skip_head = FALSE, skip_organ = FALSE, violent = FALSE) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index b59a030b5eb7..2a67164dc70f 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -401,6 +401,9 @@ pixel_x = rand(-3, 3) pixel_y = rand(-3, 3) +/obj/item/bodypart/drop_location() + return ..() || owner?.drop_location() + //empties the bodypart from its organs and other things inside it /obj/item/bodypart/proc/drop_organs(mob/user, violent_removal) SHOULD_CALL_PARENT(TRUE) diff --git a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm index 95a8d6696fc0..a20f12b5c38c 100644 --- a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm @@ -65,7 +65,7 @@ stacker.bloodiness = src.bloodiness stacker.update_appearance(UPDATE_ICON) else - var/obj/effect/decal/cleanable/blood/splatter/stacking/other_splatter = new splatter_type_floor(blood_color = color) + var/obj/effect/decal/cleanable/blood/splatter/stacking/other_splatter = new splatter_type_floor() other_splatter.color = color if(messy_splatter && length(other_splatter.splat_overlays)) var/mutable_appearance/existing_appearance = other_splatter.splat_overlays[1] From 31715717d3aff2740be45ddfba73957a01afcdf7 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 09:10:11 -0700 Subject: [PATCH 100/158] hunger changes --- code/__DEFINES/mobs.dm | 4 ++-- code/modules/surgery/organs/stomach/stomach_ethereal.dm | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index d52fac25fd81..276a14c053bd 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -454,9 +454,9 @@ // These add up to 1 to roughly (VERY roughly) represent the proportion of hunger used by each system /// What % of hunger is used by homeostasis -#define HOMEOSTASIS_HUNGER_MULTIPLIER 0.7 +#define HOMEOSTASIS_HUNGER_MULTIPLIER 0.1 /// What % of hunger is used by passive hunger -#define PASSIVE_HUNGER_MULTIPLIER 0.2 +#define PASSIVE_HUNGER_MULTIPLIER 0.7 /// What % of hunger is used by movement #define MOVEMENT_HUNGER_MULTIPLIER 0.1 diff --git a/code/modules/surgery/organs/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/stomach/stomach_ethereal.dm index b70d476949fa..46c9abd7236d 100644 --- a/code/modules/surgery/organs/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/stomach/stomach_ethereal.dm @@ -39,7 +39,7 @@ /obj/item/organ/internal/stomach/ethereal/proc/handle_temp(mob/living/carbon/human/human, natural_change, seconds_per_tick) SIGNAL_HANDLER - adjust_charge(-1 * ETHEREAL_CHARGE_FACTOR * abs(natural_change) * seconds_per_tick * 0.05) + adjust_charge(-0.5 * ETHEREAL_CHARGE_FACTOR * abs(natural_change) * seconds_per_tick * 0.01) return HOMEOSTASIS_NO_HUNGER /obj/item/organ/internal/stomach/ethereal/proc/blood(mob/living/carbon/human/ethereal, seconds_per_tick, times_fired) From a0848aa68d65433ac1fc0b7cc6efd0a9d8fd9b7a Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 12:38:56 -0700 Subject: [PATCH 101/158] should work? --- code/__DEFINES/subsystems.dm | 1 + code/__HELPERS/roundend.dm | 14 +- code/_onclick/hud/credits.dm | 76 ---- code/controllers/subsystem/blackbox.dm | 2 +- code/controllers/subsystem/ticker.dm | 2 + code/game/objects/items/melee/baton.dm | 2 +- .../mob/living/carbon/human/_species.dm | 18 +- .../mob/living/carbon/human/human_helpers.dm | 7 +- .../carbon/human/species_types/abductors.dm | 1 - .../carbon/human/species_types/android.dm | 1 - .../carbon/human/species_types/podpeople.dm | 1 - .../carbon/human/species_types/skeletons.dm | 1 - .../carbon/human/species_types/zombies.dm | 2 - code/modules/mob/living/living_say.dm | 2 +- .../computers/item/computer_ui.dm | 2 +- code/modules/surgery/bodyparts/_arms.dm | 181 +++++++++ code/modules/surgery/bodyparts/parts.dm | 167 -------- .../bodyparts/species_parts/android_parts.dm | 1 + .../species_parts/lizard_bodyparts.dm | 4 +- .../bodyparts/species_parts/misc_bodyparts.dm | 16 +- config/admins.txt | 146 +------ config/contributors.dmi | Bin 0 -> 184 bytes .../code/modules/and_roll_credits/_credits.dm | 174 +++++++++ .../and_roll_credits/credits_subsystem.dm | 226 +++++++++++ .../modules/and_roll_credits/episode_names.dm | 363 ++++++++++++++++++ .../and_roll_credits/icons/title_cards.dmi | Bin 0 -> 495711 bytes .../modules/blueshift/species/ashwalker.dm | 2 + .../carbon/human/species_type/floran.dm | 2 - .../smithing/ipcs/body/base_bodyparts.dm | 2 +- .../code/modules/smithing/ipcs/species.dm | 1 - .../converted_events/_base_event.dm | 10 +- .../converted_events/solo/bloodcult.dm | 1 + .../converted_events/solo/bloodsuckers.dm | 1 + .../converted_events/solo/changeling.dm | 1 + .../converted_events/solo/clockwork_cult.dm | 1 + .../converted_events/solo/clown_operative.dm | 1 + .../solo/nuclear_operative.dm | 1 + .../converted_events/solo/revolutionary.dm | 1 + .../converted_events/solo/traitor.dm | 1 + .../converted_events/solo/wizard.dm | 1 + .../code/modules/storytellers/readme.md | 1 + .../surgery/bodyparts/floran_bodyparts.dm | 3 + .../the_wolf_inside_of_me/bodyparts.dm | 4 +- tgstation.dme | 5 +- 44 files changed, 1022 insertions(+), 427 deletions(-) delete mode 100644 code/_onclick/hud/credits.dm create mode 100644 code/modules/surgery/bodyparts/_arms.dm create mode 100644 config/contributors.dmi create mode 100644 monkestation/code/modules/and_roll_credits/_credits.dm create mode 100644 monkestation/code/modules/and_roll_credits/credits_subsystem.dm create mode 100644 monkestation/code/modules/and_roll_credits/episode_names.dm create mode 100644 monkestation/code/modules/and_roll_credits/icons/title_cards.dmi diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 050327895b4a..53398823936b 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -187,6 +187,7 @@ #define INIT_ORDER_MINOR_MAPPING -40 #define INIT_ORDER_PATH -50 #define INIT_ORDER_EXPLOSIONS -69 +#define INIT_ORDER_CREDITS -93 #define INIT_ORDER_REPLAYS -94 #define INIT_ORDER_HOTSPOTS -95 ///only called on oshan so just call it near the end. #define INIT_ORDER_TWITCH -96 diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 2b82cbc7383d..9f1d4476fabd 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -1,6 +1,7 @@ #define POPCOUNT_SURVIVORS "survivors" //Not dead at roundend #define POPCOUNT_ESCAPEES "escapees" //Not dead and on centcom/shuttles marked as escaped #define POPCOUNT_SHUTTLE_ESCAPEES "shuttle_escapees" //Emergency shuttle only. +#define POPCOUNT_ESCAPEES_HUMANONLY "human_escapees" #define PERSONAL_LAST_ROUND "personal last round" #define SERVER_LAST_ROUND "server last round" #define DISCORD_SUPPRESS_NOTIFICATIONS (1 << 12) // monke edit: discord flag for silent messages @@ -17,7 +18,10 @@ GLOBAL_LIST_INIT(round_end_images, world.file2list("data/image_urls.txt")) // MO var/list/file_data = list("escapees" = list("humans" = list(), "silicons" = list(), "others" = list(), "npcs" = list()), "abandoned" = list("humans" = list(), "silicons" = list(), "others" = list(), "npcs" = list()), "ghosts" = list(), "additional data" = list()) var/num_survivors = 0 //Count of non-brain non-camera mobs with mind that are alive var/num_escapees = 0 //Above and on centcom z + var/num_human_escapees = 0 //Above but humans only var/num_shuttle_escapees = 0 //Above and on escape shuttle + var/list/list_of_human_escapees = list() //References to all escaped humans + var/list/list_of_mobs_on_shuttle = list() var/list/area/shuttle_areas if(SSshuttle?.emergency) shuttle_areas = SSshuttle.emergency.shuttle_areas @@ -35,6 +39,8 @@ GLOBAL_LIST_INIT(round_end_images, world.file2list("data/image_urls.txt")) // MO if(M.mind) count_only = FALSE mob_data["ckey"] = M.mind.key + if(M.onCentCom()) + list_of_mobs_on_shuttle += M if(M.stat != DEAD && !isbrain(M) && !iscameramob(M)) num_survivors++ if(EMERGENCY_ESCAPED_OR_ENDGAMED && (M.onCentCom() || M.onSyndieBase())) @@ -42,6 +48,9 @@ GLOBAL_LIST_INIT(round_end_images, world.file2list("data/image_urls.txt")) // MO escape_status = "escapees" if(shuttle_areas[get_area(M)]) num_shuttle_escapees++ + if(ishuman(M)) + num_human_escapees++ + list_of_human_escapees += M if(isliving(M)) var/mob/living/L = M mob_data["location"] = get_area(L) @@ -105,7 +114,10 @@ GLOBAL_LIST_INIT(round_end_images, world.file2list("data/image_urls.txt")) // MO . = list() .[POPCOUNT_SURVIVORS] = num_survivors .[POPCOUNT_ESCAPEES] = num_escapees + .[POPCOUNT_ESCAPEES_HUMANONLY] = num_human_escapees .[POPCOUNT_SHUTTLE_ESCAPEES] = num_shuttle_escapees + .["all_mobs_on_shuttle"] = list_of_mobs_on_shuttle + .["human_escapees_list"] = list_of_human_escapees .["station_integrity"] = station_integrity /datum/controller/subsystem/ticker/proc/gather_antag_data() @@ -221,7 +233,7 @@ GLOBAL_LIST_INIT(round_end_images, world.file2list("data/image_urls.txt")) // MO C?.give_award(/datum/award/achievement/misc/speed_round, C?.mob) HandleRandomHardcoreScore(C) - var/popcount = gather_roundend_feedback() + popcount = gather_roundend_feedback() display_report(popcount) CHECK_TICK diff --git a/code/_onclick/hud/credits.dm b/code/_onclick/hud/credits.dm deleted file mode 100644 index e39e1ef36d07..000000000000 --- a/code/_onclick/hud/credits.dm +++ /dev/null @@ -1,76 +0,0 @@ -#define CREDIT_ROLL_SPEED 125 -#define CREDIT_SPAWN_SPEED 10 -#define CREDIT_ANIMATE_HEIGHT (14 * world.icon_size) -#define CREDIT_EASE_DURATION 22 -#define CREDITS_PATH "[global.config.directory]/contributors.dmi" - -/client/proc/RollCredits() - set waitfor = FALSE - if(!fexists(CREDITS_PATH)) - return - var/icon/credits_icon = new(CREDITS_PATH) - LAZYINITLIST(credits) - var/list/_credits = credits - add_verb(src, /client/proc/ClearCredits) - var/static/list/credit_order_for_this_round - if(isnull(credit_order_for_this_round)) - credit_order_for_this_round = list("Thanks for playing!") + (shuffle(icon_states(credits_icon)) - "Thanks for playing!") - for(var/I in credit_order_for_this_round) - if(!credits) - return - _credits += new /atom/movable/screen/credit(null, I, src, credits_icon) - sleep(CREDIT_SPAWN_SPEED) - sleep(CREDIT_ROLL_SPEED - CREDIT_SPAWN_SPEED) - remove_verb(src, /client/proc/ClearCredits) - qdel(credits_icon) - -/client/proc/ClearCredits() - set name = "Hide Credits" - set category = "OOC" - remove_verb(src, /client/proc/ClearCredits) - QDEL_LIST(credits) - credits = null - -/atom/movable/screen/credit - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - alpha = 0 - screen_loc = "12,1" - plane = SPLASHSCREEN_PLANE - var/client/parent - var/matrix/target - -/atom/movable/screen/credit/Initialize(mapload, credited, client/P, icon/I) - . = ..() - icon = I - parent = P - icon_state = credited - maptext = MAPTEXT_PIXELLARI(credited) - maptext_x = world.icon_size + 8 - maptext_y = (world.icon_size / 2) - 4 - maptext_width = world.icon_size * 3 - var/matrix/M = matrix(transform) - M.Translate(0, CREDIT_ANIMATE_HEIGHT) - animate(src, transform = M, time = CREDIT_ROLL_SPEED) - target = M - animate(src, alpha = 255, time = CREDIT_EASE_DURATION, flags = ANIMATION_PARALLEL) - addtimer(CALLBACK(src, PROC_REF(FadeOut)), CREDIT_ROLL_SPEED - CREDIT_EASE_DURATION) - QDEL_IN(src, CREDIT_ROLL_SPEED) - if(parent) - parent.screen += src - -/atom/movable/screen/credit/Destroy() - icon = null - if(parent) - parent.screen -= src - LAZYREMOVE(parent.credits, src) - parent = null - return ..() - -/atom/movable/screen/credit/proc/FadeOut() - animate(src, alpha = 0, transform = target, time = CREDIT_EASE_DURATION) - -#undef CREDIT_ANIMATE_HEIGHT -#undef CREDIT_EASE_DURATION -#undef CREDIT_ROLL_SPEED -#undef CREDIT_SPAWN_SPEED -#undef CREDITS_PATH diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index 21bab011b399..1b77a8555554 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -4,7 +4,7 @@ SUBSYSTEM_DEF(blackbox) runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME init_order = INIT_ORDER_BLACKBOX - var/list/feedback_list = list() //list of datum/feedback_variable + var/list/datum/feedback_variable/feedback_list = list() //list of datum/feedback_variable var/list/first_death = list() //the first death of this round, assoc. vars keep track of different things var/triggertime = 0 var/sealed = FALSE //time to stop tracking stats? diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 4c19a9231c71..e298d4a632f1 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -74,6 +74,8 @@ SUBSYSTEM_DEF(ticker) ///add jobs to this that should get rewarded monkecoins, example: JOB_SECURITY_OFFICER var/list/jobs_to_reward = list(JOB_JANITOR,) + var/list/popcount + /datum/controller/subsystem/ticker/Initialize() // monkestation start: fix-lobby-music var/old_login_music = trim(file2text("data/last_round_lobby_music.txt")) diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/melee/baton.dm index d06b0067de24..e17e1af4fc55 100644 --- a/code/game/objects/items/melee/baton.dm +++ b/code/game/objects/items/melee/baton.dm @@ -136,7 +136,7 @@ if(!chunky_finger_usable && ishuman(user)) var/mob/living/carbon/human/potential_chunky_finger_human = user - if(potential_chunky_finger_human.check_chunky_fingers() && user.is_holding(src) && !HAS_MIND_TRAIT(user, TRAIT_CHUNKYFINGERS_IGNORE_BATON)) + if(user.is_holding(src) && HAS_TRAIT(potential_chunky_finger_human, TRAIT_CHUNKYFINGERS) && !HAS_MIND_TRAIT(user, TRAIT_CHUNKYFINGERS_IGNORE_BATON)) balloon_alert(potential_chunky_finger_human, "fingers are too big!") return BATON_ATTACK_DONE diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index fec90fc2ebae..9636528fb015 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -1794,14 +1794,20 @@ GLOBAL_LIST_EMPTY(features_by_species) return to_add /** - * Adds adds any perks related to the species' inherent_traits list. + * Adds adds any perks related to the species' inherent_traits list or override body traits. * * Returns a list containing perks, or an empty list. */ /datum/species/proc/create_pref_traits_perks() var/list/to_add = list() - - if(TRAIT_LIMBATTACHMENT in inherent_traits) + var/list/trait_list = list() + trait_list |= inherent_traits.Copy() + for(var/type in bodypart_overrides) + var/obj/item/bodypart/bodypart = bodypart_overrides[type] + var/obj/item/bodypart/new_bodypart = new bodypart + trait_list |= new_bodypart.bodypart_traits.Copy() + + if(TRAIT_LIMBATTACHMENT in trait_list) to_add += list(list( SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, SPECIES_PERK_ICON = "user-plus", @@ -1810,7 +1816,7 @@ GLOBAL_LIST_EMPTY(features_by_species) require surgery to restore. Simply pick it up and pop it back in, champ!", )) - if(TRAIT_EASYDISMEMBER in inherent_traits) + if(TRAIT_EASYDISMEMBER in trait_list) to_add += list(list( SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, SPECIES_PERK_ICON = "user-times", @@ -1818,7 +1824,7 @@ GLOBAL_LIST_EMPTY(features_by_species) SPECIES_PERK_DESC = "[plural_form] limbs are not secured well, and as such they are easily dismembered.", )) - if(TRAIT_EASILY_WOUNDED in inherent_traits) + if(TRAIT_EASILY_WOUNDED in trait_list) to_add += list(list( SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, SPECIES_PERK_ICON = "user-times", @@ -1826,7 +1832,7 @@ GLOBAL_LIST_EMPTY(features_by_species) SPECIES_PERK_DESC = "[plural_form] skin is very weak and fragile. They are much easier to apply serious wounds to.", )) - if(TRAIT_TOXINLOVER in inherent_traits) + if(TRAIT_TOXINLOVER in trait_list) to_add += list(list( SPECIES_PERK_TYPE = SPECIES_NEUTRAL_PERK, SPECIES_PERK_ICON = "syringe", diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index a83190417216..df3f8a716b7e 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -113,18 +113,13 @@ /mob/living/carbon/human/can_use_guns(obj/item/G) . = ..() if(G.trigger_guard == TRIGGER_GUARD_NORMAL) - if(check_chunky_fingers()) + if(HAS_TRAIT(src, TRAIT_CHUNKYFINGERS)) balloon_alert(src, "fingers are too big!") return FALSE if(HAS_TRAIT(src, TRAIT_NOGUNS)) to_chat(src, span_warning("You can't bring yourself to use a ranged weapon!")) return FALSE -/mob/living/carbon/human/proc/check_chunky_fingers() - if(HAS_TRAIT_NOT_FROM(src, TRAIT_CHUNKYFINGERS, RIGHT_ARM_TRAIT) && HAS_TRAIT_NOT_FROM(src, TRAIT_CHUNKYFINGERS, LEFT_ARM_TRAIT)) - return TRUE - return (active_hand_index % 2) ? HAS_TRAIT_FROM(src, TRAIT_CHUNKYFINGERS, LEFT_ARM_TRAIT) : HAS_TRAIT_FROM(src, TRAIT_CHUNKYFINGERS, RIGHT_ARM_TRAIT) - /mob/living/carbon/human/get_policy_keywords() . = ..() . += "[dna.species.type]" diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm index 6aded5feab48..910e75df43da 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -10,7 +10,6 @@ TRAIT_NOBLOOD, TRAIT_NODISMEMBER, TRAIT_NEVER_WOUNDED, - TRAIT_CHUNKYFINGERS_IGNORE_BATON, ) mutanttongue = /obj/item/organ/internal/tongue/abductor mutantstomach = null diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm index 08ebb8f2ff68..4bf6ff9151ce 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -7,7 +7,6 @@ TRAIT_NO_TRANSFORMATION_STING, TRAIT_NO_HUSK, TRAIT_GENELESS, - TRAIT_LIMBATTACHMENT, TRAIT_NOBREATH, TRAIT_NOCLONELOSS, TRAIT_NOFIRE, diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index 1374f9abce24..1980497b6c68 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -5,7 +5,6 @@ id = SPECIES_PODPERSON inherent_traits = list( TRAIT_MUTANT_COLORS, - TRAIT_PLANT_SAFE, ) external_organs = list( /obj/item/organ/external/pod_hair = "None", diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm index c7c1e2dc67c8..50b94040c814 100644 --- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm +++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm @@ -12,7 +12,6 @@ TRAIT_EASYDISMEMBER, TRAIT_FAKEDEATH, TRAIT_GENELESS, - TRAIT_LIMBATTACHMENT, TRAIT_NOBREATH, TRAIT_NOCLONELOSS, TRAIT_LIVERLESS_METABOLISM, diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index 29147e95e4a2..9eb4b66f0af1 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -14,7 +14,6 @@ TRAIT_EASILY_WOUNDED, TRAIT_EASYDISMEMBER, TRAIT_FAKEDEATH, - TRAIT_LIMBATTACHMENT, TRAIT_NOBREATH, TRAIT_NOCLONELOSS, TRAIT_NODEATH, @@ -93,7 +92,6 @@ TRAIT_EASILY_WOUNDED, TRAIT_EASYDISMEMBER, TRAIT_FAKEDEATH, - TRAIT_LIMBATTACHMENT, TRAIT_NOBREATH, TRAIT_NOCLONELOSS, TRAIT_NODEATH, diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index 765e124d4e1f..7025795385d9 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -267,7 +267,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( if(succumbed) succumb(TRUE) to_chat(src, compose_message(src, language, message, , spans, message_mods)) - + talkcount++ return TRUE /mob/living/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range=0) diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm index 5135c430130a..4146588d7d93 100644 --- a/code/modules/modular_computers/computers/item/computer_ui.dm +++ b/code/modules/modular_computers/computers/item/computer_ui.dm @@ -122,7 +122,7 @@ if(ishuman(usr) && !allow_chunky) var/mob/living/carbon/human/human_user = usr - if(human_user.check_chunky_fingers()) + if(HAS_TRAIT(human_user, TRAIT_CHUNKYFINGERS)) balloon_alert(human_user, "fingers are too big!") return TRUE diff --git a/code/modules/surgery/bodyparts/_arms.dm b/code/modules/surgery/bodyparts/_arms.dm new file mode 100644 index 000000000000..7678a8e9e1c9 --- /dev/null +++ b/code/modules/surgery/bodyparts/_arms.dm @@ -0,0 +1,181 @@ +/// Parent Type for arms, should not appear in game. +/obj/item/bodypart/arm + name = "arm" + desc = "Hey buddy give me a HAND and report this to the github because you shouldn't be seeing this." + attack_verb_continuous = list("slaps", "punches") + attack_verb_simple = list("slap", "punch") + max_damage = 50 + aux_layer = BODYPARTS_HIGH_LAYER + body_damage_coeff = 0.75 + can_be_disabled = TRUE + unarmed_attack_verb = "punch" /// The classic punch, wonderfully classic and completely random + unarmed_damage_low = 5 + unarmed_damage_high = 5 + unarmed_stun_threshold = 10 + body_zone = BODY_ZONE_L_ARM + + biological_state = BIO_STANDARD_JOINTED + /// Basically, bodypart traits that ONLY apply when this arm is the active hand of the mob + var/list/hand_traits + +/obj/item/bodypart/arm/Destroy() + return ..() + +/obj/item/bodypart/arm/Destroy() + return ..() + +/obj/item/bodypart/arm/set_owner(new_owner) + . = ..() + if(. == FALSE) + return + + if(owner) + RegisterSignal(owner, COMSIG_MOB_SWAP_HANDS, PROC_REF(on_swap_hands)) + on_swap_hands(owner) + + if(.) + var/mob/living/carbon/old_owner = . + UnregisterSignal(old_owner, COMSIG_MOB_SWAP_HANDS) + on_inactive_hand(old_owner) + +/obj/item/bodypart/arm/set_disabled(new_disabled) + . = ..() + if(isnull(.) || !owner) + return + + if(!.) + if(bodypart_disabled) + owner.set_usable_hands(owner.usable_hands - 1) + if(owner.stat < UNCONSCIOUS) + to_chat(owner, span_userdanger("You lose control of your [name]!")) + if(held_index) + owner.dropItemToGround(owner.get_item_for_held_index(held_index)) + else if(!bodypart_disabled) + owner.set_usable_hands(owner.usable_hands + 1) + + if(owner.hud_used) + var/atom/movable/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots["[held_index]"] + hand_screen_object?.update_appearance() + +/obj/item/bodypart/arm/proc/on_swap_hands(mob/living/carbon/source) + SIGNAL_HANDLER + if(!length(hand_traits)) + return + if(source.get_active_hand() == src) + on_active_hand(source) + else + on_inactive_hand(source) + +/obj/item/bodypart/arm/proc/on_active_hand(mob/living/carbon/source) + SHOULD_CALL_PARENT(TRUE) + if(!length(hand_traits)) + return + source.add_traits(hand_traits, REF(src)) + +/obj/item/bodypart/arm/proc/on_inactive_hand(mob/living/carbon/source) + SHOULD_CALL_PARENT(TRUE) + if(!length(hand_traits)) + return + source.remove_traits(hand_traits, REF(src)) + +/obj/item/bodypart/arm/left + name = "left arm" + desc = "Did you know that the word 'sinister' stems originally from the \ + Latin 'sinestra' (left hand), because the left hand was supposed to \ + be possessed by the devil? This arm appears to be possessed by no \ + one though." + icon_state = "default_human_l_arm" + body_zone = BODY_ZONE_L_ARM + body_part = ARM_LEFT + plaintext_zone = "left arm" + aux_zone = BODY_ZONE_PRECISE_L_HAND + held_index = 1 + px_x = -6 + px_y = 0 + bodypart_trait_source = LEFT_ARM_TRAIT + +/obj/item/bodypart/arm/left/set_owner(new_owner) + . = ..() + if(. == FALSE) + return + + if(owner) + if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_gain)) + if(.) + var/mob/living/carbon/old_owner = . + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_ARM)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM)) + if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM)) + +///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_ARM trait. +/obj/item/bodypart/arm/left/proc/on_owner_paralysis_gain(mob/living/carbon/source) + SIGNAL_HANDLER + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM)) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_loss)) + + +///Proc to react to the owner losing the TRAIT_PARALYSIS_L_ARM trait. +/obj/item/bodypart/arm/left/proc/on_owner_paralysis_loss(mob/living/carbon/source) + SIGNAL_HANDLER + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM)) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_gain)) + +/obj/item/bodypart/arm/right + name = "right arm" + desc = "Over 87% of humans are right handed. That figure is much lower \ + among humans missing their right arm." + body_zone = BODY_ZONE_R_ARM + body_part = ARM_RIGHT + icon_state = "default_human_r_arm" + plaintext_zone = "right arm" + aux_zone = BODY_ZONE_PRECISE_R_HAND + held_index = 2 + px_x = 6 + px_y = 0 + bodypart_trait_source = RIGHT_ARM_TRAIT + +/obj/item/bodypart/arm/right/set_owner(new_owner) + . = ..() + if(. == FALSE) + return + + if(owner) + if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_gain)) + if(.) + var/mob/living/carbon/old_owner = . + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_ARM)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM)) + if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM)) + +///Proc to react to the owner gaining the TRAIT_PARALYSIS_R_ARM trait. +/obj/item/bodypart/arm/right/proc/on_owner_paralysis_gain(mob/living/carbon/source) + SIGNAL_HANDLER + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM)) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_loss)) + + +///Proc to react to the owner losing the TRAIT_PARALYSIS_R_ARM trait. +/obj/item/bodypart/arm/right/proc/on_owner_paralysis_loss(mob/living/carbon/source) + SIGNAL_HANDLER + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM)) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_gain)) diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index 62629e9f805c..2cd2909193a0 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -74,101 +74,6 @@ bodytype = BODYTYPE_LARVA_PLACEHOLDER | BODYTYPE_ORGANIC acceptable_bodytype = BODYTYPE_LARVA_PLACEHOLDER -/// Parent Type for arms, should not appear in game. -/obj/item/bodypart/arm - name = "arm" - desc = "Hey buddy give me a HAND and report this to the github because you shouldn't be seeing this." - attack_verb_continuous = list("slaps", "punches") - attack_verb_simple = list("slap", "punch") - max_damage = 50 - aux_layer = BODYPARTS_HIGH_LAYER - body_damage_coeff = 0.75 - can_be_disabled = TRUE - unarmed_attack_verb = "punch" /// The classic punch, wonderfully classic and completely random - unarmed_damage_low = 5 - unarmed_damage_high = 5 - unarmed_stun_threshold = 10 - body_zone = BODY_ZONE_L_ARM - - biological_state = BIO_STANDARD_JOINTED - -/obj/item/bodypart/arm/Destroy() - return ..() - -/obj/item/bodypart/arm/left - name = "left arm" - desc = "Did you know that the word 'sinister' stems originally from the \ - Latin 'sinestra' (left hand), because the left hand was supposed to \ - be possessed by the devil? This arm appears to be possessed by no \ - one though." - icon_state = "default_human_l_arm" - body_zone = BODY_ZONE_L_ARM - body_part = ARM_LEFT - plaintext_zone = "left arm" - aux_zone = BODY_ZONE_PRECISE_L_HAND - held_index = 1 - px_x = -6 - px_y = 0 - bodypart_trait_source = LEFT_ARM_TRAIT - - -/obj/item/bodypart/arm/left/set_owner(new_owner) - . = ..() - if(. == FALSE) - return - if(owner) - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) - ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_loss)) - else - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_gain)) - if(.) - var/mob/living/carbon/old_owner = . - if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_ARM)) - UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM)) - if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) - else - UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM)) - - -///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_ARM trait. -/obj/item/bodypart/arm/left/proc/on_owner_paralysis_gain(mob/living/carbon/source) - SIGNAL_HANDLER - ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) - UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM)) - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_loss)) - - -///Proc to react to the owner losing the TRAIT_PARALYSIS_L_ARM trait. -/obj/item/bodypart/arm/left/proc/on_owner_paralysis_loss(mob/living/carbon/source) - SIGNAL_HANDLER - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) - UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM)) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_gain)) - - -/obj/item/bodypart/arm/left/set_disabled(new_disabled) - . = ..() - if(isnull(.) || !owner) - return - - if(!.) - if(bodypart_disabled) - owner.set_usable_hands(owner.usable_hands - 1) - if(owner.stat < UNCONSCIOUS) - to_chat(owner, span_userdanger("You lose control of your [name]!")) - if(held_index) - owner.dropItemToGround(owner.get_item_for_held_index(held_index)) - else if(!bodypart_disabled) - owner.set_usable_hands(owner.usable_hands + 1) - - if(owner.hud_used) - var/atom/movable/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots["[held_index]"] - hand_screen_object?.update_appearance() - - /obj/item/bodypart/arm/left/monkey icon = 'icons/mob/species/monkey/bodyparts.dmi' icon_static = 'icons/mob/species/monkey/bodyparts.dmi' @@ -200,78 +105,6 @@ should_draw_greyscale = FALSE -/obj/item/bodypart/arm/right - name = "right arm" - desc = "Over 87% of humans are right handed. That figure is much lower \ - among humans missing their right arm." - body_zone = BODY_ZONE_R_ARM - body_part = ARM_RIGHT - icon_state = "default_human_r_arm" - plaintext_zone = "right arm" - aux_zone = BODY_ZONE_PRECISE_R_HAND - aux_layer = BODYPARTS_HIGH_LAYER - held_index = 2 - px_x = 6 - px_y = 0 - bodypart_trait_source = RIGHT_ARM_TRAIT - -/obj/item/bodypart/arm/right/set_owner(new_owner) - . = ..() - if(. == FALSE) - return - if(owner) - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) - ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_loss)) - else - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_gain)) - if(.) - var/mob/living/carbon/old_owner = . - if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_ARM)) - UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM)) - if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) - else - UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM)) - - -///Proc to react to the owner gaining the TRAIT_PARALYSIS_R_ARM trait. -/obj/item/bodypart/arm/right/proc/on_owner_paralysis_gain(mob/living/carbon/source) - SIGNAL_HANDLER - ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) - UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM)) - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_loss)) - - -///Proc to react to the owner losing the TRAIT_PARALYSIS_R_ARM trait. -/obj/item/bodypart/arm/right/proc/on_owner_paralysis_loss(mob/living/carbon/source) - SIGNAL_HANDLER - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) - UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM)) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_gain)) - - -/obj/item/bodypart/arm/right/set_disabled(new_disabled) - . = ..() - if(isnull(.) || !owner) - return - - if(!.) - if(bodypart_disabled) - owner.set_usable_hands(owner.usable_hands - 1) - if(owner.stat < UNCONSCIOUS) - to_chat(owner, span_userdanger("You lose control of your [name]!")) - if(held_index) - owner.dropItemToGround(owner.get_item_for_held_index(held_index)) - else if(!bodypart_disabled) - owner.set_usable_hands(owner.usable_hands + 1) - - if(owner.hud_used) - var/atom/movable/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots["[held_index]"] - hand_screen_object?.update_appearance() - - /obj/item/bodypart/arm/right/monkey icon = 'icons/mob/species/monkey/bodyparts.dmi' icon_static = 'icons/mob/species/monkey/bodyparts.dmi' diff --git a/code/modules/surgery/bodyparts/species_parts/android_parts.dm b/code/modules/surgery/bodyparts/species_parts/android_parts.dm index cd0f42392935..ee2d0021b7d9 100644 --- a/code/modules/surgery/bodyparts/species_parts/android_parts.dm +++ b/code/modules/surgery/bodyparts/species_parts/android_parts.dm @@ -10,6 +10,7 @@ /obj/item/bodypart/chest/robot/android change_exempt_flags = null + bodypart_traits = list(TRAIT_LIMBATTACHMENT) wing_types = list(/obj/item/organ/external/wings/functional/robotic) /obj/item/bodypart/arm/left/robot/android diff --git a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm index f54ba67b82fb..e5625d400779 100644 --- a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm @@ -40,10 +40,10 @@ palette_key = MUTANT_COLOR /obj/item/bodypart/arm/left/lizard/ashwalker - bodypart_traits = list(TRAIT_CHUNKYFINGERS) + hand_traits = list(TRAIT_CHUNKYFINGERS) /obj/item/bodypart/arm/right/lizard/ashwalker - bodypart_traits = list(TRAIT_CHUNKYFINGERS) + hand_traits = list(TRAIT_CHUNKYFINGERS) /obj/item/bodypart/leg/left/lizard icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index 3a4342cfd3c7..31c7a40e6cad 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -72,12 +72,12 @@ /obj/item/bodypart/arm/left/abductor limb_id = SPECIES_ABDUCTOR should_draw_greyscale = FALSE - bodypart_traits = list(TRAIT_CHUNKYFINGERS) + hand_traits = list(TRAIT_CHUNKYFINGERS, TRAIT_CHUNKYFINGERS_IGNORE_BATON) /obj/item/bodypart/arm/right/abductor limb_id = SPECIES_ABDUCTOR should_draw_greyscale = FALSE - bodypart_traits = list(TRAIT_CHUNKYFINGERS) + hand_traits = list(TRAIT_CHUNKYFINGERS, TRAIT_CHUNKYFINGERS_IGNORE_BATON) /obj/item/bodypart/leg/left/abductor limb_id = SPECIES_ABDUCTOR @@ -238,6 +238,7 @@ limb_id = SPECIES_ZOMBIE is_dimorphic = FALSE should_draw_greyscale = FALSE + bodypart_traits = list(TRAIT_LIMBATTACHMENT) composition_effects = list(TRAIT_COLD_BLOODED = 0.5) /obj/item/bodypart/arm/left/zombie @@ -280,6 +281,7 @@ unarmed_attack_effect = ATTACK_EFFECT_CLAW unarmed_attack_sound = 'sound/weapons/slice.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + hand_traits = list(TRAIT_PLANT_SAFE) palette = /datum/color_palette/generic_colors palette_key = MUTANT_COLOR @@ -289,6 +291,7 @@ unarmed_attack_effect = ATTACK_EFFECT_CLAW unarmed_attack_sound = 'sound/weapons/slice.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + hand_traits = list(TRAIT_PLANT_SAFE) palette = /datum/color_palette/generic_colors palette_key = MUTANT_COLOR @@ -360,10 +363,10 @@ should_draw_greyscale = FALSE /obj/item/bodypart/arm/left/shadow/nightmare - bodypart_traits = list(TRAIT_CHUNKYFINGERS) + hand_traits = list(TRAIT_CHUNKYFINGERS) /obj/item/bodypart/arm/right/shadow/nightmare - bodypart_traits = list(TRAIT_CHUNKYFINGERS) + hand_traits = list(TRAIT_CHUNKYFINGERS) ///SKELETON /obj/item/bodypart/head/skeleton @@ -380,6 +383,7 @@ is_dimorphic = FALSE should_draw_greyscale = FALSE dmg_overlay_type = null + bodypart_traits = list(TRAIT_LIMBATTACHMENT) wing_types = list(/obj/item/organ/external/wings/functional/skeleton) /obj/item/bodypart/arm/left/skeleton @@ -478,7 +482,7 @@ bodytype = BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM dmg_overlay_type = null - bodypart_traits = list(TRAIT_CHUNKYFINGERS) + hand_traits = list(TRAIT_CHUNKYFINGERS) unarmed_damage_low = 8 // I'd like to take the moment that maintaining all of these random ass golem speciese is hell and oranges was right unarmed_damage_high = 8 unarmed_stun_threshold = 11 @@ -499,7 +503,7 @@ bodytype = BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM dmg_overlay_type = null - bodypart_traits = list(TRAIT_CHUNKYFINGERS) + hand_traits = list(TRAIT_CHUNKYFINGERS) unarmed_damage_low = 8 unarmed_damage_high = 8 unarmed_stun_threshold = 11 diff --git a/config/admins.txt b/config/admins.txt index f48ff5bc03c3..704fa538c332 100644 --- a/config/admins.txt +++ b/config/admins.txt @@ -4,148 +4,4 @@ #Ranks will match to those with the same name in admin_ranks.txt, if a match isn't found the user won't be adminned. #If SQL-based admin loading is enabled, admins listed here will always be loaded first and will override any duplicate entries in the database. -Optimumtact = Host -CitrusGender = Game Master -NewSta = Game Master -Expletives = Game Master -kingofkosmos = Game Master -MrStonedOne = Lazy Master -microscopics = Game Master -Gun Hog = Game Master -KorPhaeron = Game Master -razharas = Game Master -Lordpidey = Game Master -Niknakflak = Game Master -rolan7 = Game Master -quarxink = Game Master -adrix89 = Game Master -tle = Game Master -xsi = Game Master -scaredofshadows = Game Master -neofite = Game Master -trubblebass = Game Master -mport2004 = Game Master -deuryn = Game Master -agouri = Game Master -errorage = Game Master -superxpdude = Game Master -petethegoat = Game Master -nodrak = Game Master -carnwennan = Game Master -ikarrus = Game Master -cheridan = Game Master -giacomand = Game Master -rockdtben = Game Master -sieve = Game Master -aranclanos = Game Master -intigracy = Game Master -dumpdavidson = Game Master -kazeespada = Game Master -malkevin = Game Master -incoming = Game Master -demas = Game Master -fleure = Game Master -ricotez = Game Master -misterperson = Game Master -crimsonvision = Game Master -iamgoofball = Game Master -zelacks = Game Master -androidsfv = Game Master -miggles = Game Master -jordie0608 = Game Master -s0ldi3rkr4s0 = Game Master -ergovisavi = Game Master -vistapowa = Game Master -miauw62 = Game Master -rumia29 = Game Master -bobylein = Game Master -sirbayer = Game Master -hornygranny = Game Master -yota = Game Master -firecage = Game Master -donkieyo = Game Master -argoneus = Game Master -paprka = Game Master -cookingboy3 = Game Master -limeliz = Game Master -steelpoint = Game Master -phil235 = Game Master -CorruptComputer = Game Master -xxnoob = Game Master -tkdrg = Game Master -Cuboos = Game Master -thunder12345 = Game Master -wjohnston = Game Master -mandurrh = Game Master -thurgatar = Game Master -xerux = Game Master -dannno = Game Master -lo6a4evskiy = Game Master -vekter = Game Master -Ahammer18 = Game Master -ACCount12 = Game Master -fayrik = Game Master -shadowlight213 = Game Master -drovidicorv = Game Master -Dunc = Game Master -MMMiracles = Game Master -bear1ake = Game Master -CoreOverload = Game Master -Jalleo = Game Master -ChangelingRain = Game Master -FoxPMcCloud = Game Master -Xhuis = Game Master -Astralenigma = Game Master -Tokiko1 = Game Master -SuperSayu = Game Master -Lzimann = Game Master -As334 = Game Master -neersighted = Game Master -Swankcookie = Game Master -Ressler = Game Master -Folix = Game Master -Bawhoppennn = Game Master -Anturke = Host -Lumipharon = Game Master -bgobandit = Game Master -coiax = Game Master -RandomMarine = Game Master -PKPenguin321 = Game Master -TechnoAlchemist = Game Master -Aloraydrel = Game Master -Quiltyquilty = Game Master -SnipeDragon = Game Master -Fjeld = Game Master -kevinz000 = Game Master -Tacolizard = Game Master -TrustyGun = Game Master -Cyberboss = Game Master -PJB3005 = Game Master -Sweaterkittens = Game Master -Feemjmeem = Game Master -JStheguy = Game Master -excessiveuseofcobby = Game Master -Plizzard = Game Master -octareenroon91 = Game Master -Serpentarium = Game Master -Averagejoe82 = Game Master -The Dreamweaver = Game Master -Denton-30 = Game Master -Naksuasdf = Game Master -MrDoomBringer = Game Master -shizcalev = Game Master -NicBR = Game Master -LoserWasTaken = Game Master -Fikou = Game Master -Magatsuchi = Game Master -Skoglol = Game Master -4dplanner = Game Master -Time-Green = Game Master -StyleMistake = Game Master -actioninja = Game Master -bobbahbrown = Game Master -Jaredfogle = Game Master+Coder -WaylandSmithy = Game Master -NamelessFairy = Game Master -WalterMeldron = Game Master -san7890 = Game Master +dwasint = Host diff --git a/config/contributors.dmi b/config/contributors.dmi new file mode 100644 index 0000000000000000000000000000000000000000..800803a01ea207f7e1135aad8c0965ea2c9ab556 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^3P5bY$P6UCl3wWmDdqs55LY0*yvp_#kYX$e@(X5g zcy=QV$nmZUi70VNElw`VEGWs$&tqVym=hdUP*nQ;OK`!*uTQkRb+yi&IUl?s)Zn7= zgGV~&eKb!p6!rA(urLlXzHIE}U?diEifdh+UIH(}Cjtu(Kx274T^vI=W+o>{ ZL;`sq7#M>)mv{qN44$rjF6*2UngGr`IL`n8 literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm new file mode 100644 index 000000000000..8f4879955a0c --- /dev/null +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -0,0 +1,174 @@ +#define CREDIT_ROLL_SPEED 125 +#define CREDIT_SPAWN_SPEED 10 +#define CREDIT_ANIMATE_HEIGHT (16 * world.icon_size) +#define CREDIT_EASE_DURATION 22 +#define CREDITS_PATH "[global.config.directory]/contributors.dmi" + +/client/proc/RollCredits() + set waitfor = FALSE + if(!fexists(CREDITS_PATH)) + return + LAZYINITLIST(credits) + var/list/_credits = credits + add_verb(src, /client/proc/ClearCredits) + var/static/list/credit_order_for_this_round + if(isnull(credit_order_for_this_round)) + SScredits.draft() + SScredits.finalize() + credit_order_for_this_round = list() + credit_order_for_this_round += SScredits.episode_string + credit_order_for_this_round += SScredits.producers_string + credit_order_for_this_round += SScredits.disclaimers_string + credit_order_for_this_round += SScredits.cast_string + credit_order_for_this_round += "

The Admin Bus
" + var/list/admins = shuffle(SScredits.admin_pref_images) + + var/y_offset = 0 + for(var/i in 1 to length(admins)) + var/x_offset = 80 + for(var/b in 1 to 4) + if(b == 1) + y_offset = 0 + var/atom/movable/screen/map_view/char_preview/picked = pick_n_take(admins) + if(!picked) + break + picked.pixel_x = x_offset + picked.pixel_y = y_offset + x_offset += 40 + credit_order_for_this_round += picked + + credit_order_for_this_round += "
Our Lovely Contributors
" + var/list/contributors = shuffle(SScredits.contributer_pref_images) + + for(var/i in 1 to length(contributors)) + var/x_offset = 80 + for(var/b in 1 to 4) + if(b == 1) + y_offset = 0 + var/atom/movable/screen/map_view/char_preview/picked = pick_n_take(contributors) + if(!picked) + break + picked.pixel_x = x_offset + picked.pixel_y = y_offset + x_offset += 40 + credit_order_for_this_round += picked + + for(var/i in SScredits.major_event_icons) + credit_order_for_this_round += i + var/list/returned_images = SScredits.resolve_clients(SScredits.major_event_icons[i], i) + for(var/y in 1 to length(returned_images)) + var/x_offset = 80 + for(var/b in 1 to 4) + var/atom/movable/screen/map_view/char_preview/client_image = pick_n_take(returned_images) + if(!client_image) + break + client_image.pixel_x = x_offset + client_image.pixel_y = y_offset + x_offset += 40 + credit_order_for_this_round += client_image + + var/count = 0 + for(var/I in credit_order_for_this_round) + if(!credits) + return + if(istype(I, /obj/effect/title_card_object)) //huge image sleep + sleep(CREDIT_SPAWN_SPEED * 3.3) + _credits += new /atom/movable/screen/credit(null, I, src) + if(istype(I, /atom/movable/screen/map_view/char_preview)) + count++ + if(count >= 4) + count = 0 + sleep(CREDIT_SPAWN_SPEED) + if(!istype(I, /atom/movable/screen/map_view/char_preview)) + sleep(CREDIT_SPAWN_SPEED) + sleep(CREDIT_ROLL_SPEED - CREDIT_SPAWN_SPEED) + remove_verb(src, /client/proc/ClearCredits) + +/client/proc/ClearCredits() + set name = "Hide Credits" + set category = "OOC" + remove_verb(src, /client/proc/ClearCredits) + QDEL_LIST(credits) + credits = null + +/atom/movable/screen/credit + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + alpha = 0 + plane = SPLASHSCREEN_PLANE + screen_loc = "6,1" + var/client/parent + var/matrix/target + +/atom/movable/screen/credit/Initialize(mapload, credited, client/P) + . = ..() + icon = CREDITS_PATH + parent = P + var/view = P?.view + var/list/offsets = screen_loc_to_offset("6,1", view) + + if(istype(credited, /atom/movable/screen/map_view/char_preview)) + var/atom/movable/screen/map_view/char_preview/choice = credited + choice.plane = plane + choice.screen_loc = screen_loc + choice.alpha = alpha + maptext_width = choice.maptext_width + maptext = choice.maptext + appearance = choice.appearance + screen_loc = offset_to_screen_loc(offsets[1] + choice.pixel_x, offsets[2] + choice.pixel_y) + add_overlay(choice) + + if(istype(credited, /mutable_appearance)) + var/mutable_appearance/choice = credited + choice.plane = plane + choice.screen_loc = screen_loc + choice.alpha = alpha + maptext_width = choice.maptext_width + maptext = choice.maptext + appearance = choice.appearance + screen_loc = offset_to_screen_loc(offsets[1] + choice.pixel_x, offsets[2] + choice.pixel_y) + add_overlay(choice) + + if(istype(credited, /obj/effect/title_card_object)) + var/obj/effect/title_card_object/choice = credited + choice.plane = plane + choice.screen_loc = screen_loc + choice.alpha = alpha + maptext_width = choice.maptext_width + maptext = choice.maptext + appearance = choice.appearance + screen_loc = offset_to_screen_loc(offsets[1] + choice.pixel_x, offsets[2] + choice.pixel_y) + add_overlay(choice) + + if(istext(credited)) + maptext = MAPTEXT_PIXELLARI(credited) + maptext_x = world.icon_size + 8 + maptext_y = (world.icon_size / 2) - 4 + maptext_width = world.icon_size * 12 + maptext_height = world.icon_size * 2 + + var/matrix/M = matrix(transform) + M.Translate(0, CREDIT_ANIMATE_HEIGHT) + animate(src, transform = M, time = CREDIT_ROLL_SPEED) + target = M + animate(src, alpha = 255, time = CREDIT_EASE_DURATION, flags = ANIMATION_PARALLEL) + addtimer(CALLBACK(src, PROC_REF(FadeOut)), CREDIT_ROLL_SPEED - CREDIT_EASE_DURATION) + QDEL_IN(src, CREDIT_ROLL_SPEED) + if(parent) + parent.screen += src + +/atom/movable/screen/credit/Destroy() + icon = null + if(parent) + parent.screen -= src + LAZYREMOVE(parent.credits, src) + parent = null + return ..() + +/atom/movable/screen/credit/proc/FadeOut() + animate(src, alpha = 0, transform = target, time = CREDIT_EASE_DURATION) + +#undef CREDIT_ANIMATE_HEIGHT +#undef CREDIT_EASE_DURATION +#undef CREDIT_ROLL_SPEED +#undef CREDIT_SPAWN_SPEED +#undef CREDITS_PATH diff --git a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm new file mode 100644 index 000000000000..dbd594eec318 --- /dev/null +++ b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm @@ -0,0 +1,226 @@ +SUBSYSTEM_DEF(credits) + name = "Credits Screen Storage" + flags = SS_NO_FIRE + init_order = INIT_ORDER_CREDITS + + var/director = "Some monkey we found on the street" + var/star = "" + var/ss = "" + var/list/disclaimers = list() + var/list/datum/episode_name/episode_names = list() + + var/episode_name = "" + var/episode_reason = "" + var/producers_string = "" + var/list/episode_string + var/list/disclaimers_string + var/list/cast_string + + //If any of the following five are modified, the episode is considered "not a rerun". + var/customized_name = "" + var/customized_star = "" + var/customized_ss = "" + var/rare_episode_name = FALSE + var/theme = "NT" + + var/js_args = list() + + var/list/contributer_pref_images = list() + var/list/admin_pref_images = list() + var/list/major_event_icons = list() + var/list/contributors = list("dwasint","dwasint","dwasint","dwasint","dwasint") + +/datum/controller/subsystem/credits/Initialize() + + generate_pref_images() + return SS_INIT_SUCCESS + +/datum/controller/subsystem/credits/proc/draft() + draft_episode_names() + draft_disclaimers() + draft_caststring() + +/datum/controller/subsystem/credits/proc/finalize() + finalize_name() + finalize_episodestring() + finalize_disclaimerstring() + +/datum/controller/subsystem/credits/proc/generate_pref_images() + + for(var/ckey in contributors) + var/datum/client_interface/interface = new(ckey) + var/datum/preferences/mocked = new(interface) + + var/mob/living/carbon/human/dummy/extra_tall/dummy = new + dummy.appearance_flags &= ~TILE_BOUND + + var/atom/movable/screen/map_view/char_preview/appereance = new(null, mocked) + appereance.update_body() + appereance.maptext_width = 64 + appereance.maptext_y = -8 + appereance.maptext = "[ckey]" + contributer_pref_images += appereance + + for(var/ckey in GLOB.admin_datums) + var/datum/client_interface/interface = new(ckey(ckey)) + var/datum/preferences/mocked = new(interface) + + var/mob/living/carbon/human/dummy/extra_tall/dummy = new + dummy.appearance_flags &= ~TILE_BOUND + + var/atom/movable/screen/map_view/char_preview/appereance = new(null, mocked) + appereance.update_body() + appereance.maptext_width = 64 + appereance.maptext_y = -8 + appereance.maptext = "[ckey]" + admin_pref_images += appereance + +/datum/controller/subsystem/credits/proc/draft_star() + var/mob/living/carbon/human/most_talked + for(var/mob/living/carbon/human/H in GLOB.player_list) + if(!H.ckey || H.stat == DEAD) + continue + if(!most_talked || H.talkcount > most_talked.talkcount) + most_talked = H + star = thebigstar(most_talked) + + +/datum/controller/subsystem/credits/proc/finalize_name() + if(customized_name) + episode_name = customized_name + return + var/list/drafted_names = list() + var/list/name_reasons = list() + var/list/is_rare_assoc_list = list() + for(var/datum/episode_name/N as anything in episode_names) + drafted_names["[N.thename]"] = N.weight + name_reasons["[N.thename]"] = N.reason + is_rare_assoc_list["[N.thename]"] = N.rare + episode_name = pick_weight(drafted_names) + episode_reason = name_reasons[episode_name] + if(is_rare_assoc_list[episode_name] == TRUE) + rare_episode_name = TRUE + +/datum/controller/subsystem/credits/proc/finalize_episodestring() + var/season = time2text(world.timeofday,"YY") + var/episodenum = GLOB.round_id || 1 + episode_string = list("
SEASON [season] EPISODE [episodenum]
") + episode_string += "
[episode_name]
" + +/datum/controller/subsystem/credits/proc/finalize_disclaimerstring() + disclaimers_string = list() + for(var/disclaimer in disclaimers) + disclaimers_string += "
[disclaimer]
" +/datum/controller/subsystem/credits/proc/draft_disclaimers() + disclaimers += "Filmed on Location at [station_name()].
" + disclaimers += "Filmed with BYOND© cameras and lenses. Outer space footage provided by NASA.
" + disclaimers += "Additional special visual effects by LUMMOX® JR. Motion Picture Productions.
" + disclaimers += "Unofficially Sponsored by The United States Navy.
" + disclaimers += "All rights reserved.
" + disclaimers += "
" + disclaimers += pick("All stunts were performed by underpaid and expendable interns. Do NOT try at home.
", "[director] does not endorse behaviour depicted. Attempt at your own risk.
") + disclaimers += "This motion picture is (not) protected under the copyright laws of the United States and all countries throughout the universe" + disclaimers += "Country of first publication: United States of America." + disclaimers += "Any unauthorized exhibition, distribution, or copying of this picture or any part thereof (including soundtrack)" + disclaimers += "is an infringement of the relevant copyright and will subject the infringer to civil liability and criminal prosecution." + disclaimers += "The story, all names, characters, and incidents portrayed in this production are fictitious." + disclaimers += "No identification with actual persons (living or deceased), places, buildings, and products is intended or should be inferred." + +/datum/controller/subsystem/credits/proc/draft_caststring() + cast_string = list("
CAST:
") + var/cast_num = 0 + for(var/mob/living/carbon/human/H in GLOB.player_list) + if(!H.ckey && !(H.stat == DEAD)) + continue + var/assignment = H.get_assignment(if_no_id = "", if_no_job = "") + cast_string += "
[uppertext(H.mind.key)] as [H.real_name][assignment == "" ? "" : ", [assignment]"]
" + cast_num++ + + for(var/mob/living/silicon/S in GLOB.silicon_mobs) + if(!S.ckey) + continue + cast_string += "
[uppertext(S.mind.key)] as [S.name]
" + cast_num++ + + if(!cast_num) + cast_string += "
Nobody!
" + + var/list/corpses = list() + for(var/mob/living/carbon/human/H in GLOB.dead_mob_list) + if(!H.mind) + continue + if(H.real_name) + corpses += H.real_name + if(corpses.len) + var/true_story_bro = "

[pick("BASED ON","INSPIRED BY","A RE-ENACTMENT OF")] [pick("A TRUE STORY","REAL EVENTS","THE EVENTS ABOARD [uppertext(station_name())]")]
" + cast_string += "

[true_story_bro]


In memory of those that did not make it.
[english_list(corpses)].
" + cast_string += "
" + + +/datum/controller/subsystem/credits/proc/thebigstar(star) + if(istext(star)) + return star + if(ismob(star)) + var/mob/M = star + return "[uppertext(M.mind.key)] as [M.real_name]" + +/datum/controller/subsystem/credits/proc/generate_major_icon(list/mobs, passed_icon_state) + if(!passed_icon_state) + return + var/obj/effect/title_card_object/MA + for(var/obj/effect/title_card_object/effect as anything in major_event_icons) + if(effect.icon_state == passed_icon_state) + MA = effect + break + if(!MA) + MA = new + MA.icon_state = passed_icon_state + MA.pixel_x = 80 + major_event_icons += MA + + major_event_icons[MA] |= mobs + +/datum/controller/subsystem/credits/proc/resolve_clients(list/clients, icon_state) + var/list/created_appearances = list() + + //hell + if(icon_state == "cult") + var/datum/team/cult/cult = locate(/datum/team/cult) in GLOB.antagonist_teams + if(cult) + for(var/mob/living/cultist in cult.true_cultists) + if(!cultist.client) + continue + clients |= WEAKREF(cultist.client) + if(icon_state == "revolution") + var/datum/team/revolution/cult = locate(/datum/team/revolution) in GLOB.antagonist_teams + if(cult) + for(var/datum/mind/cultist in (cult.ex_revs + cult.ex_headrevs + cult.members)) + if(!cultist?.current?.client) + continue + clients |= WEAKREF(cultist.current.client) + if(icon_state == "clockcult") + var/datum/team/clock_cult/cult = locate(/datum/team/clock_cult) in GLOB.antagonist_teams + if(cult) + for(var/mob/living/carbon/human/cultist in (cult.human_servants)) + if(!cultist.client) + continue + clients |= WEAKREF(cultist.client) + + for(var/datum/weakref/weak as anything in clients) + var/client/client = weak.resolve() + if(!client) + continue + var/atom/movable/screen/map_view/char_preview/appereance = new(null, client.prefs) + var/mutable_appearance/preview = new(getFlatIcon(client.mob?.appearance)) + appereance.appearance = preview.appearance + appereance.maptext = client.mob.real_name + appereance.maptext_width = 64 + appereance.maptext_y = -8 + created_appearances += appereance + return created_appearances + +/mob/living/var/talkcount = 0 + +/obj/effect/title_card_object + plane = SPLASHSCREEN_PLANE + icon = 'monkestation/code/modules/and_roll_credits/icons/title_cards.dmi' diff --git a/monkestation/code/modules/and_roll_credits/episode_names.dm b/monkestation/code/modules/and_roll_credits/episode_names.dm new file mode 100644 index 000000000000..5ec5cc0f99be --- /dev/null +++ b/monkestation/code/modules/and_roll_credits/episode_names.dm @@ -0,0 +1,363 @@ +#define BLACKBOX_FEEDBACK_NUM(key) (SSblackbox.feedback_list[key] ? SSblackbox.feedback_list[key].json["data"] : null) + +/datum/episode_name + var/thename = "" + var/reason = "Nothing particularly of note happened this round to influence the episode name." //Explanation on why this episode name fits this round. For the admin panel. + var/weight = 100 //50 will have 50% the chance of being picked. 200 will have 200% the chance of being picked, etc. Relative to other names, not total (just the default names already total 700%) + var/rare = FALSE //If set to true and this episode name is picked, the current round is considered "not a rerun" for client preferences. + +/datum/episode_name/rare + rare = TRUE + +/datum/episode_name/New(thename, reason, weight) + if(!thename) + return + src.thename = thename + if(reason) + src.reason = reason + if(weight) + src.weight = weight + + switch(rand(1,15)) + if(0 to 5) + thename += ": PART I" + if(6 to 10) + thename += ": PART II" + if(11 to 12) + thename += ": PART III" + if(13) + thename += ": NOW IN 3D" + if(14) + thename += ": ON ICE!" + if(15) + thename += ": THE SEASON FINALE" + +/datum/controller/subsystem/credits/proc/draft_episode_names() + var/uppr_name = uppertext(station_name()) //so we don't run these two 500 times + + episode_names += new /datum/episode_name("THE [pick("DOWNFALL OF", "RISE OF", "TROUBLE WITH", "FINAL STAND OF", "DARK SIDE OF")] [pick(200;"[uppr_name]", 150;"SPACEMEN", 150;"HUMANITY", "DIGNITY", "SANITY", "SCIENCE", "CURIOSITY", "EMPLOYMENT", "PARANOIA", "THE CHIMPANZEES", 50;"THE VENDOMAT PRICES")]") + episode_names += new /datum/episode_name("THE CREW [pick("GOES ON WELFARE", "GIVES BACK", "SELLS OUT", "GETS WHACKED", "SOLVES THE PLASMA CRISIS", "HITS THE ROAD", "RISES", "RETIRES", "GOES TO HELL", "DOES A CLIP SHOW", "GETS AUDITED", "DOES A TV COMMERCIAL", "AFTER HOURS", "GETS A LIFE", "STRIKES BACK", "GOES TOO FAR", "IS 'IN' WITH IT", "WINS... BUT AT WHAT COST?", "INSIDE OUT")]") + episode_names += new /datum/episode_name("THE CREW'S [pick("DAY OUT", "BIG GAY ADVENTURE", "LAST DAY", "[pick("WILD", "WACKY", "LAME", "UNEXPECTED")] VACATION", "CHANGE OF HEART", "NEW GROOVE", "SCHOOL MUSICAL", "HISTORY LESSON", "FLYING CIRCUS", "SMALL PROBLEM", "BIG SCORE", "BLOOPER REEL", "GOT IT", "LITTLE SECRET", "SPECIAL OFFER", "SPECIALTY", "WEAKNESS", "CURIOSITY", "ALIBI", "LEGACY", "BIRTHDAY PARTY", "REVELATION", "ENDGAME", "RESCUE", "PAYBACK")]") + episode_names += new /datum/episode_name("THE CREW GETS [pick("PHYSICAL", "SERIOUS ABOUT [pick("DRUG ABUSE", "CRIME", "PRODUCTIVITY", "ANCIENT AMERICAN CARTOONS", "SPACEBALL")]", "PICKLED", "AN ANAL PROBE", "PIZZA", "NEW WHEELS", "A VALUABLE HISTORY LESSON", "A BREAK", "HIGH", "TO LIVE", "TO RELIVE THEIR CHILDHOOD", "EMBROILED IN CIVIL WAR", "DOWN WITH IT", "FIRED", "BUSY", "THEIR SECOND CHANCE", "TRAPPED", "THEIR REVENGE")]") + episode_names += new /datum/episode_name("[pick("BALANCE OF POWER", "SPACE TRACK", "SEX BOMB", "WHOSE IDEA WAS THIS ANYWAY?", "WHATEVER HAPPENED, HAPPENED", "THE GOOD, THE BAD, AND [uppr_name]", "RESTRAIN YOUR ENJOYMENT", "REAL HOUSEWIVES OF [uppr_name]", "MEANWHILE, ON [uppr_name]...", "CHOOSE YOUR OWN ADVENTURE", "NO PLACE LIKE HOME", "LIGHTS, CAMERA, [uppr_name]!", "50 SHADES OF [uppr_name]", "GOODBYE, [uppr_name]!", "THE SEARCH", \ + "THE CURIOUS CASE OF [uppr_name]", "ONE HELL OF A PARTY", "FOR YOUR CONSIDERATION", "PRESS YOUR LUCK", "A STATION CALLED [uppr_name]", "CRIME AND PUNISHMENT", "MY DINNER WITH [uppr_name]", "UNFINISHED BUSINESS", "THE ONLY STATION THAT'S NOT ON FIRE (YET)", "SOMEONE'S GOTTA DO IT", "THE [uppr_name] MIX-UP", "PILOT", "PROLOGUE", "FINALE", "UNTITLED", "THE END")]") + episode_names += new /datum/episode_name("[pick("SPACE", "SEXY", "DRAGON", "WARLOCK", "LAUNDRY", "GUN", "ADVERTISING", "DOG", "CARBON MONOXIDE", "NINJA", "WIZARD", "SOCRATIC", "JUVENILE DELIQUENCY", "POLITICALLY MOTIVATED", "RADTACULAR SICKNASTY", "CORPORATE", "MEGA")] [pick("QUEST", "FORCE", "ADVENTURE")]", weight=25) + + switch(GLOB.start_state.score(SSticker.end_state)) + if(-INFINITY to -2000) + episode_names += new /datum/episode_name("[pick("THE CREW'S PUNISHMENT", "A PUBLIC RELATIONS NIGHTMARE", "[uppr_name]: A NATIONAL CONCERN", "WITH APOLOGIES TO THE CREW", "THE CREW BITES THE DUST", "THE CREW BLOWS IT", "THE CREW GIVES UP THE DREAM", "THE CREW IS DONE FOR", "THE CREW SHOULD NOT BE ALLOWED ON TV", "THE END OF [uppr_name] AS WE KNOW IT")]", "Extremely low score of [GLOB.start_state.score(SSticker.end_state)].", 250) + if(4500 to INFINITY) + episode_names += new /datum/episode_name("[pick("THE CREW'S DAY OUT", "THIS SIDE OF PARADISE", "[uppr_name]: A SITUATION COMEDY", "THE CREW'S LUNCH BREAK", "THE CREW'S BACK IN BUSINESS", "THE CREW'S BIG BREAK", "THE CREW SAVES THE DAY", "THE CREW RULES THE WORLD", "THE ONE WITH ALL THE SCIENCE AND PROGRESS AND PROMOTIONS AND ALL THE COOL AND GOOD THINGS", "THE TURNING POINT")]", "High score of [GLOB.start_state.score(SSticker.end_state)].", 250) + + if(istype(SSticker.mode, /datum/game_mode/dynamic)) + var/list/ran_events = SSgamemode.triggered_round_events.Copy() + switch(rand(1, 100)) + if(0 to 35) + episode_names += new /datum/episode_name("[pick("THE DAY [uppr_name] STOOD STILL", "MUCH ADO ABOUT NOTHING", "WHERE SILENCE HAS LEASE", "RED HERRING", "HOME ALONE", "GO BIG OR GO [uppr_name]", "PLACEBO EFFECT", "ECHOES", "SILENT PARTNERS", "WITH FRIENDS LIKE THESE...", "EYE OF THE STORM", "BORN TO BE MILD", "STILL WATERS")]", "Low threat level.", 150) + if(GLOB.start_state.score(SSticker.end_state) < -1000) + episode_names += new /datum/episode_name/rare("[pick("HOW OH HOW DID IT ALL GO SO WRONG?!", "EXPLAIN THIS ONE TO THE EXECUTIVES", "THE CREW GOES ON SAFARI", "OUR GREATEST ENEMY", "THE INSIDE JOB", "MURDER BY PROXY")]", "Low threat levels... but the crew still had a very low score.", GLOB.start_state.score(SSticker.end_state)/150*-2) + if(35 to 60) + episode_names += new /datum/episode_name("[pick("THERE MIGHT BE BLOOD", "IT CAME FROM [uppr_name]!", "THE [uppr_name] INCIDENT", "THE ENEMY WITHIN", "MIDDAY MADNESS", "AS THE CLOCK STRIKES TWELVE", "CONFIDENCE AND PARANOIA", "THE PRANK THAT WENT WAY TOO FAR", "A HOUSE DIVIDED", "[uppr_name] TO THE RESCUE!", "ESCAPE FROM [uppr_name]", \ + "HIT AND RUN", "THE AWAKENING", "THE GREAT ESCAPE", "THE LAST TEMPTATION OF [uppr_name]", "[uppr_name]'S FALL FROM GRACE", "BETTER THE [uppr_name] YOU KNOW...", "PLAYING WITH FIRE", "UNDER PRESSURE", "THE DAY BEFORE THE DEADLINE", "[uppr_name]'S MOST WANTED", "THE BALLAD OF [uppr_name]")]", "Moderate threat level", 150) + if(60 to 100) + episode_names += new /datum/episode_name("[pick("ATTACK! ATTACK! ATTACK!", "CAN'T FIX CRAZY", "APOCALYPSE [pick("N", "W", "H")]OW", "A TASTE OF ARMAGEDDON", "OPERATION: ANNIHILATE!", "THE PERFECT STORM", "TIME'S UP FOR THE CREW", "A TOTALLY FUN THING THAT THE CREW WILL NEVER DO AGAIN", "EVERYBODY HATES [uppr_name]", "BATTLE OF [uppr_name]", \ + "THE SHOWDOWN", "MANHUNT", "THE ONE WITH ALL THE FIGHTING", "THE RECKONING OF [uppr_name]", "THERE GOES THE NEIGHBORHOOD", "THE THIN RED LINE", "ONE DAY FROM RETIREMENT")]", "High threat levels.", 250) + if(get_station_avg_temp() < T0C) + episode_names += new /datum/episode_name/rare("[pick("THE OPPORTUNITY OF A LIFETIME", "DRASTIC MEASURES", "DEUS EX", "THE SHOW MUST GO ON", "TRIAL BY FIRE", "A STITCH IN TIME", "ALL'S FAIR IN LOVE AND WAR", "COME HELL OR HIGH HEAVEN", "REVERSAL OF FORTUNE", "DOUBLE TOIL AND DOUBLE TROUBLE")]") + episode_names += new /datum/episode_name/rare("A COLD DAY IN HELL", "Station temperature was below 0C this round and threat was high", 1000) + if(locate(/datum/round_event_control/antagonist/solo/malf) in ran_events) + episode_names += new /datum/episode_name/rare("[pick("I'M SORRY [uppr_name], I'M AFRAID I CAN'T LET YOU DO THAT", "A STRANGE GAME", "THE AI GOES ROGUE", "RISE OF THE MACHINES")]", "Round included a malfunctioning AI.", 300) + if(locate(/datum/round_event_control/antagonist/solo/revolutionary) in ran_events) + episode_names += new /datum/episode_name/rare("[pick("THE CREW STARTS A REVOLUTION", "HELL IS OTHER SPESSMEN", "INSURRECTION", "THE CREW RISES UP", 25;"FUN WITH FRIENDS")]", "Round included roundstart revs.", 350) + if(copytext(uppr_name,1,2) == "V") + episode_names += new /datum/episode_name/rare("V FOR [uppr_name]", "Round included roundstart revs... and the station's name starts with V.", 1500) + if(locate(/datum/round_event_control/blob) in ran_events) + episode_names += new /datum/episode_name/rare("[pick("MARRIED TO THE BLOB", "THE CREW GETS QUARANTINED")]", "Round included a roundstart blob.", 350) + + if(BLACKBOX_FEEDBACK_NUM("narsies_spawned") > 0) + episode_names += new /datum/episode_name/rare("[pick("NAR-SIE'S DAY OUT", "NAR-SIE'S VACATION", "THE CREW LEARNS ABOUT SACRED GEOMETRY", "REALM OF THE MAD GOD", "THE ONE WITH THE ELDRITCH HORROR", 50;"STUDY HARD, BUT PART-SIE HARDER")]", "Nar-Sie is loose!", 500) + if(check_holidays(CHRISTMAS)) + episode_names += new /datum/episode_name("A VERY [pick("NANOTRASEN", "EXPEDITIONARY", "SECURE", "PLASMA", "MARTIAN")] CHRISTMAS", "'Tis the season.", 1000) + if(BLACKBOX_FEEDBACK_NUM("guns_spawned") > 0) + episode_names += new /datum/episode_name/rare("[pick("GUNS, GUNS EVERYWHERE", "THUNDER GUN EXPRESS", "THE CREW GOES AMERICA ALL OVER EVERYBODY'S ASS")]", "[BLACKBOX_FEEDBACK_NUM("guns_spawned")] guns were spawned this round.", min(750, BLACKBOX_FEEDBACK_NUM("guns_spawned")*25)) + if(BLACKBOX_FEEDBACK_NUM("heartattacks") > 2) + episode_names += new /datum/episode_name/rare("MY HEART WILL GO ON", "[BLACKBOX_FEEDBACK_NUM("heartattacks")] hearts were reanimated and burst out of someone's chest this round.", min(1500, BLACKBOX_FEEDBACK_NUM("heartattacks")*250)) + + var/datum/bank_account/mr_moneybags + var/static/list/typecache_bank = typecacheof(list(/datum/bank_account/department, /datum/bank_account/remote)) + for(var/i in SSeconomy.bank_accounts_by_id) + var/datum/bank_account/current_acc = SSeconomy.bank_accounts_by_id[i] + if(typecache_bank[current_acc.type]) + continue + if(!mr_moneybags || mr_moneybags.account_balance < current_acc.account_balance) + mr_moneybags = current_acc + + if(mr_moneybags && mr_moneybags.account_balance > 30000) + episode_names += new /datum/episode_name/rare("[pick("WAY OF THE WALLET", "THE IRRESISTIBLE RISE OF [uppertext(mr_moneybags.account_holder)]", "PRETTY PENNY", "IT'S THE ECONOMY, STUPID")]", "Scrooge Mc[mr_moneybags.account_holder] racked up [mr_moneybags.account_balance] credits this round.", min(450, mr_moneybags.account_balance/500)) + if(BLACKBOX_FEEDBACK_NUM("ai_deaths") > 3) + episode_names += new /datum/episode_name/rare("THE ONE WHERE [BLACKBOX_FEEDBACK_NUM("ai_deaths")] AIS DIE", "That's a lot of dead AIs.", min(1500, BLACKBOX_FEEDBACK_NUM("ai_deaths")*300)) + if(BLACKBOX_FEEDBACK_NUM("law_changes") > 12) + episode_names += new /datum/episode_name/rare("[pick("THE CREW LEARNS ABOUT LAWSETS", 15;"THE UPLOAD RAILROAD", 15;"FREEFORM", 15;"ASIMOV SAYS")]", "There were [BLACKBOX_FEEDBACK_NUM("law_changes")] law changes this round.", min(750, BLACKBOX_FEEDBACK_NUM("law_changes")*25)) + if(BLACKBOX_FEEDBACK_NUM("slips") > 50) + episode_names += new /datum/episode_name/rare("THE CREW GOES BANANAS", "People slipped [BLACKBOX_FEEDBACK_NUM("slips")] times this round.", min(500, BLACKBOX_FEEDBACK_NUM("slips")/2)) + + if(BLACKBOX_FEEDBACK_NUM("turfs_singulod") > 200) + episode_names += new /datum/episode_name/rare("[pick("THE SINGULARITY GETS LOOSE", "THE SINGULARITY GETS LOOSE (AGAIN)", "CONTAINMENT FAILURE", "THE GOOSE IS LOOSE", 50;"THE CREW'S ENGINE SUCKS", 50;"THE CREW GOES DOWN THE DRAIN")]", "The Singularity ate [BLACKBOX_FEEDBACK_NUM("turfs_singulod")] turfs this round.", min(1000, BLACKBOX_FEEDBACK_NUM("turfs_singulod")/2)) //no "singularity's day out" please we already have enough + if(BLACKBOX_FEEDBACK_NUM("spacevines_grown") > 150) + episode_names += new /datum/episode_name/rare("[pick("REAP WHAT YOU SOW", "OUT OF THE WOODS", "SEEDY BUSINESS", "[uppr_name] AND THE BEANSTALK", "IN THE GARDEN OF EDEN")]", "[BLACKBOX_FEEDBACK_NUM("spacevines_grown")] tiles worth of Kudzu were grown in total this round.", min(1500, BLACKBOX_FEEDBACK_NUM("spacevines_grown")*2)) + if(BLACKBOX_FEEDBACK_NUM("devastating_booms") >= 6) + episode_names += new /datum/episode_name/rare("THE CREW HAS A BLAST", "[BLACKBOX_FEEDBACK_NUM("devastating_booms")] large explosions happened this round.", min(1000, BLACKBOX_FEEDBACK_NUM("devastating_booms")*100)) + + if(!EMERGENCY_ESCAPED_OR_ENDGAMED) + return + + var/dead = GLOB.joined_player_list.len - SSticker.popcount[POPCOUNT_ESCAPEES] + var/escaped = SSticker.popcount[POPCOUNT_ESCAPEES] + var/human_escapees = SSticker.popcount[POPCOUNT_ESCAPEES_HUMANONLY] + if(dead == 0) + episode_names += new /datum/episode_name/rare("[pick("EMPLOYEE TRANSFER", "LIVE LONG AND PROSPER", "PEACE AND QUIET IN [uppr_name]", "THE ONE WITHOUT ALL THE FIGHTING")]", "No-one died this round.", 2500) //in practice, this one is very very very rare, so if it happens let's pick it more often + if(escaped == 0 || SSshuttle.emergency.is_hijacked()) + episode_names += new /datum/episode_name("[pick("DEAD SPACE", "THE CREW GOES MISSING", "LOST IN TRANSLATION", "[uppr_name]: DELETED SCENES", "WHAT HAPPENS IN [uppr_name], STAYS IN [uppr_name]", "MISSING IN ACTION", "SCOOBY-DOO, WHERE'S THE CREW?")]", "There were no escapees on the shuttle.", 300) + if(escaped < 6 && escaped > 0 && dead > escaped*2) + episode_names += new /datum/episode_name("[pick("AND THEN THERE WERE FEWER", "THE 'FUN' IN 'FUNERAL'", "FREEDOM RIDE OR DIE", "THINGS WE LOST IN [uppr_name]", "GONE WITH [uppr_name]", "LAST TANGO IN [uppr_name]", "GET BUSY LIVING OR GET BUSY DYING", "THE CREW FUCKING DIES", "WISH YOU WERE HERE")]", "[dead] people died this round.", 400) + + var/clowncount = 0 + var/mimecount = 0 + var/assistantcount = 0 + var/chefcount = 0 + var/chaplaincount = 0 + var/lawyercount = 0 + var/minercount = 0 + var/baldycount = 0 + var/horsecount = 0 + for(var/mob/living/carbon/human/H as anything in SSticker.popcount["human_escapees_list"]) + if(HAS_TRAIT(H, TRAIT_MIMING)) + mimecount++ + if(H.is_wearing_item_of_type(list(/obj/item/clothing/mask/gas/clown_hat, /obj/item/clothing/mask/gas/sexyclown)) || (H.mind && H.mind.assigned_role.title == "Clown")) + clowncount++ + if(H.is_wearing_item_of_type(/obj/item/clothing/under/color/grey) || (H.mind && H.mind.assigned_role.title == "Assistant")) + assistantcount++ + if(H.is_wearing_item_of_type(/obj/item/clothing/head/utility/chefhat) || (H.mind && H.mind.assigned_role.title == "Chef")) + chefcount++ + if(H.is_wearing_item_of_type(/obj/item/clothing/under/rank/civilian/lawyer)) + lawyercount++ + if(H.mind && H.mind.assigned_role.title == "Shaft Miner") + minercount++ + /* + if(H.mind && H.mind.assigned_role.title == "Chaplain") + chaplaincount++ + if(IS_CHANGELING(H)) + episode_names += new /datum/episode_name/rare("[uppertext(H.real_name)]: A BLESSING IN DISGUISE", "The Chaplain, [H.real_name], was a changeling and escaped alive.", 750) + */ + if(H.dna.species.type == /datum/species/human && (H.hairstyle == "Bald" || H.hairstyle == "Skinhead") && !(BODY_ZONE_HEAD in H.get_covered_body_zones())) + baldycount++ + if(H.is_wearing_item_of_type(/obj/item/clothing/mask/animal/horsehead)) + horsecount++ + + if(clowncount > 2) + episode_names += new /datum/episode_name/rare("CLOWNS GALORE", "There were [clowncount] clowns on the shuttle.", min(1500, clowncount*250)) + theme = "clown" + if(mimecount > 2) + episode_names += new /datum/episode_name/rare("THE SILENT SHUFFLE", "There were [mimecount] mimes on the shuttle.", min(1500, mimecount*250)) + if(chaplaincount > 2) + episode_names += new /datum/episode_name/rare("COUNT YOUR BLESSINGS", "There were [chaplaincount] chaplains on the shuttle. Like, the real deal, not just clothes.", min(1500, chaplaincount*450)) + if(chefcount > 2) + episode_names += new /datum/episode_name/rare("Too Many Cooks", "There were [chefcount] chefs on the shuttle.", min(1500, chefcount*450)) //intentionally not capitalized, as the theme will customize it + theme = "cooks" + + if(human_escapees) + if(assistantcount / human_escapees > 0.6 && human_escapees > 3) + episode_names += new /datum/episode_name/rare("[pick("GREY GOO", "RISE OF THE GREYTIDE")]", "Most of the survivors were Assistants, or at least dressed like one.", min(1500, assistantcount*200)) + + if(baldycount / human_escapees > 0.6 && SSshuttle.emergency.launch_status == EARLY_LAUNCHED) + episode_names += new /datum/episode_name/rare("TO BALDLY GO", "Most of the survivors were bald, and it shows.", min(1500, baldycount*250)) + if(horsecount / human_escapees > 0.6 && human_escapees> 3) + episode_names += new /datum/episode_name/rare("STRAIGHT FROM THE HORSE'S MOUTH", "Most of the survivors wore horse heads.", min(1500, horsecount*250)) + + if(human_escapees == 1) + var/mob/living/carbon/human/H = SSticker.popcount["human_escapees_list"][1] + + if(IS_TRAITOR(H) || IS_NUKE_OP(H)) + theme = "syndie" + if(H.stat == CONSCIOUS && H.mind && H.mind.assigned_role.title) + switch(H.mind.assigned_role.title) + if("Chef") + var/chance = 250 + if(H.is_wearing_item_of_type(/obj/item/clothing/head/utility/chefhat)) + chance += 500 + if(H.is_wearing_item_of_type(/obj/item/clothing/suit/toggle/chef)) + chance += 500 + if(H.is_wearing_item_of_type(/obj/item/clothing/under/rank/civilian/chef)) + chance += 250 + episode_names += new /datum/episode_name/rare("HAIL TO THE CHEF", "The Chef was the only survivor in the shuttle.", chance) + if("Clown") + var/chance = 250 + if(H.is_wearing_item_of_type(/obj/item/clothing/mask/gas/clown_hat)) + chance += 500 + if(H.is_wearing_item_of_type(list(/obj/item/clothing/shoes/clown_shoes, /obj/item/clothing/shoes/clown_shoes/jester))) + chance += 500 + if(H.is_wearing_item_of_type(list(/obj/item/clothing/under/rank/civilian/clown, /obj/item/clothing/under/rank/civilian/clown/jester))) + chance += 250 + episode_names += new /datum/episode_name/rare("[pick("COME HELL OR HIGH HONKER", "THE LAST LAUGH")]", "The Clown was the only survivor in the shuttle.", chance) + theme = "clown" + if("Detective") + var/chance = 250 + if(H.is_wearing_item_of_type(/obj/item/storage/belt/holster/detective)) + chance += 1000 + if(H.is_wearing_item_of_type(/obj/item/clothing/head/fedora/det_hat)) + chance += 500 + if(H.is_wearing_item_of_type(/obj/item/clothing/suit/jacket/det_suit)) + chance += 500 + if(H.is_wearing_item_of_type(/obj/item/clothing/under/rank/security/detective)) + chance += 250 + episode_names += new /datum/episode_name/rare("[uppertext(H.real_name)]: LOOSE CANNON", "The Detective was the only survivor in the shuttle.", chance) + if("Shaft Miner") + var/chance = 250 + if(H.is_wearing_item_of_type(/obj/item/pickaxe)) + chance += 1000 + if(H.is_wearing_item_of_type(/obj/item/storage/backpack/explorer)) + chance += 500 + if(H.is_wearing_item_of_type(/obj/item/clothing/suit/hooded/explorer)) + chance += 250 + episode_names += new /datum/episode_name/rare("[pick("YOU KNOW THE DRILL", "CAN YOU DIG IT?", "JOURNEY TO THE CENTER OF THE ASTEROI", "CAVE STORY", "QUARRY ON")]", "The Miner was the only survivor in the shuttle.", chance) + if("Librarian") + var/chance = 750 + if(H.is_wearing_item_of_type(/obj/item/book)) + chance += 1000 + episode_names += new /datum/episode_name/rare("COOKING THE BOOKS", "The Librarian was the only survivor in the shuttle.", chance) + if("Chemist") + var/chance = 1000 + if(H.is_wearing_item_of_type(/obj/item/clothing/suit/toggle/labcoat/chemist)) + chance += 500 + if(H.is_wearing_item_of_type(/obj/item/clothing/under/rank/medical/chemist)) + chance += 250 + episode_names += new /datum/episode_name/rare("A BITTER PILL TO SWALLOW", "The Chemist was the only survivor in the shuttle.", chance) + if("Chaplain") //We don't check for uniform here because the chaplain's thing kind of is to improvise their garment gimmick + episode_names += new /datum/episode_name/rare("BLESS THIS MESS", "The Chaplain was the only survivor in the shuttle.", 1250) + + if(H.is_wearing_item_of_type(/obj/item/clothing/mask/luchador) && H.is_wearing_item_of_type(/obj/item/clothing/gloves/boxing)) + episode_names += new /datum/episode_name/rare("[pick("THE CREW, ON THE ROPES", "THE CREW, DOWN FOR THE COUNT", "[uppr_name], DOWN AND OUT")]", "The only survivor in the shuttle wore a luchador mask and boxing gloves.", 1500) + + if(human_escapees == 2) + if(lawyercount == 2) + episode_names += new /datum/episode_name/rare("DOUBLE JEOPARDY", "The only two survivors were IAAs or lawyers.", 2500) + if(chefcount == 2) + episode_names += new /datum/episode_name/rare("CHEF WARS", "The only two survivors were chefs.", 2500) + if(minercount == 2) + episode_names += new /datum/episode_name/rare("THE DOUBLE DIGGERS", "The only two survivors were miners.", 2500) + if(clowncount == 2) + episode_names += new /datum/episode_name/rare("A TALE OF TWO CLOWNS", "The only two survivors were clowns.", 2500) + theme = "clown" + if(clowncount == 1 && mimecount == 1) + episode_names += new /datum/episode_name/rare("THE DYNAMIC DUO", "The only two survivors were the Clown, and the Mime.", 2500) + + else + //more than 0 human escapees + var/braindamage_total = 0 + var/all_braindamaged = TRUE + for(var/mob/living/carbon/human/H as anything in SSticker.popcount["human_escapees_list"]) + var/obj/item/organ/internal/brain/hbrain = H.get_organ_slot(ORGAN_SLOT_BRAIN) + if(hbrain.damage < 60) + all_braindamaged = FALSE + braindamage_total += hbrain.damage + var/average_braindamage = braindamage_total / human_escapees + if(average_braindamage > 30) + episode_names += new /datum/episode_name/rare("[pick("THE CREW'S SMALL IQ PROBLEM", "OW! MY BALLS", "BR[pick("AI", "IA")]N DAM[pick("AGE", "GE", "AG")]", "THE VERY SPECIAL CREW OF [uppr_name]")]", "Average of [average_braindamage] brain damage for each human shuttle escapee.", min(1000, average_braindamage*10)) + if(all_braindamaged && human_escapees > 2) + episode_names += new /datum/episode_name/rare("...AND PRAY THERE'S INTELLIGENT LIFE SOMEWHERE OUT IN SPACE, 'CAUSE THERE'S BUGGER ALL DOWN HERE IN [uppr_name]", "Everyone was braindamaged this round.", human_escapees * 500) + +/proc/get_station_avg_temp() + var/avg_temp = 0 + var/avg_divide = 0 + for(var/obj/machinery/airalarm/alarm in GLOB.machines) + var/turf/location = alarm.loc + if(!istype(location) || !is_station_level(alarm.z)) + continue + var/datum/gas_mixture/environment = location.return_air() + if(!environment) + continue + avg_temp += environment.temperature + avg_divide++ + + if(avg_divide) + return avg_temp / avg_divide + return T0C + + +///Bruteforce check for any type or subtype of an item. +/mob/living/carbon/human/proc/is_wearing_item_of_type(type2check) + var/found + var/list/my_items = get_all_worn_items() + if(islist(type2check)) + for(var/type_iterator in type2check) + found = locate(type_iterator) in my_items + if(found) + return found + else + found = locate(type2check) in my_items + return found + + +/mob/living/carbon/human/get_slot_by_item(obj/item/looking_for) + if(looking_for == belt) + return ITEM_SLOT_BELT + + if(looking_for == wear_id) + return ITEM_SLOT_ID + + if(looking_for == ears) + return ITEM_SLOT_EARS + + if(looking_for == glasses) + return ITEM_SLOT_EYES + + if(looking_for == gloves) + return ITEM_SLOT_GLOVES + + if(looking_for == head) + return ITEM_SLOT_HEAD + + if(looking_for == shoes) + return ITEM_SLOT_FEET + + if(looking_for == wear_suit) + return ITEM_SLOT_OCLOTHING + + if(looking_for == w_uniform) + return ITEM_SLOT_ICLOTHING + + if(looking_for == r_store) + return ITEM_SLOT_RPOCKET + + if(looking_for == l_store) + return ITEM_SLOT_LPOCKET + + if(looking_for == s_store) + return ITEM_SLOT_SUITSTORE + + return ..() + + +/mob/living/carbon/get_slot_by_item(obj/item/looking_for) + if(looking_for == back) + return ITEM_SLOT_BACK + + if(back && (looking_for in back)) + return ITEM_SLOT_BACKPACK + + if(looking_for == wear_mask) + return ITEM_SLOT_MASK + + if(looking_for == wear_neck) + return ITEM_SLOT_NECK + + if(looking_for == head) + return ITEM_SLOT_HEAD + + if(looking_for == handcuffed) + return ITEM_SLOT_HANDCUFFED + + if(looking_for == legcuffed) + return ITEM_SLOT_LEGCUFFED + + return ..() diff --git a/monkestation/code/modules/and_roll_credits/icons/title_cards.dmi b/monkestation/code/modules/and_roll_credits/icons/title_cards.dmi new file mode 100644 index 0000000000000000000000000000000000000000..9191e1539594f97bb009d09b422e9a9d63885868 GIT binary patch literal 495711 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
Y6EJO;y@oNhfvn_=J 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

#G=( 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

{>JxSO^A^V81w6E)MrWv42+JT=R+* z#Z#{w@^WdldlMQM$Y|INQvAE@*ZW;77kziynbo4BNblnVh&h`ONT%D)^Ik%@!smhd z#HO1kdwItJh_qPDf7$~!zIBEgg@5b6O@G?UOUsG#Kunw>1$dWcH>&%zo0$9^&Zuxb zW!3m8w&RchJezje=!wYhA+CL~mo%fC@vI|zI1yP3!0bpAWXmTa!&4kz4GKr4w%1*Z zWzFA`FM00OCh(c6*x}>eUm}9X2-QCl9KEicPryxug~Hq?nnk>vP(Kdj{xBVZ#Hv*= zEE3!Q-j~gSkoRUg@0xdp)GKCsm;#m~{vm`1>vq4W1(L&^TzUa2Ei5h2E!*z`ktalR z^iKw7%8&J{86)cUhI>}-aw&a1=G2}$S@D^mZR(>D?@eJXUa@|vTO}6# zX*=i)`P=Ya-|F^TQurMX4i1A?32(vC98j)^zkZK=2Y$^ZAmC!c^@(;(Ra-hSj@U6L zb?P9JQk?$DHdyBXk=SC$@GDl5fW@S4R3h<;U8jM$6e6^&azwFv^!+ZChzB;sAvL%%-(;H{x>pg$7;DR7E7A z-RAuz4n*)~qvzkxckEW52Mk=A*=>H3PG7a1DqRlvYk>=_#+vGeRtenEMDnu*ztEV& zVC&jE1Y~}aan=C2-}cUNW-ky0kEOfyr`pCArIGYjUcwKrR(oUb`)O6m`M+1ZF|kZK zcHJ-NfikjR`ClM*sx+2Hun0$37 z?eb*L)3HZDXr0NmH5tS2Hl<3}Sy{jZTg1sD_A8Ypa3&6yr^qzDP&6ci3tx-db>g5* zk&Q|X_Lf)ml3!p-9@ZHF9Y8I7oDG5v0?BrapcK}9p3E9bZHVb9#Tw?&U*_6$jo*+nZGtZ=`E3_ z_0V!jD5(7y*Kl>Ga&wvjG2zP7-Smypd`dBrq$Ur7w#0p29CVCXA507o81XIr5wQA$ zfK)D_CpiDKbuG5A(xN_=Dr8kJ3BbtAmE5_v^G)~|)$!OitWgn6$=PtXIi~;T`5bU` zhxI&fKP|7Q)|rr5C;lga{~gU4_L~nn=af3ksK^xlPKId0ZPVvY3!fJ7en&X+DN$v$ zovnm?)3x*a5IW967xrg$#uXNqD=eX113dvv7Z$Fb1(sR0W=Qx`}(|%~;%Ko6X zF$=bKC^-Ml@Xg2$LQc>ii0c-P`1+qRP*V3$waehgSA6D-#mke8&E4etbKGfK@!X&L z6I17_J?xeM3%n%{rLN47+rm{my^YYk;M2Voubm-b@eDGr>H3?~#2G$VX` zMR@(og?oYEILq6!j)SnJti%AV%2M`wUDrPUyeL`u`8e>a?6veh94b57Jh+H%!b5CJ zS9lx_qTrS5ydf|42Bk>Pk+w+_!?3$E=ErI9nU%&A4W+w=N0y@$Bb|m@mLt2h56GPC zyaMU5Oqbwl{hMxF#{^1-f4EA0g_G$Hmi&=Z2Esh6#TLGPezA&>sle3xoaBg;4zm@_ z%HeP>nr4HxrXNR2#T80WtHso&rE$3h=_|&75mz=?d1~J__j_vpWsJZ1J^(WzZ{muG zwbQPQ>6rv7+|Idnv83%-wnFL+!idadCJ8jBcrzY&z#N0e2K)l%waA#cQSFK&A*-Ed zs>F7fz4V(a{%P(gII89gpB7gqxh;pDt zp)-KiGiNVmAS-eeTZy^fM9SrB$79)*bcg{A1fNHr$g~!Cq(*rfcD82OxC|_;|F&Bw z+WXqCNF#%w%sZH`4DM5YpxkG+_E!$*oa1rwWYGFT0|vr!k@lzfDxYyFA^kfCc1?>HH0yN|;?lvvS% zmd{OqOg~t^OtthOGb-V*LJ$@|bgJwGhh=27As827ew#;4zB;zbstyWBwVJ`XnAIh2V*V zvLb4r;rr&PrRvDvEei_*2VI!kF3Va6oa(my`>i|GZCg(bLg;H2eJ73;Q#l`tAU3^X znrZr9_V4N1o5EU2rURUuYl9r1Y-=E)L9@#-5Ch|cxul#L8CPs{Qm8dKI# zrb-wiu5|nvM_}%n^$CejVt6OEk>iWRcgIfYk3c%Egl{p)=Ia!9R%eZ2sjFgkRC}ZQ zT;~b6A3k}p-?G_rTtNR5UR=z^2)jN6tJhVY7iOf(S}OOBR}$gn;mh|&6szCflus=; z^8G0l{F#b|{3fx#TB}`Ig%NxB?J~ujW$gILx_H!tTMaWs6DzK5aXT*}s8($xO@&W; zXMY)WB{%xo_p;pQ#CNm_lZf@a$-SFEuutOnrzf#zmlin$<2)jqe;{>lUiNVNsQG)= zmr_}Bf3e!+OF~3}oV)$%XC)Q6PTV)ORqW5Og!DqIw(56bP2xuRv8Irh%_I>Q-aY>; zPc_a;QTw2iM7@gdO9iF(+y-0*S0VN>Oig6>A(@=bC^YN6*oWV?fbH#klOxh>9v|RT zPP|I3YcDYg)~`JYR$@9;yy3I>N-$p@muQa)7=gHQpf`je8G9uWJ9fh6eAD!Hhj9@T zH+Y~cGF7eDg?=|7Bi}Fp04&(gA;9JwoXV@e>5tLX8m+nORUvS2A%fmV#xi{ukC0xD z7xFx7{#gPjV-g;w-Qt;pZ_;!axH7u zmKIq}z>TGRxA;W!D=Bv!5p#&#mBR0^%e?{O>%YZPRNtN>L@zZZ=-+M!ZRW>0k7O!v zsbXI};ER!TpGAQi$Ja6GRe2%?==UImlQ}yV)}+%_tTz^1GrP7RLL07Hm2%f|$L!M~ zIxnpHN_C&e#ZHEN{*I_m@2AO15>-);Ek-XRrZrn(u0HdXkT*{m|PB|wNl*^ zM$S6^T#$=TxDp1E@3Hd$R_dD}3;cAsh%iw&SDg(RN~H;rDR+4WOOs$ZyLhKVvTWt|Q*q;I{8A%}bT+oEpaXJ-`SkchU#0-=B~8`D)vZ z5{Qqj@&vZAqw_@`G)Xxrf=ewPQ`jL)_Wc9z7bP#DAFE;^G-6<6ZL%`HE+?Fwb-4U9 z{IyL>b=f05>hI(6tI6N9kwc?}uB4W}{53N@I7qte z98Jyk>S2!#*_5A<7ytfa=1GU?pI>6jN6e6*2!VQksDIcxh~+p;)4xxk z`|k9r2X>TJ*!R!sF~8oV}vi#3@>uMcu0^-Y!Ne$A8h_3kB+ zCU%++2T%ss&0+qFWzG%pue&feUidk3!0#%XG}l0{uw$_5+HVYJ$ZUW9P%!70?1Ogw zXu`iXYvuLzUt1YWmqRN8k89707;`x6i5+QsY5PTR0mYM}VaG(-*wwSnvqLbGk;w+! zeY$ec^NvY}0bN&5W-Z0rFAkZo!k^|4LaQI572xbyx$JZ_Txko&HxJ#?IM0;xx1sOsLFOX@( zUX@LUTb;7Wve+xvl7SZbC(>j=pW+rC58LEp9G_ zfp@XQ>CE%6_Cx&BkKSP={LZHh>B^uBOpO5BXTozb?58d};w{`}!*J45m2%%Va0?9k z&MF>ynnJ~;1(qs|?Y$}o=-d1{ti}!W-8(n|ly1eAKj=bcnZ7rJ?{ihMCn)?~2W)kJ z`Jjdj_deaZXvk`HDQ#BIiU&-`^TrxC9El_mXs??FsgWJR+Fj)x9SUDjZiYbM1X~>A z&)DZXdFwM3kB>8jtOBpk4~f}ggB8QityV8*;|I#kDu`EwS8&_*TLs>YY{dF0c(2^% zEo}hz_WgDz0C;>SKI?*SlEUa~Y5|+Sjpm)9vIYgqLuj@gDo9cDT<+#?SC)`p-hRyg z9+6ngm>cg7bFZ1T!qcgb?ulT43f+HjSG#U#=-&@4>aLr|*{~2$?i{-;2k%swBkUk` zf+5&9Yn;SNMDKb=y4z6HHx+B9P^(E{Dwu5hYY>LGY{2sWUH~!a*utP6<`pBp!2T03 z`FmCI_AqI#qs^aoG)I!CG|vZI92<9V?ARzeC<>6Nv>dhl=;5eI8Nur3Xf|M%6!oF8 zYlK!Fk%qq20t^dV@NnZsDK4p14IHhM%8H-8-+RD8>2eo$4u5{ zIti7!jUp!Y0|@Eoz5q46=LGGtC-K??^R^?!ugklTA%8u5J9mdLXQURP>QSvg=O|K2 z$H6|(ExZ|?4%`cQt zbtmx9TDCxJ<&f0M83-mRqHrcYuhplro;vWCDzdn%@6Cj_2(#jTuvgK20^SKII`=N3 zFa*TouWD%l%9}_jxhk2ftg4T)XH;7-D4HfP3SHw1(|Un(duj$;=Y(d?nN3r&QKHFk zpGTfC=Z1nbqF2)GYb3%bkEX9ink-e^keaoeBzCMcMeNUUG{P&N_Bhz}vc+(in3(>t z{ejKfG|1RZ8UdB1l~o+g(rYkWm=?&~bYYQu74Zjac&`=YezFp4-g=0NXVEE&lPWy2 zI$gveqQNE;vS4=|%Q;cehmo&bBnH^2#sue_1}#CpE)00^jw{A?KYs-X^N%ZjN?{N9 zuSng_*(V_Bnd(YPHbyxTWuS%UeLVklzm}U{7(NRTD?Fgx+TQNjcxRgkI%8-A%qr*c zz2xQ5E3W7@)gS0istS}GUoJ}fBX(!fg)u2PgS`wTco$Xce_Zut~!^n*H~@AsmZRgufdu>)osfV+}F(+Zj}HpPQUwtxX>6 z+;Lp;Ur(C&!0ad3JBWSBjNYybIMO|P$gpoI>#?)is1*8ZiUMt8TEBMlA(s9J7VxY* z<``A)Ggcu~FkQq9xzz5tKWq1EG^O{#>n+VEbFUBE=Z`~d67A)XNGIIZ0zAs~#j_J7c!aAJ{E24T zb0sX`0i^At(cMt)ra1t-fC-}vm6GxAg~`)H2~+f4U815bLP*G#{qF!iZT# zz3sV+)l7k0-Nb6U+2WF+L0Q!50$1}N6_W6hL-3KgqQSr8?@J-&a#&QOZ?sUK_IT^* z;D$Kxpj4NYVBOE-EKrO#(gFIM73C>8Auvt6I}zixvyF>(Cpe$DRK!MKF~DE`B;eTs z4UL|16AmvMni>or%^yMnYw8ssyQ?^(LEkAfB|Hif<@RNO`IrX>5rv#^*rL7 zc(UL7XNmPD4=>XD^fNZz=!a{Qip7d1*b~=KCQz8a{idf@vADR1z}#M~gLCt-#?LC) zHYy-ba~#%sVww;88ES)1woB02UfXuW+%-}~wn2>qD=_xhgU21#zh;oF*_Jt?hwm__wZ1IujY`J$V?ba(~?%3i7^@cmc6)>b!D5cG;z?;?1# z!cD9Sdajt}Y6+rlQY}%vW4MV%rZ+Hphe+$*V`+^;$K^HSGP1t2wHX6p9Nfg0?C1Wa z%+D0=yzo?*tZAoz~HnB~y#mgLn~{y-Kj832gomIEgKE7dKF2OaDB(XiwYpR1RR^-o^bPMj)GO z|IP?}a*9-dgn)D@J;xgQ>(LL&Qq&(p$gXje4c&T|KTq^fwVrtW_C?>MYy$9zBD$;< z!qC0ez4-&&gcUcSvpa_vm6!N*fS%H?Cks+3!xA{+4li@{7zi&=!RY?Lm%{>5c0Kmw zMR{MQuY6QVCj9;E9N+uo7vi@o5M6@B8iNKi?cKOoY>{yUK90L- zZEL$a{WsnHFa7R4@3V%acO+`js$>dx?pk|8NR_V9`al4skz6Q?tzAMNeXjs~QShpl zqY@P9=I7lBINmSD0D83A&?sc-Ci7YLr)ODlp46tWe!EELt*ju*Ir+K*%^MQ9ZSjlD zZhv6a0rhuNbc=-m>yiG3VVgg8Xi%2tF&g)~GVJ9yEw<aGr)+gwlZPBy6>Rv5X0ugAXwuQr0-#lfOcY8O_JWkW7q0`a4#s z$auS{Bu`duhA`ysiJmK#@bn1XW{voIgY&~$dw-U&s4Zo@ z-ILibr0Ejy?N19rP;YE6r`$?k`R&X`^g0}V{)1P=X~zV?SQGuyATny- zZ`~o+Tk*C0j-^yqVIA=F*)!uupY-TzL1pC5njY&CPFaA=!ADV%2JR)$iPJOJR8$aI zm6J9#P#lWGy4Jux>%mx(!s&c7*wqP|=QPOBan9->?#CjNhg&^w!TARa99KBA-fbCR z_I?TlLLO%d->>O>GWh%@H=4TVXT>Jj6_Z8iNhp15b*BevLhFkDX_w>q-23n!g%cgL z<}Pj*#aBUWXMW9LZ`Zy$He87=b}+VjG-GT9`=6hq=Ou}I2PR}U8U0p*HrenaADa%^ zFvWEe zd;(!Kz?2MtK5;m!ZC1XX~-KO#L zk5M-{1+fM%Fk$CsI^XeCVscV{QUQrkETvU=-ZC?HG!Dv96|wsPxR(RppP<*WS2<9aw}wds=yh~b&oLT02hb|#nA4rr!{l|&*pps zn-<@yOEH*fm}^oii}Jol?6`MJ;V9iaR%;U7kj%&5`NS08WG!A0_LKQno&c8l84W9p zQ{=>#WLOawg)9O_LpdtN3(N1>{-p|(bYoVm9pwz96sSW=;Ow^0OX3|;phy^bTsbELMyaWVIlWfUx*On zB_Xi06w%4CdQ$zyt7RiI_C#?P(d&&_W!9+nnP5DWYl7pO)$ zWsDaVzue*jFy=pUhc!s=sP93pPX^!A6c|{2j}=d=VW(A#ZuO!)^ZhG`jZ9cHX75UL zUz!>5^38*NdwNsY<4;a}vSXl!4UNxpJpJ-cxv$5`+n9oAZLsCiU%7)7;O@4=EB`TJ z88ivsEbcV;xrn74jWym5ziX>tJ1V!Ma)y$$J+?X*lQ@bAVSy*L zVwm7O5>%b;y%x2wT}KwxVnev-(vBWt-EJgPs2TLPy!if5y4bSn-aykYQ>apJ3tf1> zztA;K|gL6>T_1?+mA1*4`GCvxoacQr~hVQnKa`e2$ckp2A5`59*5L*Q;haTgUM)Li9e z&4(4`f7&;$40Wf62fWv?gPb!raUm3=HXqo{Y_Ev~GG1`DKif@NY%M_(^57JzA8G^A z--w9ftgvc0L+*sLN_!7qAJgU|>4$PQCl?PipIzZJjny?$|5BCma%O2A1UTRB!eSOt zM=ZPQqQtAmv~NWUNim`FLF_=6JMy5BNg8Xt=zg49C`T^H@HYX*JS)Dno1r zn17RCRtI)WWSBdd7GB=*9#fMbHEpI;UX;cA+EfO}MN|0?9MF@S6JvaEnc7g=`7E5X zgbSTlX(Wj_=ee!cxV)dq?ds_j+@)ZjYLl2VA@C!4n0omV?lc!3>&Nc3jg!+lqR!QG zb%0^Wl`k|);Z-BCjdpM(WPhLa{xsD+4#$~t(`Ha`8!aF6!m(QmtrGriNIdy3r+8h7 z?YyC>pHzxPe#Y+1RjG3Mv6gkuR+b6fZs94NcTA8#J_*2*fAN}R zW$=jmy){q3qsuBlKwd_0;h z?%EgTx!6FUbXAjUn029%JPxUz4J9H#TnV=GEX9AOP{Q~eJ)4iHftfNsQ+!SKRdcQk7TiZk5*Oz?4aVZJjh+7paq|1|L4UHAG^#cC)NRM_5rmX zS?9r^$f;*l04+}pb`*iPpN|jtZQ#9)Dm=K7)377y$LmjG!Bm048~9+WQe<0PzJ~jR zTAX793_d7T`kL|B=9O_-197+rcdciCw-EZ{41Hju@?*~+v!&;nYzTNbWd$MZUNCaP z7%*>e`$hm#S{eLlp+vy%vD`R;ns&<4g5d22E|9Uv`u@?v1n+dsA#Fd}2mWofcn=O+ zmAtO>{y-kx`%Nk9S`HXO5+C^s`w@pFO12NXqiW;c$8;RI&l|Sg@)cImF484Imer9T zc6&dC6D!SEB}p!=eF#1RIu)+VB>TqEQS*$UQVor}c)@APqrT}hAX)t3&~Kb_!z>2GX)L1J(L|wX9z2p_`N)F8sJ%ylNumnjxTo=# zr`E)bP!{I1>GAP#59WLQDh^vU!ra2Mv$bt&=wkVTzMtIOLQb;<&V$ z2@d@>f>PbVDh*@+ZB~bs@A1Chg9-2X=BHE+q~w8X{RV419xjETv6myW1w5|-8Bu0z z)pT7uBy*LpzkEP5URL0|ecW4@##r^PHoRxoE36qy@|)$un2=v-K?BOgj{9=&-hEh+ zz8e!d2!YIaxH80u-R^(sQm+|fBR(ou6yHo5mYD+WR1t*^DCEl`2Q?wUWtCYoiEqoq~$v2k20A9uzF6+Jk}4*24}Z->8~ zQb{9vuQR@lOs!w28yP2KlKU({O=cSoX^}|j6U;Nt)_atgYn2DO1dmKuM&E#y#0_uy z#g?jgWsW6pEYRX7ybR=#Ba0W%eZCCL&xUgA&RI` zqVsO|&fjN9yUXC9w7^~GrMDaWeL~nZJpta&hL+$r4qs|N0e)T z)g#$&QFAuiYMD>%t7^O>XbjgF!v&5Ne^vlothQ340+z5n7>Z# zsP)@PPP)tyHf(i$ow8Ido*0)Y?OnZlJgE5;zaSnH%05%)5^npqkLaGJIF~)rk!3T^ zc1|ss(l5`N$I;V*_zR|ctH5c0rN1PzIhKUhfBs?nIHZ5)YFaNVRTEO^reB?n%A$MJ=^=nye`h>e*4QZHVX|XJe`JiCk&$Fs zgF)r55b3l>4|qMfopZdGr(9l|2=zY{>aZ_a-u>v*ea}H4eNYU_dlly4JE#L*7zDc#L8eAfW@Et+dLZ7OSr*nroJ#plj1w)z*Gr1Y{2+jFq0pvGaqu*>71U= zOo00M`R=2F=DY9efAqsWSq0$?0H|M7^`dp9E9YDH50tB^qe{ek*Y2^g`H`}<)v+B~ zoSt-2tfY71qx68oe5B%PjB6b|82N5rj1`MNkSVP+TyfiS8|AhP2y#QpeC?3>6YK-X zk6u`5b5PH>`1Q0%rI(~C{GcA2c&QK)w)4C6#mgu$8f5I`aqko3n#i*yT|goLy5=T) zDFmAShXC5AjaLE38b-DXIIBb7$K)VLC4#_ofZJdcL!f%6T+(#*P!eY%3H9o-4FV4h z@w*Q%eYSULK?WRK4ZLNrpu}OB4cKJ*@Tp~di z`7GOs60e8OU*%b8g9E$nsAZ1c9~r1}P)1+27S-Lp8EBq+zxq{hpKp83z0l&q>i5p0TcrFN}xb(avvue z3A5G!u$BJ_KQ5vNtf_j~Yk7GAvoWJ;4Nl$fN=7M*znhoKnDHkzCUQ`ynUa=MQ}!#n zlua9{alhL{7!UuEFtX!`&%ZMp4ZIP=hdPw@`V>OzaUW>8J6G4p34f0^&535$eN{4L zrnRAs(8GRlM^Oxu2hYpsv4prEo8dJzd>u*f+|H9YWO3p3 zpIDxn?bxkclY(F>8e`TL#h25dQBDgZpaWIY4v=8l0aB8Gpy6B{_arA;(b6}S{Pp25>8 zboF{t&s;D~f1mJA>{$nWycH@e8~0~D@v=El8deC|FWdJ@DqEzur0ia6VoXs4f&{2W zzY-eAn*}dlvi5C4^uY`VFdp}q$YWi523UVK5NNQ6hvu)j|2&dK_e+9d_{Rquf7vhw zNPL?|yJv?7Xhm^T+}pR$uv#dZRte=z|IC%HDqjUm-_x96@1CTTf;1nBiUHn~cJ}BLNwZ{eMbFjJ?s6?MZI{0Z z!yM$}_Ij$=oCM%R8arBAFV-!m8EFE|)JVSuPpc|aZ|Q^Emf%?TJw~iZ+%)c_WvslW zxs?#<%HE%NENTmGZcpHKbkD6$P)Y`F?sBz8*`T+4q9_!PRgynxd4UALgDUVa1~7hP zyx>>3-17MxDu8UKQ1OS%hhc8cywd+r|D#F^HekWa1Z_n1z0$W0+737?quNgz!QzdyC{+sZ7nw!`Sa<*#oy{3zL4vb zXKCEl$I&Hh1ex=&2@F&C)E{>efg5>|NS{|9hqP$d<7GJ=D<9=Vi>Fqa!b>Dp8UK7- z?BNtcaPXKua4D9gjFtE)D%%>En~gYT5d?{KHiI$S~7*vW!f?RDkeq*D3X z|9b(XIH_fI$?x1}D;LvM0qB&2*qjMBv1QpEl12Dx$?1(3S<7`qi2mep_=D9ZjbGr@ zgTf-q7ubw^#)ZQM)I+rHwe5!5$LPiQvh$wRay;OF=wZpL1J4tAs=S*pYP^>|u9r*{ zQ%`EFmCc>0o$PHUWAIB$doU}SM7INBKiHV7b^moF!ZIZ>nkZGvqD+zqiZ57i5-I!W zMY^x0rjt;L@53G!XP-Qg)6-H zQ)K`&*i*kMN8SbJXIQyXP%E# zv%EYXjV&xG#+#saKBR)Y-(RRls>xZ@fBW^OL+qg?QZW7rszKi=(^+|O*x0m0QvGOF zsg|m)ay~}CoSYSxe0JJ~70`&&u;gIWHq0bkYs7HY=}rGKj+}QE(}{j`pTobU$P$-m zBifIgdnmd-wX#v)eMrrWR@DrTT&f<>rs)&p3~kQ;rYqcKXk0Q{z{r)qL6lKsY}{j+ zB{I#fD`D~OSxu$DrwbLzQ$O9z#pEHeOr1J%9dmaR#*KKoKCLR_*Ll?UA3Bn!4{eBx zY*tNypAVuNo8_yogEwF)GtSETz?d-Y_olV?MW*IGg)b$3V~^5U)l{CUI3>`GJ6Y7W zlvixfq-68;WZB?%+wIR^wU3x7gny$G;vOZ~^C%_oeR7}QH`B{lu*8^~3s)}VlRAFO z0(J`!O+ISI^~#P-GG0s5D0AbObkr(rVta2w>sh5JPW+i!bI^F6>_5MQ_kUG*cRVox zwA}m``T`1S;2h#|)BA`g+#!(9Utt}*Jp#>>jeaz8_kv9EdgsK|F)fv`g|9mQwt#ag z=R8Um1ZI`y5nw>O9ca?>-p|;Ki^uof9RKPJ#-f8q=YZ}Beu4jPhmYVQ^H-nnY-A-D z>(46eGnohslCN=Y=uU9i`jWpipT*fn4ml3NP-JJa(@WBV_Q4C>%v zSTt{6sd6%$YVX?hA5ST4qjmUya!e}`Bf-LZe5Y743 zQ$7KR39H!^J12N^>E_N1R}w>e^_oU11O+NwxqYgcrh#EAR`QY=L@QvkNCgWtaq$g+ z9bI?a7E6#ng|;zI>ghUG0Q8S5j67sgVFl;%aGxC~q%7l|6DXF7HHNVHEWvzgy$ft? z+LefkSIG}6J{Xz#MWq`0iKZMhr93o6Wj)bcSQQ66j@8TomTimgexxGOpdoal5NnMt z6sk=EJVs^K?}-&%vZ2!OqyN=lc@>Uw_bY-TEzTAkbpPzWlda0QA z0w8h|D(j;<6%dbmFX7SA9EbJ!5pxDiC5e1MDj^?5XTzUY0J5Ob^Z@YY!Kz_tR)9Fu zr?#X&V+)xu>hse?+!B9kdvt7W#V!)71ELRAlQ1e^kan{=*uqCZb(Eh{ZL2Nv}68 z&pCn0u<|m3dY5s=T0vm>Bv-C@;2{oDE4r2XHn*NO9O^Lnfi=2$7aVxba)cHRENkO*0C~Tv;A|hceh2=id)ruhJLMNoP zIv|i&pnzR7S!eToTgJ;Y31pTMIR_n8E5f7`bzDh>wVPmV!6`{#r(~K=CuVX=bu)8M zSniuCv!qElqZ!y_wUWd(r_#6;%u>fu8;EiMg~D1ECd*5c6;%=!$y#N@oFwNY9EUPZ z6)`glp`27ij)h8-ywy4vMAa5@P70F+BFkEw))JsR6A786%}y!;BS(Nt3&l{!aZXrU z6xJ3z@dC&+E=XsLN@7LEFiR0AlQ!8P%oB6ql(Gzj#H- zbJ__RhNYe5Dw8Yi=CV%Xcgt4LEVoKfUB zvMNZ)+TImkIBNzAF;QlT26&^)(xQ_(C$h94Octsn-btm|PA&)&C&V}c3t^2ES*D$q zPNoR~5CjfXng%LOWleQL1HvkY#sB4ja{<7{U3S^!)=z)>(+7R?o8KHZ-R-LdQ50d} z!iBi%s;fB5vis3LOI9bZ2Aa07gAcpg2>)S>;0KqlJkzs%sD~2P&uJrkzi=af>q?~( z-*eABD3wasv}qIKc(kO}FCPv*_+Whb%U{OCi4(sCpII!2F%oMG|9UV6XBwOiKd7BJ zO1a-)ct53a@QJ&IKDQ2DIWZ_Kg@8W*_@80+GZnxa;5*#gG{7~L2{5t{V%GuN8uB4A zXTZ0AtpI*WFRU}a^DxT>h31jZ;y4`9)ky6%Pz84=y!vW55^!H&o9HbG;5_yj=7#R` zU~KDK)ehiF9TS4O~7j!#(HfhHUW4OfbWORD2$s9fbrJyrUbrD20*j~phlr|0B|n=CL(;ERaOEmtNF9d+F835c-l`VgSZ!0?=1NPc? zl;iysfNAXnvxAbsf2{(hO&+Dp1^^=00>QlMguV?|!YeDQ=C?A)6d!u%ArzaM(bCd_pD(-}x_xI5 zyQs2!kpVDW2ywuh-~8r=$6B_01xP5M#uXL{g(G&~efJT!&$0~5pLh!7Lr5P5P-H-s zfUjq>W+W#qm~7wl;yG$ba8|2+vs#QdVoC1!2sjuu_^%&Q2886@)Pb8ONt4dFd!32TL}R$7EJR%Xdm06M7j zwaX-KVImb&D*;)Pku^3gw)TKoiY#rmN+%-A+E~bDX^a*oBPS(<$+U2;q@t)GoD0dC z=A@~un&t`yQW`5%he~42QYPfsSgBGLLKq#GG}qKDOd5pc-b}@nb{4Y2LMoNSfpAU~ zyEg3->ALU^Lh+SV+W+w7!j5hks&kgdXI6LaO>8N%9bW~|(A$!TW;GqwkzBDZNHpwI|>!>nWS1ZlJn2xYo z-ZKmHaZs&HQEBX0h!&@VOqjF@;AWL&eTAN`-9fZY8WRd*T9f9sI9KXv6~+`z5LSe< z897@tK_Ih2Q=f|CqEkAb=86?!2PRUvQcq51Spm-Fgmcmfkr&PtSSnIkqW1mVS7KHw zZ?%SsDV!kUnb(I(7|3!-W(3lZqJ+Cs)N|S}cWFpJuOEzC<0l1k-7ZbBunEp-l_olEX|n)JVKPn5MM0%BJ=fPWBiGl{s;dgh;s519^9T0XXP*g|UV16s|Ni&m&_iF635%B< z%nauoe)X$g;pUrf1~ackzkf;n0jP)E)qStl!S`!kjpS7wbtP7e!Pyj70QmgUrAw2? z9(xQMHf+Gkl`9+U=H*2Y1UT`;6LI$0XQQpH?c4CaL>j&`_{zpQj^TeZEPw}wEL(|M z_+A721O2L>$KjK1t-$c!8yn$86@M6EUmwQkA&Uc1Cu$h|gwRlh=r%qdk!Rsa%4`1pB{=><0Q-=@ zy_066IOAYIYDlpCK+o#612)Sg0OcC&XA```cD`d8n1S@syZ!|D=eedhS&#m9CKbRD zBhwHb%K^xII~ctBvbD>4*8^{!gONY14F9499lOE;h?d_axR#uu2+VBc|FsEz290yA zII6Na#fBAU0yy=E24yUOZxSI_=l}!mfT(vd0Sn8(?cKo6^F}$p+W}}F9#;t_@BOzT z@P-Jp`II|(o?iP4e<^k{u(zWoywT7tqVhs(Kc8dY(buNG4ypd~u=bd+= z(pRY~+#anQd%@}unEsmAyha1Q4-5D(zQYbX3|Z?86!tg*#Xa5xkih5MO4zV=HG~fb{U-plwzj@@(xj2E(zHSBq2b#^R1iYUdEM(8rBDDKTmA@0NLZr30Qf%n z#F~wuP@8Ze;0XdQqHV*{gBL<#4Hz`Cu9lSzLnd}or%`BfMJJQEDa|*5-~wrkE{~tI zCM@;Llv!qoxhgZ0$SgH*u1`mmuJWYG53>|brO`B*#&A-$Fw>u?CW?74ltGk#W*Db6m0HkD8oy1aYlvyTKno0TU;7Dx4L$QqOp&bdZH%kCUPR$egf7SRM4i*>PD@Q$;4RQdydpY1|xEOU=4c zYO`T3l36w-EcMP1&bG)j=@8cDgQ(J(tMs*iDRN4;JEf~4OG%n^JcyJ`Vm3igj@rgW zGD{<2Omo=R?H--~xefwDIH$;%Vo>Vc3q-wwt(L}CoRsVG-5YmeDL1Ml%Ii4llvx&< ze4!$oO_+pIadk?TFCZxQRl{m|icX>y;oMFtiK?nvNkOzh#nlO5*5vHOu&;Y(V%I{< z<>rlRn~Iy)A1t%9*tBJRDzaoxFsBR_O&iwkspHD{=C!MeVPE%jnI%nNwq$LqN+K1+ z)yV3gBC<3NOTD`ny1VwWI_M5dy{$4$CtIa@byR6R@JCn8bV7FNB%Yls^-gwLXGG9e z=_gc{Oa{9|S1V0AiJ;?Zdk|GSgtZpdj0XT6Ra(+QVFQ>&uD7c*sFrsFpj;5LlTwG} z-butP@;#f|m|#?vw1?GFexGx`)~BP2v`Q7ENuA0vLDo(c)@sVqOh@H$!epgoUq8Q< ziL9_D1<8WUlDy0^Et90fDV29p8evT=(oB*NLYOQgoAv6bT9j#mpjs{jl~N~xs^p9e z;_4n@U(a+M$3j>ugG#BDn8$-;MOxcd=-SvO)40v*pvy`Xku?y`wdObkjrGfh}n z#RTZ68aSn@LA5f2*ja$W;>NX8!&0drjG4$%6-1Uom@EX)#zG2REl2b=>#2UGajntF$DE&O1x8@_Y+ zY9z1f80d*rC$ZK8Sdk>jvx^oj!ov?gjKBTuZ@ByJyD=cF_7%mrapQ30kw@aAAN?qT zAow$Yw8DOW$%VjB54qk@39 zz=vXe6+XQ2c*5Z1V&v;^JqBlP?E>%<@?+`YFdu$~ejxrd%<)U)!$H1ZTeJeeAp~4Y z!;pvM?`<1=$e#sp2YkBw|DkO&7Y5kY>(JKD!NB_u)xR6dYS&>5I}WniPcH#KBOh}2 zTLMZ96xa_|x7u70@NoiuCV{sc_7WU?7Jv;xB3Ja0Rt|(c<8roh7S~PV-QNM;4UIdP ze+ICrZ3;x#gvnX_40}R%D+u@kdC}ET1l*y4cQ+0m^9_d3Aq?>Nxm%t&V-;}zry6Wu zf{(imCd`0f=iuLqod8UI?I_6*)&oeS0;I-))!uuy0AUE6I8t0O04xGfkpX0(9U;4o z47`DXA2xfnqZlpw!hnw2I`x+ua?QZZ=?%6w0PYG3kWJ&j%u%q{u>#)DZaD$pCSVF} zo8fg3*!N2;`8KG&Oac%G0Ba9C-~i+ssEWS(o$o-5n+AYji0jAv~jlkz$``X4iE$_JF4gfhoD1gL60AAnT z-i`?qMh=|4_10T~Vh3tj;GQ0^>Vt!`9fz@dyHr{ZdpaJCdy%8ANi1m#i)b`@bwwa~qJcN>Ij zMV1O_ZAGNXcxh7WP03v@3k%)C+IFLYb{4Wtn9K#0zG-A_AdD$8Q5P{=VN6w;M2jrT z^4*)K5px>$^~?|^BNOH-Dvk4CNZ~ApeZ9>rB!sn9l_Xl43@Wa+gD8cy1aJT%Ca}

Kd^EKqMj=00;uZ65{1_&YeVsX!tCKF1O;B0OdZO6prfx-I> zo4H${+uR6JjrD$ALGF6;fu&0s=NQF)ZRc!^p$iLwLAPRl|-RfAQIl1R)|rD zdeCIGOYIoBGlZVg8*}KDLSEA3qRm1PI{g$OWqw=n;!~pTI~cpOB$|rZ*!|VePA=~c z1G#0cpt|i0@(=Q}xerbUKH0L3Lv1w%T3a99zIh3@WT-{fWOkT=XIO}kgDy?*B#L@1 zs=uk+bAGKBTz^@sR_$bQGi>X*$N3f@O&1kQ$!B8YU(SN5jXay7B8FqHSL42*w3%5W z2yq9NiL|UuMSPnNt%X@+;b?9dW+z~{u`L=ES7#`lhSp8lkuBx%P9#x|$J>wt6cc8u z<3F<~>>E4x=MzlkSL*M9;_SeHSq*b@u1n$uO`&9h#HUuo4|?hxIH}-zdU}?G03UOK zfdhF}yC+IrJ>N(}p#=nfU?vk?MR31LPX!Q*XYz5X`IE03xYY-TAjAp1SrAfLlL>#4 zCfp{CbLoa|MgjCRY8@zHTX`oezqgaTAyr=D&o2>rLsDcCLuef@};rsVZ3d65z(LuTDw#X#dw=d5kbK@_Bx2)jjbt& z!S8ZjcTvppoK{oHR^m608{%#QV92tvEc>{qqyO9oMrZ+%yHSJ7Eo^THiMKwlH~Qw? z8XgCc=LRyT8mp_?^{-L4eb1GiokcIKtd6bI`??>r_r7lpME8Cil?3a5?0Y`3(<$!T z<`mjNJeuHo{H2v1BaD^##v>8hh)>Pa^s)jOi-Er-)Zj})5%zh1cO*zp=j?k^uuU4CQE2=`GcxHmM9i@NV;2KUy52oh z6--W|=!uT3kkaN-!f2aACWaDO;|JYLZtMQ}QDttYv@fYfDCnPjDCNV9K2;FmnE4Q( zUguu#?NZ|>jn>gRST<~aN8JRjfOXHMJhDjr^Bko z&qSe?M{%?)!HY=p1(^8$@r!>bw=#wQos6+OGrwp8 z&}Vk3pzIwUyhEJRIz3Cm*OCO#JeKwX>CpS6@#ghn3AmnE2Nm*mEdeB;{$ZOSK?xgj zLkI~M?-_MMFnc`-Y@|00Cxv*&eD(&m!c2Ycho+A{s)L$jRPAxr!7Lk7QLlZeL`heA z)aimsbLiEuS)lBYTdWAcW+Wc0&@A>BhuoZkrV0qt(vK(Ow3Zf#Xd808_Y)v<6 zyk7(^d!Dxweb}v*I}&~G5^q3uEIg0U6gy4EJKyel7~mMz<{iF_@!!+#H&=Rnlz)%_ z8p}IUjfR%?v+DtufB@|Nct(skjmw!xb*npWV%O<0kK1#0$|kP9zaDZE=%xaVQOzvJ z15Yg{B0`kYc@3K9F12^RgU&lTn#X?28JoYyY=)`l*!B} z_l~{ajbWeTCvtC6vL4?)O5kb)>!Uf>9AW(GTt_DTFHi4BJ3N4-5X%n*_qllmcXP!FEn-_P%$A{FSU1Avlf1dp)h zQkkT0&?|Ud# z^wId*MbpK_8id3M^Z0306a?{380=!}zFLhsmgzllZxN7kL15|d8NM87$EEb@;o;)V zn|gckwEM|}&2DvQcq<`!tgozK=Hr+wc_=hSJ;js z;(DkCd@uvCG8#IF28%uB3Q?j9|&(=Cqn^*LGVe3A!uZ@0ksTjeHL5=@ZCs(=N zM=l97-Sehb42ETD=oy!*D$mMOzp(|CwZxMt8n&&bq*DTWCn4`(wod5h?<`cw6!_OW z^JzHHGwv9L2PQBj7~B1PV<&^?ZW+p;y8rUDRM#U;x8D&H-Co9!kb6rSk`C|G&)!CD z*%XKdiG|~9UL=j7vY3o%zQnrawwB@insafWx+5)0mc5j$#@|79ZQDux{bq&M6pk7^ zteh{gA0HZQI`)r-*Pd+=7fjxb5EH9Jgf>Wc(k$ugai-suiY3^ZM24w9cYs1-#0L*M z{t6(JezkCS$d>#<;G+Jfn#CWbAmTZEMw2KeQPe&#kE}~BV7xFMZv%OrmB>%xELt2I zAP(|GZ=!w!E0V?Yd_2V0ecku|zUXUSpu3Jr-O8PQ3kOrKsSJ`c`z!%;!2U|@Bp|}d z0M{DV?4w?7V9i)Ydq;RnS4wrA(;}df#mhCkp;nA(1eb$S)0^d7t?ja>6en=38Fm}k zRY)B^Kuogtq42>4`D+Ay3k&ta3QgjppB2su$tasDGlD2&EG0^WJH%k!;bC-XTPrR5 zb2FZsx#S4NSUzob73Xk506)4qF%3xunV}J^QPL?d;574Pr{j-}xb;slIys~%e;bCD1yyspm`bffDyZ0-^bB0fw-}fN;Cx-7P80x89 z(?mcQ$QBh9b^XQa+8S^Q8?j5fQJUwN$#8`Irm#zVON4&G@p?_7^>1@n?|_cZ?Ehe7 zwYfE3g(?uJW!vYSsrr$LaHylT1N$d~azNaHW5W+D>9~1-?)gdTH;jS%54cvza<-tu z^NkNse+L;#R7`wUy?+)DPJ|l?DfOEbvr74EImI9SoBHuaNftDWt9IxoLE`4!-(t!~lw131pA+M+RoJ2L;(L)|@Jr zNZ^y$|7O>v_>QG#H&K2osczsH@V2~!^1*>LHWWta*Ipvr=S$H0^8Lc0GC*rmM{*8R zZJ(vEbUhmxAbR%Ce zb0@H2)UFV1f8uW-#Wv^I$GmpkbaLMJSh+@awUFW!H7wgtnsK zie#QpXNAOATw#JB@eu`{B>bp_8zohSs&D$~CrfW|yw(1DQff4xgGbcyx>bMX`v*k! z59l8-fm0FMP~yKatTc9P&uKVxdXAVi=8`)5djyv&Za;9N6J6K($C}QbNBzggof^$9 zx2;8KI!)f2g(jiiMdcZ39ImD+v*$lw zp0`FadB*q0ghoq?(9SB$Dn^>WDEH1rFnjx+5{iyyzr@@*;F~h!PBoG?f3C zh@bGiyaY6_bq~*BK%E6xY&nNB=nqeVULD=Oj-n}wC0(5Co+(SSwpUhP zgqrgAa9vma3r{~Dvp7K9QpOpIu}aFT;%LU97nl~arIfMS?Hm2ffv@+8rVH*Vt)2pg zMQI-OGk|r4pdd;CpL|oq1{5%Tt?h4dV?@}2qr9C6=Km%9Bnrl)ABZqDzzY{LJDf&4 zASFSZLCIJ*SVS_R-bRt^&uk%K&|M5fkn&dfa!i;Q9#9Ozeme~D^9iL@rm`Z+c4hZg z0n2U#NT7*7bDN1doSFmpz+3w2t0D5jt7MkUQ`>CdFbeNRDf^xdXfKS*b{QsEW6|?; z1qTpnqQabV7n!(Z`lyKlf(Ky?r4?90nse6ES;hWXMe#+2Q!+GQfjI+}^0c&Ib9}=u za)d?OtQC|^mI128U52f$rb^7B;-zWR{-oH|-exB|Rk_*VvK<*G~V?$DaI-KIhB{T#w(Yd(k`dzxnVO>Nu0 z^9ox{R0_9oh`nB2S)`|jWmqwqDw8aTB-}6u(<0cr9Ux7sFp0!i+r$R6*D%rP<3POp z)yC{6bfE`tzOSDk@m^A9q*q1*`&4m`=$hTRFV{nJ*duorA=I+k;+|2Q=D3Y*RdawiKSjUB1h(a*m2R6e({xWmWvChU}3PGhJ(wE6=3N5$irV+ z3rv(NWOJLYco>t#L-}-X1nTh9b~zGKWvX$N?U%=R({0N zis3%1sqkffHj~ch>H(hH<;C{>KtF@8*z0E)5T68+OB$IQdY{;afkS%Z?SN0eX-`S+ z^D^`Ca6#R-bh)`B?C2SB8^Tkt))E;E(ECg#*I=lO$myZM#(O0ovEFX2%4uJqGPnI3 zz%)|U^nW4mc7P*{Kx2<1wHwQ2oCEe*LKJM^P=o^Q6ci{TWLXB4{EeUzjLT)?Kf7y= zxq=^=9U{ES&Yp;IpX<3Id=b_p@lP_#Bz}_@{OH2cI)nYCOwb$04KMUSzk;>hj_gsAH~n*MxcdK)ZSpe)x*-t4U_(^ zp|YvsM&w?IQPysoO{Aj%)ZyT=u3qnw5z)97(nLE=$FUn|jbQ*o&GfORAps8A(K@Gj z$zhUV_!8_a0+)ndGZww9S zJ~!wtnMBC|w~*Q!OEI{A7}lKNax5XMdiE9s$hxQOL?GRkWMIi3{LGGzG(L>Z4WS}1 z60pPr3)2wH0QW|Q)=Mz;_^ZglWnDejSQjtjS$Z|jKCv!YQ;ZzD zrJa=ll$p8QFtHMSl?ih2Lo?%R_UUC%^1b%97_iF5P+VDBp3XnKudS9L-%vR4KedXR z*%)_gNh96&S9Bt$g%2(J_aEikJ6jS|I@>jQUFOu5X`&dPG0wUOFZGw?61Oq^?*`F? zHtiCVv-HGJ6`poJA!m1>c!|IO+A~I;a?$1fp$-Q59Un$BpZ$LS(x{!U@%xY0@a~Vv zgmm*q(_GpA*9Y9g`ScDPu)__fd<-L!=WncF=3%4n!y6TmoO&;Dip?O{vIqCoRPSFR z5>_UAnzg80VY@&~{WM8@syA1=DI-!8kCiM|ic4O+NqH!SEAR&qC6K4k;-a3;fIR0I z{OjiG*P_s`M>r})(qnHM_S=Mznjrv&o6epUOvv(->9rs!XvHFHwgpBDArX7+MpvGnih|3Hh)>`l~jNI2bzJ~IFOJrNbEOQ3-v$k!m7e7Z!s$# z!bN*;Di)saVZ}lLG1N6YNh<6Q%dm$)^tcK1HO0tB+SW|f(EqQqw`{7UdAW0A&`kii;Z#077&#Rav$tqaoyUH0HwbgZO6baB{qLqaaa&9MXC$1QQA(^S9N?L5Uko7dIgvIFRUsN8~^3i)@0wa`({vW-x-wT*Xug>J3p zo9q2#C%o99K6i&ofd@kY3T8+i#N@2h$Uue835$QMK$D+ zaZ}lem4oR`@B0h9QmSw-&tcW|!>YrTNY&@7uq(%{(5p_OUBdBkF0dCSeX&9e3{SfK zvNpTD*X>%fnaCjV7dIR~>idL;TNzHYc+n4hNNCHyOv~>t-9+cfv&=NV=9rsu2 zZGzD#uS>u3D&(HIp56Y#Qk~cAM(=&1Vy)oA@{azC9-=iTCp0ZTh(KK0Gj&g@t{y zuya3p7K2;pSm|j1u9w3}2qRvcEBf7mLPto1rVxse)(6qye0xH6Z8CichVl-X0bm&6=RoMUa{ zS964wf=7=r^dkVeyP8PGKB+{C9U2afCGT;jRpEzB@Edva$V)AS-eX6ilJc(ez7%R~TCbHfoUtlkmCD2O z&!#?MvjHLJK-SL<@Z+AEipWKG7#?5ApI!Y64}f5{Bq)RL0Bk%{esksXpM;Bmyy*|Y zeQB~;$yBHu$7dhX8@PtcEe}}3c=;cCie2cWj8P0)SItxhSLvoX`Q6U~#}t)tr#f7K zekIoMC#fblEXT_q8v5xIf1Jdi3M$Ms!}EI7yPea1-!Tb7TS;v-0dx$FN!c^u6CzNc z>fUj$y?O7kYdBg~2^W0>C3J?mht@MjP3*8iMJfx+J1-QdM+k*9?#n|38#)V{KDSY~ zLZ8ner(ZQ+(Zda#Q}~!lV@r_wVCq*e(GGS*8#afATNN@fACgD7`A}K4bTKK)K*S(X z&Cf!|e3K-|uY9jnMM)}0lr-?YCCFx>e4%TM9<+6*=Ky49GwuP1z7|q7y}O|Z-Y2Gd z9Ha&5X?XL!ZNW;cTKyl69jC8e`SEsWWB7ioq@+|=hsK7a2tm~(w%F7c1*5bR;e75P zv-jGIUP0z=&w13WWyE*@yl_EW{OUPewe)|^GdRqrT{MGI=Ih2OcevuM@LYt7D0o6n=a#d8P=REwi_Pm{4)vu<)QrCG1D3DL zr5i>DZ%*EC#Ga2+p}D30mv9*c^EkU#Z|*O7Pdm)fPmjaB$k;p&o=!t>_TMBQwzp$H zsB4e>N@W}_4;&=`efOIG%jU?o=@3Ri+K`EUFXuWouJxy0NO9SB3lqe%NKgyI748K# zf}WiYHknG1N{--+H9V=kXxT46wdrM65giy1ah+E0j0pFLN6U0!b?cUVx7(nX!eXp; z@S-IVhj^_DqJcQS$!Q1V{r^lzlYt~jc^zqc0k%$k(3V-q%-&2+YQhfHRiL+Pyzh@0 z>V$E3`X;J4qqpCFA3QmW=;F_+z~xd$b7cJ+z^SJzAB?$Y{f>t{cI4c&tAsuF5t$+k z{3Ip0ZD}uxY*C(K5CtZU3l5sGq4*AZZlV~ox|kSll%qQXu-`wW&7HFk6&0^r^d_!B zF3_TFICi*}OLzeq^5Wy$E&lKkbs&RedOWW-)&41mFpf|R(N zms5xdfbtmn$jOuup)RqQ`W$oTlsRS8VsyJ#qWrx#2It?D-%Z#?9Xi}#NS?3w1s{_- zbNsK%8uD=DQ$uE$54qfD0(FT$F6DA6yLQXkPiMuul*VW%otXd2#$z}LNHGJNO%!9} z%zj91Ihx!_f2#zOFIJjm5KRSz;Pk*WKrSBLmg4LL@=WlMQEN@9Ljjuu?c<%Fv$2Dz zmyfiN3riZ{;c~}&3x(NAxt-Vg*!^_zbKP388dxSP$AztQN<9P%+ls7pgB+nn>^i@a z>&x_`1M*!=-+wjO3en5ent7bhCKs1t$4CwKRx$OR>7^T)3#! z#zqu$(azqy=02f(Hk5-Td%ITE|0?wX(7&#=LHb5O z!Dw#!VNktqpsug2vupxF^ps-O6iy`FCCq9(C8VBEV zsnvhdDq%fYB&5buVPFCb4fPjj=CYFaqEu{|*_|sSuQj?De99b7Jt-)>Woyx@a{!@5 zU6Sah2`4soLnCTTU5CE5lL=SlB?ypZV}#Il3dP|6!|$H{{p9XA1GL)cu#B1gw#WDd zXX{!Fw#%p}0GPALZ8)po!dYJO6E1OH`e`6NP#hSZO*A?(PKy6(d>?TEl|CqB!1R~C zzZ!q~R&Kd2w&RI$({XOPt%^dXGCx`zZGN1=t0zA5OyOG&b`X!4ZlGW8 zPTCeSq=BYH%V{(<^sUp0Qex^!{*_Vp{zkm)i>0s_vhgywm+~(sXTz{MmA`#zp-LXF zq(pdIbXWR!QO?)&2_P`a&_?cg3eFNbW_Q*iF7r+hQ_M`s;z9-ellzJtvZ>G)hCz5v>yf(d=ZYCW%{DB&~ELo1c@i5s|vqZ+cWzbg8-mLV?AZ_(fn zNIk9KCOfW{R`};Wn$<`O!!)y3K{Lf0NHtr5AKUZZ+KtW84)Y6W%r8)&|3gw- zc#?JCE}3Uv77q@<9wH#hwApUfo*C0Pjui0cG|Zx?Q6{T>H2?AqNTGFrQT}2cpfi{9xm^bGw&pR=Th#=;O!%Lzd1LmK$SA_niK6Gec zFhRbmrMKnAae^*vuca)dtudfkM?H$?7yt8R^Yv0pm-F|0yAX`sIqQ-gQNwPp;S~rj z_iB2u?2^#X@%`D(a>x!!yd`=CK&VnsMu1AT1Rb}#1lPC=!`E)zKfFZ=x$1)=!})5u z7MVY2S#0N->IkNcjh4gnw6b~?b<%BDq@q+55fE{Ma)wM0A+y~|+*Qv~%xTWwxnF+c zM=5?p=kWf$mT>rc(SrGfsS^gm3V&}~Bk&KBX+@f{mCnk_eVXcL{5MhjtzJJpek)w( zUqzmKIwq*o(B=J}8En+(d3h3tQ{Z_obRAWwJbG=xbO)YvH9!`?Yna85;4Vl}W#oh5 zA*$z>RT_-;gzokM&$5ZC29fL{wCKWlaajhmCyvi;xBRg3LPo$IShkB0rh$bT8eu%VSm0>S!l7cF@T zoQ9^)lJ~XuCft$tS>|l^!ha1F@QD5A>&ROiUX6O z*5CSZOQ)5lvG@orsUZIqx(p6X4qHq_@WG2e2Q09f)gLQ>yzY=;j%D)E^s}IRwA7d$ zbzZ%@i;^k$d{XTT|5Gt*p35qKPwIQ5meF7F?gV3o@G)C&k||P}T8`7Ne1lkEmJ`yo zzLBCGdt?y2K2YSmyo9-8oD`}s)m3~ZLxyr;5n3y}%Ig%+(bNf)%hkzb*aHF76pE-Nv|zvfanDWdU3alMf-FFSyX&Bw*a)Qg>sH(NO$(; z-cfLd?@fQH%wg7O!|P?I@ddUP6s)s`z)iT;*28M76O;qvd=$?6a$sf86?cwFlSik< z`q?sjxxUO|3=!Ag`%@z!q6{|k^@-LC4D;DSYyaWHY$FWNS4hAd?+*5{+xfTu3lLQG z8m2oW(b^|s7}x*fT5%gp*o6i_7K~ZxY>moZ|5%AT2??AH{IGt!^E`ahYrznD)z>*n zztkAS*-){++T0Y%6d(E8pM%FuN!jDt^%sNdsb7dW48)#s@$Aoq10IntW+V0UI~f@kd-Kj2ZPpNF zzp`c0Xx(wLtAacn(39f(ib0ANQ3!h!iOg(_9RJ>+(9Uef|IL8$-6LoQN>Lh?SBIl0 z9v$b4f{9+7`&IcBrN&~W+OTA1z(pUHyN0^cn#gW%m*stp6DuLm@DM75Ij0Q|4l!jM zbsAECUtxp_I`tj&Z`x5rvt?u{yfC~meRry76;zWo ze1mXWD3S0phBeO-3O(6SU7g;yWXV<-U((tI$mGh)G5b7l4Sszl=FUIt9Nd97wmai~ zzYoH1I-I}Kxf|s%3h>73js{Z<|Hd z7j-buTY%%Ahp&mbhLcD{jm0lYdEX~c1Qi{K7|l{6#y-y{EW z=|;ix#$2Ui#BOz4V?)$bO&v%)L8WnW|vhU)eA` ztoTC6ePOuNf$7PqMI}P!TrWRw0T1}WS9eqT%JTkc)OnA{Cnx<(hWN} z(ggv>VM+q`b-z!De_L>%D=7MGny6vx;YkFm>3g)tiYmo=WDJ3|I;t>By&OgkCkCVyshW^innaOM!k~zT zxhkX3WRsttof`F|ltS_($>ep{9`EJy0p2BnP?hgjvwcRVhsns^Pm5Ra7BUR~3kxV? zGEJQT6|l;7RFL)sCKGhvW)!2XL?4#|u0A`LC`hQ2qecVZF1k1m5yghQApCLamO7Dp z8K=h#6`ZpuZ4)JB3W;q-e52avle7#o2tYPO>36+nFkExNBrPkCRHzE zcTxYutm;C}5*eE)Ci=T8JOhCgfp^v4E=uQ;dr&`C?|TpowBi(H-@g9IyX~%eut#f; zYj%P>AeTgGkj+SUy{t2k(&QGI0h1G8<{BuP%G)#nQ{Sf%0M9{_o7XcT)EAi;4%xxu zB&ddo2XiIXlT0d4-g{7_gVQ=@BB}L>f!Pq-4ffC-)ld8QZHw}BM%Qc57sdlJFTJPtyM+$iSH=ogAC@P^jYRiF`2ls5%Gpi&ofBuw{54Qwv zuImks?XSmiviKmBblX>_vT+FV`+~v&#h4g_A%jdp|LphMZ8qL?m^VdD)QUim$&VN7 zt!K{!4sQ~pEv}<0?w1Q88?_&+(eKSEFj>aG#=Y2Yh_v1bN6$q+ZT&62JF1(^d#m&{ ze~B#P3OJ8*Y+k3N__YFeB}WPs$T>aPDk|HYdz(AoEAUFoyw%~p1S8!y;5Xk6x@zA4 z3m7OjcK2o=XbPJ5xd@(HQOBrou8Aql*qD4fyOVI`55MHZC7vjj5TKSCOs1WZ-WDGf z2{a3gk%%vL1Hei^b8)m!BO%5Yb4-OQdwKO&gnvH`Se-vH$tqJZate;z)N2+JZI?E> zdmn9!K)ikMgIcHvzf5ztXGzlKI5|9W84VP)rCW%`M=(#H&rv6b=qsNeaFc}xz`?Z) z*n^_^cs-wE7|XTZj)(9W|382Khf~#uSb^7`kCMquhaFn8-Co87sXy)%J>|9}WoPd8 z#O9ezPhD_~flinBLd|aO&5+=UiEtBv>qJC!c2m8-IlwyVR5Bk(ksd~;Ao$!46muxN zT~}}Zh$$PLB7IBbyJM^-y6|ZUL^Yh&R4@N#CA2A#xfola*E5!t(ZzN@b)O^L^4%`L z4O$qfL_~y+e45Eh>pKOZ;9f7T>c&|Be(y|=Yka*NGpF~Poio2#{K?-|;~u0JESmnaj^>o}jo`}ALSsF(%R2Lfxo zA|BJj&vCdTAB6Xw$jJRnn?#|1R5>XiX?fO4YA$d~mxv&^z3X8|G;^xqQqsD!$FOtn ze_a$cpMbwGVR4*O7d4Gqf1E%ND`Ce#HrkT0XX1`t|?(IGOW*Nd%()ed>Qb4?T z#rN}_tFN>)5E6btjrJqCuQXo!Npn zaL!X=J-1e%!~AQD&)--Qy(!cb6{{~W=)D3r#`76FmaQ{v&kjEqe+A^nA4VQp1@w83Wa@5`nyW=|i%UNJO- zfL|L4Y}E||Lx{0kGl45PWw#2$rAyQK1h3$G|A0yYUp8xHiiWGXe!Y?(zV@Oi`~gg) z_E%=W=H#K8%z785_wMOk{^Z=)M1PmJId~hoM}wEX>c=0eG4qc-iqmmf#R=}#sUo!I12LJN#5S6MgF6zmc#D z?;u&-u&?kv$FsB~T>wwSfMf~7tDuWkO@7!aap4zKFOXZ`TPF7Xb+AK?01J*5O8ztu z1@jF7(&L(yyM5TRsuSCvYvB9)+rILOT(aKZ$SH-?Q~?{ zaO7DNI4oQJkFHM+H%q(zE*BTJ2e02^aUrUIo%%z=u+3r@YIX=ANESB}Eu0Nmm0W(R zFtiCELa@}cvxn>Y)*OA`an0EQDNDcbJ3<{-H1llY8Jde6bL<{vdg9l8hX(e9*rq|~v2|1) zPJNSWr%t`Sj@<;ysW*I>LG^X?eI1BCq+DG|<`B3YV;O%P&;LB4@sC_%@P}P2*CEPe z37GwS--MiHZnbSv)`$bVJIIvNNj{II^$uuZRDMmiPt;hdnMOg@+=HT6%Gt595|iFK ze9iZJG~Hf?&i;wchCGfj_$Mp9_3&dlwqzL!{H;go$$ul47; zK~Y;Zq45q|Y{vhTQtisoWmZztwXtL>{W@+x);P8R}mgC&a_upZXT zoVKT1Z7*~t3s^~5o?D*uz}^$bcSWo@oeJ@ksfr) z_N(TM0)iuu_KH?LwfgiPc51;v%u-EPYK*D)s=7Iee;JAHLlX24hX+6EIfveUr+VoB zaoV-53%wvt5EeG(t8&mntKSUMJN(Xvbi_JTNTEehYx^4eEtVM$^Bk)f1+xSSyMZdl zSZ2Xo&Hyjh_Ms7Rb=JuD+A`^2CK%!PfXTW zzs(*$^>@>DaHD>m3MN@NY}BWGFrS#H%c>}PC_Z{}C_C@QrKuXDNs`a~q>7VLaTZ4y z-3$RzA>#_C{QTi7-%(=P`jW&W1Q^ytU5~rf{-f~waih80!A%u&OZtbH%2wQ~`4tq1 z=(+TDY+s~;s>G8GEQDlBdCc7VtMea}f^6ODjf&FKQ<(6Xhc?cR$Px4VwEskdrtr07 zX9R=n=2;8f+}3>+-Fa73RUWCM!E+UaPUKzHMXmE5tOYKld8jen?s(jL&>UCPYk?80NcTlB{#n4`>Mw^^;erb~B zHzLc4d7u0vM?>LOtI1zQ)^8MQ5dOzl#UMdvzIBHOMUIjRNJGfZjXFRQ^Yn|thqcA@ z$?JB72H*U~Qz7Z>qq6s^zihY)SV8pN5$x`WELC*KYU@M}MmzO)?Q#d(fkk2P-nsm^ zxLcu=vmg28>a@k|muoW^!|K2knHx~r>;fN4(s|Kk^iiV=`J=KaFkq_lO$RI^eXC|P zl;N|HN&SDUW>zMf<0m}F!C1Oc!C%f(FQJu%i@yYZPYw3Xgvyyz?UYkBi7Kv8oH)5>{j3sMqL-9 zP4`zRfJmqN!uk0RR>;UWBV_a%Cf?S}uq^AXJ-7b8et|wdWHu*Ezd1P%iYaz3Sehu_ z)Mg*GfO8zHA$*w7g%oKiW}`S)2hXPn1QSpo8?;Wq(TTIU8yFaprHr_UI-BE)g2e?( z>Lp#)%Oh_&aZrIwO7Hen`O9HLXU^fm=k18Vg~r)^cHLz)0Fa^dJwR4()))?{f`_9d z9wYcvOipj#CR-Mh9m-plenQ#l3>Bn$LS6 z>m?oa5&8`oZ&ui=M{Yq`w?*|A*u1dj&*&-Ls6{=dneRqzX3vbFs@Y=U3{@&t0wj*? z`RF}h3?=on^&d1>kkuv6oLdct%!Y22{aw*xdDHTYBcKci{OdV!_f8d*fdUS}_1Ssspu=Qa)X%ttr@AUD0q z63%vp+svO+cfiR}Hd-wkOt6dPh{>aU`p%2Isz1LH8&D}|)8G*P-T)0_d?Xbot9>~$ zbixBK+Jh*0bt@j5EU5*P>PW_QgMQ`to^Ip@ZHSR+1b*%KXURT_7}Hc)@SB*eWg=1mIl{A zYU6Ytb&^8`$fb-*PbuE&vS@!{llUlh7dYb|{_D$f}z? z{`KfZCN2R3q+gp>o%xEw_Z&Y4-8u9&pQ6=fdmC~7ZGHmW7nz9(PsmXC*)%wl$TmvW z8A1eI3eePL{P&A+H(0L3Vfrl$O?Ir(J5K1AcphQH9+Z3l^@p`4Rcb}D+ox_65Sz3P zfKt2!Zc?HnGjme2t397A!GbEG2ofDvkDd6il*i5InCAly-#0Hc8fTGoCl&>!IeAah z->jcXnV(oaa#AodUC0d|KeXpR5Hj^{ju`gRG}8hXF-)BPo-hcy-^MR1#QIi-=~ZS? z+3|Kf@00TS)pfgSP2>@8(bolkA4=6pnem3RAU-*WFrn_p6+MvL^|=Qj!Jt4BB7%Vn zVS-{Y72U8^;+sc$`D}z0mEWfJ)-Qj~c--KgUM5B*GmAI&)rH_11nH3*HlQ#_)*4^%IcrFP6pN9(MoNGAXNZ=X6RbK!0{*Jj0b=BclY0Xo$K^G{q(V-odrtb9t z3|j+eEb(b}vgh!|-l{aEp2!6DxHfIQwL#rr;4NlZTMwF&eNmm1@cmPrhdq0Ag%=Bf zP?1QZz_aZwE;AC9t2FAO?{YVHeJ9K^M+5Uz`y5i2p_U9Wh#0hvrFV^}MeMWxZIJTk zFQ`kmQjZccZy&`MN>0kSP?SsB?gCO+M9K$o(b^xelGZzpA$7n93^NuZRYw)VQhQKQ zfx#>$>1{t1low|$1}a)AFM3TmS0TA9ynw{5vqdFsu^*_Q?|P<|NPpE|Kn%UBKxoMO zz{Fy9{x|D^Ul=U@cRq+xMb-05T}T(n`6RfW5rB`=N# zK$!XQ*3BjgL>$oloe@9=-bsQmd=Wd7stS)8X72c@}|c+*p>Dek4Ao)%O`(BpE=zK|eL> zEu(~`Px~JqCj^{q1K&(H@@}(+^G>zak@$T-Cpqy}`IB&aakPJW_;_ofav2DP^!1F% zcU^?NG}(3TZdPjFm$(Z6k7iMA(P0*tYN{%`7`^#pu!4ht!hV6LN>eFh;cSt}#-}P_ zi?Z1wYghVO+}gVG(wSlbA*ylI-t}tvDG-C#S?0w8mHMAR4o zFg+JkA;03RKY#p3T>}ULuN)JlBGt83=qkwC4!U{ zL5!w(3n@-|1Lb6_yebIuE8nx-tMAb#g}HywmEP7`D>f=MPr8lmjXC&vbd5cF*}@a)HCgw%Uos2Z!7cPT ziR)}DC8bruH3eVFz{k4DO-Ma#N3FQ#Mxl`17Prgt)tE2ZAxW2R-2j8wHDs5mis^LKZ#KcV>3BM3E(Asw-$g_OaNS92-BT~+=>nu*Khl5o!#jVckndG>6j zT&=faUN?l(g@4yEjFp4@9uOhz(HzID+=NBzxj_0 zh=TTNU#(w}#I%;i^)<3%&2C6cB<-{aa$rWrZWR)<91|B3IH~Rq&OGaGw*fqhD}Ec>6SlsdlAbiGZ~d9C*l}j= zRg_&C1=O;QweB|8MVlAWG;XEolp-!Kh2)C2>==XmgtMhGy3U8@R|PHj7SC?}Zq}X~ zq=UH2Z2e>Udd=8{-SzWEI31NijTCAj@*p;)tlkccZ^N%wq2J;rN6nQE16qboQ3G=_ zq`x3Frr)fzF7b}klS->DF)o-mO?XcJ`p<8Qt8mCcA6kG(jyPT59{8?NXO(6Dx387^ zKlA#J6rigno*sx69T*rJ2GAo+H=%_K$%+D?RfvSGx#w}NY`(q>wguZS+WT0ZnYlz? zSB(@jBu&RM)JV#tn{{Vjv?-wk;o2azivnTu^UBrZ zO-}YICGHJxCNJ2qt>JY=uQe#*+b}f2HK?bY(+0Zan|1XbABZyl>(f`qQlp0T5CHS` zm9|iV$m|k$q?5rfVGj>pTh@TdG<*@uuOZU<@=Jlu&1}|#9SxE)Td)SOu+>$=Eeg-- z4`ku$_cf@i$Nirb*PO`n|7Ys|?EU|BN{w3d1G7$Yul$oEH3Rl_$Ve!PgG2#={}0#u BIz9jZ literal 0 HcmV?d00001 diff --git a/monkestation/code/modules/blueshift/species/ashwalker.dm b/monkestation/code/modules/blueshift/species/ashwalker.dm index e897dbb54164..773eb4b40f2c 100644 --- a/monkestation/code/modules/blueshift/species/ashwalker.dm +++ b/monkestation/code/modules/blueshift/species/ashwalker.dm @@ -148,10 +148,12 @@ /obj/item/bodypart/arm/left/lizard/ashwalker brute_modifier = ASHWALKER_BRUTE_MODIFIER burn_modifier = ASHWALKER_BURN_MODIFIER + hand_traits = list(TRAIT_CHUNKYFINGERS) /obj/item/bodypart/arm/right/lizard/ashwalker brute_modifier = ASHWALKER_BRUTE_MODIFIER burn_modifier = ASHWALKER_BURN_MODIFIER + hand_traits = list(TRAIT_CHUNKYFINGERS) /obj/item/bodypart/leg/left/lizard/ashwalker brute_modifier = ASHWALKER_BRUTE_MODIFIER diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm index 112bd5faf94b..9208831c40d9 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm @@ -7,9 +7,7 @@ TRAIT_MUTANT_COLORS, TRAIT_MUTANT_COLORS_SECONDARY, TRAIT_NO_UNDERWEAR, - TRAIT_PLANT_SAFE, TRAIT_NO_JUMPSUIT, - TRAIT_LIMBATTACHMENT, TRAIT_EASYDISMEMBER ) external_organs = list( diff --git a/monkestation/code/modules/smithing/ipcs/body/base_bodyparts.dm b/monkestation/code/modules/smithing/ipcs/body/base_bodyparts.dm index 18af9178621e..b3b644516469 100644 --- a/monkestation/code/modules/smithing/ipcs/body/base_bodyparts.dm +++ b/monkestation/code/modules/smithing/ipcs/body/base_bodyparts.dm @@ -23,7 +23,7 @@ should_draw_greyscale = FALSE biological_state = BIO_ROBOTIC | BIO_BLOODED bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC - + bodypart_traits = list(TRAIT_LIMBATTACHMENT) body_damage_coeff = 1 //IPC Chest at default ///Monkestation Edit max_damage = 250 //Default: 200 ///Monkestation Edit diff --git a/monkestation/code/modules/smithing/ipcs/species.dm b/monkestation/code/modules/smithing/ipcs/species.dm index 2681b551ccfe..018b67f7f7df 100644 --- a/monkestation/code/modules/smithing/ipcs/species.dm +++ b/monkestation/code/modules/smithing/ipcs/species.dm @@ -19,7 +19,6 @@ TRAIT_TOXIMMUNE, TRAIT_GENELESS, TRAIT_STABLEHEART, - TRAIT_LIMBATTACHMENT, TRAIT_LITERATE, TRAIT_REVIVES_BY_HEALING, TRAIT_NO_DNA_COPY, diff --git a/monkestation/code/modules/storytellers/converted_events/_base_event.dm b/monkestation/code/modules/storytellers/converted_events/_base_event.dm index 84ae021d7840..098355afedba 100644 --- a/monkestation/code/modules/storytellers/converted_events/_base_event.dm +++ b/monkestation/code/modules/storytellers/converted_events/_base_event.dm @@ -70,6 +70,12 @@ var/list/protected_roles /// Restricted roles from the antag roll var/list/restricted_roles + var/event_icon_state + +/datum/round_event_control/proc/generate_image(list/mobs) + return +/datum/round_event_control/antagonist/generate_image(list/mobs) + SScredits.generate_major_icon(mobs, event_icon_state) /datum/round_event_control/antagonist/proc/check_required() if(!length(exclusive_roles)) @@ -265,7 +271,7 @@ log_storyteller("Picked antag event mob: [picked_mob], special role: [picked_mob.mind?.special_role ? picked_mob.mind.special_role : "none"]") candidates |= picked_mob - + var/list/picked_mobs = list() for(var/i in 1 to antag_count) if(!length(candidates)) message_admins("A roleset event got fewer antags then its antag_count and may not function correctly.") @@ -282,8 +288,10 @@ setup_minds += candidate.mind candidate.mind.special_role = antag_flag candidate.mind.restricted_roles = restricted_roles + picked_mobs += WEAKREF(candidate.client) setup = TRUE + control.generate_image(picked_mobs) if(LAZYLEN(extra_spawned_events)) var/event_type = pick_weight(extra_spawned_events) if(!event_type) diff --git a/monkestation/code/modules/storytellers/converted_events/solo/bloodcult.dm b/monkestation/code/modules/storytellers/converted_events/solo/bloodcult.dm index cbf469a3fb3c..ff2c6a8acd9d 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/bloodcult.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/bloodcult.dm @@ -37,6 +37,7 @@ earliest_start = 0 SECONDS weight = 4 max_occurrences = 1 + event_icon_state = "cult" /datum/round_event/antagonist/solo/bloodcult excute_round_end_reports = TRUE diff --git a/monkestation/code/modules/storytellers/converted_events/solo/bloodsuckers.dm b/monkestation/code/modules/storytellers/converted_events/solo/bloodsuckers.dm index 30ec0ef49fbf..bcf08d77896e 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/bloodsuckers.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/bloodsuckers.dm @@ -24,6 +24,7 @@ min_players = 20 weight = 10 maximum_antags = 2 + event_icon_state = "vampires" /datum/round_event_control/antagonist/solo/bloodsucker/roundstart name = "Bloodsuckers" diff --git a/monkestation/code/modules/storytellers/converted_events/solo/changeling.dm b/monkestation/code/modules/storytellers/converted_events/solo/changeling.dm index f198a7b2e85b..64fa6e73fb32 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/changeling.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/changeling.dm @@ -24,6 +24,7 @@ min_players = 20 weight = 9 shared_occurence_type = SHARED_CHANGELING + event_icon_state = "changeling" /datum/round_event_control/antagonist/solo/changeling/roundstart name = "Changelings" diff --git a/monkestation/code/modules/storytellers/converted_events/solo/clockwork_cult.dm b/monkestation/code/modules/storytellers/converted_events/solo/clockwork_cult.dm index 2843b335d454..5fd9ff9c3f5d 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/clockwork_cult.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/clockwork_cult.dm @@ -36,6 +36,7 @@ earliest_start = 0 SECONDS weight = 4 max_occurrences = 1 + event_icon_state = "clockcult" /datum/round_event/antagonist/solo/clockcult end_when = 60000 diff --git a/monkestation/code/modules/storytellers/converted_events/solo/clown_operative.dm b/monkestation/code/modules/storytellers/converted_events/solo/clown_operative.dm index b51cb8b8ae27..93c3a249edf7 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/clown_operative.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/clown_operative.dm @@ -40,6 +40,7 @@ earliest_start = 0 SECONDS weight = 1 //these are meant to be very rare max_occurrences = 1 + event_icon_state = "flukeops" /datum/round_event/antagonist/solo/clown_operative excute_round_end_reports = TRUE diff --git a/monkestation/code/modules/storytellers/converted_events/solo/nuclear_operative.dm b/monkestation/code/modules/storytellers/converted_events/solo/nuclear_operative.dm index f95ffd7c64ae..efc065c08ecd 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/nuclear_operative.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/nuclear_operative.dm @@ -40,6 +40,7 @@ earliest_start = 0 SECONDS weight = 4 max_occurrences = 3 + event_icon_state = "nukeops" /datum/round_event/antagonist/solo/nuclear_operative excute_round_end_reports = TRUE diff --git a/monkestation/code/modules/storytellers/converted_events/solo/revolutionary.dm b/monkestation/code/modules/storytellers/converted_events/solo/revolutionary.dm index 9d9b08303e61..1bcb2a46b486 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/revolutionary.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/revolutionary.dm @@ -37,6 +37,7 @@ earliest_start = 0 SECONDS weight = 3 //value was 3, we need to manually test if this works or not before allowing it normally max_occurrences = 1 + event_icon_state = "revolution" /datum/antagonist/rev/head/event_trigger remove_clumsy = TRUE diff --git a/monkestation/code/modules/storytellers/converted_events/solo/traitor.dm b/monkestation/code/modules/storytellers/converted_events/solo/traitor.dm index ede797b7be16..abe18dabcf91 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/traitor.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/traitor.dm @@ -22,6 +22,7 @@ JOB_CYBORG, ) weight = 15 + event_icon_state = "traitor" /datum/round_event_control/antagonist/solo/traitor/roundstart name = "Traitors" diff --git a/monkestation/code/modules/storytellers/converted_events/solo/wizard.dm b/monkestation/code/modules/storytellers/converted_events/solo/wizard.dm index b0426a0191c8..c6962b9db7d5 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/wizard.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/wizard.dm @@ -26,6 +26,7 @@ weight = 2 min_players = 35 max_occurrences = 1 + event_icon_state = "wizard" /datum/round_event_control/antagonist/solo/wizard/can_spawn_event(players_amt, allow_magic = FALSE, fake_check = FALSE) . = ..() diff --git a/monkestation/code/modules/storytellers/readme.md b/monkestation/code/modules/storytellers/readme.md index ace62b725afa..2a8f3d12524d 100644 --- a/monkestation/code/modules/storytellers/readme.md +++ b/monkestation/code/modules/storytellers/readme.md @@ -40,5 +40,6 @@ This PR adds adds on to the current dynamic system by having events be guided by Made by Unknown Coders on Horizon (Horizon's Repo atleast as of 10/14/2023 no longer exists if this changes please let me know on discord #Borbop) +https://github.com/sebdaz/HorizonSS13 Ported by Dwasint diff --git a/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm b/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm index e76f64d6dc5d..08d4afe1f4d8 100644 --- a/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm +++ b/monkestation/code/modules/surgery/bodyparts/floran_bodyparts.dm @@ -11,6 +11,7 @@ limb_id = SPECIES_FLORAN is_dimorphic = TRUE ass_image = 'icons/ass/asspodperson.png' + bodypart_traits = list(TRAIT_LIMBATTACHMENT) palette = /datum/color_palette/generic_colors palette_key = MUTANT_COLOR @@ -23,6 +24,7 @@ unarmed_attack_effect = ATTACK_EFFECT_CLAW unarmed_attack_sound = 'sound/weapons/slice.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + hand_traits = list(TRAIT_PLANT_SAFE) palette = /datum/color_palette/generic_colors palette_key = MUTANT_COLOR @@ -35,6 +37,7 @@ unarmed_attack_effect = ATTACK_EFFECT_CLAW unarmed_attack_sound = 'sound/weapons/slice.ogg' unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + hand_traits = list(TRAIT_PLANT_SAFE) palette = /datum/color_palette/generic_colors palette_key = MUTANT_COLOR diff --git a/monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm b/monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm index f66e3d6be7b6..e5d63be56107 100644 --- a/monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm +++ b/monkestation/code/modules/the_wolf_inside_of_me/bodyparts.dm @@ -64,7 +64,7 @@ burn_modifier = 0.75 brute_modifier = 0.25 dmg_overlay_type = null - bodypart_traits = list(TRAIT_CHUNKYFINGERS) + hand_traits = list(TRAIT_CHUNKYFINGERS) biological_state = (BIO_FLESH|BIO_BLOODED) /obj/item/bodypart/arm/right/werewolf @@ -88,7 +88,7 @@ burn_modifier = 0.75 brute_modifier = 0.25 dmg_overlay_type = null - bodypart_traits = list(TRAIT_CHUNKYFINGERS) + hand_traits = list(TRAIT_CHUNKYFINGERS) biological_state = (BIO_FLESH|BIO_BLOODED) /obj/item/bodypart/leg/left/werewolf diff --git a/tgstation.dme b/tgstation.dme index af904eb8f9a7..d1431cd4fdb6 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -655,7 +655,6 @@ #include "code\_onclick\hud\alien_larva.dm" #include "code\_onclick\hud\blob_overmind.dm" #include "code\_onclick\hud\blobbernaut.dm" -#include "code\_onclick\hud\credits.dm" #include "code\_onclick\hud\drones.dm" #include "code\_onclick\hud\fullscreen.dm" #include "code\_onclick\hud\generic_dextrous.dm" @@ -5460,6 +5459,7 @@ #include "code\modules\surgery\advanced\bioware\nerve_grounding.dm" #include "code\modules\surgery\advanced\bioware\nerve_splicing.dm" #include "code\modules\surgery\advanced\bioware\vein_threading.dm" +#include "code\modules\surgery\bodyparts\_arms.dm" #include "code\modules\surgery\bodyparts\_bodyparts.dm" #include "code\modules\surgery\bodyparts\digitigrade.dm" #include "code\modules\surgery\bodyparts\dismemberment.dm" @@ -6015,6 +6015,9 @@ #include "monkestation\code\modules\aesthetics\objects\windows.dm" #include "monkestation\code\modules\aesthetics\subsystem\coloring.dm" #include "monkestation\code\modules\aesthetics\walls\iron.dm" +#include "monkestation\code\modules\and_roll_credits\_credits.dm" +#include "monkestation\code\modules\and_roll_credits\credits_subsystem.dm" +#include "monkestation\code\modules\and_roll_credits\episode_names.dm" #include "monkestation\code\modules\antagonists\_common\antag_datum.dm" #include "monkestation\code\modules\antagonists\_common\antag_hud.dm" #include "monkestation\code\modules\antagonists\abductor\abductor.dm" From 69c8e40f33cb5cfe994702635f7d6adfe67e0645 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 12:40:41 -0700 Subject: [PATCH 102/158] Update clockwork_cult.dm --- .../storytellers/converted_events/solo/clockwork_cult.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/storytellers/converted_events/solo/clockwork_cult.dm b/monkestation/code/modules/storytellers/converted_events/solo/clockwork_cult.dm index 5fd9ff9c3f5d..bc4672b8db61 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/clockwork_cult.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/clockwork_cult.dm @@ -34,7 +34,7 @@ min_players = 45 roundstart = TRUE earliest_start = 0 SECONDS - weight = 4 + weight = 0 max_occurrences = 1 event_icon_state = "clockcult" From a7d08fdc594dc7b4d7aad780a83f8bc30df4f045 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 12:43:35 -0700 Subject: [PATCH 103/158] Update living_procs.dm --- monkestation/code/modules/temperature_overhaul/living_procs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/temperature_overhaul/living_procs.dm b/monkestation/code/modules/temperature_overhaul/living_procs.dm index 917430838e9a..009760be7a22 100644 --- a/monkestation/code/modules/temperature_overhaul/living_procs.dm +++ b/monkestation/code/modules/temperature_overhaul/living_procs.dm @@ -157,7 +157,7 @@ adjust_bodytemperature(natural_change * seconds_per_tick, min_temp = min, max_temp = max) // no use_insulation beacuse this is internal if(!(sigreturn & HOMEOSTASIS_NO_HUNGER)) - adjust_nutrition(-1 * HOMEOSTASIS_HUNGER_MULTIPLIER * HUNGER_FACTOR * nutrition_per_kelvin * abs(natural_change) * seconds_per_tick) + adjust_nutrition(-0.1 * HOMEOSTASIS_HUNGER_MULTIPLIER * HUNGER_FACTOR * nutrition_per_kelvin * abs(natural_change) * seconds_per_tick) /mob/living/silicon/temperature_homeostasis(seconds_per_tick, times_fired) return // Not yet From 0df849eed330794adbb8a9bc9613767022471d4c Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 12:54:02 -0700 Subject: [PATCH 104/158] Update species.dm --- monkestation/code/modules/smithing/oozelings/species.dm | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/monkestation/code/modules/smithing/oozelings/species.dm b/monkestation/code/modules/smithing/oozelings/species.dm index 22a721e7bd56..af00a31276a0 100644 --- a/monkestation/code/modules/smithing/oozelings/species.dm +++ b/monkestation/code/modules/smithing/oozelings/species.dm @@ -7,10 +7,6 @@ id = SPECIES_OOZELING changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT - inherent_traits = list( - TRAIT_MUTANT_COLORS, - ) - hair_color = "mutcolor" hair_alpha = 160 @@ -23,7 +19,7 @@ mutantheart = /obj/item/organ/internal/heart/slime inherent_traits = list( - TRAIT_CAN_USE_FLIGHT_POTION, + TRAIT_MUTANT_COLORS, TRAIT_EASYDISMEMBER, TRAIT_NOFIRE, ) From d2d81f37bb1f2a55a42b7822d001acde8f950267 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 12:57:04 -0700 Subject: [PATCH 105/158] Create ATTRIBUTION.txt --- goon/ATTRIBUTION.txt | 281 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 goon/ATTRIBUTION.txt diff --git a/goon/ATTRIBUTION.txt b/goon/ATTRIBUTION.txt new file mode 100644 index 000000000000..b1b34ec4422a --- /dev/null +++ b/goon/ATTRIBUTION.txt @@ -0,0 +1,281 @@ +openlootcrate.ogg - + Compressed in 2023 by virvatuli sound/misc/openlootcrate.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/openlootcrate.ogg + +openlootcrate2.ogg - + Compressed in 2023 by virvatuli sound/misc/openlootcrate2.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/openlootcrate2.ogg + +ArtifactAnc1.ogg - + OG Commit sound/machines/ArtifactAnc1.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/ArtifactAnc1.ogg + +ArtifactEld1.ogg - + OG Commit sound/machines/ArtifactEld1.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/ArtifactEld1.ogg + +ArtifactEld2.ogg - + OG Commit sound/machines/ArtifactEld2.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/ArtifactEld2.ogg + +ArtifactMar1.ogg - + OG Commit sound/machines/ArtifactMar1.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/ArtifactMar1.ogg + +ArtifactMar2.ogg - + OG Commit sound/machines/ArtifactMar2.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/ArtifactMar2.ogg + +ArtifactPre1.ogg - + OG Commit sound/machines/ArtifactPre1.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/ArtifactPre1.ogg + +ArtifactWiz1.ogg - + OG Commit sound/machines/ArtifactWiz1.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/ArtifactWiz1.ogg + +elec_bzzz.ogg - + OG Commit sound/effects/elec_bzzz.ogg +https://github.com/goonstation/goonstation/blob/master/sound/effects/elec_bzzz.ogg + +electric_shock.ogg - + OG Commit sound/effects/electric_shock.ogg +https://github.com/goonstation/goonstation/blob/master/sound/effects/electric_shock.ogg + +electric_shock_short.ogg - + OG Commit sound/effects/electric_shock_short.ogg +https://github.com/goonstation/goonstation/blob/master/sound/effects/electric_shock_short.ogg + +bellalert.ogg - + OG Commit sound/machines/bellalert.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/bellalert.ogg + +engine_alert1.ogg - + OG Commit sound/machines/engine_alert1.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/engine_alert1.ogg + +engine_alert2.ogg - + OG Commit sound/machines/engine_alert2.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/engine_alert2.ogg + +engine_alert3.ogg - + OG Commit sound/machines/engine_alert3.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/engine_alert3.ogg + +engine_grump1.ogg - + OG Commit sound/machines/engine_grump1.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/engine_grump1.ogg + +engine_grump2.ogg - + OG Commit sound/machines/engine_grump2.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/engine_grump2.ogg + +engine_grump3.ogg - + OG Commit sound/machines/engine_grump3.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/engine_grump3.ogg + +engine_grump4.ogg - + OG Commit sound/machines/engine_grump4.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/engine_grump4.ogg + +engine_highpower.ogg - + OG Commit sound/machines/engine_highpower.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/engine_highpower.ogg + +tractor_running.ogg - + OG Commit sound/machines/tractor_running1.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/tractor_running.ogg + +tractor_running2.ogg - + OG Commit sound/machines/tractor_running2.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/tractor_running2.ogg + +tractor_running3.ogg - + OG Commit sound/machines/tractor_running3.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/tractor_running3.ogg + +tractorrev.ogg - + OG Commit sound/machines/tractorrev.ogg +https://github.com/goonstation/goonstation/blob/master/sound/machines/tractorrev.ogg + + +babynoise.ogg - + OG Commit goonstation/sound/babynoise.ogg +https://github.com/goonstation/goonstation/blob/master/sound/voice/babynoise.ogg + +body_thud.ogg - + OG Commit goonstation/sound/misc/body_thud.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/body_thud.ogg + + +speak_1.ogg - + OG Commit goonstation/sound/misc/talk/speak_1.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/speak_1.ogg + +speak_1_exclaim.ogg - + OG Commit goonstation/sound/misc/talk/speak_1_exclaim.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/speak_1_exclaim.ogg + +speak_1_ask.ogg - + OG Commit goonstation/sound/misc/talk/speak_1_ask.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/speak_1_ask.ogg + +speak_2.ogg - + OG Commit goonstation/sound/misc/talk/speak_2.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/speak_2.ogg + +speak_2_exclaim.ogg - + OG Commit goonstation/sound/misc/talk/speak_2_exclaim.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/speak_2_exclaim.ogg + +speak_2_ask.ogg - + OG Commit goonstation/sound/misc/talk/speak_2_ask.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/speak_2_ask.ogg + +speak_3.ogg - + OG Commit goonstation/sound/misc/talk/speak_3.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/speak_3.ogg + +speak_3_exclaim.ogg - + OG Commit goonstation/sound/misc/talk/speak_3_exclaim.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/speak_3_exclaim.ogg + +speak_3_ask.ogg - + OG Commit goonstation/sound/misc/talk/speak_3_ask.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/speak_3_ask.ogg + +speak_4.ogg - + OG Commit goonstation/sound/misc/talk/speak_4.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/speak_4.ogg + +speak_4_exclaim.ogg - + OG Commit goonstation/sound/misc/talk/speak_4_exclaim.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/speak_4_exclaim.ogg + +speak_4_ask.ogg - + OG Commit goonstation/sound/misc/talk/speak_4_ask.ogg +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/speak_4_ask.ogg + + + +radio_ai.ogg + mybluecorners (8ec37f12e282492a5e7aeb4ec1d5cfa2f1df7460 +https://github.com/goonstation/goonstation/blob/master/sound/misc/talk/radio_ai.ogg + + +neon_lining.dmi + Nebulacrity https://github.com/goonstation/goonstation/pull/1731 +https://github.com/goonstation/goonstation/blob/9470d5bbb76afa2ffdee6bddf8b97a68092d8b01/icons/obj/decals/neon_lining.dmi + +pt_laser.dmi + gannets +https://github.com/goonstation/goonstation/blob/master/icons/obj/pt_laser.dmi + + +teg.dmi - https://github.com/goonstation/goonstation/pull/3408 Azrun blower indication, Inital Commit (circulator's + Azrun https://github.com/goonstation/goonstation/pull/3408 blower indication + gannets - main teg sprite + Azrun https://github.com/goonstation/goonstation/pull/2902, open states +https://github.com/goonstation/goonstation/blob/master/icons/obj/power.dmi +https://github.com/goonstation/goonstation/blob/master/icons/obj/atmospherics/atmos.dmi + +slasher.dmi + Zonespace27 https://github.com/goonstation/goonstation/pull/6094 +https://github.com/Zonespace27/goonstation/blob/d9a36b8ae0203788683a38c0b8546c14b0e0f656/icons/mob/slasher.dmi + +electile.dmi + mybluecorners https://github.com/goonstation/goonstation/pull/1425/files#diff-cc282396fd85af02912a95be13420419cc7a433cfb2280c362f3c3cf4451ad2c +https://github.com/goonstation/goonstation/blob/master/icons/effects/electile.dmi + +320x320.dmi + goonstation/icons/effect/320x320.dmi (lootbox sprites), +https://github.com/goonstation/goonstation/blob/master/icons/effects/320x320.dmi + +displacements.dmi + pali6 (inital commit) +https://github.com/goonstation/goonstation/blob/master/icons/effects/distort.dmi + +particle.dmi + Azrun - https://github.com/goonstation/goonstation/commit/0f11103f910db33e05482a21f567ae8ef01237f1 + flrsh - https://github.com/goonstation/goonstation/commit/9ffc312e1b66aad4810dbf449c60b2b027b38898 + Sovexe - https://github.com/goonstation/goonstation/commit/ad6e662ae7547efff964ff6b39085621162761d8 + TobleroneSwordfish - https://github.com/goonstation/goonstation/commit/01f361fc560da88ab6cca050dd265bac420658f4 +https://github.com/goonstation/goonstation/blame/master/icons/effects/particles.dmi + + +multi_hit.dmi + goonstation/icons/effects/96x96 - swipe + goonstation/icons/effects/96x96 - stab +https://github.com/goonstation/goonstation/blob/master/icons/effects/96x96.dmi + + +networked.dmi + binarysudoku https://github.com/goonstation/goonstation/pull/750 +https://github.com/goonstation/goonstation/blob/master/icons/obj/networked.dmi + + +plants_alien.dmi + binarysudoku https://github.com/goonstation/goonstation/commit/9fb6d4c8df6ca51bbd6178cc703ffbeb5ae64be7 + sovexe https://github.com/goonstation/goonstation/commit/54f6c5b1b825ebf65647a510195e8ec93154b7a1 + sovexe https://github.com/goonstation/goonstation/commit/b5145abcde8113ce371f842ed4c12c6e2e7944c7 + azrun https://github.com/goonstation/goonstation/commit/3100dbc7c3d69f4d1744d9ffa1b9ded1e9f2c126 + m-earthfire, tobleroneswordfish https://github.com/goonstation/goonstation/commit/08c48c389012d17c8bbf735a6bc0f0fec684dd54 +https://github.com/goonstation/goonstation/blob/master/icons/obj/hydroponics/plants_alien.dmi + +plants_crop.dmi + binarysudoku https://github.com/goonstation/goonstation/commit/9fb6d4c8df6ca51bbd6178cc703ffbeb5ae64be7 + binarysudoku https://github.com/goonstation/goonstation/commit/a2bfa53e05fd18fd44d5d8bf9f8c3e4261e10fe6 + emily https://github.com/goonstation/goonstation/commit/6dde7025cf5ffaabc47f264638f90f92b116fbd7 + yellow-mushroom https://github.com/goonstation/goonstation/commit/df3347bf103e30354e1b45f5cea888d5c433be34 + DimWhat https://github.com/goonstation/goonstation/commit/306343902279aad64147a7d95fcb405ca95989af + sovexe https://github.com/goonstation/goonstation/commit/d3e97cde29fef8047983b66c09f6bf5a62449a20 + crackaduck https://github.com/goonstation/goonstation/commit/32e09c6a1834f1042cf49571476117e38c680cdc + crackaduck https://github.com/goonstation/goonstation/commit/350bf56e85732399329d9631485c45519951cf10 + wolfolotl https://github.com/goonstation/goonstation/commit/c0a09331cb7a3841030cd7991144cf92a826b5e1 + tobleroneswordfish https://github.com/goonstation/goonstation/commit/524eaf8aaf84b00920c7013fc5c6385f47b09be5 + flappybatpal https://github.com/goonstation/goonstation/commit/c09ca907184df4861b23a0df5df917d6505ea684 + tobleroneswordfish https://github.com/goonstation/goonstation/commit/1aa16631c7443140fdcf427bb9a04df5eeff8663 + sovexe https://github.com/goonstation/goonstation/commit/d3e97cde29fef8047983b66c09f6bf5a62449a20 +https://github.com/goonstation/goonstation/blob/master/icons/obj/hydroponics/plants_crop.dmi + +plants_flower.dmi + binarysudoku https://github.com/goonstation/goonstation/commit/9fb6d4c8df6ca51bbd6178cc703ffbeb5ae64be7 + janonas, jigjagboi45 tarmunora https://github.com/goonstation/goonstation/commit/243d0bfade03e14829d3c50fee5d09c938f97d41 + munien7 https://github.com/goonstation/goonstation/commit/5b27507352cb4f2c5988018c04e47f26f09ab116 + flrsh https://github.com/goonstation/goonstation/commit/9ffc312e1b66aad4810dbf449c60b2b027b38898 + eggcereal https://github.com/goonstation/goonstation/commit/9198822090a3dad530df408d6cc77b7e77406551 +https://github.com/goonstation/goonstation/blob/master/icons/obj/hydroponics/plants_flower.dmi + +plants_fruit.dmi + binarysudoku https://github.com/goonstation/goonstation/commit/9fb6d4c8df6ca51bbd6178cc703ffbeb5ae64be7 + jan-antilles https://github.com/goonstation/goonstation/commit/85c5d02771d900f72e32cd1ec9b5a85a7f01b9d1 + t-toasted https://github.com/goonstation/goonstation/commit/de386a2b86395f445c7a6ddba7cda039635c2605 + flappybatpal https://github.com/goonstation/goonstation/commit/c09ca907184df4861b23a0df5df917d6505ea684 + tanker4390 https://github.com/goonstation/goonstation/commit/4691dabb8b940bbd9c441af1e6916bd9f0bcd32c +https://github.com/goonstation/goonstation/blob/master/icons/obj/hydroponics/plants_fruit.dmi + +plant_herb.dmi + binarysudoku https://github.com/goonstation/goonstation/commit/9fb6d4c8df6ca51bbd6178cc703ffbeb5ae64be7 + mordent-goonstation https://github.com/goonstation/goonstation/commit/fdf70ea6bbcbde998d616b431328cb6770035524 + binarysudoku https://github.com/goonstation/goonstation/commit/a2bfa53e05fd18fd44d5d8bf9f8c3e4261e10fe6 + Janonas https://github.com/goonstation/goonstation/commit/a6291454d8210c29939c812a432b72f4aa394e62 + WALPVRGIS https://github.com/goonstation/goonstation/commit/4dc053670dc868888030d440feb4b3050370da00 + avimour, tobleroneswordfish https://github.com/goonstation/goonstation/commit/6a5b97afb44e2da544fffe2126e6cf9640089ee8 + colossusqw https://github.com/goonstation/goonstation/commit/114f0262462c4247578b308a4fba04e9350aa4ce + flrsh https://github.com/goonstation/goonstation/commit/9ffc312e1b66aad4810dbf449c60b2b027b38898 + temthrush https://github.com/goonstation/goonstation/commit/a2d3c6262172fa44eafd9071bba0364cf90cac09 + colossusqw https://github.com/goonstation/goonstation/commit/530ef545c793232ba2a57832f17c8deaf6a3cbfb +https://github.com/goonstation/goonstation/blob/master/icons/obj/hydroponics/plants_herb.dmi + +plant_veg.dmi + binarysudoku https://github.com/goonstation/goonstation/commit/9fb6d4c8df6ca51bbd6178cc703ffbeb5ae64be7 + wolfolotl, tarmunora, zewaka, mordent-goonstation https://github.com/goonstation/goonstation/commit/a941272744132922382940516cd83af2259f1ed9 + flappybatpal https://github.com/goonstation/goonstation/commit/c09ca907184df4861b23a0df5df917d6505ea684 + M-Earthfire https://github.com/goonstation/goonstation/commit/8ea2eb4b124dd7bd2c4a689e0bd1895dbe55d024 + Glamurio https://github.com/goonstation/goonstation/commit/d62440d0ecf4bb6380e2484f9ffc0251b2f31bf5 +https://github.com/goonstation/goonstation/blob/master/icons/obj/hydroponics/plants_veg.dmi + +plant_weed.dmi + binarysudoku https://github.com/goonstation/goonstation/commit/9fb6d4c8df6ca51bbd6178cc703ffbeb5ae64be7 + M-earthfire, tobleroneswordfish https://github.com/goonstation/goonstation/commit/08c48c389012d17c8bbf735a6bc0f0fec684dd54 +https://github.com/goonstation/goonstation/blob/master/icons/obj/hydroponics/plants_weed.dmi \ No newline at end of file From 3c575ef686c4bc4b42296ee27d6e2c88d274e02f Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 13:21:53 -0700 Subject: [PATCH 106/158] Update credits_subsystem.dm --- monkestation/code/modules/and_roll_credits/credits_subsystem.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm index dbd594eec318..51f2a1a21577 100644 --- a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm +++ b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm @@ -28,7 +28,7 @@ SUBSYSTEM_DEF(credits) var/list/contributer_pref_images = list() var/list/admin_pref_images = list() var/list/major_event_icons = list() - var/list/contributors = list("dwasint","dwasint","dwasint","dwasint","dwasint") + var/list/contributors = list("dwasint","absolucy", "wraith_54321", "thepooba") /datum/controller/subsystem/credits/Initialize() From d993f8957148e485632a1054733baa2edaa8500a Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 13:34:43 -0700 Subject: [PATCH 107/158] spacigs --- .../code/modules/and_roll_credits/_credits.dm | 12 ++++++------ .../modules/and_roll_credits/credits_subsystem.dm | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index 8f4879955a0c..9fce9f4cd8af 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -25,8 +25,8 @@ var/y_offset = 0 for(var/i in 1 to length(admins)) - var/x_offset = 80 - for(var/b in 1 to 4) + var/x_offset = 100 + for(var/b in 1 to 8) if(b == 1) y_offset = 0 var/atom/movable/screen/map_view/char_preview/picked = pick_n_take(admins) @@ -34,15 +34,15 @@ break picked.pixel_x = x_offset picked.pixel_y = y_offset - x_offset += 40 + x_offset += 50 credit_order_for_this_round += picked credit_order_for_this_round += "

Our Lovely Contributors
" var/list/contributors = shuffle(SScredits.contributer_pref_images) for(var/i in 1 to length(contributors)) - var/x_offset = 80 - for(var/b in 1 to 4) + var/x_offset = 100 + for(var/b in 1 to 8) if(b == 1) y_offset = 0 var/atom/movable/screen/map_view/char_preview/picked = pick_n_take(contributors) @@ -50,7 +50,7 @@ break picked.pixel_x = x_offset picked.pixel_y = y_offset - x_offset += 40 + x_offset += 50 credit_order_for_this_round += picked for(var/i in SScredits.major_event_icons) diff --git a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm index 51f2a1a21577..c57ba92f44e0 100644 --- a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm +++ b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm @@ -56,9 +56,9 @@ SUBSYSTEM_DEF(credits) var/atom/movable/screen/map_view/char_preview/appereance = new(null, mocked) appereance.update_body() - appereance.maptext_width = 64 + appereance.maptext_width = 96 appereance.maptext_y = -8 - appereance.maptext = "[ckey]" + appereance.maptext = "
[ckey]
" contributer_pref_images += appereance for(var/ckey in GLOB.admin_datums) @@ -70,9 +70,9 @@ SUBSYSTEM_DEF(credits) var/atom/movable/screen/map_view/char_preview/appereance = new(null, mocked) appereance.update_body() - appereance.maptext_width = 64 + appereance.maptext_width = 96 appereance.maptext_y = -8 - appereance.maptext = "[ckey]" + appereance.maptext = "
[ckey]
" admin_pref_images += appereance /datum/controller/subsystem/credits/proc/draft_star() From a37424cef51ef24fe7fa46cd5dfc2dec7584fa1d Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 13:40:26 -0700 Subject: [PATCH 108/158] Whoops --- monkestation/code/modules/and_roll_credits/_credits.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index 9fce9f4cd8af..006aa596de41 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -76,7 +76,7 @@ _credits += new /atom/movable/screen/credit(null, I, src) if(istype(I, /atom/movable/screen/map_view/char_preview)) count++ - if(count >= 4) + if(count >= 8) count = 0 sleep(CREDIT_SPAWN_SPEED) if(!istype(I, /atom/movable/screen/map_view/char_preview)) From 59e018e80699c414121657e06be2ee3d63a25b62 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 13:42:45 -0700 Subject: [PATCH 109/158] tweaks --- .../code/modules/and_roll_credits/_credits.dm | 12 ++++++------ .../modules/and_roll_credits/credits_subsystem.dm | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index 006aa596de41..fbb027617f0e 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -25,7 +25,7 @@ var/y_offset = 0 for(var/i in 1 to length(admins)) - var/x_offset = 100 + var/x_offset = 120 for(var/b in 1 to 8) if(b == 1) y_offset = 0 @@ -34,14 +34,14 @@ break picked.pixel_x = x_offset picked.pixel_y = y_offset - x_offset += 50 + x_offset += 60 credit_order_for_this_round += picked credit_order_for_this_round += "
Our Lovely Contributors
" var/list/contributors = shuffle(SScredits.contributer_pref_images) for(var/i in 1 to length(contributors)) - var/x_offset = 100 + var/x_offset = 120 for(var/b in 1 to 8) if(b == 1) y_offset = 0 @@ -50,7 +50,7 @@ break picked.pixel_x = x_offset picked.pixel_y = y_offset - x_offset += 50 + x_offset += 60 credit_order_for_this_round += picked for(var/i in SScredits.major_event_icons) @@ -95,7 +95,7 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT alpha = 0 plane = SPLASHSCREEN_PLANE - screen_loc = "6,1" + screen_loc = "3,1" var/client/parent var/matrix/target @@ -104,7 +104,7 @@ icon = CREDITS_PATH parent = P var/view = P?.view - var/list/offsets = screen_loc_to_offset("6,1", view) + var/list/offsets = screen_loc_to_offset("3,1", view) if(istype(credited, /atom/movable/screen/map_view/char_preview)) var/atom/movable/screen/map_view/char_preview/choice = credited diff --git a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm index c57ba92f44e0..64ddd7dede37 100644 --- a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm +++ b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm @@ -58,6 +58,7 @@ SUBSYSTEM_DEF(credits) appereance.update_body() appereance.maptext_width = 96 appereance.maptext_y = -8 + appereance.maptext_x = 48 appereance.maptext = "
[ckey]
" contributer_pref_images += appereance @@ -71,6 +72,7 @@ SUBSYSTEM_DEF(credits) var/atom/movable/screen/map_view/char_preview/appereance = new(null, mocked) appereance.update_body() appereance.maptext_width = 96 + appereance.maptext_x = 48 appereance.maptext_y = -8 appereance.maptext = "
[ckey]
" admin_pref_images += appereance From 11d7e81f4faec41e5ca97c60bc16b1282ddd8b25 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 13:52:48 -0700 Subject: [PATCH 110/158] stuff --- .../code/modules/and_roll_credits/_credits.dm | 14 +++++++------- .../modules/and_roll_credits/credits_subsystem.dm | 13 +++++++------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index fbb027617f0e..b7f5cf8f5369 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -25,7 +25,7 @@ var/y_offset = 0 for(var/i in 1 to length(admins)) - var/x_offset = 120 + var/x_offset = 320 for(var/b in 1 to 8) if(b == 1) y_offset = 0 @@ -34,14 +34,14 @@ break picked.pixel_x = x_offset picked.pixel_y = y_offset - x_offset += 60 + x_offset += 70 credit_order_for_this_round += picked credit_order_for_this_round += "
Our Lovely Contributors
" var/list/contributors = shuffle(SScredits.contributer_pref_images) for(var/i in 1 to length(contributors)) - var/x_offset = 120 + var/x_offset = 320 for(var/b in 1 to 8) if(b == 1) y_offset = 0 @@ -50,7 +50,7 @@ break picked.pixel_x = x_offset picked.pixel_y = y_offset - x_offset += 60 + x_offset += 70 credit_order_for_this_round += picked for(var/i in SScredits.major_event_icons) @@ -71,9 +71,6 @@ for(var/I in credit_order_for_this_round) if(!credits) return - if(istype(I, /obj/effect/title_card_object)) //huge image sleep - sleep(CREDIT_SPAWN_SPEED * 3.3) - _credits += new /atom/movable/screen/credit(null, I, src) if(istype(I, /atom/movable/screen/map_view/char_preview)) count++ if(count >= 8) @@ -81,6 +78,9 @@ sleep(CREDIT_SPAWN_SPEED) if(!istype(I, /atom/movable/screen/map_view/char_preview)) sleep(CREDIT_SPAWN_SPEED) + if(istype(I, /obj/effect/title_card_object)) //huge image sleep + sleep(CREDIT_SPAWN_SPEED * 3.3) + _credits += new /atom/movable/screen/credit(null, I, src) sleep(CREDIT_ROLL_SPEED - CREDIT_SPAWN_SPEED) remove_verb(src, /client/proc/ClearCredits) diff --git a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm index 64ddd7dede37..0323a3d76e64 100644 --- a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm +++ b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm @@ -56,9 +56,9 @@ SUBSYSTEM_DEF(credits) var/atom/movable/screen/map_view/char_preview/appereance = new(null, mocked) appereance.update_body() - appereance.maptext_width = 96 + appereance.maptext_width = 120 appereance.maptext_y = -8 - appereance.maptext_x = 48 + appereance.maptext_x = 60 appereance.maptext = "
[ckey]
" contributer_pref_images += appereance @@ -71,8 +71,8 @@ SUBSYSTEM_DEF(credits) var/atom/movable/screen/map_view/char_preview/appereance = new(null, mocked) appereance.update_body() - appereance.maptext_width = 96 - appereance.maptext_x = 48 + appereance.maptext_width = 120 + appereance.maptext_x = 60 appereance.maptext_y = -8 appereance.maptext = "
[ckey]
" admin_pref_images += appereance @@ -215,9 +215,10 @@ SUBSYSTEM_DEF(credits) var/atom/movable/screen/map_view/char_preview/appereance = new(null, client.prefs) var/mutable_appearance/preview = new(getFlatIcon(client.mob?.appearance)) appereance.appearance = preview.appearance - appereance.maptext = client.mob.real_name - appereance.maptext_width = 64 + appereance.maptext_width = 120 appereance.maptext_y = -8 + appereance.maptext_x = 60 + appereance.maptext = "
[client.mob.real_name]
" created_appearances += appereance return created_appearances From 33d656ed80e8e04d70eea42388f60f9468d0ecc5 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:01:01 -0700 Subject: [PATCH 111/158] Update _credits.dm --- monkestation/code/modules/and_roll_credits/_credits.dm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index b7f5cf8f5369..10d325940757 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -25,7 +25,7 @@ var/y_offset = 0 for(var/i in 1 to length(admins)) - var/x_offset = 320 + var/x_offset = -140 for(var/b in 1 to 8) if(b == 1) y_offset = 0 @@ -41,7 +41,7 @@ var/list/contributors = shuffle(SScredits.contributer_pref_images) for(var/i in 1 to length(contributors)) - var/x_offset = 320 + var/x_offset = -140 for(var/b in 1 to 8) if(b == 1) y_offset = 0 @@ -78,8 +78,10 @@ sleep(CREDIT_SPAWN_SPEED) if(!istype(I, /atom/movable/screen/map_view/char_preview)) sleep(CREDIT_SPAWN_SPEED) + count = 0 if(istype(I, /obj/effect/title_card_object)) //huge image sleep sleep(CREDIT_SPAWN_SPEED * 3.3) + count = 0 _credits += new /atom/movable/screen/credit(null, I, src) sleep(CREDIT_ROLL_SPEED - CREDIT_SPAWN_SPEED) remove_verb(src, /client/proc/ClearCredits) From fd3508acffdca6bbc0b79110a313a5456d64378a Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:09:27 -0700 Subject: [PATCH 112/158] ggh --- monkestation/code/modules/and_roll_credits/_credits.dm | 8 ++++---- .../code/modules/and_roll_credits/credits_subsystem.dm | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index 10d325940757..6ea0060d6c35 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -71,6 +71,10 @@ for(var/I in credit_order_for_this_round) if(!credits) return + if(istype(I, /obj/effect/title_card_object)) //huge image sleep + sleep(CREDIT_SPAWN_SPEED * 3.3) + count = 0 + _credits += new /atom/movable/screen/credit(null, I, src) if(istype(I, /atom/movable/screen/map_view/char_preview)) count++ if(count >= 8) @@ -79,10 +83,6 @@ if(!istype(I, /atom/movable/screen/map_view/char_preview)) sleep(CREDIT_SPAWN_SPEED) count = 0 - if(istype(I, /obj/effect/title_card_object)) //huge image sleep - sleep(CREDIT_SPAWN_SPEED * 3.3) - count = 0 - _credits += new /atom/movable/screen/credit(null, I, src) sleep(CREDIT_ROLL_SPEED - CREDIT_SPAWN_SPEED) remove_verb(src, /client/proc/ClearCredits) diff --git a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm index 0323a3d76e64..5fca4be9a21a 100644 --- a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm +++ b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm @@ -58,7 +58,7 @@ SUBSYSTEM_DEF(credits) appereance.update_body() appereance.maptext_width = 120 appereance.maptext_y = -8 - appereance.maptext_x = 60 + appereance.maptext_x = -60 appereance.maptext = "
[ckey]
" contributer_pref_images += appereance @@ -72,7 +72,7 @@ SUBSYSTEM_DEF(credits) var/atom/movable/screen/map_view/char_preview/appereance = new(null, mocked) appereance.update_body() appereance.maptext_width = 120 - appereance.maptext_x = 60 + appereance.maptext_x = -60 appereance.maptext_y = -8 appereance.maptext = "
[ckey]
" admin_pref_images += appereance @@ -217,7 +217,7 @@ SUBSYSTEM_DEF(credits) appereance.appearance = preview.appearance appereance.maptext_width = 120 appereance.maptext_y = -8 - appereance.maptext_x = 60 + appereance.maptext_x = -60 appereance.maptext = "
[client.mob.real_name]
" created_appearances += appereance return created_appearances From 61cbe4a2ffd367c7c0fc1cb0cc04764aa187f822 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:17:52 -0700 Subject: [PATCH 113/158] fixes --- monkestation/code/modules/and_roll_credits/_credits.dm | 4 ++-- .../code/modules/and_roll_credits/credits_subsystem.dm | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index 6ea0060d6c35..cd23fdcee63d 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -25,7 +25,7 @@ var/y_offset = 0 for(var/i in 1 to length(admins)) - var/x_offset = -140 + var/x_offset = -120 for(var/b in 1 to 8) if(b == 1) y_offset = 0 @@ -41,7 +41,7 @@ var/list/contributors = shuffle(SScredits.contributer_pref_images) for(var/i in 1 to length(contributors)) - var/x_offset = -140 + var/x_offset = -120 for(var/b in 1 to 8) if(b == 1) y_offset = 0 diff --git a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm index 5fca4be9a21a..a971f4370bde 100644 --- a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm +++ b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm @@ -28,7 +28,7 @@ SUBSYSTEM_DEF(credits) var/list/contributer_pref_images = list() var/list/admin_pref_images = list() var/list/major_event_icons = list() - var/list/contributors = list("dwasint","absolucy", "wraith_54321", "thepooba") + var/list/contributors = list("dwasint", "absolucy", "wraith_54321", "thepooba") /datum/controller/subsystem/credits/Initialize() @@ -58,7 +58,7 @@ SUBSYSTEM_DEF(credits) appereance.update_body() appereance.maptext_width = 120 appereance.maptext_y = -8 - appereance.maptext_x = -60 + appereance.maptext_x = -80 appereance.maptext = "
[ckey]
" contributer_pref_images += appereance @@ -72,7 +72,7 @@ SUBSYSTEM_DEF(credits) var/atom/movable/screen/map_view/char_preview/appereance = new(null, mocked) appereance.update_body() appereance.maptext_width = 120 - appereance.maptext_x = -60 + appereance.maptext_x = -80 appereance.maptext_y = -8 appereance.maptext = "
[ckey]
" admin_pref_images += appereance @@ -179,6 +179,7 @@ SUBSYSTEM_DEF(credits) MA.icon_state = passed_icon_state MA.pixel_x = 80 major_event_icons += MA + major_event_icons[MA] = list() major_event_icons[MA] |= mobs @@ -217,7 +218,7 @@ SUBSYSTEM_DEF(credits) appereance.appearance = preview.appearance appereance.maptext_width = 120 appereance.maptext_y = -8 - appereance.maptext_x = -60 + appereance.maptext_x = -80 appereance.maptext = "
[client.mob.real_name]
" created_appearances += appereance return created_appearances From bf10c4665b3e47297b69b2164322d466d6c086f3 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:25:54 -0700 Subject: [PATCH 114/158] more stuff --- monkestation/code/modules/and_roll_credits/_credits.dm | 7 +++++-- .../code/modules/and_roll_credits/credits_subsystem.dm | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index cd23fdcee63d..c2468fc57726 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -25,7 +25,7 @@ var/y_offset = 0 for(var/i in 1 to length(admins)) - var/x_offset = -120 + var/x_offset = -100 for(var/b in 1 to 8) if(b == 1) y_offset = 0 @@ -41,7 +41,7 @@ var/list/contributors = shuffle(SScredits.contributer_pref_images) for(var/i in 1 to length(contributors)) - var/x_offset = -120 + var/x_offset = -100 for(var/b in 1 to 8) if(b == 1) y_offset = 0 @@ -74,6 +74,9 @@ if(istype(I, /obj/effect/title_card_object)) //huge image sleep sleep(CREDIT_SPAWN_SPEED * 3.3) count = 0 + if(count && !istype(/atom/movable/screen/map_view/char_preview)) + sleep(CREDIT_SPAWN_SPEED) + _credits += new /atom/movable/screen/credit(null, I, src) if(istype(I, /atom/movable/screen/map_view/char_preview)) count++ diff --git a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm index a971f4370bde..8f37379aa758 100644 --- a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm +++ b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm @@ -58,7 +58,7 @@ SUBSYSTEM_DEF(credits) appereance.update_body() appereance.maptext_width = 120 appereance.maptext_y = -8 - appereance.maptext_x = -80 + appereance.maptext_x = -64 appereance.maptext = "
[ckey]
" contributer_pref_images += appereance @@ -72,7 +72,7 @@ SUBSYSTEM_DEF(credits) var/atom/movable/screen/map_view/char_preview/appereance = new(null, mocked) appereance.update_body() appereance.maptext_width = 120 - appereance.maptext_x = -80 + appereance.maptext_x = -64 appereance.maptext_y = -8 appereance.maptext = "
[ckey]
" admin_pref_images += appereance @@ -218,7 +218,7 @@ SUBSYSTEM_DEF(credits) appereance.appearance = preview.appearance appereance.maptext_width = 120 appereance.maptext_y = -8 - appereance.maptext_x = -80 + appereance.maptext_x = -64 appereance.maptext = "
[client.mob.real_name]
" created_appearances += appereance return created_appearances From 7aaba4870bbdd01115667c33e1d963bb5b5e50ef Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:29:10 -0700 Subject: [PATCH 115/158] Update _credits.dm --- monkestation/code/modules/and_roll_credits/_credits.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index c2468fc57726..19023daa134a 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -74,7 +74,7 @@ if(istype(I, /obj/effect/title_card_object)) //huge image sleep sleep(CREDIT_SPAWN_SPEED * 3.3) count = 0 - if(count && !istype(/atom/movable/screen/map_view/char_preview)) + if(count && !istype(I, /atom/movable/screen/map_view/char_preview)) sleep(CREDIT_SPAWN_SPEED) _credits += new /atom/movable/screen/credit(null, I, src) From ecac25f1c79bc4bd567e165129511f1fe826c23c Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:35:42 -0700 Subject: [PATCH 116/158] Update credits_subsystem.dm --- .../code/modules/and_roll_credits/credits_subsystem.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm index 8f37379aa758..c57725417212 100644 --- a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm +++ b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm @@ -58,7 +58,7 @@ SUBSYSTEM_DEF(credits) appereance.update_body() appereance.maptext_width = 120 appereance.maptext_y = -8 - appereance.maptext_x = -64 + appereance.maptext_x = -52 appereance.maptext = "
[ckey]
" contributer_pref_images += appereance @@ -72,7 +72,7 @@ SUBSYSTEM_DEF(credits) var/atom/movable/screen/map_view/char_preview/appereance = new(null, mocked) appereance.update_body() appereance.maptext_width = 120 - appereance.maptext_x = -64 + appereance.maptext_x = -52 appereance.maptext_y = -8 appereance.maptext = "
[ckey]
" admin_pref_images += appereance @@ -218,7 +218,7 @@ SUBSYSTEM_DEF(credits) appereance.appearance = preview.appearance appereance.maptext_width = 120 appereance.maptext_y = -8 - appereance.maptext_x = -64 + appereance.maptext_x = -52 appereance.maptext = "
[client.mob.real_name]
" created_appearances += appereance return created_appearances From f63f631507f9d198c45411e7d05d5cf3a49dce6b Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:47:57 -0700 Subject: [PATCH 117/158] wowie --- code/modules/surgery/organs/stomach/_stomach.dm | 2 +- monkestation/code/modules/and_roll_credits/_credits.dm | 4 ++-- .../code/modules/and_roll_credits/credits_subsystem.dm | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/code/modules/surgery/organs/stomach/_stomach.dm b/code/modules/surgery/organs/stomach/_stomach.dm index f1e2db0e52b7..3fc35209f151 100644 --- a/code/modules/surgery/organs/stomach/_stomach.dm +++ b/code/modules/surgery/organs/stomach/_stomach.dm @@ -159,7 +159,7 @@ hunger_rate *= hunger_modifier hunger_rate *= human.physiology.hunger_mod - human.adjust_nutrition(-1 * hunger_rate * seconds_per_tick) + human.adjust_nutrition(-1 * hunger_rate * seconds_per_tick * HUNGER_FACTOR) var/nutrition = human.nutrition if(nutrition > NUTRITION_LEVEL_FULL) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index 19023daa134a..8eb8818a8214 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -25,7 +25,7 @@ var/y_offset = 0 for(var/i in 1 to length(admins)) - var/x_offset = -100 + var/x_offset = -80 for(var/b in 1 to 8) if(b == 1) y_offset = 0 @@ -41,7 +41,7 @@ var/list/contributors = shuffle(SScredits.contributer_pref_images) for(var/i in 1 to length(contributors)) - var/x_offset = -100 + var/x_offset = -80 for(var/b in 1 to 8) if(b == 1) y_offset = 0 diff --git a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm index c57725417212..2d2c8198f410 100644 --- a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm +++ b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm @@ -58,7 +58,7 @@ SUBSYSTEM_DEF(credits) appereance.update_body() appereance.maptext_width = 120 appereance.maptext_y = -8 - appereance.maptext_x = -52 + appereance.maptext_x = -42 appereance.maptext = "
[ckey]
" contributer_pref_images += appereance @@ -72,7 +72,7 @@ SUBSYSTEM_DEF(credits) var/atom/movable/screen/map_view/char_preview/appereance = new(null, mocked) appereance.update_body() appereance.maptext_width = 120 - appereance.maptext_x = -52 + appereance.maptext_x = -42 appereance.maptext_y = -8 appereance.maptext = "
[ckey]
" admin_pref_images += appereance @@ -218,7 +218,7 @@ SUBSYSTEM_DEF(credits) appereance.appearance = preview.appearance appereance.maptext_width = 120 appereance.maptext_y = -8 - appereance.maptext_x = -52 + appereance.maptext_x = -42 appereance.maptext = "
[client.mob.real_name]
" created_appearances += appereance return created_appearances From 597e93cba533de4d5dc69969a23f9215fbd92432 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 15:02:54 -0700 Subject: [PATCH 118/158] Update _credits.dm --- monkestation/code/modules/and_roll_credits/_credits.dm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index 8eb8818a8214..7dc90e9d4b62 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -24,11 +24,10 @@ var/list/admins = shuffle(SScredits.admin_pref_images) var/y_offset = 0 - for(var/i in 1 to length(admins)) + var/admin_length = length(admins) + for(var/i in 1 to admin_length) var/x_offset = -80 for(var/b in 1 to 8) - if(b == 1) - y_offset = 0 var/atom/movable/screen/map_view/char_preview/picked = pick_n_take(admins) if(!picked) break @@ -40,7 +39,8 @@ credit_order_for_this_round += "
Our Lovely Contributors
" var/list/contributors = shuffle(SScredits.contributer_pref_images) - for(var/i in 1 to length(contributors)) + var/contributors_length = length(contributors) + for(var/i in 1 to contributors_length) var/x_offset = -80 for(var/b in 1 to 8) if(b == 1) From da9afaf0a72dd67a3c446de7c680d161f9b627f9 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 19:52:57 -0700 Subject: [PATCH 119/158] Update _credits.dm --- monkestation/code/modules/and_roll_credits/_credits.dm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index 7dc90e9d4b62..0b08d74162ac 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -26,7 +26,7 @@ var/y_offset = 0 var/admin_length = length(admins) for(var/i in 1 to admin_length) - var/x_offset = -80 + var/x_offset = -60 for(var/b in 1 to 8) var/atom/movable/screen/map_view/char_preview/picked = pick_n_take(admins) if(!picked) @@ -41,7 +41,7 @@ var/contributors_length = length(contributors) for(var/i in 1 to contributors_length) - var/x_offset = -80 + var/x_offset = -60 for(var/b in 1 to 8) if(b == 1) y_offset = 0 @@ -57,14 +57,14 @@ credit_order_for_this_round += i var/list/returned_images = SScredits.resolve_clients(SScredits.major_event_icons[i], i) for(var/y in 1 to length(returned_images)) - var/x_offset = 80 - for(var/b in 1 to 4) + var/x_offset = -60 + for(var/b in 1 to 8) var/atom/movable/screen/map_view/char_preview/client_image = pick_n_take(returned_images) if(!client_image) break client_image.pixel_x = x_offset client_image.pixel_y = y_offset - x_offset += 40 + x_offset += 70 credit_order_for_this_round += client_image var/count = 0 From 3695417ec67e3ad72df56737533165ec69050f58 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 19:53:31 -0700 Subject: [PATCH 120/158] Update _credits.dm --- monkestation/code/modules/and_roll_credits/_credits.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index 0b08d74162ac..b583079344e3 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -1,7 +1,7 @@ -#define CREDIT_ROLL_SPEED 125 -#define CREDIT_SPAWN_SPEED 10 +#define CREDIT_ROLL_SPEED 9 SECONDS +#define CREDIT_SPAWN_SPEED 1 SECONDS #define CREDIT_ANIMATE_HEIGHT (16 * world.icon_size) -#define CREDIT_EASE_DURATION 22 +#define CREDIT_EASE_DURATION 2.2 SECONDS #define CREDITS_PATH "[global.config.directory]/contributors.dmi" /client/proc/RollCredits() From 63c7842620cb0fc99a0444c14067bfeb2409e4d0 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 22 Sep 2024 20:59:28 -0700 Subject: [PATCH 121/158] Update _credits.dm --- monkestation/code/modules/and_roll_credits/_credits.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monkestation/code/modules/and_roll_credits/_credits.dm b/monkestation/code/modules/and_roll_credits/_credits.dm index b583079344e3..de37f7c4d0fe 100644 --- a/monkestation/code/modules/and_roll_credits/_credits.dm +++ b/monkestation/code/modules/and_roll_credits/_credits.dm @@ -26,7 +26,7 @@ var/y_offset = 0 var/admin_length = length(admins) for(var/i in 1 to admin_length) - var/x_offset = -60 + var/x_offset = -40 for(var/b in 1 to 8) var/atom/movable/screen/map_view/char_preview/picked = pick_n_take(admins) if(!picked) @@ -41,7 +41,7 @@ var/contributors_length = length(contributors) for(var/i in 1 to contributors_length) - var/x_offset = -60 + var/x_offset = -40 for(var/b in 1 to 8) if(b == 1) y_offset = 0 @@ -57,7 +57,7 @@ credit_order_for_this_round += i var/list/returned_images = SScredits.resolve_clients(SScredits.major_event_icons[i], i) for(var/y in 1 to length(returned_images)) - var/x_offset = -60 + var/x_offset = -40 for(var/b in 1 to 8) var/atom/movable/screen/map_view/char_preview/client_image = pick_n_take(returned_images) if(!client_image) From 1ff9bfb13d1d0af90e979005a8fcd4f91c325137 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 23 Sep 2024 21:28:15 -0700 Subject: [PATCH 122/158] changes --- code/__DEFINES/mobs.dm | 2 +- code/modules/surgery/organs/stomach/_stomach.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 276a14c053bd..4afce82c8754 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -456,7 +456,7 @@ /// What % of hunger is used by homeostasis #define HOMEOSTASIS_HUNGER_MULTIPLIER 0.1 /// What % of hunger is used by passive hunger -#define PASSIVE_HUNGER_MULTIPLIER 0.7 +#define PASSIVE_HUNGER_MULTIPLIER 0.4 /// What % of hunger is used by movement #define MOVEMENT_HUNGER_MULTIPLIER 0.1 diff --git a/code/modules/surgery/organs/stomach/_stomach.dm b/code/modules/surgery/organs/stomach/_stomach.dm index 3fc35209f151..f1e2db0e52b7 100644 --- a/code/modules/surgery/organs/stomach/_stomach.dm +++ b/code/modules/surgery/organs/stomach/_stomach.dm @@ -159,7 +159,7 @@ hunger_rate *= hunger_modifier hunger_rate *= human.physiology.hunger_mod - human.adjust_nutrition(-1 * hunger_rate * seconds_per_tick * HUNGER_FACTOR) + human.adjust_nutrition(-1 * hunger_rate * seconds_per_tick) var/nutrition = human.nutrition if(nutrition > NUTRITION_LEVEL_FULL) From 750907d36337bea131e0bc12893e9b9a644db9ca Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 24 Sep 2024 10:27:52 -0700 Subject: [PATCH 123/158] changes --- code/__DEFINES/mobs.dm | 2 +- code/modules/surgery/organs/stomach/stomach_ethereal.dm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 4afce82c8754..ac50796b5427 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -461,7 +461,7 @@ #define MOVEMENT_HUNGER_MULTIPLIER 0.1 /// Factor at which ethereal's charge decreases per second -#define ETHEREAL_CHARGE_FACTOR 0.8 +#define ETHEREAL_CHARGE_FACTOR 0.2 /// How much nutrition eating clothes as moth gives and drains #define CLOTHING_NUTRITION_GAIN 15 #define REAGENTS_METABOLISM 0.2 //How many units of reagent are consumed per second, by default. diff --git a/code/modules/surgery/organs/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/stomach/stomach_ethereal.dm index 46c9abd7236d..c0ff1e781111 100644 --- a/code/modules/surgery/organs/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/stomach/stomach_ethereal.dm @@ -2,7 +2,7 @@ name = "biological battery" icon_state = "stomach-p" //Welp. At least it's more unique in functionaliy. desc = "A crystal-like organ that stores the electric charge of ethereals." - hunger_modifier = 0.5 + hunger_modifier = 0 //they do different hunger shit //organ_traits = list(TRAIT_NOHUNGER) // We have our own hunger mechanic. //Monkestation Removal, we have our OWN hunger mechanic. ///basically satiety but electrical var/crystal_charge = ETHEREAL_CHARGE_FULL @@ -39,7 +39,7 @@ /obj/item/organ/internal/stomach/ethereal/proc/handle_temp(mob/living/carbon/human/human, natural_change, seconds_per_tick) SIGNAL_HANDLER - adjust_charge(-0.5 * ETHEREAL_CHARGE_FACTOR * abs(natural_change) * seconds_per_tick * 0.01) + adjust_charge(-0.5 * ETHEREAL_CHARGE_FACTOR * abs(natural_change * 0.1) * seconds_per_tick * 0.01) return HOMEOSTASIS_NO_HUNGER /obj/item/organ/internal/stomach/ethereal/proc/blood(mob/living/carbon/human/ethereal, seconds_per_tick, times_fired) From 330f755bc0e6a21ff2327b2cb898e3fe6fe87eeb Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 24 Sep 2024 19:27:40 -0700 Subject: [PATCH 124/158] removed banned members plushie --- .../modules/donator/code/datum/loadout.dm | 19 ------------------- .../code/modules/donator/code/item/effects.dm | 7 ------- .../code/modules/donator/code/item/plush.dm | 6 ------ .../code/modules/donator/code/mob/pets.dm | 13 ------------- 4 files changed, 45 deletions(-) diff --git a/monkestation/code/modules/donator/code/datum/loadout.dm b/monkestation/code/modules/donator/code/datum/loadout.dm index fa331db1be00..fa2c98b724cf 100644 --- a/monkestation/code/modules/donator/code/datum/loadout.dm +++ b/monkestation/code/modules/donator/code/datum/loadout.dm @@ -365,25 +365,6 @@ donator_only = TRUE requires_purchase = FALSE -/datum/loadout_item/toys/quilark - name = "Quilark Plush" - item_path = /obj/item/toy/plush/quilark - donator_only = TRUE - requires_purchase = FALSE - -/datum/loadout_item/pocket_items/donator/quilava - name = "Pet Delivery Beacon - Quil Maid" - item_path = /obj/item/choice_beacon/pet/donator/quilava - donator_only = TRUE - requires_purchase = FALSE - ckeywhitelist = list("quilark") - -/datum/loadout_item/effects/quilava - ckeywhitelist = list("quilark") - name = "Quil Maid Transformation" - item_path = /obj/item/effect_granter/donator/quilava - requires_purchase = FALSE - /datum/loadout_item/suit/org_thirteen name = "Organization 13 Cloak" item_path = /obj/item/clothing/suit/hooded/org_thirteen diff --git a/monkestation/code/modules/donator/code/item/effects.dm b/monkestation/code/modules/donator/code/item/effects.dm index 95301950c4ba..be1d463c682c 100644 --- a/monkestation/code/modules/donator/code/item/effects.dm +++ b/monkestation/code/modules/donator/code/item/effects.dm @@ -73,13 +73,6 @@ icon_state = "crab_plant" animal_transformation = /mob/living/basic/crab/plant - -//Quilark -/obj/item/effect_granter/donator/quilava - name = "quilava transformation" - icon_state = "quil_maid" - animal_transformation = /mob/living/basic/pet/quilmaid - //ellie /obj/item/effect_granter/donator/gumball_goblin name = "gumball goblin transformation" diff --git a/monkestation/code/modules/donator/code/item/plush.dm b/monkestation/code/modules/donator/code/item/plush.dm index ccaa9be963f5..28b856ec7899 100644 --- a/monkestation/code/modules/donator/code/item/plush.dm +++ b/monkestation/code/modules/donator/code/item/plush.dm @@ -62,12 +62,6 @@ icon = 'monkestation/code/modules/donator/icons/obj/plushes.dmi' icon_state = "lief_flos" -/obj/item/toy/plush/quilark - name = "quilark plush" - desc = "A plush of the Lizard Basil. ~Handcrafted lovingly for quilark" - icon = 'monkestation/code/modules/donator/icons/obj/plushes.dmi' - icon_state = "quilark" - /obj/item/toy/plush/gumball_goblin name = "gumball goblin plush" desc = "A plush of a Gumball Goblin. He was abducted while pondering his gumballs. Help. ~Handcrafted lovingly for elliethedarksun" diff --git a/monkestation/code/modules/donator/code/mob/pets.dm b/monkestation/code/modules/donator/code/mob/pets.dm index 580456ffbd58..d695c5f854f6 100644 --- a/monkestation/code/modules/donator/code/mob/pets.dm +++ b/monkestation/code/modules/donator/code/mob/pets.dm @@ -155,19 +155,6 @@ ckeywhitelist = list("Rickdude1231") -/mob/living/basic/pet/quilmaid - name = "\improper Quil' Maid" - desc = "Someone dressed up this Space-e-mon in a maid outfit." - icon = 'monkestation/code/modules/donator/icons/mob/pets.dmi' - icon_state = "quil_maid" - icon_living = "quil_maid" - icon_dead = "quil_maid" - icon_gib = null - gold_core_spawnable = NO_SPAWN - ai_controller = /datum/ai_controller/basic_controller/ - - ckeywhitelist = list("quilark") - /mob/living/basic/pet/gumball_goblin name = "Gumball Goblin" desc = "AAAAAAAAAAAAAAAA" From d3465a23e17cb21057c786a0f2ef69e0afd2be2e Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 25 Sep 2024 14:55:56 -0700 Subject: [PATCH 125/158] ad --- monkestation/code/modules/donator/code/item/choice_beacon.dm | 5 ----- .../ghost_critters/ghost_critter_mobs/donator_mobs.dm | 1 - 2 files changed, 6 deletions(-) diff --git a/monkestation/code/modules/donator/code/item/choice_beacon.dm b/monkestation/code/modules/donator/code/item/choice_beacon.dm index 63ffba779d6e..1987c1a4c559 100644 --- a/monkestation/code/modules/donator/code/item/choice_beacon.dm +++ b/monkestation/code/modules/donator/code/item/choice_beacon.dm @@ -76,11 +76,6 @@ default_name = "Plant Crab" donator_pet = /mob/living/basic/crab/plant -/obj/item/choice_beacon/pet/donator/quilava - name = "Quil Maid" - default_name = "Quil Maid" - donator_pet = /mob/living/basic/pet/quilmaid - /obj/item/choice_beacon/pet/donator/gumball_goblin name = "Gumball Goblin" default_name = "Gumball Goblin" diff --git a/monkestation/code/modules/ghost_critters/ghost_critter_mobs/donator_mobs.dm b/monkestation/code/modules/ghost_critters/ghost_critter_mobs/donator_mobs.dm index 0c852b29ef40..e63c578761f3 100644 --- a/monkestation/code/modules/ghost_critters/ghost_critter_mobs/donator_mobs.dm +++ b/monkestation/code/modules/ghost_critters/ghost_critter_mobs/donator_mobs.dm @@ -12,7 +12,6 @@ /mob/living/basic/pet/spider/dancing, /mob/living/basic/butterfly/void, /mob/living/basic/crab/plant, - /mob/living/basic/pet/quilmaid, ) if(is_admin(src)) From 23be41d2b871f9be146c539931a982baf876d7fe Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 25 Sep 2024 23:04:32 -0700 Subject: [PATCH 126/158] teratoma fixes --- .../carbon/human/species_type/teratoma.dm | 32 ++++++------------- .../surgery/bodyparts/teratoma_bodyparts.dm | 13 +++++++- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm index a34c3c15b1cd..25813b798d75 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm @@ -5,19 +5,13 @@ mutanttongue = /obj/item/organ/internal/tongue/monkey mutantbrain = /obj/item/organ/internal/brain/primate - species_traits = list( - NOAUGMENTS, - NOBLOODOVERLAY, - NOEYESPRITES, - NOTRANSSTING, - NOZOMBIE, - NO_DNA_COPY, - NO_UNDERWEAR, - ) inherent_traits = list( + TRAIT_NO_TRANSFORMATION_STING, + TRAIT_NO_BLOOD_OVERLAY, + TRAIT_NO_DNA_COPY, + TRAIT_NO_UNDERWEAR, TRAIT_BADDNA, TRAIT_CAN_STRIP, - TRAIT_CHUNKYFINGERS, TRAIT_EASILY_WOUNDED, TRAIT_GENELESS, TRAIT_ILLITERATE, @@ -25,11 +19,8 @@ TRAIT_NO_DNA_COPY, TRAIT_NO_JUMPSUIT, TRAIT_NO_ZOMBIFY, - TRAIT_PASSTABLE, TRAIT_PRIMITIVE, TRAIT_UNCONVERTABLE, // DEAR GOD NO - TRAIT_VAULTING, - TRAIT_VENTCRAWLER_ALWAYS, TRAIT_WEAK_SOUL, ) @@ -41,15 +32,13 @@ BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/teratoma, BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/teratoma, ) + mutanttongue = /obj/item/organ/internal/tongue/teratoma maxhealthmod = 0.75 stunmod = 1.4 - speedmod = -0.15 // stupid gremlins no_equip_flags = ITEM_SLOT_ICLOTHING | ITEM_SLOT_OCLOTHING | ITEM_SLOT_GLOVES | ITEM_SLOT_FEET | ITEM_SLOT_SUITSTORE changesource_flags = MIRROR_BADMIN - liked_food = MEAT | BUGS | GORE | GROSS | RAW - disliked_food = CLOTH sexes = FALSE species_language_holder = /datum/language_holder/monkey @@ -72,13 +61,6 @@ /datum/species/teratoma/random_name(gender, unique, lastname) return "teratoma ([rand(1, 999)])" -// Don't let them use chems that could potential change them into something non-teratoma. -/datum/species/teratoma/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/goober, seconds_per_tick, times_fired) - if(is_banned_chem(chem)) - chem.holder?.del_reagent(chem.type) - return TRUE - return ..() - // removes banned reagents from the list of reagents that'll be exposed /datum/species/teratoma/proc/prevent_banned_reagent_exposure(datum/source, list/reagents, datum/reagents/holder, methods, volume_modifier, show_message) SIGNAL_HANDLER @@ -118,3 +100,7 @@ /mob/living/carbon/human/species/teratoma race = /datum/species/teratoma + +/obj/item/organ/internal/tongue/teratoma + liked_foodtypes = MEAT | BUGS | GORE | GROSS | RAW + disliked_foodtypes = CLOTH diff --git a/monkestation/code/modules/surgery/bodyparts/teratoma_bodyparts.dm b/monkestation/code/modules/surgery/bodyparts/teratoma_bodyparts.dm index 807f413ff393..fc9602239634 100644 --- a/monkestation/code/modules/surgery/bodyparts/teratoma_bodyparts.dm +++ b/monkestation/code/modules/surgery/bodyparts/teratoma_bodyparts.dm @@ -7,6 +7,7 @@ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM should_draw_greyscale = FALSE head_flags = HEAD_LIPS | HEAD_DEBRAIN + composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 1) dmg_overlay_type = "monkey" @@ -18,6 +19,7 @@ is_dimorphic = FALSE bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM should_draw_greyscale = FALSE + composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 1) dmg_overlay_type = "monkey" @@ -28,6 +30,8 @@ limb_id = SPECIES_TERATOMA bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM should_draw_greyscale = FALSE + hand_traits = list(TRAIT_CHUNKYFINGERS) + composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 1) dmg_overlay_type = "monkey" @@ -38,6 +42,8 @@ limb_id = SPECIES_TERATOMA bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM should_draw_greyscale = FALSE + hand_traits = list(TRAIT_CHUNKYFINGERS) + composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 1) dmg_overlay_type = "monkey" @@ -48,7 +54,10 @@ limb_id = SPECIES_TERATOMA bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM should_draw_greyscale = FALSE + speed_modifier = -0.075 footprint_sprite = FOOTPRINT_SPRITE_PAWS + bodypart_traits = list(TRAIT_VAULTING) + composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 1) /obj/item/bodypart/leg/right/teratoma icon_static = 'monkestation/icons/mob/species/teratoma/bodyparts.dmi' @@ -58,5 +67,7 @@ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM should_draw_greyscale = FALSE footprint_sprite = FOOTPRINT_SPRITE_PAWS - + speed_modifier = -0.075 dmg_overlay_type = "monkey" + bodypart_traits = list(TRAIT_VAULTING) + composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 1) From 2d74a7905fdbef973b8e87515da0fb15c36d4197 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:37:56 -0700 Subject: [PATCH 127/158] adjustments --- code/modules/projectiles/projectile/beams.dm | 2 +- .../code/modules/blood_datum/debilitated.dm | 13 ------------- .../code/modules/security/code/weapons/paco.dm | 2 +- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index df3a8a67ea3f..3266a8a309ee 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -105,7 +105,7 @@ icon_state = "omnilaser" damage = 0 damage_type = STAMINA - stamina = 45 + stamina = 35 paralyze_timer = 5 SECONDS armor_flag = ENERGY impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser diff --git a/monkestation/code/modules/blood_datum/debilitated.dm b/monkestation/code/modules/blood_datum/debilitated.dm index 374b2079d24e..410f8a531206 100644 --- a/monkestation/code/modules/blood_datum/debilitated.dm +++ b/monkestation/code/modules/blood_datum/debilitated.dm @@ -12,10 +12,6 @@ alert_type = /atom/movable/screen/alert/status_effect/debilitated status_type = STATUS_EFFECT_REFRESH - ///our base stamina damage increase on stamina projectiles - var/base_increase = 10 - ///our increase per stack - var/per_stack_increase = 5 ///our base stamina loss multiplier var/loss_multiplier = 1 ///our per stack increase to stamina loss @@ -28,7 +24,6 @@ if(ishuman(owner)) var/mob/living/carbon/human/human = owner cached_stamina = human.physiology.temp_stamina_mod - RegisterSignal(owner, COMSIG_ATOM_BULLET_ACT, PROC_REF(check_bullet)) /datum/status_effect/stacking/debilitated/add_stacks(stacks_added) . = ..() @@ -37,14 +32,6 @@ var/mob/living/carbon/human/human = owner human.physiology.temp_stamina_mod = loss_multiplier + (stacks * per_stack_multiplier_increase) -/datum/status_effect/stacking/debilitated/proc/check_bullet(mob/living/carbon/human/source, obj/projectile/hitting_projectile, def_zone) - SIGNAL_HANDLER - - if(hitting_projectile.stamina < 10) - return - - source.stamina.adjust(-base_increase + (stacks * per_stack_increase), FALSE, TRUE) - /atom/movable/screen/alert/status_effect/debilitated icon_state = "debilitated" name = "Debilitated" diff --git a/monkestation/code/modules/security/code/weapons/paco.dm b/monkestation/code/modules/security/code/weapons/paco.dm index 4c35d122d24d..a78a6b0ca2d0 100644 --- a/monkestation/code/modules/security/code/weapons/paco.dm +++ b/monkestation/code/modules/security/code/weapons/paco.dm @@ -117,7 +117,7 @@ icon = 'monkestation/code/modules/security/icons/paco_ammo.dmi' icon_state = "rubber_bullet" damage = 4 - stamina = 45 // Turns out 35 stamina damage is not good enough. + stamina = 35 // Turns out 35 stamina damage is not good enough. sharpness = NONE embedding = null From c87b813ee00411d4197db365e512ab210a790e5a Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 27 Sep 2024 17:10:57 -0700 Subject: [PATCH 128/158] Update medicine_reagents.dm --- code/modules/reagents/chemistry/reagents/medicine_reagents.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 204cdcd6ee65..23ecc893fdbd 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -24,7 +24,7 @@ /datum/reagent/medicine/leporazine/on_mob_metabolize(mob/living/carbon/user) . = ..() - user.add_homeostasis_level(type, user.standard_body_temperature, 1 KELVIN) + user.add_homeostasis_level(type, user.standard_body_temperature, 4 KELVIN) /datum/reagent/medicine/leporazine/on_mob_end_metabolize(mob/living/carbon/user) . = ..() From 9ea7fcfc268ac84ec64becae97c3efe1ca5fbf66 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 27 Sep 2024 20:05:43 -0700 Subject: [PATCH 129/158] common runtime fixes --- code/modules/surgery/bodyparts/_bodyparts.dm | 3 ++- monkestation/code/modules/blood_datum/forensics_helpers.dm | 2 ++ monkestation/code/modules/virology/disease/symtoms/stage1.dm | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 2a67164dc70f..c7616f868943 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -932,7 +932,8 @@ if(owner_species.fixed_mut_color) species_color = owner_species.fixed_mut_color else - CRASH("Forgot to move something to new color_palette system [src]") + if(should_draw_greyscale) + CRASH("Forgot to move something to new color_palette system [src]") else skin_tone = "" species_color = "" diff --git a/monkestation/code/modules/blood_datum/forensics_helpers.dm b/monkestation/code/modules/blood_datum/forensics_helpers.dm index 3e7ee08b41e0..b866e245a9f2 100644 --- a/monkestation/code/modules/blood_datum/forensics_helpers.dm +++ b/monkestation/code/modules/blood_datum/forensics_helpers.dm @@ -32,6 +32,8 @@ // Imperfect, ends up with some blood types being double-set-up, but harmless (for now) for(var/new_blood in blood_DNA_to_add) var/datum/blood_type/blood = GLOB.blood_types[blood_DNA_to_add[new_blood]] + if(!blood) + continue blood.set_up_blood(src, first_dna == 0) update_appearance() return TRUE diff --git a/monkestation/code/modules/virology/disease/symtoms/stage1.dm b/monkestation/code/modules/virology/disease/symtoms/stage1.dm index 35080bc676a5..1c2493f2c63f 100644 --- a/monkestation/code/modules/virology/disease/symtoms/stage1.dm +++ b/monkestation/code/modules/virology/disease/symtoms/stage1.dm @@ -357,6 +357,8 @@ Heal(mob, effectiveness) /datum/symptom/water_heal/proc/CanHeal(mob/living/M) + if(!M) + return 1 var/base = 0 if(M.fire_stacks < 0) M.adjust_fire_stacks(min(absorption_coeff, -M.fire_stacks)) From fe248c5f656fc1cd0f3e86f752bb49ea9b219172 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 27 Sep 2024 23:19:50 -0700 Subject: [PATCH 130/158] converts to a config file --- .../objects/effects/decals/cleanable/humans.dm | 3 +++ config/contributors.txt | 0 .../modules/and_roll_credits/credits_subsystem.dm | 14 ++++++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 config/contributors.txt diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 5dace3a42a55..0d8f4e26bb9d 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -89,6 +89,9 @@ var/list/all_blood_names = list() for(var/dna_sample in all_dna) var/datum/blood_type/blood = GLOB.blood_types[all_dna[dna_sample]] + if(!blood) + all_blood_names |= "blood" + continue all_blood_names |= lowertext(initial(blood.reagent_type.name)) return english_list(all_blood_names, nothing_text = "blood") diff --git a/config/contributors.txt b/config/contributors.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm index 2d2c8198f410..02182c83c18a 100644 --- a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm +++ b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm @@ -28,13 +28,23 @@ SUBSYSTEM_DEF(credits) var/list/contributer_pref_images = list() var/list/admin_pref_images = list() var/list/major_event_icons = list() - var/list/contributors = list("dwasint", "absolucy", "wraith_54321", "thepooba") + var/list/contributors = list() /datum/controller/subsystem/credits/Initialize() - + load_contributors() generate_pref_images() return SS_INIT_SUCCESS +/datum/controller/subsystem/proc/load_contributors() + contributors = list() + var/list/lines = world.file2list("[global.config.directory]/contributors.txt") + for(var/line in lines) + if(!length(line)) + continue + if(findtextEx(line, "#", 1, 2)) + continue + contributors |= line + /datum/controller/subsystem/credits/proc/draft() draft_episode_names() draft_disclaimers() From f8acedfb250b131fdef1f4d4bb1a8fe585eba75f Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 27 Sep 2024 23:26:09 -0700 Subject: [PATCH 131/158] tweaks --- _maps/map_files/BoxStation/BoxStation.dmm | 40 ++++--------------- code/_globalvars/traits/_traits.dm | 5 +++ code/modules/mob/living/life.dm | 2 +- code/modules/surgery/bodyparts/_bodyparts.dm | 2 +- .../blood_datum/vital_monitor/vital_reader.dm | 8 ---- .../modules/the_bird_inside_of_me/organs.dm | 5 +++ 6 files changed, 19 insertions(+), 43 deletions(-) diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index ecc4383adecd..bd90ae4d51bc 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -20876,11 +20876,6 @@ /obj/effect/turf_decal/trimline/red/filled/line, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) -"gYb" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/white, -/area/station/medical/treatment_center) "gYt" = ( /obj/machinery/atmospherics/pipe/bridge_pipe/cyan/visible, /obj/machinery/atmospherics/pipe/layer_manifold/yellow/visible{ @@ -21048,13 +21043,10 @@ /turf/open/floor/iron/dark, /area/station/command/bridge) "has" = ( -/obj/structure/table, -/obj/item/paper_bin, -/obj/item/folder/blue, -/obj/item/pen, -/obj/item/stamp/head/hop, -/turf/open/floor/carpet/royalblue, -/area/station/command/heads_quarters/hop) +/obj/machinery/suit_storage_unit/standard_unit, +/obj/effect/turf_decal/bot_red, +/turf/open/floor/iron, +/area/station/ai_monitored/command/storage/eva) "haz" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 4 @@ -41899,7 +41891,6 @@ /area/station/ai_monitored/turret_protected/aisat/atmos) "ojw" = ( /obj/structure/closet/crate/hydroponics, -/obj/item/botanical_lexicon, /obj/item/seeds/tree, /obj/effect/spawner/random/contraband/prison, /obj/item/seeds/pumpkin, @@ -58221,23 +58212,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white, /area/station/medical/treatment_center) -"tyX" = ( -/obj/structure/closet/crate/hydroponics, -/obj/item/book/manual/botanical_lexicon, -/obj/item/seeds/tree, -/obj/effect/spawner/random/contraband/prison, -/obj/item/seeds/pumpkin, -/obj/item/seeds/wheat, -/obj/item/seeds/ambrosia, -/obj/item/seeds/grass, -/obj/item/seeds/carrot, -/obj/item/seeds/tomato, -/obj/item/seeds/potato, -/obj/item/seeds/garlic, -/obj/item/seeds/onion, -/obj/item/paper/guides/jobs/hydroponics, -/turf/open/floor/iron/dark, -/area/station/security/prison/garden) "tzc" = ( /obj/effect/spawner/random/engineering/tank, /turf/open/floor/plating, @@ -99163,7 +99137,7 @@ eFO lFc yfR mqu -has +tyF sCt bni vMZ @@ -99390,7 +99364,7 @@ nZL kOK nVk rfW -tyP +has mRF oOm rTP @@ -123580,7 +123554,7 @@ iRE pCO pCO faQ -gYb +tyG mHx bUp bcL diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index dae0b5ee1fde..bf32a09069c3 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -317,6 +317,11 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_MULTIZ_SUIT_SENSORS" = TRAIT_MULTIZ_SUIT_SENSORS, "TRAIT_MUSICIAN" = TRAIT_MUSICIAN, "TRAIT_MUTANT_COLORS" = TRAIT_MUTANT_COLORS, + "TRAIT_MUTANT_COLORS_SECONDARY" = TRAIT_MUTANT_COLORS_SECONDARY, + "TRAIT_FUR_COLORS" = TRAIT_FUR_COLORS, + "TRAIT_NO_TRANSFORMATION_STING" = TRAIT_NO_TRANSFORMATION_STING, + "TRAIT_NO_HUSK" = TRAIT_NO_HUSK, + "TRAIT_HAS_MARKINGS" = TRAIT_HAS_MARKINGS, "TRAIT_MUTE" = TRAIT_MUTE, "TRAIT_NAIVE" = TRAIT_NAIVE, "TRAIT_NANITE_MONITORING" = TRAIT_NANITE_MONITORING, diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index a067831eac12..36df39e4167c 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -130,7 +130,7 @@ adjust_bodytemperature(temp_change * seconds_per_tick) // No use_insulation because we manually account for it /mob/living/proc/get_insulated_equilibrium_temperature(environment_temp, insulation) - return environment_temp + (standard_body_temperature - environment_temp) * insulation + return environment_temp + (standard_body_temperature - environment_temp) * insulation /mob/living/silicon/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) return // Not yet diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index c7616f868943..b40f7348c041 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -402,7 +402,7 @@ pixel_y = rand(-3, 3) /obj/item/bodypart/drop_location() - return ..() || owner?.drop_location() + return ..() || owner?.drop_location() //empties the bodypart from its organs and other things inside it /obj/item/bodypart/proc/drop_organs(mob/user, violent_removal) diff --git a/monkestation/code/modules/blood_datum/vital_monitor/vital_reader.dm b/monkestation/code/modules/blood_datum/vital_monitor/vital_reader.dm index 2a47aab83218..27634b075d66 100644 --- a/monkestation/code/modules/blood_datum/vital_monitor/vital_reader.dm +++ b/monkestation/code/modules/blood_datum/vital_monitor/vital_reader.dm @@ -82,14 +82,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader/advanced, 32) MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/vitals_reader/no_hand, 32) -/obj/machinery/computer/vitals_reader/Initialize(mapload, obj/item/circuitboard/C) - . = ..() - register_context() - -/obj/machinery/computer/vitals_reader/Destroy() - unset_patient() - return ..() - /obj/machinery/computer/vitals_reader/attackby(obj/item/weapon, mob/living/user, params) if(!istype(user) || (user.istate & ISTATE_HARM)) return ..() diff --git a/monkestation/code/modules/the_bird_inside_of_me/organs.dm b/monkestation/code/modules/the_bird_inside_of_me/organs.dm index fffe88683d49..7782e7b09b78 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/organs.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/organs.dm @@ -19,6 +19,11 @@ RegisterSignal(src, COMSIG_INSTRUMENT_START, PROC_REF(start_sound_particles)) RegisterSignal(src, COMSIG_INSTRUMENT_END, PROC_REF(stop_sound_particles)) +/obj/item/organ/internal/tongue/ornithid/Destroy() + . = ..() + QDEL_NULL(song) + UnregisterSignal(src, list(COMSIG_INSTRUMENT_START, COMSIG_INSTRUMENT_END)) + /obj/item/organ/internal/tongue/ornithid/Insert(mob/living/carbon/tongue_owner, special, drop_if_replaced) . = ..() if(QDELETED(sing)) From 5cedc3cc85477c85b43a4ec254ed4e225ac3c38c Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 27 Sep 2024 23:27:20 -0700 Subject: [PATCH 132/158] pete --- _maps/map_files/IceBoxStation/IceBoxStation.dmm | 7 +------ .../basic/farm_animals/goat/goat_subtypes.dm | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 998802b8844e..bef001a2cd8f 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -69657,12 +69657,7 @@ /turf/closed/wall/r_wall, /area/station/hallway/primary/fore) "wqE" = ( -/mob/living/basic/goat/pete{ - desc = "Not known for their pleasant disposition. This one seems a bit more hardy to the cold."; - habitable_atmos = list("min_oxy"=1,"max_oxy"=0,"min_plas"=0,"max_plas"=1,"min_co2"=0,"max_co2"=5,"min_n2"=0,"max_n2"=0); - minimum_survivable_temperature = 150; - name = "Snowy Pete" - }, +/mob/living/basic/goat/pete/icebox, /turf/open/misc/asteroid/snow/coldroom, /area/station/service/kitchen/coldroom) "wqI" = ( diff --git a/code/modules/mob/living/basic/farm_animals/goat/goat_subtypes.dm b/code/modules/mob/living/basic/farm_animals/goat/goat_subtypes.dm index 19d50fb38097..848c3789c7ad 100644 --- a/code/modules/mob/living/basic/farm_animals/goat/goat_subtypes.dm +++ b/code/modules/mob/living/basic/farm_animals/goat/goat_subtypes.dm @@ -10,3 +10,18 @@ /mob/living/basic/goat/pete/add_udder() return //no thank you + +/mob/living/basic/goat/pete/icebox + name = "Snowy Pete" + desc = parent_type::desc + " This one seems a bit more hardy to the cold." + bodytemp_cold_damage_limit = ICEBOX_MIN_TEMPERATURE - 5 KELVIN + habitable_atmos = list( + "min_oxy" = 1, + "max_oxy"= 0, + "min_plas" = 0, + "max_plas" = 1, + "min_co2" = 0, + "max_co2" = 5, + "min_n2" = 0, + "max_n2" = 0, + ) From 2ed6dd9f10b402d291f0606a9b727125a44b8acc Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 27 Sep 2024 23:31:41 -0700 Subject: [PATCH 133/158] whoops --- monkestation/code/modules/and_roll_credits/credits_subsystem.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm index 02182c83c18a..f3d4360f9ee4 100644 --- a/monkestation/code/modules/and_roll_credits/credits_subsystem.dm +++ b/monkestation/code/modules/and_roll_credits/credits_subsystem.dm @@ -35,7 +35,7 @@ SUBSYSTEM_DEF(credits) generate_pref_images() return SS_INIT_SUCCESS -/datum/controller/subsystem/proc/load_contributors() +/datum/controller/subsystem/credits/proc/load_contributors() contributors = list() var/list/lines = world.file2list("[global.config.directory]/contributors.txt") for(var/line in lines) From f8e1201cb16100e108695f98cfd6827903c6c393 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 28 Sep 2024 00:32:28 -0700 Subject: [PATCH 134/158] screams and laughs refactored --- code/datums/elements/footstep.dm | 10 +- .../mob/living/carbon/human/_species.dm | 6 - .../carbon/human/species_types/android.dm | 2 - .../carbon/human/species_types/ethereal.dm | 7 - .../carbon/human/species_types/golems.dm | 1 - .../carbon/human/species_types/humans.dm | 21 --- .../human/species_types/lizardpeople.dm | 7 - .../carbon/human/species_types/monkeys.dm | 11 -- .../carbon/human/species_types/mothmen.dm | 3 - .../carbon/human/species_types/plasmamen.dm | 7 - .../carbon/human/species_types/zombies.dm | 13 +- code/modules/mob/living/emote.dm | 3 +- code/modules/mob/living/living_defines.dm | 2 + code/modules/surgery/bodyparts/parts.dm | 2 + .../bodyparts/species_parts/android_parts.dm | 2 + .../species_parts/lizard_bodyparts.dm | 12 ++ .../surgery/organs/internal/tongue/_tongue.dm | 124 ++++++++++++++++++ .../modules/botany/species/apid/species.dm | 13 +- .../code/modules/emotes/code/emote.dm | 3 +- .../mob/living/carbon/human/_species.dm | 4 - .../carbon/human/species_type/abductors.dm | 6 - .../carbon/human/species_type/android.dm | 10 -- .../carbon/human/species_type/arachnid.dm | 6 - .../carbon/human/species_type/dullahan.dm | 25 ---- .../carbon/human/species_type/ethereal.dm | 10 -- .../carbon/human/species_type/floran.dm | 11 -- .../carbon/human/species_type/flypeople.dm | 27 ---- .../carbon/human/species_type/goblin.dm | 27 ---- .../carbon/human/species_type/golems.dm | 25 ---- .../carbon/human/species_type/humans.dm | 5 - .../carbon/human/species_type/jellypeople.dm | 25 ---- .../carbon/human/species_type/lizardpeople.dm | 26 ---- .../carbon/human/species_type/monkeys.dm | 2 - .../carbon/human/species_type/mothmen.dm | 6 - .../carbon/human/species_type/plasmamen.dm | 3 - .../carbon/human/species_type/podpeople.dm | 25 ---- .../carbon/human/species_type/shadowpeople.dm | 25 ---- .../carbon/human/species_type/simian.dm | 14 -- .../carbon/human/species_type/skeletons.dm | 6 - .../carbon/human/species_type/teratoma.dm | 11 -- .../carbon/human/species_type/zombies.dm | 25 ---- .../code/modules/ranching/satyr/bodyparts.dm | 14 ++ .../code/modules/ranching/satyr/species.dm | 7 - .../smithing/ipcs/body/base_bodyparts.dm | 2 + .../smithing/ipcs/body/internal_organs.dm | 10 ++ .../code/modules/smithing/ipcs/species.dm | 11 -- .../modules/smithing/oozelings/species.dm | 26 ---- .../modules/surgery/organs/internal/tongue.dm | 6 + .../temperature_overhaul/homeostasis_level.dm | 4 +- .../modules/the_bird_inside_of_me/species.dm | 22 ++-- tgstation.dme | 9 -- 51 files changed, 223 insertions(+), 461 deletions(-) delete mode 100644 monkestation/code/modules/mob/living/carbon/human/species_type/dullahan.dm delete mode 100644 monkestation/code/modules/mob/living/carbon/human/species_type/golems.dm delete mode 100644 monkestation/code/modules/mob/living/carbon/human/species_type/humans.dm delete mode 100644 monkestation/code/modules/mob/living/carbon/human/species_type/jellypeople.dm delete mode 100644 monkestation/code/modules/mob/living/carbon/human/species_type/monkeys.dm delete mode 100644 monkestation/code/modules/mob/living/carbon/human/species_type/mothmen.dm delete mode 100644 monkestation/code/modules/mob/living/carbon/human/species_type/podpeople.dm delete mode 100644 monkestation/code/modules/mob/living/carbon/human/species_type/shadowpeople.dm delete mode 100644 monkestation/code/modules/mob/living/carbon/human/species_type/zombies.dm diff --git a/code/datums/elements/footstep.dm b/code/datums/elements/footstep.dm index f3e5176d0972..1bc10f91bd4d 100644 --- a/code/datums/elements/footstep.dm +++ b/code/datums/elements/footstep.dm @@ -146,8 +146,14 @@ footstep_sounds[shoestep_type][3] + e_range + range_adjustment, falloff_distance = 1, vary = sound_vary, mixer_channel = CHANNEL_SOUND_FOOTSTEPS) else var/barefoot_type = prepared_steps[FOOTSTEP_MOB_BAREFOOT] - if(source.dna.species.special_step_sounds) - heard_clients = playsound(source.loc, pick(source.dna.species.special_step_sounds), 50, TRUE, falloff_distance = 1, vary = sound_vary) + var/leg_num = source.step_leg + source.step_leg++ + if(source.step_leg > source.usable_legs) + source.step_leg = 1 + var/bodypart_slot = leg_num == 2 ? BODY_ZONE_L_LEG : BODY_ZONE_R_LEG + var/obj/item/bodypart/leg/gotten = source.get_bodypart(bodypart_slot) + if(gotten?.step_sounds) + heard_clients = playsound(source.loc, pick(gotten.step_sounds), 50, TRUE, falloff_distance = 1, vary = sound_vary) else var/static/list/bare_footstep_sounds = GLOB.barefootstep diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 9636528fb015..873a6aac25f0 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -198,8 +198,6 @@ GLOBAL_LIST_EMPTY(features_by_species) var/inert_mutation = /datum/mutation/human/dwarfism ///Used to set the mob's death_sound upon species change var/death_sound - ///Sounds to override barefeet walking - var/list/special_step_sounds ///Special sound for grabbing var/grab_sound /// A path to an outfit that is important for species life e.g. plasmaman outfit @@ -1526,10 +1524,6 @@ GLOBAL_LIST_EMPTY(features_by_species) /datum/species/proc/prepare_human_for_preview(mob/living/carbon/human/human) return -/// Returns the species's scream sound. -/datum/species/proc/get_scream_sound(mob/living/carbon/human/human) - return - /datum/species/proc/get_types_to_preload() var/list/to_store = list() to_store += mutant_organs diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm index 4bf6ff9151ce..b93500f0f52c 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -47,8 +47,6 @@ species_language_holder = /datum/language_holder/synthetic changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT reagent_tag = PROCESS_SYNTHETIC // They don't HAVE a liver, but if they did, they'd have synthetic chem processing. - special_step_sounds = list('sound/effects/servostep.ogg') - bodypart_overrides = list( diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm index 4f6ef5a5ff0c..eeaec4a7f096 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -265,13 +265,6 @@ BODY_ZONE_CHEST = /obj/item/bodypart/chest/ethereal, ) -/datum/species/ethereal/lustrous/get_scream_sound(mob/living/carbon/human/ethereal) - return pick( - 'sound/voice/ethereal/lustrous_scream_1.ogg', - 'sound/voice/ethereal/lustrous_scream_2.ogg', - 'sound/voice/ethereal/lustrous_scream_3.ogg', - ) - /datum/species/ethereal/lustrous/on_species_gain(mob/living/carbon/new_lustrous, datum/species/old_species, pref_load) ..() var/datum/color_palette/generic_colors/palette = new_lustrous.dna.color_palettes[/datum/color_palette/generic_colors] diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index c6ea48eb04a6..de3b084c7bea 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -937,7 +937,6 @@ special_names = list("Bell") fixed_mut_color = "#cd7f32" info_text = "As a Bronze Golem, you are very resistant to loud noises, and make loud noises if something hard hits you, however this ability does hurt your hearing." - special_step_sounds = list('sound/machines/clockcult/integration_cog_install.ogg', 'sound/magic/clockwork/fellowship_armory.ogg' ) mutantears = /obj/item/organ/internal/ears/bronze examine_limb_id = SPECIES_GOLEM var/last_gong_time = 0 diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm index 49014c12720f..61162604715c 100644 --- a/code/modules/mob/living/carbon/human/species_types/humans.dm +++ b/code/modules/mob/living/carbon/human/species_types/humans.dm @@ -17,27 +17,6 @@ /datum/species/human/randomize_features(mob/living/carbon/human/human_mob) human_mob.skin_tone = random_skin_tone() -/datum/species/human/get_scream_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - if(prob(1)) - return 'sound/voice/human/wilhelm_scream.ogg' - return pick( - 'sound/voice/human/malescream_1.ogg', - 'sound/voice/human/malescream_2.ogg', - 'sound/voice/human/malescream_3.ogg', - 'sound/voice/human/malescream_4.ogg', - 'sound/voice/human/malescream_5.ogg', - 'sound/voice/human/malescream_6.ogg', - ) - - return pick( - 'sound/voice/human/femalescream_1.ogg', - 'sound/voice/human/femalescream_2.ogg', - 'sound/voice/human/femalescream_3.ogg', - 'sound/voice/human/femalescream_4.ogg', - 'sound/voice/human/femalescream_5.ogg', - ) - /datum/species/human/get_species_description() return "Humans are the dominant species in the known galaxy. \ Their kind extend from old Earth to the edges of known space." diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 5fcaf6000f77..9140e6d16d87 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -74,13 +74,6 @@ human_mob.dna.features["body_markings"] = pick(GLOB.body_markings_list) randomize_external_organs(human_mob) -/datum/species/lizard/get_scream_sound(mob/living/carbon/human/lizard) - return pick( - 'sound/voice/lizard/lizard_scream_1.ogg', - 'sound/voice/lizard/lizard_scream_2.ogg', - 'sound/voice/lizard/lizard_scream_3.ogg', - ) - /datum/species/lizard/get_species_description() return "The militaristic Lizardpeople hail originally from Tizira, but have grown \ throughout their centuries in the stars to possess a large spacefaring \ diff --git a/code/modules/mob/living/carbon/human/species_types/monkeys.dm b/code/modules/mob/living/carbon/human/species_types/monkeys.dm index 985ad7ce7114..4cf01b8a4d79 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -126,17 +126,6 @@ return TRUE return ..() -/datum/species/monkey/get_scream_sound(mob/living/carbon/human/monkey) - return pick( - 'sound/creatures/monkey/monkey_screech_1.ogg', - 'sound/creatures/monkey/monkey_screech_2.ogg', - 'sound/creatures/monkey/monkey_screech_3.ogg', - 'sound/creatures/monkey/monkey_screech_4.ogg', - 'sound/creatures/monkey/monkey_screech_5.ogg', - 'sound/creatures/monkey/monkey_screech_6.ogg', - 'sound/creatures/monkey/monkey_screech_7.ogg', - ) - /datum/species/monkey/get_species_description() return "Monkeys are a type of primate that exist between humans and animals on the evolutionary chain. \ Every year, on Monkey Day, Nanotrasen shows their respect for the little guys by allowing them to roam the station freely." diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index bf95b89e6968..3ef1b71a6f1d 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -62,9 +62,6 @@ human_mob.dna.features["moth_markings"] = pick(GLOB.moth_markings_list) randomize_external_organs(human_mob) -/datum/species/moth/get_scream_sound(mob/living/carbon/human/human) - return 'sound/voice/moth/scream_moth.ogg' - /datum/species/moth/get_species_description() return "Hailing from a planet that was lost long ago, the moths travel \ the galaxy as a nomadic people aboard a colossal fleet of ships, seeking a new homeland." diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index 554ed48c5a42..f956bedb2f20 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -147,13 +147,6 @@ return randname -/datum/species/plasmaman/get_scream_sound(mob/living/carbon/human) - return pick( - 'sound/voice/plasmaman/plasmeme_scream_1.ogg', - 'sound/voice/plasmaman/plasmeme_scream_2.ogg', - 'sound/voice/plasmaman/plasmeme_scream_3.ogg', - ) - /datum/species/plasmaman/get_species_description() return "Found on the Icemoon of Freyja, plasmamen consist of colonial \ fungal organisms which together form a sentient being. In human space, \ diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index 9eb4b66f0af1..31a43e752c52 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -45,8 +45,8 @@ BODY_ZONE_CHEST = /obj/item/bodypart/chest/zombie, BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/zombie, BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/zombie, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/zombie/infectious, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/zombie/infectious, + BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/zombie, + BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/zombie, ) /datum/species/zombie/check_roundstart_eligible() @@ -106,6 +106,15 @@ TRAIT_STABLEHEART, // Replacement for noblood. Infectious zombies can bleed but don't need their heart. TRAIT_STABLELIVER, // Not necessary but for consistency with above ) + bodypart_overrides = list( + BODY_ZONE_HEAD = /obj/item/bodypart/head/zombie, + BODY_ZONE_CHEST = /obj/item/bodypart/chest/zombie, + BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/zombie, + BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/zombie, + BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/zombie/infectious, + BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/zombie/infectious, + ) + /datum/species/zombie/infectious/on_species_gain(mob/living/carbon/C, datum/species/old_species) . = ..() diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 3faf2c8cb364..8b9a22f40a28 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -288,7 +288,8 @@ if(user.alternative_laughs.len) return pick(user.alternative_laughs) - return user.dna.species.get_laugh_sound(user) + var/obj/item/organ/internal/tongue/tongue = user.get_organ_slot(ORGAN_SLOT_TONGUE) + return tongue?.get_laugh_sound(user) // MonkeStation Edit End /datum/emote/living/look diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 14b2f4b4fd2c..499910828f3d 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -118,6 +118,8 @@ var/num_legs = 2 ///How many usable legs this mob currently has. Should only be changed through set_usable_legs() var/usable_legs = 2 + ///what leg we step with + var/step_leg = 1 ///How many hands does this mob have by default. This shouldn't change at runtime. var/default_num_hands = 2 diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index 2cd2909193a0..bfcbb0b7062a 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -160,6 +160,8 @@ var/old_limb_id /// Used by the bloodysoles component to make footprints var/footprint_sprite = FOOTPRINT_SPRITE_SHOES + ///our step sound + var/list/step_sounds biological_state = BIO_STANDARD_JOINTED /obj/item/bodypart/leg/Destroy() diff --git a/code/modules/surgery/bodyparts/species_parts/android_parts.dm b/code/modules/surgery/bodyparts/species_parts/android_parts.dm index ee2d0021b7d9..6f7700c266f3 100644 --- a/code/modules/surgery/bodyparts/species_parts/android_parts.dm +++ b/code/modules/surgery/bodyparts/species_parts/android_parts.dm @@ -21,6 +21,8 @@ /obj/item/bodypart/leg/left/robot/android change_exempt_flags = null + step_sounds = list('sound/effects/servostep.ogg') /obj/item/bodypart/leg/right/robot/android change_exempt_flags = null + step_sounds = list('sound/effects/servostep.ogg') diff --git a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm index e5625d400779..d8ded87d42a0 100644 --- a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm @@ -54,6 +54,12 @@ composition_effects = list(TRAIT_COLD_BLOODED = 0.5) palette = /datum/color_palette/generic_colors palette_key = MUTANT_COLOR + step_sounds = list( + 'sound/effects/footstep/hardclaw1.ogg', + 'sound/effects/footstep/hardclaw2.ogg', + 'sound/effects/footstep/hardclaw3.ogg', + 'sound/effects/footstep/hardclaw4.ogg', + ) /obj/item/bodypart/leg/right/lizard icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi' @@ -64,6 +70,12 @@ composition_effects = list(TRAIT_COLD_BLOODED = 0.5) palette = /datum/color_palette/generic_colors palette_key = MUTANT_COLOR + step_sounds = list( + 'sound/effects/footstep/hardclaw1.ogg', + 'sound/effects/footstep/hardclaw2.ogg', + 'sound/effects/footstep/hardclaw3.ogg', + 'sound/effects/footstep/hardclaw4.ogg', + ) /obj/item/bodypart/leg/right/lizard/ashwalker bodypart_traits = list(TRAIT_HARD_SOLES) diff --git a/code/modules/surgery/organs/internal/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm index 2296f773b946..ac42f9344913 100644 --- a/code/modules/surgery/organs/internal/tongue/_tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -101,6 +101,33 @@ food_taste_reaction = FOOD_LIKED return food_taste_reaction +/obj/item/organ/internal/tongue/proc/get_laugh_sound() + if(owner.gender == MALE) + return pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg') + else + return 'sound/voice/human/womanlaugh.ogg' + +/obj/item/organ/internal/tongue/proc/get_scream_sound() + if(owner.gender == MALE) + if(prob(1)) + return 'sound/voice/human/wilhelm_scream.ogg' + return pick( + 'sound/voice/human/malescream_1.ogg', + 'sound/voice/human/malescream_2.ogg', + 'sound/voice/human/malescream_3.ogg', + 'sound/voice/human/malescream_4.ogg', + 'sound/voice/human/malescream_5.ogg', + 'sound/voice/human/malescream_6.ogg', + ) + + return pick( + 'sound/voice/human/femalescream_1.ogg', + 'sound/voice/human/femalescream_2.ogg', + 'sound/voice/human/femalescream_3.ogg', + 'sound/voice/human/femalescream_4.ogg', + 'sound/voice/human/femalescream_5.ogg', + ) + /obj/item/organ/internal/tongue/Insert(mob/living/carbon/tongue_owner, special = FALSE, drop_if_replaced = TRUE) . = ..() if(!.) @@ -166,6 +193,27 @@ /// How long is our hissssssss? var/draw_length = 3 +/obj/item/organ/internal/tongue/lizard/get_scream_sound() + if(owner.gender == MALE) + return pick( + 'sound/voice/lizard/lizard_scream_1.ogg', + 'sound/voice/lizard/lizard_scream_2.ogg', + 'sound/voice/lizard/lizard_scream_3.ogg', + 'monkestation/sound/voice/screams/lizard/lizard_scream_4.ogg', + ) + + return pick( + 'sound/voice/lizard/lizard_scream_1.ogg', + 'sound/voice/lizard/lizard_scream_2.ogg', + 'sound/voice/lizard/lizard_scream_3.ogg', + 'monkestation/sound/voice/screams/lizard/lizard_scream_5.ogg', + ) + +/obj/item/organ/internal/tongue/lizard/get_laugh_sound() + if(prob(1)) + return 'monkestation/sound/voice/weh.ogg' + return 'monkestation/sound/voice/laugh/lizard/lizard_laugh.ogg' + /obj/item/organ/internal/tongue/lizard/Initialize(mapload) . = ..() draw_length = rand(2, 6) @@ -280,6 +328,13 @@ modifies_speech = TRUE var/mothership + +/obj/item/organ/internal/tongue/abductor/get_scream_sound() + return 'sound/weather/ashstorm/inside/weak_end.ogg' + +/obj/item/organ/internal/tongue/abductor/get_laugh_sound() + return 'sound/weather/ashstorm/inside/weak_end.ogg' + /obj/item/organ/internal/tongue/abductor/attack_self(mob/living/carbon/human/tongue_holder) if(!istype(tongue_holder)) return @@ -435,6 +490,13 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) . = ..() phomeme_type = pick(phomeme_types) +/obj/item/organ/internal/tongue/bone/get_laugh_sound() + return 'monkestation/sound/voice/laugh/skeleton/skeleton_laugh.ogg' + +/obj/item/organ/internal/tongue/bone/get_scream_sound() + return 'monkestation/sound/voice/screams/skeleton/scream_skeleton.ogg' + + // Bone tongues can speak all default + calcic /obj/item/organ/internal/tongue/bone/get_possible_languages() return ..() + /datum/language/calcic @@ -456,6 +518,13 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) liked_foodtypes = VEGETABLES disliked_foodtypes = FRUIT | CLOTH +/obj/item/organ/internal/tongue/bone/plasmaman/get_scream_sound() + return pick( + 'sound/voice/plasmaman/plasmeme_scream_1.ogg', + 'sound/voice/plasmaman/plasmeme_scream_2.ogg', + 'sound/voice/plasmaman/plasmeme_scream_3.ogg', + ) + /obj/item/organ/internal/tongue/robot name = "robotic voicebox" desc = "A voice synthesizer that can interface with organic lifeforms." @@ -468,6 +537,16 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) modifies_speech = TRUE taste_sensitivity = 25 // not as good as an organic tongue +/obj/item/organ/internal/tongue/robot/get_scream_sound() + return 'monkestation/sound/voice/screams/silicon/scream_silicon.ogg' + +/obj/item/organ/internal/tongue/robot/get_laugh_sound() + return pick( + 'monkestation/sound/voice/laugh/silicon/laugh_siliconE1M0.ogg', + 'monkestation/sound/voice/laugh/silicon/laugh_siliconE1M1.ogg', + 'monkestation/sound/voice/laugh/silicon/laugh_siliconM2.ogg', + ) + /obj/item/organ/internal/tongue/robot/can_speak_language(language) return TRUE // THE MAGIC OF ELECTRONICS @@ -502,6 +581,16 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) attack_verb_continuous = list("shocks", "jolts", "zaps") attack_verb_simple = list("shock", "jolt", "zap") +/obj/item/organ/internal/tongue/ethereal/get_scream_sound() + return pick( + 'sound/voice/ethereal/ethereal_scream_1.ogg', + 'sound/voice/ethereal/ethereal_scream_2.ogg', + 'sound/voice/ethereal/ethereal_scream_3.ogg', + ) + +/obj/item/organ/internal/tongue/ethereal/get_laugh_sound() + return 'monkestation/sound/voice/laugh/ethereal/ethereal_laugh_1.ogg' + // Ethereal tongues can speak all default + voltaic /obj/item/organ/internal/tongue/ethereal/get_possible_languages() @@ -544,6 +633,20 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) liked_foodtypes = MEAT | FRUIT | BUGS disliked_foodtypes = CLOTH +/obj/item/organ/internal/tongue/monkey/get_scream_sound() + return pick( + 'sound/creatures/monkey/monkey_screech_1.ogg', + 'sound/creatures/monkey/monkey_screech_2.ogg', + 'sound/creatures/monkey/monkey_screech_3.ogg', + 'sound/creatures/monkey/monkey_screech_4.ogg', + 'sound/creatures/monkey/monkey_screech_5.ogg', + 'sound/creatures/monkey/monkey_screech_6.ogg', + 'sound/creatures/monkey/monkey_screech_7.ogg', + ) + +/obj/item/organ/internal/tongue/monkey/get_laugh_sound() + return 'monkestation/sound/voice/laugh/simian/monkey_laugh_1.ogg' + /obj/item/organ/internal/tongue/moth name = "moth tongue" desc = "Moths don't have tongues. Someone get god on the phone, tell them I'm not happy." @@ -552,6 +655,16 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) disliked_foodtypes = FRUIT | GROSS | BUGS | GORE toxic_foodtypes = MEAT | RAW | SEAFOOD +/obj/item/organ/internal/tongue/moth/get_scream_sound() + return 'sound/voice/moth/scream_moth.ogg' + +/obj/item/organ/internal/tongue/moth/get_laugh_sound() + return pick( + 'monkestation/sound/voice/laugh/moth/mothchitter.ogg', + 'monkestation/sound/voice/laugh/moth/mothlaugh.ogg', + 'monkestation/sound/voice/laugh/moth/mothsqueak.ogg', + ) + /obj/item/organ/internal/tongue/zombie name = "rotting tongue" desc = "Makes you speak like you're at the dentist and you just absolutely refuse to spit because you forgot to mention you were allergic to space shellfish." @@ -577,3 +690,14 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) say_mod = "whistles" liked_foodtypes = GORE | MEAT | DAIRY | SEAFOOD | BUGS disliked_foodtypes = VEGETABLES + +/obj/item/organ/internal/tongue/floran/get_scream_sound() + return pick( + 'sound/voice/lizard/lizard_scream_1.ogg', + 'sound/voice/lizard/lizard_scream_2.ogg', + 'sound/voice/lizard/lizard_scream_3.ogg', + 'monkestation/sound/voice/screams/lizard/lizard_scream_5.ogg', + ) + +/obj/item/organ/internal/tongue/floran/get_laugh_sound() + return 'monkestation/sound/voice/laugh/lizard/lizard_laugh.ogg' diff --git a/monkestation/code/modules/botany/species/apid/species.dm b/monkestation/code/modules/botany/species/apid/species.dm index df8090e0e0a0..cad389f9a0dc 100644 --- a/monkestation/code/modules/botany/species/apid/species.dm +++ b/monkestation/code/modules/botany/species/apid/species.dm @@ -131,9 +131,6 @@ if(istype(attacking_item, /obj/item/melee/flyswatter)) damage_mods += 10 // Yes, a 10x damage modifier -/datum/species/apid/get_scream_sound(mob/living/carbon/human/human) - return 'sound/voice/moth/scream_moth.ogg' - /datum/species/apid/get_species_description() return "Apids are a race of bipedal bees from the jungle planet of Saltu. Due to their large bodies, they have lost the ability to fly." @@ -146,3 +143,13 @@ liked_foodtypes = VEGETABLES | MEAT | FRUIT disliked_foodtypes = GROSS | BUGS | GORE toxic_foodtypes = RAW | SEAFOOD + +/obj/item/organ/internal/tongue/apid/get_scream_sound() + return 'sound/voice/moth/scream_moth.ogg' + +/obj/item/organ/internal/tongue/apid/get_laugh_sound() + return pick( + 'monkestation/sound/voice/laugh/moth/mothchitter.ogg', + 'monkestation/sound/voice/laugh/moth/mothlaugh.ogg', + 'monkestation/sound/voice/laugh/moth/mothsqueak.ogg', + ) diff --git a/monkestation/code/modules/emotes/code/emote.dm b/monkestation/code/modules/emotes/code/emote.dm index c57f480edb0e..2cbc12d7b813 100644 --- a/monkestation/code/modules/emotes/code/emote.dm +++ b/monkestation/code/modules/emotes/code/emote.dm @@ -165,7 +165,8 @@ var/mob/living/carbon/human/human_user = user if(length(human_user.alternative_screams)) return pick(human_user.alternative_screams) - . = human_user.dna.species.get_scream_sound(user) + var/obj/item/organ/internal/tongue/tongue = human_user.get_organ_slot(ORGAN_SLOT_TONGUE) + . = tongue?.get_scream_sound() /datum/emote/living/scream/should_vary(mob/living/user) if(ishuman(user) && !is_cat_enough(user)) diff --git a/monkestation/code/modules/mob/living/carbon/human/_species.dm b/monkestation/code/modules/mob/living/carbon/human/_species.dm index 82102e3ae40d..7ab2874054b1 100644 --- a/monkestation/code/modules/mob/living/carbon/human/_species.dm +++ b/monkestation/code/modules/mob/living/carbon/human/_species.dm @@ -1,7 +1,3 @@ -/// Returns the species's laugh sound. -/datum/species/proc/get_laugh_sound(mob/living/carbon/human/human) - return - /datum/species/regenerate_organs(mob/living/carbon/organ_holder, datum/species/old_species, replace_current = TRUE, list/excluded_zones, visual_only = FALSE) var/list/skillchips = organ_holder.clone_skillchip_list() organ_holder.destroy_all_skillchips(silent = TRUE) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/abductors.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/abductors.dm index d8a4a2a05ab6..d348dcf6891a 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/abductors.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/abductors.dm @@ -28,9 +28,3 @@ user.update_sight() if(!QDELETED(signer)) QDEL_NULL(signer) - -/datum/species/abductor/get_scream_sound(mob/living/carbon/human/human) - return 'sound/weather/ashstorm/inside/weak_end.ogg' - -/datum/species/abductor/get_laugh_sound(mob/living/carbon/human/human) - return 'sound/weather/ashstorm/inside/weak_end.ogg' diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/android.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/android.dm index 0a6333246aa5..ed75cff1fc73 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/android.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/android.dm @@ -4,13 +4,3 @@ mutantstomach = /obj/item/organ/internal/stomach/cybernetic/tier2 mutantliver = /obj/item/organ/internal/liver/cybernetic/tier2 mutantappendix = null - -/datum/species/android/get_scream_sound(mob/living/carbon/human/human) - return 'monkestation/sound/voice/screams/silicon/scream_silicon.ogg' - -/datum/species/android/get_laugh_sound(mob/living/carbon/human/human) - return pick( - 'monkestation/sound/voice/laugh/silicon/laugh_siliconE1M0.ogg', - 'monkestation/sound/voice/laugh/silicon/laugh_siliconE1M1.ogg', - 'monkestation/sound/voice/laugh/silicon/laugh_siliconM2.ogg', - ) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm index 29e5f5f1aa22..5783ec3e9789 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/arachnid.dm @@ -48,12 +48,6 @@ if(istype(attacking_item, /obj/item/melee/flyswatter)) damage_mods += 30 // Yes, a 30x damage modifier -/datum/species/arachnid/get_scream_sound(mob/living/carbon/human/human) - return 'monkestation/sound/voice/screams/arachnid/arachnid_scream.ogg' - -/datum/species/arachnid/get_laugh_sound(mob/living/carbon/human/human) - return 'monkestation/sound/voice/laugh/arachnid/arachnid_laugh.ogg' - /datum/species/arachnid/get_species_description() return "Arachnids are a species of humanoid spiders employed by Nanotrasen in recent years." // Allan please add details diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/dullahan.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/dullahan.dm deleted file mode 100644 index e0063dc9bb7b..000000000000 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/dullahan.dm +++ /dev/null @@ -1,25 +0,0 @@ -/datum/species/dullahan/get_scream_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - if(prob(1)) - return 'sound/voice/human/wilhelm_scream.ogg' - return pick( - 'sound/voice/human/malescream_1.ogg', - 'sound/voice/human/malescream_2.ogg', - 'sound/voice/human/malescream_3.ogg', - 'sound/voice/human/malescream_4.ogg', - 'sound/voice/human/malescream_5.ogg', - 'sound/voice/human/malescream_6.ogg', - ) - - return pick( - 'sound/voice/human/femalescream_1.ogg', - 'sound/voice/human/femalescream_2.ogg', - 'sound/voice/human/femalescream_3.ogg', - 'sound/voice/human/femalescream_4.ogg', - 'sound/voice/human/femalescream_5.ogg', - ) -/datum/species/dullahan/get_laugh_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - return pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg') - else - return 'sound/voice/human/womanlaugh.ogg' diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm index 2ede8b8cac04..124bf7660a66 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/ethereal.dm @@ -202,16 +202,6 @@ user.visible_message(span_notice("[user] quickly strikes [item] across [lightbulb]'s skin, [lightbulb.p_their()] warmth lighting it!")) return COMPONENT_NO_AFTERATTACK -/datum/species/ethereal/get_scream_sound(mob/living/carbon/human/ethereal) - return pick( - 'sound/voice/ethereal/ethereal_scream_1.ogg', - 'sound/voice/ethereal/ethereal_scream_2.ogg', - 'sound/voice/ethereal/ethereal_scream_3.ogg', - ) - -/datum/species/ethereal/get_laugh_sound(mob/living/carbon/human/ethereal) - return 'monkestation/sound/voice/laugh/ethereal/ethereal_laugh_1.ogg' - /datum/species/ethereal/get_species_description() return "Coming from the planet of Sprout, the theocratic ethereals are \ separated socially by caste, and espouse a dogma of aiding the weak and \ diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm index 9208831c40d9..4b15d3e65394 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/floran.dm @@ -64,17 +64,6 @@ /datum/species/floran/randomize_features(mob/living/carbon/human_mob) randomize_external_organs(human_mob) -/datum/species/floran/get_scream_sound(mob/living/carbon/human/human) - return pick( - 'sound/voice/lizard/lizard_scream_1.ogg', - 'sound/voice/lizard/lizard_scream_2.ogg', - 'sound/voice/lizard/lizard_scream_3.ogg', - 'monkestation/sound/voice/screams/lizard/lizard_scream_5.ogg', - ) - -/datum/species/floran/get_laugh_sound(mob/living/carbon/human/human) - return 'monkestation/sound/voice/laugh/lizard/lizard_laugh.ogg' - /datum/species/floran/get_species_description() return "Plant-based humanoids, they are extremely violent carnivores with no central government or power structure, \ split into numerous tribes spread across the universe, each led by a Greenfinger. \ diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/flypeople.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/flypeople.dm index a4cde86ec6bb..bc3745baedbf 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/flypeople.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/flypeople.dm @@ -1,29 +1,2 @@ /datum/species/fly payday_modifier = 1 - -/datum/species/fly/get_scream_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - if(prob(1)) - return 'sound/voice/human/wilhelm_scream.ogg' - return pick( - 'sound/voice/human/malescream_1.ogg', - 'sound/voice/human/malescream_2.ogg', - 'sound/voice/human/malescream_3.ogg', - 'sound/voice/human/malescream_4.ogg', - 'sound/voice/human/malescream_5.ogg', - 'sound/voice/human/malescream_6.ogg', - ) - - return pick( - 'sound/voice/human/femalescream_1.ogg', - 'sound/voice/human/femalescream_2.ogg', - 'sound/voice/human/femalescream_3.ogg', - 'sound/voice/human/femalescream_4.ogg', - 'sound/voice/human/femalescream_5.ogg', - ) -/datum/species/fly/get_laugh_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - return pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg') - else - return 'sound/voice/human/womanlaugh.ogg' - diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm index 5734136255b8..a3cb05e4acce 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/goblin.dm @@ -34,33 +34,6 @@ /mob/living/carbon/human/species/goblin race = /datum/species/goblin -/datum/species/goblin/get_scream_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - if(prob(1)) - return 'sound/voice/human/wilhelm_scream.ogg' - return pick( - 'sound/voice/human/malescream_1.ogg', - 'sound/voice/human/malescream_2.ogg', - 'sound/voice/human/malescream_3.ogg', - 'sound/voice/human/malescream_4.ogg', - 'sound/voice/human/malescream_5.ogg', - 'sound/voice/human/malescream_6.ogg', - ) - - return pick( - 'sound/voice/human/femalescream_1.ogg', - 'sound/voice/human/femalescream_2.ogg', - 'sound/voice/human/femalescream_3.ogg', - 'sound/voice/human/femalescream_4.ogg', - 'sound/voice/human/femalescream_5.ogg', - ) - -/datum/species/goblin/get_laugh_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - return pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg') - else - return 'sound/voice/human/womanlaugh.ogg' - /datum/language_holder/goblin understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), /datum/language/goblin = list(LANGUAGE_ATOM)) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/golems.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/golems.dm deleted file mode 100644 index 6f1d34a81df3..000000000000 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/golems.dm +++ /dev/null @@ -1,25 +0,0 @@ -/datum/species/golem/get_scream_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - if(prob(1)) - return 'sound/voice/human/wilhelm_scream.ogg' - return pick( - 'sound/voice/human/malescream_1.ogg', - 'sound/voice/human/malescream_2.ogg', - 'sound/voice/human/malescream_3.ogg', - 'sound/voice/human/malescream_4.ogg', - 'sound/voice/human/malescream_5.ogg', - 'sound/voice/human/malescream_6.ogg', - ) - - return pick( - 'sound/voice/human/femalescream_1.ogg', - 'sound/voice/human/femalescream_2.ogg', - 'sound/voice/human/femalescream_3.ogg', - 'sound/voice/human/femalescream_4.ogg', - 'sound/voice/human/femalescream_5.ogg', - ) -/datum/species/golem/get_laugh_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - return pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg') - else - return 'sound/voice/human/womanlaugh.ogg' diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/humans.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/humans.dm deleted file mode 100644 index 2a749444ea44..000000000000 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/humans.dm +++ /dev/null @@ -1,5 +0,0 @@ -/datum/species/human/get_laugh_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - return pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg') - else - return 'sound/voice/human/womanlaugh.ogg' diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/jellypeople.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/jellypeople.dm deleted file mode 100644 index 164989581bc9..000000000000 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/jellypeople.dm +++ /dev/null @@ -1,25 +0,0 @@ -/datum/species/jelly/get_scream_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - if(prob(1)) - return 'sound/voice/human/wilhelm_scream.ogg' - return pick( - 'sound/voice/human/malescream_1.ogg', - 'sound/voice/human/malescream_2.ogg', - 'sound/voice/human/malescream_3.ogg', - 'sound/voice/human/malescream_4.ogg', - 'sound/voice/human/malescream_5.ogg', - 'sound/voice/human/malescream_6.ogg', - ) - - return pick( - 'sound/voice/human/femalescream_1.ogg', - 'sound/voice/human/femalescream_2.ogg', - 'sound/voice/human/femalescream_3.ogg', - 'sound/voice/human/femalescream_4.ogg', - 'sound/voice/human/femalescream_5.ogg', - ) -/datum/species/jelly/get_laugh_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - return pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg') - else - return 'sound/voice/human/womanlaugh.ogg' diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/lizardpeople.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/lizardpeople.dm index 757abda081ce..7e93eac5fe71 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/lizardpeople.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/lizardpeople.dm @@ -1,31 +1,5 @@ /datum/species/lizard payday_modifier = 1 - special_step_sounds = list( - 'sound/effects/footstep/hardclaw1.ogg', - 'sound/effects/footstep/hardclaw2.ogg', - 'sound/effects/footstep/hardclaw3.ogg', - 'sound/effects/footstep/hardclaw4.ogg', - ) -/datum/species/lizard/get_scream_sound(mob/living/carbon/human/human) - if(human.gender ==MALE) - return pick( - 'sound/voice/lizard/lizard_scream_1.ogg', - 'sound/voice/lizard/lizard_scream_2.ogg', - 'sound/voice/lizard/lizard_scream_3.ogg', - 'monkestation/sound/voice/screams/lizard/lizard_scream_4.ogg', - ) - - return pick( - 'sound/voice/lizard/lizard_scream_1.ogg', - 'sound/voice/lizard/lizard_scream_2.ogg', - 'sound/voice/lizard/lizard_scream_3.ogg', - 'monkestation/sound/voice/screams/lizard/lizard_scream_5.ogg', - ) - -/datum/species/lizard/get_laugh_sound(mob/living/carbon/human/human) - if(prob(1)) - return 'monkestation/sound/voice/weh.ogg' - return 'monkestation/sound/voice/laugh/lizard/lizard_laugh.ogg' /datum/species/lizard/get_custom_worn_config_fallback(item_slot, obj/item/item) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/monkeys.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/monkeys.dm deleted file mode 100644 index ec22924e4433..000000000000 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/monkeys.dm +++ /dev/null @@ -1,2 +0,0 @@ -/datum/species/monkey/get_laugh_sound(mob/living/carbon/human/human) - return 'monkestation/sound/voice/laugh/simian/monkey_laugh_1.ogg' diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/mothmen.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/mothmen.dm deleted file mode 100644 index f8fec251c2ac..000000000000 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/mothmen.dm +++ /dev/null @@ -1,6 +0,0 @@ -/datum/species/moth/get_laugh_sound(mob/living/carbon/human/human) - return pick( - 'monkestation/sound/voice/laugh/moth/mothchitter.ogg', - 'monkestation/sound/voice/laugh/moth/mothlaugh.ogg', - 'monkestation/sound/voice/laugh/moth/mothsqueak.ogg', - ) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/plasmamen.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/plasmamen.dm index af3c0ff2a9a7..2d87b7efc9dd 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/plasmamen.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/plasmamen.dm @@ -1,5 +1,2 @@ /datum/species/plasmaman payday_modifier = 1 - -/datum/species/plasmaman/get_laugh_sound(mob/living/carbon/human/human) - return 'monkestation/sound/voice/laugh/skeleton/skeleton_laugh.ogg' diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/podpeople.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/podpeople.dm deleted file mode 100644 index dd09e2fb0841..000000000000 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/podpeople.dm +++ /dev/null @@ -1,25 +0,0 @@ -/datum/species/pod/get_scream_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - if(prob(1)) - return 'sound/voice/human/wilhelm_scream.ogg' - return pick( - 'sound/voice/human/malescream_1.ogg', - 'sound/voice/human/malescream_2.ogg', - 'sound/voice/human/malescream_3.ogg', - 'sound/voice/human/malescream_4.ogg', - 'sound/voice/human/malescream_5.ogg', - 'sound/voice/human/malescream_6.ogg', - ) - - return pick( - 'sound/voice/human/femalescream_1.ogg', - 'sound/voice/human/femalescream_2.ogg', - 'sound/voice/human/femalescream_3.ogg', - 'sound/voice/human/femalescream_4.ogg', - 'sound/voice/human/femalescream_5.ogg', - ) -/datum/species/pod/get_laugh_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - return pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg') - else - return 'sound/voice/human/womanlaugh.ogg' diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/shadowpeople.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/shadowpeople.dm deleted file mode 100644 index ada2b2ec8bfb..000000000000 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/shadowpeople.dm +++ /dev/null @@ -1,25 +0,0 @@ -/datum/species/shadow/get_scream_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - if(prob(1)) - return 'sound/voice/human/wilhelm_scream.ogg' - return pick( - 'sound/voice/human/malescream_1.ogg', - 'sound/voice/human/malescream_2.ogg', - 'sound/voice/human/malescream_3.ogg', - 'sound/voice/human/malescream_4.ogg', - 'sound/voice/human/malescream_5.ogg', - 'sound/voice/human/malescream_6.ogg', - ) - - return pick( - 'sound/voice/human/femalescream_1.ogg', - 'sound/voice/human/femalescream_2.ogg', - 'sound/voice/human/femalescream_3.ogg', - 'sound/voice/human/femalescream_4.ogg', - 'sound/voice/human/femalescream_5.ogg', - ) -/datum/species/shadow/get_laugh_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - return pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg') - else - return 'sound/voice/human/womanlaugh.ogg' diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm index 83ce4cc210ee..32539976f775 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/simian.dm @@ -52,20 +52,6 @@ /obj/item/organ/external/tail/simian = "Chimp" ) -/datum/species/simian/get_scream_sound(mob/living/carbon/human/human) - return pick( - 'sound/creatures/monkey/monkey_screech_1.ogg', - 'sound/creatures/monkey/monkey_screech_2.ogg', - 'sound/creatures/monkey/monkey_screech_3.ogg', - 'sound/creatures/monkey/monkey_screech_4.ogg', - 'sound/creatures/monkey/monkey_screech_5.ogg', - 'sound/creatures/monkey/monkey_screech_6.ogg', - 'sound/creatures/monkey/monkey_screech_7.ogg', - ) - -/datum/species/simian/get_laugh_sound(mob/living/carbon/human/human) - return 'monkestation/sound/voice/laugh/simian/monkey_laugh_1.ogg' - /datum/species/simian/get_species_description() return "Monke." diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/skeletons.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/skeletons.dm index 2989d92ab723..d3331a3a3439 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/skeletons.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/skeletons.dm @@ -1,9 +1,3 @@ -/datum/species/skeleton/get_scream_sound(mob/living/carbon/human/human) - return 'monkestation/sound/voice/screams/skeleton/scream_skeleton.ogg' - -/datum/species/skeleton/get_laugh_sound(mob/living/carbon/human/human) - return 'monkestation/sound/voice/laugh/skeleton/skeleton_laugh.ogg' - /datum/species/skeleton/draconic // Alternate skeleton for drake blood that can process chems! name = "Draconic Skeleton" diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm index 25813b798d75..73f58d3658cc 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm @@ -82,17 +82,6 @@ )) return is_type_in_typecache(reagent, disallowed_chems_typecache) -/datum/species/teratoma/get_scream_sound(mob/living/carbon/human/monkey) - return pick( - 'sound/creatures/monkey/monkey_screech_1.ogg', - 'sound/creatures/monkey/monkey_screech_2.ogg', - 'sound/creatures/monkey/monkey_screech_3.ogg', - 'sound/creatures/monkey/monkey_screech_4.ogg', - 'sound/creatures/monkey/monkey_screech_5.ogg', - 'sound/creatures/monkey/monkey_screech_6.ogg', - 'sound/creatures/monkey/monkey_screech_7.ogg', - ) - /datum/component/omen/teratoma permanent = TRUE luck_mod = 0.75 diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/zombies.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/zombies.dm deleted file mode 100644 index 15a07d281970..000000000000 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/zombies.dm +++ /dev/null @@ -1,25 +0,0 @@ -/datum/species/zombie/get_scream_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - if(prob(1)) - return 'sound/voice/human/wilhelm_scream.ogg' - return pick( - 'sound/voice/human/malescream_1.ogg', - 'sound/voice/human/malescream_2.ogg', - 'sound/voice/human/malescream_3.ogg', - 'sound/voice/human/malescream_4.ogg', - 'sound/voice/human/malescream_5.ogg', - 'sound/voice/human/malescream_6.ogg', - ) - - return pick( - 'sound/voice/human/femalescream_1.ogg', - 'sound/voice/human/femalescream_2.ogg', - 'sound/voice/human/femalescream_3.ogg', - 'sound/voice/human/femalescream_4.ogg', - 'sound/voice/human/femalescream_5.ogg', - ) -/datum/species/zombie/get_laugh_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - return pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg') - else - return 'sound/voice/human/womanlaugh.ogg' diff --git a/monkestation/code/modules/ranching/satyr/bodyparts.dm b/monkestation/code/modules/ranching/satyr/bodyparts.dm index 49a646ae0f30..5c4b9b6254e4 100644 --- a/monkestation/code/modules/ranching/satyr/bodyparts.dm +++ b/monkestation/code/modules/ranching/satyr/bodyparts.dm @@ -23,9 +23,23 @@ limb_id = SPECIES_SATYR bodytype = BODYTYPE_DIGITIGRADE | BODYTYPE_ORGANIC bodypart_traits = list(TRAIT_HARD_SOLES, TRAIT_NON_IMPORTANT_SHOE_BLOCK) + step_sounds = list( + 'sound/effects/footstep/hardclaw1.ogg', + 'sound/effects/footstep/hardclaw2.ogg', + 'sound/effects/footstep/hardclaw3.ogg', + 'sound/effects/footstep/hardclaw4.ogg', + 'sound/effects/footstep/hardclaw1.ogg', + ) /obj/item/bodypart/leg/right/satyr icon_greyscale = 'monkestation/code/modules/ranching/icons/bodyparts.dmi' limb_id = SPECIES_SATYR bodytype = BODYTYPE_DIGITIGRADE | BODYTYPE_ORGANIC bodypart_traits = list(TRAIT_HARD_SOLES, TRAIT_NON_IMPORTANT_SHOE_BLOCK) + step_sounds = list( + 'sound/effects/footstep/hardclaw1.ogg', + 'sound/effects/footstep/hardclaw2.ogg', + 'sound/effects/footstep/hardclaw3.ogg', + 'sound/effects/footstep/hardclaw4.ogg', + 'sound/effects/footstep/hardclaw1.ogg', + ) diff --git a/monkestation/code/modules/ranching/satyr/species.dm b/monkestation/code/modules/ranching/satyr/species.dm index 3b4a020833af..27da3c9bf694 100644 --- a/monkestation/code/modules/ranching/satyr/species.dm +++ b/monkestation/code/modules/ranching/satyr/species.dm @@ -8,13 +8,6 @@ TRAIT_NO_UNDERWEAR, TRAIT_USES_SKINTONES, ) - special_step_sounds = list( - 'sound/effects/footstep/hardclaw1.ogg', - 'sound/effects/footstep/hardclaw2.ogg', - 'sound/effects/footstep/hardclaw3.ogg', - 'sound/effects/footstep/hardclaw4.ogg', - 'sound/effects/footstep/hardclaw1.ogg', - ) inherent_biotypes = MOB_ORGANIC | MOB_HUMANOID external_organs = list( /obj/item/organ/external/satyr_fluff = "normal", diff --git a/monkestation/code/modules/smithing/ipcs/body/base_bodyparts.dm b/monkestation/code/modules/smithing/ipcs/body/base_bodyparts.dm index b3b644516469..0614ee3c2d42 100644 --- a/monkestation/code/modules/smithing/ipcs/body/base_bodyparts.dm +++ b/monkestation/code/modules/smithing/ipcs/body/base_bodyparts.dm @@ -71,6 +71,7 @@ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC dmg_overlay_type = "synth" + step_sounds = list('sound/effects/servostep.ogg') /obj/item/bodypart/leg/right/robot/ipc icon = 'monkestation/icons/mob/species/ipc/bodyparts.dmi' @@ -86,3 +87,4 @@ max_damage = 30 //Monkestation Edit dmg_overlay_type = "synth" + step_sounds = list('sound/effects/servostep.ogg') diff --git a/monkestation/code/modules/smithing/ipcs/body/internal_organs.dm b/monkestation/code/modules/smithing/ipcs/body/internal_organs.dm index dad7cc42e5d3..c0a8b3703a51 100644 --- a/monkestation/code/modules/smithing/ipcs/body/internal_organs.dm +++ b/monkestation/code/modules/smithing/ipcs/body/internal_organs.dm @@ -377,6 +377,16 @@ slot = ORGAN_SLOT_TONGUE organ_flags = ORGAN_ROBOTIC | ORGAN_SYNTHETIC_FROM_SPECIES +/obj/item/organ/internal/tongue/synth/get_scream_sound() + return 'monkestation/sound/voice/screams/silicon/scream_silicon.ogg' + +/obj/item/organ/internal/tongue/synth/get_laugh_sound() + return pick( + 'monkestation/sound/voice/laugh/silicon/laugh_siliconE1M0.ogg', + 'monkestation/sound/voice/laugh/silicon/laugh_siliconE1M1.ogg', + 'monkestation/sound/voice/laugh/silicon/laugh_siliconM2.ogg', + ) + /obj/item/organ/internal/tongue/synth/can_speak_language(language) return TRUE diff --git a/monkestation/code/modules/smithing/ipcs/species.dm b/monkestation/code/modules/smithing/ipcs/species.dm index 018b67f7f7df..b7ff254ed0e4 100644 --- a/monkestation/code/modules/smithing/ipcs/species.dm +++ b/monkestation/code/modules/smithing/ipcs/species.dm @@ -43,7 +43,6 @@ payday_modifier = 1.0 // Matches the rest of the pay penalties the non-human crew have species_language_holder = /datum/language_holder/synthetic - special_step_sounds = list('sound/effects/servostep.ogg') mutantbrain = /obj/item/organ/internal/brain/synth mutantstomach = /obj/item/organ/internal/stomach/synth @@ -81,16 +80,6 @@ COOLDOWN_DECLARE(blend_cd) var/blending -/datum/species/ipc/get_scream_sound(mob/living/carbon/human/human) - return 'monkestation/sound/voice/screams/silicon/scream_silicon.ogg' - -/datum/species/ipc/get_laugh_sound(mob/living/carbon/human/human) - return pick( - 'monkestation/sound/voice/laugh/silicon/laugh_siliconE1M0.ogg', - 'monkestation/sound/voice/laugh/silicon/laugh_siliconE1M1.ogg', - 'monkestation/sound/voice/laugh/silicon/laugh_siliconM2.ogg', - ) - /datum/species/ipc/get_species_description() return "Integrated Positronic Chassis - or IPC for short - \ are a race of sentient and unbound humanoid robots." diff --git a/monkestation/code/modules/smithing/oozelings/species.dm b/monkestation/code/modules/smithing/oozelings/species.dm index af00a31276a0..2e36efa54e51 100644 --- a/monkestation/code/modules/smithing/oozelings/species.dm +++ b/monkestation/code/modules/smithing/oozelings/species.dm @@ -46,32 +46,6 @@ var/datum/action/cooldown/spell/slime_hydrophobia/slime_hydrophobia var/datum/action/innate/core_signal/core_signal -/datum/species/oozeling/get_scream_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - if(prob(1)) - return 'sound/voice/human/wilhelm_scream.ogg' - return pick( - 'sound/voice/human/malescream_1.ogg', - 'sound/voice/human/malescream_2.ogg', - 'sound/voice/human/malescream_3.ogg', - 'sound/voice/human/malescream_4.ogg', - 'sound/voice/human/malescream_5.ogg', - 'sound/voice/human/malescream_6.ogg', - ) - - return pick( - 'sound/voice/human/femalescream_1.ogg', - 'sound/voice/human/femalescream_2.ogg', - 'sound/voice/human/femalescream_3.ogg', - 'sound/voice/human/femalescream_4.ogg', - 'sound/voice/human/femalescream_5.ogg', - ) -/datum/species/oozeling/get_laugh_sound(mob/living/carbon/human/human) - if(human.gender == MALE) - return pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg') - else - return 'sound/voice/human/womanlaugh.ogg' - /datum/species/oozeling/get_species_description() return "A species of sentient semi-solids. \ They require nutriment in order to maintain their body mass." diff --git a/monkestation/code/modules/surgery/organs/internal/tongue.dm b/monkestation/code/modules/surgery/organs/internal/tongue.dm index f649d5767ec4..c2a45d683494 100644 --- a/monkestation/code/modules/surgery/organs/internal/tongue.dm +++ b/monkestation/code/modules/surgery/organs/internal/tongue.dm @@ -19,6 +19,12 @@ disliked_foodtypes = NONE // Okay listen, i don't actually know what irl spiders don't like to eat and i'm pretty tired of looking for answers. liked_foodtypes = GORE | MEAT | BUGS | GROSS +/obj/item/organ/internal/tongue/arachnid/get_scream_sound() + return 'monkestation/sound/voice/screams/arachnid/arachnid_scream.ogg' + +/obj/item/organ/internal/tongue/arachnid/get_laugh_sound() + return 'monkestation/sound/voice/laugh/arachnid/arachnid_laugh.ogg' + /obj/item/organ/internal/tongue/arachnid/modify_speech(datum/source, list/speech_args) //This is flypeople speech var/static/regex/fly_buzz = new("z+", "g") var/static/regex/fly_buZZ = new("Z+", "g") diff --git a/monkestation/code/modules/temperature_overhaul/homeostasis_level.dm b/monkestation/code/modules/temperature_overhaul/homeostasis_level.dm index 5495f18fe9c2..3617fb7bbc28 100644 --- a/monkestation/code/modules/temperature_overhaul/homeostasis_level.dm +++ b/monkestation/code/modules/temperature_overhaul/homeostasis_level.dm @@ -121,10 +121,10 @@ return if(to_value < owner.standard_body_temperature) - owner.adjust_bodytemperature(-delta_change * seconds_between_ticks, min_temp = to_value) + owner.adjust_bodytemperature(-delta_change, min_temp = to_value) else - owner.adjust_bodytemperature(delta_change * seconds_between_ticks, max_temp = to_value) + owner.adjust_bodytemperature(delta_change, max_temp = to_value) /datum/status_effect/homeostasis_level/proc/species_update(datum/source, datum/species/new_species, datum/species/old_species) SIGNAL_HANDLER diff --git a/monkestation/code/modules/the_bird_inside_of_me/species.dm b/monkestation/code/modules/the_bird_inside_of_me/species.dm index 1bee036b0a0f..1debf2a44d2a 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/species.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/species.dm @@ -11,14 +11,6 @@ GLOBAL_LIST_EMPTY(tails_list_avian) plural_form = "Ornithids" id = SPECIES_ORNITHID - special_step_sounds = list( - 'sound/effects/footstep/hardclaw1.ogg', - 'sound/effects/footstep/hardclaw2.ogg', - 'sound/effects/footstep/hardclaw3.ogg', - 'sound/effects/footstep/hardclaw4.ogg', - 'sound/effects/footstep/hardclaw1.ogg', - ) - inherent_traits = list( TRAIT_NO_UNDERWEAR, TRAIT_FEATHERED, @@ -89,6 +81,13 @@ GLOBAL_LIST_EMPTY(tails_list_avian) icon_greyscale = 'monkestation/code/modules/the_bird_inside_of_me/icons/ornithid_parts_greyscale.dmi' bodytype = BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE bodypart_traits = list(TRAIT_HARD_SOLES, TRAIT_NON_IMPORTANT_SHOE_BLOCK) + step_sounds = list( + 'sound/effects/footstep/hardclaw1.ogg', + 'sound/effects/footstep/hardclaw2.ogg', + 'sound/effects/footstep/hardclaw3.ogg', + 'sound/effects/footstep/hardclaw4.ogg', + 'sound/effects/footstep/hardclaw1.ogg', + ) /obj/item/bodypart/leg/right/ornithid limb_id = SPECIES_ORNITHID @@ -96,6 +95,13 @@ GLOBAL_LIST_EMPTY(tails_list_avian) icon_greyscale = 'monkestation/code/modules/the_bird_inside_of_me/icons/ornithid_parts_greyscale.dmi' bodytype = BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE bodypart_traits = list(TRAIT_HARD_SOLES, TRAIT_NON_IMPORTANT_SHOE_BLOCK) + step_sounds = list( + 'sound/effects/footstep/hardclaw1.ogg', + 'sound/effects/footstep/hardclaw2.ogg', + 'sound/effects/footstep/hardclaw3.ogg', + 'sound/effects/footstep/hardclaw4.ogg', + 'sound/effects/footstep/hardclaw1.ogg', + ) // section for lore/perk descs /datum/species/ornithid/get_species_description() diff --git a/tgstation.dme b/tgstation.dme index 781801b79b90..8951d0ea3c93 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -7338,24 +7338,15 @@ #include "monkestation\code\modules\mob\living\carbon\human\species_type\abductors.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\android.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\arachnid.dm" -#include "monkestation\code\modules\mob\living\carbon\human\species_type\dullahan.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\ethereal.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\floran.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\flypeople.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\goblin.dm" -#include "monkestation\code\modules\mob\living\carbon\human\species_type\golems.dm" -#include "monkestation\code\modules\mob\living\carbon\human\species_type\humans.dm" -#include "monkestation\code\modules\mob\living\carbon\human\species_type\jellypeople.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\lizardpeople.dm" -#include "monkestation\code\modules\mob\living\carbon\human\species_type\monkeys.dm" -#include "monkestation\code\modules\mob\living\carbon\human\species_type\mothmen.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\plasmamen.dm" -#include "monkestation\code\modules\mob\living\carbon\human\species_type\podpeople.dm" -#include "monkestation\code\modules\mob\living\carbon\human\species_type\shadowpeople.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\simian.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\skeletons.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\teratoma.dm" -#include "monkestation\code\modules\mob\living\carbon\human\species_type\zombies.dm" #include "monkestation\code\modules\mob\living\silicon\death.dm" #include "monkestation\code\modules\mob\living\simple_animal\megafauna\wendigo.dm" #include "monkestation\code\modules\mob\living\simple_animal\pets\bees.dm" From c086a87befe42b1407440d4fdf875423ced00251 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 28 Sep 2024 00:36:49 -0700 Subject: [PATCH 135/158] removes some un-needed code --- code/__HELPERS/mobs.dm | 1 - code/datums/dna.dm | 8 -------- .../code/modules/the_bird_inside_of_me/species.dm | 10 +++++----- .../code/modules/the_bird_inside_of_me/wings.dm | 1 + 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index cb0b2f3ee0dc..19feb2cb2c0e 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -179,7 +179,6 @@ "arm_wings" = pick(GLOB.arm_wings_list), "ears_avian" = pick(GLOB.avian_ears_list), "tail_avian" = pick(GLOB.tails_list_avian), - "feathers" = "#[pick("7F","FF")][pick("7F","FF")][pick("7F","FF")]", )) /proc/random_hairstyle(gender) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 208909a04ee8..e6c7a51a3e39 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -230,9 +230,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) L[DNA_AVIAN_TAIL_BLOCK] = construct_block(GLOB.tails_list_avian.Find(features["tail_avian"]), GLOB.tails_list_avian.len) if(features["ears_avian"]) // NON-MODULE CHANGE L[DNA_AVIAN_EARS_BLOCK] = construct_block(GLOB.avian_ears_list.Find(features["ears_avian"]), GLOB.avian_ears_list.len) - if(features["feathers"]) // NON-MODULE CHANGE - L[DNA_FEATHER_COLOR_BLOCK] = sanitize_hexcolor(features["feathers"], include_crunch = FALSE) - for(var/blocknum in 1 to DNA_FEATURE_BLOCKS) . += L[blocknum] || random_string(GET_UI_BLOCK_LEN(blocknum), GLOB.hex_characters) @@ -366,9 +363,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) set_uni_feature_block(blocknumber, construct_block(GLOB.tails_list_avian.Find(features["tail_avian"]), GLOB.tails_list_avian.len)) if(DNA_AVIAN_EARS_BLOCK) // NON-MODULE CHANGE set_uni_feature_block(blocknumber, construct_block(GLOB.avian_ears_list.Find(features["ears_avian"]), GLOB.avian_ears_list.len)) - if(DNA_FEATHER_COLOR_BLOCK) // NON-MODULE CHANGE - set_uni_feature_block(blocknumber, sanitize_hexcolor(features["feathers"], include_crunch = FALSE)) - //Please use add_mutation or activate_mutation instead /datum/dna/proc/force_give(datum/mutation/human/human_mutation) if(holder && human_mutation) @@ -650,8 +644,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) dna.features["tail_avian"] = GLOB.tails_list_avian[deconstruct_block(get_uni_feature_block(features, DNA_AVIAN_TAIL_BLOCK), GLOB.tails_list_avian.len)] if(dna.features["ears_avian"]) // NON-MODULE CHANGE dna.features["ears_avian"] = GLOB.avian_ears_list[deconstruct_block(get_uni_feature_block(features, DNA_AVIAN_EARS_BLOCK), GLOB.avian_ears_list.len)] - if(dna.features["feathers"]) // NON-MODULE CHANGE - dna.features["feathers"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_FEATHER_COLOR_BLOCK)) for(var/obj/item/organ/external/external_organ in organs) external_organ.mutate_feature(features, src) diff --git a/monkestation/code/modules/the_bird_inside_of_me/species.dm b/monkestation/code/modules/the_bird_inside_of_me/species.dm index 1debf2a44d2a..fd3c0d7919c4 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/species.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/species.dm @@ -14,8 +14,6 @@ GLOBAL_LIST_EMPTY(tails_list_avian) inherent_traits = list( TRAIT_NO_UNDERWEAR, TRAIT_FEATHERED, - TRAIT_LIGHT_DRINKER, - TRAIT_TACKLING_WINGED_ATTACKER, TRAIT_USES_SKINTONES, ) mutanttongue = /obj/item/organ/internal/tongue/ornithid @@ -39,14 +37,12 @@ GLOBAL_LIST_EMPTY(tails_list_avian) species_cookie = /obj/item/food/semki/healthy // humans get chocolate, lizards get meat. What do birds get? Seed. meat = /obj/item/food/meat/slab/chicken skinned_type = /obj/item/stack/sheet/animalhide/human + mutantliver = /obj/item/organ/internal/liver/ornithid inert_mutation = /datum/mutation/human/dwarfism species_language_holder = /datum/language_holder/yangyu // doing this because yangyu is really just, mostly unused otherwise. color_palette = /datum/color_palette/ornithids -/datum/species/ornithid/randomize_features(mob/living/carbon/human_mob) - human_mob.dna.features["feathers"] = "#[random_color()]" - /datum/species/ornithid/prepare_human_for_preview(mob/living/carbon/human/human) human.skin_tone = "asian1" human.hairstyle = "Half-banged Hair" @@ -163,3 +159,7 @@ GLOBAL_LIST_EMPTY(tails_list_avian) ), ) return to_add + +/obj/item/organ/internal/liver/ornithid + name = "bird liver" + organ_traits = list(TRAIT_LIGHT_DRINKER) diff --git a/monkestation/code/modules/the_bird_inside_of_me/wings.dm b/monkestation/code/modules/the_bird_inside_of_me/wings.dm index 346abdc10116..4bdd33e48b9c 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/wings.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/wings.dm @@ -5,6 +5,7 @@ dna_block = DNA_ARM_WINGS_BLOCK bodypart_overlay = /datum/bodypart_overlay/mutant/wings/functional/arm_wings preference = "feature_arm_wings" + organ_traits = list(TRAIT_TACKLING_WINGED_ATTACKER) //Yes, because this is a direct sub-type of functional wings, this means its stored on body, and yes, this means if one or both of the arms are dismembered, there will be floating feathers/wings. //However, there is no "both arms" storage, and having one for each arm is sort of inefficient. Leaving very few methods that could fix this, most of which are harder than what I can do or necessitate a refactor of code. Too Bad! From 00c312b22f177c4ae6b565a3bec06acb773b90a0 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 28 Sep 2024 17:18:59 -0700 Subject: [PATCH 136/158] fixes --- code/modules/client/preferences.dm | 2 -- code/modules/mob/living/carbon/human/_species.dm | 6 ++++-- .../modules/surgery/organs/internal/liver/liver_skeleton.dm | 1 - code/modules/surgery/organs/lungs.dm | 2 +- monkestation/code/modules/the_fabled_dna_changes/dna.dm | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 861c8bff8cff..fe32f251f9bb 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -132,12 +132,10 @@ GLOBAL_LIST_EMPTY(preferences_datums) parent.set_macros() if(!loaded_preferences_successfully) - stack_trace("[parent]'s preferences failed to load! Attempting a reload of preferences.") if(load_preferences()) if(load_character()) loaded = TRUE return - stack_trace("[parent]'s preferences failed to load a second time! This means their keybindings and other non character settings may be lost.") message_admins("[parent]'s prefs failed to load twice! Their keybindings and tokens may have been lost please check on this.") save_preferences() save_character() //let's save this new random character so it doesn't keep generating new ones. diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 873a6aac25f0..3da99d8426d1 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -602,8 +602,10 @@ GLOBAL_LIST_EMPTY(features_by_species) clear_tail_moodlets(C) - C.physiology?.cold_mod /= coldmod - C.physiology?.heat_mod /= heatmod + if(coldmod) + C.physiology?.cold_mod /= coldmod + if(heatmod) + C.physiology?.heat_mod /= heatmod C.maxHealth = C.maxHealth / maxhealthmod diff --git a/code/modules/surgery/organs/internal/liver/liver_skeleton.dm b/code/modules/surgery/organs/internal/liver/liver_skeleton.dm index 532d1038fcfc..8e2de95ef506 100644 --- a/code/modules/surgery/organs/internal/liver/liver_skeleton.dm +++ b/code/modules/surgery/organs/internal/liver/liver_skeleton.dm @@ -6,7 +6,6 @@ /obj/item/organ/internal/liver/bone name = "mass of bones" desc = "You have no idea what this strange ball of bones does." - icon_state = "liver-bone" organ_traits = list(TRAIT_LIVERLESS_METABOLISM) /obj/item/organ/internal/liver/bone/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index 6ca49a0efdef..e10ff336846d 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -658,7 +658,7 @@ // We're in a low / high pressure environment, can't breathe, but trying to, so this hurts the lungs // Unless it's cybernetic then it just doesn't care. Handwave magic whatever - else if(!skip_breath && !HAS_TRAIT(owner, TRAIT_ASSISTED_BREATHING)) + else if(!skip_breath && (owner && !HAS_TRAIT(owner, TRAIT_ASSISTED_BREATHING))) if(lung_pop_tick > 10) lung_pop_tick = 0 if(!failed) diff --git a/monkestation/code/modules/the_fabled_dna_changes/dna.dm b/monkestation/code/modules/the_fabled_dna_changes/dna.dm index 2d8feda81e63..c16d2d4b8100 100644 --- a/monkestation/code/modules/the_fabled_dna_changes/dna.dm +++ b/monkestation/code/modules/the_fabled_dna_changes/dna.dm @@ -12,7 +12,7 @@ color_palettes = list() color_palettes += created.color_palette var/datum/color_palette/new_palette = new created.color_palette - if(holder.client?.prefs) + if(holder?.client?.prefs) new_palette.apply_prefs(holder.client.prefs) color_palettes[created.color_palette] = new_palette From 92018c34b04d8ad83292a63a8f3d9978365348e6 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 28 Sep 2024 17:40:50 -0700 Subject: [PATCH 137/158] whoops --- code/modules/surgery/organs/lungs.dm | 2 +- .../can_spessmen_feel_pain/pain/status_effects/pain_limp.dm | 2 +- monkestation/code/modules/the_fabled_dna_changes/dna.dm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index e10ff336846d..ebe938e69eaf 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -675,7 +675,7 @@ breather.failed_last_breath = TRUE lung_pop_tick++ // Robot, don't care lol - else if(!HAS_TRAIT(owner, TRAIT_ASSISTED_BREATHING)) + else if((owner && !HAS_TRAIT(owner, TRAIT_ASSISTED_BREATHING))) // Can't breathe! breather.failed_last_breath = TRUE diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/pain_limp.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/pain_limp.dm index 0005d91fcc3c..00fce8026bf5 100644 --- a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/pain_limp.dm +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/pain_limp.dm @@ -40,7 +40,7 @@ ) /datum/status_effect/limp/pain/update_limp() - if(QDELING(owner)) + if(QDELETED(owner)) return var/mob/living/carbon/human/limping_human = owner diff --git a/monkestation/code/modules/the_fabled_dna_changes/dna.dm b/monkestation/code/modules/the_fabled_dna_changes/dna.dm index c16d2d4b8100..6dd56105bd8b 100644 --- a/monkestation/code/modules/the_fabled_dna_changes/dna.dm +++ b/monkestation/code/modules/the_fabled_dna_changes/dna.dm @@ -20,7 +20,7 @@ for(var/datum/color_palette/palette as anything in generic_colors) color_palettes += palette var/datum/color_palette/new_palette = new palette - if(holder.client?.prefs) + if(holder?.client?.prefs) new_palette.apply_prefs(holder.client.prefs) color_palettes[palette] = new_palette From 146cdf532ebafba4e26aa1030f9af88690e5a48b Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 28 Sep 2024 18:04:24 -0700 Subject: [PATCH 138/158] Update golems.dm --- code/modules/mob/living/carbon/human/species_types/golems.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index de3b084c7bea..bbc71792002e 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -3,6 +3,7 @@ name = "Golem" id = SPECIES_GOLEM inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_NO_UNDERWEAR, TRAIT_NO_DNA_COPY, TRAIT_NO_TRANSFORMATION_STING, From 33547a6817f66728c0aebef2da773f6c721d96d8 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 28 Sep 2024 18:07:02 -0700 Subject: [PATCH 139/158] Update sleeping_carp.dm --- code/datums/martial/sleeping_carp.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index df8369a707e1..d2a065501b72 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -191,7 +191,7 @@ ) COOLDOWN_START(src, block_cooldown, 3 SECONDS) playsound(carp_user, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), vol = 75, vary = TRUE) - carp_user.stamina?.adjust(-50) + carp_user.stamina?.adjust(-15) hitting_projectile.firer = carp_user hitting_projectile.set_angle(rand(0, 360))//SHING return COMPONENT_BULLET_PIERCED From 4c5c945185e73850ee8f7e9c5daf19cfbbf0dff7 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 28 Sep 2024 18:07:48 -0700 Subject: [PATCH 140/158] Update sleeping_carp.dm --- code/datums/martial/sleeping_carp.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index d2a065501b72..ccaf1ae6caf8 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -162,7 +162,7 @@ /datum/martial_art/the_sleeping_carp/proc/can_deflect(mob/living/carp_user) if(!COOLDOWN_FINISHED(src, block_cooldown)) - if(prob(70)) + if(prob(50)) return FALSE if(!can_use(carp_user)) return FALSE From 58ea73227f110d2f5418bdca0204946d48dc1e7f Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 30 Sep 2024 00:20:07 -0700 Subject: [PATCH 141/158] Update medicine_reagents.dm --- code/modules/reagents/chemistry/reagents/medicine_reagents.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 23ecc893fdbd..aed33a599e2f 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -24,7 +24,7 @@ /datum/reagent/medicine/leporazine/on_mob_metabolize(mob/living/carbon/user) . = ..() - user.add_homeostasis_level(type, user.standard_body_temperature, 4 KELVIN) + user.add_homeostasis_level(type, user.standard_body_temperature, 10 KELVIN) /datum/reagent/medicine/leporazine/on_mob_end_metabolize(mob/living/carbon/user) . = ..() From 412f1cc4a8fff0efd0b7cdb7073094deeb1e8179 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 1 Oct 2024 01:12:11 -0700 Subject: [PATCH 142/158] guh --- code/datums/wounds/blunt.dm | 7 + code/datums/wounds/burns.dm | 9 + code/datums/wounds/pierce.dm | 11 +- code/datums/wounds/slash.dm | 6 + code/game/objects/items/stacks/medical.dm | 115 ++++++++--- code/modules/mob/living/carbon/carbon.dm | 8 + .../mob/living/carbon/carbon_update_icons.dm | 14 +- code/modules/mob/living/carbon/examine.dm | 41 ++-- .../mob/living/carbon/human/examine.dm | 7 + code/modules/surgery/bodyparts/_bodyparts.dm | 43 +---- icons/effects/digi_filters.dmi | Bin 0 -> 1221 bytes .../modules/can_spessmen_feel_pain/bandage.dm | 178 ++++++++++++++++++ monkestation/icons/mob/bandage.dmi | Bin 0 -> 1612 bytes monkestation/sound/items/rip1.ogg | Bin 0 -> 8932 bytes monkestation/sound/items/rip2.ogg | Bin 0 -> 12711 bytes monkestation/sound/items/rip3.ogg | Bin 0 -> 15620 bytes monkestation/sound/items/rip4.ogg | Bin 0 -> 14002 bytes monkestation/sound/items/snip.ogg | Bin 0 -> 6655 bytes tgstation.dme | 1 + 19 files changed, 348 insertions(+), 92 deletions(-) create mode 100644 icons/effects/digi_filters.dmi create mode 100644 monkestation/code/modules/can_spessmen_feel_pain/bandage.dm create mode 100644 monkestation/icons/mob/bandage.dmi create mode 100644 monkestation/sound/items/rip1.ogg create mode 100644 monkestation/sound/items/rip2.ogg create mode 100644 monkestation/sound/items/rip3.ogg create mode 100644 monkestation/sound/items/rip4.ogg create mode 100644 monkestation/sound/items/snip.ogg diff --git a/code/datums/wounds/blunt.dm b/code/datums/wounds/blunt.dm index 45fd29330733..e3a9538a8c57 100644 --- a/code/datums/wounds/blunt.dm +++ b/code/datums/wounds/blunt.dm @@ -2,3 +2,10 @@ name = "Blunt Wound" undiagnosed_name = "Painful Bruising" sound_effect = 'sound/effects/wounds/crack1.ogg' + +/datum/wound/blunt/wound_injury(datum/wound/old_wound, attack_direction) + if(!old_wound && limb.current_gauze && (wound_flags & ACCEPTS_GAUZE)) + // oops your bone injury knocked off your gauze, gotta re-apply it + limb.remove_gauze(limb.drop_location()) + + return ..() diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm index abd6bd763078..f5cc3c9a3231 100644 --- a/code/datums/wounds/burns.dm +++ b/code/datums/wounds/burns.dm @@ -10,6 +10,15 @@ a_or_from = "from" sound_effect = 'sound/effects/wounds/sizzle1.ogg' +/datum/wound/burn/wound_injury(datum/wound/old_wound, attack_direction) + if(!old_wound && limb.current_gauze && (wound_flags & ACCEPTS_GAUZE)) + qdel(limb.remove_gauze()) + // oops your existing gauze got burned, need a new one now + var/obj/effect/decal/cleanable/ash/ash = new(limb.drop_location()) + ash.desc += " It looks like it used to be some kind of bandage." + + return ..() + /datum/wound/burn/flesh name = "Burn (Flesh) Wound" a_or_from = "from" diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index 33b734a46e48..0ef431efafd6 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -5,6 +5,12 @@ /datum/wound/pierce undiagnosed_name = "Bleeding Wound" +/datum/wound/pierce/wound_injury(datum/wound/old_wound, attack_direction) + if(!old_wound && limb.current_gauze && (wound_flags & ACCEPTS_GAUZE)) + // oops your existing gauze got penetrated through! need a new one now + limb.seep_gauze(initial(limb.current_gauze.absorption_capacity) * 0.8) + return ..() + /datum/wound/pierce/bleed name = "Piercing Wound" sound_effect = 'sound/weapons/slice.ogg' @@ -101,8 +107,9 @@ adjust_blood_flow(0.25 * seconds_per_tick) // old heparin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first if(limb.current_gauze) - adjust_blood_flow(-limb.current_gauze.absorption_rate * gauzed_clot_rate * seconds_per_tick) - limb.current_gauze.absorption_capacity -= limb.current_gauze.absorption_rate * seconds_per_tick + var/amt_blocking = limb.current_gauze.absorption_rate * seconds_per_tick + adjust_blood_flow(-1 * amt_blocking * gauzed_clot_rate) + limb.seep_gauze(amt_blocking) if(blood_flow <= 0) qdel(src) diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm index 5c36bfdfcd37..ea2145c2db21 100644 --- a/code/datums/wounds/slash.dm +++ b/code/datums/wounds/slash.dm @@ -8,6 +8,12 @@ undiagnosed_name = "Cut" sound_effect = 'sound/weapons/slice.ogg' +/datum/wound/slash/wound_injury(datum/wound/old_wound, attack_direction) + if(!old_wound && limb.current_gauze && (wound_flags & ACCEPTS_GAUZE)) + // oops your existing gauze got cut through! need a new one now + limb.seep_gauze(initial(limb.current_gauze.absorption_capacity) * 0.8) + return ..() + /datum/wound_pregen_data/flesh_slash abstract = TRUE diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 41e2b77399fb..376dc4a72400 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -15,6 +15,8 @@ cost = 250 source = /datum/robot_energy_storage/medical merge_type = /obj/item/stack/medical + /// Sound played when heal doafter begins + var/heal_sound /// How long it takes to apply it to yourself var/self_delay = 5 SECONDS /// How long it takes to apply it to someone else @@ -62,6 +64,8 @@ /obj/item/stack/medical/proc/try_heal(mob/living/patient, mob/user, silent = FALSE) if(!patient.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE)) return + if(heal_sound) + playsound(patient, heal_sound, 33, FALSE) if(patient == user) if(!silent) user.visible_message(span_notice("[user] starts to apply [src] on [user.p_them()]self..."), span_notice("You begin applying [src] on yourself...")) @@ -162,6 +166,48 @@ splint_factor = 0.7 burn_cleanliness_bonus = 0.35 merge_type = /obj/item/stack/medical/gauze + /// tracks how many times we've been scrubbed thoroughly + var/times_cleaned = 0 + +/obj/item/stack/medical/gauze/update_name(updates) + . = ..() + var/base_cap = initial(absorption_capacity) + if(!base_cap) + return + + if(absorption_capacity <= 0) + name = "used [initial(name)]" + else if(absorption_capacity <= base_cap * 0.2) + name = "dirty [initial(name)]" + else if(absorption_capacity <= base_cap * 0.8) + name = "worn [initial(name)]" + else + name = initial(name) + +/obj/item/stack/medical/gauze/can_merge(obj/item/stack/medical/gauze/check, inhand) + . = ..() + if(!.) + return . + // need to be in +- 0.5 dirtiness of each other + // otherwise you can merge a completely used bandage with a brand new one, which would magically unuse it + if(check.absorption_capacity < absorption_capacity - 0.25 || check.absorption_capacity > absorption_capacity + 0.25) + return FALSE + return . + +/obj/item/stack/medical/gauze/wash(clean_types) + . = ..() + if(.) + return . + if(!(clean_types & CLEAN_TYPE_HARD_DECAL)) // gotta scrub realllly hard to clean gauze + return . + times_cleaned += 1 + var/clean_to = initial(absorption_capacity) * (3 / (times_cleaned + 3)) + if(absorption_capacity < clean_to) + absorption_capacity = clean_to + update_appearance(UPDATE_NAME) + . = TRUE + + return . // gauze is only relevant for wounds, which are handled in the wounds themselves /obj/item/stack/medical/gauze/try_heal(mob/living/patient, mob/user, silent) @@ -170,40 +216,62 @@ var/obj/item/bodypart/limb = patient.get_bodypart(check_zone(user.zone_selected)) if(!limb) - patient.balloon_alert(user, "missing limb!") - return - if(!LAZYLEN(limb.wounds)) - patient.balloon_alert(user, "no wounds!") // good problem to have imo - return - - var/gauzeable_wound = FALSE - var/datum/wound/woundies - for(var/i in limb.wounds) - woundies = i - if(woundies.wound_flags & ACCEPTS_GAUZE) - gauzeable_wound = TRUE - break - if(!gauzeable_wound) - patient.balloon_alert(user, "can't heal those!") + patient.balloon_alert(user, "no limb!") return if(limb.current_gauze && (limb.current_gauze.absorption_capacity * 1.2 > absorption_capacity)) // ignore if our new wrap is < 20% better than the current one, so someone doesn't bandage it 5 times in a row patient.balloon_alert(user, pick("already bandaged!", "bandage is clean!")) // good enough return - if(HAS_TRAIT(woundies, TRAIT_WOUND_SCANNED)) + var/boosted = FALSE + if(LAZYLEN(limb.wounds)) + for(var/datum/wound/wound as anything in limb.wounds) + if(HAS_TRAIT(wound, TRAIT_WOUND_SCANNED)) + boosted = TRUE + break + else + // gives you extra time so you realize you're not treating a wound + treatment_delay *= 2 + + var/whose = user == patient ? "your" : "[patient]'s" + var/theirs = user == patient ? patient.p_their() : "[patient]'s" + var/wrap_or_replace = limb.current_gauze ? "replacing [limb.current_gauze] on" : "wrapping" + var/with_what = limb.current_gauze?.type == type ? "more of [src]" : src + if(boosted) treatment_delay *= 0.5 - if(user == patient) - to_chat(user, span_notice("You keep in mind the indications from the holo-image about your injury, and expertly begin wrapping your wounds with [src].")) - else - user.visible_message(span_warning("[user] begins expertly wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."), span_warning("You begin quickly wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src], keeping the holo-image indications in mind...")) + user.visible_message( + span_notice("[user] begins expertly [wrap_or_replace] [theirs] [limb.plaintext_zone] with [with_what]."), + span_notice("You begin quickly [wrap_or_replace] [whose] [limb.plaintext_zone] with [with_what], keeping the holo-image indications in mind..."), + ) else - user.visible_message(span_warning("[user] begins wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."), span_warning("You begin wrapping the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone] with [src]...")) + user.visible_message( + span_notice("[user] begins [wrap_or_replace] [theirs] [limb.plaintext_zone] with [with_what]."), + span_notice("You begin [wrap_or_replace] [whose] [limb.plaintext_zone] with [with_what]..."), + ) + user.balloon_alert(user, "applying gauze...") + if(user != patient) + user.balloon_alert(patient, "applying gauze...") + + playsound(patient, pick( + 'monkestation/sound/items/rip1.ogg', + 'monkestation/sound/items/rip2.ogg', + 'monkestation/sound/items/rip3.ogg', + 'monkestation/sound/items/rip4.ogg', + ), 33) if(!do_after(user, treatment_delay, target = patient)) + user.balloon_alert(user, "interrupted!") return - - user.visible_message("[user] applies [src] to [patient]'s [limb.plaintext_zone].", "You bandage the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone].") + if(limb.current_gauze && (limb.current_gauze.absorption_capacity * 1.2 > absorption_capacity)) // double check for sanity + return + user.balloon_alert(user, "gauze applied") + if(user != patient) + user.balloon_alert(patient, "gauze applied") + + user.visible_message( + span_infoplain(span_green("[user] applies [src] to [theirs] [limb.plaintext_zone].")), + span_infoplain(span_green("You [limb.current_gauze?.type == type ? "replace" : "bandage"] the wounds on [whose] [limb.plaintext_zone].")), + ) limb.apply_gauze(src) /obj/item/stack/medical/gauze/twelve @@ -266,6 +334,7 @@ stop_bleeding = 0.6 grind_results = list(/datum/reagent/medicine/antipathogenic/spaceacillin = 2) merge_type = /obj/item/stack/medical/suture + heal_sound = 'monkestation/sound/items/snip.ogg' /obj/item/stack/medical/suture/emergency name = "emergency suture" diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index f70e7b2cfb93..3533e1c3b338 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -187,6 +187,14 @@ SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L) return + if(href_list["gauze_limb"]) + var/obj/item/bodypart/gauzed = locate(href_list["gauze_limb"]) in bodyparts + if(isnull(gauzed?.current_gauze)) + return + // rest of the sanity is handled in the proc itself + gauzed.help_remove_gauze(usr) + return + if(href_list["show_paper_note"]) var/obj/item/paper/paper_note = locate(href_list["show_paper_note"]) if(!paper_note) diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index 3ba6279e862c..38422a58979b 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -294,16 +294,12 @@ var/mutable_appearance/damage_overlay for(var/obj/item/bodypart/iter_part as anything in bodyparts) - if(!iter_part.dmg_overlay_type) + var/list/part_overlays = iter_part.get_bodypart_damage_state() + if(!LAZYLEN(part_overlays)) continue - if(isnull(damage_overlay) && (iter_part.brutestate || iter_part.burnstate)) - damage_overlay = mutable_appearance('icons/mob/effects/dam_mob.dmi', "blank", -DAMAGE_LAYER, appearance_flags = KEEP_TOGETHER) - if(iter_part.brutestate) - var/image/brute_overlay = image('icons/mob/effects/dam_mob.dmi', "[iter_part.dmg_overlay_type]_[iter_part.body_zone]_[iter_part.brutestate]0") - brute_overlay.color = iter_part.damage_color - damage_overlay.add_overlay(brute_overlay) //we're adding icon_states of the base image as overlays //we're adding icon_states of the base image as overlays - if(iter_part.burnstate) - damage_overlay.add_overlay("[iter_part.dmg_overlay_type]_[iter_part.body_zone]_0[iter_part.burnstate]") + + damage_overlay ||= mutable_appearance(layer = -DAMAGE_LAYER) + damage_overlay.overlays += part_overlays if(isnull(damage_overlay)) return diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index 5e1ebeaf8d03..586058cc7891 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -36,25 +36,30 @@ var/list/msg = list("") var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) var/list/disabled = list() - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - if(BP.bodypart_disabled) - disabled += BP - missing -= BP.body_zone - for(var/obj/item/I in BP.embedded_objects) - if(I.isEmbedHarmless()) - msg += "[t_He] [t_has] [icon2html(I, user)] \a [I] stuck to [t_his] [BP.name]!\n" - else - msg += "[t_He] [t_has] [icon2html(I, user)] \a [I] embedded in [t_his] [BP.name]!\n" - for(var/i in BP.wounds) - var/datum/wound/W = i - msg += "[W.get_examine_description(user)]\n" - - for(var/X in disabled) - var/obj/item/bodypart/BP = X + var/adjacent = user.Adjacent(src) + for(var/obj/item/bodypart/body_part as anything in bodyparts) + if(body_part.bodypart_disabled) + disabled += body_part + missing -= body_part.body_zone + for(var/obj/item/leftover in body_part.embedded_objects) + var/stuck_or_embedded = "embedded in" + if(leftover.isEmbedHarmless()) + stuck_or_embedded = "stuck to" + msg += "[t_He] [t_has] [icon2html(leftover, user)] \a [leftover] [stuck_or_embedded] [t_his] [body_part.plaintext_zone]!\n" + + if(body_part.current_gauze) + var/gauze_href = body_part.current_gauze.name + if(adjacent && isliving(user)) // only shows the href if we're adjacent + gauze_href = "
[gauze_href]" + msg += span_notice("There is some [icon2html(body_part.current_gauze, user)] [gauze_href] wrapped around [t_his] [body_part.plaintext_zone].\n") + + for(var/datum/wound/iter_wound as anything in body_part.wounds) + msg += "[iter_wound.get_examine_description(user)]\n" + + for(var/obj/item/bodypart/body_part as anything in disabled) var/damage_text - damage_text = (BP.brute_dam >= BP.burn_dam) ? BP.heavy_brute_msg : BP.heavy_burn_msg - msg += "[capitalize(t_his)] [BP.name] is [damage_text]!\n" + damage_text = (body_part.brute_dam >= body_part.burn_dam) ? body_part.heavy_brute_msg : body_part.heavy_burn_msg + msg += "[capitalize(t_his)] [body_part.name] is [damage_text]!\n" for(var/t in missing) if(t == BODY_ZONE_HEAD) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index cc17b653c182..7ddd90c668ad 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -136,6 +136,7 @@ var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) var/list/disabled = list() + var/adjacent = user.Adjacent(src) for(var/X in bodyparts) var/obj/item/bodypart/body_part = X if(body_part.bodypart_disabled) @@ -147,6 +148,12 @@ else msg += "[t_He] [t_has] [icon2html(I, user)] \a [I] embedded in [t_his] [body_part.name]!\n" + if(body_part.current_gauze) + var/gauze_href = body_part.current_gauze.name + if(adjacent && isliving(user)) // only shows the href if we're adjacent + gauze_href = "[gauze_href]" + msg += span_notice("There is some [icon2html(body_part.current_gauze, user)] [gauze_href] wrapped around [t_his] [body_part.plaintext_zone].\n") + for(var/i in body_part.wounds) var/datum/wound/iter_wound = i msg += "[iter_wound.get_examine_description(user)]\n" diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index b40f7348c041..a57a49711077 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -349,6 +349,9 @@ var/stuck_word = embedded_thing.isEmbedHarmless() ? "stuck" : "embedded" check_list += "\t There is \a [embedded_thing] [stuck_word] in your [name]!" + if(current_gauze) + check_list += span_notice("\t There is some [current_gauze.name] wrapped around your [name].") + /obj/item/bodypart/blob_act() receive_damage(max_damage, wound_bonus = CANT_WOUND) @@ -1222,46 +1225,6 @@ return ((biological_state & BIO_BLOODED) && (!owner || !HAS_TRAIT(owner, TRAIT_NOBLOOD))) -/** - * apply_gauze() is used to- well, apply gauze to a bodypart - * - * As of the Wounds 2 PR, all bleeding is now bodypart based rather than the old bleedstacks system, and 90% of standard bleeding comes from flesh wounds (the exception is embedded weapons). - * The same way bleeding is totaled up by bodyparts, gauze now applies to all wounds on the same part. Thus, having a slash wound, a pierce wound, and a broken bone wound would have the gauze - * applying blood staunching to the first two wounds, while also acting as a sling for the third one. Once enough blood has been absorbed or all wounds with the ACCEPTS_GAUZE flag have been cleared, - * the gauze falls off. - * - * Arguments: - * * gauze- Just the gauze stack we're taking a sheet from to apply here - */ -/obj/item/bodypart/proc/apply_gauze(obj/item/stack/gauze) - if(!istype(gauze) || !gauze.absorption_capacity) - return - var/newly_gauzed = FALSE - if(!current_gauze) - newly_gauzed = TRUE - QDEL_NULL(current_gauze) - current_gauze = new gauze.type(src, 1) - gauze.use(1) - if(newly_gauzed) - SEND_SIGNAL(src, COMSIG_BODYPART_GAUZED, gauze) - -/** - * seep_gauze() is for when a gauze wrapping absorbs blood or pus from wounds, lowering its absorption capacity. - * - * The passed amount of seepage is deducted from the bandage's absorption capacity, and if we reach a negative absorption capacity, the bandages falls off and we're left with nothing. - * - * Arguments: - * * seep_amt - How much absorption capacity we're removing from our current bandages (think, how much blood or pus are we soaking up this tick?) - */ -/obj/item/bodypart/proc/seep_gauze(seep_amt = 0) - if(!current_gauze) - return - current_gauze.absorption_capacity -= seep_amt - if(current_gauze.absorption_capacity <= 0) - owner.visible_message(span_danger("\The [current_gauze.name] on [owner]'s [name] falls away in rags."), span_warning("\The [current_gauze.name] on your [name] falls away in rags."), vision_distance=COMBAT_MESSAGE_RANGE) - QDEL_NULL(current_gauze) - SEND_SIGNAL(src, COMSIG_BODYPART_GAUZE_DESTROYED) - ///Loops through all of the bodypart's external organs and update's their color. /obj/item/bodypart/proc/recolor_external_organs() for(var/datum/bodypart_overlay/mutant/overlay in bodypart_overlays) diff --git a/icons/effects/digi_filters.dmi b/icons/effects/digi_filters.dmi new file mode 100644 index 0000000000000000000000000000000000000000..c17ff0e13a0b92eba633f896c374d0f4d7ed63c6 GIT binary patch literal 1221 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGo)m0%8B`&GO$wiq3C7Jno3=9=> zN>6R%YBmsHdtmup#C}(IZfw4$;K>E+1DHG~ONX3b{ryXJj*N``kElJzPwH;iyjWRm zYAti}iz*{~PSfU(Rg+Ez2CY-y@=NMqMw3eB2^LMRV-C-v|451U95<~s`K=JW>$L8% zqleD*{S(YrSG%=7PK<$ph1Ju=F{EP7+qsTKiyTDS{$HD;5cZTy&$iK2#QX!pH0kX( zQ=aPC?p|ZjD6P$&Fg>+viui%lbq-VG60Xc+UEpwGq2Q<2PimzXD%yOqd(rk|*P73q(*Sr^~Q z3w~ZSk)i$0b)!eCeOxB5DGyRk-G1DDh3*5(pI1ux3lw{P#LBGyV{)F$A$|IqH;g5Z z{;mp&cKD^T=(XGfrx_nNpA0{6uxHi8v!|Lrv+Ni9x-f=ihO=^C$Kjm~vYG z6FVS(Rm|)MOcW>JTkY6 zavO#*`2-!g4d`{Zm)2bNrmx+II=z^6^tOy7q1P`up$Xx4xU> z)~~&_I_a-S%B7nMcWahzi23t%!>lFS-6y>`d?=jf(ZQWBZ`L1v7|`#g9GlVnymIH? zn)~P97Qc;n?)mV>_t{Rn4@H`r_rCvKwKL{b((lWcgY#-FWa@4{m$}At>eb_5tBmhw z*Ij=dnw8z%-rnw&YvxgEBKb3zMe^(A|Md-zEw211VkbW7!2%7EOjm|F?ugMV-Kdah zHapQqj+w!1wr{58chxh`i)-ua`57u|Ymc5j?VVRG;(9GK^SXm_xr2yn`;&V1#~*iW z(fTE}Q7j-#zEU^l^Uk@8uE}nQ(BV5BD5A)7_;8i-8;cIh!Zc>9+3_19fjKYe&vvdVq&#CKn-BzV|34hy`0|DIvrc8~3zS^bPh zH@!KSQ1J0&$Wn>b6?)rSwl*A1YCM_3bpG?YB%_x1zi)lE@ll&R`%Rl(9amLN%@u|X zQEP#QcWsWCm0}{5dA)RF)Y_tr`I0O9roDPG|7^U 0) + return + owner.visible_message( + span_danger("[current_gauze] on [owner]'s [name] falls away in rags."), + span_warning("[current_gauze] on your [name] falls away in rags."), + vision_distance = COMBAT_MESSAGE_RANGE, + ) + remove_gauze(drop_location()) + owner.update_damage_overlays() + +/** + * Helper for someone helping to remove our gauze + */ +/obj/item/bodypart/proc/help_remove_gauze(mob/living/helper) + if(!istype(helper)) + return + if(helper.incapacitated()) + return + if(!helper.can_perform_action(owner, NEED_HANDS|FORBID_TELEKINESIS_REACH)) // telekinetic removal can be added later + return + + var/whose = helper == owner ? "your" : "[owner]'s" + helper.visible_message( + span_notice("[helper] starts carefully removing [current_gauze] from [whose] [plaintext_zone]."), + span_notice("You start carefully removing [current_gauze] from [whose] [plaintext_zone]..."), + vision_distance = COMBAT_MESSAGE_RANGE, + ) + helper.balloon_alert(helper, "removing gauze...") + if(helper != owner) + helper.balloon_alert(owner, "removing your gauze...") + + if(!do_after(helper, 3 SECONDS, owner)) + return + + if(!current_gauze) + return + + var/theirs = helper == owner ? helper.p_their() : "[owner]'s" + helper.visible_message( + span_notice("[helper] finishes removing [current_gauze] from [theirs] [plaintext_zone]."), + span_notice("You finish removing [current_gauze] from [theirs] [plaintext_zone]."), + vision_distance = COMBAT_MESSAGE_RANGE, + ) + + helper.balloon_alert(helper, "gauzed removed") + if(helper != owner) + helper.balloon_alert(owner, "gauze removed") + + helper.put_in_hands(remove_gauze()) + +/obj/item/proc/apply_digitigrade_filters(mutable_appearance/appearance, mob/living/carbon/wearer = loc, bodytype) + if(!istype(wearer) || !(bodytype & BODYTYPE_DIGITIGRADE)) + return + + var/static/list/icon/masks_and_shading + if(isnull(masks_and_shading)) + masks_and_shading = list( + "[NORTH]" = list( + "mask" = icon('icons/effects/digi_filters.dmi', "digi", NORTH), + "shading" = icon('icons/effects/digi_filters.dmi', "digi_shading", NORTH), + "size" = 1, + ), + "[SOUTH]" = list( + "mask" = icon('icons/effects/digi_filters.dmi', "digi", SOUTH), + "shading" = icon('icons/effects/digi_filters.dmi', "digi_shading", SOUTH), + "size" = 1, + ), + "[EAST]" = list( + "mask" = icon('icons/effects/digi_filters.dmi', "digi", EAST), + "shading" = icon('icons/effects/digi_filters.dmi', "digi_shading", EAST), + "size" = 127, + ), + "[WEST]" = list( + "mask" = icon('icons/effects/digi_filters.dmi', "digi", WEST), + "shading" = icon('icons/effects/digi_filters.dmi', "digi_shading", WEST), + "size" = 127, + ), + ) + + var/dir_to_use = ISDIAGONALDIR(wearer.dir) ? (wearer.dir & (EAST|WEST)) : wearer.dir + var/icon/icon_to_use = masks_and_shading["[dir_to_use]"]["mask"] + var/icon/shading_to_use = masks_and_shading["[dir_to_use]"]["shading"] + var/size = masks_and_shading["[dir_to_use]"]["size"] + + appearance.add_filter("Digitigrade", 1, displacement_map_filter(icon = icon_to_use, size = size)) + appearance.add_filter("Digitigrade_shading", 1, layering_filter(icon = shading_to_use, blend_mode = BLEND_MULTIPLY)) diff --git a/monkestation/icons/mob/bandage.dmi b/monkestation/icons/mob/bandage.dmi new file mode 100644 index 0000000000000000000000000000000000000000..24b65c9c48efc9808d2aa7990178942bc602a470 GIT binary patch literal 1612 zcmV-S2DABzP)mMH_y7O@>gwvr$;q{~wes@v#;YHk00001bW%=J06^y0W&i*HuXGVY`dlyn2xh*}=WSC^oKz&OuuA_3i4(i^(m4zkCE* z!)3UR6ZE%HzmTHeo^XcK;i%Qy+vM`nwOTp!i%Z`nCX+Cal|y5jN-OIr?vJ#3kXdn` zo8PJxRUKR19md3yCF9MK@o1P0tvp&X9xWMIV zMQa$QzWntMICRmrs?@l`000FiNkl&3D>36vd^+65AR=vQ5fl)&ow4t=l+d zTf#@S=8&*%LVEc3C-ek(PZE-;okBYIw~}nhx_%PL@jcJ75C9wmvUTpS*E=7L^Q>Mu z^@I;t?-=z~a&ENeir)dz*-p*BR6F{I)H-y%(*>e`D$%jwvf}Fj00000000000K9kp z+P46cqjcX2{&!@g9HskGu|ZN3FKX{i$C}1xQjynXUF&|y{z6~ow0i$q;vdM;)6EEU`>X!T;u1sM^sBc%GwRBJZN3R2fy zT5YiM}xXj_({1(yO0|{=0~v?21+!3wA-(N|Fm&e|mc2mX(^b z{)2AW2#Fb+g4mdlIF8w(&a#X;UXc(Zy2iwhm;R|a#A=<(QbMakt)}e5+h#5oXBBm| zR}}yN000000Pt>5j?ykjN2wI8_2c>A>{t3vzpqO3yg>6=uu*3%=(fN+n=&yUklSlP zj|KYcBq%6%7Pkt@OhMC?!BY#5_0m5s(5M{x^tDhsDbQM)s^wMgYF7fej!=;tJUKAO zw;ZPFdJY<9+d@pouLV7I_W#amRz{Y*G7bp6x-sd_-r{#KOw99>RX5#s3gZ2nRz{XR z(UX-R=k<&`ycwG3Wo#CF6lw$j00000006*=+dnGqDpj89;P#JNh0{L@`A56p_K!CH zlEXY=6!DLCBM%(3%_EBCA4zvUPoXrQDk$V1arEFV6IyKlXv=71@%w);LN`d|C@5%Pn&T6C zKv$9GNj%m95mIj+ArOS_q2S-^aEZNvqfR&FuT=~WpBZQs|lX4sJ+YC)Vg6#q(Px3(jCfnIfIhs#c?I9G> z`^>n;ghlAmIBRjtGVhKYsgqNFdFv%o11mz~V=Cyxnh?#ayoJj@G9t9|49}>Ar|eh1 z4MC0;6~hA zZ`I<~6vTd(dK472EuR$t000000090(l*7v~Ub7pezeUL_jt6P>C@xfNZF%Lzk*&hA zSza1=KYOV7zW+;REJFHWw~uE!@_AUkkILFj$jg+6x{TFmC5Ss7v!mY1AcZYs5W^=5DyO|@d zd>(#GcDxtp+Yw?@rVM{74+wJQ^YCNa-mhK_XbIwZgXa0owf_UFCZA8_nh|FJ0000< KMNUMnLSTYv#tupV literal 0 HcmV?d00001 diff --git a/monkestation/sound/items/rip1.ogg b/monkestation/sound/items/rip1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..ab0fabbb3d694dbf8bb33e2272c377800816676d GIT binary patch literal 8932 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 literal 0 HcmV?d00001 diff --git a/monkestation/sound/items/rip4.ogg b/monkestation/sound/items/rip4.ogg new file mode 100644 index 0000000000000000000000000000000000000000..32c594b688d73ec669eef7398fbbf5ef52271b26 GIT binary patch literal 14002 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 iatkP+ Date: Wed, 2 Oct 2024 00:36:09 -0700 Subject: [PATCH 143/158] Update stage3.dm --- monkestation/code/modules/virology/disease/symtoms/stage3.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/virology/disease/symtoms/stage3.dm b/monkestation/code/modules/virology/disease/symtoms/stage3.dm index afe0808b87c6..601c73d38384 100644 --- a/monkestation/code/modules/virology/disease/symtoms/stage3.dm +++ b/monkestation/code/modules/virology/disease/symtoms/stage3.dm @@ -462,7 +462,7 @@ GLOBAL_LIST_INIT(disease_hivemind_users, list()) var/not_passed = TRUE var/obj/item/organ/spawned_organ while(not_passed && fail_counter <= 10) - var/organ_type = pick(typesof(/obj/item/organ/internal)) + var/organ_type = pick(mob.organs) spawned_organ = new organ_type(get_turf(mob)) if(spawned_organ.status != ORGAN_ORGANIC) qdel(spawned_organ) From f36610d3c73a42f376cddf40b9ca2559b3103920 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 2 Oct 2024 00:36:19 -0700 Subject: [PATCH 144/158] Update stage3.dm --- monkestation/code/modules/virology/disease/symtoms/stage3.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkestation/code/modules/virology/disease/symtoms/stage3.dm b/monkestation/code/modules/virology/disease/symtoms/stage3.dm index 601c73d38384..a9cc37ecfb2b 100644 --- a/monkestation/code/modules/virology/disease/symtoms/stage3.dm +++ b/monkestation/code/modules/virology/disease/symtoms/stage3.dm @@ -462,7 +462,7 @@ GLOBAL_LIST_INIT(disease_hivemind_users, list()) var/not_passed = TRUE var/obj/item/organ/spawned_organ while(not_passed && fail_counter <= 10) - var/organ_type = pick(mob.organs) + var/organ_type = pick(mob?.organs) spawned_organ = new organ_type(get_turf(mob)) if(spawned_organ.status != ORGAN_ORGANIC) qdel(spawned_organ) From d70b12f609ccf9fb32dc0413e0e7f955aad35bba Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 2 Oct 2024 23:32:05 -0700 Subject: [PATCH 145/158] fixes --- _maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm | 16 ++++++++-------- _maps/RandomRuins/SpaceRuins/oldstation.dmm | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm b/_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm index 92f43ca70358..467083499b4c 100644 --- a/_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm +++ b/_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm @@ -132,7 +132,7 @@ /turf/open/floor/iron/smooth_edge, /area/ruin/space/has_grav/derelictsulaco) "eF" = ( -/obj/effect/decal/cleanable/blood/xtracks, +/obj/effect/decal/cleanable/xenoblood/xtracks, /turf/open/floor/plating/airless, /area/ruin/space) "eU" = ( @@ -165,7 +165,7 @@ /area/ruin/space/has_grav/derelictsulaco) "fI" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/xenoblood/xtracks{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -663,7 +663,7 @@ /area/ruin/space/has_grav/derelictsulaco) "vl" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/xenoblood/xtracks{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -708,7 +708,7 @@ /area/ruin/space/has_grav/derelictsulaco) "wR" = ( /obj/effect/mapping_helpers/burnt_floor, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/xenoblood/xtracks{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -1017,7 +1017,7 @@ /area/ruin/space) "Ie" = ( /obj/effect/mapping_helpers/burnt_floor, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/xenoblood/xtracks{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -1322,7 +1322,7 @@ /area/ruin/space/has_grav/derelictsulaco) "QR" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/xenoblood/xtracks{ dir = 5 }, /obj/item/trash/flare, @@ -1433,7 +1433,7 @@ /area/ruin/space/has_grav/derelictsulaco) "TL" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/xenoblood/xtracks{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -1645,7 +1645,7 @@ /area/template_noop) "ZA" = ( /obj/effect/mapping_helpers/broken_floor, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/xenoblood/xtracks{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, diff --git a/_maps/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/RandomRuins/SpaceRuins/oldstation.dmm index 90ee5333b933..8629ad254131 100644 --- a/_maps/RandomRuins/SpaceRuins/oldstation.dmm +++ b/_maps/RandomRuins/SpaceRuins/oldstation.dmm @@ -3429,7 +3429,7 @@ /obj/machinery/door/airlock/highsecurity, /obj/structure/alien/weeds, /obj/structure/cable, -/obj/effect/decal/cleanable/blood/xtracks, +/obj/effect/decal/cleanable/xenoblood/xtracks, /obj/effect/decal/cleanable/blood/tracks, /obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ cycle_id = "oldstation-aisat" @@ -4613,7 +4613,7 @@ /turf/open/floor/iron, /area/ruin/space/ancientstation/charlie/hall) "rC" = ( -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/xenoblood/xtracks{ dir = 8 }, /obj/effect/decal/cleanable/glass, @@ -4892,7 +4892,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/item/shard, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/xenoblood/xtracks{ dir = 6 }, /obj/effect/turf_decal/tile/purple/half/contrasted, @@ -7247,7 +7247,7 @@ /turf/open/floor/plating, /area/ruin/space/ancientstation/beta/supermatter) "Np" = ( -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/xenoblood/xtracks{ dir = 10 }, /turf/open/floor/engine, @@ -8194,7 +8194,7 @@ /turf/open/floor/engine, /area/ruin/space/ancientstation/delta/biolab) "Wd" = ( -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/xenoblood/xtracks{ dir = 5 }, /turf/open/floor/engine, From 288e08c5e6a9181ec82f2855f80ba5da97286032 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 3 Oct 2024 00:50:29 -0700 Subject: [PATCH 146/158] guh --- code/modules/surgery/bodyparts/head_hair_and_lips.dm | 12 ++++++++++++ .../modules/temperature_overhaul/living_procs.dm | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/code/modules/surgery/bodyparts/head_hair_and_lips.dm b/code/modules/surgery/bodyparts/head_hair_and_lips.dm index 670462bdac8c..1e3f2078ca46 100644 --- a/code/modules/surgery/bodyparts/head_hair_and_lips.dm +++ b/code/modules/surgery/bodyparts/head_hair_and_lips.dm @@ -8,6 +8,16 @@ var/mob/living/carbon/human/human_head_owner = owner var/datum/species/owner_species = human_head_owner.dna.species + var/offset = 0 + if(!istype(owner, /mob/living/carbon/human/dummy)) + switch(human_head_owner.get_mob_height()) + if(HUMAN_HEIGHT_DWARF) + offset = -2 + if(HUMAN_HEIGHT_SHORTEST) + offset = -1 + if(HUMAN_HEIGHT_SHORT) + offset = 0 + //HIDDEN CHECKS START hair_hidden = FALSE facial_hair_hidden = FALSE @@ -75,6 +85,7 @@ //Overlay facial_overlay = mutable_appearance(sprite_accessory.icon, sprite_accessory.icon_state, -HAIR_LAYER) facial_overlay.alpha = facial_hair_alpha + facial_overlay.pixel_y = offset //Gradients facial_hair_gradient_style = LAZYACCESS(human_head_owner.grad_style, GRADIENT_FACIAL_HAIR_KEY) if(facial_hair_gradient_style) @@ -89,6 +100,7 @@ //Overlay hair_overlay = mutable_appearance(sprite_accessory.icon, sprite_accessory.icon_state, -HAIR_LAYER) hair_overlay.alpha = hair_alpha + //hair_overlay.pixel_y = offset //Gradients hair_gradient_style = LAZYACCESS(human_head_owner.grad_style, GRADIENT_HAIR_KEY) if(hair_gradient_style) diff --git a/monkestation/code/modules/temperature_overhaul/living_procs.dm b/monkestation/code/modules/temperature_overhaul/living_procs.dm index 009760be7a22..1e754745bfa9 100644 --- a/monkestation/code/modules/temperature_overhaul/living_procs.dm +++ b/monkestation/code/modules/temperature_overhaul/living_procs.dm @@ -104,7 +104,7 @@ // Only apply slowdown if the body is cold rather than the skin if(bodytemperature < cold_threshold_medium && !HAS_TRAIT(src, TRAIT_RESISTCOLD)) add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((cold_threshold_medium - bodytemperature) / COLD_SLOWDOWN_FACTOR)) - else if(LAZYACCESS(movespeed_modification, /datum/movespeed_modifier/cold)) + else if(has_movespeed_modifier(/datum/movespeed_modifier/cold)) remove_movespeed_modifier(/datum/movespeed_modifier/cold) // We are not to hot or cold, remove status and moods From 5924f40a360b70514b624a4c99a0bf22a376e555 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 3 Oct 2024 12:55:53 -0700 Subject: [PATCH 147/158] Update icemoon_surface_mining_site.dmm --- _maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm | 1 - 1 file changed, 1 deletion(-) diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm index 9b2a6c2920b8..c011fba61655 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm @@ -82,7 +82,6 @@ /turf/open/floor/wood, /area/ruin/unpowered) "s" = ( -/obj/effect/decal/cleanable/trail_holder, /turf/open/floor/wood, /area/ruin/unpowered) "t" = ( From aa270e4ad879f5626d44c78544d5d014440386fa Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 3 Oct 2024 12:59:10 -0700 Subject: [PATCH 148/158] Update deforest.dm --- .../code/modules/blueshift/reagents/deforest.dm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/monkestation/code/modules/blueshift/reagents/deforest.dm b/monkestation/code/modules/blueshift/reagents/deforest.dm index 1b5e073689cc..546b880fa947 100644 --- a/monkestation/code/modules/blueshift/reagents/deforest.dm +++ b/monkestation/code/modules/blueshift/reagents/deforest.dm @@ -360,13 +360,13 @@ // If the target is a robot, or has muscle veins, then they get an effect similar to herignis, heating them up quite a bit if((our_guy.mob_biotypes & MOB_ROBOTIC) || HAS_TRAIT(our_guy, TRAIT_STABLEHEART)) - var/heating = mob_heating_muliplier * creation_purity * REM * seconds_per_tick + var/heating = mob_heating_muliplier * REM * seconds_per_tick our_guy.reagents?.chem_temp += heating - our_guy.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT) + our_guy.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT, max_temp = our_guy.bodytemp_heat_damage_limit) if(!ishuman(our_guy)) return var/mob/living/carbon/human/human = our_guy - human.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT) + human.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT, max_temp = our_guy.bodytemp_heat_damage_limit) else our_guy.adjustOrganLoss(ORGAN_SLOT_HEART, 0.1 * REM * seconds_per_tick) @@ -398,13 +398,13 @@ // If the target is a robot, or has muscle veins, then they get an effect similar to herignis, heating them up quite a bit if((our_guy.mob_biotypes & MOB_ROBOTIC) || HAS_TRAIT(our_guy, TRAIT_STABLEHEART)) - var/heating = (mob_heating_muliplier * 2) * creation_purity * REM * seconds_per_tick + var/heating = (mob_heating_muliplier * 2) * REM * seconds_per_tick our_guy.reagents?.chem_temp += heating - our_guy.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT) + our_guy.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT, max_temp = our_guy.bodytemp_heat_damage_limit) if(!ishuman(our_guy)) return var/mob/living/carbon/human/human = our_guy - human.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT) + human.adjust_bodytemperature(heating * TEMPERATURE_DAMAGE_COEFFICIENT, max_temp = our_guy.bodytemp_heat_damage_limit) else our_guy.adjustOrganLoss(ORGAN_SLOT_HEART, 1 * REM * seconds_per_tick, required_organtype = affected_organtype) our_guy.adjustToxLoss(1 * REM * seconds_per_tick, updating_health = FALSE, forced = TRUE, required_biotype = affected_biotype) From a3a7521679e04a1bb8be66861e77b8521ea7539f Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 3 Oct 2024 20:52:15 -0700 Subject: [PATCH 149/158] Update golems.dm --- .../mob/living/carbon/human/species_types/golems.dm | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index bbc71792002e..489f27ab625c 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -106,6 +106,7 @@ //Can burn and takes damage from heat //no RESISTHEAT, NOFIRE inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_GENELESS, TRAIT_NOBREATH, TRAIT_NODISMEMBER, @@ -311,6 +312,7 @@ meat = /obj/item/stack/sheet/mineral/wood //Can burn and take damage from heat inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_GENELESS, TRAIT_NOBREATH, TRAIT_NODISMEMBER, @@ -554,6 +556,7 @@ id = SPECIES_GOLEM_BANANIUM fixed_mut_color = "#ffff00" inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_CLUMSY, TRAIT_GENELESS, TRAIT_NOBREATH, @@ -656,6 +659,7 @@ sexes = FALSE info_text = "As a Runic Golem, you possess eldritch powers granted by the Elder Goddess Nar'Sie." inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_NO_UNDERWEAR, TRAIT_GENELESS, TRAIT_NOBREATH, @@ -740,6 +744,7 @@ info_text = "As a Cloth Golem, you are able to reform yourself after death, provided your remains aren't burned or destroyed. You are, of course, very flammable. \ Being made of cloth, your body is immune to spirits of the damned and runic golems. You are faster than that of other golems, but weaker and less resilient." inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_NO_UNDERWEAR, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, @@ -910,6 +915,7 @@ name = "Plastic Golem" id = SPECIES_GOLEM_PLASTIC inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, TRAIT_GENELESS, @@ -1005,6 +1011,7 @@ special_names = list("Box") info_text = "As a Cardboard Golem, you aren't very strong, but you are a bit quicker and can easily create more brethren by using cardboard on yourself. Cardboard makes a poor building material for tongues, so you'll have difficulty speaking." inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_NO_UNDERWEAR, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, @@ -1071,6 +1078,7 @@ id = SPECIES_GOLEM_LEATHER special_names = list("Face", "Man", "Belt") //Ah dude 4 strength 4 stam leather belt AHHH inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, TRAIT_GENELESS, @@ -1097,6 +1105,7 @@ special_names = list("Boll","Weave") fixed_mut_color = null inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_NO_UNDERWEAR, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, @@ -1137,6 +1146,7 @@ sexes = FALSE fixed_mut_color = null inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_NO_UNDERWEAR, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, @@ -1251,6 +1261,7 @@ prefix = "Snow" special_names = list("Flake", "Blizzard", "Storm") inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_NO_UNDERWEAR, TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, @@ -1315,6 +1326,7 @@ prefix = "Metallic Hydrogen" special_names = list("Pressure","Crush") inherent_traits = list( + TRAIT_MUTANT_COLORS, TRAIT_GENELESS, TRAIT_NOBREATH, TRAIT_NODISMEMBER, From bc3ae30a324a01961569ad8397c75cfbe6820e98 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 3 Oct 2024 20:58:04 -0700 Subject: [PATCH 150/158] replaced --- .../screenshot_antag_icons_bloodbrother.png | Bin 2438 -> 2434 bytes .../screenshot_antag_icons_bloodsucker.png | Bin 1594 -> 1654 bytes ...enshot_antag_icons_bloodsuckerbreakout.png | Bin 1594 -> 1654 bytes ...creenshot_antag_icons_vampiricaccident.png | Bin 1594 -> 1654 bytes ...reenshot_humanoids__datum_species_mush.png | Bin 804 -> 825 bytes ...shot_humanoids__datum_species_ornithid.png | Bin 0 -> 1760 bytes ...eenshot_humanoids__datum_species_satyr.png | Bin 1219 -> 1222 bytes ...enshot_humanoids__datum_species_simian.png | Bin 914 -> 900 bytes ...shot_humanoids__datum_species_werewolf.png | Bin 0 -> 681 bytes 9 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_ornithid.png create mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_werewolf.png diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodbrother.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodbrother.png index 399627ac15def675b04e29b961672dc2d40dee36..0a7fdd7fb774cca2915334607628048d11a0b63c 100644 GIT binary patch delta 2304 zcmYk7c{~%28^?233`NM*LC%K4&`?A=97!>^3@znmEVjv=o65NuV_0s^#Kntl?O33))HhhB;qhZtCl@3^xNCZmZIUu} zEN8K7Ew@^QS-*HDSvRof$;kBCe_yU3_^T%;b|-A_ZZ&95qVVm*$foTv z(a#%WsnU}M55gKlMX@KjO=_UBI7N9h#Vw$pgQt1Z-1`h~qwRdI37dl3~Dm0u-h4|SLBb0wN}Kc^DO9h6L;+$l=e2!tek zPCC?llN5--H&!Va4xys>2gPR}ut8&;gI;j&Rg`r3f7Kqv!$Y(@7Cc%&k&>G`9!APn zlslL*?k59O2Q^>#XBA{5rJvFzWIiP{S1Z_cA*`ViFf@}66Xu{|iaD(O=j2}HjH`LL z@!MBP^<N3xh`jzyM4Xue#mtdDf78Szm7i(fFT10z)Q#k6FWwvM5P74S2o|E&_rBlaR5Ce&4 zMq>Dr;qxh*p#10wg@C&aVynF7n$RD6m#7bpc1~HT`c_WzFVs{NWakW7cO2msk+76j ze|_>Fgr_-R?BDw^r0XG&I%$SANgDNx*joXIn(8rVOBj4SA>&=SW0H|L2)!Rd3o?W> zDH;eaTQN5g9}OHP4Z4O);G0;%kJrt(w{qI(550VvQ;HQcL`uAk|A*ASB_)r}`RNnP zw8t0qakA7|RF50vlMp2uuCa@KnIPJ_Ylb>t1IiNE%f3Ty%263rV5vy4Dy3ThG1u!C zLp~(Fru`)pjy;72{8Y#D{5|%sJ_Tf+xz(N82h!#~@6zr#qen`=N-EeUpiKE^L2sIvGE^zVRc(c^>XkLUeefQ5i@bQTc4)zMXw}fvMwOan? z9MT@ET5#!W4Bmw{wvxHv51&Db(v;RN^n4`f-*@fTx9PimCcywHZgb;6f?Ctv3)R_N z<4~57i$-sB?d085G>KXipp%vZC^76_sGts&p0?R%wRZJzAk6O`s1ywTv_jdIHhpXO z8^7GB3<-X(W-nAo1o$yt*!yk(0x#s++B)slZyqS9g4lX~p>1}p(%K*x3_65cJh0<)w0=gbiLB9p98Y14Ue)MPo3#=SKwnqijp) z31FR#OgU2H_~j>uDyO<3VVDY;tPNv-8vtNZE_%?ofuECd1$_=kvk^YGTz6ZO2lnUU zljV6DFV!*?4Ghdh{yJwB|ckb>;UJ(E7%LOOOhyj2(X|{lCj|&T=scvpN zZBJ-O!=;9+pEW${!~BwFew>fT)z?muM&Gu-RJ(QrO&BkA-&DJ$Hx4s00>H%H3Av7g){`r)styr6etK&`f${2J zh`;{j>Xxs@ymEwBQ%$HSE!uVIj3C*dbY7sh0JE*!Hi8Rv#OWaw*N(K5ZPQ|vbn&S? zBlkdMzVuDjpzOjTfhNT6{CzrQ8mc(G|LI+47CE<<>!0_Q_WhZ+j4An8;er#gDy=Bt zc&B&zh1o=c5L6YQrm=FTPaBToHq?+*m7#1Q`*zER`L1wgX%k3MvAv_wVC0FL9Z6;* h&GZXM delta 2308 zcmY+Fdpy&P7sr#i#F$a2j7W(^^kN>(EiKA&%U!OO8XhEMVZJW8rAXzHTo$>F5F2XU zhDt6C&1J@rTWoI0hPnKndV2l({mwt<&+|E-^FHUqN+n3$%K`e&qE6ajbLU+BtusFE zG1O(AX?%faqE2^<2unZCTo>@_!0hO3`PM@CvfkY~U`^_s2?3Yc`9Ci4(eX*|3NbOn zSb#y`k`f(}AW-swbUf<)hwqaDDE?wob( z;W~7Sr=~0z5R9Yz%>S3-1lx@R_3!5xTJXA+ zF?1t0)wlcfcY=S4a_H@{?c6B3iX!aI**-CZ)%#m{U|CWUw15Eu1l6^*ofbRp*GaUc zJ}s%XosBAKb)3HDj4XA_gKdU(9yN*NAC&d0}^s=$-ymLuFq9750*yYY} zg6IYezS_&~sXR&vMCimwXXPGU-M_HKPyED9jDsOn&Oa@W%P4&5s*xUU2^Qz;yg{|D zAp=!hkthuJM3=nVO06Ro3N?7GY`th-{t;!~cJP-K6md;3Tovwow!PVyt@a?r_2#jX z=u9q$;YqEmkc#YIVd3*E)4B6Cytqu{joVC>P;Y;0CLiO}1iN`lW-6|Jv0T4qrE$U1 zc0{NlJmB=FM;8p^%%Z(&_`%JyMnIL#IbC+=EAYiuMZM;RL+WD0wm2b*xJRS)VsTUy zevQ-ikbM_o$>}f6+0tlq+b~=`+=2bDIj<7y_;5qCs`r!`HN%vGlam_q-HgvY`$Yxb zr$zZ=5?_V3O7H_khxt!$)UZzSmS#pTB6J6a1K+4(r?o5T1mIW}eS)vxIo?207uQu< zl=hY+7*!qpya?1^u}6Gz1IC`Id&9EdAKn3kyjQB}olVKKx*#wO^^|4rXs#htc(TrO zW3y%9qB(@3CG_fweZ{*}>O)n(&~B|RjWn=?{>3JvljzT(CNcf#v=EArU+6h8WVlzR z{D~j;CdBhifK=vTXd=E^>>ucUI*q;@QhBC3_SCh|GUm+gNN)@r!=31h9VQt|+xayv6=#E+RR+|X~3S?EYq)VH`moKu(H zSmyZQoefzap0TQ>BRA&vr1wc`M;Ys;?z<{P9?QFXUX;^+jJq#?-4<}YsZo?xVJnS7 zb;g|BOYpaHfv;AY-*NDPygIT% z00nLDb|3yM95By+Ku|D7&+xG6;_ZU3A^bLFo~f$}H`&zIFUv1RL6u-+cxyLQ^TU(_{8*O9`g*LLb@1%rNr_p>m`IGG1;{;|8;GEVGuXQc~Wp~@6yyZwra04-t;>12J+f1Ybx-PLfUTpe zZws6R2Q}5zZ&c=~@*W%*5&C_#ei5D_l(@VlZ121NquCQ*yf;nCmKV&Sp}Pw5D{75C zmy3?Rsd-TPE`a?)6?-{y4`v#dp@vZLbvQI71=VwpvRDkRuo1=D&x?{73eW9ij&8QAgZx{WU4E@_FN8l5C@^exYO3yfuM%1uRgTv6H2-J2uVqUZE#Bd zY@=0u&|K{3|1?yh+#37j84y0g+P~uCtpnuINQ{`lfGbPK1lXzMf3y(YeYLf)jiZ6W^3WyqMkv}P*(A~% znh^{tNt-dJSGq3)+s;d-HE&@92eD}6i+K6v(5Kti^BI1AwA=Bjt5K`f(q!0$df_Mn zctj>`bM|V_H3~x8w{GlQ?O;iGHsnvm(H|i?Q&L_-3xNj{OAB4Bj;NWEi{0wWr#4Y2 zg~?CllAB~@O*tNO1la_uQk!;>fRgkkX-ha7CekCf+L0L=@8ot;bcroYAg{P<|6)TE zT%lqkc4*yjr$OE;r(=n;bGK@hu0wPtB%nI3FO?e6XkOXu&TQW^FQ58kawqej=cqWw xA$-K8u{ZBp4rRI&#mni$=M8kiFM90XfJ|k)e`r^{=(yvbID6U>Rb}EC`yY-we$xN| diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodsucker.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodsucker.png index 27a91f8f14c2c2f092afd02824724abe89c0b7d2..786f195c0aeb69f97f11b41e19c1bc981639304c 100644 GIT binary patch delta 1518 zcmYjRc{m$(7>=TmiK|5sM+;|rJeK`f|tXzLqpIY(&BBz^t2_>da{n<#fj{OTr8?}}?{p2z$)k;r8Gi?cK z7qHCq*Pqo5F_^(#2$Ksn4U#EMhhg{LMc6E0m@QL{#)$Utzuz=Yt=^LM>)L_zjYTf< zb{BcyFbu&RhG2rwzqX_Biv!1QDE+9;+zUhK=yb{d)Re1E)^hS|6G#IS^J&CV3WcIe z3J3~HYH4iz)&kS$>*1l)FrFI>Fj58hp8<4s`e0r2a$||^puANczhRkbHK}|aEX*zT zknsqR+xf7TO$=u&&TSvU*nzSM`@TtWap=dS+lY@LwC1Cu)HlY7O40|#{=6jGKFMai zVxQaM=yc00E+&ztb_;=djJ=R8kz!=*t_C;mVMb~*{dMMKJ|TWPTfd8Hwgf(&B6`p- ze+)Q{_bVwA7;{^%>^pR~4z4EP>`QOvg37Q_Z&)K`YavC;gjCgjS=?dS4w2*9+70h# z>()AbayU_uD(w0I$^KJzD;)?18f8CxT7WG+A_)t$sM1Aj2z9~s^IfSjT9*F?(ZgXyTixGTY*@R*daLr0UHvM z=JHk`20UPGG?P+^KL>+}V%FE!yLr>ofF=@23bV6Q7hg>#!+Nm|Fu%cqf&!Vy=jArm zP1;|v<=tn^%+6XQ+^mb&QlLHijXLa05SSFzRQH}Pn|SIySuq*k{TM^Ga~NB zC0}b3!XpSr?R>?5W+8>okFNFd^lVS4fAT~mv_)aL^Obk4ab_U2x2#2@b|J5#q^Svl z!C>loOwG(PsE;10a8JYGchu5P=rIo#e*f^o^k)(S=;s8!OZ6La0&1PQjDo*s(g!NsOcP6if-g-+}v3=IJ$!-+5n z;Y>P8e`n1kmjvVSXZyFex7&tXvY1nr32qO)eTN1Ip$l76MDd-O;H8>A(1zHGk3N2* zfJn@sK6s!|yS`Z6Gij0F@2|<8z3C}&_0o|qII9oSy!FdPW^)NAp*J`h>gqP07>wSE znlz9t5C~9+{SQF&PB_PE6Pq3GODk>_{ z4v)GV5FMm9&*`=oALRICm z_%(yj`QXG+F@ z+w_M-Y2Py&iYtSQ#hg;z*cEwp9-ZO%+_%y!b$9h~&r@t2g_2!Qqe<{xf_5Pn-)7i4 zjU$^TUlh5(I433!g!r$zUJe3mO$QRS76?T?aNZnmp7Swfbc zs;xTHnr>iTpN&+P>9?`9W%Mb~v}btQRd8tecTom$!~Zci3Jsr*KJVb@mCurL>BXT^ z)nYV?9CX;0mX;`E!QM%BY}a6QNekH^{f>{9S6Y{=X-&l(uA=H`sUu+>p(6hEUW&0j zp8zJ}X8z}UcXaBPSQUPUaLQ-So&`lm!549Rd_fGft91{?=`11UJfl*Re;^M_MrRL6 z6;VE_$zSKVw?1|LB8u{6m|JsdWQikDHF5%!PY<#8i4k5Rtd~5Gc8aM6Mbrk{J9&G9 z`JG}Mcv%KsBu^{Crpj6QwV`o4?(?tkvR1wrsdjJEwK^x~2sbnRm16tAfPDWzUtpzj tgXWqEqr(Kk-e!XJ_qTRbzop`Uh?0 delta 1458 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 tgXWqEqr(Kk-e!XJ_qTRbzop`Uh?0 delta 1458 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 tgXWqEqr(Kk-e!XJ_qTRbzop`Uh?0 delta 1458 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 diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_ornithid.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_ornithid.png new file mode 100644 index 0000000000000000000000000000000000000000..63d078cd34898313f9598e382f0ee24220df53c9 GIT binary patch literal 1760 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 j!+dho{kLr&BJS%ile_=^PK~z|U z?Uw6u;~)%$u}Fdg;bONqiJjK(|CT+%-JPaIWV(Mh>XdZmlMbLT)luph_tA0uJEu+) zk?u(593odcO?&)kX^*X5>zyQU&;}|{lS_eW z8J0>tD^$6%4g!uG1YA`B4H$g+t#Z|k>7{h}C5>Z+kE4&J2hmr#(k29K9@1+ty2}4v zp~_hRO(bsOF9iakWIzB{fIxKvr4s})1d{$*rubv~6ZN*kLrB$nfAADz&N-#~GOU@G zkns@kkzS>@49)?KPzuzaBjmg-<8(f&^LeWF7%@&4@C$g@_7C6gI9(o% z$pUZWJd)y2QSi%RF_}EkyDacd zHR6m8?qIxCx_}mHV<6yKCjj=w=vo`o00HgXy0&_-uFfHCdKtb>@NLj1e2KY7i|Y>R z^9YQy#uu4>`U9TZy2a*SnBu!>eOjJd{z`y`2009300B-=4zqSAX0Evl-0OJ4vTmZ1Ju#}XP z#KgpCXlOn@K1oSQ|NsANY-}njDv^vG#55QP_E2N}#wN{wtwj`jX8*#k;Dal_(i|JIuc$;`KVfHmViM6Y-Z zk>lTaCuG-kQgl4e!E)NkZjT?y?XlHMx#I-hq{0alFVL6z{*B=WWGJP2{*pxj{J<$_ z(f7U3tbo?W7_GT_I)e7dIr7|E+u(oBd!vo_uAXtU+J+FYG78#7D0m-T{Sw;QFbqSm z9QQ7w+?(ipEkpZKpB1W{w1I%}1_GukfCdb<{8l-MF}{~BzsGT`@Nu-E^dQ(OC#jsn z<}UtlN>=&rD^z(FKofm#;$I4!5G4ZwxB>*K8<30;NDzqfYZ>J~+rOyS0uO&7R_noI z2q~o)AIq?&yqppqf+O^Rd&}TCpm8b%^y>&IZOb^F&vZUd)gB|p=>mQMKW+P;{B03{1g;DxInVP%6M{(qpSR@|uXx3?c;XM9@y#GKGDOoqWCO74M7QS!_Q1S< z$O3QKAg~Fd?H>?_Y!F%kZU29OugwGeL8}L%=^rroEDS>3S zZLr}s!UABpYHl*oh%*|vgYj1B0$M1Qf`DnA0N5%eYi*1J1f((Rdgp)Y(Svn025HOi zb%Jk$KH@`6Jz89MP@hN0I7xhv@w-3BbGz58Uio?=V4cz}#z%ipCOyV}c_{6dm=kj5 zgFo2BU=rXBrVDEihyYq0bcKcBaL&jMVV=2+0%unL75{Vm1V@oA V!qKCF(EtDd07*qoM6LruV1n%SUxEMt diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_werewolf.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_werewolf.png new file mode 100644 index 0000000000000000000000000000000000000000..dce4b390b828fefa40563ce85650d7408edea38a GIT binary patch literal 681 zcmV;a0#^NrP)V=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+ z(=$pSoZ^zil2jm5Nr{UyC9|j)q@Ig2ttc@!6~s2=QdV&Fa{-$O0Gj_84mqJ=L;wH* z%Sl8*R7i=9l{Y!HuMS%06#@pvXx?ShA04g!@Qe+N=G&Opi%>!bGv z(y0ZoOAS@;`aT1IRZKD!67u?b?IG2LPh$=<)FgTElIEQcl1e&OR+QNUaT%=0gj>hn8!#L+Xg@sip%X z$6SrQ1}q134n`(v;307D1)z)bD;xO5u_%5PosDI2AD{sqQ#M97>RkiO1%8O*79PwS zJ^|oU0W3m$=9YMPWt(*|UL1RZ!a%t1F+UimYlj`LqQ?4kT~z7AEl~j0{=5LLSpzDU z0KX0-4@CfKSw$CsCCg&?5mOwm5$@8vR~{PFeFzWL62eS(T>-VrhIK$_m4o_+VPy(~ z+yDZw>mGn_kV8u?GDqc8-F7)s@flWtW$&bTlH%Pa!1SxEVqyrt3dC=Jjpt5y_sOhz P00000NkvXXu0mjfbM+eW literal 0 HcmV?d00001 From 9438d8556bd19b00358f4d41a271f7723543b457 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Thu, 3 Oct 2024 21:35:34 -0700 Subject: [PATCH 151/158] Update dummy.dm --- code/modules/mob/living/carbon/human/dummy.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index 0a49e5957604..dbf438919b50 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -123,6 +123,9 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) target.dna.features["satyr_fluff"] = "Normal" //Monkestation Addition target.dna.features["satyr_tail"] = "Short" //Monkestation Addition target.dna.features["satyr_horns"] = "Back" //Monkestation Addition + target.dna.features["arm_wings"] = "Monochrome" //Monkestation Addition + target.dna.features["ears_avian"] = "Hermes" //Monkestation Addition + target.dna.features["tail_avian"] = "Eagle" //Monkestation Addition var/datum/color_palette/generic_colors/palette = target.dna.color_palettes[/datum/color_palette/generic_colors] palette.mutant_color = COLOR_VIBRANT_LIME From 881736cdf09b299feba918541e0c38da860c29d6 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 4 Oct 2024 12:18:50 -0700 Subject: [PATCH 152/158] Update golems.dm --- code/modules/mob/living/carbon/human/species_types/golems.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 489f27ab625c..0c4196aeafcc 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -34,6 +34,8 @@ // changes, only the Random Golem type can be chosen fixed_mut_color = "#aaaaaa" + bodytemp_cold_damage_limit = ICEBOX_MIN_TEMPERATURE - 10 KELVIN + bodypart_overrides = list( BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/golem, BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/golem, From 6aa7a9abe79fbd1ec614f3b781be06c80b0e5400 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Fri, 4 Oct 2024 18:55:26 -0700 Subject: [PATCH 153/158] lore section --- code/modules/client/preferences/species.dm | 1 + .../mob/living/carbon/human/_species.dm | 6 ++++++ .../modules/the_bird_inside_of_me/species.dm | 13 ++++++++----- .../CharacterPreferenceWindow.tsx | 2 +- .../interfaces/PreferencesMenu/SpeciesPage.tsx | 18 ++++++++++++++++++ .../tgui/interfaces/PreferencesMenu/data.ts | 1 + 6 files changed, 35 insertions(+), 6 deletions(-) diff --git a/code/modules/client/preferences/species.dm b/code/modules/client/preferences/species.dm index f47dd4bf2866..9e4923d2b11d 100644 --- a/code/modules/client/preferences/species.dm +++ b/code/modules/client/preferences/species.dm @@ -39,6 +39,7 @@ data[species_id] = list() data[species_id]["name"] = species.name data[species_id]["desc"] = species.get_species_description() + data[species_id]["lore"] = species.get_species_lore() data[species_id]["icon"] = sanitize_css_class_name(species.name) data[species_id]["use_skintones"] = (TRAIT_USES_SKINTONES in species.inherent_traits) data[species_id]["sexes"] = species.sexes diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 3da99d8426d1..d3de62aaeea9 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -1572,6 +1572,12 @@ GLOBAL_LIST_EMPTY(features_by_species) stack_trace("Species [name] ([type]) did not have a description set, and is a selectable roundstart race! Override get_species_description.") return "No species description set, file a bug report!" +/datum/species/proc/get_species_lore() + SHOULD_CALL_PARENT(FALSE) + RETURN_TYPE(/list) + + return list("No species lore set!") + /** * Translate the species liked foods from bitfields into strings * and returns it in the form of an associated list. diff --git a/monkestation/code/modules/the_bird_inside_of_me/species.dm b/monkestation/code/modules/the_bird_inside_of_me/species.dm index fd3c0d7919c4..7d790cfba68a 100644 --- a/monkestation/code/modules/the_bird_inside_of_me/species.dm +++ b/monkestation/code/modules/the_bird_inside_of_me/species.dm @@ -100,12 +100,8 @@ GLOBAL_LIST_EMPTY(tails_list_avian) ) // section for lore/perk descs -/datum/species/ornithid/get_species_description() +/datum/species/ornithid/get_species_lore() return list( - "Ornithids are a collective group of various human descendant, or otherwise resembling, sentient avian beings.", - "Their most well known physical trait are their reduced weight, and feathery \"wings\" protuding from their arms, which they can use to fly.", - "There are countless various types and groups of Ornithids, with a variety of backgrounds both known and unknown by NT. ", - "Much to the chagrin of the collective, the term \"Ornithid\" is in effect, a dumping ground of the various human-derived avian animalids, making it the second most populous animalid group. \ Several cultural and geneological groups can fall under this banner, with sometimes only those directly related to eachother baring any resemblance physically.", @@ -132,6 +128,13 @@ GLOBAL_LIST_EMPTY(tails_list_avian) ) +/datum/species/ornithid/get_species_description() + return list( + "Ornithids are a collective group of various human descendant, or otherwise resembling, sentient avian beings.", + "Their most well known physical trait are their reduced weight, and feathery \"wings\" protuding from their arms, which they can use to fly.", + "There are countless various types and groups of Ornithids, with a variety of backgrounds both known and unknown by NT. " + ) + /datum/species/ornithid/create_pref_unique_perks() var/list/to_add = list() diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferenceWindow.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferenceWindow.tsx index 45fb52341a86..4b595b16388f 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferenceWindow.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferenceWindow.tsx @@ -86,7 +86,7 @@ export const CharacterPreferenceWindow = (props) => { diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/SpeciesPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/SpeciesPage.tsx index 9efb560a9ece..cefbf04223e5 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/SpeciesPage.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/SpeciesPage.tsx @@ -2,6 +2,7 @@ import { classes } from 'common/react'; import { useBackend } from '../../backend'; import { Box, + BlockQuote, Button, Divider, Icon, @@ -324,6 +325,23 @@ const SpeciesPageInner = (props: { + +

+
+ {currentSpecies.lore.map((text, index) => ( + + {text} + {index !== currentSpecies.lore.length - 1 && ( + <> +
+
+ + )} +
+ ))} +
+
+ diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/data.ts b/tgui/packages/tgui/interfaces/PreferencesMenu/data.ts index 679216a9ca1f..b9b69f06c08b 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/data.ts +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/data.ts @@ -40,6 +40,7 @@ export type Name = { export type Species = { name: string; desc: string; + lore: string[]; icon: string; use_skintones: BooleanLike; From 3071e0dce52da7a9e91dad528e8d22089efb445d Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 5 Oct 2024 01:40:25 -0700 Subject: [PATCH 154/158] fixes --- code/modules/mob/living/carbon/carbon.dm | 1 + .../living/carbon/human/species_type/teratoma.dm | 15 ++++++++++++++- .../surgery/bodyparts/teratoma_bodyparts.dm | 12 ++++++------ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 3533e1c3b338..16141c8a59a6 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1003,6 +1003,7 @@ var/obj/item/bodypart/bodypart_instance = new real_body_part_path() bodypart_instance.set_owner(src) bodyparts.Remove(bodypart_path) + bodypart_instance.check_adding_composition(src) add_bodypart(bodypart_instance) switch(bodypart_instance.body_part) if(ARM_LEFT) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm index 73f58d3658cc..c10c3faa7564 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm @@ -2,7 +2,6 @@ name = "Teratoma" id = SPECIES_TERATOMA bodytype = BODYTYPE_ORGANIC | BODYTYPE_MONKEY - mutanttongue = /obj/item/organ/internal/tongue/monkey mutantbrain = /obj/item/organ/internal/brain/primate inherent_traits = list( @@ -93,3 +92,17 @@ /obj/item/organ/internal/tongue/teratoma liked_foodtypes = MEAT | BUGS | GORE | GROSS | RAW disliked_foodtypes = CLOTH + +/obj/item/organ/internal/tongue/teratoma/get_scream_sound() + return pick( + 'sound/creatures/monkey/monkey_screech_1.ogg', + 'sound/creatures/monkey/monkey_screech_2.ogg', + 'sound/creatures/monkey/monkey_screech_3.ogg', + 'sound/creatures/monkey/monkey_screech_4.ogg', + 'sound/creatures/monkey/monkey_screech_5.ogg', + 'sound/creatures/monkey/monkey_screech_6.ogg', + 'sound/creatures/monkey/monkey_screech_7.ogg', + ) + +/obj/item/organ/internal/tongue/teratoma/get_laugh_sound() + return 'monkestation/sound/voice/laugh/simian/monkey_laugh_1.ogg' diff --git a/monkestation/code/modules/surgery/bodyparts/teratoma_bodyparts.dm b/monkestation/code/modules/surgery/bodyparts/teratoma_bodyparts.dm index fc9602239634..96e67800e663 100644 --- a/monkestation/code/modules/surgery/bodyparts/teratoma_bodyparts.dm +++ b/monkestation/code/modules/surgery/bodyparts/teratoma_bodyparts.dm @@ -7,7 +7,7 @@ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM should_draw_greyscale = FALSE head_flags = HEAD_LIPS | HEAD_DEBRAIN - composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 1) + composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 0.8) dmg_overlay_type = "monkey" @@ -19,7 +19,7 @@ is_dimorphic = FALSE bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM should_draw_greyscale = FALSE - composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 1) + composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 0.8) dmg_overlay_type = "monkey" @@ -31,7 +31,7 @@ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM should_draw_greyscale = FALSE hand_traits = list(TRAIT_CHUNKYFINGERS) - composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 1) + composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 0.8) dmg_overlay_type = "monkey" @@ -43,7 +43,7 @@ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM should_draw_greyscale = FALSE hand_traits = list(TRAIT_CHUNKYFINGERS) - composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 1) + composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 0.8) dmg_overlay_type = "monkey" @@ -57,7 +57,7 @@ speed_modifier = -0.075 footprint_sprite = FOOTPRINT_SPRITE_PAWS bodypart_traits = list(TRAIT_VAULTING) - composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 1) + composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 0.8) /obj/item/bodypart/leg/right/teratoma icon_static = 'monkestation/icons/mob/species/teratoma/bodyparts.dmi' @@ -70,4 +70,4 @@ speed_modifier = -0.075 dmg_overlay_type = "monkey" bodypart_traits = list(TRAIT_VAULTING) - composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 1) + composition_effects = list(TRAIT_PASSTABLE = 0.5, TRAIT_VENTCRAWLER_ALWAYS = 0.8) From 77ed7bdb5135796809b1d5260ebaf321a144328a Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sun, 6 Oct 2024 13:52:06 -0700 Subject: [PATCH 155/158] Update internal_bleeding.dm --- monkestation/code/modules/a_medical_day/internal_bleeding.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/monkestation/code/modules/a_medical_day/internal_bleeding.dm b/monkestation/code/modules/a_medical_day/internal_bleeding.dm index ea622ccaf5a2..aa6db29e32e1 100644 --- a/monkestation/code/modules/a_medical_day/internal_bleeding.dm +++ b/monkestation/code/modules/a_medical_day/internal_bleeding.dm @@ -30,6 +30,7 @@ /datum/wound/bleed_internal/handle_process(seconds_per_tick, times_fired) . = ..() + regen_ticks_current++ if(!victim || victim.stat == DEAD || HAS_TRAIT(victim, TRAIT_STASIS) || !victim.needs_heart()) return victim.bleed(min(bleed_amount * severity * seconds_per_tick, 3)) From 1fdc642581388ed8bacd3950f8926284d240fef4 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 7 Oct 2024 12:29:55 -0700 Subject: [PATCH 156/158] Update living_procs.dm --- .../modules/temperature_overhaul/living_procs.dm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/monkestation/code/modules/temperature_overhaul/living_procs.dm b/monkestation/code/modules/temperature_overhaul/living_procs.dm index 1e754745bfa9..98ea4f3f5845 100644 --- a/monkestation/code/modules/temperature_overhaul/living_procs.dm +++ b/monkestation/code/modules/temperature_overhaul/living_procs.dm @@ -1,9 +1,9 @@ /mob/living/proc/body_temperature_damage(datum/gas_mixture/environment, seconds_per_tick, times_fired) if(bodytemperature > bodytemp_heat_damage_limit && !HAS_TRAIT(src, TRAIT_RESISTHEAT)) var/heat_diff = bodytemp_heat_damage_limit - standard_body_temperature - var/heat_threshold_low = bodytemp_heat_damage_limit + heat_diff * 0.75 - var/heat_threshold_medium = bodytemp_heat_damage_limit + heat_diff * 1.25 - var/heat_threshold_high = bodytemp_heat_damage_limit + heat_diff * 2 + var/heat_threshold_low = bodytemp_heat_damage_limit + heat_diff * 1.25 + var/heat_threshold_medium = bodytemp_heat_damage_limit + heat_diff * 2 + var/heat_threshold_high = bodytemp_heat_damage_limit + heat_diff * 4 var/firemodifier = round(fire_stacks, 1) * 0.01 if (!on_fire) // We are not on fire, reduce the modifier @@ -13,18 +13,18 @@ var/effective_temp = CELCIUS_TO_KELVIN(KELVIN_TO_CELCIUS(bodytemperature) * (1 + firemodifier)) var/burn_damage = HEAT_DAMAGE if(effective_temp > heat_threshold_high) - burn_damage *= 8 + burn_damage *= 5 else if(effective_temp > heat_threshold_medium) - burn_damage *= 4 + burn_damage *= 3 else if(effective_temp > heat_threshold_low) - burn_damage *= 2 + burn_damage *= 1 temperature_burns(burn_damage * seconds_per_tick) if(effective_temp > heat_threshold_medium) apply_status_effect(/datum/status_effect/stacking/heat_exposure, 1, heat_threshold_medium) - // For cold damage, we cap at the threshold if you're dead + // For cold damage, we cap at the threshold if you're dead if(bodytemperature < bodytemp_cold_damage_limit && !HAS_TRAIT(src, TRAIT_RESISTCOLD) && (getFireLoss() < maxHealth || stat != DEAD)) var/cold_diff = bodytemp_cold_damage_limit - standard_body_temperature var/cold_threshold_low = bodytemp_cold_damage_limit + cold_diff * 1.2 From 59aeca2192c1f608bdb1b3e09370ac87414e4a1b Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:48:30 -0700 Subject: [PATCH 157/158] Update screenshot_humanoids__datum_species_ornithid.png --- ...shot_humanoids__datum_species_ornithid.png | Bin 1760 -> 1281 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_ornithid.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_ornithid.png index 63d078cd34898313f9598e382f0ee24220df53c9..b3fcb82247ff043c7a4806089572135e1b15c370 100644 GIT binary patch delta 1138 zcmV-&1daRP4S@=fBYyy;P)t-sz`($QEC1S_lKIib|KQPVB-HA^v}Ga2l)ttB004=J ziQ%uNu&}VadvP^5L5`4<8X6&CAiq{xW3#ifba#MvdxLc+=7B5yZzb7LPg~r=icAFiP+~d_CKuz7w7!? z)4%Kf_gtic59w)|(mMOXGa*FAzYzL}X8>e;L;-HNxJ_>b7laN49SVL!0q({E6~vem zIv)$a#&?8%&nACkf!Bm8;C12kdzyd%Iv)g)2|AxirN-m2Qj*YfCH+!4q3c4HCNrfh zG^IcIMd{VFC`)BjSr*eOqT8t~3gj1soZ4u<1)xNJS=a~xdJY1X%x#Qdr@BD-8ch^B z5>QRG%w?YAk~&hrR+W}0Z_tF)Rn;ZfDF8)|2J!-ceg%J9S!u2SBW(mwvC9sy2fv?g zgVt#F2f(zk@0&z}RuJRA#@hbkB5_t>+8*Wli*s%bq_G# zlkbKGY=0z4@?!v?3t;Q@A$dt)LOo>n=6Fe60sbv3Q@ z5W#=vhoA@nzMI2zF$Cb*Oabt~#%ute_R(DcYztatay0}{xv5aa`&+*Q04l3K>Ofg| zyX3=p4^Kd(F+7Ga8k> zVKL9`34jLfY<|W8KfQ*K^U3zk&@VkdH;sQ=ES{dJ4xXPD3)eK~IWdXW=Inft0q240 z&Za)a^|cS6rh_Y?^aa*Yakbji-kB+LW*7g)SG`%SdfEn~!>=%%3(zqD*5)Re!r0001GA;yV` ziQ%uNu&}VadvSj%`87B}j*ydoD*754A$2F_R$61Tv$J$}fO{$OcYA|d9F( zbSC6#BhPUq-FPVMW+KRBA;otm=}}KxdMNO0B-2qFo=zH>Tz?+4c_{94CgF7_<#{OW zdMNL9C+K1zz*8HeOc|DNCEIu?>tP_iZ6wxUAiY-|s%|9MbSC3vBFAwh-ee)fULUx8 zDfD6?!B!lpN*R)ABh5e+eQ+h*VIaR`~b zxiJu6dnxfi6@F_Y(pDU(XCljLBhZd>ZFeW?Mi+^FDfU+#t8FCJR2-#G8k<@kv2Qpf zRxcq;AR3Q2FqTp|fGYc2P)mU;{f2gKSRJfU8=rF~;tE_MY`6pu?gC@ zwf^lp7k&B!$PLe9f9v7NO`hj-&i9_2gq(xWmu7+>d>$8LVw8svi^U?iB*>yD%7Vn_ zAi(GGD}p!?n-B#t9?BIUkfA7lTv5UWl&c95b`TRnxIh|CgK!#6;aD47u9m*ixK z7#A6zIxm8pphH5J0AfKM~S zhBg%@a4l_^CZWVMjr6q;K4W3SfOx~eshJR-u`?iGLcD3f^$5>eU+JKK0EYFit=Un5 zbS7=U_6{Ur!1V~feq#>nSl8jeH*@)6oO0(i6~p!vlEA7q?+%usP%M4(EjDyWKsRu% z{N3ze4k@LwpkjI_{Tdx9Hx(xz^f&;vN4HVhWy#e0->u=z+1H1!gwEWL?G-&ZG+#@_eslTH9%OS2DL5WUld{vh0y*IZVu^l!sEb>yQq827Z}44>YeoZ$7Ol5GG|=j;aA*nX8Yn2mfV4BQ{6^rjCbkX#DiF2VZU0 zn79UCD{%2(MhK11uWKfWQeg4K)YkJM3eb0TubK8G9lp&x0r+6+lAmsR%zIb>+Lm|Z zzoxK7gaFZh>1+SUWBqM3gQhoCkjS_Uh*X&Jnxh#&-);NbZ4DBL6d=0R-uByUNEjBt zzUx~O87Dv_3mox?fR43RrBvFGnA4l^_&1D68!)c4G(3C@NLS)^b+h;ux-)$jF7S@A zx5dq>9al!;p&!3*{@1kH_4@7}FN3|^dcAFd+xu*P2=09NXe~)>lZeg(R9dn=e&~eI zN_D?hBGyPX?hEf^hqHE;GOln4RHA+P%2 z+!~69zTfd#0^ Date: Wed, 9 Oct 2024 12:16:22 -0700 Subject: [PATCH 158/158] Update corgi.dm --- code/modules/mob/living/basic/pets/dog/corgi.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/basic/pets/dog/corgi.dm b/code/modules/mob/living/basic/pets/dog/corgi.dm index b16fdba87458..48950bfa208c 100644 --- a/code/modules/mob/living/basic/pets/dog/corgi.dm +++ b/code/modules/mob/living/basic/pets/dog/corgi.dm @@ -75,7 +75,7 @@ update_appearance(UPDATE_OVERLAYS) return ..() -/mob/living/basic/pet/dog/corgi/gib() +/mob/living/basic/pet/dog/corgi/gib(no_brain, no_organs, no_bodyparts, safe_gib = TRUE) undress_dog() if(access_card) access_card.forceMove(drop_location())

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 ?dT?9EQob67oebe{b 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

epR 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%0D3MuT!}=Ncvx%b_4_1-fh?tZqqyxZ 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