gino, compass, map, icons
authorhgn <hgodden00@gmail.com>
Tue, 6 May 2025 20:04:57 +0000 (21:04 +0100)
committerhgn <hgodden00@gmail.com>
Tue, 6 May 2025 20:04:57 +0000 (21:04 +0100)
20 files changed:
content_skaterift/maps/dev_heaven/main.mdl
content_skaterift/maps/dev_tutorial/main.mdl
content_skaterift/models/gino.mdl [new file with mode: 0644]
content_skaterift/models/rs_compass.mdl
content_skaterift/models/rs_icons.mdl
src/compass.c
src/compass.h
src/ent_route.c
src/gui.h
src/menu.c
src/npc_gino.c [new file with mode: 0644]
src/npc_gino.h [new file with mode: 0644]
src/scripts/heaven.c
src/skaterift.c
src/skaterift_script.c
src/world.c
src/world.h
src/world_map.c
src/world_render.c
src/world_volumes.c

index 956e86093c6093f4c550873e40752b0849bdc980..c1e8027d4028a03d275684dcbceb5890ae1ac76b 100644 (file)
Binary files a/content_skaterift/maps/dev_heaven/main.mdl and b/content_skaterift/maps/dev_heaven/main.mdl differ
index 3aa56889a93e20e6627d39fb51472d015b560508..79f458a2f7bfe37867bfa6ce1049392399ba1343 100644 (file)
Binary files a/content_skaterift/maps/dev_tutorial/main.mdl and b/content_skaterift/maps/dev_tutorial/main.mdl differ
diff --git a/content_skaterift/models/gino.mdl b/content_skaterift/models/gino.mdl
new file mode 100644 (file)
index 0000000..36e5cdd
Binary files /dev/null and b/content_skaterift/models/gino.mdl differ
index 23ef7baf00d1bc4f7cf570eda963c817c85356c0..b187a387038d5fea862639fb6f01efdc92423d6c 100644 (file)
Binary files a/content_skaterift/models/rs_compass.mdl and b/content_skaterift/models/rs_compass.mdl differ
index a9ada53936799ef044f548e4e1b11d0d33f47d83..2de0cf16f28b53b95f22b623fcf21adbf65989e2 100644 (file)
Binary files a/content_skaterift/models/rs_icons.mdl and b/content_skaterift/models/rs_icons.mdl differ
index 74a4c9a254ab6b327fb04e57c685282109b22190..7a651ee84c674f4b63bcebdcc77e2ad00cc74b22 100644 (file)
@@ -24,6 +24,7 @@ void compass_init(void)
    _compass.sm_comp_person = mdl_get_submesh_index( mdl, "comp_person" );
    _compass.sm_comp_s = mdl_get_submesh_index( mdl, "comp_s" );
    _compass.sm_comp_w = mdl_get_submesh_index( mdl, "comp_w" );
+   _compass.sm_comp_objective = mdl_get_submesh_index( mdl, "comp_objective" );
    mdl_close( mdl );
 
    vg_console_reg_var( "compass_alpha", &_compass.alpha, k_var_dtype_f32, VG_VAR_PERSISTENT );
@@ -110,6 +111,22 @@ void compass_render_texture(void)
    /* TODO: Players  and friends */
    shader_compass_uColour( (v4f){ 1,1,1,1 } );
 
+   if( network_connected() )
+   {
+      for( u32 i=0; i<NETWORK_MAX_PLAYERS; i ++ )
+      {
+         struct network_player *player = &netplayers.list[i];
+         if( player->active && player->same_world )
+         {
+            struct skeleton *sk = &localplayer.skeleton;
+            m4x3f *final_mtx = &netplayers.final_mtx[ sk->bone_count*i ];
+
+            if( compass_co( projection, final_mtx[0][3], 0.0f ) )
+               mdl_draw_submesh( &mdl->submeshes[ player->isfriend? _compass.sm_comp_friend: _compass.sm_comp_person ] );
+         }
+      }
+   }
+
    world_instance *world = &_world.main;
 
    /* story markers */
