From 5554f2cdd809c1e11d996e77084ccc35c412f7ab Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Tue, 23 Mar 2021 15:09:23 +0100 Subject: [PATCH] [MIRROR] Ice cream revamp: Ice cream is a component and cones can hold multiple servings of ice cream now. (#4341) * Ice cream revamp: Ice cream is a component and cones can hold multiple servings of ice cream now. (#57415) * Ice cream rework WIP * I'm done! * i'll deal with my verbose engrish at a later date. I'm dead tired. * linter aaaaaa * Take a bite! * FINALLY, A COMPONENT! * ghost macro. * Review, typos, beheading of a lame comsig. * Typo. Now I'm self-obliged to test it again. * It works. * Ice cream revamp: Ice cream is a component and cones can hold multiple servings of ice cream now. Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com> --- code/__DEFINES/food.dm | 12 + code/__HELPERS/reagents.dm | 8 + code/__HELPERS/unsorted.dm | 20 ++ code/datums/components/food/edible.dm | 1 + .../components/food/ice_cream_holder.dm | 277 ++++++++++++++++++ code/game/objects/items/food/frozen.dm | 12 + code/game/objects/items/food/pastries.dm | 35 +++ code/game/objects/items/robot/robot_items.dm | 6 +- code/game/objects/structures/morgue.dm | 6 +- .../kitchen_machinery/icecream_vat.dm | 241 +++++---------- tgstation.dme | 1 + 11 files changed, 437 insertions(+), 182 deletions(-) create mode 100644 code/datums/components/food/ice_cream_holder.dm diff --git a/code/__DEFINES/food.dm b/code/__DEFINES/food.dm index 6853c609b32..c20e202ab5b 100644 --- a/code/__DEFINES/food.dm +++ b/code/__DEFINES/food.dm @@ -75,3 +75,15 @@ #define DRINK_PRICE_EASY 35 #define DRINK_PRICE_MEDIUM 80 #define DRINK_PRICE_HIGH 200 + + +/// Flavour defines (also names) for GLOB.ice_cream_flavours list access. Safer from mispelling than plain text. +#define ICE_CREAM_VANILLA "vanilla" +#define ICE_CREAM_CHOCOLATE "chocolate" +#define ICE_CREAM_STRAWBERRY "strawberry" +#define ICE_CREAM_BLUE "blue" +#define ICE_CREAM_MOB "mob" +#define ICE_CREAM_CUSTOM "custom" +#define ICE_CREAM_BLAND "bland" + +#define DEFAULT_MAX_ICE_CREAM_SCOOPS 3 diff --git a/code/__HELPERS/reagents.dm b/code/__HELPERS/reagents.dm index ac304e312aa..e959b9734ff 100644 --- a/code/__HELPERS/reagents.dm +++ b/code/__HELPERS/reagents.dm @@ -202,3 +202,11 @@ return var/list/matching_reactions = GLOB.chemical_reactions_list_product_index[input_type] return matching_reactions + +/proc/reagent_paths_list_to_text(list/reagents, addendum) + var/list/temp = list() + for(var/datum/reagent/R as anything in reagents) + temp |= initial(R.name) + if(addendum) + temp += addendum + return jointext(temp, ", ") diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index a22dc6b7bda..827e044b3be 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1453,4 +1453,24 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) set waitfor = FALSE return call(source, proctype)(arglist(arguments)) +/// Returns the name of the mathematical tuple of same length as the number arg (rounded down). +/proc/make_tuple(number) + var/static/list/units_prefix = list("", "un", "duo", "tre", "quattuor", "quin", "sex", "septen", "octo", "novem") + var/static/list/tens_prefix = list("", "decem", "vigin", "trigin", "quadragin", "quinquagin", "sexagin", "septuagin", "octogin", "nongen") + var/static/list/one_to_nine = list("monuple", "double", "triple", "quadruple", "quintuple", "sextuple", "septuple", "octuple", "nonuple") + number = round(number) + switch(number) + if(0) + return "empty tuple" + if(1 to 9) + return one_to_nine[number] + if(10 to 19) + return "[units_prefix[(number%10)+1]]decuple" + if(20 to 99) + return "[units_prefix[(number%10)+1]][tens_prefix[round((number % 100)/10)+1]]tuple" + if(100) + return "centuple" + else //It gets too tedious to use latin prefixes from here. + return "[number]-tuple" + #define TURF_FROM_COORDS_LIST(List) (locate(List[1], List[2], List[3])) diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index cce7ed7336e..0558bdd5f7f 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -448,3 +448,4 @@ Behavior that's still missing from this component that original food items had t for (var/t in E.tastes) tastes[t] += E.tastes[t] foodtypes |= E.foodtypes + diff --git a/code/datums/components/food/ice_cream_holder.dm b/code/datums/components/food/ice_cream_holder.dm new file mode 100644 index 00000000000..88417476be5 --- /dev/null +++ b/code/datums/components/food/ice_cream_holder.dm @@ -0,0 +1,277 @@ +#define SCOOP_OFFSET 4 +#define SWEETENER_PER_SCOOP 10 +#define EXTRA_MAX_VOLUME_PER_SCOOP 20 + +/// Ice Cream Holder: Allows the edible parent object to be used as an ice cream cone (or cup... in a next future). +/datum/component/ice_cream_holder + /// List of servings of ice cream it is holding at the moment. + var/list/scoops + /// Servings of ice cream with custom names as key, and their base ones as assoc. (useful for mob/custom ice cream) + var/list/special_scoops + /* + * List of scoop overlays to add on update_overlays(). Separated from list/scoops considering how byond is inconsistent + * at handling duplicate keys and assocs. + */ + var/list/scoop_overlays + /// Number of servings of ice cream it can get through normal methods. + var/max_scoops = DEFAULT_MAX_ICE_CREAM_SCOOPS + /// Changes the name of the food depending on amount and flavours of ice cream on it. + var/change_name = TRUE + /// name to use, if set, in place of [src] on update_name. + var/filled_name + /* + * Ditto as change_name, but for descriptions. + * If false, an examine signal is registered to let the amount and types of held ice cream be known anyway. + */ + var/change_desc = FALSE + /// pixel offsets for scoop overlays. Useful for objects with off-centered sprites. + var/x_offset = 0 + var/y_offset = 0 + /* + * Extra reagent generated each time a new serving is added. Because apparently our sundaes are instead banana splits! + * And banana juice plus sugar equals laughter! (I'll leave it unchanged for honkdaes though) + */ + var/datum/reagent/sweetener + + +/datum/component/ice_cream_holder/Initialize(max_scoops = DEFAULT_MAX_ICE_CREAM_SCOOPS, + change_name = TRUE, + filled_name, + change_desc = FALSE, + x_offset = 0, + y_offset = 0, + datum/reagent/sweetener = /datum/reagent/consumable/sugar, + list/prefill_flavours) + if(!IS_EDIBLE(parent)) /// There is no easy way to add servings to those non-item edibles, but I won't stop you. + return COMPONENT_INCOMPATIBLE + + var/atom/owner = parent + + src.max_scoops = max_scoops + src.change_name = change_name + src.filled_name = filled_name + src.change_desc = change_desc + src.x_offset = x_offset + src.y_offset = y_offset + src.sweetener = sweetener + + RegisterSignal(owner, COMSIG_ITEM_ATTACK_OBJ, .proc/on_item_attack_obj) + RegisterSignal(owner, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/on_update_overlays) + if(change_name) + RegisterSignal(owner, COMSIG_ATOM_UPDATE_NAME, .proc/on_update_name) + if(!change_desc) + RegisterSignal(owner, COMSIG_PARENT_EXAMINE_MORE, .proc/on_examine_more) + else + RegisterSignal(owner, COMSIG_ATOM_UPDATE_DESC, .proc/on_update_desc) + + if(prefill_flavours) + for(var/entry in prefill_flavours) + var/list/flavour_args = list(src) + prefill_flavours[entry] + var/datum/ice_cream_flavour/flavour = GLOB.ice_cream_flavours[entry] + flavour?.add_flavour(arglist(flavour_args)) + +/datum/component/ice_cream_holder/proc/on_update_name(atom/source, updates) + var/obj/obj = source + if(istype(obj) && obj.renamedByPlayer) //Renamed by the player. + return + var/scoops_len = length(scoops) + if(!scoops_len) + source.name = initial(source.name) + else + var/name_to_use = filled_name || initial(source.name) + var/list/unique_list = uniqueList(scoops) + if(scoops_len > 1 && length(unique_list) == 1) // multiple flavours, and all of the same type + source.name = "[make_tuple(scoops_len)] [scoops[1]] [name_to_use]" // "double vanilla" sounds cooler than just "vanilla" + else + source.name = "[english_list(unique_list)] [name_to_use]" + +/datum/component/ice_cream_holder/proc/on_update_desc(atom/source, updates) + var/obj/obj = source + if(istype(obj) && obj.renamedByPlayer) //Renamed by the player. + return + var/scoops_len = length(scoops) + if(!scoops_len) + source.desc = initial(source.desc) + else if(scoops_len == 1 || length(uniqueList(scoops)) == 1) /// Only one flavour. + var/key = scoops[1] + var/datum/ice_cream_flavour/flavour = GLOB.ice_cream_flavours[LAZYACCESS(special_scoops, key) || key] + if(!flavour?.desc) //I scream. + source.desc = initial(source.desc) + else + source.desc = replacetext(replacetext("[flavour.desc_prefix] [flavour.desc]", "$CONE_NAME", initial(source.name)), "$CUSTOM_NAME", key) + else /// Many flavours. + source.desc = "A delicious [initial(source.name)] filled with scoops of [english_list(scoops)] icecream. That's as many as [scoops_len] scoops!" + +/datum/component/ice_cream_holder/proc/on_examine_more(atom/source, mob/mob, list/examine_list) + var/scoops_len = length(scoops) + if(scoops_len == 1 || length(uniqueList(scoops)) == 1) /// Only one flavour. + var/key = scoops[1] + var/datum/ice_cream_flavour/flavour = GLOB.ice_cream_flavours[LAZYACCESS(special_scoops, key) || key] + if(flavour?.desc) //I scream. + examine_list += "[source.p_theyre(TRUE)] filled with scoops of [flavour ? flavour.name : "broken, unhappy"] icecream." + else + examine_list += replacetext(replacetext("[source.p_theyre(TRUE)] [flavour.desc]", "$CONE_NAME", initial(source.name)), "$CUSTOM_NAME", key) + else /// Many flavours. + examine_list += "[source.p_theyre(TRUE)] filled with scoops of [english_list(scoops)] icecream. That's as many as [scoops_len] scoops!" + +/datum/component/ice_cream_holder/proc/on_update_overlays(atom/source, list/new_overlays) + if(!scoops) + return + var/added_offset = 0 + for(var/i in 1 to length(scoop_overlays)) + var/image/overlay = scoop_overlays[i] + if(istext(overlay)) + overlay = image('icons/obj/kitchen.dmi', overlay) + overlay.pixel_x = x_offset + overlay.pixel_y = y_offset + added_offset + new_overlays += overlay + added_offset += SCOOP_OFFSET + +/// Attack the ice cream vat to get some ice cream. This will change as new ways of getting ice cream are added. +/datum/component/ice_cream_holder/proc/on_item_attack_obj(obj/item/source, obj/target, mob/user) + if(!istype(target, /obj/machinery/icecream_vat)) + return + var/obj/machinery/icecream_vat/dispenser = target + if(length(scoops) < max_scoops) + if(dispenser.product_types[dispenser.selected_flavour] > 0) + var/datum/ice_cream_flavour/flavour = GLOB.ice_cream_flavours[dispenser.selected_flavour] + if(flavour.add_flavour(src, dispenser.beaker?.reagents.total_volume ? dispenser.beaker.reagents : null)) + dispenser.visible_message("[icon2html(dispenser, viewers(source))] [user] scoops delicious [dispenser.selected_flavour] ice cream into [source].") + dispenser.product_types[dispenser.selected_flavour]-- + dispenser.updateDialog() + else + to_chat(user, "There is not enough ice cream left!") + else + to_chat(user, "[source] can't hold anymore ice cream!") + return COMPONENT_CANCEL_ATTACK_CHAIN + +/////ICE CREAM FLAVOUR DATUM STUFF + +GLOBAL_LIST_INIT_TYPED(ice_cream_flavours, /datum/ice_cream_flavour, init_ice_cream_flavours()) + +/proc/init_ice_cream_flavours() + . = list() + for(var/datum/ice_cream_flavour/flavour as anything in subtypesof(/datum/ice_cream_flavour)) + flavour = new flavour + .[flavour.name] = flavour + +/* + * The ice cream flavour datum. What makes these digital, frozen snacks so yummy. + * They are singletons, so please bear with me if they feel a little tortous to use at time. + */ +/datum/ice_cream_flavour + /// Make sure the same name is not found on other types; These are singletons keyed by their name after all. + var/name = "Coderlicious Gourmet Double Deluxe Undefined" + /// The icon state of the flavour, overlay or not. + var/icon_state = "icecream_vanilla" + /* + * The fluff text sent to the examiner when the snack has only one flavour of ice cream. + * $CONE_NAME and $CUSTOM_NAME are both placeholders for the cone and the custom ice cream name respectively. + */ + var/desc = "" + /* + * Depending on the value of the [/datum/component/ice_cream/var/change_desc] bool, 'desc' may effectively be the description + * or a text string shown on [/atom/proc/examine_more]. In the former case, the desc is joined with this prefix. + */ + var/desc_prefix = "A delicious $CONE_NAME" + /// The ingredients required to produce a unit with the ice cream vat, these are multiplied by 3. + var/list/ingredients = list(/datum/reagent/consumable/milk, /datum/reagent/consumable/ice, /datum/reagent/consumable/vanilla) + /// The same as above, but in a readable text generated on New() that can also contain fluff ingredients such as "lot of love" or "optional flavorings". + var/ingredients_text = "" + /// the reagent added in 'add_flavour()' + var/reagent_type + /// the amount of reagent added in 'add_flavour()' + var/reagent_amount = 3 + /// Is this flavour shown in the ice cream vat menu or not? + var/hidden = FALSE + +/datum/ice_cream_flavour/New() + if(ingredients) + ingredients_text = "(Ingredients: [reagent_paths_list_to_text(ingredients, ingredients_text)])" + +/// Adds a new flavour to the ice cream cone. +/datum/ice_cream_flavour/proc/add_flavour(datum/component/ice_cream_holder/target, datum/reagents/R, custom_name) + var/atom/owner = target.parent + LAZYADD(target.scoops, custom_name || name) + if(icon_state) + LAZYADD(target.scoop_overlays, icon_state) + if(custom_name) + LAZYSET(target.special_scoops, custom_name, name) + + owner.reagents.maximum_volume += EXTRA_MAX_VOLUME_PER_SCOOP + if(reagent_type) + owner.reagents.add_reagent(reagent_type, reagent_amount, reagtemp = T0C) + // Add some sugar/sweetener to make it a more substantial snack. + owner.reagents.add_reagent(target.sweetener, SWEETENER_PER_SCOOP, reagtemp = T0C) + + var/update_flags = UPDATE_ICON + if(target.change_name) + update_flags |= UPDATE_NAME + if(target.change_desc) + update_flags |= UPDATE_DESC + owner.update_appearance(update_flags) + return TRUE + +///// OUR TYPES OF ICE CREAM, COME GET SOME. + +/datum/ice_cream_flavour/vanilla + name = ICE_CREAM_VANILLA + desc = "filled with vanilla ice cream. All the other ice creams take content from it." + reagent_type = /datum/reagent/consumable/vanilla + +/datum/ice_cream_flavour/chocolate + name = ICE_CREAM_CHOCOLATE + icon_state = "icecream_chocolate" + desc = "filled with chocolate ice cream. Surprisingly, made with real cocoa." + ingredients = list(/datum/reagent/consumable/milk, /datum/reagent/consumable/ice, /datum/reagent/consumable/coco) + reagent_type = /datum/reagent/consumable/coco + +/datum/ice_cream_flavour/strawberry + name = ICE_CREAM_STRAWBERRY + icon_state = "icecream_strawberry" + desc = "filled with strawberry ice cream. Definitely not made with real strawberries." + ingredients = list(/datum/reagent/consumable/milk, /datum/reagent/consumable/ice, /datum/reagent/consumable/berryjuice) + reagent_type = /datum/reagent/consumable/berryjuice + +/datum/ice_cream_flavour/blue + name = ICE_CREAM_BLUE + icon_state = "icecream_blue" + desc = "filled with blue ice cream. Made with real... blue?" + ingredients = list(/datum/reagent/consumable/milk, /datum/reagent/consumable/ice, /datum/reagent/consumable/ethanol/singulo) + reagent_type = /datum/reagent/consumable/ethanol/singulo + +/datum/ice_cream_flavour/mob + name = ICE_CREAM_MOB + icon_state = "icecream_mob" + desc = "filled with bright red ice cream. That's probably not strawberry..." + desc_prefix = "A suspicious $CONE_NAME" + reagent_type = /datum/reagent/liquidgibs + hidden = TRUE + +/datum/ice_cream_flavour/custom + name = ICE_CREAM_CUSTOM + icon_state = "" //has its own mutable appearance overlay. + desc = "filled with artisanal icecream. Made with real $CUSTOM_NAME. Ain't that something." + ingredients = list(/datum/reagent/consumable/milk, /datum/reagent/consumable/ice) + ingredients_text = "optional flavorings" + +/datum/ice_cream_flavour/custom/add_flavour(datum/component/ice_cream_holder/target, datum/reagents/R, custom_name) + if(!R || R.total_volume < 4) //consumable reagents have stronger taste so higher volume are required to allow non-food flavourings to break through better. + return GLOB.ice_cream_flavours[ICE_CREAM_BLAND].add_flavour(target) //Bland, sugary ice and milk. + var/image/flavoring = image('icons/obj/kitchen.dmi', "icecream_custom") + var/datum/reagent/master = R.get_master_reagent() + custom_name = lowertext(master.name) // reagent names are capitalized, while items' aren't. + flavoring.color = master.color + LAZYADD(target.scoop_overlays, flavoring) + . = ..() // Make some space for reagents before attempting to transfer some to the target. + R.trans_to(target.parent, 4) + +/datum/ice_cream_flavour/bland + name = ICE_CREAM_BLAND + icon_state = "icecream_custom" + desc = "filled with anemic, flavorless icecream. You wonder why this was ever scooped..." + hidden = TRUE + +#undef SCOOP_OFFSET +#undef SWEETENER_PER_SCOOP +#undef EXTRA_MAX_VOLUME_PER_SCOOP diff --git a/code/game/objects/items/food/frozen.dm b/code/game/objects/items/food/frozen.dm index d7a82a57c6c..f3fb6985e19 100644 --- a/code/game/objects/items/food/frozen.dm +++ b/code/game/objects/items/food/frozen.dm @@ -29,6 +29,10 @@ tastes = list("blue cherries" = 2, "ice cream" = 2) foodtypes = FRUIT | DAIRY | SUGAR +/obj/item/food/spacefreezy/MakeEdible() + . = ..() + AddComponent(/datum/component/ice_cream_holder) + /obj/item/food/sundae name = "sundae" desc = "A classic dessert." @@ -39,6 +43,10 @@ tastes = list("ice cream" = 1, "banana" = 1) foodtypes = FRUIT | DAIRY | SUGAR +/obj/item/food/sundae/MakeEdible() + . = ..() + AddComponent(/datum/component/ice_cream_holder, y_offset = -2, sweetener = /datum/reagent/consumable/caramel) + /obj/item/food/honkdae name = "honkdae" desc = "The clown's favorite dessert." @@ -49,6 +57,10 @@ tastes = list("ice cream" = 1, "banana" = 1, "a bad joke" = 1) foodtypes = FRUIT | DAIRY | SUGAR +/obj/item/food/honkdae/MakeEdible() + . = ..() + AddComponent(/datum/component/ice_cream_holder, y_offset = -2) //The sugar will react with the banana forming laughter. Honk! + ///////////// //SNOWCONES// ///////////// diff --git a/code/game/objects/items/food/pastries.dm b/code/game/objects/items/food/pastries.dm index 65fe33a8f70..e760f2dc668 100644 --- a/code/game/objects/items/food/pastries.dm +++ b/code/game/objects/items/food/pastries.dm @@ -857,5 +857,40 @@ w_class = WEIGHT_CLASS_TINY venue_value = FOOD_PRICE_CHEAP // Pastry base, 3u of sugar and a single. fucking. unit. of. milk. really? +/obj/item/food/icecream + name = "waffle cone" + desc = "Delicious waffle cone, but no ice cream." + icon = 'icons/obj/kitchen.dmi' + icon_state = "icecream_cone_waffle" + food_reagents = list(/datum/reagent/consumable/nutriment = 5) + tastes = list("cream" = 2, "waffle" = 1) + bite_consumption = 4 + foodtypes = DAIRY | SUGAR + max_volume = 10 //The max volumes scales up with the number of scoops of ice cream served. + /// These two variables are used by the ice cream vat. Latter is the one that shows on the UI. + var/list/ingredients = list(/datum/reagent/consumable/flour, /datum/reagent/consumable/sugar) + var/ingredients_text + /* + * Assoc list var used to prefill the cone with ice cream. + * Key is the flavour's name (use text defines; see __DEFINES/food.dm or ice_cream_holder.dm), + * assoc is the list of args that is going to be used in [flavour/add_flavour()]. Can as well be null for simple flavours. + */ + var/list/prefill_flavours + +/obj/item/food/icecream/Initialize(mapload, list/prefill_flavours) + if(prefill_flavours) + src.prefill_flavours = prefill_flavours + return ..() + +/obj/item/food/icecream/MakeEdible() + . = ..() + AddComponent(/datum/component/ice_cream_holder, filled_name = "ice cream", change_desc = TRUE, prefill_flavours = prefill_flavours) + +/obj/item/food/icecream/chocolate + name = "chocolate cone" + desc = "Delicious chocolate cone, but no ice cream." + icon_state = "icecream_cone_chocolate" + food_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/coco = 1) + ingredients = list(/datum/reagent/consumable/flour, /datum/reagent/consumable/sugar, /datum/reagent/consumable/coco) #undef DONUT_SPRINKLE_CHANCE diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 221a73a5a51..ce19982c17f 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -393,10 +393,8 @@ if(DISPENSE_LOLLIPOP_MODE) food_item = new /obj/item/food/chewable/lollipop(T) if(DISPENSE_ICECREAM_MODE) - food_item = new /obj/item/food/icecream(T) - var/obj/item/food/icecream/I = food_item - I.add_ice_cream("vanilla") - I.desc = "Eat the ice cream." + food_item = new /obj/item/food/icecream(T, list(ICE_CREAM_VANILLA)) + food_item.desc = "Eat the ice cream." var/into_hands = FALSE if(ismob(A)) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 4b1bfdd15cc..0a792ff6806 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -295,10 +295,8 @@ GLOBAL_LIST_EMPTY(crematoriums) /obj/structure/bodycontainer/crematorium/creamatorium/cremate(mob/user) var/list/icecreams = new() - for(var/i_scream in get_all_contents_type(/mob/living)) - var/obj/item/food/icecream/IC = new() - IC.set_cone_type("waffle") - IC.add_mob_flavor(i_scream) + for(var/mob/living/i_scream as anything in get_all_contents_type(/mob/living)) + var/obj/item/food/icecream/IC = new(null, list(ICE_CREAM_MOB = list(null, i_scream.name))) icecreams += IC . = ..() for(var/obj/IC in icecreams) diff --git a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm index d1594f90a22..c85a5f6d3be 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm @@ -1,10 +1,4 @@ -#define ICECREAM_VANILLA 1 -#define ICECREAM_CHOCOLATE 2 -#define ICECREAM_STRAWBERRY 3 -#define ICECREAM_BLUE 4 -#define ICECREAM_CUSTOM 5 -#define CONE_WAFFLE 6 -#define CONE_CHOC 7 +#define PREFILL_AMOUNT 5 /obj/machinery/icecream_vat name = "ice cream vat" @@ -17,9 +11,10 @@ layer = BELOW_OBJ_LAYER max_integrity = 300 var/list/product_types = list() - var/dispense_flavour = ICECREAM_VANILLA - var/flavour_name = "vanilla" - var/obj/item/reagent_containers/beaker = null + var/selected_flavour = ICE_CREAM_VANILLA + var/obj/item/reagent_containers/beaker + /// List of prototypes of dispensable ice cream cones. path as key, instance as assoc. + var/static/list/obj/item/food/icecream/cone_prototypes var/static/list/icecream_vat_reagents = list( /datum/reagent/consumable/milk = 6, /datum/reagent/consumable/flour = 6, @@ -30,64 +25,43 @@ /datum/reagent/consumable/berryjuice = 6, /datum/reagent/consumable/ethanol/singulo = 6) -/obj/machinery/icecream_vat/proc/get_ingredient_list(type) - switch(type) - if(ICECREAM_CHOCOLATE) - return list(/datum/reagent/consumable/milk, /datum/reagent/consumable/ice, /datum/reagent/consumable/coco) - if(ICECREAM_STRAWBERRY) - return list(/datum/reagent/consumable/milk, /datum/reagent/consumable/ice, /datum/reagent/consumable/berryjuice) - if(ICECREAM_BLUE) - return list(/datum/reagent/consumable/milk, /datum/reagent/consumable/ice, /datum/reagent/consumable/ethanol/singulo) - if(ICECREAM_CUSTOM) - return list(/datum/reagent/consumable/milk, /datum/reagent/consumable/ice) - if(CONE_WAFFLE) - return list(/datum/reagent/consumable/flour, /datum/reagent/consumable/sugar) - if(CONE_CHOC) - return list(/datum/reagent/consumable/flour, /datum/reagent/consumable/sugar, /datum/reagent/consumable/coco) - else //ICECREAM_VANILLA - return list(/datum/reagent/consumable/milk, /datum/reagent/consumable/ice, /datum/reagent/consumable/vanilla) - - -/obj/machinery/icecream_vat/proc/get_flavour_name(flavour_type) - switch(flavour_type) - if(ICECREAM_CHOCOLATE) - return "chocolate" - if(ICECREAM_STRAWBERRY) - return "strawberry" - if(ICECREAM_BLUE) - return "blue" - if(ICECREAM_CUSTOM) - return "custom" - if(CONE_WAFFLE) - return "waffle" - if(CONE_CHOC) - return "chocolate" - else //ICECREAM_VANILLA - return "vanilla" - - /obj/machinery/icecream_vat/Initialize() . = ..() - while(product_types.len < 7) - product_types.Add(5) + + if(!cone_prototypes) + cone_prototypes = list() + for(var/cone_path in typesof(/obj/item/food/icecream)) + var/obj/item/food/icecream/cone = new cone_path + if(cone.ingredients) + cone_prototypes[cone_path] = cone + cone.ingredients_text = "(Ingredients: [reagent_paths_list_to_text(cone.ingredients)])" + else + qdel(cone) + create_reagents(100, NO_REACT | OPENCONTAINER) + reagents.chem_temp = T0C //So ice doesn't melt + for(var/flavour in GLOB.ice_cream_flavours) + if(GLOB.ice_cream_flavours[flavour].hidden) + continue + product_types[flavour] = PREFILL_AMOUNT + for(var/cone in cone_prototypes) + product_types[cone] = PREFILL_AMOUNT + for(var/reagent in icecream_vat_reagents) reagents.add_reagent(reagent, icecream_vat_reagents[reagent], reagtemp = T0C) - reagents.chem_temp = T0C //So ice doesn't melt /obj/machinery/icecream_vat/ui_interact(mob/user) . = ..() var/dat dat += "ICE CREAM
" - dat += "Dispensing: [flavour_name] icecream

" - dat += "Vanilla ice cream: Select Make x5 [product_types[ICECREAM_VANILLA]] scoops left. (Ingredients: milk, ice, vanilla)
" - dat += "Strawberry ice cream: Select Make x5 [product_types[ICECREAM_STRAWBERRY]] dollops left. (Ingredients: milk, ice, berry juice)
" - dat += "Chocolate ice cream: Select Make x5 [product_types[ICECREAM_CHOCOLATE]] dollops left. (Ingredients: milk, ice, coco powder)
" - dat += "Blue ice cream: Select Make x5 [product_types[ICECREAM_BLUE]] dollops left. (Ingredients: milk, ice, singulo)
" - dat += "Custom ice cream: Select Make x5 [product_types[ICECREAM_CUSTOM]] dollops left. (Ingredients: milk, ice, optional flavoring)
" + dat += "Dispensing: [selected_flavour] icecream

" + for(var/flavour in GLOB.ice_cream_flavours) + if(GLOB.ice_cream_flavours[flavour].hidden) + continue + dat += "[capitalize(flavour)] ice cream: Select Make x5 [product_types[flavour]] scoops left[GLOB.ice_cream_flavours[flavour].ingredients_text].
" dat += "
CONES
" - dat += "Waffle cones: Dispense Make x5 [product_types[CONE_WAFFLE]] cones left. (Ingredients: flour, sugar)
" - dat += "Chocolate cones: Dispense Make x5 [product_types[CONE_CHOC]] cones left. (Ingredients: flour, sugar, coco powder)
" + for(var/cone in cone_prototypes) + dat += "[capitalize(cone_prototypes[cone].name)]s: Dispense Make x5 [product_types[cone]] cones left[cone_prototypes[cone].ingredients_text].
" dat += "
" if(beaker) dat += "BEAKER CONTENT
" @@ -106,24 +80,6 @@ popup.open() /obj/machinery/icecream_vat/attackby(obj/item/O, mob/user, params) - if(istype(O, /obj/item/food/icecream)) - var/obj/item/food/icecream/I = O - if(!I.ice_creamed) - if(product_types[dispense_flavour] > 0) - visible_message("[icon2html(src, viewers(src))] [user] scoops delicious [flavour_name] ice cream into [I].") - product_types[dispense_flavour] -= 1 - if(beaker?.reagents.total_volume) - I.add_ice_cream(flavour_name, beaker.reagents) - else - I.add_ice_cream(flavour_name) - if(I.reagents.total_volume < 10) - I.reagents.add_reagent(/datum/reagent/consumable/sugar, 10 - I.reagents.total_volume, reagtemp = T0C) - updateDialog() - else - to_chat(user, "There is not enough ice cream left!") - else - to_chat(user, "[O] already has ice cream in it!") - return 1 if(istype(O, /obj/item/reagent_containers) && !(O.item_flags & ABSTRACT) && O.is_open_container()) . = TRUE //no afterattack var/obj/item/reagent_containers/B = O @@ -149,24 +105,21 @@ playsound(src, 'sound/items/drink.ogg', 25, TRUE) return - - -/obj/machinery/icecream_vat/proc/make(mob/user, make_type, amount) +/obj/machinery/icecream_vat/proc/make(mob/user, make_type, amount, list/ingredients) var/recipe_amount = amount * 3 //prevents reagent duping by requring roughly the amount of reagenst you gain back by grinding. - for(var/R in get_ingredient_list(make_type)) - if(reagents.has_reagent(R, recipe_amount)) - continue - amount = 0 - break + for(var/R in ingredients) + if(!reagents.has_reagent(R, recipe_amount)) + amount = 0 + break if(amount) - for(var/R in get_ingredient_list(make_type)) + for(var/R in ingredients) reagents.remove_reagent(R, recipe_amount) product_types[make_type] += amount - var/flavour = get_flavour_name(make_type) - if(make_type > 5) - src.visible_message("[user] cooks up some [flavour] cones.") + var/obj/item/food/icecream/cone = cone_prototypes[make_type] + if(cone) + visible_message("[user] cooks up some [cone.name]s.") else - src.visible_message("[user] whips up some [flavour] icecream.") + visible_message("[user] whips up some [make_type] icecream.") else to_chat(user, "You don't have the ingredients to make this!") @@ -174,25 +127,37 @@ if(..()) return if(href_list["select"]) - dispense_flavour = text2num(href_list["select"]) - flavour_name = get_flavour_name(dispense_flavour) - src.visible_message("[usr] sets [src] to dispense [flavour_name] flavoured ice cream.") + var/datum/ice_cream_flavour/flavour = GLOB.ice_cream_flavours[href_list["select"]] + if(!flavour || flavour.hidden) //Nice try, tex. + return + visible_message("[usr] sets [src] to dispense [href_list["select"]] flavoured ice cream.") + selected_flavour = flavour.name if(href_list["cone"]) - var/dispense_cone = text2num(href_list["cone"]) - var/cone_name = get_flavour_name(dispense_cone) - if(product_types[dispense_cone] >= 1) - product_types[dispense_cone] -= 1 - var/obj/item/food/icecream/I = new(src.loc) - I.set_cone_type(cone_name) - src.visible_message("[usr] dispenses a crunchy [cone_name] cone from [src].") + var/obj/item/food/icecream/cone_path = text2path(href_list["cone"]) + if(!cone_path) + return + if(product_types[cone_path] >= 1) + product_types[cone_path]-- + var/obj/item/food/icecream/cone = new cone_path(loc) + visible_message("[usr] dispenses a crunchy [cone] from [src].") else - to_chat(usr, "There are no [cone_name] cones left!") + to_chat(usr, "There are no [initial(cone_path.name)]s left!") if(href_list["make"]) + var/datum/ice_cream_flavour/flavour = GLOB.ice_cream_flavours[href_list["make"]] + if(!flavour || flavour.hidden) //Nice try, tex. + return var/amount = (text2num(href_list["amount"])) - var/C = text2num(href_list["make"]) - make(usr, C, amount) + make(usr, href_list["make"], amount, flavour.ingredients) + + if(href_list["make_cone"]) + var/path = text2path(href_list["make_cone"]) + var/obj/item/food/icecream/cone = cone_prototypes[path] + if(!cone) //Nice try, tex. + return + var/amount = (text2num(href_list["amount"])) + make(usr, path, amount, cone.ingredients) if(href_list["disposeI"]) reagents.del_reagent(text2path(href_list["disposeI"])) @@ -210,72 +175,6 @@ usr << browse(null,"window=icecreamvat") return -/obj/item/food/icecream - name = "ice cream cone" - desc = "Delicious waffle cone, but no ice cream." - icon = 'icons/obj/kitchen.dmi' - icon_state = "icecream_cone_waffle" //default for admin-spawned cones, href_list["cone"] should overwrite this all the time - food_reagents = list(/datum/reagent/consumable/nutriment = 4) - tastes = list("cream" = 2, "waffle" = 1) - bite_consumption = 4 - foodtypes = DAIRY | SUGAR - max_volume = 20 - var/ice_creamed = 0 - var/cone_type - - - -/obj/item/food/icecream/proc/set_cone_type(cone_name) - cone_type = cone_name - icon_state = "icecream_cone_[cone_name]" - switch (cone_type) - if ("waffle") - reagents.add_reagent(/datum/reagent/consumable/nutriment, 1, reagtemp = T0C) - if ("chocolate") - reagents.add_reagent(/datum/reagent/consumable/coco, 1, reagtemp = T0C) // chocolate ain't as nutritious kids - - desc = "Delicious [cone_name] cone, but no ice cream." - - -/obj/item/food/icecream/proc/add_ice_cream(flavour_name, datum/reagents/R = null) - name = "[flavour_name] icecream" - switch (flavour_name) // adding the actual reagents advertised in the ingredient list - if ("vanilla") - desc = "A delicious [cone_type] cone filled with vanilla ice cream. All the other ice creams take content from it." - reagents.add_reagent(/datum/reagent/consumable/vanilla, 3, reagtemp = T0C) - if ("chocolate") - desc = "A delicious [cone_type] cone filled with chocolate ice cream. Surprisingly, made with real cocoa." - reagents.add_reagent(/datum/reagent/consumable/coco, 3, reagtemp = T0C) - if ("strawberry") - desc = "A delicious [cone_type] cone filled with strawberry ice cream. Definitely not made with real strawberries." - reagents.add_reagent(/datum/reagent/consumable/berryjuice, 3, reagtemp = T0C) - if ("blue") - desc = "A delicious [cone_type] cone filled with blue ice cream. Made with real... blue?" - reagents.add_reagent(/datum/reagent/consumable/ethanol/singulo, 3, reagtemp = T0C) - if ("mob") - desc = "A suspicious [cone_type] cone filled with bright red ice cream. That's probably not strawberry..." - reagents.add_reagent(/datum/reagent/liquidgibs, 3, reagtemp = T0C) - if ("custom") - if(R && R.total_volume >= 4) //consumable reagents have stronger taste so higher volume will allow non-food flavourings to break through better. - var/mutable_appearance/flavoring = mutable_appearance(icon,"icecream_custom") - var/datum/reagent/master = R.get_master_reagent() - flavoring.color = master.color - name = "[master.name] icecream" - desc = "A delicious [cone_type] cone filled with artisanal icecream. Made with real [master.name]. Ain't that something." - R.trans_to(src, 4) - add_overlay(flavoring) - else - name = "bland icecream" - desc = "A delicious [cone_type] cone filled with anemic, flavorless icecream.You wonder why this was ever scooped.." - add_overlay("icecream_custom") - if(flavour_name != "custom") - src.add_overlay("icecream_[flavour_name]") - ice_creamed = 1 - -/obj/item/food/icecream/proc/add_mob_flavor(mob/M) - add_ice_cream("mob") - name = "[M.name] icecream" - /obj/machinery/icecream_vat/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) new /obj/item/stack/sheet/iron(loc, 4) @@ -297,10 +196,4 @@ beaker = new_beaker return TRUE -#undef ICECREAM_VANILLA -#undef ICECREAM_CHOCOLATE -#undef ICECREAM_STRAWBERRY -#undef ICECREAM_BLUE -#undef ICECREAM_CUSTOM -#undef CONE_WAFFLE -#undef CONE_CHOC +#undef PREFILL_AMOUNT diff --git a/tgstation.dme b/tgstation.dme index 7d078e6fd75..a6cbc82a1b4 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -580,6 +580,7 @@ #include "code\datums\components\fantasy\prefixes.dm" #include "code\datums\components\fantasy\suffixes.dm" #include "code\datums\components\food\edible.dm" +#include "code\datums\components\food\ice_cream_holder.dm" #include "code\datums\components\plumbing\_plumbing.dm" #include "code\datums\components\plumbing\chemical_acclimator.dm" #include "code\datums\components\plumbing\filter.dm"