getting up, redoing challenges, spawn directions
authorhgn <hgodden00@gmail.com>
Sun, 16 Mar 2025 15:01:51 +0000 (15:01 +0000)
committerhgn <hgodden00@gmail.com>
Sun, 16 Mar 2025 15:01:51 +0000 (15:01 +0000)
27 files changed:
content_skaterift/maps/dev_tutorial/main.mdl
content_skaterift/maps/mp_mtzero/before.mdl
content_skaterift/maps/mp_mtzero/main.mdl
content_skaterift/maps/mp_spawn/main.mdl
skaterift_blender/sr_main.py
skaterift_blender/sr_mdl.py
src/control_overlay.c
src/ent_challenge.c
src/ent_challenge.h
src/ent_objective.c
src/ent_region.c
src/entity.h
src/player.c
src/player.h
src/player_dead.c
src/player_dead.h
src/player_replay.c
src/player_replay.h
src/player_skate.c
src/player_walk.c
src/player_walk.h
src/skaterift.c
src/world.h
src/world_entity.c
src/world_map.c
src/world_render.c
src/world_volumes.c

index 5264be9352af4263057570bebd0075ccf41adcfc..e4564566892264226b9a070009d4a14f4eb04477 100644 (file)
Binary files a/content_skaterift/maps/dev_tutorial/main.mdl and b/content_skaterift/maps/dev_tutorial/main.mdl differ
index 117556a8392b41753ee67c5dca7f46d3d2fcd8bb..67de6d32e1b10778b7c9ac46a51846f4f1507b3f 100644 (file)
Binary files a/content_skaterift/maps/mp_mtzero/before.mdl and b/content_skaterift/maps/mp_mtzero/before.mdl differ
index 85b238fd46eac2b73c320c6fb781579707f25aee..d7c26589051601198203db71f1468b52d243a71f 100644 (file)
Binary files a/content_skaterift/maps/mp_mtzero/main.mdl and b/content_skaterift/maps/mp_mtzero/main.mdl differ
index c5a0fdc20e1eaaf0115a64e8ebde0d25ea00930a..5862ad453581cb8e668e79a1457e9dabf23051e4 100644 (file)
Binary files a/content_skaterift/maps/mp_spawn/main.mdl and b/content_skaterift/maps/mp_spawn/main.mdl differ
index c5b31b423aa0bcfbe96d1d20ab2400e11568c9c6..c84112cf6c77081b9d468c662ea8059a3b9e2ddf 100644 (file)
@@ -511,7 +511,7 @@ class ent_challenge(Structure):#{
                ("first_objective_id",c_uint32),
                ("camera_id",c_uint32),
                ("status",c_uint32),
-               ("visible_when_unlocked_id",c_uint32)]
+               ("reset_spawn_id",c_uint32)]
    sr_functions = { 0: 'win',
                     1: 'view',
                    -1: 'unview' }
@@ -1996,15 +1996,20 @@ class SR_OBJECT_ENT_CHALLENGE(bpy.types.PropertyGroup):#{
             type=bpy.types.Object, name="Visibile when unlocked", \
             poll=lambda self,obj: sr_filter_ent_type(obj,['ent_list']))
 
+   reset_spawn: bpy.props.PointerProperty( \
+            type=bpy.types.Object, name="Reset spawn", \
+            poll=lambda self,obj: sr_filter_ent_type(obj,['ent_spawn']))
+
+
    @staticmethod
    def sr_inspector( layout, data ):
    #{
       layout.prop( data[0], 'alias' )
       layout.prop( data[0], 'camera', text=("Camera" if not data[0].is_story else "Related Objective") )
       layout.prop( data[0], 'first', text=("First Objective") )
-      #layout.prop( data[0], 'visible_when_unlocked' )
+      layout.prop( data[0], 'reset_spawn' )
       layout.prop( data[0], 'time_limit' )
-      layout.prop( data[0], 'is_story' )
+      layout.prop( data[0], 'is_story' )
       SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target', text="On Activate" )
       SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'complete', text="On Complete" )
    #}
@@ -2971,6 +2976,11 @@ def cv_draw():#{
                cv_draw_arrow( obj.location, data.complete.location, (0.1,0.9,0) )
             if data.first:
                cv_draw_arrow( obj.location, data.first.location, (1,0.6,0.2) )
+            if data.reset_spawn:
+            #{
+               cv_draw_line_dotted( obj.location, data.reset_spawn.location, (0,1,0) )
+               cv_draw_arrow( data.reset_spawn.location, data.reset_spawn.matrix_world @ Vector((0,3,0)), (0,1,0) )
+            #}
 
             cc1 = (0.4,0.3,0.2)
             info_cu = Vector((1.2,0.01,0.72))*0.5
index f9ac1e308455abe274236e0e4a3767a5bb5bedc6..4ea8827b43267eb2ae21911f6b4c1f4403426357 100644 (file)
@@ -898,7 +898,7 @@ def _mdl_compiler_compile_entities():
             challenge.first_objective_id = sr_entity_id( obj_data.first )
             challenge.camera_id = sr_entity_id( obj_data.camera )
             challenge.status = 0
