‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_dogtags.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\clientfield_shared;
5 #using scripts\shared\gameobjects_shared;
6 #using scripts\shared\hostmigration_shared;
7 #using scripts\shared\objpoints_shared;
8 #using scripts\shared\scoreevents_shared;
9 #using scripts\shared\system_shared;
10 #using scripts\shared\util_shared;
11 
12 #insert scripts\shared\shared.gsh;
13 
14 #using scripts\mp\_util;
15 #using scripts\mp\gametypes\_globallogic_audio;
16 #using scripts\mp\gametypes\_globallogic_score;
17 #using scripts\mp\gametypes\_hostmigration;
18 #using scripts\mp\gametypes\_spectating;
19 
20 #namespace dogtags;
21 
22 #define DOGTAG_VANISH_FX "ui/fx_kill_confirmed_vanish"
23 
24 #precache( "fx", DOGTAG_VANISH_FX );
25 
26 function ‪init()
27 {
28  level.antiBoostDistance = GetGametypeSetting( "antiBoostDistance" );
29  level.dogtags = [];
30 }
31 
32 function ‪spawn_dog_tag( victim, attacker, on_use_function, objectives_for_attacker_and_victim_only )
33 {
34  if ( isdefined( level.dogtags[victim.entnum] ) )
35  {
36  ‪PlayFx( ‪DOGTAG_VANISH_FX, level.dogtags[victim.entnum].curOrigin );
37  level.dogtags[victim.entnum] notify( "reset" );
38  }
39  else
40  {
41  visuals[0] = ‪spawn( "script_model", (0,0,0) );
42  visuals[0] setModel( victim GetEnemyDogTagModel() );
43  visuals[1] = ‪spawn( "script_model", (0,0,0) );
44  visuals[1] setModel( victim GetFriendlyDogTagModel() );
45 
46  trigger = ‪spawn( "trigger_radius", (0,0,0), 0, 32, 32 );
47 
48  level.dogtags[victim.entnum] = ‪gameobjects::create_use_object( "any", trigger, visuals, (0,0,16) );
49 
50  level.dogtags[victim.entnum] ‪gameobjects::set_use_time( 0 );
51  level.dogtags[victim.entnum].onUse =&‪onUse;
52  level.dogtags[victim.entnum].custom_onUse = on_use_function;
53  level.dogtags[victim.entnum].victim = victim;
54  level.dogtags[victim.entnum].victimTeam = victim.team;
55 
56  level thread ‪clear_on_victim_disconnect( victim );
57  victim thread ‪team_updater( level.dogtags[victim.entnum] );
58 
59  foreach( team in level.teams )
60  {
61  objective_add( level.dogtags[victim.entnum].objId[team], "invisible", (0,0,0) );
62  objective_icon( level.dogtags[victim.entnum].objId[team], "waypoint_dogtags" );
63  Objective_Team( level.dogtags[victim.entnum].objId[team], team );
64  if ( team == attacker.team )
65  {
66  objective_setcolor( level.dogtags[victim.entnum].objId[team], &"EnemyOrange" );
67  }
68  else
69  {
70  objective_setcolor( level.dogtags[victim.entnum].objId[team], &"FriendlyBlue" );
71  }
72  }
73  }
74 
75  pos = victim.origin + (0,0,14);
76  level.dogtags[victim.entnum].curOrigin = pos;
77  level.dogtags[victim.entnum].trigger.origin = pos;
78  level.dogtags[victim.entnum].visuals[0].origin = pos;
79  level.dogtags[victim.entnum].visuals[1].origin = pos;
80 
81  level.dogtags[victim.entnum].visuals[0] DontInterpolate();
82  level.dogtags[victim.entnum].visuals[1] DontInterpolate();
83 
84  level.dogtags[victim.entnum] ‪gameobjects::allow_use( "any" );
85 
86  level.dogtags[victim.entnum].visuals[0] thread ‪show_to_team( level.dogtags[victim.entnum], attacker.team );
87  level.dogtags[victim.entnum].visuals[1] thread ‪show_to_enemy_teams( level.dogtags[victim.entnum], attacker.team );
88 
89  level.dogtags[victim.entnum].attacker = attacker;
90  level.dogtags[victim.entnum].attackerTeam = attacker.team;
91  level.dogtags[victim.entnum].unreachable = undefined;
92  level.dogtags[victim.entnum].tacInsert = false;
93  //level.dogtags[victim.entnum] thread time_out( victim );
94 
95  foreach( team in level.teams )
96  {
97  if ( IsDefined( level.dogtags[victim.entnum].objId[team] ) )
98  {
99  objective_position( level.dogtags[victim.entnum].objId[team], pos );
100  objective_state( level.dogtags[victim.entnum].objId[team], "active" );
101  }
102  }
103 
104  if ( objectives_for_attacker_and_victim_only )
105  {
106  Objective_SetInvisibleToAll( level.dogtags[victim.entnum].objId[attacker.team] );
107 
108  if ( IsPlayer( attacker ) )
109  Objective_SetVisibleToPlayer( level.dogtags[victim.entnum].objId[attacker.team], attacker );
110 
111  Objective_SetInvisibleToAll( level.dogtags[victim.entnum].objId[victim.team] );
112 
113  if ( IsPlayer( victim ) )
114  Objective_SetVisibleToPlayer( level.dogtags[victim.entnum].objId[victim.team], victim );
115  }
116 
117  //PlaySoundAtPosition( "mpl_killconfirm_tags_drop", pos );
118 
119  level.dogtags[victim.entnum] thread ‪bounce();
120  level notify( "dogtag_spawned" );
121 }
122 
123 
124 function ‪show_to_team( gameObject, show_team )
125 {
126  self show();
127 
128  foreach( team in level.teams )
129  {
130  self HideFromTeam( team );
131  }
132  self ShowToTeam( show_team );
133 }
134 
135 function ‪show_to_enemy_teams( gameObject, friend_team )
136 {
137  self show();
138 
139  foreach( team in level.teams )
140  {
141  self ShowToTeam( team );
142  }
143  self HideFromTeam( friend_team );
144 }
145 
146 function ‪onUse( player )
147 {
148  self.visuals[0] playSound( "mpl_killconfirm_tags_pickup" );
149  tacInsertBoost = false;
150 
151  // friendly pickup
152  if ( player.team != self.attackerTeam )
153  {
154  player AddPlayerStat( "KILLSDENIED", 1 );
155  player RecordGameEvent("return");
156 
157  if ( self.victim == player )
158  {
159  if ( self.tacInsert == false )
160  {
161  event = "retrieve_own_tags";
162  }
163  else
164  {
165  tacInsertBoost = true;
166  }
167  }
168  else
169  {
170  event = "kill_denied";
171  }
172 
173  if ( !tacInsertBoost )
174  {
175  player.pers["killsdenied"]++;
176  player.killsdenied = player.pers["killsdenied"];
177  }
178  }
179  else
180  {
181  event = "kill_confirmed";
182 
183  player AddPlayerStat( "KILLSCONFIRMED", 1 );
184  player RecordGameEvent("capture");
185 
186  if ( isdefined( self.attacker ) && self.attacker != player )
187  {
188  self.attacker ‪onPickup( "teammate_kill_confirmed" );
189  }
190  }
191 
192  if ( !tacInsertBoost && isdefined( player ) )
193  {
194  player ‪onPickup( event );
195  }
196 
197  [[self.custom_onUse]]( player );
198 
199  // do all this at the end now so the location doesn't change before playing the sound on the entity
200  self ‪reset_tags();
201 }
202 
203 
204 function ‪reset_tags()
205 {
206  self.attacker = undefined;
207  self.unreachable = undefined;
208  self notify( "reset" );
209  self.visuals[0] hide();
210  self.visuals[1] hide();
211  self.curOrigin = (0,0,1000);
212  self.trigger.origin = (0,0,1000);
213  self.visuals[0].origin = (0,0,1000);
214  self.visuals[1].origin = (0,0,1000);
215  self.tacInsert = false;
216  self ‪gameobjects::allow_use( "none" );
217 
218  foreach( team in level.teams )
219  {
220  objective_state( self.objId[team], "invisible" );
221  }
222 }
223 
224 
225 function ‪onPickup( event )
226 {
227  ‪scoreevents::processScoreEvent( event, self );
228 }
229 
230 
232 {
233  level endon( "game_ended" );
234 
235  guid = victim.entnum;
236  victim waittill( "disconnect" );
237 
238  if ( isdefined( level.dogtags[guid] ) )
239  {
240  // block further use
241  level.dogtags[guid] ‪gameobjects::allow_use( "none" );
242 
243  // play vanish effect, reset, and wait for reset to process
244  ‪PlayFx( ‪DOGTAG_VANISH_FX, level.dogtags[guid].curOrigin );
245  level.dogtags[guid] notify( "reset" );
247 
248  // sanity check before removal
249  if ( isdefined( level.dogtags[guid] ) )
250  {
251  // delete objective and visuals
252  foreach( team in level.teams )
253  {
254  objective_delete( level.dogtags[guid].objId[team] );
255  }
256  level.dogtags[guid].trigger delete();
257  for ( i=0; i<level.dogtags[guid].visuals.size; i++ )
258  level.dogtags[guid].visuals[i] delete();
259  level.dogtags[guid] notify ( "deleted" );
260 
261  // remove from list
262  level.dogtags[guid] = undefined;
263  }
264  }
265 }
266 
268 {
269  if ( level.rankedMatch || level.leagueMatch )
270  {
271  if ( isdefined(self.tacticalInsertionTime) && self.tacticalInsertionTime + 100 > GetTime() )
272  {
273  minDist = level.antiBoostDistance;
274  minDistSqr = minDist * minDist;
275 
276  distSqr = DistanceSquared( self.origin, level.dogtags[self.entnum].curOrigin );
277 
278  // tac insert spawn
279  if ( distSqr < minDistSqr )
280  {
281  level.dogtags[self.entnum].tacInsert = true;
282  }
283  }
284  }
285 }
286 
287 function ‪team_updater( tags )
288 {
289  level endon( "game_ended" );
290  self endon( "disconnect" );
291 
292  while( true )
293  {
294  self waittill( "joined_team" );
295 
296  tags.victimTeam = self.team;
297  tags ‪reset_tags();
298  }
299 }
300 
301 function ‪time_out( victim )
302 {
303  level endon( "game_ended" );
304  victim endon( "disconnect" );
305  self notify( "timeout" );
306  self endon( "timeout" );
307 
309 
310  self.visuals[0] hide();
311  self.visuals[1] hide();
312  self.curOrigin = (0,0,1000);
313  self.trigger.origin = (0,0,1000);
314  self.visuals[0].origin = (0,0,1000);
315  self.visuals[1].origin = (0,0,1000);
316  self.tacInsert = false;
317  self ‪gameobjects::allow_use( "none" );
318 }
319 
320 function ‪bounce()
321 {
322  level endon( "game_ended" );
323  self endon( "reset" );
324 
325  bottomPos = self.curOrigin;
326  topPos = self.curOrigin + (0,0,12);
327 
328  while( true )
329  {
330  self.visuals[0] moveTo( topPos, 0.5, 0.15, 0.15 );
331  self.visuals[0] rotateYaw( 180, 0.5 );
332  self.visuals[1] moveTo( topPos, 0.5, 0.15, 0.15 );
333  self.visuals[1] rotateYaw( 180, 0.5 );
334 
335  wait( 0.5 );
336 
337  self.visuals[0] moveTo( bottomPos, 0.5, 0.15, 0.15 );
338  self.visuals[0] rotateYaw( 180, 0.5 );
339  self.visuals[1] moveTo( bottomPos, 0.5, 0.15, 0.15 );
340  self.visuals[1] rotateYaw( 180, 0.5 );
341 
342  wait( 0.5 );
343  }
344 }
345 
347 {
348  self endon("disconnect");
349 
351  /*
352 
353  update = false;
354 
355  livesLeft = !(level.numLives && !self.pers["lives"]);
356 
357  if ( !level.aliveCount[ game["attackers"] ] && !livesLeft )
358  {
359  level.spectateOverride[game["attackers"]].allowEnemySpectate = 1;
360  update = true;
361  }
362  if ( !level.aliveCount[ game["defenders"] ] && !livesLeft )
363  {
364  level.spectateOverride[game["defenders"]].allowEnemySpectate = 1;
365  update = true;
366  }
367  if ( update )
368  */
370 }
371 
372 //self is victim
373 function ‪should_spawn_tags( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
374 {
375  if ( IsAlive( self ) )
376  return false;
377 
378  //no on switching teams
379  if ( IsDefined( self.switching_teams ) )
380  return false;
381 
382  //no on suicide
383  if ( isDefined( attacker ) && attacker == self )
384  return false;
385 
386  //no on TK
387  if ( level.teamBased && isDefined( attacker ) && isDefined( attacker.team ) && attacker.team == self.team )
388  return false;
389 
390  //no on world suicides
391  if( IsDefined( attacker ) && ( !IsDefined( attacker.team ) || attacker.team == "free" ) && ( attacker.classname == "trigger_hurt" || attacker.classname == "worldspawn" ) )
392  return false;
393 
394  return true;
395 }
396 
397 function ‪onUseDogTag( player )
398 {
399  // friendly pickup
400  if ( player.pers["team"] == self.victimTeam )
401  {
402  player.pers["rescues"]++;
403  player.rescues = player.pers["rescues"];
404 
405  if ( isdefined( self.victim ) )
406  {
407  if ( !level.gameEnded )
408  self.victim thread ‪dt_respawn();
409  }
410  }
411 }
412 
413 function ‪dt_respawn()
414 {
415  // Need to count this player as alive immediately, because they can wait to spawn whenever they want. If we don't increment this until they become alive,
416  // then things get screwed up when level.aliveCount becomes 1. The game thinks that there's only one player left alive, and yet there are multiple players
417  // on the team with self.pers["lives"] greater than 0.
418  self thread ‪waitTillCanSpawnClient();
419 }
420 
421 //fixes a potential race condition with spawning around the same frame as friendly tag pickup
423 {
424  for (;;)
425  {
426  wait ( .05 );
427  if ( isDefined( self ) && ( self.sessionstate == "spectator" || !isAlive( self ) ) )
428  {
429  self.pers["lives"] = 1;
430  self thread [[level.spawnClient]]();
431 
432  //we need to continue here because spawn client can fail for up to 3 server frames in this instance
433  continue;
434  }
435 
436  //player either disconnected or has spawned
437  return;
438  }
439 }
‪create_use_object
‪function create_use_object(ownerTeam, trigger, visuals, offset, objectiveName, allowInitialHoldDelay=false, allowWeaponCyclingDuringHold=false)
Definition: gameobjects_shared.gsc:1491
‪clear_on_victim_disconnect
‪function clear_on_victim_disconnect(victim)
Definition: _dogtags.gsc:231
‪processScoreEvent
‪function processScoreEvent(event, player, victim, weapon)
Definition: scoreevents_shared.gsc:19
‪update_settings
‪function update_settings()
Definition: _spectating.gsc:28
‪allow_use
‪function allow_use(relativeTeam)
Definition: gameobjects_shared.gsc:3485
‪set_use_time
‪function set_use_time(time)
Definition: gameobjects_shared.gsc:3455
‪show_to_team
‪function show_to_team(gameObject, show_team)
Definition: _dogtags.gsc:124
‪waitLongDurationWithHostMigrationPause
‪function waitLongDurationWithHostMigrationPause(duration)
Definition: hostmigration_shared.gsc:216
‪team_updater
‪function team_updater(tags)
Definition: _dogtags.gsc:287
‪checkAllowSpectating
‪function checkAllowSpectating()
Definition: _dogtags.gsc:346
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪dt_respawn
‪function dt_respawn()
Definition: _dogtags.gsc:413
‪should_spawn_tags
‪function should_spawn_tags(eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
Definition: _dogtags.gsc:373
‪time_out
‪function time_out(victim)
Definition: _dogtags.gsc:301
‪show_to_enemy_teams
‪function show_to_enemy_teams(gameObject, friend_team)
Definition: _dogtags.gsc:135
‪onUseDogTag
‪function onUseDogTag(player)
Definition: _dogtags.gsc:397
‪init
‪function init()
Definition: _dogtags.gsc:26
‪on_spawn_player
‪function on_spawn_player()
Definition: _dogtags.gsc:267
‪onUse
‪function onUse(player)
Definition: _dogtags.gsc:146
‪bounce
‪function bounce()
Definition: _dogtags.gsc:320
‪spawn_dog_tag
‪function spawn_dog_tag(victim, attacker, on_use_function, objectives_for_attacker_and_victim_only)
Definition: _dogtags.gsc:32
‪DOGTAG_VANISH_FX
‪#define DOGTAG_VANISH_FX
Definition: _dogtags.gsc:22
‪waitTillCanSpawnClient
‪function waitTillCanSpawnClient()
Definition: _dogtags.gsc:422
‪reset_tags
‪function reset_tags()
Definition: _dogtags.gsc:204
‪onPickup
‪function onPickup(event)
Definition: _dogtags.gsc:225
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265
‪PlayFx
‪function PlayFx(name)
Definition: _counteruav.gsc:390