#include "skeleton.h"
#include "bvh.h"
-static float
+VG_STATIC float
k_walkspeed = 20.0f, /* no longer used */
k_runspeed = 20.0f,
k_board_radius = 0.3f,
k_walk_accel = 150.0f,
k_walk_friction = 8.0f;
-static int freecam = 0;
-static int walk_grid_iterations = 1;
-static float fc_speed = 10.0f;
+VG_STATIC int cl_playermdl_id = 0;
+VG_STATIC int freecam = 0;
+VG_STATIC int walk_grid_iterations = 1;
+VG_STATIC float fc_speed = 10.0f;
/*
* -----------------------------------------------------------------------------
* -----------------------------------------------------------------------------
*/
-static struct gplayer
+VG_STATIC struct gplayer
{
/* Physics */
rigidbody collide_front, collide_back;
inv_visual_transform;
int is_dead, death_tick_allowance, rewinding;
+ int rewind_sound_wait;
v3f land_target;
v3f land_target_log[22];
/* Camera */
float air_blend;
+ float air_time;
v3f camera_pos, smooth_localcam;
v2f angles;
u32 rewind_incrementer,
rewind_length;
- float rewind_time;
+ float rewind_time, rewind_total_length, rewind_predicted_time;
+ double diag_rewind_start, diag_rewind_time;
+ float dist_accum;
/* animation */
double jump_time;
/* player model */
struct player_model
{
- glmesh mesh;
+ glmesh player_meshes[3];
+
+ mdl_context meta;
struct skeleton sk;
struct skeleton_anim *anim_stand,
*anim_highg,
rigidbody rb;
u32 parent;
}
- *ragdoll;
+ ragdoll[32];
u32 ragdoll_count;
int shoes[2];
/*
* API
*/
-static float *player_get_pos(void);
-static void player_kill(void);
-static float *player_cam_pos(void);
-static void player_save_frame(void);
-static void player_restore_frame(void);
-static void player_save_rewind_frame(void);
+VG_STATIC float *player_get_pos(void);
+VG_STATIC void player_kill(void);
+VG_STATIC float *player_cam_pos(void);
+VG_STATIC void player_save_frame(void);
+VG_STATIC void player_restore_frame(void);
+VG_STATIC void player_save_rewind_frame(void);
/*
* Submodules
* -----------------------------------------------------------------------------
*/
-static void player_init(void) /* 1 */
+VG_STATIC void player_init(void) /* 1 */
{
rb_init( &player.phys.rb );
rb_init( &player.collide_front );
rb_init( &player.collide_back );
+ vg_convar_push( (struct vg_convar){
+ .name = "cl_playermdl_id",
+ .data = &cl_playermdl_id,
+ .data_type = k_convar_dtype_i32,
+ .opt_i32 = { .min=0, .max=2, .clamp=1 },
+ .persistent = 1
+ });
+
vg_convar_push( (struct vg_convar){
.name = "walk_speed",
.data = &k_walkspeed,
});
player.rewind_length = 0;
- player.rewind_buffer = vg_alloc( sizeof(struct rewind_frame)
- * PLAYER_REWIND_FRAMES );
+ player.rewind_buffer =
+ vg_linear_alloc( vg_mem.rtmemory,
+ sizeof(struct rewind_frame) * PLAYER_REWIND_FRAMES );
- /* other systems */
- vg_loader_highwater( player_model_init, player_model_free, NULL );
+ player_model_init();
}
-static void player_save_rewind_frame(void)
+VG_STATIC void player_save_rewind_frame(void)
{
if( player.rewind_length < PLAYER_REWIND_FRAMES )
{
v3_copy( player.camera_pos, fr->pos );
player.rewind_incrementer = 0;
+
+ if( player.rewind_length > 1 )
+ {
+ player.rewind_total_length +=
+ v3_dist( player.rewind_buffer[player.rewind_length-1].pos,
+ player.rewind_buffer[player.rewind_length-2].pos );
+ }
}
}
/* Deal with input etc */
-static void player_update_pre(void)
+VG_STATIC void player_update_pre(void)
{
struct player_phys *phys = &player.phys;
if( vg_get_button_down( "reset" ) )
{
- player.rewinding = 1;
- player.rewind_time = (float)player.rewind_length - 0.0001f;
- player_save_rewind_frame();
+ double delta = world.time - world.last_use;
- player.is_dead = 0;
- player.death_tick_allowance = 30;
- player_restore_frame();
-
- if( !phys->on_board )
+ if( (delta <= RESET_MAX_TIME) && (world.last_use != 0.0) )
{
- player.angles[0] = atan2f( -phys->rb.forward[2],
- -phys->rb.forward[0] );
- }
+ player.rewinding = 1;
+ player.rewind_sound_wait = 1;
+ player.rewind_time = (float)player.rewind_length - 0.0001f;
+ player_save_rewind_frame();
+ audio_lock();
+ audio_play_oneshot( &audio_rewind[0], 1.0f );
+ audio_unlock();
+
+ /* based on analytical testing. DONT CHANGE!
+ *
+ * time taken: y = (x^(4/5)) * 74.5
+ * inverse : x = (2/149)^(4/5) * y^(4/5)
+ */
+
+ float constant = powf( 2.0f/149.0f, 4.0f/5.0f ),
+ curve = powf( player.rewind_total_length, 4.0f/5.0f );
+
+ player.rewind_predicted_time = constant * curve;
+ player.diag_rewind_start = vg.time;
+ player.diag_rewind_time = player.rewind_time;
- player.mdl.shoes[0] = 1;
- player.mdl.shoes[1] = 1;
+ player.is_dead = 0;
+ player.death_tick_allowance = 30;
+ player_restore_frame();
- world_routes_notify_reset();
+ if( !phys->on_board )
+ {
+ player.angles[0] = atan2f( -phys->rb.forward[2],
+ -phys->rb.forward[0] );
+ }
- /* apply 1 frame of movement */
- player_do_motion();
+ player.mdl.shoes[0] = 1;
+ player.mdl.shoes[1] = 1;
+
+ world_routes_notify_reset();
+
+ /* apply 1 frame of movement */
+ player_do_motion();
+ }
}
if( vg_get_button_down( "switchmode" ) )
{
phys->on_board ^= 0x1;
+ audio_lock();
if( phys->on_board )
{
v3_muladds( phys->rb.v, phys->rb.forward, 0.2f, phys->rb.v );
+ audio_play_oneshot( &audio_lands[6], 1.0f );
+ }
+ else
+ {
+ audio_play_oneshot( &audio_lands[5], 1.0f );
}
+
+ audio_unlock();
}
}
-static void player_update_fixed(void) /* 2 */
+VG_STATIC void player_update_fixed(void) /* 2 */
{
if( player.rewinding )
return;
}
}
-static void player_update_post(void)
+VG_STATIC void player_update_post(void)
{
for( int i=0; i<player.land_log_count; i++ )
vg_line_cross( player.land_target_log[i],
{
if( player.rewind_time <= 0.0f )
{
+ double taken = vg.time - player.diag_rewind_start;
+ vg_success( "Rewind took (rt, pl, tl): %f, %f, %f\n",
+ taken, player.diag_rewind_time,
+ player.rewind_total_length );
+
player.rewinding = 0;
player.rewind_length = 1;
+ player.rewind_total_length = 0.0f;
+ player.rewind_incrementer = 0;
+ world.sky_target_rate = 1.0;
}
else
{
+ world.sky_target_rate = -100.0;
assert( player.rewind_length > 0 );
v2f override_angles;
v3f override_pos;
float budget = vg.time_delta,
- overall_length = player.rewind_length*0.25f;
+ overall_length = player.rewind_length;
+
+ world_routes_rollback_time( player.rewind_time / overall_length );
for( int i=0; (i<10)&&(player.rewind_time>0.0f)&&(budget>0.0f); i ++ )
{
advl = vg_minf( mod, subl ),
advt = (advl / mod) * budget;
-
+
+ player.dist_accum += speed * advt;
player.rewind_time -= advl;
budget -= advt;
}
player.rewind_time = vg_maxf( 0.0f, player.rewind_time );
+
+ float current_time = vg.time - player.diag_rewind_start,
+ remaining = player.rewind_predicted_time - current_time;
+
+ if( player.rewind_sound_wait )
+ {
+ if( player.rewind_predicted_time >= 6.5f )
+ {
+ if( remaining <= 6.5f )
+ {
+ audio_lock();
+ audio_play_oneshot( &audio_rewind[3], 1.0f );
+ audio_unlock();
+ player.rewind_sound_wait = 0;
+ }
+ }
+ else if( player.rewind_predicted_time >= 2.5f )
+ {
+ if( remaining <= 2.5f )
+ {
+ audio_lock();
+ audio_play_oneshot( &audio_rewind[2], 1.0f );
+ audio_unlock();
+ player.rewind_sound_wait = 0;
+ }
+ }
+ else if( player.rewind_predicted_time >= 1.5f )
+ {
+ if( remaining <= 1.5f )
+ {
+ audio_lock();
+ audio_play_oneshot( &audio_rewind[1], 1.0f );
+ audio_unlock();
+ player.rewind_sound_wait = 0;
+ }
+ }
+
+
+ }
int i0 = floorf( player.rewind_time ),
i1 = VG_MIN( i0+1, player.rewind_length-1 );
player_audio();
}
-static void draw_player( m4x3f cam )
+VG_STATIC void draw_player( m4x3f cam )
{
if( player.is_dead )
player_model_copy_ragdoll();
0,
(float *)player.mdl.sk.final_mtx );
- mesh_bind( &player.mdl.mesh );
- mesh_draw( &player.mdl.mesh );
+ mesh_bind( &player.mdl.player_meshes[cl_playermdl_id] );
+ mesh_draw( &player.mdl.player_meshes[cl_playermdl_id] );
}
/*
* -----------------------------------------------------------------------------
*/
-static float *player_get_pos(void)
+VG_STATIC float *player_get_pos(void)
{
return player.phys.rb.co;
}
-static void player_kill(void)
+VG_STATIC void player_kill(void)
{
if( player.death_tick_allowance == 0 )
{
}
}
-static float *player_cam_pos(void)
+VG_STATIC float *player_cam_pos(void)
{
return player.camera_pos;
}