new maps (dev)
[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
7 vg_tex2d tex_tiles_wood = { .path = "textures/tile_wood.qoi" };
8 vg_tex2d tex_tiles_min = { .path = "textures/tile_minimal.qoi" };
9 vg_tex2d tex_tiles_lab = { .path = "textures/tile_lab.qoi" };
10
11 vg_tex2d tex_ball_noise = { .path = "textures/bnoise.qoi" };
12 vg_tex2d tex_monofur = { .path = "textures/ascii.qoi", .flags = VG_TEXTURE_NO_MIP };
13 vg_tex2d tex_unkown = { .path = "textures/unkown.qoi" };
14 vg_tex2d tex_buttons = { .path = "textures/buttons.qoi" };
15 vg_tex2d tex_sprites = { .path = "textures/autocombine.qoi" };
16
17 vg_tex2d *texture_list[] = {
18 &tex_tile_detail,
19 &tex_tile_data,
20 &tex_tiles_wood,
21 &tex_tiles_min,
22 &tex_tiles_lab,
23 &tex_ball_noise,
24 &tex_monofur,
25 &tex_unkown,
26 &tex_buttons,
27 &tex_sprites
28 };
29
30 #include "sprites_autocombine.h"
31
32 // AUDIO
33 // ===========================================================================================================
34
35 sfx_vol_control audio_volume_sfx = { .val = 1.0f, .name = "Sound effects" };
36 sfx_vol_control audio_volume_music = { .val = 1.0f, .name = "Music" };
37
38 sfx_system audio_system_sfx =
39 {
40 .vol = 1.f,
41 .ch = 1,
42 .vol_src = &audio_volume_sfx,
43 .name = "sfx"
44 };
45
46 sfx_set audio_tile_mod =
47 {
48 .sources = "\
49 sound/mod_01.ogg\0\
50 sound/mod_02.ogg\0\
51 sound/mod_03.ogg\0\
52 sound/mod_04.ogg\0\
53 sound/mod_05.ogg\0\
54 sound/mod_06.ogg\0",
55 .flags = 0
56 };
57
58 sfx_set audio_splitter =
59 {
60 .sources = "\
61 sound/splitter_01.ogg\0"
62 };
63
64 sfx_set audio_rolls =
65 {
66 .sources = "\
67 sound/rolling_01.ogg\0\
68 sound/rolling_02.ogg\0"
69 };
70
71 sfx_set audio_random =
72 {
73 .sources = "\
74 sound/random_01.ogg\0\
75 sound/random_02.ogg\0\
76 sound/random_03.ogg\0\
77 sound/random_04.ogg\0\
78 sound/random_05.ogg\0\
79 sound/random_06.ogg\0\
80 sound/random_07.ogg\0\
81 sound/random_08.ogg\0"
82 };
83
84 sfx_set audio_clicks =
85 {
86 .sources = "\
87 sound/click_a.ogg\0\
88 sound/click_b.ogg\0\
89 sound/click_c.ogg\0"
90 };
91
92 sfx_set audio_tones =
93 {
94 .sources = "\
95 sound/y0.ogg\0\
96 sound/y1.ogg\0\
97 sound/y2.ogg\0\
98 sound/y3.ogg\0\
99 sound/y4.ogg\0\
100 sound/y5.ogg\0\
101 sound/y6.ogg\0\
102 sound/y7.ogg\0\
103 sound/y8.ogg\0\
104 sound/win.ogg\0"
105 };
106
107 // One two or three layers of rolling noise
108 sfx_system audio_system_balls_rolling =
109 {
110 .vol = 0.7f, .ch = 1, .vol_src = &audio_volume_sfx,
111 .name = "Balls Rolling", .flags = SFX_FLAG_REPEAT | SFX_FLAG_PERSISTENT
112 };
113
114 // Various oneshots
115 sfx_system audio_system_balls_switching =
116 {
117 .vol = 0.2f, .ch = 1, .vol_src = &audio_volume_sfx,
118 .name = "Balls Switching"
119 };
120
121 // Gameplay critical sounds eg. splitter sound rocking
122 sfx_system audio_system_balls_important =
123 {
124 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
125 .name = "Balls Gameplay"
126 };
127
128 // Suplemental sounds
129 sfx_system audio_system_balls_extra =
130 {
131 .vol = 0.27f, .ch = 1, .vol_src = &audio_volume_sfx,
132 .name = "Balls Extra"
133 };
134
135 sfx_system audio_system_ui =
136 {
137 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
138 .name = "UI"
139 };
140
141 static void resource_load_main(void)
142 {
143 // Textures // UI
144 vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
145
146 // Audio
147 sfx_set_init( &audio_tile_mod, NULL );
148 sfx_set_init( &audio_splitter, NULL );
149 sfx_set_init( &audio_rolls, NULL );
150 sfx_set_init( &audio_random, NULL );
151 sfx_set_init( &audio_clicks, NULL );
152 sfx_set_init( &audio_tones, NULL );
153 }
154
155 static void resource_free_main(void)
156 {
157 vg_tex2d_free( texture_list, vg_list_size( texture_list ) );
158
159 sfx_set_free( &audio_tile_mod );
160 sfx_set_free( &audio_splitter );
161 sfx_set_free( &audio_rolls );
162 sfx_set_free( &audio_random );
163 sfx_set_free( &audio_clicks );
164 sfx_set_free( &audio_tones );
165 }
166
167 // SHADERS
168 // ===========================================================================================================
169
170 SHADER_DEFINE( shader_tile_colour,
171
172 // VERTEX
173 "layout (location=0) in vec2 a_co;"
174 "uniform mat3 uPv;"
175 "uniform vec3 uOffset;"
176 ""
177 "void main()"
178 "{"
179 "gl_Position = vec4( uPv * vec3( a_co * uOffset.z + uOffset.xy, 1.0 ), 1.0 );"
180 "}",
181
182 // FRAGMENT
183 "out vec4 FragColor;"
184 "uniform vec4 uColour;"
185 ""
186 "void main()"
187 "{"
188 "FragColor = uColour;"
189 "}"
190 ,
191 UNIFORMS({ "uPv", "uOffset", "uColour" })
192 )
193
194 SHADER_DEFINE( shader_ball,
195 // VERTEX
196 "layout (location=0) in vec2 a_co;"
197 "uniform vec3 uOffset;"
198 "uniform mat3 uPv;"
199 ""
200 "out vec4 aTexCoords;"
201 ""
202 "void main()"
203 "{"
204 // Vertex transform
205 "vec3 worldpos = vec3( (a_co * 0.5 - 0.25) * uOffset.z + uOffset.xy, 1.0 );"
206 "gl_Position = vec4( uPv * worldpos, 1.0 );"
207
208 // Create texture coords
209 "aTexCoords = vec4( a_co, worldpos.xy );"
210 "}",
211
212 // FRAGMENT
213 "out vec4 FragColor;"
214 ""
215 "uniform sampler2D uTexMain;"
216 "uniform vec3 uColour;"
217 "uniform vec2 uTexOffset;"
218 ""
219 "in vec4 aTexCoords;"
220 ""
221 "void main()"
222 "{"
223 "vec2 center_coords = aTexCoords.xy - 0.5;"
224 "vec2 center_coords_sqr = center_coords*center_coords;"
225 "float circle_factor = smoothstep( 0.07, 0.0625, center_coords_sqr.x+center_coords_sqr.y );"
226
227 "float bulge_amt = center_coords_sqr.x+center_coords_sqr.y;"
228 "vec2 warped_coords = aTexCoords.zw+uTexOffset - center_coords;"
229 "vec4 noise_sample = texture( uTexMain, warped_coords );"
230
231 "float rim_light = (center_coords_sqr.x+center_coords_sqr.y)*15.0;"
232
233 "vec2 shadow_coords = center_coords + vec2(0.02,0.07);"
234 "vec2 shadow_coords_sqr = shadow_coords*shadow_coords;"
235 "float shadow = exp(-((shadow_coords_sqr.x+shadow_coords_sqr.y)-0.0125)*15.0);"
236
237 "vec3 marble_comp = uColour*0.9 + (noise_sample.x*0.7+pow(rim_light,3.0)*2.0) * 0.1;"
238 //"vec4 colour_comp = mix( vec4(0.74,0.53,0.34,shadow), vec4(marble_comp,1.0), circle_factor );"
239 "vec4 colour_comp = mix( vec4(0.2,0.2,0.2,shadow), vec4(marble_comp,1.0), circle_factor );"
240
241 "FragColor = colour_comp;"
242 "}"
243 ,
244 UNIFORMS({ "uTexMain", "uColour", "uOffset", "uPv", "uTexOffset" })
245 )
246
247 SHADER_DEFINE( shader_tile_main,
248 // VERTEX
249 "layout (location=0) in vec2 a_co;"
250 "uniform vec4 uOffset;" // Tile x/y, uv x/y
251 "uniform mat3 uPv;"
252 "uniform mat2 uSubTransform;"
253 "uniform float uVisibility;"
254 ""
255 "out vec4 aTexCoords;"
256 "out vec2 aWorldCoords;"
257 ""
258 "vec2 hash22(vec2 p)"
259 "{"
260 "vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));"
261 "p3 += dot(p3, p3.yzx+33.33);"
262 "return fract((p3.xx+p3.yz)*p3.zy);"
263 "}"
264 ""
265 "void main()"
266 "{"
267 "vec2 hash_val = hash22(uOffset.xy);"
268 "float scaling_factor = smoothstep( hash_val.x, hash_val.x+1.0, uVisibility );"
269
270 // Vertex transform
271 "vec2 subtransform = uSubTransform * (a_co-0.5) * scaling_factor + 0.5;"
272 "vec3 worldpos = vec3( subtransform + uOffset.xy, 1.0 );"
273 "gl_Position = vec4( uPv * worldpos, 1.0 );"
274
275 // Create texture coords
276 "vec2 random_offset = floor(hash_val * 4.0) * 0.25;"
277 "vec2 edge_safe_coords = a_co * 0.98 + 0.01;"
278 "aTexCoords = vec4((edge_safe_coords + uOffset.zw) * 0.25, edge_safe_coords * 0.25 + random_offset );"
279 "aWorldCoords = worldpos.xy;"
280 "}",
281
282 // FRAGMENT
283 "out vec4 FragColor;"
284 ""
285 "uniform sampler2D uTexGlyphs;"
286 "uniform sampler2D uTexWood;"
287 "uniform float uGhost;"
288 "uniform float uForeground;"
289 "uniform vec2 uMousePos;"
290 "uniform vec4 uColour;"
291 "uniform vec3 uShadowing;"
292 ""
293 "in vec4 aTexCoords;"
294 "in vec2 aWorldCoords;"
295 ""
296 "void main()"
297 "{"
298 //"vec3 shadowing_colour = vec3( 0.93, 0.88536, 0.8184 ) * 0.97;"
299 //"vec3 shadowing_colour = vec3( 0.8, 0.8, 0.8 );"
300
301 "vec4 glyph = texture( uTexGlyphs, aTexCoords.xy );"
302 "vec4 wood = texture( uTexWood, aTexCoords.zw );"
303 "vec4 wood_secondary = texture( uTexWood, aTexCoords.zw + 0.25 );"
304 "vec3 wood_comp = mix( wood_secondary.rgb * uShadowing, wood.rgb, clamp( glyph.b*2.0-1.0, 0.0, 1.0 ) );"
305
306 //"vec3 shadows = mix( vec3( 0.85, 0.7344, 0.561 ), vec3(1.0,1.0,1.0), glyph.r );"
307 "vec3 shadows = mix( uShadowing, vec3(1.0,1.0,1.0), glyph.r );"
308
309 "vec4 output_regular = vec4( wood_comp * shadows, mix( glyph.a, glyph.b, uForeground ) );"
310
311 "float ghost_dist = clamp( 1.5 - distance(uMousePos, aWorldCoords), 0.0, 1.0 );"
312 "vec4 output_ghost = vec4( 1.0, 1.0, 1.0, glyph.g * ghost_dist );"
313
314 "FragColor = mix( output_regular, output_ghost, uGhost ) * uColour;"
315 "}"
316 ,
317 UNIFORMS({ "uPv", "uOffset", "uTexGlyphs", "uTexWood", "uSubTransform", "uGhost", "uMousePos",
318 "uColour", "uForeground", "uVisibility", "uShadowing" })
319 )
320
321 SHADER_DEFINE( shader_background,
322 // VERTEX
323 "layout (location=0) in vec2 a_co;"
324 "uniform mat3 uPv;"
325 "uniform vec3 uOffset;"
326 ""
327 "out vec2 aTexCoords;"
328 ""
329 "void main()"
330 "{"
331 "vec2 world_pos = a_co * uOffset.z + uOffset.xy;"
332 "gl_Position = vec4( uPv * vec3( world_pos, 1.0 ), 1.0 );"
333 "aTexCoords = a_co;"
334 "}",
335
336 // FRAGMENT
337 "out vec4 FragColor;"
338 ""
339 "uniform sampler2D uTexMain;"
340 "uniform sampler2D uSamplerNoise;"
341 "uniform float uVariance;"
342 "uniform float uVisibility;"
343 ""
344 "in vec2 aTexCoords;"
345 ""
346 "void main()"
347 "{"
348 "float ao_accum = 0.0;"
349 "for( int i=0; i<10; ++i )"
350 "{"
351 "vec2 random_noise = (texture( uSamplerNoise, aTexCoords * 20.0 + float(i) * 0.2 ).xy - vec2( 0.5, 0.5 )) * uVariance;"
352 "vec4 background = texture( uTexMain, aTexCoords + random_noise );"
353 "ao_accum += background.r * clamp((1.0 - length( random_noise )), 0.0, 1.0);"
354 "}"
355 "ao_accum *= 0.15;"
356
357 "vec4 data_this_tile = texture( uTexMain, aTexCoords );"
358
359 "ao_accum -= data_this_tile.r;"
360 "ao_accum *= uVisibility;"
361
362 "vec3 colour_main = mix( vec3( 0.369768, 0.3654, 0.42 ), vec3( 0.275, 0.388, 0.553 ), data_this_tile.g * uVisibility );"
363
364 "vec2 square_coords = fract( aTexCoords * 64.0 );"
365 "vec2 grid_coords = abs( square_coords - 0.5 );"
366 "float edge_contrast = (1.0-ao_accum*0.2);"
367
368 "float gridline = step( 0.49, max(grid_coords.x,grid_coords.y) );"
369 "float gridline_fadeout = min(max(edge_contrast-1.0, 0.0)*40.0 + data_this_tile.g,10.0);"
370
371 "FragColor = vec4( colour_main * edge_contrast + gridline * 0.02 * gridline_fadeout, 1.0 );"
372 "}"
373 ,
374 UNIFORMS({ "uPv", "uOffset", "uTexMain", "uVariance", "uSamplerNoise", "uVisibility" })
375 )
376
377 SHADER_DEFINE( shader_wire,
378 // VERTEX
379 "layout (location=0) in vec2 a_co;"
380 "uniform vec3 uStart;"
381 "uniform vec3 uEnd;"
382 "uniform mat3 uPv;"
383 "uniform float uCurve;"
384 ""
385 "out vec2 aTexCoords;"
386 ""
387 "vec3 sample_curve_time( float t )"
388 "{"
389 "vec3 line_coord = mix( uStart, uEnd, t );"
390
391 "float curve_amt = 1.0-(pow((t*2.0-1.0),2.0));"
392 "return vec3( line_coord.x, line_coord.y - curve_amt*uCurve, line_coord.z );"
393 "}"
394 ""
395 "void main()"
396 "{"
397 // Vertex transform
398 "vec3 p0 = sample_curve_time( a_co.x );"
399 "vec3 p1 = sample_curve_time( a_co.x + 0.025 );"
400
401 "vec2 line_tangent = normalize(p1.xy-p0.xy);"
402 "vec2 line_normal = vec2( -line_tangent.y, line_tangent.x );"
403
404 "vec2 worldfinal = p0.xy + line_normal*a_co.y*p0.z;"
405
406 "gl_Position = vec4( uPv * vec3(worldfinal, 1.0), 1.0 );"
407
408 // Create texture coords (todo: include stretch adjusted coords?)
409 "aTexCoords = vec2( a_co.x, a_co.y + 0.5 );"
410 "}",
411
412 // FRAGMENT
413 "out vec4 FragColor;"
414 ""
415 "uniform sampler2D uTexMain;"
416 "uniform vec4 uColour;"
417 "uniform float uTime;"
418 "uniform float uGlow;"
419 ""
420 "in vec2 aTexCoords;"
421 ""
422 "void main()"
423 "{"
424 // Compute shadowing
425 "float shadow = 1.0 - abs(aTexCoords.y - 0.5) * 2.0;"
426 "float masking = smoothstep( 0.5, 0.8, shadow );"
427
428 "vec3 colour_comp = mix( vec3(0.0,0.0,0.0), uColour.rgb, masking );"
429
430 "float flow_thing = fract( aTexCoords.x + uTime );"
431 "vec3 final_comp = colour_comp + flow_thing * uGlow;"
432
433 "FragColor = vec4( final_comp, max( shadow* 0.2, masking ) * uColour.a );"
434 "}"
435 ,
436 UNIFORMS({ "uPv", "uColour", "uTexMain", "uStart", "uEnd", "uCurve", "uTime", "uGlow" })
437 )
438
439 SHADER_DEFINE( shader_buttons,
440 // VERTEX
441 "layout (location=0) in vec2 a_co;"
442 "uniform vec4 uOffset;" // Tile x/y, uv x/y
443 "uniform mat3 uPv;"
444 ""
445 "out vec2 aTexCoords;"
446 ""
447 "void main()"
448 "{"
449 // Vertex transform
450 "vec3 worldpos = vec3( a_co + uOffset.xy, 1.0 );"
451 "gl_Position = vec4( uPv * worldpos, 1.0 );"
452
453 // Create texture coords
454 "vec2 edge_safe_coords = a_co * 0.98 + 0.01;"
455 "aTexCoords = (edge_safe_coords + uOffset.zw) * 0.25;"
456 "}",
457
458 // FRAGMENT
459 "out vec4 FragColor;"
460 ""
461 "uniform sampler2D uTexMain;"
462 "uniform vec4 uColour;" // rgb, light amount
463 ""
464 "in vec2 aTexCoords;"
465 ""
466 "void main()"
467 "{"
468 "vec4 glyph = texture( uTexMain, aTexCoords.xy );"
469
470 "FragColor = vec4( uColour.rgb * (mix(glyph.r, glyph.g, uColour.a)+0.02)*2.6 + glyph.b * 0.4, glyph.a );"
471 "}"
472 ,
473 UNIFORMS({ "uPv", "uOffset", "uTexMain", "uColour" })
474 )
475
476 SHADER_DEFINE( shader_sprite,
477
478 // VERTEX
479 "layout (location=0) in vec2 a_co;" // quad mesh
480 "uniform vec4 uUv;"
481 "uniform vec3 uPos;"
482 ""
483 "uniform mat3 uPv;"
484 ""
485 "out vec2 aTexCoords;"
486 ""
487 "void main()"
488 "{"
489 "vec2 vertex_world = uUv.zw * (a_co-0.5) * uPos.z + uPos.xy;"
490 "gl_Position = vec4( uPv * vec3( vertex_world, 1.0 ), 1.0 );"
491 "aTexCoords = uUv.xy + a_co*uUv.zw;"
492 "}",
493
494 // FRAGMENT
495 "uniform sampler2D uTexMain;"
496 "out vec4 FragColor;"
497 ""
498 "in vec2 aTexCoords;"
499 ""
500 "void main()"
501 "{"
502 "vec4 texture_sample = texture( uTexMain, aTexCoords );"
503 "FragColor = texture_sample;"
504 "}"
505 ,
506 UNIFORMS({ "uPv", "uTexMain", "uUv", "uPos" })
507 )
508
509 void vg_register(void)
510 {
511 SHADER_INIT( shader_tile_colour );
512 SHADER_INIT( shader_tile_main );
513 SHADER_INIT( shader_ball );
514 SHADER_INIT( shader_background );
515 SHADER_INIT( shader_wire );
516 SHADER_INIT( shader_buttons );
517 SHADER_INIT( shader_sprite );
518 }
519
520 /*
521 0000 0 | 0001 1 | 0010 2 | 0011 3
522 | | | | |
523 X | X= | X | X=
524 | | |
525 0100 4 | 0101 5 | 0110 6 | 0111 7
526 | | | | |
527 =X | =X= | =X | =X=
528 | | |
529 1000 8 | 1001 9 | 1010 10 | 1011 11
530 | | | | |
531 X | X= | X | X=
532 | | | | | | |
533 1100 12 | 1101 13 | 1110 14 | 1111 15
534 | | | | |
535 =X | =X= | =X | =X=
536 | | | | | | |
537 */
538
539 struct cmp_level
540 {
541 const char *map_name;
542 const char *title;
543 const char *description;
544 const char *achievement;
545
546 int unlocked;
547 int completed_score;
548
549 int _unlock, _linked; // When completed, unlock this level
550 struct cmp_level *unlock, *linked;
551
552 struct world_string
553 {
554 enum placement
555 {
556 k_placement_top,
557 k_placement_bottom
558 }
559 placement;
560
561 const char *str;
562 }
563 strings[2];
564
565 int serial_id;
566 int is_tutorial;
567
568 struct world_button btn;
569
570 #ifdef VG_STEAM
571 SteamLeaderboard_t steam_leaderboard;
572 #endif
573 };
574
575 static struct cmp_level cmp_levels_tutorials[] =
576 {
577 {
578 .serial_id = 0,
579 .title = "PRINCIPLE 1",
580 .map_name = "cmp_t01",
581 .description =
582 "",
583
584 ._unlock = 1,
585 .is_tutorial = 1
586 },
587 {
588 .serial_id = 1,
589 .title = "PRINCIPLE 2",
590 .map_name = "cmp_t02",
591 .description =
592 "",
593
594 ._unlock = 2,
595 .is_tutorial = 1,
596 },
597 {
598 .serial_id = 2,
599 .title = "PRINCIPLE 3",
600 .map_name = "cmp_t03",
601 .description =
602 "",
603
604 ._unlock = 12,
605 .is_tutorial = 1
606 },
607 {
608 .serial_id = 12,
609 .title = "PRINCIPLE 4",
610 .map_name = "cmp_t04",
611 .description =
612 "",
613
614 ._unlock = 6,
615 .is_tutorial = 1,
616 .achievement = "TUTORIALS"
617 },
618 {
619 .serial_id = 15,
620 .title = "PRINCIPLE 5",
621 .map_name = "cmp_b10",
622 .description =
623 "",
624
625 ._unlock = 16,
626 .is_tutorial = 1
627 },
628 {
629 .serial_id = 17,
630 .title = "PRINCIPLE 6",
631 .map_name = "cmp_b11",
632 .description =
633 "(Right click)",
634
635 ._unlock = 18,
636 .is_tutorial = 1
637 },
638 {
639 .serial_id = 26,
640 .title = "PRINCIPLE 7",
641 .map_name = "cmp_p7",
642 .description = "Emitters",
643 ._unlock = 27,
644 .is_tutorial = 1
645 }
646 };
647
648 static struct cmp_level cmp_levels_basic[] =
649 {
650 {
651 .serial_id = 6,
652 .title = "PATCH",
653 .map_name = "cmp_b04",
654 .description =
655 "",
656
657 ._unlock = 7,
658 ._linked = 3
659 },
660 {
661 .serial_id = 3,
662 .title = "SUBDIVISION 1",
663 .map_name = "cmp_b01",
664 .description =
665 "",
666
667 ._linked = 4,
668 ._unlock = 5
669 },
670 {
671 .serial_id = 4,
672 .title = "SUBDIVISION 2",
673 .map_name = "cmp_b02",
674 .description =
675 "",
676
677 ._unlock = 7
678 },
679 {
680 .serial_id = 5,
681 .title = "RESTRUCTURE",
682 .map_name = "cmp_b03",
683 .description =
684 "",
685
686 ._unlock = 8
687 },
688 {
689 .serial_id = 7,
690 .title = "PATTERNS 1",
691 .map_name = "cmp_b05",
692 .description =
693 "",
694
695 ._unlock = 15,
696 ._linked = 8
697 },
698 {
699 .serial_id = 8,
700 .title = "PATTERNS 2",
701 .map_name = "cmp_b06",
702 .description =
703 "",
704
705 ._unlock = 15
706 },
707 {
708 .serial_id = 16,
709 .title = "ROUTING PROBLEM",
710 .map_name = "cmp_routing",
711 .description =
712 "",
713
714 ._linked = 9
715 },
716 {
717 .serial_id = 9,
718 .title = "MIGHTY CONSUMER",
719 .map_name = "cmp_b07",
720 .description =
721 "",
722
723 ._linked = 10,
724 ._unlock = 11,
725 .achievement = "MIGHTY_CONSUMER"
726 },
727 {
728 .serial_id = 10,
729 .title = "SHIFT",
730 .map_name = "cmp_b08",
731 .description =
732 "",
733
734 ._unlock = 17
735 },
736 {
737 .serial_id = 11,
738 .title = "REVERSE",
739 .map_name = "cmp_b09",
740 .description =
741 "",
742
743 ._unlock = 17
744 },
745 {
746 .serial_id = 18,
747 .title = "NOT GATE",
748 .map_name = "cmp_not",
749 .description = "",
750
751 ._linked = 19,
752 ._unlock = 20
753 },
754 {
755 .serial_id = 19,
756 .title = "AND GATE",
757 .map_name = "cmp_and",
758 .description = "",
759
760 ._unlock = 20
761 },
762 {
763 .serial_id = 20,
764 .title = "QUALIFICATION PROJECT",
765 .map_name = "cmp_xor",
766 .description = "",
767
768 ._unlock = 25,
769 .achievement = "GRADUATE"
770 },
771 {
772 .serial_id = 27,
773 .title = "EXPAND",
774 .map_name = "cmp_expander",
775 .description = "",
776
777 ._unlock = 28
778 },
779 {
780 .serial_id = 28,
781 .title = "PATTERNS 3",
782 .map_name = "cmp_pattern3",
783 .description = "",
784 ._linked = 29
785 },
786 {
787 .serial_id = 29,
788 .title = "ROUTING PROBLEM 2",
789 .map_name = "cmp_routing2",
790 .description = "Spaghetti!",
791 ._linked = 30
792 },
793 {
794 .serial_id = 30,
795 .title = "EXACTLY 5",
796 .map_name = "cmp_exact5",
797 .description = ""
798 }
799 };
800
801 static struct cmp_level cmp_levels_grad[] =
802 {
803 // r2
804 {
805 .serial_id = 13,
806 .title = "SORT",
807 .map_name = "cmp_i01",
808 .description = "",
809 ._linked = 14
810
811 },
812 // r2
813 {
814 .serial_id = 14,
815 .title = "THIRDS",
816 .map_name = "cmp_i02",
817 .description = "",
818 ._linked = 21
819
820 },
821 {
822 .serial_id = 21,
823 .title = "SIMPLE ADDITION",
824 .map_name = "cmp_grad",
825 .description = "",
826
827 ._linked = 22,
828 ._unlock = 23
829 },
830 {
831 .serial_id = 22,
832 .title = "SECRET CODE",
833 .map_name = "cmp_secret",
834 .description = "",
835
836 ._unlock = 23
837 }
838 };
839
840 static struct cmp_level cmp_levels_computer[] =
841 {
842 {
843 .serial_id = 23,
844 .title = "3 BIT BINARY",
845 .map_name = "cmp_binary",
846 .description = "convert amount to binary",
847 .strings =
848 {
849 {
850 .placement = k_placement_bottom,
851 .str =
852 "\t\t\t\t\t\t\t\t\t\t\x83 \x84\n"
853 "\t\t\t\t\t\t\t\t\t\t\x83 \x84 Binary\n"
854 "\t\t\t\t\t\t\t\t\t\t\x83 4 2 1 \x84"
855 },
856 {
857 .placement = k_placement_top,
858 .str =
859 "\n"
860 "\t\t\t\t\t\t\t\t\t\t\t Count"
861 }
862 },
863
864 ._unlock = 24
865 },
866 {
867 .serial_id = 24,
868 .title = "3 BIT ADDER",
869 .map_name = "cmp_add3b",
870 .description = "binary addition",
871 .strings =
872 {
873 {
874 .placement = k_placement_top,
875 //.str ="\t\t\t\t\t\t\t\t\t| NUMBER A | | NUMBER B |\n"
876 .str =""
877 "\t\t\t\t\t\t\t\t\t\x8A 4 2 1 \x8B \x8A 4 2 1 \x8B\n"
878 "\t\t\t\t\t\t\t\t\t\x83 \x84 add \x83 \x84\n"
879 "\t\t\t\t\t\t\t\t\t\x83 \x84 \x83 \x84"
880 },
881 {
882 .placement = k_placement_bottom,
883 .str =
884 "\t\t\t\x83 \x84\n"
885 "\t\t\t\x83 \x84 result a+b\n"
886 "\t\t\t\x83 8 4 2 1 \x84"
887 }
888 },
889
890 ._unlock = 25
891 },
892 {
893 .serial_id = 25,
894 .title = "3x3 PLOT",
895 .map_name = "cmp_plot3x3",
896 .description = "2 bit x/y",
897
898 .strings =
899 {
900 {
901 .placement = k_placement_top,
902 .str=
903 "\t\t\t\t\t\t\t\t\x8A 2 1 \x8B \x8A 2 1 \x8B\n"
904 "\t\t\t\t\t\t\t\t\x83 \x84 X Y \x83 \x84\n"
905 "\t\t\t\t\t\t\t\t\x83 \x84 \x83 \x84"
906 }
907 }
908 }
909 };
910
911 #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 ) )
912
913 static struct career_level_pack
914 {
915 struct cmp_level *pack;
916 int count;
917
918 v3f primary_colour;
919 v2i origin;
920 v2i dims;
921 }
922 career_packs[] =
923 {
924 {
925 .pack = cmp_levels_tutorials,
926 .count = vg_list_size( cmp_levels_tutorials ),
927 .primary_colour = { 0.204f, 0.345f, 0.553f },
928 .origin = { -5, -2 },
929 .dims = { 1, 7 }
930 },
931 {
932 .pack = cmp_levels_basic,
933 .count = vg_list_size( cmp_levels_basic ),
934 .primary_colour = { 0.304f, 0.245f, 0.553f },
935 .origin = { -3, -2 },
936 .dims = { 3, 7 }
937 },
938 {
939 .pack = cmp_levels_grad,
940 .count = vg_list_size( cmp_levels_grad ),
941 .primary_colour = { 0.553f, 0.345f, 0.204f },
942 .origin = { -5, 6 },
943 .dims = { 5, 1 }
944 },
945 {
946 .pack = cmp_levels_computer,
947 .count = vg_list_size( cmp_levels_computer ),
948 .primary_colour = { 0.75f, 0.23f, 0.39f },
949 .origin = { -5, 8 },
950 .dims = { 5, 2 }
951 }
952 };
953
954 // Setup pointers and that
955 static void career_local_data_init(void)
956 {
957 struct cmp_level *level_ptrs[ NUM_CAMPAIGN_LEVELS ];
958 for( int i = 0; i < NUM_CAMPAIGN_LEVELS; i ++ )
959 level_ptrs[i] = NULL;
960
961 // COllect pointers
962 for( int i = 0; i < vg_list_size( career_packs ); i ++ )
963 {
964 struct career_level_pack *set = &career_packs[i];
965
966 for( int j = 0; j < set->count; j ++ )
967 {
968 int id = set->pack[j].serial_id;
969
970 if( level_ptrs[ id ] )
971 vg_error( "Serial id %u already used!\n", id );
972 else
973 level_ptrs[ set->pack[j].serial_id ] = &set->pack[j];
974 }
975 }
976
977 // Apply
978 for( int i = 0; i < vg_list_size( career_packs ); i ++ )
979 {
980 struct career_level_pack *set = &career_packs[i];
981
982 for( int j = 0; j < set->count; j ++ )
983 {
984 struct cmp_level *lvl = &set->pack[j];
985
986 if( lvl->_unlock >= NUM_CAMPAIGN_LEVELS ||
987 lvl->_linked >= NUM_CAMPAIGN_LEVELS )
988 {
989 vg_error( "_unlock / _linked out of range (%d, %d)\n",
990 lvl->_unlock, lvl->_linked );
991 }
992 else
993 {
994 lvl->unlock = lvl->_unlock? level_ptrs[ lvl->_unlock ]: NULL;
995 lvl->linked = lvl->_linked? level_ptrs[ lvl->_linked ]: NULL;
996 }
997 }
998 }
999 }