‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
clientfaceanim_shared.csc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 #using scripts\shared\array_shared;
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\system_shared;
5 #using scripts\shared\util_shared;
6 
7 #insert scripts\shared\shared.gsh;
8 
9 // SUMEET TODO
10 // A very temp facial animation system for players for April 13th Demo.
11 // After the demo, I will be looking at adding mode support and make it data driven.
12 
13 #namespace clientfaceanim;
14 
15 ‪REGISTER_SYSTEM_EX( "clientfaceanim_shared", undefined, &‪main, undefined )
16 
17 #define FACIAL_STATE_COMBAT "combat"
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_SWIMMING "swimming"
23 #define FACIAL_STATE_JUMPING "jumping"
24 #define FACIAL_STATE_SLIDING "sliding"
25 #define FACIAL_STATE_SPRINTING "sprinting"
26 #define FACIAL_STATE_WALLRUNNING "wallrunning"
27 
28 #define FACIAL_STATE_INACTIVE "inactive"
29 #define FACIAL_SYSTEM_FADE_DIST 1000
30 #define FACIAL_SYSTEM_FADE_DISTSQ 1000 * 1000
31 
32 function ‪main()
33 {
35  level._clientFaceAnimOnPlayerSpawned = &‪on_player_spawned;
36 }
37 
38 function private ‪on_player_spawned( localClientNum )
39 {
40  ‪FacialAnimationsInit( localClientNum );
41 
43 
44  // local player needs to handle the death as they dont get shutdown on death
45  self thread ‪on_player_death( localClientNum );
46 }
47 
48 function private ‪on_player_shutdown( localClientNum )
49 {
50  if( self IsPlayer() )
51  {
52  self notify("stopFacialThread");
53 
54  corpse = self GetPlayerCorpse();
55  if ( !isDefined( corpse ) )
56  return;
57  if ( ‪IS_TRUE( corpse.facialDeathAnimStarted ) )
58  return;
59 
60  corpse ‪util::waittill_dobj( localClientNum );
61  if ( isDefined( corpse ) )
62  {
63  corpse ‪ApplyDeathAnim( localClientNum );
64  corpse.facialDeathAnimStarted = true;
65  }
66  }
67 }
68 
69 function private ‪on_player_death( localClientNum )
70 {
71  self endon("entityshutdown");
72  self waittill("death");
73 
74  if( self IsPlayer() )
75  {
76  self notify("stopFacialThread");
77 
78  corpse = self GetPlayerCorpse();
79  if ( ‪IS_TRUE( corpse.facialDeathAnimStarted ) )
80  return;
81 
82  corpse ‪util::waittill_dobj( localClientNum );
83  if ( isDefined( corpse ) )
84  {
85  corpse ‪ApplyDeathAnim( localClientNum );
86  corpse.facialDeathAnimStarted = true;
87  }
88  }
89 }
90 
91 function private ‪FacialAnimationsInit( localClientNum )
92 {
93  ‪BuildAndValidateFacialAnimationList( localClientNum );
94 
95  if( self IsPlayer() )
96  {
97  self thread ‪FacialAnimationThink( localClientNum );
98  }
99 }
100 
101 function ‪BuildAndValidateFacialAnimationList( localClientNum )
102 {
103  if( !IsDefined( level.__clientFacialAnimationsList ) )
104  {
105  level.__clientFacialAnimationsList = [];
106 
107  level.__clientFacialAnimationsList[‪FACIAL_STATE_COMBAT] = ‪array( "ai_face_male_generic_idle_1","ai_face_male_generic_idle_2","ai_face_male_generic_idle_3" );
108  level.__clientFacialAnimationsList[‪FACIAL_STATE_COMBAT_SHOOT] = ‪array( "ai_face_male_aim_fire_1","ai_face_male_aim_fire_2","ai_face_male_aim_fire_3" );
109  level.__clientFacialAnimationsList[‪FACIAL_STATE_DEATH] = ‪array( "ai_face_male_death_1","ai_face_male_death_2","ai_face_male_death_3" );
110  level.__clientFacialAnimationsList[‪FACIAL_STATE_MELEE] = ‪array( "ai_face_male_melee_1" );
111  level.__clientFacialAnimationsList[‪FACIAL_STATE_PAIN] = ‪array( "ai_face_male_pain_1" );
112  level.__clientFacialAnimationsList[‪FACIAL_STATE_SWIMMING] = ‪array( "mp_face_male_swim_idle_1" );
113  level.__clientFacialAnimationsList[‪FACIAL_STATE_JUMPING] = ‪array( "mp_face_male_jump_idle_1" );
114  level.__clientFacialAnimationsList[‪FACIAL_STATE_SLIDING] = ‪array( "mp_face_male_slides_1" );
115  level.__clientFacialAnimationsList[‪FACIAL_STATE_SPRINTING] = ‪array( "mp_face_male_sprint_1" );
116  level.__clientFacialAnimationsList[‪FACIAL_STATE_WALLRUNNING]= ‪array( "mp_face_male_wall_run_1" );
117 
118  // validate death animations against looping flag
119  deathAnims = level.__clientFacialAnimationsList[‪FACIAL_STATE_DEATH];
120 
121  foreach( deathAnim in deathAnims )
122  {
123  assert( !IsAnimLooping( localClientNum, deathAnim ), "FACIAL ANIM - Death facial animation " + deathAnim + " is set to looping in the GDT. It needs to be non-looping." );
124  }
125  }
126 }
127 
128 function private ‪FacialAnimationThink_getWaitTime( localClientNum )
129 {
130  if ( !isdefined( localClientNum ) )
131  return 1.0;
132 
133  // make defines
134  min_wait = 0.1;
135  max_wait = 1.0;
136  min_wait_distance_sq = 50 * 50;
137  max_wait_distance_sq = 800 * 800;
138 
139  local_player = GetLocalPlayer( localClientNum );
140 
141  if ( !isdefined( local_player ) )
142  return max_wait;
143 
144  if ( local_player == self && !IsThirdPerson( localClientNum ) )
145  return max_wait;
146 
147  distanceSq = DistanceSquared( local_player.origin, self.origin );
148 
149  if ( (distanceSq > max_wait_distance_sq) )
150  distance_factor = 1;
151  else if ( (distanceSq < min_wait_distance_sq) )
152  distance_factor = 0;
153  else
154  distance_factor = (distanceSq - min_wait_distance_sq) / (max_wait_distance_sq - min_wait_distance_sq);
155 
156  return ((max_wait - min_wait) * distance_factor) + min_wait;
157 }
158 
159 function private ‪FacialAnimationThink( localClientNum )
160 {
161  self endon ("entityshutdown");
162  self notify("stopFacialThread");
163  self endon("stopFacialThread");
164 
165  // Facial animation only required to be initialized for one local client.
166  if( IsDefined( self.__clientFacialAnimationsThinkStarted ) )
167  return;
168 
169  self.__clientFacialAnimationsThinkStarted = true;
170 
171  assert( self IsPlayer() );
172 
173  self ‪util::waittill_dobj( localClientNum );
174 
175  while( isdefined( self ) )
176  {
177  ‪UpdateFacialAnimForPlayer( localClientNum, self );
178 
179  wait_time = self ‪FacialAnimationThink_getWaitTime(localClientNum);
180 
181  ‪DEFAULT( wait_time, 1.0 );
182 
183  wait wait_time;
184  }
185 }
186 
187 function private ‪UpdateFacialAnimForPlayer( localClientNum, player )
188 {
189  if ( !isdefined( player ) )
190  return;
191 
192  if ( !isdefined( localClientNum ) )
193  return;
194 
195  if( !IsDefined( player._currentFaceState ) )
196  player._currentFaceState = ‪FACIAL_STATE_INACTIVE;
197 
198  currFaceState = player._currentFaceState;
199  nextFaceState = player._currentFaceState;
200 
201  if( player IsInScritpedAnim() )
202  {
203  ‪ClearAllFacialAnims(localClientNum);
204 
205  player._currentFaceState = ‪FACIAL_STATE_INACTIVE;
206  return;
207  }
208 
209  if( player IsPlayerDead() )
210  {
211  nextFaceState = ‪FACIAL_STATE_DEATH;
212  }
213  else if( player IsPlayerFiring() )
214  {
215  nextFaceState = ‪FACIAL_STATE_COMBAT_SHOOT;
216  }
217  else if( player IsPlayerSliding() )
218  {
219  nextFaceState = ‪FACIAL_STATE_SLIDING;
220  }
221  else if( player IsPlayerWallRunning() )
222  {
223  nextFaceState = ‪FACIAL_STATE_WALLRUNNING;
224  }
225  // sprint needs to be above the jumping because jumping stays on for a while
226  else if( player IsPlayerSprinting() )
227  {
228  nextFaceState = ‪FACIAL_STATE_SPRINTING;
229  }
230  else if( player IsPlayerJumping() || player IsPlayerDoubleJumping() )
231  {
232  nextFaceState = ‪FACIAL_STATE_JUMPING;
233  }
234  else if( player IsPlayerSwimming() )
235  {
236  nextFaceState = ‪FACIAL_STATE_SWIMMING;
237  }
238  else
239  {
240  nextFaceState = ‪FACIAL_STATE_COMBAT;
241  }
242 
243  if( player._currentFaceState == ‪FACIAL_STATE_INACTIVE || currFaceState != nextFaceState )
244  {
245  Assert( IsDefined( level.__clientFacialAnimationsList[nextFaceState] ) );
246 
247  ‪ApplyNewFaceAnim( localClientNum, array::random( level.__clientFacialAnimationsList[nextFaceState] ) );
248  player._currentFaceState = nextFaceState;
249  }
250 }
251 
252 function private ‪ApplyNewFaceAnim( localClientNum, animation )
253 {
254  ‪ClearAllFacialAnims(localClientNum);
255 
256  if( IsDefined( animation ) )
257  {
258  self._currentFaceAnim = animation;
259  self SetFlaggedAnimKnob( "ai_secondary_facial_anim", animation, 1.0, 0.1, 1.0 );
260  }
261 }
262 
263 function private ‪ApplyDeathAnim( localClientNum )
264 {
265  if( IsDefined( self._currentFaceState ) && self._currentFaceState == ‪FACIAL_STATE_DEATH )
266  return;
267 
268  if( IsDefined( self ) && IsDefined( level.__clientFacialAnimationsList ) && IsDefined( level.__clientFacialAnimationsList[‪FACIAL_STATE_DEATH] ) )
269  {
270  self._currentFaceState = ‪FACIAL_STATE_DEATH;
271  ‪ApplyNewFaceAnim( localClientNum, array::random( level.__clientFacialAnimationsList[‪FACIAL_STATE_DEATH] ) );
272  }
273 }
274 
275 function private ‪ClearAllFacialAnims(localClientNum)
276 {
277  if( IsDefined( self._currentFaceAnim ) && self hasdobj(localClientNum) )
278  {
279  self ClearAnim( self._currentFaceAnim, 0.2 );
280  }
281  self._currentFaceAnim = undefined;
282 }
‪UpdateFacialAnimForPlayer
‪function private UpdateFacialAnimForPlayer(localClientNum, player)
Definition: clientfaceanim_shared.csc:187
‪ClearAllFacialAnims
‪function private ClearAllFacialAnims(localClientNum)
Definition: clientfaceanim_shared.csc:275
‪FACIAL_STATE_DEATH
‪#define FACIAL_STATE_DEATH
Definition: clientfaceanim_shared.csc:19
‪ApplyDeathAnim
‪function private ApplyDeathAnim(localClientNum)
Definition: clientfaceanim_shared.csc:263
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪on_player_death
‪function private on_player_death(localClientNum)
Definition: clientfaceanim_shared.csc:69
‪DEFAULT
‪#define DEFAULT(__var, __default)
Definition: shared.gsh:270
‪on_spawned
‪function on_spawned(func, obj)
Definition: callbacks_shared.csc:245
‪on_player_shutdown
‪function private on_player_shutdown(localClientNum)
Definition: clientfaceanim_shared.csc:48
‪FacialAnimationThink
‪function private FacialAnimationThink(localClientNum)
Definition: clientfaceanim_shared.csc:159
‪REGISTER_SYSTEM_EX
‪#define REGISTER_SYSTEM_EX(__sys, __func_init_preload, __func_init_postload, __reqs)
Definition: shared.gsh:209
‪FACIAL_STATE_PAIN
‪#define FACIAL_STATE_PAIN
Definition: clientfaceanim_shared.csc:21
‪FACIAL_STATE_SWIMMING
‪#define FACIAL_STATE_SWIMMING
Definition: clientfaceanim_shared.csc:22
‪array
‪function filter array
Definition: array_shared.csc:16
‪BuildAndValidateFacialAnimationList
‪function BuildAndValidateFacialAnimationList(localClientNum)
Definition: clientfaceanim_shared.csc:101
‪FACIAL_STATE_SPRINTING
‪#define FACIAL_STATE_SPRINTING
Definition: clientfaceanim_shared.csc:25
‪FACIAL_STATE_MELEE
‪#define FACIAL_STATE_MELEE
Definition: clientfaceanim_shared.csc:20
‪main
‪function main()
Definition: clientfaceanim_shared.csc:32
‪FacialAnimationsInit
‪function private FacialAnimationsInit(localClientNum)
Definition: clientfaceanim_shared.csc:91
‪FACIAL_STATE_WALLRUNNING
‪#define FACIAL_STATE_WALLRUNNING
Definition: clientfaceanim_shared.csc:26
‪on_player_spawned
‪function private on_player_spawned(localClientNum)
Definition: clientfaceanim_shared.csc:38
‪waittill_dobj
‪function waittill_dobj(localClientNum)
Definition: util_shared.csc:1117
‪FACIAL_STATE_COMBAT_SHOOT
‪#define FACIAL_STATE_COMBAT_SHOOT
Definition: clientfaceanim_shared.csc:18
‪FACIAL_STATE_SLIDING
‪#define FACIAL_STATE_SLIDING
Definition: clientfaceanim_shared.csc:24
‪ApplyNewFaceAnim
‪function private ApplyNewFaceAnim(localClientNum, animation)
Definition: clientfaceanim_shared.csc:252
‪FACIAL_STATE_JUMPING
‪#define FACIAL_STATE_JUMPING
Definition: clientfaceanim_shared.csc:23
‪FacialAnimationThink_getWaitTime
‪function private FacialAnimationThink_getWaitTime(localClientNum)
Definition: clientfaceanim_shared.csc:128
‪FACIAL_STATE_COMBAT
‪#define FACIAL_STATE_COMBAT
Definition: clientfaceanim_shared.csc:17
‪FACIAL_STATE_INACTIVE
‪#define FACIAL_STATE_INACTIVE
Definition: clientfaceanim_shared.csc:28
‪on_shutdown
‪function on_shutdown(func, obj)
Definition: callbacks_shared.csc:272