From a43288c675c81952b7c5e0dde4cbffa86e9989cd Mon Sep 17 00:00:00 2001 From: DrPainis <79603707+DrPainis@users.noreply.github.com> Date: Mon, 27 Dec 2021 23:15:04 -0500 Subject: [PATCH 01/24] Slimes can now have wings. --- .../mob/living/carbon/human/species_types/jellypeople.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 04c69a4138..0693bf64e1 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -404,7 +404,7 @@ default_color = "00FFFF" species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,HAS_FLESH) inherent_traits = list(TRAIT_TOXINLOVER) - mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None", "legs" = "Plantigrade") + mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None", "legs" = "Plantigrade") say_mod = "says" hair_color = "mutcolor" hair_alpha = 160 //a notch brighter so it blends better. From 16886fc1eaf58c2f144681f1870903920bcfc96b Mon Sep 17 00:00:00 2001 From: CoreFlare Date: Thu, 30 Dec 2021 01:06:28 +0000 Subject: [PATCH 02/24] winge w --- code/modules/mob/living/carbon/human/species_types/ipc.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm index eb870f9624..7c07f5db47 100644 --- a/code/modules/mob/living/carbon/human/species_types/ipc.dm +++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm @@ -9,7 +9,7 @@ species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE,HAIR,ROBOTIC_LIMBS) hair_alpha = 210 inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID - mutant_bodyparts = list("ipc_screen" = "Blank", "ipc_antenna" = "None") + mutant_bodyparts = list("ipc_screen" = "Blank", "deco_wings" = "None", "ipc_antenna" = "None") meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless) From aac92ef0299f4e2a7f1a4e67de07b3e7d7744ccc Mon Sep 17 00:00:00 2001 From: SandPoot Date: Tue, 25 Jan 2022 12:40:57 -0300 Subject: [PATCH 03/24] Update mob.dm --- code/modules/keybindings/keybind/mob.dm | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/code/modules/keybindings/keybind/mob.dm b/code/modules/keybindings/keybind/mob.dm index 15911d831e..c9b44e7fc3 100644 --- a/code/modules/keybindings/keybind/mob.dm +++ b/code/modules/keybindings/keybind/mob.dm @@ -88,3 +88,19 @@ var/atom/A = user.mouseObject if(A) A.attempt_examinate(user.mob) + +/datum/keybinding/mob/cancel_action + hotkey_keys = list("Unbound") + name = "cancel_action" + full_name = "Cancel Action" + description = "Cancel the current action." + +/datum/keybinding/mob/cancel_action/down(client/user) + var/mob/M = user.mob + if(length(M.do_afters)) + var/atom/target = M.do_afters[M.do_afters.len] + to_chat(M, "You stop interacting with \the [target].") + LAZYREMOVE(M.do_afters, target) + else + to_chat(M, "There's nothing that you can cancel right now.") + return TRUE From de35e561b5e5f4f08e5753925c4beacd9a422dc3 Mon Sep 17 00:00:00 2001 From: SandPoot Date: Tue, 25 Jan 2022 12:52:11 -0300 Subject: [PATCH 04/24] Update files --- code/modules/keybindings/keybind/living.dm | 22 ++++++++++++++++++++++ code/modules/keybindings/keybind/mob.dm | 16 ---------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/code/modules/keybindings/keybind/living.dm b/code/modules/keybindings/keybind/living.dm index f76c86691f..7f5ccb3b51 100644 --- a/code/modules/keybindings/keybind/living.dm +++ b/code/modules/keybindings/keybind/living.dm @@ -36,3 +36,25 @@ /datum/keybinding/living/toggle_resting/down(client/user) var/mob/living/L = user.mob L.lay_down() + +/datum/keybinding/living/cancel_action + hotkey_keys = list("Unbound") + name = "cancel_action" + full_name = "Cancel Action" + description = "Cancel the current action." + +/// Technically you shouldn't be doing any actions if you were sleeping either but... +/datum/keybinding/living/can_use(client/user) + . = ..() + var/mob/living/mob = user.mob + return . && (mob.stat == CONSCIOUS) + +/datum/keybinding/living/cancel_action/down(client/user) + var/mob/M = user.mob + if(length(M.do_afters)) + var/atom/target = M.do_afters[M.do_afters.len] + to_chat(M, "You stop interacting with \the [target].") + LAZYREMOVE(M.do_afters, target) + else + to_chat(M, "There's nothing that you can cancel right now.") + return TRUE diff --git a/code/modules/keybindings/keybind/mob.dm b/code/modules/keybindings/keybind/mob.dm index c9b44e7fc3..15911d831e 100644 --- a/code/modules/keybindings/keybind/mob.dm +++ b/code/modules/keybindings/keybind/mob.dm @@ -88,19 +88,3 @@ var/atom/A = user.mouseObject if(A) A.attempt_examinate(user.mob) - -/datum/keybinding/mob/cancel_action - hotkey_keys = list("Unbound") - name = "cancel_action" - full_name = "Cancel Action" - description = "Cancel the current action." - -/datum/keybinding/mob/cancel_action/down(client/user) - var/mob/M = user.mob - if(length(M.do_afters)) - var/atom/target = M.do_afters[M.do_afters.len] - to_chat(M, "You stop interacting with \the [target].") - LAZYREMOVE(M.do_afters, target) - else - to_chat(M, "There's nothing that you can cancel right now.") - return TRUE From e71e86cf23892ccf2f949be606384f87ef9d3438 Mon Sep 17 00:00:00 2001 From: DeltaFire Date: Sat, 29 Jan 2022 16:43:03 +0100 Subject: [PATCH 05/24] adapted --- code/__DEFINES/traits.dm | 1 + code/_globalvars/traits.dm | 1 + code/datums/mutations/space_adaptation.dm | 2 ++ code/modules/mob/living/carbon/life.dm | 3 +++ 4 files changed, 7 insertions(+) diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index edc6f58eaf..30806bfc52 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -104,6 +104,7 @@ #define TRAIT_RESISTCOLD "resist_cold" #define TRAIT_RESISTHIGHPRESSURE "resist_high_pressure" #define TRAIT_RESISTLOWPRESSURE "resist_low_pressure" +#define TRAIT_LOWPRESSURECOOLING "low_pressure_cooling" #define TRAIT_BOMBIMMUNE "bomb_immunity" #define TRAIT_RADIMMUNE "rad_immunity" #define TRAIT_GENELESS "geneless" diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index a3a1a35888..4a8156d268 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -38,6 +38,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_RESISTCOLD" = TRAIT_RESISTCOLD, "TRAIT_RESISTHIGHPRESSURE" = TRAIT_RESISTHIGHPRESSURE, "TRAIT_RESISTLOWPRESSURE" = TRAIT_RESISTLOWPRESSURE, + "TRAIT_LOWPRESSURECOOLING" = TRAIT_LOWPRESSURECOOLING, "TRAIT_BOMBIMMUNE" = TRAIT_BOMBIMMUNE, "TRAIT_RADIMMUNE" = TRAIT_RADIMMUNE, "TRAIT_GENELESS" = TRAIT_GENELESS, diff --git a/code/datums/mutations/space_adaptation.dm b/code/datums/mutations/space_adaptation.dm index 4431720375..6defd05ee5 100644 --- a/code/datums/mutations/space_adaptation.dm +++ b/code/datums/mutations/space_adaptation.dm @@ -13,6 +13,7 @@ return ADD_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance") ADD_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance") + ADD_TRAIT(owner, TRAIT_LOWPRESSURECOOLING, "cold_resistance") owner.add_filter("space_glow", 2, list("type" = "outline", "color" = "#ffe46bd8", "size" = 1)) addtimer(CALLBACK(src, .proc/glow_loop, owner), rand(1,19)) @@ -27,5 +28,6 @@ return REMOVE_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance") REMOVE_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance") + REMOVE_TRAIT(owner, TRAIT_LOWPRESSURECOOLING, "cold_resistance") owner.remove_filter("space_glow") diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 9cc96f2ddd..182ae1afb8 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -699,6 +699,9 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put var/heat_efficiency = clamp(1 + ((bodytemperature - heat) * SYNTH_HEAT_EFFICIENCY_COEFF), 0, SYNTH_SINGLE_INFLUENCE_COOLING_EFFECT_CAP) var/pressure_efficiency = clamp(pressure / ONE_ATMOSPHERE, 0, SYNTH_SINGLE_INFLUENCE_COOLING_EFFECT_CAP) + if(HAS_TRAIT(src, TRAIT_LOWPRESSURECOOLING)) + pressure_efficiency = max(pressure_efficiency, 1) //Space adaptation nulls drawbacks of low-pressure cooling. + var/total_environment_efficiency = min(heat_efficiency * pressure_efficiency, SYNTH_TOTAL_ENVIRONMENT_EFFECT_CAP) //At best, you can get 200% total return total_environment_efficiency From 6e1c221e03f1194770a66c7563c8ed71482fd2ca Mon Sep 17 00:00:00 2001 From: SandPoot Date: Sat, 29 Jan 2022 23:45:44 -0300 Subject: [PATCH 06/24] Update screen_object.dm --- code/_onclick/hud/screen_objects.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 7646297163..6ca0416dfd 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -9,7 +9,6 @@ /atom/movable/screen name = "" icon = 'icons/mob/screen_gen.dmi' - layer = HUD_LAYER plane = HUD_PLANE animate_movement = SLIDE_STEPS speech_span = SPAN_ROBOT From 04d806c70001e2ffb705ca96b034e779ed8bb06c Mon Sep 17 00:00:00 2001 From: DeltaFire Date: Mon, 31 Jan 2022 00:50:22 +0100 Subject: [PATCH 07/24] orange MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit stabilized orange can now cool at most 5 per tick instead of infinite robots only cool half, which means 5 per life tick (status effects fire twice per life tick total) for robots, it cools towards ~ -100°C target temp, provided you are in a location that supports it. --- code/__DEFINES/atmospherics.dm | 1 + .../mob/living/carbon/human/species_types/anthropomorph.dm | 2 +- code/modules/mob/living/carbon/human/species_types/ipc.dm | 2 +- .../mob/living/carbon/human/species_types/synthliz.dm | 2 +- .../research/xenobiology/crossbreeding/_status_effects.dm | 6 +++++- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index 2f82e49462..2ead5ea068 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -81,6 +81,7 @@ #define SYNTH_ACTIVE_COOLING_MIN_ADJUSTMENT 5 //What is the minimum amount of temp you move towards the target point, even if it would be less with default calculations? #define SYNTH_INTEGRATION_COOLANT_PENALTY 0.4 //Integrating coolant is multiplied with this for calculation of impact on passive cooling. #define SYNTH_INTEGRATION_COOLANT_CAP 0.25 //Integrating coolant is capped at counting as current_blood * this number. This is so you can't just run on salglu or whatever. +#define SYNTH_COLD_OFFSET -125 //How much colder temps Synths can tolerate. Used in their species. #define BODYTEMP_NORMAL 310.15 //The natural temperature for a body #define BODYTEMP_AUTORECOVERY_DIVISOR 11 //This is the divisor which handles how much of the temperature difference between the current body temperature and 310.15K (optimal temperature) humans auto-regenerate each tick. The higher the number, the slower the recovery. This is applied each tick, so long as the mob is alive. diff --git a/code/modules/mob/living/carbon/human/species_types/anthropomorph.dm b/code/modules/mob/living/carbon/human/species_types/anthropomorph.dm index 334f76c487..b79c281b3b 100644 --- a/code/modules/mob/living/carbon/human/species_types/anthropomorph.dm +++ b/code/modules/mob/living/carbon/human/species_types/anthropomorph.dm @@ -32,7 +32,7 @@ coldmod = 0.5 heatmod = 1.2 - cold_offset = -125 //Can handle pretty cold environments, but it's still a slightly bad idea if you enter a room thats full of near-absolute-zero gas + cold_offset = SYNTH_COLD_OFFSET //Can handle pretty cold environments, but it's still a slightly bad idea if you enter a room thats full of near-absolute-zero gas blacklisted_quirks = list(/datum/quirk/coldblooded) balance_point_values = TRUE diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm index 4f6b940692..a680d3abc4 100644 --- a/code/modules/mob/living/carbon/human/species_types/ipc.dm +++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm @@ -15,7 +15,7 @@ coldmod = 0.5 heatmod = 1.2 - cold_offset = -125 //Can handle pretty cold environments, but it's still a slightly bad idea if you enter a room thats full of near-absolute-zero gas + cold_offset = SYNTH_COLD_OFFSET //Can handle pretty cold environments, but it's still a slightly bad idea if you enter a room thats full of near-absolute-zero gas blacklisted_quirks = list(/datum/quirk/coldblooded) balance_point_values = TRUE diff --git a/code/modules/mob/living/carbon/human/species_types/synthliz.dm b/code/modules/mob/living/carbon/human/species_types/synthliz.dm index 7fc2da1132..c692370030 100644 --- a/code/modules/mob/living/carbon/human/species_types/synthliz.dm +++ b/code/modules/mob/living/carbon/human/species_types/synthliz.dm @@ -12,7 +12,7 @@ coldmod = 0.5 heatmod = 1.2 - cold_offset = -125 //Can handle pretty cold environments, but it's still a slightly bad idea if you enter a room thats full of near-absolute-zero gas + cold_offset = SYNTH_COLD_OFFSET //Can handle pretty cold environments, but it's still a slightly bad idea if you enter a room thats full of near-absolute-zero gas blacklisted_quirks = list(/datum/quirk/coldblooded) balance_point_values = TRUE diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index c408ad096e..e51e4852e6 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -495,7 +495,11 @@ /datum/status_effect/stabilized/orange/tick() var/body_temperature_difference = BODYTEMP_NORMAL - owner.bodytemperature - owner.adjust_bodytemperature(min(5,body_temperature_difference)) + var/cooling_cap = -5 + if(HAS_TRAIT(owner, TRAIT_ROBOTIC_ORGANISM)) + cooling_cap *= 0.5 //Only cools by half as much (which is 5 per life tick since this ticks twice as much as life) so it isn't true spaceproofness.. + body_temperature_difference += SYNTH_COLD_OFFSET //.. But also cools towards a cold temp, provided there is nothing that counters it. + owner.adjust_bodytemperature(clamp(body_temperature_difference, cooling_cap, 5)) return ..() /datum/status_effect/stabilized/purple From 760ed484763745732cf05bdc98e98e5539f502e0 Mon Sep 17 00:00:00 2001 From: SandPoot Date: Wed, 2 Feb 2022 00:45:32 -0300 Subject: [PATCH 08/24] Upload files --- code/game/machinery/autolathe.dm | 425 ++++++++++----------- tgui/packages/tgui/interfaces/Autolathe.js | 202 ++++++++++ 2 files changed, 410 insertions(+), 217 deletions(-) create mode 100644 tgui/packages/tgui/interfaces/Autolathe.js diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 0e7b4aa0fa..4db565aec1 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -1,7 +1,3 @@ -#define AUTOLATHE_MAIN_MENU 1 -#define AUTOLATHE_CATEGORY_MENU 2 -#define AUTOLATHE_SEARCH_MENU 3 - /obj/machinery/autolathe name = "autolathe" desc = "It produces items using metal and glass." @@ -24,13 +20,14 @@ var/shock_wire var/busy = FALSE - var/prod_coeff = 1 + + ///the multiplier for how much materials the created object takes from this machines stored materials + var/creation_efficiency = 1.6 var/datum/design/being_built var/datum/techweb/stored_research var/list/datum/design/matching_designs - var/selected_category - var/screen = 1 + var/selected_category = "None" var/base_price = 25 var/hacked_price = 50 @@ -60,7 +57,7 @@ QDEL_NULL(wires) return ..() -/obj/machinery/autolathe/ui_interact(mob/user) +/obj/machinery/autolathe/ui_interact(mob/user, datum/tgui/ui) . = ..() if(!is_operational()) return @@ -68,101 +65,129 @@ if(shocked && !(stat & NOPOWER)) shock(user,50) - var/dat + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Autolathe", capitalize(src.name)) + ui.open() - switch(screen) - if(AUTOLATHE_MAIN_MENU) - dat = main_win(user) - if(AUTOLATHE_CATEGORY_MENU) - dat = category_win(user,selected_category) - if(AUTOLATHE_SEARCH_MENU) - dat = search_win(user) - - var/datum/browser/popup = new(user, "autolathe", name, 400, 500) - popup.set_content(dat) - popup.open() - -/obj/machinery/autolathe/on_deconstruction() +/obj/machinery/autolathe/ui_data(mob/user) + var/list/data = list() + data["materials"] = list() var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - materials.retrieve_all() + data["materialtotal"] = materials.total_amount + data["materialsmax"] = materials.max_amount + data["categories"] = categories + data["designs"] = list() + data["active"] = busy -/obj/machinery/autolathe/attackby(obj/item/O, mob/user, params) - if (busy) - to_chat(user, "The autolathe is busy. Please wait for completion of previous operation.") - return TRUE - - if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", O)) - updateUsrDialog() - return TRUE - - if(default_deconstruction_crowbar(O)) - return TRUE - - if(panel_open && is_wire_tool(O)) - wires.interact(user) - return TRUE - - if(user.a_intent == INTENT_HARM) //so we can hit the machine - return ..() - - if(stat) - return TRUE - - if(istype(O, /obj/item/disk/design_disk)) - user.visible_message("[user] begins to load \the [O] in \the [src]...", - "You begin to load a design from \the [O]...", - "You hear the chatter of a floppy drive.") - busy = TRUE - var/obj/item/disk/design_disk/D = O - if(do_after(user, 14.4, target = src)) - for(var/B in D.blueprints) - if(B) - stored_research.add_design(B) - busy = FALSE - return TRUE - - return ..() - - -/obj/machinery/autolathe/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted) - if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal)) - use_power(MINERAL_MATERIAL_AMOUNT / 10) - else if(custom_materials && custom_materials.len && custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)]) - flick("autolathe_r",src)//plays glass insertion animation by default otherwise + for(var/mat_id in materials.materials) + var/datum/material/M = mat_id + var/mineral_count = materials.materials[mat_id] + var/list/material_data = list( + name = M.name, + mineral_amount = mineral_count, + matcolour = M.color, + ) + data["materials"] += list(material_data) + if(selected_category != "None" && !length(matching_designs)) + data["designs"] = handle_designs(stored_research.researched_designs, TRUE) else - flick("autolathe_o",src)//plays metal insertion animation + data["designs"] = handle_designs(matching_designs, FALSE) + return data +/obj/machinery/autolathe/proc/handle_designs(list/designs, categorycheck) + var/list/output = list() + for(var/v in designs) + var/datum/design/D = categorycheck ? SSresearch.techweb_design_by_id(v) : v + if(categorycheck) + if(!(selected_category in D.category)) + continue + var/unbuildable = FALSE // we can't build the design currently + var/m10 = FALSE // 10x mult + var/m25 = FALSE // 25x mult + var/m50 = FALSE // 50x mult + var/m5 = FALSE // 5x mult + var/sheets = FALSE // sheets or no? + if(disabled || !can_build(D)) + unbuildable = TRUE + var/max_multiplier = unbuildable ? 0 : 1 + if(ispath(D.build_path, /obj/item/stack)) + sheets = TRUE + if(!unbuildable) + var/datum/component/material_container/mats = GetComponent(/datum/component/material_container) + for(var/datum/material/mat in D.materials) + max_multiplier = min(D.maxstack, round(mats.get_material_amount(mat)/D.materials[mat])) + if (max_multiplier>10 && !disabled) + m10 = TRUE + if (max_multiplier>25 && !disabled) + m25 = TRUE + else + if(!unbuildable) + if(!disabled && can_build(D, 5)) + m5 = TRUE + if(!disabled && can_build(D, 10)) + m10 = TRUE + var/datum/component/material_container/mats = GetComponent(/datum/component/material_container) + for(var/datum/material/mat in D.materials) + max_multiplier = min(50, round(mats.get_material_amount(mat)/(D.materials[mat] * creation_efficiency))) - use_power(min(1000, amount_inserted / 100)) - updateUsrDialog() + var/list/design = list( + name = D.name, + id = D.id, + ref = REF(src), + cost = get_design_cost(D), + buildable = unbuildable, + mult5 = m5, + mult10 = m10, + mult25 = m25, + mult50 = m50, + sheet = sheets, + maxmult = max_multiplier, + ) + output += list(design) + return output -/obj/machinery/autolathe/Topic(href, href_list) - if(..()) +/obj/machinery/autolathe/ui_act(action, params) + . = ..() + if(.) return - if (!busy) - if(href_list["menu"]) - screen = text2num(href_list["menu"]) - updateUsrDialog() + if(action == "menu") + selected_category = null + matching_designs.Cut() + . = TRUE - if(href_list["category"]) - selected_category = href_list["category"] - updateUsrDialog() + if(action == "category") + selected_category = params["selectedCategory"] + matching_designs.Cut() + . = TRUE - if(href_list["make"]) + if(action == "search") + matching_designs.Cut() + for(var/v in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(v) + if(findtext(D.name,params["to_search"])) + matching_designs.Add(D) + . = TRUE + + if(action == "make") + if (!busy) ///////////////// //href protection - being_built = stored_research.isDesignResearchedID(href_list["make"]) + being_built = stored_research.isDesignResearchedID(params["id"]) if(!being_built) return - var/multiplier = text2num(href_list["multiplier"]) + var/multiplier = text2num(params["multiplier"]) + if(!multiplier) + to_chat(usr, span_alert("[src] only accepts a numerical multiplier!")) + return var/is_stack = ispath(being_built.build_path, /obj/item/stack) - multiplier = clamp(multiplier,1,50) + multiplier = clamp(round(multiplier),1,50) ///////////////// - var/coeff = (is_stack ? 1 : prod_coeff) //stacks are unaffected by production coefficient + var/coeff = (is_stack ? 1 : creation_efficiency) //stacks are unaffected by production coefficient var/total_amount = 0 for(var/MAT in being_built.materials) @@ -184,8 +209,8 @@ if(materials.materials[i] > 0) list_to_show += i - used_material = input("Choose [used_material]", "Custom Material") as null|anything in sortList(list_to_show, /proc/cmp_typepaths_asc) - if(!used_material) + used_material = tgui_input_list(usr, "Choose [used_material]", "Custom Material", sortList(list_to_show, /proc/cmp_typepaths_asc)) + if(isnull(used_material)) return //Didn't pick any material, so you can't build shit either. custom_materials[used_material] += amount_needed @@ -193,27 +218,95 @@ if(materials.has_materials(materials_used)) busy = TRUE + to_chat(usr, span_notice("You print [multiplier] item(s) from the [src]")) use_power(power) icon_state = "autolathe_n" var/time = is_stack ? 32 : (32 * coeff * multiplier) ** 0.8 addtimer(CALLBACK(src, .proc/make_item, power, materials_used, custom_materials, multiplier, coeff, is_stack, usr), time) + . = TRUE else - to_chat(usr, "Not enough materials for this operation.") + to_chat(usr, span_alert("Not enough materials for this operation.")) + else + to_chat(usr, span_alert("The autolathe is busy. Please wait for completion of previous operation.")) - if(href_list["search"]) - matching_designs.Cut() +/obj/machinery/autolathe/on_deconstruction() + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + materials.retrieve_all() - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(findtext(D.name,href_list["to_search"])) - matching_designs.Add(D) - updateUsrDialog() +/obj/machinery/autolathe/attackby(obj/item/O, mob/living/user, params) + if(busy) + balloon_alert(user, "it's busy!") + return TRUE + + if(user.a_intent == INTENT_HARM) //so we can hit the machine + return ..() + + if(stat) + return TRUE + + if(istype(O, /obj/item/disk/design_disk)) + user.visible_message(span_notice("[user] begins to load \the [O] in \the [src]..."), + balloon_alert(user, "uploading design..."), + span_hear("You hear the chatter of a floppy drive.")) + busy = TRUE + if(do_after(user, 14.4, target = src)) + var/obj/item/disk/design_disk/disky = O + var/list/not_imported + for(var/datum/design/blueprint as anything in disky.blueprints) + if(!blueprint) + continue + if(blueprint.build_type & AUTOLATHE) + stored_research.add_design(blueprint) + else + LAZYADD(not_imported, blueprint.name) + if(not_imported) + to_chat(user, span_warning("The following design[length(not_imported) > 1 ? "s" : ""] couldn't be imported: [english_list(not_imported)]")) + busy = FALSE + return TRUE + + if(panel_open) + balloon_alert(user, "close the panel first!") + return FALSE + + return ..() + +/obj/machinery/autolathe/screwdriver_act(mob/living/user, obj/item/I) + . = ..() + if(busy) + balloon_alert(user, "it's busy!") + return STOP_ATTACK_PROC_CHAIN + + if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", I)) + return STOP_ATTACK_PROC_CHAIN + +/obj/machinery/autolathe/crowbar_act(mob/living/user, obj/item/I) + . = ..() + if(busy) + balloon_alert(user, "it's busy!") + return STOP_ATTACK_PROC_CHAIN + + if(default_deconstruction_crowbar(I)) + return STOP_ATTACK_PROC_CHAIN + +/obj/machinery/autolathe/multitool_act(mob/living/user, obj/item/I) + . = ..() + if(busy) + balloon_alert(user, "it's busy!") + return STOP_ATTACK_PROC_CHAIN + + if(panel_open) + wires.interact(user) + return STOP_ATTACK_PROC_CHAIN + +/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted) + if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal)) + use_power(MINERAL_MATERIAL_AMOUNT / 10) + else if(custom_materials && custom_materials.len && custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)]) + flick("autolathe_r", src)//plays glass insertion animation by default otherwise else - to_chat(usr, "The autolathe is busy. Please wait for completion of previous operation.") + flick("autolathe_o", src)//plays metal insertion animation - updateUsrDialog() - - return + use_power(min(1000, amount_inserted / 100)) /obj/machinery/autolathe/proc/make_item(power, list/materials_used, list/picked_materials, multiplier, coeff, is_stack, mob/user) var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) @@ -223,11 +316,11 @@ materials.use_materials(materials_used) if(is_stack) - var/obj/item/stack/N = new being_built.build_path(A, multiplier) - N.update_icon() + var/obj/item/stack/N = new being_built.build_path(A, multiplier, FALSE) + N.update_appearance() N.autolathe_crafted(src) else - for(var/i=1, i<=multiplier, i++) + for(var/i in 1 to multiplier) var/obj/item/new_item = new being_built.build_path(A) new_item.autolathe_crafted(src) @@ -241,132 +334,30 @@ icon_state = "autolathe" busy = FALSE - updateDialog() /obj/machinery/autolathe/RefreshParts() - var/T = 0 - for(var/obj/item/stock_parts/matter_bin/MB in component_parts) - T += MB.rating*75000 + var/mat_capacity = 0 + for(var/obj/item/stock_parts/matter_bin/new_matter_bin in component_parts) + mat_capacity += new_matter_bin.rating*75000 var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - materials.max_amount = T - T=1.2 - for(var/obj/item/stock_parts/manipulator/M in component_parts) - T -= M.rating*0.2 - prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4 + materials.max_amount = mat_capacity + + var/efficiency=1.2 + for(var/obj/item/stock_parts/manipulator/new_manipulator in component_parts) + efficiency -= new_manipulator.rating*0.2 + creation_efficiency = max(1,efficiency) // creation_efficiency goes 1 -> 0,8 -> 0,6 -> 0,4 per level of manipulator efficiency /obj/machinery/autolathe/examine(mob/user) . += ..() var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) if(in_range(user, src) || isobserver(user)) - . += "The status display reads: Storing up to [materials.max_amount] material units.
Material consumption at [prod_coeff*100]%.
" - -/obj/machinery/autolathe/proc/main_win(mob/user) - var/dat = "