@@ -125,6 +142,17 @@ void compass_render_texture(void)
             mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_notify ] );
       }
    }
+   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_locked ) 
+         continue;
+      if( !challenge->status )
+      {
+         if( compass_co( projection, challenge->transform.co, 0.0f ) )
+            mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_objective ] );
+      }
+   }
 
    /* gates n shit */
    f32 t = (_world.time - _world.last_gate_hit_time) / 30.0f;
@@ -135,6 +163,12 @@ void compass_render_texture(void)
       {
          ent_route *route = af_arritm( &world->ent_route, i );
 
+         if( !(route->flags & (k_ent_route_flag_achieve_gold|k_ent_route_flag_achieve_silver)) )
+         {
+            if( compass_co( projection, route->board_transform[3], 0.0f ) )
+               mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_objective ] );
+         }
+
          if( route->active_checkpoint != 0xffff )
          {
             v4f colour;
index 1d9c807eda07fdb63cbaaa81b3f04c9180d397f6..f8b08c0be5ea15733ec8e975e6f2c089a96aecaf 100644 (file)
@@ -16,7 +16,8 @@ struct _compass
        sm_comp_notify,
        sm_comp_person,
        sm_comp_s,
-       sm_comp_w;
+       sm_comp_w,
+       sm_comp_objective;
 
    f32 alpha;
 }
