‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
archetype_mocomps_utility.gsc
Go to the documentation of this file.
1 #using scripts\shared\ai\systems\animation_state_machine_mocomp;
2 #using scripts\shared\ai\systems\animation_state_machine_utility;
3 #using scripts\shared\ai\systems\behavior_tree_utility;
4 #using scripts\shared\ai\systems\blackboard;
5 #using scripts\shared\ai\archetype_utility;
6 
7 #insert scripts\shared\ai\systems\animation_state_machine.gsh;
8 #insert scripts\shared\ai\systems\behavior.gsh;
9 #insert scripts\shared\ai\systems\behavior_tree.gsh;
10 #insert scripts\shared\ai\systems\blackboard.gsh;
11 #insert scripts\shared\ai\utility.gsh;
12 #insert scripts\shared\shared.gsh;
13 
14 //*****************************************************************************
15 // NOTE! When adding a new motion compensator you must also declare the
16 // mocomp within the ast_definitions file found at:
17 //
18 // //t7/main/game/share/raw/animtables/ast_definitions.json
19 //
20 // You should add the new mocomp to the list of "possibleValues" for the
21 // "_animation_mocomp" animation selector table column.
22 //
23 // This allows the AI Editor to know about all possible mocomps that can be
24 // used.
25 //
26 //*****************************************************************************
27 
29 {
30  // mocomps have been moved into code now, although you can still add new ones here
31 
33  ‪ASM_REGISTER_MOCOMP( "locomotion_explosion_death", &‪mocompLocoExplosionInit, undefined, undefined );
34  ‪ASM_REGISTER_MOCOMP( "mocomp_flank_stand", &‪mocompFlankStandInit, undefined, undefined );
35 }
36 
37 #define COVER_ANY "cover_any"
38 #define STANCE_ANY "stance_any"
39 
40 function autoexec ‪InitAdjustToCoverParams()
41 {
42  // These values represent the normalized time the motion compensator should start procedurally orienting toward the node's forward offset.
43  // Since only four adjust animations exist, a lot of care in choosing the correct normalized time has to be taken to cover the full 360 degree range.
44 
45  // Adjust animations should end promptly as soon as the cover pose is reached. If additional "settle" frames exist at the end of the animation
46  // this will cause the adjust to cover mocomp to overshoot the desired angle.
47 
48  // If a normalized time is set too low, this can cause animations to rotate in the wrong direction.
49 
50  // 3 32 2 21 1
51  // 63 14
52  // 6 X 4
53  // 96 47
54  // 9 89 8 78 7
55 
56  // directions 2 32 3 63 6 96 9 89 8 78 7 47 4 14 1 21
57  ‪_AddAdjustToCover( "human", ‪COVER_ANY, ‪STANCE_ANY, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.9, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 );
58 
59  ‪_AddAdjustToCover( "human", ‪COVER_STAND, ‪STANCE_ANY, 0.4, 0.8, 0.6, 0.4, 0.6, 0.3, 0.3, 0.6, 0.9, 0.6, 0.3, 0.4, 0.7, 0.6, 0.6, 0.6 );
60  ‪_AddAdjustToCover( "human", ‪COVER_CROUCH, ‪STANCE_ANY, 0.4, 0.4, 0.4, 0.4, 0.8, 0.5, 0.2, 0.7, 0.9, 0.4, 0.2, 0.4, 0.5, 0.5, 0.5, 0.5 );
61 
62  ‪_AddAdjustToCover( "human", ‪COVER_LEFT, ‪STANCE_STAND, 0.8, 0.4, 0.4, 0.4, 0.4, 0.7, 0.3, 0.5, 0.8, 0.8, 0.8, 0.9, 0.6, 0.6, 0.4, 0.4 );
63  ‪_AddAdjustToCover( "human", ‪COVER_LEFT, ‪STANCE_CROUCH, 0.8, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.8, 0.8, 0.7, 0.6, 0.6, 0.4, 0.4 );
64 
65  ‪_AddAdjustToCover( "human", ‪COVER_RIGHT, ‪STANCE_STAND, 0.8, 0.4, 0.3, 0.4, 0.6, 0.8, 0.4, 0.4, 0.4, 0.4, 0.3, 0.4, 0.6, 0.6, 0.5, 0.4 );
66  ‪_AddAdjustToCover( "human", ‪COVER_RIGHT, ‪STANCE_CROUCH, 0.8, 0.4, 0.2, 0.4, 0.4, 0.7, 0.2, 0.3, 0.3, 0.5, 0.5, 0.7, 0.6, 0.6, 0.5, 0.4 );
67 
68  ‪_AddAdjustToCover( "human", ‪COVER_PILLAR, ‪STANCE_ANY, 0.8, 0.7, 0.6, 0.7, 0.6, 0.5, 0.4, 0.4, 0.4, 0.6, 0.4, 0.3, 0.7, 0.5, 0.1, 0.7 );
69 
70  ‪_AddAdjustToCover( "robot", ‪COVER_ANY, ‪STANCE_ANY, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.6, 0.7, 0.5, 0.5, 0.5, 0.5, 0.4, 0.4, 0.4 );
71  ‪_AddAdjustToCover( "robot", ‪COVER_EXPOSED, ‪STANCE_ANY, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.9, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 );
72 }
73 
74 function private ‪_AddAdjustToCover(
75  archetype, node, stance, rot2, rot32, rot3, rot36, rot6, rot69, rot9, rot98, rot8, rot87, rot7, rot47, rot4, rot14, rot1, rot21 )
76 {
77  if ( !IsDefined( level.adjustToCover ) )
78  {
79  level.adjustToCover = [];
80  }
81 
82  if ( !IsDefined( level.adjustToCover[ archetype ] ) )
83  {
84  level.adjustToCover[ archetype ] = [];
85  }
86 
87  if ( !IsDefined( level.adjustToCover[ archetype ][ node ] ) )
88  {
89  level.adjustToCover[ archetype ][ node ] = [];
90  }
91 
92  directions = [];
93  directions[ 2 ] = rot2;
94  directions[ 32 ] = rot32;
95  directions[ 3 ] = rot3;
96  directions[ 63 ] = rot36;
97  directions[ 6 ] = rot6;
98  directions[ 96 ] = rot69;
99  directions[ 9 ] = rot9;
100  directions[ 89 ] = rot98;
101  directions[ 8 ] = rot8;
102  directions[ 78 ] = rot87;
103  directions[ 7 ] = rot7;
104  directions[ 47 ] = rot47;
105  directions[ 4 ] = rot4;
106  directions[ 14 ] = rot14;
107  directions[ 1 ] = rot1;
108  directions[ 21 ] = rot21;
109 
110  level.adjustToCover[ archetype ][ node ][ stance ] = directions;
111 }
112 
113 // Angle to node within this angle [0, 360).
114 function private ‪_GetAdjustToCoverRotation( archetype, node, stance, angleToNode )
115 {
116  assert( IsArray( level.adjustToCover[ archetype ] ) );
117 
118  if ( !IsDefined( level.adjustToCover[ archetype ][ node ] ) )
119  {
120  node = ‪COVER_ANY;
121  }
122 
123  assert( IsArray( level.adjustToCover[ archetype ][ node ] ) );
124 
125  if ( !IsDefined( level.adjustToCover[ archetype ][ node ][ stance ] ) )
126  {
127  stance = ‪STANCE_ANY;
128  }
129 
130  assert( IsArray( level.adjustToCover[ archetype ][ node ][ stance ] ) );
131  assert( angleToNode >= 0 && angleToNode < 360 );
132 
133  direction = undefined;
134 
135  // Convert angles to a direction on the keypad.
136  // Direction 2 is forward, and 0 degrees.
137  // Angles are counter clockwise.
138  //
139  // 3 32 2 21 1
140  // 63 14
141  // 6 X 4
142  // 96 47
143  // 9 89 8 78 7
144 
145  if ( angletonode < 11.25 )
146  direction = 2;
147  else if ( angletonode < 33.75 )
148  direction = 32;
149  else if ( angletonode < 56.25 )
150  direction = 3;
151  else if ( angletonode < 78.75 )
152  direction = 63;
153  else if ( angletonode < 101.25 )
154  direction = 6;
155  else if ( angletonode < 123.75 )
156  direction = 96;
157  else if ( angletonode < 146.25 )
158  direction = 9;
159  else if ( angletonode < 168.75 )
160  direction = 89;
161  else if ( angletonode < 191.25 )
162  direction = 8;
163  else if ( angletonode < 213.75 )
164  direction = 78;
165  else if ( angletonode < 236.25 )
166  direction = 7;
167  else if ( angletonode < 258.75 )
168  direction = 47;
169  else if ( angletonode < 281.25 )
170  direction = 4;
171  else if ( angletonode < 303.75 )
172  direction = 14;
173  else if ( angletonode < 326.25 )
174  direction = 1;
175  else if ( angletonode < 348.75 )
176  direction = 21;
177  else
178  direction = 2;
179 
180  assert( IsDefined( level.adjustToCover[archetype][ node ][ stance ][ direction ] ) );
181 
182  adjustTime = level.adjustToCover[archetype][ node ][ stance ][ direction ];
183 
184  if ( IsDefined( adjustTime ) )
185  {
186  return adjustTime;
187  }
188 
189  // Fallback in ship builds.
190  return 0.8;
191 }
192 
193 function private ‪debugLocoExplosion( entity )
194 {
195  entity endon( "death" );
196 
197  /#
198  startOrigin = entity.origin;
199  startYawForward = AnglesToForward( ( 0, entity.angles[1], 0 ) );
200  damageYawForward = AnglesToForward( ( 0, entity.damageyaw - entity.angles[1], 0 ) );
201 
202  ‪startTime = GetTime();
203 
204  while ( GetTime() - ‪startTime < 10000 )
205  {
206  RecordSphere( startOrigin, 5, ‪RED, "Animscript", entity );
207  RecordLine( startOrigin, startOrigin + startYawForward * 100, ‪BLUE, "Animscript", entity );
208  RecordLine( startOrigin, startOrigin + damageYawForward * 100, ‪RED, "Animscript", entity );
209 
211  }
212  #/
213 }
214 
215 function private ‪mocompFlankStandInit( entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration )
216 {
217  entity AnimMode( ‪AI_ANIM_USE_BOTH_DELTAS_NOGRAVITY, false );
218  entity OrientMode( "face angle", entity.angles[1] );
219 
220  entity PathMode( "move delayed", false, RandomFloatRange( 0.5, 1.0 ) );
221 
222  if ( IsDefined( entity.enemy ) )
223  {
224  entity GetPerfectInfo( entity.enemy );
225  entity.newEnemyReaction = false;
226  }
227 }
228 
229 function private ‪mocompLocoExplosionInit( entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration )
230 {
231  entity AnimMode( ‪AI_ANIM_USE_BOTH_DELTAS_NOGRAVITY, false );
232  entity OrientMode( "face angle", entity.angles[1] );
233 
234  /#
235  if ( GetDvarInt( "ai_debugLocoExplosionMocomp" ) )
236  {
237  entity thread ‪debugLocoExplosion( entity );
238  }
239  #/
240 }
241 
242 #define MAX_MOVE_DISTANCE 1
243 
244 function private ‪mocompAdjustToCoverInit( entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration )
245 {
246  entity OrientMode( "face angle", entity.angles[1] );
247  entity AnimMode( ‪AI_ANIM_USE_ANGLE_DELTAS, false );
248  entity.blockingPain = true;
249 
250  if ( IsDefined( entity.node ) )
251  {
252  entity.adjustNode = entity.node;
253  entity.nodeOffsetOrigin = entity GetNodeOffsetPosition( entity.node );
254  entity.nodeOffsetAngles = entity GetNodeOffsetAngles( entity.node );
255  entity.nodeOffsetForward = AnglesToForward( entity.nodeOffsetAngles );
256  entity.nodeForward = AnglesToForward( entity.node.angles );
257  entity.nodeFinalStance = ‪Blackboard::GetBlackBoardAttribute( entity, ‪DESIRED_STANCE );
259 
260  if ( !IsDefined( entity.nodeFinalStance ) )
261  {
262  entity.nodeFinalStance = ‪AiUtility::getHighestNodeStance( entity.adjustNode );
263  }
264 
265  // [0, 360) relative to the node.
266  angleDifference = Floor( AbsAngleClamp360( entity.angles[1] - entity.node.angles[1] ) );
267 
268  entity.mocompAngleStartTime = ‪_GetAdjustToCoverRotation( entity.archetype, coverType, entity.nodeFinalStance, angleDifference );
269  }
270 }
271 
272 function private ‪mocompAdjustToCoverUpdate( entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration )
273 {
274  if( !IsDefined( entity.adjustNode ) )
275  {
276  return;
277  }
278 
279  moveVector = entity.nodeOffsetOrigin - entity.origin;
280 
281  if ( LengthSquared( moveVector ) > ( ‪MAX_MOVE_DISTANCE * ‪MAX_MOVE_DISTANCE ) )
282  {
283  // Scale the moveVector by the max move distance.
284  moveVector = VectorNormalize( moveVector ) * ‪MAX_MOVE_DISTANCE;
285  }
286 
287  entity ForceTeleport( entity.origin + moveVector, entity.angles, false );
288 
289  normalizedTime = ( ( entity GetAnimTime( mocompAnim ) * GetAnimLength( mocompAnim ) ) + mocompAnimBlendOutTime ) / mocompDuration;
290 
291  if ( normalizedTime > entity.mocompAngleStartTime )
292  {
293  entity OrientMode( "face angle", entity.nodeOffsetAngles );
294  entity AnimMode( ‪AI_ANIM_MOVE_CODE, false );
295  }
296 
297  /#
298  if ( GetDvarInt( "ai_debugAdjustMocomp" ) )
299  {
300  record3DText( entity.mocompAngleStartTime, entity.origin + (0, 0, 5), ‪GREEN, "Animscript" );
301 
302  hipTagOrigin = entity GetTagOrigin( "j_mainroot" );
303 
304  recordLine( entity.nodeOffsetOrigin, entity.nodeOffsetOrigin + entity.nodeOffsetForward * 30, ‪ORANGE, "Animscript", entity );
305  recordLine( entity.adjustNode.origin, entity.adjustNode.origin + entity.nodeForward * 20, ‪GREEN, "Animscript", entity );
306  recordLine( entity.origin, entity.origin + AnglesToForward( entity.angles ) * 10, ‪RED, "Animscript", entity );
307 
308  recordLine( hipTagOrigin, ( hipTagOrigin[0], hipTagOrigin[1], entity.origin[2] ), ‪BLUE, "Animscript", entity );
309  }
310  #/
311 }
312 
313 function private ‪mocompAdjustToCoverTerminate( entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration )
314 {
315  entity.blockingPain = false;
316  entity.mocompAngleStartTime = undefined;
317  entity.nodeOffsetAngle = undefined;
318  entity.nodeOffsetForward = undefined;
319  entity.nodeForward = undefined;
320  entity.nodeFinalStance = undefined;
321 
322  if( entity.adjustNode !== entity.node )
323  {
324  entity.nodeOffsetOrigin = undefined;
325  entity.nodeOffsetAngles = undefined;
326  entity.adjustNode = undefined;
327  return;
328  }
329 
330  entity ForceTeleport( entity.nodeOffsetOrigin, entity.nodeOffsetAngles, false );
331  entity.nodeOffsetOrigin = undefined;
332  entity.nodeOffsetAngles = undefined;
333  entity.adjustNode = undefined;
334 }
‪startTime
‪class AnimationAdjustmentInfoZ startTime
‪mocompLocoExplosionInit
‪function private mocompLocoExplosionInit(entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration)
Definition: archetype_mocomps_utility.gsc:229
‪mocompAdjustToCoverTerminate
‪function private mocompAdjustToCoverTerminate(entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration)
Definition: archetype_mocomps_utility.gsc:313
‪STANCE_ANY
‪#define STANCE_ANY
Definition: archetype_mocomps_utility.gsc:38
‪GetBlackBoardAttribute
‪function GetBlackBoardAttribute(entity, attributeName)
Definition: blackboard.gsc:32
‪AI_ANIM_USE_BOTH_DELTAS_NOGRAVITY
‪#define AI_ANIM_USE_BOTH_DELTAS_NOGRAVITY
Definition: animation_state_machine.gsh:84
‪GREEN
‪#define GREEN
Definition: shared.gsh:176
‪RED
‪#define RED
Definition: shared.gsh:175
‪COVER_RIGHT
‪#define COVER_RIGHT
Definition: blackboard.gsh:93
‪STANCE_STAND
‪#define STANCE_STAND
Definition: blackboard.gsh:273
‪DESIRED_STANCE
‪#define DESIRED_STANCE
Definition: blackboard.gsh:18
‪AI_ANIM_MOVE_CODE
‪#define AI_ANIM_MOVE_CODE
Definition: animation_state_machine.gsh:77
‪COVER_TYPE
‪#define COVER_TYPE
Definition: blackboard.gsh:54
‪ASM_REGISTER_MOCOMP
‪#define ASM_REGISTER_MOCOMP(name, initFunction, updateFunction, terminateFunction)
Definition: animation_state_machine.gsh:1
‪_GetAdjustToCoverRotation
‪function private _GetAdjustToCoverRotation(archetype, node, stance, angleToNode)
Definition: archetype_mocomps_utility.gsc:114
‪debugLocoExplosion
‪function private debugLocoExplosion(entity)
Definition: archetype_mocomps_utility.gsc:193
‪InitAdjustToCoverParams
‪function autoexec InitAdjustToCoverParams()
Definition: archetype_mocomps_utility.gsc:40
‪COVER_ANY
‪#define COVER_ANY
Definition: archetype_mocomps_utility.gsc:37
‪COVER_CROUCH
‪#define COVER_CROUCH
Definition: blackboard.gsh:92
‪BLUE
‪#define BLUE
Definition: shared.gsh:177
‪COVER_EXPOSED
‪#define COVER_EXPOSED
Definition: blackboard.gsh:96
‪COVER_PILLAR
‪#define COVER_PILLAR
Definition: blackboard.gsh:97
‪mocompAdjustToCoverUpdate
‪function private mocompAdjustToCoverUpdate(entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration)
Definition: archetype_mocomps_utility.gsc:272
‪mocompFlankStandInit
‪function private mocompFlankStandInit(entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration)
Definition: archetype_mocomps_utility.gsc:215
‪AI_ANIM_USE_ANGLE_DELTAS
‪#define AI_ANIM_USE_ANGLE_DELTAS
Definition: animation_state_machine.gsh:80
‪_AddAdjustToCover
‪function private _AddAdjustToCover(archetype, node, stance, rot2, rot32, rot3, rot36, rot6, rot69, rot9, rot98, rot8, rot87, rot7, rot47, rot4, rot14, rot1, rot21)
Definition: archetype_mocomps_utility.gsc:74
‪mocompAdjustToCoverInit
‪function private mocompAdjustToCoverInit(entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration)
Definition: archetype_mocomps_utility.gsc:244
‪STANCE_CROUCH
‪#define STANCE_CROUCH
Definition: blackboard.gsh:274
‪ORANGE
‪#define ORANGE
Definition: shared.gsh:179
‪RegisterDefaultAnimationMocomps
‪function autoexec RegisterDefaultAnimationMocomps()
Definition: archetype_mocomps_utility.gsc:28
‪COVER_STAND
‪#define COVER_STAND
Definition: blackboard.gsh:95
‪getHighestNodeStance
‪function getHighestNodeStance(node)
Definition: archetype_utility.gsc:2059
‪COVER_LEFT
‪#define COVER_LEFT
Definition: blackboard.gsh:94
‪MAX_MOVE_DISTANCE
‪#define MAX_MOVE_DISTANCE
Definition: archetype_mocomps_utility.gsc:242
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265