Autolathe Menu:


" - dat += materials_printout() - - dat += "
\ - \ - \ - \ - \ - \ -

" - - var/line_length = 1 - dat += "" - - for(var/C in categories) - if(line_length > 2) - dat += "" - line_length = 1 - - dat += "" - line_length++ - - dat += "
[C]
" - return dat - -/obj/machinery/autolathe/proc/category_win(mob/user,selected_category) - var/dat = "Return to main menu" - dat += "

Browsing [selected_category]:


" - dat += materials_printout() - - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(!(selected_category in D.category)) - continue - - if(disabled || !can_build(D)) - dat += "[D.name]" - else - dat += "[D.name]" - - if(ispath(D.build_path, /obj/item/stack)) - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - var/max_multiplier - for(var/datum/material/mat in D.materials) - max_multiplier = min(D.maxstack, round(materials.get_material_amount(mat)/D.materials[mat])) - if (max_multiplier>10 && !disabled) - dat += " x10" - if (max_multiplier>25 && !disabled) - dat += " x25" - if(max_multiplier > 0 && !disabled) - dat += " x[max_multiplier]" - else - if(!disabled && can_build(D, 5)) - dat += " x5" - if(!disabled && can_build(D, 10)) - dat += " x10" - - dat += "[get_design_cost(D)]
" - - dat += "
" - return dat - -/obj/machinery/autolathe/proc/search_win(mob/user) - var/dat = "Return to main menu" - dat += "

