From ee9efe61ab6c2358f84005e5d452b1b982106a06 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sat, 6 Jul 2024 02:55:15 -0400 Subject: [PATCH 01/48] Add lathe_medipens module for bounty --- code/__DEFINES/~nova_defines/techweb_nodes.dm | 1 + code/game/machinery/medipen_refiller.dm | 17 +++++- .../lathe_medipens/code/autolathe_designs.dm | 52 ++++++++++++++++++ .../modules/lathe_medipens/code/hypospray.dm | 21 +++++++ .../lathe_medipens/code/medbay_nodes.dm | 15 +++++ .../lathe_medipens/icons/reagent_fillings.dmi | Bin 0 -> 274 bytes .../modules/lathe_medipens/icons/syringe.dmi | Bin 0 -> 621 bytes tgstation.dme | 3 + 8 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 modular_nova/modules/lathe_medipens/code/autolathe_designs.dm create mode 100644 modular_nova/modules/lathe_medipens/code/hypospray.dm create mode 100644 modular_nova/modules/lathe_medipens/code/medbay_nodes.dm create mode 100644 modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi create mode 100644 modular_nova/modules/lathe_medipens/icons/syringe.dmi diff --git a/code/__DEFINES/~nova_defines/techweb_nodes.dm b/code/__DEFINES/~nova_defines/techweb_nodes.dm index 58490c04df3..79b3c0ed05e 100644 --- a/code/__DEFINES/~nova_defines/techweb_nodes.dm +++ b/code/__DEFINES/~nova_defines/techweb_nodes.dm @@ -15,6 +15,7 @@ #define TECHWEB_NODE_CYBERNETICS_DIGITIGRADE_ADVANCED "adv_digitigrade_cyber" #define TECHWEB_NODE_CYBERNETICS_TESHARI "teshari_cyber" #define TECHWEB_NODE_CYBERNETICS_TESHARI_ADVANCED "adv_teshari_cyber" +#define TECHWEB_NODE_MEDBAY_MEDIPENS "medbay_medipens" #define TECHWEB_NODE_MUTANT_TECH "mutant_tech" #define TECHWEB_NODE_NIGHT_VISION_IMPLANTS "nv_implants" #define TECHWEB_NODE_ROBOTIC_SURGERY "improved_robotic_surgery" diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index 57c3fa2f8d4..96c95506dcd 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -19,6 +19,8 @@ /obj/item/reagent_containers/hypospray/medipen/survival = /datum/reagent/medicine/c2/libital, /obj/item/reagent_containers/hypospray/medipen/survival/luxury = /datum/reagent/medicine/c2/penthrite, /obj/item/reagent_containers/hypospray/medipen/invisibility = /datum/reagent/drug/saturnx, + // NOVA EDIT - Custom medipen + /obj/item/reagent_containers/hypospray/medipen/universal = null, ) /obj/machinery/medipen_refiller/Initialize(mapload) @@ -76,14 +78,25 @@ if(medipen.reagents?.reagent_list.len) balloon_alert(user, "medipen full!") return + // NOVA EDIT BEGIN - Custom medipen + var/is_custom = istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal) + if(is_custom && !reagents.has_reagent(null, medipen.volume)) + balloon_alert(user, "not enough reagents!") + return + // NOVA EDIT END if(!reagents.has_reagent(allowed_pens[medipen.type], 10)) balloon_alert(user, "not enough reagents!") return add_overlay("active") if(do_after(user, 2 SECONDS, src)) medipen.used_up = FALSE - medipen.add_initial_reagents() - reagents.remove_reagent(allowed_pens[medipen.type], 10) + // NOVA EDIT BEGIN - Custom medipen + if(is_custom) + reagents.trans_to(medipen, medipen.volume) + else + medipen.add_initial_reagents() + reagents.remove_reagent(allowed_pens[medipen.type], medipen.volume) + // NOVA EDIT END balloon_alert(user, "refilled") use_energy(active_power_usage) cut_overlays() diff --git a/modular_nova/modules/lathe_medipens/code/autolathe_designs.dm b/modular_nova/modules/lathe_medipens/code/autolathe_designs.dm new file mode 100644 index 00000000000..62ff2a4cbf0 --- /dev/null +++ b/modular_nova/modules/lathe_medipens/code/autolathe_designs.dm @@ -0,0 +1,52 @@ +// Medipen design basetype for developer usage only +/datum/design/medipen + name = "Medipen" + id = DESIGN_ID_IGNORE + build_type = PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/plastic = SHEET_MATERIAL_AMOUNT * 3, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, + /datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.1, + /datum/material/silver = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/reagent_containers/hypospray/medipen + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_CHEMISTRY, + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL + +/datum/design/medipen/universal + name = "Universal Medipen" + id = "medipen_universal" + build_path = /obj/item/reagent_containers/hypospray/medipen/universal + +/datum/design/medipen/epinephrine + name = "Epinephrine Medipen" + id = "medipen_epinephrine" + build_path = /obj/item/reagent_containers/hypospray/medipen + +/datum/design/medipen/atropine + name = "Atropine Medipen" + id = "medipen_atropine" + build_path = /obj/item/reagent_containers/hypospray/medipen/atropine + +/datum/design/medipen/atropine + name = "Salbutamol Medipen" + id = "medipen_salbutamol" + build_path = /obj/item/reagent_containers/hypospray/medipen/salbutamol + +/datum/design/medipen/atropine + name = "Oxandrolone Medipen" + id = "medipen_oxandrolone" + build_path = /obj/item/reagent_containers/hypospray/medipen/oxandrolone + +/datum/design/medipen/atropine + name = "Salicylic Acid Medipen" + id = "medipen_salacid" + build_path = /obj/item/reagent_containers/hypospray/medipen/salacid + +/datum/design/medipen/atropine + name = "Pentetic Acid Medipen" + id = "medipen_penacid" + build_path = /obj/item/reagent_containers/hypospray/medipen/penacid diff --git a/modular_nova/modules/lathe_medipens/code/hypospray.dm b/modular_nova/modules/lathe_medipens/code/hypospray.dm new file mode 100644 index 00000000000..0c45a5e43af --- /dev/null +++ b/modular_nova/modules/lathe_medipens/code/hypospray.dm @@ -0,0 +1,21 @@ +/obj/item/reagent_containers/hypospray/medipen/universal + name = "universal medipen" + desc = "It's an auto-injecting syringe with a universal refill port on the side." + icon = 'modular_nova/modules/lathe_medipens/icons/syringe.dmi' + worn_icon_state = "dnainjector0" + inhand_icon_state = "dnainjector0" + list_reagents = null + label_examine = FALSE + +/obj/item/reagent_containers/hypospray/medipen/universal/update_overlays() + . = ..() + var/list/reagent_overlays = update_reagent_overlay() + if(reagent_overlays) + . += reagent_overlays + +/// Returns a list of overlays to add that relate to the reagents inside the syringe +/obj/item/reagent_containers/hypospray/medipen/universal/proc/update_reagent_overlay() + if(reagents?.total_volume) + var/mutable_appearance/filling_overlay = mutable_appearance('modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi', "medipen") + filling_overlay.color = mix_color_from_reagents(reagents.reagent_list) + . += filling_overlay diff --git a/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm b/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm new file mode 100644 index 00000000000..fa8b85ee5ce --- /dev/null +++ b/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm @@ -0,0 +1,15 @@ +/datum/techweb_node/medbay_equip_adv + id = TECHWEB_NODE_MEDBAY_MEDIPENS + display_name = "Auto-Injecting 'Medipen' Syringes" + description = "Advanced auto-injecting syringes, called 'medipens'. Used for automatically injecting medications into patients." + prereq_ids = list(TECHWEB_NODE_MEDBAY_EQUIP_ADV) + design_ids = list( + "medipen_universal", + "medipen_epinephrine", + "medipen_atropine", + "medipen_salbutamol", + "medipen_oxandrolone", + "medipen_salacid", + "medipen_penacid", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) diff --git a/modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi b/modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi new file mode 100644 index 0000000000000000000000000000000000000000..f358e9360021f158511f9aab2d66fd05f1122d9f GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJysD6h5|`BCiMQ8WaRr56rSX+WqBNymzueo6~!TLt4>4I0g3ZYrWfZ%;IcbYpjgzoJ}$6JZ-xa zzj|p1vemk4ZF;lu&&i|WZH}b{6K0?93Yjn^@xr8Alk9(NKei?6#?g!H6>Fs49^9NZ z1!!};r;B4qMC;qD8#xac@VEq8RxF;aSOl$<`e{c4(-0|%yGrYSnIXM zTt1*4AaHSs&zx3L`}KyL_RQRGvfjJWopa~kX4GGl$6O!!Q;-Rw>S+VJEQ_f9$%Xo1 OAOTNTKbLh*2~7a7G-z@F literal 0 HcmV?d00001 diff --git a/modular_nova/modules/lathe_medipens/icons/syringe.dmi b/modular_nova/modules/lathe_medipens/icons/syringe.dmi new file mode 100644 index 0000000000000000000000000000000000000000..8b3c9a35452a30259e8fd91435da6cda1ed4834c GIT binary patch literal 621 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQe{;k5hX6E#mPmP1tppJc?=8{ zb4pKHb2S(UxL&l{+|~Z=(RyEHLC=NN0!Fhm|4d-HyRUU_Lb?7NnOOT9oM~H13OkD4 zT*&C2bVXOMGQ-4F^Zce?U;KQElQL4Itt~6hdsuP`N{OyiJtMvUZ|PI{GZ+2Y(zbkI z_|U61_u|Z((-{~TH+i}^hGaCpow3oIDNyG4etlORVL{$Q3uUB#hrg5ekeYQ$A=^M| ziDSV^w#*K->1`QV6Wso{9NWh8h~v@|8zt6{*9*$h_mpQU{%xy{Z?V3=_x}6ewet6O zJ6_B%5lA^($o^m&+X2~zXeowrhP+IMJB&M)G8VuD8`%ZIc!T!4ZqA6)nY*B9kA81^ z4=>N_(ud*S=l>IGsIl`m4;Mex)}JqEv67X8>7085L(N*X*?$V2r%z8lkzy1iujFJg zeev@s-=+_f>la3_F{lV}J}qX@kbU>(R6Ns$DSnD_{@$)FsnDU& z;*h?fVd|3YdZFv}8XQet)$OmZShOzn;Jc`O|DtbKzuTJ{xsQSCsFB|J^UJ~0 zEI&~3SEZiQVQZA=vP`Y>2}iD9oBVPvgGv0o#97Ns)Kys8y58EK{GU)>yy^dp`zHUK z{ws?VfJ4VLn4v9k1JmE`{dJs0uy8^Io@fQbe5s&?PoLj-a}t<-7(8A5T-G@yGywp5 C1Q4G9 literal 0 HcmV?d00001 diff --git a/tgstation.dme b/tgstation.dme index 14f3ecd3edc..feb811dc0b6 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -7901,6 +7901,9 @@ #include "modular_nova\modules\kahraman_equipment\code\organic_printer_designs\equipment.dm" #include "modular_nova\modules\kahraman_equipment\code\organic_printer_designs\resources.dm" #include "modular_nova\modules\knives\knives.dm" +#include "modular_nova\modules\lathe_medipens\code\autolathe_designs.dm" +#include "modular_nova\modules\lathe_medipens\code\hypospray.dm" +#include "modular_nova\modules\lathe_medipens\code\medbay_nodes.dm" #include "modular_nova\modules\layer_shift\code\mob_movement.dm" #include "modular_nova\modules\liquids\code\drains.dm" #include "modular_nova\modules\liquids\code\height_floors.dm" From 6086076f3f399fdf509b06c30702b558ca32aa6c Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sat, 6 Jul 2024 23:18:43 -0400 Subject: [PATCH 02/48] Add whitelist to medipen refiller --- code/game/machinery/medipen_refiller.dm | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index 96c95506dcd..8a91cb6c50a 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -23,6 +23,17 @@ /obj/item/reagent_containers/hypospray/medipen/universal = null, ) + ///List containing chemicals which custom medipens can contain. + var/static/list/allowed_pen_medicine = list( + /datum/reagent/medicine, + /datum/reagent/vaccine, + ) + ///Blacklist containing medicines which custom medipens can't contain. + var/static/list/disallowed_pen_medicine = list( + /datum/reagent/inverse/, + /datum/reagent/medicine/morphine, + ) + /obj/machinery/medipen_refiller/Initialize(mapload) . = ..() AddComponent(/datum/component/plumbing/simple_demand) @@ -80,9 +91,14 @@ return // NOVA EDIT BEGIN - Custom medipen var/is_custom = istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal) - if(is_custom && !reagents.has_reagent(null, medipen.volume)) - balloon_alert(user, "not enough reagents!") - return + if(is_custom) + for(var/datum/reagent/meds in reagents.reagent_list) + if(!is_type_in_list(meds, allowed_pen_medicine)) + balloon_alert(user, "not enough reagents!") + return + if(is_type_in_list(meds, disallowed_pen_medicine)) + balloon_alert(user, "medipen incompatible!") + return // NOVA EDIT END if(!reagents.has_reagent(allowed_pens[medipen.type], 10)) balloon_alert(user, "not enough reagents!") From 212ca29a946cd3bf84321a774bd450cd238ca849 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sat, 6 Jul 2024 23:19:27 -0400 Subject: [PATCH 03/48] Add low pressure medipen design --- .../modules/lathe_medipens/code/autolathe_designs.dm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/code/autolathe_designs.dm b/modular_nova/modules/lathe_medipens/code/autolathe_designs.dm index 62ff2a4cbf0..09c36990545 100644 --- a/modular_nova/modules/lathe_medipens/code/autolathe_designs.dm +++ b/modular_nova/modules/lathe_medipens/code/autolathe_designs.dm @@ -1,6 +1,6 @@ -// Medipen design basetype for developer usage only +// Basetype for developer usage only. Shouldn't be visible ingame. /datum/design/medipen - name = "Medipen" + name = "Medipen Basetype" id = DESIGN_ID_IGNORE build_type = PROTOLATHE | AWAY_LATHE materials = list( @@ -21,6 +21,11 @@ id = "medipen_universal" build_path = /obj/item/reagent_containers/hypospray/medipen/universal +/datum/design/medipen/universal_lowpressure + name = "Universal Low-Pressure Medipen" + id = "medipen_universal_lowpressure" + build_path = /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure + /datum/design/medipen/epinephrine name = "Epinephrine Medipen" id = "medipen_epinephrine" From 5b2a18b57eb8e29a3f4b4e6988f9aac1932e003c Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sat, 6 Jul 2024 23:19:49 -0400 Subject: [PATCH 04/48] Fix typo in medbay medipen node --- modular_nova/modules/lathe_medipens/code/medbay_nodes.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm b/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm index fa8b85ee5ce..330b617c9e8 100644 --- a/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm +++ b/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm @@ -1,10 +1,11 @@ -/datum/techweb_node/medbay_equip_adv +/datum/techweb_node/medbay_medipens id = TECHWEB_NODE_MEDBAY_MEDIPENS display_name = "Auto-Injecting 'Medipen' Syringes" description = "Advanced auto-injecting syringes, called 'medipens'. Used for automatically injecting medications into patients." prereq_ids = list(TECHWEB_NODE_MEDBAY_EQUIP_ADV) design_ids = list( "medipen_universal", + "medipen_universal_lowpressure", "medipen_epinephrine", "medipen_atropine", "medipen_salbutamol", From 88c97408d13fe801ee1c9bbd9592ecf2810b5eb5 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sat, 6 Jul 2024 23:20:36 -0400 Subject: [PATCH 05/48] Update sprites for lathe medipens --- .../lathe_medipens/icons/reagent_fillings.dmi | Bin 274 -> 344 bytes .../modules/lathe_medipens/icons/syringe.dmi | Bin 621 -> 1050 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi b/modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi index f358e9360021f158511f9aab2d66fd05f1122d9f..f6429080333c8f413c2dba84542c1153335eea1e 100644 GIT binary patch literal 344 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQq@%<5hX6E#mPmP1tppJc?=8{ zbArPPib}tK2`>2f^@*0ZuGYCT=Yuzd8eBAf@JQ#pkLJk$Ajj;{qca|7ea>q%7Ib+F zc?XH+h)yXA4mRQr`aETaMX*tK7f^&}r^V$iq2gf0oRZRylAV^BJ4Cd#cl_F^vExTo z5hKHz2O8-Uw|#a8I%9^Xi(^Pe+9=#^eQCqKRZroGRl_7hJu7<3&LGi+h#WxBv*!sWny0VZ(v b3uB)0KXv6t1y3IW-N@kS>gTe~DWM4fxVMT3 literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJysD6h5|`BCiMQ8WaRr56rSX+WqBNymzueo6~!TLt4>4I0g3ZYrWfZ%;IcbYpjgzoJ}$6JZ-xa zzj|p1vemk4ZF;lu&&i|WZH}b{6K0?93Yjn^@xr8Alk9(NKei?6#?g!H6>Fs49^9NZ z1!!};r;B4qMC;qD8#xac@VEq8RxF;aSOl$<`e{c4(-0|%yGrYSnIXM zTt1*4AaHSs&zx3L`}KyL_RQRGvfjJWopa~kX4GGl$6O!!Q;-Rw>S+VJEQ_f9$%Xo1 OAOTNTKbLh*2~7a7G-z@F diff --git a/modular_nova/modules/lathe_medipens/icons/syringe.dmi b/modular_nova/modules/lathe_medipens/icons/syringe.dmi index 8b3c9a35452a30259e8fd91435da6cda1ed4834c..c0c5b57e1f94e7d84837e4e87da0e830732b445d 100644 GIT binary patch literal 1050 zcmeAS@N?(olHy`uVBq!ia0vp^2|({=UopTy*`GQj)2k?HkK0SwROk zmI;E4DJ~3>SeQLbQeXGwUHM&A@-L$Qoc!xQbvJIGc{69D-{B7%^h`Btw=Dm9ah|o_ ze)(@^#@6X;g8lwYN`0w%dX>fP+3(jsJ=_1|@bcx$zn*?l%;0eQtUN=*ynSj62fUss zi!eAiIv@NQc){UaUBZUni=tP5cH*x3mB;exO-ApDCrkcq*|FlmVukv0c2&+cw+cb?zg_ICcZ(?5=g2z9!wsJZ-$-R5!Qt7{-1@pJsx^j(zwn;t_# z@$Jf|GB`UL@XhcenvGGXCke_0O_GH`mqc=GQqm*vN&?+$ze;a8o>&q2Y{!7(>CX7n}Z1 zi2VH^FTeg@-`_tu>DGU6P zC4Wk{RW0}PVZXF;t;4?k)6C;fnkU6P$<=_w?$6as$BrFa;q?D_jV0&giS>@y;+?Zb zCN@7}n(Nu=$_+gn3d&3;Iv9+Uurl2kx4!BBFa9~(^Wtk}pT8fcetSOsRX_ja_wUd5 z-`_1g!+Yz`t!hj&et-UJ`}XP=ket5x{VVhHXL+ms^igWqX@CFz1`QV6Wso{9NWh8h~v@|8zt6{*9*$h_mpQU{%xy{Z?V3=_x}6ewet6O zJ6_B%5lA^($o^m&+X2~zXeowrhP+IMJB&M)G8VuD8`%ZIc!T!4ZqA6)nY*B9kA81^ z4=>N_(ud*S=l>IGsIl`m4;Mex)}JqEv67X8>7085L(N*X*?$V2r%z8lkzy1iujFJg zeev@s-=+_f>la3_F{lV}J}qX@kbU>(R6Ns$DSnD_{@$)FsnDU& z;*h?fVd|3YdZFv}8XQet)$OmZShOzn;Jc`O|DtbKzuTJ{xsQSCsFB|J^UJ~0 zEI&~3SEZiQVQZA=vP`Y>2}iD9oBVPvgGv0o#97Ns)Kys8y58EK{GU)>yy^dp`zHUK z{ws?VfJ4VLn4v9k1JmE`{dJs0uy8^Io@fQbe5s&?PoLj-a}t<-7(8A5T-G@yGywp5 C1Q4G9 From 66a36c7a8574e808beec599a6ef8cc2ec4fd2083 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sat, 6 Jul 2024 23:21:12 -0400 Subject: [PATCH 06/48] Add low pressure universal medipen, update icons --- .../modules/lathe_medipens/code/hypospray.dm | 56 +++++++++++++++++-- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/code/hypospray.dm b/modular_nova/modules/lathe_medipens/code/hypospray.dm index 0c45a5e43af..df3597a7046 100644 --- a/modular_nova/modules/lathe_medipens/code/hypospray.dm +++ b/modular_nova/modules/lathe_medipens/code/hypospray.dm @@ -2,6 +2,8 @@ name = "universal medipen" desc = "It's an auto-injecting syringe with a universal refill port on the side." icon = 'modular_nova/modules/lathe_medipens/icons/syringe.dmi' + icon_state = "medipen_blue" + base_icon_state = "medipen_blue" worn_icon_state = "dnainjector0" inhand_icon_state = "dnainjector0" list_reagents = null @@ -15,7 +17,53 @@ /// Returns a list of overlays to add that relate to the reagents inside the syringe /obj/item/reagent_containers/hypospray/medipen/universal/proc/update_reagent_overlay() - if(reagents?.total_volume) - var/mutable_appearance/filling_overlay = mutable_appearance('modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi', "medipen") - filling_overlay.color = mix_color_from_reagents(reagents.reagent_list) - . += filling_overlay + if(!reagents?.total_volume) + return + var/mutable_appearance/filling_overlay = mutable_appearance('modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi', "medipen") + filling_overlay.color = mix_color_from_reagents(reagents.reagent_list) + . += filling_overlay + +/obj/item/reagent_containers/hypospray/medipen/universal/lowpressure + name = "universal low-pressure medipen" + desc = "It's a low-pressure auto-injecting syringe with a universal refill port on the side." + icon_state = "medipen_red" + base_icon_state = "medipen_red" + volume = 30 + amount_per_transfer_from_this = 30 + +/obj/item/reagent_containers/hypospray/medipen/universal/lowpressure/update_icon_state() + . = ..() + if(reagents.total_volume >= volume * 0.5) + icon_state = base_icon_state + else if(reagents.total_volume == 0) + icon_state = "[base_icon_state]0" + else + icon_state = "[base_icon_state]15" + +/// Returns a list of overlays to add that relate to the reagents inside the syringe +/obj/item/reagent_containers/hypospray/medipen/universal/lowpressure/update_reagent_overlay() + if(!reagents?.total_volume) + return + var/overlay_icon = "medipen_half" + if(reagents.total_volume >= volume * 0.5) + overlay_icon = "medipen" + var/mutable_appearance/filling_overlay = mutable_appearance('modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi', overlay_icon) + filling_overlay.color = mix_color_from_reagents(reagents.reagent_list) + . += filling_overlay + +/obj/item/reagent_containers/hypospray/medipen/universal/lowpressure/inject(mob/living/affected_mob, mob/user) + if(lavaland_equipment_pressure_check(get_turf(user))) + amount_per_transfer_from_this = initial(amount_per_transfer_from_this) + return ..() + + if(DOING_INTERACTION(user, DOAFTER_SOURCE_SURVIVALPEN)) + to_chat(user,span_notice("You are too busy to use \the [src]!")) + return + + to_chat(user,span_notice("You start manually releasing the low-pressure gauge...")) + if(!do_after(user, 10 SECONDS, affected_mob, interaction_key = DOAFTER_SOURCE_SURVIVALPEN)) + return + + amount_per_transfer_from_this = initial(amount_per_transfer_from_this) * 0.5 + . = ..() + amount_per_transfer_from_this = initial(amount_per_transfer_from_this) From f6b892846970c3f07debb6a68780a73a640b6b61 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 01:00:29 -0400 Subject: [PATCH 07/48] Add readme for lathe_medipens module --- modular_nova/modules/lathe_medipens/README.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 modular_nova/modules/lathe_medipens/README.md diff --git a/modular_nova/modules/lathe_medipens/README.md b/modular_nova/modules/lathe_medipens/README.md new file mode 100644 index 00000000000..f0909afbfa0 --- /dev/null +++ b/modular_nova/modules/lathe_medipens/README.md @@ -0,0 +1,31 @@ +https://github.com/NovaSector/NovaSector/pull/3577 + +## Title: Lathe Medipens + +MODULE ID: lathe_medipens + +### Description: + +Contains empty subtypes of several medipens, custom/universal medipen subtypes with new icons, and techweb nodes/designs for them. + +### TG Proc Changes: + +- `/obj/item/reagent_containers/hypospray/medipen/Initialize` is overridden by this module to implement medipens which spawn without reagents. + +### Defines: + +Local to `hypospray.dm`: + +- Macro `HYPOSPRAY_PATH_HELPER` creates a hypospray subtype. +- Macro `EMPTY_MEDIPEN_HELPER` creates an empty medipen subtype. + +### Master file additions + +- N/A + +### Included files that are not contained in this module: + +- N/A + +### Credits: +- [@Floofies](https://github.com/Floofies) From 1bb4d061b978c3b00b64356dbb89a65ceb8e8b57 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 01:01:03 -0400 Subject: [PATCH 08/48] Cleanup edits to medipen refiller --- code/game/machinery/medipen_refiller.dm | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index 8a91cb6c50a..828784657f3 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -19,8 +19,10 @@ /obj/item/reagent_containers/hypospray/medipen/survival = /datum/reagent/medicine/c2/libital, /obj/item/reagent_containers/hypospray/medipen/survival/luxury = /datum/reagent/medicine/c2/penthrite, /obj/item/reagent_containers/hypospray/medipen/invisibility = /datum/reagent/drug/saturnx, - // NOVA EDIT - Custom medipen + // NOVA EDIT BEGIN - Custom medipen /obj/item/reagent_containers/hypospray/medipen/universal = null, + /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure = null, + // NOVA EDIT END ) ///List containing chemicals which custom medipens can contain. @@ -28,7 +30,7 @@ /datum/reagent/medicine, /datum/reagent/vaccine, ) - ///Blacklist containing medicines which custom medipens can't contain. + ///Blacklist containing chemicals which custom medipens can't contain. var/static/list/disallowed_pen_medicine = list( /datum/reagent/inverse/, /datum/reagent/medicine/morphine, @@ -92,9 +94,12 @@ // NOVA EDIT BEGIN - Custom medipen var/is_custom = istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal) if(is_custom) + if(reagents.total_volume < medipen.volume) + balloon_alert(user, "not enough reagents!") + return for(var/datum/reagent/meds in reagents.reagent_list) if(!is_type_in_list(meds, allowed_pen_medicine)) - balloon_alert(user, "not enough reagents!") + balloon_alert(user, "medipen incompatible!") return if(is_type_in_list(meds, disallowed_pen_medicine)) balloon_alert(user, "medipen incompatible!") From 09eb2644948aadc75e70c721f4ee5aae56bd2bc7 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 01:01:34 -0400 Subject: [PATCH 09/48] Finish icons for universal medipens --- .../modules/lathe_medipens/icons/syringe.dmi | Bin 1050 -> 1226 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/icons/syringe.dmi b/modular_nova/modules/lathe_medipens/icons/syringe.dmi index c0c5b57e1f94e7d84837e4e87da0e830732b445d..f58597c25f3e6242f84809b66bddce256d18a49f 100644 GIT binary patch literal 1226 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGoQ>#KEN?cNllZ!G7N;32F7#J$% zOzk_(b;v-(<@(Ne!!6aBwK|(8ik)2aw>9YGRhAqr^Uil3ZV&scm?+b77!v&fm$0OKMZrc|__9O6jhgeTF;# zr?$=03Cgz@`F=LnWj%jro9)yKOJ5!Ow!E^p?#%_>Hap9>VzH@KH5v>I%pW{m978JR zyq$C2Tcl9p*!+{GN|#l&Iyr=tUJ9g1csOo+excd@rGjg?HRr8`^$HXCoGQ3%TrRls z@XK0xcuPCYUfV9D|E-(DI46v0>8IO?W!p;Y-mEXI-BfF*@s96z?fknx&%Dul_j{eG zu`%<(Wd7fLSFD8`+?Y;yFi3JLC^M$0H1x1cn8;uR6`bk7$eVW6WJc&^>tDCO^!+n? z_tmSu-93->+RfspU7BUfZ~RP4K02d!>L07`RZI6DR^HC^TIAXBJrA3ko1ayF(qvfh z^piisft$s>3=JXAlyw*ySed!c^|LZR*~Tnx)%P@et8DI}o5kX_rFPQIHx4xXG%-v( z=)CdIztz_n89r9nlsxafzk7G>&(G&}t$UaC`S``FwI{=u8{AiaaN?nJM&EWOhFiDi zq&ed5jjX2g*2ac*+n*}Nk& zC%1n{`uBO-Z7cVE#b%aTJbEQE=hv5C)5~A^SSUK4zlI_4C%^n1{ofpGO!j~N()nlR zhbJGEH&6a)$C#X)9G0e+%AoLj4J*S0%lWJfZ}@xvdZ)c}{`YCOzWs!m-alVSoIaFx z;AOm4eaZ_r$)77v{Cs&cMen}?gTmd7TnrMsD%YmeRhjKnwYQ!9qUuU{|by4(A+N>FX_as^n#VU0~(g2EaH-X_oYQaKZ%B)HT5Ui9)i|7z0e zuDmJw+(s-tTvo#Hu<=?Lj&a1Cm`Ddf`_S(6p9RL2j`lR|g!`1WbBB%AO z{=8=z_>8&hsrX#}ikY{|PQ~?^$Ol9m zUpnV!L(tEL{~0{5&aYRyzgz88jl;%22Yxbax35#&e)etUeQBxR)4#k4`nTye(C*6t zX&}oN)csxX?@!jJz1fF8Eqb=vbYjoFwn>mQ`*}a!lggC#& zE?8uYn$FQxKbt>?e}%f%EdCX)^)*-6H{9-Ie0YC;{Eh2ztN;C|QfF(audhptuU`A> z@$0!=&zQ3=%E!OI5H0+*bH)NCP$oK4Zz{h*`sOuRGfT^zJLi6V#VETGJ#PW+{LKE` XX5Q4|C*9q^!imAt)z4*}Q$iB}3Z*;k literal 1050 zcmeAS@N?(olHy`uVBq!ia0vp^2|({=UopTy*`GQj)2k?HkK0SwROk zmI;E4DJ~3>SeQLbQeXGwUHM&A@-L$Qoc!xQbvJIGc{69D-{B7%^h`Btw=Dm9ah|o_ ze)(@^#@6X;g8lwYN`0w%dX>fP+3(jsJ=_1|@bcx$zn*?l%;0eQtUN=*ynSj62fUss zi!eAiIv@NQc){UaUBZUni=tP5cH*x3mB;exO-ApDCrkcq*|FlmVukv0c2&+cw+cb?zg_ICcZ(?5=g2z9!wsJZ-$-R5!Qt7{-1@pJsx^j(zwn;t_# z@$Jf|GB`UL@XhcenvGGXCke_0O_GH`mqc=GQqm*vN&?+$ze;a8o>&q2Y{!7(>CX7n}Z1 zi2VH^FTeg@-`_tu>DGU6P zC4Wk{RW0}PVZXF;t;4?k)6C;fnkU6P$<=_w?$6as$BrFa;q?D_jV0&giS>@y;+?Zb zCN@7}n(Nu=$_+gn3d&3;Iv9+Uurl2kx4!BBFa9~(^Wtk}pT8fcetSOsRX_ja_wUd5 z-`_1g!+Yz`t!hj&et-UJ`}XP=ket5x{VVhHXL+ms^igWqX@CFz Date: Mon, 8 Jul 2024 01:02:43 -0400 Subject: [PATCH 10/48] Macro-ize empty medipen subtypes, add overrides to allow medipens to spawn without reagents, fix iconstates, fix improper noun usage --- .../modules/lathe_medipens/code/hypospray.dm | 63 +++++++++++++++---- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/code/hypospray.dm b/modular_nova/modules/lathe_medipens/code/hypospray.dm index df3597a7046..5af002510f8 100644 --- a/modular_nova/modules/lathe_medipens/code/hypospray.dm +++ b/modular_nova/modules/lathe_medipens/code/hypospray.dm @@ -1,13 +1,54 @@ +/// Create subtype path for hypospray +#define HYPOSPRAY_PATH_HELPER(typename) /obj/item/reagent_containers/hypospray/##typename + +/// Create empty subtype of medipen +#define EMPTY_MEDIPEN_HELPER(typename) HYPOSPRAY_PATH_HELPER(medipen/##typename/empty) {\ + init_reagents = FALSE; \ + used_up = TRUE; \ +} \ + +/obj/item/reagent_containers/hypospray/medipen + /// If FALSE, the medipen will initialize without reagents. + var/init_reagents = TRUE + +// Allows medipens to initialize without reagents if init_reagents is FALSE. +/obj/item/reagent_containers/hypospray/medipen/Initialize(mapload) + if(init_reagents) + return ..() + + var/initial_reagents = list_reagents + list_reagents = null + . = ..() + list_reagents = initial_reagents + +/obj/item/reagent_containers/hypospray/medipen/empty + list_reagents = FALSE + +// Creates /obj/item/reagent_containers/hypospray/medipen/atropine/empty etc... +EMPTY_MEDIPEN_HELPER(atropine) + +EMPTY_MEDIPEN_HELPER(salbutamol) + +EMPTY_MEDIPEN_HELPER(oxandrolone) + +EMPTY_MEDIPEN_HELPER(salacid) + +EMPTY_MEDIPEN_HELPER(penacid) + +#undef HYPOSPRAY_PATH_HELPER +#undef EMPTY_MEDIPEN_HELPER + /obj/item/reagent_containers/hypospray/medipen/universal - name = "universal medipen" + name = "\improper universal medipen" desc = "It's an auto-injecting syringe with a universal refill port on the side." icon = 'modular_nova/modules/lathe_medipens/icons/syringe.dmi' - icon_state = "medipen_blue" + icon_state = "medipen_blue_unused" base_icon_state = "medipen_blue" worn_icon_state = "dnainjector0" inhand_icon_state = "dnainjector0" list_reagents = null label_examine = FALSE + used_up = TRUE /obj/item/reagent_containers/hypospray/medipen/universal/update_overlays() . = ..() @@ -24,29 +65,30 @@ . += filling_overlay /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure - name = "universal low-pressure medipen" - desc = "It's a low-pressure auto-injecting syringe with a universal refill port on the side." - icon_state = "medipen_red" + name = "\improper universal low-pressure medipen" + desc = "It's a low-pressure auto-injecting syringe with a universal refill port on the side. WARNING: This device is designed to be operated in low-pressure environments only." + icon_state = "medipen_red_unused" base_icon_state = "medipen_red" volume = 30 amount_per_transfer_from_this = 30 /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure/update_icon_state() . = ..() - if(reagents.total_volume >= volume * 0.5) + if(reagents.total_volume <= volume * 0.5) + icon_state = "[base_icon_state]15" icon_state = base_icon_state else if(reagents.total_volume == 0) icon_state = "[base_icon_state]0" else - icon_state = "[base_icon_state]15" + icon_state = base_icon_state /// Returns a list of overlays to add that relate to the reagents inside the syringe /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure/update_reagent_overlay() if(!reagents?.total_volume) return - var/overlay_icon = "medipen_half" - if(reagents.total_volume >= volume * 0.5) - overlay_icon = "medipen" + var/overlay_icon = "medipen" + if(reagents.total_volume <= volume * 0.5) + overlay_icon = "medipen_half" var/mutable_appearance/filling_overlay = mutable_appearance('modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi', overlay_icon) filling_overlay.color = mix_color_from_reagents(reagents.reagent_list) . += filling_overlay @@ -66,4 +108,3 @@ amount_per_transfer_from_this = initial(amount_per_transfer_from_this) * 0.5 . = ..() - amount_per_transfer_from_this = initial(amount_per_transfer_from_this) From e5929b02451556254a3f9a3068ac1019ef7ce462 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 01:03:26 -0400 Subject: [PATCH 11/48] Fix typos in typepaths, update buildpaths --- .../lathe_medipens/code/autolathe_designs.dm | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/code/autolathe_designs.dm b/modular_nova/modules/lathe_medipens/code/autolathe_designs.dm index 09c36990545..b95c933e665 100644 --- a/modular_nova/modules/lathe_medipens/code/autolathe_designs.dm +++ b/modular_nova/modules/lathe_medipens/code/autolathe_designs.dm @@ -29,29 +29,29 @@ /datum/design/medipen/epinephrine name = "Epinephrine Medipen" id = "medipen_epinephrine" - build_path = /obj/item/reagent_containers/hypospray/medipen + build_path = /obj/item/reagent_containers/hypospray/medipen/empty /datum/design/medipen/atropine name = "Atropine Medipen" id = "medipen_atropine" - build_path = /obj/item/reagent_containers/hypospray/medipen/atropine + build_path = /obj/item/reagent_containers/hypospray/medipen/atropine/empty -/datum/design/medipen/atropine +/datum/design/medipen/salbutamol name = "Salbutamol Medipen" id = "medipen_salbutamol" - build_path = /obj/item/reagent_containers/hypospray/medipen/salbutamol + build_path = /obj/item/reagent_containers/hypospray/medipen/salbutamol/empty -/datum/design/medipen/atropine +/datum/design/medipen/oxandrolone name = "Oxandrolone Medipen" id = "medipen_oxandrolone" - build_path = /obj/item/reagent_containers/hypospray/medipen/oxandrolone + build_path = /obj/item/reagent_containers/hypospray/medipen/oxandrolone/empty -/datum/design/medipen/atropine +/datum/design/medipen/salacid name = "Salicylic Acid Medipen" id = "medipen_salacid" - build_path = /obj/item/reagent_containers/hypospray/medipen/salacid + build_path = /obj/item/reagent_containers/hypospray/medipen/salacid/empty -/datum/design/medipen/atropine +/datum/design/medipen/penacid name = "Pentetic Acid Medipen" id = "medipen_penacid" - build_path = /obj/item/reagent_containers/hypospray/medipen/penacid + build_path = /obj/item/reagent_containers/hypospray/medipen/penacid/empty From 4d6c142ba00af15aae5491b3bab2031214521488 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 01:06:25 -0400 Subject: [PATCH 12/48] Add missing nova edit comments, change comment names --- code/game/machinery/medipen_refiller.dm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index 828784657f3..a3ff9aab8c8 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -19,12 +19,13 @@ /obj/item/reagent_containers/hypospray/medipen/survival = /datum/reagent/medicine/c2/libital, /obj/item/reagent_containers/hypospray/medipen/survival/luxury = /datum/reagent/medicine/c2/penthrite, /obj/item/reagent_containers/hypospray/medipen/invisibility = /datum/reagent/drug/saturnx, - // NOVA EDIT BEGIN - Custom medipen + // NOVA EDIT BEGIN - Universal medipen /obj/item/reagent_containers/hypospray/medipen/universal = null, /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure = null, // NOVA EDIT END ) + // NOVA EDIT BEGIN - Universal medipen ///List containing chemicals which custom medipens can contain. var/static/list/allowed_pen_medicine = list( /datum/reagent/medicine, @@ -35,6 +36,7 @@ /datum/reagent/inverse/, /datum/reagent/medicine/morphine, ) + // NOVA EDIT END /obj/machinery/medipen_refiller/Initialize(mapload) . = ..() @@ -91,7 +93,7 @@ if(medipen.reagents?.reagent_list.len) balloon_alert(user, "medipen full!") return - // NOVA EDIT BEGIN - Custom medipen + // NOVA EDIT BEGIN - Universal medipen var/is_custom = istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal) if(is_custom) if(reagents.total_volume < medipen.volume) @@ -111,7 +113,7 @@ add_overlay("active") if(do_after(user, 2 SECONDS, src)) medipen.used_up = FALSE - // NOVA EDIT BEGIN - Custom medipen + // NOVA EDIT BEGIN - Universal medipen if(is_custom) reagents.trans_to(medipen, medipen.volume) else From 5c3c34076a2e324e760db7c5ad8c972a1e8edadc Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 01:28:38 -0400 Subject: [PATCH 13/48] Fix icon for low pressure universal medipen --- .../modules/lathe_medipens/icons/syringe.dmi | Bin 1226 -> 1210 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/icons/syringe.dmi b/modular_nova/modules/lathe_medipens/icons/syringe.dmi index f58597c25f3e6242f84809b66bddce256d18a49f..ea831fb273930ae4d2ca5af1f0a4f339bb5c00fa 100644 GIT binary patch delta 1092 zcmV-K1iSmn3Azc8B!858R9JLGWpiV4X>fFDZ*Bkpc$}4wzY4-I7{up%PjR%nv|7h3 zk|G(}S12v{Gy$7R{^;vFbQLt)9sKUNt8wYCdW0G@y*Na-c}R4JhQ!;MWFc`nlCbRV zHti;+IWZ)vm5qC{pO#1FiiB|?LZT&c3-ijm{t8do=g6ig(|`O;hl1w7rahO?MKgZ< ztkI7OYS8on4AXNKX^6#6000BwNklm=9?{sV$I1f-MTAc9L#Iyg8KgOPx-#zDo!pNP~-y%a&w`gOQmOmaW- ztB*C$hlV6a?h}3P?sJ!f=6$W%*;xo4YuFpm>yse^8h;}JWPAlA%%Vw{MRVfHvN>^O z*|^V}y7$-HwfP5R^YUI$C{=ZQFqd z;N+>Zn3`|dzc{;iwWW1oS|<{#X*vw9`myL;QLWWGm0Hk-9d zb9n;*|aWA@2ZdAeENpcT;5a1SQdW!T>eq{6Bo|K$j`T(Uo7M* z`8S&Y0L7t20KkRwXCm{9gS{ZS7W|D zgvsbFh?6h`9g|Q21(Q7l5PwDj$oL9y``GVfGUiSu({_J+W1YDD`Mr=IIv?<=vTQhg z6hJHU0ZxB>W1YDD`BC}V%a=Tz%6|R%oyu=@J|HYVbUt9DvMiYzY->KCwvJ1j`GBZ= zz}u_u*PkDiA2c6OyIwo<0b%)}^8t@5%l6pwZOsSN)^Uk59}txfcvjCwzyAEF{Gj=O z+V$F*4+zWmoeyyP<6l;mxjpae0%QMDEWEBhcKhQS>m*|K=SSuH_3Qif=XWZ<)%k$1 ze6=Q$(brHi5FMd;ovhaj=!_*J0c0eAj0BL805TFlMgqu40GU7L?w*y03??H delta 1131 zcmV-x1eE)_3CanOB!889R9JLGWpiV4X>fFDZ*Bkpc$}4v%L>9U6hzm#Uoo_MX?-lS zkrv6K{e@D=)dXxRH;Mkfi*6OnZU)W_r^dOzm=WDz=*1HK8lZ99HKg9&CI^kfo|I#M zcWEmz&55B=Eo}Xh!*qRQu1Hxg5gIM2o6HMu`71o-kR#ioO@H$@Ed|fQwmp^5rRu`= zr+JNj?9dH{J~>`<7L_`DC;$Kh@JU2LRCt{2oX<-XaTvy*$u%O=B`S#s5+dmkW*A68 zvFFf(N9iC%S33#Xp?@Hd4nlYeJVek%3=bVTNJ|?+o2`cuFZPQFGi+7@rSjWhcD8kX z?5}ZsvVA@%?iUXGeV^U=%r)JGXue65Bm<(JChy*8h=OtnLq&zX4N#9Rnt5A z+w_k9HtzLGe}_kI1=iVf<%%hGr`Y*sW5t+_mHayQdZoX^Bew$U6z0dg;e&&N=6Uid z0HEdaPXNH#bBzFiROTZr0DuJp3(k)P1LU>?7dnpRYqcG1!r5~deRVz?gV?};`7|+M z!9%h9{;Ssk0Dtj#Jap%c-@Chg`SZ@YuI_5{$I;b&$ycW^-zVV6;X`PSw*mm#+njC9 zap1+Pw>Z$$i%FTVD@+0AcwLAKWkd2&^=}^Yn@QnegQCBeRqFJ^^E6 zV^(G^WdI=itOWp&IiCdp><^9oOJ?pv{_?voKaiPA`RW+U!e+qfUn+lO=tdd&smS^1 z*<>#NAT|IX-LVP)7`l0_WPW-!xg|e6oAlLbD9E?;i5M5X4J9K1WF&yhwhHL$>!S+Y zjrn>JCZneylN|#alRyLrlPd!alRyLoe-kLc?PH%xB+OJI5xGC!Tc_Oqd}e;s>~iyq z&Ic^!wsm!10#MC-fYTrEty6A)eyRMiJGXtE%0d14)#Q8E0M*Y26w5CFXCf~az%6vev{J{ADw?BR%x6SQ&-y0hHm-OsX{<7O2@2%5NW`BOE{GfjQp#J=7 z^1W-q@}lOeHIa;W^8w_1y$F-hQxF*mAR_@}B!G+rkdXi~5;WlOY2XedeE>52z<9nh&T&e|*#ju-l0N;oqNM*wlIYSABG@6cNl^@*6EA^~J1fXsh2AFvzQ)*UuEIk~x= x_38l~v1BBGj0BL805TFlMgqu402v7&^9ScVo|SXti;DmN002ovPDHLkV1kfrDsTV* From 05731f45338d442f423dc2ea5d8ee32f2ba81d9e Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 14:04:00 -0400 Subject: [PATCH 14/48] Refine init_reagents into init_empty, fix icon states --- .../modules/lathe_medipens/code/hypospray.dm | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/code/hypospray.dm b/modular_nova/modules/lathe_medipens/code/hypospray.dm index 5af002510f8..f37f785ee19 100644 --- a/modular_nova/modules/lathe_medipens/code/hypospray.dm +++ b/modular_nova/modules/lathe_medipens/code/hypospray.dm @@ -3,15 +3,15 @@ /// Create empty subtype of medipen #define EMPTY_MEDIPEN_HELPER(typename) HYPOSPRAY_PATH_HELPER(medipen/##typename/empty) {\ - init_reagents = FALSE; \ + init_empty = TRUE; \ used_up = TRUE; \ } \ /obj/item/reagent_containers/hypospray/medipen - /// If FALSE, the medipen will initialize without reagents. - var/init_reagents = TRUE + /// If TRUE, the medipen will initialize without reagents. + var/init_empty = FALSE -// Allows medipens to initialize without reagents if init_reagents is FALSE. +// Allows medipens to initialize without reagents if init_empty is TRUE. /obj/item/reagent_containers/hypospray/medipen/Initialize(mapload) if(init_reagents) return ..() @@ -22,17 +22,22 @@ list_reagents = initial_reagents /obj/item/reagent_containers/hypospray/medipen/empty - list_reagents = FALSE + init_empty = TRUE + used_up = TRUE -// Creates /obj/item/reagent_containers/hypospray/medipen/atropine/empty etc... +// Creates /obj/item/reagent_containers/hypospray/medipen/atropine/empty EMPTY_MEDIPEN_HELPER(atropine) +// Creates /obj/item/reagent_containers/hypospray/medipen/salbutamol/empty EMPTY_MEDIPEN_HELPER(salbutamol) +// Creates /obj/item/reagent_containers/hypospray/medipen/oxandrolone/empty EMPTY_MEDIPEN_HELPER(oxandrolone) +// Creates /obj/item/reagent_containers/hypospray/medipen/salacid/empty EMPTY_MEDIPEN_HELPER(salacid) +// Creates /obj/item/reagent_containers/hypospray/medipen/penacid/empty EMPTY_MEDIPEN_HELPER(penacid) #undef HYPOSPRAY_PATH_HELPER @@ -74,9 +79,8 @@ EMPTY_MEDIPEN_HELPER(penacid) /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure/update_icon_state() . = ..() - if(reagents.total_volume <= volume * 0.5) + if(reagents.total_volume <= (volume * 0.5)) icon_state = "[base_icon_state]15" - icon_state = base_icon_state else if(reagents.total_volume == 0) icon_state = "[base_icon_state]0" else @@ -84,10 +88,10 @@ EMPTY_MEDIPEN_HELPER(penacid) /// Returns a list of overlays to add that relate to the reagents inside the syringe /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure/update_reagent_overlay() - if(!reagents?.total_volume) + if(reagents.total_volume == 0) return var/overlay_icon = "medipen" - if(reagents.total_volume <= volume * 0.5) + if(reagents.total_volume <= (volume * 0.5)) overlay_icon = "medipen_half" var/mutable_appearance/filling_overlay = mutable_appearance('modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi', overlay_icon) filling_overlay.color = mix_color_from_reagents(reagents.reagent_list) From e59b10623571d2a069e55350ef79c5b6056db036 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 18:44:17 -0400 Subject: [PATCH 15/48] Remove extra slash in typepath --- code/game/machinery/medipen_refiller.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index a3ff9aab8c8..6529d67849b 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -33,7 +33,7 @@ ) ///Blacklist containing chemicals which custom medipens can't contain. var/static/list/disallowed_pen_medicine = list( - /datum/reagent/inverse/, + /datum/reagent/inverse, /datum/reagent/medicine/morphine, ) // NOVA EDIT END From c5f1ec31890168e37fa99110be10b6e9d4b63329 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 18:46:41 -0400 Subject: [PATCH 16/48] Swap init_reagents for init_empty, set label text correctly for empty medipens, fully fix icon rendering code --- .../modules/lathe_medipens/code/hypospray.dm | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/code/hypospray.dm b/modular_nova/modules/lathe_medipens/code/hypospray.dm index f37f785ee19..7f334adf6df 100644 --- a/modular_nova/modules/lathe_medipens/code/hypospray.dm +++ b/modular_nova/modules/lathe_medipens/code/hypospray.dm @@ -8,19 +8,24 @@ } \ /obj/item/reagent_containers/hypospray/medipen - /// If TRUE, the medipen will initialize without reagents. + /// If TRUE, the medipen will initialize without reagents var/init_empty = FALSE -// Allows medipens to initialize without reagents if init_empty is TRUE. +// Allows medipens to initialize without reagents if init_empty is TRUE /obj/item/reagent_containers/hypospray/medipen/Initialize(mapload) - if(init_reagents) + if(init_empty != TRUE) return ..() + // Temporarily sets list_reagents to null to avoid filling the medipen var/initial_reagents = list_reagents list_reagents = null . = ..() list_reagents = initial_reagents + if(label_examine) + // Set label text via list_reagents, due to actual reagents being empty + label_text = span_notice("There is a sticker pasted onto the side which reads, 'WARNING: This medipen contains [pretty_string_from_reagent_list(list_reagents, names_only = TRUE, join_text = ", ", final_and = TRUE, capitalize_names = TRUE)], do not use if allergic to any listed chemicals.") + /obj/item/reagent_containers/hypospray/medipen/empty init_empty = TRUE used_up = TRUE @@ -79,36 +84,43 @@ EMPTY_MEDIPEN_HELPER(penacid) /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure/update_icon_state() . = ..() - if(reagents.total_volume <= (volume * 0.5)) - icon_state = "[base_icon_state]15" - else if(reagents.total_volume == 0) + if(reagents.total_volume == 0) icon_state = "[base_icon_state]0" - else + else if(reagents.total_volume > (volume * 0.5)) icon_state = base_icon_state + else + icon_state = "[base_icon_state]15" /// Returns a list of overlays to add that relate to the reagents inside the syringe /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure/update_reagent_overlay() - if(reagents.total_volume == 0) + if(!reagents?.total_volume) return var/overlay_icon = "medipen" - if(reagents.total_volume <= (volume * 0.5)) + if(reagents.total_volume > (volume * 0.5)) + icon_state = base_icon_state + else overlay_icon = "medipen_half" var/mutable_appearance/filling_overlay = mutable_appearance('modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi', overlay_icon) filling_overlay.color = mix_color_from_reagents(reagents.reagent_list) . += filling_overlay /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure/inject(mob/living/affected_mob, mob/user) + // Calculate quantity to inject, depending on if the user is on lavaland. if(lavaland_equipment_pressure_check(get_turf(user))) amount_per_transfer_from_this = initial(amount_per_transfer_from_this) - return ..() + else + if(DOING_INTERACTION(user, DOAFTER_SOURCE_SURVIVALPEN)) + to_chat(user,span_notice("You are too busy to use \the [src]!")) + return - if(DOING_INTERACTION(user, DOAFTER_SOURCE_SURVIVALPEN)) - to_chat(user,span_notice("You are too busy to use \the [src]!")) - return + to_chat(user,span_notice("You start manually releasing the low-pressure gauge...")) + if(!do_after(user, 10 SECONDS, affected_mob, interaction_key = DOAFTER_SOURCE_SURVIVALPEN)) + return - to_chat(user,span_notice("You start manually releasing the low-pressure gauge...")) - if(!do_after(user, 10 SECONDS, affected_mob, interaction_key = DOAFTER_SOURCE_SURVIVALPEN)) - return + amount_per_transfer_from_this = initial(amount_per_transfer_from_this) * 0.5 - amount_per_transfer_from_this = initial(amount_per_transfer_from_this) * 0.5 + // Attempt the injection . = ..() + // Workaround to update icon and overlay after partial injection + if(. && !used_up) + update_appearance() From 810ce22614224e9a3252c418363c16e553c1cc65 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 19:08:43 -0400 Subject: [PATCH 17/48] Create new master file hypospray.dm to implement var init_empty, which allows medipens to spawn without reagents in a type/runtime-safe way. --- .../reagents/reagent_containers/hypospray.dm | 49 +++++++++++++++++++ tgstation.dme | 1 + 2 files changed, 50 insertions(+) create mode 100644 modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm diff --git a/modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm b/modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm new file mode 100644 index 00000000000..7a7f03a3a55 --- /dev/null +++ b/modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm @@ -0,0 +1,49 @@ +/// Create subtype path for hypospray +#define HYPOSPRAY_PATH_HELPER(typename) /obj/item/reagent_containers/hypospray/##typename + +/// Create empty subtype of medipen +#define EMPTY_MEDIPEN_HELPER(typename) HYPOSPRAY_PATH_HELPER(medipen/##typename/empty) {\ + init_empty = TRUE; \ + used_up = TRUE; \ +} \ + +/obj/item/reagent_containers/hypospray/medipen + /// If TRUE, the medipen will initialize without reagents + var/init_empty = FALSE + +// Allows medipens to initialize without reagents if init_empty is TRUE +/obj/item/reagent_containers/hypospray/medipen/Initialize(mapload) + if(init_empty != TRUE) + return ..() + + // Temporarily sets list_reagents to null to avoid filling the medipen + var/initial_reagents = list_reagents + list_reagents = null + . = ..() + list_reagents = initial_reagents + + if(label_examine) + // Set label text via list_reagents, due to actual reagents being empty + label_text = span_notice("There is a sticker pasted onto the side which reads, 'WARNING: This medipen contains [pretty_string_from_reagent_list(list_reagents, names_only = TRUE, join_text = ", ", final_and = TRUE, capitalize_names = TRUE)], do not use if allergic to any listed chemicals.") + +/obj/item/reagent_containers/hypospray/medipen/empty + init_empty = TRUE + used_up = TRUE + +// Creates /obj/item/reagent_containers/hypospray/medipen/atropine/empty +EMPTY_MEDIPEN_HELPER(atropine) + +// Creates /obj/item/reagent_containers/hypospray/medipen/salbutamol/empty +EMPTY_MEDIPEN_HELPER(salbutamol) + +// Creates /obj/item/reagent_containers/hypospray/medipen/oxandrolone/empty +EMPTY_MEDIPEN_HELPER(oxandrolone) + +// Creates /obj/item/reagent_containers/hypospray/medipen/salacid/empty +EMPTY_MEDIPEN_HELPER(salacid) + +// Creates /obj/item/reagent_containers/hypospray/medipen/penacid/empty +EMPTY_MEDIPEN_HELPER(penacid) + +#undef HYPOSPRAY_PATH_HELPER +#undef EMPTY_MEDIPEN_HELPER diff --git a/tgstation.dme b/tgstation.dme index feb811dc0b6..b7f57a97821 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -7008,6 +7008,7 @@ #include "modular_nova\master_files\code\modules\reagents\chemistry\reagents.dm" #include "modular_nova\master_files\code\modules\reagents\chemistry\recipes.dm" #include "modular_nova\master_files\code\modules\reagents\medicine_reagents\medicine_reagents.dm" +#include "modular_nova\master_files\code\modules\reagents\reagent_containers\hypospray.dm" #include "modular_nova\master_files\code\modules\reagents\withdrawal\generic_addictions.dm" #include "modular_nova\master_files\code\modules\religion\religious_sects.dm" #include "modular_nova\master_files\code\modules\research\designs\biogenerator_designs.dm" From a0526d53ceae17b3fd61702a00676cef78563452 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 19:09:03 -0400 Subject: [PATCH 18/48] Reflect new master file creation in readme --- modular_nova/modules/lathe_medipens/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modular_nova/modules/lathe_medipens/README.md b/modular_nova/modules/lathe_medipens/README.md index f0909afbfa0..b73f13c9aa2 100644 --- a/modular_nova/modules/lathe_medipens/README.md +++ b/modular_nova/modules/lathe_medipens/README.md @@ -21,7 +21,7 @@ Local to `hypospray.dm`: ### Master file additions -- N/A +- Empty medipen subtypes: `modular_nova\master_files\code\modules\reagents\reagent_containers\hypospray.dm` ### Included files that are not contained in this module: From 9d59101b0a571d07a89f8e70f439d1cbade0474b Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 19:09:26 -0400 Subject: [PATCH 19/48] Remove overrides --- .../modules/lathe_medipens/code/hypospray.dm | 50 ------------------- 1 file changed, 50 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/code/hypospray.dm b/modular_nova/modules/lathe_medipens/code/hypospray.dm index 7f334adf6df..809afc7a6e0 100644 --- a/modular_nova/modules/lathe_medipens/code/hypospray.dm +++ b/modular_nova/modules/lathe_medipens/code/hypospray.dm @@ -1,53 +1,3 @@ -/// Create subtype path for hypospray -#define HYPOSPRAY_PATH_HELPER(typename) /obj/item/reagent_containers/hypospray/##typename - -/// Create empty subtype of medipen -#define EMPTY_MEDIPEN_HELPER(typename) HYPOSPRAY_PATH_HELPER(medipen/##typename/empty) {\ - init_empty = TRUE; \ - used_up = TRUE; \ -} \ - -/obj/item/reagent_containers/hypospray/medipen - /// If TRUE, the medipen will initialize without reagents - var/init_empty = FALSE - -// Allows medipens to initialize without reagents if init_empty is TRUE -/obj/item/reagent_containers/hypospray/medipen/Initialize(mapload) - if(init_empty != TRUE) - return ..() - - // Temporarily sets list_reagents to null to avoid filling the medipen - var/initial_reagents = list_reagents - list_reagents = null - . = ..() - list_reagents = initial_reagents - - if(label_examine) - // Set label text via list_reagents, due to actual reagents being empty - label_text = span_notice("There is a sticker pasted onto the side which reads, 'WARNING: This medipen contains [pretty_string_from_reagent_list(list_reagents, names_only = TRUE, join_text = ", ", final_and = TRUE, capitalize_names = TRUE)], do not use if allergic to any listed chemicals.") - -/obj/item/reagent_containers/hypospray/medipen/empty - init_empty = TRUE - used_up = TRUE - -// Creates /obj/item/reagent_containers/hypospray/medipen/atropine/empty -EMPTY_MEDIPEN_HELPER(atropine) - -// Creates /obj/item/reagent_containers/hypospray/medipen/salbutamol/empty -EMPTY_MEDIPEN_HELPER(salbutamol) - -// Creates /obj/item/reagent_containers/hypospray/medipen/oxandrolone/empty -EMPTY_MEDIPEN_HELPER(oxandrolone) - -// Creates /obj/item/reagent_containers/hypospray/medipen/salacid/empty -EMPTY_MEDIPEN_HELPER(salacid) - -// Creates /obj/item/reagent_containers/hypospray/medipen/penacid/empty -EMPTY_MEDIPEN_HELPER(penacid) - -#undef HYPOSPRAY_PATH_HELPER -#undef EMPTY_MEDIPEN_HELPER - /obj/item/reagent_containers/hypospray/medipen/universal name = "\improper universal medipen" desc = "It's an auto-injecting syringe with a universal refill port on the side." From 0d615c7d3d7d835b696573a6a7cddaf75cee163b Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 23:19:05 -0400 Subject: [PATCH 20/48] Add empty variants of medipens to medipen refiller whitelist --- code/game/machinery/medipen_refiller.dm | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index 6529d67849b..b950cb4ac12 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -19,9 +19,15 @@ /obj/item/reagent_containers/hypospray/medipen/survival = /datum/reagent/medicine/c2/libital, /obj/item/reagent_containers/hypospray/medipen/survival/luxury = /datum/reagent/medicine/c2/penthrite, /obj/item/reagent_containers/hypospray/medipen/invisibility = /datum/reagent/drug/saturnx, - // NOVA EDIT BEGIN - Universal medipen + // NOVA EDIT BEGIN - Universal medipen and lathe medipens /obj/item/reagent_containers/hypospray/medipen/universal = null, /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure = null, + /obj/item/reagent_containers/hypospray/medipen/empty = /datum/reagent/medicine/epinephrine, + /obj/item/reagent_containers/hypospray/medipen/atropine/empty = /datum/reagent/medicine/atropine, + /obj/item/reagent_containers/hypospray/medipen/salbutamol/empty = /datum/reagent/medicine/salbutamol, + /obj/item/reagent_containers/hypospray/medipen/oxandrolone/empty = /datum/reagent/medicine/oxandrolone, + /obj/item/reagent_containers/hypospray/medipen/salacid/empty = /datum/reagent/medicine/sal_acid, + /obj/item/reagent_containers/hypospray/medipen/penacid/empty = /datum/reagent/medicine/pen_acid, // NOVA EDIT END ) @@ -54,7 +60,10 @@ context[SCREENTIP_CONTEXT_LMB] = panel_open ? "Close panel" : "Open panel" else if(is_reagent_container(held_item) && held_item.is_open_container()) context[SCREENTIP_CONTEXT_LMB] = "Refill machine" - else if(istype(held_item, /obj/item/reagent_containers/hypospray/medipen) && reagents.has_reagent(allowed_pens[held_item.type])) + // NOVA EDIT - Universal medipen + // ORIGINAL: else if(istype(held_item, /obj/item/reagent_containers/hypospray/medipen) && reagents.has_reagent(allowed_pens[held_item.type])) + else if(istype(held_item, /obj/item/reagent_containers/hypospray/medipen/universal) || istype(held_item, /obj/item/reagent_containers/hypospray/medipen) && reagents.has_reagent(allowed_pens[held_item.type])) + // NOVA EDIT END context[SCREENTIP_CONTEXT_LMB] = "Refill medipen" else if(istype(held_item, /obj/item/plunger)) context[SCREENTIP_CONTEXT_LMB] = "Plunge machine" From 0693830e051af1f9b9bfd14a52f6c354c8b27ff4 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 23:20:21 -0400 Subject: [PATCH 21/48] Remove macros, add medipen/inject() override, add medipen/var/unused --- .../reagents/reagent_containers/hypospray.dm | 52 +++++++++++-------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm b/modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm index 7a7f03a3a55..e9f8d86daa8 100644 --- a/modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm +++ b/modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm @@ -1,15 +1,8 @@ -/// Create subtype path for hypospray -#define HYPOSPRAY_PATH_HELPER(typename) /obj/item/reagent_containers/hypospray/##typename - -/// Create empty subtype of medipen -#define EMPTY_MEDIPEN_HELPER(typename) HYPOSPRAY_PATH_HELPER(medipen/##typename/empty) {\ - init_empty = TRUE; \ - used_up = TRUE; \ -} \ - /obj/item/reagent_containers/hypospray/medipen /// If TRUE, the medipen will initialize without reagents var/init_empty = FALSE + /// If TRUE, indicates that the medipen hasn't been injected by a mob yet + var/unused = TRUE // Allows medipens to initialize without reagents if init_empty is TRUE /obj/item/reagent_containers/hypospray/medipen/Initialize(mapload) @@ -26,24 +19,39 @@ // Set label text via list_reagents, due to actual reagents being empty label_text = span_notice("There is a sticker pasted onto the side which reads, 'WARNING: This medipen contains [pretty_string_from_reagent_list(list_reagents, names_only = TRUE, join_text = ", ", final_and = TRUE, capitalize_names = TRUE)], do not use if allergic to any listed chemicals.") +// Sends a more generic chat message when an unused medipen is empty +/obj/item/reagent_containers/hypospray/medipen/inject(mob/living/affected_mob, mob/user) + if(init_empty && used_up && unused) + to_chat(user, span_warning("You push [src]'s button, but nothing happens. It's empty!")) + return FALSE + + // Attempt the injection + . = ..() + + // If the injection succeeded, then the medipen is not unused anymore + if(unused && .) + unused = FALSE + /obj/item/reagent_containers/hypospray/medipen/empty init_empty = TRUE used_up = TRUE -// Creates /obj/item/reagent_containers/hypospray/medipen/atropine/empty -EMPTY_MEDIPEN_HELPER(atropine) - -// Creates /obj/item/reagent_containers/hypospray/medipen/salbutamol/empty -EMPTY_MEDIPEN_HELPER(salbutamol) +/obj/item/reagent_containers/hypospray/medipen/atropine/empty + init_empty = TRUE + used_up = TRUE -// Creates /obj/item/reagent_containers/hypospray/medipen/oxandrolone/empty -EMPTY_MEDIPEN_HELPER(oxandrolone) +/obj/item/reagent_containers/hypospray/medipen/salbutamol/empty + init_empty = TRUE + used_up = TRUE -// Creates /obj/item/reagent_containers/hypospray/medipen/salacid/empty -EMPTY_MEDIPEN_HELPER(salacid) +/obj/item/reagent_containers/hypospray/medipen/oxandrolone/empty + init_empty = TRUE + used_up = TRUE -// Creates /obj/item/reagent_containers/hypospray/medipen/penacid/empty -EMPTY_MEDIPEN_HELPER(penacid) +/obj/item/reagent_containers/hypospray/medipen/salacid/empty + init_empty = TRUE + used_up = TRUE -#undef HYPOSPRAY_PATH_HELPER -#undef EMPTY_MEDIPEN_HELPER +/obj/item/reagent_containers/hypospray/medipen/penacid/empty + init_empty = TRUE + used_up = TRUE From ab88c96578988cc99b49d2fde03abfeaf83b3d7e Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 8 Jul 2024 23:20:47 -0400 Subject: [PATCH 22/48] Update readme --- modular_nova/modules/lathe_medipens/README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/README.md b/modular_nova/modules/lathe_medipens/README.md index b73f13c9aa2..f9e48b66374 100644 --- a/modular_nova/modules/lathe_medipens/README.md +++ b/modular_nova/modules/lathe_medipens/README.md @@ -14,18 +14,19 @@ Contains empty subtypes of several medipens, custom/universal medipen subtypes w ### Defines: -Local to `hypospray.dm`: - -- Macro `HYPOSPRAY_PATH_HELPER` creates a hypospray subtype. -- Macro `EMPTY_MEDIPEN_HELPER` creates an empty medipen subtype. +- N/A ### Master file additions -- Empty medipen subtypes: `modular_nova\master_files\code\modules\reagents\reagent_containers\hypospray.dm` +Implements variables `init_empty` and `unused` on `/obj/item/reagent_containers/hypospray/medipen`: + +- `modular_nova\master_files\code\modules\reagents\reagent_containers\hypospray.dm` ### Included files that are not contained in this module: -- N/A +Dependent to avoid runtime errors: + +- `modular_nova\master_files\code\modules\reagents\reagent_containers\hypospray.dm` ### Credits: - [@Floofies](https://github.com/Floofies) From d4289871cce08e22caff7bd7f357f6300a5b02ea Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Tue, 9 Jul 2024 00:24:37 -0400 Subject: [PATCH 23/48] Add init_empty to universal medipen --- modular_nova/modules/lathe_medipens/code/hypospray.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/modular_nova/modules/lathe_medipens/code/hypospray.dm b/modular_nova/modules/lathe_medipens/code/hypospray.dm index 809afc7a6e0..0154d44e2b4 100644 --- a/modular_nova/modules/lathe_medipens/code/hypospray.dm +++ b/modular_nova/modules/lathe_medipens/code/hypospray.dm @@ -9,6 +9,7 @@ list_reagents = null label_examine = FALSE used_up = TRUE + init_empty = TRUE /obj/item/reagent_containers/hypospray/medipen/universal/update_overlays() . = ..() From 07e45aa890b0c2b06735624d8c6a9ebb2fadaf80 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Tue, 9 Jul 2024 00:30:42 -0400 Subject: [PATCH 24/48] Make balloon message more concise --- code/game/machinery/medipen_refiller.dm | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index b950cb4ac12..9a2a304de9d 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -109,11 +109,8 @@ balloon_alert(user, "not enough reagents!") return for(var/datum/reagent/meds in reagents.reagent_list) - if(!is_type_in_list(meds, allowed_pen_medicine)) - balloon_alert(user, "medipen incompatible!") - return - if(is_type_in_list(meds, disallowed_pen_medicine)) - balloon_alert(user, "medipen incompatible!") + if(!is_type_in_list(meds, allowed_pen_medicine) || is_type_in_list(meds, disallowed_pen_medicine)) + balloon_alert(user, "reagents incompatible!") return // NOVA EDIT END if(!reagents.has_reagent(allowed_pens[medipen.type], 10)) From 54045df72964f5c717c527c70b0d4518e3b12a9e Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Tue, 9 Jul 2024 01:07:00 -0400 Subject: [PATCH 25/48] Add missing info to readme --- modular_nova/modules/lathe_medipens/README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/README.md b/modular_nova/modules/lathe_medipens/README.md index f9e48b66374..71115416aff 100644 --- a/modular_nova/modules/lathe_medipens/README.md +++ b/modular_nova/modules/lathe_medipens/README.md @@ -10,7 +10,10 @@ Contains empty subtypes of several medipens, custom/universal medipen subtypes w ### TG Proc Changes: -- `/obj/item/reagent_containers/hypospray/medipen/Initialize` is overridden by this module to implement medipens which spawn without reagents. +Overridden to implement medipens which spawn without reagents: + +- `/obj/item/reagent_containers/hypospray/medipen/Initialize()` +- `/obj/item/reagent_containers/hypospray/medipen/inject()` ### Defines: @@ -18,9 +21,9 @@ Contains empty subtypes of several medipens, custom/universal medipen subtypes w ### Master file additions -Implements variables `init_empty` and `unused` on `/obj/item/reagent_containers/hypospray/medipen`: - - `modular_nova\master_files\code\modules\reagents\reagent_containers\hypospray.dm` + - Overrides `Initialize()` and `inject()`. + - Adds new variables `medipen/var/init_empty` and `medipen/var/unused`. ### Included files that are not contained in this module: From 3aba55530d4d9374e0000bdaa4cf182b930e55bf Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Tue, 9 Jul 2024 03:04:35 -0400 Subject: [PATCH 26/48] Remove worn icon var --- modular_nova/modules/lathe_medipens/code/hypospray.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/modular_nova/modules/lathe_medipens/code/hypospray.dm b/modular_nova/modules/lathe_medipens/code/hypospray.dm index 0154d44e2b4..01ca48c53ea 100644 --- a/modular_nova/modules/lathe_medipens/code/hypospray.dm +++ b/modular_nova/modules/lathe_medipens/code/hypospray.dm @@ -4,7 +4,6 @@ icon = 'modular_nova/modules/lathe_medipens/icons/syringe.dmi' icon_state = "medipen_blue_unused" base_icon_state = "medipen_blue" - worn_icon_state = "dnainjector0" inhand_icon_state = "dnainjector0" list_reagents = null label_examine = FALSE From bc655950f95d9047dfd59d32b5573046c9df24b7 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Tue, 9 Jul 2024 11:47:29 -0400 Subject: [PATCH 27/48] Add missing TG proc changes to readme --- modular_nova/modules/lathe_medipens/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/README.md b/modular_nova/modules/lathe_medipens/README.md index 71115416aff..f818d76c153 100644 --- a/modular_nova/modules/lathe_medipens/README.md +++ b/modular_nova/modules/lathe_medipens/README.md @@ -10,10 +10,10 @@ Contains empty subtypes of several medipens, custom/universal medipen subtypes w ### TG Proc Changes: -Overridden to implement medipens which spawn without reagents: - - `/obj/item/reagent_containers/hypospray/medipen/Initialize()` - `/obj/item/reagent_containers/hypospray/medipen/inject()` +- `/obj/machinery/medipen_refiller/add_context()` +- `/obj/machinery/medipen_refiller/attackby()` ### Defines: From e80c584f9cbfd8620860744fbfcffcb1dffc8e56 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sun, 4 Aug 2024 18:55:25 -0400 Subject: [PATCH 28/48] Refactor volume calc code into trans_to_equal --- code/game/machinery/medipen_refiller.dm | 42 +++--- .../code/modules/reagents/chemistry/holder.dm | 141 ++++++++++++++++++ 2 files changed, 162 insertions(+), 21 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index 9a2a304de9d..288a33cdc7e 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -32,16 +32,15 @@ ) // NOVA EDIT BEGIN - Universal medipen - ///List containing chemicals which custom medipens can contain. - var/static/list/allowed_pen_medicine = list( + ///Whitelist typecache of reagent types which are allowed to refill universal medipens. + var/static/list/medipen_reagent_whitelist = typecacheof(list( /datum/reagent/medicine, /datum/reagent/vaccine, - ) - ///Blacklist containing chemicals which custom medipens can't contain. - var/static/list/disallowed_pen_medicine = list( - /datum/reagent/inverse, + )) + ///Blacklist typecache of reagent types which are disallowed to refill universal medipens. + var/static/list/medipen_reagent_blacklist = typecacheof(list( /datum/reagent/medicine/morphine, - ) + )) // NOVA EDIT END /obj/machinery/medipen_refiller/Initialize(mapload) @@ -102,26 +101,27 @@ if(medipen.reagents?.reagent_list.len) balloon_alert(user, "medipen full!") return - // NOVA EDIT BEGIN - Universal medipen - var/is_custom = istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal) - if(is_custom) - if(reagents.total_volume < medipen.volume) - balloon_alert(user, "not enough reagents!") - return - for(var/datum/reagent/meds in reagents.reagent_list) - if(!is_type_in_list(meds, allowed_pen_medicine) || is_type_in_list(meds, disallowed_pen_medicine)) - balloon_alert(user, "reagents incompatible!") - return - // NOVA EDIT END if(!reagents.has_reagent(allowed_pens[medipen.type], 10)) balloon_alert(user, "not enough reagents!") return add_overlay("active") if(do_after(user, 2 SECONDS, src)) medipen.used_up = FALSE - // NOVA EDIT BEGIN - Universal medipen - if(is_custom) - reagents.trans_to(medipen, medipen.volume) + if(istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal)) + if(reagents.total_volume < medipen.volume) + balloon_alert(user, "not enough reagents!") + return + // Ignore reagents not in the whitelist + var/list/compatible_reagent_types = typecache_filter_list(reagents.reagent_list, medipen_reagent_whitelist) + // Ignore reagents in the blacklist + compatible_reagent_types = typecache_filter_list_reverse(compatible_reagent_types, medipen_reagent_blacklist) + + // Ensure there is enough of the whitelisted reagents + if(!length(compatible_reagent_types)) + balloon_alert(user, "reagents incompatible!") + return + // Transfer equal amounts of each reagent + reagents.trans_to_equal(target_atom = medipen, target_ids = compatible_reagent_types) else medipen.add_initial_reagents() reagents.remove_reagent(allowed_pens[medipen.type], medipen.volume) diff --git a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm index 278a685dbb7..9cf25515d21 100644 --- a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm +++ b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm @@ -15,3 +15,144 @@ return TRUE return FALSE + +/* trans_to_equal() Theory of Operation: +Vi = volume of each available reagent. +n = total types of reagents. +V = target volume for each reagent after transfer. + +Find V such that the volume of each reagent is as equal as possible. + +Total combined volume of all reagents: + n +Vtotal = ∑ Vi + i=1 + +Initial target volume per reagent: +Vinitial = Vtotal / n + +For each reagent, the volume to be transferred is: +Ti = min(Vi, Vinitial) + +After an initial transfer, we need to do a second pass. +Calculate the remaining volume after the initial round: + n +Vremaining = Vtotal - ∑ Ti + i=1 + +Redistribute remaining volume, for reagents where Vi > Ti: +T'i = Ti + Vremaining x (Vi - Ti) / ∑{j | Vj > Tj} (Vj - Tj) + +Final transfer volume for reach reagent: +T"i = Ti + T'i +*/ +/** + * Calculates and transfers even amounts of each reagent to the target atom. Calls trans_to() to do the actual transfer. + * Unlike trans_to(), amount is auto-calculated, and target_id is replaced with list target_ids. + * + * Arguments: + * * obj/target - Target atom to attempt transfers to + * * multiplier - multiplies each reagent amount by this number well byond their available volume before transfering. used to create reagents from thin air if you ever need to + * * list/datum/reagent/target_ids - transfers only the listed reagent types in this holder leaving others untouched + * * preserve_data - if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. + * * no_react - passed through to [/datum/reagents/proc/add_reagent] + * * mob/transferred_by - used for logging + * * remove_blacklisted - skips transferring of reagents without REAGENT_CAN_BE_SYNTHESIZED in chemical_flags + * * methods - passed through to [/datum/reagents/proc/expose] and [/datum/reagent/proc/on_transfer] + * * show_message - passed through to [/datum/reagents/proc/expose] + * * ignore_stomach - when using methods INGEST will not use the stomach as the target + */ +/datum/reagents/proc/trans_to_equal( + atom/target_atom, + multiplier = 1, + list/datum/reagent/target_ids, + preserve_data = TRUE, + no_react = FALSE, + mob/transferred_by, + remove_blacklisted = FALSE, + methods = NONE, + show_message = TRUE, + ignore_stomach = FALSE +) + + if(isnull(target_atom.reagents)) + return FALSE + + if(target_atom.reagents.total_volume == target_atom.reagents.maximum_volume) + return FALSE + + // Ignore reagents not in target_ids + var/list/datum/reagent/target_reagents = list() + if(length(target_ids)) + for(var/datum/reagent/target_type in target_ids) + if(reagent_list[target_type]) + target_reagents += reagent_list[target_type] + else + target_reagents = reagent_list + + if(!length(target_reagents)) + return FALSE + + // Calculate available reagent volume to transfer VS available capacity + var/max_volume = target_atom.reagents.maximum_volume + var/current_volume = target_atom.reagents.total_volume + max_volume = max_volume - current_volume + var/available_volume = 0 + for(var/datum/reagent/reagent in target_reagents) + available_volume += round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) + + if(available_volume < CHEMICAL_QUANTISATION_LEVEL) + return FALSE + + // Total transfer volume can't exceed capacity + available_volume = min(available_volume, max_volume) + + // Calculate initial target volume per reagent + var/initial_target_volume = available_volume / length(target_reagents) + + // Calculate the initial reagent transfer volumes + var/list/datum/reagent/initial_transfer_volumes = list() + var/remaining_volume = 0 + for(var/datum/reagent/reagent in target_reagents) + var/transfer_volume = min(round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL), initial_target_volume) + initial_transfer_volumes[reagent] = transfer_volume + // Also sum remaining total transfer volume here to save time + remaining_volume += transfer_volume + + // Re-distribute the remaining reagent volumes + var/datum/reagent/adjusted_transfer_volumes = list() + for(var/datum/reagent/reagent in target_reagents) + var/adjusted_transfer_volume = 0 + if(reagent.volume > adjusted_transfer_volume) + var/proportional_transfer_volume = 0 + for(reagent in target_reagents) + var/initial_volume = initial_transfer_volumes[reagent] + var/reagent_volume = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) + if(reagent_volume > initial_volume) + proportional_transfer_volume = proportional_transfer_volume + (reagent_volume - initial_volume) + adjusted_transfer_volume = adjusted_transfer_volume + (remaining_volume * proportional_transfer_volume) + else + adjusted_transfer_volumes[reagent] = adjusted_transfer_volume + + // Limit total ajusted transfer volumes to maximum capacity of target + var/final_transfer_volume = assoc_value_sum(adjusted_transfer_volumes) + var/final_transfer_volumes = list() + if(final_transfer_volume > max_volume) + var/excess_volume = final_transfer_volume - max_volume + for(var/datum/reagent/reagent in target_reagents) + var/adjusted_volume = adjusted_transfer_volumes[reagent] + final_transfer_volumes[reagent] = adjusted_volume - (adjusted_volume / final_transfer_volume) * excess_volume + + for(var/datum/reagent/reagent in target_reagents) + trans_to( + target = target_atom, + amount = final_transfer_volumes[reagent], + target_id = reagent, + preserve_data = preserve_data, + no_react = no_react, + transferred_by = transferred_by, + remove_blacklisted = remove_blacklisted, + methods = methods, + show_message = show_message, + ignore_stomach = ignore_stomach + ) From 997ae32e6e788e1c6440bd26602be6e642cb3769 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Wed, 7 Aug 2024 21:51:37 -0400 Subject: [PATCH 29/48] Refactored naive solution again for trans_to_equal --- code/game/machinery/medipen_refiller.dm | 15 +- .../code/modules/reagents/chemistry/holder.dm | 162 +++++++++++------- 2 files changed, 111 insertions(+), 66 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index 288a33cdc7e..7027d526cc8 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -107,21 +107,22 @@ add_overlay("active") if(do_after(user, 2 SECONDS, src)) medipen.used_up = FALSE + // NOVA EDIT BEGIN - Universal medipen and lathe medipens if(istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal)) if(reagents.total_volume < medipen.volume) balloon_alert(user, "not enough reagents!") return - // Ignore reagents not in the whitelist - var/list/compatible_reagent_types = typecache_filter_list(reagents.reagent_list, medipen_reagent_whitelist) - // Ignore reagents in the blacklist - compatible_reagent_types = typecache_filter_list_reverse(compatible_reagent_types, medipen_reagent_blacklist) - + // Ignore reagents which aren't the blacklist or whitelist + var/list/compatible_reagents = typecache_filter_multi_list_exclusion(reagents.reagent_list, medipen_reagent_whitelist, medipen_reagent_blacklist) // Ensure there is enough of the whitelisted reagents - if(!length(compatible_reagent_types)) + if(!length(compatible_reagents)) balloon_alert(user, "reagents incompatible!") return + var/list/datum/reagent/target_reagent_types = list() + for(var/datum/reagent/target_reagent in compatible_reagents) + target_reagent_types += target_reagent.type // Transfer equal amounts of each reagent - reagents.trans_to_equal(target_atom = medipen, target_ids = compatible_reagent_types) + reagents.trans_to_equal(target_atom = medipen, target_ids = target_reagent_types) else medipen.add_initial_reagents() reagents.remove_reagent(allowed_pens[medipen.type], medipen.volume) diff --git a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm index 9cf25515d21..72d40cac56c 100644 --- a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm +++ b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm @@ -74,80 +74,123 @@ T"i = Ti + T'i show_message = TRUE, ignore_stomach = FALSE ) - + // Targeted atom can not hold reagents if(isnull(target_atom.reagents)) return FALSE - if(target_atom.reagents.total_volume == target_atom.reagents.maximum_volume) + // Maximum amount of reagents which can fit inside the target + var/max_volume = target_atom.reagents.maximum_volume + // Total volume of the reagents already inside the target + var/current_volume = target_atom.reagents.total_volume + // Total volume of the empty space inside the target + var/empty_volume = max_volume - current_volume + + // Targeted atom is already full of reagents + if(empty_volume <= 0) return FALSE - // Ignore reagents not in target_ids + // Total volume of transferable reagents after whitelisting and rounding + var/possible_transfer_volume = 0 + // Organize targeted reagents into associative list of typepaths to datums var/list/datum/reagent/target_reagents = list() - if(length(target_ids)) - for(var/datum/reagent/target_type in target_ids) - if(reagent_list[target_type]) - target_reagents += reagent_list[target_type] - else - target_reagents = reagent_list - + // TRUE if a reagent whitelist was given + var/using_whitelist = length(target_ids) != 0 + // Perform whitelisting and rounding, then calculate total possible transfer volume + for(var/datum/reagent/reagent in reagent_list) + if(!using_whitelist || target_ids[reagent.type]) + target_reagents[reagent.type] += reagent + possible_transfer_volume += round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) + + // There are no transferable reagents if(!length(target_reagents)) return FALSE - // Calculate available reagent volume to transfer VS available capacity - var/max_volume = target_atom.reagents.maximum_volume - var/current_volume = target_atom.reagents.total_volume - max_volume = max_volume - current_volume - var/available_volume = 0 - for(var/datum/reagent/reagent in target_reagents) - available_volume += round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) - - if(available_volume < CHEMICAL_QUANTISATION_LEVEL) - return FALSE - // Total transfer volume can't exceed capacity - available_volume = min(available_volume, max_volume) - - // Calculate initial target volume per reagent - var/initial_target_volume = available_volume / length(target_reagents) - - // Calculate the initial reagent transfer volumes - var/list/datum/reagent/initial_transfer_volumes = list() - var/remaining_volume = 0 - for(var/datum/reagent/reagent in target_reagents) - var/transfer_volume = min(round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL), initial_target_volume) - initial_transfer_volumes[reagent] = transfer_volume - // Also sum remaining total transfer volume here to save time - remaining_volume += transfer_volume + possible_transfer_volume = min(empty_volume, possible_transfer_volume) + // Ensure there is enough reagent volume to transfer anything + if(possible_transfer_volume < CHEMICAL_QUANTISATION_LEVEL) + return FALSE - // Re-distribute the remaining reagent volumes - var/datum/reagent/adjusted_transfer_volumes = list() + // Implements even distribution in first pass if reagent volumes meet this minimum + var/initial_target_volume = round(possible_transfer_volume / length(target_reagents), CHEMICAL_QUANTISATION_LEVEL) + // Volume of excess reagents. Redistributed in second pass if not zero. + var/remaining_transfer_volume = 0 + // Total deficit volume. Enables second pass if not zero. + var/deficit_transfer_volume = empty_volume + // Total quantity of reagents with volume above initial_target_volume. + var/excess_reagents = length(target_reagents) + + // Organize transfer volumes into associative list of typepaths to volumes + // Used as a scratchpad to calculate transfer volumes and provide reagent transfer amounts to trans_to() + var/list/datum/reagent/transfer_volumes = list() + + // First pass, calculate initial transfer volumes per reagent + // Account for reagents with insufficient and excess volumes for(var/datum/reagent/reagent in target_reagents) - var/adjusted_transfer_volume = 0 - if(reagent.volume > adjusted_transfer_volume) - var/proportional_transfer_volume = 0 - for(reagent in target_reagents) - var/initial_volume = initial_transfer_volumes[reagent] - var/reagent_volume = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) - if(reagent_volume > initial_volume) - proportional_transfer_volume = proportional_transfer_volume + (reagent_volume - initial_volume) - adjusted_transfer_volume = adjusted_transfer_volume + (remaining_volume * proportional_transfer_volume) - else - adjusted_transfer_volumes[reagent] = adjusted_transfer_volume - - // Limit total ajusted transfer volumes to maximum capacity of target - var/final_transfer_volume = assoc_value_sum(adjusted_transfer_volumes) - var/final_transfer_volumes = list() - if(final_transfer_volume > max_volume) - var/excess_volume = final_transfer_volume - max_volume + var/reagent_volume = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) + var/transfer_volume = min(reagent_volume, initial_target_volume) + transfer_volumes[reagent.type] = transfer_volume + remaining_transfer_volume += reagent_volume - transfer_volume + // Account for insufficient reagent volume + deficit_transfer_volume = deficit_transfer_volume - transfer_volume + // This reagent has excess volume. Could be redistributed in the second pass + if(reagent_volume > initial_target_volume) + excess_reagents++ + + // Second pass, mitigate insufficient volumes via redistribution of excess volumes. + if((deficit_transfer_volume > 0) && (remaining_transfer_volume > 0)) for(var/datum/reagent/reagent in target_reagents) - var/adjusted_volume = adjusted_transfer_volumes[reagent] - final_transfer_volumes[reagent] = adjusted_volume - (adjusted_volume / final_transfer_volume) * excess_volume - + var/transfer_volume = transfer_volumes[reagent.type] + // Transfer volume of this reagent is sufficient or higher, so skip it + if(transfer_volume >= initial_target_volume) + continue + // Transfer volume of this reagent is insufficient, so others must be increased + // Increase transfer volumes of excess reagents to compensate for the deficit + for(var/datum/reagent/sub_reagent in target_reagents) + var/sub_transfer_volume = transfer_volumes[sub_reagent.type] + var/sub_volume = round(sub_reagent.volume, CHEMICAL_QUANTISATION_LEVEL) + + // This reagent has no excess volume, to skip it + var/remaining_reagent_volume = sub_volume - sub_transfer_volume + if(remaining_reagent_volume <= 0) + continue + + // Only this reagent has excess volume, so we can skip a bunch of steps + if(excess_reagents == 1) + transfer_volumes[sub_reagent.type] = min(sub_volume, deficit_transfer_volume) + excess_reagents-- + break + + // Calculate ideal volume adjustment based on deficit volume divided by quantity of excess reagents + var/proportional_volume_increase = round(deficit_transfer_volume / excess_reagents, CHEMICAL_QUANTISATION_LEVEL) + // Compensated on a best-effort basis + var/new_transfer_volume = min(sub_volume, sub_transfer_volume + proportional_volume_increase) + transfer_volumes[sub_reagent.type] = new_transfer_volume + + // Account for the remaining deficit + deficit_transfer_volume = min(0, deficit_transfer_volume - proportional_volume_increase) + if(deficit_transfer_volume == 0) + break + // Depleted this reagent after increasing but there's still a deficit + if(new_transfer_volume == sub_volume) + // Subtracting increases the proportional adjustment + excess_reagents-- + + // Used up excess reagents in nested loop + // This also implies that remaining_transfer_volume is zero + if(excess_reagents == 0) + break + // Fully fixed the deficit in nested loop + if(deficit_transfer_volume == 0) + break + + // Actually perform the reagent transfers and return total volume transferred + var/transfer_total = 0 for(var/datum/reagent/reagent in target_reagents) - trans_to( + transfer_total += trans_to( target = target_atom, - amount = final_transfer_volumes[reagent], - target_id = reagent, + amount = transfer_volumes[reagent], + target_id = reagent.type, preserve_data = preserve_data, no_react = no_react, transferred_by = transferred_by, @@ -156,3 +199,4 @@ T"i = Ti + T'i show_message = show_message, ignore_stomach = ignore_stomach ) + return transfer_total From e108333eb91fc0ed83cc15c5f021ff2a7956ad68 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 12 Aug 2024 20:16:26 -0400 Subject: [PATCH 30/48] Cleaning up --- code/game/machinery/medipen_refiller.dm | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index 7027d526cc8..f7229473a93 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -19,7 +19,7 @@ /obj/item/reagent_containers/hypospray/medipen/survival = /datum/reagent/medicine/c2/libital, /obj/item/reagent_containers/hypospray/medipen/survival/luxury = /datum/reagent/medicine/c2/penthrite, /obj/item/reagent_containers/hypospray/medipen/invisibility = /datum/reagent/drug/saturnx, - // NOVA EDIT BEGIN - Universal medipen and lathe medipens + // NOVA EDIT ADDITION BEGIN - Universal medipens and lathe medipens /obj/item/reagent_containers/hypospray/medipen/universal = null, /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure = null, /obj/item/reagent_containers/hypospray/medipen/empty = /datum/reagent/medicine/epinephrine, @@ -28,10 +28,10 @@ /obj/item/reagent_containers/hypospray/medipen/oxandrolone/empty = /datum/reagent/medicine/oxandrolone, /obj/item/reagent_containers/hypospray/medipen/salacid/empty = /datum/reagent/medicine/sal_acid, /obj/item/reagent_containers/hypospray/medipen/penacid/empty = /datum/reagent/medicine/pen_acid, - // NOVA EDIT END + // NOVA EDIT ADDITION END ) - // NOVA EDIT BEGIN - Universal medipen + // NOVA EDIT ADDITION BEGIN - Universal medipens ///Whitelist typecache of reagent types which are allowed to refill universal medipens. var/static/list/medipen_reagent_whitelist = typecacheof(list( /datum/reagent/medicine, @@ -41,7 +41,7 @@ var/static/list/medipen_reagent_blacklist = typecacheof(list( /datum/reagent/medicine/morphine, )) - // NOVA EDIT END + // NOVA EDIT ADDITION END /obj/machinery/medipen_refiller/Initialize(mapload) . = ..() @@ -59,10 +59,9 @@ context[SCREENTIP_CONTEXT_LMB] = panel_open ? "Close panel" : "Open panel" else if(is_reagent_container(held_item) && held_item.is_open_container()) context[SCREENTIP_CONTEXT_LMB] = "Refill machine" - // NOVA EDIT - Universal medipen - // ORIGINAL: else if(istype(held_item, /obj/item/reagent_containers/hypospray/medipen) && reagents.has_reagent(allowed_pens[held_item.type])) + // NOVA EDIT CHANGE - ORIGINAL: else if(istype(held_item, /obj/item/reagent_containers/hypospray/medipen) && reagents.has_reagent(allowed_pens[held_item.type])) else if(istype(held_item, /obj/item/reagent_containers/hypospray/medipen/universal) || istype(held_item, /obj/item/reagent_containers/hypospray/medipen) && reagents.has_reagent(allowed_pens[held_item.type])) - // NOVA EDIT END + // NOVA EDIT CHANGE END context[SCREENTIP_CONTEXT_LMB] = "Refill medipen" else if(istype(held_item, /obj/item/plunger)) context[SCREENTIP_CONTEXT_LMB] = "Plunge machine" @@ -101,17 +100,16 @@ if(medipen.reagents?.reagent_list.len) balloon_alert(user, "medipen full!") return - if(!reagents.has_reagent(allowed_pens[medipen.type], 10)) + // NOVA EDIT CHANGE - ORIGINAL: if(!reagents.has_reagent(allowed_pens[medipen.type], 10)) + if(!reagents.has_reagent(allowed_pens[medipen.type], medipen.volume)) + // NOVA EDIT CHANGE END balloon_alert(user, "not enough reagents!") return add_overlay("active") if(do_after(user, 2 SECONDS, src)) medipen.used_up = FALSE - // NOVA EDIT BEGIN - Universal medipen and lathe medipens + // NOVA EDIT ADDITION BEGIN - Universal medipen and lathe medipens if(istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal)) - if(reagents.total_volume < medipen.volume) - balloon_alert(user, "not enough reagents!") - return // Ignore reagents which aren't the blacklist or whitelist var/list/compatible_reagents = typecache_filter_multi_list_exclusion(reagents.reagent_list, medipen_reagent_whitelist, medipen_reagent_blacklist) // Ensure there is enough of the whitelisted reagents @@ -121,12 +119,14 @@ var/list/datum/reagent/target_reagent_types = list() for(var/datum/reagent/target_reagent in compatible_reagents) target_reagent_types += target_reagent.type - // Transfer equal amounts of each reagent - reagents.trans_to_equal(target_atom = medipen, target_ids = target_reagent_types) + // Transfer proportional amounts of each reagent + reagents.trans_to_multiple(target_atom = medipen, amount = medipen.volume, target_ids = target_reagent_types) else + // NOVA EDIT ADDITION END medipen.add_initial_reagents() + // NOVA EDIT CHANGE - ORIGINAL: reagents.remove_reagent(allowed_pens[medipen.type], 10) reagents.remove_reagent(allowed_pens[medipen.type], medipen.volume) - // NOVA EDIT END + // NOVA EDIT CHANGE END balloon_alert(user, "refilled") use_energy(active_power_usage) cut_overlays() From 4b6464c352ce01cf8a6f8b31d55d4e1753c0928d Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Mon, 12 Aug 2024 20:17:22 -0400 Subject: [PATCH 31/48] Cleaning up comments and refining --- .../code/modules/reagents/chemistry/holder.dm | 134 ++++++++++-------- 1 file changed, 71 insertions(+), 63 deletions(-) diff --git a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm index 72d40cac56c..6e6f8dbf7a5 100644 --- a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm +++ b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm @@ -47,14 +47,16 @@ Final transfer volume for reach reagent: T"i = Ti + T'i */ /** - * Calculates and transfers even amounts of each reagent to the target atom. Calls trans_to() to do the actual transfer. - * Unlike trans_to(), amount is auto-calculated, and target_id is replaced with list target_ids. + * Proportionally transfers each reagent to the target atom. Calls trans_to() to do the actual transfer. + * Unlike trans_to(), target_id is replaced with list target_ids. * * Arguments: * * obj/target - Target atom to attempt transfers to + * * amount - Maximum total reagent volume to transfer * * multiplier - multiplies each reagent amount by this number well byond their available volume before transfering. used to create reagents from thin air if you ever need to * * list/datum/reagent/target_ids - transfers only the listed reagent types in this holder leaving others untouched - * * preserve_data - if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. + * * preserve_data - if preserve_data=FALSE, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. + * * proportional - if proportional=TRUE, the volume of each reagent will be distributed proportionally to each other. If FALSE, then the volumes will be strictly equal. * * no_react - passed through to [/datum/reagents/proc/add_reagent] * * mob/transferred_by - used for logging * * remove_blacklisted - skips transferring of reagents without REAGENT_CAN_BE_SYNTHESIZED in chemical_flags @@ -62,10 +64,12 @@ T"i = Ti + T'i * * show_message - passed through to [/datum/reagents/proc/expose] * * ignore_stomach - when using methods INGEST will not use the stomach as the target */ -/datum/reagents/proc/trans_to_equal( +/datum/reagents/proc/trans_to_multiple( atom/target_atom, + amount = 1, multiplier = 1, list/datum/reagent/target_ids, + proportional = TRUE, preserve_data = TRUE, no_react = FALSE, mob/transferred_by, @@ -74,31 +78,44 @@ T"i = Ti + T'i show_message = TRUE, ignore_stomach = FALSE ) - // Targeted atom can not hold reagents - if(isnull(target_atom.reagents)) + // Nothing to transfer, or the targeted atom can't hold reagents + if(!total_volume || QDELETED(target_atom) || isnull(target_atom.reagents)) + return FALSE + + if(!IS_FINITE(amount)) + stack_trace("non-number or infinite number passed to trans_to_equal: amount = [amount]") + return FALSE + + // Ensure given amount is in a safe range + amount = round(amount, CHEMICAL_QUANTISATION_LEVEL) + if(amount <= 0) return FALSE // Maximum amount of reagents which can fit inside the target - var/max_volume = target_atom.reagents.maximum_volume + var/max_volume = min(amount, target_atom.reagents.maximum_volume) // Total volume of the reagents already inside the target var/current_volume = target_atom.reagents.total_volume - // Total volume of the empty space inside the target - var/empty_volume = max_volume - current_volume + // Total volume of fillable empty space inside the target, accounting for given maximum + var/empty_volume = max(0, max_volume - current_volume) // Targeted atom is already full of reagents - if(empty_volume <= 0) + if(max_volume == 0 || empty_volume == 0) return FALSE // Total volume of transferable reagents after whitelisting and rounding var/possible_transfer_volume = 0 - // Organize targeted reagents into associative list of typepaths to datums + // Reagent typepaths to be transferred after whitelisting var/list/datum/reagent/target_reagents = list() - // TRUE if a reagent whitelist was given - var/using_whitelist = length(target_ids) != 0 + // Only FALSE if a reagent whitelist was given + var/ignore_whitelist = isnull(target_ids) + + var/list/cached_reagents = reagent_list // Perform whitelisting and rounding, then calculate total possible transfer volume - for(var/datum/reagent/reagent in reagent_list) - if(!using_whitelist || target_ids[reagent.type]) - target_reagents[reagent.type] += reagent + for(var/datum/reagent/reagent in cached_reagents) + if(remove_blacklisted && !(reagent.chemical_flags & REAGENT_CAN_BE_SYNTHESIZED)) + continue + if(ignore_whitelist || is_type_in_list(reagent.type, target_ids)) + target_reagents += reagent.type possible_transfer_volume += round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) // There are no transferable reagents @@ -107,7 +124,7 @@ T"i = Ti + T'i // Total transfer volume can't exceed capacity possible_transfer_volume = min(empty_volume, possible_transfer_volume) - // Ensure there is enough reagent volume to transfer anything + // Insufficient reagent volume if(possible_transfer_volume < CHEMICAL_QUANTISATION_LEVEL) return FALSE @@ -118,71 +135,62 @@ T"i = Ti + T'i // Total deficit volume. Enables second pass if not zero. var/deficit_transfer_volume = empty_volume // Total quantity of reagents with volume above initial_target_volume. - var/excess_reagents = length(target_reagents) - - // Organize transfer volumes into associative list of typepaths to volumes - // Used as a scratchpad to calculate transfer volumes and provide reagent transfer amounts to trans_to() - var/list/datum/reagent/transfer_volumes = list() + var/excess_reagents = 0 + // Associative list of reagent typepaths to transfer volumes + // Used to provide reagent transfer amounts to trans_to() + var/list/transfer_volumes = list() // First pass, calculate initial transfer volumes per reagent // Account for reagents with insufficient and excess volumes for(var/datum/reagent/reagent in target_reagents) var/reagent_volume = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) var/transfer_volume = min(reagent_volume, initial_target_volume) transfer_volumes[reagent.type] = transfer_volume - remaining_transfer_volume += reagent_volume - transfer_volume + remaining_transfer_volume += max(0, reagent_volume - transfer_volume) // Account for insufficient reagent volume - deficit_transfer_volume = deficit_transfer_volume - transfer_volume + deficit_transfer_volume = max(0, deficit_transfer_volume - transfer_volume) // This reagent has excess volume. Could be redistributed in the second pass if(reagent_volume > initial_target_volume) excess_reagents++ // Second pass, mitigate insufficient volumes via redistribution of excess volumes. - if((deficit_transfer_volume > 0) && (remaining_transfer_volume > 0)) + if(proportional && (deficit_transfer_volume > 0) && (remaining_transfer_volume > 0)) + // Total transfer volume is insufficient + // Increase transfer volumes of excess reagents to compensate for the deficit for(var/datum/reagent/reagent in target_reagents) var/transfer_volume = transfer_volumes[reagent.type] - // Transfer volume of this reagent is sufficient or higher, so skip it - if(transfer_volume >= initial_target_volume) + var/reagent_volume = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) + + // This reagent has no excess volume, to skip it + var/remaining_reagent_volume = max(0, reagent_volume - transfer_volume) + if(remaining_reagent_volume == 0) continue - // Transfer volume of this reagent is insufficient, so others must be increased - // Increase transfer volumes of excess reagents to compensate for the deficit - for(var/datum/reagent/sub_reagent in target_reagents) - var/sub_transfer_volume = transfer_volumes[sub_reagent.type] - var/sub_volume = round(sub_reagent.volume, CHEMICAL_QUANTISATION_LEVEL) - - // This reagent has no excess volume, to skip it - var/remaining_reagent_volume = sub_volume - sub_transfer_volume - if(remaining_reagent_volume <= 0) - continue - - // Only this reagent has excess volume, so we can skip a bunch of steps - if(excess_reagents == 1) - transfer_volumes[sub_reagent.type] = min(sub_volume, deficit_transfer_volume) - excess_reagents-- - break - - // Calculate ideal volume adjustment based on deficit volume divided by quantity of excess reagents - var/proportional_volume_increase = round(deficit_transfer_volume / excess_reagents, CHEMICAL_QUANTISATION_LEVEL) - // Compensated on a best-effort basis - var/new_transfer_volume = min(sub_volume, sub_transfer_volume + proportional_volume_increase) - transfer_volumes[sub_reagent.type] = new_transfer_volume - - // Account for the remaining deficit - deficit_transfer_volume = min(0, deficit_transfer_volume - proportional_volume_increase) - if(deficit_transfer_volume == 0) - break - // Depleted this reagent after increasing but there's still a deficit - if(new_transfer_volume == sub_volume) - // Subtracting increases the proportional adjustment - excess_reagents-- - - // Used up excess reagents in nested loop - // This also implies that remaining_transfer_volume is zero - if(excess_reagents == 0) + + // Only this reagent has excess volume, so we can skip a bunch of steps + if(excess_reagents == 1) + transfer_volumes[reagent.type] = min(reagent_volume, deficit_transfer_volume) + excess_reagents-- break - // Fully fixed the deficit in nested loop + + // Calculate ideal volume adjustment based on deficit volume divided by quantity of excess reagents + var/proportional_volume_increase = round(deficit_transfer_volume / excess_reagents, CHEMICAL_QUANTISATION_LEVEL) + // Compensated on a best-effort basis + var/new_transfer_volume = min(reagent_volume, transfer_volume + proportional_volume_increase) + transfer_volumes[reagent.type] = new_transfer_volume + // Account for the remaining deficit + deficit_transfer_volume = max(0, deficit_transfer_volume - proportional_volume_increase) + + // Fully fixed the deficit if(deficit_transfer_volume == 0) break + // Depleted this reagent after increasing but there's still a deficit + if(new_transfer_volume == reagent_volume) + // Subtracting increases the proportional adjustment + excess_reagents-- + // Used up excess reagents + // This also implies that remaining_transfer_volume is zero + if(excess_reagents == 0) + break // Actually perform the reagent transfers and return total volume transferred var/transfer_total = 0 From 970e23b429f312a3124e855b74f253872ede7ddc Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sun, 1 Sep 2024 14:34:35 -0400 Subject: [PATCH 32/48] Improve type safety --- .../code/modules/reagents/reagent_containers/hypospray.dm | 5 +++-- modular_nova/modules/lathe_medipens/code/hypospray.dm | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm b/modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm index e9f8d86daa8..afa35fce29f 100644 --- a/modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm +++ b/modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm @@ -16,12 +16,13 @@ list_reagents = initial_reagents if(label_examine) + var/reagent_types = assoc_to_keys(list_reagents) // Set label text via list_reagents, due to actual reagents being empty - label_text = span_notice("There is a sticker pasted onto the side which reads, 'WARNING: This medipen contains [pretty_string_from_reagent_list(list_reagents, names_only = TRUE, join_text = ", ", final_and = TRUE, capitalize_names = TRUE)], do not use if allergic to any listed chemicals.") + label_text = span_notice("There is a sticker pasted onto the side which reads, 'WARNING: This medipen contains [pretty_string_from_reagent_list(reagent_types, names_only = TRUE, join_text = ", ", final_and = TRUE, capitalize_names = TRUE)], do not use if allergic to any listed chemicals.") // Sends a more generic chat message when an unused medipen is empty /obj/item/reagent_containers/hypospray/medipen/inject(mob/living/affected_mob, mob/user) - if(init_empty && used_up && unused) + if(!reagents?.total_volume || (init_empty && used_up && unused)) to_chat(user, span_warning("You push [src]'s button, but nothing happens. It's empty!")) return FALSE diff --git a/modular_nova/modules/lathe_medipens/code/hypospray.dm b/modular_nova/modules/lathe_medipens/code/hypospray.dm index 01ca48c53ea..dc71ad1ac40 100644 --- a/modular_nova/modules/lathe_medipens/code/hypospray.dm +++ b/modular_nova/modules/lathe_medipens/code/hypospray.dm @@ -34,9 +34,9 @@ /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure/update_icon_state() . = ..() - if(reagents.total_volume == 0) + if(!reagents?.total_volume == 0) icon_state = "[base_icon_state]0" - else if(reagents.total_volume > (volume * 0.5)) + else if(!reagents?.total_volume > (volume * 0.5)) icon_state = base_icon_state else icon_state = "[base_icon_state]15" @@ -46,7 +46,7 @@ if(!reagents?.total_volume) return var/overlay_icon = "medipen" - if(reagents.total_volume > (volume * 0.5)) + if(!reagents?.total_volume > (volume * 0.5)) icon_state = base_icon_state else overlay_icon = "medipen_half" From d3e9d20b0992e100b40e7bf793b7b2a80b0f6083 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sun, 1 Sep 2024 14:35:33 -0400 Subject: [PATCH 33/48] Improve type safety --- code/game/machinery/medipen_refiller.dm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index f7229473a93..d311cc126e0 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -102,7 +102,6 @@ return // NOVA EDIT CHANGE - ORIGINAL: if(!reagents.has_reagent(allowed_pens[medipen.type], 10)) if(!reagents.has_reagent(allowed_pens[medipen.type], medipen.volume)) - // NOVA EDIT CHANGE END balloon_alert(user, "not enough reagents!") return add_overlay("active") @@ -111,22 +110,24 @@ // NOVA EDIT ADDITION BEGIN - Universal medipen and lathe medipens if(istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal)) // Ignore reagents which aren't the blacklist or whitelist - var/list/compatible_reagents = typecache_filter_multi_list_exclusion(reagents.reagent_list, medipen_reagent_whitelist, medipen_reagent_blacklist) + var/list/datum/reagent/compatible_reagents = typecache_filter_multi_list_exclusion(reagents.reagent_list, medipen_reagent_whitelist, medipen_reagent_blacklist) // Ensure there is enough of the whitelisted reagents if(!length(compatible_reagents)) balloon_alert(user, "reagents incompatible!") return - var/list/datum/reagent/target_reagent_types = list() - for(var/datum/reagent/target_reagent in compatible_reagents) + // Create list of transferable reagent typepaths + var/list/target_reagent_types = list() + for(var/datum/reagent/target_reagent as anything in compatible_reagents) target_reagent_types += target_reagent.type // Transfer proportional amounts of each reagent reagents.trans_to_multiple(target_atom = medipen, amount = medipen.volume, target_ids = target_reagent_types) else // NOVA EDIT ADDITION END + // NOVA EDIT CHANGE BEGIN - Universal medipen and lathe medipens medipen.add_initial_reagents() // NOVA EDIT CHANGE - ORIGINAL: reagents.remove_reagent(allowed_pens[medipen.type], 10) reagents.remove_reagent(allowed_pens[medipen.type], medipen.volume) - // NOVA EDIT CHANGE END + // NOVA EDIT CHANGE END balloon_alert(user, "refilled") use_energy(active_power_usage) cut_overlays() From 691b1fb2a879bda0d5469f2b1fce3312e0c4739e Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sun, 1 Sep 2024 14:37:25 -0400 Subject: [PATCH 34/48] Improve type safety --- .../code/modules/reagents/chemistry/holder.dm | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm index 6e6f8dbf7a5..aa8c8d4ceac 100644 --- a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm +++ b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm @@ -104,18 +104,18 @@ T"i = Ti + T'i // Total volume of transferable reagents after whitelisting and rounding var/possible_transfer_volume = 0 - // Reagent typepaths to be transferred after whitelisting - var/list/datum/reagent/target_reagents = list() // Only FALSE if a reagent whitelist was given var/ignore_whitelist = isnull(target_ids) var/list/cached_reagents = reagent_list + // Associative list of reagent typepaths to datums + var/list/datum/reagent/target_reagents = list() // Perform whitelisting and rounding, then calculate total possible transfer volume - for(var/datum/reagent/reagent in cached_reagents) + for(var/datum/reagent/reagent as anything in cached_reagents) if(remove_blacklisted && !(reagent.chemical_flags & REAGENT_CAN_BE_SYNTHESIZED)) continue if(ignore_whitelist || is_type_in_list(reagent.type, target_ids)) - target_reagents += reagent.type + target_reagents[reagent.type] = reagent possible_transfer_volume += round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) // There are no transferable reagents @@ -142,7 +142,7 @@ T"i = Ti + T'i var/list/transfer_volumes = list() // First pass, calculate initial transfer volumes per reagent // Account for reagents with insufficient and excess volumes - for(var/datum/reagent/reagent in target_reagents) + for(var/datum/reagent/reagent as anything in target_reagents) var/reagent_volume = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) var/transfer_volume = min(reagent_volume, initial_target_volume) transfer_volumes[reagent.type] = transfer_volume @@ -157,8 +157,9 @@ T"i = Ti + T'i if(proportional && (deficit_transfer_volume > 0) && (remaining_transfer_volume > 0)) // Total transfer volume is insufficient // Increase transfer volumes of excess reagents to compensate for the deficit - for(var/datum/reagent/reagent in target_reagents) - var/transfer_volume = transfer_volumes[reagent.type] + for(var/datum/reagent/reagent as anything in target_reagents) + var/reagent_type = reagent.type + var/transfer_volume = transfer_volumes[reagent_type] var/reagent_volume = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) // This reagent has no excess volume, to skip it @@ -166,17 +167,16 @@ T"i = Ti + T'i if(remaining_reagent_volume == 0) continue - // Only this reagent has excess volume, so we can skip a bunch of steps + // Only this reagent has excess volume, so we can skip steps if(excess_reagents == 1) - transfer_volumes[reagent.type] = min(reagent_volume, deficit_transfer_volume) - excess_reagents-- + transfer_volumes[reagent_type] = min(reagent_volume, deficit_transfer_volume) break // Calculate ideal volume adjustment based on deficit volume divided by quantity of excess reagents var/proportional_volume_increase = round(deficit_transfer_volume / excess_reagents, CHEMICAL_QUANTISATION_LEVEL) // Compensated on a best-effort basis var/new_transfer_volume = min(reagent_volume, transfer_volume + proportional_volume_increase) - transfer_volumes[reagent.type] = new_transfer_volume + transfer_volumes[reagent_type] = new_transfer_volume // Account for the remaining deficit deficit_transfer_volume = max(0, deficit_transfer_volume - proportional_volume_increase) From afcc3fab5f478976321855678e06348bc9e772de Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sun, 1 Sep 2024 16:57:51 -0400 Subject: [PATCH 35/48] Cleanup list accesses --- .../code/modules/reagents/chemistry/holder.dm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm index aa8c8d4ceac..e0594d6382f 100644 --- a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm +++ b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm @@ -114,7 +114,7 @@ T"i = Ti + T'i for(var/datum/reagent/reagent as anything in cached_reagents) if(remove_blacklisted && !(reagent.chemical_flags & REAGENT_CAN_BE_SYNTHESIZED)) continue - if(ignore_whitelist || is_type_in_list(reagent.type, target_ids)) + if(ignore_whitelist || is_type_in_list(reagent, target_ids)) target_reagents[reagent.type] = reagent possible_transfer_volume += round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) @@ -142,7 +142,8 @@ T"i = Ti + T'i var/list/transfer_volumes = list() // First pass, calculate initial transfer volumes per reagent // Account for reagents with insufficient and excess volumes - for(var/datum/reagent/reagent as anything in target_reagents) + for(var/reagent_type as anything in target_reagents) + var/datum/reagent/reagent = target_reagents[reagent_type] var/reagent_volume = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) var/transfer_volume = min(reagent_volume, initial_target_volume) transfer_volumes[reagent.type] = transfer_volume @@ -157,8 +158,8 @@ T"i = Ti + T'i if(proportional && (deficit_transfer_volume > 0) && (remaining_transfer_volume > 0)) // Total transfer volume is insufficient // Increase transfer volumes of excess reagents to compensate for the deficit - for(var/datum/reagent/reagent as anything in target_reagents) - var/reagent_type = reagent.type + for(var/reagent_type as anything in target_reagents) + var/datum/reagent/reagent = target_reagents[reagent_type] var/transfer_volume = transfer_volumes[reagent_type] var/reagent_volume = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) @@ -194,7 +195,7 @@ T"i = Ti + T'i // Actually perform the reagent transfers and return total volume transferred var/transfer_total = 0 - for(var/datum/reagent/reagent in target_reagents) + for(var/datum/reagent/reagent as anything in target_reagents) transfer_total += trans_to( target = target_atom, amount = transfer_volumes[reagent], From a1877c2e64464dcdb7b71c1594685426fa5fc951 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sun, 6 Oct 2024 23:39:59 -0400 Subject: [PATCH 36/48] Add workaround for reagent flags reset on injection, fix overlay and iconstate bugs --- .../modules/lathe_medipens/code/hypospray.dm | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/code/hypospray.dm b/modular_nova/modules/lathe_medipens/code/hypospray.dm index dc71ad1ac40..7d75edea01c 100644 --- a/modular_nova/modules/lathe_medipens/code/hypospray.dm +++ b/modular_nova/modules/lathe_medipens/code/hypospray.dm @@ -1,10 +1,12 @@ /obj/item/reagent_containers/hypospray/medipen/universal - name = "\improper universal medipen" + name = "universal medipen" + article = "a" desc = "It's an auto-injecting syringe with a universal refill port on the side." icon = 'modular_nova/modules/lathe_medipens/icons/syringe.dmi' icon_state = "medipen_blue_unused" base_icon_state = "medipen_blue" inhand_icon_state = "dnainjector0" + reagent_flags = TRANSPARENT list_reagents = null label_examine = FALSE used_up = TRUE @@ -24,8 +26,14 @@ filling_overlay.color = mix_color_from_reagents(reagents.reagent_list) . += filling_overlay +/obj/item/reagent_containers/hypospray/medipen/universal/inject(mob/living/affected_mob, mob/user) + . = ..() + if(. && used_up) + // Workaround to reset reagent flags after injection (gets set to 0 by parent proc) + reagents.flags = reagent_flags + /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure - name = "\improper universal low-pressure medipen" + name = "universal low-pressure medipen" desc = "It's a low-pressure auto-injecting syringe with a universal refill port on the side. WARNING: This device is designed to be operated in low-pressure environments only." icon_state = "medipen_red_unused" base_icon_state = "medipen_red" @@ -34,9 +42,9 @@ /obj/item/reagent_containers/hypospray/medipen/universal/lowpressure/update_icon_state() . = ..() - if(!reagents?.total_volume == 0) + if(reagents?.total_volume == 0) icon_state = "[base_icon_state]0" - else if(!reagents?.total_volume > (volume * 0.5)) + else if(reagents?.total_volume > (volume * 0.5)) icon_state = base_icon_state else icon_state = "[base_icon_state]15" @@ -46,9 +54,7 @@ if(!reagents?.total_volume) return var/overlay_icon = "medipen" - if(!reagents?.total_volume > (volume * 0.5)) - icon_state = base_icon_state - else + if(reagents?.total_volume <= (volume * 0.5)) overlay_icon = "medipen_half" var/mutable_appearance/filling_overlay = mutable_appearance('modular_nova/modules/lathe_medipens/icons/reagent_fillings.dmi', overlay_icon) filling_overlay.color = mix_color_from_reagents(reagents.reagent_list) From 94ca574ed6afa94fd4fac063182e1376d2787a81 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sun, 6 Oct 2024 23:40:28 -0400 Subject: [PATCH 37/48] Fix alert bug --- code/game/machinery/medipen_refiller.dm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index d311cc126e0..76a5549d726 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -101,14 +101,16 @@ balloon_alert(user, "medipen full!") return // NOVA EDIT CHANGE - ORIGINAL: if(!reagents.has_reagent(allowed_pens[medipen.type], 10)) - if(!reagents.has_reagent(allowed_pens[medipen.type], medipen.volume)) + if(!istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal) && !reagents.has_reagent(allowed_pens[medipen.type], medipen.volume)) balloon_alert(user, "not enough reagents!") return add_overlay("active") if(do_after(user, 2 SECONDS, src)) - medipen.used_up = FALSE - // NOVA EDIT ADDITION BEGIN - Universal medipen and lathe medipens + // NOVA EDIT CHANGE BEGIN - Universal medipen and lathe medipens if(istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal)) + if(!reagents.total_volume) + balloon_alert(user, "not enough reagents!") + return // Ignore reagents which aren't the blacklist or whitelist var/list/datum/reagent/compatible_reagents = typecache_filter_multi_list_exclusion(reagents.reagent_list, medipen_reagent_whitelist, medipen_reagent_blacklist) // Ensure there is enough of the whitelisted reagents @@ -122,11 +124,10 @@ // Transfer proportional amounts of each reagent reagents.trans_to_multiple(target_atom = medipen, amount = medipen.volume, target_ids = target_reagent_types) else - // NOVA EDIT ADDITION END - // NOVA EDIT CHANGE BEGIN - Universal medipen and lathe medipens medipen.add_initial_reagents() // NOVA EDIT CHANGE - ORIGINAL: reagents.remove_reagent(allowed_pens[medipen.type], 10) reagents.remove_reagent(allowed_pens[medipen.type], medipen.volume) + medipen.used_up = FALSE // NOVA EDIT CHANGE END balloon_alert(user, "refilled") use_energy(active_power_usage) From bfadac8b4b0a9b6636c636fb60b0a9bb621bd544 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sun, 6 Oct 2024 23:40:58 -0400 Subject: [PATCH 38/48] Change universal medipens to require TECHWEB_NODE_CHEM_SYNTHESIS and have lower cost --- modular_nova/modules/lathe_medipens/code/medbay_nodes.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm b/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm index 330b617c9e8..3ed96eb1e91 100644 --- a/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm +++ b/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm @@ -2,7 +2,7 @@ id = TECHWEB_NODE_MEDBAY_MEDIPENS display_name = "Auto-Injecting 'Medipen' Syringes" description = "Advanced auto-injecting syringes, called 'medipens'. Used for automatically injecting medications into patients." - prereq_ids = list(TECHWEB_NODE_MEDBAY_EQUIP_ADV) + prereq_ids = list(TECHWEB_NODE_CHEM_SYNTHESIS) design_ids = list( "medipen_universal", "medipen_universal_lowpressure", @@ -13,4 +13,4 @@ "medipen_salacid", "medipen_penacid", ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) From a43b3186310d5892009efaf261ea253f8ecc5e13 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sun, 6 Oct 2024 23:41:16 -0400 Subject: [PATCH 39/48] Refactor naive solution --- .../code/modules/reagents/chemistry/holder.dm | 108 ++---------------- 1 file changed, 8 insertions(+), 100 deletions(-) diff --git a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm index e0594d6382f..51b8f6fd805 100644 --- a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm +++ b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm @@ -16,36 +16,6 @@ return FALSE -/* trans_to_equal() Theory of Operation: -Vi = volume of each available reagent. -n = total types of reagents. -V = target volume for each reagent after transfer. - -Find V such that the volume of each reagent is as equal as possible. - -Total combined volume of all reagents: - n -Vtotal = ∑ Vi - i=1 - -Initial target volume per reagent: -Vinitial = Vtotal / n - -For each reagent, the volume to be transferred is: -Ti = min(Vi, Vinitial) - -After an initial transfer, we need to do a second pass. -Calculate the remaining volume after the initial round: - n -Vremaining = Vtotal - ∑ Ti - i=1 - -Redistribute remaining volume, for reagents where Vi > Ti: -T'i = Ti + Vremaining x (Vi - Ti) / ∑{j | Vj > Tj} (Vj - Tj) - -Final transfer volume for reach reagent: -T"i = Ti + T'i -*/ /** * Proportionally transfers each reagent to the target atom. Calls trans_to() to do the actual transfer. * Unlike trans_to(), target_id is replaced with list target_ids. @@ -106,92 +76,30 @@ T"i = Ti + T'i var/possible_transfer_volume = 0 // Only FALSE if a reagent whitelist was given var/ignore_whitelist = isnull(target_ids) - - var/list/cached_reagents = reagent_list // Associative list of reagent typepaths to datums var/list/datum/reagent/target_reagents = list() - // Perform whitelisting and rounding, then calculate total possible transfer volume + var/list/cached_reagents = reagent_list + // Perform whitelisting, then calculate total possible transfer volume for(var/datum/reagent/reagent as anything in cached_reagents) if(remove_blacklisted && !(reagent.chemical_flags & REAGENT_CAN_BE_SYNTHESIZED)) continue - if(ignore_whitelist || is_type_in_list(reagent, target_ids)) + if(ignore_whitelist || is_type_in_list(reagent, target_ids) && reagent.volume) target_reagents[reagent.type] = reagent - possible_transfer_volume += round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) + possible_transfer_volume += reagent.volume // There are no transferable reagents - if(!length(target_reagents)) - return FALSE - - // Total transfer volume can't exceed capacity - possible_transfer_volume = min(empty_volume, possible_transfer_volume) - // Insufficient reagent volume - if(possible_transfer_volume < CHEMICAL_QUANTISATION_LEVEL) + if(!length(target_reagents) || !possible_transfer_volume) return FALSE - // Implements even distribution in first pass if reagent volumes meet this minimum - var/initial_target_volume = round(possible_transfer_volume / length(target_reagents), CHEMICAL_QUANTISATION_LEVEL) - // Volume of excess reagents. Redistributed in second pass if not zero. - var/remaining_transfer_volume = 0 - // Total deficit volume. Enables second pass if not zero. - var/deficit_transfer_volume = empty_volume - // Total quantity of reagents with volume above initial_target_volume. - var/excess_reagents = 0 - // Associative list of reagent typepaths to transfer volumes // Used to provide reagent transfer amounts to trans_to() var/list/transfer_volumes = list() - // First pass, calculate initial transfer volumes per reagent + // Calculate proportional transfer volumes per reagent // Account for reagents with insufficient and excess volumes for(var/reagent_type as anything in target_reagents) var/datum/reagent/reagent = target_reagents[reagent_type] - var/reagent_volume = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) - var/transfer_volume = min(reagent_volume, initial_target_volume) - transfer_volumes[reagent.type] = transfer_volume - remaining_transfer_volume += max(0, reagent_volume - transfer_volume) - // Account for insufficient reagent volume - deficit_transfer_volume = max(0, deficit_transfer_volume - transfer_volume) - // This reagent has excess volume. Could be redistributed in the second pass - if(reagent_volume > initial_target_volume) - excess_reagents++ - - // Second pass, mitigate insufficient volumes via redistribution of excess volumes. - if(proportional && (deficit_transfer_volume > 0) && (remaining_transfer_volume > 0)) - // Total transfer volume is insufficient - // Increase transfer volumes of excess reagents to compensate for the deficit - for(var/reagent_type as anything in target_reagents) - var/datum/reagent/reagent = target_reagents[reagent_type] - var/transfer_volume = transfer_volumes[reagent_type] - var/reagent_volume = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) - - // This reagent has no excess volume, to skip it - var/remaining_reagent_volume = max(0, reagent_volume - transfer_volume) - if(remaining_reagent_volume == 0) - continue - - // Only this reagent has excess volume, so we can skip steps - if(excess_reagents == 1) - transfer_volumes[reagent_type] = min(reagent_volume, deficit_transfer_volume) - break - - // Calculate ideal volume adjustment based on deficit volume divided by quantity of excess reagents - var/proportional_volume_increase = round(deficit_transfer_volume / excess_reagents, CHEMICAL_QUANTISATION_LEVEL) - // Compensated on a best-effort basis - var/new_transfer_volume = min(reagent_volume, transfer_volume + proportional_volume_increase) - transfer_volumes[reagent_type] = new_transfer_volume - // Account for the remaining deficit - deficit_transfer_volume = max(0, deficit_transfer_volume - proportional_volume_increase) - - // Fully fixed the deficit - if(deficit_transfer_volume == 0) - break - // Depleted this reagent after increasing but there's still a deficit - if(new_transfer_volume == reagent_volume) - // Subtracting increases the proportional adjustment - excess_reagents-- - // Used up excess reagents - // This also implies that remaining_transfer_volume is zero - if(excess_reagents == 0) - break + var/distributed_volume = round(reagent.volume / possible_transfer_volume, CHEMICAL_QUANTISATION_LEVEL) + transfer_volumes[reagent.type] = empty_volume * distributed_volume // Actually perform the reagent transfers and return total volume transferred var/transfer_total = 0 From 84f58c993f0267b4a31ed8556b028c4ddee24ed4 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Fri, 11 Oct 2024 16:44:25 -0400 Subject: [PATCH 40/48] Cleaning up unused vars and a oversight --- .../master_files/code/modules/reagents/chemistry/holder.dm | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm index 51b8f6fd805..a27880e0ff5 100644 --- a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm +++ b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm @@ -26,7 +26,6 @@ * * multiplier - multiplies each reagent amount by this number well byond their available volume before transfering. used to create reagents from thin air if you ever need to * * list/datum/reagent/target_ids - transfers only the listed reagent types in this holder leaving others untouched * * preserve_data - if preserve_data=FALSE, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. - * * proportional - if proportional=TRUE, the volume of each reagent will be distributed proportionally to each other. If FALSE, then the volumes will be strictly equal. * * no_react - passed through to [/datum/reagents/proc/add_reagent] * * mob/transferred_by - used for logging * * remove_blacklisted - skips transferring of reagents without REAGENT_CAN_BE_SYNTHESIZED in chemical_flags @@ -39,7 +38,6 @@ amount = 1, multiplier = 1, list/datum/reagent/target_ids, - proportional = TRUE, preserve_data = TRUE, no_react = FALSE, mob/transferred_by, @@ -63,10 +61,8 @@ // Maximum amount of reagents which can fit inside the target var/max_volume = min(amount, target_atom.reagents.maximum_volume) - // Total volume of the reagents already inside the target - var/current_volume = target_atom.reagents.total_volume // Total volume of fillable empty space inside the target, accounting for given maximum - var/empty_volume = max(0, max_volume - current_volume) + var/empty_volume = max(0, max_volume - target_atom.reagents.total_volume) // Targeted atom is already full of reagents if(max_volume == 0 || empty_volume == 0) From efc7837ae806fda605dc2d99f6a38b8f3e7af39c Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Fri, 11 Oct 2024 16:45:30 -0400 Subject: [PATCH 41/48] Fixing refiller logic to make more sense to the user --- code/game/machinery/medipen_refiller.dm | 28 ++++++++++++++----------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index 76a5549d726..ec32f16b5ac 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -100,28 +100,32 @@ if(medipen.reagents?.reagent_list.len) balloon_alert(user, "medipen full!") return + // NOVA EDIT CHANGE BEGIN - Universal medipen and lathe medipens + var/list/datum/reagent/compatible_universal_reagents + if(istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal)) + if(!reagents.total_volume) + balloon_alert(user, "not enough reagents!") + return + // Ignore reagents which aren't the blacklist or whitelist + compatible_universal_reagents = typecache_filter_multi_list_exclusion(reagents.reagent_list, medipen_reagent_whitelist, medipen_reagent_blacklist) + // Ensure there is enough of the whitelisted reagents + if(!length(compatible_universal_reagents)) + balloon_alert(user, "reagents incompatible!") + return + // NOVA EDIT CHANGE END // NOVA EDIT CHANGE - ORIGINAL: if(!reagents.has_reagent(allowed_pens[medipen.type], 10)) - if(!istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal) && !reagents.has_reagent(allowed_pens[medipen.type], medipen.volume)) + else if(!reagents.has_reagent(allowed_pens[medipen.type], medipen.volume)) balloon_alert(user, "not enough reagents!") return add_overlay("active") if(do_after(user, 2 SECONDS, src)) // NOVA EDIT CHANGE BEGIN - Universal medipen and lathe medipens if(istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal)) - if(!reagents.total_volume) - balloon_alert(user, "not enough reagents!") - return - // Ignore reagents which aren't the blacklist or whitelist - var/list/datum/reagent/compatible_reagents = typecache_filter_multi_list_exclusion(reagents.reagent_list, medipen_reagent_whitelist, medipen_reagent_blacklist) - // Ensure there is enough of the whitelisted reagents - if(!length(compatible_reagents)) - balloon_alert(user, "reagents incompatible!") - return // Create list of transferable reagent typepaths var/list/target_reagent_types = list() - for(var/datum/reagent/target_reagent as anything in compatible_reagents) + for(var/datum/reagent/target_reagent as anything in compatible_universal_reagents) target_reagent_types += target_reagent.type - // Transfer proportional amounts of each reagent + // Transfer proportionally distributed amounts of each reagent reagents.trans_to_multiple(target_atom = medipen, amount = medipen.volume, target_ids = target_reagent_types) else medipen.add_initial_reagents() From e635d3f6a43f749a0ade4e7b1f26149c70417e7d Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Fri, 11 Oct 2024 18:00:45 -0400 Subject: [PATCH 42/48] Add inhand sprites for universal medipens --- .../modules/lathe_medipens/code/hypospray.dm | 5 ++++- .../lathe_medipens/icons/medical_lefthand.dmi | Bin 0 -> 666 bytes .../lathe_medipens/icons/medical_righthand.dmi | Bin 0 -> 833 bytes 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 modular_nova/modules/lathe_medipens/icons/medical_lefthand.dmi create mode 100644 modular_nova/modules/lathe_medipens/icons/medical_righthand.dmi diff --git a/modular_nova/modules/lathe_medipens/code/hypospray.dm b/modular_nova/modules/lathe_medipens/code/hypospray.dm index 7d75edea01c..be269b83162 100644 --- a/modular_nova/modules/lathe_medipens/code/hypospray.dm +++ b/modular_nova/modules/lathe_medipens/code/hypospray.dm @@ -3,9 +3,11 @@ article = "a" desc = "It's an auto-injecting syringe with a universal refill port on the side." icon = 'modular_nova/modules/lathe_medipens/icons/syringe.dmi' + lefthand_file = 'modular_nova/modules/lathe_medipens/icons/medical_lefthand.dmi' + righthand_file = 'modular_nova/modules/lathe_medipens/icons//medical_righthand.dmi' icon_state = "medipen_blue_unused" base_icon_state = "medipen_blue" - inhand_icon_state = "dnainjector0" + inhand_icon_state = "medipen_blue" reagent_flags = TRANSPARENT list_reagents = null label_examine = FALSE @@ -37,6 +39,7 @@ desc = "It's a low-pressure auto-injecting syringe with a universal refill port on the side. WARNING: This device is designed to be operated in low-pressure environments only." icon_state = "medipen_red_unused" base_icon_state = "medipen_red" + inhand_icon_state = "medipen_red" volume = 30 amount_per_transfer_from_this = 30 diff --git a/modular_nova/modules/lathe_medipens/icons/medical_lefthand.dmi b/modular_nova/modules/lathe_medipens/icons/medical_lefthand.dmi new file mode 100644 index 0000000000000000000000000000000000000000..8414511a452e063e099d3d753a496711b7d86cf5 GIT binary patch literal 666 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGo zg2M`mO22;zF8KKMiI%sn*10q1gExd4Tr__0Nawtd=1GR4p57f6#zDrHjlC4+JeqW5 zQiwvZrn#x=W(8AyJI&=Lp`G2vs+(6xEScVIyjH`|T=a<9k&u`vvzoluZfaURpZkU? zL-S!R5m(u53mF&~?|Hg7hE&XXd&l1Iuz|?&LUBXGkerwX(S@s$R$f`?{=(O&u)}ZW zPM7`*9#bO(oI19OCpfz%@m6|t8Zmfvy!|e-Z~o5GxIdeJyI1uU1HA+VRkz-6TUy4u za>ft24fFoIzIn*^y#Aj4{Cm#=cHKUG?tAT{-@i^@tx}qNU*z-oH~DdQKEB=hxwe|$ z;l!!=_x66*TjqOj`Xl$5I{Th4|9x&fztDl{S<>Hhfuh&nENMCMXtIB!&gnNg^Y$H` zp;gBa{QcrqiC|Y|nB8DH!O6>a@8Z|@{omFc`ta_>*@Gd{mA`8aEiO)b_3PvUQ6<|y zm)!Q%>?o@BYdxYc`Txe-|0>l@zK5|&E!uZ$f$W7ZAEam37_Jw)zT&+4k}Ga@yFPP1 zqVuvEJ0h1sWoJ?|S7bsyGx^6&TgcQZ@&X_aCHzrwT6pI^)U zt2}g9_Tavj&o=y0O+C7f%M1A4m^;?9dU7Zpn|hMpv@FN-ACK(mC*3N{62d61m|v~4 VIL~hBnJiG4c)I$ztaD0e0syu)ArSxo literal 0 HcmV?d00001 diff --git a/modular_nova/modules/lathe_medipens/icons/medical_righthand.dmi b/modular_nova/modules/lathe_medipens/icons/medical_righthand.dmi new file mode 100644 index 0000000000000000000000000000000000000000..c55f0af5f12d6df1178db6643e0d907137de3238 GIT binary patch literal 833 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGo zg2M`mO22;zF8KKMiI%sn*10q1gExd4Tr__0Nawtd=1GR4p57f6#zDrHjlC4+JeqW5 zQiwvZrn#x=W(8AyJI&=Lp`G2vs+(6xEScVIyjH`|T=a<9k&u`vvzoluZfaURpZkU? zL-S!R5m(u53mF)gT0LDHLn`LHy}P?hI8dhHqolq@*YvFyPI2G3(V=mpqv;pRFAYr} zTQjkZ9`CgyGV&L8D;;W5n%1qKpx*TMM17*ewIe=8mY?6wso8I4F#Yq~n6mG4d?T-y zDxOpP#bh>@F@dc?k|B*@25v^gY6kgxd%vAe>(t@-@cMcG-h<{&QvZ1a?EddFe_@_? zPxIZq`jBtMp0l5x*u$RmZ2$hhYc2jhstUBO22g{M$P>?{V>t zRjX$5zp1GTK6=!?x}tDGv;4Mg=R)K6*XZcQ?)+wQ^rQZMo2a8Iy`N>Q>xz~ZpQ+)L z>UAsK^JK{^%i7M@{l7bYdlvqg@zc;#`O~U@oCY&}UcD@_deL}a|DF0f?V}rayXnQw z*lH(OX(Oj^TKU&8r+1p{p9FmV!{K#aC5Lm~kEe58&N zK7VO&!ws8@U;jVXpY*us>;BR@eviMZoICZx^VhufwRk#RmdKI;Vst0PLV=h5!Hn literal 0 HcmV?d00001 From eadc4ebd48fd4b0af429c3cbc7b99616c7407674 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Fri, 11 Oct 2024 18:01:16 -0400 Subject: [PATCH 43/48] Shorten description for medbay_medipens --- modular_nova/modules/lathe_medipens/code/medbay_nodes.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm b/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm index 3ed96eb1e91..e2b3339fea0 100644 --- a/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm +++ b/modular_nova/modules/lathe_medipens/code/medbay_nodes.dm @@ -1,7 +1,7 @@ /datum/techweb_node/medbay_medipens id = TECHWEB_NODE_MEDBAY_MEDIPENS display_name = "Auto-Injecting 'Medipen' Syringes" - description = "Advanced auto-injecting syringes, called 'medipens'. Used for automatically injecting medications into patients." + description = "Advanced auto-injecting syringes, or 'medipens'. Used for automatically injecting medications." prereq_ids = list(TECHWEB_NODE_CHEM_SYNTHESIS) design_ids = list( "medipen_universal", From 5cff6710a28297ff16126ff8edaf9f872c2dda9a Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Fri, 11 Oct 2024 18:01:44 -0400 Subject: [PATCH 44/48] Update readme --- modular_nova/modules/lathe_medipens/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modular_nova/modules/lathe_medipens/README.md b/modular_nova/modules/lathe_medipens/README.md index f818d76c153..d97668dc557 100644 --- a/modular_nova/modules/lathe_medipens/README.md +++ b/modular_nova/modules/lathe_medipens/README.md @@ -21,15 +21,17 @@ Contains empty subtypes of several medipens, custom/universal medipen subtypes w ### Master file additions -- `modular_nova\master_files\code\modules\reagents\reagent_containers\hypospray.dm` +- `modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm` - Overrides `Initialize()` and `inject()`. - Adds new variables `medipen/var/init_empty` and `medipen/var/unused`. +- `modular_nova/master_files/code/modules/reagents/chemistry/holder.dm` + - Adds new proc `/datum/reagents/proc/trans_to_multiple()` ### Included files that are not contained in this module: Dependent to avoid runtime errors: -- `modular_nova\master_files\code\modules\reagents\reagent_containers\hypospray.dm` +- `modular_nova/master_files/code/modules/reagents/reagent_containers/hypospray.dm` ### Credits: - [@Floofies](https://github.com/Floofies) From 09482894add420e76f98a4a8c87fad3208761050 Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sun, 3 Nov 2024 19:51:33 -0500 Subject: [PATCH 45/48] Update modular_nova/master_files/code/modules/reagents/chemistry/holder.dm Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com> --- .../master_files/code/modules/reagents/chemistry/holder.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm index a27880e0ff5..19066263b33 100644 --- a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm +++ b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm @@ -44,7 +44,7 @@ remove_blacklisted = FALSE, methods = NONE, show_message = TRUE, - ignore_stomach = FALSE + ignore_stomach = FALSE, ) // Nothing to transfer, or the targeted atom can't hold reagents if(!total_volume || QDELETED(target_atom) || isnull(target_atom.reagents)) From efc16506da780599dc3ce0b53d46bc68da7fa85c Mon Sep 17 00:00:00 2001 From: Dani Glore Date: Sun, 3 Nov 2024 19:52:31 -0500 Subject: [PATCH 46/48] Apply suggestions from code review Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com> --- code/game/machinery/medipen_refiller.dm | 13 +++++++------ .../code/modules/reagents/chemistry/holder.dm | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index ec32f16b5ac..9641d66888d 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -100,7 +100,8 @@ if(medipen.reagents?.reagent_list.len) balloon_alert(user, "medipen full!") return - // NOVA EDIT CHANGE BEGIN - Universal medipen and lathe medipens + //if(!reagents.has_reagent(allowed_pens[medipen.type], 10)) // NOVA EDIT REMOVAL + // NOVA EDIT ADDITION BEGIN - Universal medipen and lathe medipens var/list/datum/reagent/compatible_universal_reagents if(istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal)) if(!reagents.total_volume) @@ -112,14 +113,13 @@ if(!length(compatible_universal_reagents)) balloon_alert(user, "reagents incompatible!") return - // NOVA EDIT CHANGE END - // NOVA EDIT CHANGE - ORIGINAL: if(!reagents.has_reagent(allowed_pens[medipen.type], 10)) else if(!reagents.has_reagent(allowed_pens[medipen.type], medipen.volume)) + // NOVA EDIT ADDITION END balloon_alert(user, "not enough reagents!") return add_overlay("active") if(do_after(user, 2 SECONDS, src)) - // NOVA EDIT CHANGE BEGIN - Universal medipen and lathe medipens + // NOVA EDIT ADDITION BEGIN - Universal medipen and lathe medipens if(istype(medipen, /obj/item/reagent_containers/hypospray/medipen/universal)) // Create list of transferable reagent typepaths var/list/target_reagent_types = list() @@ -129,10 +129,11 @@ reagents.trans_to_multiple(target_atom = medipen, amount = medipen.volume, target_ids = target_reagent_types) else medipen.add_initial_reagents() - // NOVA EDIT CHANGE - ORIGINAL: reagents.remove_reagent(allowed_pens[medipen.type], 10) reagents.remove_reagent(allowed_pens[medipen.type], medipen.volume) + // NOVA EDIT ADDITION END medipen.used_up = FALSE - // NOVA EDIT CHANGE END + //medipen.add_initial_reagents() // NOVA EDIT REMOVAL - Handled above + //reagents.remove_reagent(allowed_pens[medipen.type], 10) // NOVA EDIT REMOVAL - Handled above balloon_alert(user, "refilled") use_energy(active_power_usage) cut_overlays() diff --git a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm index 19066263b33..2e38f3f4555 100644 --- a/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm +++ b/modular_nova/master_files/code/modules/reagents/chemistry/holder.dm @@ -110,6 +110,6 @@ remove_blacklisted = remove_blacklisted, methods = methods, show_message = show_message, - ignore_stomach = ignore_stomach + ignore_stomach = ignore_stomach, ) return transfer_total From 46f4e2af9d845ef7c8132ce5d94fb1776cd67d0b Mon Sep 17 00:00:00 2001 From: Bloop <13398309+vinylspiders@users.noreply.github.com> Date: Fri, 20 Dec 2024 16:21:47 -0500 Subject: [PATCH 47/48] Update code/game/machinery/medipen_refiller.dm --- code/game/machinery/medipen_refiller.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index 9641d66888d..fcfebe4abe6 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -30,7 +30,6 @@ /obj/item/reagent_containers/hypospray/medipen/penacid/empty = /datum/reagent/medicine/pen_acid, // NOVA EDIT ADDITION END ) - // NOVA EDIT ADDITION BEGIN - Universal medipens ///Whitelist typecache of reagent types which are allowed to refill universal medipens. var/static/list/medipen_reagent_whitelist = typecacheof(list( @@ -42,7 +41,6 @@ /datum/reagent/medicine/morphine, )) // NOVA EDIT ADDITION END - /obj/machinery/medipen_refiller/Initialize(mapload) . = ..() AddComponent(/datum/component/plumbing/simple_demand) From abb6a0e15283799e47e255f6467c6f4c90644a1a Mon Sep 17 00:00:00 2001 From: Bloop <13398309+vinylspiders@users.noreply.github.com> Date: Fri, 20 Dec 2024 16:22:08 -0500 Subject: [PATCH 48/48] Update code/game/machinery/medipen_refiller.dm --- code/game/machinery/medipen_refiller.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index fcfebe4abe6..f6a528e4b63 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -41,6 +41,7 @@ /datum/reagent/medicine/morphine, )) // NOVA EDIT ADDITION END + /obj/machinery/medipen_refiller/Initialize(mapload) . = ..() AddComponent(/datum/component/plumbing/simple_demand)