diff --git a/code/_helpers/icons_vr.dm b/code/_helpers/icons_vr.dm new file mode 100644 index 00000000000..be5de68e82d --- /dev/null +++ b/code/_helpers/icons_vr.dm @@ -0,0 +1,45 @@ +/proc/AverageColor(var/icon/I, var/accurate = 0, var/ignoreGreyscale = 0) +//Accurate: Use more accurate color averaging, usually has better results and prevents muddied or overly dark colors. Mad thanks to wwjnc. +//ignoreGreyscale: Excempts greyscale colors from the color list, useful for filtering outlines or plate overlays. + var/list/colors = ListColors(I, ignoreGreyscale) + if(!colors.len) + return null + + var/list/colorsum = list(0, 0, 0) //Holds the sum of the RGB values to calculate the average + var/list/RGB = list(0, 0, 0) //Temp list for each color + var/total = colors.len + + var/final_average + if (accurate) //keeping it legible + for(var/i = 1 to total) + RGB = ReadRGB(colors[i]) + colorsum[1] += RGB[1]*RGB[1] + colorsum[2] += RGB[2]*RGB[2] + colorsum[3] += RGB[3]*RGB[3] + final_average = rgb(sqrt(colorsum[1]/total), sqrt(colorsum[2]/total), sqrt(colorsum[3]/total)) + else + for(var/i = 1 to total) + RGB = ReadRGB(colors[i]) + colorsum[1] += RGB[1] + colorsum[2] += RGB[2] + colorsum[3] += RGB[3] + final_average = rgb(colorsum[1]/total, colorsum[2]/total, colorsum[3]/total) + return final_average + +/proc/ListColors(var/icon/I, var/ignoreGreyscale = 0) + var/list/colors = list() + for(var/x_pixel = 1 to I.Width()) + for(var/y_pixel = 1 to I.Height()) + var/this_color = I.GetPixel(x_pixel, y_pixel) + if(this_color) + if (ignoreGreyscale && ReadHSV(RGBtoHSV(this_color))[2] == 0) //If saturation is 0, must be greyscale + continue + colors.Add(this_color) + return colors + +/proc/empty_Y_space(var/icon/I) //Returns the amount of lines containing only transparent pixels in an icon, starting from the bottom + for(var/y_pixel = 1 to I.Height()) + for(var/x_pixel = 1 to I.Width()) + if (I.GetPixel(x_pixel, y_pixel)) + return y_pixel - 1 + return null \ No newline at end of file diff --git a/code/game/machinery/vending_vr.dm b/code/game/machinery/vending_vr.dm index 203e5c03a4d..1b37f516857 100644 --- a/code/game/machinery/vending_vr.dm +++ b/code/game/machinery/vending_vr.dm @@ -21,6 +21,33 @@ /obj/item/device/flashlight/glowstick = 3, /obj/item/device/flashlight/glowstick/red = 3, /obj/item/device/flashlight/glowstick/blue = 3, /obj/item/device/flashlight/glowstick/orange =3, /obj/item/device/flashlight/glowstick/yellow = 3, /obj/item/weapon/reagent_containers/spray/windowsealant = 5) +/obj/machinery/vending/dinnerware + name = "Dinnerware" + desc = "A kitchen and restaurant equipment vendor." + product_ads = "Mm, food stuffs!;Food and food accessories.;Get your plates!;You like forks?;I like forks.;Woo, utensils.;You don't really need these..." + icon_state = "dinnerware" + products = list( + /obj/item/weapon/tray = 8, + /obj/item/weapon/material/kitchen/utensil/fork = 6, + /obj/item/weapon/material/kitchen/utensil/knife = 6, + /obj/item/weapon/material/kitchen/utensil/spoon = 6, + /obj/item/weapon/material/knife = 3, + /obj/item/weapon/material/kitchen/rollingpin = 2, + /obj/item/weapon/reagent_containers/food/drinks/glass2/square = 8, + /obj/item/weapon/reagent_containers/food/drinks/glass2/shake = 8, + /obj/item/weapon/glass_extra/stick = 15, + /obj/item/weapon/glass_extra/straw = 15, + /obj/item/clothing/suit/chef/classic = 2, + /obj/item/weapon/storage/toolbox/lunchbox = 3, + /obj/item/weapon/storage/toolbox/lunchbox/heart = 3, + /obj/item/weapon/storage/toolbox/lunchbox/cat = 3, + /obj/item/weapon/storage/toolbox/lunchbox/nt = 3, + /obj/item/weapon/storage/toolbox/lunchbox/mars = 3, + /obj/item/weapon/storage/toolbox/lunchbox/cti = 3, + /obj/item/weapon/storage/toolbox/lunchbox/nymph = 3, + /obj/item/weapon/storage/toolbox/lunchbox/syndicate = 3, + /obj/item/trash/bowl = 30) + contraband = list(/obj/item/weapon/material/knife/butch = 2) /* var/list/log = list() var/req_log_access = access_armory diff --git a/code/modules/reagents/reagent_containers/food/z_custom_food_vr.dm b/code/modules/reagents/reagent_containers/food/z_custom_food_vr.dm new file mode 100644 index 00000000000..eeeb9896ef9 --- /dev/null +++ b/code/modules/reagents/reagent_containers/food/z_custom_food_vr.dm @@ -0,0 +1,279 @@ +// Customizable Foods ////////////////////////////////////////// +var/global/deepFriedEverything = 0 +var/global/deepFriedNutriment = 0 +var/global/foodNesting = 0 +var/global/recursiveFood = 0 +var/global/ingredientLimit = 20 + + +/obj/item/weapon/reagent_containers/food/snacks/customizable + icon = 'icons/obj/food_custom.dmi' + trash = /obj/item/trash/plate + bitesize = 2 + + var/ingMax = 100 + var/list/ingredients = list() + var/stackIngredients = 0 + var/fullyCustom = 0 + var/addTop = 0 + var/image/topping + var/image/filling + +/obj/item/weapon/reagent_containers/food/snacks/customizable/New(loc,ingredient) + . = ..() + topping = image(icon,,"[initial(icon_state)]_top") + filling = image(icon,,"[initial(icon_state)]_filling") + src.reagents.add_reagent("nutriment",3) + src.updateName() + return + +/obj/item/weapon/reagent_containers/food/snacks/customizable/attackby(obj/item/I, mob/user) + if(istype(I,/obj/item/weapon/reagent_containers/food/snacks)) + if((contents.len >= ingMax) || (contents.len >= ingredientLimit)) + to_chat(user, "That's already looking pretty stuffed.") + return + + var/obj/item/weapon/reagent_containers/food/snacks/S = I + if(istype(S,/obj/item/weapon/reagent_containers/food/snacks/customizable)) + var/obj/item/weapon/reagent_containers/food/snacks/customizable/SC = S + if(fullyCustom && SC.fullyCustom) + to_chat(user, "You slap yourself on the back of the head for thinking that stacking plates is an interesting dish.") + return + if(!recursiveFood && istype(I, /obj/item/weapon/reagent_containers/food/snacks/customizable)) + //to_chat(user, "[pick("As uniquely original as that idea is, you can't figure out how to perform it.","That would be a straining topological exercise.","This world just isn't ready for your cooking genius.","It's possible that you may have a problem.","It won't fit.","You don't think that would taste very good.","Quit goofin' around.")]") + to_chat(user, "As uniquely original as that idea is, you can't figure out how to perform it.") + return + /*if(!user.drop_item()) + user << "\The [I] is stuck to your hands!" + return*/ + user.drop_item() + I.forceMove(src) + + S.reagents.trans_to(src,S.reagents.total_volume) + ingredients += S + + if(src.addTop) + overlays -= topping //thank you Comic + if(!fullyCustom && !stackIngredients && overlays.len) + overlays -= filling //we can't directly modify the overlay, so we have to remove it and then add it again + var/newcolor = S.filling_color != "#FFFFFF" ? S.filling_color : AverageColor(getFlatIcon(S, S.dir, 0), 1, 1) + filling.color = BlendRGB(filling.color, newcolor, 1/ingredients.len) + overlays += filling + else + overlays += generateFilling(S) + if(addTop) + drawTopping() + + updateName() + to_chat(user, "You add the [I.name] to the [src.name].") + else + . = ..() + return + +/obj/item/weapon/reagent_containers/food/snacks/customizable/proc/generateFilling(var/obj/item/weapon/reagent_containers/food/snacks/S, params) + var/image/I + if(fullyCustom) + var/icon/C = getFlatIcon(S, S.dir, 0) + I = image(C) + I.pixel_y = 12 * empty_Y_space(C) + else + I = filling + if(istype(S) && S.filling_color != "#FFFFFF") + I.color = S.filling_color + else + I.color = AverageColor(getFlatIcon(S, S.dir, 0), 1, 1) + if(src.stackIngredients) + I.pixel_y = src.ingredients.len * 2 + else + src.overlays.len = 0 + if(src.fullyCustom || src.stackIngredients) + var/clicked_x = text2num(params2list(params)["icon-x"]) + if (isnull(clicked_x)) + I.pixel_x = 0 + else if (clicked_x < 9) + I.pixel_x = -2 //this looks pretty shitty + else if (clicked_x < 14) + I.pixel_x = -1 //but hey + else if (clicked_x < 19) + I.pixel_x = 0 //it works + else if (clicked_x < 25) + I.pixel_x = 1 + else + I.pixel_x = 2 + return I + +/obj/item/weapon/reagent_containers/food/snacks/customizable/proc/updateName() + var/i = 1 + var/new_name + for(var/obj/item/S in ingredients) + if(i == 1) + new_name += "[S.name]" + else if(i == src.ingredients.len) + new_name += " and [S.name]" + else + new_name += ", [S.name]" + i++ + new_name = "[new_name] [initial(name)]" + if(length(new_name) >= 150) + name = "something yummy" + else + name = new_name + return new_name + +/obj/item/weapon/reagent_containers/food/snacks/customizable/Destroy() + for(. in ingredients) qdel(.) + return ..() + +/obj/item/weapon/reagent_containers/food/snacks/customizable/proc/drawTopping() + var/image/I = topping + I.pixel_y = (ingredients.len+1)*2 + overlays += I + + +// Sandwiches ////////////////////////////////////////////////// + +/obj/item/weapon/reagent_containers/food/snacks/customizable/sandwich + name = "sandwich" + desc = "A timeless classic." + icon_state = "c_sandwich" + stackIngredients = 1 + addTop = 0 + +/obj/item/weapon/reagent_containers/food/snacks/customizable/sandwich/attackby(obj/item/I,mob/user) + if(istype(I,/obj/item/weapon/reagent_containers/food/snacks/breadslice) && !addTop) + I.reagents.trans_to(src,I.reagents.total_volume) + qdel(I) + addTop = 1 + src.drawTopping() + else + ..() + +/obj/item/weapon/reagent_containers/food/snacks/customizable/burger + name = "burger" + desc = "The apex of space culinary achievement." + icon_state = "c_burger" + stackIngredients = 1 + addTop = 1 + +// Misc Subtypes /////////////////////////////////////////////// + +/obj/item/weapon/reagent_containers/food/snacks/customizable/fullycustom + name = "on a plate" + desc = "A unique dish." + icon_state = "fullycustom" + fullyCustom = 1 //how the fuck do you forget to add this? + ingMax = 1 + +/obj/item/weapon/reagent_containers/food/snacks/customizable/soup + name = "soup" + desc = "A bowl with liquid and... stuff in it." + icon_state = "soup" + trash = /obj/item/trash/bowl + +/obj/item/weapon/reagent_containers/food/snacks/customizable/pizza + name = "pan pizza" + desc = "A personalized pan pizza meant for only one person." + icon_state = "personal_pizza" + +/obj/item/weapon/reagent_containers/food/snacks/customizable/pasta + name = "spaghetti" + desc = "Noodles. With stuff. Delicious." + icon_state = "pasta_bot" + +// Various Snacks ////////////////////////////////////////////// + +/obj/item/weapon/reagent_containers/food/snacks/breadslice/attackby(obj/item/I,mob/user,params) + if(istype(I,/obj/item/weapon/reagent_containers/food/snacks)) + if(!recursiveFood && istype(I, /obj/item/weapon/reagent_containers/food/snacks/customizable)) + to_chat(user, "Sorry, no recursive food.") + return + var/obj/F = new/obj/item/weapon/reagent_containers/food/snacks/customizable/sandwich(get_turf(src),I) //boy ain't this a mouthful + F.attackby(I, user) + qdel(src) + else + return ..() + +/obj/item/weapon/reagent_containers/food/snacks/bun/attackby(obj/item/I, mob/user) + // Bun + meatball = burger + if(istype(I,/obj/item/weapon/reagent_containers/food/snacks/meatball)) + new /obj/item/weapon/reagent_containers/food/snacks/monkeyburger(src) + to_chat(user, "You make a burger.") + qdel(I) + qdel(src) + + // Bun + cutlet = hamburger + else if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/cutlet)) + new /obj/item/weapon/reagent_containers/food/snacks/monkeyburger(src) + to_chat(user, "You make a burger.") + qdel(I) + qdel(src) + + // Bun + sausage = hotdog + else if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/sausage)) + new /obj/item/weapon/reagent_containers/food/snacks/hotdog(src) + to_chat(user, "You make a hotdog.") + qdel(I) + qdel(src) + + if(istype(I,/obj/item/weapon/reagent_containers/food/snacks)) + if(!recursiveFood && istype(I, /obj/item/weapon/reagent_containers/food/snacks/customizable)) + to_chat(user, "Sorry, no recursive food.") + return + var/obj/F = new/obj/item/weapon/reagent_containers/food/snacks/customizable/burger(get_turf(src),I) + F.attackby(I, user) + qdel(src) + else + return ..() + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/reagent_containers/food/snacks)) + if(!recursiveFood && istype(I, /obj/item/weapon/reagent_containers/food/snacks/customizable)) + to_chat(user, "Sorry, no recursive food.") + return + var/obj/F = new/obj/item/weapon/reagent_containers/food/snacks/customizable/pizza(get_turf(src),I) + F.attackby(I, user) + qdel(src) + else + return ..() + +/obj/item/weapon/reagent_containers/food/snacks/spagetti/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/reagent_containers/food/snacks)) + if(!recursiveFood && istype(I, /obj/item/weapon/reagent_containers/food/snacks/customizable)) + to_chat(user, "Sorry, no recursive food.") + return + var/obj/F = new/obj/item/weapon/reagent_containers/food/snacks/customizable/pasta(get_turf(src),I) + F.attackby(I, user) + qdel(src) + else + return ..() + +// Custom Meals //////////////////////////////////////////////// +/* +/obj/item/trash/plate/attackby(obj/item/I, mob/user) + if(istype(I,/obj/item/weapon/reagent_containers/food/snacks)) + if(istype(I,/obj/item/weapon/reagent_containers/food/snacks/customizable/fullycustom)) //no platestacking even with recursive food, for now + to_chat(user, "That's already got a plate!") + return + var/obj/F = new/obj/item/weapon/reagent_containers/food/snacks/customizable/fullycustom(get_turf(src),I) + F.attackby(I, user) + qdel(src) + else + return ..() +*/ + +/obj/item/trash/bowl + name = "bowl" + desc = "An empty bowl. Put some food in it to start making a soup." + icon = 'icons/obj/food_custom.dmi' + icon_state = "soup" + +/obj/item/trash/bowl/attackby(obj/item/I, mob/user) + if(istype(I,/obj/item/weapon/reagent_containers/food/snacks)) + if(!recursiveFood && istype(I, /obj/item/weapon/reagent_containers/food/snacks/customizable)) + to_chat(user, "Sorry, no recursive food.") + return + var/obj/F = new/obj/item/weapon/reagent_containers/food/snacks/customizable/soup(get_turf(src),I) + F.attackby(I, user) + qdel(src) + else + return ..() diff --git a/icons/obj/food_custom.dmi b/icons/obj/food_custom.dmi index 39491d65f5e..4057be39939 100644 Binary files a/icons/obj/food_custom.dmi and b/icons/obj/food_custom.dmi differ diff --git a/vorestation.dme b/vorestation.dme index 138eaa6bc72..9042c3c292b 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -57,6 +57,7 @@ #include "code\_helpers\global_lists.dm" #include "code\_helpers\global_lists_vr.dm" #include "code\_helpers\icons.dm" +#include "code\_helpers\icons_vr.dm" #include "code\_helpers\lists.dm" #include "code\_helpers\logging.dm" #include "code\_helpers\maths.dm" @@ -2067,6 +2068,7 @@ #include "code\modules\reagents\reagent_containers\food\lunch.dm" #include "code\modules\reagents\reagent_containers\food\sandwich.dm" #include "code\modules\reagents\reagent_containers\food\snacks.dm" +#include "code\modules\reagents\reagent_containers\food\z_custom_food_vr.dm" #include "code\modules\reagents\reagent_containers\food\drinks\bottle.dm" #include "code\modules\reagents\reagent_containers\food\drinks\cup.dm" #include "code\modules\reagents\reagent_containers\food\drinks\jar.dm"