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"