Advertisement
Guest User

_spawnlogic - Notesblok

a guest
Nov 19th, 2011
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 56.33 KB | None | 0 0
  1. #include common_scripts\utility;
  2. #include maps\mp\_utility;
  3.  
  4. findBoxCenter( mins, maxs )
  5. {
  6. center = ( 0, 0, 0 );
  7. center = maxs - mins;
  8. center = ( center[0]/2, center[1]/2, center[2]/2 ) + mins;
  9. return center;
  10. }
  11.  
  12. expandMins( mins, point )
  13. {
  14. if ( mins[0] > point[0] )
  15. mins = ( point[0], mins[1], mins[2] );
  16. if ( mins[1] > point[1] )
  17. mins = ( mins[0], point[1], mins[2] );
  18. if ( mins[2] > point[2] )
  19. mins = ( mins[0], mins[1], point[2] );
  20. return mins;
  21. }
  22.  
  23. expandMaxs( maxs, point )
  24. {
  25. if ( maxs[0] < point[0] )
  26. maxs = ( point[0], maxs[1], maxs[2] );
  27. if ( maxs[1] < point[1] )
  28. maxs = ( maxs[0], point[1], maxs[2] );
  29. if ( maxs[2] < point[2] )
  30. maxs = ( maxs[0], maxs[1], point[2] );
  31. return maxs;
  32. }
  33.  
  34.  
  35. addSpawnPoints( team, spawnPointName, isSetOptional )
  36. {
  37. if ( !isDefined( isSetOptional ) )
  38. isSetOptional = false;
  39.  
  40. oldSpawnPoints = [];
  41. if ( level.teamSpawnPoints[team].size )
  42. oldSpawnPoints = level.teamSpawnPoints[team];
  43.  
  44. level.teamSpawnPoints[team] = getSpawnpointArray( spawnPointName );
  45.  
  46. if ( !level.teamSpawnPoints[team].size && !isSetOptional )
  47. {
  48. println( "^1Error: No " + spawnPointName + " spawnpoints found in level!" );
  49. maps\mp\gametypes\_callbacksetup::AbortLevel();
  50. wait 1; // so we don't try to abort more than once before the frame ends
  51. return;
  52. }
  53.  
  54. if ( !isDefined( level.spawnpoints ) )
  55. level.spawnpoints = [];
  56.  
  57. for ( index = 0; index < level.teamSpawnPoints[team].size; index++ )
  58. {
  59. spawnpoint = level.teamSpawnPoints[team][index];
  60.  
  61. if ( !isdefined( spawnpoint.inited ) )
  62. {
  63. spawnpoint spawnPointInit();
  64. level.spawnpoints[ level.spawnpoints.size ] = spawnpoint;
  65. }
  66. }
  67.  
  68. for ( index = 0; index < oldSpawnPoints.size; index++ )
  69. {
  70. origin = oldSpawnPoints[index].origin;
  71.  
  72. // are these 2 lines necessary? we already did it in spawnPointInit
  73. level.spawnMins = expandMins( level.spawnMins, origin );
  74. level.spawnMaxs = expandMaxs( level.spawnMaxs, origin );
  75.  
  76. level.teamSpawnPoints[team][ level.teamSpawnPoints[team].size ] = oldSpawnPoints[index];
  77. }
  78. }
  79.  
  80. placeSpawnPoints( spawnPointName )
  81. {
  82. spawnPoints = getSpawnpointArray( spawnPointName );
  83.  
  84. /#
  85. if ( !isDefined( level.extraspawnpointsused ) )
  86. level.extraspawnpointsused = [];
  87. #/
  88.  
  89. if ( !spawnPoints.size )
  90. {
  91. println( "^1Error: No " + spawnPointName + " spawnpoints found in level!" );
  92. maps\mp\gametypes\_callbacksetup::AbortLevel();
  93. wait 1; // so we don't try to abort more than once before the frame ends
  94. return;
  95. }
  96.  
  97. if ( !isDefined( level.startSpawnPoints ) )
  98. level.startSpawnPoints = [];
  99.  
  100. for( index = 0; index < spawnPoints.size; index++ )
  101. {
  102. spawnPoints[index] spawnPointInit();
  103. // don't add this spawnpoint to level.spawnpoints,
  104. // because it's an unimportant one that we don't want to do sight traces to
  105.  
  106. // but we do want another array of spawnpoints for the uav in S&D
  107. level.startSpawnPoints[ level.startSpawnPoints.size ] = spawnPoints[index];
  108.  
  109. /#
  110. spawnPoints[index].fakeclassname = spawnPointName;
  111. level.extraspawnpointsused[ level.extraspawnpointsused.size ] = spawnPoints[index];
  112. #/
  113. }
  114. }
  115.  
  116. getSpawnpointArray( classname )
  117. {
  118. spawnPoints = getEntArray( classname, "classname" );
  119.  
  120. if ( !isdefined( level.extraspawnpoints ) || !isdefined( level.extraspawnpoints[classname] ) )
  121. return spawnPoints;
  122.  
  123. for ( i = 0; i < level.extraspawnpoints[classname].size; i++ )
  124. {
  125. spawnPoints[ spawnPoints.size ] = level.extraspawnpoints[classname][i];
  126. }
  127.  
  128. return spawnPoints;
  129. }
  130.  
  131. expandSpawnpointBounds( classname )
  132. {
  133. spawnPoints = getSpawnpointArray( classname );
  134. for( index = 0; index < spawnPoints.size; index++ )
  135. {
  136. level.spawnMins = expandMins( level.spawnMins, spawnPoints[index].origin );
  137. level.spawnMaxs = expandMaxs( level.spawnMaxs, spawnPoints[index].origin );
  138. }
  139. }
  140.  
  141. setMapCenterForReflections()
  142. {
  143. level.spawnMins = (0,0,0);
  144. level.spawnMaxs = (0,0,0);
  145.  
  146. maps\mp\gametypes\_spawnlogic::expandSpawnpointBounds( "mp_tdm_spawn_allies_start" );
  147. maps\mp\gametypes\_spawnlogic::expandSpawnpointBounds( "mp_tdm_spawn_axis_start" );
  148. level.mapCenter = maps\mp\gametypes\_spawnlogic::findBoxCenter( level.spawnMins, level.spawnMaxs );
  149. setMapCenter( level.mapCenter );
  150. }
  151.  
  152. // initspawnpoint()
  153. spawnPointInit()
  154. {
  155. spawnpoint = self;
  156. origin = spawnpoint.origin;
  157.  
  158. level.spawnMins = expandMins( level.spawnMins, origin );
  159. level.spawnMaxs = expandMaxs( level.spawnMaxs, origin );
  160.  
  161. spawnpoint placeSpawnpoint();
  162. spawnpoint.forward = anglesToForward( spawnpoint.angles );
  163. spawnpoint.sightTracePoint = spawnpoint.origin + (0,0,50);
  164.  
  165. spawnpoint.lastspawnedplayer = spawnpoint; // just want this to be any entity for which isalive() returns false
  166. spawnpoint.lastspawntime = gettime();
  167.  
  168. skyHeight = 1024;
  169. spawnpoint.outside = true;
  170. if ( !bullettracepassed( spawnpoint.sightTracePoint, spawnpoint.sightTracePoint + (0,0,skyHeight), false, undefined) )
  171. {
  172. startpoint = spawnpoint.sightTracePoint + spawnpoint.forward * 100;
  173. if ( !bullettracepassed( startpoint, startpoint + (0,0,skyHeight), false, undefined) )
  174. spawnpoint.outside = false;
  175. }
  176.  
  177. right = anglesToRight( spawnpoint.angles );
  178. spawnpoint.alternates = [];
  179. AddAlternateSpawnpoint( spawnpoint, spawnpoint.origin + right * 45 );
  180. AddAlternateSpawnpoint( spawnpoint, spawnpoint.origin - right * 45 );
  181. //AddAlternateSpawnpoint( spawnpoint, spawnpoint.origin + spawnpoint.forward * 45 );
  182.  
  183. /*
  184. spawnpoint.secondFloor = false;
  185. if ( isDefined( level.spawnSecondFloorTrig ) )
  186. {
  187. spawnpoint.secondFloor = (spawnpoint isTouching( level.spawnSecondFloorTrig ));
  188.  
  189. spawnpoint.floorTransitionDistances = [];
  190.  
  191. for ( pointIndex = 0; pointIndex < level.spawnFloorTransitions.size; pointIndex++ )
  192. {
  193. spawnpoint.floorTransitionDistances[ pointIndex ] = distance( level.spawnFloorTransitions[ pointIndex ], spawnpoint.origin );
  194. }
  195. }
  196. */
  197.  
  198. spawnPointUpdate( spawnpoint );
  199.  
  200. spawnpoint.inited = true;
  201. }
  202.  
  203. AddAlternateSpawnpoint( spawnpoint, alternatepos )
  204. {
  205. spawnpointposRaised = playerPhysicsTrace( spawnpoint.origin, spawnpoint.origin + (0,0,18), false, undefined );
  206. zdiff = spawnpointposRaised[2] - spawnpoint.origin[2];
  207.  
  208. alternateposRaised = (alternatepos[0], alternatepos[1], alternatepos[2] + zdiff );
  209.  
  210. traceResult = playerPhysicsTrace( spawnpointposRaised, alternateposRaised, false, undefined );
  211. if ( traceResult != alternateposRaised )
  212. return;
  213.  
  214. finalAlternatePos = playerPhysicsTrace( alternateposRaised, alternatepos );
  215.  
  216. spawnpoint.alternates[ spawnpoint.alternates.size ] = finalAlternatePos;
  217. }
  218.  
  219.  
  220. getTeamSpawnPoints( team )
  221. {
  222. return level.teamSpawnPoints[team];
  223. }
  224.  
  225. // selects a spawnpoint, preferring ones with heigher weights (or toward the beginning of the array if no weights).
  226. // also does final things like setting self.lastspawnpoint to the one chosen.
  227. // this takes care of avoiding telefragging, so it doesn't have to be considered by any other function.
  228. getSpawnpoint_Final( spawnpoints, useweights )
  229. {
  230. prof_begin( "spawn_final" );
  231.  
  232. bestspawnpoint = undefined;
  233.  
  234. if ( !isdefined( spawnpoints ) || spawnpoints.size == 0 )
  235. return undefined;
  236.  
  237. if ( !isdefined( useweights ) )
  238. useweights = true;
  239.  
  240. if ( useweights )
  241. {
  242. // choose spawnpoint with best weight
  243. // (if a tie, choose randomly from the best)
  244. bestspawnpoint = getBestWeightedSpawnpoint( spawnpoints );
  245. /#
  246. thread spawnWeightDebug( spawnpoints, bestspawnpoint );
  247. #/
  248. }
  249. else
  250. {
  251. carePackages = getEntArray( "care_package", "targetname" );
  252. // (only place we actually get here from is getSpawnpoint_Random() )
  253. // no weights. prefer spawnpoints toward beginning of array
  254. for ( i = 0; i < spawnpoints.size; i++ )
  255. {
  256. if( isdefined( self.lastspawnpoint ) && self.lastspawnpoint == spawnpoints[i] )
  257. continue;
  258.  
  259. if ( positionWouldTelefrag( spawnpoints[i].origin ) )
  260. continue;
  261.  
  262. if ( carePackages.size && !canSpawn( spawnpoints[i].origin ) )
  263. continue;
  264.  
  265. bestspawnpoint = spawnpoints[i];
  266. break;
  267. }
  268. if ( !isdefined( bestspawnpoint ) )
  269. {
  270. // Couldn't find a useable spawnpoint. All spawnpoints either telefragged or were our last spawnpoint
  271. // Our only hope is our last spawnpoint - unless it too will telefrag...
  272. if ( isdefined( self.lastspawnpoint ) && !positionWouldTelefrag( self.lastspawnpoint.origin ) )
  273. {
  274. // (make sure our last spawnpoint is in the valid array of spawnpoints to use)
  275. for ( i = 0; i < spawnpoints.size; i++ )
  276. {
  277. if ( spawnpoints[i] == self.lastspawnpoint )
  278. {
  279. bestspawnpoint = spawnpoints[i];
  280. break;
  281. }
  282. }
  283. }
  284. }
  285. }
  286.  
  287. if ( !isdefined( bestspawnpoint ) )
  288. {
  289. // couldn't find a useable spawnpoint! all will telefrag.
  290. if ( useweights )
  291. {
  292. // at this point, forget about weights. just take a random one.
  293. bestspawnpoint = spawnpoints[randomint(spawnpoints.size)];
  294.  
  295. /#
  296.  
  297. #/
  298. }
  299. else
  300. {
  301. bestspawnpoint = spawnpoints[0];
  302. }
  303. }
  304.  
  305. prof_end( "spawn_final" );
  306.  
  307. return bestspawnpoint;
  308. }
  309.  
  310. finalizeSpawnpointChoice( spawnpoint )
  311. {
  312. time = getTime();
  313.  
  314. self.lastspawnpoint = spawnpoint;
  315. self.lastspawntime = time;
  316. spawnpoint.lastspawnedplayer = self;
  317. spawnpoint.lastspawntime = time;
  318. }
  319.  
  320. maxSightTracedSpawnpoints = 3;
  321.  
  322. getBestWeightedSpawnpoint( spawnpoints )
  323. {
  324. otherteam = getOtherTeam( self.team );
  325.  
  326. assert( spawnpoints.size > 0 );
  327.  
  328. for ( try = 0; ; try++ )
  329. {
  330. bestspawnpoints = [];
  331. bestspawnpoints[0] = spawnpoints[0];
  332. bestweight = spawnpoints[0].weight;
  333. for ( i = 1; i < spawnpoints.size; i++ )
  334. {
  335. spawnpoint = spawnpoints[i];
  336. if ( spawnpoint.weight > bestweight )
  337. {
  338. bestspawnpoints = [];
  339. bestspawnpoints[0] = spawnpoint;
  340. bestweight = spawnpoint.weight;
  341. }
  342. else if ( spawnpoint.weight == bestweight )
  343. {
  344. bestspawnpoints[bestspawnpoints.size] = spawnpoint;
  345. }
  346. }
  347.  
  348. // pick randomly from the available spawnpoints with the best weight
  349. assert( bestspawnpoints.size > 0 );
  350. bestspawnpoint = bestspawnpoints[randomint( bestspawnpoints.size )];
  351.  
  352. if ( try >= maxSightTracedSpawnpoints )
  353. {
  354. println( "Spawning " + self.name + " at spawnpoint " + bestspawnpoint.origin + " because the " + maxSightTracedSpawnpoints + " best spawnpoints failed last minute sight trace tests." );
  355. /# DumpSpawnData( spawnpoints, bestspawnpoint ); #/
  356. return bestspawnpoint;
  357. }
  358.  
  359. // if we already know that this spawnpoint has sight lines to the enemy team, and it's still the best we've got, there's no point doing more traces.
  360. sights = 0;
  361. if ( level.teambased )
  362. sights = bestspawnpoint.sights[otherteam];
  363. else
  364. sights = bestspawnpoint.sights;
  365.  
  366. if ( sights > 0 )
  367. {
  368. println( "Spawning " + self.name + " at spawnpoint " + bestspawnpoint.origin + " even though " + sights + " lines of sight to the enemy exist." );
  369. /# DumpSpawnData( spawnpoints, bestspawnpoint ); #/
  370. return bestspawnpoint;
  371. }
  372.  
  373. if ( isdefined( bestspawnpoint.lastSightTraceTime ) && bestspawnpoint.lastSightTraceTime == gettime() )
  374. return bestspawnpoint;
  375.  
  376. sightValue = lastMinuteSightTraces( bestspawnpoint );
  377. if ( sightValue == 0 )
  378. return bestspawnpoint;
  379.  
  380. sightValue = adjustSightValue( sightvalue );
  381. if ( level.teambased )
  382. bestspawnpoint.sights[otherteam] += sightValue;
  383. else
  384. bestspawnpoint.sights += sightValue;
  385.  
  386. penalty = getLosPenalty() * sightValue;
  387. /#
  388. bestspawnpoint.spawnData[bestspawnpoint.spawnData.size] = "Last minute sight trace: -" + penalty;
  389. #/
  390. bestspawnpoint.weight -= penalty;
  391.  
  392. bestspawnpoint.lastSightTraceTime = gettime();
  393. }
  394. assertmsg( "can't get here" );
  395. }
  396.  
  397. /#
  398.  
  399. DumpSpawnData( spawnpoints, winnerspawnpoint )
  400. {
  401. if ( getSubStr( self.name, 0, 3 ) == "bot" )
  402. {
  403. if ( getdvarint("scr_spawnpointdebug") == 0 )
  404. return;
  405. }
  406.  
  407. println( "=================================" );
  408. println( "spawndata = spawnstruct();" );
  409. println( "spawndata.playername = \"" + self.name + "\";" );
  410. println( "spawndata.friends = [];" );
  411. println( "spawndata.enemies = [];" );
  412. foreach ( player in level.players )
  413. {
  414. if ( player.team == self.team )
  415. println( "spawndata.friends[ spawndata.friends.size ] = " + player.origin + ";" );
  416. else
  417. println( "spawndata.enemies[ spawndata.enemies.size ] = " + player.origin + ";" );
  418. }
  419. println( "spawndata.otherdata = [];" );
  420.  
  421. println( "spawndata.spawnpoints = [];" );
  422. index = 0;
  423. foreach ( spawnpoint in spawnpoints )
  424. {
  425. if ( spawnpoint == winnerspawnpoint )
  426. println( "spawndata.spawnpointwinner = " + index + ";" );
  427.  
  428. println( "spawnpoint = spawnstruct();" );
  429. println( "spawnpoint.weight = " + spawnpoint.weight + ";" );
  430. println( "spawnpoint.origin = " + spawnpoint.origin + ";" );
  431. println( "spawnpoint.spawndata = [];" );
  432. for ( i = 0; i < spawnpoint.spawndata.size; i++ )
  433. {
  434. println( "spawnpoint.spawndata[" + i + "] = \"" + spawnpoint.spawndata[i] + "\";" );
  435. }
  436.  
  437. println( "spawndata.spawnpoints[spawndata.spawnpoints.size] = spawnpoint;" );
  438. index++;
  439. }
  440. println( "=================================" );
  441. }
  442.  
  443. DrawRecordedSpawnData()
  444. {
  445. spawndata = undefined;
  446.  
  447. // to remove line beginnings from console log, use regexp: ^\[.*\]
  448. // ====================================
  449. // paste console log output in here
  450. // ====================================
  451.  
  452. if ( isDefined( spawndata ) )
  453. thread drawSpawnData( spawndata );
  454. }
  455.  
  456. checkBad( spawnpoint )
  457. {
  458. for ( i = 0; i < level.players.size; i++ )
  459. {
  460. player = level.players[i];
  461.  
  462. if ( !isAlive( player ) || player.sessionstate != "playing" )
  463. continue;
  464. if ( level.teambased && player.team == self.team )
  465. continue;
  466.  
  467. losExists = bullettracepassed(player.origin + (0,0,50), spawnpoint.sightTracePoint, false, undefined);
  468. if ( losExists )
  469. thread badSpawnLine( spawnpoint.sightTracePoint, player.origin + (0,0,50), self.name, player.name );
  470. }
  471. }
  472.  
  473. badSpawnLine( start, end, name1, name2 )
  474. {
  475. dist = distance(start,end);
  476. for ( i = 0; i < 20 * 10; i++ )
  477. {
  478. line( start, end, (1,0,0) );
  479. print3d( start, "Bad spawn! " + name1 + ", dist = " + dist );
  480. print3d( end, name2 );
  481.  
  482. wait .05;
  483. }
  484. }
  485.  
  486. drawSpawnData( spawndata )
  487. {
  488. level notify("drawing_spawn_data");
  489. level endon("drawing_spawn_data");
  490.  
  491. textoffset = (0,0,-12);
  492.  
  493. fakeplayer = spawnstruct();
  494. fakeplayer.name = spawndata.playername;
  495.  
  496. fakeplayer thread spawnWeightDebug( spawndata.spawnpoints, spawndata.spawnpoints[spawndata.spawnpointwinner] );
  497.  
  498. while(1)
  499. {
  500. for (i = 0; i < spawndata.friends.size; i++)
  501. {
  502. print3d(spawndata.friends[i], "=)", (.5,1,.5), 1, 5);
  503. }
  504. for (i = 0; i < spawndata.enemies.size; i++)
  505. {
  506. print3d(spawndata.enemies[i], "=(", (1,.5,.5), 1, 5);
  507. }
  508.  
  509. for (i = 0; i < spawndata.otherdata.size; i++)
  510. {
  511. print3d(spawndata.otherdata[i].origin, spawndata.otherdata[i].text, (.5,.75,1), 1, 2);
  512. }
  513.  
  514. wait .05;
  515. }
  516. }
  517.  
  518. #/
  519.  
  520. getSpawnpoint_Random(spawnpoints)
  521. {
  522. // level endon("game_ended");
  523.  
  524. // There are no valid spawnpoints in the map
  525. if(!isdefined(spawnpoints))
  526. return undefined;
  527.  
  528. // randomize order
  529. for ( i = 0; i < spawnpoints.size; i++ )
  530. {
  531. j = randomInt(spawnpoints.size);
  532. spawnpoint = spawnpoints[i];
  533. spawnpoints[i] = spawnpoints[j];
  534. spawnpoints[j] = spawnpoint;
  535. }
  536.  
  537. if ( isDefined( self.predictedSpawnPoint ) )
  538. {
  539. // if we predicted spawning at one of these spawnpoints already, favor that one.
  540. for ( i = 1; i < spawnpoints.size; i++ )
  541. {
  542. if ( spawnpoints[i] == self.predictedSpawnPoint )
  543. {
  544. temp = spawnpoints[0];
  545. spawnpoints[0] = spawnpoints[i];
  546. spawnpoints[i] = temp;
  547. break;
  548. }
  549. }
  550. }
  551.  
  552. return getSpawnpoint_Final(spawnpoints, false);
  553. }
  554.  
  555. getAllOtherPlayers()
  556. {
  557. aliveplayers = [];
  558.  
  559. // Make a list of fully connected, non-spectating, alive players
  560. for(i = 0; i < level.players.size; i++)
  561. {
  562. if ( !isdefined( level.players[i] ) )
  563. continue;
  564. player = level.players[i];
  565.  
  566. if ( player.sessionstate != "playing" || player == self )
  567. continue;
  568.  
  569. aliveplayers[aliveplayers.size] = player;
  570. }
  571. return aliveplayers;
  572. }
  573.  
  574.  
  575. // weight array manipulation code
  576. initWeights(spawnpoints)
  577. {
  578. for (i = 0; i < spawnpoints.size; i++)
  579. spawnpoints[i].weight = 0;
  580.  
  581. /#
  582. for (i = 0; i < spawnpoints.size; i++) {
  583. spawnpoints[i].spawnData = [];
  584. }
  585. #/
  586. }
  587.  
  588. // ================================================
  589.  
  590.  
  591. getSpawnpoint_NearTeam( spawnpoints, favoredspawnpoints )
  592. {
  593. // level endon("game_ended");
  594.  
  595. /*if ( self.wantSafeSpawn )
  596. {
  597. return getSpawnpoint_SafeSpawn( spawnpoints );
  598. }*/
  599.  
  600. // There are no valid spawnpoints in the map
  601. if(!isdefined(spawnpoints))
  602. return undefined;
  603.  
  604. /#
  605. setDevDvarIfUninitialized("scr_spawn_randomly", "0");
  606. if ( getdvarint("scr_spawn_randomly") == 1 )
  607. return getSpawnpoint_Random( spawnpoints );
  608. #/
  609.  
  610. prof_begin("spawn_basiclogic");
  611.  
  612. /#
  613. if ( getdvarint("scr_spawnsimple") > 0 )
  614. return getSpawnpoint_Random( spawnpoints );
  615. #/
  616.  
  617. Spawnlogic_Begin();
  618.  
  619. initWeights(spawnpoints);
  620.  
  621. alliedDistanceWeight = 2;
  622.  
  623. //prof_begin(" spawn_basicsumdists");
  624. myTeam = self.team;
  625. enemyTeam = getOtherTeam( myTeam );
  626.  
  627. carePackages = getEntArray( "care_package", "targetname" );
  628. foreach ( spawnpoint in spawnpoints )
  629. {
  630. if ( spawnpoint.numPlayersAtLastUpdate > 0 )
  631. {
  632. allyDistSum = spawnpoint.weightedDistSum[ myTeam ]; // we weight the allied distSum to account for things like snipers and tactical insertion
  633. enemyDistSum = spawnpoint.distSum[ enemyTeam ];
  634.  
  635. // high enemy distance is good, high ally distance is bad
  636. spawnpoint.weight = (enemyDistSum - alliedDistanceWeight*allyDistSum) / spawnpoint.numPlayersAtLastUpdate;
  637.  
  638. //IW5 Modification for unusual game modes
  639. if( isDefined( level.favorCloseSpawnEnt ) )
  640. {
  641. if ( !isdefined( level.favorCloseSpawnScalar ) )
  642. level.favorCloseSpawnScalar = 1;
  643.  
  644. distanceFromEnt = Distance( spawnpoint.origin, level.favorCloseSpawnEnt.origin );
  645.  
  646. spawnpoint.weight -= distanceFromEnt * level.favorCloseSpawnScalar;
  647. }
  648.  
  649. /#
  650. spawnpoint.spawnData[spawnpoint.spawnData.size] = "Base weight: " + int(spawnpoint.weight) + " = (" + int(enemyDistSum) + " - " + alliedDistanceWeight + "*" + int(allyDistSum) + ") / " + spawnpoint.numPlayersAtLastUpdate;
  651. #/
  652. }
  653. else
  654. {
  655. spawnpoint.weight = 0;
  656.  
  657. /#
  658. spawnpoint.spawnData[spawnpoint.spawnData.size] = "Base weight: 0";
  659. #/
  660. }
  661.  
  662. if ( carePackages.size && !canSpawn( spawnpoint.origin ) )
  663. spawnpoint.weight -= 500000;
  664. }
  665. //prof_end(" spawn_basicsumdists");
  666.  
  667. if ( isdefined( favoredspawnpoints ) )
  668. {
  669. for (i = 0; i < favoredspawnpoints.size; i++)
  670. {
  671. favoredspawnpoints[i].weight += 50000;
  672. /#
  673. favoredspawnpoints[i].spawnData[favoredspawnpoints[i].spawnData.size] = "Favored: 50000";
  674. #/
  675. }
  676. }
  677.  
  678. if ( isDefined( self.predictedSpawnPoint ) && isDefined( self.predictedSpawnPoint.weight ) )
  679. {
  680. // add a tiebreaker in case we end up choosing between spawnpoints of similar weight
  681. self.predictedSpawnPoint.weight += 100;
  682. /#
  683. self.predictedSpawnPoint.spawnData[self.predictedSpawnPoint.spawnData.size] = "Predicted: 100";
  684. #/
  685. }
  686.  
  687. prof_end("spawn_basiclogic");
  688.  
  689. prof_begin("spawn_complexlogic");
  690.  
  691. avoidSameSpawn();
  692. // not avoiding spawn reuse because it doesn't do anything nearbyPenalty doesn't do
  693. //avoidSpawnReuse(spawnpoints, true);
  694. // not avoiding spawning near recent deaths for team-based modes. kills the fast pace.
  695. //avoidDangerousSpawns(spawnpoints, true);
  696. avoidWeaponDamage(spawnpoints);
  697. avoidVisibleEnemies(spawnpoints, true);
  698.  
  699. //added to MW3
  700. if ( isDefined( self.lastDeathPos ) && level.gameType != "dom" )
  701. avoidRevengeSpawn( spawnpoints, self.lastDeathPos );
  702.  
  703. prof_end("spawn_complexlogic");
  704.  
  705. result = getSpawnpoint_Final(spawnpoints);
  706.  
  707. /#
  708. setdevdvarIfUninitialized("scr_spawn_showbad", "0");
  709. if ( getdvarint("scr_spawn_showbad") == 1 )
  710. checkBad( result );
  711. #/
  712.  
  713. /#
  714. foundIt = 0;
  715. foreach ( spawn in level.spawnLogData )
  716. {
  717. if ( spawn == result )
  718. {
  719. foundIt = 1;
  720. }
  721. }
  722.  
  723. if ( foundIt == 0 )
  724. level.spawnLogData[level.spawnLogData.size] = result;
  725.  
  726. if ( !isDefined( result.spawnCount ) )
  727. {
  728. result.spawnCount = 1;
  729. }
  730.  
  731. #/
  732.  
  733.  
  734. return result;
  735. }
  736.  
  737.  
  738. //Not In Use --- IW5 ---
  739. getSpawnpoint_SafeSpawn( spawnpoints )
  740. {
  741. // There are no valid spawnpoints in the map
  742. if ( !isdefined( spawnpoints ) )
  743. return undefined;
  744. assert( spawnpoints.size > 0 );
  745.  
  746. Spawnlogic_Begin();
  747.  
  748. safestSpawnpoint = undefined;
  749. safestDangerDist = undefined;
  750.  
  751. enemyTeam = getOtherTeam( self.team );
  752. if ( !level.teambased )
  753. enemyTeam = "all";
  754.  
  755. mingrenadedistsquared = 500 * 500;
  756.  
  757. foreach ( spawnpoint in spawnpoints )
  758. {
  759. dangerDist = spawnpoint.minDist[ enemyTeam ];
  760.  
  761. foreach ( grenade in level.grenades )
  762. {
  763. if ( !isdefined( grenade ) )
  764. continue;
  765.  
  766. if ( distancesquared( spawnpoint.origin, grenade.origin ) < mingrenadedistsquared )
  767. {
  768. grenadeDist = distance( spawnpoint.origin, grenade.origin ) - 220;
  769. if ( grenadeDist < dangerDist )
  770. {
  771. if ( grenadeDist < 0 )
  772. grenadeDist = 0;
  773. dangerDist = grenadeDist;
  774. }
  775. }
  776. }
  777.  
  778. if ( positionWouldTelefrag( spawnpoint.origin ) )
  779. dangerDist -= 200; // discourage telefragging but don't worry too much
  780.  
  781. if ( isDefined( level.artilleryDangerCenters ) )
  782. {
  783. airstrikeDanger = maps\mp\killstreaks\_airstrike::getAirstrikeDanger( spawnpoint.origin );
  784. if ( airstrikeDanger > 0 )
  785. dangerDist = 0;
  786. }
  787.  
  788. if ( level.teambased )
  789. {
  790. if ( spawnpoint.sights[enemyTeam] > 0 )
  791. dangerDist = 0;
  792. }
  793. else
  794. {
  795. if ( spawnpoint.sights > 0 )
  796. dangerDist = 0;
  797. }
  798.  
  799. if ( !isdefined( safestSpawnpoint ) || dangerDist > safestDangerDist )
  800. {
  801. safestSpawnpoint = spawnpoint;
  802. safestDangerDist = dangerDist;
  803. }
  804. }
  805.  
  806. assert( isdefined( safestSpawnpoint ) );
  807. if ( !isdefined( safestSpawnpoint ) )
  808. {
  809. safestSpawnpoint = spawnpoints[ randomint( spawnpoints.size ) ];
  810. safestSpawnpoint.safeSpawnDangerDist = 500;
  811. }
  812. else
  813. {
  814. safestSpawnpoint.safeSpawnDangerDist = safestDangerDist;
  815. }
  816.  
  817. return safestSpawnpoint;
  818. }
  819.  
  820. /////////////////////////////////////////////////////////////////////////
  821.  
  822. getSpawnpoint_DM(spawnpoints)
  823. {
  824. // level endon("game_ended");
  825.  
  826. /*if ( self.wantSafeSpawn )
  827. {
  828. return getSpawnpoint_SafeSpawn( spawnpoints );
  829. }*/
  830.  
  831. // There are no valid spawnpoints in the map
  832. if(!isdefined(spawnpoints))
  833. return undefined;
  834.  
  835. Spawnlogic_Begin();
  836.  
  837. initWeights(spawnpoints);
  838.  
  839. aliveplayers = getAllOtherPlayers();
  840.  
  841. // new logic: we want most players near idealDist units away.
  842. // players closer than badDist units will be considered negatively
  843. idealDist = 1600;
  844. badDist = 1200;
  845.  
  846. if (aliveplayers.size > 0 )
  847. {
  848. for (i = 0; i < spawnpoints.size; i++)
  849. {
  850. totalDistFromIdeal = 0;
  851. nearbyBadAmount = 0;
  852. for (j = 0; j < aliveplayers.size; j++)
  853. {
  854. dist = distance(spawnpoints[i].origin, aliveplayers[j].origin);
  855.  
  856. if (dist < badDist)
  857. nearbyBadAmount += (badDist - dist) / badDist;
  858.  
  859. distfromideal = abs(dist - idealDist);
  860. totalDistFromIdeal += distfromideal;
  861. }
  862. avgDistFromIdeal = totalDistFromIdeal / aliveplayers.size;
  863.  
  864. wellDistancedAmount = (idealDist - avgDistFromIdeal) / idealDist;
  865. // if (wellDistancedAmount < 0) wellDistancedAmount = 0;
  866.  
  867. // wellDistancedAmount is between -inf and 1, 1 being best (likely around 0 to 1)
  868. // nearbyBadAmount is between 0 and inf,
  869. // and it is very important that we get a bad weight if we have a high nearbyBadAmount.
  870.  
  871. spawnpoints[i].weight = wellDistancedAmount - nearbyBadAmount * 2 + randomfloat(.2);
  872. }
  873. }
  874.  
  875. carePackages = getEntArray( "care_package", "targetname" );
  876.  
  877. for (i = 0; i < spawnpoints.size; i++)
  878. {
  879. if ( carePackages.size && !canSpawn( spawnpoints[i].origin ) )
  880. spawnpoints[i].weight -= 500000;
  881. }
  882.  
  883. if ( isDefined( self.predictedSpawnPoint ) && isDefined( self.predictedSpawnPoint.weight ) )
  884. {
  885. // add a tiebreaker in case we end up choosing between spawnpoints of similar weight
  886. self.predictedSpawnPoint.weight += 100;
  887. /#
  888. self.predictedSpawnPoint.spawnData[self.predictedSpawnPoint.spawnData.size] = "Predicted: 100";
  889. #/
  890. }
  891.  
  892. avoidSameSpawn();
  893. //avoidSpawnReuse(spawnpoints, false);
  894. //avoidDangerousSpawns(spawnpoints, false);
  895. avoidWeaponDamage(spawnpoints);
  896. avoidVisibleEnemies(spawnpoints, false);
  897.  
  898. return getSpawnpoint_Final(spawnpoints);
  899. }
  900.  
  901. // =============================================
  902.  
  903. // called at the start of every spawn
  904. Spawnlogic_Begin()
  905. {
  906. //updateDeathInfo();
  907.  
  908. /#
  909. level.debugSpawning = (getdvarint("scr_spawnpointdebug") > 0);
  910. #/
  911. }
  912.  
  913. // called once at start of game
  914. init()
  915. {
  916. /#
  917. setDevDvarIfUninitialized("scr_spawnpointdebug", "0");
  918. setDevDvarIfUninitialized("scr_killbots", 0);
  919. setDevDvarIfUninitialized("scr_killbottimer", 0);
  920.  
  921. thread loopbotspawns();
  922. #/
  923.  
  924. SetupKillstreakSpawnShield();
  925.  
  926. // start keeping track of deaths
  927. level.spawnlogic_deaths = [];
  928. // DEBUG
  929. level.spawnlogic_spawnkills = [];
  930. level.players = [];
  931. level.grenades = [];
  932. level.pipebombs = [];
  933. level.turrets = [];
  934. level.helis = [];
  935. level.tanks = [];
  936. level.scramblers = [];
  937. level.ims = [];
  938. level.ugvs = [];
  939.  
  940. level.teamSpawnPoints["axis"] = [];
  941. level.teamSpawnPoints["allies"] = [];
  942.  
  943. level thread trackGrenades();
  944. level thread trackMissiles();
  945.  
  946. level.spawnMins = (0,0,0);
  947. level.spawnMaxs = (0,0,0);
  948. if ( isdefined( level.safespawns ) )
  949. {
  950. for( i = 0; i < level.safespawns.size; i++ )
  951. {
  952. level.safespawns[i] spawnPointInit();
  953. }
  954. }
  955.  
  956. /*
  957. level.spawnSecondFloorTrig = getent( "spawn_second_floor", "targetname" );
  958. if ( isDefined( level.spawnSecondFloorTrig ) )
  959. {
  960. transitions = getentarray( level.spawnSecondFloorTrig.target, "targetname" );
  961. level.spawnFloorTransitions = [];
  962.  
  963. foreach ( org in transitions )
  964. {
  965. level.spawnFloorTransitions[ level.spawnFloorTransitions.size ] = org.origin;
  966. org delete();
  967. }
  968. }
  969. */
  970.  
  971. // DEBUG
  972. /#
  973. if (getdvarint("scr_spawnpointdebug") > 0)
  974. {
  975. thread profileDebug();
  976.  
  977. thread drawRecordedSpawnData();
  978. }
  979. thread watchSpawnProfile();
  980. thread spawnGraphCheck();
  981. thread sightCheckCost();
  982. thread spawnWatcher();
  983.  
  984. thread spawnInfoWriter();
  985. level.spawnLogData = [];
  986. #/
  987. }
  988.  
  989. /#
  990. spawnWatcher()
  991. {
  992. level endon("game_ended");
  993.  
  994. for( ;; )
  995. {
  996. level waittill( "player_spawned", playerSpawned );
  997.  
  998. if ( isDefined( playerSpawned.lastSpawnPoint ) )
  999. {
  1000. if( isDefined( playerSpawned.lastSpawnPoint.spawnCount ) )
  1001. playerSpawned.lastSpawnPoint.spawnCount++;
  1002. else
  1003. playerSpawned.lastSpawnPoint.spawnCount = 1;
  1004. }
  1005. }
  1006. }
  1007. #/
  1008.  
  1009. /#
  1010. spawnInfoWriter()
  1011. {
  1012. level waittill( "game_ended" );
  1013.  
  1014. mapName = getdvar( "ui_mapname" );
  1015.  
  1016. spawnDataFile = OpenFile( "spawn_info.txt", "append" );
  1017.  
  1018. FPrintLn( spawnDataFile, "SPAWN DATA FOR: " + mapName );
  1019. FPrintLn( spawnDataFile, " " );
  1020.  
  1021. foreach( spawn in level.spawnLogData )
  1022. {
  1023. ResetTimeout();
  1024. FPrintLn( spawnDataFile, "Spawn Point Origin: " + spawn.origin );
  1025. FPrintLn( spawnDataFile, "Number of players spawned from this point: " + spawn.spawncount );
  1026. FPrintLn( spawnDataFile, " " );
  1027. }
  1028. println( "File Written" );
  1029.  
  1030. wait( 1 );
  1031. CloseFile(spawnDataFile);
  1032. }
  1033. #/
  1034.  
  1035. sightCheckCost()
  1036. {
  1037. traceCount = 30;
  1038.  
  1039. for ( ;; )
  1040. {
  1041. prof_begin( "sight_check_cost" );
  1042.  
  1043. traceType = getDvar( "scr_debugcost" );
  1044.  
  1045. if ( traceType == "bullet" && isDefined( level.players[0] ) )
  1046. {
  1047. for ( i = 0; i < traceCount; i++ )
  1048. bulletTracePassed( level.players[0].origin + (0,0,50), (0,0,0), false, undefined );
  1049.  
  1050. }
  1051. else if ( traceType == "damagecone" && isDefined( level.players[0] ) )
  1052. {
  1053. for ( i = 0; i < traceCount; i++ )
  1054. level.players[0] damageConeTrace( (0,0,0) );
  1055. }
  1056. else if ( traceType == "sightcone" && isDefined( level.players[0] ) )
  1057. {
  1058. for ( i = 0; i < traceCount; i++ )
  1059. level.players[0] sightConeTrace( (0,0,0) );
  1060. }
  1061. else
  1062. {
  1063. wait ( 1.0 );
  1064. }
  1065.  
  1066. prof_end( "sight_check_cost" );
  1067.  
  1068. wait ( 0.05 );
  1069. }
  1070. }
  1071.  
  1072. watchSpawnProfile()
  1073. {
  1074. while(1)
  1075. {
  1076. while( getDvar( "scr_spawnprofile" ) == "" || getDvar( "scr_spawnprofile" ) == "0" )
  1077. wait ( 0.05 );
  1078.  
  1079. thread spawnProfile();
  1080.  
  1081. while( getDvar( "scr_spawnprofile" ) != "" && getDvar( "scr_spawnprofile" ) != "0" )
  1082. wait ( 0.05 );
  1083.  
  1084. level notify("stop_spawn_profile");
  1085. }
  1086. }
  1087.  
  1088. spawnProfile()
  1089. {
  1090. level endon("stop_spawn_profile");
  1091.  
  1092. spawnObj = spawnStruct();
  1093.  
  1094. while(1)
  1095. {
  1096. /*
  1097.  
  1098. if ( level.players.size > 0 && level.spawnpoints.size > 0 )
  1099. {
  1100. playerNum = randomint(level.players.size);
  1101. player = level.players[playerNum];
  1102.  
  1103. if ( player.team != "allies" && player.team != "axis" )
  1104. continue;
  1105.  
  1106. if ( level.teamBased && (getDvar( "scr_spawnprofile" ) == "allies" || getDvar( "scr_spawnprofile" ) == "axis") && player.team != getDvar( "scr_spawnprofile" ) )
  1107. continue;
  1108.  
  1109. attempt = 1;
  1110. while ( !isdefined( player ) && attempt < level.players.size )
  1111. {
  1112. playerNum = ( playerNum + 1 ) % level.players.size;
  1113. attempt++;
  1114. player = level.players[playerNum];
  1115. }
  1116.  
  1117. player getSpawnpoint_NearTeam(level.spawnpoints);
  1118. }
  1119. */
  1120.  
  1121. dvarString = getDvar( "scr_spawnprofile" );
  1122.  
  1123. if ( dvarString != "allies" && dvarString != "axis" )
  1124. {
  1125. if ( cointoss() )
  1126. dvarString = "allies";
  1127. else
  1128. dvarString = "axis";
  1129. }
  1130.  
  1131. spawnObj.team = dvarString;
  1132. spawnObj.pers["team"] = dvarString;
  1133.  
  1134. spawnObj getSpawnpoint_NearTeam(level.spawnpoints);
  1135. wait ( 0.05 );
  1136. }
  1137. }
  1138.  
  1139. spawnGraphCheck()
  1140. {
  1141. while(1)
  1142. {
  1143. if ( getdvarint("scr_spawngraph") < 1 )
  1144. {
  1145. wait 3;
  1146. continue;
  1147. }
  1148. thread spawnGraph();
  1149. while ( getdvarint("scr_spawngraph") >= 1 )
  1150. {
  1151. wait .2;
  1152. continue;
  1153. }
  1154. level notify( "end_spawn_graph" );
  1155. level notify( "spawn_graph_stop_draw" );
  1156. }
  1157. }
  1158.  
  1159. spawnGraph()
  1160. {
  1161. level endon( "end_spawn_graph" );
  1162.  
  1163. w = 20;
  1164. h = 20;
  1165. weightscale = .1;
  1166. fakespawnpoints = [];
  1167.  
  1168. corners = getentarray("minimap_corner", "targetname");
  1169. if ( corners.size != 2 )
  1170. {
  1171. println("^1 can't spawn graph: no minimap corners");
  1172. return;
  1173. }
  1174. min = corners[0].origin;
  1175. max = corners[0].origin;
  1176. if ( corners[1].origin[0] > max[0] )
  1177. max = (corners[1].origin[0], max[1], max[2]);
  1178. else
  1179. min = (corners[1].origin[0], min[1], min[2]);
  1180. if ( corners[1].origin[1] > max[1] )
  1181. max = (max[0], corners[1].origin[1], max[2]);
  1182. else
  1183. min = (min[0], corners[1].origin[1], min[2]);
  1184.  
  1185. i = 0;
  1186. for ( y = 0; y < h; y++ )
  1187. {
  1188. yamnt = y / (h - 1);
  1189. for ( x = 0; x < w; x++ )
  1190. {
  1191. xamnt = x / (w - 1);
  1192. fakespawnpoints[i] = spawnstruct();
  1193. fakespawnpoints[i].origin = (min[0] * xamnt + max[0] * (1-xamnt), min[1] * yamnt + max[1] * (1-yamnt), min[2]);
  1194. fakespawnpoints[i].angles = (0,0,0);
  1195.  
  1196. fakespawnpoints[i].forward = anglesToForward( fakespawnpoints[i].angles );
  1197. fakespawnpoints[i].sightTracePoint = fakespawnpoints[i].origin;
  1198. fakespawnpoints[i].outside = true;
  1199. fakespawnpoints[i].secondfloor = false;
  1200. fakespawnpoints[i].fake = true;
  1201.  
  1202. i++;
  1203. }
  1204. }
  1205.  
  1206. didweights = false;
  1207.  
  1208. while(1)
  1209. {
  1210. spawni = 0;
  1211. numiters = 10;
  1212. for ( i = 0; i < numiters; i++ )
  1213. {
  1214. if ( !level.players.size || !isdefined( level.players[0].team ) || level.players[0].team == "spectator" || !isdefined( level.players[0].class ) )
  1215. break;
  1216.  
  1217. endspawni = spawni + fakespawnpoints.size / numiters;
  1218. if ( i == numiters - 1 )
  1219. endspawni = fakespawnpoints.size;
  1220.  
  1221. for ( ; spawni < endspawni; spawni++ )
  1222. {
  1223. spawnPointUpdate( fakespawnpoints[spawni] );
  1224. }
  1225.  
  1226. wait .05;
  1227. }
  1228.  
  1229. if ( !level.players.size || !isdefined( level.players[0].team ) || level.players[0].team == "spectator" || !isdefined( level.players[0].class ) )
  1230. {
  1231. wait 1;
  1232. continue;
  1233. }
  1234.  
  1235. level.players[0] getSpawnpoint_NearTeam( fakespawnpoints );
  1236.  
  1237. for ( i = 0; i < fakespawnpoints.size; i++ )
  1238. setupSpawnGraphPoint( fakespawnpoints[i], weightscale );
  1239.  
  1240. didweights = true;
  1241.  
  1242. level.players[0] drawSpawnGraph( fakespawnpoints, w, h, weightscale );
  1243.  
  1244. wait .05;
  1245. }
  1246. }
  1247.  
  1248. drawSpawnGraph( fakespawnpoints, w, h, weightscale )
  1249. {
  1250. level notify( "spawn_graph_stop_draw" );
  1251.  
  1252. i = 0;
  1253. for ( y = 0; y < h; y++ )
  1254. {
  1255. yamnt = y / (h - 1);
  1256. for ( x = 0; x < w; x++ )
  1257. {
  1258. xamnt = x / (w - 1);
  1259.  
  1260. if ( y > 0 )
  1261. {
  1262. thread spawnGraphLine( fakespawnpoints[i], fakespawnpoints[i-w], weightscale );
  1263. }
  1264. if ( x > 0 )
  1265. {
  1266. thread spawnGraphLine( fakespawnpoints[i], fakespawnpoints[i-1], weightscale );
  1267. }
  1268. i++;
  1269. }
  1270. }
  1271. }
  1272.  
  1273. setupSpawnGraphPoint( s1, weightscale )
  1274. {
  1275. s1.visible = true;
  1276. if ( s1.weight < -1000/weightscale )
  1277. {
  1278. s1.visible = false;
  1279. }
  1280. }
  1281.  
  1282. spawnGraphLine( s1, s2, weightscale )
  1283. {
  1284. if ( !s1.visible || !s2.visible )
  1285. return;
  1286.  
  1287. p1 = s1.origin + (0,0,s1.weight*weightscale + 100);
  1288. p2 = s2.origin + (0,0,s2.weight*weightscale + 100);
  1289.  
  1290. level endon( "spawn_graph_stop_draw" );
  1291.  
  1292. for ( ;; )
  1293. {
  1294. line( p1, p2, (1,1,1) );
  1295. wait .05;
  1296. waittillframeend;
  1297. }
  1298. }
  1299.  
  1300. loopbotspawns()
  1301. {
  1302. while(1)
  1303. {
  1304. if ( getdvarint("scr_killbots") < 1 )
  1305. {
  1306. wait 3;
  1307. continue;
  1308. }
  1309. if ( !isdefined( level.players ) )
  1310. {
  1311. wait .05;
  1312. continue;
  1313. }
  1314.  
  1315. bots = [];
  1316. for (i = 0; i < level.players.size; i++)
  1317. {
  1318. if ( !isdefined( level.players[i] ) )
  1319. continue;
  1320.  
  1321. if ( level.players[i].sessionstate == "playing" && issubstr(level.players[i].name, "bot") )
  1322. {
  1323. bots[bots.size] = level.players[i];
  1324. }
  1325. }
  1326. if ( bots.size > 0 )
  1327. {
  1328. if ( getdvarint( "scr_killbots" ) == 1 )
  1329. {
  1330. killer = bots[randomint(bots.size)];
  1331. victim = bots[randomint(bots.size)];
  1332.  
  1333. victim thread [[level.callbackPlayerDamage]] (
  1334. killer, // eInflictor The entity that causes the damage.(e.g. a turret)
  1335. killer, // eAttacker The entity that is attacking.
  1336. 1000, // iDamage Integer specifying the amount of damage done
  1337. 0, // iDFlags Integer specifying flags that are to be applied to the damage
  1338. "MOD_RIFLE_BULLET", // sMeansOfDeath Integer specifying the method of death
  1339. "none", // sWeapon The weapon number of the weapon used to inflict the damage
  1340. (0,0,0), // vPoint The point the damage is from?
  1341. (0,0,0), // vDir The direction of the damage
  1342. "none", // sHitLoc The location of the hit
  1343. 0 // psOffsetTime The time offset for the damage
  1344. );
  1345. }
  1346. else
  1347. {
  1348. numKills = getdvarint( "scr_killbots" );
  1349. lastVictim = undefined;
  1350. for ( index = 0; index < numKills; index++ )
  1351. {
  1352. killer = bots[randomint(bots.size)];
  1353. victim = bots[randomint(bots.size)];
  1354.  
  1355. while ( isDefined( lastVictim ) && victim == lastVictim )
  1356. victim = bots[randomint(bots.size)];
  1357.  
  1358. victim thread [[level.callbackPlayerDamage]] (
  1359. killer, // eInflictor The entity that causes the damage.(e.g. a turret)
  1360. killer, // eAttacker The entity that is attacking.
  1361. 1000, // iDamage Integer specifying the amount of damage done
  1362. 0, // iDFlags Integer specifying flags that are to be applied to the damage
  1363. "MOD_RIFLE_BULLET", // sMeansOfDeath Integer specifying the method of death
  1364. "none", // sWeapon The weapon number of the weapon used to inflict the damage
  1365. (0,0,0), // vPoint The point the damage is from?
  1366. (0,0,0), // vDir The direction of the damage
  1367. "none", // sHitLoc The location of the hit
  1368. 0 // psOffsetTime The time offset for the damage
  1369. );
  1370.  
  1371. lastVictim = victim;
  1372. }
  1373. }
  1374. }
  1375.  
  1376. if ( getdvarfloat( "scr_killbottimer" ) > .066 )
  1377. wait getdvarfloat( "scr_killbottimer" );
  1378. else
  1379. wait .05;
  1380. }
  1381. }
  1382.  
  1383. /#
  1384. spawnWeightDebug(spawnpoints, winner)
  1385. {
  1386. level notify("stop_spawn_weight_debug");
  1387. level endon("stop_spawn_weight_debug");
  1388. while(1)
  1389. {
  1390. if ( getdvarint("scr_spawnpointdebug") == 0 )
  1391. {
  1392. wait(3);
  1393. continue;
  1394. }
  1395.  
  1396. textoffset = (0,0,-12);
  1397. for (i = 0; i < spawnpoints.size; i++)
  1398. {
  1399. amnt = 1 * (1 - spawnpoints[i].weight / (-100000));
  1400. if (amnt < 0) amnt = 0;
  1401. if (amnt > 1) amnt = 1;
  1402.  
  1403. orig = spawnpoints[i].origin + (0,0,80);
  1404.  
  1405. print3d(orig, int(spawnpoints[i].weight), (1,amnt,.5));
  1406. orig += textoffset;
  1407.  
  1408. if ( spawnpoints[i] == winner )
  1409. {
  1410. print3d(orig, "Spawned " + self.name + " here", (1,amnt,.5));
  1411. orig += textoffset;
  1412. }
  1413.  
  1414. if (isdefined(spawnpoints[i].spawnData))
  1415. {
  1416. for (j = 0; j < spawnpoints[i].spawnData.size; j++)
  1417. {
  1418. print3d(orig, spawnpoints[i].spawnData[j], (.5,.5,.5));
  1419. orig += textoffset;
  1420. }
  1421. }
  1422.  
  1423. // "bar graph"
  1424. height = 0;
  1425. if ( spawnpoints[i].weight > -1000 )
  1426. height = (spawnpoints[i].weight + 1000) / 10;
  1427.  
  1428. amnt = spawnpoints[i].weight / 2000;
  1429. if (amnt < 0) amnt = 0;
  1430. if (amnt > 1) amnt = 1;
  1431.  
  1432. color = (1 - amnt, 1, 0);
  1433.  
  1434. pt1 = spawnpoints[i].origin + (0,0,95);
  1435. pt2 = spawnpoints[i].origin + (30,0,95);
  1436. pt3 = pt1 + (0,0,height);
  1437. pt4 = pt2 + (0,0,height);
  1438. line( pt1, pt2, color );
  1439. line( pt1, pt3, color );
  1440. line( pt2, pt4, color );
  1441. line( pt3, pt4, color );
  1442.  
  1443. if ( spawnpoints[i] == winner )
  1444. {
  1445. // checkmark
  1446. checkpt1 = pt3 + (0,0,30);
  1447. checkpt2 = pt3 + (10,0,10);
  1448. checkpt3 = pt3 + (30,0,50);
  1449.  
  1450. line( checkpt1, checkpt2, color );
  1451. line( checkpt2, checkpt3, color );
  1452. }
  1453. }
  1454. wait(.05);
  1455. }
  1456. }
  1457.  
  1458. profileDebug()
  1459. {
  1460. while(1)
  1461. {
  1462. if (getdvar("scr_spawnpointprofile") != "1") {
  1463. wait(3);
  1464. continue;
  1465. }
  1466.  
  1467. for (i = 0; i < level.spawnpoints.size; i++)
  1468. level.spawnpoints[i].weight = randomint(10000);
  1469. if (level.players.size > 0)
  1470. level.players[randomint(level.players.size)] getSpawnpoint_NearTeam(level.spawnpoints);
  1471.  
  1472. wait(.05);
  1473. }
  1474. }
  1475.  
  1476. debugNearbyPlayers(players, origin)
  1477. {
  1478. if ( getdvarint("scr_spawnpointdebug") == 0 )
  1479. return;
  1480.  
  1481. starttime = gettime();
  1482. while(1)
  1483. {
  1484. for (i = 0; i < players.size; i++)
  1485. line(players[i].origin, origin, (.5,1,.5));
  1486. if (gettime() - starttime > 5000)
  1487. return;
  1488. wait .05;
  1489. }
  1490. }
  1491. #/
  1492.  
  1493.  
  1494. trackGrenades()
  1495. {
  1496. while ( 1 )
  1497. {
  1498. level.grenades = getentarray("grenade", "classname");
  1499. wait .05;
  1500. }
  1501. }
  1502.  
  1503.  
  1504. trackMissiles()
  1505. {
  1506. for( ;; )
  1507. {
  1508. level.missiles = getentarray( "rocket", "classname" );
  1509. wait .05;
  1510. }
  1511. }
  1512.  
  1513.  
  1514. // used by spawning; needs to be fast.
  1515. isPointVulnerable(playerorigin)
  1516. {
  1517. pos = self.origin + level.claymoremodelcenteroffset;
  1518. playerpos = playerorigin + (0,0,32);
  1519. distsqrd = distancesquared(pos, playerpos);
  1520.  
  1521. forward = anglestoforward(self.angles);
  1522.  
  1523. if (distsqrd < level.claymoreDetectionRadius*level.claymoreDetectionRadius)
  1524. {
  1525. playerdir = vectornormalize(playerpos - pos);
  1526. angle = acos(vectordot(playerdir, forward));
  1527. if (angle < level.claymoreDetectionConeAngle) {
  1528. return true;
  1529. }
  1530. }
  1531. return false;
  1532. }
  1533.  
  1534.  
  1535. avoidWeaponDamage(spawnpoints)
  1536. {
  1537. //prof_begin(" spawn_complexgrenade");
  1538.  
  1539. weaponDamagePenalty = 100000;
  1540. if (getdvar("scr_spawnpointweaponpenalty") != "" && getdvar("scr_spawnpointweaponpenalty") != "0")
  1541. weaponDamagePenalty = getdvarfloat("scr_spawnpointweaponpenalty");
  1542.  
  1543. mingrenadedistsquared = 250*250; // (actual grenade radius is 220, 250 includes a safety area of 30 units)
  1544.  
  1545. for (i = 0; i < spawnpoints.size; i++)
  1546. {
  1547. for (j = 0; j < level.grenades.size; j++)
  1548. {
  1549. if ( !isdefined( level.grenades[j] ) )
  1550. continue;
  1551.  
  1552. // could also do a sight check to see if it's really dangerous.
  1553. if (distancesquared(spawnpoints[i].origin, level.grenades[j].origin) < mingrenadedistsquared)
  1554. {
  1555. spawnpoints[i].weight -= weaponDamagePenalty;
  1556. /#
  1557. spawnpoints[i].spawnData[spawnpoints[i].spawnData.size] = "Was near grenade: -" + int(weaponDamagePenalty);
  1558. #/
  1559. }
  1560. }
  1561.  
  1562. foreach( mine in level.mines )
  1563. {
  1564. if ( !isdefined( mine ) )
  1565. continue;
  1566.  
  1567. if ( distancesquared( spawnpoints[i].origin, mine.origin ) < mingrenadedistsquared)
  1568. {
  1569. spawnpoints[i].weight -= weaponDamagePenalty;
  1570.  
  1571. /#
  1572. spawnpoints[i].spawnData[spawnpoints[i].spawnData.size] = "Was near mine: -" + int(weaponDamagePenalty);
  1573. #/
  1574. }
  1575. }
  1576.  
  1577. if ( !isDefined( level.artilleryDangerCenters ) )
  1578. continue;
  1579.  
  1580. airstrikeDanger = maps\mp\killstreaks\_airstrike::getAirstrikeDanger( spawnpoints[i].origin ); // 0 = none, 1 = full, might be > 1 for more than 1 airstrike
  1581.  
  1582. if ( airstrikeDanger > 0 )
  1583. {
  1584. worsen = airstrikeDanger * weaponDamagePenalty;
  1585. spawnpoints[i].weight -= worsen;
  1586. /#
  1587. spawnpoints[i].spawnData[spawnpoints[i].spawnData.size] = "Was near artillery (" + int(airstrikeDanger*100) + "% danger): -" + int(worsen);
  1588. #/
  1589. }
  1590. }
  1591.  
  1592. //prof_end(" spawn_complexgrenade");
  1593. }
  1594.  
  1595. spawnPerFrameUpdate()
  1596. {
  1597. spawnpointindex = 0;
  1598.  
  1599. // each frame, do sight checks against a spawnpoint
  1600.  
  1601. while(1)
  1602. {
  1603. wait .05;
  1604.  
  1605. prof_begin("spawn_update");
  1606.  
  1607. //time = gettime();
  1608.  
  1609. if ( !isDefined( level.spawnPoints ) )
  1610. return;
  1611.  
  1612. spawnpointindex = (spawnpointindex + 1) % level.spawnPoints.size;
  1613.  
  1614. if ( getdvar( "scr_spawnpoint_forceindex" ) != "" )
  1615. spawnpointindex = getdvarint( "scr_spawnpoint_forceindex" );
  1616.  
  1617. spawnpoint = level.spawnPoints[spawnpointindex];
  1618.  
  1619. spawnPointUpdate( spawnpoint );
  1620.  
  1621. prof_end("spawn_update");
  1622. }
  1623. }
  1624.  
  1625. adjustSightValue( sightValue )
  1626. {
  1627. assert( sightValue >= 0 );
  1628. assert( sightValue <= 1 );
  1629. if ( sightValue <= 0 )
  1630. return 0;
  1631. if ( sightValue >= 1 )
  1632. return 1;
  1633. return sightValue * 0.5 + 0.25;
  1634. }
  1635.  
  1636. spawnPointUpdate( spawnpoint )
  1637. {
  1638. prof_begin( " spawn_update_init" );
  1639.  
  1640. if ( level.teambased )
  1641. {
  1642. spawnpoint.sights["axis"] = 0;
  1643. spawnpoint.sights["allies"] = 0;
  1644. }
  1645. else
  1646. {
  1647. spawnpoint.sights = 0;
  1648. }
  1649.  
  1650. spawnpointdir = spawnpoint.forward;
  1651.  
  1652. debug = false;
  1653. /#
  1654. debug = (getdvarint("scr_spawnpointdebug") > 0);
  1655.  
  1656. spawnpoint notify( "debug_stop_LOS" );
  1657. #/
  1658.  
  1659. spawnpoint.distSum["all"] = 0;
  1660. spawnpoint.distSum["allies"] = 0;
  1661. spawnpoint.distSum["axis"] = 0;
  1662.  
  1663. spawnpoint.weightedDistSum["all"] = 0;
  1664. spawnpoint.weightedDistSum["allies"] = 0;
  1665. spawnpoint.weightedDistSum["axis"] = 0;
  1666.  
  1667. spawnpoint.minDist["all"] = 9999999;
  1668. spawnpoint.minDist["allies"] = 9999999;
  1669. spawnpoint.minDist["axis"] = 9999999;
  1670.  
  1671. spawnpoint.numPlayersAtLastUpdate = 0;
  1672.  
  1673. totalPlayers["all"] = 0;
  1674. totalPlayers["allies"] = 0;
  1675. totalPlayers["axis"] = 0;
  1676.  
  1677. weightSum["all"] = 0;
  1678. weightSum["allies"] = 0;
  1679. weightSum["axis"] = 0;
  1680.  
  1681. winner = undefined;
  1682.  
  1683. curTime = getTime();
  1684.  
  1685. team = "all";
  1686. teambased = level.teambased;
  1687.  
  1688. prof_end( " spawn_update_init" );
  1689.  
  1690. prof_begin( " spawn_update_ploop" );
  1691.  
  1692. foreach ( player in level.players )
  1693. {
  1694. //prof_begin( " spawn_update_player" );
  1695.  
  1696. if ( player.sessionstate != "playing" )
  1697. {
  1698. //prof_end( " spawn_update_player" );
  1699. continue;
  1700. }
  1701.  
  1702. /*
  1703. playerSecondFloor = false;
  1704. if ( isDefined( level.spawnSecondFloorTrig ) && player isTouching( level.spawnSecondFloorTrig ) )
  1705. playerSecondFloor = true;
  1706. */
  1707.  
  1708. //prof_begin( " spawn_update_diff" );
  1709.  
  1710. diff = player.origin - spawnpoint.origin;
  1711. diff = (diff[0], diff[1], 0);
  1712.  
  1713. weight = 1.0; // default weight for weightedDistSum
  1714.  
  1715. dist = length( diff ); // needs to be actual distance for distSum value
  1716.  
  1717. //prof_end( " spawn_update_diff" );
  1718.  
  1719. //prof_begin( " spawn_update_team" );
  1720.  
  1721. if ( teambased )
  1722. team = player.team;
  1723.  
  1724. //prof_end( " spawn_update_team" );
  1725.  
  1726. //prof_begin( " spawn_update_nearby" );
  1727. if ( dist < spawnpoint.minDist[team] )
  1728. spawnpoint.minDist[team] = dist;
  1729. //prof_end( " spawn_update_nearby" );
  1730.  
  1731. //prof_begin( " spawn_update_weight" );
  1732. // tactical insertion weighting; players should not spawn too close to recent TI spawns
  1733. if ( player.wasTI && curTime - player.spawnTime < 15000 )
  1734. weight *= 0.1;
  1735.  
  1736. // sniper weight check
  1737. // note: weaponClass() is slow!
  1738. if ( player.isSniper )
  1739. weight *= 0.5;
  1740. //prof_end( " spawn_update_weight" );
  1741.  
  1742. //prof_begin( " spawn_update_sums" );
  1743. weightSum[ team ] += weight;
  1744. spawnpoint.weightedDistSum[ team ] += dist * weight;
  1745.  
  1746. spawnpoint.distSum[ team ] += dist;
  1747. spawnpoint.numPlayersAtLastUpdate++;
  1748.  
  1749. totalPlayers[team]++;
  1750. //prof_end( " spawn_update_sums" );
  1751.  
  1752. //prof_begin( " spawn_update_dot" );
  1753. pdir = anglestoforward(player.angles);
  1754. if (vectordot(spawnpointdir, diff) < 0 && vectordot(pdir, diff) > 0)
  1755. {
  1756. //prof_end( " spawn_update_dot" );
  1757. //prof_end( " spawn_update_player" );
  1758. continue; // player and spawnpoint are looking in opposite directions
  1759. }
  1760. //prof_end( " spawn_update_dot" );
  1761.  
  1762. /#
  1763. if ( isDefined( spawnpoint.fake ) )
  1764. {
  1765. //prof_end( " spawn_update_player" );
  1766. continue;
  1767. }
  1768. #/
  1769.  
  1770. // do sight check
  1771. /*
  1772. prof_begin( " spawn_update_told" );
  1773. losExists = bullettracepassed(player.origin + (0,0,50), spawnpoint.sightTracePoint, false, undefined);
  1774. prof_end( " spawn_update_told" );
  1775. */
  1776.  
  1777. prof_begin( " spawn_update_trace" );
  1778. sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, player.origin + (0,0,50) );
  1779. prof_end( " spawn_update_trace" );
  1780.  
  1781. //prof_begin( " spawn_update_losexists" );
  1782. spawnpoint.lastSightTraceTime = gettime();
  1783.  
  1784. if ( sightValue > 0 )
  1785. {
  1786. sightValue = adjustSightValue( sightvalue );
  1787. if ( teamBased )
  1788. spawnpoint.sights[team] += sightValue;
  1789. else
  1790. spawnpoint.sights += sightValue;
  1791.  
  1792. /#
  1793. if ( debug )
  1794. spawnpoint thread spawnpointDebugLOS( player.origin + (0,0,50) );
  1795. #/
  1796. }
  1797. //else
  1798. // line(player.origin + (0,0,50), spawnpoint.sightTracePoint, (1,.5,.5));
  1799.  
  1800. //prof_end( " spawn_update_losexists" );
  1801.  
  1802. //prof_end( " spawn_update_player" );
  1803. }
  1804.  
  1805. prof_end( " spawn_update_ploop" );
  1806.  
  1807. prof_begin( " spawn_update_other" );
  1808.  
  1809. nearbyEnemyRange = getFloatProperty( "scr_spawn_enemyavoiddist", 2000 );
  1810. nearbyEnemyPenalty = 2000; // typical base weights tend to peak around 1500 or so. this is large enough to upset that while only locally dominating it.
  1811.  
  1812. foreach ( team, value in weightSum )
  1813. {
  1814. if ( weightSum[team] )
  1815. spawnpoint.weightedDistSum[team] = spawnpoint.weightedDistSum[team] / weightSum[team] * totalPlayers[team];
  1816.  
  1817. nearbyPenalty = 0;
  1818. if ( spawnpoint.mindist[team] < nearbyEnemyRange )
  1819. nearbyPenalty = nearbyEnemyPenalty * (1 - spawnpoint.mindist[team] / nearbyEnemyRange);
  1820. spawnpoint.nearbyPenalty[team] = nearbyPenalty;
  1821. }
  1822.  
  1823.  
  1824. foreach ( tank in level.tanks )
  1825. {
  1826. sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, tank.origin + (0,0,50) );
  1827. spawnpoint.lastSightTraceTime = gettime();
  1828.  
  1829. if ( sightValue <= 0 )
  1830. continue;
  1831.  
  1832. sightValue = adjustSightValue( sightvalue );
  1833. if ( teamBased )
  1834. spawnpoint.sights[tank.team] += sightValue;
  1835. else
  1836. spawnpoint.sights += sightValue;
  1837.  
  1838. /#
  1839. if ( debug )
  1840. spawnpoint thread spawnpointDebugLOS( tank.origin + (0,0,50) );
  1841. #/
  1842. }
  1843.  
  1844. foreach ( turret in level.turrets )
  1845. {
  1846. if ( !isDefined( turret ) )
  1847. continue;
  1848.  
  1849. sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, turret.origin + (0,0,50) );
  1850. spawnpoint.lastSightTraceTime = gettime();
  1851.  
  1852. if ( sightValue <= 0 )
  1853. continue;
  1854.  
  1855. sightValue = adjustSightValue( sightvalue );
  1856. if ( teamBased )
  1857. spawnpoint.sights[turret.team] += sightValue;
  1858. else
  1859. spawnpoint.sights += sightValue;
  1860.  
  1861. /#
  1862. if ( debug )
  1863. spawnpoint thread spawnpointDebugLOS( turret.origin + (0,0,50) );
  1864. #/
  1865. }
  1866.  
  1867. foreach ( ims in level.ims )
  1868. {
  1869. if ( !isDefined( ims ) )
  1870. continue;
  1871.  
  1872. if ( !isDefined( ims.attackHeightPos ) )
  1873. continue;
  1874.  
  1875. sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, ims.attackHeightPos );
  1876. spawnpoint.lastSightTraceTime = gettime();
  1877.  
  1878. if ( sightValue <= 0 )
  1879. continue;
  1880.  
  1881. sightValue = adjustSightValue( sightvalue );
  1882. if ( teamBased )
  1883. spawnpoint.sights[ ims.team ] += sightValue;
  1884. else
  1885. spawnpoint.sights += sightValue;
  1886.  
  1887. /#
  1888. if( debug )
  1889. spawnpoint thread spawnpointDebugLOS( ims.attackHeightPos );
  1890. #/
  1891. }
  1892.  
  1893. foreach ( ugv in level.ugvs )
  1894. {
  1895. if ( !isDefined( ugv ) )
  1896. continue;
  1897.  
  1898. sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, ugv.origin + (0,0,50) );
  1899. spawnpoint.lastSightTraceTime = gettime();
  1900.  
  1901. if ( sightValue <= 0 )
  1902. continue;
  1903.  
  1904. sightValue = adjustSightValue( sightvalue );
  1905. if ( teamBased )
  1906. spawnpoint.sights[ugv.team] += sightValue;
  1907. else
  1908. spawnpoint.sights += sightValue;
  1909.  
  1910. /#
  1911. if ( debug )
  1912. spawnpoint thread spawnpointDebugLOS( ugv.origin + (0,0,50) );
  1913. #/
  1914. }
  1915.  
  1916. // Disabled to see if removal of the red boxes upon spawn is sufficient
  1917. // (helicopter traces also intentionally disabled)
  1918. /*
  1919. if ( spawnpoint.outside )
  1920. {
  1921. foreach ( heli in level.helis )
  1922. {
  1923. sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, heli.origin + (0,0,30) );
  1924. spawnpoint.lastSightTraceTime = gettime();
  1925.  
  1926. if ( sightValue <= 0 )
  1927. continue;
  1928.  
  1929. sightValue = adjustSightValue( sightvalue );
  1930. if ( teamBased )
  1931. spawnpoint.sights[heli.team] += sightValue;
  1932. else
  1933. spawnpoint.sights += sightValue;
  1934.  
  1935. /#
  1936. if ( debug )
  1937. spawnpoint thread spawnpointDebugLOS( heli.origin + (0,0,30) );
  1938. #/
  1939. }
  1940.  
  1941. foreach ( missile in level.missilesForSightTraces )
  1942. {
  1943. sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, missile.origin );
  1944. spawnpoint.lastSightTraceTime = gettime();
  1945.  
  1946. if ( sightValue <= 0 )
  1947. continue;
  1948.  
  1949. sightValue = adjustSightValue( sightvalue );
  1950. if ( teamBased )
  1951. spawnpoint.sights[missile.team] += sightValue;
  1952. else
  1953. spawnpoint.sights += sightValue;
  1954.  
  1955. /#
  1956. if ( debug )
  1957. spawnpoint thread spawnpointDebugLOS( missile.origin );
  1958. #/
  1959. }
  1960.  
  1961. if ( isDefined( level.ac130player ) && level.ac130player.team != "spectator" )
  1962. {
  1963. if ( teamBased )
  1964. spawnpoint.sights[level.ac130player.team]++;
  1965. else
  1966. spawnpoint.sights++;
  1967. }
  1968. }
  1969. */
  1970.  
  1971. prof_end( " spawn_update_other" );
  1972. }
  1973.  
  1974. /#
  1975. spawnpointDebugLOS( point )
  1976. {
  1977. // g_spawndebug is better for this
  1978. /*
  1979. self endon( "debug_stop_LOS" );
  1980. for ( ;; )
  1981. {
  1982. line( point, self.sightTracePoint, (1, .5, .5) );
  1983. wait .05;
  1984. }
  1985. */
  1986. }
  1987. #/
  1988.  
  1989. getLosPenalty()
  1990. {
  1991. if (getdvar("scr_spawnpointlospenalty") != "" && getdvar("scr_spawnpointlospenalty") != "0")
  1992. return getdvarfloat("scr_spawnpointlospenalty");
  1993. return 100000;
  1994. }
  1995.  
  1996. lastMinuteSightTraces( spawnpoint )
  1997. {
  1998. prof_begin(" spawn_final_lastminsc");
  1999.  
  2000. closest = undefined;
  2001. closestDistsq = 100000000.0;
  2002. secondClosest = undefined;
  2003. secondClosestDistsq = 100000000.0;
  2004. foreach ( player in level.players )
  2005. {
  2006. if ( player.team == self.team && level.teambased )
  2007. continue;
  2008. if ( player.sessionstate != "playing" )
  2009. continue;
  2010. if ( player == self )
  2011. continue;
  2012.  
  2013. distsq = distanceSquared( spawnpoint.origin, player.origin );
  2014. if ( distsq < closestDistsq )
  2015. {
  2016. secondClosest = closest;
  2017. secondClosestDistsq = closestDistsq;
  2018.  
  2019. closest = player;
  2020. closestDistSq = distsq;
  2021. }
  2022. else if ( distsq < secondClosestDistSq )
  2023. {
  2024. secondClosest = player;
  2025. secondClosestDistSq = distsq;
  2026. }
  2027. }
  2028.  
  2029. if ( isdefined( closest ) )
  2030. {
  2031. sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, closest.origin + (0,0,50) );
  2032. if ( sightValue > 0 )
  2033. {
  2034. sightValue = adjustSightValue( sightvalue );
  2035. prof_end(" spawn_final_lastminsc");
  2036. return sightValue;
  2037. }
  2038. }
  2039. if ( isdefined( secondClosest ) )
  2040. {
  2041. sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, secondClosest.origin + (0,0,50) );
  2042. if ( sightValue > 0 )
  2043. {
  2044. sightValue = adjustSightValue( sightvalue );
  2045. prof_end(" spawn_final_lastminsc");
  2046. return sightValue;
  2047. }
  2048. }
  2049.  
  2050. prof_end(" spawn_final_lastminsc");
  2051. return 0;
  2052. }
  2053.  
  2054.  
  2055. getRevengeSpawnPenalty()
  2056. {
  2057. penalty = getdvarfloat("scr_revengespawnpenalty", 25000 );
  2058. return penalty;
  2059. }
  2060.  
  2061.  
  2062. getRevengeSpawnDistanceSq()
  2063. {
  2064. dist = getdvarfloat("scr_revengespawndist", 1200 );
  2065. return dist * dist;
  2066. }
  2067.  
  2068.  
  2069. avoidRevengeSpawn(spawnpoints, deathpos)
  2070. {
  2071. mindistsq = getRevengeSpawnDistanceSq();
  2072. penalty = getRevengeSpawnPenalty();
  2073.  
  2074. foreach( spawnpoint in spawnpoints )
  2075. {
  2076. distsq = distanceSquared( spawnpoint.origin, deathpos );
  2077. if ( distsq < mindistsq )
  2078. {
  2079. spawnpoint.weight -= penalty;
  2080. /#
  2081. spawnpoint.spawnData[spawnpoint.spawnData.size] = "Revenge spawn: " + int(distsq) + " < " + int(mindistsq) + ", -" + int(penalty);
  2082. #/
  2083. }
  2084. }
  2085.  
  2086. if ( isDefined( self.lastAttacker ) && isDefined( self.lastAttacker.origin ) )
  2087. self avoidRevengeSpawnStage2( spawnpoints, self.lastAttacker.origin );
  2088.  
  2089. }
  2090.  
  2091. avoidRevengeSpawnStage2( spawnpoints, attackerPos )
  2092. {
  2093. mindistsq = getRevengeSpawnDistanceSq();
  2094. penalty = getRevengeSpawnPenalty();
  2095.  
  2096. foreach( spawnpoint in spawnpoints )
  2097. {
  2098. distsq = distanceSquared( spawnpoint.origin, attackerPos );
  2099. if ( distsq < mindistsq )
  2100. {
  2101. spawnpoint.weight -= penalty;
  2102. /#
  2103. spawnpoint.spawnData[spawnpoint.spawnData.size] = "Revenge spawn Attacker: " + int(distsq) + " < " + int(mindistsq) + ", -" + int(penalty);
  2104. #/
  2105. }
  2106. }
  2107. }
  2108.  
  2109. avoidVisibleEnemies(spawnpoints, teambased)
  2110. {
  2111. //prof_begin(" spawn_complexsc");
  2112.  
  2113. lospenalty = getLosPenalty();
  2114.  
  2115. otherteam = "axis";
  2116. if ( self.team == "axis" )
  2117. otherteam = "allies";
  2118.  
  2119. if ( teambased )
  2120. {
  2121. foreach ( spawnpoint in spawnpoints )
  2122. {
  2123. penalty = lospenalty * spawnpoint.sights[otherteam];
  2124. spawnpoint.weight -= penalty;
  2125.  
  2126. /#
  2127. if ( penalty > 0 )
  2128. spawnpoint.spawnData[spawnpoint.spawnData.size] = "Sight traces: -" + int(penalty);
  2129. #/
  2130. }
  2131. }
  2132. else
  2133. {
  2134. foreach ( spawnpoint in spawnpoints )
  2135. {
  2136. penalty = lospenalty * spawnpoint.sights;
  2137. spawnpoint.weight -= penalty;
  2138.  
  2139. /#
  2140. if ( penalty > 0 )
  2141. spawnpoint.spawnData[spawnpoint.spawnData.size] = "Sight traces: -" + int(penalty);
  2142. #/
  2143. }
  2144.  
  2145. otherteam = "all";
  2146. }
  2147.  
  2148. foreach ( spawnpoint in spawnpoints )
  2149. {
  2150. // penalty for nearby enemies
  2151. spawnpoint.weight -= spawnpoint.nearbyPenalty[otherteam];
  2152. /#
  2153. if ( spawnpoint.nearbyPenalty[otherteam] != 0 )
  2154. spawnpoint.spawnData[spawnpoint.spawnData.size] = "Nearest enemy at " + int(spawnpoint.minDist[otherteam]) + " units: -" + int(spawnpoint.nearbyPenalty[otherteam]);
  2155. #/
  2156.  
  2157. if ( positionWouldTelefrag( spawnpoint.origin ) )
  2158. {
  2159. telefragCount = 1;
  2160.  
  2161. foreach ( alternate in spawnpoint.alternates )
  2162. {
  2163. if ( positionWouldTelefrag( alternate ) )
  2164. telefragCount++;
  2165. else
  2166. break;
  2167. }
  2168.  
  2169. penalty = 100000;
  2170. if ( telefragCount < spawnpoint.alternates.size + 1 )
  2171. {
  2172. penalty = 1500 * telefragCount;
  2173. if ( isDefined( self.forceSpawnNearTeammates ) )
  2174. penalty = 0;
  2175. }
  2176.  
  2177. spawnpoint.weight -= penalty;
  2178. /#
  2179. spawnpoint.spawnData[spawnpoint.spawnData.size] = "Would telefrag " + telefragCount + " times: -" + penalty;
  2180. #/
  2181. }
  2182. }
  2183.  
  2184. // DEBUG
  2185. //prof_end(" spawn_complexsc");
  2186. }
  2187.  
  2188. avoidSpawnReuse(spawnpoints, teambased)
  2189. {
  2190. // DEBUG
  2191. //prof_begin(" spawn_complexreuse");
  2192.  
  2193. time = getTime();
  2194.  
  2195. maxtime = 10*1000;
  2196. maxdistSq = 1024 * 1024;
  2197.  
  2198. foreach ( spawnpoint in spawnpoints )
  2199. {
  2200. lastspawnedplayer = spawnpoint.lastspawnedplayer;
  2201.  
  2202. if ( !isalive( lastspawnedplayer ) )
  2203. continue;
  2204.  
  2205. if ( teambased && spawnpoint.lastspawnedplayer.team == self.team )
  2206. continue;
  2207. if ( spawnpoint.lastspawnedplayer == self )
  2208. continue;
  2209.  
  2210. timepassed = time - spawnpoint.lastspawntime;
  2211. if ( timepassed < maxtime )
  2212. {
  2213. distSq = distanceSquared( spawnpoint.lastspawnedplayer.origin, spawnpoint.origin );
  2214. if (distSq < maxdistSq)
  2215. {
  2216. worsen = 5000 * (1 - distSq/maxdistSq) * (1 - timepassed/maxtime);
  2217. spawnpoint.weight -= worsen;
  2218. /#
  2219. spawnpoint.spawnData[spawnpoint.spawnData.size] = "Recently spawned enemy: -" + worsen;
  2220. #/
  2221. }
  2222. else
  2223. spawnpoint.lastspawnedplayer = undefined; // don't worry any more about this spawnpoint
  2224. }
  2225. else
  2226. spawnpoint.lastspawnedplayer = undefined; // don't worry any more about this spawnpoint
  2227. }
  2228.  
  2229. //prof_end(" spawn_complexreuse");
  2230. }
  2231.  
  2232. avoidSameSpawn()
  2233. {
  2234. //prof_begin(" spawn_complexsamespwn");
  2235.  
  2236. spawnpoint = self.lastspawnpoint;
  2237.  
  2238. if ( !isdefined( spawnpoint ) || !isdefined( spawnpoint.weight ) )
  2239. {
  2240. //prof_end(" spawn_complexsamespwn");
  2241. return;
  2242. }
  2243.  
  2244. spawnpoint.weight -= 1000;
  2245. /#
  2246. spawnpoint.spawnData[spawnpoint.spawnData.size] = "Was last spawnpoint: -1000";
  2247. #/
  2248.  
  2249. //prof_end(" spawn_complexsamespwn");
  2250. }
  2251.  
  2252. SetupKillstreakSpawnShield()
  2253. {
  2254. level.killstreakSpawnShield = 5000;
  2255. if ( getDvar( "killstreakSpawnShield" ) != "" )
  2256. {
  2257. newLimit = getDvarInt( "killstreakSpawnShield" );
  2258. if ( (newLimit >= 0) && (newLimit <= 10000) )
  2259. level.killstreakSpawnShield = newLimit;
  2260. }
  2261. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement