YEAH
[carveJwlIkooP6JGAAIwe30JlM.git] / player_skate.c
index 3a78f4f9b3fed274b95417904edb590a05bba123..1f99991b1846841b16540ecef2a2e1cd7df8fd49 100644 (file)
@@ -11,6 +11,8 @@ VG_STATIC void player__skate_bind( player_instance *player )
    struct skeleton *sk = &av->sk;
 
    rb_update_transform( &player->rb );
+   s->anim_grind           = skeleton_get_anim( sk, "pose_grind" );
+   s->anim_grind_jump      = skeleton_get_anim( sk, "pose_grind_jump" );
    s->anim_stand           = skeleton_get_anim( sk, "pose_stand" );
    s->anim_highg           = skeleton_get_anim( sk, "pose_highg" );
    s->anim_air             = skeleton_get_anim( sk, "pose_air" );
@@ -405,6 +407,19 @@ void player__approximate_best_trajectory( player_instance *player )
    int grind_located = 0;
    float grind_located_gravity = k_gravity;
 
+
+   v3f launch_v_bounds[2];
+
+   for( int i=0; i<2; i++ ){
+      v3_copy( player->rb.v, launch_v_bounds[i] );
+      float ang = (float[]){ angle_begin, angle_end }[ i ];
+            ang *= 0.15f;
+
+      v4f qbias;
+      q_axis_angle( qbias, axis, ang );
+      q_mulv( qbias, launch_v_bounds[i], launch_v_bounds[i] );
+   }
+
    for( int m=0;m<=30; m++ ){
       jump_info *inf = &s->possible_jumps[ s->possible_jump_count ++ ];
       reset_jump_info( inf );
@@ -444,35 +459,59 @@ void player__approximate_best_trajectory( player_instance *player )
          v3_add( launch_co, co1, co1 );
 
          float launch_vy = v3_dot( launch_v,basis[1] );
-         if( !grind_located && (launch_vy - gravity*t < 0.0f) ){
-            v3f closest;
+
+         int search_for_grind = 1;
+         if( grind_located ) search_for_grind = 0;
+         if( launch_vy - gravity*t > 0.0f ) search_for_grind = 0;
+
+         /* TODO Cleanup */
+
+         v3f closest;
+         if( search_for_grind ){
             if( bh_closest_point( world->geo_bh, co1, closest, 1.0f ) != -1 ){
-               v3f ve;
-               v3_copy( launch_v, ve );
-               v3_muladds( ve, basis[1], -gravity * t, ve );
+               v3f bound[2];
 
-               if( skate_grind_scansq( player, closest, ve, 0.5f, &grind ) ){
-                  /* check alignment */
-                  v2f v0 = { v3_dot( ve, basis[0] ), 
-                             v3_dot( ve, basis[2] ) },
-                      v1 = { v3_dot( grind.dir, basis[0] ), 
-                             v3_dot( grind.dir, basis[2] ) };
+               for( int j=0; j<2; j++ ){
+                  v3_muls( launch_v_bounds[j], t, bound[j] );
+                  v3_muladds( bound[j], basis[1], -0.5f*gravity*t*t, bound[j] );
+                  v3_add( launch_co, bound[j], bound[j] );
+               }
 
-                  v2_normalize( v0 );
-                  v2_normalize( v1 );
+               float minh = vg_minf( bound[0][1], bound[1][1] ),
+                     maxh = vg_maxf( bound[0][1], bound[1][1] );
 
-                  float a = v2_dot( v0, v1 );
+               vg_info( "%f [%f:%f]\n", closest[1], minh, maxh );
 
-#if 0
-                  if( a >= cosf( VG_PIf * /*0.185f*/ 0.02f ) ){
-#endif
-                     grind_located = 1;
-                     grind_located_gravity = inf->gravity;
+               if( (closest[1] < minh) || (closest[1] > maxh) ){
+                  search_for_grind = 0;
+               }
+            }
+            else
+               search_for_grind = 0;
+         }
 
-                     vg_success( "Grind located\n" );
-#if 0
-                  }
-#endif
+         if( search_for_grind ){
+            v3f ve;
+            v3_copy( launch_v, ve );
+            v3_muladds( ve, basis[1], -gravity * t, ve );
+
+            if( skate_grind_scansq( player, closest, ve, 0.5f, &grind ) ){
+               /* check alignment */
+               v2f v0 = { v3_dot( ve, basis[0] ), 
+                          v3_dot( ve, basis[2] ) },
+                   v1 = { v3_dot( grind.dir, basis[0] ), 
+                          v3_dot( grind.dir, basis[2] ) };
+
+               v2_normalize( v0 );
+               v2_normalize( v1 );
+
+               float a = v2_dot( v0, v1 );
+
+               if( a >= cosf( VG_PIf * 0.185f ) ){
+                  grind_located = 1;
+                  grind_located_gravity = inf->gravity;
+
+                  vg_success( "Grind located\n" );
                }
             }
          }
@@ -887,8 +926,11 @@ VG_STATIC void skate_apply_friction_model( player_instance *player )
    s->state.slip = slip;
    s->state.reverse = -vg_signf(vel[2]);
 
-   vel[0] += vg_cfrictf( vel[0], k_friction_lat * k_rb_delta );
-   vel[2] += vg_cfrictf( vel[2], k_friction_resistance * k_rb_delta );
+   float S = (float)s->grind_cooldown * (1.0f/20.0f);
+         S = vg_minf( S, 1.0f );
+
+   vel[0] += vg_cfrictf( vel[0], S * k_friction_lat * k_rb_delta );
+   vel[2] += vg_cfrictf( vel[2], S * k_friction_resistance * k_rb_delta );
 
    /* Pushing additive force */
 
@@ -1610,7 +1652,6 @@ VG_STATIC void skate_5050_apply( player_instance *player,
    v3_normalize( axis );
 
    v3_cross( axis, inf_avg.dir, inf_avg.n );
-   
    skate_grind_decay( player, &inf_avg, 1.0f );
 
 
@@ -1778,7 +1819,7 @@ VG_STATIC void skate_boardslide_apply( player_instance *player,
                intersection );
    v3_copy( intersection, s->weight_distribution );
 
-   skate_grind_decay( player, inf, 0.1f );
+   skate_grind_decay( player, inf, 0.0125f );
    skate_grind_friction( player, inf, 0.25f );
 
    /* direction alignment */
@@ -1790,6 +1831,10 @@ VG_STATIC void skate_boardslide_apply( player_instance *player,
    m3x3_mulv( player->rb.to_world, dir, dir );
    m3x3_mulv( player->rb.to_world, perp, perp );
 
+   v4f qbalance;
+   q_axis_angle( qbalance, dir, local_co[0]*k_grind_balance );
+   q_mulv( qbalance, perp, perp );
+
    rb_effect_spring_target_vector( &player->rb, player->rb.to_world[0],
                                     dir, 
                                     k_grind_spring, k_grind_dampener,
@@ -1941,24 +1986,20 @@ VG_STATIC enum skate_activity skate_availible_grind( player_instance *player )
    }
    , new_activity = table[ res_slide << 2 | res_back50 << 1 | res_front50 ];
 
-   if(      new_activity == k_skate_activity_undefined )
-   {
+   if(      new_activity == k_skate_activity_undefined ){
       if( s->state.activity >= k_skate_activity_grind_any )
          s->grind_cooldown = 5;
    }
-   else if( new_activity == k_skate_activity_grind_boardslide )
-   {
+   else if( new_activity == k_skate_activity_grind_boardslide ){
       skate_boardslide_apply( player, &inf_slide );
    }
-   else if( new_activity == k_skate_activity_grind_back50 )
-   {
+   else if( new_activity == k_skate_activity_grind_back50 ){
       if( s->state.activity != k_skate_activity_grind_back50 )
          skate_store_grind_vec( player, &inf_back50 );
 
       skate_grind_truck_apply( player,  1.0f, &inf_back50, 1.0f );
    }
-   else if( new_activity == k_skate_activity_grind_front50 )
-   {
+   else if( new_activity == k_skate_activity_grind_front50 ){
       if( s->state.activity != k_skate_activity_grind_front50 )
          skate_store_grind_vec( player, &inf_front50 );
 
@@ -2127,8 +2168,7 @@ begin_collision:;
    v4f future_q;
    v3_muladds( player->rb.co, player->rb.v, s->substep, future_co );
 
-   if( v3_length2( player->rb.w ) > 0.0f )
-   {
+   if( v3_length2( player->rb.w ) > 0.0f ){
       v4f rotation;
       v3f axis;
       v3_copy( player->rb.w, axis );
@@ -2564,6 +2604,9 @@ VG_STATIC void player__skate_animate( player_instance *player,
             fly  = iair?                    1.0f: 0.0f,
             wdist= s->weight_distribution[2] / k_board_length;
 
+      if( s->state.activity >= k_skate_activity_grind_any )
+         wdist = 0.0f;
+
       s->blend_z     = vg_lerpf( s->blend_z,      dirz,  2.4f*vg.time_delta );
       s->blend_x     = vg_lerpf( s->blend_x,      dirx,  0.6f*vg.time_delta );
       s->blend_fly   = vg_lerpf( s->blend_fly,    fly,   3.4f*vg.time_delta );
@@ -2664,6 +2707,31 @@ VG_STATIC void player__skate_animate( player_instance *player,
 
    skeleton_lerp_pose( sk, ground_pose, air_pose, s->blend_fly, dest->pose );
 
+
+   mdl_keyframe grind_pose[32];
+   {
+      /* TODO: factor balance into this sampler */
+      float grind_frame = 0.5f;
+
+      if( s->state.activity == k_skate_activity_grind_front50 ){
+         grind_frame = 0.0f;
+      } else if( s->state.activity == k_skate_activity_grind_back50 ){
+         grind_frame = 1.0f;
+      }
+
+      float grind=s->state.activity >= k_skate_activity_grind_any? 1.0f: 0.0f;
+      s->blend_grind = vg_lerpf( s->blend_grind,  grind, 5.0f*vg.time_delta );
+      s->blend_grind_balance=vg_lerpf( s->blend_grind_balance, 
+                                       grind_frame, 5.0f*vg.time_delta );
+
+      grind_frame = s->blend_grind_balance * (15.0f/30.0f);
+
+      skeleton_sample_anim( sk, s->anim_grind, grind_frame, apose );
+      skeleton_sample_anim( sk, s->anim_grind_jump, grind_frame, bpose );
+      skeleton_lerp_pose( sk, apose, bpose, s->blend_jump, grind_pose );
+   }
+   skeleton_lerp_pose( sk, dest->pose, grind_pose, s->blend_grind, dest->pose );
+
    float add_grab_mod = 1.0f - s->blend_fly;
 
    /* additive effects */
@@ -2789,9 +2857,10 @@ VG_STATIC void player__skate_animate( player_instance *player,
 
       float jump_t = vg.time-s->state.jump_time;
 
-      float k=10.0f;
+      float k=17.0f;
       float h = k*jump_t;
       float extra = h*exp(1.0-h) * (s->state.jump_dir?1.0f:-1.0f);
+            extra *= s->state.slap * 4.0f;
 
       q_axis_angle( qyaw,   (v3f){0.0f,1.0f,0.0f}, euler[0] * 0.5f );
       q_axis_angle( qpitch, (v3f){1.0f,0.0f,0.0f}, euler[1] + extra );