diff --git a/code/__DEFINES/~skyrat_defines/synth_defines.dm b/code/__DEFINES/~skyrat_defines/synth_defines.dm index fd290de55a8..e863af5e140 100644 --- a/code/__DEFINES/~skyrat_defines/synth_defines.dm +++ b/code/__DEFINES/~skyrat_defines/synth_defines.dm @@ -6,3 +6,6 @@ #define DEFAULT_SYNTH_PART_COLOR "#746c6a" #define DEFAULT_SYNTH_SCREEN_COLOR "#b99b3a" + +#define SYNTH_ORGAN_LIGHT_EMP_DAMAGE 20 +#define SYNTH_ORGAN_HEAVY_EMP_DAMAGE 30 diff --git a/modular_skyrat/modules/customization/modules/surgery/bodyparts/robot_parts.dm b/modular_skyrat/modules/customization/modules/surgery/bodyparts/robot_parts.dm deleted file mode 100644 index 18400c2c102..00000000000 --- a/modular_skyrat/modules/customization/modules/surgery/bodyparts/robot_parts.dm +++ /dev/null @@ -1,17 +0,0 @@ -/obj/item/bodypart/arm/left/robot/l_arm - organic_render = FALSE - -/obj/item/bodypart/arm/right/robot/r_arm - organic_render = FALSE - -/obj/item/bodypart/leg/left/robot/l_leg - organic_render = FALSE - -/obj/item/bodypart/leg/right/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/organs/synth.dm b/modular_skyrat/modules/customization/modules/surgery/organs/synth.dm deleted file mode 100644 index b1af0fcf46c..00000000000 --- a/modular_skyrat/modules/customization/modules/surgery/organs/synth.dm +++ /dev/null @@ -1,239 +0,0 @@ -#define SYNTH_EMP_BRAIN_DAMAGE_HEAVY 36 -#define SYNTH_EMP_BRAIN_DAMAGE_LIGHT 12 -#define SYNTH_EMP_BRAIN_DAMAGE_MAXIMUM 75 - -/obj/item/organ/internal/brain/synth - name = "positronic brain carcass" - slot = ORGAN_SLOT_BRAIN - zone = BODY_ZONE_CHEST - status = ORGAN_ROBOTIC - organ_flags = ORGAN_SYNTHETIC - desc = "A cube of shining metal, four inches to a side and covered in shallow grooves. It has an IPC serial number engraved on the top. It is usually slotted into the chest of synthetic crewmembers." - icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' - icon_state = "posibrain-ipc" - -/obj/item/organ/internal/brain/synth/Insert(mob/living/carbon/user, special = FALSE, drop_if_replaced = TRUE, no_id_transfer = FALSE) - ..() - if(user.stat == DEAD && ishuman(user)) - var/mob/living/carbon/human/user_human = user - if(user_human?.dna?.species && (REVIVES_BY_HEALING in user_human.dna.species.species_traits)) - if(user_human.health > 50) - user_human.revive(FALSE) - -/obj/item/organ/internal/brain/synth/emp_act(severity) - switch(severity) - if(1) - owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, SYNTH_EMP_BRAIN_DAMAGE_HEAVY, SYNTH_EMP_BRAIN_DAMAGE_MAXIMUM) - to_chat(owner, span_warning("Alert: Rampant system corruption in central processing unit.")) - if(2) - owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, SYNTH_EMP_BRAIN_DAMAGE_LIGHT, SYNTH_EMP_BRAIN_DAMAGE_MAXIMUM) - to_chat(owner, span_warning("Alert: System corruption in central processing unit.")) - -/obj/item/organ/internal/stomach/synth - name = "synth power cell" - icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' - icon_state = "stomach-ipc" - w_class = WEIGHT_CLASS_NORMAL - zone = "chest" - slot = "stomach" - desc = "A specialised cell, for synthetic use only. Has a low-power mode. Without this, synthetics are unable to stay powered." - status = ORGAN_ROBOTIC - organ_flags = ORGAN_SYNTHETIC - -/obj/item/organ/internal/stomach/synth/emp_act(severity) - . = ..() - if(!owner || . & EMP_PROTECT_SELF) - return - switch(severity) - if(1) - owner.nutrition = 50 - to_chat(owner, span_warning("Alert: Detected severe battery discharge!")) - if(2) - owner.nutrition = 250 - to_chat(owner, span_warning("Alert: Minor battery discharge!")) - -/obj/item/organ/internal/ears/synth - name = "auditory sensors" - icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' - icon_state = "ears-ipc" - desc = "A pair of microphones intended to be installed in an IPC head, that grant the ability to hear." - zone = BODY_ZONE_HEAD - slot = ORGAN_SLOT_EARS - gender = PLURAL - status = ORGAN_ROBOTIC - organ_flags = ORGAN_SYNTHETIC - -/obj/item/organ/internal/ears/synth/emp_act(severity) - . = ..() - if(!owner || . & EMP_PROTECT_SELF) - return - switch(severity) - if(1) - owner.set_jitter_if_lower(60 SECONDS) - owner.set_dizzy_if_lower(60 SECONDS) - owner.Knockdown(80) - deaf = 30 - to_chat(owner, span_warning("Your system reports a complete lack of input from your auditory sensors.")) - if(2) - owner.set_jitter_if_lower(30 SECONDS) - owner.set_dizzy_if_lower(30 SECONDS) - owner.Knockdown(40) - to_chat(owner, span_warning("Your system reports anomalous feedback from your auditory sensors.")) - -/obj/item/organ/internal/tongue/synth - name = "synthetic voicebox" - desc = "A voice synthesizer that allows synths to communicate with lifeforms. Tuned to sound less agressive than robotic voiceboxes." - status = ORGAN_ROBOTIC - icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' - icon_state = "tongue-ipc" - say_mod = "beeps" - modifies_speech = TRUE - taste_sensitivity = 25 // not as good as an organic tongue - maxHealth = 100 //RoboTongue! - organ_flags = ORGAN_SYNTHETIC - -/obj/item/organ/internal/tongue/synth/handle_speech(datum/source, list/speech_args) - speech_args[SPEECH_SPANS] |= SPAN_ROBOT - -/obj/item/organ/internal/eyes/synth - name = "optical sensors" - icon_state = "cybernetic_eyeballs" - desc = "A very basic set of optical sensors with no extra vision modes or functions." - status = ORGAN_ROBOTIC - organ_flags = ORGAN_SYNTHETIC - -/obj/item/organ/internal/eyes/synth/emp_act(severity) - . = ..() - if(!owner || . & EMP_PROTECT_SELF) - return - to_chat(owner, span_warning("Electromagnetic interference clouds your optics with static.")) - owner.flash_act(visual = 1) - if(severity == EMP_HEAVY) - owner.adjustOrganLoss(ORGAN_SLOT_EYES, 20) - -/obj/item/organ/internal/lungs/synth - name = "heat sink" - desc = "A device that transfers generated heat to a fluid medium to cool it down. Required to keep your synthetics cool-headed. It's shape resembles lungs." //Purposefully left the 'fluid medium' ambigious for interpretation of the character, whether it be air or fluid cooling - icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' - icon_state = "lungs-ipc" - safe_nitro_min = 0 - safe_nitro_max = 0 - safe_co2_min = 0 - safe_co2_max = 0 - safe_plasma_min = 0 - safe_plasma_max = 0 - safe_oxygen_min = 0 //What are you doing man, dont breathe with those! - safe_oxygen_max = 0 - status = ORGAN_ROBOTIC - organ_flags = ORGAN_SYNTHETIC - -/obj/item/organ/internal/lungs/synth/emp_act(severity) - . = ..() - if(. & EMP_PROTECT_SELF) - return - switch(severity) - if(1) - to_chat(owner, span_warning("Alert: Critical cooling system failure!")) - owner.adjust_bodytemperature(100*TEMPERATURE_DAMAGE_COEFFICIENT) - if(2) - owner.adjust_bodytemperature(30*TEMPERATURE_DAMAGE_COEFFICIENT) - -/obj/item/organ/internal/heart/synth - name = "hydraulic pump engine" - desc = "An electronic device that handles the hydraulic pumps, powering one's robotic limbs. Without this, synthetics are unable to move." - organ_flags = ORGAN_SYNTHETIC - status = ORGAN_ROBOTIC - icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' - icon_state = "heart-ipc" - -/obj/item/organ/internal/liver/synth - name = "reagent processing unit" - desc = "An electronic device that processes the beneficial chemicals for the synthetic user." - organ_flags = ORGAN_SYNTHETIC - status = ORGAN_ROBOTIC - icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' - icon_state = "liver-ipc" - filterToxins = FALSE //We dont filter them, we're immune to them - -/obj/item/organ/internal/cyberimp/arm/power_cord - name = "power cord implant" - desc = "An internal power cord. Useful if you run on elecricity. Not so much otherwise." - contents = newlist(/obj/item/apc_powercord) - zone = "l_arm" - -/obj/item/apc_powercord - name = "power cord" - desc = "An internal power cord. Useful if you run on electricity. Not so much otherwise." - icon = 'icons/obj/power.dmi' - icon_state = "wire1" - -/obj/item/apc_powercord/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(!istype(target, /obj/machinery/power/apc) || !ishuman(user) || !proximity_flag) - return ..() - user.changeNext_move(CLICK_CD_MELEE) - var/obj/machinery/power/apc/target_apc = target - var/mob/living/carbon/human/ipc = user - var/obj/item/organ/internal/stomach/synth/cell = locate(/obj/item/organ/internal/stomach/synth) in ipc.internal_organs - if(!cell) - to_chat(ipc, span_warning("You try to siphon energy from the [target_apc], but your power cell is gone! How are you still standing?")) - return - - if(target_apc.cell && target_apc.cell.charge > 0) - if(ipc.nutrition >= NUTRITION_LEVEL_WELL_FED) - to_chat(user, span_warning("You are already fully charged!")) - return - else - powerdraw_loop(target_apc, ipc) - return - - to_chat(user, span_warning("There is no charge to draw from that APC.")) - -#define SYNTH_CHARGE_MAX 150 -#define SYNTH_CHARGE_MIN 50 -#define SYNTH_CHARGE_PER_NUTRITION 10 -#define SYNTH_CHARGE_DELAY_PER_100 10 - -/obj/item/apc_powercord/proc/powerdraw_loop(obj/machinery/power/apc/target_apc, mob/living/carbon/human/user) - user.visible_message(span_notice("[user] inserts a power connector into the [target_apc]."), span_notice("You begin to draw power from the [target_apc].")) - - while(TRUE) - var/power_needed = NUTRITION_LEVEL_WELL_FED - user.nutrition // How much charge do we need in total? - // Do we even need anything? - if(power_needed <= 0) - to_chat(user, span_notice("You are fully charged.")) - break - - // Is the APC almost empty? - if(target_apc.cell.percent() < 10) - to_chat(user, span_warning("[target_apc]'s emergency power is active.")) - break - - // Calculate how much to draw this cycle - var/power_use = clamp(power_needed, SYNTH_CHARGE_MIN, SYNTH_CHARGE_MAX) - power_use = clamp(power_use, 0, target_apc.cell.charge) - // Are we able to draw anything? - if(power_use == 0) - to_chat(user, span_warning("[target_apc] lacks the power to charge you.")) - break - - // Calculate the delay. - var/power_delay = (power_use / 100) * SYNTH_CHARGE_DELAY_PER_100 - // Attempt to run a charging cycle. - if(!do_after(user, power_delay, target = target_apc)) - break - - // Use the power and increase nutrition. - target_apc.cell.use(power_use) - user.nutrition += power_use / SYNTH_CHARGE_PER_NUTRITION - do_sparks(1, FALSE, target_apc) - - user.visible_message(span_notice("[user] unplugs from the [target_apc]."), span_notice("You unplug from the [target_apc].")) - -#undef SYNTH_CHARGE_MAX -#undef SYNTH_CHARGE_MIN -#undef SYNTH_CHARGE_PER_NUTRITION -#undef SYNTH_CHARGE_DELAY_PER_100 - -#undef SYNTH_EMP_BRAIN_DAMAGE_HEAVY -#undef SYNTH_EMP_BRAIN_DAMAGE_LIGHT -#undef SYNTH_EMP_BRAIN_DAMAGE_MAXIMUM diff --git a/modular_skyrat/modules/customization/modules/surgery/robot_healing.dm b/modular_skyrat/modules/customization/modules/surgery/robot_healing.dm deleted file mode 100644 index f5aadaef767..00000000000 --- a/modular_skyrat/modules/customization/modules/surgery/robot_healing.dm +++ /dev/null @@ -1,132 +0,0 @@ -//Almost copypaste of tend wounds, with some changes -/datum/surgery/robot_healing - steps = list(/datum/surgery_step/mechanic_open, - /datum/surgery_step/pry_off_plating, - /datum/surgery_step/cut_wires, - /datum/surgery_step/robot_heal, - /datum/surgery_step/mechanic_close) - - target_mobtypes = list(/mob/living/carbon/human) - possible_locs = list(BODY_ZONE_CHEST) - replaced_by = /datum/surgery - requires_bodypart_type = BODYTYPE_ROBOTIC - surgery_flags = SURGERY_IGNORE_CLOTHES | SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB - var/healing_step_type - var/antispam = FALSE - -/datum/surgery/robot_healing/New(surgery_target, surgery_location, surgery_bodypart) - ..() - if(healing_step_type) - steps = list(/datum/surgery_step/mechanic_open, - /datum/surgery_step/pry_off_plating, - /datum/surgery_step/cut_wires, - healing_step_type, - /datum/surgery_step/mechanic_close) - -/datum/surgery_step/robot_heal - name = "repair body (welder/cable)" - implements = list(TOOL_WELDER = 100, /obj/item/stack/cable_coil = 100) - repeatable = TRUE - time = 25 - var/healsbrute = FALSE - var/healsburn = FALSE - var/brutehealing = 0 - var/burnhealing = 0 - var/missinghpbonus = 0 //heals an extra point of damager per X missing damage of type (burn damage for burn healing, brute for brute). Smaller Number = More Healing! - -/datum/surgery_step/robot_heal/tool_check(mob/user, obj/item/tool) - if(implement_type == TOOL_WELDER && !tool.tool_use_check(user, 1)) - return FALSE - return TRUE - -/datum/surgery_step/robot_heal/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - var/woundtype - if(implement_type == TOOL_WELDER) - healsbrute = TRUE - healsburn = FALSE - woundtype = "dents" - else - healsbrute = FALSE - healsburn = TRUE - woundtype = "wiring" - - if(istype(surgery,/datum/surgery/robot_healing)) - var/datum/surgery/robot_healing/the_surgery = surgery - if(!the_surgery.antispam) - display_results(user, target, span_notice("You attempt to fix some of [target]'s [woundtype]."), - span_notice("[user] attempts to fix some of [target]'s [woundtype]."), - span_notice("[user] attempts to fix some of [target]'s [woundtype].")) - -/datum/surgery_step/robot_heal/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) - if(..()) - while((healsbrute && target.getBruteLoss() && tool.tool_use_check(user,1)) || (healsburn && target.getFireLoss() && tool)) - if(!..()) - break - -/datum/surgery_step/robot_heal/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - var/umsg = "You succeed in fixing some of [target]'s damage" //no period, add initial space to "addons" - var/tmsg = "[user] fixes some of [target]'s damage" //see above - var/urhealedamt_brute = 0 - if(healsbrute) - urhealedamt_brute = brutehealing - tool.use_tool(target, user, 0, volume=50, amount=1) - var/urhealedamt_burn = 0 - if(healsburn) - var/obj/item/stack/cable_coil/cable = tool - urhealedamt_burn = burnhealing - if(!cable.amount) - return - cable.use(1) - if(missinghpbonus) - if(target.stat != DEAD) - urhealedamt_brute += round((target.getBruteLoss()/ missinghpbonus),0.1) - urhealedamt_burn += round((target.getFireLoss()/ missinghpbonus),0.1) - else //less healing bonus for the dead since they're expected to have lots of damage to begin with (to make TW into defib not TOO simple) - urhealedamt_brute += round((target.getBruteLoss()/ (missinghpbonus*5)),0.1) - urhealedamt_burn += round((target.getFireLoss()/ (missinghpbonus*5)),0.1) - if(!get_location_accessible(target, target_zone)) - urhealedamt_brute *= 0.55 - urhealedamt_burn *= 0.55 - umsg += " as best as you can while they have clothing on" - tmsg += " as best as they can while [target] has clothing on" - target.heal_bodypart_damage(urhealedamt_brute,urhealedamt_burn, 0, BODYTYPE_ROBOTIC) - display_results(user, target, span_notice("[umsg]."), - "[tmsg].", - "[tmsg].") - if(istype(surgery, /datum/surgery/robot_healing)) - var/datum/surgery/robot_healing/the_surgery = surgery - the_surgery.antispam = TRUE - return TRUE - -/datum/surgery_step/robot_heal/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, span_warning("You screwed up!"), - span_warning("[user] screws up!"), - span_notice("[user] fixes some of [target]'s damage."), TRUE) - var/urdamageamt_brute = 0 - if(healsbrute) - urdamageamt_brute = brutehealing * 0.8 - var/urdamageamt_burn = 0 - if(healsburn) - urdamageamt_burn = burnhealing * 0.8 - if(missinghpbonus) - urdamageamt_brute += round((target.getBruteLoss()/ (missinghpbonus*2)),0.1) - urdamageamt_burn += round((target.getFireLoss()/ (missinghpbonus*2)),0.1) - - target.take_bodypart_damage(urdamageamt_brute, urdamageamt_burn) - return FALSE - -/***************************TYPES***************************/ -/datum/surgery/robot_healing/basic - name = "Repair robotic limbs (basic)" - healing_step_type = /datum/surgery_step/robot_heal/basic - desc = "A surgical procedure that provides repairs and maintenance to robotic limbs. Is slightly more efficient when the patient is severely damaged." - replaced_by = null - -/***************************STEPS***************************/ - -/datum/surgery_step/robot_heal/basic - name = "repair damage" - brutehealing = 10 - burnhealing = 10 - missinghpbonus = 15 - time = 10 diff --git a/modular_skyrat/modules/synths/code/README.md b/modular_skyrat/modules/synths/code/README.md new file mode 100644 index 00000000000..21ce4e629da --- /dev/null +++ b/modular_skyrat/modules/synths/code/README.md @@ -0,0 +1,29 @@ +https://github.com/Skyrat-SS13/Skyrat-tg/pull/18193, plus many others, which I can't find easily. + +## Synths + +Module ID: SYNTHS + +### Description: + +Adds in a roundstart robotic race. Currently in a very sad state, and is being worked on by RimiNosha at the moment. + +### TG Proc/File Changes: + +- Will fill out as I discover what edits were made to acommodate these. + +### Modular Overrides: + +- Will fill out as I discover what edits were made to acommodate these. + +### Defines: + +- Will fill out as I discover what defines were made to acommodate these. + +### Included files that are not contained in this module: + +- N/A + +### Credits: +Nerevar - Initial code, I think. Correct this file if wrong. +RimiNosha - Updating the code and adding various QoL features. diff --git a/modular_skyrat/modules/synths/code/bodyparts/brain.dm b/modular_skyrat/modules/synths/code/bodyparts/brain.dm new file mode 100644 index 00000000000..bc969998150 --- /dev/null +++ b/modular_skyrat/modules/synths/code/bodyparts/brain.dm @@ -0,0 +1,69 @@ +#define SYNTH_EMP_BRAIN_DAMAGE 20 +#define SYNTH_EMP_BRAIN_DAMAGE_MAXIMUM 75 +#define SYNTH_BRAIN_WAKE_THRESHOLD 50 +#define SYNTH_BRAIN_DAMAGE_MESSAGE_INTERVAL 20 SECONDS + +/obj/item/organ/internal/brain/synth + name = "compact positronic brain" + slot = ORGAN_SLOT_BRAIN + zone = BODY_ZONE_CHEST + status = ORGAN_ROBOTIC + organ_flags = ORGAN_SYNTHETIC + desc = "A cube of shining metal, four inches to a side and covered in shallow grooves. It has an IPC serial number engraved on the top. It is usually slotted into the chest of synthetic crewmembers." + icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' + icon_state = "posibrain-ipc" + /// The last time (in ticks) a message about brain damage was sent. Don't touch. + var/last_message_time = 0 + +/obj/item/organ/internal/brain/synth/Insert(mob/living/carbon/user, special = FALSE, drop_if_replaced = TRUE, no_id_transfer = FALSE) + . = ..() + + if(user.stat != DEAD || !ishuman(user)) + return + + var/mob/living/carbon/human/user_human = user + if(user_human?.dna?.species && (REVIVES_BY_HEALING in user_human.dna.species.species_traits) && user_human.health > SYNTH_BRAIN_WAKE_THRESHOLD) + user_human.revive(FALSE) + +/obj/item/organ/internal/brain/synth/emp_act(severity) + // This value is the protection value! + . = ..() + + // If EMP protected, or light EMPed, don't emp_act. + if(. & EMP_PROTECT_SELF || severity != EMP_HEAVY) + return + + applyOrganDamage(SYNTH_EMP_BRAIN_DAMAGE, SYNTH_EMP_BRAIN_DAMAGE_MAXIMUM) + +/obj/item/organ/internal/brain/synth/applyOrganDamage(damage_amount, maximumm, required_organtype) + . = ..() + + if(owner && damage > 0 && (world.time - last_message_time) > SYNTH_BRAIN_DAMAGE_MESSAGE_INTERVAL) + last_message_time = world.time + + if(damage > BRAIN_DAMAGE_SEVERE) + to_chat(owner, span_warning("Alert: Severe corruption in central processing unit.")) + return + + if(damage > BRAIN_DAMAGE_MILD) + to_chat(owner, span_warning("Alert: Minor corruption in central processing unit.")) + +/obj/item/organ/internal/brain/synth/circuit + name = "compact AI circuit" + desc = "A compact and extremely complex circuit, perfectly dimensioned to fit in the same slot as a synthetic-compatible positronic brain. It is usually slotted into the chest of synthetic crewmembers." + icon = 'modular_skyrat/master_files/icons/obj/alt_silicon_brains.dmi' + icon_state = "circuit-occupied" + inhand_icon_state = "electronic" + lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi' + +/obj/item/organ/internal/brain/synth/mmi + name = "compact man-machine interface" + desc = "A compact man-machine interface, perfectly dimensioned to fit in the same slot as a synthetic-compatible positronic brain. Unfortunately, the brain seems to be permanently attached to the circuitry, and it seems relatively sensitive to it's environment. It is usually slotted into the chest of synthetic crewmembers." + icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' + icon_state = "mmi-ipc" + +#undef SYNTH_EMP_BRAIN_DAMAGE +#undef SYNTH_EMP_BRAIN_DAMAGE_MAXIMUM +#undef SYNTH_BRAIN_WAKE_THRESHOLD +#undef SYNTH_BRAIN_DAMAGE_MESSAGE_INTERVAL diff --git a/modular_skyrat/modules/synths/code/bodyparts/ears.dm b/modular_skyrat/modules/synths/code/bodyparts/ears.dm new file mode 100644 index 00000000000..eca525a7f5f --- /dev/null +++ b/modular_skyrat/modules/synths/code/bodyparts/ears.dm @@ -0,0 +1,40 @@ +#define SYNTH_BAD_EFFECT_DURATION 30 SECONDS +#define SYNTH_DEAF_STACKS 30 +#define SYNTH_KNOCKDOWN_POWER 40 +#define SYNTH_HEAVY_EMP_MULTIPLIER 2 + +/obj/item/organ/internal/ears/synth + name = "auditory sensors" + icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' + icon_state = "ears-ipc" + desc = "A pair of microphones intended to be installed in an IPC head, that grant the ability to hear." + zone = BODY_ZONE_HEAD + slot = ORGAN_SLOT_EARS + gender = PLURAL + status = ORGAN_ROBOTIC + organ_flags = ORGAN_SYNTHETIC + +/obj/item/organ/internal/ears/synth/emp_act(severity) + . = ..() + + if(!owner || . & EMP_PROTECT_SELF) + return + + switch(severity) + if(EMP_HEAVY) + owner.set_jitter_if_lower(SYNTH_BAD_EFFECT_DURATION * SYNTH_HEAVY_EMP_MULTIPLIER) + owner.set_dizzy_if_lower(SYNTH_BAD_EFFECT_DURATION * SYNTH_HEAVY_EMP_MULTIPLIER) + owner.Knockdown(SYNTH_KNOCKDOWN_POWER * SYNTH_HEAVY_EMP_MULTIPLIER) + adjustEarDamage(SYNTH_ORGAN_HEAVY_EMP_DAMAGE, SYNTH_DEAF_STACKS) + to_chat(owner, span_warning("Your system reports a complete lack of input from your auditory sensors.")) + + if(EMP_LIGHT) + owner.set_jitter_if_lower(SYNTH_BAD_EFFECT_DURATION) + owner.set_dizzy_if_lower(SYNTH_BAD_EFFECT_DURATION) + owner.Knockdown(SYNTH_KNOCKDOWN_POWER) + to_chat(owner, span_warning("Your system reports anomalous feedback from your auditory sensors.")) + +#undef SYNTH_BAD_EFFECT_DURATION +#undef SYNTH_DEAF_STACKS +#undef SYNTH_KNOCKDOWN_POWER +#undef SYNTH_HEAVY_EMP_MULTIPLIER diff --git a/modular_skyrat/modules/synths/code/bodyparts/eyes.dm b/modular_skyrat/modules/synths/code/bodyparts/eyes.dm new file mode 100644 index 00000000000..6d6c1691376 --- /dev/null +++ b/modular_skyrat/modules/synths/code/bodyparts/eyes.dm @@ -0,0 +1,21 @@ +/obj/item/organ/internal/eyes/synth + name = "optical sensors" + icon_state = "cybernetic_eyeballs" + desc = "A very basic set of optical sensors with no extra vision modes or functions." + status = ORGAN_ROBOTIC + organ_flags = ORGAN_SYNTHETIC + +/obj/item/organ/internal/eyes/synth/emp_act(severity) + . = ..() + + if(!owner || . & EMP_PROTECT_SELF) + return + + to_chat(owner, span_warning("Electromagnetic interference clouds your optics with static.")) + owner.flash_act(visual = TRUE) + + switch(severity) + if(EMP_LIGHT) + owner.adjustOrganLoss(ORGAN_SLOT_EYES, SYNTH_ORGAN_LIGHT_EMP_DAMAGE) + if(EMP_HEAVY) + owner.adjustOrganLoss(ORGAN_SLOT_EYES, SYNTH_ORGAN_HEAVY_EMP_DAMAGE) diff --git a/modular_skyrat/modules/synths/code/bodyparts/heart.dm b/modular_skyrat/modules/synths/code/bodyparts/heart.dm new file mode 100644 index 00000000000..50d13505a8f --- /dev/null +++ b/modular_skyrat/modules/synths/code/bodyparts/heart.dm @@ -0,0 +1,7 @@ +/obj/item/organ/internal/heart/synth + name = "hydraulic pump engine" + desc = "An electronic device that handles the hydraulic pumps, powering one's robotic limbs. Without this, synthetics are unable to move." + organ_flags = ORGAN_SYNTHETIC + status = ORGAN_ROBOTIC + icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' + icon_state = "heart-ipc" diff --git a/modular_skyrat/modules/bodyparts/code/robotic/_mutant_robotic_bodyparts.dm b/modular_skyrat/modules/synths/code/bodyparts/limbs.dm similarity index 100% rename from modular_skyrat/modules/bodyparts/code/robotic/_mutant_robotic_bodyparts.dm rename to modular_skyrat/modules/synths/code/bodyparts/limbs.dm diff --git a/modular_skyrat/modules/synths/code/bodyparts/liver.dm b/modular_skyrat/modules/synths/code/bodyparts/liver.dm new file mode 100644 index 00000000000..9353eda7d6a --- /dev/null +++ b/modular_skyrat/modules/synths/code/bodyparts/liver.dm @@ -0,0 +1,8 @@ +/obj/item/organ/internal/liver/synth + name = "reagent processing unit" + desc = "An electronic device that processes the beneficial chemicals for the synthetic user." + organ_flags = ORGAN_SYNTHETIC + status = ORGAN_ROBOTIC + icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' + icon_state = "liver-ipc" + filterToxins = FALSE //We dont filter them, we're immune to them diff --git a/modular_skyrat/modules/synths/code/bodyparts/lungs.dm b/modular_skyrat/modules/synths/code/bodyparts/lungs.dm new file mode 100644 index 00000000000..6aeaacc3870 --- /dev/null +++ b/modular_skyrat/modules/synths/code/bodyparts/lungs.dm @@ -0,0 +1,35 @@ +#define SYNTH_LIGHT_EMP_TEMPERATURE_POWER 30 +#define SYNTH_HEAVY_EMP_TEMPERATURE_POWER 100 + +/obj/item/organ/internal/lungs/synth + name = "heat sink" + desc = "A device that transfers generated heat to a fluid medium to cool it down. Required to keep your synthetics cool-headed. It's shape resembles lungs." //Purposefully left the 'fluid medium' ambigious for interpretation of the character, whether it be air or fluid cooling + icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' + icon_state = "lungs-ipc" + safe_nitro_min = 0 + safe_nitro_max = 0 + safe_co2_min = 0 + safe_co2_max = 0 + safe_plasma_min = 0 + safe_plasma_max = 0 + safe_oxygen_min = 0 //What are you doing man, dont breathe with those! + safe_oxygen_max = 0 + status = ORGAN_ROBOTIC + organ_flags = ORGAN_SYNTHETIC + +/obj/item/organ/internal/lungs/synth/emp_act(severity) + . = ..() + + if(. & EMP_PROTECT_SELF) + return + + switch(severity) + if(EMP_HEAVY) + to_chat(owner, span_warning("Alert: Critical cooling system failure!")) + owner.adjust_bodytemperature(SYNTH_HEAVY_EMP_TEMPERATURE_POWER * TEMPERATURE_DAMAGE_COEFFICIENT) + + if(EMP_LIGHT) + owner.adjust_bodytemperature(SYNTH_LIGHT_EMP_TEMPERATURE_POWER * TEMPERATURE_DAMAGE_COEFFICIENT) + +#undef SYNTH_LIGHT_EMP_TEMPERATURE_POWER +#undef SYNTH_HEAVY_EMP_TEMPERATURE_POWER diff --git a/modular_skyrat/modules/synths/code/bodyparts/power_cord.dm b/modular_skyrat/modules/synths/code/bodyparts/power_cord.dm new file mode 100644 index 00000000000..3d1d6550b21 --- /dev/null +++ b/modular_skyrat/modules/synths/code/bodyparts/power_cord.dm @@ -0,0 +1,101 @@ +#define SYNTH_CHARGE_MAX 150 +#define SYNTH_CHARGE_MIN 50 +#define SYNTH_CHARGE_PER_NUTRITION 10 +#define SYNTH_CHARGE_DELAY_PER_100 10 +#define SYNTH_DRAW_NUTRITION_BUFFER 30 +#define SYNTH_APC_MINIMUM_PERCENT 20 + +/obj/item/organ/internal/cyberimp/arm/power_cord + name = "power cord implant" + desc = "An internal power cord. Useful if you run on elecricity. Not so much otherwise." + contents = newlist(/obj/item/apc_powercord) + zone = "l_arm" + +/obj/item/apc_powercord + name = "power cord" + desc = "An internal power cord. Useful if you run on electricity. Not so much otherwise." + icon = 'icons/obj/power.dmi' + icon_state = "wire1" + +/obj/item/apc_powercord/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + if(!istype(target, /obj/machinery/power/apc) || !ishuman(user) || !proximity_flag) + return ..() + + user.changeNext_move(CLICK_CD_MELEE) + var/obj/machinery/power/apc/target_apc = target + var/mob/living/carbon/human/ipc = user + var/obj/item/organ/internal/stomach/synth/cell = ipc.internal_organs_slot[ORGAN_SLOT_STOMACH] + + if(!cell) + to_chat(ipc, span_warning("You try to siphon energy from the [target_apc], but you have no stomach! How are you still standing?")) + return + + if(!istype(cell)) + to_chat(ipc, span_warning("You plug into the APC, but nothing happens! It seems you don't have a cell to charge!")) + return + + if(target_apc.cell && target_apc.cell.percent() < SYNTH_APC_MINIMUM_PERCENT) + to_chat(user, span_warning("There is no charge to draw from that APC.")) + return + + if(ipc.nutrition >= NUTRITION_LEVEL_WELL_FED) + to_chat(user, span_warning("You are already fully charged!")) + return + + powerdraw_loop(target_apc, ipc) + +/** + * Runs a loop to charge a synth cell (stomach) via powercord from an APC. + * + * Stops when: + * - The user is full. + * - The APC has less than 20% charge. + * - The APC has machine power turned off. + * - The APC is unable to provide charge for any other reason. + * - The user moves, or anything else that can happen to interrupt a do_after. + * + * Arguments: + * * target_apc - The APC to drain. + * * user - The carbon draining the APC. + */ +/obj/item/apc_powercord/proc/powerdraw_loop(obj/machinery/power/apc/target_apc, mob/living/carbon/human/user) + user.visible_message(span_notice("[user] inserts a power connector into the [target_apc]."), span_notice("You begin to draw power from the [target_apc].")) + + while(TRUE) + var/power_needed = NUTRITION_LEVEL_WELL_FED - user.nutrition // How much charge do we need in total? + // Do we even need anything? + if(power_needed <= SYNTH_CHARGE_MIN * 2) // Times two to make sure minimum draw is always lower than this margin to prevent potential needless loops. + to_chat(user, span_notice("You are fully charged.")) + break + + // Is the APC not charging equipment? And yes, synths are gonna be treated as equipment. Deal with it. + if(target_apc.cell.percent() < SYNTH_APC_MINIMUM_PERCENT) // 20%, to prevent synths from overstepping and murdering power for department machines and potentially doors. + to_chat(user, span_warning("[target_apc]'s power is too low to charge you.")) + break + + // Calculate how much to draw this cycle + var/power_use = clamp(power_needed, SYNTH_CHARGE_MIN, SYNTH_CHARGE_MAX) + power_use = clamp(power_use, 0, target_apc.cell.charge) + // Are we able to draw anything? + if(power_use <= 0) + to_chat(user, span_warning("[target_apc] lacks the power to charge you.")) + break + + // Calculate the delay. + var/power_delay = (power_use / 100) * SYNTH_CHARGE_DELAY_PER_100 + // Attempt to run a charging cycle. + if(!do_after(user, power_delay, target = target_apc)) + break + + // Use the power and increase nutrition. + target_apc.cell.use(power_use) + + user.nutrition += power_use / SYNTH_CHARGE_PER_NUTRITION + do_sparks(1, FALSE, target_apc) + + user.visible_message(span_notice("[user] unplugs from the [target_apc]."), span_notice("You unplug from the [target_apc].")) + +#undef SYNTH_CHARGE_MAX +#undef SYNTH_CHARGE_MIN +#undef SYNTH_CHARGE_PER_NUTRITION +#undef SYNTH_CHARGE_DELAY_PER_100 diff --git a/modular_skyrat/modules/customization/modules/surgery/organs/silicon_alt_brains.dm b/modular_skyrat/modules/synths/code/bodyparts/silicon_alt_brains.dm similarity index 72% rename from modular_skyrat/modules/customization/modules/surgery/organs/silicon_alt_brains.dm rename to modular_skyrat/modules/synths/code/bodyparts/silicon_alt_brains.dm index e5d5eec8773..399b5fd3660 100644 --- a/modular_skyrat/modules/customization/modules/surgery/organs/silicon_alt_brains.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/silicon_alt_brains.dm @@ -1,3 +1,5 @@ +// Don't know of a better place to put these. They're technically related to synths, so they're going here. + /obj/item/mmi/posibrain/circuit name = "compact AI circuit" desc = "A compact circuit, perfectly dimensioned to fit in the same slot as a cyborg's positronic brain." @@ -15,24 +17,10 @@ new_mob_message = span_notice("The compact AI circuit chimes quietly.") recharge_message = span_warning("The compact AI circuit isn't ready to activate again yet! Give it some time to recharge.") -/obj/item/organ/internal/brain/synth/circuit - name = "compact AI circuit" - desc = "A compact and extremely complex circuit, perfectly dimensioned to fit in the same slot as a synthetic-compatible positronic brain. It is usually slotted into the chest of synthetic crewmembers." - icon = 'modular_skyrat/master_files/icons/obj/alt_silicon_brains.dmi' - icon_state = "circuit-occupied" - inhand_icon_state = "electronic" - lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi' - righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi' - -/obj/item/organ/internal/brain/synth/mmi - name = "compact man-machine interface" - desc = "A compact man-machine interface, perfectly dimensioned to fit in the same slot as a synthetic-compatible positronic brain. Unfortunately, the brain seems to be permanently attached to the circuitry, and it seems relatively sensitive to it's environment. It is usually slotted into the chest of synthetic crewmembers." - icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' - icon_state = "mmi-ipc" - // CODE THAT ACTUALLY APPLIES THE BRAINS. // See modular_skyrat/master_files/code/modules/client/preferences/brain.dm for Synth/IPC application. +/// Returns a type to use based off of a given preference value (ORGAN_PREF_POSI_BRAIN, ORGAN_PREF_MMI_BRAIN and ORGAN_PREF_CIRCUIT_BRAIN), and if they're a cyborg or not. /mob/living/proc/prefs_get_brain_to_use(value, is_cyborg = FALSE) switch(value) if(ORGAN_PREF_POSI_BRAIN) diff --git a/modular_skyrat/modules/synths/code/bodyparts/stomach.dm b/modular_skyrat/modules/synths/code/bodyparts/stomach.dm new file mode 100644 index 00000000000..1a2ea8c9aca --- /dev/null +++ b/modular_skyrat/modules/synths/code/bodyparts/stomach.dm @@ -0,0 +1,31 @@ +#define SYNTH_STOMACH_LIGHT_EMP_CHARGE_LOSS 50 +#define SYNTH_STOMACH_HEAVY_EMP_CHARGE_LOSS 150 + +/obj/item/organ/internal/stomach/synth + name = "synth power cell" + icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' + icon_state = "stomach-ipc" + w_class = WEIGHT_CLASS_NORMAL + zone = "chest" + slot = "stomach" + desc = "A specialised cell, for synthetic use only. Has a low-power mode. Without this, synthetics are unable to stay powered." + status = ORGAN_ROBOTIC + organ_flags = ORGAN_SYNTHETIC + +/obj/item/organ/internal/stomach/synth/emp_act(severity) + . = ..() + + if(!owner || . & EMP_PROTECT_SELF) + return + + switch(severity) + if(EMP_HEAVY) + owner.nutrition = max(0, owner.nutrition - SYNTH_STOMACH_HEAVY_EMP_CHARGE_LOSS) + to_chat(owner, span_warning("Alert: Severe battery discharge!")) + + if(EMP_LIGHT) + owner.nutrition = max(0, owner.nutrition - SYNTH_STOMACH_LIGHT_EMP_CHARGE_LOSS) + to_chat(owner, span_warning("Alert: Minor battery discharge!")) + +#undef SYNTH_STOMACH_LIGHT_EMP_CHARGE_LOSS +#undef SYNTH_STOMACH_HEAVY_EMP_CHARGE_LOSS diff --git a/modular_skyrat/modules/synths/code/bodyparts/tongue.dm b/modular_skyrat/modules/synths/code/bodyparts/tongue.dm new file mode 100644 index 00000000000..93c1f094f47 --- /dev/null +++ b/modular_skyrat/modules/synths/code/bodyparts/tongue.dm @@ -0,0 +1,14 @@ +/obj/item/organ/internal/tongue/synth + name = "synthetic voicebox" + desc = "A voice synthesizer that allows synths to communicate with lifeforms. Tuned to sound less agressive than robotic voiceboxes." + status = ORGAN_ROBOTIC + icon = 'modular_skyrat/master_files/icons/obj/surgery.dmi' + icon_state = "tongue-ipc" + say_mod = "beeps" + modifies_speech = TRUE + taste_sensitivity = 25 // not as good as an organic tongue + maxHealth = 100 //RoboTongue! + organ_flags = ORGAN_SYNTHETIC + +/obj/item/organ/internal/tongue/synth/handle_speech(datum/source, list/speech_args) + speech_args[SPEECH_SPANS] |= SPAN_ROBOT diff --git a/modular_skyrat/master_files/code/modules/reagents/blood_pack.dm b/modular_skyrat/modules/synths/code/reagents/blood_pack.dm similarity index 53% rename from modular_skyrat/master_files/code/modules/reagents/blood_pack.dm rename to modular_skyrat/modules/synths/code/reagents/blood_pack.dm index b15c267723f..7731fb6a1d4 100644 --- a/modular_skyrat/master_files/code/modules/reagents/blood_pack.dm +++ b/modular_skyrat/modules/synths/code/reagents/blood_pack.dm @@ -1,3 +1,4 @@ +// I cannot wait to get rid of this. This is so many levels of awful wrapped into one. /obj/item/reagent_containers/blood/oil blood_type = "Oil" unique_blood = /datum/reagent/fuel/oil diff --git a/modular_skyrat/master_files/code/modules/reagents/pill.dm b/modular_skyrat/modules/synths/code/reagents/pill.dm similarity index 100% rename from modular_skyrat/master_files/code/modules/reagents/pill.dm rename to modular_skyrat/modules/synths/code/reagents/pill.dm diff --git a/modular_skyrat/master_files/code/game/objects/items/storage/pill_bottles.dm b/modular_skyrat/modules/synths/code/reagents/pill_bottles.dm similarity index 100% rename from modular_skyrat/master_files/code/game/objects/items/storage/pill_bottles.dm rename to modular_skyrat/modules/synths/code/reagents/pill_bottles.dm diff --git a/modular_skyrat/modules/customization/modules/reagents/chemistry/reagents/medicine_reagents.dm b/modular_skyrat/modules/synths/code/reagents/reagents.dm similarity index 97% rename from modular_skyrat/modules/customization/modules/reagents/chemistry/reagents/medicine_reagents.dm rename to modular_skyrat/modules/synths/code/reagents/reagents.dm index 9c97f10573d..cf735140820 100644 --- a/modular_skyrat/modules/customization/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/modular_skyrat/modules/synths/code/reagents/reagents.dm @@ -1,3 +1,6 @@ +#define NANITE_SLURRY_ORGANIC_PURGE_RATE 4 +#define NANITE_SLURRY_ORGANIC_VOMIT_CHANCE 25 + /datum/reagent/medicine/syndicate_nanites //Used exclusively by Syndicate medical cyborgs process_flags = REAGENT_ORGANIC | REAGENT_SYNTHETIC //Let's not cripple synth ops @@ -10,9 +13,7 @@ /datum/reagent/medicine/leporazine process_flags = REAGENT_ORGANIC | REAGENT_SYNTHETIC -//REAGENTS FOR SYNTHS -#define NANITE_SLURRY_ORGANIC_PURGE_RATE 4 -#define NANITE_SLURRY_ORGANIC_VOMIT_CHANCE 25 +// REAGENTS FOR SYNTHS /datum/reagent/medicine/system_cleaner name = "System Cleaner" @@ -25,13 +26,13 @@ /datum/reagent/medicine/system_cleaner/on_mob_life(mob/living/carbon/affected_mob, delta_time, times_fired) affected_mob.adjustToxLoss(-2 * REM * delta_time, 0) - . = 1 var/remove_amount = 1 * REM * delta_time; for(var/thing in affected_mob.reagents.reagent_list) var/datum/reagent/reagent = thing if(reagent != src) affected_mob.reagents.remove_reagent(reagent.type, remove_amount) ..() + return TRUE /datum/reagent/medicine/liquid_solder name = "Liquid Solder" @@ -45,7 +46,7 @@ affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, -3 * REM * delta_time) if(prob(10)) affected_mob.cure_trauma_type(resilience = TRAUMA_RESILIENCE_BASIC) - ..() + return ..() /datum/reagent/medicine/nanite_slurry name = "Nanite Slurry" @@ -65,7 +66,7 @@ /datum/reagent/medicine/nanite_slurry/on_mob_life(mob/living/carbon/affected_mob, delta_time) var/heal_amount = healing * REM * delta_time affected_mob.heal_bodypart_damage(heal_amount, heal_amount, required_bodytype = BODYTYPE_ROBOTIC) - ..() + return ..() /datum/reagent/medicine/nanite_slurry/overdose_process(mob/living/carbon/affected_mob, delta_time, times_fired) if(affected_mob.mob_biotypes & MOB_ROBOTIC) @@ -74,8 +75,7 @@ affected_mob.reagents.remove_reagent(type, NANITE_SLURRY_ORGANIC_PURGE_RATE) //gets removed from organics very fast if(prob(NANITE_SLURRY_ORGANIC_VOMIT_CHANCE)) affected_mob.vomit(vomit_type = VOMIT_NANITE) - ..() - . = 1 + return TRUE #undef NANITE_SLURRY_ORGANIC_PURGE_RATE #undef NANITE_SLURRY_ORGANIC_VOMIT_CHANCE diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/robotic/prefsmenu.dm b/modular_skyrat/modules/synths/code/species/prefsmenu.dm similarity index 100% rename from modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/robotic/prefsmenu.dm rename to modular_skyrat/modules/synths/code/species/prefsmenu.dm diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/robotic/screen.dm b/modular_skyrat/modules/synths/code/species/screen.dm similarity index 100% rename from modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/robotic/screen.dm rename to modular_skyrat/modules/synths/code/species/screen.dm diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/robotic/synthetic.dm b/modular_skyrat/modules/synths/code/species/synthetic.dm similarity index 95% rename from modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/robotic/synthetic.dm rename to modular_skyrat/modules/synths/code/species/synthetic.dm index ed1f464ff7b..4b25f357cb0 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/robotic/synthetic.dm +++ b/modular_skyrat/modules/synths/code/species/synthetic.dm @@ -2,7 +2,7 @@ name = "Synthetic Humanoid" id = SPECIES_SYNTH say_mod = "beeps" - inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID + inherent_biotypes = MOB_ROBOTIC | MOB_HUMANOID inherent_traits = list( TRAIT_CAN_STRIP, TRAIT_ADVANCEDTOOLUSER, @@ -39,11 +39,6 @@ ) changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT reagent_flags = PROCESS_SYNTHETIC - burnmod = 1.3 // Every 0.1% is 10% above the base. - brutemod = 1.3 - coldmod = 1.2 - heatmod = 2 - siemens_coeff = 1.4 //Not more because some shocks will outright crit you, which is very unfun payday_modifier = 0.75 // Matches the rest of the pay penalties the non-human crew have species_language_holder = /datum/language_holder/machine mutant_organs = list(/obj/item/organ/internal/cyberimp/arm/power_cord) @@ -65,6 +60,11 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/robot/synth, ) digitigrade_customization = DIGITIGRADE_OPTIONAL + burnmod = 1.3 // Every 0.1 is 10% above the base. + brutemod = 1.3 + coldmod = 1.2 + heatmod = 2 // TWO TIMES DAMAGE FROM BEING TOO HOT?! WHAT?! No wonder lava is literal instant death for us. + siemens_coeff = 1.4 // Not more because some shocks will outright crit you, which is very unfun /// The innate action that synths get, if they've got a screen selected on species being set. var/datum/action/innate/monitor_change/screen /// This is the screen that is given to the user after they get revived. On death, their screen is temporarily set to BSOD before it turns off, hence the need for this var. diff --git a/modular_skyrat/modules/customization/modules/surgery/mechanic_steps.dm b/modular_skyrat/modules/synths/code/surgery/mechanic_steps.dm similarity index 60% rename from modular_skyrat/modules/customization/modules/surgery/mechanic_steps.dm rename to modular_skyrat/modules/synths/code/surgery/mechanic_steps.dm index f4cf579432e..8389c9e1a79 100644 --- a/modular_skyrat/modules/customization/modules/surgery/mechanic_steps.dm +++ b/modular_skyrat/modules/synths/code/surgery/mechanic_steps.dm @@ -2,16 +2,21 @@ /datum/surgery_step/cut_wires name = "cut wires" implements = list( - TOOL_WIRECUTTER = 100, - TOOL_SCALPEL = 75, + TOOL_WIRECUTTER = 100, + TOOL_SCALPEL = 75, /obj/item/knife = 50, - /obj/item = 10) // 10% success with any sharp item. - time = 24 + /obj/item = 10, + ) // 10% success with any sharp item. + time = 2.4 SECONDS /datum/surgery_step/cut_wires/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, span_notice("You begin to cut loose wires in [target]'s [parse_zone(target_zone)]..."), - "[user] begins to cut loose wires in [target]'s [parse_zone(target_zone)].", - "[user] begins to cut loose wires in [target]'s [parse_zone(target_zone)].") + display_results( + user, + target, + span_notice("You begin to cut loose wires in [target]'s [parse_zone(target_zone)]..."), + "[user] begins to cut loose wires in [target]'s [parse_zone(target_zone)].", + "[user] begins to cut loose wires in [target]'s [parse_zone(target_zone)].", + ) /datum/surgery_step/cut_wires/tool_check(mob/user, obj/item/tool) if(implement_type == /obj/item && !tool.get_sharpness()) @@ -23,24 +28,30 @@ name = "pry off plating" implements = list( TOOL_CROWBAR = 100, - TOOL_HEMOSTAT = 10) - time = 24 + TOOL_HEMOSTAT = 10, + ) + time = 2.4 SECONDS /datum/surgery_step/pry_off_plating/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) do_sparks(rand(5, 9), FALSE, target.loc) return TRUE /datum/surgery_step/pry_off_plating/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, span_notice("You begin to pry off [target]'s [parse_zone(target_zone)] plating..."), - "[user] begins to pry off [target]'s [parse_zone(target_zone)] plating.", - "[user] begins to pry off [target]'s [parse_zone(target_zone)] plating.") + display_results( + user, + target, + span_notice("You begin to pry off [target]'s [parse_zone(target_zone)] plating..."), + "[user] begins to pry off [target]'s [parse_zone(target_zone)] plating.", + "[user] begins to pry off [target]'s [parse_zone(target_zone)] plating.", + ) //weld plating /datum/surgery_step/weld_plating name = "weld plating" implements = list( - TOOL_WELDER = 100) - time = 24 + TOOL_WELDER = 100, + ) + time = 2.4 SECONDS /datum/surgery_step/weld_plating/tool_check(mob/user, obj/item/tool) if(implement_type == TOOL_WELDER && !tool.use_tool(user, user, 0, volume=50, amount=1)) @@ -48,15 +59,19 @@ return TRUE /datum/surgery_step/weld_plating/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, span_notice("You begin to weld [target]'s [parse_zone(target_zone)] plating..."), - "[user] begins to weld [target]'s [parse_zone(target_zone)] plating.", - "[user] begins to weld [target]'s [parse_zone(target_zone)] plating.") + display_results( + user, + target, + span_notice("You begin to weld [target]'s [parse_zone(target_zone)] plating..."), + "[user] begins to weld [target]'s [parse_zone(target_zone)] plating.", + "[user] begins to weld [target]'s [parse_zone(target_zone)] plating.", + ) //replace wires /datum/surgery_step/replace_wires name = "replace wires" implements = list(/obj/item/stack/cable_coil = 100) - time = 24 + time = 2.4 SECONDS var/cableamount = 5 /datum/surgery_step/replace_wires/tool_check(mob/user, obj/item/tool) @@ -68,20 +83,24 @@ /datum/surgery_step/replace_wires/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) var/obj/item/stack/cable_coil/coil = tool - if(coil && !(coil.get_amount() NONE) to_chat(user, "[target]'s posibrain still has some lasting system damage that can be cleared.") + return ..() /datum/surgery_step/fix_robot_brain/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(target.getorganslot(ORGAN_SLOT_BRAIN)) - display_results(user, target, span_warning("You screw up, fragmenting their data!"), + display_results( + user, + target, + span_warning("You screw up, fragmenting their data!"), span_warning("[user] screws up, causing damage to the circuits!"), - "[user] completes the surgery on [target]'s posibrain.") + "[user] completes the surgery on [target]'s posibrain.", + ) + target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 60) target.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_LOBOTOMY) else user.visible_message(span_warning("[user] suddenly notices that the posibrain [user.p_they()] [user.p_were()] working on is not there anymore."), span_warning("You suddenly notice that the posibrain you were working on is not there anymore.")) + return FALSE diff --git a/modular_skyrat/modules/customization/modules/surgery/robot_chassis_restoration.dm b/modular_skyrat/modules/synths/code/surgery/robot_chassis_restoration.dm similarity index 58% rename from modular_skyrat/modules/customization/modules/surgery/robot_chassis_restoration.dm rename to modular_skyrat/modules/synths/code/surgery/robot_chassis_restoration.dm index 39acc05c078..bb281a637dc 100644 --- a/modular_skyrat/modules/customization/modules/surgery/robot_chassis_restoration.dm +++ b/modular_skyrat/modules/synths/code/surgery/robot_chassis_restoration.dm @@ -1,15 +1,16 @@ /datum/surgery/positronic_restoration name = "Posibrain Reboot (Revival)" steps = list( - /datum/surgery_step/mechanic_unwrench, - /datum/surgery_step/pry_off_plating/fullbody, - /datum/surgery_step/cut_wires/fullbody, - /datum/surgery_step/replace_wires/fullbody, - /datum/surgery_step/prepare_electronics, - /datum/surgery_step/add_plating/fullbody, - /datum/surgery_step/weld_plating/fullbody, - /datum/surgery_step/finalize_positronic_restoration, - /datum/surgery_step/mechanic_close) + /datum/surgery_step/mechanic_unwrench, + /datum/surgery_step/pry_off_plating/fullbody, + /datum/surgery_step/cut_wires/fullbody, + /datum/surgery_step/replace_wires/fullbody, + /datum/surgery_step/prepare_electronics, + /datum/surgery_step/add_plating/fullbody, + /datum/surgery_step/weld_plating/fullbody, + /datum/surgery_step/finalize_positronic_restoration, + /datum/surgery_step/mechanic_close, + ) target_mobtypes = list(/mob/living/carbon/human) possible_locs = list(BODY_ZONE_CHEST) @@ -17,53 +18,67 @@ desc = "A surgical procedure that reboots a positronic brain." /datum/surgery/robot_chassis_restoration/can_start(mob/user, mob/living/carbon/target) - if(!..()) - return FALSE - if(target.stat != DEAD) - return FALSE - if(target.suiciding) - return FALSE - var/obj/item/organ/internal/brain/target_brain = target.getorganslot(ORGAN_SLOT_BRAIN) - if(!target_brain) + if(!..() || target.stat != DEAD || target.suiciding || !target.getorganslot(ORGAN_SLOT_BRAIN)) return FALSE + return TRUE /datum/surgery_step/pry_off_plating/fullbody time = 12 SECONDS /datum/surgery_step/pry_off_plating/fullbody/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, span_notice("You begin to pry open compromised panels on [target]'s braincase..."), - span_notice("[user] begins to pry open compromised panels on [target]'s braincase.")) + display_results( + user, + target, + span_notice("You begin to pry open compromised panels on [target]'s braincase..."), + span_notice("[user] begins to pry open compromised panels on [target]'s braincase."), + ) /datum/surgery_step/cut_wires/fullbody time = 12 SECONDS /datum/surgery_step/cut_wires/fullbody/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, span_notice("You begin to trim [target]'s nonfunctional wires..."), - span_notice("[user] begins to cut [target]'s loose wires.")) + display_results( + user, + target, + span_notice("You begin to trim [target]'s nonfunctional wires..."), + span_notice("[user] begins to cut [target]'s loose wires."), + ) /datum/surgery_step/weld_plating/fullbody time = 12 SECONDS /datum/surgery_step/weld_plating/fullbody/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, span_notice("You begin to slice compromised panels from [target]'s braincase..."), - span_notice("[user] begins to slice compromised panels from [target]'s braincase.")) + display_results( + user, + target, + span_notice("You begin to slice compromised panels from [target]'s braincase..."), + span_notice("[user] begins to slice compromised panels from [target]'s braincase."), + ) /datum/surgery_step/replace_wires/fullbody time = 7 SECONDS cableamount = 15 /datum/surgery_step/replace_wires/fullbody/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, span_notice("You begin to replace [target]'s wiring..."), - span_notice("[user] begins to replace [target]'s wiring.")) + display_results( + user, + target, + span_notice("You begin to replace [target]'s wiring..."), + span_notice("[user] begins to replace [target]'s wiring."), + ) /datum/surgery_step/add_plating/fullbody time = 12 SECONDS ironamount = 15 /datum/surgery_step/add_plating/fullbody/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, span_notice("You begin to add new panels to [target]'s braincase..."), - span_notice("[user] begins to add new panels to [target]'s braincase.")) + display_results( + user, + target, + span_notice("You begin to add new panels to [target]'s braincase..."), + span_notice("[user] begins to add new panels to [target]'s braincase."), + ) /datum/surgery_step/finalize_positronic_restoration name = "finalize positronic restoration (multitool)" @@ -74,15 +89,21 @@ time = 12 SECONDS /datum/surgery_step/finalize_positronic_restoration/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, span_notice("You begin to force a reboot in [target]'s posibrain..."), - span_notice("[user] begins to force a reboot in [target]'s posibrain.")) + display_results( + user, + target, + span_notice("You begin to force a reboot in [target]'s posibrain..."), + span_notice("[user] begins to force a reboot in [target]'s posibrain."), + ) + target.notify_ghost_cloning("Someone is trying to reboot your posibrain.", source = target) /datum/surgery_step/finalize_positronic_restoration/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) target.cure_husk() target.grab_ghost() target.updatehealth() - target.setOrganLoss(ORGAN_SLOT_BRAIN, target.getOrganLoss(ORGAN_SLOT_BRAIN) - 200) + target.setOrganLoss(ORGAN_SLOT_BRAIN, NONE) + if(target.revive()) target.emote("chime") target.visible_message(span_notice("...[target] reactivates, their chassis coming online!")) diff --git a/modular_skyrat/modules/synths/code/surgery/robot_healing.dm b/modular_skyrat/modules/synths/code/surgery/robot_healing.dm new file mode 100644 index 00000000000..645409a5c98 --- /dev/null +++ b/modular_skyrat/modules/synths/code/surgery/robot_healing.dm @@ -0,0 +1,176 @@ +#define DAMAGE_ROUNDING 0.1 +#define FAIL_DAMAGE_MULTIPLIER 0.8 +#define FINAL_STEP_HEAL_MULTIPLIER 0.55 + +//Almost copypaste of tend wounds, with some changes +/datum/surgery/robot_healing + steps = list( + /datum/surgery_step/mechanic_open, + /datum/surgery_step/pry_off_plating, + /datum/surgery_step/cut_wires, + /datum/surgery_step/robot_heal, + /datum/surgery_step/mechanic_close, + ) + + target_mobtypes = list(/mob/living/carbon/human) + possible_locs = list(BODY_ZONE_CHEST) + replaced_by = /datum/surgery + requires_bodypart_type = BODYTYPE_ROBOTIC + surgery_flags = SURGERY_IGNORE_CLOTHES | SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB + + /// The step to use in the 4th surgery step. + var/healing_step_type + /// If true, doesn't send the surgery preop message. Set during surgery. + var/surgery_preop_message_sent = FALSE + +/datum/surgery/robot_healing/New(surgery_target, surgery_location, surgery_bodypart) + ..() + if(healing_step_type) + steps = list( + /datum/surgery_step/mechanic_open, + /datum/surgery_step/pry_off_plating, + /datum/surgery_step/cut_wires, + healing_step_type, + /datum/surgery_step/mechanic_close, + ) + +/datum/surgery_step/robot_heal + name = "repair body (welder/cable)" + implements = list(TOOL_WELDER = 100, /obj/item/stack/cable_coil = 100) + repeatable = TRUE + time = 25 + + /// If this surgery is healing brute damage. Set during operation steps. + var/heals_brute = FALSE + /// If this surgery is healing burn damage. Set during operation steps. + var/heals_burn = FALSE + /// How much healing the sugery gives. + var/brute_heal_amount = 0 + /// How much healing the sugery gives. + var/burn_heal_amount = 0 + /// Heals an extra point of damage per X missing damage of type (burn damage for burn healing, brute for brute). Smaller number = more healing! + var/missing_health_bonus = 0 + +/datum/surgery_step/robot_heal/tool_check(mob/user, obj/item/tool) + if(implement_type == TOOL_WELDER && !tool.tool_use_check(user, 1)) + return FALSE + return TRUE + +/datum/surgery_step/robot_heal/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/woundtype + if(implement_type == TOOL_WELDER) + heals_brute = TRUE + heals_burn = FALSE + woundtype = "dents" + else + heals_brute = FALSE + heals_burn = TRUE + woundtype = "wiring" + + if(!istype(surgery, /datum/surgery/robot_healing)) + return + + var/datum/surgery/robot_healing/the_surgery = surgery + if(the_surgery.surgery_preop_message_sent) + return + + display_results( + user, + target, + span_notice("You attempt to fix some of [target]'s [woundtype]."), + span_notice("[user] attempts to fix some of [target]'s [woundtype]."), + span_notice("[user] attempts to fix some of [target]'s [woundtype]."), + ) + +/datum/surgery_step/robot_heal/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) + if(..()) + while((heals_brute && target.getBruteLoss() && tool.tool_use_check(user, 1)) || (heals_burn && target.getFireLoss() && tool)) + if(!..()) + break + +/datum/surgery_step/robot_heal/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/self_message = "You succeed in fixing some of [target]'s damage" //no period, add initial space to "addons" + var/other_message = "[user] fixes some of [target]'s damage" //see above + var/healed_brute = 0 + + if(heals_brute) + healed_brute = brute_heal_amount + tool.use_tool(target, user, 0, volume = 50, amount=1) + + var/healed_burn = 0 + if(heals_burn) + var/obj/item/stack/cable_coil/cable = tool + healed_burn = burn_heal_amount + if(!cable.amount) + return + + cable.use(1) + + if(missing_health_bonus) + if(target.stat != DEAD) + healed_brute += round((target.getBruteLoss() / missing_health_bonus), DAMAGE_ROUNDING) + healed_burn += round((target.getFireLoss() / missing_health_bonus), DAMAGE_ROUNDING) + + else //less healing bonus for the dead since they're expected to have lots of damage to begin with (to make TW into defib not TOO simple) + healed_brute += round((target.getBruteLoss() / (missing_health_bonus * 5)), DAMAGE_ROUNDING) + healed_burn += round((target.getFireLoss() / (missing_health_bonus * 5)), DAMAGE_ROUNDING) + + if(!get_location_accessible(target, target_zone)) + healed_brute *= FINAL_STEP_HEAL_MULTIPLIER + healed_burn *= FINAL_STEP_HEAL_MULTIPLIER + self_message += " as best as you can while they have clothing on" + other_message += " as best as they can while [target] has clothing on" + + target.heal_bodypart_damage(healed_brute, healed_burn, 0, BODYTYPE_ROBOTIC) + display_results(user, target, span_notice("[self_message]."), "[other_message].", "[other_message].") + + if(istype(surgery, /datum/surgery/robot_healing)) + var/datum/surgery/robot_healing/the_surgery = surgery + the_surgery.surgery_preop_message_sent = TRUE + + return TRUE + +/datum/surgery_step/robot_heal/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + display_results( + user, + target, + span_warning("You screwed up!"), + span_warning("[user] screws up!"), + span_notice("[user] fixes some of [target]'s damage."), + TRUE, + ) + + var/brute_damage = 0 + if(heals_brute) + brute_damage = brute_heal_amount * FAIL_DAMAGE_MULTIPLIER + + var/burn_damage = 0 + if(heals_burn) + burn_damage = burn_heal_amount * FAIL_DAMAGE_MULTIPLIER + + if(missing_health_bonus) + brute_damage += round((target.getBruteLoss() / (missing_health_bonus * 2)), DAMAGE_ROUNDING) + burn_damage += round((target.getFireLoss() / (missing_health_bonus * 2)), DAMAGE_ROUNDING) + + target.take_bodypart_damage(brute_damage, burn_damage) + return FALSE + +/***************************TYPES***************************/ +/datum/surgery/robot_healing/basic + name = "Repair robotic limbs (basic)" + healing_step_type = /datum/surgery_step/robot_heal/basic + desc = "A surgical procedure that provides repairs and maintenance to robotic limbs. Is slightly more efficient when the patient is severely damaged." + replaced_by = null + +/***************************STEPS***************************/ + +/datum/surgery_step/robot_heal/basic + name = "repair damage" + brute_heal_amount = 10 + burn_heal_amount = 10 + missing_health_bonus = 15 + time = 10 + +#undef DAMAGE_ROUNDING +#undef FAIL_DAMAGE_MULTIPLIER +#undef FINAL_STEP_HEAL_MULTIPLIER diff --git a/tgstation.dme b/tgstation.dme index 25a616582d3..e5a6e5aac7f 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -5129,7 +5129,6 @@ #include "modular_skyrat\master_files\code\game\objects\items\stacks\sheets\sheet_types.dm" #include "modular_skyrat\master_files\code\game\objects\items\storage\backpack.dm" #include "modular_skyrat\master_files\code\game\objects\items\storage\boxes.dm" -#include "modular_skyrat\master_files\code\game\objects\items\storage\pill_bottles.dm" #include "modular_skyrat\master_files\code\game\objects\items\tools\weldingtool.dm" #include "modular_skyrat\master_files\code\game\objects\structures\railings.dm" #include "modular_skyrat\master_files\code\game\objects\structures\sauna_oven.dm" @@ -5258,9 +5257,7 @@ #include "modular_skyrat\master_files\code\modules\projectiles\guns\gun.dm" #include "modular_skyrat\master_files\code\modules\projectiles\guns\ballistic\automatic.dm" #include "modular_skyrat\master_files\code\modules\projectiles\guns\ballistic\revolver.dm" -#include "modular_skyrat\master_files\code\modules\reagents\blood_pack.dm" #include "modular_skyrat\master_files\code\modules\reagents\bottle.dm" -#include "modular_skyrat\master_files\code\modules\reagents\pill.dm" #include "modular_skyrat\master_files\code\modules\reagents\chemistry\colors.dm" #include "modular_skyrat\master_files\code\modules\reagents\withdrawal\generic_addictions.dm" #include "modular_skyrat\master_files\code\modules\research\designs\biogenerator_designs.dm" @@ -5521,7 +5518,6 @@ #include "modular_skyrat\modules\bodyparts\code\teshari_bodyparts.dm" #include "modular_skyrat\modules\bodyparts\code\vox_bodyparts.dm" #include "modular_skyrat\modules\bodyparts\code\xenohybrid_bodyparts.dm" -#include "modular_skyrat\modules\bodyparts\code\robotic\_mutant_robotic_bodyparts.dm" #include "modular_skyrat\modules\bongs\code\bong.dm" #include "modular_skyrat\modules\borg_buffs\code\robot.dm" #include "modular_skyrat\modules\borg_buffs\code\snack_dispensor.dm" @@ -5801,33 +5797,22 @@ #include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\vox.dm" #include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\vulpkanin.dm" #include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\xeno.dm" -#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\robotic\prefsmenu.dm" -#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\robotic\screen.dm" -#include "modular_skyrat\modules\customization\modules\mob\living\carbon\human\species\robotic\synthetic.dm" #include "modular_skyrat\modules\customization\modules\mob\living\simple_mob\examine.dm" #include "modular_skyrat\modules\customization\modules\reagents\chemistry\reagents.dm" #include "modular_skyrat\modules\customization\modules\reagents\chemistry\reagents\alcohol_reagents.dm" #include "modular_skyrat\modules\customization\modules\reagents\chemistry\reagents\drink_reagents.dm" #include "modular_skyrat\modules\customization\modules\reagents\chemistry\reagents\drinks.dm" #include "modular_skyrat\modules\customization\modules\reagents\chemistry\reagents\food_reagents.dm" -#include "modular_skyrat\modules\customization\modules\reagents\chemistry\reagents\medicine_reagents.dm" #include "modular_skyrat\modules\customization\modules\reagents\chemistry\reagents\other_reagents.dm" #include "modular_skyrat\modules\customization\modules\reagents\chemistry\reagents\pyrotechnic_reagents.dm" #include "modular_skyrat\modules\customization\modules\reagents\chemistry\reagents\toxin_reagents.dm" #include "modular_skyrat\modules\customization\modules\reagents\chemistry\recipes\medicine.dm" -#include "modular_skyrat\modules\customization\modules\surgery\mechanic_steps.dm" -#include "modular_skyrat\modules\customization\modules\surgery\robot_brain_surgery.dm" -#include "modular_skyrat\modules\customization\modules\surgery\robot_chassis_restoration.dm" -#include "modular_skyrat\modules\customization\modules\surgery\robot_healing.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\eyes.dm" #include "modular_skyrat\modules\customization\modules\surgery\organs\genitals.dm" #include "modular_skyrat\modules\customization\modules\surgery\organs\organ.dm" -#include "modular_skyrat\modules\customization\modules\surgery\organs\silicon_alt_brains.dm" -#include "modular_skyrat\modules\customization\modules\surgery\organs\synth.dm" #include "modular_skyrat\modules\customization\modules\surgery\organs\tails.dm" #include "modular_skyrat\modules\customization\modules\surgery\organs\vox.dm" #include "modular_skyrat\modules\customization\modules\surgery\organs\wings.dm" @@ -6499,6 +6484,28 @@ #include "modular_skyrat\modules\supermatter_surge\code\supermatter_surge.dm" #include "modular_skyrat\modules\Syndie_edits\code\area.dm" #include "modular_skyrat\modules\Syndie_edits\code\syndie_edits.dm" +#include "modular_skyrat\modules\synths\code\bodyparts\brain.dm" +#include "modular_skyrat\modules\synths\code\bodyparts\ears.dm" +#include "modular_skyrat\modules\synths\code\bodyparts\eyes.dm" +#include "modular_skyrat\modules\synths\code\bodyparts\heart.dm" +#include "modular_skyrat\modules\synths\code\bodyparts\limbs.dm" +#include "modular_skyrat\modules\synths\code\bodyparts\liver.dm" +#include "modular_skyrat\modules\synths\code\bodyparts\lungs.dm" +#include "modular_skyrat\modules\synths\code\bodyparts\power_cord.dm" +#include "modular_skyrat\modules\synths\code\bodyparts\silicon_alt_brains.dm" +#include "modular_skyrat\modules\synths\code\bodyparts\stomach.dm" +#include "modular_skyrat\modules\synths\code\bodyparts\tongue.dm" +#include "modular_skyrat\modules\synths\code\reagents\blood_pack.dm" +#include "modular_skyrat\modules\synths\code\reagents\pill.dm" +#include "modular_skyrat\modules\synths\code\reagents\pill_bottles.dm" +#include "modular_skyrat\modules\synths\code\reagents\reagents.dm" +#include "modular_skyrat\modules\synths\code\species\prefsmenu.dm" +#include "modular_skyrat\modules\synths\code\species\screen.dm" +#include "modular_skyrat\modules\synths\code\species\synthetic.dm" +#include "modular_skyrat\modules\synths\code\surgery\mechanic_steps.dm" +#include "modular_skyrat\modules\synths\code\surgery\robot_brain_surgery.dm" +#include "modular_skyrat\modules\synths\code\surgery\robot_chassis_restoration.dm" +#include "modular_skyrat\modules\synths\code\surgery\robot_healing.dm" #include "modular_skyrat\modules\tableflip\code\flipped_table.dm" #include "modular_skyrat\modules\tagline\code\world.dm" #include "modular_skyrat\modules\teshari\code\_clothing_defines.dm"