[MODULAR] Moves Synth Code to it's Own Module, Code Quality Pass, Minor EMP Nerf (#18193)

* Fucking synth code

* Fucking surgery code

* Fucking organs

* Fucking organs pt. 2

* Me being dumb part 1, cause I forgot I was testing stuff with this

* Stupid readmes.

* Stupid APC code

* Me being stupid part 2: Electric Boogaloo

* Fucking changes

* Fucking synth code

* FUCK

* Fucking commas

* UNDEFINE, NERD

* Fucking defines

* Don't forget reagents.

* Blood overlay restore, and revert a change I made without realizing the indirect consequences.

* HOW
This commit is contained in:
Rimi Nosha
2023-01-23 11:08:02 -05:00
committed by GitHub
parent e7c46adbc0
commit 7d3988213c
28 changed files with 707 additions and 507 deletions
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
@@ -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
@@ -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
@@ -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)
@@ -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"
@@ -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
@@ -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
@@ -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
@@ -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)
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
@@ -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()<cableamount)) //failproof
if(coil && !(coil.get_amount() < cableamount)) //failproof
coil.use(cableamount)
return TRUE
/datum/surgery_step/replace_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 replace [target]'s [parse_zone(target_zone)] wiring..."),
"[user] begins to replace [target]'s [parse_zone(target_zone)] wiring.",
"[user] begins to replace [target]'s [parse_zone(target_zone)] wiring.")
display_results(
user,
target,
span_notice("You begin to replace [target]'s [parse_zone(target_zone)] wiring..."),
"[user] begins to replace [target]'s [parse_zone(target_zone)] wiring.",
"[user] begins to replace [target]'s [parse_zone(target_zone)] wiring.",
)
//add plating
/datum/surgery_step/add_plating
name = "add plating"
implements = list(/obj/item/stack/sheet/iron = 100)
time = 24
time = 2.4 SECONDS
var/ironamount = 5
/datum/surgery_step/add_plating/tool_check(mob/user, obj/item/tool)
@@ -93,11 +112,13 @@
/datum/surgery_step/add_plating/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/obj/item/stack/sheet/iron/plat = tool
if(plat && !(plat.get_amount()<ironamount)) //failproof
plat.use(ironamount)
return TRUE
return plat?.use(ironamount)
/datum/surgery_step/add_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 add plating to [target]'s [parse_zone(target_zone)]..."),
"[user] begins to add plating to [target]'s [parse_zone(target_zone)].",
"[user] begins to add plating to [target]'s [parse_zone(target_zone)].")
display_results(
user,
target,
span_notice("You begin to add plating to [target]'s [parse_zone(target_zone)]..."),
"[user] begins to add plating to [target]'s [parse_zone(target_zone)].",
"[user] begins to add plating to [target]'s [parse_zone(target_zone)].",
)
@@ -1,12 +1,13 @@
/datum/surgery/robot_brain_surgery
name = "Reset Posibrain Logic (Brain Surgery)"
steps = list(
/datum/surgery_step/mechanic_open,
/datum/surgery_step/mechanic_unwrench,
/datum/surgery_step/pry_off_plating,
/datum/surgery_step/prepare_electronics,
/datum/surgery_step/fix_robot_brain,
/datum/surgery_step/mechanic_close)
/datum/surgery_step/mechanic_open,
/datum/surgery_step/mechanic_unwrench,
/datum/surgery_step/pry_off_plating,
/datum/surgery_step/prepare_electronics,
/datum/surgery_step/fix_robot_brain,
/datum/surgery_step/mechanic_close,
)
target_mobtypes = list(/mob/living/carbon/human)
possible_locs = list(BODY_ZONE_HEAD)
@@ -24,35 +25,50 @@
time = 12 SECONDS //long and complicated
/datum/surgery/robot_brain_surgery/can_start(mob/user, mob/living/carbon/target, obj/item/tool)
var/obj/item/organ/internal/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN)
if(!B)
return FALSE
return TRUE
var/obj/item/organ/internal/brain/brain = target.getorganslot(ORGAN_SLOT_BRAIN)
return !!brain
/datum/surgery_step/fix_robot_brain/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, span_notice("You begin to clear system corruption from [target]'s posibrain..."),
display_results(
user,
target,
span_notice("You begin to clear system corruption from [target]'s posibrain..."),
"[user] begins to fix [target]'s posibrain.",
"[user] begins to perform surgery on [target]'s posibrain.")
"[user] begins to perform surgery on [target]'s posibrain.",
)
/datum/surgery_step/fix_robot_brain/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, span_notice("You succeed in clearing system corruption from [target]'s posibrain."),
display_results(user,
target,
span_notice("You succeed in clearing system corruption from [target]'s posibrain."),
"[user] successfully fixes [target]'s posibrain!",
"[user] completes the surgery on [target]'s posibrain.")
"[user] completes the surgery on [target]'s posibrain.",
)
if(target.mind && target.mind.has_antag_datum(/datum/antagonist/brainwashed))
target.mind.remove_antag_datum(/datum/antagonist/brainwashed)
target.setOrganLoss(ORGAN_SLOT_BRAIN, target.getOrganLoss(ORGAN_SLOT_BRAIN) - 60) //we set damage in this case in order to clear the "failing" flag
target.cure_all_traumas(TRAUMA_RESILIENCE_LOBOTOMY) //Lobotomy tier fix cause you can't clone this!
if(target.getOrganLoss(ORGAN_SLOT_BRAIN) > 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
@@ -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!"))
@@ -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
+22 -15
View File
@@ -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"