+ SHADER_INIT( shader_background );
+ SHADER_INIT( shader_wire );
+ SHADER_INIT( shader_buttons );
+ SHADER_INIT( shader_sprite );
+ SHADER_INIT( shader_post_darken );
+ SHADER_INIT( shader_post_comp );
+ SHADER_INIT( shader_post_blur );
+}
+
+/*
+ 0000 0 | 0001 1 | 0010 2 | 0011 3
+ | | | | |
+ X | X= | X | X=
+ | | |
+ 0100 4 | 0101 5 | 0110 6 | 0111 7
+ | | | | |
+ =X | =X= | =X | =X=
+ | | |
+ 1000 8 | 1001 9 | 1010 10 | 1011 11
+ | | | | |
+ X | X= | X | X=
+ | | | | | | |
+ 1100 12 | 1101 13 | 1110 14 | 1111 15
+ | | | | |
+ =X | =X= | =X | =X=
+ | | | | | | |
+*/
+
+struct cmp_level
+{
+ // Basic info
+ int serial_id;
+
+ const char *map_name;
+ const char *title;
+ const char *description;
+
+ const char *achievement;
+
+ int _unlock, _linked; // When completed, unlock this level
+ int is_tutorial;
+
+ // Aesthetic
+ struct world_string
+ {
+ enum placement
+ {
+ k_placement_top,
+ k_placement_bottom
+ }
+ placement;
+
+ const char *str;
+ }
+ strings[2];
+
+ // Persistent stats
+ int unlocked;
+ int completed_score;
+
+ // Runtime
+ struct world_button btn;
+ struct cmp_level *unlock, *linked;
+
+ #ifdef VG_STEAM
+ SteamLeaderboard_t steam_leaderboard;
+ #endif
+};
+
+static struct cmp_level cmp_levels_tutorials[] =
+{
+ {
+ 0, "cmp_t01", "PRINCIPLE 1", "",
+ ._unlock = 1,
+ .is_tutorial = 1
+ },
+ {
+ 1, "cmp_t02", "PRINCIPLE 2", "",
+ ._unlock = 2,
+ .is_tutorial = 1,
+ },
+ {
+ 2, "cmp_t03", "PRINCIPLE 3", "",
+ ._unlock = 12,
+ .is_tutorial = 1
+ },
+ {
+ 12, "cmp_t04", "PRINCIPLE 4", "",
+ ._unlock = 6,
+ .is_tutorial = 1,
+ .achievement = "TUTORIALS"
+ },
+ {
+ 15, "cmp_b10", "PRINCIPLE 5", "",
+ ._unlock = 16,
+ .is_tutorial = 1
+ },
+ {
+ 17, "cmp_b11", "PRINCIPLE 6", "(Right click)",
+ ._unlock = 18,
+ .is_tutorial = 1
+ },
+ {
+ 26, "cmp_p7", "PRINCIPLE 7", "Emitters",
+ ._unlock = 27,
+ ._linked = 13,
+ .is_tutorial = 1
+ }
+};
+
+static struct cmp_level cmp_levels_basic[] =
+{
+ {
+ 6, "cmp_b04", "PATCH", "",
+ ._unlock = 7,
+ ._linked = 3
+ },
+ {
+ 3, "cmp_b01", "SUBDIVISION 1", "",
+ ._linked = 4,
+ ._unlock = 5
+ },
+ {
+ 4, "cmp_b02", "SUBDIVISION 2", "",
+ ._unlock = 7
+ },
+ {
+ 5, "cmp_b03", "RESTRUCTURE", "",
+ ._unlock = 8,
+ ._linked = 31
+ },
+ {
+ 31, "cmp_121", "1-2-1", "",
+ ._unlock = 8
+ },
+ {
+ 7, "cmp_b05", "PATTERNS 1", "",
+ ._unlock = 15,
+ ._linked = 8
+ },
+ {
+ 8, "cmp_b06", "PATTERNS 2", "",
+ ._unlock = 15
+ },
+ {
+ 16, "cmp_routing", "ROUTING PROBLEM", "",
+ ._linked = 9
+ },
+ {
+ 9, "cmp_b07", "MIGHTY CONSUMER", "",
+ ._linked = 10,
+ ._unlock = 11,
+ .achievement = "MIGHTY_CONSUMER"
+ },
+ {
+ 10, "cmp_b08", "SHIFT", "",
+ ._unlock = 17
+ },
+ {
+ 11, "cmp_b09", "REVERSE", "",
+ ._unlock = 17
+ },
+ {
+ 18, "cmp_not", "NOT GATE", "",
+ ._linked = 19,
+ ._unlock = 20
+ },
+ {
+ 19, "cmp_and", "AND GATE", "",
+ ._unlock = 20
+ },
+ {
+ 20, "cmp_xor", "QUALIFICATION PROJECT", "",
+ ._unlock = 26,
+ .achievement = "GRADUATE"
+ },
+ {
+ 27, "cmp_expander", "EXPAND", "",
+ ._unlock = 28
+ },
+ {
+ 28, "cmp_pattern3", "PATTERNS 3", "",
+ ._linked = 29
+ },
+ {
+ 29, "cmp_routing2", "ROUTING PROBLEM 2", "Spaghetti!",
+ ._linked = 30,
+ ._unlock = 32
+ },
+ {
+ 30, "cmp_exact5", "EXACTLY 5", "",
+ ._unlock = 32
+ },
+ {
+ 32, "cmp_3and2", "THREE AND FOUR", "",
+ ._linked = 34
+ },
+ {
+ 34, "doublex2", "DOUBLE DOUBLE", "Delay & repeat",
+ ._linked = 35
+ },
+ {
+ 35, "oddoreven", "ODD OR EVEN", ""
+ }
+};
+
+static struct cmp_level cmp_levels_grad[] =
+{
+ {
+ 13, "cmp_i01", "SORT", "",
+ ._linked = 14
+ },
+ {
+ 14, "cmp_i02", "THIRDS", "",
+ ._linked = 21
+ },
+ {
+ 21, "cmp_grad", "SIMPLE ADDITION", "",
+ ._linked = 22,
+ ._unlock = 23
+ },
+ {
+ 22, "cmp_secret", "SECRET CODE", "",
+ ._unlock = 23
+ }
+};
+
+static struct cmp_level cmp_levels_computer[] =
+{
+ {
+ 23, "cmp_binary", "3 BIT BINARY", "Convert amount to binary",
+ ._unlock = 24,
+ .strings =
+ {
+ {
+ .placement = k_placement_bottom,
+ .str =
+"\t\t\t\t\t\t\t\t\t\t\x83 \x84\n"
+"\t\t\t\t\t\t\t\t\t\t\x83 \x84 Binary\n"
+"\t\t\t\t\t\t\t\t\t\t\x83 4 2 1 \x84"
+ },
+ {
+ .placement = k_placement_top,
+ .str =
+"\n"
+"\t\t\t\t\t\t\t\t\t\t\t Count"
+ }
+ }
+ },
+ {
+ 24, "cmp_add3b", "3 BIT ADDER", "Binary addition",
+ ._unlock = 25,
+ .strings =
+ {
+ {
+ .placement = k_placement_top,
+ //.str ="\t\t\t\t\t\t\t\t\t| NUMBER A | | NUMBER B |\n"
+ .str =""
+"\t\t\t\t\t\t\t\t\t\x8A 4 2 1 \x8B \x8A 4 2 1 \x8B\n"
+"\t\t\t\t\t\t\t\t\t\x83 \x84 add \x83 \x84\n"
+"\t\t\t\t\t\t\t\t\t\x83 \x84 \x83 \x84"
+ },
+ {
+ .placement = k_placement_bottom,
+ .str =
+"\t\t\t\x83 \x84\n"
+"\t\t\t\x83 \x84 result a+b\n"
+"\t\t\t\x83 8 4 2 1 \x84"
+ }
+ }
+ },
+ {
+ 25, "cmp_plot3x3", "3x3 PLOT", "2 bit x/y",
+ ._unlock = 33,
+ .strings =
+ {
+ {
+ .placement = k_placement_top,
+ .str=
+"\t\t\t\t\t\t\t\t\x8A 2 1 \x8B \x8A 2 1 \x8B\n"
+"\t\t\t\t\t\t\t\t\x83 \x84 X Y \x83 \x84\n"
+"\t\t\t\t\t\t\t\t\x83 \x84 \x83 \x84"
+ }
+ }
+ },
+ {
+ 33, "compactxor", "Compact XOR", "",
+ .strings =
+ {
+ {
+ .placement = k_placement_top,
+ .str=
+"\t\t\t\t\x8A \x8B \x8A \x8B\n"
+"\t\t\t\t\x83 \x84""A B\x83 \x84\n"
+"\t\t\t\t\x83 \x84 \x83 \x84"
+ },
+ {
+ .placement = k_placement_bottom,
+ .str =
+"\t\t\t\x83 \x84\n"
+"\t\t\t\x83 \x84 result a xor b\n"
+"\t\t\t\x83 \x84"
+ }
+ }
+ }
+};
+
+#define NUM_CAMPAIGN_LEVELS (vg_list_size( cmp_levels_tutorials ) + vg_list_size( cmp_levels_basic ) + vg_list_size( cmp_levels_grad ) + vg_list_size( cmp_levels_computer ) )
+
+static struct career_level_pack
+{
+ struct cmp_level *pack;
+ const char *title;
+ int count;
+
+ v3f primary_colour;
+ v2i origin;
+ v2i dims;
+}
+career_packs[] =
+{
+ {
+ .pack = cmp_levels_tutorials,
+ .title = "",
+ .count = vg_list_size( cmp_levels_tutorials ),
+ .primary_colour = { 0.204f, 0.345f, 0.553f },
+ .origin = { -4, -2 },
+ .dims = { 1, 7 }
+ },
+ {
+ .pack = cmp_levels_basic,
+ .title = "\x8C\x8D"" Core",
+ .count = vg_list_size( cmp_levels_basic ),
+ .primary_colour = { 0.304f, 0.245f, 0.553f },
+ .origin = { -3, -2 },
+ .dims = { 3, 7 }
+ },
+ {
+ .pack = cmp_levels_grad,
+ .title = "\x8C\x8E"" Challenge",
+ .count = vg_list_size( cmp_levels_grad ),
+ .primary_colour = { 0.75f, 0.23f, 0.39f },
+ .origin = { -4, 5 },
+ .dims = { 4, 1 }
+ },
+ {
+ .pack = cmp_levels_computer,
+ .title = "\x8C\x8F"" 3 Bit computer\n\n (preview)",
+ .count = vg_list_size( cmp_levels_computer ),
+ .primary_colour = { 0.75f, 0.14f, 0.1f },
+ .origin = { -4, 6 },
+ .dims = { 4, 1 }
+ }
+};
+
+// Setup pointers and that
+static void career_local_data_init(void)
+{
+ struct cmp_level *level_ptrs[ NUM_CAMPAIGN_LEVELS ];
+ for( int i = 0; i < NUM_CAMPAIGN_LEVELS; i ++ )
+ level_ptrs[i] = NULL;
+
+ // COllect pointers
+ for( int i = 0; i < vg_list_size( career_packs ); i ++ )
+ {
+ struct career_level_pack *set = &career_packs[i];
+
+ for( int j = 0; j < set->count; j ++ )
+ {
+ int id = set->pack[j].serial_id;
+
+ if( level_ptrs[ id ] )
+ vg_error( "Serial id %u already used!\n", id );
+ else
+ level_ptrs[ set->pack[j].serial_id ] = &set->pack[j];
+ }
+ }
+
+ // Apply
+ for( int i = 0; i < vg_list_size( career_packs ); i ++ )
+ {
+ struct career_level_pack *set = &career_packs[i];
+
+ for( int j = 0; j < set->count; j ++ )
+ {
+ struct cmp_level *lvl = &set->pack[j];
+
+ if( lvl->_unlock >= NUM_CAMPAIGN_LEVELS ||
+ lvl->_linked >= NUM_CAMPAIGN_LEVELS )
+ {
+ vg_error( "_unlock / _linked out of range (%d, %d)\n",
+ lvl->_unlock, lvl->_linked );
+ }
+ else
+ {
+ lvl->unlock = lvl->_unlock? level_ptrs[ lvl->_unlock ]: NULL;
+ lvl->linked = lvl->_linked? level_ptrs[ lvl->_linked ]: NULL;
+ }
+ }
+ }