re-add non-local gates
authorhgn <hgodden00@gmail.com>
Wed, 22 Nov 2023 03:43:03 +0000 (03:43 +0000)
committerhgn <hgodden00@gmail.com>
Wed, 22 Nov 2023 03:43:03 +0000 (03:43 +0000)
19 files changed:
entity.h
maps_src/dev_hub/main.mdl
menu.h
models_src/rs_menu.mdl
player.c
player.h
player_skate.c
player_walk.c
player_walk.h
respawn.c
shaders/scene_override.fs
shaders/scene_override.h
skaterift.c
world_entity.c
world_gate.c
world_gate.h
world_load.c
world_render.c
world_routes.c

index 612ad61ec27e8239ecbc3eda1f11aff8c3a7e1ef..c3b6694b23c3a3ef329306ea1e0c2799ca2ca5d8 100644 (file)
--- a/entity.h
+++ b/entity.h
@@ -113,7 +113,7 @@ enum gate_type{
 /* v102+ */
 enum ent_gate_flag{
    k_ent_gate_linked      = 0x1, /* this is a working portal */
-   k_ent_gate_nonlocal_DELETED = 0x2, /* use the key string to link this portal.
+   k_ent_gate_nonlocal    = 0x2, /* use the key string to link this portal.
                                        NOTE: if set, it adds the flip flag. */
    k_ent_gate_flip        = 0x4, /* flip direction 180* for exiting portal */
    k_ent_gate_custom_mesh = 0x8, /* use a custom submesh instead of default */
index 9274c3f08d193bbf3fd803eb2381610689407a8e..43fb44ef1ba799ae38c64cf889b8f4f46a3a032a 100644 (file)
Binary files a/maps_src/dev_hub/main.mdl and b/maps_src/dev_hub/main.mdl differ
diff --git a/menu.h b/menu.h
index 0a49777e14e4b1c740e2d59cb34b9ffa0259c3c7..c9865732b6912e4a54a98106ba49ebfc59be294f 100644 (file)
--- a/menu.h
+++ b/menu.h
@@ -246,21 +246,16 @@ static void menu_trigger_item( ent_menuitem *item ){
          vg.window_should_close = 1;
       }
 
-      else if( MDL_CONST_PSTREQ( &menu.model, q, "reset" ) ){
-
-         /* FIXME: Should only be availible in CLIENT WORLD */
+      else if( MDL_CONST_PSTREQ( &menu.model, q, "map" ) ){
 
          menu_close();
          respawn_begin_chooser();
-         
-         /* FIXME: Need a back to hub button */
-#if 0
+      }
+      else if( MDL_CONST_PSTREQ( &menu.model, q, "hub" ) ){
          srinput.state = k_input_state_resume;
          menu_close();
          ent_miniworld_goback();
-#endif
       }
-
       else if( MDL_CONST_PSTREQ( &menu.model, q, "credits" ) ){
          menu.credits_open = 1;
       }
index eb04eb092b8b909295dbecd5c5e1885849e6c764..590edc3837cc5de6150566b6e0443d292709351b 100644 (file)
Binary files a/models_src/rs_menu.mdl and b/models_src/rs_menu.mdl differ
index 7a2dff5c01e491967b9dc6a25f15208274643432..3ba64eb0f38881808be33c5c0311665423bce99d 100644 (file)
--- a/player.c
+++ b/player.c
@@ -136,6 +136,18 @@ static void player__pass_gate( u32 id ){
                                cc->cam_velocity_smooth );
 
    m4x3_mulv( gate->transport, localplayer.cam.pos, localplayer.cam.pos );
+
+   if( gate->flags & k_ent_gate_nonlocal ){
+      /* FIXME: Code dupe with world_load.c */
+      ent_spawn *rp = world_find_spawn_by_name( world, "start" );
+      if( !rp ) rp = world_find_closest_spawn( world, (v3f){0.0f,0.0f,0.0f} );
+      /* TODO: fallback to searching for a safe location using raycasts */
+      assert(rp);
+      v3_copy( rp->transform.co, world->player_co );
+
+      world_static.active_instance = gate->target;
+      player__clean_refs();
+   }
    
    v3f v0;
    v3_angles_vector( localplayer.angles, v0 );
@@ -221,25 +233,10 @@ static void player__setpos( v3f pos ){
    rb_update_transform( &localplayer.rb );
 }
 
-static void player__reset(void){
+static void player__clean_refs(void){
    replay_clear( &skaterift.replay );
    gui_helper_clear();
 
-   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_transform( &localplayer.rb );
-
-   localplayer.subsystem = k_player_subsystem_walk;
-   player__walk_reset();
-
-   localplayer.immobile = 0;
-   localplayer.gate_waiting = NULL;
-
    world_static.challenge_target = NULL;
    world_static.challenge_timer = 0.0f;
    world_static.focused_entity = 0;
@@ -255,8 +252,26 @@ static void player__reset(void){
          world_routes_clear( instance );
       }
    }
+}
+
+static void player__reset(void){
+   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_transform( &localplayer.rb );
+
+   localplayer.subsystem = k_player_subsystem_walk;
+   player__walk_reset();
+
+   localplayer.immobile = 0;
+   localplayer.gate_waiting = NULL;
 
    v3_copy( localplayer.rb.co, localplayer.cam_control.tpv_lpf );
+   player__clean_refs();
 }
 
 static void player__spawn( ent_spawn *rp ){
index 63cd302d673f6f518db6e0130a1b88899ef14b01..939033a5296cca74b86692ac701279453f7b7a07 100644 (file)
--- a/player.h
+++ b/player.h
@@ -192,6 +192,7 @@ static void player__pass_gate( u32 id );
 static void player__im_gui(void);
 static void player__setpos( v3f pos );
 static void player__spawn( ent_spawn *rp );
+static void player__clean_refs(void);
 static void player__reset(void);
 static void player__kill(void);
 static void player__begin_holdout( v3f offset );
index 522ea3010a3fd93cf909063e4f6be1397203c202..63315a80d6830889219717348ff47c5641d9ef96 100644 (file)
@@ -483,6 +483,9 @@ static void player__approximate_best_trajectory(void){
                m4x3_mulv( gate->transport, co1, co1 );
                m3x3_mulv( gate->transport, launch_v, launch_v);
                m4x3_mulv( gate->transport, launch_co, launch_co );
+
+               if( gate->flags & k_ent_gate_nonlocal )
+                  trace_world = &world_static.instances[ gate->target ];
             }
          }
 
@@ -2025,11 +2028,9 @@ static void player__skate_update(void){
 
    if( world->water.enabled ){
       if( localplayer.rb.co[1]+0.25f < world->water.height ){
-#if 0
          player__networked_sfx( k_player_subsystem_walk, 32, 
                                 k_player_walk_soundeffect_splash,
                                 localplayer.rb.co, 1.0f );
-#endif
          player__skate_kill_audio();
          player__dead_transition();
          return;
index e269166630dfd85c0eb909fbdc8b34e3c7902867..12d070609153c20fbad6d62abc34055457c85ef3 100644 (file)
@@ -432,7 +432,9 @@ static void player__walk_update(void){
 
    if( world->water.enabled ){
       if( localplayer.rb.co[1]+0.4f < world->water.height ){
-         audio_oneshot_3d( &audio_splash, localplayer.rb.co, 40.0f, 1.0f );
+         player__networked_sfx( k_player_subsystem_walk, 32, 
+                                k_player_walk_soundeffect_splash,
+                                localplayer.rb.co, 1.0f );
          player__dead_transition();
          return;
       }
@@ -1064,4 +1066,14 @@ static void player__walk_animator_exchange( bitpack_ctx *ctx, void *data ){
                      &animator->pitch );
    }
 }
+
+static void player__walk_sfx_oneshot( u8 id, v3f pos, f32 volume ){
+   audio_lock();
+
+   if( id == k_player_walk_soundeffect_splash ){
+      audio_oneshot_3d( &audio_splash, pos, 40.0f, 1.0f );
+   }
+
+   audio_unlock();
+}
 #endif /* PLAYER_DEVICE_WALK_H */
index 7d3c0eba9d50ed6acdb73615c7b755a30d03a747..28e38a4347825b18bd1c9670e53ea6a9c2b38f3a 100644 (file)
@@ -75,6 +75,10 @@ struct player_walk{
 }
 static player_walk;
 
+enum player_walk_soundeffect {
+   k_player_walk_soundeffect_splash
+};
+
 static f32
    k_walkspeed             = 10.0f,
    k_airspeed              = 1.2f,
index b0235202244ef2f14bd151341db747a195cbec33..d8c470a83679fdfaa35d38c5796863313c3602dc 100644 (file)
--- a/respawn.c
+++ b/respawn.c
@@ -190,6 +190,13 @@ static void respawn_chooser_pre_update(void){
       }
    }
 
+   for( u32 i=0; i<mdl_arrcount(&world->ent_gate); i++ ){
+      ent_gate *gate = mdl_arritm( &world->ent_gate, i );
+      if( gate->flags & k_ent_gate_nonlocal ){
+         respawn_map_draw_icon( cam, k_gui_icon_rift, gate->co[0] );
+      }
+   }
+
    for( u32 i=0; i<mdl_arrcount(&world->ent_route); i++ ){
       ent_route *route = mdl_arritm( &world->ent_route, i );
 
index 2ab8d8daccdc5d92c54130bb4cb4d77d01a15858..237fe6b49adfc2055ed3673e1004c50311543d6a 100644 (file)
@@ -70,10 +70,9 @@ void main(){
    if( uIsoAmt > 0.0 ){
       float height = fract( aCo.y * 0.1 );
       float lg = 2.0*length(vec2(dFdx(height), dFdy(height)));
-      vfrag *= 1.0f+(lg*0.4*uIsoAmt);
+      vfrag *= 1.0f+(lg*0.2*uIsoAmt);
    }
 
-
    oColour = vec4( vfrag, 1.0 );
    //oColour = vec4( vfrag, 1.0 );
 }
index b457233fd5cc433a512c9bab719516deefcecc1d..74caeffcdfa1430a73d30f7de8703839d6ad6456 100644 (file)
@@ -516,13 +516,16 @@ static struct vg_shader _shader_scene_override = {
 "   float d3 = distance(p0,aCo);\n"
 "   emit += vec3(fract(t*0.2-g_realtime+d3*0.2)*max(0.0,1.0-d3*0.2));\n"
 "\n"
+"   vfrag += emit;\n"
+"\n"
 "   if( uIsoAmt > 0.0 ){\n"
 "      float height = fract( aCo.y * 0.1 );\n"
 "      float lg = 2.0*length(vec2(dFdx(height), dFdy(height)));\n"
-"      emit += vec3(lg*0.1*uIsoAmt);\n"
+"      vfrag *= 1.0f+(lg*0.4*uIsoAmt);\n"
 "   }\n"
 "\n"
-"   oColour = vec4( vfrag+emit, 1.0 );\n"
+"\n"
+"   oColour = vec4( vfrag, 1.0 );\n"
 "   //oColour = vec4( vfrag, 1.0 );\n"
 "}\n"
 ""},
index 7da7109f0afb0ff4952cd8629d73369fa091836a..326e02c65c2d6c75ad85b317cc1cc281b585d909 100644 (file)
@@ -443,6 +443,16 @@ static void render_player_transparent(void){
    player__render( &small_cam );
 }
 
+static world_instance *get_view_world(void){
+   world_instance *view_world = world_current_instance();
+   if( localplayer.gate_waiting && 
+         (localplayer.gate_waiting->flags & k_ent_gate_nonlocal) ){
+      view_world = &world_static.instances[world_static.active_instance ^ 0x1];
+   }
+
+   return view_world;
+}
+
 static void render_scene(void){
    /* Draw world */
    glEnable( GL_DEPTH_TEST );
@@ -481,7 +491,14 @@ static void render_scene(void){
       return;
    }
 
-   render_world( world_current_instance(), &skaterift.cam, 0, 0, 1, 1 );
+   world_instance *view_world = get_view_world();
+   render_world( view_world, &skaterift.cam, 0, 0, 1, 1 );
+
+   /* 
+    * render transition 
+    */
+   if( global_miniworld.transition == 0 ) 
+      return;
 
    world_instance *holdout_world = NULL;
    f32 t = 0.0f;
@@ -490,32 +507,28 @@ static void render_scene(void){
       holdout_world = &world_static.instances[ k_world_purpose_hub ];
       t = global_miniworld.t;
    }
-   else if( global_miniworld.transition == -1 ){
+   else{
       holdout_world = &world_static.instances[ k_world_purpose_client ];
       t = 1.0f-global_miniworld.t;
    }
-   else {
-   }
 
-   if( holdout_world ){
-      if( holdout_world->status != k_world_status_loaded )
-         return;
+   if( holdout_world->status != k_world_status_loaded )
+      return;
 
-      t = vg_smoothstepf( t );
+   t = vg_smoothstepf( t );
 
-      glEnable( GL_STENCIL_TEST );
-      glDisable( GL_DEPTH_TEST );
-      glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );  
-      glStencilFunc( GL_ALWAYS, 1, 0xFF ); 
-      glStencilMask( 0xFF );
+   glEnable( GL_STENCIL_TEST );
+   glDisable( GL_DEPTH_TEST );
+   glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );  
+   glStencilFunc( GL_ALWAYS, 1, 0xFF ); 
+   glStencilMask( 0xFF );
 
-      shader_blit_transition_use();
-      shader_blit_transition_uInverseRatio( (v2f){1.0f,1.0f} );
-      shader_blit_transition_uT( -(sqrtf(2)+0.5f) * t );
+   shader_blit_transition_use();
+   shader_blit_transition_uInverseRatio( (v2f){1.0f,1.0f} );
+   shader_blit_transition_uT( -(sqrtf(2)+0.5f) * t );
 
-      render_fsquad();
-      render_world( holdout_world, &global_miniworld.cam, 1, 0, 1, 1 );
-   }
+   render_fsquad();
+   render_world( holdout_world, &global_miniworld.cam, 1, 0, 1, 1 );
 }
 
 static void skaterift_composite_maincamera(void){
@@ -569,8 +582,14 @@ static void render_main_game(void){
    skaterift_composite_maincamera();
 
    /* --------------------------------------------------------------------- */
-   if( skaterift.activity != k_skaterift_respawning )
-      render_world_cubemaps( world_current_instance() );
+   if( skaterift.activity != k_skaterift_respawning ){
+      world_instance *world = world_current_instance();
+      render_world_cubemaps( world );
+
+      ent_gate *nlg = world->rendering_gate;
+      if( nlg && nlg->flags & k_ent_gate_nonlocal )
+         render_world_cubemaps( &world_static.instances[nlg->target] );
+   }
 
    /* variable res target */
    render_fb_bind( gpipeline.fb_main, 1 );
@@ -592,7 +611,7 @@ static void render_main_game(void){
    if( !global_miniworld.transition && 
          (skaterift.activity != k_skaterift_respawning) ){
       render_fb_bind( gpipeline.fb_main, 1 );
-      render_world_gates( world_current_instance(), &skaterift.cam );
+      render_world_gates( get_view_world(), &skaterift.cam );
    }
 
    /* composite */
index 47b846c658102cf29f1a038ff012e4b7b61532b1..2ba975baf04dc1b3b714870d47cda681b3b44c12 100644 (file)
@@ -118,10 +118,12 @@ static void world_gen_entities_init( world_instance *world ){
    for( u32 j=0; j<mdl_arrcount(&world->ent_gate); j ++ ){
       ent_gate *gate = mdl_arritm( &world->ent_gate, j );
 
-      if( !(gate->flags & k_ent_gate_nonlocal_DELETED) ) {
+      if( !(gate->flags & k_ent_gate_nonlocal) ) {
          gate_transform_update( gate );
       }
    }
+      
+   vg_async_call( world_link_nonlocal_async, world, 0 );
 
    /* water */
    for( u32 j=0; j<mdl_arrcount(&world->ent_water); j++ ){
index accdc06ed9195382798fa52b184ef69ed93a005a..be339cf587603482e124053b3134090aeb99cdd0 100644 (file)
@@ -250,8 +250,11 @@ static u32 world_intersect_gates( world_instance *world, v3f pos, v3f last ){
       if( !(gate->flags & k_ent_gate_linked) ) continue;
       if( gate->flags & k_ent_gate_locked ) continue;
 
-      if( gate->flags & k_ent_gate_nonlocal_DELETED )
-         continue;
+      if( gate->flags & k_ent_gate_nonlocal ){
+         if( world_static.instances[gate->target].status 
+               != k_world_status_loaded )
+            continue;
+      }
 
       if( gate_intersect( gate, pos, last ) )
          return mdl_entity_id( k_ent_gate, i );
@@ -273,4 +276,87 @@ static void ent_gate_call( world_instance *world, ent_call *call ){
    }
 }
 
+
+/* 
+ * detatches any nonlocal gates 
+ */
+static void world_unlink_nonlocal( world_instance *world ){
+   for( u32 j=0; j<mdl_arrcount(&world->ent_gate); j ++ ){
+      ent_gate *gate = mdl_arritm( &world->ent_gate, j );
+
+      if( gate->flags & k_ent_gate_nonlocal ){
+         gate->flags &= ~k_ent_gate_linked;
+      }
+   }
+}
+
+/* 
+ * attatches nonlocal gates, to be called from main thread ONLY! 
+ */
+static void world_link_nonlocal_async( void *payload, u32 size ){
+   world_instance *world = payload;
+   u32 world_id = world - world_static.instances;
+
+   for( u32 j=0; j<mdl_arrcount(&world->ent_gate); j ++ ){
+      ent_gate *gate = mdl_arritm( &world->ent_gate, j );
+
+      if( !(gate->flags & k_ent_gate_nonlocal) ) continue;
+      if( gate->flags & k_ent_gate_linked ) continue;
+
+      const char *key = mdl_pstr( &world->meta, gate->key );
+      vg_info( "key: %s\n", key );
+
+      for( u32 i=0; i<vg_list_size(world_static.instances); i++ ){
+         world_instance *other = &world_static.instances[i];
+         if( other == world ) continue;
+         if( other->status != k_world_status_loaded ) continue;
+         vg_info( "Checking world %u for key matches\n", i );
+
+         for( u32 k=0; k<mdl_arrcount( &other->ent_gate ); k++ ){
+            ent_gate *gate2 = mdl_arritm( &other->ent_gate, k );
+
+            if( !(gate2->flags & k_ent_gate_nonlocal) ) continue;
+            if( gate2->flags & k_ent_gate_linked ) continue;
+
+            const char *key2 = mdl_pstr( &other->meta, gate2->key );
+            vg_info( " key2: %s\n", key2 );
+
+            if( strcmp( key, key2 ) ) continue;
+
+            vg_success( "Non-local matching pair '%s' found. (%u:%u)\n",
+                         key, world_id, i );
+
+            gate->flags |= k_ent_gate_linked;
+            gate2->flags |= k_ent_gate_linked;
+            gate->target = i;
+            gate2->target = world_id;
+
+            v3_copy( gate->co[0], gate2->co[1] );
+            v3_copy( gate2->co[0], gate->co[1] );
+            v4_copy( gate->q[0], gate2->q[1] );
+            v4_copy( gate2->q[0], gate->q[1] );
+
+            if( world->meta.info.version < 102 ){
+               /* LEGACY BEHAVIOUR: v101
+                *   this would flip both the client worlds portal's entrance and
+                *   exit. effectively the clients portal would be the opposite 
+                *   to the hub worlds one. new behaviour is to just flip the 
+                *   destinations so the rules are consistent in each world.
+                */
+               v4f qflip;
+               q_axis_angle( qflip, (v3f){0.0f,1.0f,0.0f}, VG_PIf );
+               q_mul( gate->q[0], qflip, gate->q[0] );
+               q_mul( gate->q[1], qflip, gate->q[1] );
+               q_mul( gate2->q[1], qflip, gate2->q[1] );
+            }
+
+            gate_transform_update( gate );
+            gate_transform_update( gate2 );
+
+            goto matched;
+         }
+      } matched:;
+   }
+}
+
 #endif /* WORLD_GATE_C */
index 2201f766f00ed79fe26de1aa4ed36b75616c2383..f1b4f027fd6a4e0632f1f2e3168452bd1361713d 100644 (file)
@@ -29,4 +29,7 @@ static u32 world_intersect_gates( world_instance *world, v3f pos, v3f last );
 static void ent_gate_call( world_instance *world, ent_call *call );
 static void ent_gate_get_mdl_mtx( ent_gate *gate, m4x3f mmdl );
 
+static void world_link_nonlocal_async( void *payload, u32 size );
+static void world_unlink_nonlocal( world_instance *world );
+
 #endif /* WORLD_GATE_H */
index e2c2bb3f3c6c783304f8e0a540713e325f4792ec..78bd332a472a507e2a7c4e54532554677b349dcd 100644 (file)
@@ -300,19 +300,19 @@ static void skaterift_change_world_start( addon_reg *reg ){
 
       vg_linear_clear( vg_mem.scratch ); /* ?? */
       vg_info( "unloading old worlds\n" );
-      
-      for( u32 i=1; i<vg_list_size(world_static.instances); i++ ){
-         world_instance *inst = &world_static.instances[i];
 
-         if( inst->status == k_world_status_loaded ){
-            inst->status = k_world_status_unloading;
-            world_fadeout_audio( inst );
-         }
+      world_instance *client_world = 
+         &world_static.instances[ k_world_purpose_client ];
+
+      if( client_world->status == k_world_status_loaded ){
+         client_world->status = k_world_status_unloading;
+         world_fadeout_audio( client_world );
       }
 
       world_static.instance_addons[ k_world_purpose_client ] = reg;
       network_send_item( k_netmsg_playeritem_world1 );
       relink_all_remote_player_worlds();
+      world_unlink_nonlocal( &world_static.instances[k_world_purpose_hub] );
    }
 }
 
index 1546429235fe10b36e8643aa2132417a306dcc94..281a6e7a69cb8f75857d4ac16f49aa5a4ba8ff8a 100644 (file)
@@ -763,10 +763,6 @@ static void render_world_gates( world_instance *world, camera *cam ){
    for( u32 i=0; i<mdl_arrcount(&world->ent_gate); i++ ){
       ent_gate *gi = mdl_arritm( &world->ent_gate, i );
 
-      if( !(gi->flags & (k_ent_gate_linked|k_ent_gate_nonlocal_DELETED|
-                         k_ent_gate_locked)) )
-         continue;
-
       float dist = v3_dist2( gi->co[0], cam->transform[3] );
 
       vg_line_point( gi->co[0], 0.25f, VG__BLUE );
@@ -778,8 +774,25 @@ static void render_world_gates( world_instance *world, camera *cam ){
    }
    
    world->rendering_gate = gate;
-   if( gate )
-      render_gate( world, world, gate, cam );
+
+   if( gate ){
+      if( gate->flags & k_ent_gate_locked ){
+         world->rendering_gate = NULL;
+         return;
+      }
+
+      if( gate->flags & k_ent_gate_nonlocal ){
+         if( world_static.load_state != k_world_loader_none ){
+            world->rendering_gate = NULL;
+            return;
+         }
+
+         world_instance *dest_world = &world_static.instances[ gate->target ];
+         render_gate( world, dest_world, gate, cam );
+      }
+      else
+         render_gate( world, world, gate, cam );
+   }
 }
 
 static void world_prerender( world_instance *world ){
index 5f6d283a50dc0183621be8ef968c1fba4d56b13b..33d84db5cb8ff2a80ada0c8e2064634493afa3e5 100644 (file)
@@ -541,7 +541,7 @@ static void world_gen_routes_ent_init( world_instance *world ){
          }
 
          if( (gate->flags & k_ent_gate_linked) &
-            !(gate->flags & k_ent_gate_nonlocal_DELETED) ){
+            !(gate->flags & k_ent_gate_nonlocal) ){
             gate = mdl_arritm(&world->ent_gate, gate->target );
 
             for( u32 k=0; k<4; k++ ){
@@ -994,7 +994,7 @@ static void render_world_routes( world_instance *world,
 
          for( u32 j=0; j<mdl_arrcount(&world->ent_gate); j ++ ){
             ent_gate *gate = mdl_arritm( &world->ent_gate, j );
-            if( !(gate->flags & k_ent_gate_nonlocal_DELETED) )
+            if( !(gate->flags & k_ent_gate_nonlocal) )
                render_gate_markers( mmdl, i, gate );
          }
       }