• Register
Post tutorial Report RSS Unreal Learning #6: Post Processing

This tutorial will show you how to write a mutator that uses post processing. The code was written by Luke 'Ambershee' Parkes-Haskell for Shee Labs Mutator Week.

Posted by on - Basic Client Side Coding

Today we're going to recreate a mutator I wrote for Shee Labs Mutator Week! You can read about it here: Moddb.com

It's very short, very sweet and easy to modify to suit your needs. Once more, we're going to use a mutator and the modify player function. This time, we're going to change every players post process settings, and make it very difficult to see. We're also going to make the AI react accordingly, so they don't become too hard for the player to fight against.

class Blindness extends UTMutator;

function ModifyPlayer(Pawn Other)
{
local LocalPlayer LocalPlayer;
local PostProcessSettings DarkSettings;

LocalPlayer = LocalPlayer( PlayerController( Other.Controller ).Player );
LocalPlayer.bOverridePostProcessSettings = true;

DarkSettings = LocalPlayer.CurrentPPInfo.LastVolumeUsed.Settings;

DarkSettings.bEnableDOF = true;
DarkSettings.DOF_FocusInnerRadius = 1.f;
DarkSettings.DOF_BlurKernelSize = 12.f;

DarkSettings.DOF_MaxFarBlurAmount = 2.f;

DarkSettings.Scene_Desaturation *= 0.5f;

DarkSettings.Scene_HighLights.X -= 0.1f;
DarkSettings.Scene_HighLights.Y -= 0.1f;
DarkSettings.Scene_HighLights.Z -= 0.1f;

DarkSettings.Scene_Midtones.X *= 2.5f;
DarkSettings.Scene_Midtones.Y *= 2.5f;
DarkSettings.Scene_Midtones.Z *= 2.5f;

DarkSettings.Bloom_Scale *= 5.f;

LocalPlayer.PostProcessSettingsOverride = DarkSettings;

if ( UTPawn( Other ) != None )
{
UTPawn( Other ).SetInvisible( true );
}

super.ModifyPlayer( Other );
}

DefaultProperties
{
} 

Right! So let's analyse what we've written.

We need post process settings to set out blindness, and we also need a LocalPlayer. LocalPlayer is the class that contains the post processing controls, and it's all client side, which allows us to affect players on their machines, and not worry about the effects elsewhere - because we don't need to.

First, we find the local player (lots of nasty casting - we get the controller of the pawn, then cast it into a player controller, then we find the player of the player controller, and cast it into a local player - hope your head doesn't hurt!). We then set bOverridePostProcessSettings to true, so we can edit the post processing. We then set our post process settings to the last post process settings the local player used - this way, we don't just create new settings and ignore the post processing in the level, we can modify it instead.

In my settings, I enabled depth of field and added extra bloom. You could also add things like motion blur if you wanted. I also used the colour controls to desaturate the scene, and make it very dark - which in combination with the depth of field blur, makes it difficult to see!

I finally set the local player's post process settings override to our custom settings.

To make the AI work correctly, we check out pawn is a UTPawn, and if so, we set it invisible to AI. This means that the AI won't notice players unless the players are shooting, bump into them, or some other event that makes them noticeable.

And that's it! Compile it and play blind!

Post comment Comments
peterpanties
peterpanties - - 11 comments

For the first life works as expected. Once I die and respawn though, the darkness effect (desaturation) goes away and only the motion blur remains.
A contributor? Also, do you think there's a way to reset it once the player is killed? So that he can see what all is around him?

Reply Good karma Bad karma+1 vote
ambershee Author
ambershee - - 865 comments

You can over-ride the post process settings, and clear an over-ride at any time. You can therefore use a GameRules class to determine when you want to do this.

Reply Good karma+1 vote
peterpanties
peterpanties - - 11 comments

LocalPlayer = LocalPlayer( PlayerController( Other.Controller ).Player );
Also could you explain this a bit more. The small casting sectino on UDN didn't explain w hat it was very well.

Is LocalPlayer a singleton class? Only one object of it exists?

It seems like we're doing a LocalPlayer.PlayerController. but then I get lost at the Other.Controller..

Reply Good karma Bad karma+1 vote
ambershee Author
ambershee - - 865 comments

LocalPlayer.PlayerController is sort of what we're doing - but LocalPlayer doesn't actually have a PlayerController variable, nor a function to retrieve it.

In order to get a LocalPlayer (so that we can access the post process settings over-rides), we need to find the correct object, and cast it into a LocalPlayer.

In this case, we find the Pawn's controller (Other.Controller) and cast it into a PlayerController. The PlayerController class has a Player object called Player, and we can cast this into a LocalPlayer. Now we can finally access the post processing.

Reply Good karma+1 vote
p3gamer
p3gamer - - 10 comments

When I start a new deathmatch game (after already playing a game with this post processing effect), etc. even if I don't add this mutator to the new match, i still get the blur effect(maybe saturation also). I tried looking at the GameRules class but am not sure if I use the GetRules() method or something else. This is the first time(me being a mutator beginner) that I have seen a mutator get embedded into every following deathmatch game(even changed game type, level, etc.). Any ideas? Thanks

Reply Good karma Bad karma+1 vote
ambershee Author
ambershee - - 865 comments

I've never heard of that before - in fact it shouldn't be possible. Are you sure the mutator isn't active?

Reply Good karma+1 vote
p3gamer
p3gamer - - 10 comments

So I tried it again tonight: Two things: After I die and respawn the motion blur remains but I lose the darkness (same as peterpanties above).

But if I quit the match and change levels or game types, I continue to have the motion blur effect even when the mutator is not added (in fact I have no mutators added).

What exactly is PostProcessSettings? How would we reset them? Is it possible these settings are stored at a user or session level and only get cleared/reset when you start a new ut3.exe?

Reply Good karma Bad karma+1 vote
ambershee Author
ambershee - - 865 comments

Perhaps. Maybe patch 1.2 has changed a few things that make this work a bit funny - I'll have to look into it.

PostProcessSettings are stored on a user level on the client side (hence accessing the 'local player'. I wouldn't have thought motion blur would have persisted when the other settings do not - very unusual.

Reply Good karma+1 vote
p3gamer
p3gamer - - 10 comments

I don't think I have patch 1.2 (have not done any updates or downloads) I will check this after work.

Reply Good karma Bad karma+1 vote
p3gamer
p3gamer - - 10 comments

I updated to patch 1.2, and it still is giving me the same error. I also looked at the code found in the MWLightv100 file and did not see anything I was missing.

Reply Good karma Bad karma+1 vote
Velsk
Velsk - - 1 comments

I'm pretty late to this party, but for anyone else coming late that has the problem of the desaturation effect not working after one life here's a fix I found.

After the line:
LocalPlayer = LocalPlayer( PlayerController( Other.Controller ).Player );

Put everything before the if( UTPawn (Other) != None ) conditional line in an if block with the condition of:
if( !LocalPlayer.bOverridePostProcessSettings )

This way you're checking to see if you haven't already overridden the post processing settings. If you haven't then you apply them, otherwise you don't do anything to the PP settings.

I'm not sure why the code wasn't working after one death. If anything I would think it would just make the PP effects more severe on each subsequent death as you're modifying the PP settings by the same rate each life. Perhaps some threshold values are being reached immediately after one death?

Reply Good karma Bad karma+1 vote
Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: