audio_clip audio_jumps[] = {
{ .path = "sound/jump0.ogg", .source_mode=k_audio_source_compressed, },
{ .path = "sound/jump1.ogg", .source_mode=k_audio_source_compressed, },
- { .path = "sound/jump2.ogg", .source_mode=k_audio_source_compressed, },
- { .path = "sound/jump3.ogg", .source_mode=k_audio_source_compressed, }
};
audio_clip audio_footsteps[] = {
};
audio_clip audio_lands[] = {
- { .path = "sound/revert0.ogg", .source_mode=k_audio_source_compressed },
- { .path = "sound/revert1.ogg", .source_mode=k_audio_source_compressed },
- { .path = "sound/revert2.ogg", .source_mode=k_audio_source_compressed },
- { .path = "sound/revert3.ogg", .source_mode=k_audio_source_compressed },
- { .path = "sound/revert4.ogg", .source_mode=k_audio_source_compressed }
+ { .path = "sound/land0.ogg", .source_mode=k_audio_source_compressed },
+ { .path = "sound/land1.ogg", .source_mode=k_audio_source_compressed },
+ { .path = "sound/land2.ogg", .source_mode=k_audio_source_compressed },
+ { .path = "sound/landsk0.ogg", .source_mode=k_audio_source_compressed },
+ { .path = "sound/landsk1.ogg", .source_mode=k_audio_source_compressed },
+ { .path = "sound/onto.ogg", .source_mode=k_audio_source_compressed },
+ { .path = "sound/outo.ogg", .source_mode=k_audio_source_compressed },
};
audio_clip audio_water[] = {
.name = "Ambience"
};
+audio_player audio_rewind_player =
+{
+ .name = "Rewind"
+};
+
+audio_clip audio_rewind[] = {
+{ .path = "sound/rewind_start.ogg", .source_mode=k_audio_source_compressed },
+{ .path = "sound/rewind_end_1.5.ogg", .source_mode=k_audio_source_compressed},
+{ .path = "sound/rewind_end_2.5.ogg", .source_mode=k_audio_source_compressed },
+{ .path = "sound/rewind_end_6.5.ogg", .source_mode=k_audio_source_compressed },
+{ .path = "sound/rewind_clack.ogg", .source_mode=k_audio_source_compressed },
+};
+
+audio_clip audio_ui[] = {
+ { .path = "sound/ui_click.ogg", .source_mode=k_audio_source_compressed },
+ { .path = "sound/ui_ding.ogg", .source_mode=k_audio_source_compressed },
+};
+
audio_player ambient_sprites[4] =
{
{ .name = "Ambient Sprites 0" },
audio_player_init( &ambient_sprites[2] );
audio_player_init( &ambient_sprites[3] );
audio_player_init( &audio_player_extra );
+ audio_player_init( &audio_rewind_player );
audio_clip_loadn( audio_board, vg_list_size(audio_board) );
audio_clip_loadn( audio_ambience, vg_list_size(audio_ambience) );
audio_clip_loadn( audio_water, vg_list_size(audio_water) );
audio_clip_loadn( audio_grass, vg_list_size(audio_grass) );
audio_clip_loadn( audio_footsteps, vg_list_size(audio_footsteps) );
+ audio_clip_loadn( audio_rewind, vg_list_size(audio_rewind) );
+ audio_clip_loadn( audio_ui, vg_list_size(audio_ui) );
audio_lock();
u32 flags = AUDIO_FLAG_LOOP|AUDIO_FLAG_SPACIAL_3D;
audio_player_set_vol( &ambient_player, 1.0f );
audio_player_set_vol( &audio_player_gate, 0.0f );
audio_player_set_vol( &audio_player_extra, 1.0f );
+ audio_player_set_vol( &audio_rewind_player, 0.2f );
+ audio_player_set_flags( &audio_rewind_player, 0x00 );
audio_player_playclip( &audio_player0, &audio_board[0] );
audio_player_playclip( &audio_player1, &audio_board[1] );
class classtype_achievement_box(Structure):
_pack_ = 1
- _fields_ = [("pstr_name",c_uint32)]
+ _fields_ = [("pstr_name",c_uint32),
+ ("trigger",c_uint32)]
+
+class classtype_audio(Structure):
+ _pack_ = 1
+ _fields_ = [("pstr_file",c_uint32),
+ ("flags",c_uint32),
+ ("volume",c_float)]
# Exporter
# ==============================================================================
entdata_length += sizeof( classtype_achievement_box )
ach = classtype_achievement_box()
ach.pstr_name = emplace_string( obj.cv_data.strp )
+ ach.trigger = 0
+
+ if obj.cv_data.target != None:
+ ach.trigger = obj.cv_data.target.cv_data.uid
+
entdata_buffer += [ach]
+ elif classtype == 'k_classtype_audio':
+ node.classtype = 14
+
+ entdata_length += sizeof( classtype_audio )
+ aud = classtype_audio()
+ aud.pstr_file = emplace_string( obj.cv_data.strp )
+ aud.flags = obj.cv_data.intp
+ aud.volume = obj.cv_data.fltp
+
+ entdata_buffer += [aud]
+
elif classtype == 'k_classtype_spawn':
node.classtype = 3
verts += [(v1[0],v1[1],v1[2])]
colours += [(0,1,0,1),(0,1,0,1)]
+ if obj.cv_data.target != None:
+ vs = [None]*2
+ vs[0] = obj.location
+ vs[1] = obj.cv_data.target.location
+ indices = [(0,1)]
+ for l in indices:
+ v0 = vs[l[0]]
+ v1 = vs[l[1]]
+ verts += [(v0[0],v0[1],v0[2])]
+ verts += [(v1[0],v1[1],v1[2])]
+ colours += [(0,1,1,1),(0,1,1,1)]
+
+
elif obj.cv_data.classtype == 'k_classtype_block':
a = obj.data.cv_data.v0
b = obj.data.cv_data.v1
class CV_OBJ_SETTINGS(bpy.types.PropertyGroup):
uid: bpy.props.IntProperty( name="" )
- strp: bpy.props.StringProperty(name="string")
+ strp: bpy.props.StringProperty( name="strp" )
+ intp: bpy.props.IntProperty( name="intp" )
+ fltp: bpy.props.FloatProperty( name="fltp" )
target: bpy.props.PointerProperty( type=bpy.types.Object, name="target", \
poll=cv_poll_target )
('k_classtype_SKELETON', "","", 11 ),
('k_classtype_SKIN',"","",12),
('k_classtype_achievement_box',"k_classtype_achievement_box","",13),
+ ('k_classtype_audio',"k_classtype_audio","",14),
])
class CV_BONE_SETTINGS(bpy.types.PropertyGroup):
_.layout.prop( mesh.cv_data, "v0" )
elif active_object.cv_data.classtype == 'k_classtype_achievement_box':
_.layout.prop( active_object.cv_data, "strp" )
+ _.layout.prop( active_object.cv_data, "target" )
+ elif active_object.cv_data.classtype == 'k_classtype_audio':
+ _.layout.prop( active_object.cv_data, "strp" )
+ _.layout.prop( active_object.cv_data, "intp" )
+ _.layout.prop( active_object.cv_data, "fltp" )
class CV_INTERFACE(bpy.types.Panel):
bl_idname = "VIEW3D_PT_carve"
#include "vg/vg.h"
#include "anyascii/anyascii.h"
+#define RESET_MAX_TIME 45.0
+
typedef struct ray_hit ray_hit;
struct ray_hit
{
{
if( btn->fn_press )
{
+ audio_lock();
+ audio_play_oneshot( &audio_ui[0], 1.0f );
+ audio_unlock();
+
btn->fn_press( 1 );
return;
}
k_classtype_bone = 10,
k_classtype_skeleton = 11,
k_classtype_skin = 12,
- k_classtype_achievement_box = 13
+ k_classtype_achievement_box = 13,
+ k_classtype_audio = 14
};
struct classtype_achievement_box
{
- u32 pstr_name;
+ u32 pstr_name,
+ trigger;
+};
+
+struct classtype_audio
+{
+ u32 pstr_file,
+ flags;
+
+ float volume;
};
#pragma pack(pop)
inv_visual_transform;
int is_dead, death_tick_allowance, rewinding;
+ int rewind_sound_wait;
v3f land_target;
v3f land_target_log[22];
/* Camera */
float air_blend;
+ float air_time;
v3f camera_pos, smooth_localcam;
v2f angles;
u32 rewind_incrementer,
rewind_length;
- float rewind_time;
+ float rewind_time, rewind_total_length, rewind_predicted_time;
+ double diag_rewind_start, diag_rewind_time;
+ float dist_accum;
/* animation */
double jump_time;
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 );
+ }
}
}
if( vg_get_button_down( "reset" ) )
{
- player.rewinding = 1;
- player.rewind_time = (float)player.rewind_length - 0.0001f;
- player_save_rewind_frame();
-
- player.is_dead = 0;
- player.death_tick_allowance = 30;
- player_restore_frame();
+ double delta = world.routes.time - world.routes.last_use;
- if( !phys->on_board )
+ if( delta <= RESET_MAX_TIME )
{
- player.angles[0] = atan2f( -phys->rb.forward[2],
- -phys->rb.forward[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.mdl.shoes[0] = 1;
- player.mdl.shoes[1] = 1;
+ player.is_dead = 0;
+ player.death_tick_allowance = 30;
+ player_restore_frame();
- world_routes_notify_reset();
+ if( !phys->on_board )
+ {
+ player.angles[0] = atan2f( -phys->rb.forward[2],
+ -phys->rb.forward[0] );
+ }
- /* apply 1 frame of movement */
- player_do_motion();
+ player.mdl.shoes[0] = 1;
+ player.mdl.shoes[1] = 1;
+
+ world_routes_notify_reset();
+
+ /* apply 1 frame of movement */
+ player_do_motion();
+ }
}
if( vg_get_button_down( "switchmode" ) )
{
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( 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
advl = vg_minf( mod, subl ),
advt = (advl / mod) * budget;
-
+
+ player.dist_accum += speed * advt;
player.rewind_time -= advl;
budget -= advt;
}
+#if 0
+ if( player.dist_accum >= 5.0f )
+ {
+ audio_lock();
+ audio_player_playclip( &audio_rewind_player, &audio_rewind[4] );
+ audio_unlock();
+
+ player.dist_accum -= 5.0f;
+ }
+#endif
+
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 );
audio_lock();
-
+
double revert_delta = vg.time - last_revert;
- if( phys->on_board && (!_air && l2) && (fabsf(phys->slip) > 0.5f) &&
- (revert_delta > 0.7) )
+ if( phys->on_board && (!_air && l2) && (revert_delta > 0.7) &&
+ (player.air_time > 0.5f) )
{
audio_player_set_position( &audio_player_extra, phys->rb.co );
audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
audio_player_set_vol( &audio_player_extra, 2.0f );
- audio_player_playclip( &audio_player_extra, &audio_lands[rand()%5] );
+
+ if( (fabsf(phys->slip) > 0.75f) )
+ {
+ audio_player_playclip( &audio_player_extra, &audio_lands[rand()%2+3] );
+ }
+ else
+ {
+ audio_player_playclip( &audio_player_extra, &audio_lands[rand()%3] );
+ }
last_revert = vg.time;
}
world_audio_update( cam, ears );
#endif
audio_unlock();
+
+ if( player.phys.in_air )
+ player.air_time += vg.time_delta;
+ else
+ player.air_time = 0.0f;
+
}
#endif /* PLAYER_AUDIO_H */
player_start_air();
}
else
+ {
phys->in_air = 0;
+ }
}
for( int j=0; j<5; j++ )
audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
audio_player_set_position( &audio_player_extra, phys->rb.co );
audio_player_set_vol( &audio_player_extra, 20.0f );
- audio_player_playclip( &audio_player_extra, &audio_jumps[rand()%4] );
+ audio_player_playclip( &audio_player_extra, &audio_jumps[rand()%2] );
audio_unlock();
}
}
}
player.rewind_length = 0;
+ player.rewind_total_length = 0.0f;
player.rewind_incrementer = 10000;
player_save_frame();
spawns[32];
u32 spawn_count;
+ struct world_audio_thing
+ {
+ v3f pos;
+ float volume;
+ u32 flags;
+
+ audio_player player;
+ audio_clip temp_embedded_clip;
+ }
+ * audio_things;
+
+ u32 audio_things_count,
+ audio_things_cap;
+
struct achievement_zone
{
m4x3f transform, inv_transform;
char name[32];
int triggered;
+
+ union
+ {
+ mdl_node *ptarget_delegated;
+ struct world_audio_thing *ptarget;
+ };
}
* achievement_zones;
mesh_free( &world.cars );
mesh_free( &world.skydome );
vg_free( world.achievement_zones );
+
+ /* FIXME: This fucks with the audio player. Use-after-free */
+#if 0
+ vg_free( world.audio_things );
+#endif
}
static void world_update( v3f pos )
{
world.sky_time += world.sky_rate * vg.time_delta;
world.sky_rate = vg_lerp( world.sky_rate, world.sky_target_rate,
- vg.time_delta * 10.0 );
+ vg.time_delta * 5.0 );
world_routes_update();
#if 0
}
}
+ static int in_zone = 0;
+
+ int in_zone_this_time = 0;
+
for( int i=0; i<world.achievement_zones_count; i++ )
{
struct achievement_zone *zone = &world.achievement_zones[i];
- if( zone->triggered )
- continue;
-
v3f local;
m4x3_mulv( zone->inv_transform, pos, local );
(fabsf(local[1]) <= 1.0f) &&
(fabsf(local[2]) <= 1.0f) )
{
+ in_zone_this_time = 1;
+
+ if( !in_zone && zone->ptarget )
+ {
+ audio_lock();
+ audio_player_playclip( &zone->ptarget->player,
+ &zone->ptarget->temp_embedded_clip );
+ audio_unlock();
+ }
+
+ if( !zone->triggered )
+ {
+ steam_set_achievement( zone->name );
+ steam_store_achievements();
+ }
+
zone->triggered = 1;
- steam_set_achievement( zone->name );
- steam_store_achievements();
}
vg_line_boxf_transformed( zone->transform, (boxf){{-1.0f,-1.0f,-1.0f},
{ 1.0f, 1.0f, 1.0f}},
0xff00ff00 );
}
+
+ in_zone = in_zone_this_time;
sfd_update( &world.sfd.tester );
}
vg_strncpy( mdl_pstr(mworld, box->pstr_name), zone->name, 31 );
zone->name[31] = 0x00;
zone->triggered = 0;
+
+ if( box->trigger )
+ zone->ptarget_delegated = mdl_node_from_id( mworld, box->trigger );
+ else
+ zone->ptarget_delegated = NULL;
+ }
+ else if( pnode->classtype == k_classtype_audio )
+ {
+ world.audio_things =
+ buffer_reserve( world.audio_things,
+ world.audio_things_count,
+ &world.audio_things_cap, 1,
+ sizeof(struct world_audio_thing) );
+
+ struct world_audio_thing *thing = &world.audio_things[
+ world.audio_things_count ];
+ memset( thing, 0, sizeof(struct world_audio_thing) );
+ struct classtype_audio *aud = mdl_get_entdata(mworld,pnode);
+
+ v3_copy( pnode->co, thing->pos );
+
+ if( aud->flags & AUDIO_FLAG_SPACIAL_3D )
+ thing->volume = aud->volume * pnode->s[0];
+ else
+ thing->volume = aud->volume;
+
+ thing->flags = aud->flags;
+ const char *fp = mdl_pstr( mworld, aud->pstr_file );
+ char *path2 = vg_alloc( strlen(fp)+1 );
+ strcpy( path2, fp );
+ thing->temp_embedded_clip.path = path2;
+ thing->temp_embedded_clip.source_mode = k_audio_source_compressed;
+ audio_clip_load( &thing->temp_embedded_clip );
+ thing->player.name = "[temp]";
+ thing->player.enqued = 0;
+
+ pnode->sub_uid = world.audio_things_count;
+ world.audio_things_count ++;
}
}
+ /* fixup links */
+ for( int i=0; i<world.achievement_zones_count; i ++ )
+ {
+ struct achievement_zone *ach = &world.achievement_zones[ i ];
+ if( ach->ptarget_delegated )
+ {
+ u32 id = ach->ptarget_delegated->sub_uid;
+ ach->ptarget = &world.audio_things[ id ];
+ }
+ else
+ ach->ptarget = NULL;
+ }
+
+ /* initialize audio if need be */
+ audio_lock();
+ for( int i=0; i<world.audio_things_count; i++ )
+ {
+ struct world_audio_thing *thingy = &world.audio_things[ i ];
+
+ audio_player_init( &thingy->player );
+ audio_player_set_flags( &thingy->player, thingy->flags );
+ audio_player_set_vol( &thingy->player, thingy->volume );
+ audio_player_set_pan( &thingy->player, 0.0f );
+
+ if( thingy->flags & AUDIO_FLAG_SPACIAL_3D )
+ audio_player_set_position( &thingy->player, thingy->pos );
+
+ if( thingy->flags & AUDIO_FLAG_AUTO_START )
+ audio_player_playclip( &thingy->player, &thingy->temp_embedded_clip );
+ }
+ audio_unlock();
+
world.instance_cache = buffer_fix( world.instance_cache,
world.instance_cache_count,
&world.instance_cache_cap,
{
struct subworld_routes *r = &world.routes;
r->current_run_version = 2;
+ r->time = RESET_MAX_TIME*2.0;
+ r->last_use = 0.0;
shader_route_register();
shader_routeui_register();