From da67faca4b1b0042c35fa6ea356f8f51c90935fa Mon Sep 17 00:00:00 2001 From: Mechoid Date: Mon, 2 Mar 2020 16:20:55 -0800 Subject: [PATCH] Prosthetic Expansion Work --- code/game/mecha/mech_prosthetics.dm | 21 ++++ .../mob/living/carbon/human/human_powers.dm | 23 ++++- .../carbon/human/species/station/station.dm | 11 +++ code/modules/organs/organ_icon.dm | 4 +- code/modules/organs/robolimbs.dm | 92 ++++++++++++++++- code/modules/organs/subtypes/diona.dm | 31 ++++++ .../research/designs/circuits/disks.dm | 46 +++++++++ code/modules/research/prosfab_designs.dm | 44 ++++++++- code/modules/surgery/robotics.dm | 93 ++++++++++++++++++ .../nanotrasen/nanotrasen_tajaran.dmi | Bin 0 -> 3336 bytes .../unbranded/unbranded_tajaran.dmi | Bin 0 -> 1520 bytes .../cyberlimbs/veymed/dionaea/skrellian.dmi | Bin 0 -> 6499 bytes .../cyberlimbs/veymed/veymed_skrell.dmi | Bin 0 -> 1258 bytes nano/templates/mechfab.tmpl | 8 ++ polaris.dme | 1 + 15 files changed, 364 insertions(+), 10 deletions(-) create mode 100644 code/modules/research/designs/circuits/disks.dm create mode 100644 icons/mob/human_races/cyberlimbs/nanotrasen/nanotrasen_tajaran.dmi create mode 100644 icons/mob/human_races/cyberlimbs/unbranded/unbranded_tajaran.dmi create mode 100644 icons/mob/human_races/cyberlimbs/veymed/dionaea/skrellian.dmi create mode 100644 icons/mob/human_races/cyberlimbs/veymed/veymed_skrell.dmi diff --git a/code/game/mecha/mech_prosthetics.dm b/code/game/mecha/mech_prosthetics.dm index b633e44558..e409eaa4c3 100644 --- a/code/game/mecha/mech_prosthetics.dm +++ b/code/game/mecha/mech_prosthetics.dm @@ -25,6 +25,8 @@ var/list/categories = list() var/category = null var/manufacturer = null + var/species_types = list("Human") + var/species = "Human" var/sync_message = "" /obj/machinery/pros_fabricator/New() @@ -100,11 +102,14 @@ data["buildable"] = get_build_options() data["category"] = category data["categories"] = categories + data["species_types"] = species_types + data["species"] = species if(all_robolimbs) var/list/T = list() for(var/A in all_robolimbs) var/datum/robolimb/R = all_robolimbs[A] if(R.unavailable_to_build) continue + if(species in R.species_cannot_use) continue T += list(list("id" = A, "company" = R.company)) data["manufacturers"] = T data["manufacturer"] = manufacturer @@ -135,6 +140,10 @@ if(href_list["category"] in categories) category = href_list["category"] + if(href_list["species"]) + if(href_list["species"] in species_types) + species = href_list["species"] + if(href_list["manufacturer"]) if(href_list["manufacturer"] in all_robolimbs) manufacturer = href_list["manufacturer"] @@ -173,6 +182,18 @@ qdel(I) return + if(istype(I,/obj/item/weapon/disk/species)) + var/obj/item/weapon/disk/species/D = I + if(!D.species || !(D.species in GLOB.all_species)) + to_chat(user, "This disk seems to be corrupted!") + else + to_chat(user, "Uploading modification files for [D.species]...") + if(do_after(user,50,src)) + species_types |= D.species + to_chat(user, "Uploaded [D.species] files!") + qdel(I) + return + if(istype(I,/obj/item/stack/material)) var/obj/item/stack/material/S = I if(!(S.material.name in materials)) diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index e24a898a30..3d0dbfc3bd 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -178,9 +178,28 @@ for(var/obj/item/W in src) drop_from_inventory(W) - visible_message("\The [src] quivers slightly, then splits apart with a wet slithering noise.") + var/obj/item/organ/external/Chest = organs_by_name[BP_TORSO] - qdel(src) + if(Chest.robotic >= 2) + visible_message("\The [src] shudders slightly, then ejects a cluster of nymphs with a wet slithering noise.") + species = GLOB.all_species[SPECIES_HUMAN] // This is hard-set to default the body to a normal FBP, without changing anything. + + // Bust it + src.death() + + for(var/obj/item/organ/internal/diona/Org in internal_organs) // Remove Nymph organs. + qdel(Org) + + // Purge the diona verbs. + verbs -= /mob/living/carbon/human/proc/diona_split_nymph + verbs -= /mob/living/carbon/human/proc/regenerate + + for(var/obj/item/organ/external/E in organs) // Just fall apart. + E.droplimb(TRUE) + + else + visible_message("\The [src] quivers slightly, then splits apart with a wet slithering noise.") + qdel(src) /mob/living/carbon/human/proc/self_diagnostics() set name = "Self-Diagnostics" diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index 7c02077f4d..3383e7bdfb 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -482,6 +482,7 @@ has_organ = list( O_NUTRIENT = /obj/item/organ/internal/diona/nutrients, O_STRATA = /obj/item/organ/internal/diona/strata, + O_BRAIN = /obj/item/organ/internal/brain/cephalon, O_RESPONSE = /obj/item/organ/internal/diona/node, O_GBLADDER = /obj/item/organ/internal/diona/bladder, O_POLYP = /obj/item/organ/internal/diona/polyp, @@ -555,6 +556,16 @@ if(H.isSynthetic()) H.visible_message("\The [H] collapses into parts, revealing a solitary diona nymph at the core.") + + H.species = GLOB.all_species[SPECIES_HUMAN] // This is hard-set to default the body to a normal FBP, without changing anything. + + for(var/obj/item/organ/internal/diona/Org in H.internal_organs) // Remove Nymph organs. + qdel(Org) + + // Purge the diona verbs. + H.verbs -= /mob/living/carbon/human/proc/diona_split_nymph + H.verbs -= /mob/living/carbon/human/proc/regenerate + return for(var/mob/living/carbon/alien/diona/D in H.contents) diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 5c0d98b26d..3c50c9f53f 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -18,7 +18,7 @@ var/global/list/limb_icon_cache = list() h_col = null if(robotic >= ORGAN_ROBOT) var/datum/robolimb/franchise = all_robolimbs[model] - if(!(franchise && franchise.skin_tone)) + if(!(franchise && franchise.skin_tone) && !(franchise && franchise.skin_color)) if(human.synth_color) s_col = list(human.r_synth, human.g_synth, human.b_synth) return @@ -36,7 +36,7 @@ var/global/list/limb_icon_cache = list() h_col = null if(robotic >= ORGAN_ROBOT) var/datum/robolimb/franchise = all_robolimbs[model] - if(!(franchise && franchise.skin_tone)) + if(!(franchise && franchise.skin_tone) && !(franchise && franchise.skin_color)) return if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE)) && (species.appearance_flags & HAS_SKIN_TONE)) s_tone = dna.GetUIValue(DNA_UI_SKIN_TONE) diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm index a7b27981fc..5d7895d265 100644 --- a/code/modules/organs/robolimbs.dm +++ b/code/modules/organs/robolimbs.dm @@ -33,6 +33,14 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ if(!R.unavailable_at_chargen) chargen_robolimbs[R.company] = R //List only main brands and solo parts. + for(var/company in all_robolimbs) + var/datum/robolimb/R = all_robolimbs[company] + if(R.species_alternates) + for(var/species in R.species_alternates) + var/species_company = R.species_alternates[species] + if(species_company in all_robolimbs) + R.species_alternates[species] = all_robolimbs[species_company] + /datum/robolimb var/company = "Unbranded" // Shown when selecting the limb. var/desc = "A generic unbranded robotic prosthesis." // Seen when examining a limb. @@ -40,9 +48,11 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ var/unavailable_at_chargen // If set, not available at chargen. var/unavailable_to_build // If set, can't be constructed. var/lifelike // If set, appears organic. - var/skin_tone // If set, applies skin tone rather than part color + var/skin_tone // If set, applies skin tone rather than part color Overrides color. + var/skin_color // If set, applies skin color rather than part color. var/blood_color = "#030303" var/list/species_cannot_use = list(SPECIES_TESHARI, SPECIES_PROMETHEAN, SPECIES_DIONA) + var/list/species_alternates = list(SPECIES_TAJ = "Unbranded - Tajaran") //"Species Name" = "Robolimb Company" , List, when initialized, will become "Species Name" = RobolimbDatum, used for alternate species sprites. var/list/monitor_styles //If empty, the model of limbs offers a head compatible with monitors. var/parts = BP_ALL //Defines what parts said brand can replace on a body. var/health_hud_intensity = 1 // Intensity modifier for the health GUI indicator. @@ -72,10 +82,28 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ icon = 'icons/mob/human_races/cyberlimbs/unbranded/unbranded_alt2.dmi' unavailable_to_build = 1 +/datum/robolimb/unbranded_tajaran + company = "Unbranded - Tajaran" + species_cannot_use = list(SPECIES_TESHARI, SPECIES_PROMETHEAN, SPECIES_DIONA, SPECIES_HUMAN, SPECIES_VOX, SPECIES_HUMAN_VATBORN, SPECIES_UNATHI, SPECIES_SKRELL, SPECIES_ZADDAT) + suggested_species = SPECIES_TAJ + desc = "A simple robotic limb with feline design. Seems rather stiff." + icon = 'icons/mob/human_races/cyberlimbs/unbranded/unbranded_tajaran.dmi' + unavailable_to_build = 1 + /datum/robolimb/nanotrasen company = "NanoTrasen" desc = "A simple but efficient robotic limb, created by NanoTrasen." icon = 'icons/mob/human_races/cyberlimbs/nanotrasen/nanotrasen_main.dmi' + species_alternates = list(SPECIES_TAJ = "NanoTrasen - Tajaran") + +/datum/robolimb/nanotrasen_tajaran + company = "NanoTrasen - Tajaran" + species_cannot_use = list(SPECIES_TESHARI, SPECIES_PROMETHEAN, SPECIES_DIONA, SPECIES_HUMAN, SPECIES_VOX, SPECIES_HUMAN_VATBORN, SPECIES_UNATHI, SPECIES_SKRELL, SPECIES_ZADDAT) + species_alternates = list(SPECIES_HUMAN = "NanoTrasen") + suggested_species = SPECIES_TAJ + desc = "A simple but efficient robotic limb, created by NanoTrasen." + icon = 'icons/mob/human_races/cyberlimbs/nanotrasen/nanotrasen_tajaran.dmi' + unavailable_to_build = 1 /datum/robolimb/bishop company = "Bishop" @@ -104,6 +132,19 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ parts = list(BP_HEAD) monitor_styles = standard_monitor_styles +/datum/robolimb/gestaltframe + company = "Skrellian Exoskeleton" + desc = "This limb looks to be more like a strange.. puppet, than a prosthetic." + icon = 'icons/mob/human_races/cyberlimbs/veymed/dionaea/skrellian.dmi' + blood_color = "#63b521" + speech_bubble_appearance = "machine" + unavailable_to_build = 1 + species_cannot_use = list(SPECIES_TESHARI, SPECIES_PROMETHEAN, SPECIES_TAJ, SPECIES_HUMAN, SPECIES_VOX, SPECIES_HUMAN_VATBORN, SPECIES_UNATHI, SPECIES_SKRELL, SPECIES_ZADDAT) + suggested_species = SPECIES_DIONA + // Dionaea are naturally very tanky, so the robotic limbs are actually far weaker than their normal bodies. + robo_brute_mod = 1.3 + robo_burn_mod = 1.3 + /datum/robolimb/cybersolutions company = "Cyber Solutions" desc = "This limb is grey and rough, with little in the way of aesthetic." @@ -224,11 +265,25 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ unavailable_to_build = 1 lifelike = 1 skin_tone = 1 + species_alternates = list(SPECIES_SKRELL = "Vey-Med - Skrell") blood_color = "#CCCCCC" speech_bubble_appearance = "normal" robo_brute_mod = 1.1 robo_burn_mod = 1.1 +/datum/robolimb/veymed_skrell + company = "Vey-Med - Skrell" + desc = "This high quality limb is nearly indistinguishable from an organic one." + icon = 'icons/mob/human_races/cyberlimbs/veymed/veymed_skrell.dmi' + unavailable_to_build = 1 + lifelike = 1 + skin_color = TRUE + species_cannot_use = list(SPECIES_TESHARI, SPECIES_PROMETHEAN, SPECIES_TAJ, SPECIES_HUMAN, SPECIES_VOX, SPECIES_HUMAN_VATBORN, SPECIES_UNATHI, SPECIES_DIONA, SPECIES_ZADDAT) + blood_color = "#4451cf" + speech_bubble_appearance = "normal" + robo_brute_mod = 1.05 + robo_burn_mod = 1.05 + /datum/robolimb/wardtakahashi company = "Ward-Takahashi" desc = "This limb features sleek black and white polymers." @@ -343,6 +398,10 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ company = "Vey-Med" catalogue_data = list(/datum/category_item/catalogue/information/organization/vey_med) +// Bus disk for Diona mech parts. +/obj/item/weapon/disk/limb/veymed/diona + company = "Skrellian Exoskeleton" + /obj/item/weapon/disk/limb/wardtakahashi company = "Ward-Takahashi" catalogue_data = list(/datum/category_item/catalogue/information/organization/ward_takahashi) @@ -358,3 +417,34 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ /obj/item/weapon/disk/limb/nanotrasen company = "NanoTrasen" catalogue_data = list(/datum/category_item/catalogue/information/organization/nanotrasen) + +/obj/item/weapon/disk/species + name = "Species Bioprints" + desc = "A disk containing the blueprints for species-specific prosthetics." + icon = 'icons/obj/cloning.dmi' + icon_state = "datadisk2" + var/species = SPECIES_HUMAN + +/obj/item/weapon/disk/species/Initialize() + ..() + if(species) + name = "[species] [initial(name)]" + +/obj/item/weapon/disk/species/skrell + species = SPECIES_SKRELL + +/obj/item/weapon/disk/species/unathi + species = SPECIES_UNATHI + +/obj/item/weapon/disk/species/tajaran + species = SPECIES_TAJ + +/obj/item/weapon/disk/species/teshari + species = SPECIES_TESHARI + +// In case of bus, presently. +/obj/item/weapon/disk/species/diona + species = SPECIES_DIONA + +/obj/item/weapon/disk/species/zaddat + species = SPECIES_ZADDAT diff --git a/code/modules/organs/subtypes/diona.dm b/code/modules/organs/subtypes/diona.dm index c0e4e60c98..7d43baf757 100644 --- a/code/modules/organs/subtypes/diona.dm +++ b/code/modules/organs/subtypes/diona.dm @@ -205,6 +205,37 @@ /obj/item/organ/internal/diona/node/removed() return +// A 'brain' for the tree, still becomes a mindless nymph when removed like any other. Satisfies the FBP code. +/obj/item/organ/internal/brain/cephalon + name = "cephalon mass" + parent_organ = BP_TORSO + vital = TRUE + +/obj/item/organ/internal/brain/cephalon/Initialize() + ..() + spawn(30 SECONDS) // FBP Dionaea need some way to be disassembled through surgery, if absolutely necessary. + if(!owner.isSynthetic()) + vital = FALSE + +/obj/item/organ/internal/brain/cephalon/robotize() + return + +/obj/item/organ/internal/brain/cephalon/mechassist() + return + +/obj/item/organ/internal/brain/cephalon/digitize() + return + +/obj/item/organ/internal/brain/cephalon/removed(var/mob/living/user, var/skip_nymph) + if(robotic >= ORGAN_ROBOT) + return ..() + var/mob/living/carbon/human/H = owner + ..() + if(!istype(H) || !H.organs || !H.organs.len) + H.death() + if(prob(50) && !skip_nymph && spawn_diona_nymph(get_turf(src))) + qdel(src) + /obj/item/organ/external/head/no_eyes/diona max_damage = 50 min_broken_damage = 25 diff --git a/code/modules/research/designs/circuits/disks.dm b/code/modules/research/designs/circuits/disks.dm new file mode 100644 index 0000000000..2a3c2df83f --- /dev/null +++ b/code/modules/research/designs/circuits/disks.dm @@ -0,0 +1,46 @@ + +/datum/design/circuit/disk + build_type = IMPRINTER + req_tech = list(TECH_DATA = 3) + materials = list(MAT_PLASTIC = 2000, MAT_GLASS = 1000) + chemicals = list("pacid" = 10) + time = 5 + +/datum/design/circuit/disk/AssembleDesignName() + ..() + if(build_path) + var/obj/item/weapon/disk/D = build_path + if(istype(D, /obj/item/weapon/disk/species)) + name = "Species Prosthetic design ([item_name])" + else if(istype(D, /obj/item/weapon/disk/limb)) + name = "Transtellar Prosthetic design ([item_name])" + else + name = "Disk design ([item_name])" + +/datum/design/circuit/disk/skrellprint + name = SPECIES_SKRELL + id = "prosthetic_skrell" + req_tech = list(TECH_DATA = 3, TECH_BIO = 3) + build_path = /obj/item/weapon/disk/species/skrell + sort_string = "DBAAA" + +/datum/design/circuit/disk/tajprint + name = SPECIES_TAJ + id = "prosthetic_tajaran" + req_tech = list(TECH_DATA = 3, TECH_BIO = 3) + build_path = /obj/item/weapon/disk/species/tajaran + sort_string = "DBAAB" + +/datum/design/circuit/disk/unathiprint + name = SPECIES_UNATHI + id = "prosthetic_unathi" + req_tech = list(TECH_DATA = 3, TECH_BIO = 4) + build_path = /obj/item/weapon/disk/species/unathi + sort_string = "DBAAC" + +/datum/design/circuit/disk/teshariprint + name = SPECIES_TESHARI + id = "prosthetic_teshari" + req_tech = list(TECH_DATA = 3, TECH_BIO = 4) + build_path = /obj/item/weapon/disk/species/teshari + sort_string = "DBAAD" diff --git a/code/modules/research/prosfab_designs.dm b/code/modules/research/prosfab_designs.dm index 5af32bd6e6..d038736b96 100644 --- a/code/modules/research/prosfab_designs.dm +++ b/code/modules/research/prosfab_designs.dm @@ -13,7 +13,17 @@ var/obj/item/organ/O = new build_path(newloc) if(prosfab.manufacturer) var/datum/robolimb/manf = all_robolimbs[prosfab.manufacturer] - O.species = GLOB.all_species["[manf.suggested_species]"] + + if(!(O.organ_tag in manf.parts)) // Make sure we're using an actually present icon. + manf = all_robolimbs["Unbranded"] + + if(prosfab.species in manf.species_alternates) // If the prosthetics fab is set to say, Unbranded, and species set to 'Tajaran', it will make the Taj variant of Unbranded, if it exists. + manf = manf.species_alternates[prosfab.species] + + if(!prosfab.species || (prosfab.species in manf.species_cannot_use)) // Fabricator ensures the manufacturer can make parts for the species we're set to. + O.species = GLOB.all_species["[manf.suggested_species]"] + else + O.species = GLOB.all_species[prosfab.species] else O.species = GLOB.all_species["Human"] O.robotize(prosfab.manufacturer) @@ -30,9 +40,18 @@ if(istype(fabricator, /obj/machinery/pros_fabricator)) var/obj/machinery/pros_fabricator/prosfab = fabricator var/newspecies = "Human" - if(prosfab.manufacturer) - var/datum/robolimb/manf = all_robolimbs[prosfab.manufacturer] - newspecies = manf.suggested_species + + var/datum/robolimb/manf = all_robolimbs[prosfab.manufacturer] + + if(manf) + if(prosfab.species in manf.species_alternates) // If the prosthetics fab is set to say, Unbranded, and species set to 'Tajaran', it will make the Taj variant of Unbranded, if it exists. + manf = manf.species_alternates[prosfab.species] + + if(!prosfab.species || (prosfab.species in manf.species_cannot_use)) + newspecies = manf.suggested_species + else + newspecies = prosfab.species + var/mob/living/carbon/human/H = new(newloc,newspecies) H.stat = DEAD H.gender = gender @@ -44,11 +63,26 @@ for(var/obj/item/organ/external/O in H.organs) O.species = GLOB.all_species[newspecies] - O.robotize(prosfab.manufacturer) + + if(!(O.organ_tag in manf.parts)) // Make sure we're using an actually present icon. + manf = all_robolimbs["Unbranded"] + + O.robotize(manf.company) O.dna = new/datum/dna() O.dna.ResetUI() O.dna.ResetSE() + // Skincolor weirdness. + O.s_col[1] = 0 + O.s_col[2] = 0 + O.s_col[3] = 0 + + // Resetting the UI does strange things for the skin of a non-human robot, which should be controlled by a whole different thing. + H.r_skin = 0 + H.g_skin = 0 + H.b_skin = 0 + H.dna.ResetUIFrom(H) + H.real_name = "Synthmorph #[rand(100,999)]" H.name = H.real_name H.dir = 2 diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index 22f250dff9..6d15527eec 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -481,3 +481,96 @@ /datum/surgery_step/robotics/install_mmi/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) user.visible_message("[user]'s hand slips.", \ "Your hand slips.") + +/* + * Install a Diona Nymph into a Nymph Mech + */ + +/datum/surgery_step/robotics/install_nymph + allowed_tools = list( + /obj/item/weapon/holder/diona = 100 + ) + + min_duration = 60 + max_duration = 80 + +/datum/surgery_step/robotics/install_nymph/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if(target_zone != BP_TORSO) + return + + var/obj/item/weapon/holder/diona/N = tool + var/obj/item/organ/external/affected = target.get_organ(target_zone) + + if(!(affected && affected.open == 3)) + return 0 + + if(!istype(N)) + return 0 + + if(!N.held_mob.client || N.held_mob.stat >= DEAD) + to_chat(user, "That nymph is not viable.") + return SURGERY_FAILURE + + if(!(affected.robotic >= ORGAN_ROBOT)) + to_chat(user, "You cannot install a nymph into a meat puppet.") + return SURGERY_FAILURE + + if(!(affected.model != "Skrellian Exoskeleton")) + to_chat(user, "You're fairly certain a nymph can't pilot a normal robot.") + return SURGERY_FAILURE + + if(!target.should_have_organ("brain")) + to_chat(user, "You're pretty sure [target.species.name_plural] don't normally have a brain.") + return SURGERY_FAILURE + + if(!isnull(target.internal_organs["brain"])) + to_chat(user, "Your subject already has a cephalon.") + return SURGERY_FAILURE + + return 1 + +/datum/surgery_step/robotics/install_nymph/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 setting \the [tool] into [target]'s [affected.name].", \ + "You start setting \the [tool] into [target]'s [affected.name].") + ..() + +/datum/surgery_step/robotics/install_nymph/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("[user] has installed \the [tool] into [target]'s [affected.name].", \ + "You have installed \the [tool] into [target]'s [affected.name].") + + var/obj/item/weapon/holder/diona/N = tool + var/obj/item/organ/internal/brain/cephalon/cephalon = new(target, 1) + target.internal_organs_by_name["brain"] = cephalon + var/mob/living/carbon/alien/diona/D = N.held_mob + user.drop_from_inventory(tool) + + if(D && D.mind) + D.mind.transfer_to(target) + target.languages |= D.languages + + qdel(D) + + target.species = GLOB.all_species[SPECIES_DIONA] + + target.verbs |= /mob/living/carbon/human/proc/diona_split_nymph + target.verbs |= /mob/living/carbon/human/proc/regenerate + + spawn(0) //Name yourself on your own damn time + var/new_name = "" + while(!new_name) + if(!target) return + var/try_name = input(target,"Pick a name for your new form!", "New Name", target.name) + var/clean_name = sanitizeName(try_name, allow_numbers = TRUE) + if(clean_name) + var/okay = alert(target,"New name will be '[clean_name]', ok?", "Confirmation","Cancel","Ok") + if(okay == "Ok") + new_name = clean_name + + target.name = new_name + target.real_name = target.name + +/datum/surgery_step/robotics/install_nymph/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("[user]'s hand slips.", \ + "Your hand slips.") diff --git a/icons/mob/human_races/cyberlimbs/nanotrasen/nanotrasen_tajaran.dmi b/icons/mob/human_races/cyberlimbs/nanotrasen/nanotrasen_tajaran.dmi new file mode 100644 index 0000000000000000000000000000000000000000..5abac25088e2fae2ad11271d2bebf9a0c01ca861 GIT binary patch literal 3336 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 F{{$R)6=eVb literal 0 HcmV?d00001 diff --git a/icons/mob/human_races/cyberlimbs/unbranded/unbranded_tajaran.dmi b/icons/mob/human_races/cyberlimbs/unbranded/unbranded_tajaran.dmi new file mode 100644 index 0000000000000000000000000000000000000000..0ac5a1e16fc5ee9b70a10523f500399f4a3277f9 GIT binary patch literal 1520 zcmZ8fdo&XY7@x+gTcJpwp`^8=G_wn>SMWfL`AW&{@E`z~9B9TNQ(Zj=IZ6m+DgSj*W zgDQb7$@)1w`GPk#ugF}}{QEa?)mIr8)KS94d@Ou4wiH9t#KHF_In^|7LSUgmm;H_9 zA$oI2W$m1#I3L|W9pgCqi(g9K)CGi8n>&GC?&pV;gwv5KLY4a(JR{bxkr(O6zOW+b z0GAj4ly4N)6X#F0#y`J3(l6zlXM2xI8#~@_6X}Kuz!?BQu>=Zn@lCn6RD<>(wpYm` zA+2C`9(B5zZ#QMs_2;O~XBIFo_q4#bN!am|jeNfy%_^jqweIe=06e)UuyZ|(#k&xc zRIzBw!T~iC%Y2EekyEqv;P*od^%gqLBs2YM^t}=6A}2#9f{{>q*WgUi9lil8CDV#x zgImM(T#e!Rx>jM;-0NnZz*QY;J$3@NTBAy06uR$iCSl697poZD)!FG;jfOFRFdFT% z!C}AHv6Hs#jC?+=Fp^oVF*O_ns=?Z2nLfU*t+GMhCuYUpc{2i7@W5y5XZ>+Yo0QQB{#9|a?qbCZyW3X*gIpSb$XCb!_ z^SA@Cwf69?KZ$AI27HHkhna2mp;iWdg0fQn;au8do@GbP-DY|$o6*bM@Y>WGuGwvX zEc$%aQwRC-IWkV|%f1#VIOM9-6XDCW9nu_&D| z-+R1OZt=vi_b!V%g>fR|Xy#r@&fENCeyv{b?O9R{3zcp0N5fykOTOobz}xflTPe0RMKOgh z_OGjanu{~+e!HkiT3KnLrk0lGU+C`oP;s%$QbY}6NsLV=KL~;VQx!7z?yL%A++({}Gid&NND*jBT1&jGjvW~SW2bN%Z z`tN;4u=KIybOPGkOCgctl#o>u&nv0w87+B< zfD)RGs>QU)x_|->w|jWI4NZN*NY`B%0gKA(K(O=$Z!mCLu`29?9q>%0+^AsP?amt5 zh2Hi+hrz{;2gZXord!q8g}s!EXR+jNUC-8o?LiVmR0DNt&N0_<_sTTGMqxnOeB@H& zD!GZQ;~LKwqC|z)b22G2)vp(NCvsB3L(d}f)icC(DH)bhim-QRDpva2%A-qSZFA=t zHvIQ4l2|&nJ?K(@I)JILs;*|hAq2y34^{*%Ze|L558le3>+dvO`OG-Es9xw&z9*`O z0mhGQ-(tK;Rmx-b`N=opa++yeRJL(Kz_>MMj*A``7BEqI-#-vAKC`9Ql5C35K+5dD OiqKPDkf*L8IsXET1M}wq literal 0 HcmV?d00001 diff --git a/icons/mob/human_races/cyberlimbs/veymed/dionaea/skrellian.dmi b/icons/mob/human_races/cyberlimbs/veymed/dionaea/skrellian.dmi new file mode 100644 index 0000000000000000000000000000000000000000..243d9fde59676b98cab3010474e88d09fccc2c6c GIT binary patch literal 6499 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 U$g?%@uL)#w+T5`C%0000dP)t-sz`(#6 z85tuZBQi2F9V~Y}OPDGuDwdX(s;a6EIbjk?dV=-0C=2@lDi7SFbqX!`zuVcm%i36C81+I&{a^}o|w=S0^WtCwr zE0hYyiZksoEkm3cR3j|)=|c@93Z+v)6U0cE#pr|F-�Ba5sS6q8P&DgZ?%8XW~oO z#Fz=GNm!1UA|XxT_OIhWX@cB}ZK~Cx?VI(z-U?W*4z$l*ga7~out`KgRCt{2oWX9> zKomu1qDsj!<46Gni^P`NE{R8Sp(~JJ&w?K)k-To{qFt61-SY{20b9(9p%@4b1RTJhv%Qey}qgggkwoey>k>1(yK*wMKVWKqRBeLN2s%w>_;%b2EY zCAR2LK&y}EVF9HqU=p3Oi7cSQq_+Ba9$;kwHjf%IF{fFF0#^Dpd02q_6WB#u(;n_L z11tTSJQSA?s(>=88Hk+sZ?=JCU8xy{`B(9=i=A%qY@2qA(CO}rJoQ&2qAc75Qk5nHIpsh%Lvhj~tQY$mE<@edTBIx49JWU7F0=MU~23Ir}FKiGhloF3I6i}2qA4*LT_ALh9lk6@F^`bYsD zIu3;g#WXBH=p%Wqh7N^NSQl>lanM%M3Kuk~5JW28O%!+e7tv zz}G7rU#Riu;%@z!%ixtat4e(7oL*zV^$EO|C;E-^-pjk$WZzfNA9uOll$y&YNcE43 zCcq!IWA97vUkUxw&$v%`>JPq*@62z8d6SSIwByoOzC4lv=LH6oMoRr34j7?ug?Gj zQvJah6cuc}?mYuN{WnWKG!*-V3eZT>{Y~?GM!sVi00f~NN7t0g8 ziWhJdH--vd$(C3^qTh_pChk&;069` zbXN!OUSZQ^bB6c?iGE{o+1{Lj`hB6NRPP5&^KZrK9gxMMS3s(t5JCtcgpeKb8={}Z URq|%y2><{907*qoM6N<$f;N^+aR2}S literal 0 HcmV?d00001 diff --git a/nano/templates/mechfab.tmpl b/nano/templates/mechfab.tmpl index 29afe23cf9..bc218c8125 100644 --- a/nano/templates/mechfab.tmpl +++ b/nano/templates/mechfab.tmpl @@ -4,6 +4,14 @@ {{:data.sync}}
+ {{if data.species_types}} +
+ {{for data.species_types}} + {{:helper.link(value, null, {'species' : value}, value == data.species ? 'selected' : null)}} + {{/for}} +
+
+ {{/if}} {{if data.manufacturers}}
{{for data.manufacturers}} diff --git a/polaris.dme b/polaris.dme index 78ade1f269..2abb8776fb 100644 --- a/polaris.dme +++ b/polaris.dme @@ -2615,6 +2615,7 @@ #include "code\modules\research\designs\xenobio_toys.dm" #include "code\modules\research\designs\circuits\ai_modules.dm" #include "code\modules\research\designs\circuits\circuits.dm" +#include "code\modules\research\designs\circuits\disks.dm" #include "code\modules\scripting\Errors.dm" #include "code\modules\scripting\IDE.dm" #include "code\modules\scripting\Options.dm"