-            #challenge.visible_when_unlocked_id = sr_entity_id( obj_data.visible_when_unlocked )
+            challenge.reset_spawn_id = sr_entity_id( obj_data.reset_spawn )
             sr_ent_push( challenge )
          #}
          elif ent_type == 'ent_list':
index c7256a9a9fabc8ae0e3ddd886a16ff79179a784b..d6963a2cc5798e3bdf7eb2b99cefb5a673931d32 100644 (file)
@@ -71,6 +71,7 @@ void control_overlay_render(void)
    if( !control_overlay.enabled ) return;
    if( skaterift.activity != k_skaterift_default ) return;
    if( _cutscene.state != k_cutscene_state_none ) return;
+   if( localplayer.subsystem == k_player_subsystem_dead ) return;
 
    glEnable(GL_BLEND);
    glDisable(GL_DEPTH_TEST);
index 8edf20da79ccf9ff70381c1c965cadeb9916b1eb..f5af322aeb809253a260eef941c1883f64b02e8e 100644 (file)
@@ -27,7 +27,7 @@ entity_call_result ent_challenge_call( world_instance *world, ent_call *call )
       return k_entity_call_result_OK;
    }
 
-   if( (_world.event == k_world_event_challenge) && (_world.challenge_state == k_challenge_state_running) )
+   if( (_world.event == k_world_event_challenge) && (_world.challenge_state >= k_challenge_state_running) )
    {
       return k_entity_call_result_OK;
    }
@@ -46,7 +46,7 @@ entity_call_result ent_challenge_call( world_instance *world, ent_call *call )
                   gui_helper_reset( 1 );
                   vg_str text;
                   if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
-                     vg_strcat( &text, (challenge->flags & k_ent_challenge_is_story)? "Play video": "View Challenge" );
+                     vg_strcat( &text, "View Challenge" );
                }
             }
          }
@@ -55,7 +55,7 @@ entity_call_result ent_challenge_call( world_instance *world, ent_call *call )
       }
       else if( call->function == -1 ) /* unview() */
       {
-         if( _world.challenge_state != k_challenge_state_running )
+         if( _world.challenge_state < k_challenge_state_running )
          {
             if( !(challenge->flags & k_ent_challenge_locked) )
             {
@@ -74,6 +74,66 @@ entity_call_result ent_challenge_call( world_instance *world, ent_call *call )
    }
 }
 
+void _restart_active_challenge(void)
+{
+   world_instance *world = &_world.main;
+
+   u32 index = mdl_entity_id_id( _world.active_challenge_id );
+   ent_challenge *challenge = af_arritm( &world->ent_challenge, index );
+
+   srinput.state = k_input_state_resume;
+
+   u32 first_objective_index = mdl_entity_id_id( challenge->first_objective_id );
+   _world.challenge_state = k_challenge_state_running;
+   _world.challenge_target = af_arritm( &world->ent_objective, first_objective_index );
+   _world.challenge_timer = 0.0f;
+
+   u32 next = challenge->first_objective_id;
+   while( mdl_entity_id_type(next) == k_ent_objective )
+   {
+      u32 index = mdl_entity_id_id( next );
+      ent_objective *objective = af_arritm(&world->ent_objective,index);
+      objective->flags &= ~(k_ent_objective_passed|k_ent_objective_failed);
+      next = objective->id_next;
+      v3_fill( objective->transform.s, 1.0f );
+   }
+   vg_audio_lock();
+   vg_audio_oneshot( &audio_challenge[5], 1.0f, 0.0f, 0, 0 );
+   vg_audio_unlock();
+
+   if( challenge->reset_spawn_id )
+   {
+      if( mdl_entity_id_type( challenge->reset_spawn_id ) == k_ent_spawn )
+      {
+         ent_spawn *spawn = af_arritm( &world->ent_spawn, mdl_entity_id_id( challenge->reset_spawn_id ) );
+         v3f fwd = {0,0,-1}, angles;
+         q_mulv( spawn->transform.q, fwd, fwd );
+         v3_angles( fwd, angles );
+         localplayer.angles[0] = angles[0];
+         player__setpos( spawn->transform.co );
+         v3_zero( localplayer.rb.v );
+         v3_zero( localplayer.rb.w );
+         
+         f32 l = v4_length( localplayer.rb.q );
+         if( (l < 0.9f) || (l > 1.1f) )
+            q_identity( localplayer.rb.q );
+
+         rb_update_matrices( &localplayer.rb );
+
+         localplayer.subsystem = k_player_subsystem_walk;
+         player__walk_reset();
+
+         localplayer.immobile = 0;
+         localplayer.gate_waiting = NULL;
+         localplayer.have_glider = 0;
+         localplayer.glider_orphan = 0;
+         localplayer.drowned = 0;
+
+         v3_copy( localplayer.rb.co, localplayer.cam_control.tpv_lpf );
+      }
+   }
+}
+
 void ent_challenge_update(void)
 {
    world_instance *world = &_world.main;
@@ -99,24 +159,8 @@ void ent_challenge_update(void)
          _world.challenge_state = k_challenge_state_running;
          localplayer.immobile = 0; /* TODO: Unify this probably after eating some potats */
          menu.disable_open = 0;
-         srinput.state = k_input_state_resume;
 
-         u32 first_objective_index = mdl_entity_id_id( challenge->first_objective_id );
-         _world.challenge_target = af_arritm( &world->ent_objective, first_objective_index );
-         _world.challenge_timer = 0.0f;
-
-         u32 next = challenge->first_objective_id;
-         while( mdl_entity_id_type(next) == k_ent_objective )
-         {
-            u32 index = mdl_entity_id_id( next );
-            ent_objective *objective = af_arritm(&world->ent_objective,index);
-            objective->flags &= ~k_ent_objective_passed;
-            next = objective->id_next;
-            v3_fill( objective->transform.s, 1.0f );
-         }
-         vg_audio_lock();
-         vg_audio_oneshot( &audio_challenge[5], 1.0f, 0.0f, 0, 0 );
-         vg_audio_unlock();
+         _restart_active_challenge();
 
          if( challenge->on_activate_id )
          {
@@ -167,51 +211,26 @@ void ent_challenge_update(void)
             vg_audio_oneshot_3d( &audio_challenge[6], localplayer.rb.co, 30.0f, 1.0f, 0, 0 );
             vg_audio_unlock();
             vg_info( "Challenge expired due to player being out of range.\n" );
+            gui_helper_reset( k_gui_helper_mode_clear );
          }
       }
    }
    else if( _world.challenge_state == k_challenge_state_none )
    {
-      if( challenge->flags & k_ent_challenge_is_story )
+      if( button_down( k_srbind_maccept ) )
       {
-         if( button_down( k_srbind_maccept ) )
-         {
-            if( challenge->on_activate_id )
-            {
-               srinput.state = k_input_state_resume;
-               gui_helper_reset( k_gui_helper_mode_clear );
-               ent_call call;
-               call.data = NULL;
-               call.function = challenge->on_activate_event;
-               call.id = challenge->on_activate_id;
-               entity_call( &_world.main, &call );
+         srinput.state = k_input_state_resume;
+         gui_helper_reset( k_gui_helper_mode_clear );
+         vg_str text;
+         if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
+            vg_strcat( &text, "Start" );
+         if( gui_new_helper( input_button_list[k_srbind_mback], &text ))
+            vg_strcat( &text, "Exit" );
 
-               if( world_clear_event( k_world_event_challenge ) )
-               {
-                  _world.challenge_state = k_challenge_state_none;
-                  _world.active_challenge_id = 0;
-                  gui_helper_reset( k_gui_helper_mode_clear );
-               }
-            }
-         }
-      }
-      else
-      {
-         if( button_down( k_srbind_maccept ) )
-         {
-            srinput.state = k_input_state_resume;
-            gui_helper_reset( k_gui_helper_mode_clear );
-            vg_str text;
-            if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
-               vg_strcat( &text, "Start" );
-            if( gui_new_helper( input_button_list[k_srbind_mback], &text ))
-               vg_strcat( &text, "Exit" );
-
-            localplayer.immobile = 1;
-            menu.disable_open = 1;
-            srinput.state = k_input_state_resume;
-            _world.challenge_state = k_challenge_state_viewing;
-         }
+         localplayer.immobile = 1;
+         menu.disable_open = 1;
+         srinput.state = k_input_state_resume;
+         _world.challenge_state = k_challenge_state_viewing;
       }
    }
 }
