diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index b195328264cd..3da1aa8d24c0 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..1620543f6604 --- /dev/null +++ b/code/datums/research_upgrade_datum.dm @@ -0,0 +1,171 @@ +/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? This is also what gets passed to the initizialize of an item, this can be any number *but* it cannot be -1 or -2, as it messes with the buy menu. + var/behavior = RESEARCH_UPGRADE_EXCLUDE_BUY // should this be on the list? + /// the price of the upgrade, refer to this: 500 is a runner, 8k is queen. T3 is usually 3k, woyer is 2k. + 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 + ///The change of price for item per purchase, recommended for mass producing stuff or limited upgrade. + var/change_purchase = 0 + ///the minimum price which we cant go any cheaper usually dont need to set this if change price is 0 or positive + var/minimum_price = 0 + ///the maximum price which we cant go any more expensive, usually dont need to set this if change price is 0 or negative + var/maximum_price = INFINITY + +/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 = 200 + 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 = 2000 + 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 = 1500 + 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 = 4000 + 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 = 500 + item_reference = /obj/item/research_upgrades/sleeper + upgrade_type = ITEM_MACHINERY_UPGRADE + clearance_req = 1 + +/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 8 or 9 points." + value_upgrade = 2000 + item_reference = /obj/item/research_upgrades/credits + behavior = RESEARCH_UPGRADE_TIER_1 + upgrade_type = ITEM_ACCESSORY_UPGRADE + change_purchase = 500 + maximum_price = 5000 + clearance_req = 5 + +/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/item/incision_management + name = "Incision Management System" + desc = "A true extension of the surgeon's body, this marvel instantly and completely prepares an incision, allowing for the immediate commencement of therapeutic steps." + value_upgrade = 3000 + item_reference = /obj/item/tool/surgery/scalpel/manager + behavior = RESEARCH_UPGRADE_TIER_1 + upgrade_type = ITEM_ACCESSORY_UPGRADE + clearance_req = 4 +/datum/research_upgrades/item/nanosplints + name = "Reinforced Fiber Splints" + desc = "A set of splints made from durable carbon fiber sheets reinforced with flexible titanium lattice, comes in a stack of five." + value_upgrade = 800 + clearance_req = 3 + change_purchase = -200 + minimum_price = 200 + item_reference = /obj/item/stack/medical/splint/nano/research + behavior = RESEARCH_UPGRADE_TIER_5 //adjust this to change amount of nanosplints in a stack, cant be higher than five, go change max_amount in the nanosplint itself, then change it. + upgrade_type = ITEM_ACCESSORY_UPGRADE + +/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 = 6 + 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 = 1200 + behavior = RESEARCH_UPGRADE_TIER_1 + clearance_req = 2 + change_purchase = -200 + minimum_price = 200 + 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 and a hefty chemical tank. Attached to a uniform and on a simultaneous press, it injects an 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 = 250 + clearance_req = 1 + behavior = RESEARCH_UPGRADE_TIER_1 + change_purchase = -100 + minimum_price = 100 + upgrade_type = ITEM_ARMOR_UPGRADE + item_reference = /obj/item/clothing/accessory/health/research_plate/emergency_injector + +/datum/research_upgrades/armor/ceramic + name = "Ceramic Armor Plate" + desc = "A strong trauma plate, able to protect the user from a large amount of bullets. Completely useless against sharp objects." + value_upgrade = 500 + clearance_req = 4 + behavior = RESEARCH_UPGRADE_TIER_1 + upgrade_type = ITEM_ARMOR_UPGRADE + change_purchase = -50 + minimum_price = 200 + item_reference = /obj/item/clothing/accessory/health/ceramic_plate + +/datum/research_upgrades/armor/preservation + name = "Death Preservation Plate" + desc = "preservation plate which activates once the user is dead, uses variety of different substances and sensors to slow down the decay and increase the time before the user is permanently dead, due to small tank of preservatives, it needs to be replaced on each death. Extends time to permadeath by around four minutes." + value_upgrade = 500 + clearance_req = 4 + behavior = RESEARCH_UPGRADE_TIER_1 + upgrade_type = ITEM_ARMOR_UPGRADE + change_purchase = -100 + minimum_price = 100 + item_reference = /obj/item/clothing/accessory/health/research_plate/anti_decay + diff --git a/code/game/machinery/computer/research.dm b/code/game/machinery/computer/research.dm index 3a8292ec7d07..b51da245844e 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 [cred.credit_value] 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..937afa0cdb4d 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,22 +394,40 @@ 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) for(var/datum/wound/W in S.limb_ref.wounds) if(!surgery) break if(W.internal) - sleep(FIXVEIN_MAX_DURATION*surgery_mod) + sleep(FIXVEIN_MIN_DURATION-30) S.limb_ref.wounds -= W S.limb_ref.remove_all_bleeding(FALSE, TRUE) qdel(W) @@ -415,15 +435,15 @@ 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) - sleep(BONEGEL_REPAIR_MAX_DURATION*surgery_mod) - sleep(BONESETTER_MAX_DURATION*surgery_mod) + sleep(BONEGEL_REPAIR_MAX_DURATION*surgery_mod+20) if(S.limb_ref.brute_dam > 20) sleep(((S.limb_ref.brute_dam - 20)/2)*surgery_mod) if(!surgery) break @@ -437,10 +457,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 +540,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 +612,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 +653,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 +736,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 +759,7 @@ if("open") surgeryqueue["open"] = 1 dat += "Close Open Incisions" + dat += "
" dat += "
Begin Surgery - Refresh Menu - Clear Queue
" @@ -743,6 +783,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 +853,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 dbc6d8133de3..34da9a8128f0 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..2cfbe0ebebf8 --- /dev/null +++ b/code/game/objects/items/research_upgrades.dm @@ -0,0 +1,72 @@ +//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' + w_class = SIZE_TINY + 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 an AutoDoc. The technology on this disk is used [get_upgrade_text()]. Insert it in an 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 a sleeper system. The technology on this disk is used on a sleeper to allow a wider spectrum of chemicals to be administered." + + +/obj/item/research_upgrades/credits + name = "Research Market (Credits)" + var/credit_value = 8 + +/obj/item/research_upgrades/credits/Initialize(mapload, ...) + . = ..() + credit_value = rand(8, 9) + desc = "Research disk containing all the bits of data the analyzer could salvage, insert this into a 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 bbc9c3bd8984..64c6989b4e81 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,11 +137,11 @@ 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) - to_chat(user, SPAN_NOTICE("You use the shards of armor to cobble together an improvised trauma plate.")) + to_chat(user, SPAN_NOTICE("You use the shards of armor to cobble together an improvised ceramic plate.")) qdel(I) qdel(src) user.put_in_active_hand(new /obj/item/clothing/accessory/health/scrap()) @@ -165,6 +168,9 @@ return ..() +/obj/item/clothing/accessory/health/ceramic_plate/take_slash_damage(mob/living/user, list/slashdata) + return + /obj/item/clothing/accessory/health/scrap name = "scrap metal" desc = "A weak armor plate, only able to protect from a little bit of damage. Perhaps that will be enough." @@ -184,3 +190,265 @@ . = ..() if(. && !armor_health) qdel(src) + +/obj/item/clothing/accessory/health/scrap/take_bullet_damage(mob/living/user, damage, ammo_flags) + if(ammo_flags & AMMO_ACIDIC) + return + + return ..() + +/obj/item/clothing/accessory/health/scrap/take_slash_damage(mob/living/user, list/slashdata) + return + +/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 [src] 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 = 100 + +/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 = "plate_research" + 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 + +/obj/item/clothing/accessory/health/research_plate/anti_decay + name = "experimental preservation plate" + desc = "preservation plate which activates once the user is dead, uses variety of different substances and sensors to slow down the decay and increase the time before the user is permanently dead, due to small tank of preservatives, it needs to be replaced on each death." + var/mob/living/carbon/human/wearer + var/used = FALSE + + +/obj/item/clothing/accessory/health/research_plate/anti_decay/Destroy() + . = ..() + wearer = null + +/obj/item/clothing/accessory/health/research_plate/anti_decay/get_examine_text(mob/user) + . = ..() + if(used) + . += SPAN_WARNING("It is used!") + +/obj/item/clothing/accessory/health/research_plate/anti_decay/on_attached(obj/item/clothing/S, mob/living/carbon/human/user) + . = ..() + wearer = user + if(!used) + RegisterSignal(user, COMSIG_MOB_DEATH, PROC_REF(begin_preserving)) + user.revive_grace_period += 4 MINUTES + +/obj/item/clothing/accessory/health/research_plate/anti_decay/on_removed(mob/living/user, obj/item/clothing/C) + . = ..() + wearer = null + attached_uni = null + +/obj/item/clothing/accessory/health/research_plate/anti_decay/on_removed_sig(mob/living/user, slot) + . = ..() + if(. == FALSE) + return + wearer = null + attached_uni = null + +/obj/item/clothing/accessory/health/research_plate/anti_decay/proc/begin_preserving() + SIGNAL_HANDLER + UnregisterSignal(wearer, COMSIG_MOB_DEATH) + to_chat(wearer, SPAN_NOTICE("The [src] detects your death and starts injecting various chemicals to slow down your final demise!")) + RegisterSignal(wearer, COMSIG_HUMAN_REVIVED, PROC_REF(onetime_use)) + used = TRUE + +/obj/item/clothing/accessory/health/research_plate/anti_decay/proc/onetime_use() + SIGNAL_HANDLER + UnregisterSignal(wearer, COMSIG_HUMAN_REVIVED) + to_chat(wearer, SPAN_NOTICE("[icon2html(src, viewers(src))] \The [src] beeps: Chemical preservatives reserves depleted, replace the [src]")) + wearer.revive_grace_period = 5 MINUTES + + + + + + + diff --git a/code/modules/cm_tech/implements/medical_czsp.dm b/code/modules/cm_tech/implements/medical_czsp.dm index 30eda5b8af29..9ec56d35fbb5 100644 --- a/code/modules/cm_tech/implements/medical_czsp.dm +++ b/code/modules/cm_tech/implements/medical_czsp.dm @@ -80,6 +80,9 @@ stack_id = "nano splint" +/obj/item/stack/medical/splint/nano/research + desc = "Advanced technology allows these splints to hold bones in place while being flexible and damage-resistant. Those are made from durable carbon fiber and dont look cheap, better use them sparingly." + /obj/item/device/defibrillator/upgraded name = "upgraded emergency defibrillator" icon_state = "adv_defib" diff --git a/code/modules/mob/living/carbon/xenomorph/Evolution.dm b/code/modules/mob/living/carbon/xenomorph/Evolution.dm index cd402e2d6fbb..e0f0844bfa13 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 d33adcbce714..2cbb2af2ce86 100644 --- a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm +++ b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm @@ -248,6 +248,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 + ////////////////////////////////////////////////////////////////// // @@ -262,6 +267,7 @@ // an easily modularizable way. So, here you go. // ////////////////////////////////////////////////////////////////// + var/tunnel = FALSE /// for check on lurker invisibility var/stealth = FALSE @@ -343,6 +349,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] @@ -663,6 +676,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 @@ -982,6 +997,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/abilities/queen/queen_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm index 836854d6f956..0ee1cf6b3c27 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm @@ -87,7 +87,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) //From there, the new xeno exists, hopefully var/mob/living/carbon/xenomorph/new_xeno = new xeno_type(get_turf(target_xeno), target_xeno) 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 3b45abfc60d9..d46bfce6bf71 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 8c3fad8d0af9..35d500b15816 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 d1ef02586b68..01963496f967 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 c6eb8be5715e..2b1ef0aca867 100644 --- a/code/modules/mob/living/carbon/xenomorph/damage_procs.dm +++ b/code/modules/mob/living/carbon/xenomorph/damage_procs.dm @@ -16,6 +16,16 @@ 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) + if(!istype(item, /obj/item/reagent_container/syringe)) + 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 3d3dc2133e63..64f9949e94cd 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..5bf6561b28f4 --- /dev/null +++ b/code/modules/reagents/chemistry_machinery/xenomorph_analyzer.dm @@ -0,0 +1,182 @@ +/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" //for the time while no sprites + use_power = USE_POWER_NONE + wrenchable = FALSE + idle_power_usage = 40 + bound_x = 32 + ///assoc list containing the path to every upgrade followed by a number representing times this tech was bought. used by price inflation mechanic to increase/decrease price depending on the amount of times you bought it. + var/list/technology_purchased = list() + 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/Initialize(mapload, ...) + . = ..() + for(var/upgrade_type in subtypesof(/datum/research_upgrades)) + var/datum/research_upgrades/upgrade = upgrade_type + if(upgrade.behavior == RESEARCH_UPGRADE_CATEGORY) + continue + if(upgrade.behavior == RESEARCH_UPGRADE_EXCLUDE_BUY) + continue + technology_purchased[upgrade_type] = 0 + +/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(busy) + to_chat(user, SPAN_WARNING("The [src] is currently busy!")) + 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 + data["upgrades"] = list() + data["categories"] = list() + for(var/upgrade_type in subtypesof(/datum/research_upgrades))// moved this here since prices are dynamic now + var/datum/research_upgrades/upgrade = upgrade_type + if(upgrade.behavior == RESEARCH_UPGRADE_CATEGORY) + data["categories"] += upgrade.name + continue + if(upgrade.behavior == RESEARCH_UPGRADE_EXCLUDE_BUY) + continue + var/price_adjustment = clamp(upgrade.value_upgrade + upgrade.change_purchase * technology_purchased[upgrade_type], upgrade.minimum_price, upgrade.maximum_price) + data["upgrades"] += list(list( + "name" = capitalize_first_letters(upgrade.name), + "desc" = upgrade.desc, + "vari" = upgrade.behavior, + "cost" = price_adjustment, + "ref" = upgrade.item_reference, + "category" = upgrade.upgrade_type, + "clearance" = upgrade.clearance_req, + "price_change" = upgrade.change_purchase, + )) + return 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) + busy = TRUE + addtimer(CALLBACK(src, PROC_REF(process_organ), organ.research_value), 3 SECONDS) + flick("xeno_analyzer_on_moving", src) + playsound(loc, 'sound/machines/blender.ogg', 25, TRUE) + QDEL_NULL(organ) + . = 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" + organ.forceMove(get_turf(src)) + organ = null + +/obj/structure/machinery/xenoanalyzer/proc/process_organ(biomass_points_to_add) + biomass_points += biomass_points_to_add + icon_state = "xeno_analyzer" + busy = FALSE + + +/obj/structure/machinery/xenoanalyzer/proc/start_print_upgrade(produce_path, mob/user, variation) + if(stat & NOPOWER) + icon_state = "xeno_analyzer_off" + return + if(busy)//double check for me here + to_chat(user, SPAN_WARNING("[src] makes a annoying hum and flashes red - its currently busy!")) + return + var/path_exists = FALSE + var/datum/research_upgrades/upgrade + var/datum_upgrades + for(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(clamp(upgrade.value_upgrade + upgrade.change_purchase * technology_purchased[datum_upgrades], upgrade.minimum_price, upgrade.maximum_price) > 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 + flick("xeno_analyzer_printing", src) + busy = TRUE + biomass_points -= clamp(upgrade.value_upgrade + upgrade.change_purchase * technology_purchased[datum_upgrades], upgrade.minimum_price, upgrade.maximum_price) + technology_purchased[datum_upgrades] += 1 + addtimer(CALLBACK(src, PROC_REF(print_upgrade), produce_path, variation), 3 SECONDS) + +/obj/structure/machinery/xenoanalyzer/proc/print_upgrade(produce_path, variation) + busy = FALSE + 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..1158088e83e6 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,16 @@ 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 + if(isxeno(target)) + to_chat(user, SPAN_WARNING("You don't know any operations you could perform on this body part of a xenomorph.")) var/hint_msg for(var/datum/surgery_step/current_step as anything in valid_steps) if(hint_msg) @@ -114,7 +116,8 @@ hint_msg += ", [current_step.desc]" else hint_msg = "You can't [current_step.desc] with \the [tool]" - to_chat(user, SPAN_WARNING("[hint_msg].")) + if(!isnull(hint_msg)) + to_chat(user, SPAN_WARNING("[hint_msg].")) return FALSE var/datum/surgery/surgeryinstance @@ -159,7 +162,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..d3175a2f78d5 --- /dev/null +++ b/code/modules/surgery/xeno.dm @@ -0,0 +1,237 @@ +//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 = SURGERY_TOOL_MULT_IDEAL, + /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 [tool], carefully, trying to prevent acid leaks."), + SPAN_NOTICE("[user] starts to cut your carapace apart using [tool], carefully, trying to prevent acid leaks."), + SPAN_NOTICE("[user] starts to cut [target.caste_type] carapace. [tool], carefully, trying to prevent acid leaks.")) + else + user.affected_message(target, + SPAN_NOTICE("You start to [pick("smash", "crack", "break")] [target.caste_type] carapace apart using [tool], Recklessly, with acid splashing on you!"), + SPAN_NOTICE("[user] starts to [pick("smash", "crack", "break")] your carapace apart using [tool], recklessly splashing acid everywhere!"), + SPAN_NOTICE("[user] starts to [pick("smash", "crack", "break")] [target.caste_type] carapace with [tool], recklessly splashing acid everywhere!")) + //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 [tool]."), + SPAN_NOTICE("[user] successfully cuts through your carapace using [tool]."), + SPAN_NOTICE("[user] successfully cuts [target.caste_type] carapace using [tool].")) + else + user.affected_message(target, + SPAN_NOTICE("You successfully destroy [target.caste_type] carapace into bits and pieces using [tool]."), + SPAN_NOTICE("[user] successfully destroys your carapace into bits and pieces using [tool]."),, + SPAN_NOTICE("[user] successfully destroys [target.caste_type] carapace into bits and pieces using [tool].")) + for(var/mob/living/carbon/human/victim in orange(1, target)) + if(istype(victim.wear_suit, /obj/item/clothing/suit/bio_suit) && istype(victim.head, /obj/item/clothing/head/bio_hood)) + continue + to_chat(victim, SPAN_HIGHDANGER("You are covered in acid as you feel agonizing pain!")) + victim.apply_damage(rand(75, 125), BURN) // you WILL wear biosuit. + playsound(victim, "acid_sizzle", 25, TRUE) + animation_flash_color(victim, "#FF0000") + +/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) + user.affected_message(target, + SPAN_WARNING("Your hand slips, failing to cut [target.caste_type] carapace apart using [tool]!"), + SPAN_WARNING("[user]'s hand slips, failing to cut your carapace apart using [tool]!"), + SPAN_WARNING("[user] hand slips, failing to cut [target.caste_type] carapace using [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 [tool]"), + SPAN_NOTICE("[user] starts to pry your carapace open with [tool] very carefully"), + SPAN_NOTICE("[user] starts to pry [target.caste_type] carapace open with [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 [tool], exposing [target.caste_type] vital organs"), + SPAN_NOTICE("[user] holds your carapace and exoskeleton open with [tool], exposing [target.caste_type] vital organs "), + SPAN_NOTICE("[user] holds [target.caste_type] carapace and exoskeleton open with [tool], exposing [target.caste_type] vital organs ")) + else + user.affected_message(target, + SPAN_NOTICE("You hold [target.caste_type] carapace open using [tool] like a medieval doctor, exposing [target.caste_type] vital organs"), + SPAN_NOTICE("[user] starts to open your carapace with [tool] very carefully"), + SPAN_NOTICE("[user] starts to open [target.caste_type] carapace with [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!")) + for(var/mob/living/carbon/human/victim in orange(1, target)) + if(istype(victim.wear_suit, /obj/item/clothing/suit/bio_suit) && istype(victim.head, /obj/item/clothing/head/bio_hood)) + continue + to_chat(victim, SPAN_DANGER("You are covered in blood gushing out from [target.caste_type]")) + victim.apply_damage(rand(50, 75), BURN) // still dangerous + playsound(victim, "acid_sizzle", 25, TRUE) + animation_flash_color(victim, "#FF0000") + return FALSE + +/datum/surgery_step/xenomorph/severe_connections + name = "Sever 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 sever [target.caste_type] organ links using [tool], with confidence"), + SPAN_NOTICE("[user] start to sever your organ links using [tool], with confidence"), + SPAN_NOTICE("[user] starts to sever [target.caste_type] organ links using [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/scalpel || tool_type == /obj/item/tool/surgery/scalpel/pict_system) + user.affected_message(target, + SPAN_NOTICE("You severed [target.caste_type] connections and links to vital organs using [tool]"), + SPAN_NOTICE("[user] severed your connections and links to vital organs using [tool]"), + SPAN_NOTICE("[user] severed [target.caste_type] connections and links to vital organs using [tool]")) + else + user.affected_message(target, + SPAN_NOTICE("You rip [target.caste_type] connections and links to vital organs apart using [tool]"), + SPAN_NOTICE("[user] rips your connections and links to vital organs apart using [tool]"), + SPAN_NOTICE("[user] rips [target.caste_type] connections and links to vital organs apart using [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!")) + for(var/mob/living/carbon/human/victim in orange(1, target)) + if(istype(victim.wear_suit, /obj/item/clothing/suit/bio_suit) && istype(victim.head, /obj/item/clothing/head/bio_hood)) + continue + to_chat(victim, SPAN_DANGER("You are covered in blood gushing out from [target.caste_type]")) + victim.apply_damage(rand(50, 75), BURN) // not SO dangerous but still is + playsound(victim, "acid_sizzle", 25, TRUE) + animation_flash_color(victim, "#FF0000") + +/datum/surgery_step/xenomorph/remove_organ + name = "Remove Xenomorph Organ" + desc = "grab a hold of it and pull the organ out" + accept_hand = TRUE + tools = list( + /obj/item/tool/surgery/hemostat = SURGERY_TOOL_MULT_IDEAL, + /obj/item/tool/wirecutters = SURGERY_TOOL_MULT_SUBOPTIMAL, + /obj/item/tool/kitchen/utensil/fork = SURGERY_TOOL_MULT_SUBSTITUTE, + )//shamelessly taken from embryo code + time = 3 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 [tool] "), + SPAN_NOTICE("[user] start to get a firm grip on your insides using [tool]"), + SPAN_NOTICE("[user] starts to get a firm grip on the [target.caste_type] organ using [tool] ")) + else + user.affected_message(target, + SPAN_NOTICE("You start to get a firm grip on the [target.caste_type] organ"), + SPAN_NOTICE("[user] starts 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 [tool]"), + SPAN_NOTICE("[user] pulled your organ out using [tool]"), + SPAN_NOTICE("[user] pulled the [target.caste_type] organ out using [tool]")) + else + if(istype(user.wear_suit, /obj/item/clothing/suit/bio_suit)) + user.affected_message(target, + SPAN_NOTICE("You pulled the [target.caste_type] organ out!"), + SPAN_NOTICE("[user] pulles your insides out!"), + SPAN_NOTICE("[user] pulled the [target.caste_type] organ out.")) + 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 [user.p_their()] hands as [user.p_they()] pulled the [target.caste_type] organ out.")) + user.emote("pain") + if(user.hand) + user.apply_damage(rand(30,50), BURN, "l_hand") + else + user.apply_damage(rand(30,50), BURN, "r_hand") + playsound(user, "acid_sizzle", 25, TRUE) + animation_flash_color(user, "#FF0000") + 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 [tool]"), + SPAN_NOTICE("[user] fails to pull your organ out using [tool]"), + SPAN_NOTICE("[user] fails to pull the [target.caste_type] organ out using [tool]")) + return FALSE + diff --git a/colonialmarines.dme b/colonialmarines.dme index e97ca229b9d8..5be7a2d5df9c 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" @@ -1091,10 +1092,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" @@ -2270,6 +2271,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" @@ -2342,6 +2344,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..ab4e42717f84 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 7ee4592d8342..f15298111bf2 100644 --- a/maps/map_files/USS_Almayer/USS_Almayer.dmm +++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm @@ -17809,6 +17809,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; @@ -25584,7 +25597,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" }, @@ -45507,8 +45520,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" @@ -49804,11 +49817,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" @@ -58130,10 +58145,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" }, @@ -79699,9 +79714,6 @@ }, /area/almayer/squads/req) "wWR" = ( -/obj/structure/machinery/medical_pod/bodyscanner{ - dir = 8 - }, /obj/structure/machinery/status_display{ pixel_y = 30 }, @@ -80666,10 +80678,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 }, @@ -80680,6 +80688,7 @@ name = "Requisitions Delivery Unit"; pixel_y = 28 }, +/obj/structure/machinery/xenoanalyzer, /turf/open/floor/almayer{ icon_state = "mono" }, @@ -82907,14 +82916,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) @@ -114936,7 +114937,7 @@ wPz jeq rQy wWR -ycj +vti vkp cfT hec @@ -115143,7 +115144,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..990f3651fe66 --- /dev/null +++ b/tgui/packages/tgui/interfaces/XenomorphExtractor.jsx @@ -0,0 +1,155 @@ +import { useBackend } from '../backend'; +import { useState } from 'react'; +import { + Box, + Button, + Divider, + Dropdown, + Flex, + LabeledList, + NoticeBox, + Section, + Stack, +} from '../components'; +import { Window } from '../layouts'; + +export const XenomorphExtractor = () => { + const { act, data } = useBackend(); + + const { + organ, + points, + upgrades, + caste, + value, + categories, + current_clearance, + is_x_level, + } = data; + const dropdownOptions = categories; + const [selectedTab, setSelectedTab] = useState('NONE'); + + return ( + + +
+ + + + + + + + + Biological Matter : {points} + + +
+
+ {!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={ + + {' '} + + + } + > + + Clearance{' '} + {upgrades.clearance === 6 + ? '5X' + : upgrades.clearance}{' '} + Required + {upgrades.price_change !== 0 && ( + + + This technology will{' '} + {upgrades.price_change > 0 + ? 'increase' + : 'decrease'}{' '} + in cost by {upgrades.price_change} each purchase + + )} + {upgrades.price_change === 0 && ( + + + This technology will not change its value with + purchase. + + )} + + + ) : null, + )} + + )} + +
+
+
+
+
+ ); +};