index e0b0bb193b7bcd77024e04730889e0a52fbc2b3c..a99ff4187a5cb5a959f73bb0257dfba11ca3bbdd 100644 (file)
@@ -88,19 +88,37 @@ void ent_route_leaderboard_ui( ui_context *ctx, ui_rect ref_box, u32 route_index
       ui_capture_mouse(ctx, 1);
 
    ui_rect leaderboard_box = { ref_box[0], ref_box[1] + ref_box[3] + 16, ref_box[2], 24 };
-   
-   if( !network_connected() )
+
+   world_instance *world = &_world.main;
+   if( route_index >= af_arrcount( &world->ent_route ) )
    {
       ui_fill( ctx, leaderboard_box, ui_opacity( GUI_COL_DARK, 0.36f ) );
-      ui_text( ctx, leaderboard_box, "Offline - No Leaderboards", 1, k_ui_align_middle_center, 0 );
+      ui_text( ctx, leaderboard_box, "Error - Out of range", 1, k_ui_align_middle_center, 0 );
       return;
    }
 
-   world_instance *world = &_world.main;
-   if( route_index >= af_arrcount( &world->ent_route ) )
+   ent_route *route = af_arritm( &world->ent_route, route_index );
+   ui_rect right_box = { leaderboard_box[0] + leaderboard_box[2] + 16, leaderboard_box[1], 300, 100 };
+   ui_rect title_box;
+   ui_fill( ctx, right_box, ui_opacity( GUI_COL_DARK, 0.36f ) );
+   ctx->font = &vgf_default_title;
+   ui_split( right_box, k_ui_axis_h, 48, 2, title_box, right_box );
+   ui_text( ctx, title_box, "Completion", 1, k_ui_align_middle_center, 0 );
+
+   ctx->font = &vgf_default_large;
+
+   if( route->flags & k_ent_route_flag_achieve_gold )
+      ui_text( ctx, right_box, "Completed in Gold!", 1, k_ui_align_middle_center, 0 );
+   else if( route->flags & k_ent_route_flag_achieve_silver )
+      ui_text( ctx, right_box, "Completed in Silver\n(Don't fall for gold)", 1, k_ui_align_middle_center, 0 );
+   else
+      ui_text( ctx, right_box, "Not completed...", 1, k_ui_align_middle_center, 0 );
+
+   
+   if( !network_connected() )
    {
       ui_fill( ctx, leaderboard_box, ui_opacity( GUI_COL_DARK, 0.36f ) );
-      ui_text( ctx, leaderboard_box, "Error - Out of range", 1, k_ui_align_middle_center, 0 );
+      ui_text( ctx, leaderboard_box, "Offline - No Leaderboards", 1, k_ui_align_middle_center, 0 );
       return;
    }
 
@@ -117,7 +135,6 @@ void ent_route_leaderboard_ui( ui_context *ctx, ui_rect ref_box, u32 route_index
    if( (delta > 45.0) || (board->cache_time == 0.0) )
    {
       board->cache_time = vg.time_real;
-      ent_route *route = af_arritm( &world->ent_route, route_index );
       char mod_uid[ ADDON_UID_MAX ];
       addon_uid( _world.main.addon_id, mod_uid );
       network_request_scoreboard( mod_uid, af_str( &world->meta.af, route->pstr_name ),
index 468cdd57fcef5a88efa72eb3859dc2e51a12ef50..ad50fb3528b5ba7ed0f34bdb337060068e9cad62 100644 (file)
--- a/src/gui.h
+++ b/src/gui.h
 #define GUI_COL_HI     ui_opacity( 0x00ffffff, 0.8f )
 
 enum gui_icon {
-   k_gui_icon_tick    = 0,
-   k_gui_icon_tick_2d,
+   k_gui_icon_tick1    = 0,
+   k_gui_icon_tick2,
+   k_gui_icon_run,
+   k_gui_icon_challenge,
    k_gui_icon_exclaim,
-   k_gui_icon_exclaim_2d,
    k_gui_icon_board,
    k_gui_icon_world,
    k_gui_icon_rift,
@@ -160,8 +161,10 @@ static void gui_draw( ui_context *ctx )
    /* helpers 
     * -----------------------------------------------------------------  */
 
-   gui.factive = vg_lerpf( gui.factive, gui.helper_count?1.0f:0.0f,
-                           vg.time_frame_delta*2.0f );
+   if( _cutscene.state >= k_cutscene_state_ready )
+      return;
+
+   gui.factive = vg_lerpf( gui.factive, gui.helper_count?1.0f:0.0f, vg.time_frame_delta*2.0f );
    
    ctx->font = &vgf_default_title;
    ui_px height = ctx->font->ch + 16;
@@ -187,9 +190,7 @@ static void gui_draw( ui_context *ctx )
          opacity = 0.1f;
       }
 
-      struct ui_vert *bg = ui_fill( ctx, box, 
-                                    ui_opacity( GUI_COL_DARK, opacity ) );
-
+      struct ui_vert *bg = ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, opacity ) );
       u32 w;
       box[0] += 16;
       w = ui_text( ctx, box, buf, 1, k_ui_align_middle_left, fg );
@@ -223,7 +224,6 @@ static void gui_draw( ui_context *ctx )
    ui_flush( ctx, k_ui_shader_colour, NULL );
    vg_ui.frosting = 0.0f;
 
-
    f64 loc_t = (vg.time_real - gui.location_time) / 5.0;
    if( (loc_t < 1.0) && (gui.location_time != 0.0) )
    {
@@ -296,10 +296,11 @@ static void gui_init(void)
    mdl_open( mdl, "models/rs_icons.mdl", alloc );
    mdl_load_metadata_block( mdl, alloc );
 
-   gui.icon_submeshes[ k_gui_icon_tick ] = mdl_get_submesh_index( mdl, "icon_tick" );
-   gui.icon_submeshes[ k_gui_icon_tick_2d ] = mdl_get_submesh_index( mdl, "icon_tick2d" );
+   gui.icon_submeshes[ k_gui_icon_tick1 ] = mdl_get_submesh_index( mdl, "icon_tick1" );
+   gui.icon_submeshes[ k_gui_icon_tick2 ] = mdl_get_submesh_index( mdl, "icon_tick2" );
+   gui.icon_submeshes[ k_gui_icon_run ] = mdl_get_submesh_index( mdl, "icon_run" );
+   gui.icon_submeshes[ k_gui_icon_challenge ] = mdl_get_submesh_index( mdl, "icon_challenge" );
    gui.icon_submeshes[ k_gui_icon_exclaim ] = mdl_get_submesh_index( mdl, "icon_exclaim" );
-   gui.icon_submeshes[ k_gui_icon_exclaim_2d ] = mdl_get_submesh_index( mdl, "icon_exclaim2d" );
    gui.icon_submeshes[ k_gui_icon_board ] = mdl_get_submesh_index( mdl, "icon_board" );
    gui.icon_submeshes[ k_gui_icon_world ] = mdl_get_submesh_index( mdl, "icon_world" );
    gui.icon_submeshes[ k_gui_icon_rift ] = mdl_get_submesh_index( mdl, "icon_rift" );
index 137ee2623ee5a56855de009322cee47b134b79bf..fdf28f59e3eeded56fc5dbe47a172cf38be48aa3 100644 (file)
@@ -980,7 +980,7 @@ void menu_gui( ui_context *ctx )
       ui_rect end = { panel[0], panel[1] + panel[3] - 48, panel[2], 48 }, a,b;
       ui_split_ratio( end, k_ui_axis_v, 0.5f, 2, a, b );
 
-      if( menu_button( ctx, a, R == 0, steam_ready, "Skip" ) )
+      if( menu_button( ctx, a, R == 0, 1, "Skip" ) )
       {
          _cutscene.fadeout = 1;
          _cutscene.fadeout_start = _cutscene.time;
diff --git a/src/npc_gino.c b/src/npc_gino.c
new file mode 100644 (file)
index 0000000..a924c5e
--- /dev/null
@@ -0,0 +1,230 @@
+#include "npc_gino.h"
+
+struct
+{
+   enum gino_state
+   {
+      k_gino_none,
+      k_gino_intro,
+      k_gino_normal,
+   }
+   state;
+
+   mdl_context mdl;
+   i32 sm_main, sm_hat;
+
+   f64 command_t;
+   v3f co, p0, p1;
+
+   i32 uid;
+
+   enum gino_sub_state
+   {
+      k_gino_sub_off,
+      k_gino_sub_reading,
+      k_gino_sub_read
+   }
+   sub_state;
+
+   const cs_subtitle *subtitles;
+   i32 sub_index;
+
+   f32 spark_t;
+}
+_gino;
+
+void _npc_gino_speech( const cs_subtitle *subs )
+{
+   _gino.subtitles = subs;
+}
+
+void _npc_gino_goto( v3f pos, i32 uid )
+{
+   if( _gino.uid == uid )
+      return;
+
+   _gino.uid = uid;
+   _gino.state = k_gino_intro;
+   v3_copy( pos, _gino.p1 );
+
+   if( _gino.state == k_gino_none )
+      v3_add( pos, (v3f){0,30,0}, _gino.p0 );
+   else
+      v3_copy( _gino.co, _gino.p0 );
+
+   _gino.command_t = vg.time;
+}
+
+void _npc_gino_init(void)
+{
+   void *alloc = vg_mem.rtmemory;
+   mdl_context *mdl = &_gino.mdl;
+   mdl_open( mdl, "models/gino.mdl", alloc );
+   mdl_load_metadata_block( mdl, alloc );
+   mdl_async_full_load_std( mdl, NULL );
+   _gino.sm_main = mdl_get_submesh_index( mdl, "gino" );
+   _gino.sm_hat = mdl_get_submesh_index( mdl, "gino.hat" );
+   mdl_close( mdl );
+}
+
+void _npc_gino_preupdate(void)
+{
+   if( _gino.state == k_gino_none )
+      return;
+
+   f32 dist2 = v3_dist2( _gino.p1, localplayer.rb.co );
+   if( _world.event == k_world_event_gino )
+   {
+      if( dist2 > 4.0f*4.0f )
+      {
+         if( world_clear_event( k_world_event_gino ) )
+         {
+            _gino.sub_state = k_gino_sub_off;
+            _cutscene.subtitle = NULL;
+            gui_helper_reset( k_gui_helper_mode_clear );
+         }
+      }
+      else
+      {
+         if( (_gino.sub_state != k_gino_sub_read) && button_down( k_srbind_maccept ) )
+         {
+            srinput.state = k_input_state_resume;
+            if( _gino.sub_state == k_gino_sub_reading )
+               _gino.sub_index ++;
+
+            const cs_subtitle *sub = &_gino.subtitles[ _gino.sub_index ];
+
+            if( sub->key )
+            {
+               _gino.sub_state = k_gino_sub_reading;
+               _cutscene.subtitle = sub->value;
+
+               gui_helper_reset( k_gui_helper_mode_black_bars );
+               vg_str text;
+               if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
+                  vg_strcat( &text, "Next" );
+            }
+            else
+            {
+               _gino.sub_index = 0;
+               _gino.sub_state = k_gino_sub_read;
+               _cutscene.subtitle = NULL;
+               gui_helper_reset( k_gui_helper_mode_clear );
+            }
+         }
+      }
+   }
+
+   v3f co;
+
+   if( _gino.state == k_gino_normal )
+   {
+      v3_copy( _gino.p1, co );
+
+      if( _world.event == k_world_event_none )
+      {
+         if( dist2 < 3.0f*3.0f )
+         {
+            if( localplayer.subsystem == k_player_subsystem_walk )
+            {
+               if( world_set_event( k_world_event_gino ) )
+               {
+                  gui_helper_reset( k_gui_helper_mode_black_bars );
+                  vg_str text;
+                  if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
+                     vg_strcat( &text, "Talk to Gino" );
+               }
+            }
+         }
+      }
+   }
+   else
+   {
+      f32 t = (vg.time - _gino.command_t) / 2.0;
+      bool end = 0;
+
+      if( t >= 1.0f )
+      {
+         end = 1;
+         t = 1.0f;
+      }
+
+      if( end )
+         _gino.state = k_gino_normal;
+
+      f32 ts = vg_smoothstepf( t );
+      v3_lerp( _gino.p0, _gino.p1, ts, co );
+      co[1] += vg_smoothstepf(1.0f-(fabsf(t-0.5f)*2.0f)) * 8.0f;
+   }
+
+   co[0] += cos( vg.time * 1.23 + 0.3 ) * 0.07f;
+   co[1] += sin( vg.time ) * 0.1f;
+   co[2] += cos( vg.time * 1.1 + 0.3 ) * 0.04f;
+   v3_copy( co, _gino.co );
+
+   if( dist2 < 40.0f*40.0f )
+   {
+      if( _gino.spark_t < 0.0f )
+      {
+         _gino.spark_t += 0.05f+vg_randf64(&vg.rand)*0.1f;
+
+         v3f pos;
+         v3_add( co, (v3f){0,0.16f,0}, pos );
+         f32 a = vg_randf64(&vg.rand) * VG_TAUf,
+             r = 0.43f;
+         pos[0] += sinf( a ) * r;
+         pos[2] += cosf( a ) * r;
+         particle_spawn_cone( &particles_grind, pos, (v3f){0,-1,0}, VG_PIf/2.0f, 2, 4.0f, 0xffEC705A );
+      }
+      else
+         _gino.spark_t -= vg.time_delta;
+   }
+}
+
+void _npc_gino_render( vg_camera *cam )
+{
+   if( _gino.state == k_gino_none )
+      return;
+
+   mesh_bind( &_gino.mdl.mesh );
+   glActiveTexture( GL_TEXTURE0 );
+   glBindTexture( GL_TEXTURE_2D, _gino.mdl.textures[0].glname );
+
+   world_instance *world = &_world.main;
+   shader_model_entity_use();
+   shader_model_entity_uTexMain( 0 );
+   shader_model_entity_uCamera( cam->transform[3] );
+   shader_model_entity_uPv( cam->mtx.pv );
+   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+
+   m4x3f mmdl;
+   v3f v0 = { localplayer.rb.co[0] - _gino.co[0], 0.0f, localplayer.rb.co[2] - _gino.co[2] };
+   v3_normalize( v0 );
+   v3_copy( v0, mmdl[0] );
+   v3_copy( (v3f){0,1,0}, mmdl[1] );
+   v3_cross( mmdl[0], mmdl[1], mmdl[2] );
+   v3_copy( _gino.co, mmdl[3] );
+
+   m4x4f m4mmdl;
+   m4x3_expand( mmdl, m4mmdl );
+   m4x4_mul( cam->mtx_prev.pv, m4mmdl, m4mmdl );
+   shader_model_entity_uMdl( mmdl );
+   shader_model_entity_uPvmPrev( m4mmdl );
+   mdl_draw_submesh( &_gino.mdl.submeshes[ _gino.sm_main ] );
+
+   m3x3f mspin;
+   v4f qspin;
+   q_axis_angle( qspin, (v3f){0,1,0}, vg_fractf(vg.time)*VG_TAUf*16.0f );
+   q_m3x3( qspin, mspin );
+   m3x3_mul( mspin, mmdl, mmdl );
+   m4x3_expand( mmdl, m4mmdl );
+   m4x4_mul( cam->mtx_prev.pv, m4mmdl, m4mmdl );
+   shader_model_entity_uMdl( mmdl );
+   shader_model_entity_uPvmPrev( m4mmdl );
+   mdl_draw_submesh( &_gino.mdl.submeshes[ _gino.sm_hat ] );
+}
+
+void _npc_gino_imgui( ui_context *ctx )
+{
+   vg_camera *cam = &g_render.cam;
+}
diff --git a/src/npc_gino.h b/src/npc_gino.h
new file mode 100644 (file)
index 0000000..8cbe7c3
--- /dev/null
@@ -0,0 +1,8 @@
+#pragma once
+
+void _npc_gino_init(void);
+void _npc_gino_render( vg_camera *cam );
+void _npc_gino_goto( v3f pos, i32 uid );
+void _npc_gino_preupdate(void);
+void _npc_gino_imgui( ui_context *ctx );
+void _npc_gino_speech( const cs_subtitle *subs );
index 5b78eecf52a8d6cee1ce739ccd4730fe9632ad4b..150dca91750ca6a027654e693915ece526cea97e 100644 (file)
@@ -27,3 +27,79 @@ static bool _skaterift_script_intro( ent_script_event *event )
 
    return 1;
 }
+
+static void _skaterift_script_gino_send( ent_script_event *event, i32 which )
+{
+   i32 count = 0;
+   for( u32 i=0; i<event->entity_list->entity_ref_count; i ++ )
+   {
+      u32 ref_index = event->entity_list->entity_ref_start + i;
+      file_entity_ref *ref = af_arritm( &event->world->file_entity_ref, ref_index );
+      u32 type = mdl_entity_id_type( ref->entity_id ),
+          index = mdl_entity_id_id( ref->entity_id );
+
+      if( type == k_ent_marker )
+      {
+         if( count == which )
+         {
+            ent_marker *marker = af_arritm( &event->world->ent_marker, index );
+            _npc_gino_goto( marker->transform.co, which+1 );
+            break;
+         }
+
+         count ++;
+      }
+   }
+}
+
+static bool _skaterift_script_gino_intro( ent_script_event *event )
+{
+   static const cs_subtitle EN0[] = 
+   {
+      { "a1", KCOL_JESUS "Hello, I'm Gino!" },
+      { "a2", KCOL_JESUS "Do you remember who you are?" },
+      { "a3", KCOL_JESUS "Pick here." },
+      { NULL, NULL },
+   },
+   EN1[] = 
+   {
+      { "a1", KCOL_JESUS "Welcome to almost Heaven.." },
+      { "a2", KCOL_JESUS "For some reason the entrance is blocked" },
+      { "a3", KCOL_JESUS "You'll have to go back home for now" },
+      { "a4", KCOL_JESUS "There are people waiting for you after all." },
+      { NULL, NULL },
+   },
+   EN2[] =
+   {
+      { "a1", KCOL_JESUS "Might want to pick up one of these" },
+      { "a2", KCOL_JESUS "See you at the center Island." },
+      { NULL, NULL },
+   };
+
+   if( event->type == k_escript_event_world_start )
+   {
+      _npc_gino_speech( EN0 );
+      _skaterift_script_gino_send( event, 0 );
+      return 1;
+   }
+
+   if( on_function_trigger( event, 0 ) )
+   {
+      _npc_gino_speech( EN0 );
+      _skaterift_script_gino_send( event, 0 );
+   }
+
+   if( on_function_trigger( event, 1 ) )
+   {
+      _npc_gino_speech( EN1 );
+      _skaterift_script_gino_send( event, 1 );
+   }
+
+   if( on_function_trigger( event, 2 ) )
+   {
+      _npc_gino_speech( EN2 );
+      _skaterift_script_gino_send( event, 2 );
+   }
+
+   return 1;
+}
index 58a83dd164b9134cdc92b71dad2bfcb93a7df0ba..884e23f854950faa502c8e315c0937ab938b5f3d 100644 (file)
@@ -57,6 +57,7 @@
 #include "replay2.h"
 #include "user_profile.h"
 #include "ent_route.h"
+#include "npc_gino.h"
 
 struct skaterift_globals skaterift = 
 { 
@@ -128,6 +129,7 @@ static void game_load_co( vg_coroutine *co )
       vg_loader_step( ent_tornado_init, NULL );
       vg_loader_step( skaterift_load_player_content, NULL );
       vg_loader_step( _replay2_init, NULL );
+      vg_loader_step( _npc_gino_init, NULL );
 
       vg_loader_set_user_information( "Compiling shaders" );
       vg_bake_shaders();
@@ -656,6 +658,7 @@ void vg_framebuffer_resize( int w, int h )
 #include "compass.c"
 #include "replay2.c"
 #include "user_profile.c"
+#include "npc_gino.c"
 
 //TODO
 //#include "vg/submodules/hashmap.c/hashmap.c"
index 4ce4ebe253a0b78baf92eca30fce4d7c41c1e6be..7c5a69770f239a3e53933c206b54bb75863c4833 100644 (file)
@@ -710,6 +710,7 @@ struct ent_script_table_entry _ent_script_table[] =
    { "board_maker", _skaterift_script_board_maker },
 
    { "intro", _skaterift_script_intro },
+   { "gino.intro", _skaterift_script_gino_intro },
    { "hub", _skaterift_script_hub },
 
    { "tutorial_island", _skaterift_script_tutorial_island },
index ba08fd8c5250daaa99be9114cc36bed52884e530..ba492aed3b4a8c88c622ba50c129d11171608694 100644 (file)
@@ -40,6 +40,7 @@ void world_update( world_instance *world, v3f pos )
 {
    ent_script_update( world );
    ent_route_preupdate();
+   _npc_gino_preupdate();
    world_routes_update_timer_texts( world );
    world_routes_update( world );
    ent_traffic_update( world, pos );
@@ -54,6 +55,7 @@ void world_gui( ui_context *ctx, world_instance *world )
 {
    ent_skateshop_gui( ctx );
    _ent_challenge_ui( ctx );
+   _npc_gino_imgui( ctx );
 }
 
 bool world_set_event( enum world_event event )
index 2c8cdcca9210568b4bee359d48bf4ff748d8c322..776edf91ffe217b9c098287de70062fac4de3957 100644 (file)
@@ -269,6 +269,7 @@ struct world_static
       k_world_event_route_leaderboard,
       k_world_event_interact,
       k_world_event_board_maker,
+      k_world_event_gino,
       k_world_event_max
    }
    event;
index 05b5b42e7f567bf20c7de0b97445c52a6bc04181..588d2037ee417e908cae3c738ce646806652700c 100644 (file)
@@ -224,13 +224,14 @@ void render_world_map(void)
          if( challenge->flags & k_ent_challenge_locked ) 
             continue;
 
-         enum gui_icon icon = k_gui_icon_exclaim_2d;
-         if( challenge->status )
-            icon = k_gui_icon_tick_2d;
-
          u32 challenge_id = mdl_entity_id( k_ent_challenge, i );
-         respawn_map_draw_icon( &world_map.final_cam, icon, challenge->transform.co, 
-                                 world_map.closest_entity_id == challenge_id? 1.5f: 1.0f );
+         f32 scale = world_map.closest_entity_id == challenge_id? 1.5f: 1.0f;
+         respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_challenge, challenge->transform.co, scale );
+
+         if( challenge->status )
+            respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_tick2, challenge->transform.co, scale );
+         else
+            respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_tick1, challenge->transform.co, scale );
       }
 
       for( u32 i=0; i<af_arrcount(&world->ent_marker); i ++ )
