‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
dom.gsc
Go to the documentation of this file.
1 #using scripts\shared\callbacks_shared;
2 #using scripts\shared\challenges_shared;
3 #using scripts\shared\demo_shared;
4 #using scripts\shared\gameobjects_shared;
5 #using scripts\shared\hostmigration_shared;
6 #using scripts\shared\math_shared;
7 #using scripts\shared\popups_shared;
8 #using scripts\shared\scoreevents_shared;
9 #using scripts\shared\sound_shared;
10 #using scripts\shared\util_shared;
11 
12 #insert scripts\shared\shared.gsh;
13 #insert scripts\shared\version.gsh;
14 
15 #using scripts\mp\gametypes\_globallogic;
16 #using scripts\mp\gametypes\_globallogic_audio;
17 #using scripts\mp\gametypes\_globallogic_score;
18 #using scripts\mp\gametypes\_globallogic_utils;
19 #using scripts\mp\gametypes\_hostmigration;
20 #using scripts\mp\gametypes\_spawning;
21 #using scripts\mp\gametypes\_spawnlogic;
22 
23 #using scripts\mp\_challenges;
24 #using scripts\mp\_util;
25 #using scripts\mp\teams\_teams;
26 
27 /*
28  Domination
29  Objective: Capture all the flags by touching them
30  Map ends: When one team captures all the flags, or time limit is reached
31  Respawning: No wait / Near teammates
32 
33  Level requirements
34  ------------------
35  Spawnpoints:
36  classname mp_tdm_spawn
37  All players spawn from these. The spawnpoint chosen is dependent on the current locations of owned flags, teammates and
38  enemies at the time of spawn. Players generally spawn behind their teammates relative to the direction of enemies.
39  Optionally, give a spawnpoint a script_linkto to specify which flag it "belongs" to (see Flag Descriptors).
40 
41  Spectator Spawnpoints:
42  classname mp_global_intermission
43  Spectators spawn from these and intermission is viewed from these positions.
44  Atleast one is required, any more and they are randomly chosen between.
45 
46  Flags:
47  classname trigger_radius
48  targetname flag_primary or flag_secondary
49  Flags that need to be captured to win. Primary flags take time to capture; secondary flags are instant.
50 
51  Flag Descriptors:
52  classname script_origin
53  targetname flag_descriptor
54  Place one flag descriptor close to each flag. Use the script_linkname and script_linkto properties to say which flags
55  it can be considered "adjacent" to in the level. For instance, if players have a primary path from flag1 to flag2, and
56  from flag2 to flag3, flag2 would have a flag_descriptor with these properties:
57  script_linkname flag2
58  script_linkto flag1 flag3
59 
60  Level script requirements
61  -------------------------
62  Team Definitions:
63  game["allies"] = "marines";
64  game["axis"] = "nva";
65  This sets the nationalities of the teams. Allies can be american, british, or russian. Axis can be german.
66 
67  If using minefields or exploders:
68  load::main();
69 
70  Optional level script settings
71  ------------------------------
72  Soldier Type and Variation:
73  game["soldiertypeset"] = "seals";
74  This sets what character models are used for each nationality on a particular map.
75 
76  Valid settings:
77  soldiertypeset seals
78 */
79 
80 /*QUAKED mp_dom_spawn (0.5 0.5 1.0) (-16 -16 0) (16 16 72)
81 Players spawn near their flags at one of these positions.*/
82 
83 /*QUAKED mp_dom_spawn_flag_a (0.5 0.5 1.0) (-16 -16 0) (16 16 72)
84 Players spawn near their flags at one of these positions.*/
85 
86 /*QUAKED mp_dom_spawn_flag_b (0.5 0.5 1.0) (-16 -16 0) (16 16 72)
87 Players spawn near their flags at one of these positions.*/
88 
89 /*QUAKED mp_dom_spawn_flag_c (0.5 0.5 1.0) (-16 -16 0) (16 16 72)
90 Players spawn near their flags at one of these positions.*/
91 
92 /*QUAKED mp_dom_spawn_axis_start (1.0 0.0 1.0) (-16 -16 0) (16 16 72)
93 Axis players spawn away from enemies and near their team at one of these positions at the start of a round.*/
94 
95 /*QUAKED mp_dom_spawn_allies_start (0.0 1.0 1.0) (-16 -16 0) (16 16 72)
96 Allied players spawn away from enemies and near their team at one of these positions at the start of a round.*/
97 
98 #precache( "string", "OBJECTIVES_DOM" );
99 #precache( "string", "OBJECTIVES_DOM_SCORE" );
100 #precache( "string", "OBJECTIVES_DOM_HINT" );
101 #precache( "string", "MP_CAPTURING_FLAG" );
102 #precache( "string", "MP_LOSING_FLAG" );
103 #precache( "string", "MP_DOM_YOUR_FLAG_WAS_CAPTURED" );
104 #precache( "string", "MP_DOM_ENEMY_FLAG_CAPTURED" );
105 #precache( "string", "MP_DOM_NEUTRAL_FLAG_CAPTURED" );
106 #precache( "string", "MP_ENEMY_FLAG_CAPTURED_BY" );
107 #precache( "string", "MP_NEUTRAL_FLAG_CAPTURED_BY" );
108 #precache( "string", "MP_FRIENDLY_FLAG_CAPTURED_BY" );
109 #precache( "string", "MP_DOM_FLAG_A_CAPTURED_BY" );
110 #precache( "string", "MP_DOM_FLAG_B_CAPTURED_BY" );
111 #precache( "string", "MP_DOM_FLAG_C_CAPTURED_BY" );
112 #precache( "string", "MP_DOM_FLAG_D_CAPTURED_BY" );
113 #precache( "string", "MP_DOM_FLAG_E_CAPTURED_BY" );
114 #precache( "fx", "ui/fx_ui_flagbase_blue" );
115 #precache( "fx", "ui/fx_ui_flagbase_orng" );
116 #precache( "fx", "ui/fx_ui_flagbase_wht" );
117 #precache( "objective", "dom_a" );
118 #precache( "objective", "dom_b" );
119 #precache( "objective", "dom_c" );
120 
121 #define DIALOG_THROTTLE 10000
122 
123 function ‪main()
124 {
126 
127  ‪util::registerTimeLimit( 0, 1440 );
128  ‪util::registerScoreLimit( 0, 2000 );
133  ‪util::registerNumLives( 0, 100 );
134 
135  ‪globallogic::registerFriendlyFireDelay( level.gameType, 15, 0, 1440 );
136 
137  level.scoreRoundWinBased = ( GetGametypeSetting( "cumulativeRoundScores" ) == false );
138  level.teamBased = true;
139  level.overrideTeamScore = true;
140  level.onStartGameType =&‪onStartGameType;
141  level.onPlayerKilled =&‪onPlayerKilled;
142  level.onRoundSwitch =&‪onRoundSwitch;
143  level.onPrecacheGameType =&‪onPrecacheGameType;
144  level.onEndGame=&‪onEndGame;
145  level.onRoundEndGame =&‪onRoundEndGame;
146 
148 
149  ‪globallogic_audio::set_leader_gametype_dialog ( "startDomination", "hcStartDomination", "objCapture", "objCapture" );
150 
151  game["dialog"]["securing_a"] = "domFriendlySecuringA";
152  game["dialog"]["securing_b"] = "domFriendlySecuringB";
153  game["dialog"]["securing_c"] = "domFriendlySecuringC";
154 
155  game["dialog"]["secured_a"] = "domFriendlySecuredA";
156  game["dialog"]["secured_b"] = "domFriendlySecuredB";
157  game["dialog"]["secured_c"] = "domFriendlySecuredC";
158 
159  game["dialog"]["secured_all"] = "domFriendlySecuredAll";
160 
161  game["dialog"]["losing_a"] = "domEnemySecuringA";
162  game["dialog"]["losing_b"] = "domEnemySecuringB";
163  game["dialog"]["losing_c"] = "domEnemySecuringC";
164 
165  game["dialog"]["lost_a"] = "domEnemySecuredA";
166  game["dialog"]["lost_b"] = "domEnemySecuredB";
167  game["dialog"]["lost_c"] = "domEnemySecuredC";
168 
169  game["dialog"]["lost_all"] = "domEnemySecuredAll";
170 
171  game["dialog"]["enemy_a"] = "domEnemyHasA";
172  game["dialog"]["enemy_b"] = "domEnemyHasB";
173  game["dialog"]["enemy_c"] = "domEnemyHasC";
174 
175  game["dialogTime"] = [];
176  game["dialogTime"]["securing_a"] = 0;
177  game["dialogTime"]["securing_b"] = 0;
178  game["dialogTime"]["securing_c"] = 0;
179  game["dialogTime"]["losing_a"] = 0;
180  game["dialogTime"]["losing_b"] = 0;
181  game["dialogTime"]["losing_c"] = 0;
182 
183  // Sets the scoreboard columns and determines with data is sent across the network
184  if ( !SessionModeIsSystemlink() && !SessionModeIsOnlineGame() && IsSplitScreen() )
185  // local matches only show the first three columns
186  ‪globallogic::setvisiblescoreboardcolumns( "score", "kills", "captures", "defends", "deaths" );
187  else
188  ‪globallogic::setvisiblescoreboardcolumns( "score", "kills", "deaths" , "captures", "defends");
189 }
190 
191 
193 {
194 }
195 
196 
198 {
199  ‪util::setObjectiveText( "allies", &"OBJECTIVES_DOM" );
200  ‪util::setObjectiveText( "axis", &"OBJECTIVES_DOM" );
201 
202  if ( !isdefined( game["switchedsides"] ) )
203  game["switchedsides"] = false;
204 
205  if ( game["switchedsides"] )
206  {
207  oldAttackers = game["attackers"];
208  oldDefenders = game["defenders"];
209  game["attackers"] = oldDefenders;
210  game["defenders"] = oldAttackers;
211  }
212 
213  if ( level.splitscreen )
214  {
215  ‪util::setObjectiveScoreText( "allies", &"OBJECTIVES_DOM" );
216  ‪util::setObjectiveScoreText( "axis", &"OBJECTIVES_DOM" );
217  }
218  else
219  {
220  ‪util::setObjectiveScoreText( "allies", &"OBJECTIVES_DOM_SCORE" );
221  ‪util::setObjectiveScoreText( "axis", &"OBJECTIVES_DOM_SCORE" );
222  }
223  ‪util::setObjectiveHintText( "allies", &"OBJECTIVES_DOM_HINT" );
224  ‪util::setObjectiveHintText( "axis", &"OBJECTIVES_DOM_HINT" );
225 
226  level.flagBaseFXid = [];
227 
228  setClientNameMode("auto_change");
229 
230  // now that the game objects have been deleted place the influencers
232 
233  level.spawnMins = ( 0, 0, 0 );
234  level.spawnMaxs = ( 0, 0, 0 );
235  ‪spawnlogic::place_spawn_points( "mp_dom_spawn_allies_start" );
236  ‪spawnlogic::place_spawn_points( "mp_dom_spawn_axis_start" );
237 
238 
239  level.mapCenter = ‪math::find_box_center( level.spawnMins, level.spawnMaxs );
240  setMapCenter( level.mapCenter );
241 
243  setDemoIntermissionPoint( spawnpoint.origin, spawnpoint.angles );
244 
245  level.spawn_all = ‪spawnlogic::get_spawnpoint_array( "mp_dom_spawn" );
246 
247  level.spawn_start = [];
248 
249  foreach( team in level.teams )
250  {
251  level.spawn_start[ team ] = ‪spawnlogic::get_spawnpoint_array("mp_dom_spawn_" + team + "_start");
252  }
253 
254  flagSpawns = ‪spawnlogic::get_spawnpoint_array( "mp_dom_spawn_flag_a" );
255  //assert( flagSpawns.size > 0 );
256 
257  level.startPos["allies"] = level.spawn_start[ "allies" ][0].origin;
258  level.startPos["axis"] = level.spawn_start[ "axis" ][0].origin;
259 
260 
261  if ( !‪util::isOneRound() && level.scoreRoundWinBased )
262  {
264  }
265 
266  level.spawnsystem.sideSwitching = 0;
267 
268  level thread ‪watchForBFlagCap();
270  thread ‪domFlags();
271  thread ‪updateDomScores();
272  level ‪change_dom_spawns();
273 }
274 
275 function ‪onEndGame( winningTeam )
276 {
277  for ( i = 0; i < level.domFlags.size; i++ )
278  {
279  domFlag = level.domFlags[i];
280  domFlag ‪gameobjects::allow_use( "none" );
281  if ( isdefined( domFlag.singleOwner ) && domFlag.singleOwner == true )
282  {
283  team = domFlag ‪gameobjects::get_owner_team();
284  label = domFlag ‪gameobjects::get_label();
285  ‪challenges::holdFlagEntireMatch( team, label );
286  }
287  }
288 }
289 
290 function ‪onRoundEndGame( roundWinner )
291 {
292  if ( level.scoreRoundWinBased )
293  {
294  foreach( team in level.teams )
295  {
296  [[level._setTeamScore]]( team, game["roundswon"][team] );
297  }
298  }
299 
300  return [[level.determineWinner]]();
301 }
302 
304 {
305  level.flagCaptureTime = GetGametypeSetting( "captureTime" );
306  level.playerCaptureLPM = GetGametypeSetting( "maxPlayerEventsPerMinute" );
307  level.flagCaptureLPM = GetGametypeSetting( "maxObjectiveEventsPerMinute" );
308  level.playerOffensiveMax = GetGametypeSetting( "maxPlayerOffensive" );
309  level.playerDefensiveMax = GetGametypeSetting( "maxPlayerDefensive" );
310  level.flagCanBeNeutralized = GetGametypeSetting( "flagCanBeNeutralized" );
311 }
312 
313 function ‪domFlags()
314 {
315  level.lastStatus["allies"] = 0;
316  level.lastStatus["axis"] = 0;
317 
318  level.flagModel["allies"] = "tag_origin"; // teams::get_flag_model( "allies" );
319  level.flagModel["axis"] = "tag_origin"; // teams::get_flag_model( "axis" );
320  level.flagModel["neutral"] = "tag_origin"; // teams::get_flag_model( "neutral" );
321 
322  primaryFlags = getEntArray( "flag_primary", "targetname" );
323 
324  if ( (primaryFlags.size) < 2 )
325  {
326  /# printLn( "^1Not enough domination flags found in level!" ); #/
328  return;
329  }
330 
331  level.flags = [];
332  foreach( dom_flag in primaryFlags )
333  {
334  if ( isdefined( dom_flag.target ) )
335  {
336  trigger = getEnt( dom_flag.target, "targetname" );
337 
338  if ( isDefined( trigger ) )
339  {
340  trigger.visual = dom_flag;
341  trigger.script_label = dom_flag.script_label;
342  }
343  else
344  {
345  /#
346  println("Trigger not available for flag " + dom_flag.script_label + " with targetname " + dom_flag.target);
347  #/
348  }
349  }
350  else
351  {
352  /#
353  println("Trigger not available for flag " + dom_flag.script_label);
354  #/
355  }
356 
357  level.flags[level.flags.size] = trigger;
358  }
359 
360  level.domFlags = [];
361  foreach( trigger in level.flags )
362  {
363  trigger.visual setModel( level.flagModel["neutral"] );
364 
365  ‪name = istring("dom" + trigger.visual.script_label);
366 
367  visuals = [];
368  visuals[0] = trigger.visual;
369 
370  domFlag = ‪gameobjects::create_use_object( "neutral", trigger, visuals, (0,0,0), ‪name );
371  domFlag ‪gameobjects::allow_use( "enemy" );
372  if( level.flagCanBeNeutralized )
373  {
374  domFlag ‪gameobjects::set_use_time( level.flagCaptureTime / 2 );
375  }
376  else
377  {
378  domFlag ‪gameobjects::set_use_time( level.flagCaptureTime );
379  }
380  domFlag ‪gameobjects::set_use_text( &"MP_CAPTURING_FLAG" );
381  label = domFlag ‪gameobjects::get_label();
382  domFlag.label = label;
383  domFlag.flagIndex = trigger.visual.script_index;
384  domFlag ‪gameobjects::set_visible_team( "any" );
385  domFlag.onUse =&‪onUse;
386  domFlag.onBeginUse =&‪onBeginUse;
387  domFlag.onUseUpdate =&‪onUseUpdate;
388  domFlag.onEndUse =&‪onEndUse;
389  domFlag.onUpdateUseRate =&‪onUpdateUseRate;
390  domFlag.hasBeenCaptured = false;
391 
392  domFlag ‪gameobjects::set_objective_entity( visuals[ 0 ] );
393  domFlag ‪gameobjects::set_owner_team( "neutral" );
394 
395  traceStart = visuals[0].origin + (0,0,32);
396  traceEnd = visuals[0].origin + (0,0,-32);
397  ‪trace = bulletTrace( traceStart, traceEnd, false, undefined );
398 
399  upangles = vectorToAngles( ‪trace["normal"] );
400  domFlag.baseeffectforward = anglesToForward( upangles );
401  domFlag.baseeffectright = anglesToRight( upangles );
402 
403  domFlag.baseeffectpos = ‪trace["position"];
404 
405  // legacy spawn code support
406  trigger.useObj = domFlag;
407  trigger.adjflags = [];
408  trigger.nearbyspawns = [];
409 
410  domFlag.levelFlag = trigger;
411 
412  level.domFlags[level.domFlags.size] = domFlag;
413  }
414 
415  // level.bestSpawnFlag is used as a last resort when the enemy holds all flags.
416  level.bestSpawnFlag = [];
417  level.bestSpawnFlag[ "allies" ] = ‪getUnownedFlagNearestStart( "allies", undefined );
418  level.bestSpawnFlag[ "axis" ] = ‪getUnownedFlagNearestStart( "axis", level.bestSpawnFlag[ "allies" ] );
419 
420  for ( index = 0; index < level.domFlags.size; index++ )
421  {
422  level.domFlags[index] ‪createFlagSpawnInfluencers();
423  }
424 
425  ‪flagSetup();
426 }
427 
428 function ‪getUnownedFlagNearestStart( team, excludeFlag )
429 {
430  best = undefined;
431  bestdistsq = undefined;
432  for ( i = 0; i < level.flags.size; i++ )
433  {
434  flag = level.flags[i];
435 
436  if ( flag ‪getFlagTeam() != "neutral" )
437  continue;
438 
439  distsq = distanceSquared( flag.origin, level.startPos[team] );
440  if ( (!isdefined( excludeFlag ) || flag != excludeFlag) && (!isdefined( best ) || distsq < bestdistsq) )
441  {
442  bestdistsq = distsq;
443  best = flag;
444  }
445  }
446  return best;
447 }
448 
449 function ‪onBeginUse( player )
450 {
451  ownerTeam = self ‪gameobjects::get_owner_team();
452  self.didStatusNotify = false;
453  if ( ownerTeam == "allies" )
454  otherTeam = "axis";
455  else
456  otherTeam = "allies";
457 
458  if ( ownerTeam == "neutral" )
459  {
460  otherTeam = ‪util::getOtherTeam( player.pers["team"] );
461  ‪statusDialog( "securing"+self.label, player.pers["team"], "objective" + self.label );
462  return;
463  }
464 }
465 
466 function ‪onUseUpdate( team, progress, ‪change )
467 {
468  if ( progress > 0.05 && ‪change && !self.didStatusNotify )
469  {
470  ownerTeam = self ‪gameobjects::get_owner_team();
471  if ( ownerTeam == "neutral" )
472  {
473  otherTeam = ‪util::getOtherTeam( team );
474  ‪statusDialog( "securing"+self.label, team, "objective" + self.label );
475  }
476  else
477  {
478  ‪statusDialog( "losing"+self.label, ownerTeam, "objective" + self.label );
479  ‪statusDialog( "securing"+self.label, team, "objective" + self.label );
481  }
482 
483  self.didStatusNotify = true;
484  }
485 }
486 
488 {
492 }
493 
494 function ‪statusDialog( dialog, team, objectiveKey )
495 {
496  // Don't play some dialog over and over
497  dialogTime = game["dialogTime"][dialog];
498  if ( isdefined( dialogTime) )
499  {
500  time = GetTime();
501 
502  if ( dialogTime > time )
503  {
504  return;
505  }
506 
507  game["dialogTime"][dialog] = time + ‪DIALOG_THROTTLE;
508  }
509 
510  dialogKey = game["dialog"][dialog];
511 
512  if( isdefined( objectiveKey ) )
513  {
514  if( objectiveKey != "objective_all" )
515  {
516  dialogBufferKey = "domPointDialogBuffer";
517  }
518  }
519 
520  ‪globallogic_audio::leader_dialog( dialogKey, team, undefined, objectiveKey, undefined, dialogBufferKey );
521 }
522 
523 
524 function ‪onEndUse( team, player, success )
525 {
526  if ( !success )
527  {
528  ‪globallogic_audio::flush_objective_dialog( "objective" + self.label );
529  }
530 }
531 
533 {
534  self.singleOwner = true;
535  otherTeam = ‪util::getOtherTeam( team );
536  thread ‪util::printAndSoundOnEveryone( team, undefined, &"", undefined, "mp_war_objective_taken" );
537 
538  thread ‪sound::play_on_players( "mus_dom_captured"+"_"+level.teamPostfix[team] );
539  if ( ‪getTeamFlagCount( team ) == level.flags.size )
540  {
541  ‪statusDialog( "secured_all", team, "objective_all" );
542  ‪statusDialog( "lost_all", otherTeam, "objective_all" );
544  }
545  else
546  {
547  ‪statusDialog( "secured"+self.label, team, "objective" + self.label );
548  ‪statusDialog( "enemy"+self.label, otherTeam, "objective" + self.label );
550  ‪globallogic_audio::play_2d_on_team( "mpl_flagcapture_sting_enemy", otherTeam );
551  ‪globallogic_audio::play_2d_on_team( "mpl_flagcapture_sting_friend", team );
552  }
553 }
554 
555 function ‪flagCapturedFromTeam( team, oldTeam )
556 {
557  self.singleOwner = false;
558  thread ‪util::printAndSoundOnEveryone( team, oldTeam, &"", &"", "mp_war_objective_taken", "mp_war_objective_lost", "" );
559 
560  if ( ‪getTeamFlagCount( team ) == level.flags.size )
561  {
562  ‪statusDialog( "secured_all", team, "objective_all" );
563  ‪statusDialog( "lost_all", oldTeam, "objective_all" );
565  }
566  else
567  {
568  ‪statusDialog( "secured"+self.label, team, "objective" + self.label );
569  if( RandomInt(2) )
570  {
571  ‪statusDialog( "lost"+self.label, oldTeam, "objective" + self.label );
572  }
573  else
574  {
575  ‪statusDialog( "enemy"+self.label, oldTeam, "objective" + self.label );
576  }
578  ‪globallogic_audio::play_2d_on_team( "mpl_flagcapture_sting_enemy", oldTeam );
579  ‪globallogic_audio::play_2d_on_team( "mpl_flagcapture_sting_friend", team );
580  }
581 
582  level.bestSpawnFlag[ oldTeam ] = self.levelFlag;
583 }
584 
585 function ‪flagNeutralized( team, oldTeam )
586 {
587  self.singleOwner = true;
588  thread ‪util::printAndSoundOnEveryone( "neutral", oldTeam, &"", &"", "mp_war_objective_neutralized", "mp_war_objective_lost", "" );
589 
590  if ( ‪getTeamFlagCount( team ) == level.flags.size )
591  {
592  ‪statusDialog( "lost_all", oldTeam, "objective_all" );
594  }
595  else
596  {
597  ‪statusDialog( "lost"+self.label, oldTeam, "objective" + self.label );
598 
600  ‪globallogic_audio::play_2d_on_team( "mpl_flagcapture_sting_enemy", oldTeam );
601  }
602 }
603 
604 function ‪GetDomFlagUseString( label, neutralized )
605 {
606  string = &"";
607  if( neutralized )
608  {
609  switch ( label )
610  {
611  case "_a":
612  string = &"MP_DOM_FLAG_A_NEUTRALIZED_BY";
613  break;
614  case "_b":
615  string = &"MP_DOM_FLAG_B_NEUTRALIZED_BY";
616  break;
617  case "_c":
618  string = &"MP_DOM_FLAG_C_NEUTRALIZED_BY";
619  break;
620  case "_d":
621  string = &"MP_DOM_FLAG_D_NEUTRALIZED_BY";
622  break;
623  case "_e":
624  string = &"MP_DOM_FLAG_E_NEUTRALIZED_BY";
625  break;
626  default:
627  break;
628  }
629  }
630  else
631  {
632  switch ( label )
633  {
634  case "_a":
635  string = &"MP_DOM_FLAG_A_CAPTURED_BY";
636  break;
637  case "_b":
638  string = &"MP_DOM_FLAG_B_CAPTURED_BY";
639  break;
640  case "_c":
641  string = &"MP_DOM_FLAG_C_CAPTURED_BY";
642  break;
643  case "_d":
644  string = &"MP_DOM_FLAG_D_CAPTURED_BY";
645  break;
646  case "_e":
647  string = &"MP_DOM_FLAG_E_CAPTURED_BY";
648  break;
649  default:
650  break;
651  }
652  }
653 
654  return string;
655 }
656 
658 {
659  team = player.pers["team"];
660  oldTeam = self ‪gameobjects::get_owner_team();
661  label = self ‪gameobjects::get_label();
662 
663  /#print( "flag captured: " + self.label );#/
664 
665  level.useStartSpawns = false;
666 
667  assert( team != "neutral" );
668 
669  string = &"";
670  if ( oldTeam == "neutral" )
671  {
672  level notify( "flag_captured" );
673  string = ‪GetDomFlagUseString( label, false );
674  level.bestSpawnFlag[ oldTeam ] = self.levelFlag;
675 
676  self ‪gameobjects::set_owner_team( team );
677  self.visuals[0] setModel( level.flagModel[team] );
678  SetDvar( "scr_obj" + self ‪gameobjects::get_label(), team );
679  self ‪update_spawn_influencers( team );
680  self ‪flagCapturedFromNeutral( team );
681  }
682  else
683  {
684  level notify( "flag_neutralized" );
685  string = ‪GetDomFlagUseString( label, true );
686 
687  self ‪gameobjects::set_owner_team( "neutral" );
688  self.visuals[0] setModel( level.flagModel["neutral"] );
689  SetDvar( "scr_obj" + self ‪gameobjects::get_label(), "neutral" );
690  self ‪update_spawn_influencers( "neutral" );
691  self ‪flagNeutralized( team, oldTeam );
692  }
693  assert ( string != &"" );
694 
695  // Copy touch list so there aren't any threading issues
696  touchList = [];
697  touchKeys = GetArrayKeys( self.touchList[team] );
698  for ( i = 0 ; i < touchKeys.size ; i++ )
699  touchList[touchKeys[i]] = self.touchList[team][touchKeys[i]];
700 
701  isBFlag = false;
702  if( label == "_b" )
703  {
704  isBFlag = true;
705  }
706 
707  if( oldTeam == "neutral" )
708  {
709  thread ‪give_capture_credit( touchList, string, oldTeam, isBFlag, true );
710  }
711  else
712  {
713  thread ‪give_neutralized_credit( touchList, string, oldTeam, isBFlag );
714  }
715 
717  {
718  level thread ‪totalDomination( team );
719  }
720 }
721 
723 {
724  level notify( "flag_captured" );
725  team = player.pers["team"];
726  oldTeam = self ‪gameobjects::get_owner_team();
727  label = self ‪gameobjects::get_label();
728 
729  /#print( "flag captured: " + self.label );#/
730 
731  self ‪gameobjects::set_owner_team( team );
732  self.visuals[0] setModel( level.flagModel[team] );
733  SetDvar( "scr_obj" + self ‪gameobjects::get_label(), team );
734 
735  level.useStartSpawns = false;
736 
737  assert( team != "neutral" );
738 
739  isBFlag = false;
740  if( label == "_b" )
741  {
742  isBFlag = true;
743  }
744  string = ‪GetDomFlagUseString( label, false );
745  assert ( string != &"" );
746 
747  // Copy touch list so there aren't any threading issues
748  touchList = [];
749  touchKeys = GetArrayKeys( self.touchList[team] );
750  for ( i = 0 ; i < touchKeys.size ; i++ )
751  touchList[touchKeys[i]] = self.touchList[team][touchKeys[i]];
752 
753  thread ‪give_capture_credit( touchList, string, oldTeam, isBFlag, false );
754 
755  if ( oldTeam == "neutral" )
756  {
757  self ‪flagCapturedFromNeutral( team );
758  }
759  else
760  {
761  self ‪flagCapturedFromTeam( team, oldTeam );
762  }
763 
765  {
766  level thread ‪totalDomination( team );
767  }
768  self ‪update_spawn_influencers( team );
769 }
770 
771 function ‪onUse( player )
772 {
773  if( level.flagCanBeNeutralized )
774  {
775  self ‪onUseWithNeutralizingFlag( player );
776  }
777  else
778  {
779  self ‪onUseWithoutNeutralizingFlag( player );
780  }
781  level ‪change_dom_spawns();
782 }
783 
784 function ‪totalDomination( team )
785 {
786  level endon( "flag_captured" );
787  level endon( "game_ended" );
788 
789  wait ( 180 );
790 
792 }
793 
794 
796 {
797  level endon( "game_ended" );
798  level endon( "endWatchForBFlagCapAfterTime" );
799 
800  level thread ‪endWatchForBFlagCapAfterTime( 60 );
801  for (;;)
802  {
803  level waittill( "b_flag_captured", player );
805  }
806 }
807 
809 {
810  level endon( "game_ended" );
811  wait( 60 );
812  level notify( "endWatchForBFlagCapAfterTime" );
813 }
814 
815 function ‪give_capture_credit( touchList, string, lastOwnerTeam, isBFlag, neutralizing )
816 {
817  time = getTime();
818  wait .05;
820 
821  self ‪updateCapsPerMinute(lastOwnerTeam);
822 
823  players = getArrayKeys( touchList );
824  for ( i = 0; i < players.size; i++ )
825  {
826  player_from_touchlist = touchList[players[i]].player;
827  player_from_touchlist ‪updateCapsPerMinute(lastOwnerTeam);
828  if ( !‪isScoreBoosting( player_from_touchlist, self ) )
829  {
830  player_from_touchlist ‪challenges::capturedObjective( time, self.levelflag );
831  if (lastOwnerTeam == "neutral" && neutralizing && ‪IS_TRUE( self.hasBeenCaptured ) )
832  {
833  ‪scoreevents::processScoreEvent( "dom_point_secured_neutralizing", player_from_touchlist );
834  }
835  else if ( lastOwnerTeam == "neutral" )
836  {
837  if ( isBFlag )
838  {
839  ‪scoreevents::processScoreEvent( "dom_point_neutral_b_secured", player_from_touchlist );
840  }
841  else
842  {
843  ‪scoreevents::processScoreEvent( "dom_point_neutral_secured", player_from_touchlist );
844  }
845  }
846  else
847  {
848  ‪scoreevents::processScoreEvent( "dom_point_secured", player_from_touchlist );
849  }
850 
851  self.hasBeenCaptured = true;
852 
853  player_from_touchlist RecordGameEvent("capture");
854  if ( isBFlag )
855  {
856  level notify( "b_flag_captured", player_from_touchlist );
857  }
858  if( isdefined(player_from_touchlist.pers["captures"]) )
859  {
860  player_from_touchlist.pers["captures"]++;
861  player_from_touchlist.captures = player_from_touchlist.pers["captures"];
862  }
863  ‪demo::bookmark( "event", gettime(), player_from_touchlist );
864  player_from_touchlist AddPlayerStatWithGameType( "CAPTURES", 1 );
865  }
866  else
867  {
868  }
869 
870  level thread ‪popups::DisplayTeamMessageToAll( string, player_from_touchlist );
871  }
872 }
873 
874 function ‪give_neutralized_credit( touchList, string, lastOwnerTeam, isBFlag )
875 {
876  time = getTime();
877  wait .05;
879 
880  players = getArrayKeys( touchList );
881  for ( i = 0; i < players.size; i++ )
882  {
883  player_from_touchlist = touchList[players[i]].player;
884  player_from_touchlist ‪updateCapsPerMinute(lastOwnerTeam);
885  if ( !‪isScoreBoosting( player_from_touchlist, self ) )
886  {
887  ‪scoreevents::processScoreEvent( "dom_point_neutralized_neutralizing", player_from_touchlist );
888 
889  player_from_touchlist RecordGameEvent("neutralized");
890  if( isdefined(player_from_touchlist.pers["neutralizes"]) )
891  {
892  player_from_touchlist.pers["neutralizes"]++;
893  player_from_touchlist.captures = player_from_touchlist.pers["neutralizes"];
894  }
895  ‪demo::bookmark( "event", gettime(), player_from_touchlist );
896  }
897  else
898  {
899  }
900 
901  level thread ‪popups::DisplayTeamMessageToAll( string, player_from_touchlist );
902  }
903 }
904 
906 {
907  if ( level.roundScoreLimit && !level.timeLimit )
908  {
909  // Average time: 30 seconds, 6 intervals with 2 flags is 12 points
910  warningScore = Max( 0, level.roundScoreLimit - 12 );
911  }
912  else
913  {
914  warningScore = 0;
915  }
916 
917  playedNearEndVo = false;
918 
919  alliesRoundStartScore = [[level._getTeamScore]]( "allies" );
920  axisRoundStartScore = [[level._getTeamScore]]( "axis" );
921 
922  while ( !level.gameEnded )
923  {
924  numOwnedFlags = 0;
925 
926  scoring_teams = [];
927 
928  round_score_limit = ‪util::get_current_round_score_limit();
929  totalFlags = ‪getTeamFlagCount( "allies" ) + ‪getTeamFlagCount( "axis" );
930  if( ( totalFlags == 3 ) && ( game["teamScores"]["allies"] == round_score_limit - 1 ) && ( game["teamScores"]["axis"] == round_score_limit - 1 ) )
931  level.clampScoreLimit = false; // clear the clamp so we dont end up tie in the situation wehre the score is 199 vs 199 and one team has 2 flags and the other one has 1
932 
933  numFlags = ‪getTeamFlagCount( "allies" );
934  numOwnedFlags += numFlags;
935  if ( numFlags )
936  {
937  scoring_teams[scoring_teams.size] = "allies";
939  }
940 
941  numFlags = ‪getTeamFlagCount( "axis" );
942  numOwnedFlags += numFlags;
943  if ( numFlags )
944  {
945  scoring_teams[scoring_teams.size] = "axis";
947  }
948 
949  if ( numOwnedFlags )
951 
952  if ( warningScore && !playedNearEndVo )
953  {
954  winningTeam = undefined;
955 
956  alliesRoundScore = [[level._getTeamScore]]( "allies" ) - alliesRoundStartScore;
957  axisRoundScore = [[level._getTeamScore]]( "axis" ) - axisRoundStartScore;
958 
959  if ( alliesRoundScore >= warningScore )
960  {
961  winningTeam = "allies";
962  }
963  else if ( axisRoundScore >= warningScore )
964  {
965  winningTeam = "axis";
966  }
967 
968  if ( isdefined( winningTeam ) )
969  {
970  nearWinning = "nearWinning";
971  nearLosing = "nearLosing";
972 
974  {
975  nearWinning = "nearWinningFinal";
976  nearLosing = "nearLosingFinal";
977  }
978  else
979  {
980  if ( RandomInt( 4 ) < 3 ) // 1 in winning, 3 in winningFinal
981  {
982  nearWinning = "nearWinningFinal";
983  }
984 
985  if ( RandomInt( 4 ) < 1 ) // 3 in losing, 1 in losingFinal
986  {
987  nearLosing = "nearLosingFinal";
988  }
989  }
990 
991  ‪globallogic_audio::leader_dialog( nearWinning, winningTeam );
992  ‪globallogic_audio::leader_dialog_for_other_teams( nearLosing, winningTeam );
993  playedNearEndVo = true;
994  }
995  }
996 
998 
999  // end the game if people aren't playing
1000  timePassed = ‪globallogic_utils::getTimePassed();
1001  if ( (((timePassed / 1000) > 120 && numOwnedFlags < 2) || ((timePassed / 1000) > 300 && numOwnedFlags < 3)) && ( GameModeIsMode( ‪GAMEMODE_PUBLIC_MATCH ) ) )
1002  {
1003  thread ‪globallogic::endGame( "tie", game["strings"]["time_limit_reached"] );
1004  return;
1005  }
1006 
1007  wait ( 5.0 );
1009  }
1010 }
1011 
1013 {
1014  axisScore = [[level._getTeamScore]]( "axis" );
1015  alliedScore = [[level._getTeamScore]]( "allies" );
1016  scoreLimit = level.scoreLimit;
1017  scoreThreshold = scoreLimit * .1;
1018  scoreDif = abs(axisScore - alliedScore);
1019  scoreThresholdStart = abs(scoreLimit - scoreThreshold);
1020  scoreLimitCheck = scoreLimit - 10;
1021 
1022  if( !isdefined( level.playingActionMusic ) )
1023  level.playingActionMusic = false;
1024 
1025  if( !isdefined( level.sndHalfway ) )
1026  level.sndHalfway = false;
1027 
1028  if (alliedScore > axisScore)
1029  {
1030  currentScore = alliedScore;
1031  }
1032  else
1033  {
1034  currentScore = axisScore;
1035  }
1036 
1037  halfwayScore = scoreLimit*.5;
1038  if( isdefined( level.roundScoreLimit ) )
1039  {
1040  halfwayScore = level.roundScoreLimit*.5;
1041  if( game[ "roundsplayed" ] == 1 )
1042  {
1043  halfwayScore += level.roundScoreLimit;
1044  }
1045  }
1046 
1047  if( ((axisScore >= halfwayScore) || (alliedScore >= halfwayScore)) && !level.sndHalfway )
1048  {
1049 
1050  level notify( "sndMusicHalfway" );
1051  level.sndHalfway = true;
1052  }
1053 
1054 }
1055 
1057 {
1058  if ( !isdefined( game["switchedsides"] ) )
1059  game["switchedsides"] = false;
1060 
1061  game["switchedsides"] = !game["switchedsides"];
1062 
1063  if ( level.scoreRoundWinBased )
1064  {
1065  [[level._setTeamScore]]( "allies", game["roundswon"]["allies"] );
1066  [[level._setTeamScore]]( "axis", game["roundswon"]["axis"] );
1067  }
1068 }
1069 
1070 function ‪onPlayerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
1071 {
1072  if ( isdefined( attacker ) && isplayer( attacker ) )
1073  {
1074  scoreEventProcessed = false;
1075  if ( attacker.touchTriggers.size && attacker.pers["team"] != self.pers["team"] )
1076  {
1077  triggerIds = getArrayKeys( attacker.touchTriggers );
1078  ownerTeam = attacker.touchTriggers[triggerIds[0]].useObj.ownerTeam;
1079  team = attacker.pers["team"];
1080  if ( team != ownerTeam )
1081  {
1082  ‪scoreevents::processScoreEvent( "kill_enemy_while_capping_dom", attacker, undefined, weapon );
1083  scoreEventProcessed = true;
1084  }
1085  }
1086 
1087  for ( index = 0; index < level.flags.size; index++ )
1088  {
1089  flagTeam = "invalidTeam";
1090  inFlagZone = false;
1091  defendedFlag = false;
1092  offendedFlag = false;
1093 
1094  flagOrigin = level.flags[index].origin;
1095 
1096  offenseRadiusSQ = 300 * 300;
1097  dist = Distance2dSquared(self.origin, flagOrigin);
1098  if ( dist < offenseRadiusSQ )
1099  {
1100  inFlagZone = true;
1101  if ( level.flags[index] ‪getFlagTeam() == attacker.pers["team"] || level.flags[index] ‪getFlagTeam() == "neutral" )
1102  defendedFlag = true;
1103  else
1104  offendedFlag = true;
1105  }
1106  dist = Distance2dSquared(attacker.origin, flagOrigin);
1107  if ( dist < offenseRadiusSQ )
1108  {
1109  inFlagZone = true;
1110  if ( level.flags[index] ‪getFlagTeam() == attacker.pers["team"] || level.flags[index] ‪getFlagTeam() == "neutral" )
1111  defendedFlag = true;
1112  else
1113  offendedFlag = true;
1114  }
1115 
1116  if ( inFlagZone && isPlayer( attacker ) && attacker.pers["team"] != self.pers["team"] )
1117  {
1118  if ( offendedFlag )
1119  {
1120  if ( !isdefined( attacker.dom_defends ) )
1121  attacker.dom_defends = 0;
1122 
1123  attacker.dom_defends++;
1124  if ( level.playerDefensiveMax >= attacker.dom_defends )
1125  {
1126  attacker thread ‪challenges::killedBaseDefender( level.flags[index] );
1127  if (!scoreeventprocessed)
1128  {
1129  ‪scoreevents::processScoreEvent( "killed_defender", attacker, undefined, weapon );
1130  }
1131  self RecordKillModifier("defending");
1132  break;
1133  }
1134  else
1135  {
1136  }
1137 
1138 
1139  }
1140  if ( defendedFlag )
1141  {
1142  if ( !isdefined( attacker.dom_offends ) )
1143  attacker.dom_offends = 0;
1144 
1145  attacker thread ‪updateattackermultikills();
1146 
1147  attacker.dom_offends++;
1148  if ( level.playerOffensiveMax >= attacker.dom_offends )
1149  {
1150  attacker.pers["defends"]++;
1151  attacker.defends = attacker.pers["defends"];
1152  attacker thread ‪challenges::killedBaseOffender( level.flags[index], weapon );
1153  attacker RecordGameEvent("return");
1154  attacker ‪challenges::killedZoneAttacker( weapon );
1155  if (!scoreeventprocessed)
1156  {
1157  ‪scoreevents::processScoreEvent( "killed_attacker", attacker, undefined, weapon );
1158  }
1159  self RecordKillModifier("assaulting");
1160  break;
1161  }
1162  else
1163  {
1164  }
1165  }
1166  }
1167  }
1168 
1169  if ( self.touchTriggers.size && attacker.pers["team"] != self.pers["team"] )
1170  {
1171  triggerIds = getArrayKeys( self.touchTriggers );
1172  ownerTeam = self.touchTriggers[triggerIds[0]].useObj.ownerTeam;
1173  team = self.pers["team"];
1174  if ( team != ownerTeam )
1175  {
1176  flag = self.touchTriggers[triggerIds[0]].useObj;
1177  if ( isdefined( flag.contested ) && flag.contested == true)
1178  {
1179  attacker ‪killWhileContesting( flag );
1180  }
1181  }
1182  }
1183  }
1184 }
1185 
1186 function ‪killWhileContesting( flag )
1187 {
1188  self notify( "killWhileContesting" );
1189  self endon( "killWhileContesting" );
1190  self endon( "disconnect" );
1191 
1192  killTime = getTime();
1193  playerteam = self.pers["team"];
1194  if ( !isdefined ( self.clearEnemyCount ) )
1195  {
1196  self.clearEnemyCount = 0;
1197  }
1198 
1199  self.clearEnemyCount++;
1200 
1201  flag waittill( "contest_over" );
1202 
1203 
1204  if (playerteam != self.pers["team"] || ( isdefined( self.spawntime ) && ( killTime < self.spawntime ) ) )
1205  {
1206  self.clearEnemyCount = 0;
1207  return;
1208  }
1209  if ( flag.ownerTeam != playerteam && flag.ownerTeam != "neutral" )
1210  {
1211  self.clearEnemyCount = 0;
1212  return;
1213  }
1214 
1215  if ( self.clearEnemyCount >= 2 && killTime + 200 > getTime() )
1216  {
1217  ‪scoreevents::processScoreEvent( "clear_2_attackers", self );
1218  }
1219  self.clearEnemyCount = 0;
1220 }
1221 
1222 
1224 {
1225  self endon ( "disconnect" );
1226  level endon ( "game_ended" );
1227 
1228  self notify ( "updateDomRecentKills" );
1229  self endon ( "updateDomRecentKills" );
1230  if ( !isdefined (self.recentDomAttackerKillCount) )
1231  {
1232  self.recentDomAttackerKillCount = 0;
1233  }
1234  self.recentDomAttackerKillCount++;
1235 
1236  wait ( 4.0 );
1237 
1238 
1239  if ( self.recentDomAttackerKillCount > 1 )
1240  self ‪challenges::domAttackerMultiKill( self.recentDomAttackerKillCount );
1241 
1242  self.recentDomAttackerKillCount = 0;
1243 }
1244 
1245 
1246 
1247 function ‪getTeamFlagCount( team )
1248 {
1249  score = 0;
1250  for (i = 0; i < level.flags.size; i++)
1251  {
1252  if ( level.domFlags[i] ‪gameobjects::get_owner_team() == team )
1253  score++;
1254  }
1255  return score;
1256 }
1257 
1258 function ‪getFlagTeam()
1259 {
1260  return self.useObj ‪gameobjects::get_owner_team();
1261 }
1262 
1264 {
1265  // get all flags which are adjacent to flags that aren't owned by the same team
1266  bflags = [];
1267  for (i = 0; i < level.flags.size; i++)
1268  {
1269  for (j = 0; j < level.flags[i].adjflags.size; j++)
1270  {
1271  if (level.flags[i].useObj ‪gameobjects::get_owner_team() != level.flags[i].adjflags[j].useObj ‪gameobjects::get_owner_team() )
1272  {
1273  bflags[bflags.size] = level.flags[i];
1274  break;
1275  }
1276  }
1277  }
1278 
1279  return bflags;
1280 }
1281 
1283 {
1284  spawns = [];
1285 
1286  bflags = ‪getBoundaryFlags();
1287  for (i = 0; i < bflags.size; i++)
1288  {
1289  if (isdefined(team) && bflags[i] ‪getFlagTeam() != team)
1290  continue;
1291 
1292  for (j = 0; j < bflags[i].nearbyspawns.size; j++)
1293  spawns[spawns.size] = bflags[i].nearbyspawns[j];
1294  }
1295 
1296  return spawns;
1297 }
1298 
1299 function ‪getSpawnsBoundingFlag( avoidflag )
1300 {
1301  spawns = [];
1302 
1303  for (i = 0; i < level.flags.size; i++)
1304  {
1305  flag = level.flags[i];
1306  if ( flag == avoidflag )
1307  continue;
1308 
1309  isbounding = false;
1310  for (j = 0; j < flag.adjflags.size; j++)
1311  {
1312  if ( flag.adjflags[j] == avoidflag )
1313  {
1314  isbounding = true;
1315  break;
1316  }
1317  }
1318 
1319  if ( !isbounding )
1320  continue;
1321 
1322  for (j = 0; j < flag.nearbyspawns.size; j++)
1323  spawns[spawns.size] = flag.nearbyspawns[j];
1324  }
1325 
1326  return spawns;
1327 }
1328 
1329 // gets an array of all spawnpoints which are near flags that are
1330 // owned by the given team, or that are adjacent to flags owned by the given team.
1332 {
1333  spawns = [];
1334 
1335  for (i = 0; i < level.flags.size; i++)
1336  {
1337  if ( level.flags[i] ‪getFlagTeam() == team )
1338  {
1339  // add spawns near this flag
1340  for (s = 0; s < level.flags[i].nearbyspawns.size; s++)
1341  spawns[spawns.size] = level.flags[i].nearbyspawns[s];
1342  }
1343  else
1344  {
1345  for (j = 0; j < level.flags[i].adjflags.size; j++)
1346  {
1347  if ( level.flags[i].adjflags[j] ‪getFlagTeam() == team )
1348  {
1349  // add spawns near this flag
1350  for (s = 0; s < level.flags[i].nearbyspawns.size; s++)
1351  spawns[spawns.size] = level.flags[i].nearbyspawns[s];
1352  break;
1353  }
1354  }
1355  }
1356  }
1357 
1358  return spawns;
1359 }
1360 
1361 // gets an array of all spawnpoints which are near flags that are
1362 // owned by the given team
1364 {
1365  spawns = [];
1366 
1367  for (i = 0; i < level.flags.size; i++)
1368  {
1369  if ( level.flags[i] ‪getFlagTeam() == team )
1370  {
1371  // add spawns near this flag
1372  for (s = 0; s < level.flags[i].nearbyspawns.size; s++)
1373  spawns[spawns.size] = level.flags[i].nearbyspawns[s];
1374  }
1375  }
1376 
1377  return spawns;
1378 }
1379 
1380 function ‪flagSetup()
1381 {
1382  maperrors = [];
1383  descriptorsByLinkname = [];
1384 
1385  // (find each flag_descriptor object)
1386  descriptors = getentarray("flag_descriptor", "targetname");
1387 
1388  flags = level.flags;
1389 
1390  for (i = 0; i < level.domFlags.size; i++)
1391  {
1392  closestdist = undefined;
1393  closestdesc = undefined;
1394  for (j = 0; j < descriptors.size; j++)
1395  {
1396  dist = distance(flags[i].origin, descriptors[j].origin);
1397  if (!isdefined(closestdist) || dist < closestdist) {
1398  closestdist = dist;
1399  closestdesc = descriptors[j];
1400  }
1401  }
1402 
1403  if (!isdefined(closestdesc)) {
1404  maperrors[maperrors.size] = "there is no flag_descriptor in the map! see explanation in dom.gsc";
1405  break;
1406  }
1407  if (isdefined(closestdesc.flag)) {
1408  maperrors[maperrors.size] = "flag_descriptor with script_linkname \"" + closestdesc.script_linkname + "\" is nearby more than one flag; is there a unique descriptor near each flag?";
1409  continue;
1410  }
1411  flags[i].descriptor = closestdesc;
1412  closestdesc.flag = flags[i];
1413  descriptorsByLinkname[closestdesc.script_linkname] = closestdesc;
1414  }
1415 
1416  if (maperrors.size == 0)
1417  {
1418  // find adjacent flags
1419  for (i = 0; i < flags.size; i++)
1420  {
1421  if (isdefined(flags[i].descriptor.script_linkto))
1422  adjdescs = strtok(flags[i].descriptor.script_linkto, " ");
1423  else
1424  adjdescs = [];
1425  for (j = 0; j < adjdescs.size; j++)
1426  {
1427  otherdesc = descriptorsByLinkname[adjdescs[j]];
1428  if (!isdefined(otherdesc) || otherdesc.targetname != "flag_descriptor") {
1429  maperrors[maperrors.size] = "flag_descriptor with script_linkname \"" + flags[i].descriptor.script_linkname + "\" linked to \"" + adjdescs[j] + "\" which does not exist as a script_linkname of any other entity with a targetname of flag_descriptor (or, if it does, that flag_descriptor has not been assigned to a flag)";
1430  continue;
1431  }
1432  adjflag = otherdesc.flag;
1433  if (adjflag == flags[i]) {
1434  maperrors[maperrors.size] = "flag_descriptor with script_linkname \"" + flags[i].descriptor.script_linkname + "\" linked to itself";
1435  continue;
1436  }
1437  flags[i].adjflags[flags[i].adjflags.size] = adjflag;
1438  }
1439  }
1440  }
1441 
1442  // assign each spawnpoint to nearest flag
1443  spawnpoints = ‪spawnlogic::get_spawnpoint_array( "mp_dom_spawn" );
1444  for (i = 0; i < spawnpoints.size; i++)
1445  {
1446  if (isdefined(spawnpoints[i].script_linkto)) {
1447  desc = descriptorsByLinkname[spawnpoints[i].script_linkto];
1448  if (!isdefined(desc) || desc.targetname != "flag_descriptor") {
1449  maperrors[maperrors.size] = "Spawnpoint at " + spawnpoints[i].origin + "\" linked to \"" + spawnpoints[i].script_linkto + "\" which does not exist as a script_linkname of any entity with a targetname of flag_descriptor (or, if it does, that flag_descriptor has not been assigned to a flag)";
1450  continue;
1451  }
1452  nearestflag = desc.flag;
1453  }
1454  else {
1455  nearestflag = undefined;
1456  nearestdist = undefined;
1457  for (j = 0; j < flags.size; j++)
1458  {
1459  dist = distancesquared(flags[j].origin, spawnpoints[i].origin);
1460  if (!isdefined(nearestflag) || dist < nearestdist)
1461  {
1462  nearestflag = flags[j];
1463  nearestdist = dist;
1464  }
1465  }
1466  }
1467  nearestflag.nearbyspawns[nearestflag.nearbyspawns.size] = spawnpoints[i];
1468  }
1469 
1470  if (maperrors.size > 0)
1471  {
1472  /#
1473  println("^1------------ Map Errors ------------");
1474  for(i = 0; i < maperrors.size; i++)
1475  println(maperrors[i]);
1476  println("^1------------------------------------");
1477  println("Map errors. See above");
1478  #/
1480 
1481  return;
1482  }
1483 }
1484 
1486 {
1487  ss = level.spawnsystem;
1488 
1489  for (flag_index = 0; flag_index < level.flags.size; flag_index++)
1490  {
1491  if ( level.domFlags[flag_index] == self )
1492  break;
1493  }
1494 
1495  // domination: owned flag influencers
1496  self.owned_flag_influencer = self ‪spawning::create_influencer( "dom_friendly", self.trigger.origin, 0 );
1497 
1498  // domination: un-owned inner flag influencers
1499  self.neutral_flag_influencer = self ‪spawning::create_influencer( "dom_neutral", self.trigger.origin, 0 );
1500 
1501  // domination: enemy flag influencers
1502  self.enemy_flag_influencer = self ‪spawning::create_influencer( "dom_enemy", self.trigger.origin, 0 );
1503 
1504  // default it to neutral
1505  self ‪update_spawn_influencers("neutral");
1506 }
1507 
1509 {
1510  assert(isdefined(self.neutral_flag_influencer));
1511  assert(isdefined(self.owned_flag_influencer));
1512  assert(isdefined(self.enemy_flag_influencer));
1513 
1514  if ( team == "neutral" )
1515  {
1516  EnableInfluencer(self.neutral_flag_influencer, true);
1517  EnableInfluencer(self.owned_flag_influencer, false);
1518  EnableInfluencer(self.enemy_flag_influencer, false);
1519  }
1520  else
1521  {
1522  EnableInfluencer(self.neutral_flag_influencer, false);
1523  EnableInfluencer(self.owned_flag_influencer, true);
1524  EnableInfluencer(self.enemy_flag_influencer, true);
1525 
1526  SetInfluencerTeammask(self.owned_flag_influencer, ‪util::getTeamMask(team) );
1527  SetInfluencerTeammask(self.enemy_flag_influencer, ‪util::getOtherTeamsMask(team) );
1528  }
1529 }
1530 
1531 function ‪addSpawnPointsForFlag( team, flag_team, flagSpawnName )
1532 {
1533  // flag_team is the team that owns the flag
1534  // team is the team we are looking to add spawns for
1535  // we should add spawns for team only if the flag isn't owned by the enemy team (it may be neutral or owned by us)
1536 
1537  if ( game["switchedsides"] )
1538  team = ‪util::getOtherTeam( team );
1539 
1540  otherTeam = ‪util::getOtherTeam( team );
1541 
1542  if ( flag_team != otherTeam )
1543  {
1544  ‪spawnlogic::add_spawn_points( team, flagSpawnName );
1545  }
1546 }
1547 
1548 //Changes what spawns are available to a team based on what Domination point they own
1550 {
1551 
1553  ‪spawnlogic::add_spawn_points( "allies", "mp_dom_spawn" );
1554  ‪spawnlogic::add_spawn_points( "axis", "mp_dom_spawn" );
1555 
1556  //If one team owns all flags, we want to allow both teams to spawn anywhere
1557  flag_number = level.flags.size;
1558  if( ‪dominated_check() )
1559  {
1560  for ( i = 0 ; i < flag_number ; i++ )
1561  {
1562  label = level.flags[i].useobj ‪gameobjects::get_label();
1563  flagSpawnName = "mp_dom_spawn_flag" + label;
1564  ‪spawnlogic::add_spawn_points( "allies", flagSpawnName );
1565  ‪spawnlogic::add_spawn_points( "axis", flagSpawnName );
1566  }
1567  }
1568  else
1569  {
1570  for ( i = 0; i < flag_number; i++ )
1571  {
1572  //'getlabel' gives us the appropriate "_a" or "_b"
1573  label = level.flags[i].useobj ‪gameobjects::get_label();
1574  flagSpawnName = "mp_dom_spawn_flag" + label;
1575  flag_team = level.flags[i] ‪getFlagTeam();
1576 
1577  ‪addSpawnPointsForFlag( "allies", flag_team, flagSpawnName );
1578  ‪addSpawnPointsForFlag( "axis", flag_team, flagSpawnName );
1579  }
1580  }
1581 
1583 
1584 }
1585 
1587 {
1588  num_flags = level.flags.size;
1589  allied_flags = 0;
1590  axis_flags = 0;
1591 
1592  for ( i = 0 ; i < num_flags ; i++ )
1593  {
1594  flag_team = level.flags[i] ‪getFlagTeam();
1595 
1596  if ( flag_team == "allies" )
1597  {
1598  allied_flags++;
1599  }
1600  else if ( flag_team == "axis" )
1601  {
1602  axis_flags++;
1603  }
1604  else
1605  {
1606  return false;
1607  }
1608 
1609  if ( ( allied_flags > 0 ) && ( axis_flags > 0 ) )
1610  return false;
1611  }
1612 
1613  return true;
1614 }
1615 //This function checks to see if one team owns all three flags
1617 {
1618  num_flags = level.flags.size;
1619  allied_flags = 0;
1620  axis_flags = 0;
1621 
1622  for ( i = 0 ; i < num_flags ; i++ )
1623  {
1624  flag_team = level.flags[i] ‪getFlagTeam();
1625 
1626  if ( flag_team == "allies" )
1627  {
1628  allied_flags++;
1629  }
1630  else if ( flag_team == "axis" )
1631  {
1632  axis_flags++;
1633  }
1634 
1635  if ( ( allied_flags > 0 ) && ( axis_flags > 0 ) )
1636  return false;
1637  }
1638 
1639  return true;
1640 }
1641 
1642 function ‪updateCapsPerMinute(lastOwnerTeam)
1643 {
1644  if ( !isdefined( self.capsPerMinute ) )
1645  {
1646  self.numCaps = 0;
1647  self.capsPerMinute = 0;
1648  }
1649 
1650  // not including neutral flags as part of the boosting prevention
1651  // to help with false positives at the start
1652  if ( lastOwnerTeam == "neutral" )
1653  return;
1654 
1655  self.numCaps++;
1656 
1657  minutesPassed = ‪globallogic_utils::getTimePassed() / ( 60 * 1000 );
1658 
1659  // players use the actual time played
1660  if ( IsPlayer( self ) && isdefined(self.timePlayed["total"]) )
1661  minutesPassed = self.timePlayed["total"] / 60;
1662 
1663  self.capsPerMinute = self.numCaps / minutesPassed;
1664  if ( self.capsPerMinute > self.numCaps )
1665  self.capsPerMinute = self.numCaps;
1666 }
1667 
1668 function ‪isScoreBoosting( player, flag )
1669 {
1670  if ( !level.rankedMatch )
1671  return false;
1672 
1673  if ( player.capsPerMinute > level.playerCaptureLPM )
1674  return true;
1675 
1676  if ( flag.capsPerMinute > level.flagCaptureLPM )
1677  return true;
1678 
1679  return false;
1680 }
1681 
1682 
1684 {
1685  if ( !isdefined( self.contested ) )
1686  {
1687  self.contested = false;
1688  }
1689 
1690  numOther = ‪gameobjects::get_num_touching_except_team( self.ownerTeam );
1691  numOwners = self.numTouching[self.claimTeam];
1692 
1693  previousState = self.contested;
1694  if ( numOther > 0 && numOwners > 0 )
1695  {
1696  self.contested = true;
1697  }
1698  else
1699  {
1700  if ( previousState == true )
1701  {
1702  self notify( "contest_over" );
1703  }
1704  self.contested = false;
1705  }
1706 }
‪endGame
‪function endGame(winner, endReasonText)
Definition: _globallogic.gsc:1950
‪create_use_object
‪function create_use_object(ownerTeam, trigger, visuals, offset, objectiveName, allowInitialHoldDelay=false, allowWeaponCyclingDuringHold=false)
Definition: gameobjects_shared.gsc:1491
‪waitTillHostMigrationDone
‪function waitTillHostMigrationDone()
Definition: hostmigration_shared.gsc:193
‪statusDialog
‪function statusDialog(dialog, team, objectiveKey)
Definition: dom.gsc:494
‪processScoreEvent
‪function processScoreEvent(event, player, victim, weapon)
Definition: scoreevents_shared.gsc:19
‪setObjectiveText
‪function setObjectiveText(team, text)
Definition: _util.gsc:585
‪onPlayerKilled
‪function onPlayerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
Definition: dom.gsc:1070
‪endWatchForBFlagCapAfterTime
‪function endWatchForBFlagCapAfterTime(time)
Definition: dom.gsc:808
‪onRoundEndGame
‪function onRoundEndGame(roundWinner)
Definition: dom.gsc:290
‪give_neutralized_credit
‪function give_neutralized_credit(touchList, string, lastOwnerTeam, isBFlag)
Definition: dom.gsc:874
‪onUseWithNeutralizingFlag
‪function onUseWithNeutralizingFlag(player)
Definition: dom.gsc:657
‪leader_dialog_for_other_teams
‪function leader_dialog_for_other_teams(dialogKey, skipTeam, objectiveKey, killstreakId, dialogBufferKey)
Definition: _globallogic_audio.gsc:422
‪giveTeamScoreForObjective_DelayPostProcessing
‪function giveTeamScoreForObjective_DelayPostProcessing(team, score)
Definition: _globallogic_score.gsc:747
‪allow_use
‪function allow_use(relativeTeam)
Definition: gameobjects_shared.gsc:3485
‪getOwnedFlagSpawns
‪function getOwnedFlagSpawns(team)
Definition: dom.gsc:1363
‪setvisiblescoreboardcolumns
‪function setvisiblescoreboardcolumns(col1, col2, col3, col4, col5)
Definition: _globallogic.gsc:545
‪getSpawnsBoundingFlag
‪function getSpawnsBoundingFlag(avoidflag)
Definition: dom.gsc:1299
‪set_owner_team
‪function set_owner_team(team)
Definition: gameobjects_shared.gsc:3437
‪killedBaseDefender
‪function killedBaseDefender(objective)
Definition: _challenges.gsc:1647
‪getTeamMask
‪function getTeamMask(team)
Definition: _util.gsc:373
‪isOneRound
‪function isOneRound()
Definition: util_shared.gsc:3497
‪updateAllSpawnPoints
‪function updateAllSpawnPoints()
Definition: _spawning.gsc:551
‪onScoreCloseMusic
‪function onScoreCloseMusic()
Definition: dom.gsc:1012
‪DIALOG_THROTTLE
‪#define DIALOG_THROTTLE
Definition: dom.gsc:121
‪registerRoundWinLimit
‪function registerRoundWinLimit(minValue, maxValue)
Definition: _util.gsc:630
‪onUseWithoutNeutralizingFlag
‪function onUseWithoutNeutralizingFlag(player)
Definition: dom.gsc:722
‪get_label
‪function get_label()
Definition: gameobjects_shared.gsc:4207
‪set_use_time
‪function set_use_time(time)
Definition: gameobjects_shared.gsc:3455
‪onUseUpdate
‪function onUseUpdate(team, progress, change)
Definition: dom.gsc:466
‪register_allowed_gameobject
‪function register_allowed_gameobject(gameobject)
Definition: gameobjects_shared.gsc:67
‪killedBaseOffender
‪function killedBaseOffender(objective, weapon)
Definition: _challenges.gsc:1566
‪killWhileContesting
‪function killWhileContesting(flag)
Definition: dom.gsc:1186
‪dominated_challenge_check
‪function dominated_challenge_check()
Definition: dom.gsc:1586
‪flagSetup
‪function flagSetup()
Definition: dom.gsc:1380
‪find_box_center
‪function find_box_center(mins, maxs)
Definition: math_shared.gsc:86
‪resetTeamScores
‪function resetTeamScores()
Definition: _globallogic_score.gsc:808
‪getBoundaryFlags
‪function getBoundaryFlags()
Definition: dom.gsc:1263
‪get_current_round_score_limit
‪function get_current_round_score_limit()
Definition: util_shared.gsc:3675
‪updateattackermultikills
‪function updateattackermultikills()
Definition: dom.gsc:1223
‪GAMEMODE_PUBLIC_MATCH
‪#define GAMEMODE_PUBLIC_MATCH
Definition: shared.gsh:10
‪isLastRound
‪function isLastRound()
Definition: util_shared.gsc:3513
‪update_spawn_influencers
‪function update_spawn_influencers(team)
Definition: dom.gsc:1508
‪play_on_players
‪function play_on_players(sound, team)
Definition: sound_shared.gsc:257
‪trace
‪function trace(from, to, target)
Definition: grapple.gsc:369
‪registerFriendlyFireDelay
‪function registerFriendlyFireDelay(dvarString, defaultValue, minValue, maxValue)
Definition: _globallogic.gsc:3917
‪updateCapsPerMinute
‪function updateCapsPerMinute(lastOwnerTeam)
Definition: dom.gsc:1642
‪onRoundSwitch
‪function onRoundSwitch()
Definition: dom.gsc:1056
‪create_influencer
‪function create_influencer(name, origin, team_mask)
Definition: _spawning.gsc:267
‪updateDomScores
‪function updateDomScores()
Definition: dom.gsc:905
‪flagCapturedFromTeam
‪function flagCapturedFromTeam(team, oldTeam)
Definition: dom.gsc:555
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪capturedObjective
‪function capturedObjective(captureTime, objective)
Definition: challenges_shared.gsc:882
‪registerNumLives
‪function registerNumLives(minValue, maxValue, teamLivesMinValue, teamLivesMaxValue)
Definition: _util.gsc:664
‪registerScoreLimit
‪function registerScoreLimit(minValue, maxValue)
Definition: _util.gsc:638
‪capturedBFirstMinute
‪function capturedBFirstMinute()
Definition: challenges_shared.gsc:1259
‪add_spawn_points
‪function add_spawn_points(team, spawnPointName)
Definition: _spawnlogic.gsc:20
‪set_objective_entity
‪function set_objective_entity(entity)
Definition: gameobjects_shared.gsc:3637
‪create_map_placed_influencers
‪function create_map_placed_influencers()
Definition: _spawning.gsc:522
‪onUse
‪function onUse(player)
Definition: dom.gsc:771
‪getOtherTeam
‪function getOtherTeam(team)
Definition: _util.gsc:360
‪killedZoneAttacker
‪function killedZoneAttacker(weapon)
Definition: challenges_shared.gsc:1274
‪change_dom_spawns
‪function change_dom_spawns()
Definition: dom.gsc:1549
‪addSpawnPointsForFlag
‪function addSpawnPointsForFlag(team, flag_team, flagSpawnName)
Definition: dom.gsc:1531
‪holdFlagEntireMatch
‪function holdFlagEntireMatch(team, label)
Definition: challenges_shared.gsc:1239
‪onPrecacheGameType
‪function onPrecacheGameType()
Definition: dom.gsc:192
‪get_num_touching_except_team
‪function get_num_touching_except_team(ignoreTeam)
Definition: gameobjects_shared.gsc:2571
‪get_owner_team
‪function get_owner_team()
Definition: gameobjects_shared.gsc:3445
‪onEndUse
‪function onEndUse(team, player, success)
Definition: dom.gsc:524
‪createFlagSpawnInfluencers
‪function createFlagSpawnInfluencers()
Definition: dom.gsc:1485
‪getTimePassed
‪function getTimePassed()
Definition: _globallogic_utils.gsc:274
‪postProcessTeamScores
‪function postProcessTeamScores(teams)
Definition: _globallogic_score.gsc:762
‪printAndSoundOnEveryone
‪function printAndSoundOnEveryone(team, enemyteam, printFriendly, printEnemy, soundFriendly, soundEnemy, printarg)
Definition: _util.gsc:252
‪set_visible_team
‪function set_visible_team(relativeTeam)
Definition: gameobjects_shared.gsc:3491
‪set_leader_gametype_dialog
‪function set_leader_gametype_dialog(startGameDialogKey, startHcGameDialogKey, offenseOrderDialogKey, defenseOrderDialogKey)
Definition: _globallogic_audio.gsc:92
‪isScoreBoosting
‪function isScoreBoosting(player, flag)
Definition: dom.gsc:1668
‪onBeginUse
‪function onBeginUse(player)
Definition: dom.gsc:449
‪place_spawn_points
‪function place_spawn_points(spawnPointName)
Definition: _spawnlogic.gsc:22
‪get_spawnpoint_array
‪function get_spawnpoint_array(classname)
Definition: _spawnlogic.gsc:27
‪DisplayTeamMessageToAll
‪function DisplayTeamMessageToAll(message, player)
Definition: popups_shared.gsc:122
‪onStartGameType
‪function onStartGameType()
Definition: dom.gsc:197
‪onEndGame
‪function onEndGame(winningTeam)
Definition: dom.gsc:275
‪setObjectiveHintText
‪function setObjectiveHintText(team, text)
Definition: _util.gsc:595
‪flushObjectiveFlagDialog
‪function flushObjectiveFlagDialog()
Definition: dom.gsc:487
‪domAttackerMultiKill
‪function domAttackerMultiKill(killCount)
Definition: challenges_shared.gsc:1228
‪flagNeutralized
‪function flagNeutralized(team, oldTeam)
Definition: dom.gsc:585
‪clear_spawn_points
‪function clear_spawn_points()
Definition: _spawnlogic.gsc:19
‪bookmark
‪function bookmark(type, time, mainClientEnt, otherClientEnt, eventPriority, inflictorEnt, overrideEntityCamera, actorEnt)
Definition: demo_shared.gsc:25
‪flagCapturedFromNeutral
‪function flagCapturedFromNeutral(team)
Definition: dom.gsc:532
‪abort_level
‪function abort_level()
Definition: callbacks_shared.gsc:1018
‪give_capture_credit
‪function give_capture_credit(touchList, string, lastOwnerTeam, isBFlag, neutralizing)
Definition: dom.gsc:815
‪flush_objective_dialog
‪function flush_objective_dialog(objectiveKey)
Definition: _globallogic_audio.gsc:225
‪getTeamFlagCount
‪function getTeamFlagCount(team)
Definition: dom.gsc:1247
‪onUpdateUseRate
‪function onUpdateUseRate()
Definition: dom.gsc:1683
‪registerRoundSwitch
‪function registerRoundSwitch(minValue, maxValue)
Definition: _util.gsc:615
‪totalDomination
‪function totalDomination(team)
Definition: dom.gsc:784
‪registerRoundLimit
‪function registerRoundLimit(minValue, maxValue)
Definition: _util.gsc:622
‪init
‪function init()
Definition: struct.csc:1
‪getOtherTeamsMask
‪function getOtherTeamsMask(skip_team)
Definition: _util.gsc:382
‪main
‪function main()
Definition: dom.gsc:123
‪setObjectiveScoreText
‪function setObjectiveScoreText(team, text)
Definition: _util.gsc:590
‪leader_dialog
‪function leader_dialog(dialogKey, team, excludeList, objectiveKey, killstreakId, dialogBufferKey)
Definition: _globallogic_audio.gsc:435
‪domFlags
‪function domFlags()
Definition: dom.gsc:313
‪GetDomFlagUseString
‪function GetDomFlagUseString(label, neutralized)
Definition: dom.gsc:604
‪change
‪function change(team)
Definition: _teams.gsc:258
‪watchForBFlagCap
‪function watchForBFlagCap()
Definition: dom.gsc:795
‪set_use_text
‪function set_use_text(text)
Definition: gameobjects_shared.gsc:3460
‪WaitTillSlowProcessAllowed
‪function WaitTillSlowProcessAllowed()
Definition: util_shared.gsc:2536
‪registerTimeLimit
‪function registerTimeLimit(minValue, maxValue)
Definition: _util.gsc:655
‪name
‪class GroundFx name
‪get_random_intermission_point
‪function get_random_intermission_point()
Definition: _spawnlogic.gsc:54
‪getUnownedFlagNearestStart
‪function getUnownedFlagNearestStart(team, excludeFlag)
Definition: dom.gsc:428
‪updateGametypeDvars
‪function updateGametypeDvars()
Definition: dom.gsc:303
‪getBoundaryFlagSpawns
‪function getBoundaryFlagSpawns(team)
Definition: dom.gsc:1282
‪dominated_check
‪function dominated_check()
Definition: dom.gsc:1616
‪play_2d_on_team
‪function play_2d_on_team(alias, team)
Definition: _globallogic_audio.gsc:845
‪getOwnedAndBoundingFlagSpawns
‪function getOwnedAndBoundingFlagSpawns(team)
Definition: dom.gsc:1331
‪getFlagTeam
‪function getFlagTeam()
Definition: dom.gsc:1258
‪registerRoundScoreLimit
‪function registerRoundScoreLimit(minValue, maxValue)
Definition: _util.gsc:647