diff --git a/code/modules/food/kitchen/cooking_machines/_appliance.dm b/code/modules/food/kitchen/cooking_machines/_appliance.dm index 07d812f8b5..1c1e8046ba 100644 --- a/code/modules/food/kitchen/cooking_machines/_appliance.dm +++ b/code/modules/food/kitchen/cooking_machines/_appliance.dm @@ -734,7 +734,7 @@ /datum/cooking_item var/max_cookwork var/cookwork - var/overcook_mult = 3 // How long it takes to overcook. This is max_cookwork x overcook mult. If you're changing this, mind that at 3x, a max_cookwork of 30 becomes 90 ticks for the purpose of burning, and a max_cookwork of 4 only has 12 before burning! + var/overcook_mult = 6 // How long it takes to overcook. This is max_cookwork x overcook mult. If you're changing this, mind that at 3x, a max_cookwork of 30 becomes 90 ticks for the purpose of burning, and a max_cookwork of 4 only has 12 before burning! // CHOMPedit: doubled to 6 var/result_type = 0 var/obj/item/weapon/reagent_containers/cooking_container/container = null var/combine_target = null diff --git a/code/modules/lore_codex/codex.dm b/code/modules/lore_codex/codex.dm index d6c1eafa61..e93f10638f 100644 --- a/code/modules/lore_codex/codex.dm +++ b/code/modules/lore_codex/codex.dm @@ -9,13 +9,21 @@ var/datum/codex_tree/tree = null var/root_type = /datum/lore/codex/category/main_borealis_lore //YW EDIT + var/static/list/codex_tree_keys = list() // CHOMPedit: static list linking codexes to the correct codex_tree. + /obj/item/weapon/book/codex/Initialize() - tree = new(src, root_type) + tree = codex_tree_keys["[root_type]"] // CHOMPedit start + if(!tree) + tree = new(src, root_type) + codex_tree_keys["[root_type]"] = tree // CHOMPedit end . = ..() /obj/item/weapon/book/codex/attack_self(mob/user) - if(!tree) - tree = new(src, root_type) + if(!tree) // CHOMPedit start + tree = codex_tree_keys["[root_type]"] + if(!tree) + tree = new(src, root_type) + codex_tree_keys["[root_type]"] = tree // CHOMPedit end icon_state = "[initial(icon_state)]-open" tree.display(user) diff --git a/icons/obj/library_ch.dmi b/icons/obj/library_ch.dmi index 06a1ce0c4b..ca33af5a8c 100644 Binary files a/icons/obj/library_ch.dmi and b/icons/obj/library_ch.dmi differ diff --git a/maps/southern_cross/southern_cross-2.dmm b/maps/southern_cross/southern_cross-2.dmm index f28639c5a1..ae340e1f89 100644 --- a/maps/southern_cross/southern_cross-2.dmm +++ b/maps/southern_cross/southern_cross-2.dmm @@ -51358,7 +51358,7 @@ dir = 4 }, /obj/structure/table/marble, -/obj/item/weapon/book/manual/chef_recipes, +/obj/item/weapon/book/codex/chef_recipes, /turf/simulated/floor/tiled/white, /area/crew_quarters/kitchen) "gRL" = ( diff --git a/modular_chomp/code/modules/lore_codex/codex.dm b/modular_chomp/code/modules/lore_codex/codex.dm new file mode 100644 index 0000000000..40f7207d9e --- /dev/null +++ b/modular_chomp/code/modules/lore_codex/codex.dm @@ -0,0 +1,8 @@ +/obj/item/weapon/book/codex/chef_recipes + name = "Chef Recipes Ultramatus Edition" + color = "#585a5e" + icon = 'icons/obj/library_ch.dmi' + icon_state = "cooked_book" + item_state = "book16" + root_type = /datum/lore/codex/category/cooking_recipe_list + libcategory = "Reference" diff --git a/modular_chomp/code/modules/lore_codex/codex_tree.dm b/modular_chomp/code/modules/lore_codex/codex_tree.dm new file mode 100644 index 0000000000..200a1ec4f0 --- /dev/null +++ b/modular_chomp/code/modules/lore_codex/codex_tree.dm @@ -0,0 +1,171 @@ +// Holds the various pages and implementations for codex books, so they can be used in more than just books. + +/datum/codex_tree + var/atom/movable/holder = null + var/root_type = null + var/datum/lore/codex/home = null // Top-most page. + var/list/current_page = list() // Current page or category to display to the user. // converted to list to track multiple players. + var/list/indexed_pages = list() // Assoc list with search terms pointing to a ref of the page. It's created on New(). + var/list/history = list() // List of pages we previously visited. // now a 2D list + +/datum/codex_tree/New(var/new_holder, var/new_root_type) + holder = new_holder + root_type = new_root_type + generate_pages() + ..() + +/datum/codex_tree/proc/generate_pages() + home = new root_type(src) // This will also generate the others. + //current_page = home + indexed_pages = home.index_page() // changed from current_page to home. + +// Changes current_page to its parent, assuming one exists. +/datum/codex_tree/proc/go_to_parent(var/mob/user) + var/datum/lore/codex/D = current_page["[user]"] + if(istype(D) && D.parent) + current_page["[user]"] = D.parent + +// Changes current_page to a specific page or category. +/datum/codex_tree/proc/go_to_page(var/datum/lore/codex/new_page, var/dont_record_history = FALSE, var/mob/user) + var/datum/lore/codex/D = current_page["[user]"] + if(new_page && istype(D)) // Make sure we're not going to a null page for whatever reason. + current_page["[user]"] = new_page + if(!dont_record_history) + var/list/H = history["[user]"] + if(!H) + H = list() + H.Add(new_page) + history["[user]"] = H + +/datum/codex_tree/proc/quick_link(var/search_word, var/mob/user) + for(var/word in indexed_pages) + if(lowertext(search_word) == lowertext(word)) // Exact matches unfortunately limit our ability to perform SEOs. + go_to_page(indexed_pages[word], FALSE, user) + return + +/datum/codex_tree/proc/get_page_from_type(var/desired_type) + for(var/word in indexed_pages) + var/datum/lore/codex/C = indexed_pages[word] + if(C.type == desired_type) + return C + return null + +// Returns to the last visited page, based on the history list. +/datum/codex_tree/proc/go_back(var/mob/user) + var/list/H = history["[user]"] + var/datum/lore/codex/D = current_page["[user]"] + if(!LAZYLEN(H) || !istype(D)) + return + if((H.len) > 1) + if(H[H.len] == D) + H.len-- // This gets rid of the current page in the history. + history["[user]"] = H + if(H.len == 1) + go_to_page(H[H.len], TRUE, user) + return + go_to_page(pop(history["[user]"]), TRUE, user) // Where as this will get us the previous page that we want to go to. + else + go_to_page(H[H.len], TRUE, user) + +/datum/codex_tree/proc/get_tree_position(var/mob/user) + var/datum/lore/codex/checked = current_page["[user]"] + if(istype(checked)) + var/output = "" + output = "[checked.name]" + while(checked.parent) + output = "[checked.parent.name] \> [output]" + checked = checked.parent + return output + +/datum/codex_tree/proc/make_search_bar() + var/html = {" +
+ + + + + +
+ "} + return html + +/datum/codex_tree/proc/display(mob/user) +// icon_state = "[initial(icon_state)]-open" + if(!home) + generate_pages() + if(!user) + return + var/datum/lore/codex/D = current_page["[user]"] + if(!istype(D)) // Initialize current_page and history + current_page["[user]"] = home + D = current_page["[user]"] + if(!istype(D)) + log_debug("Codex_tree failed to failed to load for [user].") + return + var/list/H_init = list() + H_init.Add(home) + history["[user]"] = H_init + //if(!current_page) + //generate_pages() + + user << browse_rsc('html/browser/codex.css', "codex.css") + + var/dat + dat = "" + dat += "[holder.name] ([D.name])" + dat += "" + dat += "" + + dat += "" + dat += "[get_tree_position(user)]
" + dat += "[make_search_bar()]
" + dat += "
" + dat += "

