diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm
index 1dd20906704..4f9af54457c 100644
--- a/code/game/gamemodes/wizard/artefact.dm
+++ b/code/game/gamemodes/wizard/artefact.dm
@@ -465,7 +465,7 @@ var/global/list/multiverse = list()
if("cyborg")
if(M.get_species() != "Machine")
for(var/obj/item/organ/O in M.bodyparts)
- O.robotize()
+ O.robotize(make_tough = 1)
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses)
M.equip_to_slot_or_del(sword, slot_r_hand)
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index ef1589f50b7..b744edd79a6 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -7,7 +7,7 @@
slot_flags = SLOT_BELT
var/list/part = null
var/sabotaged = 0 //Emagging limbs can have repercussions when installed as prosthetics.
- var/model_info
+ var/model_info = "Unbranded"
dir = SOUTH
/obj/item/robot_parts/New(newloc, model)
@@ -23,33 +23,38 @@
else
name = "robot [initial(name)]"
+/obj/item/robot_parts/attack_self(mob/user)
+ var/choice = input(user, "Select the company appearance for this limb.", "Limb Company Selection") as null|anything in selectable_robolimbs
+ if(!choice)
+ return
+ if(loc != user)
+ return
+ model_info = choice
+ to_chat(usr, "You change the company limb model to [choice].")
+
/obj/item/robot_parts/l_arm
name = "left arm"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
icon_state = "l_arm"
part = list("l_arm","l_hand")
- model_info = 1
/obj/item/robot_parts/r_arm
name = "right arm"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
icon_state = "r_arm"
part = list("r_arm","r_hand")
- model_info = 1
/obj/item/robot_parts/l_leg
name = "left leg"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
icon_state = "l_leg"
part = list("l_leg","l_foot")
- model_info = 1
/obj/item/robot_parts/r_leg
name = "right leg"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
icon_state = "r_leg"
part = list("r_leg","r_foot")
- model_info = 1
/obj/item/robot_parts/chest
name = "torso"
@@ -80,6 +85,7 @@
name = "endoskeleton"
desc = "A complex metal backbone with standard limb sockets and pseudomuscle anchors."
icon_state = "robo_suit"
+ model_info = null
var/obj/item/robot_parts/l_arm/l_arm = null
var/obj/item/robot_parts/r_arm/r_arm = null
var/obj/item/robot_parts/l_leg/l_leg = null
@@ -108,6 +114,9 @@
forced_ai = null
return ..()
+/obj/item/robot_parts/robot_suit/attack_self(mob/user)
+ return
+
/obj/item/robot_parts/robot_suit/proc/updateicon()
overlays.Cut()
if(l_arm)
diff --git a/code/modules/mob/living/carbon/human/interactive/interactive.dm b/code/modules/mob/living/carbon/human/interactive/interactive.dm
index 00b8e0a4544..b1d9b5bc68f 100644
--- a/code/modules/mob/living/carbon/human/interactive/interactive.dm
+++ b/code/modules/mob/living/carbon/human/interactive/interactive.dm
@@ -270,20 +270,20 @@
if(prob((SNPC_FUZZY_CHANCE_LOW+SNPC_FUZZY_CHANCE_HIGH)/4))
var/obj/item/organ/external/R = bodyparts_by_name["r_arm"]
if(R)
- R.robotize()
+ R.robotize(make_tough = 1)
else
var/obj/item/organ/external/L = bodyparts_by_name["l_arm"]
if(L)
- L.robotize()
+ L.robotize(make_tough = 1)
//legs
if(prob((SNPC_FUZZY_CHANCE_LOW+SNPC_FUZZY_CHANCE_HIGH)/4))
var/obj/item/organ/external/R = bodyparts_by_name["r_leg"]
if(R)
- R.robotize()
+ R.robotize(make_tough = 1)
else
var/obj/item/organ/external/L = bodyparts_by_name["l_leg"]
if(L)
- L.robotize()
+ L.robotize(make_tough = 1)
UpdateDamageIcon()
regenerate_icons()
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index e1a1bdc1d8b..f8b8f7c84d7 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -16,11 +16,9 @@
return 0
/mob/living/carbon/human/isSynthetic()
- // If they are 100% robotic, they count as synthetic.
- for(var/obj/item/organ/external/E in bodyparts)
- if(!(E.status & ORGAN_ROBOT))
- return 0
- return 1
+ if(get_species() == "Machine")
+ return 1
+ return 0
/mob/proc/get_screen_colour()
diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm
new file mode 100644
index 00000000000..174076c5fab
--- /dev/null
+++ b/code/modules/surgery/limb_augmentation.dm
@@ -0,0 +1,55 @@
+/datum/surgery/limb_augmentation
+ name = "Augment Limb"
+ steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/augment)
+ possible_locs = list("chest","l_arm","r_arm","r_leg","l_leg")
+
+/datum/surgery/limb_augmentation/can_start(mob/user, mob/living/carbon/target)
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting)
+ if(!affected)
+ return 0
+ if(affected.status & ORGAN_BROKEN) //The arm has to be in prime condition to augment it.
+ return 0
+ if(affected.status & ORGAN_ROBOT)
+ return 0
+ return 1
+
+/datum/surgery_step/augment
+ name = "augment limb with robotic part"
+ allowed_tools = list(/obj/item/robot_parts = 100)
+ time = 32
+
+/datum/surgery_step/augment/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/robot_parts/p = tool
+ if(p.part)
+ if(!(target_zone in p.part))
+ to_chat(user, "[tool] cannot be used to augment this limb!")
+ return 0
+ return 1
+
+/datum/surgery_step/augment/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("[user] starts augmenting [affected] with [tool].", "You start augmenting [affected] with [tool].")
+
+/datum/surgery_step/augment/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/robot_parts/L = tool
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("[user] has finished augmenting [affected] with [tool].", \
+ "You augment [affected] with [tool].")
+
+ if(L.part)
+ for(var/part_name in L.part)
+ if(!target.get_organ(part_name))
+ continue
+ affected.robotize(L.model_info, make_tough = 1, convert_all = 0)
+ if(L.sabotaged)
+ affected.sabotaged = 1
+ break
+ target.update_body()
+ target.updatehealth()
+ target.UpdateDamageIcon()
+
+ qdel(tool)
+
+ return 1
\ No newline at end of file
diff --git a/code/modules/surgery/organs/organ.dm b/code/modules/surgery/organs/organ.dm
index fb52fba69f9..0c45118e9a8 100644
--- a/code/modules/surgery/organs/organ.dm
+++ b/code/modules/surgery/organs/organ.dm
@@ -268,15 +268,22 @@ var/list/organ_cache = list()
/obj/item/organ/emp_act(severity)
if(!(status & ORGAN_ROBOT))
return
- switch(severity)
- if(1.0)
- take_damage(0,20)
- return
- if(2.0)
- take_damage(0,7)
- return
- if(3.0)
- take_damage(0,3)
+ if(tough)
+ switch(severity)
+ if(1)
+ take_damage(0, 5.5)
+ if(owner)
+ owner.Stun(10)
+ if(2)
+ take_damage(0, 2.8)
+ if(owner)
+ owner.Stun(5)
+ else
+ switch(severity)
+ if(1)
+ take_damage(0, 20)
+ if(2)
+ take_damage(0, 7)
/obj/item/organ/internal/emp_act(severity)
if(!robotic)
@@ -284,13 +291,11 @@ var/list/organ_cache = list()
if(robotic == 2)
switch(severity)
if(1.0)
- take_damage(20,1)
+ take_damage(20, 1)
if(2.0)
- take_damage(7,1)
- if(3.0)
- take_damage(3,1)
+ take_damage(7, 1)
else if(robotic == 1)
- take_damage(11,1)
+ take_damage(11, 1)
/obj/item/organ/internal/heart/emp_act(intensity)
if(owner && robotic == 2)
diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm
index 151636a9a50..7d544a61cda 100644
--- a/code/modules/surgery/organs/organ_external.dm
+++ b/code/modules/surgery/organs/organ_external.dm
@@ -46,6 +46,7 @@
var/obj/item/organ/external/parent
var/list/obj/item/organ/external/children
+ var/list/convertable_children = list()
// Internal organs of this body part
var/list/internal_organs = list()
@@ -194,6 +195,10 @@
****************************************************/
/obj/item/organ/external/take_damage(brute, burn, sharp, edge, used_weapon = null, list/forbidden_limbs = list())
+ if(tough)
+ brute = max(0, brute - 5)
+ burn = max(0, burn - 4)
+
if((brute <= 0) && (burn <= 0))
return 0
@@ -847,19 +852,18 @@ Note that amputating the affected organ does in fact remove the infection from t
status &= ~ORGAN_BROKEN
return 1
-// I put these two next to each other to highlight that both exist. This should likely be resolved.
-/obj/item/organ/external/robotize()
+/obj/item/organ/external/robotize(company, make_tough = 0, convert_all = 1)
..()
//robot limbs take reduced damage
- brute_mod = 0.66
- burn_mod = 0.66
+ if(!make_tough)
+ brute_mod = 0.66
+ burn_mod = 0.66
+ fail_at_full_damage = 1
+ else
+ tough = 1
// Robot parts also lack bones
// This is so surgery isn't kaput, let's see how this does
encased = null
- fail_at_full_damage = 1
-
-/obj/item/organ/external/robotize(var/company)
- ..()
if(company && istext(company))
set_company(company)
@@ -867,8 +871,8 @@ Note that amputating the affected organ does in fact remove the infection from t
cannot_break = 1
get_icon()
for(var/obj/item/organ/external/T in children)
- if(T)
- T.robotize()
+ if((convert_all) || (T.type in convertable_children))
+ T.robotize(company, make_tough, convert_all)
@@ -900,12 +904,12 @@ Note that amputating the affected organ does in fact remove the infection from t
return 0
/obj/item/organ/external/proc/is_usable()
- if((status & ORGAN_ROBOT) && get_damage() >= max_damage) //robot limbs just become inoperable at max damage
+ if(((status & ORGAN_ROBOT) && get_damage() >= max_damage) && !tough) //robot limbs just become inoperable at max damage
return
return !(status & (ORGAN_DESTROYED|ORGAN_MUTATED|ORGAN_DEAD))
/obj/item/organ/external/proc/is_malfunctioning()
- return ((status & ORGAN_ROBOT) && (brute_dam + burn_dam) >= 10 && prob(brute_dam + burn_dam))
+ return ((status & ORGAN_ROBOT) && (brute_dam + burn_dam) >= 10 && prob(brute_dam + burn_dam) && !tough)
/obj/item/organ/external/proc/embed(var/obj/item/weapon/W, var/silent = 0)
if(!owner || loc != owner)
diff --git a/code/modules/surgery/organs/robolimbs.dm b/code/modules/surgery/organs/robolimbs.dm
index 2d31942059c..d3c297bc0c7 100644
--- a/code/modules/surgery/organs/robolimbs.dm
+++ b/code/modules/surgery/organs/robolimbs.dm
@@ -1,5 +1,6 @@
var/global/list/all_robolimbs = list()
var/global/list/chargen_robolimbs = list()
+var/global/list/selectable_robolimbs = list()
var/global/datum/robolimb/basic_robolimb
/proc/populate_robolimb_list()
@@ -11,12 +12,15 @@ var/global/datum/robolimb/basic_robolimb
if(R != "head" && R != "chest" && R != "groin" ) //Part of the method that ensures only IPCs can access head, chest and groin prosthetics.
if(R.has_subtypes) //Ensures solos get added to the list as well be incorporating has_subtypes == 1 and has_subtypes == 2.
chargen_robolimbs[R.company] = R //List only main brands and solo parts.
+ if(R.selectable)
+ selectable_robolimbs[R.company] = R
/datum/robolimb
var/company = "Unbranded" // Shown when selecting the limb.
var/desc = "A generic unbranded robotic prosthesis." // Seen when examining a limb.
var/icon = 'icons/mob/human_races/robotic.dmi' // Icon base to draw from.
var/unavailable_at_chargen // If set, not available at chargen.
+ var/selectable = 1 // If set, is it available for selection on attack_self with a robo limb?
var/is_monitor // If set, limb is a monitor and should be getting monitor styles.
var/has_subtypes = 2 // If null, object is a model. If 1, object is a brand (that serves as the default model) with child models. If 2, object is a brand that has no child models and thus also serves as the model..
var/parts = list("chest", "groin", "head", "r_arm", "r_hand", "r_leg", "r_foot", "l_leg", "l_foot", "l_arm", "l_hand") // Defines what parts said brand can replace on a body.
@@ -31,6 +35,7 @@ var/global/datum/robolimb/basic_robolimb
company = "Bishop Cybernetics alt."
icon = 'icons/mob/human_races/cyberlimbs/bishop/bishop_alt1.dmi'
parts = list("head")
+ selectable = 0
has_subtypes = null
/datum/robolimb/bishop/monitor
@@ -38,6 +43,7 @@ var/global/datum/robolimb/basic_robolimb
icon = 'icons/mob/human_races/cyberlimbs/bishop/bishop_monitor.dmi'
parts = list("head")
is_monitor = 1
+ selectable = 0
has_subtypes = null
/datum/robolimb/hesphiastos
@@ -51,6 +57,7 @@ var/global/datum/robolimb/basic_robolimb
icon = 'icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_alt1.dmi'
parts = list("head")
is_monitor = 1
+ selectable = 0
has_subtypes = null
/datum/robolimb/hesphiastos/monitor
@@ -58,6 +65,7 @@ var/global/datum/robolimb/basic_robolimb
icon = 'icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_monitor.dmi'
parts = list("head")
is_monitor = 1
+ selectable = 0
has_subtypes = null
/datum/robolimb/morpheus
@@ -74,6 +82,7 @@ var/global/datum/robolimb/basic_robolimb
parts = list("head")
unavailable_at_chargen = null
is_monitor = null
+ selectable = 0
has_subtypes = 2 //Edge case. We want to be able to pick this one, and if we had it left as null for has_subtypes we'd be assuming it'll be chosen as a child model,
//and since the parent is unavailable at chargen, we wouldn't be able to see it in the list anyway. Now, we'll be able to select the Morpheus Ckt. Alt. head as a solo-model.
@@ -87,6 +96,7 @@ var/global/datum/robolimb/basic_robolimb
company = "Ward-Takahashi alt."
icon = 'icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_alt1.dmi'
parts = list("head")
+ selectable = 0
has_subtypes = null
/datum/robolimb/wardtakahashi/monitor
@@ -94,6 +104,7 @@ var/global/datum/robolimb/basic_robolimb
icon = 'icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_monitor.dmi'
parts = list("head")
is_monitor = 1
+ selectable = 0
has_subtypes = null
/datum/robolimb/xion
@@ -106,6 +117,7 @@ var/global/datum/robolimb/basic_robolimb
company = "Xion Manufacturing Group alt."
icon = 'icons/mob/human_races/cyberlimbs/xion/xion_alt1.dmi'
parts = list("head")
+ selectable = 0
has_subtypes = null
/datum/robolimb/xion/monitor
@@ -113,6 +125,7 @@ var/global/datum/robolimb/basic_robolimb
icon = 'icons/mob/human_races/cyberlimbs/xion/xion_monitor.dmi'
parts = list("head")
is_monitor = 1
+ selectable = 0
has_subtypes = null
/datum/robolimb/zenghu
@@ -131,6 +144,7 @@ var/global/datum/robolimb/basic_robolimb
company = "Shellguard Munitions Elite Series"
icon = 'icons/mob/human_races/cyberlimbs/shellguard/shellguard_alt1.dmi'
parts = list("head")
+ selectable = 0
has_subtypes = null
/datum/robolimb/shellguard/monitor
@@ -138,4 +152,5 @@ var/global/datum/robolimb/basic_robolimb
icon = 'icons/mob/human_races/cyberlimbs/shellguard/shellguard_monitor.dmi'
parts = list("head")
is_monitor = 1
+ selectable = 0
has_subtypes = null
\ No newline at end of file
diff --git a/code/modules/surgery/organs/subtypes/standard.dm b/code/modules/surgery/organs/subtypes/standard.dm
index a6467584963..f11d123ea75 100644
--- a/code/modules/surgery/organs/subtypes/standard.dm
+++ b/code/modules/surgery/organs/subtypes/standard.dm
@@ -17,6 +17,7 @@
parent_organ = null
encased = "ribcage"
var/fat = FALSE
+ convertable_children = list(/obj/item/organ/external/groin)
/obj/item/organ/external/chest/proc/makeFat(update_body_icon = 1)
fat = TRUE
@@ -60,6 +61,7 @@
parent_organ = "chest"
amputation_point = "left shoulder"
can_grasp = 1
+ convertable_children = list(/obj/item/organ/external/hand)
/obj/item/organ/external/arm/right
limb_name = "r_arm"
@@ -67,6 +69,7 @@
icon_name = "r_arm"
body_part = ARM_RIGHT
amputation_point = "right shoulder"
+ convertable_children = list(/obj/item/organ/external/hand/right)
/obj/item/organ/external/leg
limb_name = "l_leg"
@@ -80,6 +83,7 @@
parent_organ = "groin"
amputation_point = "left hip"
can_stand = 1
+ convertable_children = list(/obj/item/organ/external/foot)
/obj/item/organ/external/leg/right
limb_name = "r_leg"
@@ -88,6 +92,7 @@
body_part = LEG_RIGHT
icon_position = RIGHT
amputation_point = "right hip"
+ convertable_children = list(/obj/item/organ/external/foot/right)
/obj/item/organ/external/foot
limb_name = "l_foot"
diff --git a/paradise.dme b/paradise.dme
index e0bd5450ef0..2d395dbf7e0 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -2137,6 +2137,7 @@
#include "code\modules\surgery\generic.dm"
#include "code\modules\surgery\helpers.dm"
#include "code\modules\surgery\implant.dm"
+#include "code\modules\surgery\limb_augmentation.dm"
#include "code\modules\surgery\limb_reattach.dm"
#include "code\modules\surgery\organs_internal.dm"
#include "code\modules\surgery\other.dm"