Gah - a solution with more questions. – EntropicLqd

Legacy:ONSOnslaughtGame

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search
UT2004 :: Actor >> Info >> GameInfo >> UnrealMPGameInfo >> DeathMatch >> TeamGame >> xTeamGame >> ONSOnslaughtGame (Package: Onslaught)

Onslaught Gameplay[edit]

"Your team must take control over PowerNodes in a 'connect the dots' fashion to establish a direct line to the enemy PowerCore. Once you establish a link to the next PowerNode, you can destroy it if controlled by the enemy. Control the PowerNode for your team by touching it to start the build process (Use the linkgun alt-fire to speed things up). Once your team has a link to the enemy PowerCore, attack and destroy it."

The Onslaught gametype involves two teams, each has a power core, and the map has a set of power nodes that are linked in a particular configuration ("Link setup"). Power nodes are 'locked' unless linked to a fully charged powernode of your team's colour, or to your team's powercore. Unlocked powernodes can be taken for your own team. If the opposing team has already taken a powernode it must first be destroyed.

This was the first gametype to fully utilize vehicles in multi-player mode. Onslaught maps are usually much larger than those for other gametypes. Vehicles spawn at the core and at locked powernodes. An element of gameplay is the race to build nodes. Vehicles perform a vital role in transporting troops to the front line.

The link gun is also key to the Onslaught gametype. It vastly accelerates the building of nodes, and heals vehicles.

See Liandri:Onslaught for gameplay-related details about the Onslaught gametype.

ONSOnslaughtGame Class[edit]

Power Cores[edit]

var array<ONSPowerCore>         PowerCores;
var int                         FinalCore[2];

Link Setup[edit]

struct PowerLinkSetup
{
	var name BaseNode;
	var array<name> LinkedNodes;
};
 
var array<ONSPowerLinkOfficialSetup> OfficialPowerLinkSetups;
var array<ONSPowerLinkCustomSetup> CustomPowerLinkSetups;
var array<PowerLink> PowerLinks;

Configuration Options[edit]

var config int OvertimeCoreDrainPerSec;
var config bool bRandSetupAfterReset;	//choose a random link setup to play after a reset
var config bool bSwapSidesAfterReset;
var bool        bSidesAreSwitched;

The last two deal with exchanging sides. Most servers have bSwapSidesAfterReset set, so that teams get to play both directions on a map, and any bias due to terrain, or placement of nodes and pickups, is minimized.

Overridden Functions[edit]

function bool AllowTransloc()
{
	return false;
}
 
static function bool NeverAllowTransloc()
{
	return true;
}

The ONS designers REALLY didn't want people Translocating around!

static function bool AllowMutator( string MutatorClassName )
{
	if ( MutatorClassName == "" )
		return false;
 
	if ( MutatorClassName ~= "xGame.MutInstagib" )
		return false;
	if ( MutatorClassName ~= "xGame.MutZoomInstagib" )
		return false;
 
	return super.AllowMutator(MutatorClassName);
}

They also don't like instagib. Anyone know the reasoning behind this?

function SetInitialState()
{
    Super.SetInitialState();
 
    SetCoreDistance(PowerCores[FinalCore[0]], 0, 0);
    SetCoreDistance(PowerCores[FinalCore[1]], 1, 0);
 
    UpdateLinks();
}
 
event InitGame(string Options, out string Error)
{
	local string InOpt, MapName;
	local ONSPowerLinkOfficialSetup P;
	local int x;
	local NavigationPoint N;
	local array<string> CustomPowerLinkSetupNames;
 
	Super.InitGame(Options, Error);
 
	x = 0;
	for(N = Level.NavigationPointList; N != None; N = N.NextNavigationPoint)
	{
		// Reset all PlayerStarts so that the PowerCores can determine their team and Pre-Rate them
		if (N.IsA('PlayerStart'))
			PlayerStart(N).bEnabled = False;
 
		// Register all the PowerCores
		if (N.IsA('ONSPowerCore'))
		{
			PowerCores[x] = ONSPowerCore(N);
			PowerCores[x].NotifyUpdateLinks = UpdateLinks;
			PowerCores[x].OnCoreDestroyed = MainCoreDestroyed;
 
			if (PowerCores[x].bFinalCore)
				FinalCore[PowerCores[x].DefenderTeamIndex] = x;
			x++;
		}
	}
 
	if (PowerCores.Length == 0)
	{
		log("Onslaught: Level doesn't have any PowerCores!",'Error');
		return;
	}
 
	MapName = Left(string(Level), InStr(string(Level), "."));
 
	OfficialPowerLinkSetups.length = 0;
	foreach AllActors(class'ONSPowerLinkOfficialSetup', P)
		OfficialPowerLinkSetups[OfficialPowerLinkSetups.length] = P;
 
	//For PerObjectConfig objects, the Outer overrides the default config file name.
	//This means by giving the Level as the Outer, the .ini name will be the same as the map name,
	//which is really cool because it makes it easy to trade custom setups - just copy that map's .ini
	CustomPowerLinkSetupNames = class'ONSPowerLinkCustomSetup'.static.GetPerObjectNames(MapName);
	for (x = 0; x < CustomPowerLinkSetupNames.length; x++)
		CustomPowerLinkSetups[CustomPowerLinkSetups.length] = new(Level, CustomPowerLinkSetupNames[x]) class'ONSPowerLinkCustomSetup';
 
	InOpt = ParseOption(Options, "bRandSetupAfterReset");
	if (InOpt != "")
		bRandSetupAfterReset = bool(InOpt);
 
	InOpt = ParseOption(Options, "LinkSetup");
	if (InOpt ~= "Random")
	{
		FindLinkSetup();
		return;
	}
	if (InOpt == "" || !SetPowerLinkSetup(InOpt, None))
	{
		if (!SetPowerLinkSetup("Default", None))
			FindLinkSetup();
	}
 
	// Big hack.. you shouldn't break scope this way :)
 
 	InOpt = ParseOption(Options,"BonusVehicles");
	if ( bool(InOpt) )
	{
		AddMutator("OnslaughtBP.MutBonusVehicles");
	}
 
}
 
