r1
[fishladder.git] / fishladder.c
index 81c2b82409e347fd85555dcf47bcb58c2c133193..c9f2eb61b5dec0b479fda5e232d4b96bbbe3f927 100644 (file)
@@ -1,7 +1,7 @@
 // Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved
 
-#define VG_CAPTURE_MODE
-#define VG_STEAM
+//#define VG_CAPTURE_MODE
+//#define VG_STEAM
 #define VG_STEAM_APPID 1218140U
 #include "vg/vg.h"
 #include "fishladder_resources.h"
@@ -258,11 +258,82 @@ struct world
 // Forward declerations
 // --------------------
 
+// Utility functions
+// -----------------
+
+static void colour_code_v3( char const cc, v3f target );
+static int hash21i( v2i p, u32 umod );
+
+// Mesh functions
+// --------------
+static void init_mesh( struct mesh *m, float const *tris, u32 length );
+static void free_mesh( struct mesh *m );
+static void use_mesh( struct mesh *m );
+static void draw_mesh( int const start, int const count );
+
+// World buttons
+// -------------
+static struct cell_button *get_wbutton( enum e_world_button btn );
+static void wbutton_run( enum e_world_button btn_name, v2f btn_tex );
+static void wbutton_draw( v2i pos, v2f tex, v4f colour );
+static void level_selection_buttons(void);
+
+// Map/world interface
+// -------------------
+static void map_free(void);
+static void io_reset(void);
+static struct cell *pcell( v2i pos );
+static void map_reclassify( v2i start, v2i end, int update_texbuffer );
+static u32 gen_text_buffer( const char *str, struct sdf_font *font, v2f origin, float size, u32 start );
+static void gen_level_text( struct cmp_level *pLevel );
+static int map_load( const char *str, const char *name );
+static void map_serialize( FILE *stream );
+
+// Career
+// ------
+static void career_serialize(void);
+static void career_unlock_level( struct cmp_level *lvl );
+static void career_unlock_level( struct cmp_level *lvl );
+static void career_pass_level( struct cmp_level *lvl, int score, int upload );
+static void career_reset_level( struct cmp_level *lvl );
+static void career_load(void);
+static void clear_animation_flags(void);
+
+// Gameplay main
+// -------------
+static void simulation_stop(void);
+static void simulation_start(void);
+static int world_check_pos_ok( v2i co );
+static int cell_interactive( v2i co );
+
+void vg_update(void);
+static void render_tiles( v2i start, v2i end, v4f const regular_colour, v4f const selected_colour );
+
+void vg_render(void);
+void vg_ui(void);
+
+// Leaderboard stuff
+// -----------------
+#ifdef STEAM_LEADERBOARDS
+void leaderboard_set_score( struct cmp_level *cmp_level, u32 score );
+void leaderboard_dispatch_score(void);
+void leaderboard_found( LeaderboardFindResult_t *pCallback );
+void leaderboard_downloaded( LeaderboardScoresDownloaded_t *pCallback );
+void leaderboard_set_score( struct cmp_level *cmp_level, u32 score );
+#endif
+
+// Console commands
+// ----------------
 static int console_credits( int argc, char const *argv[] );
 static int console_save_map( int argc, char const *argv[] );
 static int console_load_map( int argc, char const *argv[] );
 static int console_changelevel( int argc, char const *argv[] );
 
+void vg_start(void);
+void vg_free(void);
+
+int main( int argc, char *argv[] );
+
 // GLOBALS
 // ===========================================================================================================
 
@@ -275,22 +346,36 @@ struct world world;
 // UTILITY
 // ===========================================================================================================
 
