diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm
index d820becdbc8..2b40301fbf9 100644
--- a/code/__DEFINES/DNA.dm
+++ b/code/__DEFINES/DNA.dm
@@ -81,30 +81,28 @@
#define NOBLOOD 6
#define NOTRANSSTING 7
#define NOZOMBIE 8
-/// Uses weird leg sprites. Optional for Lizards, required for ashwalkers. Don't give it to other races unless you make sprites for this (see human_parts_greyscale.dmi)
-#define DIGITIGRADE 9
-#define NO_UNDERWEAR 10
-#define NOSTOMACH 11
-#define NO_DNA_COPY 12
-#define DRINKSBLOOD 13
+#define NO_UNDERWEAR 9
+#define NOSTOMACH 10
+#define NO_DNA_COPY 11
+#define DRINKSBLOOD 12
/// Use this if you want to change the race's color without the player being able to pick their own color. AKA special color shifting
-#define DYNCOLORS 14
-#define AGENDER 15
+#define DYNCOLORS 13
+#define AGENDER 14
/// Do not draw eyes or eyeless overlay
-#define NOEYESPRITES 16
+#define NOEYESPRITES 15
/// Used for determining which wounds are applicable to this species.
/// if we have flesh (can suffer slash/piercing/burn wounds, requires they don't have NOBLOOD)
-#define HAS_FLESH 17
+#define HAS_FLESH 16
/// if we have bones (can suffer bone wounds)
-#define HAS_BONE 18
+#define HAS_BONE 17
///If we have a limb-specific overlay sprite
-#define HAS_MARKINGS 19
+#define HAS_MARKINGS 18
/// Do not draw blood overlay
-#define NOBLOODOVERLAY 20
+#define NOBLOODOVERLAY 19
///No augments, for monkeys in specific because they will turn into fucking freakazoids https://cdn.discordapp.com/attachments/326831214667235328/791313258912153640/102707682-fa7cad80-4294-11eb-8f13-8c689468aeb0.png
-#define NOAUGMENTS 21
+#define NOAUGMENTS 20
///will be assigned a universal vampire themed last name shared by their department. this is preferenced!
-#define BLOOD_CLANS 22
+#define BLOOD_CLANS 21
//organ slots
#define ORGAN_SLOT_ADAMANTINE_RESONATOR "adamantine_resonator"
@@ -163,7 +161,7 @@
#define CHROMOSOME_NONE 1
#define CHROMOSOME_USED 2
-//used for mob's genetic gender (mainly just for pronouns, members of sexed species with plural gender refer to their body_type for the actual sprites, which is not genetic)
+//used for mob's genetic gender (mainly just for pronouns, members of sexed species with plural gender refer to their physique for the actual sprites, which is not genetic)
#define G_MALE 1
#define G_FEMALE 2
#define G_PLURAL 3
@@ -201,42 +199,10 @@ GLOBAL_LIST_INIT(organ_process_order, list(
ORGAN_SLOT_XENO_NEUROTOXINGLAND,
ORGAN_SLOT_XENO_EGGSAC,))
-//Defines for Species IDs
-#define SPECIES_HUMAN "human"
-#define SPECIES_FELINE "felinid"
-#define SPECIES_MOTH "moth"
-#define SPECIES_ETHEREAL "ethereal"
-#define SPECIES_PLASMAMAN "plasmaman"
-#define SPECIES_FLY "fly"
-#define SPECIES_MONKEY "monkey"
-#define SPECIES_JELLYPERSON "jelly"
-#define SPECIES_SLIMEPERSON "slime"
-#define SPECIES_LUMINESCENT "lum"
-#define SPECIES_STARGAZER "stargazer"
-#define SPECIES_LIZARD "lizard"
-#define SPECIES_LIZARD_ASH "ashlizard"
-#define SPECIES_LIZARD_SILVER "silverlizard"
-#define SPECIES_DULLAHAN "dullahan"
-#define SPECIES_SKELETON "skeleton"
-#define SPECIES_VAMPIRE "vampire"
-#define SPECIES_ZOMBIE "memezombies"
-#define SPECIES_ZOMBIE_HALLOWEEN "zombie"
-#define SPECIES_ADDICT "goofzombies"
-
-#define SPECIES_ABDUCTOR "abductor"
-#define SPECIES_ANDROID "android"
-#define SPECIES_MUSHROOM "mush"
-#define SPECIES_PODPERSON "pod"
-#define SPECIES_SHADOW "shadow"
-#define SPECIES_NIGHTMARE "nightmare"
-#define SPECIES_SNAIL "snail"
-#define SPECIES_SYNTH "synth"
-#define SPECIES_SYNTH_MILITARY "military_synth"
-
//Defines for Golem Species IDs
-#define SPECIES_GOLEM "iron_golem"
-#define SPECIES_GOLEM_ADAMANTINE "adamantine_golem"
-#define SPECIES_GOLEM_PLASMA "plasma_golem"
+#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"
@@ -249,16 +215,16 @@ GLOBAL_LIST_INIT(organ_process_order, list(
#define SPECIES_GOLEM_SAND "sand_golem"
#define SPECIES_GOLEM_GLASS "glass_golem"
#define SPECIES_GOLEM_BLUESPACE "bluespace_golem"
-#define SPECIES_GOLEM_BANANIUM "bananium_golem"
-#define SPECIES_GOLEM_CULT "runic_golem"
-#define SPECIES_GOLEM_CLOTH "cloth_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 "cardboard_golem"
+#define SPECIES_GOLEM_CARDBOARD "c_golem"
#define SPECIES_GOLEM_LEATHER "leather_golem"
-#define SPECIES_GOLEM_DURATHREAD "durathread_golem"
-#define SPECIES_GOLEM_BONE "bone_golem"
-#define SPECIES_GOLEM_SNOW "snow_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.
diff --git a/code/__DEFINES/bodyparts.dm b/code/__DEFINES/bodyparts.dm
new file mode 100644
index 00000000000..5c575184273
--- /dev/null
+++ b/code/__DEFINES/bodyparts.dm
@@ -0,0 +1,2 @@
+///The standard amount of bodyparts a carbon has. Currently 6, HEAD/L_ARM/R_ARM/CHEST/L_LEG/R_LEG
+#define BODYPARTS_DEFAULT_MAXIMUM 6
diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm
index 0d81b179fee..7921d0da933 100644
--- a/code/__DEFINES/inventory.dm
+++ b/code/__DEFINES/inventory.dm
@@ -148,13 +148,25 @@
#define ALT_STYLE 1
#define DIGITIGRADE_STYLE 2
-//flags for outfits that have mutantrace variants (try not to use this): Currently only needed if you're trying to add tight fitting bootyshorts
-#define NO_MUTANTRACE_VARIATION 0
-#define MUTANTRACE_VARIATION 1
-
-#define NOT_DIGITIGRADE 0
-#define FULL_DIGITIGRADE 1
-#define SQUISHED_DIGITIGRADE 2
+//Flags (actual flags, fucker ^) for /obj/item/var/supports_variations_flags
+///No alternative sprites based on bodytype
+#define CLOTHING_NO_VARIATION (1<<0)
+///Has a sprite for digitigrade legs specifically.
+#define CLOTHING_DIGITIGRADE_VARIATION (1<<1)
+///The sprite works fine for digitigrade legs as-is.
+#define CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON (1<<2)
+// SKYRAT EDIT ADDITION
+/// The sprite works fine for snouts.
+#define CLOTHING_SNOUTED_VARIATION (1<<3)
+/// The sprite works fine for snouts as-is.
+#define CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON (1<<4)
+/// The sprite works fine for vox snouts.
+#define CLOTHING_SNOUTED_VOX_VARIATION (1<<5)
+/// The sprite works fine for vox snouts as is.
+#define CLOTHING_SNOUTED_VOX_VARIATION_NO_NEW_ICON (1<<6)
+/// The sprite works fine for vox snouts.
+#define CLOTHING_VOX_HAND_VARIATION (1<<7)
+// SKYRAT EDIT END
//flags for covering body parts
#define GLASSESCOVERSEYES (1<<0)
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 43ceef46f0a..ab4e0830ca5 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -49,13 +49,11 @@
#define MOB_SPIRIT (1 << 9)
#define MOB_PLANT (1 << 10)
+
//Organ defines for carbon mobs
#define ORGAN_ORGANIC 1
#define ORGAN_ROBOTIC 2
-#define BODYPART_ORGANIC 1
-#define BODYPART_ROBOTIC 2
-
#define DEFAULT_BODYPART_ICON_ORGANIC 'icons/mob/human_parts_greyscale.dmi'
#define DEFAULT_BODYPART_ICON_ROBOTIC 'icons/mob/augmentation/augments.dmi'
@@ -63,7 +61,68 @@
#define ALIEN_BODYPART "alien"
#define LARVA_BODYPART "larva"
+//Bodypart change blocking flags
+///Bodypart does not get replaced during set_species()
+#define BP_BLOCK_CHANGE_SPECIES (1<<0)
+//Bodytype defines for how things can be worn, surgery, and other misc things.
+///The limb is organic
+#define BODYTYPE_ORGANIC (1<<0)
+///The limb is robotic
+#define BODYTYPE_ROBOTIC (1<<1)
+///The limb fits the human mold
+#define BODYTYPE_HUMANOID (1<<2)
+///The limb is digitigrade
+#define BODYTYPE_DIGITIGRADE (1<<3) //Cancer
+///The limb fits the monkey mold
+#define BODYTYPE_MONKEY (1<<4)
+///The limb is snouted
+#define BODYTYPE_SNOUTED (1<<5)
+// SKYRAT EDIT ADDITION
+///The limb fits the vox shape
+#define BODYTYPE_VOX (1<<6)
+///The limb fits the teshari shape
+#define BODYTYPE_TESHARI (1<<7)
+// SKYRAT EDIT END
+
+//Defines for Species IDs
+#define SPECIES_ABDUCTOR "abductor"
+#define SPECIES_ANDROID "android"
+#define SPECIES_DULLAHAN "dullahan"
+#define SPECIES_ETHEREAL "ethereal"
+#define SPECIES_FELINE "felinid"
+#define SPECIES_FLYPERSON "fly"
+#define SPECIES_HUMAN "human"
+#define SPECIES_JELLYPERSON "jelly"
+#define SPECIES_SLIMEPERSON "slime"
+#define SPECIES_LUMINESCENT "luminescent"
+#define SPECIES_STARGAZER "stargazer"
+#define SPECIES_LIZARD "lizard"
+#define SPECIES_LIZARD_ASH "ashwalker"
+#define SPECIES_LIZARD_SILVER "silverscale"
+#define SPECIES_NIGHTMARE "nightmare"
+#define SPECIES_MONKEY "monkey"
+#define SPECIES_MOTH "moth"
+#define SPECIES_MUSHROOM "mush"
+#define SPECIES_PLASMAMAN "plasmaman"
+#define SPECIES_PODPERSON "pod"
+#define SPECIES_SHADOW "shadow"
+#define SPECIES_SKELETON "skeleton"
+#define SPECIES_SNAIL "snail"
+#define SPECIES_VAMPIRE "vampire"
+#define SPECIES_ZOMBIE "zombie"
+#define SPECIES_ZOMBIE_INFECTIOUS "memezombie"
+#define SPECIES_ZOMBIE_KROKODIL "krokodil_zombie"
+
+//See: datum/species/var/digitigrade_customization
+///The species does not have digitigrade legs in generation.
+#define DIGITIGRADE_NEVER 0
+///The species can have digitigrade legs in generation
+#define DIGITIGRADE_OPTIONAL 1
+///The species is forced to have digitigrade legs in generation.
+#define DIGITIGRADE_FORCED 2
+
+//TODO: Remove entirely in favor of the BODYTYPE system
///Body type bitfields for allowed_animal_origin used to check compatible surgery body types (use NONE for no matching body type)
#define HUMAN_BODY (1 << 0)
#define MONKEY_BODY (1 << 1)
diff --git a/code/__DEFINES/species_clothing_paths.dm b/code/__DEFINES/species_clothing_paths.dm
new file mode 100644
index 00000000000..a215b37aaab
--- /dev/null
+++ b/code/__DEFINES/species_clothing_paths.dm
@@ -0,0 +1,15 @@
+//HUMAN PATHS
+///The dmi for humanoid uniforms
+#define DEFAULT_UNIFORM_FILE 'icons/mob/clothing/under/default.dmi'
+///The dmi for humanoid shoes
+#define DEFAULT_SHOES_FILE 'icons/mob/clothing/feet.dmi'
+///The dmi for humanoid oversuits
+#define DEFAULT_SUIT_FILE 'icons/mob/clothing/suit.dmi'
+
+//DIGITIGRADE PATHS
+///The dmi containing digitigrade uniforms
+#define DIGITIGRADE_UNIFORM_FILE 'modular_skyrat/master_files/icons/mob/clothing/uniform_digi.dmi' // SKYRAT EDIT CHANGE
+///The dmi containing digitigrade shoes
+#define DIGITIGRADE_SHOES_FILE 'modular_skyrat/master_files/icons/mob/clothing/feet_digi.dmi' // SKYRAT EDIT CHANGE
+///The dmi containing digitigrade oversuits
+#define DIGITIGRADE_SUIT_FILE 'modular_skyrat/master_files/icons/mob/clothing/suit_digi.dmi' // SKYRAT EDIT CHANGE
diff --git a/code/__DEFINES/~skyrat_defines/_HELPERS/lighting.dm b/code/__DEFINES/~skyrat_defines/_HELPERS/lighting.dm
new file mode 100644
index 00000000000..7c5b94ff629
--- /dev/null
+++ b/code/__DEFINES/~skyrat_defines/_HELPERS/lighting.dm
@@ -0,0 +1,7 @@
+/// Creates a mutable appearance glued to the EMISSIVE_PLAN, using the values from a mutable appearance
+/proc/emissive_appearance_copy(mutable_appearance/to_use, appearance_flags = (RESET_COLOR|KEEP_APART))
+ var/mutable_appearance/appearance = mutable_appearance(to_use.icon, to_use.icon_state, to_use.layer, EMISSIVE_PLANE, to_use.alpha, to_use.appearance_flags | appearance_flags)
+ appearance.color = GLOB.emissive_color
+ appearance.pixel_x = to_use.pixel_x
+ appearance.pixel_y = to_use.pixel_y
+ return appearance
diff --git a/code/__DEFINES/~skyrat_defines/inventory.dm b/code/__DEFINES/~skyrat_defines/inventory.dm
index 5fa7a77dbcf..9ae86967643 100644
--- a/code/__DEFINES/~skyrat_defines/inventory.dm
+++ b/code/__DEFINES/~skyrat_defines/inventory.dm
@@ -1,9 +1,6 @@
//flags for outfits that have mutant variants: Most of these require additional sprites to work.
-#define STYLE_DIGITIGRADE (1<<0) //jumpsuits, suits and shoes
-#define STYLE_MUZZLE (1<<1) //hats or masks
#define STYLE_TAUR_SNAKE (1<<2) //taur-friendly suits
#define STYLE_TAUR_PAW (1<<3)
#define STYLE_TAUR_HOOF (1<<4)
#define STYLE_TAUR_ALL (STYLE_TAUR_SNAKE|STYLE_TAUR_PAW|STYLE_TAUR_HOOF)
-#define STYLE_VOX (1<<5) //For glasses, masks and head pieces for the Vox race
#define STYLE_TESHARI (1<<6) //teshari clothes and shit
diff --git a/code/__DEFINES/~skyrat_defines/reskin_defines.dm b/code/__DEFINES/~skyrat_defines/reskin_defines.dm
index c43e44a86d5..6d4eac86f44 100644
--- a/code/__DEFINES/~skyrat_defines/reskin_defines.dm
+++ b/code/__DEFINES/~skyrat_defines/reskin_defines.dm
@@ -2,4 +2,4 @@
#define RESKIN_ICON_STATE "reskin_icon_state"
#define RESKIN_WORN_ICON "reskin_worn_icon"
#define RESKIN_WORN_ICON_STATE "reskin_worn_icon_state"
-#define RESKIN_MUTANT_VARIANTS "reskin_mutant_variants"
+#define RESKIN_supports_variations_flags "reskin_supports_variations_flags"
diff --git a/code/__DEFINES/~skyrat_defines/species_clothing_paths.dm b/code/__DEFINES/~skyrat_defines/species_clothing_paths.dm
new file mode 100644
index 00000000000..4152d9db82c
--- /dev/null
+++ b/code/__DEFINES/~skyrat_defines/species_clothing_paths.dm
@@ -0,0 +1,8 @@
+///The dmi containing snouted masks
+#define SNOUTED_MASK_FILE 'modular_skyrat/master_files/icons/mob/clothing/mask_muzzled.dmi'
+///The dmi containing snouted hats
+#define SNOUTED_HEAD_FILE 'modular_skyrat/master_files/icons/mob/clothing/head_muzzled.dmi'
+
+// Vox stuff
+///The dmi containing vox glasses
+#define VOX_GLASSES_FILE 'modular_skyrat/master_files/icons/mob/clothing/species/vox/eyes.dmi'
diff --git a/code/__HELPERS/bodyparts.dm b/code/__HELPERS/bodyparts.dm
new file mode 100644
index 00000000000..39df8e37e5f
--- /dev/null
+++ b/code/__HELPERS/bodyparts.dm
@@ -0,0 +1 @@
+#define IS_ORGANIC_LIMB(limb) (limb.bodytype & BODYTYPE_ORGANIC)
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index ba710bd7d40..8a8146a6484 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -1276,3 +1276,26 @@ GLOBAL_LIST_EMPTY(transformation_animation_objects)
animate(src, pixel_x = pixel_x + shiftx, pixel_y = pixel_y + shifty, time = 0.2, loop = duration)
pixel_x = initialpixelx
pixel_y = initialpixely
+
+///Checks if the given iconstate exists in the given file, caching the result. Setting scream to TRUE will print a stack trace ONCE.
+/proc/icon_exists(file, state, scream)
+ var/static/list/icon_states_cache = list()
+ if(icon_states_cache[file]?[state])
+ return TRUE
+
+ if(icon_states_cache[file]?[state] == FALSE)
+ return FALSE
+
+ var/list/states = icon_states(file)
+
+ if(!icon_states_cache[file])
+ icon_states_cache[file] = list()
+
+ if(state in states)
+ icon_states_cache[file][state] = TRUE
+ return TRUE
+ else
+ icon_states_cache[file][state] = FALSE
+ if(scream)
+ stack_trace("Icon Lookup for state: [state] in file [file] failed.")
+ return FALSE
diff --git a/code/__HELPERS/lighting.dm b/code/__HELPERS/lighting.dm
index d4f8b98b9f6..8c468f5357a 100644
--- a/code/__HELPERS/lighting.dm
+++ b/code/__HELPERS/lighting.dm
@@ -10,11 +10,3 @@
appearance.color = GLOB.em_block_color
return appearance
-//SKYRAT EDIT ADDITION
-/// Creates a mutable appearance glued to the EMISSIVE_PLAN, using the values from a mutable appearance
-/proc/emissive_appearance_copy(mutable_appearance/to_use, appearance_flags = (RESET_COLOR|KEEP_APART))
- var/mutable_appearance/appearance = mutable_appearance(to_use.icon, to_use.icon_state, to_use.layer, EMISSIVE_PLANE, to_use.alpha, to_use.appearance_flags | appearance_flags)
- appearance.color = GLOB.emissive_color
- appearance.pixel_x = to_use.pixel_x
- appearance.pixel_y = to_use.pixel_y
- return appearance
diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm
index cb53a39aaab..dba1db8c4bd 100644
--- a/code/__HELPERS/type2type.dm
+++ b/code/__HELPERS/type2type.dm
@@ -153,7 +153,7 @@ GLOBAL_LIST_INIT(modulo_angle_to_dir, list(NORTH,NORTHEAST,EAST,SOUTHEAST,SOUTH,
return .
/// For finding out what body parts a body zone covers, the inverse of the below basically
-/proc/zone2body_parts_covered(def_zone)
+/proc/body_zone2cover_flags(def_zone)
switch(def_zone)
if(BODY_ZONE_CHEST)
return list(CHEST, GROIN)
@@ -169,14 +169,14 @@ GLOBAL_LIST_INIT(modulo_angle_to_dir, list(NORTH,NORTHEAST,EAST,SOUTHEAST,SOUTH,
return list(LEG_RIGHT, FOOT_RIGHT)
//Turns a Body_parts_covered bitfield into a list of organ/limb names.
-//(I challenge you to find a use for this) -I found a use for it!!
-/proc/body_parts_covered2organ_names(bpc)
+//(I challenge you to find a use for this) -I found a use for it!! | So did I!.
+/proc/cover_flags2body_zones(bpc)
var/list/covered_parts = list()
if(!bpc)
return 0
- if(bpc & FULL_BODY)
+ if(bpc == FULL_BODY)
covered_parts |= list(BODY_ZONE_L_ARM,BODY_ZONE_R_ARM,BODY_ZONE_HEAD,BODY_ZONE_CHEST,BODY_ZONE_L_LEG,BODY_ZONE_R_LEG)
else
diff --git a/code/__HELPERS/type_processing.dm b/code/__HELPERS/type_processing.dm
index 4df4cece096..98aed39eba1 100644
--- a/code/__HELPERS/type_processing.dm
+++ b/code/__HELPERS/type_processing.dm
@@ -6,6 +6,7 @@
var/typename = "[type]"
var/static/list/TYPES_SHORTCUTS = list(
/obj/effect/decal/cleanable = "CLEANABLE",
+ /obj/item/bodypart = "BODYPART",
/obj/item/radio/headset = "HEADSET",
/obj/item/clothing/head/helmet/space = "SPESSHELMET",
/obj/item/book/manual = "MANUAL",
diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm
index cdd1cc60bcd..0be6e0c82ff 100644
--- a/code/_globalvars/bitfields.dm
+++ b/code/_globalvars/bitfields.dm
@@ -355,3 +355,18 @@ DEFINE_BITFIELD(reaction_flags, list(
"REACTION_PH_VOL_CONSTANT" = REACTION_PH_VOL_CONSTANT,
"REACTION_REAL_TIME_SPLIT" = REACTION_REAL_TIME_SPLIT,
))
+
+DEFINE_BITFIELD(bodytype, list(
+ "BODYTYPE_DIGITIGRADE" = BODYTYPE_DIGITIGRADE,
+ "BODYTYPE_HUMANOID" = BODYTYPE_HUMANOID,
+ "BODYTYPE_MONKEY" = BODYTYPE_MONKEY,
+ "BODYTYPE_ORGANIC" = BODYTYPE_ORGANIC,
+ "BODYTYPE_ROBOTIC" = BODYTYPE_ROBOTIC,
+ "BODYTYPE_SNOUTED" = BODYTYPE_SNOUTED,
+))
+
+DEFINE_BITFIELD(supports_variations_flags, list(
+ "CLOTHING_NO_VARIATION" = CLOTHING_NO_VARIATION,
+ "CLOTHING_DIGITIGRADE_VARIATION" = CLOTHING_DIGITIGRADE_VARIATION,
+ "CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON" = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON,
+))
diff --git a/code/_globalvars/phobias.dm b/code/_globalvars/phobias.dm
index 1394b074d33..64afd556a2a 100644
--- a/code/_globalvars/phobias.dm
+++ b/code/_globalvars/phobias.dm
@@ -493,7 +493,6 @@ GLOBAL_LIST_INIT(phobia_species, list(
"conspiracies" = typecacheof(list(
/datum/species/abductor,
/datum/species/lizard,
- /datum/species/synth,
)),
"insects" = typecacheof(list(
/datum/species/fly,
diff --git a/code/datums/brain_damage/phobia.dm b/code/datums/brain_damage/phobia.dm
index 9c4b5053841..16c10c5fd3c 100644
--- a/code/datums/brain_damage/phobia.dm
+++ b/code/datums/brain_damage/phobia.dm
@@ -52,7 +52,7 @@
freak_out(O)
return
for(var/mob/living/carbon/human/HU in seen_atoms) //check equipment for trigger items
- for(var/X in HU.get_all_slots() | HU.held_items)
+ for(var/X in HU.get_all_worn_items() | HU.held_items)
var/obj/I = X
if(!QDELETED(I) && (is_type_in_typecache(I, trigger_objs) || (phobia_type == "blood" && HAS_BLOOD_DNA(I))))
freak_out(I)
@@ -213,7 +213,7 @@
/datum/brain_trauma/mild/phobia/guns
phobia_type = "guns"
random_gain = FALSE
-
+
/datum/brain_trauma/mild/phobia/blood
phobia_type = "blood"
random_gain = FALSE
diff --git a/code/datums/components/bloodysoles.dm b/code/datums/components/bloodysoles.dm
index e6322e8c2d3..1c8969cfec1 100644
--- a/code/datums/components/bloodysoles.dm
+++ b/code/datums/components/bloodysoles.dm
@@ -241,7 +241,6 @@
/datum/component/bloodysoles/feet/update_icon()
if(ishuman(wielder))
var/mob/living/carbon/human/human = wielder
- fix_soles() //SKYRAT ADDITION - DIGI_BLOODSOLE
if(NOBLOODOVERLAY in human.dna.species.species_traits)
return
if(bloody_shoes[BLOOD_STATE_HUMAN] > 0 && !is_obscured())
@@ -261,7 +260,7 @@
var/obj/item/bodypart/affecting = X
if(affecting.body_part == LEG_RIGHT || affecting.body_part == LEG_LEFT)
if(!affecting.bodypart_disabled)
- FP.species_types |= affecting.species_id
+ FP.species_types |= affecting.limb_id
break
@@ -282,15 +281,6 @@
..()
-//SKYRAT EDIT ADDITION BEGIN - DIGI_BLOODSOLE
-/datum/component/bloodysoles/feet/proc/fix_soles()
- var/mob/living/carbon/H = parent
- if (DIGITIGRADE in H.dna.species.species_traits)
- if (bloody_feet.icon_state != "shoeblood_digi")
- bloody_feet = mutable_appearance('modular_skyrat/modules/digi_bloodsole/icons/blood.dmi', "shoeblood_digi", SHOES_LAYER)
- else if (bloody_feet.icon_state != "shoeblood")
- bloody_feet = mutable_appearance('icons/effects/blood.dmi', "shoeblood", SHOES_LAYER)
-//SKYRAT EDIT ADDITION END
/datum/component/bloodysoles/feet/proc/unequip_shoecover(datum/source)
SIGNAL_HANDLER
diff --git a/code/datums/components/caltrop.dm b/code/datums/components/caltrop.dm
index 8c2f617d1aa..57cab668741 100644
--- a/code/datums/components/caltrop.dm
+++ b/code/datums/components/caltrop.dm
@@ -89,7 +89,7 @@
if(!istype(O))
return
- if(O.status == BODYPART_ROBOTIC)
+ if(!IS_ORGANIC_LIMB(O))
return
if (!(flags & CALTROP_BYPASS_SHOES))
diff --git a/code/datums/components/creamed.dm b/code/datums/components/creamed.dm
index f718e22351a..53c92ba2513 100644
--- a/code/datums/components/creamed.dm
+++ b/code/datums/components/creamed.dm
@@ -25,9 +25,9 @@ GLOBAL_LIST_INIT(creamable, typecacheof(list(
if(ishuman(parent))
var/mob/living/carbon/human/H = parent
- if(H.dna.species.limbs_id == SPECIES_LIZARD)
+ if(H.dna.species.bodytype & BODYTYPE_SNOUTED)
creamface.icon_state = "creampie_lizard"
- else if(H.dna.species.limbs_id == SPECIES_MONKEY)
+ else if(H.dna.species.bodytype & BODYTYPE_MONKEY)
creamface.icon_state = "creampie_monkey"
else
creamface.icon_state = "creampie_human"
diff --git a/code/datums/components/surgery_initiator.dm b/code/datums/components/surgery_initiator.dm
index 4e41d6b2f81..4e66f8ab35c 100644
--- a/code/datums/components/surgery_initiator.dm
+++ b/code/datums/components/surgery_initiator.dm
@@ -89,7 +89,7 @@
if(affecting)
if(!surgery.requires_bodypart)
continue
- if(surgery.requires_bodypart_type && affecting.status != surgery.requires_bodypart_type)
+ if(surgery.requires_bodypart_type && !(affecting.bodytype & surgery.requires_bodypart_type))
continue
if(surgery.requires_real_bodypart && affecting.is_pseudopart)
continue
@@ -128,7 +128,7 @@
var/required_tool_type = TOOL_CAUTERY
var/obj/item/close_tool = user.get_inactive_held_item()
- var/is_robotic = the_surgery.requires_bodypart_type == BODYPART_ROBOTIC
+ var/is_robotic = the_surgery.requires_bodypart_type == BODYTYPE_ROBOTIC
if(is_robotic)
required_tool_type = TOOL_SCREWDRIVER
@@ -300,7 +300,7 @@
return
- if (!isnull(affecting_limb) && surgery.requires_bodypart_type && affecting_limb.status != surgery.requires_bodypart_type)
+ if (!isnull(affecting_limb) && surgery.requires_bodypart_type && !(affecting_limb.bodytype & surgery.requires_bodypart_type))
target.balloon_alert(user, "not the right type of limb!")
return
diff --git a/code/datums/components/unbreakable.dm b/code/datums/components/unbreakable.dm
index 8261dd6d3cb..0d27f7bc39c 100644
--- a/code/datums/components/unbreakable.dm
+++ b/code/datums/components/unbreakable.dm
@@ -24,7 +24,7 @@
return
COOLDOWN_START(src, surge_cooldown, 1 MINUTES)
surged.balloon_alert(surged, "you refuse to give up!")//breaks balloon alert conventions by using a "!" for a fail message but that's okay because it's a pretty awesome moment
- surged.heal_overall_damage(15, 15, 0, BODYPART_ORGANIC)
+ surged.heal_overall_damage(15, 15, 0, BODYTYPE_ORGANIC)
if(surged.reagents.get_reagent_amount(/datum/reagent/medicine/ephedrine) < 20)
surged.reagents.add_reagent(/datum/reagent/medicine/ephedrine, 10)
if(surged.reagents.get_reagent_amount(/datum/reagent/medicine/epinephrine) < 20)
diff --git a/code/datums/diseases/advance/symptoms/fire.dm b/code/datums/diseases/advance/symptoms/fire.dm
index 240abf84603..edb0d6e4aa4 100644
--- a/code/datums/diseases/advance/symptoms/fire.dm
+++ b/code/datums/diseases/advance/symptoms/fire.dm
@@ -71,14 +71,14 @@ Bonus
/datum/symptom/fire/proc/Firestacks_stage_4(mob/living/M, datum/disease/advance/A)
M.adjust_fire_stacks(1 * power)
- M.take_overall_damage(burn = 3 * power, required_status = BODYPART_ORGANIC)
+ M.take_overall_damage(burn = 3 * power, required_status = BODYTYPE_ORGANIC)
if(infective)
A.spread(2)
return 1
/datum/symptom/fire/proc/Firestacks_stage_5(mob/living/M, datum/disease/advance/A)
M.adjust_fire_stacks(3 * power)
- M.take_overall_damage(burn = 5 * power, required_status = BODYPART_ORGANIC)
+ M.take_overall_damage(burn = 5 * power, required_status = BODYTYPE_ORGANIC)
if(infective)
A.spread(4)
return 1
@@ -164,7 +164,7 @@ Bonus
/datum/symptom/alkali/proc/Alkali_fire_stage_4(mob/living/M, datum/disease/advance/A)
var/get_stacks = 6 * power
M.adjust_fire_stacks(get_stacks)
- M.take_overall_damage(burn = get_stacks / 2, required_status = BODYPART_ORGANIC)
+ M.take_overall_damage(burn = get_stacks / 2, required_status = BODYTYPE_ORGANIC)
if(chems)
M.reagents.add_reagent(/datum/reagent/clf3, 2 * power)
return 1
@@ -172,7 +172,7 @@ Bonus
/datum/symptom/alkali/proc/Alkali_fire_stage_5(mob/living/M, datum/disease/advance/A)
var/get_stacks = 8 * power
M.adjust_fire_stacks(get_stacks)
- M.take_overall_damage(burn = get_stacks, required_status = BODYPART_ORGANIC)
+ M.take_overall_damage(burn = get_stacks, required_status = BODYTYPE_ORGANIC)
if(chems)
M.reagents.add_reagent_list(list(/datum/reagent/napalm = 4 * power, /datum/reagent/clf3 = 4 * power))
return 1
diff --git a/code/datums/diseases/advance/symptoms/flesh_eating.dm b/code/datums/diseases/advance/symptoms/flesh_eating.dm
index 3bc4909a7af..31f602d4f39 100644
--- a/code/datums/diseases/advance/symptoms/flesh_eating.dm
+++ b/code/datums/diseases/advance/symptoms/flesh_eating.dm
@@ -59,7 +59,7 @@ Bonus
/datum/symptom/flesh_eating/proc/Flesheat(mob/living/M, datum/disease/advance/A)
var/get_damage = rand(15,25) * power
- M.take_overall_damage(brute = get_damage, required_status = BODYPART_ORGANIC)
+ M.take_overall_damage(brute = get_damage, required_status = BODYTYPE_ORGANIC)
if(pain)
M.adjustStaminaLoss(get_damage * 2)
if(bleed)
@@ -131,7 +131,7 @@ Bonus
/datum/symptom/flesh_death/proc/Flesh_death(mob/living/M, datum/disease/advance/A)
var/get_damage = rand(6,10)
- M.take_overall_damage(brute = get_damage, required_status = BODYPART_ORGANIC)
+ M.take_overall_damage(brute = get_damage, required_status = BODYTYPE_ORGANIC)
if(chems)
M.reagents.add_reagent_list(list(/datum/reagent/toxin/heparin = 2, /datum/reagent/toxin/lipolicide = 2))
if(zombie)
diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm
index e51b092d057..4b115b5fe9b 100644
--- a/code/datums/diseases/advance/symptoms/heal.dm
+++ b/code/datums/diseases/advance/symptoms/heal.dm
@@ -160,13 +160,13 @@
M.adjustToxLoss(-(4 * heal_amt)) //most effective on toxins
- var/list/parts = M.get_damaged_bodyparts(1,1, null, BODYPART_ORGANIC)
+ var/list/parts = M.get_damaged_bodyparts(1,1, null, BODYTYPE_ORGANIC)
if(!parts.len)
return
for(var/obj/item/bodypart/L in parts)
- if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len, null, BODYPART_ORGANIC))
+ if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len, null, BODYTYPE_ORGANIC))
M.update_damage_overlays()
return 1
@@ -278,7 +278,7 @@
/datum/symptom/heal/darkness/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power)
var/heal_amt = 2 * actual_power
- var/list/parts = M.get_damaged_bodyparts(1,1, null, BODYPART_ORGANIC)
+ var/list/parts = M.get_damaged_bodyparts(1,1, null, BODYTYPE_ORGANIC)
if(!parts.len)
return
@@ -287,7 +287,7 @@
to_chat(M, span_notice("The darkness soothes and mends your wounds."))
for(var/obj/item/bodypart/L in parts)
- if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len * 0.5, null, BODYPART_ORGANIC)) //more effective on brute
+ if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len * 0.5, null, BODYTYPE_ORGANIC)) //more effective on brute
M.update_damage_overlays()
return 1
@@ -381,7 +381,7 @@
return
for(var/obj/item/bodypart/L in parts)
- if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len, null, BODYPART_ORGANIC))
+ if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len, null, BODYTYPE_ORGANIC))
M.update_damage_overlays()
if(active_coma && M.getBruteLoss() + M.getFireLoss() == 0)
@@ -434,7 +434,7 @@
/datum/symptom/heal/water/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power)
var/heal_amt = 2 * actual_power
- var/list/parts = M.get_damaged_bodyparts(1,1, null, BODYPART_ORGANIC) //more effective on burns
+ var/list/parts = M.get_damaged_bodyparts(1,1, null, BODYTYPE_ORGANIC) //more effective on burns
if(!parts.len)
return
@@ -443,7 +443,7 @@
to_chat(M, span_notice("You feel yourself absorbing the water around you to soothe your damaged skin."))
for(var/obj/item/bodypart/L in parts)
- if(L.heal_damage(heal_amt/parts.len * 0.5, heal_amt/parts.len, null, BODYPART_ORGANIC))
+ if(L.heal_damage(heal_amt/parts.len * 0.5, heal_amt/parts.len, null, BODYTYPE_ORGANIC))
M.update_damage_overlays()
return 1
@@ -514,13 +514,13 @@
M.adjustToxLoss(-heal_amt)
- var/list/parts = M.get_damaged_bodyparts(1,1, null, BODYPART_ORGANIC)
+ var/list/parts = M.get_damaged_bodyparts(1,1, null, BODYTYPE_ORGANIC)
if(!parts.len)
return
if(prob(5))
to_chat(M, span_notice("The pain from your wounds fades rapidly."))
for(var/obj/item/bodypart/L in parts)
- if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len, null, BODYPART_ORGANIC))
+ if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len, null, BODYTYPE_ORGANIC))
M.update_damage_overlays()
return 1
@@ -564,7 +564,7 @@
M.adjustToxLoss(-(2 * heal_amt))
- var/list/parts = M.get_damaged_bodyparts(1,1, null, BODYPART_ORGANIC)
+ var/list/parts = M.get_damaged_bodyparts(1,1, null, BODYTYPE_ORGANIC)
if(!parts.len)
return
@@ -573,6 +573,6 @@
to_chat(M, span_notice("Your skin glows faintly, and you feel your wounds mending themselves."))
for(var/obj/item/bodypart/L in parts)
- if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len, null, BODYPART_ORGANIC))
+ if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len, null, BODYTYPE_ORGANIC))
M.update_damage_overlays()
return 1
diff --git a/code/datums/diseases/advance/symptoms/itching.dm b/code/datums/diseases/advance/symptoms/itching.dm
index 98318060f28..6d6c2b843fb 100644
--- a/code/datums/diseases/advance/symptoms/itching.dm
+++ b/code/datums/diseases/advance/symptoms/itching.dm
@@ -51,7 +51,7 @@ BONUS
var/mob/living/carbon/M = A.affected_mob
var/picked_bodypart = pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
var/obj/item/bodypart/bodypart = M.get_bodypart(picked_bodypart)
- if(bodypart && bodypart.status == BODYPART_ORGANIC && !bodypart.is_pseudopart) //robotic limbs will mean less scratching overall (why are golems able to damage themselves with self-scratching, but not androids? the world may never know)
+ if(bodypart && IS_ORGANIC_LIMB(bodypart) && !bodypart.is_pseudopart) //robotic limbs will mean less scratching overall (why are golems able to damage themselves with self-scratching, but not androids? the world may never know)
var/can_scratch = scratch && !M.incapacitated()
M.visible_message("[can_scratch ? span_warning("[M] scratches [M.p_their()] [bodypart.name].") : ""]", span_warning("Your [bodypart.name] itches. [can_scratch ? " You scratch it." : ""]"))
if(can_scratch)
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index ead2c481cb4..6b0a75a684f 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -539,9 +539,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE)
..()
if(icon_update)
- update_body()
- update_hair()
- update_body_parts()
+ update_body(is_creating = TRUE)
update_mutations_overlay()// no lizard with human hulk overlay please.
*/
@@ -583,9 +581,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
domutcheck()
if(mrace || newfeatures || ui)
- update_body()
- update_hair()
- update_body_parts()
+ update_body(is_creating = TRUE)
update_mutations_overlay()
if(LAZYLEN(mutations))
@@ -665,9 +661,9 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
if(icon_update)
dna.species.handle_body(src) // We want 'update_body_parts()' to be called only if mutcolor_update is TRUE, so no 'update_body()' here.
- update_hair()
+ update_hair(is_creating = TRUE)
if(mutcolor_update)
- update_body_parts()
+ update_body_parts(update_limb_data = TRUE)
if(mutations_overlay_update)
update_mutations_overlay()
*/
diff --git a/code/datums/elements/soft_landing.dm b/code/datums/elements/soft_landing.dm
new file mode 100644
index 00000000000..b57337fd643
--- /dev/null
+++ b/code/datums/elements/soft_landing.dm
@@ -0,0 +1,25 @@
+/**
+ * ## soft landing element!
+ *
+ * Non bespoke element (1 in existence) that makes objs provide a soft landing when you fall on them!
+ */
+/datum/element/soft_landing
+ element_flags = ELEMENT_DETACH
+
+/datum/element/soft_landing/Attach(datum/target)
+ . = ..()
+ if(!isatom(target))
+ return ELEMENT_INCOMPATIBLE
+ RegisterSignal(target, COMSIG_ATOM_INTERCEPT_Z_FALL, .proc/intercept_z_fall)
+
+/datum/element/soft_landing/Detach(datum/target)
+ . = ..()
+ UnregisterSignal(target, COMSIG_ATOM_INTERCEPT_Z_FALL)
+
+///signal called by the stat of the target changing
+/datum/element/soft_landing/proc/intercept_z_fall(obj/soft_object, falling_movables, levels)
+ SIGNAL_HANDLER
+
+ for (var/mob/living/falling_victim in falling_movables)
+ to_chat(falling_victim, span_notice("[soft_object] provides a soft landing for you!"))
+ return FALL_INTERCEPTED | FALL_NO_MESSAGE
diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm
index 92feffdbfe8..ca2ab4461c5 100644
--- a/code/datums/mutations/body.dm
+++ b/code/datums/mutations/body.dm
@@ -518,7 +518,7 @@
if(brain) //so this doesn't instantly kill you. we could delete the brain, but it lets people cure brain issues they /really/ shouldn't be
brain.zone = BODY_ZONE_HEAD
UnregisterSignal(owner, COMSIG_CARBON_ATTACH_LIMB)
- var/successful = owner.regenerate_limb(BODY_ZONE_HEAD, noheal = TRUE) //noheal needs to be TRUE to prevent weird adding and removing mutation healing
+ var/successful = owner.regenerate_limb(BODY_ZONE_HEAD)
if(!successful)
stack_trace("HARS mutation head regeneration failed! (usually caused by headless syndrome having a head)")
return TRUE
diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm
index f2a1b1844e5..371d3f217d1 100644
--- a/code/datums/wounds/_wounds.dm
+++ b/code/datums/wounds/_wounds.dm
@@ -110,7 +110,7 @@
* * attack_direction: For bloodsplatters, if relevant
*/
/datum/wound/proc/apply_wound(obj/item/bodypart/L, silent = FALSE, datum/wound/old_wound = null, smited = FALSE, attack_direction = null)
- if(!istype(L) || !L.owner || !(L.body_zone in viable_zones) || !L.is_organic_limb() || HAS_TRAIT(L.owner, TRAIT_NEVER_WOUNDED))
+ if(!istype(L) || !L.owner || !(L.body_zone in viable_zones) || !IS_ORGANIC_LIMB(L) || HAS_TRAIT(L.owner, TRAIT_NEVER_WOUNDED))
qdel(src)
return
diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm
index daadd135558..fb09af16656 100644
--- a/code/datums/wounds/bones.dm
+++ b/code/datums/wounds/bones.dm
@@ -50,7 +50,7 @@
I = victim.get_inactive_held_item()
if(I && victim.dropItemToGround(I))
- victim.visible_message(span_danger("[victim] drops [I] in shock!"), span_warning("The force on your [limb.name] causes you to drop [I]!"), vision_distance=COMBAT_MESSAGE_RANGE)
+ victim.visible_message(span_danger("[victim] drops [I] in shock!"), span_warning("The force on your [parse_zone(limb.body_zone)] causes you to drop [I]!"), vision_distance=COMBAT_MESSAGE_RANGE)
update_inefficiencies()
@@ -93,7 +93,7 @@
if(!victim || !limb)
qdel(src)
return
- to_chat(victim, span_green("Your [limb.name] has recovered from its [name]!"))
+ to_chat(victim, span_green("Your [parse_zone(limb.body_zone)] has recovered from its [name]!"))
remove_wound()
/// If we're a human who's punching something with a broken arm, we might hurt ourselves doing so
@@ -107,11 +107,11 @@
if(prob((severity - 1) * 15))
// And you have a 70% or 50% chance to actually land the blow, respectively
if(prob(70 - 20 * (severity - 1)))
- to_chat(victim, span_userdanger("The fracture in your [limb.name] shoots with pain as you strike [target]!"))
+ to_chat(victim, span_userdanger("The fracture in your [parse_zone(limb.body_zone)] shoots with pain as you strike [target]!"))
limb.receive_damage(brute=rand(1,5))
else
- victim.visible_message(span_danger("[victim] weakly strikes [target] with [victim.p_their()] broken [limb.name], recoiling from pain!"), \
- span_userdanger("You fail to strike [target] as the fracture in your [limb.name] lights up in unbearable pain!"), vision_distance=COMBAT_MESSAGE_RANGE)
+ victim.visible_message(span_danger("[victim] weakly strikes [target] with [victim.p_their()] broken [parse_zone(limb.body_zone)], recoiling from pain!"), \
+ span_userdanger("You fail to strike [target] as the fracture in your [parse_zone(limb.body_zone)] lights up in unbearable pain!"), vision_distance=COMBAT_MESSAGE_RANGE)
INVOKE_ASYNC(victim, /mob.proc/emote, "scream")
victim.Stun(0.5 SECONDS)
limb.receive_damage(brute=rand(3,7))
@@ -151,7 +151,7 @@
var/list/msg = list()
if(!limb.current_gauze)
- msg += "[victim.p_their(TRUE)] [limb.name] [examine_desc]"
+ msg += "[victim.p_their(TRUE)] [parse_zone(limb.body_zone)] [examine_desc]"
else
var/sling_condition = ""
// how much life we have left in these bandages
@@ -165,7 +165,7 @@
if(4 to INFINITY)
sling_condition = "tightly"
- msg += "[victim.p_their(TRUE)] [limb.name] is [sling_condition] fastened in a sling of [limb.current_gauze.name]"
+ msg += "[victim.p_their(TRUE)] [parse_zone(limb.body_zone)] is [sling_condition] fastened in a sling of [limb.current_gauze.name]"
if(taped)
msg += ", [span_notice("and appears to be reforming itself under some surgical tape!")]"
@@ -233,7 +233,7 @@
/datum/wound/blunt/moderate/proc/door_crush()
SIGNAL_HANDLER
if(prob(40))
- victim.visible_message(span_danger("[victim]'s dislocated [limb.name] pops back into place!"), span_userdanger("Your dislocated [limb.name] pops back into place! Ow!"))
+ victim.visible_message(span_danger("[victim]'s dislocated [parse_zone(limb.body_zone)] pops back into place!"), span_userdanger("Your dislocated [parse_zone(limb.body_zone)] pops back into place! Ow!"))
remove_wound()
/datum/wound/blunt/moderate/try_handling(mob/living/carbon/human/user)
@@ -245,8 +245,8 @@
return TRUE
if(user.grab_state >= GRAB_AGGRESSIVE)
- user.visible_message(span_danger("[user] begins twisting and straining [victim]'s dislocated [limb.name]!"), span_notice("You begin twisting and straining [victim]'s dislocated [limb.name]..."), ignored_mobs=victim)
- to_chat(victim, span_userdanger("[user] begins twisting and straining your dislocated [limb.name]!"))
+ user.visible_message(span_danger("[user] begins twisting and straining [victim]'s dislocated [parse_zone(limb.body_zone)]!"), span_notice("You begin twisting and straining [victim]'s dislocated [parse_zone(limb.body_zone)]..."), ignored_mobs=victim)
+ to_chat(victim, span_userdanger("[user] begins twisting and straining your dislocated [parse_zone(limb.body_zone)]!"))
if(!user.combat_mode)
chiropractice(user)
else
@@ -261,14 +261,14 @@
return
if(prob(65))
- user.visible_message(span_danger("[user] snaps [victim]'s dislocated [limb.name] back into place!"), span_notice("You snap [victim]'s dislocated [limb.name] back into place!"), ignored_mobs=victim)
- to_chat(victim, span_userdanger("[user] snaps your dislocated [limb.name] back into place!"))
+ user.visible_message(span_danger("[user] snaps [victim]'s dislocated [parse_zone(limb.body_zone)] back into place!"), span_notice("You snap [victim]'s dislocated [parse_zone(limb.body_zone)] back into place!"), ignored_mobs=victim)
+ to_chat(victim, span_userdanger("[user] snaps your dislocated [parse_zone(limb.body_zone)] back into place!"))
victim.emote("scream")
limb.receive_damage(brute=20, wound_bonus=CANT_WOUND)
qdel(src)
else
- user.visible_message(span_danger("[user] wrenches [victim]'s dislocated [limb.name] around painfully!"), span_danger("You wrench [victim]'s dislocated [limb.name] around painfully!"), ignored_mobs=victim)
- to_chat(victim, span_userdanger("[user] wrenches your dislocated [limb.name] around painfully!"))
+ user.visible_message(span_danger("[user] wrenches [victim]'s dislocated [parse_zone(limb.body_zone)] around painfully!"), span_danger("You wrench [victim]'s dislocated [parse_zone(limb.body_zone)] around painfully!"), ignored_mobs=victim)
+ to_chat(victim, span_userdanger("[user] wrenches your dislocated [parse_zone(limb.body_zone)] around painfully!"))
limb.receive_damage(brute=10, wound_bonus=CANT_WOUND)
chiropractice(user)
@@ -280,33 +280,33 @@
return
if(prob(65))
- user.visible_message(span_danger("[user] snaps [victim]'s dislocated [limb.name] with a sickening crack!"), span_danger("You snap [victim]'s dislocated [limb.name] with a sickening crack!"), ignored_mobs=victim)
- to_chat(victim, span_userdanger("[user] snaps your dislocated [limb.name] with a sickening crack!"))
+ user.visible_message(span_danger("[user] snaps [victim]'s dislocated [parse_zone(limb.body_zone)] with a sickening crack!"), span_danger("You snap [victim]'s dislocated [parse_zone(limb.body_zone)] with a sickening crack!"), ignored_mobs=victim)
+ to_chat(victim, span_userdanger("[user] snaps your dislocated [parse_zone(limb.body_zone)] with a sickening crack!"))
victim.emote("scream")
limb.receive_damage(brute=25, wound_bonus=30)
else
- user.visible_message(span_danger("[user] wrenches [victim]'s dislocated [limb.name] around painfully!"), span_danger("You wrench [victim]'s dislocated [limb.name] around painfully!"), ignored_mobs=victim)
- to_chat(victim, span_userdanger("[user] wrenches your dislocated [limb.name] around painfully!"))
+ user.visible_message(span_danger("[user] wrenches [victim]'s dislocated [parse_zone(limb.body_zone)] around painfully!"), span_danger("You wrench [victim]'s dislocated [parse_zone(limb.body_zone)] around painfully!"), ignored_mobs=victim)
+ to_chat(victim, span_userdanger("[user] wrenches your dislocated [parse_zone(limb.body_zone)] around painfully!"))
limb.receive_damage(brute=10, wound_bonus=CANT_WOUND)
malpractice(user)
/datum/wound/blunt/moderate/treat(obj/item/I, mob/user)
if(victim == user)
- victim.visible_message(span_danger("[user] begins resetting [victim.p_their()] [limb.name] with [I]."), span_warning("You begin resetting your [limb.name] with [I]..."))
+ victim.visible_message(span_danger("[user] begins resetting [victim.p_their()] [parse_zone(limb.body_zone)] with [I]."), span_warning("You begin resetting your [parse_zone(limb.body_zone)] with [I]..."))
else
- user.visible_message(span_danger("[user] begins resetting [victim]'s [limb.name] with [I]."), span_notice("You begin resetting [victim]'s [limb.name] with [I]..."))
+ user.visible_message(span_danger("[user] begins resetting [victim]'s [parse_zone(limb.body_zone)] with [I]."), span_notice("You begin resetting [victim]'s [parse_zone(limb.body_zone)] with [I]..."))
if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists)))
return
if(victim == user)
limb.receive_damage(brute=15, wound_bonus=CANT_WOUND)
- victim.visible_message(span_danger("[user] finishes resetting [victim.p_their()] [limb.name]!"), span_userdanger("You reset your [limb.name]!"))
+ victim.visible_message(span_danger("[user] finishes resetting [victim.p_their()] [parse_zone(limb.body_zone)]!"), span_userdanger("You reset your [parse_zone(limb.body_zone)]!"))
else
limb.receive_damage(brute=10, wound_bonus=CANT_WOUND)
- user.visible_message(span_danger("[user] finishes resetting [victim]'s [limb.name]!"), span_nicegreen("You finish resetting [victim]'s [limb.name]!"), ignored_mobs=victim)
- to_chat(victim, span_userdanger("[user] resets your [limb.name]!"))
+ user.visible_message(span_danger("[user] finishes resetting [victim]'s [parse_zone(limb.body_zone)]!"), span_nicegreen("You finish resetting [victim]'s [parse_zone(limb.body_zone)]!"), ignored_mobs=victim)
+ to_chat(victim, span_userdanger("[user] resets your [parse_zone(limb.body_zone)]!"))
victim.emote("scream")
qdel(src)
@@ -377,10 +377,10 @@
return
if(gelled)
- to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.name] is already coated with bone gel!"))
+ to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [parse_zone(limb.body_zone)] is already coated with bone gel!"))
return
- user.visible_message(span_danger("[user] begins hastily applying [I] to [victim]'s' [limb.name]..."), span_warning("You begin hastily applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name], disregarding the warning label..."))
+ user.visible_message(span_danger("[user] begins hastily applying [I] to [victim]'s' [parse_zone(limb.body_zone)]..."), span_warning("You begin hastily applying [I] to [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)], disregarding the warning label..."))
if(!do_after(user, base_treat_time * 1.5 * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists)))
return
@@ -388,8 +388,8 @@
I.use(1)
victim.emote("scream")
if(user != victim)
- user.visible_message(span_notice("[user] finishes applying [I] to [victim]'s [limb.name], emitting a fizzing noise!"), span_notice("You finish applying [I] to [victim]'s [limb.name]!"), ignored_mobs=victim)
- to_chat(victim, span_userdanger("[user] finishes applying [I] to your [limb.name], and you can feel the bones exploding with pain as they begin melting and reforming!"))
+ user.visible_message(span_notice("[user] finishes applying [I] to [victim]'s [parse_zone(limb.body_zone)], emitting a fizzing noise!"), span_notice("You finish applying [I] to [victim]'s [parse_zone(limb.body_zone)]!"), ignored_mobs=victim)
+ to_chat(victim, span_userdanger("[user] finishes applying [I] to your [parse_zone(limb.body_zone)], and you can feel the bones exploding with pain as they begin melting and reforming!"))
else
var/painkiller_bonus = 0
if(victim.drunkenness > 10)
@@ -404,10 +404,10 @@
painkiller_bonus += 20
if(prob(25 + (20 * (severity - 2)) - painkiller_bonus)) // 25%/45% chance to fail self-applying with severe and critical wounds, modded by painkillers
- victim.visible_message(span_danger("[victim] fails to finish applying [I] to [victim.p_their()] [limb.name], passing out from the pain!"), span_notice("You pass out from the pain of applying [I] to your [limb.name] before you can finish!"))
+ victim.visible_message(span_danger("[victim] fails to finish applying [I] to [victim.p_their()] [parse_zone(limb.body_zone)], passing out from the pain!"), span_notice("You pass out from the pain of applying [I] to your [parse_zone(limb.body_zone)] before you can finish!"))
victim.AdjustUnconscious(5 SECONDS)
return
- victim.visible_message(span_notice("[victim] finishes applying [I] to [victim.p_their()] [limb.name], grimacing from the pain!"), span_notice("You finish applying [I] to your [limb.name], and your bones explode in pain!"))
+ victim.visible_message(span_notice("[victim] finishes applying [I] to [victim.p_their()] [parse_zone(limb.body_zone)], grimacing from the pain!"), span_notice("You finish applying [I] to your [parse_zone(limb.body_zone)], and your bones explode in pain!"))
limb.receive_damage(25, stamina=100, wound_bonus=CANT_WOUND)
gelled = TRUE
@@ -418,20 +418,20 @@
return // poser
if(gelled)
- to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.name] is already coated with bone gel!"))
+ to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [parse_zone(limb.body_zone)] is already coated with bone gel!"))
return
- user.visible_message(span_danger("[user] begins applying [I] to [victim]'s' [limb.name]..."), span_warning("You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name]..."))
+ user.visible_message(span_danger("[user] begins applying [I] to [victim]'s' [parse_zone(limb.body_zone)]..."), span_warning("You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)]..."))
if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists)))
return
I.use(1)
if(user != victim)
- user.visible_message(span_notice("[user] finishes applying [I] to [victim]'s [limb.name], emitting a fizzing noise!"), span_notice("You finish applying [I] to [victim]'s [limb.name]!"), ignored_mobs=victim)
- to_chat(victim, span_userdanger("[user] finishes applying [I] to your [limb.name], and you feel a funny fizzy tickling as they begin to reform!"))
+ user.visible_message(span_notice("[user] finishes applying [I] to [victim]'s [parse_zone(limb.body_zone)], emitting a fizzing noise!"), span_notice("You finish applying [I] to [victim]'s [parse_zone(limb.body_zone)]!"), ignored_mobs=victim)
+ to_chat(victim, span_userdanger("[user] finishes applying [I] to your [parse_zone(limb.body_zone)], and you feel a funny fizzy tickling as they begin to reform!"))
else
- victim.visible_message(span_notice("[victim] finishes applying [I] to [victim.p_their()] [limb.name], emitting a funny fizzing sound!"), span_notice("You finish applying [I] to your [limb.name], and feel a funny fizzy tickling as the bone begins to reform!"))
+ victim.visible_message(span_notice("[victim] finishes applying [I] to [victim.p_their()] [parse_zone(limb.body_zone)], emitting a funny fizzing sound!"), span_notice("You finish applying [I] to your [parse_zone(limb.body_zone)], and feel a funny fizzy tickling as the bone begins to reform!"))
gelled = TRUE
processes = TRUE
@@ -439,13 +439,13 @@
/// if someone is using surgical tape on our wound
/datum/wound/blunt/proc/tape(obj/item/stack/sticky_tape/surgical/I, mob/user)
if(!gelled)
- to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.name] must be coated with bone gel to perform this emergency operation!"))
+ to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [parse_zone(limb.body_zone)] must be coated with bone gel to perform this emergency operation!"))
return
if(taped)
- to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.name] is already wrapped in [I.name] and reforming!"))
+ to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [parse_zone(limb.body_zone)] is already wrapped in [I.name] and reforming!"))
return
- user.visible_message(span_danger("[user] begins applying [I] to [victim]'s' [limb.name]..."), span_warning("You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name]..."))
+ user.visible_message(span_danger("[user] begins applying [I] to [victim]'s' [parse_zone(limb.body_zone)]..."), span_warning("You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)]..."))
if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists)))
return
@@ -455,10 +455,10 @@
I.use(1)
if(user != victim)
- user.visible_message(span_notice("[user] finishes applying [I] to [victim]'s [limb.name], emitting a fizzing noise!"), span_notice("You finish applying [I] to [victim]'s [limb.name]!"), ignored_mobs=victim)
- to_chat(victim, span_green("[user] finishes applying [I] to your [limb.name], you immediately begin to feel your bones start to reform!"))
+ user.visible_message(span_notice("[user] finishes applying [I] to [victim]'s [parse_zone(limb.body_zone)], emitting a fizzing noise!"), span_notice("You finish applying [I] to [victim]'s [parse_zone(limb.body_zone)]!"), ignored_mobs=victim)
+ to_chat(victim, span_green("[user] finishes applying [I] to your [parse_zone(limb.body_zone)], you immediately begin to feel your bones start to reform!"))
else
- victim.visible_message(span_notice("[victim] finishes applying [I] to [victim.p_their()] [limb.name], !"), span_green("You finish applying [I] to your [limb.name], and you immediately begin to feel your bones start to reform!"))
+ victim.visible_message(span_notice("[victim] finishes applying [I] to [victim.p_their()] [parse_zone(limb.body_zone)], !"), span_green("You finish applying [I] to your [parse_zone(limb.body_zone)], and you immediately begin to feel your bones start to reform!"))
taped = TRUE
processes = TRUE
diff --git a/code/datums/wounds/scars/_scars.dm b/code/datums/wounds/scars/_scars.dm
index 514f99cc687..442923dc322 100644
--- a/code/datums/wounds/scars/_scars.dm
+++ b/code/datums/wounds/scars/_scars.dm
@@ -87,7 +87,7 @@
/// Used to "load" a persistent scar
/datum/scar/proc/load(obj/item/bodypart/BP, version, description, specific_location, severity=WOUND_SEVERITY_SEVERE, biology=BIO_FLESH_BONE, char_slot)
- if(!BP.is_organic_limb())
+ if(!IS_ORGANIC_LIMB(BP))
qdel(src)
return
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 26d6ba0840d..5acf2b9bd5a 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -674,6 +674,9 @@
* Produces a signal [COMSIG_PARENT_EXAMINE_MORE]
*/
/atom/proc/examine_more(mob/user)
+ SHOULD_CALL_PARENT(TRUE)
+ RETURN_TYPE(/list)
+
. = list()
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE_MORE, user, .)
@@ -1787,6 +1790,7 @@
filters = null
/atom/proc/intercept_zImpact(list/falling_movables, levels = 1)
+ SHOULD_CALL_PARENT(TRUE)
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, falling_movables, levels)
/// Sets the custom materials for an item.
diff --git a/code/game/machinery/computer/arcade/arcade.dm b/code/game/machinery/computer/arcade/arcade.dm
index 69a9b80a75b..1f6e3ecb07d 100644
--- a/code/game/machinery/computer/arcade/arcade.dm
+++ b/code/game/machinery/computer/arcade/arcade.dm
@@ -602,14 +602,15 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
return ..() //well boys we did it, lists are no more
/obj/machinery/computer/arcade/battle/examine_more(mob/user)
- var/list/msg = list(span_notice("You notice some writing scribbled on the side of [src]..."))
- msg += "\t[span_info("smart -> defend, defend, light attack")]"
- msg += "\t[span_info("shotgun -> defend, defend, power attack")]"
- msg += "\t[span_info("short temper -> counter, counter, counter")]"
- msg += "\t[span_info("poisonous -> light attack, light attack, light attack")]"
- msg += "\t[span_info("chonker -> power attack, power attack, power attack")]"
- msg += "\t[span_info("magical -> defend until outmagiced")]"
- return msg
+ . = ..()
+ . += span_notice("You notice some writing scribbled on the side of [src]...")
+ . += "\t[span_info("smart -> defend, defend, light attack")]"
+ . += "\t[span_info("shotgun -> defend, defend, power attack")]"
+ . += "\t[span_info("short temper -> counter, counter, counter")]"
+ . += "\t[span_info("poisonous -> light attack, light attack, light attack")]"
+ . += "\t[span_info("chonker -> power attack, power attack, power attack")]"
+ . += "\t[span_info("magical -> defend until outmagiced")]"
+ return .
/obj/machinery/computer/arcade/battle/emag_act(mob/user)
if(obj_flags & EMAGGED)
diff --git a/code/game/machinery/limbgrower.dm b/code/game/machinery/limbgrower.dm
index 06863d274b7..067c64e6340 100644
--- a/code/game/machinery/limbgrower.dm
+++ b/code/game/machinery/limbgrower.dm
@@ -194,10 +194,10 @@
reagents.remove_reagent(reagent_id, modified_consumed_reagents_list[reagent_id])
var/built_typepath = being_built.build_path
- // If we have a bodypart, we need to initialize the limb on its own. Otherwise we can build it here.
if(ispath(built_typepath, /obj/item/bodypart))
- build_limb(built_typepath)
+ build_limb(create_buildpath())
else
+ //Just build whatever it is
new built_typepath(loc)
busy = FALSE
@@ -214,26 +214,24 @@
*/
/obj/machinery/limbgrower/proc/build_limb(buildpath)
/// The limb we're making with our buildpath, so we can edit it.
- var/obj/item/bodypart/limb = new buildpath(loc)
- /// Species with greyscale limbs.
- var/list/greyscale_species = list(SPECIES_HUMAN, SPECIES_LIZARD, SPECIES_ETHEREAL)
- if(selected_category in greyscale_species) //Species with greyscale parts should be included here
- if(selected_category == SPECIES_HUMAN) //humans don't use the full colour spectrum, they use random_skin_tone
- limb.skin_tone = random_skin_tone()
- else
- limb.species_color = "#[random_color()]"
- limb.icon = 'icons/mob/human_parts_greyscale.dmi'
- limb.should_draw_greyscale = TRUE
- else
- limb.icon = 'icons/mob/human_parts.dmi'
-
- // Set this limb up using the species name and body zone
- limb.icon_state = "[selected_category]_[limb.body_zone]"
- limb.name = "\improper biosynthetic [selected_category] [parse_zone(limb.body_zone)]"
- limb.desc = "A synthetically produced [selected_category] limb, grown in a tube. This one is for the [parse_zone(limb.body_zone)]."
- limb.species_id = selected_category
+ //i need to create a body part manually using a set icon (otherwise it doesnt appear)
+ var/obj/item/bodypart/limb
+ limb = new buildpath(loc)
+ limb.name = "\improper synthetic [selected_category] [parse_zone(limb.body_zone)]"
+ limb.limb_id = selected_category
+ limb.mutation_color = "#62A262"
limb.update_icon_dropped()
- limb.original_owner = WEAKREF(src) //prevents updating the icon, so a lizard arm on a human stays a lizard arm etc.
+
+///Returns a valid limb typepath based on the selected option
+/obj/machinery/limbgrower/proc/create_buildpath()
+ var/part_type = being_built.id //their ids match bodypart typepaths
+ var/species = selected_category
+ var/path
+ if(species == SPECIES_HUMAN) //Humans use the parent type.
+ path = "/obj/item/bodypart/[part_type]"
+ else
+ path = "/obj/item/bodypart/[part_type]/[species]"
+ return text2path(path)
/obj/machinery/limbgrower/RefreshParts()
reagents.maximum_volume = 0
diff --git a/code/game/objects/effects/contraband.dm b/code/game/objects/effects/contraband.dm
index 35d5decd4ad..04f93d79011 100644
--- a/code/game/objects/effects/contraband.dm
+++ b/code/game/objects/effects/contraband.dm
@@ -468,11 +468,12 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sign/poster/contraband/random, 32)
icon_state = "gas_power"
/obj/structure/sign/poster/contraband/donk_co/examine_more(mob/user)
- var/list/msg = list(span_notice("You browse some of the poster's information..."))
- msg += "\t[span_info("DONK CO. BRAND DONK POCKETS: IRRESISTABLY DONK!")]"
- msg += "\t[span_info("AVAILABLE IN OVER 200 DONKTASTIC FLAVOURS: TRY CLASSIC MEAT, HOT AND SPICY, NEW YORK PEPPERONI PIZZA, BREAKFAST SAUSAGE AND EGG, PHILADELPHIA CHEESESTEAK, HAMBURGER DONK-A-RONI, CHEESE-O-RAMA, AND MANY MORE!")]"
- msg += "\t[span_info("AVAILABLE FROM ALL GOOD RETAILERS, AND MANY BAD ONES TOO!")]"
- return msg
+ . = ..()
+ . += span_notice("You browse some of the poster's information...")
+ . += "\t[span_info("DONK CO. BRAND DONK POCKETS: IRRESISTABLY DONK!")]"
+ . += "\t[span_info("AVAILABLE IN OVER 200 DONKTASTIC FLAVOURS: TRY CLASSIC MEAT, HOT AND SPICY, NEW YORK PEPPERONI PIZZA, BREAKFAST SAUSAGE AND EGG, PHILADELPHIA CHEESESTEAK, HAMBURGER DONK-A-RONI, CHEESE-O-RAMA, AND MANY MORE!")]"
+ . += "\t[span_info("AVAILABLE FROM ALL GOOD RETAILERS, AND MANY BAD ONES TOO!")]"
+ return .
/obj/structure/sign/poster/contraband/cybersun_six_hundred
name = "Saibāsan: 600 Years Commemorative Poster"
@@ -734,15 +735,16 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sign/poster/official/random, 32)
icon_state = "plasma_effects"
/obj/structure/sign/poster/official/plasma_effects/examine_more(mob/user)
- var/list/msg = list(span_notice("You browse some of the poster's information..."))
- msg += "\t[span_info("Plasma (scientific name Amenthium) is classified by TerraGov as a Grade 1 Health Hazard, and has significant risks to health associated with chronic exposure.")]"
- msg += "\t[span_info("Plasma is known to cross the blood/brain barrier and bioaccumulate in brain tissue, where it begins to result in degradation of brain function. The mechanism for attack is not yet fully known, and as such no concrete preventative advice is available barring proper use of PPE (gloves + protective jumpsuit + respirator).")]"
- msg += "\t[span_info("In small doses, plasma induces confusion, short-term amnesia, and heightened aggression. These effects persist with continual exposure.")]"
- msg += "\t[span_info("In individuals with chronic exposure, severe effects have been noted. Further heightened aggression, long-term amnesia, Alzheimer's symptoms, schizophrenia, macular degeneration, aneurysms, heightened risk of stroke, and Parkinsons symptoms have all been noted.")]"
- msg += "\t[span_info("It is recommended that all individuals in unprotected contact with raw plasma regularly check with company health officials.")]"
- msg += "\t[span_info("For more information, please check with TerraGov's extranet site on Amenthium: www.terra.gov/health_and_safety/amenthium/, or our internal risk-assessment documents (document numbers #47582-b (Plasma safety data sheets) and #64210 through #64225 (PPE regulations for working with Plasma), available via NanoDoc to all employees).")]"
- msg += "\t[span_info("Nanotrasen: Always looking after your health.")]"
- return msg
+ . = ..()
+ . += span_notice("You browse some of the poster's information...")
+ . += "\t[span_info("Plasma (scientific name Amenthium) is classified by TerraGov as a Grade 1 Health Hazard, and has significant risks to health associated with chronic exposure.")]"
+ . += "\t[span_info("Plasma is known to cross the blood/brain barrier and bioaccumulate in brain tissue, where it begins to result in degradation of brain function. The mechanism for attack is not yet fully known, and as such no concrete preventative advice is available barring proper use of PPE (gloves + protective jumpsuit + respirator).")]"
+ . += "\t[span_info("In small doses, plasma induces confusion, short-term amnesia, and heightened aggression. These effects persist with continual exposure.")]"
+ . += "\t[span_info("In individuals with chronic exposure, severe effects have been noted. Further heightened aggression, long-term amnesia, Alzheimer's symptoms, schizophrenia, macular degeneration, aneurysms, heightened risk of stroke, and Parkinsons symptoms have all been noted.")]"
+ . += "\t[span_info("It is recommended that all individuals in unprotected contact with raw plasma regularly check with company health officials.")]"
+ . += "\t[span_info("For more information, please check with TerraGov's extranet site on Amenthium: www.terra.gov/health_and_safety/amenthium/, or our internal risk-assessment documents (document numbers #47582-b (Plasma safety data sheets) and #64210 through #64225 (PPE regulations for working with Plasma), available via NanoDoc to all employees).")]"
+ . += "\t[span_info("Nanotrasen: Always looking after your health.")]"
+ return .
/obj/structure/sign/poster/official/terragov
name = "TerraGov: United for Humanity"
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index bf3ebb02082..7c8ff8f0035 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -149,6 +149,8 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
var/list/attack_verb_simple
///list() of species types, if a species cannot put items in a certain slot, but species type is in list, it will be able to wear that item
var/list/species_exception = null
+ ///This is a bitfield that defines what variations exist for bodyparts like Digi legs. See: code\_DEFINES\inventory.dm
+ var/supports_variations_flags = NONE
///A weakref to the mob who threw the item
var/datum/weakref/thrownby = null //I cannot verbally describe how much I hate this var
@@ -1353,8 +1355,8 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
worn_icon = unique_reskin[pick][RESKIN_WORN_ICON]
if(unique_reskin[pick][RESKIN_WORN_ICON_STATE])
worn_icon_state = unique_reskin[pick][RESKIN_WORN_ICON_STATE]
- if(unique_reskin[pick][RESKIN_MUTANT_VARIANTS])
- mutant_variants = unique_reskin[pick][RESKIN_MUTANT_VARIANTS]
+ if(unique_reskin[pick][RESKIN_supports_variations_flags])
+ supports_variations_flags = unique_reskin[pick][RESKIN_supports_variations_flags]
if(ishuman(M))
var/mob/living/carbon/human/wearer = M
wearer.regenerate_icons() // update that mf
diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm
index f7a0a9dbb67..611da8c1bca 100644
--- a/code/game/objects/items/cards_ids.dm
+++ b/code/game/objects/items/cards_ids.dm
@@ -691,31 +691,32 @@
. += span_notice("There's more information below, you can look again to take a closer look...")
/obj/item/card/id/examine_more(mob/user)
- var/list/msg = list(span_notice("You examine [src] closer, and note the following..."))
+ . = ..()
+ . += span_notice("You examine [src] closer, and note the following...")
if(registered_age)
- msg += "The card indicates that the holder is [registered_age] years old. [(registered_age < AGE_MINOR) ? "There's a holographic stripe that reads [span_danger("'MINOR: DO NOT SERVE ALCOHOL OR TOBACCO'")] along the bottom of the card." : ""]"
+ . += "The card indicates that the holder is [registered_age] years old. [(registered_age < AGE_MINOR) ? "There's a holographic stripe that reads [span_danger("'MINOR: DO NOT SERVE ALCOHOL OR TOBACCO'")] along the bottom of the card." : ""]"
if(mining_points)
- msg += "There's [mining_points] mining equipment redemption point\s loaded onto this card."
+ . += "There's [mining_points] mining equipment redemption point\s loaded onto this card."
if(registered_account)
- msg += "The account linked to the ID belongs to '[registered_account.account_holder]' and reports a balance of [registered_account.account_balance] cr."
+ . += "The account linked to the ID belongs to '[registered_account.account_holder]' and reports a balance of [registered_account.account_balance] cr."
if(registered_account.account_job)
var/datum/bank_account/D = SSeconomy.get_dep_account(registered_account.account_job.paycheck_department)
if(D)
- msg += "The [D.account_holder] reports a balance of [D.account_balance] cr."
- msg += span_info("Alt-Click the ID to pull money from the linked account in the form of holochips.")
- msg += span_info("You can insert credits into the linked account by pressing holochips, cash, or coins against the ID.")
+ . += "The [D.account_holder] reports a balance of [D.account_balance] cr."
+ . += span_info("Alt-Click the ID to pull money from the linked account in the form of holochips.")
+ . += span_info("You can insert credits into the linked account by pressing holochips, cash, or coins against the ID.")
if(registered_account.civilian_bounty)
- msg += "There is an active civilian bounty."
- msg += span_info("[registered_account.bounty_text()]")
- msg += span_info("Quantity: [registered_account.bounty_num()]")
- msg += span_info("Reward: [registered_account.bounty_value()]")
+ . += "There is an active civilian bounty."
+ . += span_info("[registered_account.bounty_text()]")
+ . += span_info("Quantity: [registered_account.bounty_num()]")
+ . += span_info("Reward: [registered_account.bounty_value()]")
if(registered_account.account_holder == user.real_name)
- msg += span_boldnotice("If you lose this ID card, you can reclaim your account by Alt-Clicking a blank ID card while holding it and entering your account ID number.")
+ . += span_boldnotice("If you lose this ID card, you can reclaim your account by Alt-Clicking a blank ID card while holding it and entering your account ID number.")
else
- msg += span_info("There is no registered account linked to this card. Alt-Click to add one.")
+ . += span_info("There is no registered account linked to this card. Alt-Click to add one.")
- return msg
+ return .
/obj/item/card/id/GetAccess()
return access.Copy()
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index a000c331b0f..1fbcda5fcc4 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -786,7 +786,7 @@
if(istype(target, /obj/item/bodypart) && actually_paints)
var/obj/item/bodypart/limb = target
- if(limb.status == BODYPART_ROBOTIC)
+ if(!IS_ORGANIC_LIMB(limb))
var/list/skins = list()
var/static/list/style_list_icons = list("standard" = 'icons/mob/augmentation/augments.dmi', "engineer" = 'icons/mob/augmentation/augments_engineer.dmi', "security" = 'icons/mob/augmentation/augments_security.dmi', "mining" = 'icons/mob/augmentation/augments_mining.dmi')
for(var/skin_option in style_list_icons)
diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm
index bb788292e4e..264fc639b8c 100644
--- a/code/game/objects/items/devices/scanners/health_analyzer.dm
+++ b/code/game/objects/items/devices/scanners/health_analyzer.dm
@@ -252,7 +252,7 @@
if(mode == SCANNER_VERBOSE)
for(var/obj/item/bodypart/limb as anything in damaged)
- dmgreport += "[capitalize(limb.name)]: "
+ dmgreport += " "
dmgreport += ""
diff --git a/code/game/objects/items/food/misc.dm b/code/game/objects/items/food/misc.dm
index 190c30f3bcd..0b6a0f73457 100644
--- a/code/game/objects/items/food/misc.dm
+++ b/code/game/objects/items/food/misc.dm
@@ -922,11 +922,12 @@
w_class = WEIGHT_CLASS_SMALL
/obj/item/food/ready_donk/examine_more(mob/user)
- var/list/msg = list(span_notice("You browse the back of the box..."))
- msg += "\t[span_info("Ready-Donk: a product of Donk Co.")]"
- msg += "\t[span_info("Heating instructions: open box and pierce film, heat in microwave on high for 2 minutes. Allow to stand for 60 seconds prior to eating. Product will be hot.")]"
- msg += "\t[span_info("Per 200g serving contains: 8g Sodium; 25g Fat, of which 22g are saturated; 2g Sugar.")]"
- return msg
+ . = ..()
+ . += span_notice("You browse the back of the box...")
+ . += "\t[span_info("Ready-Donk: a product of Donk Co.")]"
+ . += "\t[span_info("Heating instructions: open box and pierce film, heat in microwave on high for 2 minutes. Allow to stand for 60 seconds prior to eating. Product will be hot.")]"
+ . += "\t[span_info("Per 200g serving contains: 8g Sodium; 25g Fat, of which 22g are saturated; 2g Sugar.")]"
+ return .
/obj/item/food/ready_donk/warm
name = "warm Ready-Donk: Bachelor Chow"
diff --git a/code/game/objects/items/food/moth.dm b/code/game/objects/items/food/moth.dm
index 92981cb7d4f..c5d8b48dbae 100644
--- a/code/game/objects/items/food/moth.dm
+++ b/code/game/objects/items/food/moth.dm
@@ -369,7 +369,7 @@
foodtypes = VEGETABLES
w_class = WEIGHT_CLASS_SMALL
-/obj/item/food/soup/moth_bean_stew
+/obj/item/food/soup/moth_bean_stew
name = "prickeldröndolhaskl" //prickeld = spicy, röndol = bean, haskl = stew
desc = "A spicy bean stew with lots of veggies, commonly served aboard the fleet as a filling and satisfying meal with rice or bread."
icon = 'icons/obj/food/moth.dmi'
@@ -389,7 +389,7 @@
foodtypes = VEGETABLES | GRAIN
w_class = WEIGHT_CLASS_SMALL
-/obj/item/food/soup/moth_fire_soup
+/obj/item/food/soup/moth_fire_soup
name = "tömpröttkrakklmæsch" //tömprött = heart (tömp = thump, rött = muscle), krakkl = fire, mæsch = soup
desc = "Tömpröttkrakklmæsch, or heartburn soup, is a cold soup dish that originated amongst the jungle moths, and is named for two things- its rosy pink colour, and its scorchingly hot chilli heat."
icon = 'icons/obj/food/moth.dmi'
@@ -400,7 +400,7 @@
w_class = WEIGHT_CLASS_SMALL
/obj/item/food/soup/rice_porridge
- name = "rice porridge"
+ name = "rice porridge"
desc = "A plate of rice porridge. It's mostly flavourless, but it does fill a spot. To the Chinese it's congee, and moths call it höllflöfmisklsløsk." //höllflöfmiskl = rice (höllflöf = cloud, miskl = seed), sløsk = porridge
icon = 'icons/obj/food/moth.dmi'
icon_state = "rice_porridge"
@@ -410,7 +410,7 @@
w_class = WEIGHT_CLASS_SMALL
/obj/item/food/soup/hua_mulan_congee
- name = "\improper Hua Mulan congee"
+ name = "\improper Hua Mulan congee"
desc = "Nobody is quite sure why this smiley bowl of rice porridge with eggs and bacon is named after a mythological Chinese figure- it's just sorta what it's always been called."
icon = 'icons/obj/food/moth.dmi'
icon_state = "hua_mulan_congee"
@@ -420,7 +420,7 @@
w_class = WEIGHT_CLASS_SMALL
/obj/item/food/soup/toechtauese_rice_porridge
- name = "töchtaüse rice porridge"
+ name = "töchtaüse rice porridge"
desc = "Commonly served aboard the mothic fleet, rice porridge with töchtaüse syrup is more palatable than the regular stuff, if even just because it's spicier than normal."
icon = 'icons/obj/food/moth.dmi'
icon_state = "toechtauese_rice_porridge"
@@ -430,7 +430,7 @@
w_class = WEIGHT_CLASS_SMALL
/obj/item/food/soup/cornmeal_porridge
- name = "cornmeal porridge"
+ name = "cornmeal porridge"
desc = "A plate of cornmeal porridge. It's more flavourful than most porridges, and makes a good base for other flavours, too."
icon = 'icons/obj/food/moth.dmi'
icon_state = "cornmeal_porridge"
@@ -440,7 +440,7 @@
w_class = WEIGHT_CLASS_SMALL
/obj/item/food/soup/cheesy_porridge //milk, polenta, firm cheese, curd cheese, butter
- name = "cheesy porridge"
+ name = "cheesy porridge"
desc = "A rich and creamy bowl of cheesy cornmeal porridge."
icon = 'icons/obj/food/moth.dmi'
icon_state = "cheesy_porridge"
@@ -450,7 +450,7 @@
w_class = WEIGHT_CLASS_SMALL
/obj/item/food/soup/fried_eggplant_polenta
- name = "fried eggplant and polenta"
+ name = "fried eggplant and polenta"
desc = "Polenta loaded with cheese, served with a few discs of fried eggplant and some tomato sauce. Lække!"
icon = 'icons/obj/food/moth.dmi'
icon_state = "fried_eggplant_polenta"
@@ -765,16 +765,17 @@
custom_premium_price = PAYCHECK_EASY * 1.5
/obj/item/storage/box/gum/wake_up/examine_more(mob/user)
- var/list/msg = list(span_notice("You read some of the health and safety information..."))
- msg += "\t[span_info("For the relief of tiredness and drowsiness while working.")]"
- msg += "\t[span_info("Do not chew more than one strip every 12 hours. Do not use as a complete substitute for sleep.")]"
- msg += "\t[span_info("Do not give to children under 16. Do not exceed the maximum dosage. Do not ingest. Do not take for more than 3 days consecutively. Do not take in conjunction with other medication. May cause adverse reactions in patients with pre-existing heart conditions.")]"
- msg += "\t[span_info("Side effects of Activin use may include twitchy antennae, overactive wings, loss of keratin sheen, loss of setae coverage, arrythmia, blurred vision, and euphoria. Cease taking the medication if side effects occur.")]"
- msg += "\t[span_info("Repeated use may cause addiction.")]"
- msg += "\t[span_info("If the maximum dosage is exceeded, inform a member of your assigned vessel's medical staff immediately. Do not induce vomiting.")]"
- msg += "\t[span_info("Ingredients: each strip contains 500mg of Activin (dextro-methamphetamine). Other ingredients include Green Dye 450 (Verdant Meadow) and artificial herb flavouring.")]"
- msg += "\t[span_info("Storage: keep in a cool dry place. Do not use after the use-by date: 32/4/350.")]"
- return msg
+ . = ..()
+ . += span_notice("You read some of the health and safety information...")
+ . += "\t[span_info("For the relief of tiredness and drowsiness while working.")]"
+ . += "\t[span_info("Do not chew more than one strip every 12 hours. Do not use as a complete substitute for sleep.")]"
+ . += "\t[span_info("Do not give to children under 16. Do not exceed the maximum dosage. Do not ingest. Do not take for more than 3 days consecutively. Do not take in conjunction with other medication. May cause adverse reactions in patients with pre-existing heart conditions.")]"
+ . += "\t[span_info("Side effects of Activin use may include twitchy antennae, overactive wings, loss of keratin sheen, loss of setae coverage, arrythmia, blurred vision, and euphoria. Cease taking the medication if side effects occur.")]"
+ . += "\t[span_info("Repeated use may cause addiction.")]"
+ . += "\t[span_info("If the maximum dosage is exceeded, inform a member of your assigned vessel's medical staff immediately. Do not induce vomiting.")]"
+ . += "\t[span_info("Ingredients: each strip contains 500mg of Activin (dextro-methamphetamine). Other ingredients include Green Dye 450 (Verdant Meadow) and artificial herb flavouring.")]"
+ . += "\t[span_info("Storage: keep in a cool dry place. Do not use after the use-by date: 32/4/350.")]"
+ return .
/obj/item/storage/box/gum/wake_up/PopulateContents()
for(var/i in 1 to 4)
diff --git a/code/game/objects/items/hand_items.dm b/code/game/objects/items/hand_items.dm
index e2351b42da5..d23bce7e6f2 100644
--- a/code/game/objects/items/hand_items.dm
+++ b/code/game/objects/items/hand_items.dm
@@ -127,7 +127,7 @@
return FALSE
var/obj/item/bodypart/head/the_head = target.get_bodypart(BODY_ZONE_HEAD)
- if((target.get_biological_state() != BIO_FLESH_BONE && target.get_biological_state() != BIO_JUST_FLESH) || !the_head.is_organic_limb())
+ if((target.get_biological_state() != BIO_FLESH_BONE && target.get_biological_state() != BIO_JUST_FLESH) || !IS_ORGANIC_LIMB(the_head))
to_chat(user, span_warning("You can't noogie [target], [target.p_they()] [target.p_have()] no skin on [target.p_their()] head!"))
return
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index dcbee9ab9eb..1d0e70fec06 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -53,17 +53,17 @@
/obj/item/robot_suit/update_overlays()
. = ..()
if(l_arm)
- . += "[l_arm.icon_state]+o"
+ . += "[initial(l_arm.icon_state)]+o"
if(r_arm)
- . += "[r_arm.icon_state]+o"
+ . += "[initial(r_arm.icon_state)]+o"
if(chest)
- . += "[chest.icon_state]+o"
+ . += "[initial(chest.icon_state)]+o"
if(l_leg)
- . += "[l_leg.icon_state]+o"
+ . += "[initial(l_leg.icon_state)]+o"
if(r_leg)
- . += "[r_leg.icon_state]+o"
+ . += "[initial(r_leg.icon_state)]+o"
if(head)
- . += "[head.icon_state]+o"
+ . += "[initial(head.icon_state)]+o"
/obj/item/robot_suit/proc/check_completion()
if(l_arm && r_arm && l_leg && r_leg && head && head.flash1 && head.flash2 && chest && chest.wired && chest.cell)
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index e3ec9267639..9a24751b733 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -83,17 +83,20 @@
if(!affecting) //Missing limb?
to_chat(user, span_warning("[C] doesn't have \a [parse_zone(user.zone_selected)]!"))
return FALSE
- if(affecting.status != BODYPART_ORGANIC) //Limb must be organic to be healed - RR
+ if(!IS_ORGANIC_LIMB(affecting)) //Limb must be organic to be healed - RR
to_chat(user, span_warning("[src] won't work on a robotic limb!"))
return FALSE
if(affecting.brute_dam && brute || affecting.burn_dam && burn)
- user.visible_message("[user] applies [src] on [C]'s [affecting.name].", "You apply [src] on [C]'s [affecting.name].")
+ user.visible_message(
+ span_infoplain(span_green("[user] applies [src] on [C]'s [parse_zone(affecting.body_zone)].")),
+ span_infoplain(span_green("You apply [src] on [C]'s [parse_zone(affecting.body_zone)]."))
+ )
var/previous_damage = affecting.get_damage()
if(affecting.heal_damage(brute, burn))
C.update_damage_overlays()
post_heal_effects(max(previous_damage - affecting.get_damage(), 0), C, user)
return TRUE
- to_chat(user, span_warning("[C]'s [affecting.name] can not be healed with [src]!"))
+ to_chat(user, span_warning("[C]'s [parse_zone(affecting.body_zone)] can not be healed with [src]!"))
return FALSE
///Override this proc for special post heal effects.
diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm
index 83e9dd277f4..c900bf3d3f1 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -132,19 +132,18 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "burning",
if(!ishuman(L))
return
var/mob/living/carbon/human/H = L
- for(var/X in H.bodyparts)
- var/obj/item/bodypart/BP = X
- if(BP.status == BODYPART_ROBOTIC)
+ for(var/obj/item/bodypart/bodypart as anything in H.bodyparts)
+ if(!IS_ORGANIC_LIMB(bodypart))
to_chat(user, span_warning("[src.deity_name] refuses to heal this metallic taint!"))
return 0
var/heal_amt = 10
- var/list/hurt_limbs = H.get_damaged_bodyparts(1, 1, null, BODYPART_ORGANIC)
+ var/list/hurt_limbs = H.get_damaged_bodyparts(1, 1, null, BODYTYPE_ORGANIC)
if(hurt_limbs.len)
for(var/X in hurt_limbs)
var/obj/item/bodypart/affecting = X
- if(affecting.heal_damage(heal_amt, heal_amt, null, BODYPART_ORGANIC))
+ if(affecting.heal_damage(heal_amt, heal_amt, null, BODYTYPE_ORGANIC))
H.update_damage_overlays()
H.visible_message(span_notice("[user] heals [H] with the power of [deity_name]!"))
to_chat(H, span_boldnotice("May the power of [deity_name] compel you to be healed!"))
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index 2c5a167fd39..606fd65e158 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -122,7 +122,7 @@
var/obj/item/bodypart/affecting = attacked_humanoid.get_bodypart(check_zone(user.zone_selected))
- if(affecting && affecting.status == BODYPART_ROBOTIC && !user.combat_mode)
+ if(affecting && !IS_ORGANIC_LIMB(affecting) && !user.combat_mode)
if(src.use_tool(attacked_humanoid, user, 0, volume=50, amount=1))
if(user == attacked_humanoid)
user.visible_message(span_notice("[user] starts to fix some of the dents on [attacked_humanoid]'s [affecting.name]."),
diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm
index f0442f6c23b..f0cf48508e9 100644
--- a/code/game/objects/structures/beds_chairs/bed.dm
+++ b/code/game/objects/structures/beds_chairs/bed.dm
@@ -22,6 +22,10 @@
var/buildstackamount = 2
var/bolts = TRUE
+/obj/structure/bed/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/soft_landing)
+
/obj/structure/bed/examine(mob/user)
. = ..()
if(bolts)
diff --git a/code/game/objects/structures/beds_chairs/sofa.dm b/code/game/objects/structures/beds_chairs/sofa.dm
index 5d294e77538..b4fcb1ee666 100644
--- a/code/game/objects/structures/beds_chairs/sofa.dm
+++ b/code/game/objects/structures/beds_chairs/sofa.dm
@@ -7,9 +7,10 @@
var/mutable_appearance/armrest
/obj/structure/chair/sofa/Initialize(mapload)
+ . = ..()
armrest = mutable_appearance(icon, "[icon_state]_armrest", ABOVE_MOB_LAYER)
armrest.plane = GAME_PLANE_UPPER
- return ..()
+ AddElement(/datum/element/soft_landing)
/obj/structure/chair/sofa/electrify_self(obj/item/assembly/shock_kit/input_shock_kit, mob/user, list/overlays_from_child_procs)
if(!overlays_from_child_procs)
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index c406877eb1d..f57109597c1 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -50,7 +50,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror, 28)
hairdresser.hairstyle = new_style
- hairdresser.update_hair()
+ hairdresser.update_hair(is_creating = TRUE)
*/
/obj/structure/mirror/examine_status(mob/user)
@@ -225,7 +225,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror, 28)
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return TRUE
amazed_human.gender = FEMALE
- amazed_human.body_type = FEMALE
+ amazed_human.physique = FEMALE
to_chat(amazed_human, span_notice("Man, you feel like a woman!"))
else
return TRUE
@@ -235,7 +235,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror, 28)
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return TRUE
amazed_human.gender = MALE
- amazed_human.body_type = MALE
+ amazed_human.physique = MALE
to_chat(amazed_human, span_notice("Whoa man, you feel like a man!"))
else
return TRUE
diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm
index 3b968e5b7c5..aaadc6c7c24 100644
--- a/code/modules/admin/create_mob.dm
+++ b/code/modules/admin/create_mob.dm
@@ -12,7 +12,7 @@
/proc/randomize_human(mob/living/carbon/human/H)
H.gender = pick(MALE, FEMALE)
- H.body_type = H.gender
+ H.physique = H.gender
H.real_name = random_unique_name(H.gender)
H.name = H.real_name
H.underwear = random_underwear(H.gender)
@@ -49,6 +49,5 @@
//SKYRAT EDIT ADDITION END
H.dna.features["pod_hair"] = pick(GLOB.pod_hair_list)
- H.update_body()
- H.update_hair()
- H.update_body_parts()
+ H.update_body(is_creating = TRUE)
+ H.update_hair(is_creating = TRUE)
diff --git a/code/modules/antagonists/abductor/equipment/glands/heal.dm b/code/modules/antagonists/abductor/equipment/glands/heal.dm
index 7335c4fdb35..ba71d1f174c 100644
--- a/code/modules/antagonists/abductor/equipment/glands/heal.dm
+++ b/code/modules/antagonists/abductor/equipment/glands/heal.dm
@@ -53,7 +53,7 @@
if(!limb)
replace_limb(zone)
return
- if((limb.get_damage() >= (limb.max_damage / 2)) || (limb.status == BODYPART_ROBOTIC))
+ if((limb.get_damage() >= (limb.max_damage / 2)) || (!IS_ORGANIC_LIMB(limb)))
replace_limb(zone, limb)
return
@@ -72,7 +72,7 @@
return
var/obj/item/bodypart/chest/chest = owner.get_bodypart(BODY_ZONE_CHEST)
- if((chest.get_damage() >= (chest.max_damage / 4)) || (chest.status == BODYPART_ROBOTIC))
+ if((chest.get_damage() >= (chest.max_damage / 4)) || (!IS_ORGANIC_LIMB(chest)))
replace_chest(chest)
return
@@ -208,7 +208,7 @@
addtimer(CALLBACK(src, .proc/keep_replacing_blood), 30)
/obj/item/organ/heart/gland/heal/proc/replace_chest(obj/item/bodypart/chest/chest)
- if(chest.status == BODYPART_ROBOTIC)
+ if(!IS_ORGANIC_LIMB(chest))
owner.visible_message(span_warning("[owner]'s [chest.name] rapidly expels its mechanical components, replacing them with flesh!"), span_userdanger("Your [chest.name] rapidly expels its mechanical components, replacing them with flesh!"))
playsound(owner, 'sound/magic/clockwork/anima_fragment_attack.ogg', 50, TRUE)
var/list/dirs = GLOB.alldirs.Copy()
diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm
index e2a23f69978..1ecf327495a 100644
--- a/code/modules/antagonists/changeling/changeling.dm
+++ b/code/modules/antagonists/changeling/changeling.dm
@@ -654,9 +654,11 @@
chosen_dna.transfer_identity(user, TRUE)
- user.Digitigrade_Leg_Swap(!(DIGITIGRADE in chosen_dna.species?.species_traits))
+ for(var/obj/item/bodypart/limb as anything in user.bodyparts)
+ if(IS_ORGANIC_LIMB(limb))
+ limb.update_limb(is_creating = TRUE)
+
user.updateappearance(mutcolor_update = TRUE)
- user.update_body()
user.domutcheck()
// Get rid of any scars from previous Changeling-ing
diff --git a/code/modules/antagonists/changeling/powers/fakedeath.dm b/code/modules/antagonists/changeling/powers/fakedeath.dm
index 835e13cfb36..05a58894cd9 100644
--- a/code/modules/antagonists/changeling/powers/fakedeath.dm
+++ b/code/modules/antagonists/changeling/powers/fakedeath.dm
@@ -43,7 +43,7 @@
"You hear organic matter ripping \
and tearing!")
user.emote("scream")
- user.regenerate_limbs(0, list(BODY_ZONE_HEAD))
+ user.regenerate_limbs(list(BODY_ZONE_HEAD))
user.regenerate_organs()
/datum/action/changeling/fakedeath/proc/ready_to_regenerate(mob/user)
diff --git a/code/modules/antagonists/changeling/powers/regenerate.dm b/code/modules/antagonists/changeling/powers/regenerate.dm
index fffcb731bed..01109161dca 100644
--- a/code/modules/antagonists/changeling/powers/regenerate.dm
+++ b/code/modules/antagonists/changeling/powers/regenerate.dm
@@ -23,7 +23,7 @@
"You hear organic matter ripping \
and tearing!")
C.emote("scream")
- C.regenerate_limbs(1)
+ C.regenerate_limbs()
if(!user.getorganslot(ORGAN_SLOT_BRAIN))
var/obj/item/organ/brain/B
if(C.has_dna() && C.dna.species.mutantbrain)
diff --git a/code/modules/antagonists/fugitive/fugitive_outfits.dm b/code/modules/antagonists/fugitive/fugitive_outfits.dm
index 6400324c720..e32e1f2ce25 100644
--- a/code/modules/antagonists/fugitive/fugitive_outfits.dm
+++ b/code/modules/antagonists/fugitive/fugitive_outfits.dm
@@ -219,18 +219,6 @@
/obj/item/bountytrap = 4
)
-/datum/outfit/bountysynth/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
- if(visualsOnly)
- return
- var/datum/species/synth/synthetic_appearance = new()
- H.set_species(synthetic_appearance)
- synthetic_appearance.assume_disguise(synthetic_appearance, H)
- H.update_hair()
- var/obj/item/card/id/W = H.wear_id
- W.registered_name = H.real_name
- W.update_label()
- W.update_icon()
-
//ids and ert code
/obj/item/card/id/advanced/bountyhunter
diff --git a/code/modules/antagonists/heretic/structures/mawed_crucible.dm b/code/modules/antagonists/heretic/structures/mawed_crucible.dm
index 32311eefada..adb7a64a5a5 100644
--- a/code/modules/antagonists/heretic/structures/mawed_crucible.dm
+++ b/code/modules/antagonists/heretic/structures/mawed_crucible.dm
@@ -75,7 +75,7 @@
if(istype(weapon, /obj/item/bodypart))
var/obj/item/bodypart/consumed = weapon
- if(consumed.status != BODYPART_ORGANIC)
+ if(!IS_ORGANIC_LIMB(consumed))
balloon_alert(user, "not organic!")
return
diff --git a/code/modules/antagonists/nightmare/nightmare_species.dm b/code/modules/antagonists/nightmare/nightmare_species.dm
index 5bd607809a3..5383982a6dd 100644
--- a/code/modules/antagonists/nightmare/nightmare_species.dm
+++ b/code/modules/antagonists/nightmare/nightmare_species.dm
@@ -4,7 +4,7 @@
/datum/species/shadow/nightmare
name = "Nightmare"
id = SPECIES_NIGHTMARE
- limbs_id = SPECIES_SHADOW
+ examine_limb_id = SPECIES_SHADOW
burnmod = 1.5
no_equip = list(ITEM_SLOT_MASK, ITEM_SLOT_OCLOTHING, ITEM_SLOT_GLOVES, ITEM_SLOT_FEET, ITEM_SLOT_ICLOTHING, ITEM_SLOT_SUITSTORE)
species_traits = list(NOBLOOD,NO_UNDERWEAR,NO_DNA_COPY,NOTRANSSTING,NOEYESPRITES)
diff --git a/code/modules/antagonists/revenant/revenant_abilities.dm b/code/modules/antagonists/revenant/revenant_abilities.dm
index 90219267ea9..8bc04f6fc52 100644
--- a/code/modules/antagonists/revenant/revenant_abilities.dm
+++ b/code/modules/antagonists/revenant/revenant_abilities.dm
@@ -358,7 +358,7 @@
if(ishuman(mob))
var/mob/living/carbon/human/H = mob
if(H.dna && H.dna.species && !HAS_TRAIT(H, TRAIT_VIRUSIMMUNE)) // SKYRAT EDIT - No more funny purple hair
- H.dna.species.handle_hair(H,"#1d2953") //will be reset when blight is cured
+ H.set_haircolor("#1d2953", override = TRUE) //will be reset when blight is cured
var/blightfound = FALSE
for(var/datum/disease/revblight/blight in H.diseases)
blightfound = TRUE
diff --git a/code/modules/antagonists/revenant/revenant_blight.dm b/code/modules/antagonists/revenant/revenant_blight.dm
index defe4a6c851..cd05d88dd9e 100644
--- a/code/modules/antagonists/revenant/revenant_blight.dm
+++ b/code/modules/antagonists/revenant/revenant_blight.dm
@@ -20,7 +20,7 @@
affected_mob.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#1d2953")
if(affected_mob.dna && affected_mob.dna.species)
affected_mob.dna.species.handle_mutant_bodyparts(affected_mob)
- affected_mob.dna.species.handle_hair(affected_mob)
+ affected_mob.set_haircolor(null, override = TRUE)
to_chat(affected_mob, span_notice("You feel better."))
..()
@@ -64,7 +64,7 @@
new /obj/effect/temp_visual/revenant(affected_mob.loc)
if(affected_mob.dna && affected_mob.dna.species)
affected_mob.dna.species.handle_mutant_bodyparts(affected_mob,"#1d2953")
- affected_mob.dna.species.handle_hair(affected_mob,"#1d2953")
+ affected_mob.set_haircolor("#1d2953", override = TRUE)
affected_mob.visible_message(span_warning("[affected_mob] looks terrifyingly gaunt..."), span_revennotice("You suddenly feel like your skin is wrong..."))
affected_mob.add_atom_colour("#1d2953", TEMPORARY_COLOUR_PRIORITY)
addtimer(CALLBACK(src, .proc/cure), 10 SECONDS)
diff --git a/code/modules/antagonists/thief/thief.dm b/code/modules/antagonists/thief/thief.dm
index 978a6c0ce52..d387d866281 100644
--- a/code/modules/antagonists/thief/thief.dm
+++ b/code/modules/antagonists/thief/thief.dm
@@ -100,7 +100,7 @@
if(SSatoms.initialized == INITIALIZATION_INSSATOMS)
thief.w_uniform?.update_greyscale()
thief.update_inv_w_uniform()
- thief.body_type = FEMALE //update_body() and gender block or something
+ thief.physique = FEMALE //update_body() and gender block or something
thief.hair_color = "#2A71DC" //hair color dna block
thief.skin_tone = "caucasian2" //skin tone dna block
thief.hairstyle = "Bun Head 2" //update_hair()
diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm
index 8c2deb4cbae..a7d07884a71 100644
--- a/code/modules/awaymissions/mission_code/snowdin.dm
+++ b/code/modules/awaymissions/mission_code/snowdin.dm
@@ -197,15 +197,15 @@
return
var/mob/living/carbon/human/burn_human = burn_living
var/datum/species/burn_species = burn_human.dna.species
- if(istype(burn_species, /datum/species/plasmaman) || istype(burn_species, /datum/species/android) || istype(burn_species, /datum/species/synth)) //ignore plasmamen/robotic species
+ if(istype(burn_species, /datum/species/plasmaman) || istype(burn_species, /datum/species/android)) //ignore plasmamen/robotic species
return
var/list/plasma_parts = list()//a list of the organic parts to be turned into plasma limbs
var/list/robo_parts = list()//keep a reference of robotic parts so we know if we can turn them into a plasmaman
for(var/obj/item/bodypart/burn_limb as anything in burn_human.bodyparts)
- if(burn_limb.status == BODYPART_ORGANIC && burn_limb.species_id != SPECIES_PLASMAMAN) //getting every organic, non-plasmaman limb (augments/androids are immune to this)
+ if(IS_ORGANIC_LIMB(burn_limb) && burn_limb.limb_id != SPECIES_PLASMAMAN) //getting every organic, non-plasmaman limb (augments/androids are immune to this)
plasma_parts += burn_limb
- if(burn_limb.status == BODYPART_ROBOTIC)
+ if(!IS_ORGANIC_LIMB(burn_limb))
robo_parts += burn_limb
burn_human.adjustToxLoss(15)
diff --git a/code/modules/capture_the_flag/ctf_game.dm b/code/modules/capture_the_flag/ctf_game.dm
index 1c3272c11b4..140cc4d5fec 100644
--- a/code/modules/capture_the_flag/ctf_game.dm
+++ b/code/modules/capture_the_flag/ctf_game.dm
@@ -389,7 +389,8 @@
var/mob/living/carbon/human/M = new /mob/living/carbon/human(get_turf(src))
new_team_member.prefs.safe_transfer_prefs_to(M, is_antag = TRUE)
- M.set_species(/datum/species/synth)
+ if(M.dna.species.outfit_important_for_life)
+ M.set_species(/datum/species/human)
M.key = new_team_member.key
M.faction += team
M.equipOutfit(chosen_class)
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 687b5b7c8ea..594ef01b5fe 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -566,10 +566,8 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/character_preview_view)
character.dna.real_name = character.real_name
if(icon_updates)
- character.icon_render_key = null //turns out if you don't set this to null update_body_parts does nothing, since it assumes the operation was cached
- character.update_body()
- character.update_hair()
- character.update_body_parts()
+ character.icon_render_keys = list()
+ character.update_body(is_creating = TRUE)
/// Returns whether the parent mob should have the random hardcore settings enabled. Assumes it has a mind.
diff --git a/code/modules/client/preferences/body_type.dm b/code/modules/client/preferences/body_type.dm
index 6f5fc7f8301..4e695f7ab9b 100644
--- a/code/modules/client/preferences/body_type.dm
+++ b/code/modules/client/preferences/body_type.dm
@@ -1,4 +1,3 @@
-/* SKYRAT EDIT REMOVAL
#define USE_GENDER "Use gender"
/datum/preference/choiced/body_type
@@ -15,9 +14,9 @@
/datum/preference/choiced/body_type/apply_to_human(mob/living/carbon/human/target, value)
if (value == USE_GENDER)
- target.body_type = target.gender
+ target.physique = target.gender
else
- target.body_type = value
+ target.physique = value
/datum/preference/choiced/body_type/is_accessible(datum/preferences/preferences)
if (!..(preferences))
@@ -27,4 +26,4 @@
return initial(species.sexes)
#undef USE_GENDER
-*/
+
diff --git a/code/modules/client/preferences/species.dm b/code/modules/client/preferences/species.dm
index 1a68f563ed9..c7a18841aea 100644
--- a/code/modules/client/preferences/species.dm
+++ b/code/modules/client/preferences/species.dm
@@ -6,7 +6,7 @@
randomize_by_default = FALSE
/datum/preference/choiced/species/deserialize(input, datum/preferences/preferences)
- return GLOB.species_list[sanitize_inlist(input, get_choices_serialized(), "human")]
+ return GLOB.species_list[sanitize_inlist(input, get_choices_serialized(), SPECIES_HUMAN)]
/datum/preference/choiced/species/serialize(input)
var/datum/species/species = input
diff --git a/code/modules/client/preferences/species_features/basic.dm b/code/modules/client/preferences/species_features/basic.dm
index bf208f36942..f75e12dd0d1 100644
--- a/code/modules/client/preferences/species_features/basic.dm
+++ b/code/modules/client/preferences/species_features/basic.dm
@@ -53,6 +53,7 @@
/datum/preference/choiced/facial_hairstyle/apply_to_human(mob/living/carbon/human/target, value)
target.facial_hairstyle = value
+ target.update_hair(is_creating = TRUE)
/datum/preference/choiced/facial_hairstyle/compile_constant_data()
var/list/data = ..()
@@ -69,6 +70,7 @@
/datum/preference/color/facial_hair_color/apply_to_human(mob/living/carbon/human/target, value)
target.facial_hair_color = value
+ target.update_hair(is_creating = TRUE)
/datum/preference/choiced/facial_hair_gradient
category = PREFERENCE_CATEGORY_SECONDARY_FEATURES
@@ -82,7 +84,7 @@
/datum/preference/choiced/facial_hair_gradient/apply_to_human(mob/living/carbon/human/target, value)
LAZYSETLEN(target.grad_style, GRADIENTS_LEN)
target.grad_style[GRADIENT_FACIAL_HAIR_KEY] = value
- target.update_hair()
+ target.update_hair(is_creating = TRUE)
/datum/preference/choiced/facial_hair_gradient/create_default_value()
return "None"
@@ -96,7 +98,7 @@
/datum/preference/color/facial_hair_gradient/apply_to_human(mob/living/carbon/human/target, value)
LAZYSETLEN(target.grad_color, GRADIENTS_LEN)
target.grad_color[GRADIENT_FACIAL_HAIR_KEY] = value
- target.update_hair()
+ target.update_hair(is_creating = TRUE)
/datum/preference/color/facial_hair_gradient/is_accessible(datum/preferences/preferences)
if (!..(preferences))
@@ -145,7 +147,7 @@
/datum/preference/choiced/hair_gradient/apply_to_human(mob/living/carbon/human/target, value)
LAZYSETLEN(target.grad_style, GRADIENTS_LEN)
target.grad_style[GRADIENT_HAIR_KEY] = value
- target.update_hair()
+ target.update_hair(is_creating = TRUE)
/datum/preference/choiced/hair_gradient/create_default_value()
return "None"
@@ -159,7 +161,7 @@
/datum/preference/color/hair_gradient/apply_to_human(mob/living/carbon/human/target, value)
LAZYSETLEN(target.grad_color, GRADIENTS_LEN)
target.grad_color[GRADIENT_HAIR_KEY] = value
- target.update_hair()
+ target.update_hair(is_creating = TRUE)
/datum/preference/color/hair_gradient/is_accessible(datum/preferences/preferences)
if (!..(preferences))
diff --git a/code/modules/client/preferences/species_features/ethereal.dm b/code/modules/client/preferences/species_features/ethereal.dm
index dfd7afb06a9..61818aee2d0 100644
--- a/code/modules/client/preferences/species_features/ethereal.dm
+++ b/code/modules/client/preferences/species_features/ethereal.dm
@@ -8,10 +8,10 @@
/datum/preference/choiced/ethereal_color/init_possible_values()
var/list/values = list()
- var/icon/ethereal_base = icon('icons/mob/human_parts_greyscale.dmi', "ethereal_head_m")
- ethereal_base.Blend(icon('icons/mob/human_parts_greyscale.dmi', "ethereal_chest_m"), ICON_OVERLAY)
- ethereal_base.Blend(icon('icons/mob/human_parts_greyscale.dmi', "ethereal_l_arm"), ICON_OVERLAY)
- ethereal_base.Blend(icon('icons/mob/human_parts_greyscale.dmi', "ethereal_r_arm"), ICON_OVERLAY)
+ var/icon/ethereal_base = icon('icons/mob/species/ethereal/bodyparts.dmi', "ethereal_head")
+ ethereal_base.Blend(icon('icons/mob/species/ethereal/bodyparts.dmi', "ethereal_chest"), ICON_OVERLAY)
+ ethereal_base.Blend(icon('icons/mob/species/ethereal/bodyparts.dmi', "ethereal_l_arm"), ICON_OVERLAY)
+ ethereal_base.Blend(icon('icons/mob/species/ethereal/bodyparts.dmi', "ethereal_r_arm"), ICON_OVERLAY)
var/icon/eyes = icon('icons/mob/human_face.dmi', "eyes")
eyes.Blend(COLOR_BLACK, ICON_MULTIPLY)
diff --git a/code/modules/client/preferences/species_features/lizard.dm b/code/modules/client/preferences/species_features/lizard.dm
index 43860174b89..96717b4d80e 100644
--- a/code/modules/client/preferences/species_features/lizard.dm
+++ b/code/modules/client/preferences/species_features/lizard.dm
@@ -1,9 +1,8 @@
-/*
+/* SKYRAT EDIT REMOVAL
/proc/generate_lizard_side_shots(list/sprite_accessories, key, include_snout = TRUE)
var/list/values = list()
- var/icon/lizard = icon('icons/mob/human_parts_greyscale.dmi', "lizard_head_m", EAST)
-
+ var/icon/lizard = icon('icons/mob/species/lizard/bodyparts.dmi', "lizard_head", EAST)
var/icon/eyes = icon('icons/mob/human_face.dmi', "eyes", EAST)
eyes.Blend(COLOR_GRAY, ICON_MULTIPLY)
lizard.Blend(eyes, ICON_OVERLAY)
@@ -39,10 +38,10 @@
/datum/preference/choiced/lizard_body_markings/init_possible_values()
var/list/values = list()
- var/icon/lizard = icon('icons/mob/human_parts_greyscale.dmi', "lizard_chest_m")
+ var/icon/lizard = icon('icons/mob/species/lizard/bodyparts.dmi', "lizard_chest_m")
- for (var/name in GLOB.sprite_accessories["body_markings"]) //SKYRAT EDIT
- var/datum/sprite_accessory/sprite_accessory = GLOB.sprite_accessories["body_markings"][name] //SKYRAT EDIT
+ for (var/name in GLOB.body_markings_list)
+ var/datum/sprite_accessory/sprite_accessory = GLOB.body_markings_list[name]
var/icon/final_icon = icon(lizard)
@@ -64,10 +63,7 @@
return values
/datum/preference/choiced/lizard_body_markings/apply_to_human(mob/living/carbon/human/target, value)
- if(!target.dna.mutant_bodyparts["body_markings"])
- target.dna.mutant_bodyparts["body_markings"] = list()
- target.dna.mutant_bodyparts["body_markings"][MUTANT_INDEX_NAME] = value
- target.dna.mutant_bodyparts["body_markings"][MUTANT_INDEX_COLOR_LIST] = list("333", "222", "444")
+ target.dna.features["body_markings"] = value
/datum/preference/choiced/lizard_frills
savefile_key = "feature_lizard_frills"
@@ -77,13 +73,10 @@
should_generate_icons = TRUE
/datum/preference/choiced/lizard_frills/init_possible_values()
- return generate_lizard_side_shots(GLOB.sprite_accessories["frills"], "frills") //SKYRAT EDIT
+ return generate_lizard_side_shots(GLOB.frills_list, "frills")
/datum/preference/choiced/lizard_frills/apply_to_human(mob/living/carbon/human/target, value)
- if(!target.dna.species.mutant_bodyparts["frills"])
- target.dna.species.mutant_bodyparts["frills"] = list()
- target.dna.species.mutant_bodyparts["frills"][MUTANT_INDEX_NAME] = value
- target.dna.species.mutant_bodyparts["frills"][MUTANT_INDEX_COLOR_LIST] = list("333", "222", "444")
+ target.dna.features["frills"] = value
/datum/preference/choiced/lizard_horns
savefile_key = "feature_lizard_horns"
@@ -93,15 +86,11 @@
should_generate_icons = TRUE
/datum/preference/choiced/lizard_horns/init_possible_values()
- return generate_lizard_side_shots(GLOB.sprite_accessories["horns"], "horns") //SKYRAT EDIT
+ return generate_lizard_side_shots(GLOB.horns_list, "horns")
/datum/preference/choiced/lizard_horns/apply_to_human(mob/living/carbon/human/target, value)
- if(!target.dna.species.mutant_bodyparts["horns"])
- target.dna.species.mutant_bodyparts["horns"] = list()
- target.dna.species.mutant_bodyparts["horns"][MUTANT_INDEX_NAME] = value
- target.dna.species.mutant_bodyparts["horns"][MUTANT_INDEX_COLOR_LIST] = list("333", "222", "444")
+ target.dna.features["horns"] = value
-/* SKYRAT EDIT REMOVAL
/datum/preference/choiced/lizard_legs
savefile_key = "feature_lizard_legs"
savefile_identifier = PREFERENCE_CHARACTER
@@ -109,27 +98,23 @@
relevant_mutant_bodypart = "legs"
/datum/preference/choiced/lizard_legs/init_possible_values()
- return GLOB.sprite_accessories["legs"] //SKYRAT EDIT CHANGE
+ return assoc_to_keys(GLOB.legs_list)
/datum/preference/choiced/lizard_legs/apply_to_human(mob/living/carbon/human/target, value)
target.dna.features["legs"] = value
-*/
/datum/preference/choiced/lizard_snout
- savefile_key = "feature_lizrd_snout"
+ savefile_key = "feature_lizard_snout"
savefile_identifier = PREFERENCE_CHARACTER
category = PREFERENCE_CATEGORY_FEATURES
main_feature_name = "Snout"
should_generate_icons = TRUE
/datum/preference/choiced/lizard_snout/init_possible_values()
- return generate_lizard_side_shots(GLOB.sprite_accessories["snout"], "snout", include_snout = FALSE) //SKYRAT EDIT
+ return generate_lizard_side_shots(GLOB.snouts_list, "snout", include_snout = FALSE)
/datum/preference/choiced/lizard_snout/apply_to_human(mob/living/carbon/human/target, value)
- if(!target.dna.species.mutant_bodyparts["snout"])
- target.dna.species.mutant_bodyparts["snout"] = list()
- target.dna.species.mutant_bodyparts["snout"][MUTANT_INDEX_NAME] = value
- target.dna.species.mutant_bodyparts["snout"][MUTANT_INDEX_COLOR_LIST] = list("333", "222", "444")
+ target.dna.features["snout"] = value
/datum/preference/choiced/lizard_spines
savefile_key = "feature_lizard_spines"
@@ -138,13 +123,10 @@
relevant_mutant_bodypart = "spines"
/datum/preference/choiced/lizard_spines/init_possible_values()
- return GLOB.sprite_accessories["spines"] //SKYRAT EDIT
+ return assoc_to_keys(GLOB.spines_list)
/datum/preference/choiced/lizard_spines/apply_to_human(mob/living/carbon/human/target, value)
- if(!target.dna.species.mutant_bodyparts["spines"])
- target.dna.species.mutant_bodyparts["spines"] = list()
- target.dna.species.mutant_bodyparts["spines"][MUTANT_INDEX_NAME] = value
- target.dna.species.mutant_bodyparts["spines"][MUTANT_INDEX_COLOR_LIST] = list("333", "222", "444")
+ target.dna.features["spines"] = value
/datum/preference/choiced/lizard_tail
savefile_key = "feature_lizard_tail"
@@ -153,11 +135,8 @@
relevant_mutant_bodypart = "tail_lizard"
/datum/preference/choiced/lizard_tail/init_possible_values()
- return GLOB.sprite_accessories["tail"] //SKYRAT EDIT
+ return assoc_to_keys(GLOB.tails_list_lizard)
/datum/preference/choiced/lizard_tail/apply_to_human(mob/living/carbon/human/target, value)
- if(!target.dna.species.mutant_bodyparts["tail"])
- target.dna.species.mutant_bodyparts["tail"] = list()
- target.dna.species.mutant_bodyparts["tail"][MUTANT_INDEX_NAME] = value
- target.dna.species.mutant_bodyparts["tail"][MUTANT_INDEX_COLOR_LIST] = list("333", "222", "444")
+ target.dna.features["tail_lizard"] = value
*/
diff --git a/code/modules/client/preferences/species_features/moth.dm b/code/modules/client/preferences/species_features/moth.dm
index 83f08b681c8..de67f09a215 100644
--- a/code/modules/client/preferences/species_features/moth.dm
+++ b/code/modules/client/preferences/species_features/moth.dm
@@ -9,11 +9,11 @@
/datum/preference/choiced/moth_antennae/init_possible_values()
var/list/values = list()
- var/icon/moth_head = icon('icons/mob/human_parts.dmi', "moth_head_m")
+ var/icon/moth_head = icon('icons/mob/species/moth/bodyparts.dmi', "moth_head")
moth_head.Blend(icon('icons/mob/human_face.dmi', "motheyes"), ICON_OVERLAY)
- for (var/antennae_name in GLOB.sprite_accessories["moth_antennae"]) //SKYRAT EDIT
- var/datum/sprite_accessory/antennae = GLOB.sprite_accessories["moth_antennae"][antennae_name] //SKYRAT EDIT
+ for (var/antennae_name in GLOB.moth_antennae_list)
+ var/datum/sprite_accessory/antennae = GLOB.moth_antennae_list[antennae_name]
var/icon/icon_with_antennae = new(moth_head)
icon_with_antennae.Blend(icon(antennae.icon, "m_moth_antennae_[antennae.icon_state]_FRONT"), ICON_OVERLAY)
@@ -43,20 +43,20 @@
moth_body.Blend(icon('icons/mob/moth_wings.dmi', "m_moth_wings_plain_BEHIND"), ICON_OVERLAY)
var/list/body_parts = list(
- BODY_ZONE_HEAD,
- BODY_ZONE_CHEST,
- BODY_ZONE_L_ARM,
- BODY_ZONE_R_ARM,
+ /obj/item/bodypart/head/moth,
+ /obj/item/bodypart/chest/moth,
+ /obj/item/bodypart/l_arm/moth,
+ /obj/item/bodypart/r_arm/moth,
)
- for (var/body_part in body_parts)
- var/gender = (body_part == "chest" || body_part == "head") ? "_m" : ""
- moth_body.Blend(icon('icons/mob/human_parts.dmi', "moth_[body_part][gender]"), ICON_OVERLAY)
+ for (var/obj/item/bodypart/body_part in body_parts)
+ var/gender = (initial(body_part.is_dimorphic)) ? "_m" : ""
+ moth_body.Blend(icon('icons/mob/species/moth/bodyparts.dmi', "moth_[body_part][gender]"), ICON_OVERLAY)
moth_body.Blend(icon('icons/mob/human_face.dmi', "motheyes"), ICON_OVERLAY)
- for (var/markings_name in GLOB.sprite_accessories["moth_markings"]) //SKYRAT EDIT
- var/datum/sprite_accessory/markings = GLOB.sprite_accessories["moth_markings"][markings_name] //SKYRAT EDIT
+ for (var/markings_name in GLOB.moth_markings_list)
+ var/datum/sprite_accessory/markings = GLOB.moth_markings_list[markings_name]
var/icon/icon_with_markings = new(moth_body)
if (markings_name != "None")
@@ -79,7 +79,6 @@
/datum/preference/choiced/moth_markings/apply_to_human(mob/living/carbon/human/target, value)
target.dna.features["moth_markings"] = value
-
/datum/preference/choiced/moth_wings
savefile_key = "feature_moth_wings"
savefile_identifier = PREFERENCE_CHARACTER
@@ -88,7 +87,11 @@
should_generate_icons = TRUE
/datum/preference/choiced/moth_wings/init_possible_values()
- var/list/icon/values = possible_values_for_sprite_accessory_list_for_body_part(GLOB.sprite_accessories["moth_wings"]) //SKYRAT EDIT
+ var/list/icon/values = possible_values_for_sprite_accessory_list_for_body_part(
+ GLOB.moth_wings_list,
+ "moth_wings",
+ list("BEHIND", "FRONT"),
+ )
// Moth wings are in a stupid dimension
for (var/name in values)
@@ -98,4 +101,5 @@
/datum/preference/choiced/moth_wings/apply_to_human(mob/living/carbon/human/target, value)
target.dna.features["moth_wings"] = value
+
*/
diff --git a/code/modules/client/preferences/species_features/pod.dm b/code/modules/client/preferences/species_features/pod.dm
index d3993fae62a..118572dc444 100644
--- a/code/modules/client/preferences/species_features/pod.dm
+++ b/code/modules/client/preferences/species_features/pod.dm
@@ -8,7 +8,7 @@
/datum/preference/choiced/pod_hair/init_possible_values()
var/list/values = list()
- var/icon/pod_head = icon('icons/mob/human_parts.dmi', "pod_head_m")
+ var/icon/pod_head = icon('icons/mob/human_parts_greyscale.dmi', "pod_head_m")
for (var/pod_name in GLOB.pod_hair_list)
var/datum/sprite_accessory/pod_hair = GLOB.pod_hair_list[pod_name]
@@ -20,6 +20,7 @@
icon_with_hair.Blend(icon_adj, ICON_OVERLAY)
icon_with_hair.Scale(64, 64)
icon_with_hair.Crop(15, 64, 15 + 31, 64 - 31)
+ icon_with_hair.Blend(COLOR_GREEN, ICON_MULTIPLY)
values[pod_hair.name] = icon_with_hair
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index d424b08dcd3..bf803101e9e 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -176,7 +176,7 @@
/obj/item/clothing/proc/take_damage_zone(def_zone, damage_amount, damage_type, armour_penetration)
if(!def_zone || !limb_integrity || (initial(body_parts_covered) in GLOB.bitflags)) // the second check sees if we only cover one bodypart anyway and don't need to bother with this
return
- var/list/covered_limbs = body_parts_covered2organ_names(body_parts_covered) // what do we actually cover?
+ var/list/covered_limbs = cover_flags2body_zones(body_parts_covered) // what do we actually cover?
if(!(def_zone in covered_limbs))
return
@@ -198,7 +198,7 @@
* * damage_type: Only really relevant for the verb for describing the breaking, and maybe atom_destruction()
*/
/obj/item/clothing/proc/disable_zone(def_zone, damage_type)
- var/list/covered_limbs = body_parts_covered2organ_names(body_parts_covered)
+ var/list/covered_limbs = cover_flags2body_zones(body_parts_covered)
if(!(def_zone in covered_limbs))
return
@@ -211,7 +211,7 @@
RegisterSignal(C, COMSIG_MOVABLE_MOVED, .proc/bristle, override = TRUE)
zones_disabled++
- for(var/i in zone2body_parts_covered(def_zone))
+ for(var/i in body_zone2cover_flags(def_zone))
body_parts_covered &= ~i
if(body_parts_covered == NONE) // if there are no more parts to break then the whole thing is kaput
diff --git a/code/modules/clothing/head/hat.dm b/code/modules/clothing/head/hat.dm
index a9616869cf5..ff229efe4da 100644
--- a/code/modules/clothing/head/hat.dm
+++ b/code/modules/clothing/head/hat.dm
@@ -186,7 +186,7 @@
flags_inv = 0
armor = list(MELEE = 30, BULLET = 15, LASER = 30, ENERGY = 40, BOMB = 25, BIO = 0, FIRE = 50, ACID = 50)
strip_delay = (8 SECONDS)
- mutant_variants = NONE //SKYRAT EDIT lets anthros wear the hat
+ supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON //SKYRAT EDIT lets anthros wear the hat
/obj/item/clothing/head/human_leather
name = "human skin hat"
diff --git a/code/modules/clothing/masks/bandana.dm b/code/modules/clothing/masks/bandana.dm
index e73c62b1a99..e2d87aa9386 100644
--- a/code/modules/clothing/masks/bandana.dm
+++ b/code/modules/clothing/masks/bandana.dm
@@ -12,9 +12,9 @@
adjustmask(user)
//SKYRAT EDIT START: BANDANA HATS FOR MUTANTS
if(slot_flags & ITEM_SLOT_HEAD)
- mutant_variants = NONE
+ supports_variations_flags = NONE
if(slot_flags & ITEM_SLOT_MASK)
- mutant_variants = initial(mutant_variants)
+ supports_variations_flags = initial(supports_variations_flags)
//SKYRAT EDIT END
/obj/item/clothing/mask/bandana/AltClick(mob/user)
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index 8e0f0eeb504..5e45f4f40b5 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -116,7 +116,7 @@
RESKIN_ICON_STATE = "peacekeeper_trench_hos",
RESKIN_WORN_ICON = 'modular_skyrat/master_files/icons/mob/clothing/suit.dmi',
RESKIN_WORN_ICON_STATE = "peacekeeper_trench_hos",
- RESKIN_MUTANT_VARIANTS = NONE
+ RESKIN_supports_variations_flags = NONE
)
)
/// SKYRAT EDIT ADDITION END
@@ -172,7 +172,7 @@
RESKIN_ICON_STATE = "peacekeeper_trench_warden",
RESKIN_WORN_ICON = 'modular_skyrat/master_files/icons/mob/clothing/suit.dmi',
RESKIN_WORN_ICON_STATE = "peacekeeper_trench_warden",
- RESKIN_MUTANT_VARIANTS = NONE
+ RESKIN_supports_variations_flags = NONE
)
)
/// SKYRAT EDIT ADDITION END
diff --git a/code/modules/clothing/suits/costume.dm b/code/modules/clothing/suits/costume.dm
index 0b29d9833d8..1bf35bac5de 100644
--- a/code/modules/clothing/suits/costume.dm
+++ b/code/modules/clothing/suits/costume.dm
@@ -470,6 +470,7 @@
icon_state = "MajimaJacket"
inhand_icon_state = "MajimaJacket"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/suit/dutch
name = "dutch's jacket"
@@ -478,6 +479,7 @@
inhand_icon_state = "DutchJacket"
body_parts_covered = ARMS
body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/suit/driscoll
name = "driscoll poncho"
@@ -485,6 +487,7 @@
icon_state = "driscoll_suit"
inhand_icon_state = "driscoll_suit"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/suit/irs
name = "internal revenue service jacket"
@@ -492,6 +495,7 @@
icon_state = "irs_suit"
inhand_icon_state = "irs_suit"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/suit/osi
name = "\improper O.S.I. body armor"
@@ -499,6 +503,7 @@
icon_state = "osi_suit"
inhand_icon_state = "osi_suit"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/suit/tmc
name = "\improper Lost M.C. cut"
@@ -506,6 +511,7 @@
icon_state = "tmc_suit"
inhand_icon_state = "tmc_suit"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/suit/pg
name = "powder ganger jacket"
@@ -513,6 +519,7 @@
icon_state = "pg_suit"
inhand_icon_state = "pg_suit"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/suit/deckers
name = "decker hoodie"
@@ -520,6 +527,7 @@
icon_state = "decker_suit"
inhand_icon_state = "decker_suit"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/suit/morningstar
name = "morningstar coat"
@@ -527,6 +535,7 @@
icon_state = "morningstar_suit"
inhand_icon_state = "morningstar_suit"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/suit/saints
name = "Third Street Saints fur coat"
@@ -536,6 +545,7 @@
body_parts_covered = CHEST|GROIN|LEGS|ARMS
cold_protection = CHEST|GROIN|LEGS|ARMS
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/suit/phantom
name = "phantom thief coat"
@@ -543,6 +553,7 @@
icon_state = "phantom_suit"
inhand_icon_state = "phantom_suit"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/suit/allies
name = "allies body armor"
@@ -550,6 +561,7 @@
icon_state = "allies_armor"
inhand_icon_state = "allies_armor"
body_parts_covered = CHEST|GROIN
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/suit/soviet
name = "soviet armored coat"
@@ -578,4 +590,3 @@
icon_state = "football_armor_red"
inhand_icon_state = "football_armor_red"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
-
diff --git a/code/modules/clothing/suits/moth.dm b/code/modules/clothing/suits/moth.dm
index e366d5e2cca..d0997c09457 100644
--- a/code/modules/clothing/suits/moth.dm
+++ b/code/modules/clothing/suits/moth.dm
@@ -25,3 +25,4 @@
body_parts_covered = CHEST|GROIN|ARMS|LEGS
cold_protection = CHEST|GROIN|ARMS|LEGS
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm
index ea05b76da70..0a607c2f0bf 100644
--- a/code/modules/clothing/under/_under.dm
+++ b/code/modules/clothing/under/_under.dm
@@ -20,7 +20,6 @@
var/alt_covers_chest = FALSE // for adjusted/rolled-down jumpsuits, FALSE = exposes chest and arms, TRUE = exposes arms only
var/obj/item/clothing/accessory/attached_accessory
var/mutable_appearance/accessory_overlay
- var/mutantrace_variation = NO_MUTANTRACE_VARIATION //Are there special sprites for specific situations? Don't use this unless you need to.
var/freshly_laundered = FALSE
/obj/item/clothing/under/Initialize(mapload)
@@ -102,9 +101,9 @@
if(!alt_covers_chest)
body_parts_covered |= CHEST
- if(mutantrace_variation && ishuman(user))
+ if((supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION) && ishuman(user))
var/mob/living/carbon/human/H = user
- if(DIGITIGRADE in H.dna.species.species_traits)
+ if(H.dna.species.bodytype & BODYTYPE_DIGITIGRADE)
adjusted = DIGITIGRADE_STYLE
H.update_inv_w_uniform()
@@ -327,7 +326,7 @@
return adjusted
for(var/zone in list(BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) // ugly check to make sure we don't reenable protection on a disabled part
if(damage_by_parts[zone] > limb_integrity)
- for(var/part in zone2body_parts_covered(zone))
+ for(var/part in body_zone2cover_flags(zone))
body_parts_covered &= part
return adjusted
diff --git a/code/modules/clothing/under/color.dm b/code/modules/clothing/under/color.dm
index 5115a2154a7..9390422e4d1 100644
--- a/code/modules/clothing/under/color.dm
+++ b/code/modules/clothing/under/color.dm
@@ -19,7 +19,8 @@
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
icon_state = "jumpskirt"
- greyscale_config_worn_digi = null
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+ greyscale_config_worn_digi = null // SKYRAT EDIT ADDITION
/// Returns a random, acceptable jumpsuit typepath
/proc/get_random_jumpsuit()
diff --git a/code/modules/clothing/under/costume.dm b/code/modules/clothing/under/costume.dm
index 1b6d8beb0dc..6dbffe2be03 100644
--- a/code/modules/clothing/under/costume.dm
+++ b/code/modules/clothing/under/costume.dm
@@ -98,6 +98,7 @@
inhand_icon_state = "gladiator"
body_parts_covered = CHEST|GROIN|ARMS
female_sprite_flags = NO_FEMALE_UNIFORM
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
can_adjust = FALSE
resistance_flags = NONE
@@ -112,6 +113,7 @@
inhand_icon_state = "maid"
body_parts_covered = CHEST|GROIN
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
can_adjust = FALSE
/obj/item/clothing/under/costume/maid/Initialize(mapload)
diff --git a/code/modules/clothing/under/jobs/cargo.dm b/code/modules/clothing/under/jobs/cargo.dm
index d68f4b9e141..4c8d6b06f8e 100644
--- a/code/modules/clothing/under/jobs/cargo.dm
+++ b/code/modules/clothing/under/jobs/cargo.dm
@@ -16,6 +16,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/cargo/tech
name = "cargo technician's jumpsuit"
@@ -23,16 +24,17 @@
icon_state = "cargotech"
inhand_icon_state = "lb_suit"
body_parts_covered = CHEST|GROIN|ARMS
- mutantrace_variation = MUTANTRACE_VARIATION
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION
alt_covers_chest = TRUE
+
/obj/item/clothing/under/rank/cargo/tech/skirt
name = "cargo technician's jumpskirt"
desc = "Skiiiiirts! They're comfy and easy to wear!"
icon_state = "cargo_skirt"
inhand_icon_state = "lb_suit"
body_parts_covered = CHEST|GROIN|ARMS
- mutantrace_variation = NO_MUTANTRACE_VARIATION
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
diff --git a/code/modules/clothing/under/jobs/centcom.dm b/code/modules/clothing/under/jobs/centcom.dm
index 6501cda85b0..3148e185f19 100644
--- a/code/modules/clothing/under/jobs/centcom.dm
+++ b/code/modules/clothing/under/jobs/centcom.dm
@@ -34,6 +34,7 @@
alt_covers_chest = TRUE
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
body_parts_covered = CHEST|GROIN|ARMS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/centcom/officer_skirt/replica
name = "\improper CentCom turtleneck skirt replica"
@@ -46,6 +47,7 @@
inhand_icon_state = "dg_suit"
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
body_parts_covered = CHEST|GROIN|ARMS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/centcom/military
name = "tactical combat uniform"
diff --git a/code/modules/clothing/under/jobs/civilian/civilian.dm b/code/modules/clothing/under/jobs/civilian/civilian.dm
index 66d3a772eb9..044e9587f9b 100644
--- a/code/modules/clothing/under/jobs/civilian/civilian.dm
+++ b/code/modules/clothing/under/jobs/civilian/civilian.dm
@@ -25,6 +25,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/chaplain
desc = "It's a black jumpsuit, often worn by religious folk."
@@ -41,6 +42,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/chef
name = "cook's suit"
@@ -55,6 +57,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/head_of_personnel
desc = "It's a jumpsuit worn by someone who works in the position of \"Head of Personnel\"."
@@ -70,6 +73,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/head_of_personnel/suit
name = "head of personnel's suit"
@@ -86,6 +90,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/hydroponics
desc = "It's a jumpsuit designed to protect against minor plant-related hazards."
@@ -102,6 +107,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/janitor
desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards."
@@ -116,6 +122,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/janitor/maid
name = "maid uniform"
@@ -148,6 +155,7 @@
inhand_icon_state = "lawyer_black"
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/lawyer/beige
name = "good lawyer's suit"
@@ -164,6 +172,7 @@
worn_icon = 'icons/mob/clothing/under/suits.dmi'
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/lawyer/red
name = "lawyer red suit"
@@ -176,6 +185,7 @@
inhand_icon_state = "lawyer_red"
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/lawyer/blue
name = "lawyer blue suit"
@@ -188,6 +198,7 @@
inhand_icon_state = "lawyer_blue"
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/lawyer/bluesuit
name = "blue suit"
@@ -205,6 +216,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/lawyer/purpsuit
name = "purple suit"
@@ -221,6 +233,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/lawyer/galaxy
worn_icon = 'icons/mob/clothing/under/lawyer_galaxy.dmi'
diff --git a/code/modules/clothing/under/jobs/civilian/clown_mime.dm b/code/modules/clothing/under/jobs/civilian/clown_mime.dm
index c9a1d67dd86..bbc66075c1e 100644
--- a/code/modules/clothing/under/jobs/civilian/clown_mime.dm
+++ b/code/modules/clothing/under/jobs/civilian/clown_mime.dm
@@ -13,6 +13,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/mime/sexy
name = "sexy mime outfit"
diff --git a/code/modules/clothing/under/jobs/civilian/curator.dm b/code/modules/clothing/under/jobs/civilian/curator.dm
index 86a8683d56f..f9d822d6130 100644
--- a/code/modules/clothing/under/jobs/civilian/curator.dm
+++ b/code/modules/clothing/under/jobs/civilian/curator.dm
@@ -18,6 +18,7 @@
can_adjust = FALSE
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/civilian/curator/treasure_hunter
name = "treasure hunter uniform"
diff --git a/code/modules/clothing/under/jobs/command.dm b/code/modules/clothing/under/jobs/command.dm
index 4a399c2f14b..3969c980da3 100644
--- a/code/modules/clothing/under/jobs/command.dm
+++ b/code/modules/clothing/under/jobs/command.dm
@@ -33,6 +33,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/captain/parade
name = "captain's formal uniform"
diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm
index 3ae5668db3c..bd95efc8830 100644
--- a/code/modules/clothing/under/jobs/engineering.dm
+++ b/code/modules/clothing/under/jobs/engineering.dm
@@ -21,6 +21,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/engineering/atmospheric_technician
desc = "It's a jumpsuit worn by atmospheric technicians. Made from fire resistant materials."
@@ -36,6 +37,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/engineering/engineer
desc = "It's an orange high visibility jumpsuit worn by engineers. Made from fire resistant materials."
@@ -59,3 +61,4 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
diff --git a/code/modules/clothing/under/jobs/medical.dm b/code/modules/clothing/under/jobs/medical.dm
index cbd86a4fb51..3b2a6bf682d 100644
--- a/code/modules/clothing/under/jobs/medical.dm
+++ b/code/modules/clothing/under/jobs/medical.dm
@@ -18,6 +18,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/medical/chief_medical_officer
desc = "It's a jumpsuit worn by those with the experience to be \"Chief Medical Officer\". It provides minor biological protection."
@@ -33,6 +34,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/medical/chief_medical_officer/turtleneck
name = "chief medical officer's turtleneck"
@@ -51,6 +53,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/medical/virologist
desc = "It's made of a special fiber that gives special protection against biohazards. It has a virologist rank stripe on it."
@@ -66,6 +69,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/medical/scrubs
name = "medical scrubs"
@@ -98,6 +102,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/medical/paramedic
desc = "It's made of a special fiber that provides minor protection against biohazards. It has a dark blue cross on the chest denoting that the wearer is a trained paramedic."
@@ -116,6 +121,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/medical/doctor/nurse
desc = "It's a jumpsuit commonly worn by nursing staff in the medical department."
diff --git a/code/modules/clothing/under/jobs/rnd.dm b/code/modules/clothing/under/jobs/rnd.dm
index ed1a2d3ae78..1d657056b76 100644
--- a/code/modules/clothing/under/jobs/rnd.dm
+++ b/code/modules/clothing/under/jobs/rnd.dm
@@ -23,6 +23,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/rnd/research_director/alt
desc = "Maybe you'll engineer your own half-man, half-pig creature some day. Its fabric provides minor protection from biological contaminants."
@@ -40,6 +41,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/rnd/research_director/turtleneck
desc = "A dark purple turtleneck and tan khakis, for a director with a superior sense of style."
@@ -57,6 +59,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/rnd/scientist
desc = "It's made of a special fiber that provides minor protection against explosives. It has markings that denote the wearer as a scientist."
@@ -73,6 +76,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/rnd/roboticist
desc = "It's a slimming black with reinforced seams; great for industrial work."
@@ -89,6 +93,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/rnd/geneticist
desc = "It's made of a special fiber that gives special protection against biohazards. It has a genetics rank stripe on it."
@@ -106,3 +111,4 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
diff --git a/code/modules/clothing/under/jobs/security.dm b/code/modules/clothing/under/jobs/security.dm
index e500fd2f91c..12b4e40f18d 100644
--- a/code/modules/clothing/under/jobs/security.dm
+++ b/code/modules/clothing/under/jobs/security.dm
@@ -37,6 +37,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/security/officer/blueshirt
name = "blue shirt and tie"
@@ -81,6 +82,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/security/warden/formal
desc = "The insignia on this uniform tells you that this uniform belongs to the Warden."
@@ -108,6 +110,7 @@
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
alt_covers_chest = TRUE
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/security/detective/noir
name = "noir suit"
@@ -125,6 +128,7 @@
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
alt_covers_chest = TRUE
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/*
* Head of Security
@@ -145,6 +149,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/security/head_of_security/grey
name = "head of security's grey jumpsuit"
@@ -168,6 +173,7 @@
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
alt_covers_chest = TRUE
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/security/head_of_security/parade
name = "head of security's parade uniform"
@@ -230,6 +236,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/rank/security/officer/beatcop
name = "space police uniform"
diff --git a/code/modules/clothing/under/shorts.dm b/code/modules/clothing/under/shorts.dm
index d523b63b014..6c409b98ca1 100644
--- a/code/modules/clothing/under/shorts.dm
+++ b/code/modules/clothing/under/shorts.dm
@@ -4,7 +4,7 @@
gender = PLURAL
body_parts_covered = GROIN
female_sprite_flags = NO_FEMALE_UNIFORM
- mutantrace_variation = MUTANTRACE_VARIATION
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION
can_adjust = FALSE
icon = 'icons/obj/clothing/under/shorts_pants.dmi'
worn_icon = 'icons/mob/clothing/under/shorts_pants.dmi'
diff --git a/code/modules/clothing/under/skirt_dress.dm b/code/modules/clothing/under/skirt_dress.dm
index f3a7521b804..e5b964ca2f7 100644
--- a/code/modules/clothing/under/skirt_dress.dm
+++ b/code/modules/clothing/under/skirt_dress.dm
@@ -2,6 +2,7 @@
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
can_adjust = FALSE
body_parts_covered = CHEST|GROIN
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
icon = 'icons/obj/clothing/under/dress.dmi'
worn_icon = 'icons/mob/clothing/under/dress.dmi'
diff --git a/code/modules/clothing/under/suits.dm b/code/modules/clothing/under/suits.dm
index a9cbc662580..f148cc16683 100644
--- a/code/modules/clothing/under/suits.dm
+++ b/code/modules/clothing/under/suits.dm
@@ -18,6 +18,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY|FEMALE_UNIFORM_NO_BREASTS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/suit/sl
desc = "It's a very amish looking suit."
@@ -53,6 +54,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY|FEMALE_UNIFORM_NO_BREASTS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/suit/black_really
name = "executive suit"
@@ -68,6 +70,7 @@
body_parts_covered = CHEST|GROIN|ARMS
dying_key = DYE_REGISTRY_JUMPSKIRT
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY|FEMALE_UNIFORM_NO_BREASTS
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/suit/green
name = "green suit"
diff --git a/code/modules/clothing/under/syndicate.dm b/code/modules/clothing/under/syndicate.dm
index 7b1a73a6ae6..6203b5f834c 100644
--- a/code/modules/clothing/under/syndicate.dm
+++ b/code/modules/clothing/under/syndicate.dm
@@ -19,6 +19,7 @@
alt_covers_chest = TRUE
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
dying_key = DYE_REGISTRY_JUMPSKIRT
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/syndicate/bloodred
name = "blood-red sneaksuit"
@@ -51,6 +52,7 @@
armor = list(MELEE = 0, BULLET = 0, LASER = 0,ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 50, ACID = 40)
female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY
dying_key = DYE_REGISTRY_JUMPSKIRT
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
/obj/item/clothing/under/syndicate/sniper
name = "tactical turtleneck suit"
diff --git a/code/modules/games/wizoff.dm b/code/modules/games/wizoff.dm
index 05044ea392d..73be649593a 100644
--- a/code/modules/games/wizoff.dm
+++ b/code/modules/games/wizoff.dm
@@ -13,13 +13,14 @@
cards += generate_card("[card]")
/obj/item/toy/cards/deck/wizoff/examine_more(mob/user)
- var/list/msg = list(span_notice("Remember the rules of Wiz-Off!"))
- msg += "\t[span_info("Each player draws 5 cards.")]"
- msg += "\t[span_info("There are five rounds. Each round, a player selects a card to play, and the winner is selected based on the following rules:")]"
- msg += "\t[span_info("Defensive beats Offensive!")]"
- msg += "\t[span_info("Offensive beats Utility!")]"
- msg += "\t[span_info("Utility beats Defensive!")]"
- msg += "\t[span_info("If both players play the same type of spell, the higher number wins!")]"
- msg += "\t[span_info("The player who wins the most of the 5 rounds wins the game!")]"
- msg += "\t[span_notice("Now get ready to battle for the fate of the universe: Wiz-Off!")]"
- return msg
+ . = ..()
+ . += span_notice("Remember the rules of Wiz-Off!")
+ . += "\t[span_info("Each player draws 5 cards.")]"
+ . += "\t[span_info("There are five rounds. Each round, a player selects a card to play, and the winner is selected based on the following rules:")]"
+ . += "\t[span_info("Defensive beats Offensive!")]"
+ . += "\t[span_info("Offensive beats Utility!")]"
+ . += "\t[span_info("Utility beats Defensive!")]"
+ . += "\t[span_info("If both players play the same type of spell, the higher number wins!")]"
+ . += "\t[span_info("The player who wins the most of the 5 rounds wins the game!")]"
+ . += "\t[span_notice("Now get ready to battle for the fate of the universe: Wiz-Off!")]"
+ return .
diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm
index f51eb02977f..957e39b6140 100644
--- a/code/modules/jobs/job_types/_job.dm
+++ b/code/modules/jobs/job_types/_job.dm
@@ -455,7 +455,7 @@
if(require_human)
player_client.prefs.randomise["species"] = FALSE
player_client.prefs.safe_transfer_prefs_to(src, TRUE, is_antag)
- if (require_human && !ishumanbasic(src))
+ if(require_human && !ishumanbasic(src))
set_species(/datum/species/human)
dna.species.roundstart_changed = TRUE
apply_pref_name(/datum/preference/name/backup_human, player_client)
diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm
index e7a553a830c..4b0aa909926 100644
--- a/code/modules/mob/living/carbon/alien/special/facehugger.dm
+++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm
@@ -205,7 +205,7 @@
worn_icon_state = "[base_icon_state]_impregnated"
var/obj/item/bodypart/chest/LC = target.get_bodypart(BODY_ZONE_CHEST)
- if((!LC || LC.status != BODYPART_ROBOTIC) && !target.getorgan(/obj/item/organ/body_egg/alien_embryo))
+ if((!LC || IS_ORGANIC_LIMB(LC)) && !target.getorgan(/obj/item/organ/body_egg/alien_embryo))
new /obj/item/organ/body_egg/alien_embryo(target)
var/turf/T = get_turf(target)
log_game("[key_name(target)] was impregnated by a facehugger at [loc_name(T)]")
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index a5b50415158..9aff312e48c 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -1,7 +1,6 @@
/mob/living/carbon/Initialize(mapload)
. = ..()
create_reagents(1000, REAGENT_HOLDER_ALIVE)
- assign_bodypart_ownership()
update_body_parts() //to update the carbon's new bodyparts appearance
register_context()
@@ -356,7 +355,7 @@
return FALSE
visible_message(span_danger("[src] manages to [cuff_break ? "break" : "remove"] [I]!"))
to_chat(src, span_notice("You successfully [cuff_break ? "break" : "remove"] [I]."))
-
+
if(cuff_break)
. = !((I == handcuffed) || (I == legcuffed))
qdel(I)
@@ -1013,6 +1012,7 @@
///Proc to hook behavior on bodypart additions.
/mob/living/carbon/proc/add_bodypart(obj/item/bodypart/new_bodypart)
bodyparts += new_bodypart
+ new_bodypart.owner = src
switch(new_bodypart.body_part)
if(LEG_LEFT, LEG_RIGHT)
@@ -1028,7 +1028,6 @@
///Proc to hook behavior on bodypart removals.
/mob/living/carbon/proc/remove_bodypart(obj/item/bodypart/old_bodypart)
bodyparts -= old_bodypart
-
switch(old_bodypart.body_part)
if(LEG_LEFT, LEG_RIGHT)
set_num_legs(num_legs - 1)
@@ -1062,43 +1061,52 @@
if(href_list[VV_HK_MODIFY_BODYPART])
if(!check_rights(R_SPAWN))
return
- var/edit_action = input(usr, "What would you like to do?","Modify Body Part") as null|anything in list("add","remove", "augment")
+ var/edit_action = input(usr, "What would you like to do?","Modify Body Part") as null|anything in list("replace","remove")
if(!edit_action)
return
var/list/limb_list = list()
- if(edit_action == "remove" || edit_action == "augment")
- for(var/obj/item/bodypart/B in bodyparts)
+ if(edit_action == "remove")
+ for(var/obj/item/bodypart/B as anything in bodyparts)
limb_list += B.body_zone
- if(edit_action == "remove")
limb_list -= BODY_ZONE_CHEST
else
- limb_list = list(BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
- for(var/obj/item/bodypart/B in bodyparts)
- limb_list -= B.body_zone
- var/result = input(usr, "Please choose which body part to [edit_action]","[capitalize(edit_action)] Body Part") as null|anything in sort_list(limb_list)
+ limb_list = list(BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG, BODY_ZONE_CHEST)
+ var/result = input(usr, "Please choose which bodypart to [edit_action]","[capitalize(edit_action)] Bodypart") as null|anything in sort_list(limb_list)
if(result)
var/obj/item/bodypart/BP = get_bodypart(result)
+ var/list/limbtypes = list()
+ switch(result)
+ if(BODY_ZONE_CHEST)
+ limbtypes = typesof(/obj/item/bodypart/chest)
+ if(BODY_ZONE_R_ARM)
+ limbtypes = typesof(/obj/item/bodypart/r_arm)
+ if(BODY_ZONE_L_ARM)
+ limbtypes = typesof(/obj/item/bodypart/l_arm)
+ if(BODY_ZONE_HEAD)
+ limbtypes = typesof(/obj/item/bodypart/head)
+ if(BODY_ZONE_L_LEG)
+ limbtypes = typesof(/obj/item/bodypart/l_leg)
+ if(BODY_ZONE_R_LEG)
+ limbtypes = typesof(/obj/item/bodypart/r_leg)
switch(edit_action)
if("remove")
if(BP)
- BP.drop_limb()
+ BP.drop_limb(special = TRUE)
+ admin_ticket_log("[key_name_admin(usr)] has removed [src]'s [parse_zone(BP.body_zone)]")
else
to_chat(usr, span_boldwarning("[src] doesn't have such bodypart."))
- if("add")
- if(BP)
- to_chat(usr, span_boldwarning("[src] already has such bodypart."))
+ admin_ticket_log("[key_name_admin(usr)] has attempted to modify the bodyparts of [src]")
+ if("replace")
+ var/limb2add = input(usr, "Select a bodypart type to add", "Add/Replace Bodypart") as null|anything in sort_list(limbtypes)
+ var/obj/item/bodypart/new_bp = new limb2add()
+
+ if(new_bp.replace_limb(src, special = TRUE))
+ admin_ticket_log("key_name_admin(usr)] has replaced [src]'s [BP.type] with [new_bp.type]")
+ qdel(BP)
else
- if(!regenerate_limb(result))
- to_chat(usr, span_boldwarning("[src] cannot have such bodypart."))
- if("augment")
- if(ishuman(src))
- if(BP)
- BP.change_bodypart_status(BODYPART_ROBOTIC, TRUE, TRUE)
- else
- to_chat(usr, span_boldwarning("[src] doesn't have such bodypart."))
- else
- to_chat(usr, span_boldwarning("Only humans can be augmented."))
- admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [src]")
+ to_chat(usr, "Failed to replace bodypart! They might be incompatible.")
+ admin_ticket_log("[key_name_admin(usr)] has attempted to modify the bodyparts of [src]")
+
if(href_list[VV_HK_MAKE_AI])
if(!check_rights(R_SPAWN))
return
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index dbb2a4415fd..743c83c340c 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -84,11 +84,11 @@
if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest)
affecting = bodyparts[1]
SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)
- send_item_attack_message(I, user, affecting.name, affecting)
+ send_item_attack_message(I, user, parse_zone(affecting.body_zone), affecting)
if(I.force)
var/attack_direction = get_dir(user, src)
apply_damage(I.force, I.damtype, affecting, wound_bonus = I.wound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness(), attack_direction = attack_direction)
- if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC)
+ if(I.damtype == BRUTE && IS_ORGANIC_LIMB(affecting))
if(prob(33))
I.add_mob_blood(src)
var/turf/location = get_turf(src)
@@ -721,7 +721,7 @@
. = health
for (var/_limb in bodyparts)
var/obj/item/bodypart/limb = _limb
- if (limb.status != BODYPART_ORGANIC)
+ if (!IS_ORGANIC_LIMB(limb))
. += (limb.brute_dam * limb.body_damage_coeff) + (limb.burn_dam * limb.body_damage_coeff)
/mob/living/carbon/grabbedby(mob/living/carbon/user, supress_message = FALSE)
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index e644bdd7171..d9348f670bd 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -74,7 +74,8 @@
/// A collection of arms (or actually whatever the fug /bodyparts you monsters use to wreck my systems)
var/list/hand_bodyparts = list()
- var/icon_render_key = ""
+ ///A cache of bodypart = icon to prevent excessive icon creation.
+ var/list/icon_render_keys = list()
var/static/list/limb_icon_cache = list()
//halucination vars
diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm
index b0a60b82147..eb6d8405298 100644
--- a/code/modules/mob/living/carbon/carbon_update_icons.dm
+++ b/code/modules/mob/living/carbon/carbon_update_icons.dm
@@ -40,10 +40,12 @@
/mob/living/carbon/regenerate_icons()
if(notransform)
return 1
+ icon_render_keys = list() //Clear this bad larry out
update_inv_hands()
update_inv_handcuffed()
update_inv_legcuffed()
update_fire()
+ update_body_parts()
/mob/living/carbon/update_inv_hands()
@@ -240,92 +242,115 @@
. += emissive_blocker(standing.icon, standing.icon_state, alpha = standing.alpha)
-/mob/living/carbon/update_body()
- update_body_parts()
+/mob/living/carbon/update_body(is_creating)
+ update_body_parts(is_creating)
-/mob/living/carbon/proc/assign_bodypart_ownership()
- for(var/X in bodyparts)
- var/obj/item/bodypart/BP = X
- BP.original_owner = WEAKREF(src)
+///Checks to see if any bodyparts need to be redrawn, then does so. update_limb_data = TRUE redraws the limbs to conform to the owner.
+/mob/living/carbon/proc/update_body_parts(update_limb_data)
+ update_damage_overlays()
+ update_wound_overlays()
+ var/list/needs_update = list()
+ var/limb_count_update = FALSE
+ for(var/obj/item/bodypart/limb as anything in bodyparts)
+ limb.update_limb(is_creating = update_limb_data) //Update limb actually doesn't do much, get_limb_icon is the cpu eater.
+ var/old_key = icon_render_keys?[limb.body_zone] //Checks the mob's icon render key list for the bodypart
+ icon_render_keys[limb.body_zone] = (limb.is_husked) ? limb.generate_husk_key().Join() : limb.generate_icon_key().Join() //Generates a key for the current bodypart
+ if(!(icon_render_keys[limb.body_zone] == old_key)) //If the keys match, that means the limb doesn't need to be redrawn
+ needs_update += limb
-//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular)
-/*
-/mob/living/carbon/proc/update_body_parts()
- //CHECK FOR UPDATE
- var/oldkey = icon_render_key
- icon_render_key = generate_icon_render_key()
- if(oldkey == icon_render_key)
+
+ var/list/missing_bodyparts = get_missing_limbs()
+ if(((dna ? dna.species.max_bodypart_count : BODYPARTS_DEFAULT_MAXIMUM) - icon_render_keys.len) != missing_bodyparts.len) //Checks to see if the target gained or lost any limbs.
+ limb_count_update = TRUE
+ for(var/missing_limb in missing_bodyparts)
+ icon_render_keys -= missing_limb //Removes dismembered limbs from the key list
+
+ if(!needs_update.len && !limb_count_update)
return
remove_overlay(BODYPARTS_LAYER)
- for(var/X in bodyparts)
- var/obj/item/bodypart/BP = X
- BP.update_limb()
-
- //LOAD ICONS
- if(limb_icon_cache[icon_render_key])
- load_limb_from_cache()
- return
-
//GENERATE NEW LIMBS
var/list/new_limbs = list()
- for(var/X in bodyparts)
- var/obj/item/bodypart/BP = X
- new_limbs += BP.get_limb_icon()
+ for(var/obj/item/bodypart/limb as anything in bodyparts)
+ if(limb in needs_update) //Checks to see if the limb needs to be redrawn
+ var/bodypart_icon = limb.get_limb_icon()
+ new_limbs += bodypart_icon
+ limb_icon_cache[icon_render_keys[limb.body_zone]] = bodypart_icon //Caches the icon with the bodypart key, as it is new
+ else
+ new_limbs += limb_icon_cache[icon_render_keys[limb.body_zone]] //Pulls existing sprites from the cache
+
if(new_limbs.len)
overlays_standing[BODYPARTS_LAYER] = new_limbs
- limb_icon_cache[icon_render_key] = new_limbs
apply_overlay(BODYPARTS_LAYER)
- update_damage_overlays()
- update_wound_overlays()
-*/
-//SKYRAT EDIT REMOVAL END
+/////////////////////////
+// Limb Icon Cache 2.0 //
+/////////////////////////
+/**
+ * Called from update_body_parts() these procs handle the limb icon cache.
+ * the limb icon cache adds an icon_render_key to a human mob, it represents:
+ * - Gender, if applicable
+ * - The ID of the limb
+ * - Draw color, if applicable
+ * These procs only store limbs as to increase the number of matching icon_render_keys
+ * This cache exists because drawing 6/7 icons for humans constantly is quite a waste
+ * See RemieRichards on irc.rizon.net #coderbus (RIP remie :sob:)
+**/
+/obj/item/bodypart/proc/generate_icon_key()
+ RETURN_TYPE(/list)
+ . = list()
+ if(is_dimorphic)
+ . += "[limb_gender]-"
+ . += "[limb_id]"
+ . += "-[body_zone]"
+ if(should_draw_greyscale && draw_color)
+ . += "-[draw_color]"
+ for(var/obj/item/organ/external/external_organ as anything in external_organs)
+ if(!external_organ.can_draw_on_bodypart(owner))
+ continue
+ . += "-[external_organ.generate_icon_cache()]"
+ // SKYRAT EDIT ADDITION - CACHING MARKINGS
+ for(var/key in markings)
+ . += limb_id == "digitigrade" ? ("digitigrade_1_" + body_zone) : body_zone
+ . += "-[key]"
+ . += "-[markings[key][1]]"
+ // SKYRAT EDIT END
-/////////////////////
-// Limb Icon Cache //
-/////////////////////
-/*
- Called from update_body_parts() these procs handle the limb icon cache.
- the limb icon cache adds an icon_render_key to a human mob, it represents:
- - skin_tone (if applicable)
- - gender
- - limbs (stores as the limb name and whether it is removed/fine, organic/robotic)
- These procs only store limbs as to increase the number of matching icon_render_keys
- This cache exists because drawing 6/7 icons for humans constantly is quite a waste
- See RemieRichards on irc.rizon.net #coderbus (RIP remie :sob:)
-*/
+ return .
-//produces a key based on the mob's limbs
+///Generates a cache key specifically for husks
+/obj/item/bodypart/proc/generate_husk_key()
+ RETURN_TYPE(/list)
+ . = list()
+ . += "[husk_type]"
+ . += "-husk"
+ . += "-[body_zone]"
+ return .
-//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular)
-/*
-/mob/living/carbon/proc/generate_icon_render_key()
- for(var/X in bodyparts)
- var/obj/item/bodypart/BP = X
- . += "-[BP.body_zone]"
- if(BP.use_digitigrade)
- . += "-digitigrade[BP.use_digitigrade]"
- if(BP.animal_origin)
- . += "-[BP.animal_origin]"
- if(BP.status == BODYPART_ORGANIC)
- . += "-organic"
- else
- . += "-robotic"
+/obj/item/bodypart/head/generate_icon_key()
+ . = ..()
+ . += "-[facial_hairstyle]"
+ . += "-[facial_hair_color]"
+ if(facial_hair_gradient_style)
+ . += "-[facial_hair_gradient_style]"
+ if(hair_gradient_color)
+ . += "-[facial_hair_gradient_color]"
+ if(facial_hair_hidden)
+ . += "-FACIAL_HAIR_HIDDEN"
+ if(show_debrained)
+ . += "-SHOW_DEBRAINED"
+ return .
- if(HAS_TRAIT(src, TRAIT_HUSK))
- . += "-husk"
-*/
-//SKYRAT EDIT REMOVAL END
+ . += "-[hair_style]"
+ . += "-[fixed_hair_color || override_hair_color || hair_color]"
+ if(hair_gradient_style)
+ . += "-[hair_gradient_style]"
+ if(hair_gradient_color)
+ . += "-[hair_gradient_color]"
+ if(hair_hidden)
+ . += "-HAIR_HIDDEN"
-
-//change the mob's icon to the one matching its key
-/mob/living/carbon/proc/load_limb_from_cache()
- if(limb_icon_cache[icon_render_key])
- remove_overlay(BODYPARTS_LAYER)
- overlays_standing[BODYPARTS_LAYER] = limb_icon_cache[icon_render_key]
- apply_overlay(BODYPARTS_LAYER)
- update_damage_overlays()
+ return .
diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm
index 65d410c314c..bac5a8dcc38 100644
--- a/code/modules/mob/living/carbon/damage_procs.dm
+++ b/code/modules/mob/living/carbon/damage_procs.dm
@@ -68,7 +68,7 @@
if(amount > 0)
take_overall_damage(amount, 0, 0, updating_health, required_status)
else
- heal_overall_damage(abs(amount), 0, 0, required_status ? required_status : BODYPART_ORGANIC, updating_health)
+ heal_overall_damage(abs(amount), 0, 0, required_status ? required_status : BODYTYPE_ORGANIC, updating_health)
return amount
/mob/living/carbon/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, required_status)
@@ -77,7 +77,7 @@
if(amount > 0)
take_overall_damage(0, amount, 0, updating_health, required_status)
else
- heal_overall_damage(0, abs(amount), 0, required_status ? required_status : BODYPART_ORGANIC, updating_health)
+ heal_overall_damage(0, abs(amount), 0, required_status ? required_status : BODYTYPE_ORGANIC, updating_health)
return amount
/mob/living/carbon/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE)
@@ -159,7 +159,7 @@
var/list/obj/item/bodypart/parts = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
- if(status && (BP.status != status))
+ if(status && !(BP.bodytype & status))
continue
if((brute && BP.brute_dam) || (burn && BP.burn_dam) || (stamina && BP.stamina_dam))
parts += BP
@@ -170,7 +170,7 @@
var/list/obj/item/bodypart/parts = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
- if(status && (BP.status != status))
+ if(status && !(BP.bodytype & status))
continue
if(BP.brute_dam + BP.burn_dam < BP.max_damage)
parts += BP
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index 4a82310b5d0..f25b08cd523 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -157,8 +157,16 @@
//SKYRAT EDIT REMOVAL - MOVED - MEDICAL
/*
/mob/living/carbon/examine_more(mob/user)
- if(!all_scars)
- return ..()
+ . = ..()
+ . += span_notice("You examine [src] closer, and note the following...")
+
+ //On closer inspection, this man isnt a man at all!
+ var/list/covered_zones = get_covered_body_zones()
+ for(var/obj/item/bodypart/part as anything in bodyparts)
+ if(part.body_zone in covered_zones)
+ continue
+ if(part.limb_id != (dna.species.examine_limb_id ? dna.species.examine_limb_id : dna.species.id))
+ . += "[span_info("[p_they(TRUE)] [p_have()] \an [part.name].")]"
var/list/visible_scars
for(var/i in all_scars)
@@ -166,15 +174,11 @@
if(S.is_visible(user))
LAZYADD(visible_scars, S)
- if(!visible_scars)
- return ..()
-
- var/msg = list(span_notice("You examine [src] closer, and note the following..."))
for(var/i in visible_scars)
var/datum/scar/S = i
var/scar_text = S.get_examine_description(user)
if(scar_text)
- msg += "[scar_text]"
+ . += "[scar_text]"
- return msg
+ return .
*/
diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm
index c76db5b88c5..d7d780537e2 100644
--- a/code/modules/mob/living/carbon/human/dummy.dm
+++ b/code/modules/mob/living/carbon/human/dummy.dm
@@ -46,7 +46,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
//Instead of just deleting our equipment, we save what we can and reinsert it into SSwardrobe's store
//Hopefully this makes preference reloading not the worst thing ever
/mob/living/carbon/human/dummy/delete_equipment()
- var/list/items_to_check = get_all_slots() + held_items
+ var/list/items_to_check = get_all_worn_items() + held_items
var/list/to_nuke = list() //List of items queued for deletion, can't qdel them before iterating their contents in case they hold something
///Travel to the bottom of the contents chain, expanding it out
for(var/i = 1; i <= length(items_to_check); i++) //Needs to be a c style loop since it can expand
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index f775ca22f26..8c959acabea 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -9,14 +9,15 @@
var/t_es = p_es()
var/obscure_name
+ var/obscured = check_obscured_slots()
+ var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
+
if(isliving(user))
var/mob/living/L = user
if(HAS_TRAIT(L, TRAIT_PROSOPAGNOSIA) || HAS_TRAIT(L, TRAIT_INVISIBLE_MAN))
obscure_name = TRUE
//SKYRAT EDIT CHANGE BEGIN - CUSTOMIZATION
- var/obscured = check_obscured_slots()
- var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
var/species_visible
var/species_name_string
if(skipface || get_visible_name() == "Unknown")
@@ -38,6 +39,13 @@
else
. += "You can't make out what species they are."
//SKYRAT EDIT CHANGE END
+
+ /* SKYRAT EDIT REMOVAL
+ var/apparent_species
+ if(dna?.species && !skipface)
+ apparent_species = ", \an [dna.species.name]"
+ . = list("*---------*\nThis is [!obscure_name ? name : "Unknown"][apparent_species]!")
+ */
//uniform
if(w_uniform && !(obscured & ITEM_SLOT_ICLOTHING) && !(w_uniform.item_flags & EXAMINE_SKIP))
//accessory
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 7a422477de0..ad4c8ea2f70 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -8,6 +8,7 @@
create_bodyparts()
setup_human_dna()
+ prepare_huds() //Prevents a nasty runtime on human init
if(dna.species)
INVOKE_ASYNC(src, .proc/set_species, dna.species.type)
@@ -509,8 +510,7 @@
facial_hairstyle = "Shaved"
hairstyle = pick("Bedhead", "Bedhead 2", "Bedhead 3")
underwear = "Nude"
- update_body()
- update_hair()
+ update_body(is_creating = TRUE)
/mob/living/carbon/human/singularity_pull(S, current_size)
..()
@@ -1193,12 +1193,6 @@
/mob/living/carbon/human/species/snail
race = /datum/species/snail
-/mob/living/carbon/human/species/synth
- race = /datum/species/synth
-
-/mob/living/carbon/human/species/synth/military
- race = /datum/species/synth/military
-
/mob/living/carbon/human/species/vampire
race = /datum/species/vampire
@@ -1207,6 +1201,3 @@
/mob/living/carbon/human/species/zombie/infectious
race = /datum/species/zombie/infectious
-
-/mob/living/carbon/human/species/zombie/krokodil_addict
- race = /datum/species/krokodil_addict
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 8a3f30723f5..4c5f8c7f946 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -478,7 +478,7 @@
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(prob(probability) && !prob(getarmor(BP, BOMB)) && BP.body_zone != BODY_ZONE_HEAD && BP.body_zone != BODY_ZONE_CHEST)
- BP.brute_dam = BP.max_damage
+ BP.receive_damage(INFINITY, wound_bonus = CANT_WOUND) //Capped by proc
BP.dismember()
max_limb_loss--
if(!max_limb_loss)
@@ -539,8 +539,8 @@
if(. & EMP_PROTECT_CONTENTS)
return
var/informed = FALSE
- for(var/obj/item/bodypart/L in src.bodyparts)
- if(L.status == BODYPART_ROBOTIC)
+ for(var/obj/item/bodypart/L as anything in src.bodyparts)
+ if(!IS_ORGANIC_LIMB(L))
if(!informed)
to_chat(src, span_userdanger("You feel a sharp pain as your robotic limbs overload."))
informed = TRUE
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 6e0b006aa89..0ecd0665627 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -75,7 +75,7 @@
var/hardcore_survival_score = 0
/// Which body type to use
- var/body_type = MALE
+ var/physique = MALE
/// How many "units of blood" we have on our hands
var/blood_in_hands = 0
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 d399ef9d097..3d26510d85c 100644
--- a/code/modules/mob/living/carbon/human/human_update_icons.dm
+++ b/code/modules/mob/living/carbon/human/human_update_icons.dm
@@ -1,3 +1,5 @@
+#define RESOLVE_ICON_STATE(worn_item) (worn_item.worn_icon_state || worn_item.icon_state)
+
///////////////////////
//UPDATE_ICONS SYSTEM//
///////////////////////
@@ -6,7 +8,7 @@ This system allows you to update individual mob-overlays, without regenerating t
When we generate overlays we generate the standing version and then rotate the mob as necessary..
As of the time of writing there are 20 layers within this list. Please try to keep this from increasing. //22 and counting, good job guys
- var/overlays_standing[20] //For the standing stance
+ var/overlays_standing[20] //For the standing stance
Most of the time we only wish to update one overlay:
e.g. - we dropped the fireaxe out of our left hand and need to remove its icon from our mob
@@ -28,7 +30,7 @@ Note: The defines for layer numbers is now kept exclusvely in __DEFINES/misc.dm
All of this means that this code is more maintainable, faster and still fairly easy to use.
There are several things that need to be remembered:
-> Whenever we do something that should cause an overlay to update (which doesn't use standard procs
+> Whenever we do something that should cause an overlay to update (which doesn't use standard procs
( i.e. you do something like l_hand = /obj/item/something new(src), rather than using the helper procs)
You will need to call the relevant update_inv_* proc
@@ -37,36 +39,37 @@ There are several things that need to be remembered:
slime etc. Instead, it'll just return without doing any work. So no harm in calling it for slimes and such.
-> There are also these special cases:
- update_damage_overlays() //handles damage overlays for brute/burn damage
- update_body() //Handles updating your mob's body layer and mutant bodyparts
+> There are also these special cases:
+ update_damage_overlays() //handles damage overlays for brute/burn damage
+ update_body() //Handles updating your mob's body layer and mutant bodyparts
as well as sprite-accessories that didn't really fit elsewhere (underwear, undershirts, socks, lips, eyes)
//NOTE: update_mutantrace() is now merged into this!
- update_hair() //Handles updating your hair overlay (used to be update_face, but mouth and
+ update_hair() //Handles updating your hair overlay (used to be update_face, but mouth and
eyes were merged into update_body())
*/
//HAIR OVERLAY
-/mob/living/carbon/human/update_hair()
- dna.species.handle_hair(src)
+/mob/living/carbon/human/update_hair(is_creating)
+ var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD)
+ if(!my_head)
+ return
+ my_head.update_limb(FALSE, is_creating)
+ update_body_parts()
+
-// SKYRAT EDIT REMOVAL - FIXING CUSTOMIZATION(?) (moved to modular)
-/*
//used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body.
-/mob/living/carbon/human/proc/update_mutant_bodyparts()
- dna.species.handle_mutant_bodyparts(src)
-*/
-//SKYRAT EDIT REMOVAL END
+/mob/living/carbon/human/proc/update_mutant_bodyparts(force_update = FALSE) // SKYRAT EDIT CHANGE
+ dna.species.handle_mutant_bodyparts(src, force_update = force_update) // SKYRAT EDIT CHANGE
+ update_body_parts()
-
-/mob/living/carbon/human/update_body()
+/mob/living/carbon/human/update_body(is_creating = FALSE)
dna.species.handle_body(src)
..()
/mob/living/carbon/human/update_fire()
- ..((fire_stacks > HUMAN_FIRE_STACK_ICON_NUM) ? dna.species.fire_overlay : "Generic_mob_burning")
+ ..((fire_stacks > HUMAN_FIRE_STACK_ICON_NUM) ? "Standing" : "Generic_mob_burning")
/* --------------------------------------- */
@@ -74,7 +77,6 @@ There are several things that need to be remembered:
/mob/living/carbon/human/regenerate_icons()
if(!..())
- icon_render_key = null //invalidate bodyparts cache
update_body()
update_hair()
update_inv_w_uniform()
@@ -100,22 +102,16 @@ There are several things that need to be remembered:
/* --------------------------------------- */
//vvvvvv UPDATE_INV PROCS vvvvvv
-//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular)
-/*
/mob/living/carbon/human/update_inv_w_uniform()
remove_overlay(UNIFORM_LAYER)
if(client && hud_used)
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_ICLOTHING) + 1]
- inv.update_appearance()
+ inv.update_icon()
if(istype(w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = w_uniform
- U.screen_loc = ui_iclothing
- if(client && hud_used?.hud_shown)
- if(hud_used.inventory_shown)
- client.screen += w_uniform
- update_observer_view(w_uniform,1)
+ update_hud_uniform(U)
if(wear_suit && (wear_suit.flags_inv & HIDEJUMPSUIT))
return
@@ -124,106 +120,126 @@ There are several things that need to be remembered:
var/target_overlay = U.icon_state
if(U.adjusted == ALT_STYLE)
target_overlay = "[target_overlay]_d"
- else if(U.adjusted == DIGITIGRADE_STYLE)
- target_overlay = "[target_overlay]_l"
-
var/mutable_appearance/uniform_overlay
- if(dna?.species.sexes)
- if(body_type == FEMALE && U.female_sprite_flags != NO_FEMALE_UNIFORM)
- uniform_overlay = U.build_worn_icon(default_layer = UNIFORM_LAYER, default_icon_file = 'icons/mob/clothing/under/default.dmi', isinhands = FALSE, femaleuniform = U.female_sprite_flags, override_state = target_overlay)
-
+ //Change check_adjustable_clothing.dm if you change this
+ var/handled_by_bodytype = TRUE
+ var/icon_file
+ var/woman
if(!uniform_overlay)
- uniform_overlay = U.build_worn_icon(default_layer = UNIFORM_LAYER, default_icon_file = 'icons/mob/clothing/under/default.dmi', isinhands = FALSE, override_state = target_overlay)
+ //BEGIN SPECIES HANDLING
+ if((dna?.species.bodytype & BODYTYPE_DIGITIGRADE) && (U.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION))
+ icon_file = U.worn_icon_digi || DIGITIGRADE_UNIFORM_FILE // SKYRAT EDIT CHANGE
- if(OFFSET_UNIFORM in dna.species.offset_features)
- uniform_overlay.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1]
- uniform_overlay.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2]
+ // SKYRAT EDIT ADDITION
+ else if(dna.species.bodytype & BODYTYPE_TESHARI)
+ icon_file = TESHARI_UNIFORM_ICON
+ // SKYRAT EDIT END
+
+ //Female sprites have lower priority than digitigrade sprites
+ else if(dna.species.sexes && (dna.species.bodytype & BODYTYPE_HUMANOID) && physique == FEMALE && U.adjusted != NO_FEMALE_UNIFORM) //Agggggggghhhhh
+ woman = TRUE
+
+ if(!icon_exists(icon_file, RESOLVE_ICON_STATE(U)))
+ icon_file = DEFAULT_UNIFORM_FILE
+ handled_by_bodytype = FALSE
+ //END SPECIES HANDLING
+ uniform_overlay = U.build_worn_icon(
+ default_layer = UNIFORM_LAYER,
+ default_icon_file = icon_file,
+ isinhands = FALSE,
+ femaleuniform = woman ? U.adjusted : null,
+ override_state = target_overlay,
+ override_file = handled_by_bodytype ? icon_file : null
+ )
+
+ if(OFFSET_UNIFORM in dna.species.offset_features && !handled_by_bodytype)
+ uniform_overlay?.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1]
+ uniform_overlay?.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2]
overlays_standing[UNIFORM_LAYER] = uniform_overlay
+ apply_overlay(UNIFORM_LAYER)
- apply_overlay(UNIFORM_LAYER)
update_mutant_bodyparts()
-*/
-//SKYRAT EDIT REMOVAL END
-
/mob/living/carbon/human/update_inv_wear_id()
remove_overlay(ID_LAYER)
- //remove_overlay(ID_CARD_LAYER) //SKYRAT EDIT REMOVAL - Ugly ID
if(client && hud_used)
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_ID) + 1]
- inv.update_appearance()
+ inv.update_icon()
- //var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER] //SKYRAT EDIT REMOVAL - Ugly ID
+ var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER]
if(wear_id)
- wear_id.screen_loc = ui_id
- if(client && hud_used?.hud_shown)
- client.screen += wear_id
- update_observer_view(wear_id)
+ var/obj/item/worn_item = wear_id
+ update_hud_id(worn_item)
+ var/handled_by_bodytype
+ var/icon_file
- //SKYRAT EDIT REMOVAL BEGIN - Ugly ID
- /*
- //TODO: add an icon file for ID slot stuff, so it's less snowflakey
- id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = 'icons/mob/clothing/id.dmi')
- if(OFFSET_ID in dna.species.offset_features)
+ if(!icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item)))
+ icon_file = 'icons/mob/mob.dmi'
+ handled_by_bodytype = FALSE
+
+ 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 && !handled_by_bodytype)
id_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1]
id_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2]
overlays_standing[ID_LAYER] = id_overlay
- var/obj/item/card/id/shown_id = wear_id.GetID()
- if(shown_id)
- var/mutable_appearance/id_card_overlay = overlays_standing[ID_CARD_LAYER]
- id_card_overlay = shown_id.build_worn_icon(default_layer = ID_CARD_LAYER, default_icon_file = 'icons/mob/clothing/id_card.dmi')
- if(OFFSET_ID in dna.species.offset_features)
- id_card_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1]
- id_card_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2]
-
- overlays_standing[ID_CARD_LAYER] = id_card_overlay
- */
- //SKYRAT EDIT REMOVAL END - Ugly ID
-
apply_overlay(ID_LAYER)
- //apply_overlay(ID_CARD_LAYER) //SKYRAT EDIT REMOVAL - Ugly ID
-/*
/mob/living/carbon/human/update_inv_gloves()
remove_overlay(GLOVES_LAYER)
- if(client && hud_used?.inv_slots[TOBITSHIFT(ITEM_SLOT_GLOVES) + 1])
+ if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_GLOVES) + 1])
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_GLOVES) + 1]
- inv.update_appearance()
+ inv.update_icon()
- if(!gloves && blood_in_hands && (num_hands > 0) && !(NOBLOODOVERLAY in dna.species.species_traits))
- var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER)
+ //Bloody hands begin
+ var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER)
+ cut_overlay(bloody_overlay)
+ if(!gloves && blood_in_hands && (num_hands > 0))
+ bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER)
if(num_hands < 2)
if(has_left_hand(FALSE))
bloody_overlay.icon_state = "bloodyhands_left"
else if(has_right_hand(FALSE))
bloody_overlay.icon_state = "bloodyhands_right"
- overlays_standing[GLOVES_LAYER] = bloody_overlay
+ add_overlay(bloody_overlay)
+ //Bloody hands end
- var/mutable_appearance/gloves_overlay = overlays_standing[GLOVES_LAYER]
+ var/mutable_appearance/gloves_overlay
if(gloves)
- gloves.screen_loc = ui_gloves
- if(client && hud_used?.hud_shown)
- if(hud_used.inventory_shown)
- client.screen += gloves
- update_observer_view(gloves,1)
- overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(default_layer = GLOVES_LAYER, default_icon_file = 'icons/mob/clothing/hands.dmi')
- gloves_overlay = overlays_standing[GLOVES_LAYER]
- if(OFFSET_GLOVES in dna.species.offset_features)
+ var/obj/item/worn_item = gloves
+ update_hud_gloves(worn_item)
+ var/icon_file
+ var/handled_by_bodytype
+
+ // SKYRAT EDIT ADDITION
+ if(dna.species.bodytype & BODYTYPE_TESHARI)
+ icon_file = TESHARI_HANDS_ICON
+ // SKYRAT EDIT END
+
+ if(!icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item)))
+ icon_file = 'icons/mob/clothing/hands.dmi'
+ handled_by_bodytype = FALSE
+
+ gloves_overlay = gloves.build_worn_icon(default_layer = GLOVES_LAYER, default_icon_file = icon_file, override_file = handled_by_bodytype ? icon_file : null) // SKYRAT EDIT CHANGE
+
+ if(!gloves_overlay)
+ return
+ if(OFFSET_GLOVES in dna.species.offset_features && !handled_by_bodytype)
gloves_overlay.pixel_x += dna.species.offset_features[OFFSET_GLOVES][1]
gloves_overlay.pixel_y += dna.species.offset_features[OFFSET_GLOVES][2]
- overlays_standing[GLOVES_LAYER] = gloves_overlay
+ overlays_standing[GLOVES_LAYER] = gloves_overlay
apply_overlay(GLOVES_LAYER)
-*/
-//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular)
-/*
+
/mob/living/carbon/human/update_inv_glasses()
remove_overlay(GLASSES_LAYER)
@@ -232,26 +248,38 @@ There are several things that need to be remembered:
if(client && hud_used)
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_EYES) + 1]
- inv.update_appearance()
+ inv.update_icon()
if(glasses)
- glasses.screen_loc = ui_glasses //...draw the item in the inventory screen
- if(client && hud_used?.hud_shown)
- if(hud_used.inventory_shown) //if the inventory is open ...
- client.screen += glasses //Either way, add the item to the HUD
- update_observer_view(glasses,1)
- //This is in case the glasses would be going above the hair, like welding goggles that were lifted up
- if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES)))
- overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/clothing/eyes.dmi')
+ var/obj/item/worn_item = glasses
+ var/mutable_appearance/glasses_overlay
+ update_hud_glasses(worn_item)
- var/mutable_appearance/glasses_overlay = overlays_standing[GLASSES_LAYER]
- if(glasses_overlay)
- if(OFFSET_GLASSES in dna.species.offset_features)
- glasses_overlay.pixel_x += dna.species.offset_features[OFFSET_GLASSES][1]
- glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2]
- overlays_standing[GLASSES_LAYER] = glasses_overlay
+ var/handled_by_bodytype
+ var/icon_file
+ // SKYRAT EDIT ADDITION
+ if((dna.species.bodytype & BODYTYPE_VOX) && (worn_item.supports_variations_flags & CLOTHING_SNOUTED_VOX_VARIATION))
+ icon_file = worn_item.worn_icon_vox || VOX_GLASSES_FILE
+ else if(dna.species.bodytype & BODYTYPE_TESHARI)
+ icon_file = TESHARI_EYES_ICON
+ // SKYRAT EDIT END
+ if(!(head?.flags_inv & HIDEEYES) && !(wear_mask?.flags_inv & HIDEEYES))
+
+ if(!icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item)))
+ icon_file = 'icons/mob/clothing/eyes.dmi'
+ handled_by_bodytype = FALSE
+
+ glasses_overlay = glasses.build_worn_icon(default_layer = GLASSES_LAYER, default_icon_file = icon_file, override_file = handled_by_bodytype ? icon_file : null) // SKYRAT EDIT CHANGE
+
+ if(!glasses_overlay)
+ return
+ if(OFFSET_GLASSES in dna.species.offset_features && !handled_by_bodytype)
+ glasses_overlay.pixel_x += dna.species.offset_features[OFFSET_GLASSES][1]
+ glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2]
+ overlays_standing[GLASSES_LAYER] = glasses_overlay
apply_overlay(GLASSES_LAYER)
+
/mob/living/carbon/human/update_inv_ears()
remove_overlay(EARS_LAYER)
@@ -260,26 +288,67 @@ There are several things that need to be remembered:
if(client && hud_used)
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_EARS) + 1]
- inv.update_appearance()
+ inv.update_icon()
if(ears)
- ears.screen_loc = ui_ears //move the item to the appropriate screen loc
- if(client && hud_used?.hud_shown)
- if(hud_used.inventory_shown) //if the inventory is open
- client.screen += ears //add it to the client's screen
- update_observer_view(ears,1)
- overlays_standing[EARS_LAYER] = ears.build_worn_icon(default_layer = EARS_LAYER, default_icon_file = 'icons/mob/clothing/ears.dmi')
- var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER]
- if(OFFSET_EARS in dna.species.offset_features)
+ var/obj/item/worn_item = ears
+ var/mutable_appearance/ears_overlay
+ update_hud_ears(worn_item)
+
+ var/handled_by_bodytype = TRUE
+ var/icon_file
+
+ if(!(icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item))))
+ handled_by_bodytype = FALSE
+ icon_file = 'icons/mob/clothing/ears.dmi'
+
+ ears_overlay = ears.build_worn_icon(default_layer = EARS_LAYER, default_icon_file = icon_file)
+
+ if(!ears_overlay)
+ return
+ if(OFFSET_EARS in dna.species.offset_features && !handled_by_bodytype)
ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1]
ears_overlay.pixel_y += dna.species.offset_features[OFFSET_EARS][2]
overlays_standing[EARS_LAYER] = ears_overlay
apply_overlay(EARS_LAYER)
-*/
-//SKYRAT EDIT REMOVAL END
-//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular)
-/*
+
+/mob/living/carbon/human/update_inv_neck()
+ remove_overlay(NECK_LAYER)
+
+ if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_NECK) + 1])
+ var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_NECK) + 1]
+ inv.update_icon()
+
+ if(wear_neck)
+ var/obj/item/worn_item = wear_neck
+
+ if(!(ITEM_SLOT_NECK in check_obscured_slots()))
+ var/mutable_appearance/neck_overlay
+ var/icon_file
+ var/handled_by_bodytype = TRUE
+
+ // SKYRAT EDIT ADDITION
+ if(dna.species.bodytype & BODYTYPE_TESHARI)
+ icon_file = TESHARI_NECK_ICON
+ // SKYRAT EDIT END
+
+ if(!(icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item))))
+ handled_by_bodytype = FALSE
+ icon_file = 'icons/mob/clothing/neck.dmi'
+
+ neck_overlay = worn_item.build_worn_icon(default_layer = NECK_LAYER, default_icon_file = icon_file, override_file = handled_by_bodytype ? icon_file : null) // SKYRAT EDIT CHANGE
+
+ if(!neck_overlay)
+ return
+ if(OFFSET_NECK in dna.species.offset_features && !handled_by_bodytype)
+ neck_overlay.pixel_x += dna.species.offset_features[OFFSET_NECK][1]
+ neck_overlay.pixel_y += dna.species.offset_features[OFFSET_NECK][2]
+ overlays_standing[NECK_LAYER] = neck_overlay
+ update_hud_neck(wear_neck)
+
+ apply_overlay(NECK_LAYER)
+
/mob/living/carbon/human/update_inv_shoes()
remove_overlay(SHOES_LAYER)
@@ -288,24 +357,38 @@ There are several things that need to be remembered:
if(client && hud_used)
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_FEET) + 1]
- inv.update_appearance()
+ inv.update_icon()
if(shoes)
- shoes.screen_loc = ui_shoes //move the item to the appropriate screen loc
- if(client && hud_used?.hud_shown)
- if(hud_used.inventory_shown) //if the inventory is open
- client.screen += shoes //add it to client's screen
- update_observer_view(shoes,1)
- overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(default_layer = SHOES_LAYER, default_icon_file = 'icons/mob/clothing/feet.dmi')
- var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER]
- if(OFFSET_SHOES in dna.species.offset_features)
+ var/obj/item/worn_item = shoes
+ var/mutable_appearance/shoes_overlay
+ var/icon_file
+ update_hud_shoes(worn_item)
+ var/handled_by_bodytype = TRUE
+
+ if((dna.species.bodytype & BODYTYPE_DIGITIGRADE) && (worn_item.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION))
+ var/obj/item/bodypart/leg = src.get_bodypart(BODY_ZONE_L_LEG)
+ if(leg.limb_id == "digitigrade")//Snowflakey and bad. But it makes it look consistent.
+ icon_file = worn_item.worn_icon_digi || DIGITIGRADE_SHOES_FILE // SKYRAT EDIT CHANGE
+ // SKYRAT EDIT ADDITION
+ else if(dna.species.bodytype & BODYTYPE_TESHARI)
+ icon_file = TESHARI_FEET_ICON
+ // SKYRAT EDIT END
+
+ if(!(icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item))))
+ handled_by_bodytype = FALSE
+ icon_file = DEFAULT_SHOES_FILE
+
+ shoes_overlay = shoes.build_worn_icon(default_layer = SHOES_LAYER, default_icon_file = icon_file, override_file = handled_by_bodytype ? icon_file : null) // SKYRAT EDIT CHANGE
+
+ if(!shoes_overlay)
+ return
+ if(!(handled_by_bodytype) && (OFFSET_SHOES in dna.species.offset_features))
shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1]
shoes_overlay.pixel_y += dna.species.offset_features[OFFSET_SHOES][2]
overlays_standing[SHOES_LAYER] = shoes_overlay
apply_overlay(SHOES_LAYER)
-*/
-//SKYRAT EDIT REMOVAL END
/mob/living/carbon/human/update_inv_s_store()
@@ -313,29 +396,52 @@ There are several things that need to be remembered:
if(client && hud_used)
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_SUITSTORE) + 1]
- inv.update_appearance()
+ inv.update_icon()
if(s_store)
- s_store.screen_loc = ui_sstore1
- if(client && hud_used?.hud_shown)
- client.screen += s_store
- update_observer_view(s_store)
- overlays_standing[SUIT_STORE_LAYER] = s_store.build_worn_icon(default_layer = SUIT_STORE_LAYER, default_icon_file = 'icons/mob/clothing/belt_mirror.dmi')
- var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_STORE_LAYER]
+ var/obj/item/worn_item = s_store
+ var/mutable_appearance/s_store_overlay
+ update_hud_s_store(worn_item)
+
+ s_store_overlay = worn_item.build_worn_icon(default_layer = SUIT_STORE_LAYER, default_icon_file = 'icons/mob/clothing/belt_mirror.dmi')
+
+ if(!s_store_overlay)
+ return
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]
overlays_standing[SUIT_STORE_LAYER] = s_store_overlay
apply_overlay(SUIT_STORE_LAYER)
-
/mob/living/carbon/human/update_inv_head()
- ..()
- update_mutant_bodyparts()
- var/mutable_appearance/head_overlay = overlays_standing[HEAD_LAYER]
- if(head_overlay)
- remove_overlay(HEAD_LAYER)
- if(OFFSET_HEAD in dna.species.offset_features)
+ remove_overlay(HEAD_LAYER)
+ if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_BACK) + 1])
+ var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_HEAD) + 1]
+ inv.update_icon()
+
+ if(head)
+ var/obj/item/worn_item = head
+ var/mutable_appearance/head_overlay
+ update_hud_head(worn_item)
+ var/handled_by_bodytype = FALSE
+ var/icon_file
+
+ // SKYRAT EDIT ADDITION - This needs to be refactored.
+ if((dna.species.bodytype & BODYTYPE_SNOUTED) && (worn_item.supports_variations_flags & CLOTHING_SNOUTED_VARIATION))
+ icon_file = worn_item.worn_icon_muzzled || SNOUTED_HEAD_FILE
+ else if(dna.species.bodytype & BODYTYPE_TESHARI)
+ icon_file = TESHARI_HEAD_ICON
+ // SKYRAT EDIT END
+
+ if(!(icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item))))
+ handled_by_bodytype = FALSE
+ icon_file = 'icons/mob/clothing/head.dmi'
+
+ head_overlay = head.build_worn_icon(default_layer = HEAD_LAYER, default_icon_file = icon_file, override_file = handled_by_bodytype ? icon_file : null) // SKYRAT EDIT CHANGE
+
+ if(!head_overlay)
+ return
+ if(!(handled_by_bodytype) && (OFFSET_HEAD in dna.species.offset_features))
head_overlay.pixel_x += dna.species.offset_features[OFFSET_HEAD][1]
head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2]
//SKYRAT EDIT ADDITION BEGIN - TESHARI CLOTHES
@@ -343,7 +449,9 @@ There are several things that need to be remembered:
head_overlay.pixel_x = 0
head_overlay.pixel_y = 0
//SKYRAT EDIT ADDITION END - TESHARI CLOTHES
- overlays_standing[HEAD_LAYER] = head_overlay
+ overlays_standing[HEAD_LAYER] = head_overlay
+
+ update_mutant_bodyparts()
apply_overlay(HEAD_LAYER)
/mob/living/carbon/human/update_inv_belt()
@@ -351,57 +459,69 @@ There are several things that need to be remembered:
if(client && hud_used)
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_BELT) + 1]
- inv.update_appearance()
+ inv.update_icon()
if(belt)
- //SKYRAT EDIT ADDITION BEGIN - TESHARI CLOTHES
- var/icon_file = belt.worn_icon
- var/applied_styles = NONE
- if(isteshari(src))
- var/static/list/tesh_icon_states = icon_states(TESHARI_BELT_ICON)
- if((belt.worn_icon_state || belt.icon_state) in tesh_icon_states)
- icon_file = TESHARI_BELT_ICON
- applied_styles = STYLE_TESHARI
- //SKYRAT EDIT ADDITION END - TESHARI CLOTHES
- belt.screen_loc = ui_belt
- if(client && hud_used?.hud_shown)
- client.screen += belt
- update_observer_view(belt)
- //SKYRAT EDIT - TESHARI CLOTHES - added override_icon and mutant_styles arguments to below function
- overlays_standing[BELT_LAYER] = belt.build_worn_icon(default_layer = BELT_LAYER, default_icon_file = 'icons/mob/clothing/belt.dmi', override_icon = icon_file, mutant_styles = applied_styles)
- var/mutable_appearance/belt_overlay = overlays_standing[BELT_LAYER]
- if(OFFSET_BELT in dna.species.offset_features)
+ var/obj/item/worn_item = belt
+ var/mutable_appearance/belt_overlay
+ update_hud_belt(worn_item)
+ var/handled_by_bodytype = TRUE
+ var/icon_file
+
+ // SKYRAT EDIT ADDITION
+ if(dna.species.bodytype & BODYTYPE_TESHARI)
+ icon_file = TESHARI_BELT_ICON
+ // SKYRAT EDIT END
+
+ if(!(icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item))))
+ handled_by_bodytype = FALSE
+ icon_file = 'icons/mob/clothing/belt.dmi'
+
+ belt_overlay = belt.build_worn_icon(default_layer = BELT_LAYER, default_icon_file = icon_file, override_file = handled_by_bodytype ? icon_file : null) // SKYRAT EDIT CHANGE
+
+ if(!belt_overlay)
+ return
+ if(OFFSET_BELT in dna.species.offset_features && !handled_by_bodytype)
belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1]
belt_overlay.pixel_y += dna.species.offset_features[OFFSET_BELT][2]
- //SKYRAT EDIT ADDITION BEGIN - TESHARI CLOTHES
- if(belt_overlay.icon == TESHARI_BELT_ICON)
- belt_overlay.pixel_x = 0
- belt_overlay.pixel_y = 0
- //SKYRAT EDIT ADDITION END - TESHARI CLOTHES
overlays_standing[BELT_LAYER] = belt_overlay
apply_overlay(BELT_LAYER)
-
-
-//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular)
-/*
/mob/living/carbon/human/update_inv_wear_suit()
remove_overlay(SUIT_LAYER)
if(client && hud_used)
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_OCLOTHING) + 1]
- inv.update_appearance()
+ inv.update_icon()
- if(istype(wear_suit, /obj/item/clothing/suit))
- wear_suit.screen_loc = ui_oclothing
- if(client && hud_used?.hud_shown)
- if(hud_used.inventory_shown)
- client.screen += wear_suit
- update_observer_view(wear_suit,1)
- overlays_standing[SUIT_LAYER] = wear_suit.build_worn_icon(default_layer = SUIT_LAYER, default_icon_file = 'icons/mob/clothing/suit.dmi')
- var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER]
- if(OFFSET_SUIT in dna.species.offset_features)
+ if(wear_suit)
+ var/obj/item/worn_item = wear_suit
+ var/mutable_appearance/suit_overlay
+ update_hud_wear_suit(worn_item)
+ var/icon_file
+
+ var/handled_by_bodytype = TRUE
+
+ //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
+
+ // SKYRAT EDIT ADDITION
+ else if(dna.species.bodytype & BODYTYPE_TESHARI)
+ icon_file = TESHARI_SUIT_ICON
+ // SKYRAT EDIT END
+
+ if(!(icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item))))
+ handled_by_bodytype = FALSE
+ icon_file = DEFAULT_SUIT_FILE
+
+ suit_overlay = wear_suit.build_worn_icon(default_layer = SUIT_LAYER, default_icon_file = icon_file, override_file = handled_by_bodytype ? icon_file : null) // SKYRAT EDIT CHANGE
+
+ if(!suit_overlay)
+ return
+ if((!handled_by_bodytype) && (OFFSET_SUIT in dna.species.offset_features))
suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1]
suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2]
overlays_standing[SUIT_LAYER] = suit_overlay
@@ -409,19 +529,15 @@ There are several things that need to be remembered:
update_mutant_bodyparts()
apply_overlay(SUIT_LAYER)
-*/
-//SKYRAT EDIT REMOVAL END
-
/mob/living/carbon/human/update_inv_pockets()
if(client && hud_used)
var/atom/movable/screen/inventory/inv
inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_LPOCKET) + 1]
- inv.update_appearance()
-
inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_RPOCKET) + 1]
- inv.update_appearance()
+
+ inv.update_icon()
if(l_store)
l_store.screen_loc = ui_storage1
@@ -435,13 +551,41 @@ There are several things that need to be remembered:
client.screen += r_store
update_observer_view(r_store)
-
/mob/living/carbon/human/update_inv_wear_mask()
- ..()
- var/mutable_appearance/mask_overlay = overlays_standing[FACEMASK_LAYER]
- if(mask_overlay)
- remove_overlay(FACEMASK_LAYER)
- if(OFFSET_FACEMASK in dna.species.offset_features)
+ remove_overlay(FACEMASK_LAYER)
+
+ if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
+ return
+
+ if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_MASK) + 1])
+ var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_MASK) + 1]
+ inv.update_icon()
+
+ if(wear_mask)
+ var/obj/item/worn_item = wear_mask
+ update_hud_wear_mask(worn_item)
+ var/mutable_appearance/mask_overlay
+ var/icon_file = 'icons/mob/clothing/mask.dmi'
+ var/handled_by_bodytype = TRUE
+
+ // SKYRAT EDIT ADDITION
+ if((dna.species.bodytype & BODYTYPE_SNOUTED) && !(worn_item.supports_variations_flags & CLOTHING_SNOUTED_VARIATION))
+ icon_file = worn_item.worn_icon_muzzled || SNOUTED_MASK_FILE
+ else if(dna.species.bodytype & BODYTYPE_TESHARI)
+ icon_file = TESHARI_MASK_ICON
+ // SKYRAT EDIT END
+
+ if(!(ITEM_SLOT_MASK in check_obscured_slots()))
+
+ if(!(icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item))))
+ icon_file = 'icons/mob/clothing/mask.dmi'
+ handled_by_bodytype = FALSE
+
+ mask_overlay = wear_mask.build_worn_icon(default_layer = FACEMASK_LAYER, default_icon_file = icon_file, override_file = handled_by_bodytype ? icon_file : null) // SKYRAT EDIT CHANGE
+
+ if(!mask_overlay)
+ return
+ if((!handled_by_bodytype) && (OFFSET_FACEMASK in dna.species.offset_features))
mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1]
mask_overlay.pixel_y += dna.species.offset_features[OFFSET_FACEMASK][2]
//SKYRAT EDIT ADDITION BEGIN - TESHARI CLOTHES
@@ -449,16 +593,39 @@ There are several things that need to be remembered:
mask_overlay.pixel_x = 0
mask_overlay.pixel_y = 0
//SKYRAT EDIT ADDITION END - TESHARI CLOTHES
- overlays_standing[FACEMASK_LAYER] = mask_overlay
- apply_overlay(FACEMASK_LAYER)
+ overlays_standing[FACEMASK_LAYER] = mask_overlay
+
+ apply_overlay(FACEMASK_LAYER)
update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout
/mob/living/carbon/human/update_inv_back()
- ..()
- var/mutable_appearance/back_overlay = overlays_standing[BACK_LAYER]
- if(back_overlay)
- remove_overlay(BACK_LAYER)
- if(OFFSET_BACK in dna.species.offset_features)
+ remove_overlay(BACK_LAYER)
+
+ if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_BACK) + 1])
+ var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_BACK) + 1]
+ inv.update_icon()
+
+ if(back)
+ var/obj/item/worn_item = back
+ var/mutable_appearance/back_overlay
+ update_hud_back(worn_item)
+ var/icon_file = 'icons/mob/clothing/back.dmi'
+ var/handled_by_bodytype = TRUE
+
+ // SKYRAT EDIT ADDITION
+ if(dna.species.bodytype & BODYTYPE_TESHARI)
+ icon_file = TESHARI_BACK_ICON
+ // SKYRAT EDIT END
+
+ if(!icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item)))
+ icon_file = 'icons/mob/clothing/back.dmi'
+ handled_by_bodytype = FALSE
+
+ back_overlay = back.build_worn_icon(default_layer = BACK_LAYER, default_icon_file = icon_file, override_file = handled_by_bodytype ? icon_file : null) // SKYRAT EDIT CHANGE
+
+ if(!back_overlay)
+ return
+ if((!handled_by_bodytype) && (OFFSET_BACK in dna.species.offset_features))
back_overlay.pixel_x += dna.species.offset_features[OFFSET_BACK][1]
back_overlay.pixel_y += dna.species.offset_features[OFFSET_BACK][2]
//SKYRAT EDIT ADDITION BEGIN - TESHARI CLOTHES
@@ -466,25 +633,59 @@ There are several things that need to be remembered:
back_overlay.pixel_x = 0
back_overlay.pixel_y = 0
//SKYRAT EDIT ADDITION END - TESHARI CLOTHES
- overlays_standing[BACK_LAYER] = back_overlay
- apply_overlay(BACK_LAYER)
+ overlays_standing[BACK_LAYER] = back_overlay
+ apply_overlay(BACK_LAYER)
/mob/living/carbon/human/update_inv_legcuffed()
remove_overlay(LEGCUFF_LAYER)
- clear_alert(ALERT_LEGCUFFED)
+ clear_alert("legcuffed")
if(legcuffed)
- var/mutable_appearance/legcuff_overlay = mutable_appearance('icons/mob/mob.dmi', "legcuff1", -LEGCUFF_LAYER)
- if(legcuffed.blocks_emissive)
- legcuff_overlay.overlays += emissive_blocker(legcuff_overlay.icon, legcuff_overlay.icon_state, alpha = legcuff_overlay.alpha)
-
- overlays_standing[LEGCUFF_LAYER] = legcuff_overlay
+ overlays_standing[LEGCUFF_LAYER] = mutable_appearance('icons/mob/mob.dmi', "legcuff1", -LEGCUFF_LAYER)
apply_overlay(LEGCUFF_LAYER)
- throw_alert(ALERT_LEGCUFFED, /atom/movable/screen/alert/restrained/legcuffed, new_master = src.legcuffed)
+ throw_alert("legcuffed", /atom/movable/screen/alert/restrained/legcuffed, new_master = src.legcuffed)
+
+/mob/living/carbon/human/update_inv_hands()
+ remove_overlay(HANDS_LAYER)
+ if (handcuffed)
+ drop_all_held_items()
+ return
+
+ var/list/hands = list()
+ for(var/obj/item/worn_item in held_items)
+ 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))
+ client.screen += worn_item
+ if(observers?.len)
+ for(var/M in observers)
+ var/mob/dead/observe = M
+ if(observe.client && observe.client.eye == src)
+ observe.client.screen += worn_item
+ else
+ observers -= observe
+ if(!observers.len)
+ observers = null
+ break
+
+ var/t_state = worn_item.inhand_icon_state
+ 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)
+
+ hands += hand_overlay
+ overlays_standing[HANDS_LAYER] = hands
+ apply_overlay(HANDS_LAYER)
/proc/wear_female_version(t_color, icon, layer, type, greyscale_colors)
var/index = "[t_color]-[greyscale_colors]"
var/icon/female_clothing_icon = GLOB.female_clothing_icons[index]
- if(!female_clothing_icon) //Create standing/laying icons if they don't exist
+ if(!female_clothing_icon) //Create standing/laying icons if they don't exist
generate_female_clothing(index, t_color, icon, type)
return mutable_appearance(GLOB.female_clothing_icons[index], layer = -layer)
@@ -500,36 +701,86 @@ There are several things that need to be remembered:
//human HUD updates for items in our inventory
-//update whether our head item appears on our hud.
-/mob/living/carbon/human/update_hud_head(obj/item/I)
- I.screen_loc = ui_head
+/mob/living/carbon/human/proc/update_hud_uniform(obj/item/worn_item)
+ worn_item.screen_loc = ui_iclothing
+ if((client && hud_used) && (hud_used.inventory_shown && hud_used.hud_shown))
+ client.screen += worn_item
+ update_observer_view(worn_item,TRUE)
+
+/mob/living/carbon/human/proc/update_hud_id(obj/item/worn_item)
+ worn_item.screen_loc = ui_id
+ if((client && hud_used?.hud_shown))
+ client.screen += worn_item
+ update_observer_view(worn_item)
+
+/mob/living/carbon/human/proc/update_hud_gloves(obj/item/worn_item)
+ worn_item.screen_loc = ui_gloves
+ if((client && hud_used) && (hud_used.inventory_shown && hud_used.hud_shown))
+ client.screen += worn_item
+ update_observer_view(worn_item,TRUE)
+
+/mob/living/carbon/human/proc/update_hud_glasses(obj/item/worn_item)
+ worn_item.screen_loc = ui_glasses
+ if((client && hud_used) && (hud_used.inventory_shown && hud_used.hud_shown))
+ client.screen += worn_item
+ update_observer_view(worn_item,TRUE)
+
+/mob/living/carbon/human/proc/update_hud_ears(obj/item/worn_item)
+ worn_item.screen_loc = ui_ears
+ if((client && hud_used) && (hud_used.inventory_shown && hud_used.hud_shown))
+ client.screen += worn_item
+ update_observer_view(worn_item,TRUE)
+
+/mob/living/carbon/human/proc/update_hud_shoes(obj/item/worn_item)
+ worn_item.screen_loc = ui_shoes
+ if((client && hud_used) && (hud_used.inventory_shown && hud_used.hud_shown))
+ client.screen += worn_item
+ update_observer_view(worn_item,TRUE)
+
+/mob/living/carbon/human/proc/update_hud_s_store(obj/item/worn_item)
+ worn_item.screen_loc = ui_sstore1
+ if((client && hud_used) && (hud_used.inventory_shown && hud_used.hud_shown))
+ client.screen += worn_item
+ update_observer_view(worn_item,TRUE)
+
+/mob/living/carbon/human/proc/update_hud_wear_suit(obj/item/worn_item)
+ worn_item.screen_loc = ui_oclothing
+ if((client && hud_used) && (hud_used.inventory_shown && hud_used.hud_shown))
+ client.screen += worn_item
+ update_observer_view(worn_item,TRUE)
+
+/mob/living/carbon/human/proc/update_hud_belt(obj/item/worn_item)
+ belt.screen_loc = ui_belt
if(client && hud_used?.hud_shown)
- if(hud_used.inventory_shown)
- client.screen += I
- update_observer_view(I,1)
+ client.screen += worn_item
+ update_observer_view(worn_item,TRUE)
+
+/mob/living/carbon/human/update_hud_head(obj/item/worn_item)
+ worn_item.screen_loc = ui_head
+ if((client && hud_used) && (hud_used.inventory_shown && hud_used.hud_shown))
+ client.screen += worn_item
+ update_observer_view(worn_item,TRUE)
//update whether our mask item appears on our hud.
-/mob/living/carbon/human/update_hud_wear_mask(obj/item/I)
- I.screen_loc = ui_mask
- if(client && hud_used?.hud_shown)
- if(hud_used.inventory_shown)
- client.screen += I
- update_observer_view(I,1)
+/mob/living/carbon/human/update_hud_wear_mask(obj/item/worn_item)
+ worn_item.screen_loc = ui_mask
+ if((client && hud_used) && (hud_used.inventory_shown && hud_used.hud_shown))
+ client.screen += worn_item
+ update_observer_view(worn_item,TRUE)
//update whether our neck item appears on our hud.
-/mob/living/carbon/human/update_hud_neck(obj/item/I)
- I.screen_loc = ui_neck
- if(client && hud_used?.hud_shown)
- if(hud_used.inventory_shown)
- client.screen += I
- update_observer_view(I,1)
+/mob/living/carbon/human/update_hud_neck(obj/item/worn_item)
+ worn_item.screen_loc = ui_neck
+ if((client && hud_used) && (hud_used.inventory_shown && hud_used.hud_shown))
+ client.screen += worn_item
+ update_observer_view(worn_item,TRUE)
//update whether our back item appears on our hud.
-/mob/living/carbon/human/update_hud_back(obj/item/I)
- I.screen_loc = ui_back
+/mob/living/carbon/human/update_hud_back(obj/item/worn_item)
+ worn_item.screen_loc = ui_back
if(client && hud_used?.hud_shown)
- client.screen += I
- update_observer_view(I)
+ client.screen += worn_item
+ update_observer_view(worn_item, inventory = TRUE)
/*
Does everything in relation to building the /mutable_appearance used in the mob's overlays list
@@ -556,9 +807,8 @@ generate/load female uniform sprites matching all previously decided variables
*/
-//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular)
-/*
-/obj/item/proc/build_worn_icon(default_layer = 0, default_icon_file = null, isinhands = FALSE, femaleuniform = NO_FEMALE_UNIFORM, override_state = null)
+
+/obj/item/proc/build_worn_icon(default_layer = 0, default_icon_file = null, isinhands = FALSE, femaleuniform = NO_FEMALE_UNIFORM, override_state = null, override_file = null)
//Find a valid icon_state from variables+arguments
var/t_state
@@ -568,8 +818,11 @@ generate/load female uniform sprites matching all previously decided variables
t_state = !isinhands ? (worn_icon_state ? worn_icon_state : icon_state) : (inhand_icon_state ? inhand_icon_state : icon_state)
//Find a valid icon file from variables+arguments
- var/file2use = !isinhands ? (worn_icon ? worn_icon : default_icon_file) : default_icon_file
-
+ var/file2use
+ if(override_file)
+ file2use = override_file
+ else
+ file2use = !isinhands ? (worn_icon ? worn_icon : default_icon_file) : default_icon_file
//Find a valid layer from variables+arguments
var/layer2use = alternate_worn_layer ? alternate_worn_layer : default_layer
@@ -596,8 +849,7 @@ generate/load female uniform sprites matching all previously decided variables
standing.color = color
return standing
-*/
-//SKYRAT EDIT REMOVAL END
+
/// Returns offsets used for equipped item overlays in list(px_offset,py_offset) form.
/obj/item/proc/get_worn_offsets(isinhands)
@@ -623,74 +875,15 @@ generate/load female uniform sprites matching all previously decided variables
else //No offsets or Unwritten number of hands
return list("x" = 0, "y" = 0)//Handle held offsets
-//produces a key based on the human's limbs
-/mob/living/carbon/human/generate_icon_render_key()
- . = "[dna.species.limbs_id]"
-
- if(dna.check_mutation(/datum/mutation/human/hulk))
- . += "-coloured-hulk"
- else if(dna.species.use_skintones)
- . += "-coloured-[skin_tone]"
- else if(dna.species.fixed_mut_color)
- . += "-coloured-[dna.species.fixed_mut_color]"
- //else if(dna.features["mcolor"]) - ORIGINAL
- // . += "-coloured-[dna.features["mcolor"]]" - ORIGINAL
- else if(MUTCOLORS in dna.species.species_traits) //SKYRAT EDIT CHANGE - CUSTOMIZATION
- . += "-coloured-[dna.features["mcolor"]]" //SKYRAT EDIT CHANGE - CUSTOMIZATION
- else
- . += "-not_coloured"
-
- . += "-[body_type]"
-
- for(var/X in bodyparts)
- var/obj/item/bodypart/BP = X
- . += "-[BP.body_zone]"
- if(!HAS_TRAIT(src, TRAIT_INVISIBLE_MAN))
- for(var/obj/item/organ/external/organ as anything in BP.external_organs)
- if(organ.can_draw_on_bodypart(src)) //make sure we're drawn before generating a key
- . += "([organ.cache_key])"
- //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION
- /*
- if(BP.status == BODYPART_ORGANIC)
- . += "-organic"
- else
- . += "-robotic"
- */
- //SKYRAT EDIT REMOVAL END
- if(BP.use_digitigrade)
- . += "-digitigrade[BP.use_digitigrade]"
- if(BP.dmg_overlay_type)
- . += "-[BP.dmg_overlay_type]"
-
- //SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION
- if(BP.organic_render)
- . += "-OR"
- //SKYRAT EDIT ADDITION END
-
- if(HAS_TRAIT(BP, TRAIT_PLASMABURNT))
- . += "-plasmaburnt"
-
- if(HAS_TRAIT(src, TRAIT_HUSK))
- . += "-husk"
-
- if(HAS_TRAIT(src, TRAIT_INVISIBLE_MAN))
- . += "-invisible"
-
-/mob/living/carbon/human/load_limb_from_cache()
- ..()
- update_hair()
-
-
-
-/mob/living/carbon/human/proc/update_observer_view(obj/item/I, inventory)
- if(observers && observers.len)
+/mob/living/carbon/human/proc/update_observer_view(obj/item/worn_item, inventory)
+ if(observers?.len)
for(var/M in observers)
var/mob/dead/observe = M
if(observe.client && observe.client.eye == src)
if(observe.hud_used)
if(inventory && !observe.hud_used.inventory_shown)
continue
- observe.client.screen += I
+ observe.client.screen += worn_item
else
observers -= observe
if(!observers.len)
@@ -698,11 +891,8 @@ generate/load female uniform sprites matching all previously decided variables
break
// Only renders the head of the human
-/mob/living/carbon/human/proc/update_body_parts_head_only()
- if (!dna)
- return
-
- if (!dna.species)
+/mob/living/carbon/human/proc/update_body_parts_head_only(update_limb_data)
+ if(!dna?.species)
return
var/obj/item/bodypart/HD = get_bodypart("head")
@@ -710,7 +900,7 @@ generate/load female uniform sprites matching all previously decided variables
if (!istype(HD))
return
- HD.update_limb()
+ HD.update_limb(is_creating = update_limb_data)
add_overlay(HD.get_limb_icon())
update_damage_overlays()
@@ -734,7 +924,7 @@ generate/load female uniform sprites matching all previously decided variables
else
eye_overlay = mutable_appearance('icons/mob/human_face.dmi', E.eye_icon_state, -BODY_LAYER)
if((EYECOLOR in dna.species.species_traits) && E)
- eye_overlay.color = eye_color
+ eye_overlay.color = "#" + eye_color
if(OFFSET_FACE in dna.species.offset_features)
eye_overlay.pixel_x += dna.species.offset_features[OFFSET_FACE][1]
eye_overlay.pixel_y += dna.species.offset_features[OFFSET_FACE][2]
@@ -749,7 +939,8 @@ generate/load female uniform sprites matching all previously decided variables
add_overlay(emissive_appearance)
//SKYRAT EDIT END
- dna.species.handle_hair(src)
update_inv_head()
update_inv_wear_mask()
+
+#undef RESOLVE_ICON_STATE
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 214f204a1da..0e971bc9cec 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -52,7 +52,7 @@
return null
-/mob/living/carbon/human/proc/get_all_slots()
+/mob/living/carbon/human/get_all_worn_items()
. = get_head_slots() | get_body_slots()
/mob/living/carbon/human/proc/get_body_slots()
@@ -235,7 +235,7 @@
/mob/living/carbon/human/equipped_speed_mods()
. = ..()
- for(var/sloties in get_all_slots() - list(l_store, r_store, s_store))
+ for(var/sloties in get_all_worn_items() - list(l_store, r_store, s_store))
var/obj/item/thing = sloties
. += thing?.slowdown
@@ -394,7 +394,7 @@
//delete all equipment without dropping anything
/mob/living/carbon/human/proc/delete_equipment()
- for(var/slot in get_all_slots())//order matters, dependant slots go first
+ for(var/slot in get_all_worn_items())//order matters, dependant slots go first
qdel(slot)
for(var/obj/item/I in held_items)
qdel(I)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index fdffbde1b92..eaeca562828 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -15,8 +15,6 @@ GLOBAL_LIST_EMPTY(features_by_species)
/datum/species
///If the game needs to manually check your race to do something not included in a proc here, it will use this.
var/id
- //This is used if you want to use a different species' limb sprites.
- var/limbs_id
///This is the fluff name. They are displayed on health analyzers and in the character setup menu. Leave them generic for other servers to customize.
var/name
/// The formatting of the name of the species in plural context. Defaults to "[name]\s" if unset.
@@ -27,15 +25,22 @@ GLOBAL_LIST_EMPTY(features_by_species)
///Whether or not the race has sexual characteristics (biological genders). At the moment this is only FALSE for skeletons and shadows
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 - OFFSET_ACCESSORY
+ ///The maximum number of bodyparts this species can have.
+ var/max_bodypart_count = 6
///This allows races to have specific hair colors. If null, it uses the H's hair/facial hair colors. If "mutcolor", it uses the H's mutant_color. If "fixedmutcolor", it uses fixedmutcolor
var/hair_color
///The alpha used by the hair. 255 is completely solid, 0 is invisible.
var/hair_alpha = 255
+ ///This is used for children, it will determine their default limb ID for use of examine. See [/mob/living/carbon/human/proc/examine].
+ var/examine_limb_id
+ ///Never, Optional, or Forced digi legs?
+ var/digitigrade_customization = DIGITIGRADE_NEVER
///Does the species use skintones or not? As of now only used by humans.
var/use_skintones = FALSE
///If your race bleeds something other than bog standard blood, change this to reagent id. For example, ethereals bleed liquid electricity.
@@ -74,13 +79,14 @@ GLOBAL_LIST_EMPTY(features_by_species)
///Internal organs that are unique to this race, like a tail.
var/list/mutant_organs = list()
///The bodyparts this species uses. assoc of bodypart string - bodypart type. Make sure all the fucking entries are in or I'll skin you alive.
- var/list/bodypart_overides = list(
- BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm,\
- BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm,\
- BODY_ZONE_HEAD = /obj/item/bodypart/head,\
- BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg,\
- BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg,\
- BODY_ZONE_CHEST = /obj/item/bodypart/chest)
+ var/list/bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest,
+ )
///List of external organs to generate like horns, frills, wings, etc. list(typepath of organ = "Round Beautiful BDSM Snout"). Still WIP
var/list/external_organs = list()
@@ -230,8 +236,6 @@ GLOBAL_LIST_EMPTY(features_by_species)
/datum/species/New()
- if(!limbs_id) //if we havent set a limbs id to use, just use our own id
- limbs_id = id
wings_icons = string_list(wings_icons)
if(!plural_form)
@@ -401,8 +405,6 @@ GLOBAL_LIST_EMPTY(features_by_species)
* * old_species - The species that the carbon used to be before becoming this race, used for regenerating organs.
* * pref_load - Preferences to be loaded from character setup, loads in preferred mutant things like bodyparts, digilegs, skin color, etc.
*/
-//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular)
-/*
/datum/species/proc/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
SHOULD_CALL_PARENT(TRUE)
// Drop the items the new species can't wear
@@ -415,16 +417,10 @@ GLOBAL_LIST_EMPTY(features_by_species)
if(C.hud_used)
C.hud_used.update_locked_slots()
- fix_non_native_limbs(C)
-
- // this needs to be FIRST because qdel calls update_body which checks if we have DIGITIGRADE legs or not and if not then removes DIGITIGRADE from species_traits
- if(C.dna.species.mutant_bodyparts["legs"] && C.dna.features["legs"] == "Digitigrade Legs")
- species_traits += DIGITIGRADE
- if(DIGITIGRADE in species_traits)
- C.Digitigrade_Leg_Swap(FALSE)
C.mob_biotypes = inherent_biotypes
+ replace_body(C, src)
regenerate_organs(C, old_species, visual_only = C.visual_only_organs)
if(exotic_bloodtype && C.dna.blood_type != exotic_bloodtype)
@@ -465,6 +461,14 @@ GLOBAL_LIST_EMPTY(features_by_species)
if(TRAIT_TOXIMMUNE in inherent_traits)
C.setToxLoss(0, TRUE, TRUE)
+ // SKYRAT EDIT ADDITION
+ if(TRAIT_OXYIMMUNE in inherent_traits)
+ C.setOxyLoss(0, TRUE, TRUE)
+
+ for(var/obj/item/bodypart/limb in C.bodyparts)
+ limb.alpha = specific_alpha
+ // SKYRAT EDIT END
+
if(TRAIT_NOMETABOLISM in inherent_traits)
C.reagents.end_metabolization(C, keep_liverless = TRUE)
@@ -482,8 +486,6 @@ GLOBAL_LIST_EMPTY(features_by_species)
C.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, multiplicative_slowdown=speedmod)
SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)
-*/
-//SKYRAT EDIT REMOVAL END
/**
* Proc called when a carbon is no longer this species.
@@ -499,8 +501,6 @@ GLOBAL_LIST_EMPTY(features_by_species)
SHOULD_CALL_PARENT(TRUE)
if(C.dna.species.exotic_bloodtype)
C.dna.blood_type = random_blood_type()
- if(DIGITIGRADE in species_traits)
- C.Digitigrade_Leg_Swap(TRUE)
for(var/X in inherent_traits)
REMOVE_TRAIT(C, X, SPECIES_TRAIT)
for(var/obj/item/organ/external/organ in C.internal_organs)
@@ -528,151 +528,6 @@ GLOBAL_LIST_EMPTY(features_by_species)
SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src)
-/**
- * Handles hair icons and dynamic hair.
- *
- * Handles hiding hair with clothing, hair layers, losing hair due to husking or augmented heads, facial hair, head hair, and hair styles.
- * Arguments:
- * * H - Human, whoever we're handling the hair for
- * * forced_colour - The colour of hair we're forcing on this human. Leave null to not change. Mind the british spelling!
- */
-/datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour)
- H.remove_overlay(HAIR_LAYER)
- var/obj/item/bodypart/head/noggin = H.get_bodypart(BODY_ZONE_HEAD)
- if(!noggin) //Decapitated
- return
-
- if(HAS_TRAIT(H, TRAIT_HUSK) || HAS_TRAIT(H, TRAIT_INVISIBLE_MAN))
- return
- var/datum/sprite_accessory/S
- var/list/standing = list()
-
- var/hair_hidden = FALSE //ignored if the matching dynamic_X_suffix is non-empty
- var/facialhair_hidden = FALSE // ^
-
- //for augmented heads
- if(noggin.status == BODYPART_ROBOTIC && !(ROBOTIC_LIMBS in species_traits)) //SKYRAT EDIT CHANGE - CUSTOMIZATION
- return
-
- //we check if our hat or helmet hides our facial hair.
- if(H.head)
- var/obj/item/I = H.head
- if(I.flags_inv & HIDEFACIALHAIR)
- facialhair_hidden = TRUE
-
- if(H.wear_mask)
- var/obj/item/I = H.wear_mask
- if(I.flags_inv & HIDEFACIALHAIR)
- facialhair_hidden = TRUE
-
- if(H.facial_hairstyle && (FACEHAIR in species_traits) && !facialhair_hidden)
- S = GLOB.facial_hairstyles_list[H.facial_hairstyle]
- if(S)
-
- var/mutable_appearance/facial_overlay = mutable_appearance(S.icon, S.icon_state, -HAIR_LAYER)
- var/mutable_appearance/gradient_overlay
-
- if(!forced_colour)
- if(hair_color)
- if(hair_color == "mutcolor")
- facial_overlay.color = H.dna.features["mcolor"]
- else if(hair_color == "fixedmutcolor")
- facial_overlay.color = fixed_mut_color
- else
- facial_overlay.color = hair_color
- else
- facial_overlay.color = H.facial_hair_color
- //Gradients
- var/grad_style = LAZYACCESS(H.grad_style, GRADIENT_FACIAL_HAIR_KEY)
- if(grad_style)
- var/grad_color = LAZYACCESS(H.grad_color, GRADIENT_FACIAL_HAIR_KEY)
- gradient_overlay = make_gradient_overlay(S.icon, S.icon_state, HAIR_LAYER, GLOB.facial_hair_gradients_list[grad_style], grad_color)
- else
- facial_overlay.color = forced_colour
-
- facial_overlay.alpha = hair_alpha
- facial_overlay.overlays += emissive_blocker(S.icon, S.icon_state, alpha = hair_alpha)
-
- standing += facial_overlay
- if(gradient_overlay)
- standing += gradient_overlay
-
- if(H.head)
- var/obj/item/I = H.head
- if(I.flags_inv & HIDEHAIR)
- hair_hidden = TRUE
-
- if(H.w_uniform)
- var/obj/item/item_uniform = H.w_uniform
- if(item_uniform.flags_inv & HIDEHAIR)
- hair_hidden = TRUE
-
- if(H.wear_mask)
- var/obj/item/I = H.wear_mask
- if(I.flags_inv & HIDEHAIR)
- hair_hidden = TRUE
-
- if(!hair_hidden)
- var/mutable_appearance/hair_overlay = mutable_appearance(layer = -HAIR_LAYER)
- var/mutable_appearance/gradient_overlay
- if(!hair_hidden && !H.getorgan(/obj/item/organ/brain)) //Applies the debrained overlay if there is no brain
- if(!(NOBLOOD in species_traits))
- hair_overlay.icon = 'icons/mob/human_face.dmi'
- hair_overlay.icon_state = "debrained"
-
- else if(H.hairstyle && (HAIR in species_traits))
- S = GLOB.hairstyles_list[H.hairstyle]
- if(S)
- var/hair_state = S.icon_state
- var/hair_file = S.icon
-
- hair_overlay.icon = hair_file
- hair_overlay.icon_state = hair_state
-
- if(!forced_colour)
- if(hair_color)
- if(hair_color == "mutcolor")
- hair_overlay.color = H.dna.features["mcolor"]
- else if(hair_color == "fixedmutcolor")
- hair_overlay.color = fixed_mut_color
- else
- hair_overlay.color = hair_color
- else
- hair_overlay.color = H.hair_color
-
- //Gradients
- var/grad_style = LAZYACCESS(H.grad_style, GRADIENT_HAIR_KEY)
- if(grad_style)
- var/grad_color = LAZYACCESS(H.grad_color, GRADIENT_HAIR_KEY)
- gradient_overlay = make_gradient_overlay(hair_file, hair_state, HAIR_LAYER, GLOB.hair_gradients_list[grad_style], grad_color)
- else
- hair_overlay.color = forced_colour
-
- hair_overlay.alpha = hair_alpha
- if(OFFSET_FACE in H.dna.species.offset_features)
- hair_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
- hair_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
-
- if(hair_overlay.icon)
- hair_overlay.overlays += emissive_blocker(hair_overlay.icon, hair_overlay.icon_state, alpha = hair_alpha)
- standing += hair_overlay
- if(gradient_overlay)
- standing += gradient_overlay
-
- if(standing.len)
- H.overlays_standing[HAIR_LAYER] = standing
-
- H.apply_overlay(HAIR_LAYER)
-
-/datum/species/proc/make_gradient_overlay(file, icon, layer, datum/sprite_accessory/gradient, grad_color)
- var/mutable_appearance/gradient_overlay = mutable_appearance(layer = -layer)
- var/icon/temp = icon(gradient.icon, gradient.icon_state)
- var/icon/temp_hair = icon(file, icon)
- temp.Blend(temp_hair, ICON_ADD)
- gradient_overlay.icon = temp
- gradient_overlay.color = grad_color
- return gradient_overlay
-
/**
* Handles the body of a human
*
@@ -753,27 +608,27 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/datum/sprite_accessory/markings = GLOB.moth_markings_list[species_human.dna.features["moth_markings"]]
if(!HAS_TRAIT(species_human, TRAIT_HUSK))
- if(noggin && (noggin.status != BODYPART_ROBOTIC))
+ if(noggin && (IS_ORGANIC_LIMB(noggin)))
var/mutable_appearance/markings_head_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_head", -BODY_LAYER)
standing += markings_head_overlay
- if(chest && (chest.status != BODYPART_ROBOTIC))
+ if(chest && (IS_ORGANIC_LIMB(chest)))
var/mutable_appearance/markings_chest_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_chest", -BODY_LAYER)
standing += markings_chest_overlay
- if(right_arm && (right_arm.status != BODYPART_ROBOTIC))
+ if(right_arm && (IS_ORGANIC_LIMB(right_arm)))
var/mutable_appearance/markings_r_arm_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_r_arm", -BODY_LAYER)
standing += markings_r_arm_overlay
- if(left_arm && (left_arm.status != BODYPART_ROBOTIC))
+ if(left_arm && (IS_ORGANIC_LIMB(left_arm)))
var/mutable_appearance/markings_l_arm_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_l_arm", -BODY_LAYER)
standing += markings_l_arm_overlay
- if(right_leg && (right_leg.status != BODYPART_ROBOTIC))
+ if(right_leg && (IS_ORGANIC_LIMB(right_leg)))
var/mutable_appearance/markings_r_leg_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_r_leg", -BODY_LAYER)
standing += markings_r_leg_overlay
- if(left_leg && (left_leg.status != BODYPART_ROBOTIC))
+ if(left_leg && (IS_ORGANIC_LIMB(left_leg)))
var/mutable_appearance/markings_l_leg_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_l_leg", -BODY_LAYER)
standing += markings_l_leg_overlay
@@ -783,7 +638,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/datum/sprite_accessory/underwear/underwear = GLOB.underwear_list[species_human.underwear]
var/mutable_appearance/underwear_overlay
if(underwear)
- if(species_human.dna.species.sexes && species_human.body_type == FEMALE && (underwear.gender == MALE))
+ if(species_human.dna.species.sexes && species_human.physique == FEMALE && (underwear.gender == MALE))
underwear_overlay = wear_female_version(underwear.icon_state, underwear.icon, BODY_LAYER, FEMALE_UNIFORM_FULL)
else
underwear_overlay = mutable_appearance(underwear.icon, underwear.icon_state, -BODY_LAYER)
@@ -794,12 +649,12 @@ GLOBAL_LIST_EMPTY(features_by_species)
if(species_human.undershirt)
var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[species_human.undershirt]
if(undershirt)
- if(species_human.dna.species.sexes && species_human.body_type == FEMALE)
+ if(species_human.dna.species.sexes && species_human.physique == FEMALE)
standing += wear_female_version(undershirt.icon_state, undershirt.icon, BODY_LAYER)
else
standing += mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER)
- if(species_human.socks && species_human.num_legs >= 2 && !(DIGITIGRADE in species_traits))
+ if(species_human.socks && species_human.num_legs >= 2 && !(src.bodytype & BODYTYPE_DIGITIGRADE))
var/datum/sprite_accessory/socks/socks = GLOB.socks_list[species_human.socks]
if(socks)
standing += mutable_appearance(socks.icon, socks.icon_state, -BODY_LAYER)
@@ -873,36 +728,13 @@ GLOBAL_LIST_EMPTY(features_by_species)
bodyparts_to_add -= "waggingspines"
if(mutant_bodyparts["ears"])
- if(!source.dna.features["ears"] || source.dna.features["ears"] == "None" || source.head && (source.head.flags_inv & HIDEHAIR) || (source.wear_mask && (source.wear_mask.flags_inv & HIDEHAIR)) || !noggin || noggin.status == BODYPART_ROBOTIC)
+ if(!source.dna.features["ears"] || source.dna.features["ears"] == "None" || source.head && (source.head.flags_inv & HIDEHAIR) || (source.wear_mask && (source.wear_mask.flags_inv & HIDEHAIR)) || !noggin || !IS_ORGANIC_LIMB(noggin))
bodyparts_to_add -= "ears"
- //Digitigrade legs are stuck in the phantom zone between true limbs and mutant bodyparts. Mainly it just needs more aggressive updating than most limbs.
- var/update_needed = FALSE
- var/not_digitigrade = TRUE
- for(var/obj/item/bodypart/bodypart as anything in source.bodyparts)
- if(!bodypart.use_digitigrade)
- continue
- not_digitigrade = FALSE
- if(!(DIGITIGRADE in species_traits)) //Someone cut off a digitigrade leg and tacked it on
- species_traits += DIGITIGRADE
- var/should_be_squished = FALSE
- if(source.wear_suit && ((source.wear_suit.flags_inv & HIDEJUMPSUIT) || (source.wear_suit.body_parts_covered & LEGS)) || (source.w_uniform && (source.w_uniform.body_parts_covered & LEGS)))
- should_be_squished = TRUE
- if(bodypart.use_digitigrade == FULL_DIGITIGRADE && should_be_squished)
- bodypart.use_digitigrade = SQUISHED_DIGITIGRADE
- update_needed = TRUE
- else if(bodypart.use_digitigrade == SQUISHED_DIGITIGRADE && !should_be_squished)
- bodypart.use_digitigrade = FULL_DIGITIGRADE
- update_needed = TRUE
- if(update_needed)
- source.update_body_parts()
- if(not_digitigrade && (DIGITIGRADE in species_traits)) //Curse is lifted
- species_traits -= DIGITIGRADE
-
if(!bodyparts_to_add)
return
- var/g = (source.body_type == FEMALE) ? "f" : "m"
+ var/g = (source.physique == FEMALE) ? "f" : "m"
for(var/layer in relevent_layers)
var/layertext = mutant_bodyparts_layertext(layer)
@@ -1106,17 +938,18 @@ GLOBAL_LIST_EMPTY(features_by_species)
if(ITEM_SLOT_FEET)
if(H.num_legs < 2)
return FALSE
- /* SKYRAT EDIT REMOVAL - Digitigrade legs are functional too ;)
- if((DIGITIGRADE in species_traits) && !(I.item_flags & IGNORE_DIGITIGRADE))
- if(!disable_warning)
- to_chat(H, span_warning("The footwear around here isn't compatible with your feet!"))
- return FALSE
- */ // SKYRAT EDIT END
+ /* SKYRAT EDIT REMOVAL
+ if((bodytype & BODYTYPE_DIGITIGRADE) && !(I.item_flags & IGNORE_DIGITIGRADE))
+ if(!(I.supports_variations_flags & (CLOTHING_DIGITIGRADE_VARIATION|CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON)))
+ if(!disable_warning)
+ to_chat(H, span_warning("The footwear around here isn't compatible with your feet!"))
+ return FALSE
+ */
return equip_delay_self_check(I, H, bypass_equip_delay_self)
if(ITEM_SLOT_BELT)
var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_CHEST)
- if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
+ if(!H.w_uniform && !nojumpsuit && (!O || IS_ORGANIC_LIMB(O)))
if(!disable_warning)
to_chat(H, span_warning("You need a jumpsuit before you can attach this [I.name]!"))
return FALSE
@@ -1140,7 +973,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
return equip_delay_self_check(I, H, bypass_equip_delay_self)
if(ITEM_SLOT_ID)
var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_CHEST)
- if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
+ if(!H.w_uniform && !nojumpsuit && (!O || IS_ORGANIC_LIMB(O)))
if(!disable_warning)
to_chat(H, span_warning("You need a jumpsuit before you can attach this [I.name]!"))
return FALSE
@@ -1153,7 +986,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_L_LEG)
- if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
+ if(!H.w_uniform && !nojumpsuit && (!O || IS_ORGANIC_LIMB(O)))
if(!disable_warning)
to_chat(H, span_warning("You need a jumpsuit before you can attach this [I.name]!"))
return FALSE
@@ -1166,7 +999,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_R_LEG)
- if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
+ if(!H.w_uniform && !nojumpsuit && (!O || IS_ORGANIC_LIMB(O)))
if(!disable_warning)
to_chat(H, span_warning("You need a jumpsuit before you can attach this [I.name]!"))
return FALSE
@@ -1522,7 +1355,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/bloody = FALSE
if(((I.damtype == BRUTE) && I.force && prob(25 + (I.force * 2))))
- if(affecting.status == BODYPART_ORGANIC)
+ if(IS_ORGANIC_LIMB(affecting))
I.add_mob_blood(H) //Make the weapon bloody, not the person.
if(prob(I.force * 2)) //blood spatter!
bloody = TRUE
@@ -2178,7 +2011,8 @@ GLOBAL_LIST_EMPTY(features_by_species)
wings_icon = pick(wings_icons)
else
wings_icon = wings_icons[1]
- var/obj/item/organ/external/wings/functional/wings = new(null, wings_icon, H.body_type)
+
+ var/obj/item/organ/external/wings/functional/wings = new(null, wings_icon, H.physique)
// SKYRAT EDIT START - Fixes the loss of wings to just run the insert twice
if(H.getorganslot(ORGAN_SLOT_EXTERNAL_WINGS))
wings.Insert(H)
@@ -2199,18 +2033,6 @@ GLOBAL_LIST_EMPTY(features_by_species)
/datum/species/proc/spec_unarmedattack(mob/living/carbon/human/user, atom/target, modifiers)
return FALSE
-
-///Removes any non-native limbs from the mob
-/datum/species/proc/fix_non_native_limbs(mob/living/carbon/human/H)
- for(var/X in H.bodyparts)
- var/obj/item/bodypart/current_part = X
- var/obj/item/bodypart/species_part = bodypart_overides[current_part.body_zone]
-
- if(current_part.type == species_part)
- continue
-
- current_part.change_bodypart(species_part)
-
/* SKYRAT EDIT REMOVAL - MOVED TO MODULAR
/// Returns a list of strings representing features this species has.
/// Used by the preferences UI to know what buttons to show.
@@ -2239,6 +2061,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
return features
*/
+
/// Given a human, will adjust it before taking a picture for the preferences UI.
/// This should create a CONSISTENT result, so the icons don't randomly change.
/datum/species/proc/prepare_human_for_preview(mob/living/carbon/human/human)
@@ -2646,3 +2469,28 @@ GLOBAL_LIST_EMPTY(features_by_species)
qdel(temp_holder)
return to_add
+
+///Handles replacing all of the bodyparts with their species version during set_species()
+/datum/species/proc/replace_body(mob/living/carbon/target, datum/species/new_species)
+ new_species ||= target.dna.species //If no new species is provided, assume its src.
+ //Note for future: Potentionally add a new C.dna.species() to build a template species for more accurate limb replacement
+
+ if((new_species.digitigrade_customization == DIGITIGRADE_OPTIONAL && target.dna.features["legs"] == "Digitigrade Legs") || new_species.digitigrade_customization == DIGITIGRADE_FORCED)
+ var/obj/item/bodypart/r_leg/r_leg = new_species.bodypart_overrides[BODY_ZONE_R_LEG]
+ if(r_leg)
+ new_species.bodypart_overrides[BODY_ZONE_R_LEG] = initial(r_leg.digitigrade_type)
+ var/obj/item/bodypart/l_leg/l_leg = new_species.bodypart_overrides[BODY_ZONE_L_LEG]
+ if(l_leg)
+ new_species.bodypart_overrides[BODY_ZONE_L_LEG] = initial(l_leg.digitigrade_type)
+
+ for(var/obj/item/bodypart/old_part as anything in target.bodyparts)
+ if(old_part.change_exempt_flags & BP_BLOCK_CHANGE_SPECIES)
+ continue
+
+ var/path = new_species.bodypart_overrides?[old_part.body_zone]
+ var/obj/item/bodypart/new_part
+ if(path)
+ new_part = new path()
+ new_part.replace_limb(target, TRUE)
+ new_part.update_limb(is_creating = TRUE)
+ qdel(old_part)
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 aa148fc3e07..a248ce1e338 100644
--- a/code/modules/mob/living/carbon/human/species_types/abductors.dm
+++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm
@@ -16,6 +16,15 @@
changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
ass_image = 'icons/ass/assgrey.png'
+ bodypart_overrides = list(
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/abductor,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/abductor,
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/abductor,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/abductor,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/abductor,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/abductor,
+ )
+
/datum/species/abductor/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
var/datum/atom_hud/abductor_hud = GLOB.huds[DATA_HUD_ABDUCTOR]
diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm
index 34bd408dffa..3735838029d 100644
--- a/code/modules/mob/living/carbon/human/species_types/android.dm
+++ b/code/modules/mob/living/carbon/human/species_types/android.dm
@@ -24,28 +24,41 @@
)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
meat = null
- damage_overlay_type = SPECIES_SYNTH
+ damage_overlay_type = "synth"
mutanttongue = /obj/item/organ/tongue/robot
species_language_holder = /datum/language_holder/synthetic
- limbs_id = SPECIES_SYNTH
wings_icons = list("Robotic")
changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
+ bodypart_overrides = list(
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/robot,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/robot,
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/robot,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/robot,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/robot,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/robot,
+ )
+ examine_limb_id = SPECIES_HUMAN
+
/datum/species/android/on_species_gain(mob/living/carbon/C)
. = ..()
- for(var/X in C.bodyparts)
- var/obj/item/bodypart/O = X
- O.change_bodypart_status(BODYPART_ROBOTIC, FALSE, TRUE)
- O.brute_reduction = 5
- O.burn_reduction = 4
-
// Androids don't eat, hunger or metabolise foods. Let's do some cleanup.
C.set_safe_hunger_level()
-/datum/species/android/on_species_loss(mob/living/carbon/C)
+/datum/species/android/replace_body(mob/living/carbon/target, datum/species/new_species)
. = ..()
- for(var/X in C.bodyparts)
- var/obj/item/bodypart/O = X
- O.change_bodypart_status(BODYPART_ORGANIC,FALSE, TRUE)
- O.brute_reduction = initial(O.brute_reduction)
- O.burn_reduction = initial(O.burn_reduction)
+ var/skintone
+ if(ishuman(target))
+ var/mob/living/carbon/human/human_target = target
+ skintone = human_target.skin_tone
+
+ for(var/obj/item/bodypart/limb as anything in target.bodyparts)
+ if(limb.body_zone == BODY_ZONE_HEAD || limb.body_zone == BODY_ZONE_CHEST)
+ limb.is_dimorphic = TRUE
+ limb.skin_tone ||= skintone
+ limb.limb_id = SPECIES_HUMAN
+ limb.should_draw_greyscale = TRUE
+ limb.name = "human [parse_zone(limb.body_zone)]"
+ limb.update_limb()
+ limb.brute_reduction = 5
+ limb.burn_reduction = 4
diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
index 4e270434143..306a3c02a2d 100644
--- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm
+++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
@@ -16,7 +16,7 @@
mutanteyes = /obj/item/organ/eyes/dullahan
mutanttongue = /obj/item/organ/tongue/dullahan
mutantears = /obj/item/organ/ears/dullahan
- limbs_id = SPECIES_HUMAN
+ examine_limb_id = SPECIES_HUMAN
skinned_type = /obj/item/stack/sheet/animalhide/human
changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | ERT_SPAWN
@@ -38,7 +38,6 @@
var/obj/item/bodypart/head/head = human.get_bodypart(BODY_ZONE_HEAD)
if(head)
- head.no_update = TRUE
head.drop_limb()
if(!QDELETED(head)) //drop_limb() deletes the limb if no drop location exists and character setup dummies are located in nullspace.
diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
index add9c4ed0ce..e4a97328772 100644
--- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
@@ -1,5 +1,5 @@
/datum/species/ethereal
- name = "Ethereal"
+ name = "\improper Ethereal"
id = SPECIES_ETHEREAL
attack_verb = "burn"
attack_sound = 'sound/weapons/etherealhit.ogg'
@@ -28,6 +28,15 @@
hair_color = "fixedmutcolor"
hair_alpha = 140
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/ethereal,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/ethereal,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/ethereal,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/ethereal,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/ethereal,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/ethereal,
+ )
+
var/current_color
var/EMPeffect = FALSE
var/emageffect = FALSE
@@ -66,6 +75,12 @@
var/obj/item/organ/heart/ethereal/ethereal_heart = C.getorganslot(ORGAN_SLOT_HEART)
ethereal_heart.ethereal_color = default_color
+ //The following code is literally only to make admin-spawned ethereals not be black.
+ C.dna.features["mcolor"] = C.dna.features["ethcolor"] //Ethcolor and Mut color are both dogshit and i hate them
+ for(var/obj/item/bodypart/limb as anything in C.bodyparts)
+ if(limb.limb_id == SPECIES_ETHEREAL)
+ limb.update_limb(is_creating = TRUE)
+
/datum/species/ethereal/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load)
UnregisterSignal(C, COMSIG_ATOM_EMAG_ACT)
UnregisterSignal(C, COMSIG_ATOM_EMP_ACT)
@@ -85,6 +100,9 @@
/datum/species/ethereal/spec_updatehealth(mob/living/carbon/human/H)
. = ..()
+ if(!ethereal_light)
+ return
+
if(H.stat != DEAD && !EMPeffect)
var/healthpercent = max(H.health, 0) / 100
if(!emageffect)
@@ -95,8 +113,7 @@
else
ethereal_light.set_light_on(FALSE)
fixed_mut_color = rgb(128,128,128)
- H.update_body()
- H.update_hair() // This should fix the ethereal hair not changing with body, no clue as to why hair is not in update_body but okay
+ H.update_body(is_creating = TRUE)
/datum/species/ethereal/proc/on_emp_act(mob/living/carbon/human/H, severity)
SIGNAL_HANDLER
diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm
index 336d5f0897c..9bb15355512 100644
--- a/code/modules/mob/living/carbon/human/species_types/felinid.dm
+++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm
@@ -3,7 +3,6 @@
name = "Felinid"
id = SPECIES_FELINE
say_mod = "meows"
- limbs_id = SPECIES_HUMAN
mutant_bodyparts = list("tail_human" = "Cat", "ears" = "Cat", "wings" = "None")
@@ -17,6 +16,7 @@
payday_modifier = 0.75
ass_image = 'icons/ass/asscat.png'
family_heirlooms = list(/obj/item/toy/cattoy)
+ examine_limb_id = SPECIES_HUMAN
// Prevents felinids from taking toxin damage from carpotoxin
/datum/species/human/felinid/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, delta_time, times_fired)
diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
index 2cee066e36e..7b130210bbd 100644
--- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
@@ -1,7 +1,7 @@
/datum/species/fly
name = "Flyperson"
plural_form = "Flypeople"
- id = SPECIES_FLY
+ id = SPECIES_FLYPERSON
say_mod = "buzzes"
species_traits = list(HAS_FLESH, HAS_BONE, TRAIT_ANTENNAE, HAIR, FACEHAIR) //SKYRAT EDIT - gives flypeople hair
inherent_traits = list(
@@ -27,6 +27,15 @@
mutantappendix = /obj/item/organ/appendix/fly
mutant_organs = list(/obj/item/organ/fly, /obj/item/organ/fly/groin)
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/fly,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/fly,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/fly,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/fly,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/fly,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/fly,
+ )
+
/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, delta_time, times_fired)
if(chem.type == /datum/reagent/toxin/pestkiller)
H.adjustToxLoss(3 * REAGENTS_EFFECT_MULTIPLIER * delta_time)
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 0f4d4629cb5..05518cee211 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -36,8 +36,17 @@
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
- limbs_id = "golem"
fixed_mut_color = "#aaaaaa"
+
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/golem,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/golem,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/golem,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/golem,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/golem,
+ 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
@@ -101,6 +110,7 @@
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)
..()
@@ -135,6 +145,7 @@
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
@@ -192,6 +203,7 @@
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
@@ -204,6 +216,7 @@
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
@@ -215,6 +228,7 @@
info_text = "As a Silver Golem, your attacks have a higher chance of stunning. Being made of silver, your body is immune to most types of magic."
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)
..()
@@ -241,6 +255,7 @@
attack_sound = 'sound/effects/meteorimpact.ogg' //hits pretty hard
prefix = "Plasteel"
special_names = null
+ examine_limb_id = SPECIES_GOLEM
/datum/species/golem/plasteel/negates_gravity(mob/living/carbon/human/H)
return TRUE
@@ -263,6 +278,7 @@
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)
. = ..()
@@ -282,6 +298,7 @@
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)
. = ..()
@@ -304,12 +321,13 @@
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, delta_time, times_fired)
if(H.stat == DEAD)
return
- H.heal_overall_damage(1 * delta_time, 1 * delta_time, 0, BODYPART_ORGANIC)
+ H.heal_overall_damage(1 * delta_time, 1 * delta_time, 0, BODYTYPE_ORGANIC)
H.adjustToxLoss(-1 * delta_time)
H.adjustOxyLoss(-1 * delta_time)
@@ -343,6 +361,7 @@
human_surname_chance = 0
special_name_chance = 100
inherent_factions = list("plants", "vines")
+ examine_limb_id = SPECIES_GOLEM
/datum/species/golem/wood/spec_life(mob/living/carbon/human/H, delta_time, times_fired)
if(H.stat == DEAD)
@@ -355,7 +374,7 @@
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(0.5 * delta_time, 0.5 * delta_time, 0, BODYPART_ORGANIC)
+ H.heal_overall_damage(0.5 * delta_time, 0.5 * delta_time, 0, BODYTYPE_ORGANIC)
H.adjustToxLoss(-0.5 * delta_time)
H.adjustOxyLoss(-0.5 * delta_time)
@@ -388,6 +407,7 @@
prefix = "Uranium"
special_names = list("Oxide", "Rod", "Meltdown", "235")
COOLDOWN_DECLARE(radiation_emission_cooldown)
+ examine_limb_id = SPECIES_GOLEM
/datum/species/golem/uranium/proc/radiation_emission(mob/living/carbon/human/H)
if(!COOLDOWN_FINISHED(src, radiation_emission_cooldown))
@@ -424,6 +444,7 @@
attack_sound = 'sound/effects/shovel_dig.ogg'
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!"))
@@ -455,6 +476,7 @@
attack_sound = 'sound/effects/glassbr2.ogg'
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)
@@ -490,6 +512,7 @@
attack_sound = 'sound/effects/phasein.ogg'
prefix = "Bluespace"
special_names = list("Crystal", "Polycrystal")
+ examine_limb_id = SPECIES_GOLEM
var/datum/action/innate/unstable_teleport/unstable_teleport
var/teleport_cooldown = 100
@@ -605,6 +628,7 @@
attack_sound = 'sound/items/airhorn2.ogg'
prefix = "Bananium"
special_names = null
+ examine_limb_id = SPECIES_GOLEM
/// Cooldown for producing honks
COOLDOWN_DECLARE(honkooldown)
@@ -684,7 +708,6 @@
/datum/species/golem/runic
name = "Runic Golem"
id = SPECIES_GOLEM_CULT
- limbs_id = "cultgolem"
sexes = FALSE
info_text = "As a Runic Golem, you possess eldritch powers granted by the Elder Goddess Nar'Sie."
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYESPRITES) //no mutcolors
@@ -709,6 +732,15 @@
special_names = null
inherent_factions = list("cult")
species_language_holder = /datum/language_holder/golem/runic
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/golem/cult,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/golem/cult,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/golem/cult,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/golem/cult,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/golem/cult,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem/cult,
+ )
+
var/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/golem/phase_shift
var/obj/effect/proc_holder/spell/pointed/abyssal_gaze/abyssal_gaze
var/obj/effect/proc_holder/spell/pointed/dominate/dominate
@@ -753,7 +785,6 @@
/datum/species/golem/cloth
name = "Cloth Golem"
id = SPECIES_GOLEM_CLOTH
- limbs_id = "clothgolem"
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 magic resistant and faster than that of other golems, but weaker and less resilient."
@@ -780,6 +811,14 @@
punchdamagehigh = 8 // not as heavy as stone
prefix = "Cloth"
special_names = null
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/golem/cloth,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/golem/cloth,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/golem/cloth,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/golem/cloth,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/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)
..()
@@ -942,6 +981,7 @@
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"
@@ -952,6 +992,7 @@
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/ears/bronze
+ examine_limb_id = SPECIES_GOLEM
var/last_gong_time = 0
var/gong_cooldown = 150
@@ -1033,7 +1074,6 @@
TRAIT_NODISMEMBER,
TRAIT_NOFLASH,
)
- limbs_id = "c_golem" //special sprites
attack_verb = "whips"
attack_sound = 'sound/weapons/whip.ogg'
miss_sound = 'sound/weapons/etherealmiss.ogg'
@@ -1045,6 +1085,14 @@
punchdamagelow = 4
punchstunthreshold = 7
punchdamagehigh = 8
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/golem/cardboard,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/golem/cardboard,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/golem/cardboard,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/golem/cardboard,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/golem/cardboard,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem/cardboard,
+ )
var/last_creation = 0
var/brother_creation_cooldown = 300
@@ -1096,12 +1144,11 @@
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'
attack_sound = 'sound/weapons/whip.ogg'
-
+ examine_limb_id = SPECIES_GOLEM
/datum/species/golem/durathread
name = "Durathread Golem"
id = SPECIES_GOLEM_DURATHREAD
prefix = "Durathread"
- limbs_id = "d_golem"
special_names = list("Boll","Weave")
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYESPRITES)
fixed_mut_color = null
@@ -1120,6 +1167,14 @@
TRAIT_NOFLASH,
)
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/l_arm/golem/durathread,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/golem/durathread,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/golem/durathread,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/golem/durathread,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/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)
. = ..()
@@ -1130,7 +1185,6 @@
id = SPECIES_GOLEM_BONE
say_mod = "rattles"
prefix = "Bone"
- limbs_id = "b_golem"
special_names = list("Head", "Broth", "Fracture", "Rattler", "Appetit")
liked_food = GROSS | MEAT | RAW
toxic_food = null
@@ -1159,6 +1213,14 @@
)
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/l_arm/golem/bone,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/golem/bone,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/golem/bone,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/golem/bone,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/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)
@@ -1238,7 +1300,6 @@
/datum/species/golem/snow
name = "Snow Golem"
id = SPECIES_GOLEM_SNOW
- limbs_id = "sn_golem"
fixed_mut_color = null //custom sprites
armor = 45 //down from 55
burnmod = 3 //melts easily
@@ -1259,7 +1320,14 @@
TRAIT_PIERCEIMMUNE,
TRAIT_NODISMEMBER,
)
-
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/golem/snow,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/golem/snow,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/golem/snow,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/golem/snow,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/golem/snow,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/golem/snow,
+ )
var/obj/effect/proc_holder/spell/targeted/conjure_item/snowball/ball
var/obj/effect/proc_holder/spell/aimed/cryo/cryo
@@ -1318,6 +1386,7 @@
TRAIT_NODISMEMBER,
TRAIT_CHUNKYFINGERS,
)
+ examine_limb_id = SPECIES_GOLEM
/datum/species/golem/mhydrogen/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm
index 271bd95c5c6..85f66b89c6f 100644
--- a/code/modules/mob/living/carbon/human/species_types/humans.dm
+++ b/code/modules/mob/living/carbon/human/species_types/humans.dm
@@ -1,5 +1,5 @@
/datum/species/human
- name = "Human"
+ name = "\improper Human"
id = SPECIES_HUMAN
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE)
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index 50fafad6429..8a1ca020a5a 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -1,6 +1,6 @@
/datum/species/jelly
// Entirely alien beings that seem to be made entirely out of gel. They have three eyes and a skeleton visible within them.
- name = "Jellyperson"
+ name = "\improper Jellyperson"
plural_form = "Jellypeople"
id = SPECIES_JELLYPERSON
default_color = "00FF90"
@@ -28,24 +28,35 @@
species_language_holder = /datum/language_holder/jelly
ass_image = 'icons/ass/assslime.png'
-/datum/species/jelly/on_species_loss(mob/living/carbon/C)
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/jelly,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/jelly,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/jelly,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/jelly,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/jelly,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/jelly,
+ )
+
+/datum/species/jelly/on_species_loss(mob/living/carbon/old_jellyperson)
if(regenerate_limbs)
- regenerate_limbs.Remove(C)
+ regenerate_limbs.Remove(old_jellyperson)
//SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION
if(slime_change)
- slime_change.Remove(C)
+ slime_change.Remove(old_jellyperson)
//SKYRAT EDIT ADDITION END
+ old_jellyperson.RemoveElement(/datum/element/soft_landing)
..()
-/datum/species/jelly/on_species_gain(mob/living/carbon/C, datum/species/old_species)
+/datum/species/jelly/on_species_gain(mob/living/carbon/new_jellyperson, datum/species/old_species)
..()
- if(ishuman(C))
+ if(ishuman(new_jellyperson))
regenerate_limbs = new
- regenerate_limbs.Grant(C)
+ regenerate_limbs.Grant(new_jellyperson)
//SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION
slime_change = new
- slime_change.Grant(C)
+ slime_change.Grant(new_jellyperson)
//SKYRAT EDIT ADDITION END
+ new_jellyperson.AddElement(/datum/element/soft_landing)
/datum/species/jelly/spec_life(mob/living/carbon/human/H, delta_time, times_fired)
if(H.stat == DEAD) //can't farm slime jelly from a dead slime/jelly person indefinitely
@@ -145,7 +156,7 @@
//Slime people are able to split like slimes, retaining a single mind that can swap between bodies at will, even after death.
/datum/species/jelly/slime
- name = "Slimeperson"
+ name = "\improper Slimeperson"
plural_form = "Slimepeople"
id = SPECIES_SLIMEPERSON
default_color = "00FFFF"
@@ -157,6 +168,15 @@
var/list/mob/living/carbon/bodies
var/datum/action/innate/swap_body/swap_body
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/slime,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/slime,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/slime,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/slime,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/slime,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/slime,
+ )
+
/datum/species/jelly/slime/on_species_loss(mob/living/carbon/C)
if(slime_split)
slime_split.Remove(C)
@@ -434,6 +454,7 @@
name = "Luminescent"
plural_form = null
id = SPECIES_LUMINESCENT
+ examine_limb_id = SPECIES_JELLYPERSON
var/glow_intensity = LUMINESCENT_DEFAULT_GLOW
var/obj/effect/dummy/luminescent_glow/glow
var/obj/item/slime_extract/current_extract
@@ -442,6 +463,7 @@
var/datum/action/innate/use_extract/major/extract_major
var/extract_cooldown = 0
+
//Species datums don't normally implement destroy, but JELLIES SUCK ASS OUT OF A STEEL STRAW
/datum/species/jelly/luminescent/Destroy(force, ...)
current_extract = null
@@ -614,9 +636,10 @@
//Stargazers are the telepathic branch of jellypeople, able to project psychic messages and to link minds with willing participants.
/datum/species/jelly/stargazer
- name = "Stargazer"
+ name = "\improper Stargazer"
plural_form = null
id = SPECIES_STARGAZER
+ examine_limb_id = SPECIES_JELLYPERSON
/// Special "project thought" telepathy action for stargazers.
var/datum/action/innate/project_thought/project_action
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 3efa5400fe8..1ae0b8d792b 100644
--- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
@@ -1,6 +1,6 @@
/datum/species/lizard
// Reptilian humanoids with scaled skin and tails.
- name = "Lizardperson"
+ name = "\improper Lizardperson"
plural_form = "Lizardfolk"
id = SPECIES_LIZARD
say_mod = "hisses"
@@ -35,12 +35,23 @@
deathsound = 'sound/voice/lizard/deathsound.ogg'
wings_icons = list("Dragon")
species_language_holder = /datum/language_holder/lizard
+ 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_cold_damage_limit = (BODYTEMP_COLD_DAMAGE_LIMIT - 10)
ass_image = 'icons/ass/asslizard.png'
+ bodypart_overrides = list(
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/lizard,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/lizard,
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/lizard,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/lizard,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/lizard,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/lizard,
+ )
+
/// Lizards are cold blooded and do not stabilize body temperature naturally
/datum/species/lizard/body_temperature_core(mob/living/carbon/human/humi, delta_time, times_fired)
return
@@ -177,8 +188,7 @@ Lizard subspecies: ASHWALKERS
/datum/species/lizard/ashwalker
name = "Ash Walker"
id = SPECIES_LIZARD_ASH
- limbs_id = SPECIES_LIZARD
- species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE,HAS_FLESH,HAS_BONE)
+ species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAS_FLESH,HAS_BONE)
mutantlungs = /obj/item/organ/lungs/ashwalker
inherent_traits = list(
TRAIT_ADVANCEDTOOLUSER,
@@ -187,14 +197,14 @@ Lizard subspecies: ASHWALKERS
TRAIT_VIRUSIMMUNE,
)
species_language_holder = /datum/language_holder/lizard/ash
-
+ digitigrade_customization = DIGITIGRADE_FORCED
+ examine_limb_id = SPECIES_LIZARD
/*
Lizard subspecies: SILVER SCALED
*/
/datum/species/lizard/silverscale
name = "Silver Scale"
id = SPECIES_LIZARD_SILVER
- limbs_id = SPECIES_LIZARD
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE
inherent_traits = list(
TRAIT_ADVANCEDTOOLUSER,
@@ -211,6 +221,7 @@ Lizard subspecies: SILVER SCALED
mutanttongue = /obj/item/organ/tongue/lizard //SKYRAT EDIT CHANGE
armor = 10 //very light silvery scales soften blows
changesource_flags = MIRROR_BADMIN | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN
+ examine_limb_id = SPECIES_LIZARD
///stored mutcolor for when we turn back off of a silverscale.
var/old_mutcolor
///stored eye color for when we turn back off of a silverscale.
diff --git a/code/modules/mob/living/carbon/human/species_types/monkeys.dm b/code/modules/mob/living/carbon/human/species_types/monkeys.dm
index c882dd56395..40063c834ce 100644
--- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm
+++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm
@@ -2,6 +2,7 @@
name = "Monkey"
id = SPECIES_MONKEY
say_mod = "chimpers"
+ bodytype = BODYTYPE_ORGANIC | BODYTYPE_MONKEY
attack_verb = "bite"
attack_effect = ATTACK_EFFECT_BITE
attack_sound = 'sound/weapons/bite.ogg'
@@ -10,7 +11,6 @@
mutant_bodyparts = list("tail_monkey" = "Monkey")
skinned_type = /obj/item/stack/sheet/animalhide/monkey
meat = /obj/item/food/meat/slab/monkey
- allowed_animal_origin = MONKEY_BODY
knife_butcher_results = list(/obj/item/food/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
species_traits = list(
HAS_FLESH,
@@ -39,14 +39,14 @@
changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | ERT_SPAWN | SLIME_EXTRACT
liked_food = MEAT | FRUIT
disliked_food = CLOTH
- limbs_id = SPECIES_MONKEY
- damage_overlay_type = SPECIES_MONKEY
+ damage_overlay_type = "monkey"
sexes = FALSE
punchdamagelow = 1
punchdamagehigh = 3
punchstunthreshold = 4 // no stun punches
species_language_holder = /datum/language_holder/monkey
- bodypart_overides = list(
+
+ bodypart_overrides = list(
BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/monkey,
BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/monkey,
BODY_ZONE_HEAD = /obj/item/bodypart/head/monkey,
diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm
index 8e533aa2c71..abb1fb4e85c 100644
--- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm
@@ -1,5 +1,5 @@
/datum/species/moth
- name = "Mothman"
+ name = "\improper Mothman"
plural_form = "Mothmen"
id = SPECIES_MOTH
say_mod = "flutters"
@@ -29,6 +29,15 @@
payday_modifier = 0.75
family_heirlooms = list(/obj/item/flashlight/lantern/heirloom_moth)
+ bodypart_overrides = list(
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/moth,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/moth,
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/moth,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/moth,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/moth,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/moth,
+ )
+
/datum/species/moth/regenerate_organs(mob/living/carbon/C, datum/species/old_species, replace_current= TRUE, list/excluded_zones, visual_only)
. = ..()
if(ishuman(C))
diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
index ebcca4c6389..a6daaf13c0f 100644
--- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
@@ -34,6 +34,15 @@
var/datum/martial_art/mushpunch/mush
species_language_holder = /datum/language_holder/mushroom
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/mushroom,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/mushroom,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/mushroom,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/mushroom,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/mushroom,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/mushroom,
+ )
+
/datum/species/mush/check_roundstart_eligible()
return FALSE //hard locked out of roundstart on the order of design lead kor, this can be removed in the future when planetstation is here OR SOMETHING but right now we have a problem with races.
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 f7d2c974b7a..5d34c91b2b3 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -1,5 +1,5 @@
/datum/species/plasmaman
- name = "Plasmaman"
+ name = "\improper Plasmaman"
plural_form = "Plasmamen"
id = SPECIES_PLASMAMAN
say_mod = "rattles"
@@ -34,6 +34,15 @@
outfit_important_for_life = /datum/outfit/plasmaman
species_language_holder = /datum/language_holder/skeleton
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/plasmaman,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/plasmaman,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/plasmaman,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/plasmaman,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/plasmaman,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/plasmaman,
+ )
+
// Body temperature for Plasmen is much lower human as they can handle colder environments
bodytemp_normal = (BODYTEMP_NORMAL - 40)
// The minimum amount they stabilize per tick is reduced making hot areas harder to deal with
@@ -56,7 +65,7 @@
var/atmos_sealed = CanIgniteMob(H) && (isclothing(H.wear_suit) && H.wear_suit.clothing_flags & STOPSPRESSUREDAMAGE) && (isclothing(H.head) && H.head.clothing_flags & STOPSPRESSUREDAMAGE)
var/flammable_limb = FALSE
for(var/obj/item/bodypart/found_bodypart as anything in H.bodyparts)//If any plasma based limb is found the plasmaman will attempt to autoignite
- if(found_bodypart.status == BODYPART_ORGANIC && (found_bodypart.species_id == SPECIES_PLASMAMAN || HAS_TRAIT(found_bodypart, TRAIT_PLASMABURNT))) //Allows for "donated" limbs and augmented limbs to prevent autoignition
+ if(IS_ORGANIC_LIMB(found_bodypart) && (found_bodypart.limb_id == SPECIES_PLASMAMAN || HAS_TRAIT(found_bodypart, TRAIT_PLASMABURNT))) //Allows for "donated" limbs and augmented limbs to prevent autoignition
flammable_limb = TRUE
break
if(!flammable_limb && !H.on_fire) //Allows their suit to attempt to autoextinguish if augged and on fire
diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
index 90197c03099..3e7bf1a6e32 100644
--- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
@@ -1,6 +1,6 @@
/datum/species/pod
// A mutation caused by a human being ressurected in a revival pod. These regain health in light, and begin to wither in darkness.
- name = "Podperson"
+ name = "\improper Podperson"
plural_form = "Podpeople"
id = SPECIES_PODPERSON
default_color = "59CE00"
@@ -29,6 +29,15 @@
changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
species_language_holder = /datum/language_holder/plant
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/pod,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/pod,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/pod,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/pod,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/pod,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/pod,
+ )
+
/datum/species/pod/spec_life(mob/living/carbon/human/H, delta_time, times_fired)
if(H.stat == DEAD)
return
@@ -41,7 +50,7 @@
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(0.5 * delta_time, 0.5 * delta_time, 0, BODYPART_ORGANIC)
+ H.heal_overall_damage(0.5 * delta_time, 0.5 * delta_time, 0, BODYTYPE_ORGANIC)
H.adjustToxLoss(-0.5 * delta_time)
H.adjustOxyLoss(-0.5 * delta_time)
diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
index e1013f5c658..4b905f35aa0 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -18,6 +18,15 @@
mutanteyes = /obj/item/organ/eyes/night_vision
species_language_holder = /datum/language_holder/shadowpeople
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/shadow,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/shadow,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/shadow,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/shadow,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/shadow,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/shadow,
+ )
+
/datum/species/shadow/spec_life(mob/living/carbon/human/H, delta_time, times_fired)
var/turf/T = H.loc
@@ -25,9 +34,9 @@
var/light_amount = T.get_lumcount()
if(light_amount > SHADOW_SPECIES_LIGHT_THRESHOLD) //if there's enough light, start dying
- H.take_overall_damage(0.5 * delta_time, 0.5 * delta_time, 0, BODYPART_ORGANIC)
+ H.take_overall_damage(0.5 * delta_time, 0.5 * delta_time, 0, BODYTYPE_ORGANIC)
else if (light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) //heal in the dark
- H.heal_overall_damage(0.5 * delta_time, 0.5 * delta_time, 0, BODYPART_ORGANIC)
+ H.heal_overall_damage(0.5 * delta_time, 0.5 * delta_time, 0, BODYTYPE_ORGANIC)
/datum/species/shadow/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
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 4e3726d80c3..302f06f052b 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -38,6 +38,15 @@
changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN
species_language_holder = /datum/language_holder/skeleton
+ bodypart_overrides = list(
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/skeleton,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/skeleton,
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/skeleton,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/skeleton,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/skeleton,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/skeleton,
+ )
+
/datum/species/skeleton/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
. = ..()
C.set_safe_hunger_level()
diff --git a/code/modules/mob/living/carbon/human/species_types/snail.dm b/code/modules/mob/living/carbon/human/species_types/snail.dm
index d8c073a5da2..46ff16c832f 100644
--- a/code/modules/mob/living/carbon/human/species_types/snail.dm
+++ b/code/modules/mob/living/carbon/human/species_types/snail.dm
@@ -24,6 +24,15 @@
mutanttongue = /obj/item/organ/tongue/snail
exotic_blood = /datum/reagent/lube
+ bodypart_overrides = list(
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/snail,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/snail,
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/snail,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/snail,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/snail,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/snail
+ )
+
/datum/species/snail/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, delta_time, times_fired)
if(istype(chem,/datum/reagent/consumable/salt))
H.adjustFireLoss(2 * REAGENTS_EFFECT_MULTIPLIER * delta_time)
diff --git a/code/modules/mob/living/carbon/human/species_types/synths.dm b/code/modules/mob/living/carbon/human/species_types/synths.dm
deleted file mode 100644
index e295ec520d0..00000000000
--- a/code/modules/mob/living/carbon/human/species_types/synths.dm
+++ /dev/null
@@ -1,142 +0,0 @@
-/datum/species/synth
- name = "Synth" //inherited from the real species, for health scanners and things
- id = SPECIES_SYNTH
- say_mod = "beep boops" //inherited from a user's real species
- sexes = 0
- species_traits = list(NOTRANSSTING, NO_DNA_COPY) //all of these + whatever we inherit from the real species
- inherent_traits = list(
- TRAIT_ADVANCEDTOOLUSER,
- TRAIT_CAN_STRIP,
- TRAIT_VIRUSIMMUNE,
- TRAIT_NODISMEMBER,
- TRAIT_NOLIMBDISABLE,
- TRAIT_NOHUNGER,
- TRAIT_NOBREATH,
- )
- inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
- meat = null
- damage_overlay_type = SPECIES_SYNTH
- limbs_id = SPECIES_SYNTH
- ///If your health becomes equal to or less than this value, your disguise is supposed to break. Unfortunately, that feature currently isn't implemented, so currently, all this threshold is used for is (I kid you not) determining whether or not your speech uses SPAN_CLOWN while you're disguised as a bananium golem. See the handle_speech() proc further down in this file for more information on that check.
- var/disguise_fail_health = 75
- var/datum/species/fake_species //a species to do most of our work for us, unless we're damaged
- var/list/initial_species_traits //for getting these values back for assume_disguise()
- var/list/initial_inherent_traits
- wings_icons = list("Robotic")
- changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC
- species_language_holder = /datum/language_holder/synthetic
-
-/datum/species/synth/New()
- initial_species_traits = species_traits.Copy()
- initial_inherent_traits = inherent_traits.Copy()
- ..()
-
-/datum/species/synth/military
- name = "Military Synth"
- id = SPECIES_SYNTH_MILITARY
- armor = 25
- punchdamagelow = 10
- punchdamagehigh = 19
- punchstunthreshold = 14 //about 50% chance to stun
- disguise_fail_health = 50
- changesource_flags = MIRROR_BADMIN | WABBAJACK
-
-/datum/species/synth/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
- ..()
- assume_disguise(old_species, H)
- RegisterSignal(H, COMSIG_MOB_SAY, .proc/handle_speech)
- H.set_safe_hunger_level()
-
-/datum/species/synth/on_species_loss(mob/living/carbon/human/H)
- . = ..()
- UnregisterSignal(H, COMSIG_MOB_SAY)
-
-/datum/species/synth/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, delta_time, times_fired)
- if(chem.type == /datum/reagent/medicine/c2/synthflesh)
- chem.expose_mob(H, TOUCH, 2 * REAGENTS_EFFECT_MULTIPLIER * delta_time,0) //heal a little
- H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * delta_time)
- return TRUE
- return ..()
-
-
-/datum/species/synth/proc/assume_disguise(datum/species/S, mob/living/carbon/human/H)
- if(S && !istype(S, type))
- name = S.name
- say_mod = S.say_mod
- sexes = S.sexes
- species_traits = initial_species_traits.Copy()
- inherent_traits = initial_inherent_traits.Copy()
- species_traits |= S.species_traits
- inherent_traits |= S.inherent_traits
- attack_verb = S.attack_verb
- attack_effect = S.attack_effect
- attack_sound = S.attack_sound
- miss_sound = S.miss_sound
- meat = S.meat
- mutant_bodyparts = S.mutant_bodyparts.Copy()
- mutant_organs = S.mutant_organs.Copy()
- nojumpsuit = S.nojumpsuit
- no_equip = S.no_equip.Copy()
- limbs_id = S.limbs_id
- use_skintones = S.use_skintones
- fixed_mut_color = S.fixed_mut_color
- hair_color = S.hair_color
- fake_species = new S.type
- else
- name = initial(name)
- say_mod = initial(say_mod)
- species_traits = initial_species_traits.Copy()
- inherent_traits = initial_inherent_traits.Copy()
- attack_verb = initial(attack_verb)
- attack_effect = initial(attack_verb)
- attack_sound = initial(attack_sound)
- miss_sound = initial(miss_sound)
- mutant_bodyparts = list()
- nojumpsuit = initial(nojumpsuit)
- no_equip = list()
- qdel(fake_species)
- fake_species = null
- meat = initial(meat)
- limbs_id = SPECIES_SYNTH
- use_skintones = 0
- sexes = 0
- fixed_mut_color = ""
- hair_color = ""
-
- for(var/X in H.bodyparts) //propagates the damage_overlay changes
- var/obj/item/bodypart/BP = X
- BP.update_limb()
- H.update_body_parts() //to update limb icon cache with the new damage overlays
-
-//Proc redirects:
-//Passing procs onto the fake_species, to ensure we look as much like them as possible
-
-/datum/species/synth/handle_hair(mob/living/carbon/human/H, forced_colour)
- if(fake_species)
- fake_species.handle_hair(H, forced_colour)
- else
- return ..()
-
-
-/datum/species/synth/handle_body(mob/living/carbon/human/H)
- if(fake_species)
- fake_species.handle_body(H)
- else
- return ..()
-
-
-/datum/species/synth/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour, force_update = FALSE) //SKYRAT EDIT - ORIGINAL: /datum/species/synth/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour) (one parameter added)
- if(fake_species)
- fake_species.handle_mutant_bodyparts(H,forced_colour, force_update)
- else
- return ..()
-
-
-/datum/species/synth/proc/handle_speech(datum/source, list/speech_args)
- SIGNAL_HANDLER
- if (isliving(source)) // yeah it's gonna be living but just to be clean
- var/mob/living/L = source
- if(fake_species && L.health > disguise_fail_health)
- switch(fake_species.type)
- if (/datum/species/golem/bananium)
- speech_args[SPEECH_SPANS] |= SPAN_CLOWN
diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm
index 6a412460867..3dace5221ff 100644
--- a/code/modules/mob/living/carbon/human/species_types/vampire.dm
+++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm
@@ -31,7 +31,7 @@
use_skintones = TRUE
mutantheart = /obj/item/organ/heart/vampire
mutanttongue = /obj/item/organ/tongue/vampire
- limbs_id = SPECIES_HUMAN
+ examine_limb_id = SPECIES_HUMAN
skinned_type = /obj/item/stack/sheet/animalhide/human
///some starter text sent to the vampire initially, because vampires have shit to do to stay alive
var/info_text = "You are a Vampire. You will slowly but constantly lose blood if outside of a coffin. If inside a coffin, you will slowly heal. You may gain more blood by grabbing a live victim and using your drain ability."
@@ -51,7 +51,7 @@
/datum/species/vampire/spec_life(mob/living/carbon/human/vampire, delta_time, times_fired)
. = ..()
if(istype(vampire.loc, /obj/structure/closet/crate/coffin))
- vampire.heal_overall_damage(2 * delta_time, 2 * delta_time, 0, BODYPART_ORGANIC)
+ vampire.heal_overall_damage(2 * delta_time, 2 * delta_time, 0, BODYTYPE_ORGANIC)
vampire.adjustToxLoss(-2 * delta_time)
vampire.adjustOxyLoss(-2 * delta_time)
vampire.adjustCloneLoss(-2 * delta_time)
diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm
index 86b674b5163..fd624b40ddc 100644
--- a/code/modules/mob/living/carbon/human/species_types/zombies.dm
+++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm
@@ -3,7 +3,7 @@
/datum/species/zombie
// 1spooky
name = "High-Functioning Zombie"
- id = SPECIES_ZOMBIE_HALLOWEEN
+ id = SPECIES_ZOMBIE
say_mod = "moans"
sexes = 0
meat = /obj/item/food/meat/slab/human/mutant/zombie
@@ -36,6 +36,15 @@
bodytemp_heat_damage_limit = FIRE_MINIMUM_TEMPERATURE_TO_EXIST // Take damage at fire temp
bodytemp_cold_damage_limit = MINIMUM_TEMPERATURE_TO_MOVE // take damage below minimum movement temp
+ bodypart_overrides = list(
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/zombie,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/zombie,
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/zombie,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/zombie,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/zombie,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/zombie
+ )
+
/// Zombies do not stabilize body temperature they are the walking dead and are cold blooded
/datum/species/zombie/body_temperature_core(mob/living/carbon/human/humi, delta_time, times_fired)
return
@@ -69,8 +78,8 @@
/datum/species/zombie/infectious
name = "Infectious Zombie"
- id = SPECIES_ZOMBIE
- limbs_id = SPECIES_ZOMBIE_HALLOWEEN
+ id = SPECIES_ZOMBIE_INFECTIOUS
+ examine_limb_id = SPECIES_ZOMBIE
mutanthands = /obj/item/zombie_hand
armor = 20 // 120 damage to KO a zombie, which kills it
speedmod = 1.6
@@ -132,19 +141,38 @@
infection.Insert(C)
// Your skin falls off
-/datum/species/krokodil_addict
- name = "Human"
- id = SPECIES_ADDICT
- limbs_id = SPECIES_ZOMBIE_HALLOWEEN //They look like zombies
+/datum/species/human/krokodil_addict
+ name = "\improper Human"
+ id = SPECIES_ZOMBIE_KROKODIL
+ examine_limb_id = SPECIES_HUMAN
sexes = 0
- meat = /obj/item/food/meat/slab/human/mutant/zombie
mutanttongue = /obj/item/organ/tongue/zombie
changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN
- species_traits = list(HAS_FLESH, HAS_BONE)
- inherent_traits = list(
- TRAIT_ADVANCEDTOOLUSER,
- TRAIT_CAN_STRIP,
- TRAIT_EASILY_WOUNDED,
+
+ bodypart_overrides = list(
+ BODY_ZONE_HEAD = /obj/item/bodypart/head/zombie,
+ BODY_ZONE_CHEST = /obj/item/bodypart/chest/zombie,
+ BODY_ZONE_L_ARM = /obj/item/bodypart/l_arm/zombie,
+ BODY_ZONE_R_ARM = /obj/item/bodypart/r_arm/zombie,
+ BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg/zombie,
+ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg/zombie
)
+/datum/species/human/krokodil_addict/replace_body(mob/living/carbon/target, datum/species/new_species)
+ ..()
+ var/skintone
+ if(ishuman(target))
+ var/mob/living/carbon/human/human_target = target
+ skintone = human_target.skin_tone
+
+ for(var/obj/item/bodypart/limb as anything in target.bodyparts)
+ if(IS_ORGANIC_LIMB(limb))
+ if(limb.body_zone == BODY_ZONE_HEAD || limb.body_zone == BODY_ZONE_CHEST)
+ limb.is_dimorphic = TRUE
+ limb.skin_tone ||= skintone
+ limb.limb_id = SPECIES_HUMAN
+ limb.should_draw_greyscale = TRUE
+ limb.name = "human [parse_zone(limb.body_zone)]"
+ limb.update_limb()
+
#undef REGENERATION_DELAY
diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm
index 5273d0dd930..9fe7e1ddcc3 100644
--- a/code/modules/mob/living/carbon/inventory.dm
+++ b/code/modules/mob/living/carbon/inventory.dm
@@ -14,6 +14,16 @@
return legcuffed
return null
+/mob/living/carbon/proc/get_all_worn_items()
+ return list(
+ back,
+ wear_mask,
+ wear_neck,
+ head,
+ handcuffed,
+ legcuffed,
+ )
+
/mob/living/carbon/proc/equip_in_one_of_slots(obj/item/I, list/slots, qdel_on_fail = 1)
for(var/slot in slots)
if(equip_to_slot_if_possible(I, slots[slot], qdel_on_fail = 0, disable_warning = TRUE))
@@ -242,3 +252,26 @@
visible_message(span_notice("[src] takes [I] from [offerer]."), \
span_notice("You take [I] from [offerer]."))
put_in_hands(I)
+
+///Returns a list of all body_zones covered by clothing
+/mob/living/carbon/proc/get_covered_body_zones()
+ RETURN_TYPE(/list)
+ SHOULD_NOT_OVERRIDE(TRUE)
+
+ var/covered_flags = NONE
+ var/list/all_worn_items = get_all_worn_items()
+ for(var/obj/item/worn_item in all_worn_items)
+ covered_flags |= worn_item.body_parts_covered
+
+ return cover_flags2body_zones(covered_flags)
+
+///Returns a bitfield of all zones covered by clothing
+/mob/living/carbon/proc/get_all_covered_flags()
+ SHOULD_NOT_OVERRIDE(TRUE)
+
+ var/covered_flags = NONE
+ var/list/all_worn_items = get_all_worn_items()
+ for(var/obj/item/worn_item in all_worn_items)
+ covered_flags |= worn_item.body_parts_covered
+
+ return covered_flags
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 85b34ffdde5..9c323859c71 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -360,15 +360,11 @@
return
/mob/living/carbon/proc/handle_bodyparts(delta_time, times_fired)
- var/stam_regen = FALSE
if(stam_regen_start_time <= world.time)
- stam_regen = TRUE
if(HAS_TRAIT_FROM(src, TRAIT_INCAPACITATED, STAMINA))
. |= BODYPART_LIFE_UPDATE_HEALTH //make sure we remove the stamcrit
- for(var/I in bodyparts)
- var/obj/item/bodypart/BP = I
- if(BP.needs_processing)
- . |= BP.on_life(delta_time, times_fired, stam_regen)
+ for(var/obj/item/bodypart/limb as anything in bodyparts)
+ . |= limb.on_life(delta_time, times_fired)
/mob/living/carbon/proc/handle_organs(delta_time, times_fired)
if(stat != DEAD)
@@ -799,7 +795,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
if(limb.get_damage() >= limb.max_damage)
limb.cremation_progress += rand(1 * delta_time, 2.5 * delta_time)
if(limb.cremation_progress >= 100)
- if(limb.status == BODYPART_ORGANIC) //Non-organic limbs don't burn
+ if(IS_ORGANIC_LIMB(limb)) //Non-organic limbs don't burn
limb.drop_limb()
limb.visible_message(span_warning("[src]'s [limb.name] crumbles into ash!"))
qdel(limb)
@@ -815,7 +811,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
if(head.get_damage() >= head.max_damage)
head.cremation_progress += rand(1 * delta_time, 2.5 * delta_time)
if(head.cremation_progress >= 100)
- if(head.status == BODYPART_ORGANIC) //Non-organic limbs don't burn
+ if(IS_ORGANIC_LIMB(head)) //Non-organic limbs don't burn
head.drop_limb()
head.visible_message(span_warning("[src]'s head crumbles into ash!"))
qdel(head)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 3edba64ba94..72f3a7d2594 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1400,9 +1400,7 @@
// Randomize everything but the species, which was already handled above.
new_human.randomize_human_appearance(~RANDOMIZE_SPECIES)
- new_human.update_body()
- new_human.update_hair()
- new_human.update_body_parts()
+ new_human.update_body(is_creating = TRUE)
new_human.dna.update_dna_identity()
new_mob = new_human
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 18b54e1c33d..246668d2d61 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -107,6 +107,7 @@
add_cell_sample()
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
+ AddElement(/datum/element/soft_landing)
/mob/living/simple_animal/slime/Destroy()
for (var/A in actions)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 42ad6d90ae8..435288f5f94 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -374,14 +374,14 @@
*/
/proc/item_heal_robotic(mob/living/carbon/human/H, mob/user, brute_heal, burn_heal)
var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected))
- if(affecting && affecting.status == BODYPART_ROBOTIC)
+ if(affecting && !IS_ORGANIC_LIMB(affecting))
var/dam //changes repair text based on how much brute/burn was supplied
if(brute_heal > burn_heal)
dam = 1
else
dam = 0
if((brute_heal > 0 && affecting.brute_dam > 0) || (burn_heal > 0 && affecting.burn_dam > 0))
- if(affecting.heal_damage(brute_heal, burn_heal, 0, BODYPART_ROBOTIC))
+ if(affecting.heal_damage(brute_heal, burn_heal, 0, BODYTYPE_ROBOTIC))
H.update_damage_overlays()
user.visible_message(span_notice("[user] fixes some of the [dam ? "dents on" : "burnt wires in"] [H]'s [affecting.name]."), \
span_notice("You fix some of the [dam ? "dents on" : "burnt wires in"] [H == user ? "your" : "[H]'s"] [affecting.name]."))
diff --git a/code/modules/mob_spawn/corpses/mining_corpses.dm b/code/modules/mob_spawn/corpses/mining_corpses.dm
index d5bc82b0b99..3d36a9e1916 100644
--- a/code/modules/mob_spawn/corpses/mining_corpses.dm
+++ b/code/modules/mob_spawn/corpses/mining_corpses.dm
@@ -187,7 +187,7 @@
/datum/outfit/consumed_dame/pre_equip(mob/living/carbon/human/dame, visualsOnly = FALSE)
if(!visualsOnly)
dame.gender = FEMALE
- dame.body_type = FEMALE
+ dame.physique = FEMALE
dame.update_body()
if(prob(30))
back = /obj/item/nullrod/scythe/talking
diff --git a/code/modules/ninja/suit/ninja_equipment_actions/energy_net_nets.dm b/code/modules/ninja/suit/ninja_equipment_actions/energy_net_nets.dm
index 2d390a1b560..ab05eb6230b 100644
--- a/code/modules/ninja/suit/ninja_equipment_actions/energy_net_nets.dm
+++ b/code/modules/ninja/suit/ninja_equipment_actions/energy_net_nets.dm
@@ -24,16 +24,16 @@
buckle_lying = 0
buckle_prevents_pull = TRUE
///The creature currently caught in the net
- var/mob/living/affecting
+ var/mob/living/affected_mob
/obj/structure/energy_net/play_attack_sound(damage, damage_type = BRUTE, damage_flag = 0)
if(damage_type == BRUTE || damage_type == BURN)
playsound(src, 'sound/weapons/slash.ogg', 80, TRUE)
/obj/structure/energy_net/Destroy()
- if(!QDELETED(affecting))
- affecting.visible_message(span_notice("[affecting.name] is recovered from the energy net!"), span_notice("You are recovered from the energy net!"), span_hear("You hear a grunt."))
- affecting = null
+ if(!QDELETED(affected_mob))
+ affected_mob.visible_message(span_notice("[affected_mob.name] is recovered from the energy net!"), span_notice("You are recovered from the energy net!"), span_hear("You hear a grunt."))
+ affected_mob = null
return ..()
/obj/structure/energy_net/attack_paw(mob/user, list/modifiers)
diff --git a/code/modules/ninja/suit/ninja_equipment_actions/ninja_net.dm b/code/modules/ninja/suit/ninja_equipment_actions/ninja_net.dm
index 29ffe4a5af0..66eb50438fe 100644
--- a/code/modules/ninja/suit/ninja_equipment_actions/ninja_net.dm
+++ b/code/modules/ninja/suit/ninja_equipment_actions/ninja_net.dm
@@ -34,7 +34,7 @@
ninja.Beam(net_target, "n_beam", time = 15)
ninja.say("Get over here!", forced = "ninja net")
var/obj/structure/energy_net/net = new /obj/structure/energy_net(net_target.drop_location())
- net.affecting = net_target
+ net.affected_mob = net_target
ninja.visible_message(span_danger("[ninja] caught [net_target] with an energy net!"),span_notice("You caught [net_target] with an energy net!"))
if(net_target.buckled)
diff --git a/code/modules/ninja/suit/suit.dm b/code/modules/ninja/suit/suit.dm
index 347621bd7e4..04fbd041f26 100644
--- a/code/modules/ninja/suit/suit.dm
+++ b/code/modules/ninja/suit/suit.dm
@@ -168,7 +168,7 @@
var/design_choice = tgui_alert(ninja, "Please choose your desired suit design.",,list("Original","New Age"))
switch(design_choice)
if("Original")
- icon_state = ninja.body_type == "female" ? "s-ninjanf" : "s-ninjan"
+ icon_state = ninja.physique == "female" ? "s-ninjanf" : "s-ninjan"
ninja.gloves.icon_state = "s-ninjan"
ninja.gloves.inhand_icon_state = "s-ninjan"
if("New Age")
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index d219e2fb086..44b6dca9f12 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -546,7 +546,7 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri
return ..()
var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected))
- if(affecting && affecting.status == BODYPART_ROBOTIC)
+ if(affecting && !IS_ORGANIC_LIMB(affecting))
if(user == H)
user.visible_message(span_notice("[user] starts to fix some of the wires in [H]'s [affecting.name]."), span_notice("You start fixing some of the wires in [H == user ? "your" : "[H]'s"] [affecting.name]."))
/* SKYRAT EDIT START - ORIGINAL:
diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
index 71686778ae6..3e593b513ec 100644
--- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
@@ -116,10 +116,10 @@
to_chat(M, span_notice("[high_message]"))
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "smacked out", /datum/mood_event/narcotic_heavy, name)
if(current_cycle == 35 && creation_purity <= 0.6)
- if(!istype(M.dna.species, /datum/species/krokodil_addict))
+ if(!istype(M.dna.species, /datum/species/human/krokodil_addict))
to_chat(M, span_userdanger("Your skin falls off easily!"))
M.adjustBruteLoss(50*REM, 0) // holy shit your skin just FELL THE FUCK OFF
- M.set_species(/datum/species/krokodil_addict)
+ M.set_species(/datum/species/human/krokodil_addict)
..()
/datum/reagent/drug/krokodil/overdose_process(mob/living/M, delta_time, times_fired)
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index dfa5ac4b08c..238f0413736 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -296,7 +296,7 @@
/datum/reagent/medicine/oxandrolone/overdose_process(mob/living/M, delta_time, times_fired)
if(M.getFireLoss()) //It only makes existing burns worse
- M.adjustFireLoss(4.5 * REM * delta_time, FALSE, FALSE, BODYPART_ORGANIC) // it's going to be healing either 4 or 0.5
+ M.adjustFireLoss(4.5 * REM * delta_time, FALSE, FALSE, BODYTYPE_ORGANIC) // it's going to be healing either 4 or 0.5
. = TRUE
..()
@@ -339,8 +339,8 @@
holder.add_reagent(/datum/reagent/consumable/sugar, 1)
holder.remove_reagent(/datum/reagent/medicine/salglu_solution, 0.5)
if(DT_PROB(18, delta_time))
- M.adjustBruteLoss(0.5, FALSE, FALSE, BODYPART_ORGANIC)
- M.adjustFireLoss(0.5, FALSE, FALSE, BODYPART_ORGANIC)
+ M.adjustBruteLoss(0.5, FALSE, FALSE, BODYTYPE_ORGANIC)
+ M.adjustFireLoss(0.5, FALSE, FALSE, BODYTYPE_ORGANIC)
. = TRUE
..()
@@ -409,8 +409,8 @@
/datum/reagent/medicine/omnizine/overdose_process(mob/living/M, delta_time, times_fired)
M.adjustToxLoss(1.5 * REM * delta_time, FALSE)
M.adjustOxyLoss(1.5 * REM * delta_time, FALSE)
- M.adjustBruteLoss(1.5 * REM * delta_time, FALSE, FALSE, BODYPART_ORGANIC)
- M.adjustFireLoss(1.5 * REM * delta_time, FALSE, FALSE, BODYPART_ORGANIC)
+ M.adjustBruteLoss(1.5 * REM * delta_time, FALSE, FALSE, BODYTYPE_ORGANIC)
+ M.adjustFireLoss(1.5 * REM * delta_time, FALSE, FALSE, BODYTYPE_ORGANIC)
..()
. = TRUE
@@ -507,7 +507,7 @@
/datum/reagent/medicine/sal_acid/overdose_process(mob/living/M, delta_time, times_fired)
if(M.getBruteLoss()) //It only makes existing bruises worse
- M.adjustBruteLoss(4.5 * REM * delta_time, FALSE, FALSE, BODYPART_ORGANIC) // it's going to be healing either 4 or 0.5
+ M.adjustBruteLoss(4.5 * REM * delta_time, FALSE, FALSE, BODYTYPE_ORGANIC) // it's going to be healing either 4 or 0.5
. = TRUE
..()
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 7941933c3d9..5cbd3f2d9d1 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -583,7 +583,7 @@
/datum/reagent/toxin/histamine/overdose_process(mob/living/M, delta_time, times_fired)
M.adjustOxyLoss(2 * REM * delta_time, FALSE)
- M.adjustBruteLoss(2 * REM * delta_time, FALSE, FALSE, BODYPART_ORGANIC)
+ M.adjustBruteLoss(2 * REM * delta_time, FALSE, FALSE, BODYTYPE_ORGANIC)
M.adjustToxLoss(2 * REM * delta_time, FALSE)
..()
. = TRUE
diff --git a/code/modules/reagents/reagent_containers/patch.dm b/code/modules/reagents/reagent_containers/patch.dm
index 4bb98269ae9..722da9e3b1a 100644
--- a/code/modules/reagents/reagent_containers/patch.dm
+++ b/code/modules/reagents/reagent_containers/patch.dm
@@ -17,7 +17,7 @@
if(!affecting)
to_chat(user, span_warning("The limb is missing!"))
return
- if(affecting.status != BODYPART_ORGANIC)
+ if(!IS_ORGANIC_LIMB(affecting))
to_chat(user, span_notice("Medicine won't work on a robotic limb!"))
return
..()
diff --git a/code/modules/religion/religion_sects.dm b/code/modules/religion/religion_sects.dm
index e4f93d21c04..037408f04cd 100644
--- a/code/modules/religion/religion_sects.dm
+++ b/code/modules/religion/religion_sects.dm
@@ -99,19 +99,18 @@
if(!ishuman(target))
return FALSE
var/mob/living/carbon/human/blessed = target
- for(var/X in blessed.bodyparts)
- var/obj/item/bodypart/bodypart = X
- if(bodypart.status == BODYPART_ROBOTIC)
+ for(var/obj/item/bodypart/bodypart as anything in blessed.bodyparts)
+ if(!IS_ORGANIC_LIMB(bodypart))
to_chat(chap, span_warning("[GLOB.deity] refuses to heal this metallic taint!"))
return TRUE
var/heal_amt = 10
- var/list/hurt_limbs = blessed.get_damaged_bodyparts(1, 1, null, BODYPART_ORGANIC)
+ var/list/hurt_limbs = blessed.get_damaged_bodyparts(1, 1, null, BODYTYPE_ORGANIC)
if(hurt_limbs.len)
for(var/X in hurt_limbs)
var/obj/item/bodypart/affecting = X
- if(affecting.heal_damage(heal_amt, heal_amt, null, BODYPART_ORGANIC))
+ if(affecting.heal_damage(heal_amt, heal_amt, null, BODYTYPE_ORGANIC))
blessed.update_damage_overlays()
blessed.visible_message(span_notice("[chap] heals [blessed] with the power of [GLOB.deity]!"))
to_chat(blessed, span_boldnotice("May the power of [GLOB.deity] compel you to be healed!"))
@@ -166,7 +165,7 @@
//if we're not targetting a robot part we stop early
var/obj/item/bodypart/bodypart = blessed.get_bodypart(chap.zone_selected)
- if(bodypart.status != BODYPART_ROBOTIC)
+ if(!IS_ORGANIC_LIMB(bodypart))
if(!did_we_charge)
to_chat(chap, span_warning("[GLOB.deity] scoffs at the idea of healing such fleshy matter!"))
else
@@ -177,7 +176,7 @@
return TRUE
//charge(?) and go
- if(bodypart.heal_damage(5,5,null,BODYPART_ROBOTIC))
+ if(bodypart.heal_damage(5,5,null,BODYTYPE_ROBOTIC))
blessed.update_damage_overlays()
blessed.visible_message(span_notice("[chap] [did_we_charge ? "repairs" : "repairs and charges"] [blessed] with the power of [GLOB.deity]!"))
@@ -253,16 +252,16 @@
return FALSE
var/mob/living/carbon/human/blessed = blessed_living
for(var/obj/item/bodypart/robolimb as anything in blessed.bodyparts)
- if(robolimb.status == BODYPART_ROBOTIC)
+ if(!IS_ORGANIC_LIMB(robolimb))
to_chat(chap, span_warning("[GLOB.deity] refuses to heal this metallic taint!"))
return TRUE
account.adjust_money(-GREEDY_HEAL_COST)
var/heal_amt = 30
- var/list/hurt_limbs = blessed.get_damaged_bodyparts(1, 1, null, BODYPART_ORGANIC)
+ var/list/hurt_limbs = blessed.get_damaged_bodyparts(1, 1, null, BODYTYPE_ORGANIC)
if(hurt_limbs.len)
for(var/obj/item/bodypart/affecting as anything in hurt_limbs)
- if(affecting.heal_damage(heal_amt, heal_amt, null, BODYPART_ORGANIC))
+ if(affecting.heal_damage(heal_amt, heal_amt, null, BODYTYPE_ORGANIC))
blessed.update_damage_overlays()
blessed.visible_message(span_notice("[chap] barters a heal for [blessed] from [GLOB.deity]!"))
to_chat(blessed, span_boldnotice("May the power of [GLOB.deity] compel you to be healed! Thank you for choosing [GLOB.deity]!"))
diff --git a/code/modules/research/designs/limbgrower_designs.dm b/code/modules/research/designs/limbgrower_designs.dm
index f648d829134..2738fc89d5c 100644
--- a/code/modules/research/designs/limbgrower_designs.dm
+++ b/code/modules/research/designs/limbgrower_designs.dm
@@ -4,7 +4,7 @@
/datum/design/leftarm
name = "Left Arm"
- id = "leftarm"
+ id = "l_arm"
build_type = LIMBGROWER
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 25)
build_path = /obj/item/bodypart/l_arm
@@ -12,7 +12,7 @@
/datum/design/rightarm
name = "Right Arm"
- id = "rightarm"
+ id = "r_arm"
build_type = LIMBGROWER
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 25)
build_path = /obj/item/bodypart/r_arm
@@ -20,35 +20,19 @@
/datum/design/leftleg
name = "Left Leg"
- id = "leftleg"
+ id = "l_leg"
build_type = LIMBGROWER
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 25)
build_path = /obj/item/bodypart/l_leg
- category = list("initial",SPECIES_HUMAN,SPECIES_LIZARD,SPECIES_MOTH,SPECIES_PLASMAMAN,SPECIES_ETHEREAL)
+ category = list("initial",SPECIES_HUMAN,SPECIES_LIZARD,SPECIES_MOTH,SPECIES_PLASMAMAN,SPECIES_ETHEREAL, "digitigrade")
/datum/design/rightleg
name = "Right Leg"
- id = "rightleg"
+ id = "r_leg"
build_type = LIMBGROWER
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 25)
build_path = /obj/item/bodypart/r_leg
- category = list("initial",SPECIES_HUMAN,SPECIES_LIZARD,SPECIES_MOTH,SPECIES_PLASMAMAN,SPECIES_ETHEREAL)
-
-/datum/design/digi_leftleg
- name = "Digitigrade Left Leg"
- id = "digi_leftleg"
- build_type = LIMBGROWER
- reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 30)
- build_path = /obj/item/bodypart/l_leg/digitigrade
- category = list(SPECIES_LIZARD)
-
-/datum/design/digi_rightleg
- name = "Digitigrade Right Leg"
- id = "digi_rightleg"
- build_type = LIMBGROWER
- reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 30)
- build_path = /obj/item/bodypart/r_leg/digitigrade
- category = list(SPECIES_LIZARD)
+ category = list("initial",SPECIES_HUMAN,SPECIES_LIZARD,SPECIES_MOTH,SPECIES_PLASMAMAN,SPECIES_ETHEREAL, "digitigrade")
//Non-limb limb designs
@@ -256,41 +240,41 @@
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/obj/item/disk/design_disk/limbs/felinid
- name = "Felinid Limb Design Disk"
+ name = "Felinid Organ Design Disk"
limb_designs = list(/datum/design/cat_tail, /datum/design/cat_ears)
/datum/design/limb_disk/felinid
- name = "Felinid Limb Design Disk"
- desc = "Contains designs for felinid bodyparts for the limbgrower - Felinid ears and tail."
+ name = "Felinid Organ Design Disk"
+ desc = "Contains designs for felinid organs for the limbgrower - Felinid ears and tail."
id = "limbdesign_felinid"
build_path = /obj/item/disk/design_disk/limbs/felinid
/obj/item/disk/design_disk/limbs/lizard
- name = "Lizard Limb Design Disk"
- limb_designs = list(/datum/design/lizard_tail, /datum/design/lizard_tongue, /datum/design/digi_leftleg, /datum/design/digi_rightleg)
+ name = "Lizard Organ Design Disk"
+ limb_designs = list(/datum/design/lizard_tail, /datum/design/lizard_tongue)
/datum/design/limb_disk/lizard
- name = "Lizard Limb Design Disk"
- desc = "Contains designs for lizard bodyparts for the limbgrower - Lizard tongue, tail, and digitigrade legs."
+ name = "Lizard Organ Design Disk"
+ desc = "Contains designs for lizard organs for the limbgrower - Lizard tongue, and tail"
id = "limbdesign_lizard"
build_path = /obj/item/disk/design_disk/limbs/lizard
/obj/item/disk/design_disk/limbs/plasmaman
- name = "Plasmaman Limb Design Disk"
+ name = "Plasmaman Organ Design Disk"
limb_designs = list(/datum/design/plasmaman_stomach, /datum/design/plasmaman_liver, /datum/design/plasmaman_lungs, /datum/design/plasmaman_tongue)
/datum/design/limb_disk/plasmaman
- name = "Plasmaman Limb Design Disk"
+ name = "Plasmaman Organ Design Disk"
desc = "Contains designs for plasmaman organs for the limbgrower - Plasmaman tongue, liver, stomach, and lungs."
id = "limbdesign_plasmaman"
build_path = /obj/item/disk/design_disk/limbs/plasmaman
/obj/item/disk/design_disk/limbs/ethereal
- name = "Ethereal Limb Design Disk"
+ name = "Ethereal Organ Design Disk"
limb_designs = list(/datum/design/ethereal_stomach, /datum/design/ethereal_tongue, /datum/design/ethereal_lungs)
/datum/design/limb_disk/ethereal
- name = "Ethereal Limb Design Disk"
+ name = "Ethereal Organ Design Disk"
desc = "Contains designs for ethereal organs for the limbgrower - Ethereal tongue and stomach."
id = "limbdesign_ethereal"
build_path = /obj/item/disk/design_disk/limbs/ethereal
diff --git a/code/modules/spells/spell_types/shadow_walk.dm b/code/modules/spells/spell_types/shadow_walk.dm
index b32eba72d1e..8bf7bdbc961 100644
--- a/code/modules/spells/spell_types/shadow_walk.dm
+++ b/code/modules/spells/spell_types/shadow_walk.dm
@@ -63,7 +63,7 @@
if(!jaunter || jaunter.loc != src)
qdel(src)
if (light_amount < 0.2 && (!QDELETED(jaunter))) //heal in the dark
- jaunter.heal_overall_damage((SHADOW_REGEN_RATE * delta_time), (SHADOW_REGEN_RATE * delta_time), 0, BODYPART_ORGANIC)
+ jaunter.heal_overall_damage((SHADOW_REGEN_RATE * delta_time), (SHADOW_REGEN_RATE * delta_time), 0, BODYTYPE_ORGANIC)
check_light_level()
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 52235d344d3..7dd9ca81dbd 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -5,17 +5,35 @@
throwforce = 3
w_class = WEIGHT_CLASS_SMALL
icon = 'icons/mob/human_parts.dmi'
- icon_state = ""
+ icon_state = "" //Leave this blank! Bodyparts are built using overlays
/// The icon for Organic limbs using greyscale
- var/icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC
- /// The icon for Robotic limbs
- var/icon_robotic = DEFAULT_BODYPART_ICON_ROBOTIC
+ VAR_PROTECTED/icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC
+ ///The icon for non-greyscale limbs
+ VAR_PROTECTED/icon_static = 'icons/mob/human_parts.dmi'
+ ///The icon for husked limbs
+ VAR_PROTECTED/icon_husk = 'icons/mob/human_parts.dmi'
+ ///The type of husk for building an iconstate
+ var/husk_type = "humanoid"
layer = BELOW_MOB_LAYER //so it isn't hidden behind objects when on the floor
grind_results = list(/datum/reagent/bone_dust = 10, /datum/reagent/liquidgibs = 5) // robotic bodyparts and chests/heads cannot be ground
var/mob/living/carbon/owner
- var/datum/weakref/original_owner
- var/status = BODYPART_ORGANIC
- var/needs_processing = FALSE
+
+ ///A bitfield of bodytypes for clothing, surgery, and misc information
+ var/bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC
+ ///Defines when a bodypart should not be changed. Example: BP_BLOCK_CHANGE_SPECIES prevents the limb from being overwritten on species gain
+ var/change_exempt_flags
+
+ var/is_husked = FALSE
+ ///The ID of a species used to generate the icon. Needs to match the icon_state portion in the limbs file!
+ var/limb_id = SPECIES_HUMAN
+ //Defines what sprite the limb should use if it is also sexually dimorphic.
+ VAR_PROTECTED/limb_gender = "m"
+ ///Does this limb have a greyscale version?
+ var/uses_mutcolor = TRUE
+ ///Is there a sprite difference between male and female?
+ var/is_dimorphic = FALSE
+ ///The actual color a limb is drawn as, set by /proc/update_limb()
+ VAR_PROTECTED/draw_color
/// BODY_ZONE_CHEST, BODY_ZONE_L_ARM, etc , used for def_zone
var/body_zone
@@ -23,8 +41,6 @@
var/aux_layer
/// bitflag used to check which clothes cover this bodypart
var/body_part
- /// Used for alternate legs, useless elsewhere
- var/use_digitigrade = NOT_DIGITIGRADE
var/list/embedded_objects = list()
/// are we a hand? if so, which one!
var/held_index = 0
@@ -40,13 +56,19 @@
var/can_be_disabled = FALSE
///Multiplier of the limb's damage that gets applied to the mob
var/body_damage_coeff = 1
+ ///Multiplier of the limb's stamina damage that gets applied to the mob. Why is this 0.75 by default? Good question!
var/stam_damage_coeff = 0.75
var/brutestate = 0
var/burnstate = 0
+ ///The current amount of brute damage the limb has
var/brute_dam = 0
+ ///The current amount of burn damage the limb has
var/burn_dam = 0
+ ///The current amount of stamina damage the limb has
var/stamina_dam = 0
+ ///The maximum stamina damage a bodypart can take
var/max_stamina_damage = 0
+ ///The maximum "physical" damage a bodypart can take. Set by children
var/max_damage = 0
///Gradually increases while burning when at full damage, destroys the limb when at 100
var/cremation_progress = 0
@@ -54,20 +76,17 @@
var/brute_reduction = 0
///Subtracted to burn damage taken
var/burn_reduction = 0
+
//Coloring and proper item icon update
var/skin_tone = ""
- var/body_gender = ""
- var/species_id = ""
- var/should_draw_gender = FALSE
- var/should_draw_greyscale = FALSE
var/species_color = ""
+ ///Limbs need this information as a back-up incase they are generated outside of a carbon (limbgrower)
+ var/should_draw_greyscale = TRUE
+ ///An "override" color that can be applied to ANY limb, greyscale or not.
var/mutation_color = ""
- var/no_update = 0
///for nonhuman bodypart (e.g. monkey)
var/animal_origin
- //for all bodyparts
- var/part_origin = HUMAN_BODY
///whether it can be dismembered with a weapon.
var/dismemberable = 1
@@ -117,24 +136,28 @@
var/datum/bodypart_aid/gauze/current_gauze
/// If we have a splint currently applied
var/datum/bodypart_aid/splint/current_splint
+ /// What icon do we use to render this limb? Ususally used by robotic limb augments.
+ var/rendered_bp_icon
+ /// Do we use an organic render for this robotic limb?
+ var/organic_render = TRUE
//SKYRAT EDIT CHANGE END
- var/rendered_bp_icon //SKYRAT EDIT ADDITION - CUSTOMIZATION
- var/organic_render = TRUE //SKYRAT EDIT ADDITION - CUSTOMIZATION
/// If something is currently grasping this bodypart and trying to staunch bleeding (see [/obj/item/hand_item/self_grasp])
var/obj/item/hand_item/self_grasp/grasped_by
///A list of all the external organs we've got stored to draw horns, wings and stuff with (special because we are actually in the limbs unlike normal organs :/ )
var/list/obj/item/organ/external/external_organs = list()
-
/obj/item/bodypart/Initialize(mapload)
. = ..()
if(can_be_disabled)
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS), .proc/on_paralysis_trait_gain)
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS), .proc/on_paralysis_trait_loss)
- if(status != BODYPART_ORGANIC)
+ if(!IS_ORGANIC_LIMB(src))
grind_results = null
+ name = "[limb_id] [parse_zone(body_zone)]"
+ update_icon_dropped()
+
/obj/item/bodypart/Destroy()
if(owner)
owner.remove_bodypart(src)
@@ -152,8 +175,16 @@
//SKYRAT EDIT ADDITION END
return ..()
+/obj/item/bodypart/forceMove(atom/destination) //Please. Never forcemove a limb if its's actually in use. This is only for borgs.
+ SHOULD_CALL_PARENT(TRUE)
+
+ . = ..()
+ if(isturf(destination))
+ update_icon_dropped()
/obj/item/bodypart/examine(mob/user)
+ SHOULD_CALL_PARENT(TRUE)
+
. = ..()
if(brute_dam > DAMAGE_PRECISION)
. += span_warning("This limb has [brute_dam > 30 ? "severe" : "minor"] bruising.")
@@ -170,10 +201,11 @@
. += span_warning("The flesh on this limb appears badly cooked.")
/obj/item/bodypart/blob_act()
- take_damage(max_damage)
-
+ receive_damage(max_damage, wound_bonus = CANT_WOUND)
/obj/item/bodypart/attack(mob/living/carbon/victim, mob/user)
+ SHOULD_CALL_PARENT(TRUE)
+
if(ishuman(victim))
var/mob/living/carbon/human/human_victim = victim
if(HAS_TRAIT(victim, TRAIT_LIMBATTACHMENT))
@@ -192,6 +224,8 @@
..()
/obj/item/bodypart/attackby(obj/item/weapon, mob/user, params)
+ SHOULD_CALL_PARENT(TRUE)
+
if(weapon.get_sharpness())
add_fingerprint(user)
if(!contents.len)
@@ -206,16 +240,20 @@
return ..()
/obj/item/bodypart/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
+ SHOULD_CALL_PARENT(TRUE)
+
..()
- if(status != BODYPART_ROBOTIC)
+ if(IS_ORGANIC_LIMB(src))
playsound(get_turf(src), 'sound/misc/splort.ogg', 50, TRUE, -1)
pixel_x = rand(-3, 3)
pixel_y = rand(-3, 3)
//empties the bodypart from its organs and other things inside it
/obj/item/bodypart/proc/drop_organs(mob/user, violent_removal)
+ SHOULD_CALL_PARENT(TRUE)
+
var/turf/bodypart_turf = get_turf(src)
- if(status != BODYPART_ROBOTIC)
+ if(IS_ORGANIC_LIMB(src))
playsound(bodypart_turf, 'sound/misc/splort.ogg', 50, TRUE, -1)
//seep_gauze(9999) // destroy any existing gauze if any exists
if(current_gauze)
@@ -229,6 +267,9 @@
///since organs aren't actually stored in the bodypart themselves while attached to a person, we have to query the owner for what we should have
/obj/item/bodypart/proc/get_organs()
+ SHOULD_CALL_PARENT(TRUE)
+ RETURN_TYPE(/list)
+
if(!owner)
return FALSE
@@ -239,10 +280,11 @@
return bodypart_organs
-
//Return TRUE to get whatever mob this is in to update health.
-/obj/item/bodypart/proc/on_life(delta_time, times_fired, stam_regen)
- if(stamina_dam > DAMAGE_PRECISION && stam_regen) //DO NOT update health here, it'll be done in the carbon's life.
+/obj/item/bodypart/proc/on_life(delta_time, times_fired)
+ SHOULD_CALL_PARENT(TRUE)
+ //DO NOT update health here, it'll be done in the carbon's life.
+ if(stamina_dam > DAMAGE_PRECISION && owner.stam_regen_start_time <= world.time)
heal_damage(0, 0, INFINITY, null, FALSE)
. |= BODYPART_LIFE_UPDATE_HEALTH
@@ -250,13 +292,14 @@
//Damage will not exceed max_damage using this proc
//Cannot apply negative damage
/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, blocked = 0, updating_health = TRUE, required_status = null, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null)
+ SHOULD_CALL_PARENT(TRUE)
+
var/hit_percent = (100-blocked)/100
if((!brute && !burn && !stamina) || hit_percent <= 0)
return FALSE
if(owner && (owner.status_flags & GODMODE))
- return FALSE //godmode
-
- if(required_status && (status != required_status))
+ return FALSE //godmode
+ if(required_status && !(bodytype & required_status))
return FALSE
var/dmg_multi = CONFIG_GET(number/damage_multiplier) * hit_percent
@@ -381,178 +424,13 @@
. = TRUE
return update_bodypart_damage_state() || .
-/// Allows us to roll for and apply a wound without actually dealing damage. Used for aggregate wounding power with pellet clouds
-/obj/item/bodypart/proc/painless_wound_roll(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus, sharpness=NONE)
- if(!owner || phantom_wounding_dmg <= WOUND_MINIMUM_DAMAGE || wound_bonus == CANT_WOUND)
- return
-
- var/mangled_state = get_mangled_state()
- var/bio_state = owner.get_biological_state()
- var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
-
- if(wounding_type == WOUND_BLUNT && sharpness)
- if(sharpness & SHARP_EDGED)
- wounding_type = WOUND_SLASH
- else if (sharpness & SHARP_POINTY)
- wounding_type = WOUND_PIERCE
-
- //Handling for bone only/flesh only(none right now)/flesh and bone targets
- switch(bio_state)
- // if we're bone only, all cutting attacks go straight to the bone
- if(BIO_JUST_BONE)
- if(wounding_type == WOUND_SLASH)
- wounding_type = WOUND_BLUNT
- phantom_wounding_dmg *= (easy_dismember ? 1 : 0.6)
- else if(wounding_type == WOUND_PIERCE)
- wounding_type = WOUND_BLUNT
- phantom_wounding_dmg *= (easy_dismember ? 1 : 0.75)
- if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
- return
- // note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday)
- // standard humanoids
- if(BIO_FLESH_BONE)
- // if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
- // So a big sharp weapon is still all you need to destroy a limb
- if(mangled_state == BODYPART_MANGLED_FLESH && sharpness)
- playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
- if(wounding_type == WOUND_SLASH && !easy_dismember)
- phantom_wounding_dmg *= 0.6 // edged weapons pass along 60% of their wounding damage to the bone since the power is spread out over a larger area
- if(wounding_type == WOUND_PIERCE && !easy_dismember)
- phantom_wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
- wounding_type = WOUND_BLUNT
- else if(mangled_state == BODYPART_MANGLED_BOTH && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
- return
-
- check_wounding(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)
-
-/**
- * check_wounding() is where we handle rolling for, selecting, and applying a wound if we meet the criteria
- *
- * We generate a "score" for how woundable the attack was based on the damage and other factors discussed in [/obj/item/bodypart/proc/check_woundings_mods], then go down the list from most severe to least severe wounds in that category.
- * We can promote a wound from a lesser to a higher severity this way, but we give up if we have a wound of the given type and fail to roll a higher severity, so no sidegrades/downgrades
- *
- * Arguments:
- * * woundtype- Either WOUND_BLUNT, WOUND_SLASH, WOUND_PIERCE, or WOUND_BURN based on the attack type.
- * * damage- How much damage is tied to this attack, since wounding potential scales with damage in an attack (see: WOUND_DAMAGE_EXPONENT)
- * * wound_bonus- The wound_bonus of an attack
- * * bare_wound_bonus- The bare_wound_bonus of an attack
- */
-/obj/item/bodypart/proc/check_wounding(woundtype, damage, wound_bonus, bare_wound_bonus, attack_direction)
- if(HAS_TRAIT(owner, TRAIT_NEVER_WOUNDED))
- return
-
- // note that these are fed into an exponent, so these are magnified
- if(HAS_TRAIT(owner, TRAIT_EASILY_WOUNDED))
- damage *= 1.5
- else
- damage = min(damage, WOUND_MAX_CONSIDERED_DAMAGE)
-
- if(HAS_TRAIT(owner,TRAIT_HARDLY_WOUNDED))
- damage *= 0.85
-
- if(HAS_TRAIT(owner, TRAIT_EASYDISMEMBER))
- damage *= 1.1
-
- var/base_roll = rand(1, round(damage ** WOUND_DAMAGE_EXPONENT))
- var/injury_roll = base_roll
- injury_roll += check_woundings_mods(woundtype, damage, wound_bonus, bare_wound_bonus)
- var/list/wounds_checking = GLOB.global_wound_types[woundtype]
-
- if(injury_roll > WOUND_DISMEMBER_OUTRIGHT_THRESH && prob(get_damage() / max_damage * 100))
- var/datum/wound/loss/dismembering = new
- dismembering.apply_dismember(src, woundtype, outright = TRUE, attack_direction = attack_direction)
- return
-
- // quick re-check to see if bare_wound_bonus applies, for the benefit of log_wound(), see about getting the check from check_woundings_mods() somehow
- if(ishuman(owner))
- var/mob/living/carbon/human/human_wearer = owner
- var/list/clothing = human_wearer.clothingonpart(src)
- for(var/obj/item/clothing/clothes_check as anything in clothing)
- // unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary
- if(clothes_check.armor.getRating(WOUND))
- bare_wound_bonus = 0
- break
-
- //cycle through the wounds of the relevant category from the most severe down
- for(var/datum/wound/possible_wound as anything in wounds_checking)
- var/datum/wound/replaced_wound
- for(var/datum/wound/existing_wound as anything in wounds)
- if(existing_wound.type in wounds_checking)
- if(existing_wound.severity >= initial(possible_wound.severity))
- return
- else
- replaced_wound = existing_wound
-
- if(initial(possible_wound.threshold_minimum) < injury_roll)
- var/datum/wound/new_wound
- if(replaced_wound)
- new_wound = replaced_wound.replace_wound(possible_wound, attack_direction = attack_direction)
- else
- new_wound = new possible_wound
- new_wound.apply_wound(src, attack_direction = attack_direction)
- log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll) // dismembering wounds are logged in the apply_wound() for loss wounds since they delete themselves immediately, these will be immediately returned
- return new_wound
-
-// try forcing a specific wound, but only if there isn't already a wound of that severity or greater for that type on this bodypart
-/obj/item/bodypart/proc/force_wound_upwards(specific_woundtype, smited = FALSE)
- var/datum/wound/potential_wound = specific_woundtype
- for(var/datum/wound/existing_wound as anything in wounds)
- if(existing_wound.wound_type == initial(potential_wound.wound_type))
- if(existing_wound.severity < initial(potential_wound.severity)) // we only try if the existing one is inferior to the one we're trying to force
- existing_wound.replace_wound(potential_wound, smited)
- return
-
- var/datum/wound/new_wound = new potential_wound
- new_wound.apply_wound(src, smited = smited)
-
-/**
- * check_wounding_mods() is where we handle the various modifiers of a wound roll
- *
- * A short list of things we consider: any armor a human target may be wearing, and if they have no wound armor on the limb, if we have a bare_wound_bonus to apply, plus the plain wound_bonus
- * We also flick through all of the wounds we currently have on this limb and add their threshold penalties, so that having lots of bad wounds makes you more liable to get hurt worse
- * Lastly, we add the inherent wound_resistance variable the bodypart has (heads and chests are slightly harder to wound), and a small bonus if the limb is already disabled
- *
- * Arguments:
- * * It's the same ones on [/obj/item/bodypart/proc/receive_damage]
- */
-/obj/item/bodypart/proc/check_woundings_mods(wounding_type, damage, wound_bonus, bare_wound_bonus)
- var/armor_ablation = 0
- var/injury_mod = 0
-
- if(owner && ishuman(owner))
- var/mob/living/carbon/human/human_owner = owner
- var/list/clothing = human_owner.clothingonpart(src)
- for(var/obj/item/clothing/clothes as anything in clothing)
- // unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary
- armor_ablation += clothes.armor.getRating(WOUND)
- if(wounding_type == WOUND_SLASH)
- clothes.take_damage_zone(body_zone, damage, BRUTE)
- else if(wounding_type == WOUND_BURN && damage >= 10) // lazy way to block freezing from shredding clothes without adding another var onto apply_damage()
- clothes.take_damage_zone(body_zone, damage, BURN)
-
- if(!armor_ablation)
- injury_mod += bare_wound_bonus
-
- injury_mod -= armor_ablation
- injury_mod += wound_bonus
-
- for(var/datum/wound/wound as anything in wounds)
- injury_mod += wound.threshold_penalty
-
- var/part_mod = -wound_resistance
- if(get_damage(TRUE) >= max_damage)
- part_mod += disabled_wound_penalty
-
- injury_mod += part_mod
-
- return injury_mod
-
//Heals brute and burn damage for the organ. Returns 1 if the damage-icon states changed at all.
//Damage cannot go below zero.
//Cannot remove negative damage (i.e. apply damage)
/obj/item/bodypart/proc/heal_damage(brute, burn, stamina, required_status, updating_health = TRUE)
+ SHOULD_CALL_PARENT(TRUE)
- if(required_status && status != required_status) //So we can only heal certain kinds of limbs, ie robotic vs organic.
+ if(required_status && !(bodytype & required_status)) //So we can only heal certain kinds of limbs, ie robotic vs organic.
return
if(brute)
@@ -579,6 +457,8 @@
///Proc to hook behavior associated to the change of the brute_dam variable's value.
/obj/item/bodypart/proc/set_brute_dam(new_value)
+ PROTECTED_PROC(TRUE)
+
if(brute_dam == new_value)
return
. = brute_dam
@@ -587,6 +467,8 @@
///Proc to hook behavior associated to the change of the burn_dam variable's value.
/obj/item/bodypart/proc/set_burn_dam(new_value)
+ PROTECTED_PROC(TRUE)
+
if(burn_dam == new_value)
return
. = burn_dam
@@ -595,15 +477,12 @@
///Proc to hook behavior associated to the change of the stamina_dam variable's value.
/obj/item/bodypart/proc/set_stamina_dam(new_value)
+ PROTECTED_PROC(TRUE)
+
if(stamina_dam == new_value)
return
. = stamina_dam
stamina_dam = new_value
- if(stamina_dam > DAMAGE_PRECISION)
- needs_processing = TRUE
- else
- needs_processing = FALSE
-
//Returns total damage.
/obj/item/bodypart/proc/get_damage(include_stamina = FALSE)
@@ -612,9 +491,10 @@
total = max(total, stamina_dam)
return total
-
//Checks disabled status thresholds
/obj/item/bodypart/proc/update_disabled()
+ SHOULD_CALL_PARENT(TRUE)
+
if(!owner)
return
@@ -655,6 +535,9 @@
///Proc to change the value of the `disabled` variable and react to the event of its change.
/obj/item/bodypart/proc/set_disabled(new_disabled)
+ SHOULD_CALL_PARENT(TRUE)
+ PROTECTED_PROC(TRUE)
+
if(bodypart_disabled == new_disabled)
return
. = bodypart_disabled
@@ -668,6 +551,8 @@
///Proc to change the value of the `owner` variable and react to the event of its change.
/obj/item/bodypart/proc/set_owner(new_owner)
+ SHOULD_CALL_PARENT(TRUE)
+
if(owner == new_owner)
return FALSE //`null` is a valid option, so we need to use a num var to make it clear no change was made.
. = owner
@@ -697,6 +582,9 @@
///Proc to change the value of the `can_be_disabled` variable and react to the event of its change.
/obj/item/bodypart/proc/set_can_be_disabled(new_can_be_disabled)
+ PROTECTED_PROC(TRUE)
+ SHOULD_CALL_PARENT(TRUE)
+
if(can_be_disabled == new_can_be_disabled)
return
. = can_be_disabled
@@ -719,32 +607,42 @@
///Called when TRAIT_PARALYSIS is added to the limb.
/obj/item/bodypart/proc/on_paralysis_trait_gain(obj/item/bodypart/source)
+ PROTECTED_PROC(TRUE)
SIGNAL_HANDLER
+
if(can_be_disabled)
set_disabled(TRUE)
///Called when TRAIT_PARALYSIS is removed from the limb.
/obj/item/bodypart/proc/on_paralysis_trait_loss(obj/item/bodypart/source)
+ PROTECTED_PROC(TRUE)
SIGNAL_HANDLER
+
if(can_be_disabled)
update_disabled()
///Called when TRAIT_NOLIMBDISABLE is added to the owner.
/obj/item/bodypart/proc/on_owner_nolimbdisable_trait_gain(mob/living/carbon/source)
+ PROTECTED_PROC(TRUE)
SIGNAL_HANDLER
+
set_can_be_disabled(FALSE)
///Called when TRAIT_NOLIMBDISABLE is removed from the owner.
/obj/item/bodypart/proc/on_owner_nolimbdisable_trait_loss(mob/living/carbon/source)
+ PROTECTED_PROC(TRUE)
SIGNAL_HANDLER
+
set_can_be_disabled(initial(can_be_disabled))
//Updates an organ's brute/burn states for use by update_damage_overlays()
//Returns 1 if we need to update overlays. 0 otherwise.
/obj/item/bodypart/proc/update_bodypart_damage_state()
+ SHOULD_CALL_PARENT(TRUE)
+
var/tbrute = round( (brute_dam/max_damage)*3, 1 )
var/tburn = round( (burn_dam/max_damage)*3, 1 )
if((tbrute != brutestate) || (tburn != burnstate))
@@ -753,132 +651,93 @@
return TRUE
return FALSE
-//Change organ status
-/obj/item/bodypart/proc/change_bodypart_status(new_limb_status, heal_limb, change_icon_to_default)
- status = new_limb_status
- if(heal_limb)
- burn_dam = 0
- brute_dam = 0
- brutestate = 0
- burnstate = 0
-
- if(change_icon_to_default)
- if(status == BODYPART_ORGANIC)
- icon = icon_greyscale
- organic_render = TRUE //SKYRAT EDIT ADDITION - CUSTOMIZATION
- else if(status == BODYPART_ROBOTIC)
- icon = icon_robotic
- organic_render = FALSE //SKYRAT EDIT ADDITION - CUSTOMIZATION
-
- if(owner)
- owner.updatehealth()
- owner.update_body() //if our head becomes robotic, we remove the lizard horns and human hair.
- owner.update_hair()
- owner.update_damage_overlays()
-
-/obj/item/bodypart/proc/is_organic_limb()
- return (status == BODYPART_ORGANIC)
-
//we inform the bodypart of the changes that happened to the owner, or give it the informations from a source mob.
-/obj/item/bodypart/proc/update_limb(dropping_limb, mob/living/carbon/source)
- var/mob/living/carbon/limb_owner
- if(source)
- limb_owner = source
- if(!original_owner)
- original_owner = WEAKREF(source)
- else
- limb_owner = owner
- if(original_owner && !IS_WEAKREF_OF(owner, original_owner)) //Foreign limb
- no_update = TRUE
- else
- no_update = FALSE
+//set is_creating to true if you want to change the appearance of the limb outside of mutation changes or forced changes.
+/obj/item/bodypart/proc/update_limb(dropping_limb = FALSE, is_creating = FALSE)
+ SHOULD_CALL_PARENT(TRUE)
- if(HAS_TRAIT(limb_owner, TRAIT_HUSK) && is_organic_limb())
- species_id = "husk" //overrides species_id
+ if(HAS_TRAIT(owner, TRAIT_HUSK) && IS_ORGANIC_LIMB(src))
dmg_overlay_type = "" //no damage overlay shown when husked
- should_draw_gender = FALSE
- should_draw_greyscale = FALSE
- no_update = TRUE
+ is_husked = TRUE
+ else
+ dmg_overlay_type = initial(dmg_overlay_type)
+ is_husked = FALSE
- if(HAS_TRAIT(src, TRAIT_PLASMABURNT) && is_organic_limb())
- species_id = SPECIES_PLASMAMAN
- dmg_overlay_type = ""
- should_draw_gender = FALSE
- should_draw_greyscale = FALSE
- no_update = TRUE
+ if(!dropping_limb && owner.dna?.check_mutation(/datum/mutation/human/hulk)) //Please remove hulk from the game. I beg you.
+ mutation_color = "#00aa00"
+ else
+ mutation_color = null
- if(HAS_TRAIT(limb_owner, TRAIT_INVISIBLE_MAN) && is_organic_limb())
- species_id = "invisible" //overrides species_id
- dmg_overlay_type = "" //no damage overlay shown when invisible since the wounds themselves are invisible.
- should_draw_gender = FALSE
- should_draw_greyscale = FALSE
- no_update = TRUE
+ if(mutation_color)
+ draw_color = mutation_color
+ else if(should_draw_greyscale)
+ draw_color = (species_color) || (skin_tone && skintone2hex(skin_tone))
+ else
+ draw_color = null
- if(no_update)
+ if(!is_creating)
return
- if(!animal_origin)
- var/mob/living/carbon/human/human_owner = limb_owner
- should_draw_greyscale = FALSE
+ if(!animal_origin && ishuman(owner))
+ var/mob/living/carbon/human/human_owner = owner
var/datum/species/owner_species = human_owner.dna.species
- if(organic_render) //SKYRAT EDIT ADDITION - CUSTOMIZATION
- species_id = owner_species.limbs_id
- alpha = owner_species.specific_alpha
- rendered_bp_icon = owner_species.limbs_icon //SKYRAT EDIT ADDITION - CUSTOMIZATION
- species_id = owner_species.limbs_id
species_flags_list = human_owner.dna.species.species_traits
+ limb_gender = (human_owner.physique == MALE) ? "m" : "f"
if(owner_species.use_skintones)
skin_tone = human_owner.skin_tone
- should_draw_greyscale = TRUE
else
skin_tone = ""
- body_gender = human_owner.body_type
- should_draw_gender = owner_species.sexes
-
- if((MUTCOLORS in owner_species.species_traits) || (DYNCOLORS in owner_species.species_traits))
+ if(((MUTCOLORS in owner_species.species_traits) || (DYNCOLORS in owner_species.species_traits)) && uses_mutcolor) //Ethereal code. Motherfuckers.
if(owner_species.fixed_mut_color)
species_color = owner_species.fixed_mut_color
else
species_color = human_owner.dna.features["mcolor"]
- should_draw_greyscale = TRUE
else
- species_color = ""
+ species_color = null
- if(!dropping_limb && human_owner.dna.check_mutation(/datum/mutation/human/hulk))
- mutation_color = "#00aa00"
- else
- mutation_color = ""
+ draw_color = mutation_color
+ if(should_draw_greyscale) //Should the limb be colored?
+ draw_color ||= (species_color) || (skin_tone && skintone2hex(skin_tone))
dmg_overlay_type = owner_species.damage_overlay_type
+ // SKYRAT EDIT ADDITION
+ markings = LAZYCOPY(owner_species.body_markings[body_zone])
+ if(aux_zone)
+ aux_zone_markings = LAZYCOPY(owner_species.body_markings[aux_zone])
+ markings_alpha = owner_species.markings_alpha
+ // SKYRAT EDIT END
+
else if(animal_origin == MONKEY_BODYPART) //currently monkeys are the only non human mob to have damage overlays.
dmg_overlay_type = animal_origin
- if(status == BODYPART_ROBOTIC)
+ if(!IS_ORGANIC_LIMB(src))
dmg_overlay_type = "robotic"
- if(dropping_limb)
- no_update = TRUE //when attached, the limb won't be affected by the appearance changes of its mob owner.
+ return TRUE
//to update the bodypart's icon when not attached to a mob
/obj/item/bodypart/proc/update_icon_dropped()
+ SHOULD_CALL_PARENT(TRUE)
+
cut_overlays()
var/list/standing = get_limb_icon(TRUE)
if(!standing.len)
icon_state = initial(icon_state)//no overlays found, we default back to initial icon.
return
- for(var/image/img in standing)
+ for(var/image/img as anything in standing)
img.pixel_x = px_x
img.pixel_y = px_y
add_overlay(standing)
-//Gives you a proper icon appearance for the dismembered limb
-//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular)
-/*
-/obj/item/bodypart/proc/get_limb_icon(dropped, draw_external_organs)
+///Generates an /image for the limb to be used as an overlay
+/obj/item/bodypart/proc/get_limb_icon(dropped)
+ SHOULD_CALL_PARENT(TRUE)
+ RETURN_TYPE(/list)
+
icon_state = "" //to erase the default sprite, we're building the visual aspects of the bodypart through overlays alone.
. = list()
@@ -897,9 +756,9 @@
. += limb
if(animal_origin)
- if(is_organic_limb())
+ if(IS_ORGANIC_LIMB(src))
limb.icon = 'icons/mob/animal_parts.dmi'
- if(species_id == "husk")
+ if(limb_id == "husk")
limb.icon_state = "[animal_origin]_husk_[body_zone]"
else
limb.icon_state = "[animal_origin]_[body_zone]"
@@ -913,121 +772,132 @@
limb.overlays += limb_em_block
return
- var/icon_gender = (body_gender == FEMALE) ? "f" : "m" //gender of the icon, if applicable
-
- if((body_zone != BODY_ZONE_HEAD && body_zone != BODY_ZONE_CHEST))
- should_draw_gender = FALSE
-
- var/draw_color
-
- if(!is_organic_limb())
- limb.icon = icon
- limb.icon_state = "[body_zone]" //Inorganic limbs are agender
-
- if(blocks_emissive)
- var/mutable_appearance/limb_em_block = emissive_blocker(limb.icon, limb.icon_state, alpha = limb.alpha)
- limb_em_block.dir = image_dir
- limb.overlays += limb_em_block
-
- if(aux_zone)
- aux = image(limb.icon, "[aux_zone]", -aux_layer, image_dir)
+ //HUSK SHIIIIT
+ if(is_husked)
+ limb.icon = icon_husk
+ limb.icon_state = "[husk_type]_husk_[body_zone]"
+ icon_exists(limb.icon, limb.icon_state, scream = TRUE) //Prints a stack trace on the first failure of a given iconstate.
+ if(aux_zone) //Hand shit
+ aux = image(limb.icon, "[husk_type]_husk_[aux_zone]", -aux_layer, image_dir)
. += aux
+ return .
+ //END HUSK SHIIIIT
- if(blocks_emissive)
- var/mutable_appearance/aux_em_block = emissive_blocker(aux.icon, aux.icon_state, alpha = aux.alpha)
- aux_em_block.dir = image_dir
- aux.overlays += aux_em_block
+ ////This is the MEAT of limb icon code
+ limb.icon = icon_greyscale
+ if(!should_draw_greyscale || !icon_greyscale)
+ limb.icon = icon_static
+ if(is_dimorphic) //Does this type of limb have sexual dimorphism?
+ limb.icon_state = "[limb_id]_[body_zone]_[limb_gender]"
else
- if(should_draw_greyscale)
- limb.icon = icon_greyscale
- if(should_draw_gender)
- limb.icon_state = "[species_id]_[body_zone]_[icon_gender]"
- else if(use_digitigrade)
- limb.icon_state = "digitigrade_[use_digitigrade]_[body_zone]"
- else
- limb.icon_state = "[species_id]_[body_zone]"
- else
- limb.icon = 'icons/mob/human_parts.dmi'
- if(should_draw_gender)
- limb.icon_state = "[species_id]_[body_zone]_[icon_gender]"
- else
- limb.icon_state = "[species_id]_[body_zone]"
+ limb.icon_state = "[limb_id]_[body_zone]"
+
+ icon_exists(limb.icon, limb.icon_state, TRUE) //Prints a stack trace on the first failure of a given iconstate.
+
+ if(aux_zone) //Hand shit
+ aux = image(limb.icon, "[limb_id]_[aux_zone]", -aux_layer, image_dir)
+ . += aux
+
+ draw_color = mutation_color
+ if(should_draw_greyscale) //Should the limb be colored outside of a forced color?
+ draw_color ||= (species_color) || (skin_tone && skintone2hex(skin_tone))
+
+ if(draw_color)
+ limb.color = "[draw_color]"
+ if(aux_zone)
+ aux.color = "[draw_color]"
+
+ //EMISSIVE CODE START
+ if(blocks_emissive)
+ var/mutable_appearance/limb_em_block = emissive_blocker(limb.icon, limb.icon_state, alpha = limb.alpha)
+ limb_em_block.dir = image_dir
+ limb.overlays += limb_em_block
if(aux_zone)
- aux = image(limb.icon, "[species_id]_[aux_zone]", -aux_layer, image_dir)
- . += aux
-
- if(should_draw_greyscale)
- draw_color = mutation_color || species_color || (skin_tone && skintone2hex(skin_tone))
- if(draw_color)
- limb.color = draw_color
- if(aux_zone)
- aux.color = draw_color
-
- if(blocks_emissive)
- var/mutable_appearance/limb_em_block = emissive_blocker(limb.icon, limb.icon_state, alpha = limb.alpha)
- limb_em_block.dir = image_dir
- limb.overlays += limb_em_block
-
- if(aux_zone)
- var/mutable_appearance/aux_em_block = emissive_blocker(aux.icon, aux.icon_state, alpha = aux.alpha)
- aux_em_block.dir = image_dir
- aux.overlays += aux_em_block
-
- if(!draw_external_organs)
- return
+ var/mutable_appearance/aux_em_block = emissive_blocker(aux.icon, aux.icon_state, alpha = aux.alpha)
+ aux_em_block.dir = image_dir
+ aux.overlays += aux_em_block
+ //EMISSIVE CODE END
//Draw external organs like horns and frills
for(var/obj/item/organ/external/external_organ in external_organs)
if(!dropped && !external_organ.can_draw_on_bodypart(owner))
continue
//Some externals have multiple layers for background, foreground and between
for(var/external_layer in external_organ.all_layers)
- if(istype(external_organ, /obj/item/organ/external/pod_hair))
- var/rgb_list = rgb2num(draw_color, COLORSPACE_RGB)
- // Invert the colour of the pod hair's flower
- draw_color = rgb(255 - rgb_list[1], 255 - rgb_list[2], 255 - rgb_list[3])
if(external_organ.layers & external_layer)
- external_organ.get_overlays(., image_dir, external_organ.bitflag_to_layer(external_layer), icon_gender, draw_color)
-*/
-//SKYRAT EDIT REMOVAL END
+ external_organ.get_overlays(
+ .,
+ image_dir,
+ external_organ.bitflag_to_layer(external_layer),
+ limb_gender,
+ external_organ.overrides_color ? external_organ.override_color(draw_color) : draw_color
+ )
+
+ // SKYRAT EDIT ADDITION BEGIN - MARKINGS CODE
+ var/override_color
+ // First, check to see if this bodypart is husked. If so, we don't want to apply our sparkledog colors to the limb.
+ if(is_husked)
+ override_color = "#888888"
+ // We need to check that the owner exists(could be a placed bodypart) and that it's not a chainsawhand and that they're a human with usable DNA.
+ if(!is_pseudopart)
+ for(var/key in markings) // Cycle through all of our currently selected markings.
+ var/datum/body_marking/body_marking = GLOB.body_markings[key]
+ if (!body_marking) // Edge case prevention.
+ continue
+
+ var/render_limb_string = limb_id == "digitigrade" ? ("digitigrade_1_" + body_zone) : body_zone // I am not sure why there are _1 and _2 versions of digi, so, it's staying like this.
+
+ var/gender_modifier = ""
+ if(body_zone == BODY_ZONE_CHEST) // Chest markings have male and female versions.
+ if(is_dimorphic)
+ gender_modifier = "_[limb_gender]"
+ else
+ gender_modifier = "_m" // Again, why we don't define if a marking can have male/female is byond me.
+
+ var/mutable_appearance/accessory_overlay
+ var/mutable_appearance/emissive
+ accessory_overlay = mutable_appearance(body_marking.icon, "[body_marking.icon_state]_[render_limb_string][gender_modifier]", -BODYPARTS_LAYER)
+ accessory_overlay.alpha = markings_alpha
+ if(markings[key][2])
+ emissive = emissive_appearance_copy(accessory_overlay)
+ if(override_color)
+ accessory_overlay.color = override_color
+ else
+ accessory_overlay.color = markings[key][1]
+ . += accessory_overlay
+ if (emissive)
+ . += emissive
+
+ if(aux_zone)
+ for(var/key in aux_zone_markings)
+ var/datum/body_marking/body_marking = GLOB.body_markings[key]
+ if (!body_marking) // Edge case prevention.
+ continue
+
+ var/render_limb_string = aux_zone
+
+ var/mutable_appearance/emissive
+ var/mutable_appearance/accessory_overlay
+ accessory_overlay = mutable_appearance(body_marking.icon, "[body_marking.icon_state]_[render_limb_string]", -aux_layer)
+ accessory_overlay.alpha = markings_alpha
+ if (aux_zone_markings[key][2])
+ emissive = emissive_appearance_copy(accessory_overlay)
+ if(override_color)
+ accessory_overlay.color = override_color
+ else
+ accessory_overlay.color = aux_zone_markings[key][1]
+ . += accessory_overlay
+ if (emissive)
+ . += emissive
+ // SKYRAT EDIT END - MARKINGS CODE END
/obj/item/bodypart/deconstruct(disassembled = TRUE)
+ SHOULD_CALL_PARENT(TRUE)
+
drop_organs()
- qdel(src)
-
-/// Get whatever wound of the given type is currently attached to this limb, if any
-/obj/item/bodypart/proc/get_wound_type(checking_type)
- if(isnull(wounds))
- return
-
- for(var/wound in wounds)
- if(istype(wound, checking_type))
- return wound
-
-/**
- * update_wounds() is called whenever a wound is gained or lost on this bodypart, as well as if there's a change of some kind on a bone wound possibly changing disabled status
- *
- * Covers tabulating the damage multipliers we have from wounds (burn specifically), as well as deleting our gauze wrapping if we don't have any wounds that can use bandaging
- *
- * Arguments:
- * * replaced- If true, this is being called from the remove_wound() of a wound that's being replaced, so the bandage that already existed is still relevant, but the new wound hasn't been added yet
- */
-/obj/item/bodypart/proc/update_wounds(replaced = FALSE)
- var/dam_mul = 1 //initial(wound_damage_multiplier)
-
- // we can (normally) only have one wound per type, but remember there's multiple types (smites like :B:loodless can generate multiple cuts on a limb)
- for(var/datum/wound/iter_wound as anything in wounds)
- dam_mul *= iter_wound.damage_mulitplier_penalty
-
- /*
- if(!LAZYLEN(wounds) && current_gauze && !replaced) // no more wounds = no need for the gauze anymore
- owner.visible_message(span_notice("\The [current_gauze.name] on [owner]'s [name] falls away."), span_notice("The [current_gauze.name] on your [name] falls away."))
- QDEL_NULL(current_gauze)
- */
-
- wound_damage_multiplier = dam_mul
+ return ..()
/**
* Calculates how much blood this limb is losing per life tick
@@ -1036,9 +906,11 @@
* * ignore_modifiers - If TRUE, ignore the bleed reduction for laying down and grabbing your limb
*/
/obj/item/bodypart/proc/get_part_bleed_rate(ignore_modifiers = FALSE)
+ SHOULD_NOT_OVERRIDE(TRUE)
+
if(HAS_TRAIT(owner, TRAIT_NOBLEED))
return
- if(status != BODYPART_ORGANIC) // maybe in the future we can bleed oil from aug parts, but not now
+ if(!IS_ORGANIC_LIMB(src))// maybe in the future we can bleed oil from aug parts, but not now
return
var/bleed_rate = 0
@@ -1073,7 +945,7 @@
/obj/item/bodypart/proc/update_part_wound_overlay()
if(!owner)
return FALSE
- if(HAS_TRAIT(owner, TRAIT_NOBLEED) || status != BODYPART_ORGANIC)
+ if(HAS_TRAIT(owner, TRAIT_NOBLEED) || !IS_ORGANIC_LIMB(src) || (NOBLOOD in species_flags_list))
if(bleed_overlay_icon)
bleed_overlay_icon = null
owner.update_wound_overlays()
@@ -1117,7 +989,7 @@
* Arguments:
* * gauze- Just the gauze stack we're taking a sheet from to apply here
*/
-/*
+/* SKYRAT EDIT REMOVAL
/obj/item/bodypart/proc/apply_gauze(obj/item/stack/gauze)
if(!istype(gauze) || !gauze.absorption_capacity)
return
@@ -1139,7 +1011,7 @@
* Arguments:
* * seep_amt - How much absorption capacity we're removing from our current bandages (think, how much blood or pus are we soaking up this tick?)
*/
-/*
+/* SKYRAT EDIT REMOVAL
/obj/item/bodypart/proc/seep_gauze(seep_amt = 0)
if(!current_gauze)
return
@@ -1153,8 +1025,8 @@
///Proc to turn bodypart into another.
/obj/item/bodypart/proc/change_bodypart(obj/item/bodypart/new_type)
+ RETURN_TYPE(/obj/item/bodypart)
+
var/mob/living/carbon/our_owner = owner //dropping nulls the limb
- drop_limb(TRUE)
var/obj/item/bodypart/new_part = new new_type()
- new_part.attach_limb(our_owner, TRUE)
- qdel(src)
+ new_part.replace_limb(our_owner, TRUE)
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index c50064ee942..4671c9b8d22 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -129,6 +129,7 @@
organ.transfer_to_limb(src, phantom_owner)
update_icon_dropped()
+ synchronize_bodytypes(phantom_owner)
phantom_owner.update_health_hud() //update the healthdoll
phantom_owner.update_body()
phantom_owner.update_hair()
@@ -292,10 +293,6 @@
if(pill)
pill.forceMove(src)
- //Make sure de-zombification happens before organ removal instead of during it
- var/obj/item/organ/zombie_infection/ooze = owner.getorganslot(ORGAN_SLOT_ZOMBIE)
- if(istype(ooze))
- ooze.transfer_to_limb(src, owner)
name = "[owner.real_name]'s head"
..()
@@ -303,11 +300,13 @@
/obj/item/bodypart/proc/replace_limb(mob/living/carbon/limb_owner, special)
if(!istype(limb_owner))
return
- var/obj/item/bodypart/limb = limb_owner.get_bodypart(body_zone) //needs to happen before attach because multiple limbs in same zone breaks helpers
- if(!attach_limb(limb_owner, special))//we can attach this limb and drop the old after because of our robust bodyparts system. you know, just for a sec.
- return
- if(limb)
- limb.drop_limb(1)
+ var/obj/item/bodypart/old_limb = limb_owner.get_bodypart(body_zone)
+ if(old_limb)
+ old_limb.drop_limb(TRUE)
+
+ . = attach_limb(limb_owner, special)
+ if(!.) //If it failed to replace, re-attach their old limb as if nothing happened.
+ old_limb.attach_limb(limb_owner, TRUE)
/obj/item/bodypart/head/replace_limb(mob/living/carbon/head_owner, special)
if(!istype(head_owner))
@@ -321,7 +320,11 @@
/obj/item/bodypart/proc/attach_limb(mob/living/carbon/new_limb_owner, special)
if(SEND_SIGNAL(new_limb_owner, COMSIG_CARBON_ATTACH_LIMB, src, special) & COMPONENT_NO_ATTACH)
return FALSE
- . = TRUE
+
+ var/obj/item/bodypart/chest/mob_chest = new_limb_owner.get_bodypart(BODY_ZONE_CHEST)
+ if(mob_chest && !(mob_chest.acceptable_bodytype & bodytype) && !special)
+ return FALSE
+
moveToNullspace()
set_owner(new_limb_owner)
new_limb_owner.add_bodypart(src)
@@ -364,20 +367,14 @@
if(can_be_disabled)
update_disabled()
+ synchronize_bodytypes(new_limb_owner)
new_limb_owner.updatehealth()
new_limb_owner.update_body()
- new_limb_owner.update_hair()
new_limb_owner.update_damage_overlays()
-
+ return TRUE
/obj/item/bodypart/head/attach_limb(mob/living/carbon/new_head_owner, special = FALSE, abort = FALSE)
// These are stored before calling super. This is so that if the head is from a different body, it persists its appearance.
- var/hair_color = src.hair_color
- var/hairstyle = src.hairstyle
- var/facial_hair_color = src.facial_hair_color
- var/facial_hairstyle = src.facial_hairstyle
- var/lip_style = src.lip_style
- var/lip_color = src.lip_color
var/real_name = src.real_name
. = ..()
@@ -400,17 +397,9 @@
if(eyes)
eyes = null
- if(ishuman(new_head_owner))
- var/mob/living/carbon/human/human_head_owner = new_head_owner
- human_head_owner.hair_color = hair_color
- human_head_owner.hairstyle = hairstyle
- human_head_owner.facial_hair_color = facial_hair_color
- human_head_owner.facial_hairstyle = facial_hairstyle
- human_head_owner.update_lips(lip_style, lip_color, stored_lipstick_trait)
if(real_name)
new_head_owner.real_name = real_name
real_name = ""
- name = initial(name)
//Handle dental implants
for(var/obj/item/reagent_containers/pill/pill in src)
@@ -421,47 +410,57 @@
new_head_owner.updatehealth()
new_head_owner.update_body()
- new_head_owner.update_hair()
new_head_owner.update_damage_overlays()
+///Makes sure that the owner's bodytype flags match the flags of all of it's parts.
+/obj/item/bodypart/proc/synchronize_bodytypes(mob/living/carbon/carbon_owner)
+ if(!carbon_owner.dna.species)
+ return
+ var/all_limb_flags
+ for(var/obj/item/bodypart/limb as anything in carbon_owner.bodyparts)
+ all_limb_flags = all_limb_flags | limb.bodytype
+
+ carbon_owner.dna.species.bodytype = all_limb_flags
//Regenerates all limbs. Returns amount of limbs regenerated
-/mob/living/proc/regenerate_limbs(noheal = FALSE, list/excluded_zones = list())
- SEND_SIGNAL(src, COMSIG_LIVING_REGENERATE_LIMBS, noheal, excluded_zones)
+/mob/living/proc/regenerate_limbs(list/excluded_zones = list())
+ SEND_SIGNAL(src, COMSIG_LIVING_REGENERATE_LIMBS, excluded_zones)
-/mob/living/carbon/regenerate_limbs(noheal = FALSE, list/excluded_zones = list())
- . = ..()
+/mob/living/carbon/regenerate_limbs(list/excluded_zones = list())
+ SEND_SIGNAL(src, COMSIG_LIVING_REGENERATE_LIMBS, excluded_zones)
var/list/zone_list = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
if(length(excluded_zones))
zone_list -= excluded_zones
for(var/limb_zone in zone_list)
- . += regenerate_limb(limb_zone, noheal)
+ regenerate_limb(limb_zone)
-/mob/living/proc/regenerate_limb(limb_zone, noheal)
+/mob/living/proc/regenerate_limb(limb_zone)
return
-/mob/living/carbon/regenerate_limb(limb_zone, noheal)
+/mob/living/carbon/regenerate_limb(limb_zone)
var/obj/item/bodypart/limb
if(get_bodypart(limb_zone))
return FALSE
limb = newBodyPart(limb_zone, 0, 0)
if(limb)
- if(!noheal)
- limb.set_brute_dam(0)
- limb.set_burn_dam(0)
- limb.brutestate = 0
- limb.burnstate = 0
-
- //SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION
- if(dna?.species && (ROBOTIC_LIMBS in dna.species.species_traits))
- limb.change_bodypart_status(BODYPART_ROBOTIC)
- if(dna?.mutant_bodyparts["legs"] && dna.mutant_bodyparts["legs"][MUTANT_INDEX_NAME] == "Digitigrade Legs")
- limb.use_digitigrade = FULL_DIGITIGRADE
- //SKYRAT EDIT ADDITION END
if(!limb.attach_limb(src, 1))
qdel(limb)
return FALSE
+ limb.update_limb(is_creating = TRUE)
var/datum/scar/scaries = new
var/datum/wound/loss/phantom_loss = new // stolen valor, really
scaries.generate(limb, phantom_loss)
+
+ //Copied from /datum/species/proc/on_species_gain()
+ for(var/obj/item/organ/external/organ_path as anything in dna.species.external_organs)
+ //Load a persons preferences from DNA
+ var/zone = initial(organ_path.zone)
+ if(zone != limb_zone)
+ continue
+ var/feature_key_name = dna.features[initial(organ_path.feature_key)]
+ var/obj/item/organ/external/new_organ = SSwardrobe.provide_type(organ_path)
+ new_organ.set_sprite(feature_key_name)
+ new_organ.Insert(src)
+
+ update_body_parts()
return TRUE
diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm
index f05659a9835..d70169c314d 100644
--- a/code/modules/surgery/bodyparts/head.dm
+++ b/code/modules/surgery/bodyparts/head.dm
@@ -17,6 +17,7 @@
disabled_wound_penalty = 25
scars_covered_by_clothes = FALSE
grind_results = null
+ is_dimorphic = TRUE
var/mob/living/brain/brainmob //The current occupant.
var/obj/item/organ/brain/brain //The brain organ
@@ -29,19 +30,47 @@
//Limb appearance info:
var/real_name = "" //Replacement name
- //Hair colour and style
+ ///Hair color source
+ var/hair_color_source = null
+ ///Hair colour and style
var/hair_color = "#000000"
- var/hairstyle = "Bald"
+ ///An override color that can be cleared later.
+ var/override_hair_color = null
+ ///An override that cannot be cleared under any circumstances
+ var/fixed_hair_color = null
+
+ var/hair_style = "Bald"
var/hair_alpha = 255
+ var/hair_gradient_style = null
+ var/hair_gradient_color = null
//Facial hair colour and style
var/facial_hair_color = "#000000"
var/facial_hairstyle = "Shaved"
- //Eye Colouring
+ var/facial_hair_gradient_style = null
+ var/facial_hair_gradient_color = null
+ ///Is the hair currently hidden by something?
+ var/hair_hidden
+ ///Is the facial hair currently hidden by something?
+ var/facial_hair_hidden
+ ///Draw this head as "debrained"
+ VAR_PROTECTED/show_debrained = FALSE
+
+
var/lip_style
var/lip_color = "white"
var/stored_lipstick_trait
+ ///The image for hair
+ var/mutable_appearance/hair_overlay
+ ///The image for hair gradient
+ var/mutable_appearance/hair_gradient_overlay
+ ///The image for face hair
+ var/mutable_appearance/facial_overlay
+ ///The image for facial hair gradient
+ var/mutable_appearance/facial_gradient_overlay
+
+
/obj/item/bodypart/head/Destroy()
@@ -72,7 +101,7 @@
/obj/item/bodypart/head/examine(mob/user)
. = ..()
- if(status == BODYPART_ORGANIC && show_organs_on_examine)
+ if(IS_ORGANIC_LIMB(src) && show_organs_on_examine)
if(!brain)
. += span_info("The brain has been removed from [src].")
else if(brain.suicided || brainmob?.suiciding)
@@ -106,8 +135,6 @@
/obj/item/bodypart/head/drop_organs(mob/user, violent_removal)
var/turf/head_turf = get_turf(src)
- if(status != BODYPART_ROBOTIC)
- playsound(head_turf, 'sound/misc/splort.ogg', 50, TRUE, -1)
for(var/obj/item/head_item in src)
if(head_item == brain)
if(user)
@@ -136,86 +163,139 @@
ears = null
tongue = null
-/obj/item/bodypart/head/update_limb(dropping_limb, mob/living/carbon/source)
- var/mob/living/carbon/head_owner
- if(source)
- head_owner = source
- else
- head_owner = owner
+ return ..()
- real_name = head_owner.real_name
- if(HAS_TRAIT(head_owner, TRAIT_HUSK))
+#define SET_OVERLAY_VALUE(X,Y,Z) if(X) X.Y = Z
+/obj/item/bodypart/head/update_limb(dropping_limb, is_creating)
+ . = ..()
+
+ real_name = owner.real_name
+ if(HAS_TRAIT(owner, TRAIT_HUSK))
real_name = "Unknown"
- hairstyle = "Bald"
+ hair_style = "Bald"
facial_hairstyle = "Shaved"
lip_style = null
stored_lipstick_trait = null
- else if(!animal_origin)
- var/mob/living/carbon/human/human_head_owner = head_owner
+ else if(!animal_origin && ishuman(owner))
+
+ var/mob/living/carbon/human/human_head_owner = owner
var/datum/species/owner_species = human_head_owner.dna.species
- //Facial hair
- if(human_head_owner.facial_hairstyle && (FACEHAIR in owner_species.species_traits))
- facial_hairstyle = human_head_owner.facial_hairstyle
- if(owner_species.hair_color)
- if(owner_species.hair_color == "mutcolor")
- facial_hair_color = human_head_owner.dna.features["mcolor"]
- else if(hair_color == "fixedmutcolor")
- facial_hair_color = owner_species.fixed_mut_color
- else
- facial_hair_color = owner_species.hair_color
- else
- facial_hair_color = human_head_owner.facial_hair_color
- hair_alpha = owner_species.hair_alpha
- else
- facial_hairstyle = "Shaved"
- facial_hair_color = "#000000"
- hair_alpha = 255
- //Hair
- if(human_head_owner.hairstyle && (HAIR in owner_species.species_traits))
- hairstyle = human_head_owner.hairstyle
- if(owner_species.hair_color)
- if(owner_species.hair_color == "mutcolor")
- hair_color = human_head_owner.dna.features["mcolor"]
- else if(hair_color == "fixedmutcolor")
- hair_color = owner_species.fixed_mut_color
- else
- hair_color = owner_species.hair_color
- else
- hair_color = human_head_owner.hair_color
- hair_alpha = owner_species.hair_alpha
- else
- hairstyle = "Bald"
- hair_color = "#000000"
- hair_alpha = initial(hair_alpha)
- // lipstick
if(human_head_owner.lip_style && (LIPS in owner_species.species_traits))
lip_style = human_head_owner.lip_style
lip_color = human_head_owner.lip_color
else
lip_style = null
lip_color = "white"
- ..()
-/obj/item/bodypart/head/update_icon_dropped()
- var/list/standing = get_limb_icon(TRUE)
- if(!standing.len)
- icon_state = initial(icon_state)//no overlays found, we default back to initial icon.
- return
- for(var/image/img in standing)
- img.pixel_x = px_x
- img.pixel_y = px_y
- add_overlay(standing)
+ ///FACIAL HAIR CHECKS START
+ //we check if our hat or helmet hides our facial hair.
+ facial_hair_hidden = FALSE
+ if(human_head_owner.head)
+ var/obj/item/hat = human_head_owner.head
+ if(hat.flags_inv & HIDEFACIALHAIR)
+ facial_hair_hidden = TRUE
+
+ if(human_head_owner.wear_mask)
+ var/obj/item/mask = human_head_owner.wear_mask
+ if(mask.flags_inv & HIDEFACIALHAIR)
+ facial_hair_hidden = TRUE
+ ///FACIAL HAIR CHECKS END
+ ///HAIR CHECKS START
+ hair_hidden = FALSE
+ if(human_head_owner.head)
+ var/obj/item/hat = human_head_owner.head
+ if(hat.flags_inv & HIDEHAIR)
+ hair_hidden = TRUE
+
+ if(human_head_owner.w_uniform)
+ var/obj/item/item_uniform = human_head_owner.w_uniform
+ if(item_uniform.flags_inv & HIDEHAIR)
+ hair_hidden = TRUE
+
+ if(human_head_owner.wear_mask)
+ var/obj/item/mask = human_head_owner.wear_mask
+ if(mask.flags_inv & HIDEHAIR)
+ hair_hidden = TRUE
+ ///HAIR CHECKS END
+
+ if(!hair_hidden && !owner.getorgan(/obj/item/organ/brain) && !(NOBLOOD in species_flags_list))
+ show_debrained = TRUE
+ else
+ show_debrained = FALSE
+
+ //CREATION-ONLY START
+ if(is_creating)
+ var/datum/sprite_accessory/sprite_accessory
+
+ facial_overlay = null
+ facial_gradient_overlay = null
+ hair_overlay = null
+ hair_gradient_overlay = null
+
+ hair_alpha = owner_species.hair_alpha
+ hair_color = human_head_owner.hair_color
+ facial_hair_color = human_head_owner.hair_color
+ fixed_hair_color = owner_species.fixed_mut_color //Can be null
+ hair_style = human_head_owner.hairstyle
+ facial_hairstyle = human_head_owner.facial_hairstyle
+
+
+ if(facial_hairstyle && !facial_hair_hidden && (FACEHAIR in species_flags_list))
+ sprite_accessory = GLOB.facial_hairstyles_list[facial_hairstyle]
+ if(sprite_accessory)
+ //Create the overlay
+ facial_overlay = mutable_appearance(sprite_accessory.icon, sprite_accessory.icon_state, -HAIR_LAYER)
+ //Gradients
+ facial_hair_gradient_style = LAZYACCESS(human_head_owner.grad_style, GRADIENT_FACIAL_HAIR_KEY)
+ if(facial_hair_gradient_style)
+ facial_hair_gradient_color = LAZYACCESS(human_head_owner.grad_color, GRADIENT_FACIAL_HAIR_KEY)
+ facial_gradient_overlay = make_gradient_overlay(sprite_accessory.icon, sprite_accessory.icon_state, HAIR_LAYER, GLOB.facial_hair_gradients_list[facial_hair_gradient_style], facial_hair_gradient_color)
+
+ facial_overlay.overlays += emissive_blocker(sprite_accessory.icon, sprite_accessory.icon_state, alpha = hair_alpha)
+
+ if(!hair_hidden && !show_debrained && (HAIR in species_flags_list))
+ sprite_accessory = GLOB.hairstyles_list[hair_style]
+ if(sprite_accessory)
+ hair_overlay = mutable_appearance(sprite_accessory.icon, sprite_accessory.icon_state, -HAIR_LAYER)
+ hair_gradient_style = LAZYACCESS(human_head_owner.grad_style, GRADIENT_HAIR_KEY)
+ if(hair_gradient_style)
+ hair_gradient_color = LAZYACCESS(human_head_owner.grad_color, GRADIENT_HAIR_KEY)
+ hair_gradient_overlay = make_gradient_overlay(sprite_accessory.icon, sprite_accessory.icon_state, HAIR_LAYER, GLOB.hair_gradients_list[hair_gradient_style], hair_gradient_color)
+
+ //CREATION-ONLY END
+ //HAIR COLOR START
+ if(!override_hair_color)
+ if(hair_color_source)
+ if(hair_color_source == "fixedmutcolor")
+ SET_OVERLAY_VALUE(facial_overlay, color, fixed_hair_color)
+ SET_OVERLAY_VALUE(hair_overlay, color, fixed_hair_color)
+ else if(hair_color_source == "mutcolor")
+ SET_OVERLAY_VALUE(facial_overlay, color, facial_hair_color)
+ SET_OVERLAY_VALUE(hair_overlay, color, hair_color)
+ else
+ SET_OVERLAY_VALUE(facial_overlay, color, hair_color_source)
+ SET_OVERLAY_VALUE(hair_overlay, color, hair_color_source)
+ else
+ SET_OVERLAY_VALUE(facial_overlay, color, hair_color)
+ SET_OVERLAY_VALUE(hair_overlay, color, hair_color)
+ else
+ SET_OVERLAY_VALUE(facial_overlay, color, override_hair_color)
+ SET_OVERLAY_VALUE(hair_overlay, color, override_hair_color)
+ //HAIR COLOR END
+
+#undef SET_OVERLAY_VALUE
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/obj/item/bodypart/head/get_limb_icon(dropped, draw_external_organs)
cut_overlays()
. = ..()
if(dropped) //certain overlays only appear when the limb is being detached from its owner.
- if(status != BODYPART_ROBOTIC) //having a robotic head hides certain features.
+ if(IS_ORGANIC_LIMB(src)) //having a robotic head hides certain features.
//facial hair
- if(facial_hairstyle)
+ if(facial_hairstyle && (FACEHAIR in species_flags_list))
var/datum/sprite_accessory/sprite = GLOB.facial_hairstyles_list[facial_hairstyle]
if(sprite)
var/image/facial_overlay = image(sprite.icon, "[sprite.icon_state]", -HAIR_LAYER, SOUTH)
@@ -237,8 +317,8 @@
debrain_overlay.icon_state = "debrained"
. += debrain_overlay
else
- var/datum/sprite_accessory/sprite2 = GLOB.hairstyles_list[hairstyle]
- if(sprite2)
+ var/datum/sprite_accessory/sprite2 = GLOB.hairstyles_list[hair_style]
+ if(sprite2 && (HAIR in species_flags_list))
var/image/hair_overlay = image(sprite2.icon, "[sprite2.icon_state]", -HAIR_LAYER, SOUTH)
hair_overlay.color = hair_color
hair_overlay.alpha = hair_alpha
@@ -260,6 +340,47 @@
if(eyes.eye_color)
eyes_overlay.color = eyes.eye_color
+ else
+ if(!facial_hair_hidden && facial_overlay && (FACEHAIR in species_flags_list))
+ facial_overlay.alpha = hair_alpha
+ . += facial_overlay
+ if(facial_gradient_overlay)
+ . += facial_gradient_overlay
+
+ if(show_debrained)
+ . += mutable_appearance('icons/mob/human_face.dmi', "debrained", HAIR_LAYER)
+
+ else if(!hair_hidden && hair_overlay && (HAIR in species_flags_list))
+ hair_overlay.alpha = hair_alpha
+ . += hair_overlay
+ if(hair_gradient_overlay)
+ . += hair_gradient_overlay
+///Set the haircolor of a human. Override instead sets the override value, it will not be changed away from the override value until override is set to null.
+/mob/proc/set_haircolor(hex_string, override)
+ return
+
+/mob/living/carbon/human/set_haircolor(hex_string, override)
+ var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD)
+ if(!my_head)
+ return
+
+ if(override)
+ my_head.override_hair_color = hex_string
+ else
+ my_head.hair_color = hex_string
+ update_hair(is_creating = TRUE)
+
+/obj/item/bodypart/head/proc/make_gradient_overlay(file, icon, layer, datum/sprite_accessory/gradient, grad_color)
+ RETURN_TYPE(/mutable_appearance)
+
+ var/mutable_appearance/gradient_overlay = mutable_appearance(layer = -layer)
+ var/icon/temp = icon(gradient.icon, gradient.icon_state)
+ var/icon/temp_hair = icon(file, icon)
+ temp.Blend(temp_hair, ICON_ADD)
+ gradient_overlay.icon = temp
+ gradient_overlay.color = grad_color
+ return gradient_overlay
+
/obj/item/bodypart/head/talk_into(mob/holder, message, channel, spans, datum/language/language, list/message_mods)
var/mob/headholder = holder
if(istype(headholder))
@@ -274,7 +395,9 @@
/obj/item/bodypart/head/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_head"
+ limb_id = SPECIES_MONKEY
animal_origin = MONKEY_BODYPART
+ bodytype = BODYTYPE_MONKEY | BODYTYPE_ORGANIC
/obj/item/bodypart/head/alien
icon = 'icons/mob/animal_parts.dmi'
diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm
index 56aa42af955..60be92d76d0 100644
--- a/code/modules/surgery/bodyparts/helpers.dm
+++ b/code/modules/surgery/bodyparts/helpers.dm
@@ -121,52 +121,23 @@
return TRUE
//Helper for quickly creating a new limb - used by augment code in species.dm spec_attacked_by
-/mob/living/carbon/proc/newBodyPart(zone, robotic, fixed_icon)
- var/obj/item/bodypart/new_bodypart
- switch(zone)
- if(BODY_ZONE_L_ARM)
- new_bodypart = new /obj/item/bodypart/l_arm()
- if(BODY_ZONE_R_ARM)
- new_bodypart = new /obj/item/bodypart/r_arm()
- if(BODY_ZONE_HEAD)
- new_bodypart = new /obj/item/bodypart/head()
- if(BODY_ZONE_L_LEG)
- new_bodypart = new /obj/item/bodypart/l_leg()
- if(BODY_ZONE_R_LEG)
- new_bodypart = new /obj/item/bodypart/r_leg()
- if(BODY_ZONE_CHEST)
- new_bodypart = new /obj/item/bodypart/chest()
- if(new_bodypart)
- new_bodypart.update_limb(fixed_icon, src)
- if(robotic)
- new_bodypart.change_bodypart_status(BODYPART_ROBOTIC)
- . = new_bodypart
+//
+// FUCK YOU AUGMENT CODE - With love, Kapu
+/mob/living/carbon/proc/newBodyPart(zone)
+ var/path = dna.species.bodypart_overrides[zone]
+ var/obj/item/bodypart/new_bodypart = new path()
+ return new_bodypart
-/mob/living/carbon/human/newBodyPart(zone, robotic, fixed_icon)
- var/obj/item/bodypart/bodypart
- var/datum/species/species = dna.species
- var/obj/item/bodypart/selected_type = species.bodypart_overides[zone]
- bodypart = new selected_type()
- if(bodypart)
- bodypart.update_limb(fixed_icon, src)
- if(robotic)
- bodypart.change_bodypart_status(BODYPART_ROBOTIC)
- . = bodypart
-
-/mob/living/carbon/alien/larva/newBodyPart(zone, robotic, fixed_icon)
+/mob/living/carbon/alien/larva/newBodyPart(zone)
var/obj/item/bodypart/new_bodypart
switch(zone)
if(BODY_ZONE_HEAD)
new_bodypart = new /obj/item/bodypart/head/larva()
if(BODY_ZONE_CHEST)
new_bodypart = new /obj/item/bodypart/chest/larva()
- if(new_bodypart)
- new_bodypart.update_limb(fixed_icon, src)
- if(robotic)
- new_bodypart.change_bodypart_status(BODYPART_ROBOTIC)
. = new_bodypart
-/mob/living/carbon/alien/humanoid/newBodyPart(zone, robotic, fixed_icon)
+/mob/living/carbon/alien/humanoid/newBodyPart(zone)
var/obj/item/bodypart/new_bodypart
switch(zone)
if(BODY_ZONE_L_ARM)
@@ -182,10 +153,8 @@
if(BODY_ZONE_CHEST)
new_bodypart = new /obj/item/bodypart/chest/alien()
if(new_bodypart)
- new_bodypart.update_limb(fixed_icon, src)
- if(robotic)
- new_bodypart.change_bodypart_status(BODYPART_ROBOTIC)
- . = new_bodypart
+ new_bodypart.update_limb(src)
+
/proc/skintone2hex(skin_tone)
@@ -217,39 +186,3 @@
. = "#fff4e6"
if("orange")
. = "#ffc905"
-
-/mob/living/carbon/proc/Digitigrade_Leg_Swap(swap_back)
- var/body_plan_changed = FALSE
- for(var/obj/item/bodypart/existing_bodypart as anything in bodyparts)
- var/obj/item/bodypart/new_bodypart
- if((!existing_bodypart.use_digitigrade && swap_back == FALSE) || (existing_bodypart.use_digitigrade && swap_back == TRUE))
- if(existing_bodypart.body_part == LEG_LEFT)
- if(swap_back == TRUE)
- new_bodypart = new /obj/item/bodypart/l_leg
- else
- new_bodypart = new /obj/item/bodypart/l_leg/digitigrade
- else if(existing_bodypart.body_part == LEG_RIGHT)
- if(swap_back == TRUE)
- new_bodypart = new /obj/item/bodypart/r_leg
- else
- new_bodypart = new /obj/item/bodypart/r_leg/digitigrade
- if(!new_bodypart)
- continue
- body_plan_changed = TRUE
- existing_bodypart.drop_limb(1)
- qdel(existing_bodypart)
- new_bodypart.attach_limb(src) //no sanity for if this fails here because we just dropped out a limb of the same zone, SHOULD be okay
- if(body_plan_changed && ishuman(src))
- var/mob/living/carbon/human/leg_owner = src
- if(leg_owner.w_uniform)
- var/obj/item/clothing/under/uniform = leg_owner.w_uniform
- if(uniform.mutantrace_variation)
- if(swap_back)
- uniform.adjusted = NORMAL_STYLE
- else
- uniform.adjusted = DIGITIGRADE_STYLE
- leg_owner.update_inv_w_uniform()
- /* SKYRAT EDIT REMOVAL - Digitigrade legs
- if(leg_owner.shoes && !(leg_owner.shoes.item_flags & IGNORE_DIGITIGRADE) && !swap_back)
- leg_owner.dropItemToGround(leg_owner.shoes)
- */ // SKYRAT EDIT END
diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm
index 9e4cce0fb67..ff8e49a103d 100644
--- a/code/modules/surgery/bodyparts/parts.dm
+++ b/code/modules/surgery/bodyparts/parts.dm
@@ -6,12 +6,16 @@
max_damage = 250 //SKYRAT EDIT CHANGE: max_damage = 200
body_zone = BODY_ZONE_CHEST
body_part = CHEST
+ is_dimorphic = TRUE
px_x = 0
px_y = 0
stam_damage_coeff = 1
max_stamina_damage = 162 // SKYRAT EDIT CHANGE: originally 120, update for stamina crit
grind_results = null
wound_resistance = 10
+ ///The bodytype required to attach to this chest
+ var/acceptable_bodytype = BODYTYPE_HUMANOID
+
var/obj/item/cavity_item
/obj/item/bodypart/chest/can_dismember(obj/item/item)
@@ -31,10 +35,14 @@
/obj/item/bodypart/chest/monkey
icon = 'icons/mob/animal_parts.dmi'
+ icon_static = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_chest"
+ limb_id = SPECIES_MONKEY
+ should_draw_greyscale = FALSE
animal_origin = MONKEY_BODYPART
- part_origin = MONKEY_BODY
wound_resistance = -10
+ bodytype = BODYTYPE_MONKEY | BODYTYPE_ORGANIC
+ acceptable_bodytype = BODYTYPE_MONKEY
/obj/item/bodypart/chest/alien
icon = 'icons/mob/animal_parts.dmi'
@@ -42,7 +50,6 @@
dismemberable = 0
max_damage = 500
animal_origin = ALIEN_BODYPART
- part_origin = ALIEN_BODY
/obj/item/bodypart/chest/larva
icon = 'icons/mob/animal_parts.dmi'
@@ -50,7 +57,6 @@
dismemberable = 0
max_damage = 50
animal_origin = LARVA_BODYPART
- part_origin = LARVA_BODY
/obj/item/bodypart/l_arm
name = "left arm"
@@ -135,9 +141,12 @@
/obj/item/bodypart/l_arm/monkey
icon = 'icons/mob/animal_parts.dmi'
+ icon_static = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_l_arm"
+ limb_id = SPECIES_MONKEY
+ should_draw_greyscale = FALSE
animal_origin = MONKEY_BODYPART
- part_origin = MONKEY_BODY
+ bodytype = BODYTYPE_MONKEY | BODYTYPE_ORGANIC
wound_resistance = -10
px_x = -5
px_y = -3
@@ -151,7 +160,6 @@
can_be_disabled = FALSE
max_damage = 100
animal_origin = ALIEN_BODYPART
- part_origin = ALIEN_BODY
/obj/item/bodypart/r_arm
name = "right arm"
@@ -234,9 +242,11 @@
/obj/item/bodypart/r_arm/monkey
icon = 'icons/mob/animal_parts.dmi'
+ icon_static = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_r_arm"
+ limb_id = SPECIES_MONKEY
+ bodytype = BODYTYPE_MONKEY | BODYTYPE_ORGANIC
animal_origin = MONKEY_BODYPART
- part_origin = MONKEY_BODY
wound_resistance = -10
px_x = 5
px_y = -3
@@ -250,7 +260,6 @@
can_be_disabled = FALSE
max_damage = 100
animal_origin = ALIEN_BODYPART
- part_origin = ALIEN_BODY
/obj/item/bodypart/l_leg
@@ -322,16 +331,14 @@
else if(!bodypart_disabled)
owner.set_usable_legs(owner.usable_legs + 1)
-
-/obj/item/bodypart/l_leg/digitigrade
- name = "left digitigrade leg"
- use_digitigrade = FULL_DIGITIGRADE
-
/obj/item/bodypart/l_leg/monkey
icon = 'icons/mob/animal_parts.dmi'
+ icon_static = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_l_leg"
+ limb_id = SPECIES_MONKEY
+ should_draw_greyscale = FALSE
animal_origin = MONKEY_BODYPART
- part_origin = MONKEY_BODY
+ bodytype = BODYTYPE_MONKEY | BODYTYPE_ORGANIC
wound_resistance = -10
px_y = 4
@@ -344,7 +351,6 @@
can_be_disabled = FALSE
max_damage = 100
animal_origin = ALIEN_BODYPART
- part_origin = ALIEN_BODY
/obj/item/bodypart/r_leg
name = "right leg"
@@ -417,16 +423,13 @@
else if(!bodypart_disabled)
owner.set_usable_legs(owner.usable_legs + 1)
-
-/obj/item/bodypart/r_leg/digitigrade
- name = "right digitigrade leg"
- use_digitigrade = FULL_DIGITIGRADE
-
/obj/item/bodypart/r_leg/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_r_leg"
+ limb_id = SPECIES_MONKEY
+ should_draw_greyscale = FALSE
animal_origin = MONKEY_BODYPART
- part_origin = MONKEY_BODY
+ bodytype = BODYTYPE_MONKEY | BODYTYPE_ORGANIC
wound_resistance = -10
px_y = 4
@@ -439,4 +442,3 @@
can_be_disabled = FALSE
max_damage = 100
animal_origin = ALIEN_BODYPART
- part_origin = ALIEN_BODY
diff --git a/code/modules/surgery/bodyparts/robot_bodyparts.dm b/code/modules/surgery/bodyparts/robot_bodyparts.dm
index 21384097bd0..d70d1cb1b93 100644
--- a/code/modules/surgery/bodyparts/robot_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/robot_bodyparts.dm
@@ -13,14 +13,17 @@
/obj/item/bodypart/l_arm/robot
name = "cyborg left arm"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
- attack_verb_continuous = list("slaps", "punches")
- attack_verb_simple = list("slap", "punch")
+ limb_id = "robotic"
+ attack_verb_simple = list("slapped", "punched")
inhand_icon_state = "buildpipe"
icon = 'icons/mob/augmentation/augments.dmi'
+ icon_static = 'icons/mob/augmentation/augments.dmi'
flags_1 = CONDUCT_1
icon_state = "borg_l_arm"
- status = BODYPART_ROBOTIC
- disable_threshold = 1
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC
+ change_exempt_flags = BP_BLOCK_CHANGE_SPECIES
brute_reduction = 5
burn_reduction = 4
@@ -36,14 +39,17 @@
/obj/item/bodypart/r_arm/robot
name = "cyborg right arm"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
- attack_verb_continuous = list("slaps", "punches")
- attack_verb_simple = list("slap", "punch")
+ attack_verb_simple = list("slapped", "punched")
inhand_icon_state = "buildpipe"
+ icon_static = 'icons/mob/augmentation/augments.dmi'
icon = 'icons/mob/augmentation/augments.dmi'
+ limb_id = "robotic"
flags_1 = CONDUCT_1
icon_state = "borg_r_arm"
- status = BODYPART_ROBOTIC
- disable_threshold = 1
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC
+ change_exempt_flags = BP_BLOCK_CHANGE_SPECIES
brute_reduction = 5
burn_reduction = 4
@@ -59,14 +65,17 @@
/obj/item/bodypart/l_leg/robot
name = "cyborg left leg"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
- attack_verb_continuous = list("kicks", "stomps")
- attack_verb_simple = list("kick", "stomp")
+ attack_verb_simple = list("kicked", "stomped")
inhand_icon_state = "buildpipe"
+ icon_static = 'icons/mob/augmentation/augments.dmi'
icon = 'icons/mob/augmentation/augments.dmi'
+ limb_id = "robotic"
flags_1 = CONDUCT_1
icon_state = "borg_l_leg"
- status = BODYPART_ROBOTIC
- disable_threshold = 1
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC
+ change_exempt_flags = BP_BLOCK_CHANGE_SPECIES
brute_reduction = 5
burn_reduction = 4
@@ -82,14 +91,17 @@
/obj/item/bodypart/r_leg/robot
name = "cyborg right leg"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
- attack_verb_continuous = list("kicks", "stomps")
- attack_verb_simple = list("kick", "stomp")
+ attack_verb_simple = list("kicked", "stomped")
inhand_icon_state = "buildpipe"
+ icon_static = 'icons/mob/augmentation/augments.dmi'
icon = 'icons/mob/augmentation/augments.dmi'
+ limb_id = "robotic"
flags_1 = CONDUCT_1
icon_state = "borg_r_leg"
- status = BODYPART_ROBOTIC
- disable_threshold = 1
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC
+ change_exempt_flags = BP_BLOCK_CHANGE_SPECIES
brute_reduction = 5
burn_reduction = 4
@@ -106,10 +118,15 @@
name = "cyborg torso"
desc = "A heavily reinforced case containing cyborg logic boards, with space for a standard power cell."
inhand_icon_state = "buildpipe"
+ icon_static = 'icons/mob/augmentation/augments.dmi'
icon = 'icons/mob/augmentation/augments.dmi'
+ limb_id = "robotic"
flags_1 = CONDUCT_1
icon_state = "borg_chest"
- status = BODYPART_ROBOTIC
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC
+ change_exempt_flags = BP_BLOCK_CHANGE_SPECIES
brute_reduction = 5
burn_reduction = 4
@@ -209,10 +226,15 @@
name = "cyborg head"
desc = "A standard reinforced braincase, with spine-plugged neural socket and sensor gimbals."
inhand_icon_state = "buildpipe"
+ icon_static = 'icons/mob/augmentation/augments.dmi'
icon = 'icons/mob/augmentation/augments.dmi'
+ limb_id = "robotic"
flags_1 = CONDUCT_1
icon_state = "borg_head"
- status = BODYPART_ROBOTIC
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC
+ change_exempt_flags = BP_BLOCK_CHANGE_SPECIES
brute_reduction = 5
burn_reduction = 4
diff --git a/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm
new file mode 100644
index 00000000000..a581790b31f
--- /dev/null
+++ b/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm
@@ -0,0 +1,31 @@
+/obj/item/bodypart/head/ethereal
+ icon_greyscale = 'icons/mob/species/ethereal/bodyparts.dmi'
+ limb_id = SPECIES_ETHEREAL
+ is_dimorphic = FALSE
+ uses_mutcolor = TRUE
+
+/obj/item/bodypart/chest/ethereal
+ icon_greyscale = 'icons/mob/species/ethereal/bodyparts.dmi'
+ limb_id = SPECIES_ETHEREAL
+ is_dimorphic = FALSE
+ uses_mutcolor = TRUE
+
+/obj/item/bodypart/l_arm/ethereal
+ icon_greyscale = 'icons/mob/species/ethereal/bodyparts.dmi'
+ limb_id = SPECIES_ETHEREAL
+ uses_mutcolor = TRUE
+
+/obj/item/bodypart/r_arm/ethereal
+ icon_greyscale = 'icons/mob/species/ethereal/bodyparts.dmi'
+ limb_id = SPECIES_ETHEREAL
+ uses_mutcolor = TRUE
+
+/obj/item/bodypart/l_leg/ethereal
+ icon_greyscale = 'icons/mob/species/ethereal/bodyparts.dmi'
+ limb_id = SPECIES_ETHEREAL
+ uses_mutcolor = TRUE
+
+/obj/item/bodypart/r_leg/ethereal
+ icon_greyscale = 'icons/mob/species/ethereal/bodyparts.dmi'
+ limb_id = SPECIES_ETHEREAL
+ uses_mutcolor = TRUE
diff --git a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm
new file mode 100644
index 00000000000..01ac9e3bb61
--- /dev/null
+++ b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm
@@ -0,0 +1,80 @@
+/obj/item/bodypart/head/lizard
+ icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi'
+ limb_id = SPECIES_LIZARD
+ uses_mutcolor = TRUE
+ is_dimorphic = FALSE
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_SNOUTED //This is temporary. Ideally the "snout" external organ adds to this.
+
+/obj/item/bodypart/chest/lizard
+ icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi'
+ uses_mutcolor = TRUE
+ limb_id = SPECIES_LIZARD
+ is_dimorphic = TRUE
+
+/obj/item/bodypart/l_arm/lizard
+ icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi'
+ uses_mutcolor = TRUE
+ limb_id = SPECIES_LIZARD
+
+/obj/item/bodypart/r_arm/lizard
+ icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi'
+ uses_mutcolor = TRUE
+ limb_id = SPECIES_LIZARD
+
+/obj/item/bodypart/l_leg/lizard
+ icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi'
+ uses_mutcolor = TRUE
+ limb_id = SPECIES_LIZARD
+
+/obj/item/bodypart/r_leg/lizard
+ icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi'
+ uses_mutcolor = TRUE
+ limb_id = SPECIES_LIZARD
+
+/* SKYRAT EDIT REMOVAL - MOVED TO MODULAR MUTANT_BODYPARTS.DM
+/obj/item/bodypart/l_leg/digitigrade
+ icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi'
+ uses_mutcolor = TRUE
+ limb_id = "digitigrade"
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE
+
+/obj/item/bodypart/l_leg/digitigrade/update_limb(dropping_limb = FALSE, is_creating = FALSE)
+ . = ..()
+ if(ishuman(owner))
+ var/mob/living/carbon/human/human_owner = owner
+ var/uniform_compatible = FALSE
+ var/suit_compatible = FALSE
+ if(!(human_owner.w_uniform) || (human_owner.w_uniform.supports_variations_flags & (CLOTHING_DIGITIGRADE_VARIATION|CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON))) //Checks uniform compatibility
+ uniform_compatible = TRUE
+ if((!human_owner.wear_suit) || (human_owner.wear_suit.supports_variations_flags & (CLOTHING_DIGITIGRADE_VARIATION|CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON)) || !(human_owner.wear_suit.body_parts_covered & LEGS)) //Checks suit compatability
+ suit_compatible = TRUE
+
+ if((uniform_compatible && suit_compatible) || (suit_compatible && human_owner.wear_suit?.flags_inv & HIDEJUMPSUIT)) //If the uniform is hidden, it doesnt matter if its compatible
+ limb_id = "digitigrade"
+
+ else
+ limb_id = "lizard"
+
+/obj/item/bodypart/r_leg/digitigrade
+ icon_greyscale = 'icons/mob/species/lizard/bodyparts.dmi'
+ uses_mutcolor = TRUE
+ limb_id = "digitigrade"
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE
+
+/obj/item/bodypart/r_leg/digitigrade/update_limb(dropping_limb = FALSE, is_creating = FALSE)
+ . = ..()
+ if(ishuman(owner))
+ var/mob/living/carbon/human/human_owner = owner
+ var/uniform_compatible = FALSE
+ var/suit_compatible = FALSE
+ if(!(human_owner.w_uniform) || (human_owner.w_uniform.supports_variations_flags & (CLOTHING_DIGITIGRADE_VARIATION|CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON))) //Checks uniform compatibility
+ uniform_compatible = TRUE
+ if((!human_owner.wear_suit) || (human_owner.wear_suit.supports_variations_flags & (CLOTHING_DIGITIGRADE_VARIATION|CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON)) || !(human_owner.wear_suit.body_parts_covered & LEGS)) //Checks suit compatability
+ suit_compatible = TRUE
+
+ if((uniform_compatible && suit_compatible) || (suit_compatible && human_owner.wear_suit?.flags_inv & HIDEJUMPSUIT)) //If the uniform is hidden, it doesnt matter if its compatible
+ limb_id = "digitigrade"
+
+ else
+ limb_id = "lizard"
+*/
diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm
new file mode 100644
index 00000000000..247706becd1
--- /dev/null
+++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm
@@ -0,0 +1,422 @@
+///SNAIL
+/obj/item/bodypart/head/snail
+ limb_id = SPECIES_SNAIL
+ is_dimorphic = FALSE
+
+/obj/item/bodypart/chest/snail
+ limb_id = SPECIES_SNAIL
+ is_dimorphic = FALSE
+
+/obj/item/bodypart/l_arm/snail
+ limb_id = SPECIES_SNAIL
+
+/obj/item/bodypart/r_arm/snail
+ limb_id = SPECIES_SNAIL
+
+/obj/item/bodypart/l_leg/snail
+ limb_id = SPECIES_SNAIL
+
+/obj/item/bodypart/r_leg/snail
+ limb_id = SPECIES_SNAIL
+
+///ABDUCTOR
+/obj/item/bodypart/head/abductor
+ limb_id = SPECIES_ABDUCTOR
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/chest/abductor
+ limb_id = SPECIES_ABDUCTOR
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_arm/abductor
+ limb_id = SPECIES_ABDUCTOR
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/abductor
+ limb_id = SPECIES_ABDUCTOR
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/abductor
+ limb_id = SPECIES_ABDUCTOR
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/abductor
+ limb_id = SPECIES_ABDUCTOR
+ should_draw_greyscale = FALSE
+
+///JELLY
+/obj/item/bodypart/head/jelly
+ limb_id = SPECIES_JELLYPERSON
+ is_dimorphic = TRUE
+
+/obj/item/bodypart/chest/jelly
+ limb_id = SPECIES_JELLYPERSON
+ is_dimorphic = TRUE
+
+/obj/item/bodypart/l_arm/jelly
+ limb_id = SPECIES_JELLYPERSON
+
+/obj/item/bodypart/r_arm/jelly
+ limb_id = SPECIES_JELLYPERSON
+
+/obj/item/bodypart/l_leg/jelly
+ limb_id = SPECIES_JELLYPERSON
+
+/obj/item/bodypart/r_leg/jelly
+ limb_id = SPECIES_JELLYPERSON
+
+///SLIME
+/obj/item/bodypart/head/slime
+ limb_id = SPECIES_SLIMEPERSON
+ is_dimorphic = FALSE
+
+/obj/item/bodypart/chest/slime
+ limb_id = SPECIES_SLIMEPERSON
+ is_dimorphic = TRUE
+
+/obj/item/bodypart/l_arm/slime
+ limb_id = SPECIES_SLIMEPERSON
+
+/obj/item/bodypart/r_arm/slime
+ limb_id = SPECIES_SLIMEPERSON
+
+/obj/item/bodypart/l_leg/slime
+ limb_id = SPECIES_SLIMEPERSON
+
+/obj/item/bodypart/r_leg/slime
+ limb_id = SPECIES_SLIMEPERSON
+
+///ZOMBIE
+/obj/item/bodypart/head/zombie
+ limb_id = SPECIES_ZOMBIE
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/chest/zombie
+ limb_id = SPECIES_ZOMBIE
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_arm/zombie
+ limb_id = SPECIES_ZOMBIE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/zombie
+ limb_id = SPECIES_ZOMBIE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/zombie
+ limb_id = SPECIES_ZOMBIE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/zombie
+ limb_id = SPECIES_ZOMBIE
+ should_draw_greyscale = FALSE
+
+///PODPEOPLE
+/obj/item/bodypart/head/pod
+ limb_id = SPECIES_PODPERSON
+ is_dimorphic = TRUE
+
+/obj/item/bodypart/chest/pod
+ limb_id = SPECIES_PODPERSON
+ is_dimorphic = TRUE
+
+/obj/item/bodypart/l_arm/pod
+ limb_id = SPECIES_PODPERSON
+
+/obj/item/bodypart/r_arm/pod
+ limb_id = SPECIES_PODPERSON
+
+/obj/item/bodypart/l_leg/pod
+ limb_id = SPECIES_PODPERSON
+
+/obj/item/bodypart/r_leg/pod
+ limb_id = SPECIES_PODPERSON
+
+///FLY
+/obj/item/bodypart/head/fly
+ limb_id = SPECIES_FLYPERSON
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/chest/fly
+ limb_id = SPECIES_FLYPERSON
+ is_dimorphic = TRUE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_arm/fly
+ limb_id = SPECIES_FLYPERSON
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/fly
+ limb_id = SPECIES_FLYPERSON
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/fly
+ limb_id = SPECIES_FLYPERSON
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/fly
+ limb_id = SPECIES_FLYPERSON
+ should_draw_greyscale = FALSE
+
+///SHADOW
+/obj/item/bodypart/head/shadow
+ limb_id = SPECIES_SHADOW
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/chest/shadow
+ limb_id = SPECIES_SHADOW
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_arm/shadow
+ limb_id = SPECIES_SHADOW
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/shadow
+ limb_id = SPECIES_SHADOW
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/shadow
+ limb_id = SPECIES_SHADOW
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/shadow
+ limb_id = SPECIES_SHADOW
+ should_draw_greyscale = FALSE
+
+///SKELETON
+/obj/item/bodypart/head/skeleton
+ limb_id = SPECIES_SKELETON
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/chest/skeleton
+ limb_id = SPECIES_SKELETON
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_arm/skeleton
+ limb_id = SPECIES_SKELETON
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/skeleton
+ limb_id = SPECIES_SKELETON
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/skeleton
+ limb_id = SPECIES_SKELETON
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/skeleton
+ limb_id = SPECIES_SKELETON
+ should_draw_greyscale = FALSE
+
+///MUSHROOM
+/obj/item/bodypart/head/mushroom
+ limb_id = SPECIES_MUSHROOM
+ is_dimorphic = TRUE
+
+/obj/item/bodypart/chest/mushroom
+ limb_id = SPECIES_MUSHROOM
+ is_dimorphic = TRUE
+
+/obj/item/bodypart/l_arm/mushroom
+ limb_id = SPECIES_MUSHROOM
+
+/obj/item/bodypart/r_arm/mushroom
+ limb_id = SPECIES_MUSHROOM
+
+/obj/item/bodypart/l_leg/mushroom
+ limb_id = SPECIES_MUSHROOM
+
+/obj/item/bodypart/r_leg/mushroom
+ limb_id = SPECIES_MUSHROOM
+
+///GOLEMS (i hate xenobio SO FUCKING MUCH)
+/obj/item/bodypart/head/golem
+ limb_id = SPECIES_GOLEM
+ is_dimorphic = FALSE
+
+/obj/item/bodypart/chest/golem
+ limb_id = SPECIES_GOLEM
+ is_dimorphic = TRUE
+
+/obj/item/bodypart/l_arm/golem
+ limb_id = SPECIES_GOLEM
+
+/obj/item/bodypart/r_arm/golem
+ limb_id = SPECIES_GOLEM
+
+/obj/item/bodypart/l_leg/golem
+ limb_id = SPECIES_GOLEM
+
+/obj/item/bodypart/r_leg/golem
+ limb_id = SPECIES_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/l_arm/golem/cult
+ limb_id = SPECIES_GOLEM_CULT
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/golem/cult
+ limb_id = SPECIES_GOLEM_CULT
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/golem/cult
+ limb_id = SPECIES_GOLEM_CULT
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/golem/cult
+ limb_id = SPECIES_GOLEM_CULT
+ should_draw_greyscale = FALSE
+
+///
+/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/l_arm/golem/cloth
+ limb_id = SPECIES_GOLEM_CLOTH
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/golem/cloth
+ limb_id = SPECIES_GOLEM_CLOTH
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/golem/cloth
+ limb_id = SPECIES_GOLEM_CLOTH
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/golem/cloth
+ limb_id = SPECIES_GOLEM_CLOTH
+ should_draw_greyscale = FALSE
+
+///
+/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/l_arm/golem/cardboard
+ limb_id = SPECIES_GOLEM_CARDBOARD
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/golem/cardboard
+ limb_id = SPECIES_GOLEM_CARDBOARD
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/golem/cardboard
+ limb_id = SPECIES_GOLEM_CARDBOARD
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/golem/cardboard
+ limb_id = SPECIES_GOLEM_CARDBOARD
+ should_draw_greyscale = FALSE
+
+///
+/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/l_arm/golem/durathread
+ limb_id = SPECIES_GOLEM_DURATHREAD
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/golem/durathread
+ limb_id = SPECIES_GOLEM_DURATHREAD
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/golem/durathread
+ limb_id = SPECIES_GOLEM_DURATHREAD
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/golem/durathread
+ limb_id = SPECIES_GOLEM_DURATHREAD
+ should_draw_greyscale = FALSE
+
+///
+/obj/item/bodypart/head/golem/bone
+ limb_id = SPECIES_GOLEM_BONE
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/chest/golem/bone
+ limb_id = SPECIES_GOLEM_BONE
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_arm/golem/bone
+ limb_id = SPECIES_GOLEM_BONE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/golem/bone
+ limb_id = SPECIES_GOLEM_BONE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/golem/bone
+ limb_id = SPECIES_GOLEM_BONE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/golem/bone
+ limb_id = SPECIES_GOLEM_BONE
+ should_draw_greyscale = FALSE
+
+///
+/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/l_arm/golem/snow
+ limb_id = SPECIES_GOLEM_SNOW
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/golem/snow
+ limb_id = SPECIES_GOLEM_SNOW
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/golem/snow
+ limb_id = SPECIES_GOLEM_SNOW
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/golem/snow
+ limb_id = SPECIES_GOLEM_SNOW
+ should_draw_greyscale = FALSE
diff --git a/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm
new file mode 100644
index 00000000000..6093405da1b
--- /dev/null
+++ b/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm
@@ -0,0 +1,45 @@
+/obj/item/bodypart/head/moth
+ icon = 'icons/mob/species/moth/bodyparts.dmi'
+ icon_state = "moth_head"
+ icon_static = 'icons/mob/species/moth/bodyparts.dmi'
+ limb_id = SPECIES_MOTH
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/chest/moth
+ icon = 'icons/mob/species/moth/bodyparts.dmi'
+ icon_state = "moth_chest_m"
+ icon_static = 'icons/mob/species/moth/bodyparts.dmi'
+ limb_id = SPECIES_MOTH
+ is_dimorphic = TRUE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_arm/moth
+ icon = 'icons/mob/species/moth/bodyparts.dmi'
+ icon_state = "moth_l_arm"
+ icon_static = 'icons/mob/species/moth/bodyparts.dmi'
+ limb_id = SPECIES_MOTH
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/moth
+ icon = 'icons/mob/species/moth/bodyparts.dmi'
+ icon_state = "moth_l_leg"
+ icon = 'icons/mob/species/moth/bodyparts.dmi'
+ icon_state = "moth_r_arm"
+ icon_static = 'icons/mob/species/moth/bodyparts.dmi'
+ limb_id = SPECIES_MOTH
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/moth
+ icon = 'icons/mob/species/moth/bodyparts.dmi'
+ icon_state = "moth_l_leg"
+ icon_static = 'icons/mob/species/moth/bodyparts.dmi'
+ limb_id = SPECIES_MOTH
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/moth
+ icon = 'icons/mob/species/moth/bodyparts.dmi'
+ icon_state = "moth_r_leg"
+ icon_static = 'icons/mob/species/moth/bodyparts.dmi'
+ limb_id = SPECIES_MOTH
+ should_draw_greyscale = FALSE
diff --git a/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm
new file mode 100644
index 00000000000..1b7179b6c0a
--- /dev/null
+++ b/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm
@@ -0,0 +1,43 @@
+/obj/item/bodypart/head/plasmaman
+ icon = 'icons/mob/species/plasmaman/bodyparts.dmi'
+ icon_state = "plasmaman_head"
+ icon_static = 'icons/mob/species/plasmaman/bodyparts.dmi'
+ limb_id = SPECIES_PLASMAMAN
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/chest/plasmaman
+ icon = 'icons/mob/species/plasmaman/bodyparts.dmi'
+ icon_state = "plasmaman_chest"
+ icon_static = 'icons/mob/species/plasmaman/bodyparts.dmi'
+ limb_id = SPECIES_PLASMAMAN
+ is_dimorphic = FALSE
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_arm/plasmaman
+ icon = 'icons/mob/species/plasmaman/bodyparts.dmi'
+ icon_state = "plasmaman_l_arm"
+ icon_static = 'icons/mob/species/plasmaman/bodyparts.dmi'
+ limb_id = SPECIES_PLASMAMAN
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_arm/plasmaman
+ icon = 'icons/mob/species/plasmaman/bodyparts.dmi'
+ icon_state = "plasmaman_r_arm"
+ icon_static = 'icons/mob/species/plasmaman/bodyparts.dmi'
+ limb_id = SPECIES_PLASMAMAN
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/l_leg/plasmaman
+ icon = 'icons/mob/species/plasmaman/bodyparts.dmi'
+ icon_state = "plasmaman_l_leg"
+ icon_static = 'icons/mob/species/plasmaman/bodyparts.dmi'
+ limb_id = SPECIES_PLASMAMAN
+ should_draw_greyscale = FALSE
+
+/obj/item/bodypart/r_leg/plasmaman
+ icon = 'icons/mob/species/plasmaman/bodyparts.dmi'
+ icon_state = "plasmaman_r_leg"
+ icon_static = 'icons/mob/species/plasmaman/bodyparts.dmi'
+ limb_id = SPECIES_PLASMAMAN
+ should_draw_greyscale = FALSE
diff --git a/code/modules/surgery/bodyparts/wounds.dm b/code/modules/surgery/bodyparts/wounds.dm
new file mode 100644
index 00000000000..be4d5072316
--- /dev/null
+++ b/code/modules/surgery/bodyparts/wounds.dm
@@ -0,0 +1,209 @@
+/// Allows us to roll for and apply a wound without actually dealing damage. Used for aggregate wounding power with pellet clouds
+/obj/item/bodypart/proc/painless_wound_roll(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus, sharpness=NONE)
+ SHOULD_CALL_PARENT(TRUE)
+
+ if(!owner || phantom_wounding_dmg <= WOUND_MINIMUM_DAMAGE || wound_bonus == CANT_WOUND)
+ return
+
+ var/mangled_state = get_mangled_state()
+ var/bio_state = owner.get_biological_state()
+ var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
+
+ if(wounding_type == WOUND_BLUNT && sharpness)
+ if(sharpness & SHARP_EDGED)
+ wounding_type = WOUND_SLASH
+ else if (sharpness & SHARP_POINTY)
+ wounding_type = WOUND_PIERCE
+
+ //Handling for bone only/flesh only(none right now)/flesh and bone targets
+ switch(bio_state)
+ // if we're bone only, all cutting attacks go straight to the bone
+ if(BIO_JUST_BONE)
+ if(wounding_type == WOUND_SLASH)
+ wounding_type = WOUND_BLUNT
+ phantom_wounding_dmg *= (easy_dismember ? 1 : 0.6)
+ else if(wounding_type == WOUND_PIERCE)
+ wounding_type = WOUND_BLUNT
+ phantom_wounding_dmg *= (easy_dismember ? 1 : 0.75)
+ if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
+ return
+ // note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday)
+ // standard humanoids
+ if(BIO_FLESH_BONE)
+ // if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
+ // So a big sharp weapon is still all you need to destroy a limb
+ if(mangled_state == BODYPART_MANGLED_FLESH && sharpness)
+ playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
+ if(wounding_type == WOUND_SLASH && !easy_dismember)
+ phantom_wounding_dmg *= 0.6 // edged weapons pass along 60% of their wounding damage to the bone since the power is spread out over a larger area
+ if(wounding_type == WOUND_PIERCE && !easy_dismember)
+ phantom_wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
+ wounding_type = WOUND_BLUNT
+ else if(mangled_state == BODYPART_MANGLED_BOTH && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
+ return
+
+ check_wounding(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)
+
+/**
+ * check_wounding() is where we handle rolling for, selecting, and applying a wound if we meet the criteria
+ *
+ * We generate a "score" for how woundable the attack was based on the damage and other factors discussed in [/obj/item/bodypart/proc/check_woundings_mods], then go down the list from most severe to least severe wounds in that category.
+ * We can promote a wound from a lesser to a higher severity this way, but we give up if we have a wound of the given type and fail to roll a higher severity, so no sidegrades/downgrades
+ *
+ * Arguments:
+ * * woundtype- Either WOUND_BLUNT, WOUND_SLASH, WOUND_PIERCE, or WOUND_BURN based on the attack type.
+ * * damage- How much damage is tied to this attack, since wounding potential scales with damage in an attack (see: WOUND_DAMAGE_EXPONENT)
+ * * wound_bonus- The wound_bonus of an attack
+ * * bare_wound_bonus- The bare_wound_bonus of an attack
+ */
+/obj/item/bodypart/proc/check_wounding(woundtype, damage, wound_bonus, bare_wound_bonus, attack_direction)
+ SHOULD_CALL_PARENT(TRUE)
+ RETURN_TYPE(/datum/wound)
+
+ if(HAS_TRAIT(owner, TRAIT_NEVER_WOUNDED))
+ return
+
+ // note that these are fed into an exponent, so these are magnified
+ if(HAS_TRAIT(owner, TRAIT_EASILY_WOUNDED))
+ damage *= 1.5
+ else
+ damage = min(damage, WOUND_MAX_CONSIDERED_DAMAGE)
+
+ if(HAS_TRAIT(owner,TRAIT_HARDLY_WOUNDED))
+ damage *= 0.85
+
+ if(HAS_TRAIT(owner, TRAIT_EASYDISMEMBER))
+ damage *= 1.1
+
+ var/base_roll = rand(1, round(damage ** WOUND_DAMAGE_EXPONENT))
+ var/injury_roll = base_roll
+ injury_roll += check_woundings_mods(woundtype, damage, wound_bonus, bare_wound_bonus)
+ var/list/wounds_checking = GLOB.global_wound_types[woundtype]
+
+ if(injury_roll > WOUND_DISMEMBER_OUTRIGHT_THRESH && prob(get_damage() / max_damage * 100))
+ var/datum/wound/loss/dismembering = new
+ dismembering.apply_dismember(src, woundtype, outright = TRUE, attack_direction = attack_direction)
+ return
+
+ // quick re-check to see if bare_wound_bonus applies, for the benefit of log_wound(), see about getting the check from check_woundings_mods() somehow
+ if(ishuman(owner))
+ var/mob/living/carbon/human/human_wearer = owner
+ var/list/clothing = human_wearer.clothingonpart(src)
+ for(var/obj/item/clothing/clothes_check as anything in clothing)
+ // unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary
+ if(clothes_check.armor.getRating(WOUND))
+ bare_wound_bonus = 0
+ break
+
+ //cycle through the wounds of the relevant category from the most severe down
+ for(var/datum/wound/possible_wound as anything in wounds_checking)
+ var/datum/wound/replaced_wound
+ for(var/datum/wound/existing_wound as anything in wounds)
+ if(existing_wound.type in wounds_checking)
+ if(existing_wound.severity >= initial(possible_wound.severity))
+ return
+ else
+ replaced_wound = existing_wound
+
+ if(initial(possible_wound.threshold_minimum) < injury_roll)
+ var/datum/wound/new_wound
+ if(replaced_wound)
+ new_wound = replaced_wound.replace_wound(possible_wound, attack_direction = attack_direction)
+ else
+ new_wound = new possible_wound
+ new_wound.apply_wound(src, attack_direction = attack_direction)
+ log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll) // dismembering wounds are logged in the apply_wound() for loss wounds since they delete themselves immediately, these will be immediately returned
+ return new_wound
+
+// try forcing a specific wound, but only if there isn't already a wound of that severity or greater for that type on this bodypart
+/obj/item/bodypart/proc/force_wound_upwards(specific_woundtype, smited = FALSE)
+ SHOULD_NOT_OVERRIDE(TRUE)
+
+ var/datum/wound/potential_wound = specific_woundtype
+ for(var/datum/wound/existing_wound as anything in wounds)
+ if(existing_wound.wound_type == initial(potential_wound.wound_type))
+ if(existing_wound.severity < initial(potential_wound.severity)) // we only try if the existing one is inferior to the one we're trying to force
+ existing_wound.replace_wound(potential_wound, smited)
+ return
+
+ var/datum/wound/new_wound = new potential_wound
+ new_wound.apply_wound(src, smited = smited)
+
+/**
+ * check_wounding_mods() is where we handle the various modifiers of a wound roll
+ *
+ * A short list of things we consider: any armor a human target may be wearing, and if they have no wound armor on the limb, if we have a bare_wound_bonus to apply, plus the plain wound_bonus
+ * We also flick through all of the wounds we currently have on this limb and add their threshold penalties, so that having lots of bad wounds makes you more liable to get hurt worse
+ * Lastly, we add the inherent wound_resistance variable the bodypart has (heads and chests are slightly harder to wound), and a small bonus if the limb is already disabled
+ *
+ * Arguments:
+ * * It's the same ones on [/obj/item/bodypart/proc/receive_damage]
+ */
+/obj/item/bodypart/proc/check_woundings_mods(wounding_type, damage, wound_bonus, bare_wound_bonus)
+ SHOULD_CALL_PARENT(TRUE)
+
+ var/armor_ablation = 0
+ var/injury_mod = 0
+
+ if(owner && ishuman(owner))
+ var/mob/living/carbon/human/human_owner = owner
+ var/list/clothing = human_owner.clothingonpart(src)
+ for(var/obj/item/clothing/clothes as anything in clothing)
+ // unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary
+ armor_ablation += clothes.armor.getRating(WOUND)
+ if(wounding_type == WOUND_SLASH)
+ clothes.take_damage_zone(body_zone, damage, BRUTE)
+ else if(wounding_type == WOUND_BURN && damage >= 10) // lazy way to block freezing from shredding clothes without adding another var onto apply_damage()
+ clothes.take_damage_zone(body_zone, damage, BURN)
+
+ if(!armor_ablation)
+ injury_mod += bare_wound_bonus
+
+ injury_mod -= armor_ablation
+ injury_mod += wound_bonus
+
+ for(var/datum/wound/wound as anything in wounds)
+ injury_mod += wound.threshold_penalty
+
+ var/part_mod = -wound_resistance
+ if(get_damage(TRUE) >= max_damage)
+ part_mod += disabled_wound_penalty
+
+ injury_mod += part_mod
+
+ return injury_mod
+
+ /// Get whatever wound of the given type is currently attached to this limb, if any
+/obj/item/bodypart/proc/get_wound_type(checking_type)
+ RETURN_TYPE(checking_type)
+ SHOULD_NOT_OVERRIDE(TRUE)
+
+ if(isnull(wounds))
+ return
+
+ for(var/wound in wounds)
+ if(istype(wound, checking_type))
+ return wound
+
+/**
+ * update_wounds() is called whenever a wound is gained or lost on this bodypart, as well as if there's a change of some kind on a bone wound possibly changing disabled status
+ *
+ * Covers tabulating the damage multipliers we have from wounds (burn specifically), as well as deleting our gauze wrapping if we don't have any wounds that can use bandaging
+ *
+ * Arguments:
+ * * replaced- If true, this is being called from the remove_wound() of a wound that's being replaced, so the bandage that already existed is still relevant, but the new wound hasn't been added yet
+ */
+/obj/item/bodypart/proc/update_wounds(replaced = FALSE)
+ SHOULD_CALL_PARENT(TRUE)
+
+ var/dam_mul = 1 //initial(wound_damage_multiplier)
+
+ // we can (normally) only have one wound per type, but remember there's multiple types (smites like :B:loodless can generate multiple cuts on a limb)
+ for(var/datum/wound/iter_wound as anything in wounds)
+ dam_mul *= iter_wound.damage_mulitplier_penalty
+
+ if(!LAZYLEN(wounds) && current_gauze && !replaced) // no more wounds = no need for the gauze anymore
+ owner.visible_message(span_notice("\The [current_gauze.name] on [owner]'s [name] falls away."), span_notice("The [current_gauze.name] on your [parse_zone(body_zone)] falls away."))
+ QDEL_NULL(current_gauze)
+
+ wound_damage_multiplier = dam_mul
diff --git a/code/modules/surgery/healing.dm b/code/modules/surgery/healing.dm
index 48c1d8e7f1c..8877b186e34 100644
--- a/code/modules/surgery/healing.dm
+++ b/code/modules/surgery/healing.dm
@@ -9,7 +9,6 @@
target_mobtypes = list(/mob/living)
possible_locs = list(BODY_ZONE_CHEST)
- requires_bodypart_type = BODYPART_ORGANIC //SKYRAT EDIT CHANGE - ORIGINAL VALUE: requires_bodypart_type = FALSE
replaced_by = /datum/surgery
ignore_clothes = TRUE
var/healing_step_type
diff --git a/code/modules/surgery/implant_removal.dm b/code/modules/surgery/implant_removal.dm
index e202820df2e..f0860fac8f6 100644
--- a/code/modules/surgery/implant_removal.dm
+++ b/code/modules/surgery/implant_removal.dm
@@ -65,7 +65,7 @@
/datum/surgery/implant_removal/mechanic
name = "implant removal"
- requires_bodypart_type = BODYPART_ROBOTIC
+ requires_bodypart_type = BODYTYPE_ROBOTIC
steps = list(
/datum/surgery_step/mechanic_open,
/datum/surgery_step/open_hatch,
diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm
index 2348e8f920d..cfd3e471c47 100644
--- a/code/modules/surgery/limb_augmentation.dm
+++ b/code/modules/surgery/limb_augmentation.dm
@@ -20,7 +20,7 @@
if(istype(tool, /obj/item/borg/apparatus/organ_storage) && istype(tool.contents[1], /obj/item/bodypart))
tool = tool.contents[1]
var/obj/item/bodypart/aug = tool
- if(aug.status != BODYPART_ROBOTIC)
+ if(IS_ORGANIC_LIMB(aug))
to_chat(user, span_warning("That's not an augment, silly!"))
return -1
if(aug.body_zone != target_zone)
@@ -59,7 +59,12 @@
tool.cut_overlays()
tool = tool.contents[1]
if(istype(tool) && user.temporarilyRemoveItemFromInventory(tool))
- tool.replace_limb(target, TRUE)
+ if(!tool.replace_limb(target))
+ display_results(user, target, span_warning("You fail in replacing [target]'s [parse_zone(target_zone)]! Their body has rejected [tool]!"),
+ span_warning("[user] fails to replace [target]'s [parse_zone(target_zone)]!"),
+ span_warning("[user] fails to replaces [target]'s [parse_zone(target_zone)]!"))
+ tool.forceMove(target.loc)
+ return
display_results(user, target, span_notice("You successfully augment [target]'s [parse_zone(target_zone)]."),
span_notice("[user] successfully augments [target]'s [parse_zone(target_zone)] with [tool]!"),
span_notice("[user] successfully augments [target]'s [parse_zone(target_zone)]!"))
diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm
index 1921bf6dff3..676c8c74012 100644
--- a/code/modules/surgery/organ_manipulation.dm
+++ b/code/modules/surgery/organ_manipulation.dm
@@ -37,7 +37,7 @@
/datum/surgery/organ_manipulation/mechanic
name = "Prosthesis organ manipulation"
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD)
- requires_bodypart_type = BODYPART_ROBOTIC
+ requires_bodypart_type = BODYTYPE_ROBOTIC
lying_required = FALSE
self_operable = TRUE
steps = list(
diff --git a/code/modules/surgery/organs/external/_external_organs.dm b/code/modules/surgery/organs/external/_external_organs.dm
index d285157d2ee..b3306a4aa8f 100644
--- a/code/modules/surgery/organs/external/_external_organs.dm
+++ b/code/modules/surgery/organs/external/_external_organs.dm
@@ -33,6 +33,9 @@
///Reference to the limb we're inside of
var/obj/item/bodypart/ownerlimb
+ ///Does this organ use it's own color instead of bodypart/var/draw_color?
+ var/overrides_color = FALSE
+
/**mob_sprite is optional if you havent set sprite_datums for the object, and is used mostly to generate sprite_datums from a persons DNA
* For _mob_sprite we make a distinction between "Round Snout" and "round". Round Snout is the name of the sprite datum, while "round" would be part of the sprite
* I'm sorry
@@ -80,11 +83,11 @@
bodypart.contents.Add(src)
///Add the overlays we need to draw on a person. Called from _bodyparts.dm
-/obj/item/organ/external/proc/get_overlays(list/overlay_list, image_dir, image_layer, body_type, image_color)
+/obj/item/organ/external/proc/get_overlays(list/overlay_list, image_dir, image_layer, physique, image_color)
if(!sprite_datum)
return
- var/gender = (body_type == FEMALE) ? "f" : "m"
+ var/gender = (physique == FEMALE) ? "f" : "m"
var/finished_icon_state = (sprite_datum.gender_specific ? gender : "m") + "_" + feature_key + "_" + sprite_datum.icon_state + mutant_bodyparts_layertext(image_layer)
var/mutable_appearance/appearance = mutable_appearance(sprite_datum.icon, finished_icon_state, layer = -image_layer)
appearance.dir = image_dir
@@ -157,6 +160,10 @@
set_sprite(feature_list[deconstruct_block(get_uni_feature_block(features, dna_block), feature_list.len)])
+///Colorizes the limb it's inserted to, if required.
+/obj/item/organ/external/proc/override_color(rgb_value)
+ return
+
///The horns of a lizard!
/obj/item/organ/external/horns
name = "horns"
@@ -278,6 +285,8 @@
dna_block = DNA_POD_HAIR_BLOCK
+ overrides_color = TRUE
+
/obj/item/organ/external/pod_hair/can_draw_on_bodypart(mob/living/carbon/human/human)
if(!(human.head?.flags_inv & HIDEHAIR) || (human.wear_mask?.flags_inv & HIDEHAIR))
return TRUE
@@ -285,3 +294,7 @@
/obj/item/organ/external/pod_hair/get_global_feature_list()
return GLOB.pod_hair_list
+
+/obj/item/organ/external/pod_hair/override_color(rgb_value)
+ var/list/rgb_list = rgb2num(rgb_value)
+ return rgb(255 - rgb_list[1], 255 - rgb_list[2], 255 - rgb_list[3])
diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm
index ef98d9c876a..3b71ac866b2 100644
--- a/code/modules/surgery/organs/heart.dm
+++ b/code/modules/surgery/organs/heart.dm
@@ -250,7 +250,7 @@
if(owner.health < 5 && COOLDOWN_FINISHED(src, adrenaline_cooldown))
COOLDOWN_START(src, adrenaline_cooldown, rand(25 SECONDS, 1 MINUTES))
to_chat(owner, span_userdanger("You feel yourself dying, but you refuse to give up!"))
- owner.heal_overall_damage(15, 15, 0, BODYPART_ORGANIC)
+ owner.heal_overall_damage(15, 15, 0, BODYTYPE_ORGANIC)
if(owner.reagents.get_reagent_amount(/datum/reagent/medicine/ephedrine) < 20)
owner.reagents.add_reagent(/datum/reagent/medicine/ephedrine, 10)
diff --git a/code/modules/surgery/prosthetic_replacement.dm b/code/modules/surgery/prosthetic_replacement.dm
index a26c586541e..fb0f462d010 100644
--- a/code/modules/surgery/prosthetic_replacement.dm
+++ b/code/modules/surgery/prosthetic_replacement.dm
@@ -42,14 +42,15 @@
tool = organ_storage_contents
if(istype(tool, /obj/item/bodypart))
var/obj/item/bodypart/bodypart_to_attach = tool
- if(bodypart_to_attach.status != BODYPART_ROBOTIC)
+ if(IS_ORGANIC_LIMB(bodypart_to_attach))
organ_rejection_dam = 10
if(ishuman(target))
var/mob/living/carbon/human/human_target = target
- if(!(bodypart_to_attach.part_origin & human_target.dna.species.allowed_animal_origin))
+ var/obj/item/bodypart/chest/target_chest = human_target.get_bodypart(BODY_ZONE_CHEST)
+ if(!(bodypart_to_attach.bodytype & target_chest.acceptable_bodytype))
to_chat(user, span_warning("[bodypart_to_attach] doesn't match the patient's morphology."))
return -1
- if(human_target.dna.species.id != bodypart_to_attach.species_id)
+ if(human_target.dna.species.id != bodypart_to_attach.limb_id)
organ_rejection_dam = 30
if(target_zone == bodypart_to_attach.body_zone) //so we can't replace a leg with an arm, or a human arm with a monkey arm.
diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm
index eaec3c8b652..ca778dab316 100644
--- a/code/modules/surgery/surgery.dm
+++ b/code/modules/surgery/surgery.dm
@@ -7,7 +7,7 @@
var/can_cancel = TRUE //Can cancel this surgery after step 1 with cautery
var/list/target_mobtypes = list(/mob/living/carbon/human) //Acceptable Species
var/location = BODY_ZONE_CHEST //Surgery location
- var/requires_bodypart_type = BODYPART_ORGANIC //Prevents you from performing an operation on incorrect limbs. 0 for any limb type
+ var/requires_bodypart_type = BODYTYPE_ORGANIC //Prevents you from performing an operation on incorrect limbs. 0 for any limb type
var/list/possible_locs = list() //Multiple locations
var/ignore_clothes = FALSE //This surgery ignores clothes
var/mob/living/carbon/target //Operation target mob
diff --git a/code/modules/unit_tests/create_and_destroy.dm b/code/modules/unit_tests/create_and_destroy.dm
index f037406dbfe..e8f61fbcd83 100644
--- a/code/modules/unit_tests/create_and_destroy.dm
+++ b/code/modules/unit_tests/create_and_destroy.dm
@@ -25,6 +25,8 @@
/mob/dview,
//Requires a circuit url
/obj/effect/mapping_helpers/circuit_spawner,
+ //Template type
+ /obj/item/bodypart,
)
//Say it with me now, type template
ignore += typesof(/obj/effect/mapping_helpers/atom_injector)
diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm
index f46a2844ac0..5375454e026 100644
--- a/code/modules/vending/_vending.dm
+++ b/code/modules/vending/_vending.dm
@@ -601,7 +601,7 @@ GLOBAL_LIST_EMPTY(vending_products)
if(5) // limb squish!
for(var/i in C.bodyparts)
var/obj/item/bodypart/squish_part = i
- if(squish_part.is_organic_limb())
+ if(IS_ORGANIC_LIMB(squish_part))
var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate))
squish_part.force_wound_upwards(type_wound)
else
diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm
index 42cec530da3..ac629053477 100644
--- a/code/modules/zombie/organs.dm
+++ b/code/modules/zombie/organs.dm
@@ -4,7 +4,6 @@
zone = BODY_ZONE_HEAD
slot = ORGAN_SLOT_ZOMBIE
icon_state = "blacktumor"
- visual = FALSE
var/causes_damage = TRUE
var/datum/species/old_species = /datum/species/human
var/living_transformation_time = 30
@@ -31,7 +30,7 @@
/obj/item/organ/zombie_infection/Remove(mob/living/carbon/M, special = 0)
. = ..()
STOP_PROCESSING(SSobj, src)
- if(iszombie(M) && old_species && !QDELETED(M))
+ if(iszombie(M) && old_species && !special && !QDELETED(src))
M.set_species(old_species)
if(timer_id)
deltimer(timer_id)
@@ -41,7 +40,7 @@
web of pus and viscera, bound tightly around the brain like some \
biological harness.")
-/obj/item/organ/zombie_infection/process(delta_time)
+/obj/item/organ/zombie_infection/process(delta_time, times_fired)
if(!owner)
return
if(!(src in owner.internal_organs))
@@ -50,7 +49,7 @@
return
if (causes_damage && !iszombie(owner) && owner.stat != DEAD)
owner.adjustToxLoss(0.5 * delta_time)
- if(DT_PROB(5, delta_time))
+ if (DT_PROB(5, delta_time))
to_chat(owner, span_danger("You feel sick..."))
if(timer_id)
return
@@ -66,9 +65,9 @@
not even death can stop, you will rise again!")
var/revive_time = rand(revive_time_min, revive_time_max)
var/flags = TIMER_STOPPABLE
- timer_id = addtimer(CALLBACK(src, .proc/zombify), revive_time, flags)
+ timer_id = addtimer(CALLBACK(src, .proc/zombify, owner), revive_time, flags)
-/obj/item/organ/zombie_infection/proc/zombify()
+/obj/item/organ/zombie_infection/proc/zombify(mob/living/carbon/target)
timer_id = null
if(!converts_living && owner.stat != DEAD)
@@ -76,24 +75,24 @@
if(!iszombie(owner))
old_species = owner.dna.species.type
- owner.set_species(/datum/species/zombie/infectious)
+ target.set_species(/datum/species/zombie/infectious)
- var/stand_up = (owner.stat == DEAD) || (owner.stat == UNCONSCIOUS)
+ var/stand_up = (target.stat == DEAD) || (target.stat == UNCONSCIOUS)
//Fully heal the zombie's damage the first time they rise
- owner.setToxLoss(0, 0)
- owner.setOxyLoss(0, 0)
- owner.heal_overall_damage(INFINITY, INFINITY, INFINITY, null, TRUE)
+ target.setToxLoss(0, 0)
+ target.setOxyLoss(0, 0)
+ target.heal_overall_damage(INFINITY, INFINITY, INFINITY, null, TRUE)
- if(!owner.revive(full_heal = FALSE, admin_revive = FALSE))
+ if(!target.revive())
return
- owner.grab_ghost()
- owner.visible_message(span_danger("[owner] suddenly convulses, as [owner.p_they()][stand_up ? " stagger to [owner.p_their()] feet and" : ""] gain a ravenous hunger in [owner.p_their()] eyes!"), span_alien("You HUNGER!"))
- playsound(owner.loc, 'sound/hallucinations/far_noise.ogg', 50, TRUE)
- owner.do_jitter_animation(living_transformation_time)
- owner.Stun(living_transformation_time)
- to_chat(owner, span_alertalien("You are now a zombie! Do not seek to be cured, do not help any non-zombies in any way, do not harm your zombie brethren and spread the disease by killing others. You are a creature of hunger and violence."))
+ target.grab_ghost()
+ target.visible_message(span_danger("[owner] suddenly convulses, as [owner.p_they()][stand_up ? " stagger to [owner.p_their()] feet and" : ""] gain a ravenous hunger in [owner.p_their()] eyes!"), span_alien("You HUNGER!"))
+ playsound(target.loc, 'sound/hallucinations/far_noise.ogg', 50, 1)
+ target.do_jitter_animation(living_transformation_time)
+ target.Stun(living_transformation_time)
+ to_chat(target, span_alertalien("You are now a zombie! Do not seek to be cured, do not help any non-zombies in any way, do not harm your zombie brethren and spread the disease by killing others. You are a creature of hunger and violence."))
/obj/item/organ/zombie_infection/nodamage
causes_damage = FALSE
diff --git a/html/changelogs/archive/2021-12.yml b/html/changelogs/archive/2021-12.yml
index 80519e52b3a..3bf2ee67696 100644
--- a/html/changelogs/archive/2021-12.yml
+++ b/html/changelogs/archive/2021-12.yml
@@ -233,7 +233,7 @@
- rscdel: The psychologist no longer has a spare skillchip on Blueshift.
2021-12-09:
AtoriBirb:
- - code_imp: Added mutant_variants = NONE to robes/cloak/mask for heretic
+ - code_imp: Added supports_variations_flags = NONE to robes/cloak/mask for heretic
- code_imp: Adds two if statements to swap between mutant_variant = none and default.
I would do an else but I dunno what other variables might hit it on accident.
If it works, it works.
diff --git a/icons/mob/augmentation/augments.dmi b/icons/mob/augmentation/augments.dmi
index 4449da22d58..21e55386d3a 100644
Binary files a/icons/mob/augmentation/augments.dmi and b/icons/mob/augmentation/augments.dmi differ
diff --git a/icons/mob/augmentation/augments_engineer.dmi b/icons/mob/augmentation/augments_engineer.dmi
index 0e7fed2873c..45a3142de24 100644
Binary files a/icons/mob/augmentation/augments_engineer.dmi and b/icons/mob/augmentation/augments_engineer.dmi differ
diff --git a/icons/mob/augmentation/augments_mining.dmi b/icons/mob/augmentation/augments_mining.dmi
index 3942dc0c851..39df4823fd1 100644
Binary files a/icons/mob/augmentation/augments_mining.dmi and b/icons/mob/augmentation/augments_mining.dmi differ
diff --git a/icons/mob/augmentation/augments_security.dmi b/icons/mob/augmentation/augments_security.dmi
index 20c25f52332..97a561ed010 100644
Binary files a/icons/mob/augmentation/augments_security.dmi and b/icons/mob/augmentation/augments_security.dmi differ
diff --git a/icons/mob/augmentation/surplus_augments.dmi b/icons/mob/augmentation/surplus_augments.dmi
index bc3e4bd73ca..0fafab05336 100644
Binary files a/icons/mob/augmentation/surplus_augments.dmi and b/icons/mob/augmentation/surplus_augments.dmi differ
diff --git a/icons/mob/clothing/under/cargo.dmi b/icons/mob/clothing/under/cargo.dmi
index 105b6ac2fd4..05220dff1db 100644
Binary files a/icons/mob/clothing/under/cargo.dmi and b/icons/mob/clothing/under/cargo.dmi differ
diff --git a/icons/mob/clothing/under/shorts_pants.dmi b/icons/mob/clothing/under/shorts_pants.dmi
index 24c684c150b..3baa75d7d84 100644
Binary files a/icons/mob/clothing/under/shorts_pants.dmi and b/icons/mob/clothing/under/shorts_pants.dmi differ
diff --git a/icons/mob/human_parts.dmi b/icons/mob/human_parts.dmi
index c9ec0084b19..187dd2738f5 100644
Binary files a/icons/mob/human_parts.dmi and b/icons/mob/human_parts.dmi differ
diff --git a/icons/mob/human_parts_greyscale.dmi b/icons/mob/human_parts_greyscale.dmi
index 647c263c407..e2a7b330cb1 100644
Binary files a/icons/mob/human_parts_greyscale.dmi and b/icons/mob/human_parts_greyscale.dmi differ
diff --git a/icons/mob/species/ethereal/bodyparts.dmi b/icons/mob/species/ethereal/bodyparts.dmi
new file mode 100644
index 00000000000..d063c92b746
Binary files /dev/null and b/icons/mob/species/ethereal/bodyparts.dmi differ
diff --git a/icons/mob/species/lizard/bodyparts.dmi b/icons/mob/species/lizard/bodyparts.dmi
new file mode 100644
index 00000000000..c3961ade3c6
Binary files /dev/null and b/icons/mob/species/lizard/bodyparts.dmi differ
diff --git a/icons/mob/species/misc/digitigrade.dmi b/icons/mob/species/misc/digitigrade.dmi
new file mode 100644
index 00000000000..9d40540c14c
Binary files /dev/null and b/icons/mob/species/misc/digitigrade.dmi differ
diff --git a/icons/mob/species/moth/bodyparts.dmi b/icons/mob/species/moth/bodyparts.dmi
new file mode 100644
index 00000000000..6324ad386e4
Binary files /dev/null and b/icons/mob/species/moth/bodyparts.dmi differ
diff --git a/icons/mob/species/plasmaman/bodyparts.dmi b/icons/mob/species/plasmaman/bodyparts.dmi
new file mode 100644
index 00000000000..c8ee2763615
Binary files /dev/null and b/icons/mob/species/plasmaman/bodyparts.dmi differ
diff --git a/modular_skyrat/master_files/code/game/objects/items/hhmirror.dm b/modular_skyrat/master_files/code/game/objects/items/hhmirror.dm
index accf7f7a1c3..e30af3d5015 100644
--- a/modular_skyrat/master_files/code/game/objects/items/hhmirror.dm
+++ b/modular_skyrat/master_files/code/game/objects/items/hhmirror.dm
@@ -15,7 +15,7 @@
desc = "A handheld mirror that allows you to change your... self?" //Later, maybe add a charge to the description.
icon = 'modular_skyrat/master_files/icons/obj/hhmirror.dmi'
icon_state = "hhmirrormagic"
- var/list/races_blacklist = list(SPECIES_SKELETON, "agent", "angel", SPECIES_SYNTH_MILITARY, SPECIES_ZOMBIE, "clockwork golem servant", SPECIES_ANDROID, SPECIES_SYNTH, SPECIES_MUSHROOM, SPECIES_ZOMBIE_HALLOWEEN, "memezombie")
+ var/list/races_blacklist = list(SPECIES_SKELETON, "agent", "angel", SPECIES_ZOMBIE, "clockwork golem servant", SPECIES_MUSHROOM, "memezombie")
var/list/choosable_races = list()
/obj/item/hhmirror/fullmagic/New()
diff --git a/modular_skyrat/master_files/code/modules/client/preferences/body_type.dm b/modular_skyrat/master_files/code/modules/client/preferences/body_type.dm
deleted file mode 100644
index ce354b20558..00000000000
--- a/modular_skyrat/master_files/code/modules/client/preferences/body_type.dm
+++ /dev/null
@@ -1,14 +0,0 @@
-/datum/preference/choiced/body_type
- category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
- priority = PREFERENCE_PRIORITY_BODY_TYPE
- savefile_key = "body_type"
- savefile_identifier = PREFERENCE_CHARACTER
-
-/datum/preference/choiced/body_type/init_possible_values()
- return list(MALE, FEMALE)
-
-/datum/preference/choiced/body_type/apply_to_human(mob/living/carbon/human/target, value)
- target.body_type = value
-
-/datum/preference/choiced/body_type/create_default_value()
- return MALE
diff --git a/modular_skyrat/master_files/code/modules/client/preferences/mutant_parts.dm b/modular_skyrat/master_files/code/modules/client/preferences/mutant_parts.dm
index f088f95c2a7..50de6b20471 100644
--- a/modular_skyrat/master_files/code/modules/client/preferences/mutant_parts.dm
+++ b/modular_skyrat/master_files/code/modules/client/preferences/mutant_parts.dm
@@ -194,6 +194,9 @@
if(!target.dna.mutant_bodyparts[relevant_mutant_bodypart])
target.dna.mutant_bodyparts[relevant_mutant_bodypart] = list(MUTANT_INDEX_NAME = "None", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF"), MUTANT_INDEX_EMISSIVE_LIST = list(FALSE, FALSE, FALSE))
target.dna.mutant_bodyparts[relevant_mutant_bodypart][MUTANT_INDEX_NAME] = value
+ var/obj/item/bodypart/head/our_head = target.get_bodypart(BODY_ZONE_HEAD)
+ our_head.bodytype |= BODYTYPE_SNOUTED
+ target.dna.species.bodytype |= BODYTYPE_SNOUTED // Snowflake code alert
/datum/preference/choiced/snout/create_default_value()
var/datum/sprite_accessory/snouts/none/default = /datum/sprite_accessory/snouts/none
@@ -488,54 +491,6 @@
relevant_mutant_bodypart = "spines"
type_to_check = /datum/preference/toggle/spines
-/// Legs
-
-/datum/preference/toggle/legs
- category = PREFERENCE_CATEGORY_SECONDARY_FEATURES
- savefile_identifier = PREFERENCE_CHARACTER
- savefile_key = "legs_toggle"
- relevant_mutant_bodypart = "legs"
- default_value = FALSE
-
-/datum/preference/toggle/legs/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences)
- return TRUE // we dont actually want this to do anything
-
-/datum/preference/toggle/legs/is_accessible(datum/preferences/preferences)
- var/passed_initial_check = ..(preferences)
- var/allowed = preferences.read_preference(/datum/preference/toggle/allow_mismatched_parts)
- return passed_initial_check || allowed
-
-/datum/preference/choiced/legs
- savefile_key = "feature_legs"
- savefile_identifier = PREFERENCE_CHARACTER
- category = PREFERENCE_CATEGORY_SECONDARY_FEATURES
- relevant_mutant_bodypart = "legs"
-
-/datum/preference/choiced/legs/is_accessible(datum/preferences/preferences)
- var/passed_initial_check = ..(preferences)
- var/allowed = preferences.read_preference(/datum/preference/toggle/allow_mismatched_parts)
- var/part_enabled = preferences.read_preference(/datum/preference/toggle/legs)
- return ((passed_initial_check || allowed) && part_enabled)
-
-/datum/preference/choiced/legs/init_possible_values()
- return assoc_to_keys(GLOB.sprite_accessories["legs"])
-
-/datum/preference/choiced/legs/apply_to_human(mob/living/carbon/human/target, value)
- if(!target.dna.mutant_bodyparts[relevant_mutant_bodypart])
- target.dna.mutant_bodyparts[relevant_mutant_bodypart] = list(MUTANT_INDEX_NAME = "None", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF"), MUTANT_INDEX_EMISSIVE_LIST = list(FALSE, FALSE, FALSE))
- target.dna.mutant_bodyparts[relevant_mutant_bodypart][MUTANT_INDEX_NAME] = value
-
-/datum/preference/choiced/legs/create_default_value()
- var/datum/sprite_accessory/legs/none/default = /datum/sprite_accessory/legs/none
- return initial(default.name)
-
-/datum/preference/tri_color/legs
- category = PREFERENCE_CATEGORY_SECONDARY_FEATURES
- savefile_identifier = PREFERENCE_CHARACTER
- savefile_key = "legs_color"
- relevant_mutant_bodypart = "legs"
- type_to_check = /datum/preference/toggle/legs
-
/// Caps
/datum/preference/toggle/caps
diff --git a/modular_skyrat/master_files/code/modules/client/preferences/species_features/digitigrade_legs.dm b/modular_skyrat/master_files/code/modules/client/preferences/species_features/digitigrade_legs.dm
new file mode 100644
index 00000000000..da0dbb5ad3e
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/client/preferences/species_features/digitigrade_legs.dm
@@ -0,0 +1,17 @@
+/// Legs
+/datum/preference/choiced/digitigrade_legs
+ savefile_key = "digitigrade_legs"
+ savefile_identifier = PREFERENCE_CHARACTER
+ category = PREFERENCE_CATEGORY_SECONDARY_FEATURES
+ relevant_mutant_bodypart = "legs"
+
+/datum/preference/choiced/digitigrade_legs/init_possible_values()
+ return assoc_to_keys(GLOB.sprite_accessories["legs"])
+
+/datum/preference/choiced/digitigrade_legs/apply_to_human(mob/living/carbon/human/target, value)
+ target.dna.features["legs"] = value
+
+/datum/preference/choiced/digitigrade_legs/is_accessible(datum/preferences/preferences)
+ var/passed_initial_check = ..(preferences)
+ var/allowed = preferences.read_preference(/datum/preference/toggle/allow_mismatched_parts)
+ return passed_initial_check || allowed
diff --git a/modular_skyrat/master_files/code/modules/clothing/anthro_clothes.dm b/modular_skyrat/master_files/code/modules/clothing/anthro_clothes.dm
index fc4432c88d0..c2ef5d965cc 100644
--- a/modular_skyrat/master_files/code/modules/clothing/anthro_clothes.dm
+++ b/modular_skyrat/master_files/code/modules/clothing/anthro_clothes.dm
@@ -2,7 +2,7 @@
//HEAD>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/obj/item/clothing/head/hardhat/atmos
- mutant_variants = STYLE_MUZZLE | STYLE_VOX
+ supports_variations_flags = CLOTHING_SNOUTED_VARIATION | CLOTHING_SNOUTED_VOX_VARIATION
/obj/item/clothing/head/sombrero
flags_inv = HIDEHAIR | SHOWSPRITEEARS
@@ -15,10 +15,10 @@
//MASK>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/obj/item/clothing/mask/gas/atmos
- mutant_variants = STYLE_MUZZLE | STYLE_VOX
+ supports_variations_flags = CLOTHING_SNOUTED_VARIATION | CLOTHING_SNOUTED_VOX_VARIATION
/obj/item/clothing/mask/gas/atmos/captain
- mutant_variants = STYLE_MUZZLE | STYLE_VOX
+ supports_variations_flags = CLOTHING_SNOUTED_VARIATION | CLOTHING_SNOUTED_VOX_VARIATION
/obj/item/clothing/mask/luchador //No longer has HIDESNOUT, has SHOWSPRITEEARS
flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|SHOWSPRITEEARS
@@ -33,6 +33,6 @@
//SUIT>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/obj/item/clothing/suit/fire
- mutant_variants = STYLE_DIGITIGRADE
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION
//FEET>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
diff --git a/modular_skyrat/master_files/code/modules/clothing/chameleon.dm b/modular_skyrat/master_files/code/modules/clothing/chameleon.dm
index 57431357e04..b0f616d1008 100644
--- a/modular_skyrat/master_files/code/modules/clothing/chameleon.dm
+++ b/modular_skyrat/master_files/code/modules/clothing/chameleon.dm
@@ -27,7 +27,7 @@
if(istype(target, /obj/item/clothing/))
var/obj/item/clothing/target_clothing = target
var/obj/item/clothing/picked_clothing = picked_item
- target_clothing.mutant_variants = initial(picked_clothing.mutant_variants)
+ target_clothing.supports_variations_flags = initial(picked_clothing.supports_variations_flags)
target_clothing.worn_icon_digi = initial(picked_clothing.worn_icon_digi)
target_clothing.worn_icon_taur_snake = initial(picked_clothing.worn_icon_taur_snake)
target_clothing.worn_icon_taur_paw = initial(picked_clothing.worn_icon_taur_paw)
diff --git a/modular_skyrat/master_files/code/modules/clothing/non_anthro_clothes.dm b/modular_skyrat/master_files/code/modules/clothing/non_anthro_clothes.dm
index ada11f9554e..8272cbe801b 100644
--- a/modular_skyrat/master_files/code/modules/clothing/non_anthro_clothes.dm
+++ b/modular_skyrat/master_files/code/modules/clothing/non_anthro_clothes.dm
@@ -3,465 +3,466 @@
//HEAD>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/obj/item/clothing/head/festive
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/gladiator
- mutant_variants = NONE
+ supports_variations_flags = NONE
+
/obj/item/clothing/head/chefhat
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hos/beret
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/soft/paramedic
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hooded/explorer
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/sec
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/warden
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/wizard/red
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/wizard
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hos
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/beret/blueshield
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/caphat
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/crown/fancy
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hopcap
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hardhat
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/beanie
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/abductor
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hooded/winterhood
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/beret
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/soft
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/flatcap
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/pirate
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/rice_hat
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/ushanka
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/collectable
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/fedora
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/that
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/rabbitears
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/mailman
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/centhat
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/nursehat
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/cueball
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/bandana
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hunter
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/scarecrow_hat
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/intern
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/blueshirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/space/space_ninja
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/space/beret
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/police
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/swat
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/spacepolice
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/sombrero
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/santa
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/durathread
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hooded/cloakhood/drake
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hooded/cloakhood/goliath
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/nun_hood
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/knight/greyscale
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/mob_holder
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hooded/cult_hoodie/void
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hooded/cult_hoodie/eldritch
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/space/hardsuit/berserker
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hooded/cloakhood/godslayer
- mutant_variants = NONE
+ supports_variations_flags = NONE
//EARS>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//EYES>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/obj/item/clothing/glasses/changeling
- mutant_variants = NONE
+ supports_variations_flags = NONE
//MASK>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/obj/item/clothing/mask/gas/hunter
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/mask/fakemoustache
flags_inv = NONE
/obj/item/clothing/mask/gas/tiki_mask/yalp_elor
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/mask/gas/carp
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/mask/gas/sechailer/swat/spacepol
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/mask/void_mask
- mutant_variants = NONE
+ supports_variations_flags = NONE
//UNDER>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/obj/item/clothing/under/costume/gladiator/ash_walker
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/costume/maid
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/costume/schoolgirl
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/rank/centcom/intern
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/misc/bouncer
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/rank/security/officer/spacepol
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/rank/medical/doctor/nurse
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/syndicate/skirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
body_parts_covered = CHEST|GROIN|ARMS
/obj/item/clothing/under/syndicate/tacticool/skirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
body_parts_covered = CHEST|GROIN|ARMS
/obj/item/clothing/under/rank/captain/suit/skirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/rank/civilian/lawyer/black/skirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/rank/civilian/lawyer/female/skirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/rank/civilian/lawyer/red/skirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/rank/civilian/lawyer/blue/skirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/color/jumpskirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/suit/black/skirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/rank/captain/pilot/skirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/toggle/labcoat/roboticist
- mutant_variants = NONE
+ supports_variations_flags = NONE
//SUIT>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/obj/item/clothing/suit/toggle/chef
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/det_suit
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/toggle/lawyer
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/toggle/suspenders
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/toggle/labcoat/paramedic
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/jacket/miljacket
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/jacket
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/ianshirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/poncho
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/wizrobe
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/hooded/bee_costume
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/space/hunter
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/chaplainsuit/holidaypriest
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/hazardvest
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/pirate/captain
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/space/officer
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/hooded/chaplain_hoodie
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/curator
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/hooded/chaplainsuit
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/chaplainsuit
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/armor/riot/knight/greyscale
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/toggle/armor/vest/centcom_formal
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/hooded/cultrobes/void
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/hooded/cultrobes/eldritch
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/armor/vest/marine
- mutant_variants = NONE
+ supports_variations_flags = NONE
//FEET>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/obj/item/clothing/under/changeling
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/changeling
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/changeling
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/shoes/changeling
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/gloves/changeling
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/mask/changeling
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/changeling
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/storage/backpack/henchmen
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/irs
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/pg
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/tmc
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/deckers
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/morningstar
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/saints
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/allies
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/yuri
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/sybil_slickers
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/basil_boys
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/alt
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/xenos
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/cone
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/mask/gas/driscoll
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/helmet/space/chronos
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/yakuza
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/dutch
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/driscoll
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/irs
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/osi
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/tmc
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/pg
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/deckers
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/morningstar
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/saints
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/phantom
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/allies
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/soviet
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/yuri
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/security
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/costume/swagoutfit
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/suit/henchmen
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/rank/cargo/tech
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/rank/prisoner/skirt
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/hooded/techpriest
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/head/hooded/techpriest
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/space/hardsuit/berserker
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/hooded/cloak/godslayer
- mutant_variants = NONE
+ supports_variations_flags = NONE
diff --git a/modular_skyrat/master_files/code/modules/mod/mod_clothes.dm b/modular_skyrat/master_files/code/modules/mod/mod_clothes.dm
index ada65644fb0..70ea67fba8e 100644
--- a/modular_skyrat/master_files/code/modules/mod/mod_clothes.dm
+++ b/modular_skyrat/master_files/code/modules/mod/mod_clothes.dm
@@ -1,19 +1,19 @@
// MODsuit-related overrides for our digitigrade sprites and such
/obj/item/clothing/head/mod
- mutant_variants = STYLE_MUZZLE
+ supports_variations_flags = CLOTHING_SNOUTED_VARIATION
worn_icon_muzzled = 'modular_skyrat/master_files/icons/mob/mod.dmi'
/obj/item/clothing/suit/mod
- mutant_variants = STYLE_DIGITIGRADE
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION
flags_inv = HIDESPINE
worn_icon_digi = 'modular_skyrat/master_files/icons/mob/mod.dmi'
/obj/item/clothing/gloves/mod
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/shoes/mod
- mutant_variants = STYLE_DIGITIGRADE
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION
worn_icon_digi = 'modular_skyrat/master_files/icons/mob/mod.dmi'
diff --git a/modular_skyrat/master_files/code/modules/mod/modules/_module.dm b/modular_skyrat/master_files/code/modules/mod/modules/_module.dm
index b577361c41b..1e6f84d75ab 100644
--- a/modular_skyrat/master_files/code/modules/mod/modules/_module.dm
+++ b/modular_skyrat/master_files/code/modules/mod/modules/_module.dm
@@ -1,6 +1,6 @@
/obj/item/mod/module
- /// The suit's mutant_variants, currently only for the chestplate and the helmet parts of the MODsuit.
- var/suit_mutant_variants = NONE
+ /// The suit's supports_variations_flags, currently only for the chestplate and the helmet parts of the MODsuit.
+ var/suit_supports_variations_flags = NONE
/// Does this module have a separate head sprite? Useful for muzzled sprites
var/has_head_sprite = FALSE
/// Is the module's visuals head-only when active? Useful for visors and such, to avoid multiplying the amount of overlay with empty images
@@ -19,18 +19,18 @@
/obj/item/mod/module/proc/handle_module_icon(mutable_appearance/standing, module_icon_state)
. = list()
if(mod.wearer)
- if(mod.chestplate && (mod.chestplate.mutant_variants & STYLE_DIGITIGRADE) && (DIGITIGRADE in mod.wearer.dna.species.species_traits))
- suit_mutant_variants |= STYLE_DIGITIGRADE
+ if(mod.chestplate && (mod.chestplate.supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION) && (mod.wearer.dna.species.bodytype & BODYTYPE_DIGITIGRADE))
+ suit_supports_variations_flags |= CLOTHING_DIGITIGRADE_VARIATION
- if(mod.helmet && (mod.helmet.mutant_variants & STYLE_MUZZLE) && mod.wearer.dna.species.mutant_bodyparts["snout"])
+ if(mod.helmet && (mod.helmet.supports_variations_flags & CLOTHING_SNOUTED_VARIATION) && mod.wearer.dna.species.mutant_bodyparts["snout"])
var/datum/sprite_accessory/snouts/snout = GLOB.sprite_accessories["snout"][mod.wearer.dna.species.mutant_bodyparts["snout"][MUTANT_INDEX_NAME]]
if(snout.use_muzzled_sprites)
- suit_mutant_variants |= STYLE_MUZZLE
+ suit_supports_variations_flags |= CLOTHING_SNOUTED_VARIATION
var/icon_to_use = 'icons/mob/clothing/mod.dmi'
var/icon_state_to_use = module_icon_state
var/add_overlay = TRUE
- if(suit_mutant_variants && (mutant_variants & STYLE_DIGITIGRADE))
+ if(suit_supports_variations_flags && (supports_variations_flags & CLOTHING_DIGITIGRADE_VARIATION))
icon_to_use = 'modular_skyrat/master_files/icons/mob/mod.dmi'
icon_state_to_use = "[module_icon_state]_digi"
@@ -46,7 +46,7 @@
icon_to_use = 'modular_skyrat/master_files/icons/mob/mod.dmi'
icon_state_to_use = "[module_icon_state]_head"
- if(suit_mutant_variants && (mutant_variants & STYLE_MUZZLE))
+ if(suit_supports_variations_flags && (supports_variations_flags & CLOTHING_SNOUTED_VARIATION))
icon_state_to_use = "[icon_state_to_use]_muzzled"
var/mutable_appearance/additional_module_icon = mutable_appearance(icon_to_use, icon_state_to_use, layer = standing.layer + 0.1)
diff --git a/modular_skyrat/master_files/code/modules/mod/modules/modules_antag.dm b/modular_skyrat/master_files/code/modules/mod/modules/modules_antag.dm
index cf4104d4f8c..fd22f651494 100644
--- a/modular_skyrat/master_files/code/modules/mod/modules/modules_antag.dm
+++ b/modular_skyrat/master_files/code/modules/mod/modules/modules_antag.dm
@@ -1,4 +1,4 @@
/obj/item/mod/module/armor_booster
- mutant_variants = STYLE_DIGITIGRADE | STYLE_MUZZLE
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION | CLOTHING_SNOUTED_VARIATION
has_head_sprite = TRUE
head_only_when_active = TRUE
diff --git a/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/_mutant_bodyparts.dm b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/_mutant_bodyparts.dm
new file mode 100644
index 00000000000..6ea59d0a43e
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/_mutant_bodyparts.dm
@@ -0,0 +1,89 @@
+/obj/item/bodypart
+ /// A list of all of our bodypart markings.
+ var/list/markings
+ /// A list of all our aux zone markings(hands)
+ var/list/aux_zone_markings
+ /// The alpha override of our markings.
+ var/markings_alpha
+ /// What is our normal limb ID? used for squashing legs.
+ var/base_limb_id = SPECIES_MAMMAL
+
+/obj/item/bodypart/proc/check_mutant_compatability()
+ if(ishuman(owner))
+ var/mob/living/carbon/human/human_owner = owner
+ var/uniform_compatible = FALSE
+ var/suit_compatible = FALSE
+ var/shoes_compatible = FALSE
+ if(!(human_owner.w_uniform) || (human_owner.w_uniform.supports_variations_flags & (CLOTHING_DIGITIGRADE_VARIATION|CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON)))
+ uniform_compatible = TRUE
+ if((!human_owner.wear_suit) || (human_owner.wear_suit.supports_variations_flags & (CLOTHING_DIGITIGRADE_VARIATION|CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON)) || !(human_owner.wear_suit.body_parts_covered & LEGS))
+ suit_compatible = TRUE
+ if((!human_owner.shoes) || (human_owner.shoes.supports_variations_flags & (CLOTHING_DIGITIGRADE_VARIATION|CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON)))
+ shoes_compatible = TRUE
+
+ if((uniform_compatible && suit_compatible && shoes_compatible) || (suit_compatible && human_owner.wear_suit?.flags_inv & HIDEJUMPSUIT)) //If the uniform is hidden, it doesnt matter if its compatible
+ limb_id = "digitigrade"
+ else
+ limb_id = base_limb_id
+
+/obj/item/bodypart/r_leg
+ /// This is used in digitigrade legs, when this leg is swapped out with the digitigrade version.
+ var/digitigrade_type = /obj/item/bodypart/r_leg/digitigrade
+
+/obj/item/bodypart/l_leg
+ /// This is used in digitigrade legs, when this leg is swapped out with the digitigrade version.
+ var/digitigrade_type = /obj/item/bodypart/l_leg/digitigrade
+
+
+/// General mutant bodyparts. Used in most mutant species.
+/obj/item/bodypart/head/mutant
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/mammal_parts_greyscale.dmi'
+ limb_id = SPECIES_MAMMAL
+ uses_mutcolor = TRUE
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_SNOUTED //This is temporary. Ideally the "snout" external organ adds to this.
+
+/obj/item/bodypart/chest/mutant
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/mammal_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ limb_id = SPECIES_MAMMAL
+ is_dimorphic = TRUE
+
+/obj/item/bodypart/l_arm/mutant
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/mammal_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ limb_id = SPECIES_MAMMAL
+
+/obj/item/bodypart/r_arm/mutant
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/mammal_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ limb_id = SPECIES_MAMMAL
+
+/obj/item/bodypart/l_leg/mutant
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/mammal_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ limb_id = SPECIES_MAMMAL
+
+/obj/item/bodypart/r_leg/mutant
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/mammal_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ limb_id = SPECIES_MAMMAL
+
+/obj/item/bodypart/l_leg/digitigrade
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/mammal_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ limb_id = "digitigrade"
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE
+
+/obj/item/bodypart/l_leg/digitigrade/update_limb(dropping_limb = FALSE, is_creating = FALSE)
+ . = ..()
+ check_mutant_compatability()
+
+/obj/item/bodypart/r_leg/digitigrade
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/mammal_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ limb_id = "digitigrade"
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE
+
+/obj/item/bodypart/r_leg/digitigrade/update_limb(dropping_limb = FALSE, is_creating = FALSE)
+ . = ..()
+ check_mutant_compatability()
diff --git a/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/akula_bodyparts.dm b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/akula_bodyparts.dm
new file mode 100644
index 00000000000..b07b87d8659
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/akula_bodyparts.dm
@@ -0,0 +1,35 @@
+// Akulas!
+/obj/item/bodypart/head/mutant/akula
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/akula_parts_greyscale.dmi'
+ limb_id = SPECIES_AKULA
+
+/obj/item/bodypart/chest/mutant/akula
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/akula_parts_greyscale.dmi'
+ limb_id = SPECIES_AKULA
+
+/obj/item/bodypart/l_arm/mutant/akula
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/akula_parts_greyscale.dmi'
+ limb_id = SPECIES_AKULA
+
+/obj/item/bodypart/r_arm/mutant/akula
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/akula_parts_greyscale.dmi'
+ limb_id = SPECIES_AKULA
+
+/obj/item/bodypart/l_leg/mutant/akula
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/akula_parts_greyscale.dmi'
+ limb_id = SPECIES_AKULA
+ digitigrade_type = /obj/item/bodypart/l_leg/digitigrade/akula
+
+/obj/item/bodypart/r_leg/mutant/akula
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/akula_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ limb_id = SPECIES_AKULA
+ digitigrade_type = /obj/item/bodypart/r_leg/digitigrade/akula
+
+/obj/item/bodypart/l_leg/digitigrade/akula
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/akula_parts_greyscale.dmi'
+ base_limb_id = SPECIES_AKULA
+
+/obj/item/bodypart/r_leg/digitigrade/akula
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/akula_parts_greyscale.dmi'
+ base_limb_id = SPECIES_AKULA
diff --git a/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/ghoul_bodyparts.dm b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/ghoul_bodyparts.dm
new file mode 100644
index 00000000000..7a0ee606f5f
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/ghoul_bodyparts.dm
@@ -0,0 +1,72 @@
+// Ghouls!
+/obj/item/bodypart/head/mutant/ghoul
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/ghoul_bodyparts.dmi'
+ is_dimorphic = FALSE
+ limb_id = SPECIES_GHOUL
+
+/obj/item/bodypart/chest/mutant/ghoul
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/ghoul_bodyparts.dmi'
+ limb_id = SPECIES_GHOUL
+ is_dimorphic = FALSE
+
+/obj/item/bodypart/l_arm/mutant/ghoul
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/ghoul_bodyparts.dmi'
+ limb_id = SPECIES_GHOUL
+
+/obj/item/bodypart/r_arm/mutant/ghoul
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/ghoul_bodyparts.dmi'
+ limb_id = SPECIES_GHOUL
+
+/obj/item/bodypart/l_leg/mutant/ghoul
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/ghoul_bodyparts.dmi'
+ limb_id = SPECIES_GHOUL
+
+/obj/item/bodypart/r_leg/mutant/ghoul
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/ghoul_bodyparts.dmi'
+ limb_id = SPECIES_GHOUL
+
+//LIMBS
+
+/obj/item/bodypart/r_arm/mutant/ghoul/drop_limb(special)
+ ..() // Create Meat, Remove Limb
+ var/percentHealth = 1 - (brute_dam + burn_dam) / max_damage
+ if (percentHealth > 0)
+ // Create Meat
+ var/obj/item/food/meat/slab/newMeat = new /obj/item/food/meat/slab(src.loc)
+
+ . = newMeat // Return MEAT
+
+ qdel(src)
+
+/obj/item/bodypart/l_arm/mutant/ghoul/drop_limb(special)
+ ..() // Create Meat, Remove Limb
+ var/percentHealth = 1 - (brute_dam + burn_dam) / max_damage
+ if (percentHealth > 0)
+ // Create Meat
+ var/obj/item/food/meat/slab/newMeat = new /obj/item/food/meat/slab(src.loc)
+
+ . = newMeat // Return MEAT
+
+ qdel(src)
+
+/obj/item/bodypart/r_leg/mutant/ghoul/drop_limb(special)
+ ..() // Create Meat, Remove Limb
+ var/percentHealth = 1 - (brute_dam + burn_dam) / max_damage
+ if (percentHealth > 0)
+ // Create Meat
+ var/obj/item/food/meat/slab/newMeat = new /obj/item/food/meat/slab(src.loc)
+
+ . = newMeat // Return MEAT
+
+ qdel(src)
+
+/obj/item/bodypart/l_leg/mutant/ghoul/drop_limb(special)
+ ..() // Create Meat, Remove Limb
+ var/percentHealth = 1 - (brute_dam + burn_dam) / max_damage
+ if (percentHealth > 0)
+ // Create Meat
+ var/obj/item/food/meat/slab/newMeat = new /obj/item/food/meat/slab(src.loc)
+
+ . = newMeat // Return MEAT
+
+ qdel(src)
diff --git a/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/insect_bodyparts.dm b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/insect_bodyparts.dm
new file mode 100644
index 00000000000..22a447b9097
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/insect_bodyparts.dm
@@ -0,0 +1,25 @@
+// Insectados!
+/obj/item/bodypart/head/mutant/insect
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/insect_parts_greyscale.dmi'
+ limb_id = SPECIES_INSECT
+
+/obj/item/bodypart/chest/mutant/insect
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/insect_parts_greyscale.dmi'
+ limb_id = SPECIES_INSECT
+
+/obj/item/bodypart/l_arm/mutant/insect
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/insect_parts_greyscale.dmi'
+ limb_id = SPECIES_INSECT
+
+/obj/item/bodypart/r_arm/mutant/insect
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/insect_parts_greyscale.dmi'
+ limb_id = SPECIES_INSECT
+
+/obj/item/bodypart/l_leg/mutant/insect
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/insect_parts_greyscale.dmi'
+ limb_id = SPECIES_INSECT
+
+/obj/item/bodypart/r_leg/mutant/insect
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/insect_parts_greyscale.dmi'
+ limb_id = SPECIES_INSECT
+
diff --git a/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/robotic/_mutant_robotic_bodyparts.dm b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/robotic/_mutant_robotic_bodyparts.dm
new file mode 100644
index 00000000000..01aedb02de0
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/robotic/_mutant_robotic_bodyparts.dm
@@ -0,0 +1,61 @@
+// Synth bois!
+/obj/item/bodypart/head/robot/mutant
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthmammal_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHMAMMAL
+ is_dimorphic = TRUE
+ should_draw_greyscale = TRUE
+ uses_mutcolor = TRUE
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_SNOUTED //This is temporary. Ideally the "snout" external organ adds to this.
+
+/obj/item/bodypart/chest/robot/mutant
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthmammal_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ should_draw_greyscale = TRUE
+ limb_id = SPECIES_SYNTHMAMMAL
+ is_dimorphic = TRUE
+
+/obj/item/bodypart/l_arm/robot/mutant
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthmammal_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHMAMMAL
+ should_draw_greyscale = TRUE
+
+/obj/item/bodypart/r_arm/robot/mutant
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthmammal_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHMAMMAL
+ should_draw_greyscale = TRUE
+
+/obj/item/bodypart/l_leg/robot/mutant
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthmammal_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHMAMMAL
+ should_draw_greyscale = TRUE
+ digitigrade_type = /obj/item/bodypart/l_leg/robot/digitigrade
+
+/obj/item/bodypart/r_leg/robot/mutant
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthmammal_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ should_draw_greyscale = TRUE
+ limb_id = SPECIES_SYNTHMAMMAL
+ digitigrade_type = /obj/item/bodypart/r_leg/robot/digitigrade
+
+/obj/item/bodypart/l_leg/robot/digitigrade
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthmammal_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ should_draw_greyscale = TRUE
+ limb_id = "digitigrade"
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE
+ base_limb_id = SPECIES_SYNTHMAMMAL
+
+/obj/item/bodypart/l_leg/robot/digitigrade/update_limb(dropping_limb = FALSE, is_creating = FALSE)
+ . = ..()
+ check_mutant_compatability()
+
+/obj/item/bodypart/r_leg/robot/digitigrade
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ limb_id = "digitigrade"
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ROBOTIC | BODYTYPE_DIGITIGRADE
+ base_limb_id = SPECIES_SYNTHMAMMAL
+
+/obj/item/bodypart/r_leg/robot/digitigrade/update_limb(dropping_limb = FALSE, is_creating = FALSE)
+ . = ..()
+ check_mutant_compatability()
diff --git a/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/robotic/ipc_bodyparts.dm b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/robotic/ipc_bodyparts.dm
new file mode 100644
index 00000000000..a161dde525b
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/robotic/ipc_bodyparts.dm
@@ -0,0 +1,32 @@
+// IPC bois!
+/obj/item/bodypart/head/robot/mutant/ipc
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/ipc_parts.dmi'
+ uses_mutcolor = FALSE
+ is_dimorphic = FALSE
+ limb_id = SPECIES_IPC
+
+/obj/item/bodypart/chest/robot/mutant/ipc
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/ipc_parts.dmi'
+ uses_mutcolor = FALSE
+ is_dimorphic = FALSE
+ limb_id = SPECIES_IPC
+
+/obj/item/bodypart/l_arm/robot/mutant/ipc
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/ipc_parts.dmi'
+ uses_mutcolor = FALSE
+ limb_id = SPECIES_IPC
+
+/obj/item/bodypart/r_arm/robot/mutant/ipc
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/ipc_parts.dmi'
+ uses_mutcolor = FALSE
+ limb_id = SPECIES_IPC
+
+/obj/item/bodypart/l_leg/robot/mutant/ipc
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/ipc_parts.dmi'
+ uses_mutcolor = FALSE
+ limb_id = SPECIES_IPC
+
+/obj/item/bodypart/r_leg/robot/mutant/ipc
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/ipc_parts.dmi'
+ uses_mutcolor = FALSE
+ limb_id = SPECIES_IPC
diff --git a/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/robotic/synthetic_human_bodyparts.dm b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/robotic/synthetic_human_bodyparts.dm
new file mode 100644
index 00000000000..9896ae54af2
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/robotic/synthetic_human_bodyparts.dm
@@ -0,0 +1,24 @@
+// Synth bois!
+/obj/item/bodypart/head/robot/mutant/human
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthhuman_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHHUMAN
+
+/obj/item/bodypart/chest/robot/mutant/human
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthhuman_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHHUMAN
+
+/obj/item/bodypart/l_arm/robot/mutant/human
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthhuman_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHHUMAN
+
+/obj/item/bodypart/r_arm/robot/mutant/human
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthhuman_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHHUMAN
+
+/obj/item/bodypart/l_leg/robot/mutant/human
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthhuman_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHHUMAN
+
+/obj/item/bodypart/r_leg/robot/mutant/human
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthhuman_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHHUMAN
diff --git a/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/robotic/synthetic_lizard_bodyparts.dm b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/robotic/synthetic_lizard_bodyparts.dm
new file mode 100644
index 00000000000..b752ae7ba06
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/robotic/synthetic_lizard_bodyparts.dm
@@ -0,0 +1,38 @@
+// Synth bois!
+/obj/item/bodypart/head/robot/mutant/lizard
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHLIZ
+
+/obj/item/bodypart/chest/robot/mutant/lizard
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHLIZ
+
+/obj/item/bodypart/l_arm/robot/mutant/lizard
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHLIZ
+
+/obj/item/bodypart/r_arm/robot/mutant/lizard
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHLIZ
+
+/obj/item/bodypart/l_leg/robot/mutant/lizard
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHLIZ
+ digitigrade_type = /obj/item/bodypart/l_leg/robot/digitigrade/lizard
+
+/obj/item/bodypart/r_leg/robot/mutant/lizard
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ limb_id = SPECIES_SYNTHLIZ
+ digitigrade_type = /obj/item/bodypart/r_leg/robot/digitigrade/lizard
+
+/obj/item/bodypart/l_leg/robot/digitigrade/lizard
+ icon = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ icon_static = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ base_limb_id = SPECIES_SYNTHLIZ
+
+/obj/item/bodypart/r_leg/robot/digitigrade/lizard
+ icon = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ icon_static = 'modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi'
+ base_limb_id = SPECIES_SYNTHLIZ
diff --git a/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/skrell_bodyparts.dm b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/skrell_bodyparts.dm
new file mode 100644
index 00000000000..01f0773fc07
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/skrell_bodyparts.dm
@@ -0,0 +1,24 @@
+// Skrell!
+/obj/item/bodypart/head/mutant/skrell
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/skrell_parts_greyscale.dmi'
+ limb_id = SPECIES_SKRELL
+
+/obj/item/bodypart/chest/mutant/skrell
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/skrell_parts_greyscale.dmi'
+ limb_id = SPECIES_SKRELL
+
+/obj/item/bodypart/l_arm/mutant/skrell
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/skrell_parts_greyscale.dmi'
+ limb_id = SPECIES_SKRELL
+
+/obj/item/bodypart/r_arm/mutant/skrell
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/skrell_parts_greyscale.dmi'
+ limb_id = SPECIES_SKRELL
+
+/obj/item/bodypart/l_leg/mutant/skrell
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/skrell_parts_greyscale.dmi'
+ limb_id = SPECIES_SKRELL
+
+/obj/item/bodypart/r_leg/mutant/skrell
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/skrell_parts_greyscale.dmi'
+ limb_id = SPECIES_SKRELL
diff --git a/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/teshari_bodyparts.dm b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/teshari_bodyparts.dm
new file mode 100644
index 00000000000..364406dffc7
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/teshari_bodyparts.dm
@@ -0,0 +1,42 @@
+// teshari!
+/obj/item/bodypart/head/mutant/teshari
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/teshari_parts_greyscale.dmi'
+ bodytype = BODYTYPE_ORGANIC | BODYTYPE_SNOUTED | BODYTYPE_TESHARI
+ limb_id = SPECIES_TESHARI
+
+/obj/item/bodypart/chest/mutant/teshari
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/teshari_parts_greyscale.dmi'
+ bodytype = BODYTYPE_ORGANIC | BODYTYPE_TESHARI
+ limb_id = SPECIES_TESHARI
+
+/obj/item/bodypart/l_arm/mutant/teshari
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/teshari_parts_greyscale.dmi'
+ bodytype = BODYTYPE_ORGANIC | BODYTYPE_TESHARI
+ limb_id = SPECIES_TESHARI
+
+/obj/item/bodypart/r_arm/mutant/teshari
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/teshari_parts_greyscale.dmi'
+ bodytype = BODYTYPE_ORGANIC | BODYTYPE_TESHARI
+ limb_id = SPECIES_TESHARI
+
+/obj/item/bodypart/l_leg/mutant/teshari
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/teshari_parts_greyscale.dmi'
+ bodytype = BODYTYPE_ORGANIC | BODYTYPE_TESHARI
+ limb_id = SPECIES_TESHARI
+ digitigrade_type = /obj/item/bodypart/l_leg/digitigrade/teshari
+
+/obj/item/bodypart/r_leg/mutant/teshari
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/teshari_parts_greyscale.dmi'
+ bodytype = BODYTYPE_ORGANIC | BODYTYPE_TESHARI
+ limb_id = SPECIES_TESHARI
+ digitigrade_type = /obj/item/bodypart/r_leg/digitigrade/teshari
+
+/obj/item/bodypart/l_leg/digitigrade/teshari
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/teshari_parts_greyscale.dmi'
+ bodytype = BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE | BODYTYPE_TESHARI
+ base_limb_id = SPECIES_TESHARI
+
+/obj/item/bodypart/r_leg/digitigrade/teshari
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/teshari_parts_greyscale.dmi'
+ bodytype = BODYTYPE_ORGANIC | BODYTYPE_DIGITIGRADE | BODYTYPE_TESHARI
+ base_limb_id = SPECIES_TESHARI
diff --git a/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/vox_bodyparts.dm b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/vox_bodyparts.dm
new file mode 100644
index 00000000000..d75438b1093
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/vox_bodyparts.dm
@@ -0,0 +1,38 @@
+// voxs!
+/obj/item/bodypart/head/mutant/vox
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/vox_parts_greyscale.dmi'
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_SNOUTED | BODYTYPE_VOX
+ limb_id = SPECIES_VOX
+
+/obj/item/bodypart/chest/mutant/vox
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/vox_parts_greyscale.dmi'
+ limb_id = SPECIES_VOX
+
+/obj/item/bodypart/l_arm/mutant/vox
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/vox_parts_greyscale.dmi'
+ limb_id = SPECIES_VOX
+
+/obj/item/bodypart/r_arm/mutant/vox
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/vox_parts_greyscale.dmi'
+ limb_id = SPECIES_VOX
+
+/obj/item/bodypart/l_leg/mutant/vox
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/vox_parts_greyscale.dmi'
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC
+ limb_id = SPECIES_VOX
+ digitigrade_type = /obj/item/bodypart/l_leg/digitigrade/vox
+
+/obj/item/bodypart/r_leg/mutant/vox
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/vox_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC
+ limb_id = SPECIES_VOX
+ digitigrade_type = /obj/item/bodypart/r_leg/digitigrade/vox
+
+/obj/item/bodypart/l_leg/digitigrade/vox
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/vox_parts_greyscale.dmi'
+ base_limb_id = SPECIES_VOX
+
+/obj/item/bodypart/r_leg/digitigrade/vox
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/vox_parts_greyscale.dmi'
+ base_limb_id = SPECIES_VOX
diff --git a/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/xenohybrid_bodyparts.dm b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/xenohybrid_bodyparts.dm
new file mode 100644
index 00000000000..b81d16002cc
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/surgery/bodyparts/species_parts/xenohybrid_bodyparts.dm
@@ -0,0 +1,35 @@
+// xenohybrid!
+/obj/item/bodypart/head/mutant/xenohybrid
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/xeno_parts_greyscale.dmi'
+ limb_id = SPECIES_XENO
+
+/obj/item/bodypart/chest/mutant/xenohybrid
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/xeno_parts_greyscale.dmi'
+ limb_id = SPECIES_XENO
+
+/obj/item/bodypart/l_arm/mutant/xenohybrid
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/xeno_parts_greyscale.dmi'
+ limb_id = SPECIES_XENO
+
+/obj/item/bodypart/r_arm/mutant/xenohybrid
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/xeno_parts_greyscale.dmi'
+ limb_id = SPECIES_XENO
+
+/obj/item/bodypart/l_leg/mutant/xenohybrid
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/xeno_parts_greyscale.dmi'
+ limb_id = SPECIES_XENO
+ digitigrade_type = /obj/item/bodypart/l_leg/digitigrade/xenohybrid
+
+/obj/item/bodypart/r_leg/mutant/xenohybrid
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/xeno_parts_greyscale.dmi'
+ uses_mutcolor = TRUE
+ limb_id = SPECIES_XENO
+ digitigrade_type = /obj/item/bodypart/r_leg/digitigrade/xenohybrid
+
+/obj/item/bodypart/l_leg/digitigrade/xenohybrid
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/xeno_parts_greyscale.dmi'
+ base_limb_id = SPECIES_XENO
+
+/obj/item/bodypart/r_leg/digitigrade/xenohybrid
+ icon_greyscale = 'modular_skyrat/master_files/icons/mob/species/xeno_parts_greyscale.dmi'
+ base_limb_id = SPECIES_XENO
diff --git a/modular_skyrat/master_files/icons/mob/clothing/species/vox/ears.dmi b/modular_skyrat/master_files/icons/mob/clothing/species/vox/ears.dmi
index b09c349cae9..b05977c27a6 100644
Binary files a/modular_skyrat/master_files/icons/mob/clothing/species/vox/ears.dmi and b/modular_skyrat/master_files/icons/mob/clothing/species/vox/ears.dmi differ
diff --git a/modular_skyrat/master_files/icons/mob/clothing/uniform_digi.dmi b/modular_skyrat/master_files/icons/mob/clothing/uniform_digi.dmi
index 1e352305e15..f126002574d 100644
Binary files a/modular_skyrat/master_files/icons/mob/clothing/uniform_digi.dmi and b/modular_skyrat/master_files/icons/mob/clothing/uniform_digi.dmi differ
diff --git a/modular_skyrat/master_files/icons/mob/species/akula_parts_greyscale.dmi b/modular_skyrat/master_files/icons/mob/species/akula_parts_greyscale.dmi
index 529818da611..68cc71e5cc0 100644
Binary files a/modular_skyrat/master_files/icons/mob/species/akula_parts_greyscale.dmi and b/modular_skyrat/master_files/icons/mob/species/akula_parts_greyscale.dmi differ
diff --git a/modular_skyrat/master_files/icons/mob/species/insect_parts_greyscale.dmi b/modular_skyrat/master_files/icons/mob/species/insect_parts_greyscale.dmi
index 895e1c87911..65e271be6ee 100644
Binary files a/modular_skyrat/master_files/icons/mob/species/insect_parts_greyscale.dmi and b/modular_skyrat/master_files/icons/mob/species/insect_parts_greyscale.dmi differ
diff --git a/modular_skyrat/master_files/icons/mob/species/mammal_parts_greyscale.dmi b/modular_skyrat/master_files/icons/mob/species/mammal_parts_greyscale.dmi
index 18310a0d128..51038358339 100644
Binary files a/modular_skyrat/master_files/icons/mob/species/mammal_parts_greyscale.dmi and b/modular_skyrat/master_files/icons/mob/species/mammal_parts_greyscale.dmi differ
diff --git a/modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi b/modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi
index 169b4d7c926..dcefe44d6e0 100644
Binary files a/modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi and b/modular_skyrat/master_files/icons/mob/species/synthliz_parts_greyscale.dmi differ
diff --git a/modular_skyrat/master_files/icons/mob/species/synthmammal_parts_greyscale.dmi b/modular_skyrat/master_files/icons/mob/species/synthmammal_parts_greyscale.dmi
index c423351fde7..3441459a905 100644
Binary files a/modular_skyrat/master_files/icons/mob/species/synthmammal_parts_greyscale.dmi and b/modular_skyrat/master_files/icons/mob/species/synthmammal_parts_greyscale.dmi differ
diff --git a/modular_skyrat/master_files/icons/mob/species/teshari_parts_greyscale.dmi b/modular_skyrat/master_files/icons/mob/species/teshari_parts_greyscale.dmi
index d476cbc3233..de9ac104ef6 100644
Binary files a/modular_skyrat/master_files/icons/mob/species/teshari_parts_greyscale.dmi and b/modular_skyrat/master_files/icons/mob/species/teshari_parts_greyscale.dmi differ
diff --git a/modular_skyrat/master_files/icons/mob/species/vox_parts_greyscale.dmi b/modular_skyrat/master_files/icons/mob/species/vox_parts_greyscale.dmi
index 2a9fa57f99b..52a3dc8f18a 100644
Binary files a/modular_skyrat/master_files/icons/mob/species/vox_parts_greyscale.dmi and b/modular_skyrat/master_files/icons/mob/species/vox_parts_greyscale.dmi differ
diff --git a/modular_skyrat/master_files/icons/mob/species/xeno_parts_greyscale.dmi b/modular_skyrat/master_files/icons/mob/species/xeno_parts_greyscale.dmi
index a1b8b20ddf2..58a956cdc34 100644
Binary files a/modular_skyrat/master_files/icons/mob/species/xeno_parts_greyscale.dmi and b/modular_skyrat/master_files/icons/mob/species/xeno_parts_greyscale.dmi differ
diff --git a/modular_skyrat/modules/aesthetics/clothing/clothing.dm b/modular_skyrat/modules/aesthetics/clothing/clothing.dm
index 584541597b9..e18ca5f428c 100644
--- a/modular_skyrat/modules/aesthetics/clothing/clothing.dm
+++ b/modular_skyrat/modules/aesthetics/clothing/clothing.dm
@@ -90,7 +90,7 @@
icon_state = "labcoat_rd"
body_parts_covered = CHEST|ARMS|LEGS
armor = list(MELEE = 5, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 80, FIRE = 80, ACID = 70)
- mutant_variants = NONE
+ supports_variations_flags = NONE
///////////////////////////////////////////////////////////////////////HEAD
diff --git a/modular_skyrat/modules/ashwalkers/code/clothing/ash_armour.dm b/modular_skyrat/modules/ashwalkers/code/clothing/ash_armour.dm
index a9e3835b1cb..38a4c447ece 100644
--- a/modular_skyrat/modules/ashwalkers/code/clothing/ash_armour.dm
+++ b/modular_skyrat/modules/ashwalkers/code/clothing/ash_armour.dm
@@ -5,7 +5,7 @@
icon = 'modular_skyrat/modules/ashwalkers/icons/ashwalker_clothing.dmi'
worn_icon = 'modular_skyrat/modules/ashwalkers/icons/ashwalker_clothing_mob.dmi'
icon_state = "headdress"
- mutant_variants = NONE
+ supports_variations_flags = NONE
greyscale_colors = null
greyscale_config = null
@@ -56,7 +56,7 @@
icon = 'modular_skyrat/modules/ashwalkers/icons/ashwalker_clothing.dmi'
worn_icon = 'modular_skyrat/modules/ashwalkers/icons/ashwalker_clothing_mob.dmi'
icon_state = "combat_plates"
- mutant_variants = NONE
+ supports_variations_flags = NONE
greyscale_colors = null
greyscale_config = null
diff --git a/modular_skyrat/modules/ashwalkers/code/clothing/head.dm b/modular_skyrat/modules/ashwalkers/code/clothing/head.dm
index b91ae2bb609..246a55c3fee 100644
--- a/modular_skyrat/modules/ashwalkers/code/clothing/head.dm
+++ b/modular_skyrat/modules/ashwalkers/code/clothing/head.dm
@@ -4,5 +4,5 @@
icon = 'modular_skyrat/modules/ashwalkers/icons/hats.dmi'
worn_icon = 'modular_skyrat/modules/ashwalkers/icons/head.dmi'
icon_state = "shamskull"
- mutant_variants = NONE
+ supports_variations_flags = NONE
diff --git a/modular_skyrat/modules/ashwalkers/code/clothing/misc.dm b/modular_skyrat/modules/ashwalkers/code/clothing/misc.dm
index 912c4fb6f7b..49600b43e6f 100644
--- a/modular_skyrat/modules/ashwalkers/code/clothing/misc.dm
+++ b/modular_skyrat/modules/ashwalkers/code/clothing/misc.dm
@@ -4,7 +4,7 @@
name = "tanned hide"
desc = "The tanned hide of some brown furred creature."
icon_state = "mantle_liz"
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/suit/ashwalkermantle/cape
icon = 'modular_skyrat/modules/ashwalkers/icons/suits.dmi'
@@ -12,5 +12,5 @@
name = "brown leather cape"
desc = "An ash coated cloak."
icon_state = "desertcloak"
- mutant_variants = NONE
+ supports_variations_flags = NONE
diff --git a/modular_skyrat/modules/ashwalkers/code/clothing/neck.dm b/modular_skyrat/modules/ashwalkers/code/clothing/neck.dm
index bf792116c16..ac18a684439 100644
--- a/modular_skyrat/modules/ashwalkers/code/clothing/neck.dm
+++ b/modular_skyrat/modules/ashwalkers/code/clothing/neck.dm
@@ -4,4 +4,4 @@
icon = 'modular_skyrat/modules/ashwalkers/icons/cloaks.dmi'
worn_icon = 'modular_skyrat/modules/ashwalkers/icons/neck.dmi'
icon_state = "tribal-mantle"
- mutant_variants = NONE
+ supports_variations_flags = NONE
diff --git a/modular_skyrat/modules/ashwalkers/code/clothing/shoes.dm b/modular_skyrat/modules/ashwalkers/code/clothing/shoes.dm
index 4396e3ab2e1..c84d61bf83d 100644
--- a/modular_skyrat/modules/ashwalkers/code/clothing/shoes.dm
+++ b/modular_skyrat/modules/ashwalkers/code/clothing/shoes.dm
@@ -4,13 +4,13 @@
icon = 'modular_skyrat/modules/ashwalkers/icons/shoes.dmi'
worn_icon = 'modular_skyrat/modules/ashwalkers/icons/feet.dmi'
icon_state = "legionmetal"
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/shoes/jackboots/ashwalker/legate
icon = 'modular_skyrat/modules/ashwalkers/icons/shoes.dmi'
worn_icon = 'modular_skyrat/modules/ashwalkers/icons/feet.dmi'
icon_state = "legionlegate"
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/shoes/wraps/ashwalker
icon = 'modular_skyrat/modules/ashwalkers/icons/shoes.dmi'
@@ -18,7 +18,7 @@
name = "ash coated foot wraps"
desc = "May hurt for less than normal legs."
icon_state = "rag"
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/shoes/wraps/ashwalker/tribalwraps
icon = 'modular_skyrat/modules/ashwalkers/icons/shoes.dmi'
@@ -27,7 +27,7 @@
name = "ornate leg wraps"
desc = "An ornate set of leg wraps commonly worn by a shaman or chieftain."
icon_state = "tribalcuffs"
- mutant_variants = STYLE_DIGITIGRADE
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION
/obj/item/clothing/shoes/wraps/ashwalker/mundanewraps
icon = 'modular_skyrat/modules/ashwalkers/icons/shoes.dmi'
@@ -36,5 +36,5 @@
name = "tribal leg wraps"
desc = "A mundane set of leg wraps often worn by tribal villagers."
icon_state = "mundanecuffs"
- mutant_variants = STYLE_DIGITIGRADE
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION
diff --git a/modular_skyrat/modules/ashwalkers/code/clothing/under.dm b/modular_skyrat/modules/ashwalkers/code/clothing/under.dm
index 93833819707..2f1f5b6e223 100644
--- a/modular_skyrat/modules/ashwalkers/code/clothing/under.dm
+++ b/modular_skyrat/modules/ashwalkers/code/clothing/under.dm
@@ -60,7 +60,7 @@
name = "ash walker tunic"
desc = "A tattered red tunic of reddened fabric."
icon_state = "caesar_clothes"
- mutant_variants = STYLE_DIGITIGRADE
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION
/obj/item/clothing/under/costume/gladiator/ash_walker/legskirt_d
icon = 'modular_skyrat/master_files/icons/obj/clothing/uniforms.dmi'
diff --git a/modular_skyrat/modules/brigoff/code/brigoff_clothes.dm b/modular_skyrat/modules/brigoff/code/brigoff_clothes.dm
index 7fa84a92e8f..b7b9e697997 100644
--- a/modular_skyrat/modules/brigoff/code/brigoff_clothes.dm
+++ b/modular_skyrat/modules/brigoff/code/brigoff_clothes.dm
@@ -18,10 +18,10 @@
desc = "A black combat sweater thrown over the standard issue shirt, perfect for wake up calls."
name = "corrections officer's sweater"
icon_state = "brigguardsweat"
- mutant_variants = NONE
+ supports_variations_flags = NONE
/obj/item/clothing/under/rank/security/brigguard/sweater/women
icon_state = "brigguardsweatw"
- mutant_variants = NONE
+ supports_variations_flags = NONE
diff --git a/modular_skyrat/modules/brigoff/code/jobs.dm b/modular_skyrat/modules/brigoff/code/jobs.dm
index 5e2118cc8b4..676cfbb5007 100644
--- a/modular_skyrat/modules/brigoff/code/jobs.dm
+++ b/modular_skyrat/modules/brigoff/code/jobs.dm
@@ -4,4 +4,4 @@
icon = 'modular_skyrat/master_files/icons/obj/clothing/hats.dmi'
worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi'
icon_state = "brigguard"
- mutant_variants = NONE
+ supports_variations_flags = NONE
diff --git a/modular_skyrat/modules/customization/modules/client/augment/limbs.dm b/modular_skyrat/modules/customization/modules/client/augment/limbs.dm
index 86f386ebce8..d396b89dc93 100644
--- a/modular_skyrat/modules/customization/modules/client/augment/limbs.dm
+++ b/modular_skyrat/modules/customization/modules/client/augment/limbs.dm
@@ -17,7 +17,6 @@
oldBP.rendered_bp_icon = initial(BP.icon)
oldBP.icon_state = initial(BP.icon_state)
oldBP.should_draw_greyscale = FALSE
- H.icon_render_key = "" //To force an update on the limbs
else
var/obj/item/bodypart/BP = new path(H)
var/obj/item/bodypart/oldBP = H.get_bodypart(BP.body_zone)
diff --git a/modular_skyrat/modules/customization/modules/client/preferences.dm b/modular_skyrat/modules/customization/modules/client/preferences.dm
deleted file mode 100644
index f4611de87ac..00000000000
--- a/modular_skyrat/modules/customization/modules/client/preferences.dm
+++ /dev/null
@@ -1,3570 +0,0 @@
-/*
-GLOBAL_LIST_EMPTY(preferences_datums)
-
-// i shall taint your pretty preferences file with bobcode
-GLOBAL_LIST_INIT(food, list(
- "Meat" = MEAT,
- "Vegetables" = VEGETABLES,
- "Raw" = RAW,
- "Junk Food" = JUNKFOOD,
- "Grain" = GRAIN,
- "Fruit" = FRUIT,
- "Dairy" = DAIRY,
- "Fried" = FRIED,
- "Alcohol" = ALCOHOL,
- "Sugar" = SUGAR,
- "Gross" = GROSS,
- "Toxic" = TOXIC,
- "Pineapple" = PINEAPPLE,
- "Breakfast" = BREAKFAST,
- "Cloth" = CLOTH
- ))
-
-/datum/preferences
- var/client/parent
- //doohickeys for savefiles
- var/path
- var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used
- var/max_save_slots = 20
-
- //non-preference stuff
- var/muted = 0
- var/last_ip
- var/last_id
-
- //game-preferences
- var/lastchangelog = "" //Saved changlog filesize to detect if there was a change
- var/ooccolor = "#c43b23"
- var/asaycolor = "#ff4500" //This won't change the color for current admins, only incoming ones.
- var/auto_dementor = TRUE //To be turned off by admins that don't want to be dementored at round start.
- /// If we spawn an ERT as an admin and choose to spawn as the briefing officer, we'll be given this outfit
- var/brief_outfit = /datum/outfit/centcom/commander
- var/enable_tips = TRUE
- var/tip_delay = 500 //tip delay in milliseconds
-
- //Antag preferences
- var/list/be_special = list() //Special role selection
- var/tmp/old_be_special = 0 //Bitflag version of be_special, used to update old savefiles and nothing more
- //If it's 0, that's good, if it's anything but 0, the owner of this prefs file's antag choices were,
- //autocorrected this round, not that you'd need to check that.
- var/be_antag = FALSE //Does this player wish to be an antag this round?
-
- var/UI_style = null
- var/buttons_locked = FALSE
- var/hotkeys = TRUE
-
- ///Runechat preference. If true, certain messages will be displayed on the map, not ust on the chat area. Boolean.
- var/chat_on_map = TRUE
- ///Limit preference on the size of the message. Requires chat_on_map to have effect.
- var/max_chat_length = CHAT_MESSAGE_MAX_LENGTH
- ///Whether non-mob messages will be displayed, such as machine vendor announcements. Requires chat_on_map to have effect. Boolean.
- var/see_chat_non_mob = TRUE
- ///Whether emotes will be displayed on runechat. Requires chat_on_map to have effect. Boolean.
- var/see_rc_emotes = TRUE
-
- // Custom Keybindings
- var/list/key_bindings = list()
-
- var/tgui_fancy = TRUE
- var/tgui_lock = FALSE
- var/windowflashing = TRUE
- var/toggles = TOGGLES_DEFAULT
- var/db_flags
- var/chat_toggles = TOGGLES_DEFAULT_CHAT
- var/skyrat_toggles = TOGGLES_DEFAULT_SKYRAT
- var/ghost_form = "ghost"
- var/ghost_orbit = GHOST_ORBIT_CIRCLE
- var/ghost_accs = GHOST_ACCS_DEFAULT_OPTION
- var/ghost_others = GHOST_OTHERS_DEFAULT_OPTION
- var/ghost_hud = 1
- var/inquisitive_ghost = 1
- var/allow_midround_antag = 1
- var/preferred_map = null
- var/pda_style = MONO
- var/pda_color = "#808000"
-
- //aphrodisiac preference
- var/aphrodisiacs_pref = 1
- var/cumfaced_pref = 0
-
- var/uses_glasses_colour = 0
-
- //character preferences
- var/slot_randomized //keeps track of round-to-round randomization of the character slot, prevents overwriting
- var/real_name //our character's name
- var/gender = MALE //gender of character (well duh)
- var/age = 30 //age of character
- var/underwear = "Nude" //underwear type
- var/underwear_color = "FFF" //underwear color
- var/undershirt = "Nude" //undershirt type
- var/undershirt_color = "FFF" //underwear color
- var/socks = "Nude" //socks type
- var/socks_color = "FFF" //underwear color
- var/backpack = DBACKPACK //backpack type
- var/jumpsuit_style = PREF_SUIT //suit/skirt
- var/hairstyle = "Bald" //Hair type
- var/hair_color = "000" //Hair color
- var/facial_hairstyle = "Shaved" //Face hair type
- var/facial_hair_color = "000" //Facial hair color
- var/skin_tone = "caucasian1" //Skin color
- var/eye_color = "000" //Eye color
- var/datum/scream_type/pref_scream = new /datum/scream_type/human() //Scream type
- var/datum/laugh_type/pref_laugh = new /datum/laugh_type/human() //Laugh type
- var/datum/species/pref_species = new /datum/species/human() //Mutant race
- //Has to include all information that extra organs from mutant bodyparts would need. (so far only genitals now)
- var/list/features = MANDATORY_FEATURE_LIST
- var/list/randomise = list(
- RANDOM_UNDERWEAR = TRUE,
- RANDOM_UNDERWEAR_COLOR = TRUE,
- RANDOM_UNDERSHIRT = TRUE,
- RANDOM_SOCKS = TRUE,
- RANDOM_BACKPACK = TRUE,
- RANDOM_JUMPSUIT_STYLE = TRUE,
- RANDOM_HAIRSTYLE = TRUE,
- RANDOM_HAIR_COLOR = TRUE,
- RANDOM_FACIAL_HAIRSTYLE = TRUE,
- RANDOM_FACIAL_HAIR_COLOR = TRUE,
- RANDOM_SKIN_TONE = TRUE,
- RANDOM_EYE_COLOR = TRUE,
- )
- var/phobia = "spiders"
- var/list/foodlikes = list()
- var/list/fooddislikes = list()
- var/maxlikes = 4
- var/maxdislikes = 6
- var/pda_ringer = "beep" //text the PDA emits when messaged
-
- var/list/custom_names = list()
- var/preferred_ai_core_display = "Blue"
- var/prefered_security_department = SEC_DEPT_NONE
-
- //Quirk list
- var/list/all_quirks = list()
-
- //Job preferences 2.0 - indexed by job title , no key or value implies never
- var/list/job_preferences = list()
-
- // Alternate Job Titles
- var/list/alt_titles_preferences = list()
- // Want randomjob if preferences already filled - Donkie
- var/joblessrole = BERANDOMJOB //defaults to 1 for fewer assistants
-
- // 0 = character settings, 1 = game preferences
- var/current_tab = 0
-
- var/unlock_content = 0
-
- var/list/ignoring = list()
-
- var/clientfps = 40
-
- var/parallax
-
- ///Do we show screentips, if so, how big?
- var/screentip_pref = TRUE
- ///Color of screentips at top of screen
- var/screentip_color = "#ffd391"
- ///Do we show item hover outlines?
- var/itemoutline_pref = TRUE
-
- var/ambientocclusion = TRUE
- ///Should we automatically fit the viewport?
- var/auto_fit_viewport = FALSE
- ///Should we be in the widescreen mode set by the config?
- var/widescreenpref = TRUE
- ///What size should pixels be displayed as? 0 is strech to fit
- var/pixel_size = 0
- ///What scaling method should we use? Distort means nearest neighbor
- var/scaling_method = SCALING_METHOD_DISTORT
- var/uplink_spawn_loc = UPLINK_PDA
- ///The playtime_reward_cloak variable can be set to TRUE from the prefs menu only once the user has gained over 5K playtime hours. If true, it allows the user to get a cool looking roundstart cloak.
- var/playtime_reward_cloak = FALSE
-
- var/list/exp = list()
- var/list/menuoptions
-
- var/action_buttons_screen_locs = list()
-
- ///Someone thought we were nice! We get a little heart in OOC until we join the server past the below time (we can keep it until the end of the round otherwise)
- var/hearted
- ///If we have a hearted commendations, we honor it every time the player loads preferences until this time has been passed
- var/hearted_until
- /// Agendered spessmen can choose whether to have a male or female bodytype
- var/body_type
- /// If we have persistent scars enabled
- var/persistent_scars = TRUE
- ///If we want to broadcast deadchat connect/disconnect messages
- var/broadcast_login_logout = TRUE
- ///What outfit typepaths we've favorited in the SelectEquipment menu
- var/list/favorite_outfits = list()
- ///If TRUE, we replace the flash effect from flashes with a solid black screen
- var/darkened_flash = FALSE
- /// Will the person see accessories not meant for their species to choose from
- var/mismatched_customization = FALSE
- var/allow_advanced_colors = FALSE
- var/list/list/mutant_bodyparts = list()
- var/list/list/body_markings = list()
-
- var/character_settings_tab = 0
-
- ///How many loadout points we've got remaining
- var/loadout_points = LOADOUT_POINTS_MAX
- ///Loadout items, this is an associative list stored as [name] = "info". Info can be either colors or styles for the loadout items
- var/loadout = list()
-
- var/loadout_category = ""
- var/loadout_subcategory = ""
-
- var/preview_pref = PREVIEW_PREF_JOB
-
- var/ooc_prefs = ""
- var/erp_pref = "Ask"
- var/noncon_pref = "Ask"
- var/vore_pref = "Ask"
- var/sextoys_pref = "No"
-
- //BACKGROUND STUFF
- var/general_record = ""
- var/security_record = ""
- var/medical_record = ""
-
- var/background_info = ""
- var/exploitable_info = ""
- ///Whether the system should have to update the sprite. This is set to TRUE whenever anything appearance changing is set
- var/needs_update = TRUE
- ///List of chosen augmentations. It's an associative list with key name of the slot, pointing to a typepath of an augment define
- var/augments = list()
- ///List of chosen preferred styles for limb replacements
- var/augment_limb_styles = list()
- ///Which augment slot we currently have chosen, this is for UI display
- var/chosen_augment_slot
- ///Whether the user wants to see body size being shown in the preview
- var/show_body_size = FALSE
- ///The arousal state of the previewed character, can be toggled by the user
- var/arousal_preview = AROUSAL_NONE
- ///The current volume setting for announcements
- var/announcement_volume = 60
-
- /// Chosen cultural informations
- var/pref_culture = /datum/cultural_info/culture/generic
- var/pref_location = /datum/cultural_info/location/generic
- var/pref_faction = /datum/cultural_info/faction/none
- /// Whether someone wishes to see more information regarding either of those
- var/culture_more_info = FALSE
- var/location_more_info = FALSE
- var/faction_more_info = FALSE
- //Associative list, keyed by language typepath, pointing to LANGUAGE_UNDERSTOOD, or LANGUAGE_SPOKEN, for whether we understand or speak the language
- var/list/languages = list()
-
-/datum/preferences/New(client/C)
- parent = C
-
- for(var/custom_name_id in GLOB.preferences_custom_names)
- custom_names[custom_name_id] = get_default_name(custom_name_id)
-
- UI_style = GLOB.available_ui_styles[1]
- if(istype(C))
- if(!IsGuestKey(C.key))
- load_path(C.ckey)
- unlock_content = GLOB.donator_list[C.ckey] || C.IsByondMember()
- if(unlock_content)
- max_save_slots = 30
- var/loaded_preferences_successfully = load_preferences()
- if(loaded_preferences_successfully)
- if(load_character())
- return
- //we couldn't load character data so just randomize the character appearance + name
- set_new_species(/datum/species/human)
- randomise_appearance_prefs() //let's create a random character then - rather than a fat, bald and naked man.
- key_bindings = deepCopyList(GLOB.hotkey_keybinding_list_by_key) // give them default keybinds and update their movement keys
- C?.set_macros()
- real_name = pref_species.random_name(gender,1)
- if(!loaded_preferences_successfully)
- save_preferences()
- save_character() //let's save this new random character so it doesn't keep generating new ones.
- menuoptions = list()
- return
-
-#define APPEARANCE_CATEGORY_COLUMN "[capitalize(parse_zone(limb.body_zone))]: "
dmgreport += "[(limb.brute_dam > 0) ? "[CEILING(limb.brute_dam,1)]" : "0"] "
dmgreport += "[(limb.burn_dam > 0) ? "[CEILING(limb.burn_dam,1)]" : "0"]
| " - dat += "Preview:" - dat += "[PREVIEW_PREF_JOB]" - dat += "[PREVIEW_PREF_LOADOUT]" - dat += "[PREVIEW_PREF_NAKED]" - dat += " | " - switch(character_settings_tab) - if(4) //Loadout - dat += "" - dat += "Remaining loadout points: [loadout_points]" - dat += " | " - dat += "" - dat += "Reset Loadout" - dat += " | " - if(5) //Augments - dat += "" - if(!(!SSquirks || !SSquirks.quirks.len)) - dat += "Remaining quirk points: [GetQuirkBalance()]" - dat += " | " - else - dat += "" - dat += "Mismatched parts: [(mismatched_customization) ? "Enabled" : "Disabled"]" - dat += " | " - - dat += ""
- dat += " Color customization: [(allow_advanced_colors) ? "Enabled" : "Disabled"]"
- if(allow_advanced_colors)
- dat += "Reset colors " - dat += " | "
-
- dat += "
| "
- if(is_banned_from(user.ckey, "Appearance"))
- dat += "You are banned from using custom names and appearances. You can continue to adjust your characters, but you will be randomised once you join the game. " - dat += "Random Name " - //dat += "Always Random Name: [(randomise[RANDOM_NAME]) ? "Yes" : "No"]" - //dat += "When Antagonist: [(randomise[RANDOM_NAME_ANTAG]) ? "Yes" : "No"]" - /*if(user.client.get_exp_living(TRUE) >= PLAYTIME_HARDCORE_RANDOM) - dat += "Hardcore Random: [(randomise[RANDOM_HARDCORE]) ? "Yes" : "No"]"*/ - dat += " Name: " - dat += "[real_name] " - - if(!(AGENDER in pref_species.species_traits)) - var/dispGender - if(gender == MALE) - dispGender = "Male" - else if(gender == FEMALE) - dispGender = "Female" - else - dispGender = "Other" - dat += "Gender: [dispGender]" - if(gender == PLURAL || gender == NEUTER) - dat += " Body Type: [body_type == MALE ? "Male" : "Female"]" - - /*if(randomise[RANDOM_BODY] || randomise[RANDOM_BODY_ANTAG]) //doesn't work unless random body - dat += "Always Random Gender: [(randomise[RANDOM_GENDER]) ? "Yes" : "No"]" - dat += "When Antagonist: [(randomise[RANDOM_GENDER_ANTAG]) ? "Yes" : "No"]"*/ - - dat += " Age: [age]" - /*if(randomise[RANDOM_BODY] || randomise[RANDOM_BODY_ANTAG]) //doesn't work unless random body - dat += "Always Random Age: [(randomise[RANDOM_AGE]) ? "Yes" : "No"]" - dat += "When Antagonist: [(randomise[RANDOM_AGE_ANTAG]) ? "Yes" : "No"]"*/ - - dat += " Special Names: " - var/old_group - for(var/custom_name_id in GLOB.preferences_custom_names) - var/namedata = GLOB.preferences_custom_names[custom_name_id] - if(!old_group) - old_group = namedata["group"] - else if(old_group != namedata["group"]) - old_group = namedata["group"] - dat += " " - dat += "[namedata["pref_name"]]: [custom_names[custom_name_id]] " - dat += " " - - dat += "Custom Job Preferences: " - dat += "Preferred AI Core Display: [preferred_ai_core_display] " - dat += "Preferred Security Department: [prefered_security_department] " - - dat += " " - dat += "PDA Color: Change " - dat += "PDA Style: [pda_style] " - dat += "PDA Ringer: [pda_ringer] | "
-
- dat += "
| "
- dat += "Species: [pref_species.name] " - dat += "Scream: [pref_scream.name] " - dat += "Laugh: [pref_laugh.name] " - dat += "Species Naming: [(features["custom_species"]) ? features["custom_species"] : "Default"] " - dat += "Sprite body size: [(features["body_size"] * 100)]% [show_body_size ? "Hide preview" : "Show preview"] " - dat += " Flavor Text" - // Carbon flavor text - dat += "Set Examine Text" - if(length(features["flavor_text"]) <= 40) - if(!length(features["flavor_text"])) - dat += "\[...\]" - else - dat += "[html_encode(features["flavor_text"])]" - else - dat += "[copytext(html_encode(features["flavor_text"]), 1, 40)]..." - - dat += " " - - // Silicon flavor text - dat += "Set Silicon Examine Text " - if(length(features["silicon_flavor_text"]) <= 40) - if(!length(features["silicon_flavor_text"])) - dat += "\[...\]" - else - dat += "[html_encode(features["silicon_flavor_text"])]" - else - dat += "[copytext(html_encode(features["silicon_flavor_text"]), 1, 40)]..." - - dat += " OOC Preferences" - dat += "ERP:[erp_pref] " - dat += "Non-Con:[noncon_pref] " - dat += "Vore:[vore_pref]" - dat += "Sex toys usage:[sextoys_pref] " - dat += "Set OOC prefs " - if(length(ooc_prefs) <= 40) - if(!length(ooc_prefs)) - dat += "\[...\]" - else - dat += "[html_encode(ooc_prefs)]" - else - dat += "[copytext(html_encode(ooc_prefs), 1, 40)]..." - dat += " " - - //dat += "Random Species " - //dat += "Always Random Species: [(randomise[RANDOM_SPECIES]) ? "Yes" : "No"] " - - var/use_skintones = pref_species.use_skintones - if(use_skintones) - - dat += APPEARANCE_CATEGORY_COLUMN - - dat += " Skin Tone" - - dat += "[skin_tone]" - //dat += "[(randomise[RANDOM_SKIN_TONE]) ? "Lock" : "Unlock"]" - dat += "" - - - if(!use_skintones) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += " Primary Color" - dat += "" - - dat += " Secondary Color" - dat += "" - - dat += " Tertiary Color" - dat += "" - - if(istype(pref_species, /datum/species/ethereal)) //not the best thing to do tbf but I dont know whats better. - - if(!use_skintones) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += " Ethereal Color" - - dat += "" - - if(istype(pref_species, /datum/species/ghoul)) //ghouls - if(!use_skintones) - dat += APPEARANCE_CATEGORY_COLUMN - dat += " Ghoul Color" - dat += " Change" - - - if((EYECOLOR in pref_species.species_traits) && !(NOEYESPRITES in pref_species.species_traits)) - - /*if(!use_skintones) - dat += APPEARANCE_CATEGORY_COLUMN*/ - - dat += " Eye Color" - dat += "" - //dat += "[(randomise[RANDOM_EYE_COLOR]) ? "Lock" : "Unlock"]" - - dat += " | "
- else if(use_skintones)
- dat += ""
-
- if(HAIR in pref_species.species_traits)
-
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "
| "
-
- dat += " Underwear: [underwear]" - //dat += "[(randomise[RANDOM_UNDERWEAR]) ? "Lock" : "Unlock"]" - - dat += "" - //dat += "[(randomise[RANDOM_UNDERWEAR_COLOR]) ? "Lock" : "Unlock"]" - - dat += " Undershirt: [undershirt]" - //dat += "[(randomise[RANDOM_UNDERSHIRT]) ? "Lock" : "Unlock"]" - dat += "" - - dat += " Socks: [socks]" - //dat += "[(randomise[RANDOM_SOCKS]) ? "Lock" : "Unlock"]" - dat += "" - - dat += " Jumpsuit Style: [jumpsuit_style]" - //dat += "[(randomise[RANDOM_JUMPSUIT_STYLE]) ? "Lock" : "Unlock"]" - - dat += " Backpack: [backpack]" - //dat += "[(randomise[RANDOM_BACKPACK]) ? "Lock" : "Unlock"]" - - if((HAS_FLESH in pref_species.species_traits) || (HAS_BONE in pref_species.species_traits)) - dat += " Temporal Scarring: [(persistent_scars) ? "Enabled" : "Disabled"]" - dat += "Clear scar slots" - - dat += " Uplink Spawn Location: [uplink_spawn_loc] | "
- if (user.client.get_exp_living(TRUE) >= PLAYTIME_VETERAN)
- dat += "
"
- var/iterated_markings = 0
- for(var/zone in GLOB.marking_zones)
- var/named_zone = " "
- switch(zone)
- if(BODY_ZONE_R_ARM)
- named_zone = "Right Arm"
- if(BODY_ZONE_L_ARM)
- named_zone = "Left Arm"
- if(BODY_ZONE_HEAD)
- named_zone = "Head"
- if(BODY_ZONE_CHEST)
- named_zone = "Chest"
- if(BODY_ZONE_R_LEG)
- named_zone = "Right Leg"
- if(BODY_ZONE_L_LEG)
- named_zone = "Left Leg"
- if(BODY_ZONE_PRECISE_R_HAND)
- named_zone = "Right Hand"
- if(BODY_ZONE_PRECISE_L_HAND)
- named_zone = "Left Hand"
- dat += "[named_zone]
| " - iterated_markings = 0 - - dat += " |
| " - dat += " | " - dat += " | " - dat += " |
| [prefix]: [cult.name][cult.get_extra_desc(more)] | " - dat += "[cult_desc] | " - dat += "[more ? "Show Less" : "Show More"] | " - dat += "
"
- dat += "Languages[initial(lang_datum.name)] - [languages[language_path] == LANGUAGE_SPOKEN ? "Spoken" : "Understood" ]" - dat += " Change Languages..." - dat += " | "
- dat += ""
- dat += "RecordsGeneral" - dat += "Set general record" - if(length(general_record) <= 40) - if(!length(general_record)) - dat += "\[...\]" - else - dat += "[html_encode(general_record)]" - else - dat += "[copytext(html_encode(general_record), 1, 40)]..." - dat += " " - - - dat += " Medical" - dat += "Set medical record" - if(length(medical_record) <= 40) - if(!length(medical_record)) - dat += "\[...\]" - else - dat += "[html_encode(medical_record)]" - else - dat += "[copytext(html_encode(medical_record), 1, 40)]..." - dat += " " - - - dat += " Security" - dat += "Set security record" - if(length(security_record) <= 40) - if(!length(security_record)) - dat += "\[...\]" - else - dat += "[html_encode(security_record)]" - else - dat += "[copytext(html_encode(security_record), 1, 40)]..." - dat += " " - dat += " | "
-
-
- dat += ""
- dat += "InformationBackground" - dat += "Set background information" - if(length(background_info) <= 40) - if(!length(background_info)) - dat += "\[...\]" - else - dat += "[html_encode(background_info)]" - else - dat += "[copytext(html_encode(background_info), 1, 40)]..." - dat += " Exploitable" - dat += "Set exploitable information" - if(length(exploitable_info) <= 40) - if(!length(exploitable_info)) - dat += "\[...\]" - else - dat += "[html_encode(exploitable_info)]" - else - dat += "[copytext(html_encode(exploitable_info), 1, 40)]..." - dat += " | "
- dat += "" - //Empty column for future stuff here - dat += " | " - dat += "
| Name | " - dat += "" - dat += " | Description | " - dat += "Restrictions | " - dat += "|
| [LI.name] | " - dat += "[customization_button] | " - dat += "[LI.description] | " - dat += "[LI.restricted_desc] | " - dat += "
"
- dat += "[category_name]:" - var/list/slot_list = GLOB.augment_categories_to_slots[category_name] - for(var/slot_name in slot_list) - var/link = "href='?_src_=prefs;task=augment_slot;slot=[slot_name]'" - var/datum/augment_item/chosen_item - if(augments[slot_name]) - chosen_item = GLOB.augment_items[augments[slot_name]] - if(chosen_augment_slot && chosen_augment_slot == slot_name) - link = "class='linkOn'" - var/print_name = "" - if(chosen_item) - print_name = chosen_item.name - var/font_color = "#AAAAFF" - if(chosen_item.cost != 0) - font_color = chosen_item.cost > 0 ? "#AAFFAA" : "#FFAAAA" - print_name = "[print_name]" - dat += "
| "
- dat += ""
- if(chosen_augment_slot)
- var/list/augment_list = GLOB.augment_slot_to_items[chosen_augment_slot]
- if(augment_list)
- dat += "
|
"
- dat += "General Settings" - dat += "UI Style: [UI_style]" - dat += "tgui Window Mode: [(tgui_fancy) ? "Fancy (default)" : "Compatible (slower)"] " - dat += "tgui Window Placement: [(tgui_lock) ? "Primary monitor" : "Free (default)"] " - dat += "Show Runechat Chat Bubbles: [chat_on_map ? "Enabled" : "Disabled"] " - dat += "Runechat message char limit: [max_chat_length] " - dat += "See Runechat for non-mobs: [see_chat_non_mob ? "Enabled" : "Disabled"] " - dat += "See Runechat emotes: [see_rc_emotes ? "Enabled" : "Disabled"] " - dat += " " - dat += "Action Buttons: [(buttons_locked) ? "Locked In Place" : "Unlocked"] " - dat += "Hotkey mode: [(hotkeys) ? "Hotkeys" : "Default"] " - dat += " " - dat += "PDA Color: Change " - dat += "PDA Style: [pda_style] " - dat += " " - dat += "Ghost Ears: [(chat_toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"] " - dat += "Ghost Radio: [(chat_toggles & CHAT_GHOSTRADIO) ? "All Messages":"No Messages"] " - dat += "Ghost Sight: [(chat_toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"] " - dat += "Ghost Whispers: [(chat_toggles & CHAT_GHOSTWHISPER) ? "All Speech" : "Nearest Creatures"] " - dat += "Ghost PDA: [(chat_toggles & CHAT_GHOSTPDA) ? "All Messages" : "Nearest Creatures"] " - dat += "Ghost Law Changes: [(chat_toggles & CHAT_GHOSTLAWS) ? "All Law Changes" : "No Law Changes"] " - - if(unlock_content) - dat += "Ghost Form: [ghost_form] " - dat += "Ghost Orbit: [ghost_orbit] " - - var/button_name = "If you see this something went wrong." - switch(ghost_accs) - if(GHOST_ACCS_FULL) - button_name = GHOST_ACCS_FULL_NAME - if(GHOST_ACCS_DIR) - button_name = GHOST_ACCS_DIR_NAME - if(GHOST_ACCS_NONE) - button_name = GHOST_ACCS_NONE_NAME - - dat += "Ghost Accessories: [button_name] " - - switch(ghost_others) - if(GHOST_OTHERS_THEIR_SETTING) - button_name = GHOST_OTHERS_THEIR_SETTING_NAME - if(GHOST_OTHERS_DEFAULT_SPRITE) - button_name = GHOST_OTHERS_DEFAULT_SPRITE_NAME - if(GHOST_OTHERS_SIMPLE) - button_name = GHOST_OTHERS_SIMPLE_NAME - - dat += "Ghosts of Others: [button_name] " - dat += " " - - dat += "Broadcast Login/Logout: [broadcast_login_logout ? "Broadcast" : "Silent"] " - dat += "See Login/Logout Messages: [(chat_toggles & CHAT_LOGIN_LOGOUT) ? "Allowed" : "Muted"] " - dat += " " - - dat += "Income Updates: [(chat_toggles & CHAT_BANKCARD) ? "Allowed" : "Muted"] " - dat += " " - - dat += "FPS: [clientfps] " - - dat += "Parallax (Fancy Space): " - switch (parallax) - if (PARALLAX_LOW) - dat += "Low" - if (PARALLAX_MED) - dat += "Medium" - if (PARALLAX_INSANE) - dat += "Insane" - if (PARALLAX_DISABLE) - dat += "Disabled" - else - dat += "High" - dat += " " - - dat += "Set screentip mode: [screentip_pref ? "Enabled" : "Disabled"] " - dat += "Screentip color: Change " - dat += "Item Hover Outlines: [itemoutline_pref ? "Enabled" : "Disabled"] " - - - dat += "Ambient Occlusion: [ambientocclusion ? "Enabled" : "Disabled"] " - dat += "Fit Viewport: [auto_fit_viewport ? "Auto" : "Manual"] " - if (CONFIG_GET(string/default_view) != CONFIG_GET(string/default_view_square)) - dat += "Widescreen: [widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled ([CONFIG_GET(string/default_view_square)])"] " - - button_name = pixel_size - dat += "Pixel Scaling: [(button_name) ? "Pixel Perfect [button_name]x" : "Stretch to fit"] " - - switch(scaling_method) - if(SCALING_METHOD_DISTORT) - button_name = "Nearest Neighbor" - if(SCALING_METHOD_NORMAL) - button_name = "Point Sampling" - if(SCALING_METHOD_BLUR) - button_name = "Bilinear" - dat += "Scaling Method: [button_name] " - - if (CONFIG_GET(flag/maprotation)) - var/p_map = preferred_map - if (!p_map) - p_map = "Default" - if (config.defaultmap) - p_map += " ([config.defaultmap.map_name])" - else - if (p_map in config.maplist) - var/datum/map_config/VM = config.maplist[p_map] - if (!VM) - p_map += " (No longer exists)" - else - p_map = VM.map_name - else - p_map += " (No longer exists)" - if(CONFIG_GET(flag/preference_map_voting)) - dat += "Preferred Map: [p_map] " - - dat += " | "
-
- dat += "Special Role Settings" - - if(is_banned_from(user.ckey, ROLE_SYNDICATE)) - dat += "You are banned from antagonist roles." - src.be_special = list() - - - for (var/special_role in GLOB.special_roles) - if(is_banned_from(user.ckey, special_role)) - dat += "Be [capitalize(special_role)]: BANNED " - else - var/days_remaining = null - if(CONFIG_GET(flag/use_age_restriction_for_jobs)) //If it's a game mode antag, check if the player meets the minimum age - var/days_needed = GLOB.special_roles[special_role] - days_remaining = user.client?.get_remaining_days(days_needed) - if(days_remaining) - dat += "Be [capitalize(special_role)]: \[IN [days_remaining] DAYS] " - else - dat += "Be [capitalize(special_role)]: [(special_role in be_special) ? "Enabled" : "Disabled"] " - dat += " " - dat += "Midround Antagonist: [(toggles & MIDROUND_ANTAG) ? "Enabled" : "Disabled"] " - dat += " |
"
- dat += "OOC Settings" - dat += "Window Flashing: [(windowflashing) ? "Enabled":"Disabled"]" - dat += " " - dat += "Play Admin MIDIs: [(toggles & SOUND_MIDI) ? "Enabled":"Disabled"] " - dat += "Play Lobby Music: [(toggles & SOUND_LOBBY) ? "Enabled":"Disabled"] " - dat += "Play End of Round Sounds: [(toggles & SOUND_ENDOFROUND) ? "Enabled":"Disabled"] " - dat += "Play Combat Mode Sounds: [(toggles & SOUND_COMBATMODE) ? "Enabled":"Disabled"] " - dat += "Announcement Sound Volume: [announcement_volume] " - dat += "See Pull Requests: [(chat_toggles & CHAT_PULLR) ? "Enabled":"Disabled"] " - dat += "Darkened Flashes: (replaces flashes with a black screen) [darkened_flash ? "Enabled":"Disabled"] " - dat += " " - - //aphrodisiac pref - dat += "Be Affected by Aphrodisiacs: [(skyrat_toggles & APHRO_PREF) ? "Enabled":"Disabled"] " - //cumface pref - dat += "Be Able To Get Covered In \"Reproductive Reagent\": [(skyrat_toggles & CUMFACE_PREF) ? "Enabled":"Disabled"] " - dat += " " - - //erp update prefs here - dat += "Bimbofication: [(skyrat_toggles & BIMBO_PREF) ? "Enabled":"Disabled"] " - dat += "Breast enlargement chemicals: [(skyrat_toggles & BREAST_ENLARGEMENT) ? "Enabled":"Disabled"] " - dat += "Penis enlargement chemicals: [(skyrat_toggles & PENIS_ENLARGEMENT) ? "Enabled":"Disabled"] " - dat += "Forced masculinity: [(skyrat_toggles & FORCED_MALE) ? "Enabled":"Disabled"] " - dat += "Forced femininity: [(skyrat_toggles & FORCED_FEM) ? "Enabled":"Disabled"] " - dat += " " - - if(user.client) - if(unlock_content) - dat += "BYOND Membership Publicity: [(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"] " - - if(unlock_content || check_rights_for(user.client, R_ADMIN)) - dat += "OOC Color: Change " - if(hearted_until) - dat += "Clear OOC Commend Heart " - - dat += " | "
-
- if(user.client.holder)
- dat +=""
-
- dat += "Admin Settings" - - dat += "Adminhelp Sounds: [(toggles & SOUND_ADMINHELP)?"Enabled":"Disabled"]" - dat += "Prayer Sounds: [(toggles & SOUND_PRAYERS)?"Enabled":"Disabled"] " - dat += "Announce Login: [(toggles & ANNOUNCE_LOGIN)?"Enabled":"Disabled"] " - dat += " " - dat += "Combo HUD Lighting: [(toggles & COMBOHUD_LIGHTING)?"Full-bright":"No Change"] " - dat += " " - dat += "Hide Dead Chat: [(chat_toggles & CHAT_DEAD)?"Shown":"Hidden"] " - dat += "Hide Radio Messages: [(chat_toggles & CHAT_RADIO)?"Shown":"Hidden"] " - dat += "Hide Prayers: [(chat_toggles & CHAT_PRAYER)?"Shown":"Hidden"] " - dat += "Split Admin Tabs: [(toggles & SPLIT_ADMIN_TABS)?"Enabled":"Disabled"] " - dat += "Ignore Being Summoned as Cult Ghost: [(toggles & ADMIN_IGNORE_CULT_GHOST)?"Don't Allow Being Summoned":"Allow Being Summoned"] " - dat += "Briefing Officer Outfit: [brief_outfit] " - if(CONFIG_GET(flag/allow_admin_asaycolor)) - dat += " " - dat += "ASAY Color: Change " - - //deadmin - dat += " Deadmin While Playing" - var/timegate = CONFIG_GET(number/auto_deadmin_timegate) - if(timegate) - dat += "Noted roles will automatically deadmin during the first [FLOOR(timegate / 600, 1)] minutes of the round, and will defer to individual preferences after." - - if(CONFIG_GET(flag/auto_deadmin_players) && !timegate) - dat += "Always Deadmin: FORCED " - else - dat += "Always Deadmin: [timegate ? "(Time Locked) " : ""][(toggles & DEADMIN_ALWAYS)?"Enabled":"Disabled"] " - if(!(toggles & DEADMIN_ALWAYS)) - dat += " " - if(!CONFIG_GET(flag/auto_deadmin_antagonists) || (CONFIG_GET(flag/auto_deadmin_antagonists) && !timegate)) - dat += "As Antag: [timegate ? "(Time Locked) " : ""][(toggles & DEADMIN_ANTAGONIST)?"Deadmin":"Keep Admin"] " - else - dat += "As Antag: FORCED " - - if(!CONFIG_GET(flag/auto_deadmin_heads) || (CONFIG_GET(flag/auto_deadmin_heads) && !timegate)) - dat += "As Command: [timegate ? "(Time Locked) " : ""][(toggles & DEADMIN_POSITION_HEAD)?"Deadmin":"Keep Admin"] " - else - dat += "As Command: FORCED " - - if(!CONFIG_GET(flag/auto_deadmin_security) || (CONFIG_GET(flag/auto_deadmin_security) && !timegate)) - dat += "As Security: [timegate ? "(Time Locked) " : ""][(toggles & DEADMIN_POSITION_SECURITY)?"Deadmin":"Keep Admin"] " - else - dat += "As Security: FORCED " - - if(!CONFIG_GET(flag/auto_deadmin_silicons) || (CONFIG_GET(flag/auto_deadmin_silicons) && !timegate)) - dat += "As Silicon: [timegate ? "(Time Locked) " : ""][(toggles & DEADMIN_POSITION_SILICON)?"Deadmin":"Keep Admin"] " - else - dat += "As Silicon: FORCED " - - dat += " | "
- dat += "
" // Table within a table for alignment, also allows you to easily add more colomns.
- HTML += "
|
|
| " - dat += " | " - dat += " | " - dat += " | ||
| [initial(S.name)] | " - dat += "[initial(S.flavor_text)] | " - dat += "Choose | " - dat += "
| " - dat += " | " - dat += " | " - dat += " | ||
| [initial(S.name)] | " - dat += "[initial(S.flavor_text)] | " - dat += "Choose | " - dat += "
| " - dat += " | " - dat += " | " - dat += " | " - dat += " | " - dat += " |
| [initial(lang_datum.name)] | " - dat += "[initial(lang_datum.desc)] | " - dat += "[unlearn_button] | " - dat += "[understood_button] | " - dat += "[spoken_button] | " - dat += "