event PostBeginPlay()
{
	SetupLinks();
	Super.PostBeginPlay();
}
 
function bool SetupExists(string SetupName)
{
	local int x;
 
	for (x = 0; x < OfficialPowerLinkSetups.length; x++)
		if (OfficialPowerLinkSetups[x].SetupName ~= SetupName)
			return true;
 
	for (x = 0; x < CustomPowerLinkSetups.length; x++)
		if (string(CustomPowerLinkSetups[x].Name) ~= SetupName)
			return true;
 
	return false;
}
 
function bool SetPowerLinkSetup(string SetupName, PlayerController Caller)
{
	local int x, y, z, i;
	local array<ONSPowerCore> Traveled;
 
	SetupName = Repl(SetupName, " ", "_");
 
	for (x = 0; x < OfficialPowerLinkSetups.length; x++)
		if (OfficialPowerLinkSetups[x].SetupName ~= SetupName)
		{
			//activate this setup
			for (y = 0; y < OfficialPowerLinkSetups[x].LinkSetups.length; y++)
				for (z = 0; z < PowerCores.length; z++)
					if (PowerCores[z].Name == OfficialPowerLinkSetups[x].LinkSetups[y].BaseNode)
						PowerCores[z].LinkedNodes = OfficialPowerLinkSetups[x].LinkSetups[y].LinkedNodes;
			ResetPowerLinks();
			Log("Using Official Link Setup: "$SetupName);
			CurrentSetupName = SetupName;
			bCurrentSetupIsOfficial = true;
			if (Caller != None)
				Caller.ReceiveLocalizedMessage(class'ONSLinkDesignMessage', 2);
			return true;
		}
 
	for (x = 0; x < CustomPowerLinkSetups.length; x++)
		if (string(CustomPowerLinkSetups[x].Name) ~= SetupName)
		{
			//activate this setup
			for (y = 0; y < CustomPowerLinkSetups[x].LinkSetups.length; y++)
				for (z = 0; z < PowerCores.length; z++)
					if (PowerCores[z].Name == CustomPowerLinkSetups[x].LinkSetups[y].BaseNode)
						PowerCores[z].LinkedNodes = CustomPowerLinkSetups[x].LinkSetups[y].LinkedNodes;
			ResetPowerLinks();
			if (PowerLinks.length > 0 && !ExistsLinkPathTo(PowerCores[FinalCore[0]], PowerCores[FinalCore[1]], Traveled))
			{
				//trying to load an invalid setup, revert to previous one
				CustomPowerLinkSetups.Remove(x, 1);
				if (Caller != None)
					Caller.ReceiveLocalizedMessage(class'ONSLinkDesignMessage', 8);
				else
					Log("Failed to load Custom Link Setup"@SetupName$": There is not a complete path between the PowerCores.");
				if (CurrentSetupName != "" && CurrentSetupName != SetupName && SetPowerLinkSetup(CurrentSetupName, None))
					return true;
				if (OfficialPowerLinkSetups.Length > 0)
				{
					FindLinkSetup();
					return true;
				}
				Log("Can't find a better link setup to load, so using"@SetupName@" anyway and forcing a connection between the PowerCores.");
				AddLink(PowerCores[FinalCore[0]], PowerCores[FinalCore[1]]);
				UpdateLinks();
				for (i = 0; i < GameReplicationInfo.PRIArray.Length; i++)
					if (PlayerController(GameReplicationInfo.PRIArray[i].Owner) != None && ONSPlayerReplicationInfo(GameReplicationInfo.PRIArray[i]) != None)
						ONSPlayerReplicationInfo(GameReplicationInfo.PRIArray[i]).ClientReceivePowerLink(PowerCores[FinalCore[0]], PowerCores[FinalCore[1]]);
				return true;
			}
			Log("Using Custom Link Setup: "$SetupName);
			CurrentSetupName = SetupName;
			bCurrentSetupIsOfficial = false;
			if (Caller != None)
				Caller.ReceiveLocalizedMessage(class'ONSLinkDesignMessage', 2);
			return true;
		}
 
	if (Caller != None)
		Caller.ReceiveLocalizedMessage(class'ONSLinkDesignMessage', 3);
	return false;
}
 
function ClearLinks()
{
	local int i;
 
	for ( i = 0; i < PowerLinks.Length; i++ )
		if ( PowerLinks[i] != None )
			PowerLinks[i].Destroy();
 
	PowerLinks.Remove(0, PowerLinks.Length);
}
 
function ResetPowerLinks()
{
	local int x;
	local ONSPlayerReplicationInfo PRI;
 
	if ( PowerLinks.Length == 0 )
		return;
 
	ClearLinks();
 
	for ( x = 0; x < PowerCores.Length; x++ )
		PowerCores[x].ResetLinks();
 
	SetupLinks();
 
	if (GameReplicationInfo != None)
	{
		for (x = 0; x < GameReplicationInfo.PRIArray.length; x++)
		{
			PRI = ONSPlayerReplicationInfo(GameReplicationInfo.PRIArray[x]);
			if ( PRI == None || PlayerController(PRI.Owner) == None )
				continue;
 
			PRI.ClientPrepareToReceivePowerLinks();
		}
	}
}
 
