From: hgn Date: Tue, 7 Dec 2021 15:21:07 +0000 (+0000) Subject: added stuff X-Git-Url: https://harrygodden.com/git/?p=fishladder.git;a=commitdiff_plain;h=aad3ce335e5a67018359442ee1c3a849d675ea18 added stuff --- diff --git a/fishladder.c b/fishladder.c index ecd4681..19e3fb4 100644 --- a/fishladder.c +++ b/fishladder.c @@ -48,91 +48,6 @@ const char *level_pack_1[] = { "thirds" }; -#pragma pack(push,1) -struct dcareer_state -{ - u32 version; - i32 total_unlocked; - - u32 reserved[14]; - - struct dlevel_state - { - i32 score; - i32 reserved[3]; - } - levels[ NUM_CAMPAIGN_LEVELS ]; -}; -#pragma pack(pop) - -static void career_serialize(void) -{ - struct dcareer_state encoded; - encoded.version = 2; - encoded.total_unlocked = career_local.total_unlocked; - - for( int i = 0; i < vg_list_size( career_serializable ); i ++ ) - { - struct serializable_set *set = &career_serializable[i]; - - for( int j = 0; j < set->count; j ++ ) - { - struct cmp_level *lvl = &set->pack[j]; - struct dlevel_state *dest = &encoded.levels[lvl->serial_id]; - - dest->score = lvl->completed_score; - dest->reserved[0] = 0; - dest->reserved[1] = 0; - dest->reserved[2] = 0; - } - } - - vg_asset_write( "sav/game.sv2", &encoded, sizeof( struct dcareer_state ) ); -} - -static void career_load(void) -{ - i64 sz; - struct dcareer_state encoded; - memset( (void*)&encoded, 0, sizeof( struct dcareer_state ) ); - - // Load and copy data into encoded - void *cr = vg_asset_read_s( "sav/game.sv2", &sz ); - - if( cr ) - { - if( sz > sizeof( struct dcareer_state ) ) - vg_warn( "This save file is too big! Some levels will be lost\n" ); - - if( sz <= offsetof( struct dcareer_state, levels ) ) - { - vg_warn( "This save file is too small to have a header. Creating a blank one\n" ); - free( cr ); - return; - } - - memcpy( (void*)&encoded, cr, VG_MIN( sizeof( struct dcareer_state ), sz ) ); - free( cr ); - } - else - vg_info( "No save file... Using blank one\n" ); - - // Decode everything from dstate - for( int i = 0; i < vg_list_size( career_serializable ); i ++ ) - { - struct serializable_set *set = &career_serializable[i]; - - for( int j = 0; j < set->count; j ++ ) - { - struct cmp_level *lvl = &set->pack[j]; - struct dlevel_state *src = &encoded.levels[lvl->serial_id]; - - lvl->completed_score = src->score; - // ... - } - } -} - m3x3f m_projection; m3x3f m_view; m3x3f m_mdl; @@ -381,7 +296,7 @@ struct world u32 score; u32 completed; u32 time; -} world = {}; +} world; void leaderboard_set_score( struct cmp_level *cmp_level, u32 score ); @@ -978,6 +893,148 @@ static int console_changelevel( int argc, char const *argv[] ) return 0; } +#pragma pack(push,1) +struct dcareer_state +{ + u32 version; + i32 in_map; + + u32 reserved[14]; + + struct dlevel_state + { + i32 score; + i32 unlocked; + i32 reserved[2]; + } + levels[ NUM_CAMPAIGN_LEVELS ]; +}; +#pragma pack(pop) + +static void career_serialize(void) +{ + struct dcareer_state encoded; + encoded.version = 2; + encoded.in_map = world.pCmpLevel? world.pCmpLevel->serial_id: -1; + + memset( encoded.reserved, 0, sizeof( encoded.reserved ) ); + + for( int i = 0; i < vg_list_size( career_serializable ); i ++ ) + { + struct serializable_set *set = &career_serializable[i]; + + for( int j = 0; j < set->count; j ++ ) + { + struct cmp_level *lvl = &set->pack[j]; + struct dlevel_state *dest = &encoded.levels[lvl->serial_id]; + + dest->score = lvl->completed_score; + dest->unlocked = lvl->unlocked; + dest->reserved[0] = 0; + dest->reserved[1] = 0; + } + } + + vg_asset_write( "sav/game.sv2", &encoded, sizeof( struct dcareer_state ) ); +} + +static void career_unlock_level( struct cmp_level *lvl ); +static void career_unlock_level( struct cmp_level *lvl ) +{ + lvl->unlocked = 1; + + if( lvl->linked ) + career_unlock_level( lvl->linked ); +} + +static void career_pass_level( struct cmp_level *lvl, int score, int upload ) +{ + if( score > 0 ) + { + if( score < lvl->completed_score || lvl->completed_score == 0 ) + { + if( !lvl->is_tutorial && upload ) + leaderboard_set_score( lvl, score ); + + lvl->completed_score = score; + } + + if( lvl->unlock ) career_unlock_level( lvl->unlock ); + } +} + +static void career_reset_level( struct cmp_level *lvl ) +{ + lvl->unlocked = 0; + lvl->completed_score = 0; +} + +static void career_load(void) +{ + i64 sz; + struct dcareer_state encoded; + + // Blank save state + memset( (void*)&encoded, 0, sizeof( struct dcareer_state ) ); + encoded.in_map = -1; + encoded.levels[0].unlocked = 1; + + // Load and copy data into encoded + void *cr = vg_asset_read_s( "sav/game.sv2", &sz ); + + if( cr ) + { + if( sz > sizeof( struct dcareer_state ) ) + vg_warn( "This save file is too big! Some levels will be lost\n" ); + + if( sz <= offsetof( struct dcareer_state, levels ) ) + { + vg_warn( "This save file is too small to have a header. Creating a blank one\n" ); + free( cr ); + return; + } + + memcpy( (void*)&encoded, cr, VG_MIN( sizeof( struct dcareer_state ), sz ) ); + free( cr ); + } + else + vg_info( "No save file... Using blank one\n" ); + + // Reset memory + for( int i = 0; i < vg_list_size( career_serializable ); i ++ ) + { + struct serializable_set *set = &career_serializable[i]; + + for( int j = 0; j < set->count; j ++ ) + career_reset_level( &set->pack[j] ); + } + + // Header information + // ================================= + + // Decode everything from dstate + for( int i = 0; i < vg_list_size( career_serializable ); i ++ ) + { + struct serializable_set *set = &career_serializable[i]; + + for( int j = 0; j < set->count; j ++ ) + { + struct cmp_level *lvl = &set->pack[j]; + struct dlevel_state *src = &encoded.levels[lvl->serial_id]; + + if( src->unlocked ) career_unlock_level( lvl ); + if( src->score ) lvl->completed_score = src->score; + + // ... + if( lvl->serial_id == encoded.in_map ) + { + if( console_changelevel( 1, &lvl->map_name ) ) + world.pCmpLevel = lvl; + } + } + } +} + void leaderboard_found( LeaderboardFindResult_t *pCallback ); void leaderboard_downloaded( LeaderboardScoresDownloaded_t *pCallback ); @@ -1139,8 +1196,8 @@ void vg_start(void) resource_load_main(); // Restore gamestate + career_local_data_init(); career_load(); - console_load_map( 1, level_pack_1 ); } void vg_free(void) @@ -1857,6 +1914,12 @@ void vg_update(void) world.score = score; world.time = world.sim_frame; + + // Copy into career data + if( world.pCmpLevel ) + { + career_pass_level( world.pCmpLevel, world.score, 1 ); + } } } else @@ -1867,14 +1930,6 @@ void vg_update(void) vg_error( "Level failed :(\n" ); } - // Copy into career data - if( world.pCmpLevel ) - { - if( world.score < world.pCmpLevel->completed_score || world.pCmpLevel->completed_score == 0 ) - leaderboard_set_score( world.pCmpLevel, world.score ); - - world.pCmpLevel->completed_score = world.score; - } simulation_stop(); // TODO: Async? break; @@ -2079,6 +2134,8 @@ void vg_render(void) // Level title + // TODO: Fix this? + /* ui_begin( &ui_global_ctx, 512, 256 ); ui_global_ctx.override_colour = 0xff9a8a89; @@ -2094,6 +2151,7 @@ void vg_render(void) m3x3_scale( world_text, (v3f){0.01f,-0.01f,0.01f} ); ui_draw( &ui_global_ctx, world_text ); + */ // Main // ========================================================================================= @@ -2304,12 +2362,13 @@ void vg_render(void) for( int j = 0; j < term->runs[k].condition_count; j ++ ) { float y_offset = is_input? 1.2f: -0.2f; - y_offset += (is_input? 0.2f: -0.2f) * (float)k; - - glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)posx + 0.2f + 0.2f * (float)j, (float)posy + y_offset, 0.1f ); + float y_h = (is_input? 0.2f: -0.2f) * (float)k; if( is_input ) { + glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)posx + 0.2f + 0.2f * (float)j, + (y_offset + (float)posy + (float)(term->run_count-1)*0.2f) - y_h, 0.1f ); + colour_code_v3( term->runs[k].conditions[j], dot_colour ); glUniform4fv( SHADER_UNIFORM( shader_tile_colour, "uColour" ), 1, dot_colour ); @@ -2321,6 +2380,8 @@ void vg_render(void) } else { + glUniform3f( SHADER_UNIFORM( shader_tile_colour, "uOffset" ), (float)posx + 0.2f + 0.2f * (float)j, (float)posy + y_offset + y_h, 0.1f ); + if( term->runs[k].recv_count > j ) { colour_code_v3( term->runs[k].recieved[j], dot_colour ); @@ -2493,8 +2554,7 @@ void vg_ui(void) { struct cmp_level *levels = pack_infos[ pack_selection ].levels; int count = pack_infos[ pack_selection ].level_count; - int unlocked = 3000; - + static struct ui_scrollbar sb = { .bar_height = 400 }; @@ -2530,7 +2590,7 @@ void vg_ui(void) { struct cmp_level *lvl_info = &levels[i]; - if( i < unlocked ) + if( lvl_info->unlocked ) { if( lvl_info->completed_score != 0 ) gui_override_colours( i&0x1? &flcol_list_complete_a: &flcol_list_complete_b ); @@ -2540,7 +2600,7 @@ void vg_ui(void) else gui_override_colours( &flcol_list_locked ); - if( i < unlocked ) + if( lvl_info->unlocked ) { if( gui_button( 2 + i ) == k_button_click ) { @@ -2648,11 +2708,13 @@ void vg_ui(void) gui_override_colours( &flcol_list_complete_a ); if( gui_button( 3002 ) == k_button_click ) { - console_changelevel( 1, &ui_data.level_selected->map_name ); - world.pCmpLevel = ui_data.level_selected; + if( console_changelevel( 1, &ui_data.level_selected->map_name ) ) + { + world.pCmpLevel = ui_data.level_selected; - ui_data.level_selected = NULL; - ui_data.leaderboard_show = 0; + ui_data.level_selected = NULL; + ui_data.leaderboard_show = 0; + } } gui_text( "PLAY", 6, k_text_alignment_center ); gui_end(); diff --git a/fishladder_resources.h b/fishladder_resources.h index c06c17d..8c8ee3b 100644 --- a/fishladder_resources.h +++ b/fishladder_resources.h @@ -566,129 +566,139 @@ struct cmp_level const char *title; const char *description; + int unlocked; int completed_score; - int unlocks; // When completed, unlock this many levels - int linked_unlocks; // When unlocked, unlock this many levels additionally + int _unlock, _linked; // When completed, unlock this level + struct cmp_level *unlock, *linked; int serial_id; + int is_tutorial; SteamLeaderboard_t steam_leaderboard; }; -struct cmp_level cmp_levels_tutorials[] = +static struct cmp_level cmp_levels_tutorials[] = { { + .serial_id = 0, .title = "PRINCIPLE 1", .map_name = "cmp_t01", .description = "Utilize basic transport methods", - .serial_id = 0, - .unlocks = 1 + ._unlock = 1, + .is_tutorial = 1 }, { + .serial_id = 1, .title = "PRINCIPLE 2", .map_name = "cmp_t02", .description = "Utilize the twisty turny(TM) piece to split\n" "the marble stream into two", - .serial_id = 1, - .unlocks = 1 + ._unlock = 2, + .is_tutorial = 1, }, { + .serial_id = 2, .title = "PRINCIPLE 3", .map_name = "cmp_t03", .description = "Merge transport into one", - .serial_id = 2, - .unlocks = 1, + ._unlock = 12, + .is_tutorial = 1 }, { + .serial_id = 12, .title = "PRINCIPLE 4", .map_name = "cmp_t04", .description = "Some stages require multiple runs to succeed\n" "in order to pass", - .serial_id = 12, - .unlocks = 3 + ._unlock = 3, + .is_tutorial = 1 } }; -struct cmp_level cmp_levels_basic[] = +static struct cmp_level cmp_levels_basic[] = { { + .serial_id = 3, .title = "SUBDIVISION 1", .map_name = "cmp_b01", .description = "Simple maths, branching required.", - .serial_id = 3, - .unlocks = 1 + ._linked = 4, + ._unlock = 6 }, { + .serial_id = 4, .title = "SUBDIVISION 2", .map_name = "cmp_b02", .description = "Simple maths, except more.", - - .serial_id = 4, - .unlocks = 1 + + ._linked = 5, + ._unlock = 7 }, { + .serial_id = 5, .title = "RESTRUCTURE", .map_name = "cmp_b03", .description = "Not so simple swap", - .serial_id = 5, - .unlocks = 1 + ._unlock = 8 }, { + .serial_id = 6, .title = "SERIALIZE", .map_name = "cmp_b04", .description = "Merge and sort", - .serial_id = 6, - .unlocks = 1 + ._unlock = 7 }, { + .serial_id = 7, .title = "PATTERNS 1", .map_name = "cmp_b05", .description = "Replicate", - .serial_id = 7, - .unlocks = 1 + ._linked = 8 }, { + .serial_id = 8, .title = "PATTERNS 2", .map_name = "cmp_b06", .description = "Replicate MORE", - .serial_id = 8, - .unlocks = 1 + ._unlock = 9 }, { + .serial_id = 9, .title = "MIGHTY CONSUMER", .map_name = "cmp_b07", .description = "Build a greedy system", - .serial_id = 9, - .unlocks = 1 + ._linked = 10, + ._unlock = 11 }, { + .serial_id = 10, .title = "ENCRYPTED 1", .map_name = "cmp_b08", .description = "Some configurations may not be valid", - .serial_id = 10, - .unlocks = 1 + ._unlock = 15 }, { + .serial_id = 11, .title = "REVERSE", .map_name = "cmp_b09", .description = "Reverse the incoming order. Always length 4", - .serial_id = 11, - .unlocks = 1 + ._unlock = 15 }, { + .serial_id = 15, .title = "PRINCIPLE 5", .map_name = "cmp_b10", .description = @@ -699,20 +709,20 @@ struct cmp_level cmp_levels_basic[] = "of your training package, you will now be tasked to\n" "complete them", - .serial_id = 15, - .linked_unlocks = 1 + ._unlock = 16 }, { + .serial_id = 16, .title = "ROUTING PROBLEM", .map_name = "cmp_routing", .description = "Things can get a little chaotic on tight boards, do your\n" "best to utilize principle 5 to get the job done\n", - .serial_id = 16, - .unlocks = 1 + ._unlock = 17 }, { + .serial_id = 17, .title = "PRINCIPLE 6", .map_name = "cmp_b11", .description = @@ -733,93 +743,95 @@ struct cmp_level cmp_levels_basic[] = "this results in no operation being performed, and no\n" "state changes take place in the Twisty Turny(TM)\n", - .serial_id = 17, - .linked_unlocks = 1 + ._unlock = 18 }, { + .serial_id = 18, .title = "NOT GATE", .map_name = "cmp_not", .description = "Test your knowledge of triggers, build an 'NOT GATE'\n" "emulated by marble logic.", - .serial_id = 18, - .unlocks = 1 + ._linked = 19, + ._unlock = 20 }, { + .serial_id = 19, .title = "AND GATE", .map_name = "cmp_and", .description = "A slightly more complicated gate, but shouldn't be\n" "too difficult for your skillset.", - .serial_id = 19, - .unlocks = 1 + ._unlock = 20 }, { + .serial_id = 20, .title = "QUALIFICATION PROJECT", .map_name = "cmp_grad", .description = "There's no instructions here, resolve and complete this\n" "task to qualify yourself as an official marble engineer", - .serial_id = 20, - .unlocks = 3 + ._unlock = 13 } }; -struct cmp_level cmp_levels_grad[] = +static struct cmp_level cmp_levels_grad[] = { { + .serial_id = 13, .title = "SORT", .map_name = "cmp_i01", .description = "Device a scheme to filter and sort the inputs. If you\n" "believe you lack the tools required to solve this one,\n" "take a harder look at the inputs.", + ._linked = 14 - .serial_id = 13 }, { + .serial_id = 14, .title = "THIRDS", .map_name = "cmp_i02", .description = "Split the inputs up into a third of their values\n" "\n" "Is this possible? -HG", + ._linked = 21 - .serial_id = 14 }, { + .serial_id = 21, .title = "XOR CHIP", .map_name = "cmp_xor", .description = "Significantly more complicated than an AND or NOT gate,\n" "but possible.", - .serial_id = 21 + ._linked = 22 }, { + .serial_id = 22, .title = "SECRET CODE", .map_name = "cmp_secret", .description = "Only one input should send an unlock signal marble to\n" "the output.\n" - "The code: 100110", - .serial_id = 22 + "The code: 100110" } }; #define NUM_CAMPAIGN_LEVELS (vg_list_size( cmp_levels_tutorials ) + vg_list_size( cmp_levels_basic ) + vg_list_size( cmp_levels_grad )) -struct +/* +static struct { - int total_unlocked; } career_local = { - .total_unlocked = 1 -}; +};*/ -struct serializable_set +static struct serializable_set { struct cmp_level *pack; int count; @@ -839,3 +851,31 @@ career_serializable[] = .count = vg_list_size( cmp_levels_grad ) } }; + +// Setup pointers and that +static void career_local_data_init(void) +{ + struct cmp_level *level_ptrs[ NUM_CAMPAIGN_LEVELS ]; + + // COllect pointers + for( int i = 0; i < vg_list_size( career_serializable ); i ++ ) + { + struct serializable_set *set = &career_serializable[i]; + + for( int j = 0; j < set->count; j ++ ) + level_ptrs[ set->pack[j].serial_id ] = &set->pack[j]; + } + + // Apply + for( int i = 0; i < vg_list_size( career_serializable ); i ++ ) + { + struct serializable_set *set = &career_serializable[i]; + + for( int j = 0; j < set->count; j ++ ) + { + struct cmp_level *lvl = &set->pack[j]; + lvl->unlock = lvl->_unlock? level_ptrs[ lvl->_unlock ]: NULL; + lvl->linked = lvl->_linked? level_ptrs[ lvl->_linked ]: NULL; + } + } +} diff --git a/maps/cmp_t01.map b/maps/cmp_t01.map new file mode 100644 index 0000000..76b32b8 --- /dev/null +++ b/maps/cmp_t01.map @@ -0,0 +1,8 @@ +#########; +###-#####;aa +## ##; +## ##; +## ##; +## ##; +#####+###;aa +#########; diff --git a/maps/cmp_t02.map b/maps/cmp_t02.map new file mode 100644 index 0000000..5d06111 --- /dev/null +++ b/maps/cmp_t02.map @@ -0,0 +1,9 @@ +#########; +##-###-##;b,b +## ##; +## ##; +## ##; +## ##; +## ##; +####+####;bb +#########; diff --git a/maps/cmp_t03.map b/maps/cmp_t03.map new file mode 100644 index 0000000..46cc4e7 --- /dev/null +++ b/maps/cmp_t03.map @@ -0,0 +1,8 @@ +###########; +#####-#####;bbbbb +## ##; +## ###; +## # ##; +## ##; +###+##+####;bbb,bb +###########; diff --git a/maps/cmp_t04.map b/maps/cmp_t04.map new file mode 100644 index 0000000..48bcc5b --- /dev/null +++ b/maps/cmp_t04.map @@ -0,0 +1,10 @@ +#############; +###-#####-###;a:aa,b:bb +## ##; +## ##; +## ##; +## ##; +## ##; +## ##; +######+######;ab:abab +#############; diff --git a/maps/level0.map b/maps/level0.map deleted file mode 100644 index a30aab9..0000000 --- a/maps/level0.map +++ /dev/null @@ -1,9 +0,0 @@ -PRINCIPLE 1 -#########; -###-#####;acac -## ##; -## ##; -## ##; -## ##; -#####+###;acac -#########; diff --git a/maps/level1.map b/maps/level1.map deleted file mode 100644 index 5d06111..0000000 --- a/maps/level1.map +++ /dev/null @@ -1,9 +0,0 @@ -#########; -##-###-##;b,b -## ##; -## ##; -## ##; -## ##; -## ##; -####+####;bb -#########; diff --git a/maps/level2.map b/maps/level2.map deleted file mode 100644 index 46cc4e7..0000000 --- a/maps/level2.map +++ /dev/null @@ -1,8 +0,0 @@ -###########; -#####-#####;bbbbb -## ##; -## ###; -## # ##; -## ##; -###+##+####;bbb,bb -###########; diff --git a/vg/vg_ui.h b/vg/vg_ui.h index 7e67654..1172850 100644 --- a/vg/vg_ui.h +++ b/vg/vg_ui.h @@ -384,8 +384,8 @@ static void ui_new_node( ui_ctx *ctx ) if( parent->mouse_over ) { - if( ctx->mouse[0] >= node->rect[0] && ctx->mouse[0] <= node->rect[0]+node->rect[2] && - ctx->mouse[1] >= node->rect[1] && ctx->mouse[1] <= node->rect[1]+node->rect[3] ) + if( ctx->mouse[0] >= node->rect[0] && ctx->mouse[0] < node->rect[0]+node->rect[2] && + ctx->mouse[1] >= node->rect[1] && ctx->mouse[1] < node->rect[1]+node->rect[3] ) node->mouse_over = 1; else node->mouse_over = 0;