‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
archetype_secondary_animations.csc
Go to the documentation of this file.
1 #using scripts\shared\ai_shared;
2 #using scripts\shared\array_shared;
3 #using scripts\shared\clientfield_shared;
4 #using scripts\shared\callbacks_shared;
5 
6 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
7 #insert scripts\shared\ai\systems\animation_state_machine.gsh;
8 #insert scripts\shared\shared.gsh;
9 
10 // SUMEET TODO
11 // A very temp secondary (facial only currently) system for AI's.
12 // Need to make it data driven and support many things after DPS
13 // We can possibly use this system for any archetype to animate some bones which are
14 // purely for cosmetic reasons.
15 
16 #define FACIAL_STATE_COMBAT "combat"
17 #define FACIAL_STATE_COMBAT_AIM "combat_aim"
18 #define FACIAL_STATE_COMBAT_SHOOT "combat_shoot"
19 #define FACIAL_STATE_DEATH "death"
20 #define FACIAL_STATE_MELEE "melee"
21 #define FACIAL_STATE_PAIN "pain"
22 #define FACIAL_STATE_ANIMSCRIPTED "animscripted"
23 
24 #define FACIAL_STATE_INACTIVE "inactive"
25 
26 #define FACIAL_SYSTEM_FADE_DIST GetDvarInt( "ai_clientFacialCullDist", 2000 )
27 
28 #using_animtree( "generic" );
29 
30 function autoexec ‪main()
31 {
32  if ( SessionModeIsZombiesGame() && GetDvarInt( "splitscreen_playerCount" ) > 2 )
33  return;
34 
37 
39 }
40 
41 function private ‪SecondaryAnimationsInit( localClientNum )
42 {
43  if( !IsDefined( level.__facialAnimationsList ) )
44  {
46  }
47 
49 
50  // Handle facial animations
51  self thread ‪SecondaryFacialAnimationThink( localClientNum );
52 }
53 
54 function private ‪on_entity_spawn( localClientNum )
55 {
56  if ( self HasDObj( localClientNum ) )
57  {
58  self ClearAnim( %faces, 0 ); // stale facial anims from the previous entity may still be running
59  }
60  self._currentFaceState = ‪FACIAL_STATE_INACTIVE;
61 }
62 
63 function private ‪on_entity_shutdown( localClientNum )
64 {
65  if( isdefined( self ) )
66  {
67  self notify("stopFacialThread");
68 
69  if ( ‪IS_TRUE( self.facialDeathAnimStarted ) )
70  return;
71 
72  self ‪ApplyDeathAnim( localClientNum );
73  self.facialDeathAnimStarted = true;
74  }
75 }
76 
77 function ‪BuildAndValidateFacialAnimationList( localClientNum )
78 {
79  assert( !IsDefined( level.__facialAnimationsList ) );
80 
81  level.__facialAnimationsList = [];
82 
83  // HUMANS
84  level.__facialAnimationsList[‪ARCHETYPE_HUMAN] = [];
85  level.__facialAnimationsList[‪ARCHETYPE_HUMAN][‪FACIAL_STATE_COMBAT] = ‪array( "ai_face_male_generic_idle_1","ai_face_male_generic_idle_2","ai_face_male_generic_idle_3" );
86  level.__facialAnimationsList[‪ARCHETYPE_HUMAN][‪FACIAL_STATE_COMBAT_AIM] = ‪array( "ai_face_male_aim_idle_1","ai_face_male_aim_idle_2","ai_face_male_aim_idle_3" );
87  level.__facialAnimationsList[‪ARCHETYPE_HUMAN][‪FACIAL_STATE_COMBAT_SHOOT] = ‪array( "ai_face_male_aim_fire_1","ai_face_male_aim_fire_2","ai_face_male_aim_fire_3" );
88  level.__facialAnimationsList[‪ARCHETYPE_HUMAN][‪FACIAL_STATE_DEATH] = ‪array( "ai_face_male_death_1","ai_face_male_death_2","ai_face_male_death_3" );
89  level.__facialAnimationsList[‪ARCHETYPE_HUMAN][‪FACIAL_STATE_MELEE] = ‪array( "ai_face_male_melee_1" );
90  level.__facialAnimationsList[‪ARCHETYPE_HUMAN][‪FACIAL_STATE_PAIN] = ‪array( "ai_face_male_pain_1" );
91  level.__facialAnimationsList[‪ARCHETYPE_HUMAN][‪FACIAL_STATE_ANIMSCRIPTED] = ‪array( "ai_face_male_generic_idle_1" );
92 
93  // ZOMBIES
94  level.__facialAnimationsList[‪ARCHETYPE_ZOMBIE] = [];
95  level.__facialAnimationsList[‪ARCHETYPE_ZOMBIE][‪FACIAL_STATE_COMBAT] = ‪array( "ai_face_zombie_generic_idle_1" );
96  level.__facialAnimationsList[‪ARCHETYPE_ZOMBIE][‪FACIAL_STATE_COMBAT_AIM] = ‪array( "ai_face_zombie_generic_idle_1" );
97  level.__facialAnimationsList[‪ARCHETYPE_ZOMBIE][‪FACIAL_STATE_COMBAT_SHOOT] = ‪array( "ai_face_zombie_generic_idle_1" );
98  level.__facialAnimationsList[‪ARCHETYPE_ZOMBIE][‪FACIAL_STATE_DEATH] = ‪array( "ai_face_zombie_generic_death_1" );
99  level.__facialAnimationsList[‪ARCHETYPE_ZOMBIE][‪FACIAL_STATE_MELEE] = ‪array( "ai_face_zombie_generic_attack_1" );
100  level.__facialAnimationsList[‪ARCHETYPE_ZOMBIE][‪FACIAL_STATE_PAIN] = ‪array( "ai_face_zombie_generic_pain_1" );
101  level.__facialAnimationsList[‪ARCHETYPE_ZOMBIE][‪FACIAL_STATE_ANIMSCRIPTED] = ‪array( "ai_face_zombie_generic_idle_1" );
102 
103 
104  // validate death animations against looping flag
105  deathAnims = [];
106 
107  foreach( animation in level.__facialAnimationsList[‪ARCHETYPE_HUMAN][‪FACIAL_STATE_DEATH] )
108  {
109  ‪array::add( deathAnims, animation );
110  }
111 
112  foreach( animation in level.__facialAnimationsList[‪ARCHETYPE_ZOMBIE][‪FACIAL_STATE_DEATH] )
113  {
114  ‪array::add( deathAnims, animation );
115  }
116 
117  foreach( deathAnim in deathAnims )
118  {
119  assert( !IsAnimLooping( localClientNum, deathAnim ), "FACIAL ANIM - Death facial animation " + deathAnim + " is set to looping in the GDT. It needs to be non-looping." );
120  }
121 }
122 
123 function private ‪GetFacialAnimOverride( localClientNum )
124 {
125  if ( SessionModeIsCampaignGame() )
126  {
127  // get the primary delta anim and see if it has any notetracks
128  primaryDeltaAnim = self GetPrimaryDeltaAnim();
129  if ( isdefined( primaryDeltaAnim ) )
130  {
131  primaryDeltaAnimLength = GetAnimLength( primaryDeltaAnim );
132  notetracks = GetNotetracksInDelta( primaryDeltaAnim, 0, 1 );
133  foreach( notetrack in notetracks )
134  {
135  if ( notetrack[1] == "facial_anim" )
136  {
137  facialAnim = notetrack[2];
138  facialAnimLength = GetAnimLength( facialAnim );
139 
140  /#
141  if ( facialAnimLength < primaryDeltaAnimLength && !IsAnimLooping( localClientNum, facialAnim ) )
142  {
143  //println( "Found facial anim '" + facialAnim + "' that is shorter than the fullbody anim '" + primaryDeltaAnim + "' it will be played on." );
144  }
145  #/
146 
147  return facialAnim;
148  }
149  }
150  }
151  }
152 
153  return undefined;
154 }
155 
156 function private ‪SecondaryFacialAnimationThink( localClientNum )
157 {
158  assert( IsDefined( self.archetype ) && ( self.archetype == ‪ARCHETYPE_HUMAN || self.archetype == ‪ARCHETYPE_ZOMBIE ) );
159 
160  self endon ("entityshutdown");
161  self endon ("stopFacialThread");
162 
163  self._currentFaceState = ‪FACIAL_STATE_INACTIVE;
164 
165  while(1)
166  {
167  if( self.archetype == ‪ARCHETYPE_HUMAN && self ‪clientfield::get( ‪HUMAN_FACIAL_DIALOG_ACTIVE ) )
168  {
169  self._currentFaceState = ‪FACIAL_STATE_INACTIVE;
170  self ‪ClearCurrentFacialAnim(localClientNum);
171 
172  wait 0.5;
173  continue;
174  }
175 
176  animOverride = self ‪GetFacialAnimOverride( localClientNum );
177 
178  asmStatus = self ASMGetStatus( localClientNum );
179  forceNewAnim = false;
180 
181  switch(asmStatus)
182  {
184  //ClearCurrentFacialAnim(localClientNum);
185  return;
186 
188  // we're in the animscripted state -- allow facial anims
189  if ( isdefined( animOverride ) )
190  {
191  // did we just start playing a new primary delta anim?
192  scriptedAnim = self GetPrimaryDeltaAnim();
193  if ( isdefined( scriptedAnim ) && ( !isdefined( self._scriptedAnim ) || self._scriptedAnim != scriptedAnim ) )
194  {
195  self._scriptedAnim = scriptedAnim;
196  forceNewAnim = true;
197  }
198  if ( isdefined( animOverride ) && animOverride !== self._currentFaceAnim )
199  {
200  forceNewAnim = true;
201  }
202  }
203  else
204  {
205  if ( self._currentFaceState !== ‪FACIAL_STATE_DEATH )
206  {
207  self._currentFaceState = ‪FACIAL_STATE_INACTIVE;
208  self ‪ClearCurrentFacialAnim(localClientNum);
209  }
210 
211  wait 0.5;
212  continue;
213  }
214  }
215 
216  closestPlayer = ArrayGetClosest( self.origin, level.localPlayers, ‪FACIAL_SYSTEM_FADE_DIST );
217 
218  if( !IsDefined( closestPlayer ) )
219  {
220  wait 0.5;
221  continue;
222  }
223 
224  if( !self HasDObj(localClientNum) || !self HasAnimTree() )
225  {
226  wait 0.5;
227  continue;
228  }
229 
230  currFaceState = self._currentFaceState;
231  currentASMState = self ASMGetCurrentState( localClientNum );
232  if( isdefined( currentASMState ) )
233  {
234  currentASMState = ToLower( currentASMState );
235  }
236 
237  if( self ASMIsTerminating( localClientNum ) )
238  {
239  nextFaceState = ‪FACIAL_STATE_DEATH;
240  }
241  else if( asmStatus == ‪ASM_STATE_INACTIVE )
242  {
243  nextFaceState = ‪FACIAL_STATE_ANIMSCRIPTED;
244  }
245  else if( IsDefined( currentASMState ) && IsSubStr( currentASMState, "pain" ) )
246  {
247  nextFaceState = ‪FACIAL_STATE_PAIN;
248  }
249  else if( IsDefined( currentASMState ) && IsSubStr( currentASMState, "melee" ) )
250  {
251  nextFaceState = ‪FACIAL_STATE_MELEE;
252  }
253  else if( self ASMIsShootLayerActive( localClientNum ) )
254  {
255  nextFaceState = ‪FACIAL_STATE_COMBAT_SHOOT;
256  }
257  else if( self ASMIsAimLayerActive( localClientNum ) )
258  {
259  nextFaceState = ‪FACIAL_STATE_COMBAT_AIM;
260  }
261  else
262  {
263  nextFaceState = ‪FACIAL_STATE_COMBAT;
264  }
265 
266  if( currFaceState == ‪FACIAL_STATE_INACTIVE || currFaceState != nextFaceState || forceNewAnim )
267  {
268  Assert( IsDefined( level.__facialAnimationsList[self.archetype][nextFaceState] ) );
269 
270  clearOnCompletion = false;
271 
272  if( nextFaceState == ‪FACIAL_STATE_DEATH )
273  {
274  //clearOnCompletion = true;
275  }
276 
277  animToPlay = array::random( level.__facialAnimationsList[self.archetype][nextFaceState] );
278  if ( isdefined( animOverride ) )
279  {
280  animToPlay = animOverride;
281  assert( nextFaceState != ‪FACIAL_STATE_DEATH || !IsAnimLooping( localClientNum, animToPlay ), "FACIAL ANIM - Death facial animation " + animToPlay + " is set to looping in the GDT. It needs to be non-looping." );
282  }
283 
284  ‪ApplyNewFaceAnim( localClientNum, animToPlay, clearOnCompletion );
285  self._currentFaceState = nextFaceState;
286  }
287 
288  if( self._currentFaceState == ‪FACIAL_STATE_DEATH )
289  break;
290 
291  wait 0.25;
292  }
293 }
294 
295 function private ‪ApplyNewFaceAnim( localClientNum, animation, clearOnCompletion = false )
296 {
297  ‪ClearCurrentFacialAnim(localClientNum);
298 
299  if( IsDefined( animation ) )
300  {
301  self._currentFaceAnim = animation;
302 
303  if( self HasDObj(localClientNum) && self HasAnimTree() )
304  {
305  self SetFlaggedAnimKnob( "ai_secondary_facial_anim", animation, 1.0, 0.1, 1.0 );
306 
307  if( clearOnCompletion )
308  {
309  wait( GetAnimLength( animation ) );
310  ‪ClearCurrentFacialAnim(localClientNum);
311  }
312  }
313  }
314 }
315 
316 function private ‪ApplyDeathAnim( localClientNum )
317 {
318  if( IsDefined( self._currentFaceState ) && self._currentFaceState == ‪FACIAL_STATE_DEATH )
319  return;
320 
321  if ( GetMigrationStatus(localClientNum) )
322  return;
323 
324  if( IsDefined( self ) &&
325  IsDefined( level.__facialAnimationsList ) &&
326  IsDefined( level.__facialAnimationsList[self.archetype] ) &&
327  IsDefined( level.__facialAnimationsList[self.archetype][‪FACIAL_STATE_DEATH] ) )
328  {
329  animToPlay = array::random( level.__facialAnimationsList[self.archetype][‪FACIAL_STATE_DEATH] );
330  animOverride = self ‪GetFacialAnimOverride( localClientNum );
331  if ( isdefined( animOverride ) )
332  {
333  animToPlay = animOverride;
334  }
335 
336  self._currentFaceState = ‪FACIAL_STATE_DEATH;
337  ‪ApplyNewFaceAnim( localClientNum, animToPlay );
338  }
339 }
340 
341 function private ‪ClearCurrentFacialAnim(localClientNum)
342 {
343  if( IsDefined( self._currentFaceAnim ) && self HasDObj(localClientNum) && self HasAnimTree() )
344  {
345  self ClearAnim( self._currentFaceAnim, 0.2 );
346  }
347 
348  self._currentFaceAnim = undefined;
349 }
‪SecondaryAnimationsInit
‪function private SecondaryAnimationsInit(localClientNum)
Definition: archetype_secondary_animations.csc:41
‪ASM_STATE_INACTIVE
‪#define ASM_STATE_INACTIVE
Definition: animation_state_machine.gsh:13
‪FACIAL_STATE_ANIMSCRIPTED
‪#define FACIAL_STATE_ANIMSCRIPTED
Definition: archetype_secondary_animations.csc:22
‪on_entity_spawn
‪function private on_entity_spawn(localClientNum)
Definition: archetype_secondary_animations.csc:54
‪SecondaryFacialAnimationThink
‪function private SecondaryFacialAnimationThink(localClientNum)
Definition: archetype_secondary_animations.csc:156
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪FACIAL_STATE_PAIN
‪#define FACIAL_STATE_PAIN
Definition: archetype_secondary_animations.csc:21
‪get
‪function get(kvp_value, kvp_key="targetname")
Definition: struct.csc:13
‪add
‪function add(entity, dyingplayer, team, timeout)
Definition: _deathicons.gsc:43
‪ApplyNewFaceAnim
‪function private ApplyNewFaceAnim(localClientNum, animation, clearOnCompletion=false)
Definition: archetype_secondary_animations.csc:295
‪ASM_STATE_TERMINATED
‪#define ASM_STATE_TERMINATED
Definition: animation_state_machine.gsh:17
‪FACIAL_STATE_MELEE
‪#define FACIAL_STATE_MELEE
Definition: archetype_secondary_animations.csc:20
‪ClearCurrentFacialAnim
‪function private ClearCurrentFacialAnim(localClientNum)
Definition: archetype_secondary_animations.csc:341
‪HUMAN_FACIAL_DIALOG_ACTIVE
‪#define HUMAN_FACIAL_DIALOG_ACTIVE
Definition: archetype_shared.gsh:56
‪FACIAL_STATE_COMBAT_SHOOT
‪#define FACIAL_STATE_COMBAT_SHOOT
Definition: archetype_secondary_animations.csc:18
‪FACIAL_STATE_COMBAT_AIM
‪#define FACIAL_STATE_COMBAT_AIM
Definition: archetype_secondary_animations.csc:17
‪FACIAL_STATE_INACTIVE
‪#define FACIAL_STATE_INACTIVE
Definition: archetype_secondary_animations.csc:24
‪array
‪function filter array
Definition: array_shared.csc:16
‪main
‪function autoexec main()
Definition: archetype_secondary_animations.csc:30
‪ARCHETYPE_ZOMBIE
‪#define ARCHETYPE_ZOMBIE
Definition: archetype_shared.gsh:10
‪FACIAL_STATE_DEATH
‪#define FACIAL_STATE_DEATH
Definition: archetype_secondary_animations.csc:19
‪add_archetype_spawn_function
‪function add_archetype_spawn_function(archetype, spawn_func)
Definition: ai_shared.csc:23
‪BuildAndValidateFacialAnimationList
‪function BuildAndValidateFacialAnimationList(localClientNum)
Definition: archetype_secondary_animations.csc:77
‪FACIAL_SYSTEM_FADE_DIST
‪#define FACIAL_SYSTEM_FADE_DIST
Definition: archetype_secondary_animations.csc:26
‪on_entity_shutdown
‪function private on_entity_shutdown(localClientNum)
Definition: archetype_secondary_animations.csc:63
‪add_ai_spawn_function
‪function add_ai_spawn_function(spawn_func)
Definition: ai_shared.csc:10
‪ARCHETYPE_HUMAN
‪#define ARCHETYPE_HUMAN
Definition: archetype_shared.gsh:4
‪GetFacialAnimOverride
‪function private GetFacialAnimOverride(localClientNum)
Definition: archetype_secondary_animations.csc:123
‪on_shutdown
‪function on_shutdown(func, obj)
Definition: callbacks_shared.csc:272
‪ApplyDeathAnim
‪function private ApplyDeathAnim(localClientNum)
Definition: archetype_secondary_animations.csc:316
‪FACIAL_STATE_COMBAT
‪#define FACIAL_STATE_COMBAT
Definition: archetype_secondary_animations.csc:16