Do you always need to initialize or register a mutator?

Discussions about Coding and Scripting
Post Reply
nullbyte
Novice
Posts: 27
Joined: Sat Sep 03, 2016 3:40 am

Do you always need to initialize or register a mutator?

Post by nullbyte »

Many mutator tutorials such as this one on BeyondUnreal include PreBeginPlay() or PostBeginPlay() blocks which initialize or register the mutator.

I tried making a very simple mutator complete with a .int file, and used it offline in a practice match via the Mutators menu. However, I kept getting an error when I started the match such as "(Function Engine.Mutator.AlwaysKeep:0000) Infinite script recursion (250 calls) detected".

When I removed the PreBeginPlay() block the mutator works fine.

So is it necessary to register your mutator? When would you or wouldn't you?

Compare the codes below:

Does not work via the Mutators menu offline:

Code: Select all

class MyFirstClass extends Mutator config(MyFirstMutator);

var bool bInitialized;

function PreBeginPlay() {
	if (!bInitialized) {
		bInitialized = true;
		Level.Game.BaseMutator.AddMutator(self);
		Level.Game.RegisterMessageMutator(Self);
	}
}

function Mutate(string MutateString, PlayerPawn Sender) {
	Sender.ClientMessage("Test");
}
Works via the Mutators menu offline:

Code: Select all

class MyFirstClass extends Mutator config(MyFirstMutator);

function Mutate(string MutateString, PlayerPawn Sender) {
	Sender.ClientMessage("Test");
}
Chris
Experienced
Posts: 134
Joined: Mon Nov 24, 2014 9:27 am

Re: Do you always need to initialize or register a mutator?

Post by Chris »

Maybe you shouldn't jump into programming before you even know the very basics of how the game is using mods.

That piece of code is adding the mutator programatically. You don't do that on itself, if the mutator is already loaded it makes no sense to load it again, so either you call that code from another actor spawning this mutator, or you just add it to the command line (Or the UT menu?) and remove this.

If you want your mutator to handle messages however then leave this.

Code: Select all

Level.Game.RegisterMessageMutator(Self);
nullbyte
Novice
Posts: 27
Joined: Sat Sep 03, 2016 3:40 am

Re: Do you always need to initialize or register a mutator?

Post by nullbyte »

Chris wrote:Maybe you shouldn't jump into programming before you even know the very basics of how the game is using mods.
You're right of course. Can you recommend any places with a high-level overview of this? I know the BeyondUnreal wiki has lots of great information but it's very in-depth and there's nothing (that I've seen, at least) which explains how the game uses mods as you say.

So if I understand correctly, when you add a mutator via the Mutators menu, UT is loading and registering the mutator itself and therefore it doesn't need to register itself programatically.

Does the same apply if you load a mutator via the server's command line?

And finally, I assume the same does not apply when you load via a ServerActor, in which case you do need to load the mutator programatically.
User avatar
PrinceOfFunky
Godlike
Posts: 1200
Joined: Mon Aug 31, 2015 10:31 pm

Re: Do you always need to initialize or register a mutator?

Post by PrinceOfFunky »

The system you're trying to understand is called Chain.
Simply, GameInfo contains the variable pointing to the first mutator which registered, this mutator contains a variable pointing to the second mutator which registered and so on...
Why do we need this chain? whatever class you make, you know for sure that all the mutators that registered are registered into that variable into GameInfo. It's just a way to standardize, organize and optimize the code making it more readable. Indeed, if you wouldn't have this chain, every class would need to use its own method to look for a mutator, like using a foreach etc...
You can see all the functions that call mutator's callback functions, call the callback from within the first mutator in GameInfo, that's cause all the mutator's callbacks, call the same callbacks from within the next mutator and so on.

Same happens to the Inventory. It doesn't happen to the TournamentPickup's when they are used as TournamentWeapon's Affector, indeed it leads to a bug. Look at this code from within ClientFire() function in TournamentWeapon.uc:

Code: Select all

if ( Affector != None )
			Affector.FireEffect();
Affector is a TournamentPickup, for example an Amplifier. Now, this is the function FIreEffect() from within TournamentPickup:

Code: Select all

function FireEffect();
Look at the difference with mutator's functions code, for example the function Mutate():

Code: Select all

function Mutate(string MutateString, PlayerPawn Sender)
{
	if ( NextMutator != None )
		NextMutator.Mutate(MutateString, Sender);
}
Do you see the difference? If you extend Mutator class, if you need the Mutate() function, you can just type super.Mutate(MutateString, Sender), and it would call the above code, calling the same function from within the NextMutator and so on, but look at the TournamentPickup code (remember TournamentPickup is an Actor and Actor has a variable pointing to the next Inventory), let's suppose you extend the class TournamentPickup and need the FireEffect() function, can you do the same that you would do for the mutator? No, you would need to handle the chain directly writing code in your class, and everyone that would extend TournamentPickup would need to do it. Thing that no one did, so for example, if you pickup 2 Amplifier they won't work properly.
"Your stuff is known to be buggy and unfinished/not properly tested"
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Do you always need to initialize or register a mutator?

Post by sektor2111 »

And now Cough Funky.
Not all time I have registered things.
Real fact:
Because I have fixed WarpZoneMarker stupid crash when player is hunting using map's paths, I went to add in server MHBotyMan4 tester mutator which is registered as message mutator but not as damagemutator. Happens because it doesn't use anything like TakeDamage, and it do works properly.
Trivia:
Default DMMutator from Botpack loaded in all default game-types doesn't register itself nowhere - it's a "BaseMutator" which also it's calling an useless "Super.PostBeginPlay()" because has it has nothing to call in parent classes. But maybe it's fancy to run useless codes for loading engine as much as possible for no purpose.
User avatar
PrinceOfFunky
Godlike
Posts: 1200
Joined: Mon Aug 31, 2015 10:31 pm

Re: Do you always need to initialize or register a mutator?

Post by PrinceOfFunky »

sektor2111 wrote:Default DMMutator from Botpack loaded in all default game-types doesn't register itself nowhere - it's a "BaseMutator" which also it's calling an useless "Super.PostBeginPlay()" because has it has nothing to call in parent classes. But maybe it's fancy to run useless codes for loading engine as much as possible for no purpose.
That's just bad programming, but it has to be registered in some way, indeed it is since DeathMatchPlus.uc specifies DMMutator as its default BaseMutator, which is the start of the mutator chain, the BaseMutator is registered by GameInfo itself:

Code: Select all

BaseMutator = spawn(MutatorClass);
It can be considered as an implicit registration.
"Your stuff is known to be buggy and unfinished/not properly tested"
Post Reply