diff --git a/code/__DEFINES/medical.dm b/code/__DEFINES/medical.dm index 899de5c273f..c41e442c88f 100644 --- a/code/__DEFINES/medical.dm +++ b/code/__DEFINES/medical.dm @@ -25,3 +25,9 @@ MENTAL_UNSTABLE, \ MENTAL_INSANE, \ ) + +/// The percentage amount of health required for a mob to be considered to be +#define CLEAN_BILL_OF_HEALTH_RATIO 0.9 + +///Cooldown for being on the recently treated trait for the purposes for bounty submission +#define RECENTLY_HEALED_COOLDOWN 5 MINUTES diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index c0340db854b..f61063aa2d7 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -212,6 +212,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_ANTIMAGIC_NO_SELFBLOCK "anti_magic_no_selfblock" /// This mob recently blocked magic with some form of antimagic #define TRAIT_RECENTLY_BLOCKED_MAGIC "recently_blocked_magic" +/// This mob was recently treated and scanned by a medical scanner. +#define TRAIT_RECENTLY_TREATED "recently_treated" /// The user can do things like use magic staffs without penalty #define TRAIT_MAGICALLY_GIFTED "magically_gifted" /// This object innately spawns with fantasy variables already applied (the magical component is given to it on initialize), and thus we never want to give it the component again. @@ -1029,6 +1031,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai ///A trait for mechs that were created through the normal construction process, and not spawned by map or other effects. #define TRAIT_MECHA_CREATED_NORMALLY "trait_mecha_created_normally" +/// Trait to apply to mechs after a diagnostic scan has been created, to prevent you from generating duplicates of a scan on the same machine. +#define TRAIT_MECHA_DIAGNOSTIC_CREATED "trait_mecha_diagnostic_created" + /// Stops a movable from being removed from the mob it's in by the content_barfer component. #define TRAIT_NOT_BARFABLE "not_barfable" diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 5f2fc6407c0..f0107820d5e 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -461,6 +461,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_RDS_SUPPRESSED" = TRAIT_RDS_SUPPRESSED, "TRAIT_REAGENT_SCANNER" = TRAIT_REAGENT_SCANNER, "TRAIT_RECENTLY_BLOCKED_MAGIC" = TRAIT_RECENTLY_BLOCKED_MAGIC, + "TRAIT_RECENTLY_TREATED" = TRAIT_RECENTLY_TREATED, "TRAIT_REGEN_SHIELD" = TRAIT_REGEN_SHIELD, "TRAIT_RELAYING_ATTACKER" = TRAIT_RELAYING_ATTACKER, "TRAIT_REMOTE_TASTING" = TRAIT_REMOTE_TASTING, @@ -739,7 +740,8 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_OREBOX_FUNCTIONAL" = TRAIT_OREBOX_FUNCTIONAL, ), /obj/vehicle/sealed/mecha = list( - "TRAIT_MECHA_CREATED_NORMALLY" = TRAIT_MECHA_CREATED_NORMALLY + "TRAIT_MECHA_CREATED_NORMALLY" = TRAIT_MECHA_CREATED_NORMALLY, + "TRAIT_MECHA_DIAGNOSTIC_CREATED" = TRAIT_MECHA_DIAGNOSTIC_CREATED, ), /turf = list( "TRAIT_CHASM_STOPPED" = TRAIT_CHASM_STOPPED, diff --git a/code/game/machinery/civilian_bounties.dm b/code/game/machinery/civilian_bounties.dm index 839151e7025..137010c5b14 100644 --- a/code/game/machinery/civilian_bounties.dm +++ b/code/game/machinery/civilian_bounties.dm @@ -160,12 +160,33 @@ if(!id_account.account_job) say("Requesting ID card has no job assignment registered!") return FALSE - var/list/datum/bounty/crumbs = list(random_bounty(id_account.account_job.bounty_types), // We want to offer 2 bounties from their appropriate job catagories - random_bounty(id_account.account_job.bounty_types), // and 1 guaranteed assistant bounty if the other 2 suck. - random_bounty(CIV_JOB_BASIC)) + + var/list/datum/bounty/crumbs = generate_bounty_list(id_account.account_job.bounty_types) COOLDOWN_START(id_account, bounty_timer, (5 MINUTES) - cooldown_reduction) id_account.bounties = crumbs +/** + * Generates a list of bounties for use with the civilian bounty pad. + * @param bounty_types the define taken from a job for selection of a random_bounty() proc. + * @param bounty_rolls the number of bounties to be selected from. + * @param assistant_failsafe Do we guarentee one assistant bounty per generated list? Used for non-assistant jobs to give an easier alternative to that job's default bounties. + */ +/obj/machinery/computer/piratepad_control/civilian/proc/generate_bounty_list(bounty_types, bounty_rolls = 3, assistant_failsafe = TRUE) + var/list/rolling_list = list() + if(assistant_failsafe) + rolling_list += random_bounty(CIV_JOB_BASIC) + while(bounty_rolls > 1) + var/datum/bounty/potential_bounty = random_bounty(bounty_types) + var/repeats_bool = FALSE + for(var/datum/iterator in rolling_list) + if(iterator.type == potential_bounty.type) + repeats_bool = TRUE + if(repeats_bool) + continue + rolling_list += potential_bounty + bounty_rolls -= 1 + return rolling_list + /** * Proc that assigned a civilian bounty to an ID card, from the list of potential bounties that that bank account currently has available. * Available choices are assigned during add_bounties, and one is locked in here. diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index a6487eb77cc..2d3208ad2a2 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -32,6 +32,8 @@ var/give_wound_treatment_bonus = FALSE var/last_scan_text var/scanner_busy = FALSE + /// Weakref to the last mob scanned by a health analyzer. Used to generate official medical reports. + var/datum/weakref/last_healthy_scanned /obj/item/healthanalyzer/Initialize(mapload) . = ..() @@ -97,6 +99,10 @@ switch (scanmode) if (SCANMODE_HEALTH) last_scan_text = healthscan(user, M, mode, advanced, tochat = readability_check) + if((M.health / M.maxHealth) > CLEAN_BILL_OF_HEALTH_RATIO) + last_healthy_scanned = WEAKREF(M) + else + last_healthy_scanned = null if (SCANMODE_WOUND) if(readability_check) woundscan(user, M, src) @@ -423,10 +429,10 @@ return scanner_busy = TRUE balloon_alert(user, "printing report...") - addtimer(CALLBACK(src, PROC_REF(print_report)), 2 SECONDS) + addtimer(CALLBACK(src, PROC_REF(print_report), user), 2 SECONDS) /obj/item/healthanalyzer/proc/print_report(mob/user) - var/obj/item/paper/report_paper = new(get_turf(src)) + var/obj/item/paper/medical_report/report_paper = new(get_turf(src)) report_paper.color = "#99ccff" report_paper.name = "health scan report - [station_time_timestamp()]" @@ -436,14 +442,41 @@ report_paper.add_raw_text(report_text) report_paper.update_appearance() - if(ismob(loc)) - var/mob/printer = loc - printer.put_in_hands(report_paper) - balloon_alert(printer, "logs cleared") + user.put_in_hands(report_paper) + balloon_alert(user, "logs cleared") + resolve_patient_eligibility(report_paper, user) report_text = list() scanner_busy = FALSE +/** + * Checks the mob and the medical report that the scanner is trying to print, checks the traits and statuses of the mob, and then resolves by true or false. + * Applies traits to the patient if the scanning is eligable to turn in for a bounty, with callbacks to remove after a cooldown. + */ +/obj/item/healthanalyzer/proc/resolve_patient_eligibility(obj/item/paper/medical_report/report_paper, mob/scanner) + var/mob/living/patient = last_healthy_scanned?.resolve() + if(!patient) + return FALSE + + if(scanner == patient) + return FALSE //You can't just scan yourself. + + if(HAS_TRAIT(patient, TRAIT_RECENTLY_TREATED)) + return FALSE + + report_paper.last_healthy_scanned_mob = last_healthy_scanned + ADD_TRAIT(patient, TRAIT_RECENTLY_TREATED, ANALYZER_TRAIT) + addtimer(TRAIT_CALLBACK_REMOVE(patient, RECENTLY_HEALED_COOLDOWN, ANALYZER_TRAIT), RECENTLY_HEALED_COOLDOWN) + return TRUE + +/obj/item/healthanalyzer/proc/clear_treatment(mob/living/target) + if(!target) + return + if(QDELETED(target)) + return + REMOVE_TRAIT(target, TRAIT_RECENTLY_TREATED, ANALYZER_TRAIT) + return TRUE + /proc/chemscan(mob/living/user, mob/living/target) if(user.incapacitated) return @@ -719,6 +752,18 @@ scanner.emotion = AID_EMOTION_WARN playsound(scanner, 'sound/machines/beep/twobeep.ogg', 50, FALSE) +/obj/item/paper/medical_report + color = "#99ccff" + desc = "An official medical bill of health generated by a computerized medical scanner." + /// A reference to a mob's weakref that was last scanned by the medical scanner. + var/datum/weakref/last_healthy_scanned_mob + +/obj/item/paper/medical_report/examine(mob/user) + . = ..() + if(last_healthy_scanned_mob) + . += span_notice("This medical report is applicable for medical bounties.") + + #undef SCANMODE_HEALTH #undef SCANMODE_WOUND #undef SCANMODE_COUNT diff --git a/code/modules/cargo/bounties/assistant.dm b/code/modules/cargo/bounties/assistant.dm index ca77572cb93..c9afa204fd6 100644 --- a/code/modules/cargo/bounties/assistant.dm +++ b/code/modules/cargo/bounties/assistant.dm @@ -41,11 +41,41 @@ wanted_types = list(/obj/item/spear = TRUE) /datum/bounty/item/assistant/toolbox - name = "Toolboxes" - description = "There's an absence of robustness at Central Command. Hurry up and ship some toolboxes as a solution." + name = "Stocked Toolbox" + description = "There's an absence of robustness at Central Command. Ship them a fully packed toolbox as a solution, containing a screwdriver, wrench, welding tool, crowbar, analyzer, and wirecutters." reward = CARGO_CRATE_VALUE * 4 - required_count = 6 wanted_types = list(/obj/item/storage/toolbox = TRUE) + /// Typecache of tools that we want to see sorted into a toolbox. Unpacked in New(), verified in applies_to(), and then contents are filtered out in ship(). + var/list/static_packing_list = list( + /obj/item/screwdriver = TRUE, + /obj/item/wrench = TRUE, + /obj/item/weldingtool = TRUE, + /obj/item/crowbar = TRUE, + /obj/item/analyzer = TRUE, + /obj/item/wirecutters = TRUE, + ) + +/datum/bounty/item/assistant/toolbox/New() + . = ..() + static_packing_list = string_assoc_list(zebra_typecacheof(static_packing_list, only_root_path = FALSE)) + +/datum/bounty/item/assistant/toolbox/applies_to(obj/shipped) + var/list/packing_list = static_packing_list.Copy() + for(var/obj/item_contents as anything in shipped.contents) + if(is_type_in_typecache(item_contents.type, packing_list)) + packing_list -= subtypesof(item_contents.type) + packing_list -= item_contents.type + if(!length(packing_list)) + return ..() + + return FALSE + +/datum/bounty/item/assistant/toolbox/ship(obj/shipped) + . = ..() + for(var/obj/object as anything in shipped.contents) + if(!is_type_in_typecache(object.type, static_packing_list)) + object.forceMove(shipped.drop_location()) + /datum/bounty/item/assistant/statue name = "Statue" @@ -133,8 +163,11 @@ name = "Potted Plants" description = "Central Command is looking to commission a new BirdBoat-class station. You've been ordered to supply the potted plants." reward = CARGO_CRATE_VALUE * 4 - required_count = 8 - wanted_types = list(/obj/item/kirbyplants = TRUE) + required_count = 3 + wanted_types = list( + /obj/item/kirbyplants = TRUE, + /obj/item/kirbyplants/synthetic = FALSE + ) /datum/bounty/item/assistant/monkey_cubes name = "Monkey Cubes" @@ -156,12 +189,12 @@ reward = CARGO_CRATE_VALUE * 6 wanted_types = list(/obj/item/food/meat/slab/corgi = TRUE) -/datum/bounty/item/assistant/action_figures - name = "Action Figures" - description = "The vice president's son saw an ad for action figures on the telescreen and now he won't shut up about them. Ship some to ease his complaints." +/datum/bounty/item/assistant/toys + name = "Arcade Toys" + description = "The vice president's son saw an ad for new toys on the telescreen and now he won't shut up about them. Ship some arcade toys over to ease his complaints." reward = CARGO_CRATE_VALUE * 8 required_count = 5 - wanted_types = list(/obj/item/toy/figure = TRUE) + wanted_types = list(/obj/item/toy = TRUE) /datum/bounty/item/assistant/paper_bin name = "Paper Bins" @@ -177,14 +210,6 @@ required_count = 8 wanted_types = list(/obj/item/toy/crayon = TRUE) -/datum/bounty/item/assistant/pens - name = "Pens" - description = "We are hosting the intergalactic pen balancing competition. We need you to send us some standardized black ballpoint pens." - reward = CARGO_CRATE_VALUE * 4 - required_count = 10 - include_subtypes = FALSE - wanted_types = list(/obj/item/pen = TRUE) - /datum/bounty/item/assistant/water_tank name = "Water Tank" description = "We need more water for our hydroponics bay. Find a water tank and ship it out to us." diff --git a/code/modules/cargo/bounties/item.dm b/code/modules/cargo/bounties/item.dm index eefc78b9d5e..1fb1df9104d 100644 --- a/code/modules/cargo/bounties/item.dm +++ b/code/modules/cargo/bounties/item.dm @@ -35,3 +35,27 @@ /// If the user can actually get this bounty as a selection. /datum/bounty/proc/can_get() return TRUE + +/** + * Debug item because it took less time to code this than it did to roll ONE toolbox bounty. + */ +/obj/item/bounty_voucher + name = "bounty voucher" + desc = "A certificate for ONE FREE BOUNTY of your choice! Wow!" + icon = 'icons/obj/service/bureaucracy.dmi' + icon_state = "paperslip_words" + +/obj/item/bounty_voucher/attack_self(mob/user, modifiers) + . = ..() + if(!isliving(user)) + return + var/mob/living/living_user = user + var/obj/item/card/id/id = living_user.get_idcard() + if(!id?.registered_account) + return + var/choice = tgui_input_list(living_user, "Choose a bounty.", "New Bounty", subtypesof(/datum/bounty)) + var/datum/bounty/new_chore = text2path("[choice]") + id.registered_account.civilian_bounty = new new_chore + balloon_alert(user, "new bounty acquired!") + playsound(src, 'sound/effects/coin2.ogg', 30, TRUE) + qdel(src) diff --git a/code/modules/cargo/bounties/mech.dm b/code/modules/cargo/bounties/mech.dm deleted file mode 100644 index 84ed9eebe92..00000000000 --- a/code/modules/cargo/bounties/mech.dm +++ /dev/null @@ -1,35 +0,0 @@ -/datum/bounty/item/mech/New() - ..() - description = "Upper management has requested one [name] mech be sent as soon as possible. Ship it to receive a large payment." - -/datum/bounty/item/mech/ship(obj/shipped) - . = ..() - if(!.) - return - var/obj/vehicle/sealed/mecha/mecha = shipped - mecha.wreckage = null // So the mech doesn't explode. - -/datum/bounty/item/mech/ripleymk2 - name = "APLU MK-II \"Ripley\"" - reward = CARGO_CRATE_VALUE * 26 - wanted_types = list(/obj/vehicle/sealed/mecha/ripley/mk2 = TRUE) - -/datum/bounty/item/mech/clarke - name = "Clarke" - reward = CARGO_CRATE_VALUE * 32 - wanted_types = list(/obj/vehicle/sealed/mecha/clarke = TRUE) - -/datum/bounty/item/mech/odysseus - name = "Odysseus" - reward = CARGO_CRATE_VALUE * 22 - wanted_types = list(/obj/vehicle/sealed/mecha/odysseus = TRUE) - -/datum/bounty/item/mech/gygax - name = "Gygax" - reward = CARGO_CRATE_VALUE * 56 - wanted_types = list(/obj/vehicle/sealed/mecha/gygax = TRUE) - -/datum/bounty/item/mech/durand - name = "Durand" - reward = CARGO_CRATE_VALUE * 40 - wanted_types = list(/obj/vehicle/sealed/mecha/durand = TRUE) diff --git a/code/modules/cargo/bounties/mecha.dm b/code/modules/cargo/bounties/mecha.dm new file mode 100644 index 00000000000..fc211810d4a --- /dev/null +++ b/code/modules/cargo/bounties/mecha.dm @@ -0,0 +1,45 @@ +/datum/bounty/item/mech + wanted_types = list(/obj/item/mecha_diagnostic = TRUE) + /// What mech do we need data of inside this mecha diagnostic? + var/required_data = null + +/datum/bounty/item/mech/New() + ..() + description = "Upper management has requested holodiagnostic scans of \a [name] mech be sent as soon as possible. A diagnostic holoscan can be generated from inside a new mecha. Ship it to receive a large payment." + +/datum/bounty/item/mech/applies_to(obj/shipped) + . = ..() + if(istype(shipped, /obj/vehicle/sealed/mecha)) + shipped.balloon_alert_to_viewers("make diagnostic from inside!") + + var/obj/item/mecha_diagnostic/diagnostic_sheet = shipped + if(!diagnostic_sheet.mech_data) + CRASH("Diagnostic sheet submitted with no mech data contained!") + if(istype(diagnostic_sheet.mech_data, required_data)) + return TRUE + return FALSE + +/datum/bounty/item/mech/ripleymk2 + name = "APLU MK-II \"Ripley\"" + reward = CARGO_CRATE_VALUE * 6.5 + required_data = /obj/vehicle/sealed/mecha/ripley/mk2 + +/datum/bounty/item/mech/clarke + name = "Clarke" + reward = CARGO_CRATE_VALUE * 12 + required_data = /obj/vehicle/sealed/mecha/clarke + +/datum/bounty/item/mech/odysseus + name = "Odysseus" + reward = CARGO_CRATE_VALUE * 5.5 + required_data = /obj/vehicle/sealed/mecha/odysseus + +/datum/bounty/item/mech/gygax + name = "Gygax" + reward = CARGO_CRATE_VALUE * 28 + required_data = /obj/vehicle/sealed/mecha/gygax + +/datum/bounty/item/mech/durand + name = "Durand" + reward = CARGO_CRATE_VALUE * 20 + required_data = /obj/vehicle/sealed/mecha/durand diff --git a/code/modules/cargo/bounties/medical.dm b/code/modules/cargo/bounties/medical.dm index d15f4405f7b..c3106c426b2 100644 --- a/code/modules/cargo/bounties/medical.dm +++ b/code/modules/cargo/bounties/medical.dm @@ -104,3 +104,23 @@ description = "After a recent influx of infected crew members, we've seen that masks just aren't cutting it alone. Silver operating tables might just do the trick though, send us one to use." reward = CARGO_CRATE_VALUE * 6 wanted_types = list(/obj/structure/table/optable = TRUE) + +/datum/bounty/item/medical/scanning + name = "Crew Medical Scanning" + description = "Conduct a routine medical scan using any health analyzer of a crew member with with a near perfect bill of health or better to ensure the crew is taking their medical care seriously. Then, print the medical report and ship it back to us." + reward = CARGO_CRATE_VALUE * 8 + required_count = 2 + wanted_types = list(/obj/item/paper/medical_report = TRUE) + +/datum/bounty/item/medical/scanning/applies_to(obj/shipped) + . = ..() + if(!istype(shipped, /obj/item/paper/medical_report)) + return FALSE + var/obj/item/paper/medical_report/report = shipped + if(!report) + return FALSE + + var/mob/living/patient = report.last_healthy_scanned_mob?.resolve() + if(patient) + return TRUE + return FALSE diff --git a/code/modules/cargo/bounty.dm b/code/modules/cargo/bounty.dm index 38b26e44027..b90e8816a1f 100644 --- a/code/modules/cargo/bounty.dm +++ b/code/modules/cargo/bounty.dm @@ -19,26 +19,26 @@ D.adjust_money(reward * SSeconomy.bounty_modifier) claimed = TRUE -/// If an item sent in the cargo shuttle can satisfy the bounty. +/// If an item in question can satisfy the bounty. /datum/bounty/proc/applies_to(obj/O) return FALSE -/// Called when an object is shipped on the cargo shuttle. +/// Called when an object is sent on the bounty pad. /datum/bounty/proc/ship(obj/O) return /** Returns a new bounty of random type, but does not add it to GLOB.bounties_list. * - * *Guided determines what specific catagory of bounty should be chosen. + * * Category determines what specific catagory of bounty should be chosen. */ -/proc/random_bounty(guided = 0) +/proc/random_bounty(category = 0) var/bounty_num var/chosen_type var/bounty_succeeded = FALSE var/datum/bounty/item/bounty_ref while(!bounty_succeeded) - if(guided && (guided != CIV_JOB_RANDOM)) - bounty_num = guided + if(category && (category != CIV_JOB_RANDOM)) + bounty_num = category else bounty_num = rand(1, MAXIMUM_BOUNTY_JOBS) switch(bounty_num) diff --git a/code/modules/cargo/exports/mecha.dm b/code/modules/cargo/exports/mecha.dm new file mode 100644 index 00000000000..06eb94401a6 --- /dev/null +++ b/code/modules/cargo/exports/mecha.dm @@ -0,0 +1,24 @@ +/datum/export/mecha/ripley + cost = CARGO_CRATE_VALUE * 13 + unit_name = "APLU MK-II Ripley" + export_types = list(/obj/vehicle/sealed/mecha/ripley/mk2) + +/datum/export/mecha/clarke + cost = CARGO_CRATE_VALUE * 16 + unit_name = "Clarke" + export_types = list(/obj/vehicle/sealed/mecha/clarke) + +/datum/export/mecha/odysseus + cost = CARGO_CRATE_VALUE * 11 + unit_name = "Odysseus" + export_types = list(/obj/vehicle/sealed/mecha/odysseus) + +/datum/export/mecha/gygax + cost = CARGO_CRATE_VALUE * 28 + unit_name = "Gygax" + export_types = list(/obj/vehicle/sealed/mecha/gygax) + +/datum/export/mecha/durand + cost = CARGO_CRATE_VALUE * 20 + unit_name = "Durand" + export_types = list(/obj/vehicle/sealed/mecha/durand) diff --git a/code/modules/vehicles/mecha/mecha_diagnostic.dm b/code/modules/vehicles/mecha/mecha_diagnostic.dm new file mode 100644 index 00000000000..7252a361b77 --- /dev/null +++ b/code/modules/vehicles/mecha/mecha_diagnostic.dm @@ -0,0 +1,26 @@ +/obj/item/mecha_diagnostic + name = "mecha holodiagnostic" + desc = "A holographic datasheet of unique data related to the mecha's construction and any production differences between the published designs to increment improvements." + icon = 'icons/obj/devices/scanner.dmi' + icon_state = "holosheet" + w_class = WEIGHT_CLASS_SMALL + layer = ABOVE_MOB_LAYER + light_system = OVERLAY_LIGHT + light_range = 1 + light_power = 2 + light_color = "#79aeeb" + /// What mech was this diagnostic sheet generated from? Used for applicability in bounties. + var/obj/vehicle/sealed/mecha/mech_data + +/obj/item/mecha_diagnostic/Initialize(mapload) + . = ..() + set_light_on(TRUE) + +/obj/item/mecha_diagnostic/Destroy(force) + . = ..() + mech_data = null + +/obj/item/mecha_diagnostic/examine(mob/user) + . = ..() + if(mech_data) + . += "This holodata sheet consists of data from a [initial(mech_data.name)]." diff --git a/code/modules/vehicles/mecha/mecha_ui.dm b/code/modules/vehicles/mecha/mecha_ui.dm index 41d858e5ebe..a3bfb9f97bc 100644 --- a/code/modules/vehicles/mecha/mecha_ui.dm +++ b/code/modules/vehicles/mecha/mecha_ui.dm @@ -60,6 +60,7 @@ "MECHA_INT_CONTROL_LOST" = MECHA_INT_CONTROL_LOST, "MECHA_INT_SHORT_CIRCUIT" = MECHA_INT_SHORT_CIRCUIT, ) + data["diagnostic_status"] = HAS_TRAIT(src, TRAIT_MECHA_DIAGNOSTIC_CREATED) var/list/regions = list() var/list/tgui_region_data = SSid_access.all_region_access_tgui @@ -225,5 +226,12 @@ if("equip_act") var/obj/item/mecha_parts/mecha_equipment/gear = locate(params["ref"]) in flat_equipment return gear?.ui_act(params["gear_action"], params, ui, state) + if("diagnostic") + if(HAS_TRAIT(src, TRAIT_MECHA_DIAGNOSTIC_CREATED)) + return FALSE + var/obj/item/mecha_diagnostic/diagnostic = new /obj/item/mecha_diagnostic(get_turf(src)) + diagnostic.name = "mecha holodiagnostic ([src.name])" + diagnostic.mech_data += src + ADD_TRAIT(src, TRAIT_MECHA_DIAGNOSTIC_CREATED, REF(src)) return TRUE diff --git a/code/modules/vehicles/mecha/working/ripley.dm b/code/modules/vehicles/mecha/working/ripley.dm index 29bc3fb4d48..b201e323fdd 100644 --- a/code/modules/vehicles/mecha/working/ripley.dm +++ b/code/modules/vehicles/mecha/working/ripley.dm @@ -276,6 +276,7 @@ GLOBAL_DATUM(cargo_ripley, /obj/vehicle/sealed/mecha/ripley/cargo) take_damage(max_integrity * 0.5, sound_effect=FALSE) //Low starting health if(!GLOB.cargo_ripley && mapload) GLOB.cargo_ripley = src + ADD_TRAIT(src, TRAIT_MECHA_DIAGNOSTIC_CREATED, REF(src)) //It was built *long* before the shift started. /obj/vehicle/sealed/mecha/ripley/cargo/Destroy() if(GLOB.cargo_ripley == src) diff --git a/icons/obj/devices/scanner.dmi b/icons/obj/devices/scanner.dmi index dd947699481..c5a1ec68324 100644 Binary files a/icons/obj/devices/scanner.dmi and b/icons/obj/devices/scanner.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 4fd22f28eb7..b25780c4564 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3760,7 +3760,7 @@ #include "code\modules\cargo\bounties\chef.dm" #include "code\modules\cargo\bounties\engineering.dm" #include "code\modules\cargo\bounties\item.dm" -#include "code\modules\cargo\bounties\mech.dm" +#include "code\modules\cargo\bounties\mecha.dm" #include "code\modules\cargo\bounties\medical.dm" #include "code\modules\cargo\bounties\mining.dm" #include "code\modules\cargo\bounties\reagent.dm" @@ -3779,6 +3779,7 @@ #include "code\modules\cargo\exports\lavaland.dm" #include "code\modules\cargo\exports\manifest.dm" #include "code\modules\cargo\exports\materials.dm" +#include "code\modules\cargo\exports\mecha.dm" #include "code\modules\cargo\exports\organs.dm" #include "code\modules\cargo\exports\parts.dm" #include "code\modules\cargo\exports\seeds.dm" @@ -6368,6 +6369,7 @@ #include "code\modules\vehicles\mecha\mecha_control_console.dm" #include "code\modules\vehicles\mecha\mecha_damage.dm" #include "code\modules\vehicles\mecha\mecha_defense.dm" +#include "code\modules\vehicles\mecha\mecha_diagnostic.dm" #include "code\modules\vehicles\mecha\mecha_helpers.dm" #include "code\modules\vehicles\mecha\mecha_mob_interaction.dm" #include "code\modules\vehicles\mecha\mecha_movement.dm" diff --git a/tgui/packages/tgui/interfaces/Mecha/data.ts b/tgui/packages/tgui/interfaces/Mecha/data.ts index 9832eff273f..07e84b1d66f 100644 --- a/tgui/packages/tgui/interfaces/Mecha/data.ts +++ b/tgui/packages/tgui/interfaces/Mecha/data.ts @@ -54,6 +54,7 @@ export type MainData = { modules: MechModule[]; selected_module_index: number; sheet_material_amount: number; + diagnostic_status: BooleanLike; }; export type MechModule = { diff --git a/tgui/packages/tgui/interfaces/Mecha/index.tsx b/tgui/packages/tgui/interfaces/Mecha/index.tsx index 0bf81298b72..47e996510d1 100644 --- a/tgui/packages/tgui/interfaces/Mecha/index.tsx +++ b/tgui/packages/tgui/interfaces/Mecha/index.tsx @@ -38,6 +38,7 @@ export const Content = (props) => { one_access, regions, accesses, + diagnostic_status, } = data; const id_lock = mecha_flags & mechflag_keys['ID_LOCK_ON']; return ( @@ -49,12 +50,23 @@ export const Content = (props) => { fill title={name} buttons={ -