//Save a powercore link setup. Returns true if it successfully created a NEW setup and neither failed nor overwrote an old setup
function bool SavePowerLinkSetup(string SetupName, PlayerController Caller)
{
	local int x, y, z;
	local PowerLinkSetup BlankSetup;
	local string MapName;
 
	MapName = Left(string(Level), InStr(string(Level), "."));
	SetupName = Repl(SetupName, " ", "_");
 
	for (x = 0; x < OfficialPowerLinkSetups.length; x++)
		if (OfficialPowerLinkSetups[x].SetupName ~= SetupName)
		{
			Caller.ReceiveLocalizedMessage(class'ONSLinkDesignMessage', 1);
			return false;
		}
 
	for (x = 0; x < CustomPowerLinkSetups.length; x++)
		if (string(CustomPowerLinkSetups[x].Name) ~= SetupName)
		{
			//overwrite
			CustomPowerLinkSetups[x].LinkSetups.length = 0;
			for (y = 0; y < PowerCores.length; y++)
			{
				CustomPowerLinkSetups[x].LinkSetups[y] = BlankSetup;
				CustomPowerLinkSetups[x].LinkSetups[y].BaseNode = PowerCores[y].Name;
				for (z = 0; z < PowerCores[y].PowerLinks.length; z++)
					CustomPowerLinkSetups[x].LinkSetups[y].LinkedNodes[z] = PowerCores[y].PowerLinks[z].Name;
			}
			CustomPowerLinkSetups[x].SaveConfig();
			Caller.ReceiveLocalizedMessage(class'ONSLinkDesignMessage', 0);
			return false;
		}
 
	//save new
	x = CustomPowerLinkSetups.length;
	CustomPowerLinkSetups.length = CustomPowerLinkSetups.length + 1;
	CustomPowerLinkSetups[x] = new(Level, SetupName) class'ONSPowerLinkCustomSetup';
	CustomPowerLinkSetups[x].LinkSetups.length = 0;
	for (y = 0; y < PowerCores.length; y++)
	{
		CustomPowerLinkSetups[x].LinkSetups[y] = BlankSetup;
		CustomPowerLinkSetups[x].LinkSetups[y].BaseNode = PowerCores[y].Name;
		for (z = 0; z < PowerCores[y].PowerLinks.length; z++)
			CustomPowerLinkSetups[x].LinkSetups[y].LinkedNodes[z] = PowerCores[y].PowerLinks[z].Name;
	}
	CustomPowerLinkSetups[x].SaveConfig();
	Caller.ReceiveLocalizedMessage(class'ONSLinkDesignMessage', 0);
 
	return true;
}
 
//Deletes a powercore link setup. Returns true if successful, false if not
function bool DeletePowerLinkSetup(string SetupName, PlayerController Caller)
{
	local int x;
	local string MapName;
 
	MapName = Left(string(Level), InStr(string(Level), "."));
	SetupName = Repl(SetupName, " ", "_");
 
	for (x = 0; x < OfficialPowerLinkSetups.length; x++)
		if (OfficialPowerLinkSetups[x].SetupName ~= SetupName)
		{
			Caller.ReceiveLocalizedMessage(class'ONSLinkDesignMessage', 5);
			return false;
		}
 
	for (x = 0; x < CustomPowerLinkSetups.length; x++)
		if (string(CustomPowerLinkSetups[x].Name) ~= SetupName)
		{
			CustomPowerLinkSetups[x].ClearConfig();
			CustomPowerLinkSetups.Remove(x, 1);
			Caller.ReceiveLocalizedMessage(class'ONSLinkDesignMessage', 4);
			return true;
		}
 
	Caller.ReceiveLocalizedMessage(class'ONSLinkDesignMessage', 6);
	return false;
}
 
function FindLinkSetup(optional string IgnoredSetup)
{
	local int i, Sanity, TotalNumSetups;
	local string NewSetupName;
 
	TotalNumSetups = OfficialPowerLinkSetups.length + CustomPowerLinkSetups.length;
 
	if (TotalNumSetups == 0)
		Log("Using default Link Setup");
	else if (TotalNumSetups == 1 && CurrentSetupName != "")
		SetPowerLinkSetup(CurrentSetupName, None);
	else
	{
		do
		{
			i = Rand(TotalNumSetups);
			if (i < OfficialPowerLinkSetups.length)
				NewSetupName = OfficialPowerLinkSetups[i].SetupName;
			else
				NewSetupName = string(CustomPowerLinkSetups[i-OfficialPowerLinkSetups.length].Name);
			Sanity++;
		} until (NewSetupName != IgnoredSetup || Sanity > 1000)
 
		SetPowerLinkSetup(NewSetupName, None);
	}
}
 
static simulated function bool ExistsLinkPathTo(ONSPowerCore Start, ONSPowerCore Destination, out array<ONSPowerCore> Traveled)
{
	local int i, j;
	local bool bSkip;
 
	if (Start == None || Destination == None)
		return false;
 
	Traveled[Traveled.length] = Start;
 
	for (i = 0; i < Start.PowerLinks.Length; i++)
	{
		if (Start.PowerLinks[i] == Destination)
			return true;
		bSkip = false;
		for (j = 0; j < Traveled.length; j++)
		{
			if (Traveled[j] == Start.PowerLinks[i])
			{
				bSkip = true;
				break;
			}
		}
		if (!bSkip && ExistsLinkPathTo(Start.PowerLinks[i], Destination, Traveled))
			return true;
	}
 
	return false;
}
 
