4 #include "player_api.h"
6 #include "player_common.h"
7 #include "player_walk.h"
8 #include "player_skate.h"
9 #include "player_dead.h"
11 struct player_instance
13 /* transform definition */
18 m3x3f basis
, invbasis
, basis_gate
;
22 * ---------------------------
24 camera cam
; /* output final camera */
28 k_cam_firstperson
= 0,
32 float camera_type_blend
;
35 v3f fpv_offset
, /* expressed relative to rigidbody */
37 fpv_viewpoint
, /* expressed relative to neck bone inverse final */
44 float cam_velocity_influence
,
45 cam_velocity_coefficient
,
46 cam_velocity_constant
,
47 cam_velocity_coefficient_smooth
,
48 cam_velocity_constant_smooth
,
49 cam_velocity_influence_smooth
,
53 teleport_gate
*gate_waiting
;
57 * --------------------------------
59 struct input_binding
*input_js1h
,
78 * --------------------------------------------------
81 struct player_avatar
*playeravatar
;
83 struct player_ragdoll ragdoll
;
86 player_pose holdout_pose
;
91 * -------------------------------------------------
96 k_player_subsystem_walk
= 0,
97 k_player_subsystem_skate
= 1,
98 k_player_subsystem_dead
= 2
102 struct player_skate _skate
;
103 struct player_walk _walk
;
104 struct player_dead _dead
;
109 * ---------------------------------------------------------
113 void (*_player_bind
[])( player_instance
*player
) =
121 void (*_player_reset
[])( player_instance
*player
, struct respawn_point
*rp
) =
129 void (*_player_pre_update
[])( player_instance
*player
) =
131 player__walk_pre_update
,
132 player__skate_pre_update
,
137 void( *_player_update
[])( player_instance
*player
) =
140 player__skate_update
,
145 void( *_player_post_update
[])( player_instance
*player
) =
147 player__walk_post_update
,
148 player__skate_post_update
,
153 void( *_player_im_gui
[])( player_instance
*player
) =
156 player__skate_im_gui
,
161 void( *_player_animate
[])( player_instance
*player
, player_animation
*dest
) =
163 player__walk_animate
,
164 player__skate_animate
,
169 void( *_player_post_animate
[])( player_instance
*player
) =
171 player__walk_post_animate
,
172 player__skate_post_animate
,
173 player__dead_post_animate
179 #include "player_common.c"
180 #include "player_walk.c"
181 #include "player_skate.c"
182 #include "player_dead.c"
184 #endif /* PLAYER_H */
189 * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
196 #define PLAYER_REWIND_FRAMES 60*4
202 #include "skeleton.h"
207 * -----------------------------------------------------------------------------
209 * -----------------------------------------------------------------------------
212 VG_STATIC
struct gplayer
214 rigidbody rb
, rb_frame
;
215 v3f co
, angles
; /* used as transfer between controllers */
217 enum player_controller
219 k_player_controller_walk
,
220 k_player_controller_skate
,
221 k_player_controller_ragdoll
,
222 k_player_controller_mountain_skate
,
223 k_player_controller_snowboard
,
224 k_player_controller_drive
229 m4x3f visual_transform
,
230 inv_visual_transform
;
232 int is_dead
, death_tick_allowance
, rewinding
;
233 int rewind_sound_wait
;
236 v3f handl_target
, handr_target
,
240 struct input_binding
*input_js1h
,
255 v3f camera_pos
, smooth_localcam
;
263 u32 rewind_incrementer
,
266 float rewind_time
, rewind_total_length
, rewind_predicted_time
;
267 double diag_rewind_start
, diag_rewind_time
;
290 enum mdl_surface_prop surface_prop
;
295 glmesh player_meshes
[3];
299 struct skeleton_anim
*anim_stand
,
303 *anim_push
, *anim_push_reverse
,
304 *anim_ollie
, *anim_ollie_reverse
,
305 *anim_grabs
, *anim_stop
,
306 *anim_walk
, *anim_run
, *anim_idle
,
326 /* Collider transform relative to bone */
340 rb_constr_pos position_constraints
[32];
341 u32 position_constraints_count
;
343 rb_constr_swingtwist cone_constraints
[32];
344 u32 cone_constraints_count
;
355 .collide_front
= { .type
= k_rb_shape_sphere
, .inf
.sphere
.radius
= 0.3f
},
356 .collide_back
= { .type
= k_rb_shape_sphere
, .inf
.sphere
.radius
= 0.3f
}
365 VG_STATIC
float *player_get_pos(void);
366 VG_STATIC
void player_kill(void);
367 VG_STATIC
float *player_cam_pos(void);
368 VG_STATIC
void player_save_frame(void);
369 VG_STATIC
void player_restore_frame(void);
370 VG_STATIC
void player_save_rewind_frame(void);
375 VG_STATIC
void player_mouseview(void);
377 #include "player_physics.h"
378 #include "player_physics_skate.h"
379 #include "player_physics_walk.h"
380 #include "player_ragdoll.h"
381 #include "player_model.h"
382 #include "player_animation.h"
383 #include "player_audio.h"
386 * player_physics_<INTERFACE>_<SUB-INTERFACE>
393 * -----------------------------------------------------------------------------
395 * -----------------------------------------------------------------------------
397 VG_STATIC
int kill_player( int argc
, char const *argv
[] );
398 VG_STATIC
int reset_player( int argc
, char const *argv
[] );
399 VG_STATIC
void reset_player_poll( int argc
, char const *argv
[] );
401 VG_STATIC
void player_init(void) /* 1 */
404 player
.input_js1h
= vg_create_named_input( "steer-h", k_input_type_axis
);
405 player
.input_js1v
= vg_create_named_input( "steer-v", k_input_type_axis
);
406 player
.input_grab
= vg_create_named_input( "grab", k_input_type_axis_norm
);
407 player
.input_js2h
= vg_create_named_input( "grab-h", k_input_type_axis
);
408 player
.input_js2v
= vg_create_named_input( "grab-v", k_input_type_axis
);
409 player
.input_jump
= vg_create_named_input( "jump", k_input_type_button
);
410 player
.input_push
= vg_create_named_input( "push", k_input_type_button
);
411 player
.input_walk
= vg_create_named_input( "walk", k_input_type_button
);
413 player
.input_walkh
= vg_create_named_input( "walk-h",
415 player
.input_walkv
= vg_create_named_input( "walk-v",
419 player
.input_switch_mode
= vg_create_named_input( "switch-mode",
420 k_input_type_button
);
421 player
.input_reset
= vg_create_named_input( "reset", k_input_type_button
);
423 const char *default_cfg
[] =
425 "bind steer-h gp-ls-h",
429 "bind steer-v gp-ls-v",
435 "bind grab-h gp-rs-h",
436 "bind grab-v gp-rs-v",
447 "bind walk-h gp-ls-h",
448 "bind walk-v -gp-ls-v",
457 "bind switch-mode gp-y",
458 "bind switch-mode e",
461 for( int i
=0; i
<vg_list_size(default_cfg
); i
++ )
462 vg_execute_console_input(default_cfg
[i
]);
465 rb_init( &player
.rb
);
467 VG_VAR_F32( k_walkspeed
);
468 VG_VAR_F32( k_stopspeed
);
469 VG_VAR_F32( k_airspeed
);
470 VG_VAR_F32( k_walk_friction
);
471 VG_VAR_F32( k_walk_air_accel
);
472 VG_VAR_F32( k_runspeed
);
473 VG_VAR_F32( k_walk_accel
);
475 VG_VAR_I32( freecam
);
476 VG_VAR_I32( cl_thirdperson
);
477 VG_VAR_F32_PERSISTENT( fc_speed
);
479 /* TODO: NOT PERSISTENT */
480 VG_VAR_F32( k_ragdoll_limit_scale
);
481 VG_VAR_I32( k_ragdoll_div
);
482 VG_VAR_I32( k_ragdoll_debug_collider
);
483 VG_VAR_I32( k_ragdoll_debug_constraints
);
485 VG_VAR_F32( k_friction_lat
);
487 VG_VAR_F32( k_cog_spring
);
488 VG_VAR_F32( k_cog_damp
);
490 VG_VAR_F32( k_cog_mass_ratio
);
491 VG_VAR_F32( k_downforce
);
493 VG_VAR_F32( k_spring_force
);
494 VG_VAR_F32( k_spring_dampener
);
495 VG_VAR_F32( k_spring_angular
);
497 VG_VAR_F32( k_mmthrow_scale
);
498 VG_VAR_F32( k_mmcollect_lat
);
499 VG_VAR_F32( k_mmcollect_vert
);
500 VG_VAR_F32( k_mmdecay
);
502 vg_function_push( (struct vg_cmd
){
504 .function
= reset_player
,
505 .poll_suggest
= reset_player_poll
508 vg_function_push( (struct vg_cmd
){
510 .function
= kill_player
516 player
.rewind_length
= 0;
517 player
.rewind_buffer
=
518 vg_linear_alloc( vg_mem
.rtmemory
,
519 sizeof(struct rewind_frame
) * PLAYER_REWIND_FRAMES
);
524 VG_STATIC
void player_save_rewind_frame(void)
526 if( player
.rewind_length
< PLAYER_REWIND_FRAMES
)
528 struct rewind_frame
*fr
=
529 &player
.rewind_buffer
[ player
.rewind_length
++ ];
531 v2_copy( player
.angles
, fr
->ang
);
532 v3_copy( player
.camera_pos
, fr
->pos
);
534 player
.rewind_incrementer
= 0;
536 if( player
.rewind_length
> 1 )
538 player
.rewind_total_length
+=
539 v3_dist( player
.rewind_buffer
[player
.rewind_length
-1].pos
,
540 player
.rewind_buffer
[player
.rewind_length
-2].pos
);
547 VG_STATIC
int menu_enabled(void);
550 VG_STATIC
void player_do_motion(void);
552 * Free camera movement
554 VG_STATIC
void player_mouseview(void)
559 v2_muladds( player
.angles
, vg
.mouse_delta
, 0.0025f
, player
.angles
);
561 if( vg_input
.controller_should_use_trackpad_look
)
563 static v2f last_input
;
565 static v2f vel_smooth
;
567 v2f input
= { player
.input_js2h
->axis
.value
,
568 player
.input_js2v
->axis
.value
};
570 if( (v2_length2(last_input
) > 0.001f
) && (v2_length2(input
) > 0.001f
) )
572 v2_sub( input
, last_input
, vel
);
573 v2_muls( vel
, 1.0f
/vg
.time_delta
, vel
);
580 v2_lerp( vel_smooth
, vel
, vg
.time_delta
*8.0f
, vel_smooth
);
582 v2_muladds( player
.angles
, vel_smooth
, vg
.time_delta
, player
.angles
);
583 v2_copy( input
, last_input
);
587 player
.angles
[0] += player
.input_js2h
->axis
.value
* vg
.time_delta
* 4.0f
;
588 player
.angles
[1] += player
.input_js2v
->axis
.value
* vg
.time_delta
* 4.0f
;
591 player
.angles
[1] = vg_clampf( player
.angles
[1], -VG_PIf
*0.5f
, VG_PIf
*0.5f
);
594 /* Deal with input etc */
595 VG_STATIC
void player_update_pre(void)
600 v3_copy( main_camera
.pos
, ra
);
601 v3_muladds( ra
, main_camera
.transform
[2], -10.0f
, rb
);
604 if( spherecast_world( ra
, rb
, 0.4f
, &t
, rx
) != -1 )
607 m3x3_identity( mtx
);
608 v3_lerp( ra
, rb
, t
, mtx
[3] );
610 debug_sphere( mtx
, 0.4f
, 0xff00ff00 );
613 v3_muladds( mtx
[3], rx
, 0.4f
, x1
);
614 vg_line( mtx
[3], x1
, 0xffffffff );
620 vg_line_pt3( phys
->cog
, 0.10f
, 0xffffffff );
621 vg_line_pt3( phys
->cog
, 0.09f
, 0xffffffff );
622 vg_line_pt3( phys
->cog
, 0.08f
, 0xffffffff );
623 vg_line( phys
->cog
, phys
->rb
.co
, 0xff000000 );
626 v3f throw_end
, p0
, p1
;
627 v3_muladds( phys
->rb
.co
, phys
->rb
.up
, 1.0f
, spring_end
);
628 v3_muladds( spring_end
, phys
->throw_v
, 1.0f
, throw_end
);
629 v3_muladds( spring_end
, player
.debug_mmcollect_lat
, 1.0f
, p0
);
630 v3_muladds( spring_end
, player
.debug_mmcollect_vert
, 1.0f
, p1
);
631 vg_line( spring_end
, throw_end
, VG__RED
);
632 vg_line( spring_end
, p0
, VG__GREEN
);
633 vg_line( spring_end
, p1
, VG__BLUE
);
636 if( player
.rewinding
)
639 if( vg_input_button_down( player
.input_reset
) && !menu_enabled() )
641 double delta
= world
.time
- world
.last_use
;
643 if( (delta
<= RESET_MAX_TIME
) && (world
.last_use
!= 0.0) )
645 player
.rewinding
= 1;
646 player
.rewind_sound_wait
= 1;
647 player
.rewind_time
= (float)player
.rewind_length
- 0.0001f
;
648 player_save_rewind_frame();
650 audio_play_oneshot( &audio_rewind
[0], 1.0f
);
653 /* based on analytical testing. DONT CHANGE!
655 * time taken: y = (x^(4/5)) * 74.5
656 * inverse : x = (2/149)^(4/5) * y^(4/5)
659 float constant
= powf( 2.0f
/149.0f
, 4.0f
/5.0f
),
660 curve
= powf( player
.rewind_total_length
, 4.0f
/5.0f
);
662 player
.rewind_predicted_time
= constant
* curve
;
663 player
.diag_rewind_start
= vg
.time
;
664 player
.diag_rewind_time
= player
.rewind_time
;
667 player
.death_tick_allowance
= 30;
668 player_restore_frame();
670 if( player
.controller
== k_player_controller_walk
)
672 player
.angles
[0] = atan2f( -player
.rb
.forward
[2],
673 -player
.rb
.forward
[0] );
676 player
.mdl
.shoes
[0] = 1;
677 player
.mdl
.shoes
[1] = 1;
679 world_routes_notify_reset();
681 /* apply 1 frame of movement */
688 reset_player( 0, NULL
);
694 audio_play_oneshot( &audio_rewind
[4], 1.0f
);
700 if( vg_input_button_down( player
.input_switch_mode
) && !menu_enabled() )
705 if( phys
->controller
== k_player_controller_walk
)
707 phys
->controller
= k_player_controller_skate
;
709 v3_muladds( phys
->rb
.v
, phys
->rb
.forward
, 0.2f
, phys
->rb
.v
);
710 audio_play_oneshot( &audio_lands
[6], 1.0f
);
712 else if( phys
->controller
== k_player_controller_skate
)
714 phys
->controller
= k_player_controller_walk
;
716 audio_play_oneshot( &audio_lands
[5], 1.0f
);
723 if( player
.controller
== k_player_controller_walk
)
727 VG_STATIC
void player_update_fixed(void) /* 2 */
729 if( player
.rewinding
)
732 if( player
.death_tick_allowance
)
733 player
.death_tick_allowance
--;
737 player_ragdoll_iter();
741 player
.rewind_incrementer
++;
743 if( player
.rewind_incrementer
> (u32
)(0.25/VG_TIMESTEP_FIXED
) )
745 player_save_rewind_frame();
752 VG_STATIC
void player_update_post(void)
755 for( int i
=0; i
<player
.prediction_count
; i
++ )
757 struct land_prediction
*p
= &player
.predictions
[i
];
759 for( int j
=0; j
<p
->log_length
- 1; j
++ )
760 vg_line( p
->log
[j
], p
->log
[j
+1], p
->colour
);
762 vg_line_cross( p
->log
[p
->log_length
-1], p
->colour
, 0.25f
);
765 v3_add( p
->log
[p
->log_length
-1], p
->n
, p1
);
766 vg_line( p
->log
[p
->log_length
-1], p1
, 0xffffffff );
773 player_debug_ragdoll();
776 player_animate_death_cam();
785 player_animate_camera_thirdperson();
787 player_animate_camera();
795 /* CAMERA POSITIONING: LAYER 0 */
796 v2_copy( player
.angles
, main_camera
.angles
);
797 v3_copy( player
.camera_pos
, main_camera
.pos
);
800 if( player
.rewinding
)
802 if( player
.rewind_time
<= 0.0f
)
804 double taken
= vg
.time
- player
.diag_rewind_start
;
805 vg_success( "Rewind took (rt, pl, tl): %f, %f, %f\n",
806 taken
, player
.diag_rewind_time
,
807 player
.rewind_total_length
);
809 player
.rewinding
= 0;
810 player
.rewind_length
= 1;
811 player
.rewind_total_length
= 0.0f
;
812 player
.rewind_incrementer
= 0;
813 world
.sky_target_rate
= 1.0;
817 world
.sky_target_rate
= -100.0;
818 assert( player
.rewind_length
> 0 );
823 float budget
= vg
.time_delta
,
824 overall_length
= player
.rewind_length
;
826 world_routes_rollback_time( player
.rewind_time
/ overall_length
);
828 for( int i
=0; (i
<10)&&(player
.rewind_time
>0.0f
)&&(budget
>0.0f
); i
++ )
830 /* Interpolate frames */
831 int i0
= floorf( player
.rewind_time
),
832 i1
= VG_MIN( i0
+1, player
.rewind_length
-1 );
834 struct rewind_frame
*fr
= &player
.rewind_buffer
[i0
],
835 *fr1
= &player
.rewind_buffer
[i1
];
837 float dist
= vg_maxf( v3_dist( fr
->pos
, fr1
->pos
), 0.001f
),
838 subl
= vg_fractf( player
.rewind_time
) + 0.001f
,
840 sramp
= 3.0f
-(1.0f
/(0.4f
+0.4f
*player
.rewind_time
)),
841 speed
= sramp
*28.0f
+ 0.5f
*player
.rewind_time
,
842 mod
= speed
* (budget
/ dist
),
844 advl
= vg_minf( mod
, subl
),
845 advt
= (advl
/ mod
) * budget
;
847 player
.dist_accum
+= speed
* advt
;
848 player
.rewind_time
-= advl
;
852 player
.rewind_time
= vg_maxf( 0.0f
, player
.rewind_time
);
854 float current_time
= vg
.time
- player
.diag_rewind_start
,
855 remaining
= player
.rewind_predicted_time
- current_time
;
857 if( player
.rewind_sound_wait
)
859 if( player
.rewind_predicted_time
>= 6.5f
)
861 if( remaining
<= 6.5f
)
864 audio_play_oneshot( &audio_rewind
[3], 1.0f
);
866 player
.rewind_sound_wait
= 0;
869 else if( player
.rewind_predicted_time
>= 2.5f
)
871 if( remaining
<= 2.5f
)
874 audio_play_oneshot( &audio_rewind
[2], 1.0f
);
876 player
.rewind_sound_wait
= 0;
879 else if( player
.rewind_predicted_time
>= 1.5f
)
881 if( remaining
<= 1.5f
)
884 audio_play_oneshot( &audio_rewind
[1], 1.0f
);
886 player
.rewind_sound_wait
= 0;
891 int i0
= floorf( player
.rewind_time
),
892 i1
= VG_MIN( i0
+1, player
.rewind_length
-1 );
894 struct rewind_frame
*fr
= &player
.rewind_buffer
[i0
],
895 *fr1
= &player
.rewind_buffer
[i1
];
897 float sub
= vg_fractf(player
.rewind_time
);
899 v3_lerp( fr
->pos
, fr1
->pos
, sub
, override_pos
);
900 override_angles
[0] = vg_alerpf( fr
->ang
[0], fr1
->ang
[0], sub
);
901 override_angles
[1] = vg_lerpf ( fr
->ang
[1], fr1
->ang
[1], sub
);
903 /* CAMERA POSITIONING: LAYER 1 */
904 float blend
= (4.0f
-player
.rewind_time
) * 0.25f
,
905 c
= vg_clampf( blend
, 0.0f
, 1.0f
);
907 main_camera
.angles
[0] =
908 vg_alerpf(override_angles
[0], player
.angles
[0], c
);
909 main_camera
.angles
[1] =
910 vg_lerpf (override_angles
[1], player
.angles
[1], c
);
911 v3_lerp( override_pos
, player
.camera_pos
, c
, main_camera
.pos
);
916 camera_update_transform( &main_camera
);
920 VG_STATIC
void draw_player( camera
*cam
)
923 player_model_copy_ragdoll();
925 shader_viewchar_use();
926 vg_tex2d_bind( &tex_characters
, 0 );
927 shader_viewchar_uTexMain( 0 );
928 shader_viewchar_uCamera( cam
->transform
[3] );
929 shader_viewchar_uPv( cam
->mtx
.pv
);
930 shader_link_standard_ub( _shader_viewchar
.id
, 2 );
931 glUniformMatrix4x3fv( _uniform_viewchar_uTransforms
,
932 player
.mdl
.sk
.bone_count
,
934 (float *)player
.mdl
.sk
.final_mtx
);
936 mesh_bind( &player
.mdl
.player_meshes
[cl_playermdl_id
] );
937 mesh_draw( &player
.mdl
.player_meshes
[cl_playermdl_id
] );
940 VG_STATIC
void player_do_motion(void)
942 if( world
.water
.enabled
)
944 if( (player
.rb
.co
[1] < 0.0f
) && !player
.is_dead
)
947 audio_player_set_flags( &audio_player_extra
, AUDIO_FLAG_SPACIAL_3D
);
948 audio_player_set_position( &audio_player_extra
, player
.rb
.co
);
949 audio_player_set_vol( &audio_player_extra
, 20.0f
);
950 audio_player_playclip( &audio_player_extra
, &audio_splash
);
958 v3_copy( player
.rb
.co
, prevco
);
960 if( player
.controller
== k_player_controller_skate
)
963 player_skate_update();
967 player_walk_physics( &player_walky
);
970 /* Real angular velocity integration */
972 v3_lerp( phys
->rb
.w
, (v3f
){0.0f
,0.0f
,0.0f
}, 0.125f
*0.5f
, phys
->rb
.w
);
973 if( v3_length2( phys
->rb
.w
) > 0.0f
)
977 v3_copy( phys
->rb
.w
, axis
);
979 float mag
= v3_length( axis
);
980 v3_divs( axis
, mag
, axis
);
981 q_axis_angle( rotation
, axis
, mag
*k_rb_delta
);
982 q_mul( rotation
, phys
->rb
.q
, phys
->rb
.q
);
985 /* Faux angular velocity */
988 float lerpq
= (player_skate
.activity
== k_skate_activity_air
)? 0.04f
: 0.3f
;
989 phys
->siY
= vg_lerpf( phys
->siY
, phys
->iY
, lerpq
);
991 q_axis_angle( rotate
, phys
->rb
.up
, phys
->siY
);
992 q_mul( rotate
, phys
->rb
.q
, phys
->rb
.q
);
997 * Gate intersection, by tracing a line over the gate planes
1000 for( int i
=0; i
<world
.gate_count
; i
++ )
1002 struct route_gate
*rg
= &world
.gates
[i
];
1003 teleport_gate
*gate
= &rg
->gate
;
1005 if( gate_intersect( gate
, phys
->rb
.co
, prevco
) )
1007 m4x3_mulv( gate
->transport
, phys
->rb
.co
, phys
->rb
.co
);
1008 m4x3_mulv( gate
->transport
, phys
->cog
, phys
->cog
);
1009 m3x3_mulv( gate
->transport
, phys
->cog_v
, phys
->cog_v
);
1010 m3x3_mulv( gate
->transport
, phys
->rb
.v
, phys
->rb
.v
);
1011 m3x3_mulv( gate
->transport
, phys
->vl
, phys
->vl
);
1012 m3x3_mulv( gate
->transport
, phys
->v_last
, phys
->v_last
);
1013 m3x3_mulv( gate
->transport
, phys
->m
, phys
->m
);
1014 m3x3_mulv( gate
->transport
, phys
->bob
, phys
->bob
);
1016 /* Pre-emptively edit the camera matrices so that the motion vectors
1020 m4x3_invert_affine( gate
->transport
, transport_i
);
1021 m4x3_expand( transport_i
, transport_4
);
1022 m4x4_mul( main_camera
.mtx
.pv
, transport_4
, main_camera
.mtx
.pv
);
1023 m4x4_mul( main_camera
.mtx
.v
, transport_4
, main_camera
.mtx
.v
);
1025 v4f transport_rotation
;
1026 m3x3_q( gate
->transport
, transport_rotation
);
1027 q_mul( transport_rotation
, phys
->rb
.q
, phys
->rb
.q
);
1029 world_routes_activate_gate( i
);
1031 if( phys
->controller
== k_player_controller_walk
)
1033 v3f fwd_dir
= {cosf(player
.angles
[0]),
1035 sinf(player
.angles
[0])};
1036 m3x3_mulv( gate
->transport
, fwd_dir
, fwd_dir
);
1038 player
.angles
[0] = atan2f( fwd_dir
[2], fwd_dir
[0] );
1041 player
.rewind_length
= 0;
1042 player
.rewind_total_length
= 0.0f
;
1043 player
.rewind_incrementer
= 10000;
1044 player_save_frame();
1047 audio_play_oneshot( &audio_gate_pass
, 1.0f
);
1054 rb_update_transform( &player
.rb
);
1058 * -----------------------------------------------------------------------------
1059 * API implementation
1060 * -----------------------------------------------------------------------------
1063 VG_STATIC
float *player_get_pos(void)
1065 return player
.rb
.co
;
1068 VG_STATIC
void player_kill(void)
1070 if( player
.death_tick_allowance
== 0 )
1073 player_ragdoll_copy_model( player
.rb
.v
);
1077 VG_STATIC
float *player_cam_pos(void)
1079 return player
.camera_pos
;
1083 VG_STATIC
void player_save_frame(void)
1085 player
.controller_frame
= player
.controller
;
1087 /* TODO <interface>->save() */
1090 VG_STATIC
void player_restore_frame(void)
1092 player
.controller
= player
.controller_frame
;
1094 /* TODO <interface>->load() */
1097 #endif /* PLAYER_H */