@@ -230,7 +249,7 @@ void _ent_challenge_ui( ui_context *ctx )
    ui_rect description_box = { vg.window_x - (w + 8), 8, w, 32 };
    ctx->font = &vgf_default_large;
    
-   if( _world.challenge_state != k_challenge_state_running )
+   if( !(_world.challenge_state >= k_challenge_state_running) )
       description_box[1] += 48;
 
    u32 next = challenge->first_objective_id;
@@ -242,8 +261,12 @@ void _ent_challenge_ui( ui_context *ctx )
 
       if( objective->pstr_description_ui )
       {
-         bool passed = (objective->flags & k_ent_objective_passed)? 1: 0;
-         u32 colour = passed? ui_colour(ctx,k_ui_yellow): 0xffcccccc;
+         u32 colour = 0xffcccccc;
+         if( objective->flags & k_ent_objective_passed )
+            colour = ui_colour(ctx,k_ui_yellow);
+
+         if( objective->flags & k_ent_objective_failed )
+            colour = ui_colour(ctx,k_ui_red);
          
          ui_fill( ctx, description_box, ui_opacity( GUI_COL_DARK, 0.36f ) );
          ui_outline( ctx, description_box, 1, colour, 0 );
index 4751c11ccd89e24fabf17daf7daf46281ede683f..36ae1b67e70b08c2e94d73a183cda70e1bda458a 100644 (file)
@@ -3,3 +3,4 @@
 
 entity_call_result ent_challenge_call( world_instance *world, ent_call *call );
 void _ent_challenge_ui( ui_context *ctx );
+void _restart_active_challenge(void);
index c1750c816078b61938a7f7215062f4851472af33..5891d835f79f94e2dfbf150b7c915a5dd7d13197 100644 (file)
@@ -96,29 +96,35 @@ entity_call_result ent_objective_call( world_instance *world, ent_call *call )
 
    if( call->function == 0 )
    {
-      if( objective->flags & (k_ent_objective_hidden|k_ent_objective_passed))
+      if( (_world.event == k_world_event_challenge) && (_world.challenge_state == k_challenge_state_running) )
       {
-         return k_entity_call_result_OK;
-      }
-
-      if( _world.challenge_target )
-      {
-         if( (_world.challenge_target == objective) && ent_objective_check_filter( objective ))
+         if( objective->flags & (k_ent_objective_hidden|k_ent_objective_passed|k_ent_objective_failed))
          {
-            ent_objective_pass( world, objective );
+            return k_entity_call_result_OK;
          }
-         else 
-         {
-            vg_audio_lock();
-            vg_audio_oneshot_3d( &audio_challenge[6], localplayer.rb.co, 30.0f, 1.0f, 0, 0 );
-            vg_audio_unlock();
-            vg_error( "challenge failed, filter was not met\n" );
 
-            if( world_clear_event( k_world_event_challenge ) )
+         if( _world.challenge_target )
+         {
+            if( (_world.challenge_target == objective) && ent_objective_check_filter( objective ))
+            {
+               ent_objective_pass( world, objective );
+            }
+            else 
             {
-               _world.active_challenge_id = 0;
-               _world.challenge_target = NULL;
-               _world.challenge_timer = 0.0f;
+               vg_audio_lock();
+               vg_audio_oneshot_3d( &audio_challenge[6], localplayer.rb.co, 30.0f, 1.0f, 0, 0 );
+               vg_audio_unlock();
+               vg_error( "challenge failed, filter was not met\n" );
+               objective->flags |= k_ent_objective_failed;
+               _world.challenge_state = k_challenge_state_fail;
+
+               gui_helper_reset( k_gui_helper_mode_black_bars );
+               vg_str str;
+               struct gui_helper *helper;
+               if( (helper = gui_new_helper(input_button_list[k_srbind_reset], &str)) )
+               {
+                  vg_strcat( &str, "Retry" );
+               }
             }
          }
       }
index 425b1018de1681fbcaadb8e7fd996c3adea5d20b..35df0b1119ebe18a86d323fa9ef08e76addd3859 100644 (file)
@@ -104,9 +104,6 @@ void ent_region_re_eval( world_instance *world )
             {
                ent_challenge *challenge = af_arritm( &world->ent_challenge, index );
 
-               if( challenge->flags & k_ent_challenge_is_story )
-                  continue;
-
                u32 flags = 0x00;
                if( challenge->status )
                {
index fbc1c9e6c74ae485cd2442c9b4e21ad9e9f88377..ec431352cc4317e69afe6859dc1549da3c33153d 100644 (file)
@@ -628,7 +628,8 @@ enum ent_objective_filter{
 enum ent_objective_flag 
 {
    k_ent_objective_hidden = 0x1,
-   k_ent_objective_passed = 0x2
+   k_ent_objective_passed = 0x2,
+   k_ent_objective_failed = 0x4
 };
 
 struct ent_objective
@@ -648,7 +649,7 @@ struct ent_objective
 enum ent_challenge_flag 
 {
    k_ent_challenge_timelimit = 0x1,
-   k_ent_challenge_is_story  = 0x2,
+   //k_ent_challenge_is_story  = 0x2,
    k_ent_challenge_locked    = 0x4,
 };
 
@@ -668,6 +669,7 @@ struct ent_challenge
    u32 camera_id;
 
    u32 status;
+   u32 reset_spawn_id;
 };
 
 struct ent_relay {
index b3c3f47cb2513f608e14aa3e7e070c43a8bfffe7..f4fdc17a498f62c4b292cda234a9a0a264548924 100644 (file)
@@ -34,7 +34,8 @@ struct localplayer localplayer =
       .q = { 0,0,0,1 },
       .to_world = M4X3_IDENTITY,
       .to_local = M4X3_IDENTITY
-   }
+   },
+   .immunity = 1 /* just for one frame */
 };
 
 struct player_subsystem_interface *player_subsystems[] = 
@@ -361,6 +362,11 @@ void player__reset(void)
 
 void player__spawn( ent_spawn *rp )
 {
+   v3f fwd = {0,0,-1}, angles;
+   q_mulv( rp->transform.q, fwd, fwd );
+   v3_angles( fwd, angles );
+   localplayer.angles[0] = angles[0];
+
    player__setpos( rp->transform.co );
    player__reset();
 }
index 6b10f6586fc0c9398ec50f8d5fa69539fa3c1029..caff55b8a2285de22b46b1bb38768feb4644a2f5 100644 (file)
@@ -89,6 +89,7 @@ struct localplayer
    int deferred_frame_record;
 
    int immobile;
+   bool immunity;
    int rewinded_since_last_gate;
 
    /* 
index dd2b9aeba5188437b4ff98cb2f28f84754db5ae8..f4161211a8e2248942874dbfb6dfd14a71582e5d 100644 (file)
@@ -26,9 +26,9 @@ void player__dead_update(void)
    world_water_player_safe( world, 0.2f );
 }
 
-void player__dead_post_update(void){
-   struct ragdoll_part *part = 
-      &localplayer.ragdoll.parts[ localplayer.id_hip-1 ];
+void player__dead_post_update(void)
+{
+   struct ragdoll_part *part = &localplayer.ragdoll.parts[ localplayer.id_hip-1 ];
    struct player_dead *d = &player_dead;
 
    v3f ext_co;
@@ -43,23 +43,44 @@ void player__dead_post_update(void){
    v3_zero( localplayer.rb.v );
    v3_zero( localplayer.rb.w );
 
-   if( (skaterift.activity == k_skaterift_default) && 
-         button_down(k_srbind_dead_respawn) ){
-      ent_spawn *spawn = world_find_closest_spawn( 
-            &_world.main, localplayer.rb.co );
-
-      if( spawn ){
-         v3_copy( spawn->transform.co, localplayer.rb.co );
-         player__reset();
-         srinput.state = k_input_state_resume;
-      }
-      else {
-         vg_error( "No spawns!\n" );
+   if( v3_length( d->v_lpf ) < 0.5f )
+   {
+      if( player_dead.helper_getup )
+         player_dead.helper_getup->greyed = 0;
+
+      if( button_down(k_srbind_skate) )
+      {
+         localplayer.subsystem = k_player_subsystem_walk;
+         player__walk_transition( 0, 0.0f );
+         player__walk_upright();
+
+         if( (_world.event == k_world_event_challenge) && (_world.challenge_state >= k_challenge_state_running) )
+         {
+            vg_audio_lock();
+            vg_audio_oneshot_3d( &audio_challenge[6], localplayer.rb.co, 30.0f, 1.0f, 0, 0 );
+            vg_audio_unlock();
+            vg_error( "Challenge failed.\n" );
+
+            if( world_clear_event( k_world_event_challenge ) )
+            {
+               _world.active_challenge_id = 0;
+               _world.challenge_target = NULL;
+               _world.challenge_timer = 0.0f;
+            }
+         }
+
+         gui_helper_reset( k_gui_helper_mode_clear );
       }
    }
+   else
+   {
+      if( player_dead.helper_getup )
+         player_dead.helper_getup->greyed = 1;
+   }
 }
 
-void player__dead_animate(void){
+void player__dead_animate(void)
+{
    struct player_dead *d = &player_dead;
    struct player_dead_animator *animator = &d->animator;
    struct player_ragdoll *rd = &localplayer.ragdoll;
@@ -75,7 +96,8 @@ void player__dead_animate(void){
    v3_copy( localplayer.rb.co, animator->transforms[0].co );
 
    /* colliders with bones transforms */
-   for( int i=0; i<rd->part_count; i++ ){
+   for( int i=0; i<rd->part_count; i++ )
+   {
       struct ragdoll_part *part = &rd->parts[i];
 
       m4x3f mtx;
@@ -95,10 +117,12 @@ void player__dead_animate(void){
    }
 
    /* bones without colliders transforms */
-   for( u32 i=1; i<sk->bone_count; i++ ){
+   for( u32 i=1; i<sk->bone_count; i++ )
+   {
       struct skeleton_bone *sb = &sk->bones[i];
 
-      if( sb->parent && !sb->collider ){
+      if( sb->parent && !sb->collider )
+      {
          v3f delta;
          v3_sub( sk->bones[i].co, sk->bones[sb->parent].co, delta );
 
@@ -112,7 +136,8 @@ void player__dead_animate(void){
    }
 
    /* measurements */
-   for( u32 i=1; i<sk->bone_count; i++ ){
+   for( u32 i=1; i<sk->bone_count; i++ )
+   {
       struct skeleton_bone *sb = &sk->bones[i];
 
       v3_zero( animator->transforms[i].co );
@@ -126,8 +151,7 @@ void player__dead_animate(void){
 
       v3f _s;
       m4x3_mul( inverse, transforms[i], local );
-      m4x3_decompose( local, animator->transforms[i].co, 
-                             animator->transforms[i].q, _s );
+      m4x3_decompose( local, animator->transforms[i].co, animator->transforms[i].q, _s );
    }
 }
 
@@ -143,7 +167,8 @@ void player__dead_pose( void *_animator, player_pose *pose )
    v3_copy( animator->transforms[0].co, pose->root_co );
    v4_copy( animator->transforms[0].q, pose->root_q );
 
-   for( u32 i=1; i<sk->bone_count; i++ ){
+   for( u32 i=1; i<sk->bone_count; i++ )
+   {
       v3_copy( animator->transforms[i].co, pose->keyframes[i-1].co );
       v4_copy( animator->transforms[i].q, pose->keyframes[i-1].q );
       v3_fill( pose->keyframes[i-1].s, 1.0f );
@@ -164,12 +189,8 @@ void player__dead_transition( enum player_die_type type )
    if( localplayer.subsystem == k_player_subsystem_dead )
       return;
 
-   static bool dont_ask = 1;
-   if( dont_ask )
-   {
-      dont_ask = 0;
+   if( localplayer.immunity )
       return;
-   }
 
    localplayer.subsystem = k_player_subsystem_dead;
    copy_localplayer_to_ragdoll( &localplayer.ragdoll, type );
@@ -180,21 +201,36 @@ void player__dead_transition( enum player_die_type type )
    v3_copy( part->rb.w,  player_dead.w_lpf );
 
    gui_helper_reset( k_gui_helper_mode_black_bars );
+
    vg_str str;
+   if( (player_dead.helper_getup = gui_new_helper(input_button_list[k_srbind_skate], &str) ))
+   {
+      vg_strcat( &str, "Get Up" );
 
-   struct gui_helper *h;
-   if( (h = gui_new_helper(input_button_list[k_srbind_reset], &str) ))
-      vg_strcat( &str, "Rewind" );
+      if( (_world.event == k_world_event_challenge) && (_world.challenge_state >= k_challenge_state_running) )
+      {
+         vg_strcat( &str, " (Exit challenge)" );
 
-   if( gui_new_helper(input_button_list[k_srbind_dead_respawn], &str ))
-      vg_strcat( &str, "Spawn" );
+         struct gui_helper *helper;
+         if( (helper = gui_new_helper(input_button_list[k_srbind_reset], &str)) )
+         {
+            vg_strcat( &str, "Retry" );
+         }
+      }
+
+      player_dead.helper_getup->greyed = 1;
+   }
+
+   //if( gui_new_helper(input_button_list[k_srbind_dead_respawn], &str ))
+   //   vg_strcat( &str, "Spawn" );
 }
 
 void player__dead_animator_exchange( bitpack_ctx *ctx, void *data )
 {
    struct player_dead_animator *animator = data;
 
-   for( u32 i=0; i<localplayer.skeleton.bone_count; i ++ ){
+   for( u32 i=0; i<localplayer.skeleton.bone_count; i ++ )
+   {
       bitpack_qv3f( ctx, 24, -1024.0f, 1024.0f, animator->transforms[i].co );
       bitpack_qquat( ctx, animator->transforms[i].q );
    }
index b86c586493b6653531498f7ad9ea5a9521b9dbee..30d9a72495e85554457dab7b0c3de331d79b3f1d 100644 (file)
@@ -16,6 +16,7 @@ struct player_dead
    animator;
 
    skeleton_anim anim_bail;
+   struct gui_helper *helper_getup;
 }
 extern player_dead;
 extern struct player_subsystem_interface player_subsystem_dead;
index f0ad6d488296be1347ff120a0ac97cdb9ea9b41a..e06ddfe63f2c3497394d4e506dfa135c22da8c1c 100644 (file)
@@ -759,27 +759,49 @@ void skaterift_replay_post_render(void)
       return;
 #endif
 
-   /* capture the current resume frame at the very last point */
-   if( button_down( k_srbind_reset ) )
+   if( (_world.event == k_world_event_challenge) && (_world.challenge_state >= k_challenge_state_running) )
    {
-      if( _world.main.info.flags & k_world_flag_no_rewind )
+      if( button_press( k_srbind_reset ) )
       {
-         gui_location_print_ccmd( 1, (const char *[]){ KRED "Rewind is not allowed here.." } );
+         player_replay.reset_timer += vg.time_delta;
+
+         if( player_replay.reset_timer > 1.0f )
+         {
+            srinput.state = k_input_state_resume;
+            _restart_active_challenge();
+            player_replay.reset_timer = 0.0f;
+            gui_helper_reset( k_gui_helper_mode_clear );
+         }
       }
       else
       {
-         if( skaterift.activity == k_skaterift_default )
+         player_replay.reset_timer = 0.0f;
+      }
+   }
+   else
+   {
+      /* capture the current resume frame at the very last point */
+      if( button_down( k_srbind_reset ) )
+      {
+         if( _world.main.info.flags & k_world_flag_no_rewind )
+         {
+            gui_location_print_ccmd( 1, (const char *[]){ KRED "Rewind is not allowed here.." } );
+         }
+         else
          {
-            localplayer.rewinded_since_last_gate = 1;
-            skaterift.activity = k_skaterift_replay;
-            skaterift_record_frame( &player_replay.local, 1 );
-            if( player_replay.local.head )
+            if( skaterift.activity == k_skaterift_default )
             {
-               player_replay.local.cursor = player_replay.local.head->time;
-               player_replay.local.cursor_frame = player_replay.local.head;
+               localplayer.rewinded_since_last_gate = 1;
+               skaterift.activity = k_skaterift_replay;
+               skaterift_record_frame( &player_replay.local, 1 );
+               if( player_replay.local.head )
+               {
+                  player_replay.local.cursor = player_replay.local.head->time;
+                  player_replay.local.cursor_frame = player_replay.local.head;
+               }
+               player_replay.replay_control = k_replay_control_scrub;
+               replay_show_helpers();
             }
-            player_replay.replay_control = k_replay_control_scrub;
-            replay_show_helpers();
          }
       }
    }
@@ -876,6 +898,28 @@ static void replay_fly_edit_keyframe( ui_context *ctx, replay_keyframe *kf )
 
 void skaterift_replay_imgui( ui_context *ctx )
 {
+   if( (_world.event == k_world_event_challenge) && (_world.challenge_state >= k_challenge_state_running) )
+   {
+      if( player_replay.reset_timer > 0.0f )
+      {
+         ui_rect box = { vg.window_x/2 - 200, vg.window_y - 200, 400, 100 };
+         ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.35f ) );
+         ui_outline( ctx, box, 1, GUI_COL_NORM, 0 );
+
+         ctx->font = &vgf_default_title;
+         ui_rect title = { box[0], box[1] + 16, box[2], box[3]-16 };
+         ui_text( ctx, box, "Retry?", 1, k_ui_align_center, 0 );
+
+         ui_rect bar = { box[0] + 8, (box[1] + box[3]) - (24+8), box[2] - 16, 24 };
+         ui_fill( ctx, bar, ui_opacity( GUI_COL_DARK, 0.8f ) );
+
+         ui_rect inner = { bar[0]+1, bar[1]+1, (f32)(bar[2]-2)*player_replay.reset_timer, bar[3]-2 };
+         ui_fill( ctx, inner, ui_colour( ctx, k_ui_yellow ) );
+
+         ctx->font = &vgf_default_small;
+      }
+   }
+
    if( skaterift.activity != k_skaterift_replay ) return;
 
    /* extra keys for entering editor */
index 313b4d4f0bb273434ec39ecf4d2c63b135ba47c9..f84a76757ced21aff1094fea9f3d4a417edaf83e 100644 (file)
@@ -102,6 +102,8 @@ struct replay_globals
    replay_keyframe keyframes[32];
    u32 keyframe_count;
    i32 active_keyframe;
+
+   f32 reset_timer;
 }
 extern player_replay;
 
index fb25787cfaf2ea1c1578d752ba84323a1f0ad40c..2eb37fab08e866d7fd8f964cb0d23a78ac0b8500 100644 (file)
@@ -1277,13 +1277,11 @@ void player__skate_pre_update(void){
       v3_add( newpos, (v3f){0.0f,-1.0f,0.0f}, newpos );
       v3_sub( localplayer.rb.co, newpos, offset );
       v3_copy( newpos, localplayer.rb.co );
-      v3_muladds( localplayer.rb.co, localplayer.rb.to_world[1], -0.1f,
-                  localplayer.rb.co );
+      v3_muladds( localplayer.rb.co, localplayer.rb.to_world[1], -0.1f, localplayer.rb.co );
 
       player__begin_holdout( offset );
-      player__walk_transition( state->activity <= k_skate_activity_air_to_grind?
-                               0: 1, state->trick_euler[0] );
-
+      player__walk_transition( state->activity <= k_skate_activity_air_to_grind? 0: 1, state->trick_euler[0] );
+      player__walk_upright();
       return;
    }
 
index 03fe56b72f9a065c37e05dd2385fd6b4c3971160..fe136bfe981d3a6b1de6bf5f4f3c439a17006f5d 100644 (file)
@@ -1223,18 +1223,21 @@ void player__walk_transition( bool grounded, f32 board_yaw ){
    rb_update_matrices( &localplayer.rb );
 }
 
+void player__walk_upright(void)
+{
+   v3f fwd = { 0.0f, 0.0f, 1.0f };
+   q_mulv( localplayer.rb.q, fwd, fwd );
+   q_axis_angle( localplayer.rb.q, (v3f){0.0f,1.0f,0.0f}, atan2f(fwd[0], fwd[2]) );
+   rb_update_matrices( &localplayer.rb );
+}
+
 void player__walk_reset(void)
 {
    struct player_walk *w = &player_walk;
    w->state.activity = k_walk_activity_air;
    w->state.transition_t = 0.0f;
 
-   v3f fwd = { 0.0f, 0.0f, 1.0f };
-   q_mulv( localplayer.rb.q, fwd, fwd );
-   q_axis_angle( localplayer.rb.q, (v3f){0.0f,1.0f,0.0f}, 
-                 atan2f(fwd[0], fwd[2]) );
-
-   rb_update_matrices( &localplayer.rb );
+   player__walk_upright();
 }
 
 void player__walk_animator_exchange( bitpack_ctx *ctx, void *data ){
index b740a8ca40cb3869a5f39bebd771f6db074adcb9..50c1a7c508e58588f48a85543b508991bbc870be 100644 (file)
@@ -112,3 +112,4 @@ void player__walk_restore     (void);
 void player__walk_animator_exchange( bitpack_ctx *ctx, void *data );
 void player__walk_transition( bool grounded, f32 board_yaw );
 void player__walk_sfx_oneshot( u8 id, v3f pos, f32 volume );
+void player__walk_upright(void);
index 7a9f745dbe27a183d8683a3476086b14f1c8372a..3ec7873b64b145532e000f035f492ebe61aa661d 100644 (file)
@@ -247,6 +247,8 @@ void vg_post_update(void)
 
    vehicle_update_post();
    skaterift_autosave_update();
+
+   localplayer.immunity = 0;
 }
 
 /*
index 7b8a2889c03050c7142c5cfd9f0a86bdc7fb3a7c..dad0421a0bc4f08c1f66a2cb8eaa1724b55be51f 100644 (file)
@@ -274,7 +274,8 @@ struct world_static
    {
       k_challenge_state_none = 0,
       k_challenge_state_viewing,
-      k_challenge_state_running
+      k_challenge_state_running,
+      k_challenge_state_fail
    }
    challenge_state;
 
index 0fa08f5175eafaff0645326475ae4fbeba8be8d4..279667a08f5f4d0edf7de76b96b7d29951ffcd9d 100644 (file)
@@ -658,22 +658,16 @@ void world_entity_start( world_instance *world, vg_msg *sav )
       ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
       const char *alias = af_str( &world->meta.af, challenge->pstr_alias );
 
-      if( challenge->flags & k_ent_challenge_is_story )
-      {
-      }
-      else
-      {
-         u32 result;
-         vg_msg_getkvintg( sav, alias, k_vg_msg_u32, &result, NULL );
+      u32 result;
+      vg_msg_getkvintg( sav, alias, k_vg_msg_u32, &result, NULL );
 
-         if( result )
-         {
-            ent_call call;
-            call.data = NULL;
-            call.function = 0;
-            call.id = mdl_entity_id( k_ent_challenge, i );
-            entity_call( world, &call );
-         }
+      if( result )
+      {
+         ent_call call;
+         call.data = NULL;
+         call.function = 0;
+         call.id = mdl_entity_id( k_ent_challenge, i );
+         entity_call( world, &call );
       }
    }
 
index d8ee256b8e18048b230f537853c179ff01cb3687..2a89476fb38bf528e4dad1e66227bf59acebba32 100644 (file)
@@ -638,8 +638,6 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
                   else if( type == k_ent_challenge )
                   {
                      ent_challenge *challenge = af_arritm( &world->ent_challenge, index );
-                     if( challenge->flags & k_ent_challenge_is_story )
-                        continue;
 
                      vg_strnull( &str, buf, sizeof(buf) );
                      vg_strcat( &str, af_str( &world->meta.af,challenge->pstr_alias));
index f9d395b5329ba03aeb0ba4701cb31641c4e4e8bd..44fa8620ceb42758f9b2f7f113c9ceaf429ea0d7 100644 (file)
@@ -506,7 +506,7 @@ static void world_render_challenges( world_instance *world, struct world_pass *p
    u32 objective_count = 0,
        challenge_count = 0;
 
-   if( (_world.event == k_world_event_challenge) && (_world.challenge_state == k_challenge_state_running) )
+   if( (_world.event == k_world_event_challenge) && (_world.challenge_state >= k_challenge_state_running) )
    {
       u32 challenge_index = mdl_entity_id_id( _world.active_challenge_id );
       ent_challenge *challenge = af_arritm( &world->ent_challenge, challenge_index );
@@ -563,7 +563,7 @@ static void world_render_challenges( world_instance *world, struct world_pass *p
       f32 scale = 1.0f;
 
       if( (_world.event == k_world_event_challenge) && 
-          (_world.challenge_state == k_challenge_state_running || _world.challenge_state == k_challenge_state_viewing) )
+          (_world.challenge_state >= k_challenge_state_running || _world.challenge_state == k_challenge_state_viewing) )
       {
          u32 passed = objective->flags & k_ent_objective_passed;
          f32 target = passed? 0.0f: 1.0f;
@@ -611,12 +611,9 @@ static void world_render_challenges( world_instance *world, struct world_pass *p
    for( u32 i=0; i<af_arrcount(&world->ent_challenge); i++ )
    {
       ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
-      if( !(challenge->flags & k_ent_challenge_is_story) )
-      {
-         if( challenge->status ) 
-            count ++;
-         total ++;
-      }
+      if( challenge->status ) 
+         count ++;
+      total ++;
    }
 
    char buf[32];
@@ -638,9 +635,6 @@ static void world_render_challenges( world_instance *world, struct world_pass *p
       u32 index = challenge_list[ i ];
       ent_challenge *challenge = af_arritm( &world->ent_challenge, index );
 
-      if( challenge->flags & k_ent_challenge_is_story )
-         continue;
-
       m4x3f mmdl;
       mdl_transform_m4x3( &challenge->transform, mmdl );
       m4x3_mul( mmdl, mlocal, mmdl );
index d111264225817dfb0ceb4cce0481941fde8f4e90..d3dbcf703fbac4110734f7ad78f575d2bfc96e76 100644 (file)
@@ -15,7 +15,8 @@ void world_volumes_update( world_instance *world, v3f pos )
       m4x3_mulv( volume->to_local, pos, local );
       if( (fabsf(local[0]) <= 1.0f) &&
           (fabsf(local[1]) <= 1.0f) &&
-          (fabsf(local[2]) <= 1.0f) )
+          (fabsf(local[2]) <= 1.0f) && 
+          (localplayer.subsystem != k_player_subsystem_dead) )
       {
          _world.active_trigger_volumes[ j ++ ] = idx;
          boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}};
@@ -111,6 +112,9 @@ void world_volumes_update( world_instance *world, v3f pos )
          if( _world.active_trigger_volume_count > VG_ARRAY_LEN(_world.active_trigger_volumes) ) 
             continue;
 
+         if( localplayer.subsystem == k_player_subsystem_dead )
+            continue;
+
          v3f local;
          m4x3_mulv( volume->to_local, pos, local );