Search results:


" - dat += materials_printout() - - for(var/v in matching_designs) - var/datum/design/D = v - if(disabled || !can_build(D)) - dat += "[D.name]" - else - dat += "[D.name]" - - if(ispath(D.build_path, /obj/item/stack)) - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - var/max_multiplier - for(var/datum/material/mat in D.materials) - max_multiplier = min(D.maxstack, round(materials.get_material_amount(mat)/D.materials[mat])) - if (max_multiplier>10 && !disabled) - dat += " x10" - if (max_multiplier>25 && !disabled) - dat += " x25" - if(max_multiplier > 0 && !disabled) - dat += " x[max_multiplier]" - - dat += "[get_design_cost(D)]
" - - dat += "
" - return dat - -/obj/machinery/autolathe/proc/materials_printout() - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - var/dat = "Total amount: [materials.total_amount] / [materials.max_amount] cm3
" - for(var/mat_id in materials.materials) - var/datum/material/M = mat_id - var/mineral_amount = materials.materials[mat_id] - if(mineral_amount > 0) - dat += "[M.name] amount: [mineral_amount] cm3
" - return dat + . += span_notice("The status display reads: Storing up to [materials.max_amount] material units.
Material consumption at [creation_efficiency*100]%.") /obj/machinery/autolathe/proc/can_build(datum/design/D, amount = 1) - if(D.make_reagents.len) + if(length(D.make_reagents)) return FALSE - var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff) + var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : creation_efficiency) var/list/required_materials = list() @@ -379,7 +370,7 @@ /obj/machinery/autolathe/proc/get_design_cost(datum/design/D) - var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff) + var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : creation_efficiency) var/dat for(var/i in D.materials) if(istext(i)) //Category handling @@ -402,7 +393,7 @@ disabled = FALSE /obj/machinery/autolathe/proc/shock(mob/user, prb) - if(stat & (BROKEN|NOPOWER)) // unpowered, no shock + if(stat & (BROKEN|NOPOWER)) // unpowered, no shock return FALSE if(!prob(prb)) return FALSE @@ -424,7 +415,7 @@ else stored_research.remove_design(D) -/obj/machinery/autolathe/hacked/Initialize() +/obj/machinery/autolathe/hacked/Initialize(mapload) . = ..() adjust_hacked(TRUE) diff --git a/tgui/packages/tgui/interfaces/Autolathe.js b/tgui/packages/tgui/interfaces/Autolathe.js new file mode 100644 index 0000000000..ede46b5526 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Autolathe.js @@ -0,0 +1,202 @@ +import { useBackend, useLocalState } from '../backend'; +import { Button, LabeledList, Section, ProgressBar, Flex, Box, Table, Collapsible, Input, Dimmer, Icon } from '../components'; +import { Window } from '../layouts'; +import { capitalize } from "common/string"; + +export const Autolathe = (props, context) => { + const { act, data } = useBackend(context); + // Extract `health` and `color` variables from the `data` object. + const { + materialtotal, + materialsmax, + materials = [], + categories = [], + designs = [], + active, + } = data; + const [ + current_category, + setCategory, + ] = useLocalState(context, 'current_category', "None"); + const filteredmaterials = materials.filter(material => + material.mineral_amount > 0); + return ( + + +
+ + + + {materialtotal + '/' + materialsmax + ' cm³'} + + + + {filteredmaterials.length > 0 && ( + + + {filteredmaterials.map(filteredmaterial => ( + + +
{filteredmaterial.mineral_amount + ' cm³'}
+
+
+ ))} +
+
)} +
+
+
+
+ { + if (value.length) { + act('search', { + to_search: value, + }); + setCategory('results for "' + value + '"'); + } + }} /> +
+
+ + {categories.map(category => ( + // eslint-disable-next-line react/jsx-key +
+ {current_category.toString() !== "None" && ( +
{ + act('menu'); + setCategory("None"); + }} /> + )}> + {active === 1 && ( + + + {'Building items...'} + + )} + + + {designs.length + && (designs.map(design => ( + + +
+
+
+ )} +
+
+ ); +}; From 6d2680d7ecd5125404a7903e5527b93b69da5656 Mon Sep 17 00:00:00 2001 From: SandPoot Date: Wed, 2 Feb 2022 12:31:20 -0300 Subject: [PATCH 09/24] Update files --- .../mob/living/simple_animal/bot/bot.dm | 122 +++--- .../mob/living/simple_animal/bot/cleanbot.dm | 56 ++- .../mob/living/simple_animal/bot/ed209bot.dm | 75 ++-- .../mob/living/simple_animal/bot/firebot.dm | 40 +- .../mob/living/simple_animal/bot/floorbot.dm | 72 ++-- .../mob/living/simple_animal/bot/honkbot.dm | 18 - .../mob/living/simple_animal/bot/medbot.dm | 123 +++--- .../mob/living/simple_animal/bot/mulebot.dm | 50 --- .../mob/living/simple_animal/bot/secbot.dm | 63 +--- tgui/packages/tgui/interfaces/SimpleBot.tsx | 351 ++++++++++++++++++ 10 files changed, 565 insertions(+), 405 deletions(-) create mode 100644 tgui/packages/tgui/interfaces/SimpleBot.tsx diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index bc8c3fed87..ca9ca75e6c 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -292,18 +292,21 @@ /mob/living/simple_animal/bot/on_attack_hand(mob/living/carbon/human/H) if(H.a_intent == INTENT_HELP) - interact(H) + ui_interact(H) else return ..() /mob/living/simple_animal/bot/attack_ai(mob/user) if(!topic_denied(user)) - interact(user) + ui_interact(user) else to_chat(user, "[src]'s interface is not responding!") -/mob/living/simple_animal/bot/interact(mob/user) - show_controls(user) +/mob/living/simple_animal/bot/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "SimpleBot", name) + ui.open() /mob/living/simple_animal/bot/attackby(obj/item/W, mob/user, params) if(W.tool_behaviour == TOOL_SCREWDRIVER) @@ -795,56 +798,48 @@ Pass a positive integer as an argument to override a bot's default speed. else // no path, so calculate new one calc_summon_path() -/mob/living/simple_animal/bot/Bump(M as mob|obj) //Leave no door unopened! +// Variables sent to TGUI +/mob/living/simple_animal/bot/ui_data(mob/user) + var/list/data = list() + data["can_hack"] = (issilicon(user) || IsAdminGhost(user)) + data["custom_controls"] = list() + data["emagged"] = emagged + data["locked"] = locked + data["pai"] = list() + data["settings"] = list() + if(!locked || issilicon(user) || IsAdminGhost(user)) + data["pai"]["allow_pai"] = allow_pai + data["pai"]["card_inserted"] = paicard + data["settings"]["airplane_mode"] = remote_disabled + data["settings"]["maintenance_lock"] = !open + data["settings"]["power"] = on + data["settings"]["patrol_station"] = auto_patrol + return data + +// Actions received from TGUI +/mob/living/simple_animal/bot/ui_act(action, params) . = ..() - if((istype(M, /obj/machinery/door/airlock) || istype(M, /obj/machinery/door/window)) && (!isnull(access_card))) - var/obj/machinery/door/D = M - if(D.check_access(access_card)) - D.open() - frustration = 0 - -/mob/living/simple_animal/bot/proc/show_controls(mob/M) - users |= M - var/dat = "" - dat = get_controls(M) - var/datum/browser/popup = new(M,window_id,window_name,350,600) - popup.set_content(dat) - popup.open(use_onclose = 0) - onclose(M,window_id,ref=src) - return - -/mob/living/simple_animal/bot/proc/update_controls() - for(var/mob/M in users) - show_controls(M) - -/mob/living/simple_animal/bot/proc/get_controls(mob/M) - return "PROTOBOT - NOT FOR USE" - -/mob/living/simple_animal/bot/Topic(href, href_list) - //No ..() to prevent strip panel showing up - Todo: make that saner - if(href_list["close"])// HUE HUE - if(usr in users) - users.Remove(usr) - return TRUE - - if(topic_denied(usr)) - to_chat(usr, "[src]'s interface is not responding!") - return TRUE - add_fingerprint(usr) - - if((href_list["power"]) && (bot_core.allowed(usr) || !locked)) - if(on) - turn_off() - else - turn_on() - - switch(href_list["operation"]) + if(.) + return + if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) + to_chat(usr, span_warning("Access denied.")) + return + if(action == "lock") + locked = !locked + if(locked && !(issilicon(usr) || IsAdminGhost(usr))) + return + switch(action) + if("power") + on = !on + update_appearance() + if("maintenance") + open = !open if("patrol") if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) return TRUE auto_patrol = !auto_patrol bot_reset() - if("remote") + if("airplane") remote_disabled = !remote_disabled if("hack") if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr)) @@ -865,11 +860,11 @@ Pass a positive integer as an argument to override a bot's default speed. hacked = FALSE to_chat(usr, "[text_dehack]") bot_reset() - if("ejectpai") + if("eject_pai") if(paicard && (!locked || hasSiliconAccessInArea(usr) || IsAdminGhost(usr))) to_chat(usr, "You eject [paicard] from [bot_name]") ejectpai(usr) - update_controls() + return /mob/living/simple_animal/bot/update_icon_state() icon_state = "[initial(icon_state)][on]" @@ -897,33 +892,6 @@ Pass a positive integer as an argument to override a bot's default speed. return TRUE return FALSE -/mob/living/simple_animal/bot/proc/hack(mob/user) - var/hack - if(hasSiliconAccessInArea(user) || IsAdminGhost(user)) //Allows silicons or admins to toggle the emag status of a bot. - hack += "[emagged == 2 ? "Software compromised! Unit may exhibit dangerous or erratic behavior." : "Unit operating normally. Release safety lock?"]
" - hack += "Harm Prevention Safety System: [emagged ? "DANGER" : "Engaged"]
" - else if(!locked) //Humans with access can use this option to hide a bot from the AI's remote control panel and PDA control. - hack += "Remote network control radio: [remote_disabled ? "Disconnected" : "Connected"]
" - return hack - -/mob/living/simple_animal/bot/proc/showpai(mob/user) - var/eject = "" - if((!locked || hasSiliconAccessInArea(usr) || IsAdminGhost(usr))) - if(paicard || allow_pai) - eject += "Personality card status: " - if(paicard) - if(client) - eject += "Active" - else - eject += "Inactive" - else if(!allow_pai || key) - eject += "Unavailable" - else - eject += "Not inserted" - eject += "
" - eject += "
" - return eject - /mob/living/simple_animal/bot/proc/insertpai(mob/user, obj/item/paicard/card) if(paicard) to_chat(user, "A [paicard] is already inserted!") diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index 5b812086c8..c683267a58 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -443,37 +443,33 @@ /obj/machinery/bot_core/cleanbot req_one_access = list(ACCESS_JANITOR, ACCESS_ROBOTICS) -/mob/living/simple_animal/bot/cleanbot/get_controls(mob/user) - var/dat - dat += hack(user) - dat += showpai(user) - dat += text({" -Status: [on ? "On" : "Off"]
-Behaviour controls are [locked ? "locked" : "unlocked"]
-Maintenance panel panel is [open ? "opened" : "closed"]"}) - if(!locked || issilicon(user)|| IsAdminGhost(user)) - dat += "
Clean Blood: [blood ? "Yes" : "No"]" - dat += "
Clean Trash: [trash ? "Yes" : "No"]" - dat += "
Clean Graffiti: [drawn ? "Yes" : "No"]" - dat += "
Exterminate Pests: [pests ? "Yes" : "No"]" - dat += "

Patrol Station: [auto_patrol ? "Yes" : "No"]" - return dat +// Variables sent to TGUI +/mob/living/simple_animal/bot/cleanbot/ui_data(mob/user) + var/list/data = ..() -/mob/living/simple_animal/bot/cleanbot/Topic(href, href_list) - if(..()) - return 1 - if(href_list["operation"]) - switch(href_list["operation"]) - if("blood") - blood = !blood - if("pests") - pests = !pests - if("trash") - trash = !trash - if("drawn") - drawn = !drawn - get_targets() - update_controls() + if(!locked || issilicon(user)|| IsAdminGhost(user)) + data["custom_controls"]["clean_blood"] = blood + data["custom_controls"]["clean_trash"] = trash + data["custom_controls"]["clean_graffiti"] = drawn + data["custom_controls"]["pest_control"] = pests + return data + +// Actions received from TGUI +/mob/living/simple_animal/bot/cleanbot/ui_act(action, params) + . = ..() + if(. || !hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) + return TRUE + switch(action) + if("clean_blood") + blood = !blood + if("pest_control") + pests = !pests + if("clean_trash") + trash = !trash + if("clean_graffiti") + drawn = !drawn + get_targets() + return /obj/machinery/bot_core/cleanbot/medbay req_one_access = list(ACCESS_JANITOR, ACCESS_ROBOTICS, ACCESS_MEDICAL) diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 604a72b43e..c3ae3898dd 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -96,64 +96,45 @@ text_dehack = "You restore [name]'s combat inhibitor." text_dehack_fail = "[name] ignores your attempts to restrict him!" -/mob/living/simple_animal/bot/ed209/get_controls(mob/user) - var/dat - dat += hack(user) - dat += showpai(user) - dat += text({" -Security Unit v2.6 controls

-Status: []
-Behaviour controls are [locked ? "locked" : "unlocked"]
-Maintenance panel panel is [open ? "opened" : "closed"]
"}, - -"[on ? "On" : "Off"]" ) - +// Variables sent to TGUI +/mob/living/simple_animal/bot/ed209/ui_data(mob/user) + var/list/data = ..() if(!locked || hasSiliconAccessInArea(user)|| IsAdminGhost(user)) if(!lasercolor) - dat += text({"
-Arrest Unidentifiable Persons: []
-Arrest for Unauthorized Weapons: []
-Arrest for Warrant: []
-
-Operating Mode: []
-Report Arrests[]
-Auto Patrol[]"}, + data["custom_controls"]["check_id"] = idcheck + data["custom_controls"]["check_weapons"] = weaponscheck + data["custom_controls"]["check_warrants"] = check_records + data["custom_controls"]["handcuff_targets"] = !arrest_type + data["custom_controls"]["arrest_alert"] = declare_arrests + return data -"[idcheck ? "Yes" : "No"]", -"[weaponscheck ? "Yes" : "No"]", -"[check_records ? "Yes" : "No"]", -"[arrest_type ? "Detain" : "Arrest"]", -"[declare_arrests ? "Yes" : "No"]", -"[auto_patrol ? "On" : "Off"]" ) - - return dat - -/mob/living/simple_animal/bot/ed209/Topic(href, href_list) +// Actions received from TGUI +/mob/living/simple_animal/bot/ed209/ui_act(action, params) if(lasercolor && ishuman(usr)) var/mob/living/carbon/human/H = usr - if((lasercolor == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag)))//Opposing team cannot operate it - return - else if((lasercolor == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag))) - return - if(..()) - return 1 + switch(lasercolor) //Opposing team cannot operate it + if("b") + if(istype(H.wear_suit, /obj/item/clothing/suit/redtag)) + return TRUE + if("r") + if(istype(H.wear_suit, /obj/item/clothing/suit/bluetag)) + return TRUE + . = ..() + if(. || !hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) + return TRUE - switch(href_list["operation"]) - if("idcheck") + switch(action) + if("check_id") idcheck = !idcheck - update_controls() - if("weaponscheck") + if("check_weapons") weaponscheck = !weaponscheck - update_controls() - if("ignorerec") + if("check_warrants") check_records = !check_records - update_controls() - if("switchmode") + if("handcuff_targets") arrest_type = !arrest_type - update_controls() - if("declarearrests") + if("arrest_alert") declare_arrests = !declare_arrests - update_controls() + return /mob/living/simple_animal/bot/ed209/proc/judgement_criteria() var/final = FALSE diff --git a/code/modules/mob/living/simple_animal/bot/firebot.dm b/code/modules/mob/living/simple_animal/bot/firebot.dm index d0e969dc4e..66d1955502 100644 --- a/code/modules/mob/living/simple_animal/bot/firebot.dm +++ b/code/modules/mob/living/simple_animal/bot/firebot.dm @@ -102,23 +102,6 @@ text_dehack = "You detect errors in [name] and reset his programming." text_dehack_fail = "[name] is not responding to reset commands!" -/mob/living/simple_animal/bot/firebot/get_controls(mob/user) - var/dat - dat += hack(user) - dat += showpai(user) - dat += "Mobile Fire Extinguisher v1.0

" - dat += "Status: [on ? "On" : "Off"]
" - dat += "Maintenance panel panel is [open ? "opened" : "closed"]
" - - dat += "Behaviour controls are [locked ? "locked" : "unlocked"]
" - if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user)) - dat += "Extinguish Fires: [extinguish_fires ? "Yes" : "No"]
" - dat += "Extinguish People: [extinguish_people ? "Yes" : "No"]
" - dat += "Patrol Station: [auto_patrol ? "Yes" : "No"]
" - dat += "Stationary Mode: [stationary_mode ? "Yes" : "No"]
" - - return dat - /mob/living/simple_animal/bot/firebot/emag_act(mob/user) . = ..() if(emagged == 1) @@ -138,20 +121,29 @@ internal_ext.max_water = INFINITY internal_ext.refill() -/mob/living/simple_animal/bot/firebot/Topic(href, href_list) - if(..()) - return TRUE +// Variables sent to TGUI +/mob/living/simple_animal/bot/firebot/ui_data(mob/user) + var/list/data = ..() + if(!locked || issilicon(user) || IsAdminGhost(user)) + data["custom_controls"]["extinguish_fires"] = extinguish_fires + data["custom_controls"]["extinguish_people"] = extinguish_people + data["custom_controls"]["stationary_mode"] = stationary_mode + return data - switch(href_list["operation"]) +// Actions received from TGUI +/mob/living/simple_animal/bot/firebot/ui_act(action, params) + . = ..() + if(. || !hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) + return TRUE + switch(action) if("extinguish_fires") extinguish_fires = !extinguish_fires if("extinguish_people") extinguish_people = !extinguish_people if("stationary_mode") stationary_mode = !stationary_mode - - update_controls() - update_icon() + update_appearance() + return /mob/living/simple_animal/bot/firebot/proc/is_burning(atom/target) if(ismob(target)) diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index a67642f8ca..5f0075aaa2 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -71,36 +71,6 @@ text_dehack = "You detect errors in [name] and reset his programming." text_dehack_fail = "[name] is not responding to reset commands!" -/mob/living/simple_animal/bot/floorbot/get_controls(mob/user) - var/dat - dat += hack(user) - dat += showpai(user) - dat += "Floor Repairer Controls v1.1

" - dat += "Status: [on ? "On" : "Off"]
" - dat += "Maintenance panel panel is [open ? "opened" : "closed"]
" - dat += "Special tiles: " - if(specialtiles) - dat += "Loaded \[[specialtiles]/[maxtiles]\]
" - else - dat += "None Loaded
" - - dat += "Behaviour controls are [locked ? "locked" : "unlocked"]
" - if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user)) - dat += "Add tiles to new hull plating: [autotile ? "Yes" : "No"]
" - dat += "Place floor tiles: [placetiles ? "Yes" : "No"]
" - dat += "Replace existing floor tiles with custom tiles: [replacetiles ? "Yes" : "No"]
" - dat += "Repair damaged tiles and platings: [fixfloors ? "Yes" : "No"]
" - dat += "Traction Magnets: [anchored ? "Engaged" : "Disengaged"]
" - dat += "Patrol Station: [auto_patrol ? "Yes" : "No"]
" - var/bmode - if(targetdirection) - bmode = dir2text(targetdirection) - else - bmode = "disabled" - dat += "Line Mode : [bmode]
" - - return dat - /mob/living/simple_animal/bot/floorbot/attackby(obj/item/W , mob/user, params) if(istype(W, /obj/item/stack/tile/plasteel)) to_chat(user, "The floorbot can produce normal tiles itself.") @@ -161,26 +131,44 @@ if(user) to_chat(user, "[src] buzzes and beeps.") -/mob/living/simple_animal/bot/floorbot/Topic(href, href_list) - if(..()) - return 1 +// Variables sent to TGUI +/mob/living/simple_animal/bot/floorbot/ui_data(mob/user) + var/list/data = ..() + if(!locked || issilicon(user) || IsAdminGhost(user)) + data["custom_controls"]["tile_hull"] = autotile + data["custom_controls"]["place_tiles"] = placetiles + data["custom_controls"]["place_custom"] = replacetiles + data["custom_controls"]["repair_damage"] = fixfloors + data["custom_controls"]["traction_magnets"] = anchored + data["custom_controls"]["tile_stack"] = 0 + data["custom_controls"]["line_mode"] = FALSE + if(specialtiles) + data["custom_controls"]["tile_stack"] = specialtiles + if(targetdirection) + data["custom_controls"]["line_mode"] = dir2text(targetdirection) + return data - switch(href_list["operation"]) - if("replace") +// Actions received from TGUI +/mob/living/simple_animal/bot/floorbot/ui_act(action, params) + . = ..() + if(. || !hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) + return TRUE + switch(action) + if("place_custom") replacetiles = !replacetiles - if("place") + if("place_tiles") placetiles = !placetiles - if("fix") + if("repair_damage") fixfloors = !fixfloors - if("autotile") + if("tile_hull") autotile = !autotile - if("anchor") + if("traction_magnets") anchored = !anchored - if("eject") + if("eject_tiles") if(specialtiles && tiletype != null) empty_tiles() - if("linemode") + if("line_mode") var/setdir = input("Select construction direction:") as null|anything in list("north","east","south","west","disable") switch(setdir) if("north") @@ -193,7 +181,7 @@ targetdirection = 8 if("disable") targetdirection = null - update_controls() + return /mob/living/simple_animal/bot/floorbot/proc/empty_tiles() new tiletype(drop_location(), specialtiles) diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index 9625d2b084..eb415b9bb5 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -78,24 +78,6 @@ text_dehack = "You reboot [name] and restore the sound control system." text_dehack_fail = "[name] refuses to accept your authority!" -/mob/living/simple_animal/bot/honkbot/get_controls(mob/user) - var/dat - dat += hack(user) - dat += showpai(user) - dat += text({" -Honkomatic Bike Horn Unit v1.0.7 controls

-Status: []
-Behaviour controls are [locked ? "locked" : "unlocked"]
-Maintenance panel panel is [open ? "opened" : "closed"]"}, - -"[on ? "On" : "Off"]" ) - - if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user)) - dat += text({"
Auto Patrol: []"}, - -"[auto_patrol ? "On" : "Off"]" ) - return dat - /mob/living/simple_animal/bot/honkbot/proc/judgement_criteria() var/final = NONE if(check_records) diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index b343328e7f..e00adfd8e8 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -155,87 +155,63 @@ /mob/living/simple_animal/bot/medbot/attack_paw(mob/user) return attack_hand(user) -/mob/living/simple_animal/bot/medbot/get_controls(mob/user) - var/dat - dat += hack(user) - dat += showpai(user) - dat += "Medical Unit Controls v1.1

" - dat += "Status: [on ? "On" : "Off"]
" - dat += "Maintenance panel panel is [open ? "opened" : "closed"]
" - dat += "Beaker: " +// Variables sent to TGUI +/mob/living/simple_animal/bot/medbot/ui_data(mob/user) + var/list/data = ..() if(reagent_glass) - dat += "Loaded \[[reagent_glass.reagents.total_volume]/[reagent_glass.reagents.maximum_volume]\]" - else - dat += "None Loaded" - dat += "
Behaviour controls are [locked ? "locked" : "unlocked"]
" + data["custom_controls"]["beaker"] = reagent_glass + data["custom_contrlos"]["reagents"] = "[reagent_glass.reagents.total_volume]/[reagent_glass.reagents.maximum_volume]" if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user)) - dat += "Healing Threshold: " - dat += "-- " - dat += "- " - dat += "[heal_threshold] " - dat += "+ " - dat += "++" - dat += "
" + data["custom_controls"]["injection_amount"] = injection_amount + data["custom_controls"]["use_beaker"] = use_beaker + data["custom_controls"]["treat_virus"] = treat_virus + data["custom_controls"]["heal_threshold"] = heal_threshold + data["custom_controls"]["speaker"] = !shut_up + data["custom_controls"]["crit_alerts"] = declare_crit + data["custom_controls"]["stationary_mode"] = stationary_mode + return data - dat += "Injection Level: " - dat += "- " - dat += "[injection_amount] " - dat += "+ " - dat += "
" +// Actions received from TGUI +/mob/living/simple_animal/bot/medbot/ui_act(action, params) + . = ..() + if(. || !hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) + return TRUE + switch(action) + if("heal_threshold") + var/adjust_num = round(text2num(params["threshold"])) + heal_threshold = adjust_num + if(heal_threshold < 5) + heal_threshold = 5 + if(heal_threshold > 75) + heal_threshold = 75 - dat += "Reagent Source: " - dat += "[use_beaker ? "Loaded Beaker (When available)" : "Internal Synthesizer"]
" + if("injection_amount") + var/adjust_num = round(text2num(params["amount"])) + injection_amount = adjust_num + if(injection_amount < 1) + injection_amount = 1 + if(injection_amount > 15) + injection_amount = 15 - dat += "Treat Viral Infections: [treat_virus ? "Yes" : "No"]
" - dat += "The speaker switch is [shut_up ? "off" : "on"]. Toggle
" - dat += "Critical Patient Alerts: [declare_crit ? "Yes" : "No"]
" - dat += "Patrol Station: [auto_patrol ? "Yes" : "No"]
" - dat += "Stationary Mode: [stationary_mode ? "Yes" : "No"]
" + if("use_beaker") + use_beaker = !use_beaker - return dat + if("eject") + if(!isnull(reagent_glass)) + reagent_glass.forceMove(drop_location()) + reagent_glass = null -/mob/living/simple_animal/bot/medbot/Topic(href, href_list) - if(..()) - return 1 + if("speaker") + shut_up = !shut_up + if("crit_alerts") + declare_crit = !declare_crit + if("stationary_mode") + stationary_mode = !stationary_mode + path = list() + update_appearance() - if(href_list["adj_threshold"]) - var/adjust_num = text2num(href_list["adj_threshold"]) - heal_threshold += adjust_num - if(heal_threshold < 5) - heal_threshold = 5 - if(heal_threshold > 75) - heal_threshold = 75 - - else if(href_list["adj_inject"]) - var/adjust_num = text2num(href_list["adj_inject"]) - injection_amount += adjust_num - if(injection_amount < 5) - injection_amount = 5 - if(injection_amount > 15) - injection_amount = 15 - - else if(href_list["use_beaker"]) - use_beaker = !use_beaker - - else if(href_list["eject"] && (!isnull(reagent_glass))) - reagent_glass.forceMove(drop_location()) - reagent_glass = null - - else if(href_list["togglevoice"]) - shut_up = !shut_up - - else if(href_list["critalerts"]) - declare_crit = !declare_crit - - else if(href_list["stationary"]) - stationary_mode = !stationary_mode - path = list() - update_icon() - - else if(href_list["virus"]) - treat_virus = !treat_virus - - update_controls() + if("virus") + treat_virus = !treat_virus return /mob/living/simple_animal/bot/medbot/attackby(obj/item/W as obj, mob/user as mob, params) @@ -251,7 +227,6 @@ reagent_glass = W to_chat(user, "You insert [W].") - show_controls(user) else if(istype(W, /obj/item/reagent_containers/syringe/piercing)) if(bot_core.allowed(user) && open && !(upgrades & UPGRADE_MEDICAL_PIERERCING)) diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 077e31062a..dcb5e5f237 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -276,56 +276,6 @@ if("ejectpai") ejectpairemote(user) -// TODO: remove this; PDAs currently depend on it -/mob/living/simple_animal/bot/mulebot/get_controls(mob/user) - var/ai = hasSiliconAccessInArea(user) - var/dat - dat += "

Multiple Utility Load Effector Mk. V

" - dat += "ID: [id]
" - dat += "Power: [on ? "On" : "Off"]
" - dat += "

Status

" - dat += "
" - switch(mode) - if(BOT_IDLE) - dat += "Ready" - if(BOT_DELIVER) - dat += "[mode_name[BOT_DELIVER]]" - if(BOT_GO_HOME) - dat += "[mode_name[BOT_GO_HOME]]" - if(BOT_BLOCKED) - dat += "[mode_name[BOT_BLOCKED]]" - if(BOT_NAV,BOT_WAIT_FOR_NAV) - dat += "[mode_name[BOT_NAV]]" - if(BOT_NO_ROUTE) - dat += "[mode_name[BOT_NO_ROUTE]]" - dat += "
" - - dat += "Current Load: [load ? load.name : "none"]
" - dat += "Destination: [!destination ? "none" : destination]
" - dat += "Power level: [cell ? cell.percent() : 0]%" - - if(locked && !ai && !IsAdminGhost(user)) - dat += " 
Controls are locked
Unlock Controls" - else - dat += " 
Controls are unlocked
Lock Controls

" - - dat += "Toggle Power
" - dat += "Stop
" - dat += "Proceed
" - dat += "Return to Home
" - dat += "Set Destination
" - dat += "Set Bot ID
" - dat += "Set Home
" - dat += "Toggle Auto Return Home ([auto_return ? "On":"Off"])
" - dat += "Toggle Auto Pickup Crate ([auto_pickup ? "On":"Off"])
" - dat += "Toggle Delivery Reporting ([report_delivery ? "On" : "Off"])
" - if(load) - dat += "Unload Now
" - dat += "
The maintenance hatch is closed.
" - - return dat - - // returns true if the bot has power /mob/living/simple_animal/bot/mulebot/proc/has_power() return !open && cell && cell.charge > 0 && (!wires.is_cut(WIRE_POWER1) && !wires.is_cut(WIRE_POWER2)) diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index 8bb30a11a6..c3ab805d62 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -209,57 +209,34 @@ text_dehack = "You reboot [name] and restore the target identification." text_dehack_fail = "[name] refuses to accept your authority!" -/mob/living/simple_animal/bot/secbot/get_controls(mob/user) - var/dat - dat += hack(user) - dat += showpai(user) - dat += text({" -Securitron v1.6 controls

-Status: []
-Behaviour controls are [locked ? "locked" : "unlocked"]
-Maintenance panel panel is [open ? "opened" : "closed"]"}, - -"[on ? "On" : "Off"]" ) - +// Variables sent to TGUI +/mob/living/simple_animal/bot/secbot/ui_data(mob/user) + var/list/data = ..() if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user)) - dat += text({"
-Arrest Unidentifiable Persons: []
-Arrest for Unauthorized Weapons: []
-Arrest for Warrant: []
-Operating Mode: []
-Report Arrests[]
-Auto Patrol: []"}, + data["custom_controls"]["check_id"] = idcheck + data["custom_controls"]["check_weapons"] = weaponscheck + data["custom_controls"]["check_warrants"] = check_records + data["custom_controls"]["handcuff_targets"] = !arrest_type + data["custom_controls"]["arrest_alert"] = declare_arrests + return data -"[idcheck ? "Yes" : "No"]", -"[weaponscheck ? "Yes" : "No"]", -"[check_records ? "Yes" : "No"]", -"[arrest_type ? "Detain" : "Arrest"]", -"[declare_arrests ? "Yes" : "No"]", -"[auto_patrol ? "On" : "Off"]" ) - - return dat - -/mob/living/simple_animal/bot/secbot/Topic(href, href_list) - if(..()) - return 1 - if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) +// Actions received from TGUI +/mob/living/simple_animal/bot/secbot/ui_act(action, params) + . = ..() + if(. || !hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) return TRUE - switch(href_list["operation"]) - if("idcheck") + switch(action) + if("check_id") idcheck = !idcheck - update_controls() - if("weaponscheck") + if("check_weapons") weaponscheck = !weaponscheck - update_controls() - if("ignorerec") + if("check_warrants") check_records = !check_records - update_controls() - if("switchmode") + if("handcuff_targets") arrest_type = !arrest_type - update_controls() - if("declarearrests") + if("arrest_alert") declare_arrests = !declare_arrests - update_controls() + return /mob/living/simple_animal/bot/secbot/proc/retaliate(mob/living/carbon/human/H) var/judgement_criteria = judgement_criteria() diff --git a/tgui/packages/tgui/interfaces/SimpleBot.tsx b/tgui/packages/tgui/interfaces/SimpleBot.tsx new file mode 100644 index 0000000000..b5cfce4be7 --- /dev/null +++ b/tgui/packages/tgui/interfaces/SimpleBot.tsx @@ -0,0 +1,351 @@ +import { multiline } from '../../common/string'; +import { useBackend } from '../backend'; +import { Button, Icon, LabeledControls, NoticeBox, Section, Slider, Stack, Tooltip } from '../components'; +import { Window } from '../layouts'; + +type SimpleBotContext = { + can_hack: number; + locked: number; + emagged: number; + pai: Pai; + settings: Settings; + custom_controls: Controls; +}; + +type Pai = { + allow_pai: number; + card_inserted: number; +}; + +type Settings = { + power: number; + airplane_mode: number; + maintenance_lock: number; + patrol_station: number; +}; + +type Controls = { + [Control: string]: [Value: number]; +}; + +export const SimpleBot = (_, context) => { + const { data } = useBackend(context); + const { can_hack, locked } = data; + const access = (!locked || can_hack); + + return ( + + + + +
}> + {!access + ? (Locked!) + : ()} +
+
+ {access && ( + +
+ +
+
+ )} +
+
+
+ ); +}; + +/** Creates a lock button at the top of the controls */ +const TabDisplay = (_, context) => { + const { act, data } = useBackend(context); + const { can_hack, locked, pai } = data; + const { allow_pai } = pai; + + return ( + <> + {!!can_hack && } + {!!allow_pai && } + + + ); +}; + +/** If user is a bad silicon, they can press this button to hack the bot */ +const HackButton = (_, context) => { + const { act, data } = useBackend(context); + const { can_hack, emagged } = data; + + return ( + + ); +}; + +/** Creates a button indicating PAI status and offers the eject action */ +const PaiButton = (_, context) => { + const { act, data } = useBackend(context); + const { card_inserted } = data.pai; + + if (!card_inserted) { + return ( + + ); + } else { + return ( + + ); + } +}; + +/** Displays the bot's standard settings: Power, patrol, etc. */ +const SettingsDisplay = (_, context) => { + const { act, data } = useBackend(context); + const { settings } = data; + const { airplane_mode, patrol_station, power, maintenance_lock } = settings; + + return ( + + + + act('power')} + /> + + + + + act('airplane')} + /> + + + + + act('patrol')} + /> + + + + + act('maintenance')} + /> + + + + ); +}; + +/** Iterates over custom controls. + * Calls the helper to identify which button to use. + */ +const ControlsDisplay = (_, context) => { + const { data } = useBackend(context); + const { custom_controls } = data; + + return ( + + {Object.entries(custom_controls).map((control) => { + return ( + + letter.toUpperCase())}> + + + ); + })} + + ); +}; + +/** Helper function which identifies which button to create. + * Might need some fine tuning if you are using more advanced controls. + */ +const ControlHelper = (props, context) => { + const { act } = useBackend(context); + const { control } = props; + if (control[0] === 'sync_tech') { + /** Control is for sync - this is medbot specific */ + return ; + } else if (control[0] === 'heal_threshold') { + /** Control is a threshold - this is medbot specific */ + return ; + } else if (control[0] === 'injection_amount') { + /** Control is for injection - this is medbot specific */ + return ; + } else if (control[0] === 'tile_stack') { + return ; + } else if (control[0] === 'line_mode') { + return ; + } else { + /** Control is a boolean of some type */ + return ( + act(control[0])} + /> + ); + } +}; + +/** Small button to sync medbots with research. */ +const MedbotSync = (_, context) => { + const { act } = useBackend(context); + + return ( + + act('sync_tech')} + /> + + ); +}; + +/** Slider button for medbot injection thresholds */ +const InjectionThreshold = (props, context) => { + const { act } = useBackend(context); + const { control } = props; + + return ( + + act(control[0], { amount: value })} + /> + + ); +}; + +/** Slider button for medbot healing thresholds */ +const MedbotThreshold = (props, context) => { + const { act } = useBackend(context); + const { control } = props; + + return ( + + act(control[0], { threshold: value })} + /> + + ); +}; + +/** Tile stacks for floorbots - shows number and eject button */ +const FloorbotTiles = (props, context) => { + const { act } = useBackend(context); + const { control } = props; + + return ( + + ); +}; + +/** Direction indicator for floorbot when line mode is chosen. */ +const FloorbotLine = (props, context) => { + const { act } = useBackend(context); + const { control } = props; + + return ( + + act('line_mode')} + size={!control[1] ? 2 : 1.5}> + {' '} + {control[1] ? control[1].toString().charAt(0).toUpperCase() : ''} + + + ); +}; From 8acb800301760d7535a091a02cb0ce5dc52956d3 Mon Sep 17 00:00:00 2001 From: SandPoot Date: Wed, 2 Feb 2022 17:57:48 -0300 Subject: [PATCH 10/24] Upload files --- code/modules/shuttle/custom_shuttle.dm | 82 +++++------ .../tgui/interfaces/CustomShuttleConsole.js | 135 ++++++++++++++++++ 2 files changed, 174 insertions(+), 43 deletions(-) create mode 100644 tgui/packages/tgui/interfaces/CustomShuttleConsole.js diff --git a/code/modules/shuttle/custom_shuttle.dm b/code/modules/shuttle/custom_shuttle.dm index 8047e972db..e9a5ca4688 100644 --- a/code/modules/shuttle/custom_shuttle.dm +++ b/code/modules/shuttle/custom_shuttle.dm @@ -35,67 +35,63 @@ . = ..() . += distance_multiplier < 1 ? "Bluespace shortcut module installed. Route is [distance_multiplier]x the original length." : "" -/obj/machinery/computer/custom_shuttle/ui_interact(mob/user) +/obj/machinery/computer/custom_shuttle/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "CustomShuttleConsole", name) + ui.open() + +/obj/machinery/computer/custom_shuttle/ui_data(mob/user) + var/list/data = list() var/list/options = params2list(possible_destinations) var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId) - var/dat = "[M ? "Current Location : [M.getStatusText()]" : "Shuttle link required."]

