diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index c3da908ee1..04ce1bbe36 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -8,6 +8,8 @@ #define ismovableatom(A) (istype(A, /atom/movable)) +#define isatom(A) (istype(A, /atom)) + //Turfs //#define isturf(A) (istype(A, /turf)) This is actually a byond built-in. Added here for completeness sake. diff --git a/code/datums/components/material_container.dm b/code/datums/components/material_container.dm index d4b75e3892..0c025aab44 100644 --- a/code/datums/components/material_container.dm +++ b/code/datums/components/material_container.dm @@ -20,6 +20,7 @@ var/last_inserted_id var/last_amount_inserted var/last_insert_success + var/precise_insertion = FALSE var/datum/callback/precondition //MAX_STACK_SIZE = 50 //MINERAL_MATERIAL_AMOUNT = 2000 @@ -70,10 +71,21 @@ if(!has_space(material_amount)) to_chat(user, "[parent] is full. Please remove metal or glass from [parent] in order to insert more.") return + INVOKE_ASYNC(src, .proc/user_insert, I, user) + +/datum/component/material_container/proc/user_insert(obj/item/I, mob/living/user) + var/requested_amount + if(istype(I, /obj/item/stack) && precise_insertion) + var/atom/current_parent = parent + requested_amount = input(user, "How much do you want to insert?", "Inserting sheets") as num|null + if(isnull(requested_amount) || (requested_amount <= 0)) + return + if(QDELETED(I) || QDELETED(user) || QDELETED(src) || parent != current_parent || !user.canUseTopic(current_parent) || !user.is_holding(I) || !user.Adjacent(current_parent)) + return if(!user.temporarilyRemoveItemFromInventory(I)) to_chat(user, "[I] is stuck to you and cannot be placed into [parent].") return - var/inserted = insert_item(I) + var/inserted = insert_item(I, stack_amt = requested_amount) if(inserted) last_insert_success = TRUE if(istype(I, /obj/item/stack)) @@ -84,7 +96,7 @@ to_chat(user, "You insert a material total of [inserted] into [parent].") qdel(I) else - user.put_in_active_hand(I) + user.put_in_active_hand(I) //For inserting an amount of material /datum/component/material_container/proc/insert_amount(amt, id = null) @@ -101,21 +113,25 @@ M.amount += amt total_amount += amt return (total_amount - total_amount_saved) - return 0 + return FALSE /datum/component/material_container/proc/insert_stack(obj/item/stack/S, amt = 0) + if(isnull(amt)) + amt = S.amount + if(amt <= 0) - return 0 + return FALSE + if(amt > S.amount) amt = S.amount var/material_amt = get_item_material_amount(S) if(!material_amt) - return 0 + return FALSE amt = min(amt, round(((max_amount - total_amount) / material_amt))) if(!amt) - return 0 + return FALSE last_inserted_id = insert_materials(S,amt) last_inserted_type = S.type @@ -123,16 +139,15 @@ last_amount_inserted = amt return amt -/datum/component/material_container/proc/insert_item(obj/item/I, multiplier = 1) +/datum/component/material_container/proc/insert_item(obj/item/I, multiplier = 1, stack_amt) if(!I) - return 0 + return FALSE if(istype(I, /obj/item/stack)) - var/obj/item/stack/S = I - return insert_stack(I, S.amount) + return insert_stack(I, stack_amt) var/material_amount = get_item_material_amount(I) if(!material_amount || !has_space(material_amount)) - return 0 + return FALSE last_inserted_id = insert_materials(I, multiplier) last_inserted_type = I.type @@ -155,13 +170,13 @@ //mats is a list of types of material to use and the corresponding amounts, example: list(MAT_METAL=100, MAT_GLASS=200) /datum/component/material_container/proc/use_amount(list/mats, multiplier=1) if(!mats || !mats.len) - return 0 + return FALSE var/datum/material/M for(var/MAT in materials) M = materials[MAT] if(M.amount < (mats[MAT] * multiplier)) - return 0 + return FALSE var/total_amount_save = total_amount for(var/MAT in materials) @@ -179,7 +194,7 @@ M.amount -= amt total_amount -= amt return amt - return 0 + return FALSE /datum/component/material_container/proc/can_use_amount(amt, id, list/mats) if(amt && id) @@ -198,7 +213,7 @@ //For spawning mineral sheets; internal use only /datum/component/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null) if(!M.sheet_type) - return 0 + return FALSE if(sheet_amt > 0) if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT)) sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT) @@ -215,12 +230,12 @@ count += sheet_amt use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id) return count - return 0 + return FALSE /datum/component/material_container/proc/retrieve_sheets(sheet_amt, id, target = null) if(materials[id]) return retrieve(sheet_amt, materials[id], target) - return 0 + return FALSE /datum/component/material_container/proc/retrieve_amount(amt, id, target) return retrieve_sheets(amount2sheet(amt), id, target) @@ -238,24 +253,24 @@ /datum/component/material_container/proc/has_materials(list/mats, multiplier=1) if(!mats || !mats.len) - return 0 + return FALSE var/datum/material/M for(var/MAT in mats) M = materials[MAT] if(M.amount < (mats[MAT] * multiplier)) - return 0 - return 1 + return FALSE + return TRUE /datum/component/material_container/proc/amount2sheet(amt) if(amt >= MINERAL_MATERIAL_AMOUNT) return round(amt / MINERAL_MATERIAL_AMOUNT) - return 0 + return FALSE /datum/component/material_container/proc/sheet2amount(sheet_amt) if(sheet_amt > 0) return sheet_amt * MINERAL_MATERIAL_AMOUNT - return 0 + return FALSE /datum/component/material_container/proc/amount(id) var/datum/material/M = materials[id] @@ -265,7 +280,7 @@ //if this container does not support glass, any glass in 'I' will not be taken into account /datum/component/material_container/proc/get_item_material_amount(obj/item/I) if(!istype(I)) - return 0 + return FALSE var/material_amount = 0 for(var/MAT in materials) material_amount += I.materials[MAT] diff --git a/code/game/machinery/droneDispenser.dm b/code/game/machinery/droneDispenser.dm index 5d7be7fbd8..a6fffea19a 100644 --- a/code/game/machinery/droneDispenser.dm +++ b/code/game/machinery/droneDispenser.dm @@ -56,6 +56,7 @@ . = ..() var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, TRUE) materials.insert_amount(starting_amount) + materials.precise_insertion = TRUE using_materials = list(MAT_METAL=metal_cost, MAT_GLASS=glass_cost) /obj/machinery/droneDispenser/preloaded diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 747647b1a5..524dc4e5b5 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -35,9 +35,10 @@ ) /obj/machinery/mecha_part_fabricator/Initialize() - AddComponent(/datum/component/material_container, + var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready)) + materials.precise_insertion = TRUE . = ..() files = new /datum/research(src) //Setup the research data holder. diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm index 311efd0140..a341121390 100644 --- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm +++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm @@ -1,94 +1,99 @@ + +#define MILK_TO_BUTTER_COEFF 15 + /obj/machinery/reagentgrinder - name = "All-In-One Grinder" - desc = "From BlenderTech. Will It Blend? Let's test it out!" - icon = 'icons/obj/kitchen.dmi' - icon_state = "juicer1" - layer = BELOW_OBJ_LAYER - anchored = TRUE - use_power = IDLE_POWER_USE - idle_power_usage = 5 - active_power_usage = 100 - pass_flags = PASSTABLE - resistance_flags = ACID_PROOF - var/operating = FALSE - var/obj/item/reagent_containers/beaker = null - var/limit = 10 + name = "All-In-One Grinder" + desc = "From BlenderTech. Will It Blend? Let's test it out!" + icon = 'icons/obj/kitchen.dmi' + icon_state = "juicer1" + layer = BELOW_OBJ_LAYER + anchored = TRUE + use_power = IDLE_POWER_USE + idle_power_usage = 5 + active_power_usage = 100 + pass_flags = PASSTABLE + resistance_flags = ACID_PROOF + var/operating = FALSE + var/obj/item/reagent_containers/beaker = null + var/limit = 10 - var/static/list/blend_items = list( - //Sheets - /obj/item/stack/sheet/mineral/plasma = list("plasma" = 20), - /obj/item/stack/sheet/metal = list("iron" = 20), - /obj/item/stack/sheet/plasteel = list("iron" = 20, "plasma" = 20), - /obj/item/stack/sheet/mineral/wood = list("carbon" = 20), - /obj/item/stack/sheet/glass = list("silicon" = 20), - /obj/item/stack/sheet/rglass = list("silicon" = 20, "iron" = 20), - /obj/item/stack/sheet/mineral/uranium = list("uranium" = 20), - /obj/item/stack/sheet/mineral/bananium = list("banana" = 20), - /obj/item/stack/sheet/mineral/silver = list("silver" = 20), - /obj/item/stack/sheet/mineral/gold = list("gold" = 20), - /obj/item/stack/sheet/bluespace_crystal = list("bluespace" = 20), - /obj/item/ore/bluespace_crystal = list("bluespace" = 20), - /obj/item/grown/nettle/basic = list("sacid" = 0), - /obj/item/grown/nettle/death = list("facid" = 0, "sacid" = 0), - /obj/item/grown/novaflower = list("capsaicin" = 0, "condensedcapsaicin" = 0), - //Blender Stuff - /obj/item/reagent_containers/food/snacks/grown/soybeans = list("soymilk" = 0), - /obj/item/reagent_containers/food/snacks/grown/tomato = list("ketchup" = 0), - /obj/item/reagent_containers/food/snacks/grown/wheat = list("flour" = -5), - /obj/item/reagent_containers/food/snacks/grown/oat = list("flour" = -5), - /obj/item/reagent_containers/food/snacks/grown/rice = list("rice" = -5), - /obj/item/reagent_containers/food/snacks/donut = list("sprinkles" = -2, "sugar" = 1), - /obj/item/reagent_containers/food/snacks/grown/cherries = list("cherryjelly" = 0), - /obj/item/reagent_containers/food/snacks/grown/bluecherries = list("bluecherryjelly" = 0), - /obj/item/reagent_containers/food/snacks/egg = list("eggyolk" = -5), - //Grinder stuff, but only if dry - /obj/item/reagent_containers/food/snacks/grown/coffee/robusta = list("coffeepowder" = 0, "morphine" = 0), - /obj/item/reagent_containers/food/snacks/grown/coffee = list("coffeepowder" = 0), - /obj/item/reagent_containers/food/snacks/grown/tea/astra = list("teapowder" = 0, "salglu_solution" = 0), - /obj/item/reagent_containers/food/snacks/grown/tea = list("teapowder" = 0), - //All types that you can put into the grinder to transfer the reagents to the beaker. !Put all recipes above this.! - /obj/item/slime_extract = list(), - /obj/item/reagent_containers/pill = list(), - /obj/item/reagent_containers/food = list(), - /obj/item/reagent_containers/honeycomb = list(), - /obj/item/toy/crayon = list()) + var/static/list/blend_items = list( + //Sheets + /obj/item/stack/sheet/mineral/plasma = list("plasma" = 20), + /obj/item/stack/sheet/metal = list("iron" = 20), + /obj/item/stack/sheet/plasteel = list("iron" = 20, "plasma" = 20), + /obj/item/stack/sheet/mineral/wood = list("carbon" = 20), + /obj/item/stack/sheet/glass = list("silicon" = 20), + /obj/item/stack/sheet/rglass = list("silicon" = 20, "iron" = 20), + /obj/item/stack/sheet/mineral/uranium = list("uranium" = 20), + /obj/item/stack/sheet/mineral/bananium = list("banana" = 20), + /obj/item/stack/sheet/mineral/silver = list("silver" = 20), + /obj/item/stack/sheet/mineral/gold = list("gold" = 20), + /obj/item/stack/sheet/bluespace_crystal = list("bluespace" = 20), + /obj/item/ore/bluespace_crystal = list("bluespace" = 20), + /obj/item/grown/nettle/basic = list("sacid" = 0), + /obj/item/grown/nettle/death = list("facid" = 0, "sacid" = 0), + /obj/item/grown/novaflower = list("capsaicin" = 0, "condensedcapsaicin" = 0), + //Blender Stuff + /obj/item/reagent_containers/food/snacks/grown/soybeans = list("soymilk" = 0), + /obj/item/reagent_containers/food/snacks/grown/tomato = list("ketchup" = 0), + /obj/item/reagent_containers/food/snacks/grown/wheat = list("flour" = -5), + /obj/item/reagent_containers/food/snacks/grown/oat = list("flour" = -5), + /obj/item/reagent_containers/food/snacks/grown/rice = list("rice" = -5), + /obj/item/reagent_containers/food/snacks/donut = list("sprinkles" = -2, "sugar" = 1), + /obj/item/reagent_containers/food/snacks/grown/cherries = list("cherryjelly" = 0), + /obj/item/reagent_containers/food/snacks/grown/bluecherries = list("bluecherryjelly" = 0), + /obj/item/reagent_containers/food/snacks/egg = list("eggyolk" = -5), + //Grinder stuff, but only if dry + /obj/item/reagent_containers/food/snacks/grown/coffee/robusta = list("coffeepowder" = 0, "morphine" = 0), + /obj/item/reagent_containers/food/snacks/grown/coffee = list("coffeepowder" = 0), + /obj/item/reagent_containers/food/snacks/grown/tea/astra = list("teapowder" = 0, "salglu_solution" = 0), + /obj/item/reagent_containers/food/snacks/grown/tea = list("teapowder" = 0), + //All types that you can put into the grinder to transfer the reagents to the beaker. !Put all recipes above this.! + /obj/item/slime_extract = list(), + /obj/item/reagent_containers/pill = list(), + /obj/item/reagent_containers/food = list(), + /obj/item/reagent_containers/honeycomb = list(), + /obj/item/toy/crayon = list()) - var/static/list/juice_items = list( - //Juicer Stuff - /obj/item/reagent_containers/food/snacks/grown/corn = list("corn_starch" = 0), - /obj/item/reagent_containers/food/snacks/grown/tomato = list("tomatojuice" = 0), - /obj/item/reagent_containers/food/snacks/grown/carrot = list("carrotjuice" = 0), - /obj/item/reagent_containers/food/snacks/grown/berries = list("berryjuice" = 0), - /obj/item/reagent_containers/food/snacks/grown/banana = list("banana" = 0), - /obj/item/reagent_containers/food/snacks/grown/potato = list("potato" = 0), - /obj/item/reagent_containers/food/snacks/grown/citrus/lemon = list("lemonjuice" = 0), - /obj/item/reagent_containers/food/snacks/grown/citrus/orange = list("orangejuice" = 0), - /obj/item/reagent_containers/food/snacks/grown/citrus/lime = list("limejuice" = 0), - /obj/item/reagent_containers/food/snacks/grown/watermelon = list("watermelonjuice" = 0), - /obj/item/reagent_containers/food/snacks/watermelonslice = list("watermelonjuice" = 0), - /obj/item/reagent_containers/food/snacks/grown/berries/poison = list("poisonberryjuice" = 0), - /obj/item/reagent_containers/food/snacks/grown/pumpkin = list("pumpkinjuice" = 0), - /obj/item/reagent_containers/food/snacks/grown/blumpkin = list("blumpkinjuice" = 0), - /obj/item/reagent_containers/food/snacks/grown/apple = list("applejuice" = 0), - /obj/item/reagent_containers/food/snacks/grown/grapes = list("grapejuice" = 0), - /obj/item/reagent_containers/food/snacks/grown/grapes/green = list("grapejuice" = 0)) + var/static/list/juice_items = list( + //Juicer Stuff + /obj/item/reagent_containers/food/snacks/grown/corn = list("corn_starch" = 0), + /obj/item/reagent_containers/food/snacks/grown/tomato = list("tomatojuice" = 0), + /obj/item/reagent_containers/food/snacks/grown/carrot = list("carrotjuice" = 0), + /obj/item/reagent_containers/food/snacks/grown/berries = list("berryjuice" = 0), + /obj/item/reagent_containers/food/snacks/grown/banana = list("banana" = 0), + /obj/item/reagent_containers/food/snacks/grown/potato = list("potato" = 0), + /obj/item/reagent_containers/food/snacks/grown/citrus/lemon = list("lemonjuice" = 0), + /obj/item/reagent_containers/food/snacks/grown/citrus/orange = list("orangejuice" = 0), + /obj/item/reagent_containers/food/snacks/grown/citrus/lime = list("limejuice" = 0), + /obj/item/reagent_containers/food/snacks/grown/watermelon = list("watermelonjuice" = 0), + /obj/item/reagent_containers/food/snacks/watermelonslice = list("watermelonjuice" = 0), + /obj/item/reagent_containers/food/snacks/grown/berries/poison = list("poisonberryjuice" = 0), + /obj/item/reagent_containers/food/snacks/grown/pumpkin = list("pumpkinjuice" = 0), + /obj/item/reagent_containers/food/snacks/grown/blumpkin = list("blumpkinjuice" = 0), + /obj/item/reagent_containers/food/snacks/grown/apple = list("applejuice" = 0), + /obj/item/reagent_containers/food/snacks/grown/grapes = list("grapejuice" = 0), + /obj/item/reagent_containers/food/snacks/grown/grapes/green = list("grapejuice" = 0)) - var/static/list/dried_items = list( - //Grinder stuff, but only if dry, - /obj/item/reagent_containers/food/snacks/grown/coffee/robusta = list("coffeepowder" = 0, "morphine" = 0), - /obj/item/reagent_containers/food/snacks/grown/coffee = list("coffeepowder" = 0), - /obj/item/reagent_containers/food/snacks/grown/tea/astra = list("teapowder" = 0, "salglu_solution" = 0), - /obj/item/reagent_containers/food/snacks/grown/tea = list("teapowder" = 0)) + var/static/list/dried_items = list( + //Grinder stuff, but only if dry, + /obj/item/reagent_containers/food/snacks/grown/coffee/robusta = list("coffeepowder" = 0, "morphine" = 0), + /obj/item/reagent_containers/food/snacks/grown/coffee = list("coffeepowder" = 0), + /obj/item/reagent_containers/food/snacks/grown/tea/astra = list("teapowder" = 0, "salglu_solution" = 0), + /obj/item/reagent_containers/food/snacks/grown/tea = list("teapowder" = 0)) - var/list/holdingitems = list() + var/list/holdingitems /obj/machinery/reagentgrinder/Initialize() . = ..() + holdingitems = list() beaker = new /obj/item/reagent_containers/glass/beaker/large(src) beaker.desc += " May contain blended dust. Don't breathe this in!" /obj/machinery/reagentgrinder/Destroy() QDEL_NULL(beaker) + drop_all_items() return ..() /obj/machinery/reagentgrinder/contents_explosion(severity, target) @@ -96,14 +101,22 @@ beaker.ex_act(severity, target) /obj/machinery/reagentgrinder/handle_atom_del(atom/A) - ..() + . = ..() if(A == beaker) beaker = null update_icon() updateUsrDialog() + if(holdingitems[A]) + holdingitems -= A + +/obj/machinery/reagentgrinder/proc/drop_all_items() + for(var/i in holdingitems) + var/atom/movable/AM = i + AM.forceMove(drop_location()) + holdingitems = list() /obj/machinery/reagentgrinder/deconstruct(disassembled = TRUE) - new /obj/item/stack/sheet/metal (loc, 3) + new /obj/item/stack/sheet/metal (drop_location(), 3) qdel(src) /obj/machinery/reagentgrinder/update_icon() @@ -113,380 +126,344 @@ icon_state = "juicer0" /obj/machinery/reagentgrinder/attackby(obj/item/I, mob/user, params) - if(default_unfasten_wrench(user, I)) - return + if(default_unfasten_wrench(user, I)) + return - if (istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER_1) ) - if (!beaker) - if(!user.transferItemToLoc(I, src)) - return 1 - beaker = I - update_icon() - src.updateUsrDialog() - else - to_chat(user, "There's already a container inside [src].") - return 1 //no afterattack + if (istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER_1) ) + if (!beaker) + if(!user.transferItemToLoc(I, src)) + to_chat(user, "[I] is stuck to your hand!") + return TRUE + beaker = I + update_icon() + updateUsrDialog() + else + to_chat(user, "There's already a container inside [src].") + return TRUE //no afterattack - if(is_type_in_list(I, dried_items)) - if(istype(I, /obj/item/reagent_containers/food/snacks/grown)) - var/obj/item/reagent_containers/food/snacks/grown/G = I - if(!G.dry) - to_chat(user, "You must dry [G] first!") - return 1 + if(is_type_in_list(I, dried_items)) + if(istype(I, /obj/item/reagent_containers/food/snacks/grown)) + var/obj/item/reagent_containers/food/snacks/grown/G = I + if(!G.dry) + to_chat(user, "You must dry [G] first!") + return TRUE - if(holdingitems && holdingitems.len >= limit) - to_chat(usr, "The machine cannot hold anymore items.") - return 1 + if(length(holdingitems) >= limit) + to_chat(user, "The machine cannot hold anymore items.") + return TRUE - //Fill machine with a bag! - if(istype(I, /obj/item/storage/bag)) - var/obj/item/storage/bag/B = I - for (var/obj/item/reagent_containers/food/snacks/grown/G in B.contents) - B.remove_from_storage(G, src) - holdingitems += G - if(holdingitems && holdingitems.len >= limit) //Sanity checking so the blender doesn't overfill - to_chat(user, "You fill [src] to the brim.") - break + //Fill machine with a bag! + if(istype(I, /obj/item/storage/bag)) + var/obj/item/storage/bag/B = I + for (var/obj/item/reagent_containers/food/snacks/grown/G in B.contents) + B.remove_from_storage(G, src) + holdingitems[G] = TRUE + if(length(holdingitems) >= limit) //Sanity checking so the blender doesn't overfill + to_chat(user, "You fill [src] to the brim.") + break - if(!I.contents.len) - to_chat(user, "You empty [I] into [src].") + if(!I.contents.len) + to_chat(user, "You empty [I] into [src].") - src.updateUsrDialog() - return 1 + updateUsrDialog() + return TRUE - if (!is_type_in_list(I, blend_items) && !is_type_in_list(I, juice_items)) - if(user.a_intent == INTENT_HARM) - return ..() - else - to_chat(user, "Cannot refine into a reagent!") - return 1 + if (!is_type_in_list(I, blend_items) && !is_type_in_list(I, juice_items)) + if(user.a_intent == INTENT_HARM) + return ..() + else + to_chat(user, "Cannot refine into a reagent!") + return TRUE - if(user.transferItemToLoc(I, src)) - holdingitems += I - src.updateUsrDialog() - return 0 + if(user.transferItemToLoc(I, src)) + holdingitems[I] = TRUE + updateUsrDialog() + return FALSE /obj/machinery/reagentgrinder/attack_paw(mob/user) - return src.attack_hand(user) + return attack_hand(user) /obj/machinery/reagentgrinder/attack_ai(mob/user) - return 0 + return FALSE /obj/machinery/reagentgrinder/attack_hand(mob/user) - user.set_machine(src) - interact(user) + user.set_machine(src) + interact(user) /obj/machinery/reagentgrinder/interact(mob/user) // The microwave Menu - var/is_chamber_empty = 0 - var/is_beaker_ready = 0 - var/processing_chamber = "" - var/beaker_contents = "" - var/dat = "" + var/is_chamber_empty = FALSE + var/is_beaker_ready = FALSE + var/processing_chamber = "" + var/beaker_contents = "" + var/dat = "" - if(!operating) - for (var/obj/item/O in holdingitems) - processing_chamber += "\A [O.name]
" + if(!operating) + for (var/i in holdingitems) + var/obj/item/O = i + processing_chamber += "\A [O.name]
" - if (!processing_chamber) - is_chamber_empty = 1 - processing_chamber = "Nothing." - if (!beaker) - beaker_contents = "No beaker attached.
" - else - is_beaker_ready = 1 - beaker_contents = "The beaker contains:
" - var/anything = 0 - for(var/datum/reagent/R in beaker.reagents.reagent_list) - anything = 1 - beaker_contents += "[R.volume] - [R.name]
" - if(!anything) - beaker_contents += "Nothing
" - - - dat = {" - Processing chamber contains:
- [processing_chamber]
- [beaker_contents]
- "} - if (is_beaker_ready) - if(!is_chamber_empty && !(stat & (NOPOWER|BROKEN))) - dat += "Grind the reagents
" - dat += "Juice the reagents

