an atelier fangame for the pico-8
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
atelier_phoebe/screen_crafting.lua

505 lines
16 KiB

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)