‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
grapple.gsc
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\clientfield_shared;
5 #using scripts\shared\flagsys_shared;
6 #using scripts\shared\hud_util_shared;
7 #using scripts\shared\system_shared;
8 #using scripts\shared\util_shared;
9 #using scripts\shared\abilities\_ability_util;
10 
11 #insert scripts\shared\weapons\grapple.gsh;
12 #insert scripts\shared\shared.gsh;
13 #insert scripts\shared\version.gsh;
14 
15 #namespace grapple;
16 
17 ‪REGISTER_SYSTEM_EX( "grapple", &‪__init__, &‪__main__, undefined )
18 
19 #define GRAPPLE_TARGET "grapple_target"
20 #define GRAPPLE_RETARGET_DELAY 0.1
21 
22 #define WEAPON_CHANGE_NOTIFY "grapple_weapon_change"
23 
24 
25 function ‪__init__()
26 {
28 }
29 
30 function ‪__main__()
31 {
32  grapple_targets = GetEntArray( ‪GRAPPLE_TARGET, "targetname" );
33  foreach( target in grapple_targets )
34  {
35  target.grapple_type = ‪GRAPPLE_TYPE_REELPLAYER;
36  target SetGrapplableType( target.grapple_type );
37  }
38 }
39 
40 function ‪translate_notify_1( from_notify, to_notify )
41 {
42  self endon( "disconnect" );
43  self endon( "death" );
44  self endon( "spawned_player" );
45 
46  while (IsDefined(self))
47  {
48  self waittill( from_notify, param1, param2, param3 );
49  self notify( to_notify, from_notify, param1, param2, param3 );
50  }
51 }
52 
53 
55 {
56  self endon( "disconnect" );
57  self endon( "death" );
58  self endon( "spawned_player" );
59  self endon("killReplayGunMonitor");
60 
61  self thread ‪translate_notify_1( "weapon_switch_started", ‪WEAPON_CHANGE_NOTIFY );
62  self thread ‪translate_notify_1( "weapon_change_complete", ‪WEAPON_CHANGE_NOTIFY );
63 
64  while( 1 )
65  {
66  self waittill( ‪WEAPON_CHANGE_NOTIFY, event, weapon );
67 
68  if ( ‪IS_TRUE(weapon.grappleWeapon) )
69  {
70  self thread ‪watch_lockon(weapon);
71  }
72  else
73  {
74  self notify( "grapple_unwield" );
75  }
76  }
77 }
78 
79 function ‪watch_lockon(weapon)
80 {
81  self endon( "disconnect" );
82  self endon( "death" );
83  self endon( "spawned_player" );
84  self endon( "grapple_unwield" );
85  self notify( "watch_lockon" );
86  self endon( "watch_lockon" );
87 
88  self thread ‪watch_lockon_angles(weapon);
89  self thread ‪clear_lockon_after_grapple(weapon);
90 
91  // find an initial target quickly
92  self.use_expensive_targeting = true;
93 
94  while(1)
95  {
97  if ( !(self IsGrappling()) )
98  {
99  target = self ‪get_a_target(weapon);
100  if ( !(self IsGrappling()) && !‪IS_EQUAL(target,self.lockonentity) )
101  {
102  self WeaponLockNoClearance( !‪IS_EQUAL( target, self.dummy_target ) );
103  self.lockonentity = target;
105  }
106  }
107  }
108 }
109 
111 {
112  self endon( "disconnect" );
113  self endon( "death" );
114  self endon( "spawned_player" );
115  self endon( "grapple_unwield" );
116  self notify( "clear_lockon_after_grapple" );
117  self endon( "clear_lockon_after_grapple" );
118 
119  while(1)
120  {
121  self ‪util::waittill_any( "grapple_pulled", "grapple_landed" );
122  if ( IsDefined( self.lockonentity ) )
123  {
124  self.lockonentity = undefined;
125  self.use_expensive_targeting = true;
126  }
127  }
128 }
129 
130 function ‪watch_lockon_angles(weapon)
131 {
132  self endon( "disconnect" );
133  self endon( "death" );
134  self endon( "spawned_player" );
135  self endon( "grapple_unwield" );
136  self notify( "watch_lockon_angles" );
137  self endon( "watch_lockon_angles" );
138 
139  while(1)
140  {
142  if ( !(self IsGrappling()) )
143  {
144  if ( IsDefined( self.lockonentity ) )
145  {
146  if ( ‪IS_EQUAL( self.lockonentity, self.dummy_target ) )
147  {
148  self weaponlocktargettooclose( false );
149  }
150  else
151  {
152  testOrigin = ‪get_target_lock_on_origin( self.lockonentity );
153  if ( !self ‪inside_screen_angles( testOrigin, weapon, false ) )
154  {
155  self weaponlocktargettooclose( true );
156  }
157  else
158  {
159  self weaponlocktargettooclose( false );
160  }
161  }
162  }
163 
164  }
165  }
166 }
167 
168 function ‪place_dummy_target( origin, forward, weapon )
169 {
170  if ( !IsDefined(self.dummy_target) )
171  {
172  self.dummy_target = ‪Spawn( "script_origin", origin );
173  }
174  self.dummy_target SetGrapplableType( ‪GRAPPLE_TYPE_TARGETONLY );
175 
176  start = origin;
177 
178  distance = weapon.lockOnMaxRange * 0.9;
179  if ( IsDefined( level.grapple_notarget_distance ) )
180  distance = level.grapple_notarget_distance;
181 
182  ‪end = origin + forward * distance;
183 
184  if ( !(self IsGrappling()) )
185  {
186  self.dummy_target.origin = self ‪trace( start, ‪end, self.dummy_target );
187  }
188 
189  minrange_sq = weapon.lockOnMinRange * weapon.lockOnMinRange;
190  if ( DistanceSquared( self.dummy_target.origin, origin ) < minrange_sq )
191  return undefined;
192 
193  return self.dummy_target;
194 }
195 
196 function ‪get_a_target(weapon)
197 {
198  origin = self geteye();
199  forward = self GetWeaponForwardDir();
200 
201  targets = GetGrappleTargetArray();
202 
203  if ( !IsDefined( targets ) )
204  return undefined;
205 
206  if ( !IsDefined(weapon.lockOnScreenRadius) || weapon.lockOnScreenRadius< 1 )
207  return undefined;
208 
209  validTargets = [];
210  should_wait = 0;
211  should_wait_limit = 2;
212 
213  if ( ‪IS_TRUE( self.use_expensive_targeting ) )
214  {
215  should_wait_limit = 4;
216  self.use_expensive_targeting = false;
217  }
218 
219  for ( i = 0; i < targets.size; i++ )
220  {
221  if ( should_wait >= should_wait_limit )
222  {
224  origin = self GetWeaponMuzzlePoint();
225  forward = self GetWeaponForwardDir();
226  should_wait = 0;
227  }
228 
229  testTarget = targets[i];
230 
231  if ( !‪is_valid_target( testTarget ) )
232  {
233  continue;
234  }
235 
236  testOrigin = ‪get_target_lock_on_origin( testTarget );
237  //test_range_squared = DistanceSquared( origin, testOrigin );
238  test_range = Distance( origin, testOrigin );
239  //gun_range = self get_grapple_range(weapon);
240 
241  if ( test_range > weapon.lockOnMaxRange ||
242  test_range < weapon.lockOnMinRange )
243  {
244  continue;
245  }
246 
247  normal = VectorNormalize( testOrigin - origin );
248  dot = VectorDot( forward, normal );
249 
250  if ( 0 > dot )
251  {
252  // guy's behind us
253  continue;
254  }
255 
256  if ( !self ‪inside_screen_angles( testOrigin, weapon, !‪IS_EQUAL(testTarget,self.lockonentity) ) )
257  {
258  continue;
259  }
260 
261  canSee = self ‪can_see( testTarget, testOrigin, origin, forward, 30 );
262  should_wait++; // ^^ that's expensive
263 
264  if ( canSee )
265  {
266  validTargets[ validTargets.size ] = testTarget;
267  }
268  }
269 
270  best = ‪pick_a_target_from( validTargets, origin, forward, weapon.lockOnMinRange, weapon.lockOnMaxRange );
271 
272  if ( ‪IS_TRUE( level.grapple_notarget_enabled ) )
273  {
274  if (!IsDefined(best) || ‪IS_EQUAL(best,self.dummy_target) )
275  {
276  best = ‪place_dummy_target( origin, forward, weapon );
277  }
278  }
279 
280  return best;
281 }
282 
283 function ‪get_target_type_score( target )
284 {
285  if ( !IsDefined( target ) )
286  return 0;
287 
288  if ( ‪IS_EQUAL(target,self.dummy_target) )
289  return 0;
290 
291  if ( ‪IS_EQUAL(target.grapple_type,‪GRAPPLE_TYPE_REELPLAYER) )
292  return 1;
293 
294  if ( ‪IS_EQUAL(target.grapple_type,‪GRAPPLE_TYPE_PULLENTIN) )
295  return 0.985;
296 
297  if ( !IsDefined(target.grapple_type) )
298  return 0.90;
299 
300  if ( ‪IS_EQUAL(target.grapple_type,‪GRAPPLE_TYPE_TARGETONLY) )
301  return 0.75;
302 
303  return 0;
304 }
305 
306 // target selection tuning
307 // 0 = only consider distance
308 // 1 = only consider dot product
309 // anything in the middle is some mixture of the two
310 #define GRAPPLE_TARGET_WEIGHT_DOT_OVER_DIST 0.85
311 
312 function ‪get_target_score( target, origin, forward, min_range, max_range )
313 {
314  if ( !IsDefined( target ) )
315  return -1;
316 
317  if ( ‪IS_EQUAL(target,self.dummy_target) )
318  return 0;
319 
320  if ( ‪is_valid_target( target ) )
321  {
322  testOrigin = ‪get_target_lock_on_origin( target );
323  normal = VectorNormalize( testOrigin - origin );
324  dot = VectorDot( forward, normal );
325  targetDistance = Distance( self.origin, testOrigin );
326  distance_score = 1-((targetDistance - min_range) / (max_range - min_range));
327 
328  type_score = ‪get_target_type_score( target );
329 
331  }
332 
333  return -1;
334 }
335 
336 
337 
338 function ‪pick_a_target_from( targets, origin, forward, min_range, max_range )
339 {
340  if ( !IsDefined( targets ) )
341  return undefined;
342 
343  bestTarget = undefined;
344  bestScore = undefined;
345 
346  for ( i = 0; i < targets.size; i++ )
347  {
348  target = targets[i];
349 
350  if ( ‪is_valid_target( target ) )
351  {
352  score = ‪get_target_score( target, origin, forward, min_range, max_range );
353 
354  if ( !IsDefined( bestTarget ) || !IsDefined( bestScore ) )
355  {
356  bestTarget = target;
357  bestScore = score;
358  }
359  else if ( score > bestScore )
360  {
361  bestTarget = target;
362  bestScore = score;
363  }
364  }
365  }
366  return bestTarget;
367 }
368 
369 function ‪trace( from, to, target )
370 {
371  ‪trace = bullettrace(from,to, false, self, true, false, target );
372  return ‪trace[ "position" ];
373 }
374 
375 
376 
377 function ‪can_see( target, target_origin, player_origin, player_forward, distance )
378 {
379  start = player_origin + player_forward * distance;
380  ‪end = target_origin - player_forward * distance;
381 
382  collided = self ‪trace( start, ‪end, target );
383 
384  if ( Distance2DSquared(‪end,collided) > 3 * 3 )
385  {
386  /#
387  if ( GetDvarInt( "scr_grapple_target_debug" ) )
388  {
389  Line(start,collided,(0,0,1),1,0,50);
390  Line(collided,‪end,(1,0,0),1,0,50);
391  }
392  #/
393  return false;
394  }
395 
396  /#
397  if ( GetDvarInt( "scr_grapple_target_debug" ) )
398  {
399  Line(start,‪end,(0,1,0),1,0,30);
400  }
401  #/
402  return true;
403 }
404 
405 function ‪is_valid_target( ent )
406 {
407  if ( IsDefined( ent ) && IsDefined( level.grapple_valid_target_check ) )
408  {
409  if ( ![[level.grapple_valid_target_check]](ent) )
410  return false;
411  }
412  return IsDefined( ent ) && ( IsAlive( ent ) || !IsSentient(ent) );
413 }
414 
415 function ‪inside_screen_angles( testOrigin, weapon, newtarget )
416 {
417  hang = weapon.lockonlossanglehorizontal;
418  if ( newtarget )
419  hang = weapon.lockonanglehorizontal;
420  vang = weapon.lockonlossanglevertical;
421  if ( newtarget )
422  vang = weapon.lockonanglevertical;
423 
424  angles = self GetTargetScreenAngles( testOrigin );
425 
426  return abs(angles[0]) < hang && abs(angles[1]) < vang;
427 }
428 
429 function ‪inside_screen_crosshair_radius( testOrigin, weapon )
430 {
431  radius = weapon.lockOnScreenRadius;
432 
433  return self ‪inside_screen_radius( testOrigin, radius );
434 }
435 
436 function ‪inside_screen_lockon_radius( targetOrigin )
437 {
438  radius = self getLockOnRadius();
439 
440  return self ‪inside_screen_radius( targetOrigin, radius );
441 }
442 
443 function ‪inside_screen_radius( targetOrigin, radius )
444 {
445  const useFov = 65;
446 
447  return Target_OriginIsInCircle( targetOrigin, self, useFov, radius );
448 }
449 
451 {
452  return self GetLockOnOrigin( target );
453 }
454 
455 
456 
457 
‪__init__
‪function __init__()
Definition: grapple.gsc:25
‪watch_lockon_angles
‪function watch_lockon_angles(weapon)
Definition: grapple.gsc:130
‪inside_screen_angles
‪function inside_screen_angles(testOrigin, weapon, newtarget)
Definition: grapple.gsc:415
‪GRAPPLE_TARGET_WEIGHT_DOT_OVER_DIST
‪#define GRAPPLE_TARGET_WEIGHT_DOT_OVER_DIST
Definition: grapple.gsc:310
‪watch_lockon
‪function watch_lockon(weapon)
Definition: grapple.gsc:79
‪inside_screen_lockon_radius
‪function inside_screen_lockon_radius(targetOrigin)
Definition: grapple.gsc:436
‪trace
‪function trace(from, to, target)
Definition: grapple.gsc:369
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪pow
‪function pow(base, exp)
Definition: math_shared.gsc:544
‪WEAPON_CHANGE_NOTIFY
‪#define WEAPON_CHANGE_NOTIFY
Definition: grapple.gsc:22
‪GRAPPLE_TARGET
‪#define GRAPPLE_TARGET
Definition: grapple.gsc:19
‪get_a_target
‪function get_a_target(weapon)
Definition: grapple.gsc:196
‪on_spawned
‪function on_spawned(func, obj)
Definition: callbacks_shared.csc:245
‪translate_notify_1
‪function translate_notify_1(from_notify, to_notify)
Definition: grapple.gsc:40
‪is_valid_target
‪function is_valid_target(ent)
Definition: grapple.gsc:405
‪clear_lockon_after_grapple
‪function clear_lockon_after_grapple(weapon)
Definition: grapple.gsc:110
‪REGISTER_SYSTEM_EX
‪#define REGISTER_SYSTEM_EX(__sys, __func_init_preload, __func_init_postload, __reqs)
Definition: shared.gsh:209
‪end
‪function end(final)
Definition: _killcam.gsc:511
‪inside_screen_radius
‪function inside_screen_radius(targetOrigin, radius)
Definition: grapple.gsc:443
‪waittill_any
‪function waittill_any(str_notify1, str_notify2, str_notify3, str_notify4, str_notify5)
Definition: util_shared.csc:375
‪__main__
‪function __main__()
Definition: grapple.gsc:30
‪get_target_score
‪function get_target_score(target, origin, forward, min_range, max_range)
Definition: grapple.gsc:312
‪pick_a_target_from
‪function pick_a_target_from(targets, origin, forward, min_range, max_range)
Definition: grapple.gsc:338
‪Spawn
‪function Spawn(parent, onDeathCallback)
Definition: _flak_drone.gsc:427
‪GRAPPLE_TYPE_TARGETONLY
‪#define GRAPPLE_TYPE_TARGETONLY
Definition: grapple.gsh:7
‪IS_EQUAL
‪#define IS_EQUAL(__a, __b)
Definition: shared.gsh:250
‪GRAPPLE_TYPE_PULLENTIN
‪#define GRAPPLE_TYPE_PULLENTIN
Definition: grapple.gsh:6
‪get_target_lock_on_origin
‪function get_target_lock_on_origin(target)
Definition: grapple.gsc:450
‪get_target_type_score
‪function get_target_type_score(target)
Definition: grapple.gsc:283
‪inside_screen_crosshair_radius
‪function inside_screen_crosshair_radius(testOrigin, weapon)
Definition: grapple.gsc:429
‪can_see
‪function can_see(target, target_origin, player_origin, player_forward, distance)
Definition: grapple.gsc:377
‪place_dummy_target
‪function place_dummy_target(origin, forward, weapon)
Definition: grapple.gsc:168
‪GRAPPLE_TYPE_REELPLAYER
‪#define GRAPPLE_TYPE_REELPLAYER
Definition: grapple.gsh:5
‪GRAPPLE_RETARGET_DELAY
‪#define GRAPPLE_RETARGET_DELAY
Definition: grapple.gsc:20
‪watch_for_grapple
‪function watch_for_grapple()
Definition: grapple.gsc:54
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265