322 lines
11 KiB
Plaintext
322 lines
11 KiB
Plaintext
|
|
#define MILK_TO_BUTTER_COEFF 15
|
|
|
|
/obj/machinery/reagentgrinder
|
|
name = "\improper 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
|
|
use_power = IDLE_POWER_USE
|
|
idle_power_usage = 5
|
|
active_power_usage = 100
|
|
circuit = /obj/item/circuitboard/machine/reagentgrinder
|
|
pass_flags = PASSTABLE
|
|
resistance_flags = ACID_PROOF
|
|
var/operating = FALSE
|
|
var/obj/item/reagent_containers/beaker = null
|
|
var/limit = 10
|
|
var/speed = 1
|
|
var/list/holdingitems
|
|
|
|
var/static/radial_examine = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine")
|
|
var/static/radial_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject")
|
|
var/static/radial_grind = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_grind")
|
|
var/static/radial_juice = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_juice")
|
|
var/static/radial_mix = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_mix")
|
|
|
|
/obj/machinery/reagentgrinder/Initialize(mapload)
|
|
. = ..()
|
|
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/constructed/Initialize(mapload)
|
|
. = ..()
|
|
holdingitems = list()
|
|
QDEL_NULL(beaker)
|
|
update_icon()
|
|
|
|
/obj/machinery/reagentgrinder/Destroy()
|
|
if(beaker)
|
|
beaker.forceMove(drop_location())
|
|
drop_all_items()
|
|
return ..()
|
|
|
|
/obj/machinery/reagentgrinder/contents_explosion(severity, target, origin)
|
|
if(beaker)
|
|
beaker.ex_act(severity, target, origin)
|
|
|
|
/obj/machinery/reagentgrinder/RefreshParts()
|
|
speed = 1
|
|
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
|
speed = M.rating
|
|
|
|
/obj/machinery/reagentgrinder/handle_atom_del(atom/A)
|
|
. = ..()
|
|
if(A == beaker)
|
|
beaker = null
|
|
update_icon()
|
|
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/update_icon_state()
|
|
if(beaker)
|
|
icon_state = "juicer1"
|
|
else
|
|
icon_state = "juicer0"
|
|
|
|
/obj/machinery/reagentgrinder/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
|
|
if(beaker)
|
|
beaker.forceMove(drop_location())
|
|
if(user && Adjacent(user) && user.can_hold_items())
|
|
user.put_in_hands(beaker)
|
|
if(new_beaker)
|
|
beaker = new_beaker
|
|
else
|
|
beaker = null
|
|
update_icon()
|
|
return TRUE
|
|
|
|
/obj/machinery/reagentgrinder/attackby(obj/item/I, mob/user, params)
|
|
//You can only screw open empty grinder
|
|
if(!beaker && !length(holdingitems) && default_deconstruction_screwdriver(user, icon_state, icon_state, I))
|
|
return
|
|
|
|
if(default_deconstruction_crowbar(I))
|
|
return
|
|
|
|
if(default_unfasten_wrench(user, I))
|
|
return
|
|
|
|
if(panel_open) //Can't insert objects when its screwed open
|
|
return TRUE
|
|
|
|
if (istype(I, /obj/item/reagent_containers) && !(I.item_flags & ABSTRACT) && I.is_open_container())
|
|
var/obj/item/reagent_containers/B = I
|
|
. = TRUE
|
|
if(!user.transferItemToLoc(B, src))
|
|
return
|
|
replace_beaker(user, B)
|
|
to_chat(user, "<span class='notice'>You add [B] to [src].</span>")
|
|
update_icon()
|
|
return
|
|
|
|
if(holdingitems.len >= limit)
|
|
to_chat(user, "<span class='warning'>[src] is filled to capacity!</span>")
|
|
return TRUE
|
|
|
|
//Fill machine with a bag!
|
|
if(istype(I, /obj/item/storage/bag))
|
|
var/list/inserted = list()
|
|
if(SEND_SIGNAL(I, COMSIG_TRY_STORAGE_TAKE_TYPE, /obj/item/reagent_containers/food/snacks/grown, src, limit - length(holdingitems), null, null, user, inserted))
|
|
for(var/i in inserted)
|
|
holdingitems[i] = TRUE
|
|
if(!I.contents.len)
|
|
to_chat(user, "<span class='notice'>You empty [I] into [src].</span>")
|
|
else
|
|
to_chat(user, "<span class='notice'>You fill [src] to the brim.</span>")
|
|
return TRUE
|
|
|
|
if(!I.grind_results && !I.juice_results)
|
|
if(user.a_intent == INTENT_HARM)
|
|
return ..()
|
|
else
|
|
to_chat(user, "<span class='warning'>You cannot grind [I] into reagents!</span>")
|
|
return TRUE
|
|
|
|
if(!I.grind_requirements(src)) //Error messages should be in the objects' definitions
|
|
return
|
|
|
|
if(user.transferItemToLoc(I, src))
|
|
to_chat(user, "<span class='notice'>You add [I] to [src].</span>")
|
|
holdingitems[I] = TRUE
|
|
return FALSE
|
|
|
|
/obj/machinery/reagentgrinder/ui_interact(mob/user) // The microwave Menu //I am reasonably certain that this is not a microwave
|
|
. = ..()
|
|
|
|
if(operating || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
|
return
|
|
|
|
var/list/options = list()
|
|
|
|
if(beaker || length(holdingitems))
|
|
options["eject"] = radial_eject
|
|
|
|
if(isAI(user))
|
|
if(machine_stat & NOPOWER)
|
|
return
|
|
options["examine"] = radial_examine
|
|
|
|
// if there is no power or it's broken, the procs will fail but the buttons will still show
|
|
if(length(holdingitems))
|
|
options["grind"] = radial_grind
|
|
options["juice"] = radial_juice
|
|
else if(beaker?.reagents.total_volume)
|
|
options["mix"] = radial_mix
|
|
|
|
var/choice
|
|
|
|
if(length(options) < 1)
|
|
return
|
|
if(length(options) == 1)
|
|
for(var/key in options)
|
|
choice = key
|
|
else
|
|
choice = show_radial_menu(user, src, options, require_near = !hasSiliconAccessInArea(user))
|
|
|
|
// post choice verification
|
|
if(operating || (isAI(user) && machine_stat & NOPOWER) || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
|
return
|
|
|
|
switch(choice)
|
|
if("eject")
|
|
eject(user)
|
|
if("grind")
|
|
grind(user)
|
|
if("juice")
|
|
juice(user)
|
|
if("mix")
|
|
mix(user)
|
|
if("examine")
|
|
examine(user)
|
|
|
|
/obj/machinery/reagentgrinder/examine(mob/user)
|
|
. = ..()
|
|
if(!in_range(user, src) && !hasSiliconAccessInArea(user) && !isobserver(user))
|
|
. += "<span class='warning'>You're too far away to examine [src]'s contents and display!</span>"
|
|
return
|
|
|
|
if(operating)
|
|
. += "<span class='warning'>\The [src] is operating.</span>"
|
|
return
|
|
|
|
if(beaker || length(holdingitems))
|
|
. += "<span class='notice'>\The [src] contains:</span>"
|
|
if(beaker)
|
|
. += "<span class='notice'>- \A [beaker].</span>"
|
|
for(var/i in holdingitems)
|
|
var/obj/item/O = i
|
|
. += "<span class='notice'>- \A [O.name].</span>"
|
|
|
|
if(!(machine_stat & (NOPOWER|BROKEN)))
|
|
. += "<span class='notice'>The status display reads:</span>"
|
|
. += "<span class='notice'>- Grinding reagents at <b>[speed*100]%</b>.<span>"
|
|
if(beaker)
|
|
for(var/datum/reagent/R in beaker.reagents.reagent_list)
|
|
. += "<span class='notice'>- [R.volume] units of [R.name].</span>"
|
|
|
|
/obj/machinery/reagentgrinder/AltClick(mob/user)
|
|
. = ..()
|
|
if(istype(user) && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
|
replace_beaker(user)
|
|
|
|
/obj/machinery/reagentgrinder/proc/eject(mob/user)
|
|
for(var/i in holdingitems)
|
|
var/obj/item/O = i
|
|
O.forceMove(drop_location())
|
|
holdingitems -= O
|
|
if(beaker)
|
|
replace_beaker(user)
|
|
|
|
/obj/machinery/reagentgrinder/proc/remove_object(obj/item/O)
|
|
holdingitems -= O
|
|
qdel(O)
|
|
|
|
/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_REF(stop_shaking), old_pixel_x), duration)
|
|
|
|
/obj/machinery/reagentgrinder/proc/stop_shaking(old_px)
|
|
animate(src)
|
|
pixel_x = old_px
|
|
|
|
/obj/machinery/reagentgrinder/proc/operate_for(time, silent = FALSE, juicing = FALSE)
|
|
shake_for(time / speed)
|
|
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_REF(stop_operating)), time / speed)
|
|
|
|
/obj/machinery/reagentgrinder/proc/stop_operating()
|
|
operating = FALSE
|
|
|
|
/obj/machinery/reagentgrinder/proc/juice()
|
|
power_change()
|
|
if(!beaker || machine_stat & (NOPOWER|BROKEN) || beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
|
|
return
|
|
operate_for(50, juicing = TRUE)
|
|
for(var/obj/item/i in holdingitems)
|
|
if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
|
|
break
|
|
var/obj/item/I = i
|
|
if(I.juice_results)
|
|
juice_item(I)
|
|
|
|
/obj/machinery/reagentgrinder/proc/juice_item(obj/item/I) //Juicing results can be found in respective object definitions
|
|
if(I.on_juice(src) == -1)
|
|
to_chat(usr, "<span class='danger'>[src] shorts out as it tries to juice up [I], and transfers it back to storage.</span>")
|
|
return
|
|
beaker.reagents.add_reagent_list(I.juice_results)
|
|
remove_object(I)
|
|
|
|
/obj/machinery/reagentgrinder/proc/grind()
|
|
power_change()
|
|
if(!beaker || machine_stat & (NOPOWER|BROKEN) || 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
|
|
if(I.grind_results)
|
|
grind_item(i)
|
|
|
|
/obj/machinery/reagentgrinder/proc/grind_item(obj/item/I) //Grind results can be found in respective object definitions
|
|
if(I.on_grind(src) == -1) //Call on_grind() to change amount as needed, and stop grinding the item if it returns -1
|
|
to_chat(usr, "<span class='danger'>[src] shorts out as it tries to grind up [I], and transfers it back to storage.</span>")
|
|
return
|
|
beaker.reagents.add_reagent_list(I.grind_results)
|
|
if(I.reagents)
|
|
I.reagents.trans_to(beaker, I.reagents.total_volume)
|
|
remove_object(I)
|
|
|
|
/obj/machinery/reagentgrinder/proc/mix(mob/user)
|
|
//For butter and other things that would change upon shaking or mixing
|
|
power_change()
|
|
if(!beaker || machine_stat & (NOPOWER|BROKEN))
|
|
return
|
|
operate_for(50, juicing = TRUE)
|
|
addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/machinery/reagentgrinder, mix_complete)), 50)
|
|
|
|
/obj/machinery/reagentgrinder/proc/mix_complete()
|
|
if(beaker?.reagents.total_volume)
|
|
//Recipe to make Butter
|
|
var/butter_amt = FLOOR(beaker.reagents.get_reagent_amount(/datum/reagent/consumable/milk) / MILK_TO_BUTTER_COEFF, 1)
|
|
beaker.reagents.remove_reagent(/datum/reagent/consumable/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(/datum/reagent/consumable/eggyolk))
|
|
var/amount = beaker.reagents.get_reagent_amount(/datum/reagent/consumable/eggyolk)
|
|
beaker.reagents.remove_reagent(/datum/reagent/consumable/eggyolk, amount)
|
|
beaker.reagents.add_reagent(/datum/reagent/consumable/mayonnaise, amount)
|
|
//Moonsugar for skooma
|
|
if(beaker.reagents.has_reagent(/datum/reagent/consumable/sugar) && beaker.reagents.has_reagent(/datum/reagent/consumable/ethanol/moonshine))
|
|
var/amount = min(beaker.reagents.get_reagent_amount(/datum/reagent/consumable/sugar), beaker.reagents.get_reagent_amount(/datum/reagent/consumable/ethanol/moonshine))
|
|
beaker.reagents.remove_reagent(/datum/reagent/consumable/sugar, amount)
|
|
beaker.reagents.remove_reagent(/datum/reagent/consumable/ethanol/moonshine, amount)
|
|
beaker.reagents.add_reagent(/datum/reagent/moonsugar, amount*2)
|