function SetCoreDistance(ONSPowerCore PC, byte T, byte Distance)
{
    local int i;
 
    PC.FinalCoreDistance[T] = Distance;
 
    for (i=0; i<PC.PowerLinks.Length; i++)
    {
        if (PC.PowerLinks[i].FinalCoreDistance[T] > Distance + 1)
            SetCoreDistance(PC.PowerLinks[i], T, Distance + 1);
    }
}
 
function UpdateLinks()
{
    local int i, j;
    local bool bRedCoreWasVulnerable, bBlueCoreWasVulnerable;
 
    if (!bScriptInitialized)	//PowerCores haven't done PostBeginPlay() yet
        return;
 
//	log(Name@"UpdateLinks");
    bRedCoreWasVulnerable = PowerCores[FinalCore[0]].bPoweredByBlue;
    bBlueCoreWasVulnerable = PowerCores[FinalCore[1]].bPoweredByRed;
 
    UpdateSeveredLinks();
 
    for (i=0; i<PowerCores.Length; i++)
    {
        PowerCores[i].bPoweredByRed = False;
        PowerCores[i].bPoweredByBlue = False;
        for (j=0; j<PowerCores[i].PowerLinks.Length; j++)
            if (PowerCores[i].PowerLinks[j].CoreStage == 0 && !PowerCores[i].PowerLinks[j].bSevered)
            {
                if (PowerCores[i].PowerLinks[j].DefenderTeamIndex == 0)
                    PowerCores[i].bPoweredByRed = True;
                else if (PowerCores[i].PowerLinks[j].DefenderTeamIndex == 1)
                    PowerCores[i].bPoweredByBlue = True;
            }
 
	if (PowerCores[i].CoreStage == 4 && (PowerCores[i].bPoweredByRed || PowerCores[i].bPoweredByBlue))
		PowerCores[i].CheckTouching();
        PowerCores[i].CheckShield();
    }
 
    if (!bRedCoreWasVulnerable && PowerCores[FinalCore[0]].bPoweredByBlue)
    	BroadcastLocalizedMessage(class'ONSOnslaughtMessage', 20);
    if (!bBlueCoreWasVulnerable && PowerCores[FinalCore[1]].bPoweredByRed)
    	BroadcastLocalizedMessage(class'ONSOnslaughtMessage', 21);
}
 
function UpdateSeveredLinks()
{
    local int i;
    local array<byte> WasSevered;
 
    for (i = 0; i < PowerCores.Length; i++)
    {
        WasSevered[i] = byte(PowerCores[i].bSevered);
        PowerCores[i].bSevered = True;
    }
 
    Sever(PowerCores[FinalCore[0]], 0);
    Sever(PowerCores[FinalCore[1]], 1);
 
    for (i = 0; i < PowerCores.Length; i++)
        if (!PowerCores[i].bDisabled && PowerCores[i].CoreStage != 4)
        {
            if (PowerCores[i].bSevered && WasSevered[i] == 0)
		PowerCores[i].Sever();
	    else if (!PowerCores[i].bSevered && WasSevered[i] == 1)
	    	PowerCores[i].UnSever();
	}
}
 
function Sever(ONSPowerCore PC, int TeamIndex)
{
    local int i;
    PC.bSevered = False;
    if (PC.CoreStage != 0)
        return;
    for (i = 0; i < PC.PowerLinks.Length; i++)
        if (PC.PowerLinks[i].bSevered && PC.PowerLinks[i].DefenderTeamIndex == TeamIndex)
            Sever(PC.PowerLinks[i], TeamIndex);
}
 
function Reset()
{
	bOverTime = false;
	bOverTimeBroadcast = false;
}
 
function StartMatch()
{
	local array<ONSPowerCore> Traveled;
	local int i;
 
	//check if the link setup is valid (in case host/admin edited it before game start)
	if (Level.NetMode != NM_Standalone && !ExistsLinkPathTo(PowerCores[FinalCore[0]], PowerCores[FinalCore[1]], Traveled))
	{
		//trying to load an invalid setup, revert to previous one
		Log("Current link setup is invalid: There is not a complete path between the PowerCores.");
		if (CurrentSetupName == "" || !SetPowerLinkSetup(CurrentSetupName, None))
		{
			if (OfficialPowerLinkSetups.length > 0)
				FindLinkSetup();
			else
			{
				Log("Can't find a better link setup to load, so forcing a connection between the PowerCores.");
				AddLink(PowerCores[FinalCore[0]], PowerCores[FinalCore[1]]);
				UpdateLinks();
				for (i = 0; i < GameReplicationInfo.PRIArray.Length; i++)
					if (PlayerController(GameReplicationInfo.PRIArray[i].Owner) != None && ONSPlayerReplicationInfo(GameReplicationInfo.PRIArray[i]) != None)
						ONSPlayerReplicationInfo(GameReplicationInfo.PRIArray[i]).ClientReceivePowerLink(PowerCores[FinalCore[0]], PowerCores[FinalCore[1]]);
			}
		}
	}
 
	Super.StartMatch();
}
 
