From 7bf4c2a34f640f9e0acffa734445d33a13eae8a5 Mon Sep 17 00:00:00 2001 From: Zandario Date: Sun, 20 Nov 2022 18:36:24 -0600 Subject: [PATCH] Early Assets, Lateloaded Assets, and Debugging Tools (#4696) ## About The Pull Request Various asset systems I want in before more TGUI work. and also byond-tracy support... and also light update debugging... ## Changelog :cl: tweak: Chem Master UI has been reworked slightly. --- .gitignore | 50 +- citadel.dme | 44 +- code/__DEFINES/assets/medical.dm | 14 + code/__DEFINES/chemistry.dm | 47 +- code/__DEFINES/color/lights.dm | 37 + code/__DEFINES/controllers/_subsystems.dm | 5 +- .../signals/signals_atom/signals_atom_main.dm | 4 +- code/__DEFINES/inventory/icons.dm | 2 + code/__DEFINES/is_helpers.dm | 4 +- code/__DEFINES/lighting.dm | 59 - code/__DEFINES/mobs.dm | 11 + code/__DEFINES/mobs/mobility.dm | 41 +- code/___compile_options.dm | 94 +- code/controllers/subsystem/asset_loading.dm | 30 + code/controllers/subsystem/assets.dm | 4 +- code/controllers/subsystem/early_assets.dm | 26 + code/controllers/subsystem/lighting.dm | 9 +- .../subsystem/processing/chemistry.dm | 16 +- code/datums/elements/update_icon_blocker.dm | 18 + code/game/atoms/atoms.dm | 7 +- code/game/dna/dna2_helpers.dm | 6 + code/game/dna/dna_modifier.dm | 2 +- code/game/machinery/Sleeper.dm | 4 +- code/game/machinery/_machinery.dm | 44 +- code/game/machinery/adv_med.dm | 4 +- code/game/machinery/cryo.dm | 4 +- code/game/machinery/cryopod.dm | 6 +- code/game/machinery/iv_drip.dm | 403 ++++-- .../machinery/virtual_reality/ar_console.dm | 2 +- .../machinery/virtual_reality/vr_console.dm | 2 +- code/game/machinery/vr_console.dm | 2 +- code/game/mecha/equipment/tools/sleeper.dm | 2 +- .../game/mecha/equipment/tools/syringe_gun.dm | 2 +- code/game/objects/effects/chem/water.dm | 3 +- .../objects/effects/debris/cleanable/misc.dm | 2 +- code/game/objects/items/bodybag.dm | 8 +- .../game/objects/items/circuitboards/other.dm | 1 + code/game/objects/items/devices/defib.dm | 4 +- code/game/objects/items/robobag.dm | 4 +- code/game/objects/items/storage/_storage.dm | 2 +- code/game/objects/items/storage/firstaid.dm | 4 +- code/game/objects/items/toys.dm | 2 +- code/game/objects/objs.dm | 3 + code/game/objects/random/misc.dm | 2 +- .../objects/random/unidentified/medicine.dm | 2 +- .../objects/structures/ghost_pods/human.dm | 4 +- .../structures/stool_bed_chair_nest/bed.dm | 6 +- code/game/world.dm | 19 + code/modules/asset_cache/asset_list.dm | 136 +- .../asset_cache/assets/chemistry/bottles.dm | 8 + .../asset_cache/assets/chemistry/patches.dm | 8 + .../asset_cache/assets/chemistry/pills.dm | 26 + code/modules/asset_cache/assets/condiments.dm | 32 +- code/modules/asset_cache/assets/patches.dm | 8 - code/modules/asset_cache/assets/pills.dm | 40 - .../machinery/components/unary/cold_sink.dm | 2 +- .../machinery/components/unary/heat_source.dm | 2 +- .../modules/food/food/drinks/drinkingglass.dm | 4 +- code/modules/food/glass/bottle.dm | 36 +- code/modules/food/glass/bottle/robot.dm | 5 +- code/modules/food/glass/bottle_vr.dm | 40 +- .../hydroponics/trays/tray_reagents.dm | 10 +- code/modules/lighting/lighting_corner.dm | 41 +- code/modules/lighting/lighting_object.dm | 36 +- code/modules/mob/_modifiers/traits_phobias.dm | 3 +- code/modules/mob/dead/observer/observer.dm | 3 + code/modules/mob/inventory/slot_meta.dm | 2 + .../mob/living/carbon/metroid/items.dm | 8 +- code/modules/mob/living/living.dm | 12 + code/modules/mob/living/silicon/ai/ai.dm | 6 + code/modules/mob/living/silicon/pai/pai.dm | 5 + .../modules/mob/living/silicon/robot/robot.dm | 6 + code/modules/mob/mob.dm | 13 + .../_readme.dm} | 0 .../chemical_reactions.dm} | 14 +- .../colors.dm} | 22 + .../helpers.dm} | 0 .../holder.dm} | 32 +- .../logging.dm} | 0 .../machinery.dm} | 2 +- .../metabolism.dm} | 0 .../reagents.dm} | 7 + .../reagents}/Chemistry-Reagents-Core.dm | 0 .../reagents}/Chemistry-Reagents-Dispenser.dm | 0 .../Chemistry-Reagents-Food-Drinks.dm | 0 .../reagents}/Chemistry-Reagents-Medicine.dm | 0 .../reagents}/Chemistry-Reagents-Modifiers.dm | 0 .../reagents}/Chemistry-Reagents-Other.dm | 0 .../reagents}/Chemistry-Reagents-Toxins.dm | 0 .../reagents}/Chemistry-Topical.dm | 26 +- code/modules/reagents/exposedprocs.dm | 4 +- .../modules/reagents/machinery/chem_master.dm | 1177 ++++++++++------- .../machinery/dispenser/dispenser2.dm | 2 +- code/modules/reagents/reagent_containers.dm | 2 +- .../reagents/reagent_containers/borghydro.dm | 2 +- .../reagents/reagent_containers/dropper.dm | 2 +- .../reagents/reagent_containers/glass.dm | 35 +- .../reagent_containers/glass/bottle_vr.dm | 4 +- .../reagents/reagent_containers/hypospray.dm | 2 +- .../reagents/reagent_containers/organic.dm | 2 +- .../reagents/reagent_containers/patch.dm | 70 +- .../reagents/reagent_containers/pill.dm | 14 +- .../reagents/reagent_containers/spray.dm | 2 +- .../reagents/reagent_containers/syringes.dm | 2 +- .../reagent_containers/syringes_vr.dm | 2 - code/modules/species/species.dm | 1 + .../xenoarcheaology/artifacts/autocloner.dm | 2 +- code/modules/xenobio/items/extracts.dm | 4 +- code/modules/xenobio/items/slimepotions.dm | 2 +- .../xenobio2/machinery/gene_manipulators.dm | 2 +- icons/mob/items/lefthand_kitchen.dmi | Bin 0 -> 2289 bytes icons/mob/items/righthand_kitchen.dmi | Bin 0 -> 2578 bytes icons/obj/chempuff.dmi | Bin 7671 -> 0 bytes icons/obj/cryogenics.dmi | Bin 30471 -> 0 bytes icons/obj/iv_drip.dmi | Bin 1281 -> 0 bytes icons/obj/medical/bloodpack.dmi | Bin 0 -> 1262 bytes icons/obj/{ => medical}/bodybag.dmi | Bin icons/obj/medical/chemical.dmi | Bin 0 -> 61399 bytes icons/obj/medical/chemical_tanks.dmi | Bin 0 -> 10619 bytes icons/obj/medical/chempuff.dmi | Bin 0 -> 6891 bytes icons/obj/{ => medical}/cryobag.dmi | Bin .../cryogenic2.dmi} | Bin icons/obj/medical/cryogenics.dmi | Bin 0 -> 42913 bytes icons/obj/{ => medical}/cryogenics_split.dmi | Bin icons/obj/{ => medical}/defibrillator.dmi | Bin icons/obj/medical/iv_drip.dmi | Bin 0 -> 2903 bytes icons/obj/{chemical.dmi => medical/og.dmi} | Bin icons/obj/{ => medical}/reagentfillings.dmi | Bin icons/obj/{ => medical}/robobag.dmi | Bin icons/obj/{ => medical}/rollerbed.dmi | Bin icons/obj/medical/stack_medical .dmi | Bin 0 -> 7999 bytes icons/obj/medical/surgery_table.dmi | Bin 0 -> 566 bytes icons/obj/medical/surgery_tools.dmi | Bin 0 -> 8159 bytes icons/obj/medical/syringe.dmi | Bin 0 -> 13293 bytes icons/obj/{ => medical}/syringefilling.dmi | Bin icons/obj/syringe.dmi | Bin 13311 -> 0 bytes icons/obj/syringe_vr.dmi | Bin 1555 -> 0 bytes .../assets}/condiments/bbqsauce.png | Bin .../assets}/condiments/coldsauce.png | Bin .../assets}/condiments/condi_empty.png | Bin .../assets}/condiments/emptycondiment.png | Bin .../assets}/condiments/enzyme.png | Bin .../assets}/condiments/flour.png | Bin .../assets}/condiments/hotsauce.png | Bin .../assets}/condiments/ketchup.png | Bin .../assets}/condiments/mayonnaise.png | Bin .../assets}/condiments/milk.png | Bin .../assets}/condiments/oliveoil.png | Bin .../assets}/condiments/peppermillsmall.png | Bin .../assets}/condiments/rice.png | Bin .../assets}/condiments/saltshakersmall.png | Bin .../assets}/condiments/soymilk.png | Bin .../assets}/condiments/soysauce.png | Bin .../assets}/condiments/sugar.png | Bin .../assets/medical/bottles/bottle1.png | Bin 0 -> 190 bytes .../assets/medical/bottles/bottle2.png | Bin 0 -> 227 bytes .../assets/medical/bottles/bottle3.png | Bin 0 -> 184 bytes .../assets/medical/bottles/bottle4.png | Bin 0 -> 233 bytes .../assets/medical/patches/patch.png} | Bin .../assets/medical/patches/patch_both.png} | Bin .../assets/medical/patches/patch_brute.png} | Bin .../assets/medical/patches/patch_burn.png} | Bin .../assets/medical}/pills/pill1.png | Bin .../assets/medical}/pills/pill10.png | Bin .../assets/medical}/pills/pill11.png | Bin .../assets/medical}/pills/pill12.png | Bin .../assets/medical}/pills/pill13.png | Bin .../assets/medical}/pills/pill14.png | Bin .../assets/medical}/pills/pill15.png | Bin .../assets/medical}/pills/pill16.png | Bin .../assets/medical}/pills/pill17.png | Bin .../assets/medical}/pills/pill18.png | Bin .../assets/medical}/pills/pill19.png | Bin .../assets/medical}/pills/pill2.png | Bin .../assets/medical}/pills/pill20.png | Bin .../assets/medical}/pills/pill21.png | Bin .../assets/medical}/pills/pill22.png | Bin .../assets/medical}/pills/pill3.png | Bin .../assets/medical}/pills/pill4.png | Bin .../assets/medical}/pills/pill5.png | Bin .../assets/medical}/pills/pill6.png | Bin .../assets/medical}/pills/pill7.png | Bin .../assets/medical}/pills/pill8.png | Bin .../assets/medical}/pills/pill9.png | Bin icons/runtime/placeholder | 1 - tgui/docs/component-reference.md | 26 +- .../tgui/components/{Modal.js => Modal.tsx} | 14 +- tgui/packages/tgui/interfaces/ChemMaster.js | 487 ------- tgui/packages/tgui/interfaces/ChemMaster.tsx | 522 ++++++++ tgui/packages/tgui/interfaces/ChemPress.js | 19 +- .../{ComplexModal.js => ComplexModal.tsx} | 30 +- 191 files changed, 2507 insertions(+), 1591 deletions(-) create mode 100644 code/__DEFINES/assets/medical.dm create mode 100644 code/__DEFINES/color/lights.dm create mode 100644 code/controllers/subsystem/asset_loading.dm create mode 100644 code/controllers/subsystem/early_assets.dm create mode 100644 code/datums/elements/update_icon_blocker.dm create mode 100644 code/modules/asset_cache/assets/chemistry/bottles.dm create mode 100644 code/modules/asset_cache/assets/chemistry/patches.dm create mode 100644 code/modules/asset_cache/assets/chemistry/pills.dm delete mode 100644 code/modules/asset_cache/assets/patches.dm delete mode 100644 code/modules/asset_cache/assets/pills.dm rename code/modules/reagents/{Chemistry-Readme.dm => chemistry/_readme.dm} (100%) rename code/modules/reagents/{Chemistry-Recipes.dm => chemistry/chemical_reactions.dm} (95%) rename code/modules/reagents/{Chemistry-Colours.dm => chemistry/colors.dm} (66%) rename code/modules/reagents/{Chemistry-Reagents-Helpers.dm => chemistry/helpers.dm} (100%) rename code/modules/reagents/{Chemistry-Holder.dm => chemistry/holder.dm} (93%) rename code/modules/reagents/{Chemistry-Logging.dm => chemistry/logging.dm} (100%) rename code/modules/reagents/{Chemistry-Machinery.dm => chemistry/machinery.dm} (99%) rename code/modules/reagents/{Chemistry-Metabolism.dm => chemistry/metabolism.dm} (100%) rename code/modules/reagents/{Chemistry-Reagents.dm => chemistry/reagents.dm} (97%) rename code/modules/reagents/{Chemistry-Reagents => chemistry/reagents}/Chemistry-Reagents-Core.dm (100%) rename code/modules/reagents/{Chemistry-Reagents => chemistry/reagents}/Chemistry-Reagents-Dispenser.dm (100%) rename code/modules/reagents/{Chemistry-Reagents => chemistry/reagents}/Chemistry-Reagents-Food-Drinks.dm (100%) rename code/modules/reagents/{Chemistry-Reagents => chemistry/reagents}/Chemistry-Reagents-Medicine.dm (100%) rename code/modules/reagents/{Chemistry-Reagents => chemistry/reagents}/Chemistry-Reagents-Modifiers.dm (100%) rename code/modules/reagents/{Chemistry-Reagents => chemistry/reagents}/Chemistry-Reagents-Other.dm (100%) rename code/modules/reagents/{Chemistry-Reagents => chemistry/reagents}/Chemistry-Reagents-Toxins.dm (100%) rename code/modules/reagents/{Chemistry-Reagents => chemistry/reagents}/Chemistry-Topical.dm (96%) create mode 100644 icons/mob/items/lefthand_kitchen.dmi create mode 100644 icons/mob/items/righthand_kitchen.dmi delete mode 100644 icons/obj/chempuff.dmi delete mode 100644 icons/obj/cryogenics.dmi delete mode 100644 icons/obj/iv_drip.dmi create mode 100644 icons/obj/medical/bloodpack.dmi rename icons/obj/{ => medical}/bodybag.dmi (100%) create mode 100644 icons/obj/medical/chemical.dmi create mode 100644 icons/obj/medical/chemical_tanks.dmi create mode 100644 icons/obj/medical/chempuff.dmi rename icons/obj/{ => medical}/cryobag.dmi (100%) rename icons/obj/{Cryogenic2.dmi => medical/cryogenic2.dmi} (100%) create mode 100644 icons/obj/medical/cryogenics.dmi rename icons/obj/{ => medical}/cryogenics_split.dmi (100%) rename icons/obj/{ => medical}/defibrillator.dmi (100%) create mode 100644 icons/obj/medical/iv_drip.dmi rename icons/obj/{chemical.dmi => medical/og.dmi} (100%) rename icons/obj/{ => medical}/reagentfillings.dmi (100%) rename icons/obj/{ => medical}/robobag.dmi (100%) rename icons/obj/{ => medical}/rollerbed.dmi (100%) create mode 100644 icons/obj/medical/stack_medical .dmi create mode 100644 icons/obj/medical/surgery_table.dmi create mode 100644 icons/obj/medical/surgery_tools.dmi create mode 100644 icons/obj/medical/syringe.dmi rename icons/obj/{ => medical}/syringefilling.dmi (100%) delete mode 100644 icons/obj/syringe.dmi delete mode 100644 icons/obj/syringe_vr.dmi rename icons/{UI_Icons => runtime/assets}/condiments/bbqsauce.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/coldsauce.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/condi_empty.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/emptycondiment.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/enzyme.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/flour.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/hotsauce.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/ketchup.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/mayonnaise.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/milk.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/oliveoil.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/peppermillsmall.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/rice.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/saltshakersmall.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/soymilk.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/soysauce.png (100%) rename icons/{UI_Icons => runtime/assets}/condiments/sugar.png (100%) create mode 100644 icons/runtime/assets/medical/bottles/bottle1.png create mode 100644 icons/runtime/assets/medical/bottles/bottle2.png create mode 100644 icons/runtime/assets/medical/bottles/bottle3.png create mode 100644 icons/runtime/assets/medical/bottles/bottle4.png rename icons/{UI_Icons/patches/bandaid.png => runtime/assets/medical/patches/patch.png} (100%) rename icons/{UI_Icons/patches/bandaid_both.png => runtime/assets/medical/patches/patch_both.png} (100%) rename icons/{UI_Icons/patches/bandaid_brute.png => runtime/assets/medical/patches/patch_brute.png} (100%) rename icons/{UI_Icons/patches/bandaid_burn.png => runtime/assets/medical/patches/patch_burn.png} (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill1.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill10.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill11.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill12.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill13.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill14.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill15.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill16.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill17.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill18.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill19.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill2.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill20.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill21.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill22.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill3.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill4.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill5.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill6.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill7.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill8.png (100%) rename icons/{UI_Icons => runtime/assets/medical}/pills/pill9.png (100%) delete mode 100644 icons/runtime/placeholder rename tgui/packages/tgui/components/{Modal.js => Modal.tsx} (60%) delete mode 100644 tgui/packages/tgui/interfaces/ChemMaster.js create mode 100644 tgui/packages/tgui/interfaces/ChemMaster.tsx rename tgui/packages/tgui/interfaces/common/{ComplexModal.js => ComplexModal.tsx} (85%) diff --git a/.gitignore b/.gitignore index 47ee524374b..5d93bb91162 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,27 @@ -###Files and folders specified here will never be tracked. +### Files and folders specified here will never be tracked. -#Ignore everything in datafolder and subdirectories +# Ignore everything in datafolder and subdirectories /data/**/* /tmp/**/* -#Ignore byond config folder. +# Ignore byond config folder. /cfg/**/* +# Ignore IDE files we don't need in the repo. +/.vs/**/* +/tgstation/FileContentIndex/**/* +/FileContentIndex/**/* +/v17/**/* +/v18/**/* +/v19/**/* +/v20/**/* +/v21/**/* +/v22/**/* + # Ignore compiled linux libs in the root folder, e.g. librust_g.so /*.so -#Ignore compiled files and other files generated during compilation. +# Ignore compiled files and other files generated during compilation. *.mdme *.mdme.* *.dmb @@ -24,7 +35,7 @@ *~ -# temporary files which can be created if a process still has a handle open of a deleted file +# Temporary files which can be created if a process still has a handle open of a deleted file .fuse_hidden* # KDE directory preferences @@ -155,29 +166,32 @@ Temporary Items *.before -#Sublime +# Sublime *.sublime-project *.sublime-workspace -#Visual studio stuff +# Visual studio stuff *.vscode/* /tools/MapAtmosFixer/MapAtmosFixer/obj/* /tools/MapAtmosFixer/MapAtmosFixer/bin/* /tools/CreditsTool/bin/* /tools/CreditsTool/obj/* -#GitHub Atom +# GitHub Atom .atom-build.json -#KDevelop and Kate +# KDevelop and Kate *.kdev4* *.kate-swp -#extra map stuff +# Extra map stuff /_maps/**/backup/ /_maps/templates.dm /maps/**/backup/ +# Extra DMI stuff +/icons/*.dme + #dmdoc default folder /dmdoc @@ -198,5 +212,17 @@ Temporary Items /tools/LinuxOneShot/TGS_Instances /tools/LinuxOneShot/TGS_Logs -# Autowiki -/tools/autowiki/node_modules +# Built auxtools libraries and intermediate files +aux*.dll +libaux*.so +aux*.pdb + +# byond-tracy, we intentionally do not ship this and do not want to maintain it +prof.dll +libprof.so + +# JavaScript tools +**/node_modules + +# Screenshot tests +/artifacts diff --git a/citadel.dme b/citadel.dme index 79af566be9b..07b3d8551e2 100644 --- a/citadel.dme +++ b/citadel.dme @@ -112,6 +112,7 @@ #include "code\__DEFINES\_flags\obj_flags.dm" #include "code\__DEFINES\_flags\turf_flags.dm" #include "code\__DEFINES\admin\keybindings.dm" +#include "code\__DEFINES\assets\medical.dm" #include "code\__DEFINES\atmospherics\atmos.dm" #include "code\__DEFINES\atmospherics\atmospheres.dm" #include "code\__DEFINES\atmospherics\constants.dm" @@ -124,6 +125,7 @@ #include "code\__DEFINES\client\player_flags.dm" #include "code\__DEFINES\color\color.dm" #include "code\__DEFINES\color\colour_priority.dm" +#include "code\__DEFINES\color\lights.dm" #include "code\__DEFINES\color\lum.dm" #include "code\__DEFINES\combat\atom_damage.dm" #include "code\__DEFINES\combat\explosions.dm" @@ -412,12 +414,14 @@ #include "code\controllers\subsystem\air.dm" #include "code\controllers\subsystem\airflow.dm" #include "code\controllers\subsystem\alarm.dm" +#include "code\controllers\subsystem\asset_loading.dm" #include "code\controllers\subsystem\assets.dm" #include "code\controllers\subsystem\atoms.dm" #include "code\controllers\subsystem\automata.dm" #include "code\controllers\subsystem\bellies_vr.dm" #include "code\controllers\subsystem\chat.dm" #include "code\controllers\subsystem\dcs.dm" +#include "code\controllers\subsystem\early_assets.dm" #include "code\controllers\subsystem\emergency_shuttle.dm" #include "code\controllers\subsystem\events.dm" #include "code\controllers\subsystem\fail2topic.dm" @@ -1842,6 +1846,7 @@ #include "code\modules\asset_cache\assets\arcade.dm" #include "code\modules\asset_cache\assets\chat.dm" #include "code\modules\asset_cache\assets\common.dm" +#include "code\modules\asset_cache\assets\condiments.dm" #include "code\modules\asset_cache\assets\fontawesome.dm" #include "code\modules\asset_cache\assets\genetics.dm" #include "code\modules\asset_cache\assets\inventory.dm" @@ -1853,10 +1858,8 @@ #include "code\modules\asset_cache\assets\notes.dm" #include "code\modules\asset_cache\assets\orbit.dm" #include "code\modules\asset_cache\assets\paper.dm" -#include "code\modules\asset_cache\assets\patches.dm" #include "code\modules\asset_cache\assets\pda.dm" #include "code\modules\asset_cache\assets\permission.dm" -#include "code\modules\asset_cache\assets\pills.dm" #include "code\modules\asset_cache\assets\pipes.dm" #include "code\modules\asset_cache\assets\radar.dm" #include "code\modules\asset_cache\assets\safe.dm" @@ -1864,6 +1867,9 @@ #include "code\modules\asset_cache\assets\tgfont.dm" #include "code\modules\asset_cache\assets\tgui.dm" #include "code\modules\asset_cache\assets\vv.dm" +#include "code\modules\asset_cache\assets\chemistry\bottles.dm" +#include "code\modules\asset_cache\assets\chemistry\patches.dm" +#include "code\modules\asset_cache\assets\chemistry\pills.dm" #include "code\modules\asset_cache\transports\asset_transport.dm" #include "code\modules\asset_cache\transports\webroot_transport.dm" #include "code\modules\atmospherics\atmosphere\_atmosphere.dm" @@ -3665,29 +3671,29 @@ #include "code\modules\random_map\noise\noise.dm" #include "code\modules\random_map\noise\ore.dm" #include "code\modules\random_map\noise\tundra.dm" -#include "code\modules\reagents\Chemistry-Colours.dm" -#include "code\modules\reagents\Chemistry-Holder.dm" -#include "code\modules\reagents\Chemistry-Logging.dm" -#include "code\modules\reagents\Chemistry-Machinery.dm" -#include "code\modules\reagents\Chemistry-Metabolism.dm" -#include "code\modules\reagents\Chemistry-Readme.dm" -#include "code\modules\reagents\Chemistry-Reagents-Helpers.dm" -#include "code\modules\reagents\Chemistry-Reagents.dm" -#include "code\modules\reagents\Chemistry-Recipes.dm" #include "code\modules\reagents\Drink-Recipes.dm" #include "code\modules\reagents\exposedprocs.dm" #include "code\modules\reagents\Food-Recipes.dm" #include "code\modules\reagents\Misc-Recipes.dm" #include "code\modules\reagents\reagent_containers.dm" #include "code\modules\reagents\Topical-Recipes.dm" -#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Core.dm" -#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Dispenser.dm" -#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Food-Drinks.dm" -#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Medicine.dm" -#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Modifiers.dm" -#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Other.dm" -#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Toxins.dm" -#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Topical.dm" +#include "code\modules\reagents\chemistry\_readme.dm" +#include "code\modules\reagents\chemistry\chemical_reactions.dm" +#include "code\modules\reagents\chemistry\colors.dm" +#include "code\modules\reagents\chemistry\helpers.dm" +#include "code\modules\reagents\chemistry\holder.dm" +#include "code\modules\reagents\chemistry\logging.dm" +#include "code\modules\reagents\chemistry\machinery.dm" +#include "code\modules\reagents\chemistry\metabolism.dm" +#include "code\modules\reagents\chemistry\reagents.dm" +#include "code\modules\reagents\chemistry\reagents\Chemistry-Reagents-Core.dm" +#include "code\modules\reagents\chemistry\reagents\Chemistry-Reagents-Dispenser.dm" +#include "code\modules\reagents\chemistry\reagents\Chemistry-Reagents-Food-Drinks.dm" +#include "code\modules\reagents\chemistry\reagents\Chemistry-Reagents-Medicine.dm" +#include "code\modules\reagents\chemistry\reagents\Chemistry-Reagents-Modifiers.dm" +#include "code\modules\reagents\chemistry\reagents\Chemistry-Reagents-Other.dm" +#include "code\modules\reagents\chemistry\reagents\Chemistry-Reagents-Toxins.dm" +#include "code\modules\reagents\chemistry\reagents\Chemistry-Topical.dm" #include "code\modules\reagents\distilling\Distilling-Recipes.dm" #include "code\modules\reagents\distilling\distilling.dm" #include "code\modules\reagents\machinery\chem_master.dm" diff --git a/code/__DEFINES/assets/medical.dm b/code/__DEFINES/assets/medical.dm new file mode 100644 index 00000000000..1e7925d6f21 --- /dev/null +++ b/code/__DEFINES/assets/medical.dm @@ -0,0 +1,14 @@ +//! Used by chem masters and pill presses +#define PILL_STYLE_COUNT 22 // Update this if you add more pill icons or you die. +#define RANDOM_PILL_STYLE 22 // Don't change this one though. + +#define PILL_STYLE_RED list("pill4", "pill5", "pill12") // Red pills have an extra spooky description. +#define PILL_STYLE_COLORABLE list("pill9", "pill18", "pill19", "pill21") // Put your pill here if it's greyscale. + +#define BOTTLE_STYLE_COUNT 4 // Update this if you add more bottle icons or you die. +#define RANDOM_BOTTLE_STYLE 4 // Don't change this one though. + +//used by chem masters and pill presses +//update this if you add more patch icons +#define PATCH_STYLE_LIST list("patch", "patch_brute", "patch_burn", "patch_both") //icon_state list +#define DEFAULT_PATCH_STYLE "patch" diff --git a/code/__DEFINES/chemistry.dm b/code/__DEFINES/chemistry.dm index a667a2931ef..147c9e3dcb7 100644 --- a/code/__DEFINES/chemistry.dm +++ b/code/__DEFINES/chemistry.dm @@ -4,9 +4,21 @@ #define DEFAULT_THIRST_FACTOR 0.03 /// Means 'Reagent Effect Multiplier'. This is how many units of reagent are consumed per tick #define REM 0.2 -#define CHEM_TOUCH 1 -#define CHEM_INGEST 2 -#define CHEM_BLOOD 3 + +//! Reagent exposure methods. +/// Used for splashing. +#define CHEM_TOUCH (1<<0) +/// Used for ingesting the reagents. Food, drinks, inhaling smoke. +#define CHEM_INGEST (1<<1) +/// Used by foams, sprays, and blob attacks. +#define CHEM_VAPOR (1<<2) +/// Used by medical patches and gels. +#define CHEM_PATCH (1<<3) +/// Used for direct injection of reagents. +#define CHEM_INJECT (1<<4) +/// Used for blood contamination. +#define CHEM_BLOOD (1<<5) + #define MINIMUM_CHEMICAL_VOLUME 0.01 @@ -67,10 +79,6 @@ var/list/bradycardics = list("neurotoxin", "cryoxadone", "clonexadone", "space_ var/list/heartstopper = list("potassium_chlorophoride", "zombie_powder") // This stops the heart. var/list/cheartstopper = list("potassium_chloride") // This stops the heart when overdose is met. -- c = conditional -///Max icon state of the pill sprites -#define MAX_PILL_SPRITE 24 -///Max icon state of the pill sprites -#define MAX_BOTTLE_SPRITE 4 ///Max number of pills/patches that can be made at once #define MAX_MULTI_AMOUNT 20 ///Max amount of units in a pill @@ -90,6 +98,7 @@ var/list/cheartstopper = list("potassium_chloride") // Thi #define SYRINGE_DRAW 0 #define SYRINGE_INJECT 1 #define SYRINGE_BROKEN 2 +#define SYRINGE_CAPPED 3 //reagents_holder_flags defines ///Makes it possible to add reagents through droppers and syringes. @@ -108,3 +117,27 @@ var/list/cheartstopper = list("potassium_chloride") // Thi #define AMOUNT_VISIBLE (1<<5) ///Applied to a reagent holder, the contents will not react with each other. #define NO_REACT (1<<6) + +//! Used by chem master +#define CONDIMASTER_STYLE_AUTO "auto" +#define CONDIMASTER_STYLE_FALLBACK "_" + +/// When processing a reaction, iterate this many times. +#define PROCESS_REACTION_ITER 5 + +/** + * Helper that ensures the reaction rate holds after iterating + * Ex. REACTION_RATE(0.3) means that 30% of the reagents will react each chemistry tick (~2 seconds by default). + */ +#define REACTION_RATE(rate) (1.0 - (1.0-rate)**(1.0/PROCESS_REACTION_ITER)) + +/** + * Helper to define reaction rate in terms of half-life + * + * Ex. + * HALF_LIFE(0) -> Reaction completes immediately (default chems) + * HALF_LIFE(1) -> Half of the reagents react immediately, the rest over the following ticks. + * HALF_LIFE(2) -> Half of the reagents are consumed after 2 chemistry ticks. + * HALF_LIFE(3) -> Half of the reagents are consumed after 3 chemistry ticks. + */ +#define HALF_LIFE(ticks) (ticks? 1.0 - (0.5)**(1.0/(ticks*PROCESS_REACTION_ITER)) : 1.0) diff --git a/code/__DEFINES/color/lights.dm b/code/__DEFINES/color/lights.dm new file mode 100644 index 00000000000..ad777e2f687 --- /dev/null +++ b/code/__DEFINES/color/lights.dm @@ -0,0 +1,37 @@ +//Some defines to generalise colours used in lighting. +//! ## GENERAL COLORS +//? Important note on colors. Colors can end up significantly different from the basic html picture, especially when saturated! +#define LIGHT_COLOR_WHITE "#FFFFFF" // rgb(255, 255, 255) Pure white. +#define LIGHT_COLOR_RED "#FA8282" // rgb(250, 130, 130) Warm but extremely diluted red. +#define LIGHT_COLOR_GREEN "#64C864" // rgb(100, 200, 100) Bright but quickly dissipating neon green. +#define LIGHT_COLOR_BLUE "#6496FA" // rgb(100, 150, 250) Cold, diluted blue. +#define LIGHT_COLOR_BLUEGREEN "#7DE1AF" // rgb(125, 225, 175) Light blueish green. +#define LIGHT_COLOR_PALEBLUE "#7DAFE1" // rgb(125, 175, 225) A pale blue-ish color. +#define LIGHT_COLOR_CYAN "#7DE1E1" // rgb(125, 225, 225) Diluted cyan. +#define LIGHT_COLOR_LIGHT_CYAN "#40CEFF" // rgb(64, 206, 255) More-saturated cyan. +#define LIGHT_COLOR_DARK_BLUE "#6496FA" // rgb(51, 117, 248) Saturated blue. +#define LIGHT_COLOR_PINK "#E17DE1" // rgb(225, 125, 225) Diluted, mid-warmth pink. +#define LIGHT_COLOR_YELLOW "#E1E17D" // rgb(225, 225, 125) Dimmed yellow, leaning kaki. +#define LIGHT_COLOR_BROWN "#966432" // rgb(150, 100, 50) Clear brown, mostly dim. +#define LIGHT_COLOR_ORANGE "#FA9632" // rgb(250, 150, 50) Mostly pure orange. +#define LIGHT_COLOR_PURPLE "#952CF4" // rgb(149, 44, 244) Light Purple. +#define LIGHT_COLOR_LAVENDER "#9B51FF" // rgb(155, 81, 255) Less-saturated light purple. +#define LIGHT_COLOR_HOLY_MAGIC "#FFF743" // rgb(255, 247, 67) Slightly desaturated bright yellow. +#define LIGHT_COLOR_BLOOD_MAGIC "#D00000" // rgb(208, 0, 0) Deep crimson. + +//?These ones aren't a direct colour like the ones above, because nothing would fit + +#define LIGHT_COLOR_FIRE "#FAA019" // rgb(250, 160, 25) Warm orange color, leaning strongly towards yellow. +#define LIGHT_COLOR_LAVA "#C48A18" // rgb(196, 138, 24) Very warm yellow, leaning slightly towards orange. +#define LIGHT_COLOR_FLARE "#FA644B" // rgb(250, 100, 75) Bright, non-saturated red. Leaning slightly towards pink for visibility. +#define LIGHT_COLOR_SLIME_LAMP "#AFC84B" // rgb(175, 200, 75) Weird color, between yellow and green, very slimy. +#define LIGHT_COLOR_TUNGSTEN "#FAE1AF" // rgb(250, 225, 175) Extremely diluted yellow, close to skin color (for some reason). +#define LIGHT_COLOR_HALOGEN "#F0FAFA" // rgb(240, 250, 250) Barely visible cyan-ish hue, as the doctor prescribed. + +//! ## STATION LIGHT COLORS +#define LIGHT_COLOR_FLUORESCENT_TUBE "#B3D7FF" // rgb(179, 215, 255) Bright, slightly blueish white. +#define LIGHT_COLOR_FLUORESCENT_FLASHLIGHT "#CDDDFF" // rgb(205, 221, 255) Bright, slightly blueish white. +#define LIGHT_COLOR_INCANDESCENT_TUBE "#E0EFF0" // rgb(224, 239, 240) Slightly blueish white. +#define LIGHT_COLOR_INCANDESCENT_BULB "#FFFEB8" // rgb(255, 254, 184) Slightly yellowish white. +#define LIGHT_COLOR_INCANDESCENT_FLASHLIGHT "#FFCC66" // rgb(255, 204, 102) Slightly yellowish white. +#define LIGHT_COLOR_NIGHTSHIFT "#EFCC86" // rgb(239, 204, 134) Slightly yellowish white. diff --git a/code/__DEFINES/controllers/_subsystems.dm b/code/__DEFINES/controllers/_subsystems.dm index f8574de92f8..0b14c0830c9 100644 --- a/code/__DEFINES/controllers/_subsystems.dm +++ b/code/__DEFINES/controllers/_subsystems.dm @@ -81,6 +81,7 @@ DEFINE_BITFIELD(runlevels, list( #define INIT_ORDER_SERVER_MAINT 65 #define INIT_ORDER_TIMER 60 #define INIT_ORDER_INSTRUMENTS 50 +#define INIT_ORDER_EARLY_ASSETS 48 #define INIT_ORDER_SQLITE 40 #define INIT_ORDER_CHEMISTRY 35 #define INIT_ORDER_SKYBOX 30 @@ -135,6 +136,7 @@ DEFINE_BITFIELD(runlevels, list( #define FIRE_PRIORITY_PLANETS 75 #define FIRE_PRIORITY_INSTRUMENTS 90 #define FIRE_PRIORITY_MACHINES 100 +#define FIRE_PRIORITY_ASSETS 105 #define FIRE_PRIORITY_TGUI 110 #define FIRE_PRIORITY_PROJECTILES 150 #define FIRE_PRIORITY_THROWING 150 @@ -142,8 +144,7 @@ DEFINE_BITFIELD(runlevels, list( #define FIRE_PRIORITY_OVERLAYS 500 #define FIRE_PRIORITY_SMOOTHING 500 #define FIRE_PRIORITY_TIMER 700 -///never drop input -#define FIRE_PRIORITY_INPUT 1000 +#define FIRE_PRIORITY_INPUT 1000 //! Never drop input /** Create a new timer and add it to the queue. diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm index 62b93db1624..595bb93bee2 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm @@ -35,9 +35,9 @@ /// From base of [/atom/update_icon]: () #define COMSIG_ATOM_UPDATE_ICON "atom_update_icon" ///? If returned from [COMSIG_ATOM_UPDATE_ICON] it prevents the atom from updating its icon state. - ////#define COMSIG_ATOM_NO_UPDATE_ICON_STATE UPDATE_ICON_STATE + #define COMSIG_ATOM_NO_UPDATE_ICON_STATE UPDATE_ICON_STATE ///? If returned from [COMSIG_ATOM_UPDATE_ICON] it prevents the atom from updating its overlays. - ////#define COMSIG_ATOM_NO_UPDATE_OVERLAYS UPDATE_OVERLAYS + #define COMSIG_ATOM_NO_UPDATE_OVERLAYS UPDATE_OVERLAYS /// From base of [atom/update_icon_state]: () #define COMSIG_ATOM_UPDATE_ICON_STATE "atom_update_icon_state" /// From base of [/atom/update_overlays]: (list/new_overlays) diff --git a/code/__DEFINES/inventory/icons.dm b/code/__DEFINES/inventory/icons.dm index 922793b1234..593b277fb1d 100644 --- a/code/__DEFINES/inventory/icons.dm +++ b/code/__DEFINES/inventory/icons.dm @@ -13,6 +13,8 @@ #define INHAND_DEFAULT_ICON_HATS "hats" /// holders #define INHAND_DEFAULT_ICON_HOLDERS "holders" +/// kitchen +#define INHAND_DEFAULT_ICON_KITCHEN "kitchen" /// magic #define INHAND_DEFAULT_ICON_MAGIC "magic" /// masks diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 9453063a6e3..82fb2c54612 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -41,7 +41,9 @@ #define isairlock(A) istype(A, /obj/machinery/door/airlock) -#define isbelly(A) istype(A, /obj/belly) +#define isbelly(A) istype(A, /obj/belly) + +#define is_reagent_container(O) (istype(O, /obj/item/reagent_containers)) //Areas diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm index a2759343330..c5bd4d117d1 100644 --- a/code/__DEFINES/lighting.dm +++ b/code/__DEFINES/lighting.dm @@ -29,65 +29,6 @@ 0, 0, 0, 1 \ ) \ -//Some defines to generalise colours used in lighting. -//! ## GENERAL COLORS -//? Important note on colors. Colors can end up significantly different from the basic html picture, especially when saturated! -#define LIGHT_COLOR_WHITE "#FFFFFF" -/// Warm but extremely diluted red. rgb(250, 130, 130) -#define LIGHT_COLOR_RED "#FA8282" -/// Bright but quickly dissipating neon green. rgb(100, 200, 100) -#define LIGHT_COLOR_GREEN "#64C864" -/// Cold, diluted blue. rgb(100, 150, 250) -#define LIGHT_COLOR_BLUE "#6496FA" -/// Light blueish green. rgb(125, 225, 175) -#define LIGHT_COLOR_BLUEGREEN "#7DE1AF" -/// A pale blue-ish color. rgb(125, 175, 225) -#define LIGHT_COLOR_PALEBLUE "#7DAFE1" -/// Diluted cyan. rgb(125, 225, 225) -#define LIGHT_COLOR_CYAN "#7DE1E1" -/// More-saturated cyan. rgb(64, 206, 255) -#define LIGHT_COLOR_LIGHT_CYAN "#40CEFF" -/// Saturated blue. rgb(51, 117, 248) -#define LIGHT_COLOR_DARK_BLUE "#6496FA" -/// Diluted, mid-warmth pink. rgb(225, 125, 225) -#define LIGHT_COLOR_PINK "#E17DE1" -/// Dimmed yellow, leaning kaki. rgb(225, 225, 125) -#define LIGHT_COLOR_YELLOW "#E1E17D" -/// Clear brown, mostly dim. rgb(150, 100, 50) -#define LIGHT_COLOR_BROWN "#966432" -/// Mostly pure orange. rgb(250, 150, 50) -#define LIGHT_COLOR_ORANGE "#FA9632" -/// Light Purple. rgb(149, 44, 244) -#define LIGHT_COLOR_PURPLE "#952CF4" -/// Less-saturated light purple. rgb(155, 81, 255) -#define LIGHT_COLOR_LAVENDER "#9B51FF" -/// Slightly desaturated bright yellow. -#define LIGHT_COLOR_HOLY_MAGIC "#FFF743" -/// Deep crimson. -#define LIGHT_COLOR_BLOOD_MAGIC "#D00000" - -//?These ones aren't a direct colour like the ones above, because nothing would fit -/// Warm orange color, leaning strongly towards yellow. rgb(250, 160, 25) -#define LIGHT_COLOR_FIRE "#FAA019" -/// Very warm yellow, leaning slightly towards orange. rgb(196, 138, 24) -#define LIGHT_COLOR_LAVA "#C48A18" -/// Bright, non-saturated red. Leaning slightly towards pink for visibility. rgb(250, 100, 75) -#define LIGHT_COLOR_FLARE "#FA644B" -/// Weird color, between yellow and green, very slimy. rgb(175, 200, 75) -#define LIGHT_COLOR_SLIME_LAMP "#AFC84B" -/// Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175) -#define LIGHT_COLOR_TUNGSTEN "#FAE1AF" -/// Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250) -#define LIGHT_COLOR_HALOGEN "#F0FAFA" - -//! ## STATION LIGHT COLORS -#define LIGHT_COLOR_FLUORESCENT_TUBE "#B3D7FF" -#define LIGHT_COLOR_FLUORESCENT_FLASHLIGHT "#CDDDFF" -#define LIGHT_COLOR_INCANDESCENT_TUBE "#E0EFF0" -#define LIGHT_COLOR_INCANDESCENT_BULB "#FFFEB8" -#define LIGHT_COLOR_INCANDESCENT_FLASHLIGHT "#FFCC66" -#define LIGHT_COLOR_NIGHTSHIFT "#EFCC86" - /// How many tiles standard fires glow. #define LIGHT_RANGE_FIRE 3 diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 39c3fa18695..54563f376dd 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -369,3 +369,14 @@ #define EXAMINE_MORE_TIME 1 SECONDS #define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return; + +//! Blood levels +#define BLOOD_VOLUME_MAX_LETHAL 2150 +#define BLOOD_VOLUME_EXCESS 2100 +#define BLOOD_VOLUME_MAXIMUM 2000 +#define BLOOD_VOLUME_SLIME_SPLIT 1120 +#define BLOOD_VOLUME_NORMAL 560 +#define BLOOD_VOLUME_SAFE 475 +#define BLOOD_VOLUME_OKAY 336 +#define BLOOD_VOLUME_BAD 224 +#define BLOOD_VOLUME_SURVIVE 122 diff --git a/code/__DEFINES/mobs/mobility.dm b/code/__DEFINES/mobs/mobility.dm index 0265b9a5532..d0a45837b5a 100644 --- a/code/__DEFINES/mobs/mobility.dm +++ b/code/__DEFINES/mobs/mobility.dm @@ -1,26 +1,29 @@ -//Mob mobility var flags +//! Mob mobility var flags /// any flag #define CHECK_MOBILITY(target, flags) (target.mobility_flags & flags) #define CHECK_ALL_MOBILITY(target, flags) CHECK_MULTIPLE_BITFIELDS(target.mobility_flags, flags) -/// can move -#define MOBILITY_MOVE (1<<0) -/// can, and is, standing up. -#define MOBILITY_STAND (1<<1) -/// can pickup items -#define MOBILITY_PICKUP (1<<2) -/// can use items and interact with world objects like opening closets/etc -#define MOBILITY_USE (1<<3) -/// can use interfaces like consoles -#define MOBILITY_UI (1<<4) -/// can use storage item -#define MOBILITY_STORAGE (1<<5) -/// can pull things -#define MOBILITY_PULL (1<<6) -/// can hold non-nodropped items voluntarily -#define MOBILITY_HOLD (1<<7) -/// Can resist out of buckling, grabs, cuffs, etc, in the usual order (buckle --> cuffs --> grab) -#define MOBILITY_RESIST (1<<8) +#define MOBILITY_MOVE (1<<0) // Can move. +#define MOBILITY_STAND (1<<1) // Can, and is, standing up. +#define MOBILITY_PICKUP (1<<2) // Can pickup items. +#define MOBILITY_USE (1<<3) // Can use items and interact with world objects like opening closets/etc. +#define MOBILITY_UI (1<<4) // Can use interfaces like consoles. +#define MOBILITY_STORAGE (1<<5) // Can use storage item. +#define MOBILITY_PULL (1<<6) // Can pull things. +#define MOBILITY_HOLD (1<<7) // Can hold non-nodropped items voluntarily. +#define MOBILITY_RESIST (1<<8) // Can resist out of buckling, grabs, cuffs, etc, in the usual order (buckle --> cuffs --> grab) #define MOBILITY_FLAGS_DEFAULT (MOBILITY_MOVE | MOBILITY_STAND | MOBILITY_PICKUP | MOBILITY_USE | MOBILITY_UI | MOBILITY_STORAGE | MOBILITY_PULL | MOBILITY_RESIST) #define MOBILITY_FLAGS_ANY_INTERACTION (MOBILITY_USE | MOBILITY_PICKUP | MOBILITY_UI | MOBILITY_STORAGE) + +DEFINE_BITFIELD(mobility_flags, list( + "MOVE" = MOBILITY_MOVE, + "STAND" = MOBILITY_STAND, + "PICKUP" = MOBILITY_PICKUP, + "USE" = MOBILITY_USE, + "UI" = MOBILITY_UI, + "STORAGE" = MOBILITY_STORAGE, + "PULL" = MOBILITY_PULL, + "HOLD" = MOBILITY_HOLD, + "RESIST" = MOBILITY_RESIST, +)) diff --git a/code/___compile_options.dm b/code/___compile_options.dm index 4349437410b..fc83239269d 100644 --- a/code/___compile_options.dm +++ b/code/___compile_options.dm @@ -1,45 +1,103 @@ //* Core settings //! Fastboot flags - useful for debugging -/// disable automatic roundstart icon smoothing +/// Disable automatic roundstart icon smoothing. // #define FASTBOOT_DISABLE_SMOOTHING (1<<0) -/// disable loading late maps +/// Disable loading late maps. // #define FASTBOOT_DISABLE_LATELOAD (1<<1) -/// disable atmospherics zone build +/// Disable atmospherics zone build. // #define FASTBOOT_DISABLE_ZONES (1<<2) -///By using the testing("message") proc you can create debug-feedback for people with this -//#define TESTING - //uncommented, but not visible in the release version) +/** + * By using the testing("message") proc you can create debug-feedback for people with this uncommented, + * but not visible in the release version + */ +// #define TESTING -///Enables the ability to cache datum vars and retrieve later for debugging which vars changed. -//#define DATUMVAR_DEBUGGING_MODE -// Comment this out if you are debugging problems that might be obscured by custom error handling in world/Error +/// Enables the ability to cache datum vars and retrieve later for debugging which vars changed. +// #define DATUMVAR_DEBUGGING_MODE + +/// Comment this out if you are debugging problems that might be obscured by custom error handling in world/Error #ifdef DEBUG - #define USE_CUSTOM_ERROR_HANDLER +#define USE_CUSTOM_ERROR_HANDLER +#define DEBUG_SHUTTLES #endif -#define DEBUG_SHUTTLES #ifdef TESTING #define DATUMVAR_DEBUGGING_MODE -///Used to find the sources of harddels, quite laggy, don't be surpised if it freezes your client for a good while +/// Used to find the sources of harddels, quite laggy, don't be surpised if it freezes your client for a good while +// #define REFERENCE_TRACKING #ifdef REFERENCE_TRACKING -///Run a lookup on things hard deleting by default. -//#define GC_FAILURE_HARD_LOOKUP +/// Used for doing dry runs of the reference finder, to test for feature completeness +/// Slightly slower, higher in memory. Just not optimal +// #define REFERENCE_TRACKING_DEBUG + +/// Run a lookup on things hard deleting by default. +// #define GC_FAILURE_HARD_LOOKUP #ifdef GC_FAILURE_HARD_LOOKUP +/// Don't stop when searching, go till you're totally done #define FIND_REF_NO_CHECK_TICK #endif //ifdef GC_FAILURE_HARD_LOOKUP #endif //ifdef REFERENCE_TRACKING -///Highlights atmos active turfs in green -//#define VISUALIZE_ACTIVE_TURFS +/** + * Enables debug messages for every single reaction step. + * This is 1 message per 0.5s for a SINGLE reaction. + * Useful for tracking down bugs/asking me for help in the main reaction handiler (equilibrium.dm). + * + * * Requires TESTING to be defined to work. + * ! Not implemented yet. + */ +// #define REAGENTS_TESTING + +/** + * Displays static object lighting updates. + * + * Also enables some debug vars on sslighting that can be used to modify + * how extensively we prune lighting corners to update. + */ +#define VISUALIZE_LIGHT_UPDATES + +/// Highlights atmos active turfs in green. +#define VISUALIZE_ACTIVE_TURFS #endif //ifdef TESTING -///Enables unit tests via TEST_RUN_PARAMETER -//#define UNIT_TESTS +/// If this is uncommented, we do a single run though of the game setup and tear down process with unit tests in between +// #define UNIT_TESTS + +/** + * If this is uncommented, will attempt to load and initialize prof.dll/libprof.so. + * We do not ship byond-tracy. Build it yourself here: https://github.com/mafemergency/byond-tracy/ + */ +// #define USE_BYOND_TRACY + +/// If defined, we will NOT defer asset generation till later in the game, and will instead do it all at once, during initiialize. +//#define DO_NOT_DEFER_ASSETS + +/// If this is uncommented, Autowiki will generate edits and shut down the server. +/// Prefer the autowiki build target instead. +// #define AUTOWIKI + +/// If this is uncommented, will profile mapload atom initializations +// #define PROFILE_MAPLOAD_INIT_ATOM + +/// If this is uncommented, force our verb processing into just the 2% of a tick +/// We normally reserve for it +/// NEVER run this on live, it's for simulating highpop only +// #define VERB_STRESS_TEST + +#ifdef VERB_STRESS_TEST +/// Uncomment this to force all verbs to run into overtime all of the time +/// Essentially negating the reserve 2% + +// #define FORCE_VERB_OVERTIME +#warn Hey brother, you're running in LAG MODE. +#warn IF YOU PUT THIS ON LIVE I WILL FIND YOU AND MAKE YOU WISH YOU WERE NEVE- +#endif + #ifndef PRELOAD_RSC //set to: /// 0 to allow using external resources or on-demand behaviour; #define PRELOAD_RSC 2 diff --git a/code/controllers/subsystem/asset_loading.dm b/code/controllers/subsystem/asset_loading.dm new file mode 100644 index 00000000000..5010d7e13af --- /dev/null +++ b/code/controllers/subsystem/asset_loading.dm @@ -0,0 +1,30 @@ +/** + * Allows us to lazyload asset datums. + * Anything inserted here will fully load if directly gotten. + * So this just serves to remove the requirement to load assets fully during init. + */ +SUBSYSTEM_DEF(asset_loading) + name = "Asset Loading" + priority = FIRE_PRIORITY_ASSETS + subsystem_flags = SS_NO_INIT + runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT + var/list/datum/asset/generate_queue = list() + +/datum/controller/subsystem/asset_loading/fire(resumed) + while(length(generate_queue)) + var/datum/asset/to_load = generate_queue[generate_queue.len] + + to_load.queued_generation() + + if(MC_TICK_CHECK) + return + generate_queue.len-- + +/datum/controller/subsystem/asset_loading/proc/queue_asset(datum/asset/queue) +#ifdef DO_NOT_DEFER_ASSETS + stack_trace("We queued an instance of [queue.type] for lateloading despite not allowing it") +#endif + generate_queue += queue + +/datum/controller/subsystem/asset_loading/proc/dequeue_asset(datum/asset/queue) + generate_queue -= queue diff --git a/code/controllers/subsystem/assets.dm b/code/controllers/subsystem/assets.dm index fe2abb4879f..cf8c2780a98 100644 --- a/code/controllers/subsystem/assets.dm +++ b/code/controllers/subsystem/assets.dm @@ -26,11 +26,11 @@ SUBSYSTEM_DEF(assets) for(var/type in typesof(/datum/asset)) var/datum/asset/A = type if (type != initial(A._abstract)) - get_asset_datum(type) + load_asset_datum(type) transport.Initialize(cache) - ..() + return ..() /datum/controller/subsystem/assets/Recover() cache = SSassets.cache diff --git a/code/controllers/subsystem/early_assets.dm b/code/controllers/subsystem/early_assets.dm new file mode 100644 index 00000000000..f77c6875186 --- /dev/null +++ b/code/controllers/subsystem/early_assets.dm @@ -0,0 +1,26 @@ +/** + * Initializes any assets that need to be loaded ASAP. + * This houses preference menu assets, since they can be loaded at any time, + * most dangerously before the atoms SS initializes. + * Thus, we want it to fail consistently in CI as if it would've if a player + * opened it up early. + */ +SUBSYSTEM_DEF(early_assets) + name = "Early Assets" + init_order = INIT_ORDER_EARLY_ASSETS + subsystem_flags = SS_NO_FIRE + +/datum/controller/subsystem/early_assets/Initialize(timeofday) + for (var/datum/asset/asset_type as anything in subtypesof(/datum/asset)) + if (initial(asset_type._abstract) == asset_type) + continue + + if (!initial(asset_type.early)) + continue + + if (!load_asset_datum(asset_type)) + stack_trace("Could not initialize early asset [asset_type]!") + + CHECK_TICK + + return ..() diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index f7c36c68271..72b61cacb8d 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -1,7 +1,12 @@ -GLOBAL_LIST_EMPTY(lighting_update_lights) // List of lighting sources queued for update. -GLOBAL_LIST_EMPTY(lighting_update_corners) // List of lighting corners queued for update. +GLOBAL_LIST_EMPTY(lighting_update_lights) // List of lighting sources queued for update. +GLOBAL_LIST_EMPTY(lighting_update_corners) // List of lighting corners queued for update. GLOBAL_LIST_EMPTY(lighting_update_objects) // List of lighting objects queued for update. +#ifdef VISUALIZE_LIGHT_UPDATES +GLOBAL_VAR_INIT(allow_duped_values, FALSE) +GLOBAL_VAR_INIT(allow_duped_corners, FALSE) +#endif + SUBSYSTEM_DEF(lighting) name = "Lighting" wait = 2 diff --git a/code/controllers/subsystem/processing/chemistry.dm b/code/controllers/subsystem/processing/chemistry.dm index 1e489ffa37d..9a10c3c2f83 100644 --- a/code/controllers/subsystem/processing/chemistry.dm +++ b/code/controllers/subsystem/processing/chemistry.dm @@ -17,12 +17,14 @@ PROCESSING_SUBSYSTEM_DEF(chemistry) initialize_chemical_reagents() return ..() -//Chemical Reactions - Initialises all /datum/chemical_reaction into a list -// It is filtered into multiple lists within a list. -// For example: -// chemical_reaction_list["phoron"] is a list of all reactions relating to phoron -// Note that entries in the list are NOT duplicated. So if a reaction pertains to -// more than one chemical it will still only appear in only one of the sublists. +/** + * Chemical Reactions - Initialises all /datum/chemical_reaction into a list + * It is filtered into multiple lists within a list. + * For example: + * - chemical_reaction_list["phoron"] is a list of all reactions relating to phoron + * - Note that entries in the list are NOT duplicated. So if a reaction pertains to + * - more than one chemical it will still only appear in only one of the sublists. + */ /datum/controller/subsystem/processing/chemistry/proc/initialize_chemical_reactions() var/paths = typesof(/datum/chemical_reaction) - /datum/chemical_reaction chemical_reactions = list() @@ -36,7 +38,7 @@ PROCESSING_SUBSYSTEM_DEF(chemistry) LAZYINITLIST(chemical_reactions_by_reagent[reagent_id]) chemical_reactions_by_reagent[reagent_id] += D -//Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id +/// Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id /datum/controller/subsystem/processing/chemistry/proc/initialize_chemical_reagents() var/paths = typesof(/datum/reagent) - /datum/reagent chemical_reagents = list() diff --git a/code/datums/elements/update_icon_blocker.dm b/code/datums/elements/update_icon_blocker.dm new file mode 100644 index 00000000000..45206772564 --- /dev/null +++ b/code/datums/elements/update_icon_blocker.dm @@ -0,0 +1,18 @@ +/// Prevents calling anything in update_icon() like update_icon_state() or update_overlays() +/datum/element/update_icon_blocker + +/datum/element/update_icon_blocker/Attach(datum/target) + . = ..() + if(!isatom(target)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, COMSIG_ATOM_UPDATE_ICON, .proc/block_update_icon) + +/datum/element/update_icon_blocker/Detach(datum/source, ...) + UnregisterSignal(source, COMSIG_ATOM_UPDATE_ICON) + return ..() + +/datum/element/update_icon_blocker/proc/block_update_icon() + SIGNAL_HANDLER + + return COMSIG_ATOM_NO_UPDATE_ICON_STATE | COMSIG_ATOM_NO_UPDATE_OVERLAYS diff --git a/code/game/atoms/atoms.dm b/code/game/atoms/atoms.dm index b38373dea61..ff16bc124d5 100644 --- a/code/game/atoms/atoms.dm +++ b/code/game/atoms/atoms.dm @@ -845,11 +845,12 @@ /atom/proc/InsertedContents() return contents +/// Where atoms should drop if taken from this atom. /atom/proc/drop_location() - var/atom/L = loc - if(!L) + var/atom/location = loc + if(!location) return null - return L.AllowDrop() ? L : L.drop_location() + return location.AllowDrop() ? location : location.drop_location() /atom/proc/AllowDrop() return FALSE diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index b8ca5857b6a..91d8322ed7e 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -287,3 +287,9 @@ /// Used below, simple injection modifier. /proc/probinj(pr, inj) return prob(pr+inj*pr) + +/mob/proc/has_dna() + return + +/mob/living/carbon/has_dna() + return dna diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 51b39c8dd2e..b9868ca4eac 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -42,7 +42,7 @@ /obj/machinery/dna_scannernew name = "\improper DNA modifier" desc = "It scans DNA structures." - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "scanner_0" density = TRUE anchored = TRUE diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 45921ae95c5..118a36d9047 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -1,6 +1,6 @@ /obj/machinery/sleep_console name = "sleeper console" - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "sleeperconsole" var/obj/machinery/sleeper/sleeper anchored = TRUE @@ -160,7 +160,7 @@ /obj/machinery/sleeper name = "sleeper" desc = "A stasis pod with built-in injectors, a dialysis machine, and a limited health scanner." - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "sleeper_0" density = TRUE anchored = TRUE diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index c612d6af9e0..805020690fd 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -105,10 +105,12 @@ var/machine_stat = 0 var/emagged = FALSE + /** + * USE_POWER_OFF = dont run the auto + * USE_POWER_IDLE = run auto, use idle + * USE_POWER_ACTIVE = run auto, use active + */ var/use_power = USE_POWER_IDLE - //0 = dont run the auto - //1 = run auto, use idle - //2 = run auto, use active /// idle power usage in watts var/idle_power_usage = 0 /// active power usage in watts @@ -456,7 +458,8 @@ /obj/machinery/proc/dismantle() playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) - //TFF 3/6/19 - port Cit RP fix of infinite frames. If it doesn't have a circuit board, don't create a frame. Return a smack instead. BONK! + on_deconstruction() + // If it doesn't have a circuit board, don't create a frame. Return a smack instead. BONK! if(!circuit) return 0 var/obj/structure/frame/A = new /obj/structure/frame(src.loc) @@ -501,3 +504,36 @@ M.after_deconstruct(src) qdel(src) return 1 + +//called on machinery construction (i.e from frame to machinery) but not on initialization +// /obj/machinery/proc/on_construction() //! Not used yet. +// return + +//called on deconstruction before the final deletion +/obj/machinery/proc/on_deconstruction() + return + +/** + * Puts passed object in to user's hand + * + * Puts the passed object in to the users hand if they are adjacent. + * If the user is not adjacent then place the object on top of the machine. + * + * Vars: + * * object (obj) The object to be moved in to the users hand. + * * user (mob/living) The user to recive the object + */ +/obj/machinery/proc/try_put_in_hand(obj/object, mob/living/user) + if(!issilicon(user) && in_range(src, user)) + user.put_in_hands(object) + else + object.forceMove(drop_location()) + +/// Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8. +/obj/machinery/proc/adjust_item_drop_location(atom/movable/dropped_atom) + var/md5 = md5(dropped_atom.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot. + for (var/i in 1 to 32) + . += hex2num(md5[i]) + . = . % 9 + dropped_atom.pixel_x = -8 + ((.%3)*8) + dropped_atom.pixel_y = -8 + (round( . / 3)*8) diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 6d935d291ff..b3f4b0ad4ee 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -4,7 +4,7 @@ var/mob/living/carbon/occupant var/locked name = "Body Scanner" - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "scanner_open" density = 1 anchored = 1 @@ -166,7 +166,7 @@ var/delete var/temphtml name = "Body Scanner Console" - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "scanner_terminal_off" dir = 8 density = 1 diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 79f6ee0d859..1fd3d6d3e2e 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -2,7 +2,7 @@ #define HEAT_CAPACITY_HUMAN 100 /obj/machinery/atmospherics/component/unary/cryo_cell name = "cryo cell" - icon = 'icons/obj/cryogenics.dmi' // map only + icon = 'icons/obj/medical/cryogenics.dmi' // map only icon_state = "pod_preview" density = TRUE anchored = TRUE @@ -27,7 +27,7 @@ /obj/machinery/atmospherics/component/unary/cryo_cell/Initialize(mapload) . = ..() - icon = 'icons/obj/cryogenics_split.dmi' + icon = 'icons/obj/medical/cryogenics_split.dmi' icon_state = "base" initialize_directions = dir diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 160051cc68d..598de3f4e66 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -11,7 +11,7 @@ /obj/machinery/computer/cryopod name = "cryogenic oversight console" desc = "An interface between crew and the cryogenic storage oversight systems." - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "cellconsole" circuit = /obj/item/circuitboard/cryopodcontrol density = FALSE @@ -190,7 +190,7 @@ name = "cryogenic feed" desc = "A bewildering tangle of machinery and pipes." - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "cryo_rear" anchored = TRUE dir = WEST @@ -199,7 +199,7 @@ /obj/machinery/cryopod name = "cryogenic freezer" desc = "A man-sized pod for entering suspended animation." - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "cryopod_0" density = TRUE anchored = TRUE diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index a5e2db02de4..0428bfe6ff6 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -1,74 +1,160 @@ +#define IV_TAKING 0 +#define IV_INJECTING 1 + +#define MIN_IV_TRANSFER_RATE 0.1 +#define MAX_IV_TRANSFER_RATE 5 + + +/// Universal IV that can drain blood or feed reagents over a period of time from or to a replaceable container. /obj/machinery/iv_drip name = "\improper IV drip" - icon = 'icons/obj/iv_drip.dmi' + icon = 'icons/obj/medical/iv_drip.dmi' + icon_state = "iv_drip" + base_icon_state = "iv_drip" anchored = FALSE - density = FALSE + mouse_drag_pointer = MOUSE_ACTIVE_POINTER + use_power = USE_POWER_OFF pass_flags_self = ATOM_PASS_TABLE | ATOM_PASS_OVERHEAD_THROW - var/mob/living/carbon/human/attached = null - var/mode = 1 // 1 is injecting, 0 is taking blood. - var/obj/item/reagent_containers/beaker = null + /// Who are we sticking our needle in? + var/mob/living/carbon/attached + /// Are we donating or injecting? + var/mode = IV_INJECTING + /// Whether we feed slower. + var/transfer_rate = MAX_IV_TRANSFER_RATE + /// Internal beaker. + var/obj/item/reagent_container = null + ///Typecache of containers we accept + var/static/list/drip_containers = typecacheof(list( + /obj/item/reagent_containers/blood, + )) + /// If the blood draining tab should be greyed out. + ///! Not Used. + var/inject_only = FALSE -/obj/machinery/iv_drip/update_icon() +/obj/machinery/iv_drip/Initialize(mapload) + . = ..() + update_appearance() + // if(use_internal_storage) + // create_reagents(100, TRANSPARENT) + interaction_flags_machine |= INTERACT_MACHINE_OFFLINE + +/obj/machinery/iv_drip/Destroy() + attached = null + QDEL_NULL(reagent_container) + return ..() + +/obj/machinery/iv_drip/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "IVDrip", name) + ui.open() + +/obj/machinery/iv_drip/ui_data(mob/user) + var/list/data = list() + data["transferRate"] = transfer_rate + data["maxInjectRate"] = MAX_IV_TRANSFER_RATE + data["minInjectRate"] = MIN_IV_TRANSFER_RATE + data["mode"] = mode == IV_INJECTING ? TRUE : FALSE + data["connected"] = attached ? TRUE : FALSE + data["beakerAttached"] = reagent_container ? TRUE : FALSE + // data["useInternalStorage"] = use_internal_storage + return data + +/obj/machinery/iv_drip/ui_act(action, params) + . = ..() + if(.) + return + switch(action) + if("changeMode") + toggle_mode() + . = TRUE + if("eject") + eject_beaker() + . = TRUE + if("changeRate") + var/target_rate = params["rate"] + if(text2num(target_rate) != null) + target_rate = text2num(target_rate) + transfer_rate = round(clamp(target_rate, MIN_IV_TRANSFER_RATE, MAX_IV_TRANSFER_RATE), 0.1) + . = TRUE + update_appearance() + +/obj/machinery/iv_drip/update_icon_state() if(attached) - icon_state = "hooked" + icon_state = "[base_icon_state]_[mode ? "injecting" : "donating"]" else - icon_state = "" + icon_state = "[base_icon_state]_[mode ? "injectidle" : "donateidle"]" + return ..() - overlays = null +/obj/machinery/iv_drip/update_overlays() + . = ..() - if(beaker) - var/datum/reagents/reagents = beaker.reagents - if(reagents.total_volume) - var/image/filling = image('icons/obj/iv_drip.dmi', src, "reagent") + if(!reagent_container) + return - var/percent = round((reagents.total_volume / beaker.volume) * 100) - switch(percent) - if(0 to 9) - filling.icon_state = "reagent0" - if(10 to 24) - filling.icon_state = "reagent10" - if(25 to 49) - filling.icon_state = "reagent25" - if(50 to 74) - filling.icon_state = "reagent50" - if(75 to 79) - filling.icon_state = "reagent75" - if(80 to 90) - filling.icon_state = "reagent80" - if(91 to INFINITY) - filling.icon_state = "reagent100" + . += attached ? "beakeractive" : "beakeridle" + var/datum/reagents/target_reagents = get_reagent_holder() + if(!target_reagents) + return - filling.icon += reagents.get_color() - overlays += filling + var/mutable_appearance/filling_overlay = mutable_appearance('icons/obj/medical/iv_drip.dmi', "reagent") + var/percent = round((target_reagents.total_volume / target_reagents.maximum_volume) * 100) + switch(percent) + if(0 to 9) + filling_overlay.icon_state = "reagent0" + if(10 to 24) + filling_overlay.icon_state = "reagent10" + if(25 to 49) + filling_overlay.icon_state = "reagent25" + if(50 to 74) + filling_overlay.icon_state = "reagent50" + if(75 to 79) + filling_overlay.icon_state = "reagent75" + if(80 to 90) + filling_overlay.icon_state = "reagent80" + if(91 to INFINITY) + filling_overlay.icon_state = "reagent100" -/obj/machinery/iv_drip/OnMouseDropLegacy(over_object, src_location, over_location) - ..() - if(!isliving(usr)) + filling_overlay.color = mix_color_from_reagents(target_reagents.reagent_list) + . += filling_overlay + +/obj/machinery/iv_drip/OnMouseDropLegacy(mob/living/target) + . = ..() + if(!ishuman(usr) || !usr.canUseTopic(src, be_close = TRUE) || !isliving(target)) return if(attached) - visible_message(SPAN_NOTICE("[attached] is detached from \the [src]")) + visible_message(SPAN_WARNING("[attached] is detached from [src].")) attached = null - update_icon() + update_appearance() return - if(in_range(src, usr) && ishuman(over_object) && get_dist(over_object, src) <= 1) - visible_message(SPAN_NOTICE("[usr] attaches \the [src] to \the [over_object].")) - attached = over_object - update_icon() + if(!target.has_dna()) + to_chat(usr, SPAN_DANGER("The drip beeps: Warning, incompatible creature!")) + return + if(Adjacent(target) && usr.Adjacent(target)) + if(get_reagent_holder()) + attach_iv(target, usr) + else + to_chat(usr, SPAN_WARNING("There's nothing attached to the IV drip!")) -/obj/machinery/iv_drip/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/reagent_containers)) - if(!isnull(beaker)) - to_chat(user, SPAN_WARNING("There is already a reagent container loaded!")) +/obj/machinery/iv_drip/attackby(obj/item/W, mob/user, params) + // if(use_internal_storage) + // return ..() + + if(is_type_in_typecache(W, drip_containers)) + if(reagent_container) + to_chat(user, SPAN_WARNING("[reagent_container] is already loaded on [src]!")) return if(!user.attempt_insert_item_for_installation(W, src)) return - beaker = W - to_chat(user, SPAN_NOTICE("You attach \the [W] to \the [src].")) - update_icon() + reagent_container = W + to_chat(user, SPAN_NOTICE("You attach [W] to [src].")) + // user.log_message("attached a [W] to [src] at [AREACOORD(src)] containing ([reagent_container.reagents.get_reagent_log_string()])", LOG_ATTACK) + add_fingerprint(user) + update_appearance() return if(W.is_screwdriver()) @@ -78,109 +164,174 @@ to_chat(user, SPAN_NOTICE("You dismantle the IV drip.")) var/obj/item/stack/rods/A = new /obj/item/stack/rods(src.loc) A.amount = 6 - if(beaker) - beaker.loc = get_turf(src) - beaker = null + if(reagent_container) + reagent_container.loc = get_turf(src) + reagent_container = null qdel(src) return else return ..() - -/obj/machinery/iv_drip/process(delta_time) - set background = 1 - - if(attached) - - if(!(get_dist(src, attached) <= 1 && isturf(attached.loc))) - visible_message("The needle is ripped out of [attached], doesn't that hurt?") - attached:apply_damage(3, BRUTE, pick("r_arm", "l_arm")) - attached = null - update_icon() - return - - if(attached && beaker) - // Give blood - if(mode) - if(beaker.volume > 0) - var/transfer_amount = REM - if(istype(beaker, /obj/item/reagent_containers/blood)) - // speed up transfer on blood packs - transfer_amount = 4 - beaker.reagents.trans_to_mob(attached, transfer_amount, CHEM_BLOOD) - update_icon() - - // Take blood - else - var/amount = beaker.reagents.maximum_volume - beaker.reagents.total_volume - amount = min(amount, 4) - // If the beaker is full, ping - if(amount == 0) - if(prob(5)) - visible_message(SPAN_NOTICE("\The [src] pings.")) - return - - var/mob/living/carbon/human/T = attached - - if(!istype(T)) - return - if(!T.dna) - return - if(MUTATION_NOCLONE in T.mutations) - return - - if(!T.should_have_organ(O_HEART)) - return - - // If the human is losing too much blood, beep. - if(T.vessel.get_reagent_amount("blood") < T.species.blood_volume*T.species.blood_level_safe) - visible_message(SPAN_BOLDNOTICE("\The [src] beeps loudly.")) - - var/datum/reagent/B = T.take_blood(beaker,amount) - - if(B) - beaker.reagents.reagent_list |= B - beaker.reagents.update_total() - beaker.on_reagent_change() - beaker.reagents.handle_reactions() - update_icon() - /obj/machinery/iv_drip/attack_hand(mob/user) - if(beaker) - beaker.loc = get_turf(src) - beaker = null - update_icon() + if(reagent_container) + reagent_container.loc = get_turf(src) + reagent_container = null + update_appearance() else return ..() +/obj/machinery/iv_drip/process(delta_time) + if(!attached) + return PROCESS_KILL + + if(!(get_dist(src, attached) <= 1 && isturf(attached.loc))) + to_chat(attached, SPAN_USERDANGER("The IV drip needle is ripped out of you, leaving an open bleeding wound!")) + var/list/arm_zones = shuffle(list(BP_R_ARM, BP_L_ARM)) + var/obj/item/organ/external/chosen_limb = attached.get_organ(arm_zones[1]) || attached.get_organ(arm_zones[2]) || attached.get_organ(BP_TORSO) + chosen_limb.take_damage(3) + chosen_limb.createwound(CUT, 5) + detach_iv() + return PROCESS_KILL + + var/datum/reagents/target_reagents = get_reagent_holder() + if(target_reagents) + // Give blood + if(mode) + if(target_reagents.total_volume) + var/real_transfer_amount = transfer_rate + if(istype(reagent_container, /obj/item/reagent_containers/blood)) + // speed up transfer on blood packs + real_transfer_amount *= 2 + target_reagents.trans_to_mob(attached, real_transfer_amount * delta_time * 0.5, type = CHEM_BLOOD) + update_appearance() + + // Take blood + else + var/amount = target_reagents.maximum_volume - target_reagents.total_volume + amount = min(amount, 4) * delta_time * 0.5 + // If the beaker is full, ping + if(!amount) + if(prob(5)) + visible_message(SPAN_HEAR("[src] pings.")) + return + + // If the human is losing too much blood, beep. + if(attached.species.blood_volume < BLOOD_VOLUME_SAFE && prob(5)) + visible_message(SPAN_HEAR("[src] beeps loudly.")) + playsound(loc, 'sound/machines/twobeep_high.ogg', 50, TRUE) + // var/atom/movable/target = use_internal_storage ? src : reagent_container + var/atom/movable/target = reagent_container + attached.inject_blood(target, amount) + update_appearance() + +/// called when an IV is attached. +/obj/machinery/iv_drip/proc/attach_iv(mob/living/target, mob/user) + user.visible_message( + SPAN_WARNING("[usr] begins attaching [src] to [target]..."), + SPAN_WARNING("You begin attaching [src] to [target]."), + ) + if(!do_after(usr, 1 SECONDS, target)) + return + usr.visible_message( + SPAN_WARNING("[usr] attaches [src] to [target]."), + SPAN_NOTICE("You attach [src] to [target]."), + ) + // var/datum/reagents/container = get_reagent_holder() + // log_combat(usr, target, "attached", src, "containing: ([container.get_reagent_log_string()])") + add_fingerprint(usr) + attached = target + // START_PROCESSING(SSmachines, src) + update_appearance() + + //! Plumbing Signal + // SEND_SIGNAL(src, COMSIG_IV_ATTACH, target) + +/** + * Called when an iv is detached. + * doesn't include chat stuff because there's multiple options and its better handled by the caller. + */ +/obj/machinery/iv_drip/proc/detach_iv() + //! Plumbing Signal + // SEND_SIGNAL(src, COMSIG_IV_DETACH, attached) + + attached = null + update_appearance() + +/obj/machinery/iv_drip/proc/get_reagent_holder() + // return use_internal_storage ? reagents : reagent_container?.reagents + return reagent_container?.reagents + +/obj/machinery/iv_drip/verb/eject_beaker() + set category = "Object" + set name = "Remove IV Container" + set src in view(1) + + if(!isliving(usr)) + to_chat(usr, SPAN_WARNING("You can't do that!")) + return + if (!usr.canUseTopic()) + return + if(usr.incapacitated()) + return + if(reagent_container) + if(attached) + visible_message(SPAN_WARNING("[attached] is detached from [src].")) + detach_iv() + reagent_container.forceMove(drop_location()) + reagent_container = null + update_appearance() /obj/machinery/iv_drip/verb/toggle_mode() set category = "Object" set name = "Toggle Mode" set src in view(1) - if(!istype(usr, /mob/living)) - to_chat(usr, SPAN_WARNING("You can't do that.")) + if(!isliving(usr)) + to_chat(usr, SPAN_WARNING("You can't do that!")) return - - if(usr.stat) + if (!usr.canUseTopic()) + return + if(usr.incapacitated()) return - mode = !mode - to_chat(usr, SPAN_INFO("The IV drip is now [mode ? "injecting" : "taking blood"].")) + to_chat(usr, SPAN_NOTICE("The IV drip is now [mode ? "injecting" : "taking blood"].")) + update_appearance() /obj/machinery/iv_drip/examine(mob/user) . = ..() - if(!(user in view(2)) && user != src.loc) + if(get_dist(user, src) > 2) return - . += SPAN_INFO("The IV drip is [mode ? "injecting" : "taking blood"].") - if(beaker) - if(beaker.reagents && beaker.reagents.reagent_list.len) - . += SPAN_NOTICE("Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.") + . += "[src] is [mode ? "injecting" : "taking blood"]." + + if(reagent_container) + if(reagent_container.reagents && reagent_container.reagents.reagent_list.len) + . += SPAN_NOTICE("Attached is \a [reagent_container] with [reagent_container.reagents.total_volume] units of liquid.") else - . += SPAN_NOTICE("Attached is an empty [beaker].") - else + . += SPAN_NOTICE("Attached is an empty [reagent_container.name].") + // else if(use_internal_storage) + // . += SPAN_NOTICE("It has an internal chemical storage.") + // else . += SPAN_NOTICE("No chemicals are attached.") . += SPAN_NOTICE("[attached ? attached : "No one"] is attached.") +/* +/obj/machinery/iv_drip/saline + name = "saline drip" + desc = "An all-you-can-drip saline canister designed to supply a hospital without running out, with a scary looking pump rigged to inject saline into containers, but filling people directly might be a bad idea." + icon_state = "saline" + base_icon_state = "saline" + density = TRUE + inject_only = TRUE + +/obj/machinery/iv_drip/saline/Initialize(mapload) + AddElement(/datum/element/update_icon_blocker) + . = ..() + reagent_container = new /obj/item/reagent_containers/cup/saline(src) + +/obj/machinery/iv_drip/saline/eject_beaker() + return + +/obj/machinery/iv_drip/saline/toggle_mode() + return +*/ diff --git a/code/game/machinery/virtual_reality/ar_console.dm b/code/game/machinery/virtual_reality/ar_console.dm index 85916d437d1..8941321769a 100644 --- a/code/game/machinery/virtual_reality/ar_console.dm +++ b/code/game/machinery/virtual_reality/ar_console.dm @@ -6,7 +6,7 @@ /obj/machinery/vr_sleeper/alien name = "strange pod" desc = "A strange machine with what appears to be a comfortable, if quite vertical, bed. Numerous mechanical cylinders dot the ceiling, their purpose uncertain." - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "alienpod_0" base_state = "alienpod_" diff --git a/code/game/machinery/virtual_reality/vr_console.dm b/code/game/machinery/virtual_reality/vr_console.dm index 258fd29d3a0..938dc3de600 100644 --- a/code/game/machinery/virtual_reality/vr_console.dm +++ b/code/game/machinery/virtual_reality/vr_console.dm @@ -1,7 +1,7 @@ /obj/machinery/vr_sleeper name = "virtual reality sleeper" desc = "A fancy bed with built-in sensory I/O ports and connectors to interface users' minds with their bodies in virtual reality." - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "syndipod_0" var/base_state = "syndipod_" diff --git a/code/game/machinery/vr_console.dm b/code/game/machinery/vr_console.dm index e76980eba38..de72c441912 100644 --- a/code/game/machinery/vr_console.dm +++ b/code/game/machinery/vr_console.dm @@ -1,7 +1,7 @@ /obj/machinery/vr_sleeper name = "virtual reality sleeper" desc = "A fancy bed with built-in sensory I/O ports and connectors to interface users' minds with their bodies in virtual reality." - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "syndipod_0" density = TRUE anchored = TRUE diff --git a/code/game/mecha/equipment/tools/sleeper.dm b/code/game/mecha/equipment/tools/sleeper.dm index 5f3d429f49b..03c6c68c8cd 100644 --- a/code/game/mecha/equipment/tools/sleeper.dm +++ b/code/game/mecha/equipment/tools/sleeper.dm @@ -1,7 +1,7 @@ /obj/item/mecha_parts/mecha_equipment/tool/sleeper name = "mounted sleeper" desc = "A sleeper. Mountable to an exosuit. (Can be attached to: Medical Exosuits)" - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "sleeper_0" origin_tech = list(TECH_DATA = 2, TECH_BIO = 3) energy_drain = 20 diff --git a/code/game/mecha/equipment/tools/syringe_gun.dm b/code/game/mecha/equipment/tools/syringe_gun.dm index 28510cba26c..582bde85df5 100644 --- a/code/game/mecha/equipment/tools/syringe_gun.dm +++ b/code/game/mecha/equipment/tools/syringe_gun.dm @@ -66,7 +66,7 @@ S.forceMove(get_turf(chassis)) reagents.trans_to_obj(S, min(S.volume, reagents.total_volume)) syringes -= S - S.icon = 'icons/obj/chemical.dmi' + S.icon = 'icons/obj/medical/chemical.dmi' S.icon_state = "syringeproj" playsound(src, 'sound/items/syringeproj.ogg', 50, 1) log_message("Launched [S] from [src], targeting [target].") diff --git a/code/game/objects/effects/chem/water.dm b/code/game/objects/effects/chem/water.dm index bb4da7d1fbb..b5f941c096c 100644 --- a/code/game/objects/effects/chem/water.dm +++ b/code/game/objects/effects/chem/water.dm @@ -48,5 +48,6 @@ //Used by spraybottles. /obj/effect/water/chempuff name = "chemicals" - icon = 'icons/obj/chempuff.dmi' + icon = 'icons/obj/medical/chempuff.dmi' icon_state = "" + layer = FLY_LAYER diff --git a/code/game/objects/effects/debris/cleanable/misc.dm b/code/game/objects/effects/debris/cleanable/misc.dm index d6c79e4ecd3..2bca9ff33cb 100644 --- a/code/game/objects/effects/debris/cleanable/misc.dm +++ b/code/game/objects/effects/debris/cleanable/misc.dm @@ -72,7 +72,7 @@ density = 0 anchored = 1 plane = OBJ_PLANE - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "molten" /obj/effect/debris/cleanable/cobweb2 diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index a96a9a7f8cb..adc47411457 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -3,7 +3,7 @@ /obj/item/bodybag name = "body bag" desc = "A folded bag designed for the storage and transportation of cadavers." - icon = 'icons/obj/bodybag.dmi' + icon = 'icons/obj/medical/bodybag.dmi' icon_state = "bodybag_folded" w_class = ITEMSIZE_SMALL @@ -32,7 +32,7 @@ /obj/structure/closet/body_bag name = "body bag" desc = "A plastic bag designed for the storage and transportation of cadavers." - icon = 'icons/obj/bodybag.dmi' + icon = 'icons/obj/medical/bodybag.dmi' icon_state = "bodybag_closed" icon_closed = "bodybag_closed" icon_opened = "bodybag_open" @@ -118,7 +118,7 @@ name = "stasis bag" desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \ especially useful if short on time or in a hostile enviroment." - icon = 'icons/obj/cryobag.dmi' + icon = 'icons/obj/medical/cryobag.dmi' icon_state = "bodybag_folded" item_state = "bodybag_cryo_folded" origin_tech = list(TECH_BIO = 4) @@ -136,7 +136,7 @@ name = "stasis bag" desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \ especially useful if short on time or in a hostile enviroment." - icon = 'icons/obj/cryobag.dmi' + icon = 'icons/obj/medical/cryobag.dmi' item_path = /obj/item/bodybag/cryobag store_misc = 0 store_items = 0 diff --git a/code/game/objects/items/circuitboards/other.dm b/code/game/objects/items/circuitboards/other.dm index 900476518a9..da7e89e1b4c 100644 --- a/code/game/objects/items/circuitboards/other.dm +++ b/code/game/objects/items/circuitboards/other.dm @@ -15,6 +15,7 @@ board_type = new /datum/frame/frame_types/machine origin_tech = list(TECH_DATA = 3, TECH_MAGNET = 2) req_components = list( + /obj/item/reagent_containers/glass/beaker = 2, /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/manipulator = 2, ) diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index f89da8cab2f..ee31c521df4 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -6,7 +6,7 @@ /obj/item/defib_kit name = "defibrillator" desc = "A device that delivers powerful shocks to detachable paddles that resuscitate incapacitated patients." - icon = 'icons/obj/defibrillator.dmi' + icon = 'icons/obj/medical/defibrillator.dmi' icon_state = "defibunit" item_state = "defibunit" slot_flags = SLOT_BACK @@ -187,7 +187,7 @@ /obj/item/shockpaddles name = "defibrillator paddles" desc = "A pair of plastic-gripped paddles with flat metal surfaces that are used to deliver powerful electric shocks." - icon = 'icons/obj/defibrillator.dmi' + icon = 'icons/obj/medical/defibrillator.dmi' icon_state = "defibpaddles" item_state = "defibpaddles" gender = PLURAL diff --git a/code/game/objects/items/robobag.dm b/code/game/objects/items/robobag.dm index e9c46db31e5..22224379ce5 100644 --- a/code/game/objects/items/robobag.dm +++ b/code/game/objects/items/robobag.dm @@ -3,7 +3,7 @@ name = "synthmorph bag" desc = "A reusable polymer bag designed to slow down synthetic functions such as data corruption and coolant flow, \ especially useful if short on time or in a hostile enviroment." - icon = 'icons/obj/robobag.dmi' + icon = 'icons/obj/medical/robobag.dmi' icon_state = "bodybag_folded" item_state = "bodybag_cryo_folded" origin_tech = list(TECH_ENGINEERING = 3) @@ -20,7 +20,7 @@ name = "synthmorph bag" desc = "A reusable polymer bag designed to slow down synthetic functions such as data corruption and coolant flow, \ especially useful if short on time or in a hostile enviroment." - icon = 'icons/obj/robobag.dmi' + icon = 'icons/obj/medical/robobag.dmi' item_path = /obj/item/bodybag/cryobag/robobag tank_type = /obj/item/tank/stasis/nitro_cryo stasis_level = 2 // Lower than the normal cryobag, because it's not made for meat that dies. It's made for robots and is freezing. diff --git a/code/game/objects/items/storage/_storage.dm b/code/game/objects/items/storage/_storage.dm index 36f6909f4a5..f9345dbebbd 100644 --- a/code/game/objects/items/storage/_storage.dm +++ b/code/game/objects/items/storage/_storage.dm @@ -716,4 +716,4 @@ . += "\The [src] contains \the [display_item]!" /obj/item/storage/AllowDrop() - return TRUE + return FALSE diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm index 60038e7e4f0..3dc238d69b7 100644 --- a/code/game/objects/items/storage/firstaid.dm +++ b/code/game/objects/items/storage/firstaid.dm @@ -162,7 +162,7 @@ name = "pill bottle" desc = "It's an airtight container for storing medication." icon_state = "pill_canister" - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' drop_sound = 'sound/items/drop/pillbottle.ogg' pickup_sound = 'sound/items/pickup/pillbottle.ogg' item_state_slots = list(SLOT_ID_RIGHT_HAND = "contsolid", SLOT_ID_LEFT_HAND = "contsolid") @@ -244,7 +244,7 @@ /obj/item/storage/pill_bottle/update_icon() ..() if(labeled == 1) - add_overlay(image(icon = 'icons/obj/chemical.dmi', icon_state = "pill_canister_label")) + add_overlay(image(icon = 'icons/obj/medical/chemical.dmi', icon_state = "pill_canister_label")) if(base_icon == "pill_canister") if(bottle_color == "orange") icon_state = "[base_icon]" diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index b7979233d7f..b96add03c94 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -388,7 +388,7 @@ var/obj/effect/decal/D = new/obj/effect/decal/(get_turf(src)) D.name = "water" - D.icon = 'icons/obj/chemical.dmi' + D.icon = 'icons/obj/medical/chemical.dmi' D.icon_state = "chempuff" D.create_reagents(5) src.reagents.trans_to_obj(D, 1) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 333e6d613c7..700b133fa6a 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -29,6 +29,9 @@ var/list/req_access var/list/req_one_access + /// Set when a player renames a renamable object. + var/renamed_by_player = FALSE + /obj/Initialize(mapload) if(register_as_dangerous_object) register_dangerous_to_step() diff --git a/code/game/objects/random/misc.dm b/code/game/objects/random/misc.dm index f875c01ffa6..f6d0cfed736 100644 --- a/code/game/objects/random/misc.dm +++ b/code/game/objects/random/misc.dm @@ -187,7 +187,7 @@ /obj/random/medical/pillbottle name = "Random Pill Bottle" desc = "This is a random pill bottle." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "pill_canister" /obj/random/medical/pillbottle/item_to_spawn() diff --git a/code/game/objects/random/unidentified/medicine.dm b/code/game/objects/random/unidentified/medicine.dm index 1d26d93abf8..61c03551690 100644 --- a/code/game/objects/random/unidentified/medicine.dm +++ b/code/game/objects/random/unidentified/medicine.dm @@ -14,7 +14,7 @@ much more likely to show up. This is done for several purposes; /obj/random/unidentified_medicine name = "unidentified medicine" desc = "This will make a random hypo." - icon = 'icons/obj/syringe.dmi' + icon = 'icons/obj/medical/syringe.dmi' icon_state = "autoinjector1" /obj/random/unidentified_medicine/item_to_spawn() diff --git a/code/game/objects/structures/ghost_pods/human.dm b/code/game/objects/structures/ghost_pods/human.dm index efefe4140e2..92dda473cec 100644 --- a/code/game/objects/structures/ghost_pods/human.dm +++ b/code/game/objects/structures/ghost_pods/human.dm @@ -5,7 +5,7 @@ desc = "This is a pod which appears to contain a body." description_info = "This contains a body, which may wake at any time. The external controls\ seem to be malfunctioning." - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "sleeper_1" icon_state_opened = "sleeper_0" density = TRUE @@ -132,7 +132,7 @@ desc = "This is a pod which appears to contain a body." description_info = "This contains a body, which may wake at any time. The external controls\ seem to be functioning, though the warning lights that flash give no solace.." - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "sleeper_1" icon_state_opened = "sleeper_0" density = TRUE diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index 5d0ecfc0209..d1de4e28801 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -197,7 +197,7 @@ /obj/structure/bed/roller name = "roller bed" desc = "A portable bed-on-wheels made for transporting medical patients." - icon = 'icons/obj/rollerbed.dmi' + icon = 'icons/obj/medical/rollerbed.dmi' icon_state = "rollerbed" base_icon_state = "rollerbed" anchored = FALSE @@ -266,7 +266,7 @@ /obj/item/roller name = "roller bed" desc = "A collapsed roller bed that can be carried around." - icon = 'icons/obj/rollerbed.dmi' + icon = 'icons/obj/medical/rollerbed.dmi' icon_state = "folded_rollerbed" slot_flags = SLOT_BACK w_class = ITEMSIZE_LARGE @@ -303,7 +303,7 @@ /obj/item/roller_holder name = "roller bed rack" desc = "A rack for carrying a collapsed roller bed." - icon = 'icons/obj/rollerbed.dmi' + icon = 'icons/obj/medical/rollerbed.dmi' icon_state = "rollerbed" var/obj/item/roller/held diff --git a/code/game/world.dm b/code/game/world.dm index a22d9fe1582..820dae69e0e 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -18,6 +18,10 @@ GLOBAL_LIST(topic_status_cache) //This happens after the Master subsystem new(s) (it's a global datum) //So subsystems globals exist, but are not initialised /world/New() +#ifdef USE_BYOND_TRACY + #warn USE_BYOND_TRACY is enabled + init_byond_tracy() +#endif log_world("World loaded at [TIME_STAMP("hh:mm:ss", FALSE)]!") var/tempfile = "data/logs/config_error.[GUID()].log" //temporary file used to record errors with loading config, moved to log directory once logging is set @@ -461,3 +465,18 @@ GLOBAL_LIST(topic_status_cache) #endif //! END + +/world/proc/init_byond_tracy() + var/library + + switch (system_type) + if (MS_WINDOWS) + library = "prof.dll" + if (UNIX) + library = "libprof.so" + else + CRASH("Unsupported platform: [system_type]") + + var/init_result = call(library, "init")() + if (init_result != "0") + CRASH("Error initializing byond-tracy: [init_result]") diff --git a/code/modules/asset_cache/asset_list.dm b/code/modules/asset_cache/asset_list.dm index 8fc87721798..a6431a6bf43 100644 --- a/code/modules/asset_cache/asset_list.dm +++ b/code/modules/asset_cache/asset_list.dm @@ -6,8 +6,16 @@ //all of our asset datums, used for referring to these later GLOBAL_LIST_EMPTY(asset_datums) -//get an assetdatum or make a new one +/// Get an assetdatum or make a new one. /proc/get_asset_datum(type) + var/datum/asset/loaded_asset = GLOB.asset_datums[type] || new type() + return loaded_asset.ensure_ready() + +/** + * Get an assetdatum or make a new one. + *! But does NOT ensure it's filled, if you want that use get_asset_datum() + */ +/proc/load_asset_datum(type) return GLOB.asset_datums[type] || new type() /datum/asset @@ -18,11 +26,25 @@ GLOBAL_LIST_EMPTY(asset_datums) /// Whether or not this asset should be loaded in the "early assets" SS var/early = FALSE - /// Whether or not this asset can be cached across rounds of the same commit under the `CACHE_ASSETS` config. - /// This is not a *guarantee* the asset will be cached. Not all asset subtypes respect this field, and the - /// config can, of course, be disabled. + /** + * Whether or not this asset can be cached across rounds of the same commit under the `CACHE_ASSETS` config. + * This is not a *guarantee* the asset will be cached. Not all asset subtypes respect this field, and the + * config can, of course, be disabled. + */ var/cross_round_cachable = FALSE +/** + * Stub that allows us to react to something trying to get us. + * Not useful here, more handy for sprite sheets. + */ +/datum/asset/proc/ensure_ready() + return src + +/// Stub to hook into if your asset is having its generation queued by SSasset_loading +/datum/asset/proc/queued_generation() + CRASH("[type] inserted into SSasset_loading despite not implementing /proc/queued_generation") + + /datum/asset/New() GLOB.asset_datums[type] = src register() @@ -51,12 +73,16 @@ GLOBAL_LIST_EMPTY(asset_datums) /// If you don't need anything complicated. /datum/asset/simple _abstract = /datum/asset/simple - /// list of assets for this datum in the form of: - /// asset_filename = asset_file. At runtime the asset_file will be - /// converted into a asset_cache datum. + /** + * List of assets for this datum in the form of: + * * asset_filename = asset_file. + * At runtime the asset_file will be converted into a asset_cache datum. + */ var/assets = list() - /// Set to true to have this asset also be sent via the legacy browse_rsc - /// system when cdn transports are enabled? + /** + * Set to true to have this asset also be sent via the legacy browse_rsc + * system when cdn transports are enabled? + */ var/legacy = FALSE /// TRUE for keeping local asset names when browse_rsc backend is used var/keep_local_name = FALSE @@ -88,7 +114,7 @@ GLOBAL_LIST_EMPTY(asset_datums) /datum/asset/group/register() for(var/type in children) - get_asset_datum(type) + load_asset_datum(type) /datum/asset/group/send(client/C) for(var/type in children) @@ -101,28 +127,44 @@ GLOBAL_LIST_EMPTY(asset_datums) var/datum/asset/A = get_asset_datum(type) . += A.get_url_mappings() -// spritesheet implementation - coalesces various icons into a single .png file -// and uses CSS to select icons out of that file - saves on transferring some -// 1400-odd individual PNG files +/** + * spritesheet implementation - coalesces various icons into a single .png file + * and uses CSS to select icons out of that file - saves on transferring some + * 1400-odd individual PNG files + */ #define SPR_SIZE 1 -#define SPR_IDX 2 -#define SPRSZ_COUNT 1 -#define SPRSZ_ICON 2 +#define SPR_IDX 2 + +#define SPRSZ_COUNT 1 +#define SPRSZ_ICON 2 #define SPRSZ_STRIPPED 3 /datum/asset/spritesheet _abstract = /datum/asset/spritesheet var/name - var/list/sizes = list() // "32x32" -> list(10, icon/normal, icon/stripped) - var/list/sprites = list() // "foo_bar" -> list("32x32", 5) + /** + * List of arguments to pass into queuedInsert. + * Exists so we can queue icon insertion, mostly for stuff like preferences. + */ + var/list/to_generate = list() + /// "32x32" -> list(10, icon/normal, icon/stripped) + var/list/sizes = list() + /// "foo_bar" -> list("32x32", 5) + var/list/sprites = list() var/list/cached_spritesheets_needed var/generating_cache = FALSE + var/fully_generated = FALSE + /** + * If this asset should be fully loaded on new + * Defaults to false so we can process this stuff nicely + */ + var/load_immediately = FALSE /datum/asset/spritesheet/should_refresh() if (..()) return TRUE - // Static so that the result is the same, even when the files are created, for this run + /// Static so that the result is the same, even when the files are created, for this run. var/static/should_refresh = null if (isnull(should_refresh)) @@ -140,7 +182,25 @@ GLOBAL_LIST_EMPTY(asset_datums) if (!should_refresh() && read_from_cache()) return + /// If it's cached, may as well load it now, while the loading is cheap + if(CONFIG_GET(flag/cache_assets) && cross_round_cachable) + load_immediately = TRUE + create_spritesheets() + if(load_immediately) + realize_spritesheets(yield = FALSE) + else + SSasset_loading.generate_queue += src + +/datum/asset/spritesheet/proc/realize_spritesheets(yield) + if(fully_generated) + return + while(length(to_generate)) + var/list/stored_args = to_generate[to_generate.len] + to_generate.len-- + queuedInsert(arglist(stored_args)) + if(yield && TICK_CHECK) + return ensure_stripped() for(var/size_id in sizes) @@ -156,6 +216,18 @@ GLOBAL_LIST_EMPTY(asset_datums) if (CONFIG_GET(flag/cache_assets) && cross_round_cachable) write_to_cache() + fully_generated = TRUE + // If we were ever in there, remove ourselves + SSasset_loading.generate_queue -= src + +/datum/asset/spritesheet/queued_generation() + realize_spritesheets(yield = TRUE) + +/datum/asset/spritesheet/ensure_ready() + if(!fully_generated) + realize_spritesheets(yield = FALSE) + return ..() + /datum/asset/spritesheet/send(client/client) if (!name) return @@ -270,17 +342,31 @@ GLOBAL_LIST_EMPTY(asset_datums) return mappings -/// Override this in order to start the creation of the spritehseet. -/// This is where all your Insert, InsertAll, etc calls should be inside. +/** + *! Override this in order to start the creation of the spritehseet. + *! This is where all your Insert, InsertAll, etc calls should be inside. + */ /datum/asset/spritesheet/proc/create_spritesheets() SHOULD_CALL_PARENT(FALSE) CRASH("create_spritesheets() not implemented for [type]!") /datum/asset/spritesheet/proc/Insert(sprite_name, icon/I, icon_state="", dir=SOUTH, frame=1, moving=FALSE) + if(load_immediately) + queuedInsert(sprite_name, I, icon_state, dir, frame, moving) + else + to_generate += list(args.Copy()) + +/** + * LEMON NOTE + * A GOON CODER SAYS BAD ICON ERRORS CAN BE THROWN BY THE "ICON CACHE" + * APPARENTLY IT MAKES ICONS IMMUTABLE + * LOOK INTO USING THE MUTABLE APPEARANCE PATTERN HERE + */ +/datum/asset/spritesheet/proc/queuedInsert(sprite_name, icon/I, icon_state="", dir=SOUTH, frame=1, moving=FALSE) I = icon(I, icon_state=icon_state, dir=dir, frame=frame, moving=moving) - if (!I || !length(icon_states(I))) // that direction or state doesn't exist + if (!I || !length(icon_states(I))) // That direction or state doesn't exist! return - //any sprite modifications we want to do (aka, coloring a greyscaled asset) + // Any sprite modifications we want to do (aka, coloring a greyscaled asset) I = ModifyInserted(I) var/size_id = "[I.Width()]x[I.Height()]" var/size = sizes[size_id] @@ -291,8 +377,10 @@ GLOBAL_LIST_EMPTY(asset_datums) if (size) var/position = size[SPRSZ_COUNT]++ var/icon/sheet = size[SPRSZ_ICON] + var/icon/sheet_copy = icon(sheet) size[SPRSZ_STRIPPED] = null - sheet.Insert(I, icon_state=sprite_name) + sheet_copy.Insert(I, icon_state=sprite_name) + size[SPRSZ_ICON] = sheet_copy sprites[sprite_name] = list(size_id, position) else sizes[size_id] = size = list(1, I, null) diff --git a/code/modules/asset_cache/assets/chemistry/bottles.dm b/code/modules/asset_cache/assets/chemistry/bottles.dm new file mode 100644 index 00000000000..f875dbf8e58 --- /dev/null +++ b/code/modules/asset_cache/assets/chemistry/bottles.dm @@ -0,0 +1,8 @@ +/datum/asset/spritesheet/simple/bottles + name = "bottles" + assets = list( + "bottle1" = 'icons/runtime/assets/medical/bottles/bottle1.png', + "bottle2" = 'icons/runtime/assets/medical/bottles/bottle2.png', + "bottle3" = 'icons/runtime/assets/medical/bottles/bottle3.png', + "bottle4" = 'icons/runtime/assets/medical/bottles/bottle4.png', + ) diff --git a/code/modules/asset_cache/assets/chemistry/patches.dm b/code/modules/asset_cache/assets/chemistry/patches.dm new file mode 100644 index 00000000000..4483167c263 --- /dev/null +++ b/code/modules/asset_cache/assets/chemistry/patches.dm @@ -0,0 +1,8 @@ +/datum/asset/spritesheet/simple/patches + name = "patches" + assets = list( + "patch" = 'icons/runtime/assets/medical/patches/patch.png', + "patch_brute" = 'icons/runtime/assets/medical/patches/patch_brute.png', + "patch_burn" = 'icons/runtime/assets/medical/patches/patch_burn.png', + "patch_both" = 'icons/runtime/assets/medical/patches/patch_both.png', + ) diff --git a/code/modules/asset_cache/assets/chemistry/pills.dm b/code/modules/asset_cache/assets/chemistry/pills.dm new file mode 100644 index 00000000000..9c852b6e31b --- /dev/null +++ b/code/modules/asset_cache/assets/chemistry/pills.dm @@ -0,0 +1,26 @@ +/datum/asset/spritesheet/simple/pills + name = "pills" + assets = list( + "pill1" = 'icons/runtime/assets/medical/pills/pill1.png', + "pill2" = 'icons/runtime/assets/medical/pills/pill2.png', + "pill3" = 'icons/runtime/assets/medical/pills/pill3.png', + "pill4" = 'icons/runtime/assets/medical/pills/pill4.png', + "pill5" = 'icons/runtime/assets/medical/pills/pill5.png', + "pill6" = 'icons/runtime/assets/medical/pills/pill6.png', + "pill7" = 'icons/runtime/assets/medical/pills/pill7.png', + "pill8" = 'icons/runtime/assets/medical/pills/pill8.png', + "pill9" = 'icons/runtime/assets/medical/pills/pill9.png', + "pill10" = 'icons/runtime/assets/medical/pills/pill10.png', + "pill11" = 'icons/runtime/assets/medical/pills/pill11.png', + "pill12" = 'icons/runtime/assets/medical/pills/pill12.png', + "pill13" = 'icons/runtime/assets/medical/pills/pill13.png', + "pill14" = 'icons/runtime/assets/medical/pills/pill14.png', + "pill15" = 'icons/runtime/assets/medical/pills/pill15.png', + "pill16" = 'icons/runtime/assets/medical/pills/pill16.png', + "pill17" = 'icons/runtime/assets/medical/pills/pill17.png', + "pill18" = 'icons/runtime/assets/medical/pills/pill18.png', + "pill19" = 'icons/runtime/assets/medical/pills/pill19.png', + "pill20" = 'icons/runtime/assets/medical/pills/pill20.png', + "pill21" = 'icons/runtime/assets/medical/pills/pill21.png', + "pill22" = 'icons/runtime/assets/medical/pills/pill22.png', + ) diff --git a/code/modules/asset_cache/assets/condiments.dm b/code/modules/asset_cache/assets/condiments.dm index d72716f778c..58a9f2e6072 100644 --- a/code/modules/asset_cache/assets/condiments.dm +++ b/code/modules/asset_cache/assets/condiments.dm @@ -1,20 +1,20 @@ /datum/asset/spritesheet/simple/condiments name = "condiments" assets = list( - CONDIMASTER_STYLE_FALLBACK = 'icons/ui_icons/condiments/emptycondiment.png', - "enzyme" = 'icons/ui_icons/condiments/enzyme.png', - "flour" = 'icons/ui_icons/condiments/flour.png', - "mayonnaise" = 'icons/ui_icons/condiments/mayonnaise.png', - "milk" = 'icons/ui_icons/condiments/milk.png', - "blackpepper" = 'icons/ui_icons/condiments/peppermillsmall.png', - "rice" = 'icons/ui_icons/condiments/rice.png', - "sodiumchloride" = 'icons/ui_icons/condiments/saltshakersmall.png', - "soymilk" = 'icons/ui_icons/condiments/soymilk.png', - "soysauce" = 'icons/ui_icons/condiments/soysauce.png', - "sugar" = 'icons/ui_icons/condiments/sugar.png', - "ketchup" = 'icons/ui_icons/condiments/ketchup.png', - "capsaicin" = 'icons/ui_icons/condiments/hotsauce.png', - "frostoil" = 'icons/ui_icons/condiments/coldsauce.png', - "bbqsauce" = 'icons/ui_icons/condiments/bbqsauce.png', - "cornoil" = 'icons/ui_icons/condiments/oliveoil.png', + CONDIMASTER_STYLE_FALLBACK = 'icons/runtime/assets/condiments/emptycondiment.png', + "enzyme" = 'icons/runtime/assets/condiments/enzyme.png', + "flour" = 'icons/runtime/assets/condiments/flour.png', + "mayonnaise" = 'icons/runtime/assets/condiments/mayonnaise.png', + "milk" = 'icons/runtime/assets/condiments/milk.png', + "blackpepper" = 'icons/runtime/assets/condiments/peppermillsmall.png', + "rice" = 'icons/runtime/assets/condiments/rice.png', + "sodiumchloride" = 'icons/runtime/assets/condiments/saltshakersmall.png', + "soymilk" = 'icons/runtime/assets/condiments/soymilk.png', + "soysauce" = 'icons/runtime/assets/condiments/soysauce.png', + "sugar" = 'icons/runtime/assets/condiments/sugar.png', + "ketchup" = 'icons/runtime/assets/condiments/ketchup.png', + "capsaicin" = 'icons/runtime/assets/condiments/hotsauce.png', + "frostoil" = 'icons/runtime/assets/condiments/coldsauce.png', + "bbqsauce" = 'icons/runtime/assets/condiments/bbqsauce.png', + "cornoil" = 'icons/runtime/assets/condiments/oliveoil.png', ) diff --git a/code/modules/asset_cache/assets/patches.dm b/code/modules/asset_cache/assets/patches.dm deleted file mode 100644 index 2c5bf7e252a..00000000000 --- a/code/modules/asset_cache/assets/patches.dm +++ /dev/null @@ -1,8 +0,0 @@ -/datum/asset/spritesheet/simple/patches - name = "patches" - assets = list( - "bandaid" = 'icons/ui_icons/patches/bandaid.png', - "bandaid_brute" = 'icons/ui_icons/patches/bandaid_brute.png', - "bandaid_burn" = 'icons/ui_icons/patches/bandaid_burn.png', - "bandaid_both" = 'icons/ui_icons/patches/bandaid_both.png' - ) diff --git a/code/modules/asset_cache/assets/pills.dm b/code/modules/asset_cache/assets/pills.dm deleted file mode 100644 index 98a4b62de53..00000000000 --- a/code/modules/asset_cache/assets/pills.dm +++ /dev/null @@ -1,40 +0,0 @@ -/datum/asset/simple/namespaced/chem_master - keep_local_name = TRUE - -/datum/asset/simple/namespaced/chem_master/register() - for(var/i = 1 to 24) - assets["pill[i].png"] = icon('icons/obj/chemical.dmi', "pill[i]") - - for(var/i = 1 to 4) - assets["bottle-[i].png"] = icon('icons/obj/chemical.dmi', "bottle-[i]") - - return ..() - -/* -/datum/asset/spritesheet/simple/pills - name = "pills" - assets = list( - "pill1" = 'icons/ui_icons/pills/pill1.png', - "pill2" = 'icons/ui_icons/pills/pill2.png', - "pill3" = 'icons/ui_icons/pills/pill3.png', - "pill4" = 'icons/ui_icons/pills/pill4.png', - "pill5" = 'icons/ui_icons/pills/pill5.png', - "pill6" = 'icons/ui_icons/pills/pill6.png', - "pill7" = 'icons/ui_icons/pills/pill7.png', - "pill8" = 'icons/ui_icons/pills/pill8.png', - "pill9" = 'icons/ui_icons/pills/pill9.png', - "pill10" = 'icons/ui_icons/pills/pill10.png', - "pill11" = 'icons/ui_icons/pills/pill11.png', - "pill12" = 'icons/ui_icons/pills/pill12.png', - "pill13" = 'icons/ui_icons/pills/pill13.png', - "pill14" = 'icons/ui_icons/pills/pill14.png', - "pill15" = 'icons/ui_icons/pills/pill15.png', - "pill16" = 'icons/ui_icons/pills/pill16.png', - "pill17" = 'icons/ui_icons/pills/pill17.png', - "pill18" = 'icons/ui_icons/pills/pill18.png', - "pill19" = 'icons/ui_icons/pills/pill19.png', - "pill20" = 'icons/ui_icons/pills/pill20.png', - "pill21" = 'icons/ui_icons/pills/pill21.png', - "pill22" = 'icons/ui_icons/pills/pill22.png', - ) -*/ diff --git a/code/modules/atmospherics/machinery/components/unary/cold_sink.dm b/code/modules/atmospherics/machinery/components/unary/cold_sink.dm index 75ee4af1dee..7337e94a39a 100644 --- a/code/modules/atmospherics/machinery/components/unary/cold_sink.dm +++ b/code/modules/atmospherics/machinery/components/unary/cold_sink.dm @@ -2,7 +2,7 @@ /obj/machinery/atmospherics/component/unary/freezer name = "gas cooling system" desc = "Cools gas when connected to pipe network" - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "freezer_0" density = 1 anchored = 1 diff --git a/code/modules/atmospherics/machinery/components/unary/heat_source.dm b/code/modules/atmospherics/machinery/components/unary/heat_source.dm index d10462bd12d..ebcb7c9c12f 100644 --- a/code/modules/atmospherics/machinery/components/unary/heat_source.dm +++ b/code/modules/atmospherics/machinery/components/unary/heat_source.dm @@ -2,7 +2,7 @@ /obj/machinery/atmospherics/component/unary/heater name = "gas heating system" desc = "Heats gas when connected to a pipe network" - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/medical/cryogenic2.dmi' icon_state = "heater_0" density = TRUE anchored = TRUE diff --git a/code/modules/food/food/drinks/drinkingglass.dm b/code/modules/food/food/drinks/drinkingglass.dm index 3f69342da38..e088eebcb26 100644 --- a/code/modules/food/food/drinks/drinkingglass.dm +++ b/code/modules/food/food/drinks/drinkingglass.dm @@ -119,7 +119,7 @@ overlays.Cut() if(reagents.total_volume) - var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]1") + var/image/filling = image('icons/obj/medical/reagentfillings.dmi', src, "[icon_state]1") switch(reagents.total_volume) if(0 to 3) filling.icon_state = "[icon_state]1" @@ -147,7 +147,7 @@ overlays.Cut() if(reagents.total_volume) - var/image/filling = image('icons/obj/reagentfillings.dmi', src, "fitness-cup10") + var/image/filling = image('icons/obj/medical/reagentfillings.dmi', src, "fitness-cup10") switch(reagents.total_volume) if(0 to 10) filling.icon_state = "fitness-cup10" diff --git a/code/modules/food/glass/bottle.dm b/code/modules/food/glass/bottle.dm index 6b360f436fc..cd74c6cf7df 100644 --- a/code/modules/food/glass/bottle.dm +++ b/code/modules/food/glass/bottle.dm @@ -4,7 +4,7 @@ /obj/item/reagent_containers/glass/bottle name = "bottle" desc = "A small bottle." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = null item_state = "atoxinbottle" amount_per_transfer_from_this = 10 @@ -38,7 +38,7 @@ overlays.Cut() if(reagents.total_volume && (icon_state == "bottle-1" || icon_state == "bottle-2" || icon_state == "bottle-3" || icon_state == "bottle-4")) - var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]10") + var/image/filling = image('icons/obj/medical/reagentfillings.dmi', src, "[icon_state]10") var/percent = round((reagents.total_volume / volume) * 100) switch(percent) @@ -60,91 +60,91 @@ /obj/item/reagent_containers/glass/bottle/inaprovaline name = "inaprovaline bottle" desc = "A small bottle. Contains inaprovaline - used to stabilize patients." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("inaprovaline" = 60) /obj/item/reagent_containers/glass/bottle/toxin name = "toxin bottle" desc = "A small bottle of toxins. Do not drink, it is poisonous." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-3" prefill = list("toxin" = 60) /obj/item/reagent_containers/glass/bottle/cyanide name = "cyanide bottle" desc = "A small bottle of cyanide. Bitter almonds?" - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-3" prefill = list("cyanide" = 30) //volume changed to match chloral /obj/item/reagent_containers/glass/bottle/stoxin name = "soporific bottle" desc = "A small bottle of soporific. Just the fumes make you sleepy." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-3" prefill = list("stoxin" = 60) /obj/item/reagent_containers/glass/bottle/chloralhydrate name = "chloral hydrate bottle" desc = "A small bottle of Choral Hydrate. Mickey's Favorite!" - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-3" prefill = list("chloralhydrate" = 30) //Intentionally low since it is so strong. Still enough to knock someone out. /obj/item/reagent_containers/glass/bottle/antitoxin name = "dylovene bottle" desc = "A small bottle of dylovene. Counters poisons, and repairs damage. A wonder drug." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("anti_toxin" = 60) /obj/item/reagent_containers/glass/bottle/mutagen name = "unstable mutagen bottle" desc = "A small bottle of unstable mutagen. Randomly changes the DNA structure of whoever comes in contact." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-1" prefill = list("mutagen" = 60) /obj/item/reagent_containers/glass/bottle/ammonia name = "ammonia bottle" desc = "A small bottle." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-1" prefill = list("ammonia" = 60) /obj/item/reagent_containers/glass/bottle/eznutrient name = "\improper EZ NUtrient bottle" desc = "A small bottle." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("eznutrient" = 60) /obj/item/reagent_containers/glass/bottle/left4zed name = "\improper Left-4-Zed bottle" desc = "A small bottle." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("left4zed" = 60) /obj/item/reagent_containers/glass/bottle/robustharvest name = "\improper Robust Harvest" desc = "A small bottle." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("robustharvest" = 60) /obj/item/reagent_containers/glass/bottle/diethylamine name = "diethylamine bottle" desc = "A small bottle." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("diethylamine" = 60) /obj/item/reagent_containers/glass/bottle/pacid name = "polytrinic acid bottle" desc = "A small bottle. Contains a small amount of Polytrinic Acid" - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("pacid" = 60) @@ -158,20 +158,20 @@ /obj/item/reagent_containers/glass/bottle/capsaicin name = "capsaicin bottle" desc = "A small bottle. Contains hot sauce." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("capsaicin" = 60) /obj/item/reagent_containers/glass/bottle/frostoil name = "frost oil bottle" desc = "A small bottle. Contains cold sauce." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("frostoil" = 60) /obj/item/reagent_containers/glass/bottle/biomass name = "biomass bottle" desc = "A bottle of raw biomass! Gross!" - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-3" prefill = list("biomass" = 60) diff --git a/code/modules/food/glass/bottle/robot.dm b/code/modules/food/glass/bottle/robot.dm index f9c7ab33e94..ecd0b67fcbe 100644 --- a/code/modules/food/glass/bottle/robot.dm +++ b/code/modules/food/glass/bottle/robot.dm @@ -10,7 +10,7 @@ /obj/item/reagent_containers/glass/bottle/robot/inaprovaline name = "internal inaprovaline bottle" desc = "A small bottle. Contains inaprovaline - used to stabilize patients." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" reagent = "inaprovaline" prefill = list("inaprovaline" = 60) @@ -19,8 +19,7 @@ /obj/item/reagent_containers/glass/bottle/robot/antitoxin name = "internal anti-toxin bottle" desc = "A small bottle of Anti-toxins. Counters poisons, and repairs damage, a wonder drug." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" reagent = "anti_toxin" prefill = list("anti_toxin" = 60) - diff --git a/code/modules/food/glass/bottle_vr.dm b/code/modules/food/glass/bottle_vr.dm index 840a6049681..408ab71aca5 100644 --- a/code/modules/food/glass/bottle_vr.dm +++ b/code/modules/food/glass/bottle_vr.dm @@ -1,140 +1,140 @@ /obj/item/reagent_containers/glass/bottle/bicaridine name = "bicaridine bottle" desc = "A small bottle. Bicaridine is an analgesic medication and can be used to treat blunt trauma." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("bicaridine" = 60) /obj/item/reagent_containers/glass/bottle/keloderm name = "keloderm bottle" desc = "A small bottle. A fifty-fifty mix of the popular burn medications kelotane and deramline." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("dermaline" = 30, "kelotane" = 30) /obj/item/reagent_containers/glass/bottle/dermaline name = "dermaline bottle" desc = "A small bottle. Dermaline is the next step in burn medication. Works twice as good as kelotane and enables the body to restore even the direst heat-damaged tissue." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("dermaline" = 60) /obj/item/reagent_containers/glass/bottle/carthatoline name = "carthatoline bottle" desc = "A small bottle. Carthatoline is strong evacuant used to treat severe poisoning." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("carthatoline" = 60) /obj/item/reagent_containers/glass/bottle/dexalinp name = "dexalinp bottle" desc = "A small bottle. Dexalin Plus is used in the treatment of oxygen deprivation. It is highly effective." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("dexalinp" = 60) /obj/item/reagent_containers/glass/bottle/tramadol name = "tramadol bottle" desc = "A small bottle. A simple, yet effective painkiller." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("tramadol" = 60) /obj/item/reagent_containers/glass/bottle/oxycodone name = "oxycodone bottle" desc = "A small bottle. An effective and very addictive painkiller." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("oxycodone" = 60) /obj/item/reagent_containers/glass/bottle/alkysine name = "alkysine bottle" desc = "A small bottle. Alkysine is a drug used to lessen the damage to neurological tissue after a catastrophic injury. Can heal brain tissue." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("alkysine" = 60) /obj/item/reagent_containers/glass/bottle/imidazoline name = "imidazoline bottle" desc = "A small bottle. Heals eye damage." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("imidazoline" = 60) /obj/item/reagent_containers/glass/bottle/peridaxon name = "peridaxon bottle" desc = "A small bottle. Used to encourage recovery of internal organs and nervous systems. Medicate cautiously." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("peridaxon" = 60) /obj/item/reagent_containers/glass/bottle/osteodaxon name = "osteodaxon bottle" desc = "A small bottle. An experimental drug used to heal bone fractures." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("osteodaxon" = 60) /obj/item/reagent_containers/glass/bottle/myelamine name = "myelamine bottle" desc = "A small bottle. Used to rapidly clot internal hemorrhages by increasing the effectiveness of platelets." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("myelamine" = 60) /obj/item/reagent_containers/glass/bottle/hyronalin name = "hyronalin bottle" desc = "A small bottle. Hyronalin is a medicinal drug used to counter the effect of radiation poisoning." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("hyronalin" = 60) /obj/item/reagent_containers/glass/bottle/arithrazine name = "arithrazine bottle" desc = "A small bottle. Arithrazine is an unstable medication used for the most extreme cases of radiation poisoning." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("arithrazine" = 60) /obj/item/reagent_containers/glass/bottle/spaceacillin name = "spaceacillin bottle" desc = "A small bottle. An all-purpose antiviral agent." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("spaceacillin" = 60) /obj/item/reagent_containers/glass/bottle/corophizine name = "corophizine bottle" desc = "A small bottle. A wide-spectrum antibiotic drug. Powerful and uncomfortable in equal doses." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("corophizine" = 60) /obj/item/reagent_containers/glass/bottle/rezadone name = "rezadone bottle" desc = "A small bottle. A powder with almost magical properties, this substance can effectively treat genetic damage in humanoids, though excessive consumption has side effects." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("rezadone" = 60) /obj/item/reagent_containers/glass/bottle/healing_nanites name = "healing nanites bottle" desc = "A small bottle. Miniature medical robots that swiftly restore bodily damage." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("healing_nanites" = 60) /obj/item/reagent_containers/glass/bottle/ickypak name = "ickypak bottle" desc = "A small bottle of ickypak. The smell alone makes you gag." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-3" prefill = list("ickypak" = 60) /obj/item/reagent_containers/glass/bottle/unsorbitol name = "unsorbitol bottle" desc = "A small bottle of unsorbitol. Sickeningly sweet." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-3" prefill = list("unsorbitol" = 60) diff --git a/code/modules/hydroponics/trays/tray_reagents.dm b/code/modules/hydroponics/trays/tray_reagents.dm index 67201900680..851842f309f 100644 --- a/code/modules/hydroponics/trays/tray_reagents.dm +++ b/code/modules/hydroponics/trays/tray_reagents.dm @@ -26,7 +26,7 @@ /obj/item/plantspray/pests/old name = "bottle of pestkiller" - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle16" /obj/item/plantspray/pests/old/carbaryl @@ -53,28 +53,28 @@ /obj/item/weedkiller name = "bottle of weedkiller" - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle16" var/toxicity = 0 var/weed_kill_str = 0 /obj/item/weedkiller/triclopyr name = "bottle of glyphosate" - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle16" toxicity = 4 weed_kill_str = 2 /obj/item/weedkiller/lindane name = "bottle of triclopyr" - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle18" toxicity = 6 weed_kill_str = 4 /obj/item/weedkiller/D24 name = "bottle of 2,4-D" - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle15" toxicity = 8 weed_kill_str = 7 diff --git a/code/modules/lighting/lighting_corner.dm b/code/modules/lighting/lighting_corner.dm index 7932f5c183e..61f73afbb15 100644 --- a/code/modules/lighting/lighting_corner.dm +++ b/code/modules/lighting/lighting_corner.dm @@ -1,14 +1,18 @@ -// Because we can control each corner of every lighting object. -// And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't). -// For the record: these should never ever ever be deleted, even if the turf doesn't have dynamic lighting. - +/** + * Because we can control each corner of every lighting object. + * And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't). + * For the record: these should never ever ever be deleted, even if the turf doesn't have dynamic lighting. + */ /datum/lighting_corner var/turf/northeast var/turf/northwest var/turf/southeast var/turf/southwest - var/list/datum/light_source/affecting // Light sources affecting us. - var/active = FALSE // TRUE if one of our masters has dynamic lighting. + + /// Light sources affecting us. + var/list/datum/light_source/affecting + /// TRUE if one of our masters has dynamic lighting. + var/active = FALSE var/x = 0 var/y = 0 @@ -72,10 +76,15 @@ active = TRUE // God that was a mess, now to do the rest of the corner code! Hooray! -/datum/lighting_corner/proc/update_lumcount(var/delta_r, var/delta_g, var/delta_b) +/datum/lighting_corner/proc/update_lumcount(delta_r, delta_g, delta_b) - if ((abs(delta_r)+abs(delta_g)+abs(delta_b)) == 0) +#ifdef VISUALIZE_LIGHT_UPDATES + if (!GLOB.allow_duped_values && !(delta_r || delta_g || delta_b)) // 0 is falsey ok return +#else + if (!(delta_r || delta_g || delta_b)) // 0 is falsey ok + return +#endif lum_r += delta_r lum_g += delta_g @@ -86,7 +95,7 @@ GLOB.lighting_update_corners += src /datum/lighting_corner/proc/update_objects() - // Cache these values a head of time so 4 individual lighting objects don't all calculate them individually. + // Cache these values ahead of time so 4 individual lighting objects don't all calculate them individually. var/lum_r = src.lum_r var/lum_g = src.lum_g var/lum_b = src.lum_b @@ -95,6 +104,10 @@ if (mx > 1) . = 1 / mx + var/old_r = cache_r + var/old_g = cache_g + var/old_b = cache_b + #if LIGHTING_SOFT_THRESHOLD != 0 else if (mx < LIGHTING_SOFT_THRESHOLD) . = 0 // 0 means soft lighting. @@ -109,6 +122,14 @@ #endif cache_mx = round(mx, LIGHTING_ROUND_VALUE) +#ifdef VISUALIZE_LIGHT_UPDATES + if(!GLOB.allow_duped_corners && old_r == cache_r && old_g == cache_g && old_b == cache_b) + return +#else + if(old_r == cache_r && old_g == cache_g && old_b == cache_b) + return +#endif + #define QUEUE(turf) if(turf?.lighting_object && !turf.lighting_object.needs_update) { turf.lighting_object.needs_update = TRUE; GLOB.lighting_update_objects += turf.lighting_object } QUEUE(northeast) QUEUE(northwest) @@ -120,7 +141,7 @@ return -/datum/lighting_corner/Destroy(var/force) +/datum/lighting_corner/Destroy(force) if (!force) return QDEL_HINT_LETMELIVE diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm index 33e593a46e6..433f722da49 100644 --- a/code/modules/lighting/lighting_object.dm +++ b/code/modules/lighting/lighting_object.dm @@ -1,15 +1,15 @@ /atom/movable/lighting_object - name = "" - anchored = TRUE - flags = ATOM_ABSTRACT + name = "" + anchored = TRUE + flags = ATOM_ABSTRACT - icon = LIGHTING_ICON - icon_state = "transparent" - color = null //we manually set color in init instead - plane = LIGHTING_PLANE - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - layer = LIGHTING_LAYER - invisibility = INVISIBILITY_LIGHTING + icon = LIGHTING_ICON + icon_state = "transparent" + color = null //we manually set color in init instead + plane = LIGHTING_PLANE + layer = LIGHTING_LAYER + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + invisibility = INVISIBILITY_LIGHTING var/needs_update = FALSE var/turf/myturf @@ -33,9 +33,9 @@ needs_update = TRUE GLOB.lighting_update_objects += src -/atom/movable/lighting_object/Destroy(var/force) +/atom/movable/lighting_object/Destroy(force) if (force) - GLOB.lighting_update_objects -= src + GLOB.lighting_update_objects -= src if (loc != myturf) var/turf/oldturf = get_turf(myturf) var/turf/newturf = get_turf(loc) @@ -71,10 +71,16 @@ // See LIGHTING_CORNER_DIAGONAL in lighting_corner.dm for why these values are what they are. var/static/datum/lighting_corner/dummy/dummy_lighting_corner = new - var/datum/lighting_corner/cr = myturf.lc_bottomleft || dummy_lighting_corner +#ifdef VISUALIZE_LIGHT_UPDATES + myturf.add_atom_colour(LIGHT_COLOR_LIGHT_CYAN, ADMIN_COLOUR_PRIORITY) + animate(myturf, 10, color = null) + addtimer(CALLBACK(myturf, /atom/proc/remove_atom_colour, ADMIN_COLOUR_PRIORITY, LIGHT_COLOR_LIGHT_CYAN), 10, TIMER_UNIQUE|TIMER_OVERRIDE) +#endif + + var/datum/lighting_corner/cr = myturf.lc_bottomleft || dummy_lighting_corner var/datum/lighting_corner/cg = myturf.lc_bottomright || dummy_lighting_corner - var/datum/lighting_corner/cb = myturf.lc_topleft || dummy_lighting_corner - var/datum/lighting_corner/ca = myturf.lc_topright || dummy_lighting_corner + var/datum/lighting_corner/cb = myturf.lc_topleft || dummy_lighting_corner + var/datum/lighting_corner/ca = myturf.lc_topright || dummy_lighting_corner var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx) diff --git a/code/modules/mob/_modifiers/traits_phobias.dm b/code/modules/mob/_modifiers/traits_phobias.dm index b50bb21aa5a..cc253e0743e 100644 --- a/code/modules/mob/_modifiers/traits_phobias.dm +++ b/code/modules/mob/_modifiers/traits_phobias.dm @@ -496,7 +496,7 @@ if(istype(thing, /obj/machinery/iv_drip)) var/obj/machinery/iv_drip/I = thing - if(I.beaker) + if(I.reagent_container) fear_amount += 8 else fear_amount += 6 @@ -670,4 +670,3 @@ "WetSkrell was a mistake." ) return pick(generic_responses) - diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 9ccb214e33d..00fe1d2d59e 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -850,3 +850,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/datum/perspective/P = ..() P.SetSight(SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF) P.SetSeeInvis(SEE_INVISIBLE_OBSERVER) + +/mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE) + return isAdminGhostAI(usr) diff --git a/code/modules/mob/inventory/slot_meta.dm b/code/modules/mob/inventory/slot_meta.dm index b34f0525518..e47c08fdd36 100644 --- a/code/modules/mob/inventory/slot_meta.dm +++ b/code/modules/mob/inventory/slot_meta.dm @@ -741,6 +741,7 @@ GLOBAL_LIST_EMPTY(inventory_slot_type_cache) INHAND_DEFAULT_ICON_GUNS = 'icons/mob/items/lefthand_guns.dmi', INHAND_DEFAULT_ICON_HATS = 'icons/mob/items/lefthand_hats.dmi', INHAND_DEFAULT_ICON_HOLDERS = 'icons/mob/items/lefthand_holder.dmi', + INHAND_DEFAULT_ICON_KITCHEN = 'icons/mob/items/lefthand_kitchen.dmi', INHAND_DEFAULT_ICON_MAGIC = 'icons/mob/items/lefthand_magic.dmi', INHAND_DEFAULT_ICON_MASKS = 'icons/mob/items/lefthand_masks.dmi', INHAND_DEFAULT_ICON_MATERIAL = 'icons/mob/items/lefthand_material.dmi', @@ -768,6 +769,7 @@ GLOBAL_LIST_EMPTY(inventory_slot_type_cache) INHAND_DEFAULT_ICON_GUNS = 'icons/mob/items/righthand_guns.dmi', INHAND_DEFAULT_ICON_HATS = 'icons/mob/items/righthand_hats.dmi', INHAND_DEFAULT_ICON_HOLDERS = 'icons/mob/items/righthand_holder.dmi', + INHAND_DEFAULT_ICON_KITCHEN = 'icons/mob/items/righthand_kitchen.dmi', INHAND_DEFAULT_ICON_MAGIC = 'icons/mob/items/righthand_magic.dmi', INHAND_DEFAULT_ICON_MASKS = 'icons/mob/items/righthand_masks.dmi', INHAND_DEFAULT_ICON_MATERIAL = 'icons/mob/items/righthand_material.dmi', diff --git a/code/modules/mob/living/carbon/metroid/items.dm b/code/modules/mob/living/carbon/metroid/items.dm index d6434ced211..71c25fa9a3d 100644 --- a/code/modules/mob/living/carbon/metroid/items.dm +++ b/code/modules/mob/living/carbon/metroid/items.dm @@ -120,7 +120,7 @@ icon_state = "rainbow slime extract" /obj/item/slimepotion - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' ////Pet Slime Creation/// /* @@ -183,7 +183,7 @@ /obj/item/slimepotion2 name = "advanced docility potion" desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame. This one is meant for adult slimes" - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle19" attack(mob/living/carbon/slime/M as mob, mob/user as mob) @@ -215,7 +215,7 @@ /obj/item/slimesteroid name = "slime steroid" desc = "A potent chemical mix that will cause a slime to generate more extract." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle16" attack(mob/living/carbon/slime/M as mob, mob/user as mob) @@ -239,7 +239,7 @@ /obj/item/slimesteroid2 name = "extract enhancer" desc = "A potent chemical mix that will give a slime extract three uses." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle17" /*afterattack(obj/target, mob/user , flag) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 3906e961b0a..6a9bd7445df 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1098,3 +1098,15 @@ default behaviour is: . = ..() // since we're shifted up by transforms.. . += ((size_multiplier * icon_scale_y) - 1) * 16 + +/mob/living/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE) + if(incapacitated()) + to_chat(src, SPAN_WARNING("You can't do that right now!")) + return FALSE + if(be_close && !in_range(M, src)) + to_chat(src, SPAN_WARNING("You are too far away!")) + return FALSE + if(!no_dexterity && !IsAdvancedToolUser()) + to_chat(src, SPAN_WARNING("You don't have the dexterity to do this!")) + return FALSE + return TRUE diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 50f91a45456..c13a4654555 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -916,3 +916,9 @@ var/list/ai_verbs_default = list( #undef AI_CHECK_WIRELESS #undef AI_CHECK_RADIO + +/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE) + if(control_disabled) + to_chat(src, SPAN_WARNING("You can't do that right now!")) + return FALSE + return can_see(M) && ..() //stop AIs from leaving windows open and using then after they lose vision diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index c973aaca37b..b911dc9a4c2 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -493,3 +493,8 @@ visible_message("[src] fades away from the screen, the pAI device goes silent.") card.removePersonality() clear_client() + +// See software.dm for Topic() +/mob/living/silicon/pai/canUseTopic(atom/movable/movable, be_close = FALSE, no_dexterity = FALSE, no_tk = FALSE) + // Resting is just an aesthetic feature for them. + return ..(movable, be_close, no_dexterity, no_tk) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 97e7fad1345..edae7160744 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1405,3 +1405,9 @@ to_chat(src,"Your connection with the shell is suddenly interrupted!") undeploy() ..() + +/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE) + if(lockcharge) + to_chat(src, SPAN_WARNING("You can't do that right now!")) + return FALSE + return ..() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index e8f5021f5ce..d071e1c8a65 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1235,3 +1235,16 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) /mob/CanReachIn(atom/movable/mover, atom/target, obj/item/tool, list/cache) return FALSE + +/** + * Whether the mob can use Topic to interact with machines + * + * Args: + * be_close - Whether you need to be next to/on top of M + * no_dexterity - Whether you need to be an ADVANCEDTOOLUSER + * no_tk - If be_close is TRUE, this will block Telekinesis from bypassing the requirement + * need_hands - Whether you need hands to use this + * floor_okay - Whether mobility flags should be checked for MOBILITY_UI to use. + */ +/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE) + return diff --git a/code/modules/reagents/Chemistry-Readme.dm b/code/modules/reagents/chemistry/_readme.dm similarity index 100% rename from code/modules/reagents/Chemistry-Readme.dm rename to code/modules/reagents/chemistry/_readme.dm diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/chemistry/chemical_reactions.dm similarity index 95% rename from code/modules/reagents/Chemistry-Recipes.dm rename to code/modules/reagents/chemistry/chemical_reactions.dm index e28a49e9200..67aeb047944 100644 --- a/code/modules/reagents/Chemistry-Recipes.dm +++ b/code/modules/reagents/chemistry/chemical_reactions.dm @@ -1,15 +1,3 @@ -//helper that ensures the reaction rate holds after iterating -//Ex. REACTION_RATE(0.3) means that 30% of the reagents will react each chemistry tick (~2 seconds by default). -#define REACTION_RATE(rate) (1.0 - (1.0-rate)**(1.0/PROCESS_REACTION_ITER)) - -//helper to define reaction rate in terms of half-life -//Ex. -//HALF_LIFE(0) -> Reaction completes immediately (default chems) -//HALF_LIFE(1) -> Half of the reagents react immediately, the rest over the following ticks. -//HALF_LIFE(2) -> Half of the reagents are consumed after 2 chemistry ticks. -//HALF_LIFE(3) -> Half of the reagents are consumed after 3 chemistry ticks. -#define HALF_LIFE(ticks) (ticks? 1.0 - (0.5)**(1.0/(ticks*PROCESS_REACTION_ITER)) : 1.0) - /datum/chemical_reaction var/name = null var/id = null @@ -35,7 +23,7 @@ var/log_is_important = 0 // If this reaction should be considered important for logging. Important recipes message admins when mixed, non-important ones just log to file. -/datum/chemical_reaction/proc/can_happen(var/datum/reagents/holder) +/datum/chemical_reaction/proc/can_happen(datum/reagents/holder) //check that all the required reagents are present if(!holder.has_all_reagents(required_reagents)) return 0 diff --git a/code/modules/reagents/Chemistry-Colours.dm b/code/modules/reagents/chemistry/colors.dm similarity index 66% rename from code/modules/reagents/Chemistry-Colours.dm rename to code/modules/reagents/chemistry/colors.dm index 6b8a96062e9..ace030e3bfe 100644 --- a/code/modules/reagents/Chemistry-Colours.dm +++ b/code/modules/reagents/chemistry/colors.dm @@ -1,3 +1,25 @@ +/proc/mix_color_from_reagents(list/reagent_list) + if(!istype(reagent_list)) + return + + var/mixcolor + var/vol_counter = 0 + var/vol_temp + + for(var/datum/reagent/R in reagent_list) + vol_temp = R.volume + vol_counter += vol_temp + + if(!mixcolor) + mixcolor = R.color + + else if (length(mixcolor) >= length(R.color)) + mixcolor = BlendRGB(mixcolor, R.color, vol_temp/vol_counter) + else + mixcolor = BlendRGB(R.color, mixcolor, vol_temp/vol_counter) + + return mixcolor + /datum/reagents/proc/get_color() if(!reagent_list || !reagent_list.len) return "#ffffffff" diff --git a/code/modules/reagents/Chemistry-Reagents-Helpers.dm b/code/modules/reagents/chemistry/helpers.dm similarity index 100% rename from code/modules/reagents/Chemistry-Reagents-Helpers.dm rename to code/modules/reagents/chemistry/helpers.dm diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/chemistry/holder.dm similarity index 93% rename from code/modules/reagents/Chemistry-Holder.dm rename to code/modules/reagents/chemistry/holder.dm index 52a4e3fbd7e..d595790528f 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -1,5 +1,3 @@ -///when processing a reaction, iterate this many times -#define PROCESS_REACTION_ITER 5 /datum/reagents var/list/datum/reagent/reagent_list = list() var/total_volume = 0 @@ -293,11 +291,13 @@ /* Holder-to-atom and similar procs */ -//The general proc for applying reagents to things. This proc assumes the reagents are being applied externally, -//not directly injected into the contents. It first calls touch, then the appropriate trans_to_*() or splash_mob(). -//If for some reason touch effects are bypassed (e.g. injecting stuff directly into a reagent container or person), -//call the appropriate trans_to_*() proc. -/datum/reagents/proc/trans_to(var/atom/target, var/amount = 1, var/multiplier = 1, var/copy = 0) +/** + * The general proc for applying reagents to things. This proc assumes the reagents are being applied externally, + * not directly injected into the contents. It first calls touch, then the appropriate trans_to_*() or splash_mob(). + * If for some reason touch effects are bypassed (e.g. injecting stuff directly into a reagent container or person), + * call the appropriate trans_to_*() proc. + */ +/datum/reagents/proc/trans_to(atom/target, amount = 1, multiplier = 1, copy = 0) touch(target) //First, handle mere touch effects if(ismob(target)) @@ -417,7 +417,8 @@ R.touch_turf(target, amount) return -/datum/reagents/proc/trans_to_obj(var/obj/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Objects may or may not; if they do, it's probably a beaker or something and we need to transfer properly; otherwise, just touch. +/// Objects may or may not; if they do, it's probably a beaker or something and we need to transfer properly; otherwise, just touch. +/datum/reagents/proc/trans_to_obj(var/obj/target, var/amount = 1, var/multiplier = 1, var/copy = 0) if(!target) return @@ -495,3 +496,18 @@ for(var/datum/reagent/R in cached_reagents) R.on_update (A) update_total() + +// I wrote this while :headempty: and I'm not sure if it's correct. @Zandario +/datum/reagents/proc/can_reactions_happen() + var/do_happen = FALSE + var/list/eligible_reactions = list() + for(var/i in reagent_list) + var/datum/reagent/R = i + if(SSchemistry.chemical_reactions_by_reagent[R.id]) + eligible_reactions |= SSchemistry.chemical_reactions_by_reagent[R.id] + + for(var/i in eligible_reactions) + var/datum/chemical_reaction/C = i + if(C.can_happen(src)) + do_happen = TRUE + return do_happen diff --git a/code/modules/reagents/Chemistry-Logging.dm b/code/modules/reagents/chemistry/logging.dm similarity index 100% rename from code/modules/reagents/Chemistry-Logging.dm rename to code/modules/reagents/chemistry/logging.dm diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/chemistry/machinery.dm similarity index 99% rename from code/modules/reagents/Chemistry-Machinery.dm rename to code/modules/reagents/chemistry/machinery.dm index 6ad96cd81c9..80b57dc0564 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/chemistry/machinery.dm @@ -284,7 +284,7 @@ It may also identify the liquid contents of unknown objects." description_info = "This machine will try to tell you what reagents are inside of something capable of holding reagents. \ It is also used to 'identify' specific reagent-based objects with their properties obscured from inspection by normal means." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "chem_analyzer" density = TRUE anchored = TRUE diff --git a/code/modules/reagents/Chemistry-Metabolism.dm b/code/modules/reagents/chemistry/metabolism.dm similarity index 100% rename from code/modules/reagents/Chemistry-Metabolism.dm rename to code/modules/reagents/chemistry/metabolism.dm diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/chemistry/reagents.dm similarity index 97% rename from code/modules/reagents/Chemistry-Reagents.dm rename to code/modules/reagents/chemistry/reagents.dm index 31cef3e9acf..415bb4cded8 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -1,4 +1,11 @@ +GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) +/proc/build_name2reagent() + . = list() + for (var/t in subtypesof(/datum/reagent)) + var/datum/reagent/R = t + if (length(initial(R.name))) + .[ckey(initial(R.name))] = t /datum/reagent diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Core.dm similarity index 100% rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm rename to code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Core.dm diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Dispenser.dm similarity index 100% rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm rename to code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Dispenser.dm diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Food-Drinks.dm similarity index 100% rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm rename to code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Food-Drinks.dm diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Medicine.dm similarity index 100% rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm rename to code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Medicine.dm diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Modifiers.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Modifiers.dm similarity index 100% rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Modifiers.dm rename to code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Modifiers.dm diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Other.dm similarity index 100% rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm rename to code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Other.dm diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Toxins.dm similarity index 100% rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm rename to code/modules/reagents/chemistry/reagents/Chemistry-Reagents-Toxins.dm diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Topical.dm b/code/modules/reagents/chemistry/reagents/Chemistry-Topical.dm similarity index 96% rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Topical.dm rename to code/modules/reagents/chemistry/reagents/Chemistry-Topical.dm index 8d3ef21c2b5..3e90cd6694b 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Topical.dm +++ b/code/modules/reagents/chemistry/reagents/Chemistry-Topical.dm @@ -7,7 +7,7 @@ description = "A gel meant to be applied to the skin." taste_description = "Sourness" taste_mult = 2 - + metabolism = REM / 2//The skin is not directly connected to any filter organs so reagents are removed much slower overdose = REAGENTS_OVERDOSE //Usually we want topicals to overdose just as other chems do. @@ -30,10 +30,10 @@ else//or half the reagent passes through into blood(rest is filtered off) and alittle bit affects the inner skin affect_blood(M, alien, removed/2) affect_touch(M, alien, removed/10) - + /datum/reagent/topical/affect_touch(mob/living/carbon/M, alien, removed) M.add_chemical_effect(CE_PAINKILLER, 1)//just so there is something here... - + /datum/reagent/topical/bicarilaze name = "Bicarilaze" id = "bicarilaze" @@ -112,7 +112,7 @@ if(world.time > (data + (60*10))) data = world.time to_chat(M, "You feel like all your nerves are itching.") - + /datum/reagent/topical/neurolaze/affect_blood(mob/living/carbon/M, alien, removed) if(alien != IS_DIONA) M.apply_damage(5 * removed, HALLOSS)//holodeck boxing glove damage @@ -151,7 +151,7 @@ /datum/reagent/topical/cleansalaze/affect_touch(mob/living/carbon/M, alien, removed) if(alien != IS_DIONA) M.radiation = max(M.radiation - 15 * removed, 0)//Half as potent as hyroaline - + /datum/reagent/topical/lotion//Because chemistry should have some recreational uses name = "Lotion" id = "lotion" @@ -182,55 +182,55 @@ /obj/item/reagent_containers/glass/bottle/inaprovalaze name = "Inaprovalaze bottle" desc = "A small bottle of Inaprovalaze. Do NOT drink." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-2" prefill = list("inaprovalaze" = 60) /obj/item/reagent_containers/glass/bottle/bicarilaze name = "Bicarilaze bottle" desc = "A small bottle of Bicarilaze. Do NOT drink." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-2" prefill = list("bicarilaze" = 60) /obj/item/reagent_containers/glass/bottle/kelotalaze name = "Kelotalaze bottle" desc = "A small bottle of Kelotalaze. Do NOT drink." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-2" prefill = list("kelotalaze" = 60) /obj/item/reagent_containers/glass/bottle/tricoralaze name = "Tricoralaze bottle" desc = "A small bottle of Tricoralaze. Do NOT drink." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-2" prefill = list("tricoralaze" = 60) /obj/item/reagent_containers/glass/bottle/neurolaze name = "Neurolaze bottle" desc = "A small bottle of Neurolaze. Do NOT drink." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-2" prefill = list("neurolaze" = 60) /obj/item/reagent_containers/glass/bottle/sterilaze name = "Sterilaze bottle" desc = "A small bottle of Sterilaze. Do NOT drink." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-2" prefill = list("sterilaze" = 60) /obj/item/reagent_containers/glass/bottle/cleansalaze name = "Cleansalaze bottle" desc = "A small bottle of Cleansalaze. Do NOT drink." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-2" prefill = list("cleansalaze" = 60) /obj/item/reagent_containers/glass/bottle/lotion name = "Lotion bottle" desc = "A small bottle of Lotion. Do NOT drink." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-2" prefill = list("lotion" = 60) diff --git a/code/modules/reagents/exposedprocs.dm b/code/modules/reagents/exposedprocs.dm index ffee71dc0e8..28fbe79acca 100644 --- a/code/modules/reagents/exposedprocs.dm +++ b/code/modules/reagents/exposedprocs.dm @@ -12,7 +12,7 @@ if(!src) return reagents.trans_to_obj(D, amount_per_transfer_from_this) - D.set_color() + D.color = mix_color_from_reagents(D.reagents.reagent_list) D.set_up(my_target, spray_size, delay) return @@ -34,7 +34,7 @@ return playsound(src.loc, 'sound/effects/spray2.ogg', 50, 1, -6) reagents.trans_to_obj(D, amount_per_transfer_from_this) - D.set_color() + D.color = mix_color_from_reagents(D.reagents.reagent_list) spray_size ? null : (spray_size = rand(6, 8)) D.set_up(my_target, spray_size, delay) return diff --git a/code/modules/reagents/machinery/chem_master.dm b/code/modules/reagents/machinery/chem_master.dm index 872dd9d00d0..de2684a6fa3 100644 --- a/code/modules/reagents/machinery/chem_master.dm +++ b/code/modules/reagents/machinery/chem_master.dm @@ -1,37 +1,81 @@ +//TODO: We don't have check_reactions or something like it, so we can't prevent idiot transfers. @Zandario /obj/machinery/chem_master name = "ChemMaster 3000" desc = "Used to seperate and package chemicals in to autoinjectors, lollipops, patches, pills, or bottles. Warranty void if used to create Space Drugs." density = TRUE anchored = TRUE - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "mixer0" + base_icon_state = "mixer" circuit = /obj/item/circuitboard/chem_master use_power = USE_POWER_IDLE idle_power_usage = 20 + flags = OPENCONTAINER + clicksound = "button" + + /// Input reagents container. var/obj/item/reagent_containers/beaker = null - var/obj/item/storage/pill_bottle/loaded_pill_bottle = null - var/mode = 0 - var/condi = 0 + /// Pill pill_bottle for newly created pills. + var/obj/item/storage/pill_bottle/pill_bottle = null var/useramount = 15 // Last used amount var/pillamount = 10 var/lolliamount = 5 var/autoamount = 5 - var/list/bottle_styles - var/bottlesprite = 1 - var/pillsprite = 1 - var/lollisprite = 1 - var/autosprite = 1 var/max_pill_count = 20 var/max_lolli_count = 10 var/max_auto_count = 5 var/printing = FALSE - flags = OPENCONTAINER - clicksound = "button" + var/autosprite = TRUE + + /// Current UI screen. On the moment of writing this comment there were two: 'home' - main screen, and 'analyze' - info about specific reagent + var/screen = "home" + /// Info to display on 'analyze' screen + var/analyze_vars[0] + + /// Whether separated reagents should be moved back to container or destroyed. 1 - move, 0 - destroy + var/mode = 1 + /// Decides what UI to show. If TRUE shows UI of CondiMaster, if FALSE - ChemMaster + var/condi = FALSE + + /// Currently selected pill style. + var/chosen_pill_style = 1 + /// List of available pill styles for UI + var/list/pill_styles + + /// Currently selected pill_bottle style. + var/chosen_bottle_style = 1 + /// List of available pill_bottle styles for UI + var/list/bottle_styles + + /// Currently selected patch style. + var/chosen_patch_style = DEFAULT_PATCH_STYLE + /// List of available patch styles for UI + var/list/patch_styles + + /// Currently selected condi style. + var/chosen_condi_style = CONDIMASTER_STYLE_AUTO + /// List of available condi styles for UI + var/list/condi_styles + +/obj/machinery/chem_master/condimaster + name = "CondiMaster 3000" + condi = TRUE /obj/machinery/chem_master/Initialize(mapload, newdir) . = ..() - default_apply_parts() create_reagents(1000) + default_apply_parts() + +/obj/machinery/chem_master/Destroy() + QDEL_NULL(beaker) + QDEL_NULL(pill_bottle) + return ..() + +/obj/machinery/chem_master/RefreshParts() + . = ..() + reagents.maximum_volume = 0 + for(var/obj/item/reagent_containers/glass/beaker/B in component_parts) + reagents.maximum_volume += B.reagents.maximum_volume /obj/machinery/chem_master/legacy_ex_act(severity) switch(severity) @@ -43,41 +87,65 @@ qdel(src) return -/obj/machinery/chem_master/update_icon() - icon_state = "mixer[beaker ? "1" : "0"]" +/obj/machinery/chem_master/update_icon_state() + icon_state = "[base_icon_state][beaker ? 1 : 0][(machine_stat & BROKEN) ? "_b" : (powered() ? null : "_nopower")]" + return ..() -/obj/machinery/chem_master/attackby(var/obj/item/B as obj, var/mob/user as mob) +/obj/machinery/chem_master/update_overlays() + . = ..() + if(machine_stat & BROKEN) + . += "waitlight" - if(istype(B, /obj/item/reagent_containers/glass) || istype(B, /obj/item/reagent_containers/food)) +/obj/machinery/chem_master/blob_act(obj/structure/blob/B) + if (prob(50)) + qdel(src) +/obj/machinery/chem_master/attackby(obj/item/I, mob/user, params) + if(default_unfasten_wrench(user, I, 20)) + return + else if(default_deconstruction_screwdriver(user, I)) + return + + else if(default_deconstruction_crowbar(user, I)) + return + + if(is_reagent_container(I) && !(I.item_flags & ATOM_ABSTRACT) && I.is_open_container()) + . = TRUE // no afterattack + if(panel_open) + to_chat(user, SPAN_WARNING("You can't use the [src.name] while its panel is opened!")) + return if(src.beaker) to_chat(user, "\A [beaker] is already loaded into the machine.") return - if(!user.attempt_insert_item_for_installation(B, src)) - return - src.beaker = B - to_chat(user, "You add \the [B] to the machine.") - update_icon() - - else if(istype(B, /obj/item/storage/pill_bottle)) - - if(src.loaded_pill_bottle) - to_chat(user, "A \the [loaded_pill_bottle] s already loaded into the machine.") - return + var/obj/item/reagent_containers/B = I + . = TRUE // no afterattack if(!user.attempt_insert_item_for_installation(B, src)) return - src.loaded_pill_bottle = B - to_chat(user, "You add \the [loaded_pill_bottle] into the dispenser slot.") + replace_beaker(user, B) + to_chat(user, SPAN_NOTICE("You add [B] to [src].")) + ui_interact(user) + update_appearance() - else if(default_unfasten_wrench(user, B, 20)) - return - if(default_deconstruction_screwdriver(user, B)) - return - if(default_deconstruction_crowbar(user, B)) - return + else if(!condi && istype(I, /obj/item/storage/pill_bottle)) + if(pill_bottle) + to_chat(user, SPAN_WARNING("A pill pill_bottle is already loaded into [src]!")) + return + if(!user.attempt_insert_item_for_installation(I, src)) + return + pill_bottle = I + to_chat(user, SPAN_NOTICE("You add [I] into the dispenser slot.")) + ui_interact(user) + else + return ..() - return +/obj/machinery/chem_master/on_deconstruction() + replace_beaker() + if(pill_bottle) + pill_bottle.forceMove(drop_location()) + adjust_item_drop_location(pill_bottle) + pill_bottle = null + return ..() /obj/machinery/chem_master/attack_hand(mob/user) if(machine_stat & BROKEN) @@ -85,9 +153,62 @@ user.set_machine(src) ui_interact(user) +/** + * Handles process of moving input reagents containers in/from machine + * + * When called checks for previously inserted beaker and gives it to user. + * Then, if new_beaker provided, places it into src.beaker. + * Returns `boolean`. TRUE if user provided (ignoring whether threre was any beaker change) and FALSE if not. + * + * Arguments: + * * user - Mob that initialized replacement, gets previously inserted beaker if there's any + * * new_beaker - New beaker to insert. Optional + */ +/obj/machinery/chem_master/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker) + if(!user) + return FALSE + if(beaker) + try_put_in_hand(beaker, user) + beaker = null + if(new_beaker) + beaker = new_beaker + update_appearance() + return TRUE + +/obj/machinery/chem_master/proc/load_styles() + /// Calculate the span tags and ids fo all the available pill icons. + var/datum/asset/spritesheet/simple/pill_assets = get_asset_datum(/datum/asset/spritesheet/simple/pills) + pill_styles = list() + for (var/x in 1 to PILL_STYLE_COUNT) + var/list/pill_style_list = list() + pill_style_list["id"] = x + pill_style_list["className"] = pill_assets.icon_class_name("pill[x]") + pill_styles += list(pill_style_list) + + var/datum/asset/spritesheet/simple/bottle_assets = get_asset_datum(/datum/asset/spritesheet/simple/bottles) + bottle_styles = list() + for (var/x in 1 to BOTTLE_STYLE_COUNT) + var/list/bottle_style_list = list() + bottle_style_list["id"] = x + bottle_style_list["className"] = bottle_assets.icon_class_name("bottle[x]") + bottle_styles += list(bottle_style_list) + + var/datum/asset/spritesheet/simple/patches_assets = get_asset_datum(/datum/asset/spritesheet/simple/patches) + patch_styles = list() + for (var/raw_patch_style in PATCH_STYLE_LIST) + //adding className for use in UI + var/list/patch_style = list() + patch_style["id"] = raw_patch_style + patch_style["className"] = patches_assets.icon_class_name(raw_patch_style) + patch_styles += list(patch_style) + + condi_styles = strip_condi_styles_to_icons(get_condi_styles()) + /obj/machinery/chem_master/ui_assets(mob/user) return list( - get_asset_datum(/datum/asset/simple/namespaced/chem_master), + get_asset_datum(/datum/asset/spritesheet/simple/pills), + get_asset_datum(/datum/asset/spritesheet/simple/bottles), + get_asset_datum(/datum/asset/spritesheet/simple/patches), ) /obj/machinery/chem_master/ui_interact(mob/user, datum/tgui/ui = null) @@ -96,470 +217,306 @@ ui = new(user, src, "ChemMaster", name) ui.open() -/** - * Display the NanoUI window for the chem master. - * - * See NanoUI documentation for details. - */ /obj/machinery/chem_master/ui_data(mob/user) var/list/data = list() - data["condi"] = condi + data["mode"] = mode + data["condi"] = condi + data["screen"] = screen + data["analyzeVars"] = analyze_vars - data["loaded_pill_bottle"] = !!loaded_pill_bottle - if(loaded_pill_bottle) - data["loaded_pill_bottle_name"] = loaded_pill_bottle.name - data["loaded_pill_bottle_contents_len"] = loaded_pill_bottle.contents.len - data["loaded_pill_bottle_storage_slots"] = loaded_pill_bottle.max_storage_space + data["chosen_pill_style"] = chosen_pill_style + data["chosen_bottle_style"] = chosen_bottle_style + data["chosen_patch_style"] = chosen_patch_style + data["chosen_condi_style"] = chosen_condi_style - data["beaker"] = !!beaker + data["auto_condi_style"] = CONDIMASTER_STYLE_AUTO + + data["is_pill_bottle_loaded"] = pill_bottle ? TRUE : FALSE + if(pill_bottle) + data["pill_bottle_current_amount"] = pill_bottle.contents.len + data["pill_bottle_max_amount"] = pill_bottle.max_storage_space + + data["is_beaker_loaded"] = beaker ? TRUE : FALSE + data["beaker_current_volume"] = beaker ? round(beaker.reagents.total_volume, 0.01) : null + data["beaker_max_volume"] = beaker ? beaker.volume : null + + var/beaker_contents[0] if(beaker) - var/list/beaker_reagents_list = list() - data["beaker_reagents"] = beaker_reagents_list for(var/datum/reagent/R in beaker.reagents.reagent_list) - beaker_reagents_list[++beaker_reagents_list.len] = list("name" = R.name, "volume" = R.volume, "description" = R.description, "id" = R.id) + beaker_contents.Add(list(list( //! list in a list because Byond merges the first list... + "name" = R.name, + "volume" = round(R.volume, 0.01), + "description" = R.description, + "id" = R.id, + ))) + data["beaker_contents"] = beaker_contents - var/list/buffer_reagents_list = list() - data["buffer_reagents"] = buffer_reagents_list + var/buffer_contents[0] + if(reagents.total_volume) for(var/datum/reagent/R in reagents.reagent_list) - buffer_reagents_list[++buffer_reagents_list.len] = list("name" = R.name, "volume" = R.volume, "id" = R.id, "description" = R.description) - - data["pillsprite"] = pillsprite - data["bottlesprite"] = bottlesprite - data["lollisprite"] = lollisprite - data["autosprite"] = autosprite - data["mode"] = mode - data["printing"] = printing - - // Transfer modal information if there is one - data["modal"] = ui_modal_data(src) + buffer_contents.Add(list(list( //! ^ + "name" = R.name, + "volume" = round(R.volume, 0.01), + "description" = R.description, + "id" = R.id, + ))) + data["buffer_contents"] = buffer_contents return data -/** - * Called in ui_act() to process modal actions - * - * Arguments: - * * action - The action passed by tgui - * * params - The params passed by tgui - */ -/obj/machinery/chem_master/proc/ui_act_modal(action, params, datum/tgui/ui, datum/ui_state/state) - . = TRUE - var/id = params["id"] // The modal's ID - var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"] - switch(ui_modal_act(src, action, params)) - if(UI_MODAL_OPEN) - switch(id) - if("analyze") - var/idx = text2num(arguments["idx"]) || 0 - var/from_beaker = text2num(arguments["beaker"]) || FALSE - var/reagent_list = from_beaker ? beaker.reagents.reagent_list : reagents.reagent_list - if(idx < 1 || idx > length(reagent_list)) - return +/obj/machinery/chem_master/ui_static_data(mob/user) + var/list/static_data = list() + //Calculated once since it'll never change + if(!pill_styles || !bottle_styles || !chosen_patch_style || !patch_styles) + load_styles() + static_data["pill_styles"] = pill_styles + static_data["bottle_styles"] = bottle_styles + static_data["patch_styles"] = patch_styles + static_data["condi_styles"] = condi_styles - var/datum/reagent/R = reagent_list[idx] - var/list/result = list("idx" = idx, "name" = R.name, "desc" = R.description) - if(!condi && istype(R, /datum/reagent/blood)) - var/datum/reagent/blood/B = R - result["blood_type"] = B.data["blood_type"] - result["blood_dna"] = B.data["blood_DNA"] + return static_data - arguments["analysis"] = result - ui_modal_message(src, id, "", null, arguments) - // if("change_pill_bottle_style") - // if(!loaded_pill_bottle) - // return - // if(!pill_bottle_wrappers) - // pill_bottle_wrappers = list( - // "CLEAR" = "Default", - // COLOR_RED = "Red", - // COLOR_GREEN = "Green", - // COLOR_PALE_BTL_GREEN = "Pale green", - // COLOR_BLUE = "Blue", - // COLOR_CYAN_BLUE = "Light blue", - // COLOR_TEAL = "Teal", - // COLOR_YELLOW = "Yellow", - // COLOR_ORANGE = "Orange", - // COLOR_PINK = "Pink", - // COLOR_MAROON = "Brown" - // ) - // var/current = pill_bottle_wrappers[loaded_pill_bottle.wrapper_color] || "Default" - // ui_modal_choice(src, id, "Please select a pill bottle wrapper:", null, arguments, current, pill_bottle_wrappers) - if("addcustom") - if(!beaker || !beaker.reagents.total_volume) - return - ui_modal_input(src, id, "Please enter the amount to transfer to buffer:", null, arguments, useramount) - if("removecustom") - if(!reagents.total_volume) - return - ui_modal_input(src, id, "Please enter the amount to transfer to [mode ? "beaker" : "disposal"]:", null, arguments, useramount) - if("create_condi_pack") - if(!condi || !reagents.total_volume) - return - ui_modal_input(src, id, "Please name your new condiment pack:", null, arguments, reagents.get_master_reagent_name(), MAX_CUSTOM_NAME_LEN) - if("create_pill") - if(condi || !reagents.total_volume) - return - var/num = round(text2num(arguments["num"] || 1)) - if(!num) - return - arguments["num"] = num - var/amount_per_pill = clamp(reagents.total_volume / num, 0, MAX_UNITS_PER_PILL) - var/default_name = "[reagents.get_master_reagent_name()] ([amount_per_pill]u)" - var/pills_text = num == 1 ? "new pill" : "[num] new pills" - ui_modal_input(src, id, "Please name your [pills_text]:", null, arguments, default_name, MAX_CUSTOM_NAME_LEN) - if("create_pill_multiple") - if(condi || !reagents.total_volume) - return - ui_modal_input(src, id, "Please enter the amount of pills to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5) - if("change_pill_style") - var/list/choices = list() - for(var/i = 1 to MAX_PILL_SPRITE) - choices += "pill[i].png" - ui_modal_bento(src, id, "Please select the new style for pills:", null, arguments, pillsprite, choices) - if("create_patch") - if(condi || !reagents.total_volume) - return - var/num = round(text2num(arguments["num"] || 1)) - if(!num) - return - arguments["num"] = num - var/amount_per_patch = clamp(reagents.total_volume / num, 0, MAX_UNITS_PER_PATCH) - var/default_name = "[reagents.get_master_reagent_name()] ([amount_per_patch]u)" - var/patches_text = num == 1 ? "new patch" : "[num] new patches" - ui_modal_input(src, id, "Please name your [patches_text]:", null, arguments, default_name, MAX_CUSTOM_NAME_LEN) - if("create_patch_multiple") - if(condi || !reagents.total_volume) - return - ui_modal_input(src, id, "Please enter the amount of patches to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5) - if("create_lollipop") - if(condi || !reagents.total_volume) - return - var/num = round(text2num(arguments["num"] || 1)) - if(!num) - return - arguments["num"] = num - var/amount_per_lolli = clamp(reagents.total_volume / num, 0, MAX_UNITS_PER_LOLLI) - var/default_name = "[reagents.get_master_reagent_name()] ([amount_per_lolli]u)" - var/lolli_text = num == 1 ? "new lollipop" : "[num] new lollipops" - ui_modal_input(src, id, "Please name your [lolli_text]:", null, arguments, default_name, MAX_CUSTOM_NAME_LEN) - if("create_lollipop_multiple") - if(condi || !reagents.total_volume) - return - ui_modal_input(src, id, "Please enter the amount of lollipops to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, lolliamount, 5) - if("create_autoinjector") - if(condi || !reagents.total_volume) - return - var/num = round(text2num(arguments["num"] || 1)) - if(!num) - return - arguments["num"] = num - var/amount_per_auto = clamp(reagents.total_volume / num, 0, MAX_UNITS_PER_AUTO) - var/default_name = "[reagents.get_master_reagent_name()] ([amount_per_auto]u)" - var/auto_text = num == 1 ? "new autoinjector" : "[num] new autoinjectors" - ui_modal_input(src, id, "Please name your [auto_text]:", null, arguments, default_name, MAX_CUSTOM_NAME_LEN) - if("create_autoinjector_multiple") - if(condi || !reagents.total_volume) - return - ui_modal_input(src, id, "Please enter the amount of autoinjectors to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, autoamount, 5) - if("create_bottle") - if(condi || !reagents.total_volume) - return - var/num = round(text2num(arguments["num"] || 1)) - if(!num) - return - arguments["num"] = num - var/amount_per_bottle = clamp(reagents.total_volume / num, 0, MAX_UNITS_PER_BOTTLE) - var/default_name = "[reagents.get_master_reagent_name()]" - var/bottles_text = num == 1 ? "new bottle" : "[num] new bottles" - ui_modal_input(src, id, "Please name your [bottles_text] ([amount_per_bottle]u in bottle):", null, arguments, default_name, MAX_CUSTOM_NAME_LEN) - if("create_bottle_multiple") - if(condi || !reagents.total_volume) - return - ui_modal_input(src, id, "Please enter the amount of bottles to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, 2, 5)//two bottles on default - if("change_bottle_style") - var/list/choices = list() - for(var/i = 1 to MAX_BOTTLE_SPRITE) - choices += "bottle-[i].png" - ui_modal_bento(src, id, "Please select the new style for bottles:", null, arguments, bottlesprite, choices) - else - return FALSE - if(UI_MODAL_ANSWER) - var/answer = params["answer"] - switch(id) - // if("change_pill_bottle_style") - // if(!pill_bottle_wrappers || !loaded_pill_bottle) // wat? - // return - // var/color = "CLEAR" - // for(var/col in pill_bottle_wrappers) - // var/col_name = pill_bottle_wrappers[col] - // if(col_name == answer) - // color = col - // break - // if(length(color) && color != "CLEAR") - // loaded_pill_bottle.wrapper_color = color - // loaded_pill_bottle.apply_wrap() - // else - // loaded_pill_bottle.wrapper_color = null - // loaded_pill_bottle.cut_overlays() - if("addcustom") - var/amount = isgoodnumber(text2num(answer)) - if(!amount || !arguments["id"]) - return - ui_act("add", list("id" = arguments["id"], "amount" = amount), ui, state) - if("removecustom") - var/amount = isgoodnumber(text2num(answer)) - if(!amount || !arguments["id"]) - return - ui_act("remove", list("id" = arguments["id"], "amount" = amount), ui, state) - if("create_condi_pack") - if(!condi || !reagents.total_volume) - return - if(!length(answer)) - answer = reagents.get_master_reagent_name() - var/obj/item/reagent_containers/pill/P = new(loc) - P.name = "[answer] pack" - P.desc = "A small condiment pack. The label says it contains [answer]." - P.icon_state = "bouilloncube"//Reskinned monkey cube - reagents.trans_to_obj(P, 10) - if("create_pill") - if(condi || !reagents.total_volume) - return - var/count = clamp(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT) - if(!count) - return - - if(!length(answer)) - answer = reagents.get_master_reagent_name() - var/amount_per_pill = clamp(reagents.total_volume / count, 0, MAX_UNITS_PER_PILL) - while(count--) - if(reagents.total_volume <= 0) - to_chat(usr, "Not enough reagents to create these pills!") - return - - var/obj/item/reagent_containers/pill/P = new(loc) - P.name = "[answer] pill" - P.pixel_x = rand(-7, 7) // Random position - P.pixel_y = rand(-7, 7) - P.icon_state = "pill[pillsprite]" - if(P.icon_state in list("pill1", "pill2", "pill3", "pill4")) // if using greyscale, take colour from reagent - P.color = reagents.get_color() - reagents.trans_to_obj(P, amount_per_pill) - // Load the pills in the bottle if there's one loaded - if(istype(loaded_pill_bottle) && length(loaded_pill_bottle.contents) < loaded_pill_bottle.max_storage_space) - P.forceMove(loaded_pill_bottle) - if("create_pill_multiple") - if(condi || !reagents.total_volume) - return - ui_act("modal_open", list("id" = "create_pill", "arguments" = list("num" = answer)), ui, state) - if("change_pill_style") - var/new_style = clamp(text2num(answer) || 0, 0, MAX_PILL_SPRITE) - if(!new_style) - return - pillsprite = new_style - if("create_patch") - if(condi || !reagents.total_volume) - return - var/count = clamp(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT) - if(!count) - return - - if(!length(answer)) - answer = reagents.get_master_reagent_name() - var/amount_per_patch = clamp(reagents.total_volume / count, 0, MAX_UNITS_PER_PATCH) - // var/is_medical_patch = chemical_safety_check(reagents) - while(count--) - if(reagents.total_volume <= 0) - to_chat(usr, "Not enough reagents to create these patches!") - return - - var/obj/item/reagent_containers/pill/patch/P = new(loc) - P.name = "[answer] patch" - P.pixel_x = rand(-7, 7) // random position - P.pixel_y = rand(-7, 7) - reagents.trans_to_obj(P, amount_per_patch) - // if(is_medical_patch) - // P.instant_application = TRUE - // P.icon_state = "bandaid_med" - if("create_patch_multiple") - if(condi || !reagents.total_volume) - return - ui_act("modal_open", list("id" = "create_patch", "arguments" = list("num" = answer)), ui, state) - if("create_lollipop") - if(condi || !reagents.total_volume) - return - var/count = clamp(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT) - if(!count) - return - - if(!length(answer)) - answer = reagents.get_master_reagent_name() - var/amount_per_lolli = clamp(reagents.total_volume / count, 0, MAX_UNITS_PER_LOLLI) - // var/is_medical_patch = chemical_safety_check(reagents) - while(count--) - if(reagents.total_volume <= 0) - to_chat(usr, "Not enough reagents to create these candies!") - return - - var/obj/item/reagent_containers/hard_candy/lollipop/L = new(loc) - L.name = "[answer] lollipop" - L.pixel_x = rand(-7, 7) // random position - L.pixel_y = rand(-7, 7) - reagents.trans_to_obj(L, amount_per_lolli) - if("create_lollipop_multiple") - if(condi || !reagents.total_volume) - return - ui_act("modal_open", list("id" = "create_lollipop", "arguments" = list("num" = answer)), ui, state) - if("create_autoinjector") - if(condi || !reagents.total_volume) - return - var/count = clamp(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT) - if(!count) - return - - if(!length(answer)) - answer = reagents.get_master_reagent_name() - var/amount_per_auto = clamp(reagents.total_volume / count, 0, MAX_UNITS_PER_AUTO) - // var/is_medical_patch = chemical_safety_check(reagents) - while(count--) - if(reagents.total_volume <= 0) - to_chat(usr, "Not enough reagents to create these injectors!") - return - - var/obj/item/reagent_containers/hypospray/autoinjector/empty/A = new(loc) - A.name = "[answer] autoinjector" - A.pixel_x = rand(-7, 7) // random position - A.pixel_y = rand(-7, 7) - reagents.trans_to_obj(A, amount_per_auto) - if("create_autoinjector_multiple") - if(condi || !reagents.total_volume) - return - ui_act("modal_open", list("id" = "create_autoinjector", "arguments" = list("num" = answer)), ui, state) - if("create_bottle") - if(condi || !reagents.total_volume) - return - var/count = clamp(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT) - if(!count) - return - - if(!length(answer)) - answer = reagents.get_master_reagent_name() - var/amount_per_bottle = clamp(reagents.total_volume / count, 0, MAX_UNITS_PER_BOTTLE) - while(count--) - if(reagents.total_volume <= 0) - to_chat(usr, "Not enough reagents to create these bottles!") - return - var/obj/item/reagent_containers/glass/bottle/P = new(loc) - P.name = "[answer] bottle" - P.pixel_x = rand(-7, 7) // random position - P.pixel_y = rand(-7, 7) - P.icon_state = "bottle-[bottlesprite]" || "bottle-1" - reagents.trans_to_obj(P, amount_per_bottle) - P.update_icon() - if("create_bottle_multiple") - if(condi || !reagents.total_volume) - return - ui_act("modal_open", list("id" = "create_bottle", "arguments" = list("num" = answer)), ui, state) - if("change_bottle_style") - var/new_style = clamp(text2num(answer) || 0, 0, MAX_BOTTLE_SPRITE) - if(!new_style) - return - bottlesprite = new_style - else - return FALSE - else - return FALSE - -/obj/machinery/chem_master/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) - if(..()) - return TRUE - - if(ui_act_modal(action, params, ui, state)) - return TRUE - - add_fingerprint(usr) - usr.set_machine(src) - - . = TRUE - switch(action) - if("toggle") - mode = !mode - if("ejectp") - if(loaded_pill_bottle) - loaded_pill_bottle.forceMove(get_turf(src)) - if(Adjacent(usr) && !issilicon(usr)) - usr.put_in_hands(loaded_pill_bottle) - loaded_pill_bottle = null - if("print") - if(printing || condi) - return - - var/idx = text2num(params["idx"]) || 0 - var/from_beaker = text2num(params["beaker"]) || FALSE - var/reagent_list = from_beaker ? beaker.reagents.reagent_list : reagents.reagent_list - if(idx < 1 || idx > length(reagent_list)) - return - - var/datum/reagent/R = reagent_list[idx] - - printing = TRUE - visible_message("[src] rattles and prints out a sheet of paper.") - // playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1) - - var/obj/item/paper/P = new /obj/item/paper(loc) - P.info = "
Chemical Analysis

" - P.info += "Time of analysis: [worldtime2stationtime(world.time)]

" - P.info += "Chemical name: [R.name]
" - if(istype(R, /datum/reagent/blood)) - var/datum/reagent/blood/B = R - P.info += "Description: N/A
Blood Type: [B.data["blood_type"]]
DNA: [B.data["blood_DNA"]]" - else - P.info += "Description: [R.description]" - P.info += "

Notes:
" - P.name = "Chemical Analysis - [R.name]" - spawn(50) - printing = FALSE - else - . = FALSE - - if(. || !beaker) +/obj/machinery/chem_master/ui_act(action, params) + . = ..() + if(.) return - . = TRUE - var/datum/reagents/R = beaker.reagents switch(action) - if("add") - var/id = params["id"] - var/amount = text2num(params["amount"]) - if(!id || !amount) - return - R.trans_id_to(src, id, amount) - if("remove") - var/id = params["id"] - var/amount = text2num(params["amount"]) - if(!id || !amount) - return - if(mode) - reagents.trans_id_to(beaker, id, amount) - else - reagents.remove_reagent(id, amount) if("eject") - if(!beaker) - return - beaker.forceMove(get_turf(src)) - if(Adjacent(usr) && !issilicon(usr)) - usr.put_in_hands(beaker) - beaker = null - reagents.clear_reagents() - update_icon() - if("create_condi_bottle") - if(!condi || !reagents.total_volume) - return - var/obj/item/reagent_containers/food/condiment/P = new(loc) - reagents.trans_to_obj(P, 50) - else + replace_beaker(usr) + return TRUE + + if("ejectPillBottle") + if(!pill_bottle) + return FALSE + pill_bottle.forceMove(drop_location()) + adjust_item_drop_location(pill_bottle) + pill_bottle = null + return TRUE + + if("transfer") + var/id = params["id"] + var/amount = text2num(params["amount"]) + var/to_container = params["to"] + // Custom amount + if (amount == -1) + amount = text2num(input( + "Enter the amount you want to transfer:", + name, "")) + if (amount == null || amount <= 0) + return FALSE + use_power(active_power_usage) + if (to_container == "beaker" && !mode) + reagents.remove_reagent(id, amount) + return TRUE + if (!beaker) + return FALSE + if (to_container == "buffer") + beaker.reagents.trans_id_to(src, id, amount) + return TRUE + if (to_container == "beaker" && mode) + reagents.trans_id_to(beaker, id, amount) + return TRUE return FALSE + if("toggleMode") + mode = !mode + return TRUE + + if("create") + if(reagents.total_volume == 0) + return FALSE + var/item_type = params["type"] + // Get amount of items + var/amount = text2num(params["amount"]) + if(amount == null) + amount = text2num(input(usr, + "Max 10. Buffer content will be split evenly.", + "How many to make?", 1)) + amount = clamp(round(amount), 0, 10) + if (amount <= 0) + return FALSE + // Get units per item + var/vol_each = text2num(params["volume"]) + var/vol_each_text = params["volume"] + var/vol_each_max = reagents.total_volume / amount + var/list/style + use_power(active_power_usage) + if (item_type == "pill") + vol_each_max = min(60, vol_each_max) + else if (item_type == "patch") + vol_each_max = min(40, vol_each_max) + else if (item_type == "pill_bottle") + vol_each_max = min(30, vol_each_max) + else if (item_type == "bottle") + vol_each_max = min(30, vol_each_max) + else if (item_type == "condiment_pack") + vol_each_max = min(10, vol_each_max) + else if (item_type == "condiment_bottle") + var/list/styles = get_condi_styles() + if (chosen_condi_style == CONDIMASTER_STYLE_AUTO || !(chosen_condi_style in styles)) + style = guess_condi_style(reagents) + else + style = styles[chosen_condi_style] + vol_each_max = min(50, vol_each_max) + else + return FALSE + if(vol_each_text == "auto") + vol_each = vol_each_max + if(vol_each == null) + vol_each = text2num(input(usr, + "Maximum [vol_each_max] units per item.", + "How many units to fill?", + vol_each_max)) + vol_each = round(clamp(vol_each, 0, vol_each_max), 0.01) + if(vol_each <= 0) + return FALSE + // Get item name + var/name = params["name"] + var/name_has_units = item_type == "pill" || item_type == "patch" + if(!name) + var/name_default + if (style && style["name"] && !style["generate_name"]) + name_default = style["name"] + else + name_default = reagents.get_master_reagent_name() + if (name_has_units) + name_default += " ([vol_each]u)" + name = tgui_input_text(usr, + "Give it a name!", + "Name", + name_default, + MAX_NAME_LEN) + if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) + return FALSE + + //! Start filling + if(item_type == "pill") + var/obj/item/reagent_containers/pill/P + var/target_loc = drop_location() + var/drop_threshold = INFINITY + if(pill_bottle) + if(pill_bottle.max_storage_space) + drop_threshold = pill_bottle.max_storage_space - pill_bottle.contents.len + target_loc = pill_bottle + for(var/i in 1 to amount) + if(i-1 < drop_threshold) + P = new/obj/item/reagent_containers/pill(target_loc) + else + P = new/obj/item/reagent_containers/pill(drop_location()) + P.name = trim("[name] pill") + if(chosen_pill_style == RANDOM_PILL_STYLE) + P.icon_state ="pill[rand(1,21)]" + else + P.icon_state = "pill[chosen_pill_style]" + if(P.icon_state in PILL_STYLE_RED) + P.desc = "A tablet or capsule, but not just any, a red one, one taken by the ones not scared of knowledge, freedom, uncertainty and the brutal truths of reality." + if(P.icon_state in PILL_STYLE_COLORABLE) // if using greyscale, take colour from reagent + P.color = reagents.get_color() + adjust_item_drop_location(P) + reagents.trans_to_obj(P, vol_each,/* transfered_by = usr*/) + return TRUE + + if(item_type == "patch") + var/obj/item/reagent_containers/pill/patch/P + for(var/i in 1 to amount) + P = new/obj/item/reagent_containers/pill/patch(drop_location()) + P.name = trim("[name] patch") + P.icon_state = chosen_patch_style + adjust_item_drop_location(P) + reagents.trans_to_obj(P, vol_each,/* transfered_by = usr*/) + return TRUE + + if(item_type == "pill_bottle") + var/obj/item/storage/pill_bottle/P + for(var/i in 1 to amount) + P = new/obj/item/storage/pill_bottle(drop_location()) + P.name = trim("[name] pill_bottle") + adjust_item_drop_location(P) + reagents.trans_to_obj(P, vol_each,/* transfered_by = usr*/) + return TRUE + + // if(item_type == "condiment_pack") + // var/obj/item/reagent_containers/condiment/pack/P + // for(var/i in 1 to amount) + // P = new/obj/item/reagent_containers/condiment/pack(drop_location()) + // P.originalname = name + // P.name = trim("[name] pack") + // P.desc = "A small condiment pack. The label says it contains [name]." + // reagents.trans_to_obj(P, vol_each,/* transfered_by = usr*/) + // return TRUE + + if(item_type == "bottle") + var/obj/item/reagent_containers/glass/bottle/P + for(var/i in 1 to amount) + P = new/obj/item/reagent_containers/glass/bottle(drop_location()) + P.name = trim("[name] bottle") + P.icon_state = "bottle[chosen_bottle_style]" + P.renamed_by_player = TRUE + reagents.trans_to_obj(P, vol_each,/* transfered_by = usr*/) + return TRUE + + if(item_type == "condiment_bottle") + var/obj/item/reagent_containers/food/condiment/P + for(var/i in 1 to amount) + P = new/obj/item/reagent_containers/food/condiment(drop_location()) + if (style) + apply_condi_style(P, style) + P.renamed_by_player = TRUE + P.name = name + reagents.trans_to_obj(P, vol_each,/* transfered_by = usr*/) + return TRUE + + return FALSE + + if("analyze") + var/datum/reagent/analyzed_reagent = GLOB.name2reagent[params["id"]] + if(analyzed_reagent) + var/state = "Unknown" + if(initial(analyzed_reagent.reagent_state) == REAGENT_SOLID) + state = "Solid" + else if(initial(analyzed_reagent.reagent_state) == REAGENT_LIQUID) + state = "Liquid" + else if(initial(analyzed_reagent.reagent_state) == REAGENT_GAS) + state = "Gas" + var/metabolization_rate = initial(analyzed_reagent.metabolism)// * (60 / SSMOBS_DT) + analyze_vars = list( + "name" = initial(analyzed_reagent.name), + "state" = state, + "color" = initial(analyzed_reagent.color), + "description" = initial(analyzed_reagent.description), + "metaRate" = metabolization_rate, + "overD" = initial(analyzed_reagent.overdose), + // "pH" = initial(analyzed_reagent.ph), + ) + screen = "analyze" + return TRUE + + if("goScreen") + screen = params["screen"] + return TRUE + + if("change_pill_style") + var/id = text2num(params["id"]) + chosen_pill_style = id + return TRUE + + if("change_bottle_style") + var/id = text2num(params["id"]) + chosen_bottle_style = id + return TRUE + + if("change_condi_style") + chosen_condi_style = params["id"] + return TRUE + + if("change_patch_style") + chosen_patch_style = params["chosen_patch_style"] + return TRUE + + return FALSE + /obj/machinery/chem_master/attack_ai(mob/user) return attack_hand(user) @@ -580,6 +537,258 @@ // all_safe = FALSE // return all_safe -/obj/machinery/chem_master/condimaster - name = "CondiMaster 3000" - condi = 1 +/obj/machinery/chem_master/adjust_item_drop_location(atom/movable/AM) // Special version for chemmasters and condimasters + if (AM == beaker) + AM.pixel_x = AM.base_pixel_x - 8 + AM.pixel_y = AM.base_pixel_y + 8 + return null + else if (AM == pill_bottle) + if (length(pill_bottle.contents)) + AM.pixel_x = AM.base_pixel_x - 13 + else + AM.pixel_x = AM.base_pixel_x - 7 + AM.pixel_y = AM.base_pixel_y - 8 + return null + else if (istype(AM, /obj/item/reagent_containers/pill)) + AM.pixel_x = AM.base_pixel_x + rand(-10, 10) + AM.pixel_y = AM.base_pixel_y + rand(-10, 10) + return null + else + var/md5 = md5(AM.name) + for (var/i in 1 to 32) + . += hex2num(md5[i]) + . = . % 9 + AM.pixel_x = AM.base_pixel_x + ((.%3)*6) + AM.pixel_y = AM.base_pixel_y - 8 + (round( . / 3)*8) + +/** + * Translates styles data into UI compatible format + * + * Expects to receive list of availables condiment styles in its complete format, and transforms them in simplified form with enough data to get UI going. + * Returns list(list("id" = , "className" = , "title" = ),..). + * + * Arguments: + * * styles - List of styles for condiment bottles in internal format: [/obj/machinery/chem_master/proc/get_condi_styles] + */ +/obj/machinery/chem_master/proc/strip_condi_styles_to_icons(list/styles) + var/list/icons = list() + for (var/s in styles) + if (styles[s] && styles[s]["className"]) + var/list/icon = list() + var/list/style = styles[s] + icon["id"] = s + icon["className"] = style["className"] + icon["title"] = "[style["name"]]\n[style["desc"]]" + icons += list(icon) + + return icons + +/** + * Defines and provides list of available condiment bottle styles + * + * Uses typelist() for styles storage after initialization. + * For fallback style must provide style with key (const) CONDIMASTER_STYLE_FALLBACK + * Returns list( + * = list( + * "icon_state" = , + * "name" = , + * "desc" = , + * ?"generate_name" = , + * ?"icon_empty" = , + * ?"fill_icon_thresholds" = , + * ?"inhand_icon_state" = , + * ?"lefthand_file" = , + * ?"righthand_file" = , + * ), + * .. + * ) + * + */ +/obj/machinery/chem_master/proc/get_condi_styles() + var/list/styles = typelist("condi_styles") + if (!styles.len) + //Possible_states has the reagent type as key and a list of, in order, the icon_state, the name and the desc as values. Was used in the condiment/on_reagent_change(changetype) to change names, descs and sprites. + styles += list( + CONDIMASTER_STYLE_FALLBACK = list( + "icon_state" = "emptycondiment", + "icon_empty" = "", + "name" = "condiment bottle", + "desc" = "Just your average condiment bottle.", + // "fill_icon_thresholds" = list(0, 10, 25, 50, 75, 100), + "generate_name" = TRUE, + ), + "enzyme" = list( + "icon_state" = "enzyme", + "icon_empty" = "", + "name" = "universal enzyme bottle", + "desc" = "Used in cooking various dishes.", + ), + "flour" = list( + "icon_state" = "flour", + "icon_empty" = "", + "name" = "flour sack", + "desc" = "A big bag of flour. Good for baking!", + ), + "mayonnaise" = list( + "icon_state" = "mayonnaise", + "icon_empty" = "", + "name" = "mayonnaise jar", + "desc" = "An oily condiment made from egg yolks.", + ), + "milk" = list( + "icon_state" = "milk", + "icon_empty" = "", + "name" = "space milk", + "desc" = "It's milk. White and nutritious goodness!", + ), + "blackpepper" = list( + "icon_state" = "peppermillsmall", + "inhand_icon_state" = "", + "icon_empty" = "emptyshaker", + "name" = "pepper mill", + "desc" = "Often used to flavor food or make people sneeze.", + ), + "rice" = list( + "icon_state" = "rice", + "icon_empty" = "", + "name" = "rice sack", + "desc" = "A big bag of rice. Good for cooking!", + ), + "sodiumchloride" = list( + "icon_state" = "saltshakersmall", + "inhand_icon_state" = "", + "icon_empty" = "emptyshaker", + "name" = "salt shaker", + "desc" = "Salt. From dead crew, presumably.", + ), + "soymilk" = list( + "icon_state" = "soymilk", + "icon_empty" = "", + "name" = "soy milk", + "desc" = "It's soy milk. White and nutritious goodness!", + ), + "soysauce" = list( + "icon_state" = "soysauce", + "inhand_icon_state" = "", + "icon_empty" = "", + "name" = "soy sauce bottle", + "desc" = "A salty soy-based flavoring.", + ), + "sugar" = list( + "icon_state" = "sugar", + "icon_empty" = "", + "name" = "sugar sack", + "desc" = "Tasty spacey sugar!", + ), + "ketchup" = list( + "icon_state" = "ketchup", + "icon_empty" = "", + "name" = "ketchup bottle", + "desc" = "You feel more American already.", + ), + "capsaicin" = list( + "icon_state" = "hotsauce", + "icon_empty" = "", + "name" = "hotsauce bottle", + "desc" = "You can almost TASTE the stomach ulcers!", + ), + "frostoil" = list( + "icon_state" = "coldsauce", + "icon_empty" = "", + "name" = "coldsauce bottle", + "desc" = "Leaves the tongue numb from its passage.", + ), + "cornoil" = list( + "icon_state" = "oliveoil", + "icon_empty" = "", + "name" = "corn oil bottle", + "desc" = "A delicious oil used in cooking. Made from corn.", + ), + "bbqsauce" = list( + "icon_state" = "bbqsauce", + "icon_empty" = "", + "name" = "bbq sauce bottle", + "desc" = "Hand wipes not included.", + ), + "peanut_butter" = list( + "icon_state" = "peanutbutter", + "icon_empty" = "", + "name" = "peanut butter jar", + "desc" = "A creamy paste made from ground peanuts.", + ), + "honey" = list( + "icon_state" = "honey", + "icon_empty" = "", + "name" = "honey bottle", + "desc" = "A cheerful bear-shaped bottle of tasty honey.", + ), + "cherryjelly" = list( + "icon_state" = "cherryjelly", + "icon_empty" = "", + "name" = "cherry jelly jar", + "desc" = "A jar of super-sweet cherry jelly.", + ), + ) + + var/list/carton_in_hand = list( + "inhand_icon_state" = "carton", + "lefthand_file" = 'icons/mob/items/lefthand_kitchen.dmi', + "righthand_file" = 'icons/mob/items/righthand_kitchen.dmi', + ) + for (var/style_reagent in list( + "flour", + "milk", + "rice", + "soymilk", + "sugar", + )) + if (style_reagent in styles) + styles[style_reagent] += carton_in_hand + + var/datum/asset/spritesheet/simple/assets = get_asset_datum(/datum/asset/spritesheet/simple/condiments) + for (var/reagent in styles) + styles[reagent]["className"] = assets.icon_class_name(reagent) + return styles + +/** + * Provides condiment bottle style based on reagents. + * + * Gets style from available by key, using last part of main reagent type (eg. "rice" for /datum/reagent/consumable/rice) as key. + * If not available returns fallback style, or null if no such thing. + * Returns list that is one of condibottle styles from [/obj/machinery/chem_master/proc/get_condi_styles] + */ +/obj/machinery/chem_master/proc/guess_condi_style(datum/reagents/reagents) + var/list/styles = get_condi_styles() + if (reagents.reagent_list.len > 0) + var/main_reagent = reagents.get_master_reagent_id() + if (main_reagent) + var/list/path = splittext("[main_reagent]", "/") + main_reagent = path[path.len] + if(main_reagent in styles) + return styles[main_reagent] + return styles[CONDIMASTER_STYLE_FALLBACK] + +/** + * Applies style to condiment bottle. + * + * Applies props provided in "style" assuming that "container" is freshly created with no styles applied before. + * User specified name for bottle applied after this method during bottle creation, + * so container.name overwritten here for consistency rather than with some purpose in mind. + * + * Arguments: + * * container - condiment bottle that gets style applied to it + * * style - assoc list, must probably one from [/obj/machinery/chem_master/proc/get_condi_styles] + */ +/obj/machinery/chem_master/proc/apply_condi_style(obj/item/reagent_containers/food/condiment/container, list/style) + container.name = style["name"] + container.desc = style["desc"] + container.icon_state = style["icon_state"] + /* + container.icon_empty = style["icon_empty"] + container.fill_icon_thresholds = style["fill_icon_thresholds"] + if ("inhand_icon_state" in style) + container.inhand_icon_state = style["inhand_icon_state"] + if (style["lefthand_file"] || style["righthand_file"]) + container.lefthand_file = style["lefthand_file"] + container.righthand_file = style["righthand_file"] + */ diff --git a/code/modules/reagents/machinery/dispenser/dispenser2.dm b/code/modules/reagents/machinery/dispenser/dispenser2.dm index c7daebf72f1..8dee2f76afd 100644 --- a/code/modules/reagents/machinery/dispenser/dispenser2.dm +++ b/code/modules/reagents/machinery/dispenser/dispenser2.dm @@ -1,6 +1,6 @@ /obj/machinery/chemical_dispenser name = "chemical dispenser" - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "dispenser" var/list/spawn_cartridges = null // Set to a list of types to spawn one of each on New() diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index a5a770f908d..7cf7053c477 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -1,7 +1,7 @@ /obj/item/reagent_containers name = "Container" desc = "..." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = null w_class = ITEMSIZE_SMALL var/amount_per_transfer_from_this = 5 diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index 9026095e239..f9a600cc51b 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -1,7 +1,7 @@ /obj/item/reagent_containers/borghypo name = "cyborg hypospray" desc = "An advanced chemical synthesizer and injection system, designed for heavy-duty medical equipment." - icon = 'icons/obj/syringe.dmi' + icon = 'icons/obj/medical/syringe.dmi' item_state = "hypo" icon_state = "borghypo" amount_per_transfer_from_this = 5 diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm index 1df56bcb91d..7916e35b0a0 100644 --- a/code/modules/reagents/reagent_containers/dropper.dm +++ b/code/modules/reagents/reagent_containers/dropper.dm @@ -4,7 +4,7 @@ /obj/item/reagent_containers/dropper name = "dropper" desc = "A dropper. Transfers up to 5 units at a time." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "dropper0" amount_per_transfer_from_this = 5 possible_transfer_amounts = list(1,2,3,4,5) diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 0d20394b73a..0b37d1dfae0 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -7,7 +7,7 @@ var/base_name = " " desc = " " var/base_desc = " " - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "null" item_state = "null" amount_per_transfer_from_this = 10 @@ -144,8 +144,9 @@ /obj/item/reagent_containers/glass/beaker name = "beaker" desc = "A beaker." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "beaker" + base_icon_state = "beaker" item_state = "beaker" matter = list(MAT_GLASS = 500) drop_sound = 'sound/items/drop/glass.ogg' @@ -174,29 +175,30 @@ overlays.Cut() if(reagents.total_volume) - var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]10") + var/image/filling = image('icons/obj/medical/reagentfillings.dmi', src, "[base_icon_state]10") var/percent = round((reagents.total_volume / volume) * 100) switch(percent) - if(0 to 9) filling.icon_state = "[icon_state]-10" - if(10 to 24) filling.icon_state = "[icon_state]10" - if(25 to 49) filling.icon_state = "[icon_state]25" - if(50 to 74) filling.icon_state = "[icon_state]50" - if(75 to 79) filling.icon_state = "[icon_state]75" - if(80 to 90) filling.icon_state = "[icon_state]80" - if(91 to INFINITY) filling.icon_state = "[icon_state]100" + if(0 to 9) filling.icon_state = "[base_icon_state]-10" + if(10 to 24) filling.icon_state = "[base_icon_state]10" + if(25 to 49) filling.icon_state = "[base_icon_state]25" + if(50 to 74) filling.icon_state = "[base_icon_state]50" + if(75 to 79) filling.icon_state = "[base_icon_state]75" + if(80 to 90) filling.icon_state = "[base_icon_state]80" + if(91 to INFINITY) filling.icon_state = "[base_icon_state]100" filling.color = reagents.get_color() overlays += filling if (!is_open_container()) - var/image/lid = image(icon, src, "lid_[initial(icon_state)]") + var/image/lid = image(icon, src, "lid_[base_icon_state]") overlays += lid /obj/item/reagent_containers/glass/beaker/large name = "large beaker" desc = "A large beaker." icon_state = "beakerlarge" + base_icon_state = "beakerlarge" matter = list(MAT_GLASS = 1000) volume = 120 amount_per_transfer_from_this = 10 @@ -207,6 +209,7 @@ name = "cryostasis beaker" desc = "A cryostasis beaker that allows for chemical storage without reactions." icon_state = "beakernoreact" + base_icon_state = "beakernoreact" matter = list(MAT_GLASS = 500) volume = 60 amount_per_transfer_from_this = 10 @@ -216,6 +219,7 @@ name = "bluespace beaker" desc = "A bluespace beaker, powered by experimental bluespace technology." icon_state = "beakerbluespace" + base_icon_state = "beakerbluespace" matter = list(MAT_GLASS = 5000) volume = 300 amount_per_transfer_from_this = 10 @@ -225,7 +229,8 @@ /obj/item/reagent_containers/glass/beaker/vial name = "vial" desc = "A small glass vial." - icon_state = "vial" + icon_state = "vial0" + base_icon_state = "vial" matter = list(MAT_GLASS = 250) volume = 30 w_class = ITEMSIZE_TINY @@ -247,6 +252,7 @@ name = "bucket" icon = 'icons/obj/janitor.dmi' icon_state = "bucket" + base_icon_state = "bucket" item_state = "bucket" matter = list(MAT_STEEL = 200) w_class = ITEMSIZE_NORMAL @@ -302,6 +308,7 @@ name = "wooden bucket" icon = 'icons/obj/janitor.dmi' icon_state = "woodbucket" + base_icon_state = "woodbucket" item_state = "woodbucket" matter = list(MAT_WOOD = 50) w_class = ITEMSIZE_LARGE @@ -338,6 +345,7 @@ name = "water-cooler bottle" icon = 'icons/obj/vending.dmi' icon_state = "water_cooler_bottle" + base_icon_state = "water_cooler_bottle" matter = list(MAT_GLASS = 2000) w_class = ITEMSIZE_NORMAL amount_per_transfer_from_this = 20 @@ -350,6 +358,7 @@ desc = "A small fuel canister used to refuel tools and gear in the field." icon = 'icons/obj/tank.dmi' icon_state = "portable_fuelcan" + base_icon_state = "portable_fuelcan" matter = list("metal" = 2000) w_class = ITEMSIZE_SMALL amount_per_transfer_from_this = 10 @@ -377,6 +386,7 @@ name = "miniature fuel canister" desc = "A tiny fuel canister used to refuel tools and gear in the field. Useful for single recharges." icon_state = "portable_fuelcan_tiny" + base_icon_state = "portable_fuelcan_tiny" matter = list("metal" = 500) w_class = ITEMSIZE_TINY volume = 20 @@ -385,6 +395,7 @@ name = "stone mortar" desc = "A hand-crafted stone mortar, designed to hold ground up herbs and reagents." icon_state = "stonebeaker" + base_icon_state = "stonebeaker" //Vials /obj/item/reagent_containers/glass/beaker/vial/bicaridine diff --git a/code/modules/reagents/reagent_containers/glass/bottle_vr.dm b/code/modules/reagents/reagent_containers/glass/bottle_vr.dm index 765d3095e28..1b7563bb629 100644 --- a/code/modules/reagents/reagent_containers/glass/bottle_vr.dm +++ b/code/modules/reagents/reagent_containers/glass/bottle_vr.dm @@ -1,13 +1,13 @@ /obj/item/reagent_containers/glass/bottle/ickypak name = "ickypak bottle" desc = "A small bottle of ickypak. The smell alone makes you gag." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-3" prefill = list("ickypak" = 60) /obj/item/reagent_containers/glass/bottle/unsorbitol name = "unsorbitol bottle" desc = "A small bottle of unsorbitol. Sickeningly sweet." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-3" prefill = list("unsorbitol" = 60) diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 3173747d602..4c2eeba376f 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -5,7 +5,7 @@ /obj/item/reagent_containers/hypospray name = "hypospray" desc = "The DeForest Medical Corporation hypospray is a sterile, air-needle autoinjector for rapid administration of drugs to patients." - icon = 'icons/obj/syringe.dmi' + icon = 'icons/obj/medical/syringe.dmi' item_state = "hypo" icon_state = "hypo" amount_per_transfer_from_this = 5 diff --git a/code/modules/reagents/reagent_containers/organic.dm b/code/modules/reagents/reagent_containers/organic.dm index 2f276f75c4e..9a3d00ef5c5 100644 --- a/code/modules/reagents/reagent_containers/organic.dm +++ b/code/modules/reagents/reagent_containers/organic.dm @@ -4,7 +4,7 @@ var/base_name = " " desc = " " var/base_desc = " " - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "null" item_state = "null" amount_per_transfer_from_this = 10 diff --git a/code/modules/reagents/reagent_containers/patch.dm b/code/modules/reagents/reagent_containers/patch.dm index a1dcf95262b..21ea964af70 100644 --- a/code/modules/reagents/reagent_containers/patch.dm +++ b/code/modules/reagents/reagent_containers/patch.dm @@ -6,12 +6,11 @@ /obj/item/reagent_containers/pill/patch name = "patch" desc = "A patch." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = null + base_icon_state = "patch" item_state = "pill" - base_state = "patch" - possible_transfer_amounts = null w_class = ITEMSIZE_TINY slot_flags = SLOT_EARS @@ -19,6 +18,28 @@ var/pierce_material = FALSE // If true, the patch can be used through thick material. +//! Non-implemented Subtypes +/* +/obj/item/reagent_containers/pill/patch/libital + name = "libital patch (brute)" + desc = "A pain reliever. Does minor liver damage. Diluted with Granibitaluri." + list_reagents = list(/datum/reagent/medicine/c2/libital = 2, /datum/reagent/medicine/granibitaluri = 8) //10 iterations + icon_state = "bandaid_brute" + +/obj/item/reagent_containers/pill/patch/aiuri + name = "aiuri patch (burn)" + desc = "Helps with burn injuries. Does minor eye damage. Diluted with Granibitaluri." + list_reagents = list(/datum/reagent/medicine/c2/aiuri = 2, /datum/reagent/medicine/granibitaluri = 8) + icon_state = "bandaid_burn" + +/obj/item/reagent_containers/pill/patch/synthflesh + name = "synthflesh patch" + desc = "Helps with brute and burn injuries. Slightly toxic." + list_reagents = list(/datum/reagent/medicine/c2/synthflesh = 20) + icon_state = "bandaid_both" +*/ +//! End ofNon-implemented Subtypes + /obj/item/reagent_containers/pill/patch/attack(mob/M as mob, mob/user as mob) var/mob/living/L = user @@ -27,22 +48,22 @@ var/mob/living/carbon/human/H = M var/obj/item/organ/external/affecting = H.get_organ(check_zone(L.zone_sel.selecting)) if(!affecting) - to_chat(user, "The limb is missing!") + to_chat(user, SPAN_WARNING("The limb is missing!")) return if(affecting.robotic >= ORGAN_ROBOT) - to_chat(user, "\The [src] won't work on a robotic limb!") + to_chat(user, SPAN_WARNING("\The [src] won't work on a robotic limb!")) return if(!H.can_inject(user, FALSE, L.zone_sel.selecting, pierce_material)) - to_chat(user, "\The [src] can't be applied through such a thick material!") + to_chat(user, SPAN_NOTICE("\The [src] can't be applied through such a thick material!")) return if(affecting.open)// you cant place Bandaids on open surgeries, why chemical patches. - to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!") + to_chat(user, SPAN_NOTICE("The [affecting.name] is cut open, you'll need more than a bandage!")) return - to_chat(H, "\The [src] is placed on your [affecting].") + to_chat(H, SPAN_NOTICE("\The [src] is placed on your [affecting].")) M.temporarily_remove_from_inventory(src, INV_OP_FORCE) if(reagents.total_volume) reagents.trans_to_mob(M, reagents.total_volume, CHEM_TOUCH) @@ -56,39 +77,43 @@ W.bandage() break;//dont bandage more than one wound, its only one patch you can have in your stack affecting.update_damages() - return 1 + return TRUE else if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/affecting = H.get_organ(check_zone(L.zone_sel.selecting)) if(!affecting) - to_chat(user, "The limb is missing!") + to_chat(user, SPAN_WARNING("The limb is missing!")) return if(affecting.robotic >= ORGAN_ROBOT) - to_chat(user, "\The [src] won't work on a robotic limb!") + to_chat(user, SPAN_NOTICE("\The [src] won't work on a robotic limb!")) return if(!H.can_inject(user, FALSE, L.zone_sel.selecting, pierce_material)) - to_chat(user, "\The [src] can't be applied through such a thick material!") + to_chat(user, SPAN_NOTICE("\The [src] can't be applied through such a thick material!")) return if(affecting.open)// you cant place Bandaids on open surgeries, why chemical patches. - to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!") + to_chat(user, SPAN_NOTICE("The [affecting.name] is cut open, you'll need more than a bandage!")) return - user.visible_message("[user] attempts to place \the [src] onto [H]`s [affecting].") + user.visible_message(SPAN_WARNING("[user] attempts to place \the [src] onto [H]`s [affecting].")) user.setClickCooldown(user.get_attack_speed(src)) if(!do_mob(user, M)) return user.temporarily_remove_from_inventory(src, INV_OP_FORCE) - user.visible_message("[user] applies \the [src] to [H].") + user.visible_message(SPAN_WARNING("[user] applies \the [src] to [H].")) + user.visible_message( + SPAN_NOTICE("[user] applies \the [src] to [H]."), + SPAN_NOTICE("You apply \the [src] to [H]."), + ) var/contained = reagentlist() - add_attack_logs(user,M,"Applied a patch containing [contained]") + add_attack_logs(user, M, "Applied a patch containing [contained]") - to_chat(H, "\The [src] is placed on your [affecting].") + to_chat(H, SPAN_NOTICE("\The [src] is placed on your [affecting].")) M.temporarily_remove_from_inventory(src, INV_OP_FORCE) if(reagents.total_volume) @@ -96,14 +121,13 @@ qdel(src) for(var/datum/wound/W in affecting.wounds) - if (W.internal)//ignore internal wounds and check the remaining + if (W.internal) //ignore internal wounds and check the remaining continue - if(W.bandaged)//already bandaged wounds dont need to be bandaged again + if(W.bandaged) //already bandaged wounds dont need to be bandaged again continue W.bandage() - break;//dont bandage more than one wound, its only one patch you can have in your stack + break //dont bandage more than one wound, its only one patch you can have in your stack affecting.update_damages() - return 1 - - return 0 + return TRUE + return FALSE diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index cd22858c95e..f232e8bdd7c 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -4,23 +4,27 @@ /obj/item/reagent_containers/pill name = "pill" desc = "A pill." - icon = 'icons/obj/chemical.dmi' - icon_state = null + icon = 'icons/obj/medical/chemical.dmi' + icon_state = "pill" + base_icon_state = "pill" item_state = "pill" drop_sound = 'sound/items/drop/food.ogg' pickup_sound = 'sound/items/pickup/food.ogg' - var/base_state = "pill" - possible_transfer_amounts = null w_class = ITEMSIZE_TINY slot_flags = SLOT_EARS volume = 60 + /// When set, we allow automatic naming on init. + var/rename_with_volume = FALSE + /obj/item/reagent_containers/pill/Initialize(mapload) . = ..() if(!icon_state) - icon_state = "[base_state][rand(1, 4)]" //preset pills only use colour changing or unique icons + icon_state = "pill[rand(1,20)]" + if(reagents.total_volume && rename_with_volume) + name += " ([reagents.total_volume]u)" /obj/item/reagent_containers/pill/attack(mob/M as mob, mob/user as mob) if(M == user) diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 3b21802540d..bfc04277e6a 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -65,7 +65,7 @@ if(!src) return reagents.trans_to_obj(D, amount_per_transfer_from_this) - D.set_color() + D.color = mix_color_from_reagents(D.reagents.reagent_list) D.set_up(my_target, spray_size, 10) return diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index d31a89fc469..2ec0ad02936 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -5,7 +5,7 @@ /obj/item/reagent_containers/syringe name = "syringe" desc = "A syringe." - icon = 'icons/obj/syringe.dmi' + icon = 'icons/obj/medical/syringe.dmi' item_state = "syringe_0" icon_state = "0" matter = list(MAT_GLASS = 150) diff --git a/code/modules/reagents/reagent_containers/syringes_vr.dm b/code/modules/reagents/reagent_containers/syringes_vr.dm index 5a4cacf6243..4298757eb24 100644 --- a/code/modules/reagents/reagent_containers/syringes_vr.dm +++ b/code/modules/reagents/reagent_containers/syringes_vr.dm @@ -1,5 +1,3 @@ -#define SYRINGE_CAPPED 10 - /obj/item/reagent_containers/syringe icon = 'icons/goonstation/objects/syringe_vr.dmi' mode = SYRINGE_CAPPED //Override diff --git a/code/modules/species/species.dm b/code/modules/species/species.dm index 02a4c025460..39e8fbc40ea 100644 --- a/code/modules/species/species.dm +++ b/code/modules/species/species.dm @@ -155,6 +155,7 @@ /// Name for the species' blood. var/blood_name = "blood" /// Initial blood volume. + /// TODO: Put this on living so this is moreso an override. @Zandario var/blood_volume = 560 /// Multiplier for how fast a species bleeds out. Higher = Faster var/bloodloss_rate = 1 diff --git a/code/modules/xenoarcheaology/artifacts/autocloner.dm b/code/modules/xenoarcheaology/artifacts/autocloner.dm index 786c64ee469..9429d0c9ff2 100644 --- a/code/modules/xenoarcheaology/artifacts/autocloner.dm +++ b/code/modules/xenoarcheaology/artifacts/autocloner.dm @@ -1,7 +1,7 @@ /obj/machinery/auto_cloner name = "mysterious pod" desc = "It's full of a viscous liquid, but appears dark and silent." - icon = 'icons/obj/cryogenics.dmi' + icon = 'icons/obj/medical/cryogenics.dmi' icon_state = "cellold0" var/spawn_type var/time_spent_spawning = 0 diff --git a/code/modules/xenobio/items/extracts.dm b/code/modules/xenobio/items/extracts.dm index 726c6706317..e180a955b6f 100644 --- a/code/modules/xenobio/items/extracts.dm +++ b/code/modules/xenobio/items/extracts.dm @@ -140,7 +140,7 @@ /obj/item/reagent_containers/glass/bottle/metamorphic name = "Metamorphic Metal Bottle" desc = "A small bottle. Contains some really weird liquid metal." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("metamorphic" = 60) @@ -211,7 +211,7 @@ /obj/item/reagent_containers/glass/bottle/binding name = "Binding Metal Bottle" desc = "A small bottle. Contains some really weird liquid metal." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' icon_state = "bottle-4" prefill = list("binding" = 60) diff --git a/code/modules/xenobio/items/slimepotions.dm b/code/modules/xenobio/items/slimepotions.dm index 1f98f2fbaed..31e613711d1 100644 --- a/code/modules/xenobio/items/slimepotions.dm +++ b/code/modules/xenobio/items/slimepotions.dm @@ -3,7 +3,7 @@ /obj/item/slimepotion name = "slime agent" desc = "A flask containing strange, mysterious substances excreted by a slime." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/medical/chemical.dmi' w_class = ITEMSIZE_TINY origin_tech = list(TECH_BIO = 4) diff --git a/code/modules/xenobio2/machinery/gene_manipulators.dm b/code/modules/xenobio2/machinery/gene_manipulators.dm index 593a7bc72b2..e5ca40233d6 100644 --- a/code/modules/xenobio2/machinery/gene_manipulators.dm +++ b/code/modules/xenobio2/machinery/gene_manipulators.dm @@ -257,7 +257,7 @@ /obj/machinery/xenobio/editor name = "biological genetic bombarder" - icon = 'icons/obj/cryogenics.dmi' + icon = 'icons/obj/medical/cryogenics.dmi' icon_state = "cellold0" disk_needs_genes = 1 circuit = /obj/item/circuitboard/biobombarder diff --git a/icons/mob/items/lefthand_kitchen.dmi b/icons/mob/items/lefthand_kitchen.dmi new file mode 100644 index 0000000000000000000000000000000000000000..3d8843c85758efa7ae55ade36981d59b72891b80 GIT binary patch literal 2289 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 literal 0 HcmV?d00001 diff --git a/icons/obj/chempuff.dmi b/icons/obj/chempuff.dmi deleted file mode 100644 index 811c5e82142e5e63a4a5253ac054f7908bc14bc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7671 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 diff --git a/icons/obj/medical/bloodpack.dmi b/icons/obj/medical/bloodpack.dmi new file mode 100644 index 0000000000000000000000000000000000000000..fdbc5bceb9e91b7b77de0a4d81dc4e67cee197b9 GIT binary patch literal 1262 zcmVV=-0C=30i@grQAQVPt?o)hecjMp6VrUwM_7x1mwGagi5Pf}zCXPn8bCPp< zoQ6@)P?M%7ml|?{#BsAF@d~baNF4SgJcq@%RcbShA<n(deONeg3HFb}dXC@19>c7lCQWamAx28*Kstv200bUML_t(|ob6goXw*O$ zeJfJ+*7#FJDD@y&*0DcRR zgALC4v8b5RE5P$SQxxtvPRG2MvnNJI;4=WA2pfC%@5L*W@eMfCz8az+ zC4e9gD_lU#RVtOlMesb&Y+SoI(RXp!|LqJ~IElwwpAXt@6Yby1c2dU@y)`*g4A7r^cfS&%8kJds+zc*XwmW#c4chyu)*pu>O@6k1T*V1Hm)i?G+H@(?%}DibuW#7-JY1 z7=US-sMTuVoMY>$t7Cblfgpdg*~HPWui<$fip3)N64>@0&}{_yhlYmy6EHtNj|Zc9 zQoLAuK)0^`cg>(F(*gWqu+JQ&S`w}25s zTqyxuck_=%p-_k{(zb25t_w}m2x-Xi^A^DK(Mz1dFMSEPt_$0?VcRwUgpQ*4G%!9p z>kH5N!^hxpGLRCWR4N&zQppg-EiW&Jj;`za$5N7zrycIr<&(1DU`N^B0C^Bs9 z21JozW1M)T7b5>7cKl1xOaRphs75A$>I76H6F_wWs*wqxIsw(l1W=uTYGeYaPCzw! z)*p}*KS_WHe}K82L{#xhzYmD=2Z$GymSv?PLR$P%0*LT_4CRRF-$)D#$FvHS@==MPw1TV^j{pDw07*qoM6N<$g8JxD9{>OV literal 0 HcmV?d00001 diff --git a/icons/obj/bodybag.dmi b/icons/obj/medical/bodybag.dmi similarity index 100% rename from icons/obj/bodybag.dmi rename to icons/obj/medical/bodybag.dmi diff --git a/icons/obj/medical/chemical.dmi b/icons/obj/medical/chemical.dmi new file mode 100644 index 0000000000000000000000000000000000000000..533ca1100a96c5e4b181fe6bea81501a52b4c3fc GIT binary patch literal 61399 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 literal 0 HcmV?d00001 diff --git a/icons/obj/medical/chempuff.dmi b/icons/obj/medical/chempuff.dmi new file mode 100644 index 0000000000000000000000000000000000000000..012aa081a13dca13f08a9601a1cd0d404dfb56c0 GIT binary patch literal 6891 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 literal 0 HcmV?d00001 diff --git a/icons/obj/cryobag.dmi b/icons/obj/medical/cryobag.dmi similarity index 100% rename from icons/obj/cryobag.dmi rename to icons/obj/medical/cryobag.dmi diff --git a/icons/obj/Cryogenic2.dmi b/icons/obj/medical/cryogenic2.dmi similarity index 100% rename from icons/obj/Cryogenic2.dmi rename to icons/obj/medical/cryogenic2.dmi diff --git a/icons/obj/medical/cryogenics.dmi b/icons/obj/medical/cryogenics.dmi new file mode 100644 index 0000000000000000000000000000000000000000..1e34ed1477bd9b5423ea662186cba7193dfd6cb4 GIT binary patch literal 42913 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 P$^iRg7*vg|Z~Q+2-%fgC literal 0 HcmV?d00001 diff --git a/icons/obj/chemical.dmi b/icons/obj/medical/og.dmi similarity index 100% rename from icons/obj/chemical.dmi rename to icons/obj/medical/og.dmi diff --git a/icons/obj/reagentfillings.dmi b/icons/obj/medical/reagentfillings.dmi similarity index 100% rename from icons/obj/reagentfillings.dmi rename to icons/obj/medical/reagentfillings.dmi diff --git a/icons/obj/robobag.dmi b/icons/obj/medical/robobag.dmi similarity index 100% rename from icons/obj/robobag.dmi rename to icons/obj/medical/robobag.dmi diff --git a/icons/obj/rollerbed.dmi b/icons/obj/medical/rollerbed.dmi similarity index 100% rename from icons/obj/rollerbed.dmi rename to icons/obj/medical/rollerbed.dmi diff --git a/icons/obj/medical/stack_medical .dmi b/icons/obj/medical/stack_medical .dmi new file mode 100644 index 0000000000000000000000000000000000000000..4aee00431030d272f76c44428739d1b8cdf11eda GIT binary patch literal 7999 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 JDrL)%{{oHNIfDQI literal 0 HcmV?d00001 diff --git a/icons/obj/medical/surgery_table.dmi b/icons/obj/medical/surgery_table.dmi new file mode 100644 index 0000000000000000000000000000000000000000..2db30fee06d7840ea5281200ee83b1cfba7217e9 GIT binary patch literal 566 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 literal 0 HcmV?d00001 diff --git a/icons/obj/medical/syringe.dmi b/icons/obj/medical/syringe.dmi new file mode 100644 index 0000000000000000000000000000000000000000..53858ebf549bb164d36ffe32c155570b2ad7b575 GIT binary patch literal 13293 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

