added stuff
[fishladder.git] / fishladder.c
index ecd46814f29908b149143f235d1a52547aa1d331..19e3fb42b54f681bfa913e4a45201686ae55dc0f 100644 (file)
@@ -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();