‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
archetype_thrasher.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\ai_shared;
4 #using scripts\shared\array_shared;
5 #using scripts\shared\callbacks_shared;
6 #using scripts\shared\clientfield_shared;
7 #using scripts\shared\fx_shared;
8 #using scripts\shared\laststand_shared;
9 #using scripts\shared\lui_shared;
10 #using scripts\shared\math_shared;
11 #using scripts\shared\scene_shared;
12 #using scripts\shared\spawner_shared;
13 #using scripts\shared\system_shared;
14 #using scripts\shared\util_shared;
15 #using scripts\shared\visionset_mgr_shared;
16 
17 #using scripts\shared\ai\systems\ai_interface;
18 #using scripts\shared\ai\systems\animation_state_machine_utility;
19 #using scripts\shared\ai\systems\animation_state_machine_notetracks;
20 #using scripts\shared\ai\systems\animation_state_machine_mocomp;
21 #using scripts\shared\ai\archetype_utility;
22 #using scripts\shared\ai\systems\behavior_tree_utility;
23 #using scripts\shared\ai\systems\blackboard;
24 #using scripts\shared\ai\systems\debug;
25 #using scripts\shared\ai\systems\gib;
26 #using scripts\shared\ai\zombie_utility;
27 #using scripts\shared\ai\archetype_locomotion_utility;
28 #using scripts\shared\ai\archetype_mocomps_utility;
29 #using scripts\shared\ai\archetype_thrasher_interface;
30 
31 #using scripts\shared\weapons\_weaponobjects;
32 
33 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
34 #insert scripts\shared\ai\systems\animation_state_machine.gsh;
35 #insert scripts\shared\ai\systems\behavior.gsh;
36 #insert scripts\shared\ai\systems\behavior_tree.gsh;
37 #insert scripts\shared\ai\systems\blackboard.gsh;
38 #insert scripts\shared\ai\systems\gib.gsh;
39 #insert scripts\shared\ai\archetype_thrasher.gsh;
40 #insert scripts\shared\ai\utility.gsh;
41 #insert scripts\shared\shared.gsh;
42 #insert scripts\shared\version.gsh;
43 
44 #define N_THRASHER_CHARGE_HEALTH_THRESHOLD_PCT 0.6 //how low health has to be before Thrasher can start charging
45 
46 #namespace ThrasherBehavior;
47 
48 ‪REGISTER_SYSTEM( "thrasher", &‪__init__, undefined )
49 
50 function ‪__init__()
51 {
53 
54  // INIT BEHAVIORS
56 
57  // INIT BLACKBOARD
59 
60  // INIT THRASHER ON SPAWN
62 
64  {
67 
68  ‪clientfield::register( "actor", "thrasher_player_hide", ‪VERSION_TU8, 4, "int" ); // Leave at VERSION_TU8
69  ‪clientfield::register( "toplayer", "sndPlayerConsumed", ‪VERSION_TU10, 1, "int" ); // Leave at VERSION_TU10
70 
71  foreach ( spore in ‪THRASHER_SPORE_CF_SPORES )
72  {
74  "actor",
76  ‪VERSION_TU8, // Leave at VERSION_TU8
79  }
80  }
81 
83 }
84 
86 {
87  // SERVICES
91  ‪BT_REGISTER_API( "thrasherAttackableObjectService", &‪ThrasherBehavior::thrasherAttackableObjectService );
92 
93  // CONDITIONS
100  ‪BT_REGISTER_API( "thrasherShouldConsumeZombie", &‪ThrasherBehavior::thrasherShouldConsumeZombie );
101 
102  // ACTIONS
111 
112  // FUNCTIONS
115 
116  // MOCOMPS
117 
118  // NOTETRACKS
120 }
121 
123 {
124  entity = self;
125 
126  // CREATE BLACKBOARD
128 
129  // USE UTILITY BLACKBOARD
131 
132  // CREATE INTERFACE
134 
135  // CREATE THRASHER BLACKBOARD
136  thrasher_speed = ‪LOCOMOTION_SPEED_WALK;
137  if( entity.thrasherHasTurnedBerserk === true )
138  {
139  thrasher_speed = ‪LOCOMOTION_SPEED_RUN;
140  }
141  ‪BB_REGISTER_ATTRIBUTE( ‪LOCOMOTION_SPEED_TYPE, thrasher_speed, undefined );
144 
145  // REGISTER ANIMSCRIPTED CALLBACK
146  entity.___ArchetypeOnAnimscriptedCallback = &‪ArchetypeThrasherOnAnimscriptedCallback;
147 
148  // ENABLE DEBUGGING IN ODYSSEY
150 }
151 
153 {
154  // UNREGISTER THE BLACKBOARD
155  entity.__blackboard = undefined;
156 
157  // REREGISTER BLACKBOARD
159 }
160 
161 function private ‪thrasherSpawnSetup()
162 {
163  entity = self;
164 
165  entity.health = ‪THRASHER_TOTAL_HEALTH;
166  entity.maxHealth = entity.health;
167  entity.thrasherConsumedPlayer = false;
168 
169  // Berserk
170  entity.thrasherIsBerserk = false;
171  entity.thrasherHasTurnedBerserk = false;
172 
173  entity.thrasherHeadHealth = ‪THRASHER_HEAD_HEALTH;
174 
175  // Consume Zombies
176  entity.thrasherLastConsume = GetTime();
177  entity.thrasherConsumeCooldown = ‪THRASHER_CONSUME_COOLDOWN;
178  entity.thrasherConsumeCount = 0;
179  entity.thrasherConsumeMax = ‪THRASHER_CONSUME_MAX;
180 
181  // Teleport
182  entity.thrasherLastTeleportTime = GetTime();
183 
184  // Stunned
185  entity.thrasherStunHealth = ‪THRASHER_STUN_HEALTH;
186 
187  // Rage
188  entity.thrasherRageCount = 0;
189  entity.thrasherRageLevel = 1;
190 
191  // entity SetAvoidanceMask( "avoid none" );
192 
193  // Spores
195 
196  // Spikes
198 
199  AiUtility::AddAiOverrideDamageCallback( entity, &‪ThrasherServerUtils::thrasherDamageCallback );
200 }
201 
202 function private ‪BB_GetShouldTurn()
203 {
204  entity = self;
205 
206  if ( IsDefined( entity.should_turn ) && entity.should_turn )
207  {
208  return ‪SHOULD_TURN;
209  }
210  return ‪SHOULD_NOT_TURN;
211 }
212 
213 function private ‪thrasherInitSpores()
214 {
215  entity = self;
216 
217  assert( ‪THRASHER_SPORES.size == ‪THRASHER_SPORE_CF_SPORES.size );
218 
219  thrasherSpores = ‪THRASHER_SPORES;
220  thrasherSporeDamageDists = ‪THRASHER_SPORE_DAMAGE_DISTS;
221  thrasherClientfields = ‪THRASHER_SPORE_CF_SPORES;
222  entity.thrasherSpores = [];
223 
224  for ( index = 0; index < ‪THRASHER_SPORES.size; index++ )
225  {
226  sporeStruct = SpawnStruct();
227 
228  sporeStruct.dist = thrasherSporeDamageDists[ index ];
229  sporeStruct.health = ‪THRASHER_PUSTULE_HEALTH;
230  sporeStruct.maxhealth = sporeStruct.health;
231  sporeStruct.state = ‪THRASHER_SPORE_STATE_HEALTHY;
232  sporeStruct.tag = thrasherSpores[ index ];
233  sporeStruct.clientfield = thrasherClientfields[ index ];
234 
235  entity.thrasherSpores[ index ] = sporeStruct;
236  }
237 }
238 
239 //----------------------------------------------------------------------------------------------------------------------------
240 // NOTETRACK HANDLERS
241 //----------------------------------------------------------------------------------------------------------------------------
242 function private ‪thrasherNotetrackMelee( entity )
243 {
244  if( isDefined( entity.thrasher_melee_knockdown_function ))
245  {
246  entity thread [[ entity.thrasher_melee_knockdown_function ]]();
247  }
248 
249  hitEntity = entity Melee();
250 
251  if ( IsDefined( hitEntity ) && IsDefined( entity.thrasherMeleeHitCallback ) )
252  {
253  entity thread [[ entity.thrasherMeleeHitCallback ]]( hitEntity );
254  }
255 
256  if ( ‪AiUtility::shouldAttackObject( entity ) )
257  {
258  if ( IsDefined( level.attackableCallback ) )
259  {
260  entity.attackable [[ level.attackableCallback ]]( entity );
261  }
262  }
263 }
264 
265 //----------------------------------------------------------------------------------------------------------------------------
266 // BEHAVIOR TREE
267 //----------------------------------------------------------------------------------------------------------------------------
268 function private ‪thrasherGetClosestLaststandPlayer( entity )
269 {
270  if ( entity.thrasherConsumedPlayer )
271  {
272  return;
273  }
274 
275  maxConsumeDistanceSq = ‪SQR( ‪THRASHER_CONSUME_PLAYER_DISTANCE );
276 
277  targets = GetPlayers();
278 
279  // Don't consume single players
280  if ( targets.size == 1 )
281  {
282  return;
283  }
284 
285  laststandTargets = [];
286 
287  foreach ( target in targets )
288  {
289  if ( !IsDefined( target.laststandStartTime ) ||
290  ( target.laststandStartTime + ‪THRASHER_LASTSTAND_SAFETY ) > GetTime() )
291  {
292  // At least THRASHER_LASTSTAND_SAFETY time must pass before targeting.
293  continue;
294  }
295 
296  if ( IsDefined( target.thrasherFreedTime ) &&
297  ( target.thrasherFreedTime + ‪THRASHER_FREED_SAFETY ) > GetTime() )
298  {
299  // At least THRASHER_FREED_SAFETY time must pass before targeting.
300  continue;
301  }
302 
303  if ( target ‪laststand::player_is_in_laststand() &&
304  !‪IS_TRUE( target.thrasherConsumed ) &&
305  DistanceSquared( target.origin, entity.origin ) <= maxConsumeDistanceSq )
306  {
307  laststandTargets[ laststandTargets.size ] = target;
308  }
309  }
310 
311  if ( laststandTargets.size > 0 )
312  {
313  sortedPotentialTargets = ArraySortClosest( laststandTargets, entity.origin );
314 
315  return sortedPotentialTargets[0];
316  }
317 }
318 
319 function private ‪thrasherRageService( entity )
320 {
321  entity.thrasherRageCount += entity.thrasherRageLevel * ‪THRASHER_RAGE_AUTO_MULTIPLIER + ‪THRASHER_RAGE_AUTO;
322 
323  if ( entity.thrasherRageCount >= ‪THRASHER_RAGE_THRESHOLD )
324  {
326  }
327 }
328 
329 function private ‪thrasherTargetService( entity )
330 {
331  if ( ‪IS_TRUE( entity.ignoreall ) )
332  {
333  return false;
334  }
335 
336  if ( entity ‪ai::get_behavior_attribute( "move_mode" ) == "friendly" )
337  {
338  if ( IsDefined( entity.thrasherMoveModeFriendlyCallback ) )
339  {
340  entity [[ entity.thrasherMoveModeFriendlyCallback ]]();
341  }
342 
343  return true;
344  }
345 
346  laststandPlayer = ‪thrasherGetClosestLaststandPlayer( entity );
347 
348  if ( IsDefined( laststandPlayer ) )
349  {
350  entity.favoriteenemy = laststandPlayer;
351  entity SetGoal( entity.favoriteenemy.origin );
352 
353  return true;
354  }
355 
356  entity.ignore_player = [];
357  players = GetPlayers();
358 
359  foreach ( player in players )
360  {
361  if ( player IsNoTarget() ||
362  player.ignoreme ||
364  ‪IS_TRUE( player.thrasherConsumed ) )
365  {
366  entity.ignore_player[ entity.ignore_player.size ] = player;
367  }
368  }
369 
370  player = undefined;
371 
372  if ( IsDefined( entity.thrasherClosestValidPlayer ) )
373  {
374  player = [[ entity.thrasherClosestValidPlayer ]]( entity.origin, entity.ignore_player );
375  }
376  else
377  {
378  player = ‪zombie_utility::get_closest_valid_player( entity.origin, entity.ignore_player );
379  }
380 
381  entity.favoriteenemy = player;
382 
383  if( !IsDefined( player ) || player IsNoTarget() )
384  {
385  if( IsDefined( entity.ignore_player ) )
386  {
387  if( IsDefined(level._should_skip_ignore_player_logic) && [[level._should_skip_ignore_player_logic]]() )
388  {
389  return;
390  }
391  entity.ignore_player = [];
392  }
393 
394  entity SetGoal( entity.origin );
395  return false;
396  }
397  else if ( IsDefined( entity.attackable ) )
398  {
399  if ( IsDefined( entity.attackable_slot ) )
400  {
401  entity SetGoal( entity.attackable_slot.origin, true );
402  }
403  }
404  else
405  {
406  targetPos = GetClosestPointOnNavMesh( player.origin, ‪THRASHER_NAVMESH_RADIUS, ‪THRASHER_NAVMESH_BOUNDARY_DIST );
407  if ( IsDefined( targetPos ) )
408  {
409  entity SetGoal( targetPos );
410  return true;
411  }
412  else
413  {
414  entity SetGoal( entity.origin );
415  return false;
416  }
417  }
418 }
419 
420 function private ‪thrasherAttackableObjectService( entity )
421 {
422  if ( IsDefined( entity.thrasherAttackableObjectCallback ) )
423  {
424  return [[ entity.thrasherAttackableObjectCallback ]]( entity );
425  }
426 
427  return false;
428 }
429 
430 function private ‪thrasherKnockdownService( entity )
431 {
432  velocity = entity GetVelocity();
433  predict_time = 0.3;
434  predicted_pos = entity.origin + ( velocity * predict_time );
435  move_dist_sq = DistanceSquared( predicted_pos, entity.origin );
436  speed = move_dist_sq / predict_time;
437 
438  if( speed >= 10 )
439  {
440  a_zombies = GetAIArchetypeArray( ‪ARCHETYPE_ZOMBIE );
441 
442  a_filtered_zombies = array::filter( a_zombies, false, &‪thrasherZombieEligibleForKnockdown, entity, predicted_pos );
443 
444  if( a_filtered_zombies.size > 0 )
445  {
446  foreach( zombie in a_filtered_zombies )
447  {
449  }
450  }
451  }
452 }
453 
454 function private ‪thrasherZombieEligibleForKnockdown( zombie, thrasher, predicted_pos )
455 {
456  if( zombie.knockdown === true )
457  {
458  return false;
459  }
460 
461  knockdown_dist_sq = 48*48;
462 
463  dist_sq = DistanceSquared( predicted_pos, zombie.origin );
464 
465  if( dist_sq > knockdown_dist_sq )
466  {
467  return false;
468  }
469 
470  origin = thrasher.origin;
471 
472  facing_vec = AnglesToForward( thrasher.angles );
473  enemy_vec = zombie.origin - origin;
474 
475  enemy_yaw_vec = (enemy_vec[0], enemy_vec[1], 0);
476  facing_yaw_vec = (facing_vec[0], facing_vec[1], 0);
477 
478  enemy_yaw_vec = VectorNormalize( enemy_yaw_vec );
479  facing_yaw_vec = VectorNormalize( facing_yaw_vec );
480 
481  enemy_dot = VectorDot( facing_yaw_vec, enemy_yaw_vec );
482 
483  if( enemy_dot < 0 )// is enemy behind thrasher
484  {
485  return false;
486  }
487 
488  return true;
489 
490 }
491 
492 //----------------------------------------------------------------------------------------------------------------------------------
493 // CONDITIONS
494 //----------------------------------------------------------------------------------------------------------------------------------
495 function ‪thrasherShouldMelee( entity )
496 {
497  if( !IsDefined( entity.favoriteenemy ) )
498  {
499  return false;
500  }
501 
502  if( DistanceSquared( entity.origin, entity.favoriteenemy.origin ) > ‪THRASHER_MELEE_DIST_SQ )
503  {
504  return false;
505  }
506 
507  if ( entity.favoriteenemy IsNoTarget() )
508  {
509  return false;
510  }
511 
512  yaw = abs( zombie_utility::getYawToEnemy() );
513  if( ( yaw > ‪THRASHER_MELEE_YAW ) )
514  {
515  return false;
516  }
517 
518  if ( entity.favoriteenemy ‪laststand::player_is_in_laststand() )
519  {
520  return false;
521  }
522 
523  return true;
524 }
525 
526 function private ‪thrasherShouldShowPain( entity )
527 {
528  return false;
529 }
530 
531 function private ‪thrasherShouldTurnBerserk( entity )
532 {
533  return entity.thrasherIsBerserk && !entity.thrasherHasTurnedBerserk;
534 }
535 
536 function private ‪thrasherShouldTeleport( entity )
537 {
538  if ( !IsDefined( entity.favoriteenemy ) )
539  {
540  return false;
541  }
542 
543  if ( ( entity.thrasherLastTeleportTime + ‪THRASHER_TELEPORT_COOLDOWN ) > GetTime() )
544  {
545  return false;
546  }
547 
548  if ( DistanceSquared( entity.origin, entity.favoriteenemy.origin ) >= ‪THRASHER_TELERPOT_MIN_DISTANCE_SQ )
549  {
550  if ( IsDefined( entity.thrasherShouldTeleportCallback ) )
551  {
552  return ( [[ entity.thrasherShouldTeleportCallback ]]( entity.origin ) &&
553  [[ entity.thrasherShouldTeleportCallback ]]( entity.favoriteenemy.origin ) );
554  }
555  else
556  {
557  return true;
558  }
559  }
560 
561  return false;
562 }
563 
564 function private ‪thrasherShouldConsumePlayer( entity )
565 {
566  if( !IsDefined( entity.favoriteenemy ) )
567  {
568  return false;
569  }
570 
571  targets = GetPlayers();
572 
573  // Don't consume single players
574  if ( targets.size == 1 )
575  {
576  return false;
577  }
578 
579  if( DistanceSquared( entity.origin, entity.favoriteenemy.origin ) > ‪THRASHER_CONSUME_DIST_SQ )
580  {
581  return false;
582  }
583 
584  if ( !entity.favoriteenemy ‪laststand::player_is_in_laststand() )
585  {
586  return false;
587  }
588 
589  if ( ‪IS_TRUE( entity.favoriteenemy.thrasherConsumed ) )
590  {
591  return false;
592  }
593 
594  if ( IsDefined( entity.thrasherCanConsumePlayerCallback ) && !entity [[ entity.thrasherCanConsumePlayerCallback ]]( entity ) )
595  {
596  return false;
597  }
598 
599  return true;
600 }
601 
602 function private ‪thrasherShouldConsumeZombie( entity )
603 {
604  if ( entity.thrasherConsumeCount >= entity.thrasherConsumeMax )
605  {
606  return false;
607  }
608 
609  if ( ( entity.thrasherLastConsume + entity.thrasherConsumeCooldown ) >= GetTime() )
610  {
611  return false;
612  }
613 
614  hasPoppedPustule = false;
615 
616  for( index = 0; index < ‪THRASHER_SPORES.size; index++ )
617  {
618  sporeStruct = entity.thrasherSpores[ index ];
619  if ( sporeStruct.health <= 0 )
620  {
621  hasPoppedPustule = true;
622  break;
623  }
624  }
625 
626  if ( hasPoppedPustule )
627  {
628  if ( IsDefined( entity.thrasherCanConsumeCallback ) )
629  {
630  return [[ entity.thrasherCanConsumeCallback ]]( entity );
631  }
632  }
633 
634  return false;
635 }
636 
637 function private ‪thrasherConsumePlayer( entity )
638 {
639  if ( IsPlayer( entity.favoriteenemy ) )
640  {
641  entity thread ‪ThrasherServerUtils::thrasherConsumePlayerUtil( entity, entity.favoriteenemy );
642  }
643 }
644 
645 function private ‪thrasherDeath( entity )
646 {
648 }
649 
650 function private ‪thrasherConsumeZombie( entity )
651 {
652  if ( IsDefined( entity.thrasherConsumeZombieCallback ) )
653  {
654  if ( [[ entity.thrasherConsumeZombieCallback ]]( entity ) )
655  {
656  entity.thrasherConsumeCount++;
657  entity.thrasherLastConsume = GetTime();
658  }
659  }
660 }
661 
662 function private ‪thrasherShouldBeStunned( entity )
663 {
664  return entity ‪ai::get_behavior_attribute( "stunned" );
665 }
666 
667 #namespace ThrasherServerUtils;
668 
669 function ‪thrasherKnockdownZombie( entity, zombie )
670 {
671  zombie.knockdown = true;
672  zombie.knockdown_type = ‪KNOCKDOWN_SHOVED;
673  zombie_to_thrasher = entity.origin - zombie.origin;
674  zombie_to_thrasher_2d = VectorNormalize( ( zombie_to_thrasher[0], zombie_to_thrasher[1], 0 ) );
675 
676  zombie_forward = AnglesToForward( zombie.angles );
677  zombie_forward_2d = VectorNormalize( ( zombie_forward[0], zombie_forward[1], 0 ) );
678 
679  zombie_right = AnglesToRight( zombie.angles );
680  zombie_right_2d = VectorNormalize( ( zombie_right[0], zombie_right[1], 0 ) );
681 
682  dot = VectorDot( zombie_to_thrasher_2d, zombie_forward_2d );
683 
684  if( dot >= 0.5 )
685  {
686  zombie.knockdown_direction = "front";
687  zombie.getup_direction = ‪GETUP_BACK;
688  }
689  else if ( dot < 0.5 && dot > -0.5 )
690  {
691  dot = VectorDot( zombie_to_thrasher_2d, zombie_right_2d );
692  if( dot > 0 )
693  {
694  zombie.knockdown_direction = "right";
695 
696  if ( ‪math::cointoss() )
697  {
698  zombie.getup_direction = ‪GETUP_BACK;
699  }
700  else
701  {
702  zombie.getup_direction = ‪GETUP_BELLY;
703  }
704  }
705  else
706  {
707  zombie.knockdown_direction = "left";
708  zombie.getup_direction = ‪GETUP_BELLY;
709  }
710  }
711  else
712  {
713  zombie.knockdown_direction = "back";
714  zombie.getup_direction = ‪GETUP_BELLY;
715  }
716 }
717 
718 function ‪thrasherGoBerserk( entity )
719 {
720  if ( !entity.thrasherIsBerserk )
721  {
723  entity.thrasherIsBerserk = true;
724  entity.health += ‪THRASHER_RAGE_HEALTH_BONUS;
727  }
728 }
729 
730 function private ‪thrasherPlayedBerserkIntro( entity )
731 {
732  entity.thrasherHasTurnedBerserk = true;
733  meleeWeapon = GetWeapon( ‪THRASHER_MELEE_ENRAGED );
734  entity.meleeweapon = GetWeapon( ‪THRASHER_MELEE_ENRAGED );
735  entity ‪ai::set_behavior_attribute( "stunned", false );
736  entity.thrasherStunHealth = ‪THRASHER_STUN_HEALTH;
737 
739 }
740 
741 function ‪thrasherDamageCallback( inflictor, attacker, ‪damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex )
742 {
743  entity = self;
744 
745  if ( hitLoc == ‪THRASHER_HEAD_HITLOC &&
747  {
748  entity.thrasherRageCount += ‪THRASHER_RAGE_INC_HEADSHOT;
749  entity.thrasherHeadHealth -= ‪damage;
750 
751  if( entity.thrasherHeadHealth <= 0 )
752  {
753  if( isdefined( attacker ) )
754  {
755  attacker notify( "destroyed_thrasher_head" );
756  }
757 
758  ‪GibServerUtils::GibHead( entity );
760  }
761  }
762  else
763  {
764  entity.thrasherRageCount += ‪THRASHER_RAGE_INC_NONVITAL;
765 
766  entity.thrasherStunHealth -= ‪damage;
767  if ( entity.thrasherStunHealth <= 0 )
768  {
769  entity ‪ai::set_behavior_attribute( "stunned", true );
770  if ( IsDefined( attacker ) )
771  {
772  attacker notify( "player_stunned_thrasher" ); // For VO and other applications.
773  }
774  }
775  }
776 
777  ‪damage = ‪thrasherSporeDamageCallback( inflictor, attacker, ‪damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex );
778 
779  if ( entity.thrasherRageCount >= ‪THRASHER_RAGE_THRESHOLD )
780  {
781  ‪thrasherGoBerserk( entity );
782 
783  if ( IsDefined( attacker ) )
784  {
785  attacker notify( "player_enraged_thrasher" ); // For VO and other applications.
786  }
787  }
788 
789  if ( ‪IS_TRUE( entity.b_thrasher_temp_invulnerable ) )
790  {
791  ‪damage = 1;
792  }
793 
794  ‪damage = Int( ‪damage );
795 
796  return ‪damage;
797 }
798 
799 function private ‪thrasherInvulnerability( n_time )
800 {
801  entity = self;
802 
803  entity endon( "death" );
804  entity notify( "end_invulnerability" );
805 
806  entity.b_thrasher_temp_invulnerable = true;
807 
808  entity ‪util::waittill_notify_or_timeout( "end_invulnerability", n_time );
809 
810  entity.b_thrasher_temp_invulnerable = false;
811 }
812 
813 function ‪thrasherSporeDamageCallback( inflictor, attacker, ‪damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex )
814 {
815  entity = self;
816 
817  assert( IsDefined( entity.thrasherSpores ) );
818 
819  if ( !IsDefined( point ) )
820  {
821  return ‪damage;
822  }
823 
824  healthySpores = 0;
825 
826  for( index = 0; index < ‪THRASHER_SPORES.size; index++ )
827  {
828  sporeStruct = entity.thrasherSpores[ index ];
829  assert( IsDefined( sporeStruct ) );
830 
831  if ( sporeStruct.health < 0 )
832  {
833  // Pustule already destroyed.
834  continue;
835  }
836 
837  tagOrigin = entity GetTagOrigin( sporeStruct.tag );
838 
839  if ( IsDefined( tagOrigin ) && DistanceSquared( tagOrigin, point ) < ‪SQR( sporeStruct.dist ) )
840  {
841  entity.thrasherRageCount += ‪THRASHER_RAGE_INC_PUSTULE;
842  sporeStruct.health -= ‪damage;
843 
844  entity ‪clientfield::increment( ‪THRASHER_SPORE_IMPACT_CF + sporeStruct.clientfield );
845 
846  if ( sporeStruct.health <= 0 )
847  {
848  entity HidePart( sporeStruct.tag );
849  sporeStruct.state = ‪THRASHER_SPORE_STATE_DESTROYED;
850 
851  destroyedSpores = entity ‪clientfield::get( ‪THRASHER_SPORE_CF );
852  destroyedSpores |= sporeStruct.clientfield;
853  entity ‪clientfield::set( ‪THRASHER_SPORE_CF, destroyedSpores );
854 
855  if ( IsDefined( entity.thrasherPustulePopCallback ) )
856  {
857  entity thread [[ entity.thrasherPustulePopCallback ]]( tagOrigin, weapon, attacker );
858  }
859 
860  entity ‪ai::set_behavior_attribute( "stunned", true );
861 
862  ‪damage = entity.maxHealth / ‪THRASHER_SPORES.size;
863  }
864 
865  /#
866  RecordSphere( tagOrigin, sporeStruct.dist, ‪YELLOW, "Script", entity );
867  #/
868  }
869 
870  if ( sporeStruct.health > 0 )
871  {
872  healthySpores++;
873  }
874  }
875 
876  if ( healthySpores == 0 )
877  {
878  // All weak spots destroyed, kill off the thrasher.
879  ‪damage = entity.maxHealth;
880  }
881 
882  return ‪damage;
883 }
884 
885 function private ‪thrasherTeleportOut( entity )
886 {
887  if ( IsDefined( entity.thrasherTeleportCallback ) )
888  {
889  entity thread [[ entity.thrasherTeleportCallback ]]( entity );
890  }
891 }
892 
893 function ‪thrasherStartTraverse( entity )
894 {
895  ‪AiUtility::traverseSetup( entity );
896 
897  if ( IsDefined( entity.thrasherStartTraverseCallback ) )
898  {
899  entity [[ entity.thrasherStartTraverseCallback ]]( entity );
900  }
901 }
902 
904 {
905  if ( IsDefined( entity.thrasherTerminateTraverseCallback ) )
906  {
907  entity [[ entity.thrasherTerminateTraverseCallback ]]( entity );
908  }
909 }
910 
911 function ‪thrasherTeleport( entity )
912 {
913  if( !IsDefined( entity.favoriteenemy ))
914  {
915  /#println ("*** Thrasher is trying to teleport, but has no favorite enemy, so he cannot ***" );#/
916  return;
917  }
918 
920  entity.favoriteenemy.origin,
922  THRASHER_TELEPORT_DESTINATION_MAX_RADIUS,
923  32,
924  64,
925  entity );
926 
927  filteredPoints = [];
928  thrashers = GetAIArchetypeArray( "thrasher" );
929  overlapSqr = ‪SQR( ‪THRASHER_TELEPORT_OVERLAP );
930 
931  foreach ( point in points )
932  {
933  valid = true;
934 
935  foreach ( thrasher in thrashers )
936  {
937  if ( DistanceSquared( point, thrasher.origin ) <= overlapSqr )
938  {
939  valid = false;
940  break;
941  }
942  }
943 
944  if ( valid )
945  {
946  filteredPoints[ filteredPoints.size ] = point;
947  }
948  }
949 
950  //filter points again if needed with stricter criteria
951  if( isdefined( entity.thrasher_teleport_dest_func ) )
952  {
953  filteredPoints = entity [[entity.thrasher_teleport_dest_func]]( filteredPoints );
954  }
955 
956  sortedPoints = ArraySortClosest( filteredPoints, entity.origin );
957  teleport_point = sortedPoints[0];
958 
959  if ( IsDefined( teleport_point ) )
960  {
961  v_dir = ( entity.favoriteenemy.origin - teleport_point );
962  v_dir = VectorNormalize( v_dir );
963  v_angles = VectorToAngles( v_dir );
964 
965  entity ForceTeleport( teleport_point, v_angles );
966  }
967 
968  entity.thrasherLastTeleportTime = GetTime();
969 }
970 
971 function private ‪thrasherStunInitialize( entity )
972 {
973  entity.thrasherStunStartTime = GetTime();
974 }
975 
976 function private ‪thrasherStunUpdate( entity )
977 {
978  if ( entity.thrasherStunStartTime + ‪THRASHER_STUN_TIME < GetTime() )
979  {
980  entity ‪ai::set_behavior_attribute( "stunned", false );
981  entity.thrasherStunHealth = ‪THRASHER_STUN_HEALTH;
982  }
983 }
984 
985 function private ‪thrasherHideSpikes( entity, hide )
986 {
987  for ( index = 1; index <= ‪THRASHER_SPIKE_COUNT; index++ )
988  {
989  tag = "j_spike";
990  if ( index < 10 )
991  {
992  tag = tag + "0";
993  }
994  tag = tag + index + "_root";
995 
996  if ( hide )
997  {
998  entity HidePart( tag, "", true );
999  }
1000  else
1001  {
1002  entity ShowPart( tag, "", true );
1003  }
1004  }
1005 }
1006 
1007 function ‪thrasherHideFromPlayer( thrasher, player, hide )
1008 {
1009  entityNumber = player GetEntityNumber();
1010  entityBit = 1 << entityNumber;
1011 
1012  currentHidden = ‪clientfield::get( "thrasher_player_hide" );
1013  hiddenPlayers = currentHidden;
1014 
1015  if (hide )
1016  {
1017  hiddenPlayers = currentHidden | entityBit;
1018  }
1019  else
1020  {
1021  hiddenPlayers = currentHidden & ~entityBit;
1022  }
1023 
1024  thrasher ‪clientfield::set( "thrasher_player_hide", hiddenPlayers );
1025 }
1026 
1028 {
1029  for( index = 0; index < ‪THRASHER_SPORES.size; index++ )
1030  {
1031  sporeStruct = entity.thrasherSpores[ index ];
1032 
1033  if ( sporeStruct.health <= 0 )
1034  {
1035  entity HidePart( sporeStruct.tag );
1036  }
1037  else
1038  {
1039  entity ShowPart( sporeStruct.tag );
1040  }
1041  }
1042 }
1043 
1044 function ‪thrasherRestorePustule( entity )
1045 {
1046  for( index = 0; index < ‪THRASHER_SPORES.size; index++ )
1047  {
1048  sporeStruct = entity.thrasherSpores[ index ];
1049 
1050  if ( sporeStruct.health <= 0 )
1051  {
1052  sporeStruct.health = sporeStruct.maxhealth;
1053  entity.health += Int( entity.maxHealth / ‪THRASHER_SPORES.size );
1054 
1055  destroyedSpores = entity ‪clientfield::get( ‪THRASHER_SPORE_CF );
1056  destroyedSpores &= ~sporeStruct.clientfield;
1057  entity ‪clientfield::set( ‪THRASHER_SPORE_CF, destroyedSpores );
1058 
1059  break;
1060  }
1061  }
1062 
1064 }
1065 
1067 {
1068  clone = ‪Spawn( "script_model", player.origin );
1069  clone.angles = player.angles;
1070 
1071  // Clone player's look
1072  bodyModel = player GetCharacterBodyModel();
1073  if ( IsDefined( bodyModel ) )
1074  {
1075  clone SetModel( bodyModel );
1076  }
1077 
1078  headModel = player GetCharacterHeadModel();
1079  if ( IsDefined( headModel ) && headModel != "tag_origin" )
1080  {
1081  if ( IsDefined( clone.head ) )
1082  {
1083  clone Detach( clone.head );
1084  }
1085 
1086  clone Attach( headModel );
1087  }
1088 
1089  helmetModel = player GetCharacterHelmetModel();
1090  if ( IsDefined( helmetModel ) && headModel != "tag_origin" )
1091  {
1092  clone Attach( helmetModel );
1093  }
1094 
1095  return clone;
1096 }
1097 
1098 function ‪thrasherHidePlayerBody( thrasher, player )
1099 {
1100  player endon( "death" );
1101 
1102  player waittill( "hide_body" );
1103 
1104  player Hide();
1105 }
1106 
1107 function ‪thrasherCanBeRevived( revivee )
1108 {
1109  if ( IsDefined( revivee.thrasherConsumed ) && revivee.thrasherConsumed )
1110  {
1111  return false;
1112  }
1113 
1114  return true;
1115 }
1116 
1117 function private ‪thrasherStopConsumePlayerScene( thrasher, playerClone )
1118 {
1119  thrasher endon( "consume_scene_end" );
1120 
1121  thrasher waittill( "death" );
1122 
1123  if ( IsDefined( thrasher ) )
1124  {
1125  thrasher ‪scene::stop( "scene_zm_dlc2_thrasher_eat_player" );
1126  }
1127 
1128  if ( IsDefined( playerClone ) )
1129  {
1130  playerClone Delete();
1131  }
1132 }
1133 
1134 function private ‪thrasherConsumePlayerScene( thrasher, playerClone )
1135 {
1136  thrasher endon( "death" );
1137 
1138  thrasher thread ‪thrasherStopConsumePlayerScene( thrasher, playerClone );
1139  thrasher ‪scene::play( "scene_zm_dlc2_thrasher_eat_player", ‪array( thrasher, playerClone ) );
1140  thrasher notify( "consume_scene_end" );
1141 
1142  targetPos = GetClosestPointOnNavMesh( thrasher.origin, 1024, 18 );
1143 
1144  if ( IsDefined( targetPos ) )
1145  {
1146  thrasher ForceTeleport( targetPos );
1147  }
1148 }
1149 
1150 function ‪thrasherConsumePlayerUtil( thrasher, player )
1151 {
1152  assert( IsActor( thrasher ) );
1153  assert( thrasher.archetype == "thrasher" );
1154  assert( IsPlayer( player ) );
1155 
1156  thrasher endon( "kill_consume_player" );
1157 
1158  if ( ‪IS_TRUE( player.thrasherConsumed ) )
1159  {
1160  return;
1161  }
1162 
1163  playerClone = ‪thrasherCreatePlayerClone( player );
1164  playerClone.origin = player.origin;
1165  playerClone.angles = player.angles;
1166  playerClone Hide();
1167 
1168  thrasher.offsetModel = ‪Spawn( "script_model", thrasher.origin );
1169 
1171 
1172  if ( !IsDefined( thrasher ) || ‪IS_TRUE( player.thrasherConsumed ) )
1173  {
1174  playerClone Destroy();
1175  return;
1176  }
1177 
1178  ‪thrasherHideFromPlayer( thrasher, player, true );
1179 
1180  if ( IsDefined( thrasher.thrasherConsumedCallback ) )
1181  {
1182  [[ thrasher.thrasherConsumedCallback ]]( thrasher, player );
1183  }
1184 
1185  if ( IsDefined( player.revivetrigger ) )
1186  {
1187  player.revivetrigger SetInvisibleToAll();
1188  player.revivetrigger TriggerEnable( false );
1189  }
1190 
1191  player SetClientUIVisibilityFlag( "hud_visible", 0 );
1192  player SetClientUIVisibilityFlag( "weapon_hud_visible", 0 );
1193  player.thrasherConsumed = true;
1194  player.thrasher = thrasher;
1195  player SetPlayerCollision( false );
1196  player WalkUnderwater( true );
1197  player.ignoreme = true;
1198  player HideViewModel();
1199  player FreezeControls( false );
1200  player FreezeControlsAllowLook( true );
1201  player thread ‪lui::screen_fade_in( 10 );
1202  player ‪clientfield::set_to_player( "sndPlayerConsumed", 1 );
1204  player thread ‪thrasherKillThrasherOnAutoRevive( thrasher, player );
1205 
1206  eyePosition = player GetTagOrigin( "tag_eye" );
1207  eyeOffset = abs( eyePosition[2] - player.origin[2] ) + 10;
1208 
1209  thrasher.offsetModel LinkTo( thrasher, "tag_camera_thrasher", ( 0, 0, -eyeOffset + 27 ) ); //HACK raising player body another 27 units so that revive icon is above thrasher's head. Check if there's a UI-specific way to do this
1210 
1211  // player PlayerLinkTo( thrasher.offsetModel, undefined, 0.2, 25, 25, 5, 5 );
1212  // player PlayerLinkTo( thrasher.offsetModel );
1213  player PlayerLinkTo( thrasher.offsetModel, undefined, 1, 0, 0, 0, 0, true );
1214 
1215  thrasher thread ‪thrasherPlayerDeath( thrasher, player );
1216 
1217  thrasher.thrasherConsumedPlayer = true;
1218  thrasher.thrasherPlayer = player;
1219 
1220  // Prevent the thrasher from teleporting to the next enemy.
1221  thrasher.thrasherLastTeleportTime = GetTime();
1222 
1223  player Ghost();
1224  playerClone Show();
1225 
1226  if ( IsDefined( playerClone ) )
1227  {
1228  thrasher thread ‪thrasherConsumePlayerScene( thrasher, playerClone );
1229  playerClone thread ‪thrasherHidePlayerBody( thrasher, playerClone );
1230 
1231  // Notify for VO and other applications.
1232  player notify( "player_eaten_by_thrasher" );
1233  }
1234 
1235  thrasher waittill( "death" );
1236 
1237  ‪thrasherReleasePlayer( thrasher, player );
1238 }
1239 
1240 function ‪thrasherKillThrasherOnAutoRevive( thrasher, player )
1241 {
1242  player endon( "death" );
1243  player endon( "kill_thrasher_on_auto_revive" );
1244 
1245  player waittill( "bgb_revive" );
1246 
1247  if ( IsDefined( player.thrasher ) )
1248  {
1249  player.thrasher Kill();
1250  }
1251 }
1252 
1253 function ‪thrasherReleasePlayer( thrasher, player )
1254 {
1255  if ( !IsAlive( player ) )
1256  {
1257  return;
1258  }
1259 
1260  if ( IsDefined( thrasher.offsetModel ) )
1261  {
1262  thrasher.offsetModel Unlink();
1263  thrasher.offsetModel Delete();
1264  }
1265 
1266  if ( IsDefined( player.revivetrigger ) )
1267  {
1268  player.revivetrigger SetVisibleToAll();
1269  player.revivetrigger TriggerEnable( true );
1270  }
1271 
1272  // thrasherHideFromPlayer( thrasher, player, false );
1273 
1274  if ( IsDefined( thrasher.thrasherReleaseConsumedCallback ) )
1275  {
1276  [[ thrasher.thrasherReleaseConsumedCallback ]]( thrasher, player );
1277  }
1278 
1279  thrasher.thrasherPlayer = undefined;
1280 
1281  player SetClientUIVisibilityFlag( "hud_visible", 1 );
1282  player SetClientUIVisibilityFlag( "weapon_hud_visible", 1 );
1283  player.thrasherFreedTime = GetTime();
1284  player SetStance( "prone" );
1285  player notify( "kill_thrasher_on_auto_revive" );
1286  player.thrasherConsumed = undefined;
1287  player.thrasher = undefined;
1288  player WalkUnderwater( false );
1289  player Unlink();
1290  player SetPlayerCollision( true );
1291  player Show();
1292  player.ignoreme = false;
1293  player ShowViewModel();
1294  player FreezeControlsAllowLook( false );
1295  player thread ‪lui::screen_fade_in( 2 );
1296  player ‪clientfield::set_to_player( "sndPlayerConsumed", 0 );
1298  player thread ‪check_revive_after_consumed();
1299 
1300  targetPos = GetClosestPointOnNavMesh( player.origin, 1024, 18 );
1301 
1302  if ( IsDefined( targetPos ) )
1303  {
1304  newPosition = player.origin;
1305  groundPosition = bullettrace( targetPos + (0, 0, -128), targetPos + (0, 0, 128), false, player );
1306 
1307  if ( IsDefined( groundPosition[ "position" ] ) )
1308  {
1309  newPosition = groundPosition[ "position" ];
1310  }
1311  else
1312  {
1313  groundPosition = bullettrace( targetPos + (0, 0, -256), targetPos + (0, 0, 256), false, player );
1314 
1315  if ( IsDefined( groundPosition[ "position" ] ) )
1316  {
1317  newPosition = groundPosition[ "position" ];
1318  }
1319  else
1320  {
1321  groundPosition = bullettrace( targetPos + (0, 0, -512), targetPos + (0, 0, 512), false, player );
1322 
1323  if ( IsDefined( groundPosition[ "position" ] ) )
1324  {
1325  newPosition = groundPosition[ "position" ];
1326  }
1327  }
1328  }
1329 
1330  if ( newPosition[2] > player.origin[2] )
1331  {
1332  player.origin = newPosition;
1333  }
1334  }
1335 
1336  // Kill off the thread waiting to release the player, just in case.
1337  thrasher notify( "kill_consume_player" );
1338 }
1339 
1340 //self is a player
1342 {
1343  self endon( "death" );
1344 
1345  self waittill( "player_revived" );
1346 
1347  self notify( "achievement_ZM_ISLAND_THRASHER_RESCUE" );
1348 }
1349 
1350 function ‪thrasherPlayerDeath( thrasher, player )
1351 {
1352  thrasher endon( "kill_consume_player" );
1353 
1354  thrasher.thrasherPlayer = undefined;
1355 
1356  characterIndex = player.characterindex;
1357 
1358  if ( !IsDefined( characterIndex ) )
1359  {
1360  return;
1361  }
1362 
1363  level waittill( "bleed_out", characterIndex );
1364 
1365  if ( IsDefined( thrasher.thrasherReleaseConsumedCallback ) )
1366  {
1367  [[ thrasher.thrasherReleaseConsumedCallback ]]( thrasher, player );
1368  }
1369 
1370  if ( IsDefined( thrasher ) && IsDefined( player ) )
1371  {
1372  ‪thrasherHideFromPlayer( thrasher, player, false );
1373  }
1374 
1375  if ( IsDefined( player ) )
1376  {
1377  player ShowViewModel();
1378  player ‪clientfield::set_to_player( "sndPlayerConsumed", 0 );
1380  }
1381 }
1382 
1383 function ‪thrasherMoveModeAttributeCallback( entity, attribute, oldValue, value )
1384 {
1385  if ( value == "normal" )
1386  {
1387  entity.team = "axis";
1388  }
1389  else if ( value == "friendly" )
1390  {
1391  entity.team = "allies";
1392  }
1393 }
‪YELLOW
‪#define YELLOW
Definition: shared.gsh:178
‪ArchetypeThrasherOnAnimscriptedCallback
‪function private ArchetypeThrasherOnAnimscriptedCallback(entity)
Definition: archetype_thrasher.gsc:152
‪THRASHER_SPORE_IMPACT_CF_BITS
‪#define THRASHER_SPORE_IMPACT_CF_BITS
Definition: archetype_thrasher.gsh:153
‪activate
‪function activate()
Definition: traps_shared.gsc:655
‪thrasherConsumePlayerUtil
‪function thrasherConsumePlayerUtil(thrasher, player)
Definition: archetype_thrasher.gsc:1150
‪thrasherDamageCallback
‪function thrasherDamageCallback(inflictor, attacker, damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex)
Definition: archetype_thrasher.gsc:741
‪THRASHER_CONSUME_PLAYER_DISTANCE
‪#define THRASHER_CONSUME_PLAYER_DISTANCE
Definition: archetype_thrasher.gsh:57
‪BT_REGISTER_API
‪#define BT_REGISTER_API(name, function)
Definition: behavior.gsh:1
‪THRASHER_SPORES
‪#define THRASHER_SPORES
Definition: archetype_thrasher.gsh:131
‪THRASHER_RAGE_INC_NONVITAL
‪#define THRASHER_RAGE_INC_NONVITAL
Definition: archetype_thrasher.gsh:27
‪thrasherRestorePustule
‪function thrasherRestorePustule(entity)
Definition: archetype_thrasher.gsc:1044
‪thrasherKnockdownService
‪function private thrasherKnockdownService(entity)
Definition: archetype_thrasher.gsc:430
‪THRASHER_RAGE_INVULNERABLE_TIME
‪#define THRASHER_RAGE_INVULNERABLE_TIME
Definition: archetype_thrasher.gsh:66
‪THRASHER_TELEPORT_OVERLAP
‪#define THRASHER_TELEPORT_OVERLAP
Definition: archetype_thrasher.gsh:54
‪thrasherShouldTurnBerserk
‪function private thrasherShouldTurnBerserk(entity)
Definition: archetype_thrasher.gsc:531
‪THRASHER_MELEE_YAW
‪#define THRASHER_MELEE_YAW
Definition: archetype_thrasher.gsh:109
‪thrasherConsumeZombie
‪function private thrasherConsumeZombie(entity)
Definition: archetype_thrasher.gsc:650
‪VERSION_TU5
‪#define VERSION_TU5
Definition: version.gsh:47
‪set_to_player
‪function set_to_player(str_field_name, n_value)
Definition: clientfield_shared.gsc:58
‪thrasherCanBeRevived
‪function thrasherCanBeRevived(revivee)
Definition: archetype_thrasher.gsc:1107
‪THRASHER_SPORE_IMPACT_CF
‪#define THRASHER_SPORE_IMPACT_CF
Definition: archetype_thrasher.gsh:151
‪THRASHER_CONSUMED_PLAYER_VISIONSET_ALIAS
‪#define THRASHER_CONSUMED_PLAYER_VISIONSET_ALIAS
Definition: archetype_thrasher.gsh:216
‪VERSION_TU10
‪#define VERSION_TU10
Definition: version.gsh:59
‪THRASHER_BERSERK_CF_TYPE
‪#define THRASHER_BERSERK_CF_TYPE
Definition: archetype_thrasher.gsh:181
‪play
‪function play(animation, v_origin_or_ent, v_angles_or_tag, n_rate=1, n_blend_in=.2, n_blend_out=.2, n_lerp, b_link=false)
Definition: animation_shared.csc:44
‪thrasherTeleportOut
‪function private thrasherTeleportOut(entity)
Definition: archetype_thrasher.gsc:885
‪thrasherMoveModeAttributeCallback
‪function thrasherMoveModeAttributeCallback(entity, attribute, oldValue, value)
Definition: archetype_thrasher.gsc:1383
‪thrasherStunUpdate
‪function private thrasherStunUpdate(entity)
Definition: archetype_thrasher.gsc:976
‪thrasherHidePlayerBody
‪function thrasherHidePlayerBody(thrasher, player)
Definition: archetype_thrasher.gsc:1098
‪thrasherTargetService
‪function private thrasherTargetService(entity)
Definition: archetype_thrasher.gsc:329
‪cointoss
‪function cointoss()
Definition: math_shared.csc:171
‪LOCOMOTION_SPEED_WALK
‪#define LOCOMOTION_SPEED_WALK
Definition: blackboard.gsh:156
‪THRASHER_BERSERK_CF
‪#define THRASHER_BERSERK_CF
Definition: archetype_thrasher.gsh:180
‪BB_GetShouldTurn
‪function private BB_GetShouldTurn()
Definition: archetype_thrasher.gsc:202
‪THRASHER_RAGE_AUTO
‪#define THRASHER_RAGE_AUTO
Definition: archetype_thrasher.gsh:32
‪BB_REGISTER_ATTRIBUTE
‪#define BB_REGISTER_ATTRIBUTE(name, defaultValue, getter)
Definition: blackboard.gsh:1
‪ASM_REGISTER_NOTETRACK_HANDLER
‪#define ASM_REGISTER_NOTETRACK_HANDLER(notetrackname, handlerfunction)
Definition: animation_state_machine.gsh:4
‪thrasherReleasePlayer
‪function thrasherReleasePlayer(thrasher, player)
Definition: archetype_thrasher.gsc:1253
‪screen_fade_in
‪function screen_fade_in(fadeintime)
Definition: hud_shared.gsc:264
‪THRASHER_STUN_TIME
‪#define THRASHER_STUN_TIME
Definition: archetype_thrasher.gsh:60
‪ZOMBIE_DAMAGEWEAPON_REGULAR
‪#define ZOMBIE_DAMAGEWEAPON_REGULAR
Definition: blackboard.gsh:190
‪thrasherAttackableObjectService
‪function private thrasherAttackableObjectService(entity)
Definition: archetype_thrasher.gsc:420
‪THRASHER_BERSERK_CF_BITS
‪#define THRASHER_BERSERK_CF_BITS
Definition: archetype_thrasher.gsh:182
‪PositionQuery_PointArray
‪function PositionQuery_PointArray(origin, minSearchRadius, maxSearchRadius, halfHeight, innerSpacing, reachableBy_Ent)
Definition: util_shared.gsc:3462
‪__init__
‪function __init__()
Definition: archetype_thrasher.gsc:50
‪THRASHER_SPORE_CF_SPORES
‪#define THRASHER_SPORE_CF_SPORES
Definition: archetype_thrasher.gsh:163
‪SHOULD_TURN
‪#define SHOULD_TURN
Definition: blackboard.gsh:138
‪SetBlackBoardAttribute
‪function SetBlackBoardAttribute(entity, attributeName, attributeValue)
Definition: blackboard.gsc:56
‪ARCHETYPE_THRASHER
‪#define ARCHETYPE_THRASHER
Definition: archetype_shared.gsh:19
‪THRASHER_CONSUMED_PLAYER_VISIONSET_LERP_STEP_COUNT
‪#define THRASHER_CONSUMED_PLAYER_VISIONSET_LERP_STEP_COUNT
Definition: archetype_thrasher.gsh:217
‪THRASHER_MELEE_ENRAGED
‪#define THRASHER_MELEE_ENRAGED
Definition: archetype_thrasher.gsh:110
‪thrasherCreatePlayerClone
‪function thrasherCreatePlayerClone(player)
Definition: archetype_thrasher.gsc:1066
‪thrasherGetClosestLaststandPlayer
‪function private thrasherGetClosestLaststandPlayer(entity)
Definition: archetype_thrasher.gsc:268
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪thrasherShouldMelee
‪function thrasherShouldMelee(entity)
Definition: archetype_thrasher.gsc:495
‪THRASHER_FREED_SAFETY
‪#define THRASHER_FREED_SAFETY
Definition: archetype_thrasher.gsh:96
‪THRASHER_RAGE_HEALTH_BONUS
‪#define THRASHER_RAGE_HEALTH_BONUS
Definition: archetype_thrasher.gsh:24
‪get
‪function get(kvp_value, kvp_key="targetname")
Definition: struct.csc:13
‪SQR
‪#define SQR(__var)
Definition: shared.gsh:293
‪thrasherShouldTeleport
‪function private thrasherShouldTeleport(entity)
Definition: archetype_thrasher.gsc:536
‪thrasherGoBerserk
‪function thrasherGoBerserk(entity)
Definition: archetype_thrasher.gsc:718
‪thrasherSpawnSetup
‪function private thrasherSpawnSetup()
Definition: archetype_thrasher.gsc:161
‪thrasherHidePoppedPustules
‪function thrasherHidePoppedPustules(entity)
Definition: archetype_thrasher.gsc:1027
‪RegisterUtilityBlackboardAttributes
‪function RegisterUtilityBlackboardAttributes()
Definition: archetype_utility.gsc:139
‪Annihilate
‪function Annihilate(entity)
Definition: gib.gsc:393
‪thrasherTerminateTraverse
‪function thrasherTerminateTraverse(entity)
Definition: archetype_thrasher.gsc:903
‪thrasherShouldBeStunned
‪function private thrasherShouldBeStunned(entity)
Definition: archetype_thrasher.gsc:662
‪THRASHER_NAVMESH_BOUNDARY_DIST
‪#define THRASHER_NAVMESH_BOUNDARY_DIST
Definition: archetype_thrasher.gsh:123
‪thrasherConsumePlayer
‪function private thrasherConsumePlayer(entity)
Definition: archetype_thrasher.gsc:637
‪thrasherInvulnerability
‪function private thrasherInvulnerability(n_time)
Definition: archetype_thrasher.gsc:799
‪damage
‪function damage(trap)
Definition: _zm_trap_electric.gsc:116
‪thrasherKnockdownZombie
‪function thrasherKnockdownZombie(entity, zombie)
Definition: archetype_thrasher.gsc:669
‪THRASHER_MELEE_DIST_SQ
‪#define THRASHER_MELEE_DIST_SQ
Definition: archetype_thrasher.gsh:108
‪THRASHER_SPORE_CF_BITS
‪#define THRASHER_SPORE_CF_BITS
Definition: archetype_thrasher.gsh:159
‪THRASHER_TELEPORT_DESTINATION_SAFE_RADIUS
‪#define THRASHER_TELEPORT_DESTINATION_SAFE_RADIUS
Definition: archetype_thrasher.gsh:227
‪VERSION_TU8
‪#define VERSION_TU8
Definition: version.gsh:54
‪LOCOMOTION_SHOULD_TURN
‪#define LOCOMOTION_SHOULD_TURN
Definition: blackboard.gsh:137
‪thrasherPlayedBerserkIntro
‪function private thrasherPlayedBerserkIntro(entity)
Definition: archetype_thrasher.gsc:730
‪THRASHER_SPORE_CF
‪#define THRASHER_SPORE_CF
Definition: archetype_thrasher.gsh:157
‪ENABLE_BLACKBOARD_DEBUG_TRACKING
‪#define ENABLE_BLACKBOARD_DEBUG_TRACKING(self)
Definition: blackboard.gsh:7
‪THRASHER_RAGE_AUTO_MULTIPLIER
‪#define THRASHER_RAGE_AUTO_MULTIPLIER
Definition: archetype_thrasher.gsh:35
‪THRASHER_RAGE_THRESHOLD
‪#define THRASHER_RAGE_THRESHOLD
Definition: archetype_thrasher.gsh:42
‪THRASHER_BERSERK_CF_BERSERK
‪#define THRASHER_BERSERK_CF_BERSERK
Definition: archetype_thrasher.gsh:184
‪thrasherKillThrasherOnAutoRevive
‪function thrasherKillThrasherOnAutoRevive(thrasher, player)
Definition: archetype_thrasher.gsc:1240
‪thrasherPlayerDeath
‪function thrasherPlayerDeath(thrasher, player)
Definition: archetype_thrasher.gsc:1350
‪InitThrasherBehaviorsAndASM
‪function private InitThrasherBehaviorsAndASM()
Definition: archetype_thrasher.gsc:85
‪THRASHER_SPIKE_COUNT
‪#define THRASHER_SPIKE_COUNT
Definition: archetype_thrasher.gsh:187
‪LOCOMOTION_SPEED_TYPE
‪#define LOCOMOTION_SPEED_TYPE
Definition: blackboard.gsh:155
‪wait_network_frame
‪function wait_network_frame(n_count=1)
Definition: util_shared.gsc:64
‪thrasherTeleport
‪function thrasherTeleport(entity)
Definition: archetype_thrasher.gsc:911
‪traverseSetup
‪function traverseSetup(behaviorTreeEntity)
Definition: archetype_locomotion_utility.gsc:305
‪thrasherNotetrackMelee
‪function private thrasherNotetrackMelee(entity)
Definition: archetype_thrasher.gsc:242
‪thrasherStopConsumePlayerScene
‪function private thrasherStopConsumePlayerScene(thrasher, playerClone)
Definition: archetype_thrasher.gsc:1117
‪THRASHER_PUSTULE_HEALTH
‪#define THRASHER_PUSTULE_HEALTH
Definition: archetype_thrasher.gsh:15
‪waittill_notify_or_timeout
‪function waittill_notify_or_timeout(msg, timer)
Definition: util_shared.csc:473
‪SHOULD_NOT_TURN
‪#define SHOULD_NOT_TURN
Definition: blackboard.gsh:139
‪thrasherRageService
‪function private thrasherRageService(entity)
Definition: archetype_thrasher.gsc:319
‪THRASHER_CONSUMED_PLAYER_VISIONSET_RAMP_IN_DURATION
‪#define THRASHER_CONSUMED_PLAYER_VISIONSET_RAMP_IN_DURATION
Definition: archetype_thrasher.gsh:218
‪deactivate
‪function deactivate()
Definition: traps_shared.gsc:649
‪RegisterThrasherInterfaceAttributes
‪function RegisterThrasherInterfaceAttributes()
Definition: archetype_thrasher_interface.gsc:6
‪thrasherConsumePlayerScene
‪function private thrasherConsumePlayerScene(thrasher, playerClone)
Definition: archetype_thrasher.gsc:1134
‪IsGibbed
‪function IsGibbed(localClientNum, entity, gibFlag)
Definition: gib.csc:734
‪increment
‪function increment(str_field_name, n_increment_count=1)
Definition: clientfield_shared.gsc:110
‪KNOCKDOWN_SHOVED
‪#define KNOCKDOWN_SHOVED
Definition: blackboard.gsh:212
‪THRASHER_SPORE_IMPACT_CF_TYPE
‪#define THRASHER_SPORE_IMPACT_CF_TYPE
Definition: archetype_thrasher.gsh:152
‪THRASHER_RAGE_INC_PUSTULE
‪#define THRASHER_RAGE_INC_PUSTULE
Definition: archetype_thrasher.gsh:29
‪REGISTER_SYSTEM
‪#define REGISTER_SYSTEM(__sys, __func_init_preload, __reqs)
Definition: shared.gsh:204
‪THRASHER_CONSUME_MAX
‪#define THRASHER_CONSUME_MAX
Definition: archetype_thrasher.gsh:48
‪array
‪function filter array
Definition: array_shared.csc:16
‪THRASHER_NAVMESH_RADIUS
‪#define THRASHER_NAVMESH_RADIUS
Definition: archetype_thrasher.gsh:122
‪get_closest_valid_player
‪function get_closest_valid_player(origin, ignore_player)
Definition: skeleton.gsc:321
‪THRASHER_SPORE_DAMAGE_DISTS
‪#define THRASHER_SPORE_DAMAGE_DISTS
Definition: archetype_thrasher.gsh:132
‪ArchetypeThrasherBlackboardInit
‪function private ArchetypeThrasherBlackboardInit()
Definition: archetype_thrasher.gsc:122
‪Spawn
‪function Spawn(parent, onDeathCallback)
Definition: _flak_drone.gsc:427
‪THRASHER_CONSUMED_PLAYER_VISIONSET_PRIORITY
‪#define THRASHER_CONSUMED_PLAYER_VISIONSET_PRIORITY
Definition: archetype_thrasher.gsh:219
‪register_info
‪function register_info(type, name, version, lerp_step_count)
Definition: visionset_mgr_shared.csc:334
‪THRASHER_SPORE_STATE_HEALTHY
‪#define THRASHER_SPORE_STATE_HEALTHY
Definition: archetype_thrasher.gsh:135
‪ARCHETYPE_ZOMBIE
‪#define ARCHETYPE_ZOMBIE
Definition: archetype_shared.gsh:10
‪stop
‪function stop(n_blend=0.2)
Definition: animation_shared.gsc:97
‪add_archetype_spawn_function
‪function add_archetype_spawn_function(archetype, spawn_func)
Definition: ai_shared.csc:23
‪GETUP_BELLY
‪#define GETUP_BELLY
Definition: blackboard.gsh:206
‪thrasherShouldConsumePlayer
‪function private thrasherShouldConsumePlayer(entity)
Definition: archetype_thrasher.gsc:564
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪set_behavior_attribute
‪function set_behavior_attribute(attribute, value)
Definition: ai_shared.gsc:159
‪CreateBlackBoardForEntity
‪function CreateBlackBoardForEntity(entity)
Definition: blackboard.gsc:77
‪thrasherStunInitialize
‪function private thrasherStunInitialize(entity)
Definition: archetype_thrasher.gsc:971
‪player_is_in_laststand
‪function player_is_in_laststand()
Definition: laststand_shared.gsc:18
‪THRASHER_HEAD_HITLOC
‪#define THRASHER_HEAD_HITLOC
Definition: archetype_thrasher.gsh:223
‪thrasherDeath
‪function private thrasherDeath(entity)
Definition: archetype_thrasher.gsc:645
‪ASM_THRASHER_MELEE_NOTETRACK
‪#define ASM_THRASHER_MELEE_NOTETRACK
Definition: archetype_thrasher.gsh:104
‪shouldRegisterClientFieldForArchetype
‪function shouldRegisterClientFieldForArchetype(archetype)
Definition: ai_shared.csc:72
‪thrasherShouldConsumeZombie
‪function private thrasherShouldConsumeZombie(entity)
Definition: archetype_thrasher.gsc:602
‪THRASHER_HEAD_HEALTH
‪#define THRASHER_HEAD_HEALTH
Definition: archetype_thrasher.gsh:21
‪THRASHER_CONSUME_COOLDOWN
‪#define THRASHER_CONSUME_COOLDOWN
Definition: archetype_thrasher.gsh:45
‪thrasherHideFromPlayer
‪function thrasherHideFromPlayer(thrasher, player, hide)
Definition: archetype_thrasher.gsc:1007
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪thrasherShouldShowPain
‪function private thrasherShouldShowPain(entity)
Definition: archetype_thrasher.gsc:526
‪thrasherSporeDamageCallback
‪function thrasherSporeDamageCallback(inflictor, attacker, damage, dFlags, mod, weapon, point, dir, hitLoc, offsetTime, boneIndex, modelIndex)
Definition: archetype_thrasher.gsc:813
‪shouldAttackObject
‪function shouldAttackObject(entity)
Definition: archetype_utility.gsc:3181
‪THRASHER_SPORE_STATE_DESTROYED
‪#define THRASHER_SPORE_STATE_DESTROYED
Definition: archetype_thrasher.gsh:134
‪GibHead
‪function GibHead(entity)
Definition: gib.gsc:443
‪THRASHER_SPORE_CF_TYPE
‪#define THRASHER_SPORE_CF_TYPE
Definition: archetype_thrasher.gsh:158
‪thrasherZombieEligibleForKnockdown
‪function private thrasherZombieEligibleForKnockdown(zombie, thrasher, predicted_pos)
Definition: archetype_thrasher.gsc:454
‪VERSION_DLC2
‪#define VERSION_DLC2
Definition: version.gsh:93
‪get_behavior_attribute
‪function get_behavior_attribute(attribute)
Definition: ai_shared.gsc:184
‪ramp_in_thread_per_player
‪function ramp_in_thread_per_player(player, duration)
Definition: visionset_mgr_shared.gsc:229
‪THRASHER_RAGE_INC_HEADSHOT
‪#define THRASHER_RAGE_INC_HEADSHOT
Definition: archetype_thrasher.gsh:28
‪thrasherStartTraverse
‪function thrasherStartTraverse(entity)
Definition: archetype_thrasher.gsc:893
‪THRASHER_TOTAL_HEALTH
‪#define THRASHER_TOTAL_HEALTH
Definition: archetype_thrasher.gsh:8
‪LOCOMOTION_SPEED_RUN
‪#define LOCOMOTION_SPEED_RUN
Definition: blackboard.gsh:157
‪CreateInterfaceForEntity
‪function CreateInterfaceForEntity(entity)
Definition: ai_interface.gsc:110
‪GIB_TORSO_HEAD_FLAG
‪#define GIB_TORSO_HEAD_FLAG
Definition: gib.gsh:24
‪check_revive_after_consumed
‪function check_revive_after_consumed()
Definition: archetype_thrasher.gsc:1341
‪THRASHER_LASTSTAND_SAFETY
‪#define THRASHER_LASTSTAND_SAFETY
Definition: archetype_thrasher.gsh:93
‪THRASHER_CONSUME_DIST_SQ
‪#define THRASHER_CONSUME_DIST_SQ
Definition: archetype_thrasher.gsh:114
‪ZOMBIE_DAMAGEWEAPON_TYPE
‪#define ZOMBIE_DAMAGEWEAPON_TYPE
Definition: blackboard.gsh:189
‪THRASHER_TELERPOT_MIN_DISTANCE_SQ
‪#define THRASHER_TELERPOT_MIN_DISTANCE_SQ
Definition: archetype_thrasher.gsh:226
‪thrasherHideSpikes
‪function private thrasherHideSpikes(entity, hide)
Definition: archetype_thrasher.gsc:985
‪THRASHER_STUN_HEALTH
‪#define THRASHER_STUN_HEALTH
Definition: archetype_thrasher.gsh:63
‪thrasherInitSpores
‪function private thrasherInitSpores()
Definition: archetype_thrasher.gsc:213
‪THRASHER_TELEPORT_COOLDOWN
‪#define THRASHER_TELEPORT_COOLDOWN
Definition: archetype_thrasher.gsh:51
‪GETUP_BACK
‪#define GETUP_BACK
Definition: blackboard.gsh:205