‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_quadtank.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
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;
15 
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;
20 
21 #using scripts\shared\ai\systems\blackboard;
22 #using scripts\shared\ai\blackboard_vehicle;
23 #insert scripts\shared\ai\utility.gsh;
24 
25 #using scripts\cp\gametypes\_globallogic_ui;
26 
27 #using scripts\shared\vehicle_shared;
28 #using scripts\shared\vehicle_ai_shared;
29 #using scripts\shared\vehicle_death_shared;
30 
31 #using scripts\cp\_oed;
32 
33 #define SCAN_HEIGHT_OFFSET 40
34 
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
41 
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
44 
45 #define SPIKE_HIT_LIMIT 5 //Used to limit the number of spikes that can hit a QT before trophy system gets re-enabled
46 
47 #define MELEE_RADIUS 270
48 #define MELEE_INNER_RADIUS_DAMAGE 400
49 #define MELEE_OUTER_RADIUS_DAMAGE 400
50 
51 #define ROCKET_LAUNCHER_MIN_DIST 350
52 
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
56 
57 #define NEAR_GOAL_DIST 50
58 
59 #precache( "objective", "cp_quadtank_weakpoint" );
60 #precache( "objective", "cp_quadtank_trophy_disabled" );
61 #precache( "objective", "cp_quadtank_rocket_icon" );
62 
63 #define WEAKSPOT_BONE_NAME "tag_target_lower"
64 #precache( "string", WEAKSPOT_BONE_NAME );
65 
66 #namespace quadtank;
67 
68 ‪REGISTER_SYSTEM( "quadtank", &‪__init__, undefined )
69 
70 #using_animtree( "generic" );
71 
72 function ‪__init__()
73 {
74  vehicle::add_main_callback( "quadtank", &‪quadtank_initialize );
75 
76  ‪clientfield::register( "toplayer", "player_shock_fx", ‪VERSION_SHIP, 1, "int" );
77  ‪clientfield::register( "vehicle", "quadtank_trophy_state", ‪VERSION_SHIP, 1, "int" );
78 }
79 
81 {
82  self useanimtree( #animtree );
83 
84  self EnableAimAssist();
85  self SetNearGoalNotifyDist( ‪NEAR_GOAL_DIST );
86 
87  // AI SPECIFIC INITIALIZATION
90 
91  self.turret_state = ‪TURRET_STATE_SCAN_FORWARD;
92 
93  self.fovcosine = 0; // +/-90 degrees = 180 fov, err 0 actually means 360 degree view
94  self.fovcosinebusy = 0;
95  self.maxsightdistsqrd = ‪SQR( 10000 );
96 
97  self.weakpointobjective = 0;
98  self.combatactive = true; //used for weakpoint marker to make sure that objective is not added if tank is off
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;
103 
104  assert( isdefined( self.scriptbundlesettings ) );
105 
106  self.settings = ‪struct::get_script_bundle( "vehiclecustomsettings", self.scriptbundlesettings );
107 
108 
109  ‪objectives::set( "cp_quadtank_rocket_icon", self );
110  objectives::hide_for_target( "cp_quadtank_rocket_icon", self );
111 
112 
113  self.variant = "cannon";
114 
115  if( IsSubStr( self.vehicleType, "mlrs" ) )
116  {
117  self.variant = "rocketpod";
118  }
119 
120  self.goalRadius = 9999999;
121  self.goalHeight = 512;
122  self SetGoal( self.origin, false, self.goalRadius, self.goalHeight );
123 
124  self SetSpeed( self.settings.defaultMoveSpeed, 10, 10 );
125  self SetMinDesiredTurnYaw( 45 );
126  self ‪show_weak_spots( false );
127 
130 
133 
135 
137  self.overrideVehicleDamage = &‪QuadtankCallback_VehicleDamage;
138 
139  //disable some cybercom abilities
140  if( IsDefined( level.vehicle_initializer_cb ) )
141  {
142  [[level.vehicle_initializer_cb]]( self );
143  }
144 
145  self.ignoreFireFly = true;
146  self.ignoreDecoy = true;
148 
149  self.disableElectroDamage = true;
150  self.disableBurnDamage = true;
151 
152  self thread ‪vehicle_ai::target_hijackers();
153 
154  self HidePart( "tag_defense_active" );
155 
156  ‪defaultRole();
157 }
158 
160 {
161 // testing out changing the turret parameters based solely upon the number of players, since damage
162 // is alread scaled based upon the difficulty of the individual player
163 // so, saving out current method until change has been tested
164 //
165 // value = gameskill::get_general_difficulty_level();
166 //
167 // scale_up = mapfloat( 0, 7, 0.8, 2.0, value );
168 // scale_down = mapfloat( 0, 7, 1.0, 0.5, value );
169 
170  if( isDefined( level.players) )
171  {
172  value = level.players.size;
173  }
174  else
175  {
176  value = 1;
177  }
178 
179 
180  scale_up = mapfloat( 1, 4, 1, 1.5, value );
181  scale_down = mapfloat( 1, 4, 1.0, 0.75, value );
182 
183  ‪turret::set_burst_parameters( 1.5, 2.5 * scale_up, 0.25 * scale_down, 0.75 * scale_down, 1 );
184  ‪turret::set_burst_parameters( 1.5, 2.5 * scale_up, 0.25 * scale_down, 0.75 * scale_down, 2 );
185 
186  self.difficulty_scale_up = scale_up;
187  self.difficulty_scale_down = scale_down;
188 }
189 
190 function ‪defaultRole()
191 {
192  self.state_machine = self ‪vehicle_ai::init_state_machine_for_role( "default" );
193 
194  self ‪vehicle_ai::get_state_callbacks( "pain" ).update_func = &‪pain_update;
195  self ‪vehicle_ai::get_state_callbacks( "emped" ).update_func = &‪quadtank_emped;
196 
197  self ‪vehicle_ai::get_state_callbacks( "off" ).enter_func = &‪state_off_enter;
198  self ‪vehicle_ai::get_state_callbacks( "off" ).exit_func = &‪state_off_exit;
199 
200  self ‪vehicle_ai::get_state_callbacks( "scripted" ).update_func = &‪state_scripted_update;
201  self ‪vehicle_ai::get_state_callbacks( "driving" ).update_func = &‪state_driving_update;
202 
203  self ‪vehicle_ai::get_state_callbacks( "combat" ).update_func = &‪state_combat_update;
204  self ‪vehicle_ai::get_state_callbacks( "combat" ).exit_func = &‪state_combat_exit;
205 
206  self ‪vehicle_ai::get_state_callbacks( "death" ).update_func = &‪quadtank_death;
207 
209 
211 }
212 
213 // ----------------------------------------------
214 // State: off
215 // ----------------------------------------------
216 function ‪quadtank_off()
217 {
218  self ‪vehicle_ai::set_state( "off" );
219  self.combatactive = false;
220 }
221 
222 function ‪quadtank_on()
223 {
224  self ‪vehicle_ai::set_state( "combat" );
225  self.combatactive = true;
226 }
227 
228 function ‪state_off_enter( params )
229 {
230  self playsound( "veh_quadtank_power_down" );
231 
232  self LaserOff();
233  self ClearTargetEntity();
234  self CancelAIMove();
235  self ClearVehGoalPos();
236 
239  self ‪vehicle::toggle_tread_fx( 0 );
240  self ‪vehicle::toggle_sounds( 0 );
242 
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 );
247  self ‪set_side_turrets_enabled( false );
248  self thread ‪quadtank_disabletrophy();
249 
250  if( !isdefined( self.‪emped ) )
251  {
252  self DisableAimAssist();
253  }
254 }
255 
256 function ‪state_off_exit( params )
257 {
258  self ‪vehicle::lights_on();
259  self ‪vehicle::toggle_tread_fx( 1 );
260  self ‪vehicle::toggle_sounds( 1 );
261  self thread ‪bootup();
263  self EnableAimAssist();
264 }
265 
266 function ‪bootup()
267 {
268  self endon("death");
269  self playsound( "veh_quadtank_power_up" );
271 
272  angles = self GetTagAngles( "tag_flash" );
273  target_vec = self.origin + AnglesToForward( ( 0, angles[1], 0 ) ) * 1000;
274  self.turretRotScale = 0.3;
275 
276  driver = self GetSeatOccupant( 0 );
277  if( !isdefined(driver) )
278  {
279  self SetTargetOrigin( target_vec );
280  }
281  wait 1;
282 
283  self.turretRotScale = 1 * self.difficulty_scale_up;
284 }
285 // State: off -----------------------------------
286 
287 // ----------------------------------------------
288 // State: pain
289 // ----------------------------------------------
290 function ‪pain_update( params )
291 {
292  self endon( "change_state" );
293  self endon( "death" );
294 
295  isTrophyDownPain = params.notify_param[0];
296 
297  if( isTrophyDownPain === true )
298  {
299  // trophy system must be going down now
300  asmState = "trophy_disabled@stationary";
301  }
302  else
303  {
304  // can only take pain when trophy is down
305  asmState = "pain@stationary";
306  }
307  self ASMRequestSubstate( asmState );
308  playsoundatposition ("prj_quad_impact", self.origin);
309 
310  self CancelAIMove();
311  self ClearVehGoalPos();
312  self ClearTurretTarget();
313  self SetBrake( 1 );
314 
315  self ‪vehicle_ai::waittill_asm_complete( asmState, 6 );
316 
317  self SetBrake( 0 );
318 
319  self ASMRequestSubstate( "locomotion@movement" );
320 
321  driver = self GetSeatOccupant( 0 );
322  if( !isdefined( driver ) )
323  {
324  self ‪vehicle_ai::set_state( "combat" );
325  }
326  else
327  {
328  self ‪vehicle_ai::set_state( "driving" );
329  }
330 }
331 // State: pain ----------------------------------
332 
333 // ----------------------------------------------
334 // State: scripted
335 // ----------------------------------------------
336 function ‪state_scripted_update( params )
337 {
338  self endon( "death" );
339  self endon( "change_state" );
340 
341  self ‪set_side_turrets_enabled( false );
342  self LaserOff();
343  self ClearTargetEntity();
344  self CancelAIMove();
345  self ClearVehGoalPos();
346 
348 }
349 // State: scripted ------------------------------
350 
351 // ----------------------------------------------
352 // State: driving
353 // ----------------------------------------------
354 function ‪state_driving_update( params )
355 {
356  self endon( "death" );
357  self endon( "change_state" );
358 
359  self ‪set_side_turrets_enabled( false );
360  self LaserOff();
361  self ClearTargetEntity();
362  self CancelAIMove();
363  self ClearVehGoalPos();
364 
366  objectives::hide_for_target( "cp_quadtank_rocket_icon", self );
367 
368  driver = self GetSeatOccupant( 0 );
369  if( isdefined(driver) )
370  {
371  self.turretRotScale = 1;
372  self DisableAimAssist();
373  self thread ‪quadtank_set_team( driver.team );
374  self SetBrake( 0 );
375  self ASMRequestSubstate( "locomotion@movement" );
376  self thread ‪quadtank_player_fireupdate();
377  self thread ‪footstep_handler();
378 
379  self.trophy_disables = ‪TROPHY_DISABLE_LIMIT - 1;
380  self thread ‪quadtank_disabletrophy();
381  }
382 }
383 
385 {
386  self SetGoal( self.origin );
387 }
388 // State: driving -------------------------------
389 
390 // ----------------------------------------------
391 // State: combat
392 // ----------------------------------------------
393 function ‪state_combat_update( params )
394 {
395  self endon( "death" );
396  self endon( "change_state" );
397 
398  if ( isalive( self ) )
399  {
400  }
401 
402  if ( isalive( self ) && !‪trophy_disabled() )
403  {
404  self thread ‪quadtank_enabletrophy();
405  }
406 
407  if ( self.allow_movement )
408  {
409  self thread ‪quadtank_movementupdate();
410  }
411  else
412  {
413  self SetBrake( 1 );
414  }
415 
416  switch ( self.variant )
417  {
418  case "cannon":
419  ‪vehicle_ai::Cooldown( "main_cannon", 4 ); // don't shoot cannon immediately
420  self thread ‪quadtank_weapon_think_cannon();
421  break;
422  case "rocketpod":
423  self thread ‪Attack_Thread_rocket();
424  break;
425  }
426 }
427 
428 function ‪state_combat_exit( params )
429 {
430  self notify( "end_attack_thread" );
431  self notify( "end_movement_thread" );
432  self ClearTurretTarget();
433  self ClearLookAtEnt();
434 }
435 // State: combat --------------------------------
436 
437 // ----------------------------------------------
438 // State: death
439 // ----------------------------------------------
440 function ‪quadtank_death( params )
441 {
442  self endon( "death" );
443  self endon( "nodeath_thread" );
444 
445  self ‪set_trophy_state( false );
446  self ‪quadtank_weakpoint_display( false );
447  objectives::hide_for_target( "cp_quadtank_rocket_icon", self );
448  self ‪remove_repulsor();
449  self HidePart( "tag_lidar_null", "", true );
451 
452  // Need to prep the death model
453  StreamerModelHint( self.deathmodel, 6 );
454 
455  if ( !isdefined( self.custom_death_sequence ) )
456  {
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" );
462  }
463  else
464  {
465  self [[self.custom_death_sequence]]();
466  }
467 
468  if( isdefined( level.disable_thermal ) )
469  {
470  [[level.disable_thermal]]();
471  }
472 
473  if( isdefined( self.stun_fx ) )
474  {
475  self.stun_fx delete();
476  }
477 
478  BadPlace_Box( "", 0, self.origin, 90, "neutral" );
479  self ‪vehicle_death::set_death_model( self.deathmodel, self.modelswapdelay );
481 
482  ‪vehicle_ai::waittill_asm_complete( "death@stationary", 5 );
483 
484  self thread ‪vehicle_death::CleanUp();
486 }
487 
488 // ----------------------------------------------
489 // State: emped
490 // ----------------------------------------------
491 function ‪quadtank_emped( params )
492 {
493  self endon ("death");
494  self endon( "change_state" );
495  self endon( "emped" );
496 
497  if( isdefined( self.‪emped ) )
498  {
499  // already emped, just return for now.
500  return;
501  }
502 
503  self.emped = true;
504  PlaySoundAtPosition( "veh_quadtankemp_down", self.origin );
505  self.turretRotScale = 0.2;
506  if( !isdefined( self.stun_fx) )
507  {
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) );
511  //PlayFXOnTag( level._effect[ "quadtank_stun" ], self.stun_fx, "tag_origin" );
512  }
513 
514  time = params.notify_param[0];
515  assert( isdefined( time ) );
516  ‪vehicle_ai::Cooldown( "emped_timer", time );
517 
518  while( !‪vehicle_ai::IsCooldownReady( "emped_timer" ) )
519  {
520  timeLeft = max( ‪vehicle_ai::GetCooldownLeft( "emped_timer" ), 0.5 );
521  wait timeLeft;
522  }
523 
524  self.stun_fx delete();
525  self.emped = undefined;
526  self playsound ("veh_boot_quadtank");
527 
529 }
530 
531 // ----------------------------------------------
532 // trophy system
533 // ----------------------------------------------
535 {
536  if( self.trophy_down === true )
537  {
538  return true;
539  }
540 
541  if ( ‪trophy_destroyed() )
542  {
543  return true;
544  }
545 
546  return false;
547 }
548 
550 {
551  if ( self.trophy_disables >= ‪TROPHY_DISABLE_LIMIT )
552  {
553  return true;
554  }
555  return false;
556 }
557 
558 function ‪set_trophy_state( isOn )
559 {
560  self ‪clientfield::set( "quadtank_trophy_state", isOn );
561 }
562 
564 {
565  self endon( "death" );
566  self notify( "stop_disabletrophy" );
567  self endon( "stop_disabletrophy" );
568  self notify( "stop_enabletrophy" );
569 
570  ‪set_trophy_state( false );
571 
572  if( ‪trophy_disabled() )
573  return;
574 
575  self.trophy_down = true;
576 
577  driver = self GetSeatOccupant( 0 );
578  if( !isdefined( driver ) && self ‪vehicle_ai::get_current_state() != "off" && self ‪vehicle_ai::get_next_state() !== "off" )
579  {
580  self notify( "pain", true ); // Play a trophy system down animation using the pain state
581  }
582 
583  Target_Set( self , (0,0,60) );
584 
585  self HidePart( "tag_defense_active" );
586  //self HidePart( "tag_target_upper" );
587 
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;
592 
593  self ‪quadtank_weakpoint_display( false );
594  self ‪remove_repulsor();
595 
596  driver = self GetSeatOccupant( 0 );
597  if( !isdefined( driver ) && self ‪vehicle_ai::get_current_state() != "off" && self ‪vehicle_ai::get_next_state() !== "off" )
598  {
599  objectives::show_for_target( "cp_quadtank_rocket_icon", self );
600  }
601  else
602  {
603  objectives::hide_for_target( "cp_quadtank_rocket_icon", self );
604  }
605 
606  self ‪set_side_turrets_enabled( false );
607 
608  if( IsDefined( level.vehicle_defense_cb ) )
609  {
610  [[level.vehicle_defense_cb]]( self, false );
611  }
612 
613  if( ‪trophy_destroyed() )
614  {
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 );
620  return;
621  }
622 
623  self notify("trophy_system_disabled");
624  level notify("trophy_system_disabled",self);
625  self playsound ("wpn_trophy_disable");
626 
627  self ‪vehicle_ai::Cooldown( "trophy_down", self.settings.trophySystemDownTime );
628  while( !self ‪vehicle_ai::IsCooldownReady("trophy_down") || self ‪vehicle_ai::get_current_state() === "off" )
629  {
630  if ( ‪vehicle_ai::GetCooldownLeft( "trophy_down" ) < 0.5 * self.settings.trophySystemDownTime && ( self.damage_during_trophy_down >= self.settings.trophysystemdisablethreshold ||
631  self.spike_hits_during_trophy_down >= ‪SPIKE_HIT_LIMIT ) )
632  {
633  self ‪vehicle_ai::ClearCooldown( "trophy_down" );
634  }
635 
636  wait 1;
637  }
638 
639  // player's trophy don't get back up
640  driver = self GetSeatOccupant( 0 );
641  if( isdefined( driver ) )
642  {
643  self.trophy_disables = ‪TROPHY_DISABLE_LIMIT;
644  }
645 
646  if( !‪trophy_destroyed() )
647  {
648  self thread ‪quadtank_enabletrophy();
649  }
650 }
651 
653 {
654  self endon( "death" );
655  self notify( "stop_enabletrophy" );
656  self endon( "stop_enabletrophy" );
657 
658  ‪set_trophy_state( true );
659  time = ‪VAL( self.settings.trophywarmup, 0.1 );
660  wait time;
661 
662  driver = self GetSeatOccupant( 0 );
663 
664  self.trophy_down = false;
665  self.attackerAccuracy = 1;
666  self ShowPart( "tag_defense_active" );
667  //self ShowPart( "tag_target_upper" );
668  objectives::hide_for_target( "cp_quadtank_rocket_icon", self );
669 
671  self thread ‪quadtank_automelee_update();
672 
673  if( !isdefined( driver ) )
674  {
675  self ‪quadtank_weakpoint_display( true );
676  }
677  else
678  {
679  self ‪quadtank_weakpoint_display( false );
680  }
681 
682  if ( Target_IsTarget(self) )
683  {
684  Target_remove( self );
685  }
686 
687  if( !isdefined( driver ) )
688  {
689  self ‪set_side_turrets_enabled( true );
690  }
691  self.trophy_system_health = self.settings.trophySystemHealth;
692 
693  if( isDefined( level.players) && level.players.size > 0 )
694  {
695  num_players_trophy_health_modifier = 0.75;
696 
697  if( level.players.size == 2)
698  {
699  num_players_trophy_health_modifier = 1;
700  }
701  if( level.players.size == 3)
702  {
703  num_players_trophy_health_modifier = 1.25;
704  }
705  if( level.players.size >= 4)
706  {
707  num_players_trophy_health_modifier = 1.5;
708  }
709  self.trophy_system_health = self.trophy_system_health * num_players_trophy_health_modifier;
710  }
711 
712  if( IsDefined( level.vehicle_defense_cb ) )
713  {
714  [[level.vehicle_defense_cb]]( self, true );
715  }
716 
717  self notify("trophy_system_enabled");
718  level notify("trophy_system_enabled",self);
719 }
720 
721 // trophy system --------------------------------
722 
724 {
725  self SetTurretTargetRelativeAngles( (10, -90, 0), 1 );
726  self SetTurretTargetRelativeAngles( (10, 90, 0), 2 );
727  self.turretRotScale = 1 * self.difficulty_scale_up;
728 }
729 
730 // rotates the turret around until he can see his enemy
731 function ‪quadtank_turret_scan( scan_forever )
732 {
733  self endon( "death" );
734  self endon( "change_state" );
735 
736  self.turretRotScale = 0.3;
737 
738  while( scan_forever || ( !isdefined( self.enemy ) || !(self VehCanSee( self.enemy )) ) )
739  {
740  if( self.turretontarget && self.turret_state != ‪TURRET_STATE_SCAN_AT_ENEMY )
741  {
742  self.turret_state++;
743  if( self.turret_state >= ‪NUM_TURRET_STATES )
744  self.turret_state = ‪TURRET_STATE_SCAN_FORWARD;
745  }
746 
747  switch( self.turret_state )
748  {
749  // reserved for taking damage and looking responsive
751  if( isdefined( self.enemy ) )
752  {
753  self SetLookAtEnt( self.enemy );
754  target_vec = self.enemy.origin + ( 0, 0, ‪SCAN_HEIGHT_OFFSET );
755  self SetTargetOrigin( target_vec );
756  wait 1.0;
757  self ClearLookAtEnt();
758  self.turret_state++;
759  } // else fall through to FORWARD
760 
762  target_vec = self.origin + AnglesToForward( ( 0, self.angles[1], 0 ) ) * 1000;
763  break;
764 
766  target_vec = self.origin + AnglesToForward( ( 0, self.angles[1] + 30, 0 ) ) * 1000;
767  break;
768 
770  target_vec = self.origin + AnglesToForward( ( 0, self.angles[1], 0 ) ) * 1000;
771  break;
772 
774  target_vec = self.origin + AnglesToForward( ( 0, self.angles[1] - 30, 0 ) ) * 1000;
775  break;
776  }
777 
778  target_vec = target_vec + ( 0, 0, ‪SCAN_HEIGHT_OFFSET );
779  self SetTargetOrigin( target_vec );
780 
781  wait 0.2;
782  }
783 }
784 
786 {
787  if( on )
788  {
789  ‪turret::enable( 1, false );
790  ‪turret::enable( 2, false );
791  }
792  else
793  {
794  ‪turret::disable( 1 );
795  ‪turret::disable( 2 );
796  }
797 }
798 
799 function ‪show_weak_spots( show ) // vents on the sides that are exposed when firing the main gun
800 {
801  if( show )
802  {
804  }
805  else
806  {
808  }
809 }
810 
811 function ‪set_detonation_time( target )
812 {
813  self endon( "change_state" );
814 
815  self playsound("veh_quadtank_cannon_charge");
816 
817  self waittill( "weapon_fired", proj );
818 
819  self thread ‪railgun_sound(proj);
820 
821  if( isdefined( target ) && isdefined( proj ) )
822  {
823  vel = proj GetVelocity();
824 
825  proj_speed = length( vel );
826 
827  dist = Distance( proj.origin, target.origin ) + RandomFloatRange( 0, 40 );
828 
829  time_to_enemy = dist / proj_speed;
830 
831  proj ResetMissileDetonationTime( time_to_enemy );
832  }
833 }
834 
836 {
837  self endon( "death" );
838  self endon( "change_state" );
839 
840  cant_see_enemy_count = 0;
841 
842  self ‪set_side_turrets_enabled( true );
843  self SetOnTargetAngle( 10 ); // self.turretontarget will be true when the turret is aimed within this rage
844 
845  self.getreadytofire = undefined;
846 
847  while ( 1 )
848  {
849  if( self.hold_cannon === true || !‪vehicle_ai::IsCooldownReady( "main_cannon" ) )
850  {
851  if ( isdefined( self.enemy ) && self VehCanSee( self.enemy ) )
852  {
853  self SetTurretTargetEnt( self.enemy );
854  self SetLookAtEnt( self.enemy );
855  }
856 
857  wait 0.2;
858  continue;
859  }
860 
861  if ( isdefined( self.enemy ) && self VehCanSee( self.enemy ) )
862  {
863  self.turretRotScale = 1 * self.difficulty_scale_up;
864  self SetTurretTargetEnt( self.enemy );
865  self SetLookAtEnt( self.enemy );
866 
867  if( cant_see_enemy_count >= 2 )
868  {
869  wait 0.1; // let the self.turretontarget have time to update so we don't shoot in a bad direction
870 
871  // found enemy, react by changing goal positions
872  self CancelAIMove();
873  self ClearVehGoalPos();
874  self notify( "near_goal" );
875  }
876  cant_see_enemy_count = 0;
877  fired = false;
878 
879  if ( isdefined( self.enemy ) && self VehCanSee( self.enemy ) )
880  {
881  if( DistanceSquared( self.origin, self.enemy.origin ) > ‪MELEE_RADIUS * ‪MELEE_RADIUS && self.turretontarget )
882  {
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 );
887 
888  if( dot > 0.707 ) // body is facing within 45' of enemy
889  {
890  self ASMRequestSubstate( "fire@stationary" );
891  self SetTurretTargetEnt( self.enemy );
892  self thread ‪set_detonation_time( self.enemy );
893 
894  if( isDefined( level.players) && level.players.size < 3)
895  {
896  self ‪set_side_turrets_enabled( false );
897  }
898 
899  self ‪show_weak_spots( true );
900  self.getreadytofire = true;
901  fired = true;
902 
903  self CancelAIMove();
904  self ClearVehGoalPos();
905  self notify( "near_goal" );
906 
907  self.turretRotScale = 0.7;
908 
909  wait 1;
910 
911  level notify( "sndStopCountdown" );
912 
913  self ‪vehicle_ai::waittill_asm_complete( "fire@stationary", 6 );
914 
915  self ‪set_side_turrets_enabled( true );
916 
917  self.turretRotScale = 1;
918  }
919  }
920  }
921 
922  self.getreadytofire = undefined;
923 
924  if ( isdefined( self.enemy ) )
925  {
926  self SetTurretTargetEnt( self.enemy );
927  self SetLookAtEnt( self.enemy );
928  }
929 
930  if( fired )
931  {
932  self ‪show_weak_spots( false );
933 
934  ‪vehicle_ai::Cooldown( "main_cannon", RandomFloatRange( 5, 7.5 ) );
935  }
936  else
937  {
938  wait 0.25;
939  }
940  }
941  else
942  {
943  cant_see_enemy_count++;
944 
945  wait 0.5;
946 
947  if( cant_see_enemy_count > 40 )
948  {
949  self ‪quadtank_turret_scan( false );
950  }
951  else if( cant_see_enemy_count > 30 )
952  {
953  self ClearLookAtEnt();
954  self ClearTargetEntity();
955  }
956  else
957  {
958  if( isdefined( self.enemy ) )
959  {
960  self SetTurretTargetEnt( self.enemy );
961  self ClearLookAtEnt();
962  }
963  else
964  {
965  self ClearLookAtEnt();
966  self ‪quadtank_turret_scan( false );
967  }
968  }
969  }
970  }
971 }
972 
973 
975 {
976  self endon( "death" );
977  self endon( "end_attack_thread" );
978 
979  self ‪vehicle::toggle_ambient_anim_group( 2, false ); // close the weapon doors
980 
981  while( true )
982  {
983  useJavelin = false;
984 
985  if ( isdefined( self.enemy ) )
986  {
987  self SetTurretTargetEnt( self.enemy );
988  self SetLookAtEnt( self.enemy );
989  }
990 
991  if( isdefined( self.enemy) && ‪vehicle_ai::IsCooldownReady( "javelin_rocket_launcher", 0.5 ) )
992  {
993  if( isVehicle( self.enemy ) || Distance2DSquared( self.origin, self.enemy.origin) >= ‪SQR( ‪JAVELIN_MIN_USE_DISTANCE ) )
994  {
995  useJavelin = !self vehseenrecently( self.enemy, 3 ) || ( RandomInt( 100 ) < 3 );
996  }
997  }
998 
999  if ( isdefined( self.enemy ) && ‪vehicle_ai::IsCooldownReady( "rocket_launcher", 0.5 ) )
1000  {
1001  if( isDefined( level.players) && level.players.size < 3)
1002  {
1003  self ‪set_side_turrets_enabled( false );
1004  }
1005  self ClearVehGoalPos();
1006  self notify( "near_goal" );
1007  self ‪show_weak_spots( true );
1008  self ‪vehicle::toggle_ambient_anim_group( 2, true );
1009 
1010  if( !useJavelin )
1011  {
1012  self SetVehWeapon( GetWeapon( ‪WEAPON_STRAIGHT ) );
1013  offset = ( 0, 0, -50 );
1014  if ( isPlayer( self.enemy ) )
1015  {
1016  origin = self.enemy.origin;
1017  eye = self.enemy GetEye();
1018  offset = ( 0, 0, origin[2] - eye[2] - 5 );
1019  }
1020  ‪vehicle_ai::SetTurretTarget( self.enemy, 0, offset );
1021  }
1022  else
1023  {
1024  self playsound ("veh_quadtank_mlrs_plant_start");
1025 
1026  self SetVehWeapon( GetWeapon( ‪WEAPON_JAVELIN ) );
1027 
1028  ‪vehicle_ai::SetTurretTarget( self.enemy, 0, (0,0,300) );
1029  }
1030 
1031  wait 1;
1032  msg = self ‪util::waittill_any_timeout( 2, "turret_on_target" );
1033 
1034  if ( isdefined( self.enemy ) && Distance2DSquared( self.origin, self.enemy.origin ) > ‪SQR( ‪ROCKET_LAUNCHER_MIN_DIST ) )
1035  {
1036  fired = false;
1037  for( i = 0; i < 4 && isdefined( self.enemy ); i++ )
1038  {
1039  if( useJavelin )
1040  {
1041  if ( isPlayer( self.enemy ) )
1042  {
1043  self thread ‪vehicle_ai::Javelin_LoseTargetAtRightTime( self.enemy );
1044  }
1045  self thread ‪javeline_incoming(GetWeapon( ‪WEAPON_JAVELIN ));
1046  }
1047  self FireWeapon( 0, self.enemy );
1048 
1049  fired = true;
1050  wait 0.8;
1051  }
1052 
1053  if ( fired )
1054  {
1055  ‪vehicle_ai::Cooldown( "rocket_launcher", randomFloatRange( 8, 10 ) );
1056 
1057  if( useJavelin )
1058  {
1059  ‪vehicle_ai::Cooldown( "javelin_rocket_launcher", 20 );
1060  }
1061  }
1062  }
1063 
1064  self ‪set_side_turrets_enabled( true );
1065  self ‪vehicle::toggle_ambient_anim_group( 2, false );
1066  }
1067  wait 1;
1068  }
1069 }
1070 
1071 // self == player
1073 {
1074  if ( !isdefined( self._player_shock_fx_quadtank_melee ) )
1075  {
1076  self._player_shock_fx_quadtank_melee = 0;
1077  }
1078 
1079  self._player_shock_fx_quadtank_melee = !self._player_shock_fx_quadtank_melee;
1080  self ‪clientfield::set_to_player( "player_shock_fx", self._player_shock_fx_quadtank_melee );
1081 }
1082 
1084 {
1085  self endon( "death" );
1086  self endon( "change_state" );
1087  self endon( "near_goal" );
1088  self endon( "reached_end_node" );
1089 
1090  wait 1;
1091 
1092  cantSeeEnemyCount = 0;
1093 
1094  while( 1 )
1095  {
1096  if( isdefined( self.current_pathto_pos ) )
1097  {
1098  if( isdefined( self.enemy ) )
1099  {
1100  if( distance2dSquared( self.enemy.origin, self.current_pathto_pos ) < 250 * 250 )
1101  {
1102  self.move_now = true;
1103  self notify( "near_goal" );
1104  }
1105 
1106  if( !self VehCanSee( self.enemy ) )
1107  {
1108  if( !self ‪vehicle_ai::CanSeeEnemyFromPosition( self.current_pathto_pos, self.enemy, 80 ) )
1109  {
1110  cantSeeEnemyCount++;
1111  if( cantSeeEnemyCount > 5 )
1112  {
1113  self.move_now = true;
1114  self notify( "near_goal" );
1115  }
1116  }
1117  }
1118  }
1119 
1120  if( distance2dSquared( self.current_pathto_pos, self.goalpos ) > self.goalradius * self.goalradius )
1121  {
1122  wait 1;
1123 
1124  self.move_now = true;
1125  self notify( "near_goal" );
1126  }
1127  }
1128 
1129  wait 0.3;
1130  }
1131 }
1132 
1134 {
1135  self endon( "death" );
1136  self endon( "change_state" );
1137  self notify( "end_movement_thread" );
1138  self endon( "end_movement_thread" );
1139 
1140  if( self.goalforced )
1141  {
1142  return self.goalpos;
1143  }
1144 
1145  minSearchRadius = 0;
1146  maxSearchRadius = 2000;
1147  halfHeight = 300;
1148  innerSpacing = 90;
1149  outerSpacing = innerSpacing * 2;
1150  maxGoalTimeout = 15;
1151 
1152  self ASMRequestSubstate( "locomotion@movement" );
1153 
1154  wait 0.5;
1155  self SetBrake( 0 );
1156 
1157  while ( true )
1158  {
1159  self SetSpeed( self.settings.defaultMoveSpeed, 5, 5 );
1160 
1161  PixBeginEvent( "_quadtank::Movement_Thread_Wander" );
1162  queryResult = PositionQuery_Source_Navigation( self.origin, minSearchRadius, maxSearchRadius, halfHeight, innerSpacing, self, outerSpacing );
1163  PixEndEvent();
1164 
1165  // filter
1166  PositionQuery_Filter_DistanceToGoal( queryResult, self );
1168  ‪vehicle_ai::PositionQuery_Filter_Random( queryResult, 200, 250 );
1169 
1170  foreach ( point in queryResult.data )
1171  {
1172  if( distance2dSquared( self.origin, point.origin ) < 170 * 170 )
1173  {
1174  ADD_POINT_SCORE( point, "tooCloseToSelf", -100 );
1175  }
1176  }
1177  self ‪vehicle_ai::PositionQuery_DebugScores( queryResult );
1178 
1180 
1181  foundpath = false;
1182  goalPos = self.origin;
1183  count = queryResult.data.size;
1184  if( count > 3 )
1185  count = 3;
1186 
1187  for ( i = 0; i < count && !foundpath; i++ )
1188  {
1189  goalPos = queryResult.data[i].origin;
1190  foundpath = self SetVehGoalPos( goalPos, false, true );
1191  }
1192 
1193  if( foundpath )
1194  {
1195 
1196  self.current_pathto_pos = goalpos;
1197  self thread ‪path_update_interrupt();
1198  self ASMRequestSubstate( "locomotion@movement" );
1199 
1200  msg = self ‪util::waittill_any_timeout( maxGoalTimeout, "near_goal", "force_goal", "reached_end_node", "goal" );
1201  self CancelAIMove();
1202  self ClearVehGoalPos();
1203 
1204  if( isdefined( self.move_now ) )
1205  {
1206  self.move_now = undefined;
1207 
1208  wait 0.1;
1209  }
1210  else
1211  {
1212  wait 0.5;
1213  }
1214  }
1215  else
1216  {
1217  self.current_pathto_pos = undefined;
1218 
1219  goalYaw = self GetGoalYaw();
1220 
1221  wait 1;
1222  }
1223  }
1224 }
1225 
1227 {
1228  self endon( "death" );
1229  self endon( "change_state" );
1230 
1231  //if( distance2dSquared( self.origin, self.goalpos ) > 20 * 20 )
1232  // self SetVehGoalPos( self.goalpos, true, 2 );
1233 
1234  self ASMRequestSubstate( "locomotion@movement" );
1235  wait 0.5;
1236 
1237  self SetBrake( 0 );
1238 
1239  while ( self.allow_movement )
1240  {
1241  if ( self.getreadytofire !== true )
1242  {
1243  goalpos = ‪vehicle_ai::FindNewPosition( 80 );
1244 
1245  if ( isdefined( goalpos ) && ( Distance2DSquared( goalpos, self.origin ) > ‪SQR( ‪NEAR_GOAL_DIST ) || Abs( goalpos[2] - self.origin[2] ) > self.height ) )
1246  {
1247  self SetSpeed( self.settings.defaultMoveSpeed, 5, 5 );
1248  self SetVehGoalPos( goalpos, false, true );
1249  self.current_pathto_pos = goalpos;
1250  self thread ‪path_update_interrupt();
1251  self ASMRequestSubstate( "locomotion@movement" );
1252  ‪result = self ‪util::waittill_any_return( "near_goal", "reached_end_node", "force_goal" );
1253  }
1254  else
1255  {
1256  self notify( "goal" );
1257  }
1258 
1259  self CancelAIMove();
1260  self ClearVehGoalPos();
1261 
1262  if ( isdefined( self.move_now ) )
1263  {
1264  self.move_now = undefined;
1265 
1266  wait 0.1;
1267  }
1268  else
1269  {
1270  wait 0.5;
1271  }
1272  }
1273  else
1274  {
1275  while ( isdefined( self.getreadytofire ) )
1276  {
1277  wait 0.2;
1278  }
1279  }
1280 
1281  }
1282 }
1283 
1285 {
1286  self endon( "death" );
1287  self endon( "exit_vehicle" );
1288 
1289  weapon = self SeatGetWeapon( 1 );
1290  fireTime = weapon.fireTime;
1291 
1292  while( 1 )
1293  {
1294  self SetGunnerTargetVec( self GetGunnerTargetVec( 0 ), 1 );
1295  if( self IsGunnerFiring( 0 ) )
1296  {
1297  self FireWeapon( 2 );
1298  }
1299  wait fireTime;
1300  }
1301 }
1302 
1303 function ‪do_melee( shouldDoDamage, enemy )
1304 {
1305  if( !isAlive( enemy ) || distanceSquared( enemy.origin, self.origin ) > ‪SQR( ‪MELEE_RADIUS ) )
1306  {
1307  return false;
1308  }
1309 
1310  if ( ‪vehicle_ai::EntityIsArchetype( enemy, "quadtank" ) || ‪vehicle_ai::EntityIsArchetype( enemy, "raps" ) )
1311  {
1312  return false;
1313  }
1314 
1315  if ( isPlayer( enemy ) && enemy ‪laststand::player_is_in_laststand() )
1316  {
1317  return false;
1318  }
1319 
1320  self notify ( "play_meleefx" );
1321 
1322  if ( shouldDoDamage )
1323  {
1324  // don't damage player, but crush player vehicle
1325  players = GetPlayers();
1326  foreach( player in players )
1327  {
1328  player._takedamage_old = player.takedamage;
1329  player.takedamage = false;
1330  }
1331 
1332  RadiusDamage( self.origin + (0,0,40), ‪MELEE_RADIUS, ‪MELEE_INNER_RADIUS_DAMAGE, ‪MELEE_OUTER_RADIUS_DAMAGE, self );
1333 
1334  foreach( player in players )
1335  {
1336  player.takedamage = player._takedamage_old;
1337  player._takedamage_old = undefined;
1338  }
1339  }
1340 
1341  if ( isdefined( enemy ) && isPlayer( enemy ) )
1342  {
1343  direction = ‪FLAT_ORIGIN( ( enemy.origin - self.origin ) );
1344  if ( Abs( direction[0] ) < 0.01 && Abs( direction[1] ) < 0.01 )
1345  {
1346  direction = ( RandomFloatRange( 1, 2 ), RandomFloatRange( 1, 2 ), 0 );
1347  }
1348  direction = VectorNormalize( direction );
1349  strength = 1000;
1350  enemy SetVelocity( enemy GetVelocity() + direction * strength );
1352  enemy DoDamage( 15, self.origin, self );
1353  }
1354 
1355  self playsound( "veh_quadtank_emp" );
1356 
1357  return true;
1358 }
1359 
1361 {
1362  self endon( "death" );
1363 
1364  assert( isdefined( self.team ) );
1365 
1366  while( !‪trophy_disabled() )
1367  {
1368  enemies = self GetEnemies();
1369 
1370  meleed = false;
1371 
1372  foreach( enemy in enemies )
1373  {
1374  if( enemy IsNoTarget() )
1375  {
1376  continue;
1377  }
1378 
1379  meleed = meleed || self ‪do_melee( !meleed, enemy );
1380  if ( meleed )
1381  {
1382  break;
1383  }
1384  }
1385 
1386  wait 0.3;
1387  }
1388 }
1389 
1390 
1391 function ‪quadtank_destroyturret( index )
1392 {
1393  ‪turret::disable( index );
1394 
1395  if( index == 1 )
1396  {
1397  self HidePart( "tag_gunner_barrel1" );
1398  self HidePart( "tag_gunner_turret1" );
1399  }
1400  else if( index == 2 )
1401  {
1402  self HidePart( "tag_gunner_barrel2" );
1403  self HidePart( "tag_gunner_turret2" );
1404  }
1405 }
1406 
1407 function ‪QuadtankCallback_VehicleDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal )
1408 {
1409  is_damaged_by_grenade = weapon.weapClass == "grenade";
1410 
1411  if( IsSubstr( weapon.name , "spike") )
1412  {
1413  if ( eAttacker.team !== self.team )
1414  {
1415  self.spike_hits_during_trophy_down += 1;
1416  }
1417  is_damaged_by_grenade = false;
1418  }
1419 
1420  if ( isdefined( eAttacker ) && ( eAttacker == self || isplayer( eAttacker ) && eAttacker.usingvehicle && eAttacker.viewlockedentity === self ) )
1421  {
1422  return 0;
1423  }
1424 
1425  if ( sMeansOfDeath === "MOD_MELEE" || sMeansOfDeath === "MOD_MELEE_WEAPON_BUTT" || sMeansOfDeath === "MOD_MELEE_ASSASSINATE" || sMeansOfDeath === "MOD_ELECTROCUTED" || sMeansOfDeath === "MOD_CRUSH" || weapon.isEmp )
1426  {
1427  return 0;
1428  }
1429 
1430  if ( ‪vehicle_ai::EntityIsArchetype( eAttacker, "raps" ) && !‪trophy_disabled() )
1431  {
1432  self.trophy_system_health = 0;
1433  self.trophy_disables = ‪TROPHY_DISABLE_LIMIT - 1;
1434  self thread ‪quadtank_disabletrophy();
1435 
1436  if( IsPlayer( eAttacker ) && ‪damagefeedback::doDamageFeedback( weapon, eInflictor ) )
1437  {
1438  eAttacker thread ‪damagefeedback::update( sMeansOfDeath, eInflictor );
1439  }
1440  }
1441 
1442  if ( partName == "tag_target_lower" || partName == "tag_target_upper" || partName == "tag_defense_active" || partName == "tag_body_animate" )
1443  {
1444  if( isdefined( eAttacker) && IsPlayer( eAttacker ) && eAttacker.team != self.team )
1445  {
1446  if ( !isDefined( self.trophy_system_health ) )
1447  {
1448  self.trophy_system_health = self.settings.trophySystemHealth;
1449  }
1450 
1451  //debug display information regarding damage done to weak spot
1452 // damage_amount = STR( iDamage );
1453 // trophy_health = STR( self.trophy_system_health );
1454 // damage_string = "Damage Done = " + damage_amount + " || Remaining Health = " + trophy_health;
1455 // /#
1456 // PrintTopRightln( damage_string );
1457 // #/
1458 
1459  if( !‪trophy_disabled() )
1460  {
1461  self.trophy_system_health -= iDamage;
1463 
1464  if( self.trophy_system_health <= 0 )
1465  {
1466  self thread ‪quadtank_disabletrophy();
1467  }
1468 
1469  if( IsPlayer( eAttacker ) && ‪damagefeedback::doDamageFeedback( weapon, eInflictor ) )
1470  {
1471  if ( iDamage > 0 )
1472  eAttacker thread ‪damagefeedback::update( sMeansOfDeath, eInflictor );
1473  }
1474  }
1475  }
1476  }
1477  else if ( is_damaged_by_grenade /*|| sMeansOfDeath == "MOD_EXPLOSIVE" */ )
1478  {
1479  iDamage = Int( iDamage * 3 );
1480  }
1481 
1482  // when taking damage let the turret know if it is scanning to look at our enemy
1483  // hopefully code will update our enemy
1484  self.turret_state = ‪TURRET_STATE_SCAN_AT_ENEMY;
1485  self.turretRotScale = 1.0 * self.difficulty_scale_up;
1486  self.turret_on_target = true;
1487 
1488  if( sMeansOfDeath == "MOD_RIFLE_BULLET" || sMeansOfDeath == "MOD_PISTOL_BULLET" ) // Quadtank is immune to bullets but that filtering happens later
1489  {
1490  return iDamage;
1491  }
1492 
1493  // cap the damage actors can do
1494  if( IsActor( eAttacker ) && iDamage > 250 )
1495  {
1496  iDamage = 250;
1497  }
1498 
1499  num_players = GetPlayers().size;
1500  maxDamage = self.healthdefault * ( 0.20 - 0.025 * num_players );
1501  if ( sMeansOfDeath !== "MOD_UNKNOWN" && iDamage > maxDamage )
1502  {
1503  iDamage = maxDamage;
1504  }
1505 
1506  damageLevelChanged = ‪vehicle::update_damage_fx_level( self.health, iDamage, self.healthdefault );
1507 
1508  driver = self GetSeatOccupant( 0 );
1509 
1510  if ( sMeansOfDeath != "MOD_UNKNOWN" && !‪vehicle_ai::EntityIsArchetype( eAttacker, "quadtank" ) )
1511  {
1512  if( self.damage_during_trophy_down + iDamage > self.settings.trophysystemdisablethreshold && self.trophy_disables < ‪TROPHY_DISABLE_LIMIT && !isdefined(driver) )
1513  {
1514  iDamage = max( 1, self.settings.trophysystemdisablethreshold - self.damage_during_trophy_down );
1515  }
1516 
1517  self.damage_during_trophy_down += iDamage;
1518  }
1519 
1520  if( damageLevelChanged && sMeansOfDeath != "MOD_MELEE_ASSASSINATE" && ( !isdefined(eAttacker) || eAttacker.team !== self.team ) && !isdefined( driver ) ) // no pain for player driving version
1521  {
1522  //self notify( "pain" ); // too many pains. no pain for damage state change
1523  playsoundatposition ("prj_quad_impact", self.origin);
1524  }
1525 
1526  iDamage = ‪vehicle_ai::shared_callback_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal );
1527 
1528  return iDamage;
1529 }
1530 
1531 function ‪quadtank_set_team( team )
1532 {
1533  self.team = team;
1534 
1535  if( !self ‪vehicle_ai::is_instate( "off" ) )
1536  {
1538  }
1539 }
1540 
1542 {
1543  if( isdefined( self.missile_repulsor ) )
1544  {
1545  missile_deleteattractor( self.missile_repulsor );
1546  self.missile_repulsor = undefined;
1547  }
1548  self notify( "end_repulsor_fx" );
1549 }
1550 
1551 function ‪repulsor_fx()
1552 {
1553  self notify( "end_repulsor_fx" );
1554  self endon( "end_repulsor_fx" );
1555  self endon( "death" );
1556  self endon( "change_state" );
1557 
1558  while( 1 )
1559  {
1560  self ‪util::waittill_any( "projectile_applyattractor", "play_meleefx" );
1561  if ( ‪vehicle_ai::IsCooldownReady("repulsorfx_interval") )
1562  {
1563  PlayFxOnTag( self.settings.trophyrepulsefx, self, "tag_body" );
1564 
1565  self ‪vehicle::impact_fx( self.settings.trophyrepulsefx_ground );
1566 
1567  ‪vehicle_ai::Cooldown( "repulsorfx_interval", 0.5 );
1568 
1569  self PlaySound( "wpn_quadtank_shield_impact" );
1570 
1572  }
1573  }
1574 }
1575 
1577 {
1578  if( !isdefined( self.missile_repulsor ) )
1579  {
1580  self.missile_repulsor = missile_createrepulsorent( self, 40000, self.settings.trophysystemrange, true );
1581  }
1582  self thread ‪repulsor_fx();
1583 }
1584 
1585 function ‪turn_off_laser_after( time )
1586 {
1587  self notify( "turn_off_laser_thread" );
1588  self endon( "turn_off_laser_thread" );
1589  self endon( "death" );
1590 
1591  wait time;
1592 
1593  self LaserOff();
1594 }
1595 
1596 
1597 
1598 //self = turret/vehicle
1599 function ‪side_turret_is_target_in_view_score( v_target, n_index )
1600 {
1601  s_turret = ‪turret::_get_turret_data( n_index );
1602 
1603  v_pivot_pos = self GetTagOrigin( s_turret.str_tag_pivot );
1604  v_angles_to_target = VectorToAngles( v_target - v_pivot_pos );
1605 
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];
1608 
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 );
1611 
1612  b_out_of_range = false;
1613 
1614  if ( n_ang_pitch > 0 )
1615  {
1616  if ( n_ang_pitch > s_turret.bottomarc )
1617  {
1618  b_out_of_range = true;
1619  }
1620  }
1621  else
1622  {
1623  if ( Abs( n_ang_pitch ) > s_turret.toparc )
1624  {
1625  b_out_of_range = true;
1626  }
1627  }
1628 
1629  if ( n_ang_yaw > 0 )
1630  {
1631  if ( n_ang_yaw > s_turret.leftarc )
1632  {
1633  b_out_of_range = true;
1634  }
1635  }
1636  else
1637  {
1638  if ( Abs( n_ang_yaw ) > s_turret.rightarc )
1639  {
1640  b_out_of_range = true;
1641  }
1642  }
1643 
1644  if( b_out_of_range )
1645  {
1646  return 0.0;
1647  }
1648 
1649  return ( Abs( n_ang_yaw ) / 90 * 800 );
1650 }
1651 
1652 function ‪_get_best_target_quadtank_side_turret( a_potential_targets, n_index )
1653 {
1654  takeEasyOnOneTarget = MapFloat( 0, 4, 800, 0, level.gameskill );
1655 
1656  if ( n_index === 1 )
1657  {
1658  other_turret_target = ‪turret::get_target( 2 );
1659  }
1660  else if ( n_index === 2 )
1661  {
1662  other_turret_target = ‪turret::get_target( 1 );
1663  }
1664 
1665  e_best_target = undefined;
1666  f_best_score = 100000; // lower is better
1667 
1668  s_turret = ‪turret::_get_turret_data( n_index );
1669 
1670  foreach( ‪e_target in a_potential_targets )
1671  {
1672  f_score = Distance( self.origin, ‪e_target.origin );
1673 
1674  b_current_target = ‪turret::is_target( ‪e_target, n_index );
1675 
1676  if( b_current_target )
1677  {
1678  f_score -= 100;
1679  }
1680 
1681  if( ‪e_target === self.enemy )
1682  {
1683  f_score += 300;
1684  }
1685 
1686  if ( ‪e_target === other_turret_target )
1687  {
1688  f_score += ( 100 + takeEasyOnOneTarget );
1689  }
1690 
1691  if( IsSentient( ‪e_target ) && ‪e_target AttackedRecently( self, 2 ) )
1692  {
1693  f_score -= 200;
1694  }
1695 
1696  if ( isAlive( self.lockon_owner ) && ‪e_target === self.lockon_owner )
1697  {
1698  f_score -= 1000;
1699  }
1700 
1701  v_offset = ‪turret::_get_default_target_offset( ‪e_target, n_index );
1702 
1703  view_score = ‪side_turret_is_target_in_view_score( ‪e_target.origin + v_offset, n_index );
1704 
1705  if( view_score != 0.0 )
1706  {
1707  f_score += view_score;
1708 
1709  b_trace_passed = ‪turret::trace_test( ‪e_target, v_offset, n_index );
1710 
1711  if ( b_current_target && !b_trace_passed && !isdefined( s_turret.n_time_lose_sight ) )
1712  {
1713  s_turret.n_time_lose_sight = GetTime();
1714  }
1715 
1716  if( b_trace_passed )
1717  {
1718  f_score -= 500;
1719  }
1720  }
1721  else if ( b_current_target )
1722  {
1723  s_turret.b_target_out_of_range = true;
1724  f_score += 5000;
1725  }
1726 
1727  if( f_score < f_best_score )
1728  {
1729  f_best_score = f_score;
1730  e_best_target = ‪e_target;
1731  }
1732  }
1733 
1734  return e_best_target;
1735 }
1736 
1738 {
1739  if( ‪IS_TRUE( self.displayweakpoint ) )
1740  {
1741  self globallogic_ui::triggerWeakpointDamage( &‪WEAKSPOT_BONE_NAME );
1742  }
1743 }
1744 
1746 {
1747  if( self.displayweakpoint !== state )
1748  {
1749  self.displayweakpoint = state;
1750 
1751  if( !self.displayweakpoint && self.weakpointobjective === 1 )
1752  {
1753  self.weakpointobjective = 0;
1754  self globallogic_ui::destroyWeakpointWidget( &‪WEAKSPOT_BONE_NAME );
1755  }
1756 
1757  player = level.players[0];
1758  if( self.displayweakpoint && self.combatactive && self.weakpointobjective !== 1 && ( !isdefined( player ) || player.team !== self.team ) )
1759  {
1760  self.weakpointobjective = 1;
1761  self globallogic_ui::createWeakpointWidget( &‪WEAKSPOT_BONE_NAME );
1762  }
1763  }
1764 }
1765 
1767 {
1768  self endon( "death" );
1769  self endon( "exit_vehicle" );
1770 
1771  while( 1 )
1772  {
1773  note = self ‪util::waittill_any_return( "footstep_front_left", "footstep_front_right", "footstep_rear_left", "footstep_rear_right" );
1774 
1775  switch( note )
1776  {
1777  case "footstep_front_left":
1778  {
1779  bone = "tag_foot_fx_left_front";
1780  break;
1781  }
1782  case "footstep_front_right":
1783  {
1784  bone = "tag_foot_fx_right_front";
1785  break;
1786  }
1787  case "footstep_rear_left":
1788  {
1789  bone = "tag_foot_fx_left_back";
1790  break;
1791  }
1792  case "footstep_rear_right":
1793  {
1794  bone = "tag_foot_fx_right_back";
1795  break;
1796  }
1797  }
1798 
1799  position = self GetTagOrigin( bone ) + (0,0,15);
1800 
1801  self RadiusDamage( position, 60, 50, 50, self, "MOD_CRUSH" );
1802  }
1803 }
1804 
1805 function ‪javeline_incoming(projectile)
1806 {
1807  self endon( "entityshutdown" );
1808  self endon ("death");
1809 
1810  self waittill( "weapon_fired", projectile );
1811 
1812  distance = 1400;
1813  alias = "prj_quadtank_javelin_incoming";
1814 
1815  wait(5);
1816 
1817  if(!isdefined( projectile ) )
1818  return;
1819 
1820  while(isdefined(projectile) && isdefined( projectile.origin ))
1821  {
1822  if ( isdefined( self.enemy ) && isdefined( self.enemy.origin ))
1823  {
1824  projectileDistance = DistanceSquared( projectile.origin, self.enemy.origin);
1825 
1826  if( projectileDistance <= distance * distance )
1827  {
1828  projectile playsound (alias);
1829  return;
1830  }
1831  }
1832 
1833  wait (.2);
1834  }
1835 }
1836 
1837 function ‪railgun_sound(projectile)
1838 {
1839  self endon( "entityshutdown" );
1840  self endon ("death");
1841 
1842  self waittill( "weapon_fired", projectile );
1843 
1844  distance = 900;
1845  alais = "wpn_quadtank_railgun_fire_rocket_flux";
1846  players = level.players;
1847 
1848  while(isdefined(projectile) && isdefined( projectile.origin ))
1849  {
1850  if ( isdefined( players[0] ) && isdefined( players[0].origin ))
1851  {
1852  projectileDistance = DistanceSquared( projectile.origin, players[0].origin);
1853 
1854  if( projectileDistance <= distance * distance )
1855  {
1856  projectile playsound (alais);
1857  return;
1858  }
1859  }
1860 
1861  wait (.2);
1862  }
1863 
1864 }
1865 
1866 
‪footstep_handler
‪function footstep_handler()
Definition: _quadtank.gsc:1655
‪quadtank_update_difficulty
‪function quadtank_update_difficulty()
Definition: _quadtank.gsc:158
‪call_custom_add_state_callbacks
‪function call_custom_add_state_callbacks()
Definition: vehicle_ai_shared.gsc:1152
‪trophy_disabled
‪function trophy_disabled()
Definition: _quadtank.gsc:531
‪set_death_model
‪function set_death_model(sModel, fDelay)
Definition: vehicle_death_shared.gsc:258
‪state_driving_update
‪function state_driving_update(params)
Definition: _quadtank.gsc:353
‪enable
‪function enable(handler)
Definition: _perplayer.gsc:54
‪is_target
‪function is_target(e_target, n_index)
Definition: turret_shared.gsc:769
‪repulsor_fx
‪function repulsor_fx()
Definition: _quadtank.gsc:1452
‪set_state
‪function set_state(name, state_params)
Definition: statemachine_shared.gsc:133
‪evaluate_connections
‪function evaluate_connections(eval_func, params)
Definition: statemachine_shared.gsc:266
‪e_target
‪var e_target
Definition: traps_shared.gsc:2029
‪quadtank_disabletrophy
‪function quadtank_disabletrophy()
Definition: _quadtank.gsc:555
‪_get_default_target_offset
‪function _get_default_target_offset(e_target, n_index)
Definition: turret_shared.gsc:703
‪quadtank_weakpoint_display
‪function quadtank_weakpoint_display(state)
Definition: _quadtank.gsc:1636
‪state_combat_exit
‪function state_combat_exit(params)
Definition: _quadtank.gsc:426
‪do_melee
‪function do_melee(shouldDoDamage, enemy)
Definition: _quadtank.gsc:1288
‪state_off_enter
‪function state_off_enter(params)
Definition: _quadtank.gsc:227
‪bootup
‪function bootup()
Definition: _quadtank.gsc:265
‪set_damage_fx_level
‪function set_damage_fx_level(damage_level)
Definition: vehicle_shared.gsc:3012
‪toggle_tread_fx
‪function toggle_tread_fx(on)
Definition: vehicle_shared.gsc:3357
‪IsCooldownReady
‪function IsCooldownReady(name, timeForward_seconds)
Definition: vehicle_ai_shared.gsc:1968
‪InitThreatBias
‪function InitThreatBias()
Definition: vehicle_ai_shared.gsc:60
‪_get_best_target_quadtank_side_turret
‪function _get_best_target_quadtank_side_turret(a_potential_targets, n_index)
Definition: _quadtank.gsc:1551
‪get_current_state
‪function get_current_state()
Definition: vehicle_ai_shared.gsc:960
‪set_to_player
‪function set_to_player(str_field_name, n_value)
Definition: clientfield_shared.gsc:58
‪SetTurretTarget
‪function SetTurretTarget(target, turretIdx=0, offset=(0, 0, 0))
Definition: vehicle_ai_shared.gsc:277
‪SCAN_HEIGHT_OFFSET
‪#define SCAN_HEIGHT_OFFSET
Definition: _quadtank.gsc:33
‪TurnOffAllLightsAndLaser
‪function TurnOffAllLightsAndLaser()
Definition: vehicle_ai_shared.gsc:678
‪WEAPON_STRAIGHT
‪#define WEAPON_STRAIGHT
Definition: _quadtank.gsc:54
‪PositionQuery_Filter_Random
‪function PositionQuery_Filter_Random(queryResult, min, max)
Definition: vehicle_ai_shared.gsc:2088
‪NEAR_GOAL_DIST
‪#define NEAR_GOAL_DIST
Definition: _quadtank.gsc:57
‪quadtank_on
‪function quadtank_on()
Definition: _quadtank.gsc:221
‪Javelin_LoseTargetAtRightTime
‪function Javelin_LoseTargetAtRightTime(target)
Definition: vehicle_ai_shared.gsc:314
‪quadtank_projectile_watcher
‪function quadtank_projectile_watcher()
Definition: _quadtank.gsc:1475
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪waittill_any_return
‪function waittill_any_return(string1, string2, string3, string4, string5, string6, string7)
Definition: util_shared.csc:212
‪Attack_Thread_rocket
‪function Attack_Thread_rocket()
Definition: _quadtank.gsc:959
‪toggle_exhaust_fx
‪function toggle_exhaust_fx(on)
Definition: vehicle_shared.gsc:3335
‪set_side_turrets_enabled
‪function set_side_turrets_enabled(on)
Definition: _quadtank.gsc:771
‪VAL
‪#define VAL(__var, __default)
Definition: shared.gsh:272
‪remove_repulsor
‪function remove_repulsor()
Definition: _quadtank.gsc:1442
‪quadtank_initialize
‪function quadtank_initialize()
Definition: _quadtank.gsc:76
‪TURRET_STATE_SCAN_RIGHT
‪#define TURRET_STATE_SCAN_RIGHT
Definition: _quadtank.gsc:37
‪update_damage_fx_level
‪function update_damage_fx_level(currentHealth, damage, maxHealth)
Definition: vehicle_shared.gsc:2999
‪trace_test
‪function trace_test(e_target, v_offset=(0, 0, 0), n_index)
Definition: turret_shared.gsc:2535
‪state_off_exit
‪function state_off_exit(params)
Definition: _quadtank.gsc:255
‪waittill_any_timeout
‪function waittill_any_timeout(n_timeout, string1, string2, string3, string4, string5)
Definition: util_shared.csc:423
‪quadtank_set_team
‪function quadtank_set_team(team)
Definition: _quadtank.gsc:1432
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪WEAKSPOT_BONE_NAME
‪#define WEAKSPOT_BONE_NAME
Definition: _quadtank.gsc:63
‪set_burst_parameters
‪function set_burst_parameters(n_fire_min, n_fire_max, n_wait_min, n_wait_max, n_index)
Definition: turret_shared.gsc:609
‪turn_off_laser_after
‪function turn_off_laser_after(time)
Definition: _quadtank.gsc:1484
‪TURRET_STATE_SCAN_AT_ENEMY
‪#define TURRET_STATE_SCAN_AT_ENEMY
Definition: _quadtank.gsc:35
‪SQR
‪#define SQR(__var)
Definition: shared.gsh:293
‪ROCKET_LAUNCHER_MIN_DIST
‪#define ROCKET_LAUNCHER_MIN_DIST
Definition: _quadtank.gsc:51
‪disable
‪function disable(handler)
Definition: _perplayer.gsc:79
‪is_instate
‪function is_instate(statename)
Definition: vehicle_ai_shared.gsc:994
‪show_weak_spots
‪function show_weak_spots(show)
Definition: _quadtank.gsc:785
‪get_next_state
‪function get_next_state()
Definition: vehicle_ai_shared.gsc:982
‪set_trophy_state
‪function set_trophy_state(isOn)
Definition: _quadtank.gsc:558
‪death_radius_damage
‪function death_radius_damage(meansOfDamage="MOD_EXPLOSIVE")
Definition: vehicle_death_shared.gsc:1196
‪shared_callback_damage
‪function shared_callback_damage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal)
Definition: vehicle_ai_shared.gsc:726
‪WEAPON_JAVELIN
‪#define WEAPON_JAVELIN
Definition: _quadtank.gsc:53
‪StartInitialState
‪function StartInitialState(defaultState="combat")
Definition: vehicle_ai_shared.gsc:866
‪CanSeeEnemyFromPosition
‪function CanSeeEnemyFromPosition(position, enemy, sight_check_height)
Definition: vehicle_ai_shared.gsc:1815
‪impact_fx
‪function impact_fx(fxname, surfaceTypes)
Definition: vehicle_shared.gsc:2765
‪quadtank_enabletrophy
‪function quadtank_enabletrophy()
Definition: _quadtank.gsc:639
‪MELEE_OUTER_RADIUS_DAMAGE
‪#define MELEE_OUTER_RADIUS_DAMAGE
Definition: _quadtank.gsc:49
‪FreeWhenSafe
‪function FreeWhenSafe(time=4)
Definition: vehicle_death_shared.gsc:1756
‪railgun_sound
‪function railgun_sound(projectile)
Definition: _quadtank.gsc:1726
‪JAVELIN_MIN_USE_DISTANCE
‪#define JAVELIN_MIN_USE_DISTANCE
Definition: _quadtank.gsc:55
‪_init_turret
‪function _init_turret(n_index=0)
Definition: turret_shared.gsc:1773
‪quadtank_destroyturret
‪function quadtank_destroyturret(index)
Definition: _quadtank.gsc:1376
‪set_best_target_func
‪function set_best_target_func(func_get_best_target, n_index)
Definition: turret_shared.gsc:1871
‪TurnOffAllAmbientAnims
‪function TurnOffAllAmbientAnims()
Definition: vehicle_ai_shared.gsc:690
‪Cooldown
‪function Cooldown(name, time_seconds)
Definition: vehicle_ai_shared.gsc:1943
‪init_state_machine_for_role
‪function init_state_machine_for_role(rolename)
Definition: vehicle_ai_shared.gsc:1034
‪PositionQuery_DebugScores
‪function PositionQuery_DebugScores(queryResult)
Definition: vehicle_ai_shared.gsc:2010
‪pain_update
‪function pain_update(params)
Definition: _quadtank.gsc:289
‪waittill_any
‪function waittill_any(str_notify1, str_notify2, str_notify3, str_notify4, str_notify5)
Definition: util_shared.csc:375
‪quadtank_weakpoint_trigger
‪function quadtank_weakpoint_trigger()
Definition: _quadtank.gsc:1737
‪doDamageFeedback
‪function doDamageFeedback(weapon, eInflictor, iDamage, sMeansOfDeath)
Definition: damagefeedback_shared.gsc:423
‪quadtank_player_fireupdate
‪function quadtank_player_fireupdate()
Definition: _quadtank.gsc:1269
‪PositionQuery_PostProcess_SortScore
‪function PositionQuery_PostProcess_SortScore(queryResult, descending=true)
Definition: vehicle_ai_shared.gsc:2097
‪quadtank_side_turrets_forward
‪function quadtank_side_turrets_forward()
Definition: _quadtank.gsc:709
‪javeline_incoming
‪function javeline_incoming(projectile)
Definition: _quadtank.gsc:1694
‪PositionQuery_Filter_OutOfGoalAnchor
‪function PositionQuery_Filter_OutOfGoalAnchor(queryResult, tolerance=1)
Definition: vehicle_ai_shared.gsc:2104
‪ClearCooldown
‪function ClearCooldown(name)
Definition: vehicle_ai_shared.gsc:1981
‪quadtank_weapon_think_cannon
‪function quadtank_weapon_think_cannon()
Definition: _quadtank.gsc:821
‪quadtank_movementupdate
‪function quadtank_movementupdate()
Definition: _quadtank.gsc:1211
‪REGISTER_SYSTEM
‪#define REGISTER_SYSTEM(__sys, __func_init_preload, __reqs)
Definition: shared.gsh:204
‪blink_lights_for_time
‪function blink_lights_for_time(time)
Definition: vehicle_ai_shared.gsc:648
‪__init__
‪function __init__()
Definition: _quadtank.gsc:68
‪TURRET_STATE_SCAN_FORWARD2
‪#define TURRET_STATE_SCAN_FORWARD2
Definition: _quadtank.gsc:38
‪TURRET_STATE_SCAN_FORWARD
‪#define TURRET_STATE_SCAN_FORWARD
Definition: _quadtank.gsc:36
‪emped
‪function emped(down_time)
Definition: _siegebot.gsc:1359
‪Spawn
‪function Spawn(parent, onDeathCallback)
Definition: _flak_drone.gsc:427
‪quadtank_exit_vehicle
‪function quadtank_exit_vehicle()
Definition: _quadtank.gsc:382
‪Movement_Thread_Wander
‪function Movement_Thread_Wander()
Definition: _quadtank.gsc:1118
‪quadtank_off
‪function quadtank_off()
Definition: _quadtank.gsc:215
‪defaultRole
‪function defaultRole()
Definition: _quadtank.gsc:189
‪target_hijackers
‪function target_hijackers()
Definition: vehicle_ai_shared.gsc:2312
‪waittill_asm_complete
‪function waittill_asm_complete(substate_to_wait, timeout=10)
Definition: vehicle_ai_shared.gsc:374
‪_get_turret_data
‪function _get_turret_data(n_index)
Definition: turret_shared.gsc:1725
‪quadtank_turret_scan
‪function quadtank_turret_scan(scan_forever)
Definition: _quadtank.gsc:717
‪GetCooldownLeft
‪function GetCooldownLeft(name)
Definition: vehicle_ai_shared.gsc:1961
‪QuadtankCallback_VehicleDamage
‪function QuadtankCallback_VehicleDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal)
Definition: _quadtank.gsc:1408
‪RegisterVehicleBlackBoardAttributes
‪function RegisterVehicleBlackBoardAttributes()
Definition: blackboard_vehicle.gsc:24
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪get_target
‪function get_target(n_index)
Definition: turret_shared.gsc:760
‪TROPHY_DISABLE_LIMIT
‪#define TROPHY_DISABLE_LIMIT
Definition: _quadtank.gsc:43
‪state_combat_update
‪function state_combat_update(params)
Definition: _quadtank.gsc:391
‪path_update_interrupt
‪function path_update_interrupt()
Definition: _quadtank.gsc:1068
‪CreateBlackBoardForEntity
‪function CreateBlackBoardForEntity(entity)
Definition: blackboard.gsc:77
‪player_is_in_laststand
‪function player_is_in_laststand()
Definition: laststand_shared.gsc:18
‪CleanUp
‪function CleanUp()
Definition: vehicle_death_shared.gsc:1795
‪side_turret_is_target_in_view_score
‪function side_turret_is_target_in_view_score(v_target, n_index)
Definition: _quadtank.gsc:1498
‪NUM_TURRET_STATES
‪#define NUM_TURRET_STATES
Definition: _quadtank.gsc:40
‪quadtank_automelee_update
‪function quadtank_automelee_update()
Definition: _quadtank.gsc:1345
‪EntityIsArchetype
‪function EntityIsArchetype(entity, archetype)
Definition: vehicle_ai_shared.gsc:83
‪update
‪function update()
Definition: _serversettings.gsc:71
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪FLAT_ORIGIN
‪#define FLAT_ORIGIN(__origin)
Definition: shared.gsh:256
‪get_script_bundle
‪function get_script_bundle(str_type, str_name)
Definition: struct.csc:45
‪trophy_destroyed
‪function trophy_destroyed()
Definition: _quadtank.gsc:546
‪MELEE_RADIUS
‪#define MELEE_RADIUS
Definition: _quadtank.gsc:47
‪trigger_player_shock_fx
‪function trigger_player_shock_fx()
Definition: _quadtank.gsc:1057
‪toggle_sounds
‪function toggle_sounds(on)
Definition: vehicle_shared.gsc:3379
‪state_scripted_update
‪function state_scripted_update(params)
Definition: _quadtank.gsc:335
‪quadtank_death
‪function quadtank_death(params)
Definition: _quadtank.gsc:438
‪result
‪function result(death, attacker, mod, weapon)
Definition: _zm_aat_blast_furnace.gsc:46
‪quadtank_emped
‪function quadtank_emped(params)
Definition: _quadtank.gsc:488
‪lights_on
‪function lights_on(localClientNum, team)
Definition: vehicle_shared.csc:404
‪MELEE_INNER_RADIUS_DAMAGE
‪#define MELEE_INNER_RADIUS_DAMAGE
Definition: _quadtank.gsc:48
‪set_detonation_time
‪function set_detonation_time(target)
Definition: _quadtank.gsc:797
‪FindNewPosition
‪function FindNewPosition(sight_check_height)
Definition: vehicle_ai_shared.gsc:1821
‪SPIKE_HIT_LIMIT
‪#define SPIKE_HIT_LIMIT
Definition: _quadtank.gsc:45
‪toggle_ambient_anim_group
‪function toggle_ambient_anim_group(groupID, on)
Definition: vehicle_shared.gsc:2844
‪get_state_callbacks
‪function get_state_callbacks(statename)
Definition: vehicle_ai_shared.gsc:927
‪TURRET_STATE_SCAN_LEFT
‪#define TURRET_STATE_SCAN_LEFT
Definition: _quadtank.gsc:39