IW4-Dump-Files/maps/mp/_crib.gsc

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;
}
}