1 #using scripts\codescripts\struct;
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\gameobjects_shared;
5 #using scripts\shared\system_shared;
7 #insert scripts\shared\shared.gsh;
22 level.spawnlogic_deaths = [];
24 level.spawnlogic_spawnkills = [];
29 level.spawnMins = (0,0,0);
30 level.spawnMaxs = (0,0,0);
31 level.spawnMinsMaxsPrimed =
false;
32 if ( isdefined( level.safespawns ) )
34 for( i = 0; i < level.safespawns.size; i++ )
40 if ( GetDvarString(
"scr_spawn_enemyavoiddist") ==
"" )
41 SetDvar(
"scr_spawn_enemyavoiddist",
"800");
42 if ( GetDvarString(
"scr_spawn_enemyavoidweight") ==
"" )
43 SetDvar(
"scr_spawn_enemyavoidweight",
"0");
51 center = ( center[0]/2, center[1]/2, center[2]/2 ) + mins;
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] );
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] );
81 if ( level.teamSpawnPoints[team].size )
82 oldSpawnPoints = level.teamSpawnPoints[team];
86 if ( !isdefined( level.spawnpoints ) )
87 level.spawnpoints = [];
89 for ( index = 0; index < level.teamSpawnPoints[team].size; index++ )
91 spawnpoint = level.teamSpawnPoints[team][index];
93 if ( !isdefined( spawnpoint.inited ) )
96 level.spawnpoints[ level.spawnpoints.size ] = spawnpoint;
100 for ( index = 0; index < oldSpawnPoints.size; index++ )
102 origin = oldSpawnPoints[index].origin;
105 level.spawnMins =
expandMins( level.spawnMins, origin );
106 level.spawnMaxs =
expandMaxs( level.spawnMaxs, origin );
108 level.teamSpawnPoints[team][ level.teamSpawnPoints[team].size ] = oldSpawnPoints[index];
111 if ( !level.teamSpawnPoints[team].size )
122 foreach( team
in level.teams )
124 level.teamSpawnPoints[team] = [];
126 level.spawnpoints = [];
127 level.unified_spawn_points = undefined;
140 level.teamSpawnPoints[team] = [];
142 for ( index = 0; index < level.spawn_point_team_class_names[team].size; index++ )
154 if ( !spawnPoints.size )
162 for( index = 0; index < spawnPoints.size; index++ )
181 if ( !spawnPoints.size )
187 for( index = 0; index < spawnPoints.size; index++ )
189 spawnPoints[index] placeSpawnpoint();
195 if ( !isdefined( level.spawn_point_class_names ) )
197 level.spawn_point_class_names = [];
200 level.spawn_point_class_names[ level.spawn_point_class_names.size ] = spawnPointClassName;
205 level.spawn_point_team_class_names[team][ level.spawn_point_team_class_names[team].size ] = spawnPointClassName;
210 spawnPoints = getEntArray( classname,
"classname" );
212 if ( !isdefined( level.extraspawnpoints ) || !isdefined( level.extraspawnpoints[classname] ) )
215 for ( i = 0; i < level.extraspawnpoints[classname].size; i++ )
217 spawnPoints[ spawnPoints.size ] = level.extraspawnpoints[classname][i];
226 origin = spawnpoint.origin;
230 if ( !level.spawnMinsMaxsPrimed )
232 level.spawnMins = origin;
233 level.spawnMaxs = origin;
234 level.spawnMinsMaxsPrimed =
true;
238 level.spawnMins =
expandMins( level.spawnMins, origin );
239 level.spawnMaxs =
expandMaxs( level.spawnMaxs, origin );
242 spawnpoint placeSpawnpoint();
243 spawnpoint.forward = anglesToForward( spawnpoint.angles );
244 spawnpoint.sightTracePoint = spawnpoint.origin + (0,0,50);
255 spawnpoint.inited =
true;
260 return level.teamSpawnPoints[team];
269 bestspawnpoint = undefined;
271 if ( !isdefined( spawnpoints ) || spawnpoints.size == 0 )
274 if ( !isdefined( useweights ) )
288 for ( i = 0; i < spawnpoints.size; i++ )
290 if( isdefined(
self.lastspawnpoint ) &&
self.lastspawnpoint == spawnpoints[i] )
293 if ( positionWouldTelefrag( spawnpoints[i].origin ) )
296 bestspawnpoint = spawnpoints[i];
299 if ( !isdefined( bestspawnpoint ) )
303 if ( isdefined(
self.lastspawnpoint ) && !positionWouldTelefrag(
self.lastspawnpoint.origin ) )
306 for ( i = 0; i < spawnpoints.size; i++ )
308 if ( spawnpoints[i] ==
self.lastspawnpoint )
310 bestspawnpoint = spawnpoints[i];
318 if ( !isdefined( bestspawnpoint ) )
324 bestspawnpoint = spawnpoints[randomint(spawnpoints.size)];
328 bestspawnpoint = spawnpoints[0];
334 return bestspawnpoint;
341 self.lastspawnpoint = spawnpoint;
342 self.lastspawntime = time;
343 spawnpoint.lastspawnedplayer =
self;
344 spawnpoint.lastspawntime = time;
349 maxSightTracedSpawnpoints = 3;
350 for (
try = 0;
try <= maxSightTracedSpawnpoints;
try++ )
352 bestspawnpoints = [];
353 bestweight = undefined;
354 bestspawnpoint = undefined;
355 for ( i = 0; i < spawnpoints.size; i++ )
357 if ( !isdefined( bestweight ) || spawnpoints[i].weight > bestweight )
359 if ( positionWouldTelefrag( spawnpoints[i].origin ) )
362 bestspawnpoints = [];
363 bestspawnpoints[0] = spawnpoints[i];
364 bestweight = spawnpoints[i].weight;
366 else if ( spawnpoints[i].weight == bestweight )
368 if ( positionWouldTelefrag( spawnpoints[i].origin ) )
371 bestspawnpoints[bestspawnpoints.size] = spawnpoints[i];
374 if ( bestspawnpoints.size == 0 )
378 bestspawnpoint = bestspawnpoints[randomint( bestspawnpoints.size )];
380 if (
try == maxSightTracedSpawnpoints )
381 return bestspawnpoint;
383 if ( isdefined( bestspawnpoint.lastSightTraceTime ) && bestspawnpoint.lastSightTraceTime == gettime() )
384 return bestspawnpoint;
387 return bestspawnpoint;
390 bestspawnpoint.weight -= penalty;
392 bestspawnpoint.lastSightTraceTime = gettime();
401 if(!isdefined(spawnpoints))
405 for(i = 0; i < spawnpoints.size; i++)
407 j = randomInt(spawnpoints.size);
408 spawnpoint = spawnpoints[i];
409 spawnpoints[i] = spawnpoints[j];
410 spawnpoints[j] = spawnpoint;
421 for(i = 0; i < level.players.size; i++)
423 if ( !isdefined( level.players[i] ) )
425 player = level.players[i];
427 if ( player.sessionstate !=
"playing" || player ==
self )
429 if ( IsDefined(level.customAliveCheck) )
430 if ( ! [[level.customAliveCheck]]( player ) )
433 aliveplayers[aliveplayers.size] = player;
441 if ( level.teambased )
443 assert( isdefined( level.teams[
self.team] ) );
448 for(i = 0; i < level.players.size; i++)
450 if ( !isdefined( level.players[i] ) )
452 player = level.players[i];
454 if ( player.sessionstate !=
"playing" || player ==
self )
456 if ( IsDefined(level.customAliveCheck) )
457 if ( ! [[level.customAliveCheck]]( player ) )
460 if (player.team ==
self.team)
461 obj.allies[obj.allies.size] = player;
463 obj.enemies[obj.enemies.size] = player;
493 obj.enemies = level.activePlayers;
500 for (i = 0; i < spawnpoints.size; i++)
501 spawnpoints[i].weight = 0;
507 foreach( team
in level.teams )
509 spawnpoint.distSum[ team ]=0;
510 spawnpoint.enemyDistSum[ team ]=0;
512 players = GetPlayers();
513 spawnpoint.numPlayersAtLastUpdate = players.size;
514 foreach(player
in players)
516 if ( !isdefined( player ) )
518 if ( player.sessionstate !=
"playing" )
520 if ( IsDefined(level.customAliveCheck) )
521 if ( ! [[level.customAliveCheck]]( player ) )
523 dist = distance( spawnpoint.origin, player.origin );
524 spawnpoint.distSum[ player.team ]+=dist;
525 foreach( team
in level.teams )
527 if (team != player.team )
528 spawnpoint.enemyDistSum[ team ]+=dist;
546 if(!isdefined(spawnpoints))
549 if ( GetDvarint(
"scr_spawnsimple") > 0 )
554 k_favored_spawn_point_bonus= 25000;
561 numplayers = obj.allies.size + obj.enemies.size;
563 alliedDistanceWeight = 2;
564 if (IsDefined(forceAllyDistanceWeight))
565 alliedDistanceWeight = forceAllyDistanceWeight;
567 enemyDistanceWeight = 1;
568 if (IsDefined(forceEnemyDistanceWeight))
569 enemyDistanceWeight = forceEnemyDistanceWeight;
572 for (i = 0; i < spawnpoints.size; i++)
574 spawnpoint = spawnpoints[i];
578 if (!IsDefined(spawnpoint.numPlayersAtLastUpdate))
580 spawnpoint.numPlayersAtLastUpdate= 0;
583 if ( spawnpoint.numPlayersAtLastUpdate > 0 )
585 allyDistSum = spawnpoint.distSum[ myTeam ];
586 enemyDistSum = spawnpoint.enemyDistSum[ myTeam ];
589 spawnpoint.weight = (enemyDistanceWeight*enemyDistSum - alliedDistanceWeight*allyDistSum) / spawnpoint.numPlayersAtLastUpdate;
593 spawnpoint.weight = 0;
597 if (isdefined(favoredspawnpoints))
599 for (i= 0; i < favoredspawnpoints.size; i++)
601 if (isdefined(favoredspawnpoints[i].weight))
603 favoredspawnpoints[i].weight+= k_favored_spawn_point_bonus;
607 favoredspawnpoints[i].weight= k_favored_spawn_point_bonus;
639 if(!isdefined(spawnpoints))
653 if (aliveplayers.size > 0)
655 for (i = 0; i < spawnpoints.size; i++)
657 totalDistFromIdeal = 0;
659 for (j = 0; j < aliveplayers.size; j++)
661 dist = distance(spawnpoints[i].origin, aliveplayers[j].origin);
664 nearbyBadAmount += (badDist - dist) / badDist;
666 distfromideal = abs(dist - idealDist);
667 totalDistFromIdeal += distfromideal;
669 avgDistFromIdeal = totalDistFromIdeal / aliveplayers.size;
671 wellDistancedAmount = (idealDist - avgDistFromIdeal) / idealDist;
678 spawnpoints[i].weight = wellDistancedAmount - nearbyBadAmount * 2 + randomfloat(.2);
707 if(!isdefined(spawnpoints))
718 if (!isDefined(idealDist))
720 if (!isDefined(idealDistTeam))
721 idealDistTeam = 1200;
722 if (!isDefined(badDist))
724 if (!isDefined(badDistTeam))
728 if (aliveplayers.size > 0)
730 for (i = 0; i < spawnpoints.size; i++)
732 totalDistFromIdeal = 0;
734 for (j = 0; j < aliveplayers.size; j++)
736 dist = distance(spawnpoints[i].origin, aliveplayers[j].origin);
739 if ( aliveplayers[j].team == myTeam )
741 if (dist < badDistTeam )
742 nearbyBadAmount += (badDistTeam - dist) / badDistTeam;
743 distfromideal = abs(dist - idealDistTeam);
748 nearbyBadAmount += (badDist - dist) / badDist;
749 distfromideal = abs(dist - idealDist);
752 totalDistFromIdeal += distfromideal;
754 avgDistFromIdeal = totalDistFromIdeal / aliveplayers.size;
756 wellDistancedAmount = (idealDist - avgDistFromIdeal) / idealDist;
763 spawnpoints[i].weight = wellDistancedAmount - nearbyBadAmount * 2 + randomfloat(.2);
794 if (GetDvarString(
"scr_spawnpointdebug") ==
"0") {
805 level notify(
"stop_spawn_weight_debug");
806 level endon(
"stop_spawn_weight_debug");
813 if (GetDvarString(
"scr_spawnpointprofile") !=
"1") {
818 for (i = 0; i < level.spawnpoints.size; i++)
819 level.spawnpoints[i].weight = randomint(10000);
820 if (level.players.size > 0)
883 for (i = 0; i < level.spawnlogic_deaths.size; i++)
885 if (level.spawnlogic_deaths[i].killer == deathInfo.killer)
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;
892 level.spawnlogic_deaths[i].remove =
true;
901 for (i = 0; i < level.spawnlogic_deaths.size; i++)
904 deathInfo = level.spawnlogic_deaths[i];
906 if (time - deathInfo.time > 1000*90 ||
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;
916 oldarray = level.spawnlogic_deaths;
917 level.spawnlogic_deaths = [];
921 if (oldarray.size - 1024 > 0) start = oldarray.size - 1024;
923 for (i = start; i < oldarray.size; i++)
925 if (!isdefined(oldarray[i].
remove))
926 level.spawnlogic_deaths[level.spawnlogic_deaths.size] = oldarray[i];
980 pos =
self.origin + level.bettymodelcenteroffset;
981 playerpos = playerorigin + (0,0,32);
982 distsqrd = distancesquared(pos, playerpos);
984 forward = anglestoforward(
self.angles);
986 if (distsqrd < level.bettyDetectionRadius*level.bettyDetectionRadius)
988 playerdir = vectornormalize(playerpos - pos);
989 angle = acos(vectordot(playerdir, forward));
990 if (angle < level.bettyDetectionConeAngle) {
1000 if (GetDvarString(
"scr_spawnpointnewlogic") ==
"0")
1006 weaponDamagePenalty = 100000;
1007 if (GetDvarString(
"scr_spawnpointweaponpenalty") !=
"" && GetDvarString(
"scr_spawnpointweaponpenalty") !=
"0")
1008 weaponDamagePenalty = GetDvarfloat(
"scr_spawnpointweaponpenalty");
1010 mingrenadedistsquared = 250*250;
1012 for (i = 0; i < spawnpoints.size; i++)
1014 for (j = 0; j < level.grenades.size; j++)
1016 if ( !isdefined( level.grenades[j] ) )
1020 if (distancesquared(spawnpoints[i].origin, level.grenades[j].origin) < mingrenadedistsquared)
1022 spawnpoints[i].weight -= weaponDamagePenalty;
1031 spawnpointindex = 0;
1042 if ( !isdefined( level.spawnPoints ) )
1045 spawnpointindex = (spawnpointindex + 1) % level.spawnPoints.size;
1046 spawnpoint = level.spawnPoints[spawnpointindex];
1056 foreach( team
in level.teams )
1058 if ( team == skip_team )
1061 value += sums[team];
1070 foreach( team
in level.teams )
1072 if ( team == skip_team )
1075 if ( dist > minDists[team] )
1076 dist = minDists[team];
1085 if ( level.teambased )
1088 foreach( team
in level.teams )
1090 spawnpoint.enemySights[team] = 0;
1092 spawnpoint.nearbyPlayers[team] = [];
1097 spawnpoint.enemySights = 0;
1099 spawnpoint.nearbyPlayers[
"all"] = [];
1102 spawnpointdir = spawnpoint.forward;
1109 if ( !level.teambased )
1111 minDist[
"all"] = 9999999;
1114 foreach( team
in level.teams )
1116 spawnpoint.distSum[team] = 0;
1117 spawnpoint.enemyDistSum[team] = 0;
1118 spawnpoint.minEnemyDist[team] = 9999999;
1119 minDist[team] = 9999999;
1122 spawnpoint.numPlayersAtLastUpdate = 0;
1124 for (i = 0; i < level.players.size; i++)
1126 player = level.players[i];
1128 if ( player.sessionstate !=
"playing" )
1131 diff = player.origin - spawnpoint.origin;
1132 diff = (diff[0], diff[1], 0);
1133 dist = length( diff );
1136 if ( level.teambased )
1141 spawnpoint.nearbyPlayers[team][spawnpoint.nearbyPlayers[team].size] = player;
1144 if ( dist < minDist[team] )
1145 minDist[team] = dist;
1147 distSum[ team ] += dist;
1148 spawnpoint.numPlayersAtLastUpdate++;
1150 pdir = anglestoforward(player.angles);
1151 if (vectordot(spawnpointdir, diff) < 0 && vectordot(pdir, diff) > 0)
1155 losExists = bullettracepassed(player.origin + (0,0,50), spawnpoint.sightTracePoint,
false, undefined);
1157 spawnpoint.lastSightTraceTime = gettime();
1161 if ( level.teamBased )
1162 sights[player.team]++;
1164 spawnpoint.enemySights++;
1189 if ( level.teamBased )
1191 foreach( team
in level.teams )
1195 spawnpoint.distSum[team] = distSum[team];
1201 spawnpoint.distSum[
"all"] = distSum[
"all"];
1202 spawnpoint.enemyDistSum[
"all"] = distSum[
"all"];
1203 spawnpoint.minEnemyDist[
"all"] = minDist[
"all"];
1210 if (GetDvarString(
"scr_spawnpointlospenalty") !=
"" && GetDvarString(
"scr_spawnpointlospenalty") !=
"0")
1211 return GetDvarfloat(
"scr_spawnpointlospenalty");
1217 if ( !isdefined( spawnpoint.nearbyPlayers ) )
1220 closest = undefined;
1221 closestDistsq = undefined;
1222 secondClosest = undefined;
1223 secondClosestDistsq = undefined;
1225 foreach( team
in spawnpoint.nearbyPlayers )
1227 if ( team ==
self.team )
1230 for ( i = 0; i < spawnpoint.nearbyPlayers[team].size; i++ )
1232 player = spawnpoint.nearbyPlayers[team][i];
1234 if ( !isdefined( player ) )
1236 if ( player.sessionstate !=
"playing" )
1238 if ( player ==
self )
1241 distsq = distanceSquared( spawnpoint.origin, player.origin );
1242 if ( !isdefined( closest ) || distsq < closestDistsq )
1244 secondClosest = closest;
1245 secondClosestDistsq = closestDistsq;
1248 closestDistSq = distsq;
1250 else if ( !isdefined( secondClosest ) || distsq < secondClosestDistSq )
1252 secondClosest = player;
1253 secondClosestDistSq = distsq;
1258 if ( isdefined( closest ) )
1260 if ( bullettracepassed( closest.origin + (0,0,50), spawnpoint.sightTracePoint,
false, undefined) )
1263 if ( isdefined( secondClosest ) )
1265 if ( bullettracepassed( secondClosest.origin + (0,0,50), spawnpoint.sightTracePoint,
false, undefined) )
1276 if (GetDvarString(
"scr_spawnpointnewlogic") ==
"0")
1285 minDistTeam =
self.team;
1289 for ( i = 0; i < spawnpoints.size; i++ )
1291 if ( !isdefined(spawnpoints[i].enemySights) )
1294 penalty = lospenalty * spawnpoints[i].enemySights[
self.team];
1295 spawnpoints[i].weight -= penalty;
1300 for ( i = 0; i < spawnpoints.size; i++ )
1302 if ( !isdefined(spawnpoints[i].enemySights) )
1305 penalty = lospenalty * spawnpoints[i].enemySights;
1306 spawnpoints[i].weight -= penalty;
1309 minDistTeam =
"all";
1312 avoidWeight = GetDvarfloat(
"scr_spawn_enemyavoidweight");
1313 if ( avoidWeight != 0 )
1315 nearbyEnemyOuterRange = GetDvarfloat(
"scr_spawn_enemyavoiddist");
1316 nearbyEnemyOuterRangeSq = nearbyEnemyOuterRange * nearbyEnemyOuterRange;
1317 nearbyEnemyPenalty = 1500 * avoidWeight;
1318 nearbyEnemyMinorPenalty = 800 * avoidWeight;
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;
1327 for ( i = 0; i < spawnpoints.size; i++ )
1330 mindist = spawnpoints[i].minEnemyDist[minDistTeam];
1331 if ( mindist < nearbyEnemyOuterRange*2 )
1333 penalty = nearbyEnemyMinorPenalty * (1 - mindist / (nearbyEnemyOuterRange*2));
1334 if ( mindist < nearbyEnemyOuterRange )
1335 penalty += nearbyEnemyPenalty * (1 - mindist / nearbyEnemyOuterRange);
1338 spawnpoints[i].weight -= penalty;
1372 if (GetDvarString(
"scr_spawnpointnewlogic") ==
"0") {
1380 maxdistSq = 1024 * 1024;
1382 for (i = 0; i < spawnpoints.size; i++)
1384 spawnpoint = spawnpoints[i];
1386 if (!isdefined(spawnpoint.lastspawnedplayer) || !isdefined(spawnpoint.lastspawntime) ||
1387 !isalive(spawnpoint.lastspawnedplayer))
1390 if (spawnpoint.lastspawnedplayer ==
self)
1392 if (teambased && spawnpoint.lastspawnedplayer.team ==
self.team)
1395 timepassed = time - spawnpoint.lastspawntime;
1396 if (timepassed < maxtime)
1398 distSq = distanceSquared(spawnpoint.lastspawnedplayer.origin, spawnpoint.origin);
1399 if (distSq < maxdistSq)
1401 worsen = 5000 * (1 - distSq/maxdistSq) * (1 - timepassed/maxtime);
1402 spawnpoint.weight -= worsen;
1405 spawnpoint.lastspawnedplayer = undefined;
1408 spawnpoint.lastspawnedplayer = undefined;
1416 if (GetDvarString(
"scr_spawnpointnewlogic") ==
"0") {
1421 if (!isdefined(
self.lastspawnpoint))
1424 for (i = 0; i < spawnpoints.size; i++)
1426 if (spawnpoints[i] ==
self.lastspawnpoint)
1428 spawnpoints[i].weight -= 50000;
1437 spawnpoints = getentarray(
"mp_global_intermission",
"classname");
1438 if ( !spawnpoints.size )
1440 spawnpoints = getentarray(
"info_player_start",
"classname");
1442 assert( spawnpoints.size );