727 lines
20 KiB
Plaintext
727 lines
20 KiB
Plaintext
#include maps\mp\_utility;
|
|
#include common_scripts\utility;
|
|
|
|
CONST_default_radial_radius = 8; // default distance between radial button and center
|
|
CONST_radial_center_extrude_dist = 40; // this is the distance between the floating radial center and the oberver's eye
|
|
CONST_direct_travel = 1; // no path, directly zoom to position
|
|
CONST_view_travel_unit_dist = 1200; // distance unit per travel interval
|
|
CONST_view_travel_unit_time = 1; // in seconds per travel interval
|
|
CONST_blur_strength = 3; // blur strength during view travel, sine curved over travel duration
|
|
|
|
init()
|
|
{
|
|
precacheShellShock( "frag_grenade_mp" );
|
|
|
|
radial_button_definitions(); // define radial button sets and buttons
|
|
radial_init(); // setup radial button mechanism
|
|
view_path_setup(); // setup view flight paths
|
|
player_init();
|
|
}
|
|
|
|
// ====================================================================================
|
|
// == inits ==
|
|
// ====================================================================================
|
|
|
|
radial_button_definitions()
|
|
{
|
|
newRadialButtonGroup( "main", "player_view1_start", "player_view1_end" );
|
|
|
|
// Main menu's buttons:
|
|
bWeapons_a = newRadialButton( "main", "Primary Weapon", "radial_weapons_primary", ::action_weapons_primary );
|
|
bWeapons_b = newRadialButton( "main", "Secondary Weapon", "radial_weapons_secondary", ::action_weapons_secondary );
|
|
bGears = newRadialButton( "main", "Gears", "radial_gears", ::action_gears );
|
|
bKillStreaks= newRadialButton( "main", "Kill Streaks", "radial_killstreaks", ::action_killstreak );
|
|
bLeadboards = newRadialButton( "main", "Leaderboards", "radial_leaderboards", ::action_leaderboards );
|
|
//
|
|
|
|
newRadialButtonGroup( "gears", "player_view2_start", "player_view2_end" );
|
|
newRadialButtonGroup( "weapons_primary", "player_view3_start", "player_view3_end" );
|
|
newRadialButtonGroup( "weapons_secondary", "player_view3_start", "player_view3_end" );
|
|
newRadialButtonGroup( "killstreak", "player_view4_start", "player_view4_end" );
|
|
newRadialButtonGroup( "leaderboards", "player_view5_start", "player_view5_end" );
|
|
}
|
|
|
|
|
|
radial_init()
|
|
{
|
|
// calculate start & end angles of all buttons for range selection
|
|
foreach ( button_group in level.radial_button_group )
|
|
{
|
|
// sort buttons by angle so we can calculate mid angles in sequence
|
|
sort_buttons_by_angle( button_group );
|
|
|
|
for ( i = 0; i < button_group.size; i ++ )
|
|
{
|
|
if ( isdefined( button_group[ i + 1 ] ) )
|
|
{
|
|
mid_angle = getMidAngle( button_group[ i ].pos_angle, button_group[ i + 1 ].pos_angle );
|
|
button_group[ i ].end_angle = mid_angle;
|
|
button_group[ i + 1 ].start_angle = mid_angle;
|
|
}
|
|
else
|
|
{
|
|
mid_angle = getMidAngle( button_group[ i ].pos_angle, button_group[ 0 ].pos_angle ) + 180; // +180 to mirror angle
|
|
if ( mid_angle > 360 )
|
|
mid_angle -= 360;
|
|
|
|
button_group[ i ].end_angle = mid_angle;
|
|
button_group[ 0 ].start_angle = mid_angle;
|
|
}
|
|
}
|
|
}
|
|
|
|
// monitors
|
|
thread updateSelectedButton();
|
|
thread watchSelectButtonPress();
|
|
thread watchBackButtonPress();
|
|
thread debug_toggle();
|
|
}
|
|
|
|
|
|
debug_toggle()
|
|
{
|
|
level endon( "game_ended" );
|
|
level.crib_debug = 1;
|
|
|
|
while ( 1 )
|
|
{
|
|
if ( !isdefined( level.observer ) )
|
|
{
|
|
wait 0.05;
|
|
continue;
|
|
}
|
|
|
|
button_reset = true;
|
|
while ( !( level.observer buttonPressed( "BUTTON_Y" ) ) )
|
|
wait 0.05;
|
|
|
|
level.observer playsound("mouse_click");
|
|
|
|
if ( button_reset )
|
|
{
|
|
level.crib_debug *= -1;
|
|
button_reset = false;
|
|
}
|
|
|
|
while ( level.observer buttonPressed( "BUTTON_Y" ) )
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
|
|
player_init()
|
|
{
|
|
level thread onPlayerConnect();
|
|
level thread return_hud();
|
|
}
|
|
|
|
|
|
return_hud()
|
|
{
|
|
level waittill( "game_ended" );
|
|
setdvar( "cg_draw2d", 1 );
|
|
}
|
|
|
|
|
|
onPlayerConnect()
|
|
{
|
|
level waittill("connected", player);
|
|
|
|
player thread readyPlayer();
|
|
player waittill( "spawned_player" );
|
|
|
|
wait 1;
|
|
|
|
player takeallweapons();
|
|
setdvar( "cg_draw2d", 0 );
|
|
|
|
if ( !isdefined( player ) )
|
|
return;
|
|
else
|
|
level.observer = player;
|
|
|
|
player thread get_right_stick_angle();
|
|
|
|
zoom_to_radial_menu( "main" ); // fly to the first radial menu
|
|
}
|
|
|
|
|
|
readyPlayer()
|
|
{
|
|
self endon( "disconnect" );
|
|
|
|
team = "autoassign";
|
|
|
|
while(!isdefined(self.pers["team"]))
|
|
wait .05;
|
|
|
|
self notify("menuresponse", game["menu_team"], team);
|
|
wait 0.5;
|
|
|
|
classes = getArrayKeys( level.classMap );
|
|
okclasses = [];
|
|
for ( i = 0; i < classes.size; i++ )
|
|
{
|
|
if ( !isSubStr( classes[i], "custom" ) )
|
|
okclasses[ okclasses.size ] = classes[i];
|
|
}
|
|
|
|
assert( okclasses.size );
|
|
|
|
while( 1 )
|
|
{
|
|
class = okclasses[ 0 ];
|
|
self notify("menuresponse", "changeclass", class);
|
|
|
|
self waittill( "spawned_player" );
|
|
wait ( 0.10 );
|
|
}
|
|
}
|
|
|
|
// ====================================================================================
|
|
// == Radial Mechanics ==
|
|
// ====================================================================================
|
|
|
|
get_right_stick_angle()
|
|
{
|
|
// self is user
|
|
level endon( "game_ended" );
|
|
self endon( "disconnect" );
|
|
|
|
while ( 1 )
|
|
{
|
|
rs_vec = self GetNormalizedMovement();
|
|
rs_angles = vectortoangles( rs_vec );
|
|
level.rs_angle = int( rs_angles[1] );
|
|
|
|
wait 0.05; // update rate
|
|
}
|
|
}
|
|
|
|
|
|
newRadialButtonGroup( group_name, view_start, view_end )
|
|
{
|
|
if ( isdefined( level.radial_button_group ) && level.radial_button_group.size )
|
|
assertex( !isdefined( level.radial_button_group[ group_name ] ), "Radial button group: " + group_name + " is already defined." );
|
|
|
|
player_view_ent = getent( view_end, "targetname" );
|
|
assertex( isdefined( player_view_ent ), "Missing player view entity, can not setup radial menu in space" );
|
|
|
|
extruded_vec = vector_multiply( VectorNormalize( AnglesToForward( player_view_ent.angles ) ), CONST_radial_center_extrude_dist );
|
|
|
|
level.radial_button_group[ group_name ] = [];
|
|
level.radial_button_group_info[ group_name ][ "view_start" ] = view_start;
|
|
level.radial_button_group_info[ group_name ][ "view_pos" ] = player_view_ent.origin + extruded_vec;
|
|
level.radial_button_group_info[ group_name ][ "player_view_pos" ] = player_view_ent.origin;
|
|
level.radial_button_group_info[ group_name ][ "view_angles" ] = player_view_ent.angles;
|
|
}
|
|
|
|
|
|
newRadialButton( button_group, button_label, button_ent_name, action_func )
|
|
{
|
|
assertex( isdefined( level.radial_button_group[ button_group ] ), "Radial button group: " + button_group + " does not exist." );
|
|
|
|
ent = getent( button_ent_name, "targetname" );
|
|
new_button_angle = getRadialAngleFromEnt( button_group, ent );
|
|
|
|
button = spawnstruct();
|
|
button.pos = ent.origin;
|
|
button.label = button_label;
|
|
button.font_size = 1;
|
|
button.font_color = ( 0.5, 0.5, 1 );
|
|
button.pos_angle = new_button_angle;
|
|
button.action_func = action_func;
|
|
button.radius_pos = CONST_default_radial_radius;
|
|
|
|
level.radial_button_group[ button_group ][ level.radial_button_group[ button_group ].size ] = button;
|
|
return button;
|
|
}
|
|
|
|
|
|
updateSelectedButton()
|
|
{
|
|
level endon( "game_ended" );
|
|
|
|
while ( 1 )
|
|
{
|
|
if ( !isdefined( level.radial_button_current_group ) )
|
|
{
|
|
wait 0.05;
|
|
continue;
|
|
}
|
|
|
|
last_active_button = level.active_button;
|
|
|
|
foreach ( button in level.radial_button_group[ level.radial_button_current_group ] )
|
|
{
|
|
if ( isInRange( button.start_angle, button.end_angle ) )
|
|
level.active_button = button;
|
|
else
|
|
button.font_color = ( 0.5, 0.5, 1 );
|
|
}
|
|
|
|
if ( isdefined ( level.active_button ) )
|
|
{
|
|
level.active_button.font_color = ( 1, 1, 0.5 );
|
|
|
|
if ( isdefined( last_active_button ) && last_active_button != level.active_button )
|
|
level.observer playsound("mouse_over");
|
|
}
|
|
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
|
|
watchSelectButtonPress()
|
|
{
|
|
level endon( "game_ended" );
|
|
|
|
while ( 1 )
|
|
{
|
|
if ( !isdefined( level.observer ) )
|
|
{
|
|
wait 0.05;
|
|
continue;
|
|
}
|
|
|
|
button_reset = true;
|
|
while ( !( level.observer buttonPressed( "BUTTON_A" ) ) )
|
|
wait 0.05;
|
|
|
|
level.observer playsound("mouse_click");
|
|
|
|
if ( isdefined( level.active_button ) && button_reset )
|
|
{
|
|
level.active_button notify( "select_button_pressed" );
|
|
[[level.active_button.action_func]]();
|
|
button_reset = false;
|
|
}
|
|
|
|
while ( level.observer buttonPressed( "BUTTON_A" ) )
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
|
|
watchBackButtonPress()
|
|
{
|
|
level endon( "game_ended" );
|
|
|
|
while ( 1 )
|
|
{
|
|
if ( !isdefined( level.observer ) )
|
|
{
|
|
wait 0.05;
|
|
continue;
|
|
}
|
|
|
|
button_reset = true;
|
|
while ( !( level.observer buttonPressed( "BUTTON_X" ) ) )
|
|
wait 0.05;
|
|
|
|
level.observer playsound("mouse_click");
|
|
|
|
if ( button_reset )
|
|
{
|
|
action_back();
|
|
button_reset = false;
|
|
}
|
|
|
|
while ( level.observer buttonPressed( "BUTTON_X" ) )
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
|
|
sort_buttons_by_angle( button_group )
|
|
{
|
|
// button_group is actual array
|
|
// bubble sort buttons
|
|
for ( i = 0; i < button_group.size - 1; i++ )
|
|
{
|
|
for ( j = 0; j < button_group.size - 1 - i; j++ )
|
|
{
|
|
if ( button_group[ j + 1 ].pos_angle < button_group[ j ].pos_angle )
|
|
button_switch( button_group[ j ], button_group[ j + 1 ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
button_switch( button1, button2 )
|
|
{
|
|
temp_pos = button1.pos;
|
|
temp_label = button1.label;
|
|
temp_pos_angle = button1.pos_angle;
|
|
temp_action_func = button1.action_func;
|
|
temp_radius_pos = button1.radius_pos;
|
|
|
|
button1.pos = button2.pos;
|
|
button1.label = button2.label;
|
|
button1.pos_angle = button2.pos_angle;
|
|
button1.action_func = button2.action_func;
|
|
button1.radius_pos = button2.radius_pos;
|
|
|
|
button2.pos = temp_pos;
|
|
button2.label = temp_label;
|
|
button2.pos_angle = temp_pos_angle;
|
|
button2.action_func = temp_action_func;
|
|
button2.radius_pos = temp_radius_pos;
|
|
}
|
|
|
|
|
|
draw_radial_buttons( button_group )
|
|
{
|
|
foreach ( button in level.radial_button_group[ button_group ] )
|
|
button thread draw_radial_button( button_group );
|
|
}
|
|
|
|
|
|
//print3d(<origin>, <text>, <color>, <alpha>, <scale>, <duration> )
|
|
draw_radial_button( button_group )
|
|
{
|
|
level endon( "game_ended" );
|
|
self endon( "remove_button" );
|
|
|
|
floating_origin = level.radial_button_group_info[ button_group ][ "view_pos" ];
|
|
button_radial_pos = floating_origin + radial_angle_to_vector( self.pos_angle, 4 );
|
|
|
|
while ( 1 )
|
|
{
|
|
//line( level.radial_button_group_info[ button_group ][ "view_pos" ], self.pos, ( 0, 1, 0 ), 0.05, false );
|
|
|
|
range_color = ( 1, 0, 0 );
|
|
if ( isInRange( self.start_angle, self.end_angle ) )
|
|
range_color = ( 1, 1, 0 );
|
|
|
|
print3d( self.pos, self.label, self.font_color, 0.75, self.font_size, 1 );
|
|
|
|
if ( isdefined( level.crib_debug ) && level.crib_debug > 0 )
|
|
{
|
|
print3d( button_radial_pos, ".("+int(self.pos_angle)+")", range_color, 0.75, 0.05, 1 );
|
|
|
|
line( floating_origin, floating_origin + radial_angle_to_vector( self.start_angle, 2 ), range_color, 0.05 );
|
|
line( floating_origin + radial_angle_to_vector( self.start_angle, 2 ), floating_origin + radial_angle_to_vector( self.end_angle, 2 ), range_color, 0.05 );
|
|
|
|
// right stick debug ling
|
|
r_radial_pos = floating_origin + radial_angle_to_vector( level.rs_angle, 2 );
|
|
line( floating_origin, r_radial_pos, ( 1, 1, 1 ), 0.05 );
|
|
|
|
|
|
}
|
|
print3d( floating_origin - ( 0, 0, 4.5 ), "(A)=Select (X)=Back", (1, 1, 1), 0.5, 0.05, 1 );
|
|
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
|
|
Zoom_To_Radial_Menu( button_group, reverse )
|
|
{
|
|
level.active_button = undefined;
|
|
|
|
assertex( isdefined( level.observer ), "Missing observer (connected player), can not attach player to view path" );
|
|
|
|
if ( isdefined( level.radial_button_current_group ) && level.radial_button_current_group != "" )
|
|
{
|
|
level.radial_button_previous_group = level.radial_button_current_group;
|
|
}
|
|
else
|
|
{
|
|
level.radial_button_previous_group = "main";
|
|
level.radial_button_current_group = "main";
|
|
}
|
|
|
|
foreach ( button in level.radial_button_group[ level.radial_button_previous_group ] )
|
|
button notify( "remove_button" );
|
|
|
|
//iPrintLnBold( "flying to: " + button_group );
|
|
|
|
if ( isdefined( reverse ) && reverse )
|
|
level.observer go_path_by_targetname_reverse( level.radial_button_group_info[ level.radial_button_previous_group ][ "view_start" ], button_group );
|
|
else
|
|
level.observer go_path_by_targetname( level.radial_button_group_info[ button_group ][ "view_start" ] );
|
|
|
|
level thread draw_radial_buttons( button_group );
|
|
level.radial_button_current_group = button_group;
|
|
}
|
|
|
|
|
|
// ====================================================================================
|
|
// == Radial menu - math ==
|
|
// ====================================================================================
|
|
|
|
// edit function with care, returns orientation-sensistive angles
|
|
getRadialAngleFromEnt( button_group, ent )
|
|
{
|
|
assertex( isdefined( level.radial_button_group[ button_group ] ), "getRadialAngleFromEnt: Radial button group does not exist." );
|
|
assertex( isdefined( ent ), "getRadialAngleFromEnt: Missing entity to be measured." );
|
|
|
|
rAngle = level.radial_button_group_info[ button_group ][ "view_angles" ];
|
|
rPos = level.radial_button_group_info[ button_group ][ "view_pos" ];
|
|
rPos += vector_multiply( VectorNormalize( AnglesToForward( rAngle ) ), CONST_radial_center_extrude_dist );
|
|
rForward = AnglesToForward( rAngle );
|
|
rUpwardNorm = VectorNormalize( AnglesToUp( rAngle ) );
|
|
|
|
eAngle = ent.angles;
|
|
ePos = ent.origin;
|
|
|
|
projNorm = VectorNormalize( VectorFromLineToPoint( rPos, ( rPos + rForward ), ePos ) );
|
|
radial_angle = Acos( VectorDot( projNorm, rUpwardNorm ) );
|
|
|
|
// vector mirroring
|
|
if ( VectorDot( AnglesToRight( rAngle ), projNorm ) < 0 )
|
|
radial_angle = 360 - radial_angle;
|
|
|
|
return radial_angle;
|
|
}
|
|
|
|
|
|
// converts projected angle into player's view plane into a vector
|
|
radial_angle_to_vector( angle, scaler )
|
|
{
|
|
b_angles = ( 270 - ( angle ), 0 , 0 ); // 270 degrees offset to face the player
|
|
b_vec = AnglesToForward( b_angles );
|
|
b_vec_norm = VectorNormalize( b_vec );
|
|
b_vec_final = vector_multiply( b_vec_norm, scaler );
|
|
|
|
return b_vec_final;
|
|
}
|
|
|
|
|
|
getMidAngle( a1, a2 )
|
|
{
|
|
// 0 -> 360 domain
|
|
mid_angle = ( ( a1 + a2 + 720 ) / 2 ) - 360;
|
|
return mid_angle;
|
|
}
|
|
|
|
|
|
isInRange( start_angle, end_angle )
|
|
{
|
|
inside_big_angle = ( level.rs_angle > start_angle && level.rs_angle < 360 );
|
|
inside_small_angle = ( level.rs_angle > 0 && level.rs_angle < end_angle );
|
|
|
|
if ( start_angle > end_angle )
|
|
in_range = ( inside_big_angle || inside_small_angle );
|
|
else
|
|
in_range = ( level.rs_angle > start_angle && level.rs_angle < end_angle );
|
|
|
|
return in_range;
|
|
}
|
|
|
|
// ====================================================================================
|
|
// == Button action functions ==
|
|
// ====================================================================================
|
|
|
|
// close radial buttons
|
|
action_back()
|
|
{
|
|
//if ( isdefined( level.radial_button_previous_group ) && level.radial_button_previous_group != "" )
|
|
// zoom_to_radial_menu( level.radial_button_previous_group );
|
|
/*else*/ if ( isdefined( level.radial_button_current_group ) && level.radial_button_current_group != "main" )
|
|
zoom_to_radial_menu( "main", true );
|
|
else
|
|
return;
|
|
}
|
|
|
|
|
|
// ==== main ====
|
|
action_weapons_primary()
|
|
{
|
|
iPrintLnBold( "action_weapons_primary" );
|
|
zoom_to_radial_menu( "weapons_primary" );
|
|
}
|
|
|
|
|
|
action_weapons_secondary()
|
|
{
|
|
iPrintLnBold( "action_weapons_secondary" );
|
|
zoom_to_radial_menu( "weapons_secondary" );
|
|
}
|
|
|
|
action_gears()
|
|
{
|
|
iPrintLnBold( "action_gears" );
|
|
zoom_to_radial_menu( "gears" );
|
|
}
|
|
|
|
|
|
action_killstreak()
|
|
{
|
|
iPrintLnBold( "action_killstreak" );
|
|
zoom_to_radial_menu( "killstreak" );
|
|
}
|
|
|
|
|
|
action_leaderboards()
|
|
{
|
|
iPrintLnBold( "action_leaderboards" );
|
|
zoom_to_radial_menu( "leaderboards" );
|
|
}
|
|
|
|
// ====================================================================================
|
|
// == Pathing functions ==
|
|
// ====================================================================================
|
|
|
|
view_path_setup()
|
|
{
|
|
// setup all paths
|
|
level.view_paths = [];
|
|
|
|
// build paths
|
|
build_path_by_targetname( "player_view1_start" );
|
|
build_path_by_targetname( "player_view2_start" );
|
|
build_path_by_targetname( "player_view3_start" );
|
|
build_path_by_targetname( "player_view4_start" );
|
|
build_path_by_targetname( "player_view5_start" );
|
|
}
|
|
|
|
|
|
build_path_by_targetname( path_name )
|
|
{
|
|
level.view_paths[ path_name ] = [];
|
|
|
|
path_node = getent( path_name, "targetname" );
|
|
level.view_paths[ path_name ][ level.view_paths[ path_name ].size ] = path_node;
|
|
|
|
while( isdefined( path_node ) && isdefined( path_node.target ) )
|
|
{
|
|
next_node = getent( path_node.target, "targetname" );
|
|
level.view_paths[ path_name ][ level.view_paths[ path_name ].size ] = next_node;
|
|
path_node = next_node;
|
|
}
|
|
}
|
|
|
|
|
|
go_path_by_targetname( path_name )
|
|
{
|
|
// self is player
|
|
if ( !isdefined( level.dummy_mover ) )
|
|
{
|
|
start_node = level.view_paths[ path_name ][ 0 ];
|
|
level.dummy_mover = spawn( "script_model", start_node.origin );
|
|
level.dummy_mover.angles = start_node.angles;
|
|
//self AllowedStances( "stand" );
|
|
self setOrigin( level.dummy_mover.origin - ( 0, 0, 65 ) );
|
|
self linkTo( level.dummy_mover );
|
|
wait 0.05;
|
|
self setplayerangles ( level.dummy_mover.angles );
|
|
|
|
self thread force_player_angles();
|
|
}
|
|
|
|
/*
|
|
travel_time = 1;
|
|
dist = 0;
|
|
foreach ( idx, node in level.view_paths[ path_name ] )
|
|
{
|
|
if ( isdefined( level.view_paths[ path_name ][ idx + 1 ] ) )
|
|
dist += abs( distance( level.view_paths[ path_name ][ idx ].origin, level.view_paths[ path_name ][ idx + 1 ].origin ) );
|
|
}*/
|
|
|
|
travel_speed = CONST_view_travel_unit_time;
|
|
total_distance = abs( distance( level.dummy_mover.origin, level.view_paths[ path_name ][ level.view_paths[ path_name ].size - 1 ].origin ) );
|
|
travel_speed *= total_distance / CONST_view_travel_unit_dist;
|
|
travel_speed = max( travel_speed, 0.1 ); // due to repeated button presses, the travel distance can be cut to 0 travel speed at times.
|
|
|
|
blur_time = travel_speed;
|
|
if ( !CONST_direct_travel )
|
|
blur_time *= travel_speed * ( level.view_paths[ path_name ].size + 1 );
|
|
self thread blur_sine( CONST_blur_strength, blur_time );
|
|
|
|
foreach ( idx, node in level.view_paths[ path_name ] )
|
|
{
|
|
//travel_speed = travel_time * ( abs( distance( level.dummy_mover.origin, node.origin ) ) / dist );
|
|
//travel_speed += 0.05;
|
|
|
|
if ( CONST_direct_travel )
|
|
{
|
|
if ( idx != level.view_paths[ path_name ].size - 1 )
|
|
continue;
|
|
}
|
|
|
|
//level.dummy_mover MoveTo( node.origin, travel_speed );
|
|
level.dummy_mover MoveTo( node.origin, travel_speed, travel_speed * 0.5, 0 );
|
|
level.dummy_mover RotateTo( node.angles, travel_speed, travel_speed * 0.5, 0);
|
|
wait travel_speed;
|
|
}
|
|
}
|
|
|
|
|
|
go_path_by_targetname_reverse( path_name, back_to_button_group )
|
|
{
|
|
assertex( isdefined( level.dummy_mover ), "go_path_by_targetname_reverse called before go_path_by_targetname" );
|
|
|
|
travel_speed = CONST_view_travel_unit_time;
|
|
total_distance = abs( distance( level.dummy_mover.origin, level.radial_button_group_info[ back_to_button_group ][ "player_view_pos" ] ) );
|
|
travel_speed *= total_distance / CONST_view_travel_unit_dist;
|
|
travel_speed = max( travel_speed, 0.1 ); // due to repeated button presses, the travel distance can be cut to 0 travel speed at times.
|
|
|
|
blur_time = travel_speed;
|
|
if ( !CONST_direct_travel )
|
|
blur_time *= travel_speed * ( level.view_paths[ path_name ].size + 1 );
|
|
self thread blur_sine( CONST_blur_strength, blur_time );
|
|
|
|
if ( !CONST_direct_travel )
|
|
{
|
|
for ( idx = level.view_paths[ path_name ].size - 1; idx >= 0; idx-- )
|
|
{
|
|
node = level.view_paths[ path_name ][ idx ];
|
|
level.dummy_mover MoveTo( node.origin, travel_speed );
|
|
level.dummy_mover RotateTo( node.angles, travel_speed );
|
|
|
|
//self thread travel_view_fx( travel_speed );
|
|
wait travel_speed;
|
|
}
|
|
}
|
|
|
|
self thread blur_sine( CONST_blur_strength, travel_speed );
|
|
|
|
pos = level.radial_button_group_info[ back_to_button_group ][ "player_view_pos" ];
|
|
angle = level.radial_button_group_info[ back_to_button_group ][ "view_angles" ];
|
|
|
|
level.dummy_mover MoveTo( pos, travel_speed, travel_speed * 0.5, 0 );
|
|
level.dummy_mover RotateTo( angle, travel_speed, travel_speed * 0.5, 0 );
|
|
wait travel_speed;
|
|
}
|
|
|
|
|
|
travel_view_fx( time )
|
|
{
|
|
self setblurforplayer( 20, ( time + 0.2 )/2 );
|
|
self setblurforplayer( 0, ( time + 0.2 )/2 );
|
|
self shellshock( "frag_grenade_mp", time + 0.2 );
|
|
}
|
|
|
|
|
|
blur_sine( strength, time )
|
|
{
|
|
time_scaled = int( time/0.05 );
|
|
|
|
for( i = 0; i < time_scaled; i ++ )
|
|
{
|
|
fraction = ( i / ( time_scaled ) );
|
|
cos_fraction= sin( 180 * fraction );
|
|
blur_amount = strength * cos_fraction;
|
|
|
|
setdvar( "r_blur", blur_amount );
|
|
wait 0.05;
|
|
}
|
|
setdvar( "r_blur", 0 );
|
|
}
|
|
|
|
|
|
force_player_angles()
|
|
{
|
|
level endon( "game_ended" );
|
|
self endon( "disconnect" );
|
|
level.dummy_mover endon( "remove_dummy" );
|
|
|
|
while ( 1 )
|
|
{
|
|
self setplayerangles ( level.dummy_mover.angles );
|
|
wait 0.05;
|
|
}
|
|
} |