From aac6045ba8b193aaaff85e9492de5b7703f508d1 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Tue, 9 May 2023 03:56:30 +0100 Subject: [PATCH] [MIRROR] Golem Rework [MDB IGNORE] (#21001) * Golem Rework * SECT 9 * ok --------- Co-authored-by: Jacquerel Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com> --- .../map_files/IceBoxStation/IceBoxStation.dmm | 1 - code/__DEFINES/DNA.dm | 87 +- .../atmospherics/atmos_mob_interaction.dm | 9 + code/__DEFINES/colors.dm | 3 + .../signals_atom/signals_atom_movement.dm | 2 + .../signals/signals_mob/signals_mob_carbon.dm | 5 + code/__DEFINES/food.dm | 6 +- code/__DEFINES/mobs.dm | 14 +- code/__DEFINES/traits.dm | 12 + code/_globalvars/phobias.dm | 1 - code/_globalvars/traits.dm | 1 + code/datums/atmosphere/planetary.dm | 6 +- .../emote_bodypart_overlay.dm | 22 +- code/datums/components/food/edible.dm | 4 +- code/datums/components/food/golem_food.dm | 119 ++ code/game/atoms.dm | 3 +- .../stacks/golem_food/golem_food_buff.dm | 117 ++ .../stacks/golem_food/golem_hand_actions.dm | 106 ++ .../stacks/golem_food/golem_status_effects.dm | 446 ++++++ code/game/objects/items/stacks/stack.dm | 3 + code/game/turfs/closed/minerals.dm | 37 +- .../antagonists/abductor/machinery/pad.dm | 8 +- code/modules/clothing/masks/gasmask.dm | 3 - code/modules/clothing/shoes/boots.dm | 1 - code/modules/clothing/shoes/clown.dm | 1 - code/modules/clothing/suits/jacket.dm | 2 - code/modules/clothing/suits/wintercoats.dm | 1 - .../under/jobs/civilian/clown_mime.dm | 1 - .../clothing/under/jobs/engineering.dm | 1 - code/modules/explorer_drone/exodrone.dm | 2 +- .../mapfluff/ruins/lavaland_ruin_code.dm | 64 +- .../monster_organs/regenerative_core.dm | 2 - code/modules/mining/ores_coins.dm | 81 +- code/modules/mob/inventory.dm | 4 +- code/modules/mob/living/brain/brain_item.dm | 8 + .../mob/living/carbon/carbon_defense.dm | 4 +- .../mob/living/carbon/carbon_update_icons.dm | 35 + code/modules/mob/living/carbon/human/human.dm | 72 - .../living/carbon/human/human_update_icons.dm | 159 +- .../mob/living/carbon/human/species.dm | 44 +- .../carbon/human/species_types/abductors.dm | 1 + .../carbon/human/species_types/android.dm | 1 + .../carbon/human/species_types/golems.dm | 1366 +---------------- .../human/species_types/lizardpeople.dm | 2 +- .../carbon/human/species_types/plasmamen.dm | 1 + .../carbon/human/species_types/skeletons.dm | 1 + code/modules/mob/living/living_defense.dm | 7 + .../hostile/megafauna/colossus.dm | 13 +- .../mob_spawn/corpses/mining_corpses.dm | 11 +- .../mob_spawn/ghost_roles/golem_roles.dm | 74 +- code/modules/movespeed/modifiers/mobs.dm | 3 + .../movespeed/modifiers/status_effects.dm | 3 + code/modules/power/cell.dm | 10 +- code/modules/power/lighting/light.dm | 2 +- code/modules/power/lighting/light_items.dm | 5 + .../projectiles/guns/energy/special.dm | 4 +- .../chemistry/reagents/food_reagents.dm | 17 + .../chemistry/reagents/other_reagents.dm | 10 - .../xenobiology/crossbreeding/charged.dm | 2 +- .../xenobiology/crossbreeding/chilling.dm | 13 +- .../research/xenobiology/xenobiology.dm | 4 +- code/modules/surgery/bodyparts/_bodyparts.dm | 8 + .../surgery/bodyparts/dismemberment.dm | 7 +- code/modules/surgery/bodyparts/hair.dm | 2 +- code/modules/surgery/bodyparts/head.dm | 63 +- code/modules/surgery/bodyparts/parts.dm | 37 + .../bodyparts/species_parts/misc_bodyparts.dm | 401 ++--- .../surgery/bodyparts/worn_feature_offset.dm | 67 + code/modules/surgery/organs/appendix_golem.dm | 82 + code/modules/surgery/organs/ears.dm | 6 - code/modules/surgery/organs/eyes.dm | 33 +- .../surgery/organs/stomach/_stomach.dm | 2 +- .../surgery/organs/stomach/stomach_golem.dm | 98 ++ code/modules/surgery/organs/tongue.dm | 17 +- code/modules/surgery/organs/vocal_cords.dm | 70 +- .../screenshot_antag_icons_blobinfection.png | Bin 6287 -> 6291 bytes ...nshot_antag_icons_sentiencepotionspawn.png | Bin 2076 -> 2088 bytes ...eenshot_humanoids__datum_species_golem.png | Bin 1905 -> 1097 bytes ...anoids__datum_species_golem_adamantine.png | Bin 2146 -> 0 bytes ...t_humanoids__datum_species_golem_alloy.png | Bin 1402 -> 0 bytes ...umanoids__datum_species_golem_bananium.png | Bin 2146 -> 0 bytes ...manoids__datum_species_golem_bluespace.png | Bin 2146 -> 0 bytes ...ot_humanoids__datum_species_golem_bone.png | Bin 838 -> 0 bytes ..._humanoids__datum_species_golem_bronze.png | Bin 2146 -> 0 bytes ...manoids__datum_species_golem_cardboard.png | Bin 943 -> 0 bytes ...t_humanoids__datum_species_golem_cloth.png | Bin 837 -> 0 bytes ...humanoids__datum_species_golem_diamond.png | Bin 2146 -> 0 bytes ...anoids__datum_species_golem_durathread.png | Bin 929 -> 0 bytes ...t_humanoids__datum_species_golem_glass.png | Bin 4102 -> 0 bytes ...ot_humanoids__datum_species_golem_gold.png | Bin 2003 -> 0 bytes ...humanoids__datum_species_golem_leather.png | Bin 1872 -> 0 bytes ...manoids__datum_species_golem_mhydrogen.png | Bin 1954 -> 0 bytes ..._humanoids__datum_species_golem_plasma.png | Bin 2146 -> 0 bytes ...umanoids__datum_species_golem_plasteel.png | Bin 1952 -> 0 bytes ...humanoids__datum_species_golem_plastic.png | Bin 2139 -> 0 bytes ...oids__datum_species_golem_plastitanium.png | Bin 1803 -> 0 bytes ...t_humanoids__datum_species_golem_runic.png | Bin 889 -> 0 bytes ...ot_humanoids__datum_species_golem_sand.png | Bin 2146 -> 0 bytes ..._humanoids__datum_species_golem_silver.png | Bin 2040 -> 0 bytes ...ot_humanoids__datum_species_golem_snow.png | Bin 1882 -> 0 bytes ...umanoids__datum_species_golem_titanium.png | Bin 2139 -> 0 bytes ...humanoids__datum_species_golem_uranium.png | Bin 2146 -> 0 bytes ...ot_humanoids__datum_species_golem_wood.png | Bin 2003 -> 0 bytes ...nshot_humanoids__datum_species_teshari.png | Bin 1058 -> 1065 bytes icons/hud/screen_alert.dmi | Bin 133028 -> 134022 bytes icons/mob/inhands/golem_lefthand.dmi | Bin 0 -> 1482 bytes icons/mob/inhands/golem_righthand.dmi | Bin 0 -> 1527 bytes icons/mob/inhands/weapons/guns_righthand.dmi | Bin 71675 -> 67098 bytes icons/mob/species/golems.dmi | Bin 0 -> 19061 bytes icons/obj/wizard.dmi | Bin 16304 -> 16478 bytes .../modules/bodyparts/code/ghoul_bodyparts.dm | 38 + .../modules/bodyparts/code/parts.dm | 7 + .../bodyparts/code/teshari_bodyparts.dm | 34 + .../modules/clothing/masks/gasmask.dm | 2 - .../living/carbon/human/custom_bodytype.dm | 5 +- .../mob/living/carbon/human/species.dm | 24 +- .../mob/living/carbon/human/species/ghoul.dm | 16 - .../mob/living/carbon/human/worn_overlays.dm | 9 +- .../lewd_items/code/lewd_helpers/human.dm | 23 +- .../modules/salon/code/misc_items.dm | 3 + .../modules/teshari/code/_teshari.dm | 1 - .../modules/teshari/code/teshari_bodytype.dm | 18 +- tgstation.dme | 8 + .../tgui/interfaces/PersonalCrafting.tsx | 1 + .../PreferencesMenu/SpeciesPage.tsx | 2 + .../tgui/interfaces/PreferencesMenu/data.ts | 1 + 126 files changed, 1920 insertions(+), 2212 deletions(-) create mode 100644 code/datums/components/food/golem_food.dm create mode 100644 code/game/objects/items/stacks/golem_food/golem_food_buff.dm create mode 100644 code/game/objects/items/stacks/golem_food/golem_hand_actions.dm create mode 100644 code/game/objects/items/stacks/golem_food/golem_status_effects.dm create mode 100644 code/modules/surgery/bodyparts/worn_feature_offset.dm create mode 100644 code/modules/surgery/organs/appendix_golem.dm create mode 100644 code/modules/surgery/organs/stomach/stomach_golem.dm delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_adamantine.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_alloy.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_bananium.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_bluespace.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_bone.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_bronze.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_cardboard.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_cloth.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_diamond.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_durathread.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_glass.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_gold.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_leather.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_mhydrogen.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_plasma.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_plasteel.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_plastic.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_plastitanium.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_runic.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_sand.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_silver.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_snow.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_titanium.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_uranium.png delete mode 100644 code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_wood.png create mode 100644 icons/mob/inhands/golem_lefthand.dmi create mode 100644 icons/mob/inhands/golem_righthand.dmi create mode 100644 icons/mob/species/golems.dmi create mode 100644 modular_skyrat/modules/bodyparts/code/parts.dm diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index d2c2168827f..14246f7403b 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -39846,7 +39846,6 @@ "mNO" = ( /obj/structure/window/reinforced/spawner/directional/south, /obj/structure/window/reinforced/spawner/directional/west, -/obj/structure/cloth_pile, /obj/effect/turf_decal/tile/blue/opposingcorners{ dir = 1 }, diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 9c7a9f09e4b..c6634a15b47 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -101,6 +101,8 @@ #define NOAUGMENTS 17 ///will be assigned a universal vampire themed last name shared by their department. this is preferenced! #define BLOOD_CLANS 18 +/// Similar to NOEYESPRITES but only excludes the eyeless overlay +#define NOEYEHOLES 19 //organ slots #define ORGAN_SLOT_ADAMANTINE_RESONATOR "adamantine_resonator" @@ -198,31 +200,6 @@ GLOBAL_LIST_INIT(organ_process_order, list( //Defines for Golem Species IDs #define SPECIES_GOLEM "golem" -#define SPECIES_GOLEM_ADAMANTINE "a_golem" -#define SPECIES_GOLEM_PLASMA "p_golem" -#define SPECIES_GOLEM_DIAMOND "diamond_golem" -#define SPECIES_GOLEM_GOLD "gold_golem" -#define SPECIES_GOLEM_SILVER "silver_golem" -#define SPECIES_GOLEM_PLASTEEL "plasteel_golem" -#define SPECIES_GOLEM_TITANIUM "titanium_golem" -#define SPECIES_GOLEM_PLASTITANIUM "plastitanium_golem" -#define SPECIES_GOLEM_ALIEN "alloy_golem" -#define SPECIES_GOLEM_WOOD "wood_golem" -#define SPECIES_GOLEM_URANIUM "uranium_golem" -#define SPECIES_GOLEM_SAND "sand_golem" -#define SPECIES_GOLEM_GLASS "glass_golem" -#define SPECIES_GOLEM_BLUESPACE "bluespace_golem" -#define SPECIES_GOLEM_BANANIUM "ba_golem" -#define SPECIES_GOLEM_CULT "cultgolem" -#define SPECIES_GOLEM_CLOTH "clothgolem" -#define SPECIES_GOLEM_PLASTIC "plastic_golem" -#define SPECIES_GOLEM_BRONZE "bronze_golem" -#define SPECIES_GOLEM_CARDBOARD "c_golem" -#define SPECIES_GOLEM_LEATHER "leather_golem" -#define SPECIES_GOLEM_DURATHREAD "d_golem" -#define SPECIES_GOLEM_BONE "b_golem" -#define SPECIES_GOLEM_SNOW "sn_golem" -#define SPECIES_GOLEM_HYDROGEN "metallic_hydrogen_golem" // Defines for used in creating "perks" for the species preference pages. /// A key that designates UI icon displayed on the perk. @@ -239,3 +216,63 @@ GLOBAL_LIST_INIT(organ_process_order, list( #define SPECIES_POSITIVE_PERK "positive" #define SPECIES_NEGATIVE_PERK "negative" #define SPECIES_NEUTRAL_PERK "neutral" + +/// Golem food defines +#define GOLEM_FOOD_IRON "golem_food_iron" +#define GOLEM_FOOD_GLASS "golem_food_glass" +#define GOLEM_FOOD_URANIUM "golem_food_uranium" +#define GOLEM_FOOD_SILVER "golem_food_silver" +#define GOLEM_FOOD_PLASMA "golem_food_plasma" +#define GOLEM_FOOD_GOLD "golem_food_gold" +#define GOLEM_FOOD_DIAMOND "golem_food_diamond" +#define GOLEM_FOOD_TITANIUM "golem_food_titanium" +#define GOLEM_FOOD_PLASTEEL "golem_food_plasteel" +#define GOLEM_FOOD_BANANIUM "golem_food_bananium" +#define GOLEM_FOOD_BLUESPACE "golem_food_bluespace" +#define GOLEM_FOOD_GIBTONITE "golem_food_gibtonite" +#define GOLEM_FOOD_LIGHTBULB "golem_food_lightbulb" + +/// Golem food datum singletons +GLOBAL_LIST_INIT(golem_stack_food_types, list( + GOLEM_FOOD_IRON = new /datum/golem_food_buff/iron(), + GOLEM_FOOD_GLASS = new /datum/golem_food_buff/glass(), + GOLEM_FOOD_URANIUM = new /datum/golem_food_buff/uranium(), + GOLEM_FOOD_SILVER = new /datum/golem_food_buff/silver(), + GOLEM_FOOD_PLASMA = new /datum/golem_food_buff/plasma(), + GOLEM_FOOD_GOLD = new /datum/golem_food_buff/gold(), + GOLEM_FOOD_DIAMOND = new /datum/golem_food_buff/diamond(), + GOLEM_FOOD_TITANIUM = new /datum/golem_food_buff/titanium(), + GOLEM_FOOD_PLASTEEL = new /datum/golem_food_buff/plasteel(), + GOLEM_FOOD_BANANIUM = new /datum/golem_food_buff/bananium(), + GOLEM_FOOD_BLUESPACE = new /datum/golem_food_buff/bluespace(), + GOLEM_FOOD_GIBTONITE = new /datum/golem_food_buff/gibtonite(), + GOLEM_FOOD_LIGHTBULB = new /datum/golem_food_buff/lightbulb(), +)) + +/// Associated list of stack types to a golem food +GLOBAL_LIST_INIT(golem_stack_food_directory, list( + /obj/item/gibtonite = GLOB.golem_stack_food_types[GOLEM_FOOD_GIBTONITE], + /obj/item/light = GLOB.golem_stack_food_types[GOLEM_FOOD_LIGHTBULB], + /obj/item/stack/sheet/iron = GLOB.golem_stack_food_types[GOLEM_FOOD_IRON], + /obj/item/stack/ore/iron = GLOB.golem_stack_food_types[GOLEM_FOOD_IRON], + /obj/item/stack/sheet/glass = GLOB.golem_stack_food_types[GOLEM_FOOD_GLASS], + /obj/item/stack/sheet/mineral/uranium = GLOB.golem_stack_food_types[GOLEM_FOOD_URANIUM], + /obj/item/stack/ore/uranium = GLOB.golem_stack_food_types[GOLEM_FOOD_URANIUM], + /obj/item/stack/sheet/mineral/silver = GLOB.golem_stack_food_types[GOLEM_FOOD_SILVER], + /obj/item/stack/ore/silver = GLOB.golem_stack_food_types[GOLEM_FOOD_SILVER], + /obj/item/stack/sheet/mineral/plasma = GLOB.golem_stack_food_types[GOLEM_FOOD_PLASMA], + /obj/item/stack/ore/plasma = GLOB.golem_stack_food_types[GOLEM_FOOD_PLASMA], + /obj/item/stack/sheet/mineral/gold = GLOB.golem_stack_food_types[GOLEM_FOOD_GOLD], + /obj/item/stack/ore/gold = GLOB.golem_stack_food_types[GOLEM_FOOD_GOLD], + /obj/item/stack/sheet/mineral/diamond = GLOB.golem_stack_food_types[GOLEM_FOOD_DIAMOND], + /obj/item/stack/ore/diamond = GLOB.golem_stack_food_types[GOLEM_FOOD_DIAMOND], + /obj/item/stack/sheet/mineral/titanium = GLOB.golem_stack_food_types[GOLEM_FOOD_TITANIUM], + /obj/item/stack/ore/titanium = GLOB.golem_stack_food_types[GOLEM_FOOD_TITANIUM], + /obj/item/stack/sheet/plasteel = GLOB.golem_stack_food_types[GOLEM_FOOD_PLASTEEL], + /obj/item/stack/ore/bananium = GLOB.golem_stack_food_types[GOLEM_FOOD_BANANIUM], + /obj/item/stack/sheet/mineral/bananium = GLOB.golem_stack_food_types[GOLEM_FOOD_BANANIUM], + /obj/item/stack/ore/bluespace_crystal = GLOB.golem_stack_food_types[GOLEM_FOOD_BLUESPACE], + /obj/item/stack/ore/bluespace_crystal/refined = GLOB.golem_stack_food_types[GOLEM_FOOD_BLUESPACE], + /obj/item/stack/ore/bluespace_crystal/artificial = GLOB.golem_stack_food_types[GOLEM_FOOD_BLUESPACE], + /obj/item/stack/sheet/bluespace_crystal = GLOB.golem_stack_food_types[GOLEM_FOOD_BLUESPACE], +)) diff --git a/code/__DEFINES/atmospherics/atmos_mob_interaction.dm b/code/__DEFINES/atmospherics/atmos_mob_interaction.dm index 4144be832e2..0472bc96bfd 100644 --- a/code/__DEFINES/atmospherics/atmos_mob_interaction.dm +++ b/code/__DEFINES/atmospherics/atmos_mob_interaction.dm @@ -41,6 +41,11 @@ /// 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 +/// The maximum temperature of Lavaland +#define LAVALAND_MAX_TEMPERATURE 350 +/// The minimum temperature of Icebox +#define ICEBOX_MIN_TEMPERATURE 180 + /// 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. @@ -59,10 +64,14 @@ /// 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) +/// A temperature limit which is above the maximum lavaland temperature +#define BODYTEMP_HEAT_LAVALAND_SAFE (LAVALAND_MAX_TEMPERATURE + 5) /// 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) +/// A temperature limit which is above the minimum icebox temperature +#define BODYTEMP_COLD_ICEBOX_SAFE (ICEBOX_MIN_TEMPERATURE - 5) /// 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 diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 1c40654a177..ae5896f2a8b 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -121,6 +121,7 @@ #define COLOR_PALE_RED_GRAY "#D59998" #define COLOR_PALE_PURPLE_GRAY "#CBB1CA" #define COLOR_PURPLE_GRAY "#AE8CA8" +#define COLOR_GOLEM_GRAY "#8E8C81" //Color defines used by the assembly detailer. #define COLOR_ASSEMBLY_BLACK "#545454" @@ -176,6 +177,8 @@ * * Important note: colors can end up significantly different from the basic html picture, especially when saturated */ +/// Bright light used by default in tubes and bulbs +#define LIGHT_COLOR_DEFAULT "#f3fffa" /// Bright but quickly dissipating neon green. rgb(100, 200, 100) #define LIGHT_COLOR_GREEN "#64C864" /// Vivid, slightly blue green. rgb(60, 240, 70) diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm index 4ba6ef8f3a8..d5c6a188852 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm @@ -42,6 +42,8 @@ #define COMPONENT_ATOM_BLOCK_DIR_CHANGE (1<<0) ///from base of atom/setDir(): (old_dir, new_dir). Called before the direction changes. #define COMSIG_ATOM_DIR_CHANGE "atom_dir_change" +///from base of atom/setDir(): (old_dir, new_dir). Called after the direction changes. +#define COMSIG_ATOM_POST_DIR_CHANGE "atom_dir_change" /// from /datum/component/singularity/proc/can_move(), as well as /obj/energy_ball/proc/can_move() /// if a callback returns `SINGULARITY_TRY_MOVE_BLOCK`, then the singularity will not move to that turf #define COMSIG_ATOM_SINGULARITY_TRY_MOVE "atom_singularity_try_move" 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 b3237d22ebc..2abec797fc6 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -32,11 +32,16 @@ #define COMPONENT_NO_ATTACH (1<<0) ///from base of /obj/item/bodypart/proc/try_attach_limb(): (new_limb, special) #define COMSIG_CARBON_ATTACH_LIMB "carbon_attach_limb" +/// Called from bodypart being attached /obj/item/bodypart/proc/try_attach_limb(mob/living/carbon/new_owner, special) +#define COMSIG_BODYPART_ATTACHED "bodypart_removed" ///from base of /obj/item/bodypart/proc/try_attach_limb(): (new_limb, special) #define COMSIG_CARBON_POST_ATTACH_LIMB "carbon_post_attach_limb" #define COMSIG_BODYPART_GAUZED "bodypart_gauzed" // from /obj/item/bodypart/proc/apply_gauze(/obj/item/stack/gauze) #define COMSIG_BODYPART_GAUZE_DESTROYED "bodypart_degauzed" // from [/obj/item/bodypart/proc/seep_gauze] when it runs out of absorption +/// Called from bodypart changing owner, which could be on attach or detachment. Either argument can be null. (mob/living/carbon/new_owner, mob/living/carbon/old_owner) +#define COMSIG_BODYPART_CHANGED_OWNER "bodypart_changed_owner" + /// Called from update_health_hud, whenever a bodypart is being updated on the health doll #define COMSIG_BODYPART_UPDATING_HEALTH_HUD "bodypart_updating_health_hud" /// Return to override that bodypart's health hud with your own icon diff --git a/code/__DEFINES/food.dm b/code/__DEFINES/food.dm index b6ba97ef312..2448b34c935 100644 --- a/code/__DEFINES/food.dm +++ b/code/__DEFINES/food.dm @@ -18,7 +18,8 @@ #define ORANGES (1<<17) #define BUGS (1<<18) #define GORE (1<<19) -#define BLOODY (1<<20) // SKYRAT EDIT - Hemophage Food +#define STONE (1<<20) +#define BLOODY (1<<21) // SKYRAT EDIT - Hemophage Food DEFINE_BITFIELD(foodtypes, list( "MEAT" = MEAT, @@ -41,6 +42,7 @@ DEFINE_BITFIELD(foodtypes, list( "ORANGES" = ORANGES, "BUGS" = BUGS, "GORE" = GORE, + "STONE" = STONE, "BLOODY" = BLOODY, // SKYRAT EDIT - Hemophage Food )) @@ -66,6 +68,7 @@ DEFINE_BITFIELD(foodtypes, list( "ORANGES", \ "BUGS", \ "GORE", \ + "STONE", \ "BLOODY", /* SKYRAT EDIT - Hemophage Food */ \ ) @@ -91,6 +94,7 @@ DEFINE_BITFIELD(foodtypes, list( "Oranges", \ "Bugs", \ "Gore", \ + "Rocks", \ "Bloody", /* SKYRAT EDIT - Hemophage Food */ \ ) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index b72feb82ed5..cc0b51ff327 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -88,17 +88,22 @@ #define BODYTYPE_LARVA_PLACEHOLDER (1<<6) ///The limb is from a xenomorph. #define BODYTYPE_ALIEN (1<<7) +///The limb is from a golem +#define BODYTYPE_GOLEM (1<<8) // SKYRAT EDIT ADDITION ///The limb fits a modular custom shape -#define BODYTYPE_CUSTOM (1<<8) +#define BODYTYPE_CUSTOM (1<<9) ///The limb fits a taur body -#define BODYTYPE_TAUR (1<<9) +#define BODYTYPE_TAUR (1<<10) ///The limb causes shoes to no longer be displayed, useful for taurs. -#define BODYTYPE_HIDE_SHOES (1<<10) +#define BODYTYPE_HIDE_SHOES (1<<11) ///The limb causes glasses and hats to be drawn on layers 5 and 4 respectively. Currently used for snouts with the (Top) suffix, which are drawn on layer 6 and would normally cover facewear -#define BODYTYPE_ALT_FACEWEAR_LAYER (1<<11) +#define BODYTYPE_ALT_FACEWEAR_LAYER (1<<12) // SKYRAT EDIT END +#define BODYTYPE_BIOSCRAMBLE_COMPATIBLE (BODYTYPE_HUMANOID | BODYTYPE_MONKEY | BODYTYPE_ALIEN) +#define BODYTYPE_CAN_BE_BIOSCRAMBLED(bodytype) (!(bodytype & BODYTYPE_ROBOTIC) && (bodytype & BODYTYPE_BIOSCRAMBLE_COMPATIBLE)) + // Defines for Species IDs. Used to refer to the name of a species, for things like bodypart names or species preferences. #define SPECIES_ABDUCTOR "abductor" #define SPECIES_ANDROID "android" @@ -429,6 +434,7 @@ #define OFFSET_BACK "back" #define OFFSET_SUIT "suit" #define OFFSET_NECK "neck" +#define OFFSET_HELD "held" #define OFFSET_ACCESSORY "accessory" // Skyrat edit - addition //MINOR TWEAKS/MISC diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 89dd504b416..16f1f57fc26 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -159,6 +159,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_CLUMSY "clumsy" /// means that you can't use weapons with normal trigger guards. #define TRAIT_CHUNKYFINGERS "chunkyfingers" +/// Allows you to mine with your bare hands +#define TRAIT_FIST_MINING "fist_mining" #define TRAIT_DUMB "dumb" /// Whether a mob is dexterous enough to use machines and certain items or not. #define TRAIT_ADVANCEDTOOLUSER "advancedtooluser" @@ -218,6 +220,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_NOHUNGER "no_hunger" ///This carbon doesn't bleed #define TRAIT_NOBLOOD "noblood" +///This carbon doesn't show an overlay when they have no brain +#define TRAIT_NO_DEBRAIN_OVERLAY "no_debrain_overlay" #define TRAIT_NOMETABOLISM "no_metabolism" // Use when you want a mob to be able to metabolize plasma temporarily (e.g. plasma fixation disease symptom) #define TRAIT_PLASMA_LOVER_METABOLISM "plasma_lover_metabolism" @@ -428,6 +432,14 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai // and emit less heat. Present on /mob or /datum/mind #define TRAIT_SUPERMATTER_SOOTHER "supermatter_soother" +/// Trait which prevents you from becoming overweight +#define TRAIT_NOFAT "cant_get_fat" + +/// Trait which allows you to eat rocks +#define TRAIT_ROCK_EATER "rock_eater" +/// Trait which allows you to gain bonuses from consuming rocks +#define TRAIT_ROCK_METAMORPHIC "rock_metamorphic" + /// `do_teleport` will not allow this atom to teleport #define TRAIT_NO_TELEPORT "no-teleport" /// This atom is a secluded location, which is counted as out of bounds. diff --git a/code/_globalvars/phobias.dm b/code/_globalvars/phobias.dm index 98fc9514729..06a7299a685 100644 --- a/code/_globalvars/phobias.dm +++ b/code/_globalvars/phobias.dm @@ -511,7 +511,6 @@ GLOBAL_LIST_INIT(phobia_species, list( /datum/species/plasmaman, /datum/species/skeleton, )), - "the supernatural" = typecacheof(list(/datum/species/golem/runic)), )) /// Creates a regular expression to match against the given phobia diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index d40be5d92af..85a40fd0688 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -27,6 +27,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_BADDNA" = TRAIT_BADDNA, "TRAIT_CLUMSY" = TRAIT_CLUMSY, "TRAIT_CHUNKYFINGERS" = TRAIT_CHUNKYFINGERS, + "TRAIT_FIST_MINING" = TRAIT_FIST_MINING, "TRAIT_DUMB" = TRAIT_DUMB, "TRAIT_ADVANCEDTOOLUSER" = TRAIT_ADVANCEDTOOLUSER, "TRAIT_DISCOORDINATED_TOOL_USER" = TRAIT_DISCOORDINATED_TOOL_USER, diff --git a/code/datums/atmosphere/planetary.dm b/code/datums/atmosphere/planetary.dm index 044d29d9586..29db62369b9 100644 --- a/code/datums/atmosphere/planetary.dm +++ b/code/datums/atmosphere/planetary.dm @@ -23,7 +23,7 @@ maximum_pressure = LAVALAND_EQUIPMENT_EFFECT_PRESSURE - 1 minimum_temp = BODYTEMP_COLD_DAMAGE_LIMIT + 1 - maximum_temp = 350 + maximum_temp = LAVALAND_MAX_TEMPERATURE /datum/atmosphere/icemoon id = ICEMOON_DEFAULT_ATMOS @@ -47,6 +47,6 @@ 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 diff --git a/code/datums/bodypart_overlays/emote_bodypart_overlay.dm b/code/datums/bodypart_overlays/emote_bodypart_overlay.dm index a110be348bd..4143efb67db 100644 --- a/code/datums/bodypart_overlays/emote_bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/emote_bodypart_overlay.dm @@ -3,26 +3,22 @@ icon = 'icons/mob/species/human/emote_visuals.dmi' ///The body zone to attach the overlay to, overlay won't be added if no bodypart can be found with this var/attached_body_zone = BODY_ZONE_CHEST - ///The offset define to use with the overlay (none by default), should correspond with a list(0,0) in a species' offset_features - var/offset - ///X offset of the overlay image, stored here so we can access this even after bodypart we're on gets severed - var/offset_x = 0 - ///Y offset of the overlay image, stored here so we can access this even after bodypart we're on gets severed - var/offset_y = 0 + ///The feature key used to figure out what specific bodily feature we offset this to follow + var/offset_key + ///Datum giving us details about what offset to apply to the limb + var/datum/worn_feature_offset/feature_offset ///The bodypart that the overlay is currently applied to var/datum/weakref/attached_bodypart /datum/bodypart_overlay/simple/emote/get_image(layer, obj/item/bodypart/limb) var/image/image = ..() - image.pixel_x = offset_x - image.pixel_y = offset_y + feature_offset?.apply_offset(image) return image /datum/bodypart_overlay/simple/emote/added_to_limb(obj/item/bodypart/limb) attached_bodypart = WEAKREF(limb) - if(offset in limb.owner?.dna?.species.offset_features) - offset_x = limb.owner.dna.species.offset_features[offset][1] - offset_y = limb.owner.dna.species.offset_features[offset][2] + if (offset_key in limb.feature_offsets) + feature_offset = limb.feature_offsets[offset_key] /datum/bodypart_overlay/simple/emote/removed_from_limb(obj/item/bodypart/limb) attached_bodypart = null @@ -60,12 +56,12 @@ icon_state = "blush" draw_color = COLOR_BLUSH_PINK layers = EXTERNAL_ADJACENT - offset = OFFSET_FACE + offset_key = OFFSET_FACE attached_body_zone = BODY_ZONE_HEAD /datum/bodypart_overlay/simple/emote/cry icon_state = "tears" draw_color = COLOR_DARK_CYAN layers = EXTERNAL_ADJACENT - offset = OFFSET_FACE + offset_key = OFFSET_FACE attached_body_zone = BODY_ZONE_HEAD diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index 79fbcbba245..b89f7976cc5 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -30,7 +30,7 @@ Behavior that's still missing from this component that original food items had t var/list/eatverbs ///Callback to be ran for when you take a bite of something var/datum/callback/after_eat - ///Callback to be ran for when you take a bite of something + ///Callback to be ran for when you finish eating something var/datum/callback/on_consume ///Callback to be ran for when the code check if the food is liked, allowing for unique overrides for special foods like donuts with cops. var/datum/callback/check_liked @@ -524,6 +524,8 @@ Behavior that's still missing from this component that original food items had t SEND_SIGNAL(parent, COMSIG_FOOD_CONSUMED, eater, feeder) on_consume?.Invoke(eater, feeder) + if (QDELETED(parent)) // might be destroyed by the callback + return to_chat(feeder, span_warning("There is nothing left of [parent], oh no!")) if(isturf(parent)) diff --git a/code/datums/components/food/golem_food.dm b/code/datums/components/food/golem_food.dm new file mode 100644 index 00000000000..0f728caebdb --- /dev/null +++ b/code/datums/components/food/golem_food.dm @@ -0,0 +1,119 @@ +/// Component which allows something to be eaten by a golem +/datum/component/golem_food + /// Whether to destroy our item when we eat it + var/consume_on_eat + /// Reference to the kind of food we provide + var/datum/golem_food_buff/snack_type + /// Our abstract fake food item + var/obj/item/food/golem_food/golem_snack + /// Any extra checks which need to be done when seeing if this is edible + var/datum/callback/extra_validation + +/datum/component/golem_food/Initialize(consume_on_eat = TRUE, golem_food_key, datum/callback/extra_validation) + if (!isatom(parent)) + return COMPONENT_INCOMPATIBLE + if (!golem_food_key || !is_path_in_list(golem_food_key, GLOB.golem_stack_food_directory)) + CRASH("Golem food type not specified, this is a required parameter.") + + src.consume_on_eat = consume_on_eat + snack_type = GLOB.golem_stack_food_directory[golem_food_key] + src.extra_validation = extra_validation + + +/datum/component/golem_food/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(on_attack)) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine)) + +/datum/component/golem_food/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_ITEM_ATTACK, COMSIG_PARENT_EXAMINE)) + return ..() + +/datum/component/golem_food/Destroy(force, silent) + QDEL_NULL(golem_snack) + QDEL_NULL(extra_validation) + return ..() + +/// Attempt to feed this item to golem +/datum/component/golem_food/proc/on_attack(atom/source, mob/living/target, mob/living/user, click_parameters) + SIGNAL_HANDLER + if (user.combat_mode || !HAS_TRAIT(target, TRAIT_ROCK_EATER)) + return + if (extra_validation && !extra_validation.Invoke()) + source.balloon_alert(user, "not edible!") + return COMPONENT_CANCEL_ATTACK_CHAIN + if (!snack_type.can_consume(target)) + source.balloon_alert(user, "incompatible mineral!") + return COMPONENT_CANCEL_ATTACK_CHAIN + if (!golem_snack) + golem_snack = new( + /* loc = */ null, + /* name = */ source.name, + /* consume_food = */ consume_on_eat, + /* food_buff = */ snack_type, + /* owner = */ parent, + ) + RegisterSignal(golem_snack, COMSIG_PARENT_QDELETING, PROC_REF(on_food_destroyed)) + golem_snack.attack(target, user, click_parameters) + return COMPONENT_CANCEL_ATTACK_CHAIN + +/// Reference handling for abstract food object +/datum/component/golem_food/proc/on_food_destroyed() + SIGNAL_HANDLER + golem_snack = null + +/// Add extra examine text to people who have golem brains +/datum/component/golem_food/proc/on_examine(datum/source, mob/user, list/examine_text) + SIGNAL_HANDLER + if(!HAS_TRAIT(user, TRAIT_ROCK_METAMORPHIC)) + return + examine_text += span_notice(snack_type.added_info) + +/// Abstract food item used to feed golems +/obj/item/food/golem_food + name = "temporary golem material snack item" + desc = "You shouldn't be able to see this. This is an abstract item which exists to allow you to eat rocks." + bite_consumption = 2 + food_reagents = list(/datum/reagent/consumable/nutriment/mineral = INFINITY) // Destroyed when stack runs out, not when reagents do + foodtypes = STONE + /// If we use up a stack of food on use or not + var/consume_food = TRUE + /// A reference to whatever it is we represent + var/atom/owner + /// Golem food buff to apply on consumption + var/datum/golem_food_buff/food_buff + +/obj/item/food/golem_food/Initialize(mapload, name, consume_food, datum/golem_food_buff/food_buff, atom/owner) + . = ..() + src.name = name + src.consume_food = consume_food + src.food_buff = food_buff + src.owner = owner + + RegisterSignal(owner, COMSIG_PARENT_QDELETING, PROC_REF(on_parent_destroyed)) + +/// Clean ourselves up if our parent dies +/obj/item/food/golem_food/proc/on_parent_destroyed(datum/destroyed_thing) + SIGNAL_HANDLER + qdel(src) + +/obj/item/food/golem_food/make_edible() + . = ..() + AddComponent(/datum/component/edible, after_eat = CALLBACK(src, PROC_REF(took_bite)), volume = INFINITY) + +/// Called when someone bites this food, subtract one charge from our material stack +/obj/item/food/golem_food/proc/took_bite(mob/eater) + if (!owner) + qdel(src) + return + + food_buff.on_consumption(eater, owner) + if (!consume_food) + qdel(src) + return + + if (isstack(owner)) + var/obj/item/stack/stack_owner = owner + stack_owner.use(used = 1) + else + qdel(owner) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index aff22c908f8..79367824e58 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -374,7 +374,7 @@ /atom/proc/handle_ricochet(obj/projectile/ricocheting_projectile) var/turf/p_turf = get_turf(ricocheting_projectile) - var/face_direction = get_dir(src, p_turf) + var/face_direction = get_dir(src, p_turf) || get_dir(src, ricocheting_projectile) var/face_angle = dir2angle(face_direction) var/incidence_s = GET_ANGLE_OF_INCIDENCE(face_angle, (ricocheting_projectile.Angle + 180)) var/a_incidence_s = abs(incidence_s) @@ -1169,6 +1169,7 @@ return SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir) dir = newdir + SEND_SIGNAL(src, COMSIG_ATOM_POST_DIR_CHANGE, dir, newdir) /** * Called when the atom log's in or out diff --git a/code/game/objects/items/stacks/golem_food/golem_food_buff.dm b/code/game/objects/items/stacks/golem_food/golem_food_buff.dm new file mode 100644 index 00000000000..09c1a335ef1 --- /dev/null +++ b/code/game/objects/items/stacks/golem_food/golem_food_buff.dm @@ -0,0 +1,117 @@ +/// An effect you gain from eating minerals +/datum/golem_food_buff + /// If we can apply this while you already have a different status effect + var/exclusive = TRUE + /// Nutrition to grant per stack consumed + var/nutrition = 2 + /// Typepath of status effect to apply + var/status_effect + /// Extra information to display when a valid food is examined + var/added_info = "" + +/// Returns true if the passed mob can currently gain this buff +/datum/golem_food_buff/proc/can_consume(mob/living/consumer) + if (!exclusive) + return TRUE + var/datum/status_effect/golem/existing = consumer.has_status_effect(/datum/status_effect/golem) + return !existing || istype(existing, status_effect) + +/// Called when someone actually eats this +/datum/golem_food_buff/proc/on_consumption(mob/living/carbon/consumer, atom/movable/consumed) + if (!HAS_TRAIT(consumer, TRAIT_ROCK_METAMORPHIC)) + return + apply_effects(consumer, consumed) + +/// Apply our desired effects to the eater +/datum/golem_food_buff/proc/apply_effects(mob/living/carbon/consumer, atom/movable/consumed) + if (status_effect) + consumer.apply_status_effect(status_effect) + +/// Can eat at any time, but isn't very nutritious +/datum/golem_food_buff/glass + exclusive = FALSE + nutrition = 0.5 + added_info = "This mineral can be consumed at any time, but it's mostly empty calories." + +/// More filling, and heals you +/datum/golem_food_buff/iron + nutrition = 3 + added_info = "This mineral is filling and even heals you a little." + /// Amount by which you heal from eating some iron + var/healed_amount = 3 + /// Order in which to heal damage types + var/list/damage_heal_order = list(BRUTE, BURN, TOX, OXY) + +/datum/golem_food_buff/iron/apply_effects(mob/living/carbon/consumer, atom/movable/consumed) + if (consumer.health == consumer.maxHealth) + return + consumer.heal_ordered_damage(healed_amount, damage_heal_order) + new /obj/effect/temp_visual/heal(get_turf(consumer), COLOR_HEALING_CYAN) + +/datum/golem_food_buff/uranium + status_effect = /datum/status_effect/golem/uranium + added_info = "If consumed this mineral will power you in place of food, pausing your digestion for five minutes." + +/datum/golem_food_buff/silver + status_effect = /datum/status_effect/golem/silver + added_info = "If consumed this mineral will repel the supernatural, affording you resistance to mystical effects." + +/datum/golem_food_buff/plasma + status_effect = /datum/status_effect/golem/plasma + added_info = "If consumed this mineral will allow you to absorb heat and convert it into power." + +/datum/golem_food_buff/plasteel + status_effect = /datum/status_effect/golem/plasteel + added_info = "If consumed this mineral will harden you against the hazards of space." + +/datum/golem_food_buff/gold + status_effect = /datum/status_effect/golem/gold + added_info = "If consumed this mineral will grant you a shiny coating which reflects projectiles." + +/datum/golem_food_buff/diamond + status_effect = /datum/status_effect/golem/diamond + added_info = "If consumed this mineral will reflact light around you, making you faster and harder to see." + +/datum/golem_food_buff/titanium + status_effect = /datum/status_effect/golem/titanium + added_info = "If consumed this mineral will make you tougher and punch harder." + +/datum/golem_food_buff/bananium + status_effect = /datum/status_effect/golem/bananium + added_info = "If consumed this mineral will make you funnier." + +/datum/golem_food_buff/lightbulb + nutrition = 0 + exclusive = FALSE + status_effect = /datum/status_effect/golem_lightbulb + added_info = "Not nutritious, but gives you a healthy glow if eaten." + +/datum/golem_food_buff/gibtonite + exclusive = FALSE + added_info = "After consumption, you can launch this mineral like a rocket. It's a little hard to keep down." + +/datum/golem_food_buff/gibtonite/apply_effects(mob/living/carbon/human/consumer, atom/movable/consumed) + var/obj/item/gibtonite_hand/new_hand = new(null, /* held_gibtonite = */ consumed) + + if(consumer.put_in_hands(new_hand)) + return + consumer.drop_all_held_items() + if(consumer.put_in_hands(new_hand)) + return + + consumed.forceMove(get_turf(consumer)) + new_hand.held_gibtonite = null + qdel(new_hand) + consumer.visible_message(span_warning("[consumer] can't keep [consumed] down, and coughs it onto the ground!")) + +/datum/golem_food_buff/bluespace + exclusive = FALSE + added_info = "After consumption, you can use the stored power to teleport yourself." + +/datum/golem_food_buff/bluespace/apply_effects(mob/living/carbon/human/consumer, obj/item/stack/consumed) + var/obj/item/bluespace_finger/new_hand = new + if (consumed.amount == 1) + consumer.dropItemToGround(consumed) + if (consumer.put_in_hands(new_hand, del_on_fail = TRUE)) + return + consumer.balloon_alert(consumer, "no free hands!") diff --git a/code/game/objects/items/stacks/golem_food/golem_hand_actions.dm b/code/game/objects/items/stacks/golem_food/golem_hand_actions.dm new file mode 100644 index 00000000000..97165b18355 --- /dev/null +++ b/code/game/objects/items/stacks/golem_food/golem_hand_actions.dm @@ -0,0 +1,106 @@ +/// How long can you hold onto gibtonite before you need to let it go? +#define GIBTONITE_GOLEM_HOLD_TIME 2 MINUTES +/// ID for a filter we apply so we can remove it again +#define BLUESPACE_GLOW_FILTER "bluespace_glow_filter" + +/// Lets you hold a gibtonite ore in one hand and shoot it like a gun +/obj/item/gibtonite_hand + name = "stabilised gibtonite fist" + desc = "You had better launch this at something before it comes out the other end of your body." + icon = 'icons/obj/ore.dmi' + icon_state = "Gibtonite ore" + lefthand_file = 'icons/mob/inhands/golem_lefthand.dmi' + righthand_file = 'icons/mob/inhands/golem_righthand.dmi' + inhand_icon_state = "gibtonite_hand" + item_flags = ABSTRACT + w_class = WEIGHT_CLASS_HUGE + /// The bomb we're going to throw + var/obj/item/gibtonite/held_gibtonite + +/obj/item/gibtonite_hand/Initialize(mapload, obj/item/gibtonite/held_gibtonite) + . = ..() + if (!held_gibtonite) + return INITIALIZE_HINT_QDEL + ADD_TRAIT(src, TRAIT_NODROP, HAND_REPLACEMENT_TRAIT) + src.held_gibtonite = held_gibtonite + held_gibtonite.forceMove(src) + addtimer(CALLBACK(src, PROC_REF(release_gibtonite)), GIBTONITE_GOLEM_HOLD_TIME, TIMER_DELETE_ME) + +/obj/item/gibtonite_hand/afterattack(atom/target, mob/living/user, flag, params) + . = ..() + if (!held_gibtonite) + to_chat(user, span_warning("[src] fizzles, it was a dud!")) + qdel(src) + return TRUE | AFTERATTACK_PROCESSED_ITEM + playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, TRUE) + held_gibtonite.forceMove(get_turf(src)) + held_gibtonite.det_time = 2 SECONDS + held_gibtonite.GibtoniteReaction(user) + held_gibtonite.throw_at(target, range = 10, speed = 3, thrower = user) + held_gibtonite = null + qdel(src) + return TRUE | AFTERATTACK_PROCESSED_ITEM + +/// Called when you can't hold it in any longer and just drop it on the ground +/obj/item/gibtonite_hand/proc/release_gibtonite() + held_gibtonite.forceMove(get_turf(src)) + held_gibtonite.GibtoniteReaction(isliving(loc) ? loc : null) + held_gibtonite = null + qdel(src) + +/obj/item/gibtonite_hand/Destroy() + QDEL_NULL(held_gibtonite) + return ..() + +/// Point at a target and teleport somewhere vaguely close to it +/obj/item/bluespace_finger + name = "bluespace knot" + desc = "Firmly grasp reality and pull yourself to a nearby location." + icon = 'icons/obj/weapons/guns/projectiles.dmi' + icon_state = "bluespace" + lefthand_file = 'icons/mob/inhands/golem_lefthand.dmi' + righthand_file = 'icons/mob/inhands/golem_righthand.dmi' + inhand_icon_state = "bluespace_hand" + item_flags = ABSTRACT | DROPDEL + /// How far away can you point? + var/teleport_range = 7 + /// How long does it take to teleport? + var/teleport_time = 3 SECONDS + /// How accurate are you? + var/teleport_vary = 2 + +/obj/item/bluespace_finger/afterattack(atom/target, mob/living/user, flag, params) + . = ..() + var/turf/target_turf = get_turf(target) + if (get_dist(target_turf, get_turf(src)) > teleport_range) + balloon_alert(user, "too far!") + return TRUE | AFTERATTACK_PROCESSED_ITEM + if (target_turf.is_blocked_turf(exclude_mobs = TRUE)) + balloon_alert(user, "no room!") + return TRUE | AFTERATTACK_PROCESSED_ITEM + + var/obj/effect/temp_visual/teleport_golem/landing_indicator = new(target_turf) + user.add_filter(BLUESPACE_GLOW_FILTER, 2, list("type" = "outline", "color" = COLOR_BRIGHT_BLUE, "alpha" = 0, "size" = 1)) + var/filter = user.get_filter(BLUESPACE_GLOW_FILTER) + animate(filter, alpha = 200, time = 0.5 SECONDS, loop = -1) + animate(alpha = 0, time = 0.5 SECONDS) + + var/did_teleport = do_after(user, delay = teleport_time, target = src, interaction_key = REF(src)) + qdel(landing_indicator) + user.remove_filter(BLUESPACE_GLOW_FILTER) + if (!did_teleport) + return + + var/list/valid_landing_tiles = list(target_turf) + for (var/turf/potential_landing in oview(teleport_vary, target_turf)) + if (potential_landing.is_blocked_turf(exclude_mobs = TRUE)) + continue + valid_landing_tiles += potential_landing + var/turf/final_destination = pick(valid_landing_tiles) + for (var/mob/living/telefrag in final_destination) + telefrag.Knockdown(2 SECONDS) + do_teleport(user, final_destination, asoundin = 'sound/effects/phasein.ogg', no_effects = TRUE) + qdel(src) + +#undef GIBTONITE_GOLEM_HOLD_TIME +#undef BLUESPACE_GLOW_FILTER diff --git a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm new file mode 100644 index 00000000000..03c7af2dc12 --- /dev/null +++ b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm @@ -0,0 +1,446 @@ +/// Abstract holder for golem status effects, you should never have more than one of these active +/datum/status_effect/golem + id = "golem_status" + duration = 5 MINUTES + alert_type = /atom/movable/screen/alert/status_effect/golem_status + /// Icon state prefix for overlay to display on golem limbs + var/overlay_state_prefix + /// Name of the mineral we ate to get this + var/mineral_name = "" + /// Text to display on buff application + var/applied_fluff = "" + /// Overlays we have applied to our mob + var/list/active_overlays = list() + /// Icon used to represent the alert + var/alert_icon = 'icons/obj/stack_objects.dmi' + /// Icon state to display to represent the alert + var/alert_icon_state = "sheet-monkey" + /// Tooltip to display when hovering over the alert + var/alert_desc = "Something went wrong and this tooltip is not displaying correctly." + +/atom/movable/screen/alert/status_effect/golem_status + name = "Metamorphic %SOMETHING%" + desc = "You've enjoyed a tasty meal and are now experiencing a bug." + icon_state = "template" + /// Overlay we show on top of the template icon + var/mutable_appearance/mineral_overlay + /// When we reach this much remaining time we will start animating as a warning + var/early_expiry_warning = 30 SECONDS + /// When we reach this much remaining time we will start animating more urgently as a warning + var/imminent_expiry_warning = 5 SECONDS + +/// Set up how the alert ACTUALLY looks, based on the effect applied +/atom/movable/screen/alert/status_effect/golem_status/proc/update_details(buff_time) + var/datum/status_effect/golem/golem_effect = attached_effect + if (!istype(golem_effect)) + CRASH("Golem status alert attached to invalid status effect.") + name = replacetext(name, "%SOMETHING%", golem_effect.mineral_name) + desc = golem_effect.alert_desc + mineral_overlay = mutable_appearance(golem_effect.alert_icon, golem_effect.alert_icon_state) + update_appearance(UPDATE_ICON) + + if (buff_time > early_expiry_warning) + addtimer(CALLBACK(src, PROC_REF(early_warning)), buff_time - early_expiry_warning, TIMER_DELETE_ME) + if (buff_time > imminent_expiry_warning) + addtimer(CALLBACK(src, PROC_REF(imminent_warning)), buff_time - imminent_expiry_warning, TIMER_DELETE_ME) + +/// Animate to indicate effect is expiring soon +/atom/movable/screen/alert/status_effect/golem_status/proc/early_warning() + animate(src, alpha = 75, time = 1 SECONDS, loop = -1) + animate(alpha = 255, time = 1 SECONDS, loop = -1) + +/// Animate to indicate effect is expiring very soon +/atom/movable/screen/alert/status_effect/golem_status/proc/imminent_warning() + animate(src, alpha = 25, time = 0.5 SECONDS, loop = -1) + animate(alpha = 200, time = 0.5 SECONDS, loop = -1) + +/atom/movable/screen/alert/status_effect/golem_status/update_overlays() + . = ..() + . += mineral_overlay + +/atom/movable/screen/alert/status_effect/golem_status/Destroy() + QDEL_NULL(mineral_overlay) + return ..() + +/datum/status_effect/golem/on_apply() + . = ..() + if (!ishuman(owner)) + return FALSE + if (owner.has_status_effect(/datum/status_effect/golem)) + return FALSE + if (applied_fluff) + to_chat(owner, span_notice(applied_fluff)) + if (!overlay_state_prefix || !iscarbon(owner)) + return TRUE + var/mob/living/carbon/golem_owner = owner + for (var/obj/item/bodypart/part in golem_owner.bodyparts) + if (part.limb_id != SPECIES_GOLEM) + continue + var/datum/bodypart_overlay/simple/golem_overlay/overlay = new() + overlay.add_to_bodypart(overlay_state_prefix, part) + active_overlays += overlay + golem_owner.update_body_parts() + return TRUE + +/datum/status_effect/golem/on_creation(mob/living/new_owner) + . = ..() + if (!.) + return FALSE + var/atom/movable/screen/alert/status_effect/golem_status/status_alert = linked_alert + status_alert?.update_details(buff_time = initial(duration)) + +/datum/status_effect/golem/on_remove() + to_chat(owner, span_warning("The effect of the [mineral_name] fades.")) + QDEL_LIST(active_overlays) + return ..() + +/datum/status_effect/golem/get_examine_text() + return span_notice("[owner.p_their(capitalized = TRUE)] body has been augmented with veins of [mineral_name].") + +/// Body part overlays applied by golem status effects +/datum/bodypart_overlay/simple/golem_overlay + icon = 'icons/mob/species/golems.dmi' + layers = ALL_EXTERNAL_OVERLAYS + ///The bodypart that the overlay is currently applied to + var/datum/weakref/attached_bodypart + +/datum/bodypart_overlay/simple/golem_overlay/proc/add_to_bodypart(prefix, obj/item/bodypart/part) + icon_state = "[prefix]_[part.body_zone]" + attached_bodypart = WEAKREF(part) + part.add_bodypart_overlay(src) + +/datum/bodypart_overlay/simple/golem_overlay/Destroy(force) + var/obj/item/bodypart/referenced_bodypart = attached_bodypart.resolve() + if(!referenced_bodypart) + return ..() + referenced_bodypart.remove_bodypart_overlay(src) + if(referenced_bodypart.owner) //Keep in mind that the bodypart could have been severed from the owner by now + referenced_bodypart.owner.update_body_parts() + else + referenced_bodypart.update_icon_dropped() + return ..() + +/// Freezes hunger for the duration +/datum/status_effect/golem/uranium + overlay_state_prefix = "uranium" + mineral_name = "uranium" + applied_fluff = "Glowing crystals sprout from your body. You feel energised!" + alert_icon_state = "sheet-uranium" + alert_desc = "Internal radiation is providing all of your nutritional needs." + +/datum/status_effect/golem/uranium/on_apply() + . = ..() + if (!.) + return FALSE + ADD_TRAIT(owner, TRAIT_NOHUNGER, TRAIT_STATUS_EFFECT(id)) + owner.remove_movespeed_modifier(/datum/movespeed_modifier/golem_hunger) + owner.remove_status_effect(/datum/status_effect/golem_statued) // Instant fix! + return TRUE + +/datum/status_effect/golem/uranium/on_remove() + REMOVE_TRAIT(owner, TRAIT_NOHUNGER, TRAIT_STATUS_EFFECT(id)) + return ..() + +/// Magic immunity +/datum/status_effect/golem/silver + overlay_state_prefix = "silver" + mineral_name = "silver" + applied_fluff = "Shining plates grace your shoulders. You feel holy!" + alert_icon_state = "sheet-silver" + alert_desc = "Your body repels supernatural influences." + +/datum/status_effect/golem/silver/on_apply() + . = ..() + if (!.) + return FALSE + owner.add_traits(list(TRAIT_ANTIMAGIC, TRAIT_HOLY), TRAIT_STATUS_EFFECT(id)) + return TRUE + +/datum/status_effect/golem/silver/on_remove() + owner.remove_traits(list(TRAIT_ANTIMAGIC, TRAIT_HOLY), TRAIT_STATUS_EFFECT(id)) + return ..() + +/// Heat immunity, turns heat damage into local power +/datum/status_effect/golem/plasma + overlay_state_prefix = "plasma" + mineral_name = "plasma" + applied_fluff = "Plasma cooling rods sprout from your body. You can take the heat!" + alert_icon_state = "sheet-plasma" + alert_desc = "You are protected from high pressure and can convert heat damage into power." + /// What do we multiply our damage by to convert it into power? + var/power_multiplier = 5 + /// Multiplier to apply to burn damage, not 0 so that we can reverse it more easily + var/burn_multiplier = 0.05 + +/datum/status_effect/golem/plasma/on_apply() + . = ..() + if (!.) + return FALSE + owner.add_traits(list(TRAIT_RESISTHIGHPRESSURE, TRAIT_RESISTHEAT), TRAIT_STATUS_EFFECT(id)) + RegisterSignal(owner, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(on_burned)) + var/mob/living/carbon/human/human_owner = owner + human_owner.physiology.burn_mod *= burn_multiplier + return TRUE + +/datum/status_effect/golem/plasma/on_remove() + owner.remove_traits(list(TRAIT_RESISTHIGHPRESSURE, TRAIT_RESISTHEAT), TRAIT_STATUS_EFFECT(id)) + UnregisterSignal(owner, COMSIG_MOB_APPLY_DAMAGE) + var/mob/living/carbon/human/human_owner = owner + human_owner.physiology.burn_mod /= burn_multiplier + return ..() + +/// When we take fire damage (or... technically also cold damage, we don't differentiate), zap a nearby APC +/datum/status_effect/golem/plasma/proc/on_burned(datum/source, damage, damagetype) + SIGNAL_HANDLER + if(damagetype != BURN) + return + + var/power = damage * power_multiplier + var/obj/machinery/power/energy_accumulator/ground = get_closest_atom(/obj/machinery/power/energy_accumulator, view(4, owner), owner) + if (ground) + zap_effect(ground) + ground.zap_act(damage, ZAP_GENERATES_POWER) + return + var/area/our_area = get_area(owner) + var/obj/machinery/power/apc/our_apc = our_area.apc + if (!our_apc) + return + zap_effect(our_apc) + our_apc.cell?.give(power) + +/// Shoot a beam at the target atom +/datum/status_effect/golem/plasma/proc/zap_effect(atom/target) + owner.Beam(target, icon_state = "lightning[rand(1,12)]", time = 0.5 SECONDS) + playsound(owner, 'sound/magic/lightningshock.ogg', vol = 50, vary = TRUE) + +/// Makes you spaceproof +/datum/status_effect/golem/plasteel + overlay_state_prefix = "iron" + mineral_name = "plasteel" + applied_fluff = "Plasteel plates seal you tight. You feel insulated!" + alert_icon_state = "sheet-plasteel" + alert_desc = "You are sealed against the cold, and against low pressure environments." + +/datum/status_effect/golem/plasteel/on_apply() + . = ..() + if (!.) + return FALSE + owner.add_traits(list(TRAIT_RESISTLOWPRESSURE, TRAIT_RESISTCOLD), TRAIT_STATUS_EFFECT(id)) + return TRUE + +/datum/status_effect/golem/plasteel/on_remove() + owner.remove_traits(list(TRAIT_RESISTLOWPRESSURE, TRAIT_RESISTCOLD), TRAIT_STATUS_EFFECT(id)) + return ..() + +/// Makes you reflect energy projectiles +/datum/status_effect/golem/gold + overlay_state_prefix = "gold" + mineral_name = "gold" + applied_fluff = "Shining plates form across your body. You feel reflective!" + alert_icon_state = "sheet-gold_2" + alert_desc = "Your shining body reflects energy weapons." + +/datum/status_effect/golem/gold/on_apply() + . = ..() + if (!.) + return FALSE + owner.flags_ricochet |= RICOCHET_SHINY + return TRUE + +/datum/status_effect/golem/gold/on_remove() + owner.flags_ricochet &= ~RICOCHET_SHINY + return ..() + +/// Makes you hard to see +/datum/status_effect/golem/diamond + overlay_state_prefix = "diamond" + mineral_name = "diamonds" + applied_fluff = "Sparkling gems bend light around you. You feel stealthy!" + tick_interval = 0.25 SECONDS + alert_icon_state = "sheet-diamond" + alert_desc = "Light is bending around you, making you hard to see while still and faster while moving." + /// Alpha to remove per second while stood still + var/alpha_per_tick = 25 + /// Alpha to apply while moving + var/moving_alpha = 150 + /// List of arms we have updated + var/list/modified_arms + +/datum/status_effect/golem/diamond/on_apply() + . = ..() + if (!.) + return FALSE + RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) + owner.alpha = moving_alpha + owner.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/light_speed) + + var/mob/living/carbon/carbon_owner = owner + for (var/obj/item/bodypart/arm/arm in carbon_owner.bodyparts) + if (arm.limb_id != SPECIES_GOLEM) + continue + set_arm_fluff(arm) + return TRUE + +/datum/status_effect/golem/diamond/tick(delta_time, times_fired) + owner.alpha = max(owner.alpha - alpha_per_tick, 0) + +/// Reset alpha to starting value +/datum/status_effect/golem/diamond/proc/on_move() + SIGNAL_HANDLER + owner.alpha = moving_alpha + +/// Make our arm do slashing effects +/datum/status_effect/golem/diamond/proc/set_arm_fluff(obj/item/bodypart/arm/arm) + arm.unarmed_attack_verb = "slash" + arm.unarmed_attack_effect = ATTACK_EFFECT_CLAW + arm.unarmed_attack_sound = 'sound/weapons/slash.ogg' + arm.unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + RegisterSignal(arm, COMSIG_PARENT_QDELETING, PROC_REF(on_arm_destroyed)) + LAZYADD(modified_arms, arm) + +/datum/status_effect/golem/diamond/on_remove() + owner.alpha = initial(owner.alpha) + owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/light_speed) + UnregisterSignal(owner, COMSIG_MOVABLE_MOVED) + for (var/obj/item/bodypart/arm/arm as anything in modified_arms) + reset_arm_fluff(arm) + LAZYCLEARLIST(modified_arms) + return ..() + +/// Make our arm do whatever it originally did +/datum/status_effect/golem/diamond/proc/reset_arm_fluff(obj/item/bodypart/arm/arm) + if (!arm) + return + arm.unarmed_attack_verb = initial(arm.unarmed_attack_verb) + arm.unarmed_attack_effect = initial(arm.unarmed_attack_effect) + arm.unarmed_attack_sound = initial(arm.unarmed_attack_sound) + arm.unarmed_miss_sound = initial(arm.unarmed_miss_sound) + UnregisterSignal(arm, COMSIG_PARENT_QDELETING) + +/// Remove references to deleted arms +/datum/status_effect/golem/diamond/proc/on_arm_destroyed(obj/item/bodypart/arm/arm) + SIGNAL_HANDLER + modified_arms -= arm + +/// Makes you tougher +/datum/status_effect/golem/titanium + overlay_state_prefix = "platinum" + mineral_name = "titanium" + applied_fluff = "Titanium rings burst from your arms. You feel ready to take on the world!" + alert_icon_state = "sheet-titanium" + alert_desc = "You are more resistant to physical blows, and pack more of a punch yourself." + /// Amount to reduce brute damage by + var/brute_modifier = 0.7 + /// How much extra damage do we do with our fists? + var/damage_increase = 3 + /// Deal this much extra damage to mining mobs, most of which take 0 unarmed damage usually + var/mining_bonus = 30 + /// List of arms we have updated + var/list/modified_arms + +/datum/status_effect/golem/titanium/on_apply() + . = ..() + if (!.) + return FALSE + var/mob/living/carbon/human/human_owner = owner + RegisterSignal(human_owner, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, PROC_REF(on_punched)) + human_owner.physiology.brute_mod *= brute_modifier + for (var/obj/item/bodypart/arm/arm in human_owner.bodyparts) + if (arm.limb_id != SPECIES_GOLEM) + continue + buff_arm(arm) + +/// Give mining mobs an extra slap +/datum/status_effect/golem/titanium/proc/on_punched(mob/living/puncher, atom/punchee, proximity) + SIGNAL_HANDLER + if (!proximity || !isliving(punchee)) + return + var/mob/living/victim = punchee + if (victim.body_position == LYING_DOWN || (!(FACTION_MINING in victim.faction) && !(FACTION_BOSS in victim.faction))) + return + victim.apply_damage(mining_bonus, BRUTE) + +/// Make the targeted arm big and strong +/datum/status_effect/golem/titanium/proc/buff_arm(obj/item/bodypart/arm/arm) + arm.unarmed_damage_low += damage_increase + arm.unarmed_damage_high += damage_increase + arm.unarmed_stun_threshold += damage_increase // We don't want to make knockdown more likely + RegisterSignal(arm, COMSIG_PARENT_QDELETING, PROC_REF(on_arm_destroyed)) + LAZYADD(modified_arms, arm) + +/datum/status_effect/golem/titanium/on_remove() + var/mob/living/carbon/human/human_owner = owner + UnregisterSignal(human_owner, COMSIG_HUMAN_MELEE_UNARMED_ATTACK) + human_owner.physiology.brute_mod /= brute_modifier + for (var/obj/item/bodypart/arm/arm as anything in modified_arms) + debuff_arm(arm) + LAZYCLEARLIST(modified_arms) + return ..() + +/// Make the targeted arm small and weak +/datum/status_effect/golem/titanium/proc/debuff_arm(obj/item/bodypart/arm/arm) + if (!arm) + return + arm.unarmed_damage_low -= damage_increase + arm.unarmed_damage_high -= damage_increase + arm.unarmed_stun_threshold -= damage_increase + UnregisterSignal(arm, COMSIG_PARENT_QDELETING) + +/// Remove references to deleted arms +/datum/status_effect/golem/titanium/proc/on_arm_destroyed(obj/item/bodypart/arm/arm) + SIGNAL_HANDLER + modified_arms -= arm + +/// Makes you slippery +/datum/status_effect/golem/bananium + overlay_state_prefix = "banana" + mineral_name = "bananium" + applied_fluff = "Bananium veins ooze from your crags. You feel a little funny!" + alert_icon_state = "sheet-bananium" + alert_desc = "You feel kind of funny." + /// The slipperiness component which we have applied + var/datum/component/slippery/slipperiness + +/datum/status_effect/golem/bananium/on_apply() + . = ..() + if (!.) + return + owner.AddElement(/datum/element/waddling) + ADD_TRAIT(owner, TRAIT_NO_SLIP_WATER, TRAIT_STATUS_EFFECT(id)) + slipperiness = owner.AddComponent(/datum/component/slippery, knockdown = 12 SECONDS, lube_flags = NO_SLIP_WHEN_WALKING) + +/datum/status_effect/golem/bananium/on_remove() + REMOVE_TRAIT(owner, TRAIT_NO_SLIP_WATER, TRAIT_STATUS_EFFECT(id)) + owner.RemoveElement(/datum/element/waddling) + QDEL_NULL(slipperiness) + return ..() + +#define LIGHTBULB_FILTER "filter_lightbulb_glow" + +/// Lights up the golem, NOT using the golem subtype because it is not exclusive with other status effects +/datum/status_effect/golem_lightbulb + id = "golem_lightbulb" + status_type = STATUS_EFFECT_REFRESH + duration = 2 MINUTES + alert_type = null + var/glow_range = 3 + var/glow_power = 1 + var/glow_color = LIGHT_COLOR_DEFAULT + var/datum/component/overlay_lighting/lightbulb + +/datum/status_effect/golem_lightbulb/on_apply() + . = ..() + if (!.) + return + to_chat(owner, span_notice("You start to emit a healthy glow.")) + owner.light_system = MOVABLE_LIGHT + lightbulb = owner.AddComponent(/datum/component/overlay_lighting, _range = glow_range, _power = glow_power, _color = glow_color) + owner.add_filter(LIGHTBULB_FILTER, 2, list("type" = "outline", "color" = glow_color, "alpha" = 60, "size" = 1)) + +/datum/status_effect/golem_lightbulb/on_remove() + QDEL_NULL(lightbulb) + owner.remove_filter(LIGHTBULB_FILTER) + to_chat(owner, span_warning("Your glow fades.")) + return ..() + +#undef LIGHTBULB_FILTER diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 4b24b70447b..8f2503847ac 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -120,6 +120,9 @@ ) AddElement(/datum/element/connect_loc, loc_connections) + if(is_path_in_list(merge_type, GLOB.golem_stack_food_directory)) + AddComponent(/datum/component/golem_food, golem_food_key = merge_type) + /** Sets the amount of materials per unit for this stack. * * Arguments: diff --git a/code/game/turfs/closed/minerals.dm b/code/game/turfs/closed/minerals.dm index f7fa570452a..a00d6ea8583 100644 --- a/code/game/turfs/closed/minerals.dm +++ b/code/game/turfs/closed/minerals.dm @@ -94,37 +94,40 @@ to_chat(usr, span_warning("You don't have the dexterity to do this!")) return - if(I.tool_behaviour == TOOL_MINING) - var/turf/T = user.loc - if (!isturf(T)) - return + if(I.tool_behaviour != TOOL_MINING) + return + var/turf/T = user.loc + if (!isturf(T)) + return - if(TIMER_COOLDOWN_CHECK(src, REF(user))) //prevents mining turfs in progress - return + if(TIMER_COOLDOWN_CHECK(src, REF(user))) //prevents mining turfs in progress + return - TIMER_COOLDOWN_START(src, REF(user), tool_mine_speed) + TIMER_COOLDOWN_START(src, REF(user), tool_mine_speed) - balloon_alert(user, "picking...") + balloon_alert(user, "picking...") - if(!I.use_tool(src, user, tool_mine_speed, volume=50)) - TIMER_COOLDOWN_END(src, REF(user)) //if we fail we can start again immediately - return - if(ismineralturf(src)) - gets_drilled(user, TRUE) - SSblackbox.record_feedback("tally", "pick_used_mining", 1, I.type) + if(!I.use_tool(src, user, tool_mine_speed, volume=50)) + TIMER_COOLDOWN_END(src, REF(user)) //if we fail we can start again immediately + return + if(ismineralturf(src)) + gets_drilled(user, TRUE) + SSblackbox.record_feedback("tally", "pick_used_mining", 1, I.type) /turf/closed/mineral/attack_hand(mob/user) - if(!weak_turf) + var/mining_arms = HAS_TRAIT(user, TRAIT_FIST_MINING) + if(!weak_turf && !mining_arms) return ..() var/turf/user_turf = user.loc if (!isturf(user_turf)) return if(TIMER_COOLDOWN_CHECK(src, REF(user))) //prevents mining turfs in progress return - TIMER_COOLDOWN_START(src, REF(user), hand_mine_speed) + var/mining_speed = mining_arms ? tool_mine_speed : hand_mine_speed + TIMER_COOLDOWN_START(src, REF(user), mining_speed) var/skill_modifier = user.mind?.get_skill_modifier(/datum/skill/mining, SKILL_SPEED_MODIFIER) || 1 balloon_alert(user, "pulling out pieces...") - if(!do_after(user, hand_mine_speed * skill_modifier, target = src)) + if(!do_after(user, mining_speed * skill_modifier, target = src)) TIMER_COOLDOWN_END(src, REF(user)) //if we fail we can start again immediately return if(ismineralturf(src)) diff --git a/code/modules/antagonists/abductor/machinery/pad.dm b/code/modules/antagonists/abductor/machinery/pad.dm index 515f181fc3c..f6fc659f6d1 100644 --- a/code/modules/antagonists/abductor/machinery/pad.dm +++ b/code/modules/antagonists/abductor/machinery/pad.dm @@ -54,10 +54,16 @@ name = "Huh" icon = 'icons/obj/abductor.dmi' icon_state = "teleport" - duration = 80 + duration = 8 SECONDS /obj/effect/temp_visual/teleport_abductor/Initialize(mapload) . = ..() var/datum/effect_system/spark_spread/S = new S.set_up(10,0,loc) S.start() + +/obj/effect/temp_visual/teleport_golem + name = "bluespace silhouette" + icon = 'icons/obj/abductor.dmi' + icon_state = "teleport" + duration = 6 SECONDS diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index c5d2defd623..498cc8f9c9d 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -208,7 +208,6 @@ GLOBAL_LIST_INIT(clown_mask_options, list( resistance_flags = FLAMMABLE actions_types = list(/datum/action/item_action/adjust) dog_fashion = /datum/dog_fashion/head/clown - species_exception = list(/datum/species/golem/bananium) has_fov = FALSE var/list/clownmask_designs = list() @@ -252,7 +251,6 @@ GLOBAL_LIST_INIT(clown_mask_options, list( righthand_file = 'icons/mob/inhands/clothing/hats_righthand.dmi' flags_cover = MASKCOVERSEYES resistance_flags = FLAMMABLE - species_exception = list(/datum/species/golem/bananium) has_fov = FALSE /obj/item/clothing/mask/gas/mime @@ -375,7 +373,6 @@ GLOBAL_LIST_INIT(clown_mask_options, list( max_integrity = 100 actions_types = list(/datum/action/item_action/adjust) dog_fashion = null - species_exception = list(/datum/species/golem/wood) var/list/tikimask_designs = list() /obj/item/clothing/mask/gas/tiki_mask/Initialize(mapload) diff --git a/code/modules/clothing/shoes/boots.dm b/code/modules/clothing/shoes/boots.dm index df7f6da84e4..4c3887fec67 100644 --- a/code/modules/clothing/shoes/boots.dm +++ b/code/modules/clothing/shoes/boots.dm @@ -121,7 +121,6 @@ strip_delay = 20 equip_delay_other = 40 lace_time = 8 SECONDS - species_exception = list(/datum/species/golem/uranium) /datum/armor/shoes_workboots bio = 80 diff --git a/code/modules/clothing/shoes/clown.dm b/code/modules/clothing/shoes/clown.dm index 9c68e44cbbe..bc1415de84c 100644 --- a/code/modules/clothing/shoes/clown.dm +++ b/code/modules/clothing/shoes/clown.dm @@ -8,7 +8,6 @@ ///List of possible sounds for the squeak component to use, allows for different clown shoe subtypes to have different sounds. var/list/squeak_sound = list('sound/effects/footstep/clownstep1.ogg'=1,'sound/effects/footstep/clownstep2.ogg'=1) lace_time = 20 SECONDS // how the hell do these laces even work?? - species_exception = list(/datum/species/golem/bananium) /obj/item/clothing/shoes/clown_shoes/Initialize(mapload) . = ..() diff --git a/code/modules/clothing/suits/jacket.dm b/code/modules/clothing/suits/jacket.dm index d441db0efad..cc5909d41c5 100644 --- a/code/modules/clothing/suits/jacket.dm +++ b/code/modules/clothing/suits/jacket.dm @@ -54,7 +54,6 @@ resistance_flags = NONE max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT 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/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver, /obj/item/gun/ballistic/revolver/c38/detective, /obj/item/radio) - species_exception = list(/datum/species/golem/bone) //bad to the bone /obj/item/clothing/suit/jacket/leather/biker name = "biker jacket" @@ -67,7 +66,6 @@ icon_state = "pufferjacket" inhand_icon_state = "hostrench" armor_type = /datum/armor/jacket_puffer - species_exception = list(/datum/species/golem/bone) /datum/armor/jacket_puffer bio = 50 diff --git a/code/modules/clothing/suits/wintercoats.dm b/code/modules/clothing/suits/wintercoats.dm index 2d43655da20..a34759789b8 100644 --- a/code/modules/clothing/suits/wintercoats.dm +++ b/code/modules/clothing/suits/wintercoats.dm @@ -521,7 +521,6 @@ ) armor_type = /datum/armor/wintercoat_engineering hoodtype = /obj/item/clothing/head/hooded/winterhood/engineering - species_exception = list(/datum/species/golem/uranium) /datum/armor/wintercoat_engineering fire = 20 diff --git a/code/modules/clothing/under/jobs/civilian/clown_mime.dm b/code/modules/clothing/under/jobs/civilian/clown_mime.dm index 9d55a30d564..e726ba54689 100644 --- a/code/modules/clothing/under/jobs/civilian/clown_mime.dm +++ b/code/modules/clothing/under/jobs/civilian/clown_mime.dm @@ -29,7 +29,6 @@ desc = "'HONK!'" icon_state = "clown" inhand_icon_state = "clown" - species_exception = list(/datum/species/golem/bananium) female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY can_adjust = FALSE diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm index b99e3fc90ec..e7611612a5b 100644 --- a/code/modules/clothing/under/jobs/engineering.dm +++ b/code/modules/clothing/under/jobs/engineering.dm @@ -54,7 +54,6 @@ name = "engineer's jumpsuit" icon_state = "engine" inhand_icon_state = "engi_suit" - species_exception = list(/datum/species/golem/uranium) /obj/item/clothing/under/rank/engineering/engineer/hazard name = "engineer's hazard jumpsuit" diff --git a/code/modules/explorer_drone/exodrone.dm b/code/modules/explorer_drone/exodrone.dm index 0f3d03f4baa..a33ad0f1430 100644 --- a/code/modules/explorer_drone/exodrone.dm +++ b/code/modules/explorer_drone/exodrone.dm @@ -444,7 +444,7 @@ GLOBAL_LIST_EMPTY(exodrone_launchers) /// The amount of uses left in this fuel pellet. var/uses = 5 -/obj/item/fuel_pellet/use() +/obj/item/fuel_pellet/use(used) uses-- if(uses <= 0) qdel(src) diff --git a/code/modules/mapfluff/ruins/lavaland_ruin_code.dm b/code/modules/mapfluff/ruins/lavaland_ruin_code.dm index 00f2124f13d..73afd60b3a6 100644 --- a/code/modules/mapfluff/ruins/lavaland_ruin_code.dm +++ b/code/modules/mapfluff/ruins/lavaland_ruin_code.dm @@ -32,57 +32,33 @@ /obj/item/golem_shell name = "incomplete free golem shell" icon = 'icons/obj/wizard.dmi' - icon_state = "construct" - desc = "The incomplete body of a golem. Add ten sheets of any mineral to finish." + icon_state = "shell_unfinished" + desc = "The incomplete body of a golem. Add ten sheets of certain minerals to finish." w_class = WEIGHT_CLASS_BULKY - + /// Amount of minerals you need to feed the shell to wake it up + var/required_stacks = 10 + /// Type of shell to create var/shell_type = /obj/effect/mob_spawn/ghost_role/human/golem -/obj/item/golem_shell/attackby(obj/item/I, mob/user, params) +/obj/item/golem_shell/attackby(obj/item/potential_food, mob/user, params) . = ..() - var/static/list/golem_shell_species_types = list( - /obj/item/stack/sheet/iron = /datum/species/golem, - /obj/item/stack/sheet/glass = /datum/species/golem/glass, - /obj/item/stack/sheet/plasteel = /datum/species/golem/plasteel, - /obj/item/stack/sheet/mineral/sandstone = /datum/species/golem/sand, - /obj/item/stack/sheet/mineral/plasma = /datum/species/golem/plasma, - /obj/item/stack/sheet/mineral/diamond = /datum/species/golem/diamond, - /obj/item/stack/sheet/mineral/gold = /datum/species/golem/gold, - /obj/item/stack/sheet/mineral/silver = /datum/species/golem/silver, - /obj/item/stack/sheet/mineral/uranium = /datum/species/golem/uranium, - /obj/item/stack/sheet/mineral/bananium = /datum/species/golem/bananium, - /obj/item/stack/sheet/mineral/titanium = /datum/species/golem/titanium, - /obj/item/stack/sheet/mineral/plastitanium = /datum/species/golem/plastitanium, - /obj/item/stack/sheet/mineral/abductor = /datum/species/golem/alloy, - /obj/item/stack/sheet/mineral/wood = /datum/species/golem/wood, - /obj/item/stack/sheet/bluespace_crystal = /datum/species/golem/bluespace, - /obj/item/stack/sheet/runed_metal = /datum/species/golem/runic, - /obj/item/stack/medical/gauze = /datum/species/golem/cloth, - /obj/item/stack/sheet/cloth = /datum/species/golem/cloth, - /obj/item/stack/sheet/mineral/adamantine = /datum/species/golem/adamantine, - - /obj/item/stack/sheet/bronze = /datum/species/golem/bronze, - /obj/item/stack/sheet/cardboard = /datum/species/golem/cardboard, - /obj/item/stack/sheet/leather = /datum/species/golem/leather, - /obj/item/stack/sheet/bone = /datum/species/golem/bone, - /obj/item/stack/sheet/durathread = /datum/species/golem/durathread, - /obj/item/stack/sheet/cotton/durathread = /datum/species/golem/durathread, - /obj/item/stack/sheet/mineral/snow = /datum/species/golem/snow, - /obj/item/stack/sheet/mineral/metal_hydrogen= /datum/species/golem/mhydrogen, - ) - - if(!isstack(I)) + if(!isstack(potential_food)) + balloon_alert(user, "not a mineral!") return - var/obj/item/stack/stuff_stack = I - var/species = golem_shell_species_types[stuff_stack.merge_type] - if(!species) - to_chat(user, span_warning("You can't build a golem out of this kind of material!")) + var/obj/item/stack/stack_food = potential_food + var/stack_type = stack_food.merge_type + if (!is_path_in_list(stack_type, GLOB.golem_stack_food_directory)) + balloon_alert(user, "incompatible mineral!") return - if(!stuff_stack.use(10)) - to_chat(user, span_warning("You need at least ten sheets to finish a golem!")) + if(stack_food.amount < required_stacks) + balloon_alert(user, "not enough minerals!") return - to_chat(user, span_notice("You finish up the golem shell with ten sheets of [stuff_stack].")) - new shell_type(get_turf(src), species, user) + if(!do_after(user, delay = 4 SECONDS, target = src)) + return + if(!stack_food.use(required_stacks)) + balloon_alert(user, "not enough minerals!") + return + new shell_type(get_turf(src), /* creator = */ user, /* made_of = */ stack_type) qdel(src) ///made with xenobiology, the golem obeys its creator diff --git a/code/modules/mining/equipment/monster_organs/regenerative_core.dm b/code/modules/mining/equipment/monster_organs/regenerative_core.dm index bb56b773d73..f8c95536258 100644 --- a/code/modules/mining/equipment/monster_organs/regenerative_core.dm +++ b/code/modules/mining/equipment/monster_organs/regenerative_core.dm @@ -61,5 +61,3 @@ This process will trigger automatically if you are badly wounded." button_icon_state = "legion_core_stable" check_flags = NONE - -/datum/action/cooldown/monster_core_action/regenerative_core diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index 207461167e2..8ad06edb849 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -241,6 +241,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ /obj/item/gibtonite/Initialize(mapload) . = ..() AddComponent(/datum/component/two_handed, require_twohands=TRUE) + AddComponent(/datum/component/golem_food, consume_on_eat = FALSE, golem_food_key = /obj/item/gibtonite) /obj/item/gibtonite/Destroy() qdel(wires) @@ -264,53 +265,61 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ if(I.tool_behaviour == TOOL_MINING || istype(I, /obj/item/resonator) || I.force >= 10) GibtoniteReaction(user) return - if(primed) - if(istype(I, /obj/item/mining_scanner) || istype(I, /obj/item/t_scanner/adv_mining_scanner) || I.tool_behaviour == TOOL_MULTITOOL) - primed = FALSE - if(det_timer) - deltimer(det_timer) - user.visible_message(span_notice("The chain reaction stopped! ...The ore's quality looks diminished."), span_notice("You stopped the chain reaction. ...The ore's quality looks diminished.")) - icon_state = "Gibtonite ore" - quality = GIBTONITE_QUALITY_LOW - return - ..() + + if(istype(I, /obj/item/mining_scanner) || istype(I, /obj/item/t_scanner/adv_mining_scanner) || I.tool_behaviour == TOOL_MULTITOOL) + defuse(user) + return + + return ..() + +/// Stop the reaction and reduce ore explosive power +/obj/item/gibtonite/proc/defuse(mob/defuser) + if (!primed) + return + primed = FALSE + if(det_timer) + deltimer(det_timer) + defuser?.visible_message(span_notice("The chain reaction stopped! ...The ore's quality looks diminished."), span_notice("You stopped the chain reaction. ...The ore's quality looks diminished.")) + icon_state = "Gibtonite ore" + quality = GIBTONITE_QUALITY_LOW /obj/item/gibtonite/attack_self(user) if(wires) wires.interact(user) else - ..() + return ..() /obj/item/gibtonite/bullet_act(obj/projectile/P) GibtoniteReaction(P.firer) - . = ..() + return ..() /obj/item/gibtonite/ex_act() GibtoniteReaction(null, 1) return TRUE /obj/item/gibtonite/proc/GibtoniteReaction(mob/user, triggered_by = 0) - if(!primed) - primed = TRUE - playsound(src,'sound/effects/hit_on_shattered_glass.ogg',50,TRUE) - icon_state = "Gibtonite active" - var/notify_admins = FALSE - if(z != 5)//Only annoy the admins ingame if we're triggered off the mining zlevel - notify_admins = TRUE + if(primed) + return + primed = TRUE + playsound(src,'sound/effects/hit_on_shattered_glass.ogg',50,TRUE) + icon_state = "Gibtonite active" + var/notify_admins = FALSE + if(!is_mining_level(z))//Only annoy the admins ingame if we're triggered off the mining zlevel + notify_admins = TRUE - if(triggered_by == 1) - log_bomber(null, "An explosion has primed a", src, "for detonation", notify_admins) - else if(triggered_by == 2) - var/turf/bombturf = get_turf(src) - if(notify_admins) - message_admins("A signal has triggered a [name] to detonate at [ADMIN_VERBOSEJMP(bombturf)]. Igniter attacher: [ADMIN_LOOKUPFLW(attacher)]") - var/bomb_message = "A signal has primed a [name] for detonation at [AREACOORD(bombturf)]. Igniter attacher: [key_name(attacher)]." - log_game(bomb_message) - GLOB.bombers += bomb_message - else - user.visible_message(span_warning("[user] strikes \the [src], causing a chain reaction!"), span_danger("You strike \the [src], causing a chain reaction.")) - log_bomber(user, "has primed a", src, "for detonation", notify_admins) - det_timer = addtimer(CALLBACK(src, PROC_REF(detonate), notify_admins), det_time, TIMER_STOPPABLE) + if(triggered_by == 1) + log_bomber(null, "An explosion has primed a", src, "for detonation", notify_admins) + else if(triggered_by == 2) + var/turf/bombturf = get_turf(src) + if(notify_admins) + message_admins("A signal has triggered a [name] to detonate at [ADMIN_VERBOSEJMP(bombturf)]. Igniter attacher: [ADMIN_LOOKUPFLW(attacher)]") + var/bomb_message = "A signal has primed a [name] for detonation at [AREACOORD(bombturf)]. Igniter attacher: [key_name(attacher)]." + log_game(bomb_message) + GLOB.bombers += bomb_message + else + user.visible_message(span_warning("[user] strikes \the [src], causing a chain reaction!"), span_danger("You strike \the [src], causing a chain reaction.")) + log_bomber(user, "has primed a", src, "for detonation", notify_admins) + det_timer = addtimer(CALLBACK(src, PROC_REF(detonate), notify_admins), det_time, TIMER_STOPPABLE) /obj/item/gibtonite/proc/detonate(notify_admins) if(primed) @@ -323,6 +332,14 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ explosion(src, heavy_impact_range = 1, light_impact_range = 3, adminlog = notify_admins) qdel(src) +/obj/item/gibtonite/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + . = ..() + if (throwingdatum.dist_travelled < 2 || !isliving(hit_atom)) + return + var/mob/living/hit_mob = hit_atom + hit_mob.Paralyze(1.5 SECONDS) + hit_mob.Knockdown(8 SECONDS) + /obj/item/stack/ore/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1) . = ..() pixel_x = base_pixel_x + rand(0, 16) - 8 diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index da0c6d55200..04e754c8d22 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -217,13 +217,13 @@ return FALSE if (merge_stacks) - if (istype(active_stack) && active_stack.can_merge(item_stack)) + if (istype(active_stack) && active_stack.can_merge(item_stack, inhand = TRUE)) if (item_stack.merge(active_stack)) to_chat(usr, span_notice("Your [active_stack.name] stack now contains [active_stack.get_amount()] [active_stack.singular_name]\s.")) return TRUE else var/obj/item/stack/inactive_stack = get_inactive_held_item() - if (istype(inactive_stack) && inactive_stack.can_merge(item_stack)) + if (istype(inactive_stack) && inactive_stack.can_merge(item_stack, inhand = TRUE)) if (item_stack.merge(inactive_stack)) to_chat(usr, span_notice("Your [inactive_stack.name] stack now contains [inactive_stack.get_amount()] [inactive_stack.singular_name]\s.")) return TRUE diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 78d78bcc7cb..2f0397a46b5 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -373,6 +373,14 @@ desc = "This juicy piece of meat has a clearly underdeveloped frontal lobe." organ_traits = list(TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, TRAIT_PRIMITIVE) // No literacy +/obj/item/organ/internal/brain/golem + name = "crystalline matrix" + desc = "This collection of sparkling gems somehow allows a golem to think." + icon_state = "adamantine_resonator" + color = COLOR_GOLEM_GRAY + status = ORGAN_MINERAL + organ_traits = list(TRAIT_ADVANCEDTOOLUSER, TRAIT_LITERATE, TRAIT_CAN_STRIP, TRAIT_ROCK_METAMORPHIC) + ////////////////////////////////////TRAUMAS//////////////////////////////////////// /obj/item/organ/internal/brain/proc/has_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience = TRAUMA_RESILIENCE_ABSOLUTE) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index bea0d1dba96..38fda76da2a 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -860,7 +860,7 @@ var/obj/item/bodypart/new_part = pick(GLOB.bioscrambler_valid_parts) var/obj/item/bodypart/picked_user_part = get_bodypart(initial(new_part.body_zone)) - if (!(picked_user_part?.bodytype & BODYTYPE_ROBOTIC)) + if (picked_user_part && BODYTYPE_CAN_BE_BIOSCRAMBLED(picked_user_part.bodytype)) changed_something = TRUE new_part = new new_part() new_part.replace_limb(src, special = TRUE) @@ -878,7 +878,7 @@ /mob/living/carbon/proc/init_bioscrambler_lists() var/list/body_parts = typesof(/obj/item/bodypart/chest) + typesof(/obj/item/bodypart/head) + subtypesof(/obj/item/bodypart/arm) + subtypesof(/obj/item/bodypart/leg) for (var/obj/item/bodypart/part as anything in body_parts) - if (!is_type_in_typecache(part, GLOB.bioscrambler_parts_blacklist) && !(initial(part.bodytype) & BODYTYPE_ROBOTIC)) + if (!is_type_in_typecache(part, GLOB.bioscrambler_parts_blacklist) && BODYTYPE_CAN_BE_BIOSCRAMBLED(initial(part.bodytype))) continue body_parts -= part GLOB.bioscrambler_valid_parts = body_parts diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index a340d7650ea..958c22ab44d 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -32,6 +32,41 @@ if(slot_flags & (ITEM_SLOT_LPOCKET|ITEM_SLOT_RPOCKET)) update_pockets() +/// Updates features and clothing attached to a specific limb with limb-specific offsets +/mob/living/carbon/proc/update_features(feature_key) + switch(feature_key) + if(OFFSET_UNIFORM) + update_worn_undersuit() + if(OFFSET_ID) + update_worn_id() + if(OFFSET_GLOVES) + update_worn_gloves() + if(OFFSET_GLASSES) + update_worn_glasses() + if(OFFSET_EARS) + update_inv_ears() + if(OFFSET_SHOES) + update_worn_shoes() + if(OFFSET_S_STORE) + update_suit_storage() + if(OFFSET_FACEMASK) + update_worn_mask() + if(OFFSET_HEAD) + update_worn_head() + if(OFFSET_FACE) + dna?.species?.handle_body(src) // updates eye icon + update_worn_mask() + if(OFFSET_BELT) + update_worn_belt() + if(OFFSET_BACK) + update_worn_back() + if(OFFSET_SUIT) + update_worn_oversuit() + if(OFFSET_NECK) + update_worn_neck() + if(OFFSET_HELD) + update_held_items() + //IMPORTANT: Multiple animate() calls do not stack well, so try to do them all at once if you can. /mob/living/carbon/perform_update_transform() var/matrix/ntransform = matrix(transform) //aka transform.Copy() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index dcb0d457072..3634807bce3 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1065,78 +1065,6 @@ /mob/living/carbon/human/species/golem race = /datum/species/golem -/mob/living/carbon/human/species/golem/adamantine - race = /datum/species/golem/adamantine - -/mob/living/carbon/human/species/golem/plasma - race = /datum/species/golem/plasma - -/mob/living/carbon/human/species/golem/diamond - race = /datum/species/golem/diamond - -/mob/living/carbon/human/species/golem/gold - race = /datum/species/golem/gold - -/mob/living/carbon/human/species/golem/silver - race = /datum/species/golem/silver - -/mob/living/carbon/human/species/golem/plasteel - race = /datum/species/golem/plasteel - -/mob/living/carbon/human/species/golem/titanium - race = /datum/species/golem/titanium - -/mob/living/carbon/human/species/golem/plastitanium - race = /datum/species/golem/plastitanium - -/mob/living/carbon/human/species/golem/alien_alloy - race = /datum/species/golem/alloy - -/mob/living/carbon/human/species/golem/wood - race = /datum/species/golem/wood - -/mob/living/carbon/human/species/golem/uranium - race = /datum/species/golem/uranium - -/mob/living/carbon/human/species/golem/sand - race = /datum/species/golem/sand - -/mob/living/carbon/human/species/golem/glass - race = /datum/species/golem/glass - -/mob/living/carbon/human/species/golem/bluespace - race = /datum/species/golem/bluespace - -/mob/living/carbon/human/species/golem/bananium - race = /datum/species/golem/bananium - -/mob/living/carbon/human/species/golem/blood_cult - race = /datum/species/golem/runic - -/mob/living/carbon/human/species/golem/cloth - race = /datum/species/golem/cloth - -/mob/living/carbon/human/species/golem/plastic - race = /datum/species/golem/plastic - -/mob/living/carbon/human/species/golem/bronze - race = /datum/species/golem/bronze - -/mob/living/carbon/human/species/golem/cardboard - race = /datum/species/golem/cardboard - -/mob/living/carbon/human/species/golem/leather - race = /datum/species/golem/leather - -/mob/living/carbon/human/species/golem/bone - race = /datum/species/golem/bone - -/mob/living/carbon/human/species/golem/durathread - race = /datum/species/golem/durathread - -/mob/living/carbon/human/species/golem/snow - race = /datum/species/golem/snow - /mob/living/carbon/human/species/jelly race = /datum/species/jelly 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 b733568f8dd..9fc659eb5b4 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -105,13 +105,13 @@ There are several things that need to be remembered: var/mutant_styles = NONE // SKYRAT EDIT ADDITON - mutant styles to pass down to build_worn_icon. //BEGIN SPECIES HANDLING if((dna?.species.bodytype & BODYTYPE_MONKEY) && (uniform.supports_variations_flags & CLOTHING_MONKEY_VARIATION)) - icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_UNIFORM, w_uniform) + icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_UNIFORM, w_uniform, src) else if((dna?.species.bodytype & BODYTYPE_DIGITIGRADE) && (uniform.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION)) icon_file = uniform.worn_icon_digi || DIGITIGRADE_UNIFORM_FILE // SKYRAT EDIT CHANGE // SKYRAT EDIT ADDITION - birbs else if(dna.species.bodytype & BODYTYPE_CUSTOM) - icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_UNIFORM, w_uniform) + icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_UNIFORM, w_uniform, src) // SKYRAT EDIT END //Female sprites have lower priority than digitigrade sprites @@ -139,9 +139,8 @@ There are several things that need to be remembered: mutant_styles = mutant_styles, // SKYRAT EDIT ADDITION - Taur-friendly uniforms! ) - if(!handled_by_bodytype && (OFFSET_UNIFORM in dna.species.offset_features)) // SKYRAT EDIT CHANGE - uniform_overlay?.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1] - uniform_overlay?.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2] + var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST) + my_chest?.worn_uniform_offset?.apply_offset(uniform_overlay) overlays_standing[UNIFORM_LAYER] = uniform_overlay apply_overlay(UNIFORM_LAYER) @@ -163,9 +162,9 @@ There are several things that need to be remembered: id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = icon_file) if(!id_overlay) return - if(OFFSET_ID in dna.species.offset_features) - id_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1] - id_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2] + + var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST) + my_chest?.worn_id_offset?.apply_offset(id_overlay) overlays_standing[ID_LAYER] = id_overlay apply_overlay(ID_LAYER) @@ -203,7 +202,7 @@ There are several things that need to be remembered: // SKYRAT EDIT ADDITION var/mutant_override = FALSE if(dna.species.bodytype & BODYTYPE_CUSTOM) - var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_GLOVES, gloves) + var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_GLOVES, gloves, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE @@ -211,9 +210,13 @@ There are several things that need to be remembered: var/mutable_appearance/gloves_overlay = gloves.build_worn_icon(default_layer = GLOVES_LAYER, default_icon_file = icon_file, override_file = mutant_override ? icon_file : null) // SKYRAT EDIT CHANGE - if(!mutant_override && (OFFSET_GLOVES in dna.species.offset_features)) // SKYRAT EDIT CHANGE - gloves_overlay.pixel_x += dna.species.offset_features[OFFSET_GLOVES][1] - gloves_overlay.pixel_y += dna.species.offset_features[OFFSET_GLOVES][2] + var/feature_y_offset = 0 + for (var/obj/item/bodypart/arm/my_hand as anything in hand_bodyparts) + var/list/glove_offset = my_hand.worn_glove_offset?.get_offset() + if (glove_offset && glove_offset["y"] > feature_y_offset) + feature_y_offset = glove_offset["y"] + + gloves_overlay.pixel_y += feature_y_offset overlays_standing[GLOVES_LAYER] = gloves_overlay apply_overlay(GLOVES_LAYER) @@ -221,7 +224,8 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_worn_glasses() remove_overlay(GLASSES_LAYER) - if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated + var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) + if(isnull(my_head)) //decapitated return if(client && hud_used) @@ -240,7 +244,7 @@ There are several things that need to be remembered: // SKYRAT EDIT ADDITION var/mutant_override = FALSE if(dna.species.bodytype & BODYTYPE_CUSTOM) - var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_GLASSES, glasses) + var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_GLASSES, glasses, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE @@ -248,9 +252,7 @@ There are several things that need to be remembered: var/mutable_appearance/glasses_overlay = glasses.build_worn_icon(default_layer = GLASSES_LAYER, default_icon_file = icon_file, override_file = mutant_override ? icon_file : null) // SKYRAT EDIT CHANGE - if(!mutant_override && (OFFSET_GLASSES in dna.species.offset_features)) // SKYRAT EDIT CHANGE - glasses_overlay.pixel_x += dna.species.offset_features[OFFSET_GLASSES][1] - glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2] + my_head.worn_glasses_offset?.apply_offset(glasses_overlay) overlays_standing[GLASSES_LAYER] = glasses_overlay apply_overlay(GLASSES_LAYER) @@ -258,7 +260,8 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_ears() remove_overlay(EARS_LAYER) - if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated + var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) + if(isnull(my_head)) //decapitated return if(client && hud_used) @@ -277,7 +280,7 @@ There are several things that need to be remembered: // SKYRAT EDIT ADDITION var/mutant_override = FALSE if(dna.species.bodytype & BODYTYPE_CUSTOM) - var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_EARS, ears) + var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_EARS, ears, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE @@ -285,9 +288,7 @@ There are several things that need to be remembered: var/mutable_appearance/ears_overlay = ears.build_worn_icon(default_layer = EARS_LAYER, default_icon_file = icon_file, override_file = mutant_override ? icon_file : null) // SKYRAT EDIT CHANGE - if(!mutant_override && (OFFSET_EARS in dna.species.offset_features)) // SKYRAT EDIT CHANGE - ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1] - ears_overlay.pixel_y += dna.species.offset_features[OFFSET_EARS][2] + my_head.worn_ears_offset?.apply_offset(ears_overlay) overlays_standing[EARS_LAYER] = ears_overlay apply_overlay(EARS_LAYER) @@ -310,7 +311,7 @@ There are several things that need to be remembered: // SKYRAT EDIT ADDITION var/mutant_override = FALSE if(dna.species.bodytype & BODYTYPE_CUSTOM) - var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_NECK, wear_neck) + var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_NECK, wear_neck, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE @@ -318,9 +319,8 @@ There are several things that need to be remembered: var/mutable_appearance/neck_overlay = worn_item.build_worn_icon(default_layer = NECK_LAYER, default_icon_file = icon_file, override_file = mutant_override ? icon_file : null) // SKYRAT EDIT CHANGE - if(!mutant_override && (OFFSET_NECK in dna.species.offset_features)) // SKYRAT EDIT CHANGE - neck_overlay.pixel_x += dna.species.offset_features[OFFSET_NECK][1] - neck_overlay.pixel_y += dna.species.offset_features[OFFSET_NECK][2] + var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST) + my_chest?.worn_belt_offset?.apply_offset(neck_overlay) overlays_standing[NECK_LAYER] = neck_overlay apply_overlay(NECK_LAYER) @@ -353,7 +353,7 @@ There are several things that need to be remembered: icon_file = worn_item.worn_icon_digi || DIGITIGRADE_SHOES_FILE // SKYRAT EDIT CHANGE mutant_override = TRUE // SKYRAT EDIT ADDITION else if(dna.species.bodytype & BODYTYPE_CUSTOM) - var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_SHOES, shoes) + var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_SHOES, shoes, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE @@ -363,9 +363,19 @@ There are several things that need to be remembered: var/mutable_appearance/shoes_overlay = shoes.build_worn_icon(default_layer = SHOES_LAYER, default_icon_file = icon_file, override_file = mutant_override ? icon_file : null) // SKYRAT EDIT CHANGE - if(!mutant_override && (OFFSET_SHOES in dna.species.offset_features)) // SKYRAT EDIT CHANGE - shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1] - shoes_overlay.pixel_y += dna.species.offset_features[OFFSET_SHOES][2] + if(!shoes_overlay) + return + + var/feature_y_offset = 0 + for (var/body_zone in list(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) + var/obj/item/bodypart/leg/my_leg = get_bodypart(body_zone) + if(isnull(my_leg)) + continue + var/list/foot_offset = my_leg.worn_foot_offset?.get_offset() + if (foot_offset && foot_offset["y"] > feature_y_offset) + feature_y_offset = foot_offset["y"] + + shoes_overlay.pixel_y += feature_y_offset overlays_standing[SHOES_LAYER] = shoes_overlay apply_overlay(SHOES_LAYER) @@ -388,10 +398,8 @@ There are several things that need to be remembered: return var/mutable_appearance/s_store_overlay = worn_item.build_worn_icon(default_layer = SUIT_STORE_LAYER, default_icon_file = 'icons/mob/clothing/belt_mirror.dmi') - - if(OFFSET_S_STORE in dna.species.offset_features) - s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1] - s_store_overlay.pixel_y += dna.species.offset_features[OFFSET_S_STORE][2] + var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST) + my_chest?.worn_suit_storage_offset?.apply_offset(s_store_overlay) overlays_standing[SUIT_STORE_LAYER] = s_store_overlay apply_overlay(SUIT_STORE_LAYER) @@ -413,7 +421,7 @@ There are several things that need to be remembered: // SKYRAT EDIT ADDITION - This needs to be refactored. var/mutant_override = FALSE if(dna.species.bodytype & BODYTYPE_CUSTOM) - var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_HEAD, head) + var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_HEAD, head, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE @@ -426,9 +434,8 @@ There are several things that need to be remembered: var/mutable_appearance/head_overlay = head.build_worn_icon(default_layer = HEAD_LAYER, default_icon_file = icon_file, override_file = mutant_override ? icon_file : null) // SKYRAT EDIT CHANGE - if(!mutant_override && (OFFSET_HEAD in dna.species.offset_features)) // SKYRAT EDIT CHANGE - head_overlay.pixel_x += dna.species.offset_features[OFFSET_HEAD][1] - head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2] + var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) + my_head?.worn_head_offset?.apply_offset(head_overlay) overlays_standing[HEAD_LAYER] = head_overlay update_mutant_bodyparts() @@ -453,7 +460,7 @@ There are several things that need to be remembered: // SKYRAT EDIT ADDITION var/mutant_override = FALSE if(dna.species.bodytype & BODYTYPE_CUSTOM) - var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_BELT, belt) + var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_BELT, belt, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE @@ -461,9 +468,8 @@ There are several things that need to be remembered: var/mutable_appearance/belt_overlay = belt.build_worn_icon(default_layer = BELT_LAYER, default_icon_file = icon_file, override_file = mutant_override ? icon_file : null) // SKYRAT EDIT CHANGE - if(!mutant_override && (OFFSET_BELT in dna.species.offset_features)) // SKYRAT EDIT CHANGE - belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1] - belt_overlay.pixel_y += dna.species.offset_features[OFFSET_BELT][2] + var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST) + my_chest?.worn_belt_offset?.apply_offset(belt_overlay) overlays_standing[BELT_LAYER] = belt_overlay apply_overlay(BELT_LAYER) @@ -480,23 +486,22 @@ There are several things that need to be remembered: update_hud_wear_suit(worn_item) var/icon_file = DEFAULT_SUIT_FILE - var/mutant_override = FALSE // SKYRAT EDIT ADDITION - var/mutant_styles = NONE // SKYRAT EDIT ADDITON - mutant styles to pass down to build_worn_icon. + // SKYRAT EDIT ADDITION + var/mutant_override = FALSE + var/mutant_styles = NONE + //More currently unused digitigrade handling if(dna.species.bodytype & BODYTYPE_DIGITIGRADE) if(worn_item.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION) icon_file = worn_item.worn_icon_digi || DIGITIGRADE_SUIT_FILE // SKYRAT EDIT CHANGE - mutant_override = TRUE // SKYRAT EDIT ADDITION + mutant_override = TRUE - // SKYRAT EDIT ADDITION else if(dna.species.bodytype & BODYTYPE_CUSTOM) - var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_SUIT, wear_suit) + var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_SUIT, wear_suit, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE - // SKYRAT EDIT END - // SKYRAT EDIT ADDITION START - Taur-friendly suits! if(dna.species.bodytype & BODYTYPE_TAUR) var/obj/item/clothing/suit/worn_suit = wear_suit if(istype(worn_suit) && worn_suit.gets_cropped_on_taurs) @@ -505,9 +510,8 @@ There are several things that need to be remembered: var/mutable_appearance/suit_overlay = wear_suit.build_worn_icon(default_layer = SUIT_LAYER, default_icon_file = icon_file, override_file = mutant_override ? icon_file : null, mutant_styles = mutant_styles) // SKYRAT EDIT CHANGE - Mutant bodytypes and Taur-friendly suits! - if(!mutant_override && (OFFSET_UNIFORM in dna.species.offset_features)) // SKYRAT EDIT CHANGE - suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1] - suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2] + var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST) + my_chest?.worn_suit_offset?.apply_offset(suit_overlay) overlays_standing[SUIT_LAYER] = suit_overlay update_body_parts() update_mutant_bodyparts() @@ -539,7 +543,8 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_worn_mask() remove_overlay(FACEMASK_LAYER) - if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated + var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) + if(isnull(my_head)) //Decapitated return if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_MASK) + 1]) @@ -558,7 +563,7 @@ There are several things that need to be remembered: // SKYRAT EDIT ADDITION var/mutant_override = FALSE if(dna.species.bodytype & BODYTYPE_CUSTOM) - var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_MASK, wear_mask) + var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_MASK, wear_mask, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE @@ -571,9 +576,7 @@ There are several things that need to be remembered: var/mutable_appearance/mask_overlay = wear_mask.build_worn_icon(default_layer = FACEMASK_LAYER, default_icon_file = icon_file, override_file = mutant_override ? icon_file : null) // SKYRAT EDIT CHANGE - if(!mutant_override && (OFFSET_FACEMASK in dna.species.offset_features)) // SKYRAT EDIT CHANGE - mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1] - mask_overlay.pixel_y += dna.species.offset_features[OFFSET_FACEMASK][2] + my_head.worn_mask_offset?.apply_offset(mask_overlay) overlays_standing[FACEMASK_LAYER] = mask_overlay apply_overlay(FACEMASK_LAYER) @@ -595,7 +598,7 @@ There are several things that need to be remembered: // SKYRAT EDIT ADDITION var/mutant_override = FALSE if(dna.species.bodytype & BODYTYPE_CUSTOM) - var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_MISC, back) + var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_MISC, back, src) if(species_icon_file) icon_file = species_icon_file mutant_override = TRUE @@ -605,9 +608,8 @@ There are several things that need to be remembered: if(!back_overlay) return - if(!mutant_override && (OFFSET_BACK in dna.species.offset_features)) // SKYRAT EDIT CHANGE - back_overlay.pixel_x += dna.species.offset_features[OFFSET_BACK][1] - back_overlay.pixel_y += dna.species.offset_features[OFFSET_BACK][2] + var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST) + my_chest?.worn_back_offset?.apply_offset(back_overlay) overlays_standing[BACK_LAYER] = back_overlay apply_overlay(BACK_LAYER) @@ -627,8 +629,9 @@ There are several things that need to be remembered: var/list/hands = list() for(var/obj/item/worn_item in held_items) + var/held_index = get_held_index_of_item(worn_item) if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) - worn_item.screen_loc = ui_hand_position(get_held_index_of_item(worn_item)) + worn_item.screen_loc = ui_hand_position(held_index) client.screen += worn_item if(observers?.len) for(var/M in observers) @@ -645,13 +648,11 @@ There are several things that need to be remembered: if(!t_state) t_state = worn_item.icon_state - var/icon_file = worn_item.lefthand_file var/mutable_appearance/hand_overlay - if(get_held_index_of_item(worn_item) % 2 == 0) - icon_file = worn_item.righthand_file - hand_overlay = worn_item.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE) - else - hand_overlay = worn_item.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE) + var/icon_file = held_index % 2 == 0 ? worn_item.righthand_file : worn_item.lefthand_file + hand_overlay = worn_item.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE) + var/obj/item/bodypart/arm/held_in_hand = hand_bodyparts[held_index] + held_in_hand?.held_hand_offset?.apply_offset(hand_overlay) hands += hand_overlay overlays_standing[HANDS_LAYER] = hands @@ -903,24 +904,22 @@ mutant_styles: The mutant style - taur bodytype, STYLE_TESHARI, etc. // SKYRAT E if(!dna?.species) return - var/obj/item/bodypart/HD = get_bodypart("head") + var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) - if (!istype(HD)) + if (!istype(my_head)) return - HD.update_limb(is_creating = update_limb_data) + my_head.update_limb(is_creating = update_limb_data) - add_overlay(HD.get_limb_icon()) + add_overlay(my_head.get_limb_icon()) update_damage_overlays() - if(HD && !(HAS_TRAIT(src, TRAIT_HUSK))) + if(my_head && !(HAS_TRAIT(src, TRAIT_HUSK))) // lipstick if(lip_style && (LIPS in dna.species.species_traits)) var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/species/human/human_face.dmi', "lips_[lip_style]", -BODY_LAYER) lip_overlay.color = lip_color - if(OFFSET_FACE in dna.species.offset_features) - lip_overlay.pixel_x += dna.species.offset_features[OFFSET_FACE][1] - lip_overlay.pixel_y += dna.species.offset_features[OFFSET_FACE][2] + my_head.worn_face_offset?.apply_offset(lip_overlay) add_overlay(lip_overlay) // eyes @@ -930,18 +929,14 @@ mutant_styles: The mutant style - taur bodytype, STYLE_TESHARI, etc. // SKYRAT E add_overlay(parent_eyes.generate_body_overlay(src)) else var/mutable_appearance/missing_eyes = mutable_appearance('icons/mob/species/human/human_face.dmi', "eyes_missing", -BODY_LAYER) - if(OFFSET_FACE in dna.species.offset_features) - missing_eyes.pixel_x += dna.species.offset_features[OFFSET_FACE][1] - missing_eyes.pixel_y += dna.species.offset_features[OFFSET_FACE][2] + my_head.worn_face_offset?.apply_offset(missing_eyes) add_overlay(missing_eyes) //SKYRAT EDIT ADDITION if (parent_eyes && parent_eyes.is_emissive) var/mutable_appearance/emissive_appearance = emissive_appearance('icons/mob/species/human/human_face.dmi', parent_eyes ? parent_eyes.eye_icon_state : "eyes_missing", -BODY_LAYER) emissive_appearance.appearance_flags &= ~RESET_TRANSFORM - if(OFFSET_FACE in dna.species.offset_features) - emissive_appearance.pixel_x += dna.species.offset_features[OFFSET_FACE][1] - emissive_appearance.pixel_y += dna.species.offset_features[OFFSET_FACE][2] + my_head.worn_face_offset?.apply_offset(emissive_appearance) add_overlay(emissive_appearance) //SKYRAT EDIT END diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 14ae96e8f14..4c55c40c5fd 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -25,24 +25,6 @@ GLOBAL_LIST_EMPTY(features_by_species) var/sexes = TRUE ///A bitfield of "bodytypes", updated by /datum/obj/item/bodypart/proc/synchronize_bodytypes() var/bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC - ///Clothing offsets. If a species has a different body than other species, you can offset clothing so they look less weird. - var/list/offset_features = list( - OFFSET_UNIFORM = list(0,0), - OFFSET_ID = list(0,0), - OFFSET_GLOVES = list(0,0), - OFFSET_GLASSES = list(0,0), - OFFSET_EARS = list(0,0), - OFFSET_SHOES = list(0,0), - OFFSET_S_STORE = list(0,0), - OFFSET_FACEMASK = list(0,0), - OFFSET_HEAD = list(0,0), - OFFSET_FACE = list(0,0), - OFFSET_BELT = list(0,0), - OFFSET_BACK = list(0,0), - OFFSET_SUIT = list(0,0), - OFFSET_NECK = list(0,0), - OFFSET_ACCESSORY = list(0, 0), // SKYRAT EDIT ADDITION - ) ///The maximum number of bodyparts this species can have. var/max_bodypart_count = 6 @@ -635,9 +617,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(species_human.lip_style && (LIPS in species_traits)) var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/species/human/human_face.dmi', "lips_[species_human.lip_style]", -BODY_LAYER) lip_overlay.color = species_human.lip_color - if(OFFSET_FACE in species_human.dna.species.offset_features) - lip_overlay.pixel_x += species_human.dna.species.offset_features[OFFSET_FACE][1] - lip_overlay.pixel_y += species_human.dna.species.offset_features[OFFSET_FACE][2] + noggin.worn_face_offset?.apply_offset(lip_overlay) lip_overlay.pixel_y += height_offset standing += lip_overlay @@ -650,24 +630,22 @@ GLOBAL_LIST_EMPTY(features_by_species) //cut any possible vis overlays if(body_vis_overlays.len) SSvis_overlays.remove_vis_overlay(species_human, body_vis_overlays) - - if(OFFSET_FACE in species_human.dna.species.offset_features) - add_pixel_x = species_human.dna.species.offset_features[OFFSET_FACE][1] - add_pixel_y = species_human.dna.species.offset_features[OFFSET_FACE][2] + var/list/feature_offset = noggin.worn_face_offset?.get_offset() + if(feature_offset) + add_pixel_x = feature_offset["x"] + add_pixel_y = feature_offset["y"] add_pixel_y += height_offset - if(!eye_organ) + if(eye_organ) + eye_organ.refresh(call_update = FALSE) + for(var/mutable_appearance/eye_overlay in eye_organ.generate_body_overlay(species_human)) + eye_overlay.pixel_y += height_offset + standing += eye_overlay + else if (!(NOEYEHOLES in species_traits)) no_eyeslay = mutable_appearance('icons/mob/species/human/human_face.dmi', "eyes_missing", -BODY_LAYER) no_eyeslay.pixel_x += add_pixel_x no_eyeslay.pixel_y += add_pixel_y standing += no_eyeslay - else - eye_organ.refresh(call_update = FALSE) - - if(!no_eyeslay) - for(var/mutable_appearance/eye_overlay in eye_organ.generate_body_overlay(species_human)) - eye_overlay.pixel_y += height_offset - standing += eye_overlay // organic body markings if(HAS_MARKINGS in species_traits) 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 3706d114457..e1387adf0a1 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -11,6 +11,7 @@ TRAIT_NOHUNGER, TRAIT_VIRUSIMMUNE, TRAIT_NOBLOOD, + TRAIT_NO_DEBRAIN_OVERLAY, ) 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 152d5609b45..41828bdf1b4 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -23,6 +23,7 @@ TRAIT_RESISTHIGHPRESSURE, TRAIT_TOXIMMUNE, TRAIT_NOBLOOD, + TRAIT_NO_DEBRAIN_OVERLAY, ) inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID 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 a13272c23ae..dfa61321d58 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -1,44 +1,46 @@ +/// Animated beings of stone. They have increased defenses, and do not need to breathe. They must eat minerals to live, which give additional buffs. /datum/species/golem - // 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, + NOTRANSSTING, + NO_UNDERWEAR, + NOEYEHOLES, ) inherent_traits = list( TRAIT_GENELESS, + TRAIT_LAVA_IMMUNE, TRAIT_NOBREATH, TRAIT_NODISMEMBER, + TRAIT_NOBLOOD, TRAIT_NOFIRE, TRAIT_PIERCEIMMUNE, TRAIT_RADIMMUNE, - TRAIT_RESISTCOLD, - TRAIT_RESISTHEAT, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_RESISTLOWPRESSURE, - TRAIT_NOBLOOD, ) mutantheart = null mutantlungs = null inherent_biotypes = MOB_HUMANOID|MOB_MINERAL - mutant_organs = list(/obj/item/organ/internal/adamantine_resonator) - speedmod = 2 + liked_food = STONE payday_modifier = 0.75 armor = 55 siemens_coeff = 0 no_equip_flags = ITEM_SLOT_MASK | ITEM_SLOT_OCLOTHING | ITEM_SLOT_GLOVES | ITEM_SLOT_FEET | ITEM_SLOT_ICLOTHING | ITEM_SLOT_SUITSTORE nojumpsuit = 1 changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC - sexes = 1 + sexes = FALSE meat = /obj/item/food/meat/slab/human/mutant/golem species_language_holder = /datum/language_holder/golem - // To prevent golem subtypes from overwhelming the odds when random species - // changes, only the Random Golem type can be chosen - fixed_mut_color = "#aaaaaa" + bodytemp_heat_damage_limit = BODYTEMP_HEAT_LAVALAND_SAFE + bodytemp_cold_damage_limit = BODYTEMP_COLD_ICEBOX_SAFE + + mutant_organs = list(/obj/item/organ/internal/adamantine_resonator) + mutanteyes = /obj/item/organ/internal/eyes/golem + mutantbrain = /obj/item/organ/internal/brain/golem + mutanttongue = /obj/item/organ/internal/tongue/golem + mutantstomach = /obj/item/organ/internal/stomach/golem + mutantappendix = /obj/item/organ/internal/appendix/golem bodypart_overrides = list( BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/golem, BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/golem, @@ -48,1333 +50,55 @@ BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem, ) - var/info_text = "As an Iron Golem, you don't have any special traits." - var/random_eligible = TRUE //If false, the golem subtype can't be made through golem mutation toxin - - var/prefix = "Iron" - var/list/special_names = list("Tarkus") + /// Chance that we will generate a human surname, for lore reasons var/human_surname_chance = 3 - var/special_name_chance = 5 /datum/species/golem/random_name(gender,unique,lastname) - var/golem_surname = pick(GLOB.golem_names) - // 3% chance that our golem has a human surname, because - // cultural contamination - if(prob(human_surname_chance)) - golem_surname = pick(GLOB.last_names) - else if(special_names?.len && prob(special_name_chance)) - golem_surname = pick(special_names) - - var/golem_name = "[prefix] [golem_surname]" - return golem_name + var/name = pick(GLOB.golem_names) + if (prob(human_surname_chance)) + name += " [pick(GLOB.last_names)]" + return name /datum/species/golem/create_pref_unique_perks() var/list/to_add = list() to_add += list(list( SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, - SPECIES_PERK_ICON = "gem", + SPECIES_PERK_ICON = "user-shield", SPECIES_PERK_NAME = "Lithoid", - SPECIES_PERK_DESC = "Lithoids are creatures made out of elements instead of \ - blood and flesh. Because of this, they're generally stronger, slower, \ - and mostly immune to environmental dangers and dangers to their health, \ - such as viruses and dismemberment.", + SPECIES_PERK_DESC = "Lithoids are creatures made out of minerals instead of \ + blood and flesh. They are strong and immune to many environmental and personal dangers \ + such as fire, radiation, lack of air, lava, viruses, and dismemberment.", )) - return to_add - -/datum/species/golem/adamantine - name = "Adamantine Golem" - id = SPECIES_GOLEM_ADAMANTINE - meat = /obj/item/food/meat/slab/human/mutant/golem/adamantine - mutant_organs = list(/obj/item/organ/internal/adamantine_resonator, /obj/item/organ/internal/vocal_cords/adamantine) - fixed_mut_color = "#44eedd" - info_text = "As an Adamantine Golem, you possess special vocal cords allowing you to \"resonate\" messages to all golems. Your unique mineral makeup makes you immune to most types of magic." - prefix = "Adamantine" - special_names = null - examine_limb_id = SPECIES_GOLEM - -/datum/species/golem/adamantine/on_species_gain(mob/living/carbon/C, datum/species/old_species) - ..() - ADD_TRAIT(C, TRAIT_ANTIMAGIC, SPECIES_TRAIT) - -/datum/species/golem/adamantine/on_species_loss(mob/living/carbon/C) - REMOVE_TRAIT(C, TRAIT_ANTIMAGIC, SPECIES_TRAIT) - ..() - -//The suicide bombers of golemkind -/datum/species/golem/plasma - name = "Plasma Golem" - id = SPECIES_GOLEM_PLASMA - fixed_mut_color = "#aa33dd" - meat = /obj/item/stack/ore/plasma - //Can burn and takes damage from heat - //no RESISTHEAT, NOFIRE - inherent_traits = list( - TRAIT_GENELESS, - TRAIT_NOBREATH, - TRAIT_NODISMEMBER, - TRAIT_PIERCEIMMUNE, - TRAIT_RADIMMUNE, - TRAIT_RESISTCOLD, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_RESISTLOWPRESSURE, - ) - info_text = "As a Plasma Golem, you burn easily. Be careful, if you get hot enough while burning, you'll blow up!" - heatmod = 0 //fine until they blow up - prefix = "Plasma" - special_names = list("Flood","Fire","Bar","Man") - examine_limb_id = SPECIES_GOLEM - var/boom_warning = FALSE - var/datum/action/innate/ignite/ignite - -/datum/species/golem/plasma/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) - if(H.bodytemperature > 750) - if(!boom_warning && H.on_fire) - to_chat(H, span_userdanger("You feel like you could blow up at any moment!")) - boom_warning = TRUE - else - if(boom_warning) - to_chat(H, span_notice("You feel more stable.")) - boom_warning = FALSE - - if(H.bodytemperature > 850 && H.on_fire && prob(25)) - explosion(H, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 4, flame_range = 5, explosion_cause = src) - if(H) - H.investigate_log("has been gibbed as [H.p_their()] body explodes.", INVESTIGATE_DEATHS) - H.gib() - if(H.fire_stacks < 2) //flammable - H.adjust_fire_stacks(0.5 * seconds_per_tick) - ..() - -/datum/species/golem/plasma/on_species_gain(mob/living/carbon/C, datum/species/old_species) - ..() - if(ishuman(C)) - ignite = new - ignite.Grant(C) - -/datum/species/golem/plasma/on_species_loss(mob/living/carbon/C) - if(ignite) - ignite.Remove(C) - ..() - -/datum/action/innate/ignite - name = "Ignite" - desc = "Set yourself aflame, bringing yourself closer to exploding!" - check_flags = AB_CHECK_CONSCIOUS - button_icon_state = "sacredflame" - -/datum/action/innate/ignite/Activate() - if(ishuman(owner)) - var/mob/living/carbon/human/H = owner - if(H.fire_stacks) - to_chat(owner, span_notice("You ignite yourself!")) - else - to_chat(owner, span_warning("You try to ignite yourself, but fail!")) - H.ignite_mob() //firestacks are already there passively - -//Harder to hurt -/datum/species/golem/diamond - name = "Diamond Golem" - id = SPECIES_GOLEM_DIAMOND - fixed_mut_color = "#00ffff" - armor = 70 //up from 55 - meat = /obj/item/stack/ore/diamond - info_text = "As a Diamond Golem, you are more resistant than the average golem." - prefix = "Diamond" - special_names = list("Back","Grill") - examine_limb_id = SPECIES_GOLEM - -//Faster but softer and less armoured -/datum/species/golem/gold - 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." - prefix = "Golden" - special_names = list("Boy") - examine_limb_id = SPECIES_GOLEM - -//Heavier, thus higher chance of stunning when punching -/datum/species/golem/silver - name = "Silver Golem" - id = SPECIES_GOLEM_SILVER - fixed_mut_color = "#dddddd" - meat = /obj/item/stack/ore/silver - info_text = "As a Silver Golem, your attacks have a higher chance of stunning. Being made of silver, your body is immune to spirits of the damned and runic golems." - prefix = "Silver" - special_names = list("Surfer", "Chariot", "Lining") - examine_limb_id = SPECIES_GOLEM - -/datum/species/golem/silver/on_species_gain(mob/living/carbon/C, datum/species/old_species) - ..() - ADD_TRAIT(C, TRAIT_HOLY, SPECIES_TRAIT) - -/datum/species/golem/silver/on_species_loss(mob/living/carbon/C) - REMOVE_TRAIT(C, TRAIT_HOLY, SPECIES_TRAIT) - ..() - -//Harder to stun, deals more damage, massively slowpokes, but gravproof and obstructive. Basically, The Wall. -/datum/species/golem/plasteel - name = "Plasteel Golem" - 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" - special_names = null - examine_limb_id = SPECIES_GOLEM - bodypart_overrides = list( - BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/golem/plasteel, - BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/golem/plasteel, - BODY_ZONE_HEAD = /obj/item/bodypart/head/golem, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/golem/plasteel, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/golem/plasteel, - BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem, - ) - -/datum/species/golem/plasteel/negates_gravity(mob/living/carbon/human/H) - return TRUE - -/datum/species/golem/plasteel/on_species_gain(mob/living/carbon/C, datum/species/old_species) - ..() - ADD_TRAIT(C, TRAIT_NOMOBSWAP, SPECIES_TRAIT) //THE WALL THE WALL THE WALL - -/datum/species/golem/plasteel/on_species_loss(mob/living/carbon/C) - REMOVE_TRAIT(C, TRAIT_NOMOBSWAP, SPECIES_TRAIT) //NOTHING ON ERF CAN MAKE IT FALL - ..() - -//Immune to ash storms -/datum/species/golem/titanium - name = "Titanium Golem" - id = SPECIES_GOLEM_TITANIUM - fixed_mut_color = "#ffffff" - meat = /obj/item/stack/ore/titanium - info_text = "As a Titanium Golem, you are immune to ash storms, and slightly more resistant to burn damage." - burnmod = 0.9 - prefix = "Titanium" - special_names = list("Dioxide") - examine_limb_id = SPECIES_GOLEM - -/datum/species/golem/titanium/on_species_gain(mob/living/carbon/C, datum/species/old_species) - . = ..() - ADD_TRAIT(C, TRAIT_ASHSTORM_IMMUNE, SPECIES_TRAIT) - -/datum/species/golem/titanium/on_species_loss(mob/living/carbon/C) - . = ..() - REMOVE_TRAIT(C, TRAIT_ASHSTORM_IMMUNE, SPECIES_TRAIT) - -//Immune to ash storms and lava -/datum/species/golem/plastitanium - name = "Plastitanium Golem" - id = SPECIES_GOLEM_PLASTITANIUM - fixed_mut_color = "#888888" - meat = /obj/item/stack/ore/titanium - info_text = "As a Plastitanium Golem, you are immune to both ash storms and lava, and slightly more resistant to burn damage." - burnmod = 0.8 - prefix = "Plastitanium" - special_names = null - examine_limb_id = SPECIES_GOLEM - -/datum/species/golem/plastitanium/on_species_gain(mob/living/carbon/C, datum/species/old_species) - . = ..() - C.add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE), SPECIES_TRAIT) - -/datum/species/golem/plastitanium/on_species_loss(mob/living/carbon/C) - . = ..() - C.remove_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE), SPECIES_TRAIT) - -//Fast and regenerates... but can only speak like an abductor -/datum/species/golem/alloy - name = "Alien Alloy Golem" - id = SPECIES_GOLEM_ALIEN - 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 - examine_limb_id = SPECIES_GOLEM - -//Regenerates because self-repairing super-advanced alien tech -/datum/species/golem/alloy/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) - if(H.stat == DEAD) - return - H.heal_overall_damage(brute = 1 * seconds_per_tick, burn = 1 * seconds_per_tick, required_bodytype = BODYTYPE_ORGANIC) - H.adjustToxLoss(-1 * seconds_per_tick) - H.adjustOxyLoss(-1 * seconds_per_tick) - -//Since this will usually be created from a collaboration between podpeople and free golems, wood golems are a mix between the two races -/datum/species/golem/wood - name = "Wood Golem" - id = SPECIES_GOLEM_WOOD - fixed_mut_color = "#9E704B" - meat = /obj/item/stack/sheet/mineral/wood - //Can burn and take damage from heat - inherent_traits = list( - TRAIT_GENELESS, - TRAIT_NOBREATH, - TRAIT_NODISMEMBER, - TRAIT_PIERCEIMMUNE, - TRAIT_RADIMMUNE, - TRAIT_RESISTCOLD, - TRAIT_RESISTLOWPRESSURE, - TRAIT_RESISTHIGHPRESSURE, - ) - inherent_biotypes = MOB_ORGANIC | MOB_HUMANOID | MOB_PLANT - armor = 30 - burnmod = 1.25 - heatmod = 1.5 - info_text = "As a Wooden Golem, you have plant-like traits: you take damage from extreme temperatures, can be set on fire, and have lower armor than a normal golem. You regenerate when in the light and wither in the darkness." - prefix = "Wooden" - special_names = list("Bark", "Willow", "Catalpa", "Woody", "Oak", "Sap", "Twig", "Branch", "Maple", "Birch", "Elm", "Basswood", "Cottonwood", "Larch", "Aspen", "Ash", "Beech", "Buckeye", "Cedar", "Chestnut", "Cypress", "Fir", "Hawthorn", "Hazel", "Hickory", "Ironwood", "Juniper", "Leaf", "Mangrove", "Palm", "Pawpaw", "Pine", "Poplar", "Redwood", "Redbud", "Sassafras", "Spruce", "Sumac", "Trunk", "Walnut", "Yew") - human_surname_chance = 0 - special_name_chance = 100 - inherent_factions = list(FACTION_PLANTS, FACTION_VINES) - examine_limb_id = SPECIES_GOLEM - -/datum/species/golem/wood/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) - if(H.stat == DEAD) - return - var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing - if(isturf(H.loc)) //else, there's considered to be no light - var/turf/T = H.loc - light_amount = min(1, T.get_lumcount()) - 0.5 - H.adjust_nutrition(5 * light_amount * seconds_per_tick) - if(H.nutrition > NUTRITION_LEVEL_ALMOST_FULL) - H.set_nutrition(NUTRITION_LEVEL_ALMOST_FULL) - if(light_amount > 0.2) //if there's enough light, heal - H.heal_overall_damage(brute = 0.5 * seconds_per_tick, burn = 0.5 * seconds_per_tick, required_bodytype = BODYTYPE_ORGANIC) - H.adjustToxLoss(-0.5 * seconds_per_tick) - H.adjustOxyLoss(-0.5 * seconds_per_tick) - - 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) - 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) - return TRUE - return ..() - -//Radioactive puncher, hits for burn but only as hard as human, slightly more durable against brute but less against everything else -/datum/species/golem/uranium - name = "Uranium Golem" - id = SPECIES_GOLEM_URANIUM - fixed_mut_color = "#77ff00" - meat = /obj/item/stack/ore/uranium - info_text = "As an Uranium Golem, your very touch burns and irradiates organic lifeforms. You don't hit as hard as most golems, but you are far more durable against blunt force trauma." - var/last_event = 0 - var/active = null - armor = 40 - brutemod = 0.5 - prefix = "Uranium" - special_names = list("Oxide", "Rod", "Meltdown", "235") - COOLDOWN_DECLARE(radiation_emission_cooldown) - examine_limb_id = SPECIES_GOLEM - bodypart_overrides = list( - BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/golem/uranium, - BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/golem/uranium, - BODY_ZONE_HEAD = /obj/item/bodypart/head/golem, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/golem, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/golem, - BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem, - ) - -/datum/species/golem/uranium/proc/radiation_emission(mob/living/carbon/human/H) - if(!COOLDOWN_FINISHED(src, radiation_emission_cooldown)) - return - else - radiation_pulse(H, max_range = 1, threshold = RAD_VERY_LIGHT_INSULATION, chance = 3) - COOLDOWN_START(src, radiation_emission_cooldown, 2 SECONDS) - -/datum/species/golem/uranium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) - ..() - if(COOLDOWN_FINISHED(src, radiation_emission_cooldown) && M != H && M.combat_mode) - radiation_emission(H) - -/datum/species/golem/uranium/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, mob/living/carbon/human/H) - ..() - if(COOLDOWN_FINISHED(src, radiation_emission_cooldown) && user != H) - radiation_emission(H) - -/datum/species/golem/uranium/on_hit(obj/projectile/P, mob/living/carbon/human/H) - ..() - if(COOLDOWN_FINISHED(src, radiation_emission_cooldown)) - radiation_emission(H) - -//Immune to physical bullets and resistant to brute, but very vulnerable to burn damage. Dusts on death. -/datum/species/golem/sand - name = "Sand Golem" - id = SPECIES_GOLEM_SAND - fixed_mut_color = "#ffdc8f" - meat = /obj/item/stack/ore/glass //this is sand - armor = 0 - burnmod = 3 //melts easily - brutemod = 0.25 - info_text = "As a Sand Golem, you are immune to physical bullets and take very little brute damage, but are extremely vulnerable to burn damage and energy weapons. You will also turn to sand when dying, preventing any form of recovery." - prefix = "Sand" - special_names = list("Castle", "Bag", "Dune", "Worm", "Storm") - examine_limb_id = SPECIES_GOLEM - -/datum/species/golem/sand/spec_death(gibbed, mob/living/carbon/human/H) - H.visible_message(span_danger("[H] turns into a pile of sand!")) - for(var/obj/item/W in H) - H.dropItemToGround(W) - for(var/i in 1 to rand(3,5)) - new /obj/item/stack/ore/glass(get_turf(H)) - qdel(H) - -/datum/species/golem/sand/bullet_act(obj/projectile/P, mob/living/carbon/human/H) - if(!(P.original == H && P.firer == H)) - if(P.armor_flag == BULLET || P.armor_flag == BOMB) - playsound(H, 'sound/effects/shovel_dig.ogg', 70, TRUE) - H.visible_message(span_danger("The [P.name] sinks harmlessly in [H]'s sandy body!"), \ - span_userdanger("The [P.name] sinks harmlessly in [H]'s sandy body!")) - return BULLET_ACT_BLOCK - return ..() - -//Reflects lasers and resistant to burn damage, but very vulnerable to brute damage. Shatters on death. -/datum/species/golem/glass - name = "Glass Golem" - id = SPECIES_GOLEM_GLASS - fixed_mut_color = "#5a96b4aa" //transparent body - meat = /obj/item/shard - armor = 0 - brutemod = 3 //very fragile - burnmod = 0.25 - info_text = "As a Glass Golem, you reflect lasers and energy weapons, and are very resistant to burn damage. However, you are extremely vulnerable to brute damage. On death, you'll shatter beyond any hope of recovery." - prefix = "Glass" - special_names = list("Lens", "Prism", "Fiber", "Bead") - examine_limb_id = SPECIES_GOLEM - -/datum/species/golem/glass/spec_death(gibbed, mob/living/carbon/human/H) - playsound(H, SFX_SHATTER, 70, TRUE) - H.visible_message(span_danger("[H] shatters!")) - for(var/obj/item/W in H) - H.dropItemToGround(W) - for(var/i in 1 to rand(3,5)) - new /obj/item/shard(get_turf(H)) - qdel(H) - -/datum/species/golem/glass/bullet_act(obj/projectile/P, mob/living/carbon/human/H) - if(!(P.original == H && P.firer == H)) //self-shots don't reflect - if(P.armor_flag == LASER || P.armor_flag == ENERGY) - H.visible_message(span_danger("The [P.name] gets reflected by [H]'s glass skin!"), \ - span_userdanger("The [P.name] gets reflected by [H]'s glass skin!")) - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - // redirect the projectile - P.firer = H - P.preparePixelProjectile(locate(clamp(new_x, 1, world.maxx), clamp(new_y, 1, world.maxy), H.z), H) - return BULLET_ACT_FORCE_PIERCE - return ..() - -//Teleports when hit or when it wants to -/datum/species/golem/bluespace - name = "Bluespace Golem" - id = SPECIES_GOLEM_BLUESPACE - fixed_mut_color = "#3333ff" - meat = /obj/item/stack/ore/bluespace_crystal - info_text = "As a Bluespace Golem, you are spatially unstable: You will teleport when hit, and you can teleport manually at a long distance." - prefix = "Bluespace" - special_names = list("Crystal", "Polycrystal") - examine_limb_id = SPECIES_GOLEM - - var/datum/action/cooldown/unstable_teleport/unstable_teleport - var/teleport_cooldown = 100 - var/last_teleport = 0 - -/datum/species/golem/bluespace/proc/reactive_teleport(mob/living/carbon/human/H) - H.visible_message(span_warning("[H] teleports!"), span_danger("You destabilize and teleport!")) - new /obj/effect/particle_effect/sparks(get_turf(H)) - playsound(get_turf(H), SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - do_teleport(H, get_turf(H), 6, asoundin = 'sound/weapons/emitter2.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) - last_teleport = world.time - -/datum/species/golem/bluespace/spec_hitby(atom/movable/AM, mob/living/carbon/human/H) - ..() - var/obj/item/I - if(isitem(AM)) - I = AM - if(I.thrownby == WEAKREF(H)) //No throwing stuff at yourself to trigger the teleport - return 0 - else - reactive_teleport(H) - -/datum/species/golem/bluespace/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) - ..() - if(world.time > last_teleport + teleport_cooldown && M != H && M.combat_mode) - reactive_teleport(H) - -/datum/species/golem/bluespace/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, mob/living/carbon/human/H) - ..() - if(world.time > last_teleport + teleport_cooldown && user != H) - reactive_teleport(H) - -/datum/species/golem/bluespace/on_hit(obj/projectile/P, mob/living/carbon/human/H) - ..() - if(world.time > last_teleport + teleport_cooldown) - reactive_teleport(H) - -/datum/species/golem/bluespace/on_species_gain(mob/living/carbon/C, datum/species/old_species) - ..() - if(ishuman(C)) - unstable_teleport = new - unstable_teleport.Grant(C) - last_teleport = world.time - -/datum/species/golem/bluespace/on_species_loss(mob/living/carbon/C) - if(unstable_teleport) - unstable_teleport.Remove(C) - ..() - -/datum/action/cooldown/unstable_teleport - name = "Unstable Teleport" - check_flags = AB_CHECK_CONSCIOUS - button_icon_state = "jaunt" - button_icon = 'icons/mob/actions/actions_spells.dmi' - cooldown_time = 17.5 SECONDS - -/datum/action/cooldown/unstable_teleport/Activate() - var/mob/living/carbon/human/H = owner - H.visible_message(span_warning("[H] starts vibrating!"), span_danger("You start charging your bluespace core...")) - playsound(get_turf(H), 'sound/weapons/flash.ogg', 25, TRUE) - addtimer(CALLBACK(src, PROC_REF(teleport), H), 1.5 SECONDS) - return TRUE - -/datum/action/cooldown/unstable_teleport/proc/teleport(mob/living/carbon/human/H) - StartCooldown() - H.visible_message(span_warning("[H] disappears in a shower of sparks!"), span_danger("You teleport!")) - var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread - spark_system.set_up(10, 0, src) - spark_system.attach(H) - spark_system.start() - do_teleport(H, get_turf(H), 12, asoundin = 'sound/weapons/emitter2.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) - -//honk -/datum/species/golem/bananium - name = "Bananium Golem" - id = SPECIES_GOLEM_BANANIUM - fixed_mut_color = "#ffff00" - inherent_traits = list( - TRAIT_CLUMSY, - TRAIT_GENELESS, - TRAIT_NOBREATH, - TRAIT_NODISMEMBER, - TRAIT_NOFIRE, - TRAIT_PIERCEIMMUNE, - TRAIT_RADIMMUNE, - TRAIT_RESISTCOLD, - TRAIT_RESISTHEAT, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_RESISTLOWPRESSURE, - ) - mutanttongue = /obj/item/organ/internal/tongue/bananium - meat = /obj/item/stack/ore/bananium - info_text = "As a Bananium Golem, you are made for pranking. Your body emits natural honks, and you can barely even hurt people when punching them. Your skin also bleeds banana peels when damaged." - prefix = "Bananium" - special_names = null - examine_limb_id = SPECIES_GOLEM - bodypart_overrides = list( - BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/golem/bananium, - BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/golem/bananium, - BODY_ZONE_HEAD = /obj/item/bodypart/head/golem, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/golem/bananium, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/golem/bananium, - BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem, - ) - - /// Cooldown for producing honks - COOLDOWN_DECLARE(honkooldown) - /// Cooldown for producing bananas - COOLDOWN_DECLARE(banana_cooldown) - /// Time between possible banana productions - var/banana_delay = 10 SECONDS - /// Same as the uranium golem. I'm pretty sure this is vestigial. - var/active = FALSE - -/datum/species/golem/bananium/on_species_gain(mob/living/carbon/C, datum/species/old_species) - ..() - COOLDOWN_START(src, honkooldown, 0) - COOLDOWN_START(src, banana_cooldown, banana_delay) - RegisterSignal(C, COMSIG_MOB_SAY, PROC_REF(handle_speech)) - var/obj/item/organ/internal/liver/liver = C.get_organ_slot(ORGAN_SLOT_LIVER) - if(liver) - ADD_TRAIT(liver, TRAIT_COMEDY_METABOLISM, SPECIES_TRAIT) - -/datum/species/golem/bananium/on_species_loss(mob/living/carbon/C) - . = ..() - UnregisterSignal(C, COMSIG_MOB_SAY) - - var/obj/item/organ/internal/liver/liver = C.get_organ_slot(ORGAN_SLOT_LIVER) - if(liver) - REMOVE_TRAIT(liver, TRAIT_COMEDY_METABOLISM, SPECIES_TRAIT) - -/datum/species/golem/bananium/random_name(gender,unique,lastname) - var/clown_name = pick(GLOB.clown_names) - var/golem_name = "[uppertext(clown_name)]" - return golem_name - -/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) - ..() - if(COOLDOWN_FINISHED(src, banana_cooldown) && M != H && M.combat_mode) - new /obj/item/grown/bananapeel/specialpeel(get_turf(H)) - COOLDOWN_START(src, banana_cooldown, banana_delay) - -/datum/species/golem/bananium/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, mob/living/carbon/human/H) - ..() - if((user != H) && COOLDOWN_FINISHED(src, banana_cooldown)) - new /obj/item/grown/bananapeel/specialpeel(get_turf(H)) - COOLDOWN_START(src, banana_cooldown, banana_delay) - -/datum/species/golem/bananium/on_hit(obj/projectile/P, mob/living/carbon/human/H) - ..() - if(COOLDOWN_FINISHED(src, banana_cooldown)) - new /obj/item/grown/bananapeel/specialpeel(get_turf(H)) - COOLDOWN_START(src, banana_cooldown, banana_delay) - -/datum/species/golem/bananium/spec_hitby(atom/movable/AM, mob/living/carbon/human/H) - ..() - var/obj/item/I - if(isitem(AM)) - I = AM - if(I.thrownby == WEAKREF(H)) //No throwing stuff at yourself to make bananas - return 0 - else - new/obj/item/grown/bananapeel/specialpeel(get_turf(H)) - COOLDOWN_START(src, banana_cooldown, banana_delay) - -/datum/species/golem/bananium/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) - if(!active && COOLDOWN_FINISHED(src, honkooldown)) - active = TRUE - playsound(get_turf(H), 'sound/items/bikehorn.ogg', 50, TRUE) - COOLDOWN_START(src, honkooldown, rand(2 SECONDS, 8 SECONDS)) - active = FALSE - ..() - -/datum/species/golem/bananium/spec_death(gibbed, mob/living/carbon/human/H) - playsound(get_turf(H), 'sound/misc/sadtrombone.ogg', 70, FALSE) - -/datum/species/golem/bananium/proc/handle_speech(datum/source, list/speech_args) - SIGNAL_HANDLER - speech_args[SPEECH_SPANS] |= SPAN_CLOWN - -/datum/species/golem/runic - name = "Runic Golem" - 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_GENELESS, - TRAIT_NOBREATH, - TRAIT_NODISMEMBER, - TRAIT_NOFIRE, - TRAIT_NOFLASH, - TRAIT_PIERCEIMMUNE, - TRAIT_RADIMMUNE, - TRAIT_RESISTHEAT, - TRAIT_RESISTCOLD, - TRAIT_RESISTLOWPRESSURE, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_NOBLOOD, - ) - inherent_biotypes = MOB_HUMANOID|MOB_MINERAL - prefix = "Runic" - special_names = null - inherent_factions = list(FACTION_CULT) - species_language_holder = /datum/language_holder/golem/runic - bodypart_overrides = list( - BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/golem/cult, - BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/golem/cult, - BODY_ZONE_HEAD = /obj/item/bodypart/head/golem/cult, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/golem/cult, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/golem/cult, - BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem/cult, - ) - - /// A ref to our jaunt spell that we get on species gain. - var/datum/action/cooldown/spell/jaunt/ethereal_jaunt/shift/golem/jaunt - /// A ref to our gaze spell that we get on species gain. - var/datum/action/cooldown/spell/pointed/abyssal_gaze/abyssal_gaze - /// A ref to our dominate spell that we get on species gain. - var/datum/action/cooldown/spell/pointed/dominate/dominate - -/datum/species/golem/runic/random_name(gender,unique,lastname) - var/edgy_first_name = pick("Razor","Blood","Dark","Evil","Cold","Pale","Black","Silent","Chaos","Deadly","Coldsteel") - var/edgy_last_name = pick("Edge","Night","Death","Razor","Blade","Steel","Calamity","Twilight","Shadow","Nightmare") //dammit Razor Razor - var/golem_name = "[edgy_first_name] [edgy_last_name]" - return golem_name - -/datum/species/golem/runic/on_species_gain(mob/living/carbon/grant_to, datum/species/old_species) - . = ..() - // Create our species specific spells here. - // Note we link them to the mob, not the mind, - // so they're not moved around on mindswaps - jaunt = new(grant_to) - jaunt.StartCooldown() - jaunt.Grant(grant_to) - - abyssal_gaze = new(grant_to) - abyssal_gaze.StartCooldown() - abyssal_gaze.Grant(grant_to) - - dominate = new(grant_to) - dominate.StartCooldown() - dominate.Grant(grant_to) - -/datum/species/golem/runic/on_species_loss(mob/living/carbon/C) - // Aaand cleanup our species specific spells. - // No free rides. - QDEL_NULL(jaunt) - QDEL_NULL(abyssal_gaze) - QDEL_NULL(dominate) - return ..() - -/datum/species/golem/runic/handle_chemicals(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) - H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick) - - if(chem.type == /datum/reagent/fuel/unholywater) - H.adjustBruteLoss(-4 * REM * seconds_per_tick) - H.adjustFireLoss(-4 * REM * seconds_per_tick) - H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick) - -/datum/species/golem/cloth - name = "Cloth Golem" - id = SPECIES_GOLEM_CLOTH - 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_ADVANCEDTOOLUSER, - TRAIT_CAN_STRIP, - TRAIT_GENELESS, - TRAIT_LITERATE, - TRAIT_NOBREATH, - TRAIT_NODISMEMBER, - TRAIT_PIERCEIMMUNE, - TRAIT_RADIMMUNE, - TRAIT_RESISTCOLD, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_RESISTLOWPRESSURE, - TRAIT_NOBLOOD, - ) - 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( - BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/golem/cloth, - BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/golem/cloth, - BODY_ZONE_HEAD = /obj/item/bodypart/head/golem/cloth, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/golem/cloth, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/golem/cloth, - BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem/cloth, - ) - -/datum/species/golem/cloth/on_species_gain(mob/living/carbon/C, datum/species/old_species) - ..() - ADD_TRAIT(C, TRAIT_HOLY, SPECIES_TRAIT) - -/datum/species/golem/cloth/on_species_loss(mob/living/carbon/C) - REMOVE_TRAIT(C, TRAIT_HOLY, SPECIES_TRAIT) - ..() - -/datum/species/golem/cloth/check_roundstart_eligible() - if(check_holidays(HALLOWEEN)) - return TRUE - return ..() - -/datum/species/golem/cloth/random_name(gender,unique,lastname) - var/pharaoh_name = pick("Neferkare", "Hudjefa", "Khufu", "Mentuhotep", "Ahmose", "Amenhotep", "Thutmose", "Hatshepsut", "Tutankhamun", "Ramses", "Seti", \ - "Merenptah", "Djer", "Semerkhet", "Nynetjer", "Khafre", "Pepi", "Intef", "Ay") //yes, Ay was an actual pharaoh - var/golem_name = "[pharaoh_name] \Roman[rand(1,99)]" - return golem_name - -/datum/species/golem/cloth/spec_life(mob/living/carbon/human/H) - if(H.fire_stacks < 1) - H.adjust_fire_stacks(1) //always prone to burning - ..() - -/datum/species/golem/cloth/spec_death(gibbed, mob/living/carbon/human/H) - if(gibbed) - return - if(H.on_fire) - H.visible_message(span_danger("[H] burns into ash!")) - H.dust(just_ash = TRUE) - return - - H.visible_message(span_danger("[H] falls apart into a pile of bandages!")) - new /obj/structure/cloth_pile(get_turf(H), H) - ..() - -/datum/species/golem/cloth/get_species_description() - return "A wrapped up Mummy! They descend upon Space Station Thirteen every year to spook the crew! \"Return the slab!\"" - -/datum/species/golem/cloth/get_species_lore() - return list( - "Mummies are very self conscious. They're shaped weird, they walk slow, and worst of all, \ - they're considered the laziest halloween costume. But that's not even true, they say.", - - "Making a mummy costume may be easy, but making a CONVINCING mummy costume requires \ - things like proper fabric and purposeful staining to achieve the look. Which is FAR from easy. Gosh.", - ) - -// Calls parent, as Golems have a species-wide perk we care about. -/datum/species/golem/cloth/create_pref_unique_perks() - var/list/to_add = ..() - to_add += list(list( SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, - SPECIES_PERK_ICON = "recycle", - SPECIES_PERK_NAME = "Reformation", - SPECIES_PERK_DESC = "A boon quite similar to Ethereals, Mummies collapse into \ - a pile of bandages after they die. If left alone, they will reform back \ - into themselves. The bandages themselves are very vulnerable to fire.", + SPECIES_PERK_ICON = "gem", + SPECIES_PERK_NAME = "Metamorphic Rock", + SPECIES_PERK_DESC = "Consuming minerals can grant Lithoids temporary benefits based on the type consumed.", )) - return to_add - -// Override to add a perk elaborating on just how dangerous fire is. -/datum/species/golem/cloth/create_pref_temperature_perks() - var/list/to_add = list() + to_add += list(list( + SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, + SPECIES_PERK_ICON = "pickaxe", + SPECIES_PERK_NAME = "Natural Miners", + SPECIES_PERK_DESC = "Golems can see dimly in the dark, sense minerals, and mine stone with their bare hands. \ + They can even smelt ores in an internal furnace, if their surrounding environment is hot enough.", + )) to_add += list(list( SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, - SPECIES_PERK_ICON = "fire-alt", - SPECIES_PERK_NAME = "Incredibly Flammable", - SPECIES_PERK_DESC = "Mummies are made entirely of cloth, which makes them \ - very vulnerable to fire. They will not reform if they die while on \ - fire, and they will easily catch alight. If your bandages burn to ash, you're toast!", + SPECIES_PERK_ICON = "bolt", + SPECIES_PERK_NAME = "Anima", + SPECIES_PERK_DESC = "Maintaining the force animating stone is taxing. Lithoids must eat frequently \ + in order to avoid returning to inanimate statues, and only derive nutrition from eating minerals.", )) return to_add -/obj/structure/cloth_pile - name = "pile of bandages" - desc = "It emits a strange aura, as if there was still life within it..." - max_integrity = 50 - armor_type = /datum/armor/structure_cloth_pile - icon = 'icons/obj/objects.dmi' - icon_state = "pile_bandages" - resistance_flags = FLAMMABLE - - var/revive_time = 90 SECONDS - var/mob/living/carbon/human/cloth_golem - -/datum/armor/structure_cloth_pile - melee = 90 - bullet = 90 - laser = 25 - energy = 80 - bomb = 50 - fire = -50 - acid = -50 - -/obj/structure/cloth_pile/Initialize(mapload, mob/living/carbon/human/H) - . = ..() - if(!QDELETED(H) && is_species(H, /datum/species/golem/cloth)) - H.unequip_everything() - H.forceMove(src) - cloth_golem = H - to_chat(cloth_golem, span_notice("You start gathering your life energy, preparing to rise again...")) - addtimer(CALLBACK(src, PROC_REF(revive)), revive_time) - else - return INITIALIZE_HINT_QDEL - -/obj/structure/cloth_pile/Destroy() - if(cloth_golem) - QDEL_NULL(cloth_golem) - return ..() - -/obj/structure/cloth_pile/burn() - visible_message(span_danger("[src] burns into ash!")) - new /obj/effect/decal/cleanable/ash(get_turf(src)) - ..() - -/obj/structure/cloth_pile/proc/revive() - if(QDELETED(src) || QDELETED(cloth_golem)) //QDELETED also checks for null, so if no cloth golem is set this won't runtime - return - if(HAS_TRAIT_FROM_ONLY(cloth_golem, TRAIT_SUICIDED, REF(cloth_golem))) - QDEL_NULL(cloth_golem) - return - - invisibility = INVISIBILITY_MAXIMUM //disappear before the animation - new /obj/effect/temp_visual/mummy_animation(get_turf(src)) - cloth_golem.revive(ADMIN_HEAL_ALL) - sleep(2 SECONDS) - cloth_golem.forceMove(get_turf(src)) - cloth_golem.visible_message(span_danger("[src] rises and reforms into [cloth_golem]!"),span_userdanger("You reform into yourself!")) - cloth_golem = null - qdel(src) - -/obj/structure/cloth_pile/attackby(obj/item/P, mob/living/carbon/human/user, params) - . = ..() - - if(resistance_flags & ON_FIRE) - return - - if(P.get_temperature()) - visible_message(span_danger("[src] bursts into flames!")) - fire_act() - -/datum/species/golem/plastic - name = "Plastic Golem" - id = SPECIES_GOLEM_PLASTIC - inherent_traits = list( - TRAIT_ADVANCEDTOOLUSER, - TRAIT_CAN_STRIP, - TRAIT_GENELESS, - TRAIT_LITERATE, - TRAIT_NOBREATH, - TRAIT_NODISMEMBER, - TRAIT_NOFIRE, - TRAIT_PIERCEIMMUNE, - TRAIT_RADIMMUNE, - TRAIT_RESISTCOLD, - TRAIT_RESISTHEAT, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_RESISTLOWPRESSURE, - TRAIT_VENTCRAWLER_NUDE, - ) - prefix = "Plastic" - special_names = list("Sheet", "Bag", "Bottle") - fixed_mut_color = "fffa" - info_text = "As a Plastic Golem, you are capable of ventcrawling and passing through plastic flaps as long as you are naked." - examine_limb_id = SPECIES_GOLEM - -/datum/species/golem/bronze - name = "Bronze Golem" - id = SPECIES_GOLEM_BRONZE - prefix = "Bronze" - 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 - var/gong_cooldown = 150 - -/datum/species/golem/bronze/bullet_act(obj/projectile/P, mob/living/carbon/human/H) - if(!(world.time > last_gong_time + gong_cooldown)) - return ..() - if(P.armor_flag == BULLET || P.armor_flag == BOMB) - gong(H) - return ..() - -/datum/species/golem/bronze/spec_hitby(atom/movable/AM, mob/living/carbon/human/H) - ..() - if(world.time > last_gong_time + gong_cooldown) - gong(H) - -/datum/species/golem/bronze/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) - ..() - if(world.time > last_gong_time + gong_cooldown && M.combat_mode) - gong(H) - -/datum/species/golem/bronze/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, mob/living/carbon/human/H) - ..() - if(world.time > last_gong_time + gong_cooldown) - gong(H) - -/datum/species/golem/bronze/on_hit(obj/projectile/P, mob/living/carbon/human/H) - ..() - if(world.time > last_gong_time + gong_cooldown) - gong(H) - -/datum/species/golem/bronze/proc/gong(mob/living/carbon/human/H) - last_gong_time = world.time - for(var/mob/living/M in get_hearers_in_view(7,H)) - if(M.stat == DEAD) //F - continue - if(M == H) - H.show_message(span_narsiesmall("You cringe with pain as your body rings around you!"), MSG_AUDIBLE) - H.playsound_local(H, 'sound/effects/gong.ogg', 100, TRUE) - H.soundbang_act(2, 0, 100, 1) - H.adjust_jitter(14 SECONDS) - var/distance = max(0,get_dist(get_turf(H),get_turf(M))) - switch(distance) - if(0 to 1) - M.show_message(span_narsiesmall("GONG!"), MSG_AUDIBLE) - M.playsound_local(H, 'sound/effects/gong.ogg', 100, TRUE) - M.soundbang_act(1, 0, 30, 3) - M.adjust_confusion(10 SECONDS) - M.adjust_jitter(8 SECONDS) - M.add_mood_event("gonged", /datum/mood_event/loud_gong) - if(2 to 3) - M.show_message(span_cult("GONG!"), MSG_AUDIBLE) - M.playsound_local(H, 'sound/effects/gong.ogg', 75, TRUE) - M.soundbang_act(1, 0, 15, 2) - M.adjust_jitter(6 SECONDS) - M.add_mood_event("gonged", /datum/mood_event/loud_gong) - else - M.show_message(span_warning("GONG!"), MSG_AUDIBLE) - M.playsound_local(H, 'sound/effects/gong.ogg', 50, TRUE) - - -/datum/species/golem/cardboard //Faster but weaker, can also make new shells on its own - name = "Cardboard Golem" - id = SPECIES_GOLEM_CARDBOARD - 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_ADVANCEDTOOLUSER, - TRAIT_CAN_STRIP, - TRAIT_GENELESS, - TRAIT_LITERATE, - TRAIT_NOBREATH, - TRAIT_NODISMEMBER, - TRAIT_NOFLASH, - TRAIT_PIERCEIMMUNE, - TRAIT_RADIMMUNE, - TRAIT_RESISTCOLD, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_RESISTLOWPRESSURE, - TRAIT_NOBLOOD, - ) - mutanttongue = null - fixed_mut_color = null - 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, - BODY_ZONE_HEAD = /obj/item/bodypart/head/golem/cardboard, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/golem/cardboard, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/golem/cardboard, - BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem/cardboard, - ) - var/last_creation = 0 - var/brother_creation_cooldown = 300 - -/datum/species/golem/cardboard/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, mob/living/carbon/human/H) - . = ..() - if(user != H) - return FALSE //forced reproduction is rape. - if(istype(I, /obj/item/stack/sheet/cardboard)) - var/obj/item/stack/sheet/cardboard/C = I - if(last_creation + brother_creation_cooldown > world.time) //no cheesing dork - return - if(C.amount < 10) - to_chat(H, span_warning("You do not have enough cardboard!")) - return FALSE - to_chat(H, span_notice("You attempt to create a new cardboard brother.")) - if(do_after(user, 30, target = user)) - if(last_creation + brother_creation_cooldown > world.time) //no cheesing dork - return - if(!C.use(10)) - to_chat(H, span_warning("You do not have enough cardboard!")) - return FALSE - to_chat(H, span_notice("You create a new cardboard golem shell.")) - create_brother(H, H.loc) - -/datum/species/golem/cardboard/proc/create_brother(mob/living/carbon/human/golem, atom/location) - var/mob/living/master = golem.mind.enslaved_to?.resolve() - if(master) - new /obj/effect/mob_spawn/ghost_role/human/golem/servant(location, /datum/species/golem/cardboard, master) - else - new /obj/effect/mob_spawn/ghost_role/human/golem(location, /datum/species/golem/cardboard) - - last_creation = world.time - -/datum/species/golem/leather - name = "Leather Golem" - id = SPECIES_GOLEM_LEATHER - special_names = list("Face", "Man", "Belt") //Ah dude 4 strength 4 stam leather belt AHHH - inherent_traits = list( - TRAIT_ADVANCEDTOOLUSER, - TRAIT_CAN_STRIP, - TRAIT_GENELESS, - TRAIT_LITERATE, - TRAIT_NOBREATH, - TRAIT_NODISMEMBER, - TRAIT_PIERCEIMMUNE, - TRAIT_RADIMMUNE, - TRAIT_RESISTCOLD, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_RESISTLOWPRESSURE, - TRAIT_STRONG_GRABBER, - ) - prefix = "Leather" - fixed_mut_color = "#624a2e" - info_text = "As a Leather Golem, you are flammable, but you can grab things with incredible ease, allowing all your grabs to start at a strong level." - grab_sound = 'sound/weapons/whipgrab.ogg' - examine_limb_id = SPECIES_GOLEM - -/datum/species/golem/durathread - name = "Durathread Golem" - 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_ADVANCEDTOOLUSER, - TRAIT_CAN_STRIP, - TRAIT_GENELESS, - TRAIT_LITERATE, - TRAIT_NOBREATH, - TRAIT_NODISMEMBER, - TRAIT_NOFLASH, - TRAIT_PIERCEIMMUNE, - TRAIT_RADIMMUNE, - TRAIT_RESISTCOLD, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_RESISTLOWPRESSURE, - TRAIT_NOBLOOD, - ) - info_text = "As a Durathread Golem, your strikes will cause those your targets to start choking, but your woven body won't withstand fire as well." - bodypart_overrides = list( - BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/golem/durathread, - BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/golem/durathread, - BODY_ZONE_HEAD = /obj/item/bodypart/head/golem/durathread, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/golem/durathread, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/golem/durathread, - BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem/durathread, - ) - -/datum/species/golem/durathread/spec_unarmedattacked(mob/living/carbon/human/user, mob/living/carbon/human/target) - . = ..() - target.apply_status_effect(/datum/status_effect/strandling) - -/datum/species/golem/bone - name = "Bone Golem" - 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 - sexes = FALSE - fixed_mut_color = null - species_traits = list( - NO_UNDERWEAR, - NOEYESPRITES, - ) - inherent_traits = list( - TRAIT_ADVANCEDTOOLUSER, - TRAIT_CAN_STRIP, - TRAIT_FAKEDEATH, - TRAIT_GENELESS, - TRAIT_LITERATE, - TRAIT_NOBREATH, - TRAIT_NOFIRE, - TRAIT_NODISMEMBER, - TRAIT_NOFLASH, - TRAIT_PIERCEIMMUNE, - TRAIT_RADIMMUNE, - TRAIT_RESISTCOLD, - TRAIT_RESISTHEAT, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_RESISTLOWPRESSURE, - TRAIT_NOBLOOD, - ) - species_language_holder = /datum/language_holder/golem/bone - info_text = "As a Bone Golem, You have a powerful spell that lets you chill your enemies with fear, and milk heals you! Just make sure to watch our for bone-hurting juice." - bodypart_overrides = list( - BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/golem/bone, - BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/golem/bone, - BODY_ZONE_HEAD = /obj/item/bodypart/head/golem/bone, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/golem/bone, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/golem/bone, - BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem/bone, - ) - var/datum/action/innate/bonechill/bonechill - -/datum/species/golem/bone/on_species_gain(mob/living/carbon/C, datum/species/old_species) - ..() - if(ishuman(C)) - bonechill = new - bonechill.Grant(C) - -/datum/species/golem/bone/on_species_loss(mob/living/carbon/C) - if(bonechill) - bonechill.Remove(C) - ..() - -/datum/species/golem/bone/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired) - . = ..() - if(chem.type == /datum/reagent/toxin/bonehurtingjuice) - H.adjustStaminaLoss(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/action/innate/bonechill - name = "Bone Chill" - desc = "Rattle your bones and strike fear into your enemies!" - check_flags = AB_CHECK_CONSCIOUS - button_icon = 'icons/mob/actions/actions_spells.dmi' - button_icon_state = "bonechill" - var/cooldown = 600 - var/last_use - var/snas_chance = 3 - -/datum/action/innate/bonechill/Activate() - if(world.time < last_use + cooldown) - to_chat(owner, span_warning("You aren't ready yet to rattle your bones again!")) - return - owner.visible_message(span_warning("[owner] rattles [owner.p_their()] bones harrowingly."), span_notice("You rattle your bones")) - last_use = world.time - if(prob(snas_chance)) - playsound(get_turf(owner),'sound/magic/RATTLEMEBONES2.ogg', 100) - if(ishuman(owner)) - var/mob/living/carbon/human/H = owner - var/mutable_appearance/badtime = mutable_appearance('icons/mob/species/human/bodyparts.dmi', "b_golem_eyes", -FIRE_LAYER-0.5) - badtime.appearance_flags = RESET_COLOR - H.overlays_standing[FIRE_LAYER+0.5] = badtime - H.apply_overlay(FIRE_LAYER+0.5) - addtimer(CALLBACK(H, TYPE_PROC_REF(/mob/living/carbon/, remove_overlay), FIRE_LAYER+0.5), 25) - else - playsound(get_turf(owner),'sound/magic/RATTLEMEBONES.ogg', 100) - for(var/mob/living/L in orange(7, get_turf(owner))) - if((L.mob_biotypes & MOB_UNDEAD) || isgolem(L) || HAS_TRAIT(L, TRAIT_RESISTCOLD)) - continue //Do not affect our brothers - - to_chat(L, span_cultlarge("A spine-chilling sound chills you to the bone!")) - L.apply_status_effect(/datum/status_effect/bonechill) - L.add_mood_event("spooked", /datum/mood_event/spooked) - -/datum/species/golem/snow - name = "Snow Golem" - id = SPECIES_GOLEM_SNOW - fixed_mut_color = null //custom sprites - armor = 45 //down from 55 - burnmod = 3 //melts easily - 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_ADVANCEDTOOLUSER, - TRAIT_CAN_STRIP, - TRAIT_GENELESS, - TRAIT_LITERATE, - TRAIT_NOBREATH, - TRAIT_NODISMEMBER, - TRAIT_PIERCEIMMUNE, - TRAIT_RADIMMUNE, - TRAIT_RESISTCOLD, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_RESISTLOWPRESSURE, - TRAIT_NOBLOOD, - ) - bodypart_overrides = list( - BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/golem/snow, - BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/golem/snow, - BODY_ZONE_HEAD = /obj/item/bodypart/head/golem/snow, - BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/golem/snow, - BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/golem/snow, - BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem/snow, - ) - - /// A ref to our "throw snowball" spell we get on species gain. - var/datum/action/cooldown/spell/conjure_item/snowball/snowball - /// A ref to our cryobeam spell we get on species gain. - var/datum/action/cooldown/spell/pointed/projectile/cryo/cryo - -/datum/species/golem/snow/spec_death(gibbed, mob/living/carbon/human/H) - H.visible_message(span_danger("[H] turns into a pile of snow!")) - for(var/obj/item/W in H) - H.dropItemToGround(W) - for(var/i in 1 to rand(3,5)) - new /obj/item/stack/sheet/mineral/snow(get_turf(H)) - new /obj/item/food/grown/carrot(get_turf(H)) - qdel(H) - -/datum/species/golem/snow/on_species_gain(mob/living/carbon/grant_to, datum/species/old_species) - . = ..() - ADD_TRAIT(grant_to, TRAIT_SNOWSTORM_IMMUNE, SPECIES_TRAIT) - - snowball = new(grant_to) - snowball.StartCooldown() - snowball.Grant(grant_to) - - cryo = new(grant_to) - cryo.StartCooldown() - cryo.Grant(grant_to) - -/datum/species/golem/snow/on_species_loss(mob/living/carbon/remove_from) - REMOVE_TRAIT(remove_from, TRAIT_SNOWSTORM_IMMUNE, SPECIES_TRAIT) - QDEL_NULL(snowball) - QDEL_NULL(cryo) - return ..() - -/datum/species/golem/mhydrogen //Effectively most other metal-based golem types rolled into one - immune to all weather, lava, flashes, and magic, while being just as hardened as diamond golems. - name = "Metallic Hydrogen Golem" - id = SPECIES_GOLEM_HYDROGEN - fixed_mut_color = "#535469" - armor = 70 //equal to a diamond golem - info_text = "As a Metallic Hydrogen Golem, you were forged in the highest pressures and the highest heats. Your unique material makeup makes you immune to magic and most environmental damage, while helping you resist most other attacks." - prefix = "Metallic Hydrogen" - special_names = list("Pressure","Crush") - inherent_traits = list( - TRAIT_GENELESS, - TRAIT_NOBREATH, - TRAIT_NODISMEMBER, - TRAIT_NOFIRE, - TRAIT_NOFLASH, - TRAIT_PIERCEIMMUNE, - TRAIT_RADIMMUNE, - TRAIT_RESISTCOLD, - TRAIT_RESISTHEAT, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_RESISTLOWPRESSURE, - TRAIT_NOBLOOD, - TRAIT_ADVANCEDTOOLUSER, - TRAIT_CAN_STRIP, - TRAIT_LITERATE, - TRAIT_WEATHER_IMMUNE, - TRAIT_LAVA_IMMUNE, - ) - examine_limb_id = SPECIES_GOLEM - -/datum/species/golem/mhydrogen/on_species_gain(mob/living/carbon/C, datum/species/old_species) - . = ..() - ADD_TRAIT(C, TRAIT_ANTIMAGIC, SPECIES_TRAIT) - -/datum/species/golem/mhydrogen/on_species_loss(mob/living/carbon/C) - REMOVE_TRAIT(C, TRAIT_ANTIMAGIC, SPECIES_TRAIT) +/// Remove nutrient value from non-mineral food, wish this was on an organ and not species but such is life +/datum/species/golem/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, delta_time, times_fired) + if (istype(chem, /datum/reagent/consumable) && !istype(chem, /datum/reagent/consumable/nutriment/mineral)) + var/datum/reagent/consumable/yummy_chem = chem + yummy_chem.nutriment_factor = 0 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 1dbe2d34189..aa14852dd98 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -39,7 +39,7 @@ digitigrade_customization = DIGITIGRADE_OPTIONAL // Lizards are coldblooded and can stand a greater temperature range than humans - 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 bodytemp_cold_damage_limit = (BODYTEMP_COLD_DAMAGE_LIMIT - 10) ass_image = 'icons/ass/asslizard.png' 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 f4889c352a7..34f0310c39b 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -14,6 +14,7 @@ TRAIT_RADIMMUNE, TRAIT_RESISTCOLD, TRAIT_NOBLOOD, + TRAIT_NO_DEBRAIN_OVERLAY, ) inherent_biotypes = MOB_HUMANOID|MOB_MINERAL 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 d96be568b44..73a41863145 100644 --- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm +++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm @@ -28,6 +28,7 @@ TRAIT_TOXIMMUNE, TRAIT_XENO_IMMUNE, TRAIT_NOBLOOD, + TRAIT_NO_DEBRAIN_OVERLAY, ) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutanttongue = /obj/item/organ/internal/tongue/bone diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 03b69159c06..479a468dc6c 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -537,3 +537,10 @@ for(var/reagent in reagents) var/datum/reagent/R = reagent . |= R.expose_mob(src, methods, reagents[R], show_message, touch_protection) + +/// Simplified ricochet angle calculation for mobs (also the base version doesn't work on mobs) +/mob/living/handle_ricochet(obj/projectile/ricocheting_projectile) + var/face_angle = get_angle_raw(ricocheting_projectile.x, ricocheting_projectile.pixel_x, ricocheting_projectile.pixel_y, ricocheting_projectile.p_y, x, y, pixel_x, pixel_y) + var/new_angle_s = SIMPLIFY_DEGREES(face_angle + GET_ANGLE_OF_INCIDENCE(face_angle, (ricocheting_projectile.Angle + 180))) + ricocheting_projectile.set_angle(new_angle_s) + return TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 4830aa995bc..bbea6b6fe00 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -151,13 +151,12 @@ icon_state = initial(icon_state) /mob/living/simple_animal/hostile/megafauna/colossus/proc/enrage(mob/living/victim) - if(ishuman(victim)) - var/mob/living/carbon/human/human_victim = victim - if(human_victim.mind) - if(istype(human_victim.mind.martial_art, /datum/martial_art/the_sleeping_carp)) - . = TRUE - if (is_species(human_victim, /datum/species/golem/sand)) - . = TRUE + if(!ishuman(victim)) + return FALSE + if(isgolem(victim) && victim.has_status_effect(/datum/status_effect/golem/gold)) + return TRUE + var/mob/living/carbon/human/human_victim = victim + return human_victim.mind && istype(human_victim.mind.martial_art, /datum/martial_art/the_sleeping_carp) /mob/living/simple_animal/hostile/megafauna/colossus/devour(mob/living/victim) visible_message(span_colossus("[src] disintegrates [victim]!")) diff --git a/code/modules/mob_spawn/corpses/mining_corpses.dm b/code/modules/mob_spawn/corpses/mining_corpses.dm index c6e7525a92c..f43351f8261 100644 --- a/code/modules/mob_spawn/corpses/mining_corpses.dm +++ b/code/modules/mob_spawn/corpses/mining_corpses.dm @@ -201,16 +201,7 @@ /datum/outfit/consumed_golem/pre_equip(mob/living/carbon/human/golem, visualsOnly = FALSE) if(!visualsOnly) - golem.set_species(pick( - /datum/species/golem/adamantine, - /datum/species/golem/diamond, - /datum/species/golem/gold, - /datum/species/golem/plasma, - /datum/species/golem/plasteel, - /datum/species/golem/plastitanium, - /datum/species/golem/silver, - /datum/species/golem/titanium, - )) + golem.set_species(/datum/species/golem) if(prob(30)) glasses = pick_weight(list( /obj/item/clothing/glasses/hud/diagnostic = 2, diff --git a/code/modules/mob_spawn/ghost_roles/golem_roles.dm b/code/modules/mob_spawn/ghost_roles/golem_roles.dm index 483646f98ad..9feff309ef4 100644 --- a/code/modules/mob_spawn/ghost_roles/golem_roles.dm +++ b/code/modules/mob_spawn/ghost_roles/golem_roles.dm @@ -6,7 +6,7 @@ name = "inert free golem shell" desc = "A humanoid shape, empty, lifeless, and full of potential." icon = 'icons/obj/wizard.dmi' - icon_state = "construct" + icon_state = "shell_complete" mob_species = /datum/species/golem anchored = FALSE move_resist = MOVE_FORCE_NORMAL @@ -15,22 +15,20 @@ you_are_text = "You are a Free Golem. Your family worships The Liberator." flavour_text = "In his infinite and divine wisdom, he set your clan free to travel the stars with a single declaration: \"Yeah go do whatever.\"" spawner_job_path = /datum/job/free_golem - /// If TRUE, other golems can touch us to swap into this shell. - var/can_transfer = TRUE /// Weakref to the creator of this golem shell. var/datum/weakref/owner_ref + /// Typepath to a material to feed to the golem as soon as it is built + var/initial_type -/obj/effect/mob_spawn/ghost_role/human/golem/Initialize(mapload, datum/species/golem/species, mob/creator) +/obj/effect/mob_spawn/ghost_role/human/golem/Initialize(mapload, mob/creator, made_of) if(creator) name = "inert servant golem shell" prompt_name = "servant golem" - if(species) //spawners list uses object name to register so this goes before ..() - name += " ([initial(species.prefix)])" - mob_species = species + initial_type = made_of . = ..() var/area/init_area = get_area(src) if(!mapload && init_area) - notify_ghosts("\A [initial(species.prefix)] golem shell has been completed in \the [init_area.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_GOLEM) + notify_ghosts("\A golem shell has been completed in \the [init_area.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_GOLEM) if(creator) you_are_text = "You are a golem." flavour_text = "You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools." @@ -40,31 +38,35 @@ /obj/effect/mob_spawn/ghost_role/human/golem/name_mob(mob/living/spawned_mob, forced_name) - if(!forced_name) - var/datum/species/golem/golem_species = mob_species - if(owner_ref?.resolve()) - forced_name = "[initial(golem_species.prefix)] Golem ([rand(1,999)])" - else - golem_species = new mob_species - forced_name = golem_species.random_name() + if(forced_name || !iscarbon(spawned_mob)) + return ..() + + if(owner_ref?.resolve()) + forced_name = "Golem ([rand(1,999)])" + return ..() + + var/datum/species/golem/golem_species = new() + forced_name = golem_species.random_name() return ..() /obj/effect/mob_spawn/ghost_role/human/golem/special(mob/living/new_spawn, mob/mob_possessor) . = ..() + if(is_path_in_list(initial_type, GLOB.golem_stack_food_directory)) + var/datum/golem_food_buff/initial_buff = GLOB.golem_stack_food_directory[initial_type] + initial_buff.apply_effects(new_spawn) + var/mob/living/real_owner = owner_ref?.resolve() - var/datum/species/golem/golem_species = mob_species - to_chat(new_spawn, "[initial(golem_species.info_text)]") if(isnull(real_owner)) if(!is_station_level(new_spawn.z)) to_chat(new_spawn, "Build golem shells in the autolathe, and feed refined mineral sheets to the shells to bring them to life! \ You are generally a peaceful group unless provoked.") try_keep_home(new_spawn) + new_spawn.log_message("possessed a free golem shell.", LOG_GAME) log_admin("[key_name(new_spawn)] possessed a free golem shell.") else if(new_spawn.mind) new_spawn.mind.enslave_mind_to_creator(real_owner) - else stack_trace("[type] created a golem without a mind.") @@ -78,32 +80,6 @@ ADD_TRAIT(new_spawn, TRAIT_FORBID_MINING_SHUTTLE_CONSOLE_OUTSIDE_STATION, INNATE_TRAIT) new_spawn.AddComponent(/datum/component/hazard_area, area_whitelist = allowed_areas) -/obj/effect/mob_spawn/ghost_role/human/golem/attack_hand(mob/user, list/modifiers) - . = ..() - if(.) - return - if(!isgolem(user) || !can_transfer) - return - - var/mob/living/carbon/human/golem = user - var/transfer_choice = tgui_alert(usr, "Transfer your soul to [src]? (Warning, your old body will die!)",,list("Yes","No")) - if(transfer_choice != "Yes") - return - if(QDELETED(src) || uses <= 0) - return - uses -= 1 - golem.log_message("golem-swapped into [src].", LOG_GAME) - golem.visible_message( - span_notice("A faint light leaves [golem], moving to [src] and animating it!"), - span_notice("You leave your old body behind, and transfer into [src]!"), - ) - show_flavor = FALSE - var/mob/living/carbon/human/newgolem = create(user, golem.real_name) - golem.transfer_quirk_datums(newgolem) - golem.death() - check_uses() - return TRUE - /obj/effect/mob_spawn/ghost_role/human/golem/servant name = "inert servant golem shell" prompt_name = "servant golem" @@ -112,5 +88,11 @@ name = "dust-caked free golem shell" desc = "A humanoid shape, empty, lifeless, and full of potential." prompt_name = "free golem" - can_transfer = FALSE - mob_species = /datum/species/golem/adamantine + +/obj/effect/mob_spawn/ghost_role/human/golem/adamantine/special(mob/living/new_spawn, mob/mob_possessor) + . = ..() + if(!ishuman(new_spawn)) + return + var/mob/living/carbon/human/new_golem = new_spawn + var/obj/item/organ/internal/vocal_cords/adamantine/free_golem_radio = new() + free_golem_radio.Insert(new_golem) diff --git a/code/modules/movespeed/modifiers/mobs.dm b/code/modules/movespeed/modifiers/mobs.dm index b16b7174c45..3856a52784a 100644 --- a/code/modules/movespeed/modifiers/mobs.dm +++ b/code/modules/movespeed/modifiers/mobs.dm @@ -13,6 +13,9 @@ /datum/movespeed_modifier/hunger variable = TRUE +/datum/movespeed_modifier/golem_hunger + variable = TRUE + /datum/movespeed_modifier/slaughter multiplicative_slowdown = -1 diff --git a/code/modules/movespeed/modifiers/status_effects.dm b/code/modules/movespeed/modifiers/status_effects.dm index d2120541cfa..734a45b95cd 100644 --- a/code/modules/movespeed/modifiers/status_effects.dm +++ b/code/modules/movespeed/modifiers/status_effects.dm @@ -31,3 +31,6 @@ /datum/movespeed_modifier/status_effect/inflated multiplicative_slowdown = 3.5 + +/datum/movespeed_modifier/status_effect/light_speed + multiplicative_slowdown = -0.2 // lighting is pretty slow in BYOND diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 0ce4f33ac4b..e7ba3be1e1f 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -138,13 +138,13 @@ return 100 * charge / maxcharge // use power from a cell -/obj/item/stock_parts/cell/use(amount, force) - if(rigged && amount > 0) +/obj/item/stock_parts/cell/use(used, force) + if(rigged && used > 0) explode() return FALSE - if(!force && charge < amount) + if(!force && charge < used) return FALSE - charge = max(charge - amount, 0) + charge = max(charge - used, 0) if(!istype(loc, /obj/machinery/power/apc)) SSblackbox.record_feedback("tally", "cell_used", 1, type) return TRUE @@ -392,7 +392,7 @@ chargerate = INFINITY ratingdesc = FALSE -/obj/item/stock_parts/cell/infinite/use() +/obj/item/stock_parts/cell/infinite/use(used) return TRUE /obj/item/stock_parts/cell/infinite/abductor diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm index ebab72ba3df..6cfdcb2c762 100644 --- a/code/modules/power/lighting/light.dm +++ b/code/modules/power/lighting/light.dm @@ -25,7 +25,7 @@ ///Basically the alpha of the emitted light source var/bulb_power = 1 ///Default colour of the light. - var/bulb_colour = "#f3fffa" + var/bulb_colour = LIGHT_COLOR_DEFAULT ///LIGHT_OK, _EMPTY, _BURNED or _BROKEN var/status = LIGHT_OK ///Should we flicker? diff --git a/code/modules/power/lighting/light_items.dm b/code/modules/power/lighting/light_items.dm index fb74f3b77f7..44a2cc2d89a 100644 --- a/code/modules/power/lighting/light_items.dm +++ b/code/modules/power/lighting/light_items.dm @@ -21,6 +21,11 @@ /obj/item/light/Initialize(mapload) . = ..() AddElement(/datum/element/update_icon_updates_onmob, ITEM_SLOT_HANDS) + AddComponent(/datum/component/golem_food, golem_food_key = /obj/item/light, extra_validation = CALLBACK(src, PROC_REF(is_intact))) + +/// Returns true if bulb is intact +/obj/item/light/proc/is_intact() + return status == LIGHT_OK /obj/item/light/suicide_act(mob/living/carbon/user) if (status == LIGHT_BROKEN) diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 017844db70b..eea60afd8cf 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -171,8 +171,8 @@ return TRUE -/obj/item/gun/energy/plasmacutter/use(amount) - return (!QDELETED(cell) && cell.use(amount ? amount * charge_weld : charge_weld)) +/obj/item/gun/energy/plasmacutter/use(used) + return (!QDELETED(cell) && cell.use(used ? used * charge_weld : charge_weld)) /obj/item/gun/energy/plasmacutter/use_tool(atom/target, mob/living/user, delay, amount=1, volume=0, datum/callback/extra_checks) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index d99a795c3e0..3f092bffac3 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -164,6 +164,23 @@ M.adjust_nutrition(-delayed_satiety_drain) return ..() +/datum/reagent/consumable/nutriment/mineral + name = "Mineral Slurry" + description = "Minerals pounded into a paste, nutritious only if you too are made of rocks." + color = COLOR_WEBSAFE_DARK_GRAY + chemical_flags = NONE + brute_heal = 0 + burn_heal = 0 + +/datum/reagent/consumable/nutriment/mineral/on_mob_life(mob/living/carbon/eater, delta_time, times_fired) + current_cycle++ + if (HAS_TRAIT(eater, TRAIT_ROCK_EATER) && !HAS_TRAIT(eater, TRAIT_NOHUNGER) && ishuman(eater)) + var/mob/living/carbon/human/golem_eater = eater + golem_eater.adjust_nutrition(nutriment_factor * REM * delta_time) + if(length(reagent_removal_skip_list)) + return + holder.remove_reagent(type, metabolization_rate * delta_time) + /datum/reagent/consumable/cooking_oil name = "Cooking Oil" description = "A variety of cooking oil derived from fat or plants. Used in food preparation and frying." diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 8b12b9e1c19..a99c6f4d608 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -722,16 +722,6 @@ taste_description = "rocks" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED|REAGENT_NO_RANDOM_RECIPE -/datum/reagent/mutationtoxin/golem/on_mob_metabolize() - var/static/list/random_golem_types - random_golem_types = subtypesof(/datum/species/golem) - type - for(var/i in random_golem_types) - var/datum/species/golem/golem = i - if(!initial(golem.random_eligible)) - random_golem_types -= golem - race = pick(random_golem_types) - ..() - /datum/reagent/mutationtoxin/abductor name = "Abductor Mutation Toxin" description = "An alien toxin." diff --git a/code/modules/research/xenobiology/crossbreeding/charged.dm b/code/modules/research/xenobiology/crossbreeding/charged.dm index dff26b1c0b1..f9d59193a66 100644 --- a/code/modules/research/xenobiology/crossbreeding/charged.dm +++ b/code/modules/research/xenobiology/crossbreeding/charged.dm @@ -266,7 +266,7 @@ Charged extracts: /obj/item/slimecross/charged/adamantine/do_effect(mob/user) user.visible_message(span_notice("[src] produces a fully formed golem shell!")) - new /obj/effect/mob_spawn/ghost_role/human/golem/servant(get_turf(src), /datum/species/golem/adamantine, user) + new /obj/effect/mob_spawn/ghost_role/human/golem/servant(get_turf(src), /datum/species/golem, user) ..() /obj/item/slimecross/charged/rainbow diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm index 18f5a2849ca..b2bf3684661 100644 --- a/code/modules/research/xenobiology/crossbreeding/chilling.dm +++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm @@ -295,20 +295,13 @@ Chilling extracts: /obj/item/slimecross/chilling/black colour = "black" - effect_desc = "Transforms the user into a random type of golem." + effect_desc = "Transforms the user into a golem." /obj/item/slimecross/chilling/black/do_effect(mob/user) if(ishuman(user)) - user.visible_message(span_notice("[src] crystallizes along [user]'s skin, turning into metallic scales!")) + user.visible_message(span_notice("[src] crystallizes along [user]'s skin, turning into solid stone!")) var/mob/living/carbon/human/H = user - - var/static/list/random_golem_types - random_golem_types = subtypesof(/datum/species/golem) - type - - for(var/datum/species/golem/golem as anything in random_golem_types) - if(!initial(golem.random_eligible)) - random_golem_types -= golem - H.set_species(pick(random_golem_types)) + H.set_species(/datum/species/golem) ..() /obj/item/slimecross/chilling/lightpink diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index c07004ed824..da012a95fe6 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -482,10 +482,10 @@ return 450 if(SLIME_ACTIVATE_MAJOR) - to_chat(user, span_warning("You feel your body rapidly crystallizing...")) + to_chat(user, span_warning("You feel your body rapidly hardening...")) if(do_after(user, 120, target = user)) to_chat(user, span_warning("You feel solid.")) - user.set_species(pick(/datum/species/golem/adamantine)) + user.set_species(/datum/species/golem) return to_chat(user, span_notice("You stop feeding [src], and your body returns to its slimelike state.")) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 4d263ff88cb..1f6bd734fee 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -195,6 +195,8 @@ var/list/bodypart_traits = list() /// The name of the trait source that the organ gives. Should not be altered during the events of gameplay, and will cause problems if it is. var/bodypart_trait_source = BODYPART_TRAIT + /// List of the above datums which have actually been instantiated, managed automatically + var/list/feature_offsets = list() /obj/item/bodypart/Initialize(mapload) . = ..() @@ -233,6 +235,7 @@ qdel(external_organ) // It handles removing its references to this limb on its own. external_organs = list() + QDEL_LIST_ASSOC_VAL(feature_offsets) return ..() @@ -689,8 +692,11 @@ return FALSE //`null` is a valid option, so we need to use a num var to make it clear no change was made. var/mob/living/carbon/old_owner = owner owner = new_owner + SEND_SIGNAL(src, COMSIG_BODYPART_CHANGED_OWNER, new_owner, old_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(initial(can_be_disabled)) if(HAS_TRAIT(old_owner, TRAIT_NOLIMBDISABLE)) if(!owner || !HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) @@ -704,6 +710,8 @@ )) UnregisterSignal(old_owner, COMSIG_ATOM_RESTYLE) if(owner) + if(length(bodypart_traits)) + owner.add_traits(bodypart_traits, bodypart_trait_source) 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 7b0d04bc02e..37204dae53b 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -133,9 +133,6 @@ continue organ.transfer_to_limb(src, phantom_owner) - if(length(bodypart_traits)) - phantom_owner.remove_traits(bodypart_traits, bodypart_trait_source) - update_icon_dropped() synchronize_bodytypes(phantom_owner) phantom_owner.update_health_hud() //update the healthdoll @@ -327,6 +324,7 @@ return FALSE SEND_SIGNAL(new_limb_owner, COMSIG_CARBON_ATTACH_LIMB, src, special) + SEND_SIGNAL(src, COMSIG_BODYPART_ATTACHED, new_limb_owner, special) moveToNullspace() set_owner(new_limb_owner) new_limb_owner.add_bodypart(src) @@ -367,9 +365,6 @@ if(can_be_disabled) update_disabled() - if(length(bodypart_traits)) - owner.add_traits(bodypart_traits, bodypart_trait_source) - // Bodyparts need to be sorted for leg masking to be done properly. It also will allow for some predictable // behavior within said bodyparts list. We sort it here, as it's the only place we make changes to bodyparts. new_limb_owner.bodyparts = sort_list(new_limb_owner.bodyparts, GLOBAL_PROC_REF(cmp_bodypart_by_body_part_asc)) diff --git a/code/modules/surgery/bodyparts/hair.dm b/code/modules/surgery/bodyparts/hair.dm index 80fc4a38297..8b76bc2e12b 100644 --- a/code/modules/surgery/bodyparts/hair.dm +++ b/code/modules/surgery/bodyparts/hair.dm @@ -48,7 +48,7 @@ hair_hidden = TRUE facial_hair_hidden = TRUE - if(!hair_hidden && !owner.get_organ_slot(ORGAN_SLOT_BRAIN) && !HAS_TRAIT(owner, TRAIT_NOBLOOD)) + if(!hair_hidden && !owner.get_organ_slot(ORGAN_SLOT_BRAIN) && !HAS_TRAIT(owner, TRAIT_NO_DEBRAIN_OVERLAY)) show_debrained = TRUE else show_debrained = FALSE diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index a0017241ae4..2dc654fa7af 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -67,6 +67,17 @@ var/lip_style var/lip_color = "white" + /// Offset to apply to equipment worn on the ears + var/datum/worn_feature_offset/worn_ears_offset + /// Offset to apply to equipment worn on the eyes + var/datum/worn_feature_offset/worn_glasses_offset + /// Offset to apply to equipment worn on the mouth + var/datum/worn_feature_offset/worn_mask_offset + /// Offset to apply to equipment worn on the head + var/datum/worn_feature_offset/worn_head_offset + /// Offset to apply to overlays placed on the face + var/datum/worn_feature_offset/worn_face_offset + var/stored_lipstick_trait ///The image for hair var/mutable_appearance/hair_overlay @@ -77,13 +88,18 @@ ///The image for facial hair gradient var/mutable_appearance/facial_gradient_overlay - /obj/item/bodypart/head/Destroy() QDEL_NULL(brainmob) //order is sensitive, see warning in handle_atom_del() below QDEL_NULL(brain) QDEL_NULL(eyes) QDEL_NULL(ears) QDEL_NULL(tongue) + + QDEL_NULL(worn_ears_offset) + QDEL_NULL(worn_glasses_offset) + QDEL_NULL(worn_mask_offset) + QDEL_NULL(worn_head_offset) + QDEL_NULL(worn_face_offset) return ..() /obj/item/bodypart/head/handle_atom_del(atom/head_atom) @@ -200,22 +216,14 @@ facial_overlay.alpha = hair_alpha . += facial_overlay - if(!eyes) - . += image('icons/mob/species/human/human_face.dmi', "eyes_missing", -BODY_LAYER, SOUTH) + if(!eyes && !(NOEYEHOLES in species_flags_list) && !(NOEYESPRITES in species_flags_list)) + var/image/no_eyes = image('icons/mob/species/human/human_face.dmi', "eyes_missing", -BODY_LAYER, SOUTH) + worn_glasses_offset?.apply_offset(no_eyes) + . += no_eyes //Applies the debrained overlay if there is no brain if(!brain) - var/image/debrain_overlay = image(layer = -HAIR_LAYER, dir = SOUTH) - if(bodytype & BODYTYPE_ALIEN) - debrain_overlay.icon = 'icons/mob/species/alien/bodyparts.dmi' - debrain_overlay.icon_state = "debrained_alien" - else if(bodytype & BODYTYPE_LARVA_PLACEHOLDER) - debrain_overlay.icon = 'icons/mob/species/alien/bodyparts.dmi' - debrain_overlay.icon_state = "debrained_larva" - else if(!(TRAIT_NOBLOOD in species_flags_list)) - debrain_overlay.icon = 'icons/mob/species/human/human_face.dmi' - debrain_overlay.icon_state = "debrained" - . += debrain_overlay + . += get_debrain_overlay(can_rotate = FALSE) else var/datum/sprite_accessory/sprite2 = GLOB.hairstyles_list[hair_style] if(sprite2 && (HAIR in species_flags_list)) @@ -232,7 +240,7 @@ . += lips_overlay // eyes - if(eyes) // This is a bit of copy/paste code from eyes.dm:generate_body_overlay + if(eyes && eyes.eye_icon_state && !(NOEYESPRITES in species_flags_list)) // This is a bit of copy/paste code from eyes.dm:generate_body_overlay var/image/eye_left = image('icons/mob/species/human/human_face.dmi', "[eyes.eye_icon_state]_l", -BODY_LAYER, SOUTH) var/image/eye_right = image('icons/mob/species/human/human_face.dmi', "[eyes.eye_icon_state]_r", -BODY_LAYER, SOUTH) if(eyes.eye_color_left) @@ -256,7 +264,7 @@ . += facial_gradient_overlay if(show_debrained) - . += mutable_appearance('icons/mob/species/human/human_face.dmi', "debrained", HAIR_LAYER) + . += get_debrain_overlay(can_rotate = TRUE) else if(!hair_hidden && hair_overlay && (HAIR in species_flags_list)) hair_overlay.alpha = hair_alpha @@ -264,6 +272,29 @@ if(hair_gradient_overlay) . += hair_gradient_overlay +/// Returns an appropriate debrained icon state +/obj/item/bodypart/head/proc/get_debrain_overlay(can_rotate = TRUE) + var/debrain_icon = 'icons/mob/species/human/human_face.dmi' + var/debrain_icon_state = "debrained" + if(bodytype & BODYTYPE_ALIEN) + debrain_icon = 'icons/mob/species/alien/bodyparts.dmi' + debrain_icon_state = "debrained_alien" + else if(bodytype & BODYTYPE_LARVA_PLACEHOLDER) + debrain_icon = 'icons/mob/species/alien/bodyparts.dmi' + debrain_icon_state = "debrained_larva" + else if(bodytype & BODYTYPE_GOLEM) + debrain_icon = 'icons/mob/species/golems.dmi' + debrain_icon_state = "debrained" + else if((TRAIT_NOBLOOD in species_flags_list)) + return null + + var/image/debrain_overlay + if (can_rotate) + debrain_overlay = mutable_appearance(debrain_icon, debrain_icon_state, HAIR_LAYER) + else + debrain_overlay = image(debrain_icon, debrain_icon_state, -HAIR_LAYER, SOUTH) + return debrain_overlay + /mob/living/proc/set_haircolor(hex_string, override) return diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index 4ecf2f3481e..882f07ad075 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -18,6 +18,21 @@ var/obj/item/cavity_item + /// Offset to apply to equipment worn as a uniform + var/datum/worn_feature_offset/worn_uniform_offset + /// Offset to apply to equipment worn on the id slot + var/datum/worn_feature_offset/worn_id_offset + /// Offset to apply to equipment worn in the suit slot + var/datum/worn_feature_offset/worn_suit_storage_offset + /// Offset to apply to equipment worn on the hips + var/datum/worn_feature_offset/worn_belt_offset + /// Offset to apply to overlays placed on the back + var/datum/worn_feature_offset/worn_back_offset + /// Offset to apply to equipment worn as a suit + var/datum/worn_feature_offset/worn_suit_offset + /// Offset to apply to equipment worn on the neck + var/datum/worn_feature_offset/worn_neck_offset + /obj/item/bodypart/chest/can_dismember(obj/item/item) if(owner.stat < HARD_CRIT || !get_organs()) return FALSE @@ -25,6 +40,13 @@ /obj/item/bodypart/chest/Destroy() QDEL_NULL(cavity_item) + QDEL_NULL(worn_uniform_offset) + QDEL_NULL(worn_id_offset) + QDEL_NULL(worn_suit_storage_offset) + QDEL_NULL(worn_belt_offset) + QDEL_NULL(worn_back_offset) + QDEL_NULL(worn_suit_offset) + QDEL_NULL(worn_neck_offset) return ..() /obj/item/bodypart/chest/drop_organs(mob/user, violent_removal) @@ -87,6 +109,15 @@ unarmed_damage_high = 10 unarmed_stun_threshold = 10 body_zone = BODY_ZONE_L_ARM + /// Datum describing how to offset things worn on the hands of this arm, note that an x offset won't do anything here + var/datum/worn_feature_offset/worn_glove_offset + /// Datum describing how to offset things held in the hands of this arm, the x offset IS functional here + var/datum/worn_feature_offset/held_hand_offset + +/obj/item/bodypart/arm/Destroy() + QDEL_NULL(worn_glove_offset) + QDEL_NULL(held_hand_offset) + return ..() /obj/item/bodypart/arm/left name = "left arm" @@ -310,6 +341,12 @@ unarmed_damage_low = 2 unarmed_damage_high = 15 unarmed_stun_threshold = 10 + /// Datum describing how to offset things worn on the foot of this leg, note that an x offset won't do anything here + var/datum/worn_feature_offset/worn_foot_offset + +/obj/item/bodypart/leg/Destroy() + QDEL_NULL(worn_foot_offset) + return ..() /obj/item/bodypart/leg/left name = "left leg" diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index d41d0ea4ec1..3967323cf48 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -358,344 +358,131 @@ unarmed_damage_high = 21 unarmed_stun_threshold = 14 -///GOLEMS (i hate xenobio SO FUCKING MUCH) (from 2022: Yeah I fucking feel your pain brother) /obj/item/bodypart/head/golem + icon = 'icons/mob/species/golems.dmi' + icon_static = 'icons/mob/species/golems.dmi' + icon_state = "golem_head" biological_state = BIO_INORGANIC + bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM is_dimorphic = FALSE + should_draw_greyscale = FALSE dmg_overlay_type = null +/obj/item/bodypart/head/golem/Initialize(mapload) + worn_ears_offset = new( + attached_part = src, + feature_key = OFFSET_EARS, + offset_x = list("north" = 1, "south" = -1, "east" = 1, "west" = -1), + offset_y = list("south" = 1), + ) + worn_glasses_offset = new( + attached_part = src, + feature_key = OFFSET_GLASSES, + offset_x = list("north" = 1, "south" = -1, "east" = 1, "west" = -1), + ) + worn_head_offset = new( + attached_part = src, + feature_key = OFFSET_HEAD, + offset_x = list("north" = 1, "south" = -1, "east" = 1, "west" = -1), + offset_y = list("south" = 1), + ) + worn_face_offset = new( + attached_part = src, + feature_key = OFFSET_FACE, + offset_x = list("north" = 1, "south" = -1, "east" = 1, "west" = -1), + ) + return ..() + /obj/item/bodypart/chest/golem + icon = 'icons/mob/species/golems.dmi' + icon_static = 'icons/mob/species/golems.dmi' + icon_state = "golem_chest" biological_state = BIO_INORGANIC + acceptable_bodytype = BODYTYPE_GOLEM + bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM - is_dimorphic = TRUE + is_dimorphic = FALSE + should_draw_greyscale = FALSE dmg_overlay_type = null bodypart_traits = list(TRAIT_NO_JUMPSUIT) -/obj/item/bodypart/arm/left/golem - biological_state = BIO_INORGANIC - limb_id = SPECIES_GOLEM - dmg_overlay_type = null - bodypart_traits = list(TRAIT_CHUNKYFINGERS) - unarmed_damage_low = 5 // 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 = 14 - unarmed_stun_threshold = 11 +/obj/item/bodypart/chest/golem/Initialize(mapload) + worn_belt_offset = new( + attached_part = src, + feature_key = OFFSET_BELT, + offset_x = list("north" = 1, "south" = -1, "east" = 1, "west" = -1), + ) + return ..() -/obj/item/bodypart/arm/right/golem +/obj/item/bodypart/arm/left/golem + icon = 'icons/mob/species/golems.dmi' + icon_static = 'icons/mob/species/golems.dmi' + icon_state = "golem_l_arm" biological_state = BIO_INORGANIC + bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM + should_draw_greyscale = FALSE dmg_overlay_type = null - bodypart_traits = list(TRAIT_CHUNKYFINGERS) + bodypart_traits = list(TRAIT_CHUNKYFINGERS, TRAIT_FIST_MINING) unarmed_damage_low = 5 unarmed_damage_high = 14 unarmed_stun_threshold = 11 -/obj/item/bodypart/leg/left/golem +/obj/item/bodypart/arm/left/golem/Initialize(mapload) + held_hand_offset = new( + attached_part = src, + feature_key = OFFSET_HELD, + offset_x = list("north" = -1, "south" = 2, "east" = 0, "west" = -3), + offset_y = list("south" = -2), + ) + return ..() + +/obj/item/bodypart/arm/right/golem + icon = 'icons/mob/species/golems.dmi' + icon_static = 'icons/mob/species/golems.dmi' + icon_state = "golem_r_arm" biological_state = BIO_INORGANIC + bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM + should_draw_greyscale = FALSE + dmg_overlay_type = null + bodypart_traits = list(TRAIT_CHUNKYFINGERS, TRAIT_FIST_MINING) + unarmed_damage_low = 5 + unarmed_damage_high = 14 + unarmed_stun_threshold = 11 + +/obj/item/bodypart/arm/right/golem/Initialize(mapload) + held_hand_offset = new( + attached_part = src, + feature_key = OFFSET_HELD, + offset_x = list("north" = 2, "south" = -2, "east" = 3, "west" = 0), + offset_y = list("south" = -2), + ) + return ..() + +/obj/item/bodypart/leg/left/golem + icon = 'icons/mob/species/golems.dmi' + icon_static = 'icons/mob/species/golems.dmi' + icon_state = "golem_l_leg" + biological_state = BIO_INORGANIC + bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC + limb_id = SPECIES_GOLEM + should_draw_greyscale = FALSE dmg_overlay_type = null unarmed_damage_low = 7 unarmed_damage_high = 21 unarmed_stun_threshold = 11 /obj/item/bodypart/leg/right/golem + icon = 'icons/mob/species/golems.dmi' + icon_static = 'icons/mob/species/golems.dmi' + icon_state = "golem_r_leg" biological_state = BIO_INORGANIC + bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM + should_draw_greyscale = FALSE dmg_overlay_type = null unarmed_damage_low = 7 unarmed_damage_high = 21 unarmed_stun_threshold = 11 - -///CULT GOLEM -/obj/item/bodypart/head/golem/cult - limb_id = SPECIES_GOLEM_CULT - is_dimorphic = FALSE - should_draw_greyscale = FALSE - -/obj/item/bodypart/chest/golem/cult - limb_id = SPECIES_GOLEM_CULT - is_dimorphic = FALSE - should_draw_greyscale = FALSE - -/obj/item/bodypart/arm/left/golem/cult - limb_id = SPECIES_GOLEM_CULT - should_draw_greyscale = FALSE - -/obj/item/bodypart/arm/right/golem/cult - limb_id = SPECIES_GOLEM_CULT - should_draw_greyscale = FALSE - -/obj/item/bodypart/leg/left/golem/cult - limb_id = SPECIES_GOLEM_CULT - should_draw_greyscale = FALSE - -/obj/item/bodypart/leg/right/golem/cult - limb_id = SPECIES_GOLEM_CULT - should_draw_greyscale = FALSE - -///CLOTH GOLEM -/obj/item/bodypart/head/golem/cloth - limb_id = SPECIES_GOLEM_CLOTH - is_dimorphic = FALSE - should_draw_greyscale = FALSE - -/obj/item/bodypart/chest/golem/cloth - limb_id = SPECIES_GOLEM_CLOTH - is_dimorphic = FALSE - should_draw_greyscale = FALSE - -/obj/item/bodypart/arm/left/golem/cloth - limb_id = SPECIES_GOLEM_CLOTH - should_draw_greyscale = FALSE - unarmed_damage_low = 4 - unarmed_stun_threshold = 7 - unarmed_damage_high = 8 - -/obj/item/bodypart/arm/right/golem/cloth - limb_id = SPECIES_GOLEM_CLOTH - should_draw_greyscale = FALSE - unarmed_damage_low = 4 - unarmed_stun_threshold = 7 - unarmed_damage_high = 8 - -/obj/item/bodypart/leg/left/golem/cloth - limb_id = SPECIES_GOLEM_CLOTH - should_draw_greyscale = FALSE - unarmed_damage_low = 6 - unarmed_stun_threshold = 7 - unarmed_damage_high = 12 - -/obj/item/bodypart/leg/right/golem/cloth - limb_id = SPECIES_GOLEM_CLOTH - should_draw_greyscale = FALSE - unarmed_damage_low = 6 - unarmed_stun_threshold = 7 - unarmed_damage_high = 12 - -///CARDBOARD GOLEM -/obj/item/bodypart/head/golem/cardboard - limb_id = SPECIES_GOLEM_CARDBOARD - is_dimorphic = FALSE - should_draw_greyscale = FALSE - -/obj/item/bodypart/chest/golem/cardboard - limb_id = SPECIES_GOLEM_CARDBOARD - is_dimorphic = TRUE - should_draw_greyscale = FALSE - -/obj/item/bodypart/arm/left/golem/cardboard - limb_id = SPECIES_GOLEM_CARDBOARD - should_draw_greyscale = FALSE - unarmed_attack_verb = "whip" - unarmed_attack_sound = 'sound/weapons/whip.ogg' - unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' - unarmed_damage_low = 4 - unarmed_stun_threshold = 7 - unarmed_damage_high = 8 - -/obj/item/bodypart/arm/right/golem/cardboard - limb_id = SPECIES_GOLEM_CARDBOARD - should_draw_greyscale = FALSE - unarmed_attack_verb = "whip" - unarmed_attack_sound = 'sound/weapons/whip.ogg' - unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' - unarmed_damage_low = 4 - unarmed_stun_threshold = 7 - unarmed_damage_high = 8 - -/obj/item/bodypart/leg/left/golem/cardboard - limb_id = SPECIES_GOLEM_CARDBOARD - should_draw_greyscale = FALSE - unarmed_attack_sound = 'sound/weapons/whip.ogg' - unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' - unarmed_damage_low = 6 - unarmed_stun_threshold = 7 - unarmed_damage_high = 12 - -/obj/item/bodypart/leg/right/golem/cardboard - limb_id = SPECIES_GOLEM_CARDBOARD - should_draw_greyscale = FALSE - unarmed_attack_sound = 'sound/weapons/whip.ogg' - unarmed_miss_sound = 'sound/weapons/etherealmiss.ogg' - unarmed_damage_low = 6 - unarmed_stun_threshold = 7 - unarmed_damage_high = 12 - -///DURATHREAD GOLEM -/obj/item/bodypart/head/golem/durathread - limb_id = SPECIES_GOLEM_DURATHREAD - is_dimorphic = FALSE - should_draw_greyscale = FALSE - -/obj/item/bodypart/chest/golem/durathread - limb_id = SPECIES_GOLEM_DURATHREAD - is_dimorphic = FALSE - should_draw_greyscale = FALSE - -/obj/item/bodypart/arm/left/golem/durathread - limb_id = SPECIES_GOLEM_DURATHREAD - should_draw_greyscale = FALSE - -/obj/item/bodypart/arm/right/golem/durathread - limb_id = SPECIES_GOLEM_DURATHREAD - should_draw_greyscale = FALSE - -/obj/item/bodypart/leg/left/golem/durathread - limb_id = SPECIES_GOLEM_DURATHREAD - should_draw_greyscale = FALSE - -/obj/item/bodypart/leg/right/golem/durathread - limb_id = SPECIES_GOLEM_DURATHREAD - should_draw_greyscale = FALSE - -///BONE GOLEM -/obj/item/bodypart/head/golem/bone - biological_state = BIO_BONE - limb_id = SPECIES_GOLEM_BONE - is_dimorphic = FALSE - should_draw_greyscale = FALSE - -/obj/item/bodypart/chest/golem/bone - biological_state = BIO_BONE - limb_id = SPECIES_GOLEM_BONE - is_dimorphic = FALSE - should_draw_greyscale = FALSE - -/obj/item/bodypart/arm/left/golem/bone - biological_state = BIO_BONE - limb_id = SPECIES_GOLEM_BONE - should_draw_greyscale = FALSE - -/obj/item/bodypart/arm/right/golem/bone - biological_state = BIO_BONE - limb_id = SPECIES_GOLEM_BONE - should_draw_greyscale = FALSE - -/obj/item/bodypart/leg/left/golem/bone - biological_state = BIO_BONE - limb_id = SPECIES_GOLEM_BONE - should_draw_greyscale = FALSE - -/obj/item/bodypart/leg/right/golem/bone - biological_state = BIO_BONE - limb_id = SPECIES_GOLEM_BONE - should_draw_greyscale = FALSE - -///SNOW GOLEM -/obj/item/bodypart/head/golem/snow - limb_id = SPECIES_GOLEM_SNOW - is_dimorphic = FALSE - should_draw_greyscale = FALSE - -/obj/item/bodypart/chest/golem/snow - limb_id = SPECIES_GOLEM_SNOW - is_dimorphic = TRUE //WHO MADE SNOW BREASTS? - should_draw_greyscale = FALSE - -/obj/item/bodypart/arm/left/golem/snow - limb_id = SPECIES_GOLEM_SNOW - should_draw_greyscale = FALSE - -/obj/item/bodypart/arm/right/golem/snow - limb_id = SPECIES_GOLEM_SNOW - should_draw_greyscale = FALSE - -/obj/item/bodypart/leg/left/golem/snow - limb_id = SPECIES_GOLEM_SNOW - should_draw_greyscale = FALSE - -/obj/item/bodypart/leg/right/golem/snow - limb_id = SPECIES_GOLEM_SNOW - should_draw_greyscale = FALSE - -///URANIUM GOLEM -/obj/item/bodypart/arm/left/golem/uranium - attack_type = BURN - unarmed_attack_verb = "burn" - unarmed_attack_sound = 'sound/weapons/sear.ogg' - unarmed_damage_low = 1 - unarmed_damage_high = 10 - unarmed_stun_threshold = 9 - -/obj/item/bodypart/arm/right/golem/uranium - attack_type = BURN - unarmed_attack_verb = "burn" - unarmed_attack_sound = 'sound/weapons/sear.ogg' - unarmed_damage_low = 1 - unarmed_damage_high = 10 - unarmed_stun_threshold = 9 - -/obj/item/bodypart/leg/left/golem/uranium - attack_type = BURN - unarmed_attack_sound = 'sound/weapons/sear.ogg' - unarmed_damage_low = 2 - unarmed_damage_high = 15 - unarmed_stun_threshold = 9 - -/obj/item/bodypart/leg/right/golem/uranium - attack_type = BURN - unarmed_attack_sound = 'sound/weapons/sear.ogg' - unarmed_damage_low = 2 - unarmed_damage_high = 15 - unarmed_stun_threshold = 9 - -///PLASTEEL GOLEM -/obj/item/bodypart/arm/left/golem/plasteel - unarmed_attack_verb = "smash" - unarmed_attack_effect = ATTACK_EFFECT_SMASH - unarmed_attack_sound = 'sound/effects/meteorimpact.ogg' //hits pretty hard - unarmed_damage_low = 12 - unarmed_damage_high = 21 - unarmed_stun_threshold = 18 - -/obj/item/bodypart/arm/right/golem/plasteel - unarmed_attack_verb = "smash" - unarmed_attack_effect = ATTACK_EFFECT_SMASH - unarmed_attack_sound = 'sound/effects/meteorimpact.ogg' - unarmed_damage_low = 12 - unarmed_damage_high = 21 - unarmed_stun_threshold = 18 - - -/obj/item/bodypart/leg/left/golem/plasteel - unarmed_attack_effect = ATTACK_EFFECT_SMASH - unarmed_attack_sound = 'sound/effects/meteorimpact.ogg' - unarmed_damage_low = 18 - unarmed_damage_high = 32 - unarmed_stun_threshold = 18 - -/obj/item/bodypart/leg/right/golem/plasteel - unarmed_attack_effect = ATTACK_EFFECT_SMASH - unarmed_attack_sound = 'sound/effects/meteorimpact.ogg' - unarmed_damage_low = 18 - unarmed_damage_high = 32 - unarmed_stun_threshold = 18 - -///BANANIUM GOLEM -/obj/item/bodypart/arm/left/golem/bananium - unarmed_attack_verb = "honk" - unarmed_attack_sound = 'sound/items/airhorn2.ogg' - unarmed_damage_low = 0 - unarmed_damage_high = 1 - unarmed_stun_threshold = 2 //Harmless and can't stun - -/obj/item/bodypart/arm/right/golem/bananium - unarmed_attack_verb = "honk" - unarmed_attack_sound = 'sound/items/airhorn2.ogg' - unarmed_damage_low = 0 - unarmed_damage_high = 1 - unarmed_stun_threshold = 2 - -/obj/item/bodypart/leg/right/golem/bananium - unarmed_attack_verb = "honk" - unarmed_attack_sound = 'sound/items/airhorn2.ogg' - unarmed_damage_low = 0 - unarmed_damage_high = 1 - unarmed_stun_threshold = 2 - -/obj/item/bodypart/leg/left/golem/bananium - unarmed_attack_verb = "honk" - unarmed_attack_sound = 'sound/items/airhorn2.ogg' - unarmed_damage_low = 0 - unarmed_damage_high = 1 - unarmed_stun_threshold = 2 diff --git a/code/modules/surgery/bodyparts/worn_feature_offset.dm b/code/modules/surgery/bodyparts/worn_feature_offset.dm new file mode 100644 index 00000000000..3e2a9c7c2d7 --- /dev/null +++ b/code/modules/surgery/bodyparts/worn_feature_offset.dm @@ -0,0 +1,67 @@ +/// A datum for controlling how to position items on an unusually offset body part +/// For instance if you have an asymmetrical head, hats might need to be offset to one side +/datum/worn_feature_offset + /// Owner of mob we are attached to, could be null on a severed limb + var/mob/living/carbon/owner + /// What are we attached to + var/obj/item/bodypart/attached_part + /// Key used to identify what this offset applies to + var/feature_key + /// Offsets to apply on the x axis for each direction + var/list/offset_x + /// Offsets to apply on the y axis for each direction + var/list/offset_y + +/datum/worn_feature_offset/New( + obj/item/bodypart/attached_part, + feature_key, + list/offset_x = list("south" = 0), + list/offset_y = list("south" = 0), +) + attached_part.feature_offsets[feature_key] = src + owner = attached_part.owner + src.attached_part = attached_part + src.feature_key = feature_key + src.offset_x = offset_x + src.offset_y = offset_y + + if (length(offset_x) <= 1 && length(offset_y) <= 1) + return // We don't need to do any extra signal handling + + if (!isnull(owner)) + changed_owner(owner) + RegisterSignal(attached_part, COMSIG_BODYPART_CHANGED_OWNER, PROC_REF(changed_owner)) + +/// Returns the current offset which should be used for this feature +/datum/worn_feature_offset/proc/get_offset() + var/current_dir = owner ? owner.dir : SOUTH + current_dir = dir2text(current_dir) + var/x = length(offset_x) ? ((current_dir in offset_x) ? offset_x[current_dir] : offset_x["south"]) : 0 + var/y = length(offset_y) ? ((current_dir in offset_y) ? offset_y[current_dir] : offset_y["south"]) : 0 + return list("x" = x, "y" = y) + +/// Applies the current offset to a provided overlay image +/datum/worn_feature_offset/proc/apply_offset(image/overlay) + var/list/offset = get_offset() + overlay.pixel_x += offset["x"] + overlay.pixel_y += offset["y"] + +/// When the owner of the bodypart changes, update our signal registrations +/datum/worn_feature_offset/proc/changed_owner(obj/item/bodypart/part, mob/living/new_owner, mob/living/old_owner) + SIGNAL_HANDLER + owner = new_owner + if (!isnull(old_owner)) + UnregisterSignal(old_owner, COMSIG_ATOM_POST_DIR_CHANGE) + if (!isnull(new_owner)) + RegisterSignal(new_owner, COMSIG_ATOM_POST_DIR_CHANGE, PROC_REF(on_dir_change)) + RegisterSignal(new_owner, COMSIG_PARENT_QDELETING, PROC_REF(on_owner_deleted)) + +/// If the owner is deleted, stop updating +/datum/worn_feature_offset/proc/on_owner_deleted(mob/living/host) + SIGNAL_HANDLER + owner = null + +/// When we change direction, re-apply the offset +/datum/worn_feature_offset/proc/on_dir_change(mob/living/carbon/owner, olddir, newdir) + SIGNAL_HANDLER + owner.update_features(feature_key) diff --git a/code/modules/surgery/organs/appendix_golem.dm b/code/modules/surgery/organs/appendix_golem.dm new file mode 100644 index 00000000000..eb89112cbd0 --- /dev/null +++ b/code/modules/surgery/organs/appendix_golem.dm @@ -0,0 +1,82 @@ + +/obj/item/organ/internal/appendix/golem + name = "internal forge" + desc = "This expanded digestive chamber allows golems to smelt minerals, provided that they are immersed in lava." + icon_state = "ethereal_heart" + color = COLOR_GOLEM_GRAY + status = ORGAN_MINERAL + /// Action which performs smelting + var/datum/action/cooldown/internal_smelting/smelter + +/obj/item/organ/internal/appendix/golem/Initialize(mapload) + . = ..() + smelter = new(src) + +/obj/item/organ/internal/appendix/golem/on_insert(mob/living/carbon/organ_owner) + . = ..() + RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(check_for_lava)) + +/// Give the action while in lava +/obj/item/organ/internal/appendix/golem/proc/check_for_lava(mob/living/owner) + SIGNAL_HANDLER + if (!islava(owner.loc)) + smelter.Remove(owner) + return + if (smelter.owner != owner) + smelter.Grant(owner) + +/obj/item/organ/internal/appendix/golem/on_remove(mob/living/carbon/organ_owner) + UnregisterSignal(organ_owner, COMSIG_MOVABLE_MOVED) + smelter?.Remove(organ_owner) // Might have been deleted by Destroy already + return ..() + +/obj/item/organ/internal/appendix/golem/Destroy() + QDEL_NULL(smelter) + return ..() + +/// Lets golems smelt ore with their organs +/datum/action/cooldown/internal_smelting + name = "Internal Forge" + desc = "While stood in lava you can use your internal forge to smelt ores into processed bars." + button_icon = 'icons/obj/stack_objects.dmi' + button_icon_state = "sheet-adamantine_2" + check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_LYING | AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED + /// Time it takes to smelt one ore into one result + var/smelt_speed = 2 SECONDS + /// Amount to speed up by every completion + var/speed_up_interval = 0.2 SECONDS + /// Minimum time to take to smelt one ore into one result + var/minimum_smelt_speed = 1 SECONDS + +/datum/action/cooldown/internal_smelting/IsAvailable(feedback) + . = ..() + if (!.) + return FALSE + if (!islava(owner.loc)) + if (feedback) + owner.balloon_alert(owner, "requires lava!") + return FALSE + return TRUE + +/datum/action/cooldown/internal_smelting/Activate(mob/target) + . = ..() + smelt_speed = initial(smelt_speed) + smelt_held(target) + +/// Smelt an item held in one hand and put the result in the other +/datum/action/cooldown/internal_smelting/proc/smelt_held(mob/target) + var/obj/item/stack/ore/held_ore = locate(/obj/item/stack/ore) in target.held_items + if (!held_ore?.refined_type) + target.balloon_alert(target, "nothing to smelt!") + return + target.balloon_alert(owner, "smelting...") + if (!do_after(target, smelt_speed, target = held_ore, timed_action_flags = IGNORE_USER_LOC_CHANGE, extra_checks = CALLBACK(src, PROC_REF(IsAvailable), FALSE), interaction_key = REF(src))) + return + var/obj/item/smelted = new held_ore.refined_type + held_ore.use(1) + target.put_in_hands(smelted) + if (!held_ore) + target.balloon_alert(target, "no ore left!") + return + smelt_speed = max(smelt_speed - speed_up_interval, minimum_smelt_speed) + smelt_held(target) diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm index 93be04d6348..0f02f71153f 100644 --- a/code/modules/surgery/organs/ears.dm +++ b/code/modules/surgery/organs/ears.dm @@ -103,12 +103,6 @@ to_chat(ear_owner, span_notice("Your sense of balance comes back to you.")) ear_owner.RemoveElement(/datum/element/waddling) -/obj/item/organ/internal/ears/bronze - name = "tin ears" - desc = "The robust ears of a bronze golem. " - damage_multiplier = 0.1 //STRONK - bang_protect = 1 //Fear me weaklings. - /obj/item/organ/internal/ears/cybernetic name = "cybernetic ears" icon_state = "ears-c" diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 262de707378..c5e8b6e803e 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -125,6 +125,8 @@ if(!istype(parent) || parent.get_organ_by_type(/obj/item/organ/internal/eyes) != src) CRASH("Generating a body overlay for [src] targeting an invalid parent '[parent]'.") + if(isnull(eye_icon_state)) + return list() var/eye_icon = parent.dna?.species.eyes_icon || 'icons/mob/species/human/human_face.dmi' // SKYRAT EDIT ADDITION var/mutable_appearance/eye_left = mutable_appearance(eye_icon, "[eye_icon_state]_l", -eyes_layer) // SKYRAT EDIT CHANGE - Customization - ORIGINAL: var/mutable_appearance/eye_left = mutable_appearance('icons/mob/human_face.dmi', "[eye_icon_state]_l", -BODY_LAYER) @@ -140,11 +142,10 @@ eye_left.overlays += emissive_appearance(eye_left.icon, eye_left.icon_state, parent, alpha = eye_left.alpha) eye_right.overlays += emissive_appearance(eye_right.icon, eye_right.icon_state, parent, alpha = eye_right.alpha) - if(OFFSET_FACE in parent.dna?.species.offset_features) - var/offset = parent.dna.species.offset_features[OFFSET_FACE] + var/obj/item/bodypart/head/my_head = parent.get_bodypart(BODY_ZONE_HEAD) + if(my_head?.worn_face_offset) for(var/mutable_appearance/overlay in overlays) - overlay.pixel_x += offset[OFFSET_X] - overlay.pixel_y += offset[OFFSET_Y] + my_head.worn_face_offset.apply_offset(overlay) // SKYRAT EDIT START - Customization (darn synths I swear) if(eye_icon_state == "None") @@ -266,6 +267,30 @@ sight_flags = SEE_MOBS color_cutoffs = list(25, 5, 42) +/obj/item/organ/internal/eyes/golem + name = "resonating crystal" + icon_state = "adamantine_cords" + eye_icon_state = null + desc = "Golems somehow measure external light levels and detect nearby ore using this sensitive mineral lattice." + color = COLOR_GOLEM_GRAY + visual = FALSE + status = ORGAN_MINERAL + color_cutoffs = list(10, 15, 5) + actions_types = list(/datum/action/cooldown/golem_ore_sight) + +/// Send an ore detection pulse on a cooldown +/datum/action/cooldown/golem_ore_sight + name = "Ore Resonance" + desc = "Causes nearby ores to vibrate, revealing their location." + button_icon = 'icons/obj/device.dmi' + button_icon_state = "manual_mining" + check_flags = AB_CHECK_CONSCIOUS + cooldown_time = 10 SECONDS + +/datum/action/cooldown/golem_ore_sight/Activate(atom/target) + . = ..() + mineral_scan_pulse(get_turf(target)) + ///Robotic /obj/item/organ/internal/eyes/robotic diff --git a/code/modules/surgery/organs/stomach/_stomach.dm b/code/modules/surgery/organs/stomach/_stomach.dm index 98b662e31c1..345027ef5d7 100644 --- a/code/modules/surgery/organs/stomach/_stomach.dm +++ b/code/modules/surgery/organs/stomach/_stomach.dm @@ -158,7 +158,7 @@ human.adjust_nutrition(-hunger_rate * seconds_per_tick) var/nutrition = human.nutrition - if(nutrition > NUTRITION_LEVEL_FULL) + if(nutrition > NUTRITION_LEVEL_FULL && !HAS_TRAIT(human, TRAIT_NOFAT)) if(human.overeatduration < 20 MINUTES) //capped so people don't take forever to unfat human.overeatduration = min(human.overeatduration + (1 SECONDS * seconds_per_tick), 20 MINUTES) else diff --git a/code/modules/surgery/organs/stomach/stomach_golem.dm b/code/modules/surgery/organs/stomach/stomach_golem.dm new file mode 100644 index 00000000000..9a085a5bbfb --- /dev/null +++ b/code/modules/surgery/organs/stomach/stomach_golem.dm @@ -0,0 +1,98 @@ +/obj/item/organ/internal/stomach/golem + name = "silicate grinder" + icon_state = "stomach-p" + desc = "A rocklike organ which grinds and processes nutrition from minerals." + color = COLOR_GOLEM_GRAY + status = ORGAN_MINERAL + organ_traits = list(TRAIT_ROCK_EATER) + /// Multiplier for the hunger rate, golems burn fuel quickly + var/hunger_mod = 10 + /// How slow are you when the "hungry" icon appears? + var/min_hunger_slowdown = 0.5 + /// How slow are you if you have absolutely nothing in the tank? + var/max_hunger_slowdown = 4 + +/obj/item/organ/internal/stomach/golem/on_insert(mob/living/carbon/organ_owner, special) + . = ..() + RegisterSignal(owner, COMSIG_CARBON_ATTEMPT_EAT, PROC_REF(try_eating)) + if (!ishuman(organ_owner)) + return + if (organ_owner.flags_1 & INITIALIZED_1) + setup_physiology(organ_owner) + else + RegisterSignal(owner, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE, PROC_REF(setup_physiology)) + +/// Physiology doesn't exist yet if this is added on initialisation of a golem, so we need to wait until it does +/obj/item/organ/internal/stomach/golem/proc/setup_physiology(mob/living/carbon/human/human_owner) + SIGNAL_HANDLER + human_owner.physiology?.hunger_mod *= hunger_mod + UnregisterSignal(human_owner, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE) + +/obj/item/organ/internal/stomach/golem/on_remove(mob/living/carbon/organ_owner, special) + . = ..() + UnregisterSignal(organ_owner, COMSIG_CARBON_ATTEMPT_EAT) + organ_owner.remove_movespeed_modifier(/datum/movespeed_modifier/golem_hunger) + organ_owner.remove_status_effect(/datum/status_effect/golem_statued) + if (!ishuman(organ_owner)) + return + var/mob/living/carbon/human/human_owner = organ_owner + human_owner.physiology?.hunger_mod /= hunger_mod + +/// Reject food, rocks only +/obj/item/organ/internal/stomach/golem/proc/try_eating(mob/living/carbon/source, atom/eating) + SIGNAL_HANDLER + if (istype(eating, /obj/item/food/golem_food)) + return + source.balloon_alert(source, "minerals only!") + return COMSIG_CARBON_BLOCK_EAT + +/// Golem stomach cannot process nutriment except from minerals +/obj/item/organ/internal/stomach/golem/on_life(delta_time, times_fired) + for(var/datum/reagent/consumable/food in reagents.reagent_list) + if (istype(food, /datum/reagent/consumable/nutriment/mineral)) + continue + food.nutriment_factor = 0 + return ..() + +/// Slow down based on how full you are +/obj/item/organ/internal/stomach/golem/handle_hunger(mob/living/carbon/human/human, delta_time, times_fired) + if(HAS_TRAIT(human, TRAIT_NOHUNGER)) + return + . = ..() + var/hunger = (NUTRITION_LEVEL_HUNGRY - human.nutrition) / NUTRITION_LEVEL_HUNGRY // starving = 1, satisfied = 0 + if(hunger > 0) + var/slowdown = LERP(min_hunger_slowdown, max_hunger_slowdown, hunger) + human.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/golem_hunger, multiplicative_slowdown = slowdown) + else + human.remove_movespeed_modifier(/datum/movespeed_modifier/golem_hunger) + + if (hunger >= 1) + human.apply_status_effect(/datum/status_effect/golem_statued) + else + human.remove_status_effect(/datum/status_effect/golem_statued) + +/// Uh oh, you can't move, yell for help +/datum/status_effect/golem_statued + id = "golem_statued" + alert_type = /atom/movable/screen/alert/status_effect/golem_statued + +/atom/movable/screen/alert/status_effect/golem_statued + name = "Statued" + desc = "You no longer have the energy to move your body!" + icon_state = "golem_statued" + +/datum/status_effect/golem_statued/on_apply() + . = ..() + if (!.) + return FALSE + owner.visible_message(span_warning("[owner] siezes up and becomes as rigid as a statue!"), span_warning("Your limbs fall still. You no longer have enough energy to move!")) + owner.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_FORCED_STANDING, TRAIT_HANDS_BLOCKED, TRAIT_INCAPACITATED), TRAIT_STATUS_EFFECT(id)) + return TRUE + +/datum/status_effect/golem_statued/get_examine_text() + return span_warning("[owner.p_they(TRUE)] are as still as a statue!") + +/datum/status_effect/golem_statued/on_remove() + owner.visible_message(span_notice("[owner] slowly stirs back into motion!"), span_notice("You have gathered enough strength to move your body once more.")) + owner.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_FORCED_STANDING, TRAIT_HANDS_BLOCKED, TRAIT_INCAPACITATED), TRAIT_STATUS_EFFECT(id)) + return ..() diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index 5e682ae1c75..1ba3260011d 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -469,15 +469,6 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) desc = "A fleshy muscle mostly used for meowing." say_mod = "meows" -/obj/item/organ/internal/tongue/bananium - name = "bananium tongue" - desc = "A bananium geode mostly used for honking." - say_mod = "honks" - icon = 'icons/obj/weapons/horn.dmi' - icon_state = "gold_horn" - lefthand_file = 'icons/mob/inhands/equipment/horns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/horns_righthand.dmi' - /obj/item/organ/internal/tongue/jelly name = "jelly tongue" desc = "Ah... That's not the sound I expected it to make. Sounds like a Space Autumn Bird." @@ -505,3 +496,11 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) icon = 'icons/obj/hydroponics/seeds.dmi' icon_state = "mycelium-angel" + +/obj/item/organ/internal/tongue/golem + name = "golem tongue" + color = COLOR_WEBSAFE_DARK_GRAY + desc = "This silicate plate doesn't seem particularly mobile, but golems use it to form sounds." + say_mod = "rumbles" + sense_of_taste = FALSE + status = ORGAN_MINERAL diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 68f6e758cbf..9183c7eb809 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -18,41 +18,6 @@ /obj/item/organ/internal/vocal_cords/proc/handle_speech(message) //actually say the message owner.say(message, spans = spans, sanitize = FALSE) -/obj/item/organ/internal/adamantine_resonator - visual = FALSE - name = "adamantine resonator" - desc = "Fragments of adamantine exist in all golems, stemming from their origins as purely magical constructs. These are used to \"hear\" messages from their leaders." - zone = BODY_ZONE_HEAD - slot = ORGAN_SLOT_ADAMANTINE_RESONATOR - icon_state = "adamantine_resonator" - -/obj/item/organ/internal/vocal_cords/adamantine - name = "adamantine vocal cords" - desc = "When adamantine resonates, it causes all nearby pieces of adamantine to resonate as well. Adamantine golems use this to broadcast messages to nearby golems." - actions_types = list(/datum/action/item_action/organ_action/use/adamantine_vocal_cords) - icon_state = "adamantine_cords" - -/datum/action/item_action/organ_action/use/adamantine_vocal_cords/Trigger(trigger_flags) - if(!IsAvailable(feedback = TRUE)) - return - var/message = tgui_input_text(owner, "Resonate a message to all nearby golems", "Resonate") - if(!message) - return - if(QDELETED(src) || QDELETED(owner)) - return - owner.say(".x[message]") - -/obj/item/organ/internal/vocal_cords/adamantine/handle_speech(message) - var/msg = span_resonate(span_name("[owner.real_name] resonates, \"[message]\"")) - for(var/player in GLOB.player_list) - if(iscarbon(player)) - var/mob/living/carbon/speaker = player - if(speaker.get_organ_slot(ORGAN_SLOT_ADAMANTINE_RESONATOR)) - to_chat(speaker, msg) - if(isobserver(player)) - var/link = FOLLOW_LINK(player, owner) - to_chat(player, "[link] [msg]") - //Colossus drop, forces the listeners to obey certain commands /obj/item/organ/internal/vocal_cords/colossus name = "divine vocal cords" @@ -120,3 +85,38 @@ /obj/item/organ/internal/vocal_cords/colossus/speak_with(message) var/cooldown = voice_of_god(uppertext(message), owner, spans, base_multiplier) next_command = world.time + (cooldown * cooldown_mod) + +/obj/item/organ/internal/adamantine_resonator + visual = FALSE + name = "adamantine resonator" + desc = "Fragments of adamantine exist in all golems, stemming from their origins as purely magical constructs. These are used to \"hear\" messages from their leaders." + zone = BODY_ZONE_HEAD + slot = ORGAN_SLOT_ADAMANTINE_RESONATOR + icon_state = "adamantine_resonator" + +/obj/item/organ/internal/vocal_cords/adamantine + name = "adamantine vocal cords" + desc = "When adamantine resonates, it causes all nearby pieces of adamantine to resonate as well. Golems containing these formations use this to broadcast messages to nearby golems." + actions_types = list(/datum/action/item_action/organ_action/use/adamantine_vocal_cords) + icon_state = "adamantine_cords" + +/datum/action/item_action/organ_action/use/adamantine_vocal_cords/Trigger(trigger_flags) + if(!IsAvailable(feedback = TRUE)) + return + var/message = tgui_input_text(owner, "Resonate a message to all nearby golems", "Resonate") + if(!message) + return + if(QDELETED(src) || QDELETED(owner)) + return + owner.say(".x[message]") + +/obj/item/organ/internal/vocal_cords/adamantine/handle_speech(message) + var/msg = span_resonate("[span_name("[owner.real_name]")] resonates, \"[message]\"") + for(var/player in GLOB.player_list) + if(iscarbon(player)) + var/mob/living/carbon/speaker = player + if(speaker.get_organ_slot(ORGAN_SLOT_ADAMANTINE_RESONATOR)) + to_chat(speaker, msg) + if(isobserver(player)) + var/link = FOLLOW_LINK(player, owner) + to_chat(player, "[link] [msg]") diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_blobinfection.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_blobinfection.png index e3d7acbf5d891f24b1c97f51d6b646d419f1038c..6f0663e347f435c9c61d524749886c827260f959 100644 GIT binary patch delta 6192 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 KMNUMnLSTZ@V=g}c diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_sentiencepotionspawn.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_sentiencepotionspawn.png index 02cdb1cb31a9f144267b67297fffe773e1985aea..2e21dd7d4098e1a37d9acfada760b89179ffcf1b 100644 GIT binary patch literal 2088 zcmXX{dpr|<7hWa2Ax7mgBFe48uh5t*Y-T28x>Ax`?%S~3_91gynTl!1EzBynSr@!6 z6}cpAOCh(hVJbgDEGc{Ue)!}2J?F3UIp=wv^Bj_^GeT~U+8zJ^Acu5-xryWT|37I- z@z2Y>1r~>(SocejFuw>NTp%VgFgy$Zh%P{1z~G{UKhc<_)oDZ2al`&z7MgM1gmZF| zcZ}s^@ZObio?*)8^*Z!9vGi|a?w}M=Zu>*_Qz#8!^ohH7#Hnl}c;Jp=1o}{j-|mZ0 z<=x6&E=GW&_bQrBkpKq(Kq>|avvH3u__vT7?0H_HD}37jmQr>I&m7wQ@OlX+HE6(% z3w>di4r1AK#Z6DJ?!-~U?E(>gzRj69 z8>L^GzA7LLvgb$ZIX|iO=|?iN^|_S3WBs7w=%fqam&grpO52{(qstmTWfD^@rKKm& zsK_On+`ghfRS3l&?}p=bC#pS-zl1JUr9R|vUJF|Cm5ywX^DgsO&iU-JVzmrnXZ?}* z2CjDY$>({D0J|*=QVV;|&2*>WeCf2t&z`KaXVpM6-5sJ1<6Ej0`Tgfq8=t21e2^9p zhbo`l=(K;2d!SReqfJbkcd*Ua9w|SGDMicvG*EFiaPLpS8*D3hxoatlFgM_@gE*ME zvn^wpXNyK@m3^SdI&Xunt7X%$Y(wf62&(ah@By;NR0-7WJUmLJxmG|`lkZ#PIWCWztxOU|hfmcAGRSU9F2hZMOR(tDXIs-->p_enGg@xU*JZM*hgO6H z70b*Igdvcn&S}u^izc{a;*}%Cb?08!vxjn6M40?)`KuZaU^LBBkwF9W-%&e_ijR!SB+#Uiy$f1kx`~IQgno zRQmjl2k~GLYwc23M#tA;QM(X&g}^ZI(jP{#=i1GL7F+a)(K0&XN70e+lcGsZ`F7Dh zq@GAx=Eaa7Z>r}y9m*{^y)kUIEewST15k0fef$QS;~=#C@^;0mK?Ccbmu2R}W^A@2)wfl(>5D%xCWArd zgA=F~%`&&Aj~=YQW}KEIOeMW+_v2C6rFV>UG0*iFX>Tfj%vX<4{Xyn?9_c2vfJ}iCwBTcz%_!8QRo58AN|+ zW(DNGS$e(ZHrvV){%hsEQk#KJiutXLRK+(mjC0g~O&r=%>(UZNVgb0P%IP{h`REbq zz`~r^2&&^5bwvpUY71sle`6kYz?tY>Yn`VNDFNJg@{C`V2-8#s3ZAnZq-?vz*NjV_ z_)m;B8*D_)fCtGzSP-9!Guav73`n51Gi;SDnMvNJzgY?b-zd^AZq}4>o0MO24-B6Fz zo+Ho0ogoJI@FA5^+pguC=J6SWO9sEs+*Oc)VG>KA^+Zc80)UF~{!hNgl$Me40(*;p z?o0{n@pbA0YS+A=jXk?Jn2~s_ytPd2+*0F;`C?+TySuCHzPsaQ_^YC+oA=(#`_BHA z=`8B!a2+2lj{?N@5`vJOk-i86McG%W|ANiejO+1!4Y#x@x0IUpv5sG^{qCVuuc`*{ zF0i~It%pz_<9vEvOGYEA2*t{~J%QfL19v$hmzM$Z_G%G91!XIAh))Aqso{gb~jlkAe8Om*Qb59-=`ev0A zgDc8DVM-*tnW-g|C_LW&w+BX(WdHQ-Uue4dOud45`kt(kKEO;mFq&1GbyI2;r!$CzBo8n%^)ipY|)$}N?z-=d~+8|p_}X1UCD zbXMmi)QZg9mrGb2ETV=fmiyT`dj0-*{`mayeBRINd0!qDga*kl2IQ{zxH*HWI(AKg zKp^=rlotvFs!89ndPYI^Rw23jT>*i%z4@o)ntx-3fIvz$9%vLUE>KJla;Hb@H0Ns- zBZfL?ceJ7(r)r8jGps^Vb;|p6toxcyqp_%aEJk_lXJ+kO)k9O}Sq1G1lP}B@`-FEW z=Uv`X7u+PkYqd$VIx*~t=)534D6V5=WnFaetF(CBJI;|bcehTjQ}V}1Sm(;>@W?gZ z&s$y6w*sf^UN|5}MDCL-%hU*A9`bv6L6Tacb*m4ASb{Yr!OKcZM?)M=sy>wCzXzFW z6&iThhIjkCTZav0jpSIik>Jz%4b*AdsE8K``v#!Eq&bBp9V^;c3ye@S4F)r06GOyp z9UYgcrBziEqAM?=lLiL_xXzUGAraIp_T${-`PtpaM+1K)y2W>J9G>iC+>@c_aqmZJWZ-ZamsQHIhg7p#lIR4S5{~+>(&I*ViKVCyUokkg6FKmVa zocq;sSQB>?H73Sl*BF{}^X1zB5!-6Vo`wl%u@Mf^@Q7Pbfb(7X#BHXI7xBaNI9Xtr z;V-1?yFa;?QPSwkT@w&uTUDtXlg!A#dB+BdOFRzL5B3a@1+Y~R^>tVEF64muYB%GM~kd=i#i zy-REpNgPAlI9k1J>G$SI+!|^vyEO<04Dk@XnJOmuH%Uo z#$gD~lV^1Tm3lAD(hluPfzWRZy`(g!ic92%UFL7Pg=a>diU_!Q^m9pYe0=Op9$?*;6-A( zKX)R5`c-S2#uhe7SNFrU&d}EU#)9HoZu7;AUW$y>K;+43vAgP^?HU}xEa)4jQBK}| zG=Yw4SOjAnSq7rX2PXVIrf8%lOUBe9rMmuJdFawl7LQ{l3T*dP7Hi*~nKi?s?ZDYJ za@fNG+3Ka_Kt%p!jzY(yE*oys!vSTRT<)~}|GETGqtB8G08@KR9 zp9UAx4!$zW8@%Q?3H92@e>4h(0pF3BZb|;3S1rf83bfi&$i`Th@*;2tXu66?XdQ%d z6lF3zTtO}z#_(G5qNuyWmGXls$e^A~d7@HgnSuN@$5V6|jbgEC-)0t{zHmeeI1~7r zjyc-Z+Z`UAlyqJx6B_mWt1*IETs(h~7!uL8aQ)dLOr~SThsqi0SWd5d0+&uXgVZ(G z|FR>OOfa(p0sIh>=PDoXS{y^kU`(PN85lLZT4H1~4W?+4SaEA-Zl z*}$hsn{E}+T(|@jse2QbYCetlGTjQ2AP|-+h5hh6>VXL}t@^BrJ!;EUy;)JY_!7qZ z>DOw1QV;@XW++VjP!l~Ve7)BAmy{M+!~mAcg+tuW$&kA3tTS|^V(h?>j6y($%{X+{ zXG9SNOWtJ}uEf2NKv10;H1u%u`FQiiM3H%sWY91?r#&>$+7860fFaV0p6Mqni*BPU z=mHnG=qdqR6XU6F+=rRcxKQ$q^3*rpK$1`+0H^Gb9#P-Sz;QfE(1(jK3P$Qi-)ufI z(meTmZaTZ1{H(SNNGuBg4wsRuZBr{l<&QPY8Cw*pzRs~Oo#*1KGlu8`%+)fDQ(7Z4Z_M8Q35A-eAK%w;nZao4J(iMbK28($ zaW-Q?rS<}|F!SRV4J~cspJTi5X3EpMv!37ejnc#cQ-eHw316BA!9gN}T#XeB4flU? z`jNzc!f!deHcvfHO#feh8m5$yp=HIMw}02a>D=T`tbYI*Hwfa1s~5*|DT86xdv=shr4BJ z^w}^#=ud5zZkk*cjH9F0mTfWU_V#ufrRtRV##%(D3vJc^ zezH(e9|gch6Rd>%I}X&v2ct@B@BejmZjWpp!n?VKE=@2PoDyRfL7L7WaIv#!S8z&K5WCfX;Lk!J(tEFzVl#vz$;^%U-h4^ iXV@mHCGJ6Q$ZhkP@u`+S-6uQnAY~6%47$qsH2H6MRO(y+ diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem.png index 1f5e06af14041ffff9d57fecafe137b4e1ff16b6..b6ceaeaec20ca4315966d1152cd55b36007c254b 100644 GIT binary patch delta 952 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 IM6N<$f@1Pnt^fc4 diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_bananium.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_bananium.png deleted file mode 100644 index 341d03e2327ac2e9ee7baaf89dd2916d51003b26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2146 zcmWkuX*3iJ8@-x%l@O6ESwohPea$-dt(nO#6h0|SmNMwgng$i3Xvkh;X;HF%LKLzk zg_>SuONuv@7Al|b$G!L5bN@W&Joj9hqrC;^R-vr`IIS$rNE>SOf3OoaxS&4%Be2QW z(UwANYiqNxfVDL&EphQ8=I4=T1;0p|%!PRbVhcCS!UUlaqM=ej~-* zyLVk(5f_K%X56|3XJ@3O;K~(Ty^8#NczYu+53{q-&^C5+!=+0&bO=I15>9SMuU$iK zE{2A1IwtYdDU6I@a1h~jm}PZ zdZMrp2M(aV9HdqoM+3WhgC0WhM0WVQh?t57E^HJv}rvp}ZW~*?92+&!0nA z7g}1lc@rfiu(N}e6`Y(fK8}P0=;%OO8%K^nRTW-dpirQx2|68SX4tzYlkJ#Kd6lUc|;iS{kQMqpb}xGLV&pxH!bbuxAfAI6x#~*Dk23 zK}7|Uk`NSxfB=${Au0+H5%BWDzyRv%@bLkYiKHZ)IfDxq@b}-y%EG&M@bJL1XXvZI zi4$mTMSDAHYH;oxG&CS3wecVb3qw&6+qQw79Rvc{*uYl^J=Peewf+gXFu1REE?hrxXWm<$4g7 zexX5IjiffLW-XpSmDQO=5hq*G($u8yGj^3-PgA?KcfS^Yr{)aFDRd>Ah0cy^>$|vg zihaxgRy`{-V~R`iKUX=NcUbUs$y)JC-rHZE7F56KO0IPri0Az4%X#*kkF%5ruq>0d ztSb6ilZA&uCF}{CST=8>wL4~~oWB&vbC6Gr;Z?b#+Mw&>_;36f?CH^2qpuAX=;^6x zv7ZUZ>fz7wkhp5qb+$IR#Ur6tYJ_O5vscS3C_VLtk$r_`h2eP7W@?{o#K$?8RdRQH ziQ!uQ&m(ENY^vwe9LAbvdprAu;*QrHYb`0AUpxs1lcpKI$VzMO8w>}V!5_M=7Um{g zdCXHM5~pdVBU~~&(k-;1y$Ny30!jY@PiG}I7Qj_DHvwKz2T(895mAgY}>(5~=A8R>rXH6*NIZ)5u9eJJ6@K136@djiZ$Bk_m;%WOYq>9xJ-MxJi`s{jrS! zWAx>yv^CGdLikF_bsK?ZmW$E)$66R(7Tk!98(AqGS9jp{RS7ugX>Qu_UN`Q;^OTfl zemQ>IRd-GO{QHIB6hC!n)c5nn?E_y-Gur1}X7+ymdB^D8yD-ah642`z?p$L>bT1Nw>+>7wXq4gtw%wn~7_av=VO^ zj1or8erD7kRHhRb*Rn!t?P;GXMudCTUJq5in;7s87DbY=>`clW&`VUnhwzT!;d!fa4y~)E8%*6rYpnmnfweMPU4H`4aDL>9X zDHv`Lo0*RYPTxNjtXP|uA@?mfX}_d%lu*m%-kr`K6;8xUwCS3FoThs}Lg*ao+W8Te zii4gIwi|la4)wKUbri8ISRYwp);`{@H1c{$ZQV##R8qE%esWu{%%xxq7elhO{(?g!;xWBv-LEBh~}YJh^W&wG|TUV=>%NrK+auS^O3=E_@| z)7B|9eErYQrT8f+_QmNxa=MjzL@cr_N}S+e-6eH}bnI5~&?Z9P!O8=bWw&LRT!Lfw zk1tp=4)8zTqSyFrHl#dEBsDwUhx^m*CjAbA+*S)NKh72Qx7pd!6ThN#)@U-u#XGee z6?oMh?p+n5e@WKxxSxBX$~w}`&PHi3VKl2}!S+@leRK57XzoE}u~dO?Z0o%uX9M!y z8LVu7=Uzz?xYpKhqUkjGZ|i4Tr^AJ^mLkNmzW-7qo1^xXVS!0h+Y@nzzchYi|GyA!$nl42DUjA=qr z*ST+3|JcK(uRvzKo>-N>@S*T8ir?U#ZHLpFa+ICDjJ`fzuqlt>dnD1{cjsaBZ-3sR l%a=nAx4IP+QvZG1>d=@x^X%wn-i_Uc717@8wuyJb{{Ss|oFM=J diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_bluespace.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_bluespace.png deleted file mode 100644 index 5f172fa8ab555f986b08af0ea5fe8ec8ff87183f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2146 zcmV-o2%YzdP)1O=P!|_-8XAKb7r#|#WRB_+BcA*CK3 zlqxFJDk{h z3kxl;DhUZIBqXyE5?dJ=dk6?985w*B z2PGI7cP1vl2nZ$!2qy*xAO;2>2L~hq0t*ffMFj;I3JNm{3NQx;A_WB*1qBxy8-)f2 z9tH*+1OyTc3_S`8G!qkHEG*j^8iW}ceHZ9g;3C=MoZJDk{(^BBvG>Y$hhZ zCnv!pBe5GBh6@Wd2L~es1sVkf8wm+40s;&I0tf*C0|5aBXJ!~v00001bW%=J06^y0 zW&i*HWqMRtbVOxyV{&P5bZKvH004NLQ&wYE6 z2mqS@7!En1VMG7`1v^PZK~z|U-Iohj6Gs%sCrK3|vN5HLZMOoJm`Z>EMTTa#r4b~E zfJh-|NTel5tDy9;k^sIMq6mTl0R#ex!BCWkh>vO!Q4}AjU#b(VJ;&_c{Q&;Y$;mnU zoBPk5J3BKs2z_Xh$rX}ZA(u(Vf3$ABT!PCZ)qNC{TaR5(3y5tmfs!9*0s837J z_&QlfMnVpm+jeY&w0NnQt~3Fu+*@4k??3;yIl0?RVRA$hUYrhrbUA zbK(w^k=vP0XKl~T<96kX@cdnv<48QmVWZeOnF@Au$%T8EqT&)RVXyFQk?l=ji31U4 zcNdt12Bmo>Ze3d8zOo;3IazsyfLD~uFpF81e6T66RKU%Z1*O=ye-C{iG80=8t1MyM zQk7^SlP3v~Qj``{ngs@0BevQOR{!`@O`;vw>IDY+TJ&}XWDe+%R$!1{Ng;V%!q2}P z-g=}S*&AxZcx{87tj^nb4pWtaGAoWAQ&cqm`rGgNKi2cdn;gzC?sPPTX1`WL%pN-` z*!9O9dCm4C22*JZ)oOQ~IC(0JpE`NM5vm{#)v-CxaXj4MbaR8n*?Q(r*O4~2j5=E_ z$e{WxC3Bx6(Hk{ROGESNa0ArNqx0rX9i11>l~broP$OjSLR5L%1zCsEd>--b0v=NL z#Y;V?*VWf0N)hVnbM>O0OBcHVj(R+4y{KPD4*-0C*7c*_G*1s?FlbR-Mnl8tI)Lla zhlkK*m1Phz7~=VU)IZ`CdC}Ko@{SPB^Fxrq=vd?^^7*eo=d%2Y--kvc$3`K8fIo8_ zT~!o9Md~h8Tt(xV{s5SP@q!NpeG`8HJUHPCBHyGD%HUey`qVUu-KVY=c%)OGspaJSiV(#0t#Skvm+U_&|Kqnp|C$^h$>KLfQA<{59C*vlEyJ$SQ zxyh-`4kRA4Sqn7lueL(*)@naXFJ!S;#DUzqtU~)BYLPYV6l*Wm zl)ux&E=E1jDng^f4al{n^m_+rwxqlbGH5F=Vd(*{Um3dJgc)F0*+T=(MlT7wi~m%y z6wT6xhh;7-%z!+?R;`L+A9bX7AOlZI$0L?fX|18r0t3uZsy?cut|r?K8Q8OH>Po0S z6~zfVxzOcrrE(mKl!0Ln@UFT%!viS_M-F8T^$6jVlqKK%cscutCPASVH&81QG*7aZ zADi=qHC(fpY^zFjT1`tXCKApO4$Ni#SPf->-tp~&jB}S=4i;%d8 zwSPi|gECZ9w{_=l=+v>WAwvIvn~swhqTJFE;eX(yGQjDEF8mEOs&H&0((SAae9ZU# z@bk+HLNB%mu4Z6iB_lt+##Q`k5HPVKJQ*iV^g%j~q;uphuG8o-3B^gD8tI zsB;sDSQLWZ5isCLUnJ#b&jkbrRqSvCNd^C3Ak#EbI$@9j!wNo}g9Sd%FS7`#W?&3gv785cqjLT}HeXiyX}i_A(ReZ&1itP~!9F!ZToPlz$lI`z zM5BhGxY(M1PZ!v_e+>0$iSA}y*mWo#Hs!#WKQ6cTriTxW;r#JPo>+AF(yYUf?&{(= zW4z+$O}sG9P3!UVpF#=5ct@9}V8}Z)<-rx>PCYdR>0(zC$1L5|uTEqRN;yz=S8DEg zvoYnNDex(;;Mo@3Sb~%9iEmjj+XJ%<8n(bH41{(^Ss`H8!BvbLVvYkKB>4C1FD2}f|5$*< Qi2wiq07*qoM6N<$f`FcZbN~PV diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_bronze.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_bronze.png deleted file mode 100644 index b62d312616ad680bfd06649263420adc4d1551e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2146 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 R$a4Sy002ovPDHLkV1j#&vQYp4 diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_cloth.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_cloth.png deleted file mode 100644 index f66a531659ef7a21ecc63e451db5817911cbdf6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 837 zcmV-L1G@Z)P)BGarl)twB|Nn`JiLkJ+H8?>U8X;C%V|ROll$4YiAg5;l0004WQchCV=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRL zOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5Nr{UyC9|j)q@Ig2ttc@!6~s2=QdV&Fa{-$O z0Gj_84mqJ=L;wH+TS-JgR7i=vl)X|LF%ZX3C==|N6nCozds0NJ#xO1{Z9WV`l}89~ zkSAdB1UNMQND)JG$Izs+^#n}Z1Zctx50xVm>$GwPI<+gId|vq1eQ zXNo9)j9<8;PlMRt5Z}i9vNog+?_)mxUx?#~x9bzk0T4gL+#<5Qh}*sKct3WSenps` zG<-2zt)|}_76;nuJsVi|{OaeT;mqv;K)0#G?M}U)M0KgI)%rk%G-+5?W!bRA9R%os zX?W?Ei@=$%BeL3#Y~Ysnej!26!fM7D3)}hP++cgRCb}?C>vh`);UC33N$&y zZ%a^-7g5lZpXn0?=X5{RZ;e?t_Jbha-t;kN@*^I_{4QAsnf#3GYSVp@Z9f^}ORAum z!nmGcW{?It;|5!+Wo3Aowz^oI1e{&X^%*N1I?$P2t*Pzj4$k9|%k-``9lzc&?dsIn zd7_})unG=-I`s(54EvkR(az%d)8gm$=<{7ew5F=%2$M_D+d@;Aa<^ P00000NkvXXu0mjfnhT5@ diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_diamond.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_diamond.png deleted file mode 100644 index f5c99146a68ee4f903ad273f99e7f5248e767ee3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2146 zcmWkuXE+rM13kL&Dj_0~?2!?&XXZ6C@6DDGJ}D!kT=d%MqC$u+*}6tUiQ==Okd+il zuT4_CsWhm3z8~kD=lna*bIx<9HdZFAJNb43U^O!}vfEO<|AU#Z#RUy-z@b!g-1p)$)k%9Dd`1`}g2BD!yNC1U`@bIkGdK495 zVPSJ~6BQLGE=EiYR#q@Khu~nWu2QK~)YPE99(8r7t_GbB5(%@jn3}@-_n=bm-n|Pa zC&b30sR_4k!NCE^$;ipUwQI=FhldC9@-RQIqOK2TXI#00W5@XTgzcSA;QDps=3;2* zTvP(ip2f%r1_#mIjaRR5^eF7?(9?tIX{4rNW(IL_2n$0{5S~4Qtu0bg5D|f=PjTV| zjE!Msg)?W++l#H#Za( z;>Zy+G~o4X3=iY@aa2~KtPG{4sH%dtHuUw;(t@roXlbFb5#{B`%EHT+c<}<7nov{2 z&6_AGfu$wP%wTVii3!BVLqh}V>hSV{q9WYgK_)|06*L-*jBxlcF6&gNTlXxH!(8!&bQx5|EUHkPrj~AtnYE77&Tpw+~86P*8w~ z2zYtH!-J$G2nc|mADo=f(SfouJUuZ!j>JTqKaWe7@b}-y%*4BQaCOD==cv4i)2Gqe ziuQKY*5bkisHi|x6nuQxzaO%)*tHAH%pefJ#H4O*o3%ANhA=xT67&|ve7B5GB-t^{ z$S3qf$jRWalR<$%L_WzrI3)c0S5olm+MKk-A?bm>LDJo03PVa$GqQt6rFsyOcIlzI zlAY49lDSa+OlD^$S%_ptO;r-VPv2K|BUS0v!NY3YovL$o_Q7kR3^Zn3-`vNhQS501 zFlw0@>60Ck{<+5Du*Za}OVW&66NOJGWBKbx_9>|qT1c_GC;E}Ye}o^S24{e-Vd?nt-G z+DpF9$mA?q|Ax(e^9RYYBh$L`*RxFCY>Vmk9_j98!W6g1gRT4%k!1p}_xpE5 z1SAyH42(yxk+S0zWiAVl$jX1#$Nyc|9r@Bl;~!912~$q;ZM8S-6VQ?#TkASN>Hj9m zL^{dx%Ku!xIz>9IP?PeQqe_VFRjtP08SS@IVWA06UPmrik7lSgq-nYw>MmNB6%Q>G z9onyAWnuW`eK6tWK;x^N!xTd%sd9lZ{2YjD-_obwl~xj&T_f zm*mK<#M!(*$cK~N+dV=X+L_@ zQ`tZF*p06wgjX@q^|J_@n81A}7Ud6j>J3&${B z{RsDy9a@i`&j*!<@TX+Od9r`H-KgC`klJa&=EJ(iJe`##KKUy`V}mN8U%Xe%Mut<_ z`rb7`+Lt61*ZaArtIflmEiL2@5=Jw7mX6-?r)`gX70Es*FPOsfjcK!&KgKWbozB|s zcP>?SJlEU$4OCr*4g8O>u(K}?&_9{}na_xlR&4tdPapmq)-Ke}dLij%jun-G^nl2l zxykdDm-xWz`-B!Nclh^p@rRR><8Ir(@fiI+F|kVA(ehAz diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_durathread.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_durathread.png deleted file mode 100644 index 7c968e546c64672705915c5debca95f9e3fd7823..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 929 zcmV;S177@zP)8T4{)ak)f2owmLaJiHV7@u&_ErW;HlL8X6&1T4Q&6gCZ(NuEOFUBNR~p z0004WQchCV=-0C=2JR&a84_w-Y6@%7{?OD!tS z%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5Nr{UyC9|j)q@Ig2ttc@! z6~s2=QdV&Fa{-$O0Gj_84mqJ=L;wH+t4TybR9J=GSJ84LAqX51atZ3W|Nphuuv1sL zD45&FILS_BTiON{$aVd+QA$a1s+8LkQN{rKlz~a`aEMnD5vn2nM!#%?4AuFC-Xenc zdqP6Mc<4RAKaMVtR6K;45re{BLwjgo;u_jttq>+qX#w7Avr&6wKUz`Ng7@BjwBI(` z*fS^%B2gi{cWx-PFW7vDzW-s3y$4++C#!dfl%S% zM;ULN*%deMJ%+8XxCOcVRZ!M28*UM77RL>a735)8!45M&WTQYHKw*s;8yvah0Y6;< z{Clif1$b4eT1o2;w*l^X&G9vRyXde&j6 zdw}G=wMXSf)@IHWGGhvg{DuMcsN2G*8c7UFM}g>V!+^TmRg~tw_}>KR5!6};oBfpl zWeXlw?s*V9NQAAvtqNLI)SVtBoXc}kw{wC*y(qv});G+KHZ45tu%&Kokj-8Q+NhPS zHqY3FsqCHLSUWjyeOT%|DVP;k)_R1mAi`p{dQzb7#}Y%Qu-jbmk<>m`>$o-ORkhj@ zvHg=_Vp@o^i%bZP6L5;soUfV`=bK<=1oJ?En{p!9^;e%1;JW7ooaPHJ{s#rtBV-EX zq#*yF$cul%FyrpvRsa`g%m66O>S!gWkC4E}zkTK(hz=exFR+d*00000NkvXXu0mjf D?0%@o diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_glass.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_glass.png deleted file mode 100644 index f9a2ace1ed068cac7dad29171db16b22122a8b05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4102 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 Ef>CSS9smFU diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_gold.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_gold.png deleted file mode 100644 index 093d50727c0e787bca2dc9e08825b88de8cb59b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2003 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 KMNUMnLSTY^F!g5u diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_mhydrogen.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_mhydrogen.png deleted file mode 100644 index d41b7fdb91ec61530a4f9fd23d108376291986cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1954 zcmV;T2VMAyP)2HliHV6gIY&D@OFKJCI5H8w*O6d4s28$Lfy6B8Ic zJxw+?L=qAgHaA5zHA5L0AV^7DDl0Y<6Bi&LC=d`88yq7N5*9KuKo%Ap5D*j(4--d7 zS`7{n9UUYN4iOFx5;{9d9v&qqDKiZX5DW|tCnqsJKTiw|5DE(o3JMJb1O*ls90&*s z5fK#&3l0Ye2`el&3JMGf2@D1X2Pr8tE-pGSFgzX}CPFwxBP1+8KuKAp`)F%9}TCRbAr%&Q;rg zWQv)Z3V_!lhqKONqg~(>UG)u(KRF#_B&5((eY+a=CkoBC*(T5*@huF)mXr!Sz_GyR ztObe@FY=8)|5D>7|Jwc{|7*^8QCk6f#MTC;xu#7L?|3!1_YNcuwk4abI71 z7w_r6#|#uT@&2lSKacwZRerK~G652buJ%5kO2F>nF+CUz{ytO{;zKT#fGdPPuYjxp z4ck=$-ad>BBb9&rIeK$!9EB!Ad7L~UyYtzfM4``{FJOEyX{5pr|N7hYuuz_wmLhpP zB2DL3e;Gp_Pd-rH`YB1835^L{*DNj!Nt14sfO}HPMUcjHGN5F3Sl>AgL53Q7XL!TGI)#!&N)i&tq??lHnXv;3 z(sGCK8A>*#GvEw7;S|cIQriG0D2q}%9%u%;nZ1>Lv^%ny)qX`LyE(Fp_G5dQT}_@) z!Y=9n&38MW7iw+PO5t;7_dGhFTwz5sjPdy4!HXl5${rpbYHd`UJkO@k(Tjt_IJlAD zf<@%TJw3j+DCb}FuWWzFKDYqh6|xfxgZ80)n6LGR-2z7rJj6FS!5!`gIht!L^O#o4 zq05B0@>P?^)TYix|67!<=~CEc?|_pcd^mV6rW(O)e8xDTRD7E%-D^&(fIK0yO zOxtr+IzI@x;*aT7Y#kYD$?pxmSg2)a#EMsGEUG&>eAxiGC1c(CMhrNs(b&d%ol$aM z_DQO(B4P3Rw$57KaFs@jwt&T0$-QYg+wytUF}#%6F$8Q8%$-J|8AMMx9I*uqJHSa9 zkIC}cuua_?d@-MG_)L~#;}Dl;1GeL7@UoE0HhpXh%*yb9{a$c2Izu{17bTp_@w5(4r{l{`u)iR-rYOl19e#3>R1`QV zBa}Kn&+5b&$#VAmJf$<>T@Rgk5AHG=AAg^rd*0~?TqFf^V*3K37uyN5kc4o~c8|6{ oeEhTn(4C!6A3tm#echk@2eS|_eS>3OW&i*H07*qoM6N<$g6`7|b^rhX diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_plasma.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_plasma.png deleted file mode 100644 index 7cb8a3cf45d02d8c4f8b8781d297e9263c32925b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2146 zcmV-o2%YzdP)$u&6!y zWt6|RYaol6F311>|8F6XYaonO8E&62&X_L7OBP|FFwu#LiE|>Ac_f~AB%E?0lyD-F zHxWpeEya~B!kaJ3TN`(ikW*>!_ zF2*%DK|B&pUmbio5lR{wAy!&rXCH-S9)yc3wRd}iPZ(y8E4hj(vxO+Fjw`t{4?;H( zM}{b_mMz0w9C(*4#8w(`O&4WK7GQ@cuQm`yTpV~%7-)njtU?r4FAhC45JXECVuvZP zNfuu$4LN%ypfwOgOc!H)J`+)D zAc`prHhLwWkt@87Dz`rqQE?)YZ6S_rA&qe&lPC-{D-Ae*CZ&ZatS1aJd?lf7A&+Ao zfQ>4+j4HM#3^FAPFmEA|Y#@v?4?{5zKRFRglq|qk8gV8IF(nHzK@?RX3M)SoQaBMw zBnvNRABHUsJ0S`x9|HYYYa0k7QyFU+ z2Ov)vXMiTA83-X72qF~*92Eu|7zZB*0tzk;JP-vHA_^=Z3Mv-|9T5c<4+Rui8*>x} z8WRQ>38;B9TZIUVkR0 zfhVVSBbiwnbR!Ec7Y7~@1s4(p7aa*E2m%TP0tW&C0|WsDQ;a?~00001bW%=J06^y0 zW&i*HWqMRtbVOxyV{&P5bZKvH004NLQ&wYE6 z2mqS@7!En1VMG7`1v^PZK~z|U-Iohj6Gs%sCrK3|vN5HLZMOoJm`Z>EMTTa#r4b~E zfJh-|NTel5tDy9;k^sIMq6mTl0R#ex!BCWkh>vO!Q4}AjU#b(VJ;&_c{Q&;Y$;mnU zoBPk5J3BKs2z_Xh$rX}ZA(u(Vf3$ABT!PCZ)qNC{TaR5(3y5tmfs!9*0s837J z_&QlfMnVpm+jeY&w0NnQt~3Fu+*@4k??3;yIl0?RVRA$hUYrhrbUA zbK(w^k=vP0XKl~T<96kX@cdnv<48QmVWZeOnF@Au$%T8EqT&)RVXyFQk?l=ji31U4 zcNdt12Bmo>Ze3d8zOo;3IazsyfLD~uFpF81e6T66RKU%Z1*O=ye-C{iG80=8t1MyM zQk7^SlP3v~Qj``{ngs@0BevQOR{!`@O`;vw>IDY+TJ&}XWDe+%R$!1{Ng;V%!q2}P z-g=}S*&AxZcx{87tj^nb4pWtaGAoWAQ&cqm`rGgNKi2cdn;gzC?sPPTX1`WL%pN-` z*!9O9dCm4C22*JZ)oOQ~IC(0JpE`NM5vm{#)v-CxaXj4MbaR8n*?Q(r*O4~2j5=E_ z$e{WxC3Bx6(Hk{ROGESNa0ArNqx0rX9i11>l~broP$OjSLR5L%1zCsEd>--b0v=NL z#Y;V?*VWf0N)hVnbM>O0OBcHVj(R+4y{KPD4*-0C*7c*_G*1s?FlbR-Mnl8tI)Lla zhlkK*m1Phz7~=VU)IZ`CdC}Ko@{SPB^Fxrq=vd?^^7*eo=d%2Y--kvc$3`K8fIo8_ zT~!o9Md~h8Tt(xV{s5SP@q!NpeG`8HJUHPCBHyGD%HUey`qVUu-KVY=c%)OGspaJSiV(#0t#Skvm+U_&|Kqnp|C$^h$>KLfQA<{59C*vlEyJ$SQ zxyh-`4kRA4Sqn7lueL(*)@naXFJ!S;#DUzqtU~)BYLPYV6l*Wm zl)ux&E=E1jDng^f4al{n^m_+rwxqlbGH5F=Vd(*{Um3dJgc)F0*+T=(MlT7wi~m%y z6wT6xhh;7-%z!+?R;`L+A9bX7AOlZI$0L?fX|18r0t3uZsy?cut|r?K8Q8OH>Po0S z6~zfVxzOcrrE(mKl!0Ln@UFT%!viS_M-F8T^$6jVlqKK%cscutCPASVH&81QG*7aZ zADi=qHC(fpY^zFjT1`tXC9aSMn*<(aB!%os5Ll2LPA1m zX=y$_J{lS!R$60madDZMnRk1GS65e^ot>DNn3I!}oSd9EI5<2!Jf)?jW@ctzUtd*K zRZ&qL_{quEry1MpP!$bo0~;NMSOgGczAd$EG&|ek}E4Kd3kx7 znwlsmD0g>vKR-XCqoXP+Dk&)`NJvN}B_%R4G9)AsiVPRohTwG^oXKQO~mVA0oPfv`DjE;_uf`Wo4CnpmV6BHB_2?+@X z1_lBG0t5sEcBEl800001bW%=J06^y0W&i*HWqMRtbVOxyV{&P5bZKvH004NLQ&wYE62mqS@7!En1VMG7`1pP@wK~z|U-ItG75?K_- zFR+QkOl*$r?rda`7^66Ewilt)qPmI z=fupNKcIUKhjaM6`#45OC(m@Bup!*mWB-XUGiR*`KL?Ip ztEG>2q9Ho_2VCcS9b_e@;O@E5gZmSO!3(S#^#^W=Q0YDqOn62?FsK1Wr^tC%^Bq&^yw@21bKI*A?a4 zqPxj2$69g#fjH?m|(k` zi+0DNEj$|Qj*`uj07xn*-*`kJU>CVKeSKo$_e6J+n{+A!oRjcr2V@U$!>$mJ#wpN; zy8ig{=IM?UB&Q}@_~cZQoX#hI62iD5&4ydkhVaZ^w{JVow8_y#I@7{4=|pq)hdJc< z>063hA5HsW$qtX7x_TAVh&jkt2wBfC}l|x;aziKFG5Qei+612lG&n z7CfpHz_TC~VE(~*<(~18K-UoX0P^c zwymk~wYJUPtFy47bIw#$(^x2MZ9LhAmB!ZAmfArT$nT96*nYCHRX`8&Yp_fz|5S@V z&8J!~`WLpIuwQ?M-W77)o?W*m)^WagZN{6kkry80Wn0cWa}DK?9X>7^pLb%H3H+VU zjiPZFtp^~{*3oebZCqBz%SPHVKKc)>*7!cz&2ukUh8BYu4~jIyz6jn#1;BHTeM#F# zF+6IgU$QT-iU*`(=h%#c#U>nLHrA10bELSd`jgI0sx~`}Pia66vt$Wr@+u0%pW_F2 z7+#!+WB&08k!N-Wc}_)v^j+RyXUt{Ze-X{HbkWb3&5Yg9T-_=_+LlSII2b+{LT6Qd zD9AI8ifC%~H)RBzH0Jd%ym41KU3|9iu90Uv-Z6<&MnHbz;&z(iU(H#Im_X4w_ll=z zd%U??A;1X~y+8#+iJ>GWkQ_>cg46;{3Cc;X+5F>_H*K&wmWoIgrQ(vqYDjyjcymT* zr6es<-b`t1iA(t(&(-*rV;|sE`a8dIwkG>do;q?R{AKl#1 z2mm~uoy}-oW5L>Fz@_{lWH^^U1&c_cR_q{Csc#0000mzS5EoSa}_V40bj<>loy zI6+!kT91#9RaI3Q8X;C%W15HJQi;Iim;^KjUfpm0qZ*OnP%F0nuQHqL+czAfm#>Qh~V@5_sPEJm7adFGb%WiIN zLPA2hxw%hIPjYf{!^6Ya*x1+C*Jx;Hy}i9aKtMk~Kb@VOWMpK-#Kc`)U7w$yK0ZFT zx3}5Z+0)b0US3|Qsi~x-q@$yws;a6yJUl@`LB77e$H&JzJ3G3%x}~M1l$4az)YQ__ z(mFaiH#aw@r>CN#qD@UrNl8goR#x8L-hzUHIXO8vI5=WrVlpx^UteETR8%%LHk+H9 zL_|a}F)=PKF524KLqkI;DJfW3ST8RxDk>@~D=V|Jvs+tRdwY8*C@6efFDZ*Bkpc$`yKaB_9`^iy#0_2eo`Eh^5;&r`5fFwryM;w;ZhDainG zjE%TBGg33tGfE(w;*!LYR3KAHiHkEOv#1!Po{KZBC^0t`#5UwoR&e!m0hBvaP zA!GNR-Ecf{$lSwZfbj@t(KPeTHUkDYYrr98u~0mR)4%;LHk*8l$8-4mkT56iKpDB5 zG&(ajH;>z!FT(TpVvZy69EXi!>trg}$0Zf+XNrnTxcCFYw?%d!o+S=MnB7-k5*n1| znYc}GI>V{=lNmCU~D{c4Eg+5p>tV&)$c=Nk>g{KLBO9efvzbEp(6DZ zDz2f441WO3z}V$OLEq$G01r<3g2*>zgfh4uxG_D0X6r|T;y)1xj@Hkj8PAQtbx}U- zZPLr;Q2W88o2}C#e7f~!(!q8#C(}21MawueG(UH10Zj(y=jX*1YKS}!PNIcdbMr&s zLVgHx-tN33#qV_94&UhSX{J_NeHYv-WV_w1*4ECzeBe-1wp&A9c!-Z`+}TZsK#tDk zZZ}5Ui-9&1GR54BFh=AGPosBo*(c6f{8HiOd6=wiv?2TH6EWALztGBUSIi#U*bmsMyVMlG?X9I^IdL-{!-b}8zi zRuLKf4${rbLHhNjuUHqqt`78qcTQuR|M^|e`c$iSXeTVF!;t0+#`$%QU| zE0yg~BoB^wfOpm985vAgII<~gs7DB=q%8U7Co5S`HSr3yxPe*`uX&oa^2D4ktl@^m zR9jVw(`s6FK^eG~O;%@0RofKMt2TIee&tAh+r`fKE-ldHrgAVfMX;{{s8lfJy*q R{8Rt{002ovPDHLkV1m$P|I7dY diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_plastitanium.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_plastitanium.png deleted file mode 100644 index 5dc6ac923bf2e469ff8d259e4ea839d40a0400f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1803 zcmV+m2lV)fP)d3Ser zNl8htu&^&LFJxq7E-o%eNJvmnP*G7)Q&UqjGc!_BQZ+b1FfcGJEiD=vAy!&rZ*OmR zdxJkeKXP(%Zf@?BO_yD zV`yk-b8~YyH#cQvWg;RXR8&-6US4TwX)-c0At51RVq$c3ba8QUS65dcARr$fA6Qse zaBy%P9UXRdb{-xcG&D3D8yh4fBpMnT85tQC78Vy57hhjrF)=YhLP8Z46%-T{W@cs) z5fKv;69xtb4Gj$v5)upy3`a*t5D*X#4-X0o3LG39b#-+^LqkhTOHNKsZCY7pXJ-x$ z4g>@Q0s;a90|Roj#o+(|00DGTPE!Ct=GbNc003orR9JLGWpiV4X>fFDZ*Bkpc$`yK zaB_9`^iy#0_2eo`Eh^5;&r`5fFwryM;w;ZhDainGjE%TBGg33tGfE(w;*!LYR3KAH ziHkEOv#1!Po{KZBC^0t`#5UwoR&e!m0hk zX7cR$p$VqC_?wGKGd}^AWnVq3u zLkcAA{EKnDu}?t)bME=KZ{97;vH)inJ!7~4w!L*!Q1eCtjx9tkP< z7dIARf2_c4Fn-V<@tZWwyqXN~02c!Mz%~WQU*vrozNH}kH})6#zX!&P#tNh)ZmrSG z(soGPk`1`L#fu{L7e!t&S|>L2UUY^RnTR7Q&hO}V3$ZgVUOA}75L~)6 z6NMupkz4rifqQ3GlbKj?h!#;fFVUFP>>s_UR&3{{l)6F)dp&MX)nMrX`;p| zehXlYB-KQ%lQmFa?WBd8RI&jHv{bc;nr#iNNLm|nRc%269c{dWy3#3BmrbWq7j?$9 z4kXZ({2kOI!cdY*VWNjReyjpTAo;tf*F8H2c<-#+L*0Y~MR3ur)-TaTyxlW?MYq?E zU!cocwR>U6TUw4Iu24DbyfzyxRNZ{-442Ur!R0i=G&UMHSD$auS?}iNreVbK^WGV{ z{d{%PFyeoV74y}*QT(o&A3o^6*=5GFR{_roUWv+{Cvyq&=1wliv3SEnyv=gK+z!Z5 zX?sete3^j`6Jlq+SR~6fSPzg)%{g3l%Ay%#%|h8-j!DYs;(NB-@>hnYq$tFr5=Ap# zqd8Cj1(um_l*a*Khll#ce1$3=!WEliie3gx0ZszrEixP~?uP#O=EhZ<*@n9`L~b*9 z2)^VE6tF)pFnwB(()ybIVoF*P=sqLx1`7Dz6$lS)YYVJld+}uQ7Av%Ew1*gs9u~mY zmQ~Wcv=EJhy{ai56=<&}SqJxM&p^y;ojhvWj8bNC|RILQQyf8E`Nm##)uW~Ne#%N zTs!fu5V0Vs40?oNiqj%1rw^M4>^xyN7O)fZ?7`;4sUquh_#}}qrQAh@y_cZ~KeE(5vQas`{|+2KN!(N$&jzRjuVAt{$h{{S0_m@L|jJ-Kk?09#HZnY9l{+Otpj$ zt|tgplh^$b0iZyjf1Rw37*Nkfd?UXXIA0_?qUfSlq|}f`a7k*EB4B@kt*L39_6Xi? zcQg$y%J>GqyX%d}F;dmu-5uCpU_0BTx{u&0qkR6cOYNSG5P0lx*4FtWL?6#vR;~l# tfnD65fB*3lst1Y0&mZ5V=-0C=2JR&a84 z_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5Nr{Uy zC9|j)q@Ig2ttc@!6~s2=QdV&Fa{-$O0Gj_84mqJ=L;wH+cS%G+R9J=Gmf>#eFbIVM zBu!V_*Y2A4f7TtGc2{ZuSL%LD^VD|IF<*e#z%>1~Mephy?;slJEFl5>fiCkB?0`;@ zej=IIc?kgUPZm0P`gsh%-$G|c{@6p1D1?r{PM>fI?C%8EeoC;vToy`>o+;^~?Ae#Z zAP9bK`;z|YO2sCS6s~ZwN-@JAkPGZfNzK-|)U^^mg^eB1GYD8Ii$y?wzC9qr1?VZK zobgGfjx&;kuXvLU8xD`?ddYAAsW5asBZ;nh(i-7E13=Rr0b-brdcTI)M3q#e&jUam zxaXi)F%UDseWBKX5d**)ea|7XXaEF+D1BKLB{VOBbMV7-!(s4WkGAh8(;P7~~+kK)ZVdyLz0|qnD z2XwgL$#7r*sGSf1)V_K$DmI#Hl%swh>WboS+M{!$YS%DFT(JdB-XOp}q2||IeHYNW zGkRZ61_6CHSgt!P3tBa zum@muK!<~44m*PMrcn&o#~5!`-RG0du?JyO7lN9EK`6d#ea48-`U`+?oX2}`1JJc` z&>DAupMeh81^{wj!NY^NuKz>`Zvtoxh(pkm>RkoB4Eu}_d7vu*9EXE1q~92&wWH=d P00000NkvXXu0mjfPymMc diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_sand.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_sand.png deleted file mode 100644 index 9cf198e2ae55ef985533ed45ca7907b4152a8f1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2146 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 U0ID9rz5oCK07*qoM6N<$f~l^kKL7v# diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_titanium.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_titanium.png deleted file mode 100644 index 2dfec2d7a842073fab721f129ae4de033e7f9bda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2139 zcmV-h2&DIkP)mzS5EoSa}_V40bj<>loy zI6+!kT91#9RaI3Q8X;C%W15HJQi;Iim;^KjUfpm0qZ*OnP%F0nuQHqL+czAfm#>Qh~V@5_sPEJm7adFGb%WiIN zLPA2hxw%hIPjYf{!^6Ya*x1+C*Jx;Hy}i9aKtMk~Kb@VOWMpK-#Kc`)U7w$yK0ZFT zx3}5Z+0)b0US3|Qsi~x-q@$yws;a6yJUl@`LB77e$H&JzJ3G3%x}~M1l$4az)YQ__ z(mFaiH#aw@r>CN#qD@UrNl8goR#x8L-hzUHIXO8vI5=WrVlpx^UteETR8%%LHk+H9 zL_|a}F)=PKF524KLqkI;DJfW3ST8RxDk>@~D=V|Jvs+tRdwY8*C@6efFDZ*Bkpc$`yKaB_9`^iy#0_2eo`Eh^5;&r`5fFwryM;w;ZhDainG zjE%TBGg33tGfE(w;*!LYR3KAHiHkEOv#1!Po{KZBC^0t`#5UwoR&e!m0hBvaP zA!GNR-Ecf{$lSwZfbj@t(KPeTHUkDYYrr98u~0mR)4%;LHk*8l$8-4mkT56iKpDB5 zG&(ajH;>z!FT(TpVvZy69EXi!>trg}$0Zf+XNrnTxcCFYw?%d!o+S=MnB7-k5*n1| znYc}GI>V{=lNmCU~D{c4Eg+5p>tV&)$c=Nk>g{KLBO9efvzbEp(6DZ zDz2f441WO3z}V$OLEq$G01r<3g2*>zgfh4uxG_D0X6r|T;y)1xj@Hkj8PAQtbx}U- zZPLr;Q2W88o2}C#e7f~!(!q8#C(}21MawueG(UH10Zj(y=jX*1YKS}!PNIcdbMr&s zLVgHx-tN33#qV_94&UhSX{J_NeHYv-WV_w1*4ECzeBe-1wp&A9c!-Z`+}TZsK#tDk zZZ}5Ui-9&1GR54BFh=AGPosBo*(c6f{8HiOd6=wiv?2TH6EWALztGBUSIi#U*bmsMyVMlG?X9I^IdL-{!-b}8zi zRuLKf4${rbLHhNjuUHqqt`78qcTQuR|M^|e`c$iSXeTVF!;t0+#`$%QU| zE0yg~BoB^wfOpm985vAgII<~gs7DB=q%8U7Co5S`HSr3yxPe*`uX&oa^2D4ktl@^m zR9jVw(`s6FK^eG~O;%@0RofKMt2TIee&tAh+r`fKE-ldHrgAVfMX;{{s8lfJy*q R{8Rt{002ovPDHLkV1m$P|I7dY diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_uranium.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_uranium.png deleted file mode 100644 index ccc8749342166306f3d5a30e40f8a141d7fe8dff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2146 zcmWlZX*d)L1BH(!F3F5FYZ&{MeHn}}jD5>YcFFpoETJ;!W=R^{k|-KlEQJ=7D1Ak# zMY63CuV8up5 zLxYAdsOj*&jcr$;?hVTv*qwykDL9s4%TCyrV%HlOQLHumU~>#=+aV=I_VNpLI1T#} zgbZMRYL>}9gbg9MAAye%`W%WbQ1Qf$E=0YCbsnN7LCt`15)9+8<8P>JgH~;aCoxFnBh={{b`u z;dB<8w_!e1a{5L!FnUJKVMxKzTu4l-28TEq7)0y`mN4)0dDR)b!I&}RsF3TZP) znZWHLTq>aC3I#`~c_DHP7MYMXg%kzaArRMxRuEK~kTiw^2lBQM*MpcgB3?qy1|sTE z_rWF|h-yGo6U^(-@P}zCMATrG1|elo_QS6o!YU9}1xX%6IS46%n;-IY@Jm3#0Go6n zsDO=<;1|c%Y!GE3AOl`u$XGza5L$Cc#i#(>q#NW||Ep2GA= zvJFoRO^Aw5ii(Q`lFJxg@dkb%9OltMJsCOYD|F4@A z15blN11I^i$-)PPOnHVQJI_G*dW}TYnLL9lYI-JO4~(Zhz2cV>xj4Kyy(U34Js)ff zaGN{YS~GpJ|2f6)En+X)sp=@Ea80i|FQ#SP$r7h@&<{tnR0}B`Np~PeI#ek;TspVZ zSctn)6}*}2xYn;@-}5NSIdUvoXq%{9O;DZ4WsA-aV?Xh$zpKl1m9yGkZf>sdXjNgrl>Rv3>nDlAva zzK7(Q@#r7Pb02Aa)BT`VDt%XTR9i*m?ED_M(^{uR_trU)F4VX?_kT0{3#DQ_S&s*PU#FP{e-ml0!VzES1`6#VA6l*)Gju0~=|*k~w6p1WXO{l{X->|Q@ZxYm zeTm8Me?GIE6k`nxhkZUO*tcj?aBtRUTJ7`qdaJkBe&mkl*eQ0}k+ae*6J-Loi_++G z+ROm@ROv62WGrNoxDSXNw?8FVc7P2 zLCZEB4t;*LFs{js{i$|Hx@-02z-5>5S+Ols6BDmK^s)?v$~YVm{~GJhR7%E7Twk9+ zCjWQxW7eg`X3@5PSej{-Z5Q83&EGSh*g+nh@3W5SHSAgaYBF=vXgWLR+mT1*gE!@- zXOm*{^(JGrno0}Qzr-HWQ}9lfx^tp?lXpO^7yTG}sxh*-_1d>M4!ytr7996^$!JnRv;?LUialUd|%&8TNsMAbk+%L^m&l+>h@*Ys(kcuqj}L?IzvTm zgAcUrES_l4Dmw%o->6c0Z|k(xTe@3`uNBwNQ1N$&K1VMFM()8V_Fx5jJ~ z?R|PUCtO>rC!KoV>q>5j+}^5Wd4juBr{YP^s4M3O))9KP)orb-x~eitlpMLfYtE@= ztJp(6^IK2e#8oHArc*!taZyAj4XX?u`Kx3 zzs^(qbbBw&*nf}~y`7&#n(eFkzf}tm7SIwe)b#xjI$!KDoE2{%*?82;p-lPQ>kK g^D95g`uBC4`>pKhC!wE(fB!Zd>29`HX*)Cj2XhH($^ZZW diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_wood.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_wood.png deleted file mode 100644 index fe7cc0e4bbc913046598369b63297fcbe21996ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2003 zcmV;^2Q2uBP);EJ80IKP?_aFd$k$D_K7(G9wsAGa^wsCrdRXNHZdozqVsW zFOOwJ|NsAINik$cFHblnlW9hcWJ5(UA(d)JiHV78Ofzv%HgHchYD+R`N-;Ae7>i;; zkY+_yJSecRus0_fPdFxYQa3gx8dN(dT|z8gLM&lLE;}k5Uqda9WkWSMK{zNHH60_8xn(EJ~}BJX-YC?NHAqcFlkFNB^nYa9TRp_ID1z+B^nWP zQa5HuF@jt^BpDGR7!YJfFf}F_ief=gIVK|+5hEE89~KWZB^eJS!cDU_ebbC09NvPB$ev zC>w!WJ$_0tLoXn9R5*B5Ic`ogQ#&Ui7Z4T?3J?nj2L%KL1Ofs90R#gAIkt#Y00001 zbW%=J06^y0W&i*HWqMRtbVOxyV{&P5bZKvH004NLQ&wYE62mqS@7!En1VMG7`1q?|IA?~BWG=$#b$PaDZ1(#8k=gJ z*b`E4GiMk$9xF7TVccLm;#z2$DL?Ar0M2_j#aehMUf>#k`0-RL{@0EdxStf`1Z@S% zE3`Gx&8ONsgtI;k?mNo~0*)61&a1UfZ09+l)_P0=_;95kvN0e;Yno8ADO~ zU=bg*NAc=>iWfMl&sQu!Mn=fq(cl00)Ad)0ba^bEDB_9unDX==Ysm2<5!J509Pb#9 zR(ja(D^y7|K63S15x;hIB(7ADQ|dV05x-n4aDCh!Oq5jrEmo3A19c;!${=!sG9+)} z=yEm@w2xme7C;jcx+NYBOuBCdC^V(25fY~m6(HS)03qH&(u9gDHhuff44M_^rZg!+ zQ*+`hnz?g(8sKOqRX>YlC+!3{CNi3>Pt8CA^Fi}nlwN261sWF8=&m_94+*3tNk;Nw z2JA?gMa(5B4GG9gr83Iq?m=CXxR=W!xpYZ}1oAm|9^EJXP?4tnx74y~f~)Pwx0CQoNZU4{)b;jevIvZle; zN*>nwC(wq$HJV9l3Cz!LZftF%<-+FXrq)8ulIS(%6mtcw5@9>{zafJ1qr0;0xx*V z>5oT{e`k^^+^WtQt#6 z(q5Ad-fT#;HSI}KDh6@sO25rC25uI-*~Uz^{wosfFx}Xj(*5KiQoW7fe1UB;_}b*r z;U16ab#PM0VQsLhQTKbn)z~$tb?zNnx@&qir^9o(+3Bvdj)T0E$?xd!ot=CJo-eRv z_xB4rHAa$D*x%3UIK1gG=ih>>jAF63d2`Pj9f2)5Nu&?9Ai8ysCXzCQ6W-u>JXb@*kB&JpX@qI-URk002ovPDHLkV1mA$I%fa? diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_teshari.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_teshari.png index aec29b7c0c8a91df4c5089c7ed6bb950fe479cb1..453f283728ef205dbbcb90c2f19422cb5f4a6d26 100644 GIT binary patch delta 867 zcmV-p1DyP#2&o8=Bmr-cB_BBe004VnJ(Rz;j*yddcYukBiLkJ+v$L~kXlPMSTS-Yt zPChR_K0a)0Y!MU`iHoAt*WZzmkt!-Gk$M{hO9#NYk(q&i_en%SR9J=WSKD&qAPfa_ zsocVrV3W3Su1^2|8~4abv&jr15Bpk;>&)cn93erFs?@JNn11+>;D$q|?>;10c2Gul z##+;9Bf(lZ$Naj3^2T(_;{^dwUtaK%1eEVgho{b86cEFUe2+CcV;ojkmGIhV(s+!P zme_e`t@AH`^$-Z)ERl6W01iRDb3F+G76q8dhllTpdN1RKoFkbJ;}jaOdbRfTO@`kB zM+mY*h_F90{+=RHOi{vPN+G25E(*kuVoX66unA^mJb(?pq!0r^!IBsuhE>cdu4I7~ zSxX|W@@hy}!?4N%jtVc2gr{^7NU7=p+`4geR=}Nq&0z>R@vC+ifS0v(&aO)pS5W^L zKEJ*`hYv)l;Z(}TxlJil!<8kKC+u>VvZ9IuNM&7!@KW{T>L?Gq&qJmvPGec~3f5($ z8V-vCpR_?dDAT0|lZ2}{4LJ{!eA1>hOvZ6ius^wRl*3fYB;)X4f&akO7GT`U_zu{1 z*AUo$1KjOp{J{93!9Vi*C@MU|e+}kU>&k!bgr3)I8W%pgtJIv)nx87b0S#Of(9aZ@ zuVn$v3c8c|o%UKDP*?#2h zVSeBQ!Jkhz1?)LiFy2~aSTZu@xyI*zN$6{T zXuAG@%VrMe@9bm&m%q)Oa!}0N}zvRmjDoK2ae>4C9002ovPDHLkV1n-|nY91_ delta 860 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 HGzs{BNIyjE delta 15727 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 diff --git a/icons/mob/inhands/golem_lefthand.dmi b/icons/mob/inhands/golem_lefthand.dmi new file mode 100644 index 0000000000000000000000000000000000000000..71dad57145ef3f24ef9006ba54a90a7f6ddb38fe GIT binary patch literal 1482 zcmbtUYfzF26#X2P%pz-QH(!g|ZktlAPENifBh9c8%swFREp zDGDVZ;R8&Z$qW&-kzEC}49O79s3-*uO(+#z`nkXMM>FT%^W&bmGv~~mdm|Vf05!KZ z2LJ$yI_?)@;Jbz@G=ms=Y1~;G1O1r`p3d+~z{g$0ozK9frvU(=E`RXBmOlF(rXw}F z@7&darH*@V;^Hh{#<+mwYcx6}STW`8(dkKk)8Vm{z5#Lw8+~LzXAzzA-{^a942Q}VZ z1%{lwS)dw$-bRqST_D#QO@sho@(Ja41SHg{Cmx_}!gma46ly{d4V^sX#KifU?;nw& zY{JbkTTgl%B#^+Y!HQkbgLKhIa7z82Uv zzMT+3yC&*=(9zD#4kjFznTR$`)HyqCzn4--xnPAf4B9mE2&D>{BbuO+>(AKrko1-V z}IEzaVqTidfZfB zI0HQY`j+iL3l*Ms{%X-fE)|~oN=f<Y*mzDSdn5{)Y|3DIXn+q*p(wlHC5`N**Y4NUD%G5u5}$a^fnuE zTaKQ&Aa<+d{tmBNe_A={j#~>ztWwipN?P;+q-m^CC#_ODO+}9LxMI|!H&C#(vd2l* zPQ`?)He7u^hA^dCnc3665!N>RRX7KpEaHlBO-+l;9ehwHeVe^OJiiUB8wFvDOs*pCs!XY@Nf`4rU^-+T1r`#qSZ# zubWm%t~foW4lC*!Z%c`R?iCAbUF);Wfo9F*(dP?yFdvF42<+^qa+@c4d=Q3gSk<4a z$~(oz*ET&Pa#bW>BC^-3GBamiJnywWU4(5@?_E6&JFcO=UmXAd zXn1+L`6~Q9h2qsz6t)C)UQgj}X89q~+#*v^DKSZDF^L!eAmeUs@6(+fMthY92oi13 z!if@d%iPMKXPGBt;*@?Nv9)JNAic}BVx2uwVoB&v4U!%`*EDyX(`r;F|IG}L{LT1>g6xJ!R0RUxVFSlcU8Fv@>P`I9#E^84De^8d88ZbpXsA2h_rVeO< z(O{gKL#Wer@a8AqRGHrP`T>b7``M)LPpT&=;OHJr7vkQ*6utiR590;)SH)90^0 zv)5XioB2-CsdkH+MZ&qUXcqTFo2=e zJiP-$-BlTz*UvR%?|xVhw1Sni&aO{SH_J-=N6OJrf4?Prd(isqo2E(4s}{N&5;p$*j0~5))>{Are3WaQ&kZ16;YOUaMNpave;AErkz~Sjg!2InXdah?xqPasAP<&p z$6@y~1yL3Kuu!w~ecWu)L|`mBp(!LPeG@m?Xqcbko7q1miSU_(Flo`;F)N-vEF_`b z=~up?HU}gvjxs1!G!%-l$0mkz9D1=8af#J(gruh59McZM?ZUKV55{E4JGny1K$ls& zc==4<7T7CF9u{`XN7UQeJx^lN#+z?SQR8KYuJIN`VX3d!!Y2&7FU@+ukBPOr)$-Oh zHSHuyN^JIO6YsC^?8qq;W}8}l?UvoP4iA8_`?txA1AZc_7d*6Sd?mTGcvyHC|5!vl zv$FSUvRt#AM;2HIivct4dNN#48U|IKj=Un+S2E-FU#i91U6P+4)aAOHXW literal 0 HcmV?d00001 diff --git a/icons/mob/inhands/weapons/guns_righthand.dmi b/icons/mob/inhands/weapons/guns_righthand.dmi index 89a9d42f280998ad6645d5e747cd3ca577a7c6d1..2aca6d31727cfdc97d16588c2e7585c9149c583b 100644 GIT binary patch literal 67098 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 m|0_nrbC>wTVgz0WdILrsa~Cf!XC2t@My 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%0A<&yP@x+wCH-dm!_SjZZ+_ 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 diff --git a/icons/mob/species/golems.dmi b/icons/mob/species/golems.dmi new file mode 100644 index 0000000000000000000000000000000000000000..c29fb38be43ac8f46768b60ec17d8bf0838b4e12 GIT binary patch literal 19061 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 literal 16304 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 IE0~A;FK^AU8~^|S diff --git a/modular_skyrat/modules/bodyparts/code/ghoul_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/ghoul_bodyparts.dm index 0c16b363fa3..37a9cc982df 100644 --- a/modular_skyrat/modules/bodyparts/code/ghoul_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/ghoul_bodyparts.dm @@ -4,11 +4,47 @@ is_dimorphic = FALSE limb_id = SPECIES_GHOUL +/obj/item/bodypart/head/mutant/ghoul/Initialize(mapload) + worn_ears_offset = new( + attached_part = src, + feature_key = OFFSET_EARS, + offset_y = list("north" = 1, "south" = 1, "east" = 1, "west" = 1), + ) + worn_head_offset = new( + attached_part = src, + feature_key = OFFSET_HEAD, + offset_x = list("north" = 1, "south" = 1, "east" = 1, "west" = 1), + ) + worn_mask_offset = new( + attached_part = src, + feature_key = OFFSET_FACEMASK, + offset_y = list("north" = 1, "south" = 1, "east" = 1, "west" = 1), + ) + worn_glasses_offset = new( + attached_part = src, + feature_key = OFFSET_GLASSES, + offset_y = list("north" = 1, "south" = 1, "east" = 1, "west" = 1), + ) + worn_face_offset = new( + attached_part = src, + feature_key = OFFSET_FACE, + offset_y = list("north" = 1, "south" = 1, "east" = 1, "west" = 1), + ) + return ..() + /obj/item/bodypart/chest/mutant/ghoul icon_greyscale = BODYPART_ICON_GHOUL limb_id = SPECIES_GHOUL is_dimorphic = FALSE +/obj/item/bodypart/chest/mutant/ghoul/Initialize(mapload) + worn_neck_offset = new( + attached_part = src, + feature_key = OFFSET_NECK, + offset_y = list("north" = 1, "south" = 1, "east" = 1, "west" = 1), + ) + return ..() + /obj/item/bodypart/arm/left/mutant/ghoul icon_greyscale = BODYPART_ICON_GHOUL limb_id = SPECIES_GHOUL @@ -20,6 +56,8 @@ unarmed_miss_sound = 'sound/weapons/punchmiss.ogg' + + /obj/item/bodypart/arm/right/mutant/ghoul icon_greyscale = BODYPART_ICON_GHOUL limb_id = SPECIES_GHOUL diff --git a/modular_skyrat/modules/bodyparts/code/parts.dm b/modular_skyrat/modules/bodyparts/code/parts.dm new file mode 100644 index 00000000000..af75cc9a032 --- /dev/null +++ b/modular_skyrat/modules/bodyparts/code/parts.dm @@ -0,0 +1,7 @@ +/obj/item/bodypart/chest + /// The offset datum for our accessory overlay. + var/datum/worn_feature_offset/worn_accessory_offset + +/obj/item/bodypart/chest/Destroy(force) + QDEL_NULL(worn_accessory_offset) + return ..() diff --git a/modular_skyrat/modules/bodyparts/code/teshari_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/teshari_bodyparts.dm index 1be2e49268a..800cc978cc1 100644 --- a/modular_skyrat/modules/bodyparts/code/teshari_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/teshari_bodyparts.dm @@ -7,11 +7,45 @@ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM limb_id = SPECIES_TESHARI +/obj/item/bodypart/head/mutant/teshari/Initialize(mapload) + worn_ears_offset = new( + attached_part = src, + feature_key = OFFSET_EARS, + offset_y = list("north" = -4, "south" = -4, "east" = -4, "west" = -4), + ) + worn_head_offset = new( + attached_part = src, + feature_key = OFFSET_HEAD, + offset_x = list("north" = 1, "south" = 1, "east" = 1, "west" = 1), + offset_y = list("north" = -4, "south" = -4, "east" = -4, "west" = -4), + ) + worn_mask_offset = new( + attached_part = src, + feature_key = OFFSET_FACEMASK, + offset_y = list("north" = -5, "south" = -5, "east" = -5, "west" = -5), + ) + return ..() + + /obj/item/bodypart/chest/mutant/teshari icon_greyscale = BODYPART_ICON_TESHARI bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM limb_id = SPECIES_TESHARI +/obj/item/bodypart/chest/mutant/teshari/Initialize(mapload) + worn_back_offset = new( + attached_part = src, + feature_key = OFFSET_BACK, + offset_y = list("north" = -4, "south" = -4, "east" = -4, "west" = -4), + ) + worn_accessory_offset = new( + attached_part = src, + feature_key = OFFSET_ACCESSORY, + offset_y = list("north" = -4, "south" = -4, "east" = -4, "west" = -4), + ) + return ..() + + /obj/item/bodypart/arm/left/mutant/teshari icon_greyscale = BODYPART_ICON_TESHARI bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM diff --git a/modular_skyrat/modules/customization/modules/clothing/masks/gasmask.dm b/modular_skyrat/modules/customization/modules/clothing/masks/gasmask.dm index 75bd6b05d4a..9174700e738 100644 --- a/modular_skyrat/modules/customization/modules/clothing/masks/gasmask.dm +++ b/modular_skyrat/modules/customization/modules/clothing/masks/gasmask.dm @@ -55,7 +55,6 @@ clothing_flags = MASKINTERNALS flags_cover = MASKCOVERSEYES resistance_flags = FLAMMABLE - species_exception = list(/datum/species/golem/bananium) has_fov = FALSE greyscale_config = /datum/greyscale_config/clown_mask greyscale_config_worn = /datum/greyscale_config/clown_mask/worn @@ -72,7 +71,6 @@ inhand_icon_state = null flags_cover = MASKCOVERSEYES resistance_flags = FLAMMABLE - species_exception = list(/datum/species/golem/bananium) /obj/item/clothing/mask/gas/respirator name = "half mask respirator" diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/custom_bodytype.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/custom_bodytype.dm index 0639d1fbcdf..f3ce6b8b109 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/custom_bodytype.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/custom_bodytype.dm @@ -57,8 +57,9 @@ * Arguments: * * item_slot: The slot we're updating. One of LOADOUT_ITEM_HEAD, etc. * * item: The item being rendered. + * * human_owner: The human wearing the item. */ -/datum/species/proc/generate_custom_worn_icon(item_slot, obj/item/item) +/datum/species/proc/generate_custom_worn_icon(item_slot, obj/item/item, mob/living/carbon/human/human_owner) // If already set (possibly by us, or manually, use it.) var/icon/final_icon = get_custom_worn_icon(item_slot, item) if(final_icon && icon_exists(final_icon, item.worn_icon_state || item.icon_state)) @@ -82,7 +83,7 @@ /** * Generate a fallback worn icon, if the species supports it. You must call it in an override of generate_custom_worn_icon() */ -/datum/species/proc/generate_custom_worn_icon_fallback(item_slot, obj/item/item) +/datum/species/proc/generate_custom_worn_icon_fallback(item_slot, obj/item/item, mob/living/carbon/human/human_owner) var/icon/human_icon = item.worn_icon || item.icon var/human_icon_state = item.worn_icon_state || item.icon_state diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm index 926667b8acb..efa851a5431 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm @@ -105,16 +105,14 @@ GLOBAL_LIST_EMPTY(customizable_races) var/height_offset = species_human.get_top_offset() // From high changed by varying limb height var/list/standing = list() - var/obj/item/bodypart/head/HD = species_human.get_bodypart(BODY_ZONE_HEAD) + var/obj/item/bodypart/head/noggin = species_human.get_bodypart(BODY_ZONE_HEAD) - if(HD && !(HAS_TRAIT(species_human, TRAIT_HUSK))) + if(noggin && !(HAS_TRAIT(species_human, TRAIT_HUSK))) // lipstick if(species_human.lip_style && (LIPS in species_traits)) var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/species/human/human_face.dmi', "lips_[species_human.lip_style]", -BODY_LAYER) lip_overlay.color = species_human.lip_color - if(OFFSET_FACE in species_human.dna.species.offset_features) - lip_overlay.pixel_x += species_human.dna.species.offset_features[OFFSET_FACE][1] - lip_overlay.pixel_y += species_human.dna.species.offset_features[OFFSET_FACE][2] + noggin.worn_face_offset?.apply_offset(lip_overlay) lip_overlay.pixel_y += height_offset standing += lip_overlay @@ -122,17 +120,15 @@ GLOBAL_LIST_EMPTY(customizable_races) if(!(NOEYESPRITES in species_traits)) var/obj/item/organ/internal/eyes/eye_organ = species_human.get_organ_slot(ORGAN_SLOT_EYES) var/mutable_appearance/no_eyeslay - var/add_pixel_x = 0 var/add_pixel_y = 0 //cut any possible vis overlays - if(length(body_vis_overlays)) + if(body_vis_overlays.len) SSvis_overlays.remove_vis_overlay(species_human, body_vis_overlays) - - if(OFFSET_FACE in species_human.dna.species.offset_features) - add_pixel_x = species_human.dna.species.offset_features[OFFSET_FACE][1] - add_pixel_y = species_human.dna.species.offset_features[OFFSET_FACE][2] - + var/list/feature_offset = noggin.worn_face_offset?.get_offset() + if(feature_offset) + add_pixel_x = feature_offset["x"] + add_pixel_y = feature_offset["y"] add_pixel_y += height_offset if(!eye_organ) @@ -149,8 +145,8 @@ GLOBAL_LIST_EMPTY(customizable_races) standing += eye_overlay if(eye_organ.is_emissive) var/mutable_appearance/eye_emissive = emissive_appearance_copy(eye_overlay, species_human) - eye_emissive.pixel_x += species_human.dna.species.offset_features[OFFSET_FACE][1] - eye_emissive.pixel_y += species_human.dna.species.offset_features[OFFSET_FACE][2] + eye_emissive.pixel_x += add_pixel_x + eye_emissive.pixel_y += add_pixel_y standing += eye_emissive //Underwear, Undershirts & Socks diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm index 6943d5381b2..e30f1138bfe 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm @@ -24,22 +24,6 @@ TRAIT_EASILY_WOUNDED, //theyre like fuckin skin and bones TRAIT_LITERATE, ) - offset_features = list( - OFFSET_UNIFORM = list(0,0), - OFFSET_ID = list(0,0), - OFFSET_GLOVES = list(0,0), - OFFSET_GLASSES = list(0,1), - OFFSET_EARS = list(0,1), - OFFSET_SHOES = list(0,0), - OFFSET_S_STORE = list(0,0), - OFFSET_FACEMASK = list(0,1), - OFFSET_HEAD = list(0,1), - OFFSET_FACE = list(0,1), - OFFSET_BELT = list(0,0), - OFFSET_BACK = list(0,0), - OFFSET_SUIT = list(0,0), - OFFSET_NECK = list(0,1), - ) toxic_food = DAIRY | PINEAPPLE disliked_food = VEGETABLES | FRUIT | CLOTH liked_food = RAW | MEAT diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/worn_overlays.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/worn_overlays.dm index 91660ed9367..a35a261439a 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/worn_overlays.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/worn_overlays.dm @@ -16,12 +16,7 @@ // Make new appearance so we don't break the real accessory overlay for other species, and treat it as final. return mutable_appearance(custom_accessory_icon, accessory_overlay.icon_state) - // Apply an offset only if we didn't apply a different appearance. - if(OFFSET_ACCESSORY in human_wearer.dna.species.offset_features) - accessory_overlay.pixel_x = human_wearer.dna.species.offset_features[OFFSET_ACCESSORY][1] - accessory_overlay.pixel_y = human_wearer.dna.species.offset_features[OFFSET_ACCESSORY][2] - else - accessory_overlay.pixel_x = 0 - accessory_overlay.pixel_y = 0 + var/obj/item/bodypart/chest/my_chest = human_wearer.get_bodypart(BODY_ZONE_CHEST) + my_chest?.worn_accessory_offset?.apply_offset(accessory_overlay) return accessory_overlay diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_helpers/human.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_helpers/human.dm index 18161d119d0..ce6aa14dfb2 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_helpers/human.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_helpers/human.dm @@ -251,9 +251,8 @@ if(!vagina_overlay) vagina_overlay = sex_toy?.build_worn_icon(default_layer = VAGINA_LAYER, default_icon_file = 'icons/mob/clothing/under/default.dmi', isinhands = FALSE, override_file = icon_file) - if(OFFSET_UNIFORM in dna.species.offset_features) - vagina_overlay?.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1] - vagina_overlay?.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2] + var/obj/item/bodypart/chest/chest_part = get_bodypart(BODY_ZONE_CHEST) + chest_part?.worn_uniform_offset?.apply_offset(vagina_overlay) // every day we stray further and further from god overlays_standing[VAGINA_LAYER] = vagina_overlay apply_overlay(VAGINA_LAYER) @@ -275,9 +274,9 @@ if(!anus_overlay) anus_overlay = sex_toy?.build_worn_icon(default_layer = ANUS_LAYER, default_icon_file = 'icons/mob/clothing/under/default.dmi', isinhands = FALSE, override_file = icon_file) - if(OFFSET_UNIFORM in dna.species.offset_features) - anus_overlay?.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1] - anus_overlay?.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2] + var/obj/item/bodypart/chest/chest_part = get_bodypart(BODY_ZONE_CHEST) + + chest_part?.worn_uniform_offset?.apply_offset(anus_overlay) // and i keep on asking myself... why? why do we do this? overlays_standing[ANUS_LAYER] = anus_overlay apply_overlay(ANUS_LAYER) @@ -299,9 +298,9 @@ if(!nipples_overlay) nipples_overlay = sex_toy?.build_worn_icon(default_layer = NIPPLES_LAYER, default_icon_file = 'icons/mob/clothing/under/default.dmi', isinhands = FALSE, override_file = icon_file) - if(OFFSET_UNIFORM in dna.species.offset_features) - nipples_overlay?.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1] - nipples_overlay?.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2] + var/obj/item/bodypart/chest/chest_part = get_bodypart(BODY_ZONE_CHEST) + chest_part?.worn_uniform_offset?.apply_offset(nipples_overlay) // then i realised something, something horrific + overlays_standing[NIPPLES_LAYER] = nipples_overlay apply_overlay(NIPPLES_LAYER) @@ -323,9 +322,9 @@ if(!penis_overlay) penis_overlay = sex_toy?.build_worn_icon(default_layer = PENIS_LAYER, default_icon_file = 'icons/mob/clothing/under/default.dmi', isinhands = FALSE, override_file = icon_file) - if(OFFSET_UNIFORM in dna.species.offset_features) - penis_overlay?.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1] - penis_overlay?.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2] + var/obj/item/bodypart/chest/chest_part = get_bodypart(BODY_ZONE_CHEST) + chest_part?.worn_uniform_offset?.apply_offset(penis_overlay) // we can never escape, we are forever governed by sex(two) + overlays_standing[PENIS_LAYER] = penis_overlay apply_overlay(PENIS_LAYER) diff --git a/modular_skyrat/modules/salon/code/misc_items.dm b/modular_skyrat/modules/salon/code/misc_items.dm index f5f4727a719..56b035d29f0 100644 --- a/modular_skyrat/modules/salon/code/misc_items.dm +++ b/modular_skyrat/modules/salon/code/misc_items.dm @@ -20,6 +20,9 @@ to_chat(user, span_warning("Where are the lips on that?")) return + INVOKE_ASYNC(src, PROC_REF(async_set_color), attacked_mob, user) + +/obj/item/lipstick/quantum/proc/async_set_color(mob/attacked_mob, mob/user) var/new_color = input( user, "Select lipstick color", diff --git a/modular_skyrat/modules/teshari/code/_teshari.dm b/modular_skyrat/modules/teshari/code/_teshari.dm index 3a8e8bd358e..ddc5391533e 100644 --- a/modular_skyrat/modules/teshari/code/_teshari.dm +++ b/modular_skyrat/modules/teshari/code/_teshari.dm @@ -42,7 +42,6 @@ LOADOUT_ITEM_ACCESSORY = TESHARI_ACCESSORIES_ICON, LOADOUT_ITEM_EARS = TESHARI_EARS_ICON ) - offset_features = list(OFFSET_UNIFORM = list(0,0), OFFSET_ID = list(0,0), OFFSET_GLOVES = list(0,0), OFFSET_GLASSES = list(0,0), OFFSET_EARS = list(0,-4), OFFSET_SHOES = list(0,0), OFFSET_S_STORE = list(0,0), OFFSET_FACEMASK = list(0,-5), OFFSET_HEAD = list(1,-4), OFFSET_FACE = list(0,0), OFFSET_BELT = list(0,0), OFFSET_BACK = list(0,-4), OFFSET_SUIT = list(0,0), OFFSET_NECK = list(0,0), OFFSET_ACCESSORY = list(0, -4)) coldmod = TESHARI_COLDMOD heatmod = TESHARI_HEATMOD brutemod = TESHARI_BRUTEMOD diff --git a/modular_skyrat/modules/teshari/code/teshari_bodytype.dm b/modular_skyrat/modules/teshari/code/teshari_bodytype.dm index db0882c55aa..1cefbd6dc55 100644 --- a/modular_skyrat/modules/teshari/code/teshari_bodytype.dm +++ b/modular_skyrat/modules/teshari/code/teshari_bodytype.dm @@ -18,30 +18,29 @@ return item.greyscale_config_worn_teshari_fallback -/datum/species/teshari/generate_custom_worn_icon(item_slot, obj/item/item) +/datum/species/teshari/generate_custom_worn_icon(item_slot, obj/item/item, mob/living/carbon/human/human_owner) . = ..() if(.) return // Use the fancy fallback sprites. - . = generate_custom_worn_icon_fallback(item_slot, item) + . = generate_custom_worn_icon_fallback(item_slot, item, human_owner) if(.) return // If there isn't even a fallback, use snouted sprites for masks and helmets, but offsetted if((item_slot == LOADOUT_ITEM_MASK || item_slot == LOADOUT_ITEM_HEAD) && (item.supports_variations_flags & CLOTHING_SNOUTED_VARIATION)) + var/obj/item/bodypart/head/my_head = human_owner.get_bodypart(BODY_ZONE_HEAD) + var/datum/worn_feature_offset/selected_offset var/human_icon - var/offset_x - var/offset_y var/human_icon_state = item.worn_icon_state || item.icon_state if(item_slot == LOADOUT_ITEM_HEAD) + human_icon = item.worn_icon_muzzled || SNOUTED_HEAD_FILE - offset_x = offset_features[OFFSET_HEAD][1] - offset_y = offset_features[OFFSET_HEAD][2] + selected_offset = my_head?.worn_head_offset else human_icon = item.worn_icon_muzzled || SNOUTED_MASK_FILE - offset_x = offset_features[OFFSET_FACEMASK][1] + MASK_SNOUT_EXTRA_OFFSET_X - offset_y = offset_features[OFFSET_FACEMASK][2] + MASK_SNOUT_EXTRA_OFFSET_Y + selected_offset = my_head?.worn_mask_offset // Did the snout variation flag lie to us? if(!icon_exists(human_icon, human_icon_state)) @@ -55,7 +54,8 @@ // Generate muzzled icon, but offset var/icon/new_icon = icon('icons/blanks/32x32.dmi', "nothing") - new_icon.Blend( icon(human_icon, human_icon_state), ICON_OVERLAY, x = offset_x, y = offset_y) + selected_offset?.apply_offset(new_icon) + new_icon.Blend(icon(human_icon, human_icon_state), ICON_OVERLAY) new_icon.Insert(new_icon, human_icon_state) set_custom_worn_icon_cached(human_icon, human_icon_state, "m", new_icon) return new_icon diff --git a/tgstation.dme b/tgstation.dme index 02a16a22a8c..674b1313253 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1145,6 +1145,7 @@ #include "code\datums\components\fantasy\suffixes.dm" #include "code\datums\components\food\decomposition.dm" #include "code\datums\components\food\edible.dm" +#include "code\datums\components\food\golem_food.dm" #include "code\datums\components\food\ice_cream_holder.dm" #include "code\datums\components\pet_commands\fetch.dm" #include "code\datums\components\pet_commands\obeys_commands.dm" @@ -2147,6 +2148,9 @@ #include "code\game\objects\items\stacks\telecrystal.dm" #include "code\game\objects\items\stacks\tickets.dm" #include "code\game\objects\items\stacks\wrap.dm" +#include "code\game\objects\items\stacks\golem_food\golem_food_buff.dm" +#include "code\game\objects\items\stacks\golem_food\golem_hand_actions.dm" +#include "code\game\objects\items\stacks\golem_food\golem_status_effects.dm" #include "code\game\objects\items\stacks\sheets\glass.dm" #include "code\game\objects\items\stacks\sheets\hot_ice.dm" #include "code\game\objects\items\stacks\sheets\leather.dm" @@ -5039,6 +5043,7 @@ #include "code\modules\surgery\bodyparts\helpers.dm" #include "code\modules\surgery\bodyparts\parts.dm" #include "code\modules\surgery\bodyparts\robot_bodyparts.dm" +#include "code\modules\surgery\bodyparts\worn_feature_offset.dm" #include "code\modules\surgery\bodyparts\wounds.dm" #include "code\modules\surgery\bodyparts\species_parts\android_parts.dm" #include "code\modules\surgery\bodyparts\species_parts\ethereal_bodyparts.dm" @@ -5048,6 +5053,7 @@ #include "code\modules\surgery\bodyparts\species_parts\plasmaman_bodyparts.dm" #include "code\modules\surgery\organs\_organ.dm" #include "code\modules\surgery\organs\appendix.dm" +#include "code\modules\surgery\organs\appendix_golem.dm" #include "code\modules\surgery\organs\augments_arms.dm" #include "code\modules\surgery\organs\augments_chest.dm" #include "code\modules\surgery\organs\augments_eyes.dm" @@ -5071,6 +5077,7 @@ #include "code\modules\surgery\organs\external\wings\wings.dm" #include "code\modules\surgery\organs\stomach\_stomach.dm" #include "code\modules\surgery\organs\stomach\stomach_ethereal.dm" +#include "code\modules\surgery\organs\stomach\stomach_golem.dm" #include "code\modules\tgchat\message.dm" #include "code\modules\tgchat\to_chat.dm" #include "code\modules\tgs\includes.dm" @@ -5820,6 +5827,7 @@ #include "modular_skyrat\modules\bodyparts\code\luminescent_bodyparts.dm" #include "modular_skyrat\modules\bodyparts\code\moth_bodyparts.dm" #include "modular_skyrat\modules\bodyparts\code\mushperson_bodyparts.dm" +#include "modular_skyrat\modules\bodyparts\code\parts.dm" #include "modular_skyrat\modules\bodyparts\code\podperson_bodyparts.dm" #include "modular_skyrat\modules\bodyparts\code\roundstartslime_bodyparts.dm" #include "modular_skyrat\modules\bodyparts\code\skrell_bodyparts.dm" diff --git a/tgui/packages/tgui/interfaces/PersonalCrafting.tsx b/tgui/packages/tgui/interfaces/PersonalCrafting.tsx index a9f7e5e0e3c..fa255709c2f 100644 --- a/tgui/packages/tgui/interfaces/PersonalCrafting.tsx +++ b/tgui/packages/tgui/interfaces/PersonalCrafting.tsx @@ -27,6 +27,7 @@ const TYPE_ICONS = { [Food.Pineapple]: 'apple-alt', [Food.Raw]: 'drumstick-bite', [Food.Seafood]: 'fish', + [Food.Stone]: 'gem', [Food.Sugar]: 'candy-cane', [Food.Toxic]: 'biohazard', [Food.Vegetables]: 'carrot', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/SpeciesPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/SpeciesPage.tsx index afe4166c576..0ba890e18bc 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/SpeciesPage.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/SpeciesPage.tsx @@ -19,6 +19,7 @@ const FOOD_ICONS = { [Food.Nuts]: 'seedling', [Food.Raw]: 'drumstick-bite', [Food.Seafood]: 'fish', + [Food.Stone]: 'gem', [Food.Sugar]: 'candy-cane', [Food.Toxic]: 'biohazard', [Food.Vegetables]: 'carrot', @@ -38,6 +39,7 @@ const FOOD_NAMES: Record = { [Food.Nuts]: 'Nuts', [Food.Raw]: 'Raw', [Food.Seafood]: 'Seafood', + [Food.Stone]: 'Rocks', [Food.Sugar]: 'Sugar', [Food.Toxic]: 'Toxic food', [Food.Vegetables]: 'Vegetables', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/data.ts b/tgui/packages/tgui/interfaces/PreferencesMenu/data.ts index 3d6d5734316..5f3f2bfbf73 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/data.ts +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/data.ts @@ -20,6 +20,7 @@ export enum Food { Pineapple = 'PINEAPPLE', Raw = 'RAW', Seafood = 'SEAFOOD', + Stone = 'STONE', Sugar = 'SUGAR', Toxic = 'TOXIC', Vegetables = 'VEGETABLES',