2023-04-13 17:30:38 +02:00

1443 lines
42 KiB
Plaintext

#using scripts\shared\flag_shared;
#using scripts\shared\array_shared;
#using scripts\shared\callbacks_shared;
#using scripts\shared\gameobjects_shared;
#using scripts\shared\hostmigration_shared;
#using scripts\shared\hud_util_shared;
#using scripts\shared\math_shared;
#using scripts\shared\scoreevents_shared;
#using scripts\shared\sound_shared;
#using scripts\shared\util_shared;
#using scripts\shared\abilities\_ability_util;
#using scripts\mp\gametypes\_globallogic;
#using scripts\mp\gametypes\_globallogic_audio;
#using scripts\mp\gametypes\_globallogic_score;
#using scripts\mp\gametypes\_globallogic_spawn;
#using scripts\mp\gametypes\_globallogic_ui;
#using scripts\mp\gametypes\_loadout;
#using scripts\mp\gametypes\_spawning;
#using scripts\mp\gametypes\_spawnlogic;
#using scripts\mp\gametypes\_spectating;
#using scripts\mp\gametypes\_wager;
#using scripts\mp\bots\_bot;
#using scripts\mp\_teamops;
#using scripts\mp\_util;
#using scripts\mp\teams\_teams;
/*
Infect - Infected
Attackers objective: Infect all Defenders
Defenders objective: Kill / Avoid Attackers and survive until time limit is reached
Respawning: No wait / Near teammates for Attackers, Defenders immediately respawned as Attackers when killed
*/
#precache( "string", "OBJECTIVES_INFECT" );
#precache( "string", "OBJECTIVES_INFECT_HINT" );
#precache( "string", "MP_DRAFT_STARTS_IN" );
#precache( "string", "MP_GOT_INFECTED" );
#precache( "string", "MPUI_INFECTED" );
#precache( "string", "MPUI_SURVIVORS" );
#precache( "string", "MP_SURVIVORS_ELIMINATED" );
#precache( "string", "MP_INFECTED_ELIMINATED" );
#precache( "string", "MP_INFECTED_TIME_EXTENDED" );
function main()
{
globallogic::init();
level.isInfectMode = true;
level.weapon_FIRST_INFECTED_PRIMARY_WEAPON = GetWeapon( "pistol_standard" );
level.weapon_INFECTED_PRIMARY_WEAPON = GetWeapon( "melee_boneglass" );
level.weapon_INFECTED_PRIMARY_GRENADE_WEAPON = GetWeapon( "hatchet" );
util::registerRoundSwitch( 0, 9 );
util::registerTimeLimit( 0, 1440 );
util::registerScoreLimit( 0, 50000 );
util::registerRoundLimit( 0, 10 );
util::registerRoundWinLimit( 0, 10 );
util::registerNumLives( 0, 100 );
globallogic::registerFriendlyFireDelay( level.gameType, 15, 0, 1440 );
level.scoreRoundWinBased = ( GetGametypeSetting( "cumulativeRoundScores" ) == false );
level.teamScorePerKill = GetGametypeSetting( "teamScorePerKill" );
level.teamScorePerDeath = GetGametypeSetting( "teamScorePerDeath" );
level.teamScorePerHeadshot = GetGametypeSetting( "teamScorePerHeadshot" );
level.teamBased = true;
level.overrideTeamScore = true;
level.onStartGameType =&onStartGameType;
level.onEndGame = &onEndGame;
level.onSpawnPlayer =&onSpawnPlayer;
level.onRoundEndGame =&onRoundEndGame;
level.onRoundSwitch =&onRoundSwitch;
level.onPlayerKilled =&onPlayerKilled;
level.playerGetWeaponScavengeAmmo = &playerGetWeaponScavengeAmmo;
level.getTimeLimit = &getTimeLimit;
level.gameModeWeaponDropped = &weaponDropped;
// level.gametypeRoundEndScoreHud =&gametypeRoundEndScoreHud;
// level.onCloneSelectWeapon = &onCloneSelectWeapon;
callback::on_connect( &onPlayerConnect );
callback::on_disconnect( &onPlayerDisconnect );
callback::on_joined_team( &onPlayerJoinedTeam );
callback::on_joined_spectate( &onPlayerJoinedSpectate );
gameobjects::register_allowed_gameobject( level.gameType );
// globallogic_audio::set_leader_gametype_dialog ( "startTeamDeathmatch", "hcStartTeamDeathmatch", "gameBoost", "gameBoost" );
// Sets the scoreboard columns and determines with data is sent across the network
if ( !SessionModeIsSystemlink() && !SessionModeIsOnlineGame() && IsSplitScreen() )
// local matches only show the first three columns
globallogic::setvisiblescoreboardcolumns( "score", "kills", "infects", "deaths", "assists" );
else
globallogic::setvisiblescoreboardcolumns( "score", "kills", "deaths", "infects", "assists" );
level.giveCustomLoadout =&giveCustomLoadout;
level.getAutoAssignTeamName = &getAutoAssignTeamName;
level.onTimeLimit =&onTimeLimit;
level.mayDropWeapon = &mayDropWeapon;
infect_perks = [];
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_longersprint";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_quieter";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_loudenemies";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_movefaster";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_jetnoradar";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_jetquiet";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_fallheight";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_fastladderclimb";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_fastmantle";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_fastreload";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_detectexplosive";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_bulletaccuracy";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_stalker";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_jetcharger";;
if ( !isdefined( infect_perks ) ) infect_perks = []; else if ( !IsArray( infect_perks ) ) infect_perks = array( infect_perks ); infect_perks[infect_perks.size]="specialty_overcharge";;
level.infect_perks = infect_perks;
infect_gadgets = [];
if ( !isdefined( infect_gadgets ) ) infect_gadgets = []; else if ( !IsArray( infect_gadgets ) ) infect_gadgets = array( infect_gadgets ); infect_gadgets[infect_gadgets.size]="gadget_camo";;
if ( !isdefined( infect_gadgets ) ) infect_gadgets = []; else if ( !IsArray( infect_gadgets ) ) infect_gadgets = array( infect_gadgets ); infect_gadgets[infect_gadgets.size]="gadget_clone";;
if ( !isdefined( infect_gadgets ) ) infect_gadgets = []; else if ( !IsArray( infect_gadgets ) ) infect_gadgets = array( infect_gadgets ); infect_gadgets[infect_gadgets.size]="gadget_armor";;
level.infect_gadgets = infect_gadgets;
}
function onStartGameType()
{
setClientNameMode("auto_change");
game["defenders"] = "allies";
game["attackers"] = "axis";
if ( !IsDefined( game["switchedsides"] ) )
game["switchedsides"] = false;
if ( game["switchedsides"] )
{
oldAttackers = game["attackers"];
oldDefenders = game["defenders"];
game["attackers"] = oldDefenders;
game["defenders"] = oldAttackers;
}
// setCustomTeamNames();
level.displayRoundEndText = false;
// now that the game objects have been deleted place the influencers
spawning::create_map_placed_influencers();
level.spawnMins = ( 0, 0, 0 );
level.spawnMaxs = ( 0, 0, 0 );
foreach ( team in level.teams )
{
util::setObjectiveText( team, &"OBJECTIVES_INFECT" );
util::setObjectiveHintText( team, &"OBJECTIVES_INFECT_HINT" );
util::setObjectiveScoreText( team, &"OBJECTIVES_INFECT" );
spawnlogic::add_spawn_points( team, "mp_tdm_spawn" );
spawnlogic::place_spawn_points( spawning::getTDMStartSpawnName(team) );
}
spawning::updateAllSpawnPoints();
level.spawn_start = [];
foreach ( team in level.teams )
{
level.spawn_start[ team ] = spawnlogic::get_spawnpoint_array( spawning::getTDMStartSpawnName(team) );
}
level.mapCenter = math::find_box_center( level.spawnMins, level.spawnMaxs );
setMapCenter( level.mapCenter );
spawnpoint = spawnlogic::get_random_intermission_point();
setDemoIntermissionPoint( spawnpoint.origin, spawnpoint.angles );
if ( !util::isOneRound() )
{
level.displayRoundEndText = true;
if( level.scoreRoundWinBased )
{
globallogic_score::resetTeamScores();
}
}
level.infect_choseFirstInfected = false;
level.infect_choosingFirstInfected = false;
level.infect_allowSuicide = false;
level.infect_awardedFinalSurvivor = false;
level.infect_players = [];
initHud();
/# level thread devgui_infect(); #/
// gametype is user-facing as FFA so we need to use FFA bot-population logic
maxFree = GetDvarInt( "bot_maxFree", 0 );
level thread bot::monitor_bot_population( maxFree );
level thread abortedCountdownCleanup();
level thread timeExtendedCleanup();
}
function setCustomTeamNames()
{
setTeamCustomName( game["attackers"], "MPUI_INFECTED" );
setTeamCustomName( game["defenders"], "MPUI_SURVIVORS" );
}
function setTeamCustomName( team, name )
{
customTeamDvar = "g_customTeamName_" + team;
if ( GetDvarString( customTeamDvar ) == "" )
{
SetDvar( customTeamDvar, name );
}
}
function onEndGame( winningTeam )
{
if ( !util::isOneRound() && !util::isLastRound() )
{
// give a win/loss for each round played
infectUpdateWinLossStats( winningTeam );
}
}
function infectUpdateWinLossStats( winningTeam )
{
players = level.players;
for ( i = 0; i < players.size; i++ )
{
if ( !isdefined( players[i].pers["team"] ) )
continue;
if ( level.hostForcedEnd && players[i] IsHost() )
continue;
if ( winningTeam == "tie" )
globallogic_score::updateTieStats( players[i] );
else if ( players[i].pers["team"] == winningTeam )
globallogic_score::updateWinStats( players[i] );
else
{
// need to add condition for arena late join loss prevention
if ( level.rankedMatch && !level.leagueMatch && ( players[i].pers["lateJoin"] === true ) )
{
globallogic_score::updateLossLateJoinStats( players[i] );
}
if ( !level.disableStatTracking )
{
players[i] SetDStat( "playerstatslist", "cur_win_streak", "StatValue", 0 );
}
}
}
}
function initHud()
{
level.infect_timerDisplay = hud::createServerTimer( "objective", 1.5 );
level.infect_timerDisplay hud::setPoint( "CENTER", undefined, 0, 50 );
level.infect_timerDisplay.label = &"MP_DRAFT_STARTS_IN";
level.infect_timerDisplay.alpha = 0;
level.infect_timerDisplay.archived = false;
level.infect_timerDisplay.hideWhenInMenu = true;
level.infect_timeExtendedDisplay = hud::createServerFontString( "objective", 1.5 );
level.infect_timeExtendedDisplay hud::setPoint( "CENTER", undefined, 0, 50 );
level.infect_timeExtendedDisplay.label = &"MP_INFECTED_TIME_EXTENDED";
level.infect_timeExtendedDisplay.alpha = 0;
level.infect_timeExtendedDisplay.archived = false;
level.infect_timeExtendedDisplay.hideWhenInMenu = true;
}
function onPlayerConnect()
{
self.infect_firstSpawn = true;
self.infect_joinedAtStart = level.inPrematchPeriod;
if ( self.sessionteam != "spectator" )
{
self.pers["needteam"] = 1;
}
playerXuid = self GetXUID();
if ( IsDefined( level.infect_players[playerXuid] ) )
{
self.infect_rejoined = true;
}
self.noDrowning = true;
}
function onPlayerJoinedTeam()
{
if ( self.team == game["attackers"] )
{
self.disableClassSelection = true;
}
else
{
self.disableClassSelection = undefined;
}
}
function getAutoAssignTeamName( player, comingFromMenu )
{
if ( !comingFromMenu && player.sessionteam == "spectator" )
{
teamName = "spectator";
}
else if ( ( isdefined( level.infect_forceAssignDefender ) && level.infect_forceAssignDefender ) )
{
level.infect_forceAssignDefender = undefined;
teamName = game["defenders"];
level thread delayedForceSpawnDefenders();
}
else if ( ( isdefined( player.infect_rejoined ) && player.infect_rejoined ) || ( isdefined( level.infect_choseFirstInfected ) && level.infect_choseFirstInfected ) )
{
teamName = game["attackers"];
}
else
{
teamName = game["defenders"];
}
return teamName;
}
function playerWaitForStreamer()
{
started_waiting = GetTime();
// try to let them finish loading the level
while ( ( !self isStreamerReady( -1, true ) ) && started_waiting + 90000 > GetTime() )
{
{wait(.05);};
}
}
function onSpawnPlayer(predictedSpawn)
{
if ( level.useStartSpawns && !level.inGracePeriod && !level.playerQueuedRespawn )
{
level.useStartSpawns = false;
}
updateTeamScores();
if ( self.team == game["attackers"] )
{
sanitizeInfectedLoadouts();
}
// let the first spawned player kick this off
if ( !level.infect_choosingFirstInfected )
{
level.infect_choosingFirstInfected = true;
level thread chooseFirstInfected();
}
spawning::onSpawnPlayer(predictedSpawn);
}
function onRoundSwitch()
{
game["switchedsides"] = !game["switchedsides"];
}
function onRoundEndGame( roundWinner )
{
if ( level.scoreRoundWinBased )
{
foreach( team in level.teams )
{
[[level._setTeamScore]]( team, game["roundswon"][team] );
}
}
return [[level.determineWinner]]();
}
function playerHasParticipated()
{
return ( self.pers["time_played_moving"] > 0 );
}
function teamCallout( team, calloutMessage, calloutPlayer )
{
players = getPlayersOnTeam( team );
foreach ( player in players )
{
player LUINotifyEvent( &"player_callout", 2, calloutMessage, calloutPlayer );
}
}
function onPlayerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
{
processKill = false;
wasSuicide = false;
if ( self.team == game["defenders"] && IsDefined( attacker ) )
{
if ( level.friendlyfire > 0 && isdefined( attacker.team ) && attacker.team == self.team )
{
processkill = false;
}
else if ( IsPlayer( attacker ) && attacker != self )
{
processKill = true;
}
else if ( level.infect_allowSuicide && ( attacker == self || !isPlayer( attacker ) ) )
{
processKill = true;
wasSuicide = true;
}
}
if ( !processKill )
{
return;
}
if ( !wasSuicide )
{
// regular attacker reward
scoreevents::processScoreEvent( "infected_survivor", attacker, self, weapon );
if ( isdefined( attacker.pers["infects"] ) )
{
attacker.pers["infects"] = attacker.pers["infects"] + 1;
attacker.infects = attacker.pers["infects"];
}
attacker AddPlayerStatWithGameType( "INFECTS", 1 );
}
level thread handlePlayerDeath( self, wasSuicide );
}
function handlePlayerDeath( victim, wasSuicide )
{
level endon( "game_ended" );
waittillframeend; // give laststand a chance to kick in
if ( isdefined( victim.laststand ) )
{
result = victim playerWaitForLastStand();
if ( result === "player_input_revive" )
{
return;
}
}
{wait(.05);}; // allows obituary to have expected team colors (i.e. Infected as enemy, Survivor as friendly)
if ( IsDefined( victim ) )
{
level thread displayTimeExtended();
switchPlayerToInfectedTeam( victim );
sanitizeInfectedLoadouts();
}
// generic messages/sounds, and reward survivors
totalDefenders = [[level._getTeamScore]]( game["defenders"] );
if ( totalDefenders > 1 && IsDefined( victim ) )
{
sound::play_on_players( "mpl_flagget_sting_enemy", game["defenders"] );
sound::play_on_players( "mpl_flagget_sting_friend", game["attackers"] );
teamCallout( game["defenders"], &"MP_GOT_INFECTED", victim.entnum );
if ( !wasSuicide )
{
teamCallout( game["attackers"], &"SCORE_INFECTED_SURVIVOR", victim.entnum );
survivors = getPlayersOnTeam( game["defenders"] );
foreach ( survivor in survivors )
{
if ( survivor != victim && survivor playerHasParticipated() )
{
survivor scoreevents::processScoreEvent( "survivor_still_alive", survivor );
}
}
}
}
// inform/reward last
else if ( totalDefenders == 1 )
{
onFinalSurvivor();
}
// infected win
else if ( totalDefenders == 0 )
{
onSurvivorsEliminated();
}
}
function playerWaitForLastStand()
{
level endon( "game_ended" );
self endon( "disconnect" );
return self util::waittill_any_return( "player_input_revive", "death" );
}
function onFinalSurvivor()
{
if ( ( isdefined( level.infect_announcedFinalSurvivor ) && level.infect_announcedFinalSurvivor ) )
{
return;
}
sound::play_on_players( "mpl_ballreturn_sting" );
finalSurvivor = getPlayersOnTeam( game["defenders"] )[0];
if ( !level.infect_awardedFinalSurvivor )
{
finalSurvivor playerFullyChargeHeroWeapon();
if ( finalSurvivor.infect_joinedAtStart && finalSurvivor playerHasParticipated() )
{
finalSurvivor scoreevents::processScoreEvent( "final_survivor", finalSurvivor );
}
level.infect_awardedFinalSurvivor = true;
}
LUINotifyEvent( &"player_callout", 2, &"SCORE_FINAL_SURVIVOR", finalSurvivor.entnum );
doFinalSurvivorUAV = GetDvarInt( "scr_infect_finaluav" );
if ( doFinalSurvivorUAV )
{
level thread finalSurvivorUAV( finalSurvivor );
}
level.infect_announcedFinalSurvivor = true;
}
function playerFullyChargeHeroWeapon()
{
if ( !IsDefined( self.heroWeapon ) )
{
return;
}
heroWeaponSlot = self GadgetGetSlot( self.heroWeapon );
if ( self GadgetIsReady( heroWeaponSlot ) )
{
return;
}
self GadgetPowerSet( heroWeaponSlot, 100.0 );
}
function finalSurvivorUAV( finalSurvivor )
{
level endon( "game_ended" );
finalSurvivor endon( "disconnect" );
finalSurvivor endon( "death" );
level endon( "infect_lateJoiner" );
level thread endUAVonLateJoiner( finalSurvivor );
SetTeamSpyplane( game["attackers"], 1 );
util::set_team_radar( game["attackers"], 1 );
removeUAV = false;
while ( true )
{
prevPos = finalSurvivor.origin;
wait( 4.0 );
if ( removeUAV )
{
SetTeamSpyplane( game["attackers"], 0 );
util::set_team_radar( game["attackers"], 0 );
removeUAV = false;
}
wait( 6.0 );
if ( DistanceSquared( prevPos, finalSurvivor.origin ) < ( (200) * (200) ) )
{
SetTeamSpyplane( game["attackers"], 1 );
util::set_team_radar( game["attackers"], 1 );
removeUAV = true;
foreach ( player in level.players )
{
sound::play_on_players( "fly_hunter_raise_plr" );
}
}
}
}
function endUAVonLateJoiner( finalSurvivor )
{
level endon( "game_ended" );
finalSurvivor endon( "disconnect" );
finalSurvivor endon( "death" );
while( true )
{
totalDefenders = [[level._getTeamScore]]( game["defenders"] );
if ( totalDefenders > 1 )
{
level notify( "infect_lateJoiner" );
{wait(.05);};
SetTeamSpyplane( game["attackers"], 1 );
util::set_team_radar( game["attackers"], 1 );
break;
}
{wait(.05);};
}
}
function onTimeLimit()
{
winner = game["defenders"];
level thread endGame( winner, game["strings"]["time_limit_reached"] );
}
function onSurvivorsEliminated()
{
updateTeamScores();
winner = game["attackers"];
loser = util::getOtherTeam( winner );
level thread endGame( winner, game["strings"][loser + "_eliminated"] );
}
function endGame( winner, endReasonText )
{
if ( ( isdefined( level.infect_gameEnded ) && level.infect_gameEnded ) )
{
return;
}
level.infect_gameEnded = true;
util::wait_network_frame(); // give final player a chance to switch teams in native
globallogic::endGame( winner, endReasonText );
}
function onPlayerJoinedSpectate()
{
checkTeamStates();
}
function onPlayerDisconnect()
{
checkTeamStates();
}
function checkTeamStates()
{
if ( ( isdefined( level.gameEnded ) && level.gameEnded ) )
{
return;
}
updateTeamScores();
totalAttackers = [[level._getTeamScore]]( game["attackers"] );
totalDefenders = [[level._getTeamScore]]( game["defenders"] );
// team actions or win condition necessary?
if ( isDefined( self.infect_isBeingChosen ) || level.infect_choseFirstInfected )
{
if ( totalAttackers > 0 && totalDefenders > 0 )
{
if ( totalDefenders == 1 )
{
// final survivor was abandoned: inform, reward, call uav
onFinalSurvivor();
}
}
else if ( totalDefenders == 0 )
{
// no more survivors, infected win
onSurvivorsEliminated();
}
else if ( totalAttackers == 0 )
{
if ( totalDefenders == 1 )
{
// last survivor wins
winner = game["defenders"];
loser = util::getOtherTeam( winner );
level thread endGame( winner, game["strings"][loser + "_eliminated"] );
}
else if ( totalDefenders > 1 )
{
// pick a new infected and keep the game going
level.infect_choseFirstInfected = false;
level thread chooseFirstInfected();
}
}
}
else
{
activeDefenders = getActivePlayersOnTeam( game["defenders"] );
if ( activeDefenders.size < 1 )
{
level notify( "infect_stopCountdown" );
}
}
}
function giveCustomLoadout( takeAllWeapons, alreadySpawned )
{
if ( self.team == game["attackers"] )
{
self giveInfectedLoadout();
self.movementSpeedModifier = 1.2;
}
else if ( self.team == game["defenders"] )
{
self giveWeaponClassLoadout();
self.movementSpeedModifier = undefined;
}
return self.spawnWeapon;
}
// direct copy of non-giveCustomLoadout block from loadout::giveLoadout to avoid invasive changes to _loadout.gsc
function giveWeaponClassLoadout()
{
loadout::giveLoadout_init( true );
loadout::setClassNum( self.curClass );
self SetActionSlot( 3, "altMode" );
self SetActionSlot( 4, "" );
allocationSpent = self GetLoadoutAllocation( self.class_num );
overAllocation = ( allocationSpent > level.maxAllocation );
if ( !overAllocation )
{
//Perks must come first in case other give-functions check for perks
givePerks();
loadout::giveWeapons();
loadout::givePrimaryOffhand();
}
else
{
loadout::giveBaseWeapon();
}
loadout::giveSecondaryOffhand();
if ( GetDvarint( "tu11_enableClassicMode") == 0 )
{
loadout::giveSpecialOffhand();
loadout::giveHeroWeapon();
}
loadout::giveKillStreaks();
}
function givePerks()
{
self.specialty = self GetLoadoutPerks( self.class_num );
if ( level.leagueMatch )
{
for ( i = 0; i < self.specialty.size; i++ )
{
if ( loadout::isLeagueItemRestricted( self.specialty[i] ) )
{
ArrayRemoveIndex( self.specialty, i );
i--;
}
}
}
// re-registering perks to code since perks are cleared after respawn in case if players switch classes
self loadout::register_perks();
// now that perks are re-registered...
// update player momentum taking into account anteup perk; any score less than the initial value is boosted to that value
anteup_bonus = GetDvarInt( "perk_killstreakAnteUpResetValue" );
momentum_at_spawn_or_game_end = (isdefined(self.pers["momentum_at_spawn_or_game_end"])?self.pers["momentum_at_spawn_or_game_end"]:0);
hasNotDoneCombat = !( self.hasDoneCombat === true ); // fixes dev gui bot spawning in grace period
if ( ( level.inPreMatchPeriod || ( level.inGracePeriod && hasNotDoneCombat ) ) && momentum_at_spawn_or_game_end < anteup_bonus )
{
new_momentum = ( self HasPerk( "specialty_anteup" ) ? anteup_bonus : momentum_at_spawn_or_game_end );
globallogic_score::_setPlayerMomentum( self, new_momentum, false );
}
}
function giveInfectedLoadout()
{
self loadout::giveLoadout_init( true );
loadout::setClassNum( self.curClass );
self ClearPerks();
foreach ( perkName in level.infect_perks )
{
if ( !self HasPerk( perkName ) )
{
self SetPerk( perkName );
}
}
totalAttackers = [[level._getTeamScore]]( game["attackers"] );
if ( totalAttackers == 1 )
{
defaultWeapon = level.weapon_FIRST_INFECTED_PRIMARY_WEAPON;
}
else
{
defaultWeapon = level.weapon_INFECTED_PRIMARY_WEAPON;
}
self playerInfectedGivePrimaryWeapon( defaultWeapon );
self SwitchToWeapon( defaultWeapon );
self SetSpawnWeapon( defaultWeapon );
self.spawnWeapon = defaultWeapon;
primaryOffhand = level.weapon_INFECTED_PRIMARY_GRENADE_WEAPON;
primaryOffhandCount = 1;
self GiveWeapon( primaryOffhand );
self SetWeaponAmmoStock( primaryOffhand, primaryOffhandCount );
self SwitchToOffhand( primaryOffhand );
self.grenadeTypePrimary = primaryOffhand;
self.grenadeTypePrimaryCount = primaryOffhandCount;
secondaryOffhand = GetWeapon( "null_offhand_secondary" );
secondaryOffhandCount = 0;
self GiveWeapon( secondaryOffhand );
self SetWeaponAmmoClip( secondaryOffhand, secondaryOffhandCount );
self SwitchToOffhand( secondaryOffhand );
self.grenadeTypeSecondary = secondaryOffhand;
self.grenadeTypeSecondaryCount = secondaryOffhandCount;
self GiveWeapon( level.weaponBaseMelee );
giveRandomGadget();
self.heroWeapon = undefined;
}
function giveRandomGadget()
{
specialOffhand = self.infect_randomGadget;
resetCharge = false;
if ( !isdefined( specialOffhand ) )
{
randomGadget = array::random( level.infect_gadgets );
specialOffhand = GetWeapon( randomGadget );
resetCharge = true;
}
specialOffhandCount = specialOffhand.startammo;
self GiveWeapon( specialOffhand );
self SetWeaponAmmoClip( specialOffhand, specialOffhandCount );
self SwitchToOffhand( specialOffhand );
self.grenadeTypeSpecial = specialOffhand;
self.grenadeTypeSpecialCount = specialOffhandCount;
if ( ( isdefined( resetCharge ) && resetCharge ) )
{
slot = self GadgetGetSlot( specialOffhand );
self GadgetPowerReset( slot );
}
self.infect_randomGadget = specialOffhand;
}
function chooseFirstInfected()
{
level endon( "game_ended" );
level endon( "infect_stopCountdown" );
// no suicides
level.infect_allowSuicide = false;
level.lastInfectionTime = undefined;
if ( level.inPrematchPeriod )
{
level waittill( "prematch_over" );
}
level.infect_timerDisplay.label = &"MP_DRAFT_STARTS_IN";
level.infect_timerDisplay setTimer( 8 );
level.infect_timerDisplay.alpha = 1;
hostmigration::waitLongDurationWithHostMigrationPause( 8.0 );
level.infect_timerDisplay.alpha = 0;
activeDefenders = getActivePlayersOnTeam( game["defenders"] );
if ( activeDefenders.size > 0 )
{
activeDefenders[GetArrayKeys(activeDefenders)[RandomInt(GetArrayKeys(activeDefenders).size)]] setFirstInfected();
}
else
{
level.infect_choosingFirstInfected = false;
}
}
function abortedCountdownCleanup()
{
while ( true )
{
event = level util::waittill_any_return( "game_ended", "infect_stopCountdown" );
if ( isdefined( level.infect_timerDisplay ) )
{
level.infect_timerDisplay.alpha = 0;
}
if ( event == "game_ended" )
{
return;
}
level.infect_choosingFirstInfected = false;
}
}
function displayTimeExtended()
{
level notify( "timeExtended" );
level endon( "game_ended" );
level endon( "infect_stopTimeExtended" );
level endon( "timeExtended" );
timeout = 0;
while( isDefined( level.infect_timerDisplay ) && level.infect_timerDisplay.alpha > 0 )
{
hostmigration::waitLongDurationWithHostMigrationPause( 0.5 );
timeout++;
if( timeout == 20 )
return;
}
level.infect_timeExtendedDisplay.alpha = 1;
hostmigration::waitLongDurationWithHostMigrationPause( 1.0 );
level.infect_timeExtendedDisplay FadeOverTime( 2 );
level.infect_timeExtendedDisplay.alpha = 0;
}
function timeExtendedCleanup()
{
while ( true )
{
event = level util::waittill_any_return( "game_ended", "infect_stopTimeExtended" );
if ( isdefined( level.infect_timeExtendedDisplay ) )
{
level.infect_timeExtendedDisplay.alpha = 0;
}
if ( event == "game_ended" )
{
return;
}
}
}
function getActivePlayersOnTeam( team )
{
activePlayers = [];
teamPlayers = getPlayersOnTeam( team );
foreach ( player in teamPlayers )
{
if ( player.sessionstate == "spectator" )
{
continue;
}
if ( !isdefined( activePlayers ) ) activePlayers = []; else if ( !IsArray( activePlayers ) ) activePlayers = array( activePlayers ); activePlayers[activePlayers.size]=player;;
}
return activePlayers;
}
function setFirstInfected()
{
self endon( "disconnect" );
self.infect_isBeingChosen = true;
// wait alive
while( !IsAlive( self ) || self util::isUsingRemote() )
{wait(.05);};
// remove placement item if carrying
if ( ( isdefined( self.isCarrying ) && self.isCarrying ) )
{
self notify( "force_cancel_placement" );
{wait(.05);};
}
// not while mantling
while ( self IsMantling() )
{wait(.05);};
// not while in air
while ( !self IsOnGround() && !self IsOnLadder() )
{wait(.05);};
switchPlayerToInfectedTeam( self );
self.switching_teams = undefined; // otherwise first death will be ignored by stats system
if ( self IsUsingOffHand() )
{
self ForceOffHandEnd();
}
self DisableOffhandSpecial(); // circumvents a weapon-flag issue if drafted while cooking an offhand weapon
self thread playerEnableOffhandAfterWeaponSwitch();
loadout::giveLoadout( self.team, self.curClass );
totalDefenders = [[level._getTeamScore]]( game["defenders"] );
if ( totalDefenders < 1 )
{
level.infect_forceAssignDefender = true;
}
else
{
forceSpawnTeam( game["defenders"] );
}
// tell the world!
LUINotifyEvent( &"player_callout", 2, &"SCORE_FIRST_INFECTED", self.entnum );
scoreevents::processScoreEvent( "first_infected", self );
sound::play_on_players( "mpl_flagget_sting_enemy" );
level.infect_allowSuicide = true;
level.infect_choseFirstInfected = true;
self.infect_isBeingChosen = undefined;
}
function forceSpawnTeam( team )
{
players = getPlayersOnTeam( team );
foreach ( player in players )
{
player thread playerForceSpawn();
}
}
function playerForceSpawn()
{
level endon( "game_ended" );
self endon( "death" );
self endon( "disconnect" );
self endon( "spawned" );
if ( self.hasSpawned )
{
return;
}
if ( self.pers["team"] == "spectator" )
{
return;
}
self playerWaitForStreamer();
self.pers["class"] = level.defaultClass;
self.curClass = level.defaultClass;
self globallogic_ui::closeMenus();
self CloseMenu( "ChooseClass_InGame" );
self thread [[level.spawnClient]]();
}
function switchPlayerToInfectedTeam( player )
{
storeInfectedPlayer( player );
destroyPlayerEquipment( player );
player changeTeam( game["attackers"] );
updateTeamScores();
resetTimeLimit();
}
function playerEnableOffhandAfterWeaponSwitch()
{
level endon( "game_ended" );
self endon( "disconnect" );
self endon( "death" );
self waittill( "weapon_change" );
self EnableOffhandSpecial();
}
function storeInfectedPlayer( player )
{
playerXuid = player GetXUID();
level.infect_players[playerXuid] = true;
}
function changeTeam( team )
{
if ( self.sessionstate != "dead" )
{
// Set a flag on the player to they aren't robbed points for dying - the callback will remove the flag
self.switching_teams = true;
self.switchedTeamsResetGadgets = true;
self.joining_team = team;
self.leaving_team = self.pers["team"];
}
self.pers["team"] = team;
self.team = team;
self.pers["weapon"] = undefined;
self.pers["spawnweapon"] = undefined;
self.pers["savedmodel"] = undefined;
self.pers["teamTime"] = undefined;
self.sessionteam = self.pers["team"];
self globallogic_ui::updateObjectiveText();
// update spectator permissions immediately on change of team
self spectating::set_permissions();
self notify("end_respawn");
}
function getPlayersOnTeam( team )
{
playersOnTeam = [];
foreach ( player in level.players )
{
if ( !isdefined( player ) )
{
continue;
}
playerTeam = player.pers[ "team" ];
if ( IsDefined( playerTeam ) && IsDefined( level.teams[ playerTeam ] ) && playerTeam == team )
{
if ( !isdefined( playersOnTeam ) ) playersOnTeam = []; else if ( !IsArray( playersOnTeam ) ) playersOnTeam = array( playersOnTeam ); playersOnTeam[playersOnTeam.size]=player;;
}
}
return playersOnTeam;
}
function countPlayersOnTeam( team )
{
playersOnTeam = getPlayersOnTeam( team );
return playersOnTeam.size;
}
function updateTeamScores()
{
updateTeamScore( game["attackers"] );
updateTeamScore( game["defenders"] );
}
function updateTeamScore( team )
{
score = countPlayersOnTeam( team );
game["teamScores"][team] = score;
globallogic_score::updateTeamScores( team );
}
function mayDropWeapon( weapon )
{
if ( self.team === game["attackers"] )
{
return false;
}
return true;
}
function playerInfectedGivePrimaryWeapon( weapon )
{
self GiveWeapon( weapon );
self GiveStartAmmo( weapon );
self SetBlockWeaponPickup( weapon, true );
self.infect_primaryWeapon = weapon;
}
function sanitizeInfectedLoadouts()
{
attackers = getPlayersOnTeam( game["attackers"] );
if ( attackers.size < 2 )
{
return;
}
foreach ( player in attackers )
{
if ( !IsAlive( player ) )
{
continue;
}
if ( player.infect_primaryWeapon !== level.weapon_INFECTED_PRIMARY_WEAPON )
{
if ( isdefined( player.infect_primaryWeapon ) )
{
player TakeWeapon( player.infect_primaryWeapon );
}
newWeapon = level.weapon_INFECTED_PRIMARY_WEAPON;
player playerInfectedGivePrimaryWeapon( newWeapon );
player SwitchToWeapon( newWeapon );
}
}
}
function playerGetWeaponScavengeAmmo( weapon, defaultAmmo )
{
if ( weapon == self.grenadeTypePrimary || weapon == self.grenadeTypeSecondary )
{
return 0;
}
return defaultAmmo;
}
function resetTimeLimit()
{
level.lastInfectionTime = GetTime();
}
function getTimeLimit()
{
defaultTimeLimit = GetGametypeSetting( "timeLimit" );
if ( defaultTimeLimit == 0 )
{
return 0;
}
if ( !isdefined( level.lastInfectionTime ) )
{
return 0;
}
minutesElapsed = ( ( level.lastInfectionTime - level.startTime + 1000 ) / 60000 );
timeLimit = minutesElapsed + defaultTimeLimit;
return timeLimit;
}
function destroyPlayerEquipment( player )
{
for ( i = 0; i < level.missileEntities.size; i++ )
{
item = level.missileEntities[i];
if ( !isdefined( item ) )
{
continue;
}
if ( !isdefined( item.weapon ) )
{
continue;
}
if ( item.owner !== player && item.originalowner !== player )
{
continue;
}
item notify( "detonating" );
if ( isdefined( item ) )
item Delete();
}
}
function gametypeRoundEndScoreHud( winner, endType, endReasonText, outcomeText, team, winnerEnum, notifyRoundEndToUI, matchbonus )
{
if ( endType == "roundend" )
{
if ( winner == "tie" )
{
outcomeText = game["strings"]["draw"];
}
else if ( isdefined( self.pers["team"] ) && winner == team )
{
outcomeText = game["strings"]["victory"];
overrideSpectator = true;
}
else
{
outcomeText = game["strings"]["defeat"];
if ( ( level.rankedMatch || level.leagueMatch ) && ( self.pers[ "lateJoin" ] === true ) )
{
endReasonText = game["strings"]["join_in_progress_loss"];
}
overrideSpectator = true;
}
notifyRoundEndToUI = false;
// Codcaster Specific Outcome Override
if ( team == "spectator" && overrideSpectator )
{
// Special case handling of end reason text
foreach ( team in level.teams )
{
if ( endreasontext == game["strings"][team + "_eliminated"] )
{
endReasonText = game["strings"]["cod_caster_team_eliminated"];
break;
}
}
outcomeText = game["strings"]["cod_caster_team_wins"];
}
self LUINotifyEvent( &"show_outcome", 5, outcomeText, endReasonText, int( matchBonus ), winnerEnum, notifyRoundEndToUI );
return true;
}
return false;
}
function onCloneSelectWeapon( player )
{
if ( player.team === game["attackers"] )
{
playerWeapon = player GetCurrentWeapon();
if ( isdefined( playerWeapon.worldModel ) )
{
return playerWeapon;
}
}
return undefined; // use default logic
}
function delayedForceSpawnDefenders()
{
level endon( "game_ended" );
level notify( "infect_forcespawn_defenders" );
level endon( "infect_forcespawn_defenders" );
wait( 30 );
forceSpawnTeam( game["defenders"] );
}
function weaponDropped( weaponItem )
{
weaponItem HideFromTeam( game["attackers"] );
}
/#
function runDvarHandler( dvarName, commandHandlerFunc )
{
SetDvar( dvarName, "" );
while ( true )
{
{wait(.05);};
dvarValue = GetDvarString( dvarName );
if ( dvarValue == "" )
{
continue;
}
SetDvar( dvarName, "" );
tokens = StrTok( dvarValue, " " );
if ( !IsDefined( tokens ) || tokens.size < 1 )
{
continue;
}
command = tokens[0];
ArrayRemoveIndex( tokens, 1 );
[[ commandHandlerFunc ]]( command, tokens );
}
}
function handleDevCommand( command, args )
{
switch ( command )
{
case "killall_bots":
foreach ( player in level.players )
{
if ( player util::is_bot() )
{
player Kill();
}
}
break;
default:
break;
}
}
function devgui_infect()
{
level thread runDvarHandler( "scr_infect_devcmd", &handleDevCommand );
level flag::wait_till("all_players_spawned" );
devguiRoot = "devgui_cmd \"Infected/";
AddDebugCommand( devguiRoot + "Kill All Bots" + "\" \"set " + "scr_infect_devcmd" + " killall_bots\" \n");
}
#/