State MatchInProgress
{
	event Timer()
	{
        local Controller C;
    	local int i, TeamNodes[2], TotalNodes;
    	local Actor A;
    	local bool bOldUnderAttack;
 
        for(i=0;i<PowerCores.Length;i++)
        {
        	if ( Level.TimeSeconds > PowerCores[i].LastAttackExpirationTime )
        	{
	            bOldUnderAttack = PowerCores[i].bUnderAttack;
	            PowerCores[i].bUnderAttack = (Level.TimeSeconds - PowerCores[i].LastAttackTime < PowerCores[i].LastAttackExpirationTime);
	            if (bOldUnderAttack != PowerCores[i].bUnderAttack)
	                PowerCores[i].UnderAttackChange();
	        }
 
            if (!PowerCores[i].bFinalCore && PowerCores[i].CoreStage != 255)
    	    {
    	    	if (PowerCores[i].CoreStage == 0 && PowerCores[i].DefenderTeamIndex < 2)
    	            	TeamNodes[PowerCores[i].DefenderTeamIndex]++;
    	        TotalNodes++;
    	    }
        }
 
        if (bOverTime)
        {
        	PowerCores[FinalCore[0]].TakeDamage(OvertimeCoreDrainPerSec - OvertimeCoreDrainPerSec * (float(TeamNodes[0]) / TotalNodes), None, vect(0,0,0), vect(0,0,0), None);
        	PowerCores[FinalCore[1]].TakeDamage(OvertimeCoreDrainPerSec - OvertimeCoreDrainPerSec * (float(TeamNodes[1]) / TotalNodes), None, vect(0,0,0), vect(0,0,0), None);
        }
 
        Super.Timer(); // Need this!!!
 
        if (ResetCountDown > 0)
        {
            ResetCountDown--;
            if ( ResetCountDown < 3 )
            {
				// blow up all redeemer guided warheads
				for ( C=Level.ControllerList; C!=None; C=C.NextController )
					if ( (C.Pawn != None) && C.Pawn.IsA('RedeemerWarhead') )
						C.Pawn.Fire(1);
 
			}
            if ( ResetCountDown == 8 )
            {
                for ( C = Level.ControllerList; C != None; C = C.NextController )
                    if ( PlayerController(C) != None )
                        PlayerController(C).PlayStatusAnnouncement('NewRoundIn',1,true);
            }
            else if ( (ResetCountDown > 1) && (ResetCountDown < 7) )
                BroadcastLocalizedMessage(class'TimerMessage', ResetCountDown-1);
            else if (ResetCountDown == 1)
            {
                Log("Reset Onslaught.");
 
            	for (C = Level.ControllerList; C != None; C = C.NextController)
            	{
                    if (PlayerController(C) != None)
                        PlayerController(C).ClientReset();
                    C.Reset();
                }
 
            	foreach AllActors(class'Actor', A)
            		if (!A.IsA('Controller') && !A.IsA('ONSPowerCore') && !A.IsA('TeamInfo'))
            			A.Reset();
 
            	//we reset powercores after everything else because their reset might cause
            	//vehiclefactories, etc to activate and spawn new actors that we don't want to affect
            	for (i = 0; i < PowerCores.length; i++)
            	{
                    if (bSwapSidesAfterReset && PowerCores[i].bFinalCore)
                    {
                        if (bSidesAreSwitched)
                            PowerCores[i].DefenderTeamIndex = PowerCores[i].default.DefenderTeamIndex;
                        else
                            PowerCores[i].DefenderTeamIndex = abs(PowerCores[i].default.DefenderTeamIndex - 1);
 
                        FinalCore[PowerCores[i].DefenderTeamIndex] = i;
                    }
                    else
                        PowerCores[i].DefenderTeamIndex = PowerCores[i].default.DefenderTeamIndex;
 
                    PowerCores[i].FinalCoreDistance[0] = 255;
                    PowerCores[i].FinalCoreDistance[1] = 255;
 
            		PowerCores[i].Reset();
            	}
 
            	if (bSwapSidesAfterReset)
            	{
                    SetCoreDistance(PowerCores[FinalCore[0]], 0, 0);
                    SetCoreDistance(PowerCores[FinalCore[1]], 1, 0);
                    bSidesAreSwitched = !bSidesAreSwitched;
                }
 
        		//possibly choose a new link setup
            	if (bRandSetupAfterReset && (OfficialPowerLinkSetups.length + CustomPowerLinkSetups.length) > 1)
            		FindLinkSetup(CurrentSetupName);
            	else
            		UpdateLinks();
 
                FindNewObjectives(None); //update AI
 
            	//now respawn all the players
            	for (C = Level.ControllerList; C != None; C = C.nextController)
            		if (C.PlayerReplicationInfo != None && !C.PlayerReplicationInfo.bOnlySpectator)
	            		RestartPlayer(C);
 
            	//reset timelimit
            	RemainingTime = 60 * TimeLimit;
            	GameReplicationInfo.RemainingMinute = RemainingTime;
 
                ResetCountDown = 0;
           }
        }
    }
}
 
function MainCoreDestroyed(byte T)
{
    local Controller C;
    local PlayerController PC;
    local int Score;
 
    if (bOverTime)
    	Score = 1;
    else
    	Score = 2;
 
    if (T == 1)
    {
        BroadcastLocalizedMessage( class'ONSOnslaughtMessage', 0);
        TeamScoreEvent(0, Score, "enemy_core_destroyed");
        Teams[0].Score += Score;
 		Teams[0].NetUpdateTime = Level.TimeSeconds - 1;
       CheckScore(PowerCores[FinalCore[1]].LastDamagedBy);
    }
    else
    {
        BroadcastLocalizedMessage( class'ONSOnslaughtMessage', 1);
        TeamScoreEvent(1, Score, "enemy_core_destroyed");
        Teams[1].Score += Score;
		Teams[1].NetUpdateTime = Level.TimeSeconds - 1;
        CheckScore(PowerCores[FinalCore[0]].LastDamagedBy);
    }
 
    //round has ended
    for (C = Level.ControllerList; C != None; C = C.NextController)
    {
    	PC = PlayerController(C);
    	if (PC != None)
    	{
    		PC.ClientSetBehindView(true);
    		PC.ClientSetViewTarget(PowerCores[FinalCore[T]]);
    		PC.SetViewTarget(PowerCores[FinalCore[T]]);
    		if (!bGameEnded)
    			PC.ClientRoundEnded();
    	}
    	if (!bGameEnded)
	    	C.RoundHasEnded();
    }
 
    ResetCountDown = ResetTimeDelay;
}
 
