diff --git a/code/_globalvars/lists/reagents.dm b/code/_globalvars/lists/reagents.dm index 68d63d97934..47b1008aa8a 100644 --- a/code/_globalvars/lists/reagents.dm +++ b/code/_globalvars/lists/reagents.dm @@ -63,8 +63,6 @@ GLOBAL_LIST_INIT(blacklisted_metalgen_types, typecacheof(list( /turf/closed/indestructible, //indestructible turfs should be indestructible, metalgen transmutation to plasma allows them to be destroyed /turf/open/indestructible ))) -/// Names of human readable reagents used by plumbing UI. -GLOBAL_LIST_INIT(chemical_name_list, init_chemical_name_list()) /// Map of reagent names to its datum path GLOBAL_LIST_INIT(name2reagent, build_name2reagentlist()) @@ -81,16 +79,6 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagentlist()) return reagent_list -/// Creates an list which is indexed by reagent name . used by plumbing reaction chamber and chemical filter UI -/proc/init_chemical_name_list() - var/list/name_list = list() - - for(var/X in GLOB.chemical_reagents_list) - var/datum/reagent/Reagent = GLOB.chemical_reagents_list[X] - name_list += Reagent.name - - return sort_list(name_list) - /** * Chemical Reactions - Initialises all /datum/chemical_reaction into a list * It is filtered into multiple lists within a list. @@ -196,7 +184,19 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagentlist()) /// Builds map of reagent name to its datum path /proc/build_name2reagentlist() . = list() - for (var/datum/reagent/R as anything in subtypesof(/datum/reagent)) - var/name = initial(R.name) + + //build map with keys stored seperatly + var/list/name_to_reagent = list() + var/list/only_names = list() + for (var/datum/reagent/reagent as anything in GLOB.chemical_reagents_list) + var/name = initial(reagent.name) if (length(name)) - .[ckey(name)] = R + name_to_reagent[name] = reagent + only_names += name + + //sort keys + only_names = sort_list(only_names) + + //build map with sorted keys + for(var/name as anything in only_names) + .[name] = name_to_reagent[name] diff --git a/code/game/objects/items/devices/portable_chem_mixer.dm b/code/game/objects/items/devices/portable_chem_mixer.dm index 18458f75697..c48e9fe8f1e 100644 --- a/code/game/objects/items/devices/portable_chem_mixer.dm +++ b/code/game/objects/items/devices/portable_chem_mixer.dm @@ -4,19 +4,18 @@ icon = 'icons/obj/medical/chemical.dmi' icon_state = "portablechemicalmixer_open" worn_icon_state = "portable_chem_mixer" + equip_sound = 'sound/items/equip/toolbelt_equip.ogg' w_class = WEIGHT_CLASS_HUGE slot_flags = ITEM_SLOT_BELT - equip_sound = 'sound/items/equip/toolbelt_equip.ogg' custom_price = PAYCHECK_CREW * 10 custom_premium_price = PAYCHECK_CREW * 14 - var/obj/item/reagent_containers/beaker = null ///Creating an empty slot for a beaker that can be added to dispense into - var/amount = 30 ///The amount of reagent that is to be dispensed currently - - var/list/dispensable_reagents = list() ///List in which all currently dispensable reagents go - - ///If the UI has the pH meter shown - var/show_ph = TRUE + ///Creating an empty slot for a beaker that can be added to dispense into + var/obj/item/reagent_containers/beaker = null + ///The amount of reagent that is to be dispensed currently + var/amount = 30 + ///List in which all currently dispensable reagents go + var/list/dispensable_reagents = list() /obj/item/storage/portable_chem_mixer/Initialize(mapload) . = ..() @@ -29,45 +28,56 @@ /obj/item/reagent_containers/cup/glass/waterbottle, /obj/item/reagent_containers/condiment, )) + register_context() /obj/item/storage/portable_chem_mixer/Destroy() QDEL_NULL(beaker) return ..() +/obj/item/storage/portable_chem_mixer/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + + context[SCREENTIP_CONTEXT_CTRL_LMB] = "[atom_storage.locked ? "Un" : ""]Lock storage" + if(atom_storage.locked && !QDELETED(beaker)) + context[SCREENTIP_CONTEXT_ALT_LMB] = "Eject beaker" + + if(!isnull(held_item)) + if (!atom_storage.locked || \ + (held_item.item_flags & ABSTRACT) || \ + !is_reagent_container(held_item) || \ + !held_item.is_open_container() \ + ) + return CONTEXTUAL_SCREENTIP_SET + context[SCREENTIP_CONTEXT_LMB] = "Insert beaker" + + return CONTEXTUAL_SCREENTIP_SET + +/obj/item/storage/portable_chem_mixer/examine(mob/user) + . = ..() + if(!atom_storage.locked) + . += span_notice("Use [EXAMINE_HINT("ctrl click")] to lock in order to use its interface.") + else + . += span_notice("Its storage is locked, use [EXAMINE_HINT("ctrl click")] to unlock it.") + if(QDELETED(beaker)) + . += span_notice("A beaker can be inserted to dispense reagents after it is locked.") + else + . += span_notice("A beaker of [beaker.reagents.maximum_volume] units capacity is inserted.") + . += span_notice("It can be ejected with [EXAMINE_HINT("alt click")].") + /obj/item/storage/portable_chem_mixer/ex_act(severity, target) - if(severity > EXPLODE_LIGHT) + return severity > EXPLODE_LIGHT ? ..() : FALSE + +/obj/item/storage/portable_chem_mixer/attackby(obj/item/weapon, mob/user, params) + if (!atom_storage.locked || \ + (weapon.item_flags & ABSTRACT) || \ + !is_reagent_container(weapon) || \ + !weapon.is_open_container() \ + ) return ..() - return FALSE - -/obj/item/storage/portable_chem_mixer/attackby(obj/item/I, mob/user, params) - if (is_reagent_container(I) && !(I.item_flags & ABSTRACT) && I.is_open_container() && atom_storage.locked) - var/obj/item/reagent_containers/B = I - . = TRUE //no afterattack - if(!user.transferItemToLoc(B, src)) - return - replace_beaker(user, B) - update_appearance() - ui_interact(user) - return - return ..() - -/** - * Updates the contents of the portable chemical mixer - * - * A list of dispensable reagents is created by iterating through each source beaker in the portable chemical beaker and reading its contents - */ -/obj/item/storage/portable_chem_mixer/proc/update_contents() - dispensable_reagents.Cut() - - for (var/obj/item/reagent_containers/B in contents) - var/key = B.reagents.get_master_reagent_id() - if (!(key in dispensable_reagents)) - dispensable_reagents[key] = list() - dispensable_reagents[key]["reagents"] = list() - dispensable_reagents[key]["reagents"] += B.reagents - - return + replace_beaker(user, weapon) + update_appearance() + return TRUE /obj/item/storage/portable_chem_mixer/update_icon_state() if(!atom_storage.locked) @@ -79,28 +89,48 @@ icon_state = "portablechemicalmixer_empty" return ..() - /obj/item/storage/portable_chem_mixer/AltClick(mob/living/user) if(!atom_storage.locked) + balloon_alert(user, "lock first to use alt eject!") return ..() if(!can_interact(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return + replace_beaker(user) update_appearance() /obj/item/storage/portable_chem_mixer/CtrlClick(mob/living/user) - if(atom_storage.locked) + if(atom_storage.locked == STORAGE_FULLY_LOCKED) atom_storage.locked = STORAGE_NOT_LOCKED + replace_beaker(user) + SStgui.close_all_uis() else atom_storage.locked = STORAGE_FULLY_LOCKED - if (!atom_storage.locked) - update_contents() - if (atom_storage.locked) atom_storage.hide_contents(usr) - replace_beaker(user) + update_appearance() - playsound(src, 'sound/items/screwdriver2.ogg', 50) - return + +/obj/item/storage/portable_chem_mixer/Exited(atom/movable/gone, direction) + . = ..() + if(gone == beaker) + beaker = null + else + update_contents() + +/// Reload dispensable reagents from new contents +/obj/item/storage/portable_chem_mixer/proc/update_contents() + dispensable_reagents.Cut() + for (var/obj/item/reagent_containers/container in contents) + var/key = container.reagents.get_master_reagent_id() + if (!(key in dispensable_reagents)) + dispensable_reagents[key] = list() + dispensable_reagents[key]["reagents"] = list() + dispensable_reagents[key]["reagents"] += container.reagents + +/obj/item/storage/portable_chem_mixer/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) + . = ..() + if(!atom_storage.locked) + update_contents() /** * Replaces the beaker of the portable chemical mixer with another beaker, or simply adds the new beaker if none is in currently @@ -111,34 +141,12 @@ * * obj/item/reagent_containers/new_beaker - The new beaker that the user wants to put into the device */ /obj/item/storage/portable_chem_mixer/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker) - if(!user) - return FALSE if(beaker) user.put_in_hands(beaker) - beaker = null if(new_beaker) + if(!user.transferItemToLoc(new_beaker, src)) + return beaker = new_beaker - return TRUE - -/obj/item/storage/portable_chem_mixer/attack_hand(mob/user, list/modifiers) - if (loc != user) - return ..() - else - if (!atom_storage.locked) - return ..() - if(atom_storage?.locked) - ui_interact(user) - return - -/obj/item/storage/portable_chem_mixer/attack_self(mob/user) - if(loc == user) - if (atom_storage.locked) - ui_interact(user) - return - else - to_chat(user, span_notice("It looks like this device can be worn as a belt for increased accessibility. A label indicates that the 'CTRL'-button on the device may be used to close it after it has been filled with bottles and beakers of chemicals.")) - return - return /obj/item/storage/portable_chem_mixer/MouseDrop(obj/over_object) . = ..() @@ -149,30 +157,29 @@ M.putItemFromInventoryInHandIfPossible(src, H.held_index) /obj/item/storage/portable_chem_mixer/ui_interact(mob/user, datum/tgui/ui) + if(loc != user) + balloon_alert(user, "hold it in your hand!") + return + if(!atom_storage.locked) + balloon_alert(user, "lock it first!") + return + ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "PortableChemMixer", name) - - var/is_hallucinating = FALSE - if(isliving(user)) - var/mob/living/living_user = user - is_hallucinating = !!living_user.has_status_effect(/datum/status_effect/hallucination) - - if(is_hallucinating) - // to not ruin the immersion by constantly changing the fake chemicals - ui.set_autoupdate(FALSE) - ui.open() + var/is_hallucinating = FALSE + if(isliving(user)) + var/mob/living/living_user = user + is_hallucinating = !!living_user.has_status_effect(/datum/status_effect/hallucination) + ui.set_autoupdate(!is_hallucinating) // to not ruin the immersion by constantly changing the fake chemicals + /obj/item/storage/portable_chem_mixer/ui_data(mob/user) - var/list/data = list() - data["amount"] = amount - data["isBeakerLoaded"] = beaker ? 1 : 0 - data["beakerCurrentVolume"] = beaker ? beaker.reagents.total_volume : null - data["beakerMaxVolume"] = beaker ? beaker.volume : null - data["beakerTransferAmounts"] = beaker ? list(1,5,10,30,50,100) : null - data["showpH"] = show_ph - var/chemicals[0] + . = list() + .["amount"] = amount + + var/list/chemicals = list() var/is_hallucinating = FALSE if(isliving(user)) var/mob/living/living_user = user @@ -190,46 +197,54 @@ total_ph = rs.ph if(is_hallucinating && prob(5)) chemname = "[pick_list_replacements("hallucination.json", "chemicals")]" - chemicals.Add(list(list("title" = chemname, "id" = ckey(temp.name), "volume" = total_volume, "pH" = total_ph))) - data["chemicals"] = chemicals - var/beakerContents[0] - if(beaker) - for(var/datum/reagent/R in beaker.reagents.reagent_list) - beakerContents.Add(list(list("name" = R.name, "id" = ckey(R.name), "volume" = R.volume, "pH" = R.ph))) // list in a list because Byond merges the first list... - data["beakerCurrentpH"] = round(beaker.reagents.ph, 0.01) - data["beakerContents"] = beakerContents + chemicals += list(list("title" = chemname, "id" = temp.name, "volume" = total_volume, "pH" = total_ph)) + .["chemicals"] = chemicals - return data + var/list/beaker_data = null + if(!QDELETED(beaker)) + beaker_data = list() + beaker_data["maxVolume"] = beaker.volume + beaker_data["transferAmounts"] = beaker.possible_transfer_amounts + beaker_data["pH"] = round(beaker.reagents.ph, 0.01) + beaker_data["currentVolume"] = round(beaker.reagents.total_volume, 0.01) + var/list/beakerContents = list() + if(length(beaker?.reagents.reagent_list)) + for(var/datum/reagent/reagent in beaker.reagents.reagent_list) + beakerContents += list(list("name" = reagent.name, "volume" = round(reagent.volume, 0.01))) // list in a list because Byond merges the first list... + beaker_data["contents"] = beakerContents + .["beaker"] = beaker_data -/obj/item/storage/portable_chem_mixer/ui_act(action, params) +/obj/item/storage/portable_chem_mixer/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) return + switch(action) if("amount") - var/target = text2num(params["target"]) - amount = target - . = TRUE + amount = text2num(params["target"]) + return TRUE + if("dispense") - var/reagent_name = params["reagent"] - var/datum/reagent/reagent = GLOB.name2reagent[reagent_name] - var/entry = dispensable_reagents[reagent] - if(beaker && beaker.loc == src) - var/datum/reagents/R = beaker.reagents - var/actual = min(amount, 1000, R.maximum_volume - R.total_volume) - // todo: add check if we have enough reagent left - for (var/datum/reagents/source in entry["reagents"]) + var/datum/reagent/reagent = GLOB.name2reagent[params["reagent"]] + if(isnull(reagent)) + return + + if(!QDELETED(beaker)) + var/datum/reagents/container = beaker.reagents + var/actual = min(amount, 1000, container.maximum_volume - container.total_volume) + for (var/datum/reagents/source in dispensable_reagents[reagent]["reagents"]) var/to_transfer = min(source.total_volume, actual) - source.trans_to(beaker, to_transfer) + source.trans_to(beaker, to_transfer, transferred_by = ui.user) actual -= to_transfer if (actual <= 0) break - . = TRUE + return TRUE + if("remove") - var/amount = text2num(params["amount"]) - beaker.reagents.remove_all(amount) - . = TRUE + beaker.reagents.remove_all(text2num(params["amount"])) + return TRUE + if("eject") - replace_beaker(usr) + replace_beaker(ui.user) update_appearance() - . = TRUE + return TRUE diff --git a/code/modules/plumbing/plumbers/filter.dm b/code/modules/plumbing/plumbers/filter.dm index 4e4a282bd1d..633f70830f0 100644 --- a/code/modules/plumbing/plumbers/filter.dm +++ b/code/modules/plumbing/plumbers/filter.dm @@ -38,11 +38,12 @@ switch(action) if("add") var/which = params["which"] - var/selected_reagent = tgui_input_list(usr, "Select [which] reagent", "Reagent", GLOB.chemical_name_list) + + var/selected_reagent = tgui_input_list(usr, "Select [which] reagent", "Reagent", GLOB.name2reagent) if(!selected_reagent) return TRUE - var/chem_id = get_chem_id(selected_reagent) + var/datum/reagent/chem_id = GLOB.name2reagent[selected_reagent] if(!chem_id) return TRUE diff --git a/code/modules/plumbing/plumbers/reaction_chamber.dm b/code/modules/plumbing/plumbers/reaction_chamber.dm index 01a6b4a0b82..be7724ac554 100644 --- a/code/modules/plumbing/plumbers/reaction_chamber.dm +++ b/code/modules/plumbing/plumbers/reaction_chamber.dm @@ -4,7 +4,7 @@ #define HEATER_COEFFICIENT 0.05 /// maximum number of attempts the reaction chamber will make to balance the ph(More means better results but higher tick usage) -#define MAX_PH_ADJUSTMENTS 5 +#define MAX_PH_ADJUSTMENTS 3 /obj/machinery/plumbing/reaction_chamber name = "mixing chamber" @@ -107,13 +107,13 @@ switch(action) if("add") - var/selected_reagent = tgui_input_list(ui.user, "Select reagent", "Reagent", GLOB.chemical_name_list) + var/selected_reagent = tgui_input_list(ui.user, "Select reagent", "Reagent", GLOB.name2reagent) if(!selected_reagent) - return TRUE + return FALSE - var/input_reagent = get_chem_id(selected_reagent) + var/datum/reagent/input_reagent = GLOB.name2reagent[selected_reagent] if(!input_reagent) - return TRUE + return FALSE if(!required_reagents.Find(input_reagent)) var/input_amount = text2num(params["amount"]) @@ -194,13 +194,15 @@ return //transfer buffer and handle reactions - var/ph_change = (reagents.ph > alkaline_limit ? (reagents.ph - alkaline_limit) : (acidic_limit - reagents.ph)) - var/buffer_amount = ((ph_change * reagents.total_volume) / (BUFFER_IONIZING_STRENGTH * num_of_reagents)) - if(!buffer.trans_to(reagents, buffer_amount * seconds_per_tick)) + var/ph_change = max((reagents.ph > alkaline_limit ? (reagents.ph - alkaline_limit) : (acidic_limit - reagents.ph)), 0.25) + if(ph_change <= 0.7) //make big jumps towards the end so we can end our work quickly + ph_change *= 2 + var/buffer_amount = ((ph_change * reagents.total_volume) / (BUFFER_IONIZING_STRENGTH * num_of_reagents)) * seconds_per_tick + if(!buffer.trans_to(reagents, buffer_amount)) return //some power for accurate ph balancing & keep track of attempts made - use_power(active_power_usage * 0.03 * buffer_amount * seconds_per_tick) + use_power(active_power_usage * 0.03 * buffer_amount) ph_balance_attempts += 1 /obj/machinery/plumbing/reaction_chamber/chem/ui_interact(mob/user, datum/tgui/ui) diff --git a/code/modules/plumbing/plumbers/synthesizer.dm b/code/modules/plumbing/plumbers/synthesizer.dm index 3dddd648e61..0e9cb0c1b11 100644 --- a/code/modules/plumbing/plumbers/synthesizer.dm +++ b/code/modules/plumbing/plumbers/synthesizer.dm @@ -2,7 +2,6 @@ /obj/machinery/plumbing/synthesizer name = "chemical synthesizer" desc = "Produces a single chemical at a given volume. Must be plumbed. Most effective when working in unison with other chemical synthesizers, heaters and filters." - icon_state = "synthesizer" icon = 'icons/obj/pipes_n_cables/hydrochem/plumbers.dmi' active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 @@ -52,10 +51,13 @@ /obj/machinery/plumbing/synthesizer/process(seconds_per_tick) if(machine_stat & NOPOWER || !reagent_id || !amount) return - if(reagents.total_volume >= amount*seconds_per_tick*0.5) //otherwise we get leftovers, and we need this to be precise + + //otherwise we get leftovers, and we need this to be precise + if(reagents.total_volume >= amount) return - reagents.add_reagent(reagent_id, amount*seconds_per_tick*0.5) - use_power(active_power_usage * amount * seconds_per_tick * 0.5) + reagents.add_reagent(reagent_id, amount) + + use_power(active_power_usage) /obj/machinery/plumbing/synthesizer/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -63,8 +65,13 @@ ui = new(user, src, "ChemSynthesizer", name) ui.open() +/obj/machinery/plumbing/synthesizer/ui_static_data(mob/user) + . = ..() + .["possible_amounts"] = possible_amounts + /obj/machinery/plumbing/synthesizer/ui_data(mob/user) - var/list/data = list() + . = list() + .["amount"] = amount var/is_hallucinating = FALSE if(isliving(user)) @@ -72,36 +79,35 @@ is_hallucinating = !!living_user.has_status_effect(/datum/status_effect/hallucination) var/list/chemicals = list() - for(var/A in dispensable_reagents) - var/datum/reagent/R = GLOB.chemical_reagents_list[A] - if(R) - var/chemname = R.name + for(var/reagentID in dispensable_reagents) + var/datum/reagent/reagent = GLOB.chemical_reagents_list[reagentID] + if(reagent) + var/chemname = reagent.name if(is_hallucinating && prob(5)) chemname = "[pick_list_replacements("hallucination.json", "chemicals")]" - chemicals.Add(list(list("title" = chemname, "id" = ckey(R.name)))) - data["chemicals"] = chemicals - data["amount"] = amount - data["possible_amounts"] = possible_amounts + chemicals += list(list("title" = chemname, "id" = reagent.name)) + .["chemicals"] = chemicals - data["current_reagent"] = ckey(initial(reagent_id.name)) - return data + .["current_reagent"] = initial(reagent_id.name) /obj/machinery/plumbing/synthesizer/ui_act(action, params) . = ..() if(.) return - . = TRUE + switch(action) if("amount") var/new_amount = text2num(params["target"]) if(new_amount in possible_amounts) amount = new_amount . = TRUE + if("select") var/new_reagent = GLOB.name2reagent[params["reagent"]] if(new_reagent in dispensable_reagents) reagent_id = new_reagent . = TRUE + update_appearance() reagents.clear_reagents() diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index a3ed883551f..b677a8c02c9 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -1,16 +1,3 @@ -/proc/translate_legacy_chem_id(id) - switch (id) - if ("sacid") - return "sulfuricacid" - if ("facid") - return "fluorosulfuricacid" - if ("co2") - return "carbondioxide" - if ("mine_salve") - return "minerssalve" - else - return ckey(id) - /obj/machinery/chem_dispenser name = "chem dispenser" desc = "Creates and dispenses chemicals." @@ -23,21 +10,57 @@ circuit = /obj/item/circuitboard/machine/chem_dispenser processing_flags = NONE + /// The cell used to dispense reagents var/obj/item/stock_parts/cell/cell + /// Efficiency used when converting cell power to reagents var/powerefficiency = 0.1 + /// The current amount this machine is dispensing var/amount = 30 + /// The rate at which this machine recharges the power cell var/recharge_amount = 10 + /// Keep track of the intervals made during recharges var/recharge_counter = 0 + /// The temperature reagents are dispensed into the beaker var/dispensed_temperature = DEFAULT_REAGENT_TEMPERATURE - ///If the UI has the pH meter shown + /// If the UI has the pH meter shown var/show_ph = TRUE + /// The overlay used to display the beaker on the machine var/mutable_appearance/beaker_overlay + /// Icon to display when the machine is powered var/working_state = "dispenser_working" + /// Icon to display when the machine is not powered var/nopower_state = "dispenser_nopower" + /// Should we display the open panel overlay when the panel is opened with a screwdriver var/has_panel_overlay = TRUE + /// The actual beaker inserted into this machine var/obj/item/reagent_containers/beaker = null - //dispensable_reagents is copypasted in plumbing synthesizers. Please update accordingly. (I didn't make it global because that would limit custom chem dispensers) - var/list/dispensable_reagents = list( + /// Dispensable_reagents is copypasted in plumbing synthesizers. Please update accordingly. (I didn't make it global because that would limit custom chem dispensers) + var/list/dispensable_reagents = list() + /// These become available once the manipulator has been upgraded to tier 2 (nano) // SKYRAT EDIT CHANGE - ORIGINAL: /// These become available once the manipulator has been upgraded to tier 4 (femto) + var/list/upgrade_reagents = list() + // SKYRAT EDIT ADDITION BEGIN + /// These become available once the manipulator has been upgraded to tier 3 (pico) + var/list/upgrade2_reagents = list() + /// These become available once the manipulator has been upgraded to tier 4 (femto) + var/list/upgrade3_reagents = list() + // SKYRAT EDIT ADDITION END + /// These become available once the machine has been emaged + var/list/emagged_reagents = list() + /// Starting purity of the created reagents + var/base_reagent_purity = 1 + /// Records the reagents dispensed by the user if this list is not null + var/list/recording_recipe + /// Saves all the recipes recorded by the machine + var/list/saved_recipes = list() + // SKYRAT EDIT ADDITION BEGIN + /// Used for custom transfer amounts + var/list/transferAmounts = list() + /// The custom transfer amount + var/customTransferAmount + // SKYRAT EDIT ADDITION END + + /// The default list of dispensable_reagents + var/static/list/default_dispensable_reagents = list( /datum/reagent/aluminium, /datum/reagent/bromine, /datum/reagent/carbon, @@ -64,10 +87,11 @@ /datum/reagent/water, /datum/reagent/fuel, ) - //these become available once the manipulator has been upgraded to tier 4 (femto) - //SKYRAT EDIT REMOVAL BEGIN - Skyrat-SS13/Skyrat-tg#1931 + + //SKYRAT EDIT CHANGE BEGIN - ORIGINAL /* - var/list/upgrade_reagents = list( + /// The default list of reagents upgrade_reagents + var/static/list/default_upgrade_reagents = list( /datum/reagent/acetone, /datum/reagent/ammonia, /datum/reagent/ash, @@ -75,7 +99,8 @@ /datum/reagent/fuel/oil, /datum/reagent/saltpetre ) - var/list/emagged_reagents = list( + /// The default list of reagents emagged_reagents + var/static/list/default_emagged_reagents = list( /datum/reagent/toxin/carpotoxin, /datum/reagent/medicine/mine_salve, /datum/reagent/medicine/morphine, @@ -83,26 +108,24 @@ /datum/reagent/toxin ) */ - //SKYRAT EDIT REMOVAL END - //SKYRAT EDIT ADDITION BEGIN - Skyrat-SS13/Skyrat-tg#1931 - var/list/upgrade_reagents = list( + var/static/list/default_upgrade_reagents = list( /datum/reagent/fuel/oil, /datum/reagent/ammonia, /datum/reagent/ash ) - var/list/upgrade_reagents2 = list( + var/static/list/default_upgrade2_reagents = list( /datum/reagent/acetone, /datum/reagent/phenol, /datum/reagent/diethylamine ) - var/list/upgrade_reagents3 = list( + var/static/list/default_upgrade3_reagents = list( /datum/reagent/medicine/mine_salve, /datum/reagent/toxin ) - var/list/emagged_reagents = list( + var/static/list/default_emagged_reagents = list( /datum/reagent/drug/space_drugs, /datum/reagent/toxin/plasma, /datum/reagent/consumable/frostoil, @@ -110,38 +133,42 @@ /datum/reagent/toxin/histamine, /datum/reagent/medicine/morphine ) - //SKYRAT EDIT ADDITION END - /// Starting purity of the created reagents - var/base_reagent_purity = 1 - - var/list/recording_recipe - - var/list/saved_recipes = list() - //SKYRAT EDIT BEGIN - CHEMISTRY QOL - var/list/transferAmounts = list() - var/customTransferAmount - //SKYRAT EDIT END + //SKYRAT EDIT CHANGE END /obj/machinery/chem_dispenser/Initialize(mapload) . = ..() - dispensable_reagents = sort_list(dispensable_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) - if(emagged_reagents) - emagged_reagents = sort_list(emagged_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) + if(dispensable_reagents != null && !dispensable_reagents.len) + dispensable_reagents = default_dispensable_reagents + if(dispensable_reagents) + dispensable_reagents = sort_list(dispensable_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) + + if(upgrade_reagents != null && !upgrade_reagents.len) + upgrade_reagents = default_upgrade_reagents if(upgrade_reagents) upgrade_reagents = sort_list(upgrade_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) - //SKYRAT EDIT ADDITION BEGIN - Skyrat-SS13/Skyrat-tg#1931 - if(upgrade_reagents2) - upgrade_reagents2 = sort_list(upgrade_reagents2, GLOBAL_PROC_REF(cmp_reagents_asc)) - if(upgrade_reagents3) - upgrade_reagents3 = sort_list(upgrade_reagents3, GLOBAL_PROC_REF(cmp_reagents_asc)) + //SKYRAT EDIT ADDITION BEGIN + if(upgrade2_reagents != null && !upgrade2_reagents.len) + upgrade2_reagents = default_upgrade2_reagents + if(upgrade2_reagents) + upgrade2_reagents = sort_list(upgrade2_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) + if(upgrade3_reagents != null && !upgrade3_reagents.len) + upgrade3_reagents = default_upgrade3_reagents + if(upgrade3_reagents) + upgrade3_reagents = sort_list(upgrade3_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) //SKYRAT EDIT ADDITION END + + if(emagged_reagents != null && !emagged_reagents.len) + emagged_reagents = default_emagged_reagents + if(emagged_reagents) + emagged_reagents = sort_list(emagged_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) + if(is_operational) begin_processing() update_appearance() /obj/machinery/chem_dispenser/Destroy() + cell = null QDEL_NULL(beaker) - QDEL_NULL(cell) return ..() /obj/machinery/chem_dispenser/examine(mob/user) @@ -151,17 +178,15 @@ if(in_range(user, src) || isobserver(user)) . += "The status display reads:\n\ Recharging [recharge_amount] power units per interval.\n\ - Power efficiency increased by [round((powerefficiency*1000)-100, 1)]%." + Power efficiency increased by [round((powerefficiency * 1000) -100, 1)]%." . += span_notice("Use RMB to eject a stored beaker.") - /obj/machinery/chem_dispenser/on_set_is_operational(old_value) if(old_value) //Turned off end_processing() else //Turned on begin_processing() - /obj/machinery/chem_dispenser/process(seconds_per_tick) if (recharge_counter >= 8) var/usedpower = cell.give(recharge_amount) @@ -194,7 +219,6 @@ beaker_overlay = display_beaker() . += beaker_overlay - /obj/machinery/chem_dispenser/emag_act(mob/user, obj/item/card/emag/emag_card) if(obj_flags & EMAGGED) balloon_alert(user, "already emagged!") @@ -205,12 +229,10 @@ return TRUE /obj/machinery/chem_dispenser/ex_act(severity, target) - if(severity <= EXPLODE_LIGHT) - return FALSE - return ..() + return severity <= EXPLODE_LIGHT ? FALSE : ..() /obj/machinery/chem_dispenser/contents_explosion(severity, target) - ..() + . = ..() if(!beaker) return @@ -232,45 +254,25 @@ ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "ChemDispenser", name) - - var/is_hallucinating = FALSE - if(isliving(user)) - var/mob/living/living_user = user - is_hallucinating = !!living_user.has_status_effect(/datum/status_effect/hallucination) - - if(is_hallucinating) - ui.set_autoupdate(FALSE) //to not ruin the immersion by constantly changing the fake chemicals - ui.open() + var/is_hallucinating = FALSE + if(isliving(user)) + var/mob/living/living_user = user + is_hallucinating = !!living_user.has_status_effect(/datum/status_effect/hallucination) + ui.set_autoupdate(!is_hallucinating) //to not ruin the immersion by constantly changing the fake chemicals + +/obj/machinery/chem_dispenser/ui_static_data(mob/user) + . = ..() + .["showpH"] = show_ph + /obj/machinery/chem_dispenser/ui_data(mob/user) - var/data = list() - data["amount"] = amount - data["energy"] = cell.charge ? cell.charge * powerefficiency : "0" //To prevent NaN in the UI. - data["maxEnergy"] = cell.maxcharge * powerefficiency - data["isBeakerLoaded"] = beaker ? 1 : 0 - data["showpH"] = show_ph + . = list() + .["amount"] = amount + .["energy"] = cell.charge ? cell.charge * powerefficiency : 0 //To prevent NaN in the UI. + .["maxEnergy"] = cell.maxcharge * powerefficiency - var/beakerContents[0] - var/beakerCurrentVolume = 0 - if(beaker && beaker.reagents && beaker.reagents.reagent_list.len) - for(var/datum/reagent/R in beaker.reagents.reagent_list) - beakerContents.Add(list(list("name" = R.name, "volume" = round(R.volume, 0.01), "pH" = R.ph, "purity" = R.purity))) // list in a list because Byond merges the first list... - beakerCurrentVolume += R.volume - data["beakerContents"] = beakerContents - - if (beaker) - data["beakerCurrentVolume"] = round(beakerCurrentVolume, 0.01) - data["beakerMaxVolume"] = beaker.volume - data["beakerTransferAmounts"] = beaker.possible_transfer_amounts - data["beakerCurrentpH"] = round(beaker.reagents.ph, 0.01) - else - data["beakerCurrentVolume"] = null - data["beakerMaxVolume"] = null - data["beakerTransferAmounts"] = null - data["beakerCurrentpH"] = null - - var/chemicals[0] + var/list/chemicals = list() var/is_hallucinating = FALSE if(isliving(user)) var/mob/living/living_user = user @@ -282,23 +284,37 @@ var/chemname = temp.name if(is_hallucinating && prob(5)) chemname = "[pick_list_replacements("hallucination.json", "chemicals")]" - chemicals.Add(list(list("title" = chemname, "id" = ckey(temp.name), "pH" = temp.ph, "pHCol" = convert_ph_to_readable_color(temp.ph)))) - data["chemicals"] = chemicals - data["recipes"] = saved_recipes + chemicals += list(list("title" = chemname, "id" = temp.name, "pH" = temp.ph, "pHCol" = convert_ph_to_readable_color(temp.ph))) + .["chemicals"] = chemicals + .["recipes"] = saved_recipes - data["recordingRecipe"] = recording_recipe - data["recipeReagents"] = list() + .["recordingRecipe"] = recording_recipe + .["recipeReagents"] = list() if(beaker?.reagents.ui_reaction_id) var/datum/chemical_reaction/reaction = get_chemical_reaction(beaker.reagents.ui_reaction_id) for(var/_reagent in reaction.required_reagents) var/datum/reagent/reagent = find_reagent_object_from_type(_reagent) - data["recipeReagents"] += ckey(reagent.name) - return data + .["recipeReagents"] += reagent.name -/obj/machinery/chem_dispenser/ui_act(action, params) + var/list/beaker_data = null + if(!QDELETED(beaker)) + beaker_data = list() + beaker_data["maxVolume"] = beaker.volume + beaker_data["transferAmounts"] = beaker.possible_transfer_amounts + beaker_data["pH"] = round(beaker.reagents.ph, 0.01) + beaker_data["currentVolume"] = round(beaker.reagents.total_volume, 0.01) + var/list/beakerContents = list() + if(beaker && beaker.reagents && beaker.reagents.reagent_list.len) + for(var/datum/reagent/reagent in beaker.reagents.reagent_list) + beakerContents += list(list("name" = reagent.name, "volume" = round(reagent.volume, 0.01))) // list in a list because Byond merges the first list... + beaker_data["contents"] = beakerContents + .["beaker"] = beaker_data + +/obj/machinery/chem_dispenser/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) return + switch(action) if("amount") if(!is_operational || QDELETED(beaker)) @@ -307,7 +323,8 @@ if(target in beaker.possible_transfer_amounts) amount = target work_animation() - . = TRUE + return TRUE + if("dispense") if(!is_operational || QDELETED(cell)) return @@ -318,7 +335,7 @@ var/datum/reagents/holder = beaker.reagents var/to_dispense = max(0, min(amount, holder.maximum_volume - holder.total_volume)) - if(!cell?.use(to_dispense / powerefficiency)) + if(!cell.use(to_dispense / powerefficiency)) say("Not enough energy to complete operation!") return holder.add_reagent(reagent, to_dispense, reagtemp = dispensed_temperature, added_purity = base_reagent_purity) @@ -326,7 +343,8 @@ work_animation() else recording_recipe[reagent_name] += amount - . = TRUE + return TRUE + if("remove") if(!is_operational || recording_recipe) return @@ -334,10 +352,12 @@ if(beaker && (amount in beaker.possible_transfer_amounts)) beaker.reagents.remove_all(amount) work_animation() - . = TRUE + return TRUE + if("eject") - replace_beaker(usr) - . = TRUE + replace_beaker(ui.user) + return TRUE + if("dispense_recipe") if(!is_operational || QDELETED(cell)) return @@ -346,7 +366,7 @@ if(!LAZYLEN(chemicals_to_dispense)) return for(var/key in chemicals_to_dispense) - var/reagent = GLOB.name2reagent[translate_legacy_chem_id(key)] + var/reagent = GLOB.name2reagent[key] var/dispense_amount = chemicals_to_dispense[key] if(!dispensable_reagents.Find(reagent)) return @@ -358,50 +378,49 @@ var/to_dispense = max(0, min(dispense_amount, holder.maximum_volume - holder.total_volume)) if(!to_dispense) continue - if(!cell?.use(to_dispense / powerefficiency)) + if(!cell.use(to_dispense / powerefficiency)) say("Not enough energy to complete operation!") return holder.add_reagent(reagent, to_dispense, reagtemp = dispensed_temperature, added_purity = base_reagent_purity) work_animation() else recording_recipe[key] += dispense_amount - . = TRUE + return TRUE + if("clear_recipes") - if(!is_operational) - return - var/yesno = tgui_alert(usr, "Clear all recipes?",, list("Yes","No")) - if(yesno == "Yes") + if(is_operational && tgui_alert(ui.user, "Clear all recipes?", "Clear?", list("Yes", "No")) == "Yes") saved_recipes = list() - . = TRUE + return TRUE + if("record_recipe") - if(!is_operational) - return - recording_recipe = list() - . = TRUE + if(is_operational) + recording_recipe = list() + return TRUE + if("save_recording") if(!is_operational) return - var/name = tgui_input_text(usr, "What do you want to name this recipe?", "Recipe Name", MAX_NAME_LEN) - if(!usr.can_perform_action(src, ALLOW_SILICON_REACH)) + var/name = tgui_input_text(ui.user, "What do you want to name this recipe?", "Recipe Name", MAX_NAME_LEN) + if(!ui.user.can_perform_action(src, ALLOW_SILICON_REACH)) return - if(saved_recipes[name] && tgui_alert(usr, "\"[name]\" already exists, do you want to overwrite it?",, list("Yes", "No")) == "No") + if(saved_recipes[name] && tgui_alert(ui.user, "\"[name]\" already exists, do you want to overwrite it?",, list("Yes", "No")) == "No") return if(name && recording_recipe) for(var/reagent in recording_recipe) - var/reagent_id = GLOB.name2reagent[translate_legacy_chem_id(reagent)] + var/reagent_id = GLOB.name2reagent[reagent] if(!dispensable_reagents.Find(reagent_id)) visible_message(span_warning("[src] buzzes."), span_hear("You hear a faint buzz.")) - to_chat(usr, span_warning("[src] cannot find [reagent]!")) + to_chat(ui.user, span_warning("[src] cannot find [reagent]!")) playsound(src, 'sound/machines/buzz-two.ogg', 50, TRUE) return saved_recipes[name] = recording_recipe recording_recipe = null - . = TRUE + return TRUE + if("cancel_recording") - if(!is_operational) - return - recording_recipe = null - . = TRUE + if(is_operational) + recording_recipe = null + return TRUE //SKYRAT EDIT ADDITION BEGIN - CHEMISTRY QOL if("custom_amount") if(!beaker) @@ -411,22 +430,30 @@ transferAmounts -= customTransferAmount customTransferAmount = clamp(input(usr, "Please enter your desired transfer amount.", "Transfer amount", 0) as num|null, 0, beaker.volume) transferAmounts += customTransferAmount + return TRUE //SKYRAT EDIT ADDITION END + if("reaction_lookup") if(beaker) - beaker.reagents.ui_interact(usr) + beaker.reagents.ui_interact(ui.user) /obj/machinery/chem_dispenser/wrench_act(mob/living/user, obj/item/tool) . = ..() - default_unfasten_wrench(user, tool) - return TOOL_ACT_TOOLTYPE_SUCCESS + if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/machinery/chem_dispenser/screwdriver_act(mob/living/user, obj/item/tool) + . = ..() + if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool)) + update_appearance() + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/machinery/chem_dispenser/crowbar_act(mob/living/user, obj/item/tool) + . = ..() + if(default_deconstruction_crowbar(tool)) + return TOOL_ACT_TOOLTYPE_SUCCESS /obj/machinery/chem_dispenser/attackby(obj/item/I, mob/living/user, params) - if(default_deconstruction_screwdriver(user, icon_state, icon_state, I)) - update_appearance() - return - if(default_deconstruction_crowbar(I)) - return if(is_reagent_container(I) && !(I.item_flags & ABSTRACT) && I.is_open_container()) var/obj/item/reagent_containers/B = I //SKYRAT EDIT BEGIN - CHEMISTRY QOL @@ -496,14 +523,14 @@ dispensable_reagents -= upgrade_reagents if (servo.tier > 2) - dispensable_reagents |= upgrade_reagents2 + dispensable_reagents |= upgrade2_reagents else - dispensable_reagents -= upgrade_reagents2 + dispensable_reagents -= upgrade2_reagents if (servo.tier > 3) - dispensable_reagents |= upgrade_reagents3 + dispensable_reagents |= upgrade3_reagents else - dispensable_reagents -= upgrade_reagents3 + dispensable_reagents -= upgrade3_reagents //SKYRAT EDIT END parts_rating += servo.tier powerefficiency = round(newpowereff, 0.01) @@ -559,7 +586,8 @@ nopower_state = null pass_flags = PASSTABLE show_ph = FALSE - dispensable_reagents = list( + /// The default list of reagents dispensable by the soda dispenser + var/static/list/drinks_dispensable_reagents = list( /datum/reagent/consumable/coffee, /datum/reagent/consumable/space_cola, /datum/reagent/consumable/cream, @@ -586,24 +614,26 @@ /datum/reagent/consumable/tonic, /datum/reagent/water, ) - //SKYRAT EDIT ADDITION BEGIN - Skyrat-SS13/Skyrat-tg#2429 - upgrade_reagents = list( + //SKYRAT EDIT ADDITION BEGIN + var/static/list/drink_upgrade_reagents = list( /datum/reagent/consumable/applejuice, /datum/reagent/consumable/pumpkinjuice, /datum/reagent/consumable/vanilla ) - upgrade_reagents2 = list( + var/static/list/drink_upgrade2_reagents = list( /datum/reagent/consumable/banana, /datum/reagent/consumable/berryjuice, /datum/reagent/consumable/blumpkinjuice ) - upgrade_reagents3 = list( + var/static/list/drink_upgrade3_reagents = list( /datum/reagent/consumable/watermelonjuice, /datum/reagent/consumable/peachjuice, /datum/reagent/consumable/sol_dry ) //SKYRAT EDIT ADDITION END - emagged_reagents = list( + upgrade_reagents = null + /// The default list of emagged reagents dispensable by the soda dispenser + var/static/list/drink_emagged_reagents = list( /datum/reagent/consumable/ethanol/thirteenloko, /datum/reagent/consumable/ethanol/whiskey_cola, /datum/reagent/toxin/mindbreaker, @@ -612,6 +642,24 @@ base_reagent_purity = 0.5 /obj/machinery/chem_dispenser/drinks/Initialize(mapload) + if(dispensable_reagents != null && !dispensable_reagents.len) + dispensable_reagents = drinks_dispensable_reagents + if(emagged_reagents != null && !emagged_reagents.len) + emagged_reagents = drink_emagged_reagents + //SKYRAT EDIT ADDITION BEGIN + if(upgrade_reagents != null && !upgrade_reagents.len) + upgrade_reagents = drink_upgrade_reagents + if(upgrade_reagents) + upgrade_reagents = sort_list(upgrade_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) + if(upgrade2_reagents != null && !upgrade2_reagents.len) + upgrade2_reagents = drink_upgrade2_reagents + if(upgrade2_reagents) + upgrade2_reagents = sort_list(upgrade2_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) + if(upgrade3_reagents != null && !upgrade3_reagents.len) + upgrade3_reagents = drink_upgrade3_reagents + if(upgrade3_reagents) + upgrade3_reagents = sort_list(upgrade3_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) + //SKYRAT EDIT ADDITION END . = ..() AddComponent(/datum/component/simple_rotation) @@ -656,7 +704,8 @@ base_icon_state = "booze_dispenser" dispensed_temperature = WATER_MATTERSTATE_CHANGE_TEMP circuit = /obj/item/circuitboard/machine/chem_dispenser/drinks/beer - dispensable_reagents = list( + /// The default list of reagents dispensable by the beer dispenser + var/static/list/beer_dispensable_reagents = list( /datum/reagent/consumable/ethanol/absinthe, /datum/reagent/consumable/ethanol/ale, /datum/reagent/consumable/ethanol/applejack, @@ -685,9 +734,10 @@ /datum/reagent/consumable/ethanol/yuyake, ) upgrade_reagents = null - upgrade_reagents2 = null //SKYRAT EDIT - upgrade_reagents3 = null //SKYRAT EDIT - emagged_reagents = list( + upgrade2_reagents = null //SKYRAT EDIT + upgrade3_reagents = null //SKYRAT EDIT + /// The default list of emagged reagents dispensable by the beer dispenser + var/static/list/beer_emagged_reagents = list( /datum/reagent/consumable/ethanol, /datum/reagent/iron, /datum/reagent/consumable/mintextract, @@ -695,6 +745,11 @@ /datum/reagent/consumable/ethanol/fernet ) +/obj/machinery/chem_dispenser/drinks/beer/Initialize(mapload) + dispensable_reagents = beer_dispensable_reagents + emagged_reagents = beer_emagged_reagents + . = ..() + /obj/machinery/chem_dispenser/drinks/beer/fullupgrade //fully ugpraded stock parts, emagged desc = "Contains a large reservoir of the good stuff. This model has had its safeties shorted out." obj_flags = CAN_BE_HIT | EMAGGED @@ -708,19 +763,25 @@ /obj/machinery/chem_dispenser/mutagen name = "mutagen dispenser" desc = "Creates and dispenses mutagen." - dispensable_reagents = list(/datum/reagent/toxin/mutagen) + /// The default list of reagents dispensable by mutagen chem dispenser + var/static/list/mutagen_dispensable_reagents = list(/datum/reagent/toxin/mutagen) upgrade_reagents = null - emagged_reagents = list(/datum/reagent/toxin/plasma) + /// The default list of emagged reagents dispensable by mutagen chem dispenser + var/static/list/mutagen_emagged_reagents = list(/datum/reagent/toxin/plasma) +/obj/machinery/chem_dispenser/mutagen/Initialize(mapload) + dispensable_reagents = mutagen_dispensable_reagents + emagged_reagents = mutagen_emagged_reagents + . = ..() /obj/machinery/chem_dispenser/mutagensaltpeter name = "botanical chemical dispenser" desc = "Creates and dispenses chemicals useful for botany." flags_1 = NODECONSTRUCT_1 - circuit = /obj/item/circuitboard/machine/chem_dispenser/mutagensaltpeter - dispensable_reagents = list( + /// The default list of dispensable reagents available in the mutagensaltpeter chem dispenser + var/static/list/mutagensaltpeter_dispensable_reagents = list( /datum/reagent/toxin/mutagen, /datum/reagent/saltpetre, /datum/reagent/plantnutriment/eznutriment, @@ -736,6 +797,10 @@ /datum/reagent/diethylamine) upgrade_reagents = null +/obj/machinery/chem_dispenser/mutagensaltpeter/Initialize(mapload) + dispensable_reagents = mutagensaltpeter_dispensable_reagents + . = ..() + /obj/machinery/chem_dispenser/fullupgrade //fully ugpraded stock parts, emagged desc = "Creates and dispenses chemicals. This model has had its safeties shorted out." obj_flags = CAN_BE_HIT | EMAGGED @@ -757,7 +822,9 @@ working_state = null nopower_state = null use_power = NO_POWER_USE - dispensable_reagents = list( + + /// The default list of dispensable reagents available in the abductor chem dispenser + var/static/list/abductor_dispensable_reagents = list( /datum/reagent/aluminium, /datum/reagent/bromine, /datum/reagent/carbon, @@ -799,3 +866,7 @@ /datum/reagent/consumable/liquidelectricity/enriched, /datum/reagent/medicine/c2/synthflesh ) + +/obj/machinery/chem_dispenser/abductor/Initialize(mapload) + dispensable_reagents = abductor_dispensable_reagents + . = ..() diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index c5f62883b5f..83b1b0705ef 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -597,33 +597,31 @@ ui.open() /obj/item/blood_filter/ui_data(mob/user) - var/list/data = list() - var/list/chem_names = list() + . = list() + + .["whitelist"] = list() for(var/key in whitelist) - chem_names += whitelist[key] - data["whitelist"] = chem_names - return data + .["whitelist"] += whitelist[key] /obj/item/blood_filter/ui_act(action, params) . = ..() if(.) return + . = TRUE switch(action) if("add") - var/selected_reagent = tgui_input_list(usr, "Select reagent to filter", "Whitelist reagent", GLOB.chemical_name_list) + var/selected_reagent = tgui_input_list(usr, "Select reagent to filter", "Whitelist reagent", GLOB.name2reagent) if(!selected_reagent) - return TRUE + return FALSE - var/chem_id = get_chem_id(selected_reagent) + var/datum/reagent/chem_id = GLOB.name2reagent[selected_reagent] if(!chem_id) - return TRUE + return FALSE if(!(chem_id in whitelist)) whitelist[chem_id] = selected_reagent - - if("remove") var/chem_name = params["reagent"] var/chem_id = get_chem_id(chem_name) diff --git a/tgui/packages/tgui/interfaces/ChemDispenser.js b/tgui/packages/tgui/interfaces/ChemDispenser.tsx similarity index 82% rename from tgui/packages/tgui/interfaces/ChemDispenser.js rename to tgui/packages/tgui/interfaces/ChemDispenser.tsx index d1035900a32..c8dc25e943f 100644 --- a/tgui/packages/tgui/interfaces/ChemDispenser.js +++ b/tgui/packages/tgui/interfaces/ChemDispenser.tsx @@ -1,22 +1,49 @@ import { toFixed } from 'common/math'; +import { BooleanLike } from 'common/react'; import { toTitleCase } from 'common/string'; -import { Fragment } from 'inferno'; import { useBackend, useLocalState } from '../backend'; import { AnimatedNumber, Box, Button, Icon, LabeledList, ProgressBar, Section } from '../components'; import { Window } from '../layouts'; +export type BeakerReagent = { + name: string; + volume: number; +}; + +export type Beaker = { + maxVolume: number; + transferAmounts: number[]; + pH: number; + currentVolume: number; + contents: BeakerReagent[]; +}; + +type DispensableReagent = { + title: string; + id: string; + pH: number; + pHCol: string; +}; + +type Data = { + showpH: BooleanLike; + amount: number; + energy: number; + maxEnergy: number; + chemicals: DispensableReagent[]; + recipes: string[]; + recordingRecipe: string[]; + recipeReagents: string[]; + beaker: Beaker; +}; + export const ChemDispenser = (props, context) => { - const { act, data } = useBackend(context); + const { act, data } = useBackend(context); const recording = !!data.recordingRecipe; - const { recipeReagents = [] } = data; + const { recipeReagents = [], recipes = [], beaker } = data; const [hasCol, setHasCol] = useLocalState(context, 'has_col', false); - // TODO: Change how this piece of shit is built on server side - // It has to be a list, not a fucking OBJECT! - const recipes = Object.keys(data.recipes).map((name) => ({ - name, - contents: data.recipes[name], - })); - const beakerTransferAmounts = data.beakerTransferAmounts || []; + + const beakerTransferAmounts = beaker ? beaker.transferAmounts : []; const beakerContents = (recording && Object.keys(data.recordingRecipe).map((id) => ({ @@ -24,7 +51,7 @@ export const ChemDispenser = (props, context) => { name: toTitleCase(id.replace(/_/, ' ')), volume: data.recordingRecipe[id], }))) || - data.beakerContents || + beaker?.contents || []; return ( @@ -41,10 +68,10 @@ export const ChemDispenser = (props, context) => { )}