‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
bot_traversals.gsc
Go to the documentation of this file.
1 #using scripts\shared\array_shared;
2 #using scripts\shared\callbacks_shared;
3 #using scripts\shared\math_shared;
4 #using scripts\shared\system_shared;
5 #using scripts\shared\util_shared;
6 #using scripts\shared\weapons_shared;
7 #using scripts\shared\weapons\_weapons;
8 
9 #using scripts\shared\bots\_bot;
10 #using scripts\shared\bots\bot_buttons;
11 
12 #insert scripts\shared\shared.gsh;
13 
14 #define TRACE_DISTANCE 128
15 
16 #define TRAVERSAL_TIMEOUT 8
17 
18 // Dconst wallrun_jumpheight
19 #define WALLRUN_JUMP_HEIGHT 40
20 // Dconst wallrun_jumpvelocity
21 #define WALLRUN_JUMP_VELOCITY 200
22 
23 #define MANTLE_CHECK_HEIGHT 16
24 
25 // AIPHYS_DEFAULT_HEIGHT
26 #define BOT_HEIGHT 72
27 #define BOT_RADIUS 15
28 
29 // doubleJump_maxUpwardsVelocity = 225
30 #define DOUBLEJUMP_V_UP 80
31 #define BOT_MIN_JUMP_JET 0.7
32 
33 #define BOT_JUMP_ALIGN_DOT 0.94
34 
35 #namespace bot;
36 
37 function ‪Callback_BotEnteredUserEdge( startNode, endNode )
38 {
39  zDelta = endNode.origin[2] - startNode.origin[2];
40  xyDist = Distance2D( startNode.origin, endNode.origin );
41 
42 /* No ladders in BO 3
43  result = BulletTrace( start, start + ( startDir * TRACE_DISTANCE ), false, self );
44 
45  if ( result["surfacetype"] == "ladder" )
46  {
47  self thread climb_traversal();
48  return;
49  }
50  */
51 
52  standingViewHeight = GetDvarFloat( "player_standingViewHeight", 0 );
53  swimWaterHeight = standingViewHeight * GetDvarFloat( "player_swimHeightRatio", 0 );
54 
55  startWaterHeight = GetWaterHeight( startNode.origin );
56  startInWater = startWaterHeight != 0 && startWaterHeight > ( startNode.origin[2] + swimWaterHeight );
57 
58  endWaterHeight = GetWaterHeight( endNode.origin );
59  endInWater = endWaterHeight != 0 && endWaterHEight > ( endNode.origin[2] + swimWaterHeight );
60 
61  if ( IsWallrunNode( endNode ) )
62  {
63  self thread ‪wallrun_traversal( startNode, endNode );
64  }
65  else if ( startInWater && !endInWater )
66  {
67  self thread ‪leave_water_traversal( startNode, endNode );
68  }
69  else if ( startInWater && endInWater )
70  {
71  self thread ‪swim_traversal( startNode, endNode );
72  }
73  else if ( zDelta >= 0 )
74  {
75  self thread ‪jump_up_traversal( startNode, endNode );
76  }
77  else if ( zDelta < 0 )
78  {
79  self thread ‪jump_down_traversal( startNode, endNode );
80  }
81  else
82  {
83  //Can't figure out how to handle traversal
84  self BotReleaseManualControl();
85 /#
86  PrintLn( "Bot ", self.‪name, " can't handle traversal!" );
87 #/
88  }
89 }
90 
91 /* No ladders in BO3
92 function climb_traversal( start, end, startDir, endDir )
93 {
94  self BotSetMoveAngleFromPoint( end );
95  self thread wait_acrobatics_end();
96 }
97 */
98 
99 function ‪traversing()
100 {
101  // IsMantling also checks TRM
102  return !self IsOnGround() || self IsWallRunning() || self IsDoubleJumping() || self IsMantling() || self IsSliding();
103 }
104 
105 
106 // Water traversals
107 //========================================
108 
109 function ‪leave_water_traversal( startNode, endNode )
110 {
111  self endon( "death" );
112  self endon( "traversal_end" );
113  level endon( "game_ended" );
114 
115  self thread ‪watch_traversal_end(); // Start the timeout thread
116 
117  self BotSetMoveAngleFromPoint( endNode.origin );
118 
119  while ( self IsPlayerUnderWater() )
120  {
121  self ‪bot::press_swim_up();
122 
124  }
125 
126  while( 1 )
127  {
129 
131  }
132 }
133 
134 function ‪swim_traversal( startNode, endNode )
135 {
136  self endon( "death" );
137  level endon( "game_ended" );
138  self endon( "traversal_end" );
139 
140  self BotSetMoveAngleFromPoint( endNode.origin );
141 
142  wait 0.5;
143 
144  self ‪traversal_end();
145 }
146 
147 // Jump traversals
148 //========================================
149 
150 function ‪jump_up_traversal( startNode, endNode )
151 {
152  self endon( "death" );
153  level endon( "game_ended" );
154  self endon( "traversal_end" );
155 
156  self thread ‪watch_traversal_end();
157 
158  ledgeTop = CheckNavMeshDirection( endNode.origin, self.origin - endNode.origin, 128, 1 );
159 
160  height = ledgeTop[2] - self.origin[2];
161 
162  // Do we need to check for an overhang?
163  if ( height <= ‪BOT_HEIGHT )
164  {
165  self thread ‪jump_to( ledgeTop );
166  return;
167  }
168  dist = Distance2D( self.origin, ledgeTop );
169  ledgeBottom = CheckNavMeshDirection( self.origin, ledgeTop - self.origin, dist + ‪BOT_RADIUS, 1 );
170  bottomDist = Distance2D( self.origin, ledgeBottom );
171 
172  // No overhang since the navmesh on the bottom doesn't run under the top
173  if ( bottomDist <= dist )
174  {
175  self thread ‪jump_to( ledgeTop );
176  return;
177  }
178 
179  // Use the distance between the ledge and leading edge of the bot
180  dist = dist - ‪BOT_RADIUS;
181  height = height - ‪BOT_HEIGHT;
182 
183  t = height / ‪DOUBLEJUMP_V_UP;
184  speed2D = self ‪bot_speed2D();
185  speed = self GetPlayerSpeed();
186  moveDist = t * speed2D;
187 
188  if ( !moveDist || dist > moveDist )
189  {
190  self thread ‪jump_to( ledgeTop );
191  return;
192  }
193 
194  self BotSetMoveMagnitude( dist / moveDist );
195 
197 
198  self thread ‪jump_to( ledgeTop );
199 
201 
202  while( ( self.origin[2] + ‪BOT_HEIGHT ) < ledgeTop[2] )
203  {
205  }
206 
207  self BotSetMoveMagnitude( 1 );
208 }
209 
210 function ‪jump_down_traversal( startNode, endNode )
211 {
212  self endon( "death" );
213  self endon( "traversal_end" );
214  level endon( "game_ended" );
215 
216  self thread ‪watch_traversal_end();
217 
218  // Check for a barrier at the beginning
219  fwd = ( endNode.origin[0] - startNode.origin[0], endNode.origin[1] - startNode.origin[1], 0 );
220  fwd = VectorNormalize( fwd ) * ‪TRACE_DISTANCE;
221 
222  // Don't scrape the trace along the ground
223  start = startNode.origin + ( 0, 0, ‪MANTLE_CHECK_HEIGHT );
224  ‪end = startNode.origin + fwd + ( 0, 0, ‪MANTLE_CHECK_HEIGHT );
225 
226  ‪result = BulletTrace( start, ‪end, false, self );
227 
228  if ( ‪result["surfacetype"] != "none" )
229  {
230  self BotSetMoveAngleFromPoint( endNode.origin );
231 
233 
235 
236  return;
237  }
238 
239  // Check if we need to jump to get the distance we need
240  dist = Distance2D( startNode.origin, endNode.origin );
241  height = startNode.origin[2] - endNode.origin[2];
242 
243  gravity = self GetPlayerGravity();
244 
245  t = Sqrt( ( 2 * height ) / gravity );
246 
247  speed2D = self ‪bot_speed2D();
248 
249  if ( t * speed2D < dist )
250  {
251  // We may be able to just fall
252  ledgeTop = CheckNavMeshDirection( startNode.origin, endNode.origin - startNode.origin, ‪TRACE_DISTANCE, 1 );
253 
254  bottomDist = dist - Distance2D( startNode.origin, ledgeTop );
255  ledgeBottom = CheckNavMeshDirection( endNode.origin, startNode.origin - endNode.origin, bottomDist, 1 );
256 
257  meshDist = Distance2D( ledgeTop, ledgeBottom );
258 
259  if ( meshDist > ( 2 * ‪BOT_RADIUS ) )
260  {
261  self thread ‪jump_to( endNode.origin );
262  return;
263  }
264  }
265 
266  self BotSetMoveAngleFromPoint( endNode.origin );
267 }
268 
269 // Wallrun
270 //========================================
271 
272 function ‪wallrun_traversal( startNode, endNode, vector )
273 {
274  self endon( "death" );
275  self endon( "traversal_end" );
276  level endon( "game_ended" );
277 
278  self thread ‪watch_traversal_end();
279 
280  // Navmesh wall normals get tilted
281  wallNormal = GetNavMeshFaceNormal( endNode.origin, 30 );
282  wallNormal = VectorNormalize( ( wallNormal[0], wallNormal[1], 0 ) );
283 
284  traversalDir = ( startNode.origin[0] - endNode.origin[0], startNode.origin[1] - endNode.origin[1], 0 );
285 
286  cross = VectorCross( wallNormal, traversalDir );
287 
288  runDir = VectorCross( wallNormal, cross );
289 
290  self BotSetLookAngles( runDir );
291 
292  self thread ‪jump_to( endNode.origin, vector );
293 
294  self thread ‪wait_wallrun_begin( startNode, endNode, wallNormal, runDir );
295 }
296 
297 function ‪wait_wallrun_begin( startNode, endNode, wallNormal, runDir )
298 {
299  self endon( "death" );
300  self endon( "traversal_end" );
301  level endon( "game_ended" );
302 
303  self waittill( "wallrun_begin" );
304 
305  self thread ‪watch_traversal_end(); // Reset the timeout
306 
307  self BotLookNone();
308  self BotSetMoveAngle( runDir );
309 
311 
312  index = self GetNodeIndexOnPath( startNode );
313  index++;
314 
315  exitStartNode = self GetNextTraversalNodeOnPath( index );
316  if ( isdefined( exitStartNode ) )
317  {
318  exitEndNode = GetOtherNodeInNegotiationPair( exitStartNode );
319 
320  if ( isdefined( exitEndNode ) )
321  {
322  self thread ‪exit_wallrun( exitStartNode, exitEndNode, wallNormal, VectorNormalize( runDir ) );
323  }
324  }
325 }
326 
327 function ‪exit_wallrun( startNode, endNode, wallNormal, runNormal )
328 {
329  self endon( "death" );
330  self endon( "traversal_end" );
331  level endon( "game_ended" );
332 
333  self thread ‪watch_traversal_end(); // Reset the timeout
334 
335  gravity = self GetPlayerGravity();
336  // TODO: gadget_speedBurstWallRunJumpVelocity
337 
338  vUp = Sqrt( ‪WALLRUN_JUMP_HEIGHT * 2 * gravity );
339  tPeak = vUp / gravity;
340 
341  hPeak = self.origin[2] + ‪WALLRUN_JUMP_HEIGHT;
342 
343  fallDist = hPeak - endNode.origin[2];
344 
345  if ( fallDist > 0 )
346  {
347  tFall = Sqrt( fallDist / ( 0.5 * gravity ) );
348  }
349  else
350  {
351  // Probably need to do something else here
352  tFall = 0;
353  }
354 
355  t = tPeak + tFall;
356 
357  exitDir = endNode.origin - startNode.origin;
358  dNormal = VectorDot( exitDir, wallNormal );
359 
360  vNormal = dNormal / t;
361 
362  if ( vNormal <= ‪WALLRUN_JUMP_VELOCITY )
363  {
364  dot = Sqrt( vNormal / ‪WALLRUN_JUMP_VELOCITY );
365  vForward = Sqrt( ( ‪WALLRUN_JUMP_VELOCITY * ‪WALLRUN_JUMP_VELOCITY * dot * dot ) - ( vNormal * vNormal ) );
366  }
367  else
368  {
369  vForward = 0;
370  }
371 
372  // TODO: Handle the case where the solution fails
373  while(1)
374  {
376 
377  endDir = endNode.origin - self.origin;
378  endDist = VectorDot( endDir, runNormal );
379 
380  vRun = self ‪bot_speed2D();
381 
382  dForward = ( vRun + vForward ) * t;
383 
384 /*#
385  dorigin = (self.origin[0], self.origin[1], endNode.origin[2] );
386 
387  Line( dorigin, dorigin + ( wallNormal * dNormal ) );
388  Line( dorigin, dorigin + ( runNormal * dForward ) );
389  Line( dorigin, dorigin + ( wallNormal * dNormal ) + ( runNormal * dForward ) );
390  line( dorigin, endNode.origin );
391 
392 #*/
393  if ( endDist <= dForward )
394  {
395  jumpAngle = ( wallNormal * vNormal ) + ( runNormal * vForward );
396 
397  if ( IsWallrunNode( endNode ) )
398  {
399  self thread ‪wallrun_traversal( startNode, endNode, jumpAngle );
400  }
401  else
402  {
403  self BotSetLookAnglesFromPoint( endNode.origin );
404  self thread ‪jump_to( endNode.origin, jumpAngle );
405  }
406  return;
407  }
408  }
409 }
410 
411 function ‪jump_to( target, vector )
412 {
413  self endon( "death" );
414  self endon( "traversal_end" );
415  level endon( "game_ended" );
416 
417  if ( isdefined( vector ) )
418  {
419  self BotSetMoveAngle( vector );
420  moveDir = VectorNormalize( ( vector[0], vector[1], 0 ) );
421  }
422  else
423  {
424  self BotSetMoveAngleFromPoint( target );
425  targetDelta = target - self.origin;
426  moveDir = VectorNormalize( ( targetDelta[0], targetDelta[1], 0 ) );
427  }
428 
429  velocity = self GetVelocity( );
430  velocityDir = VectorNormalize( ( velocity[0], velocity[1], 0 ) );
431 
432  if ( VectorDot( moveDir, velocityDir ) < ‪BOT_JUMP_ALIGN_DOT )
433  {
435  }
436 
438 
440 
441  while ( !self IsOnGround() &&
442  !self IsMantling() &&
443  !self IsWallRunning() &&
444  !self ‪bot_hit_target( target ) )
445  {
447 
448  if ( !isdefined( vector ) )
449  {
450  self BotSetMoveAngleFromPoint( target );
451  }
452 
454  }
455 
457 }
458 
459 function ‪bot_update_move_angle( target )
460 {
461  self endon( "death" );
462  self endon( "traversal_end" );
463  level endon( "game_ended" );
464 
465  while ( !self IsMantling() )
466  {
467  self BotSetMoveAngleFromPoint( target );
468 
470  }
471 }
472 
473 function ‪bot_hit_target( target )
474 {
475  velocity = self GetVelocity();
476 
477  targetDir = target - self.origin;
478  targetDir = ( targetDir[0], targetDir[1], 0 );
479 
480  // Check for 'overshoot' when going down
481  if ( self.origin[2] > target[2] && VectorDot( velocity, targetDir ) <= 0 )
482  {
483  return true;
484  }
485 
486  targetDist = Length( targetDir );
487 
488  targetSpeed = Length( velocity );
489 
490  if ( targetSpeed == 0 )
491  {
492  return false;
493  }
494 
495  t = targetDist / targetSpeed;
496 
497  gravity = self GetPlayerGravity();
498 
499  height = self.origin[2] + velocity[2] * t - ( gravity * t * t * .5 );
500 
501  return height >= ( target[2] + 32 );
502 }
503 
504 function ‪bot_speed2D()
505 {
506  velocity = self GetVelocity();
507 
508  speed2D = Distance2D( velocity, ( 0, 0, 0 ) );
509 
510  return speed2D;
511 }
512 
513 // Traversal End
514 //========================================
515 
517 {
518  self notify( "watch_travesal_end" );
519 
520  self endon( "death" );
521  self endon( "traversal_end" );
522  self endon( "watch_travesal_end" );
523  level endon( "game_ended" );
524 
525  self thread ‪wait_traversal_timeout();
526  self thread ‪watch_start_swimming();
527 
528  self waittill( "acrobatics_end" );
529 
530  self thread ‪traversal_end();
531 }
532 
534 {
535  self endon( "death" );
536  self endon( "traversal_end" );
537  self endon( "watch_travesal_end" );
538  level endon( "game_ended" );
539 
540  while( self IsPlayerSwimming() )
541  {
543  }
544 
546 
547  while( !self IsPlayerSwimming() )
548  {
550  }
551 
552  self thread ‪traversal_end();
553 }
554 
556 {
557  self endon( "death" );
558  self endon( "traversal_end" );
559  self endon( "watch_travesal_end" );
560  level endon( "game_ended" );
561 
562  wait( ‪TRAVERSAL_TIMEOUT );
563 
564  self thread ‪traversal_end();
565 
566  self BotRequestPath();
567 }
568 
570 {
571  self notify( "traversal_end" );
572 
574 
575  self BotLookForward();
576  self BotSetMoveMagnitude( 1 );
577  self BotReleaseManualControl();
578 }
‪bot_hit_target
‪function bot_hit_target(target)
Definition: bot_traversals.gsc:473
‪bot_update_move_angle
‪function bot_update_move_angle(target)
Definition: bot_traversals.gsc:459
‪BOT_JUMP_ALIGN_DOT
‪#define BOT_JUMP_ALIGN_DOT
Definition: bot_traversals.gsc:33
‪wallrun_traversal
‪function wallrun_traversal(startNode, endNode, vector)
Definition: bot_traversals.gsc:272
‪TRACE_DISTANCE
‪#define TRACE_DISTANCE
Definition: bot_traversals.gsc:14
‪bot_speed2D
‪function bot_speed2D()
Definition: bot_traversals.gsc:504
‪tap_jump_button
‪function tap_jump_button()
Definition: bot_buttons.gsc:128
‪BOT_HEIGHT
‪#define BOT_HEIGHT
Definition: bot_traversals.gsc:26
‪swim_traversal
‪function swim_traversal(startNode, endNode)
Definition: bot_traversals.gsc:134
‪BOT_RADIUS
‪#define BOT_RADIUS
Definition: bot_traversals.gsc:27
‪jump_down_traversal
‪function jump_down_traversal(startNode, endNode)
Definition: bot_traversals.gsc:210
‪release_doublejump_button
‪function release_doublejump_button()
Definition: bot_buttons.gsc:168
‪WALLRUN_JUMP_HEIGHT
‪#define WALLRUN_JUMP_HEIGHT
Definition: bot_traversals.gsc:19
‪TRAVERSAL_TIMEOUT
‪#define TRAVERSAL_TIMEOUT
Definition: bot_traversals.gsc:16
‪end
‪function end(final)
Definition: _killcam.gsc:511
‪traversal_end
‪function traversal_end()
Definition: bot_traversals.gsc:569
‪wait_wallrun_begin
‪function wait_wallrun_begin(startNode, endNode, wallNormal, runDir)
Definition: bot_traversals.gsc:297
‪wait_traversal_timeout
‪function wait_traversal_timeout()
Definition: bot_traversals.gsc:555
‪WALLRUN_JUMP_VELOCITY
‪#define WALLRUN_JUMP_VELOCITY
Definition: bot_traversals.gsc:21
‪jump_to
‪function jump_to(target, vector)
Definition: bot_traversals.gsc:411
‪jump_up_traversal
‪function jump_up_traversal(startNode, endNode)
Definition: bot_traversals.gsc:150
‪DOUBLEJUMP_V_UP
‪#define DOUBLEJUMP_V_UP
Definition: bot_traversals.gsc:30
‪MANTLE_CHECK_HEIGHT
‪#define MANTLE_CHECK_HEIGHT
Definition: bot_traversals.gsc:23
‪press_doublejump_button
‪function press_doublejump_button()
Definition: bot_buttons.gsc:163
‪watch_start_swimming
‪function watch_start_swimming()
Definition: bot_traversals.gsc:533
‪exit_wallrun
‪function exit_wallrun(startNode, endNode, wallNormal, runNormal)
Definition: bot_traversals.gsc:327
‪leave_water_traversal
‪function leave_water_traversal(startNode, endNode)
Definition: bot_traversals.gsc:109
‪result
‪function result(death, attacker, mod, weapon)
Definition: _zm_aat_blast_furnace.gsc:46
‪name
‪class GroundFx name
‪press_swim_up
‪function press_swim_up()
Definition: bot_buttons.gsc:178
‪traversing
‪function traversing()
Definition: bot_traversals.gsc:99
‪Callback_BotEnteredUserEdge
‪function Callback_BotEnteredUserEdge(startNode, endNode)
Definition: bot_traversals.gsc:37
‪watch_traversal_end
‪function watch_traversal_end()
Definition: bot_traversals.gsc:516
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265