logic
[carveJwlIkooP6JGAAIwe30JlM.git] / player_skate.c
index aae8280f5b30a006fe00172717bf01a7e8d8dce6..744b5eb050ca27c7fb5c040c21cffb2843b0aabf 100644 (file)
@@ -2,6 +2,7 @@
 #define PLAYER_SKATE_C
 
 #include "player.h"
+#include "audio.h"
 
 VG_STATIC void player__skate_bind( player_instance *player )
 {
@@ -35,8 +36,10 @@ VG_STATIC int skate_collide_smooth( player_instance *player,
                                     m4x3f mtx, rb_sphere *sphere,
                                     rb_ct *man )
 {
+   world_instance *world = get_active_world();
+
    int len = 0;
-   len = rb_sphere__scene( mtx, sphere, NULL, &world.rb_geo.inf.scene, man );
+   len = rb_sphere__scene( mtx, sphere, NULL, &world->rb_geo.inf.scene, man );
 
    for( int i=0; i<len; i++ )
    {
@@ -70,6 +73,8 @@ VG_STATIC int skate_grind_scansq( player_instance *player,
                                   v3f pos, v3f dir, float r,
                                   struct grind_info *inf )
 {
+   world_instance *world = get_active_world();
+
    v4f plane;
    v3_copy( dir, plane );
    v3_normalize( plane );
@@ -100,17 +105,17 @@ VG_STATIC int skate_grind_scansq( player_instance *player,
    v3_cross( plane, player->basis[1], support_axis );
    v3_normalize( support_axis );
    
-   while( bh_next( world.geo_bh, &it, box, &idx ) )
+   while( bh_next( world->geo_bh, &it, box, &idx ) )
    {
-      u32 *ptri = &world.scene_geo->arrindices[ idx*3 ];
+      u32 *ptri = &world->scene_geo->arrindices[ idx*3 ];
       v3f tri[3];
 
-      struct world_material *mat = world_tri_index_material(ptri[0]);
+      struct world_material *mat = world_tri_index_material(world,ptri[0]);
       if( !(mat->info.flags & k_material_flag_skate_surface) )
          continue;
 
       for( int j=0; j<3; j++ )
-         v3_copy( world.scene_geo->arrvertices[ptri[j]].co, tri[j] );
+         v3_copy( world->scene_geo->arrvertices[ptri[j]].co, tri[j] );
 
       for( int j=0; j<3; j++ )
       {
@@ -323,6 +328,8 @@ VG_STATIC int solve_prediction_for_target( player_instance *player,
 VG_STATIC 
 void player__approximate_best_trajectory( player_instance *player )
 {
+   world_instance *world = get_active_world();
+
    struct player_skate *s = &player->_skate;
    float k_trace_delta = k_rb_delta * 10.0f;
 
@@ -390,7 +397,7 @@ void player__approximate_best_trajectory( player_instance *player )
          if( !grind_located && (launch_vy - gravity*t < 0.0f) )
          {
             v3f closest;
-            if( bh_closest_point( world.geo_bh, co1, closest, 1.0f ) != -1 )
+            if( bh_closest_point( world->geo_bh, co1, closest, 1.0f ) != -1 )
             {
                v3f ve;
                v3_copy( launch_v, ve );
@@ -420,7 +427,7 @@ void player__approximate_best_trajectory( player_instance *player )
          float t1;
          v3f n;
 
-         int idx = spherecast_world( co0, co1, k_board_radius, &t1, n );
+         int idx = spherecast_world( world, co0, co1, k_board_radius, &t1, n );
          if( idx != -1 )
          {
             v3f co;
@@ -444,8 +451,9 @@ void player__approximate_best_trajectory( player_instance *player )
             p->score = -v3_dot( ve, p->n );
             p->land_dist = t + k_trace_delta * t1;
 
-            u32 vert_index = world.scene_geo->arrindices[ idx*3 ];
-            struct world_material *mat = world_tri_index_material( vert_index );
+            u32 vert_index = world->scene_geo->arrindices[ idx*3 ];
+            struct world_material *mat = 
+               world_tri_index_material( world, vert_index );
             
             /* Bias prediction towords ramps */
             if( !(mat->info.flags & k_material_flag_skate_surface) )
@@ -844,7 +852,7 @@ VG_STATIC void skate_apply_jump_model( player_instance *player )
       v2f steer = { player->input_js1h->axis.value,
                     player->input_js1v->axis.value };
       v2_normalize_clamp( steer );
-
+      skate_apply_air_model( player );
 
 #if 0
       float maxspin = k_steer_air * k_rb_delta * k_spin_boost;
@@ -853,15 +861,9 @@ VG_STATIC void skate_apply_jump_model( player_instance *player )
       s->state.lift_frames ++;
 #endif
 
-      /* FIXME audio events */
-#if 0
       audio_lock();
-      audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
-      audio_player_set_position( &audio_player_extra, player.rb.co );
-      audio_player_set_vol( &audio_player_extra, 20.0f );
-      audio_player_playclip( &audio_player_extra, &audio_jumps[rand()%2] );
+      audio_oneshot_3d( &audio_jumps[rand()%2], player->rb.co, 40.0f, 1.0f );
       audio_unlock();
-#endif
    }
 }
 
@@ -869,6 +871,12 @@ VG_STATIC void skate_apply_pump_model( player_instance *player )
 {
    struct player_skate *s = &player->_skate;
 
+   if( s->state.activity != k_skate_activity_ground )
+   {
+      v3_zero( s->state.throw_v );
+      return;
+   }
+
    /* Throw / collect routine 
     *
     * TODO: Max speed boost
@@ -1064,6 +1072,70 @@ VG_STATIC void player__skate_post_update( player_instance *player )
 #if 0
    vg_line_pt3( s->state.apex, 0.030f, 0xff0000ff );
 #endif
+
+   audio_lock();
+
+   float air   = s->state.activity == k_skate_activity_air? 1.0f: 0.0f,
+         speed = v3_length( player->rb.v ),
+         attn  = vg_minf( 1.0f, speed*0.1f ),
+         slide = vg_clampf( fabsf(s->state.slip), 0.0f, 1.0f ),
+
+         vol_main    = sqrtf( (1.0f-air)*attn*(1.0f-slide) * 0.4f ),
+         vol_air     = sqrtf(       air *attn * 0.5f ),
+         vol_slide   = sqrtf( (1.0f-air)*attn*slide * 0.25f );
+
+   const u32 flags = AUDIO_FLAG_SPACIAL_3D|AUDIO_FLAG_LOOP;
+   if( !s->aud_main )
+      s->aud_main = audio_request_channel( &audio_board[0], flags );
+
+   if( !s->aud_air )
+      s->aud_air = audio_request_channel( &audio_board[1], flags );
+
+   if( !s->aud_slide )
+      s->aud_slide = audio_request_channel( &audio_board[2], flags );
+
+
+   /* brrrrrrrrrrrt sound for tiles and stuff 
+    * --------------------------------------------------------*/
+   float sidechain_amt = 0.0f,
+         hz            = speed * 2.0f;
+
+   if( s->surface == k_surface_prop_tiles )
+      sidechain_amt = 1.0f;
+   else
+      sidechain_amt = 0.0f;
+
+   audio_set_lfo_frequency( 0, hz );
+   audio_set_lfo_wave( 0, k_lfo_polynomial_bipolar, 
+                        vg_lerpf( 250.0f, 80.0f, attn ) );
+
+   if( s->aud_main )
+   {
+      s->aud_main->colour = 0x00103efe;
+      audio_channel_set_spacial( s->aud_main, player->rb.co, 40.0f );
+      audio_channel_slope_volume( s->aud_main, 0.05f, vol_main );
+      audio_channel_sidechain_lfo( s->aud_main, 0, sidechain_amt );
+
+      float rate = 1.0f + (attn-0.5f)*0.2f;
+      audio_channel_set_sampling_rate( s->aud_main, rate );
+   }
+
+   if( s->aud_slide )
+   {
+      s->aud_slide->colour = 0x00103efe;
+      audio_channel_set_spacial( s->aud_slide, player->rb.co, 40.0f );
+      audio_channel_slope_volume( s->aud_slide, 0.05f, vol_slide );
+      audio_channel_sidechain_lfo( s->aud_slide, 0, sidechain_amt );
+   }
+
+   if( s->aud_air )
+   {
+      s->aud_air->colour = 0x00103efe;
+      audio_channel_set_spacial( s->aud_air, player->rb.co, 40.0f );
+      audio_channel_slope_volume( s->aud_air, 0.05f, vol_air );
+   }
+
+   audio_unlock();
 }
 
 /*
@@ -1080,6 +1152,7 @@ int skate_compute_surface_alignment( player_instance *player,
                                      v3f surface_normal, v3f axel_dir )
 {
    struct player_skate *s = &player->_skate;
+   world_instance *world = get_active_world();
 
    v3f truck, left, right;
    m4x3_mulv( player->rb.to_world, ra, truck );
@@ -1104,7 +1177,7 @@ int skate_compute_surface_alignment( player_instance *player,
       v3_muladds( left,  player->rb.to_world[1],  k_board_radius,   left );
       ray_l.dist = 2.1f * k_board_radius;
 
-      res_l = ray_world( left, dir, &ray_l );
+      res_l = ray_world( world, left, dir, &ray_l );
 
       if( res_l )
          break;
@@ -1117,7 +1190,7 @@ int skate_compute_surface_alignment( player_instance *player,
       v3_muladds( right, player->rb.to_world[1],  k_board_radius,   right );
       ray_r.dist = 2.1f * k_board_radius;
 
-      res_r = ray_world( right, dir, &ray_r );
+      res_r = ray_world( world, right, dir, &ray_r );
 
       if( res_r )
          break;
@@ -1155,15 +1228,15 @@ int skate_compute_surface_alignment( player_instance *player,
    {
       /* fallback: use the closes point to the trucks */
       v3f closest;
-      int idx = bh_closest_point( world.geo_bh, midpoint, closest, 0.1f );
+      int idx = bh_closest_point( world->geo_bh, midpoint, closest, 0.1f );
 
       if( idx != -1 )
       {
-         u32 *tri = &world.scene_geo->arrindices[ idx * 3 ];
+         u32 *tri = &world->scene_geo->arrindices[ idx * 3 ];
          v3f verts[3];
 
          for( int j=0; j<3; j++ )
-            v3_copy( world.scene_geo->arrvertices[ tri[j] ].co, verts[j] );
+            v3_copy( world->scene_geo->arrvertices[ tri[j] ].co, verts[j] );
 
          v3f vert0, vert1, n;
          v3_sub( verts[1], verts[0], vert0 );
@@ -1302,7 +1375,7 @@ VG_STATIC int skate_point_visible( v3f origin, v3f target )
    v3_muls( dir, 1.0f/ray.dist, dir );
    ray.dist -= 0.025f;
 
-   if( ray_world( origin, dir, &ray ) )
+   if( ray_world( get_active_world(), origin, dir, &ray ) )
       return 0;
 
    return 1;
@@ -1812,6 +1885,8 @@ VG_STATIC enum skate_activity skate_availible_grind( player_instance *player )
 VG_STATIC void player__skate_update( player_instance *player )
 {
    struct player_skate *s = &player->_skate;
+   world_instance *world = get_active_world();
+
    v3_copy( player->rb.co, s->state.prev_pos );
    s->state.activity_prev = s->state.activity;
 
@@ -1894,7 +1969,6 @@ VG_STATIC void player__skate_update( player_instance *player )
 
       skate_apply_friction_model( player );
       skate_weight_distribute( player );
-      skate_apply_pump_model( player );
    }
    else
    {
@@ -1922,6 +1996,7 @@ grinding:;
    skate_apply_jump_model( player );
    skate_apply_grab_model( player );
    skate_apply_trick_model( player );
+   skate_apply_pump_model( player );
 
 begin_collision:;
 
@@ -1980,7 +2055,7 @@ begin_collision:;
       v3f n;
 
       float cast_radius = wheels[i].radius - k_penetration_slop * 2.0f;
-      if( spherecast_world( current, future, cast_radius, &t, n ) != -1)
+      if( spherecast_world( world, current, future, cast_radius, &t, n ) != -1)
          max_time = vg_minf( max_time, t * s->substep );
    }
 
@@ -2029,7 +2104,7 @@ begin_collision:;
    float t;
    v3f n;
    if( (v3_dist2( head_wp0, head_wp1 ) > 0.001f) &&
-       (spherecast_world( head_wp0, head_wp1, 0.2f, &t, n ) != -1) )
+       (spherecast_world( world, head_wp0, head_wp1, 0.2f, &t, n ) != -1) )
    {
       v3_lerp( start_co, player->rb.co, t, player->rb.co );
       rb_update_transform( &player->rb );
@@ -2075,7 +2150,7 @@ begin_collision:;
 
    rb_ct *cman = &manifold[manifold_len];
 
-   int l = rb_capsule__scene( mtx, &capsule, NULL, &world.rb_geo.inf.scene,
+   int l = rb_capsule__scene( mtx, &capsule, NULL, &world->rb_geo.inf.scene,
                               cman );
 
    /* weld joints */
@@ -2198,6 +2273,17 @@ begin_collision:;
     * --------------------------------------------------------------------------
     */
 
+   s->surface = k_surface_prop_concrete;
+
+   for( int i=0; i<manifold_len; i++ )
+   {
+      rb_ct *ct = &manifold[i];
+      struct world_material *surface_mat = world_contact_material( world, ct );
+
+      if( surface_mat->info.surface_prop != k_surface_prop_concrete )
+         s->surface = surface_mat->info.surface_prop;
+   }
+
    for( int i=0; i<k_wheel_count; i++ )
    {
       m4x3f mtx;
@@ -2209,11 +2295,12 @@ begin_collision:;
    }
 
    skate_integrate( player );
-   vg_line_pt3( s->state.cog, 0.02f,  VG__WHITE );
+   vg_line_pt3( s->state.cog, 0.02f, VG__WHITE );
 
-   teleport_gate *gate;
-   if( (gate = world_intersect_gates( player->rb.co, s->state.prev_pos )) )
+   struct gate_hit hit;
+   if( world_intersect_gates(world, player->rb.co, s->state.prev_pos, &hit) )
    {
+      teleport_gate *gate = hit.gate;
       m4x3_mulv( gate->transport, player->rb.co, player->rb.co );
       m3x3_mulv( gate->transport, player->rb.v,  player->rb.v );
       m4x3_mulv( gate->transport, s->state.cog,   s->state.cog );
@@ -2229,15 +2316,38 @@ begin_collision:;
       rb_update_transform( &player->rb );
 
       s->state_gate_storage = s->state;
-      player__pass_gate( player, gate );
+      player__pass_gate( player, &hit );
+   }
+
+   /* FIXME: Rate limit */
+   static int stick_frames = 0;
+
+   if( s->state.activity == k_skate_activity_ground )
+      stick_frames ++;
+   else
+      stick_frames = 0;
+
+
+   if( stick_frames == 4 )
+   {
+      audio_lock();
+      if( (fabsf(s->state.slip) > 0.75f) )
+      {
+         audio_oneshot_3d( &audio_lands[rand()%2+3], player->rb.co, 
+                           40.0f, 1.0f );
+      }
+      else
+      {
+         audio_oneshot_3d( &audio_lands[rand()%3], player->rb.co, 
+                           40.0f, 1.0f );
+      }
+      audio_unlock();
    }
 }
 
 VG_STATIC void player__skate_im_gui( player_instance *player )
 {
    struct player_skate *s = &player->_skate;
-
-   /* FIXME: Compression */
    player__debugtext( 1, "V:  %5.2f %5.2f %5.2f",player->rb.v[0],
                                                 player->rb.v[1],
                                                 player->rb.v[2] );
@@ -2566,24 +2676,18 @@ VG_STATIC void player__skate_animate( player_instance *player,
    v3_muladds( dest->root_co, player->rb.to_world[1], -0.1f, dest->root_co );
 
    float substep = vg_clampf( vg.accumulator / VG_TIMESTEP_FIXED, 0.0f, 1.0f );
-#if 0
-   v4f qresy, qresx, qresidual;
-   m3x3f mtx_residual;
-   q_axis_angle( qresy, player->rb.to_world[1], s->state.steery_s*substep );
-   q_axis_angle( qresx, player->rb.to_world[0], s->state.steerx_s*substep );
-
-   q_mul( qresy, qresx, qresidual );
-   q_normalize( qresidual );
-   q_mul( dest->root_q, qresidual, dest->root_q );
-   q_normalize( dest->root_q );
-#endif
 
    v4f qflip;
    if( (s->state.activity == k_skate_activity_air) &&
        (fabsf(s->state.flip_rate) > 0.01f) )
    {
-      float t = s->state.flip_time + s->state.flip_rate*substep*k_rb_delta,
-            angle = vg_clampf( t, -1.0f, 1.0f ) * VG_TAUf,
+      float t     = s->state.flip_time;
+            sign  = vg_signf( t );
+
+      t  = 1.0f - vg_minf( 1.0f, fabsf( t * 1.1f ) );
+      t  = sign * (1.0f-t*t);
+
+      float angle = vg_clampf( t, -1.0f, 1.0f ) * VG_TAUf,
             distm = s->land_dist * fabsf(s->state.flip_rate) * 3.0f,
             blend = vg_clampf( 1.0f-distm, 0.0f, 1.0f );
 
@@ -2611,7 +2715,7 @@ VG_STATIC void player__skate_post_animate( player_instance *player )
 
    player->cam_velocity_influence = 1.0f;
 
-   v3f head = { 0.0f, 1.8f, 0.0f }; /* FIXME: Viewpoint entity */
+   v3f head = { 0.0f, 1.8f, 0.0f };
    m4x3_mulv( av->sk.final_mtx[ av->id_head ], head, s->state.head_position );
    m4x3_mulv( player->rb.to_local, s->state.head_position, 
                                    s->state.head_position );