+static int colour_set_id = 0;
+
 static void colour_code_v3( char const cc, v3f target )
 {
-       static v3f colour_sets[] =
-       { { 1.0f, 0.9f, 0.3f },
-         { 0.2f, 0.9f, 0.14f },
-         { 0.4f, 0.8f, 1.00f },
-         { 0.882f, 0.204f, 0.922f }
+       static v3f colour_sets[][4] =
+       {
+               { { 1.0f, 0.9f, 0.3f },                 // Yellow
+                 { 0.4f, 0.8f, 1.00f },                // Blue
+                 { 0.2f, 0.9f, 0.14f },                // Green
+                 { 0.882f, 0.204f, 0.922f }    // Pink
+               },
+               { { 1.0f, 0.9f, 0.3f },                 // Yellow
+                 { 0.4f, 0.8f, 1.00f },                // Blue
+                 { 0.85f, 0.85f, 0.85f },              // Weiss
+                 { 0.2f, 0.2f, 0.2f }                  // Black/Gray
+               },
+               { { 1.0f, 0.9f, 0.3f },                 // Yellow
+                 { 0.827f, 0.373f, 0.718f },   // Pink
+                 { 0.0f, 0.353f, 0.71f },              // Blue
+                 { 0.863f, 0.196f, 0.125f }    // Red
+               },
        };
 
        if( cc >= 'a' && cc <= 'z' )
        {
                int id = cc - 'a';
                
-               if( id < vg_list_size( colour_sets ) )
+               if( id < vg_list_size( colour_sets[0] ) )
                {
-                       v3_copy( colour_sets[ id ], target );
+                       v3_copy( colour_sets[colour_set_id][ id ], target );
                        return;
                }
        }
@@ -818,9 +903,9 @@ static int map_load( const char *str, const char *name )
                
                // Level selection area
                
-               for( int i = 0; i < vg_list_size( button_grids ); i ++ )
+               for( int i = 0; i < vg_list_size( career_packs ); i ++ )
                {
-                       struct button_grid *grid = &button_grids[ i ];
+                       struct career_level_pack *grid = &career_packs[ i ];
                        
                        for( int y = 0; y < grid->dims[1]; y ++ )
                        {
@@ -1042,9 +1127,9 @@ static void career_serialize(void)
        
        memset( encoded.reserved, 0, sizeof( encoded.reserved ) );
 
-       for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
+       for( int i = 0; i < vg_list_size( career_packs ); i ++ )
        {
-               struct serializable_set *set = &career_serializable[i];
+               struct career_level_pack *set = &career_packs[i];
                
                for( int j = 0; j < set->count; j ++ )
                {
@@ -1076,23 +1161,26 @@ static void career_pass_level( struct cmp_level *lvl, int score, int upload )
        {
                if( score < lvl->completed_score || lvl->completed_score == 0 )
                {
+                       #ifdef VG_STEAM
                        if( !lvl->is_tutorial && upload )
                                leaderboard_set_score( lvl, score );
-                       
+                       #endif
+
                        lvl->completed_score = score;
                }
                
                if( lvl->unlock ) career_unlock_level( lvl->unlock );
                
+               #ifdef VG_STEAM
                if( lvl->achievement )
                {
                        sw_set_achievement( lvl->achievement );
                }
-               
+
                // Check ALL maps to trigger master engineer
-               for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
+               for( int i = 0; i < vg_list_size( career_packs ); i ++ )
                {
-                       struct serializable_set *set = &career_serializable[i];
+                       struct career_level_pack *set = &career_packs[i];
                        
                        for( int j = 0; j < set->count; j ++ )
                        {
@@ -1102,6 +1190,7 @@ static void career_pass_level( struct cmp_level *lvl, int score, int upload )
                }
                
                sw_set_achievement( "MASTER_ENGINEER" );
+               #endif
        }
 }
 
@@ -1142,9 +1231,9 @@ static void career_load(void)
                vg_info( "No save file... Using blank one\n" );
        
        // Reset memory
-       for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
+       for( int i = 0; i < vg_list_size( career_packs ); i ++ )
        {
-               struct serializable_set *set = &career_serializable[i];
+               struct career_level_pack *set = &career_packs[i];
                
                for( int j = 0; j < set->count; j ++ )
                        career_reset_level( &set->pack[j] );
@@ -1154,9 +1243,9 @@ static void career_load(void)
        // =================================
        
        // Decode everything from dstate
-       for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
+       for( int i = 0; i < vg_list_size( career_packs ); i ++ )
        {
-               struct serializable_set *set = &career_serializable[i];
+               struct career_level_pack *set = &career_packs[i];
                
                for( int j = 0; j < set->count; j ++ )
                {
@@ -1679,8 +1768,10 @@ void vg_update(void)
                                                        if( cell_entry->config == k_cell_type_con_r || cell_entry->config == k_cell_type_con_u 
                                                                || cell_entry->config == k_cell_type_con_l || cell_entry->config == k_cell_type_con_d )
                                                        {
+                                                               #ifdef VG_STEAM
                                                                sw_set_achievement( "CAN_DO_THAT" );
-                                                       
+                                                               #endif
+
                                                                fish->state = k_fish_state_soon_alive;
                                                                
                                                                fish->dir[0] = 0;
@@ -1766,8 +1857,10 @@ void vg_update(void)
                                                        
                                                        if( collide_next_frame || collide_this_frame )
                                                        {
+                                                               #ifdef VG_STEAM
                                                                sw_set_achievement( "BANG" );
-                                                       
+                                                               #endif
+
                                                                // Shatter death (+0.5s)
                                                                float death_time = world.sim_internal_time + ( collide_this_frame? 0.0f: 0.5f );
                                                                
@@ -1905,9 +1998,11 @@ void vg_update(void)
                                }
                                else
                                {
+                                       #ifdef VG_STEAM
                                        if( world.sim_run > 0 )
                                                sw_set_achievement( "GOOD_ENOUGH" );
-                                       
+                                       #endif
+
                                        vg_error( "Level failed :(\n" );
                                }
                                
@@ -2018,9 +2113,6 @@ void vg_update(void)
        }
 }
 
-void leaderboard_found( LeaderboardFindResult_t *pCallback );
-void leaderboard_downloaded( LeaderboardScoresDownloaded_t *pCallback );
-
 static void render_tiles( v2i start, v2i end, v4f const regular_colour, v4f const selected_colour )
 {
        v2i full_start = { 0,0 };
@@ -2218,9 +2310,9 @@ static void level_selection_buttons(void)
        if( vg_get_button_down( "primary" ) )
                select_from = NULL;
        
-       for( int i = 0; i < vg_list_size( button_grids ); i ++ )
+       for( int i = 0; i < vg_list_size( career_packs ); i ++ )
        {
-               struct button_grid *grid = &button_grids[i];
+               struct career_level_pack *grid = &career_packs[i];
                
                int j = 0;
                
@@ -2230,7 +2322,7 @@ static void level_selection_buttons(void)
                        {
                                if( j < grid->count )
                                {
-                                       struct cmp_level *lvl = &grid->levels[ j ];
+                                       struct cmp_level *lvl = &grid->pack[ j ];
                                        
                                        // Determine colour
                                        if( lvl->unlocked )
@@ -2352,6 +2444,7 @@ void vg_render(void)
        glUniformMatrix3fv( SHADER_UNIFORM( shader_tile_main, "uPv" ), 1, GL_FALSE, (float *)vg_pv );
        glUniform1f( SHADER_UNIFORM( shader_tile_main, "uGhost" ), 0.0f );
        glUniform1f( SHADER_UNIFORM( shader_tile_main, "uForeground" ), 0.0f );
+       //glUniform1f( SHADER_UNIFORM( shader_tile_main, "uVisibility" ), sinf( vg_time ) + 1.0f );
        
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -2774,9 +2867,9 @@ void vg_render(void)
 
 void vg_ui(void) {}
 
+#if STEAM_LEADERBOARDS
 void leaderboard_dispatch_score(void)
 {
-#if STEAM_LEADERBOARDS
        sw_upload_leaderboard_score( 
                ui_data.upload_request.level->steam_leaderboard, 
                k_ELeaderboardUploadScoreMethodKeepBest,
@@ -2788,12 +2881,10 @@ void leaderboard_dispatch_score(void)
        ui_data.upload_request.is_waiting = 0;
        
        vg_success( "Dispatched leaderboard score\n" );
-#endif
 }
 
 void leaderboard_found( LeaderboardFindResult_t *pCallback )
 {
-#ifdef STEAM_LEADERBOARDS
        if( !pCallback->m_bLeaderboardFound )
        {
                vg_error( "Leaderboard could not be found\n" );
@@ -2823,12 +2914,10 @@ void leaderboard_found( LeaderboardFindResult_t *pCallback )
                        }
                }
        }
-#endif
 }
 
 void leaderboard_downloaded( LeaderboardScoresDownloaded_t *pCallback )
 {
-#ifdef STEAM_LEADERBOARDS
        // Update UI if this leaderboard matches what we currently have in view
        if( ui_data.level_selected->steam_leaderboard == pCallback->m_hSteamLeaderboard )
        {
@@ -2863,12 +2952,10 @@ void leaderboard_downloaded( LeaderboardScoresDownloaded_t *pCallback )
                        ui_data.leaderboard_show = 0;
        }
        else vg_warn( "Downloaded leaderboard does not match requested!\n" );
-#endif
 }
 
 void leaderboard_set_score( struct cmp_level *cmp_level, u32 score )
 {
-#ifdef STEAM_LEADERBOARDS
        if( ui_data.upload_request.is_waiting )
                vg_warn( "You are uploading leaderboard entries too quickly!\n" );
                
@@ -2881,8 +2968,8 @@ void leaderboard_set_score( struct cmp_level *cmp_level, u32 score )
                leaderboard_dispatch_score();
        else
                sw_find_leaderboard( cmp_level->map_name );
-#endif
 }
+#endif
 
 // CONSOLE COMMANDS
 // ===========================================================================================================
@@ -3032,6 +3119,13 @@ void vg_start(void)
                .function = console_credits
        });
 
+       vg_convar_push( (struct vg_convar){
+               .name = "colours",
+               .data = &colour_set_id,
+               .data_type = k_convar_dtype_i32,
+               .opt_i32 = { .min = 0, .max = 2, .clamp = 1 }
+       });
+
        // Combined quad, long quad / empty circle / filled circle mesh
        {
                float combined_mesh[6*6 + 32*6*3] = {
@@ -3157,9 +3251,9 @@ void vg_start(void)
                        size_level_texts = 6*9*7
                ;
                
-               for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
+               for( int i = 0; i < vg_list_size( career_packs ); i ++ )
                {
-                       struct serializable_set *set = &career_serializable[i];
+                       struct career_level_pack *set = &career_packs[i];
                        for( int j = 0; j < set->count; j ++ )
                        {
                                struct cmp_level *lvl = &set->pack[j];
@@ -3268,7 +3362,10 @@ void vg_start(void)
 
 void vg_free(void)
 {
+#ifdef VG_STEAM
        sw_free_opengl();
+#endif
+
        console_save_map( 0, NULL );
        career_serialize();