diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm
index b3f3eef2d94..d98a8abe039 100644
--- a/code/datums/traits/negative.dm
+++ b/code/datums/traits/negative.dm
@@ -408,6 +408,8 @@
medical_record_text = "Patient suffers from prosopagnosia and cannot recognize faces."
hardcore_value = 5
+//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION
+/*
/datum/quirk/prosthetic_limb
name = "Prosthetic Limb"
desc = "An accident caused you to lose one of your limbs. Because of this, you now have a random prosthetic!"
@@ -441,6 +443,8 @@
/datum/quirk/prosthetic_limb/post_add()
to_chat(quirk_holder, "Your [slot_string] has been replaced with a surplus prosthetic. It is fragile and will easily come apart under duress. Additionally, \
you need to use a welding tool and cables to repair it, instead of bruise packs and ointment.")
+*/
+//SKYRAT EDIT REMOVAL END
/datum/quirk/pushover
name = "Pushover"
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 f925a4c9ae7..1f8b9f4042d 100644
--- a/code/modules/mob/living/carbon/human/human_update_icons.dm
+++ b/code/modules/mob/living/carbon/human/human_update_icons.dm
@@ -591,14 +591,22 @@ generate/load female uniform sprites matching all previously decided variables
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
. += "-[BP.body_zone]"
+ //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(src, TRAIT_HUSK))
. += "-husk"
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 335c13e0dd4..ed651686e68 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -95,6 +95,7 @@
/// If something is currently grasping this bodypart and trying to staunch bleeding (see [/obj/item/self_grasp])
var/obj/item/self_grasp/grasped_by
var/rendered_bp_icon //SKYRAT EDIT ADDITION - CUSTOMIZATION
+ var/organic_render = TRUE //SKYRAT EDIT ADDITION - CUSTOMIZATION
/obj/item/bodypart/Initialize(mapload)
@@ -736,8 +737,10 @@
if(change_icon_to_default)
if(status == BODYPART_ORGANIC)
icon = DEFAULT_BODYPART_ICON_ORGANIC
+ organic_render = TRUE //SKYRAT EDIT ADDITION - CUSTOMIZATION
else if(status == BODYPART_ROBOTIC)
icon = DEFAULT_BODYPART_ICON_ROBOTIC
+ organic_render = FALSE //SKYRAT EDIT ADDITION - CUSTOMIZATION
if(owner)
owner.updatehealth()
@@ -777,8 +780,9 @@
should_draw_greyscale = FALSE
var/datum/species/S = H.dna.species
- species_id = S.limbs_id
- rendered_bp_icon = S.limbs_icon
+ if(organic_render) //SKYRAT EDIT ADDITION - CUSTOMIZATION
+ species_id = S.limbs_id
+ rendered_bp_icon = S.limbs_icon //SKYRAT EDIT ADDITION - CUSTOMIZATION
species_flags_list = H.dna.species.species_traits
if(S.use_skintones)
diff --git a/modular_skyrat/modules/customization/__DEFINES/augment.dm b/modular_skyrat/modules/customization/__DEFINES/augment.dm
new file mode 100644
index 00000000000..b17a66a1cdb
--- /dev/null
+++ b/modular_skyrat/modules/customization/__DEFINES/augment.dm
@@ -0,0 +1,27 @@
+#define AUGMENT_CATEGORY_NONE "ERROR"
+#define AUGMENT_SLOT_NONE "ERROR"
+//ALL OF THOSE DEFINES NEED TO BE UNIQUE!!!
+//Limbs
+#define AUGMENT_CATEGORY_LIMBS "Limbs"
+#define AUGMENT_SLOT_HEAD "Head"
+#define AUGMENT_SLOT_CHEST "Chest"
+#define AUGMENT_SLOT_L_ARM "Left Arm"
+#define AUGMENT_SLOT_R_ARM "Right Arm"
+#define AUGMENT_SLOT_L_LEG "Left Leg"
+#define AUGMENT_SLOT_R_LEG "Right Leg"
+//Organs
+#define AUGMENT_CATEGORY_ORGANS "Organs"
+#define AUGMENT_SLOT_HEART "Heart"
+#define AUGMENT_SLOT_LUNGS "Lungs"
+#define AUGMENT_SLOT_LIVER "Liver"
+#define AUGMENT_SLOT_STOMACH "Stomach"
+#define AUGMENT_SLOT_EYES "Eyes"
+#define AUGMENT_SLOT_TONGUE "Tongue"
+//Implants - we add an "implant" suffix because the defines need to be unique
+#define AUGMENT_CATEGORY_IMPLANTS "Implants"
+#define AUGMENT_SLOT_BRAIN_IMPLANT "Brain implant"
+#define AUGMENT_SLOT_CHEST_IMPLANT "Chest implant"
+#define AUGMENT_SLOT_LEFT_ARM_IMPLANT "Left Arm implant"
+#define AUGMENT_SLOT_RIGHT_ARM_IMPLANT "Right Arm implant"
+#define AUGMENT_SLOT_EYES_IMPLANT "Eyes implant"
+#define AUGMENT_SLOT_MOUTH_IMPLANT "Mouth implant"
diff --git a/modular_skyrat/modules/customization/__DEFINES/lists.dm b/modular_skyrat/modules/customization/__DEFINES/lists.dm
index 8dcf8448b51..2973dbdfaa6 100644
--- a/modular_skyrat/modules/customization/__DEFINES/lists.dm
+++ b/modular_skyrat/modules/customization/__DEFINES/lists.dm
@@ -7,3 +7,7 @@ GLOBAL_LIST_EMPTY(body_marking_sets)
GLOBAL_LIST_EMPTY(loadout_items)
GLOBAL_LIST_EMPTY(loadout_category_to_subcategory_to_items)
+
+GLOBAL_LIST_EMPTY(augment_items)
+GLOBAL_LIST_EMPTY(augment_categories_to_slots)
+GLOBAL_LIST_EMPTY(augment_slot_to_items)
diff --git a/modular_skyrat/modules/customization/__HELPERS/global_lists.dm b/modular_skyrat/modules/customization/__HELPERS/global_lists.dm
index 48a43ddc34b..a9fbd76e809 100644
--- a/modular_skyrat/modules/customization/__HELPERS/global_lists.dm
+++ b/modular_skyrat/modules/customization/__HELPERS/global_lists.dm
@@ -3,6 +3,7 @@
make_body_marking_references()
make_body_marking_set_references()
make_loadout_references()
+ make_augment_references()
//We're loading donators here because it's the least intrusive way modularly
load_donators()
@@ -54,3 +55,18 @@
if(!GLOB.loadout_category_to_subcategory_to_items[L.category][L.subcategory])
GLOB.loadout_category_to_subcategory_to_items[L.category][L.subcategory] = list()
GLOB.loadout_category_to_subcategory_to_items[L.category][L.subcategory] += L.path
+
+/proc/make_augment_references()
+ // Here we build the global loadout lists
+ for(var/path in subtypesof(/datum/augment_item))
+ var/datum/augment_item/L = path
+ if(initial(L.path))
+ L = new path()
+ GLOB.augment_items[L.path] = L
+
+ if(!GLOB.augment_slot_to_items[L.slot])
+ GLOB.augment_slot_to_items[L.slot] = list()
+ if(!GLOB.augment_categories_to_slots[L.category])
+ GLOB.augment_categories_to_slots[L.category] = list()
+ GLOB.augment_categories_to_slots[L.category] += L.slot
+ GLOB.augment_slot_to_items[L.slot] += L.path
diff --git a/modular_skyrat/modules/customization/_globalvars/lists.dm b/modular_skyrat/modules/customization/_globalvars/lists.dm
index a2a46e32423..6a4f94df03e 100644
--- a/modular_skyrat/modules/customization/_globalvars/lists.dm
+++ b/modular_skyrat/modules/customization/_globalvars/lists.dm
@@ -54,3 +54,21 @@ GLOBAL_LIST_INIT(marking_zones, list(BODY_ZONE_HEAD,BODY_ZONE_CHEST,BODY_ZONE_L_
GLOBAL_LIST_INIT(preference_breast_sizes, list("Flatchested","A","B","C","D","E","F","G","H"))
GLOBAL_LIST_INIT(preference_balls_sizes, list("Small","Average","Big","Enormous"))
+
+GLOBAL_LIST_INIT(robotic_styles_list, list("None" = "None",
+ "Surplus" = 'icons/mob/augmentation/surplus_augments.dmi',
+ "Cyborg" = 'icons/mob/augmentation/augments.dmi',
+ "Engineering" = 'icons/mob/augmentation/augments_engineer.dmi',
+ "Mining" = 'icons/mob/augmentation/augments_mining.dmi',
+ "Security" = 'icons/mob/augmentation/augments_security.dmi',
+ "Morpheus Cyberkinetics" = 'modular_skyrat/modules/customization/icons/mob/augmentation/mcgipc.dmi',
+ "Bishop Cyberkinetics" = 'modular_skyrat/modules/customization/icons/mob/augmentation/bshipc.dmi',
+ "Bishop Cyberkinetics 2.0" = 'modular_skyrat/modules/customization/icons/mob/augmentation/bs2ipc.dmi',
+ "Hephaestus Industries" = 'modular_skyrat/modules/customization/icons/mob/augmentation/hsiipc.dmi',
+ "Hephaestus Industries 2.0" = 'modular_skyrat/modules/customization/icons/mob/augmentation/hi2ipc.dmi',
+ "Shellguard Munitions Standard Series" = 'modular_skyrat/modules/customization/icons/mob/augmentation/sgmipc.dmi',
+ "Ward-Takahashi Manufacturing" = 'modular_skyrat/modules/customization/icons/mob/augmentation/wtmipc.dmi',
+ "Xion Manufacturing Group" = 'modular_skyrat/modules/customization/icons/mob/augmentation/xmgipc.dmi',
+ "Xion Manufacturing Group 2.0" = 'modular_skyrat/modules/customization/icons/mob/augmentation/xm2ipc.dmi',
+ "Zeng-Hu Pharmaceuticals" = 'modular_skyrat/modules/customization/icons/mob/augmentation/zhpipc.dmi'
+ ))
diff --git a/modular_skyrat/modules/customization/icons/mob/augmentation/bs2ipc.dmi b/modular_skyrat/modules/customization/icons/mob/augmentation/bs2ipc.dmi
new file mode 100644
index 00000000000..3c25aa6aa30
Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/augmentation/bs2ipc.dmi differ
diff --git a/modular_skyrat/modules/customization/icons/mob/augmentation/bshipc.dmi b/modular_skyrat/modules/customization/icons/mob/augmentation/bshipc.dmi
new file mode 100644
index 00000000000..8eb7a2668fa
Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/augmentation/bshipc.dmi differ
diff --git a/modular_skyrat/modules/customization/icons/mob/augmentation/hi2ipc.dmi b/modular_skyrat/modules/customization/icons/mob/augmentation/hi2ipc.dmi
new file mode 100644
index 00000000000..067f217aee9
Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/augmentation/hi2ipc.dmi differ
diff --git a/modular_skyrat/modules/customization/icons/mob/augmentation/hsiipc.dmi b/modular_skyrat/modules/customization/icons/mob/augmentation/hsiipc.dmi
new file mode 100644
index 00000000000..a15c7b94e24
Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/augmentation/hsiipc.dmi differ
diff --git a/modular_skyrat/modules/customization/icons/mob/augmentation/mcgipc.dmi b/modular_skyrat/modules/customization/icons/mob/augmentation/mcgipc.dmi
new file mode 100644
index 00000000000..63b79807d9e
Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/augmentation/mcgipc.dmi differ
diff --git a/modular_skyrat/modules/customization/icons/mob/augmentation/sgmipc.dmi b/modular_skyrat/modules/customization/icons/mob/augmentation/sgmipc.dmi
new file mode 100644
index 00000000000..82d35d77090
Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/augmentation/sgmipc.dmi differ
diff --git a/modular_skyrat/modules/customization/icons/mob/augmentation/wtmipc.dmi b/modular_skyrat/modules/customization/icons/mob/augmentation/wtmipc.dmi
new file mode 100644
index 00000000000..eb8bf8e727a
Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/augmentation/wtmipc.dmi differ
diff --git a/modular_skyrat/modules/customization/icons/mob/augmentation/xm2ipc.dmi b/modular_skyrat/modules/customization/icons/mob/augmentation/xm2ipc.dmi
new file mode 100644
index 00000000000..3be3166a846
Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/augmentation/xm2ipc.dmi differ
diff --git a/modular_skyrat/modules/customization/icons/mob/augmentation/xmgipc.dmi b/modular_skyrat/modules/customization/icons/mob/augmentation/xmgipc.dmi
new file mode 100644
index 00000000000..20e94250dd6
Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/augmentation/xmgipc.dmi differ
diff --git a/modular_skyrat/modules/customization/icons/mob/augmentation/zhpipc.dmi b/modular_skyrat/modules/customization/icons/mob/augmentation/zhpipc.dmi
new file mode 100644
index 00000000000..327f0145fe5
Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/augmentation/zhpipc.dmi differ
diff --git a/modular_skyrat/modules/customization/modules/client/augment/_augment.dm b/modular_skyrat/modules/customization/modules/client/augment/_augment.dm
new file mode 100644
index 00000000000..6b53eb2ef27
--- /dev/null
+++ b/modular_skyrat/modules/customization/modules/client/augment/_augment.dm
@@ -0,0 +1,22 @@
+/datum/augment_item
+ var/name
+ ///Category in which the augment belongs to. check "_DEFINES/augment.dm"
+ var/category = AUGMENT_CATEGORY_NONE
+ ///Slot in which the augment belongs to, MAKE SURE THE SAME SLOT IS ONLY IN ONE CATEGORY
+ var/slot = AUGMENT_SLOT_NONE
+ ///Description of the loadout augment, automatically set by New() if null
+ var/description
+ ///Typepath to the augment being used
+ var/path
+ ///How much quirky points does it cost?
+ var/cost = 0
+ ///Which biotypes are allowed to recieve the augment
+ var/allowed_biotypes = MOB_ORGANIC
+
+/datum/augment_item/New()
+ if(!description && path)
+ var/obj/O = path
+ description = initial(O.desc)
+
+/datum/augment_item/proc/apply(mob/living/carbon/human/H, character_setup = FALSE, datum/preferences/prefs)
+ return
diff --git a/modular_skyrat/modules/customization/modules/client/augment/implants.dm b/modular_skyrat/modules/customization/modules/client/augment/implants.dm
new file mode 100644
index 00000000000..231fba9f592
--- /dev/null
+++ b/modular_skyrat/modules/customization/modules/client/augment/implants.dm
@@ -0,0 +1,37 @@
+/datum/augment_item/implant
+ category = AUGMENT_CATEGORY_IMPLANTS
+
+/datum/augment_item/implant/apply(mob/living/carbon/human/H, character_setup = FALSE, datum/preferences/prefs)
+ if(character_setup)
+ return
+ var/obj/item/organ/new_organ = new path()
+ new_organ.Insert(H,FALSE,FALSE)
+
+//BRAIN IMPLANTS
+/datum/augment_item/implant/brain
+ slot = AUGMENT_SLOT_BRAIN_IMPLANT
+
+//CHEST IMPLANTS
+/datum/augment_item/implant/chest
+ slot = AUGMENT_SLOT_CHEST_IMPLANT
+
+//LEFT ARM IMPLANTS
+/datum/augment_item/implant/l_arm
+ slot = AUGMENT_SLOT_LEFT_ARM_IMPLANT
+
+//RIGHT ARM IMPLANTS
+/datum/augment_item/implant/r_arm
+ slot = AUGMENT_SLOT_RIGHT_ARM_IMPLANT
+
+//EYES IMPLANTS
+/datum/augment_item/implant/eyes
+ slot = AUGMENT_SLOT_EYES_IMPLANT
+
+//MOUTH IMPLANTS
+/datum/augment_item/implant/mouth
+ slot = AUGMENT_SLOT_MOUTH_IMPLANT
+
+/datum/augment_item/implant/mouth/breathing_tube
+ name = "Breathing Tube"
+ cost = 2
+ path = /obj/item/organ/cyberimp/mouth/breathing_tube
diff --git a/modular_skyrat/modules/customization/modules/client/augment/limbs.dm b/modular_skyrat/modules/customization/modules/client/augment/limbs.dm
new file mode 100644
index 00000000000..cfdb8a0ffa7
--- /dev/null
+++ b/modular_skyrat/modules/customization/modules/client/augment/limbs.dm
@@ -0,0 +1,88 @@
+/datum/augment_item/limb
+ category = AUGMENT_CATEGORY_LIMBS
+ allowed_biotypes = MOB_ORGANIC|MOB_ROBOTIC
+ ///Hardcoded styles that can be chosen from and apply to limb, if it's true
+ var/uses_robotic_styles = TRUE
+
+/datum/augment_item/limb/apply(mob/living/carbon/human/H, character_setup = FALSE, datum/preferences/prefs)
+ if(character_setup)
+ //Cheaply "faking" the appearance of the prosthetic. Species code sets this back if it doesnt exist anymore
+ var/obj/item/bodypart/BP = path
+ var/obj/item/bodypart/oldBP = H.get_bodypart(initial(BP.body_zone))
+ oldBP.organic_render = FALSE
+ if(uses_robotic_styles && prefs.augment_limb_styles[slot])
+ oldBP.icon = GLOB.robotic_styles_list[prefs.augment_limb_styles[slot]]
+ else
+ oldBP.icon = initial(BP.icon)
+ 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)
+ if(uses_robotic_styles && prefs.augment_limb_styles[slot])
+ BP.icon = GLOB.robotic_styles_list[prefs.augment_limb_styles[slot]]
+ BP.organic_render = FALSE
+ BP.replace_limb(H)
+ qdel(oldBP)
+
+//HEADS
+/datum/augment_item/limb/head
+ slot = AUGMENT_SLOT_HEAD
+
+//CHESTS
+/datum/augment_item/limb/chest
+ slot = AUGMENT_SLOT_CHEST
+
+//LEFT ARMS
+/datum/augment_item/limb/l_arm
+ slot = AUGMENT_SLOT_L_ARM
+
+/datum/augment_item/limb/l_arm/prosthetic
+ name = "Prosthetic"
+ path = /obj/item/bodypart/l_arm/robot/surplus
+ cost = -1
+
+/datum/augment_item/limb/l_arm/cyborg
+ name = "Cyborg"
+ path = /obj/item/bodypart/l_arm/robot/weak
+
+//RIGHT ARMS
+/datum/augment_item/limb/r_arm
+ slot = AUGMENT_SLOT_R_ARM
+
+/datum/augment_item/limb/r_arm/prosthetic
+ name = "Prosthetic"
+ path = /obj/item/bodypart/r_arm/robot/surplus
+ cost = -1
+
+/datum/augment_item/limb/r_arm/cyborg
+ name = "Cyborg"
+ path = /obj/item/bodypart/r_arm/robot/weak
+
+//LEFT LEGS
+/datum/augment_item/limb/l_leg
+ slot = AUGMENT_SLOT_L_LEG
+
+/datum/augment_item/limb/l_leg/prosthetic
+ name = "Prosthetic"
+ path = /obj/item/bodypart/l_leg/robot/surplus
+ cost = -1
+
+/datum/augment_item/limb/l_leg/cyborg
+ name = "Cyborg"
+ path = /obj/item/bodypart/l_leg/robot/weak
+
+//RIGHT LEGS
+/datum/augment_item/limb/r_leg
+ slot = AUGMENT_SLOT_R_LEG
+
+/datum/augment_item/limb/r_leg/prosthetic
+ name = "Prosthetic"
+ path = /obj/item/bodypart/r_leg/robot/surplus
+ cost = -1
+
+/datum/augment_item/limb/r_leg/cyborg
+ name = "Cyborg"
+ path = /obj/item/bodypart/r_leg/robot/weak
diff --git a/modular_skyrat/modules/customization/modules/client/augment/organs.dm b/modular_skyrat/modules/customization/modules/client/augment/organs.dm
new file mode 100644
index 00000000000..b5a875fe5c3
--- /dev/null
+++ b/modular_skyrat/modules/customization/modules/client/augment/organs.dm
@@ -0,0 +1,69 @@
+/datum/augment_item/organ
+ category = AUGMENT_CATEGORY_ORGANS
+
+/datum/augment_item/organ/apply(mob/living/carbon/human/H, character_setup = FALSE, datum/preferences/prefs)
+ if(character_setup)
+ return
+ var/obj/item/organ/new_organ = new path()
+ new_organ.Insert(H,FALSE,FALSE)
+
+//HEARTS
+/datum/augment_item/organ/heart
+ slot = AUGMENT_SLOT_HEART
+
+/datum/augment_item/organ/heart/cybernetic
+ name = "Cybernetic heart"
+ path = /obj/item/organ/heart/cybernetic
+
+//LUNGS
+/datum/augment_item/organ/lungs
+ slot = AUGMENT_SLOT_LUNGS
+
+/datum/augment_item/organ/lungs/cybernetic
+ name = "Cybernetic lungs"
+ path = /obj/item/organ/lungs/cybernetic
+
+//LIVERS
+/datum/augment_item/organ/liver
+ slot = AUGMENT_SLOT_LIVER
+
+/datum/augment_item/organ/liver/cybernetic
+ name = "Cybernetic liver"
+ path = /obj/item/organ/liver/cybernetic
+
+//STOMACHES
+/datum/augment_item/organ/stomach
+ slot = AUGMENT_SLOT_STOMACH
+
+/datum/augment_item/organ/stomach/cybernetic
+ name = "Cybernetic stomach"
+ path = /obj/item/organ/stomach/cybernetic
+
+//EYES
+/datum/augment_item/organ/eyes
+ slot = AUGMENT_SLOT_EYES
+
+/datum/augment_item/organ/eyes/cybernetic
+ name = "Cybernetic eyes"
+ path = /obj/item/organ/eyes/robotic
+
+/datum/augment_item/organ/eyes/highlumi
+ name = "High-luminosity eyes"
+ path = /obj/item/organ/eyes/robotic/glow
+ cost = 1
+
+//TONGUES
+/datum/augment_item/organ/tongue
+ slot = AUGMENT_SLOT_TONGUE
+
+/datum/augment_item/organ/tongue/normal
+ name = "Organic tongue"
+ path = /obj/item/organ/tongue
+
+/datum/augment_item/organ/tongue/robo
+ name = "Robotic voicebox"
+ path = /obj/item/organ/tongue/robot
+
+/datum/augment_item/organ/tongue/forked
+ name = "Forked tongue"
+ path = /obj/item/organ/tongue/lizard
diff --git a/modular_skyrat/modules/customization/modules/client/preferences.dm b/modular_skyrat/modules/customization/modules/client/preferences.dm
index fe9655864d0..4a3e6a10cb8 100644
--- a/modular_skyrat/modules/customization/modules/client/preferences.dm
+++ b/modular_skyrat/modules/customization/modules/client/preferences.dm
@@ -174,6 +174,12 @@
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
@@ -259,6 +265,7 @@
dat += "Markings"
dat += "Background"
dat += "Loadout" //If you change the index of this tab, change all the logic regarding tab
+ dat += "Augmentation"
dat += ""
dat += "
"
@@ -271,23 +278,29 @@
dat += "[PREVIEW_PREF_LOADOUT]"
dat += "[PREVIEW_PREF_NAKED]"
dat += ""
- if(character_settings_tab == 4) //if loadout
- dat += ""
- dat += "Remaining loadout points: [loadout_points]"
- dat += " | "
- dat += ""
- dat += "Reset Loadout"
- dat += " | "
- else
- dat += ""
- dat += "Mismatched parts: [(mismatched_customization) ? "Enabled" : "Disabled"]"
- 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 += " Advanced colors: [(allow_advanced_colors) ? "Enabled" : "Disabled"]"
- if(allow_advanced_colors)
- dat += "Reset colors "
- dat += " | "
+ dat += ""
+ dat += " Advanced colors: [(allow_advanced_colors) ? "Enabled" : "Disabled"]"
+ if(allow_advanced_colors)
+ dat += "Reset colors "
+ dat += " | "
dat += ""
dat += ""
@@ -778,6 +791,75 @@
dat += "Thank you for staffing the server! Enjoy those cool items"
else
dat += "You can support us on our patreon to help us run the servers, and get access to cool loadout items, and more points!"
+ if(5) //Augmentations
+ if(!pref_species.can_augment)
+ dat += "Sorry, but your species doesn't support augmentations"
+ else if(!SSquirks || !SSquirks.quirks.len)
+ dat += "The quirk subsystem is still initializing! Try again in a minute."
+ else
+ dat += ""
+ for(var/category_name in GLOB.augment_categories_to_slots)
+ 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 += "| [slot_name]: [print_name] | "
+ if(category_name == AUGMENT_CATEGORY_LIMBS && chosen_item)
+ var/datum/augment_item/limb/chosen_limb = chosen_item
+ var/print_style = "None"
+ if(augment_limb_styles[slot_name])
+ print_style = augment_limb_styles[slot_name]
+ if(chosen_limb.uses_robotic_styles)
+ dat += "| Style: [print_style] | "
+ dat += "| [chosen_item ? "[chosen_item.description]" : ""] | "
+ dat += " "
+ dat += " | "
+ dat += ""
+ if(chosen_augment_slot)
+ var/list/augment_list = GLOB.augment_slot_to_items[chosen_augment_slot]
+ if(augment_list)
+ dat += ""
+ dat += "[chosen_augment_slot]"
+ dat += ""
+ dat += "| Name | "
+ dat += "Cost | "
+ dat += "Description | "
+ dat += " "
+ var/even = FALSE
+ for(var/type_thing in augment_list)
+ var/datum/augment_item/aug_datum = GLOB.augment_items[type_thing]
+ var/datum/augment_item/current
+ even = !even
+ if(augments[chosen_augment_slot])
+ current = GLOB.augment_items[augments[chosen_augment_slot]]
+ var/aug_link = "class='linkOff'"
+ var/name_print = aug_datum.name
+ if (current == aug_datum)
+ aug_link = "class='linkOn' href='?_src_=prefs;task=set_augment;type=[type_thing]'"
+ name_print = "[name_print] (Remove)"
+ else if(CanBuyAugment(aug_datum, current))
+ aug_link = "href='?_src_=prefs;task=set_augment;type=[type_thing]'"
+ dat += ""
+ dat += "| [name_print] | "
+ dat += "[aug_datum.cost] | "
+ dat += "[aug_datum.description] | "
+ dat += " "
+ dat += " "
+ dat += " |
"
if (1) // Game Preferences
dat += "| "
@@ -1310,6 +1392,9 @@
for(var/V in all_quirks)
var/datum/quirk/T = SSquirks.quirks[V]
bal -= initial(T.value)
+ for(var/key in augments)
+ var/datum/augment_item/aug = GLOB.augment_items[augments[key]]
+ bal -= aug.cost
return bal
/datum/preferences/proc/GetPositiveQuirkCount()
@@ -1410,6 +1495,31 @@
return TRUE
switch(href_list["task"])
+ if("augment_style")
+ needs_update = TRUE
+ var/slot_name = href_list["slot"]
+ var/new_style = input(user, "Choose your character's [slot_name] augmentation style:", "Character Preference") as null|anything in GLOB.robotic_styles_list
+ if(new_style)
+ if(new_style == "None")
+ if(augment_limb_styles[slot_name])
+ augment_limb_styles -= slot_name
+ else
+ augment_limb_styles[slot_name] = new_style
+ if("set_augment")
+ if(pref_species.can_augment)
+ needs_update = TRUE
+ var/typed_path = text2path(href_list["type"])
+ var/datum/augment_item/target_aug = GLOB.augment_items[typed_path]
+ var/datum/augment_item/current
+ if(augments[target_aug.slot])
+ current = GLOB.augment_items[augments[target_aug.slot]]
+ if(current == target_aug)
+ augments -= target_aug.slot
+ else if(CanBuyAugment(target_aug, current))
+ augments[target_aug.slot] = typed_path
+ if("augment_slot")
+ var/slot_name = href_list["slot"]
+ chosen_augment_slot = slot_name
if("change_loadout_customization")
needs_update = TRUE
var/path = text2path(href_list["item"])
@@ -2549,6 +2659,10 @@
/*if("tail_lizard" in pref_species.default_features)
character.dna.species.mutant_bodyparts |= "tail_lizard"*/
+ if(length(augments))
+ for(var/key in augments)
+ var/datum/augment_item/aug = GLOB.augment_items[augments[key]]
+ aug.apply(character, character_setup, src)
if(icon_updates)
character.update_body()
@@ -2631,3 +2745,16 @@
return LOADOUT_POINTS_MAX_DONATOR
else
return LOADOUT_POINTS_MAX
+
+/datum/preferences/proc/CanBuyAugment(datum/augment_item/target_aug, datum/augment_item/current_aug)
+ //Check biotypes
+ if(!(pref_species.inherent_biotypes & target_aug.allowed_biotypes))
+ return
+ var/quirk_points = GetQuirkBalance()
+ var/leverage = 0
+ if(current_aug)
+ leverage += current_aug.cost
+ if((quirk_points+leverage)>= target_aug.cost)
+ return TRUE
+ else
+ return FALSE
diff --git a/modular_skyrat/modules/customization/modules/client/preferences_savefile.dm b/modular_skyrat/modules/customization/modules/client/preferences_savefile.dm
index 60b9f535948..4a75f832ff7 100644
--- a/modular_skyrat/modules/customization/modules/client/preferences_savefile.dm
+++ b/modular_skyrat/modules/customization/modules/client/preferences_savefile.dm
@@ -435,6 +435,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
READ_FILE(S["mismatched_customization"] , mismatched_customization)
READ_FILE(S["allow_advanced_colors"] , allow_advanced_colors)
+ READ_FILE(S["augments"] , augments)
+ READ_FILE(S["augment_limb_styles"] , augment_limb_styles)
+
features = SANITIZE_LIST(features)
mutant_bodyparts = SANITIZE_LIST(mutant_bodyparts)
body_markings = SANITIZE_LIST(body_markings)
@@ -483,6 +486,18 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if(!(name in GLOB.body_markings_per_limb[zone]))
body_markings[zone] -= name
+ augments = SANITIZE_LIST(augments)
+ //validating augments
+ for(var/aug_slot in augments)
+ var/datum/augment_item/aug = GLOB.augment_items[augments[aug_slot]]
+ if(!aug)
+ augments -= aug_slot
+ augment_limb_styles = SANITIZE_LIST(augment_limb_styles)
+ //validating limb styles
+ for(var/key in augment_limb_styles)
+ if(!GLOB.robotic_styles_list[key])
+ augment_limb_styles -= key
+
validate_species_parts()
needs_update = TRUE
@@ -577,6 +592,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["mismatched_customization"] , mismatched_customization)
WRITE_FILE(S["allow_advanced_colors"] , allow_advanced_colors)
+ WRITE_FILE(S["augments"] , augments)
+ WRITE_FILE(S["augment_limb_styles"] , augment_limb_styles)
+
return TRUE
diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/preferences_setup.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/preferences_setup.dm
index 966f2bf131d..24ac5d8fa71 100644
--- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/preferences_setup.dm
+++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/preferences_setup.dm
@@ -100,6 +100,9 @@
features[key] = new_features[key]
mutant_bodyparts = pref_species.get_random_mutant_bodyparts(features)
body_markings = pref_species.get_random_body_markings(features)
+ //We reset the quirk-based stuff
+ augments = list()
+ all_quirks = list()
/datum/preferences/proc/reset_colors()
for(var/key in mutant_bodyparts)
@@ -148,15 +151,13 @@
mannequin.job = previewJob.title
previewJob.equip(mannequin, TRUE, preference_source = parent)
mannequin.underwear_visibility = NONE
- mannequin.update_body() //Unfortunately, due to a certain case we need to update this just in case
if(PREVIEW_PREF_LOADOUT)
mannequin.underwear_visibility = NONE
equip_preference_loadout(mannequin, TRUE, previewJob)
mannequin.underwear_visibility = NONE
- mannequin.update_body()
if(PREVIEW_PREF_NAKED)
mannequin.underwear_visibility = UNDERWEAR_HIDE_UNDIES | UNDERWEAR_HIDE_SHIRT | UNDERWEAR_HIDE_SOCKS
- mannequin.update_body() //Unfortunately, due to a certain case we need to update this just in case
+ mannequin.update_body() //Unfortunately, due to a certain case we need to update this just in case
COMPILE_OVERLAYS(mannequin)
parent.show_character_previews(new /mutable_appearance(mannequin))
diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/carbon_update_icons.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/carbon_update_icons.dm
index 15e751c6850..f72e289b211 100644
--- a/modular_skyrat/modules/customization/modules/mob/living/carbon/carbon_update_icons.dm
+++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/carbon_update_icons.dm
@@ -45,10 +45,8 @@
. += "-digitigrade[BP.use_digitigrade]"
if(BP.animal_origin)
. += "-[BP.animal_origin]"
- if(BP.status == BODYPART_ORGANIC)
- . += "-organic"
- else
- . += "-robotic"
+ if(BP.organic_render)
+ . += "-OR"
if(HAS_TRAIT(src, TRAIT_HUSK))
. += "-husk"
diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm
index 66f9b2bf129..3a6a25557df 100644
--- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm
+++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm
@@ -10,6 +10,8 @@
var/eyes_icon
///How are we treated regarding processing reagents, by default we process them as if we're organic
var/reagent_flags = PROCESS_ORGANIC
+ ///Whether a species can use augmentations in preferences
+ var/can_augment = TRUE
/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
var/list/standing = list()
@@ -275,11 +277,13 @@
default_features = null
mutant_bodyparts = list()
can_have_genitals = FALSE
+ can_augment = FALSE
/datum/species/ethereal
default_features = null
mutant_bodyparts = list()
can_have_genitals = FALSE
+ can_augment = FALSE
/datum/species/proc/get_random_features()
var/list/returned = MANDATORY_FEATURE_LIST
@@ -373,9 +377,15 @@
fly = new
fly.Grant(C)
+ var/robotic_limbs
if(ROBOTIC_LIMBS in species_traits)
- for(var/obj/item/bodypart/B in C.bodyparts)
+ robotic_limbs = TRUE
+ for(var/obj/item/bodypart/B in C.bodyparts)
+ if(robotic_limbs)
B.change_bodypart_status(BODYPART_ROBOTIC, FALSE, TRUE)
+ B.organic_render = TRUE
+ else if (B.status == BODYPART_ORGANIC)
+ B.organic_render = TRUE
C.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, multiplicative_slowdown=speedmod)
diff --git a/modular_skyrat/modules/customization/modules/surgery/bodyparts/_bodyparts.dm b/modular_skyrat/modules/customization/modules/surgery/bodyparts/_bodyparts.dm
index 52814c96f1d..fb85841b73a 100644
--- a/modular_skyrat/modules/customization/modules/surgery/bodyparts/_bodyparts.dm
+++ b/modular_skyrat/modules/customization/modules/surgery/bodyparts/_bodyparts.dm
@@ -33,7 +33,7 @@
if((body_zone != BODY_ZONE_HEAD && body_zone != BODY_ZONE_CHEST))
should_draw_gender = FALSE
- if(species_id)
+ if(organic_render)
if(should_draw_greyscale)
limb.icon = rendered_bp_icon || 'icons/mob/human_parts_greyscale.dmi' //Skyrat change - customization
if(should_draw_gender)
diff --git a/modular_skyrat/modules/customization/modules/surgery/bodyparts/robot_bodyparts.dm b/modular_skyrat/modules/customization/modules/surgery/bodyparts/robot_bodyparts.dm
new file mode 100644
index 00000000000..b675d156dc2
--- /dev/null
+++ b/modular_skyrat/modules/customization/modules/surgery/bodyparts/robot_bodyparts.dm
@@ -0,0 +1,15 @@
+/obj/item/bodypart/l_arm/robot/weak
+ brute_reduction = 0
+ burn_reduction = 0
+
+/obj/item/bodypart/r_arm/robot/weak
+ brute_reduction = 0
+ burn_reduction = 0
+
+/obj/item/bodypart/l_leg/robot/weak
+ brute_reduction = 0
+ burn_reduction = 0
+
+/obj/item/bodypart/r_leg/robot/weak
+ brute_reduction = 0
+ burn_reduction = 0
diff --git a/modular_skyrat/modules/customization/modules/surgery/bodyparts/robot_parts.dm b/modular_skyrat/modules/customization/modules/surgery/bodyparts/robot_parts.dm
new file mode 100644
index 00000000000..ef3b524c01b
--- /dev/null
+++ b/modular_skyrat/modules/customization/modules/surgery/bodyparts/robot_parts.dm
@@ -0,0 +1,17 @@
+/obj/item/bodypart/l_arm/robot/l_arm
+ organic_render = FALSE
+
+/obj/item/bodypart/r_arm/robot/r_arm
+ organic_render = FALSE
+
+/obj/item/bodypart/l_leg/robot/l_leg
+ organic_render = FALSE
+
+/obj/item/bodypart/r_leg/robot/r_leg
+ organic_render = FALSE
+
+/obj/item/bodypart/chest/robot/chest
+ organic_render = FALSE
+
+/obj/item/bodypart/head/robot/head
+ organic_render = FALSE
diff --git a/modular_skyrat/modules/customization/modules/surgery/robot_restore_looks.dm b/modular_skyrat/modules/customization/modules/surgery/robot_restore_looks.dm
index 6a9224ad5da..4c1d0edfe42 100644
--- a/modular_skyrat/modules/customization/modules/surgery/robot_restore_looks.dm
+++ b/modular_skyrat/modules/customization/modules/surgery/robot_restore_looks.dm
@@ -35,6 +35,7 @@
if(O.status == BODYPART_ROBOTIC)
O.rendered_bp_icon = target.dna.species.limbs_icon
O.species_id = target.dna.species.limbs_id
+ O.organic_render = TRUE
if(O.body_zone == BODY_ZONE_L_LEG || O.body_zone == BODY_ZONE_R_LEG)
if(target.dna.mutant_bodyparts["legs"] && target.dna.mutant_bodyparts["legs"][MUTANT_INDEX_NAME] == "Digitigrade Legs")
O.use_digitigrade = FULL_DIGITIGRADE
diff --git a/modular_skyrat/modules/customization/readme.md b/modular_skyrat/modules/customization/readme.md
index 4f33da6409a..5eb248a8a79 100644
--- a/modular_skyrat/modules/customization/readme.md
+++ b/modular_skyrat/modules/customization/readme.md
@@ -35,6 +35,7 @@ Re-writes how mutant bodyparts exist and how they're handled. Adds in a per limb
./code/modules/mob/living/carbon/human/human_defense.dm > /mob/living/carbon/human/emp_act()
./code/modules/mob/living/carbon/human.dm > /mob/living/carbon/human/revive() > APPENDED
./code/modules/reagents/chemistry/reagents/food_reagents.dm > datum/reagent/consumable/on_mob_life()
+ ./code/datums/traits/negative.dm > /datum/quirk/prosthetic_limb
./code/modules/mob/living/carbon/human/species.dm > /datum/species/regenerate_organs() > APPENDED
diff --git a/tgstation.dme b/tgstation.dme
index 0923fdb94a1..fa8f9cf583e 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -3280,6 +3280,7 @@
#include "modular_skyrat\modules\blueshield\code\modules\jobs\job_types\blueshield.dm"
#include "modular_skyrat\modules\blueshield\code\modules\projectiles\guns\energy\special.dm"
#include "modular_skyrat\modules\cryosleep\code\cryopod.dm"
+#include "modular_skyrat\modules\customization\__DEFINES\augment.dm"
#include "modular_skyrat\modules\customization\__DEFINES\inventory.dm"
#include "modular_skyrat\modules\customization\__DEFINES\lists.dm"
#include "modular_skyrat\modules\customization\__DEFINES\loadout.dm"
@@ -3296,6 +3297,10 @@
#include "modular_skyrat\modules\customization\modules\admin\donator_list.dm"
#include "modular_skyrat\modules\customization\modules\client\preferences.dm"
#include "modular_skyrat\modules\customization\modules\client\preferences_savefile.dm"
+#include "modular_skyrat\modules\customization\modules\client\augment\_augment.dm"
+#include "modular_skyrat\modules\customization\modules\client\augment\implants.dm"
+#include "modular_skyrat\modules\customization\modules\client\augment\limbs.dm"
+#include "modular_skyrat\modules\customization\modules\client\augment\organs.dm"
#include "modular_skyrat\modules\customization\modules\client\loadout\_loadout.dm"
#include "modular_skyrat\modules\customization\modules\client\loadout\backpack.dm"
#include "modular_skyrat\modules\customization\modules\client\loadout\glasses.dm"
@@ -3380,6 +3385,8 @@
#include "modular_skyrat\modules\customization\modules\surgery\robot_healing.dm"
#include "modular_skyrat\modules\customization\modules\surgery\robot_restore_looks.dm"
#include "modular_skyrat\modules\customization\modules\surgery\bodyparts\_bodyparts.dm"
+#include "modular_skyrat\modules\customization\modules\surgery\bodyparts\robot_bodyparts.dm"
+#include "modular_skyrat\modules\customization\modules\surgery\bodyparts\robot_parts.dm"
#include "modular_skyrat\modules\customization\modules\surgery\organs\ears.dm"
#include "modular_skyrat\modules\customization\modules\surgery\organs\genitals.dm"
#include "modular_skyrat\modules\customization\modules\surgery\organs\ipc.dm"
|