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;
14 #using scripts\cp\_objectives;
16 #insert scripts\shared\shared.gsh;
17 #insert scripts\shared\statemachine.gsh;
18 #insert scripts\shared\version.gsh;
19 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
21 #using scripts\shared\ai\systems\blackboard;
22 #using scripts\shared\ai\blackboard_vehicle;
23 #insert scripts\shared\ai\utility.gsh;
25 #using scripts\cp\gametypes\_globallogic_ui;
27 #using scripts\shared\vehicle_shared;
28 #using scripts\shared\vehicle_ai_shared;
29 #using scripts\shared\vehicle_death_shared;
31 #using scripts\cp\_oed;
33 #define SCAN_HEIGHT_OFFSET 40
35 #define TURRET_STATE_SCAN_AT_ENEMY 0
36 #define TURRET_STATE_SCAN_FORWARD 1
37 #define TURRET_STATE_SCAN_RIGHT 2
38 #define TURRET_STATE_SCAN_FORWARD2 3
39 #define TURRET_STATE_SCAN_LEFT 4
40 #define NUM_TURRET_STATES 5
42 #define DEFAULT_WEAK_SPOT_DAMAGE_LIMIT 600
43 #define TROPHY_DISABLE_LIMIT 4 //Number of times that a player can destroy the trophy weakspot before it is permanently destroyed
45 #define SPIKE_HIT_LIMIT 5 //Used to limit the number of spikes that can hit a QT before trophy system gets re-enabled
47 #define MELEE_RADIUS 270
48 #define MELEE_INNER_RADIUS_DAMAGE 400
49 #define MELEE_OUTER_RADIUS_DAMAGE 400
51 #define ROCKET_LAUNCHER_MIN_DIST 350
53 #define WEAPON_JAVELIN "quadtank_main_turret_rocketpods_javelin"
54 #define WEAPON_STRAIGHT "quadtank_main_turret_rocketpods_straight"
55 #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
57 #define NEAR_GOAL_DIST 50
59 #precache( "objective", "cp_quadtank_weakpoint" );
60 #precache( "objective", "cp_quadtank_trophy_disabled" );
61 #precache( "objective", "cp_quadtank_rocket_icon" );
63 #define WEAKSPOT_BONE_NAME "tag_target_lower"
64 #precache( "string", WEAKSPOT_BONE_NAME );
70 #using_animtree( "generic" );
82 self useanimtree( #animtree );
84 self EnableAimAssist();
94 self.fovcosinebusy = 0;
95 self.maxsightdistsqrd =
SQR( 10000 );
97 self.weakpointobjective = 0;
98 self.combatactive =
true;
99 self.damage_during_trophy_down = 0;
100 self.spike_hits_during_trophy_down = 0;
101 self.trophy_disables = 0;
102 self.allow_movement =
true;
104 assert( isdefined(
self.scriptbundlesettings ) );
110 objectives::hide_for_target(
"cp_quadtank_rocket_icon",
self );
113 self.variant =
"cannon";
115 if( IsSubStr(
self.vehicleType,
"mlrs" ) )
117 self.variant =
"rocketpod";
120 self.goalRadius = 9999999;
121 self.goalHeight = 512;
122 self SetGoal(
self.origin,
false,
self.goalRadius,
self.goalHeight );
124 self SetSpeed(
self.settings.defaultMoveSpeed, 10, 10 );
125 self SetMinDesiredTurnYaw( 45 );
140 if( IsDefined( level.vehicle_initializer_cb ) )
142 [[level.vehicle_initializer_cb]]( self );
145 self.ignoreFireFly =
true;
146 self.ignoreDecoy =
true;
149 self.disableElectroDamage =
true;
150 self.disableBurnDamage =
true;
154 self HidePart(
"tag_defense_active" );
170 if( isDefined( level.players) )
172 value = level.players.size;
180 scale_up = mapfloat( 1, 4, 1, 1.5, value );
181 scale_down = mapfloat( 1, 4, 1.0, 0.75, value );
186 self.difficulty_scale_up = scale_up;
187 self.difficulty_scale_down = scale_down;
219 self.combatactive =
false;
225 self.combatactive =
true;
230 self playsound(
"veh_quadtank_power_down" );
233 self ClearTargetEntity();
235 self ClearVehGoalPos();
243 angles =
self GetTagAngles(
"tag_flash" );
244 target_vec =
self.origin + AnglesToForward( ( 0, angles[1], 0 ) ) * 1000;
245 target_vec = target_vec + ( 0, 0, -500 );
246 self SetTargetOrigin( target_vec );
250 if( !isdefined(
self.
emped ) )
252 self DisableAimAssist();
263 self EnableAimAssist();
269 self playsound(
"veh_quadtank_power_up" );
272 angles =
self GetTagAngles(
"tag_flash" );
273 target_vec =
self.origin + AnglesToForward( ( 0, angles[1], 0 ) ) * 1000;
274 self.turretRotScale = 0.3;
276 driver =
self GetSeatOccupant( 0 );
277 if( !isdefined(driver) )
279 self SetTargetOrigin( target_vec );
283 self.turretRotScale = 1 *
self.difficulty_scale_up;
292 self endon(
"change_state" );
293 self endon(
"death" );
295 isTrophyDownPain = params.notify_param[0];
297 if( isTrophyDownPain ===
true )
300 asmState =
"trophy_disabled@stationary";
305 asmState =
"pain@stationary";
307 self ASMRequestSubstate( asmState );
308 playsoundatposition (
"prj_quad_impact",
self.origin);
311 self ClearVehGoalPos();
312 self ClearTurretTarget();
319 self ASMRequestSubstate(
"locomotion@movement" );
321 driver =
self GetSeatOccupant( 0 );
322 if( !isdefined( driver ) )
338 self endon(
"death" );
339 self endon(
"change_state" );
343 self ClearTargetEntity();
345 self ClearVehGoalPos();
356 self endon(
"death" );
357 self endon(
"change_state" );
361 self ClearTargetEntity();
363 self ClearVehGoalPos();
366 objectives::hide_for_target(
"cp_quadtank_rocket_icon",
self );
368 driver =
self GetSeatOccupant( 0 );
369 if( isdefined(driver) )
371 self.turretRotScale = 1;
372 self DisableAimAssist();
375 self ASMRequestSubstate(
"locomotion@movement" );
386 self SetGoal(
self.origin );
395 self endon(
"death" );
396 self endon(
"change_state" );
398 if ( isalive(
self ) )
407 if (
self.allow_movement )
416 switch (
self.variant )
430 self notify(
"end_attack_thread" );
431 self notify(
"end_movement_thread" );
432 self ClearTurretTarget();
433 self ClearLookAtEnt();
442 self endon(
"death" );
443 self endon(
"nodeath_thread" );
447 objectives::hide_for_target(
"cp_quadtank_rocket_icon",
self );
449 self HidePart(
"tag_lidar_null",
"",
true );
453 StreamerModelHint(
self.deathmodel, 6 );
455 if ( !isdefined(
self.custom_death_sequence ) )
457 playsoundatposition (
"prj_quad_impact",
self.origin);
458 self playsound(
"veh_quadtank_power_down" );
459 self playsound(
"veh_quadtank_sparks");
460 self ASMRequestSubstate(
"death@stationary" );
461 self waittill(
"explosion_c" );
465 self [[
self.custom_death_sequence]]();
468 if( isdefined( level.disable_thermal ) )
470 [[level.disable_thermal]]();
473 if( isdefined(
self.stun_fx ) )
475 self.stun_fx
delete();
478 BadPlace_Box(
"", 0,
self.origin, 90,
"neutral" );
493 self endon (
"death");
494 self endon(
"change_state" );
495 self endon(
"emped" );
497 if( isdefined(
self.
emped ) )
504 PlaySoundAtPosition(
"veh_quadtankemp_down",
self.origin );
505 self.turretRotScale = 0.2;
506 if( !isdefined(
self.stun_fx) )
508 self.stun_fx =
Spawn(
"script_model",
self.origin );
509 self.stun_fx SetModel(
"tag_origin" );
510 self.stun_fx LinkTo(
self,
"tag_turret", (0,0,0), (0,0,0) );
514 time = params.notify_param[0];
515 assert( isdefined( time ) );
524 self.stun_fx
delete();
525 self.emped = undefined;
526 self playsound (
"veh_boot_quadtank");
536 if(
self.trophy_down ===
true )
565 self endon(
"death" );
566 self notify(
"stop_disabletrophy" );
567 self endon(
"stop_disabletrophy" );
568 self notify(
"stop_enabletrophy" );
575 self.trophy_down =
true;
577 driver =
self GetSeatOccupant( 0 );
580 self notify(
"pain",
true );
583 Target_Set(
self , (0,0,60) );
585 self HidePart(
"tag_defense_active" );
588 self.attackerAccuracy = 0.5;
589 self.damage_during_trophy_down = 0;
590 self.spike_hits_during_trophy_down = 0;
591 self.trophy_disables += 1;
596 driver =
self GetSeatOccupant( 0 );
599 objectives::show_for_target(
"cp_quadtank_rocket_icon",
self );
603 objectives::hide_for_target(
"cp_quadtank_rocket_icon",
self );
608 if( IsDefined( level.vehicle_defense_cb ) )
610 [[level.vehicle_defense_cb]](
self, false );
615 self notify(
"trophy_system_destroyed");
616 level notify(
"trophy_system_destroyed",
self);
617 self playsound (
"wpn_trophy_disable");
618 PlayFXOnTag(
self.settings.trophydetonationfx,
self,
"tag_target_lower" );
619 self HidePart(
"tag_lidar_null",
"",
true );
623 self notify(
"trophy_system_disabled");
624 level notify(
"trophy_system_disabled",
self);
625 self playsound (
"wpn_trophy_disable");
630 if (
vehicle_ai::GetCooldownLeft(
"trophy_down" ) < 0.5 *
self.settings.trophySystemDownTime && (
self.damage_during_trophy_down >=
self.settings.trophysystemdisablethreshold ||
640 driver =
self GetSeatOccupant( 0 );
641 if( isdefined( driver ) )
654 self endon(
"death" );
655 self notify(
"stop_enabletrophy" );
656 self endon(
"stop_enabletrophy" );
659 time =
VAL(
self.settings.trophywarmup, 0.1 );
662 driver =
self GetSeatOccupant( 0 );
664 self.trophy_down =
false;
665 self.attackerAccuracy = 1;
666 self ShowPart(
"tag_defense_active" );
668 objectives::hide_for_target(
"cp_quadtank_rocket_icon",
self );
673 if( !isdefined( driver ) )
682 if ( Target_IsTarget(
self) )
684 Target_remove(
self );
687 if( !isdefined( driver ) )
691 self.trophy_system_health =
self.settings.trophySystemHealth;
693 if( isDefined( level.players) && level.players.size > 0 )
695 num_players_trophy_health_modifier = 0.75;
697 if( level.players.size == 2)
699 num_players_trophy_health_modifier = 1;
701 if( level.players.size == 3)
703 num_players_trophy_health_modifier = 1.25;
705 if( level.players.size >= 4)
707 num_players_trophy_health_modifier = 1.5;
709 self.trophy_system_health =
self.trophy_system_health * num_players_trophy_health_modifier;
712 if( IsDefined( level.vehicle_defense_cb ) )
714 [[level.vehicle_defense_cb]](
self, true );
717 self notify(
"trophy_system_enabled");
718 level notify(
"trophy_system_enabled",
self);
725 self SetTurretTargetRelativeAngles( (10, -90, 0), 1 );
726 self SetTurretTargetRelativeAngles( (10, 90, 0), 2 );
727 self.turretRotScale = 1 *
self.difficulty_scale_up;
733 self endon(
"death" );
734 self endon(
"change_state" );
736 self.turretRotScale = 0.3;
738 while( scan_forever || ( !isdefined(
self.enemy ) || !(
self VehCanSee(
self.enemy )) ) )
747 switch(
self.turret_state )
751 if( isdefined(
self.enemy ) )
753 self SetLookAtEnt(
self.enemy );
755 self SetTargetOrigin( target_vec );
757 self ClearLookAtEnt();
762 target_vec =
self.origin + AnglesToForward( ( 0,
self.angles[1], 0 ) ) * 1000;
766 target_vec =
self.origin + AnglesToForward( ( 0,
self.angles[1] + 30, 0 ) ) * 1000;
770 target_vec =
self.origin + AnglesToForward( ( 0,
self.angles[1], 0 ) ) * 1000;
774 target_vec =
self.origin + AnglesToForward( ( 0,
self.angles[1] - 30, 0 ) ) * 1000;
779 self SetTargetOrigin( target_vec );
813 self endon(
"change_state" );
815 self playsound(
"veh_quadtank_cannon_charge");
817 self waittill(
"weapon_fired", proj );
821 if( isdefined( target ) && isdefined( proj ) )
823 vel = proj GetVelocity();
825 proj_speed = length( vel );
827 dist = Distance( proj.origin, target.origin ) + RandomFloatRange( 0, 40 );
829 time_to_enemy = dist / proj_speed;
831 proj ResetMissileDetonationTime( time_to_enemy );
837 self endon(
"death" );
838 self endon(
"change_state" );
840 cant_see_enemy_count = 0;
843 self SetOnTargetAngle( 10 );
845 self.getreadytofire = undefined;
851 if ( isdefined(
self.enemy ) &&
self VehCanSee(
self.enemy ) )
853 self SetTurretTargetEnt(
self.enemy );
854 self SetLookAtEnt(
self.enemy );
861 if ( isdefined(
self.enemy ) &&
self VehCanSee(
self.enemy ) )
863 self.turretRotScale = 1 *
self.difficulty_scale_up;
864 self SetTurretTargetEnt(
self.enemy );
865 self SetLookAtEnt(
self.enemy );
867 if( cant_see_enemy_count >= 2 )
873 self ClearVehGoalPos();
874 self notify(
"near_goal" );
876 cant_see_enemy_count = 0;
879 if ( isdefined(
self.enemy ) &&
self VehCanSee(
self.enemy ) )
883 v_my_forward = Anglestoforward(
self.angles );
884 v_to_enemy =
self.enemy.origin -
self.origin;
885 v_to_enemy = VectorNormalize( v_to_enemy );
886 dot = VectorDot( v_to_enemy, v_my_forward );
890 self ASMRequestSubstate(
"fire@stationary" );
891 self SetTurretTargetEnt(
self.enemy );
894 if( isDefined( level.players) && level.players.size < 3)
900 self.getreadytofire =
true;
904 self ClearVehGoalPos();
905 self notify(
"near_goal" );
907 self.turretRotScale = 0.7;
911 level notify(
"sndStopCountdown" );
917 self.turretRotScale = 1;
922 self.getreadytofire = undefined;
924 if ( isdefined(
self.enemy ) )
926 self SetTurretTargetEnt(
self.enemy );
927 self SetLookAtEnt(
self.enemy );
943 cant_see_enemy_count++;
947 if( cant_see_enemy_count > 40 )
951 else if( cant_see_enemy_count > 30 )
953 self ClearLookAtEnt();
954 self ClearTargetEntity();
958 if( isdefined(
self.enemy ) )
960 self SetTurretTargetEnt(
self.enemy );
961 self ClearLookAtEnt();
965 self ClearLookAtEnt();
976 self endon(
"death" );
977 self endon(
"end_attack_thread" );
985 if ( isdefined(
self.enemy ) )
987 self SetTurretTargetEnt(
self.enemy );
988 self SetLookAtEnt(
self.enemy );
995 useJavelin = !
self vehseenrecently(
self.enemy, 3 ) || ( RandomInt( 100 ) < 3 );
1001 if( isDefined( level.players) && level.players.size < 3)
1005 self ClearVehGoalPos();
1006 self notify(
"near_goal" );
1013 offset = ( 0, 0, -50 );
1014 if ( isPlayer(
self.enemy ) )
1016 origin =
self.enemy.origin;
1017 eye =
self.enemy GetEye();
1018 offset = ( 0, 0, origin[2] - eye[2] - 5 );
1024 self playsound (
"veh_quadtank_mlrs_plant_start");
1037 for( i = 0; i < 4 && isdefined(
self.enemy ); i++ )
1041 if ( isPlayer(
self.enemy ) )
1047 self FireWeapon( 0,
self.enemy );
1074 if ( !isdefined(
self._player_shock_fx_quadtank_melee ) )
1076 self._player_shock_fx_quadtank_melee = 0;
1079 self._player_shock_fx_quadtank_melee = !
self._player_shock_fx_quadtank_melee;
1085 self endon(
"death" );
1086 self endon(
"change_state" );
1087 self endon(
"near_goal" );
1088 self endon(
"reached_end_node" );
1092 cantSeeEnemyCount = 0;
1096 if( isdefined(
self.current_pathto_pos ) )
1098 if( isdefined(
self.enemy ) )
1100 if( distance2dSquared(
self.enemy.origin,
self.current_pathto_pos ) < 250 * 250 )
1102 self.move_now =
true;
1103 self notify(
"near_goal" );
1106 if( !
self VehCanSee(
self.enemy ) )
1110 cantSeeEnemyCount++;
1111 if( cantSeeEnemyCount > 5 )
1113 self.move_now =
true;
1114 self notify(
"near_goal" );
1120 if( distance2dSquared(
self.current_pathto_pos,
self.goalpos ) >
self.goalradius *
self.goalradius )
1124 self.move_now =
true;
1125 self notify(
"near_goal" );
1135 self endon(
"death" );
1136 self endon(
"change_state" );
1137 self notify(
"end_movement_thread" );
1138 self endon(
"end_movement_thread" );
1140 if(
self.goalforced )
1142 return self.goalpos;
1145 minSearchRadius = 0;
1146 maxSearchRadius = 2000;
1149 outerSpacing = innerSpacing * 2;
1150 maxGoalTimeout = 15;
1152 self ASMRequestSubstate(
"locomotion@movement" );
1159 self SetSpeed(
self.settings.defaultMoveSpeed, 5, 5 );
1161 PixBeginEvent(
"_quadtank::Movement_Thread_Wander" );
1162 queryResult = PositionQuery_Source_Navigation(
self.origin, minSearchRadius, maxSearchRadius, halfHeight, innerSpacing,
self, outerSpacing );
1166 PositionQuery_Filter_DistanceToGoal( queryResult,
self );
1170 foreach ( point
in queryResult.data )
1172 if( distance2dSquared(
self.origin, point.origin ) < 170 * 170 )
1174 ADD_POINT_SCORE( point,
"tooCloseToSelf", -100 );
1182 goalPos =
self.origin;
1183 count = queryResult.data.size;
1187 for ( i = 0; i < count && !foundpath; i++ )
1189 goalPos = queryResult.data[i].origin;
1190 foundpath =
self SetVehGoalPos( goalPos,
false,
true );
1196 self.current_pathto_pos = goalpos;
1198 self ASMRequestSubstate(
"locomotion@movement" );
1201 self CancelAIMove();
1202 self ClearVehGoalPos();
1204 if( isdefined(
self.move_now ) )
1206 self.move_now = undefined;
1217 self.current_pathto_pos = undefined;
1219 goalYaw =
self GetGoalYaw();
1228 self endon(
"death" );
1229 self endon(
"change_state" );
1234 self ASMRequestSubstate(
"locomotion@movement" );
1239 while (
self.allow_movement )
1241 if (
self.getreadytofire !==
true )
1245 if ( isdefined( goalpos ) && ( Distance2DSquared( goalpos,
self.origin ) >
SQR(
NEAR_GOAL_DIST ) || Abs( goalpos[2] -
self.origin[2] ) >
self.height ) )
1247 self SetSpeed(
self.settings.defaultMoveSpeed, 5, 5 );
1248 self SetVehGoalPos( goalpos,
false,
true );
1249 self.current_pathto_pos = goalpos;
1251 self ASMRequestSubstate(
"locomotion@movement" );
1256 self notify(
"goal" );
1259 self CancelAIMove();
1260 self ClearVehGoalPos();
1262 if ( isdefined(
self.move_now ) )
1264 self.move_now = undefined;
1275 while ( isdefined(
self.getreadytofire ) )
1286 self endon(
"death" );
1287 self endon(
"exit_vehicle" );
1289 weapon =
self SeatGetWeapon( 1 );
1290 fireTime = weapon.fireTime;
1294 self SetGunnerTargetVec(
self GetGunnerTargetVec( 0 ), 1 );
1295 if(
self IsGunnerFiring( 0 ) )
1297 self FireWeapon( 2 );
1305 if( !isAlive( enemy ) || distanceSquared( enemy.origin,
self.origin ) >
SQR(
MELEE_RADIUS ) )
1320 self notify (
"play_meleefx" );
1322 if ( shouldDoDamage )
1325 players = GetPlayers();
1326 foreach( player
in players )
1328 player._takedamage_old = player.takedamage;
1329 player.takedamage =
false;
1334 foreach( player
in players )
1336 player.takedamage = player._takedamage_old;
1337 player._takedamage_old = undefined;
1341 if ( isdefined( enemy ) && isPlayer( enemy ) )
1343 direction =
FLAT_ORIGIN( ( enemy.origin -
self.origin ) );
1344 if ( Abs( direction[0] ) < 0.01 && Abs( direction[1] ) < 0.01 )
1346 direction = ( RandomFloatRange( 1, 2 ), RandomFloatRange( 1, 2 ), 0 );
1348 direction = VectorNormalize( direction );
1350 enemy SetVelocity( enemy GetVelocity() + direction * strength );
1352 enemy DoDamage( 15,
self.origin,
self );
1355 self playsound(
"veh_quadtank_emp" );
1362 self endon(
"death" );
1364 assert( isdefined(
self.team ) );
1368 enemies =
self GetEnemies();
1372 foreach( enemy
in enemies )
1374 if( enemy IsNoTarget() )
1379 meleed = meleed ||
self do_melee( !meleed, enemy );
1397 self HidePart(
"tag_gunner_barrel1" );
1398 self HidePart(
"tag_gunner_turret1" );
1400 else if( index == 2 )
1402 self HidePart(
"tag_gunner_barrel2" );
1403 self HidePart(
"tag_gunner_turret2" );
1407 function QuadtankCallback_VehicleDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal )
1409 is_damaged_by_grenade = weapon.weapClass ==
"grenade";
1411 if( IsSubstr( weapon.name ,
"spike") )
1413 if ( eAttacker.team !==
self.team )
1415 self.spike_hits_during_trophy_down += 1;
1417 is_damaged_by_grenade =
false;
1420 if ( isdefined( eAttacker ) && ( eAttacker ==
self || isplayer( eAttacker ) && eAttacker.usingvehicle && eAttacker.viewlockedentity ===
self ) )
1425 if ( sMeansOfDeath ===
"MOD_MELEE" || sMeansOfDeath ===
"MOD_MELEE_WEAPON_BUTT" || sMeansOfDeath ===
"MOD_MELEE_ASSASSINATE" || sMeansOfDeath ===
"MOD_ELECTROCUTED" || sMeansOfDeath ===
"MOD_CRUSH" || weapon.isEmp )
1432 self.trophy_system_health = 0;
1442 if ( partName ==
"tag_target_lower" || partName ==
"tag_target_upper" || partName ==
"tag_defense_active" || partName ==
"tag_body_animate" )
1444 if( isdefined( eAttacker) && IsPlayer( eAttacker ) && eAttacker.team !=
self.team )
1446 if ( !isDefined(
self.trophy_system_health ) )
1448 self.trophy_system_health =
self.settings.trophySystemHealth;
1461 self.trophy_system_health -= iDamage;
1464 if(
self.trophy_system_health <= 0 )
1477 else if ( is_damaged_by_grenade )
1479 iDamage = Int( iDamage * 3 );
1485 self.turretRotScale = 1.0 *
self.difficulty_scale_up;
1486 self.turret_on_target =
true;
1488 if( sMeansOfDeath ==
"MOD_RIFLE_BULLET" || sMeansOfDeath ==
"MOD_PISTOL_BULLET" )
1494 if( IsActor( eAttacker ) && iDamage > 250 )
1499 num_players = GetPlayers().size;
1500 maxDamage =
self.healthdefault * ( 0.20 - 0.025 * num_players );
1501 if ( sMeansOfDeath !==
"MOD_UNKNOWN" && iDamage > maxDamage )
1503 iDamage = maxDamage;
1508 driver =
self GetSeatOccupant( 0 );
1512 if(
self.damage_during_trophy_down + iDamage >
self.settings.trophysystemdisablethreshold &&
self.trophy_disables <
TROPHY_DISABLE_LIMIT && !isdefined(driver) )
1514 iDamage = max( 1,
self.settings.trophysystemdisablethreshold -
self.damage_during_trophy_down );
1517 self.damage_during_trophy_down += iDamage;
1520 if( damageLevelChanged && sMeansOfDeath !=
"MOD_MELEE_ASSASSINATE" && ( !isdefined(eAttacker) || eAttacker.team !==
self.team ) && !isdefined( driver ) )
1523 playsoundatposition (
"prj_quad_impact",
self.origin);
1526 iDamage =
vehicle_ai::shared_callback_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal );
1543 if( isdefined(
self.missile_repulsor ) )
1545 missile_deleteattractor(
self.missile_repulsor );
1546 self.missile_repulsor = undefined;
1548 self notify(
"end_repulsor_fx" );
1553 self notify(
"end_repulsor_fx" );
1554 self endon(
"end_repulsor_fx" );
1555 self endon(
"death" );
1556 self endon(
"change_state" );
1563 PlayFxOnTag(
self.settings.trophyrepulsefx,
self,
"tag_body" );
1569 self PlaySound(
"wpn_quadtank_shield_impact" );
1578 if( !isdefined(
self.missile_repulsor ) )
1580 self.missile_repulsor = missile_createrepulsorent(
self, 40000,
self.settings.trophysystemrange,
true );
1587 self notify(
"turn_off_laser_thread" );
1588 self endon(
"turn_off_laser_thread" );
1589 self endon(
"death" );
1603 v_pivot_pos =
self GetTagOrigin( s_turret.str_tag_pivot );
1604 v_angles_to_target = VectorToAngles( v_target - v_pivot_pos );
1606 n_rest_angle_pitch = s_turret.n_rest_angle_pitch +
self.angles[0];
1607 n_rest_angle_yaw = s_turret.n_rest_angle_yaw +
self.angles[1];
1609 n_ang_pitch = AngleClamp180( v_angles_to_target[0] - n_rest_angle_pitch );
1610 n_ang_yaw = AngleClamp180( v_angles_to_target[1] - n_rest_angle_yaw );
1612 b_out_of_range =
false;
1614 if ( n_ang_pitch > 0 )
1616 if ( n_ang_pitch > s_turret.bottomarc )
1618 b_out_of_range =
true;
1623 if ( Abs( n_ang_pitch ) > s_turret.toparc )
1625 b_out_of_range =
true;
1629 if ( n_ang_yaw > 0 )
1631 if ( n_ang_yaw > s_turret.leftarc )
1633 b_out_of_range =
true;
1638 if ( Abs( n_ang_yaw ) > s_turret.rightarc )
1640 b_out_of_range =
true;
1644 if( b_out_of_range )
1649 return ( Abs( n_ang_yaw ) / 90 * 800 );
1654 takeEasyOnOneTarget = MapFloat( 0, 4, 800, 0, level.gameskill );
1656 if ( n_index === 1 )
1660 else if ( n_index === 2 )
1665 e_best_target = undefined;
1666 f_best_score = 100000;
1670 foreach(
e_target in a_potential_targets )
1672 f_score = Distance(
self.origin,
e_target.origin );
1676 if( b_current_target )
1686 if (
e_target === other_turret_target )
1688 f_score += ( 100 + takeEasyOnOneTarget );
1696 if ( isAlive(
self.lockon_owner ) &&
e_target ===
self.lockon_owner )
1705 if( view_score != 0.0 )
1707 f_score += view_score;
1711 if ( b_current_target && !b_trace_passed && !isdefined( s_turret.n_time_lose_sight ) )
1713 s_turret.n_time_lose_sight = GetTime();
1716 if( b_trace_passed )
1721 else if ( b_current_target )
1723 s_turret.b_target_out_of_range =
true;
1727 if( f_score < f_best_score )
1729 f_best_score = f_score;
1734 return e_best_target;
1739 if(
IS_TRUE(
self.displayweakpoint ) )
1747 if(
self.displayweakpoint !== state )
1749 self.displayweakpoint = state;
1751 if( !
self.displayweakpoint &&
self.weakpointobjective === 1 )
1753 self.weakpointobjective = 0;
1757 player = level.players[0];
1758 if(
self.displayweakpoint &&
self.combatactive &&
self.weakpointobjective !== 1 && ( !isdefined( player ) || player.team !==
self.team ) )
1760 self.weakpointobjective = 1;
1768 self endon(
"death" );
1769 self endon(
"exit_vehicle" );
1773 note =
self util::waittill_any_return(
"footstep_front_left",
"footstep_front_right",
"footstep_rear_left",
"footstep_rear_right" );
1777 case "footstep_front_left":
1779 bone =
"tag_foot_fx_left_front";
1782 case "footstep_front_right":
1784 bone =
"tag_foot_fx_right_front";
1787 case "footstep_rear_left":
1789 bone =
"tag_foot_fx_left_back";
1792 case "footstep_rear_right":
1794 bone =
"tag_foot_fx_right_back";
1799 position =
self GetTagOrigin( bone ) + (0,0,15);
1801 self RadiusDamage( position, 60, 50, 50,
self,
"MOD_CRUSH" );
1807 self endon(
"entityshutdown" );
1808 self endon (
"death");
1810 self waittill(
"weapon_fired", projectile );
1813 alias =
"prj_quadtank_javelin_incoming";
1817 if(!isdefined( projectile ) )
1820 while(isdefined(projectile) && isdefined( projectile.origin ))
1822 if ( isdefined(
self.enemy ) && isdefined(
self.enemy.origin ))
1824 projectileDistance = DistanceSquared( projectile.origin,
self.enemy.origin);
1826 if( projectileDistance <= distance * distance )
1828 projectile playsound (alias);
1839 self endon(
"entityshutdown" );
1840 self endon (
"death");
1842 self waittill(
"weapon_fired", projectile );
1845 alais =
"wpn_quadtank_railgun_fire_rocket_flux";
1846 players = level.players;
1848 while(isdefined(projectile) && isdefined( projectile.origin ))
1850 if ( isdefined( players[0] ) && isdefined( players[0].origin ))
1852 projectileDistance = DistanceSquared( projectile.origin, players[0].origin);
1854 if( projectileDistance <= distance * distance )
1856 projectile playsound (alais);