diff --git a/.vscode/settings.json b/.vscode/settings.json index c1c58bc3287..a5f5ccd084c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,10 +3,7 @@ "./tgui-next" ], - "workbench.editorAssociations": [ - { - "filenamePattern": "*.dmi", - "viewType": "imagePreview.previewEditor" - } - ] + "workbench.editorAssociations": { + "*.dmi": "imagePreview.previewEditor" + } } diff --git a/code/__DEFINES/exosuit_fab.dm b/code/__DEFINES/exosuit_fab.dm new file mode 100644 index 00000000000..a237d5b0fb1 --- /dev/null +++ b/code/__DEFINES/exosuit_fab.dm @@ -0,0 +1,32 @@ +/// Module is compatible with Security Cyborg models +#define BORG_MODULE_SECURITY (1<<0) +/// Module is compatible with Miner Cyborg models +#define BORG_MODULE_MINER (1<<1) +/// Module is compatible with Janitor Cyborg models +#define BORG_MODULE_JANITOR (1<<2) +/// Module is compatible with Medical Cyborg models +#define BORG_MODULE_MEDICAL (1<<3) +/// Module is compatible with Engineering Cyborg models +#define BORG_MODULE_ENGINEERING (1<<4) + +/// Module is compatible with Ripley Exosuit models +#define EXOSUIT_MODULE_RIPLEY (1<<0) +/// Module is compatible with Odyseeus Exosuit models +#define EXOSUIT_MODULE_ODYSSEUS (1<<1) +/// Module is compatible with Clarke Exosuit models +#define EXOSUIT_MODULE_CLARKE (1<<2) +/// Module is compatible with Gygax Exosuit models +#define EXOSUIT_MODULE_GYGAX (1<<3) +/// Module is compatible with Durand Exosuit models +#define EXOSUIT_MODULE_DURAND (1<<4) +/// Module is compatible with H.O.N.K Exosuit models +#define EXOSUIT_MODULE_HONK (1<<5) +/// Module is compatible with Phazon Exosuit models +#define EXOSUIT_MODULE_PHAZON (1<<6) + +/// Module is compatible with "Working" Exosuit models - Ripley and Clarke +#define EXOSUIT_MODULE_WORKING EXOSUIT_MODULE_RIPLEY | EXOSUIT_MODULE_CLARKE +/// Module is compatible with "Combat" Exosuit models - Gygax, H.O.N.K, Durand and Phazon +#define EXOSUIT_MODULE_COMBAT EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_HONK | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON +/// Module is compatible with "Medical" Exosuit modelsm - Odysseus +#define EXOSUIT_MODULE_MEDICAL EXOSUIT_MODULE_ODYSSEUS diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index 6e4a4a4c7d8..e14220f7562 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -11,7 +11,10 @@ var/equip_ready = 1 //whether the equipment is ready for use. (or deactivated/activated for static stuff) var/energy_drain = 0 var/obj/mecha/chassis = null - var/range = MELEE //bitFflags + ///Bitflag. Determines the range of the equipment. + var/range = MECHA_MELEE + /// Bitflag. Used by exosuit fabricator to assign sub-categories based on which exosuits can equip this. + var/mech_flags = NONE var/salvageable = 1 var/selectable = 1 // Set to 0 for passive equipment such as mining scanner or armor plates var/harmful = FALSE //Controls if equipment can be used to attack by a pacifist. diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index f701bef92bc..75e59214a6f 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -1,6 +1,7 @@ // Sleeper, Medical Beam, and Syringe gun /obj/item/mecha_parts/mecha_equipment/medical + mech_flags = EXOSUIT_MODULE_MEDICAL /obj/item/mecha_parts/mecha_equipment/medical/Initialize() . = ..() diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm index 9a33a596a07..152ea73db9c 100644 --- a/code/game/mecha/equipment/tools/mining_tools.dm +++ b/code/game/mecha/equipment/tools/mining_tools.dm @@ -15,6 +15,7 @@ harmful = TRUE var/drill_delay = 7 var/drill_level = DRILL_BASIC + mech_flags = EXOSUIT_MODULE_WORKING | EXOSUIT_MODULE_COMBAT /obj/item/mecha_parts/mecha_equipment/drill/Initialize() . = ..() @@ -145,16 +146,23 @@ /obj/item/mecha_parts/mecha_equipment/mining_scanner name = "exosuit mining scanner" - desc = "Equipment for engineering and combat exosuits. It will automatically check surrounding rock for useful minerals." + desc = "Equipment for working exosuits. It will automatically check surrounding rock for useful minerals." icon_state = "mecha_analyzer" selectable = 0 equip_cooldown = 15 var/scanning_time = 0 + mech_flags = EXOSUIT_MODULE_WORKING /obj/item/mecha_parts/mecha_equipment/mining_scanner/Initialize() . = ..() START_PROCESSING(SSfastprocess, src) +/obj/item/mecha_parts/mecha_equipment/mining_scanner/can_attach(obj/mecha/M as obj) + if(..()) + if(istype(M, /obj/mecha/working)) + return TRUE + return FALSE + /obj/item/mecha_parts/mecha_equipment/mining_scanner/process() if(!loc) STOP_PROCESSING(SSfastprocess, src) diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm index a8f6e8962e9..88b9f14fbca 100644 --- a/code/game/mecha/equipment/tools/work_tools.dm +++ b/code/game/mecha/equipment/tools/work_tools.dm @@ -11,6 +11,7 @@ var/dam_force = 20 var/obj/mecha/working/ripley/cargo_holder harmful = TRUE + mech_flags = EXOSUIT_MODULE_RIPLEY /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj) if(..()) @@ -172,7 +173,8 @@ icon_state = "mecha_exting" equip_cooldown = 5 energy_drain = 0 - range = MELEE|RANGED + range = MECHA_MELEE|MECHA_RANGED + mech_flags = EXOSUIT_MODULE_WORKING /obj/item/mecha_parts/mecha_equipment/extinguisher/Initialize() . = ..() @@ -337,6 +339,7 @@ name = "Ripley MK-II Conversion Kit" desc = "A pressurized canopy attachment kit for an Autonomous Power Loader Unit \"Ripley\" MK-I mecha, to convert it to the slower, but space-worthy MK-II design. This kit cannot be removed, once applied." icon_state = "ripleyupgrade" + mech_flags = EXOSUIT_MODULE_RIPLEY /obj/item/mecha_parts/mecha_equipment/ripleyupgrade/can_attach(obj/mecha/working/ripley/M) if(M.type != /obj/mecha/working/ripley) diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 2dcf93980ad..aac0a49ec78 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -9,6 +9,7 @@ var/projectile_delay = 0 var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the weapon is fired. var/kickback = TRUE //Will using this weapon in no grav push mecha back. + mech_flags = EXOSUIT_MODULE_COMBAT /obj/item/mecha_parts/mecha_equipment/weapon/can_attach(obj/mecha/M) if(!..()) @@ -143,7 +144,7 @@ fire_sound = 'sound/weapons/plasma_cutter.ogg' harmful = TRUE -/obj/item/mecha_parts/mecha_equipment/weapon/energy/plasma/can_attach(obj/mecha/working/M) +/obj/item/mecha_parts/mecha_equipment/weapon/energy/plasma/can_attach(obj/mecha/M) if(..()) //combat mech return 1 else if(M.equipment.len < M.max_equip && istype(M)) @@ -168,6 +169,7 @@ equip_cooldown = 150 range = MELEE|RANGED kickback = FALSE + mech_flags = EXOSUIT_MODULE_HONK /obj/item/mecha_parts/mecha_equipment/weapon/honker/can_attach(obj/mecha/combat/honker/M) if(..()) @@ -373,6 +375,7 @@ missile_speed = 1.5 projectile_energy_cost = 100 equip_cooldown = 20 + mech_flags = EXOSUIT_MODULE_HONK /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/banana_mortar/can_attach(obj/mecha/combat/honker/M) if(..()) @@ -390,6 +393,7 @@ missile_speed = 1.5 projectile_energy_cost = 100 equip_cooldown = 10 + mech_flags = EXOSUIT_MODULE_HONK /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/mousetrap_mortar/can_attach(obj/mecha/combat/honker/M) if(..()) @@ -415,6 +419,11 @@ projectiles = 10 projectile_energy_cost = 500 diags_first = TRUE + /// Damage done by the glove on contact. Also used to determine throw distance (damage / 5) + var/punch_damage = 35 + /// TRUE - Can toggle between lethal and non-lethal || FALSE - Cannot toggle + var/can_toggle_lethal = TRUE + mech_flags = EXOSUIT_MODULE_HONK /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/punching_glove/can_attach(obj/mecha/combat/honker/M) if(..()) diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 52f7750b8de..6ab1fcc1fbb 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -9,18 +9,41 @@ active_power_usage = 5000 req_access = list(ACCESS_ROBOTICS) circuit = /obj/item/circuitboard/machine/mechfab + processing_flags = START_PROCESSING_MANUALLY + + subsystem_type = /datum/controller/subsystem/processing/fastprocess + + /// Current items in the build queue. + var/list/queue = list() + /// Whether or not the machine is building the entire queue automagically. + var/process_queue = FALSE + + /// The current design datum that the machine is building. + var/datum/design/being_built + /// World time when the build will finish. + var/build_finish = 0 + /// World time when the build started. + var/build_start = 0 + /// Reference to all materials used in the creation of the item being_built. + var/list/build_materials + /// Part currently stored in the Exofab. + var/obj/item/stored_part + + /// Coefficient for the speed of item building. Based on the installed parts. var/time_coeff = 1 + /// Coefficient for the efficiency of material usage in item building. Based on the installed parts. var/component_coeff = 1 + + /// Copy of the currently synced techweb. var/datum/techweb/specialized/autounlocking/exofab/stored_research - var/sync = 0 - var/part_set - var/datum/design/being_built - var/list/queue = list() - var/processing_queue = 0 - var/screen = "main" + + /// Whether the Exofab links to the ore silo on init. Special derelict or maintanance variants should set this to FALSE. var/link_on_init = TRUE - var/temp + + /// Reference to a remote material inventory, such as an ore silo. var/datum/component/remote_materials/rmat + + /// A list of categories that valid MECHFAB design datums will broadly categorise themselves under. var/list/part_sets = list( "Cyborg", "Ripley", @@ -32,6 +55,9 @@ "Phazon", "Exosuit Equipment", "Cyborg Upgrade Modules", + "Cybernetics", + "Implants", + "Control Interfaces", "Misc" ) @@ -61,352 +87,534 @@ T += Ml.rating time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01) + // Adjust the build time of any item currently being built. + if(being_built) + var/last_const_time = build_finish - build_start + var/new_const_time = get_construction_time_w_coeff(initial(being_built.construction_time)) + var/const_time_left = build_finish - world.time + var/new_build_time = (new_const_time / last_const_time) * const_time_left + build_finish = world.time + new_build_time + + update_static_data(usr) + /obj/machinery/mecha_part_fabricator/examine(mob/user) . = ..() if(in_range(user, src) || isobserver(user)) . += "The status display reads: Storing up to [rmat.local_size] material units.
Material consumption at [component_coeff*100]%.
Build time reduced by [100-time_coeff*100]%." -/obj/machinery/mecha_part_fabricator/emag_act() - if(obj_flags & EMAGGED) - return - obj_flags |= EMAGGED - req_access = list() - say("DB error \[Code 0x00F1\]") - sleep(10) - say("Attempting auto-repair...") - sleep(15) - say("User DB corrupted \[Code 0x00FA\]. Truncating data structure...") - sleep(30) - say("User DB truncated. Please contact your Nanotrasen system operator for future assistance.") - -/obj/machinery/mecha_part_fabricator/proc/output_parts_list(set_name) - var/output = "" - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(D.build_type & MECHFAB) - if(!(set_name in D.category)) - continue - output += "
[output_part_info(D)]
\[" - if(check_resources(D)) - output += "Build | " - output += "Add to queue\]\[?\]
" - return output - -/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D) - var/output = "[initial(D.name)] (Cost: [output_part_cost(D)]) [get_construction_time_w_coeff(D)/10]sec" - return output - -/obj/machinery/mecha_part_fabricator/proc/output_part_cost(datum/design/D) - var/i = 0 - var/output +/** + * Generates an info list for a given part. + * + * Returns a list of part information. + * * D - Design datum to get information on. + * * categories - Boolean, whether or not to parse snowflake categories into the part information list. + */ +/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D, var/categories = FALSE) + var/cost = list() for(var/c in D.materials) - output += "[i?" | ":null][get_resource_cost_w_coeff(D, c)] [material2name(c)]" - i++ - return output - + var/datum/material/M = c + cost[M.name] = get_resource_cost_w_coeff(D, M) + + var/obj/built_item = D.build_path + + var/list/category_override = null + var/list/sub_category = null + + if(categories) + // Handle some special cases to build up sub-categories for the fab interface. + // Start with checking if this design builds a cyborg module. + if(built_item in typesof(/obj/item/borg/upgrade)) + var/obj/item/borg/upgrade/U = built_item + var/module_types = initial(U.module_flags) + sub_category = list() + if(module_types) + if(module_types & BORG_MODULE_SECURITY) + sub_category += "Security" + if(module_types & BORG_MODULE_MINER) + sub_category += "Mining" + if(module_types & BORG_MODULE_JANITOR) + sub_category += "Janitor" + if(module_types & BORG_MODULE_MEDICAL) + sub_category += "Medical" + if(module_types & BORG_MODULE_ENGINEERING) + sub_category += "Engineering" + else + sub_category += "All Cyborgs" + // Else check if this design builds a piece of exosuit equipment. + else if(built_item in typesof(/obj/item/mecha_parts/mecha_equipment)) + var/obj/item/mecha_parts/mecha_equipment/E = built_item + var/mech_types = initial(E.mech_flags) + sub_category = "Equipment" + if(mech_types) + category_override = list() + if(mech_types & EXOSUIT_MODULE_RIPLEY) + category_override += "Ripley" + if(mech_types & EXOSUIT_MODULE_ODYSSEUS) + category_override += "Odysseus" + if(mech_types & EXOSUIT_MODULE_CLARKE) + category_override += "Clarke" + if(mech_types & EXOSUIT_MODULE_GYGAX) + category_override += "Gygax" + if(mech_types & EXOSUIT_MODULE_DURAND) + category_override += "Durand" + if(mech_types & EXOSUIT_MODULE_HONK) + category_override += "H.O.N.K" + if(mech_types & EXOSUIT_MODULE_PHAZON) + category_override += "Phazon" + + + var/list/part = list( + "name" = D.name, + "desc" = initial(built_item.desc), + "printTime" = get_construction_time_w_coeff(initial(D.construction_time))/10, + "cost" = cost, + "id" = D.id, + "subCategory" = sub_category, + "categoryOverride" = category_override, + "searchMeta" = D.search_metadata + ) + + return part + +/** + * Generates a list of resources / materials available to this Exosuit Fab + * + * Returns null if there is no material container available. + * List format is list(material_name = list(amount = ..., ref = ..., etc.)) + */ /obj/machinery/mecha_part_fabricator/proc/output_available_resources() - var/output var/datum/component/material_container/materials = rmat.mat_container + var/list/material_data = list() + if(materials) for(var/mat_id in materials.materials) - var/datum/material/M = materials.materials[mat_id] - output += "[M.name]: [M.amount] cm³" - if(M.amount >= MINERAL_MATERIAL_AMOUNT) - output += "- Remove \[1\]" - if(M.amount >= (MINERAL_MATERIAL_AMOUNT * 10)) - output += " | \[10\]" - output += " | \[50\]" - output += "
" - else - output += "No material storage connected, please contact the quartermaster.
" - return output + var/datum/material/M = mat_id + var/list/material_info = list() + var/amount = materials.materials[mat_id] + + material_info = list( + "name" = M.name, + "ref" = REF(M), + "amount" = amount, + "sheets" = round(amount / MINERAL_MATERIAL_AMOUNT), + "removable" = amount >= MINERAL_MATERIAL_AMOUNT + ) + + material_data += list(material_info) + + return material_data + + return null + +/** + * Intended to be called when an item starts printing. + * + * Adds the overlay to show the fab working and sets active power usage settings. + */ +/obj/machinery/mecha_part_fabricator/proc/on_start_printing() + add_overlay("fab-active") + use_power = ACTIVE_POWER_USE +/** + * Intended to be called when the exofab has stopped working and is no longer printing items. + * + * Removes the overlay to show the fab working and sets idle power usage settings. Additionally resets the description and turns off queue processing. + */ +/obj/machinery/mecha_part_fabricator/proc/on_finish_printing() + cut_overlay("fab-active") + use_power = IDLE_POWER_USE + desc = initial(desc) + process_queue = FALSE + +/** + * Calculates resource/material costs for printing an item based on the machine's resource coefficient. + * + * Returns a list of k,v resources with their amounts. + * * D - Design datum to calculate the modified resource cost of. + */ /obj/machinery/mecha_part_fabricator/proc/get_resources_w_coeff(datum/design/D) var/list/resources = list() for(var/R in D.materials) resources[R] = get_resource_cost_w_coeff(D, R) return resources +/** + * Checks if the Exofab has enough resources to print a given item. + * + * Returns FALSE if the design has no reagents used in its construction (?) or if there are insufficient resources. + * Returns TRUE if there are sufficient resources to print the item. + * * D - Design datum to calculate the modified resource cost of. + */ /obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D) - if(D.reagents_list.len) // No reagents storage - no reagent designs. + if(length(D.reagents_list)) // No reagents storage - no reagent designs. return FALSE var/datum/component/material_container/materials = rmat.mat_container if(materials.has_materials(get_resources_w_coeff(D))) return TRUE return FALSE -/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D) - var/list/res_coef = get_resources_w_coeff(D) +/** + * Attempts to build the next item in the build queue. + * + * Returns FALSE if either there are no more parts to build or the next part is not buildable. + * Returns TRUE if the next part has started building. + * * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build. + */ +/obj/machinery/mecha_part_fabricator/proc/build_next_in_queue(verbose = TRUE) + if(!length(queue)) + return FALSE + + var/datum/design/D = queue[1] + if(build_part(D, verbose)) + remove_from_queue(1) + return TRUE + + return FALSE + +/** + * Starts the build process for a given design datum. + * + * Returns FALSE if the procedure fails. Returns TRUE when being_built is set. + * Uses materials. + * * D - Design datum to attempt to print. + * * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build. + */ +/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D, verbose = TRUE) + if(!D) + return FALSE var/datum/component/material_container/materials = rmat.mat_container if (!materials) - say("No access to material storage, please contact the quartermaster.") + if(verbose) + say("No access to material storage, please contact the quartermaster.") return FALSE if (rmat.on_hold()) - say("Mineral access is on hold, please contact the quartermaster.") + if(verbose) + say("Mineral access is on hold, please contact the quartermaster.") return FALSE if(!check_resources(D)) - say("Not enough resources. Queue processing stopped.") + if(verbose) + say("Not enough resources. Processing stopped.") return FALSE + + build_materials = get_resources_w_coeff(D) + + materials.use_materials(build_materials) being_built = D - desc = "It's building \a [initial(D.name)]." - materials.use_amount(res_coef) - rmat.silo_log(src, "built", -1, "[D.name]", res_coef) + build_finish = world.time + get_construction_time_w_coeff(initial(D.construction_time)) + build_start = world.time + desc = "It's building \a [D.name]." - add_overlay("fab-active") - use_power = ACTIVE_POWER_USE - updateUsrDialog() - sleep(get_construction_time_w_coeff(D)) - use_power = IDLE_POWER_USE - cut_overlay("fab-active") - desc = initial(desc) + rmat.silo_log(src, "built", -1, "[D.name]", build_materials) - var/location = get_step(src,(dir)) - var/obj/item/I = new D.build_path(location) - I.materials = res_coef - say("\The [I] is complete.") - being_built = null + return TRUE - updateUsrDialog() +/obj/machinery/mecha_part_fabricator/process() + // If there's a stored part to dispense due to an obstruction, try to dispense it. + if(stored_part) + var/turf/exit = get_step(src,(dir)) + if(exit.density) + return TRUE + + say("Obstruction cleared. \The [stored_part] is complete.") + stored_part.forceMove(exit) + stored_part = null + + // If there's nothing being built, try to build something + if(!being_built) + // If we're not processing the queue anymore or there's nothing to build, end processing. + if(!process_queue || !build_next_in_queue()) + on_finish_printing() + end_processing() + return TRUE + on_start_printing() + + // If there's an item being built, check if it is complete. + if(being_built && (build_finish < world.time)) + // Then attempt to dispense it and if appropriate build the next item. + dispense_built_part(being_built) + if(process_queue) + build_next_in_queue(FALSE) + return TRUE - process_malfunction(1, (((1/time_coeff) ** 2) * 3)) // hippie -- scientist cremation -- Roboticists are goddamn wankers so I'll give them a 3% chance at low tier to an 18.75% chance at high tier +/** + * Dispenses a part to the tile infront of the Exosuit Fab. + * + * Returns FALSE is the machine cannot dispense the part on the appropriate turf. + * Return TRUE if the part was successfully dispensed. + * * D - Design datum to attempt to dispense. + */ +/obj/machinery/mecha_part_fabricator/proc/dispense_built_part(datum/design/D) + var/obj/item/I = new D.build_path(src) + I.material_flags |= MATERIAL_NO_EFFECTS //Find a better way to do this. + I.set_custom_materials(build_materials) - return TRUE + being_built = null -/obj/machinery/mecha_part_fabricator/proc/update_queue_on_page() - send_byjax(usr,"mecha_fabricator.browser","queue",list_queue()) - return + var/turf/exit = get_step(src,(dir)) + if(exit.density) + say("Error! Part outlet is obstructed.") + desc = "It's trying to dispense \a [D.name], but the part outlet is obstructed." + stored_part = I + return FALSE -/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(set_name) - if(set_name in part_sets) - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(D.build_type & MECHFAB) - if(set_name in D.category) - add_to_queue(D) + say("\The [I] is complete.") + I.forceMove(exit) + return TRUE -/obj/machinery/mecha_part_fabricator/proc/add_to_queue(D) +/** + * Adds a list of datum designs to the build queue. + * + * Will only add designs that are in this machine's stored techweb. + * Does final checks for datum IDs and makes sure this machine can build the designs. + * * part_list - List of datum design ids for designs to add to the queue. + */ +/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(list/part_list) + for(var/v in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(v) + if((D.build_type & MECHFAB) && (D.id in part_list)) + add_to_queue(D) + +/** + * Adds a datum design to the build queue. + * + * Returns TRUE if successful and FALSE if the design was not added to the queue. + * * D - Datum design to add to the queue. + */ +/obj/machinery/mecha_part_fabricator/proc/add_to_queue(datum/design/D) if(!istype(queue)) queue = list() if(D) queue[++queue.len] = D - return queue.len + return TRUE + return FALSE +/** + * Removes datum design from the build queue based on index. + * + * Returns TRUE if successful and FALSE if a design was not removed from the queue. + * * index - Index in the build queue of the element to remove. + */ /obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index) - if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>queue.len)) + if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>length(queue))) return FALSE queue.Cut(index,++index) return TRUE -/obj/machinery/mecha_part_fabricator/proc/process_queue() - var/datum/design/D = queue[1] - if(!D) - remove_from_queue(1) - if(queue.len) - return process_queue() - else - return - temp = null - while(D) - if(stat&(NOPOWER|BROKEN)) - return FALSE - if(build_part(D)) - remove_from_queue(1) - else - return FALSE - D = listgetindex(queue, 1) - say("Queue processing finished successfully.") - +/** + * Generates a list of parts formatted for tgui based on the current build queue. + * + * Returns a formatted list of lists containing formatted part information for every part in the build queue. + */ /obj/machinery/mecha_part_fabricator/proc/list_queue() - var/output = "Queue contains:" - if(!istype(queue) || !queue.len) - output += "
Nothing" - else - output += "
    " - var/i = 0 - for(var/datum/design/D in queue) - i++ - var/obj/part = D.build_path - output += "" - output += initial(part.name) + " - " - output += "[i>1?"":null] " - output += "[i↓":null] " - output += "Remove" - - output += "
" - output += "\[Process queue | Clear queue\]" - return output - + if(!istype(queue) || !length(queue)) + return null + + var/list/queued_parts = list() + for(var/datum/design/D in queue) + var/list/part = output_part_info(D) + queued_parts += list(part) + return queued_parts + +/** + * Syncs machine with R&D servers. + * + * Requires an R&D Console visible within 7 tiles. Copies techweb research. Updates tgui's state data. + */ /obj/machinery/mecha_part_fabricator/proc/sync() - temp = "Updating local R&D database..." - updateUsrDialog() - sleep(30) //only sleep if called by user - - for(var/obj/machinery/computer/rdconsole/RDC in oview(7,src)) + for(var/obj/machinery/computer/rdconsole/RDC in orange(7,src)) RDC.stored_research.copy_research_to(stored_research) - temp = "Processed equipment designs.
" - //check if the tech coefficients have changed - temp += "Return" - - updateUsrDialog() + update_static_data(usr) say("Successfully synchronized with R&D server.") return - temp = "Unable to connect to local R&D Database.
Please check your connections and try again.
Return" - updateUsrDialog() + say("Unable to connect to local R&D server.") return -/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, resource, roundto = 1) +/** + * Calculates the coefficient-modified resource cost of a single material component of a design's recipe. + * + * Returns coefficient-modified resource cost for the given material component. + * * D - Design datum to pull the resource cost from. + * * resource - Material datum reference to the resource to calculate the cost of. + * * roundto - Rounding value for round() proc + */ +/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, var/datum/material/resource, roundto = 1) return round(D.materials[resource]*component_coeff, roundto) -/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(datum/design/D, roundto = 1) //aran - return round(initial(D.construction_time)*time_coeff, roundto) +/** + * Calculates the coefficient-modified build time of a design. + * + * Returns coefficient-modified build time of a given design. + * * D - Design datum to calculate the modified build time of. + * * roundto - Rounding value for round() proc + */ +/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(construction_time, roundto = 1) //aran + return round(construction_time*time_coeff, roundto) -/obj/machinery/mecha_part_fabricator/ui_interact(mob/user as mob) - . = ..() - var/dat, left_part - user.set_machine(src) - var/turf/exit = get_step(src,(dir)) - if(exit.density) - say("Error! Part outlet is obstructed.") - return - if(temp) - left_part = temp - else if(being_built) - var/obj/I = being_built.build_path - left_part = {"Building [initial(I.name)].
- Please wait until completion...
"} +/obj/machinery/mecha_part_fabricator/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/sheetmaterials) + ) + +/obj/machinery/mecha_part_fabricator/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ExosuitFabricator") + ui.open() + +/obj/machinery/mecha_part_fabricator/ui_static_data(mob/user) + var/list/data = list() + + var/list/final_sets = list() + var/list/buildable_parts = list() + + for(var/part_set in part_sets) + final_sets += part_set + + for(var/v in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(v) + if(D.build_type & MECHFAB) + // This is for us. + var/list/part = output_part_info(D, TRUE) + + if(part["category_override"]) + for(var/cat in part["category_override"]) + buildable_parts[cat] += list(part) + if(!(cat in part_sets)) + final_sets += cat + continue + + for(var/cat in part_sets) + // Find all matching categories. + if(!(cat in D.category)) + continue + + buildable_parts[cat] += list(part) + + data["partSets"] = final_sets + data["buildableParts"] = buildable_parts + + return data + +/obj/machinery/mecha_part_fabricator/ui_data(mob/user) + var/list/data = list() + + data["materials"] = output_available_resources() + + if(being_built) + var/list/part = list( + "name" = being_built.name, + "duration" = build_finish - world.time, + "printTime" = get_construction_time_w_coeff(initial(being_built.construction_time)) + ) + data["buildingPart"] = part else - switch(screen) - if("main") - left_part = output_available_resources()+"
" - left_part += "Sync with R&D servers
" - for(var/part_set in part_sets) - left_part += "[part_set] - \[Add all parts to queue\]
" - if("parts") - left_part += output_parts_list(part_set) - left_part += "
Return" - dat = {" - [UTF8HEADER] - [name] - - - - - - - - - -
- [left_part] - - [list_queue()] -
- - "} - user << browse(dat, "window=mecha_fabricator;size=1000x430") - onclose(user, "mecha_fabricator") - return + data["buildingPart"] = null + + data["queue"] = list_queue() + + if(stored_part) + data["storedPart"] = stored_part.name + else + data["storedPart"] = null + + data["isProcessingQueue"] = process_queue + + return data -/obj/machinery/mecha_part_fabricator/Topic(href, href_list) +/obj/machinery/mecha_part_fabricator/ui_act(action, var/list/params) if(..()) - return - if(href_list["part_set"]) - var/tpart_set = href_list["part_set"] - if(tpart_set) - if(tpart_set=="clear") - part_set = null - else - part_set = tpart_set - screen = "parts" - if(href_list["part"]) - var/T = href_list["part"] - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(D.build_type & MECHFAB) - if(D.id == T) - if(!processing_queue) - build_part(D) - else - add_to_queue(D) - break - if(href_list["add_to_queue"]) - var/T = href_list["add_to_queue"] - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(D.build_type & MECHFAB) - if(D.id == T) + return TRUE + + . = TRUE + + add_fingerprint(usr) + usr.set_machine(src) + + switch(action) + if("sync_rnd") + // Sync with R&D Servers + sync() + return + if("add_queue_set") + // Add all parts of a set to queue + var/part_list = params["part_list"] + add_part_set_to_queue(part_list) + return + if("add_queue_part") + // Add a specific part to queue + var/T = params["id"] + for(var/v in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(v) + if((D.build_type & MECHFAB) && (D.id == T)) add_to_queue(D) break - return update_queue_on_page() - if(href_list["remove_from_queue"]) - remove_from_queue(text2num(href_list["remove_from_queue"])) - return update_queue_on_page() - if(href_list["partset_to_queue"]) - add_part_set_to_queue(href_list["partset_to_queue"]) - return update_queue_on_page() - if(href_list["process_queue"]) - spawn(0) - if(processing_queue || being_built) - return FALSE - processing_queue = 1 - process_queue() - processing_queue = 0 - if(href_list["clear_temp"]) - temp = null - if(href_list["screen"]) - screen = href_list["screen"] - if(href_list["queue_move"] && href_list["index"]) - var/index = text2num(href_list["index"]) - var/new_index = index + text2num(href_list["queue_move"]) - if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index)) - if(ISINRANGE(new_index,1,queue.len)) - queue.Swap(index,new_index) - return update_queue_on_page() - if(href_list["clear_queue"]) - queue = list() - return update_queue_on_page() - if(href_list["sync"]) - sync() - if(href_list["part_desc"]) - var/T = href_list["part_desc"] - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(D.build_type & MECHFAB) - if(D.id == T) - var/obj/part = D.build_path - temp = {"

[initial(part.name)] description:

- [initial(part.desc)]
- Return - "} - break + return + if("del_queue_part") + // Delete a specific from from the queue + var/index = text2num(params["index"]) + remove_from_queue(index) + return + if("clear_queue") + // Delete everything from queue + queue.Cut() + return + if("build_queue") + // Build everything in queue + if(process_queue) + return + process_queue = TRUE + + if(!being_built) + begin_processing() + return + if("stop_queue") + // Pause queue building. Also known as stop. + process_queue = FALSE + return + if("build_part") + // Build a single part + if(being_built || process_queue) + return - if(href_list["remove_mat"] && href_list["material"]) - eject_sheets(href_list["material"], text2num(href_list["remove_mat"])) + var/id = params["id"] + var/datum/design/D = SSresearch.techweb_design_by_id(id) - updateUsrDialog() - return + if(!(D.build_type & MECHFAB) || !(D.id == id)) + return -/obj/machinery/mecha_part_fabricator/proc/do_process_queue() - if(processing_queue || being_built) - return FALSE - processing_queue = 1 - process_queue() - processing_queue = 0 + if(build_part(D)) + on_start_printing() + begin_processing() + return + if("move_queue_part") + // Moves a part up or down in the queue. + var/index = text2num(params["index"]) + var/new_index = index + text2num(params["newindex"]) + if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index)) + if(ISINRANGE(new_index,1,length(queue))) + queue.Swap(index,new_index) + return + if("remove_mat") + // Remove a material from the fab + var/mat_ref = params["ref"] + var/amount = text2num(params["amount"]) + var/datum/material/mat = locate(mat_ref) + eject_sheets(mat, amount) + return + + return FALSE + +/** + * Eject material sheets. + * + * Returns the number of sheets successfully ejected. + * eject_sheet - Byond REF of the material to eject. + * eject_amt - Number of sheets to attempt to eject. + */ /obj/machinery/mecha_part_fabricator/proc/eject_sheets(eject_sheet, eject_amt) var/datum/component/material_container/mat_container = rmat.mat_container if (!mat_container) @@ -421,23 +629,26 @@ rmat.silo_log(src, "ejected", -count, "sheets", matlist) return count -/obj/machinery/mecha_part_fabricator/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted) - var/stack_name = material2name(id_inserted) - add_overlay("fab-load-[stack_name]") - addtimer(CALLBACK(src, /atom/proc/cut_overlay, "fab-load-[stack_name]"), 10) - updateUsrDialog() +/obj/machinery/mecha_part_fabricator/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted) + var/datum/material/M = id_inserted + add_overlay("fab-load-[M.name]") + addtimer(CALLBACK(src, /atom/proc/cut_overlay, "fab-load-[M.name]"), 10) -/obj/machinery/mecha_part_fabricator/attackby(obj/item/W, mob/user, params) - if(default_deconstruction_screwdriver(user, "fab-o", "fab-idle", W)) +/obj/machinery/mecha_part_fabricator/screwdriver_act(mob/living/user, obj/item/I) + if(..()) return TRUE + if(being_built) + to_chat(user, "\The [src] is currently processing! Please wait until completion.") + return FALSE + return default_deconstruction_screwdriver(user, "fab-o", "fab-idle", I) - if(default_deconstruction_crowbar(W)) +/obj/machinery/mecha_part_fabricator/crowbar_act(mob/living/user, obj/item/I) + if(..()) return TRUE - - return ..() - -/obj/machinery/mecha_part_fabricator/proc/material2name(ID) - return copytext(ID,2) + if(being_built) + to_chat(user, "\The [src] is currently processing! Please wait until completion.") + return FALSE + return default_deconstruction_crowbar(I) /obj/machinery/mecha_part_fabricator/proc/is_insertion_ready(mob/user) if(panel_open) diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 7bbb0f898d0..f2e5ababc18 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -9,7 +9,9 @@ var/locked = FALSE var/installed = 0 var/require_module = 0 - var/module_type = null + var/list/module_type = null + /// Bitflags listing module compatibility. Used in the exosuit fabricator for creating sub-categories. + var/list/module_flags = NONE // if true, is not stored in the robot to be ejected // if module is reset var/one_use = FALSE @@ -91,7 +93,8 @@ desc = "Used to cool a mounted disabler, increasing the potential current in it and thus its recharge rate." icon_state = "cyborg_upgrade3" require_module = 1 - module_type = /obj/item/robot_module/security + module_type = list(/obj/item/robot_module/security) + module_flags = BORG_MODULE_SECURITY /obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -139,7 +142,8 @@ desc = "A diamond drill replacement for the mining module's standard drill." icon_state = "cyborg_upgrade3" require_module = 1 - module_type = /obj/item/robot_module/miner + module_type = list(/obj/item/robot_module/miner) + module_flags = BORG_MODULE_MINER /obj/item/borg/upgrade/ddrill/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -171,7 +175,8 @@ desc = "A satchel of holding replacement for mining cyborg's ore satchel module." icon_state = "cyborg_upgrade3" require_module = 1 - module_type = /obj/item/robot_module/miner + module_type = list(/obj/item/robot_module/miner) + module_flags = BORG_MODULE_MINER /obj/item/borg/upgrade/soh/action(mob/living/silicon/robot/R) . = ..() @@ -198,7 +203,8 @@ desc = "A trash bag of holding replacement for the janiborg's standard trash bag." icon_state = "cyborg_upgrade3" require_module = 1 - module_type = /obj/item/robot_module/janitor + module_type = list(/obj/item/robot_module/janitor) + module_flags = BORG_MODULE_JANITOR /obj/item/borg/upgrade/tboh/action(mob/living/silicon/robot/R) . = ..() @@ -225,7 +231,8 @@ desc = "An advanced mop replacement for the janiborg's standard mop." icon_state = "cyborg_upgrade3" require_module = 1 - module_type = /obj/item/robot_module/janitor + module_type = list(/obj/item/robot_module/janitor) + module_flags = BORG_MODULE_JANITOR /obj/item/borg/upgrade/amop/action(mob/living/silicon/robot/R) . = ..() @@ -274,7 +281,8 @@ icon_state = "ash_plating" resistance_flags = LAVA_PROOF | FIRE_PROOF require_module = 1 - module_type = /obj/item/robot_module/miner + module_type = list(/obj/item/robot_module/miner) + module_flags = BORG_MODULE_MINER /obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -402,7 +410,8 @@ to produce more advanced and complex medical reagents." icon_state = "cyborg_upgrade3" require_module = 1 - module_type = /obj/item/robot_module/medical + module_type = list(/obj/item/robot_module/medical) + module_flags = BORG_MODULE_MEDICAL var/list/additional_reagents = list() /obj/item/borg/upgrade/hypospray/action(mob/living/silicon/robot/R, user = usr) @@ -458,7 +467,9 @@ defibrillator, for on the scene revival." icon_state = "cyborg_upgrade3" require_module = 1 - module_type = /obj/item/robot_module/medical + module_type = list(/obj/item/robot_module/medical) + module_flags = BORG_MODULE_MEDICAL + var/backpack = FALSE //True if we get the defib from a physical backpack unit rather than an upgrade card, so that we can return that upon deactivate() /obj/item/borg/upgrade/defib/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -480,7 +491,8 @@ out procedures" icon_state = "cyborg_upgrade3" require_module = 1 - module_type = /obj/item/robot_module/medical + module_type = list(/obj/item/robot_module/medical, /obj/item/robot_module/syndicate_medical) + module_flags = BORG_MODULE_MEDICAL /obj/item/borg/upgrade/processor/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -565,7 +577,8 @@ icon = 'icons/obj/storage.dmi' icon_state = "borgrped" require_module = TRUE - module_type = /obj/item/robot_module/engineering + module_type = list(/obj/item/robot_module/engineering, /obj/item/robot_module/saboteur) + module_flags = BORG_MODULE_ENGINEERING /obj/item/borg/upgrade/rped/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -593,7 +606,9 @@ icon = 'icons/obj/device.dmi' icon_state = "pinpointer_crew" require_module = TRUE - module_type = /obj/item/robot_module/medical + module_type = list(/obj/item/robot_module/medical, /obj/item/robot_module/syndicate_medical) + module_flags = BORG_MODULE_MEDICAL + var/datum/action/crew_monitor /obj/item/borg/upgrade/pinpointer/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -631,3 +646,85 @@ desc = "Allows you to to turn a cyborg into a clown, honk." icon_state = "cyborg_upgrade3" new_module = /obj/item/robot_module/clown + +/obj/item/borg/upgrade/circuit_app + name = "circuit manipulation apparatus" + desc = "An engineering cyborg upgrade allowing for manipulation of circuit boards." + icon_state = "cyborg_upgrade3" + require_module = TRUE + module_type = list(/obj/item/robot_module/engineering, /obj/item/robot_module/saboteur) + module_flags = BORG_MODULE_ENGINEERING + +/obj/item/borg/upgrade/circuit_app/action(mob/living/silicon/robot/R, user = usr) + . = ..() + if(.) + var/obj/item/borg/apparatus/circuit/C = locate() in R.module.modules + if(C) + to_chat(user, "This unit is already equipped with a circuit apparatus!") + return FALSE + + C = new(R.module) + R.module.basic_modules += C + R.module.add_module(C, FALSE, TRUE) + +/obj/item/borg/upgrade/circuit_app/deactivate(mob/living/silicon/robot/R, user = usr) + . = ..() + if (.) + var/obj/item/borg/apparatus/circuit/C = locate() in R.module.modules + if (C) + R.module.remove_module(C, TRUE) + +/obj/item/borg/upgrade/beaker_app + name = "beaker storage apparatus" + desc = "A supplementary beaker storage apparatus for medical cyborgs." + icon_state = "cyborg_upgrade3" + require_module = TRUE + module_type = list(/obj/item/robot_module/medical) + module_flags = BORG_MODULE_MEDICAL + +/obj/item/borg/upgrade/beaker_app/action(mob/living/silicon/robot/R, user = usr) + . = ..() + if(.) + var/obj/item/borg/apparatus/beaker/extra/E = locate() in R.module.modules + if(E) + to_chat(user, "This unit has no room for additional beaker storage!") + return FALSE + + E = new(R.module) + R.module.basic_modules += E + R.module.add_module(E, FALSE, TRUE) + +/obj/item/borg/upgrade/beaker_app/deactivate(mob/living/silicon/robot/R, user = usr) + . = ..() + if (.) + var/obj/item/borg/apparatus/beaker/extra/E = locate() in R.module.modules + if (E) + R.module.remove_module(E, TRUE) + +/obj/item/borg/upgrade/broomer + name = "experimental push broom" + desc = "An experimental push broom used for efficiently pushing refuse." + icon_state = "cyborg_upgrade3" + require_module = TRUE + module_type = list(/obj/item/robot_module/janitor) + module_flags = BORG_MODULE_JANITOR + +/obj/item/borg/upgrade/broomer/action(mob/living/silicon/robot/R, user = usr) + . = ..() + if (!.) + return + var/obj/item/pushbroom/cyborg/BR = locate() in R.module.modules + if (BR) + to_chat(user, "This janiborg is already equipped with an experimental broom!") + return FALSE + BR = new(R.module) + R.module.basic_modules += BR + R.module.add_module(BR, FALSE, TRUE) + +/obj/item/borg/upgrade/broomer/deactivate(mob/living/silicon/robot/R, user = usr) + . = ..() + if (!.) + return + var/obj/item/pushbroom/cyborg/BR = locate() in R.module.modules + if (BR) + R.module.remove_module(BR, TRUE) diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm index 9eb30ef10d0..1fd381dfcc5 100644 --- a/code/modules/asset_cache/asset_list_items.dm +++ b/code/modules/asset_cache/asset_list_items.dm @@ -1,351 +1,408 @@ -//DEFINITIONS FOR ASSET DATUMS START HERE. - -/datum/asset/simple/tgui - assets = list( - // tgui - "tgui.css" = 'tgui/assets/tgui.css', - "tgui.js" = 'tgui/assets/tgui.js', - // tgui-next - "tgui-main.html" = 'tgui-next/packages/tgui/public/tgui-main.html', - "tgui-fallback.html" = 'tgui-next/packages/tgui/public/tgui-fallback.html', - "tgui.bundle.js" = 'tgui-next/packages/tgui/public/tgui.bundle.js', - "tgui.bundle.css" = 'tgui-next/packages/tgui/public/tgui.bundle.css', - "shim-html5shiv.js" = 'tgui-next/packages/tgui/public/shim-html5shiv.js', - "shim-ie8.js" = 'tgui-next/packages/tgui/public/shim-ie8.js', - "shim-dom4.js" = 'tgui-next/packages/tgui/public/shim-dom4.js', - "shim-css-om.js" = 'tgui-next/packages/tgui/public/shim-css-om.js', - ) - -/datum/asset/simple/font - assets = list( - "runes.ttf" = 'hippiestation/interface/runes.ttf' - ) - -/datum/asset/group/tgui - children = list( - /datum/asset/simple/tgui, - /datum/asset/simple/fontawesome - ) - -/datum/asset/simple/headers - assets = list( - "alarm_green.gif" = 'icons/program_icons/alarm_green.gif', - "alarm_red.gif" = 'icons/program_icons/alarm_red.gif', - "batt_5.gif" = 'icons/program_icons/batt_5.gif', - "batt_20.gif" = 'icons/program_icons/batt_20.gif', - "batt_40.gif" = 'icons/program_icons/batt_40.gif', - "batt_60.gif" = 'icons/program_icons/batt_60.gif', - "batt_80.gif" = 'icons/program_icons/batt_80.gif', - "batt_100.gif" = 'icons/program_icons/batt_100.gif', - "charging.gif" = 'icons/program_icons/charging.gif', - "downloader_finished.gif" = 'icons/program_icons/downloader_finished.gif', - "downloader_running.gif" = 'icons/program_icons/downloader_running.gif', - "ntnrc_idle.gif" = 'icons/program_icons/ntnrc_idle.gif', - "ntnrc_new.gif" = 'icons/program_icons/ntnrc_new.gif', - "power_norm.gif" = 'icons/program_icons/power_norm.gif', - "power_warn.gif" = 'icons/program_icons/power_warn.gif', - "sig_high.gif" = 'icons/program_icons/sig_high.gif', - "sig_low.gif" = 'icons/program_icons/sig_low.gif', - "sig_lan.gif" = 'icons/program_icons/sig_lan.gif', - "sig_none.gif" = 'icons/program_icons/sig_none.gif', - "smmon_0.gif" = 'icons/program_icons/smmon_0.gif', - "smmon_1.gif" = 'icons/program_icons/smmon_1.gif', - "smmon_2.gif" = 'icons/program_icons/smmon_2.gif', - "smmon_3.gif" = 'icons/program_icons/smmon_3.gif', - "smmon_4.gif" = 'icons/program_icons/smmon_4.gif', - "smmon_5.gif" = 'icons/program_icons/smmon_5.gif', - "smmon_6.gif" = 'icons/program_icons/smmon_6.gif' - ) - -/datum/asset/spritesheet/simple/pda - name = "pda" - assets = list( - "atmos" = 'icons/pda_icons/pda_atmos.png', - "back" = 'icons/pda_icons/pda_back.png', - "bell" = 'icons/pda_icons/pda_bell.png', - "blank" = 'icons/pda_icons/pda_blank.png', - "boom" = 'icons/pda_icons/pda_boom.png', - "bucket" = 'icons/pda_icons/pda_bucket.png', - "medbot" = 'icons/pda_icons/pda_medbot.png', - "floorbot" = 'icons/pda_icons/pda_floorbot.png', - "cleanbot" = 'icons/pda_icons/pda_cleanbot.png', - "crate" = 'icons/pda_icons/pda_crate.png', - "cuffs" = 'icons/pda_icons/pda_cuffs.png', - "eject" = 'icons/pda_icons/pda_eject.png', - "flashlight" = 'icons/pda_icons/pda_flashlight.png', - "honk" = 'icons/pda_icons/pda_honk.png', - "mail" = 'icons/pda_icons/pda_mail.png', - "medical" = 'icons/pda_icons/pda_medical.png', - "menu" = 'icons/pda_icons/pda_menu.png', - "mule" = 'icons/pda_icons/pda_mule.png', - "notes" = 'icons/pda_icons/pda_notes.png', - "power" = 'icons/pda_icons/pda_power.png', - "rdoor" = 'icons/pda_icons/pda_rdoor.png', - "reagent" = 'icons/pda_icons/pda_reagent.png', - "refresh" = 'icons/pda_icons/pda_refresh.png', - "scanner" = 'icons/pda_icons/pda_scanner.png', - "signaler" = 'icons/pda_icons/pda_signaler.png', - "status" = 'icons/pda_icons/pda_status.png', - "dronephone" = 'icons/pda_icons/pda_dronephone.png' - ) - -/datum/asset/spritesheet/simple/paper - name = "paper" - assets = list( - "stamp-clown" = 'icons/stamp_icons/large_stamp-clown.png', - "stamp-deny" = 'icons/stamp_icons/large_stamp-deny.png', - "stamp-ok" = 'icons/stamp_icons/large_stamp-ok.png', - "stamp-hop" = 'icons/stamp_icons/large_stamp-hop.png', - "stamp-cmo" = 'icons/stamp_icons/large_stamp-cmo.png', - "stamp-ce" = 'icons/stamp_icons/large_stamp-ce.png', - "stamp-hos" = 'icons/stamp_icons/large_stamp-hos.png', - "stamp-rd" = 'icons/stamp_icons/large_stamp-rd.png', - "stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png', - "stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png', - "stamp-law" = 'icons/stamp_icons/large_stamp-law.png' - ) - - -/datum/asset/simple/IRV - assets = list( - "jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js', - ) - -/datum/asset/group/IRV - children = list( - /datum/asset/simple/jquery, - /datum/asset/simple/IRV - ) - -/datum/asset/simple/changelog - assets = list( - "88x31.png" = 'html/88x31.png', - "bug-minus.png" = 'html/bug-minus.png', - "cross-circle.png" = 'html/cross-circle.png', - "hard-hat-exclamation.png" = 'html/hard-hat-exclamation.png', - "image-minus.png" = 'html/image-minus.png', - "image-plus.png" = 'html/image-plus.png', - "music-minus.png" = 'html/music-minus.png', - "music-plus.png" = 'html/music-plus.png', - "tick-circle.png" = 'html/tick-circle.png', - "wrench-screwdriver.png" = 'html/wrench-screwdriver.png', - "spell-check.png" = 'html/spell-check.png', - "burn-exclamation.png" = 'html/burn-exclamation.png', - "chevron.png" = 'html/chevron.png', - "chevron-expand.png" = 'html/chevron-expand.png', - "scales.png" = 'html/scales.png', - "coding.png" = 'html/coding.png', - "ban.png" = 'html/ban.png', - "chrome-wrench.png" = 'html/chrome-wrench.png', - "changelog.css" = 'html/changelog.css' - ) - -/datum/asset/group/goonchat - children = list( - /datum/asset/simple/jquery, - /datum/asset/simple/goonchat, - /datum/asset/spritesheet/goonchat, - /datum/asset/simple/fontawesome - ) - -/datum/asset/simple/jquery - assets = list( - "jquery.min.js" = 'code/modules/goonchat/browserassets/js/jquery.min.js', - ) - -/datum/asset/simple/goonchat - assets = list( - "json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js', - "browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js', - "browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css', - "browserOutput_white.css" = 'code/modules/goonchat/browserassets/css/browserOutput_white.css', - ) - -/datum/asset/simple/fontawesome - assets = list( - "fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot', - "fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff', - "fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot', - "fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff', - "font-awesome.css" = 'html/font-awesome/css/all.min.css', - "v4shim.css" = 'html/font-awesome/css/v4-shims.min.css' - ) - -/datum/asset/spritesheet/goonchat - name = "chat" - -/datum/asset/spritesheet/goonchat/register() - InsertAll("emoji", 'icons/emoji.dmi') - - // pre-loading all lanugage icons also helps to avoid meta - InsertAll("language", 'icons/misc/language.dmi') - // catch languages which are pulling icons from another file - for(var/path in typesof(/datum/language)) - var/datum/language/L = path - var/icon = initial(L.icon) - if (icon != 'icons/misc/language.dmi') - var/icon_state = initial(L.icon_state) - Insert("language-[icon_state]", icon, icon_state=icon_state) - - ..() - -/datum/asset/simple/permissions - assets = list( - "padlock.png" = 'html/padlock.png' - ) - -/datum/asset/simple/notes - assets = list( - "high_button.png" = 'html/high_button.png', - "medium_button.png" = 'html/medium_button.png', - "minor_button.png" = 'html/minor_button.png', - "none_button.png" = 'html/none_button.png', - ) - -/datum/asset/spritesheet/simple/pills - name ="pills" - assets = list( - "pill1" = 'icons/UI_Icons/Pills/pill1.png', - "pill2" = 'icons/UI_Icons/Pills/pill2.png', - "pill3" = 'icons/UI_Icons/Pills/pill3.png', - "pill4" = 'icons/UI_Icons/Pills/pill4.png', - "pill5" = 'icons/UI_Icons/Pills/pill5.png', - "pill6" = 'icons/UI_Icons/Pills/pill6.png', - "pill7" = 'icons/UI_Icons/Pills/pill7.png', - "pill8" = 'icons/UI_Icons/Pills/pill8.png', - "pill9" = 'icons/UI_Icons/Pills/pill9.png', - "pill10" = 'icons/UI_Icons/Pills/pill10.png', - "pill11" = 'icons/UI_Icons/Pills/pill11.png', - "pill12" = 'icons/UI_Icons/Pills/pill12.png', - "pill13" = 'icons/UI_Icons/Pills/pill13.png', - "pill14" = 'icons/UI_Icons/Pills/pill14.png', - "pill15" = 'icons/UI_Icons/Pills/pill15.png', - "pill16" = 'icons/UI_Icons/Pills/pill16.png', - "pill17" = 'icons/UI_Icons/Pills/pill17.png', - "pill18" = 'icons/UI_Icons/Pills/pill18.png', - "pill19" = 'icons/UI_Icons/Pills/pill19.png', - "pill20" = 'icons/UI_Icons/Pills/pill20.png', - "pill21" = 'icons/UI_Icons/Pills/pill21.png', - "pill22" = 'icons/UI_Icons/Pills/pill22.png', - ) - -//this exists purely to avoid meta by pre-loading all language icons. -/datum/asset/language/register() - for(var/path in typesof(/datum/language)) - set waitfor = FALSE - var/datum/language/L = new path () - L.get_icon() - -/datum/asset/spritesheet/pipes - name = "pipes" - -/datum/asset/spritesheet/pipes/register() - for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi', 'icons/obj/atmospherics/pipes/transit_tube.dmi', 'icons/obj/plumbing/fluid_ducts.dmi')) - InsertAll("", each, GLOB.alldirs) - ..() - -// Representative icons for each research design -/datum/asset/spritesheet/research_designs - name = "design" - -/datum/asset/spritesheet/research_designs/register() - for (var/path in subtypesof(/datum/design)) - var/datum/design/D = path - - var/icon_file - var/icon_state - var/icon/I - - if(initial(D.research_icon) && initial(D.research_icon_state)) //If the design has an icon replacement skip the rest - icon_file = initial(D.research_icon) - icon_state = initial(D.research_icon_state) - if(!(icon_state in icon_states(icon_file))) - warning("design [D] with icon '[icon_file]' missing state '[icon_state]'") - continue - I = icon(icon_file, icon_state, SOUTH) - - else - // construct the icon and slap it into the resource cache - var/atom/item = initial(D.build_path) - if (!ispath(item, /atom)) - // biogenerator outputs to beakers by default - if (initial(D.build_type) & BIOGENERATOR) - item = /obj/item/reagent_containers/glass/beaker/large - else - continue // shouldn't happen, but just in case - - // circuit boards become their resulting machines or computers - if (ispath(item, /obj/item/circuitboard)) - var/obj/item/circuitboard/C = item - var/machine = initial(C.build_path) - if (machine) - item = machine - - icon_file = initial(item.icon) - icon_state = initial(item.icon_state) - - if(!(icon_state in icon_states(icon_file))) - warning("design [D] with icon '[icon_file]' missing state '[icon_state]'") - continue - I = icon(icon_file, icon_state, SOUTH) - - // computers (and snowflakes) get their screen and keyboard sprites - if (ispath(item, /obj/machinery/computer) || ispath(item, /obj/machinery/power/solar_control)) - var/obj/machinery/computer/C = item - var/screen = initial(C.icon_screen) - var/keyboard = initial(C.icon_keyboard) - var/all_states = icon_states(icon_file) - if (screen && (screen in all_states)) - I.Blend(icon(icon_file, screen, SOUTH), ICON_OVERLAY) - if (keyboard && (keyboard in all_states)) - I.Blend(icon(icon_file, keyboard, SOUTH), ICON_OVERLAY) - - Insert(initial(D.id), I) - return ..() - -/datum/asset/spritesheet/vending - name = "vending" - -/datum/asset/spritesheet/vending/register() - for (var/k in GLOB.vending_products) - var/atom/item = k - - - var/icon_file - var/icon_state - var/icon/I - - - if (!ispath(item, /atom)) - continue - - icon_file = initial(item.icon) - icon_state = initial(item.icon_state) - - if(icon_state in icon_states(icon_file)) - I = icon(icon_file, icon_state, SOUTH) - var/c = initial(item.color) - if (!isnull(c) && c != "#FFFFFF") - I.Blend(initial(c), ICON_MULTIPLY) - else - item = new item() - I = icon(item.icon, item.icon_state, SOUTH) - qdel(item) - - var/imgid = replacetext(replacetext("[item]", "/obj/item/", ""), "/", "-") - - Insert(imgid, I) - return ..() - -/datum/asset/simple/genetics - assets = list( - "dna_discovered.png" = 'html/dna_discovered.png', - "dna_undiscovered.png" = 'html/dna_undiscovered.png', - "dna_extra.png" = 'html/dna_extra.png' -) +//DEFINITIONS FOR ASSET DATUMS START HERE. +/datum/asset/simple/tgui + assets = list( + // tgui + "tgui.css" = 'tgui/assets/tgui.css', + "tgui.js" = 'tgui/assets/tgui.js', + // tgui-next + "tgui-main.html" = 'tgui-next/packages/tgui/public/tgui-main.html', + "tgui-fallback.html" = 'tgui-next/packages/tgui/public/tgui-fallback.html', + "tgui.bundle.js" = 'tgui-next/packages/tgui/public/tgui.bundle.js', + "tgui.bundle.css" = 'tgui-next/packages/tgui/public/tgui.bundle.css', + "shim-html5shiv.js" = 'tgui-next/packages/tgui/public/shim-html5shiv.js', + "shim-ie8.js" = 'tgui-next/packages/tgui/public/shim-ie8.js', + "shim-dom4.js" = 'tgui-next/packages/tgui/public/shim-dom4.js', + "shim-css-om.js" = 'tgui-next/packages/tgui/public/shim-css-om.js', + ) + +/datum/asset/simple/font + assets = list( + "runes.ttf" = 'hippiestation/interface/runes.ttf' + ) + +/datum/asset/group/tgui + children = list( + /datum/asset/simple/tgui, + /datum/asset/simple/fontawesome + ) + +/datum/asset/simple/headers + assets = list( + "alarm_green.gif" = 'icons/program_icons/alarm_green.gif', + "alarm_red.gif" = 'icons/program_icons/alarm_red.gif', + "batt_5.gif" = 'icons/program_icons/batt_5.gif', + "batt_20.gif" = 'icons/program_icons/batt_20.gif', + "batt_40.gif" = 'icons/program_icons/batt_40.gif', + "batt_60.gif" = 'icons/program_icons/batt_60.gif', + "batt_80.gif" = 'icons/program_icons/batt_80.gif', + "batt_100.gif" = 'icons/program_icons/batt_100.gif', + "charging.gif" = 'icons/program_icons/charging.gif', + "downloader_finished.gif" = 'icons/program_icons/downloader_finished.gif', + "downloader_running.gif" = 'icons/program_icons/downloader_running.gif', + "ntnrc_idle.gif" = 'icons/program_icons/ntnrc_idle.gif', + "ntnrc_new.gif" = 'icons/program_icons/ntnrc_new.gif', + "power_norm.gif" = 'icons/program_icons/power_norm.gif', + "power_warn.gif" = 'icons/program_icons/power_warn.gif', + "sig_high.gif" = 'icons/program_icons/sig_high.gif', + "sig_low.gif" = 'icons/program_icons/sig_low.gif', + "sig_lan.gif" = 'icons/program_icons/sig_lan.gif', + "sig_none.gif" = 'icons/program_icons/sig_none.gif', + "smmon_0.gif" = 'icons/program_icons/smmon_0.gif', + "smmon_1.gif" = 'icons/program_icons/smmon_1.gif', + "smmon_2.gif" = 'icons/program_icons/smmon_2.gif', + "smmon_3.gif" = 'icons/program_icons/smmon_3.gif', + "smmon_4.gif" = 'icons/program_icons/smmon_4.gif', + "smmon_5.gif" = 'icons/program_icons/smmon_5.gif', + "smmon_6.gif" = 'icons/program_icons/smmon_6.gif' + ) + +/datum/asset/spritesheet/simple/pda + name = "pda" + assets = list( + "atmos" = 'icons/pda_icons/pda_atmos.png', + "back" = 'icons/pda_icons/pda_back.png', + "bell" = 'icons/pda_icons/pda_bell.png', + "blank" = 'icons/pda_icons/pda_blank.png', + "boom" = 'icons/pda_icons/pda_boom.png', + "bucket" = 'icons/pda_icons/pda_bucket.png', + "medbot" = 'icons/pda_icons/pda_medbot.png', + "floorbot" = 'icons/pda_icons/pda_floorbot.png', + "cleanbot" = 'icons/pda_icons/pda_cleanbot.png', + "crate" = 'icons/pda_icons/pda_crate.png', + "cuffs" = 'icons/pda_icons/pda_cuffs.png', + "eject" = 'icons/pda_icons/pda_eject.png', + "flashlight" = 'icons/pda_icons/pda_flashlight.png', + "honk" = 'icons/pda_icons/pda_honk.png', + "mail" = 'icons/pda_icons/pda_mail.png', + "medical" = 'icons/pda_icons/pda_medical.png', + "menu" = 'icons/pda_icons/pda_menu.png', + "mule" = 'icons/pda_icons/pda_mule.png', + "notes" = 'icons/pda_icons/pda_notes.png', + "power" = 'icons/pda_icons/pda_power.png', + "rdoor" = 'icons/pda_icons/pda_rdoor.png', + "reagent" = 'icons/pda_icons/pda_reagent.png', + "refresh" = 'icons/pda_icons/pda_refresh.png', + "scanner" = 'icons/pda_icons/pda_scanner.png', + "signaler" = 'icons/pda_icons/pda_signaler.png', + "status" = 'icons/pda_icons/pda_status.png', + "dronephone" = 'icons/pda_icons/pda_dronephone.png' + ) + +/datum/asset/spritesheet/simple/paper + name = "paper" + assets = list( + "stamp-clown" = 'icons/stamp_icons/large_stamp-clown.png', + "stamp-deny" = 'icons/stamp_icons/large_stamp-deny.png', + "stamp-ok" = 'icons/stamp_icons/large_stamp-ok.png', + "stamp-hop" = 'icons/stamp_icons/large_stamp-hop.png', + "stamp-cmo" = 'icons/stamp_icons/large_stamp-cmo.png', + "stamp-ce" = 'icons/stamp_icons/large_stamp-ce.png', + "stamp-hos" = 'icons/stamp_icons/large_stamp-hos.png', + "stamp-rd" = 'icons/stamp_icons/large_stamp-rd.png', + "stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png', + "stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png', + "stamp-law" = 'icons/stamp_icons/large_stamp-law.png' + ) + + +/datum/asset/simple/IRV + assets = list( + "jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js', + ) + +/datum/asset/group/IRV + children = list( + /datum/asset/simple/jquery, + /datum/asset/simple/IRV + ) + +/datum/asset/simple/changelog + assets = list( + "88x31.png" = 'html/88x31.png', + "bug-minus.png" = 'html/bug-minus.png', + "cross-circle.png" = 'html/cross-circle.png', + "hard-hat-exclamation.png" = 'html/hard-hat-exclamation.png', + "image-minus.png" = 'html/image-minus.png', + "image-plus.png" = 'html/image-plus.png', + "music-minus.png" = 'html/music-minus.png', + "music-plus.png" = 'html/music-plus.png', + "tick-circle.png" = 'html/tick-circle.png', + "wrench-screwdriver.png" = 'html/wrench-screwdriver.png', + "spell-check.png" = 'html/spell-check.png', + "burn-exclamation.png" = 'html/burn-exclamation.png', + "chevron.png" = 'html/chevron.png', + "chevron-expand.png" = 'html/chevron-expand.png', + "scales.png" = 'html/scales.png', + "coding.png" = 'html/coding.png', + "ban.png" = 'html/ban.png', + "chrome-wrench.png" = 'html/chrome-wrench.png', + "changelog.css" = 'html/changelog.css' + ) + +/datum/asset/group/goonchat + children = list( + /datum/asset/simple/jquery, + /datum/asset/simple/goonchat, + /datum/asset/spritesheet/goonchat, + /datum/asset/simple/fontawesome + ) + +/datum/asset/simple/jquery + assets = list( + "jquery.min.js" = 'code/modules/goonchat/browserassets/js/jquery.min.js', + ) + +/datum/asset/simple/goonchat + assets = list( + "json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js', + "browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js', + "browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css', + "browserOutput_white.css" = 'code/modules/goonchat/browserassets/css/browserOutput_white.css', + ) + +/datum/asset/simple/fontawesome + assets = list( + "fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot', + "fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff', + "fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot', + "fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff', + "font-awesome.css" = 'html/font-awesome/css/all.min.css', + "v4shim.css" = 'html/font-awesome/css/v4-shims.min.css' + ) + +/datum/asset/spritesheet/goonchat + name = "chat" + +/datum/asset/spritesheet/goonchat/register() + InsertAll("emoji", 'icons/emoji.dmi') + + // pre-loading all lanugage icons also helps to avoid meta + InsertAll("language", 'icons/misc/language.dmi') + // catch languages which are pulling icons from another file + for(var/path in typesof(/datum/language)) + var/datum/language/L = path + var/icon = initial(L.icon) + if (icon != 'icons/misc/language.dmi') + var/icon_state = initial(L.icon_state) + Insert("language-[icon_state]", icon, icon_state=icon_state) + + ..() + +/datum/asset/simple/permissions + assets = list( + "padlock.png" = 'html/padlock.png' + ) + +/datum/asset/simple/notes + assets = list( + "high_button.png" = 'html/high_button.png', + "medium_button.png" = 'html/medium_button.png', + "minor_button.png" = 'html/minor_button.png', + "none_button.png" = 'html/none_button.png', + ) + +/datum/asset/simple/arcade + assets = list( + "boss1.gif" = 'icons/UI_Icons/Arcade/boss1.gif', + "boss2.gif" = 'icons/UI_Icons/Arcade/boss2.gif', + "boss3.gif" = 'icons/UI_Icons/Arcade/boss3.gif', + "boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif', + "boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif', + "boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif', + ) + +/datum/asset/spritesheet/simple/achievements + name ="achievements" + assets = list( + "default" = 'icons/UI_Icons/Achievements/default.png', + "basemisc" = 'icons/UI_Icons/Achievements/basemisc.png', + "baseboss" = 'icons/UI_Icons/Achievements/baseboss.png', + "baseskill" = 'icons/UI_Icons/Achievements/baseskill.png', + "bbgum" = 'icons/UI_Icons/Achievements/Boss/bbgum.png', + "colossus" = 'icons/UI_Icons/Achievements/Boss/colossus.png', + "hierophant" = 'icons/UI_Icons/Achievements/Boss/hierophant.png', + "legion" = 'icons/UI_Icons/Achievements/Boss/legion.png', + "miner" = 'icons/UI_Icons/Achievements/Boss/miner.png', + "swarmer" = 'icons/UI_Icons/Achievements/Boss/swarmer.png', + "tendril" = 'icons/UI_Icons/Achievements/Boss/tendril.png', + "featofstrength" = 'icons/UI_Icons/Achievements/Misc/featofstrength.png', + "helbital" = 'icons/UI_Icons/Achievements/Misc/helbital.png', + "jackpot" = 'icons/UI_Icons/Achievements/Misc/jackpot.png', + "meteors" = 'icons/UI_Icons/Achievements/Misc/meteors.png', + "timewaste" = 'icons/UI_Icons/Achievements/Misc/timewaste.png', + "upgrade" = 'icons/UI_Icons/Achievements/Misc/upgrade.png', + "clownking" = 'icons/UI_Icons/Achievements/Misc/clownking.png', + "clownthanks" = 'icons/UI_Icons/Achievements/Misc/clownthanks.png', + "rule8" = 'icons/UI_Icons/Achievements/Misc/rule8.png', + "snail" = 'icons/UI_Icons/Achievements/Misc/snail.png', + "mining" = 'icons/UI_Icons/Achievements/Skills/mining.png', + ) + +/datum/asset/spritesheet/simple/pills + name ="pills" + assets = list( + "pill1" = 'icons/UI_Icons/Pills/pill1.png', + "pill2" = 'icons/UI_Icons/Pills/pill2.png', + "pill3" = 'icons/UI_Icons/Pills/pill3.png', + "pill4" = 'icons/UI_Icons/Pills/pill4.png', + "pill5" = 'icons/UI_Icons/Pills/pill5.png', + "pill6" = 'icons/UI_Icons/Pills/pill6.png', + "pill7" = 'icons/UI_Icons/Pills/pill7.png', + "pill8" = 'icons/UI_Icons/Pills/pill8.png', + "pill9" = 'icons/UI_Icons/Pills/pill9.png', + "pill10" = 'icons/UI_Icons/Pills/pill10.png', + "pill11" = 'icons/UI_Icons/Pills/pill11.png', + "pill12" = 'icons/UI_Icons/Pills/pill12.png', + "pill13" = 'icons/UI_Icons/Pills/pill13.png', + "pill14" = 'icons/UI_Icons/Pills/pill14.png', + "pill15" = 'icons/UI_Icons/Pills/pill15.png', + "pill16" = 'icons/UI_Icons/Pills/pill16.png', + "pill17" = 'icons/UI_Icons/Pills/pill17.png', + "pill18" = 'icons/UI_Icons/Pills/pill18.png', + "pill19" = 'icons/UI_Icons/Pills/pill19.png', + "pill20" = 'icons/UI_Icons/Pills/pill20.png', + "pill21" = 'icons/UI_Icons/Pills/pill21.png', + "pill22" = 'icons/UI_Icons/Pills/pill22.png', + ) + +//this exists purely to avoid meta by pre-loading all language icons. +/datum/asset/language/register() + for(var/path in typesof(/datum/language)) + set waitfor = FALSE + var/datum/language/L = new path () + L.get_icon() + +/datum/asset/spritesheet/pipes + name = "pipes" + +/datum/asset/spritesheet/pipes/register() + for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi', 'icons/obj/atmospherics/pipes/transit_tube.dmi', 'icons/obj/plumbing/fluid_ducts.dmi')) + InsertAll("", each, GLOB.alldirs) + ..() + +// Representative icons for each research design +/datum/asset/spritesheet/research_designs + name = "design" + +/datum/asset/spritesheet/research_designs/register() + for (var/path in subtypesof(/datum/design)) + var/datum/design/D = path + + var/icon_file + var/icon_state + var/icon/I + + if(initial(D.research_icon) && initial(D.research_icon_state)) //If the design has an icon replacement skip the rest + icon_file = initial(D.research_icon) + icon_state = initial(D.research_icon_state) + if(!(icon_state in icon_states(icon_file))) + warning("design [D] with icon '[icon_file]' missing state '[icon_state]'") + continue + I = icon(icon_file, icon_state, SOUTH) + + else + // construct the icon and slap it into the resource cache + var/atom/item = initial(D.build_path) + if (!ispath(item, /atom)) + // biogenerator outputs to beakers by default + if (initial(D.build_type) & BIOGENERATOR) + item = /obj/item/reagent_containers/glass/beaker/large + else + continue // shouldn't happen, but just in case + + // circuit boards become their resulting machines or computers + if (ispath(item, /obj/item/circuitboard)) + var/obj/item/circuitboard/C = item + var/machine = initial(C.build_path) + if (machine) + item = machine + + icon_file = initial(item.icon) + icon_state = initial(item.icon_state) + + if(!(icon_state in icon_states(icon_file))) + warning("design [D] with icon '[icon_file]' missing state '[icon_state]'") + continue + I = icon(icon_file, icon_state, SOUTH) + + // computers (and snowflakes) get their screen and keyboard sprites + if (ispath(item, /obj/machinery/computer) || ispath(item, /obj/machinery/power/solar_control)) + var/obj/machinery/computer/C = item + var/screen = initial(C.icon_screen) + var/keyboard = initial(C.icon_keyboard) + var/all_states = icon_states(icon_file) + if (screen && (screen in all_states)) + I.Blend(icon(icon_file, screen, SOUTH), ICON_OVERLAY) + if (keyboard && (keyboard in all_states)) + I.Blend(icon(icon_file, keyboard, SOUTH), ICON_OVERLAY) + + Insert(initial(D.id), I) + return ..() + +/datum/asset/spritesheet/vending + name = "vending" + +/datum/asset/spritesheet/vending/register() + for (var/k in GLOB.vending_products) + var/atom/item = k + + + var/icon_file + var/icon_state + var/icon/I + + + if (!ispath(item, /atom)) + continue + + icon_file = initial(item.icon) + icon_state = initial(item.icon_state) + + if(icon_state in icon_states(icon_file)) + I = icon(icon_file, icon_state, SOUTH) + var/c = initial(item.color) + if (!isnull(c) && c != "#FFFFFF") + I.Blend(initial(c), ICON_MULTIPLY) + else + item = new item() + I = icon(item.icon, item.icon_state, SOUTH) + qdel(item) + + var/imgid = replacetext(replacetext("[item]", "/obj/item/", ""), "/", "-") + + Insert(imgid, I) + return ..() + +/datum/asset/simple/genetics + assets = list( + "dna_discovered.png" = 'html/dna_discovered.png', + "dna_undiscovered.png" = 'html/dna_undiscovered.png', + "dna_extra.png" = 'html/dna_extra.png' +) + + +/datum/asset/simple/vv + assets = list( + "view_variables.css" = 'html/admin/view_variables.css' + ) + +/datum/asset/simple/orbit + assets = list( + "ghost.png" = 'html/ghost.png' + ) /datum/asset/simple/vv assets = list( "view_variables.css" = 'html/admin/view_variables.css' ) + +/datum/asset/spritesheet/sheetmaterials + name = "sheetmaterials" + +/datum/asset/spritesheet/sheetmaterials/register() + InsertAll("", 'icons/obj/stack_objects.dmi') + + // Special case to handle Bluespace Crystals + Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal") + ..() diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index 440ce4d3ab0..6e20bc5815c 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -226,7 +226,8 @@ icon_state = "modkit" w_class = WEIGHT_CLASS_SMALL require_module = 1 - module_type = /obj/item/robot_module/miner + module_type = list(/obj/item/robot_module/miner) + module_flags = BORG_MODULE_MINER var/denied_type = null var/maximum_of_type = 1 var/cost = 30 diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index 5cbe9a6f163..d7057dbf78c 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -48,6 +48,8 @@ other types of metals and chemistry for reagents). var/research_icon //Replaces the item icon in the research console var/research_icon_state var/icon_cache + /// Optional string that interfaces can use as part of search filters. See- item/borg/upgrade/ai and the Exosuit Fabs. + var/search_metadata /datum/design/error_design name = "ERROR" diff --git a/code/modules/research/designs/mecha_designs.dm b/code/modules/research/designs/mecha_designs.dm index 892d32ddd08..f6969b9c062 100644 --- a/code/modules/research/designs/mecha_designs.dm +++ b/code/modules/research/designs/mecha_designs.dm @@ -228,7 +228,7 @@ category = list("Exosuit Equipment") /datum/design/clusterbang_launcher - name = "Exosuit Module (SOB-3 Clusterbang Launcher)" + name = "Exosuit Weapon (SOB-3 Clusterbang Launcher)" desc = "A weapon that violates the Geneva Convention at 3 rounds per minute" id = "clusterbang_launcher" build_type = MECHFAB @@ -318,7 +318,7 @@ category = list("Exosuit Equipment") /datum/design/mech_diamond_drill - name = "Exosuit Module (Diamond Mining Drill)" + name = "Exosuit Mining (Diamond Mining Drill)" desc = "An upgraded version of the standard drill." id = "mech_diamond_drill" build_type = MECHFAB @@ -338,7 +338,7 @@ category = list("Exosuit Equipment") /datum/design/mech_plasma_cutter - name = "Exosuit Module Design (217-D Heavy Plasma Cutter)" + name = "Exosuit Mining (217-D Heavy Plasma Cutter)" desc = "A device that shoots resonant plasma bursts at extreme velocity. The blasts are capable of crushing rock and demolishing solid obstacles." id = "mech_plasma_cutter" build_type = MECHFAB @@ -358,7 +358,7 @@ category = list("Exosuit Equipment") /datum/design/mech_sleeper - name = "Exosuit Medical Equipment (Mounted Sleeper)" + name = "Exosuit Medical (Mounted Sleeper)" desc = "Equipment for medical exosuits. A mounted sleeper that stabilizes patients and can inject reagents in the exosuit's reserves." id = "mech_sleeper" build_type = MECHFAB @@ -368,7 +368,7 @@ category = list("Exosuit Equipment") /datum/design/mech_syringe_gun - name = "Exosuit Medical Equipment (Syringe Gun)" + name = "Exosuit Medical (Syringe Gun)" desc = "Equipment for medical exosuits. A chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur." id = "mech_syringe_gun" build_type = MECHFAB @@ -378,7 +378,7 @@ category = list("Exosuit Equipment") /datum/design/mech_medical_beamgun - name = "Exosuit Medical Equipment (Medical Beamgun)" + name = "Exosuit Medical (Medical Beamgun)" desc = "Equipment for medical exosuits. A mounted medical nanite projector which will treat patients with a focused beam." id = "mech_medi_beam" build_type = MECHFAB diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 0d56dbc8a47..e87f25b4b90 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -477,7 +477,7 @@ //Exosuit Equipment /datum/design/ripleyupgrade - name = "Ripley MK-1 to MK-II conversion kit" + name = "Ripley MK-I to MK-II conversion kit" id = "ripleyupgrade" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/ripleyupgrade @@ -486,7 +486,7 @@ category = list("Exosuit Equipment") /datum/design/mech_hydraulic_clamp - name = "Exosuit Engineering Equipment (Hydraulic Clamp)" + name = "Exosuit Engineering (Hydraulic Clamp)" id = "mech_hydraulic_clamp" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp @@ -495,7 +495,7 @@ category = list("Exosuit Equipment") /datum/design/mech_drill - name = "Exosuit Engineering Equipment (Drill)" + name = "Exosuit Mining (Mining Drill)" id = "mech_drill" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/drill @@ -504,7 +504,7 @@ category = list("Exosuit Equipment") /datum/design/mech_mining_scanner - name = "Exosuit Engineering Equipment (Mining Scanner)" + name = "Exosuit Engineering (Mining Scanner)" id = "mech_mscanner" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/mining_scanner @@ -513,7 +513,7 @@ category = list("Exosuit Equipment") /datum/design/mech_extinguisher - name = "Exosuit Engineering Equipment (Extinguisher)" + name = "Exosuit Engineering (Extinguisher)" id = "mech_extinguisher" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/extinguisher @@ -522,7 +522,7 @@ category = list("Exosuit Equipment") /datum/design/mech_generator - name = "Exosuit Equipment (Plasma Generator)" + name = "Exosuit Module (Plasma Generator)" id = "mech_generator" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/generator @@ -531,7 +531,7 @@ category = list("Exosuit Equipment") /datum/design/mech_mousetrap_mortar - name = "H.O.N.K Mousetrap Mortar" + name = "H.O.N.K Weapon (Mousetrap Mortar)" id = "mech_mousetrap_mortar" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/mousetrap_mortar @@ -540,7 +540,7 @@ category = list("Exosuit Equipment") /datum/design/mech_banana_mortar - name = "H.O.N.K Banana Mortar" + name = "H.O.N.K Weapon (Banana Mortar)" id = "mech_banana_mortar" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/banana_mortar @@ -549,7 +549,7 @@ category = list("Exosuit Equipment") /datum/design/mech_honker - name = "HoNkER BlAsT 5000" + name = "H.O.N.K Weapon (HoNkER BlAsT 5000)" id = "mech_honker" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/weapon/honker @@ -558,7 +558,7 @@ category = list("Exosuit Equipment") /datum/design/mech_punching_glove - name = "Oingo Boingo Punch-face" + name = "H.O.N.K Weapon (Oingo Boingo Punch-face)" id = "mech_punching_face" build_type = MECHFAB build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/punching_glove @@ -757,7 +757,8 @@ build_path = /obj/item/borg/upgrade/ai materials = list(MAT_METAL = 1200, MAT_GLASS = 1500, MAT_GOLD = 200) construction_time = 50 - category = list("Misc") + category = list("Control Interfaces") + search_metadata = "boris" /datum/design/borg_upgrade_rped name = "Cyborg Upgrade (RPED)" @@ -779,13 +780,13 @@ //Misc /datum/design/mecha_tracking - name = "Exosuit Tracking Beacon" + name = "Exosuit Tracker (Exosuit Tracking Beacon)" id = "mecha_tracking" build_type = MECHFAB build_path =/obj/item/mecha_parts/mecha_tracking materials = list(MAT_METAL=500) construction_time = 50 - category = list("Misc") + category = list("Exosuit Equipment") /datum/design/mecha_tracking_ai_control name = "AI Control Beacon" @@ -794,7 +795,7 @@ build_path = /obj/item/mecha_parts/mecha_tracking/ai_control materials = list(MAT_METAL = 1000, MAT_GLASS = 500, MAT_SILVER = 200) construction_time = 50 - category = list("Misc") + category = list("Control Interfaces") /datum/design/synthetic_flash name = "Flash" diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index edacfd13735..cece361eaac 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -10,7 +10,7 @@ materials = list(MAT_METAL = 1000, MAT_GLASS = 500) construction_time = 75 build_path = /obj/item/mmi - category = list("Misc","Medical Designs") + category = list("Control Interfaces", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE /datum/design/posibrain @@ -21,7 +21,7 @@ materials = list(MAT_METAL = 1700, MAT_GLASS = 1350, MAT_GOLD = 500) //Gold, because SWAG. construction_time = 75 build_path = /obj/item/mmi/posibrain - category = list("Misc", "Medical Designs") + category = list("Control Interfaces", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE /datum/design/bluespacebeaker @@ -243,7 +243,7 @@ construction_time = 40 materials = list(MAT_METAL = 600, MAT_GLASS = 400) build_path = /obj/item/organ/eyes/robotic/shield - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_gloweyes @@ -254,7 +254,7 @@ construction_time = 40 materials = list(MAT_METAL = 600, MAT_GLASS = 1000) build_path = /obj/item/organ/eyes/robotic/glow - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_breather @@ -265,7 +265,7 @@ construction_time = 35 materials = list(MAT_METAL = 600, MAT_GLASS = 250) build_path = /obj/item/organ/cyberimp/mouth/breathing_tube - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_surgical @@ -276,7 +276,7 @@ materials = list (MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500) construction_time = 200 build_path = /obj/item/organ/cyberimp/arm/surgery - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_toolset @@ -287,7 +287,7 @@ materials = list (MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500) construction_time = 200 build_path = /obj/item/organ/cyberimp/arm/toolset - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_medical_hud @@ -298,7 +298,7 @@ construction_time = 50 materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 500, MAT_GOLD = 500) build_path = /obj/item/organ/cyberimp/eyes/hud/medical - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_security_hud @@ -309,7 +309,7 @@ construction_time = 50 materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 750, MAT_GOLD = 750) build_path = /obj/item/organ/cyberimp/eyes/hud/security - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_diagnostic_hud @@ -320,7 +320,7 @@ construction_time = 50 materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 600, MAT_GOLD = 600) build_path = /obj/item/organ/cyberimp/eyes/hud/diagnostic - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_xray @@ -331,7 +331,7 @@ construction_time = 60 materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 600, MAT_GOLD = 600, MAT_PLASMA = 1000, MAT_URANIUM = 1000, MAT_DIAMOND = 1000, MAT_BLUESPACE = 1000) build_path = /obj/item/organ/eyes/robotic/xray - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_thermals @@ -342,7 +342,7 @@ construction_time = 60 materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 600, MAT_GOLD = 600, MAT_PLASMA = 1000, MAT_DIAMOND = 2000) build_path = /obj/item/organ/eyes/robotic/thermals - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_antidrop @@ -353,7 +353,7 @@ construction_time = 60 materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 400, MAT_GOLD = 400) build_path = /obj/item/organ/cyberimp/brain/anti_drop - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_antistun @@ -364,7 +364,7 @@ construction_time = 60 materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 500, MAT_GOLD = 1000) build_path = /obj/item/organ/cyberimp/brain/anti_stun - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_nutriment @@ -375,7 +375,7 @@ construction_time = 40 materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_GOLD = 500) build_path = /obj/item/organ/cyberimp/chest/nutriment - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_nutriment_plus @@ -386,7 +386,7 @@ construction_time = 50 materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_GOLD = 500, MAT_URANIUM = 750) build_path = /obj/item/organ/cyberimp/chest/nutriment/plus - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_reviver @@ -397,7 +397,7 @@ construction_time = 60 materials = list(MAT_METAL = 800, MAT_GLASS = 800, MAT_GOLD = 300, MAT_URANIUM = 500) build_path = /obj/item/organ/cyberimp/chest/reviver - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cyberimp_thrusters @@ -408,7 +408,7 @@ construction_time = 80 materials = list(MAT_METAL = 4000, MAT_GLASS = 2000, MAT_SILVER = 1000, MAT_DIAMOND = 1000) build_path = /obj/item/organ/cyberimp/chest/thrusters - category = list("Misc", "Medical Designs") + category = list("Implants", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL ///////////////////////////////////////// @@ -475,7 +475,7 @@ construction_time = 40 materials = list(MAT_METAL = 500, MAT_GLASS = 500) build_path = /obj/item/organ/liver/cybernetic - category = list("Misc", "Medical Designs") + category = list("Cybernetics", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cybernetic_liver_u @@ -497,7 +497,7 @@ construction_time = 40 materials = list(MAT_METAL = 500, MAT_GLASS = 500) build_path = /obj/item/organ/heart/cybernetic - category = list("Misc", "Medical Designs") + category = list("Cybernetics", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cybernetic_heart_u @@ -519,7 +519,7 @@ construction_time = 40 materials = list(MAT_METAL = 500, MAT_GLASS = 500) build_path = /obj/item/organ/lungs/cybernetic - category = list("Misc", "Medical Designs") + category = list("Cybernetics", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL /datum/design/cybernetic_lungs_u @@ -528,9 +528,29 @@ id = "cybernetic_lungs_u" build_type = PROTOLATHE | MECHFAB construction_time = 50 - materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 500) - build_path = /obj/item/organ/lungs/cybernetic/upgraded - category = list("Misc", "Medical Designs") + materials = list(/datum/material/iron = 500, /datum/material/glass = 500, /datum/material/silver = 500) + build_path = /obj/item/organ/stomach/cybernetic/tier3 + +/datum/design/cybernetic_ears + name = "Cybernetic Ears" + desc = "A pair of cybernetic ears." + id = "cybernetic_ears" + build_type = PROTOLATHE | MECHFAB + construction_time = 30 + materials = list(/datum/material/iron = 250, /datum/material/glass = 400) + build_path = /obj/item/organ/ears/cybernetic + category = list("Cybernetics", "Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL + +/datum/design/cybernetic_ears_u + name = "Upgraded Cybernetic Ears" + desc = "A pair of upgraded cybernetic ears." + id = "cybernetic_ears_u" + build_type = PROTOLATHE | MECHFAB + construction_time = 40 + materials = list(/datum/material/iron = 500, /datum/material/glass = 500, /datum/material/silver = 500) + build_path = /obj/item/organ/ears/cybernetic/upgraded + category = list("Cybernetics", "Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL ///////////////////// diff --git a/tgstation.dme b/tgstation.dme index 1388d5bad9a..2bdb2ac38bd 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -43,6 +43,7 @@ #include "code\__DEFINES\DNA.dm" #include "code\__DEFINES\economy.dm" #include "code\__DEFINES\events.dm" +#include "code\__DEFINES\exosuit_fab.dm" #include "code\__DEFINES\exports.dm" #include "code\__DEFINES\fantasy_affixes.dm" #include "code\__DEFINES\flags.dm" diff --git a/tgui/packages/tgui/interfaces/ExosuitFabricator.js b/tgui/packages/tgui/interfaces/ExosuitFabricator.js new file mode 100644 index 00000000000..a9c42d91a81 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ExosuitFabricator.js @@ -0,0 +1,796 @@ +import { classes } from 'common/react'; +import { uniqBy } from 'common/collections'; +import { useBackend, useSharedState } from '../backend'; +import { formatSiUnit, formatMoney } from '../format'; +import { Flex, Section, Tabs, Box, Button, Fragment, ProgressBar, NumberInput, Icon, Input } from '../components'; +import { Window } from '../layouts'; +import { createSearch } from 'common/string'; + +const MATERIAL_KEYS = { + "iron": "sheet-metal_3", + "glass": "sheet-glass_3", + "silver": "sheet-silver_3", + "gold": "sheet-gold_3", + "diamond": "sheet-diamond", + "plasma": "sheet-plasma_3", + "uranium": "sheet-uranium", + "bananium": "sheet-bananium", + "titanium": "sheet-titanium_3", + "bluespace crystal": "polycrystal", + "plastic": "sheet-plastic_3", +}; + +const COLOR_NONE = 0; +const COLOR_AVERAGE = 1; +const COLOR_BAD = 2; + +const COLOR_KEYS = { + [COLOR_NONE]: false, + [COLOR_AVERAGE]: "average", + [COLOR_BAD]: "bad", +}; + +const materialArrayToObj = materials => { + let materialObj = {}; + + materials.forEach(m => { + materialObj[m.name] = m.amount; }); + + return materialObj; +}; + +const partBuildColor = (cost, tally, material) => { + if (cost > material) { + return { color: COLOR_BAD, deficit: (cost - material) }; + } + + if (tally > material) { + return { color: COLOR_AVERAGE, deficit: cost }; + } + + if (cost + tally > material) { + return { color: COLOR_AVERAGE, deficit: ((cost + tally) - material) }; + } + + return { color: COLOR_NONE, deficit: 0 }; +}; + +const partCondFormat = (materials, tally, part) => { + let format = { "textColor": COLOR_NONE }; + + Object.keys(part.cost).forEach(mat => { + format[mat] = partBuildColor(part.cost[mat], tally[mat], materials[mat]); + + if (format[mat].color > format["textColor"]) { + format["textColor"] = format[mat].color; + } + }); + + return format; +}; + +const queueCondFormat = (materials, queue) => { + let materialTally = {}; + let matFormat = {}; + let missingMatTally = {}; + let textColors = {}; + + queue.forEach((part, i) => { + textColors[i] = COLOR_NONE; + Object.keys(part.cost).forEach(mat => { + materialTally[mat] = materialTally[mat] || 0; + missingMatTally[mat] = missingMatTally[mat] || 0; + + matFormat[mat] = partBuildColor( + part.cost[mat], materialTally[mat], materials[mat] + ); + + if (matFormat[mat].color !== COLOR_NONE) { + if (textColors[i] < matFormat[mat].color) { + textColors[i] = matFormat[mat].color; + } + } + else { + materialTally[mat] += part.cost[mat]; + } + + missingMatTally[mat] += matFormat[mat].deficit; + }); + }); + return { materialTally, missingMatTally, textColors, matFormat }; +}; + +const searchFilter = (search, allparts) => { + let searchResults = []; + + if (!search.length) { + return; + } + + const resultFilter = createSearch(search, part => ( + (part.name || "") + + (part.desc || "") + + (part.searchMeta || "") + )); + + Object.keys(allparts).forEach(category => { + allparts[category] + .filter(resultFilter) + .forEach(e => { searchResults.push(e); }); + }); + + searchResults = uniqBy(part => part.name)(searchResults); + + return searchResults; +}; + +export const ExosuitFabricator = (props, context) => { + const { act, data } = useBackend(context); + + const queue = data.queue || []; + const materialAsObj = materialArrayToObj(data.materials || []); + + const { + materialTally, + missingMatTally, + textColors, + } = queueCondFormat(materialAsObj, queue); + + const [ + displayMatCost, + setDisplayMatCost, + ] = useSharedState(context, "display_mats", false); + + return ( + + + + + +
+ +
+
+ +
+ setDisplayMatCost(!displayMatCost)} + checked={displayMatCost}> + Display Material Costs + +
+
+
+ + + +
act("sync_rnd")} /> + )}> + +
+
+ + + + + + + + +
+
+
+
+
+ ); +}; + +const EjectMaterial = (props, context) => { + const { act } = useBackend(context); + + const { material } = props; + + const { + name, + removable, + sheets, + ref, + } = material; + + const [ + removeMaterials, + setRemoveMaterials, + ] = useSharedState(context, "remove_mats_" + name, 1); + + if ((removeMaterials > 1) && (sheets < removeMaterials)) { + setRemoveMaterials(sheets || 1); + } + + return ( + + { + const newVal = parseInt(val, 10); + if (Number.isInteger(newVal)) { + setRemoveMaterials(newVal); + } + }} /> +