diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 36b9cc01a38c..fd3cdcab9263 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -155,11 +155,36 @@ #define ASSEMBLY_UNLOCKED 1 #define ASSEMBLY_LOCKED 2 +// RESEARCH UPGRADES DEFINES // + // Matrix CAS Upgrades #define MATRIX_DEFAULT 0 #define MATRIX_NVG 1 #define MATRIX_WIDE 2 +#define RESEARCH_UPGRADE_EXCLUDE_BUY -2 +#define RESEARCH_UPGRADE_CATEGORY -1 //lord forgive me +#define RESEARCH_UPGRADE_TIER_1 1 +#define RESEARCH_UPGRADE_TIER_2 2 +#define RESEARCH_UPGRADE_TIER_3 3 +#define RESEARCH_UPGRADE_TIER_4 4 +#define RESEARCH_UPGRADE_TIER_5 5 +//Value define + +#define ITEM_MACHINERY_UPGRADE "Machinery" //*must* be same as category name. +#define ITEM_ACCESSORY_UPGRADE "Items" +#define ITEM_ARMOR_UPGRADE "Armor" + +//injector plate stuff +#define EMERGENCY_PLATE_OD_PROTECTION_OFF 0 +#define EMERGENCY_PLATE_OD_PROTECTION_STRICT 1 +#define EMERGENCY_PLATE_OD_PROTECTION_DYNAMIC 2 +#define EMERGENCY_PLATE_OD_WARNING 1 +#define EMERGENCY_PLATE_ADJUSTED_WARNING 2 + + +// RESEARCH UPGRADES DEFINES END + // Statistics defines #define STATISTIC_XENO "xeno" #define STATISTIC_HUMAN "human" diff --git a/code/datums/research_upgrade_datum.dm b/code/datums/research_upgrade_datum.dm new file mode 100644 index 000000000000..1644667c75f8 --- /dev/null +++ b/code/datums/research_upgrade_datum.dm @@ -0,0 +1,122 @@ +/datum/research_upgrades + ///unique to every upgrade. not the name of the item. name of the upgrade + var/name = "Upgrade." + ///name of upgrades, not items. Items are at research_upgrades.dm somewhere in item folder. + var/desc = "something is broken. yippee!!" + ///which behavior should this type follow. Should this be completely excluded from the buy menu? should it be one of the dropdown options? + var/behavior = RESEARCH_UPGRADE_EXCLUDE_BUY // should this be on the list? whatever. + /// the price of the upgrade, refer to this: 500 is a runner, 8k is queen. T3 is usually 3k. + var/value_upgrade = 1000 + /// actual path to the item.(upgrade) + var/item_reference + ///In which tab the upgrade should be. + var/upgrade_type + ///Clearance requirment to buy this upgrade. 5x is level 6. Why is it not that way? no one knows. + var/clearance_req = 5 + +/datum/research_upgrades/machinery + name = "Machinery" + behavior = RESEARCH_UPGRADE_CATEGORY // one on the dropdown choices you get + +/datum/research_upgrades/machinery/autodoc + name = "AutoDoc Upgrade" + behavior = RESEARCH_UPGRADE_EXCLUDE_BUY + item_reference = /obj/item/research_upgrades/autodoc + upgrade_type = ITEM_MACHINERY_UPGRADE + +/datum/research_upgrades/machinery/autodoc/internal_bleed + name = "AutoDoc Internal Bleeding Repair" + desc = "A data and instruction set for the Autodoc, making it capable of rapidly fixing internal bleeding." + behavior = RESEARCH_UPGRADE_TIER_1 + value_upgrade = 1000 + clearance_req = 1 + +/datum/research_upgrades/machinery/autodoc/broken_bone + name = "AutoDoc Bone Fracture Repair" + desc = "A data instruction set for the Autodoc, making it capable of setting fractures and applying bonegel." + behavior = RESEARCH_UPGRADE_TIER_2 + value_upgrade = 5000 + clearance_req = 3 + +/datum/research_upgrades/machinery/autodoc/organ_damage + name = "AutoDoc Broken Organ Repair" + desc = "A data and instruction set for the Autodoc, making it capable of fixing organ damage." + behavior = RESEARCH_UPGRADE_TIER_3 + value_upgrade = 4500 + clearance_req = 2 + +/datum/research_upgrades/machinery/autodoc/larva_removal + name = "AutoDoc Embryo Removal" + desc = "Data and instruction set for AutoDoc making it mildly proficient in removing parasites left by unknown organism." + behavior = RESEARCH_UPGRADE_TIER_4 + value_upgrade = 8000 + clearance_req = 6 + + +/datum/research_upgrades/machinery/sleeper + name = "Sleeper Upgrade" + desc = "Research upgrade for Sleeper system, technology on this disk is used on a sleeper to allow wider spectrum of chemicals to be administered, as well as upgrading dialysis software." + behavior = RESEARCH_UPGRADE_TIER_1 + value_upgrade = 1000 + item_reference = /obj/item/research_upgrades/sleeper + upgrade_type = ITEM_MACHINERY_UPGRADE + clearance_req = 2 + +/datum/research_upgrades/item + name = "Items" + behavior = RESEARCH_UPGRADE_CATEGORY + +/datum/research_upgrades/item/research_credits + name = "Research Credits" + desc = "Sell the data acquired to the nearest Weyland-Yutani Science division team for two points." + value_upgrade = 2000 + item_reference = /obj/item/research_upgrades/credits + behavior = RESEARCH_UPGRADE_TIER_1 + upgrade_type = ITEM_ACCESSORY_UPGRADE + clearance_req = 3 + +/datum/research_upgrades/item/laser_scalpel + name = "Laser Scalpel" + desc = "An advanced, robust version of the normal scalpel, allowing it to pierce through thick skin and chitin alike with extreme ease." + value_upgrade = 3000 + item_reference = /obj/item/tool/surgery/scalpel/laser/advanced + behavior = RESEARCH_UPGRADE_TIER_1 + upgrade_type = ITEM_ACCESSORY_UPGRADE + clearance_req = 3 + +/datum/research_upgrades/armor + name = "Armor" + behavior = RESEARCH_UPGRADE_CATEGORY + +/datum/research_upgrades/armor/translator + name = "Universal Translator Plate" + desc = "A uniform-attachable plate capable of translating any unknown language heard by the wearer." + value_upgrade = 2000 + behavior = RESEARCH_UPGRADE_TIER_1 + clearance_req = 4 + upgrade_type = ITEM_ARMOR_UPGRADE + item_reference = /obj/item/clothing/accessory/health/research_plate/translator + + +/datum/research_upgrades/armor/coagulator + name = "Active Blood Coagulator Plate" + desc = "A uniform-attachable plate capable of coagulating any bleeding wounds the user possesses." + value_upgrade = 3000 + behavior = RESEARCH_UPGRADE_TIER_1 + clearance_req = 2 + upgrade_type = ITEM_ARMOR_UPGRADE + item_reference = /obj/item/clothing/accessory/health/research_plate/coagulator + +/datum/research_upgrades/armor/emergency_injector + name = "Medical Emergency Injector" + desc = "A medical plate with two buttons on the sides with hefty chemical tank. Attached to uniform and on simultanious press injects emergency dose of medical chemicals much larger than a normal emergency autoinjector. Single time use and is recycled in biomass printer. Features overdose protection" + value_upgrade = 1000 + clearance_req = 3 + behavior = RESEARCH_UPGRADE_TIER_1 + upgrade_type = ITEM_ARMOR_UPGRADE + item_reference = /obj/item/clothing/accessory/health/research_plate/emergency_injector + + + + + diff --git a/code/game/machinery/computer/research.dm b/code/game/machinery/computer/research.dm index d5158cb76451..28c028f37d9a 100644 --- a/code/game/machinery/computer/research.dm +++ b/code/game/machinery/computer/research.dm @@ -53,6 +53,12 @@ var/obj/item/paper/research_report/CR = P.convert_to_chem_report() GLOB.chemical_data.save_document(CR, response, CR.name) return + //biomass credits rewards + if(istype(B, /obj/item/research_upgrades/credits)) + var/obj/item/research_upgrades/credits/cred = B + GLOB.chemical_data.update_credits(cred.credit_value) + visible_message(SPAN_NOTICE("[user] inserts [cred] in [src], collecting 2 points from sales.")) + qdel(cred) //Clearance Updating if(!istype(B, /obj/item/card/id)) return @@ -162,7 +168,6 @@ visible_message(SPAN_NOTICE("Clearance access increased to level [GLOB.chemical_data.clearance_level] for [cost] credits.")) msg_admin_niche("[key_name(user)] traded research credits to upgrade the clearance to level [GLOB.chemical_data.clearance_level].") if(max_clearance < GLOB.chemical_data.clearance_level) - GLOB.chemical_data.update_income(1) //Bonus income and a paper for buying clearance instead of swiping it up switch(GLOB.chemical_data.clearance_level) if(2) new /obj/item/paper/research_notes/unique/tier_two/(photocopier.loc) diff --git a/code/game/machinery/medical_pod/autodoc.dm b/code/game/machinery/medical_pod/autodoc.dm index 7049df4c661c..1e3bf6e967d0 100644 --- a/code/game/machinery/medical_pod/autodoc.dm +++ b/code/game/machinery/medical_pod/autodoc.dm @@ -331,10 +331,11 @@ if(ORGAN_SURGERY) switch(S.surgery_procedure) if("damage") - if(prob(30)) visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Beginning organ restoration."); + if(prob(30)) + visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Beginning organ restoration.") if(S.unneeded) sleep(UNNEEDED_DELAY) - visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Procedure has been deemed unnecessary."); + visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Procedure has been deemed unnecessary.") surgery_todo_list -= S continue open_incision(H,S.limb_ref) @@ -352,7 +353,7 @@ if(istype(S.organ_ref,/datum/internal_organ)) S.organ_ref.rejuvenate() else - visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Organ is missing."); + visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Organ is missing.") // close them if(S.limb_ref.name != "groin") // TODO: fix brute damage before closing @@ -360,10 +361,11 @@ close_incision(H,S.limb_ref) if("eyes") - if(prob(30)) visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Beginning corrective eye surgery."); + if(prob(30)) + visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Beginning corrective eye surgery.") if(S.unneeded) sleep(UNNEEDED_DELAY) - visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Procedure has been deemed unnecessary."); + visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Procedure has been deemed unnecessary.") surgery_todo_list -= S continue if(istype(S.organ_ref,/datum/internal_organ/eyes)) @@ -392,15 +394,33 @@ H.sdisabilities &= ~DISABILITY_BLIND E.heal_damage(E.damage) E.eye_surgery_stage = 0 + if("larva") + if(prob(30)) + visible_message("[icon2html(src, viewers(src))] \The [src]beeps: Removing unknown parasites.") + if(!locate(/obj/item/alien_embryo) in occupant) + sleep(UNNEEDED_DELAY) + visible_message("[icon2html(src, viewers(src))] [src] speaks: Procedure has been deemed unnecessary.")// >:) + surgery_todo_list -= S + continue + sleep(SCALPEL_MAX_DURATION + HEMOSTAT_MAX_DURATION + REMOVE_OBJECT_MAX_DURATION) + var/obj/item/alien_embryo/alien_larva = locate() in occupant + var/mob/living/carbon/xenomorph/larva/living_xeno = locate() in occupant + if(living_xeno) + living_xeno.forceMove(get_turf(occupant)) //funny stealth larva bursts incoming + qdel(alien_larva) + else + alien_larva.forceMove(get_turf(occupant)) + occupant.status_flags &= ~XENO_HOST if(LIMB_SURGERY) switch(S.surgery_procedure) if("internal") - if(prob(30)) visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Beginning internal bleeding procedure."); + if(prob(30)) + visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Beginning internal bleeding procedure.") if(S.unneeded) sleep(UNNEEDED_DELAY) - visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Procedure has been deemed unnecessary."); + visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Procedure has been deemed unnecessary.") surgery_todo_list -= S continue open_incision(H,S.limb_ref) @@ -415,10 +435,11 @@ close_incision(H,S.limb_ref) if("broken") - if(prob(30)) visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Beginning broken bone procedure."); + if(prob(30)) + visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Beginning broken bone procedure.") if(S.unneeded) sleep(UNNEEDED_DELAY) - visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Procedure has been deemed unnecessary."); + visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Procedure has been deemed unnecessary.") surgery_todo_list -= S continue open_incision(H,S.limb_ref) @@ -437,10 +458,11 @@ close_incision(H,S.limb_ref) if("missing") - if(prob(30)) visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Beginning limb replacement."); + if(prob(30)) + visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Beginning limb replacement.") if(S.unneeded) sleep(UNNEEDED_DELAY) - visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Procedure has been deemed unnecessary."); + visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Procedure has been deemed unnecessary.") surgery_todo_list -= S continue @@ -519,6 +541,7 @@ close_encased(H,S.limb_ref) close_incision(H,S.limb_ref) + if(prob(30)) visible_message("[icon2html(src, viewers(src))] \The [src] speaks: Procedure complete."); surgery_todo_list -= S continue @@ -590,6 +613,8 @@ unslashable = TRUE use_power = USE_POWER_IDLE idle_power_usage = 40 + /// What kind of upgrade do we have in this console? used by research upgrades. 1 is IB. 2 is bone frac. 3 is organ damage. 4 is larva removal + var/list/upgrades = list() /obj/structure/machinery/autodoc_console/Initialize() . = ..() @@ -629,6 +654,18 @@ /obj/structure/machinery/autodoc_console/process() updateUsrDialog() +/obj/structure/machinery/autodoc_console/attackby(obj/item/with, mob/user) + if(istype(with, /obj/item/research_upgrades/autodoc)) + var/obj/item/research_upgrades/autodoc/upgrd = with + for(var/iter in upgrades) + if(iter == upgrd.value) + to_chat(user, SPAN_NOTICE("This data is already present in [src]!")) + return + if(!user.drop_inv_item_to_loc(with, src)) + return + to_chat(user, SPAN_NOTICE("You insert the data into [src] and the drive whirrs to life, reading the data.")) + upgrades += upgrd.value + /obj/structure/machinery/autodoc_console/attack_hand(mob/living/user) if(..()) return @@ -700,6 +737,9 @@ if("eyes") surgeryqueue["eyes"] = 1 dat += "Corrective Eye Surgery" + if("larva") + surgeryqueue["larva"] = 1 + dat += "Experimental Parasite Surgery" if(LIMB_SURGERY) switch(A.surgery_procedure) if("internal") @@ -720,6 +760,7 @@ if("open") surgeryqueue["open"] = 1 dat += "Close Open Incisions" + dat += "
" dat += "
Begin Surgery - Refresh Menu - Clear Queue
" @@ -743,6 +784,22 @@ if(isnull(surgeryqueue["toxin"])) dat += "Bloodstream Toxin Removal
" dat += "
" + if(length(upgrades)) + dat += "Orthopedic Surgeries" + for(var/iter in upgrades) + switch(iter) + if(RESEARCH_UPGRADE_TIER_2) + if(isnull(surgeryqueue["broken"])) + dat += "Broken Bone Surgery
" + if(RESEARCH_UPGRADE_TIER_1) + if(isnull(surgeryqueue["internal"])) + dat += "Internal Bleeding Surgery
" + if(RESEARCH_UPGRADE_TIER_3) + if(isnull(surgeryqueue["organdamage"])) + dat += "Organ Damage Treatment
" + if(RESEARCH_UPGRADE_TIER_4) + if(isnull(surgeryqueue["larva"])) + dat += "Experimental Parasite Exctraction
" else dat += "The autodoc is empty." dat += text("Close", user) @@ -797,7 +854,9 @@ if(!needed) N.fields["autodoc_manual"] += create_autodoc_surgery(null,ORGAN_SURGERY,"damage",1) updateUsrDialog() - + if(href_list["larva"]) + N.fields["autodoc_manual"] += create_autodoc_surgery("chest",ORGAN_SURGERY,"larva",0) + updateUsrDialog() if(href_list["internal"]) for(var/obj/limb/L in connected.occupant.limbs) if(L) diff --git a/code/game/machinery/medical_pod/sleeper.dm b/code/game/machinery/medical_pod/sleeper.dm index 5868df901c6a..4250d9d7d0af 100644 --- a/code/game/machinery/medical_pod/sleeper.dm +++ b/code/game/machinery/medical_pod/sleeper.dm @@ -59,6 +59,20 @@ // tgui \\ +/obj/structure/machinery/sleep_console/attackby(obj/item/with, mob/user) + if(!istype(with, /obj/item/research_upgrades/sleeper)) + return + if(connected.upgraded) + return + if(!user.drop_inv_item_to_loc(with, src)) + return + to_chat(user, SPAN_NOTICE("As you insert [with] into the console, you hear it whir to life as [src] reads it.")) + connected.upgraded = TRUE + connected.available_chemicals = connected.upgraded_chemicals + connected.emergency_chems = connected.upgraded_emergency_chems + connected.reagent_removed_per_second = connected.reagent_removed_per_second_upgraded + + /obj/structure/machinery/sleep_console/attack_hand(mob/living/user) if(..()) return @@ -243,16 +257,21 @@ entry_timer = 2 SECONDS - var/available_chemicals = list("inaprovaline", "paracetamol", "anti_toxin", "dexalin", "tricordrazine") - var/emergency_chems = list("inaprovaline", "paracetamol", "anti_toxin", "dexalin", "tricordrazine", "oxycodone", "bicaridine", "kelotane") - var/amounts = list(5, 10) + var/list/available_chemicals = list("inaprovaline", "paracetamol", "anti_toxin", "dexalin", "tricordrazine") + var/list/upgraded_chemicals = list("inaprovaline", "tramadol", "anti_toxin", "dexalinp", "tricordrazine", "alkysine", "imidazoline") + var/list/emergency_chems = list("inaprovaline", "paracetamol", "anti_toxin", "dexalin", "tricordrazine", "oxycodone", "bicaridine", "kelotane") + var/list/upgraded_emergency_chems = list("inaprovaline", "tramadol", "anti_toxin", "dexalinp", "tricordrazine", "oxycodone", "bicaridine", "kelotane", "meralyne", "dermaline", "alkysine", "imidazoline") + var/list/amounts = list(5, 10) var/filtering = FALSE var/obj/structure/machinery/sleep_console/connected var/min_health = 10 var/max_chem = 40 var/auto_eject_dead = FALSE var/reagent_removed_per_second = AMOUNT_PER_TIME(3, 1 SECONDS) + var/reagent_removed_per_second_upgraded = AMOUNT_PER_TIME(8, 1 SECONDS) var/dialysis_started_reagent_vol = null // how many reagents the occupant had in them when we STARTED dialysis + ///is it already upgraded by research disc and do we have upgraded chemicals? + var/upgraded = FALSE use_power = USE_POWER_IDLE idle_power_usage = 15 diff --git a/code/game/objects/items/old_research.dm b/code/game/objects/items/old_research.dm deleted file mode 100644 index 7330baac5812..000000000000 --- a/code/game/objects/items/old_research.dm +++ /dev/null @@ -1,112 +0,0 @@ -/obj/item/XenoBio - name = "An unidentified Alien Organ" - desc = "Looking at it makes you want to vomit" - icon = 'icons/obj/items/Marine_Research.dmi' - icon_state = "biomass" - black_market_value = 50 - //For all of them for now, until we have specific organs/more techs - -/obj/item/XenoBio/Resin - name = "Alien Resin" - desc = "A piece of alien Resin" - icon_state = "biomass" - - -/obj/item/XenoBio/Chitin - name = "Alien Chitin" - desc = "A chunk of alien Chitin" - icon_state = "chitin-chunk" - - -/obj/item/XenoBio/Blood - name = "Alien Blood" - desc = "A sample of alien Blood" - icon_state = "blood-vial" - - - - - - - - -// ======== ITEMS YOU CAN MAKE THAT ARE BADASS ======== // - -/obj/item/XenoItem - name = "Strange Item" - desc = "Some sort of fucked up item from the Weyland-Yutani brand 3D Biometric Printer... Probably should make a bug report if you got this..." - icon_state = "chitin-chunk" - icon = 'icons/obj/items/Marine_Research.dmi' - -/obj/item/XenoItem/ResinPaste - name = "Resin Paste" - desc = "This resin paste will fix a broken helmet. (Use by clicking the glue with the armor)." - icon_state = "resin-glue" - icon = 'icons/obj/items/Marine_Research.dmi' - -/obj/item/XenoItem/ResinPaste/afterattack(obj/item/clothing/head/helmet/marine/A as obj, mob/user as mob) - if (!istype(A) || !istype(usr)) - to_chat(usr, "Doesn't work that way") - return - if (A.anti_hug >= 1) - usr <<"This Helmet can't be further reinforced." - return - to_chat(usr, "You reinforce the Helmet...") - A.anti_hug++ - user.temp_drop_inv_item(src) - qdel(src) - ..() - return - -/obj/item/XenoItem/ChitinPlate - name = "Chitin Plate" - desc = "A plate of Chitin Armor that can be attached to your Marine Armor to make it stronger, but will also slow you down. (Use by clicking the plate with the armor)." - icon_state = "chitin-armor" - icon = 'icons/obj/items/Marine_Research.dmi' - -/obj/item/XenoItem/ChitinPlate/afterattack(obj/item/clothing/suit/storage/marine/A as obj, mob/user as mob) - if (!istype(A) || !istype(usr)) - to_chat(usr, "Doesn't work that way...") - return - if (A.flags_marine_armor & ARMOR_IS_REINFORCED) - usr <<"This armor is already reinforced." - return - to_chat(usr, "You reinforce the armor with some Chitin Plating...") - A.armor_melee = 70 - A.armor_bullet = 90 - A.armor_laser = 7 - A.armor_energy = 40 - A.armor_bomb = 50 - A.armor_bio = 40 - A.armor_rad = 20 - A.slowdown++ - A.flags_marine_armor |= ARMOR_IS_REINFORCED - user.temp_drop_inv_item(src) - qdel(src) - ..() - return - - -/obj/item/XenoItem/AntiAcid - name = "Anti-Acid Spray" - desc = "A spray that makes whatever it's used on unacidable. Single use." - icon_state = "anti-acid" - icon = 'icons/obj/items/Marine_Research.dmi' - - -/obj/item/XenoItem/AntiAcid/afterattack(obj/A as obj, mob/user as mob, proximity) - if (!isobj(A)) - to_chat(usr, "Doesn't work that way...") - return - if (A.unacidable == 1) - to_chat(usr, "It's already resistant to acid...") - return - if (istype(A, /obj/structure/machinery/door)) - to_chat(usr, "It doesn't work on doors...") - return - to_chat(usr, "You spray [A] with the Anti-Acid spray making it unacidable...") - A.unacidable = TRUE - user.temp_drop_inv_item(src) - qdel(src) - ..() - return diff --git a/code/game/objects/items/research_upgrades.dm b/code/game/objects/items/research_upgrades.dm new file mode 100644 index 000000000000..315c27ea4bfe --- /dev/null +++ b/code/game/objects/items/research_upgrades.dm @@ -0,0 +1,73 @@ +//prop items +/obj/item/oldresearch + name = "Alien Organ" + desc = "Looking at it makes you want to vomit" + icon = 'icons/obj/items/Marine_Research.dmi' + icon_state = "biomass" + black_market_value = 50 + //For all of them for now, until we have specific organs/more techs + +/obj/item/oldresearch/Resin + name = "Alien Resin" + desc = "A piece of alien Resin" + icon_state = "biomass" + + +/obj/item/oldresearch/Chitin + name = "Chunk of Chitin" + desc = "A chunk of alien Chitin" + icon_state = "chitin-chunk" + + +/obj/item/oldresearch/Blood + name = "Blood Vial" + desc = "A sample of alien Blood" + icon_state = "blood-vial" + +//prop items end + + + +//previously file holding left over stuff that never got finished from 8 years ago, it was boring though, so we change that. +/obj/item/research_upgrades + name = "Research upgrade" + desc = "Somehow you got this, you shouldnt be able to, consider yourself special." + icon = 'icons/obj/items/disk.dmi' + icon_state = "datadisk1" // doesnt HAVE to be a disk! + ///technology stored on this disk, goes through one to whatever levels of upgrades there are. + var/value + +/obj/item/research_upgrades/autodoc + name = "Research Upgrade (AutoDoc)" + value = RESEARCH_UPGRADE_TIER_1 + + +/obj/item/research_upgrades/autodoc/Initialize(mapload, value) + . = ..() + src.value = value + desc = "Research upgrade for AutoDoc, Technology on this disk is used [get_upgrade_text()] Insert it in the autodoc to use it." + +/obj/item/research_upgrades/autodoc/proc/get_upgrade_text() + switch(value) + if(RESEARCH_UPGRADE_TIER_1) + return "for stitching up internal bleedings" + if(RESEARCH_UPGRADE_TIER_2) + return "for fixing broken bones." + if(RESEARCH_UPGRADE_TIER_3) + return "for treating internal organ damage." + if(RESEARCH_UPGRADE_TIER_4) + return "for extracting unknown parasites." + +/obj/item/research_upgrades/sleeper + name = "Research Upgrade (Sleeper)" + desc = "Research upgrade for sleeper system, Technology on this disk is used on a sleeper to allow wider spectrum of chemicals to be administered" + + +/obj/item/research_upgrades/credits + name = "Research Market (Credits)" + var/credit_value = 2 + +/obj/item/research_upgrades/credits/Initialize(mapload, ...) + . = ..() + credit_value = rand(2, 3) + desc = "Research points disk for chemical synthesis, insert this into research computer in order to sell the data and acquire [credit_value] points" diff --git a/code/game/objects/items/tools/surgery_tools.dm b/code/game/objects/items/tools/surgery_tools.dm index a1792b574eec..0c5b3925ca34 100644 --- a/code/game/objects/items/tools/surgery_tools.dm +++ b/code/game/objects/items/tools/surgery_tools.dm @@ -532,8 +532,8 @@ t. optimisticdude to_chat(usr, "This is difficult, you probably shouldn't move") return to_chat(usr, "You've cut through the outer layers of Chitin") - new /obj/item/XenoBio/Chitin(T.loc) //This will be 1-3 Chitin eventually (depending on tier) - new /obj/item/XenoBio/Chitin(T.loc) //This will be 1-3 Chitin eventually (depending on tier) + new /obj/item/oldresearch/Chitin(T.loc) //This will be 1-3 Chitin eventually (depending on tier) + new /obj/item/oldresearch/Chitin(T.loc) //This will be 1-3 Chitin eventually (depending on tier) T.butchery_progress++ active = 0 if(1) @@ -542,7 +542,7 @@ t. optimisticdude to_chat(usr, "This is difficult, you probably shouldn't move.") return to_chat(usr, "You've cut into the chest cavity and retreived a sample of blood.") - new /obj/item/XenoBio/Blood(T.loc)//This will be a sample of blood eventually + new /obj/item/oldresearch/Blood(T.loc)//This will be a sample of blood eventually T.butchery_progress++ active = 0 if(2) @@ -552,7 +552,7 @@ t. optimisticdude return //to_chat(usr, "You've cut out an intact organ.") to_chat(usr, "You've cut out some Biomass...") - new /obj/item/XenoBio/Resin(T.loc)//This will be an organ eventually, based on the caste. + new /obj/item/oldresearch/Resin(T.loc)//This will be an organ eventually, based on the caste. T.butchery_progress++ active = 0 if(3) @@ -562,6 +562,6 @@ t. optimisticdude return to_chat(usr, "You scrape out the remaining biomass.") active = 0 - new /obj/item/XenoBio/Resin(T.loc) + new /obj/item/oldresearch/Resin(T.loc) new /obj/effect/decal/remains/xeno(T.loc) qdel(T) diff --git a/code/modules/cm_tech/implements/armor.dm b/code/modules/cm_tech/implements/armor.dm index c08bf6d3c128..de0579c0195f 100644 --- a/code/modules/cm_tech/implements/armor.dm +++ b/code/modules/cm_tech/implements/armor.dm @@ -7,9 +7,10 @@ var/base_icon_state = "regular2" slot = ACCESSORY_SLOT_ARMOR_C + /// is it *armor* or something different & irrelevant and always passes damage & doesnt take damage to itself? + var/is_armor = TRUE var/armor_health = 10 var/armor_maxhealth = 10 - var/take_slash_damage = TRUE var/slash_durability_mult = 0.25 var/FF_projectile_durability_mult = 0.1 @@ -98,14 +99,14 @@ SIGNAL_HANDLER if(damage <= 0 || (ammo_flags & AMMO_IGNORE_ARMOR)) return - + if(!is_armor) + return var/damage_to_nullify = armor_health var/final_proj_mult = FF_projectile_durability_mult var/mob/living/carbon/human/pfirer = P.firer if(user.faction != pfirer.faction) final_proj_mult = hostile_projectile_durability_mult - armor_health = max(armor_health - damage*final_proj_mult, 0) update_icon() @@ -120,6 +121,8 @@ /obj/item/clothing/accessory/health/proc/take_slash_damage(mob/living/user, list/slashdata) SIGNAL_HANDLER + if(!is_armor) + return var/armor_damage = slashdata["n_damage"] var/damage_to_nullify = armor_health armor_health = max(armor_health - armor_damage*slash_durability_mult, 0) @@ -134,7 +137,7 @@ slashdata["slash_noise"] = armor_hitsound /obj/item/clothing/accessory/health/attackby(obj/item/clothing/accessory/health/I, mob/user) - if(!istype(I, src.type) || !scrappable || has_suit || I.has_suit) + if(!istype(I, src.type) || !scrappable || has_suit || I.has_suit || !is_armor) return if(!I.armor_health && !armor_health) @@ -184,3 +187,201 @@ . = ..() if(. && !armor_health) qdel(src) + +/obj/item/clothing/accessory/health/research_plate + name = "experimental uniform attachment" + desc = "Attachment to the uniform which gives X (this shouldn't be in your handdssss)" + is_armor = FALSE + icon_state = "plate_research" + var/obj/item/clothing/attached_uni + ///can the plate be recycled after X condition? 0 means it cannot be recycled, otherwise put in the biomass points to refund. + var/recyclable_value = 0 + +/obj/item/clothing/accessory/health/research_plate/Destroy() + attached_uni = null + . = ..() + +/obj/item/clothing/accessory/health/research_plate/on_attached(obj/item/clothing/attached_to, mob/living/carbon/human/user) + . = ..() + attached_uni = attached_to + +/obj/item/clothing/accessory/health/research_plate/proc/can_recycle(mob/living/user) //override this proc for check if you can recycle the plate. + return FALSE + + +/obj/item/clothing/accessory/health/research_plate/on_attached(obj/item/clothing/S, mob/living/carbon/human/user) + . = ..() + RegisterSignal(user, COMSIG_MOB_ITEM_UNEQUIPPED, PROC_REF(on_removed_sig)) + +/obj/item/clothing/accessory/health/research_plate/on_removed(mob/living/user, obj/item/clothing/C) + . = ..() + UnregisterSignal(user, COMSIG_MOB_ITEM_UNEQUIPPED) + +/obj/item/clothing/accessory/health/research_plate/proc/on_removed_sig(mob/living/user, slot) + SIGNAL_HANDLER + if(slot != attached_uni) + return FALSE + UnregisterSignal(user, COMSIG_MOB_ITEM_UNEQUIPPED) + return TRUE + +/obj/item/clothing/accessory/health/research_plate/translator + name = "experimental language translator" + desc = "Translates any language heard by the microphones on the plate without any linguistical input, allowing to translate languages never heard before and known languages alike." + +/obj/item/clothing/accessory/health/research_plate/translator/on_attached(obj/item/clothing/S, mob/living/carbon/human/user) + . = ..() + to_chat(user, SPAN_NOTICE("[src] buzzes as it begins to listen for input.")) + user.universal_understand = TRUE + +/obj/item/clothing/accessory/health/research_plate/translator/on_removed(mob/living/carbon/human/user, obj/item/clothing/C) + . = ..() + if(user.universal_understand) + to_chat(user, SPAN_NOTICE("[src] makes a sad woop sound as it powers down.")) + attached_uni = null + if(user.chem_effect_flags & CHEM_EFFECT_HYPER_THROTTLE) // we are currently under effect of simular univeral understand drug. + return + user.universal_understand = FALSE + +/obj/item/clothing/accessory/health/research_plate/translator/on_removed_sig(mob/living/carbon/human/user, slot) + . = ..() + if(. == FALSE) + return + if(user.universal_understand) + to_chat(user, SPAN_NOTICE("[src] makes a woop sound as it is powered down.")) + if(user.chem_effect_flags & CHEM_EFFECT_HYPER_THROTTLE) // we are currently under effect of simular univeral understand drug. + return + attached_uni = null + user.universal_understand = FALSE + +/obj/item/clothing/accessory/health/research_plate/coagulator + name = "experimental blood coagulator" + desc = "A device that encourages clotting through the coordinated effort of multiple sensors and radiation emitters. The Surgeon General warns that continuous exposure to radiation may be hazardous to your health." + +/obj/item/clothing/accessory/health/research_plate/coagulator/on_attached(obj/item/clothing/S, mob/living/carbon/human/user) + . = ..() + if (user.chem_effect_flags & CHEM_EFFECT_NO_BLEEDING) + return + user.chem_effect_flags |= CHEM_EFFECT_NO_BLEEDING + to_chat(user, SPAN_NOTICE("You feel tickling as you activate [src].")) + +/obj/item/clothing/accessory/health/research_plate/coagulator/on_removed(mob/living/carbon/human/user, obj/item/clothing/C) + . = ..() + if (user.chem_effect_flags & CHEM_EFFECT_NO_BLEEDING) + user.chem_effect_flags &= CHEM_EFFECT_NO_BLEEDING + to_chat(user, SPAN_NOTICE("You feel [src] peeling off from your skin.")) + attached_uni = null + +/obj/item/clothing/accessory/health/research_plate/coagulator/on_removed_sig(mob/living/carbon/human/user, slot) + . = ..() + if(. == FALSE) + return + if(user.chem_effect_flags & CHEM_EFFECT_NO_BLEEDING) + to_chat(user, SPAN_NOTICE("You feel coagulator peeling off from your skin.")) + user.chem_effect_flags &= CHEM_EFFECT_NO_BLEEDING + attached_uni = null + +/obj/item/clothing/accessory/health/research_plate/emergency_injector + name = "emergency chemical plate" + desc = "One-time disposable research plate packing all kinds of chemicals injected at the will of the user by pressing two buttons on the sides simultaneously. The injection is painless, instant and packs much more chemicals than your normal emergency injector. Features OD Protection in three modes." + var/od_protection_mode = EMERGENCY_PLATE_OD_PROTECTION_STRICT + var/datum/action/item_action/activation + var/mob/living/wearer + var/used = FALSE + /// 1 means the player overdosed with OD_OFF mode. 2 means the plate adjusted the chemicals injected. + var/warning_type = FALSE + var/list/chemicals_to_inject = list( + "oxycodone" = 20, + "bicaridine" = 30, + "kelotane" = 30, + "meralyne" = 15, + "dermaline" = 15, + "dexalinp" = 1, + "inaprovaline" = 30, + ) + recyclable_value = 500 + +/obj/item/clothing/accessory/health/research_plate/emergency_injector/Destroy() + wearer = null + if(!QDELETED(activation)) + QDEL_NULL(activation) + . = ..() + +/obj/item/clothing/accessory/health/research_plate/emergency_injector/get_examine_text(mob/user) + . = ..() + . += SPAN_INFO("ALT-Clicking the plate will toggle overdose protection") + . += SPAN_INFO("Overdose protection seems to be [od_protection_mode == 1 ? "ON" : od_protection_mode == 2 ? "DYNAMIC" : "OFF"]") + if(used) + . += SPAN_WARNING("It is already used!") + +/obj/item/clothing/accessory/health/research_plate/emergency_injector/clicked(mob/user, list/mods) + . = ..() + if(mods["alt"]) + var/text = "You toggle overdose protection " + if(od_protection_mode == EMERGENCY_PLATE_OD_PROTECTION_DYNAMIC) + od_protection_mode = EMERGENCY_PLATE_OD_PROTECTION_OFF + text += "to OVERRIDE. Overdose protection is now offline." + else + od_protection_mode++ + if(od_protection_mode == EMERGENCY_PLATE_OD_PROTECTION_DYNAMIC) + text += "to DYNAMIC. Overdose subsystems will inject chemicals but will not go above overdose levels." + else + text += "to STRICT. Overdose subsystems will refuse to inject if any of chemicals will overdose." + to_chat(user, SPAN_NOTICE(text)) + return TRUE + return + +/obj/item/clothing/accessory/health/research_plate/emergency_injector/can_recycle(mob/living/user) + if(used) + return TRUE + return FALSE + +/obj/item/clothing/accessory/health/research_plate/emergency_injector/on_attached(obj/item/clothing/S, mob/living/carbon/human/user) + . = ..() + wearer = user + activation = new /datum/action/item_action/emergency_plate/inject_chemicals(src, attached_uni) + activation.give_to(wearer) + +/obj/item/clothing/accessory/health/research_plate/emergency_injector/on_removed(mob/living/user, obj/item/clothing/C) + . = ..() + QDEL_NULL(activation) + attached_uni = null + +/obj/item/clothing/accessory/health/research_plate/emergency_injector/on_removed_sig(mob/living/carbon/human/user, slot) + . = ..() + if(. == FALSE) + return + QDEL_NULL(activation) + attached_uni = null + +//Action buttons +/datum/action/item_action/emergency_plate/inject_chemicals/New(Target, obj/item/holder) + . = ..() + name = "Inject Emergency Plate" + action_icon_state = "regular2_100" + button.name = name + button.overlays.Cut() + button.overlays += image('icons/obj/items/items.dmi', button, action_icon_state) + +/obj/item/clothing/accessory/health/research_plate/emergency_injector/ui_action_click(mob/owner, obj/item/holder) + if(used) + to_chat(wearer, SPAN_DANGER("[src]'s inner reserve is empty, replace the plate!")) + return + for(var/chemical in chemicals_to_inject) + var/datum/reagent/reag = GLOB.chemical_reagents_list[chemical] + if(wearer.reagents.get_reagent_amount(chemical) + chemicals_to_inject[chemical] > reag.overdose) + if(od_protection_mode == EMERGENCY_PLATE_OD_PROTECTION_STRICT) + to_chat(wearer, SPAN_DANGER("You hold the two buttons, but the plate buzzes and refuses to inject, indicating the potential overdose!")) + return + if (od_protection_mode == EMERGENCY_PLATE_OD_PROTECTION_DYNAMIC) + var/adjust_volume_to_inject = reag.overdose - wearer.reagents.get_reagent_amount(chemical) + chemicals_to_inject[chemical] = adjust_volume_to_inject + warning_type = EMERGENCY_PLATE_ADJUSTED_WARNING + if(wearer.reagents.get_reagent_amount(chemical) + chemicals_to_inject[chemical] > reag.overdose && od_protection_mode == EMERGENCY_PLATE_OD_PROTECTION_OFF) + warning_type = EMERGENCY_PLATE_OD_WARNING + wearer.reagents.add_reagent(chemical, chemicals_to_inject[chemical]) + if(warning_type == EMERGENCY_PLATE_OD_WARNING) + to_chat(wearer, SPAN_DANGER("You hold the two buttons, and the plate injects the chemicals, but makes a worrying beep, indicating overdose!")) + if(warning_type == EMERGENCY_PLATE_ADJUSTED_WARNING) + to_chat(wearer, SPAN_DANGER("You hold the two buttons, and the plate injects the chemicals, but makes a relieving beep, indicating it adjusted amounts it injected to prevent overdose!")) + playsound(loc, "sound/items/air_release.ogg", 100, TRUE) + used = TRUE diff --git a/code/modules/mob/living/carbon/xenomorph/Evolution.dm b/code/modules/mob/living/carbon/xenomorph/Evolution.dm index b6576b764b51..4589a3212893 100644 --- a/code/modules/mob/living/carbon/xenomorph/Evolution.dm +++ b/code/modules/mob/living/carbon/xenomorph/Evolution.dm @@ -130,7 +130,9 @@ // subtract the threshold, keep the stored amount evolution_stored -= evolution_threshold - + var/obj/item/organ/xeno/organ = locate() in src + if(!isnull(organ)) + qdel(organ) //From there, the new xeno exists, hopefully var/mob/living/carbon/xenomorph/new_xeno = new M(get_turf(src), src) @@ -330,7 +332,9 @@ xeno_type = /mob/living/carbon/xenomorph/defender if(XENO_CASTE_BURROWER) xeno_type = /mob/living/carbon/xenomorph/burrower - + var/obj/item/organ/xeno/organ = locate() in src + if(!isnull(organ)) + qdel(organ) var/mob/living/carbon/xenomorph/new_xeno = new xeno_type(get_turf(src), src) new_xeno.built_structures = built_structures.Copy() diff --git a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm index 16cfeca8f87e..ef82dfdd75bb 100644 --- a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm +++ b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm @@ -249,6 +249,11 @@ // Life reduction variables. var/life_slow_reduction = -1.5 + //Research organ harvesting. + var/organ_removed = FALSE + /// value of organ in each caste, e.g. 10k is autodoc larva removal. runner is 500 + var/organ_value = 0 + ////////////////////////////////////////////////////////////////// // @@ -263,6 +268,7 @@ // an easily modularizable way. So, here you go. // ////////////////////////////////////////////////////////////////// + var/tunnel = FALSE /// for check on lurker invisibility var/stealth = FALSE @@ -344,6 +350,13 @@ src.hivenumber = old_xeno.hivenumber else if(hivenumber) src.hivenumber = hivenumber + //putting the organ in for research + if(organ_value != 0) + var/obj/item/organ/xeno/organ = new() //give + organ.forceMove(src) + organ.research_value = organ_value + organ.caste_origin = caste_type + organ.icon_state = get_organ_icon() var/datum/hive_status/hive = GLOB.hive_datum[src.hivenumber] @@ -664,6 +677,8 @@ if(iff_tag) . += SPAN_NOTICE("It has an IFF tag sticking out of its carapace.") + if(organ_removed) + . += "It seems to have its carapace cut open." /mob/living/carbon/xenomorph/Destroy() GLOB.living_xeno_list -= src @@ -983,6 +998,9 @@ visible_message(SPAN_DANGER("[src] has successfully extinguished themselves!"), \ SPAN_NOTICE("We extinguish ourselves."), null, 5) +/mob/living/carbon/xenomorph/proc/get_organ_icon() + return "heart_t[tier]" + /mob/living/carbon/xenomorph/resist_restraints() if(!legcuffed) return diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Burrower.dm b/code/modules/mob/living/carbon/xenomorph/castes/Burrower.dm index bec41a87521e..294817f5e74e 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Burrower.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Burrower.dm @@ -52,6 +52,7 @@ base_pixel_x = 0 base_pixel_y = -20 tier = 2 + organ_value = 1500 base_actions = list( /datum/action/xeno_action/onclick/xeno_resting, diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm b/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm index d290b917e945..1da4c632e917 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm @@ -58,6 +58,7 @@ tier = 2 pixel_x = -16 //Needed for 2x2 old_x = -16 + organ_value = 1000 base_actions = list( /datum/action/xeno_action/onclick/xeno_resting, diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Crusher.dm b/code/modules/mob/living/carbon/xenomorph/castes/Crusher.dm index 38b1e5816ffe..7ccab754d6dd 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Crusher.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Crusher.dm @@ -51,7 +51,7 @@ base_pixel_y = -16 rebounds = FALSE // no more fucking pinball crooshers - + organ_value = 3000 base_actions = list( /datum/action/xeno_action/onclick/xeno_resting, /datum/action/xeno_action/onclick/regurgitate, diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Defender.dm b/code/modules/mob/living/carbon/xenomorph/castes/Defender.dm index a63bafb5d2b0..548b0389e683 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Defender.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Defender.dm @@ -39,6 +39,7 @@ pixel_x = -16 old_x = -16 tier = 1 + organ_value = 1000 base_actions = list( /datum/action/xeno_action/onclick/xeno_resting, diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Drone.dm b/code/modules/mob/living/carbon/xenomorph/castes/Drone.dm index a0ce70316eb8..e6c4a76c9353 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Drone.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Drone.dm @@ -53,6 +53,7 @@ icon_state = "Drone Walking" plasma_types = list(PLASMA_PURPLE) tier = 1 + organ_value = 800 pixel_x = -12 old_x = -12 base_actions = list( diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Hivelord.dm b/code/modules/mob/living/carbon/xenomorph/castes/Hivelord.dm index ee4157a67d84..43fb8b4976f2 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Hivelord.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Hivelord.dm @@ -56,6 +56,7 @@ mob_size = MOB_SIZE_BIG drag_delay = 6 //pulling a big dead xeno is hard tier = 2 + organ_value = 1500 base_actions = list( /datum/action/xeno_action/onclick/xeno_resting, diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm b/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm index 5196be26f3d7..0ab9e9862b16 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm @@ -38,6 +38,7 @@ pixel_x = -12 old_x = -12 tier = 2 + organ_value = 2000 base_actions = list( /datum/action/xeno_action/onclick/xeno_resting, /datum/action/xeno_action/onclick/regurgitate, diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Praetorian.dm b/code/modules/mob/living/carbon/xenomorph/castes/Praetorian.dm index 69b679573352..70d33b905a00 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Praetorian.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Praetorian.dm @@ -52,6 +52,7 @@ mob_size = MOB_SIZE_BIG drag_delay = 6 //pulling a big dead xeno is hard tier = 3 + organ_value = 3000 base_actions = list( /datum/action/xeno_action/onclick/xeno_resting, diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Predalien.dm b/code/modules/mob/living/carbon/xenomorph/castes/Predalien.dm index 841675234e63..830f4fc5a9cf 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Predalien.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Predalien.dm @@ -47,6 +47,7 @@ old_x = -16 mob_size = MOB_SIZE_BIG tier = 1 + organ_value = 20000 age = XENO_NO_AGE //Predaliens are already in their ultimate form, they don't get even better show_age_prefix = FALSE small_explosives_stun = FALSE @@ -96,6 +97,9 @@ You must still listen to the queen. "}) emote("roar") +/mob/living/carbon/xenomorph/predalien/get_organ_icon() + return "heart_t3" + /mob/living/carbon/xenomorph/predalien/resist_fire() ..() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm b/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm index f5207e6abf30..f4f57c0afbc5 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm @@ -270,6 +270,7 @@ hive_pos = XENO_QUEEN small_explosives_stun = FALSE pull_speed = 3 //screech/neurodragging is cancer, at the very absolute least get some runner to do it for teamwork + organ_value = 8000 // queen is expensive icon_xeno = 'icons/mob/xenos/queen.dmi' icon_xenonid = 'icons/mob/xenonids/queen.dmi' @@ -360,6 +361,10 @@ /mob/living/carbon/xenomorph/queen/can_destroy_special() return TRUE + +/mob/living/carbon/xenomorph/queen/get_organ_icon() + return "heart_t3" + /mob/living/carbon/xenomorph/queen/corrupted hivenumber = XENO_HIVE_CORRUPTED diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Ravager.dm b/code/modules/mob/living/carbon/xenomorph/castes/Ravager.dm index e50a0f026d65..6e5da79fbed1 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Ravager.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Ravager.dm @@ -50,7 +50,7 @@ pixel_x = -16 old_x = -16 claw_type = CLAW_TYPE_VERY_SHARP - + organ_value = 3000 base_actions = list( /datum/action/xeno_action/onclick/xeno_resting, /datum/action/xeno_action/onclick/regurgitate, diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm b/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm index 400195f21de0..8721294173e9 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm @@ -47,6 +47,7 @@ base_pixel_y = -20 pull_speed = -0.5 viewsize = 9 + organ_value = 500 //worthless mob_size = MOB_SIZE_XENO_SMALL diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Sentinel.dm b/code/modules/mob/living/carbon/xenomorph/castes/Sentinel.dm index 2e53f97e297b..47591f01cf00 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Sentinel.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Sentinel.dm @@ -39,6 +39,7 @@ pixel_x = -12 old_x = -12 tier = 1 + organ_value = 800 base_actions = list( /datum/action/xeno_action/onclick/xeno_resting, /datum/action/xeno_action/onclick/regurgitate, diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Spitter.dm b/code/modules/mob/living/carbon/xenomorph/castes/Spitter.dm index 984a2d08bb75..006f66b7f1b2 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Spitter.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Spitter.dm @@ -40,7 +40,7 @@ plasma_types = list(PLASMA_NEUROTOXIN) pixel_x = -12 old_x = -12 - + organ_value = 2000 tier = 2 base_actions = list( /datum/action/xeno_action/onclick/xeno_resting, diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm b/code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm index 1c329c8b9e82..2885dd6ac553 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm @@ -43,7 +43,7 @@ old_x = -16 tier = 2 pull_speed = 2 // about what it was before, slightly faster - + organ_value = 2000 base_actions = list( /datum/action/xeno_action/onclick/xeno_resting, /datum/action/xeno_action/onclick/regurgitate, diff --git a/code/modules/mob/living/carbon/xenomorph/damage_procs.dm b/code/modules/mob/living/carbon/xenomorph/damage_procs.dm index f399dbcb59cd..04a8f00811ad 100644 --- a/code/modules/mob/living/carbon/xenomorph/damage_procs.dm +++ b/code/modules/mob/living/carbon/xenomorph/damage_procs.dm @@ -16,6 +16,15 @@ return programmer.visible_message(SPAN_NOTICE("[programmer] reprograms \the [src]'s IFF tag."), SPAN_NOTICE("You reprogram \the [src]'s IFF tag."), max_distance = 3) return + if(stat == DEAD) + var/datum/surgery/current_surgery = active_surgeries[user.zone_selected] + if(current_surgery) + if(current_surgery.attempt_next_step(user, item)) + return + else + if(initiate_surgery_moment(item, src, "head" , user)) + return + return if(item.type in SURGERY_TOOLS_PINCH) if(!iff_tag) to_chat(user, SPAN_WARNING("\The [src] doesn't have an IFF tag to remove.")) diff --git a/code/modules/mob/living/carbon/xenomorph/update_icons.dm b/code/modules/mob/living/carbon/xenomorph/update_icons.dm index ac0c381f5ed4..d0f423c038dc 100644 --- a/code/modules/mob/living/carbon/xenomorph/update_icons.dm +++ b/code/modules/mob/living/carbon/xenomorph/update_icons.dm @@ -340,6 +340,8 @@ wound_icon_holder.icon_state = "[caste.caste_type]_walk_[health_threshold]" else wound_icon_holder.icon_state = handle_special_wound_states(health_threshold) + if(organ_removed) + wound_icon_holder.icon_state = "[caste.caste_type]_dissection" ///Used to display the xeno wounds/backpacks without rapidly switching overlays /atom/movable/vis_obj diff --git a/code/modules/organs/organ_objects.dm b/code/modules/organs/organ_objects.dm index d011933e4b2e..934a981e6f8f 100644 --- a/code/modules/organs/organ_objects.dm +++ b/code/modules/organs/organ_objects.dm @@ -114,6 +114,17 @@ organ_tag = "liver" organ_type = /datum/internal_organ/liver +/obj/item/organ/xeno + name = "acidic heart" + desc = "Acidic heart removed from a xenomorph. It spews droplets of acid every so often." + icon_state = "heart_t1" + organ_tag = "heart" + black_market_value = 60 + ///value of the organ in the recycler, heavily varies from size and tier + var/research_value = 1 //depending on the size and tier + ///the caste in a string, which is used in a xenoanalyzer + var/caste_origin // used for desc in xenoanalyzer + //These are here so they can be printed out via the fabricator. /obj/item/organ/heart/prosthetic name = "circulatory pump" diff --git a/code/modules/reagents/chemistry_machinery/xenomorph_analyzer.dm b/code/modules/reagents/chemistry_machinery/xenomorph_analyzer.dm new file mode 100644 index 000000000000..0f48f7aad046 --- /dev/null +++ b/code/modules/reagents/chemistry_machinery/xenomorph_analyzer.dm @@ -0,0 +1,164 @@ +/obj/structure/machinery/xenoanalyzer + name = "Biomass Analyzer" + desc = "Analyzer of biological material which processes valuable matter into even more valueble data." + density = TRUE + anchored = TRUE + icon = 'icons/obj/structures/machinery/science_machines_64x32.dmi' + icon_state = "xeno_analyzer_off" //for the time while no sprites + use_power = USE_POWER_NONE + wrenchable = FALSE + idle_power_usage = 40 + bound_x = 32 + var/biomass_points = 0 //most important thing in this + var/obj/item/organ/xeno/organ = null + var/busy = FALSE + var/caste_of_organ = null + +/obj/structure/machinery/xenoanalyzer/attack_hand(mob/user as mob) + if(!skillcheck(user, SKILL_RESEARCH, SKILL_RESEARCH_TRAINED)) + to_chat(user, SPAN_WARNING("You have no idea how to use this.")) + return + tgui_interact(user) + +/obj/structure/machinery/xenoanalyzer/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "XenomorphExtractor", name) + ui.open() + +/obj/structure/machinery/xenoanalyzer/attackby(obj/item/attacked_item, mob/user) + if(!skillcheck(user, SKILL_RESEARCH, SKILL_RESEARCH_TRAINED)) + to_chat(user, SPAN_WARNING("You have no idea how to use this.")) + return + if(istype(attacked_item, /obj/item/organ/xeno)) + if(organ) + to_chat(user, SPAN_WARNING("Organ slot is already full!")) + return + if(!do_after(user, 3 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC)) + to_chat(user, SPAN_WARNING("You were interupted!")) + return + if(!user.drop_inv_item_to_loc(attacked_item, src)) + return + to_chat(user, SPAN_NOTICE("You place the organ in the machine")) + organ = attacked_item + icon_state = "xeno_analyzer_organ_on" + caste_of_organ = organ.caste_origin + playsound(loc, 'sound/machines/fax.ogg', 15, 1) + if(istype(attacked_item, /obj/item/clothing/accessory/health/research_plate)) + var/obj/item/clothing/accessory/health/research_plate/plate = attacked_item + if(plate.recyclable_value == 0 && !plate.can_recycle(user)) + to_chat(user, SPAN_WARNING("You cannot recycle this type of plate")) + return + if(!do_after(user, 3 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC)) + to_chat(user, SPAN_WARNING("You were interupted!")) + return + to_chat(user, SPAN_NOTICE("You recycle [attacked_item]")) + biomass_points += plate.recyclable_value + qdel(attacked_item) + playsound(loc, 'sound/machines/fax.ogg', 15, 1) + +/obj/structure/machinery/xenoanalyzer/ui_data(mob/user) + var/list/data = list() + data["points"] = biomass_points + data["current_clearance"] = GLOB.chemical_data.clearance_level + data["is_x_level"] = GLOB.chemical_data.reached_x_access // why just why + + if(organ) + data["organ"] = TRUE + data["caste"] = caste_of_organ + data["value"] = organ.research_value + else + data["organ"] = FALSE + return data + +/obj/structure/machinery/xenoanalyzer/ui_static_data(mob/user) + var/list/static_data = list() + static_data["upgrades"] = list() + static_data["categories"] = list() + for(var/upgrade_type in subtypesof(/datum/research_upgrades)) + var/datum/research_upgrades/upgrade = upgrade_type + if(upgrade.behavior == RESEARCH_UPGRADE_CATEGORY) + static_data["categories"] += upgrade.name + continue + if(upgrade.behavior == RESEARCH_UPGRADE_EXCLUDE_BUY) + continue + static_data["upgrades"] += list(list( + "name" = capitalize_first_letters(upgrade.name), + "desc" = upgrade.desc, + "vari" = upgrade.behavior, + "cost" = upgrade.value_upgrade, + "ref" = upgrade.item_reference, + "category" = upgrade.upgrade_type, + "clearance" = upgrade.clearance_req, + )) + return static_data + +/obj/structure/machinery/xenoanalyzer/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + + switch(action) + if("eject_organ") + eject_biomass(usr) + . = TRUE + + if("process_organ") + if(!busy) + addtimer(CALLBACK(src, PROC_REF(process_organ)), 3 SECONDS) + icon_state = "xeno_analyzer_on_moving" + playsound(loc, 'sound/machines/blender.ogg', 25, TRUE) + QDEL_NULL(organ) + . = TRUE + busy = TRUE + if("produce") + if(!busy) + start_print_upgrade(text2path(params["ref"]), usr, text2num(params["vari"])) + playsound(src, 'sound/machines/keyboard2.ogg', 25, TRUE) + +/obj/structure/machinery/xenoanalyzer/proc/eject_biomass(mob/user) + if(busy) + to_chat(user, SPAN_WARNING("[src] is currently busy!")) + return + if(isnull(organ)) + return + icon_state = "xeno_analyzer_off" + organ.forceMove(get_turf(src)) + organ = null + +/obj/structure/machinery/xenoanalyzer/proc/process_organ() + biomass_points += organ.research_value + icon_state = "xeno_analyzer_off" + busy = FALSE + +/obj/structure/machinery/xenoanalyzer/proc/start_print_upgrade(produce_path, mob/user, variation) + if (stat & NOPOWER) + return + var/path_exists = FALSE + var/datum/research_upgrades/upgrade + for(var/datum_upgrades in subtypesof(/datum/research_upgrades)) + upgrade = datum_upgrades + if(upgrade.behavior == RESEARCH_UPGRADE_CATEGORY || upgrade.behavior == RESEARCH_UPGRADE_EXCLUDE_BUY) + continue + if(produce_path == upgrade.item_reference && upgrade.behavior == variation) + path_exists = TRUE + break + if(!path_exists) + to_chat(user, SPAN_WARNING("[src] makes a suspicious wail before powering down.")) + return + if(upgrade.value_upgrade > biomass_points) + to_chat(user, SPAN_WARNING("[src] makes a worrying beep and flashes red, theres not enough data processed to build the requested upgrade!")) + return + if((upgrade.clearance_req > GLOB.chemical_data.clearance_level && upgrade.clearance_req != 6) || (upgrade.clearance_req == 6 && !GLOB.chemical_data.reached_x_access)) + to_chat(user, SPAN_WARNING("[src] makes a annoying hum and flashes red - you don't have access to this upgrade!")) + return + icon_state = "xeno_analyzer_printing" + busy = TRUE + biomass_points -= upgrade.value_upgrade + addtimer(CALLBACK(src, PROC_REF(print_upgrade), produce_path, variation), 3 SECONDS) + +/obj/structure/machinery/xenoanalyzer/proc/print_upgrade(produce_path, variation) + busy = FALSE + icon_state = "xeno_analyzer_off" + new produce_path(get_turf(src), variation) + diff --git a/code/modules/surgery/surgery_initiator.dm b/code/modules/surgery/surgery_initiator.dm index 706b28d0e94e..b99a4250dd0d 100644 --- a/code/modules/surgery/surgery_initiator.dm +++ b/code/modules/surgery/surgery_initiator.dm @@ -7,7 +7,6 @@ /proc/initiate_surgery_moment(obj/item/tool, mob/living/carbon/target, obj/limb/affecting, mob/living/user) if(!tool && !(affecting.status & LIMB_UNCALIBRATED_PROSTHETIC)) return FALSE - var/target_zone = user.zone_selected var/list/available_surgeries = list() var/list/valid_steps = list() //Steps that could be performed, if we had the right tool. @@ -45,6 +44,7 @@ //Lying and self-surgery checks. if(surgeryloop.lying_required && target.body_position != LYING_DOWN) continue + if(!surgeryloop.self_operable && target == user) continue @@ -58,12 +58,16 @@ if(affecting.status & LIMB_DESTROYED) continue else - if(!(affecting.status & LIMB_DESTROYED)) - continue - if(affecting.parent && affecting.parent.status & LIMB_DESTROYED) - continue + if(ishuman(target))//otherwise breaks when trying to op xeno + if(!(affecting.status & LIMB_DESTROYED) && ishuman(target)) + continue + + if(affecting.parent && affecting.parent.status & LIMB_DESTROYED && ishuman(target)) + continue + if(surgeryloop.requires_bodypart_type && !(affecting.status & surgeryloop.requires_bodypart_type)) continue + else if(surgeryloop.requires_bodypart) //mob with no limb in surgery zone when we need a limb continue @@ -71,7 +75,6 @@ if(!surgeryloop.can_start(user, target, affecting, tool)) continue - //Tool checks. var/datum/surgery_step/current_step = GLOB.surgery_step_list[surgeryloop.steps[1]] @@ -84,9 +87,7 @@ continue else continue - available_surgeries[surgeryloop.name] = surgeryloop //Add it to the list. - if(!length(available_surgeries)) if(!tool) return FALSE @@ -96,15 +97,14 @@ to_chat(user, SPAN_WARNING("You can't perform surgery on the same \ [target_zone == "r_hand"||target_zone == "l_hand" ? "hand":"arm"] you're using!")) return FALSE - if(!length(valid_steps)) - var/limbname = affecting?.status & LIMB_DESTROYED ? "the stump of [target]'s [affecting.display_name]" : "[target]'s [parse_zone(target_zone)]" - if(target.incision_depths[target_zone] != SURGERY_DEPTH_SURFACE) - to_chat(user, SPAN_WARNING("You don't know of any operations you could perform in the [target.incision_depths[target_zone]] incision on [limbname].")) - else - to_chat(user, SPAN_WARNING("You don't know of any operations you could begin on [limbname].")) - return FALSE - + if(ishuman(target)) + var/limbname = affecting?.status & LIMB_DESTROYED ? "the stump of [target]'s [affecting.display_name]" : "[target]'s [parse_zone(target_zone)]" + if(target.incision_depths[target_zone] != SURGERY_DEPTH_SURFACE) + to_chat(user, SPAN_WARNING("You don't know of any operations you could perform in the [target.incision_depths[target_zone]] incision on [limbname].")) + else + to_chat(user, SPAN_WARNING("You don't know of any operations you could begin on [limbname].")) + return FALSE var/hint_msg for(var/datum/surgery_step/current_step as anything in valid_steps) if(hint_msg) @@ -159,7 +159,6 @@ return TRUE if(!surgeryinstance.can_start(user, target, affecting, tool)) return TRUE - var/datum/surgery/procedure = new surgeryinstance.type(target, target_zone, affecting) #ifdef DEBUG_SURGERY_INIT message_admins("[procedure.name] started.") diff --git a/code/modules/surgery/surgery_procedure.dm b/code/modules/surgery/surgery_procedure.dm index 8620c557eb4b..1ec72ae77673 100644 --- a/code/modules/surgery/surgery_procedure.dm +++ b/code/modules/surgery/surgery_procedure.dm @@ -73,6 +73,7 @@ if(!user.action_busy) //Otherwise, assume it's the same person. to_chat(user, SPAN_WARNING("Someone is already performing surgery on [target]'s [affected_limb.display_name]!")) return FALSE + return TRUE //So that you don't poke them with a tool you're already using. if(user.action_busy) @@ -93,7 +94,6 @@ if(lying_required && target.body_position != LYING_DOWN) to_chat(user, SPAN_WARNING("[user == target ? "You need" : "[target] needs"] to be lying down for this operation!")) return FALSE - if(user == target) if(!self_operable) to_chat(user, SPAN_WARNING("You can't perform this operation on yourself!")) @@ -102,7 +102,6 @@ to_chat(user, SPAN_WARNING("You can't perform surgery on the same \ [user.zone_selected == "r_hand"||user.zone_selected == "l_hand" ? "hand":"arm"] you're using!")) return FALSE - var/datum/surgery_step/current_step = GLOB.surgery_step_list[steps[status]] if(current_step) if(current_step.attempt_step(user, target, user.zone_selected, tool, src, repeating)) //First, try this step. diff --git a/code/modules/surgery/xeno.dm b/code/modules/surgery/xeno.dm new file mode 100644 index 000000000000..fd5377f5d46c --- /dev/null +++ b/code/modules/surgery/xeno.dm @@ -0,0 +1,219 @@ +//Research stuff to extract stuff from xenomorphs for goodies. In other words, to extract useful material that could be used to upgrade marines etc. + +/datum/surgery/xenomorph + name = "Experimental Harvesting Surgery" + invasiveness = list(SURGERY_DEPTH_SURFACE) + required_surgery_skill = SKILL_SURGERY_TRAINED + possible_locs = list("head") + target_mobtypes = list(/mob/living/carbon/xenomorph) + steps = list( + /datum/surgery_step/xenomorph/cut_exoskeleton, + /datum/surgery_step/xenomorph/open_exoskeleton, + /datum/surgery_step/xenomorph/severe_connections, + /datum/surgery_step/xenomorph/remove_organ, + ) + lying_required = FALSE + requires_bodypart_type = NONE + requires_bodypart = FALSE + +/datum/surgery/xenomorph/can_start(mob/user, mob/living/carbon/xenomorph/patient, obj/limb/L, obj/item/tool) + if(islarva(patient) || isfacehugger(patient)) + to_chat(user, SPAN_DANGER("This race is probably too small to have a mature organ worthy to extract...")) + return FALSE + if((patient.tier > 2 || isqueen(patient)) && !istype(tool, /obj/item/tool/surgery/scalpel/laser/advanced)) + to_chat(user, SPAN_DANGER("Chitin of this kind is too thick for an ordinary tool, you would need something special.")) + return FALSE + if(patient.stat == DEAD && !patient.organ_removed) + return TRUE + return FALSE + +/datum/surgery_step/xenomorph/cut_exoskeleton + name = "Cut Exoskeleton Carapace" + desc = "cut the carapace open" + tools = list( + /obj/item/tool/surgery/scalpel/laser/advanced = 1.5, + /obj/item/tool/surgery/circular_saw = SURGERY_TOOL_MULT_IDEAL, + /obj/item/weapon/twohanded/fireaxe = SURGERY_TOOL_MULT_SUBOPTIMAL, + /obj/item/weapon/sword/machete = SURGERY_TOOL_MULT_SUBOPTIMAL, + /obj/item/tool/hatchet = SURGERY_TOOL_MULT_SUBSTITUTE, + /obj/item/tool/kitchen/knife/butcher = SURGERY_TOOL_MULT_SUBSTITUTE, + /obj/item/attachable/bayonet = SURGERY_TOOL_MULT_BAD_SUBSTITUTE + ) + + time = 4 SECONDS + preop_sound = 'sound/handling/clothingrustle1.ogg' + success_sound = 'sound/handling/bandage.ogg' + failure_sound = 'sound/surgery/organ2.ogg' + +/datum/surgery_step/xenomorph/cut_exoskeleton/preop(mob/living/carbon/human/user, mob/living/carbon/xenomorph/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + if(tool_type == /obj/item/tool/surgery/circular_saw || tool_type == /obj/item/tool/surgery/scalpel/laser/advanced) + user.affected_message(target, + SPAN_NOTICE("You start to cut [target.caste_type] carapace apart using \the [tool], carefully, with barely any acid."), + SPAN_NOTICE("[user] starts to cut Your carapace apart using \the [tool], carefully, with barely any acid."), + SPAN_NOTICE("[user] starts to cut [target.caste_type] carapace. \the [tool], carefully, with barely any acid.")) + else + user.affected_message(target, + SPAN_NOTICE("You start to [pick("smash", "crack", "break")] [target.caste_type] carapace apart using \the [tool], Recklessly, with acid splashing on you!"), + SPAN_NOTICE("[user] starts to [pick("smash", "crack", "break")] Your carapace apart using \the [tool], Recklessly, with acid splashing all of the place!"), + SPAN_NOTICE("[user] starts to [pick("smash", "crack", "break")] [target.caste_type] carapace with \the [tool], Recklessly, with acid splashing them!")) + user.apply_damage(rand(25,50),BURN) + to_chat(user, SPAN_DANGER("You burn as acid gets on your skin!")) + //we dont really need log interact since we're working with dead body... I hope + +/datum/surgery_step/xenomorph/cut_exoskeleton/success(mob/living/carbon/human/user, mob/living/carbon/xenomorph/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + if(tool_type == /obj/item/tool/surgery/circular_saw) + user.affected_message(target, + SPAN_NOTICE("You succesfully cut through [target.caste_type] carapace apart using \the [tool]."), + SPAN_NOTICE("[user] Succesfully cuts through Your carapace. \the [tool]."), + SPAN_NOTICE("[user] Succesfully cuts [target.caste_type] carapace. \the [tool].")) + else + user.affected_message(target, + SPAN_NOTICE("You succesfully destroy [target.caste_type] carapace into bits and pieces apart using \the [tool]."), + SPAN_NOTICE("[user] succesfully destroys Your carapace into bits and pieces apart using \the [tool]."),, + SPAN_NOTICE("[user] Succesfully destroys [target.caste_type] carapace into bits and pieces apart using \the [tool].")) + +/datum/surgery_step/xenomorph/cut_exoskeleton/failure(mob/living/carbon/human/user, mob/living/carbon/xenomorph/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + if(tool_type == /obj/item/tool/surgery/circular_saw) + user.affected_message(target, + SPAN_WARNING("Your hand slips, failing to cut [target.caste_type] carapace apart using \the [tool]!"), + SPAN_WARNING("[user] hand slips, failing to cut Your carapace apart using \the [tool]!"), + SPAN_WARNING("[user] hand slips, failing to cut [target.caste_type] carapace using \the [tool]!")) + else + user.affected_message(target, + SPAN_WARNING("Your hand slips, failing to destroy [target.caste_type] carapace into bits and pieces apart using \the [tool]."), + SPAN_WARNING("[user] hand slips, failing to destroy Your carapace into bits and pieces using \the [tool]."), + SPAN_WARNING("[user] hand slips, failing to destroy [target.caste_type] carapace into bits and pieces using \the [tool].")) + return FALSE + +/datum/surgery_step/xenomorph/open_exoskeleton + name = "Pry exoskeleton open" + desc = "open the exoskeleton in the incision" + tools = SURGERY_TOOLS_PRY_ENCASED + time = 2 SECONDS + preop_sound = 'sound/surgery/retractor1.ogg' + success_sound = 'sound/surgery/retractor2.ogg' + failure_sound = 'sound/surgery/organ1.ogg' + +/datum/surgery_step/xenomorph/open_exoskeleton/preop(mob/living/carbon/human/user, mob/living/carbon/xenomorph/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + user.affected_message(target, + SPAN_NOTICE("You start to pry [target.caste_type] carapace open using \the [tool]"), + SPAN_NOTICE("[user] starts to pry Your carapace open with \the [tool] very carefully"), + SPAN_NOTICE("[user] starts to pry [target.caste_type] carapace open with \the [tool] very carefully")) + +/datum/surgery_step/xenomorph/open_exoskeleton/success(mob/living/carbon/human/user, mob/living/carbon/xenomorph/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + if(tool_type == /obj/item/tool/surgery/retractor) + user.affected_message(target, + SPAN_NOTICE("You hold [target.caste_type] carapace and exoskeleton open using \the [tool], exposing [target.caste_type] vital organs"), + SPAN_NOTICE("[user] Holds Your carapace and exoskeleton open with \the [tool], exposing [target.caste_type] vital organs "), + SPAN_NOTICE("[user] Holds [target.caste_type] carapace and exoskeleton open with \the [tool], exposing [target.caste_type] vital organs ")) + else + user.affected_message(target, + SPAN_NOTICE("You Hold [target.caste_type] carapace open using \the [tool] like a medieval doctor, exposing [target.caste_type] vital organs"), + SPAN_NOTICE("[user] starts to open Your carapace with \the [tool] very carefully"), + SPAN_NOTICE("[user] starts to open [target.caste_type] carapace with \the [tool] very carefully")) + +/datum/surgery_step/xenomorph/open_exoskeleton/failure(mob/living/carbon/human/user, mob/living/carbon/xenomorph/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + user.affected_message(target, + SPAN_WARNING("Your hand slips, letting go of [target.caste_type] carapace and exoskeleton, slaming it back into place and splashing acid everywhere!"), + SPAN_WARNING("[user] hand slips, letting go of [target.caste_type] carapace and exoskeleton, slaming it back into place and splashing acid everywhere!"), + SPAN_WARNING("[user] hand slips, letting go of [target.caste_type] carapace and exoskeleton, slaming it back into place and splashing acid everywhere!")) + user.apply_damage(rand(15, 45), BURN) + return FALSE + +/datum/surgery_step/xenomorph/severe_connections + name = "Severe organ connections" + desc = "detach tubes and connections from organ" + tools = list( + /obj/item/tool/surgery/scalpel = SURGERY_TOOL_MULT_IDEAL, + /obj/item/tool/surgery/scalpel/pict_system = SURGERY_TOOL_MULT_IDEAL, + /obj/item/attachable/bayonet = SURGERY_TOOL_MULT_SUBSTITUTE, + /obj/item/tool/kitchen/knife = SURGERY_TOOL_MULT_SUBSTITUTE, + /obj/item/shard = SURGERY_TOOL_MULT_AWFUL, + ) + time = 4 SECONDS + preop_sound = 'sound/surgery/scalpel1.ogg' + success_sound = 'sound/surgery/scalpel2.ogg' + failure_sound = 'sound/surgery/organ2.ogg' + +/datum/surgery_step/xenomorph/severe_connections/preop(mob/living/carbon/human/user, mob/living/carbon/xenomorph/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + user.affected_message(target, + SPAN_NOTICE("You start to severe [target.caste_type] organ links using \the [tool], with confidence"), + SPAN_NOTICE("[user] start to severe Your organ links using \the [tool], with confidence"), + SPAN_NOTICE("[user] starts to severe [target.caste_type] organ links using \the [tool], with confidence")) + +/datum/surgery_step/xenomorph/severe_connections/success(mob/living/carbon/human/user, mob/living/carbon/xenomorph/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + if(tool_type == /obj/item/tool/surgery/retractor) + user.affected_message(target, + SPAN_NOTICE("You severed [target.caste_type] connections and links to vital organs using \the [tool]"), + SPAN_NOTICE("[user] severed Your connections and links to vital organs using \the [tool]"), + SPAN_NOTICE("[user] severed [target.caste_type] connections and links to vital organs using \the [tool]")) + else + user.affected_message(target, + SPAN_NOTICE("You rip [target.caste_type] connections and links to vital organs apart using \the [tool]"), + SPAN_NOTICE("[user] rips Your connections and links to vital organs apart using \the [tool]"), + SPAN_NOTICE("[user] rips [target.caste_type] connections and links to vital organs apart using \the [tool]")) + +/datum/surgery_step/xenomorph/severe_connections/failure(mob/living/carbon/human/user, mob/living/carbon/xenomorph/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + user.affected_message(target, + SPAN_WARNING("Your hand slips, damaging one of [target.caste_type] [pick("arteries", "viens")], gushing acid blood everywhere!"), + SPAN_WARNING("[user] hand slips, damaging one of Your [pick("arteries", "viens")], gushing acid blood everywhere!"), + SPAN_WARNING("[user] hand slips, damaging one of [target.caste_type] [pick("arteries", "viens")], gushing acid blood everywhere!")) + user.apply_damage(rand(15, 45), BURN) + return FALSE + +/datum/surgery_step/xenomorph/remove_organ + name = "Take out the organ" + desc = "grab a hold of it and pull the organ out" + accept_hand = TRUE + tools = list( + /obj/item/tool/surgery/hemostat = 1.5, + /obj/item/tool/wirecutters = SURGERY_TOOL_MULT_SUBOPTIMAL, + /obj/item/tool/kitchen/utensil/fork = SURGERY_TOOL_MULT_SUBSTITUTE + )//shamelessly taken from embryo code + time = 6 SECONDS + preop_sound = 'sound/surgery/scalpel1.ogg' + success_sound = 'sound/surgery/scalpel2.ogg' + failure_sound = 'sound/surgery/organ2.ogg' + +/datum/surgery_step/xenomorph/remove_organ/preop(mob/living/carbon/human/user, mob/living/carbon/xenomorph/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + if(tool) + user.affected_message(target, + SPAN_NOTICE("You start to get a firm grip on the [target.caste_type] organ using \the [tool] "), + SPAN_NOTICE("[user] start to get a firm grip on your insides using \the [tool]"), + SPAN_NOTICE("[user] starts to get a firm grip on the [target.caste_type] organ using \the [tool] ")) + else + user.affected_message(target, + SPAN_NOTICE("You start to get a firm grip on the [target.caste_type] organ"), + SPAN_NOTICE("[user] start to get a firm grip on your insides"), + SPAN_NOTICE("[user] starts to get a firm grip on the [target.caste_type] organ")) + +/datum/surgery_step/xenomorph/remove_organ/success(mob/living/carbon/human/user, mob/living/carbon/xenomorph/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + if(tool) + user.affected_message(target, + SPAN_NOTICE("You pulled the [target.caste_type] organ out using \the [tool]"), + SPAN_NOTICE("[user] pulled Your organ out using \the [tool]"), + SPAN_NOTICE("[user] pulled the [target.caste_type] organ out using \the [tool]")) + else + user.affected_message(target, + SPAN_NOTICE("You burn your hands as you pulled the [target.caste_type] organ out!"), + SPAN_NOTICE("[user] burns their hands as they pulled Your insides out!"), + SPAN_NOTICE("[user] burns their hands as they pulled the [target.caste_type] organ out")) + user.emote("pain") + if(user.hand) + user.apply_damage(15, BURN, "l_hand") + else + user.apply_damage(15, BURN, "r_hand") + var/obj/item/organ/xeno/organ = locate() in target + if(!isnull(organ)) + organ.forceMove(target.loc) + target.organ_removed = TRUE + target.update_wounds() + +/datum/surgery_step/xenomorph/remove_organ/failure(mob/living/carbon/human/user, mob/living/carbon/xenomorph/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + if(tool) + user.affected_message(target, + SPAN_NOTICE("You fail to pull the [target.caste_type] organ out using \the [tool]"), + SPAN_NOTICE("[user] fails to pull Your organ out using \the [tool]"), + SPAN_NOTICE("[user] fails to pull the [target.caste_type] organ out using \the [tool]")) + return FALSE + diff --git a/colonialmarines.dme b/colonialmarines.dme index 5b4be362fbd8..d1d758b08e48 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -357,6 +357,7 @@ #include "code\datums\mutable_appearance.dm" #include "code\datums\quadtree.dm" #include "code\datums\recipe.dm" +#include "code\datums\research_upgrade_datum.dm" #include "code\datums\shuttles.dm" #include "code\datums\soundOutput.dm" #include "code\datums\tgs_event_handler.dm" @@ -1088,10 +1089,10 @@ #include "code\game\objects\items\legcuffs.dm" #include "code\game\objects\items\lightstick.dm" #include "code\game\objects\items\misc.dm" -#include "code\game\objects\items\old_research.dm" #include "code\game\objects\items\ore.dm" #include "code\game\objects\items\paint.dm" #include "code\game\objects\items\pamphlets.dm" +#include "code\game\objects\items\research_upgrades.dm" #include "code\game\objects\items\shards.dm" #include "code\game\objects\items\stock_parts.dm" #include "code\game\objects\items\trash.dm" @@ -2267,6 +2268,7 @@ #include "code\modules\reagents\chemistry_machinery\pandemic.dm" #include "code\modules\reagents\chemistry_machinery\reagent_analyzer.dm" #include "code\modules\reagents\chemistry_machinery\reagent_grinder.dm" +#include "code\modules\reagents\chemistry_machinery\xenomorph_analyzer.dm" #include "code\modules\reagents\chemistry_properties\chem_property.dm" #include "code\modules\reagents\chemistry_properties\prop_negative.dm" #include "code\modules\reagents\chemistry_properties\prop_neutral.dm" @@ -2339,6 +2341,7 @@ #include "code\modules\surgery\surgery_steps.dm" #include "code\modules\surgery\surgery_toggle.dm" #include "code\modules\surgery\tendwounds.dm" +#include "code\modules\surgery\xeno.dm" #include "code\modules\teleporters\teleporter.dm" #include "code\modules\teleporters\teleporter_admin_verbs.dm" #include "code\modules\teleporters\teleporter_console.dm" diff --git a/icons/mob/xenos/wounds.dmi b/icons/mob/xenos/wounds.dmi index 730e367f43ae..1b8ca0cebdd5 100644 Binary files a/icons/mob/xenos/wounds.dmi and b/icons/mob/xenos/wounds.dmi differ diff --git a/icons/obj/items/items.dmi b/icons/obj/items/items.dmi index c4d34d3b790c..81a0e526f1b7 100644 Binary files a/icons/obj/items/items.dmi and b/icons/obj/items/items.dmi differ diff --git a/icons/obj/items/organs.dmi b/icons/obj/items/organs.dmi index 06bf5e302f45..0cbe238f7522 100644 Binary files a/icons/obj/items/organs.dmi and b/icons/obj/items/organs.dmi differ diff --git a/icons/obj/structures/machinery/science_machines_64x32.dmi b/icons/obj/structures/machinery/science_machines_64x32.dmi index 8defd1917720..5d76a47e596c 100644 Binary files a/icons/obj/structures/machinery/science_machines_64x32.dmi and b/icons/obj/structures/machinery/science_machines_64x32.dmi differ diff --git a/maps/map_files/BigRed/BigRed.dmm b/maps/map_files/BigRed/BigRed.dmm index 422a143de94a..82871ec53f85 100644 --- a/maps/map_files/BigRed/BigRed.dmm +++ b/maps/map_files/BigRed/BigRed.dmm @@ -4912,7 +4912,7 @@ /area/bigredv2/caves/lambda/xenobiology) "aoJ" = ( /obj/structure/surface/table/reinforced, -/obj/item/XenoBio/Resin, +/obj/item/oldresearch/Resin, /turf/open/floor{ dir = 4; icon_state = "whitepurple" @@ -13936,8 +13936,8 @@ /area/bigredv2/caves/eta/research) "aPg" = ( /obj/structure/surface/table, -/obj/item/XenoBio/Blood, -/obj/item/XenoBio/Blood, +/obj/item/oldresearch/Blood, +/obj/item/oldresearch/Blood, /obj/item/paper, /turf/open/floor{ icon_state = "darkredcorners2" @@ -25124,8 +25124,8 @@ /area/bigredv2/caves/eta/xenobiology) "bCg" = ( /obj/structure/surface/table, -/obj/item/XenoBio/Blood, -/obj/item/XenoBio/Blood, +/obj/item/oldresearch/Blood, +/obj/item/oldresearch/Blood, /obj/item/tool/pen, /turf/open/floor{ dir = 4; @@ -38493,7 +38493,7 @@ name = "trophy board"; pixel_y = 30 }, -/obj/item/XenoBio/Chitin{ +/obj/item/oldresearch/Chitin{ anchored = 1; pixel_y = 27 }, diff --git a/maps/map_files/CORSAT/Corsat.dmm b/maps/map_files/CORSAT/Corsat.dmm index 28db8fa8831f..01777db10275 100644 --- a/maps/map_files/CORSAT/Corsat.dmm +++ b/maps/map_files/CORSAT/Corsat.dmm @@ -27814,7 +27814,6 @@ name = "Secure Racks"; req_access_txt = "103" }, -/obj/item/XenoItem/AntiAcid, /turf/open/floor/corsat{ icon_state = "purplewhite" }, @@ -27833,21 +27832,6 @@ icon_state = "retrosquareslight" }, /area/corsat/gamma/medbay) -"bAt" = ( -/obj/structure/surface/rack, -/obj/structure/window/reinforced/toughened{ - dir = 8 - }, -/obj/structure/machinery/door/window/eastright{ - dir = 1; - name = "Secure Racks"; - req_access_txt = "103" - }, -/obj/item/XenoItem/ResinPaste, -/turf/open/floor/corsat{ - icon_state = "purplewhite" - }, -/area/corsat/omega/complex) "bAu" = ( /obj/structure/machinery/vending/snack, /turf/open/floor/corsat{ @@ -27882,7 +27866,7 @@ /area/corsat/omega/complex) "bAy" = ( /obj/structure/surface/rack, -/obj/item/XenoBio/Resin, +/obj/item/oldresearch/Resin, /obj/structure/window/reinforced/toughened{ dir = 8 }, @@ -28360,7 +28344,7 @@ name = "Secure Racks"; req_access_txt = "103" }, -/obj/item/XenoBio/Blood, +/obj/item/oldresearch/Blood, /turf/open/floor/corsat{ dir = 1; icon_state = "purplewhite" @@ -28374,7 +28358,7 @@ /area/corsat/omega/complex) "bBJ" = ( /obj/structure/surface/rack, -/obj/item/XenoBio/Chitin, +/obj/item/oldresearch/Chitin, /obj/structure/window/reinforced/toughened{ dir = 8 }, @@ -76237,7 +76221,7 @@ crG aoc bBH bCv -bAt +bAq aoE bBO bUn diff --git a/maps/map_files/DesertDam/Desert_Dam.dmm b/maps/map_files/DesertDam/Desert_Dam.dmm index 3c4125023686..0c33d3d251f8 100644 --- a/maps/map_files/DesertDam/Desert_Dam.dmm +++ b/maps/map_files/DesertDam/Desert_Dam.dmm @@ -3589,7 +3589,7 @@ "akX" = ( /obj/structure/surface/table/reinforced, /obj/item/tool/pen, -/obj/item/XenoBio/Blood, +/obj/item/oldresearch/Blood, /turf/open/floor/prison{ dir = 8; icon_state = "darkpurple2" diff --git a/maps/map_files/DesertDam/sprinkles/10.damtemple_intact.dmm b/maps/map_files/DesertDam/sprinkles/10.damtemple_intact.dmm index 6c7e859826db..53aaaee59201 100644 --- a/maps/map_files/DesertDam/sprinkles/10.damtemple_intact.dmm +++ b/maps/map_files/DesertDam/sprinkles/10.damtemple_intact.dmm @@ -313,12 +313,6 @@ /obj/structure/surface/table/reinforced/prison{ color = "#6b675e" }, -/obj/item/XenoItem/AntiAcid{ - pixel_x = -6 - }, -/obj/item/XenoItem/AntiAcid{ - pixel_x = 4 - }, /turf/open/floor/strata{ color = "#5e5d5d"; icon_state = "multi_tiles" diff --git a/maps/map_files/LV624/maintemple/1.intact.dmm b/maps/map_files/LV624/maintemple/1.intact.dmm index ea69a6c4c787..16dc3740a77d 100644 --- a/maps/map_files/LV624/maintemple/1.intact.dmm +++ b/maps/map_files/LV624/maintemple/1.intact.dmm @@ -1468,12 +1468,6 @@ /obj/structure/surface/table/reinforced/prison{ color = "#6b675e" }, -/obj/item/XenoItem/AntiAcid{ - pixel_x = -6 - }, -/obj/item/XenoItem/AntiAcid{ - pixel_x = 4 - }, /obj/effect/landmark/objective_landmark/close, /turf/open/floor/sandstone/runed, /area/lv624/ground/caves/sand_temple) diff --git a/maps/map_files/USS_Almayer/USS_Almayer.dmm b/maps/map_files/USS_Almayer/USS_Almayer.dmm index 6640691f2ebc..e2f13ca86394 100644 --- a/maps/map_files/USS_Almayer/USS_Almayer.dmm +++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm @@ -17830,6 +17830,19 @@ icon_state = "test_floor4" }, /area/almayer/hallways/upper/starboard) +"chc" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "E"; + pixel_x = 1 + }, +/obj/structure/machinery/body_scanconsole{ + dir = 8 + }, +/turf/open/floor/almayer{ + dir = 4; + icon_state = "sterile_green_side" + }, +/area/almayer/medical/medical_science) "chf" = ( /obj/structure/window/reinforced{ dir = 4; @@ -25572,7 +25585,7 @@ }, /area/almayer/maint/hull/lower/l_m_p) "eBO" = ( -/obj/structure/bed, +/obj/structure/machinery/medical_pod/bodyscanner, /turf/open/floor/almayer{ icon_state = "mono" }, @@ -45639,8 +45652,8 @@ }, /area/almayer/maint/upper/u_m_s) "lzA" = ( -/obj/structure/machinery/sleep_console{ - dir = 8 +/obj/structure/bed/chair/comfy{ + dir = 5 }, /turf/open/floor/almayer{ icon_state = "mono" @@ -49969,11 +49982,13 @@ }, /area/almayer/living/briefing) "naR" = ( -/obj/structure/machinery/iv_drip, /obj/effect/decal/warning_stripes{ icon_state = "E"; pixel_x = 1 }, +/obj/structure/machinery/sleep_console{ + dir = 8 + }, /turf/open/floor/almayer{ dir = 4; icon_state = "sterile_green_corner" @@ -58369,10 +58384,10 @@ }, /area/almayer/living/offices) "pRn" = ( -/obj/structure/bed, /obj/structure/machinery/power/apc/almayer{ dir = 4 }, +/obj/structure/machinery/medical_pod/sleeper, /turf/open/floor/almayer{ icon_state = "mono" }, @@ -80130,9 +80145,6 @@ }, /area/almayer/squads/req) "wWR" = ( -/obj/structure/machinery/medical_pod/bodyscanner{ - dir = 8 - }, /obj/structure/machinery/status_display{ pixel_y = 30 }, @@ -81090,10 +81102,6 @@ /turf/open/floor/plating/plating_catwalk, /area/almayer/maint/upper/u_m_s) "xqp" = ( -/obj/structure/machinery/body_scanconsole{ - dir = 8; - layer = 3.1 - }, /obj/structure/disposalpipe/trunk{ dir = 1 }, @@ -81104,6 +81112,7 @@ name = "Requisitions Delivery Unit"; pixel_y = 28 }, +/obj/structure/machinery/xenoanalyzer, /turf/open/floor/almayer{ icon_state = "mono" }, @@ -83359,14 +83368,6 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/squads/delta) -"ycj" = ( -/obj/structure/machinery/medical_pod/sleeper{ - dir = 8 - }, -/turf/open/floor/almayer{ - icon_state = "mono" - }, -/area/almayer/medical/medical_science) "ycl" = ( /turf/open/floor/plating, /area/almayer/maint/hull/lower/l_m_s) @@ -115394,7 +115395,7 @@ wPz jeq rQy wWR -ycj +vti vkp cfT hec @@ -115601,7 +115602,7 @@ vdO vkp aoM kBo -kBP +chc naR vOy hrn diff --git a/maps/predship/huntership.dmm b/maps/predship/huntership.dmm index 433d9057dc70..8a2019b55d76 100644 --- a/maps/predship/huntership.dmm +++ b/maps/predship/huntership.dmm @@ -840,8 +840,6 @@ /obj/structure/surface/table/reinforced/prison{ color = "#6b675e" }, -/obj/item/XenoItem/ChitinPlate, -/obj/item/XenoItem/ChitinPlate, /obj/item/stack/sheet/xenochitin, /obj/item/stack/sheet/xenochitin, /turf/open/floor/corsat{ @@ -1744,18 +1742,6 @@ icon_state = "cult" }, /area/yautja) -"fB" = ( -/obj/structure/surface/table/reinforced/prison{ - color = "#6b675e" - }, -/obj/item/XenoItem/AntiAcid, -/obj/item/XenoItem/AntiAcid, -/obj/item/XenoItem/AntiAcid, -/turf/open/floor/corsat{ - dir = 1; - icon_state = "squareswood" - }, -/area/yautja) "fF" = ( /obj/structure/surface/rack{ color = "#6b675e"; @@ -4840,7 +4826,7 @@ bj cP cP bj -fB +ZM bL bL bL diff --git a/maps/predship/regular.dmm b/maps/predship/regular.dmm index 984bd4e7c65a..b155d3f8ae84 100644 --- a/maps/predship/regular.dmm +++ b/maps/predship/regular.dmm @@ -1177,16 +1177,8 @@ /area/yautja) "dp" = ( /obj/structure/surface/table/reinforced, -/obj/item/XenoBio/Blood, -/obj/item/XenoBio/Blood, -/turf/open/floor/holofloor{ - dir = 2; - icon_state = "cult" - }, -/area/yautja) -"dq" = ( -/obj/structure/surface/table/reinforced, -/obj/item/XenoItem, +/obj/item/oldresearch/Blood, +/obj/item/oldresearch/Blood, /turf/open/floor/holofloor{ dir = 2; icon_state = "cult" @@ -1202,8 +1194,8 @@ /area/yautja) "dz" = ( /obj/structure/surface/table/reinforced, -/obj/item/XenoBio/Resin, -/obj/item/XenoBio/Resin, +/obj/item/oldresearch/Resin, +/obj/item/oldresearch/Resin, /turf/open/floor/holofloor{ dir = 2; icon_state = "cult" @@ -3112,7 +3104,7 @@ dd Zv Zv ZI -dq +cv cu Zv Zv diff --git a/tgui/packages/tgui/interfaces/XenomorphExtractor.jsx b/tgui/packages/tgui/interfaces/XenomorphExtractor.jsx new file mode 100644 index 000000000000..f29a1a0f1875 --- /dev/null +++ b/tgui/packages/tgui/interfaces/XenomorphExtractor.jsx @@ -0,0 +1,124 @@ +import { useBackend, useLocalState } from '../backend'; +import { Section, Button, Stack, NoticeBox, LabeledList, Flex, Box, Dropdown, Divider } from '../components'; +import { Window } from '../layouts'; + +export const XenomorphExtractor = (_props, context) => { + const { act, data } = useBackend(context); + + const { + organ, + points, + upgrades, + caste, + value, + categories, + current_clearance, + is_x_level, + } = data; + const dropdownOptions = categories; + const [selectedTab, setSelectedTab] = useLocalState('category', 'NONE'); + + return ( + + +
+ + +
+
+ {!organ ? ( + + Recepticle is empty, analyzing is impossible! + + ) : ( + Biomass accepted. Ready to analyze. + )} +
+ +
Select Technology to print.}> + + setSelectedTab(value)} + /> + + + + + {selectedTab !== 'NONE' && ( + + {upgrades.map((upgrades) => + upgrades.category === selectedTab ? ( + + {upgrades.name} + + } + buttons={ + +
+
+
+ ); +};