mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-22 03:27:05 +01:00
603 lines
20 KiB
Plaintext
603 lines
20 KiB
Plaintext
#define NO_DIRT 0
|
|
#define MAX_DIRT 100
|
|
|
|
/obj/machinery/kitchen_machine
|
|
name = "Base Kitchen Machine"
|
|
desc = "If you are seeing this, a coder/mapper messed up. Please report it."
|
|
layer = 2.9
|
|
density = TRUE
|
|
anchored = TRUE
|
|
idle_power_consumption = 5
|
|
active_power_consumption = 100
|
|
container_type = OPENCONTAINER
|
|
var/operating = FALSE // Is it on?
|
|
var/dirty = NO_DIRT // = {0..100} Does it need cleaning?
|
|
var/efficiency = 0
|
|
var/list/cook_verbs = list("Cooking")
|
|
//Recipe & Item vars
|
|
var/recipe_type //Make sure to set this on the machine definition, or else you're gonna runtime on New()
|
|
var/max_n_of_items = 25
|
|
//Icon states
|
|
var/off_icon
|
|
var/on_icon
|
|
var/dirty_icon
|
|
var/open_icon
|
|
///Sound used when starting and ending cooking
|
|
var/datum/looping_sound/kitchen/soundloop
|
|
var/soundloop_type
|
|
/// Time between special attacks
|
|
var/special_attack_cooldown_time = 7 SECONDS
|
|
/// Whether or not a special attack can be performed right now
|
|
var/special_attack_on_cooldown = FALSE
|
|
|
|
/*******************
|
|
* Initialising
|
|
********************/
|
|
|
|
/obj/machinery/kitchen_machine/Initialize(mapload)
|
|
. = ..()
|
|
if(soundloop_type)
|
|
soundloop = new soundloop_type(list(src), FALSE)
|
|
create_reagents(100)
|
|
reagents.set_reacting(FALSE)
|
|
init_lists()
|
|
|
|
/obj/machinery/kitchen_machine/Destroy()
|
|
QDEL_NULL(soundloop)
|
|
return ..()
|
|
|
|
/obj/machinery/kitchen_machine/proc/init_lists()
|
|
if(!GLOB.cooking_recipes[recipe_type])
|
|
GLOB.cooking_recipes[recipe_type] = list()
|
|
GLOB.cooking_ingredients[recipe_type] = list()
|
|
GLOB.cooking_reagents[recipe_type] = list()
|
|
if(!length(GLOB.cooking_recipes[recipe_type]))
|
|
for(var/type in subtypesof(GLOB.cooking_recipe_types[recipe_type]))
|
|
var/datum/recipe/recipe = new type
|
|
if(recipe in GLOB.cooking_recipes[recipe_type])
|
|
qdel(recipe)
|
|
continue
|
|
if(recipe.result) // Ignore recipe subtypes that lack a result
|
|
GLOB.cooking_recipes[recipe_type] += recipe
|
|
for(var/item in recipe.items)
|
|
GLOB.cooking_ingredients[recipe_type] |= item
|
|
for(var/reagent in recipe.reagents)
|
|
GLOB.cooking_reagents[recipe_type] |= reagent
|
|
else
|
|
qdel(recipe)
|
|
GLOB.cooking_ingredients[recipe_type] |= /obj/item/food/grown
|
|
|
|
/*******************
|
|
* Item Adding
|
|
********************/
|
|
|
|
/obj/machinery/kitchen_machine/attackby(obj/item/O, mob/user, params)
|
|
if(operating)
|
|
return
|
|
|
|
if(dirty < MAX_DIRT)
|
|
if(default_deconstruction_screwdriver(user, open_icon, off_icon, O))
|
|
return
|
|
|
|
if(istype(O, /obj/item/storage/part_replacer))
|
|
return ..()
|
|
|
|
default_deconstruction_crowbar(user, O)
|
|
|
|
if(dirty == MAX_DIRT) // The machine is all dirty so can't be used!
|
|
if(istype(O, /obj/item/reagent_containers/spray/cleaner) || istype(O, /obj/item/soap) || istype(O, /obj/item/reagent_containers/glass/rag)) // If they're trying to clean it then let them
|
|
user.visible_message("<span class='notice'>[user] starts to clean [src].</span>", "<span class='notice'>You start to clean [src].</span>")
|
|
if(do_after(user, 20 * O.toolspeed, target = src))
|
|
user.visible_message("<span class='notice'>[user] has cleaned [src].</span>", "<span class='notice'>You have cleaned [src].</span>")
|
|
dirty = NO_DIRT
|
|
update_icon(UPDATE_ICON_STATE)
|
|
container_type = OPENCONTAINER
|
|
return TRUE
|
|
|
|
else //Otherwise bad luck!!
|
|
to_chat(user, "<span class='alert'>It's dirty!</span>")
|
|
return TRUE
|
|
|
|
if(is_type_in_list(O, GLOB.cooking_ingredients[recipe_type]) || istype(O, /obj/item/mixing_bowl))
|
|
if(length(contents) >= max_n_of_items)
|
|
to_chat(user, "<span class='alert'>This [src] is full of ingredients, you cannot put more.</span>")
|
|
return TRUE
|
|
|
|
if(istype(O,/obj/item/stack))
|
|
var/obj/item/stack/S = O
|
|
if(S.get_amount() > 1)
|
|
var/obj/item/stack/to_add = S.split(user, 1)
|
|
to_add.forceMove(src)
|
|
user.visible_message("<span class='notice'>[user] adds one of [S] to [src].</span>", "<span class='notice'>You add one of [S] to [src].</span>")
|
|
else
|
|
add_item(S, user)
|
|
else
|
|
add_item(O, user)
|
|
else if(is_type_in_list(O, list(/obj/item/reagent_containers/glass, /obj/item/reagent_containers/drinks, /obj/item/reagent_containers/condiment)))
|
|
if(!O.reagents)
|
|
return TRUE
|
|
|
|
for(var/datum/reagent/R in O.reagents.reagent_list)
|
|
if(!(R.id in GLOB.cooking_reagents[recipe_type]))
|
|
to_chat(user, "<span class='alert'>Your [O] contains components unsuitable for cookery.</span>")
|
|
return TRUE
|
|
|
|
else if(istype(O, /obj/item/grab))
|
|
var/obj/item/grab/G = O
|
|
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
|
to_chat(user, "<span class='danger'>Slamming [G.affecting] into [src] might hurt them!</span>")
|
|
return
|
|
return special_attack_grab(G, user)
|
|
|
|
else
|
|
to_chat(user, "<span class='alert'>You have no idea what you can cook with [O].</span>")
|
|
return TRUE
|
|
|
|
/obj/machinery/kitchen_machine/wrench_act(mob/living/user, obj/item/I)
|
|
if(operating)
|
|
return
|
|
|
|
default_unfasten_wrench(user, I, 0)
|
|
return TRUE
|
|
|
|
/obj/machinery/kitchen_machine/proc/add_item(obj/item/I, mob/user)
|
|
if(!user.drop_item())
|
|
to_chat(user, "<span class='notice'>[I] is stuck to your hand, you cannot put it in [src]</span>")
|
|
return
|
|
|
|
I.forceMove(src)
|
|
user.visible_message("<span class='notice'>[user] adds [I] to [src].</span>", "<span class='notice'>You add [I] to [src].</span>")
|
|
SStgui.update_uis(src)
|
|
|
|
/obj/machinery/kitchen_machine/attack_ai(mob/user)
|
|
return FALSE
|
|
|
|
/obj/machinery/kitchen_machine/proc/special_attack_grab(obj/item/grab/G, mob/user)
|
|
if(special_attack_on_cooldown)
|
|
return FALSE
|
|
if(!istype(G))
|
|
return FALSE
|
|
if(!iscarbon(G.affecting))
|
|
to_chat(user, "<span class='warning'>You can't shove that in there!</span>")
|
|
return FALSE
|
|
if(G.state < GRAB_AGGRESSIVE)
|
|
to_chat(user, "<span class='warning'>You need a better grip to do that!</span>")
|
|
return FALSE
|
|
var/result = special_attack(user, G.affecting, TRUE)
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
special_attack_on_cooldown = TRUE
|
|
addtimer(VARSET_CALLBACK(src, special_attack_on_cooldown, FALSE), special_attack_cooldown_time)
|
|
if(result && !isnull(G) && !QDELETED(G))
|
|
qdel(G)
|
|
|
|
return TRUE
|
|
|
|
/**
|
|
* Perform the special grab interaction.
|
|
* Return TRUE to drop the grab or FALSE to keep the grab afterwards.
|
|
*/
|
|
/obj/machinery/kitchen_machine/proc/special_attack(mob/user, mob/living/carbon/target, obj/item/grab/G)
|
|
to_chat(user, "<span class='alert'>This is ridiculous. You can not fit [target] in this [src].</span>")
|
|
return FALSE
|
|
|
|
/obj/machinery/kitchen_machine/shove_impact(mob/living/target, mob/living/attacker)
|
|
if(special_attack_on_cooldown)
|
|
return FALSE
|
|
|
|
if(!operating)
|
|
// only do a special interaction if it's actually cooking something
|
|
return FALSE
|
|
|
|
return special_attack_shove(target, attacker)
|
|
|
|
/**
|
|
* Perform a special shove attack.
|
|
* The return value of this proc gets passed up to shove_impact, so returning TRUE will prevent any further shove handling (like knockdown).
|
|
*/
|
|
/obj/machinery/kitchen_machine/proc/special_attack_shove(mob/living/target, mob/living/attacker)
|
|
return FALSE
|
|
|
|
/********************
|
|
* Machine Menu *
|
|
********************/
|
|
|
|
/obj/machinery/kitchen_machine/proc/format_content_descs()
|
|
. = ""
|
|
var/list/items_counts = list()
|
|
var/list/name_overrides = list()
|
|
for(var/obj/O in contents)
|
|
var/display_name = O.name
|
|
if(isfood(O))
|
|
var/obj/item/food/food = O
|
|
if(!items_counts[display_name])
|
|
if(food.ingredient_name)
|
|
name_overrides[display_name] = food.ingredient_name
|
|
else
|
|
name_overrides[display_name] = display_name
|
|
else
|
|
if(food.ingredient_name_plural)
|
|
name_overrides[display_name] = food.ingredient_name_plural
|
|
else if(items_counts[display_name] == 1) // Must only add "s" once or you get stuff like "eggsssss"
|
|
name_overrides[display_name] = "[name_overrides[display_name]]s" //name_overrides[display_name] Will be set on the first time as the singular form
|
|
|
|
items_counts[display_name]++
|
|
|
|
for(var/O in items_counts)
|
|
var/N = items_counts[O]
|
|
if(!(O in name_overrides))
|
|
. += {"<b>[capitalize(O)]:</b> [N] [lowertext(O)]\s<br>"}
|
|
else
|
|
if(N==1)
|
|
. += {"<b>[capitalize(O)]:</b> [N] [name_overrides[O]]<br>"}
|
|
else
|
|
. += {"<b>[capitalize(O)]:</b> [N] [name_overrides[O]]<br>"}
|
|
|
|
for(var/datum/reagent/R in reagents.reagent_list)
|
|
var/display_name = R.name
|
|
if(R.id == "capsaicin")
|
|
display_name = "Hotsauce"
|
|
if(R.id == "frostoil")
|
|
display_name = "Coldsauce"
|
|
|
|
. += {"<b>[display_name]:</b> [R.volume] unit\s<br>"}
|
|
|
|
/************************************
|
|
* Machine Menu Handling/Cooking *
|
|
************************************/
|
|
|
|
/obj/machinery/kitchen_machine/proc/cook()
|
|
if(stat & (NOPOWER|BROKEN))
|
|
return
|
|
start()
|
|
if(!has_cookables()) //dry run
|
|
if(!wzhzhzh(10))
|
|
abort()
|
|
return
|
|
stop()
|
|
return
|
|
|
|
var/list/recipes_to_make = choose_recipes()
|
|
|
|
if(length(recipes_to_make) == 1 && recipes_to_make[1][2] == RECIPE_FAIL)
|
|
//This only runs if there is a single recipe source to be made and it is a failure (the machine was loaded with only 1 mixing bowl that results in failure OR was directly loaded with ingredients that results in failure).
|
|
//If there are multiple sources, this bit gets skipped.
|
|
dirty += 1
|
|
if(prob(max(10, dirty * 5) || has_extra_item())) // 5% failure per failed recipee, maxed at 10%, or it has an extra item
|
|
if(!wzhzhzh(4))
|
|
abort()
|
|
return
|
|
muck_start()
|
|
wzhzhzh(4)
|
|
muck_finish()
|
|
fail()
|
|
return
|
|
else //otherwise just stop without requiring cleaning
|
|
if(!wzhzhzh(10))
|
|
abort()
|
|
return
|
|
stop()
|
|
fail()
|
|
return
|
|
else
|
|
if(!wzhzhzh(5))
|
|
abort()
|
|
return
|
|
if(!wzhzhzh(5))
|
|
abort()
|
|
fail()
|
|
return
|
|
make_recipes(recipes_to_make)
|
|
|
|
/obj/machinery/kitchen_machine/proc/dispose(mob/user)
|
|
for(var/obj/O in contents)
|
|
O.forceMove(loc)
|
|
O.pixel_y = rand(-5, 5)
|
|
O.pixel_x = rand(-5, 5)
|
|
if(reagents.total_volume)
|
|
dirty++
|
|
reagents.clear_reagents()
|
|
to_chat(user, "<span class='notice'>You eject the contents of [src].</span>")
|
|
SStgui.update_uis(src)
|
|
|
|
//choose_recipes(): picks out recipes for the machine and any mixing bowls it may contain.
|
|
//builds a list of the selected recipes to be made in a later proc by associating the "source" of the ingredients (mixing bowl, machine) with the recipe for that source
|
|
/obj/machinery/kitchen_machine/proc/choose_recipes()
|
|
var/list/recipes_to_make = list()
|
|
for(var/obj/item/mixing_bowl/mb in contents) //if we have mixing bowls present, check each one for possible recipes from its respective contents. Mixing bowls act like a wrapper for recipes and ingredients, isolating them from other ingredients and mixing bowls within a machine.
|
|
var/datum/recipe/recipe = select_recipe(GLOB.cooking_recipes[recipe_type], mb)
|
|
if(recipe)
|
|
recipes_to_make.Add(list(list(mb, recipe)))
|
|
else //if the ingredients of the mixing bowl don't make a valid recipe, we return a fail recipe to generate the burned mess
|
|
recipes_to_make.Add(list(list(mb, RECIPE_FAIL)))
|
|
|
|
var/datum/recipe/recipe_src = select_recipe(GLOB.cooking_recipes[recipe_type], src, ignored_items = list(/obj/item/mixing_bowl)) //check the machine's directly-inserted ingredients for possible recipes as well, ignoring the mixing bowls when selecting recipe
|
|
if(recipe_src) //if we found a valid recipe for directly-inserted ingredients, add that to our list
|
|
recipes_to_make.Add(list(list(src, recipe_src)))
|
|
else if(!length(recipes_to_make)) //if the machine has no mixing bowls to make recipes from AND also doesn't have a valid recipe of directly-inserted ingredients, return a failure so we can make a burned mess
|
|
recipes_to_make.Add(list(list(src, RECIPE_FAIL)))
|
|
return recipes_to_make
|
|
|
|
//make_recipes(recipes_to_make): cycles through the supplied list of recipes and creates each recipe associated with the "source" for that entry
|
|
/obj/machinery/kitchen_machine/proc/make_recipes(list/recipes_to_make)
|
|
if(!recipes_to_make)
|
|
return
|
|
|
|
var/datum/reagents/temp_reagents = new(500)
|
|
for(var/list/L as anything in recipes_to_make)
|
|
var/obj/source = L[1] // The machine or a mixing bowl
|
|
var/datum/recipe/recipe = L[2] // Valid recipe or RECIPE_FAIL
|
|
|
|
if(recipe == RECIPE_FAIL)
|
|
fail()
|
|
continue
|
|
|
|
for(var/obj/O in source.contents) // Process supplied ingredients
|
|
if(istype(O, /obj/item/mixing_bowl)) // Mixing bowls are not ingredients, ignore
|
|
continue
|
|
|
|
if(O.reagents)
|
|
O.reagents.del_reagent("nutriment")
|
|
O.reagents.update_total()
|
|
O.reagents.trans_to(temp_reagents, O.reagents.total_volume, no_react = TRUE) // Don't react with the abstract holder please
|
|
|
|
qdel(O)
|
|
source.reagents.clear_reagents()
|
|
var/portions = recipe.duplicate ? efficiency : 1
|
|
var/reagents_per_serving = temp_reagents.total_volume / portions
|
|
for(var/i in 1 to portions) // Extra servings when upgraded, ingredient reagents split equally
|
|
var/obj/cooked = new recipe.result(loc)
|
|
cooked.pixel_y = rand(-5, 5)
|
|
cooked.pixel_x = rand(-5, 5)
|
|
temp_reagents.trans_to(cooked, reagents_per_serving, no_react = TRUE) // Don't react with the abstract holder please
|
|
temp_reagents.clear_reagents()
|
|
|
|
var/obj/byproduct = recipe.get_byproduct()
|
|
if(byproduct)
|
|
new byproduct(loc)
|
|
|
|
if(istype(source, /obj/item/mixing_bowl)) // Cooking in mixing bowls returns them dirtier
|
|
var/obj/item/mixing_bowl/mb = source
|
|
mb.make_dirty(5 * portions)
|
|
mb.forceMove(loc)
|
|
|
|
stop()
|
|
|
|
/obj/machinery/kitchen_machine/proc/wzhzhzh(seconds)
|
|
for(var/i=1 to seconds)
|
|
if(stat & (NOPOWER|BROKEN))
|
|
return FALSE
|
|
use_power(500)
|
|
sleep(10)
|
|
return TRUE
|
|
|
|
/obj/machinery/kitchen_machine/proc/has_extra_item()
|
|
for(var/obj/O in contents)
|
|
if(!is_type_in_list(O, list(/obj/item/food, /obj/item/grown, /obj/item/mixing_bowl)))
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/obj/machinery/kitchen_machine/proc/start()
|
|
visible_message("<span class='notice'>[src] turns on.</span>", blind_message = "<span class='notice'>You hear \a [src].</span>")
|
|
if(soundloop)
|
|
soundloop.start()
|
|
else
|
|
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
|
operating = TRUE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
SStgui.update_uis(src)
|
|
|
|
/obj/machinery/kitchen_machine/proc/finish_sound()
|
|
if(soundloop)
|
|
soundloop.stop()
|
|
else
|
|
playsound(loc, 'sound/machines/ding.ogg', 50, 1)
|
|
|
|
/obj/machinery/kitchen_machine/proc/abort()
|
|
operating = FALSE // Turn it off again aferwards
|
|
update_icon(UPDATE_ICON_STATE)
|
|
|
|
/obj/machinery/kitchen_machine/proc/stop()
|
|
finish_sound()
|
|
operating = FALSE // Turn it off again aferwards
|
|
update_icon(UPDATE_ICON_STATE)
|
|
|
|
/obj/machinery/kitchen_machine/proc/muck_start()
|
|
playsound(loc, 'sound/effects/splat.ogg', 50, 1) // Play a splat sound
|
|
dirty = MAX_DIRT // Make it dirty so it can't be used until cleaned
|
|
update_icon(UPDATE_ICON_STATE)
|
|
|
|
/obj/machinery/kitchen_machine/proc/muck_finish()
|
|
visible_message("<span class='alert'>[src] gets covered in muck!</span>")
|
|
flags = null //So you can't add condiments
|
|
stop()
|
|
|
|
/obj/machinery/kitchen_machine/proc/fail()
|
|
var/amount = 0
|
|
for(var/obj/item/mixing_bowl/mb in contents) //fail and remove any mixing bowls present before making the burned mess from the machine itself (to avoid them being destroyed as part of the failure)
|
|
mb.fail(src)
|
|
mb.forceMove(get_turf(src))
|
|
for(var/obj/O in contents)
|
|
if(O.reagents?.total_volume)
|
|
amount += O.reagents.total_volume
|
|
qdel(O)
|
|
if(reagents?.total_volume)
|
|
amount += reagents.total_volume
|
|
reagents.clear_reagents()
|
|
if(amount)
|
|
var/obj/item/food/badrecipe/mysteryfood = new(src)
|
|
mysteryfood.reagents.add_reagent("carbon", amount / 2)
|
|
mysteryfood.reagents.add_reagent("????", amount / 15)
|
|
mysteryfood.forceMove(get_turf(src))
|
|
|
|
/obj/machinery/kitchen_machine/update_icon_state()
|
|
. = ..()
|
|
if(dirty == MAX_DIRT)
|
|
icon_state = dirty_icon
|
|
return
|
|
if(operating)
|
|
icon_state = on_icon
|
|
else
|
|
icon_state = off_icon
|
|
|
|
/obj/machinery/kitchen_machine/build_reagent_description(mob/user)
|
|
return
|
|
|
|
/obj/machinery/kitchen_machine/examine(mob/user)
|
|
. = ..()
|
|
var/dat = format_content_descs()
|
|
if(dat)
|
|
. += "It contains: <br>[dat]"
|
|
|
|
if(!HAS_MIND_TRAIT(user, TRAIT_KNOWS_COOKING_RECIPES))
|
|
return
|
|
|
|
if(locate(/obj/item/mixing_bowl) in contents)
|
|
. += "<span class='notice'>You can't see inside the mixing bowl, you're not sure what it would do.</span>"
|
|
return
|
|
|
|
var/list/recipes = choose_recipes()
|
|
if(length(recipes) == 1 && recipes[1][2] != RECIPE_FAIL)
|
|
var/datum/recipe/recipe = recipes[1][2]
|
|
var/obj/item/result = recipe.result
|
|
. += "<span class='notice'>Your expert chef knowledge tells you that this would make \a [initial(result.name)].</span>"
|
|
|
|
/obj/machinery/kitchen_machine/attack_hand(mob/user)
|
|
if(stat & (BROKEN|NOPOWER) || panel_open || !anchored)
|
|
return
|
|
|
|
ui_interact(user)
|
|
|
|
/obj/machinery/kitchen_machine/attack_ghost(mob/user)
|
|
ui_interact(user)
|
|
|
|
/obj/machinery/kitchen_machine/ui_state(mob/user)
|
|
return GLOB.default_state
|
|
|
|
/obj/machinery/kitchen_machine/ui_interact(mob/user, datum/tgui/ui = null)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "KitchenMachine", name)
|
|
ui.open()
|
|
|
|
/obj/machinery/kitchen_machine/ui_data(mob/user)
|
|
var/list/data = list()
|
|
data["operating"] = operating
|
|
data["inactive"] = FALSE
|
|
data["no_eject"] = FALSE
|
|
data["tooltip"] = ""
|
|
if(dirty >= MAX_DIRT)
|
|
data["inactive"] = TRUE
|
|
data["tooltip"] = "It's too dirty."
|
|
else if(!has_cookables())
|
|
data["inactive"] = TRUE
|
|
data["no_eject"] = TRUE
|
|
data["tooltip"] = "There are no contents."
|
|
|
|
var/list/items_counts = list()
|
|
var/list/name_overrides = list()
|
|
for(var/obj/O in contents)
|
|
var/display_name = O.name
|
|
if(istype(O, /obj/item/food))
|
|
var/obj/item/food/food = O
|
|
if(!items_counts[display_name])
|
|
if(food.ingredient_name)
|
|
name_overrides[display_name] = food.ingredient_name
|
|
else
|
|
name_overrides[display_name] = display_name
|
|
else
|
|
if(food.ingredient_name_plural)
|
|
name_overrides[display_name] = food.ingredient_name_plural
|
|
else if(items_counts[display_name] == 1) // Must only add "s" once or you get stuff like "eggsssss"
|
|
name_overrides[display_name] = "[name_overrides[display_name]]s" //name_overrides[display_name] Will be set on the first time as the singular form
|
|
|
|
items_counts[display_name]++
|
|
|
|
data["ingredients"] = list()
|
|
for(var/food in items_counts)
|
|
var/N = items_counts[food]
|
|
var/units
|
|
if(!(food in name_overrides))
|
|
units = "[lowertext(food)]"
|
|
else
|
|
units = "[name_overrides[food]]"
|
|
|
|
var/list/data_pr = list(
|
|
"name" = capitalize(food),
|
|
"amount" = N,
|
|
"units" = units
|
|
)
|
|
|
|
data["ingredients"] += list(data_pr)
|
|
|
|
for(var/datum/reagent/R in reagents.reagent_list)
|
|
var/display_name = R.name
|
|
if(R.id == "capsaicin")
|
|
display_name = "Hotsauce"
|
|
if(R.id == "frostoil")
|
|
display_name = "Coldsauce"
|
|
|
|
var/unitamt = "unit"
|
|
if(R.volume > 1)
|
|
unitamt = "units"
|
|
|
|
var/list/data_pr = list(
|
|
"name" = display_name,
|
|
"amount" = R.volume,
|
|
"units" = unitamt
|
|
)
|
|
|
|
data["ingredients"] += list(data_pr)
|
|
|
|
return data
|
|
|
|
/obj/machinery/kitchen_machine/ui_act(action, params, datum/tgui/ui)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
|
|
switch(action)
|
|
if("cook")
|
|
if(!check_useable(ui.user))
|
|
return
|
|
|
|
cook()
|
|
if("eject")
|
|
dispose(ui.user)
|
|
|
|
/obj/machinery/kitchen_machine/AltClick(mob/user)
|
|
if(!Adjacent(user) || !check_useable(user))
|
|
return
|
|
|
|
cook()
|
|
to_chat(user, "<span class='notice'>You activate [src].</span>")
|
|
|
|
/obj/machinery/kitchen_machine/proc/has_cookables()
|
|
return reagents.total_volume > 0 || length(contents)
|
|
|
|
/obj/machinery/kitchen_machine/proc/check_useable(mob/user)
|
|
if(dirty >= MAX_DIRT)
|
|
to_chat(user, "<span class='warning'>It's too dirty.</span>")
|
|
return FALSE
|
|
if(!has_cookables())
|
|
to_chat(user, "<span class='warning'>It's empty!</span>")
|
|
return FALSE
|
|
if(stat & BROKEN)
|
|
to_chat(user, "<span class='warning'>It's broken!</span>")
|
|
return FALSE
|
|
if(stat & NOPOWER)
|
|
to_chat(user, "<span class='warning'>It's depowered!</span>")
|
|
return FALSE
|
|
if(panel_open)
|
|
to_chat(user, "<span class='warning'>Its panel is open!</span>")
|
|
return FALSE
|
|
if(!anchored)
|
|
to_chat(user, "<span class='warning'>It's unanchored!</span>")
|
|
return FALSE
|
|
if(operating)
|
|
to_chat(user, "<span class='warning'>Its already cooking!</span>")
|
|
return FALSE
|
|
return TRUE
|
|
|
|
#undef NO_DIRT
|
|
#undef MAX_DIRT
|