Actor.uc
Code: Select all
event PreBeginPlay()
{
// [...]
// Handle autodestruction if desired.
if( !bGameRelevant && (Level.NetMode != NM_Client) && !Level.Game.IsRelevant(Self) )
Destroy();
}
GameInfo.uc
Code: Select all
function bool IsRelevant( actor Other )
{
local byte bSuperRelevant;
// let the mutators mutate the actor or choose to remove it
if ( BaseMutator.AlwaysKeep(Other) )
return true;
if ( BaseMutator.IsRelevant(Other, bSuperRelevant) )
{
if ( bSuperRelevant == 1 ) // mutator wants to override any logic in here
return true;
}
else return false;
// [...]
return True;
}
event InitGame( string Options, out string Error )
{
local string InOpt, LeftOpt;
local int pos;
local class<Mutator> MClass;
// [...]
BaseMutator = spawn(MutatorClass);
log("Base Mutator is "$BaseMutator);
InOpt = ParseOption( Options, "Mutator");
if ( InOpt != "" )
{
log("Mutators"@InOpt);
while ( InOpt != "" )
{
pos = InStr(InOpt,",");
if ( pos > 0 )
{
LeftOpt = Left(InOpt, pos);
InOpt = Right(InOpt, Len(InOpt) - pos - 1);
}
else
{
LeftOpt = InOpt;
InOpt = "";
}
log("Add mutator "$LeftOpt);
MClass = class<Mutator>(DynamicLoadObject(LeftOpt, class'Class'));
BaseMutator.AddMutator(Spawn(MClass));
}
}
// [...]
}
The Mutators are basically some kind of a linked list.
Mutator.uc
Code: Select all
function bool AlwaysKeep(Actor Other)
{
if ( NextMutator != None )
return ( NextMutator.AlwaysKeep(Other) );
return false;
}
function bool IsRelevant(Actor Other, out byte bSuperRelevant)
{
local bool bResult;
// allow mutators to remove actors
bResult = CheckReplacement(Other, bSuperRelevant);
if ( bResult && (NextMutator != None) )
bResult = NextMutator.IsRelevant(Other, bSuperRelevant);
return bResult;
}
So it's end up that Mutator.CheckReplacement() is called, which you can implement your Mutator stuff. Or if you want to enforce the actor to stick around you would override Mutator.AlwaysKeep().
To hook an own mutator in you can use the BaseMutator setting in your gameinfo, add the options to the URL, or spawn your mutator explicit for your gameinfo, this would be handy when you have more then one mutator. e.g.
HXGameInfo.uc
Code: Select all
// ---------------------------------------------------------------------
// InitGame()
// ---------------------------------------------------------------------
event InitGame( string Options, out string Error )
{
// [...]
Super.InitGame(Options, Error);
// [...]
BaseMutator.AddMutator(Spawn(class'HXMutator'));
// [...]
}
However:
For classes which skip the Mutator logic, or you want to modify them before their PreBegin() call, you can do this in GameInfo's InitGame(), or in Mutators.*BeginPlay() events. However, the mutator events will be called twice, so make sure you wrote code which will not break when run twice. This spot is kinda nice when you want to use spawnnotifies. However when you want to catch actors spawned as early as PreBeginPlay(), like the AutoTurretGun, you will need to Link the spawnnotify in manually.
HXMutator.uc
Code: Select all
event PreBeginPlay()
{
local PawnGenerator PawnGen;
local ThrownProjectile ThrownProj;
local ElectricityEmitter Emitter;
local HXSpawnNotify SpawnNotify;
//local Dispatcher Disp;
foreach AllActors( class'DeusExLevelInfo', Info )
break;
if ( Info != None && localURL == "" )
LocalURL = Caps(Info.mapName);
// hackish (move to a spawn notify!)
foreach AllActors( class'PawnGenerator', PawnGen )
SetupPawnGenerator( PawnGen );
foreach AllActors( class'ThrownProjectile', ThrownProj )
{
if ( !ReplaceThrownProjectile( ThrownProj ) )
ThrownProj.Destroy();
}
foreach AllActors( class'ElectricityEmitter', Emitter )
{
if ( !ReplaceElectricityEmitter( Emitter ) )
Emitter.Destroy();
}
if ( localURL == "04_NYC_BATTERYPARK" )
{
Log( "TODO: Spawn BUZZ Sound Actors for 04_NYC_BATTERYPARK" );
}
SpawnNotify = Spawn(class'HXAutoTurretGunSpawnNotify');
SpawnNotify.Link();
}