‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_bouncingbetty.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\challenges_shared;
5 #using scripts\shared\clientfield_shared;
6 #using scripts\shared\scoreevents_shared;
7 #using scripts\shared\system_shared;
8 #using scripts\shared\util_shared;
9 #using scripts\shared\weapons\_weaponobjects;
10 
11 #insert scripts\shared\shared.gsh;
12 #insert scripts\shared\version.gsh;
13 
14 #define BETTY_DESTROYED_DAMAGE_RADIUS 128
15 #define BETTY_DESTROYED_DAMAGE_MAX 110
16 #define BETTY_DESTROYED_DAMAGE_MIN 10
17 
18 #precache( "fx", "weapon/fx_betty_exp_destroyed" );
19 #precache( "fx", "weapon/fx_betty_light_blue" );
20 #precache( "fx", "weapon/fx_betty_light_orng" );
21 
22 #precache( "model", "wpn_t7_grenade_incendiary_world" );
23 
24 
25 #using_animtree ( "bouncing_betty" );
26 
27 
28 #namespace bouncingbetty;
29 
30 function ‪init_shared()
31 {
32  level.bettyDestroyedFX = "weapon/fx_betty_exp_destroyed";
33 
34  level._effect["fx_betty_friendly_light"] = "weapon/fx_betty_light_blue";
35  level._effect["fx_betty_enemy_light"] = "weapon/fx_betty_light_orng";
36 
37  level.bettyMinDist = 20;
38  level.bettyStunTime = 1;
39 
40  bettyExplodeAnim = %o_spider_mine_detonate;
41  bettyDeployAnim = %o_spider_mine_deploy;
42 
43  level.bettyRadius = getDvarInt( "betty_detect_radius", 180 );
44  level.bettyActivationDelay = getDvarFloat( "betty_activation_delay", 1 );
45  level.bettyGracePeriod = getDvarFloat( "betty_grace_period", 0.0 );
46  level.bettyDamageRadius = getDvarInt( "betty_damage_radius", 180 );
47  level.bettyDamageMax = getDvarInt( "betty_damage_max", 180 );
48  level.bettyDamageMin = getDvarInt( "betty_damage_min", 70 );
49  level.bettyDamageHeight = getDvarInt( "betty_damage_cylinder_height", 200 );
50 
51  level.bettyJumpHeight = getDvarInt( "betty_jump_height_onground", 55 );
52  level.bettyJumpHeightWall = getDvarInt( "betty_jump_height_wall", 20 );
53  level.bettyJumpHeightWallAngle = getDvarInt( "betty_onground_angle_threshold", 30 );
54  level.bettyJumpHeightWallAngleCos = cos( level.bettyJumpHeightWallAngle );
55  level.bettyJumpTime = getDvarFloat( "betty_jump_time", 0.7 );
56 
57  level.bettyBombletSpawnDistance = 20;
58  level.bettyBombletCount = 4;
59 
60  level thread register();
61 
63 }
64 
65 function register()
66 {
67  ‪clientfield::register( "missile", "bouncingbetty_state", ‪VERSION_SHIP, 2, "int" );
68  ‪clientfield::register( "scriptmover", "bouncingbetty_state", ‪VERSION_SHIP, 2, "int" );
69 }
70 
71 //******************************************************************
72 // *
73 // *
74 //******************************************************************
75 function ‪createBouncingBettyWatcher() // self == player
76 {
77  watcher = self ‪weaponobjects::createProximityWeaponObjectWatcher( "bouncingbetty", self.team );
78 
79  watcher.onSpawn =&‪onSpawnBouncingBetty;
80  watcher.watchForFire = true;
81  watcher.onDetonateCallback =&‪bouncingBettyDetonate;
82  //Eckert - playing sound later
83  //watcher.activateSound = "fly_betty_exp";
84  watcher.activateSound = "wpn_betty_alert";
85  watcher.hackable = true;
86  watcher.hackerToolRadius = level.equipmentHackerToolRadius;
87  watcher.hackerToolTimeMs = level.equipmentHackerToolTimeMs;
88  watcher.ownerGetsAssist = true;
89  watcher.ignoreDirection = true;
90  watcher.immediateDetonation = true;
91  watcher.immunespecialty = "specialty_immunetriggerbetty";
92 
93  watcher.detectionMinDist = level.bettyMinDist;
94  watcher.detectionGracePeriod = level.bettyGracePeriod;
95  watcher.detonateRadius = level.bettyRadius;
96  watcher.onFizzleOut = &‪bouncingbetty::onBouncingBettyFizzleOut;
97 
98  watcher.stun =&‪weaponobjects::weaponStun;
99  watcher.stunTime = level.bettyStunTime;
100 
101  watcher.activationDelay = level.bettyActivationDelay;
102 }
103 
105 {
106  if ( isdefined( self.mineMover ) )
107  {
108  if ( isdefined( self.mineMover.killcament ) )
109  {
110  self.mineMover.killcament delete();
111  }
112  self.mineMover delete();
113  }
114  self delete();
115 }
116 
117 //******************************************************************
118 // *
119 // *
120 //******************************************************************
121 function ‪onSpawnBouncingBetty( watcher, owner ) // self == betty ent
122 {
124  self.originalOwner = owner;
125  self thread ‪spawnMineMover();
126  self ‪trackOnOwner( owner );
127  self thread ‪trackUsedStatOnDeath();
128  self thread ‪doNoTrackUsedStatOnPickup();
129  self thread ‪trackUsedOnHack();
130 }
131 
133 {
134  self endon( "do_not_track_used" );
135  self waittill( "death" );
136  waittillframeend; // to compensate for timiing issues with notifies and death
137  if ( isdefined( self.owner ) )
138  {
139  self.owner ‪trackBouncingBettyAsUsed(); // since betties can be picked up or hacked, we track them as used on death
140  }
141  self notify( "end_doNoTrackUsedOnPickup" );
142  self notify( "end_doNoTrackUsedOnHacked" );
143 }
144 
145 function ‪doNoTrackUsedStatOnPickup() // self == betty ent
146 {
147  self endon( "end_doNoTrackUsedOnPickup" );
148  self waittill( "picked_up" );
149  self notify( "do_not_track_used" );
150 }
151 
152 function ‪trackUsedOnHack() // self == betty ent
153 {
154  self endon( "end_doNoTrackUsedOnHacked" );
155  self waittill( "hacked" );
156  self.originalOwner ‪trackBouncingBettyAsUsed(); // since betties can be picked up or hacked, we track them as used on hack too
157  self notify( "do_not_track_used" ); // remove old one as it was hacked
158 }
159 
161 {
162  if ( IsPlayer( self ) )
163  {
164  self AddWeaponStat( GetWeapon( "bouncingbetty" ), "used", 1 );
165  }
166 }
167 
168 function ‪trackOnOwner( owner )
169 {
170  if ( level.trackBouncingBettiesOnOwner === true )
171  {
172  if ( !isdefined( owner ) )
173  return;
174 
175  if ( !isdefined( owner.activeBouncingBetties ) )
176  {
177  owner.activeBouncingBetties = [];
178  }
179  else
180  {
181  ArrayRemoveValue( owner.activeBouncingBetties, undefined );
182  }
183 
184  owner.activeBouncingBetties[ owner.activeBouncingBetties.size ] = self;
185  }
186 }
187 
188 //******************************************************************
189 // *
190 // *
191 //******************************************************************
192 function ‪spawnMineMover() // self == betty ent
193 {
194  self endon( "death" );
196  self ‪clientfield::set( "bouncingbetty_state", ‪BOUNCINGBETTY_DEPLOYING );
197 
198  self UseAnimTree( #animtree );
199  self SetAnim( %o_spider_mine_deploy, 1.0, 0.0, 1.0 );
200 
201  mineMover = ‪spawn( "script_model", self.origin );
202  mineMover.angles = self.angles;
203  mineMover SetModel( "tag_origin" );
204  mineMover.owner = self.owner;
205  mineUp = AnglesToUp( mineMover.angles );
206  z_offset = GetDvarFloat( "scr_bouncing_betty_killcam_offset", 18.0 );
207  mineMover.killCamOffset = VectorScale( mineUp, z_offset );
208  mineMover.weapon = self.weapon;
209  mineMover playsound ("wpn_betty_arm");
210 
211  killcamEnt = ‪spawn( "script_model", mineMover.origin + mineMover.killCamOffset );
212  killcamEnt.angles = ( 0,0,0 );
213  killcamEnt SetModel( "tag_origin" );
214  killcamEnt SetWeapon( self.weapon );
215 
216  mineMover.killcamEnt = killcamEnt;
217 
218  self.mineMover = mineMover;
219 
220  self thread ‪killMineMoverOnPickup();
221 }
222 
223 //******************************************************************
224 // *
225 // *
226 //******************************************************************
227 function ‪killMineMoverOnPickup() // self == betty ent
228 {
229  self.mineMover endon( "death" );
230 
231  self ‪util::waittill_any( "picked_up", "hacked" );
232 
233  self ‪killMineMover();
234 }
235 
236 //******************************************************************
237 // *
238 // *
239 //******************************************************************
240 function ‪killMineMover() // self == betty ent
241 {
242  if ( isdefined( self.mineMover ))
243  {
244  if ( isdefined( self.mineMover.killcamEnt ) )
245  {
246  self.mineMover.killcamEnt delete();
247  }
248  self.mineMover delete();
249  }
250 }
251 
252 //******************************************************************
253 // *
254 // *
255 //******************************************************************
256 function ‪bouncingBettyDetonate( attacker, weapon, target ) // self == betty
257 {
258  if ( IsDefined( weapon ) && weapon.isValid )
259  {
260  self.destroyedBy = attacker;
261  if ( isdefined( attacker ) )
262  {
263  if ( self.owner ‪util::IsEnemyPlayer( attacker ) )
264  {
265  attacker ‪challenges::destroyedExplosive( weapon );
266  ‪scoreevents::processScoreEvent( "destroyed_bouncingbetty", attacker, self.owner, weapon );
267  }
268  }
269 
271  }
272  else if ( isdefined( self.mineMover ))
273  {
274  self.mineMover.ignore_team_kills = true;
275  self.mineMover SetModel( self.model );
276  self.mineMover thread ‪bouncingBettyJumpAndExplode();
277  self delete();
278  }
279  else
280  {
281  // tagTMR<NOTE>: special case where betty hasn't settled yet but something has triggered a detonate
282  // i.e. the moving platforms doors on drone, etc
284  }
285 }
286 
287 //******************************************************************
288 // *
289 // *
290 //******************************************************************
291 function ‪bouncingBettyDestroyed( ) // self == betty
292 {
293  PlayFX( level.bettyDestroyedFX, self.origin );
294  PlaySoundAtPosition ( "dst_equipment_destroy", self.origin );
295 
296  if ( isdefined( self.trigger ) )
297  {
298  self.trigger delete();
299  }
300 
301  self ‪killMineMover();
302 
303  self RadiusDamage( self.origin, ‪BETTY_DESTROYED_DAMAGE_RADIUS, ‪BETTY_DESTROYED_DAMAGE_MAX, ‪BETTY_DESTROYED_DAMAGE_MIN, self.owner, "MOD_EXPLOSIVE", self.weapon );
304 
305  self delete();
306 }
307 
308 //******************************************************************
309 // *
310 // *
311 //******************************************************************
312 function ‪bouncingBettyJumpAndExplode() // self == script mover spawned at weaponobject location
313 {
314  jumpDir = VectorNormalize( AnglesToUp( self.angles ) );
315 
316  if ( jumpDir[2] > level.bettyJumpHeightWallAngleCos )
317  {
318  jumpHeight = level.bettyJumpHeight;
319  }
320  else
321  {
322  jumpHeight = level.bettyJumpHeightWall;
323  }
324 
325  explodePos = self.origin + jumpDir * jumpHeight;
326 
327  self.killCamEnt MoveTo( explodePos + self.killCamOffset, level.bettyJumpTime, 0, level.bettyJumpTime );
328 
329  self ‪clientfield::set( "bouncingbetty_state", ‪BOUNCINGBETTY_DETONATING );
330 
331  wait( level.bettyJumpTime );
332 
333  self thread ‪mineExplode( jumpDir, explodePos );
334 }
335 
336 
337 function ‪mineExplode( explosionDir, explodePos )
338 {
339  if ( !isdefined( self ) || !isdefined( self.owner ) )
340  return;
341 
342  self playsound( "wpn_betty_explo" );
343 
344  self ‪clientfield::set( "sndRattle", 1 );
345 
346  ‪WAIT_SERVER_FRAME; // needed or the effect doesn't play
347  if ( !isdefined( self ) || !isdefined(self.owner) )
348  return;
349 
350  self CylinderDamage( explosionDir * level.bettyDamageHeight, explodePos, level.bettyDamageRadius, level.bettyDamageRadius, level.bettyDamageMax, level.bettyDamageMin, self.owner, "MOD_EXPLOSIVE", self.weapon );
351  self ghost();
352 
353  wait( 0.1 );
354 
355 
356  if ( !isdefined( self ) || !isdefined(self.owner) )
357  return;
358 
359  if ( isdefined( self.trigger ) )
360  self.trigger delete();
361 
362  self.killCamEnt delete();
363  self delete();
364 }
365 
‪processScoreEvent
‪function processScoreEvent(event, player, victim, weapon)
Definition: scoreevents_shared.gsc:19
‪weaponStun
‪function weaponStun()
Definition: _weaponobjects.gsc:1128
‪BETTY_DESTROYED_DAMAGE_RADIUS
‪#define BETTY_DESTROYED_DAMAGE_RADIUS
Definition: _bouncingbetty.gsc:14
‪bouncingBettyDetonate
‪function bouncingBettyDetonate(attacker, weapon, target)
Definition: _bouncingbetty.gsc:256
‪bouncingBettyJumpAndExplode
‪function bouncingBettyJumpAndExplode()
Definition: _bouncingbetty.gsc:312
‪destroyedExplosive
‪function destroyedExplosive(weapon)
Definition: challenges_shared.gsc:951
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪trackUsedOnHack
‪function trackUsedOnHack()
Definition: _bouncingbetty.gsc:152
‪BOUNCINGBETTY_DEPLOYING
‪#define BOUNCINGBETTY_DEPLOYING
Definition: shared.gsh:328
‪killMineMover
‪function killMineMover()
Definition: _bouncingbetty.gsc:240
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪bouncingBettyDestroyed
‪function bouncingBettyDestroyed()
Definition: _bouncingbetty.gsc:291
‪IsEnemyPlayer
‪function IsEnemyPlayer(player)
Definition: util_shared.csc:1220
‪killMineMoverOnPickup
‪function killMineMoverOnPickup()
Definition: _bouncingbetty.gsc:227
‪BETTY_DESTROYED_DAMAGE_MIN
‪#define BETTY_DESTROYED_DAMAGE_MIN
Definition: _bouncingbetty.gsc:16
‪trackUsedStatOnDeath
‪function trackUsedStatOnDeath()
Definition: _bouncingbetty.gsc:132
‪doNoTrackUsedStatOnPickup
‪function doNoTrackUsedStatOnPickup()
Definition: _bouncingbetty.gsc:145
‪waittill_any
‪function waittill_any(str_notify1, str_notify2, str_notify3, str_notify4, str_notify5)
Definition: util_shared.csc:375
‪register
‪function register()
Definition: _bouncingbetty.gsc:65
‪init_shared
‪function init_shared()
Definition: _bouncingbetty.gsc:30
‪add_weapon_watcher
‪function add_weapon_watcher(callback)
Definition: callbacks_shared.gsc:609
‪spawnMineMover
‪function spawnMineMover()
Definition: _bouncingbetty.gsc:192
‪onBouncingBettyFizzleOut
‪function onBouncingBettyFizzleOut()
Definition: _bouncingbetty.gsc:104
‪createProximityWeaponObjectWatcher
‪function createProximityWeaponObjectWatcher(weaponname, ownerTeam)
Definition: _weaponobjects.gsc:1307
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪waitTillNotMoving
‪function waitTillNotMoving()
Definition: util_shared.gsc:2621
‪trackBouncingBettyAsUsed
‪function trackBouncingBettyAsUsed()
Definition: _bouncingbetty.gsc:160
‪onSpawnProximityWeaponObject
‪function onSpawnProximityWeaponObject(watcher, owner)
Definition: _weaponobjects.gsc:1603
‪BOUNCINGBETTY_DETONATING
‪#define BOUNCINGBETTY_DETONATING
Definition: shared.gsh:327
‪onSpawnBouncingBetty
‪function onSpawnBouncingBetty(watcher, owner)
Definition: _bouncingbetty.gsc:121
‪createBouncingBettyWatcher
‪function createBouncingBettyWatcher()
Definition: _bouncingbetty.gsc:75
‪trackOnOwner
‪function trackOnOwner(owner)
Definition: _bouncingbetty.gsc:168
‪BETTY_DESTROYED_DAMAGE_MAX
‪#define BETTY_DESTROYED_DAMAGE_MAX
Definition: _bouncingbetty.gsc:15
‪mineExplode
‪function mineExplode(explosionDir, explodePos)
Definition: _bouncingbetty.gsc:337
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265