function CheckScore(PlayerReplicationInfo Scorer)
{
	if (CheckMaxLives(Scorer))
		return;
 
	if (GameRulesModifiers != None && GameRulesModifiers.CheckScore(Scorer))
		return;
 
	if (GoalScore != 0 && (Teams[0].Score >= GoalScore || Teams[1].Score >= GoalScore))
		EndGame(Scorer,"teamscorelimit");
}
 
function bool CheckEndGame(PlayerReplicationInfo Winner, string Reason)
{
	if (Reason ~= "TimeLimit")
	{
		if ( !bOverTimeBroadcast )
		{
			StartupStage = 7;
			PlayStartupMessage();
			bOverTimeBroadcast = true;
		}
		return false;
	}
 
	return Super.CheckEndGame(Winner, Reason);
}
 
function SetEndGameFocus(PlayerReplicationInfo Winner)
{
	local Controller P;
	local PlayerController player;
 
	if ( Winner != None )
	{
		if (Winner.Team.TeamIndex == 0)
			EndGameFocus = PowerCores[FinalCore[1]];
		else
			EndGameFocus = PowerCores[FinalCore[0]];
	}
	if ( EndGameFocus != None )
		EndGameFocus.bAlwaysRelevant = true;
 
	for ( P=Level.ControllerList; P!=None; P=P.nextController )
	{
		player = PlayerController(P);
		if ( Player != None )
		{
			if ( !Player.PlayerReplicationInfo.bOnlySpectator )
				PlayWinMessage(Player, (Player.PlayerReplicationInfo.Team == GameReplicationInfo.Winner));
			Player.ClientSetBehindView(true);
			Player.CameraDist = 10;
			if ( EndGameFocus != None )
			{
				Player.ClientSetViewTarget(EndGameFocus);
				Player.SetViewTarget(EndGameFocus);
			}
			Player.ClientGameEnded();
			if ( CurrentGameProfile != None )
				CurrentGameProfile.bWonMatch = (Player.PlayerReplicationInfo.Team == GameReplicationInfo.Winner);
		}
		P.GameHasEnded();
	}
}
 
function Killed(Controller Killer, Controller Killed, Pawn KilledPawn, class<DamageType> damageType)
{
	if (PlayerController(Killed) != None && ONSPlayerReplicationInfo(Killed.PlayerReplicationInfo) != None)
		ONSPlayerReplicationInfo(Killed.PlayerReplicationInfo).OwnerDied();
 
	Super.Killed(Killer, Killed, KilledPawn, damageType);
}
 
function bool CriticalPlayer(Controller Other)
{
	local int x;
 
	if (Other.Pawn == None || Other.PlayerReplicationInfo == None)
		return Super.CriticalPlayer(Other);
 
	for (x = 0; x < PowerCores.length; x++)
		if ( (PowerCores[x].CoreStage == 0 || PowerCores[x].CoreStage == 2) && PowerCores[x].DefenderTeamIndex != Other.GetTeamNum()
		     && ((PowerCores[x].bUnderAttack && Other.PlayerReplicationInfo == PowerCores[x].LastDamagedBy) || VSize(Other.Pawn.Location - PowerCores[x].Location) < 2000) )
			return true;
 
	return Super.CriticalPlayer(Other);
}
 
function bool ValidSpawnPoint(ONSPowerCore PC, int TeamIndex)
{
    return (PC != None && PC.DefenderTeamIndex == TeamIndex &&
            !PC.IsInState('NeutralCore') && !PC.IsInState('Reconstruction') &&
            (!PC.bUnderAttack || PC.bFinalCore));
}
 