@@ -292,8 +293,19 @@ void render_world_map(void)
          gui_icon_setcolour( colour );
 
          u32 route_id = mdl_entity_id( k_ent_route, i );
-         respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_rift_run_2d, route->board_transform[3], 
-                                 world_map.closest_entity_id == route_id? 1.5f: 1.0f );
+         f32 scale = world_map.closest_entity_id == route_id? 1.5f: 1.0f;
+         respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_run, route->board_transform[3], scale );
+                                 
+         if( route->flags & k_ent_route_flag_achieve_gold )
+         {
+            gui_icon_setcolour( (v4f){1,1,1,1} );
+            respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_tick2, route->board_transform[3], scale );
+         }
+         else if( route->flags & k_ent_route_flag_achieve_silver )
+         {
+            gui_icon_setcolour( (v4f){1,1,1,1} );
+            respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_tick1, route->board_transform[3], scale );
+         }
       }
 
       for( u32 i=0; i<af_arrcount(&world->ent_glider); i ++ )
index f52a5fecd8491d66a1ff1147da1c3c34cf761e9b..27c499e195131a5a588a7152fd10270bd818ff9d 100644 (file)
@@ -354,8 +354,7 @@ static void render_world_standard( world_instance *world, vg_camera *cam )
    world_render_both_stages( world, &pass );
 }
 
