small animation to ball dying
[fishladder.git] / fishladder_resources.h
1 // TEXTURES
2 // ===========================================================================================================
3
4 vg_tex2d tex_tile_data = { .path = "textures/tileset.qoi" };
5 vg_tex2d tex_tile_detail = { .path = "textures/tile_overlays.qoi" };
6 vg_tex2d tex_wood = { .path = "textures/wood.qoi" };
7 vg_tex2d tex_background = { .path = "textures/background.qoi" };
8 vg_tex2d tex_ball_noise = { .path = "textures/bnoise.qoi" };
9 vg_tex2d tex_monofur = { .path = "textures/ascii.qoi", .flags = VG_TEXTURE_NO_MIP };
10 vg_tex2d tex_unkown = { .path = "textures/unkown.qoi" };
11 vg_tex2d tex_buttons = { .path = "textures/buttons.qoi" };
12
13 vg_tex2d *texture_list[] = { &tex_tile_detail, &tex_tile_data, &tex_wood, &tex_background, &tex_ball_noise, &tex_monofur, &tex_unkown, &tex_buttons };
14
15 // AUDIO
16 // ===========================================================================================================
17
18 sfx_vol_control audio_volume_sfx = { .val = 1.0f, .name = "Sound effects" };
19 sfx_vol_control audio_volume_music = { .val = 1.0f, .name = "Music" };
20
21 sfx_system audio_system_sfx =
22 {
23 .vol = 1.f,
24 .ch = 1,
25 .vol_src = &audio_volume_sfx,
26 .name = "sfx"
27 };
28
29 sfx_set audio_tile_mod =
30 {
31 .sources = "\
32 sound/mod_01.ogg\0\
33 sound/mod_02.ogg\0\
34 sound/mod_03.ogg\0\
35 sound/mod_04.ogg\0\
36 sound/mod_05.ogg\0\
37 sound/mod_06.ogg\0",
38 .flags = 0
39 };
40
41 sfx_set audio_splitter =
42 {
43 .sources = "\
44 sound/splitter_01.ogg\0"
45 };
46
47 sfx_set audio_rolls =
48 {
49 .sources = "\
50 sound/rolling_01.ogg\0\
51 sound/rolling_02.ogg\0"
52 };
53
54 sfx_set audio_random =
55 {
56 .sources = "\
57 sound/random_01.ogg\0\
58 sound/random_02.ogg\0\
59 sound/random_03.ogg\0\
60 sound/random_04.ogg\0\
61 sound/random_05.ogg\0\
62 sound/random_06.ogg\0\
63 sound/random_07.ogg\0\
64 sound/random_08.ogg\0"
65 };
66
67 // One two or three layers of rolling noise
68 sfx_system audio_system_balls_rolling =
69 {
70 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
71 .name = "Balls Rolling", .flags = SFX_FLAG_REPEAT
72 };
73
74 // Various oneshots
75 sfx_system audio_system_balls_switching =
76 {
77 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
78 .name = "Balls Switching"
79 };
80
81 // Gameplay critical sounds eg. splitter sound rocking
82 sfx_system audio_system_balls_important =
83 {
84 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
85 .name = "Balls Gameplay"
86 };
87
88 // Suplemental sounds
89 sfx_system audio_system_balls_extra =
90 {
91 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
92 .name = "Balls Extra"
93 };
94
95 ui_colourset ui_fl_colours = {
96 .main = 0xff807373,
97 .hover = 0xff918484,
98 .active = 0xffad9f9e
99 };
100
101 ui_colourset ui_fl_colours_inactive = {
102 .main = 0xff655958,
103 .hover = 0xff655958,
104 .active = 0xff655958
105 };
106
107 static void resource_load_main(void)
108 {
109 // Textures
110 vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
111
112 ui_override_font( tex_monofur.name, 7 );
113
114 ui_global_ctx.colours_main = &ui_fl_colours;
115 gui_reset_colours();
116
117 // Audio
118 sfx_set_init( &audio_tile_mod, NULL );
119 sfx_set_init( &audio_splitter, NULL );
120 sfx_set_init( &audio_rolls, NULL );
121 sfx_set_init( &audio_random, NULL );
122 }
123
124 static void resource_free_main(void)
125 {
126 vg_tex2d_free( texture_list, vg_list_size( texture_list ) );
127
128 sfx_set_free( &audio_tile_mod );
129 sfx_set_free( &audio_splitter );
130 sfx_set_free( &audio_rolls );
131 sfx_set_free( &audio_random );
132 }
133
134 // SHADERS
135 // ===========================================================================================================
136
137 SHADER_DEFINE( shader_tile_colour,
138
139 // VERTEX
140 "layout (location=0) in vec2 a_co;"
141 "uniform mat3 uPv;"
142 "uniform vec3 uOffset;"
143 ""
144 "void main()"
145 "{"
146 "gl_Position = vec4( uPv * vec3( a_co * uOffset.z + uOffset.xy, 1.0 ), 1.0 );"
147 "}",
148
149 // FRAGMENT
150 "out vec4 FragColor;"
151 "uniform vec4 uColour;"
152 ""
153 "void main()"
154 "{"
155 "FragColor = uColour;"
156 "}"
157 ,
158 UNIFORMS({ "uPv", "uOffset", "uColour" })
159 )
160
161 SHADER_DEFINE( shader_ball,
162 // VERTEX
163 "layout (location=0) in vec2 a_co;"
164 "uniform vec3 uOffset;"
165 "uniform mat3 uPv;"
166 ""
167 "out vec4 aTexCoords;"
168 ""
169 "void main()"
170 "{"
171 // Vertex transform
172 "vec3 worldpos = vec3( (a_co * 0.5 - 0.25) * uOffset.z + uOffset.xy, 1.0 );"
173 "gl_Position = vec4( uPv * worldpos, 1.0 );"
174
175 // Create texture coords
176 "aTexCoords = vec4( a_co, worldpos.xy );"
177 "}",
178
179 // FRAGMENT
180 "out vec4 FragColor;"
181 ""
182 "uniform sampler2D uTexMain;"
183 "uniform vec3 uColour;"
184 "uniform vec2 uTexOffset;"
185 ""
186 "in vec4 aTexCoords;"
187 ""
188 "void main()"
189 "{"
190 "vec2 center_coords = aTexCoords.xy - 0.5;"
191 "vec2 center_coords_sqr = center_coords*center_coords;"
192 "float circle_factor = smoothstep( 0.07, 0.0625, center_coords_sqr.x+center_coords_sqr.y );"
193
194 "float bulge_amt = center_coords_sqr.x+center_coords_sqr.y;"
195 "vec2 warped_coords = aTexCoords.zw+uTexOffset - center_coords;"
196 "vec4 noise_sample = texture( uTexMain, warped_coords );"
197
198 "float rim_light = (center_coords_sqr.x+center_coords_sqr.y)*15.0;"
199
200 "vec2 shadow_coords = center_coords + vec2(0.02,0.07);"
201 "vec2 shadow_coords_sqr = shadow_coords*shadow_coords;"
202 "float shadow = exp(-((shadow_coords_sqr.x+shadow_coords_sqr.y)-0.0125)*15.0);"
203
204 "vec3 marble_comp = uColour*0.9 + (noise_sample.x*0.7+pow(rim_light,3.0)*2.0) * 0.1;"
205 "vec4 colour_comp = mix( vec4(0.74,0.53,0.34,shadow), vec4(marble_comp,1.0), circle_factor );"
206
207 "FragColor = colour_comp;"
208 "}"
209 ,
210 UNIFORMS({ "uTexMain", "uColour", "uOffset", "uPv", "uTexOffset" })
211 )
212
213 SHADER_DEFINE( shader_tile_main,
214 // VERTEX
215 "layout (location=0) in vec2 a_co;"
216 "uniform vec4 uOffset;" // Tile x/y, uv x/y
217 "uniform mat3 uPv;"
218 "uniform mat2 uSubTransform;"
219 ""
220 "out vec4 aTexCoords;"
221 "out vec2 aWorldCoords;"
222 ""
223 "vec2 hash22(vec2 p)"
224 "{"
225 "vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));"
226 "p3 += dot(p3, p3.yzx+33.33);"
227 "return fract((p3.xx+p3.yz)*p3.zy);"
228 "}"
229 ""
230 "void main()"
231 "{"
232 // Vertex transform
233 "vec2 subtransform = uSubTransform * (a_co-0.5) + 0.5;"
234 "vec3 worldpos = vec3( subtransform + uOffset.xy, 1.0 );"
235 "gl_Position = vec4( uPv * worldpos, 1.0 );"
236
237 // Create texture coords
238 "vec2 random_offset = floor(hash22(uOffset.xy) * 4.0) * 0.25;"
239 "vec2 edge_safe_coords = a_co * 0.98 + 0.01;"
240 "aTexCoords = vec4((edge_safe_coords + uOffset.zw) * 0.25, edge_safe_coords * 0.25 + random_offset );"
241 "aWorldCoords = worldpos.xy;"
242 "}",
243
244 // FRAGMENT
245 "out vec4 FragColor;"
246 ""
247 "uniform sampler2D uTexGlyphs;"
248 "uniform sampler2D uTexWood;"
249 "uniform float uGhost;"
250 "uniform float uForeground;"
251 "uniform vec2 uMousePos;"
252 "uniform vec4 uColour;"
253 ""
254 "in vec4 aTexCoords;"
255 "in vec2 aWorldCoords;"
256 ""
257 "void main()"
258 "{"
259 "vec3 shadowing_colour = vec3( 0.93, 0.88536, 0.8184 ) * 0.97;"
260 "vec4 glyph = texture( uTexGlyphs, aTexCoords.xy );"
261 "vec4 wood = texture( uTexWood, aTexCoords.zw );"
262 "vec4 wood_secondary = texture( uTexWood, aTexCoords.zw + 0.25 );"
263 "vec3 wood_comp = mix( wood_secondary.rgb * shadowing_colour, wood.rgb, clamp( glyph.b * 2.0 - 1.0, 0.0, 1.0 ) );"
264
265 "vec3 shadows = mix( vec3( 0.85, 0.7344, 0.561 ), vec3(1.0,1.0,1.0), glyph.r );"
266
267 "vec4 output_regular = vec4( wood_comp * shadows, mix( glyph.a, glyph.b, uForeground ) );"
268
269 "float ghost_dist = clamp( 1.5 - distance(uMousePos, aWorldCoords), 0.0, 1.0 );"
270 "vec4 output_ghost = vec4( 1.0, 1.0, 1.0, glyph.g * ghost_dist );"
271
272 "FragColor = mix( output_regular, output_ghost, uGhost ) * uColour;"
273 "}"
274 ,
275 UNIFORMS({ "uPv", "uOffset", "uTexGlyphs", "uTexWood", "uSubTransform", "uGhost", "uMousePos", "uColour", "uForeground" })
276 )
277
278 SHADER_DEFINE( shader_background,
279 // VERTEX
280 "layout (location=0) in vec2 a_co;"
281 "uniform mat3 uPv;"
282 "uniform vec3 uOffset;"
283 ""
284 "out vec2 aTexCoords;"
285 ""
286 "void main()"
287 "{"
288 "vec2 world_pos = a_co * uOffset.z + uOffset.xy;"
289 "gl_Position = vec4( uPv * vec3( world_pos, 1.0 ), 1.0 );"
290 "aTexCoords = a_co;"
291 "}",
292
293 // FRAGMENT
294 "out vec4 FragColor;"
295 ""
296 "uniform sampler2D uTexMain;"
297 "uniform sampler2D uSamplerNoise;"
298 "uniform float uVariance;"
299 ""
300 "in vec2 aTexCoords;"
301 ""
302 "void main()"
303 "{"
304 "float ao_accum = 0.0;"
305 "for( int i=0; i<10; ++i )"
306 "{"
307 "vec2 random_noise = (texture( uSamplerNoise, aTexCoords * 20.0 + float(i) * 0.2 ).xy - vec2( 0.5, 0.5 )) * uVariance;"
308 "vec4 background = texture( uTexMain, aTexCoords + random_noise );"
309 "ao_accum += background.r * clamp((1.0 - length( random_noise )), 0.0, 1.0);"
310 "}"
311 "ao_accum *= 0.15;"
312
313 "vec4 data_this_tile = texture( uTexMain, aTexCoords );"
314
315 "ao_accum -= data_this_tile.r;"
316
317 "vec3 colour_main = mix( vec3( 0.369768, 0.3654, 0.42 ),vec3( 0.275, 0.388, 0.553 ), data_this_tile.g );"
318
319 "vec2 square_coords = fract( aTexCoords * 64.0 );"
320 "vec2 grid_coords = abs( square_coords - 0.5 );"
321 "float edge_contrast = (1.0-ao_accum*0.2);"
322
323 "float gridline = step( 0.49, max(grid_coords.x,grid_coords.y) );"
324 "float gridline_fadeout = min(max(edge_contrast-1.0, 0.0)*40.0 + data_this_tile.g,10.0);"
325
326 "FragColor = vec4( colour_main * edge_contrast + gridline * 0.02 * gridline_fadeout, 1.0 );"
327 "}"
328 ,
329 UNIFORMS({ "uPv", "uOffset", "uTexMain", "uVariance", "uSamplerNoise" })
330 )
331
332 SHADER_DEFINE( shader_wire,
333 // VERTEX
334 "layout (location=0) in vec2 a_co;"
335 "uniform vec3 uStart;"
336 "uniform vec3 uEnd;"
337 "uniform mat3 uPv;"
338 "uniform float uCurve;"
339 ""
340 "out vec2 aTexCoords;"
341 ""
342 "vec3 sample_curve_time( float t )"
343 "{"
344 "vec3 line_coord = mix( uStart, uEnd, t );"
345
346 "float curve_amt = 1.0-(pow((t*2.0-1.0),2.0));"
347 "return vec3( line_coord.x, line_coord.y - curve_amt*uCurve, line_coord.z );"
348 "}"
349 ""
350 "void main()"
351 "{"
352 // Vertex transform
353 "vec3 p0 = sample_curve_time( a_co.x );"
354 "vec3 p1 = sample_curve_time( a_co.x + 0.025 );"
355
356 "vec2 line_tangent = normalize(p1.xy-p0.xy);"
357 "vec2 line_normal = vec2( -line_tangent.y, line_tangent.x );"
358
359 "vec2 worldfinal = p0.xy + line_normal*a_co.y*p0.z;"
360
361 "gl_Position = vec4( uPv * vec3(worldfinal, 1.0), 1.0 );"
362
363 // Create texture coords (todo: include stretch adjusted coords?)
364 "aTexCoords = vec2( a_co.x, a_co.y + 0.5 );"
365 "}",
366
367 // FRAGMENT
368 "out vec4 FragColor;"
369 ""
370 "uniform sampler2D uTexMain;"
371 "uniform vec4 uColour;"
372 ""
373 "in vec2 aTexCoords;"
374 ""
375 "void main()"
376 "{"
377 "FragColor = uColour;"
378 "}"
379 ,
380 UNIFORMS({ "uPv", "uColour", "uTexMain", "uStart", "uEnd", "uCurve" })
381 )
382
383 SHADER_DEFINE( shader_buttons,
384 // VERTEX
385 "layout (location=0) in vec2 a_co;"
386 "uniform vec4 uOffset;" // Tile x/y, uv x/y
387 "uniform mat3 uPv;"
388 ""
389 "out vec2 aTexCoords;"
390 ""
391 "void main()"
392 "{"
393 // Vertex transform
394 "vec3 worldpos = vec3( a_co + uOffset.xy, 1.0 );"
395 "gl_Position = vec4( uPv * worldpos, 1.0 );"
396
397 // Create texture coords
398 "vec2 edge_safe_coords = a_co * 0.98 + 0.01;"
399 "aTexCoords = (edge_safe_coords + uOffset.zw) * 0.25;"
400 "}",
401
402 // FRAGMENT
403 "out vec4 FragColor;"
404 ""
405 "uniform sampler2D uTexMain;"
406 "uniform vec4 uColour;" // rgb, light amount
407 ""
408 "in vec2 aTexCoords;"
409 ""
410 "void main()"
411 "{"
412 "vec4 glyph = texture( uTexMain, aTexCoords.xy );"
413
414 "FragColor = vec4( uColour.rgb * (mix(glyph.r, glyph.g, uColour.a)+0.02)*2.6 + glyph.b * 0.4, glyph.a );"
415 "}"
416 ,
417 UNIFORMS({ "uPv", "uOffset", "uTexMain", "uColour" })
418 )
419
420
421 void vg_register(void)
422 {
423 SHADER_INIT( shader_tile_colour );
424 SHADER_INIT( shader_tile_main );
425 SHADER_INIT( shader_ball );
426 SHADER_INIT( shader_background );
427 SHADER_INIT( shader_wire );
428 SHADER_INIT( shader_buttons );
429 }
430
431 /*
432 0000 0 | 0001 1 | 0010 2 | 0011 3
433 | | | | |
434 X | X= | X | X=
435 | | |
436 0100 4 | 0101 5 | 0110 6 | 0111 7
437 | | | | |
438 =X | =X= | =X | =X=
439 | | |
440 1000 8 | 1001 9 | 1010 10 | 1011 11
441 | | | | |
442 X | X= | X | X=
443 | | | | | | |
444 1100 12 | 1101 13 | 1110 14 | 1111 15
445 | | | | |
446 =X | =X= | =X | =X=
447 | | | | | | |
448 */
449
450 float const MESH_NUMBER_0[] = {
451 #include "fonts/numbers/n0.h"
452 };
453
454 float const MESH_NUMBER_1[] = {
455 #include "fonts/numbers/n1.h"
456 };
457
458 float const MESH_NUMBER_2[] = {
459 #include "fonts/numbers/n2.h"
460 };
461
462 float const MESH_NUMBER_3[] = {
463 #include "fonts/numbers/n3.h"
464 };
465
466 float const MESH_NUMBER_4[] = {
467 #include "fonts/numbers/n4.h"
468 };
469
470 float const MESH_NUMBER_5[] = {
471 #include "fonts/numbers/n5.h"
472 };
473
474 float const MESH_NUMBER_6[] = {
475 #include "fonts/numbers/n6.h"
476 };
477
478 float const MESH_NUMBER_7[] = {
479 #include "fonts/numbers/n7.h"
480 };
481
482 float const MESH_NUMBER_8[] = {
483 #include "fonts/numbers/n8.h"
484 };
485
486 float const MESH_NUMBER_9[] = {
487 #include "fonts/numbers/n9.h"
488 };
489
490 float const MESH_NUMBERS_BUFFER[] =
491 {
492 #include "fonts/numbers/n0.h"
493 #include "fonts/numbers/n1.h"
494 #include "fonts/numbers/n2.h"
495 #include "fonts/numbers/n3.h"
496 #include "fonts/numbers/n4.h"
497 #include "fonts/numbers/n5.h"
498 #include "fonts/numbers/n6.h"
499 #include "fonts/numbers/n7.h"
500 #include "fonts/numbers/n8.h"
501 #include "fonts/numbers/n9.h"
502 };
503
504 #define MESH_NUMBER_DIVISOR 6
505
506 u32 const MESH_NUMBERS_OFFSETS[][2] =
507 {
508 {
509 0,
510 vg_list_size( MESH_NUMBER_0 ) / MESH_NUMBER_DIVISOR
511 },
512 {
513 vg_list_size( MESH_NUMBER_0 ) / MESH_NUMBER_DIVISOR,
514 vg_list_size( MESH_NUMBER_1 ) / MESH_NUMBER_DIVISOR
515 },
516 {
517 (
518 vg_list_size( MESH_NUMBER_0 ) +
519 vg_list_size( MESH_NUMBER_1 )
520 ) / MESH_NUMBER_DIVISOR,
521 vg_list_size( MESH_NUMBER_2 ) / MESH_NUMBER_DIVISOR
522 },
523 {
524 (
525 vg_list_size( MESH_NUMBER_0 ) +
526 vg_list_size( MESH_NUMBER_1 ) +
527 vg_list_size( MESH_NUMBER_2 )
528 ) / MESH_NUMBER_DIVISOR,
529 vg_list_size( MESH_NUMBER_3 ) / MESH_NUMBER_DIVISOR
530 },
531 {
532 (
533 vg_list_size( MESH_NUMBER_0 ) +
534 vg_list_size( MESH_NUMBER_1 ) +
535 vg_list_size( MESH_NUMBER_2 ) +
536 vg_list_size( MESH_NUMBER_3 )
537 ) / MESH_NUMBER_DIVISOR,
538 vg_list_size( MESH_NUMBER_4 ) / MESH_NUMBER_DIVISOR
539 },
540 {
541 (
542 vg_list_size( MESH_NUMBER_0 ) +
543 vg_list_size( MESH_NUMBER_1 ) +
544 vg_list_size( MESH_NUMBER_2 ) +
545 vg_list_size( MESH_NUMBER_3 ) +
546 vg_list_size( MESH_NUMBER_4 )
547 ) / MESH_NUMBER_DIVISOR,
548 vg_list_size( MESH_NUMBER_5 ) / MESH_NUMBER_DIVISOR
549 },
550 {
551 (
552 vg_list_size( MESH_NUMBER_0 ) +
553 vg_list_size( MESH_NUMBER_1 ) +
554 vg_list_size( MESH_NUMBER_2 ) +
555 vg_list_size( MESH_NUMBER_3 ) +
556 vg_list_size( MESH_NUMBER_4 ) +
557 vg_list_size( MESH_NUMBER_5 )
558 ) / MESH_NUMBER_DIVISOR,
559 vg_list_size( MESH_NUMBER_6 ) / MESH_NUMBER_DIVISOR
560 },
561 {
562 (
563 vg_list_size( MESH_NUMBER_0 ) +
564 vg_list_size( MESH_NUMBER_1 ) +
565 vg_list_size( MESH_NUMBER_2 ) +
566 vg_list_size( MESH_NUMBER_3 ) +
567 vg_list_size( MESH_NUMBER_4 ) +
568 vg_list_size( MESH_NUMBER_5 ) +
569 vg_list_size( MESH_NUMBER_6 )
570 ) / MESH_NUMBER_DIVISOR,
571 vg_list_size( MESH_NUMBER_7 ) / MESH_NUMBER_DIVISOR
572 },
573 {
574 (
575 vg_list_size( MESH_NUMBER_0 ) +
576 vg_list_size( MESH_NUMBER_1 ) +
577 vg_list_size( MESH_NUMBER_2 ) +
578 vg_list_size( MESH_NUMBER_3 ) +
579 vg_list_size( MESH_NUMBER_4 ) +
580 vg_list_size( MESH_NUMBER_5 ) +
581 vg_list_size( MESH_NUMBER_6 ) +
582 vg_list_size( MESH_NUMBER_7 )
583 ) / MESH_NUMBER_DIVISOR,
584 vg_list_size( MESH_NUMBER_8 ) / MESH_NUMBER_DIVISOR
585 },
586 {
587 (
588 vg_list_size( MESH_NUMBER_0 ) +
589 vg_list_size( MESH_NUMBER_1 ) +
590 vg_list_size( MESH_NUMBER_2 ) +
591 vg_list_size( MESH_NUMBER_3 ) +
592 vg_list_size( MESH_NUMBER_4 ) +
593 vg_list_size( MESH_NUMBER_5 ) +
594 vg_list_size( MESH_NUMBER_6 ) +
595 vg_list_size( MESH_NUMBER_7 ) +
596 vg_list_size( MESH_NUMBER_8 )
597 ) / MESH_NUMBER_DIVISOR,
598 vg_list_size( MESH_NUMBER_9 ) / MESH_NUMBER_DIVISOR
599 }
600 };
601
602 struct cmp_level
603 {
604 const char *map_name;
605 const char *title;
606 const char *description;
607
608 int unlocked;
609 int completed_score;
610
611 int _unlock, _linked; // When completed, unlock this level
612 struct cmp_level *unlock, *linked;
613
614 int serial_id;
615 int is_tutorial;
616
617 SteamLeaderboard_t steam_leaderboard;
618 };
619
620 static struct cmp_level cmp_levels_tutorials[] =
621 {
622 // r1
623 {
624 .serial_id = 0,
625 .title = "PRINCIPLE 1",
626 .map_name = "cmp_t01",
627 .description = "Utilize basic transport methods",
628
629 ._unlock = 1,
630 .is_tutorial = 1
631 },
632 // r1
633 {
634 .serial_id = 1,
635 .title = "PRINCIPLE 2",
636 .map_name = "cmp_t02",
637 .description = "Utilize the twisty turny(TM) piece to split\n"
638 "the marble stream into two",
639
640 ._unlock = 2,
641 .is_tutorial = 1,
642 },
643 // r1
644 {
645 .serial_id = 2,
646 .title = "PRINCIPLE 3",
647 .map_name = "cmp_t03",
648 .description = "Merge transport into one",
649
650 ._unlock = 12,
651 .is_tutorial = 1
652 },
653 // r1
654 {
655 .serial_id = 12,
656 .title = "PRINCIPLE 4",
657 .map_name = "cmp_t04",
658 .description = "Some stages require multiple runs to succeed\n"
659 "in order to pass",
660
661 ._unlock = 3,
662 .is_tutorial = 1
663 }
664 };
665
666 static struct cmp_level cmp_levels_basic[] =
667 {
668 // r1
669 {
670 .serial_id = 3,
671 .title = "SUBDIVISION 1",
672 .map_name = "cmp_b01",
673 .description = "Sometimes getting the desired amount takes\n"
674 "dividing up the input and recombining it.",
675
676 ._linked = 4,
677 ._unlock = 6
678 },
679 // r1
680 {
681 .serial_id = 4,
682 .title = "SUBDIVISION 2",
683 .map_name = "cmp_b02",
684 .description = "",
685
686 ._linked = 5,
687 ._unlock = 7
688 },
689 // r1
690 {
691 .serial_id = 5,
692 .title = "RESTRUCTURE",
693 .map_name = "cmp_b03",
694 .description = "It is possible to swap these values using\n"
695 "simple division and addition.",
696
697 ._unlock = 8
698 },
699 {
700 .serial_id = 6,
701 .title = "SERIALIZE",
702 .map_name = "cmp_b04",
703 .description = "Merge and sort",
704
705 ._unlock = 7
706 },
707 {
708 .serial_id = 7,
709 .title = "PATTERNS 1",
710 .map_name = "cmp_b05",
711 .description = "Replicate",
712
713 ._linked = 8
714 },
715 {
716 .serial_id = 8,
717 .title = "PATTERNS 2",
718 .map_name = "cmp_b06",
719 .description = "Replicate MORE",
720
721 ._unlock = 9
722 },
723 {
724 .serial_id = 9,
725 .title = "MIGHTY CONSUMER",
726 .map_name = "cmp_b07",
727 .description = "Build a greedy system",
728
729 ._linked = 10,
730 ._unlock = 11
731 },
732 {
733 .serial_id = 10,
734 .title = "ENCRYPTED 1",
735 .map_name = "cmp_b08",
736 .description = "Some configurations may not be valid",
737
738 ._unlock = 15
739 },
740 {
741 .serial_id = 11,
742 .title = "REVERSE",
743 .map_name = "cmp_b09",
744 .description = "Reverse the incoming order. Always length 4",
745
746 ._unlock = 15
747 },
748 // r2
749 {
750 .serial_id = 15,
751 .title = "PRINCIPLE 5",
752 .map_name = "cmp_b10",
753 .description =
754 "The eager engineers among you may have already spotted\n"
755 "and utilized these parts of the system\n"
756 "\n"
757 "We forgot to include the relevant principle tasks as\n"
758 "of your training package, you will now be tasked to\n"
759 "complete them",
760
761 ._unlock = 16,
762 .is_tutorial = 1
763 },
764 // r2
765 {
766 .serial_id = 16,
767 .title = "ROUTING PROBLEM",
768 .map_name = "cmp_routing",
769 .description =
770 "Things can get a little chaotic on tight boards, do your\n"
771 "best to utilize principle 5 to get the job done\n",
772
773 ._unlock = 17
774 },
775 {
776 .serial_id = 17,
777 .title = "PRINCIPLE 6",
778 .map_name = "cmp_b11",
779 .description =
780 "While hovering over a simple tile peice, right click and\n"
781 "drag to start creating a wire. These can be connected to\n"
782 "the left, or right recieving pins of a Twisty Turny(TM).\n"
783 "\n"
784 "Once connected, the Twisty Turny(TM) will no longer\n"
785 "'flip flop' as marbles run through them, but instead be\n"
786 "et to left or right rotating only. As indicated by the\n"
787 "status arrow beneath them\n"
788 "\n"
789 "When the left or right slot is triggered, the Twisty\n"
790 "Turny(TM) will switch modes according to that input.\n"
791 "\n"
792 "Trigger wires apply instantaneously, however if both the\n"
793 "left and right inputs are recieved at the same time,\n"
794 "this results in no operation being performed, and no\n"
795 "state changes take place in the Twisty Turny(TM)\n",
796
797 ._unlock = 18,
798 .is_tutorial = 1
799 },
800 {
801 .serial_id = 18,
802 .title = "NOT GATE",
803 .map_name = "cmp_not",
804 .description =
805 "Test your knowledge of triggers, build an 'NOT GATE'\n"
806 "emulated by marble logic.",
807
808 ._linked = 19,
809 ._unlock = 20
810 },
811 {
812 .serial_id = 19,
813 .title = "AND GATE",
814 .map_name = "cmp_and",
815 .description =
816 "A slightly more complicated gate, but shouldn't be\n"
817 "too difficult for your skillset.",
818
819 ._unlock = 20
820 },
821 {
822 .serial_id = 20,
823 .title = "QUALIFICATION PROJECT",
824 .map_name = "cmp_grad",
825 .description =
826 "There's no instructions here, resolve and complete this\n"
827 "task to qualify yourself as an official marble engineer",
828 ._unlock = 13
829 }
830 };
831
832 static struct cmp_level cmp_levels_grad[] =
833 {
834 {
835 .serial_id = 13,
836 .title = "SORT",
837 .map_name = "cmp_i01",
838 .description =
839 "Device a scheme to filter and sort the inputs. If you\n"
840 "believe you lack the tools required to solve this one,\n"
841 "take a harder look at the inputs.",
842 ._linked = 14
843
844 },
845 {
846 .serial_id = 14,
847 .title = "THIRDS",
848 .map_name = "cmp_i02",
849 .description =
850 "Split the inputs up into a third of their values\n"
851 "\n"
852 "Is this possible? -HG",
853 ._linked = 21
854
855 },
856 {
857 .serial_id = 21,
858 .title = "XOR CHIP",
859 .map_name = "cmp_xor",
860 .description =
861 "Significantly more complicated than an AND or NOT gate,\n"
862 "but possible.",
863 ._linked = 22
864 },
865 {
866 .serial_id = 22,
867 .title = "SECRET CODE",
868 .map_name = "cmp_secret",
869 .description =
870 "Only one input should send an unlock signal marble to\n"
871 "the output.\n"
872 "The code: 100110"
873 }
874 };
875
876 #define NUM_CAMPAIGN_LEVELS (vg_list_size( cmp_levels_tutorials ) + vg_list_size( cmp_levels_basic ) + vg_list_size( cmp_levels_grad ))
877
878 /*
879 static struct
880 {
881 }
882 career_local =
883 {
884 };*/
885
886 static struct serializable_set
887 {
888 struct cmp_level *pack;
889 int count;
890 }
891 career_serializable[] =
892 {
893 {
894 .pack = cmp_levels_tutorials,
895 .count = vg_list_size( cmp_levels_tutorials )
896 },
897 {
898 .pack = cmp_levels_basic,
899 .count = vg_list_size( cmp_levels_basic )
900 },
901 {
902 .pack = cmp_levels_grad,
903 .count = vg_list_size( cmp_levels_grad )
904 }
905 };
906
907 // Setup pointers and that
908 static void career_local_data_init(void)
909 {
910 struct cmp_level *level_ptrs[ NUM_CAMPAIGN_LEVELS ];
911
912 // COllect pointers
913 for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
914 {
915 struct serializable_set *set = &career_serializable[i];
916
917 for( int j = 0; j < set->count; j ++ )
918 level_ptrs[ set->pack[j].serial_id ] = &set->pack[j];
919 }
920
921 // Apply
922 for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
923 {
924 struct serializable_set *set = &career_serializable[i];
925
926 for( int j = 0; j < set->count; j ++ )
927 {
928 struct cmp_level *lvl = &set->pack[j];
929 lvl->unlock = lvl->_unlock? level_ptrs[ lvl->_unlock ]: NULL;
930 lvl->linked = lvl->_linked? level_ptrs[ lvl->_linked ]: NULL;
931 }
932 }
933 }