" + data["docked_location"] = M ? M.get_status_text_tgui() : null if(M) - dat += "Run Flight Calculations
" - dat += "Shuttle Data
" - dat += "Shuttle Mass: [calculated_mass/10]tons
" - dat += "Engine Force: [calculated_dforce]kN ([calculated_engine_count] engines)
" - dat += "Sublight Speed: [calculated_speed]ms-1
" - dat += calculated_speed < 1 ? "INSUFFICIENT ENGINE POWER
" : "" - dat += calculated_non_operational_thrusters > 0 ? "Warning: [calculated_non_operational_thrusters] thrusters offline.
" : "" - dat += "Fuel Consumption: [calculated_consumption]units per distance
" - dat += "Engine Cooldown: [calculated_cooldown]s
" - var/destination_found + calculateStats(FALSE, 0, TRUE) + data["ship_name"] = M.area_type ? M.area_type:name : "ERROR" + data["shuttle_mass"] = calculated_mass/10 + data["engine_force"] = calculated_dforce + data["engines"] = calculated_engine_count + data["calculated_speed"] = calculated_speed + data["damaged_engines"] = calculated_non_operational_thrusters + data["calculated_consumption"] = calculated_consumption + data["calculated_cooldown"] = calculated_cooldown + data["locations"] = list() for(var/obj/docking_port/stationary/S in SSshuttle.stationary) if(!options.Find(S.id)) continue - if(!M.check_dock(S, silent=TRUE)) + if(!M.check_dock(S, silent = TRUE)) continue - if(calculated_speed == 0) - break - destination_found = TRUE - var/dist = round(calculateDistance(S)) - dat += "Target [S.name] (Dist: [dist] | Fuel Cost: [round(dist * calculated_consumption)] | Time: [round(dist / calculated_speed)])
" - if(!destination_found) - dat += "No valid destinations
" - dat += "
[targetLocation ? "Target Location : [targetLocation]" : "No Target Location"]" - dat += "
Initate Flight
" - dat += "Close" + var/list/location_data = list( + id = S.id, + name = S.name, + dist = round(calculateDistance(S)) + ) + data["locations"] += list(location_data) + data["destination"] = targetLocation + return data - popup = new(user, "computer", M ? M.name : "shuttle", 350, 450) - popup.set_content("
[dat]
") - popup.open() - -/obj/machinery/computer/custom_shuttle/Topic(href, href_list) - if(..()) +/obj/machinery/computer/custom_shuttle/ui_act(action, params) + . = ..() + if(.) return - usr.set_machine(src) - src.add_fingerprint(usr) if(!allowed(usr)) to_chat(usr, "Access denied.") return - if(href_list["calculate"]) - calculateStats() - ui_interact(usr) - return var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId) if(!M) + to_chat(usr, "Shuttle Link Required.") return if(M.launch_status == ENDGAME_LAUNCHED) return - if(href_list["setloc"]) - SetTargetLocation(href_list["setloc"]) - ui_interact(usr) - return - else if(href_list["fly"]) - Fly() - ui_interact(usr) - return + + switch(action) + if("setloc") + SetTargetLocation(params["setloc"]) + if("fly") + Fly() + return /obj/machinery/computer/custom_shuttle/proc/calculateDistance(var/obj/docking_port/stationary/port) var/deltaX = port.x - x diff --git a/tgui/packages/tgui/interfaces/CustomShuttleConsole.js b/tgui/packages/tgui/interfaces/CustomShuttleConsole.js new file mode 100644 index 0000000000..b1a764e99b --- /dev/null +++ b/tgui/packages/tgui/interfaces/CustomShuttleConsole.js @@ -0,0 +1,135 @@ +import { useBackend } from '../backend'; +import { Box, Button, Flex, Icon, LabeledList, Modal, Section, Table, Tooltip } from '../components'; +import { Window } from '../layouts'; + +export const CustomShuttleConsole = (props, context) => { + const { act, data } = useBackend(context); + const { + docked_location, + ship_name = "ERROR", + shuttle_mass = 0, + engine_force = 0, + engines = 0, + calculated_speed = 0, + calculated_non_operational_thrusters = 0, + calculated_consumption = 0, + calculated_cooldown = 0, + locations = [], + destination = null, + } = data; + return ( + + +
+ {!docked_location ? ( + + + + + + + {"Shuttle Link Required."} + + + + ) : ( + <> +
{ship_name}
+
+ + + {docked_location} + + + {shuttle_mass / 10}ton{shuttle_mass != 1 ? "s" : null} + + + {engine_force}Kn ({engines} engine{engines != 1 ? "s" : null}) + + + {calculated_speed}ms{-1} {calculated_speed < 1 ? : null} + + {calculated_non_operational_thrusters.len + ? + {calculated_non_operational_thrusters} thruster{calculated_non_operational_thrusters != 1 ? "s are" : " is"} not operational. + + : null} + + {calculated_consumption} unit{calculated_consumption != 1 ? "s" : null} per travel + + + {calculated_cooldown}s + + +
+
+ {locations.length===0 && ( + + No valid destinations + + ) || ( + + {locations.map(location => ( + + {location.name} + + + ))} +
({location.dist}m) +
+ )} +
+
+
+ + )} +
+
+
+ ); +}; + +const getLocationNameById = (locations, id) => { + return locations?.find(location => location.id === id)?.name; +}; + +const getLocationIdByName = (locations, name) => { + return locations?.find(location => location.name === name)?.id; +}; + +const STATUS_COLOR_KEYS = { + "In Transit": "good", + "Idle": "average", + "Igniting": "average", + "Recharging": "average", + "Missing": "bad", + "Unauthorized Access": "bad", + "Locked": "bad", +}; From 0fca5f80eb12d9977f34896e879674cbf2f736cd Mon Sep 17 00:00:00 2001 From: SandPoot Date: Wed, 2 Feb 2022 18:51:26 -0300 Subject: [PATCH 11/24] i have three different js linters and one says that the other is wrong. --- .../tgui/interfaces/CustomShuttleConsole.js | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/tgui/packages/tgui/interfaces/CustomShuttleConsole.js b/tgui/packages/tgui/interfaces/CustomShuttleConsole.js index b1a764e99b..f6d76754a7 100644 --- a/tgui/packages/tgui/interfaces/CustomShuttleConsole.js +++ b/tgui/packages/tgui/interfaces/CustomShuttleConsole.js @@ -1,3 +1,4 @@ +/* eslint-disable react/jsx-closing-tag-location */ import { useBackend } from '../backend'; import { Box, Button, Flex, Icon, LabeledList, Modal, Section, Table, Tooltip } from '../components'; import { Window } from '../layouts'; @@ -54,21 +55,21 @@ export const CustomShuttleConsole = (props, context) => { {docked_location} - {shuttle_mass / 10}ton{shuttle_mass != 1 ? "s" : null} + {shuttle_mass / 10}ton{shuttle_mass !== 1 ? "s" : null} - {engine_force}Kn ({engines} engine{engines != 1 ? "s" : null}) + {engine_force}Kn ({engines} engine{engines !== 1 ? "s" : null}) {calculated_speed}ms{-1} {calculated_speed < 1 ? : null} {calculated_non_operational_thrusters.len ? - {calculated_non_operational_thrusters} thruster{calculated_non_operational_thrusters != 1 ? "s are" : " is"} not operational. + {calculated_non_operational_thrusters} thruster{calculated_non_operational_thrusters !== 1 ? "s are" : " is"} not operational. : null} - {calculated_consumption} unit{calculated_consumption != 1 ? "s" : null} per travel + {calculated_consumption} unit{calculated_consumption !== 1 ? "s" : null} per travel {calculated_cooldown}s @@ -82,23 +83,23 @@ export const CustomShuttleConsole = (props, context) => { color="bad"> No valid destinations - ) || ( + ) || ( {locations.map(location => ( - + {location.name} ))}
({location.dist}m) -
- )} + )}