Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include common_scripts\utility;
- #include maps\mp\_utility;
- findBoxCenter( mins, maxs )
- {
- center = ( 0, 0, 0 );
- center = maxs - mins;
- center = ( center[0]/2, center[1]/2, center[2]/2 ) + mins;
- return center;
- }
- expandMins( mins, point )
- {
- if ( mins[0] > point[0] )
- mins = ( point[0], mins[1], mins[2] );
- if ( mins[1] > point[1] )
- mins = ( mins[0], point[1], mins[2] );
- if ( mins[2] > point[2] )
- mins = ( mins[0], mins[1], point[2] );
- return mins;
- }
- expandMaxs( maxs, point )
- {
- if ( maxs[0] < point[0] )
- maxs = ( point[0], maxs[1], maxs[2] );
- if ( maxs[1] < point[1] )
- maxs = ( maxs[0], point[1], maxs[2] );
- if ( maxs[2] < point[2] )
- maxs = ( maxs[0], maxs[1], point[2] );
- return maxs;
- }
- addSpawnPoints( team, spawnPointName, isSetOptional )
- {
- if ( !isDefined( isSetOptional ) )
- isSetOptional = false;
- oldSpawnPoints = [];
- if ( level.teamSpawnPoints[team].size )
- oldSpawnPoints = level.teamSpawnPoints[team];
- level.teamSpawnPoints[team] = getSpawnpointArray( spawnPointName );
- if ( !level.teamSpawnPoints[team].size && !isSetOptional )
- {
- println( "^1Error: No " + spawnPointName + " spawnpoints found in level!" );
- maps\mp\gametypes\_callbacksetup::AbortLevel();
- wait 1; // so we don't try to abort more than once before the frame ends
- return;
- }
- if ( !isDefined( level.spawnpoints ) )
- level.spawnpoints = [];
- for ( index = 0; index < level.teamSpawnPoints[team].size; index++ )
- {
- spawnpoint = level.teamSpawnPoints[team][index];
- if ( !isdefined( spawnpoint.inited ) )
- {
- spawnpoint spawnPointInit();
- level.spawnpoints[ level.spawnpoints.size ] = spawnpoint;
- }
- }
- for ( index = 0; index < oldSpawnPoints.size; index++ )
- {
- origin = oldSpawnPoints[index].origin;
- // are these 2 lines necessary? we already did it in spawnPointInit
- level.spawnMins = expandMins( level.spawnMins, origin );
- level.spawnMaxs = expandMaxs( level.spawnMaxs, origin );
- level.teamSpawnPoints[team][ level.teamSpawnPoints[team].size ] = oldSpawnPoints[index];
- }
- }
- placeSpawnPoints( spawnPointName )
- {
- spawnPoints = getSpawnpointArray( spawnPointName );
- /#
- if ( !isDefined( level.extraspawnpointsused ) )
- level.extraspawnpointsused = [];
- #/
- if ( !spawnPoints.size )
- {
- println( "^1Error: No " + spawnPointName + " spawnpoints found in level!" );
- maps\mp\gametypes\_callbacksetup::AbortLevel();
- wait 1; // so we don't try to abort more than once before the frame ends
- return;
- }
- for( index = 0; index < spawnPoints.size; index++ )
- {
- spawnPoints[index] spawnPointInit();
- // don't add this spawnpoint to level.spawnpoints,
- // because it's an unimportant one that we don't want to do sight traces to
- /#
- spawnPoints[index].fakeclassname = spawnPointName;
- level.extraspawnpointsused[ level.extraspawnpointsused.size ] = spawnPoints[index];
- #/
- }
- }
- getSpawnpointArray( classname )
- {
- spawnPoints = getEntArray( classname, "classname" );
- if ( !isdefined( level.extraspawnpoints ) || !isdefined( level.extraspawnpoints[classname] ) )
- return spawnPoints;
- for ( i = 0; i < level.extraspawnpoints[classname].size; i++ )
- {
- spawnPoints[ spawnPoints.size ] = level.extraspawnpoints[classname][i];
- }
- return spawnPoints;
- }
- expandSpawnpointBounds( classname )
- {
- spawnPoints = getSpawnpointArray( classname );
- for( index = 0; index < spawnPoints.size; index++ )
- {
- level.spawnMins = expandMins( level.spawnMins, spawnPoints[index].origin );
- level.spawnMaxs = expandMaxs( level.spawnMaxs, spawnPoints[index].origin );
- }
- }
- setMapCenterForReflections()
- {
- level.spawnMins = (0,0,0);
- level.spawnMaxs = (0,0,0);
- maps\mp\gametypes\_spawnlogic::expandSpawnpointBounds( "mp_tdm_spawn_allies_start" );
- maps\mp\gametypes\_spawnlogic::expandSpawnpointBounds( "mp_tdm_spawn_axis_start" );
- level.mapCenter = maps\mp\gametypes\_spawnlogic::findBoxCenter( level.spawnMins, level.spawnMaxs );
- setMapCenter( level.mapCenter );
- }
- // initspawnpoint()
- spawnPointInit()
- {
- spawnpoint = self;
- origin = spawnpoint.origin;
- level.spawnMins = expandMins( level.spawnMins, origin );
- level.spawnMaxs = expandMaxs( level.spawnMaxs, origin );
- spawnpoint placeSpawnpoint();
- spawnpoint.forward = anglesToForward( spawnpoint.angles );
- spawnpoint.sightTracePoint = spawnpoint.origin + (0,0,50);
- spawnpoint.lastspawnedplayer = spawnpoint; // just want this to be any entity for which isalive() returns false
- spawnpoint.lastspawntime = gettime();
- skyHeight = 1024;
- spawnpoint.outside = true;
- if ( !bullettracepassed( spawnpoint.sightTracePoint, spawnpoint.sightTracePoint + (0,0,skyHeight), false, undefined) )
- {
- startpoint = spawnpoint.sightTracePoint + spawnpoint.forward * 100;
- if ( !bullettracepassed( startpoint, startpoint + (0,0,skyHeight), false, undefined) )
- spawnpoint.outside = false;
- }
- right = anglesToRight( spawnpoint.angles );
- spawnpoint.alternates = [];
- AddAlternateSpawnpoint( spawnpoint, spawnpoint.origin + right * 45 );
- AddAlternateSpawnpoint( spawnpoint, spawnpoint.origin - right * 45 );
- //AddAlternateSpawnpoint( spawnpoint, spawnpoint.origin + spawnpoint.forward * 45 );
- /*
- spawnpoint.secondFloor = false;
- if ( isDefined( level.spawnSecondFloorTrig ) )
- {
- spawnpoint.secondFloor = (spawnpoint isTouching( level.spawnSecondFloorTrig ));
- spawnpoint.floorTransitionDistances = [];
- for ( pointIndex = 0; pointIndex < level.spawnFloorTransitions.size; pointIndex++ )
- {
- spawnpoint.floorTransitionDistances[ pointIndex ] = distance( level.spawnFloorTransitions[ pointIndex ], spawnpoint.origin );
- }
- }
- */
- spawnPointUpdate( spawnpoint );
- spawnpoint.inited = true;
- }
- AddAlternateSpawnpoint( spawnpoint, alternatepos )
- {
- spawnpointposRaised = playerPhysicsTrace( spawnpoint.origin, spawnpoint.origin + (0,0,18), false, undefined );
- zdiff = spawnpointposRaised[2] - spawnpoint.origin[2];
- alternateposRaised = (alternatepos[0], alternatepos[1], alternatepos[2] + zdiff );
- traceResult = playerPhysicsTrace( spawnpointposRaised, alternateposRaised, false, undefined );
- if ( traceResult != alternateposRaised )
- return;
- finalAlternatePos = playerPhysicsTrace( alternateposRaised, alternatepos );
- spawnpoint.alternates[ spawnpoint.alternates.size ] = finalAlternatePos;
- }
- getTeamSpawnPoints( team )
- {
- return level.teamSpawnPoints[team];
- }
- // selects a spawnpoint, preferring ones with heigher weights (or toward the beginning of the array if no weights).
- // also does final things like setting self.lastspawnpoint to the one chosen.
- // this takes care of avoiding telefragging, so it doesn't have to be considered by any other function.
- getSpawnpoint_Final( spawnpoints, useweights )
- {
- prof_begin( "spawn_final" );
- bestspawnpoint = undefined;
- if ( !isdefined( spawnpoints ) || spawnpoints.size == 0 )
- return undefined;
- if ( !isdefined( useweights ) )
- useweights = true;
- if ( useweights )
- {
- // choose spawnpoint with best weight
- // (if a tie, choose randomly from the best)
- bestspawnpoint = getBestWeightedSpawnpoint( spawnpoints );
- /#
- thread spawnWeightDebug( spawnpoints, bestspawnpoint );
- #/
- }
- else
- {
- carePackages = getEntArray( "care_package", "targetname" );
- // (only place we actually get here from is getSpawnpoint_Random() )
- // no weights. prefer spawnpoints toward beginning of array
- for ( i = 0; i < spawnpoints.size; i++ )
- {
- if( isdefined( self.lastspawnpoint ) && self.lastspawnpoint == spawnpoints[i] )
- continue;
- if ( positionWouldTelefrag( spawnpoints[i].origin ) )
- continue;
- if ( carePackages.size && !canSpawn( spawnpoints[i].origin ) )
- continue;
- bestspawnpoint = spawnpoints[i];
- break;
- }
- if ( !isdefined( bestspawnpoint ) )
- {
- // Couldn't find a useable spawnpoint. All spawnpoints either telefragged or were our last spawnpoint
- // Our only hope is our last spawnpoint - unless it too will telefrag...
- if ( isdefined( self.lastspawnpoint ) && !positionWouldTelefrag( self.lastspawnpoint.origin ) )
- {
- // (make sure our last spawnpoint is in the valid array of spawnpoints to use)
- for ( i = 0; i < spawnpoints.size; i++ )
- {
- if ( spawnpoints[i] == self.lastspawnpoint )
- {
- bestspawnpoint = spawnpoints[i];
- break;
- }
- }
- }
- }
- }
- if ( !isdefined( bestspawnpoint ) )
- {
- // couldn't find a useable spawnpoint! all will telefrag.
- if ( useweights )
- {
- // at this point, forget about weights. just take a random one.
- bestspawnpoint = spawnpoints[randomint(spawnpoints.size)];
- }
- else
- {
- bestspawnpoint = spawnpoints[0];
- }
- }
- prof_end( "spawn_final" );
- return bestspawnpoint;
- }
- finalizeSpawnpointChoice( spawnpoint )
- {
- time = getTime();
- self.lastspawnpoint = spawnpoint;
- self.lastspawntime = time;
- spawnpoint.lastspawnedplayer = self;
- spawnpoint.lastspawntime = time;
- }
- maxSightTracedSpawnpoints = 3;
- getBestWeightedSpawnpoint( spawnpoints )
- {
- otherteam = getOtherTeam( self.team );
- assert( spawnpoints.size > 0 );
- for ( try = 0; ; try++ )
- {
- bestspawnpoints = [];
- bestspawnpoints[0] = spawnpoints[0];
- bestweight = spawnpoints[0].weight;
- for ( i = 1; i < spawnpoints.size; i++ )
- {
- spawnpoint = spawnpoints[i];
- if ( spawnpoint.weight > bestweight )
- {
- bestspawnpoints = [];
- bestspawnpoints[0] = spawnpoint;
- bestweight = spawnpoint.weight;
- }
- else if ( spawnpoint.weight == bestweight )
- {
- bestspawnpoints[bestspawnpoints.size] = spawnpoint;
- }
- }
- // pick randomly from the available spawnpoints with the best weight
- assert( bestspawnpoints.size > 0 );
- bestspawnpoint = bestspawnpoints[randomint( bestspawnpoints.size )];
- if ( try >= maxSightTracedSpawnpoints )
- {
- println( "Spawning " + self.name + " at spawnpoint " + bestspawnpoint.origin + " because the " + maxSightTracedSpawnpoints + " best spawnpoints failed last minute sight trace tests." );
- /# DumpSpawnData( spawnpoints, bestspawnpoint ); #/
- return bestspawnpoint;
- }
- // 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.
- sights = 0;
- if ( level.teambased )
- sights = bestspawnpoint.sights[otherteam];
- else
- sights = bestspawnpoint.sights;
- if ( sights > 0 )
- {
- println( "Spawning " + self.name + " at spawnpoint " + bestspawnpoint.origin + " even though " + sights + " lines of sight to the enemy exist." );
- /# DumpSpawnData( spawnpoints, bestspawnpoint ); #/
- return bestspawnpoint;
- }
- if ( isdefined( bestspawnpoint.lastSightTraceTime ) && bestspawnpoint.lastSightTraceTime == gettime() )
- return bestspawnpoint;
- sightValue = lastMinuteSightTraces( bestspawnpoint );
- if ( sightValue == 0 )
- return bestspawnpoint;
- sightValue = adjustSightValue( sightvalue );
- if ( level.teambased )
- bestspawnpoint.sights[otherteam] += sightValue;
- else
- bestspawnpoint.sights += sightValue;
- penalty = getLosPenalty() * sightValue;
- /#
- bestspawnpoint.spawnData[bestspawnpoint.spawnData.size] = "Last minute sight trace: -" + penalty;
- #/
- bestspawnpoint.weight -= penalty;
- bestspawnpoint.lastSightTraceTime = gettime();
- }
- assertmsg( "can't get here" );
- }
- /#
- DumpSpawnData( spawnpoints, winnerspawnpoint )
- {
- if ( getSubStr( self.name, 0, 3 ) == "bot" )
- {
- if ( getdvarint("scr_spawnpointdebug") == 0 )
- return;
- }
- println( "=================================" );
- println( "spawndata = spawnstruct();" );
- println( "spawndata.playername = \"" + self.name + "\";" );
- println( "spawndata.friends = [];" );
- println( "spawndata.enemies = [];" );
- foreach ( player in level.players )
- {
- if ( player.team == self.team )
- println( "spawndata.friends[ spawndata.friends.size ] = " + player.origin + ";" );
- else
- println( "spawndata.enemies[ spawndata.enemies.size ] = " + player.origin + ";" );
- }
- println( "spawndata.otherdata = [];" );
- println( "spawndata.spawnpoints = [];" );
- index = 0;
- foreach ( spawnpoint in spawnpoints )
- {
- if ( spawnpoint == winnerspawnpoint )
- println( "spawndata.spawnpointwinner = " + index + ";" );
- println( "spawnpoint = spawnstruct();" );
- println( "spawnpoint.weight = " + spawnpoint.weight + ";" );
- println( "spawnpoint.origin = " + spawnpoint.origin + ";" );
- println( "spawnpoint.spawndata = [];" );
- for ( i = 0; i < spawnpoint.spawndata.size; i++ )
- {
- println( "spawnpoint.spawndata[" + i + "] = \"" + spawnpoint.spawndata[i] + "\";" );
- }
- println( "spawndata.spawnpoints[spawndata.spawnpoints.size] = spawnpoint;" );
- index++;
- }
- println( "=================================" );
- }
- DrawRecordedSpawnData()
- {
- spawndata = undefined;
- // to remove line beginnings from console log, use regexp: ^\[.*\]
- // ====================================
- // paste console log output in here
- // ====================================
- if ( isDefined( spawndata ) )
- thread drawSpawnData( spawndata );
- }
- checkBad( spawnpoint )
- {
- for ( i = 0; i < level.players.size; i++ )
- {
- player = level.players[i];
- if ( !isAlive( player ) || player.sessionstate != "playing" )
- continue;
- if ( level.teambased && player.team == self.team )
- continue;
- losExists = bullettracepassed(player.origin + (0,0,50), spawnpoint.sightTracePoint, false, undefined);
- if ( losExists )
- thread badSpawnLine( spawnpoint.sightTracePoint, player.origin + (0,0,50), self.name, player.name );
- }
- }
- badSpawnLine( start, end, name1, name2 )
- {
- dist = distance(start,end);
- for ( i = 0; i < 20 * 10; i++ )
- {
- line( start, end, (1,0,0) );
- print3d( start, "Bad spawn! " + name1 + ", dist = " + dist );
- print3d( end, name2 );
- wait .05;
- }
- }
- drawSpawnData( spawndata )
- {
- level notify("drawing_spawn_data");
- level endon("drawing_spawn_data");
- textoffset = (0,0,-12);
- fakeplayer = spawnstruct();
- fakeplayer.name = spawndata.playername;
- fakeplayer thread spawnWeightDebug( spawndata.spawnpoints, spawndata.spawnpoints[spawndata.spawnpointwinner] );
- while(1)
- {
- for (i = 0; i < spawndata.friends.size; i++)
- {
- print3d(spawndata.friends[i], "=)", (.5,1,.5), 1, 5);
- }
- for (i = 0; i < spawndata.enemies.size; i++)
- {
- print3d(spawndata.enemies[i], "=(", (1,.5,.5), 1, 5);
- }
- for (i = 0; i < spawndata.otherdata.size; i++)
- {
- print3d(spawndata.otherdata[i].origin, spawndata.otherdata[i].text, (.5,.75,1), 1, 2);
- }
- wait .05;
- }
- }
- #/
- getSpawnpoint_Random(spawnpoints)
- {
- // level endon("game_ended");
- // There are no valid spawnpoints in the map
- if(!isdefined(spawnpoints))
- return undefined;
- // randomize order
- for ( i = 0; i < spawnpoints.size; i++ )
- {
- j = randomInt(spawnpoints.size);
- spawnpoint = spawnpoints[i];
- spawnpoints[i] = spawnpoints[j];
- spawnpoints[j] = spawnpoint;
- }
- if ( isDefined( self.predictedSpawnPoint ) )
- {
- // if we predicted spawning at one of these spawnpoints already, favor that one.
- for ( i = 1; i < spawnpoints.size; i++ )
- {
- if ( spawnpoints[i] == self.predictedSpawnPoint )
- {
- temp = spawnpoints[0];
- spawnpoints[0] = spawnpoints[i];
- spawnpoints[i] = temp;
- break;
- }
- }
- }
- return getSpawnpoint_Final(spawnpoints, false);
- }
- getAllOtherPlayers()
- {
- aliveplayers = [];
- // Make a list of fully connected, non-spectating, alive players
- for(i = 0; i < level.players.size; i++)
- {
- if ( !isdefined( level.players[i] ) )
- continue;
- player = level.players[i];
- if ( player.sessionstate != "playing" || player == self )
- continue;
- aliveplayers[aliveplayers.size] = player;
- }
- return aliveplayers;
- }
- // weight array manipulation code
- initWeights(spawnpoints)
- {
- for (i = 0; i < spawnpoints.size; i++)
- spawnpoints[i].weight = 0;
- /#
- for (i = 0; i < spawnpoints.size; i++) {
- spawnpoints[i].spawnData = [];
- }
- #/
- }
- // ================================================
- getSpawnpoint_NearTeam( spawnpoints, favoredspawnpoints )
- {
- // level endon("game_ended");
- /*if ( self.wantSafeSpawn )
- {
- return getSpawnpoint_SafeSpawn( spawnpoints );
- }*/
- // There are no valid spawnpoints in the map
- if(!isdefined(spawnpoints))
- return undefined;
- /#
- setDevDvarIfUninitialized("scr_spawn_randomly", "0");
- if ( getdvarint("scr_spawn_randomly") == 1 )
- return getSpawnpoint_Random( spawnpoints );
- #/
- prof_begin("spawn_basiclogic");
- /#
- if ( getdvarint("scr_spawnsimple") > 0 )
- return getSpawnpoint_Random( spawnpoints );
- #/
- Spawnlogic_Begin();
- initWeights(spawnpoints);
- obj = spawnstruct();
- alliedDistanceWeight = 2;
- //prof_begin(" spawn_basicsumdists");
- myTeam = self.team;
- enemyTeam = getOtherTeam( myTeam );
- carePackages = getEntArray( "care_package", "targetname" );
- foreach ( spawnpoint in spawnpoints )
- {
- if ( spawnpoint.numPlayersAtLastUpdate > 0 )
- {
- allyDistSum = spawnpoint.weightedDistSum[ myTeam ]; // we weight the allied distSum to account for things like snipers and tactical insertion
- enemyDistSum = spawnpoint.distSum[ enemyTeam ];
- // high enemy distance is good, high ally distance is bad
- spawnpoint.weight = (enemyDistSum - alliedDistanceWeight*allyDistSum) / spawnpoint.numPlayersAtLastUpdate;
- /#
- spawnpoint.spawnData[spawnpoint.spawnData.size] = "Base weight: " + int(spawnpoint.weight) + " = (" + int(enemyDistSum) + " - " + alliedDistanceWeight + "*" + int(allyDistSum) + ") / " + spawnpoint.numPlayersAtLastUpdate;
- #/
- }
- else
- {
- spawnpoint.weight = 0;
- /#
- spawnpoint.spawnData[spawnpoint.spawnData.size] = "Base weight: 0";
- #/
- }
- if ( carePackages.size && !canSpawn( spawnpoint.origin ) )
- spawnpoint.weight -= 500000;
- }
- //prof_end(" spawn_basicsumdists");
- if ( isdefined( favoredspawnpoints ) )
- {
- for (i = 0; i < favoredspawnpoints.size; i++)
- {
- favoredspawnpoints[i].weight += 50000;
- /#
- favoredspawnpoints[i].spawnData[favoredspawnpoints[i].spawnData.size] = "Favored: 50000";
- #/
- }
- }
- if ( isDefined( self.predictedSpawnPoint ) && isDefined( self.predictedSpawnPoint.weight ) )
- {
- // add a tiebreaker in case we end up choosing between spawnpoints of similar weight
- self.predictedSpawnPoint.weight += 100;
- /#
- self.predictedSpawnPoint.spawnData[self.predictedSpawnPoint.spawnData.size] = "Predicted: 100";
- #/
- }
- prof_end("spawn_basiclogic");
- prof_begin("spawn_complexlogic");
- avoidSameSpawn();
- // not avoiding spawn reuse because it doesn't do anything nearbyPenalty doesn't do
- //avoidSpawnReuse(spawnpoints, true);
- // not avoiding spawning near recent deaths for team-based modes. kills the fast pace.
- //avoidDangerousSpawns(spawnpoints, true);
- avoidWeaponDamage(spawnpoints);
- avoidVisibleEnemies(spawnpoints, true);
- prof_end("spawn_complexlogic");
- result = getSpawnpoint_Final(spawnpoints);
- /#
- setdevdvarIfUninitialized("scr_spawn_showbad", "0");
- if ( getdvarint("scr_spawn_showbad") == 1 )
- checkBad( result );
- #/
- return result;
- }
- getSpawnpoint_SafeSpawn( spawnpoints )
- {
- // There are no valid spawnpoints in the map
- if ( !isdefined( spawnpoints ) )
- return undefined;
- assert( spawnpoints.size > 0 );
- Spawnlogic_Begin();
- safestSpawnpoint = undefined;
- safestDangerDist = undefined;
- enemyTeam = getOtherTeam( self.team );
- if ( !level.teambased )
- enemyTeam = "all";
- mingrenadedistsquared = 500 * 500;
- foreach ( spawnpoint in spawnpoints )
- {
- dangerDist = spawnpoint.minDist[ enemyTeam ];
- foreach ( grenade in level.grenades )
- {
- if ( !isdefined( grenade ) )
- continue;
- if ( distancesquared( spawnpoint.origin, grenade.origin ) < mingrenadedistsquared )
- {
- grenadeDist = distance( spawnpoint.origin, grenade.origin ) - 220;
- if ( grenadeDist < dangerDist )
- {
- if ( grenadeDist < 0 )
- grenadeDist = 0;
- dangerDist = grenadeDist;
- }
- }
- }
- if ( positionWouldTelefrag( spawnpoint.origin ) )
- dangerDist -= 200; // discourage telefragging but don't worry too much
- if ( isDefined( level.artilleryDangerCenters ) )
- {
- airstrikeDanger = maps\mp\killstreaks\_airstrike::getAirstrikeDanger( spawnpoint.origin );
- if ( airstrikeDanger > 0 )
- dangerDist = 0;
- }
- if ( level.teambased )
- {
- if ( spawnpoint.sights[enemyTeam] > 0 )
- dangerDist = 0;
- }
- else
- {
- if ( spawnpoint.sights > 0 )
- dangerDist = 0;
- }
- if ( !isdefined( safestSpawnpoint ) || dangerDist > safestDangerDist )
- {
- safestSpawnpoint = spawnpoint;
- safestDangerDist = dangerDist;
- }
- }
- assert( isdefined( safestSpawnpoint ) );
- if ( !isdefined( safestSpawnpoint ) )
- {
- safestSpawnpoint = spawnpoints[ randomint( spawnpoints.size ) ];
- safestSpawnpoint.safeSpawnDangerDist = 500;
- }
- else
- {
- safestSpawnpoint.safeSpawnDangerDist = safestDangerDist;
- }
- return safestSpawnpoint;
- }
- /////////////////////////////////////////////////////////////////////////
- getSpawnpoint_DM(spawnpoints)
- {
- // level endon("game_ended");
- /*if ( self.wantSafeSpawn )
- {
- return getSpawnpoint_SafeSpawn( spawnpoints );
- }*/
- // There are no valid spawnpoints in the map
- if(!isdefined(spawnpoints))
- return undefined;
- Spawnlogic_Begin();
- initWeights(spawnpoints);
- aliveplayers = getAllOtherPlayers();
- // new logic: we want most players near idealDist units away.
- // players closer than badDist units will be considered negatively
- idealDist = 1600;
- badDist = 1200;
- if (aliveplayers.size > 0 )
- {
- for (i = 0; i < spawnpoints.size; i++)
- {
- totalDistFromIdeal = 0;
- nearbyBadAmount = 0;
- for (j = 0; j < aliveplayers.size; j++)
- {
- dist = distance(spawnpoints[i].origin, aliveplayers[j].origin);
- if (dist < badDist)
- nearbyBadAmount += (badDist - dist) / badDist;
- distfromideal = abs(dist - idealDist);
- totalDistFromIdeal += distfromideal;
- }
- avgDistFromIdeal = totalDistFromIdeal / aliveplayers.size;
- wellDistancedAmount = (idealDist - avgDistFromIdeal) / idealDist;
- // if (wellDistancedAmount < 0) wellDistancedAmount = 0;
- // wellDistancedAmount is between -inf and 1, 1 being best (likely around 0 to 1)
- // nearbyBadAmount is between 0 and inf,
- // and it is very important that we get a bad weight if we have a high nearbyBadAmount.
- spawnpoints[i].weight = wellDistancedAmount - nearbyBadAmount * 2 + randomfloat(.2);
- }
- }
- carePackages = getEntArray( "care_package", "targetname" );
- for (i = 0; i < spawnpoints.size; i++)
- {
- if ( carePackages.size && !canSpawn( spawnpoints[i].origin ) )
- spawnpoints[i].weight -= 500000;
- }
- if ( isDefined( self.predictedSpawnPoint ) && isDefined( self.predictedSpawnPoint.weight ) )
- {
- // add a tiebreaker in case we end up choosing between spawnpoints of similar weight
- self.predictedSpawnPoint.weight += 100;
- /#
- self.predictedSpawnPoint.spawnData[self.predictedSpawnPoint.spawnData.size] = "Predicted: 100";
- #/
- }
- avoidSameSpawn();
- //avoidSpawnReuse(spawnpoints, false);
- //avoidDangerousSpawns(spawnpoints, false);
- avoidWeaponDamage(spawnpoints);
- avoidVisibleEnemies(spawnpoints, false);
- return getSpawnpoint_Final(spawnpoints);
- }
- // =============================================
- // called at the start of every spawn
- Spawnlogic_Begin()
- {
- //updateDeathInfo();
- /#
- level.debugSpawning = (getdvarint("scr_spawnpointdebug") > 0);
- #/
- }
- // called once at start of game
- init()
- {
- /#
- setDevDvarIfUninitialized("scr_spawnpointdebug", "0");
- setDevDvarIfUninitialized("scr_killbots", 0);
- setDevDvarIfUninitialized("scr_killbottimer", 0);
- thread loopbotspawns();
- #/
- // start keeping track of deaths
- level.spawnlogic_deaths = [];
- // DEBUG
- level.spawnlogic_spawnkills = [];
- level.players = [];
- level.grenades = [];
- level.pipebombs = [];
- level.turrets = [];
- level.helis = [];
- level.tanks = [];
- level.teamSpawnPoints["axis"] = [];
- level.teamSpawnPoints["allies"] = [];
- level thread trackGrenades();
- level.spawnMins = (0,0,0);
- level.spawnMaxs = (0,0,0);
- if ( isdefined( level.safespawns ) )
- {
- for( i = 0; i < level.safespawns.size; i++ )
- {
- level.safespawns[i] spawnPointInit();
- }
- }
- /*
- level.spawnSecondFloorTrig = getent( "spawn_second_floor", "targetname" );
- if ( isDefined( level.spawnSecondFloorTrig ) )
- {
- transitions = getentarray( level.spawnSecondFloorTrig.target, "targetname" );
- level.spawnFloorTransitions = [];
- foreach ( org in transitions )
- {
- level.spawnFloorTransitions[ level.spawnFloorTransitions.size ] = org.origin;
- org delete();
- }
- }
- */
- // DEBUG
- /#
- if (getdvarint("scr_spawnpointdebug") > 0)
- {
- thread profileDebug();
- thread drawRecordedSpawnData();
- }
- thread watchSpawnProfile();
- thread spawnGraphCheck();
- thread sightCheckCost();
- #/
- }
- /#
- sightCheckCost()
- {
- traceCount = 30;
- for ( ;; )
- {
- prof_begin( "sight_check_cost" );
- traceType = getDvar( "scr_debugcost" );
- if ( traceType == "bullet" && isDefined( level.players[0] ) )
- {
- for ( i = 0; i < traceCount; i++ )
- bulletTracePassed( level.players[0].origin + (0,0,50), (0,0,0), false, undefined );
- }
- else if ( traceType == "damagecone" && isDefined( level.players[0] ) )
- {
- for ( i = 0; i < traceCount; i++ )
- level.players[0] damageConeTrace( (0,0,0) );
- }
- else if ( traceType == "sightcone" && isDefined( level.players[0] ) )
- {
- for ( i = 0; i < traceCount; i++ )
- level.players[0] sightConeTrace( (0,0,0) );
- }
- else
- {
- wait ( 1.0 );
- }
- prof_end( "sight_check_cost" );
- wait ( 0.05 );
- }
- }
- watchSpawnProfile()
- {
- while(1)
- {
- while( getDvar( "scr_spawnprofile" ) == "" || getDvar( "scr_spawnprofile" ) == "0" )
- wait ( 0.05 );
- thread spawnProfile();
- while( getDvar( "scr_spawnprofile" ) != "" && getDvar( "scr_spawnprofile" ) != "0" )
- wait ( 0.05 );
- level notify("stop_spawn_profile");
- }
- }
- spawnProfile()
- {
- level endon("stop_spawn_profile");
- spawnObj = spawnStruct();
- while(1)
- {
- /*
- if ( level.players.size > 0 && level.spawnpoints.size > 0 )
- {
- playerNum = randomint(level.players.size);
- player = level.players[playerNum];
- if ( player.team != "allies" && player.team != "axis" )
- continue;
- if ( level.teamBased && (getDvar( "scr_spawnprofile" ) == "allies" || getDvar( "scr_spawnprofile" ) == "axis") && player.team != getDvar( "scr_spawnprofile" ) )
- continue;
- attempt = 1;
- while ( !isdefined( player ) && attempt < level.players.size )
- {
- playerNum = ( playerNum + 1 ) % level.players.size;
- attempt++;
- player = level.players[playerNum];
- }
- player getSpawnpoint_NearTeam(level.spawnpoints);
- }
- */
- dvarString = getDvar( "scr_spawnprofile" );
- if ( dvarString != "allies" && dvarString != "axis" )
- {
- if ( cointoss() )
- dvarString = "allies";
- else
- dvarString = "axis";
- }
- spawnObj.team = dvarString;
- spawnObj.pers["team"] = dvarString;
- spawnObj getSpawnpoint_NearTeam(level.spawnpoints);
- wait ( 0.05 );
- }
- }
- spawnGraphCheck()
- {
- while(1)
- {
- if ( getdvarint("scr_spawngraph") < 1 )
- {
- wait 3;
- continue;
- }
- thread spawnGraph();
- while ( getdvarint("scr_spawngraph") >= 1 )
- {
- wait .2;
- continue;
- }
- level notify( "end_spawn_graph" );
- level notify( "spawn_graph_stop_draw" );
- }
- }
- spawnGraph()
- {
- level endon( "end_spawn_graph" );
- w = 20;
- h = 20;
- weightscale = .1;
- fakespawnpoints = [];
- corners = getentarray("minimap_corner", "targetname");
- if ( corners.size != 2 )
- {
- println("^1 can't spawn graph: no minimap corners");
- return;
- }
- min = corners[0].origin;
- max = corners[0].origin;
- if ( corners[1].origin[0] > max[0] )
- max = (corners[1].origin[0], max[1], max[2]);
- else
- min = (corners[1].origin[0], min[1], min[2]);
- if ( corners[1].origin[1] > max[1] )
- max = (max[0], corners[1].origin[1], max[2]);
- else
- min = (min[0], corners[1].origin[1], min[2]);
- i = 0;
- for ( y = 0; y < h; y++ )
- {
- yamnt = y / (h - 1);
- for ( x = 0; x < w; x++ )
- {
- xamnt = x / (w - 1);
- fakespawnpoints[i] = spawnstruct();
- fakespawnpoints[i].origin = (min[0] * xamnt + max[0] * (1-xamnt), min[1] * yamnt + max[1] * (1-yamnt), min[2]);
- fakespawnpoints[i].angles = (0,0,0);
- fakespawnpoints[i].forward = anglesToForward( fakespawnpoints[i].angles );
- fakespawnpoints[i].sightTracePoint = fakespawnpoints[i].origin;
- fakespawnpoints[i].outside = true;
- fakespawnpoints[i].secondfloor = false;
- fakespawnpoints[i].fake = true;
- i++;
- }
- }
- didweights = false;
- while(1)
- {
- spawni = 0;
- numiters = 10;
- for ( i = 0; i < numiters; i++ )
- {
- if ( !level.players.size || !isdefined( level.players[0].team ) || level.players[0].team == "spectator" || !isdefined( level.players[0].class ) )
- break;
- endspawni = spawni + fakespawnpoints.size / numiters;
- if ( i == numiters - 1 )
- endspawni = fakespawnpoints.size;
- for ( ; spawni < endspawni; spawni++ )
- {
- spawnPointUpdate( fakespawnpoints[spawni] );
- }
- wait .05;
- }
- if ( !level.players.size || !isdefined( level.players[0].team ) || level.players[0].team == "spectator" || !isdefined( level.players[0].class ) )
- {
- wait 1;
- continue;
- }
- level.players[0] getSpawnpoint_NearTeam( fakespawnpoints );
- for ( i = 0; i < fakespawnpoints.size; i++ )
- setupSpawnGraphPoint( fakespawnpoints[i], weightscale );
- didweights = true;
- level.players[0] drawSpawnGraph( fakespawnpoints, w, h, weightscale );
- wait .05;
- }
- }
- drawSpawnGraph( fakespawnpoints, w, h, weightscale )
- {
- level notify( "spawn_graph_stop_draw" );
- i = 0;
- for ( y = 0; y < h; y++ )
- {
- yamnt = y / (h - 1);
- for ( x = 0; x < w; x++ )
- {
- xamnt = x / (w - 1);
- if ( y > 0 )
- {
- thread spawnGraphLine( fakespawnpoints[i], fakespawnpoints[i-w], weightscale );
- }
- if ( x > 0 )
- {
- thread spawnGraphLine( fakespawnpoints[i], fakespawnpoints[i-1], weightscale );
- }
- i++;
- }
- }
- }
- setupSpawnGraphPoint( s1, weightscale )
- {
- s1.visible = true;
- if ( s1.weight < -1000/weightscale )
- {
- s1.visible = false;
- }
- }
- spawnGraphLine( s1, s2, weightscale )
- {
- if ( !s1.visible || !s2.visible )
- return;
- p1 = s1.origin + (0,0,s1.weight*weightscale + 100);
- p2 = s2.origin + (0,0,s2.weight*weightscale + 100);
- level endon( "spawn_graph_stop_draw" );
- for ( ;; )
- {
- line( p1, p2, (1,1,1) );
- wait .05;
- waittillframeend;
- }
- }
- loopbotspawns()
- {
- while(1)
- {
- if ( getdvarint("scr_killbots") < 1 )
- {
- wait 3;
- continue;
- }
- if ( !isdefined( level.players ) )
- {
- wait .05;
- continue;
- }
- bots = [];
- for (i = 0; i < level.players.size; i++)
- {
- if ( !isdefined( level.players[i] ) )
- continue;
- if ( level.players[i].sessionstate == "playing" && issubstr(level.players[i].name, "bot") )
- {
- bots[bots.size] = level.players[i];
- }
- }
- if ( bots.size > 0 )
- {
- if ( getdvarint( "scr_killbots" ) == 1 )
- {
- killer = bots[randomint(bots.size)];
- victim = bots[randomint(bots.size)];
- victim thread [[level.callbackPlayerDamage]] (
- killer, // eInflictor The entity that causes the damage.(e.g. a turret)
- killer, // eAttacker The entity that is attacking.
- 1000, // iDamage Integer specifying the amount of damage done
- 0, // iDFlags Integer specifying flags that are to be applied to the damage
- "MOD_RIFLE_BULLET", // sMeansOfDeath Integer specifying the method of death
- "none", // sWeapon The weapon number of the weapon used to inflict the damage
- (0,0,0), // vPoint The point the damage is from?
- (0,0,0), // vDir The direction of the damage
- "none", // sHitLoc The location of the hit
- 0 // psOffsetTime The time offset for the damage
- );
- }
- else
- {
- numKills = getdvarint( "scr_killbots" );
- lastVictim = undefined;
- for ( index = 0; index < numKills; index++ )
- {
- killer = bots[randomint(bots.size)];
- victim = bots[randomint(bots.size)];
- while ( isDefined( lastVictim ) && victim == lastVictim )
- victim = bots[randomint(bots.size)];
- victim thread [[level.callbackPlayerDamage]] (
- killer, // eInflictor The entity that causes the damage.(e.g. a turret)
- killer, // eAttacker The entity that is attacking.
- 1000, // iDamage Integer specifying the amount of damage done
- 0, // iDFlags Integer specifying flags that are to be applied to the damage
- "MOD_RIFLE_BULLET", // sMeansOfDeath Integer specifying the method of death
- "none", // sWeapon The weapon number of the weapon used to inflict the damage
- (0,0,0), // vPoint The point the damage is from?
- (0,0,0), // vDir The direction of the damage
- "none", // sHitLoc The location of the hit
- 0 // psOffsetTime The time offset for the damage
- );
- lastVictim = victim;
- }
- }
- }
- if ( getdvarfloat( "scr_killbottimer" ) > .05 )
- wait getdvarfloat( "scr_killbottimer" );
- else
- wait .05;
- }
- }
- spawnWeightDebug(spawnpoints, winner)
- {
- level notify("stop_spawn_weight_debug");
- level endon("stop_spawn_weight_debug");
- while(1)
- {
- if ( getdvarint("scr_spawnpointdebug") == 0 )
- {
- wait(3);
- continue;
- }
- textoffset = (0,0,-12);
- for (i = 0; i < spawnpoints.size; i++)
- {
- amnt = 1 * (1 - spawnpoints[i].weight / (-100000));
- if (amnt < 0) amnt = 0;
- if (amnt > 1) amnt = 1;
- orig = spawnpoints[i].origin + (0,0,80);
- print3d(orig, int(spawnpoints[i].weight), (1,amnt,.5));
- orig += textoffset;
- if ( spawnpoints[i] == winner )
- {
- print3d(orig, "Spawned " + self.name + " here", (1,amnt,.5));
- orig += textoffset;
- }
- if (isdefined(spawnpoints[i].spawnData))
- {
- for (j = 0; j < spawnpoints[i].spawnData.size; j++)
- {
- print3d(orig, spawnpoints[i].spawnData[j], (.5,.5,.5));
- orig += textoffset;
- }
- }
- // "bar graph"
- height = 0;
- if ( spawnpoints[i].weight > -1000 )
- height = (spawnpoints[i].weight + 1000) / 10;
- amnt = spawnpoints[i].weight / 2000;
- if (amnt < 0) amnt = 0;
- if (amnt > 1) amnt = 1;
- color = (1 - amnt, 1, 0);
- pt1 = spawnpoints[i].origin + (0,0,95);
- pt2 = spawnpoints[i].origin + (30,0,95);
- pt3 = pt1 + (0,0,height);
- pt4 = pt2 + (0,0,height);
- line( pt1, pt2, color );
- line( pt1, pt3, color );
- line( pt2, pt4, color );
- line( pt3, pt4, color );
- if ( spawnpoints[i] == winner )
- {
- // checkmark
- checkpt1 = pt3 + (0,0,30);
- checkpt2 = pt3 + (10,0,10);
- checkpt3 = pt3 + (30,0,50);
- line( checkpt1, checkpt2, color );
- line( checkpt2, checkpt3, color );
- }
- }
- wait(.05);
- }
- }
- profileDebug()
- {
- while(1)
- {
- if (getdvar("scr_spawnpointprofile") != "1") {
- wait(3);
- continue;
- }
- for (i = 0; i < level.spawnpoints.size; i++)
- level.spawnpoints[i].weight = randomint(10000);
- if (level.players.size > 0)
- level.players[randomint(level.players.size)] getSpawnpoint_NearTeam(level.spawnpoints);
- wait(.05);
- }
- }
- debugNearbyPlayers(players, origin)
- {
- if ( getdvarint("scr_spawnpointdebug") == 0 )
- return;
- starttime = gettime();
- while(1)
- {
- for (i = 0; i < players.size; i++)
- line(players[i].origin, origin, (.5,1,.5));
- if (gettime() - starttime > 5000)
- return;
- wait .05;
- }
- }
- #/
- trackGrenades()
- {
- while ( 1 )
- {
- level.grenades = getentarray("grenade", "classname");
- wait .05;
- }
- }
- // used by spawning; needs to be fast.
- isPointVulnerable(playerorigin)
- {
- pos = self.origin + level.claymoremodelcenteroffset;
- playerpos = playerorigin + (0,0,32);
- distsqrd = distancesquared(pos, playerpos);
- forward = anglestoforward(self.angles);
- if (distsqrd < level.claymoreDetectionRadius*level.claymoreDetectionRadius)
- {
- playerdir = vectornormalize(playerpos - pos);
- angle = acos(vectordot(playerdir, forward));
- if (angle < level.claymoreDetectionConeAngle) {
- return true;
- }
- }
- return false;
- }
- avoidWeaponDamage(spawnpoints)
- {
- //prof_begin(" spawn_complexgrenade");
- weaponDamagePenalty = 100000;
- if (getdvar("scr_spawnpointweaponpenalty") != "" && getdvar("scr_spawnpointweaponpenalty") != "0")
- weaponDamagePenalty = getdvarfloat("scr_spawnpointweaponpenalty");
- mingrenadedistsquared = 250*250; // (actual grenade radius is 220, 250 includes a safety area of 30 units)
- for (i = 0; i < spawnpoints.size; i++)
- {
- for (j = 0; j < level.grenades.size; j++)
- {
- if ( !isdefined( level.grenades[j] ) )
- continue;
- // could also do a sight check to see if it's really dangerous.
- if (distancesquared(spawnpoints[i].origin, level.grenades[j].origin) < mingrenadedistsquared)
- {
- spawnpoints[i].weight -= weaponDamagePenalty;
- /#
- spawnpoints[i].spawnData[spawnpoints[i].spawnData.size] = "Was near grenade: -" + int(weaponDamagePenalty);
- #/
- }
- }
- if ( !isDefined( level.artilleryDangerCenters ) )
- continue;
- airstrikeDanger = maps\mp\killstreaks\_airstrike::getAirstrikeDanger( spawnpoints[i].origin ); // 0 = none, 1 = full, might be > 1 for more than 1 airstrike
- if ( airstrikeDanger > 0 )
- {
- worsen = airstrikeDanger * weaponDamagePenalty;
- spawnpoints[i].weight -= worsen;
- /#
- spawnpoints[i].spawnData[spawnpoints[i].spawnData.size] = "Was near artillery (" + int(airstrikeDanger*100) + "% danger): -" + int(worsen);
- #/
- }
- }
- //prof_end(" spawn_complexgrenade");
- }
- spawnPerFrameUpdate()
- {
- spawnpointindex = 0;
- // each frame, do sight checks against a spawnpoint
- while(1)
- {
- wait .05;
- prof_begin("spawn_update");
- //time = gettime();
- if ( !isDefined( level.spawnPoints ) )
- return;
- spawnpointindex = (spawnpointindex + 1) % level.spawnPoints.size;
- if ( getdvar( "scr_spawnpoint_forceindex" ) != "" )
- spawnpointindex = getdvarint( "scr_spawnpoint_forceindex" );
- spawnpoint = level.spawnPoints[spawnpointindex];
- spawnPointUpdate( spawnpoint );
- prof_end("spawn_update");
- }
- }
- adjustSightValue( sightValue )
- {
- assert( sightValue >= 0 );
- assert( sightValue <= 1 );
- if ( sightValue <= 0 )
- return 0;
- if ( sightValue >= 1 )
- return 1;
- return sightValue * 0.5 + 0.25;
- }
- spawnPointUpdate( spawnpoint )
- {
- prof_begin( " spawn_update_init" );
- if ( level.teambased )
- {
- spawnpoint.sights["axis"] = 0;
- spawnpoint.sights["allies"] = 0;
- }
- else
- {
- spawnpoint.sights = 0;
- }
- spawnpointdir = spawnpoint.forward;
- debug = false;
- /#
- debug = (getdvarint("scr_spawnpointdebug") > 0);
- spawnpoint notify( "debug_stop_LOS" );
- #/
- spawnpoint.distSum["all"] = 0;
- spawnpoint.distSum["allies"] = 0;
- spawnpoint.distSum["axis"] = 0;
- spawnpoint.weightedDistSum["all"] = 0;
- spawnpoint.weightedDistSum["allies"] = 0;
- spawnpoint.weightedDistSum["axis"] = 0;
- spawnpoint.minDist["all"] = 9999999;
- spawnpoint.minDist["allies"] = 9999999;
- spawnpoint.minDist["axis"] = 9999999;
- spawnpoint.numPlayersAtLastUpdate = 0;
- totalPlayers["all"] = 0;
- totalPlayers["allies"] = 0;
- totalPlayers["axis"] = 0;
- weightSum["all"] = 0;
- weightSum["allies"] = 0;
- weightSum["axis"] = 0;
- winner = undefined;
- curTime = getTime();
- team = "all";
- teambased = level.teambased;
- prof_end( " spawn_update_init" );
- prof_begin( " spawn_update_ploop" );
- foreach ( player in level.players )
- {
- //prof_begin( " spawn_update_player" );
- if ( player.sessionstate != "playing" )
- {
- //prof_end( " spawn_update_player" );
- continue;
- }
- /*
- playerSecondFloor = false;
- if ( isDefined( level.spawnSecondFloorTrig ) && player isTouching( level.spawnSecondFloorTrig ) )
- playerSecondFloor = true;
- */
- //prof_begin( " spawn_update_diff" );
- diff = player.origin - spawnpoint.origin;
- diff = (diff[0], diff[1], 0);
- weight = 1.0; // default weight for weightedDistSum
- dist = length( diff ); // needs to be actual distance for distSum value
- //prof_end( " spawn_update_diff" );
- //prof_begin( " spawn_update_team" );
- if ( teambased )
- team = player.team;
- //prof_end( " spawn_update_team" );
- //prof_begin( " spawn_update_nearby" );
- if ( dist < spawnpoint.minDist[team] )
- spawnpoint.minDist[team] = dist;
- //prof_end( " spawn_update_nearby" );
- //prof_begin( " spawn_update_weight" );
- // tactical insertion weighting; players should not spawn too close to recent TI spawns
- if ( player.wasTI && curTime - player.spawnTime < 15000 )
- weight *= 0.1;
- // sniper weight check
- // note: weaponClass() is slow!
- if ( player.isSniper )
- weight *= 0.5;
- //prof_end( " spawn_update_weight" );
- //prof_begin( " spawn_update_sums" );
- weightSum[ team ] += weight;
- spawnpoint.weightedDistSum[ team ] += dist * weight;
- spawnpoint.distSum[ team ] += dist;
- spawnpoint.numPlayersAtLastUpdate++;
- totalPlayers[team]++;
- //prof_end( " spawn_update_sums" );
- //prof_begin( " spawn_update_dot" );
- pdir = anglestoforward(player.angles);
- if (vectordot(spawnpointdir, diff) < 0 && vectordot(pdir, diff) > 0)
- {
- //prof_end( " spawn_update_dot" );
- //prof_end( " spawn_update_player" );
- continue; // player and spawnpoint are looking in opposite directions
- }
- //prof_end( " spawn_update_dot" );
- /#
- if ( isDefined( spawnpoint.fake ) )
- {
- //prof_end( " spawn_update_player" );
- continue;
- }
- #/
- // do sight check
- /*
- prof_begin( " spawn_update_told" );
- losExists = bullettracepassed(player.origin + (0,0,50), spawnpoint.sightTracePoint, false, undefined);
- prof_end( " spawn_update_told" );
- */
- prof_begin( " spawn_update_trace" );
- sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, player.origin + (0,0,50) );
- prof_end( " spawn_update_trace" );
- //prof_begin( " spawn_update_losexists" );
- spawnpoint.lastSightTraceTime = gettime();
- if ( sightValue > 0 )
- {
- sightValue = adjustSightValue( sightvalue );
- if ( teamBased )
- spawnpoint.sights[team] += sightValue;
- else
- spawnpoint.sights += sightValue;
- /#
- if ( debug )
- spawnpoint thread spawnpointDebugLOS( player.origin + (0,0,50) );
- #/
- }
- //else
- // line(player.origin + (0,0,50), spawnpoint.sightTracePoint, (1,.5,.5));
- //prof_end( " spawn_update_losexists" );
- //prof_end( " spawn_update_player" );
- }
- prof_end( " spawn_update_ploop" );
- prof_begin( " spawn_update_other" );
- nearbyEnemyRange = getFloatProperty( "scr_spawn_enemyavoiddist", 1000 );
- nearbyEnemyPenalty = 2000; // typical base weights tend to peak around 1500 or so. this is large enough to upset that while only locally dominating it.
- foreach ( team, value in weightSum )
- {
- if ( weightSum[team] )
- spawnpoint.weightedDistSum[team] = spawnpoint.weightedDistSum[team] / weightSum[team] * totalPlayers[team];
- nearbyPenalty = 0;
- if ( spawnpoint.mindist[team] < nearbyEnemyRange )
- nearbyPenalty = nearbyEnemyPenalty * (1 - spawnpoint.mindist[team] / nearbyEnemyRange);
- spawnpoint.nearbyPenalty[team] = nearbyPenalty;
- }
- foreach ( tank in level.tanks )
- {
- sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, tank.origin + (0,0,50) );
- spawnpoint.lastSightTraceTime = gettime();
- if ( sightValue <= 0 )
- continue;
- sightValue = adjustSightValue( sightvalue );
- if ( teamBased )
- spawnpoint.sights[tank.team] += sightValue;
- else
- spawnpoint.sights += sightValue;
- /#
- if ( debug )
- spawnpoint thread spawnpointDebugLOS( tank.origin + (0,0,50) );
- #/
- }
- foreach ( turret in level.turrets )
- {
- if ( !isDefined( turret ) )
- continue;
- sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, turret.origin + (0,0,50) );
- spawnpoint.lastSightTraceTime = gettime();
- if ( sightValue <= 0 )
- continue;
- sightValue = adjustSightValue( sightvalue );
- if ( teamBased )
- spawnpoint.sights[turret.team] += sightValue;
- else
- spawnpoint.sights += sightValue;
- /#
- if ( debug )
- spawnpoint thread spawnpointDebugLOS( turret.origin + (0,0,50) );
- #/
- }
- // Disabled to see if removal of the red boxes upon spawn is sufficient
- // (helicopter traces also intentionally disabled)
- /*
- if ( spawnpoint.outside )
- {
- foreach ( heli in level.helis )
- {
- sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, heli.origin + (0,0,30) );
- spawnpoint.lastSightTraceTime = gettime();
- if ( sightValue <= 0 )
- continue;
- sightValue = adjustSightValue( sightvalue );
- if ( teamBased )
- spawnpoint.sights[heli.team] += sightValue;
- else
- spawnpoint.sights += sightValue;
- /#
- if ( debug )
- spawnpoint thread spawnpointDebugLOS( heli.origin + (0,0,30) );
- #/
- }
- foreach ( missile in level.missilesForSightTraces )
- {
- sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, missile.origin );
- spawnpoint.lastSightTraceTime = gettime();
- if ( sightValue <= 0 )
- continue;
- sightValue = adjustSightValue( sightvalue );
- if ( teamBased )
- spawnpoint.sights[missile.team] += sightValue;
- else
- spawnpoint.sights += sightValue;
- /#
- if ( debug )
- spawnpoint thread spawnpointDebugLOS( missile.origin );
- #/
- }
- if ( isDefined( level.ac130player ) && level.ac130player.team != "spectator" )
- {
- if ( teamBased )
- spawnpoint.sights[level.ac130player.team]++;
- else
- spawnpoint.sights++;
- }
- }
- */
- prof_end( " spawn_update_other" );
- }
- /#
- spawnpointDebugLOS( point )
- {
- // g_spawndebug is better for this
- /*
- self endon( "debug_stop_LOS" );
- for ( ;; )
- {
- line( point, self.sightTracePoint, (1, .5, .5) );
- wait .05;
- }
- */
- }
- #/
- getLosPenalty()
- {
- if (getdvar("scr_spawnpointlospenalty") != "" && getdvar("scr_spawnpointlospenalty") != "0")
- return getdvarfloat("scr_spawnpointlospenalty");
- return 100000;
- }
- lastMinuteSightTraces( spawnpoint )
- {
- prof_begin(" spawn_final_lastminsc");
- closest = undefined;
- closestDistsq = 100000000.0;
- secondClosest = undefined;
- secondClosestDistsq = 100000000.0;
- foreach ( player in level.players )
- {
- if ( player.team == self.team && level.teambased )
- continue;
- if ( player.sessionstate != "playing" )
- continue;
- if ( player == self )
- continue;
- distsq = distanceSquared( spawnpoint.origin, player.origin );
- if ( distsq < closestDistsq )
- {
- secondClosest = closest;
- secondClosestDistsq = closestDistsq;
- closest = player;
- closestDistSq = distsq;
- }
- else if ( distsq < secondClosestDistSq )
- {
- secondClosest = player;
- secondClosestDistSq = distsq;
- }
- }
- if ( isdefined( closest ) )
- {
- sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, closest.origin + (0,0,50) );
- if ( sightValue > 0 )
- {
- sightValue = adjustSightValue( sightvalue );
- prof_end(" spawn_final_lastminsc");
- return sightValue;
- }
- }
- if ( isdefined( secondClosest ) )
- {
- sightValue = SpawnSightTrace( spawnpoint, spawnpoint.sightTracePoint, secondClosest.origin + (0,0,50) );
- if ( sightValue > 0 )
- {
- sightValue = adjustSightValue( sightvalue );
- prof_end(" spawn_final_lastminsc");
- return sightValue;
- }
- }
- prof_end(" spawn_final_lastminsc");
- return 0;
- }
- avoidVisibleEnemies(spawnpoints, teambased)
- {
- //prof_begin(" spawn_complexsc");
- lospenalty = getLosPenalty();
- otherteam = "axis";
- if ( self.team == "axis" )
- otherteam = "allies";
- if ( teambased )
- {
- foreach ( spawnpoint in spawnpoints )
- {
- penalty = lospenalty * spawnpoint.sights[otherteam];
- spawnpoint.weight -= penalty;
- /#
- if ( penalty > 0 )
- spawnpoint.spawnData[spawnpoint.spawnData.size] = "Sight traces: -" + int(penalty);
- #/
- }
- }
- else
- {
- foreach ( spawnpoint in spawnpoints )
- {
- penalty = lospenalty * spawnpoint.sights;
- spawnpoint.weight -= penalty;
- /#
- if ( penalty > 0 )
- spawnpoint.spawnData[spawnpoint.spawnData.size] = "Sight traces: -" + int(penalty);
- #/
- }
- otherteam = "all";
- }
- foreach ( spawnpoint in spawnpoints )
- {
- // penalty for nearby enemies
- spawnpoint.weight -= spawnpoint.nearbyPenalty[otherteam];
- /#
- if ( spawnpoint.nearbyPenalty[otherteam] != 0 )
- spawnpoint.spawnData[spawnpoint.spawnData.size] = "Nearest enemy at " + int(spawnpoint.minDist[otherteam]) + " units: -" + int(spawnpoint.nearbyPenalty[otherteam]);
- #/
- if ( positionWouldTelefrag( spawnpoint.origin ) )
- {
- telefragCount = 1;
- foreach ( alternate in spawnpoint.alternates )
- {
- if ( positionWouldTelefrag( alternate ) )
- telefragCount++;
- else
- break;
- }
- penalty = 100000;
- if ( telefragCount < spawnpoint.alternates.size + 1 )
- {
- penalty = 1500 * telefragCount;
- if ( isDefined( self.forceSpawnNearTeammates ) )
- penalty = 0;
- }
- spawnpoint.weight -= penalty;
- /#
- spawnpoint.spawnData[spawnpoint.spawnData.size] = "Would telefrag " + telefragCount + " times: -" + penalty;
- #/
- }
- }
- // DEBUG
- //prof_end(" spawn_complexsc");
- }
- avoidSpawnReuse(spawnpoints, teambased)
- {
- // DEBUG
- //prof_begin(" spawn_complexreuse");
- time = getTime();
- maxtime = 10*1000;
- maxdistSq = 1024 * 1024;
- foreach ( spawnpoint in spawnpoints )
- {
- lastspawnedplayer = spawnpoint.lastspawnedplayer;
- if ( !isalive( lastspawnedplayer ) )
- continue;
- if ( teambased && spawnpoint.lastspawnedplayer.team == self.team )
- continue;
- if ( spawnpoint.lastspawnedplayer == self )
- continue;
- timepassed = time - spawnpoint.lastspawntime;
- if ( timepassed < maxtime )
- {
- distSq = distanceSquared( spawnpoint.lastspawnedplayer.origin, spawnpoint.origin );
- if (distSq < maxdistSq)
- {
- worsen = 5000 * (1 - distSq/maxdistSq) * (1 - timepassed/maxtime);
- spawnpoint.weight -= worsen;
- /#
- spawnpoint.spawnData[spawnpoint.spawnData.size] = "Recently spawned enemy: -" + worsen;
- #/
- }
- else
- spawnpoint.lastspawnedplayer = undefined; // don't worry any more about this spawnpoint
- }
- else
- spawnpoint.lastspawnedplayer = undefined; // don't worry any more about this spawnpoint
- }
- //prof_end(" spawn_complexreuse");
- }
- avoidSameSpawn()
- {
- //prof_begin(" spawn_complexsamespwn");
- spawnpoint = self.lastspawnpoint;
- if ( !isdefined( spawnpoint ) || !isdefined( spawnpoint.weight ) )
- {
- //prof_end(" spawn_complexsamespwn");
- return;
- }
- spawnpoint.weight -= 1000;
- /#
- spawnpoint.spawnData[spawnpoint.spawnData.size] = "Was last spawnpoint: -1000";
- #/
- //prof_end(" spawn_complexsamespwn");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement