gui_location_print_ccmd( 1, (const char *[]){
mdl_pstr(&world->meta,region->pstr_title)} );
+
+ if( region->flags & k_ent_route_flag_achieve_gold )
+ localplayer.effect_data.spark.colour = 0xff8ce0fa;
+ else if( region->flags & k_ent_route_flag_achieve_silver )
+ localplayer.effect_data.spark.colour = 0xffc2c2c2;
+ else
+ localplayer.effect_data.spark.colour = 0x00;
}
else if( call->function == 1 ){ /* leave */
for( u32 i=0; i<mdl_arrcount(&world->ent_route); i ++ ){
ent_route *route = mdl_arritm( &world->ent_route, i );
route->flags |= k_ent_route_flag_out_of_zone;
}
+ localplayer.effect_data.spark.colour = 0x00;
}
}
p->colour = colour;
}
+static void particle_spawn_cone( particle_system *sys,
+ v3f co, v3f dir, f32 angle, f32 speed,
+ f32 lifetime, u32 colour ){
+ if( sys->alive == sys->max ) return;
+
+ particle *p = &sys->array[ sys->alive ++ ];
+
+ v3f tx, ty;
+ v3_tangent_basis( dir, tx, ty );
+
+ v3f rand;
+ vg_rand_cone( rand, angle );
+ v3_muls( tx, rand[0]*speed, p->v );
+ v3_muladds( p->v, ty, rand[1]*speed, p->v );
+ v3_muladds( p->v, dir, rand[2]*speed, p->v );
+
+ p->life = lifetime;
+ p->colour = colour;
+ v3_copy( co, p->co );
+}
+
static void particle_system_update( particle_system *sys, f32 dt ){
u32 i = 0;
iter: if( i == sys->alive ) return;
VG_CHECK_GL_ERR();
}
-static void particle_init( particle_system *sys, u32 max ){
+static void particle_alloc( particle_system *sys, u32 max ){
static int reg = 1;
if( reg ){
shader_particle_register();
size_t stride = sizeof(particle_vert);
- particles_grind.max = max;
- particles_grind.array =
- vg_linear_alloc( vg_mem.rtmemory, max*sizeof(particle) );
- particles_grind.vertices =
- vg_linear_alloc( vg_mem.rtmemory, max*stride*4 );
+ sys->max = max;
+ sys->array = vg_linear_alloc( vg_mem.rtmemory, max*sizeof(particle) );
+ sys->vertices = vg_linear_alloc( vg_mem.rtmemory, max*stride*4 );
vg_async_item *call =
vg_async_alloc( sizeof(particle_system *) + max*sizeof(u16)*6 );
v3f v, right;
v3_copy( p->v, v );
- v3_normalize( v );
+
+ f32 vm = v3_length( p->v );
+ v3_muls( v, 1.0f/vm, v );
v3_cross( v, (v3f){0,1,0}, right );
- f32 l = 0.3f, w = 0.025f;
+ f32 l = (sys->scale+sys->velocity_scale*vm),
+ w = sys->width;
v3f p0, p1;
v3_muladds( p->co, p->v, l, p0 );
static void particle_system_render( particle_system *sys, camera *cam ){
glDisable( GL_CULL_FACE );
- glDisable( GL_DEPTH_TEST );
+ glEnable( GL_DEPTH_TEST );
shader_particle_use();
shader_particle_uPv( cam->mtx.pv );
#ifndef PARTICLE_H
#define PARTICLE_H
+#include "skaterift.h"
+
typedef struct particle_system particle_system;
typedef struct particle particle;
typedef struct particle_vert particle_vert;
u32 alive, max;
GLuint vao, vbo, ebo;
+
+ /* render settings */
+ f32 scale, velocity_scale, width;
}
-static particles_grind;
+static particles_grind = {
+ .scale = 0.02f,
+ .velocity_scale = 0.001f,
+ .width = 0.0125f
+};
+
+static void particle_alloc( particle_system *sys, u32 max );
+static void particle_system_update( particle_system *sys, f32 dt );
+static void particle_system_debug( particle_system *sys );
+static void particle_system_prerender( particle_system *sys );
+static void particle_system_render( particle_system *sys, camera *cam );
static void particle_spawn( particle_system *sys,
v3f co, v3f v, f32 lifetime, u32 colour );
-static void particle_init( particle_system *sys, u32 max );
+static void particle_spawn_cone( particle_system *sys,
+ v3f co, v3f dir, f32 angle, f32 speed,
+ f32 lifetime, u32 colour );
#include "shaders/particle.h"
#include "skaterift.h"
#include "player_common.h"
#include "network_compression.h"
+#include "player_effects.h"
enum player_subsystem{
k_player_subsystem_walk = 0,
void(*im_gui)(void);
void(*animate)(void);
void(*pose)( void *animator, player_pose *pose );
+ void(*effects)( void *animator, m4x3f *final_mtx, struct player_board *board,
+ struct player_effects_data *effect_data );
void(*post_animate)(void);
void(*network_animator_exchange)( bitpack_ctx *ctx, void *data );
void(*sfx_oneshot)( u8 id, v3f pos, f32 volume );
id_wheel_r,
id_board,
id_eyes;
+
+ struct player_effects_data effect_data;
}
static localplayer = {
.rb = {
--- /dev/null
+#include "player_effects.h"
+#include "particle.h"
+
+static void effect_blink_apply( effect_blink *ef, player_pose *pose, f32 dt ){
+ if( ef->t < 0.0f ){
+ ef->t = (1.0f-powf(vg_randf64(),4.0f))*4.0f;
+ ef->l = 0.08f;
+ }
+
+ pose->keyframes[ localplayer.id_eyes-1 ].s[1] = ef->l > 0.0f? 0.2f: 1.0f;
+
+ ef->t -= dt;
+ ef->l -= dt;
+}
+
+static void effect_spark_apply( effect_spark *ef, v3f co, v3f v, f32 dt ){
+ if( !ef->colour ) return;
+
+ if( ef->t < 0.0f ){
+ ef->t = 0.05f+vg_randf64()*0.1f;
+
+ v3f dir;
+ v3_copy( v, dir );
+ dir[1] += 1.0f;
+ f32 l = v3_length(dir);
+ v3_muls( dir, 1.0f/l, dir );
+
+ particle_spawn_cone( &particles_grind, co, dir, VG_PIf/2.0f, l,
+ 4.0f, ef->colour );
+ }
+ else
+ ef->t -= dt;
+}
--- /dev/null
+#ifndef PLAYER_EFFECTS
+#define PLAYER_EFFECTS
+
+#include "skaterift.h"
+
+typedef struct effect_blink effect_blink;
+typedef struct effect_spark effect_spark;
+
+struct effect_blink {
+ f32 t, l;
+};
+
+struct effect_spark {
+ u32 colour;
+ f32 t;
+};
+
+static void effect_blink_apply( effect_blink *ef, player_pose *pose, f32 dt );
+static void effect_spark_apply( effect_spark *ef, v3f co, v3f v, f32 dt );
+
+struct player_effects_data {
+ effect_blink blink;
+ effect_spark spark;
+};
+
+#endif /* PLAYER_EFFECTS */
}
}
+static void remote_player_effect( struct network_player *player,
+ player_pose *final_pose ){
+ /* effects */
+}
+
/*
* write the remote players final_mtx
*/
struct player_subsystem_interface *sys0 = player_subsystems[f0->subsystem],
*sys1 = NULL;
+ struct player_board *board =
+ addon_cache_item_if_loaded( k_addon_type_board, player->board_view_slot );
+
player_pose pose0, pose1, posed;
sys0->pose( &f0->data, &pose0 );
}
instance_id = f1->instance_id;
-
lerp_player_pose( &pose0, &pose1, t, &posed );
+ effect_blink_apply( &player->effect_data.blink, &posed, vg.time_delta );
+
apply_full_skeleton_pose( sk, &posed, final_mtx );
+
+ if( t < 0.5f ){
+ if( sys0->effects )
+ sys0->effects( &f0->data, final_mtx, board, &player->effect_data );
+ }
+ else{
+ if( sys1->effects )
+ sys1->effects( &f1->data, final_mtx, board, &player->effect_data );
+ }
+
memcpy( board_pose, &posed.board, sizeof(*board_pose) );
}
else {
instance_id = f0->instance_id;
-
+ effect_blink_apply( &player->effect_data.blink, &pose0, vg.time_delta );
apply_full_skeleton_pose( sk, &pose0, final_mtx );
+ if( sys0->effects )
+ sys0->effects( &f0->data, final_mtx, board, &player->effect_data );
memcpy( board_pose, &pose0.board, sizeof(*board_pose) );
}
#include "player.h"
#include "network.h"
#include "network_common.h"
+#include "player_effects.h"
#define NETWORK_SFX_QUEUE_LENGTH 12
u32 down_bytes;
f32 down_kbs;
+
+ struct player_effects_data effect_data;
}
list[ NETWORK_MAX_PLAYERS ];
struct player_subsystem_interface *sys =
player_subsystems[localplayer.subsystem];
+ struct player_board *board =
+ addon_cache_item_if_loaded( k_addon_type_board,
+ localplayer.board_view_slot );
+
assert( sys->animate );
assert( sys->pose );
assert( sys->animator_data );
localplayer.holdout_time -= vg.time_frame_delta * 2.0f;
}
- static float blinkt = 1.0f,
- blinkl = 0.0f;
-
- if( blinkt < 0.0f ){
- blinkt = (1.0f-powf(vg_randf64(),4.0f))*4.0f;
- blinkl = 0.08f;
+ effect_blink_apply( &localplayer.effect_data.blink,
+ &localplayer.pose, vg.time_delta );
+ apply_full_skeleton_pose( sk, &localplayer.pose, localplayer.final_mtx );
+
+ if( sys->effects ){
+ sys->effects( sys->animator_data, localplayer.final_mtx, board,
+ &localplayer.effect_data );
}
- pose->keyframes[ localplayer.id_eyes-1 ].s[1] = blinkl > 0.0f? 0.2f: 1.0f;
-
- blinkt -= vg.time_delta;
- blinkl -= vg.time_delta;
-
- apply_full_skeleton_pose( sk, &localplayer.pose, localplayer.final_mtx );
skeleton_debug( sk, localplayer.final_mtx );
if( sys->post_animate )
animator->grind_balance = vg_lerpf( animator->grind_balance, grind_frame,
5.0f*vg.time_delta );
+ animator->activity = state->activity;
/* pushing */
animator->push_time = vg.time - state->start_push;
}
else q_identity( animator->qfixuptotal );
rb_extrapolate( &localplayer.rb, animator->root_co, animator->root_q );
+ v3_copy( localplayer.rb.v, animator->root_v );
}
static void player__skate_pose( void *_animator, player_pose *pose ){
}
}
+static void player__skate_effects( void *_animator, m4x3f *final_mtx,
+ struct player_board *board,
+ struct player_effects_data *effect_data ){
+
+ struct skeleton *sk = &localplayer.skeleton;
+ struct player_skate_animator *animator = _animator;
+
+ if( animator->grind > 0.5f ){
+ v3f vp0, vp1, vpc;
+ if( board ){
+ v3_copy((v3f){0.0f,0.02f, board->truck_positions[0][2]}, vp1 );
+ v3_copy((v3f){0.0f,0.02f, board->truck_positions[1][2]}, vp0 );
+ }
+ else{
+ v3_zero( vp0 );
+ v3_zero( vp1 );
+ }
+
+ v3f *board_mtx = final_mtx[ localplayer.id_board ];
+ m4x3_mulv( board_mtx, vp0, vp0 );
+ m4x3_mulv( board_mtx, vp1, vp1 );
+ v3_add( vp0, vp1, vpc );
+ v3_muls( vpc, 0.5f, vpc );
+
+ int back = 0, front = 0, mid = 0;
+
+ if( animator->activity == k_skate_activity_grind_5050 ){
+ back = 1;
+ front = 1;
+ }
+ else if( animator->activity == k_skate_activity_grind_back50 ){
+ back = 1;
+ }
+ else if( animator->activity == k_skate_activity_grind_front50 ){
+ front = 1;
+ }
+ else if( animator->activity == k_skate_activity_grind_boardslide ){
+ mid = 1;
+ }
+
+ if( back ){
+ effect_spark_apply( &effect_data->spark, vp0,
+ animator->root_v, vg.time_delta );
+ }
+
+ if( front ){
+ effect_spark_apply( &effect_data->spark, vp1,
+ animator->root_v, vg.time_delta );
+ }
+
+ if( mid ){
+ effect_spark_apply( &effect_data->spark, vpc,
+ animator->root_v, vg.time_delta );
+ }
+ }
+}
+
static void player__skate_post_animate(void){
struct player_skate_state *state = &player_skate.state;
localplayer.cam_velocity_influence = 1.0f;
bitpack_qf32( ctx, 16, 0.0f, 120.0f, &animator->push_time );
bitpack_qf32( ctx, 16, 0.0f, 120.0f, &animator->jump_time );
+ bitpack_qv3f( ctx, 16, -100.0f, 100.0f, animator->root_v );
+ bitpack_bytes( ctx, 1, &animator->activity );
}
static void player__skate_sfx_oneshot( u8 id, v3f pos, f32 volume ){
struct player_skate_animator {
v3f root_co;
v4f root_q;
+ v3f root_v;
v3f offset,
local_cog;
f32 push_time, jump_time;
u8 jump_dir;
u8 trick_type;
+ u8 activity;
}
animator;
static void player__skate_im_gui (void);
static void player__skate_animate (void);
static void player__skate_pose (void *animator, player_pose *pose);
+static void player__skate_effects( void *_animator, m4x3f *final_mtx,
+ struct player_board *board,
+ struct player_effects_data *effect_data );
static void player__skate_post_animate (void);
static void player__skate_animator_exchange( bitpack_ctx *ctx, void *data );
static void player__skate_sfx_oneshot ( u8 id, v3f pos, f32 volume );
.im_gui = player__skate_im_gui,
.animate = player__skate_animate,
.pose = player__skate_pose,
+ .effects = player__skate_effects,
.post_animate = player__skate_post_animate,
.network_animator_exchange = player__skate_animator_exchange,
.sfx_oneshot = player__skate_sfx_oneshot,
#include "vg/vg_audio_dsp.h"
#include "world_routes_ui.c"
#include "particle.c"
+#include "player_effects.c"
static int k_tools_mode = 0;
skaterift.replay.size = bytes;
replay_clear( &skaterift.replay );
- particle_init( &particles_grind, 300 );
+ particle_alloc( &particles_grind, 300 );
player_load_animation_reference( "models/ch_none.mdl" );
player_model_load( &localplayer.fallback_model, "models/ch_none.mdl" );
world_instance *view_world = get_view_world();
render_world( view_world, &skaterift.cam, 0, 0, 1, 1 );
+#if 0
particle_spawn( &particles_grind, localplayer.rb.co,
(v3f){vg_randf64()*2.0f,vg_randf64()*3.0f,vg_randf64()*2.0f},
vg_randf64(), 0xff0000ff );
+#endif
particle_system_update( &particles_grind, vg.time_delta );
//particle_system_debug( &particles_grind );
particle_system_prerender( &particles_grind );
particle_system_render( &particles_grind, &skaterift.cam );
-
/*
* render transition
*/