[D.name]

" + dat += "
" + if(D.data) + dat += "[D.data]
" + dat += "
" + if(istype(D, /datum/lore/codex/category)) + dat += "
" + var/datum/lore/codex/category/C = D + for(var/datum/lore/codex/child in C.children) + dat += "[child.name]" + dat += "
" + dat += "
" + var/list/H = history["[user]"] + if(LAZYLEN(H)) + dat += "
\[Go Back\]" + if(D.parent) + dat += "
\[Go Up\]" + if(D != home) + dat += "
\[Go To Home\]" + dat += "
" + user << browse(dat, "window=the_empress_protects;size=600x550") + onclose(user, "the_empress_protects", src) + +/datum/codex_tree/Topic(href, href_list) + . = ..() + if(.) + return + + + if(href_list["target"]) // Direct link, using a ref + var/datum/lore/codex/new_page = locate(href_list["target"]) + go_to_page(new_page, FALSE, usr) + else if(href_list["search_query"]) + quick_link(href_list["search_query"], usr) + else if(href_list["go_to_parent"]) + go_to_parent(usr) + else if(href_list["go_back"]) + go_back(usr) + else if(href_list["go_to_home"]) + go_to_page(home, FALSE, usr) + else if(href_list["quick_link"]) // Indirect link, using a (hopefully) indexed word. + quick_link(href_list["quick_link"], usr) + else if(href_list["close"]) + // Close the book, if our holder is actually a book. + //if(istype(holder, /obj/item/weapon/book/codex)) + //holder.icon_state = initial(holder.icon_state) + usr << browse(null, "window=the_empress_protects") + return + display(usr) diff --git a/modular_chomp/code/modules/lore_codex/cooking_codex.dm b/modular_chomp/code/modules/lore_codex/cooking_codex.dm new file mode 100644 index 0000000000..4b464ee518 --- /dev/null +++ b/modular_chomp/code/modules/lore_codex/cooking_codex.dm @@ -0,0 +1,138 @@ +// These aren't lore but I guess that's part of the typepath forever. +/datum/lore/codex/category/cooking_recipe_list + name = "Index" + data = "Greetings, fellow sapient! Within these hallowed scripts rest sacred incantations for the rearrangement \ + of carbon structures into shapes most delectable to those possessing exquisite gustatory senses and requiring \ + nutrituous sustenance. As a reference for Gustomancy of all experience Classes, below explains the form of \ + each component spell. Hark, reader beware! To peruse beyond permission of the mighty Wizard Federation is to \ + be struck with a 10,000 year imprisonment curse of cuboidal containment sphere!\ +