" - else if (beaker.reagents.total_volume) - dat += "Mix the reagents

" - if(holdingitems && holdingitems.len > 0) - dat += "Eject the reagents
" - if (beaker) - dat += "Detach the beaker
" + if (!processing_chamber) + is_chamber_empty = TRUE + processing_chamber = "Nothing." + if (!beaker) + beaker_contents = "No beaker attached.
" else - dat += "Please wait..." + is_beaker_ready = TRUE + beaker_contents = "The beaker contains:
" + var/anything = FALSE + for(var/datum/reagent/R in beaker.reagents.reagent_list) + anything = TRUE + beaker_contents += "[R.volume] - [R.name]
" + if(!anything) + beaker_contents += "Nothing
" - var/datum/browser/popup = new(user, "reagentgrinder", "All-In-One Grinder") - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open(1) - return + dat = {" + Processing chamber contains:
+ [processing_chamber]
+ [beaker_contents]
+ "} + if (is_beaker_ready) + if(!is_chamber_empty && !(stat & (NOPOWER|BROKEN))) + dat += "Grind the reagents
" + dat += "Juice the reagents

" + else if (beaker.reagents.total_volume) + dat += "Mix the reagents

" + if(length(holdingitems)) + dat += "Eject the reagents
" + if(beaker) + dat += "Detach the beaker
" + else + dat += "Please wait..." + + var/datum/browser/popup = new(user, "reagentgrinder", "All-In-One Grinder") + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open(1) + return /obj/machinery/reagentgrinder/Topic(href, href_list) if(..()) return - usr.set_machine(src) + var/mob/user = usr + if(!user.canUseTopic(src)) + return + if(stat & (NOPOWER|BROKEN)) + return + user.set_machine(src) if(operating) updateUsrDialog() return switch(href_list["action"]) if ("grind") - grind() + grind(user) if("juice") - juice() + juice(user) if("mix") - mix() + mix(user) if("eject") - eject() - if ("detach") - detach() + eject(user) + if("detach") + detach(user) + updateUsrDialog() -/obj/machinery/reagentgrinder/proc/detach() +/obj/machinery/reagentgrinder/proc/detach(mob/user) + if(!beaker) + return + beaker.forceMove(drop_location()) + beaker = null + update_icon() + updateUsrDialog() - if (usr.stat != 0) - return - if (!beaker) - return - beaker.loc = src.loc - beaker = null - update_icon() - updateUsrDialog() +/obj/machinery/reagentgrinder/proc/eject(mob/user) + if(!length(holdingitems)) + return + for(var/i in holdingitems) + var/obj/item/O = i + O.forceMove(drop_location()) + holdingitems -= O + updateUsrDialog() -/obj/machinery/reagentgrinder/proc/eject() +/obj/machinery/reagentgrinder/proc/get_allowed_by_obj(obj/item/O) + return blend_items[O.type] - if (usr.stat != 0) - return - if (holdingitems && holdingitems.len == 0) - return - - for(var/obj/item/O in holdingitems) - O.loc = src.loc - holdingitems -= O - holdingitems = list() - updateUsrDialog() - -/obj/machinery/reagentgrinder/proc/is_allowed(obj/item/reagent_containers/O) - for (var/i in blend_items) - if(istype(O, i)) - return 1 - return 0 - -/obj/machinery/reagentgrinder/proc/get_allowed_by_id(obj/item/O) - for (var/i in blend_items) - if (istype(O, i)) - return blend_items[i] - -/obj/machinery/reagentgrinder/proc/get_allowed_snack_by_id(obj/item/reagent_containers/food/snacks/O) - for(var/i in blend_items) - if(istype(O, i)) - return blend_items[i] - -/obj/machinery/reagentgrinder/proc/get_allowed_juice_by_id(obj/item/reagent_containers/food/snacks/O) - for(var/i in juice_items) - if(istype(O, i)) - return juice_items[i] +/obj/machinery/reagentgrinder/proc/get_allowed_juice_by_obj(obj/item/reagent_containers/food/snacks/O) + for(var/i in juice_items) + if(istype(O, i)) + return juice_items[i] /obj/machinery/reagentgrinder/proc/get_grownweapon_amount(obj/item/grown/O) - if (!istype(O) || !O.seed) - return 5 - else if (O.seed.potency == -1) - return 5 - else - return round(O.seed.potency) + if (!istype(O) || !O.seed) + return 5 + else if (O.seed.potency == -1) + return 5 + else + return round(O.seed.potency) /obj/machinery/reagentgrinder/proc/get_juice_amount(obj/item/reagent_containers/food/snacks/grown/O) - if (!istype(O) || !O.seed) - return 5 - else if (O.seed.potency == -1) - return 5 - else - return round(5*sqrt(O.seed.potency)) + if (!istype(O) || !O.seed) + return 5 + else if (O.seed.potency == -1) + return 5 + else + return round(5*sqrt(O.seed.potency)) /obj/machinery/reagentgrinder/proc/remove_object(obj/item/O) - holdingitems -= O - qdel(O) + holdingitems -= O + qdel(O) /obj/machinery/reagentgrinder/proc/juice() - power_change() - if(stat & (NOPOWER|BROKEN)) - return - if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)) - return - playsound(src.loc, 'sound/machines/juicer.ogg', 20, 1) - var/offset = prob(50) ? -2 : 2 - animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 250) //start shaking - operating = TRUE - updateUsrDialog() - spawn(50) - pixel_x = initial(pixel_x) //return to its spot after shaking - operating = FALSE - updateUsrDialog() + power_change() + if(!beaker || (beaker && (beaker.reagents.total_volume >= beaker.reagents.maximum_volume))) + return + operate_for(50, juicing = TRUE) - //Snacks - for (var/obj/item/reagent_containers/food/snacks/O in holdingitems) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break + //Snacks + for(var/obj/item/i in holdingitems) + var/obj/item/I = i + if(istype(I, /obj/item/reagent_containers/food/snacks)) + var/obj/item/reagent_containers/food/snacks/O = I + if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + var/list/allowed = get_allowed_juice_by_obj(O) + if(isnull(allowed)) + break + for(var/r_id in allowed) + var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume + var/amount = get_juice_amount(O) + beaker.reagents.add_reagent(r_id, min(amount, space)) + if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + remove_object(O) - var/allowed = get_allowed_juice_by_id(O) - if(isnull(allowed)) - break +/obj/machinery/reagentgrinder/proc/shake_for(duration) + var/offset = prob(50) ? -2 : 2 + var/old_pixel_x = pixel_x + animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = -1) //start shaking + addtimer(CALLBACK(src, .proc/stop_shaking, old_pixel_x), duration) - for (var/r_id in allowed) +/obj/machinery/reagentgrinder/proc/stop_shaking(old_px) + animate(src) + pixel_x = old_px - var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - var/amount = get_juice_amount(O) +/obj/machinery/reagentgrinder/proc/operate_for(time, silent = FALSE, juicing = FALSE) + shake_for(time) + updateUsrDialog() + operating = TRUE + if(!silent) + if(!juicing) + playsound(src, 'sound/machines/blender.ogg', 50, 1) + else + playsound(src, 'sound/machines/juicer.ogg', 20, 1) + addtimer(CALLBACK(src, .proc/stop_operating), time) - beaker.reagents.add_reagent(r_id, min(amount, space)) - - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - - remove_object(O) +/obj/machinery/reagentgrinder/proc/stop_operating() + operating = FALSE + updateUsrDialog() /obj/machinery/reagentgrinder/proc/grind() - power_change() - if(stat & (NOPOWER|BROKEN)) - return - if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)) - return - playsound(src.loc, 'sound/machines/blender.ogg', 50, 1) - var/offset = prob(50) ? -2 : 2 - animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 250) //start shaking - operating = TRUE - updateUsrDialog() - spawn(60) - pixel_x = initial(pixel_x) //return to its spot after shaking - operating = FALSE - updateUsrDialog() - - //Snacks and Plants - for (var/obj/item/reagent_containers/food/snacks/O in holdingitems) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - - var/allowed = get_allowed_snack_by_id(O) - if(isnull(allowed)) - break - - for (var/r_id in allowed) - - var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - var/amount = allowed[r_id] - if(amount <= 0) - if(amount == 0) - if (O.reagents != null && O.reagents.has_reagent("nutriment")) - beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("nutriment"), space)) - O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) - else - if (O.reagents != null && O.reagents.has_reagent("nutriment")) - beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("nutriment")*abs(amount)), space)) - O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) - - else - O.reagents.trans_id_to(beaker, r_id, min(amount, space)) - - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - - if(O.reagents.reagent_list.len == 0) - remove_object(O) - - //Sheets - for (var/obj/item/stack/sheet/O in holdingitems) - var/allowed = get_allowed_by_id(O) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - for(var/i = 1; i <= round(O.amount, 1); i++) - for (var/r_id in allowed) - var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - var/amount = allowed[r_id] - beaker.reagents.add_reagent(r_id,min(amount, space)) - if (space < amount) - break - if (i == round(O.amount, 1)) - remove_object(O) - break - //Plants - for (var/obj/item/grown/O in holdingitems) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - var/allowed = get_allowed_by_id(O) - for (var/r_id in allowed) - var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - var/amount = allowed[r_id] - if (amount == 0) - if (O.reagents != null && O.reagents.has_reagent(r_id)) - beaker.reagents.add_reagent(r_id,min(O.reagents.get_reagent_amount(r_id), space)) - else - beaker.reagents.add_reagent(r_id,min(amount, space)) - - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - remove_object(O) - - //Slime Extractis - for (var/obj/item/slime_extract/O in holdingitems) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break + power_change() + if(!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)) + return + operate_for(60) + for(var/i in holdingitems) + if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + var/obj/item/I = i + //Snacks + if(istype(I, /obj/item/reagent_containers/food/snacks)) + var/obj/item/reagent_containers/food/snacks/O = I + var/list/allowed = get_allowed_by_obj(O) + if(isnull(allowed)) + continue + for(var/r_id in allowed) var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - if (O.reagents != null) - var/amount = O.reagents.total_volume - O.reagents.trans_to(beaker, min(amount, space)) - if (O.Uses > 0) - beaker.reagents.add_reagent("slimejelly",min(20, space)) + var/amount = allowed[r_id] + if(amount <= 0) + if(amount == 0) + if (O.reagents != null && O.reagents.has_reagent("nutriment")) + beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("nutriment"), space)) + O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) + else + if (O.reagents != null && O.reagents.has_reagent("nutriment")) + beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("nutriment")*abs(amount)), space)) + O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) + else + O.reagents.trans_id_to(beaker, r_id, min(amount, space)) + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + if(O.reagents.reagent_list.len == 0) + remove_object(O) + //Sheets + else if(istype(I, /obj/item/stack/sheet)) + var/obj/item/stack/sheet/O = I + var/list/allowed = get_allowed_by_obj(O) + for(var/t in 1 to round(O.amount, 1)) + for(var/r_id in allowed) + var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume + var/amount = allowed[r_id] + beaker.reagents.add_reagent(r_id,min(amount, space)) + if (space < amount) + break + if(t == round(O.amount, 1)) + remove_object(O) + break + //Plants + else if(istype(I, /obj/item/grown)) + var/obj/item/grown/O = I + var/list/allowed = get_allowed_by_obj(O) + for (var/r_id in allowed) + var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume + var/amount = allowed[r_id] + if (amount == 0) + if (O.reagents != null && O.reagents.has_reagent(r_id)) + beaker.reagents.add_reagent(r_id,min(O.reagents.get_reagent_amount(r_id), space)) + else + beaker.reagents.add_reagent(r_id,min(amount, space)) + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + remove_object(O) + else if(istype(I, /obj/item/slime_extract)) + var/obj/item/slime_extract/O = I + var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume + if (O.reagents != null) + var/amount = O.reagents.total_volume + O.reagents.trans_to(beaker, min(amount, space)) + if (O.Uses > 0) + beaker.reagents.add_reagent("slimejelly",min(20, space)) + remove_object(O) + else if(istype(I, /obj/item/reagent_containers)) + var/obj/item/reagent_containers/O = I + var/amount = O.reagents.total_volume + O.reagents.trans_to(beaker, amount) + if(!O.reagents.total_volume) + remove_object(O) + else if(istype(I, /obj/item/toy/crayon)) + var/obj/item/toy/crayon/O = I + for (var/r_id in O.reagent_contents) + var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume + if(!space) + break + beaker.reagents.add_reagent(r_id, min(O.reagent_contents[r_id], space)) remove_object(O) - //Everything else - Transfers reagents from it into beaker - for (var/obj/item/reagent_containers/O in holdingitems) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - var/amount = O.reagents.total_volume - O.reagents.trans_to(beaker, amount) - if(!O.reagents.total_volume) - remove_object(O) - - for (var/obj/item/toy/crayon/O in holdingitems) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - for (var/r_id in O.reagent_contents) - var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - if (space == 0) - break - beaker.reagents.add_reagent(r_id, min(O.reagent_contents[r_id], space)) - remove_object(O) - -/obj/machinery/reagentgrinder/proc/mix() - - //For butter and other things that would change upon shaking or mixing - power_change() - if(stat & (NOPOWER|BROKEN)) - return - if (!beaker) - return - playsound(src.loc, 'sound/machines/juicer.ogg', 20, 1) - var/offset = prob(50) ? -2 : 2 - animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 250) //start shaking - operating = TRUE - updateUsrDialog() - addtimer(CALLBACK(src, /obj/machinery/reagentgrinder/proc/mix_complete), 50) +/obj/machinery/reagentgrinder/proc/mix(mob/user) + //For butter and other things that would change upon shaking or mixing + power_change() + if(!beaker) + return + operate_for(50, juicing = TRUE) + addtimer(CALLBACK(src, /obj/machinery/reagentgrinder/proc/mix_complete), 50) /obj/machinery/reagentgrinder/proc/mix_complete() - pixel_x = initial(pixel_x) //return to its spot after shaking - operating = FALSE - updateUsrDialog() - if (beaker.reagents.total_volume) - //Recipe to make Butter - while(beaker.reagents.get_reagent_amount("milk") >= 15) - beaker.reagents.remove_reagent("milk", 15) - new /obj/item/reagent_containers/food/snacks/butter(src.loc) - //Recipe to make Mayonnaise - if (beaker.reagents.has_reagent("eggyolk")) - var/amount = beaker.reagents.get_reagent_amount("eggyolk") - beaker.reagents.remove_reagent("eggyolk", amount) - beaker.reagents.add_reagent("mayonnaise", amount) + if(beaker && beaker.reagents.total_volume) + //Recipe to make Butter + var/butter_amt = Floor(beaker.reagents.get_reagent_amount("milk") / MILK_TO_BUTTER_COEFF) + beaker.reagents.remove_reagent("milk", MILK_TO_BUTTER_COEFF * butter_amt) + for(var/i in 1 to butter_amt) + new /obj/item/reagent_containers/food/snacks/butter(drop_location()) + //Recipe to make Mayonnaise + if (beaker.reagents.has_reagent("eggyolk")) + var/amount = beaker.reagents.get_reagent_amount("eggyolk") + beaker.reagents.remove_reagent("eggyolk", amount) + beaker.reagents.add_reagent("mayonnaise", amount) diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index f9a2c0d63c..ebeb869d9c 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -28,8 +28,9 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). ) /obj/machinery/r_n_d/circuit_imprinter/Initialize() - AddComponent(/datum/component/material_container, list(MAT_GLASS, MAT_GOLD, MAT_DIAMOND, MAT_METAL, MAT_BLUESPACE), + var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_GLASS, MAT_GOLD, MAT_DIAMOND, MAT_METAL, MAT_BLUESPACE), FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready)) + materials.precise_insertion = TRUE create_reagents(0) return ..() diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index 88c902a70d..9df4946ed2 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -33,9 +33,10 @@ Note: Must be placed west/left of and R&D console to function. /obj/machinery/r_n_d/protolathe/Initialize() create_reagents(0) - AddComponent(/datum/component/material_container, + var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready)) + materials.precise_insertion = TRUE return ..() /obj/machinery/r_n_d/protolathe/RefreshParts()