function NavigationPoint FindPlayerStart( Controller Player, optional byte InTeam, optional string incomingName )
{
    local NavigationPoint N, BestStart;
    local Teleporter Tel;
    local float BestRating, NewRating;
    local byte Team, EnemyTeam;
    local ONSPowerCore SelectedPC;
    local float CoreDistA, CoreDistB;
    local int i;
    local Bot B;
 
    if ( GameRulesModifiers != None )
    {
        N = GameRulesModifiers.FindPlayerStart(Player,InTeam,incomingName);
        if ( N != None )
            return N;
    }
 
    // if incoming start is specified, then just use it
    if( incomingName!="" )
        foreach AllActors( class 'Teleporter', Tel )
            if( string(Tel.Tag)~=incomingName )
                return Tel;
 
    // use InTeam if player doesn't have a team yet
    if ( (Player != None) && (Player.PlayerReplicationInfo != None) )
    {
        if ( Player.PlayerReplicationInfo.Team != None )
            Team = Player.PlayerReplicationInfo.Team.TeamIndex;
        else
            Team = InTeam;
        //Use the powercore the player selected (if it's valid)
		if ( ONSPlayerReplicationInfo(Player.PlayerReplicationInfo) != None )
        {
    		SelectedPC = ONSPlayerReplicationInfo(Player.PlayerReplicationInfo).TemporaryStartCore;
    		ONSPlayerReplicationInfo(Player.PlayerReplicationInfo).TemporaryStartCore = None;
    		if (SelectedPC != None && !ValidSpawnPoint(SelectedPC, Team))
    			SelectedPC = None;
    		if (SelectedPC == None)
    		{
	        	SelectedPC = ONSPlayerReplicationInfo(Player.PlayerReplicationInfo).StartCore;
		        if (!ValidSpawnPoint(SelectedPC, Team))
                    SelectedPC = None;
	        }
        }
        if ( SelectedPC == None )
        {
	        //Bots always want to go to their SquadObjective
	        B = Bot(Player);
        	if (B != None && B.Squad != None && ONSPowerCore(B.Squad.SquadObjective) != None && ValidSpawnPoint(ONSPowerCore(B.Squad.SquadObjective), Team))
        		SelectedPC = ONSPowerCore(B.Squad.SquadObjective);
        }
    }
    else
        Team = InTeam;
 
    if (SelectedPC == None)
    {
    	if (PowerCores[FinalCore[Team]].PoweredBy(1 - Team))
    		SelectedPC = PowerCores[FinalCore[Team]];
 
    	if (SelectedPC == None)
    	{
	        // Find the Closest Controlled Node(s) to Enemy PowerCore.
	        EnemyTeam = abs(Team - 1);
	        BestRating = 255;
	        for (i = 0; i < PowerCores.Length; i++)
	        {
	            if (ValidSpawnPoint(PowerCores[i], Team))
	            {
	                NewRating = PowerCores[i].FinalCoreDistance[EnemyTeam];
	                if ( NewRating < BestRating )
	                {
	                    BestRating = NewRating;
	                    SelectedPC = PowerCores[i];
	                }
	                else if ( NewRating == BestRating ) // If we have two nodes at equal link distance, we check geometric distance
	                {
                        CoreDistA = VSize(PowerCores[FinalCore[EnemyTeam]].Location - PowerCores[i].Location);
                        CoreDistB = VSize(PowerCores[FinalCore[EnemyTeam]].Location - SelectedPC.Location);
                        if (CoreDistA < CoreDistB)
                            SelectedPC = PowerCores[i];
                    }
	            }
	        }
 
	        // If no valid power node found, set to power core.
            if (SelectedPC == None)
		        SelectedPC = PowerCores[FinalCore[Team]];
        }
    }
 
    for (i = 0; i < SelectedPC.CloseActors.length; i++)
        if (NavigationPoint(SelectedPC.CloseActors[i]) != None)
        {
	        NewRating = RatePlayerStart(NavigationPoint(SelectedPC.CloseActors[i]),Team,Player);
        	if ( NewRating > BestRating )
	        {
        	    BestRating = NewRating;
	            BestStart = NavigationPoint(SelectedPC.CloseActors[i]);
        	}
	}
 
    if (PlayerStart(BestStart) == None && SelectedPC != PowerCores[FinalCore[Team]])
    {
    	//couldn't find a start at the requested node, so try powercore
    	SelectedPC = PowerCores[FinalCore[Team]];
    	for (i = 0; i < SelectedPC.CloseActors.length; i++)
	        if (NavigationPoint(SelectedPC.CloseActors[i]) != None)
	        {
		        NewRating = RatePlayerStart(NavigationPoint(SelectedPC.CloseActors[i]),Team,Player);
	        	if ( NewRating > BestRating )
		        {
	        	    BestRating = NewRating;
		            BestStart = NavigationPoint(SelectedPC.CloseActors[i]);
	        	}
		}
    }
 
    if (PlayerStart(BestStart) == None)
    {
        log("Warning - PATHS NOT DEFINED or NO PLAYERSTART with positive rating");
	BestRating = -100000000;
        ForEach AllActors( class 'NavigationPoint', N )
        {
            NewRating = RatePlayerStart(N,0,Player);
            if ( InventorySpot(N) != None )
				NewRating -= 50;
			NewRating += 20 * FRand();
            if ( NewRating > BestRating )
            {
                BestRating = NewRating;
                BestStart = N;
            }
        }
    }
 
    return BestStart;
}
 
function ShowPathTo(PlayerController P, int TeamNum)
{
	local int x;
	local ONSPowerCore Best;
	local float BestDist;
	local class<WillowWhisp>	WWclass< SEMI >
 
	for (x = 0; x < PowerCores.Length; x++)
		if ( (PowerCores[x].CoreStage != 0 || PowerCores[x].DefenderTeamIndex != TeamNum) && PowerCores[x].PoweredBy(TeamNum)
		     && (Best == None || VSize(P.Pawn.Location - PowerCores[x].Location) < BestDist) )
		{
			Best = PowerCores[x];
			BestDist = VSize(P.Pawn.Location - PowerCores[x].Location);
		}
 
	if (Best != None && P.FindPathToward(Best, false) != None)
	{
		WWclass = class<WillowWhisp>(DynamicLoadObject(PathWhisps[TeamNum], class'Class'));
		Spawn(WWclass, P,, P.Pawn.Location);
	}
}
 
function GetServerInfo(out ServerResponseLine ServerState)
{
	Super.GetServerInfo(ServerState);
 
	if (!bCurrentSetupIsOfficial)
		ServerState.MapName $= "*";
}
 
function GetServerDetails(out ServerResponseLine ServerState)
{
	Super.GetServerDetails(ServerState);
 
	AddServerDetail( ServerState, "LinkSetup", CurrentSetupName );
}
 
