2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
8 #define PLAYER_REWIND_FRAMES 60*4
18 k_air_accelerate
= 20.0f
,
21 k_board_radius
= 0.3f
,
22 k_board_length
= 0.45f
,
23 k_board_allowance
= 0.04f
,
24 //k_friction_lat = 8.8f,
25 k_friction_lat
= 12.0f
,
26 k_friction_resistance
= 0.01f
,
27 k_max_push_speed
= 16.0f
,
29 k_push_cycle_rate
= 8.0f
,
30 k_steer_ground
= 2.5f
,
32 k_steer_air_lerp
= 0.3f
,
35 k_walk_downforce
= 8.0f
,
36 k_jump_charge_speed
= (1.0f
/1.0f
),
40 k_walk_accel
= 150.0f
,
41 k_walk_friction
= 8.0f
;
43 VG_STATIC
int cl_playermdl_id
= 0;
44 VG_STATIC
int freecam
= 0;
45 VG_STATIC
int walk_grid_iterations
= 1;
46 VG_STATIC
float fc_speed
= 10.0f
;
49 * -----------------------------------------------------------------------------
51 * -----------------------------------------------------------------------------
54 VG_STATIC
struct gplayer
57 rigidbody collide_front
, collide_back
;
61 rigidbody rb
, rb_gate_frame
;
62 float iY
, siY
; /* Yaw inertia */
64 v3f a
, v_last
, m
, bob
, vl
;
67 float vswitch
, slip
, slip_last
,
70 float grab
, jump
, pushing
, push_time
;
74 int in_air
, on_board
, jump_charge
, jump_dir
;
81 m4x3f visual_transform
,
84 int is_dead
, death_tick_allowance
, rewinding
;
85 int rewind_sound_wait
;
88 v3f land_target_log
[22];
89 u32 land_target_colours
[22];
92 v3f handl_target
, handr_target
,
96 struct input_binding
*input_js1h
,
113 v3f camera_pos
, smooth_localcam
;
122 u32 rewind_incrementer
,
125 float rewind_time
, rewind_total_length
, rewind_predicted_time
;
126 double diag_rewind_start
, diag_rewind_time
;
145 enum mdl_surface_prop surface_prop
;
150 glmesh player_meshes
[3];
154 struct skeleton_anim
*anim_stand
,
158 *anim_push
, *anim_push_reverse
,
159 *anim_ollie
, *anim_ollie_reverse
,
160 *anim_grabs
, *anim_stop
,
161 *anim_walk
, *anim_run
, *anim_idle
,
193 .collide_front
= { .type
= k_rb_shape_sphere
, .inf
.sphere
.radius
= 0.3f
},
194 .collide_back
= { .type
= k_rb_shape_sphere
, .inf
.sphere
.radius
= 0.3f
}
200 VG_STATIC
float *player_get_pos(void);
201 VG_STATIC
void player_kill(void);
202 VG_STATIC
float *player_cam_pos(void);
203 VG_STATIC
void player_save_frame(void);
204 VG_STATIC
void player_restore_frame(void);
205 VG_STATIC
void player_save_rewind_frame(void);
210 VG_STATIC
void player_mouseview(void);
212 #include "player_physics.h"
213 #include "player_ragdoll.h"
214 #include "player_model.h"
215 #include "player_animation.h"
216 #include "player_audio.h"
219 * -----------------------------------------------------------------------------
221 * -----------------------------------------------------------------------------
224 VG_STATIC
void player_init(void) /* 1 */
226 player
.input_js1h
= vg_create_named_input( "steer-h", k_input_type_axis
);
227 player
.input_js1v
= vg_create_named_input( "steer-v", k_input_type_axis
);
228 player
.input_grab
= vg_create_named_input( "grab", k_input_type_axis_norm
);
229 player
.input_js2h
= vg_create_named_input( "grab-h", k_input_type_axis
);
230 player
.input_js2v
= vg_create_named_input( "grab-v", k_input_type_axis
);
231 player
.input_jump
= vg_create_named_input( "jump", k_input_type_button
);
232 player
.input_push
= vg_create_named_input( "push", k_input_type_button
);
233 player
.input_walk
= vg_create_named_input( "walk", k_input_type_button
);
235 player
.input_walkh
= vg_create_named_input( "walk-h",
237 player
.input_walkv
= vg_create_named_input( "walk-v",
241 player
.input_switch_mode
= vg_create_named_input( "switch-mode",
242 k_input_type_button
);
243 player
.input_reset
= vg_create_named_input( "reset", k_input_type_button
);
245 const char *default_cfg
[] =
247 "bind steer-h gp-ls-h",
251 "bind steer-v gp-ls-v",
257 "bind grab-h gp-rs-h",
258 "bind grab-v gp-rs-v",
269 "bind walk-h gp-ls-h",
270 "bind walk-v -gp-ls-v",
279 "bind switch-mode gp-y",
280 "bind switch-mode e",
283 for( int i
=0; i
<vg_list_size(default_cfg
); i
++ )
284 execute_console_input(default_cfg
[i
]);
286 rb_init( &player
.phys
.rb
);
287 rb_init( &player
.collide_front
);
288 rb_init( &player
.collide_back
);
290 vg_convar_push( (struct vg_convar
){
291 .name
= "cl_playermdl_id",
292 .data
= &cl_playermdl_id
,
293 .data_type
= k_convar_dtype_i32
,
294 .opt_i32
= { .min
=0, .max
=2, .clamp
=1 },
298 vg_convar_push( (struct vg_convar
){
299 .name
= "gwalk_speed",
300 .data
= &k_walkspeed
,
301 .data_type
= k_convar_dtype_f32
,
302 .opt_f32
= { .clamp
= 0 },
306 vg_convar_push( (struct vg_convar
){
307 .name
= "air_accelerate",
308 .data
= &k_air_accelerate
,
309 .data_type
= k_convar_dtype_f32
,
310 .opt_f32
= { .clamp
= 0 },
314 vg_convar_push( (struct vg_convar
){
317 .data_type
= k_convar_dtype_f32
,
318 .opt_f32
= { .clamp
= 0 },
322 vg_convar_push( (struct vg_convar
){
323 .name
= "walk_accel",
324 .data
= &k_walk_accel
,
325 .data_type
= k_convar_dtype_f32
,
326 .opt_f32
= { .clamp
= 0 },
330 vg_convar_push( (struct vg_convar
){
333 .data_type
= k_convar_dtype_i32
,
334 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
338 vg_convar_push( (struct vg_convar
){
341 .data_type
= k_convar_dtype_f32
,
342 .opt_f32
= { .clamp
= 0 },
346 vg_function_push( (struct vg_cmd
){
348 .function
= reset_player
351 player
.rewind_length
= 0;
352 player
.rewind_buffer
=
353 vg_linear_alloc( vg_mem
.rtmemory
,
354 sizeof(struct rewind_frame
) * PLAYER_REWIND_FRAMES
);
362 VG_STATIC
void player_save_rewind_frame(void)
364 if( player
.rewind_length
< PLAYER_REWIND_FRAMES
)
366 struct rewind_frame
*fr
=
367 &player
.rewind_buffer
[ player
.rewind_length
++ ];
369 v2_copy( player
.angles
, fr
->ang
);
370 v3_copy( player
.camera_pos
, fr
->pos
);
372 player
.rewind_incrementer
= 0;
374 if( player
.rewind_length
> 1 )
376 player
.rewind_total_length
+=
377 v3_dist( player
.rewind_buffer
[player
.rewind_length
-1].pos
,
378 player
.rewind_buffer
[player
.rewind_length
-2].pos
);
385 VG_STATIC
int menu_enabled(void);
389 * Free camera movement
391 VG_STATIC
void player_mouseview(void)
396 v2_muladds( player
.angles
, vg
.mouse_delta
, 0.0025f
, player
.angles
);
398 if( vg_input
.controller_should_use_trackpad_look
)
400 static v2f last_input
;
402 static v2f vel_smooth
;
404 v2f input
= { player
.input_js2h
->axis
.value
,
405 player
.input_js2v
->axis
.value
};
407 if( (v2_length2(last_input
) > 0.001f
) && (v2_length2(input
) > 0.001f
) )
409 v2_sub( input
, last_input
, vel
);
410 v2_muls( vel
, 1.0f
/vg
.time_delta
, vel
);
417 v2_lerp( vel_smooth
, vel
, vg
.time_delta
*8.0f
, vel_smooth
);
419 v2_muladds( player
.angles
, vel_smooth
, vg
.time_delta
, player
.angles
);
420 v2_copy( input
, last_input
);
424 player
.angles
[0] += player
.input_js2h
->axis
.value
* vg
.time_delta
* 4.0f
;
425 player
.angles
[1] += player
.input_js2v
->axis
.value
* vg
.time_delta
* 4.0f
;
428 player
.angles
[1] = vg_clampf( player
.angles
[1], -VG_PIf
*0.5f
, VG_PIf
*0.5f
);
431 /* Deal with input etc */
432 VG_STATIC
void player_update_pre(void)
434 struct player_phys
*phys
= &player
.phys
;
436 if( player
.rewinding
)
441 if( vg_input_button_down( player
.input_reset
) && !menu_enabled() )
445 reset_player( 0, NULL
);
447 audio_play_oneshot( &audio_ui
[0], 1.0f
);
452 double delta
= world
.time
- world
.last_use
;
454 if( (delta
<= RESET_MAX_TIME
) && (world
.last_use
!= 0.0) )
456 player
.rewinding
= 1;
457 player
.rewind_sound_wait
= 1;
458 player
.rewind_time
= (float)player
.rewind_length
- 0.0001f
;
459 player_save_rewind_frame();
461 audio_play_oneshot( &audio_rewind
[0], 1.0f
);
464 /* based on analytical testing. DONT CHANGE!
466 * time taken: y = (x^(4/5)) * 74.5
467 * inverse : x = (2/149)^(4/5) * y^(4/5)
470 float constant
= powf( 2.0f
/149.0f
, 4.0f
/5.0f
),
471 curve
= powf( player
.rewind_total_length
, 4.0f
/5.0f
);
473 player
.rewind_predicted_time
= constant
* curve
;
474 player
.diag_rewind_start
= vg
.time
;
475 player
.diag_rewind_time
= player
.rewind_time
;
478 player
.death_tick_allowance
= 30;
479 player_restore_frame();
481 if( !phys
->on_board
)
483 player
.angles
[0] = atan2f( -phys
->rb
.forward
[2],
484 -phys
->rb
.forward
[0] );
487 player
.mdl
.shoes
[0] = 1;
488 player
.mdl
.shoes
[1] = 1;
490 world_routes_notify_reset();
492 /* apply 1 frame of movement */
499 audio_play_oneshot( &audio_rewind
[4], 1.0f
);
505 if( vg_input_button_down( player
.input_switch_mode
) && !menu_enabled() )
507 phys
->on_board
^= 0x1;
512 v3_muladds( phys
->rb
.v
, phys
->rb
.forward
, 0.2f
, phys
->rb
.v
);
513 audio_play_oneshot( &audio_lands
[6], 1.0f
);
517 audio_play_oneshot( &audio_lands
[5], 1.0f
);
523 if( !phys
->on_board
)
527 VG_STATIC
void player_update_fixed(void) /* 2 */
529 if( player
.rewinding
)
532 if( player
.death_tick_allowance
)
533 player
.death_tick_allowance
--;
535 struct player_phys
*phys
= &player
.phys
;
539 player_ragdoll_iter();
543 player
.rewind_incrementer
++;
545 if( player
.rewind_incrementer
> (u32
)(0.25/VG_TIMESTEP_FIXED
) )
547 player_save_rewind_frame();
554 VG_STATIC
void player_update_post(void)
556 for( int i
=0; i
<player
.land_log_count
; i
++ )
557 vg_line_cross( player
.land_target_log
[i
],
558 player
.land_target_colours
[i
], 0.25f
);
562 player_debug_ragdoll();
565 player_animate_death_cam();
572 player_animate_camera();
579 /* CAMERA POSITIONING: LAYER 0 */
580 v2_copy( player
.angles
, camera_angles
);
581 v3_copy( player
.camera_pos
, camera_pos
);
583 if( player
.rewinding
)
585 if( player
.rewind_time
<= 0.0f
)
587 double taken
= vg
.time
- player
.diag_rewind_start
;
588 vg_success( "Rewind took (rt, pl, tl): %f, %f, %f\n",
589 taken
, player
.diag_rewind_time
,
590 player
.rewind_total_length
);
592 player
.rewinding
= 0;
593 player
.rewind_length
= 1;
594 player
.rewind_total_length
= 0.0f
;
595 player
.rewind_incrementer
= 0;
596 world
.sky_target_rate
= 1.0;
600 world
.sky_target_rate
= -100.0;
601 assert( player
.rewind_length
> 0 );
606 float budget
= vg
.time_delta
,
607 overall_length
= player
.rewind_length
;
609 world_routes_rollback_time( player
.rewind_time
/ overall_length
);
611 for( int i
=0; (i
<10)&&(player
.rewind_time
>0.0f
)&&(budget
>0.0f
); i
++ )
613 /* Interpolate frames */
614 int i0
= floorf( player
.rewind_time
),
615 i1
= VG_MIN( i0
+1, player
.rewind_length
-1 );
617 struct rewind_frame
*fr
= &player
.rewind_buffer
[i0
],
618 *fr1
= &player
.rewind_buffer
[i1
];
620 float dist
= vg_maxf( v3_dist( fr
->pos
, fr1
->pos
), 0.001f
),
621 subl
= vg_fractf( player
.rewind_time
) + 0.001f
,
623 sramp
= 3.0f
-(1.0f
/(0.4f
+0.4f
*player
.rewind_time
)),
624 speed
= sramp
*28.0f
+ 0.5f
*player
.rewind_time
,
625 mod
= speed
* (budget
/ dist
),
627 advl
= vg_minf( mod
, subl
),
628 advt
= (advl
/ mod
) * budget
;
630 player
.dist_accum
+= speed
* advt
;
631 player
.rewind_time
-= advl
;
635 player
.rewind_time
= vg_maxf( 0.0f
, player
.rewind_time
);
637 float current_time
= vg
.time
- player
.diag_rewind_start
,
638 remaining
= player
.rewind_predicted_time
- current_time
;
640 if( player
.rewind_sound_wait
)
642 if( player
.rewind_predicted_time
>= 6.5f
)
644 if( remaining
<= 6.5f
)
647 audio_play_oneshot( &audio_rewind
[3], 1.0f
);
649 player
.rewind_sound_wait
= 0;
652 else if( player
.rewind_predicted_time
>= 2.5f
)
654 if( remaining
<= 2.5f
)
657 audio_play_oneshot( &audio_rewind
[2], 1.0f
);
659 player
.rewind_sound_wait
= 0;
662 else if( player
.rewind_predicted_time
>= 1.5f
)
664 if( remaining
<= 1.5f
)
667 audio_play_oneshot( &audio_rewind
[1], 1.0f
);
669 player
.rewind_sound_wait
= 0;
676 int i0
= floorf( player
.rewind_time
),
677 i1
= VG_MIN( i0
+1, player
.rewind_length
-1 );
679 struct rewind_frame
*fr
= &player
.rewind_buffer
[i0
],
680 *fr1
= &player
.rewind_buffer
[i1
];
682 float sub
= vg_fractf(player
.rewind_time
);
684 v3_lerp( fr
->pos
, fr1
->pos
, sub
, override_pos
);
685 override_angles
[0] = vg_alerpf( fr
->ang
[0], fr1
->ang
[0], sub
);
686 override_angles
[1] = vg_lerpf ( fr
->ang
[1], fr1
->ang
[1], sub
);
688 /* CAMERA POSITIONING: LAYER 1 */
689 float blend
= (4.0f
-player
.rewind_time
) * 0.25f
,
690 c
= vg_clampf( blend
, 0.0f
, 1.0f
);
692 camera_angles
[0] = vg_alerpf(override_angles
[0], player
.angles
[0], c
);
693 camera_angles
[1] = vg_lerpf (override_angles
[1], player
.angles
[1], c
);
694 v3_lerp( override_pos
, player
.camera_pos
, c
, camera_pos
);
702 VG_STATIC
void draw_player( m4x3f cam
)
705 player_model_copy_ragdoll();
707 shader_viewchar_use();
708 vg_tex2d_bind( &tex_characters
, 0 );
709 shader_viewchar_uTexMain( 0 );
710 shader_viewchar_uCamera( cam
[3] );
711 shader_viewchar_uPv( vg
.pv
);
712 shader_link_standard_ub( _shader_viewchar
.id
, 2 );
713 glUniformMatrix4x3fv( _uniform_viewchar_uTransforms
,
714 player
.mdl
.sk
.bone_count
,
716 (float *)player
.mdl
.sk
.final_mtx
);
718 mesh_bind( &player
.mdl
.player_meshes
[cl_playermdl_id
] );
719 mesh_draw( &player
.mdl
.player_meshes
[cl_playermdl_id
] );
723 * -----------------------------------------------------------------------------
725 * -----------------------------------------------------------------------------
728 VG_STATIC
float *player_get_pos(void)
730 return player
.phys
.rb
.co
;
733 VG_STATIC
void player_kill(void)
735 if( player
.death_tick_allowance
== 0 )
738 player_ragdoll_copy_model( player
.phys
.rb
.v
);
739 world_routes_clear();
743 VG_STATIC
float *player_cam_pos(void)
745 return player
.camera_pos
;
749 #endif /* PLAYER_H */