-static void bindpoint_world_cubemapped( world_instance *world,
-                                        struct world_surface *mat )
+static void bindpoint_world_cubemapped( world_instance *world, struct world_surface *mat )
 {
    struct shader_props_cubemapped *props = mat->info.props.compiled;
 
@@ -388,8 +387,7 @@ static void bindpoint_world_cubemapped_disabled( world_instance *world,
                   world_get_texture( world, props->tex_diffuse ) );
 }
 
-static void render_world_cubemapped( world_instance *world, vg_camera *cam,
-                                     int enabled )
+static void render_world_cubemapped( world_instance *world, vg_camera *cam, int enabled )
 {
    if( !af_arrcount( &world->ent_cubemap ) )
       return;
@@ -1062,6 +1060,7 @@ static void render_other_entities( world_instance *world, vg_camera *cam )
    }
 
    cutscene_render( world, cam );
+   _npc_gino_render( cam );
 }
 
 void render_world( world_instance *world, vg_camera *cam,
index bfa5064baadd06d8949e5142b4b6e0ed434f35b9..160c3252b8002cc471f19f124e25999faff4f4cc 100644 (file)
@@ -114,6 +114,7 @@ void world_volumes_update( world_instance *world, v3f pos )
             if( _world.active_trigger_volumes[i] == index )
                goto next_volume;
 
+         /* on enter */
          if( _world.active_trigger_volume_count > VG_ARRAY_LEN(_world.active_trigger_volumes) ) 
             continue;