+ v3f co;
+ remote_player_position( i, co );
+
+ if( player->active_world != world ){
+ continue;
+ }
+
+ f32 d2 = v3_dist2( co, localplayer.rb.co );
+
+ if( d2 > (max_dist*max_dist) )
+ continue;
+
+ f32 dist = sqrtf(d2);
+ f32 opacity = 0.95f * sqrtf(((max_dist-dist)/max_dist));
+
+ if( geo_cull ){
+ ray_hit hit;
+ hit.dist = dist;
+
+ v3f dir;
+ v3_sub( co, skaterift.cam.pos, dir );
+ v3_normalize( dir );
+
+ if( ray_world( world, skaterift.cam.pos, dir, &hit,
+ k_material_flag_ghosts ) ){
+ opacity *= 0.5f;
+ }
+ }
+
+ player->opacity = vg_lerpf( player->opacity, opacity,
+ vg.time_frame_delta * 2.0f );
+
+ remote_player_world_gui(
+ pv, netplayers.final_mtx[localplayer.skeleton.bone_count*i][3],
+ player );
+
+ vg_ui.colour[3] = player->opacity;
+ ui_flush( k_ui_shader_colour );
+ }
+ }
+
+ vg_ui.colour[3] = 1.0f;
+
+ remote_player_world_gui( pv, localplayer.rb.co, NULL );
+ ui_flush( k_ui_shader_colour );
+}
+
+static void chat_escape(void){
+ netplayers.chatting = -1;
+}
+
+static void chat_enter( char *buf, u32 len ){
+ vg_strncpy( buf, netplayers.chat_message, NETWORK_MAX_CHAT,
+ k_strncpy_always_add_null );
+ netplayers.chatting = -1;
+ netplayers.chat_time = vg.time_real;
+ chat_send_message( buf );
+}
+
+static void remote_players_chat_imgui(void){
+ if( netplayers.chatting == 1 ){
+ ui_rect box = { 0, 0, 400, 40 },
+ window = { 0, 0, vg.window_x, vg.window_y };
+ ui_rect_center( window, box );
+
+ struct ui_textbox_callbacks callbacks = {
+ .enter = chat_enter,
+ .escape = chat_escape
+ };
+
+ ui_textbox( box, NULL,
+ netplayers.chat_buffer, NETWORK_MAX_CHAT, 1,
+ UI_TEXTBOX_AUTOFOCUS, &callbacks );
+ }
+ else {
+ if( netplayers.chatting == -1 ){
+ netplayers.chatting = 0;
+ srinput.state = k_input_state_resume;
+ }
+ else {
+ if( (skaterift.activity == k_skaterift_default) &&
+ button_down( k_srbind_chat ) ){
+ netplayers.chatting = 1;
+ netplayers.chat_buffer[0] = '\0';
+ srinput.state = k_input_state_pause;
+ }