diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm
index 89b01a699b..124be53452 100644
--- a/code/__defines/damage_organs.dm
+++ b/code/__defines/damage_organs.dm
@@ -44,10 +44,11 @@
#define DROPLIMB_BURN 2
// Damage above this value must be repaired with surgery.
-#define ROBOLIMB_SELF_REPAIR_CAP 30
+#define ROBOLIMB_REPAIR_CAP 30
-#define ORGAN_ASSISTED 1
-#define ORGAN_ROBOT 2
+#define ORGAN_ASSISTED 1 // Like pacemakers, not robotic
+#define ORGAN_ROBOT 2 // Fully robotic, no organic parts
+#define ORGAN_LIFELIKE 3 // Robotic, made to appear organic
//Germs and infections.
#define GERM_LEVEL_AMBIENT 110 // Maximum germ level you can reach by standing still.
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 83b6f2ce86..bdab3bbbb1 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -360,7 +360,7 @@
return
if(subject.isSynthetic())
- scantemp = "Error: Subject is not organic."
+ scantemp = "Error: Majority of subject is non-organic."
return
if (subject.suiciding == 1)
scantemp = "Error: Subject's brain is not responding to scanning stimuli."
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index 036e427078..fc764efd02 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -17,6 +17,7 @@ var/global/list/image/splatter_cache=list()
var/base_icon = 'icons/effects/blood.dmi'
blood_DNA = list()
var/basecolor="#A10808" // Color when wet.
+ var/synthblood = 0
var/list/datum/disease2/disease/virus2 = list()
var/amount = 5
var/drytime
@@ -61,9 +62,9 @@ var/global/list/image/splatter_cache=list()
/obj/effect/decal/cleanable/blood/update_icon()
if(basecolor == "rainbow") basecolor = "#[get_random_colour(1)]"
color = basecolor
- if(basecolor == SYNTH_BLOOD_COLOUR)
- name = "oil"
- desc = "It's black and greasy."
+ if(synthblood)
+ name = "synthetic blood"
+ desc = "It's quite greasy."
else
name = initial(name)
desc = initial(desc)
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index d47df19f19..2ddbd4e330 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -37,8 +37,13 @@
user << "You can't apply [src] through [H.wear_suit]!"
return 1
- if(affecting.robotic >= ORGAN_ROBOT)
- user << "This isn't useful at all on a robotic limb.."
+ if(affecting.robotic == ORGAN_ROBOT)
+ user << "This isn't useful at all on a robotic limb."
+ return 1
+
+ if(affecting.robotic >= ORGAN_LIFELIKE)
+ user << "You apply the [src], but it seems to have no effect..."
+ use(1)
return 1
H.UpdateDamageIcon()
diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm
index 5b85763b32..1ff55adf85 100644
--- a/code/game/objects/items/stacks/nanopaste.dm
+++ b/code/game/objects/items/stacks/nanopaste.dm
@@ -27,19 +27,12 @@
var/mob/living/carbon/human/H = M
var/obj/item/organ/external/S = H.get_organ(user.zone_sel.selecting)
- if(S.open == 1)
- if (S && (S.robotic >= ORGAN_ROBOT))
- if(S.get_damage())
- S.heal_damage(15, 15, robo_repair = 1)
- H.updatehealth()
- use(1)
- user.visible_message("\The [user] applies some nanite paste at[user != M ? " \the [M]'s" : " \the"][S.name] with \the [src].",\
- "You apply some nanite paste at [user == M ? "your" : "[M]'s"] [S.name].")
- else
- user << "Nothing to fix here."
+ if (S && (S.robotic >= ORGAN_ROBOT))
+ if(S.robo_repair(15, "omni", 0, src, user))
+ use(1)
+ user.visible_message("\The [user] applies some nanite paste on [user != M ? "\the [M]'s" : "their"] [S.name].",\
+ "You apply some nanite paste on [user == M ? "your" : "[M]'s"] [S.name].")
else
if (can_operate(H))
if (do_surgery(H,user,src))
return
- else
- user << "Nothing to fix in here."
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index de3764e5af..53d12e8b7d 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -4,26 +4,69 @@
var/skipjumpsuit = 0
var/skipshoes = 0
var/skipmask = 0
+
var/skipears = 0
var/skipeyes = 0
var/skipface = 0
+ var/skipchest = 0
+ var/skipgroin = 0
+ var/skiphands = 0
+ var/skiplegs = 0
+ var/skiparms = 0
+ var/skipfeet = 0
+
+ var/looks_synth = looksSynthetic()
//exosuits and helmets obscure our view and stuff.
if(wear_suit)
- skipgloves = wear_suit.flags_inv & HIDEGLOVES
- skipsuitstorage = wear_suit.flags_inv & HIDESUITSTORAGE
- skipjumpsuit = wear_suit.flags_inv & HIDEJUMPSUIT
- skipshoes = wear_suit.flags_inv & HIDESHOES
+ skipsuitstorage |= wear_suit.flags_inv & HIDESUITSTORAGE
+ if(wear_suit.flags_inv & HIDEJUMPSUIT)
+ skiparms |= 1
+ skiplegs |= 1
+ skipchest |= 1
+ skipgroin |= 1
+ if(wear_suit.flags_inv & HIDESHOES)
+ skipshoes |= 1
+ skipfeet |= 1
+ if(wear_suit.flags_inv & HIDEGLOVES)
+ skipgloves |= 1
+ skiphands |= 1
+
+ if(w_uniform)
+ skiplegs |= w_uniform.body_parts_covered & LEGS
+ skiparms |= w_uniform.body_parts_covered & ARMS
+ skipchest |= w_uniform.body_parts_covered & UPPER_TORSO
+ skipgroin |= w_uniform.body_parts_covered & LOWER_TORSO
+
+ if(gloves)
+ skiphands |= gloves.body_parts_covered & HANDS
+
+ if(shoes)
+ skipfeet |= shoes.body_parts_covered & FEET
if(head)
- skipmask = head.flags_inv & HIDEMASK
- skipeyes = head.flags_inv & HIDEEYES
- skipears = head.flags_inv & HIDEEARS
- skipface = head.flags_inv & HIDEFACE
+ skipmask |= head.flags_inv & HIDEMASK
+ skipeyes |= head.flags_inv & HIDEEYES
+ skipears |= head.flags_inv & HIDEEARS
+ skipface |= head.flags_inv & HIDEFACE
if(wear_mask)
skipface |= wear_mask.flags_inv & HIDEFACE
+ //This is what hides what
+ var/list/hidden = list(
+ BP_GROIN = skipgroin,
+ BP_TORSO = skipchest,
+ BP_HEAD = skipface,
+ BP_L_ARM = skiparms,
+ BP_R_ARM = skiparms,
+ BP_L_HAND= skiphands,
+ BP_R_HAND= skiphands,
+ BP_L_FOOT= skipfeet,
+ BP_R_FOOT= skipfeet,
+ BP_L_LEG = skiplegs,
+ BP_R_LEG = skiplegs)
+
var/msg = "*---------*\nThis is "
var/datum/gender/T = gender_datums[get_gender()]
@@ -39,9 +82,8 @@
msg += "[src.name]"
- var/is_synth = isSynthetic()
if(!(skipjumpsuit && skipface))
- if(is_synth)
+ if(looks_synth)
var/use_gender = "a synthetic"
if(gender == MALE)
use_gender = "an android"
@@ -124,8 +166,6 @@
else if(blood_DNA)
msg += "[T.He] [T.has] [(hand_blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained hands!\n"
- //handcuffed?
-
//handcuffed?
if(handcuffed)
if(istype(handcuffed, /obj/item/weapon/handcuffs/cable))
@@ -273,14 +313,16 @@
for(var/obj/item/organ/external/temp in organs)
if(temp)
+ if((temp.organ_tag in hidden) && hidden[temp.organ_tag])
+ continue //Organ is hidden, don't talk about it
if(temp.status & ORGAN_DESTROYED)
wound_flavor_text["[temp.name]"] = "[T.He] [T.is] missing [T.his] [temp.name].\n"
continue
- if(!is_synth && temp.robotic >= ORGAN_ROBOT)
+ if(!looks_synth && temp.robotic == ORGAN_ROBOT)
if(!(temp.brute_dam + temp.burn_dam))
wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a [temp.name].\n"
else
- wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a [temp.name]. It has [temp.get_wounds_desc()]!\n"
+ wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a [temp.name] with [temp.get_wounds_desc()]!\n"
continue
else if(temp.wounds.len > 0 || temp.open)
if(temp.is_stump() && temp.parent_organ && organs_by_name[temp.parent_organ])
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index b5ea7931c1..7736a66657 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1140,8 +1140,6 @@
qdel(hud_used)
hud_used = new /datum/hud(src)
- full_prosthetic = null
-
if(species)
return 1
else
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 390e7ee6c5..5a9d384602 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -31,6 +31,7 @@
var/age = 30 //Player's age (pure fluff)
var/b_type = "A+" //Player's bloodtype
+ var/synthetic //If they are a synthetic (aka synthetic torso)
var/underwear_top = 1 //Which underwear the player wants
var/underwear_bottom = 1
@@ -83,7 +84,6 @@
var/list/flavor_texts = list()
var/gunshot_residue
var/pulling_punches // Are you trying not to hurt your opponent?
- var/full_prosthetic // We are a robutt.
var/robolimb_count = 0 // Number of robot limbs.
mob_bump_flag = HUMAN
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index df8eead14e..db0f44ce31 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -58,6 +58,37 @@
/mob/living/carbon/human/get_gender()
return identifying_gender ? identifying_gender : gender
+// This is the 'mechanical' check for synthetic-ness, not appearance
+// Returns the company that made the synthetic
+/mob/living/carbon/human/isSynthetic()
+ if(synthetic) return synthetic //Your synthetic-ness is not going away
+ var/obj/item/organ/external/T = organs_by_name[BP_TORSO]
+ if(T && T.robotic >= ORGAN_ROBOT)
+ var/datum/robolimb/R = all_robolimbs[T.model]
+ synthetic = R
+ return synthetic
+
+ return 0
+
+// Would an onlooker know this person is synthetic?
+// Based on sort of logical reasoning, 'Look at head, look at torso'
+/mob/living/carbon/human/proc/looksSynthetic()
+ var/obj/item/organ/external/T = organs_by_name[BP_TORSO]
+ var/obj/item/organ/external/H = organs_by_name[BP_HEAD]
+
+ //Look at their head
+ if(!head || !(head && (head.flags_inv & HIDEFACE)))
+ if(H && H.robotic == ORGAN_ROBOT) //Exactly robotic, not higher as lifelike is higher
+ return 1
+
+ //Look at their torso
+ if(!wear_suit || (wear_suit && !(wear_suit.flags_inv & HIDEJUMPSUIT)))
+ if(!w_uniform || (w_uniform && !(w_uniform.body_parts_covered & UPPER_TORSO)))
+ if(T && T.robotic == ORGAN_ROBOT)
+ return 1
+
+ return 0
+
#undef HUMAN_EATING_NO_ISSUE
#undef HUMAN_EATING_NO_MOUTH
#undef HUMAN_EATING_BLOCKED_MOUTH
diff --git a/code/modules/mob/living/carbon/human/species/species_getters.dm b/code/modules/mob/living/carbon/human/species/species_getters.dm
index 625d555943..efb053eddf 100644
--- a/code/modules/mob/living/carbon/human/species/species_getters.dm
+++ b/code/modules/mob/living/carbon/human/species/species_getters.dm
@@ -47,10 +47,19 @@
return "no message"
/datum/species/proc/get_ssd(var/mob/living/carbon/human/H)
- return ((H && H.isSynthetic()) ? "flashing a 'system offline' glyph on their monitor" : show_ssd)
+ if(H)
+ if(H.looksSynthetic())
+ return "flashing a 'system offline' light"
+ else
+ return show_ssd
/datum/species/proc/get_blood_colour(var/mob/living/carbon/human/H)
- return ((H && H.isSynthetic()) ? SYNTH_BLOOD_COLOUR : blood_color)
+ if(H)
+ var/datum/robolimb/company = H.isSynthetic()
+ if(company)
+ return company.blood_color
+ else
+ return blood_color
/datum/species/proc/get_virus_immune(var/mob/living/carbon/human/H)
return ((H && H.isSynthetic()) ? 1 : virus_immune)
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 088c796f28..64a50e2696 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -220,6 +220,8 @@ var/global/list/damage_icon_parts = list()
var/hulk = (HULK in src.mutations)
var/skeleton = (SKELETON in src.mutations)
+ robolimb_count = 0
+
//CACHING: Generate an index key from visible bodyparts.
//0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic.
@@ -249,6 +251,7 @@ var/global/list/damage_icon_parts = list()
icon_key += "0"
else if(part.robotic >= ORGAN_ROBOT)
icon_key += "2[part.model ? "-[part.model]": ""]"
+ robolimb_count++
else if(part.status & ORGAN_DEAD)
icon_key += "3"
else
@@ -596,7 +599,7 @@ var/global/list/damage_icon_parts = list()
standing = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]")
standing.color = l_ear.color
both.overlays += standing
-
+
if(r_ear)
var/image/standing
var/t_type = r_ear.icon_state
@@ -610,7 +613,7 @@ var/global/list/damage_icon_parts = list()
standing = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]")
standing.color = r_ear.color
both.overlays += standing
-
+
overlays_standing[EARS_LAYER] = both
else
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 612861ed8c..5271034d2b 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -19,18 +19,6 @@
return L.mob_size <= MOB_MINISCULE
return 0
-
-// If they are 100% robotic, they count as synthetic.
-/mob/living/carbon/human/isSynthetic()
- if(isnull(full_prosthetic))
- robolimb_count = 0
- for(var/obj/item/organ/external/E in organs)
- if(E.robotic >= ORGAN_ROBOT)
- robolimb_count++
- if(robolimb_count == organs.len)
- full_prosthetic = 1
- return full_prosthetic
-
/mob/living/silicon/isSynthetic()
return 1
diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm
index 17219a48d4..2c5f24984a 100644
--- a/code/modules/organs/blood.dm
+++ b/code/modules/organs/blood.dm
@@ -266,9 +266,11 @@ proc/blood_splatter(var/target,var/datum/reagent/blood/source,var/large)
var/obj/effect/decal/cleanable/blood/B
var/decal_type = /obj/effect/decal/cleanable/blood/splatter
var/turf/T = get_turf(target)
+ var/synth = 0
if(istype(source,/mob/living/carbon/human))
var/mob/living/carbon/human/M = source
+ if(M.isSynthetic()) synth = 1
source = M.get_blood(M.vessel)
// Are we dripping or splattering?
@@ -297,6 +299,7 @@ proc/blood_splatter(var/target,var/datum/reagent/blood/source,var/large)
// Update appearance.
if(source.data["blood_colour"])
B.basecolor = source.data["blood_colour"]
+ B.synthblood = synth
B.update_icon()
// Update blood information.
diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm
index cc105e1bbf..419d82ea64 100644
--- a/code/modules/organs/organ_external.dm
+++ b/code/modules/organs/organ_external.dm
@@ -363,15 +363,16 @@
var/damage_amount
switch(damage_type)
- if(BRUTE) damage_amount = brute_dam
- if(BURN) damage_amount = burn_dam
+ if(BRUTE) damage_amount = brute_dam
+ if(BURN) damage_amount = burn_dam
+ if("omni") damage_amount = max(brute_dam,burn_dam)
else return 0
if(!damage_amount)
user << "Nothing to fix!"
return 0
- if(damage_amount >= ROBOLIMB_SELF_REPAIR_CAP)
+ if(damage_amount >= ROBOLIMB_REPAIR_CAP)
user << "The damage is far too severe to patch over externally."
return 0
@@ -394,10 +395,13 @@
switch(damage_type)
if(BRUTE) src.heal_damage(repair_amount, 0, 0, 1)
if(BURN) src.heal_damage(0, repair_amount, 0, 1)
- if(user == src.owner)
- user.visible_message("\The [user] patches [damage_desc] on \his [src.name] with [tool].")
- else
- user.visible_message("\The [user] patches [damage_desc] on [owner]'s [src.name] with [tool].")
+ if("omni")src.heal_damage(repair_amount, repair_amount, 0, 1)
+
+ if(damage_desc)
+ if(user == src.owner)
+ user.visible_message("\The [user] patches [damage_desc] on \his [src.name] with [tool].")
+ else
+ user.visible_message("\The [user] patches [damage_desc] on [owner]'s [src.name] with [tool].")
return 1
@@ -1028,7 +1032,11 @@ Note that amputating the affected organ does in fact remove the infection from t
R = basic_robolimb
if(R)
force_icon = R.icon
- name = "robotic [initial(name)]"
+ if(R.lifelike)
+ robotic = ORGAN_LIFELIKE
+ name = "[initial(name)]"
+ else
+ name = "robotic [initial(name)]"
desc = "[R.desc] It looks like it was produced by [R.company]."
dislocated = -1
@@ -1041,9 +1049,6 @@ Note that amputating the affected organ does in fact remove the infection from t
if(owner)
- if(!skip_prosthetics)
- owner.full_prosthetic = null // Will be rechecked next isSynthetic() call.
-
if(!keep_organs)
for(var/obj/item/organ/thing in internal_organs)
if(istype(thing))
@@ -1175,29 +1180,39 @@ Note that amputating the affected organ does in fact remove the infection from t
if(status & ORGAN_DESTROYED && !is_stump())
. += "tear at [amputation_point] so severe that it hangs by a scrap of flesh"
+ //Handle robotic and synthetic organ damage
if(robotic >= ORGAN_ROBOT)
+ var/LL //Life-Like, aka only show that it's robotic in heavy damage
+ if(robotic >= ORGAN_LIFELIKE)
+ LL = 1
if(brute_dam)
switch(brute_dam)
if(0 to 20)
- . += "some dents"
+ . += "some [LL ? "cuts" : "dents"]"
if(21 to INFINITY)
- . += pick("a lot of dents","severe denting")
+ . += "[LL ? pick("exposed wiring","torn-back synthflesh") : pick("a lot of dents","severe denting")]"
+
if(brute_dam && burn_dam)
. += " and "
+
if(burn_dam)
switch(burn_dam)
if(0 to 20)
. += "some burns"
if(21 to INFINITY)
- . += pick("a lot of burns","severe melting")
+ . += "[LL ? pick("roasted synth-flesh","melted internal wiring") : pick("many burns","scorched metal")]"
+
if(open)
if(brute_dam || burn_dam)
- . += " and an open panel"
+ . += " and "
+ if(open == 1)
+ . += "some exposed screws"
else
. += "an open panel"
return
+ //Normal organic organ damage
var/list/wound_descriptors = list()
if(open > 1)
wound_descriptors["an open incision"] = 1
diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm
index e54598d23e..a20777928d 100644
--- a/code/modules/organs/robolimbs.dm
+++ b/code/modules/organs/robolimbs.dm
@@ -15,6 +15,9 @@ var/datum/robolimb/basic_robolimb
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/unavailable_to_build // If set, can't be constructed.
+ var/lifelike // If set, appears organic.
+ var/blood_color = "#030303"
var/list/species_cannot_use = list("Teshari")
/datum/robolimb/bishop
@@ -48,6 +51,8 @@ var/datum/robolimb/basic_robolimb
icon = 'icons/mob/human_races/cyberlimbs/wardtakahashi.dmi'
/datum/robolimb/veymed
+ lifelike = 1
+ blood_color = "#CCCCCC"
company = "Vey-Med"
desc = "This high quality limb is nearly indistinguishable from an organic one."
icon = 'icons/mob/human_races/cyberlimbs/veymed.dmi'
\ No newline at end of file
diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm
index eadd4db655..ee0dfecb4f 100644
--- a/code/modules/surgery/limb_reattach.dm
+++ b/code/modules/surgery/limb_reattach.dm
@@ -21,6 +21,18 @@
min_duration = 50
max_duration = 70
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/E = tool
+ var/obj/item/organ/external/P = target.organs_by_name[E.parent_organ]
+ if(!P)
+ user << "There's nothing to attach [E] to!"
+ return 0
+ else if((P.robotic >= ORGAN_ROBOT) && (E.robotic < ORGAN_ROBOT))
+ user << "Attaching [E] to [P] wouldn't work well."
+ return 0
+ else
+ return 1
+
begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/E = tool
user.visible_message("[user] starts attaching [E.name] to [target]'s [E.amputation_point].", \