‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_spawnlogic.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\gameobjects_shared;
5 #using scripts\shared\system_shared;
6 
7 #insert scripts\shared\shared.gsh;
8 
9 #namespace spawnlogic;
10 
11 ‪REGISTER_SYSTEM( "spawnlogic", &‪__init__, undefined )
12 
13 function ‪__init__()
14 {
16 }
17 
18 // called once at start of game
19 function ‪main()
20 {
21  // start keeping track of deaths
22  level.spawnlogic_deaths = [];
23  // DEBUG
24  level.spawnlogic_spawnkills = [];
25  level.players = [];
26  level.grenades = [];
27  level.pipebombs = [];
28 
29  level.spawnMins = (0,0,0);
30  level.spawnMaxs = (0,0,0);
31  level.spawnMinsMaxsPrimed = false;
32  if ( isdefined( level.safespawns ) )
33  {
34  for( i = 0; i < level.safespawns.size; i++ )
35  {
36  level.safespawns[i] ‪spawnPointInit();
37  }
38  }
39 
40  if ( GetDvarString( "scr_spawn_enemyavoiddist") == "" )
41  SetDvar("scr_spawn_enemyavoiddist", "800");
42  if ( GetDvarString( "scr_spawn_enemyavoidweight") == "" )
43  SetDvar("scr_spawn_enemyavoidweight", "0");
44 
45 }
46 
47 function ‪findBoxCenter( mins, maxs )
48 {
49  center = ( 0, 0, 0 );
50  center = maxs - mins;
51  center = ( center[0]/2, center[1]/2, center[2]/2 ) + mins;
52  return center;
53 }
54 
55 function ‪expandMins( mins, point )
56 {
57  if ( mins[0] > point[0] )
58  mins = ( point[0], mins[1], mins[2] );
59  if ( mins[1] > point[1] )
60  mins = ( mins[0], point[1], mins[2] );
61  if ( mins[2] > point[2] )
62  mins = ( mins[0], mins[1], point[2] );
63  return mins;
64 }
65 
66 function ‪expandMaxs( maxs, point )
67 {
68  if ( maxs[0] < point[0] )
69  maxs = ( point[0], maxs[1], maxs[2] );
70  if ( maxs[1] < point[1] )
71  maxs = ( maxs[0], point[1], maxs[2] );
72  if ( maxs[2] < point[2] )
73  maxs = ( maxs[0], maxs[1], point[2] );
74  return maxs;
75 }
76 
77 
78 function ‪addSpawnPointsInternal( team, spawnPointName )
79 {
80  oldSpawnPoints = [];
81  if ( level.teamSpawnPoints[team].size )
82  oldSpawnPoints = level.teamSpawnPoints[team];
83 
84  level.teamSpawnPoints[team] = ‪getSpawnpointArray( spawnPointName );
85 
86  if ( !isdefined( level.spawnpoints ) )
87  level.spawnpoints = [];
88 
89  for ( index = 0; index < level.teamSpawnPoints[team].size; index++ )
90  {
91  spawnpoint = level.teamSpawnPoints[team][index];
92 
93  if ( !isdefined( spawnpoint.inited ) )
94  {
95  spawnpoint ‪spawnPointInit();
96  level.spawnpoints[ level.spawnpoints.size ] = spawnpoint;
97  }
98  }
99 
100  for ( index = 0; index < oldSpawnPoints.size; index++ )
101  {
102  origin = oldSpawnPoints[index].origin;
103 
104  // are these 2 lines necessary? we already did it in spawnPointInit
105  level.spawnMins = ‪expandMins( level.spawnMins, origin );
106  level.spawnMaxs = ‪expandMaxs( level.spawnMaxs, origin );
107 
108  level.teamSpawnPoints[team][ level.teamSpawnPoints[team].size ] = oldSpawnPoints[index];
109  }
110 
111  if ( !level.teamSpawnPoints[team].size )
112  {
113 
115  wait 1; // so we don't try to abort more than once before the frame ends
116  return;
117  }
118 }
119 
121 {
122  foreach( team in level.teams )
123  {
124  level.teamSpawnPoints[team] = [];
125  }
126  level.spawnpoints = [];
127  level.unified_spawn_points = undefined;
128 }
129 
130 function ‪addSpawnPoints( team, spawnPointName )
131 {
132  ‪addSpawnPointClassName( spawnPointName );
133  ‪addSpawnPointTeamClassName( team, spawnPointName );
134 
135  ‪addSpawnPointsInternal( team, spawnPointName );
136 }
137 
138 function ‪rebuildSpawnPoints( team )
139 {
140  level.teamSpawnPoints[team] = [];
141 
142  for ( index = 0; index < level.spawn_point_team_class_names[team].size; index++ )
143  {
144  ‪addSpawnPointsInternal( team, level.spawn_point_team_class_names[team][index] );
145  }
146 }
147 
148 function ‪placeSpawnPoints( spawnPointName )
149 {
150  ‪addSpawnPointClassName( spawnPointName );
151 
152  spawnPoints = ‪getSpawnpointArray( spawnPointName );
153 
154  if ( !spawnPoints.size )
155  {
156 
158  wait 1; // so we don't try to abort more than once before the frame ends
159  return;
160  }
161 
162  for( index = 0; index < spawnPoints.size; index++ )
163  {
164  spawnPoints[index] ‪spawnPointInit();
165  // don't add this spawnpoint to level.spawnpoints,
166  // because it's an unimportant one that we don't want to do sight traces to
167 
168  }
169 }
170 
171 // just drops to ground
172 // needed for demolition because secondary attacker points do
173 // not get used until mid round and therefore dont get processed
174 // this was making the rendered debug boxes appear to be floating
175 // and causing confusion amongst the masses. Need the points to
176 // be debug friendly. Cant use the placeSpawnPoints function because
177 // that does somethings that we dont want to do until they are actually used
178 function ‪dropSpawnPoints( spawnPointName )
179 {
180  spawnPoints = ‪getSpawnpointArray( spawnPointName );
181  if ( !spawnPoints.size )
182  {
183 
184  return;
185  }
186 
187  for( index = 0; index < spawnPoints.size; index++ )
188  {
189  spawnPoints[index] placeSpawnpoint();
190  }
191 }
192 
193 function ‪addSpawnPointClassName( spawnPointClassName )
194 {
195  if ( !isdefined( level.spawn_point_class_names ) )
196  {
197  level.spawn_point_class_names = [];
198  }
199 
200  level.spawn_point_class_names[ level.spawn_point_class_names.size ] = spawnPointClassName;
201 }
202 
203 function ‪addSpawnPointTeamClassName( team, spawnPointClassName )
204 {
205  level.spawn_point_team_class_names[team][ level.spawn_point_team_class_names[team].size ] = spawnPointClassName;
206 }
207 
208 function ‪getSpawnpointArray( classname )
209 {
210  spawnPoints = getEntArray( classname, "classname" );
211 
212  if ( !isdefined( level.extraspawnpoints ) || !isdefined( level.extraspawnpoints[classname] ) )
213  return spawnPoints;
214 
215  for ( i = 0; i < level.extraspawnpoints[classname].size; i++ )
216  {
217  spawnPoints[ spawnPoints.size ] = level.extraspawnpoints[classname][i];
218  }
219 
220  return spawnPoints;
221 }
222 
224 {
225  spawnpoint = self;
226  origin = spawnpoint.origin;
227 
228  // we need to properly prime the mins and maxs otherwise a level that is entirely
229  // on one side of the zero line for any axis will have an invalid map center
230  if ( !level.spawnMinsMaxsPrimed )
231  {
232  level.spawnMins = origin;
233  level.spawnMaxs = origin;
234  level.spawnMinsMaxsPrimed = true;
235  }
236  else
237  {
238  level.spawnMins = ‪expandMins( level.spawnMins, origin );
239  level.spawnMaxs = ‪expandMaxs( level.spawnMaxs, origin );
240  }
241 
242  spawnpoint placeSpawnpoint();
243  spawnpoint.forward = anglesToForward( spawnpoint.angles );
244  spawnpoint.sightTracePoint = spawnpoint.origin + (0,0,50);
245 
246  /*skyHeight = 500;
247  spawnpoint.outside = true;
248  if ( !bullettracepassed( spawnpoint.sightTracePoint, spawnpoint.sightTracePoint + (0,0,skyHeight), false, undefined) )
249  {
250  startpoint = spawnpoint.sightTracePoint + spawnpoint.forward * 100;
251  if ( !bullettracepassed( startpoint, startpoint + (0,0,skyHeight), false, undefined) )
252  spawnpoint.outside = false;
253  }*/
254 
255  spawnpoint.inited = true;
256 }
257 
258 function ‪getTeamSpawnPoints( team )
259 {
260  return level.teamSpawnPoints[team];
261 }
262 
263 // selects a spawnpoint, preferring ones with heigher weights (or toward the beginning of the array if no weights).
264 // also does final things like setting self.lastspawnpoint to the one chosen.
265 // this takes care of avoiding telefragging, so it doesn't have to be considered by any other function.
266 function ‪getSpawnpoint_Final( spawnpoints, useweights )
267 {
268 
269  bestspawnpoint = undefined;
270 
271  if ( !isdefined( spawnpoints ) || spawnpoints.size == 0 )
272  return undefined;
273 
274  if ( !isdefined( useweights ) )
275  useweights = true;
276 
277  if ( useweights )
278  {
279  // choose spawnpoint with best weight
280  // (if a tie, choose randomly from the best)
281  bestspawnpoint = ‪getBestWeightedSpawnpoint( spawnpoints );
282  thread ‪spawnWeightDebug( spawnpoints );
283  }
284  else
285  {
286  // (only place we actually get here from is getSpawnpoint_Random() )
287  // no weights. prefer spawnpoints toward beginning of array
288  for ( i = 0; i < spawnpoints.size; i++ )
289  {
290  if( isdefined( self.lastspawnpoint ) && self.lastspawnpoint == spawnpoints[i] )
291  continue;
292 
293  if ( positionWouldTelefrag( spawnpoints[i].origin ) )
294  continue;
295 
296  bestspawnpoint = spawnpoints[i];
297  break;
298  }
299  if ( !isdefined( bestspawnpoint ) )
300  {
301  // Couldn't find a useable spawnpoint. All spawnpoints either telefragged or were our last spawnpoint
302  // Our only hope is our last spawnpoint - unless it too will telefrag...
303  if ( isdefined( self.lastspawnpoint ) && !positionWouldTelefrag( self.lastspawnpoint.origin ) )
304  {
305  // (make sure our last spawnpoint is in the valid array of spawnpoints to use)
306  for ( i = 0; i < spawnpoints.size; i++ )
307  {
308  if ( spawnpoints[i] == self.lastspawnpoint )
309  {
310  bestspawnpoint = spawnpoints[i];
311  break;
312  }
313  }
314  }
315  }
316  }
317 
318  if ( !isdefined( bestspawnpoint ) )
319  {
320  // couldn't find a useable spawnpoint! all will telefrag.
321  if ( useweights )
322  {
323  // at this point, forget about weights. just take a random one.
324  bestspawnpoint = spawnpoints[randomint(spawnpoints.size)];
325  }
326  else
327  {
328  bestspawnpoint = spawnpoints[0];
329  }
330  }
331 
332  self ‪finalizeSpawnpointChoice( bestspawnpoint );
333 
334  return bestspawnpoint;
335 }
336 
337 function ‪finalizeSpawnpointChoice( spawnpoint )
338 {
339  time = getTime();
340 
341  self.lastspawnpoint = spawnpoint;
342  self.lastspawntime = time;
343  spawnpoint.lastspawnedplayer = self;
344  spawnpoint.lastspawntime = time;
345 }
346 
347 function ‪getBestWeightedSpawnpoint( spawnpoints )
348 {
349  maxSightTracedSpawnpoints = 3;
350  for ( try = 0; try <= maxSightTracedSpawnpoints; try++ )
351  {
352  bestspawnpoints = [];
353  bestweight = undefined;
354  bestspawnpoint = undefined;
355  for ( i = 0; i < spawnpoints.size; i++ )
356  {
357  if ( !isdefined( bestweight ) || spawnpoints[i].weight > bestweight )
358  {
359  if ( positionWouldTelefrag( spawnpoints[i].origin ) )
360  continue;
361 
362  bestspawnpoints = [];
363  bestspawnpoints[0] = spawnpoints[i];
364  bestweight = spawnpoints[i].weight;
365  }
366  else if ( spawnpoints[i].weight == bestweight )
367  {
368  if ( positionWouldTelefrag( spawnpoints[i].origin ) )
369  continue;
370 
371  bestspawnpoints[bestspawnpoints.size] = spawnpoints[i];
372  }
373  }
374  if ( bestspawnpoints.size == 0 )
375  return undefined;
376 
377  // pick randomly from the available spawnpoints with the best weight
378  bestspawnpoint = bestspawnpoints[randomint( bestspawnpoints.size )];
379 
380  if ( try == maxSightTracedSpawnpoints )
381  return bestspawnpoint;
382 
383  if ( isdefined( bestspawnpoint.lastSightTraceTime ) && bestspawnpoint.lastSightTraceTime == gettime() )
384  return bestspawnpoint;
385 
386  if ( !‪lastMinuteSightTraces( bestspawnpoint ) )
387  return bestspawnpoint;
388 
389  penalty = ‪getLosPenalty();
390  bestspawnpoint.weight -= penalty;
391 
392  bestspawnpoint.lastSightTraceTime = gettime();
393  }
394 }
395 
396 function ‪getSpawnpoint_Random(spawnpoints)
397 {
398 // level endon("game_ended");
399 
400  // There are no valid spawnpoints in the map
401  if(!isdefined(spawnpoints))
402  return undefined;
403 
404  // randomize order
405  for(i = 0; i < spawnpoints.size; i++)
406  {
407  j = randomInt(spawnpoints.size);
408  spawnpoint = spawnpoints[i];
409  spawnpoints[i] = spawnpoints[j];
410  spawnpoints[j] = spawnpoint;
411  }
412 
413  return ‪getSpawnpoint_Final(spawnpoints, false);
414 }
415 
417 {
418  aliveplayers = [];
419 
420  // Make a list of fully connected, non-spectating, alive players
421  for(i = 0; i < level.players.size; i++)
422  {
423  if ( !isdefined( level.players[i] ) )
424  continue;
425  player = level.players[i];
426 
427  if ( player.sessionstate != "playing" || player == self )
428  continue;
429  if ( IsDefined(level.customAliveCheck) )
430  if ( ! [[level.customAliveCheck]]( player ) )
431  continue;
432 
433  aliveplayers[aliveplayers.size] = player;
434  }
435  return aliveplayers;
436 }
437 
438 
440 {
441  if ( level.teambased )
442  {
443  assert( isdefined( level.teams[self.team] ) );
444 
445  obj.allies = [];
446  obj.enemies = [];
447 
448  for(i = 0; i < level.players.size; i++)
449  {
450  if ( !isdefined( level.players[i] ) )
451  continue;
452  player = level.players[i];
453 
454  if ( player.sessionstate != "playing" || player == self )
455  continue;
456  if ( IsDefined(level.customAliveCheck) )
457  if ( ! [[level.customAliveCheck]]( player ) )
458  continue;
459 
460  if (player.team == self.team)
461  obj.allies[obj.allies.size] = player;
462  else
463  obj.enemies[obj.enemies.size] = player;
464 
465  }
466 
467 /*
468  obj.allies = level.alivePlayers[self.team];
469 
470  obj.enemies = undefined;
471  foreach( team in level.teams )
472  {
473  if ( team == self.team )
474  continue;
475 
476  if ( !isdefined( obj.enemies ) )
477  {
478  obj.enemies = level.alivePlayers[team];
479  }
480  else
481  {
482  foreach( player in level.alivePlayers[team] )
483  {
484  obj.enemies[obj.enemies.size] = player;
485  }
486  }
487  }
488 */
489  }
490  else
491  {
492  obj.allies = [];
493  obj.enemies = level.activePlayers;
494  }
495 }
496 
497 // weight array manipulation code
498 function ‪initWeights(spawnpoints)
499 {
500  for (i = 0; i < spawnpoints.size; i++)
501  spawnpoints[i].weight = 0;
502 }
503 
504 
505 function ‪spawnPointUpdate_zm( spawnpoint )
506 {
507  foreach( team in level.teams )
508  {
509  spawnpoint.distSum[ team ]=0;
510  spawnpoint.enemyDistSum[ team ]=0;
511  }
512  players = GetPlayers();
513  spawnpoint.numPlayersAtLastUpdate = players.size;
514  foreach(player in players)
515  {
516  if ( !isdefined( player ) )
517  continue;
518  if ( player.sessionstate != "playing" )
519  continue;
520  if ( IsDefined(level.customAliveCheck) )
521  if ( ! [[level.customAliveCheck]]( player ) )
522  continue;
523  dist = distance( spawnpoint.origin, player.origin );
524  spawnpoint.distSum[ player.team ]+=dist;
525  foreach( team in level.teams )
526  {
527  if (team != player.team )
528  spawnpoint.enemyDistSum[ team ]+=dist;
529  }
530  }
531 }
532 
533 // ================================================
534 
535 
536 function ‪getSpawnpoint_NearTeam( spawnpoints, favoredspawnpoints, forceAllyDistanceWeight, forceEnemyDistanceWeight )
537 {
538 // level endon("game_ended");
539 
540  /*if ( self.wantSafeSpawn )
541  {
542  return getSpawnpoint_SafeSpawn( spawnpoints );
543  }*/
544 
545  // There are no valid spawnpoints in the map
546  if(!isdefined(spawnpoints))
547  return undefined;
548 
549  if ( GetDvarint( "scr_spawnsimple") > 0 )
550  return ‪getSpawnpoint_Random( spawnpoints );
551 
553 
554  k_favored_spawn_point_bonus= 25000;
555 
556  ‪initWeights(spawnpoints);
557 
558  obj = spawnstruct();
560 
561  numplayers = obj.allies.size + obj.enemies.size;
562 
563  alliedDistanceWeight = 2;
564  if (IsDefined(forceAllyDistanceWeight))
565  alliedDistanceWeight = forceAllyDistanceWeight;
566 
567  enemyDistanceWeight = 1;
568  if (IsDefined(forceEnemyDistanceWeight))
569  enemyDistanceWeight = forceEnemyDistanceWeight;
570 
571  myTeam = self.team;
572  for (i = 0; i < spawnpoints.size; i++)
573  {
574  spawnpoint = spawnpoints[i];
575 
576  ‪spawnPointUpdate_zm( spawnpoint );
577 
578  if (!IsDefined(spawnpoint.numPlayersAtLastUpdate))
579  {
580  spawnpoint.numPlayersAtLastUpdate= 0;
581  }
582 
583  if ( spawnpoint.numPlayersAtLastUpdate > 0 )
584  {
585  allyDistSum = spawnpoint.distSum[ myTeam ];
586  enemyDistSum = spawnpoint.enemyDistSum[ myTeam ];
587 
588  // high enemy distance is good, high ally distance is bad
589  spawnpoint.weight = (enemyDistanceWeight*enemyDistSum - alliedDistanceWeight*allyDistSum) / spawnpoint.numPlayersAtLastUpdate;
590  }
591  else
592  {
593  spawnpoint.weight = 0;
594  }
595  }
596 
597  if (isdefined(favoredspawnpoints))
598  {
599  for (i= 0; i < favoredspawnpoints.size; i++)
600  {
601  if (isdefined(favoredspawnpoints[i].weight))
602  {
603  favoredspawnpoints[i].weight+= k_favored_spawn_point_bonus;
604  }
605  else
606  {
607  favoredspawnpoints[i].weight= k_favored_spawn_point_bonus;
608  }
609  }
610  }
611 
612 
613 
614  ‪avoidSameSpawn(spawnpoints);
615  ‪avoidSpawnReuse(spawnpoints, true);
616  // not avoiding spawning near recent deaths for team-based modes. kills the fast pace.
617  //avoidDangerousSpawns(spawnpoints, true);
618  ‪avoidWeaponDamage(spawnpoints);
619  ‪avoidVisibleEnemies(spawnpoints, true);
620 
621 
622  ‪result = ‪getSpawnpoint_Final(spawnpoints);
623 
624  return ‪result;
625 }
626 
628 
629 function ‪getSpawnpoint_DM(spawnpoints)
630 {
631 // level endon("game_ended");
632 
633  /*if ( self.wantSafeSpawn )
634  {
635  return getSpawnpoint_SafeSpawn( spawnpoints );
636  }*/
637 
638  // There are no valid spawnpoints in the map
639  if(!isdefined(spawnpoints))
640  return undefined;
641 
643 
644  ‪initWeights(spawnpoints);
645 
646  aliveplayers = ‪getAllOtherPlayers();
647 
648  // new logic: we want most players near idealDist units away.
649  // players closer than badDist units will be considered negatively
650  idealDist = 1600;
651  badDist = 1200;
652 
653  if (aliveplayers.size > 0)
654  {
655  for (i = 0; i < spawnpoints.size; i++)
656  {
657  totalDistFromIdeal = 0;
658  nearbyBadAmount = 0;
659  for (j = 0; j < aliveplayers.size; j++)
660  {
661  dist = distance(spawnpoints[i].origin, aliveplayers[j].origin);
662 
663  if (dist < badDist )
664  nearbyBadAmount += (badDist - dist) / badDist;
665 
666  distfromideal = abs(dist - idealDist);
667  totalDistFromIdeal += distfromideal;
668  }
669  avgDistFromIdeal = totalDistFromIdeal / aliveplayers.size;
670 
671  wellDistancedAmount = (idealDist - avgDistFromIdeal) / idealDist;
672  // if (wellDistancedAmount < 0) wellDistancedAmount = 0;
673 
674  // wellDistancedAmount is between -inf and 1, 1 being best (likely around 0 to 1)
675  // nearbyBadAmount is between 0 and inf,
676  // and it is very important that we get a bad weight if we have a high nearbyBadAmount.
677 
678  spawnpoints[i].weight = wellDistancedAmount - nearbyBadAmount * 2 + randomfloat(.2);
679  }
680  }
681 
682  ‪avoidSameSpawn(spawnpoints);
683  ‪avoidSpawnReuse(spawnpoints, false);
684  //avoidDangerousSpawns(spawnpoints, false);
685  ‪avoidWeaponDamage(spawnpoints);
686  ‪avoidVisibleEnemies(spawnpoints, false);
687 
688  return ‪getSpawnpoint_Final(spawnpoints);
689 }
690 
692 //
693 // Hybrid of NearTeam and DM
694 //
695 
696 
697 function ‪getSpawnpoint_Turned( spawnpoints, idealDist, badDist, idealDistTeam, badDistTeam )
698 {
699 // level endon("game_ended");
700 
701  /*if ( self.wantSafeSpawn )
702  {
703  return getSpawnpoint_SafeSpawn( spawnpoints );
704  }*/
705 
706  // There are no valid spawnpoints in the map
707  if(!isdefined(spawnpoints))
708  return undefined;
709 
711 
712  ‪initWeights(spawnpoints);
713 
714  aliveplayers = ‪getAllOtherPlayers();
715 
716  // new logic: we want most players near idealDist units away.
717  // players closer than badDist units will be considered negatively
718  if (!isDefined(idealDist))
719  idealDist = 1600;
720  if (!isDefined(idealDistTeam))
721  idealDistTeam = 1200;
722  if (!isDefined(badDist))
723  badDist = 1200;
724  if (!isDefined(badDistTeam))
725  badDistTeam = 600;
726 
727  myTeam = self.team;
728  if (aliveplayers.size > 0)
729  {
730  for (i = 0; i < spawnpoints.size; i++)
731  {
732  totalDistFromIdeal = 0;
733  nearbyBadAmount = 0;
734  for (j = 0; j < aliveplayers.size; j++)
735  {
736  dist = distance(spawnpoints[i].origin, aliveplayers[j].origin);
737  distfromideal = 0;
738 
739  if ( aliveplayers[j].team == myTeam )
740  {
741  if (dist < badDistTeam )
742  nearbyBadAmount += (badDistTeam - dist) / badDistTeam;
743  distfromideal = abs(dist - idealDistTeam);
744  }
745  else
746  {
747  if (dist < badDist )
748  nearbyBadAmount += (badDist - dist) / badDist;
749  distfromideal = abs(dist - idealDist);
750  }
751 
752  totalDistFromIdeal += distfromideal;
753  }
754  avgDistFromIdeal = totalDistFromIdeal / aliveplayers.size;
755 
756  wellDistancedAmount = (idealDist - avgDistFromIdeal) / idealDist;
757  // if (wellDistancedAmount < 0) wellDistancedAmount = 0;
758 
759  // wellDistancedAmount is between -inf and 1, 1 being best (likely around 0 to 1)
760  // nearbyBadAmount is between 0 and inf,
761  // and it is very important that we get a bad weight if we have a high nearbyBadAmount.
762 
763  spawnpoints[i].weight = wellDistancedAmount - nearbyBadAmount * 2 + randomfloat(.2);
764  }
765  }
766 
767  ‪avoidSameSpawn(spawnpoints);
768  ‪avoidSpawnReuse(spawnpoints, false);
769  //avoidDangerousSpawns(spawnpoints, false);
770  ‪avoidWeaponDamage(spawnpoints);
771  ‪avoidVisibleEnemies(spawnpoints, false);
772 
773  return ‪getSpawnpoint_Final(spawnpoints);
774 }
775 
776 // =============================================
777 
778 // called at the start of every spawn
780 {
781  //updateDeathInfo();
782 
783 }
784 
785 // DEBUG
787 {
788 }
789 // DEBUG
791 {
792  while(1)
793  {
794  if (GetDvarString( "scr_spawnpointdebug") == "0") {
795  wait(3);
796  continue;
797  }
799  wait(3);
800  }
801 }
802 // DEBUG
803 function ‪spawnWeightDebug(spawnpoints)
804 {
805  level notify("stop_spawn_weight_debug");
806  level endon("stop_spawn_weight_debug");
807 }
808 // DEBUG
809 function ‪profileDebug()
810 {
811  while(1)
812  {
813  if (GetDvarString( "scr_spawnpointprofile") != "1") {
814  wait(3);
815  continue;
816  }
817 
818  for (i = 0; i < level.spawnpoints.size; i++)
819  level.spawnpoints[i].weight = randomint(10000);
820  if (level.players.size > 0)
821  level.players[randomint(level.players.size)] ‪getSpawnpoint_NearTeam(level.spawnpoints);
822 
823  wait(.05);
824  }
825 }
826 // DEBUG
827 function ‪debugNearbyPlayers(players, origin)
828 {
829 }
830 
831 function ‪deathOccured(dier, killer)
832 {
833  /*if (!isdefined(killer) || !isdefined(dier) || !isplayer(killer) || !isplayer(dier) || killer == dier)
834  return;
835 
836  time = getTime();
837 
838  // DEBUG
839  // check if there was a spawn kill
840  if (time - dier.lastspawntime < 5*1000 && distance(dier.origin, dier.lastspawnpoint.origin) < 300)
841  {
842  spawnkill = spawnstruct();
843  spawnkill.dierwasspawner = true;
844  spawnkill.dierorigin = dier.origin;
845  spawnkill.killerorigin = killer.origin;
846  spawnkill.spawnpointorigin = dier.lastspawnpoint.origin;
847  spawnkill.time = time;
848  level.spawnlogic_spawnkills[level.spawnlogic_spawnkills.size] = spawnkill;
849  }
850  else if (time - killer.lastspawntime < 5*1000 && distance(killer.origin, killer.lastspawnpoint.origin) < 300)
851  {
852  spawnkill = spawnstruct();
853  spawnkill.dierwasspawner = false;
854  spawnkill.dierorigin = dier.origin;
855  spawnkill.killerorigin = killer.origin;
856  spawnkill.spawnpointorigin = killer.lastspawnpoint.origin;
857  spawnkill.time = time;
858  level.spawnlogic_spawnkills[level.spawnlogic_spawnkills.size] = spawnkill;
859  }
860 
861  // record kill information
862  deathInfo = spawnstruct();
863 
864  deathInfo.time = time;
865  deathInfo.org = dier.origin;
866  deathInfo.killOrg = killer.origin;
867  deathInfo.killer = killer;
868 
869  checkForSimilarDeaths(deathInfo);
870  level.spawnlogic_deaths[level.spawnlogic_deaths.size] = deathInfo;
871 
872  // keep track of the most dangerous players in terms of how far they have killed people recently
873  dist = distance(dier.origin, killer.origin);
874  if (!isdefined(killer.spawnlogic_killdist) || time - killer.spawnlogic_killtime > 1000*30 || dist > killer.spawnlogic_killdist)
875  {
876  killer.spawnlogic_killdist = dist;
877  killer.spawnlogic_killtime = time;
878  }*/
879 }
880 function ‪checkForSimilarDeaths(deathInfo)
881 {
882  // check if this is really similar to any old deaths, and if so, mark them for removal later
883  for (i = 0; i < level.spawnlogic_deaths.size; i++)
884  {
885  if (level.spawnlogic_deaths[i].killer == deathInfo.killer)
886  {
887  dist = distance(level.spawnlogic_deaths[i].org, deathInfo.org);
888  if (dist > 200) continue;
889  dist = distance(level.spawnlogic_deaths[i].killOrg, deathInfo.killOrg);
890  if (dist > 200) continue;
891 
892  level.spawnlogic_deaths[i].remove = true;
893  }
894  }
895 }
896 
898 {
899 
900  time = getTime();
901  for (i = 0; i < level.spawnlogic_deaths.size; i++)
902  {
903  // if the killer has walked away or enough time has passed, get rid of this death information
904  deathInfo = level.spawnlogic_deaths[i];
905 
906  if (time - deathInfo.time > 1000*90 || // if 90 seconds have passed
907  !isdefined(deathInfo.killer) ||
908  !isalive(deathInfo.killer) ||
909  (!isdefined( level.teams[deathInfo.killer.team] )) ||
910  distance(deathInfo.killer.origin, deathInfo.killOrg) > 400) {
911  level.spawnlogic_deaths[i].remove = true;
912  }
913  }
914 
915  // remove all deaths with remove set
916  oldarray = level.spawnlogic_deaths;
917  level.spawnlogic_deaths = [];
918 
919  // never keep more than the 1024 most recent entries in the array
920  start = 0;
921  if (oldarray.size - 1024 > 0) start = oldarray.size - 1024;
922 
923  for (i = start; i < oldarray.size; i++)
924  {
925  if (!isdefined(oldarray[i].‪remove))
926  level.spawnlogic_deaths[level.spawnlogic_deaths.size] = oldarray[i];
927  }
928 
929 }
930 
931 /*
932 // uses death information to reduce the weights of spawns that might cause spawn kills
933 function avoidDangerousSpawns(spawnpoints, teambased) // (assign weights to the return value of this)
934 {
935  // DEBUG
936  if (GetDvarString( "scr_spawnpointnewlogic") == "0") {
937  return;
938  }
939 
940  // DEBUG
941 
942  deathpenalty = 100000;
943  if (GetDvarString( "scr_spawnpointdeathpenalty") != "" && GetDvarString( "scr_spawnpointdeathpenalty") != "0")
944  deathpenalty = GetDvarfloat( "scr_spawnpointdeathpenalty");
945 
946  maxDist = 200;
947  if (GetDvarString( "scr_spawnpointmaxdist") != "" && GetDvarString( "scr_spawnpointmaxdist") != "0")
948  maxdist = GetDvarfloat( "scr_spawnpointmaxdist");
949 
950  maxDistSquared = maxDist*maxDist;
951  for (i = 0; i < spawnpoints.size; i++)
952  {
953  for (d = 0; d < level.spawnlogic_deaths.size; d++)
954  {
955  // (we've got a lotta checks to do, want to rule them out quickly)
956  distSqrd = distanceSquared(spawnpoints[i].origin, level.spawnlogic_deaths[d].org);
957  if (distSqrd > maxDistSquared)
958  continue;
959 
960  // make sure the killer in question is on the opposing team
961  player = level.spawnlogic_deaths[d].killer;
962  if (!isalive(player)) continue;
963  if (player == self) continue;
964  if (teambased && player.team == self.team) continue;
965 
966  // (no sqrt, must recalculate distance)
967  dist = distance(spawnpoints[i].origin, level.spawnlogic_deaths[d].org);
968  spawnpoints[i].weight -= (1 - dist/maxDist) * deathpenalty; // possible spawn kills are *really* bad
969  }
970  }
971 
972  // DEBUG
973 }
974 */
975 
976 
977 // used by spawning; needs to be fast.
978 function ‪isPointVulnerable(playerorigin)
979 {
980  pos = self.origin + level.bettymodelcenteroffset;
981  playerpos = playerorigin + (0,0,32);
982  distsqrd = distancesquared(pos, playerpos);
983 
984  forward = anglestoforward(self.angles);
985 
986  if (distsqrd < level.bettyDetectionRadius*level.bettyDetectionRadius)
987  {
988  playerdir = vectornormalize(playerpos - pos);
989  angle = acos(vectordot(playerdir, forward));
990  if (angle < level.bettyDetectionConeAngle) {
991  return true;
992  }
993  }
994  return false;
995 }
996 
997 
998 function ‪avoidWeaponDamage(spawnpoints)
999 {
1000  if (GetDvarString( "scr_spawnpointnewlogic") == "0")
1001  {
1002  return;
1003  }
1004 
1005 
1006  weaponDamagePenalty = 100000;
1007  if (GetDvarString( "scr_spawnpointweaponpenalty") != "" && GetDvarString( "scr_spawnpointweaponpenalty") != "0")
1008  weaponDamagePenalty = GetDvarfloat( "scr_spawnpointweaponpenalty");
1009 
1010  mingrenadedistsquared = 250*250; // (actual grenade radius is 220, 250 includes a safety area of 30 units)
1011 
1012  for (i = 0; i < spawnpoints.size; i++)
1013  {
1014  for (j = 0; j < level.grenades.size; j++)
1015  {
1016  if ( !isdefined( level.grenades[j] ) )
1017  continue;
1018 
1019  // could also do a sight check to see if it's really dangerous.
1020  if (distancesquared(spawnpoints[i].origin, level.grenades[j].origin) < mingrenadedistsquared)
1021  {
1022  spawnpoints[i].weight -= weaponDamagePenalty;
1023  }
1024  }
1025  }
1026 
1027 }
1028 
1030 {
1031  spawnpointindex = 0;
1032 
1033  // each frame, do sight checks against a spawnpoint
1034 
1035  while(1)
1036  {
1037  wait .05;
1038 
1039 
1040  //time = gettime();
1041 
1042  if ( !isdefined( level.spawnPoints ) )
1043  return;
1044 
1045  spawnpointindex = (spawnpointindex + 1) % level.spawnPoints.size;
1046  spawnpoint = level.spawnPoints[spawnpointindex];
1047 
1048  ‪spawnPointUpdate( spawnpoint );
1049 
1050  }
1051 }
1052 
1053 function ‪getNonTeamSum( skip_team, sums )
1054 {
1055  value = 0;
1056  foreach( team in level.teams )
1057  {
1058  if ( team == skip_team )
1059  continue;
1060 
1061  value += sums[team];
1062  }
1063 
1064  return value;
1065 }
1066 
1067 function ‪getNonTeamMinDist( skip_team, minDists )
1068 {
1069  dist = 9999999;
1070  foreach( team in level.teams )
1071  {
1072  if ( team == skip_team )
1073  continue;
1074 
1075  if ( dist > minDists[team] )
1076  dist = minDists[team];
1077  }
1078 
1079  return dist;
1080 }
1081 
1082 
1083 function ‪spawnPointUpdate( spawnpoint )
1084 {
1085  if ( level.teambased )
1086  {
1087  sights = [];
1088  foreach( team in level.teams )
1089  {
1090  spawnpoint.enemySights[team] = 0;
1091  sights[team] = 0;
1092  spawnpoint.nearbyPlayers[team] = [];
1093  }
1094  }
1095  else
1096  {
1097  spawnpoint.enemySights = 0;
1098 
1099  spawnpoint.nearbyPlayers["all"] = [];
1100  }
1101 
1102  spawnpointdir = spawnpoint.forward;
1103 
1104  debug = false;
1105 
1106  minDist = [];
1107  distSum = [];
1108 
1109  if ( !level.teambased )
1110  {
1111  minDist["all"] = 9999999;
1112  }
1113 
1114  foreach( team in level.teams )
1115  {
1116  spawnpoint.distSum[team] = 0;
1117  spawnpoint.enemyDistSum[team] = 0;
1118  spawnpoint.minEnemyDist[team] = 9999999;
1119  minDist[team] = 9999999;
1120  }
1121 
1122  spawnpoint.numPlayersAtLastUpdate = 0;
1123 
1124  for (i = 0; i < level.players.size; i++)
1125  {
1126  player = level.players[i];
1127 
1128  if ( player.sessionstate != "playing" )
1129  continue;
1130 
1131  diff = player.origin - spawnpoint.origin;
1132  diff = (diff[0], diff[1], 0);
1133  dist = length( diff ); // needs to be actual distance for distSum value
1134 
1135  team = "all";
1136  if ( level.teambased )
1137  team = player.team;
1138 
1139  if ( dist < 1024 )
1140  {
1141  spawnpoint.nearbyPlayers[team][spawnpoint.nearbyPlayers[team].size] = player;
1142  }
1143 
1144  if ( dist < minDist[team] )
1145  minDist[team] = dist;
1146 
1147  distSum[ team ] += dist;
1148  spawnpoint.numPlayersAtLastUpdate++;
1149 
1150  pdir = anglestoforward(player.angles);
1151  if (vectordot(spawnpointdir, diff) < 0 && vectordot(pdir, diff) > 0)
1152  continue; // player and spawnpoint are looking in opposite directions
1153 
1154  // do sight check
1155  losExists = bullettracepassed(player.origin + (0,0,50), spawnpoint.sightTracePoint, false, undefined);
1156 
1157  spawnpoint.lastSightTraceTime = gettime();
1158 
1159  if (losExists)
1160  {
1161  if ( level.teamBased )
1162  sights[player.team]++;
1163  else
1164  spawnpoint.enemySights++;
1165 
1166  // DEBUG
1167  //println("Sight check succeeded!");
1168 
1169  /*
1170  death info stuff is disabled right now
1171  // pretend this player killed a person at this spawnpoint, so we don't try to use it again any time soon.
1172  deathInfo = spawnstruct();
1173 
1174  deathInfo.time = time;
1175  deathInfo.org = spawnpoint.origin;
1176  deathInfo.killOrg = player.origin;
1177  deathInfo.killer = player;
1178  deathInfo.los = true;
1179 
1180  checkForSimilarDeaths(deathInfo);
1181  level.spawnlogic_deaths[level.spawnlogic_deaths.size] = deathInfo;
1182  */
1183 
1184  }
1185  //else
1186  // line(player.origin + (0,0,50), spawnpoint.sightTracePoint, (1,.5,.5));
1187  }
1188 
1189  if ( level.teamBased )
1190  {
1191  foreach( team in level.teams )
1192  {
1193  spawnpoint.enemySights[team] = ‪getNonTeamSum( team, sights );
1194  spawnpoint.minEnemyDist[team] = ‪getNonTeamMinDist( team, minDist );
1195  spawnpoint.distSum[team] = distSum[team];
1196  spawnpoint.enemyDistSum[team] = ‪getNonTeamSum( team, distSum);
1197  }
1198  }
1199  else
1200  {
1201  spawnpoint.distSum["all"] = distSum["all"];
1202  spawnpoint.enemyDistSum["all"] = distSum["all"];
1203  spawnpoint.minEnemyDist["all"] = minDist["all"];
1204  }
1205 
1206 }
1207 
1209 {
1210  if (GetDvarString( "scr_spawnpointlospenalty") != "" && GetDvarString( "scr_spawnpointlospenalty") != "0")
1211  return GetDvarfloat( "scr_spawnpointlospenalty");
1212  return 100000;
1213 }
1214 
1215 function ‪lastMinuteSightTraces( spawnpoint )
1216 {
1217  if ( !isdefined( spawnpoint.nearbyPlayers ) )
1218  return false;
1219 
1220  closest = undefined;
1221  closestDistsq = undefined;
1222  secondClosest = undefined;
1223  secondClosestDistsq = undefined;
1224 
1225  foreach( team in spawnpoint.nearbyPlayers )
1226  {
1227  if ( team == self.team )
1228  continue;
1229 
1230  for ( i = 0; i < spawnpoint.nearbyPlayers[team].size; i++ )
1231  {
1232  player = spawnpoint.nearbyPlayers[team][i];
1233 
1234  if ( !isdefined( player ) )
1235  continue;
1236  if ( player.sessionstate != "playing" )
1237  continue;
1238  if ( player == self )
1239  continue;
1240 
1241  distsq = distanceSquared( spawnpoint.origin, player.origin );
1242  if ( !isdefined( closest ) || distsq < closestDistsq )
1243  {
1244  secondClosest = closest;
1245  secondClosestDistsq = closestDistsq;
1246 
1247  closest = player;
1248  closestDistSq = distsq;
1249  }
1250  else if ( !isdefined( secondClosest ) || distsq < secondClosestDistSq )
1251  {
1252  secondClosest = player;
1253  secondClosestDistSq = distsq;
1254  }
1255  }
1256  }
1257 
1258  if ( isdefined( closest ) )
1259  {
1260  if ( bullettracepassed( closest.origin + (0,0,50), spawnpoint.sightTracePoint, false, undefined) )
1261  return true;
1262  }
1263  if ( isdefined( secondClosest ) )
1264  {
1265  if ( bullettracepassed( secondClosest.origin + (0,0,50), spawnpoint.sightTracePoint, false, undefined) )
1266  return true;
1267  }
1268 
1269  return false;
1270 }
1271 
1272 
1273 
1274 function ‪avoidVisibleEnemies(spawnpoints, teambased)
1275 {
1276  if (GetDvarString( "scr_spawnpointnewlogic") == "0")
1277  {
1278  return;
1279  }
1280 
1281  // DEBUG
1282 
1283  lospenalty = ‪getLosPenalty();
1284 
1285  minDistTeam = self.team;
1286 
1287  if ( teambased )
1288  {
1289  for ( i = 0; i < spawnpoints.size; i++ )
1290  {
1291  if ( !isdefined(spawnpoints[i].enemySights) )
1292  continue;
1293 
1294  penalty = lospenalty * spawnpoints[i].enemySights[self.team];
1295  spawnpoints[i].weight -= penalty;
1296  }
1297  }
1298  else
1299  {
1300  for ( i = 0; i < spawnpoints.size; i++ )
1301  {
1302  if ( !isdefined(spawnpoints[i].enemySights) )
1303  continue;
1304 
1305  penalty = lospenalty * spawnpoints[i].enemySights;
1306  spawnpoints[i].weight -= penalty;
1307  }
1308 
1309  minDistTeam = "all";
1310  }
1311 
1312  avoidWeight = GetDvarfloat( "scr_spawn_enemyavoidweight");
1313  if ( avoidWeight != 0 )
1314  {
1315  nearbyEnemyOuterRange = GetDvarfloat( "scr_spawn_enemyavoiddist");
1316  nearbyEnemyOuterRangeSq = nearbyEnemyOuterRange * nearbyEnemyOuterRange;
1317  nearbyEnemyPenalty = 1500 * avoidWeight; // typical base weights tend to peak around 1500 or so. this is large enough to upset that while only locally dominating it.
1318  nearbyEnemyMinorPenalty = 800 * avoidWeight; // additional negative weight for distances up to 2 * nearbyEnemyOuterRange
1319 
1320  lastAttackerOrigin = (-99999,-99999,-99999);
1321  lastDeathPos = (-99999,-99999,-99999);
1322  if ( isAlive( self.lastAttacker ) )
1323  lastAttackerOrigin = self.lastAttacker.origin;
1324  ‪if ( isdefined( self.lastDeathPos ) )
1325  lastDeathPos = self.lastDeathPos;
1326 
1327  for ( i = 0; i < spawnpoints.size; i++ )
1328  {
1329  // penalty for nearby enemies
1330  mindist = spawnpoints[i].minEnemyDist[minDistTeam];
1331  if ( mindist < nearbyEnemyOuterRange*2 )
1332  {
1333  penalty = nearbyEnemyMinorPenalty * (1 - mindist / (nearbyEnemyOuterRange*2));
1334  if ( mindist < nearbyEnemyOuterRange )
1335  penalty += nearbyEnemyPenalty * (1 - mindist / nearbyEnemyOuterRange);
1336  if ( penalty > 0 )
1337  {
1338  spawnpoints[i].weight -= penalty;
1339  }
1340  }
1341 
1342  /*
1343  // additional penalty for being near the guy who just killed me
1344  distSq = distanceSquared( lastAttackerOrigin, spawnpoints[i].origin );
1345  if ( distSq < nearbyEnemyOuterRangeSq )
1346  {
1347  penalty = nearbyEnemyPenalty * (1 - sqrt( distSq ) / nearbyEnemyOuterRange);
1348  assert( penalty > 0 );
1349  spawnpoints[i].weight -= penalty;
1350  }
1351  */
1352 
1353  /*
1354  // penalty for being near where i just died
1355  distSq = distanceSquared( lastDeathPos, spawnpoints[i].origin );
1356  if ( distSq < nearbyEnemyOuterRangeSq )
1357  {
1358  penalty = nearbyEnemyPenalty * (1 - sqrt( distSq ) / nearbyEnemyOuterRange);
1359  assert( penalty > 0 );
1360  spawnpoints[i].weight -= penalty;
1361  }
1362  */
1363  }
1364  }
1365 
1366  // DEBUG
1367 }
1368 
1369 function ‪avoidSpawnReuse(spawnpoints, teambased)
1370 {
1371  // DEBUG
1372  if (GetDvarString( "scr_spawnpointnewlogic") == "0") {
1373  return;
1374  }
1375 
1376 
1377  time = getTime();
1378 
1379  maxtime = 10*1000;
1380  maxdistSq = 1024 * 1024;
1381 
1382  for (i = 0; i < spawnpoints.size; i++)
1383  {
1384  spawnpoint = spawnpoints[i];
1385 
1386  if (!isdefined(spawnpoint.lastspawnedplayer) || !isdefined(spawnpoint.lastspawntime) ||
1387  !isalive(spawnpoint.lastspawnedplayer))
1388  continue;
1389 
1390  if (spawnpoint.lastspawnedplayer == self)
1391  continue;
1392  if (teambased && spawnpoint.lastspawnedplayer.team == self.team)
1393  continue;
1394 
1395  timepassed = time - spawnpoint.lastspawntime;
1396  if (timepassed < maxtime)
1397  {
1398  distSq = distanceSquared(spawnpoint.lastspawnedplayer.origin, spawnpoint.origin);
1399  if (distSq < maxdistSq)
1400  {
1401  worsen = 5000 * (1 - distSq/maxdistSq) * (1 - timepassed/maxtime);
1402  spawnpoint.weight -= worsen;
1403  }
1404  else
1405  spawnpoint.lastspawnedplayer = undefined; // don't worry any more about this spawnpoint
1406  }
1407  else
1408  spawnpoint.lastspawnedplayer = undefined; // don't worry any more about this spawnpoint
1409  }
1410 
1411 }
1412 
1413 function ‪avoidSameSpawn(spawnpoints)
1414 {
1415  // DEBUG
1416  if (GetDvarString( "scr_spawnpointnewlogic") == "0") {
1417  return;
1418  }
1419 
1420 
1421  if (!isdefined(self.lastspawnpoint))
1422  return;
1423 
1424  for (i = 0; i < spawnpoints.size; i++)
1425  {
1426  if (spawnpoints[i] == self.lastspawnpoint)
1427  {
1428  spawnpoints[i].weight -= 50000; // (half as bad as a likely spawn kill)
1429  break;
1430  }
1431  }
1432 
1433 }
1434 
1436 {
1437  spawnpoints = getentarray("mp_global_intermission", "classname");
1438  if ( !spawnpoints.size )
1439  {
1440  spawnpoints = getentarray("info_player_start", "classname");
1441  }
1442  assert( spawnpoints.size );
1443  spawnpoint = ‪spawnlogic::getSpawnpoint_Random(spawnpoints);
1444 
1445  return spawnpoint;
1446 }
‪getSpawnpointArray
‪function getSpawnpointArray(classname)
Definition: _spawnlogic.gsc:208
‪getLosPenalty
‪function getLosPenalty()
Definition: _spawnlogic.gsc:1208
‪spawnWeightDebug
‪function spawnWeightDebug(spawnpoints)
Definition: _spawnlogic.gsc:803
‪getNonTeamSum
‪function getNonTeamSum(skip_team, sums)
Definition: _spawnlogic.gsc:1053
‪getAllAlliedAndEnemyPlayers
‪function getAllAlliedAndEnemyPlayers(obj)
Definition: _spawnlogic.gsc:439
‪expandMins
‪function expandMins(mins, point)
Definition: _spawnlogic.gsc:55
‪getSpawnpoint_Final
‪function getSpawnpoint_Final(spawnpoints, useweights)
Definition: _spawnlogic.gsc:266
‪getSpawnpoint_DM
‪function getSpawnpoint_DM(spawnpoints)
Definition: _spawnlogic.gsc:629
‪spawnPerFrameUpdate
‪function spawnPerFrameUpdate()
Definition: _spawnlogic.gsc:1029
‪findBoxCenter
‪function findBoxCenter(mins, maxs)
Definition: _spawnlogic.gsc:47
‪addSpawnPointClassName
‪function addSpawnPointClassName(spawnPointClassName)
Definition: _spawnlogic.gsc:193
‪updateDeathInfoDebug
‪function updateDeathInfoDebug()
Definition: _spawnlogic.gsc:790
‪Spawnlogic_Begin
‪function Spawnlogic_Begin()
Definition: _spawnlogic.gsc:779
‪avoidWeaponDamage
‪function avoidWeaponDamage(spawnpoints)
Definition: _spawnlogic.gsc:998
‪main
‪function main()
Definition: _spawnlogic.gsc:19
‪showDeathsDebug
‪function showDeathsDebug()
Definition: _spawnlogic.gsc:786
‪on_start_gametype
‪function on_start_gametype(func, obj)
Definition: callbacks_shared.csc:285
‪getSpawnpoint_Turned
‪function getSpawnpoint_Turned(spawnpoints, idealDist, badDist, idealDistTeam, badDistTeam)
Definition: _spawnlogic.gsc:697
‪__init__
‪function __init__()
Definition: _spawnlogic.gsc:16
‪dropSpawnPoints
‪function dropSpawnPoints(spawnPointName)
Definition: _spawnlogic.gsc:178
‪remove
‪function remove(weapon)
Definition: aat_shared.gsc:499
‪spawnPointInit
‪function spawnPointInit()
Definition: _spawnlogic.gsc:223
‪if
‪if(on_off)
Definition: util_shared.csc:908
‪getNonTeamMinDist
‪function getNonTeamMinDist(skip_team, minDists)
Definition: _spawnlogic.gsc:1067
‪getSpawnpoint_NearTeam
‪function getSpawnpoint_NearTeam(spawnpoints, favoredspawnpoints, forceAllyDistanceWeight, forceEnemyDistanceWeight)
Definition: _spawnlogic.gsc:536
‪getAllOtherPlayers
‪function getAllOtherPlayers()
Definition: _spawnlogic.gsc:416
‪addSpawnPointTeamClassName
‪function addSpawnPointTeamClassName(team, spawnPointClassName)
Definition: _spawnlogic.gsc:203
‪clearSpawnPoints
‪function clearSpawnPoints()
Definition: _spawnlogic.gsc:120
‪getBestWeightedSpawnpoint
‪function getBestWeightedSpawnpoint(spawnpoints)
Definition: _spawnlogic.gsc:347
‪avoidSpawnReuse
‪function avoidSpawnReuse(spawnpoints, teambased)
Definition: _spawnlogic.gsc:1369
‪finalizeSpawnpointChoice
‪function finalizeSpawnpointChoice(spawnpoint)
Definition: _spawnlogic.gsc:337
‪getSpawnpoint_Random
‪function getSpawnpoint_Random(spawnpoints)
Definition: _spawnlogic.gsc:396
‪addSpawnPointsInternal
‪function addSpawnPointsInternal(team, spawnPointName)
Definition: _spawnlogic.gsc:78
‪REGISTER_SYSTEM
‪#define REGISTER_SYSTEM(__sys, __func_init_preload, __reqs)
Definition: shared.gsh:204
‪abort_level
‪function abort_level()
Definition: callbacks_shared.gsc:1018
‪expandMaxs
‪function expandMaxs(maxs, point)
Definition: _spawnlogic.gsc:66
‪initWeights
‪function initWeights(spawnpoints)
Definition: _spawnlogic.gsc:498
‪avoidVisibleEnemies
‪function avoidVisibleEnemies(spawnpoints, teambased)
Definition: _spawnlogic.gsc:1274
‪profileDebug
‪function profileDebug()
Definition: _spawnlogic.gsc:809
‪deathOccured
‪function deathOccured(dier, killer)
Definition: _spawnlogic.gsc:831
‪rebuildSpawnPoints
‪function rebuildSpawnPoints(team)
Definition: _spawnlogic.gsc:138
‪avoidSameSpawn
‪function avoidSameSpawn(spawnpoints)
Definition: _spawnlogic.gsc:1413
‪spawnPointUpdate_zm
‪function spawnPointUpdate_zm(spawnpoint)
Definition: _spawnlogic.gsc:505
‪updateDeathInfo
‪function updateDeathInfo()
Definition: _spawnlogic.gsc:897
‪isPointVulnerable
‪function isPointVulnerable(playerorigin)
Definition: _spawnlogic.gsc:978
‪getTeamSpawnPoints
‪function getTeamSpawnPoints(team)
Definition: _spawnlogic.gsc:258
‪lastMinuteSightTraces
‪function lastMinuteSightTraces(spawnpoint)
Definition: _spawnlogic.gsc:1215
‪result
‪function result(death, attacker, mod, weapon)
Definition: _zm_aat_blast_furnace.gsc:46
‪debugNearbyPlayers
‪function debugNearbyPlayers(players, origin)
Definition: _spawnlogic.gsc:827
‪getRandomIntermissionPoint
‪function getRandomIntermissionPoint()
Definition: _spawnlogic.gsc:1435
‪placeSpawnPoints
‪function placeSpawnPoints(spawnPointName)
Definition: _spawnlogic.gsc:148
‪addSpawnPoints
‪function addSpawnPoints(team, spawnPointName)
Definition: _spawnlogic.gsc:130
‪checkForSimilarDeaths
‪function checkForSimilarDeaths(deathInfo)
Definition: _spawnlogic.gsc:880
‪spawnPointUpdate
‪function spawnPointUpdate(spawnpoint)
Definition: _spawnlogic.gsc:1083