The script compiler is hardcoded to match the variably type of parameter 2 to that of the class type of parameter 1, but you can force it to search any non-hardcoded actor type... as long as the parameter 2 corresponds to 'Actor'.
=== Both syntaxis allowed by the compiler:
Code: Select all
local info IF;
ForEach AllActors( class'Info', IF)
break;
Code: Select all
local class<Actor> AC;
local Actor A;
//Load AC
if ( AC != None )
ForEach AllActors( AC, A)
break;
- With the second mechanism, if AC is none, then class'Actor' is forced internally.
- TraceActors is bugged and returns EVERY hit, for safety always do (class'Actor', A, ...) at all times.
=== Iterating with a different context:
It is possible to call these iterators using a different actor as context to modify the behaviour of the iterators, some iterators are designed for this to be explicitly done.
Find actors belonging to 'self'
Code: Select all
ForEach ChildActors( class'Actor', A)
{...}
Code: Select all
local Actor B;
if ( B != None )
ForEach B.ChildActors( class'Actor', A)
{...}
- If context is none, the game will crash.
- Both class/type mechanisms can be used here.
- In the case of TraceActors, parameter start will default to context's Location.
=== Non-standard iterators.
Both mechanisms also works on non-standard iterators, as long as you match the base object type the iterator wants you to input, in the following case it's Inventory.
Code: Select all
native(3542) final iterator function InventoryActors( class<Inventory> InvClass, out Inventory Inv, optional bool bSubclasses, optional Actor StartFrom);
The script engine doesn't verify that 'DesiredClass' is indeed a class<Inventory> type after the horrible hack I used, same happens with TraceActors when you try to get non-Actor results.
Code: Select all
function Inventory FindInventoryType_Fast( class<Inventory> DesiredClass ) //Compiler hack, originally class<Object>, parameter still passed!!!
{
local Inventory Inv;
if ( ClassIsChildOf( DesiredClass, class'Inventory') ) //Here we do check that it's a class<Inventory> being passed
ForEach InventoryActors( DesiredClass, Inv) //Native class check occurs here, so Inv matches what we're looking for
return Inv;
}
===============================
Here are a few examples of how this can be used in real life situations, mainly goes into interacting with other mods without requiring to load them.
Code: Select all
final function class<Actor> LoadActorClass( string S)
{
return Class<Actor>( DynamicLoadObject( S, class'class', true) ); //Third parameter prevents failure output in log
}
Code: Select all
function IteratorsTest()
{
local Actor A, B, C;
local Pawn P;
local class<Actor> AClass, BClass, CClass;
AClass = LoadActorClass( "XC_Engine.XC_Engine_Actor");
BClass = LoadActorClass( "SmartCTF_4D.SmartCTFPlayerReplicationInfo");
if ( BClass == None )
BClass = LoadActorClass( "SmartCTF_4C.SmartCTFPlayerReplicationInfo");
CClass = LoadActorClass( "IACEv10.IACEActor");
if ( CClass == None )
CClass = LoadActorClass( "IACEv08c.IACEActor");
//Find XC_Engine's main actor
if ( AClass != None )
ForEach AllActors( AClass, A)
Log("XC_Engine actor: "$A.Name);
//Find SmartCTF stats
if ( BClass != None )
For ( P=Level.PawnList ; P!=None ; P=P.NextPawn )
if ( P.bIsPlayer && (P.PlayerReplicationInfo != None) )
ForEach P.ChildActors( BClass, B)
{
//Do stuff
break;
}
//Find actors spawned by ACE
if ( CClass != None )
ForEach AllActors( CClass, C)
Log("ACE actor: "$C.Name@[$string(C.Class)$"]");
}