basic dead device and some comments for next time
[carveJwlIkooP6JGAAIwe30JlM.git] / skaterift.c
1 /*
2 * =============================================================================
3 *
4 * Copyright . . . -----, ,----- ,---. .---.
5 * 2021-2023 |\ /| | / | | | | /|
6 * | \ / | +-- / +----- +---' | / |
7 * | \ / | | / | | \ | / |
8 * | \/ | | / | | \ | / |
9 * ' ' '--' [] '----- '----- ' ' '---' SOFTWARE
10 *
11 * =============================================================================
12 */
13
14 #define SR_NETWORKED
15 #include "common.h"
16 #include "conf.h"
17 #include "steam.h"
18 #include "render.h"
19 #include "audio.h"
20 #include "world.h"
21
22 #if 0
23 #include "player.h"
24 #else
25 #include "player_interface.h"
26 #include "player_device_walk.h"
27 #include "player_device_skate.h"
28 #include "player_device_dead.h"
29 #include "player_model.h"
30
31 /* temp */
32 VG_STATIC player_interface localplayer;
33 VG_STATIC struct player_device_walk localplayer_walk;
34 VG_STATIC struct player_device_skate localplayer_skate;
35 VG_STATIC struct player_device_dead localplayer_dead;
36 VG_STATIC struct player_avatar localplayer_avatar;
37 VG_STATIC glmesh localplayer_meshes[3];
38
39 #endif
40
41 #include "network.h"
42
43 #if 0
44 #include "menu.h"
45 #endif
46 #include "vehicle.h"
47
48 static int cl_ui = 1,
49 cl_view_id = 0,
50 cl_light_edit = 0;
51
52 int main( int argc, char *argv[] )
53 {
54 vg_mem.use_libc_malloc = 0;
55 vg_set_mem_quota( 128*1024*1024 );
56 vg_enter( argc, argv, "Voyager Game Engine" );
57
58 return 0;
59 }
60
61 VG_STATIC void highscores_save_at_exit(void)
62 {
63 highscores_serialize_all();
64 }
65
66 VG_STATIC void vg_launch_opt(void)
67 {
68
69 }
70
71 VG_STATIC int __kill( int argc, const char *argv[] )
72 {
73 player_use_device( &localplayer, &player_device_dead, &localplayer_dead );
74 return 0;
75 }
76
77 VG_STATIC int __respawn( int argc, const char *argv[] )
78 {
79 struct respawn_point *rp = NULL, *r;
80
81 if( argc == 1 )
82 {
83 for( int i=0; i<world.spawn_count; i++ )
84 {
85 r = &world.spawns[i];
86 if( !strcmp( r->name, argv[0] ) )
87 {
88 rp = r;
89 break;
90 }
91 }
92
93 if( !rp )
94 vg_warn( "No spawn named '%s'\n", argv[0] );
95 }
96
97 if( !rp )
98 {
99 float min_dist = INFINITY;
100
101 for( int i=0; i<world.spawn_count; i++ )
102 {
103 r = &world.spawns[i];
104 float d = v3_dist2( r->co, localplayer.rb.co );
105
106 vg_info( "Dist %s : %f\n", r->name, d );
107 if( d < min_dist )
108 {
109 min_dist = d;
110 rp = r;
111 }
112 }
113 }
114
115 if( !rp )
116 {
117 vg_error( "No spawn found\n" );
118
119 if( !world.spawn_count )
120 return 0;
121
122 rp = &world.spawns[0];
123 }
124
125 player_spawn( &localplayer, rp );
126 return 1;
127 }
128
129 VG_STATIC void vg_preload(void)
130 {
131 g_conf_init();
132
133 common_var_temp();
134
135 vg_var_push( (struct vg_var){
136 .name = "cl_ui",
137 .data = &cl_ui,
138 .data_type = k_var_dtype_i32,
139 .opt_i32 = { .min=0, .max=1, .clamp=1 },
140 .persistent = 0
141 });
142
143 vg_var_push( (struct vg_var){
144 .name = "cl_view_id",
145 .data = &cl_view_id,
146 .data_type = k_var_dtype_i32,
147 .opt_i32 = { .min=0, .max=1, .clamp=1 },
148 .persistent = 0
149 });
150
151 vg_var_push( (struct vg_var){
152 .name = "ledit",
153 .data = &cl_light_edit,
154 .data_type = k_var_dtype_i32,
155 .opt_i32 = { .min=0, .max=1, .clamp=1 },
156 .persistent = 0
157 });
158
159 vg_function_push( (struct vg_cmd) {
160 .name = "respawn",
161 .function = __respawn,
162 //.poll_suggest = reset_player_poll
163 });
164
165 vg_function_push( (struct vg_cmd) {
166 .name = "ded",
167 .function = __kill,
168 //.poll_suggest = reset_player_poll
169 });
170
171 vg_info(" Copyright . . . -----, ,----- ,---. .---. \n" );
172 vg_info(" 2021-2022 |\\ /| | / | | | | /| \n" );
173 vg_info(" | \\ / | +-- / +----- +---' | / | \n" );
174 vg_info(" | \\ / | | / | | \\ | / | \n" );
175 vg_info(" | \\/ | | / | | \\ | / | \n" );
176 vg_info(" ' ' '--' [] '----- '----- ' ' '---' "
177 "SOFTWARE\n" );
178
179 highscores_init( 2000, 50 );
180 if( !highscores_read() )
181 highscores_create_db();
182
183 vg_loader_step( NULL, highscores_save_at_exit );
184
185 steam_init();
186 vg_loader_step( NULL, steam_end );
187 vg_loader_step( network_init, network_end );
188 }
189
190 VG_STATIC void load_playermodels(void)
191 {
192 vg_linear_clear( vg_mem.scratch );
193
194 /*
195 * load in other player models. This may need to be more sophisticated in
196 * the futre if we have more of these guys
197 */
198 mdl_context ctx_default,
199 ctx_outlaw,
200 ctx_jordan;
201
202 mdl_open( &ctx_default, "models/ch_new.mdl" );
203 mdl_load_metadata( &ctx_default, vg_mem.scratch );
204 mdl_load_mesh_data( &ctx_default, vg_mem.scratch );
205 mdl_close( &ctx_default );
206
207 mdl_open( &ctx_outlaw, "models/ch_outlaw.mdl" );
208 mdl_load_metadata( &ctx_outlaw, vg_mem.scratch );
209 mdl_load_mesh_data( &ctx_outlaw, vg_mem.scratch );
210 mdl_close( &ctx_outlaw );
211
212 mdl_open( &ctx_jordan, "models/ch_jordan.mdl" );
213 mdl_load_metadata( &ctx_jordan, vg_mem.scratch );
214 mdl_load_mesh_data( &ctx_jordan, vg_mem.scratch );
215 mdl_close( &ctx_jordan );
216
217 vg_acquire_thread_sync();
218 {
219 mdl_unpack_glmesh( &ctx_default, &localplayer_meshes[0] );
220 mdl_unpack_glmesh( &ctx_outlaw, &localplayer_meshes[1] );
221 mdl_unpack_glmesh( &ctx_jordan, &localplayer_meshes[2] );
222 }
223 vg_release_thread_sync();
224
225 /* FIXME: hack */
226 shader_viewchar_register();
227 vg_acquire_thread_sync();
228 {
229 vg_tex2d_init( (vg_tex2d *[]){ &tex_characters }, 1 );
230 }
231 vg_release_thread_sync();
232 }
233
234 VG_STATIC void vg_load(void)
235 {
236 vg_loader_step( render_init, NULL );
237 //vg_loader_step( menu_init, NULL );
238 vg_loader_step( world_init, NULL );
239 //vg_loader_step( player_init, NULL );
240 //vg_loader_step( vehicle_init, NULL );
241 //
242 //vg_loader_step( player_model_init, NULL );
243
244 /* ----------------- */
245 vg_loader_step( load_playermodels, NULL );
246
247 /* player setup */
248 player_interface_create_player( &localplayer );
249
250 player_avatar_load( &localplayer_avatar, "models/ch_new.mdl" );
251 player_use_avatar( &localplayer, &localplayer_avatar );
252 player_use_mesh( &localplayer, &localplayer_meshes[0] );
253 player_use_device( &localplayer, &player_device_walk, &localplayer_walk );
254 player_use_device( &localplayer, &player_device_skate, &localplayer_skate );
255
256 /* --------------------- */
257
258 vg_bake_shaders();
259 vg_loader_step( audio_init, audio_free );
260 world_audio_init();
261
262 /* 'systems' are completely loaded now */
263 strcpy( world.world_name, "maps/mp_mtzero.mdl" );
264 strcpy( world.world_name, "maps/mp_gridmap.mdl" );
265 world_load();
266 vg_console_load_autos();
267 }
268
269 VG_STATIC void vg_start(void)
270 {
271 __respawn( 1, (const char *[]){ "start" } );
272 }
273
274 VG_STATIC void draw_origin_axis(void)
275 {
276 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
277 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
278 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
279 }
280
281 VG_STATIC void vg_update(void)
282 {
283 steam_update();
284
285 if( vg.is_loaded )
286 {
287 draw_origin_axis();
288 network_update();
289
290 #if 0
291 if( !gzoomer.inside )
292 player_update_pre();
293 #endif
294
295 player_pre_update( &localplayer );
296 world_update( localplayer.rb.co );
297 }
298 }
299
300 VG_STATIC void vg_update_fixed(void)
301 {
302 if( vg.is_loaded )
303 {
304 #if 0
305 if( !gzoomer.inside )
306 player_update_fixed();
307
308 vehicle_update_fixed();
309 #endif
310
311 player_update( &localplayer );
312 }
313 }
314
315 VG_STATIC void vg_update_post(void)
316 {
317 if( vg.is_loaded )
318 {
319 #if 0
320 if( gzoomer.inside )
321 {
322 vehicle_camera();
323 }
324 else
325 {
326 player_update_post();
327 }
328 #endif
329
330 player_post_update( &localplayer );
331
332 #if 0
333 menu_update();
334 vehicle_update_post();
335 #endif
336 }
337 }
338
339 VG_STATIC void vg_framebuffer_resize( int w, int h )
340 {
341 render_fb_resize();
342 }
343
344 VG_STATIC void present_view_with_post_processing(void)
345 {
346 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
347
348 glEnable(GL_BLEND);
349 glDisable(GL_DEPTH_TEST);
350 glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
351 glBlendEquation(GL_FUNC_ADD);
352
353 if( cl_blur )
354 {
355 shader_blitblur_use();
356 shader_blitblur_uTexMain( 0 );
357 shader_blitblur_uTexMotion( 1 );
358 shader_blitblur_uBlurStrength(cl_blur_strength / (vg.frame_delta*60.0f));
359
360 v2f menu_blurring;
361 //v2_muls( (v2f){ 0.04f, 0.001f }, menu_opacity, menu_blurring );
362 v2_muls( (v2f){ 0.04f, 0.001f }, 0.0f, menu_blurring );
363 shader_blitblur_uOverrideDir( menu_blurring );
364
365 if( cl_view_id == 0 )
366 render_fb_bind_texture( gpipeline.fb_main, 0, 0 );
367 else if( cl_view_id == 1 )
368 render_fb_bind_texture( gpipeline.fb_main, 1, 0 );
369 else
370 render_fb_bind_texture( gpipeline.fb_main, 0, 0 );
371
372 render_fb_bind_texture( gpipeline.fb_main, 1, 1 );
373 }
374 else
375 {
376 shader_blit_use();
377 shader_blit_uTexMain( 0 );
378 render_fb_bind_texture( gpipeline.fb_main, 0, 0 );
379 }
380
381 render_fsquad();
382 }
383
384 VG_STATIC void render_player_transparent(void)
385 {
386 static camera small_cam; /* DOES NOT NEED TO BE STATIC BUT MINGW
387 SAIS OTHERWISE */
388
389 m4x3_copy( main_camera.transform, small_cam.transform );
390
391 small_cam.fov = main_camera.fov;
392 small_cam.nearz = 0.05f;
393 small_cam.farz = 60.0f;
394
395 camera_update_view( &small_cam );
396 camera_update_projection( &small_cam );
397 camera_finalize( &small_cam );
398
399 /* Draw player to window buffer and blend background ontop */
400 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
401 player_render( &small_cam, &localplayer );
402 }
403
404 VG_STATIC void render_scene(void)
405 {
406 render_fb_bind( gpipeline.fb_main );
407 glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
408 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
409
410 /* Draw world */
411 glEnable( GL_DEPTH_TEST );
412 render_world( &main_camera );
413
414
415
416 int player_transparent = 1,
417 player_draw = 1;
418
419 if( !player_transparent && player_draw )
420 player_render( &main_camera, &localplayer );
421
422 render_water_texture( &main_camera );
423 render_fb_bind( gpipeline.fb_main );
424 render_water_surface( &main_camera );
425 render_world_gates( &main_camera );
426
427 if( player_transparent && player_draw )
428 render_player_transparent();
429 }
430
431 VG_STATIC void render_menu(void)
432 {
433 glClear( GL_DEPTH_BUFFER_BIT );
434 #if 0
435 menu_render( &main_camera );
436 #endif
437 }
438
439 VG_STATIC void render_main_game(void)
440 {
441 #if 0
442 static float fov = 60.0f;
443 float fov_target = vg_lerpf( 90.0f, 110.0f, cl_fov );
444
445 if( player.controller == k_player_controller_skate )
446 fov_target = vg_lerpf( 97.0f, 135.0f, cl_fov );
447
448 if( cl_menu )
449 fov_target = menu_fov_target;
450 fov = vg_lerpf( fov, fov_target, vg.frame_delta * 2.0f );
451 fov = freecam? 60.0f: fov;
452
453 main_camera.fov = fov;
454 #endif
455
456 /* copy camera from player.
457 * TODO: blend with camera from menu */
458
459 /* FIXME: TEMP!! */
460 player_pre_render( &localplayer );
461
462 v3_copy( localplayer.cam.pos, main_camera.pos );
463 v3_copy( localplayer.cam.angles, main_camera.angles );
464 main_camera.fov = localplayer.cam.fov;
465 main_camera.nearz = 0.1f;
466 main_camera.farz = 2100.0f;
467
468 camera_update_transform( &main_camera );
469 camera_update_view( &main_camera );
470 camera_update_projection( &main_camera );
471 camera_finalize( &main_camera );
472
473 /* ========== Begin Frame ========== */
474
475 render_scene();
476 present_view_with_post_processing();
477
478 #if 0
479 if( cl_menu )
480 {
481 render_menu();
482 render_player_transparent();
483 }
484 #endif
485
486 /* =========== End Frame =========== */
487 }
488
489 VG_STATIC void vg_render(void)
490 {
491 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
492
493 glViewport( 0,0, vg.window_x, vg.window_y );
494 glDisable( GL_DEPTH_TEST );
495
496 glClearColor( 1.0f, 0.0f, 0.0f, 0.0f );
497 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
498
499 render_main_game();
500
501 /* Other shite */
502 glDisable(GL_BLEND);
503 glDisable( GL_DEPTH_TEST );
504 vg_lines_drawall( (float *)main_camera.mtx.pv );
505 glViewport( 0,0, vg.window_x, vg.window_y );
506 }
507
508 VG_STATIC void run_light_widget( struct light_widget *lw );
509 VG_STATIC void vg_ui(void)
510 {
511 player_ui( &localplayer );
512
513 #if 0
514 menu_crap_ui();
515 #endif
516
517 if( cl_light_edit )
518 {
519 vg_uictx.cursor[0] = 10;
520 vg_uictx.cursor[1] = 10;
521 vg_uictx.cursor[2] = 200;
522 vg_uictx.cursor[3] = 20;
523
524 struct ub_world_lighting *wl = &gpipeline.ub_world_lighting;
525 struct ui_slider_vector
526 s5 = { .min=0.0f, .max=2.0f, .len=3, .data=wl->g_ambient_colour };
527
528 struct ui_slider
529 s8 = { .min=0.0f, .max=2.0f, .data = &gpipeline.shadow_spread },
530 s9 = { .min=0.0f, .max=25.0f, .data = &gpipeline.shadow_length };
531
532 for( int i=0; i<3; i++ )
533 run_light_widget( &gpipeline.widgets[i] );
534
535 ui_text( vg_uictx.cursor, "Ambient", 1, 0 );
536 vg_uictx.cursor[1] += 16;
537 ui_slider_vector( &s5 );
538
539 ui_text( vg_uictx.cursor, "Shadows", 1, 0 );
540 vg_uictx.cursor[1] += 16;
541 ui_slider( &s8 );
542 ui_slider( &s9 );
543
544 ui_text( vg_uictx.cursor, "Misc", 1, 0 );
545 vg_uictx.cursor[1] += 16;
546 struct ui_checkbox c1 = {.data = &wl->g_light_preview};
547 ui_checkbox( &c1 );
548
549 render_update_lighting_ub();
550 }
551
552 //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
553 if( cl_ui )
554 {
555 render_world_routes_ui();
556 }
557 //glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
558
559 audio_debug_soundscapes();
560 render_view_framebuffer_ui();
561
562 #if 0
563 player_physics_gui();
564 #endif
565 }
566
567 VG_STATIC void run_light_widget( struct light_widget *lw )
568 {
569 struct ui_checkbox c1 = { .data=&lw->enabled };
570
571 ui_checkbox( &c1 );
572
573 if( lw->enabled )
574 {
575 struct ui_slider_vector
576 colour = { .min=0.0f, .max=2.0f, .len=3, .data=lw->colour },
577 dir = { .min=-VG_PIf, .max=VG_PIf, .len=2, .data=lw->dir };
578
579 ui_slider_vector( &colour );
580 vg_uictx.cursor[1] += 4;
581 ui_slider_vector( &dir );
582 }
583 }
584
585 VG_STATIC void run_debug_info(void)
586 {
587 #if 0
588 char buf[40];
589
590 snprintf( buf, 40, "%.2fm/s", v3_length( player.rb.v ) );
591 ui_text( (ui_px [2]){ 0, 0 }, buf, 1, k_text_align_left );
592
593 snprintf( buf, 40, "%.2f %.2f %.2f m/s",
594 player.phys.a[0], player.phys.a[1], player.phys.a[2] );
595 ui_text( (ui_px [2]){ 0, 20 }, buf, 1, k_text_align_left );
596
597 snprintf( buf, 40, "pos %.2f %.2f %.2f",
598 player.phys.rb.co[0], player.phys.rb.co[1], player.phys.rb.co[2] );
599 ui_text( (ui_px [2]){ 0, 40 }, buf, 1, k_text_align_left );
600
601 if( vg_input.controller_handle )
602 {
603 for( int i=0; i<vg_list_size(vg_input.controller_axises); i++ )
604 {
605 snprintf( buf, 40, "%.2f", vg_input.controller_axises[i] );
606 ui_text( (ui_px [2]){ 0, (i+3)*20 }, buf, 1, k_text_align_left );
607 }
608 }
609 else
610 {
611 ui_text( (ui_px [2]){ 0, 60 },
612 "Gamepad not ready", 1, k_text_align_left );
613 }
614 #endif
615 }