function bool ChangeTeam(Controller Other, int num, bool bNewTeam)
{
	local int i;
	local ONSPlayerReplicationInfo PRI;
 
	if (Super.ChangeTeam(Other, num, bNewTeam))
	{
		if (Other == Level.GetLocalPlayerController())
		{
			//Update client side effects on powercores to reflect which ones the player can go after changing teams
			for (i = 0; i < PowerCores.length; i++)
				PowerCores[i].CheckShield();
		}
 
		PRI = ONSPlayerReplicationInfo(Other.PlayerReplicationInfo);
		if (PRI != None)
		{
			PRI.StartCore = None;
			PRI.TemporaryStartCore = None;
		}
 
		return true;
	}
 
	return false;
}
 
function PlayStartupMessage()
{
	Super.PlayStartupMessage();
 
	if (StartupStage == 7 && OvertimeCoreDrainPerSec > 0)
		BroadcastLocalizedMessage(class'ONSOnslaughtMessage', 29);
}
 
function ScoreObjective(PlayerReplicationInfo Scorer, float Score)
{
	if (Scorer != None)
		Scorer.Score += Score;
 
	if (GameRulesModifiers != None)
		GameRulesModifiers.ScoreObjective(Scorer,Score);
}
 
static event bool AcceptPlayInfoProperty(string PropertyName)
{
	if ( InStr(PropertyName, "bAllowTrans") != -1 )
		return false;
 
	return Super.AcceptPlayInfoProperty(PropertyName);
}
 
static function FillPlayInfo(PlayInfo PlayInfo)
{
	local int i;
 
	Super.FillPlayInfo(PlayInfo);  // Always begin with calling parent
 
	PlayInfo.AddSetting(default.GameGroup, "OvertimeCoreDrainPerSec", default.ONSPropsDisplayText[i++], 40, 1, "Text", "2;0:99");
	PlayInfo.AddSetting(default.GameGroup, "bRandSetupAfterReset",    default.ONSPropsDisplayText[i++], 0,  1, "Check",        ,,     , true);
	PlayInfo.AddSetting(default.GameGroup, "bSwapSidesAfterReset",    default.ONSPropsDisplayText[i++], 0,  1, "Check",        ,,     , true);
}
 
static event string GetDescriptionText(string PropName)
{
	switch (PropName)
	{
		case "OvertimeCoreDrainPerSec":	return default.ONSPropDescText[0];
		case "bRandSetupAfterReset":	return default.ONSPropDescText[1];
		case "bSwapSidesAfterReset":	return default.ONSPropDescText[2];
	}
 
	return Super.GetDescriptionText(PropName);
}
 
static function array<string> GetAllLoadHints(optional bool bThisClassOnly)
{
	local int i;
	local array<string> Hints;
 
	if ( !bThisClassOnly || default.ONSHints.Length == 0 )
		Hints = Super.GetAllLoadHints();
 
	for ( i = 0; i < default.ONSHints.Length; i++ )
		Hints[Hints.Length] = default.ONSHints[i];
 
	return Hints;
}
 
event Destroyed()
{
	CustomPowerLinkSetups.length = 0;
 
	Super.Destroyed();
}
 
function SetupLinks()
{
	local ONSPowerCore Core;
	local int i;
 
	if ( PowerCores.Length == 0 )
		return;
 
	Core = PowerCores[0];
	do
	{
		for ( i = 0; i < Core.PowerLinks.Length; i++ )
			AddLink(Core, Core.PowerLinks[i]);
 
		Core = Core.NextCore;
	} until ( Core == None || Core == PowerCores[0] );
}
 
function bool AddLink( ONSPowerCore A, ONSPowerCore B )
{
	local PowerLink Link;
 
	if ( HasLink(A,B) )
		return false;
 
	Link = Spawn(class'PowerLink');
	Link.SetNodes(A,B);
 
//	log(Name@"AddLink Link:"$Link.Name@"A:"$A.Name@"B:"$B.Name);
	PowerLinks[PowerLinks.Length] = Link;
//	A.AddPowerLink(B);
//	A.PowerCoreReset();
//	B.PowerCoreReset();
	return True;
}
 
function bool RemoveLink( ONSPowerCore A, ONSPowerCore B )
{
	local int i;
 
	for ( i = PowerLinks.Length - 1; i >= 0; i-- )
	{
		if ( PowerLinks[i] == None )
		{
			PowerLinks.Remove(i,1);
			continue;
		}
 
		if ( PowerLinks[i].HasNodes(A,B) )
		{
//			A.RemovePowerLink(B);
 
//			A.PowerCoreReset();
//			B.PowerCoreReset();
			PowerLinks[i].Destroy();
			PowerLinks.Remove(i,1);
			return True;
		}
	}
 
	return False;
}
 
function bool HasLink( ONSPowerCore A, ONSPowerCore B )
{
	local int i;
 
	for ( i = PowerLinks.Length - 1; i >= 0; i-- )
	{
		if ( PowerLinks[i] == None )
		{
			PowerLinks.Remove(i,1);
			continue;
		}
 
		if ( PowerLinks[i].HasNodes(A,B) )
			return True;
	}
 
	return False;
}
 
event PostLogin(PlayerController NewPlayer)
{
	Super.PostLogin(NewPlayer);
 
	if ( ONSPlayerReplicationInfo(NewPlayer.PlayerReplicationInfo) != None )
		ONSPlayerReplicationInfo(NewPlayer.PlayerReplicationInfo).ClientPrepareToReceivePowerLinks();
}
 
function DeadUse(PlayerController PC)
{
	Super.DeadUse(PC);
	PC.ShowMenu();
}

Related Classes[edit]

Discussion[edit]

Wormbo: Please don't create pages just for putting source code of stock classes on them. It important to write descriptions of the properties and functions of a class. The source is available for download anyway.

Sweavo: yep sorry, realized what I'd done as soon as I did it, but was starting to go cross-eyed and couldn't face doing the research! Will fix this.