~>>xz1WaRb483V+4Jp-%{RgdAKcZ7 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 diff --git a/icons/UI_Icons/condiments/bbqsauce.png b/icons/runtime/assets/condiments/bbqsauce.png similarity index 100% rename from icons/UI_Icons/condiments/bbqsauce.png rename to icons/runtime/assets/condiments/bbqsauce.png diff --git a/icons/UI_Icons/condiments/coldsauce.png b/icons/runtime/assets/condiments/coldsauce.png similarity index 100% rename from icons/UI_Icons/condiments/coldsauce.png rename to icons/runtime/assets/condiments/coldsauce.png diff --git a/icons/UI_Icons/condiments/condi_empty.png b/icons/runtime/assets/condiments/condi_empty.png similarity index 100% rename from icons/UI_Icons/condiments/condi_empty.png rename to icons/runtime/assets/condiments/condi_empty.png diff --git a/icons/UI_Icons/condiments/emptycondiment.png b/icons/runtime/assets/condiments/emptycondiment.png similarity index 100% rename from icons/UI_Icons/condiments/emptycondiment.png rename to icons/runtime/assets/condiments/emptycondiment.png diff --git a/icons/UI_Icons/condiments/enzyme.png b/icons/runtime/assets/condiments/enzyme.png similarity index 100% rename from icons/UI_Icons/condiments/enzyme.png rename to icons/runtime/assets/condiments/enzyme.png diff --git a/icons/UI_Icons/condiments/flour.png b/icons/runtime/assets/condiments/flour.png similarity index 100% rename from icons/UI_Icons/condiments/flour.png rename to icons/runtime/assets/condiments/flour.png diff --git a/icons/UI_Icons/condiments/hotsauce.png b/icons/runtime/assets/condiments/hotsauce.png similarity index 100% rename from icons/UI_Icons/condiments/hotsauce.png rename to icons/runtime/assets/condiments/hotsauce.png diff --git a/icons/UI_Icons/condiments/ketchup.png b/icons/runtime/assets/condiments/ketchup.png similarity index 100% rename from icons/UI_Icons/condiments/ketchup.png rename to icons/runtime/assets/condiments/ketchup.png diff --git a/icons/UI_Icons/condiments/mayonnaise.png b/icons/runtime/assets/condiments/mayonnaise.png similarity index 100% rename from icons/UI_Icons/condiments/mayonnaise.png rename to icons/runtime/assets/condiments/mayonnaise.png diff --git a/icons/UI_Icons/condiments/milk.png b/icons/runtime/assets/condiments/milk.png similarity index 100% rename from icons/UI_Icons/condiments/milk.png rename to icons/runtime/assets/condiments/milk.png diff --git a/icons/UI_Icons/condiments/oliveoil.png b/icons/runtime/assets/condiments/oliveoil.png similarity index 100% rename from icons/UI_Icons/condiments/oliveoil.png rename to icons/runtime/assets/condiments/oliveoil.png diff --git a/icons/UI_Icons/condiments/peppermillsmall.png b/icons/runtime/assets/condiments/peppermillsmall.png similarity index 100% rename from icons/UI_Icons/condiments/peppermillsmall.png rename to icons/runtime/assets/condiments/peppermillsmall.png diff --git a/icons/UI_Icons/condiments/rice.png b/icons/runtime/assets/condiments/rice.png similarity index 100% rename from icons/UI_Icons/condiments/rice.png rename to icons/runtime/assets/condiments/rice.png diff --git a/icons/UI_Icons/condiments/saltshakersmall.png b/icons/runtime/assets/condiments/saltshakersmall.png similarity index 100% rename from icons/UI_Icons/condiments/saltshakersmall.png rename to icons/runtime/assets/condiments/saltshakersmall.png diff --git a/icons/UI_Icons/condiments/soymilk.png b/icons/runtime/assets/condiments/soymilk.png similarity index 100% rename from icons/UI_Icons/condiments/soymilk.png rename to icons/runtime/assets/condiments/soymilk.png diff --git a/icons/UI_Icons/condiments/soysauce.png b/icons/runtime/assets/condiments/soysauce.png similarity index 100% rename from icons/UI_Icons/condiments/soysauce.png rename to icons/runtime/assets/condiments/soysauce.png diff --git a/icons/UI_Icons/condiments/sugar.png b/icons/runtime/assets/condiments/sugar.png similarity index 100% rename from icons/UI_Icons/condiments/sugar.png rename to icons/runtime/assets/condiments/sugar.png diff --git a/icons/runtime/assets/medical/bottles/bottle1.png b/icons/runtime/assets/medical/bottles/bottle1.png new file mode 100644 index 0000000000000000000000000000000000000000..6821a1ed3e4adbd9456224a29cef9d8f6cfd6ed7 GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^96-#?!3HFqW}i_7QjEnx?oJHr&dIz4aw%boFyt=akR{02m-VzW@LL literal 0 HcmV?d00001 diff --git a/icons/runtime/assets/medical/bottles/bottle2.png b/icons/runtime/assets/medical/bottles/bottle2.png new file mode 100644 index 0000000000000000000000000000000000000000..9195de497d73dc84a52f3381e9e1b73a81ca0b20 GIT binary patch literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^U^WLEkTt>lKP!-8EDmyaVpw-h<|U9b*VDx@L}Oxd zjp1WEW}b?3JX%Q(Ot&vz|9bF-&WSFw{Cjs!A2@KJ;KKvQjtGB&7(-#^i47U8Jty*} z1U$35mZkBlrLnPb;jcg0GsVmIM bx0Q*ZIZCV7s3;~MXgh#0g7>k44ofy`glX(f`EcSG943U_c zTx0myj+v+89FJC#1Jmux*S{XTp>v|^+Pc`=+>hs5mv$Z8Y|OE4MrWhPfsUN5Ek@rr zhB;qU=K+GN&*M+;+41`-m)h}`H5_+EQVhjPCMPf)o1Tzh@$J#OaBa7?yXzlx-Dy?q zD%d6?**FH)!NwD$hb~| dyP;K;LG-xOKF7FiVnF9Ic)I$ztaD0e0sx(xUHJe2 literal 0 HcmV?d00001 diff --git a/icons/UI_Icons/patches/bandaid.png b/icons/runtime/assets/medical/patches/patch.png similarity index 100% rename from icons/UI_Icons/patches/bandaid.png rename to icons/runtime/assets/medical/patches/patch.png diff --git a/icons/UI_Icons/patches/bandaid_both.png b/icons/runtime/assets/medical/patches/patch_both.png similarity index 100% rename from icons/UI_Icons/patches/bandaid_both.png rename to icons/runtime/assets/medical/patches/patch_both.png diff --git a/icons/UI_Icons/patches/bandaid_brute.png b/icons/runtime/assets/medical/patches/patch_brute.png similarity index 100% rename from icons/UI_Icons/patches/bandaid_brute.png rename to icons/runtime/assets/medical/patches/patch_brute.png diff --git a/icons/UI_Icons/patches/bandaid_burn.png b/icons/runtime/assets/medical/patches/patch_burn.png similarity index 100% rename from icons/UI_Icons/patches/bandaid_burn.png rename to icons/runtime/assets/medical/patches/patch_burn.png diff --git a/icons/UI_Icons/pills/pill1.png b/icons/runtime/assets/medical/pills/pill1.png similarity index 100% rename from icons/UI_Icons/pills/pill1.png rename to icons/runtime/assets/medical/pills/pill1.png diff --git a/icons/UI_Icons/pills/pill10.png b/icons/runtime/assets/medical/pills/pill10.png similarity index 100% rename from icons/UI_Icons/pills/pill10.png rename to icons/runtime/assets/medical/pills/pill10.png diff --git a/icons/UI_Icons/pills/pill11.png b/icons/runtime/assets/medical/pills/pill11.png similarity index 100% rename from icons/UI_Icons/pills/pill11.png rename to icons/runtime/assets/medical/pills/pill11.png diff --git a/icons/UI_Icons/pills/pill12.png b/icons/runtime/assets/medical/pills/pill12.png similarity index 100% rename from icons/UI_Icons/pills/pill12.png rename to icons/runtime/assets/medical/pills/pill12.png diff --git a/icons/UI_Icons/pills/pill13.png b/icons/runtime/assets/medical/pills/pill13.png similarity index 100% rename from icons/UI_Icons/pills/pill13.png rename to icons/runtime/assets/medical/pills/pill13.png diff --git a/icons/UI_Icons/pills/pill14.png b/icons/runtime/assets/medical/pills/pill14.png similarity index 100% rename from icons/UI_Icons/pills/pill14.png rename to icons/runtime/assets/medical/pills/pill14.png diff --git a/icons/UI_Icons/pills/pill15.png b/icons/runtime/assets/medical/pills/pill15.png similarity index 100% rename from icons/UI_Icons/pills/pill15.png rename to icons/runtime/assets/medical/pills/pill15.png diff --git a/icons/UI_Icons/pills/pill16.png b/icons/runtime/assets/medical/pills/pill16.png similarity index 100% rename from icons/UI_Icons/pills/pill16.png rename to icons/runtime/assets/medical/pills/pill16.png diff --git a/icons/UI_Icons/pills/pill17.png b/icons/runtime/assets/medical/pills/pill17.png similarity index 100% rename from icons/UI_Icons/pills/pill17.png rename to icons/runtime/assets/medical/pills/pill17.png diff --git a/icons/UI_Icons/pills/pill18.png b/icons/runtime/assets/medical/pills/pill18.png similarity index 100% rename from icons/UI_Icons/pills/pill18.png rename to icons/runtime/assets/medical/pills/pill18.png diff --git a/icons/UI_Icons/pills/pill19.png b/icons/runtime/assets/medical/pills/pill19.png similarity index 100% rename from icons/UI_Icons/pills/pill19.png rename to icons/runtime/assets/medical/pills/pill19.png diff --git a/icons/UI_Icons/pills/pill2.png b/icons/runtime/assets/medical/pills/pill2.png similarity index 100% rename from icons/UI_Icons/pills/pill2.png rename to icons/runtime/assets/medical/pills/pill2.png diff --git a/icons/UI_Icons/pills/pill20.png b/icons/runtime/assets/medical/pills/pill20.png similarity index 100% rename from icons/UI_Icons/pills/pill20.png rename to icons/runtime/assets/medical/pills/pill20.png diff --git a/icons/UI_Icons/pills/pill21.png b/icons/runtime/assets/medical/pills/pill21.png similarity index 100% rename from icons/UI_Icons/pills/pill21.png rename to icons/runtime/assets/medical/pills/pill21.png diff --git a/icons/UI_Icons/pills/pill22.png b/icons/runtime/assets/medical/pills/pill22.png similarity index 100% rename from icons/UI_Icons/pills/pill22.png rename to icons/runtime/assets/medical/pills/pill22.png diff --git a/icons/UI_Icons/pills/pill3.png b/icons/runtime/assets/medical/pills/pill3.png similarity index 100% rename from icons/UI_Icons/pills/pill3.png rename to icons/runtime/assets/medical/pills/pill3.png diff --git a/icons/UI_Icons/pills/pill4.png b/icons/runtime/assets/medical/pills/pill4.png similarity index 100% rename from icons/UI_Icons/pills/pill4.png rename to icons/runtime/assets/medical/pills/pill4.png diff --git a/icons/UI_Icons/pills/pill5.png b/icons/runtime/assets/medical/pills/pill5.png similarity index 100% rename from icons/UI_Icons/pills/pill5.png rename to icons/runtime/assets/medical/pills/pill5.png diff --git a/icons/UI_Icons/pills/pill6.png b/icons/runtime/assets/medical/pills/pill6.png similarity index 100% rename from icons/UI_Icons/pills/pill6.png rename to icons/runtime/assets/medical/pills/pill6.png diff --git a/icons/UI_Icons/pills/pill7.png b/icons/runtime/assets/medical/pills/pill7.png similarity index 100% rename from icons/UI_Icons/pills/pill7.png rename to icons/runtime/assets/medical/pills/pill7.png diff --git a/icons/UI_Icons/pills/pill8.png b/icons/runtime/assets/medical/pills/pill8.png similarity index 100% rename from icons/UI_Icons/pills/pill8.png rename to icons/runtime/assets/medical/pills/pill8.png diff --git a/icons/UI_Icons/pills/pill9.png b/icons/runtime/assets/medical/pills/pill9.png similarity index 100% rename from icons/UI_Icons/pills/pill9.png rename to icons/runtime/assets/medical/pills/pill9.png diff --git a/icons/runtime/placeholder b/icons/runtime/placeholder deleted file mode 100644 index 522ee0789dd..00000000000 --- a/icons/runtime/placeholder +++ /dev/null @@ -1 +0,0 @@ -placeholder file, delete when folder used. diff --git a/tgui/docs/component-reference.md b/tgui/docs/component-reference.md index c5963e4ab0c..77c4fa38d49 100644 --- a/tgui/docs/component-reference.md +++ b/tgui/docs/component-reference.md @@ -14,6 +14,7 @@ Make sure to add new items to this list if you document new components. - [`AnimatedNumber`](#animatednumber) - [`BlockQuote`](#blockquote) - [`Box`](#box) + - [Box Units](#box-units) - [`Button`](#button) - [`Button.Checkbox`](#buttoncheckbox) - [`Button.Confirm`](#buttonconfirm) @@ -137,7 +138,7 @@ This way, `Button` can pull out the `className` generated by the `Box`. ``` -**Box Units** +#### Box Units `Box` units, like width, height and margins can be defined in two ways: @@ -222,7 +223,7 @@ Buttons allow users to take actions, and make choices, with a single click. - `selected: boolean` - Activates the button (gives it a green color). - `tooltip: string` - A fancy, boxy tooltip, which appears when hovering over the button. -- `tooltipPosition?: string` - Position of the tooltip. See [`Popper`](#Popper) for valid options. +- `tooltipPosition?: string` - Position of the tooltip. See [`Popper`](#popper) for valid options. - `ellipsis: boolean` - If button width is constrained, button text will be truncated with an ellipsis. Be careful however, because this prop breaks the baseline alignment. @@ -280,7 +281,7 @@ interface. Example (button): -``` +```dm { - const { - className, - children, - ...rest - } = props; +export const Modal = (props) => { + const { className, children, ...rest } = props; return (

{children}
diff --git a/tgui/packages/tgui/interfaces/ChemMaster.js b/tgui/packages/tgui/interfaces/ChemMaster.js deleted file mode 100644 index 633d87b04ab..00000000000 --- a/tgui/packages/tgui/interfaces/ChemMaster.js +++ /dev/null @@ -1,487 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from "../backend"; -import { Box, Button, Flex, Icon, LabeledList, Section } from "../components"; -import { Window } from "../layouts"; -import { BeakerContents } from './common/BeakerContents'; -import { ComplexModal, modalOpen, modalRegisterBodyOverride } from './common/ComplexModal'; - -const transferAmounts = [1, 5, 10, 30, 60]; -const bottleStyles = [ - "bottle.png", - "small_bottle.png", - "wide_bottle.png", - "round_bottle.png", - "reagent_bottle.png", -]; - -const analyzeModalBodyOverride = (modal, context) => { - const { act, data } = useBackend(context); - const result = modal.args.analysis; - return ( -
- - - - {result.name} - - - {(result.desc || "").length > 0 ? result.desc : "N/A"} - - {result.blood_type && ( - - - {result.blood_type} - - - {result.blood_dna} - - - )} - {!data.condi && ( -
- ); -}; - -export const ChemMaster = (props, context) => { - const { data } = useBackend(context); - const { - condi, - beaker, - beaker_reagents = [], - buffer_reagents = [], - mode, - } = data; - return ( - - - - 0} - /> - - 0} - /> - {/* */} - - - ); -}; - -const ChemMasterBeaker = (props, context) => { - const { act, data } = useBackend(context); - const { - beaker, - beakerReagents, - bufferNonEmpty, - } = props; - - let headerButton = bufferNonEmpty ? ( - act('eject')} - /> - ) : ( - - - - - - - ); -}; - -const ChemMasterProductionCondiment = (props, context) => { - const { act } = useBackend(context); - return ( - - + ))} + + )} + {!condi && ( + setPillAmount(value)} + onCreate={() => + act('create', { + type: 'pill', + amount: pillAmount, + volume: 'auto', + })} + /> + )} + {!condi && ( + + {patch_styles.map((patch) => ( + + ))} + + )} + {!condi && ( + setPatchAmount(value)} + onCreate={() => + act('create', { + type: 'patch', + amount: patchAmount, + volume: 'auto', + })} + /> + )} + {!condi && ( + + {bottle_styles.map((bottle) => ( + + ))} + + )} + {!condi && ( + setBottleAmount(value)} + onCreate={() => + act('create', { + type: 'bottle', + amount: bottleAmount, + volume: 'auto', + })} + /> + )} + {!!condi && ( + + + act('change_condi_style', { + id: auto_condi_style_chosen ? condi_styles[0].id : auto_condi_style, + })} + checked={auto_condi_style_chosen} + disabled={!condi_styles.length}> + Guess from contents + + + )} + {!!condi && !auto_condi_style_chosen && ( + + {condi_styles.map((style) => ( + + ))} + + )} + {!!condi && ( + setBottleAmount(value)} + onCreate={() => + act('create', { + type: 'condiment_bottle', + amount: bottleAmount, + volume: 'auto', + })} + /> + )} + {!!condi && ( + setPackAmount(value)} + onCreate={() => + act('create', { + type: 'condiment_pack', + amount: packAmount, + volume: 'auto', + })} + /> + )} + + ); +}; + +const AnalysisResults = (props, context) => { + const { act, data } = useBackend(context); + const { analyzeVars } = data; + return ( +
+ act('goScreen', { + screen: 'home', + })} + /> + }> + + {analyzeVars.name} + {analyzeVars.state} + {/* {analyzeVars.ph} */} + + + {analyzeVars.color} + + + {analyzeVars.description} + + + {analyzeVars.metaRate} + + + {analyzeVars.overD} + + {/* + {analyzeVars.addicD} + */} + +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/ChemPress.js b/tgui/packages/tgui/interfaces/ChemPress.js index f9df812c2b1..75d86bc8930 100644 --- a/tgui/packages/tgui/interfaces/ChemPress.js +++ b/tgui/packages/tgui/interfaces/ChemPress.js @@ -7,11 +7,13 @@ export const ChemPress = (props, context) => { const { current_volume, product_name, - pill_style, - pill_styles = [], product, min_volume, max_volume, + bottle_style, + bottle_styles = [], + pill_style, + pill_styles = [], patch_style, patch_styles = [], } = data; @@ -86,17 +88,16 @@ export const ChemPress = (props, context) => { ))} )} - {product === "patch" && ( - - {patch_styles.map(patch => ( + {!condi && ( + + {patch_styles.map((patch) => ( ))} diff --git a/tgui/packages/tgui/interfaces/common/ComplexModal.js b/tgui/packages/tgui/interfaces/common/ComplexModal.tsx similarity index 85% rename from tgui/packages/tgui/interfaces/common/ComplexModal.js rename to tgui/packages/tgui/interfaces/common/ComplexModal.tsx index d46dde0d7fd..37a97e88ffc 100644 --- a/tgui/packages/tgui/interfaces/common/ComplexModal.js +++ b/tgui/packages/tgui/interfaces/common/ComplexModal.tsx @@ -3,6 +3,14 @@ import { Box, Button, Dropdown, Flex, Input, Modal } from '../../components'; let bodyOverrides = {}; +type ModalData = { + id: number; + text: string; + type: string; + uid: string; + modal: any; +}; + /** * Sends a call to BYOND to open a modal * @param {any} context The React context @@ -10,7 +18,7 @@ let bodyOverrides = {}; * @param {object=} args The arguments to pass to the modal */ export const modalOpen = (context, id, args) => { - const { act, data } = useBackend(context); + const { act, data } = useBackend(context); const newArgs = Object.assign(data.modal ? data.modal.args : {}, args || {}); act('modal_open', { @@ -30,7 +38,7 @@ export const modalRegisterBodyOverride = (id, bodyOverride) => { }; const modalAnswer = (context, id, answer, args) => { - const { act, data } = useBackend(context); + const { act, data } = useBackend(context); if (!data.modal) { return; } @@ -68,7 +76,7 @@ const modalClose = (context, id) => { * @param {object} context */ export const ComplexModal = (props, context) => { - const { data } = useBackend(context); + const { data } = useBackend(context); if (!data.modal) { return; } @@ -87,7 +95,7 @@ export const ComplexModal = (props, context) => { icon="arrow-left" content="Cancel" color="grey" - onClick={() => modalClose(context)} + onClick={() => modalClose(context, null)} /> ); @@ -96,7 +104,7 @@ export const ComplexModal = (props, context) => { modalBody = bodyOverrides[id](data.modal, context); } else if (type === "input") { const [curValue, setCurValue] = useLocalState(context, 'curValue' + data.modal.uid.toString(), data.modal.value.toString()); - modalOnEnter = e => modalAnswer(context, id, curValue); + modalOnEnter = e => modalAnswer(context, id, curValue, null); modalBody = ( { icon="arrow-left" content="Cancel" color="grey" - onClick={() => modalClose(context)} + onClick={() => modalClose(context, null)} /> @@ -169,7 +177,7 @@ export const ComplexModal = (props, context) => { color="bad" float="left" mb="0" - onClick={() => modalAnswer(context, id, 0)} + onClick={() => modalAnswer(context, id, 0, null)} />