X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=player.h;h=ecf595d42c51a731daecfef6b4e99bdbaf43fd5c;hb=9eb3de757a997becb8406417a4bf613f4cb04900;hp=f63069240bcd3f2b83b15fc88b59ba6fa9cc2fcf;hpb=c52e639cdcf6d21f69caa9625238afded7513ca4;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/player.h b/player.h index f630692..ecf595d 100644 --- a/player.h +++ b/player.h @@ -1,861 +1,246 @@ -/* - * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved - */ - -/* - * TODO: Tilt camera down to face borde when its behind you or out of vision - */ - #ifndef PLAYER_H #define PLAYER_H -#define PLAYER_REWIND_FRAMES 60*4 - -#include "conf.h" -#include "audio.h" -#include "common.h" -#include "world.h" -#include "skeleton.h" -#include "bvh.h" - -VG_STATIC float - k_walkspeed = 12.0f, - k_air_accelerate = 20.0f, - - k_runspeed = 20.0f, - k_board_radius = 0.3f, - k_board_length = 0.45f, - k_board_allowance = 0.04f, - //k_friction_lat = 8.8f, - k_friction_lat = 12.0f, - k_friction_resistance = 0.01f, - k_max_push_speed = 16.0f, - k_push_accel = 10.0f, - k_push_cycle_rate = 8.0f, - k_steer_ground = 2.5f, - k_steer_air = 3.6f, - k_steer_air_lerp = 0.3f, - k_pump_force = 0.0f, - k_downforce = 8.0f, - k_walk_downforce = 8.0f, - k_jump_charge_speed = (1.0f/1.0f), - k_jump_force = 5.0f, - k_pitch_limit = 1.5f, - k_look_speed = 2.0f, - k_walk_accel = 150.0f, - k_walk_friction = 8.0f; - -VG_STATIC int freecam = 0; -VG_STATIC int walk_grid_iterations = 1; -VG_STATIC float fc_speed = 10.0f; -VG_STATIC int cl_thirdperson = 0; - -/* - * ----------------------------------------------------------------------------- - * Memory - * ----------------------------------------------------------------------------- - */ - -VG_STATIC struct gplayer -{ - /* Physics */ - rigidbody collide_front, collide_back; - - struct player_phys - { - rigidbody rb, rb_gate_frame; - float iY, siY; /* Yaw inertia */ - - v3f a, v_last, m, bob, vl; +#include "skaterift.h" - /* Utility */ - float vswitch, slip, slip_last, reverse; - float grab, jump, pushing, push_time, rise; - v2f grab_mouse_delta; - - int lift_frames; - - double start_push; - int in_air, on_board, jump_charge, jump_dir, grind; - - m3x3f vr,vr_pstep; - } - phys, - phys_gate_frame; - - m4x3f visual_transform, - inv_visual_transform; - - int is_dead, death_tick_allowance, rewinding; - int rewind_sound_wait; - - struct land_prediction - { - v3f log[50]; - v3f n; - u32 log_length; - float score; - - enum prediction_type - { - k_prediction_none, - k_prediction_land, - k_prediction_grind - } - type; - - u32 colour; - } - predictions[22]; - u32 prediction_count; - - v3f handl_target, handr_target, - handl, handr; - - /* Input */ - struct input_binding *input_js1h, - *input_js1v, - *input_js2h, - *input_js2v, - *input_jump, - *input_push, - *input_walk, - *input_walkh, - *input_walkv, - *input_switch_mode, - *input_reset, - *input_grab; - - /* Camera */ - float air_blend; - float air_time; - - v3f camera_pos, smooth_localcam; - v2f angles; - - struct rewind_frame - { - v3f pos; - v2f ang; - } - *rewind_buffer; - u32 rewind_incrementer, - rewind_length; - - float rewind_time, rewind_total_length, rewind_predicted_time; - double diag_rewind_start, diag_rewind_time; - float dist_accum; - - /* animation */ - double jump_time; - float fslide, - fdirz, fdirx, - fstand, - ffly, - fpush, - fairdir, - fsetup, - walk_timer, - fjump, - fonboard, - frun, - fgrind; - - float walk; - int step_phase; - enum mdl_surface_prop surface_prop; - - /* player model */ - struct player_model - { - glmesh player_meshes[3]; - - mdl_context meta; - struct skeleton sk; - struct skeleton_anim *anim_stand, - *anim_highg, - *anim_slide, - *anim_air, - *anim_push, *anim_push_reverse, - *anim_ollie, *anim_ollie_reverse, - *anim_grabs, *anim_stop, - *anim_walk, *anim_run, *anim_idle, - *anim_jump; - - u32 id_hip, - id_ik_hand_l, - id_ik_hand_r, - id_ik_elbow_l, - id_ik_elbow_r, - id_head; - - v3f cam_pos; - - struct ragdoll_part - { - u32 bone_id; - //v3f offset; - - /* Collider transform relative to bone */ - m4x3f collider_mtx, - inv_collider_mtx; - - u32 use_limits; - v3f limits[2]; - - rigidbody rb; - u32 parent; - u32 colour; - } - ragdoll[32]; - u32 ragdoll_count; - - rb_constr_pos position_constraints[32]; - u32 position_constraints_count; - - rb_constr_swingtwist cone_constraints[32]; - u32 cone_constraints_count; - - int shoes[2]; - } - mdl; -} -player = -{ - .collide_front = { .type = k_rb_shape_sphere, .inf.sphere.radius = 0.3f }, - .collide_back = { .type = k_rb_shape_sphere, .inf.sphere.radius = 0.3f } +enum player_subsystem{ + k_player_subsystem_walk = 0, + k_player_subsystem_skate = 1, + k_player_subsystem_dead = 2, + k_player_subsystem_drive = 3 }; -/* - * API - */ -VG_STATIC float *player_get_pos(void); -VG_STATIC void player_kill(void); -VG_STATIC float *player_cam_pos(void); -VG_STATIC void player_save_frame(void); -VG_STATIC void player_restore_frame(void); -VG_STATIC void player_save_rewind_frame(void); - -/* - * Submodules - */ -VG_STATIC void player_mouseview(void); +struct player_cam_controller { + enum camera_mode{ + k_cam_firstperson = 1, + k_cam_thirdperson = 0 + } + camera_mode; + f32 camera_type_blend; + + v3f fpv_offset, /* expressed relative to rigidbody */ + tpv_offset, + tpv_offset_extra, + fpv_viewpoint, /* expressed relative to neck bone inverse final*/ + fpv_offset_smooth, + fpv_viewpoint_smooth, + tpv_offset_smooth, + tpv_lpf, + cam_velocity_smooth; +}; -#include "player_physics.h" #include "player_ragdoll.h" +#include "player_render.h" #include "player_model.h" -#include "player_animation.h" -#include "player_audio.h" - -/* - * ----------------------------------------------------------------------------- - * Events - * ----------------------------------------------------------------------------- - */ -VG_STATIC int kill_player( int argc, char const *argv[] ); -VG_STATIC int reset_player( int argc, char const *argv[] ); -VG_STATIC void reset_player_poll( int argc, char const *argv[] ); - -VG_STATIC void player_init(void) /* 1 */ -{ - player.input_js1h = vg_create_named_input( "steer-h", k_input_type_axis ); - player.input_js1v = vg_create_named_input( "steer-v", k_input_type_axis ); - player.input_grab = vg_create_named_input( "grab", k_input_type_axis_norm ); - player.input_js2h = vg_create_named_input( "grab-h", k_input_type_axis ); - player.input_js2v = vg_create_named_input( "grab-v", k_input_type_axis ); - player.input_jump = vg_create_named_input( "jump", k_input_type_button ); - player.input_push = vg_create_named_input( "push", k_input_type_button ); - player.input_walk = vg_create_named_input( "walk", k_input_type_button ); - - player.input_walkh = vg_create_named_input( "walk-h", - k_input_type_axis ); - player.input_walkv = vg_create_named_input( "walk-v", - k_input_type_axis ); - - - player.input_switch_mode = vg_create_named_input( "switch-mode", - k_input_type_button ); - player.input_reset = vg_create_named_input( "reset", k_input_type_button ); - - const char *default_cfg[] = - { - "bind steer-h gp-ls-h", - "bind -steer-h a", - "bind +steer-h d", - - "bind steer-v gp-ls-v", - "bind -steer-v w", - "bind +steer-v s", - - "bind grab gp-rt", - "bind +grab shift", - "bind grab-h gp-rs-h", - "bind grab-v gp-rs-v", - - "bind jump space", - "bind jump gp-a", - - "bind push gp-b", - "bind push w", - - "bind walk shift", - "bind walk gp-ls", - - "bind walk-h gp-ls-h", - "bind walk-v -gp-ls-v", - "bind +walk-h d", - "bind -walk-h a", - "bind +walk-v w", - "bind -walk-v s", - - "bind reset gp-lb", - "bind reset r", - - "bind switch-mode gp-y", - "bind switch-mode e", - }; - - for( int i=0; iang ); - v3_copy( player.camera_pos, fr->pos ); - - player.rewind_incrementer = 0; - - if( player.rewind_length > 1 ) - { - player.rewind_total_length += - v3_dist( player.rewind_buffer[player.rewind_length-1].pos, - player.rewind_buffer[player.rewind_length-2].pos ); - } - } +#define PLAYER_REWIND_FRAMES 60*4 +#define RESET_MAX_TIME 45.0 + +static i32 k_cinema_fixed = 0; +static f32 k_cinema = 0.0f; +static i32 k_invert_y = 0; + +struct player_instance{ + /* transform definition */ + rigidbody rb; + v3f angles; + + v4f qbasis; + m3x3f basis, invbasis, basis_gate; + world_instance *viewable_world; + + /* + * Camera management + * --------------------------- + */ + camera cam; + struct player_cam_controller cam_control; + + v3f cam_override_pos; + v3f cam_override_angles; + float cam_override_fov; + float cam_override_strength; + f32 cam_trackshake; + + float cam_velocity_influence, + cam_velocity_coefficient, + cam_velocity_constant, + cam_velocity_coefficient_smooth, + cam_velocity_constant_smooth, + cam_velocity_influence_smooth; + + v3f cam_land_punch, cam_land_punch_v; + ent_gate *gate_waiting; + + int immobile; + + /* + * Animation + * -------------------------------------------------- + */ + + struct player_avatar *playeravatar; + struct player_ragdoll ragdoll; + struct player_model fallback_model; + + u16 board_view_slot, playermodel_view_slot; + + player_pose holdout_pose; + float holdout_time; + + struct board_pose board_pose; + + /* + * Replay + * ------------------------------------------------- + */ + replay_buffer replay; + + /* + * Subsystems + * ------------------------------------------------- + */ + + enum player_subsystem subsystem; /* .. prev */ + + struct player_skate _skate; + struct player_walk _walk; + struct player_dead _dead; + struct player_drive _drive; } - - -/* disaster */ -VG_STATIC int menu_enabled(void); -#include "menu.h" +static localplayer; /* - * Free camera movement + * Gameloop tables + * --------------------------------------------------------- */ -VG_STATIC void player_mouseview(void) -{ - if( menu_enabled() ) - return; - - v2_muladds( player.angles, vg.mouse_delta, 0.0025f, player.angles ); - - if( vg_input.controller_should_use_trackpad_look ) - { - static v2f last_input; - static v2f vel; - static v2f vel_smooth; - - v2f input = { player.input_js2h->axis.value, - player.input_js2v->axis.value }; - - if( (v2_length2(last_input) > 0.001f) && (v2_length2(input) > 0.001f) ) - { - v2_sub( input, last_input, vel ); - v2_muls( vel, 1.0f/vg.time_delta, vel ); - } - else - { - v2_zero( vel ); - } - - v2_lerp( vel_smooth, vel, vg.time_delta*8.0f, vel_smooth ); - - v2_muladds( player.angles, vel_smooth, vg.time_delta, player.angles ); - v2_copy( input, last_input ); - } - else - { - player.angles[0] += player.input_js2h->axis.value * vg.time_delta * 4.0f; - player.angles[1] += player.input_js2v->axis.value * vg.time_delta * 4.0f; - } - - player.angles[1] = vg_clampf( player.angles[1], -VG_PIf*0.5f, VG_PIf*0.5f ); -} -/* Deal with input etc */ -VG_STATIC void player_update_pre(void) +VG_STATIC +void (*_player_system_register[])(void) = { - struct player_phys *phys = &player.phys; - - - { - v3f ra, rb, rx; - v3_copy( main_camera.pos, ra ); - v3_muladds( ra, main_camera.transform[2], -10.0f, rb ); - - float t; - if( spherecast_world( ra, rb, 0.4f, &t, rx ) != -1 ) - { - m4x3f mtx; - m3x3_identity( mtx ); - v3_lerp( ra, rb, t, mtx[3] ); - - debug_sphere( mtx, 0.4f, 0xff00ff00 ); - - v3f x1; - v3_muladds( mtx[3], rx, 0.4f, x1 ); - vg_line( mtx[3], x1, 0xffffffff ); - } - } - - - - - - - - - if( player.rewinding ) - return; - - if( vg_input_button_down( player.input_reset ) && !menu_enabled() ) - { - double delta = world.time - world.last_use; - - if( (delta <= RESET_MAX_TIME) && (world.last_use != 0.0) ) - { - player.rewinding = 1; - player.rewind_sound_wait = 1; - player.rewind_time = (float)player.rewind_length - 0.0001f; - player_save_rewind_frame(); - audio_lock(); - audio_play_oneshot( &audio_rewind[0], 1.0f ); - audio_unlock(); - - /* based on analytical testing. DONT CHANGE! - * - * time taken: y = (x^(4/5)) * 74.5 - * inverse : x = (2/149)^(4/5) * y^(4/5) - */ - - float constant = powf( 2.0f/149.0f, 4.0f/5.0f ), - curve = powf( player.rewind_total_length, 4.0f/5.0f ); - - player.rewind_predicted_time = constant * curve; - player.diag_rewind_start = vg.time; - player.diag_rewind_time = player.rewind_time; - - player.is_dead = 0; - player.death_tick_allowance = 30; - player_restore_frame(); - - if( !phys->on_board ) - { - player.angles[0] = atan2f( -phys->rb.forward[2], - -phys->rb.forward[0] ); - } - - player.mdl.shoes[0] = 1; - player.mdl.shoes[1] = 1; - - world_routes_notify_reset(); - - /* apply 1 frame of movement */ - player_do_motion(); - } - else - { - if( player.is_dead ) - { - reset_player( 0, NULL ); - } - else - { - /* cant do that */ - audio_lock(); - audio_play_oneshot( &audio_rewind[4], 1.0f ); - audio_unlock(); - } - } - } - - if( vg_input_button_down( player.input_switch_mode ) && !menu_enabled() ) - { - phys->on_board ^= 0x1; - - audio_lock(); - if( phys->on_board ) - { - v3_muladds( phys->rb.v, phys->rb.forward, 0.2f, phys->rb.v ); - audio_play_oneshot( &audio_lands[6], 1.0f ); - } - else - { - audio_play_oneshot( &audio_lands[5], 1.0f ); - } - - audio_unlock(); - } - - if( !phys->on_board ) - player_mouseview(); -} + player__walk_register, + player__skate_register, + NULL, + NULL +}; -VG_STATIC void player_update_fixed(void) /* 2 */ +VG_STATIC +void (*_player_bind[])( player_instance *player ) = { - if( player.rewinding ) - return; - - if( player.death_tick_allowance ) - player.death_tick_allowance --; - - struct player_phys *phys = &player.phys; - - if( player.is_dead ) - { - player_ragdoll_iter(); - } - else - { - player.rewind_incrementer ++; - - if( player.rewind_incrementer > (u32)(0.25/VG_TIMESTEP_FIXED) ) - { - player_save_rewind_frame(); - } - - player_do_motion(); - } -} + player__walk_bind, + player__skate_bind, + NULL, + player__drive_bind +}; -VG_STATIC void player_update_post(void) +VG_STATIC +void (*_player_reset[])( player_instance *player, ent_spawn *rp ) = { - for( int i=0; ilog_length - 1; j ++ ) - vg_line( p->log[j], p->log[j+1], p->colour ); - - vg_line_cross( p->log[p->log_length-1], p->colour, 0.25f ); - - v3f p1; - v3_add( p->log[p->log_length-1], p->n, p1 ); - vg_line( p->log[p->log_length-1], p1, 0xffffffff ); - } - - if( player.is_dead ) - { - player_debug_ragdoll(); + player__walk_reset, + player__skate_reset, + NULL, + player__drive_reset +}; - if( !freecam ) - player_animate_death_cam(); - } - else - { - player_animate(); - - if( !freecam ) - { - if( cl_thirdperson ) - player_animate_camera_thirdperson(); - else - player_animate_camera(); - } - } +VG_STATIC +void (*_player_pre_update[])( player_instance *player ) = +{ + player__walk_pre_update, + player__skate_pre_update, + NULL, + player__drive_pre_update +}; - if( freecam ) - player_freecam(); - - /* CAMERA POSITIONING: LAYER 0 */ - v2_copy( player.angles, main_camera.angles ); - v3_copy( player.camera_pos, main_camera.pos ); - - if( player.rewinding ) - { - if( player.rewind_time <= 0.0f ) - { - double taken = vg.time - player.diag_rewind_start; - vg_success( "Rewind took (rt, pl, tl): %f, %f, %f\n", - taken, player.diag_rewind_time, - player.rewind_total_length ); - - player.rewinding = 0; - player.rewind_length = 1; - player.rewind_total_length = 0.0f; - player.rewind_incrementer = 0; - world.sky_target_rate = 1.0; - } - else - { - world.sky_target_rate = -100.0; - assert( player.rewind_length > 0 ); - - v2f override_angles; - v3f override_pos; - - float budget = vg.time_delta, - overall_length = player.rewind_length; - - world_routes_rollback_time( player.rewind_time / overall_length ); - - for( int i=0; (i<10)&&(player.rewind_time>0.0f)&&(budget>0.0f); i ++ ) - { - /* Interpolate frames */ - int i0 = floorf( player.rewind_time ), - i1 = VG_MIN( i0+1, player.rewind_length-1 ); - - struct rewind_frame *fr = &player.rewind_buffer[i0], - *fr1 = &player.rewind_buffer[i1]; - - float dist = vg_maxf( v3_dist( fr->pos, fr1->pos ), 0.001f ), - subl = vg_fractf( player.rewind_time ) + 0.001f, - - sramp= 3.0f-(1.0f/(0.4f+0.4f*player.rewind_time)), - speed = sramp*28.0f + 0.5f*player.rewind_time, - mod = speed * (budget / dist), - - advl = vg_minf( mod, subl ), - advt = (advl / mod) * budget; - - player.dist_accum += speed * advt; - player.rewind_time -= advl; - budget -= advt; - } - - player.rewind_time = vg_maxf( 0.0f, player.rewind_time ); - - float current_time = vg.time - player.diag_rewind_start, - remaining = player.rewind_predicted_time - current_time; - - if( player.rewind_sound_wait ) - { - if( player.rewind_predicted_time >= 6.5f ) - { - if( remaining <= 6.5f ) - { - audio_lock(); - audio_play_oneshot( &audio_rewind[3], 1.0f ); - audio_unlock(); - player.rewind_sound_wait = 0; - } - } - else if( player.rewind_predicted_time >= 2.5f ) - { - if( remaining <= 2.5f ) - { - audio_lock(); - audio_play_oneshot( &audio_rewind[2], 1.0f ); - audio_unlock(); - player.rewind_sound_wait = 0; - } - } - else if( player.rewind_predicted_time >= 1.5f ) - { - if( remaining <= 1.5f ) - { - audio_lock(); - audio_play_oneshot( &audio_rewind[1], 1.0f ); - audio_unlock(); - player.rewind_sound_wait = 0; - } - } - } - - int i0 = floorf( player.rewind_time ), - i1 = VG_MIN( i0+1, player.rewind_length-1 ); - - struct rewind_frame *fr = &player.rewind_buffer[i0], - *fr1 = &player.rewind_buffer[i1]; - - float sub = vg_fractf(player.rewind_time); - - v3_lerp( fr->pos, fr1->pos, sub, override_pos ); - override_angles[0] = vg_alerpf( fr->ang[0], fr1->ang[0], sub ); - override_angles[1] = vg_lerpf ( fr->ang[1], fr1->ang[1], sub ); - - /* CAMERA POSITIONING: LAYER 1 */ - float blend = (4.0f-player.rewind_time) * 0.25f, - c = vg_clampf( blend, 0.0f, 1.0f ); - - main_camera.angles[0] = - vg_alerpf(override_angles[0], player.angles[0], c); - main_camera.angles[1] = - vg_lerpf (override_angles[1], player.angles[1], c); - v3_lerp( override_pos, player.camera_pos, c, main_camera.pos ); - } - } +VG_STATIC +void( *_player_update[])( player_instance *player ) = +{ + player__walk_update, + player__skate_update, + player__dead_update, + player__drive_update +}; - camera_update_transform( &main_camera ); - player_audio(); -} +VG_STATIC +void( *_player_post_update[])( player_instance *player ) = +{ + player__walk_post_update, + player__skate_post_update, + NULL, + player__drive_post_update +}; -VG_STATIC void draw_player( camera *cam ) +VG_STATIC +void( *_player_im_gui[])( player_instance *player ) = { - if( player.is_dead ) - player_model_copy_ragdoll(); - - shader_viewchar_use(); - vg_tex2d_bind( &tex_characters, 0 ); - shader_viewchar_uTexMain( 0 ); - shader_viewchar_uCamera( cam->transform[3] ); - shader_viewchar_uPv( cam->mtx.pv ); - shader_link_standard_ub( _shader_viewchar.id, 2 ); - glUniformMatrix4x3fv( _uniform_viewchar_uTransforms, - player.mdl.sk.bone_count, - 0, - (float *)player.mdl.sk.final_mtx ); - - mesh_bind( &player.mdl.player_meshes[cl_playermdl_id] ); - mesh_draw( &player.mdl.player_meshes[cl_playermdl_id] ); -} + player__walk_im_gui, + player__skate_im_gui, + NULL, + player__drive_im_gui +}; -/* - * ----------------------------------------------------------------------------- - * API implementation - * ----------------------------------------------------------------------------- - */ +VG_STATIC +void( *_player_animate[])( player_instance *player, player_animation *dest ) = +{ + player__walk_animate, + player__skate_animate, + player__dead_animate, + player__drive_animate +}; -VG_STATIC float *player_get_pos(void) +VG_STATIC +void( *_player_post_animate[])( player_instance *player ) = { - return player.phys.rb.co; -} + player__walk_post_animate, + player__skate_post_animate, + player__dead_post_animate, + player__drive_post_animate +}; -VG_STATIC void player_kill(void) +VG_STATIC +void( *_player_store_state[] )( player_instance *player ) = { - if( player.death_tick_allowance == 0 ) - { - player.is_dead = 1; - player_ragdoll_copy_model( player.phys.rb.v ); - } -} + NULL, + NULL, + NULL, + NULL +}; -VG_STATIC float *player_cam_pos(void) +VG_STATIC +void( *_player_load_state_lerp[] )( player_instance *player, + void *A, void *B, f32 t ) = { - return player.camera_pos; -} + NULL, + NULL, + NULL, + NULL +}; +PLAYER_API void player__debugtext( int size, const char *fmt, ... ); +PLAYER_API void player__create( player_instance *inst ); +PLAYER_API void player__use_avatar( player_instance *player, + struct player_avatar *av ); +PLAYER_API void player__use_mesh( player_instance *player, glmesh *mesh ); +PLAYER_API void player__use_texture( player_instance *player, vg_tex2d *tex ); +PLAYER_API void player__use_model( player_instance *player, u16 reg_id ); + +PLAYER_API void player__bind( player_instance *player ); +PLAYER_API void player__pre_update( player_instance *player ); +PLAYER_API void player__update( player_instance *player ); +PLAYER_API void player__post_update( player_instance *player ); + +PLAYER_API void player__pass_gate( player_instance *player, ent_gate *gate ); +PLAYER_API void player__im_gui( player_instance *player ); +PLAYER_API void player__setpos( player_instance *player, v3f pos ); +PLAYER_API void player__spawn( player_instance *player, ent_spawn *rp ); +PLAYER_API void player__kill( player_instance *player ); + +VG_STATIC int localplayer_cmd_respawn( int argc, const char *argv[] ); +VG_STATIC void player_apply_transport_to_cam( m4x3f transport ); #endif /* PLAYER_H */