From fff4e9ffc55c9f4f59956dca0aee152da31f2921 Mon Sep 17 00:00:00 2001 From: Runa Dacino Date: Sun, 12 Feb 2023 21:03:07 +0100 Subject: [PATCH] Implements new machine that creates autoinjectors en masse --- code/game/machinery/frame.dm | 6 + .../items/weapons/circuitboards/frame.dm | 15 +- .../reagents/machinery/injector_maker.dm | 181 ++++++++++++++++++ icons/obj/chemical_vr.dmi | Bin 2107 -> 2850 bytes vorestation.dme | 1 + 5 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 code/modules/reagents/machinery/injector_maker.dm diff --git a/code/game/machinery/frame.dm b/code/game/machinery/frame.dm index 6c71e63207..c3fa1701fd 100644 --- a/code/game/machinery/frame.dm +++ b/code/game/machinery/frame.dm @@ -202,6 +202,12 @@ frame_class = FRAME_CLASS_MACHINE frame_size = 3 +/datum/frame/frame_types/injector_maker + name = "Ready-to-Use Medicine 3000" + frame_class = FRAME_CLASS_MACHINE + circuit = /obj/machinery/atmospheric_field_generator + frame_size = 3 + ////////////////////////////// // Frame Object (Structure) ////////////////////////////// diff --git a/code/game/objects/items/weapons/circuitboards/frame.dm b/code/game/objects/items/weapons/circuitboards/frame.dm index 7ef7c4bfef..000cd011f6 100644 --- a/code/game/objects/items/weapons/circuitboards/frame.dm +++ b/code/game/objects/items/weapons/circuitboards/frame.dm @@ -264,4 +264,17 @@ /obj/item/weapon/stock_parts/micro_laser/high = 2, //field emitters /obj/item/weapon/stock_parts/scanning_module = 1, //atmosphere sensor /obj/item/weapon/stock_parts/capacitor/adv = 1, //for the JUICE - /obj/item/stack/cable_coil = 10) \ No newline at end of file + /obj/item/stack/cable_coil = 10) + + +/obj/item/weapon/circuitboard/injector_maker + name = T_BOARD("Ready-to-Use Medicine 3000") + build_path = /obj/machinery/injector_maker + board_type = new /datum/frame/frame_types/injector_maker + origin_tech = list(TECH_BIO = 3, TECH_ENGINEERING = 2, TECH_MATERIAL = 2) + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 2, + /obj/item/weapon/stock_parts/manipulator = 1, + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/weapon/stock_parts/console_screen = 1 + ) diff --git a/code/modules/reagents/machinery/injector_maker.dm b/code/modules/reagents/machinery/injector_maker.dm new file mode 100644 index 0000000000..0aa79fa88c --- /dev/null +++ b/code/modules/reagents/machinery/injector_maker.dm @@ -0,0 +1,181 @@ +/obj/machinery/injector_maker + name = "Ready-to-Use Medicine 3000" + desc = "Molds plastic into autoinjectors and fills them with chemicals. \n Add a beaker or a bottle filled with chemicals and a sheet of plastic to use!" + icon = 'icons/obj/chemical_vr.dmi' //placeholder for testing + icon_state = "injector" + use_power = USE_POWER_IDLE + anchored = FALSE + density = FALSE + clicksound = "button" + clickvol = 30 + idle_power_usage = 5 + active_power_usage = 100 + circuit = /obj/item/weapon/circuitboard/injector_maker + var/obj/item/weapon/reagent_containers/beaker = null + var/plastic_amount = 0 + var/max_plastic = 10000 + var/stack_value = 2000 + var/material_per_sheet = 2000 + var/plastic_cost_small = 10 + var/plastic_cost_large = 500 + var/list/beaker_reagents_list = list() + + +/obj/machinery/injector_maker/Initialize() + . = ..() + default_apply_parts() + +obj/machinery/injector_maker/update_icon() + if(!plastic_amount && !beaker) + icon_state = "injector" + else if(!plastic_amount && beaker != null) + icon_state = "injector_b" + else if(!beaker && plastic_amount > 0) + icon_state = "injector_p" + else if(beaker != null && plastic_amount > 0) + icon_state = "injector_pb" + + +/obj/machinery/injector_maker/attackby(var/obj/item/O as obj, var/mob/user as mob) + + if (istype(O, /obj/item/device/multitool)) + return ..() + + if(istype(O,/obj/item/weapon/reagent_containers/glass) || \ + istype(O,/obj/item/weapon/reagent_containers/food/drinks/glass2) || \ + istype(O,/obj/item/weapon/reagent_containers/food/drinks/shaker)) + + if (beaker) + return 1 + else + src.beaker = O + user.drop_item() + O.loc = src + update_icon() + src.updateUsrDialog() + return 0 + + if(istype(O,/obj/item/stack/material)) + if(O.get_material_name() == MAT_PLASTIC) + var/obj/item/stack/S = O + var/input_amount = tgui_input_number(user, "How many sheets would you like to add?", "Add plastic", 0, S.get_amount(), 0, 0, TRUE) + if(input_amount == 0) + return + var/plastic_input = input_amount * stack_value + var/free_space = max_plastic - src.plastic_amount + if(plastic_input > free_space) + to_chat(user, SPAN_WARNING("Storage is full! There is only [free_space] units worth of space left!")) + else + S.use(input_amount) + src.plastic_amount = plastic_input + update_icon() + +/obj/machinery/injector_maker/AltClick(mob/user) + . = ..() + if(beaker) + if(!user.incapacitated() && Adjacent(user)) + user.put_in_hands(beaker) + else + beaker.forceMove(drop_location()) + beaker = null + update_icon() + +/obj/machinery/injector_maker/examine(mob/user) + . = ..() + if(!in_range(user, src) && !issilicon(user) && !isobserver(user)) + . += "You're too far away to examine [src]'s contents and display!" + return + + if(beaker) + . += "\The [src] contains:" + if(beaker) + . += "- \A [beaker]." + + . += "\The [src] contains [plastic_amount] units of plastic.\n It can hold up to [max_plastic] units! 1 sheet gives [stack_value] units." + + if(!(stat & (NOPOWER|BROKEN))) + . += "The status display reads:\n" + if(beaker) + for(var/datum/reagent/R in beaker.reagents.reagent_list) + . += "- [R.volume] units of [R.name]." + +/obj/machinery/injector_maker/attack_hand(mob/user as mob) + interact(user) + +/obj/machinery/injector_maker/interact(mob/user as mob) + if(user.incapacitated() || !beaker) + return + + var/choice = tgui_input_list(user, "There is [plastic_amount] units of plastic left", "Choose what to do", list("large injector", "small injector", "eject", "cancel")) + + switch(choice) + if("cancel") + return + if("eject") + if(!user.incapacitated() && Adjacent(user)) + user.put_in_hands(beaker) + else + beaker.forceMove(drop_location()) + beaker = null + update_icon() + if("small injector") + if(!beaker.reagents.total_volume) + to_chat(user, SPAN_WARNING("Chemical storage is empty!")) + return + if(!plastic_amount) + to_chat(user, SPAN_WARNING("No plastic in storage! Add at least 1 sheet of plastic.")) + return + var/injector_amount = tgui_input_number(user, "How many injectors would you like?", "Make small injectors", 0, 100, 0, 0, TRUE) + if(injector_amount > 0) + var/plastic_needed = injector_amount * plastic_cost_small + if(src.plastic_amount < plastic_needed ) + to_chat(user, SPAN_WARNING("Not enough plastic! You only have enough plastic for [src.plastic_amount / plastic_cost_small] small injectors!")) + return + var/name = sanitize(tgui_input_text(user, "Name Injector", "Naming", null, 32, 0, 0, 0, 0),MAX_MESSAGE_LEN,0,0,0) + make_injector("large injector", injector_amount, name) + update_icon() + if("large injector") + if(!beaker.reagents.total_volume) + to_chat(user, SPAN_WARNING("Chemical storage is empty!")) + return + if(!plastic_amount) + to_chat(user, SPAN_WARNING("No plastic in storage! Add at least 1 sheet of plastic.")) + return + var/injector_amount = tgui_input_number(user, "How many injectors would you like?", "Make small injectors", 0, 100, 0, 0, TRUE) + if(injector_amount > 0) + var/plastic_needed = injector_amount * plastic_cost_small + if(src.plastic_amount < plastic_needed) + to_chat(user, SPAN_WARNING("Not enough plastic! You only have enough plastic for [src.plastic_amount / plastic_cost_large] large injectors!")) + return + var/name = sanitize(tgui_input_text(user, "Name Injector", "Naming", null, 32, 0, 0, 0, 0),MAX_MESSAGE_LEN,0,0,0) + make_injector("large injector", injector_amount, name) + update_icon() + +/obj/machinery/injector_maker/proc/make_injector(var/size, var/amount, var/new_name) + if(!beaker) + return + for(var/i, i <= amount, i++) + switch(size) + if("small injector") + to_world("Making [size], checking if we got enough.") + var/amount_per_injector = CLAMP(beaker.reagents.total_volume / amount, 0, 15) + if(!amount_per_injector || (plastic_cost_small > src.plastic_amount)) + return + to_world("Enough") + var/obj/item/weapon/reagent_containers/hypospray/autoinjector/empty/P = new(loc) + beaker.reagents.trans_to_obj(P, amount_per_injector) + P.update_icon() + if(new_name) + P.name = new_name + src.plastic_amount = src.plastic_amount - plastic_cost_small + + if("large injector") + var/amount_per_injector = CLAMP(beaker.reagents.total_volume / amount, 0, 15) + if(!amount_per_injector || (plastic_cost_large > src.plastic_amount)) + return + var/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/empty/P = new(loc) + beaker.reagents.trans_to_obj(P, amount_per_injector) + P.update_icon() + if(new_name) + P.name = new_name + src.plastic_amount = src.plastic_amount - plastic_cost_large diff --git a/icons/obj/chemical_vr.dmi b/icons/obj/chemical_vr.dmi index a08a052c90f5f070b8a79a18bbc5ecb123226093..224dbe18671135f8258f29eaa1f43a547e1eb102 100644 GIT binary patch literal 2850 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 a4~4dCy>s2r_;~847iekdsh8Za4*D0)WnqN? literal 2107 zcmV-B2*me^P)V=-0C=2*%R3H(Fc3x2+Fr#7YNGsFH<3}~0=5uYc!Ed42F;jc`zfdq-Mi9x zH9Xp<>%n$Tf02de3of$c-dFP0h%NxzZ{S z3mCX)^=6-N+k3A=pU}(7_!`#b&<+vPhsvI-q3tc$&gnliNk_+VChUv=00(19L_t(| zob8)^Ok39(#(##Qq|9S!LKI381&E3kC@>kV%GQ`LO=5znY!QvRMMxXblti1Zz&QJA zE7YOTv>U`QFH=IJ;!ZB1Y;F>^!kS8{`Pde+m@JM)TC>fCrNmJRWZ;<)Q@lUmde_*1 zF*dgp9?8-@?>YAKKF>Yp-1lBxE6ipys~Hc?)sd^s^+bZuTw_)QGp@L}I3oN;qtS<7 z5oiYFYI8kgM}i)(ENnt?aj_>YEiEGSy}i9YCiofP6`vRpei&q46GZWGad8o$9~~X_ zF~MgEJSlh=IOCEtzrX{UL{eA?;G z8w;HvKk;qdSC@_7Zw73y%iuR}T?F9F=~J9F9_O)RUjV?~c#|D>q3gY80cdT#Ov7`R zc<)R#058;?C9E3kx= zZ&+Y78Wp|0z01z)vk97O%nJALU0(S9_qcNQRXSSU1mM5d?r|V-ACm(U0OS{(;TP2| zUOfH|0H;iUpxyl$djDacZeJe6x-Fls{xNLMXhudxf=b3{G%h=T)a-y`tAl^wtMm;i94n2~9_Dx^xSFu)>wq-_2W!GBY#J1I&&~`Y$YGLdcKBD_W;~UVE%8h)S$@>*GNb3Mvbt z!t$Q!TxUFx5%ZXEem)Zxy$4jZP7PMHP7T(Trp1e&+R|OFiq@$?6bjUP5?r&*2?e5f zsW9{zf^lmVi!+R|OF-&uwS#E;1`f_hJa3!t;h5gRTO7K2btSd;E~VHNJtQb@{*Dgnwsl8Z#18Z%gM>vEA|Cr#$so|lIj4p`cao!{iw@i8Np<^ zx0IjqLa*1KXlQ8Q?Y6&locvYe=&f6~XlkzYG&P@!OG!zY(+rhLrI~#!ju8amf^=3% zvFOWSWkFP8MXO`*>Fka1zyLr|_9K+l-Hes){+(Tp*ri+za&+Z+IY7yVjET3~u6MMz zx9{DyZ5uDXRO(T%?sI=^>n1ZZQ)9JSbt;ugV=|d)#P9Z8xl)*wm9@8|q@-P?zW542 zPiJ1LAPD7pz5c|K3-|XF{bx`A<%V?qi^$5#@@|IhSM$FPzE>9! zAujR?NLXAgEL-&5@M-`#4;`FHrxHl>KN9 z{q~%$ev1tt{^9E1!?(54F)P{t5%ohu9BQ@t#tJh1#(gw?^eG@!8v9fj0D%Qd@I`?5 zhpQ_-bu-{E|D68Q#FuvN2pC5J@4jD2+~kqpm92#?u168 zA