HUDMutator Mini-Howto

  As you may have noticed, the HUD class has a HUDMutatorvar that can be used to call a Mutator to add features to the HUD. Unfortuneatly, the normal ModifyPlayer can't be used to set up each player's HUD in a network game. It works fine on the server side, but none of the clients get a modified HUD. This is because calls the MyHUD of players who aren't locally owned always returns a None.
  You can however use the SpawnNotify class to catch and modify HUD's (or anything else) when they are spawned. SpawnNotify is called on both client players and server players, so it works for all. Here's how it goes:

  1. Your main mutator should spawn a SpawnNotify Class.
  2. The SpawnNotify adds itself to everyone's level object automatically, insuring it gets called when a new object is spawned.
  3. Everytime a HUD is created, you catch it in the SpawnNotify Class and spawn a copy of your hud mutator, seting the HUD's HUDMutator variable to this new object. (Or to the NextMutator var of any Mutator already attached to the HUD.)
  Here is sampe source code. I have tested the code out - should allow multiple mutators that use this scheme to all link togeather and all work correctly. Please read through carefully, if you have any questions, email me. Feel free to use, modify, or redistribute the source, although I would prefer it if you left some comments in so the next guy can learn from your work.

Special thanks to Necron_99 for pointing out the AddMutator function. Makes this whole thing a lot more straightforward. Thanks also to Ob1 for pointing out that on listen servers and single player games, two hud mutators were being added and for providing a fix.




//=============================================================================
//  HUDTestMut is jsut a sample of how to get your SpawnNotify Class spawned.
//   This will be the Mutator you select from the Mutator Menu, so make sure
//   you .int file references this, not the HUDMut.
//
//  Andrew "drunken master" Scholer - ascholer@mediaone.net
//=============================================================================

class HUDTestMut expands Mutator;

function PreBeginPlay()
{
    spawn(class'asHUDTest.asHUDNotify');
}


defaultproperties
{
}




//=============================================================================
//  HUDMut is the mutator you will spawn for each actor to handle
//   the PostRender calls. Note that if there is another HUDMutator
//   attached to it it passes on the function call, allowing the
//   other mutator to do its work also.
//
//  Obviously, to coexist well with other HUDMutators, it might be a good
//   idea to make you draw location adjustable. If you display some status
//   indicators, try creating Mod Menu configurable choices between
//   displaying on the right, left or top of screen. That way user can set up
//   a few different HUD modifying mutators and know they won't overwrite
//   each other on screen.
//
//  Andrew "drunken master" Scholer - ascholer@mediaone.net
//=============================================================================

class HUDMut expands Mutator;


simulated function PostRender(canvas Canvas)
{
    //Do your cool stuff here instrad of this test code.

   Canvas.SetPos(50,50);
   Canvas.DrawText("This is a test");

    //If there is someone chained to this Mutator, call them
    // NextMutator is a variable of the Mutator class and will be set
    // up by the AddMutator call below.

    if ( NextMutator != None ) //next mutator is already defined within the mutator script
    {
         NextMutator.PostRender(Canvas);
    }
}


defaultproperties
{
}




//=============================================================================
// SpawnNotify - Actor spawn notification.
//   NB - This happens on the client AND server for replicated actors.
//
//  As many of you may have noticed, trying to get at MyHUD for clients in
//   a network game through ModifyPlayer dosen't work. Instead you have to
//   use a SpawnNotify actor. Once spawned, this guy sits around and intercepts
//   all spawn hotifications of a given class (Selected in default properties). 
//   Note the simulated function call - this guy works on both server and clients.
//
//  I added code to allow HUDmutators to chain off one another. This depends
//   on your HUDMutator class having a variable HUDMutator (see HUDMut). If
//   you really don't want to play nice, just can the else statement below.
//   Then only the first mutator in gets to use it's HUD.
//
//  Andrew "drunken master" Scholer - ascholer@mediaone.net
//=============================================================================

class asHUDNotify expands SpawnNotify;

//Called automatically anytime the class you specified in default properites
// is spawned (also called if a subclass of that class is spawned).
//Great way to catch things to modify or replace them - just make sure to use
// if statements to avoid infinite recursion if you replace something by
// spawning a new subclass.

simulated event Actor SpawnNotification( Actor A )
{
    local Mutator tempActor;
    local bool bFound;

    if ( HUD(A).HUDMutator == none ) {
        //If there aren't any HUDMutators attached to the HUD, attach
        // your mutator.
        HUD(A).HUDMutator = spawn(class'asHUDTest.HUDMut',A);
    }
    else
    {
        bFound = false;
	for (tempActor = HUD(A).HUDMutator; tempActor != None;
	     tempActor = tempActor.NextMutator)
	{
	    //make sure we don't add two of our mutator - can happen
	    // on listen servers and single player games
	    if (tempActor.class == class'asHUDTest.HUDMut')
	    {
	        bFound = true;
		break;
	    }
	}
	
        //If there is a HUDMutator attached to the HUD already, and
	// there are no instances of our mutator, call
	// AddMutator on that hud, passing it a newly spawned mutator
	// of your own. Note that the AddMutator function will
	// automatically seek the end of the mutator chain. (If the
	// one you try to add yourself to has a NextMutator, the
	// function call is passed to that mutator.)
	if (!bFound)	
            HUD(A).HUDMutator.AddMutator(spawn(class'asHUDTest.HUDMut',A));
    }

    //Have to return the original actor (the HUD). If we had completely
    // replaced it we would return the replacement.
    return A;
}


defaultproperties
{
    //This selects what class to intercept spawns for.
    ActorClass=class'Engine.HUD'
}