‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
koth.gsc
Go to the documentation of this file.
1 #using scripts\shared\callbacks_shared;
2 #using scripts\shared\challenges_shared;
3 #using scripts\shared\clientfield_shared;
4 #using scripts\shared\demo_shared;
5 #using scripts\shared\gameobjects_shared;
6 #using scripts\shared\hostmigration_shared;
7 #using scripts\shared\hud_util_shared;
8 #using scripts\shared\math_shared;
9 #using scripts\shared\medals_shared;
10 #using scripts\shared\popups_shared;
11 #using scripts\shared\scoreevents_shared;
12 #using scripts\shared\sound_shared;
13 #using scripts\shared\util_shared;
14 
15 #insert scripts\shared\shared.gsh;
16 #insert scripts\shared\version.gsh;
17 
18 #using scripts\mp\gametypes\_battlechatter;
19 #using scripts\mp\gametypes\_globallogic;
20 #using scripts\mp\gametypes\_globallogic_audio;
21 #using scripts\mp\gametypes\_globallogic_score;
22 #using scripts\mp\gametypes\_globallogic_utils;
23 #using scripts\mp\gametypes\_hostmigration;
24 #using scripts\mp\gametypes\_spawning;
25 #using scripts\mp\gametypes\_spawnlogic;
26 
27 #using scripts\mp\_challenges;
28 #using scripts\mp\_util;
29 
30 #define RANDOM_ZONE_LOCATIONS_OFF 0
31 #define RANDOM_ZONE_LOCATIONS_ON 1
32 #define RANDOM_ZONE_LOCATIONS_AFTER_FIRST 2
33 
34 #define OBJECTIVE_FLAG_NORMAL 0
35 #define OBJECTIVE_FLAG_TARGET 1
36 
37 /*QUAKED mp_multi_team_spawn (1.0 0.0 0.0) (-16 -16 0) (16 16 72)
38 Spawns used for use in some multi team game modes to open up other portions of the map for multi team scenarios.*/
39 
40 #precache( "string", "OBJECTIVES_KOTH" );
41 #precache( "string", "OBJECTIVES_KOTH_SCORE" );
42 #precache( "string", "MP_WAITING_FOR_HQ" );
43 #precache( "string", "MP_KOTH_CAPTURED_BY" );
44 #precache( "string", "MP_KOTH_CAPTURED_BY_ENEMY" );
45 #precache( "string", "MP_KOTH_MOVING_IN" );
46 #precache( "string", "MP_CAPTURING_OBJECTIVE" );
47 #precache( "string", "MP_KOTH_CONTESTED_BY_ENEMY" );
48 #precache( "string", "MP_KOTH_AVAILABLE_IN" );
49 #precache( "string", "MP_CONTROL_KOTH" );
50 #precache( "string", "MP_CAPTURE_KOTH" );
51 #precache( "string", "MP_DEFEND_KOTH" );
52 #precache( "string", "MP_KOTH_AVAILABLE_IN" );
53 #precache( "string", "MP_HQ_DESPAWN_IN" );
54 #precache( "string", "MP_HQ_REINFORCEMENTS_IN" );
55 #precache( "string", "MP_CAPTURING_HQ" );
56 #precache( "string", "MP_DESTROYING_HQ" );
57 #precache( "fx", "ui/fx_koth_marker_blue" );
58 #precache( "fx", "ui/fx_koth_marker_orng" );
59 #precache( "fx", "ui/fx_koth_marker_neutral" );
60 #precache( "fx", "ui/fx_koth_marker_contested" );
61 #precache( "fx", "ui/fx_koth_marker_blue_window" );
62 #precache( "fx", "ui/fx_koth_marker_orng_window" );
63 #precache( "fx", "ui/fx_koth_marker_neutral_window" );
64 #precache( "fx", "ui/fx_koth_marker_contested_window" );
65 #precache( "objective", "hardpoint" );
66 
67 function ‪main()
68 {
70 
71  ‪util::registerTimeLimit( 0, 1440 );
72  ‪util::registerScoreLimit( 0, 1000 );
73  ‪util::registerNumLives( 0, 100 );
76 
77  ‪globallogic::registerFriendlyFireDelay( level.gameType, 15, 0, 1440 );
78 
79  level.teamBased = true;
80  level.doPrematch = true;
81  level.overrideTeamScore = true;
82  level.scoreRoundWinBased = true;
83  level.kothStartTime = 0;
84  level.onStartGameType =&‪onStartGameType;
85  level.playerSpawnedCB =&‪koth_playerSpawnedCB;
86  level.onRoundSwitch =&‪onRoundSwitch;
87  level.onPlayerKilled =&‪onPlayerKilled;
88  level.onEndGame=&‪onEndGame;
89 
90  ‪clientfield::register( "world", "hardpoint", ‪VERSION_SHIP, 5, "int" );
91  ‪clientfield::register( "world", "hardpointteam", ‪VERSION_SHIP, 5, "int" );
92 
93  level.zoneAutoMoveTime = GetGametypeSetting( "autoDestroyTime" );
94  level.zoneSpawnTime = GetGametypeSetting( "objectiveSpawnTime" );
95  level.kothMode = GetGametypeSetting( "kothMode" );
96  level.captureTime = GetGametypeSetting( "captureTime" );
97  level.destroyTime = GetGametypeSetting( "destroyTime" );
98  level.delayPlayer = GetGametypeSetting( "delayPlayer" );
99  level.randomZoneSpawn = GetGametypeSetting( "randomObjectiveLocations" );
100  level.scorePerPlayer = GetGametypeSetting( "scorePerPlayer" );
101  level.timePausesWhenInZone = GetGametypeSetting( "timePausesWhenInZone" );
102 
103  level.iconoffset = (0,0,32);
104 
105  level.onRespawnDelay =&‪getRespawnDelay;
106 
108 
109  ‪globallogic_audio::set_leader_gametype_dialog ( "startHardPoint", "hcStartHardPoint", "objCapture", "objCapture" );
110 
111  game["objective_gained_sound"] = "mpl_flagcapture_sting_friend";
112  game["objective_lost_sound"] = "mpl_flagcapture_sting_enemy";
113  game["objective_contested_sound"] = "mpl_flagreturn_sting";
114 
115  level.lastDialogTime = 0;
116  level.zoneSpawnQueue = [];
117 
118  // Sets the scoreboard columns and determines with data is sent across the network
119  if ( !SessionModeIsSystemlink() && !SessionModeIsOnlineGame() && IsSplitScreen() )
120  // local matches only show the first three columns
121  ‪globallogic::setvisiblescoreboardcolumns( "score", "kills", "objtime", "defends", "deaths" );
122  else
123  ‪globallogic::setvisiblescoreboardcolumns( "score", "kills", "deaths", "objtime", "defends" );
124 
125  /#
126  // HQ radio triggers are not scoped to exclude koth right now
127  // going to delete them just so if we render triggers we dont see all these
128  // TODO in the future is to get them into the automatic game type delete system
129  trigs = getentarray("radiotrigger", "targetname");
130  foreach( trig in trigs )
131  {
132  trig delete();
133  }
134  #/
135 }
136 
137 
138 function ‪updateObjectiveHintMessages( defenderTeam, defendMessage, attackMessage )
139 {
140  foreach( team in level.teams )
141  {
142  if ( defenderTeam == team )
143  {
144  game["strings"]["objective_hint_" + team] = defendMessage;
145  }
146  else
147  {
148  game["strings"]["objective_hint_" + team] = attackMessage;
149  }
150  }
151 }
152 
153 function ‪updateObjectiveHintMessage( message )
154 {
155  foreach( team in level.teams )
156  {
157  game["strings"]["objective_hint_" + team] = message;
158  }
159 }
160 
162 {
163  self.lowerMessageOverride = undefined;
164 
165  if ( !isdefined( level.zone.gameobject ) )
166  return undefined;
167 
168  zoneOwningTeam = level.zone.gameobject ‪gameobjects::get_owner_team();
169  if ( self.pers["team"] == zoneOwningTeam )
170  {
171  if ( !isdefined( level.zoneMoveTime ) )
172  return undefined;
173 
174  timeRemaining = (level.zoneMoveTime - gettime()) / 1000;
175 
176  if (!level.playerObjectiveHeldRespawnDelay )
177  return undefined;
178 
179  if ( level.playerObjectiveHeldRespawnDelay >= level.zoneAutoMoveTime )
180  self.lowerMessageOverride = &"MP_WAITING_FOR_HQ";
181 
182  if ( level.delayPlayer )
183  {
184  return min( level.spawnDelay, timeRemaining );
185  }
186  else
187  {
188  return ceil(timeRemaining);
189  }
190  }
191 }
192 
194 {
195  if ( !isdefined( game["switchedsides"] ) )
196  game["switchedsides"] = false;
197 
198  if ( game["switchedsides"] )
199  {
200  oldAttackers = game["attackers"];
201  oldDefenders = game["defenders"];
202  game["attackers"] = oldDefenders;
203  game["defenders"] = oldAttackers;
204  }
205 
206 
208 
209  foreach( team in level.teams )
210  {
211  ‪util::setObjectiveText( team, &"OBJECTIVES_KOTH" );
212 
213  if ( level.splitscreen )
214  {
215  ‪util::setObjectiveScoreText( team, &"OBJECTIVES_KOTH" );
216  }
217  else
218  {
219  ‪util::setObjectiveScoreText( team, &"OBJECTIVES_KOTH_SCORE" );
220  }
221  }
222 
223  level.kothTotalSecondsInZone = 0;
224 
225  level.objectiveHintPrepareZone = &"MP_CONTROL_KOTH";
226  level.objectiveHintCaptureZone = &"MP_CAPTURE_KOTH";
227  level.objectiveHintDefendHQ = &"MP_DEFEND_KOTH";
228 
229  if ( level.zoneSpawnTime )
230  ‪updateObjectiveHintMessage( level.objectiveHintPrepareZone );
231  else
232  ‪updateObjectiveHintMessage( level.objectiveHintCaptureZone );
233 
234  setClientNameMode("auto_change");
235 
236  // now that the game objects have been deleted place the influencers
238 
239  // TODO: HQ spawnpoints
240  level.spawnMins = ( 0, 0, 0 );
241  level.spawnMaxs = ( 0, 0, 0 );
242  foreach( team in level.teams )
243  {
244  ‪spawnlogic::add_spawn_points( team, "mp_tdm_spawn" );
245  ‪spawnlogic::add_spawn_points( team, "mp_multi_team_spawn" );
246 
248  }
249 
251 
252  level.spawn_start = [];
253 
254  foreach( team in level.teams )
255  {
256  level.spawn_start[ team ] = ‪spawnlogic::get_spawnpoint_array( ‪spawning::getTDMStartSpawnName(team) );
257  }
258 
259  level.mapCenter = ‪math::find_box_center( level.spawnMins, level.spawnMaxs );
260  setMapCenter( level.mapCenter );
261 
263  setDemoIntermissionPoint( spawnpoint.origin, spawnpoint.angles );
264 
265  level.spawn_all = ‪spawnlogic::get_spawnpoint_array( "mp_tdm_spawn" );
266  if ( !level.spawn_all.size )
267  {
268 /#
269  println("^1No mp_tdm_spawn spawnpoints in level!");
270 #/
272  return;
273  }
274 
275 
276  thread ‪SetupZones();
277 
279 
280  thread ‪KothMainLoop();
281 }
282 
283 function ‪pause_time()
284 {
285  if ( level.timePausesWhenInZone )
286  {
288  level.timerPaused = true;
289  }
290 }
291 
292 function ‪resume_time()
293 {
294  if ( level.timePausesWhenInZone )
295  {
296  ‪globallogic_utils::resumeTimerDiscardOverride( level.kothTotalSecondsInZone * 1000 );
297  level.timerPaused = false;
298  }
299 }
300 
302 {
303  level.playerCaptureLPM = GetGametypeSetting( "maxPlayerEventsPerMinute" );
304  level.timePausesWhenInZone = GetGametypeSetting( "timePausesWhenInZone" );
305 }
306 
308 {
309  // pick next Zone object
310  if ( level.randomZoneSpawn == ‪RANDOM_ZONE_LOCATIONS_ON )
311  {
312  level.zone = ‪GetNextZoneFromQueue();
313  }
314  else
315  {
316  level.zone = ‪GetFirstZone();
317  }
318 
319  if ( isdefined( level.zone ) )
320  {
321  /#print("zone spawned: ("+level.zone.trigOrigin[0]+","+level.zone.trigOrigin[1]+","+level.zone.trigOrigin[2]+")");#/
322 
323  level.zone ‪spawning::enable_influencers(true);
324  }
325 
326  level.zone.gameobject.trigger AllowTacticalInsertion( false );
327 
328  return;
329 }
330 
332 {
333  level.zone.gameobject.trigger AllowTacticalInsertion( true );
334 
335  // pick next Zone object
336  if ( level.randomZoneSpawn != ‪RANDOM_ZONE_LOCATIONS_OFF )
337  {
338  level.zone = ‪GetNextZoneFromQueue();
339  }
340  else
341  {
342  level.zone = ‪GetNextZone();
343  }
344 
345  if ( isdefined( level.zone ) )
346  {
347  /#print("zone spawned: ("+level.zone.trigOrigin[0]+","+level.zone.trigOrigin[1]+","+level.zone.trigOrigin[2]+")");#/
348 
349  level.zone ‪spawning::enable_influencers(true);
350  }
351 
352  level.zone.gameobject.trigger AllowTacticalInsertion( false );
353 
354  return;
355 }
356 
357 function ‪getNumTouching( )
358 {
359  numTouching = 0;
360  foreach( team in level.teams )
361  {
362  numTouching += self.numTouching[team];
363  }
364 
365  return numTouching;
366 }
367 
368 function ‪toggleZoneEffects( enabled )
369 {
370  index = 0;
371 
372  if ( enabled )
373  {
374  index = self.script_index;
375  }
376 
377  level ‪clientfield::set( "hardpoint", index );
378  level ‪clientfield::set( "hardpointteam", 0 );
379 }
380 
382 {
383  level endon("game_ended");
384  level endon("zone_moved");
385  level.kothStartTime = gettime();
386 
387  while( 1 )
388  {
389  level.zone.gameobject ‪gameobjects::allow_use( "any" );
390  level.zone.gameobject ‪gameobjects::set_use_time( level.captureTime );
391  level.zone.gameobject ‪gameobjects::set_use_text( &"MP_CAPTURING_OBJECTIVE" );
392 
393  numTouching = level.zone.gameobject ‪getNumTouching( );
394 
395  level.zone.gameobject ‪gameobjects::set_visible_team( "any" );
396  level.zone.gameobject ‪gameobjects::set_model_visibility( true );
397  level.zone.gameobject ‪gameobjects::must_maintain_claim( false );
398  level.zone.gameobject ‪gameobjects::can_contest_claim( true );
399 
400  level.zone.gameobject.onUse =&‪onZoneCapture;
401  level.zone.gameobject.onBeginUse =&‪onBeginUse;
402  level.zone.gameobject.onEndUse =&‪onEndUse;
403 
404  level.zone ‪toggleZoneEffects( true );
405 
406  msg = level ‪util::waittill_any_return( "zone_captured", "zone_destroyed", "game_ended", "zone_moved" );
407 
408  // this happens if it goes from contested to neutral
409  if ( msg == "zone_destroyed" )
410  continue;
411 
412  ownerTeam = level.zone.gameobject ‪gameobjects::get_owner_team();
413 
414  foreach( team in level.teams )
415  {
416  ‪updateObjectiveHintMessages( ownerTeam, level.objectiveHintDefendHQ, level.objectiveHintCaptureZone );
417  }
418 
419  level.zone.gameobject ‪gameobjects::allow_use( "none" );
420 
421  level.zone.gameobject.onUse = undefined;
422  level.zone.gameobject.onUnoccupied =&‪onZoneUnoccupied;
423  level.zone.gameobject.onContested =&‪onZoneContested;
424  level.zone.gameobject.onUncontested =&‪onZoneUncontested;
425 
426  level waittill( "zone_destroyed", destroy_team );
427 
428  if ( !level.kothMode || level.zoneDestroyedByTimer )
429  break;
430 
431  thread ‪forceSpawnTeam( ownerTeam );
432 
433  if ( isdefined( destroy_team ) )
434  {
435  level.zone.gameobject ‪gameobjects::set_owner_team( destroy_team );
436  }
437  else
438  {
439  level.zone.gameobject ‪gameobjects::set_owner_team( "none" );
440  }
441  }
442 }
443 
444 function ‪KothMainLoop()
445 {
446  level endon("game_ended");
447 
448  level.zoneRevealTime = -100000;
449 
450  zoneSpawningInStr = &"MP_KOTH_AVAILABLE_IN";
451  if ( level.kothMode )
452  {
453  zoneDestroyedInFriendlyStr = &"MP_HQ_DESPAWN_IN";
454  zoneDestroyedInEnemyStr = &"MP_KOTH_MOVING_IN";
455  }
456  else
457  {
458  zoneDestroyedInFriendlyStr = &"MP_HQ_REINFORCEMENTS_IN";
459  zoneDestroyedInEnemyStr = &"MP_HQ_DESPAWN_IN";
460  }
461 
463 
464  while ( level.inPrematchPeriod )
466 
467  ‪pause_time();
468 
469  wait 5;
470 
471  SetBombTimer( "A", 0 );
472  setMatchFlag( "bomb_timer_a", 0 );
473 
475 
476  while( 1 )
477  {
478  ‪resume_time();
479 
480  ‪sound::play_on_players( "mp_suitcase_pickup" );
481 
482  ‪globallogic_audio::leader_dialog( "kothLocated", undefined, undefined, "gamemode_objective", undefined, "kothActiveDialogBuffer" );
483 
484  level.zone.gameobject ‪gameobjects::set_model_visibility( true );
485 
486  level.zoneRevealTime = gettime();
487 
488  if ( level.zoneSpawnTime )
489  {
490  level.zone.gameobject ‪gameobjects::set_visible_team( "any" );
491  level.zone.gameobject ‪gameobjects::set_flags( ‪OBJECTIVE_FLAG_TARGET );
492 
493  ‪updateObjectiveHintMessage( level.objectiveHintPrepareZone );
494  setMatchFlag( "bomb_timer_a", 1 );
495  SetBombTimer( "A", int( gettime() + 1000 + level.zoneSpawnTime * 1000 ) );
496 
497  wait level.zoneSpawnTime;
498 
499  level.zone.gameobject ‪gameobjects::set_flags( ‪OBJECTIVE_FLAG_NORMAL );
500  ‪globallogic_audio::leader_dialog( "kothOnline", undefined, undefined, "gamemode_objective", undefined, "kothActiveDialogBuffer" );
501  }
502 
503  setMatchFlag( "bomb_timer_a", 0 );
504 
505  waittillframeend;
506 
507  ‪updateObjectiveHintMessage( level.objectiveHintCaptureZone );
508  ‪sound::play_on_players( "mpl_hq_cap_us" );
509 
510  level.zone.gameobject ‪gameobjects::enable_object();
511  // Attach the objective to the visuals since it is at the right position and we can't attch it to the koth_zone_center script_origin
512  Objective_OnEntity( level.zone.gameobject.objectiveID, level.zone.objectiveAnchor );
513 
514  level.zone.gameobject.captureCount = 0;
515 
516  if ( level.zoneAutoMoveTime )
517  {
518  thread ‪MoveZoneAfterTime( level.zoneAutoMoveTime );
519  setMatchFlag( "bomb_timer_a", 1 );
520  SetBombTimer( "A", int( gettime() + 1000 + level.zoneAutoMoveTime * 1000 ) );
521  }
522  else
523  {
524  level.zoneDestroyedByTimer = false;
525  }
526 
528 
529  ownerTeam = level.zone.gameobject ‪gameobjects::get_owner_team();
530 
531  if ( level.zone.gameobject.captureCount == 1 )
532  {
533  // Copy touch list so there aren't any threading issues
534  touchList = [];
535  touchKeys = GetArrayKeys( level.zone.gameobject.touchList[ownerTeam] );
536  for ( i = 0 ; i < touchKeys.size ; i++ )
537  touchList[touchKeys[i]] = level.zone.gameobject.touchList[ownerTeam][touchKeys[i]];
538  thread ‪give_held_credit( touchList );
539  }
540 
541  ‪pause_time();
542 
543  level.zone ‪spawning::enable_influencers(false);
544  level.zone.gameobject.lastCaptureTeam = undefined;
545  level.zone.gameobject ‪gameobjects::disable_object();
546  level.zone.gameobject ‪gameobjects::allow_use( "none" );
547  level.zone.gameobject ‪gameobjects::set_owner_team( "neutral" );
548  level.zone.gameobject ‪gameobjects::set_model_visibility( false );
549  level.zone.gameobject ‪gameobjects::must_maintain_claim( false );
550  level.zone ‪toggleZoneEffects( false );
551 
552  level notify("zone_reset");
553 
554  setMatchFlag( "bomb_timer_a", 0 );
556 
557  wait 0.5;
558 
559  thread ‪forceSpawnTeam( ownerTeam );
560 
561  wait 0.5;
562  }
563 }
564 
565 
567 {
568  level waittill("game_ended");
569  setMatchFlag( "bomb_timer_a", 0 );
570 }
571 
572 
573 function ‪forceSpawnTeam( team )
574 {
575  players = level.players;
576  for ( i = 0; i < players.size; i++ )
577  {
578  player = players[i];
579  if ( !isdefined( player ) )
580  continue;
581 
582  if ( player.pers["team"] == team )
583  {
584  player notify( "force_spawn" );
585  wait .1;
586  }
587  }
588 }
589 
591 {
592  ownerTeam = self ‪gameobjects::get_owner_team();
593 
594  if ( ‪IS_TRUE( self.isContested ) )
595  {
596  level ‪clientfield::set( "hardpointteam", 3 );
597  }
598  else if ( ownerTeam == "neutral" )
599  {
600  level ‪clientfield::set( "hardpointteam", 0 );
601  }
602  else
603  {
604  if ( ownerTeam == "allies" )
605  level ‪clientfield::set( "hardpointteam", 1 );
606  else
607  level ‪clientfield::set( "hardpointteam", 2 );
608  }
609 }
610 
611 function ‪onBeginUse( player )
612 {
613  ownerTeam = self ‪gameobjects::get_owner_team();
614 
615  if ( ownerTeam == "neutral" )
616  {
617  player thread ‪battlechatter::gametype_specific_battle_chatter( "hq_protect", player.pers["team"] );
618  }
619  else
620  {
621  player thread ‪battlechatter::gametype_specific_battle_chatter( "hq_attack", player.pers["team"] );
622  }
623 }
624 
625 
626 function ‪onEndUse( team, player, success )
627 {
628  player notify( "event_ended" );
629 }
630 
631 
632 function ‪onZoneCapture( player )
633 {
634  capture_team = player.pers["team"];
635  captureTime = getTime();
636 
637  /#print( "zone captured" );#/
638 
639  ‪pause_time();
640 
641  string = &"MP_KOTH_CAPTURED_BY";
642 
643  level.zone.gameobject.isContested = false;
644  level.useStartSpawns = false;
645 
646  if ( !isdefined( self.lastCaptureTeam ) || self.lastCaptureTeam != capture_team )
647  {
648  // Copy touch list so there aren't any threading issues
649  touchList = [];
650  touchKeys = GetArrayKeys( self.touchList[capture_team] );
651  for ( i = 0 ; i < touchKeys.size ; i++ )
652  touchList[touchKeys[i]] = self.touchList[capture_team][touchKeys[i]];
653  thread ‪give_capture_credit( touchList, string, captureTime, capture_team, self.lastCaptureTeam );
654  }
655 
656  level.kothCapTeam = capture_team;
657 
658  self ‪gameobjects::set_owner_team( capture_team );
659  if ( !level.kothMode )
660  self ‪gameobjects::set_use_time( level.destroyTime );
661 
662  foreach( team in level.teams )
663  {
664  if ( team == capture_team )
665  {
666  if ( !isdefined( self.lastCaptureTeam ) || ( self.lastCaptureTeam != team ) ) // If retaking this point after being contested, don't play VO again
667  {
668  ‪globallogic_audio::leader_dialog( "kothSecured", team, undefined, "gamemode_objective", undefined, "kothActiveDialogBuffer" );
669  for ( index = 0; index < level.players.size; index++ )
670  {
671  player = level.players[index];
672 
673  if ( player.pers["team"] == team )
674  {
675  if ( player.lastKilltime + 500 > getTime() )
676  {
678  }
679  }
680  }
681  }
682  thread ‪sound::play_on_players( game["objective_gained_sound"], team );
683  }
684  else
685  {
686  if ( !isdefined( self.lastCaptureTeam ) )
687  {
688  ‪globallogic_audio::leader_dialog( "kothCaptured", team, undefined, "gamemode_objective", undefined, "kothActiveDialogBuffer" );
689  }
690  else if ( self.lastCaptureTeam == team )
691  {
692  ‪globallogic_audio::leader_dialog( "kothLost", team, undefined, "gamemode_objective", undefined, "kothActiveDialogBuffer" );
693  }
694  thread ‪sound::play_on_players( game["objective_lost_sound"], team );
695  }
696  }
697 
698  self thread ‪awardCapturePoints( capture_team, self.lastCaptureTeam );
699  self.captureCount++;
700  self.lastCaptureTeam = capture_team;
701 
703 
705 
706  player RecordGameEvent( "hardpoint_captured" );
707 
708  level notify( "zone_captured" );
709  level notify( "zone_captured" + capture_team );
710  player notify( "event_ended" );
711 }
712 
714 {
715 }
716 
717 function ‪give_capture_credit( touchList, string, captureTime, capture_team, lastCaptureTeam )
718 {
719  wait .05;
721 
722  players = getArrayKeys( touchList );
723  for ( i = 0; i < players.size; i++ )
724  {
725  player = touchList[players[i]].player;
726 
727  player ‪updateCapsPerMinute( lastCaptureTeam );
728 
729  if ( !‪isScoreBoosting( player ) )
730  {
731  player ‪challenges::capturedObjective( captureTime, self.trigger );
732  if ( level.kothStartTime + 3000 > captureTime && level.kothCapTeam == capture_team )
733  {
734  ‪scoreevents::processScoreEvent( "quickly_secure_point", player );
735  }
736 
737  ‪scoreevents::processScoreEvent( "koth_secure", player );
738  player RecordGameEvent("capture");
739 
740  level thread ‪popups::DisplayTeamMessageToAll( string, player );
741 
742  if( isdefined(player.pers["captures"]) )
743  {
744  player.pers["captures"]++;
745  player.captures = player.pers["captures"];
746  }
747 
748  if ( level.kothStartTime + 500 > captureTime )
749  {
751  }
752 
753  ‪demo::bookmark( "event", gettime(), player );
754  player AddPlayerStatWithGameType( "CAPTURES", 1 );
755  }
756  else
757  {
758  }
759  }
760 }
761 
762 function ‪give_held_credit( touchList, team )
763 {
764  wait .05;
766 
767  players = getArrayKeys( touchList );
768  for ( i = 0; i < players.size; i++ )
769  {
770  player = touchList[players[i]].player;
771 
772  //scoreevents::processScoreEvent( "koth_held", player );
773 
774  // do not know if we want the following
775  //player RecordGameEvent("held");
776 
777  }
778 }
779 
780 function ‪onZoneDestroy( player )
781 {
782  destroyed_team = player.pers["team"];
783 
784  /#print( "zone destroyed" );#/
785  ‪scoreevents::processScoreEvent( "zone_destroyed", player );
786  player RecordGameEvent("destroy");
787  player AddPlayerStatWithGameType( "DESTRUCTIONS", 1 );
788 
789  if( isdefined(player.pers["destructions"]) )
790  {
791  player.pers["destructions"]++;
792  player.destructions = player.pers["destructions"];
793  }
794 
795  destroyTeamMessage = &"MP_HQ_DESTROYED_BY";
796  otherTeamMessage = &"MP_HQ_DESTROYED_BY_ENEMY";
797 
798  if ( level.kothMode )
799  {
800  destroyTeamMessage = &"MP_KOTH_CAPTURED_BY";
801  otherTeamMessage = &"MP_KOTH_CAPTURED_BY_ENEMY";
802  }
803 
804  level thread ‪popups::DisplayTeamMessageToAll( destroyTeamMessage, player );
805 
806  foreach( team in level.teams )
807  {
808  if ( team == destroyed_team )
809  {
810  ‪globallogic_audio::leader_dialog( "koth_secured", team, undefined, "gamemode_objective" );
811  }
812  else
813  {
814  ‪globallogic_audio::leader_dialog( "koth_destroyed", team, undefined, "gamemode_objective" );
815  }
816  }
817 
818  level notify( "zone_destroyed", destroyed_team );
819 
820  if ( level.kothMode )
821  level thread ‪awardCapturePoints( destroyed_team );
822 
823  player notify( "event_ended" );
824 }
825 
827 {
828  level notify( "zone_destroyed" );
829  level.kothCapTeam = "neutral";
830  level.zone.gameobject.wasLeftUnoccupied = true;
831  level.zone.gameobject.isContested = false;
832 
833  level.zone.gameobject RecordGameEventNonPlayer( "hardpoint_empty" );
834 
835  ‪resume_time();
836 
838 }
839 
841 {
842  zoneOwningTeam = self ‪gameobjects::get_owner_team();
843  self.wasContested = true;
844  self.isContested = true;
845 
847 
848  self RecordGameEventNonPlayer( "hardpoint_contested" );
849 
850  ‪resume_time();
851 
852  foreach( team in level.teams )
853  {
854  if ( team == zoneOwningTeam )
855  {
856  thread ‪sound::play_on_players( game["objective_contested_sound"], team );
857  ‪globallogic_audio::leader_dialog( "kothContested", team, undefined, "gamemode_objective", undefined, "kothActiveDialogBuffer" );
858  }
859  }
860 }
861 
862 function ‪onZoneUncontested( lastClaimTeam )
863 {
864  assert( lastClaimTeam == level.zone.gameobject ‪gameobjects::get_owner_team() );
865 
866  self.isContested = false;
867 
868  ‪pause_time();
869 
870  self ‪gameobjects::set_claim_team( lastClaimTeam );
871 
873 
874  self RecordGameEventNonPlayer( "hardpoint_uncontested" );
875 }
876 
877 function ‪MoveZoneAfterTime( time )
878 {
879  level endon( "game_ended" );
880  level endon( "zone_reset" );
881 
882  level.zoneMoveTime = gettime() + time * 1000;
883  level.zoneDestroyedByTimer = false;
884 
885  wait time;
886 
887  if ( !isdefined( level.zone.gameobject.wasContested ) || level.zone.gameobject.wasContested == false )
888  {
889  if ( !isdefined( level.zone.gameobject.wasLeftUnoccupied ) || level.zone.gameobject.wasLeftUnoccupied == false )
890  {
891  zoneOwningTeam = level.zone.gameobject ‪gameobjects::get_owner_team();
892  ‪challenges::controlZoneEntirely( zoneOwningTeam );
893  }
894  }
895 
896  level.zoneDestroyedByTimer = true;
897 
898  level.zone.gameobject RecordGameEventNonPlayer( "hardpoint_moved" );
899 
900  level notify( "zone_moved" );
901 }
902 
903 
904 function ‪awardCapturePoints( team, lastCaptureTeam )
905 {
906  level endon( "game_ended" );
907  level endon( "zone_destroyed" );
908  level endon( "zone_reset" );
909  level endon( "zone_moved" );
910 
911  level notify("awardCapturePointsRunning");
912  level endon("awardCapturePointsRunning");
913 
914  seconds = 1;
915  score = 1;
916 
917  while ( !level.gameEnded )
918  {
919  wait seconds;
920 
922 
923  if ( !level.zone.gameobject.isContested )
924  {
925  if ( level.scorePerPlayer )
926  {
927  score = level.zone.gameobject.numTouching[team];
928  }
929 
931  level.kothTotalSecondsInZone++;
932 
933  foreach( player in level.aliveplayers[team] )
934  {
935  if ( !IsDefined( player.touchTriggers[self.entNum] ) )
936  continue;
937 
938  if( isdefined(player.pers["objtime"]) )
939  {
940  player.pers["objtime"]++;
941  player.objtime = player.pers["objtime"];
942  }
943  player AddPlayerStatWithGameType( "OBJECTIVE_TIME", 1 );
944  }
945  }
946  }
947 }
948 
950 {
951  self.lowerMessageOverride = undefined;
952 }
953 
954 function ‪CompareZoneIndexes( zone_a, zone_b )
955 {
956  script_index_a = zone_a.script_index;
957  script_index_b = zone_b.script_index;
958 
959  if( !isdefined(script_index_a) && !isdefined(script_index_b) )
960  {
961  return false;
962  }
963 
964  if( !isdefined(script_index_a) && isdefined(script_index_b) )
965  {
966 /#
967  println( "KOTH: Missing script_index on zone at " + zone_a.origin );
968 #/
969  return true;
970  }
971 
972  if( isdefined(script_index_a) && !isdefined(script_index_b) )
973  {
974 /#
975  println( "KOTH: Missing script_index on zone at " + zone_b.origin );
976 #/
977  return false;
978  }
979 
980  if( script_index_a > script_index_b )
981  {
982  return true;
983  }
984 
985  return false;
986 }
987 
988 
989 function ‪getZoneArray()
990 {
991  zones = getentarray( "koth_zone_center", "targetname" );
992 
993  if( !isdefined( zones ) )
994  {
995  return undefined;
996  }
997 
998  swapped = true;
999  n = zones.size;
1000  while ( swapped )
1001  {
1002  swapped = false;
1003  for( i = 0 ; i < n-1 ; i++ )
1004  {
1005  if( ‪CompareZoneIndexes(zones[i], zones[i+1]) )
1006  {
1007  temp = zones[i];
1008  zones[i] = zones[i+1];
1009  zones[i+1] = temp;
1010  swapped = true;
1011  }
1012  }
1013  n--;
1014  }
1015  return zones;
1016 }
1017 
1018 
1019 function ‪SetupZones()
1020 {
1021  maperrors = [];
1022 
1023  zones = ‪getZoneArray();
1024 
1025 // if ( zones.size < 2 )
1026 // {
1027 // maperrors[maperrors.size] = "There are not at least 2 entities with targetname \"zone\"";
1028 // }
1029 
1030  trigs = getentarray("koth_zone_trigger", "targetname");
1031  for ( i = 0; i < zones.size; i++ )
1032  {
1033  errored = false;
1034 
1035  zone = zones[i];
1036  zone.trig = undefined;
1037  for ( j = 0; j < trigs.size; j++ )
1038  {
1039  if ( zone istouching( trigs[j] ) )
1040  {
1041  if ( isdefined( zone.trig ) )
1042  {
1043  maperrors[maperrors.size] = "Zone at " + zone.origin + " is touching more than one \"zonetrigger\" trigger";
1044  errored = true;
1045  break;
1046  }
1047  zone.trig = trigs[j];
1048  break;
1049  }
1050  }
1051 
1052  if ( !isdefined( zone.trig ) )
1053  {
1054  if ( !errored )
1055  {
1056  maperrors[maperrors.size] = "Zone at " + zone.origin + " is not inside any \"zonetrigger\" trigger";
1057  continue;
1058  }
1059 
1060  // possible fallback (has been tested)
1061  //zone.trig = spawn( "trigger_radius", zone.origin, 0, 128, 128 );
1062  //errored = false;
1063  }
1064 
1065  assert( !errored );
1066 
1067  zone.trigorigin = zone.trig.origin;
1068 
1069  zone.objectiveAnchor = ‪Spawn( "script_model", zone.origin ); // We need a script_model to attach the objective to
1070 
1071  visuals = [];
1072  visuals[0] = zone;
1073 
1074  if ( isdefined( zone.target ) )
1075  {
1076  otherVisuals = getEntArray( zone.target, "targetname" );
1077  for ( j = 0; j < otherVisuals.size; j++ )
1078  {
1079  visuals[visuals.size] = otherVisuals[j];
1080  }
1081  }
1082 
1083  objective_name = istring("hardpoint");
1084 
1085  zone.gameObject = ‪gameobjects::create_use_object( "neutral", zone.trig, visuals, (0,0,0), objective_name );
1086  zone.gameObject ‪gameobjects::set_objective_entity( zone );
1087  zone.gameObject ‪gameobjects::disable_object();
1088  zone.gameObject ‪gameobjects::set_model_visibility( false );
1089  zone.trig.useObj = zone.gameObject;
1090  zone.trig.remote_control_player_can_trigger = true;
1091  zone ‪setUpNearbySpawns();
1093  }
1094 
1095  if (maperrors.size > 0)
1096  {
1097  /#
1098  println("^1------------ Map Errors ------------");
1099  for(i = 0; i < maperrors.size; i++)
1100  println(maperrors[i]);
1101  println("^1------------------------------------");
1102 
1103  println("Map errors. See above");
1104  #/
1106 
1107  return;
1108  }
1109 
1110  level.zones = zones;
1111 
1112  level.prevzone = undefined;
1113  level.prevzone2 = undefined;
1114 
1116 
1117  return true;
1118 }
1119 
1121 {
1122  if ( !isdefined( level.levelkothDisable ) )
1123  return;
1124 
1125  foreach( nullZone in level.levelkothDisable )
1126  {
1127  mindist = 10000000000;
1128  foundZone = undefined;
1129 
1130  foreach( zone in level.zones )
1131  {
1132  distance = DistanceSquared( nullZone.origin, zone.origin );
1133 
1134  if ( distance < mindist )
1135  {
1136  foundZone = zone;
1137  mindist = distance;
1138  }
1139  }
1140 
1141  if ( isdefined( foundZone ) )
1142  {
1143  if ( !isdefined( foundZone.gameObject.exclusions ) )
1144  {
1145  foundZone.gameObject.exclusions = [];
1146  }
1147  foundZone.gameObject.exclusions[ foundZone.gameObject.exclusions.size ] = nullZone;
1148  }
1149  }
1150 
1151 }
1152 
1154 {
1155  spawns = level.spawn_all;
1156 
1157  for ( i = 0; i < spawns.size; i++ )
1158  {
1159  spawns[i].distsq = distanceSquared( spawns[i].origin, self.origin );
1160  }
1161 
1162  // sort by distsq
1163  for ( i = 1; i < spawns.size; i++ )
1164  {
1165  thespawn = spawns[i];
1166  for ( j = i - 1; j >= 0 && thespawn.distsq < spawns[j].distsq; j-- )
1167  spawns[j + 1] = spawns[j];
1168  spawns[j + 1] = thespawn;
1169  }
1170 
1171  first = [];
1172  second = [];
1173  third = [];
1174  outer = [];
1175 
1176  thirdSize = spawns.size / 3;
1177  for ( i = 0; i <= thirdSize; i++ )
1178  {
1179  first[ first.size ] = spawns[i];
1180  }
1181  for ( ; i < spawns.size; i++ )
1182  {
1183  outer[ outer.size ] = spawns[i];
1184  if ( i <= (thirdSize*2) )
1185  second[ second.size ] = spawns[i];
1186  else
1187  third[ third.size ] = spawns[i];
1188  }
1189 
1190  self.gameObject.nearSpawns = first;
1191  self.gameObject.midSpawns = second;
1192  self.gameObject.farSpawns = third;
1193  self.gameObject.outerSpawns = outer;
1194 }
1195 
1197 {
1198  zone = level.zones[ 0 ];
1199 
1200  // old linear and "random" systems
1201  level.prevzone2 = level.prevzone;
1202  level.prevzone = zone;
1203  level.prevZoneIndex = 0;
1204 
1205  // new shuffled system
1206  ‪ShuffleZones();
1207  ArrayRemoveValue( level.zoneSpawnQueue, zone );
1208 
1209  return zone;
1210 }
1211 
1212 function ‪GetNextZone()
1213 {
1214  nextZoneIndex = (level.prevZoneIndex + 1) % level.zones.size;
1215  zone = level.zones[ nextZoneIndex ];
1216  level.prevzone2 = level.prevzone;
1217  level.prevzone = zone;
1218  level.prevZoneIndex = nextZoneIndex;
1219 
1220  return zone;
1221 }
1222 
1224 {
1225  level.prevZoneIndex = randomint( level.zones.size);
1226  zone = level.zones[ level.prevZoneIndex ];
1227  level.prevzone2 = level.prevzone;
1228  level.prevzone = zone;
1229 
1230  return zone;
1231 }
1232 
1234 {
1235  level.zoneSpawnQueue = [];
1236 
1237  spawnQueue = ArrayCopy(level.zones);
1238  total_left = spawnQueue.size;
1239 
1240  while( total_left > 0 )
1241  {
1242  index = randomint( total_left );
1243 
1244  valid_zones = 0;
1245  for( zone = 0; zone < level.zones.size; zone++ )
1246  {
1247  if ( !isdefined(spawnQueue[zone]) )
1248  continue;
1249 
1250  if ( valid_zones == index )
1251  {
1252  // dont allow the last radio from the previous shuffle to be put first in the next
1253  if ( level.zoneSpawnQueue.size == 0 && isdefined( level.zone ) && level.zone == spawnQueue[zone] )
1254  continue;
1255 
1256  level.zoneSpawnQueue[level.zoneSpawnQueue.size] = spawnQueue[zone];
1257  spawnQueue[zone] = undefined;
1258  break;
1259  }
1260 
1261  valid_zones++;
1262  }
1263 
1264  total_left--;
1265  }
1266 }
1267 
1268 // shuffled picking
1270 {
1271  if ( level.zoneSpawnQueue.size == 0 )
1272  ‪ShuffleZones();
1273 
1274  assert( level.zoneSpawnQueue.size > 0 );
1275 
1276  next_zone = level.zoneSpawnQueue[0];
1277  ArrayRemoveIndex( level.zoneSpawnQueue, 0 );
1278 
1279  return next_zone;
1280 }
1281 
1283 {
1284  has_players = 0;
1285 
1286  foreach( team in level.teams )
1287  {
1288  if ( num[team] > 0 )
1289  has_players++;
1290  }
1291 
1292  return has_players;
1293 }
1294 
1295 function ‪GetPointCost( avgpos, origin )
1296 {
1297  avg_distance = 0;
1298  total_error = 0;
1299  distances = [];
1300 
1301  foreach( team, position in avgpos )
1302  {
1303  distances[team] = Distance(origin, avgpos[team]);
1304  avg_distance += distances[team];
1305  }
1306 
1307  avg_distance = avg_distance / distances.size;
1308 
1309  foreach( team, dist in distances )
1310  {
1311  err = (distances[team] - avg_distance);
1312  total_error += err * err;
1313  }
1314 
1315  return total_error;
1316 }
1317 
1319 {
1320  // find average of positions of each team
1321  // (medians would be better, to get rid of outliers...)
1322  // and find the zone which has the least difference in distance from those two averages
1323 
1324  foreach( team in level.teams )
1325  {
1326  avgpos[team] = (0,0,0);
1327  num[team] = 0;
1328  }
1329 
1330  for ( i = 0; i < level.players.size; i++ )
1331  {
1332  player = level.players[i];
1333  if ( isalive( player ) )
1334  {
1335  avgpos[ player.pers["team"] ] += player.origin;
1336  num[ player.pers["team"] ]++;
1337  }
1338  }
1339 
1340  if ( ‪GetCountOfTeamsWithPlayers(num) <= 1 )
1341  {
1342  zone = level.zones[ randomint( level.zones.size) ];
1343  while ( isdefined( level.prevzone ) && zone == level.prevzone ) // so lazy
1344  zone = level.zones[ randomint( level.zones.size) ];
1345 
1346  level.prevzone2 = level.prevzone;
1347  level.prevzone = zone;
1348 
1349  return zone;
1350  }
1351 
1352  foreach( team in level.teams )
1353  {
1354  if ( num[team] == 0 )
1355  {
1356  avgpos[team] = undefined;
1357  }
1358  else
1359  {
1360  avgpos[team] = avgpos[team] / num[team];
1361  }
1362  }
1363 
1364  bestzone = undefined;
1365  lowestcost = undefined;
1366  for ( i = 0; i < level.zones.size; i++ )
1367  {
1368  zone = level.zones[i];
1369 
1370  // (purposefully using distance instead of distanceSquared)
1371  cost = ‪GetPointCost( avgpos, zone.origin );
1372 
1373  if ( isdefined( level.prevzone ) && zone == level.prevzone )
1374  {
1375  continue;
1376  }
1377  if ( isdefined( level.prevzone2 ) && zone == level.prevzone2 )
1378  {
1379  if ( level.zones.size > 2 )
1380  continue;
1381  else
1382  cost += 512 * 512;
1383  }
1384 
1385  if ( !isdefined( lowestcost ) || cost < lowestcost )
1386  {
1387  lowestcost = cost;
1388  bestzone = zone;
1389  }
1390  }
1391  assert( isdefined( bestzone ) );
1392 
1393  level.prevzone2 = level.prevzone;
1394  level.prevzone = bestzone;
1395 
1396  return bestzone;
1397 }
1398 
1400 {
1401  game["switchedsides"] = !game["switchedsides"];
1402 }
1403 
1404 
1405 function ‪onPlayerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
1406 {
1407  if ( !isPlayer( attacker ) || (level.captureTime && !self.touchTriggers.size && !attacker.touchTriggers.size) || attacker.pers["team"] == self.pers["team"] )
1408  return;
1409 
1410  medalGiven = false;
1411  scoreEventProcessed = false;
1412 
1413  ownerTeam = undefined;
1414 
1415  if ( level.captureTime == 0 )
1416  {
1417  if ( !isdefined( level.zone ) )
1418  return;
1419 
1420  ownerTeam = level.zone.gameObject.ownerTeam ;
1421 
1422  if ( !isdefined( ownerTeam ) || ownerTeam == "neutral" )
1423  return;
1424  }
1425 
1426  if ( self.touchTriggers.size || ( level.captureTime == 0 && self IsTouching( level.zone.trig ) ) )
1427  {
1428  if ( level.captureTime > 0 )
1429  {
1430  triggerIds = getArrayKeys( self.touchTriggers );
1431  ownerTeam = self.touchTriggers[triggerIds[0]].useObj.ownerTeam;
1432  }
1433 
1434  if ( ownerTeam != "neutral" )
1435  {
1436  attacker.lastKilltime = getTime();
1437  team = attacker.pers["team"];
1438  if ( team == ownerTeam )
1439  {
1440  if ( !medalGiven )
1441  {
1442  attacker ‪medals::offenseGlobalCount();
1443  attacker thread ‪challenges::killedBaseOffender(level.zone.trig, weapon);
1444 
1445  medalGiven = true;
1446  }
1447  //scoreevents::processScoreEvent( "killed_defender", attacker, undefined, weapon );// TFLAME 9/3/12 - Changing these events to "hardpoint_kill" as attacker / defender changes so often in Hardpoint
1448  ‪scoreevents::processScoreEvent( "hardpoint_kill", attacker, undefined, weapon );
1449  self RecordKillModifier("defending");
1450  scoreEventProcessed = true;
1451  }
1452  else
1453  {
1454  if ( !medalGiven )
1455  {
1456  if( isdefined(attacker.pers["defends"]) )
1457  {
1458  attacker.pers["defends"]++;
1459  attacker.defends = attacker.pers["defends"];
1460  }
1461 
1462  attacker ‪medals::defenseGlobalCount();
1463  medalGiven = true;
1464  attacker thread ‪challenges::killedBaseDefender(level.zone.trig);
1465  attacker RecordGameEvent("defending");
1466  }
1467  attacker ‪challenges::killedZoneAttacker( weapon );
1468  //scoreevents::processScoreEvent( "killed_attacker", attacker, undefined, weapon ); // TFLAME 9/3/12 - Changing these events to "hardpoint_kill" as attacker / defender changes so often in Hardpoint
1469  ‪scoreevents::processScoreEvent( "hardpoint_kill", attacker, undefined, weapon );
1470  self RecordKillModifier("assaulting");
1471  scoreEventProcessed = true;
1472  }
1473  }
1474  }
1475 
1476  if ( attacker.touchTriggers.size || ( level.captureTime == 0 && attacker IsTouching( level.zone.trig ) ) )
1477  {
1478  if ( level.captureTime > 0 )
1479  {
1480  triggerIds = getArrayKeys( attacker.touchTriggers );
1481  ownerTeam = attacker.touchTriggers[triggerIds[0]].useObj.ownerTeam;
1482  }
1483 
1484  if ( ownerTeam != "neutral" )
1485  {
1486  team = self.pers["team"];
1487  if ( team == ownerTeam )
1488  {
1489  if ( !medalGiven )
1490  {
1491  if( isdefined(attacker.pers["defends"]) )
1492  {
1493  attacker.pers["defends"]++;
1494  attacker.defends = attacker.pers["defends"];
1495  }
1496 
1497  attacker ‪medals::defenseGlobalCount();
1498  medalGiven = true;
1499  attacker thread ‪challenges::killedBaseDefender(level.zone.trig);
1500  attacker RecordGameEvent("defending");
1501  }
1502  if ( scoreEventProcessed == false )
1503  {
1504  attacker ‪challenges::killedZoneAttacker( weapon );
1505  //scoreevents::processScoreEvent( "killed_attacker", attacker, undefined, weapon );// TFLAME 9/3/12 - Changing these events to "hardpoint_kill" as attacker / defender changes so often in Hardpoint
1506  ‪scoreevents::processScoreEvent( "hardpoint_kill", attacker, undefined, weapon );
1507  self RecordKillModifier("assaulting");
1508  }
1509  }
1510  else
1511  {
1512  if ( !medalGiven )
1513  {
1514  attacker ‪medals::offenseGlobalCount();
1515  medalGiven = true;
1516  attacker thread ‪challenges::killedBaseOffender(level.zone.trig, weapon);
1517  }
1518  if ( scoreEventProcessed == false )
1519  {
1520  //scoreevents::processScoreEvent( "killed_defender", attacker, undefined, weapon );// TFLAME 9/3/12 - Changing these events to "hardpoint_kill" as attacker / defender changes so often in Hardpoint
1521  ‪scoreevents::processScoreEvent( "hardpoint_kill", attacker, undefined, weapon );
1522  self RecordKillModifier("defending");
1523  }
1524  }
1525  }
1526  }
1527 
1528  if ( medalGiven == true )
1529  {
1530  if ( ‪IS_TRUE( level.zone.gameobject.isContested ) )
1531  {
1532  attacker thread ‪killWhileContesting();
1533  }
1534  }
1535 }
1536 
1537 function ‪watchKillWhileContesting( zone_captured_team )
1538 {
1539  level endon( zone_captured_team );
1540  level endon( "zone_destroyed" );
1541  level endon( "zone_captured" );
1542  level endon( "death" );
1543 
1544  self ‪util::waittill_any_return( "killWhileContesting", "disconnect" );
1545  level notify( "abortKillWhileContesting" );
1546 }
1547 
1549 {
1550  self notify( "killWhileContesting" );
1551  self endon( "killWhileContesting" );
1552  self endon( "disconnect" );
1553 
1554  killTime = getTime();
1555  playerteam = self.pers["team"];
1556  if ( !isdefined ( self.clearEnemyCount ) )
1557  {
1558  self.clearEnemyCount = 0;
1559  }
1560 
1561  self.clearEnemyCount++;
1562 
1563  zone_captured_team = "zone_captured" + playerteam;
1564  self thread ‪watchKillWhileContesting( zone_captured_team );
1565  zoneReturn = level ‪util::waittill_any_return( zone_captured_team, "zone_destroyed", "zone_captured", "death", "abortKillWhileContesting" );
1566 
1567  if ( zoneReturn == "death" || playerteam != self.pers["team"] )
1568  {
1569  self.clearEnemyCount = 0;
1570  return;
1571  }
1572 
1573  if ( self.clearEnemyCount >= 2 && killTime + 200 > getTime() )
1574  {
1575  ‪scoreevents::processScoreEvent( "clear_2_attackers", self );
1576  }
1577  self.clearEnemyCount = 0;
1578 }
1579 
1580 function ‪onEndGame( winningTeam )
1581 {
1582  for ( i = 0; i < level.zones.size; i++ )
1583  {
1584  level.zones[i].gameobject ‪gameobjects::allow_use( "none" );
1585  }
1586 }
1587 
1589 {
1590  // this affects both teams
1591  self ‪spawning::create_influencer( "koth_large", self.gameobject.curOrigin, 0 );
1592  self ‪spawning::create_influencer( "koth_small", self.gameobject.curOrigin, 0 );
1593 
1594  // turn it off for now
1595  self ‪spawning::enable_influencers(false);
1596 }
1597 
1598 function ‪updateCapsPerMinute(lastOwnerTeam)
1599 {
1600  if ( !isdefined( self.capsPerMinute ) )
1601  {
1602  self.numCaps = 0;
1603  self.capsPerMinute = 0;
1604  }
1605 
1606  // not including neutral flags as part of the boosting prevention
1607  // to help with false positives at the start
1608  if ( !isdefined ( lastOwnerTeam ) || lastOwnerTeam == "neutral" )
1609  return;
1610 
1611  self.numCaps++;
1612 
1613  minutesPassed = ‪globallogic_utils::getTimePassed() / ( 60 * 1000 );
1614 
1615  // players use the actual time played
1616  if ( IsPlayer( self ) && isdefined(self.timePlayed["total"]) )
1617  minutesPassed = self.timePlayed["total"] / 60;
1618 
1619  self.capsPerMinute = ( minutesPassed ? self.numCaps / minutesPassed : 0 );
1620  if ( self.capsPerMinute > self.numCaps )
1621  self.capsPerMinute = self.numCaps;
1622 }
1623 
1624 function ‪isScoreBoosting( player )
1625 {
1626  if ( !level.rankedMatch )
1627  return false;
1628 
1629  if ( player.capsPerMinute > level.playerCaptureLPM )
1630  return true;
1631 
1632  return false;
1633 }
‪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
‪processScoreEvent
‪function processScoreEvent(event, player, victim, weapon)
Definition: scoreevents_shared.gsc:19
‪setObjectiveText
‪function setObjectiveText(team, text)
Definition: _util.gsc:585
‪enable_influencers
‪function enable_influencers(enabled)
Definition: _spawning.gsc:449
‪killedLastContester
‪function killedLastContester()
Definition: challenges_shared.gsc:1347
‪allow_use
‪function allow_use(relativeTeam)
Definition: gameobjects_shared.gsc:3485
‪setvisiblescoreboardcolumns
‪function setvisiblescoreboardcolumns(col1, col2, col3, col4, col5)
Definition: _globallogic.gsc:545
‪set_owner_team
‪function set_owner_team(team)
Definition: gameobjects_shared.gsc:3437
‪killedBaseDefender
‪function killedBaseDefender(objective)
Definition: _challenges.gsc:1647
‪updateAllSpawnPoints
‪function updateAllSpawnPoints()
Definition: _spawning.gsc:551
‪CompareZoneIndexes
‪function CompareZoneIndexes(zone_a, zone_b)
Definition: koth.gsc:954
‪getZoneArray
‪function getZoneArray()
Definition: koth.gsc:989
‪registerRoundWinLimit
‪function registerRoundWinLimit(minValue, maxValue)
Definition: _util.gsc:630
‪KothMainLoop
‪function KothMainLoop()
Definition: koth.gsc:444
‪RANDOM_ZONE_LOCATIONS_ON
‪#define RANDOM_ZONE_LOCATIONS_ON
Definition: koth.gsc:31
‪setupZoneExclusions
‪function setupZoneExclusions()
Definition: koth.gsc:1120
‪set_use_time
‪function set_use_time(time)
Definition: gameobjects_shared.gsc:3455
‪give_held_credit
‪function give_held_credit(touchList, team)
Definition: koth.gsc:762
‪register_allowed_gameobject
‪function register_allowed_gameobject(gameobject)
Definition: gameobjects_shared.gsc:67
‪defenseGlobalCount
‪function defenseGlobalCount()
Definition: medals_shared.gsc:41
‪killedBaseOffender
‪function killedBaseOffender(objective, weapon)
Definition: _challenges.gsc:1566
‪track_capture_time
‪function track_capture_time()
Definition: koth.gsc:713
‪find_box_center
‪function find_box_center(mins, maxs)
Definition: math_shared.gsc:86
‪offenseGlobalCount
‪function offenseGlobalCount()
Definition: medals_shared.gsc:36
‪onZoneDestroy
‪function onZoneDestroy(player)
Definition: koth.gsc:780
‪resetTeamScores
‪function resetTeamScores()
Definition: _globallogic_score.gsc:808
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪waittill_any_return
‪function waittill_any_return(string1, string2, string3, string4, string5, string6, string7)
Definition: util_shared.csc:212
‪play_on_players
‪function play_on_players(sound, team)
Definition: sound_shared.gsc:257
‪getRespawnDelay
‪function getRespawnDelay()
Definition: koth.gsc:161
‪registerFriendlyFireDelay
‪function registerFriendlyFireDelay(dvarString, defaultValue, minValue, maxValue)
Definition: _globallogic.gsc:3917
‪set_claim_team
‪function set_claim_team(newTeam)
Definition: gameobjects_shared.gsc:2271
‪hideTimerDisplayOnGameEnd
‪function hideTimerDisplayOnGameEnd()
Definition: koth.gsc:566
‪create_influencer
‪function create_influencer(name, origin, team_mask)
Definition: _spawning.gsc:267
‪must_maintain_claim
‪function must_maintain_claim(enabled)
Definition: gameobjects_shared.gsc:4224
‪OBJECTIVE_FLAG_TARGET
‪#define OBJECTIVE_FLAG_TARGET
Definition: koth.gsc:35
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪pauseTimer
‪function pauseTimer(pausePlayableTimer=false)
Definition: _globallogic_utils.gsc:287
‪capturedObjective
‪function capturedObjective(captureTime, objective)
Definition: challenges_shared.gsc:882
‪set_flags
‪function set_flags(flags)
Definition: gameobjects_shared.gsc:4234
‪registerNumLives
‪function registerNumLives(minValue, maxValue, teamLivesMinValue, teamLivesMaxValue)
Definition: _util.gsc:664
‪registerScoreLimit
‪function registerScoreLimit(minValue, maxValue)
Definition: _util.gsc:638
‪awardCapturePoints
‪function awardCapturePoints(team, lastCaptureTeam)
Definition: koth.gsc:904
‪GetFirstZone
‪function GetFirstZone()
Definition: koth.gsc:1196
‪delay
‪function delay(time_or_notify, str_endon, func, arg1, arg2, arg3, arg4, arg5, arg6)
Definition: util_shared.csc:784
‪PickZoneToSpawn
‪function PickZoneToSpawn()
Definition: koth.gsc:1318
‪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
‪updateTeamClientField
‪function updateTeamClientField()
Definition: koth.gsc:590
‪killedZoneAttacker
‪function killedZoneAttacker(weapon)
Definition: challenges_shared.gsc:1274
‪onZoneUncontested
‪function onZoneUncontested(lastClaimTeam)
Definition: koth.gsc:862
‪spawn_next_zone
‪function spawn_next_zone()
Definition: koth.gsc:331
‪PickRandomZoneToSpawn
‪function PickRandomZoneToSpawn()
Definition: koth.gsc:1223
‪immediateCapture
‪function immediateCapture()
Definition: challenges_shared.gsc:1341
‪set_model_visibility
‪function set_model_visibility(visibility)
Definition: gameobjects_shared.gsc:3503
‪get_owner_team
‪function get_owner_team()
Definition: gameobjects_shared.gsc:3445
‪setUpNearbySpawns
‪function setUpNearbySpawns()
Definition: koth.gsc:1153
‪onZoneUnoccupied
‪function onZoneUnoccupied()
Definition: koth.gsc:826
‪updateCapsPerMinute
‪function updateCapsPerMinute(lastOwnerTeam)
Definition: koth.gsc:1598
‪getTimePassed
‪function getTimePassed()
Definition: _globallogic_utils.gsc:274
‪onZoneCapture
‪function onZoneCapture(player)
Definition: koth.gsc:632
‪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
‪koth_playerSpawnedCB
‪function koth_playerSpawnedCB()
Definition: koth.gsc:949
‪main
‪function main()
Definition: koth.gsc:67
‪enable_object
‪function enable_object(forceShow)
Definition: gameobjects_shared.gsc:3938
‪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
‪isScoreBoosting
‪function isScoreBoosting(player)
Definition: koth.gsc:1624
‪OBJECTIVE_FLAG_NORMAL
‪#define OBJECTIVE_FLAG_NORMAL
Definition: koth.gsc:34
‪onEndGame
‪function onEndGame(winningTeam)
Definition: koth.gsc:1580
‪onRoundSwitch
‪function onRoundSwitch()
Definition: koth.gsc:1399
‪gametype_specific_battle_chatter
‪function gametype_specific_battle_chatter(event, team)
Definition: _battlechatter.gsc:838
‪updateGametypeDvars
‪function updateGametypeDvars()
Definition: koth.gsc:301
‪GetCountOfTeamsWithPlayers
‪function GetCountOfTeamsWithPlayers(num)
Definition: koth.gsc:1282
‪MoveZoneAfterTime
‪function MoveZoneAfterTime(time)
Definition: koth.gsc:877
‪bookmark
‪function bookmark(type, time, mainClientEnt, otherClientEnt, eventPriority, inflictorEnt, overrideEntityCamera, actorEnt)
Definition: demo_shared.gsc:25
‪give_capture_credit
‪function give_capture_credit(touchList, string, captureTime, capture_team, lastCaptureTeam)
Definition: koth.gsc:717
‪abort_level
‪function abort_level()
Definition: callbacks_shared.gsc:1018
‪Spawn
‪function Spawn(parent, onDeathCallback)
Definition: _flak_drone.gsc:427
‪updateObjectiveHintMessages
‪function updateObjectiveHintMessages(defenderTeam, defendMessage, attackMessage)
Definition: koth.gsc:138
‪registerRoundSwitch
‪function registerRoundSwitch(minValue, maxValue)
Definition: _util.gsc:615
‪createZoneSpawnInfluencer
‪function createZoneSpawnInfluencer()
Definition: koth.gsc:1588
‪resumeTimerDiscardOverride
‪function resumeTimerDiscardOverride(discardTime)
Definition: _globallogic_utils.gsc:309
‪init
‪function init()
Definition: struct.csc:1
‪getTDMStartSpawnName
‪function getTDMStartSpawnName(team)
Definition: _spawning.gsc:1067
‪killWhileContesting
‪function killWhileContesting()
Definition: koth.gsc:1548
‪controlZoneEntirely
‪function controlZoneEntirely(team)
Definition: challenges_shared.gsc:1264
‪giveTeamScoreForObjective
‪function giveTeamScoreForObjective(team, score)
Definition: _globallogic_score.gsc:773
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪setObjectiveScoreText
‪function setObjectiveScoreText(team, text)
Definition: _util.gsc:590
‪can_contest_claim
‪function can_contest_claim(enabled)
Definition: gameobjects_shared.gsc:4229
‪watchKillWhileContesting
‪function watchKillWhileContesting(zone_captured_team)
Definition: koth.gsc:1537
‪leader_dialog
‪function leader_dialog(dialogKey, team, excludeList, objectiveKey, killstreakId, dialogBufferKey)
Definition: _globallogic_audio.gsc:435
‪getNumTouching
‪function getNumTouching()
Definition: koth.gsc:357
‪pause_time
‪function pause_time()
Definition: koth.gsc:283
‪spawn_first_zone
‪function spawn_first_zone(delay)
Definition: koth.gsc:307
‪resume_time
‪function resume_time()
Definition: koth.gsc:292
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪GetPointCost
‪function GetPointCost(avgpos, origin)
Definition: koth.gsc:1295
‪RANDOM_ZONE_LOCATIONS_OFF
‪#define RANDOM_ZONE_LOCATIONS_OFF
Definition: koth.gsc:30
‪GetNextZone
‪function GetNextZone()
Definition: koth.gsc:1212
‪set_use_text
‪function set_use_text(text)
Definition: gameobjects_shared.gsc:3460
‪forceSpawnTeam
‪function forceSpawnTeam(team)
Definition: koth.gsc:573
‪onBeginUse
‪function onBeginUse(player)
Definition: koth.gsc:611
‪SetupZones
‪function SetupZones()
Definition: koth.gsc:1019
‪onZoneContested
‪function onZoneContested()
Definition: koth.gsc:840
‪updateObjectiveHintMessage
‪function updateObjectiveHintMessage(message)
Definition: koth.gsc:153
‪WaitTillSlowProcessAllowed
‪function WaitTillSlowProcessAllowed()
Definition: util_shared.gsc:2536
‪registerTimeLimit
‪function registerTimeLimit(minValue, maxValue)
Definition: _util.gsc:655
‪get_random_intermission_point
‪function get_random_intermission_point()
Definition: _spawnlogic.gsc:54
‪onStartGameType
‪function onStartGameType()
Definition: koth.gsc:193
‪toggleZoneEffects
‪function toggleZoneEffects(enabled)
Definition: koth.gsc:368
‪disable_object
‪function disable_object(forceHide)
Definition: gameobjects_shared.gsc:3909
‪onPlayerKilled
‪function onPlayerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
Definition: koth.gsc:1405
‪GetNextZoneFromQueue
‪function GetNextZoneFromQueue()
Definition: koth.gsc:1269
‪onEndUse
‪function onEndUse(team, player, success)
Definition: koth.gsc:626
‪KothCaptureLoop
‪function KothCaptureLoop()
Definition: koth.gsc:381
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265
‪ShuffleZones
‪function ShuffleZones()
Definition: koth.gsc:1233