|
|
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)
|
|
|
|