diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index ea8ceb93c95..4ce8554bb4c 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -36,6 +36,7 @@
#define NO_BLOOD 1
#define NO_BREATHE 2
+#define NO_DNA_RAD 4
#define RAD_ABSORB 8
#define NO_SCAN 16
#define NO_PAIN 32
@@ -43,11 +44,11 @@
#define IS_WHITELISTED 128
#define HAS_LIPS 512
#define HAS_UNDERWEAR 1024
-#define IS_SYNTHETIC 2048
-#define IS_PLANT 4096
-#define CAN_BE_FAT 8192
-#define IS_RESTRICTED 16384
-#define NO_INTORGANS 32768
+#define IS_PLANT 2048
+#define CAN_BE_FAT 4096
+#define IS_RESTRICTED 8192
+#define NO_INTORGANS 16384
+#define NO_POISON 32768
//Species Blood Flags
#define BLOOD_SLIME 1
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 4a5b588a629..d686095ea59 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -51,7 +51,7 @@
#define INFECTION_LEVEL_THREE 1000
// Damage above this value must be repaired with surgery.
-#define ROBOLIMB_SELF_REPAIR_CAP 30
+#define ROBOLIMB_SELF_REPAIR_CAP 60
//metal, glass, rod stacks
#define MAX_STACK_AMOUNT_METAL 50
diff --git a/code/__DEFINES/mob.dm b/code/__DEFINES/mob.dm
index fcb6e53c365..0080658562b 100644
--- a/code/__DEFINES/mob.dm
+++ b/code/__DEFINES/mob.dm
@@ -29,6 +29,8 @@
#define ORGAN_ASSISTED 4096
#define DROPLIMB_EDGE 0
+#define DROPLIMB_BLUNT 1
+#define DROPLIMB_BURN 2
#define AGE_MIN 17 //youngest a character can be
#define AGE_MAX 85 //oldest a character can be
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index 9d5207e5493..0553e65edfb 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -258,6 +258,10 @@ client
body += ""
body += ""
body += ""
+ body += ""
+ body += ""
+
+ body += ""
body += ""
body += ""
@@ -929,7 +933,65 @@ client
else
H.verbs -= verb
+ else if(href_list["addorgan"])
+ if(!check_rights(R_SPAWN)) return
+ var/mob/living/carbon/M = locate(href_list["addorgan"])
+ if(!istype(M))
+ usr << "This can only be done to instances of type /mob/living/carbon"
+ return
+
+ var/new_organ = input("Please choose an organ to add.","Organ",null) as null|anything in subtypesof(/obj/item/organ)-/obj/item/organ
+ if(!new_organ) return
+
+ if(!M)
+ usr << "Mob doesn't exist anymore"
+ return
+
+ if(locate(new_organ) in M.internal_organs)
+ usr << "Mob already has that organ."
+ return
+
+ new new_organ(M)
+
+
+ else if(href_list["remorgan"])
+ if(!check_rights(R_SPAWN)) return
+
+ var/mob/living/carbon/M = locate(href_list["remorgan"])
+ if(!istype(M))
+ usr << "This can only be done to instances of type /mob/living/carbon"
+ return
+
+ var/obj/item/organ/rem_organ = input("Please choose an organ to remove.","Organ",null) as null|anything in M.internal_organs
+
+ if(!M)
+ usr << "Mob doesn't exist anymore"
+ return
+
+ if(!(locate(rem_organ) in M.internal_organs))
+ usr << "Mob does not have that organ."
+ return
+
+ usr << "Removed [rem_organ] from [M]."
+ rem_organ.removed()
+ qdel(rem_organ)
+
+ else if(href_list["fix_nano"])
+ if(!check_rights(R_DEBUG)) return
+
+ var/mob/H = locate(href_list["fix_nano"])
+
+ if(!istype(H) || !H.client)
+ usr << "This can only be done on mobs with clients"
+ return
+
+ nanomanager.send_resources(H.client)
+
+ usr << "Resource files sent"
+ H << "Your NanoUI Resource files have been refreshed"
+
+ log_admin("[key_name(usr)] resent the NanoUI resource files to [key_name(H)] ")
else if(href_list["regenerateicons"])
if(!check_rights(0)) return
diff --git a/code/game/dna/dna2_domutcheck.dm b/code/game/dna/dna2_domutcheck.dm
index 545e65b691d..745af66ac15 100644
--- a/code/game/dna/dna2_domutcheck.dm
+++ b/code/game/dna/dna2_domutcheck.dm
@@ -52,7 +52,7 @@
/proc/genemutcheck(var/mob/living/M, var/block, var/connected=null, var/flags=0)
if(ishuman(M)) // Would've done this via species instead of type, but the basic mob doesn't have a species, go figure.
var/mob/living/carbon/human/H = M
- if(H.species.flags & IS_SYNTHETIC)
+ if(H.species.flags & NO_DNA_RAD)
return
if(!M)
return
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index ab0a7b5a464..2687a886e7d 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -296,10 +296,10 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
user << "DNA of [target] is ruined beyond usability!"
return
- if(T.species.flags & IS_SYNTHETIC)
+ if(T.species.flags & NO_DNA_RAD)
user << "This creature does not have DNA!"
- return
-
+ return
+
if(T.species.flags & NO_SCAN)
user << "We do not know how to parse this creature's DNA!"
return
diff --git a/code/game/gamemodes/changeling/powers/swap_form.dm b/code/game/gamemodes/changeling/powers/swap_form.dm
index 4b5646dc237..ffbadfab21c 100644
--- a/code/game/gamemodes/changeling/powers/swap_form.dm
+++ b/code/game/gamemodes/changeling/powers/swap_form.dm
@@ -17,7 +17,7 @@
if((NOCLONE || SKELETON || HUSK) in target.mutations)
user << "DNA of [target] is ruined beyond usability!"
return
- if(!istype(target) || issmall(target) || target.species.flags & IS_SYNTHETIC || target.species.flags & NO_SCAN || target.species.flags & NO_BLOOD)
+ if(!istype(target) || issmall(target) || target.species.flags & NO_DNA_RAD || target.species.flags & NO_SCAN || target.species.flags & NO_BLOOD)
user << "[target] is not compatible with this ability."
return
return 1
diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm
index b772cfca49a..bc21b6d7ebc 100644
--- a/code/game/gamemodes/changeling/powers/tiny_prick.dm
+++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm
@@ -34,7 +34,7 @@
return
if(ishuman(target))
var/mob/living/carbon/human/H = target
- if(H.species.flags & IS_SYNTHETIC)
+ if(H.isSynthetic())
user << "This won't work on synthetics."
return
if(!isturf(user.loc))
diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm
index aaa06ccf403..87d8e4e083c 100644
--- a/code/game/gamemodes/events.dm
+++ b/code/game/gamemodes/events.dm
@@ -42,7 +42,7 @@
if(!(T.z in config.station_levels))
continue
if(istype(H,/mob/living/carbon/human))
- if(H.species.flags & IS_SYNTHETIC)
+ if(H.species.flags & NO_DNA_RAD)
return
H.apply_effect((rand(15,75)),IRRADIATE,0)
if (prob(5))
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index a5881156f80..3921bcf19a2 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -91,7 +91,7 @@
if (C == user)
user.visible_message("[user] climbs on the operating table.","You climb on the operating table.")
else
- visible_message("\red [C] has been laid on the operating table by [user].", 3)
+ visible_message("[C] has been laid on the operating table by [user].", 3)
if (C.client)
C.client.perspective = EYE_PERSPECTIVE
C.client.eye = src
@@ -126,12 +126,12 @@
/obj/machinery/optable/proc/check_table(mob/living/carbon/patient as mob)
- if(src.victim)
- usr << "\blue The table is already occupied!"
+ if(src.victim && get_turf(victim) == get_turf(src) && victim.lying)
+ usr << "The table is already occupied!"
return 0
-
+
if(patient.buckled)
- usr << "\blue Unbuckle first!"
+ usr << "Unbuckle first!"
return 0
-
+
return 1
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index b1507fcb63d..14c72f6ee9c 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -177,6 +177,10 @@ Class Procs:
if(prob(50))
qdel(src)
+//sets the use_power var and then forces an area power update
+/obj/machinery/proc/update_use_power(var/new_use_power)
+ use_power = new_use_power
+
/obj/machinery/proc/auto_use_power()
if(!powered(power_channel))
return 0
diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index 49ea6865f58..37220d43956 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -10,6 +10,7 @@
var/mob/occupant = null
var/circuitboard = "/obj/item/weapon/circuitboard/cyborgrecharger"
var/recharge_speed
+ var/recharge_speed_nutrition
var/repairs
/obj/machinery/recharge_station/New()
@@ -35,9 +36,11 @@
/obj/machinery/recharge_station/RefreshParts()
recharge_speed = 0
+ recharge_speed_nutrition = 0
repairs = 0
for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts)
recharge_speed += C.rating * 100
+ recharge_speed_nutrition += C.rating * 10
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
repairs += M.rating - 1
for(var/obj/item/weapon/stock_parts/cell/C in component_parts)
@@ -51,6 +54,9 @@
process_occupant()
return 1
+/obj/machinery/recharge_station/Bumped(var/mob/AM)
+ move_inside(AM)
+
/obj/machinery/recharge_station/allow_drop()
return 0
@@ -105,6 +111,14 @@
R.cell.charge = R.cell.maxcharge
else
R.cell.charge = min(R.cell.charge + recharge_speed, R.cell.maxcharge)
+ else if(istype(occupant, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = occupant
+ if(!isnull(H.internal_organs_by_name["cell"]) && H.nutrition < 450)
+ H.nutrition = min(H.nutrition+recharge_speed_nutrition, 450)
+ if(repairs)
+ H.adjustBruteLoss(-(repairs))
+ H.adjustFireLoss(-(repairs))
+ H.updatehealth()
/obj/machinery/recharge_station/proc/go_out()
if(!( src.occupant ))
@@ -198,34 +212,51 @@
add_fingerprint(usr)
return
-/obj/machinery/recharge_station/verb/move_inside()
+/obj/machinery/recharge_station/verb/move_inside(var/mob/user = usr)
set category = "Object"
set src in oview(1)
- if (usr.stat == 2)
- //Whoever had it so that a borg with a dead cell can't enter this thing should be shot. --NEO
- return
- if (!(istype(usr, /mob/living/silicon/)))
- usr << "\blue Only non-organics may enter the recharger!"
- return
- if (src.occupant)
- usr << "\blue The cell is already occupied!"
- return
- if (!usr:cell)
- usr << "\blue Without a powercell, you can't be recharged."
- //Make sure they actually HAVE a cell, now that they can get in while powerless. --NEO
+
+ if(!user)
return
+
if (panel_open)
- usr << "\blue Close the maintenance panel first."
+ usr << "Close the maintenance panel first."
+ return
+
+ var/can_accept_user
+ if(isrobot(user))
+ var/mob/living/silicon/robot/R = user
+
+ if(R.stat == DEAD)
+ //Whoever had it so that a borg with a dead cell can't enter this thing should be shot. --NEO
+ return
+ if(occupant)
+ R << "The cell is already occupied!"
+ return
+ if(!R.cell)
+ R << "Without a power cell, you can't be recharged."
+ //Make sure they actually HAVE a cell, now that they can get in while powerless. --NEO
+ return
+ can_accept_user = 1
+
+ else if(istype(user, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = user
+ if(!isnull(H.internal_organs_by_name["cell"]))
+ can_accept_user = 1
+
+ if(!can_accept_user)
+ user << "Only non-organics may enter the recharger!"
return
- usr.stop_pulling()
- if(usr && usr.client)
- usr.client.perspective = EYE_PERSPECTIVE
- usr.client.eye = src
- usr.loc = src
- src.occupant = usr
- /*for(var/obj/O in src)
- O.loc = src.loc*/
- src.add_fingerprint(usr)
+
+ user.stop_pulling()
+ if(user && user.client)
+ user.client.perspective = EYE_PERSPECTIVE
+ user.client.eye = src
+ user.forceMove(src)
+ occupant = user
+
+ add_fingerprint(user)
build_icon()
- src.use_power = 2
- return
\ No newline at end of file
+ update_use_power(1)
+ return
+
\ No newline at end of file
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index d090712dea9..82402e273c9 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -137,12 +137,9 @@ REAGENT SCANNER
user.show_message("\blue Key: Suffocation/Toxin/Burns/Brute", 1)
user.show_message("\blue Body Temperature: ???", 1)
return
- if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
- usr << "\red You don't have the dexterity to do this!"
- return
- user.visible_message(" [user] has analyzed [M]'s vitals."," You have analyzed [M]'s vitals.")
+ user.visible_message("[user] has analyzed [M]'s vitals."," You have analyzed [M]'s vitals.")
- if (!istype(M, /mob/living/carbon) || (ishuman(M) && (M:species.flags & IS_SYNTHETIC)))
+ if (!istype(M,/mob/living/carbon/human) || M.isSynthetic())
//these sensors are designed for organic life
user.show_message("\blue Analyzing Results for ERROR:\n\t Overall Status: ERROR")
user.show_message("\t Key: Suffocation/Toxin/Burns/Brute", 1)
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index fd8963f9b02..79cbe026503 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -66,6 +66,7 @@
name = "torso"
desc = "A heavily reinforced case containing cyborg logic boards, with space for a standard power cell."
icon_state = "chest"
+ part = list("groin","chest")
construction_time = 350
construction_cost = list("metal"=40000)
var/wires = 0.0
@@ -75,6 +76,7 @@
name = "head"
desc = "A standard reinforced braincase, with spine-plugged neural socket and sensor gimbals."
icon_state = "head"
+ part = list("head")
construction_time = 350
construction_cost = list("metal"=5000)
var/obj/item/device/flash/flash1 = null
diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm
index 8e34085d48b..7e49a4465b9 100644
--- a/code/game/objects/items/weapons/dna_injector.dm
+++ b/code/game/objects/items/weapons/dna_injector.dm
@@ -95,7 +95,7 @@
/obj/item/weapon/dnainjector/attack(mob/M as mob, mob/user as mob)
if(ishuman(M)) // Would've done this via species instead of type, but the basic mob doesn't have a species, go figure.
var/mob/living/carbon/human/H = M
- if(H.species.flags & IS_SYNTHETIC)
+ if(H.species.flags & NO_DNA_RAD)
return
if (!usr.IsAdvancedToolUser())
return
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 2d2be9fe495..c964dd1e0b4 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -369,7 +369,8 @@ the implant may become unstable and either pre-maturely inject the subject or si
if(M == user)
user << "Making yourself loyal to yourself was a great idea! Perhaps even the best idea ever! Actually, you just feel like an idiot."
if(isliving(user))
- user:brainloss += 20
+ var/mob/living/L = user
+ L.adjustBrainLoss(20)
return
if(locate(/obj/item/weapon/implant/loyalty) in H.contents)
H.visible_message("[H] seems to resist the implant!", "You feel a strange sensation in your head that quickly dissipates.")
diff --git a/code/game/objects/items/weapons/shards.dm b/code/game/objects/items/weapons/shards.dm
index bc7c6dca09a..d73281a46ed 100644
--- a/code/game/objects/items/weapons/shards.dm
+++ b/code/game/objects/items/weapons/shards.dm
@@ -62,9 +62,6 @@
if(ishuman(M))
var/mob/living/carbon/human/H = M
- if(H.species.flags & IS_SYNTHETIC)
- return
-
if( !H.shoes && ( !H.wear_suit || !(H.wear_suit.body_parts_covered & FEET) ) )
var/obj/item/organ/external/affecting = H.get_organ(pick("l_foot", "r_foot"))
if(!affecting)
diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm
index 4d3563b1ba6..a71b1c76df4 100644
--- a/code/game/objects/items/weapons/tools.dm
+++ b/code/game/objects/items/weapons/tools.dm
@@ -84,7 +84,8 @@
return
/obj/item/weapon/screwdriver/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
- if(!istype(M)) return ..()
+ if(!istype(M) || user.a_intent == "help")
+ return ..()
if(user.zone_sel.selecting != "eyes" && user.zone_sel.selecting != "head")
return ..()
if((CLUMSY in user.mutations) && prob(50))
@@ -307,7 +308,7 @@
/obj/item/weapon/weldingtool/proc/setWelding(var/temp_welding)
//If we're turning it on
if(temp_welding > 0)
- if (remove_fuel(1))
+ if (get_fuel() > 0)
usr << "\blue The [src] switches on."
src.force = 15
src.damtype = "fire"
@@ -370,8 +371,6 @@
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
var/obj/item/organ/eyes/E = H.internal_organs_by_name["eyes"]
- if(H.species.flags & IS_SYNTHETIC)
- return
if(!E) // No eyes? No problem!
return
switch(safety)
@@ -475,37 +474,29 @@
icon_state = "crowbar_large"
/obj/item/weapon/weldingtool/attack(mob/M as mob, mob/user as mob)
- if(hasorgans(M))
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ var/obj/item/organ/external/S = H.organs_by_name[user.zone_sel.selecting]
- var/obj/item/organ/external/S = M:organs_by_name[user.zone_sel.selecting]
-
- if (!S) return
- if(!(S.status & ORGAN_ROBOT) || user.a_intent != "help")
+ if (!S)
+ return
+ if(!(S.status & ORGAN_ROBOT) || user.a_intent != "help" || S.open == 2)
return ..()
- if(istype(M,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- if(H.species.flags & IS_SYNTHETIC)
- if(M == user)
- user << "\red You can't repair damage to your own body - it's against OH&S."
- return
-
if(S.brute_dam)
- var/obj/item/weapon/weldingtool/WT = src
- if (WT.remove_fuel(0,null))
- playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
- S.heal_damage(15,0,0,1)
- user.visible_message("\red \The [user] patches some dents on \the [M]'s [S.name] with \the [src].")
- if(istype(M,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- H.updatehealth()
- return
+ if(S.brute_dam < ROBOLIMB_SELF_REPAIR_CAP)
+ if (remove_fuel(0,null))
+ playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
+ S.heal_damage(15,0,0,1)
+ user.visible_message("\The [user] patches some dents on \the [M]'s [S.name] with \the [src].")
+ else if(S.open != 2)
+ user << "Need more welding fuel!"
+ return 1
else
- user << "\red You need more welding fuel to complete this task."
- return
- else
- user << "Nothing to fix!"
- return
+ user << "The damage is far too severe to patch over externally."
+ return 1
+ else if(S.open != 2)
+ user << "Nothing to fix!"
else
return ..()
diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm
index d22c1338c38..2018558a055 100644
--- a/code/modules/events/radiation_storm.dm
+++ b/code/modules/events/radiation_storm.dm
@@ -39,7 +39,7 @@
for(var/i = 0, i < 10, i++)
for(var/mob/living/carbon/human/H in living_mob_list)
- if(H.species.flags & IS_SYNTHETIC) // Leave synthetics completely unaffected
+ if(H.species.flags & NO_DNA_RAD) // Leave synthetics completely unaffected
continue
var/turf/T = get_turf(H)
if(!T)
diff --git a/code/modules/events/tgevents/mass_hallucination.dm b/code/modules/events/tgevents/mass_hallucination.dm
index f23a2c15510..ffb6909aec2 100644
--- a/code/modules/events/tgevents/mass_hallucination.dm
+++ b/code/modules/events/tgevents/mass_hallucination.dm
@@ -3,7 +3,7 @@
/datum/event/mass_hallucination/start()
for(var/mob/living/carbon/human/C in living_mob_list)
- if(!(C.species.flags & IS_SYNTHETIC))
+ if(!(C.species.flags & NO_DNA_RAD))
C.hallucination += rand(50, 100)
/datum/event/mass_hallucination/announce()
command_announcement.Announce("It seems that station [station_name()] is passing through a minor radiation field, this may cause some hallucination, but no further damage")
\ No newline at end of file
diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm
index a6d44fa768b..4b5fc980d2c 100644
--- a/code/modules/mob/language.dm
+++ b/code/modules/mob/language.dm
@@ -246,6 +246,13 @@
key = "5"
flags = RESTRICTED | WHITELISTED
syllables = list("02011","01222","10100","10210","21012","02011","21200","1002","2001","0002","0012","0012","000","120","121","201","220","10","11","0")
+
+/datum/language/machine/get_random_name()
+ if(prob(70))
+ name = "[pick(list("PBU","HIU","SINA","ARMA","OSI"))]-[rand(100, 999)]"
+ else
+ name = pick(ai_names)
+ return name
/datum/language/kidan
name = "Chittin"
diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm
index d039311fe53..4c36d82202a 100644
--- a/code/modules/mob/living/carbon/alien/special/facehugger.dm
+++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm
@@ -169,9 +169,9 @@ var/const/MAX_ACTIVE_TIME = 400
if(ishuman(target))
var/mob/living/carbon/human/H = target
- if((H.species.flags & IS_SYNTHETIC))
+ if(!H.check_has_mouth())
return
-
+
if(!sterile)
//target.contract_disease(new /datum/disease/alien_embryo(0)) //so infection chance is same as virus infection chance
target.visible_message("[src] falls limp after violating [target]'s face!", \
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index 721bf0fa6a8..a9cf1ea1094 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -5,7 +5,7 @@
canmove = 0
icon = null
invisibility = 101
- if(!(species.flags & IS_SYNTHETIC))
+ if(!isSynthetic())
animation = new(loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
@@ -27,7 +27,7 @@
// Override the current limb status and don't cause an explosion
E.droplimb(DROPLIMB_EDGE)
- if(!(species.flags & IS_SYNTHETIC))
+ if(!isSynthetic())
flick("gibbed-h", animation)
hgibs(loc, viruses, dna)
else
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index c0c11aa1aa7..c951a0a88ca 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -283,7 +283,7 @@
if(temp && !temp.is_stump())
if(temp.status & ORGAN_ROBOT)
if(!(temp.brute_dam + temp.burn_dam))
- if(!(species.flags & IS_SYNTHETIC))
+ if(!isSynthetic())
wound_flavor_text["[temp.limb_name]"] = "[t_He] has a robotic [temp.name]!\n"
continue
else
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 68b4a936d3c..5ae42000949 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1130,26 +1130,47 @@
return
/mob/living/carbon/human/can_inject(var/mob/user, var/error_msg, var/target_zone)
- . = 1 // Default to returning true.
- if(user && !target_zone)
- target_zone = user.zone_sel.selecting
- // If targeting the head, see if the head item is thin enough.
- // If targeting anything else, see if the wear suit is thin enough.
- if(above_neck(target_zone))
- if(head && head.flags & THICKMATERIAL)
- . = 0
+ . = 1
+
+ if(!target_zone)
+ if(!user)
+ target_zone = pick("chest","chest","chest","left leg","right leg","left arm", "right arm", "head")
+ else
+ target_zone = user.zone_sel.selecting
+
+ var/obj/item/organ/external/affecting = get_organ(target_zone)
+ var/fail_msg
+ if(!affecting)
+ . = 0
+ fail_msg = "They are missing that limb."
+ else if (affecting.status & ORGAN_ROBOT)
+ . = 0
+ fail_msg = "That limb is robotic."
else
- if(wear_suit && wear_suit.flags & THICKMATERIAL)
- . = 0
+ switch(target_zone)
+ if("head")
+ if(head && head.flags & THICKMATERIAL)
+ . = 0
+ else
+ if(wear_suit && wear_suit.flags & THICKMATERIAL)
+ . = 0
if(!. && error_msg && user)
- // Might need re-wording.
- user << "There is no exposed flesh or thin material [target_zone == "head" ? "on their head" : "on their body"]."
+ if(!fail_msg)
+ fail_msg = "There is no exposed flesh or thin material [target_zone == "head" ? "on their head" : "on their body"] to inject into."
+ user << "[fail_msg]"
+
+/mob/living/carbon/human/proc/check_has_mouth()
+ // Todo, check stomach organ when implemented.
+ var/obj/item/organ/external/head/H = get_organ("head")
+ if(!H || !H.can_intake_reagents)
+ return 0
+ return 1
/mob/living/carbon/human/proc/vomit(hairball=0)
- if(stat==2)return
+ if(stat==DEAD)return
- if(species.flags & IS_SYNTHETIC)
- return //Machines don't throw up.
+ if(!check_has_mouth())
+ return
if(!lastpuke)
lastpuke = 1
diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm
index fc9b52de47e..fe466cb1c74 100644
--- a/code/modules/mob/living/carbon/human/human_attackhand.dm
+++ b/code/modules/mob/living/carbon/human/human_attackhand.dm
@@ -63,13 +63,17 @@
help_shake_act(M)
add_logs(src, M, "shaked")
return 1
-// if(M.health < -75) return 0
-
+ if(!H.check_has_mouth())
+ H << "You don't have a mouth, you cannot perform CPR!"
+ return
+ if(!check_has_mouth())
+ H << "They don't have a mouth, you cannot perform CPR!"
+ return
if((M.head && (M.head.flags & HEADCOVERSMOUTH)) || (M.wear_mask && (M.wear_mask.flags & MASKCOVERSMOUTH) && !M.wear_mask.mask_adjusted))
- M << "Remove your mask!"
+ M << "Remove your mask!"
return 0
if((head && (head.flags & HEADCOVERSMOUTH)) || (wear_mask && (wear_mask.flags & MASKCOVERSMOUTH) && !wear_mask.mask_adjusted))
- M << "Remove his mask!"
+ M << "Remove his mask!"
return 0
var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human()
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index d72cef8de63..dcb1ee4e50c 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -11,13 +11,8 @@
total_burn += O.burn_dam
health = 100 - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
//TODO: fix husking
- if( (((100 - total_burn) < config.health_threshold_dead) && stat == DEAD) && (!(species.flags & IS_SYNTHETIC)))//100 only being used as the magic human max health number, feel free to change it if you add a var for it -- Urist
+ if( (((100 - total_burn) < config.health_threshold_dead) && stat == DEAD))//100 only being used as the magic human max health number, feel free to change it if you add a var for it -- Urist
ChangeToHusk()
- if (species.flags & IS_SYNTHETIC)
- var/obj/item/organ/external/head/H = organs_by_name["head"]
- if(H)
- if((health >= (config.health_threshold_dead/100*75)) && stat == DEAD) //need to get them 25% away from death point before reviving synthetics
- update_revive()
if (stat == CONSCIOUS && (src in dead_mob_list)) //Defib fix
update_revive()
return
@@ -31,17 +26,45 @@
tod = 0
timeofdeath = 0
+/mob/living/carbon/human/adjustBrainLoss(var/amount)
+ if(status_flags & GODMODE) return 0 //godmode
+
+ if(species && species.has_organ["brain"])
+ var/obj/item/organ/brain/sponge = internal_organs_by_name["brain"]
+ if(sponge)
+ sponge.take_damage(amount)
+ sponge.damage = min(max(sponge.damage, 0),(maxHealth*2))
+ brainloss = sponge.damage
+ else
+ brainloss = 200
+ else
+ brainloss = 0
+
+/mob/living/carbon/human/setBrainLoss(var/amount)
+ if(status_flags & GODMODE) return 0 //godmode
+
+ if(species && species.has_organ["brain"])
+ var/obj/item/organ/brain/sponge = internal_organs_by_name["brain"]
+ if(sponge)
+ sponge.damage = min(max(amount, 0),(maxHealth*2))
+ brainloss = sponge.damage
+ else
+ brainloss = 200
+ else
+ brainloss = 0
+
/mob/living/carbon/human/getBrainLoss()
- var/res = brainloss
- var/obj/item/organ/brain/sponge = internal_organs_by_name["brain"]
- if(!sponge)
- return
- if (sponge.is_bruised())
- res += 20
- if (sponge.is_broken())
- res += 50
- res = min(res,maxHealth*2)
- return res
+ if(status_flags & GODMODE) return 0 //godmode
+
+ if(species && species.has_organ["brain"])
+ var/obj/item/organ/brain/sponge = internal_organs_by_name["brain"]
+ if(sponge)
+ brainloss = min(sponge.damage,maxHealth*2)
+ else
+ brainloss = 200
+ else
+ brainloss = 0
+ return brainloss
//These procs fetch a cumulative total damage from all organs
/mob/living/carbon/human/getBruteLoss()
@@ -114,13 +137,12 @@
/mob/living/carbon/human/Paralyse(amount)
..()
-
/mob/living/carbon/human/adjustCloneLoss(var/amount)
-
- if(species.flags & IS_SYNTHETIC)
- return
-
..()
+
+ if(species.flags & (NO_SCAN))
+ cloneloss = 0
+ return
var/heal_prob = max(0, 80 - getCloneLoss())
var/mut_prob = min(80, getCloneLoss()+10)
@@ -151,6 +173,41 @@
O.unmutate()
src << "Your [O.name] is shaped normally again."
hud_updateflag |= 1 << HEALTH_HUD
+
+// Defined here solely to take species flags into account without having to recast at mob/living level.
+/mob/living/carbon/human/getOxyLoss()
+ if(species.flags & NO_BREATHE)
+ oxyloss = 0
+ return ..()
+
+/mob/living/carbon/human/adjustOxyLoss(var/amount)
+ if(species.flags & NO_BREATHE)
+ oxyloss = 0
+ else
+ ..()
+
+/mob/living/carbon/human/setOxyLoss(var/amount)
+ if(species.flags & NO_BREATHE)
+ oxyloss = 0
+ else
+ ..()
+
+/mob/living/carbon/human/getToxLoss()
+ if(species.flags & NO_POISON)
+ toxloss = 0
+ return ..()
+
+/mob/living/carbon/human/adjustToxLoss(var/amount)
+ if(species.flags & NO_POISON)
+ toxloss = 0
+ else
+ ..()
+
+/mob/living/carbon/human/setToxLoss(var/amount)
+ if(species.flags & NO_POISON)
+ toxloss = 0
+ else
+ ..()
////////////////////////////////////////////
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 21b554bde94..036dcc78803 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -35,13 +35,13 @@ emp_act
if(check_shields(P.damage, "the [P.name]", P))
P.on_hit(src, 100, def_zone)
return 2
-
+
+ var/obj/item/organ/external/organ = get_organ(check_zone(def_zone))
+ if(isnull(organ))
+ return
//Shrapnel
if (P.damage_type == BRUTE)
- var/obj/item/organ/external/organ = get_organ(check_zone(def_zone))
- if(!organ)
- return
var/armor = getarmor_organ(organ, "bullet")
if((P.embed && prob(20 + max(P.damage - armor, -10))))
var/obj/item/weapon/shard/shrapnel/SP = new()
@@ -50,9 +50,7 @@ emp_act
(SP.loc) = organ
organ.embed(SP)
- var/mob/living/carbon/human/M = src
- var/obj/item/organ/external/affected = M.get_organ(def_zone)
- affected.add_autopsy_data(P.name, P.damage) // Add the bullet's name to the autopsy data
+ organ.add_autopsy_data(P.name, P.damage) // Add the bullet's name to the autopsy data
return (..(P , def_zone))
@@ -204,11 +202,6 @@ emp_act
for(var/obj/O in src)
if(!O) continue
O.emp_act(severity)
- for(var/obj/item/organ/external/O in organs)
- if(O.status & ORGAN_DESTROYED) continue
- O.emp_act(severity)
- for(var/obj/item/organ/I in O.internal_organs)
- I.emp_act(severity)
..()
/mob/living/carbon/human/emag_act(user as mob, var/obj/item/organ/external/affecting)
diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm
index 193f8373242..8889e5370da 100644
--- a/code/modules/mob/living/carbon/human/human_organs.dm
+++ b/code/modules/mob/living/carbon/human/human_organs.dm
@@ -72,11 +72,9 @@
for(var/limb_tag in list("l_leg","r_leg","l_foot","r_foot"))
var/obj/item/organ/external/E = organs_by_name[limb_tag]
- if(!E)
- stance_damage += 2
- else if (E.status & ORGAN_DESTROYED)
- stance_damage += 2 // let it fail even if just foot&leg
- else if (E.is_malfunctioning() || (E.is_broken() && !(E.status & ORGAN_SPLINTED)) || !E.is_usable())
+ if(!E || (E.status & (ORGAN_DESTROYED|ORGAN_DEAD)) || E.is_malfunctioning())
+ stance_damage += 2 // let it fail even if just foot&leg. Also malfunctioning happens sporadically so it should impact more when it procs
+ else if (E.is_broken() || !E.is_usable())
stance_damage += 1
// Canes and crutches help you stand (if the latter is ever added)
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index bc0504f29c9..507c8dab0ca 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -56,7 +56,7 @@
/mob/living/carbon/human/proc/has_organ(name)
var/obj/item/organ/external/O = organs_by_name[name]
- return (O && !(O.status & ORGAN_DESTROYED) )
+ return (O && !(O.status & ORGAN_DESTROYED) && !O.is_stump())
/mob/living/carbon/human/proc/has_organ_for_slot(slot)
switch(slot)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index d51d1f9de64..5a0028bb952 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -245,10 +245,6 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
adjustCloneLoss(0.1)
/mob/living/carbon/human/proc/handle_mutations_and_radiation()
-
- if(species.flags & IS_SYNTHETIC) //Robots don't suffer from mutations or radloss.
- return
-
if(getFireLoss())
if((RESIST_HEAT in mutations) || (prob(1)))
heal_organ_damage(0,1)
@@ -847,7 +843,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
if(species && species.flags & NO_INTORGANS) return
- if(!(species.flags & IS_SYNTHETIC)) handle_trace_chems()
+ handle_trace_chems()
updatehealth()
@@ -904,7 +900,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
if(!reagents.has_reagent("epinephrine"))
adjustOxyLoss(1)*/
- if(hallucination && !(species.flags & IS_SYNTHETIC))
+ if(hallucination && !(species.flags & NO_DNA_RAD))
spawn handle_hallucinations()
if(hallucination<=2)
@@ -967,18 +963,35 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
if(!E.len)
embedded_flag = 0
-
- //Eyes
- if(sdisabilities & BLIND) //disabled-blind, doesn't get better on its own
- blinded = 1
- else if(eye_blind) //blindness, heals slowly over time
- eye_blind = max(eye_blind-1,0)
- blinded = 1
- else if(tinttotal >= TINT_BLIND) //covering your eyes heals blurry eyes faster
- eye_blurry = max(eye_blurry-3, 0)
- // blinded = 1 //now handled under /handle_regular_hud_updates()
- else if(eye_blurry) //blurry eyes heal slowly
- eye_blurry = max(eye_blurry-1, 0)
+ //Vision
+ var/obj/item/organ/vision
+ if(species.vision_organ)
+ vision = internal_organs_by_name[species.vision_organ]
+
+ if(!species.vision_organ) // Presumably if a species has no vision organs, they see via some other means.
+ eye_blind = 0
+ blinded = 0
+ eye_blurry = 0
+ else if(!vision || vision.is_broken()) // Vision organs cut out or broken? Permablind.
+ eye_blind = 1
+ blinded = 1
+ eye_blurry = 1
+ else
+ //blindness
+ if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own
+ blinded = 1
+ else if(eye_blind) // Blindness, heals slowly over time
+ eye_blind = max(eye_blind-1,0)
+ blinded = 1
+ else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster
+ eye_blurry = max(eye_blurry-3, 0)
+ blinded = 1
+
+ //blurry sight
+ if(vision.is_bruised()) // Vision organs impaired? Permablurry.
+ eye_blurry = 1
+ if(eye_blurry) // Blurry eyes heal slowly
+ eye_blurry = max(eye_blurry-1, 0)
//Ears
if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own
@@ -1569,7 +1582,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
/mob/living/carbon/human/proc/handle_decay()
var/decaytime = world.time - timeofdeath
- if(species.flags & IS_SYNTHETIC)
+ if(isSynthetic())
return
if(reagents.has_reagent("formaldehyde")) //embalming fluid stops decay
diff --git a/code/modules/mob/living/carbon/human/species/apollo.dm b/code/modules/mob/living/carbon/human/species/apollo.dm
index fa428ac43a2..ccfc7d429ef 100644
--- a/code/modules/mob/living/carbon/human/species/apollo.dm
+++ b/code/modules/mob/living/carbon/human/species/apollo.dm
@@ -1,5 +1,6 @@
/datum/species/wryn
name = "Wryn"
+ name_plural = "Wryn"
icobase = 'icons/mob/human_races/r_wryn.dmi'
deform = 'icons/mob/human_races/r_wryn.dmi'
language = "Wryn Hivemind"
@@ -76,6 +77,7 @@
/datum/species/nucleation
name = "Nucleation"
+ name_plural = "Nucleations"
icobase = 'icons/mob/human_races/r_nucleation.dmi'
unarmed_type = /datum/unarmed_attack/punch
blurb = "A sub-race of unforunates who have been exposed to too much supermatter radiation. As a result, \
diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm
index cfc0eb08207..9c5a9ef851e 100644
--- a/code/modules/mob/living/carbon/human/species/golem.dm
+++ b/code/modules/mob/living/carbon/human/species/golem.dm
@@ -1,5 +1,6 @@
/datum/species/golem
name = "Golem"
+ name_plural = "Golems"
icobase = 'icons/mob/human_races/r_golem.dmi'
deform = 'icons/mob/human_races/r_golem.dmi'
diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm
index 7c3dbd46108..d8487e8d795 100644
--- a/code/modules/mob/living/carbon/human/species/monkey.dm
+++ b/code/modules/mob/living/carbon/human/species/monkey.dm
@@ -1,5 +1,6 @@
/datum/species/monkey
name = "Monkey"
+ name_plural = "Monkeys"
blurb = "Ook."
icobase = 'icons/mob/human_races/monkeys/r_monkey.dmi'
@@ -52,7 +53,8 @@ datum/species/monkey/get_random_name(var/gender)
/datum/species/monkey/tajaran
name = "Farwa"
-
+ name_plural = "Farwa"
+
icobase = 'icons/mob/human_races/monkeys/r_farwa.dmi'
deform = 'icons/mob/human_races/monkeys/r_farwa.dmi'
@@ -66,6 +68,7 @@ datum/species/monkey/get_random_name(var/gender)
/datum/species/monkey/vulpkanin
name = "Wolpin"
+ name_plural = "Wolpin"
icobase = 'icons/mob/human_races/monkeys/r_wolpin.dmi'
deform = 'icons/mob/human_races/monkeys/r_wolpin.dmi'
@@ -80,6 +83,7 @@ datum/species/monkey/get_random_name(var/gender)
/datum/species/monkey/skrell
name = "Neara"
+ name_plural = "Neara"
icobase = 'icons/mob/human_races/monkeys/r_neara.dmi'
deform = 'icons/mob/human_races/monkeys/r_neara.dmi'
@@ -96,6 +100,7 @@ datum/species/monkey/get_random_name(var/gender)
/datum/species/monkey/unathi
name = "Stok"
+ name_plural = "Stok"
icobase = 'icons/mob/human_races/monkeys/r_stok.dmi'
deform = 'icons/mob/human_races/monkeys/r_stok.dmi'
diff --git a/code/modules/mob/living/carbon/human/species/plasmaman.dm b/code/modules/mob/living/carbon/human/species/plasmaman.dm
index 890a5c3102b..5c36ba41bbd 100644
--- a/code/modules/mob/living/carbon/human/species/plasmaman.dm
+++ b/code/modules/mob/living/carbon/human/species/plasmaman.dm
@@ -1,5 +1,6 @@
/datum/species/plasmaman // /vg/
name = "Plasmaman"
+ name_plural = "Plasmamen"
icobase = 'icons/mob/human_races/r_plasmaman_sb.dmi'
deform = 'icons/mob/human_races/r_plasmaman_pb.dmi' // TODO: Need deform.
//language = "Clatter"
diff --git a/code/modules/mob/living/carbon/human/species/shadow.dm b/code/modules/mob/living/carbon/human/species/shadow.dm
index cd0b03fc745..3e888c026f8 100644
--- a/code/modules/mob/living/carbon/human/species/shadow.dm
+++ b/code/modules/mob/living/carbon/human/species/shadow.dm
@@ -1,6 +1,7 @@
/datum/species/shadow
name = "Shadow"
-
+ name_plural = "Shadows"
+
icobase = 'icons/mob/human_races/r_shadow.dmi'
deform = 'icons/mob/human_races/r_shadow.dmi'
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index 5113ea3144e..96d0d89030f 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -4,6 +4,7 @@
/datum/species
var/name // Species name.
+ var/name_plural // Pluralized name (since "[name]s" is not always valid)
var/path // Species path
var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set.
var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set.
@@ -37,7 +38,7 @@
var/heat_level_3_breathe = 1000 // Heat damage level 3 above this point; used for breathed air temperature
var/body_temperature = 310.15 //non-IS_SYNTHETIC species will try to stabilize at this temperature. (also affects temperature processing)
- var/synth_temp_gain = 0 //IS_SYNTHETIC species will gain this much temperature every second
+ var/passive_temp_gain = 0 //IS_SYNTHETIC species will gain this much temperature every second
var/reagent_tag //Used for metabolizing reagents.
var/darksight = 2
@@ -78,6 +79,7 @@
var/icon/icon_template
var/is_small
var/show_ssd = 1
+ var/virus_immune
// Language/culture vars.
var/default_language = "Galactic Common" // Default language is used when 'say' is used without modifiers.
@@ -95,8 +97,8 @@
"brain" = /obj/item/organ/brain,
"appendix" = /obj/item/organ/appendix,
"eyes" = /obj/item/organ/eyes
- )
-
+ )
+ var/vision_organ // If set, this organ is required for vision. Defaults to "eyes" if the species has them.
var/list/has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/chest),
"groin" = list("path" = /obj/item/organ/external/groin),
@@ -112,6 +114,10 @@
)
/datum/species/New()
+ //If the species has eyes, they are the default vision organ
+ if(!vision_organ && has_organ["eyes"])
+ vision_organ = "eyes"
+
unarmed = new unarmed_type()
/datum/species/proc/get_random_name(var/gender)
@@ -150,14 +156,6 @@
for(var/obj/item/organ/external/O in H.organs)
O.owner = H
- if(flags & IS_SYNTHETIC)
- for(var/obj/item/organ/external/E in H.organs)
- if(E.status & ORGAN_CUT_AWAY || E.status & ORGAN_DESTROYED) continue
- E.robotize()
- for(var/obj/item/organ/I in H.internal_organs)
- I.robotize()
-
-
/datum/species/proc/handle_breath(var/datum/gas_mixture/breath, var/mob/living/carbon/human/H)
var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa
//var/safe_oxygen_max = 140 // Maximum safe partial pressure of O2, in kPa (Not used for now)
diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm
index 01f4c13a549..5cb414f1bd4 100644
--- a/code/modules/mob/living/carbon/human/species/station.dm
+++ b/code/modules/mob/living/carbon/human/species/station.dm
@@ -1,5 +1,6 @@
/datum/species/human
name = "Human"
+ name_plural = "Humans"
icobase = 'icons/mob/human_races/r_human.dmi'
deform = 'icons/mob/human_races/r_def_human.dmi'
primitive_form = "Monkey"
@@ -19,6 +20,7 @@
/datum/species/unathi
name = "Unathi"
+ name_plural = "Unathi"
icobase = 'icons/mob/human_races/r_lizard.dmi'
deform = 'icons/mob/human_races/r_def_lizard.dmi'
path = /mob/living/carbon/human/unathi
@@ -59,6 +61,7 @@
/datum/species/tajaran
name = "Tajaran"
+ name_plural = "Tajaran"
icobase = 'icons/mob/human_races/r_tajaran.dmi'
deform = 'icons/mob/human_races/r_def_tajaran.dmi'
path = /mob/living/carbon/human/tajaran
@@ -99,6 +102,7 @@
/datum/species/vulpkanin
name = "Vulpkanin"
+ name_plural = "Vulpakanin"
icobase = 'icons/mob/human_races/r_vulpkanin.dmi'
deform = 'icons/mob/human_races/r_vulpkanin.dmi'
path = /mob/living/carbon/human/vulpkanin
@@ -129,6 +133,7 @@
/datum/species/skrell
name = "Skrell"
+ name_plural = "Skrell"
icobase = 'icons/mob/human_races/r_skrell.dmi'
deform = 'icons/mob/human_races/r_def_skrell.dmi'
path = /mob/living/carbon/human/skrell
@@ -153,6 +158,7 @@
/datum/species/vox
name = "Vox"
+ name_plural = "Vox"
icobase = 'icons/mob/human_races/r_vox.dmi'
deform = 'icons/mob/human_races/r_def_vox.dmi'
path = /mob/living/carbon/human/vox
@@ -213,6 +219,7 @@
/datum/species/vox/armalis
name = "Vox Armalis"
+ name_plural = "Vox Armalis"
icobase = 'icons/mob/human_races/r_armalis.dmi'
deform = 'icons/mob/human_races/r_armalis.dmi'
path = /mob/living/carbon/human/voxarmalis
@@ -260,6 +267,7 @@
/datum/species/kidan
name = "Kidan"
+ name_plural = "Kidan"
icobase = 'icons/mob/human_races/r_kidan.dmi'
deform = 'icons/mob/human_races/r_def_kidan.dmi'
path = /mob/living/carbon/human/kidan
@@ -278,6 +286,7 @@
/datum/species/slime
name = "Slime People"
+ name_plural = "Slime People"
default_language = "Galactic Common"
language = "Bubblish"
icobase = 'icons/mob/human_races/r_slime.dmi'
@@ -299,6 +308,7 @@
/datum/species/grey
name = "Grey"
+ name_plural = "Greys"
icobase = 'icons/mob/human_races/r_grey.dmi'
deform = 'icons/mob/human_races/r_def_grey.dmi'
default_language = "Galactic Common"
@@ -332,6 +342,7 @@
/datum/species/diona
name = "Diona"
+ name_plural = "Dionaea"
icobase = 'icons/mob/human_races/r_diona.dmi'
deform = 'icons/mob/human_races/r_def_plant.dmi'
path = /mob/living/carbon/human/diona
@@ -421,17 +432,25 @@
else
del(D)
- H.visible_message("\red[H] splits apart with a wet slithering noise!") */
+ H.visible_message("= 60) && prob(50))
- user << text("\red You try to analyze the floor's vitals!")
- for(var/mob/O in viewers(M, null))
- O.show_message(text("\red [user] has analyzed the floor's vitals!"), 1)
- user.show_message(text("\blue Analyzing Results for The floor:\n\t Overall Status: Healthy"), 1)
- user.show_message(text("\blue \t Damage Specifics: [0]-[0]-[0]-[0]"), 1)
- user.show_message("\blue Key: Suffocation/Toxin/Burns/Brute", 1)
- user.show_message("\blue Body Temperature: ???", 1)
+ user.visible_message("[user] has analyzed the floor's vitals!", "You try to analyze the floor's vitals!")
+ user << "Analyzing Results for The floor:\n\t Overall Status: Healthy"
+ user << "\t Damage Specifics: [0]-[0]-[0]-[0]"
+ user << "Key: Suffocation/Toxin/Burns/Brute"
+ user << "Body Temperature: ???"
return
- if(!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
- user << "\red You don't have the dexterity to do this!"
- return
- if(!istype(M, /mob/living/silicon/robot) && !(ishuman(M) && (M:species.flags & IS_SYNTHETIC)))
- user << "\red You can't analyze non-robotic things!"
- return
-
- user.visible_message(" [user] has analyzed [M]'s components."," You have analyzed [M]'s components.")
- var/BU = M.getFireLoss() > 50 ? "[M.getFireLoss()]" : M.getFireLoss()
- var/BR = M.getBruteLoss() > 50 ? "[M.getBruteLoss()]" : M.getBruteLoss()
- var/TX = M.getToxLoss() > 50 ? "[M.getToxLoss()]" : M.getToxLoss()
-
- user.show_message("\blue Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "fully disabled" : "[M.health - M.halloss]% functional"]")
- if (ishuman(M) && (M:species.flags & IS_SYNTHETIC))
- user.show_message("\t Key: Electronics/Brute/Residue", 1)
- user.show_message("\t Damage Specifics: [BU] - [BR] - [TX]")
+
+ var/scan_type
+ if(istype(M, /mob/living/silicon/robot))
+ scan_type = "robot"
+ else if(istype(M, /mob/living/carbon/human))
+ scan_type = "prosthetics"
else
- user.show_message("\t Key: Electronics/Brute", 1)
- user.show_message("\t Damage Specifics: [BU] - [BR]")
- if(M.tod && M.stat == DEAD)
- user.show_message("\blue Time of Disable: [M.tod]")
+ user << "You can't analyze non-robotic things!"
+ return
- if (istype(M, /mob/living/silicon/robot))
- var/mob/living/silicon/robot/H = M
- var/list/damaged = H.get_damaged_components(1,1,1)
- user.show_message("\blue Localized Damage:",1)
- if(length(damaged)>0)
- for(var/datum/robot_component/org in damaged)
- user.show_message(text("\blue \t []: [][] - [] - [] - []", \
- capitalize(org.name), \
- (org.installed == -1) ? "DESTROYED " :"",\
- (org.electronics_damage > 0) ? "[org.electronics_damage]" :0, \
- (org.brute_damage > 0) ? "[org.brute_damage]" :0, \
- (org.toggled) ? "Toggled ON" : "Toggled OFF",\
- (org.powered) ? "Power ON" : "Power OFF"),1)
- else
- user.show_message("\blue \t Components are OK.",1)
- if(H.emagged && prob(5))
- user.show_message("\red \t ERROR: INTERNAL SYSTEMS COMPROMISED",1)
+ user.visible_message("[user] has analyzed [M]'s components.","You have analyzed [M]'s components.")
+ switch(scan_type)
+ if("robot")
+ var/BU = M.getFireLoss() > 50 ? "[M.getFireLoss()]" : M.getFireLoss()
+ var/BR = M.getBruteLoss() > 50 ? "[M.getBruteLoss()]" : M.getBruteLoss()
+ user << "Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "fully disabled" : "[M.health - M.halloss]% functional"]"
+ user << "\t Key: Electronics/Brute"
+ user << "\t Damage Specifics: [BU] - [BR]"
+ if(M.tod && M.stat == DEAD)
+ user << "Time of Disable: [M.tod]"
+ var/mob/living/silicon/robot/H = M
+ var/list/damaged = H.get_damaged_components(1,1,1)
+ user << "Localized Damage:"
+ if(length(damaged)>0)
+ for(var/datum/robot_component/org in damaged)
+ user.show_message(text("\t []: [][] - [] - [] - []", \
+ capitalize(org.name), \
+ (org.installed == -1) ? "DESTROYED " :"",\
+ (org.electronics_damage > 0) ? "[org.electronics_damage]" :0, \
+ (org.brute_damage > 0) ? "[org.brute_damage]" :0, \
+ (org.toggled) ? "Toggled ON" : "Toggled OFF",\
+ (org.powered) ? "Power ON" : "Power OFF"),1)
+ else
+ user << "\t Components are OK."
+ if(H.emagged && prob(5))
+ user << "\t ERROR: INTERNAL SYSTEMS COMPROMISED"
- if (ishuman(M) && (M:species.flags & IS_SYNTHETIC))
- var/mob/living/carbon/human/H = M
- var/list/damaged = H.get_damaged_organs(1,1)
- user.show_message("\blue Localized Damage, Brute/Electronics:",1)
- if(length(damaged)>0)
- for(var/obj/item/organ/external/org in damaged)
- user.show_message(text("\blue \t []: [] - []", \
- capitalize(org.name), \
- (org.brute_dam > 0) ? "\red [org.brute_dam]" :0, \
- (org.burn_dam > 0) ? "[org.burn_dam]" :0),1)
- else
- user.show_message("\blue \t Components are OK.",1)
- if (M.getBrainLoss() >= 100 || istype(M, /mob/living/carbon/human) && M:brain_op_stage == 4.0)
- user.show_message("\red Subject posibrain is unresponsive. System shutdown imminent.")
- else if (M.getBrainLoss() >= 60)
- user.show_message("\red Severe posibrain damage detected. Heavy corrosion present.")
- else if (M.getBrainLoss() >= 10)
- user.show_message("\red Significant posibrain damage detected. Moderate corrosion present.")
-
- user.show_message("\blue Operating Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1)
+ if("prosthetics")
+ var/mob/living/carbon/human/H = M
+ user << "Analyzing Results for \the [H]:"
+ user << "Key: Electronics/Brute"
+ user << "External prosthetics:"
+ var/organ_found
+ if(H.internal_organs.len)
+ for(var/obj/item/organ/external/E in H.organs)
+ if(!(E.status & ORGAN_ROBOT))
+ continue
+ organ_found = 1
+ user << "[E.name]: [round(E.brute_dam)] [round(E.burn_dam)]"
+ if(!organ_found)
+ user << "No prosthetics located."
+ user << "
"
+ user << "Internal prosthetics:"
+ organ_found = null
+ if(H.internal_organs.len)
+ for(var/obj/item/organ/O in H.internal_organs)
+ if(!(O.status & ORGAN_ROBOT))
+ continue
+ organ_found = 1
+ user << "[capitalize(O.name)]: [O.damage]"
+ if(!organ_found)
+ user << "No prosthetics located."
+
src.add_fingerprint(user)
- return
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 0a18501ee01..c55cd5a7bbf 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -542,13 +542,6 @@ var/list/robot_verbs_default = list(
return
now_pushing = 0
..()
- if (istype(AM, /obj/machinery/recharge_station))
- var/obj/machinery/recharge_station/F = AM
- if(F.panel_open)
- usr << "\blue Close the maintenance panel first."
- return
- else
- F.move_inside()
if (!istype(AM, /atom/movable))
return
if (!now_pushing)
@@ -587,34 +580,35 @@ var/list/robot_verbs_default = list(
return
- if (istype(W, /obj/item/weapon/weldingtool))
- if(W == module_active) return
+ if (istype(W, /obj/item/weapon/weldingtool) && user.a_intent == "help")
+ if(W == module_active)
+ return
if (!getBruteLoss())
- user << "Nothing to fix here!"
+ user << "Nothing to fix!"
return
var/obj/item/weapon/weldingtool/WT = W
user.changeNext_move(CLICK_CD_MELEE)
if (WT.remove_fuel(0))
+ playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
adjustBruteLoss(-30)
updatehealth()
add_fingerprint(user)
- for(var/mob/O in viewers(user, null))
- O.show_message(text("\red [user] has fixed some of the dents on [src]!"), 1)
+ user.visible_message("\The [user] patches some dents on \the [src] with \the [WT].")
else
- user << "Need more welding fuel!"
+ user << "Need more welding fuel!"
return
- else if(istype(W, /obj/item/stack/cable_coil) && (wiresexposed || istype(src,/mob/living/silicon/robot/drone)))
+ else if(istype(W, /obj/item/stack/cable_coil) && user.a_intent == "help" && (wiresexposed || istype(src,/mob/living/silicon/robot/drone)))
if (!getFireLoss())
- user << "Nothing to fix here!"
+ user << "Nothing to fix!"
return
var/obj/item/stack/cable_coil/coil = W
adjustFireLoss(-30)
updatehealth()
+ add_fingerprint(user)
coil.use(1)
- for(var/mob/O in viewers(user, null))
- O.show_message(text("\red [user] has fixed some of the burnt wires on [src]!"), 1)
+ user.visible_message("\The [user] fixes some of the burnt wires on \the [src] with \the [coil].")
else if (istype(W, /obj/item/weapon/crowbar)) // crowbar means open or close the cover
if(opened)
diff --git a/code/modules/mob/living/simple_animal/borer.dm b/code/modules/mob/living/simple_animal/borer.dm
index 0397fee8924..8ab01f44ab1 100644
--- a/code/modules/mob/living/simple_animal/borer.dm
+++ b/code/modules/mob/living/simple_animal/borer.dm
@@ -96,7 +96,7 @@
if(prob(5))
host.adjustBrainLoss(rand(1,2))
- if(prob(host.brainloss/20))
+ if(prob(host.getBrainLoss()/20))
host.say("*[pick(list("blink","blink_r","choke","aflap","drool","twitch","twitch_s","gasp"))]")
/mob/living/simple_animal/borer/New(var/by_gamemode=0)
@@ -148,7 +148,7 @@
var/list/choices = list()
for(var/mob/living/carbon/C in view(3,src))
- if(C.stat != 2)
+ if(C.stat != DEAD)
choices += C
if(world.time - used_dominate < 300)
@@ -188,7 +188,7 @@
src << "You begin delicately adjusting your connection to the host brain..."
- spawn(300+(host.brainloss*5))
+ spawn(300+(host.getBrainLoss()*5))
if(!host || !src || controlling)
return
@@ -387,11 +387,14 @@ mob/living/simple_animal/borer/proc/detatch()
return
var/list/choices = list()
- for(var/mob/living/carbon/C in view(1,src))
- if(C.stat != 2 && src.Adjacent(C))
- choices += C
+ for(var/mob/living/carbon/human/H in view(1,src))
+ var/obj/item/organ/external/head/head = H.get_organ("head")
+ if(head.status & ORGAN_ROBOT)
+ continue
+ if(H.stat != DEAD && src.Adjacent(H) && !H.has_brain_worms())
+ choices += H
- var/mob/living/carbon/M = input(src,"Who do you wish to infest?") in null|choices
+ var/mob/living/carbon/human/M = input(src,"Who do you wish to infest?") in null|choices
if(!M || !src) return
@@ -400,13 +403,6 @@ mob/living/simple_animal/borer/proc/detatch()
if(M.has_brain_worms())
src << "You cannot infest someone who is already infested!"
return
-/*
- if(istype(M,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- if(H.check_head_coverage())
- src << "You cannot get through that host's protective gear."
- return
-*/
src << "You slither up [M] and begin probing at their ear canal..."
diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm
index 65f6c6242ed..b13714ae552 100644
--- a/code/modules/mob/living/simple_animal/friendly/cat.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cat.dm
@@ -90,7 +90,7 @@
icon_dead = "Syndicat_dead"
icon_resting = "Syndicat_rest"
gender = FEMALE
- flags = IS_SYNTHETIC|NO_BREATHE
+ flags = NO_BREATHE
faction = list("syndicate")
var/turns_since_scan = 0
var/mob/living/simple_animal/mouse/movement_target
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/friendly/fox.dm b/code/modules/mob/living/simple_animal/friendly/fox.dm
index aa644b00d91..38d79141803 100644
--- a/code/modules/mob/living/simple_animal/friendly/fox.dm
+++ b/code/modules/mob/living/simple_animal/friendly/fox.dm
@@ -31,5 +31,5 @@
icon_living = "Syndifox"
icon_dead = "Syndifox_dead"
icon_resting = "Syndifox_rest"
- flags = IS_SYNTHETIC|NO_BREATHE
+ flags = NO_BREATHE
faction = list("syndicate")
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index dcf93ca214c..7fd2dba5c90 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -180,7 +180,7 @@
if(Environment)
- if( abs(Environment.temperature - bodytemperature) > 40 && !(flags & IS_SYNTHETIC))
+ if( abs(Environment.temperature - bodytemperature) > 40 && !(flags & NO_BREATHE))
bodytemperature += ((Environment.temperature - bodytemperature) / 5)
if(min_oxy)
@@ -213,7 +213,7 @@
if(max_co2)
if(Environment.carbon_dioxide > max_co2)
atmos_suitable = 0
- if(flags & NO_BREATHE || flags & IS_SYNTHETIC)
+ if(flags & NO_BREATHE)
atmos_suitable = 1
//Atmos effect
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 4416a6f33db..a67a2eed0d9 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -96,6 +96,16 @@ proc/isembryo(A)
if(istype(A, /mob/living/silicon/ai))
return 1
return 0
+
+/mob/proc/isSynthetic()
+ return 0
+
+/mob/living/carbon/human/isSynthetic()
+ // If they are 100% robotic, they count as synthetic.
+ for(var/obj/item/organ/external/E in organs)
+ if(!(E.status & ORGAN_ROBOT))
+ return 0
+ return 1
/proc/isAIEye(A)
if(istype(A, /mob/aiEye))
diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm
index d2ccb0a698c..01b95c09ddf 100644
--- a/code/modules/organs/organ.dm
+++ b/code/modules/organs/organ.dm
@@ -58,39 +58,59 @@ var/list/organ_cache = list()
if(status & ORGAN_ROBOT)
return
damage = max_damage
+ status |= ORGAN_DEAD
processing_objects -= src
if(dead_icon)
icon_state = dead_icon
+ if(owner && vital)
+ owner.death()
/obj/item/organ/process()
+ if(loc != owner)
+ owner = null
+ //dead already, no need for more processing
+ if(status & ORGAN_DEAD)
+ return
+
// Don't process if we're in a freezer, an MMI or a stasis bag. //TODO: ambient temperature?
if(istype(loc,/obj/item/device/mmi) || istype(loc,/obj/item/bodybag/cryobag) || istype(loc,/obj/structure/closet/crate/freezer))
return
//Process infections
- if (robotic >= 2 || (owner && owner.species && (owner.species.flags & IS_PLANT)))
+ if ((status & ORGAN_ROBOT) || (owner && owner.species && (owner.species.flags & IS_PLANT)))
germ_level = 0
return
-
- if(loc != owner)
- owner = null
-
+
if(!owner)
if(reagents)
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in reagents.reagent_list
if(B && prob(40))
reagents.remove_reagent("blood",0.1)
blood_splatter(src,B,1)
- if(prob(5)) //How about we not have organs become completely useless less than a minute after removal?
- damage += 1
+
+ germ_level += rand(2,6)
+ if(germ_level >= INFECTION_LEVEL_TWO)
+ germ_level += rand(2,6)
+ if(germ_level >= INFECTION_LEVEL_THREE)
+ die()
if(damage >= max_damage)
die()
+
else if(owner.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs
//** Handle antibiotics and curing infections
handle_antibiotics()
handle_germ_effects()
+
+ //check if we've hit max_damage
+ if(damage >= max_damage)
+ die()
+
+/obj/item/organ/examine(mob/user)
+ ..(user)
+ if(status & ORGAN_DEAD)
+ user << "The decay has set in."
/obj/item/organ/proc/handle_germ_effects()
//** Handle the effects of infections
@@ -188,31 +208,17 @@ var/list/organ_cache = list()
min_broken_damage = 35
/obj/item/organ/emp_act(severity)
- switch(robotic)
- if(0)
+ if(!(status & ORGAN_ROBOT))
+ return
+ switch (severity)
+ if (1.0)
+ take_damage(0,20)
return
- if(1)
- switch (severity)
- if (1.0)
- take_damage(20,0)
- return
- if (2.0)
- take_damage(7,0)
- return
- if(3.0)
- take_damage(3,0)
- return
- if(2)
- switch (severity)
- if (1.0)
- take_damage(40,0)
- return
- if (2.0)
- take_damage(15,0)
- return
- if(3.0)
- take_damage(10,0)
- return
+ if (2.0)
+ take_damage(0,7)
+ return
+ if(3.0)
+ take_damage(0,3)
/obj/item/organ/proc/removed(var/mob/living/user)
diff --git a/code/modules/organs/organ_alien.dm b/code/modules/organs/organ_alien.dm
deleted file mode 100644
index 82b4c549bb5..00000000000
--- a/code/modules/organs/organ_alien.dm
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
-/proc/spawn_diona_nymph_from_organ(var/obj/item/organ/organ)
- if(!istype(organ))
- return
-
- //This is a terrible hack and I should be ashamed.
- var/datum/seed/diona = plant_controller.seeds["diona"]
- if(!diona)
- del(src)
-
- spawn(1) // So it has time to be thrown about by the gib() proc.
- var/mob/living/simple_animal/diona/D = new(get_turf(organ))
- diona.request_player(D)
- del(organ)
-*/
-
-/obj/item/organ/external/diona
- name = "tendril"
- cannot_break = 1
- amputation_point = "branch"
-
-/obj/item/organ/external/diona/chest
- name = "core trunk"
- limb_name = "chest"
- icon_name = "torso"
- health = 200
- min_broken_damage = 50
- body_part = UPPER_TORSO
- vital = 1
- cannot_amputate = 1
- parent_organ = null
-
-/obj/item/organ/external/diona/groin
- name = "fork"
- limb_name = "groin"
- icon_name = "groin"
- health = 100
- min_broken_damage = 50
- body_part = LOWER_TORSO
- vital = 1
- parent_organ = "chest"
-
-/obj/item/organ/external/diona/arm
- name = "left upper tendril"
- limb_name = "l_arm"
- icon_name = "l_arm"
- health = 35
- min_broken_damage = 20
- body_part = ARM_LEFT
- parent_organ = "chest"
- can_grasp = 1
-
-/obj/item/organ/external/diona/arm/right
- name = "right upper tendril"
- limb_name = "r_arm"
- icon_name = "r_arm"
- body_part = ARM_RIGHT
-
-/obj/item/organ/external/diona/leg
- name = "left lower tendril"
- limb_name = "l_leg"
- icon_name = "l_leg"
- health = 35
- min_broken_damage = 20
- body_part = LEG_LEFT
- icon_position = LEFT
- parent_organ = "groin"
- can_stand = 1
-
-/obj/item/organ/external/diona/leg/right
- name = "right lower tendril"
- limb_name = "r_leg"
- icon_name = "r_leg"
- body_part = LEG_RIGHT
- icon_position = RIGHT
-
-/obj/item/organ/external/diona/foot
- name = "left foot"
- limb_name = "l_foot"
- icon_name = "l_foot"
- health = 20
- min_broken_damage = 10
- body_part = FOOT_LEFT
- icon_position = LEFT
- parent_organ = "l_leg"
- can_stand = 1
-
-/obj/item/organ/external/diona/foot/right
- name = "right foot"
- limb_name = "r_foot"
- icon_name = "r_foot"
- body_part = FOOT_RIGHT
- icon_position = RIGHT
- parent_organ = "r_leg"
- amputation_point = "right ankle"
-
-/obj/item/organ/external/diona/hand
- name = "left grasper"
- limb_name = "l_hand"
- icon_name = "l_hand"
- health = 30
- min_broken_damage = 15
- body_part = HAND_LEFT
- parent_organ = "l_arm"
- can_grasp = 1
-
-/obj/item/organ/external/diona/hand/right
- name = "right grasper"
- limb_name = "r_hand"
- icon_name = "r_hand"
- body_part = HAND_RIGHT
- parent_organ = "r_arm"
-
-/obj/item/organ/external/diona/head
- limb_name = "head"
- icon_name = "head"
- name = "head"
- health = 50
- min_broken_damage = 25
- body_part = HEAD
- vital = 1
- parent_organ = "chest"
-
-/obj/item/organ/external/diona/head/removed()
- if(owner)
- owner.unEquip(owner.head)
- owner.unEquip(owner.l_ear)
- ..()
-
-/*
-//DIONA ORGANS.
-/obj/item/organ/external/diona/removed()
- ..()
- if(!istype(owner))
- del(src)
-
- if(!owner.organs.len)
- owner.death()
-
- if(prob(50))
- spawn_diona_nymph_from_organ(src)
-*/
-/obj/item/organ/diona/process()
- return
-
-/obj/item/organ/diona/strata
- name = "neural strata"
- parent_organ = "chest"
-
-/obj/item/organ/diona/bladder
- name = "gas bladder"
- parent_organ = "head"
-
-/obj/item/organ/diona/polyp
- name = "polyp segment"
- parent_organ = "groin"
-
-/obj/item/organ/diona/ligament
- name = "anchoring ligament"
- parent_organ = "groin"
-
-/obj/item/organ/diona/node
- name = "receptor node"
- parent_organ = "head"
-
-/obj/item/organ/diona/nutrients
- name = "nutrient vessel"
- parent_organ = "chest"
-
-/obj/item/organ/diona
- name = "diona nymph"
- icon = 'icons/obj/objects.dmi'
- icon_state = "nymph"
- organ_tag = "special" // Turns into a nymph instantly, no transplanting possible.
-/*
-/obj/item/organ/diona/removed(var/mob/living/user)
-
- ..()
- if(!istype(owner))
- del(src)
-
- if(!owner.internal_organs.len)
- owner.death()
-
- spawn_diona_nymph_from_organ(src)
-*/
-// These are different to the standard diona organs as they have a purpose in other
-// species (absorbing radiation and light respectively)
-/obj/item/organ/diona/nutrients
- name = "nutrient vessel"
- organ_tag = "nutrient vessel"
- icon = 'icons/mob/alien.dmi'
- icon_state = "claw"
-
-/obj/item/organ/diona/nutrients/removed()
- return
-
-/obj/item/organ/diona/node
- name = "receptor node"
- organ_tag = "receptor node"
- icon = 'icons/mob/alien.dmi'
- icon_state = "claw"
-
-/obj/item/organ/diona/node/removed()
- return
-
-//CORTICAL BORER ORGANS.
-/obj/item/organ/borer
- name = "cortical borer"
- parent_organ = "head"
- vital = 1
-
-/obj/item/organ/borer/process()
-
- // Borer husks regenerate health, feel no pain, and are resistant to stuns and brainloss.
- for(var/chem in list("saline", "sailcylic", "meth", "mannitol"))
- if(owner.reagents.get_reagent_amount(chem) < 3)
- owner.reagents.add_reagent(chem, 5)
-
- // They're also super gross and ooze ichor.
- if(prob(5))
- var/mob/living/carbon/human/H = owner
- if(!istype(H))
- return
-
- var/datum/reagent/blood/B = locate(/datum/reagent/blood) in H.vessel.reagent_list
- blood_splatter(H,B,1)
- var/obj/effect/decal/cleanable/blood/splatter/goo = locate() in get_turf(owner)
- if(goo)
- goo.name = "husk ichor"
- goo.desc = "It's thick and stinks of decay."
- goo.basecolor = "#412464"
- goo.update_icon()
-
-/obj/item/organ/borer
- name = "cortical borer"
- icon = 'icons/obj/objects.dmi'
- icon_state = "borer"
- organ_tag = "brain"
- desc = "A disgusting space slug."
-
-/obj/item/organ/borer/removed(var/mob/living/user)
-
- ..()
-
- var/mob/living/simple_animal/borer/B = owner.has_brain_worms()
- if(B)
- B.leave_host()
- B.ckey = owner.ckey
-
- spawn(0)
- qdel(src)
-
-//XENOMORPH ORGANS
-/obj/item/organ/xenos/eggsac
- name = "egg sac"
- parent_organ = "groin"
-
-/obj/item/organ/xenos/plasmavessel
- name = "plasma vessel"
- parent_organ = "chest"
- var/stored_plasma = 0
- var/max_plasma = 500
-
-/obj/item/organ/xenos/plasmavessel/queen
- name = "bloated plasma vessel"
- stored_plasma = 200
- max_plasma = 500
-
-/obj/item/organ/xenos/plasmavessel/sentinel
- stored_plasma = 100
- max_plasma = 250
-
-/obj/item/organ/xenos/plasmavessel/hunter
- name = "tiny plasma vessel"
- stored_plasma = 100
- max_plasma = 150
-
-/obj/item/organ/xenos/acidgland
- name = "acid gland"
- parent_organ = "head"
-
-/obj/item/organ/xenos/hivenode
- name = "hive node"
- parent_organ = "chest"
-
-/obj/item/organ/xenos/resinspinner
- name = "resin spinner"
- parent_organ = "head"
-
-/obj/item/organ/xenos
- name = "xeno organ"
- icon = 'icons/effects/blood.dmi'
- desc = "It smells like an accident in a chemical factory."
-
-/obj/item/organ/xenos/eggsac
- name = "egg sac"
- icon_state = "xgibmid1"
- organ_tag = "egg sac"
-
-/obj/item/organ/xenos/plasmavessel
- name = "plasma vessel"
- icon_state = "xgibdown1"
- organ_tag = "plasma vessel"
-
-/obj/item/organ/xenos/acidgland
- name = "acid gland"
- icon_state = "xgibtorso"
- organ_tag = "acid gland"
-
-/obj/item/organ/xenos/hivenode
- name = "hive node"
- icon_state = "xgibmid2"
- organ_tag = "hive node"
-
-/obj/item/organ/xenos/resinspinner
- name = "hive node"
- icon_state = "xgibmid2"
- organ_tag = "resin spinner"
-
-//VOX ORGANS.
-/obj/item/organ/stack
- name = "cortical stack"
- icon_state = "brain-prosthetic"
- parent_organ = "head"
- organ_tag = "stack"
- robotic = 2
- vital = 1
- var/backup_time = 0
- var/datum/mind/backup
-
-/obj/item/organ/stack/process()
- if(owner && owner.stat != 2 && !is_broken())
- backup_time = world.time
- if(owner.mind) backup = owner.mind
-
-/obj/item/organ/stack/vox
- name = "vox cortical stack"
-
-/obj/item/organ/stack/vox/stack
-
-
-//WRYN ORGAN
-
-/obj/item/organ/wryn/hivenode
- name = "antennae"
- parent_organ = "head"
-
-/obj/item/organ/wryn/hivenode
- name = "antennae"
- organ_tag = "antennae"
- icon = 'icons/mob/human_races/r_wryn.dmi'
- icon_state = "antennae"
-
-
-//NUCLEATION ORGAN
-
-/obj/item/organ/nucleation
- name = "nucleation organ"
- icon = 'icons/obj/surgery.dmi'
- desc = "A crystalized human organ. /red It has a strangely iridescent glow."
-
-/obj/item/organ/nucleation/resonant_crystal
- name = "resonant crystal"
- icon_state = "resonant-crystal"
- organ_tag = "resonant crystal"
- parent_organ = "head"
-
-/obj/item/organ/nucleation/strange_crystal
- name = "strange crystal"
- icon_state = "strange-crystal"
- organ_tag = "strange crystal"
- parent_organ = "chest"
-
-/obj/item/organ/eyes/luminescent_crystal
- name = "luminescent eyes"
- icon_state = "crystal-eyes"
- organ_tag = "luminescent eyes"
- light_color = "#1C1C00"
- parent_organ = "head"
-
- New()
- set_light(2)
-
-/obj/item/organ/brain/crystal
- name = "crystalized brain"
- icon_state = "crystal-brain"
- organ_tag = "crystalized brain"
\ No newline at end of file
diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm
index fdccbd826a7..92af27ee01a 100644
--- a/code/modules/organs/organ_external.dm
+++ b/code/modules/organs/organ_external.dm
@@ -7,6 +7,10 @@
max_damage = 0
dir = SOUTH
organ_tag = "limb"
+
+ var/brute_mod = 1
+ var/burn_mod = 1
+
var/icon_name = null
var/body_part = null
var/icon_position = 0
@@ -102,6 +106,7 @@
/obj/item/organ/external/replaced(var/mob/living/carbon/human/target)
owner = target
+ status = status & ~ORGAN_DESTROYED
if(istype(owner))
owner.organs_by_name[limb_name] = src
owner.organs |= src
@@ -115,6 +120,12 @@
if(!parent.children)
parent.children = list()
parent.children.Add(src)
+
+/obj/item/organ/external/robotize()
+ ..()
+ //robot limbs take reduced damage
+ brute_mod = 0.66
+ burn_mod = 0.66
/****************************************************
DAMAGE PROCS
@@ -126,22 +137,12 @@
if(status & ORGAN_DESTROYED)
return 0
- if(status & ORGAN_ROBOT )
-
- var/brmod = 0.66
- var/bumod = 0.66
-
- if(istype(owner,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = owner
- if(H.species && H.species.flags & IS_SYNTHETIC) // No need for this - the modifer is being applied in the species' code already. Leaving it in, in case it ever changes.
- brmod = 1 //H.species.brute_mod
- bumod = 1 //H.species.burn_mod
-
- brute *= brmod //~2/3 damage for ROBOLIMBS
- burn *= bumod //~2/3 damage for ROBOLIMBS
+
+ brute *= brute_mod
+ burn *= burn_mod
// High brute damage or sharp objects may damage internal organs
- if(internal_organs && ((brute_dam >= max_damage) || (sharp && brute >= 5) || brute >= 10) && prob(5))
+ if(internal_organs && (brute_dam >= max_damage || (((sharp && brute >= 5) || brute >= 10) && prob(5))))
// Damage an internal organ
if(internal_organs && internal_organs.len)
var/obj/item/organ/I = pick(internal_organs)
@@ -301,12 +302,16 @@ This function completely restores a damaged organ to perfect condition.
var/datum/wound/W = pick(compatible_wounds)
W.open_wound(damage)
if(prob(25))
- //maybe have a separate message for BRUISE type damage?
- owner.visible_message("\red The wound on [owner.name]'s [name] widens with a nasty ripping voice.",\
- "\red The wound on your [name] widens with a nasty ripping voice.",\
- "You hear a nasty ripping noise, as if flesh is being torn apart.")
+ if(status & ORGAN_ROBOT)
+ owner.visible_message("The damage to [owner.name]'s [name] worsens.",\
+ "The damage to your [name] worsens.",\
+ "You hear the screech of abused metal.")
+ else
+ owner.visible_message("The wound on [owner.name]'s [name] widens with a nasty ripping noise.",\
+ "The wound on your [name] widens with a nasty ripping noise.",\
+ "You hear a nasty ripping noise, as if flesh is being torn apart.")
return
-
+
//Creating wound
var/wound_type = get_wound_type(type, damage)
@@ -329,7 +334,7 @@ This function completely restores a damaged organ to perfect condition.
//Determines if we even need to process this organ.
/obj/item/organ/external/proc/need_process()
- if(status && status != ORGAN_ROBOT) // If it's robotic, that's fine it will have a status.
+ if(status & (ORGAN_CUT_AWAY|ORGAN_GAUZED|ORGAN_BLEEDING|ORGAN_BROKEN|ORGAN_DESTROYED|ORGAN_SPLINTED|ORGAN_DEAD|ORGAN_MUTATED))
return 1
if(brute_dam || burn_dam)
return 1
@@ -344,11 +349,6 @@ This function completely restores a damaged organ to perfect condition.
/obj/item/organ/external/process()
if(owner)
- //Dismemberment
- if(status & ORGAN_DESTROYED)
- if(config.limbs_can_break)
- droplimb(0,DROPLIMB_EDGE) //Might be worth removing this check since take_damage handles it.
- return
if(parent)
if(parent.status & ORGAN_DESTROYED)
status |= ORGAN_DESTROYED
@@ -366,10 +366,6 @@ This function completely restores a damaged organ to perfect condition.
if(trace_chemicals[chemID] <= 0)
trace_chemicals.Remove(chemID)
- //Bone fractures
- if(config.bones_can_break && brute_dam > min_broken_damage * config.organ_health_multiplier && !(status & ORGAN_ROBOT))
- src.fracture()
-
if(!(status & ORGAN_BROKEN))
perma_injury = 0
@@ -537,6 +533,11 @@ Note that amputating the affected organ does in fact remove the infection from t
burn_dam = 0
status &= ~ORGAN_BLEEDING
var/clamped = 0
+
+ var/mob/living/carbon/human/H
+ if(istype(owner,/mob/living/carbon/human))
+ H = owner
+
for(var/datum/wound/W in wounds)
if(W.damage_type == CUT || W.damage_type == BRUISE)
brute_dam += W.damage
@@ -551,9 +552,12 @@ Note that amputating the affected organ does in fact remove the infection from t
number_wounds += W.amount
- if (open && !clamped) //things tend to bleed if they are CUT OPEN
+ if (open && !clamped && (H && !(H.species.flags & NO_BLOOD)))
status |= ORGAN_BLEEDING
-
+
+ //Bone fractures
+ if(config.bones_can_break && brute_dam > min_broken_damage * config.organ_health_multiplier && !(status & ORGAN_ROBOT))
+ src.fracture()
// new damage icon system
// returns just the brute/burn damage code
@@ -599,10 +603,24 @@ Note that amputating the affected organ does in fact remove the infection from t
switch(disintegrate)
if(DROPLIMB_EDGE)
if(!clean)
+ var/gore_sound = "[(status & ORGAN_ROBOT) ? "tortured metal" : "ripping tendons and flesh"]"
owner.visible_message(
"\The [owner]'s [src.name] flies off in an arc!",\
"Your [src.name] goes flying off!",\
- "You hear a terrible sound of ripping tendons and flesh.")
+ "You hear a terrible sound of [gore_sound].")
+ if(DROPLIMB_BURN)
+ var/gore = "[(status & ORGAN_ROBOT) ? "": " of burning flesh"]"
+ owner.visible_message(
+ "\The [owner]'s [src.name] flashes away into ashes!",\
+ "Your [src.name] flashes away into ashes!",\
+ "You hear a crackling sound[gore].")
+ if(DROPLIMB_BLUNT)
+ var/gore = "[(status & ORGAN_ROBOT) ? "": " in shower of gore"]"
+ var/gore_sound = "[(status & ORGAN_ROBOT) ? "rending sound of tortured metal" : "sickening splatter of gore"]"
+ owner.visible_message(
+ "\The [owner]'s [src.name] explodes[gore]!",\
+ "Your [src.name] explodes[gore]!",\
+ "You hear the [gore_sound].")
var/mob/living/carbon/human/victim = owner //Keep a reference for post-removed().
removed(null, ignore_children)
@@ -610,17 +628,15 @@ Note that amputating the affected organ does in fact remove the infection from t
wounds.Cut()
if(parent && !nodamage)
- var/datum/wound/W
- if(clean || max_damage < 50)
- W = new/datum/wound/lost_limb/small(max_damage)
- else
- W = new/datum/wound/lost_limb(max_damage)
+ var/datum/wound/lost_limb/W = new (src, disintegrate, clean)
parent.children -= src
if(clean)
parent.wounds |= W
parent.update_damages()
else
var/obj/item/organ/external/stump/stump = new (victim, 0, src)
+ if(status & ORGAN_ROBOT)
+ stump.robotize()
stump.wounds |= W
victim.organs |= stump
stump.update_damages()
@@ -705,15 +721,18 @@ Note that amputating the affected organ does in fact remove the infection from t
return rval
/obj/item/organ/external/proc/fracture()
+ if(status & ORGAN_ROBOT)
+ return //ORGAN_BROKEN doesn't have the same meaning for robot limbs
+
if((status & ORGAN_BROKEN) || cannot_break)
return
- owner.visible_message(\
- "\red You hear a loud cracking sound coming from \the [owner].",\
- "\red Something feels like it shattered in your [name]!",\
- "You hear a sickening crack.")
-
- if(owner.species && !(owner.species.flags & NO_PAIN))
- owner.emote("scream")
+ if(owner)
+ owner.visible_message(\
+ "\red You hear a loud cracking sound coming from \the [owner].",\
+ "\red Something feels like it shattered in your [name]!",\
+ "You hear a sickening crack.")
+ if(owner.species && !(owner.species.flags & NO_PAIN))
+ owner.emote("scream")
status |= ORGAN_BROKEN
broken_description = pick("broken","fracture","hairline fracture")
@@ -751,11 +770,11 @@ Note that amputating the affected organ does in fact remove the infection from t
/obj/item/organ/external/proc/mutate()
src.status |= ORGAN_MUTATED
- owner.update_body()
+ if(owner) owner.update_body()
/obj/item/organ/external/proc/unmutate()
src.status &= ~ORGAN_MUTATED
- owner.update_body()
+ if(owner) owner.update_body()
/obj/item/organ/external/proc/get_damage() //returns total damage
return max(brute_dam + burn_dam - perma_injury, perma_injury) //could use health?
@@ -767,13 +786,15 @@ 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
+ 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))
/obj/item/organ/external/proc/embed(var/obj/item/weapon/W, var/silent = 0)
- if(loc != owner)
+ if(!owner || loc != owner)
return
if(!silent)
owner.visible_message("\The [W] sticks in the wound!")
@@ -806,12 +827,12 @@ Note that amputating the affected organ does in fact remove the infection from t
for(var/obj/item/organ/external/O in children)
O.removed()
if(O)
- O.loc = src
+ O.forceMove(src)
// Grab all the internal giblets too.
for(var/obj/item/organ/organ in internal_organs)
organ.removed()
- organ.loc = src
+ organ.forceMove(src)
release_restraints(victim)
victim.organs -= src
@@ -845,153 +866,3 @@ Note that amputating the affected organ does in fact remove the infection from t
"\red Your [name] melts away!", \
"\red You hear a sickening sizzle.")
disfigured = 1
-
-/****************************************************
- ORGAN DEFINES
-****************************************************/
-
-/obj/item/organ/external/chest
- name = "upper body"
- limb_name = "chest"
- icon_name = "torso"
- max_damage = 100
- min_broken_damage = 50
- body_part = UPPER_TORSO
- vital = 1
- amputation_point = "spine"
- gendered_icon = 1
- cannot_amputate = 1
- parent_organ = null
- encased = "ribcage"
-
-/obj/item/organ/external/groin
- name = "lower body"
- limb_name = "groin"
- icon_name = "groin"
- max_damage = 100
- min_broken_damage = 50
- body_part = LOWER_TORSO
- vital = 1
- parent_organ = "chest"
- amputation_point = "lumbar"
- gendered_icon = 1
-
-/obj/item/organ/external/arm
- limb_name = "l_arm"
- name = "left arm"
- icon_name = "l_arm"
- max_damage = 60
- min_broken_damage = 30
- body_part = ARM_LEFT
- parent_organ = "chest"
- amputation_point = "left shoulder"
- can_grasp = 1
-
-/obj/item/organ/external/arm/right
- limb_name = "r_arm"
- name = "right arm"
- icon_name = "r_arm"
- body_part = ARM_RIGHT
- amputation_point = "right shoulder"
-
-/obj/item/organ/external/leg
- limb_name = "l_leg"
- name = "left leg"
- icon_name = "l_leg"
- max_damage = 60
- min_broken_damage = 30
- body_part = LEG_LEFT
- icon_position = LEFT
- parent_organ = "groin"
- amputation_point = "left hip"
- can_stand = 1
-
-/obj/item/organ/external/leg/right
- limb_name = "r_leg"
- name = "right leg"
- icon_name = "r_leg"
- body_part = LEG_RIGHT
- icon_position = RIGHT
- amputation_point = "right hip"
-
-/obj/item/organ/external/foot
- limb_name = "l_foot"
- name = "left foot"
- icon_name = "l_foot"
- max_damage = 30
- min_broken_damage = 15
- body_part = FOOT_LEFT
- icon_position = LEFT
- parent_organ = "l_leg"
- amputation_point = "left ankle"
- can_stand = 1
-
-/obj/item/organ/external/foot/removed()
- if(owner) owner.unEquip(owner.shoes)
- ..()
-
-/obj/item/organ/external/foot/right
- limb_name = "r_foot"
- name = "right foot"
- icon_name = "r_foot"
- body_part = FOOT_RIGHT
- icon_position = RIGHT
- parent_organ = "r_leg"
- amputation_point = "right ankle"
-
-/obj/item/organ/external/hand
- limb_name = "l_hand"
- name = "left hand"
- icon_name = "l_hand"
- max_damage = 30
- min_broken_damage = 15
- body_part = HAND_LEFT
- parent_organ = "l_arm"
- amputation_point = "left wrist"
- can_grasp = 1
-
-/obj/item/organ/external/hand/removed()
- if(owner) owner.unEquip(owner.gloves)
- ..()
-
-/obj/item/organ/external/hand/right
- limb_name = "r_hand"
- name = "right hand"
- icon_name = "r_hand"
- body_part = HAND_RIGHT
- parent_organ = "r_arm"
- amputation_point = "right wrist"
-
-/obj/item/organ/external/head
- limb_name = "head"
- icon_name = "head"
- name = "head"
- max_damage = 70
- min_broken_damage = 35
- body_part = HEAD
- vital = 1
- parent_organ = "chest"
- amputation_point = "neck"
- gendered_icon = 1
- encased = "skull"
-
-/obj/item/organ/external/head/removed()
- if(owner)
- name = "[owner.real_name]'s head"
- owner.unEquip(owner.glasses)
- owner.unEquip(owner.head)
- owner.unEquip(owner.l_ear)
- owner.unEquip(owner.r_ear)
- owner.unEquip(owner.wear_mask)
- spawn(1)
- owner.update_hair()
- ..()
-
-/obj/item/organ/external/head/take_damage(brute, burn, sharp, edge, used_weapon = null, list/forbidden_limbs = list())
- ..(brute, burn, sharp, edge, used_weapon, forbidden_limbs)
- if (!disfigured)
- if (brute_dam > 40)
- if (prob(50))
- disfigure("brute")
- if (burn_dam > 40)
- disfigure("burn")
diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm
index f025e9adcd8..26ca1f5079a 100644
--- a/code/modules/organs/organ_icon.dm
+++ b/code/modules/organs/organ_icon.dm
@@ -87,7 +87,7 @@ var/global/list/limb_icon_cache = list()
if(skeletal)
mob_icon = new /icon('icons/mob/human_races/r_skeleton.dmi', "[icon_name][gender ? "_[gender]" : ""]")
- else if ((status & ORGAN_ROBOT) && !(owner.species && owner.species.flags & IS_SYNTHETIC))
+ else if (status & ORGAN_ROBOT)
mob_icon = new /icon('icons/mob/human_races/robotic.dmi', "[icon_name][gender ? "_[gender]" : ""]")
else
if (status & ORGAN_MUTATED)
diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm
index b1b3fcbc0a5..5438fdd3ec3 100644
--- a/code/modules/organs/organ_internal.dm
+++ b/code/modules/organs/organ_internal.dm
@@ -81,17 +81,6 @@
owner.b_eyes ? owner.b_eyes : 0
)
-
-/obj/item/organ/eyes/process() //Eye damage replaces the old eye_stat var.
- ..()
- if(!owner)
- return
- if(is_bruised())
- owner.eye_blurry = 20
- if(is_broken())
- owner.eye_blind = 20
-
-
/obj/item/organ/liver
name = "liver"
icon_state = "liver"
diff --git a/code/modules/organs/organ_stump.dm b/code/modules/organs/organ_stump.dm
index 545ca746275..1f9cdb1217b 100644
--- a/code/modules/organs/organ_stump.dm
+++ b/code/modules/organs/organ_stump.dm
@@ -1,7 +1,6 @@
/obj/item/organ/external/stump
name = "limb stump"
icon_name = ""
- cannot_amputate = 0 //You need to remove stumps to attach new limbs, but you can't remove stumps... What the fuck?
/obj/item/organ/external/stump/New(var/mob/living/carbon/holder, var/internal, var/obj/item/organ/external/limb)
if(istype(limb))
@@ -13,6 +12,8 @@
..(holder, internal)
if(istype(limb))
max_damage = limb.max_damage
+ if((limb.status & ORGAN_ROBOT) && (!parent || (parent.status & ORGAN_ROBOT)))
+ robotize() //if both limb and the parent are robotic, the stump is robotic too
/obj/item/organ/external/stump/is_stump()
return 1
@@ -20,3 +21,6 @@
/obj/item/organ/external/stump/removed()
..()
qdel(src)
+
+/obj/item/organ/external/stump/is_usable()
+ return 0
\ No newline at end of file
diff --git a/code/modules/organs/pain.dm b/code/modules/organs/pain.dm
index d48592f64d9..bd9e9a9694a 100644
--- a/code/modules/organs/pain.dm
+++ b/code/modules/organs/pain.dm
@@ -78,8 +78,8 @@ mob/living/carbon/human/proc/handle_pain()
// not when sleeping
if(species && species.flags & NO_PAIN)
- //While IPCs don't feel pain, they will notice their gears gunking up with residue (toxins)
- if(species && species.flags & IS_SYNTHETIC)
+ //While synthetics don't feel pain, they will notice their gears gunking up with residue (toxins)
+ if(isSynthetic())
var/toxDamageMessage = null
var/toxMessageProb = 1
switch(getToxLoss())
diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm
index 8d19d60b491..fc4151e4fef 100644
--- a/code/modules/organs/robolimbs.dm
+++ b/code/modules/organs/robolimbs.dm
@@ -35,3 +35,9 @@ var/global/datum/robolimb/basic_robolimb
company = "Xion Manufacturing Group"
desc = "This limb has a minimalist black and red casing."
icon = 'icons/mob/human_races/cyberlimbs/xion.dmi'
+
+/datum/robolimb/ipc
+ company = "Morpheus Cyberkinetics"
+ desc = "This limb is simple and functional; no effort has been made to make it look human."
+ icon = 'icons/mob/human_races/cyberlimbs/ipc.dmi'
+ unavailable_at_chargen = 1
diff --git a/code/modules/organs/subtypes/diona.dm b/code/modules/organs/subtypes/diona.dm
new file mode 100644
index 00000000000..735b5120582
--- /dev/null
+++ b/code/modules/organs/subtypes/diona.dm
@@ -0,0 +1,207 @@
+/*/proc/spawn_diona_nymph_from_organ(var/obj/item/organ/organ)
+ if(!istype(organ))
+ return 0
+
+ //This is a terrible hack and I should be ashamed.
+ var/datum/seed/diona = plant_controller.seeds["diona"]
+ if(!diona)
+ return 0
+
+ spawn(1) // So it has time to be thrown about by the gib() proc.
+ var/mob/living/simple_animal/diona/D = new(get_turf(organ))
+ var/datum/ghosttrap/plant/P = get_ghost_trap("living plant")
+ P.request_player(D, "A diona nymph has split off from its gestalt. ")
+ spawn(60)
+ if(D)
+ if(!D.ckey || !D.client)
+ D.death()
+ return 1 */
+
+/obj/item/organ/external/diona
+ name = "tendril"
+ cannot_break = 1
+ amputation_point = "branch"
+
+/obj/item/organ/external/diona/chest
+ name = "core trunk"
+ limb_name = "chest"
+ icon_name = "torso"
+ max_damage = 200
+ min_broken_damage = 50
+ w_class = 5
+ body_part = UPPER_TORSO
+ vital = 1
+ cannot_amputate = 1
+ parent_organ = null
+
+/obj/item/organ/external/diona/groin
+ name = "fork"
+ limb_name = "groin"
+ icon_name = "groin"
+ max_damage = 100
+ min_broken_damage = 50
+ w_class = 4
+ body_part = LOWER_TORSO
+ parent_organ = "chest"
+
+/obj/item/organ/external/diona/arm
+ name = "left upper tendril"
+ limb_name = "l_arm"
+ icon_name = "l_arm"
+ max_damage = 35
+ min_broken_damage = 20
+ w_class = 3
+ body_part = ARM_LEFT
+ parent_organ = "chest"
+ can_grasp = 1
+
+/obj/item/organ/external/diona/arm/right
+ name = "right upper tendril"
+ limb_name = "r_arm"
+ icon_name = "r_arm"
+ body_part = ARM_RIGHT
+
+/obj/item/organ/external/diona/leg
+ name = "left lower tendril"
+ limb_name = "l_leg"
+ icon_name = "l_leg"
+ max_damage = 35
+ min_broken_damage = 20
+ w_class = 3
+ body_part = LEG_LEFT
+ icon_position = LEFT
+ parent_organ = "groin"
+ can_stand = 1
+
+/obj/item/organ/external/diona/leg/right
+ name = "right lower tendril"
+ limb_name = "r_leg"
+ icon_name = "r_leg"
+ body_part = LEG_RIGHT
+ icon_position = RIGHT
+
+/obj/item/organ/external/diona/foot
+ name = "left foot"
+ limb_name = "l_foot"
+ icon_name = "l_foot"
+ max_damage = 20
+ min_broken_damage = 10
+ w_class = 2
+ body_part = FOOT_LEFT
+ icon_position = LEFT
+ parent_organ = "l_leg"
+ can_stand = 1
+
+/obj/item/organ/external/diona/foot/right
+ name = "right foot"
+ limb_name = "r_foot"
+ icon_name = "r_foot"
+ body_part = FOOT_RIGHT
+ icon_position = RIGHT
+ parent_organ = "r_leg"
+ amputation_point = "right ankle"
+
+/obj/item/organ/external/diona/hand
+ name = "left grasper"
+ limb_name = "l_hand"
+ icon_name = "l_hand"
+ max_damage = 30
+ min_broken_damage = 15
+ w_class = 2
+ body_part = HAND_LEFT
+ parent_organ = "l_arm"
+ can_grasp = 1
+
+/obj/item/organ/external/diona/hand/right
+ name = "right grasper"
+ limb_name = "r_hand"
+ icon_name = "r_hand"
+ body_part = HAND_RIGHT
+ parent_organ = "r_arm"
+
+/obj/item/organ/external/diona/head
+ limb_name = "head"
+ icon_name = "head"
+ name = "head"
+ max_damage = 50
+ min_broken_damage = 25
+ vital = 1
+ w_class = 3
+ body_part = HEAD
+ parent_organ = "chest"
+
+/obj/item/organ/external/diona/head/removed()
+ if(owner)
+ owner.unEquip(owner.head)
+ owner.unEquip(owner.l_ear)
+ ..()
+
+//DIONA ORGANS.
+/* /obj/item/organ/external/diona/removed()
+ var/mob/living/carbon/human/H = owner
+ ..()
+ if(!istype(H) || !H.organs || !H.organs.len)
+ H.death()
+ if(prob(50) && spawn_diona_nymph_from_organ(src))
+ qdel(src) */
+
+/obj/item/organ/diona/process()
+ return
+
+/obj/item/organ/diona/strata
+ name = "neural strata"
+ parent_organ = "chest"
+
+/obj/item/organ/diona/bladder
+ name = "gas bladder"
+ parent_organ = "head"
+
+/obj/item/organ/diona/polyp
+ name = "polyp segment"
+ parent_organ = "groin"
+
+/obj/item/organ/diona/ligament
+ name = "anchoring ligament"
+ parent_organ = "groin"
+
+/obj/item/organ/diona/node
+ name = "receptor node"
+ parent_organ = "head"
+
+/obj/item/organ/diona/nutrients
+ name = "nutrient vessel"
+ parent_organ = "chest"
+
+/obj/item/organ/diona
+ name = "diona nymph"
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "nymph"
+ organ_tag = "special" // Turns into a nymph instantly, no transplanting possible.
+
+/*/obj/item/organ/diona/removed(var/mob/living/user)
+ var/mob/living/carbon/human/H = owner
+ ..()
+ if(!istype(H) || !H.organs || !H.organs.len)
+ H.death()
+ if(prob(50) && spawn_diona_nymph_from_organ(src))
+ qdel(src) */
+
+// These are different to the standard diona organs as they have a purpose in other
+// species (absorbing radiation and light respectively)
+/obj/item/organ/diona/nutrients
+ name = "nutrient vessel"
+ organ_tag = "nutrient vessel"
+ icon = 'icons/mob/alien.dmi'
+ icon_state = "claw"
+
+/obj/item/organ/diona/nutrients/removed()
+ return
+
+/obj/item/organ/diona/node
+ name = "receptor node"
+ organ_tag = "receptor node"
+ icon = 'icons/mob/alien.dmi'
+ icon_state = "claw"
+
+/obj/item/organ/diona/node/removed()
+ return
diff --git a/code/modules/organs/subtypes/machine.dm b/code/modules/organs/subtypes/machine.dm
new file mode 100644
index 00000000000..ee71bb59d21
--- /dev/null
+++ b/code/modules/organs/subtypes/machine.dm
@@ -0,0 +1,138 @@
+// IPC limbs.
+/obj/item/organ/external/head/ipc
+ can_intake_reagents = 0
+ vital = 0
+ max_damage = 50 //made same as arm, since it is not vital
+ min_broken_damage = 30
+ encased = null
+
+/obj/item/organ/external/head/ipc/New()
+ robotize("Morpheus Cyberkinetics")
+ ..()
+
+/obj/item/organ/external/chest/ipc
+ encased = null
+
+/obj/item/organ/external/chest/ipc/New()
+ robotize("Morpheus Cyberkinetics")
+ ..()
+
+/obj/item/organ/external/groin/ipc/New()
+ robotize("Morpheus Cyberkinetics")
+ ..()
+
+/obj/item/organ/external/arm/ipc/New()
+ robotize("Morpheus Cyberkinetics")
+ ..()
+
+/obj/item/organ/external/arm/right/ipc/New()
+ robotize("Morpheus Cyberkinetics")
+ ..()
+
+/obj/item/organ/external/leg/ipc/New()
+ robotize("Morpheus Cyberkinetics")
+ ..()
+
+/obj/item/organ/external/leg/right/ipc/New()
+ robotize("Morpheus Cyberkinetics")
+ ..()
+
+/obj/item/organ/external/foot/ipc/New()
+ robotize("Morpheus Cyberkinetics")
+ ..()
+
+/obj/item/organ/external/foot/right/ipc/New()
+ robotize("Morpheus Cyberkinetics")
+ ..()
+
+/obj/item/organ/external/hand/ipc/New()
+ robotize("Morpheus Cyberkinetics")
+ ..()
+
+/obj/item/organ/external/hand/right/ipc/New()
+ robotize("Morpheus Cyberkinetics")
+ ..()
+
+/obj/item/organ/cell
+ name = "microbattery"
+ desc = "A small, powerful cell for use in fully prosthetic bodies."
+ icon = 'icons/obj/power.dmi'
+ icon_state = "scell"
+ organ_tag = "cell"
+ parent_organ = "chest"
+ vital = 1
+
+/obj/item/organ/cell/New()
+ robotize()
+ ..()
+
+/obj/item/organ/cell/replaced()
+ ..()
+ // This is very ghetto way of rebooting an IPC. TODO better way.
+ if(owner && owner.stat == DEAD)
+ owner.stat = CONSCIOUS
+ owner.visible_message("\The [owner] twitches visibly!")
+
+/obj/item/organ/optical_sensor
+ name = "optical sensor"
+ organ_tag = "optics"
+ parent_organ = "head"
+ icon = 'icons/obj/robot_component.dmi'
+ icon_state = "camera"
+ dead_icon = "camera_broken"
+
+/obj/item/organ/optical_sensor/New()
+ robotize()
+ ..()
+
+// Used for an MMI or posibrain being installed into a human.
+/obj/item/organ/mmi_holder
+ name = "brain"
+ organ_tag = "brain"
+ parent_organ = "chest"
+ vital = 1
+ var/obj/item/device/mmi/stored_mmi
+
+/obj/item/organ/mmi_holder/proc/update_from_mmi()
+ if(!stored_mmi)
+ return
+ name = stored_mmi.name
+ desc = stored_mmi.desc
+ icon = stored_mmi.icon
+ icon_state = stored_mmi.icon_state
+
+/obj/item/organ/mmi_holder/removed(var/mob/living/user)
+
+ if(stored_mmi)
+ stored_mmi.loc = get_turf(src)
+ if(owner.mind)
+ owner.mind.transfer_to(stored_mmi.brainmob)
+ ..()
+
+ var/mob/living/holder_mob = loc
+ if(istype(holder_mob))
+ holder_mob.unEquip(src)
+ qdel(src)
+
+/obj/item/organ/mmi_holder/New()
+ ..()
+ // This is very ghetto way of rebooting an IPC. TODO better way.
+ spawn(1)
+ if(owner && owner.stat == DEAD)
+ owner.stat = 0
+ owner.visible_message("\The [owner] twitches visibly!")
+
+/obj/item/organ/mmi_holder/posibrain/New()
+ robotize()
+ stored_mmi = new /obj/item/device/mmi/posibrain(src)
+ ..()
+ spawn(1)
+ if(owner)
+ stored_mmi.name = "positronic brain ([owner.name])"
+ stored_mmi.brainmob.real_name = owner.name
+ stored_mmi.brainmob.name = stored_mmi.brainmob.real_name
+ stored_mmi.icon_state = "posibrain-occupied"
+ update_from_mmi()
+ else
+ stored_mmi.loc = get_turf(src)
+ qdel(src)
\ No newline at end of file
diff --git a/code/modules/organs/subtypes/misc.dm b/code/modules/organs/subtypes/misc.dm
new file mode 100644
index 00000000000..a2febc6d1e4
--- /dev/null
+++ b/code/modules/organs/subtypes/misc.dm
@@ -0,0 +1,67 @@
+//CORTICAL BORER ORGANS.
+/obj/item/organ/borer
+ name = "cortical borer"
+ parent_organ = "head"
+ vital = 1
+
+/obj/item/organ/borer/process()
+
+ // Borer husks regenerate health, feel no pain, and are resistant to stuns and brainloss.
+ for(var/chem in list("saline", "sailcylic", "meth", "mannitol"))
+ if(owner.reagents.get_reagent_amount(chem) < 3)
+ owner.reagents.add_reagent(chem, 5)
+
+ // They're also super gross and ooze ichor.
+ if(prob(5))
+ var/mob/living/carbon/human/H = owner
+ if(!istype(H))
+ return
+
+ var/datum/reagent/blood/B = locate(/datum/reagent/blood) in H.vessel.reagent_list
+ blood_splatter(H,B,1)
+ var/obj/effect/decal/cleanable/blood/splatter/goo = locate() in get_turf(owner)
+ if(goo)
+ goo.name = "husk ichor"
+ goo.desc = "It's thick and stinks of decay."
+ goo.basecolor = "#412464"
+ goo.update_icon()
+
+/obj/item/organ/borer
+ name = "cortical borer"
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "borer"
+ organ_tag = "brain"
+ desc = "A disgusting space slug."
+
+/obj/item/organ/borer/removed(var/mob/living/user)
+
+ ..()
+
+ var/mob/living/simple_animal/borer/B = owner.has_brain_worms()
+ if(B)
+ B.leave_host()
+ B.ckey = owner.ckey
+
+ spawn(0)
+ qdel(src)
+
+//VOX ORGANS.
+/obj/item/organ/stack
+ name = "cortical stack"
+ icon_state = "brain-prosthetic"
+ parent_organ = "head"
+ organ_tag = "stack"
+ robotic = 2
+ vital = 1
+ var/backup_time = 0
+ var/datum/mind/backup
+
+/obj/item/organ/stack/process()
+ if(owner && owner.stat != 2 && !is_broken())
+ backup_time = world.time
+ if(owner.mind) backup = owner.mind
+
+/obj/item/organ/stack/vox
+ name = "vox cortical stack"
+
+/obj/item/organ/stack/vox/stack
diff --git a/code/modules/organs/subtypes/nucleation.dm b/code/modules/organs/subtypes/nucleation.dm
new file mode 100644
index 00000000000..40d7745d86e
--- /dev/null
+++ b/code/modules/organs/subtypes/nucleation.dm
@@ -0,0 +1,33 @@
+//NUCLEATION ORGAN
+/obj/item/organ/nucleation
+ name = "nucleation organ"
+ icon = 'icons/obj/surgery.dmi'
+ desc = "A crystalized human organ. /red It has a strangely iridescent glow."
+
+/obj/item/organ/nucleation/resonant_crystal
+ name = "resonant crystal"
+ icon_state = "resonant-crystal"
+ organ_tag = "resonant crystal"
+ parent_organ = "head"
+
+/obj/item/organ/nucleation/strange_crystal
+ name = "strange crystal"
+ icon_state = "strange-crystal"
+ organ_tag = "strange crystal"
+ parent_organ = "chest"
+
+/obj/item/organ/eyes/luminescent_crystal
+ name = "luminescent eyes"
+ icon_state = "crystal-eyes"
+ organ_tag = "luminescent eyes"
+ light_color = "#1C1C00"
+ parent_organ = "head"
+
+ New()
+ set_light(2)
+
+/obj/item/organ/brain/crystal
+ name = "crystalized brain"
+ icon_state = "crystal-brain"
+ organ_tag = "crystalized brain"
+
\ No newline at end of file
diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm
new file mode 100644
index 00000000000..6663f833bef
--- /dev/null
+++ b/code/modules/organs/subtypes/standard.dm
@@ -0,0 +1,157 @@
+/****************************************************
+ ORGAN DEFINES
+****************************************************/
+
+/obj/item/organ/external/chest
+ name = "upper body"
+ limb_name = "chest"
+ icon_name = "torso"
+ max_damage = 100
+ min_broken_damage = 35
+ w_class = 5
+ body_part = UPPER_TORSO
+ vital = 1
+ amputation_point = "spine"
+ gendered_icon = 1
+ cannot_amputate = 1
+ parent_organ = null
+ encased = "ribcage"
+
+/obj/item/organ/external/groin
+ name = "lower body"
+ limb_name = "groin"
+ icon_name = "groin"
+ max_damage = 100
+ min_broken_damage = 35
+ w_class = 4
+ body_part = LOWER_TORSO
+ vital = 1
+ parent_organ = "chest"
+ amputation_point = "lumbar"
+ gendered_icon = 1
+
+/obj/item/organ/external/arm
+ limb_name = "l_arm"
+ name = "left arm"
+ icon_name = "l_arm"
+ max_damage = 50
+ min_broken_damage = 30
+ w_class = 3
+ body_part = ARM_LEFT
+ parent_organ = "chest"
+ amputation_point = "left shoulder"
+ can_grasp = 1
+
+/obj/item/organ/external/arm/right
+ limb_name = "r_arm"
+ name = "right arm"
+ icon_name = "r_arm"
+ body_part = ARM_RIGHT
+ amputation_point = "right shoulder"
+
+/obj/item/organ/external/leg
+ limb_name = "l_leg"
+ name = "left leg"
+ icon_name = "l_leg"
+ max_damage = 50
+ min_broken_damage = 30
+ w_class = 3
+ body_part = LEG_LEFT
+ icon_position = LEFT
+ parent_organ = "groin"
+ amputation_point = "left hip"
+ can_stand = 1
+
+/obj/item/organ/external/leg/right
+ limb_name = "r_leg"
+ name = "right leg"
+ icon_name = "r_leg"
+ body_part = LEG_RIGHT
+ icon_position = RIGHT
+ amputation_point = "right hip"
+
+/obj/item/organ/external/foot
+ limb_name = "l_foot"
+ name = "left foot"
+ icon_name = "l_foot"
+ max_damage = 30
+ min_broken_damage = 15
+ w_class = 2
+ body_part = FOOT_LEFT
+ icon_position = LEFT
+ parent_organ = "l_leg"
+ amputation_point = "left ankle"
+ can_stand = 1
+
+/obj/item/organ/external/foot/removed()
+ if(owner) owner.unEquip(owner.shoes)
+ ..()
+
+/obj/item/organ/external/foot/right
+ limb_name = "r_foot"
+ name = "right foot"
+ icon_name = "r_foot"
+ body_part = FOOT_RIGHT
+ icon_position = RIGHT
+ parent_organ = "r_leg"
+ amputation_point = "right ankle"
+
+/obj/item/organ/external/hand
+ limb_name = "l_hand"
+ name = "left hand"
+ icon_name = "l_hand"
+ max_damage = 30
+ min_broken_damage = 15
+ w_class = 2
+ body_part = HAND_LEFT
+ parent_organ = "l_arm"
+ amputation_point = "left wrist"
+ can_grasp = 1
+
+/obj/item/organ/external/hand/removed()
+ owner.unEquip(owner.gloves)
+ ..()
+
+/obj/item/organ/external/hand/right
+ limb_name = "r_hand"
+ name = "right hand"
+ icon_name = "r_hand"
+ body_part = HAND_RIGHT
+ parent_organ = "r_arm"
+ amputation_point = "right wrist"
+
+/obj/item/organ/external/head
+ limb_name = "head"
+ icon_name = "head"
+ name = "head"
+ max_damage = 75
+ min_broken_damage = 35
+ w_class = 3
+ body_part = HEAD
+ vital = 1
+ parent_organ = "chest"
+ amputation_point = "neck"
+ gendered_icon = 1
+ encased = "skull"
+ var/can_intake_reagents = 1
+
+/obj/item/organ/external/head/removed()
+ if(owner)
+ name = "[owner.real_name]'s head"
+ owner.unEquip(owner.glasses)
+ owner.unEquip(owner.head)
+ owner.unEquip(owner.l_ear)
+ owner.unEquip(owner.r_ear)
+ owner.unEquip(owner.wear_mask)
+ spawn(1)
+ owner.update_hair()
+ ..()
+
+/obj/item/organ/external/head/take_damage(brute, burn, sharp, edge, used_weapon = null, list/forbidden_limbs = list())
+ ..(brute, burn, sharp, edge, used_weapon, forbidden_limbs)
+ if (!disfigured)
+ if (brute_dam > 40)
+ if (prob(50))
+ disfigure("brute")
+ if (burn_dam > 40)
+ disfigure("burn")
diff --git a/code/modules/organs/subtypes/unbreakable.dm b/code/modules/organs/subtypes/unbreakable.dm
new file mode 100644
index 00000000000..74dc1ae3de7
--- /dev/null
+++ b/code/modules/organs/subtypes/unbreakable.dm
@@ -0,0 +1,34 @@
+// Slime limbs.
+/obj/item/organ/external/chest/unbreakable
+ cannot_break = 1
+
+/obj/item/organ/external/groin/unbreakable
+ cannot_break = 1
+
+/obj/item/organ/external/arm/unbreakable
+ cannot_break = 1
+
+/obj/item/organ/external/arm/right/unbreakable
+ cannot_break = 1
+
+/obj/item/organ/external/leg/unbreakable
+ cannot_break = 1
+
+/obj/item/organ/external/leg/right/unbreakable
+ cannot_break = 1
+
+/obj/item/organ/external/foot/unbreakable
+ cannot_break = 1
+
+/obj/item/organ/external/foot/right/unbreakable
+ cannot_break = 1
+
+/obj/item/organ/external/hand/unbreakable
+ cannot_break = 1
+
+/obj/item/organ/external/hand/right/unbreakable
+ cannot_break = 1
+
+/obj/item/organ/external/head/unbreakable
+ cannot_break = 1
+
diff --git a/code/modules/organs/subtypes/wryn.dm b/code/modules/organs/subtypes/wryn.dm
new file mode 100644
index 00000000000..5d0c687f9f2
--- /dev/null
+++ b/code/modules/organs/subtypes/wryn.dm
@@ -0,0 +1,11 @@
+//WRYN ORGAN
+/obj/item/organ/wryn/hivenode
+ name = "antennae"
+ parent_organ = "head"
+
+/obj/item/organ/wryn/hivenode
+ name = "antennae"
+ organ_tag = "antennae"
+ icon = 'icons/mob/human_races/r_wryn.dmi'
+ icon_state = "antennae"
+
\ No newline at end of file
diff --git a/code/modules/organs/subtypes/xenos.dm b/code/modules/organs/subtypes/xenos.dm
new file mode 100644
index 00000000000..7052237b163
--- /dev/null
+++ b/code/modules/organs/subtypes/xenos.dm
@@ -0,0 +1,66 @@
+//XENOMORPH ORGANS
+/obj/item/organ/xenos/eggsac
+ name = "egg sac"
+ parent_organ = "groin"
+
+/obj/item/organ/xenos/plasmavessel
+ name = "plasma vessel"
+ parent_organ = "chest"
+ var/stored_plasma = 0
+ var/max_plasma = 500
+
+/obj/item/organ/xenos/plasmavessel/queen
+ name = "bloated plasma vessel"
+ stored_plasma = 200
+ max_plasma = 500
+
+/obj/item/organ/xenos/plasmavessel/sentinel
+ stored_plasma = 100
+ max_plasma = 250
+
+/obj/item/organ/xenos/plasmavessel/hunter
+ name = "tiny plasma vessel"
+ stored_plasma = 100
+ max_plasma = 150
+
+/obj/item/organ/xenos/acidgland
+ name = "acid gland"
+ parent_organ = "head"
+
+/obj/item/organ/xenos/hivenode
+ name = "hive node"
+ parent_organ = "chest"
+
+/obj/item/organ/xenos/resinspinner
+ name = "resin spinner"
+ parent_organ = "head"
+
+/obj/item/organ/xenos
+ name = "xeno organ"
+ icon = 'icons/effects/blood.dmi'
+ desc = "It smells like an accident in a chemical factory."
+
+/obj/item/organ/xenos/eggsac
+ name = "egg sac"
+ icon_state = "xgibmid1"
+ organ_tag = "egg sac"
+
+/obj/item/organ/xenos/plasmavessel
+ name = "plasma vessel"
+ icon_state = "xgibdown1"
+ organ_tag = "plasma vessel"
+
+/obj/item/organ/xenos/acidgland
+ name = "acid gland"
+ icon_state = "xgibtorso"
+ organ_tag = "acid gland"
+
+/obj/item/organ/xenos/hivenode
+ name = "hive node"
+ icon_state = "xgibmid2"
+ organ_tag = "hive node"
+
+/obj/item/organ/xenos/resinspinner
+ name = "hive node"
+ icon_state = "xgibmid2"
+ organ_tag = "resin spinner"
\ No newline at end of file
diff --git a/code/modules/organs/wound.dm b/code/modules/organs/wound.dm
index bd044163ff3..55a2f3f5cee 100644
--- a/code/modules/organs/wound.dm
+++ b/code/modules/organs/wound.dm
@@ -36,9 +36,8 @@
var/list/stages
// internal wounds can only be fixed through surgery
var/internal = 0
- // maximum stage at which bleeding should still happen, counted from the right rather than the left of the list
- // 1 means all stages except the last should bleed
- var/max_bleeding_stage = 1
+ // maximum stage at which bleeding should still happen. Beyond this stage bleeding is prevented.
+ var/max_bleeding_stage = 0
// one of CUT, BRUISE, BURN
var/damage_type = CUT
// whether this wound needs a bandage/salve to heal at all
@@ -64,8 +63,6 @@
src.damage = damage
- max_bleeding_stage = src.desc_list.len - max_bleeding_stage
-
// initialize with the appropriate stage
src.init_stage(damage)
@@ -247,8 +244,9 @@
/** CUTS **/
/datum/wound/cut/small
- // link wound descriptions to amounts of damage
- max_bleeding_stage = 2
+ // Minor cuts have max_bleeding_stage set to the stage that bears the wound type's name.
+ // The major cut types have the max_bleeding_stage set to the clot stage (which is accordingly given the "blood soaked" descriptor).
+ max_bleeding_stage = 3
stages = list("ugly ripped cut" = 20, "ripped cut" = 10, "cut" = 5, "healing cut" = 2, "small scab" = 0)
damage_type = CUT
@@ -263,25 +261,25 @@
damage_type = CUT
/datum/wound/cut/gaping
- max_bleeding_stage = 2
- stages = list("gaping wound" = 50, "large blood soaked clot" = 25, "large clot" = 15, "small angry scar" = 5, "small straight scar" = 0)
+ max_bleeding_stage = 3
+ stages = list("gaping wound" = 50, "large blood soaked clot" = 25, "blood soaked clot" = 15, "small angry scar" = 5, "small straight scar" = 0)
damage_type = CUT
/datum/wound/cut/gaping_big
- max_bleeding_stage = 2
- stages = list("big gaping wound" = 60, "healing gaping wound" = 40, "large angry scar" = 10, "large straight scar" = 0)
+ max_bleeding_stage = 3
+ stages = list("big gaping wound" = 60, "healing gaping wound" = 40, "large blood soaked clot" = 25, "large angry scar" = 10, "large straight scar" = 0)
damage_type = CUT
datum/wound/cut/massive
- max_bleeding_stage = 2
- stages = list("massive wound" = 70, "massive healing wound" = 50, "massive angry scar" = 10, "massive jagged scar" = 0)
+ max_bleeding_stage = 3
+ stages = list("massive wound" = 70, "massive healing wound" = 50, "massive blood soaked clot" = 25, "massive angry scar" = 10, "massive jagged scar" = 0)
damage_type = CUT
/** BRUISES **/
/datum/wound/bruise
- stages = list("monumental bruise" = 80, "huge bruise" = 50, "large bruise" = 30,\
+ stages = list("monumental bruise" = 80, "huge bruise" = 50, "large bruise" = 30,
"moderate bruise" = 20, "small bruise" = 10, "tiny bruise" = 5)
- max_bleeding_stage = 3
+ max_bleeding_stage = 3 //only large bruise and above can bleed.
autoheal_cutoff = 30
damage_type = BRUISE
@@ -309,18 +307,38 @@ datum/wound/cut/massive
/** INTERNAL BLEEDING **/
/datum/wound/internal_bleeding
internal = 1
- stages = list("severed vein" = 30, "cut vein" = 20, "damaged vein" = 10, "bruised vein" = 5)
+ stages = list("severed artery" = 30, "cut artery" = 20, "damaged artery" = 10, "bruised artery" = 5)
autoheal_cutoff = 5
- max_bleeding_stage = 0 //all stages bleed. It's called internal bleeding after all.
+ max_bleeding_stage = 4 //all stages bleed. It's called internal bleeding after all.
+
/** EXTERNAL ORGAN LOSS **/
/datum/wound/lost_limb
- damage_type = CUT
- stages = list("ripped stump" = 65, "bloody stump" = 50, "clotted stump" = 25, "scarred stump" = 0)
- max_bleeding_stage = 3
- can_merge(var/datum/wound/other)
- return 0 //cannot be merged
+/datum/wound/lost_limb/New(var/obj/item/organ/external/lost_limb, var/losstype, var/clean)
+ var/damage_amt = lost_limb.max_damage
+ if(clean) damage_amt /= 2
+
+ switch(losstype)
+ if(DROPLIMB_EDGE, DROPLIMB_BLUNT)
+ damage_type = CUT
+ max_bleeding_stage = 3 //clotted stump and above can bleed.
+ stages = list(
+ "ripped stump" = damage_amt*1.3,
+ "bloody stump" = damage_amt,
+ "clotted stump" = damage_amt*0.5,
+ "scarred stump" = 0
+ )
+ if(DROPLIMB_BURN)
+ damage_type = BURN
+ stages = list(
+ "ripped charred stump" = damage_amt*1.3,
+ "charred stump" = damage_amt,
+ "scarred stump" = damage_amt*0.5,
+ "scarred stump" = 0
+ )
+
+ ..(damage_amt)
-/datum/wound/lost_limb/small
- stages = list("ripped hole" = 40, "bloody hole" = 30, "clotted hole" = 15, "scarred hole" = 0)
+/datum/wound/lost_limb/can_merge(var/datum/wound/other)
+ return 0 //cannot be merged
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 7c235022c92..07c0ea13e8d 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -641,16 +641,15 @@
//Synthetic human mob goes here.
if(istype(user,/mob/living/carbon/human))
var/mob/living/carbon/human/H = user
- if(H.species.flags & IS_SYNTHETIC && H.a_intent == "grab")
+ if(!isnull(H.internal_organs_by_name["cell"]) && H.a_intent == "grab")
if(emagged || stat & BROKEN)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
- H << "The APC power currents surge eratically, damaging your chassis!"
+ H << "The APC power currents surge erratically, damaging your chassis!"
H.adjustFireLoss(10,0)
else if(src.cell && src.cell.charge > 0)
if(H.nutrition < 450)
-
if(src.cell.charge >= 500)
H.nutrition += 50
src.cell.charge -= 500
@@ -659,14 +658,15 @@
src.cell.charge = 0
user << "You slot your fingers into the APC interface and siphon off some of the stored charge for your own use."
- if(src.cell.charge < 0) src.cell.charge = 0
- if(H.nutrition > 500) H.nutrition = 500
+ if(src.cell.charge < 0)
+ src.cell.charge = 0
+ if(H.nutrition > 500)
+ H.nutrition = 500
src.charging = 1
-
else
user << "You are already fully charged."
else
- user << "There is no charge to draw from that APC."
+ user << "There is no charge to draw from that APC."
return
if(usr == user && opened && (!issilicon(user)))
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index 38a1c5e927e..de6fb00c621 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -496,31 +496,29 @@ obj/structure/cable/proc/cableColor(var/colorC)
///////////////////////////////////
// General procedures
///////////////////////////////////
-
//you can use wires to heal robotics
/obj/item/stack/cable_coil/attack(mob/M as mob, mob/user as mob)
- if(istype(M,/mob/living/carbon/human))
+ if(ishuman(M))
var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/S = H.get_organ(user.zone_sel.selecting)
- if(!(S.status & ORGAN_ROBOT) || user.a_intent != "help")
+ var/obj/item/organ/external/S = H.organs_by_name[user.zone_sel.selecting]
+
+ if(!S)
+ return
+ if(!(S.status & ORGAN_ROBOT) || user.a_intent != "help" || S.open == 2)
return ..()
- if(H.species.flags & IS_SYNTHETIC)
- if(M == user)
- user << "\red You can't repair damage to your own body - it's against OH&S."
- return
-
- if(S.burn_dam > 0 && use(1))
- S.heal_damage(0,15,0,1)
- user.visible_message("\red \The [user] repairs some burn damage on \the [M]'s [S.name] with \the [src].")
- return
- else
- user << "Nothing to fix!"
-
+ if(S.burn_dam)
+ if(S.burn_dam < ROBOLIMB_SELF_REPAIR_CAP)
+ S.heal_damage(0,15,0,1)
+ user.visible_message("\The [user] repairs some burn damage on \the [M]'s [S.name] with \the [src].")
+ else if(S.open != 2)
+ user << "The damage is far too severe to patch over externally."
+ return 1
+ else if(S.open != 2)
+ user << "Nothing to fix!"
else
return ..()
-
/obj/item/stack/cable_coil/update_icon()
if (!color)
color = pick(COLOR_RED, COLOR_BLUE, COLOR_GREEN, COLOR_ORANGE, COLOR_WHITE, COLOR_PINK, COLOR_YELLOW, COLOR_CYAN)
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index d4204d7535e..8542729e3d1 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -130,6 +130,11 @@
forcedodge = -1
else
*/
+ if(ishuman(A))
+ var/mob/living/carbon/human/H = A
+ var/obj/item/organ/external/organ = H.get_organ(check_zone(def_zone))
+ if(isnull(organ))
+ return
if(silenced)
playsound(loc, hitsound, 5, 1, -1)
M << "\red You've been shot in the [parse_zone(def_zone)] by the [src.name]!"
diff --git a/code/modules/reagents/newchem/toxins.dm b/code/modules/reagents/newchem/toxins.dm
index 63e6304dd55..00135ad0c05 100644
--- a/code/modules/reagents/newchem/toxins.dm
+++ b/code/modules/reagents/newchem/toxins.dm
@@ -125,7 +125,7 @@ datum/reagent/neurotoxin2/on_mob_life(var/mob/living/M as mob)
if(current_cycle >= 5)
if(prob(5))
M.emote("drool")
- if(M.brainloss < 60)
+ if(M.getBrainLoss() < 60)
M.adjustBrainLoss(1*REM)
M.adjustToxLoss(1*REM)
if(current_cycle >= 9)
diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm
index 98366e36e22..e5f1345f8fd 100644
--- a/code/modules/reagents/reagent_containers/borghydro.dm
+++ b/code/modules/reagents/reagent_containers/borghydro.dm
@@ -70,18 +70,29 @@
/obj/item/weapon/reagent_containers/borghypo/attack(mob/living/M as mob, mob/user as mob)
var/datum/reagents/R = reagent_list[mode]
if(!R.total_volume)
- user << "\red The injector is empty."
+ user << "The injector is empty."
return
- if (!(istype(M)))
+ if (!istype(M))
return
+
+ var/mob/living/carbon/human/H = M
+ if(istype(H))
+ var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting)
+ if(!affected)
+ user << "\The [H] is missing that limb!"
+ return
+ else if(affected.status & ORGAN_ROBOT)
+ user << "You cannot inject a robotic limb."
+ return
+
if (R.total_volume && M.can_inject(user,1))
- user << "\blue You inject [M] with the injector."
- M << "\red You feel a tiny prick!"
+ user << "You inject [M] with the injector."
+ M << "You feel a tiny prick!"
R.add_reagent(M)
if(M.reagents)
var/trans = R.trans_to(M, amount_per_transfer_from_this)
- user << "\blue [trans] units injected. [R.total_volume] units remaining."
+ user << "[trans] units injected. [R.total_volume] units remaining."
return
/obj/item/weapon/reagent_containers/borghypo/attack_self(mob/user as mob)
diff --git a/code/modules/reagents/reagent_containers/food/drinks.dm b/code/modules/reagents/reagent_containers/food/drinks.dm
index 7396f307955..8528e364dc7 100644
--- a/code/modules/reagents/reagent_containers/food/drinks.dm
+++ b/code/modules/reagents/reagent_containers/food/drinks.dm
@@ -30,8 +30,8 @@
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- if(H.species.flags & IS_SYNTHETIC)
- H << "\red You have a monitor for a head, where do you think you're going to put that?"
+ if(!H.check_has_mouth())
+ user << "Where do you intend to put \the [src]? You don't have a mouth!"
return
M << "\blue You swallow a gulp of [src]."
@@ -45,8 +45,8 @@
else if( istype(M, /mob/living/carbon/human) )
var/mob/living/carbon/human/H = M
- if(H.species.flags & IS_SYNTHETIC)
- user << "\red They have a monitor for a head, where do you think you're going to put that?"
+ if(!H.check_has_mouth())
+ user << "Where do you intend to put \the [src]? \The [H] doesn't have a mouth!"
return
for(var/mob/O in viewers(world.view, user))
diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm
index d77edbb6903..760988b4977 100644
--- a/code/modules/reagents/reagent_containers/food/snacks.dm
+++ b/code/modules/reagents/reagent_containers/food/snacks.dm
@@ -48,8 +48,8 @@
if(M == user) //If you're eating it yourself
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- if(H.species.flags & IS_SYNTHETIC)
- H << "\red You have a monitor for a head, where do you think you're going to put that?"
+ if(!H.check_has_mouth())
+ user << "Where do you intend to put \the [src]? You don't have a mouth!"
return
if (fullness <= 50)
M << "\red You hungrily chew out a piece of [src] and gobble it!"
@@ -65,8 +65,8 @@
else
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- if(H.species.flags & IS_SYNTHETIC)
- H << "\red They have a monitor for a head, where do you think you're going to put that?"
+ if(!H.check_has_mouth())
+ user << "Where do you intend to put \the [src]? \The [H] doesn't have a mouth!"
return
if(!istype(M, /mob/living/carbon/slime)) //If you're feeding it to someone else.
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index 0e706d5ebe5..534de035872 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -23,8 +23,8 @@
if(M == user)
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
- if(H.species.flags & IS_SYNTHETIC)
- H << "You have a monitor for a head, where do you think you're going to put that?"
+ if(!H.check_has_mouth())
+ user << "Where do you intend to put \the [src]? You don't have a mouth!"
return
M << "You [apply_method] [src]."
@@ -41,8 +41,8 @@
else if(istype(M, /mob/living/carbon/human) )
var/mob/living/carbon/human/H = M
- if(H.species.flags & IS_SYNTHETIC)
- user << "They have a monitor for a head, where do you think you're going to put that?"
+ if(!H.check_has_mouth())
+ user << "Where do you intend to put \the [src]? \The [H] doesn't have a mouth!"
return
for(var/mob/O in viewers(world.view, user))
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 8211ff7f8d7..408076341ee 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -168,11 +168,20 @@
if(target.reagents.total_volume >= target.reagents.maximum_volume)
user << "\red [target] is full."
return
+
+ var/mob/living/carbon/human/H = target
+ if(istype(H))
+ var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting)
+ if(!affected)
+ user << "\The [H] is missing that limb!"
+ return
+ /* else if(affected.status & ORGAN_ROBOT)
+ user << "You cannot inject a robotic limb."
+ return */
if(ismob(target) && target != user)
var/time = 30 //Injecting through a hardsuit takes longer due to needing to find a port.
if(istype(target,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = target
if(H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space))
time = 60
diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm
index 2aac7c6ab91..9bfb67034ab 100644
--- a/code/modules/surgery/bones.dm
+++ b/code/modules/surgery/bones.dm
@@ -16,7 +16,7 @@
can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- return affected && affected.open == 2 && affected.stage == 0
+ return affected && !(affected.status & ORGAN_ROBOT) && affected.open == 2 && affected.stage == 0
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)
@@ -48,7 +48,7 @@
can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- return affected && affected.limb_name != "head" && affected.open == 2 && affected.stage == 1
+ return affected && !(affected.status & ORGAN_ROBOT) && affected.limb_name != "head" && affected.open == 2 && affected.stage == 1
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)
@@ -85,7 +85,7 @@
can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- return affected && affected.limb_name == "head" && affected.open == 2 && affected.stage == 1
+ return affected && !(affected.status & ORGAN_ROBOT) && affected.limb_name == "head" && affected.open == 2 && affected.stage == 1
begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("[user] is beginning piece together [target]'s skull with \the [tool]." , \
@@ -119,7 +119,7 @@
can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- return affected && affected.open == 2 && affected.stage == 2
+ return affected && !(affected.status & ORGAN_ROBOT) && affected.open == 2 && affected.stage == 2
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)
diff --git a/code/modules/surgery/encased.dm b/code/modules/surgery/encased.dm
index fedf5bbc1c0..48baea91d3b 100644
--- a/code/modules/surgery/encased.dm
+++ b/code/modules/surgery/encased.dm
@@ -12,7 +12,7 @@
return 0
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- return affected && affected.encased && affected.open >= 2
+ return affected && !(affected.status & ORGAN_ROBOT) && affected.encased && affected.open >= 2
/datum/surgery_step/open_encased/saw
diff --git a/code/modules/surgery/eye.dm b/code/modules/surgery/eye.dm
index 072d95b001b..327a90170d9 100644
--- a/code/modules/surgery/eye.dm
+++ b/code/modules/surgery/eye.dm
@@ -10,7 +10,7 @@
if (!hasorgans(target))
return 0
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- if (!affected)
+ if (!affected || (affected.status & ORGAN_ROBOT))
return 0
return target_zone == "eyes"
diff --git a/code/modules/surgery/face.dm b/code/modules/surgery/face.dm
index c5779936966..9513bbe8f07 100644
--- a/code/modules/surgery/face.dm
+++ b/code/modules/surgery/face.dm
@@ -10,7 +10,7 @@
if (!hasorgans(target))
return 0
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- if (!affected)
+ if (!affected || (affected.status & ORGAN_ROBOT))
return 0
return target_zone == "mouth"
diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm
index 6f8e8f537d0..5c503a035ac 100644
--- a/code/modules/surgery/generic.dm
+++ b/code/modules/surgery/generic.dm
@@ -15,8 +15,6 @@
return 0
if (affected.status & ORGAN_DESTROYED)
return 0
- if (target_zone == "head" && target.species && (target.species.flags & IS_SYNTHETIC))
- return 1
if (affected.status & ORGAN_ROBOT)
return 0
return 1
diff --git a/code/modules/surgery/headreattach.dm b/code/modules/surgery/headreattach.dm
deleted file mode 100644
index 4be43c44fd6..00000000000
--- a/code/modules/surgery/headreattach.dm
+++ /dev/null
@@ -1,33 +0,0 @@
-//This is an uguu head restoration surgery TOTALLY not yoinked from chinsky's limb reattacher
-/datum/surgery_step/attach_head/
- priority = 3 // Must be higher than /datum/surgery_step/internal
- allowed_tools = list(/obj/item/organ/external/head = 100)
- can_infect = 0
-
- min_duration = 80
- max_duration = 100
-
- can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/head = target.get_organ(target_zone)
- return isnull(head) && target_zone == "head" && !isnull(target.species.has_limbs["head"])
-
- begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- user.visible_message("[user] starts attaching [tool] to [target]'s neck.", \
- "You start attaching [tool] to [target]'s neck.")
-
- end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- user.visible_message("\blue [user] has attached [target]'s head to the body.", \
- "\blue You have attached [target]'s head to the body.")
- var/obj/item/organ/external/head = tool
- user.unEquip(head)
- head.replaced(target)
- head.loc = target
- head.status = 0
- target.update_body()
- target.updatehealth()
- target.UpdateDamageIcon()
-
- fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- user.visible_message("\red [user]'s hand slips, damaging [target]'s neck!", \
- "\red Your hand slips, damaging [target]'s neck!")
- target.apply_damage(10, BRUTE, null, sharp=1)
diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm
index 083f5e3c6d7..d4d51e41f76 100644
--- a/code/modules/surgery/implant.dm
+++ b/code/modules/surgery/implant.dm
@@ -31,6 +31,12 @@
if ("groin")
return "abdominal"
return ""
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
+ user.visible_message("\red [user]'s hand slips, scraping around inside [target]'s [affected.name] with \the [tool]!", \
+ "\red Your hand slips, scraping around inside [target]'s [affected.name] with \the [tool]!")
+ affected.createwound(CUT, 20)
/datum/surgery_step/cavity/make_space
allowed_tools = list(
@@ -59,12 +65,6 @@
user.visible_message("\blue [user] makes some space inside [target]'s [get_cavity(affected)] cavity with \the [tool].", \
"\blue You make some space inside [target]'s [get_cavity(affected)] cavity with \the [tool]." )
- fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
- user.visible_message("\red [user]'s hand slips, scraping tissue inside [target]'s [affected.name] with \the [tool]!", \
- "\red Your hand slips, scraping tissue inside [target]'s [affected.name] with \the [tool]!")
- affected.createwound(CUT, 20)
-
/datum/surgery_step/cavity/close_space
priority = 2
allowed_tools = list(
@@ -94,12 +94,6 @@
user.visible_message("\blue [user] mends [target]'s [get_cavity(affected)] cavity walls with \the [tool].", \
"\blue You mend [target]'s [get_cavity(affected)] cavity walls with \the [tool]." )
- fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
- user.visible_message("\red [user]'s hand slips, scraping tissue inside [target]'s [affected.name] with \the [tool]!", \
- "\red Your hand slips, scraping tissue inside [target]'s [affected.name] with \the [tool]!")
- affected.createwound(CUT, 20)
-
/datum/surgery_step/cavity/place_item
priority = 0
allowed_tools = list(/obj/item = 100)
@@ -129,7 +123,7 @@
else
user.visible_message("\blue [user] puts \the [tool] inside [target]'s [get_cavity(affected)] cavity.", \
"\blue You put \the [tool] inside [target]'s [get_cavity(affected)] cavity." )
- if (tool.w_class > get_max_wclass(affected)/2 && prob(50))
+ if (tool.w_class > get_max_wclass(affected)/2 && prob(50) && !(affected.status & ORGAN_ROBOT))
user << "\red You tear some vessels trying to fit such big object in this cavity."
var/datum/wound/internal_bleeding/I = new ()
affected.wounds += I
@@ -139,12 +133,6 @@
tool.loc = target
affected.cavity = 0
- fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
- user.visible_message("\red [user]'s hand slips, scraping tissue inside [target]'s [affected.name] with \the [tool]!", \
- "\red Your hand slips, scraping tissue inside [target]'s [affected.name] with \the [tool]!")
- affected.createwound(CUT, 20)
-
//////////////////////////////////////////////////////////////////
// IMPLANT/ITEM REMOVAL SURGERY //
//////////////////////////////////////////////////////////////////
@@ -161,9 +149,9 @@
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 poking around inside the incision on [target]'s [affected.name] with \the [tool].", \
- "You start poking around inside the incision on [target]'s [affected.name] with \the [tool]" )
- target.custom_pain("The pain in your chest is living hell!",1)
+ user.visible_message("[user] starts poking around inside [target]'s [affected.name] with \the [tool].", \
+ "You start poking around inside [target]'s [affected.name] with \the [tool]." )
+ target.custom_pain("The pain in your [affected.name] is living hell!",1)
..()
end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -185,8 +173,8 @@
find_prob +=50
if (prob(find_prob))
- user.visible_message("\blue [user] takes something out of incision on [target]'s [affected.name] with \the [tool].", \
- "\blue You take [obj] out of incision on [target]'s [affected.name]s with \the [tool]." )
+ user.visible_message("\blue [user] takes something out of [target]'s [affected.name] with \the [tool].", \
+ "\blue You take [obj] out of [target]'s [affected.name]s with \the [tool]." )
affected.implants -= obj
target.hud_updateflag |= 1 << IMPLOYAL_HUD
@@ -221,10 +209,8 @@
"\blue You could not find anything inside [target]'s [affected.name]." )
fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ ..()
var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
- user.visible_message("\red [user]'s hand slips, scraping tissue inside [target]'s [affected.name] with \the [tool]!", \
- "\red Your hand slips, scraping tissue inside [target]'s [affected.name] with \the [tool]!")
- affected.createwound(CUT, 20)
if (affected.implants.len)
var/fail_prob = 10
fail_prob += 100 - tool_quality(tool)
diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm
new file mode 100644
index 00000000000..e264753633f
--- /dev/null
+++ b/code/modules/surgery/limb_reattach.dm
@@ -0,0 +1,129 @@
+//Procedures in this file: Robotic limbs attachment, meat limbs attachment
+//////////////////////////////////////////////////////////////////
+// LIMB SURGERY //
+//////////////////////////////////////////////////////////////////
+
+/datum/surgery_step/limb/
+ priority = 3 // Must be higher than /datum/surgery_step/internal
+ can_infect = 0
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if (!hasorgans(target))
+ return 0
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if (affected)
+ return 0
+ var/list/organ_data = target.species.has_limbs["[target_zone]"]
+ return !isnull(organ_data)
+
+/datum/surgery_step/limb/attach
+ allowed_tools = list(/obj/item/organ/external = 100)
+
+ min_duration = 50
+ max_duration = 70
+
+ 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].", \
+ "You start attaching [E.name] to [target]'s [E.amputation_point].")
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/E = tool
+ user.visible_message("[user] has attached [target]'s [E.name] to the [E.amputation_point].", \
+ "You have attached [target]'s [E.name] to the [E.amputation_point].")
+ user.unEquip(E)
+ E.replaced(target)
+ E.forceMove(target)
+ target.update_body()
+ target.updatehealth()
+ target.UpdateDamageIcon()
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/E = tool
+ user.visible_message("[user]'s hand slips, damaging [target]'s [E.amputation_point]!", \
+ "Your hand slips, damaging [target]'s [E.amputation_point]!")
+ target.apply_damage(10, BRUTE, null, sharp=1)
+
+/datum/surgery_step/limb/connect
+ allowed_tools = list(
+ /obj/item/weapon/hemostat = 100, \
+ /obj/item/stack/cable_coil = 75, \
+ /obj/item/device/assembly/mousetrap = 20
+ )
+ can_infect = 1
+
+ min_duration = 100
+ max_duration = 120
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/E = target.get_organ(target_zone)
+ return E && !E.is_stump() && (E.status & ORGAN_DESTROYED)
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/E = target.get_organ(target_zone)
+ user.visible_message("[user] starts connecting tendons and muscles in [target]'s [E.amputation_point] with [tool].", \
+ "You start connecting tendons and muscle in [target]'s [E.amputation_point].")
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/E = target.get_organ(target_zone)
+ user.visible_message("[user] has connected tendons and muscles in [target]'s [E.amputation_point] with [tool].", \
+ "You have connected tendons and muscles in [target]'s [E.amputation_point] with [tool].")
+ E.status &= ~ORGAN_DESTROYED
+ if(E.children)
+ for(var/obj/item/organ/external/C in E.children)
+ C.status &= ~ORGAN_DESTROYED
+ target.update_body()
+ target.updatehealth()
+ target.UpdateDamageIcon()
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/E = tool
+ user.visible_message("[user]'s hand slips, damaging [target]'s [E.amputation_point]!", \
+ "Your hand slips, damaging [target]'s [E.amputation_point]!")
+ target.apply_damage(10, BRUTE, null, sharp=1)
+
+/datum/surgery_step/limb/mechanize
+ allowed_tools = list(/obj/item/robot_parts = 100)
+
+ min_duration = 80
+ max_duration = 100
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if(..())
+ var/obj/item/robot_parts/p = tool
+ if (p.part)
+ if (!(target_zone in p.part))
+ return 0
+ return isnull(target.get_organ(target_zone))
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("[user] starts attaching \the [tool] to [target].", \
+ "You start attaching \the [tool] to [target].")
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/robot_parts/L = tool
+ user.visible_message("[user] has attached \the [tool] to [target].", \
+ "You have attached \the [tool] to [target].")
+
+ if(L.part)
+ for(var/part_name in L.part)
+ if(!isnull(target.get_organ(part_name)))
+ continue
+ var/list/organ_data = target.species.has_limbs["[part_name]"]
+ if(!organ_data)
+ continue
+ var/new_limb_type = organ_data["path"]
+ var/obj/item/organ/external/new_limb = new new_limb_type(target)
+ new_limb.robotize(L.model_info)
+ if(L.sabotaged)
+ new_limb.sabotaged = 1
+
+ target.update_body()
+ target.updatehealth()
+ target.UpdateDamageIcon()
+
+ qdel(tool)
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("[user]'s hand slips, damaging [target]'s flesh!", \
+ "Your hand slips, damaging [target]'s flesh!")
+ target.apply_damage(10, BRUTE, null, sharp=1)
diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm
index f3d50555bb0..6fe84897c3b 100644
--- a/code/modules/surgery/organs_internal.dm
+++ b/code/modules/surgery/organs_internal.dm
@@ -178,75 +178,6 @@
if(I && I.damage > 0)
I.take_damage(dam_amt,0)
-/datum/surgery_step/internal/fix_organ_robotic //For artificial organs
- allowed_tools = list(
- /obj/item/stack/nanopaste = 100, \
- /obj/item/weapon/bonegel = 30, \
- /obj/item/weapon/screwdriver = 70, \
- )
-
- min_duration = 70
- max_duration = 90
-
- can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
-
- if (!hasorgans(target))
- return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
- if(!affected) return
- var/is_organ_damaged = 0
- for(var/obj/item/organ/I in affected.internal_organs)
- if(I.damage > 0 && I.robotic >= 2)
- is_organ_damaged = 1
- break
- return ..() && is_organ_damaged
-
- begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
-
- if (!hasorgans(target))
- return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
-
- for(var/obj/item/organ/I in affected.internal_organs)
- if(I && I.damage > 0)
- if(I.robotic >= 2)
- user.visible_message("[user] starts mending the damage to [target]'s [I.name]'s mechanisms.", \
- "You start mending the damage to [target]'s [I.name]'s mechanisms." )
-
- target.custom_pain("The pain in your [affected.name] is living hell!",1)
- ..()
-
- end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
-
- if (!hasorgans(target))
- return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
-
- for(var/obj/item/organ/I in affected.internal_organs)
-
- if(I && I.damage > 0)
- if(I.robotic >= 2)
- user.visible_message("\blue [user] repairs [target]'s [I.name] with [tool].", \
- "\blue You repair [target]'s [I.name] with [tool]." )
- I.damage = 0
-
- fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
-
- if (!hasorgans(target))
- return
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
-
- user.visible_message("\red [user]'s hand slips, gumming up the mechanisms inside of [target]'s [affected.name] with \the [tool]!", \
- "\red Your hand slips, gumming up the mechanisms inside of [target]'s [affected.name] with \the [tool]!")
-
- target.adjustToxLoss(5)
- affected.createwound(CUT, 5)
-
- for(var/obj/item/organ/I in affected.internal_organs)
- if(I)
- I.take_damage(rand(3,5),0)
-
-
/datum/surgery_step/internal/detatch_organ
allowed_tools = list(
@@ -262,13 +193,18 @@
if (!..())
return 0
+
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+
+ if(!(affected && !(affected.status & ORGAN_ROBOT)))
+ return 0
target.op_stage.current_organ = null
var/list/attached_organs = list()
for(var/organ in target.internal_organs_by_name)
var/obj/item/organ/I = target.internal_organs_by_name[organ]
- if(I && !I.status && I.parent_organ == target_zone)
+ if(I && !(I.status & ORGAN_CUT_AWAY) && I.parent_organ == target_zone)
attached_organs |= organ
var/organ_to_remove = input(user, "Which organ do you want to prepare for removal?") as null|anything in attached_organs
@@ -323,7 +259,7 @@
var/list/removable_organs = list()
for(var/organ in target.internal_organs_by_name)
var/obj/item/organ/I = target.internal_organs_by_name[organ]
- if(I.status & ORGAN_CUT_AWAY && I.parent_organ == target_zone)
+ if((I.status & ORGAN_CUT_AWAY) && I.parent_organ == target_zone)
removable_organs |= organ
var/organ_to_remove = input(user, "Which organ do you want to remove?") as null|anything in removable_organs
@@ -352,8 +288,8 @@
fail_step(mob/living/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("\red [user]'s hand slips, damaging the flesh in [target]'s [affected.name] with \the [tool]!", \
- "\red Your hand slips, damaging the flesh in [target]'s [affected.name] with \the [tool]!")
+ user.visible_message("\red [user]'s hand slips, damaging [target]'s [affected.name] with \the [tool]!", \
+ "\red Your hand slips, damaging [target]'s [affected.name] with \the [tool]!")
affected.createwound(BRUISE, 20)
/datum/surgery_step/internal/replace_organ
@@ -374,6 +310,10 @@
if(!istype(O))
return 0
+
+ if((affected.status & ORGAN_ROBOT) && !(O.status & ORGAN_ROBOT))
+ user << "You cannot install a naked organ into a robotic body."
+ return 2
if(!target.species)
user << "\red You have no idea what species this person is. Report this on the bug tracker."
@@ -450,7 +390,7 @@
var/list/removable_organs = list()
for(var/organ in target.internal_organs_by_name)
var/obj/item/organ/I = target.internal_organs_by_name[organ]
- if(I && I.status & ORGAN_CUT_AWAY && I.parent_organ == target_zone)
+ if(I && (I.status & ORGAN_CUT_AWAY) && !(I.status & ORGAN_ROBOT) && I.parent_organ == target_zone)
removable_organs |= organ
var/organ_to_replace = input(user, "Which organ do you want to reattach?") as null|anything in removable_organs
diff --git a/code/modules/surgery/robolimbs.dm b/code/modules/surgery/robolimbs.dm
deleted file mode 100644
index 17d92cf9b4e..00000000000
--- a/code/modules/surgery/robolimbs.dm
+++ /dev/null
@@ -1,60 +0,0 @@
-//Procedures in this file: Robotic limbs attachment
-//////////////////////////////////////////////////////////////////
-// LIMB SURGERY //
-//////////////////////////////////////////////////////////////////
-
-/datum/surgery_step/limb/
- can_infect = 0
- can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- if (!hasorgans(target))
- return 0
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
- if (affected)
- return 0
- var/list/organ_data = target.species.has_limbs["[target_zone]"]
- return !isnull(organ_data) && !(target_zone in list("head","groin","chest"))
-
-/datum/surgery_step/limb/attach
- allowed_tools = list(/obj/item/robot_parts = 100)
-
- min_duration = 80
- max_duration = 100
-
- can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- if(..())
- var/obj/item/robot_parts/p = tool
- if (p.part)
- if (!(target_zone in p.part))
- return 0
- return isnull(target.get_organ(target_zone))
-
- begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- user.visible_message("[user] starts attaching \the [tool] to [target].", \
- "You start attaching \the [tool] to [target].")
-
- end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- var/obj/item/robot_parts/L = tool
- user.visible_message("\blue [user] has attached \the [tool] to [target].", \
- "\blue You have attached \the [tool] to [target].")
-
- if(L.part)
- for(var/part_name in L.part)
- if(!isnull(target.get_organ(part_name))) continue
- var/list/organ_data = target.species.has_limbs["[part_name]"]
- if(!organ_data) continue
- var/new_limb_type = organ_data["path"]
- var/obj/item/organ/external/new_limb = new new_limb_type(target)
- new_limb.robotize(L.model_info)
- if(L.sabotaged)
- new_limb.sabotaged = 1
-
- target.update_body()
- target.updatehealth()
- target.UpdateDamageIcon()
-
- qdel(tool)
-
- fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
- user.visible_message("\red [user]'s hand slips, damaging [target]'s flesh!", \
- "\red Your hand slips, damaging [target]'s flesh!")
- target.apply_damage(10, BRUTE, null, sharp=1)
diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm
new file mode 100644
index 00000000000..f0da9944abf
--- /dev/null
+++ b/code/modules/surgery/robotics.dm
@@ -0,0 +1,430 @@
+//Procedures in this file: Generic surgery steps for robots
+//////////////////////////////////////////////////////////////////
+// COMMON STEPS //
+//////////////////////////////////////////////////////////////////
+
+/datum/surgery_step/robotics/
+ can_infect = 0
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if (isslime(target))
+ return 0
+ if (target_zone == "eyes") //there are specific steps for eye surgery
+ return 0
+ if (!hasorgans(target))
+ return 0
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if (affected == null)
+ return 0
+ if (affected.status & ORGAN_DESTROYED)
+ return 0
+ if (!(affected.status & ORGAN_ROBOT))
+ return 0
+ return 1
+
+/datum/surgery_step/robotics/unscrew_hatch
+ allowed_tools = list(
+ /obj/item/weapon/screwdriver = 100,
+ /obj/item/weapon/coin = 50,
+ /obj/item/weapon/kitchen/utensil/knife = 50
+ )
+
+ min_duration = 90
+ max_duration = 110
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if(..())
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ return affected && affected.open == 0 && target_zone != "mouth"
+
+ 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 to unscrew the maintenance hatch on [target]'s [affected.name] with \the [tool].", \
+ "You start to unscrew the maintenance hatch on [target]'s [affected.name] with \the [tool].")
+ ..()
+
+ end_step(mob/living/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("\blue [user] has opened the maintenance hatch on [target]'s [affected.name] with \the [tool].", \
+ "\blue You have opened the maintenance hatch on [target]'s [affected.name] with \the [tool].",)
+ affected.open = 1
+
+ fail_step(mob/living/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("\red [user]'s [tool.name] slips, failing to unscrew [target]'s [affected.name].", \
+ "\red Your [tool] slips, failing to unscrew [target]'s [affected.name].")
+
+/datum/surgery_step/robotics/open_hatch
+ allowed_tools = list(
+ /obj/item/weapon/retractor = 100,
+ /obj/item/weapon/crowbar = 100,
+ /obj/item/weapon/kitchen/utensil/ = 50
+ )
+
+ min_duration = 30
+ max_duration = 40
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if(..())
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ return affected && affected.open == 1
+
+ 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 to pry open the maintenance hatch on [target]'s [affected.name] with \the [tool].",
+ "You start to pry open the maintenance hatch on [target]'s [affected.name] with \the [tool].")
+ ..()
+
+ end_step(mob/living/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("\blue [user] opens the maintenance hatch on [target]'s [affected.name] with \the [tool].", \
+ "\blue You open the maintenance hatch on [target]'s [affected.name] with \the [tool]." )
+ affected.open = 2
+
+ fail_step(mob/living/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("\red [user]'s [tool.name] slips, failing to open the hatch on [target]'s [affected.name].",
+ "\red Your [tool] slips, failing to open the hatch on [target]'s [affected.name].")
+
+/datum/surgery_step/robotics/close_hatch
+ allowed_tools = list(
+ /obj/item/weapon/retractor = 100,
+ /obj/item/weapon/crowbar = 100,
+ /obj/item/weapon/kitchen/utensil = 50
+ )
+
+ min_duration = 70
+ max_duration = 100
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if(..())
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ return affected && affected.open && target_zone != "mouth"
+
+ 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] begins to close and secure the hatch on [target]'s [affected.name] with \the [tool]." , \
+ "You begin to close and secure the hatch on [target]'s [affected.name] with \the [tool].")
+ ..()
+
+ end_step(mob/living/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("\blue [user] closes and secures the hatch on [target]'s [affected.name] with \the [tool].", \
+ "\blue You close and secure the hatch on [target]'s [affected.name] with \the [tool].")
+ affected.open = 0
+ affected.germ_level = 0
+
+ fail_step(mob/living/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("\red [user]'s [tool.name] slips, failing to close the hatch on [target]'s [affected.name].",
+ "\red Your [tool.name] slips, failing to close the hatch on [target]'s [affected.name].")
+
+/datum/surgery_step/robotics/repair_brute
+ allowed_tools = list(
+ /obj/item/weapon/weldingtool = 100,
+ /obj/item/weapon/gun/energy/plasmacutter = 50
+ )
+
+ min_duration = 50
+ max_duration = 60
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if(..())
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(istype(tool,/obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/welder = tool
+ if(!welder.isOn() || !welder.remove_fuel(1,user))
+ return 0
+ return affected && affected.open == 2 && affected.brute_dam > 0 && target_zone != "mouth"
+
+ 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] begins to patch damage to [target]'s [affected.name]'s support structure with \the [tool]." , \
+ "You begin to patch damage to [target]'s [affected.name]'s support structure with \the [tool].")
+ ..()
+
+ end_step(mob/living/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("\blue [user] finishes patching damage to [target]'s [affected.name] with \the [tool].", \
+ "\blue You finish patching damage to [target]'s [affected.name] with \the [tool].")
+ affected.heal_damage(rand(30,50),0,1,1)
+
+ fail_step(mob/living/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("\red [user]'s [tool.name] slips, damaging the internal structure of [target]'s [affected.name].",
+ "\red Your [tool.name] slips, damaging the internal structure of [target]'s [affected.name].")
+ target.apply_damage(rand(5,10), BURN, affected)
+
+/datum/surgery_step/robotics/repair_burn
+ allowed_tools = list(
+ /obj/item/stack/cable_coil = 100
+ )
+
+ min_duration = 50
+ max_duration = 60
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if(..())
+ var/obj/item/stack/cable_coil/C = tool
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ var/limb_can_operate = (affected && affected.open == 2 && affected.burn_dam > 0 && target_zone != "mouth")
+ if(limb_can_operate)
+ if(istype(C))
+ if(!C.get_amount() >= 3)
+ user << "You need three or more cable pieces to repair this damage."
+ return 2
+ C.use(3)
+ return 1
+ return 0
+
+ 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] begins to splice new cabling into [target]'s [affected.name]." , \
+ "You begin to splice new cabling into [target]'s [affected.name].")
+ ..()
+
+ end_step(mob/living/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("\blue [user] finishes splicing cable into [target]'s [affected.name].", \
+ "\blue You finishes splicing new cable into [target]'s [affected.name].")
+ affected.heal_damage(0,rand(30,50),1,1)
+
+ fail_step(mob/living/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("\red [user] causes a short circuit in [target]'s [affected.name]!",
+ "\red You cause a short circuit in [target]'s [affected.name]!")
+ target.apply_damage(rand(5,10), BURN, affected)
+
+/datum/surgery_step/robotics/fix_organ_robotic //For artificial organs
+ allowed_tools = list(
+ /obj/item/stack/nanopaste = 100, \
+ /obj/item/weapon/bonegel = 30, \
+ /obj/item/weapon/screwdriver = 70, \
+ )
+
+ min_duration = 70
+ max_duration = 90
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ if (!hasorgans(target))
+ return
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(!affected) return
+ var/is_organ_damaged = 0
+ for(var/obj/item/organ/I in affected.internal_organs)
+ if(I.damage > 0 && I.robotic >= 2)
+ is_organ_damaged = 1
+ break
+ return affected.open == 2 && is_organ_damaged
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ if (!hasorgans(target))
+ return
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+
+ for(var/obj/item/organ/I in affected.internal_organs)
+ if(I && I.damage > 0)
+ if(I.robotic >= 2)
+ user.visible_message("[user] starts mending the damage to [target]'s [I.name]'s mechanisms.", \
+ "You start mending the damage to [target]'s [I.name]'s mechanisms." )
+
+ target.custom_pain("The pain in your [affected.name] is living hell!",1)
+ ..()
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ if (!hasorgans(target))
+ return
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+
+ for(var/obj/item/organ/I in affected.internal_organs)
+
+ if(I && I.damage > 0)
+ if(I.robotic >= 2)
+ user.visible_message("\blue [user] repairs [target]'s [I.name] with [tool].", \
+ "\blue You repair [target]'s [I.name] with [tool]." )
+ I.damage = 0
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ if (!hasorgans(target))
+ return
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+
+ user.visible_message("\red [user]'s hand slips, gumming up the mechanisms inside of [target]'s [affected.name] with \the [tool]!", \
+ "\red Your hand slips, gumming up the mechanisms inside of [target]'s [affected.name] with \the [tool]!")
+
+ target.adjustToxLoss(5)
+ affected.createwound(CUT, 5)
+
+ for(var/obj/item/organ/I in affected.internal_organs)
+ if(I)
+ I.take_damage(rand(3,5),0)
+
+/datum/surgery_step/robotics/detatch_organ_robotic
+
+ allowed_tools = list(
+ /obj/item/device/multitool = 100
+ )
+
+ min_duration = 90
+ max_duration = 110
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(!(affected && (affected.status & ORGAN_ROBOT)))
+ return 0
+ if(affected.open != 2)
+ return 0
+
+ target.op_stage.current_organ = null
+
+ var/list/attached_organs = list()
+ for(var/organ in target.internal_organs_by_name)
+ var/obj/item/organ/I = target.internal_organs_by_name[organ]
+ if(I && !(I.status & ORGAN_CUT_AWAY) && I.parent_organ == target_zone)
+ attached_organs |= organ
+
+ var/organ_to_remove = input(user, "Which organ do you want to prepare for removal?") as null|anything in attached_organs
+ if(!organ_to_remove)
+ return 0
+
+ target.op_stage.current_organ = organ_to_remove
+
+ return ..() && organ_to_remove
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("[user] starts to decouple [target]'s [target.op_stage.current_organ] with \the [tool].", \
+ "You start to decouple [target]'s [target.op_stage.current_organ] with \the [tool]." )
+ ..()
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("\blue [user] has decoupled [target]'s [target.op_stage.current_organ] with \the [tool]." , \
+ "\blue You have decoupled [target]'s [target.op_stage.current_organ] with \the [tool].")
+
+ var/obj/item/organ/I = target.internal_organs_by_name[target.op_stage.current_organ]
+ if(I && istype(I))
+ I.status |= ORGAN_CUT_AWAY
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("\red [user]'s hand slips, disconnecting \the [tool].", \
+ "\red Your hand slips, disconnecting \the [tool].")
+
+/datum/surgery_step/robotics/attach_organ_robotic
+ allowed_tools = list(
+ /obj/item/weapon/screwdriver = 100,
+ )
+
+ min_duration = 100
+ max_duration = 120
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(!(affected && (affected.status & ORGAN_ROBOT)))
+ return 0
+ if(affected.open != 2)
+ return 0
+
+ target.op_stage.current_organ = null
+
+ var/list/removable_organs = list()
+ for(var/organ in target.internal_organs_by_name)
+ var/obj/item/organ/I = target.internal_organs_by_name[organ]
+ if(I && (I.status & ORGAN_CUT_AWAY) && (I.status & ORGAN_ROBOT) && I.parent_organ == target_zone)
+ removable_organs |= organ
+
+ var/organ_to_replace = input(user, "Which organ do you want to reattach?") as null|anything in removable_organs
+ if(!organ_to_replace)
+ return 0
+
+ target.op_stage.current_organ = organ_to_replace
+ return ..()
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("[user] begins reattaching [target]'s [target.op_stage.current_organ] with \the [tool].", \
+ "You start reattaching [target]'s [target.op_stage.current_organ] with \the [tool].")
+ ..()
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("\blue [user] has reattached [target]'s [target.op_stage.current_organ] with \the [tool]." , \
+ "\blue You have reattached [target]'s [target.op_stage.current_organ] with \the [tool].")
+
+ var/obj/item/organ/I = target.internal_organs_by_name[target.op_stage.current_organ]
+ if(I && istype(I))
+ I.status &= ~ORGAN_CUT_AWAY
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("\red [user]'s hand slips, disconnecting \the [tool].", \
+ "\red Your hand slips, disconnecting \the [tool].")
+
+/datum/surgery_step/robotics/install_mmi
+ allowed_tools = list(
+ /obj/item/device/mmi = 100
+ )
+
+ min_duration = 60
+ max_duration = 80
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ if(target_zone != "head")
+ return
+
+ var/obj/item/device/mmi/M = tool
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(!(affected && affected.open == 2))
+ return 0
+
+ if(!istype(M))
+ return 0
+
+ if(!M.brainmob || !M.brainmob.client || !M.brainmob.ckey || M.brainmob.stat >= DEAD)
+ user << "That brain is not usable."
+ return 2
+
+ if(!(affected.status & ORGAN_ROBOT))
+ user << "You cannot install a computer brain into a meat skull."
+ return 2
+
+ if(!target.species)
+ user << "You have no idea what species this person is. Report this on the bug tracker."
+ return 2
+
+ if(!target.species.has_organ["brain"])
+ user << "You're pretty sure [target.species.name_plural] don't normally have a brain."
+ return 2
+
+ if(!isnull(target.internal_organs["brain"]))
+ user << "Your subject already has a brain."
+ return 2
+
+ return 1
+
+ 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 installing \the [tool] into [target]'s [affected.name].", \
+ "You start installing \the [tool] into [target]'s [affected.name].")
+ ..()
+
+ end_step(mob/living/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("\blue [user] has installed \the [tool] into [target]'s [affected.name].", \
+ "\blue You have installed \the [tool] into [target]'s [affected.name].")
+
+ var/obj/item/device/mmi/M = tool
+ var/obj/item/organ/mmi_holder/holder = new(target, 1)
+ target.internal_organs_by_name["brain"] = holder
+ user.unEquip(tool)
+ tool.loc = holder
+ holder.stored_mmi = tool
+ holder.update_from_mmi()
+
+ if(M.brainmob && M.brainmob.mind)
+ M.brainmob.mind.transfer_to(target)
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("\red [user]'s hand slips.", \
+ "\red Your hand slips.")
\ No newline at end of file
diff --git a/code/modules/surgery/slime.dm b/code/modules/surgery/slime.dm
index 048c6d3e3c1..02cf0219366 100644
--- a/code/modules/surgery/slime.dm
+++ b/code/modules/surgery/slime.dm
@@ -87,7 +87,6 @@
if(target.cores <= 0)
target.icon_state = "[target.colour] baby slime dead-nocore"
-
fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
user.visible_message("\red [user]'s hand slips, causing \him to miss the core!", \
"\red Your hand slips, causing you to miss the core!")
\ No newline at end of file
diff --git a/code/modules/virus2/disease2.dm b/code/modules/virus2/disease2.dm
index a72b66e88e1..f685bbe2b12 100644
--- a/code/modules/virus2/disease2.dm
+++ b/code/modules/virus2/disease2.dm
@@ -40,7 +40,7 @@
var/list/res = list()
for (var/specie in all_species)
var/datum/species/S = all_species[specie]
- if(!(S.flags & IS_SYNTHETIC))
+ if(!(S.virus_immune))
meat += S.name
if(meat.len)
var/num = rand(1,meat.len)
@@ -58,10 +58,11 @@
if(mob.stat == 2)
return
- var/mob/living/carbon/human/MS = mob
- if(istype(MS))
- if(MS.species.flags & IS_SYNTHETIC)
- return
+ // Some species are flat out immune to organic viruses.
+ var/mob/living/carbon/human/H = mob
+ if(istype(H) && H.species.virus_immune)
+ cure(mob)
+ return
if(stage <= 1 && clicks == 0) // with a certain chance, the mob may become immune to the disease before it starts properly
if(prob(5))
diff --git a/code/modules/virus2/helpers.dm b/code/modules/virus2/helpers.dm
index cfc6bd1bdb6..91a287044e9 100644
--- a/code/modules/virus2/helpers.dm
+++ b/code/modules/virus2/helpers.dm
@@ -3,6 +3,11 @@ proc/get_infection_chance(var/mob/living/carbon/M, var/vector = "Airborne")
var/score = 0
if (!istype(M))
return 0
+
+ var/mob/living/carbon/human/H = M
+ if(istype(H) && H.species.virus_immune)
+ return 0
+
if(istype(M, /mob/living/carbon/human))
if (vector == "Airborne")
if(M.internal) //not breathing infected air helps greatly
diff --git a/icons/mob/human_races/cyberlimbs/ipc.dmi b/icons/mob/human_races/cyberlimbs/ipc.dmi
new file mode 100644
index 00000000000..b0ae6739177
Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/ipc.dmi differ
diff --git a/icons/mob/human_races/r_machine.dmi b/icons/mob/human_races/r_machine.dmi
index 31a8ebd68c4..ec48364386b 100644
Binary files a/icons/mob/human_races/r_machine.dmi and b/icons/mob/human_races/r_machine.dmi differ
diff --git a/paradise.dme b/paradise.dme
index 57f12bcfa7c..a1748771fa1 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -1500,7 +1500,6 @@
#include "code\modules\ninja\suit\suit_initialisation.dm"
#include "code\modules\organs\blood.dm"
#include "code\modules\organs\organ.dm"
-#include "code\modules\organs\organ_alien.dm"
#include "code\modules\organs\organ_external.dm"
#include "code\modules\organs\organ_icon.dm"
#include "code\modules\organs\organ_internal.dm"
@@ -1509,6 +1508,14 @@
#include "code\modules\organs\robolimbs.dm"
#include "code\modules\organs\skeleton.dm"
#include "code\modules\organs\wound.dm"
+#include "code\modules\organs\subtypes\diona.dm"
+#include "code\modules\organs\subtypes\machine.dm"
+#include "code\modules\organs\subtypes\misc.dm"
+#include "code\modules\organs\subtypes\nucleation.dm"
+#include "code\modules\organs\subtypes\standard.dm"
+#include "code\modules\organs\subtypes\unbreakable.dm"
+#include "code\modules\organs\subtypes\wryn.dm"
+#include "code\modules\organs\subtypes\xenos.dm"
#include "code\modules\paperwork\carbonpaper.dm"
#include "code\modules\paperwork\clipboard.dm"
#include "code\modules\paperwork\fax.dm"
@@ -1782,11 +1789,11 @@
#include "code\modules\surgery\eye.dm"
#include "code\modules\surgery\face.dm"
#include "code\modules\surgery\generic.dm"
-#include "code\modules\surgery\headreattach.dm"
#include "code\modules\surgery\implant.dm"
+#include "code\modules\surgery\limb_reattach.dm"
#include "code\modules\surgery\organs_internal.dm"
#include "code\modules\surgery\other.dm"
-#include "code\modules\surgery\robolimbs.dm"
+#include "code\modules\surgery\robotics.dm"
#include "code\modules\surgery\slime.dm"
#include "code\modules\surgery\surgery.dm"
#include "code\modules\surgery\tools.dm"