\ +
Heat Applicator: A device, commonly of metal, into which component spells are inserted and transmogrified \ + into the Gustomancic Product. Applicators convert Electromancy into heat, and may require heating to an ideal \ + temperature before spellcrafting. Overapplication will result in failure of the spell, and respiratory distress! \ +
\ +
Pure Fluids: A purified substance, typically of liquid form, added to the Applicator from a fluid vessel. \ + Fluids are typically extracted from a bearing object, ground from bulk form, or produced by Chemomancy. \ +
\ +
Material Objects: Any component spell object not created by Botanomancy. Most are created by lesser \ + Gustomancy tools or Gustomancy spells. Others may require creative acquistion methods! \ +
\ +
Grown Produce: A product of the soils and vessels of Botanomancy, typically fruit or vegetable. The \ + methods of Botanomancy lie beyond the scope of this Gustomancy tome! \ +
\ +
Cooked Shell: A coating of specified pure fluid, typically batter, applied to all component spell \ + objects. Traditionally, specified fluid is placed in a glass vessel and each component spell dipped within. \ +
\ +
Temporal Shift: Length of passage through the temporial medium, unaffected by Chronomancy. \ +
\ +
Meal Quantity: Number of uses of the completed spell. \ +


\ + The segmented fusion of Gustomancy and Chemomancy is currently beyond the scope of this tome, as is the \ + usage of simple Gustomantic techniques such as rolling flat and slicing dough. The Gustomancer is reminded \ + most basic tools and supplies within the Gustomancy study, and most fusion fluids may be created with some \ + combination of flour, milk, water, egg, and enzyme." + // The joke is none of this is magic, and neither is the Wizard Federation. + +/datum/lore/codex/page/cooking_recipe + name = null + +// Algorithmically write all cooking recipes in the game. This should run once per round. +/datum/lore/codex/category/cooking_recipe_list/New() + ..() + var/list/new_children_list = list() + var/list/name_repeats = list() + for(var/Rp in subtypesof(/datum/recipe)) + var/datum/recipe/R = new Rp() // Datums must be initialized to read list vars + if(!istype(R)) + log_debug("Recipe generation failed, recipe datum is [R].") + qdel(R) + continue + + var/datum/lore/codex/page/cooking_recipe/D = new(holder, src) + var/atom/movable/these = R.result // Result is a typepath, requiring use of initial() + D.name = capitalize("[initial(these.name)]") // Capitalization on recipe names is inconsistent + + var/n = 1 + while(D.name in name_repeats) // Ensure each name is unique so we have a unique keyword for every recipe + D.name = "[capitalize("[initial(these.name)]")]-[n]" + n++ + name_repeats["[D.name]"] = TRUE // The value here doesn't matter, we just need this to be an associative list. + D.keywords.Add(D.name) + + // Most ingredient names will be capitalized to draw the reader's eye. + var/text = R.appliance + switch(text) // These are binary values, so we'll use the defines to convert to a string + if(MICROWAVE) + text = "Microwave" + if(FRYER) + text = "Deep fryer" + if(OVEN) + text = "Oven" + if(GRILL) + text = "Grill" + if(CANDYMAKER) + text = "Candy maker" + if(CEREALMAKER) + text = "Cereal maker" + else + text = "" + D.data = "Heat Applicator: [text ? text : "none"]
" + text = "" + + if(LAZYLEN(R.reagents)) + var/i = 0 // Comma counter + for(var/thing in R.reagents) // String + if(i) + text += ", " + text += "[capitalize(thing)]: [R.reagents[thing]] units" + i++ + D.data += "Pure Fluids: [text ? text : "none"]
" + text = "" + + if(LAZYLEN(R.items)) + var/i = 0 + for(var/atom/movable/AM as anything in R.items) // Atom typepath + if(i) + text += ", " + text += "[capitalize(initial(AM.name))]" + i++ + D.data += "Material Objects: [text ? text : "none"]
" + text = "" + + if(LAZYLEN(R.fruit)) // Inelegant copypasta time + var/i = 0 + for(var/thing in R.fruit) // String + if(i) + text += ", " + text += "[capitalize(thing)]: [R.fruit[thing]] quantity" + i++ + D.data += "Grown Produce: [text ? text : "none"]
" + text = "" + + if(R.coating) + var/datum/reagent/ooze = initial(R.coating) // Datum typepath + text = capitalize(initial(ooze.name)) + D.data += "Cooked Shell: [text ? text : "none"]
" + text = 0 + + if(R.time) // Deciseconds + text = R.time + D.data += "Temporal Shift: [text ? text/10 : 0] second\s
" + text = 0 + + if(R.result_quantity) // Should never be null. + text = R.result_quantity + D.data += "Meal Quantity: [text ? text : 0] plate\s
" + + new_children_list[D.name] = D // We make this an associative list so we can alphabetize later + qdel(R) // Delete recipe datum after we're done with it + + // This nonsense alphabetizes the list and converts back to array format before handing off to the parent. + // Array format is necessary for the codex code to work properly. + new_children_list = sortList(new_children_list) + var/list/sorted_children[LAZYLEN(new_children_list)] + for(var/x = 1, x <= LAZYLEN(sorted_children), x++) + var/key = new_children_list[x] + sorted_children[x] = new_children_list[key] + children = sortList(sorted_children) + src.index_page() diff --git a/vorestation.dme b/vorestation.dme index 1e9d60bc3e..64826c3882 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -2767,7 +2767,6 @@ #include "code\modules\looking_glass\lg_imageholder.dm" #include "code\modules\looking_glass\lg_turfs.dm" #include "code\modules\lore_codex\codex.dm" -#include "code\modules\lore_codex\codex_tree.dm" #include "code\modules\lore_codex\pages.dm" #include "code\modules\lore_codex\lore_data_yw\important_locations.dm" #include "code\modules\lore_codex\lore_data_yw\main.dm" @@ -4676,6 +4675,9 @@ #include "modular_chomp\code\modules\food\food\drinks\bottle.dm" #include "modular_chomp\code\modules\food\food\snacks\meat.dm" #include "modular_chomp\code\modules\living\carbon\human\ai_controlled\ai_controlled.dm" +#include "modular_chomp\code\modules\lore_codex\codex.dm" +#include "modular_chomp\code\modules\lore_codex\codex_tree.dm" +#include "modular_chomp\code\modules\lore_codex\cooking_codex.dm" #include "modular_chomp\code\modules\materials\materials\gems.dm" #include "modular_chomp\code\modules\materials\materials\metals\metals.dm" #include "modular_chomp\code\modules\materials\materials\organic\animal_products.dm"