IW4-Dump-Files/maps/af_chase_code.gsc

2856 lines
68 KiB
Plaintext

#include maps\_utility;
#include common_scripts\utility;
#include maps\_anim;
#include animscripts\utility;
#include maps\_vehicle_spline_zodiac;
#include maps\_vehicle;
trigger_multiple_speed_think()
{
speed = self.script_speed;
AssertEx( IsDefined( speed ), "Trigger at " + self.origin + " has no script_speed" );
for ( ;; )
{
self waittill( "trigger", other );
if ( !isdefined( other.vehicle ) )
continue;
other.vehicle.veh_topspeed = speed;
}
}
//hmmmmmmmm
/*QUAKED trigger_multiple_speed (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE
defaulttexture="trigger"
Set the player vehicle maxspeed with script_speed.*/
ZODIAC_TREADFX_MOVETIME = .2;
ZODIAC_TREADFX_MOVETIMEFRACTION = 1 / ( ZODIAC_TREADFX_MOVETIME + .05 );
ZODIAC_TREADFX_HEIGHTOFFSET = ( 0, 0, 16 );
zodiac_treadfx_chaser( chaseobj )
{
// self here is the invisible boat for playing leveled wake fx.
PlayFXOnTag( getfx( "zodiac_wake_geotrail" ), self, "tag_origin" );
self NotSolid();
self Hide();
self endon( "death" );
chaseobj endon( "death" );
// needs to be it's own thread so can cleanup after the thing dies.
thread zodiac_treadfx_chaser_death( chaseobj );
chaseobj ent_flag_init( "in_air" );
childthread zodiac_treadfx_stop_notify( chaseobj );
childthread zodiac_treadfx_toggle( chaseobj );
while ( IsAlive( chaseobj ) )
{
// self DontInterpolate();
self MoveTo( chaseobj GetTagOrigin( "tag_origin" ) + ZODIAC_TREADFX_HEIGHTOFFSET + ( chaseobj Vehicle_GetVelocity() / ZODIAC_TREADFX_MOVETIMEFRACTION ), ZODIAC_TREADFX_MOVETIME );
self RotateTo( ( 0, chaseobj.angles[ 1 ], 0 ), ZODIAC_TREADFX_MOVETIME ) ;
wait ZODIAC_TREADFX_MOVETIME + .05;// + .05 to get rid of silly jiggle at the end when issueing back to back moveto's. Code bug I believe.
waittillframeend;
}
self Delete();
}
zodiac_treadfx_toggle( chaseobj )
{
while ( 1 )
{
msg = chaseobj waittill_any_return( "zodiac_treadfx_stop", "veh_leftground" );
if ( msg == "veh_leftground" )
chaseobj ent_flag_set( "in_air" );
StopFXOnTag( getfx( "zodiac_wake_geotrail" ), self, "tag_origin" );
msg = chaseobj waittill_any_return( "zodiac_treadfx_go", "veh_landed" );
if ( msg == "veh_landed" )
chaseobj ent_flag_clear( "in_air" );
PlayFXOnTag( getfx( "zodiac_wake_geotrail" ), self, "tag_origin" );
}
}
zodiac_treadfx_stop_notify( chaseobj )
{
while ( 1 )
{
if ( chaseobj Vehicle_GetSpeed() < 4 )
chaseobj notify( "zodiac_treadfx_stop" );
else if ( ! chaseobj ent_flag( "in_air" ) )
chaseobj notify( "zodiac_treadfx_go" );
wait .05;
}
}
zodiac_treadfx_chaser_death( chaseobj )
{
chaseobj waittill_any( "stop_bike", "death", "kill_treadfx" );
self Delete();
}
zodiac_treadfx()
{
chaser = Spawn( "script_model", self.origin );
chaser SetModel( self.model );
chaser.angles = ( 0, self.angles[ 1 ], 0 );
chaser thread zodiac_treadfx_chaser( self );
}
enemy_chase_boat_breadcrumb()
{
struct = SpawnStruct();
struct.origin = self.origin;
struct.angles = flat_angle( self.angles );
struct.spawn_time = GetTime();
level.breadcrumb[ level.breadcrumb.size ] = struct;
}
vehicle_dump()
{
predumpvehicles = GetEntArray( "script_vehicle", "code_classname" );
vehicles = [];
// dumping can jump a frame in which the information could be altered, this stores the necessary info real quick
foreach ( vehicle in predumpvehicles )
{
if ( IsSpawner( vehicle ) )
continue;
struct = SpawnStruct();
struct.classname = vehicle.classname;
struct.origin = vehicle.origin;
struct.angles = vehicle.angles;
// struct.spawner_id = vehicle.spawner_id;
struct.speedbeforepause = vehicle Vehicle_GetSpeed();
struct.script_VehicleSpawngroup = vehicle.script_vehiclespawngroup;
struct.script_VehicleStartMove = vehicle.script_vehiclestartmove;
struct.model = vehicle.model;
struct.angles = vehicle.angles;
if ( IsDefined( level.playersride ) && vehicle == level.playersride )
struct.playersride = true;
vehicles[ vehicles.size ] = struct;
}
fileprint_launcher_start_file();
fileprint_map_start();
foreach ( i, vehicle in vehicles )
{
origin = fileprint_radiant_vec( vehicle.origin );// convert these vectors to mapfile keypair format
angles = fileprint_radiant_vec( vehicle.angles );
fileprint_map_entity_start();
fileprint_map_keypairprint( "classname", "script_struct" );
fileprint_map_keypairprint( "model", vehicle.model );
fileprint_map_keypairprint( "origin", origin );
fileprint_map_keypairprint( "angles", angles );
if ( IsDefined( vehicle.speedbeforepause ) )
fileprint_map_keypairprint( "current_speed", vehicle.speedbeforepause );
if ( IsDefined( vehicle.script_VehicleSpawngroup ) )
fileprint_map_keypairprint( "script_vehiclespawngroup", vehicle.script_VehicleSpawngroup );
if ( IsDefined( vehicle.script_VehicleStartMove ) )
fileprint_map_keypairprint( "script_vehiclestartmove", vehicle.script_VehicleStartMove );
fileprint_map_entity_end();
}
map_name = level.script + "_veh_ref.map";
fileprint_launcher_end_file( "/map_source/" + map_name );
launcher_write_clipboard( map_name );
}
draw_crumb( crumb, lastcrumb, fraction )
{
if ( !flag( "debug_crumbs" ) )
return;
left_spot = crumb.origin + AnglesToRight( crumb.angles ) * -1000 ;
right_spot = crumb.origin + AnglesToRight( crumb.angles ) * 1000 ;
color = ( fraction, 1 - fraction, 0 );
Line( left_spot, right_spot, color );
if ( !isdefined( lastcrumb ) )
return;
left_spot_last = lastcrumb.origin + AnglesToRight( lastcrumb.angles ) * -1000 ;
right_spot_last = lastcrumb.origin + AnglesToRight( lastcrumb.angles ) * 1000 ;
Line( left_spot, left_spot_last, color );
Line( right_spot, right_spot_last, color );
}
zodiac_physics()
{
self.bigjump_timedelta = 500;
self.event_time = -1;
self.event = [];
self.event[ "jump" ] = [];
self.event[ "jump" ][ "driver" ] = false;
self.event[ "jump" ][ "passenger" ] = false;
self.event[ "bump" ] = [];
self.event[ "bump" ][ "driver" ] = false;
self.event[ "bump" ][ "passenger" ] = false;
self.event[ "bump_big" ] = [];
self.event[ "bump_big" ][ "driver" ] = false;
self.event[ "bump_big" ][ "passenger" ] = false;
self.event[ "sway_left" ] = [];
self.event[ "sway_left" ][ "driver" ] = false;
self.event[ "sway_left" ][ "passenger" ] = false;
self.event[ "sway_right" ] = [];
self.event[ "sway_right" ][ "driver" ] = false;
self.event[ "sway_right" ][ "passenger" ] = false;
self childthread watchVelocity();
self childthread listen_leftground();
self childthread listen_landed();
self childthread listen_jolt();
self childthread listen_bounce();
self childthread listen_turn_spray();
// self thread listen_collision();
}
zodiac_fx( fxName )
{
tag = "tag_origin";
if ( IsDefined( level._effect_tag[ fxName ] ) )
tag = level._effect_tag[ fxName ];
if ( IsDefined( level._effect[ fxName ] ) )
PlayFXOnTag( level._effect[ fxName ], self, tag );
//iprintlnbold( fxName );
if ( IsDefined( level.zodiac_fx_sound[ fxname ] ) )
thread play_sound_on_entity( level.zodiac_fx_sound[ fxname ] );
//println( fxName );
}
listen_leftground()
{
self endon( "death" );
flag_wait( "player_on_boat" );
for ( ;; )
{
self waittill( "veh_leftground" );
self.event_time = GetTime();
self.event[ "jump" ][ "driver" ] = true;
self.event[ "jump" ][ "passenger" ] = true;
zodiac_fx( "zodiac_leftground" );
}
}
listen_landed()
{
self endon( "death" );
wait 2; // no ignore the land that happens when they spawn above the water.
flag_wait( "player_on_boat" );
for ( ;; )
{
self waittill( "veh_landed" );
if ( self.event_time + self.bigjump_timedelta < GetTime() )
{
self.event[ "bump_big" ][ "driver" ] = true;
self.event[ "bump_big" ][ "passenger" ] = true;
if ( ! flag( "player_in_sight_of_boarding" ) )
thread water_bump( "bump_big" );
if ( self == level.players_boat )
zodiac_fx( "player_zodiac_bumpbig" );
else
zodiac_fx( "zodiac_bumpbig" );
}
else
{
self.event[ "bump" ][ "driver" ] = true;
self.event[ "bump" ][ "passenger" ] = true;
if ( ! flag( "player_in_sight_of_boarding" ) )
thread water_bump( "bump" );
if ( self == level.players_boat )
zodiac_fx( "player_zodiac_bump" );
else
zodiac_fx( "zodiac_bump" );
}
}
}
trigger_set_water_sheating_time( bump_small, bump_big )
{
self waittill( "trigger" );
set_water_sheating_time( bump_small, bump_big );
}
set_water_sheating_time( bump_small, bump_big )
{
// duplicated in af_chase_knife_fight_code
level.water_sheating_time[ "bump" ] = level.water_sheating_time[ bump_small ];
level.water_sheating_time[ "bump_big" ] = level.water_sheating_time[ bump_big ];
}
water_bump( bumptype )
{
if ( !isdefined( level.players_boat ) || self != level.players_boat )
return;
level endon( "missionfailed" );
if ( flag( "missionfailed" ) )
return;
if ( bumptype == "bump_big" )
level.player PlayRumbleOnEntity( "damage_heavy" );
else
level.player PlayRumbleOnEntity( "damage_light" );
if ( !flag( "no_more_physics_effects" ) )
level.player SetWaterSheeting( 1, level.water_sheating_time[ bumptype ] );
}
listen_jolt()
{
self endon( "death" );
flag_wait( "player_on_boat" );
for ( ;; )
{
self waittill( "veh_jolt", jolt );
if ( jolt[ 1 ] >= 0 )
{
self.event[ "sway_left" ][ "driver" ] = true;
self.event[ "sway_left" ][ "passenger" ] = true;
zodiac_fx( "zodiac_sway_left" );
}
else
{
self.event[ "sway_right" ][ "driver" ] = true;
self.event[ "sway_right" ][ "passenger" ] = true;
zodiac_fx( "zodiac_sway_right" );
}
}
}
listen_bounce()
{
self endon( "death" );
flag_wait( "player_on_boat" );
for ( ;; )
{
self waittill( "veh_boatbounce", force );
// if ( self == level.players_boat )
// IPrintLnBold( force );
if ( force < 50.0 )
{
//PlayFXOnTag( getfx( "zodiac_bounce_small_left" ), self, "TAG_FX_LF" );
//PlayFXOnTag( getfx( "zodiac_bounce_small_left" ), self, "TAG_FX_RF" );
zodiac_fx( "zodiac_bounce_small_left" );
zodiac_fx( "zodiac_bounce_small_right" );
}
else
{
//PlayFXOnTag( getfx( "zodiac_bounce_large_left" ), self, "TAG_FX_LF" );
//PlayFXOnTag( getfx( "zodiac_bounce_large_left" ), self, "TAG_FX_RF" );
zodiac_fx( "zodiac_bounce_large_left" );
zodiac_fx( "zodiac_bounce_large_right" );
}
}
}
listen_turn_spray()
{
self endon( "death" );
while ( 1 )
{
velocity = self Vehicle_GetBodyVelocity();
if ( self Vehicle_GetSpeed() > 40 )
{
if ( velocity[ 1 ] < -150.0 )
zodiac_fx( "zodiac_sway_right" );
else if ( velocity[ 1 ] > 150.0 )
zodiac_fx( "zodiac_sway_left" );
}
else if ( self Vehicle_GetSpeed() > 10 )
{
if ( velocity[ 1 ] < -30.0 )
zodiac_fx( "zodiac_sway_right_light" );
else if ( velocity[ 1 ] > 30.0 )
zodiac_fx( "zodiac_sway_left_light" );
}
wait .05;
}
}
listen_collision()
{
self endon( "death" );
for ( ;; )
{
self waittill( "veh_collision", collision, start_vel );
foreach ( rider in self.riders )
{
if ( IsAlive( rider ) && !isdefined( rider.magic_bullet_shield ) )
{
// rider.specialDeathFunc = animscripts\snowmobile::snowmobile_collide_death;
rider Kill();
}
}
zodiac_fx( "zodiac_collision" );
}
}
watchVelocity()
{
self endon( "death" );
vel = self Vehicle_GetVelocity();
for ( ;; )
{
self.prevFrameVelocity = vel;
vel = self Vehicle_GetVelocity();
wait .05;
}
}
autosave_boat_chase()
{
// I should just replace these with real autosave triggers.
self waittill( "trigger" );
if ( IsDefined( self.targetname ) )
autosave_by_name( self.targetname );
else
autosave_by_name( "boat_chase" );
}
autosave_boat_check_trailing()
{
return bread_crumb_get_player_trailing_fraction() < .5;
}
autosave_boat_check_player_speeding_along()
{
return level.players_boat Vehicle_GetSpeed() > 20;
}
bread_crumb_get_player_trailing_fraction()
{
if ( ! level.breadcrumb.size )
return 0;
crumb = level.breadcrumb[ 0 ];
time = ( GetTime() - crumb.spawn_time ) / 1000;
return time / level.breadcrumb_settings.fail_time;
}
bread_crumb_chase()
{
/#
SetDvarIfUninitialized( "scr_debug_breadcrumbs", 1 );
#/
/#
if ( GetDvarInt( "scr_zodiac_test" ) )
return;
#/
currenttime = GetTime();
lastcrumb = undefined;
test_array = [];
count = 0;
foreach ( crumb in level.breadcrumb )
{
time = ( currenttime - crumb.spawn_time ) / 1000;
trailing_fraction = time / level.breadcrumb_settings.fail_time;
if ( trailing_fraction > 1 )
bread_crumb_fail();
if ( ! count )
breadcrumb_docatchup( trailing_fraction );
if ( count < level.breadcrumb_settings.checkdepth )
test_array[ count ] = crumb;
if ( is_breadcrumb_debug() )
draw_crumb( crumb, lastcrumb, trailing_fraction );
lastcrumb = crumb;
count++;
}
// skipped = false;
foreach ( crumb in test_array )
{
vec = AnglesToForward( crumb.angles );
vec2 = VectorNormalize( ( level.player.origin - crumb.origin ) );
vecdot = VectorDot( vec, vec2 );
if ( vecdot > 0 )
level.breadcrumb = array_remove( level.breadcrumb, crumb );
}
}
breadcrumb_docatchup( trailing_fraction )
{
if ( trailing_fraction < .25 )
flag_set( "zodiac_catchup" );
else
flag_clear( "zodiac_catchup" );
}
bread_crumb_fail()
{
if ( !isalive( level.player ) )
return;
/#
if ( GetDvarInt( "scr_zodiac_test" ) )
return;
#/
// Shepherd got away.
level notify ( "stop_deadquote_for_gettingout_of_bounds" );
SetDvar( "ui_deadquote", &"AF_CHASE_MISSION_FAILED_KEEP_UP" );
if ( level.start_point != "test_boat_current" )
missionFailedWrapper();
}
is_breadcrumb_debug()
{
return GetDvarInt( "scr_debug_breadcrumbs" );
}
zodiac_monitor_player_trailing_time()
{
self endon( "death" );
flag_wait( "player_on_boat" );
while ( 1 )
{
level waittill( "zodiac_catchup" );
if ( flag( "zodiac_boarding" ) )
return;
if ( flag( "zodiac_catchup" ) )
{
player_boat_speed_plus = level.players_boat Vehicle_GetSpeed() + 5;
if ( self Vehicle_GetSpeed() < player_boat_speed_plus )
self Vehicle_SetSpeed( player_boat_speed_plus, 15, 15 );
player_boat_speed_plus = undefined;
}
else
self ResumeSpeed( 15 );
}
}
zodiac_catchup()
{
player_speed_plus = level.players_boat Vehicle_GetSpeed() + 5;
if ( self Vehicle_GetSpeed() < player_speed_plus )
self Vehicle_SetSpeed( player_speed_plus, 15, 15 );
}
is_main_enemy_boat()
{
if ( !isdefined( self.targetname ) )
return false;
return self.targetname == "enemy_chase_boat";
}
zodiac_boat_ai( boat )
{
// kill _vehicle_anim stuff. not completely just gets them out of idle loop
if ( !isai( self ) )
return;
self notify( "newanim" );
//make them crouch
self.desired_anim_pose = "crouch";
self AllowedStances( "crouch" );
self thread animscripts\utility::UpdateAnimPose();
self AllowedStances( "crouch" );
self.baseaccuracy = 0;// don't get accurate untill they are in range.
self.accuracystationarymod = .5;
}
heli_attack_player_idle()
{
self waittill( "trigger", heli );
level.players_boat endon( "death" );
heli thread mgoff();
heli endon( "death" );
heli thread handle_fire_missiles();
while ( Distance( level.player.origin, self.origin ) > 8500 )
wait .05;
heli thread mgon();
foreach ( turret in heli.mgturret )
{
turret SetAISpread( 2 );
turret SetConvergenceTime( 5 );
turret.accuracy = .5;
}
if ( ! flag( "rapids_trigger" ) )// don't care about this particular dialog after the rapids.
level notify( "dialog_helicopter_ahead" );
heli SetLookAtEnt( level.player );
while ( in_front( level.players_boat, heli ) )
wait .05;
if ( ! flag( "rapids_trigger" ) )// don't care about this particular dialog after the rapids.
level notify( "dialog_helicopter_six" );
foreach ( turret in heli.mgturret )
{
turret SetAISpread( 20 );
turret SetConvergenceTime( 7 );
turret.accuracy = 0;
}
wait 3;// let it try to converge then turn it off.
heli thread mgoff();
}
rumble_with_throttle()
{
rumble_ent = get_rumble_ent();
throttle_leveling_time = 3.4;
level_throttle = .01;
full_throttled_time = 0;
rumble_fraction = .13;
while ( 1 )
{
throttle = self Vehicle_GetThrottle();
full_throttled_time += .05;
if ( throttle < .5 )
{
full_throttled_time = 0;
throttle_level_fraction = 1;
}
else
{
throttle_level_fraction = 1 - ( full_throttled_time / throttle_leveling_time );
}
rumble_ent.intensity = ( throttle * rumble_fraction * throttle_level_fraction );
if ( full_throttled_time > throttle_leveling_time || self Vehicle_GetSpeed() > 43 )
{
full_throttled_time = throttle_leveling_time;// probably not necessary. just keeping the number from going really high.
rumble_ent.intensity = 0;
}
wait .05;
if ( flag( "player_in_sight_of_boarding" ) )
break;
}
rumble_ent Delete();
}
kill_ai_in_volume()
{
volume = GetEnt( self.target, "targetname" );
Assert( IsDefined( volume ) );
self waittill( "trigger" );
ai = GetAIArray();
foreach ( guy in ai )
if ( guy IsTouching( volume ) && !guy is_hero() )
guy Delete();
//hack.. shortcutting adding another volume. want to delete these fx forever.
tester = Spawn( "script_origin", ( 0, 0, 0 ) );
inc = 0;
foreach ( createfxent in level.createfxent )
{
inc++;
if ( IsDefined( createfxent.looper ) )
{
level.createfxent = array_remove( level.createfxent, createfxent );
tester.origin = createfxent.v[ "origin" ];
if ( tester IsTouching( volume ) )
createfxent.looper Delete();
}
if ( inc > 3 )
{
inc = 0;
wait .05;
}
}
tester Delete();
}
kill_all_the_ai_and_fx_from_boatride()
{
kill_ai_in_volume = GetEntArray( "kill_ai_in_volume", "targetname" );
foreach ( trigger in kill_ai_in_volume )
{
wait( 0.1 );
trigger notify( "trigger", level.player );
}
}
kill_destructibles_and_barrels_in_volume()
{
volume = GetEnt( self.target, "targetname" );
Assert( IsDefined( volume ) );
self waittill( "trigger" );
shootable_stuff = GetEntArray( "destructible_toy", "targetname" );
inc = 0;
foreach ( thing in shootable_stuff )
{
thing delete_shootable_stuff_in_volume( volume );
inc++;
if ( inc > 3 )
{
inc = 0;
wait .05;
}
}
//dupping script for speed.
shootable_stuff = GetEntArray( "explodable_barrel", "targetname" );
foreach ( thing in shootable_stuff )
{
thing delete_shootable_stuff_in_volume( volume );
inc++;
if ( inc > 3 )
{
inc = 0;
wait .05;
}
}
}
delete_shootable_stuff_in_volume( volume )
{
if ( ! self IsTouching( volume ) )
return;
self notify( "delete_destructible" );// kill the effects looping first.
self Delete();
}
disable_origin_offset()
{
// I need this for more precise hovering with the ramp in the water.
self.originheightoffset = undefined;
}
destructible_fake()
{
self waittill( "trigger" );
destructible_org = GetEnt( self.target, "targetname" );
radius = 600;
if ( IsDefined( destructible_org.radius ) )
radius = destructible_org.radius;
count = 3;
destructible_damage_count_in_radius( count, radius, destructible_org.origin );
}
destructible_damage_count_in_radius( count, radius, origin )
{
destructible_toys = get_array_of_closest( origin, GetEntArray( "destructible_toy", "targetname" ), undefined, count, radius, 0 ) ;
foreach ( toy in destructible_toys )
{
wait RandomFloatRange( .1, .4 );
// toy thread common_scripts\_destructible::force_explosion();
thread destroy_fast( toy );
}
}
destroy_fast( toy )
{
for ( i = 0; i < 5; i++ )
{
toy notify( "damage", 160, level.player, self.origin, toy.origin, "MOD_PISTOL_BULLET", "", "" );
wait RandomFloatRange( .1, .2 );
}
}
raise_attacker_accuracy_on_nearby_boats()
{
flag_wait( "player_on_boat" );
level.players_boat endon( "death" );
while ( 1 )
{
attack_boats_in_range_in_front();
wait .05;
}
}
SQRT_BOATS_IN_RANGE = 1400 * 1400;
SQRT_BOATS_IN_RANGE_BEHIND = 50 * 50;
attack_boats_in_range_in_front( range, backrange )
{
boats = GetEntArray( "script_vehicle_zodiac_physics", "classname" );
return_boats = [];
foreach ( boat in boats )
{
if ( boat == level.players_boat )
continue;
if ( IsSpawner( boat ) )
continue;
if ( ! boat_in_range_in_front( boat ) )
continue;
boat thread raise_attacker_accuracy_while_in_range();
}
return return_boats;
}
raise_attacker_accuracy_while_in_range()
{
self notify( "raise_attacker_accuracy_while_in_range" );
self endon( "raise_attacker_accuracy_while_in_range" );
self endon( "death" );
foreach ( rider in self.riders )
{
rider.baseaccuracy = 6;
// rider.baseaccuracy = 10;
rider.suppressionwait = 1000;
}
while ( boat_in_range_in_front( self ) )
wait .05;
foreach ( rider in self.riders )
{
rider.baseaccuracy = 0;
// rider.ignoreSuppression = false;
}
}
boat_in_range_in_front( boat )
{
if ( flag( "player_in_open" ) )
return true;
if ( DistanceSquared( boat.origin, level.players_boat.origin ) > SQRT_BOATS_IN_RANGE )
return false;
dot = get_dot( level.players_boat.origin, level.players_boat.angles, boat.origin );
// if ( dot < 0 && DistanceSquared( boat.origin, level.players_boat.origin ) > SQRT_BOATS_IN_RANGE_BEHIND )
if ( dot < 0.642787 )// ~50
return false;
return true;
}
conveyerbelt_speed( yaw, speed, rate )
{
level.VehPhys_SetConveyorBelt_yaw = yaw;
speeddiff = speed - level.VehPhys_SetConveyorBelt_speed;
if ( speeddiff == 0 )
return;
time = abs( speeddiff / rate );
level notify( "conveyerbelt_speed" );
level endon( "conveyerbelt_speed" );
iterations = Int( time / .05 ) ;
speedinc = 0;
if ( iterations != 0 )
speedinc = speeddiff / iterations;
else
return;
for ( i = 0; i < iterations; i++ )
{
wait .05;
level.VehPhys_SetConveyorBelt_speed += speedinc;
}
level.VehPhys_SetConveyorBelt_speed = speed;
}
CONVEYERBELT_PLAYER_MAX_SPEED = 40;
CONVEYERBELT_PLAYER_MIN_SPEED = 20;
conveyerbelt_player_speed_mod()
{
mod = 1;
dif = CONVEYERBELT_PLAYER_MAX_SPEED - CONVEYERBELT_PLAYER_MIN_SPEED;
velocity = level.players_boat Vehicle_GetVelocity();
speed = Distance( velocity, ( 0, 0, 0 ) ) / 17.6;
velocity = flat_origin( velocity );
normal = VectorNormalize( velocity );
forward = AnglesToForward( ( 0, level.VehPhys_SetConveyorBelt_yaw, 0 ) );
dot = VectorDot( forward, normal );
// speed = level.players_boat Vehicle_GetSpeed();
if ( flag( "enemy_heli_takes_off" ) )
mod = 1;
if ( speed > CONVEYERBELT_PLAYER_MAX_SPEED )
mod = 0;
else if ( speed < CONVEYERBELT_PLAYER_MIN_SPEED )
mod = 1;
else
{
players_dif = speed - CONVEYERBELT_PLAYER_MIN_SPEED;
mod = 1 - ( players_dif / dif );
}
level.conveyerbelt_player_speed_mod = level.VehPhys_SetConveyorBelt_speed * mod;// for debugging
level.conveyerbelt_player_speed_mod *= level.VehPhys_SetConveyorBelt_speed_fraction;
self VehPhys_SetConveyorBelt( level.VehPhys_SetConveyorBelt_yaw, level.conveyerbelt_player_speed_mod );
}
conveyerbelt_set_speed_fraction( dest_fraction, time )
{
level notify( "conveyerbelt_set_speed_fraction" );
level endon( "conveyerbelt_set_speed_fraction" );
if ( time == 0 )
{
level.VehPhys_SetConveyorBelt_speed_fraction = dest_fraction;
return;
}
current_fraction = level.VehPhys_SetConveyorBelt_speed_fraction;
incs = Int( time * 20 );
fraction_increment = ( dest_fraction - current_fraction ) / incs;
for ( i = 0; i < incs; i++ )
{
level.VehPhys_SetConveyorBelt_speed_fraction += fraction_increment;
wait .05;
}
level.VehPhys_SetConveyorBelt_speed_fraction = dest_fraction;
}
conveyerbelt_clear_speed_fraction()
{
conveyerbelt_set_speed_fraction( 1 );
}
set_fixed_node_after_seeing_player_spawn_func()
{
self endon( "death" );
if ( IsSubStr( self.classname, "shepherd" ) )
return;
while ( !self CanSee( level.player ) && Distance( self.origin, level.player.origin ) > 3500 )
wait .1;
self.fixednode = true;
self.pathenemyfightdist = 0;
self.pathenemylookahead = 0;
}
CONVEYER_RATE = 4;
river_current( noteworthy )
{
level notify( "new_river_current" );
level endon( "new_river_current" );
/#
if ( GetDvarInt( "scr_zodiac_test" ) )
return;
#/
current_node = getstruct( noteworthy, "script_noteworthy" );
next_node = getstruct( current_node.target, "targetname" );
maxdropspeed_cos = Cos( 35 );
maxdropspeed = 45;
maxdropspeed_lower_cap = maxdropspeed;
mindropspeed_cos = Cos( 3 );
mindropspeed = 10;
if ( IsDefined( current_node.script_speed ) )
mindropspeed = current_node.script_speed;
next_angle = get_next_angle( next_node );
level.VehPhys_SetConveyorBelt_speed = 4;
flag_wait( "player_on_boat" );
level.players_boat endon( "death" );
level endon( "player_over_the_waterfall" );
level endon( "water_cliff_jump_splash_sequence" );
childthread river_current_apply();
flat_angle = ( 0, 0, 0 );
while ( 1 )
{
dot = get_dot( next_node.origin, next_angle, level.players_boat.origin );
if ( dot < 0 )
{
// draw_arrow( current_node.origin , next_node.origin, (0,1,0) );
dot = get_dot( current_node.origin, flat_angle( VectorToAngles( next_node.origin - current_node.origin ) ), level.players_boat.origin );
if ( dot > 0 )
{
wait .05;
continue;
}
else
{
current_node = getstruct( current_node.targetname, "target" );
if ( !isdefined( current_node ) )
{
current_node = getstruct( next_node.targetname, "target" );// reset to the first node..
level.players_boat thread conveyerbelt_speed( flat_angle[ 1 ], 0, CONVEYER_RATE );
}
}
}
else
{
current_node = next_node;
}
if ( IsDefined( current_node.script_speed ) )
mindropspeed = current_node.script_speed;
if ( !isdefined( current_node.target ) )
break;
if ( mindropspeed > maxdropspeed_lower_cap )
maxdropspeed = mindropspeed + 20;
else
maxdropspeed = maxdropspeed_lower_cap;
next_node = getstruct( current_node.target, "targetname" );
if ( !isdefined( next_node ) )
{
next_node = current_node;
current_node = getstruct( next_node.targetname, "target" );// keep cycling the last section in this case.
wait .05;
continue;
}
if ( IsDefined( next_node.target ) )
next_angle = get_next_angle( next_node );
speed = mindropspeed;
flat_angle = flat_angle( VectorToAngles( next_node.origin - current_node.origin ) );
dot = get_dot( current_node.origin, flat_angle, next_node.origin );
dot = abs( dot );
if ( dot > mindropspeed_cos )
speed = mindropspeed;
else if ( dot < maxdropspeed_cos )
speed = maxdropspeed;
else
speed = maxdropspeed_cos / dot * maxdropspeed;
level.boatdropspeed = speed;
level.players_boat childthread conveyerbelt_speed( flat_angle[ 1 ], speed, CONVEYER_RATE );
wait .05;
}
level.players_boat childthread conveyerbelt_speed( 0, 0, CONVEYER_RATE );
}
river_current_apply()
{
if ( !isdefined( level.VehPhys_SetConveyorBelt_speed_fraction ) )
level.VehPhys_SetConveyorBelt_speed_fraction = 1;
while ( !isdefined( level.vehphys_setconveyorbelt_yaw ) )
wait .05;
level.players_boat endon( "death" );
while ( 1 )
{
level.players_boat conveyerbelt_player_speed_mod();
wait .05;
}
}
get_next_angle( current_node, currentangles )
{
next_node = getstruct( current_node.target, "targetname" );
Assert( IsDefined( next_node ) );
return VectorToAngles( next_node.origin - current_node.origin );
}
enable_bread_crumb_chase()
{
s = SpawnStruct();
s.checkdepth = 3;// how far up the chain do I crawl to see if we're caught up.
s.fail_time = 10;// how far behind the player is allowed to trail..
level endon( "quit_bread_crumb" );
level.breadcrumb_settings = s;
level.breadcrumb = [];
// thread bread_crumb_button();
while ( 1 )
{
bread_crumb_chase();
wait .05;
}
}
set_breadcrumb_fail_time( fail_time, transition_time )
{
if ( !isdefined( transition_time ) )
{
level.breadcrumb_settings.fail_time = fail_time;
return;
}
level notify( "set_breadcrumb_fail_time" );
level endon( "set_breadcrumb_fail_time" );
last_time = level.breadcrumb_settings.fail_time;
increase_time_by = fail_time - last_time;
increments = transition_time * 20;
inc_step = increase_time_by / increments;
for ( i = 0; i < increments; i++ )
{
level.breadcrumb_settings.fail_time += inc_step;
wait .05;
}
level.breadcrumb_settings.fail_time = fail_time;
}
bread_crumb_button()
{
while ( 1 )
{
while ( !level.player ButtonPressed( "BUTTON_Y" ) )
wait .05;
if ( flag( "debug_crumbs" ) )
flag_clear( "debug_crumbs" );
else
flag_set( "debug_crumbs" );
while ( level.player ButtonPressed( "BUTTON_Y" ) )
wait .05;
}
}
test_m203()
{
level.price endon( "death" );
effect = LoadFX( "muzzleflashes/m203_flshview" );
while ( ! flag( "exit_caves" ) )
{
start = level.price GetTagOrigin( "tag_flash" );
angles = level.price GetTagAngles( "tag_flash" );
if ( level.price has_good_enemy_for_grenade_launcher( start, angles ) )
{
PlayFXOnTag( effect, level.price, "tag_flash" );
shootpos = level.price.enemy GetShootAtPos() + ( 0, 0, 150 );
if ( Distance( level.price.origin, level.price.enemy.origin ) > 1700 )
shootpos += ( 0, 0, 150 );// I'm just guessing here. magical numbers make grenads go farther..
MagicBullet( "m203", start, shootpos );
wait 2.5;
}
wait .05;
}
}
test_m203_again()
{
level.price endon( "death" );
effect = LoadFX( "muzzleflashes/m203_flshview" );
while ( 1 )
{
start = level.price GetTagOrigin( "tag_flash" );
angles = level.price GetTagAngles( "tag_flash" );
if ( level.price has_good_enemy_for_grenade_launcher( start, angles ) )
{
PlayFXOnTag( effect, level.price, "tag_flash" );
shootpos = level.price.enemy GetShootAtPos() + ( 0, 0, 190 );
if ( Distance( level.price.origin, level.price.enemy.origin ) > 1700 )
shootpos += ( 0, 0, 120 );// I'm just guessing here. magical numbers make grenads go farther..
MagicBullet( "m203", start, shootpos );
wait 2.5;
}
wait .05;
}
}
FOV_M203 = 0.965925;// Cos( 15 )
DIST_M203_SQRD = 650 * 650;
//good_spot_for_grenade_launcher
has_good_enemy_for_grenade_launcher( start, angles )
{
if ( !isdefined( self.enemy ) )
return false;
if ( ! DistanceSquared( start, self.enemy.origin ) > DIST_M203_SQRD )
return false;
if ( ! within_fov( start, angles, self.enemy GetShootAtPos(), FOV_M203 ) )
return false;
good_spot_for_grenade_launcher = getstructarray( "good_spot_for_grenade_launcher", "targetname" );
foreach ( spot in good_spot_for_grenade_launcher )
{
Assert( IsDefined( spot.radius ) );
if ( Distance( spot.origin, self.enemy.origin ) < spot.radius )
if ( ! burning_barrel_in_spots_radius( spot ) )
return true;
}
return false;
}
burning_barrel_in_spots_radius( spot )
{
barrels = GetEntArray( "explodable_barrel", "targetname" );
squaredist = spot.radius * spot.radius;
foreach ( barrel in barrels )
{
if ( DistanceSquared( spot.origin, barrel.origin ) > squaredist )
continue;
if ( barrel.damagetaken )
return true;
}
return false;
}
price_position_switch()
{
Assert( IsDefined( self.script_noteworthy ) );
self waittill( "trigger" );
level.price.scripted_boat_pose = self.script_noteworthy;
}
bobbing_boat_spawn()
{
self VehPhys_Crash();
}
in_front( ent1, ent2 )
{
return get_dot( ent1.origin, ent1.angles, ent2.origin ) > 0 ;
}
in_front_by_velocity( ent1, ent2 )
{
return get_dot( ent1.origin, VectorToAngles( ent1 Vehicle_GetVelocity() ), ent2.origin ) > 0 ;
}
delete_when_not_in_view()
{
cosa = Cos( 55 );
while ( within_fov_of_players( self.origin, cosa ) )
wait .05;
self Delete();
}
//movewithrate( dest, destang, moverate, endrate, gravity, accelfraction, decelfraction )
movewithrate( dest, moverate, accelfraction, decelfraction )
{
self notify( "newmove" );
self endon( "newmove" );
if ( !isdefined( accelfraction ) )
accelfraction = 0;
if ( !isdefined( decelfraction ) )
decelfraction = 0;
self.movefinished = false;
// moverate = units / persecond
if ( !isdefined( moverate ) )
moverate = 200;
dist = Distance( self.origin, dest );
movetime = dist / moverate;
movevec = VectorNormalize( dest - self.origin );
accel = 0;
decel = 0;
if ( accelfraction > 0 )
accel = movetime * accelfraction;
if ( decelfraction > 0 )
decel = movetime * decelfraction;
self MoveTo( dest, movetime, accel, decel );
// self RotateTo( destang, movetime, accel, decel );
wait movetime;
if ( !isdefined( self ) )
return;
self.velocity = movevec * ( dist / movetime );
self.movefinished = true;
}
price_anim_single_on_boat( anim_scene, relink )
{
self endon( "death" );
if ( !isdefined( relink ) )
relink = true;
level.price notify( "new_price_anim_single_on_boat" );
level.price endon( "new_price_anim_single_on_boat" );
flag_set( "price_anim_on_boat" );
level.price radio_dialogue_stop();
level.price LinkTo( level.players_boat, "tag_guy2" );
level.players_boat anim_generic_queue( level.price, anim_scene, "tag_guy2" );
if ( ! relink )
return;// assuming a looped anim call follows
price_link_and_think();
flag_clear( "price_anim_on_boat" );
}
price_anim_loop_on_boat( anim_scene, notify_str, relink )
{
if ( !isdefined( relink ) )
relink = true;
level.price notify( "new_price_anim_single_on_boat" );
level.price endon( "new_price_anim_single_on_boat" );
level.players_boat thread anim_generic_loop( level.price, anim_scene, notify_str, "tag_guy2" );
level.players_boat waittill( notify_str );
if ( relink )
price_link_and_think();
flag_clear( "price_anim_on_boat" );
}
boatrider_link( vehicle )
{
self LinkToBlendToTag( vehicle, "tag_guy2", false );
}
boatrider_think( vehicle )
{
boatrider_link( vehicle );
self AllowedStances( "crouch" );
self.vehicle = vehicle;
self.force_canAttackEnemyNode = true;
self thread boatrider_targets();
self.fullAutoRangeSq = 2000 * 2000;
// make Price know about all enemies (helps enemy selection when moving fast)
self.highlyAwareRadius = 2048;
self AnimCustom( maps\_zodiac_ai::think );
}
boatrider_targets()
{
level.price endon( "stop_boatrider_targets" );
level.price endon( "death" );
while ( 1 )
{
wait .05;
end = level.price maps\_zodiac_drive::drive_magic_bullet_get_end( level.players_boat, level.player GetEye(), true );// piggyback this functionality. Price finds the same targets interesting.
if ( !isdefined( end.obj ) )
{
level.price ClearEntityTarget();
continue;
}
if ( !isai( end.obj ) )
{
level.price SetEntityTarget( end.obj );
level.price.favoriteenemy = undefined;
if ( IsDefined( end.shootable_driver ) )
end.obj thread enable_shoot_driver();
}
else
{
level.price ClearEntityTarget();
level.price.favoriteenemy = end.obj;
}
}
}
enable_shoot_driver()
{
self notify( "enable_shoot_driver" );
self endon( "enable_shoot_driver" );
self.allowdeath = 1;
self SetCanDamage( true );
self waittill( "damage" );
maps\_zodiac_drive::driver_death( self );
}
price_link_and_think()
{
level.price boatrider_link( level.players_boat );
level.price AnimCustom( maps\_zodiac_ai::think );
}
player_lerplink_fov( opts )
{
time = opts.time;
ent = opts.ent;
tag = opts.tag;
base_fov = opts.base_fov;
dest_fov = opts.dest_fov;
level.player FreezeControls( true );
// this is ghetto hack..
Assert( time > 0.0 );
timeincs = time * 20;
current_fov = base_fov;
fov_dif = dest_fov - base_fov;
fov_inc = fov_dif / timeincs;
timeincs = Int( timeincs );
for ( i = 0; i < timeincs; i++ )
{
current_fov += fov_inc;
level.player PlayerLinkToDelta( ent, tag, 1, current_fov, current_fov, current_fov, current_fov );
wait .05;
}
level.player FreezeControls( false );
}
trigger_thread_the_needle()
{
targetent = getstruct( self.target, "targetname" );
Assert( IsDefined( targetent ) );
self waittill( "trigger" );
normal = VectorNormalize( self.origin - targetent.origin );
forward = VectorNormalize( level.players_boat Vehicle_GetVelocity() );
dot = VectorDot( forward, normal );
if ( dot > 0.984807 )// cos 10
level.price radio_dialogue( "afchase_pri_threadtheneedle", 1 );
}
_objective_onentity( id, ent )
{
Objective_OnEntity( id, ent, ( 0, 0, 80 ) );
ent waittill( "death" );
Objective_Position( id, ( 0, 0, 0 ) );
/*
ent endon( "death" );
while ( 1 )
{
eye_pos = level.player GetEye();
Objective_Position( id, (ent.origin[0],ent.origin[1],eye_pos[2]) );
wait .05;
}
*/
}
crashable_whizby_boats()
{
self.veh_pathtype = "follow";
self VehPhys_EnableCrashing();
while ( 1 )
{
self waittill( "veh_jolt" );// veh_collision wasn't working, just make it crash when it jolts around the player that should do.
if ( Distance( self.origin, level.player.origin ) < 512 )
break;
}
self VehPhys_Crash();
}
get_farthest_struct( org, array )
{
if ( array.size < 1 )
return;
dist = DistanceSquared( array[ 0 ].origin, org );
ent = array[ 0 ];
for ( i = 0; i < array.size; i++ )
{
newdist = DistanceSquared( array[ i ].origin, org );
if ( newdist < dist )
continue;
dist = newdist;
ent = array[ i ];
}
return ent;
}
ignoreall_till_not_touch( guy )
{
prevteam = guy.team;
guy endon( "death" );
guy.ignoreall = true;
while ( guy IsTouching( self ) )// teehee
wait .05;
guy.ignoreall = false;
}
dump_on_command()
{
while ( 1 )
{
while ( ! level.player ButtonPressed( "BUTTON_B" ) )
wait .05;
vehicle_dump();
while ( level.player ButtonPressed( "BUTTON_B" ) )
wait .05;
}
}
set_lerp_opts( time, ent, tag, base_fov, dest_fov )
{
opts = SpawnStruct();
opts.time = time;
opts.ent = ent;
opts.tag = tag;
opts.base_fov = base_fov;
opts.dest_fov = dest_fov;
return opts;
}
player_full_heath()
{
return level.player.health / level.player.maxhealth == 1;
}
trigger_neutral_enemies()
{
while ( 1 )
{
self waittill( "trigger", other );
if ( !isalive( other ) )
continue;
if ( !first_touch( other ) )
continue;
thread ignoreall_till_not_touch( other );
}
}
draw_arrow_forward()
{
self endon( "death" );
while ( 1 )
{
draw_arrow( self.origin, self.origin + AnglesToForward( self.angles ) * 200, ( 0, 0, 1 ) );
wait .05;
}
}
dvar_warn()
{
if ( ! GetDvarInt( "scr_zodiac_test" ) )
return;
wait 3;
IPrintLnBold( "you will need to reset scr_zodiac_test to play the level normally again ( restart the game )" );
}
get_boat_rider( num )
{
if ( !isdefined( level.boatrider ) )
level.boatrider = [];
else
if ( IsDefined( level.boatrider[ num ] ) )
return level.boatrider[ num ];
level.boatrider[ num ] = spawn_targetname( num, true );
level.boatrider[ num ] magic_bullet_shield();
level.boatrider[ num ] disable_pain();
level.boatrider[ num ].ignoreSuppression = true;
level.boatrider[ num ] set_battlechatter( false ); // got enough chatter on the boat.
return level.boatrider[ num ];
}
set_price_auto_switch_pose()
{
level.price.scripted_boat_pose = undefined;
level.price.use_auto_pose = true;
}
ZODIAC_DIALOGUE_RANGE = 3000 * 3000;
zodiac_enemy_setup()
{
self.dontunloadonend = true;
// self thread zodiac_monitor_player_trailing_time();
foreach ( rider in self.riders )
{
rider thread zodiac_boat_ai( self );
}
flag_wait( "player_on_boat" );
self endon( "death" );
level.players_boat endon( "death" );
while ( 1 )
{
start_origin = level.players_boat.origin;
end_origin = self.origin;
// normal = VectorNormalize( end_origin - start_origin );
// forward = AnglesToRight( level.players_boat.angles );
// dot = VectorDot( forward, normal );
if ( DistanceSquared( self.origin, level.players_boat.origin ) > ZODIAC_DIALOGUE_RANGE )
{
wait .05;
continue;
}
level.dialog_dir = animscripts\battlechatter::getDirectionFacingClock( level.players_boat.angles, start_origin, end_origin );
level notify( "dialog_direction" );
wait .05;
}
}
exp_fade_overlay( target_alpha, fade_time )
{
self notify( "exp_fade_overlay" );
self endon( "exp_fade_overlay" );
fade_steps = 4;
step_angle = 90 / fade_steps;
current_angle = 0;
step_time = fade_time / fade_steps;
current_alpha = self.alpha;
alpha_dif = current_alpha - target_alpha;
for ( i = 0; i < fade_steps; i++ )
{
current_angle += step_angle;
self FadeOverTime( step_time );
if ( target_alpha > current_alpha )
{
fraction = 1 - Cos( current_angle );
self.alpha = current_alpha - alpha_dif * fraction;
}
else
{
fraction = Sin( current_angle );
self.alpha = current_alpha - alpha_dif * fraction;
}
wait step_time;
}
}
handle_fire_missiles()
{
self endon( "death" );
level.players_boat endon( "death" );
while ( 1 )
{
dofire = true;
predictorg = fire_volley_of_missiles_predict( level.players_boat Vehicle_GetVelocity() );
// draw_arrow( self.origin, predictorg, (1,0,0) );
if ( !within_fov_2d( self.origin, self.angles, predictorg, 0.984807753 ) )
dofire = false;
if ( Distance( self.origin, predictorg ) < 2000 )
dofire = false;
if ( Distance( self.origin, predictorg ) > 5000 )
dofire = false;
if ( ! player_full_heath() )
dofire = false;
if ( dofire )
{
thread fire_volley_of_missiles_at_player();
flag_waitopen( "heli_firing" );
wait RandomFloatRange( 1.2, 2.4 );
}
wait .05;
}
}
fire_volley_of_missiles_predict( velocity )
{
return level.players_boat.origin + ( velocity * 1.50 );// guessing
}
dialog_fire_volley_of_missiles_at_player( base_origin )
{
if ( flag( "rapids_trigger" ) )
return;
normal = VectorNormalize( base_origin - level.players_boat.origin );
forward = AnglesToRight( level.players_boat.angles );
dot = VectorDot( forward, normal );
if ( dot < 0 )
{
if ( cointoss() )
level.price thread generic_dialogue_queue( "afchase_pri_rightright", .5 );
else
level.price thread generic_dialogue_queue( "afchase_pri_right", .5 );
}
else
{
if ( cointoss() )
level.price thread generic_dialogue_queue( "afchase_pri_leftleft", .5 );
else
level.price thread generic_dialogue_queue( "afchase_pri_left", .5 );
}
}
fire_volley_of_missiles_at_player()
{
if ( !isalive( self ) )
return;
if ( flag( "heli_firing" ) )
return;
flag_set( "heli_firing" );
timer = GetTime() + 3000;
if ( !isalive( self ) )
{
flag_clear( "heli_firing" );
return;
}
number_of_shots = RandomIntRange( 4, 5 );
velocity = level.players_boat Vehicle_GetVelocity();
base_origin = fire_volley_of_missiles_predict( velocity );
base_origin += flat_origin( randomvectorrange( -120, 120 ) );
dialog_fire_volley_of_missiles_at_player( base_origin );
// base_origin += ( 0, 0, 24 );
shot_origin = base_origin;
shotorgs = [];
linkorg = Spawn( "script_origin", level.players_boat.origin );
linkorg thread linkorg( level.players_boat );
// if( IsDefined( level.players_boat ) )
// thread draw_line_from_ent_to_ent_until_notify( linkorg , level.players_boat , 0 , 1 , 0 , linkorg , "balls" );
for ( i = 0; i < number_of_shots; i++ )
{
shotorgs[ i ] = Spawn( "script_origin", shot_origin );
shotorgs[ i ] LinkTo( linkorg );
shot_origin += velocity * .1;
// thread draw_line_from_ent_to_ent_until_notify( linkorg , shotorgs[i] , 1 , 0 , 1 , linkorg , "balls" );
}
tags = [];
tags[ 0 ] = "tag_missile_right";
tags[ 1 ] = "tag_missile_left";
ents = [];
for ( i = 0; i < number_of_shots; i++ )
{
if ( !isalive( self ) )
break;
self SetVehWeapon( "littlebird_FFAR" );
self SetTurretTargetEnt( shotorgs[ i ] );
missile = self FireWeapon( tags[ i % tags.size ], shotorgs[ i ], ( 0, 0, 0 ) );
missile Missile_SetFlightmodeDirect();
missile Missile_SetTargetEnt( shotorgs[ i ] );
missile thread kill_rpg_shot_behind_player();
// missile delayCall( 2.51, ::Missile_ClearTarget );
wait RandomFloatRange( 0.2, 0.3 );
}
linkorg notify( "balls" );
flag_clear( "heli_firing" );
wait 15;
foreach ( ent in shotorgs )
ent Delete();
linkorg Delete();
}
linkorg( linkent )
{
self endon( "death" );
linkent endon( "death" );
offset = self.origin - linkent.origin;
while ( 1 )
{
self MoveTo( linkent.origin + offset, .05, 0, 0 );
// self.origin = linkent.origin + offset;
wait .05;
}
}
get_generic_anim( anime )
{
return level.scr_anim[ "generic" ][ anime ];
}
cleanup_stuff_on_players_boat()
{
level.players_boat notify( "cleanup" );
if ( IsDefined( level.players_boat.gun_attached ) )
{
level.players_boat Detach( level.zodiac_gunModel, "tag_weapon_left" );
level.players_boat.gun_attached = undefined;
}
level.players_boat Detach( level.zodiac_playerHandModel, "tag_player" );
}
TEST_FLIP = false;
flip_when_player_dies()
{
level endon( "water_cliff_jump_splash_sequence" );
if ( !TEST_FLIP )
level.player waittill( "death" );
if ( TEST_FLIP )
{
while ( ! level.player ButtonPressed( "BUTTON_B" ) )
wait .05;
}
thread radio_dialogue_stop();
set_water_sheating_time( "bump_small_player_dies", "bump_big_player_dies" );
cleanup_stuff_on_players_boat();
linkobj = Spawn( "script_model", level.player.origin );
linkobj.angles = level.player.angles;
linkobj Hide();
linkobj SetModel( "zodiac_head_roller" );
linkobj LinkTo( self, "tag_player", ( 0, 0, 60 ), ( 0, 0, 0 ) );
offset_obj = Spawn( "script_model", level.player.origin );
offset_obj SetModel( "zodiac_head_roller" );
offset_obj LinkTo( linkobj, "tag_player", ( 0, 0, -60 ), ( 0, 0, 0 ) );
offset_obj.angles = level.player.angles;
offset_obj Hide();
blend_time = 1;
if ( TEST_FLIP )
{
level.player DismountVehicle();
level.player.drivingVehicle = level.players_boat;
}
wait .1;
// level.player PlayerLinkWeaponViewToDelta( linkobj, "tag_player", 1.0 );
level.player PlayerLinkToDelta( offset_obj, "tag_player", 1.0, 0, 0, 0, 0 );
level.player PlayerSetGroundReferenceEnt( offset_obj );
boatvelocity = self Vehicle_GetVelocity();
foreach ( rider in level.boatrider )
{
rider stop_magic_bullet_shield();
rider Unlink();
if ( IsDefined( rider.function_stack ) )
rider function_stack_clear();
rider Kill();
}
// if ( self Vehicle_GetSpeed() > 50 )
// self VehPhys_Crash( true );
// else if ( self Vehicle_GetSpeed() > 30 )
self delayCall( .75, ::VehPhys_Crash );
// wait 0.75;
oldorg = self.origin;
wait .1;
linkobj Unlink();
offset_vec = oldorg - self.origin;
offset_launchpoint = ( 0, 0, 0 );
//for spin
offset_launchpoint = ( offset_vec[ 0 ] * 100, offset_vec[ 1 ] * 100, 0 );
linkobj PhysicsLaunchServer( linkobj.origin + offset_launchpoint, 8 * boatvelocity + ( 0, 0, 500 ) );
lastorg = ( 0, 0, 0 );
while ( lastorg != linkobj.origin )
{
lastorg = linkobj.origin;
wait .05;
}
}
node_can_reach_spot_infront_of_player( basenode )
{
//might check basenode moveability
nodearray = GetNodesInRadius( level.player.origin, 800, 500, 1000, "path" );
forward = AnglesToForward( level.player.angles );
foreach ( node in nodearray )
{
normal = VectorNormalize( node.origin - level.player.origin );
dot = VectorDot( forward, normal );
if ( dot > Cos( 15 ) )
{
level.node_to_reach = node;// in a spawn function
return true;
}
}
return false;
}
find_good_node_for_price_to_spawn_at()
{
nodearray = GetNodesInRadius( level.player.origin, 230, 100, 1000, "path" );
forward = AnglesToForward( level.player.angles );
foreach ( node in nodearray )
{
normal = VectorNormalize( node.origin - level.player.origin );
dot = VectorDot( forward, normal );
//should spawn on the periphery
if ( dot < Cos( 45 ) && dot > 0 && node_can_reach_spot_infront_of_player( node ) )
return node;
}
}
lower_accuracy_behind_player()
{
self endon( "death" );
originalbaseaccuracy = self.baseaccuracy;
wait .1;// just in case I'm first.
if ( !isdefined( level.players_boat ) )
return;// craziness keeps goiing.
level.players_boat endon( "death" );
if ( IsDefined( self.ridingVehicle ) && IsSubStr( self.ridingvehicle.classname, "zodiac" ) )
return;
if ( IsSubStr( self.classname, "shepherd" ) )
return;
while ( 1 )
{
while ( boat_in_range_in_front( self ) )
wait .05;
self.baseaccuracy = 0;
self.ignoreSuppression = false;
while ( ! boat_in_range_in_front( self ) )
wait .05;
self.baseaccuracy = originalbaseaccuracy;
}
}
/*
point_end( shepherd )
{
Shepherd notify( "point_end" );
controller = Shepherd getanim( "ending_additive_controller" );
Shepherd ClearAnim( controller, 0.2 );
shepherd SetLookAtEntity( level.player );
//( position, turn acceleration );
}
*/
setup_boat_for_drive()
{
self Vehicle_TurnEngineOff();
self maps\_vehicle::godon();
self MakeUnusable();
level.players_boat = self;
level.players_boat StartUsingHeroOnlyLighting();
self SetModel( "vehicle_zodiac" );
self waittill( "vehicle_mount", player );
level.dofDefault[ "nearStart" ] = 10;
level.dofDefault[ "nearEnd" ] = 20;
// thread missile_repulser();
level.price.orgmodel = level.price.model;
level.price SetModel( "body_desert_tf141_zodiac" );
hideTagList = GetWeaponHideTags( level.price.weapon );
for ( i = 0; i < hideTagList.size; i++ )
level.price HidePart( hideTagList[ i ], "weapon_m4" );
self SetModel( "vehicle_zodiac_viewmodel" );
self Vehicle_TurnEngineOn();
flag_set( "player_on_boat" );
thread autosave_by_name_silent( "mount_boat" );
delayThread( 4, ::add_extra_autosave_check, "boat_check_player_speeding_along", ::autosave_boat_check_player_speeding_along, "players boat not moving fast enough!" );
level.player ent_flag_clear( "near_death_vision_enabled" );
thread dialog_boat_nag();
thread dialog_boat_direction_nag();
thread raise_attacker_accuracy_on_nearby_boats();
thread rumble_with_throttle();
thread flip_when_player_dies();
thread zodiac_treadfx();
boatrider = get_boat_rider( "boatrider0" );
if ( ! boatrider ent_flag_exist( "price_animated_into_boat" ) )
boatrider thread boatrider_think( self );
else
{
boatrider ent_flag_wait( "price_animated_into_boat" );
level notify( "stop_animate_price_into_boat" );
level.price StopAnimScripted();
level.price thread boatrider_think( level.players_boat );
}
}
price_ai_mods( price )
{
price.attackeraccuracy = 0;
price.baseaccuracy = .1;
price.ignoreSuppression = true;
price.dontavoidplayer = true;
price.takedamage = false;
price.suppressionwait = 0;
price.pathrandompercent = 0;
price.ignoreExplosionEvents = true;
price disable_surprise();
price.grenadeawareness = 0;
price.ignoreme = true;
price.IgnoreRandomBulletDamage = true;
price.disableBulletWhizbyReaction = true;
flag_wait( "player_on_boat" );
price.baseaccuracy = 25;
}
players_boat()
{
}
change_target_on_vehicle_spawner( boat_targetname, boat_destination_node )
{
boat = GetEnt( boat_targetname, "targetname" );
destnode = GetVehicleNode( boat_destination_node, "targetname" );
boat.target = destnode.targetname;
}
change_target_ent_on_vehicle_spawner( heli_targetname, boat_destination_node )
{
boat = GetEnt( heli_targetname, "targetname" );
destnode = GetEnt( boat_destination_node, "targetname" );
boat.target = destnode.targetname;
//this stuff should probably be in another function
boat.origin = destnode.origin;
boat.angles = destnode.angles;
boat.speed = destnode.speed;
}
enemy_chase_boat()
{
level.breadcrumb = [];
level.enemy_boat = self;
self endon( "death" );
self VehPhys_DisableCrashing();
self.veh_pathtype = "constrained";
self thread zodiac_monitor_player_trailing_time();
foreach ( rider in self.riders )
{
if ( IsDefined( rider.magic_bullet_shield ) && rider.magic_bullet_shield )
continue;
rider thread magic_bullet_shield();
}
// self.veh_pathtype = "follow";
while ( 1 )
{
wait .25;
enemy_chase_boat_breadcrumb();
}
}
boat_common()
{
if( ! is_default_start() )
maps\_friendlyfire::TurnOff();
boatrider = get_boat_rider( "boatrider0" );
level.price = boatrider;
thread price_ai_mods( boatrider );
thread test_m203();
kill_ai_in_volume = GetEntArray( "kill_ai_in_volume", "targetname" );
array_thread( kill_ai_in_volume, ::kill_ai_in_volume );
}
rpg_bridge_guy()
{
trigger = Spawn( "trigger_radius", self.origin + ( 0, 0, -2000 ), 0, 4500, 2000 );
trigger waittill( "trigger" );
level notify( "dialog_rpg_bridge_guy" );
}
rpg_bridge_guy_target()
{
target_ent = Spawn( "script_origin", level.players_boat.origin );
self ent_flag_init( "first_player_sighting" );
self disable_long_death();
self SetEntityTarget( target_ent );
self.favoriteenemy = target_ent;
self.ignoreall = true;
self.rpg_setup_time = GetTime() + RandomIntRange( 1000, 2000 );// "reaction time so they don't instantly shoot when you round a corner.
random_vec = flat_origin( randomvectorrange( -64, 64 ) );
firing_range = 3000;
while ( IsAlive( self ) )
{
velocity_offset = level.players_boat Vehicle_GetVelocity() * 1.4 ;
// target_ent.origin = level.players_boat.origin +( level.players_boat Vehicle_GetVelocity() * 1.89 );
forward_origin = level.players_boat.origin + velocity_offset;
forward_origin = set_z( forward_origin, level.players_boat.origin[ 2 ] + 24 );
// Line( forward_origin, level.players_boat.origin, (0,1,0) );
//when the player is headed towards something use the spline direction to influence the shot. otherwise fire away in the direct forward path.
if ( ! BulletTracePassed( level.player GetEye() + ( 0, 0, 16 ), forward_origin, false, self ) )
{
offset = Distance( ( 0, 0, 0 ), velocity_offset );
target_ent.origin = get_position_from_spline_unlimited( level.player.targ, level.player.progress + offset - level.POS_LOOKAHEAD_DIST, level.player.offset );
target_ent.origin = set_z( target_ent.origin, level.players_boat.origin[ 2 ] + 24 );
// Line( target_ent.origin, level.players_boat.origin, (0,0,1) );
target_ent.origin = ( target_ent.origin + forward_origin ) / 2;
}
else
{
target_ent.origin = forward_origin;
}
// Line( target_ent.origin, level.players_boat.origin, (1,0,0) );
self OrientMode( "face point", target_ent.origin ) ;
bullettraced_to_player = false;
if ( BulletTracePassed( self GetTagOrigin( "tag_flash" ), level.player GetEye(), false, self ) )
{
bullettraced_to_player = true;
if ( ! ent_flag( "first_player_sighting" ) )
ent_flag_set( "first_player_sighting" );
}
if ( ! ent_flag( "first_player_sighting" ) )
self.rpg_setup_time = GetTime() + RandomIntRange( 1000, 2000 );// "reaction time so they don't instantly shoot when you round a corner.
if ( GetTime() > self.rpg_setup_time )
if ( bullettraced_to_player )
if ( BulletTracePassed( self GetTagOrigin( "tag_flash" ), target_ent.origin + random_vec, false, self ) )
if ( Distance( self.origin, level.player.origin ) < firing_range )
if ( GetTime() > level.next_rpg_firetime )
break;
wait .05;
}
ammo = "rpg_straight_af_chase";
// if( cointoss() )
// ammo = "rpg";
if ( IsDefined( self ) && IsDefined( self GetTagOrigin( "tag_flash" ) ) )// Tried isalive . debugger is broken today = ( .
{
rpg_shot = MagicBullet( ammo, self GetTagOrigin( "tag_flash" ), target_ent.origin + random_vec );
rpg_shot thread kill_rpg_shot_behind_player();
}
level.next_rpg_firetime = GetTime() + RandomIntRange( 300, 500 );// stagger time between multiple guys
target_ent Delete();
}
kill_rpg_shot_behind_player()
{
level.players_boat endon( "death" );
self endon( "death" );
while ( in_front( level.player, self ) )
wait .05;
thread play_sound_in_space( "rocket_explode_water" );
self Delete();
}
set_price_autoswitch_after_caves()
{
flag_wait( "exit_caves" );
set_price_auto_switch_pose();
}
teleport_price_on_mount( node )
{
level endon( "end_teleport_price_on_mount" );
level.players_boat waittill( "vehicle_mount" );
level.price teleport_ai_here( node );
}
teleport_ai_here( eNode )
{
AssertEx( IsAI( self ), "Function teleport_ai can only be called on an AI entity" );
AssertEx( IsDefined( eNode ), "Need to pass a node entity to function teleport_ai" );
self ForceTeleport( eNode.origin, eNode.angles );
self SetGoalPos( self.origin );
}
dialog_boat_battlechatter()
{
dialog_direction = [];
dialog_direction = array_add( dialog_direction, "TF_pri_callout_targetclock_" );
dialog_helicopter_six = [];
dialog_helicopter_six = array_add( dialog_helicopter_six, "afchase_pri_evasive" );
dialog_helicopter_six = array_add( dialog_helicopter_six, "afchase_pri_shakeemoff" );
dialog_helicopter_six = array_add( dialog_helicopter_six, "afchase_pri_miniguns" );
dialog_helicopter_ahead = [];
dialog_helicopter_ahead = array_add( dialog_helicopter_ahead, "afchase_pri_dodgeheli" );
dialog_helicopter_ahead = array_add( dialog_helicopter_ahead, "afchase_pri_gunsspinup" );
dialog_helicopter_ahead = array_add( dialog_helicopter_ahead, "afchase_pri_steerclear" );
dialog_rpg_bridge_guy = [];
dialog_rpg_bridge_guy = array_add( dialog_rpg_bridge_guy, "afchase_pri_rpgsonbridge" );
dialog = [];
dialog[ "dialog_direction" ] = dialog_direction;
dialog[ "dialog_helicopter_six" ] = dialog_helicopter_six;
dialog[ "dialog_helicopter_ahead" ] = dialog_helicopter_ahead;
dialog[ "dialog_rpg_bridge_guy" ] = dialog_rpg_bridge_guy;
timeout[ "dialog_direction" ] = .5;
timeout[ "dialog_helicopter_six" ] = 1;
timeout[ "dialog_helicopter_ahead" ] = 1;
timeout[ "dialog_rpg_bridge_guy" ] = .7;
nagtime[ "dialog_direction" ] = 5500;
nagtime[ "dialog_helicopter_six" ] = 9300;
nagtime[ "dialog_helicopter_ahead" ] = 2000;
nagtime[ "dialog_rpg_bridge_guy" ] = 10000;
last_nagtime[ "dialog_direction" ] = GetTime();
last_nagtime[ "dialog_helicopter_six" ] = GetTime();
last_nagtime[ "dialog_helicopter_ahead" ] = GetTime();
last_nagtime[ "dialog_rpg_bridge_guy" ] = GetTime();
unused_dialog = dialog;
picked = undefined;
wait 1;// let enemy boat get defined..
/#
if ( GetDvarInt( "scr_zodiac_test" ) )
return;
#/
level endon( "price_stops_talking_about_helicopters" );
level.player endon( "death" );
self endon( "death" );
flag_wait( "exit_caves" );
while ( 1 )
{
type = level waittill_any_return( "dialog_direction", "dialog_helicopter_six", "dialog_helicopter_ahead", "dialog_rpg_bridge_guy" );
if ( flag( "price_anim_on_boat" ) )
continue;
if ( flag( "rapids_head_bobbing" ) )
continue;
picked = random( unused_dialog[ type ] );
if ( GetTime() - last_nagtime[ type ] < nagtime[ type ] )
continue;
last_nagtime[ type ] = GetTime();
if ( type == "dialog_direction" )
level.price thread generic_dialogue_queue( picked + level.dialog_dir, timeout[ type ] );
else
level.price thread generic_dialogue_queue( picked, timeout[ type ] );
unused_dialog[ type ] = array_remove( unused_dialog[ type ], picked );
if ( !unused_dialog[ type ].size )
unused_dialog[ type ] = dialog[ type ];
wait .05;
if ( flag( "player_in_sight_of_boarding" ) )
return;
}
}
dialog_boat_nag()
{
nagtime = 8000;
next_nag = GetTime() + nagtime;
dialog = [];
dialog = array_add( dialog, "afchase_pri_gettingaway" );
dialog = array_add( dialog, "afchase_pri_gogogo" );
dialog = array_add( dialog, "afchase_pri_cantlet" );
dialog = array_add( dialog, "afchase_pri_losinghim" );
dialog = array_add( dialog, "afchase_pri_drivingtheboat" );
dialog = array_add( dialog, "afchase_pri_fullpower" );
unused_dialog = dialog;
picked = undefined;
self endon( "death" );
level.price endon( "death" );
while ( 1 )
{
if ( bread_crumb_get_player_trailing_fraction() > .5 && next_nag < GetTime() && ! level.price ent_flag( "transitioning_positions" ) )
{
picked = random( unused_dialog );
// level.price thread radio_dialogue( picked );
side = level.price.a.boat_pose;
Assert( IsDefined( side ) && ( side == "left" || side == "right" ) );
doradio = false;
if ( level.price.a.lastShootTime > GetTime() - 2000 && ! player_full_heath() )
doradio = true;
if ( flag( "rapids_head_bobbing" ) )
{
wait .05;
continue;
}
if ( doradio )
level.price thread generic_dialogue_queue( picked, 1 );
else
level.price thread price_anim_single_on_boat( side + "_" + picked );
unused_dialog = array_remove( unused_dialog, picked );
next_nag = GetTime() + nagtime;
if ( !unused_dialog.size )
unused_dialog = dialog;
}
wait .05;
if ( flag( "stop_boat_dialogue" ) )
return;
}
}
dialog_cave()
{
level.player endon( "death" );
self waittill( "trigger" );
level.price generic_dialogue_queue( "afchase_pri_thrucave" );
}
dialog_start()
{
// thread add_dialogue_line( "Price", "They're just around the corner, come on." );
level.price thread generic_dialogue_queue( "afchase_pri_aroundcorner" );
wait 4;
// thread add_dialogue_line( "Price", "We need to get on that boat. " );
level.price thread generic_dialogue_queue( "afchase_pri_getonboat" );
wait 2;
}
dialog_boat_direction_nag()
{
nagtime = 4000;
next_nag = GetTime() + nagtime;
wrong_way_time = 2;
wrong_way_time_count = 0;
dialog = [];
dialog = array_add( dialog, "afchase_pri_wrongway" );
dialog = array_add( dialog, "afchase_pri_turntoobjective" );
dialog = array_add( dialog, "afchase_pri_wheregoing" );
unused_dialog = dialog;
picked = undefined;
wait 1;// let enemy boat get defined..
/#
if ( GetDvarInt( "scr_zodiac_test" ) )
return;
#/
self endon( "death" );
level.enemy_boat endon( "death" );
level.player endon( "death" );
while ( 1 )
{
if ( !in_front_by_velocity( level.players_boat, level.enemy_boat ) && next_nag < GetTime() )
wrong_way_time_count += .05;
else
wrong_way_time_count = 0;
if ( flag( "price_anim_on_boat" ) )
{
wait .05;
continue;
}
if ( wrong_way_time_count > wrong_way_time )
{
picked = random( unused_dialog );
level.price thread generic_dialogue_queue( picked );
unused_dialog = array_remove( unused_dialog, picked );
next_nag = GetTime() + nagtime;
if ( !unused_dialog.size )
unused_dialog = dialog;
}
wait .05;
if ( flag( "stop_boat_dialogue" ) )
return;
}
}
animate_price_into_boat()
{
level endon( "stop_animate_price_into_boat" );
waittillframeend;// let players boat get spawned and defined
pathnode = GetNode( self.target, "targetname" );
node = Spawn( "script_origin", pathnode.origin );
node.angles = pathnode.angles + ( 0, -90, 0 );
level.price ent_flag_init( "price_animated_into_boat" );
//make the scene stick to boat should player start to drive
node delayCall( 2, ::linkto, level.players_boat );// give it time to settle before linking
thread teleport_price_on_mount( node );
node anim_generic_reach( level.price, "price_into_boat" );
level notify( "end_teleport_price_on_mount" );
level.price LinkTo( node );
level.price delayThread( 1.5, ::ent_flag_set, "price_animated_into_boat" );// I timed this as a good cutoff point for when the player jumps in first.
level.players_boat delayCall( 1, ::JoltBody, level.price.origin, .15 );
level.players_boat delayThread( 1, ::play_sound_in_space, "water_boat_splash_small", level.players_boat.origin );
node anim_generic( level.price, "price_into_boat" );
level.price thread boatrider_think( level.players_boat );
}
search_the_scrash_site()
{
GetEnt( "damaged_pavelow", "targetname" ) Hide();
flag_wait( "end_heli_crashed" );
exploder( "heli_fire" );
damaged_heli = GetEnt( "damaged_pavelow", "targetname" );
wait .5;
damaged_heli Show();
trigger = Spawn( "trigger_radius", damaged_heli.origin + ( 0, 0, -100 ), 0, 670, 600 );
trigger waittill( "trigger" );
}
trigger_out_of_caves()
{
self waittill( "trigger" );
level.price thread generic_dialogue_queue( "afchase_pri_openareas" );
}
trigger_boat_mount()
{
self waittill( "trigger" );
if ( flag( "player_on_boat" ) )
return;
origin = level.players_boat GetTagOrigin( "tag_player" );
angles = level.players_boat GetTagAngles( "tag_player" );
level.player SwitchToWeapon( "uzi" );
level.player FreezeControls( true );
level.player PlayerLinkToBlend( level.players_boat, "tag_player", .35, .2, .1 );
wait .35;
level.player FreezeControls( false );
// level.price ent_flag_wait( "price_animated_into_boat" );
level.players_boat MakeUsable();
level.players_boat UseBy( level.player );
level.player.drivingVehicle = level.players_boat;
}
trigger_price_tells_player_go_right()
{
self.origin += ( 0, 0, -50 );
self waittill( "trigger" );
level.price thread generic_dialogue_queue( "afchase_pri_right" );
}
hint_test()
{
return player_steadies_boat();
}
trigger_end_caves()
{
self waittill( "trigger" );
flag_set( "exit_caves" );
wait 1.1;
thread maps\_utility::set_ambient( "af_chase_exit" );
wait 3;
SetSavedDvar( "sm_sunSampleSizeNear", "2" );
if ( IsDefined( level.price ) )
level.price DontCastShadows();
}
rope_splashers()
{
self endon( "death" );
wait .5;
org_z = self.origin[ 2 ];
while ( self.origin[ 2 ] == org_z )
wait .1;
self Kill();
//this might be cool if I could do client ragdoll..
//self waittill ( "death" );
//self endon ("death");
//
//ent = SpawnStruct();
//ent endon( "complete" );
//ent delayThread( 5, ::send_notify, "complete" );
// while( self.origin[2] > 48 )
// wait .05;
//
// PlayFX( getfx("body_falls_from_ropes_splash") , set_z( self.origin,48 ) );
// StartRagdoll();
}
trigger_set_max_zodiacs( value )
{
self waittill( "trigger" );
level.enemy_snowmobiles_max = value;
}
trigger_rapids()
{
level.player endon( "death" );
self waittill( "trigger" );
flag_set( "rapids_trigger" );
thread maps\_utility::set_ambient( "af_chase_rapids" );
level.player.nooffset = true;// makes enemy boats spawn exactly behind the player.
level.enemy_snowmobiles_max = 1;
flag_set( "rapids_head_bobbing" );
// price_anim_single_on_boat( "rapids_in", false );
level.price generic_dialogue_queue( "afchase_pri_rapidsahead" );
thread price_anim_loop_on_boat( "rapids_loop", "end_the_rapids_loop" );
end_price_crazy = GetEnt( "end_price_crazy", "targetname" );
end_price_crazy waittill( "trigger" );
flag_clear( "rapids_head_bobbing" );
level.players_boat notify( "end_the_rapids_loop" );
level.enemy_snowmobiles_max = 2;
wait 1;
set_price_auto_switch_pose();
// they get really bogged in so reduce them after a bit.
wait 9;
level.enemy_snowmobiles_max = 1;
}
trigger_on_river()
{
self waittill( "trigger" );
thread maps\_utility::set_ambient( "af_chase_river" );
flag_set( "on_river" );
}
trigger_open_area()
{
flag_wait( "exit_caves" );
level endon ( "stop_deadquote_for_gettingout_of_bounds" );
level.player endon( "death" );
nagtime = GetTime() + 30000;
while ( 1 )
{
SetDvar( "ui_deadquote", "" );
level thread maps\_quotes::setDeadQuote();
flag_clear( "player_in_open" );
self waittill( "trigger" );
while ( level.player IsTouching( self ) )
{
if ( GetTime() > nagtime )
{
nagtime = GetTime() + RandomFloatRange( 20000, 22000 );
//Price: Stay clear of open areas as much as possible!
level.price thread generic_dialogue_queue( "afchase_pri_openareas" );
}
flag_set( "player_in_open" );// done every frame to support overlap.
level notify( "new_quote_string" );
// Stay clear of open areas as much as possible!
SetDvar( "ui_deadquote", &"AF_CHASE_MISSION_FAILED_IN_THE_OPEN" );
wait .05;
}
}
}
/*
setDeadQuote()
{
level endon( "mine death" );
// kill any deadquotes already running
level notify( "new_quote_string" );
level endon( "new_quote_string" );
*/
sentry_technical_think()
{
wait .5;
turret = self.mgturret[ 0 ];
turret SetMode( "manual_ai" );
turret SetTargetEntity( level.player );
foreach ( rider in self.riders )
{
rider.favoriteenemy = level.player;
rider.maxsightdistsqrd = 20000 * 20000;
}
}
sunsample_after_caves()
{
flag_wait( "exit_caves" );
SetSavedDvar( "sm_sunSampleSizeNear", "2" );
}
boatsquish()
{
if ( IsDefined( level.noTankSquish ) )
{
AssertEx( level.noTankSquish, "level.noTankSquish must be true or undefined" );
return;
}
if ( IsDefined( level.levelHasVehicles ) && !level.levelHasVehicles )
return;
self add_damage_function( ::boatsquish_damage_check );
self remove_damage_function( maps\_spawner::tanksquish_damage_check );
}
boatsquish_damage_check( amt, who, force, b, c, d, e )
{
if ( !isdefined( self ) )
{
return;
}
if ( IsAlive( self ) )
return;
if ( !isalive( who ) )
return;
if ( !isdefined( who.vehicletype ) )
return;
if ( who maps\_vehicle::ishelicopter() )
return;
if ( abs( self.origin[ 2 ] - level.players_boat.origin[ 2 ] ) > 64 )
{
self Delete();// these guys are getting hit by the players tall boat collision.. just delete them so they don't fly over.
}
self thread boat_squish_ragdoll_or_bust();
if ( !isdefined( self ) )
{
return;
}
self remove_damage_function( ::boatsquish_damage_check );
// self PlaySound( "human_crunch" );
}
boat_squish_ragdoll_or_bust()
{
make_room_for_priority_squished_guy_corpse();
timer = GetTime() + 500;
while ( GetTime() < timer )
{
if ( !isdefined( self ) )
return;
if ( self IsRagdoll() )
return;
self StartRagdoll();
wait .05;
}
self Delete();
}
make_room_for_priority_squished_guy_corpse()
{
corpses = GetCorpseArray();
foreach ( corpse in corpses )
if ( Distance( corpse.origin, level.player GetEye() ) > 600 )
corpse Delete();
}
explode_barrels_in_radius_think()
{
assert( isdefined( self.radius ) );
shootable_stuff = GetEntArray( "explodable_barrel", "targetname" );
flat_org = flat_origin ( self.origin );
my_barrels = [];
foreach ( thing in shootable_stuff )
{
if( distance( flat_org, flat_origin( thing.origin) ) < self.radius )
my_barrels[ my_barrels.size ] = thing;
}
self waittill ( "trigger" );
for ( i = 0; i < 10; i++ )
{
foreach( barrel in my_barrels )
barrel notify( "damage", 50, level.player, (0,0,0), barrel.origin, "MOD_EXPLOSIVE" );
wait .05;
}
}
player_steadies_boat()
{
return level.player ButtonPressed( "BUTTON_B" ) || 1;
}
remove_global_spawn_funcs()
{
flag_wait( "water_cliff_jump_splash_sequence" );
remove_global_spawn_function( "axis", ::lower_accuracy_behind_player );
remove_global_spawn_function( "axis", ::set_fixed_node_after_seeing_player_spawn_func );
}