1 #using scripts\codescripts\struct;
3 #using scripts\shared\clientfield_shared;
4 #using scripts\shared\gameskill_shared;
5 #using scripts\shared\math_shared;
6 #using scripts\shared\statemachine_shared;
7 #using scripts\shared\system_shared;
8 #using scripts\shared\util_shared;
9 #using scripts\shared\turret_shared;
10 #using scripts\shared\flag_shared;
11 #using scripts\shared\damagefeedback_shared;
12 #using scripts\shared\laststand_shared;
13 #using scripts\shared\gameobjects_shared;
15 #insert scripts\shared\shared.gsh;
16 #insert scripts\shared\statemachine.gsh;
17 #insert scripts\shared\version.gsh;
18 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
20 #using scripts\shared\ai\systems\blackboard;
21 #using scripts\shared\ai\blackboard_vehicle;
22 #insert scripts\shared\ai\utility.gsh;
24 #using scripts\shared\vehicle_shared;
25 #using scripts\shared\vehicle_ai_shared;
26 #using scripts\shared\vehicle_death_shared;
28 #using scripts\mp\killstreaks\_killstreaks;
29 #using scripts\mp\killstreaks\_killstreak_bundles;
31 #define SCAN_HEIGHT_OFFSET 40
33 #define TURRET_STATE_SCAN_AT_ENEMY 0
34 #define TURRET_STATE_SCAN_FORWARD 1
35 #define TURRET_STATE_SCAN_RIGHT 2
36 #define TURRET_STATE_SCAN_FORWARD2 3
37 #define TURRET_STATE_SCAN_LEFT 4
38 #define NUM_TURRET_STATES 5
40 #define DEFAULT_WEAK_SPOT_DAMAGE_LIMIT 600
41 #define TROPHY_DISABLE_LIMIT 1 //Number of times that a player can destroy the trophy weakspot before it is permanently destroyed
43 #define SPIKE_HIT_LIMIT 5 //Used to limit the number of spikes that can hit a QT before trophy system gets re-enabled
45 #define MELEE_RADIUS 270
46 #define MELEE_INNER_RADIUS_DAMAGE 400
47 #define MELEE_OUTER_RADIUS_DAMAGE 400
49 #define ROCKET_LAUNCHER_MIN_DIST 350
51 #define WEAPON_JAVELIN "quadtank_main_turret_rocketpods_javelin"
52 #define WEAPON_STRAIGHT "quadtank_main_turret_rocketpods_straight"
53 #define JAVELIN_MIN_USE_DISTANCE 800 //an actor target must be at least this range from the QT for the QT to use the javelin attack
55 #define NEAR_GOAL_DIST 50
57 #define WEAKSPOT_BONE_NAME "tag_target_lower"
58 #precache( "string", WEAKSPOT_BONE_NAME );
60 #define QUADTANK_BUNDLE "quadtank"
66 #using_animtree( "generic" );
78 self useanimtree( #animtree );
80 self EnableAimAssist();
90 self.fovcosinebusy = 0;
91 self.maxsightdistsqrd =
SQR( 10000 );
93 self.weakpointobjective = 0;
94 self.combatactive =
true;
95 self.damage_during_trophy_down = 0;
96 self.spike_hits_during_trophy_down = 0;
97 self.trophy_disables = 0;
98 self.allow_movement =
true;
100 assert( isdefined(
self.scriptbundlesettings ) );
104 self.variant =
"cannon";
106 if( IsSubStr(
self.vehicleType,
"mlrs" ) )
108 self.variant =
"rocketpod";
111 self.goalRadius = 9999999;
112 self.goalHeight = 512;
113 self SetGoal(
self.origin,
false,
self.goalRadius,
self.goalHeight );
115 self SetSpeed(
self.settings.defaultMoveSpeed, 10, 10 );
116 self SetMinDesiredTurnYaw( 45 );
131 if( IsDefined( level.vehicle_initializer_cb ) )
133 [[level.vehicle_initializer_cb]]( self );
136 self.ignoreFireFly =
true;
137 self.ignoreDecoy =
true;
140 self.disableElectroDamage =
true;
141 self.disableBurnDamage =
true;
145 self HidePart(
"tag_defense_active" );
153 self.heatlh =
self.maxhealth;
169 if( isDefined( level.players) )
171 value = level.players.size;
179 scale_up = mapfloat( 1, 4, 1, 1.5, value );
180 scale_down = mapfloat( 1, 4, 1.0, 0.75, value );
185 self.difficulty_scale_up = scale_up;
186 self.difficulty_scale_down = scale_down;
218 self.combatactive =
false;
224 self.combatactive =
true;
229 self playsound(
"veh_quadtank_power_down" );
232 self ClearTargetEntity();
234 self ClearVehGoalPos();
242 angles =
self GetTagAngles(
"tag_flash" );
243 target_vec =
self.origin + AnglesToForward( ( 0, angles[1], 0 ) ) * 1000;
244 target_vec = target_vec + ( 0, 0, -500 );
245 self SetTargetOrigin( target_vec );
249 if( !isdefined(
self.
emped ) )
251 self DisableAimAssist();
262 self EnableAimAssist();
268 self playsound(
"veh_quadtank_power_up" );
271 angles =
self GetTagAngles(
"tag_flash" );
272 target_vec =
self.origin + AnglesToForward( ( 0, angles[1], 0 ) ) * 1000;
273 self.turretRotScale = 0.3;
275 driver =
self GetSeatOccupant( 0 );
276 if( !isdefined(driver) )
278 self SetTargetOrigin( target_vec );
282 self.turretRotScale = 1 *
self.difficulty_scale_up;
291 self endon(
"change_state" );
292 self endon(
"death" );
294 isTrophyDownPain = params.notify_param[0];
296 if( isTrophyDownPain ===
true )
299 asmState =
"trophy_disabled@stationary";
304 asmState =
"pain@stationary";
306 self ASMRequestSubstate( asmState );
307 playsoundatposition (
"prj_quad_impact",
self.origin);
310 self ClearVehGoalPos();
311 self ClearTurretTarget();
318 self ASMRequestSubstate(
"locomotion@movement" );
320 driver =
self GetSeatOccupant( 0 );
321 if( !isdefined( driver ) )
337 self endon(
"death" );
338 self endon(
"change_state" );
342 self ClearTargetEntity();
344 self ClearVehGoalPos();
355 self endon(
"death" );
356 self endon(
"change_state" );
360 self ClearTargetEntity();
362 self ClearVehGoalPos();
366 driver =
self GetSeatOccupant( 0 );
367 if( isdefined(driver) )
369 self.turretRotScale = 1;
370 self DisableAimAssist();
373 self ASMRequestSubstate(
"locomotion@movement" );
384 self SetGoal(
self.origin );
393 self endon(
"death" );
394 self endon(
"change_state" );
396 if ( isalive(
self ) )
405 if (
self.allow_movement )
414 switch (
self.variant )
428 self notify(
"end_attack_thread" );
429 self notify(
"end_movement_thread" );
430 self ClearTurretTarget();
431 self ClearLookAtEnt();
440 self endon(
"death" );
441 self endon(
"nodeath_thread" );
446 self HidePart(
"tag_lidar_null",
"",
true );
450 StreamerModelHint(
self.deathmodel, 6 );
452 if ( !isdefined(
self.custom_death_sequence ) )
454 playsoundatposition (
"prj_quad_impact",
self.origin);
455 self playsound(
"veh_quadtank_power_down" );
456 self playsound(
"veh_quadtank_sparks");
457 self ASMRequestSubstate(
"death@stationary" );
458 self waittill(
"explosion_c" );
462 self [[
self.custom_death_sequence]]();
465 if( isdefined( level.disable_thermal ) )
467 [[level.disable_thermal]]();
470 if( isdefined(
self.stun_fx ) )
472 self.stun_fx
delete();
475 BadPlace_Box(
"", 0,
self.origin, 90,
"neutral" );
490 self endon (
"death");
491 self endon(
"change_state" );
492 self endon(
"emped" );
494 if( isdefined(
self.
emped ) )
501 PlaySoundAtPosition(
"veh_quadtankemp_down",
self.origin );
502 self.turretRotScale = 0.2;
503 if( !isdefined(
self.stun_fx) )
505 self.stun_fx =
Spawn(
"script_model",
self.origin );
506 self.stun_fx SetModel(
"tag_origin" );
507 self.stun_fx LinkTo(
self,
"tag_turret", (0,0,0), (0,0,0) );
511 time = params.notify_param[0];
512 assert( isdefined( time ) );
521 self.stun_fx
delete();
522 self.emped = undefined;
523 self playsound (
"veh_boot_quadtank");
533 if(
self.trophy_down ===
true )
557 self endon(
"death" );
558 self notify(
"stop_disabletrophy" );
559 self endon(
"stop_disabletrophy" );
560 self notify(
"stop_enabletrophy" );
567 self.trophy_down =
true;
569 driver =
self GetSeatOccupant( 0 );
572 if( !isdefined( driver ) && isdefined( curr_state ) && ( curr_state !=
"off" ) && isdefined( next_state ) && ( next_state !=
"off" ) )
574 self notify(
"pain",
true );
578 self.targetOffset = ( 0, 0, 60 );
580 self HidePart(
"tag_defense_active" );
583 self.attackerAccuracy = 0.5;
584 self.damage_during_trophy_down = 0;
585 self.spike_hits_during_trophy_down = 0;
586 self.trophy_disables += 1;
591 driver =
self GetSeatOccupant( 0 );
595 if( IsDefined( level.vehicle_defense_cb ) )
597 [[level.vehicle_defense_cb]](
self, false );
602 self notify(
"trophy_system_destroyed");
603 level notify(
"trophy_system_destroyed",
self);
604 self playsound (
"wpn_trophy_disable");
605 PlayFXOnTag(
self.settings.trophydetonationfx,
self,
"tag_target_lower" );
606 self HidePart(
"tag_lidar_null",
"",
true );
610 self notify(
"trophy_system_disabled");
611 level notify(
"trophy_system_disabled",
self);
612 self playsound (
"wpn_trophy_disable");
617 if (
vehicle_ai::GetCooldownLeft(
"trophy_down" ) < 0.5 *
self.settings.trophySystemDownTime && (
self.damage_during_trophy_down >=
self.settings.trophysystemdisablethreshold ||
627 driver =
self GetSeatOccupant( 0 );
628 if( isdefined( driver ) )
641 self endon(
"death" );
642 self notify(
"stop_enabletrophy" );
643 self endon(
"stop_enabletrophy" );
646 time =
VAL(
self.settings.trophywarmup, 0.1 );
649 driver =
self GetSeatOccupant( 0 );
651 self.trophy_down =
false;
652 self.attackerAccuracy = 1;
653 self ShowPart(
"tag_defense_active" );
659 if( !isdefined( driver ) )
668 if ( Target_IsTarget(
self ) )
673 if( !isdefined( driver ) )
677 self.trophy_system_health =
self.settings.trophySystemHealth;
679 if( isDefined( level.players) && level.players.size > 0 )
681 num_players_trophy_health_modifier = 0.75;
683 if( level.players.size == 2)
685 num_players_trophy_health_modifier = 1;
687 if( level.players.size == 3)
689 num_players_trophy_health_modifier = 1.25;
691 if( level.players.size >= 4)
693 num_players_trophy_health_modifier = 1.5;
695 self.trophy_system_health =
self.trophy_system_health * num_players_trophy_health_modifier;
698 if( IsDefined( level.vehicle_defense_cb ) )
700 [[level.vehicle_defense_cb]](
self, true );
703 self notify(
"trophy_system_enabled");
704 level notify(
"trophy_system_enabled",
self);
711 self SetTurretTargetRelativeAngles( (10, -90, 0), 1 );
712 self SetTurretTargetRelativeAngles( (10, 90, 0), 2 );
713 self.turretRotScale = 1 *
self.difficulty_scale_up;
719 self endon(
"death" );
720 self endon(
"change_state" );
722 self.turretRotScale = 0.3;
724 while( scan_forever || ( !isdefined(
self.enemy ) || !(
self VehCanSee(
self.enemy )) ) )
733 switch(
self.turret_state )
737 if( isdefined(
self.enemy ) )
739 self SetLookAtEnt(
self.enemy );
741 self SetTargetOrigin( target_vec );
743 self ClearLookAtEnt();
748 target_vec =
self.origin + AnglesToForward( ( 0,
self.angles[1], 0 ) ) * 1000;
752 target_vec =
self.origin + AnglesToForward( ( 0,
self.angles[1] + 30, 0 ) ) * 1000;
756 target_vec =
self.origin + AnglesToForward( ( 0,
self.angles[1], 0 ) ) * 1000;
760 target_vec =
self.origin + AnglesToForward( ( 0,
self.angles[1] - 30, 0 ) ) * 1000;
765 self SetTargetOrigin( target_vec );
799 self endon(
"change_state" );
801 self playsound(
"veh_quadtank_cannon_charge");
803 self waittill(
"weapon_fired", proj );
807 if( isdefined( target ) && isdefined( proj ) )
809 vel = proj GetVelocity();
811 proj_speed = length( vel );
813 dist = Distance( proj.origin, target.origin ) + RandomFloatRange( 0, 40 );
815 time_to_enemy = dist / proj_speed;
817 proj ResetMissileDetonationTime( time_to_enemy );
823 self endon(
"death" );
824 self endon(
"change_state" );
826 cant_see_enemy_count = 0;
829 self SetOnTargetAngle( 10 );
831 self.getreadytofire = undefined;
836 if ( isdefined(
self.enemy ) &&
self VehCanSee(
self.enemy ) )
838 self SetTurretTargetEnt(
self.enemy );
839 self SetLookAtEnt(
self.enemy );
846 if ( isdefined(
self.enemy ) &&
self VehCanSee(
self.enemy ) )
848 self.turretRotScale = 1 *
self.difficulty_scale_up;
849 self SetTurretTargetEnt(
self.enemy );
850 self SetLookAtEnt(
self.enemy );
852 if( cant_see_enemy_count >= 2 )
858 self ClearVehGoalPos();
859 self notify(
"near_goal" );
861 cant_see_enemy_count = 0;
864 if ( isdefined(
self.enemy ) &&
self VehCanSee(
self.enemy ) )
868 v_my_forward = Anglestoforward(
self.angles );
869 v_to_enemy =
self.enemy.origin -
self.origin;
870 v_to_enemy = VectorNormalize( v_to_enemy );
871 dot = VectorDot( v_to_enemy, v_my_forward );
875 self ASMRequestSubstate(
"fire@stationary" );
876 self SetTurretTargetEnt(
self.enemy );
879 if( isDefined( level.players) && level.players.size < 3)
885 self.getreadytofire =
true;
889 self ClearVehGoalPos();
890 self notify(
"near_goal" );
892 self.turretRotScale = 0.7;
896 level notify(
"sndStopCountdown" );
902 self.turretRotScale = 1;
907 self.getreadytofire = undefined;
909 if ( isdefined(
self.enemy ) )
911 self SetTurretTargetEnt(
self.enemy );
912 self SetLookAtEnt(
self.enemy );
928 cant_see_enemy_count++;
932 if( cant_see_enemy_count > 40 )
936 else if( cant_see_enemy_count > 30 )
938 self ClearLookAtEnt();
939 self ClearTargetEntity();
943 if( isdefined(
self.enemy ) )
945 self SetTurretTargetEnt(
self.enemy );
946 self ClearLookAtEnt();
950 self ClearLookAtEnt();
961 self endon(
"death" );
962 self endon(
"end_attack_thread" );
970 if ( isdefined(
self.enemy ) )
972 self SetTurretTargetEnt(
self.enemy );
973 self SetLookAtEnt(
self.enemy );
980 useJavelin = !
self vehseenrecently(
self.enemy, 3 ) || ( RandomInt( 100 ) < 3 );
986 if( isDefined( level.players) && level.players.size < 3)
990 self ClearVehGoalPos();
991 self notify(
"near_goal" );
998 offset = ( 0, 0, -50 );
999 if ( isPlayer(
self.enemy ) )
1001 origin =
self.enemy.origin;
1002 eye =
self.enemy GetEye();
1003 offset = ( 0, 0, origin[2] - eye[2] - 5 );
1009 self playsound (
"veh_quadtank_mlrs_plant_start");
1022 for( i = 0; i < 4 && isdefined(
self.enemy ); i++ )
1026 if ( isPlayer(
self.enemy ) )
1032 self FireWeapon( 0,
self.enemy );
1059 if ( !isdefined(
self._player_shock_fx_quadtank_melee ) )
1061 self._player_shock_fx_quadtank_melee = 0;
1064 self._player_shock_fx_quadtank_melee = !
self._player_shock_fx_quadtank_melee;
1070 self endon(
"death" );
1071 self endon(
"change_state" );
1072 self endon(
"near_goal" );
1073 self endon(
"reached_end_node" );
1077 cantSeeEnemyCount = 0;
1081 if( isdefined(
self.current_pathto_pos ) )
1083 if( isdefined(
self.enemy ) )
1085 if( distance2dSquared(
self.enemy.origin,
self.current_pathto_pos ) < 250 * 250 )
1087 self.move_now =
true;
1088 self notify(
"near_goal" );
1091 if( !
self VehCanSee(
self.enemy ) )
1095 cantSeeEnemyCount++;
1096 if( cantSeeEnemyCount > 5 )
1098 self.move_now =
true;
1099 self notify(
"near_goal" );
1105 if( distance2dSquared(
self.current_pathto_pos,
self.goalpos ) >
self.goalradius *
self.goalradius )
1109 self.move_now =
true;
1110 self notify(
"near_goal" );
1120 self endon(
"death" );
1121 self endon(
"change_state" );
1122 self notify(
"end_movement_thread" );
1123 self endon(
"end_movement_thread" );
1125 if(
self.goalforced )
1127 return self.goalpos;
1130 minSearchRadius = 0;
1131 maxSearchRadius = 2000;
1134 outerSpacing = innerSpacing * 2;
1135 maxGoalTimeout = 15;
1137 self ASMRequestSubstate(
"locomotion@movement" );
1144 self SetSpeed(
self.settings.defaultMoveSpeed, 5, 5 );
1146 PixBeginEvent(
"_quadtank::Movement_Thread_Wander" );
1147 queryResult = PositionQuery_Source_Navigation(
self.origin, minSearchRadius, maxSearchRadius, halfHeight, innerSpacing,
self, outerSpacing );
1151 PositionQuery_Filter_DistanceToGoal( queryResult,
self );
1155 foreach ( point
in queryResult.data )
1157 if( distance2dSquared(
self.origin, point.origin ) < 170 * 170 )
1159 ADD_POINT_SCORE( point,
"tooCloseToSelf", -100 );
1167 goalPos =
self.origin;
1168 count = queryResult.data.size;
1172 for ( i = 0; i < count && !foundpath; i++ )
1174 goalPos = queryResult.data[i].origin;
1175 foundpath =
self SetVehGoalPos( goalPos,
false,
true );
1181 self.current_pathto_pos = goalpos;
1183 self ASMRequestSubstate(
"locomotion@movement" );
1186 self CancelAIMove();
1187 self ClearVehGoalPos();
1189 if( isdefined(
self.move_now ) )
1191 self.move_now = undefined;
1202 self.current_pathto_pos = undefined;
1204 goalYaw =
self GetGoalYaw();
1213 self endon(
"death" );
1214 self endon(
"change_state" );
1219 self ASMRequestSubstate(
"locomotion@movement" );
1224 while (
self.allow_movement )
1226 if (
self.getreadytofire !==
true )
1230 if ( isdefined( goalpos ) && ( Distance2DSquared( goalpos,
self.origin ) >
SQR(
NEAR_GOAL_DIST ) || Abs( goalpos[2] -
self.origin[2] ) >
self.height ) )
1232 self SetSpeed(
self.settings.defaultMoveSpeed, 5, 5 );
1233 self SetVehGoalPos( goalpos,
false,
true );
1234 self.current_pathto_pos = goalpos;
1236 self ASMRequestSubstate(
"locomotion@movement" );
1241 self notify(
"goal" );
1244 self CancelAIMove();
1245 self ClearVehGoalPos();
1247 if ( isdefined(
self.move_now ) )
1249 self.move_now = undefined;
1260 while ( isdefined(
self.getreadytofire ) )
1271 self endon(
"death" );
1272 self endon(
"exit_vehicle" );
1274 weapon =
self SeatGetWeapon( 1 );
1275 fireTime = weapon.fireTime;
1279 self SetGunnerTargetVec(
self GetGunnerTargetVec( 0 ), 1 );
1280 if(
self IsGunnerFiring( 0 ) )
1282 self FireWeapon( 2 );
1290 if( !isAlive( enemy ) || distanceSquared( enemy.origin,
self.origin ) >
SQR(
MELEE_RADIUS ) )
1305 self notify (
"play_meleefx" );
1307 if ( shouldDoDamage )
1310 players = GetPlayers();
1311 foreach( player
in players )
1313 player._takedamage_old = player.takedamage;
1314 player.takedamage =
false;
1319 foreach( player
in players )
1321 player.takedamage = player._takedamage_old;
1322 player._takedamage_old = undefined;
1326 if ( isdefined( enemy ) && isPlayer( enemy ) )
1328 direction =
FLAT_ORIGIN( ( enemy.origin -
self.origin ) );
1329 if ( Abs( direction[0] ) < 0.01 && Abs( direction[1] ) < 0.01 )
1331 direction = ( RandomFloatRange( 1, 2 ), RandomFloatRange( 1, 2 ), 0 );
1333 direction = VectorNormalize( direction );
1335 enemy SetVelocity( enemy GetVelocity() + direction * strength );
1337 enemy DoDamage( 15,
self.origin,
self );
1340 self playsound(
"veh_quadtank_emp" );
1347 self endon(
"death" );
1349 assert( isdefined(
self.team ) );
1353 enemies =
self GetEnemies();
1357 foreach( enemy
in enemies )
1359 if( enemy IsNoTarget() )
1364 meleed = meleed ||
self do_melee( !meleed, enemy );
1382 self HidePart(
"tag_gunner_barrel1" );
1383 self HidePart(
"tag_gunner_turret1" );
1385 else if( index == 2 )
1387 self HidePart(
"tag_gunner_barrel2" );
1388 self HidePart(
"tag_gunner_turret2" );
1395 self endon(
"death" );
1399 self waittill(
"enter_vehicle", player );
1401 if ( isdefined( player ) && isPlayer( player ) )
1408 function QuadtankCallback_VehicleDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal )
1410 if ( isdefined( eAttacker ) && ( eAttacker ==
self || isplayer( eAttacker ) && eAttacker.usingvehicle && eAttacker.viewlockedentity ===
self ) )
1415 if ( sMeansOfDeath ===
"MOD_MELEE" || sMeansOfDeath ===
"MOD_MELEE_WEAPON_BUTT" || sMeansOfDeath ===
"MOD_MELEE_ASSASSINATE" || sMeansOfDeath ===
"MOD_ELECTROCUTED" || sMeansOfDeath ===
"MOD_CRUSH" || weapon.isEmp )
1420 iDamage =
self killstreaks::OnDamagePerWeapon(
QUADTANK_BUNDLE, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon,
self.maxhealth, undefined,
self.maxhealth * 0.4, undefined, 0, undefined,
true, 1.0 );
1423 driver =
self GetSeatOccupant( 0 );
1424 if ( isPlayer( driver ) )
1444 if( isdefined(
self.missile_repulsor ) )
1446 missile_deleteattractor(
self.missile_repulsor );
1447 self.missile_repulsor = undefined;
1449 self notify(
"end_repulsor_fx" );
1454 self notify(
"end_repulsor_fx" );
1455 self endon(
"end_repulsor_fx" );
1456 self endon(
"death" );
1457 self endon(
"change_state" );
1464 PlayFxOnTag(
self.settings.trophyrepulsefx,
self,
"tag_body" );
1470 self PlaySound(
"wpn_quadtank_shield_impact" );
1477 if( !isdefined(
self.missile_repulsor ) )
1479 self.missile_repulsor = missile_createrepulsorent(
self, 40000,
self.settings.trophysystemrange,
true );
1486 self notify(
"turn_off_laser_thread" );
1487 self endon(
"turn_off_laser_thread" );
1488 self endon(
"death" );
1502 v_pivot_pos =
self GetTagOrigin( s_turret.str_tag_pivot );
1503 v_angles_to_target = VectorToAngles( v_target - v_pivot_pos );
1505 n_rest_angle_pitch = s_turret.n_rest_angle_pitch +
self.angles[0];
1506 n_rest_angle_yaw = s_turret.n_rest_angle_yaw +
self.angles[1];
1508 n_ang_pitch = AngleClamp180( v_angles_to_target[0] - n_rest_angle_pitch );
1509 n_ang_yaw = AngleClamp180( v_angles_to_target[1] - n_rest_angle_yaw );
1511 b_out_of_range =
false;
1513 if ( n_ang_pitch > 0 )
1515 if ( n_ang_pitch > s_turret.bottomarc )
1517 b_out_of_range =
true;
1522 if ( Abs( n_ang_pitch ) > s_turret.toparc )
1524 b_out_of_range =
true;
1528 if ( n_ang_yaw > 0 )
1530 if ( n_ang_yaw > s_turret.leftarc )
1532 b_out_of_range =
true;
1537 if ( Abs( n_ang_yaw ) > s_turret.rightarc )
1539 b_out_of_range =
true;
1543 if( b_out_of_range )
1548 return ( Abs( n_ang_yaw ) / 90 * 800 );
1553 takeEasyOnOneTarget = MapFloat( 0, 4, 800, 0, level.gameskill );
1555 if ( n_index === 1 )
1559 else if ( n_index === 2 )
1564 e_best_target = undefined;
1565 f_best_score = 100000;
1569 foreach(
e_target in a_potential_targets )
1571 f_score = Distance(
self.origin,
e_target.origin );
1575 if( b_current_target )
1585 if (
e_target === other_turret_target )
1587 f_score += ( 100 + takeEasyOnOneTarget );
1595 if ( isAlive(
self.lockon_owner ) &&
e_target ===
self.lockon_owner )
1604 if( view_score != 0.0 )
1606 f_score += view_score;
1610 if ( b_current_target && !b_trace_passed && !isdefined( s_turret.n_time_lose_sight ) )
1612 s_turret.n_time_lose_sight = GetTime();
1615 if( b_trace_passed )
1620 else if ( b_current_target )
1622 s_turret.b_target_out_of_range =
true;
1626 if( f_score < f_best_score )
1628 f_best_score = f_score;
1633 return e_best_target;
1638 if(
self.displayweakpoint !== state )
1640 self.displayweakpoint = state;
1642 if( !
self.displayweakpoint &&
self.weakpointobjective === 1 )
1644 self.weakpointobjective = 0;
1647 player = level.players[0];
1648 if(
self.displayweakpoint &&
self.combatactive &&
self.weakpointobjective !== 1 && ( !isdefined( player ) || player.team !==
self.team ) )
1650 self.weakpointobjective = 1;
1657 self endon(
"death" );
1658 self endon(
"exit_vehicle" );
1662 note =
self util::waittill_any_return(
"footstep_front_left",
"footstep_front_right",
"footstep_rear_left",
"footstep_rear_right" );
1666 case "footstep_front_left":
1668 bone =
"tag_foot_fx_left_front";
1671 case "footstep_front_right":
1673 bone =
"tag_foot_fx_right_front";
1676 case "footstep_rear_left":
1678 bone =
"tag_foot_fx_left_back";
1681 case "footstep_rear_right":
1683 bone =
"tag_foot_fx_right_back";
1688 position =
self GetTagOrigin( bone ) + (0,0,15);
1690 self RadiusDamage( position, 60, 50, 50,
self,
"MOD_CRUSH" );
1696 self endon(
"entityshutdown" );
1697 self endon (
"death");
1699 self waittill(
"weapon_fired", projectile );
1702 alias =
"prj_quadtank_javelin_incoming";
1706 if(!isdefined( projectile ) )
1709 while(isdefined(projectile) && isdefined( projectile.origin ))
1711 if ( isdefined(
self.enemy ) && isdefined(
self.enemy.origin ))
1713 projectileDistance = DistanceSquared( projectile.origin,
self.enemy.origin);
1715 if( projectileDistance <= distance * distance )
1717 projectile playsound (alias);
1728 self endon(
"entityshutdown" );
1729 self endon (
"death");
1731 self waittill(
"weapon_fired", projectile );
1734 alais =
"wpn_quadtank_railgun_fire_rocket_flux";
1735 players = level.players;
1737 while(isdefined(projectile) && isdefined( projectile.origin ))
1739 if ( isdefined( players[0] ) && isdefined( players[0].origin ))
1741 projectileDistance = DistanceSquared( projectile.origin, players[0].origin);
1743 if( projectileDistance <= distance * distance )
1745 projectile playsound (alais);