grid_size = 8 grid_width = 5 grid_height = 5 grid_x = 14 grid_y = 34 center_glyph = 132 cursor = { ing_slot=1, ing_idx=1, trait_slot=1, x=0, y=0, big_button=false, } partial_recipe = { ingredients = {}, trait_listings = {}, final_selected_traits = {} } state = { choosing_ingredient = true, placing_trait = false, finalizing = false, filtered_ingredients={}, final_trait_options={}, } function crafting_before() center_glyph = rnd({132, 134, 164, 166}) cursor = { ing_slot=1, ing_idx=1, trait_slot=1, x=0, y=0, big_button=false, -- are we selecting the big button? } partial_recipe = { ingredients = {}, trait_listings = {}, final_selected_traits = {} } state = { -- three state flags for which phase of synthesis we're in choosing_ingredient = true, -- choosing an ingredient for one of the slots of the recipe. placing_trait = false, -- placing a trait into the grid. finalizing = false, -- selecting the final traits and clicking the create glyph -- arrays in use filtered_ingredients={}, -- the filtered list of ingredients we could use for the currently selected slot final_trait_options={}, -- all the traits which were active at the end of the } update_filtered_ingredients() end function crafting_update() if state.choosing_ingredient then crafting_choice_update() elseif state.placing_trait then crafting_place_update() elseif state.finalizing then crafting_finalize_update() end end function crafting_choice_update() local current_slot_requirement = current_recipe.ingredients[cursor.ing_slot] if btnp(0) and cursor.ing_idx>1 then sfx(3) cursor.ing_idx -= 1 end if btnp(1) and cursor.ing_idx<#state.filtered_ingredients then sfx(3) cursor.ing_idx += 1 end local current_ingredient = state.filtered_ingredients[cursor.ing_idx] if btnp(4) and current_ingredient ~= nil then -- lock in this ingredient and move on to moving traits arund add(partial_recipe.ingredients, current_ingredient) if #(current_ingredient.traits) ~= 0 then -- if there are traits on this ingredient, set them. state.choosing_ingredient = false state.placing_trait = true cursor.trait_slot = 1 elseif #partial_recipe.ingredients < #current_recipe.ingredients then -- if there are remaining ingredients to set, do that. cursor.ing_idx = 1 cursor.ing_slot += 1 update_filtered_ingredients() else -- if there are no more ingredients to set, then move on to finalizing. begin_finalize() end end if btnp(5) then local previous_index = cursor.ing_slot - 1 if #(partial_recipe.ingredients) == 0 then -- if there's no ingredients set, we back out. change_screen(screen_recipe_list) --otherwise, there are ingreddients set, and cursor.ing_slot is greater than one. elseif #(partial_recipe.ingredients[previous_index].traits) ~= 0 then -- we're setting an ingredient. -- the previous ingredient slot has an ingredient set with traits. -- delete the last set trait and pick it up as our cursor. local last_set_trait = deli(partial_recipe.trait_listings) cursor.ing_slot -= 1 cursor.ing_idx = 1 cursor.trait_slot = last_set_trait.ingredient_trait_slot cursor.x = last_set_trait.x cursor.y = last_set_trait.y state.choosing_ingredient = false state.placing_trait = true else --we're setting an ingredient, but the previouus ingredient didn't have any traits. deli(partial_recipe.ingredients) cursor.ing_slot = cursor.ing_slot - 1 cursor.ing_idx = 1 update_filtered_ingredients() end end end function update_filtered_ingredients() local current_slot_requirement = current_recipe.ingredients[cursor.ing_slot] state.filtered_ingredients = filter_list( inventory, function(ing) if contains(partial_recipe.ingredients, ing) then return false end if contains(ing.tags, current_recipe.ingredients[cursor.ing_slot]) then return true end return current_slot_requirement == ing.title end) end function crafting_place_update() local current_ingredient = partial_recipe.ingredients[cursor.ing_slot] local current_trait_name = current_ingredient.traits[cursor.trait_slot] local current_trait = library.traits[current_trait_name] local width = current_trait[4] local height = current_trait[5] if btnp(0) and cursor.x>0 then cursor.x -= 1 end if btnp(1) and cursor.x+width < grid_width then cursor.x += 1 end if btnp(2) and cursor.y>0 then cursor.y -= 1 end if btnp(3) and cursor.y+height < grid_height then cursor.y += 1 end if btnp(4) then -- make a new trait listing local new_trait_listing = { ingredient_i_belong_to=cursor.ing_slot, -- index of the ingredient this strait belongs to ingredient_trait_slot=cursor.trait_slot, -- which trait slot we came from x=cursor.x, y=cursor.y, --offset of the piece in the grid trait = current_trait, -- the trait in question active = true, -- whether the trait is active } -- turn off all overlapped traits for idx, trait_listing in ipairs(partial_recipe.trait_listings) do if overlaps(trait_listing, new_trait_listing) then trait_listing.active = false end end -- add it to the record!~ add(partial_recipe.trait_listings, new_trait_listing) -- move on to the next step if cursor.trait_slot < #current_ingredient.traits then -- if there's more traits to set, then we should keep setting traits! cursor.trait_slot += 1 elseif cursor.ing_slot < #current_recipe.ingredients then -- if there's more ingredients to set, then we move on to setting ingredients. state.choosing_ingredient = true state.placing_trait = false cursor.trait_slot = 1 cursor.ing_slot += 1 cursor.ing_idx = 1 update_filtered_ingredients() else -- if there's no more ingredients to set, then we move on to finalizing. begin_finalize() end end if btnp(5) then -- we are placing traits. -- that means that cursor.ing_slot refers to an ingredient which is set -- and cursor.trait_slot refers to 1 or 2, and one which isn't set. -- if curssor.trait_slot is 2, then we should delete the last set trait. if cursor.trait_slot == 1 then state.choosing_ingredient = true state.placing_trait = false deli(partial_recipe.ingredients) update_filtered_ingredients() else -- if we were placing the second trait, then we should go to placing the first trait, -- which we also need to remoove from the trait listings. cursor.trait_slot -= 1 local last = deli(partial_recipe.trait_listings) cursor.x = last.x cursor.y = last.y end end end function begin_finalize() sfx(2) state.final_trait_options = filter_list(partial_recipe.trait_listings, function(x) return x.active end) state.choosing_ingredient = false state.placing_trait = false state.finalizing = true cursor.x = 0 cursor.y = 0 end function crafting_finalize_update() if #state.final_trait_options < 3 then cursor.big_button = true end local newx = cursor.x local newy = cursor.y if btnp(0) then newx -= 1 end if btnp(1) then newx += 1 end if btnp(2) then newy -= 1 end if btnp(3) then newy += 1 end if not cursor.big_button and (state.final_trait_options[2*newy + newx + 1] ~= nil) and newx <= 1 and newx >= 0 then cursor.x, cursor.y = newx, newy elseif btnp(3) and not (btnp(0) or btnp(1) or btnp(2)) then -- if the next selected thing was out of bounds but we pressed down, then we're highlighting the big button cursor.big_button = true end local i = 2*cursor.y + cursor.x + 1 if btnp(4) and not cursor.big_button then if contains(partial_recipe.final_selected_traits, i) then del(partial_recipe.final_selected_traits, i) elseif #partial_recipe.final_selected_traits < 2 then add(partial_recipe.final_selected_traits, i) end end if btnp(2) and cursor.big_button and #state.final_trait_options > 2 then -- if we're on the big button, and there's enough trait options, then if we press up, -- it should unsselect the big button. cursor.big_button = false end if btnp(4) and cursor.big_button then -- if you pressed o and had the big button selected, then do the thing! make_the_product() cursor.big_button = false end if btnp(5) then local last_ingredient = partial_recipe.ingredients[#partial_recipe.ingredients] if #last_ingredient.traits == 0 then state.finalizing = false state.choosing_ingredient = true cursor.ing_idx = 1 deli(partial_recipe.ingredients) else local trait_listing = deli(partial_recipe.trait_listings) state.finalizing = false state.placing_trait = true cursor.trait_slot = trait_listing.ingredient_trait_slot cursor.x = trait_listing.x cursor.y = trait_listing.y end end end function make_the_product() local product = make_item(library.item_blueprints[current_recipe.result]) product.quality = quality() for ingredient in all(partial_recipe.ingredients) do -- remove all the ingredientss that we used del(inventory, ingredient) end product.traits = {} if #state.final_trait_options < 3 then for trait_listing in all(state.final_trait_options) do add(product.traits, trait_listing.trait[1]) end else for idx in all(partial_recipe.final_selected_traits) do add(product.traits, state.final_trait_options[idx].trait[1]) end end add(inventory, product) sfx(5) change_screen(screen_recipe_list) end function crafting_draw() cls() draw_background() draw_paper(30,8,140,140) draw_recipe_on_paper(current_recipe, 30, 8) draw_recipe_in_progress_on_paper(30, 8) -- puzzle grid including pieces draw_grid() if state.finalizing then draw_finalizing_sheet() end end function draw_grid() map(0,0, grid_x,grid_y, grid_width+1,grid_height+1) for t in all(partial_recipe.trait_listings) do if t.active then map(t.trait[2], t.trait[3], (t.x*grid_size)+grid_x, (t.y*grid_size)+grid_y, t.trait[4], t.trait[5]) end end if (state.placing_trait) then local current_ingredient = partial_recipe.ingredients[cursor.ing_slot] local current_trait_label = current_ingredient.traits[cursor.trait_slot] local trait = library.traits[current_trait_label] -- draw the currently selected trait into the grid map(trait[2], trait[3], (cursor.x*grid_size)+grid_x, (cursor.y*grid_size)+grid_y, trait[4], trait[5]) end end function draw_recipe_in_progress_on_paper(x, y) -- selected ingredients for i, ing in ipairs(partial_recipe.ingredients) do draw_ingredient_listing(ing, x+40, y + 26*i) end color(blank_ingredient_outline_color) for i=(cursor.ing_slot+1),#current_recipe.ingredients do print(current_recipe.ingredients[i], x+46, y+2+26*i+9) end -- quality listing color(base_text_color) print("quality", x+2, y+12) print_quality(quality(), x+44, y+18) if state.choosing_ingredient and cursor.ing_slot < #current_recipe.ingredients + 1 then -- draw a box around the ingredient we're choosing yc = y + 26*cursor.ing_slot xc = x+40 rect(xc, yc, xc+55, yc+26,10) spr(6, xc-8, yc+10) spr(7, xc+56, yc+10) local current_ingredient = state.filtered_ingredients[cursor.ing_idx] if current_ingredient == nil then color(blank_ingredient_outline_color) print(current_recipe.ingredients[cursor.ing_slot], x+46, y+2+26*cursor.ing_slot+9) else -- draw the ingredient listing for the selected ingredient draw_ingredient_listing(current_ingredient, xc, yc) end elseif state.placing_trait then -- draw a marker for the trait we're picking yc = y + 26*cursor.ing_slot yc = 3+yc+cursor.trait_slot*6 xc = x+38 spr(8, xc, yc) end for i, t in ipairs(filter_list(partial_recipe.trait_listings, function(trait) return trait.active end)) do color(base_text_color) print(t.trait[1], x+5, y+78 + 8*i) end end function draw_finalizing_sheet() if #state.final_trait_options > 2 then draw_paper(24, 10, 128-24-24, 128-10-10) color(highlight_text_color) print("pick two traits\nto keep!",32, 20) for i, trait_listing in ipairs(state.final_trait_options) do xi, yi = (i-1)%2, (i+i%2-2)/2 x, y = 64-32+xi*32, 34+yi*8 if contains(partial_recipe.final_selected_traits, i) then rect(x-1, y-1, x+29, y+5, 10) end if not cursor.big_button and xi == cursor.x and yi == cursor.y then rect(x-2, y-2, x+30, y+6, 0) end if contains(partial_recipe.final_selected_traits, i) then color(highlight_text_color) else color(base_text_color) end print(trait_listing.trait[1], x, y ) end --draw_paper(40, 76, 128-40-40, 12) color(highlight_text_color) if cursor.big_button then pal(9,0) else palt(12, true) end spr(128, 64-16, 72, 4,4) spr(center_glyph, 64-8, 80, 2, 2) pal() palt() if cursor.big_button then color(12) else color(highlight_text_color) end print("create!", 64-12, 108) else draw_paper(30, 30, 128-30-30, 128-30-30) pal(9,0) spr(128, 64-16, 60-16, 4,4) spr(center_glyph, 64-8, 60-8, 2, 2) pal() palt() if cursor.big_button then color(12) else color(highlight_text_color) end print("create!", 64-12, 80) end end function quality() local quality_sum = 0 for ing in all(partial_recipe.ingredients) do quality_sum += ing.quality end if #partial_recipe.ingredients > 1 then quality_sum = flr(quality_sum/#partial_recipe.ingredients) else quality_sum = flr(quality_sum) end for trait in all(partial_recipe.traits) do if trait.active then quality_sum += 5 end end return quality_sum end screen_crafting_raw = {before=crafting_before, draw=crafting_draw, update=crafting_update} screen_crafting = screen_conversation({ {ph_p, [[when i craft, i pick which of each ingredient to use with left and right,]]}, {ph_p, [[and press 🅾️ to lock them in.]]}, {ph_p, [[some items have additional traits for their special properties.]]}, {ph_p, [[i set a puzzle piece into the grid for each trait on the object.]]}, {ph_p, [[every trait i put in the grid increases the overall quality.]]}, {ph_p, [[but if you overlap other traits' tiles, it'll remove the old ones!]]}, {ph_p, [[then at the end, you can pick two traits to transfer]]}, {ph_p, [[onto the final product.]]}, }, function() screen_crafting = screen_crafting_raw change_screen(screen_crafting) end, screen_crafting_raw)