@ -4,218 +4,294 @@ grid_height = 5
grid_x = 14
grid_y = 34
c = {
ing_slot = 1 , -- the slot in the recipe currently being modified, whether sselecting trait or ingredient
ing_idx = 1 , -- the index into filtered ingredients of the current ingredient selection
trait_slot = 0 , -- the trait sslot of the recipe we're modifying.
x = 0 , y = 0 -- x y coordinates in the puzzle grid for the current trait
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 = { }
}
center_glyph = 132
ingredients = { }
-- traits which have been placed
traits = { }
state = {
choosing_ingredient = true ,
placing_trait = false ,
finalizing = false ,
choosing_ingredient = true
placing_trait = false
finalizing = false
big_button = false
final_trait_options = { }
final_selected_traits = { }
filtered_ingredients = { } ,
final_trait_options = { } ,
}
function crafting_before ( )
center_glyph = rnd ( { 132 , 134 , 164 , 166 } )
c.x = 0
c.y = 0
c.ing_slot = 1
c.ing_idx = 1
c.trait_slot = 0
ingredients = { }
traits = { }
final_trait_options = { }
choosing_ingredient = true
placing_trait = false
finalizing = false
big_button = false
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 choosing_ingredient then
if state. choosing_ingredient then
crafting_choice_update ( )
elseif placing_trait then
elseif state. placing_trait then
crafting_place_update ( )
elseif finalizing then
elseif state. finalizing then
crafting_finalize_update ( )
end
end
function crafting_choice_update ( )
requirement = current_recipe.ingredients [ c.ing_slot ]
filtered_ingredients = filter_list (
inventory ,
function ( ing )
if contains ( ingredients , ing ) then return false end
return requirement == ing.title or contains ( ing.tags , requirement )
end )
current_ingredient = filtered_ingredients [ c.ing_idx ]
local current_slot_requirement = current_recipe.ingredients [ cursor.ing_slot ]
if btnp ( 0 ) and c.ing_idx > 1 then
if btnp ( 0 ) and cursor.ing_idx > 1 then
sfx ( 3 )
c.ing_idx -= 1
cursor.ing_idx -= 1
end
if btnp ( 1 ) and c.ing_idx <# filtered_ingredients then
if btnp ( 1 ) and cursor.ing_idx <# state.filtered_ingredients then
sfx ( 3 )
c.ing_idx += 1
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 ( ingredients , current_ingredient )
if # current_ingredient.traits ~= 0 then
-- if there are traits on tihs ingredient, move on to setting traits.
choosing_ingredient = false
placing_trait = true
finalizing = false
c.trait_slot = 1
c.ing_idx = 1
elseif # ingredients < # current_recipe.ingredients then
-- if there are remaining ingredients to set, then we move to the next ingredient slot.
choosing_ingredient = true
placing_trait = false
finalizing = false
c.trait_slot = 0
c.ing_idx = 1
c.ing_slot += 1
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 we finalize.
sfx ( 2 )
c.x , c.y = 0 , 0
final_trait_options = filter_list ( traits , function ( x ) return x.active end )
choosing_ingredient = false
placing_trait = false
final_selected_traits = { }
finalizing = true
c.trait_slot = 0
c.ing_idx = 1
c.ing_slot = 1
-- if there are no more ingredients to set, then move on to finalizing.
begin_finalize ( )
end
end
if ( btnp ( 5 ) ) then
-- delete the last ingredient from the ingredients list
if # ingredients == 0 then
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
traits = filter_list (
traits ,
function ( set_trait ) return set_trait.from_ingredient_slot ~= # ingredients end
)
deli ( ingredients )
c.trait_slot = 0
if choosing_ingredient and c.ing_slot > 1 then c.ing_slot -= 1 end
choosing_ingredient = true
placing_trait = false
--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 ( )
current_ingredient = ingredients [ c.ing_slot ]
current_trait = library.traits [ current_ingredient.traits [ c.trait_slot ] ]
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 ]
width = current_trait [ 4 ]
height = current_trait [ 5 ]
local width = current_trait [ 4 ]
local height = current_trait [ 5 ]
if btnp ( 0 ) and c.x > 0 then c.x -= 1 end
if btnp ( 1 ) and c.x + width < grid_width then c.x += 1 end
if btnp ( 2 ) and c.y > 0 then c.y -= 1 end
if btnp ( 3 ) and c.y + height < grid_height then c.y += 1 end
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
new_trait = { trait = current_trait , x = c.x , y = c.y , active = true , from_ingredient_slot = c.ing_slot }
for idx , trait in ipairs ( traits ) do
if overlaps ( trait , new_trait ) then
traits [ idx ] . active = false
-- 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 ( traits , new_trait )
c.x , c.y = 0 , 0
-- add it to the record!~
add ( partial_recipe.trait_listings , new_trait_listing )
if c.trait_slot < # current_ingredient.traits then
-- if there's more traits to set, then we should keep setting traits.
choosing_ingredient = false
placing_trait = true
finalizing = false
c.trait_slot += 1
elseif c.ing_slot < # current_recipe.ingredients then
-- 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.
choosing_ingredient = true
placing_trait = false
finalizing = false
c.trait_slot = 0
c.ing_slot += 1
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.
sfx ( 2 )
c.x , c.y = 0 , 0
final_trait_options = filter_list ( traits , function ( x ) return x.active end )
choosing_ingredient = false
placing_trait = false
finalizing = true
final_selected_traits = { }
c.trait_slot = 0
c.ing_slot = 1
begin_finalize ( )
end
end
if ( btnp ( 5 ) ) then
undo_ingredient ( )
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 # final_trait_options < 3 then big_button = true end
if not big_button then
newx , newy = c.x , c.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 ( final_trait_options [ 2 * newy + newx + 1 ] ~= nil ) and newx <= 1 and newx >= 0 then
c.x , c.y = newx , newy
elseif btnp ( 3 ) and not ( btnp ( 0 ) or btnp ( 1 ) or btnp ( 2 ) ) then
big_button = true
end
local i = 2 * c.y + c.x + 1
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 big_button then
if contains ( final_selected_traits , i ) then
del ( final_selected_traits , i )
elseif # final_selected_traits < 2 then
add ( final_selected_traits , i )
end
end
--todo: go back (btnp5)
else
if btnp ( 2 ) and # final_trait_options > 2 then big_button = false end
if btnp ( 4 ) then
make_the_product ( )
big_button = false
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
if btnp ( 5 ) and # final_trait_options < 3 then
-- go back a step
undo_ingredient ( )
finalizing = false
elseif btnp ( 5 ) then
big_button = false
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
@ -223,41 +299,29 @@ end
function make_the_product ( )
local product = make_item ( library.item_blueprints [ current_recipe.result ] )
product.quality = quality ( )
add ( inventory , product )
for x in all ( ingredients ) do
del ( inventory , x )
for ingredient in all ( partial_recipe.ingredients ) do
-- remove all the ingredientss that we used
del ( inventory , ingredient )
end
product.traits = { }
if # final_trait_options < 3 then
for t in all ( final_trait_options ) do
add ( product.traits , t.trait [ 1 ] )
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 i in all ( final_selected_traits ) do
add ( product.traits , final_trait_options [ i ] . trait [ 1 ] )
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 undo_ingredient ( )
if # ingredients == 0 then
change_screen ( screen_recipe_list )
else
traits = filter_list (
traits ,
function ( set_trait ) return set_trait.from_ingredient_slot ~= # ingredients end
)
deli ( ingredients )
c.trait_slot = 0
if choosing_ingredient and c.ing_slot > 1 then c.ing_slot -= 1 end
choosing_ingredient = true
placing_trait = false
end
end
function crafting_draw ( )
cls ( )
@ -270,91 +334,41 @@ function crafting_draw()
-- puzzle grid including pieces
draw_grid ( )
if finalizing then
if # final_trait_options > 2 then
draw_paper ( 24 , 10 , 128 - 24 - 24 , 128 - 10 - 10 )
color ( highlight_text_color )
print ( " pick two traits \n to keep! " , 32 , 20 )
for i , trait in ipairs ( 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 ( final_selected_traits , i ) then
rect ( x - 2 , y - 2 , x + 30 , y + 6 , 10 )
end
if not big_button and xi == c.x and yi == c.y then
rect ( x - 2 , y - 2 , x + 30 , y + 6 , 0 )
end
if contains ( final_selected_traits , i ) then
color ( highlight_text_color )
else
color ( base_text_color )
end
print ( trait.trait [ 1 ] , x , y )
end
--draw_paper(40, 76, 128-40-40, 12)
color ( highlight_text_color )
if 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 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 big_button then
color ( 12 )
else
color ( highlight_text_color )
end
print ( " create! " , 64 - 12 , 80 )
end
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 trait in all ( traits ) do
if trait .active then
map ( trait .trait [ 2 ] , trai t.trait[ 3 ] ,
( trait .x * grid_size ) + grid_x , ( trai t.y* grid_size ) + grid_y ,
trait .trait [ 4 ] , trai t.trait[ 5 ] )
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 ( placing_trait ) then
trait = library.traits [ ingredients [ c.ing_slot ] . traits [ c.trait_slot ] ]
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 ] ,
( c.x * grid_size ) + grid_x , ( c.y * grid_size ) + grid_y ,
( 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 ( ingredients ) do
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 = ( c.ing_slot + 1 ) , # current_recipe.ingredients do
for i = ( cursor.ing_slot + 1 ) , # current_recipe.ingredients do
print ( current_recipe.ingredients [ i ] , x + 46 , y + 2 + 26 * i + 9 )
end
@ -365,49 +379,108 @@ function draw_recipe_in_progress_on_paper(x, y)
print_quality ( quality ( ) , x + 44 , y + 18 )
if ( choosing_ingredient and c.ing_slot < # current_recipe.ingredients + 1 ) then
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 * c.ing_slot
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 [ c.ing_slot ] , x + 46 , y + 2 + 26 * c.ing_slot + 9 )
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 ( placing_trait ) then
elseif state.placing_trait then
-- draw a marker for the trait we're picking
yc = y + 26 * c.ing_slot
yc = 3 + yc + c.trait_slot * 6
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 ( traits , function ( trait ) return trait.active end ) ) do
for i , t in ipairs ( filter_list ( partial_recipe. trait_listing s, 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 \n to 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 ( ingredients ) do
for ing in all ( partial_recipe. ingredients) do
quality_sum += ing.quality
end
if # ingredients > 1 then
quality_sum = flr ( quality_sum /# ingredients )
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 ( traits ) do
for trait in all ( partial_recipe. traits) do
if trait.active then quality_sum += 5 end
end
@ -416,12 +489,14 @@ end
screen_crafting_raw = { before = crafting_before , draw = crafting_draw , update = crafting_update }
screen_crafting = screen_conversation ( {
{ phoebe_portrait , [[when i craft, i pick ingredients one by one with left and right]] } ,
{ phoebe_portrait , [[and press 🅾️ to lock them in before picking what traits to use]] } ,
{ phoebe_portrait , [[trying to fit them into the grid, which increases the quality. ]] } ,
{ phoebe_portrait , [[two traits from those still in the grid at the end are added to the product!]] } ,
{ phoebe_portrait , [[but if you overlap a trait, it will be removed.]] } ,
{ phoebe_portrait , [[i've even heard of some traits that combine to form others!]] }
{ 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