show friends in yellow, dont show out-of-world people
[carveJwlIkooP6JGAAIwe30JlM.git] / respawn.c
1 #ifndef RESPAWN_C
2 #define RESPAWN_C
3
4 #include "respawn.h"
5 #include "skaterift.h"
6 #include "world.h"
7 #include "input.h"
8 #include "gui.h"
9 #include "menu.h"
10 #include "scene.h"
11
12 static void respawn_chooser_get_dir( v3f dir ){
13 /* idk */
14 dir[0] = -sqrtf(0.5f);
15 dir[2] = sqrtf(0.5f);
16 dir[1] = 1.0f;
17 v3_normalize(dir);
18 }
19
20 static void respawn_chooser_get_plane( v4f plane ){
21 world_instance *world = &world_static.instances[ respawn_chooser.world_id ];
22 f32 h = localplayer.rb.co[1];
23 if( respawn_chooser.world_id != world_static.active_instance )
24 h = (world->scene_geo.bbx[0][1] + world->scene_geo.bbx[1][1]) * 0.5f;
25
26 v4_copy( (v4f){0.0f,1.0f,0.0f,h}, plane );
27 }
28
29 static void respawn_world_to_plane_pos( v3f pos, v2f plane_pos ){
30 v3f dir;
31 respawn_chooser_get_dir( dir );
32 v3_negate(dir,dir);
33 v4f plane;
34 respawn_chooser_get_plane( plane );
35
36 v3f co;
37 f32 t = ray_plane( plane, pos, dir );
38 v3_muladds( pos, dir, t, co );
39 plane_pos[0] = co[0];
40 plane_pos[1] = co[2];
41 }
42
43 static void respawn_chooser_setworld( u32 next ){
44 world_instance *nw = &world_static.instances[next];
45 if( nw->status == k_world_status_loaded ){
46 respawn_chooser.world_id = next;
47
48 v3f target;
49 if( next == world_static.active_instance )
50 v3_copy( localplayer.rb.co, target );
51 else {
52 scene_context *sc = &nw->scene_geo;
53 v3_lerp( sc->bbx[0], sc->bbx[1], 0.5f, target );
54 }
55 respawn_world_to_plane_pos( target, respawn_chooser.plane_pos );
56 }
57 }
58
59 static void respawn_chooser_gohome(void){
60 respawn_chooser_setworld(0);
61 world_instance *world = &world_static.instances[ respawn_chooser.world_id ];
62
63 const char **alias = respawn_homes[respawn_chooser.home_select];
64 ent_spawn *spawn = world_find_spawn_by_name( world, alias[0] );
65
66 if( spawn ){
67 respawn_world_to_plane_pos( spawn->transform.co,
68 respawn_chooser.plane_pos );
69
70 gui_location_print_ccmd( 1, (const char *[]){ alias[1] } );
71 }
72 else
73 gui_location_print_ccmd( 1, (const char *[]){ "Invalid home ID" } );
74 }
75
76 static void respawn_map_draw_icon( camera *cam,
77 enum gui_icon icon, v3f pos ){
78 v4f v;
79 v3_copy( pos, v );
80 v[3] = 1.0f;
81 m4x4_mulv( cam->mtx.pv, v, v );
82 v2_divs( v, v[3], v );
83
84 gui_draw_icon( icon, (v2f){ v[0]*0.5f+0.5f,v[1]*0.5f+0.5f }, 1.0f );
85 }
86
87 static void respawn_chooser_pre_update(void){
88 if( skaterift.activity != k_skaterift_respawning ) return;
89
90 gui_helper_action( joystick_display_string(k_srjoystick_steer,2), "move" );
91 if( world_static.instances[0].status == k_world_status_loaded )
92 gui_helper_action( axis_display_string(k_sraxis_mworld_h), "world" );
93 gui_helper_action( button_display_string(k_srbind_maccept), "spawn" );
94 gui_helper_action( button_display_string(k_srbind_home), "home" );
95
96 if( button_down( k_srbind_mback ) ){
97 srinput.enabled = 0;
98 skaterift.activity = k_skaterift_menu;
99 menu.page = 0xffffffff;
100 menu_open_page( "Main Menu", k_ent_menuitem_stack_append );
101 return;
102 }
103
104 if( button_down( k_srbind_maccept ) ){
105 skaterift.activity = k_skaterift_default;
106 srinput.enabled = 0;
107
108 if( respawn_chooser.spawn ){
109 world_static.active_instance = respawn_chooser.world_id;
110 localplayer.viewable_world =
111 &world_static.instances[ respawn_chooser.world_id ];
112 player__spawn( respawn_chooser.spawn );
113 }
114 return;
115 }
116
117 if( button_down( k_srbind_world_left ) ){
118 if( respawn_chooser.world_id > 0 )
119 respawn_chooser_setworld( respawn_chooser.world_id-1 );
120 }
121
122 if( button_down( k_srbind_world_right ) ){
123 u32 next = respawn_chooser.world_id+1;
124 if( next < vg_list_size(world_static.instances) )
125 respawn_chooser_setworld( next );
126 }
127
128 if( button_down(k_srbind_home) ){
129 respawn_chooser.home_select ++;
130 if( respawn_chooser.home_select >= vg_list_size(respawn_homes) )
131 respawn_chooser.home_select = 0;
132 respawn_chooser_gohome();
133 }
134
135 world_instance *world = &world_static.instances[ respawn_chooser.world_id ];
136 v3f *bbx = world->scene_geo.bbx;
137 f32 *pos = respawn_chooser.plane_pos;
138
139 v2f steer;
140 joystick_state( k_srjoystick_steer, steer );
141 v2_normalize_clamp( steer );
142
143 m2x2f rm;
144 m2x2_create_rotation( rm, -0.25f*VG_PIf );
145 m2x2_mulv( rm, steer, steer );
146
147 v2_muladds( pos, steer, vg.time_frame_delta * 200.0f, pos );
148 v2_minv( (v2f){ bbx[1][0], bbx[1][2] }, pos, pos );
149 v2_maxv( (v2f){ bbx[0][0], bbx[0][2] }, pos, pos );
150
151 /* update camera */
152 camera *cam = &respawn_chooser.cam;
153 v3f dir;
154 respawn_chooser_get_dir(dir);
155
156 v4f plane;
157 respawn_chooser_get_plane( plane );
158
159 v3f co = { pos[0], plane[3]*plane[1], pos[1] };
160 v3_muladds( co, dir, respawn_chooser.boom_dist, cam->pos );
161
162 vg_line_cross( co, VG__RED, 10.0f );
163
164 cam->angles[0] = 0.25f * VG_PIf;
165 cam->angles[1] = 0.25f * VG_PIf;
166 cam->farz = 5000.0f;
167 cam->nearz = 10.0f;
168 cam->fov = 40.0f;
169
170 camera_update_transform( cam );
171 camera_update_view( cam );
172 camera_update_projection( cam );
173 camera_finalize( cam );
174
175 /* pick spawn */
176 respawn_chooser.spawn = NULL;
177 f32 closest2 = INFINITY;
178
179 for( u32 i=0; i<mdl_arrcount(&world->ent_spawn); i++ ){
180 ent_spawn *spawn = mdl_arritm(&world->ent_spawn,i);
181
182 v4f v;
183 v3_copy( spawn->transform.co, v );
184 v[3] = 1.0f;
185 m4x4_mulv( cam->mtx.pv, v, v );
186 v2_divs( v, v[3], v );
187
188 f32 d2 = v2_length2(v);
189 if( d2 < closest2 ){
190 respawn_chooser.spawn = spawn;
191 closest2 = d2;
192 }
193 }
194
195 /* icons
196 * ---------------------*/
197 for( u32 i=0; i<mdl_arrcount(&world->ent_challenge); i++ ){
198 ent_challenge *challenge = mdl_arritm( &world->ent_challenge, i );
199
200 enum gui_icon icon = k_gui_icon_exclaim;
201 if( challenge->status )
202 icon = k_gui_icon_tick;
203
204 respawn_map_draw_icon( cam, icon, challenge->transform.co );
205 }
206
207 for( u32 i=0; i<mdl_arrcount(&world->ent_skateshop); i++ ){
208 ent_skateshop *shop = mdl_arritm( &world->ent_skateshop, i );
209 if( shop->type == k_skateshop_type_boardshop ){
210 respawn_map_draw_icon( cam, k_gui_icon_board, shop->transform.co );
211 }
212 else if( shop->type == k_skateshop_type_worldshop ){
213 respawn_map_draw_icon( cam, k_gui_icon_world, shop->transform.co );
214 }
215 }
216
217 for( u32 i=0; i<mdl_arrcount(&world->ent_gate); i++ ){
218 ent_gate *gate = mdl_arritm( &world->ent_gate, i );
219 if( gate->flags & k_ent_gate_nonlocal ){
220 respawn_map_draw_icon( cam, k_gui_icon_rift, gate->co[0] );
221 }
222 }
223
224 for( u32 i=0; i<mdl_arrcount(&world->ent_route); i++ ){
225 ent_route *route = mdl_arritm( &world->ent_route, i );
226
227 v4f colour;
228 v4_copy( route->colour, colour );
229 v3_muls( colour, 1.6666f, colour );
230 gui_icon_setcolour( colour );
231 respawn_map_draw_icon( cam, k_gui_icon_rift_run,
232 route->board_transform[3] );
233 }
234 }
235
236 static void respawn_begin_chooser(void){
237 skaterift.activity = k_skaterift_respawning;
238 respawn_chooser.world_id = world_static.active_instance;
239
240 world_instance *world = &world_static.instances[ respawn_chooser.world_id ];
241 v3f *bbx = world->scene_geo.bbx;
242
243 respawn_world_to_plane_pos( localplayer.rb.co, respawn_chooser.plane_pos );
244 respawn_chooser.boom_dist = 400.0f;
245 respawn_chooser.home_select = 0;
246 }
247
248 static void respawn_chooser_shader_uniforms(void){
249 v4f uPlayerPos, uSpawnPos;
250 v4_zero( uPlayerPos );
251 v4_zero( uSpawnPos );
252
253 v3_copy( localplayer.rb.co, uPlayerPos );
254
255 if( respawn_chooser.spawn )
256 v3_copy( respawn_chooser.spawn->transform.co, uSpawnPos );
257
258 uPlayerPos[3] = v3_dist(uPlayerPos,uSpawnPos);
259 uSpawnPos[3] = 1.0f/uPlayerPos[3];
260
261 shader_scene_override_uPlayerPos( uPlayerPos );
262 shader_scene_override_uSpawnPos( uSpawnPos );
263 }
264
265 #endif /* RESPAWN_C */