6 #include "player_model.h"
8 VG_STATIC
int localplayer_cmd_respawn( int argc
, const char *argv
[] )
10 ent_spawn
*rp
= NULL
, *r
;
11 world_instance
*world
= localplayer
.viewable_world
;
14 rp
= world_find_spawn_by_name( world
, argv
[0] );
17 rp
= world_find_closest_spawn( world
, localplayer
.rb
.co
);
23 player__spawn( &localplayer
, rp
);
27 VG_STATIC
void player_init(void)
29 for( u32 i
=0; i
<vg_list_size(_player_system_register
); i
++ ){
30 if( _player_system_register
[i
] )
31 _player_system_register
[i
]();
34 vg_console_reg_cmd( "respawn", localplayer_cmd_respawn
, NULL
);
38 void player__debugtext( int size
, const char *fmt
, ... )
43 va_start( args
, fmt
);
44 vsnprintf( buffer
, 1024, fmt
, args
);
47 ui_text( vg_uictx
.cursor
, buffer
, size
, k_text_align_right
);
48 vg_uictx
.cursor
[1] += 14*size
;
55 void player__create( player_instance
*inst
)
57 static int only_once
= 0;
58 assert( only_once
== 0 );
61 inst
->input_js1h
= vg_create_named_input( "steer-h", k_input_type_axis
);
62 inst
->input_js1v
= vg_create_named_input( "steer-v", k_input_type_axis
);
63 inst
->input_grab
= vg_create_named_input( "grab", k_input_type_axis_norm
);
64 inst
->input_js2h
= vg_create_named_input( "grab-h", k_input_type_axis
);
65 inst
->input_js2v
= vg_create_named_input( "grab-v", k_input_type_axis
);
66 inst
->input_jump
= vg_create_named_input( "jump", k_input_type_button
);
67 inst
->input_push
= vg_create_named_input( "push", k_input_type_button
);
68 inst
->input_walk
= vg_create_named_input( "walk", k_input_type_button
);
69 inst
->input_walkh
= vg_create_named_input( "walk-h", k_input_type_axis
);
70 inst
->input_walkv
= vg_create_named_input( "walk-v", k_input_type_axis
);
71 inst
->input_use
= vg_create_named_input( "use", k_input_type_button
);
72 inst
->input_reset
= vg_create_named_input( "reset", k_input_type_button
);
73 inst
->input_camera
=vg_create_named_input( "camera", k_input_type_button
);
74 inst
->input_trick0
=vg_create_named_input( "trick0", k_input_type_button
);
75 inst
->input_trick1
=vg_create_named_input( "trick1", k_input_type_button
);
76 inst
->input_trick2
=vg_create_named_input( "trick2", k_input_type_button
);
78 const char *default_cfg
[] =
80 "bind steer-h gp-ls-h",
84 "bind steer-v gp-ls-v",
90 "bind grab-h gp-rs-h",
91 "bind grab-v gp-rs-v",
100 "bind trick2 gp-x", /* keyboard: m0 + m1 */
108 "bind walk-h gp-ls-h",
109 "bind walk-v -gp-ls-v",
124 for( int i
=0; i
<vg_list_size(default_cfg
); i
++ )
125 vg_execute_console_input(default_cfg
[i
]);
127 v3_zero( inst
->rb
.co
);
128 v3_zero( inst
->rb
.w
);
129 v3_zero( inst
->rb
.v
);
130 q_identity( inst
->rb
.q
);
131 m4x3_identity( inst
->rb
.to_world
);
132 m4x3_identity( inst
->rb
.to_local
);
134 inst
->rewind_length
= 0;
135 inst
->rewind_buffer
=
136 vg_linear_alloc( vg_mem
.rtmemory
,
137 sizeof(struct rewind_frame
) * PLAYER_REWIND_FRAMES
);
145 void player__use_avatar( player_instance
*player
, struct player_avatar
*av
)
147 player
->playeravatar
= av
;
148 player_setup_ragdoll_from_avatar( &player
->ragdoll
, av
);
152 void player__use_model( player_instance
*player
, struct player_model
*mdl
)
154 player
->playermodel
= mdl
;
158 void player__bind( player_instance
*player
)
160 for( u32 i
=0; i
<vg_list_size(_player_bind
); i
++ ){
161 if( _player_bind
[i
] )
162 _player_bind
[i
]( player
);
168 * ----------------------------------------------------------------------------
171 VG_STATIC
void player_save_rewind_frame( player_instance
*player
)
173 if( player
->rewind_length
< PLAYER_REWIND_FRAMES
){
174 struct rewind_frame
*fr
=
175 &player
->rewind_buffer
[ player
->rewind_length
++ ];
177 v2_copy( player
->cam
.angles
, fr
->ang
);
178 v3_copy( player
->cam
.pos
, fr
->pos
);
180 if( player
->rewind_length
>= 2 ){
181 player
->rewind_total_length
+=
182 v3_dist( player
->rewind_buffer
[player
->rewind_length
-1].pos
,
183 player
->rewind_buffer
[player
->rewind_length
-2].pos
);
189 void player__pre_update( player_instance
*player
)
191 if( player
->rewinding
){
195 if( vg_input_button_down( player
->input_reset
) && !player
->immobile
){
196 double delta
= world_global
.time
- world_global
.last_use
;
198 if( (delta
<= RESET_MAX_TIME
) && (world_global
.last_use
!= 0.0) ){
199 player
->rewinding
= 1;
200 player
->rewind_sound_wait
= 1;
201 player
->rewind_time
= (double)player
->rewind_length
- 0.0001;
202 player_save_rewind_frame( player
);
205 audio_oneshot( &audio_rewind
[0], 1.0f
, 0.0f
);
208 /* based on testing. DONT CHANGE!
210 * time taken: y = (x^(4/5)) * 74.5
211 * inverse : x = (2/149)^(4/5) * y^(4/5)
214 float constant
= powf( 2.0f
/149.0f
, 4.0f
/5.0f
),
215 curve
= powf( player
->rewind_total_length
, 4.0f
/5.0f
);
217 player
->rewind_predicted_time
= constant
* curve
;
218 player
->rewind_start
= vg
.time
;
219 player
->subsystem
= player
->subsystem_gate
;
220 player
->rb
= player
->rb_gate_storage
;
221 v3_copy( player
->angles_storage
, player
->angles
);
223 if( _player_restore
[ player
->subsystem
] )
224 _player_restore
[ player
->subsystem
]( player
);
227 if( player
->subsystem
== k_player_subsystem_dead
){
228 localplayer_cmd_respawn( 0, NULL
);
233 audio_oneshot( &audio_rewind
[4], 1.0f
, 0.0f
);
239 if( vg_input_button_down( player
->input_camera
) && !player
->immobile
){
240 if( player
->camera_mode
== k_cam_firstperson
)
241 player
->camera_mode
= k_cam_thirdperson
;
243 player
->camera_mode
= k_cam_firstperson
;
246 if( _player_pre_update
[ player
->subsystem
] )
247 _player_pre_update
[ player
->subsystem
]( player
);
251 void player__update( player_instance
*player
)
253 if( player
->rewinding
)
256 if( _player_update
[ player
->subsystem
] )
257 _player_update
[ player
->subsystem
]( player
);
261 void player__post_update( player_instance
*player
)
263 if( player
->rewinding
)
266 if( _player_post_update
[ player
->subsystem
] )
267 _player_post_update
[ player
->subsystem
]( player
);
269 if((player
->subsystem
!= k_player_subsystem_dead
) && !player
->gate_waiting
){
270 player
->rewind_accum
+= vg
.time_frame_delta
;
272 if( player
->rewind_accum
> 0.25f
){
273 player
->rewind_accum
-= 0.25f
;
274 player_save_rewind_frame( player
);
280 * Applies gate transport to a player_interface
283 void player__pass_gate( player_instance
*player
, ent_gate
*gate
)
285 world_routes_fracture( get_active_world(), gate
,
286 player
->rb
.co
, player
->rb
.v
);
288 player
->gate_waiting
= gate
;
289 world_routes_activate_entry_gate( get_active_world(), gate
);
291 m4x3_mulv( gate
->transport
, player
->tpv_lpf
, player
->tpv_lpf
);
292 m3x3_mulv( gate
->transport
, player
->cam_velocity_smooth
,
293 player
->cam_velocity_smooth
);
295 m3x3_copy( player
->basis
, player
->basis_gate
);
298 m3x3_q( gate
->transport
, q
);
299 q_mul( q
, player
->qbasis
, player
->qbasis
);
300 q_normalize( player
->qbasis
);
301 q_m3x3( player
->qbasis
, player
->basis
);
302 m3x3_transpose( player
->basis
, player
->invbasis
);
304 player
->subsystem_gate
= player
->subsystem
;
305 player
->rb_gate_storage
= player
->rb
;
306 v3_copy( player
->angles
, player
->angles_storage
);
307 player
->rewind_length
= 0;
308 player
->rewind_total_length
= 0.0f
;
309 player
->rewind_gate
= gate
;
310 player
->rewind_accum
= 0.0f
;
312 m4x3_mulv( gate
->transport
, player
->cam
.pos
, player
->cam
.pos
);
313 player_save_rewind_frame( player
);
315 if( gate
->type
== k_gate_type_nonlocel
)
316 world_global
.active_world
= gate
->target
;
318 world_global
.in_volume
= 0;
321 audio_oneshot( &audio_gate_pass
, 1.0f
, 0.0f
);
325 VG_STATIC
void player_apply_transport_to_cam( m4x3f transport
)
327 /* FIXME: Applies to main_camera directly! */
329 /* Pre-emptively edit the camera matrices so that the motion vectors
333 m4x3_invert_affine( transport
, transport_i
);
334 m4x3_expand( transport_i
, transport_4
);
335 m4x4_mul( main_camera
.mtx
.pv
, transport_4
, main_camera
.mtx
.pv
);
336 m4x4_mul( main_camera
.mtx
.v
, transport_4
, main_camera
.mtx
.v
);
338 /* we want the regular transform here no the inversion */
339 m4x3_expand( transport
, transport_4
);
340 m4x4_mul( gate_camera
.mtx
.pv
, transport_4
, gate_camera
.mtx
.pv
);
341 m4x4_mul( gate_camera
.mtx
.v
, transport_4
, gate_camera
.mtx
.v
);
344 __attribute__ ((deprecated
))
345 VG_STATIC
void gate_rotate_angles( ent_gate
*gate
, v3f angles
, v3f d
)
347 v3_copy( angles
, d
);
350 v3f fwd_dir
= { cosf(angles
[0]),
353 m3x3_mulv( gate
->transport
, fwd_dir
, fwd_dir
);
355 v3_copy( angles
, d
);
356 d
[0] = atan2f( fwd_dir
[2], fwd_dir
[0] );
359 PLAYER_API
void player__im_gui( player_instance
*player
)
361 vg_uictx
.cursor
[0] = vg
.window_x
- 200;
362 vg_uictx
.cursor
[1] = 0;
363 vg_uictx
.cursor
[2] = 200;
364 vg_uictx
.cursor
[3] = 200;
366 struct ui_vert
*b
= ui_fill_rect( vg_uictx
.cursor
, 0x70000000 );
368 vg_uictx
.cursor
[0] = vg
.window_x
;
370 player__debugtext( 1, "angles: " PRINTF_v3f( player
->cam
.angles
) );
371 player__debugtext( 1, "basis: " PRINTF_v4f( player
->qbasis
) );
373 if( _player_im_gui
[ player
->subsystem
] )
374 _player_im_gui
[ player
->subsystem
]( player
);
376 b
[2].co
[1] = vg_uictx
.cursor
[1];
377 b
[3].co
[1] = vg_uictx
.cursor
[1];
380 VG_STATIC
void global_skateshop_exit(void);
381 PLAYER_API
void player__spawn( player_instance
*player
,
384 v3_copy( rp
->transform
.co
, player
->rb
.co
);
385 v3_zero( player
->rb
.v
);
386 v3_zero( player
->rb
.w
);
387 q_identity( player
->rb
.q
);
388 rb_update_transform( &player
->rb
);
390 q_identity( player
->qbasis
);
391 m3x3_identity( player
->basis
);
392 m3x3_identity( player
->invbasis
);
394 player
->subsystem
= k_player_subsystem_walk
;
395 player
->immobile
= 0;
396 player
->gate_waiting
= NULL
;
398 global_skateshop_exit();
400 if( _player_reset
[ player
->subsystem
] )
401 _player_reset
[ player
->subsystem
]( player
, rp
);
405 PLAYER_API
void player__kill( player_instance
*player
)
410 #endif /* PLAYER_C */