2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
8 #define PLAYER_REWIND_FRAMES 60*4
17 k_walkspeed
= 20.0f
, /* no longer used */
19 k_board_radius
= 0.3f
,
20 k_board_length
= 0.45f
,
21 k_board_allowance
= 0.04f
,
22 //k_friction_lat = 8.8f,
23 k_friction_lat
= 12.0f
,
24 k_friction_resistance
= 0.01f
,
25 k_max_push_speed
= 16.0f
,
27 k_push_cycle_rate
= 8.0f
,
28 k_steer_ground
= 2.5f
,
30 k_steer_air_lerp
= 0.3f
,
33 k_walk_downforce
= 8.0f
,
34 k_jump_charge_speed
= (1.0f
/1.0f
),
38 k_walk_accel
= 150.0f
,
39 k_walk_friction
= 8.0f
;
41 VG_STATIC
int cl_playermdl_id
= 0;
42 VG_STATIC
int freecam
= 0;
43 VG_STATIC
int walk_grid_iterations
= 1;
44 VG_STATIC
float fc_speed
= 10.0f
;
47 * -----------------------------------------------------------------------------
49 * -----------------------------------------------------------------------------
52 VG_STATIC
struct gplayer
55 rigidbody collide_front
, collide_back
;
59 rigidbody rb
, rb_gate_frame
;
60 float iY
, siY
; /* Yaw inertia */
62 v3f a
, v_last
, m
, bob
, vl
;
65 float vswitch
, slip
, slip_last
,
68 float grab
, jump
, pushing
, push_time
;
70 int in_air
, on_board
, jump_charge
, jump_dir
;
77 m4x3f visual_transform
,
80 int is_dead
, death_tick_allowance
, rewinding
;
81 int rewind_sound_wait
;
84 v3f land_target_log
[22];
85 u32 land_target_colours
[22];
88 v3f handl_target
, handr_target
,
95 v3f camera_pos
, smooth_localcam
;
104 u32 rewind_incrementer
,
107 float rewind_time
, rewind_total_length
, rewind_predicted_time
;
108 double diag_rewind_start
, diag_rewind_time
;
131 glmesh player_meshes
[3];
135 struct skeleton_anim
*anim_stand
,
139 *anim_push
, *anim_push_reverse
,
140 *anim_ollie
, *anim_ollie_reverse
,
141 *anim_grabs
, *anim_stop
,
142 *anim_walk
, *anim_run
, *anim_idle
,
174 .collide_front
= { .type
= k_rb_shape_sphere
, .inf
.sphere
.radius
= 0.3f
},
175 .collide_back
= { .type
= k_rb_shape_sphere
, .inf
.sphere
.radius
= 0.3f
}
181 VG_STATIC
float *player_get_pos(void);
182 VG_STATIC
void player_kill(void);
183 VG_STATIC
float *player_cam_pos(void);
184 VG_STATIC
void player_save_frame(void);
185 VG_STATIC
void player_restore_frame(void);
186 VG_STATIC
void player_save_rewind_frame(void);
191 #include "player_physics.h"
192 #include "player_ragdoll.h"
193 #include "player_model.h"
194 #include "player_animation.h"
195 #include "player_audio.h"
198 * -----------------------------------------------------------------------------
200 * -----------------------------------------------------------------------------
203 VG_STATIC
void player_init(void) /* 1 */
205 rb_init( &player
.phys
.rb
);
206 rb_init( &player
.collide_front
);
207 rb_init( &player
.collide_back
);
209 vg_convar_push( (struct vg_convar
){
210 .name
= "cl_playermdl_id",
211 .data
= &cl_playermdl_id
,
212 .data_type
= k_convar_dtype_i32
,
213 .opt_i32
= { .min
=0, .max
=2, .clamp
=1 },
217 vg_convar_push( (struct vg_convar
){
218 .name
= "walk_speed",
219 .data
= &k_walkspeed
,
220 .data_type
= k_convar_dtype_f32
,
221 .opt_f32
= { .clamp
= 0 },
225 vg_convar_push( (struct vg_convar
){
228 .data_type
= k_convar_dtype_f32
,
229 .opt_f32
= { .clamp
= 0 },
233 vg_convar_push( (struct vg_convar
){
234 .name
= "walk_accel",
235 .data
= &k_walk_accel
,
236 .data_type
= k_convar_dtype_f32
,
237 .opt_f32
= { .clamp
= 0 },
241 vg_convar_push( (struct vg_convar
){
244 .data_type
= k_convar_dtype_i32
,
245 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
249 vg_convar_push( (struct vg_convar
){
252 .data_type
= k_convar_dtype_f32
,
253 .opt_f32
= { .clamp
= 0 },
257 vg_function_push( (struct vg_cmd
){
259 .function
= reset_player
262 player
.rewind_length
= 0;
263 player
.rewind_buffer
=
264 vg_linear_alloc( vg_mem
.rtmemory
,
265 sizeof(struct rewind_frame
) * PLAYER_REWIND_FRAMES
);
270 VG_STATIC
void player_save_rewind_frame(void)
272 if( player
.rewind_length
< PLAYER_REWIND_FRAMES
)
274 struct rewind_frame
*fr
=
275 &player
.rewind_buffer
[ player
.rewind_length
++ ];
277 v2_copy( player
.angles
, fr
->ang
);
278 v3_copy( player
.camera_pos
, fr
->pos
);
280 player
.rewind_incrementer
= 0;
282 if( player
.rewind_length
> 1 )
284 player
.rewind_total_length
+=
285 v3_dist( player
.rewind_buffer
[player
.rewind_length
-1].pos
,
286 player
.rewind_buffer
[player
.rewind_length
-2].pos
);
291 /* Deal with input etc */
292 VG_STATIC
void player_update_pre(void)
294 struct player_phys
*phys
= &player
.phys
;
296 if( player
.rewinding
)
301 if( vg_get_button_down( "reset" ) )
303 double delta
= world
.time
- world
.last_use
;
305 if( (delta
<= RESET_MAX_TIME
) && (world
.last_use
!= 0.0) )
307 player
.rewinding
= 1;
308 player
.rewind_sound_wait
= 1;
309 player
.rewind_time
= (float)player
.rewind_length
- 0.0001f
;
310 player_save_rewind_frame();
312 audio_play_oneshot( &audio_rewind
[0], 1.0f
);
315 /* based on analytical testing. DONT CHANGE!
317 * time taken: y = (x^(4/5)) * 74.5
318 * inverse : x = (2/149)^(4/5) * y^(4/5)
321 float constant
= powf( 2.0f
/149.0f
, 4.0f
/5.0f
),
322 curve
= powf( player
.rewind_total_length
, 4.0f
/5.0f
);
324 player
.rewind_predicted_time
= constant
* curve
;
325 player
.diag_rewind_start
= vg
.time
;
326 player
.diag_rewind_time
= player
.rewind_time
;
329 player
.death_tick_allowance
= 30;
330 player_restore_frame();
332 if( !phys
->on_board
)
334 player
.angles
[0] = atan2f( -phys
->rb
.forward
[2],
335 -phys
->rb
.forward
[0] );
338 player
.mdl
.shoes
[0] = 1;
339 player
.mdl
.shoes
[1] = 1;
341 world_routes_notify_reset();
343 /* apply 1 frame of movement */
348 if( vg_get_button_down( "switchmode" ) )
350 phys
->on_board
^= 0x1;
355 v3_muladds( phys
->rb
.v
, phys
->rb
.forward
, 0.2f
, phys
->rb
.v
);
356 audio_play_oneshot( &audio_lands
[6], 1.0f
);
360 audio_play_oneshot( &audio_lands
[5], 1.0f
);
367 VG_STATIC
void player_update_fixed(void) /* 2 */
369 if( player
.rewinding
)
372 if( player
.death_tick_allowance
)
373 player
.death_tick_allowance
--;
375 struct player_phys
*phys
= &player
.phys
;
379 player_ragdoll_iter();
383 player
.rewind_incrementer
++;
385 if( player
.rewind_incrementer
> (u32
)(0.25/VG_TIMESTEP_FIXED
) )
387 player_save_rewind_frame();
394 VG_STATIC
void player_update_post(void)
396 for( int i
=0; i
<player
.land_log_count
; i
++ )
397 vg_line_cross( player
.land_target_log
[i
],
398 player
.land_target_colours
[i
], 0.25f
);
402 player_debug_ragdoll();
405 player_animate_death_cam();
412 player_animate_camera();
419 /* CAMERA POSITIONING: LAYER 0 */
420 v2_copy( player
.angles
, camera_angles
);
421 v3_copy( player
.camera_pos
, camera_pos
);
423 if( player
.rewinding
)
425 if( player
.rewind_time
<= 0.0f
)
427 double taken
= vg
.time
- player
.diag_rewind_start
;
428 vg_success( "Rewind took (rt, pl, tl): %f, %f, %f\n",
429 taken
, player
.diag_rewind_time
,
430 player
.rewind_total_length
);
432 player
.rewinding
= 0;
433 player
.rewind_length
= 1;
434 player
.rewind_total_length
= 0.0f
;
435 player
.rewind_incrementer
= 0;
436 world
.sky_target_rate
= 1.0;
440 world
.sky_target_rate
= -100.0;
441 assert( player
.rewind_length
> 0 );
446 float budget
= vg
.time_delta
,
447 overall_length
= player
.rewind_length
;
449 world_routes_rollback_time( player
.rewind_time
/ overall_length
);
451 for( int i
=0; (i
<10)&&(player
.rewind_time
>0.0f
)&&(budget
>0.0f
); i
++ )
453 /* Interpolate frames */
454 int i0
= floorf( player
.rewind_time
),
455 i1
= VG_MIN( i0
+1, player
.rewind_length
-1 );
457 struct rewind_frame
*fr
= &player
.rewind_buffer
[i0
],
458 *fr1
= &player
.rewind_buffer
[i1
];
460 float dist
= vg_maxf( v3_dist( fr
->pos
, fr1
->pos
), 0.001f
),
461 subl
= vg_fractf( player
.rewind_time
) + 0.001f
,
463 sramp
= 3.0f
-(1.0f
/(0.4f
+0.4f
*player
.rewind_time
)),
464 speed
= sramp
*28.0f
+ 0.5f
*player
.rewind_time
,
465 mod
= speed
* (budget
/ dist
),
467 advl
= vg_minf( mod
, subl
),
468 advt
= (advl
/ mod
) * budget
;
470 player
.dist_accum
+= speed
* advt
;
471 player
.rewind_time
-= advl
;
476 if( player
.dist_accum
>= 5.0f
)
479 audio_player_playclip( &audio_rewind_player
, &audio_rewind
[4] );
482 player
.dist_accum
-= 5.0f
;
486 player
.rewind_time
= vg_maxf( 0.0f
, player
.rewind_time
);
488 float current_time
= vg
.time
- player
.diag_rewind_start
,
489 remaining
= player
.rewind_predicted_time
- current_time
;
491 if( player
.rewind_sound_wait
)
493 if( player
.rewind_predicted_time
>= 6.5f
)
495 if( remaining
<= 6.5f
)
498 audio_play_oneshot( &audio_rewind
[3], 1.0f
);
500 player
.rewind_sound_wait
= 0;
503 else if( player
.rewind_predicted_time
>= 2.5f
)
505 if( remaining
<= 2.5f
)
508 audio_play_oneshot( &audio_rewind
[2], 1.0f
);
510 player
.rewind_sound_wait
= 0;
513 else if( player
.rewind_predicted_time
>= 1.5f
)
515 if( remaining
<= 1.5f
)
518 audio_play_oneshot( &audio_rewind
[1], 1.0f
);
520 player
.rewind_sound_wait
= 0;
527 int i0
= floorf( player
.rewind_time
),
528 i1
= VG_MIN( i0
+1, player
.rewind_length
-1 );
530 struct rewind_frame
*fr
= &player
.rewind_buffer
[i0
],
531 *fr1
= &player
.rewind_buffer
[i1
];
533 float sub
= vg_fractf(player
.rewind_time
);
535 v3_lerp( fr
->pos
, fr1
->pos
, sub
, override_pos
);
536 override_angles
[0] = vg_alerpf( fr
->ang
[0], fr1
->ang
[0], sub
);
537 override_angles
[1] = vg_lerpf ( fr
->ang
[1], fr1
->ang
[1], sub
);
539 /* CAMERA POSITIONING: LAYER 1 */
540 float blend
= (4.0f
-player
.rewind_time
) * 0.25f
,
541 c
= vg_clampf( blend
, 0.0f
, 1.0f
);
543 camera_angles
[0] = vg_alerpf(override_angles
[0], player
.angles
[0], c
);
544 camera_angles
[1] = vg_lerpf (override_angles
[1], player
.angles
[1], c
);
545 v3_lerp( override_pos
, player
.camera_pos
, c
, camera_pos
);
553 VG_STATIC
void draw_player( m4x3f cam
)
556 player_model_copy_ragdoll();
558 shader_viewchar_use();
559 vg_tex2d_bind( &tex_characters
, 0 );
560 shader_viewchar_uTexMain( 0 );
561 shader_viewchar_uCamera( cam
[3] );
562 shader_viewchar_uPv( vg
.pv
);
563 shader_link_standard_ub( _shader_viewchar
.id
, 2 );
564 glUniformMatrix4x3fv( _uniform_viewchar_uTransforms
,
565 player
.mdl
.sk
.bone_count
,
567 (float *)player
.mdl
.sk
.final_mtx
);
569 mesh_bind( &player
.mdl
.player_meshes
[cl_playermdl_id
] );
570 mesh_draw( &player
.mdl
.player_meshes
[cl_playermdl_id
] );
574 * -----------------------------------------------------------------------------
576 * -----------------------------------------------------------------------------
579 VG_STATIC
float *player_get_pos(void)
581 return player
.phys
.rb
.co
;
584 VG_STATIC
void player_kill(void)
586 if( player
.death_tick_allowance
== 0 )
589 player_ragdoll_copy_model( player
.phys
.rb
.v
);
593 VG_STATIC
float *player_cam_pos(void)
595 return player
.camera_pos
;
599 #endif /* PLAYER_H */