Presentation is loading. Please wait.

Presentation is loading. Please wait.

Sega 500 Mutators Jeff “Ezeikeil” Giles

Similar presentations


Presentation on theme: "Sega 500 Mutators Jeff “Ezeikeil” Giles"— Presentation transcript:

1 Sega 500 Mutators Jeff “Ezeikeil” Giles jgiles@artschool.com http://gamestudies.cdis.org/~jgiles

2 So far We’ve created changes to the UT game play by modifying & creating our own content. HUD Weapons Game play / timing However all our changes have been restricted to game types.

3 Today We’re going to look at an alternate method of changing how UT runs / plays, known as mutators. The goal of the week is to cover how to build a mutator & wrap it up into an installer package for distribution.

4 Mutators…What are they? Mutators are special classes which modify the game being played in some way. Normally, mutators are single minded in their goals, such as just making the players fat, or reducing the gravity. As they’re name suggests, they are pretty good at modifying and replacing stuff. Although this can be accomplished by creating new game types, one of the main advantages of the Mutators is that you don't need a new game type.

5 Mutators…What are they? In fact, you can combine Mutators with any game type, including 3rd party mods. Provided they are properly written, they can be linked together, thus allowing you to more fully customize your gaming experience. For instance, it allows you to be fat AND have low gravity.

6 Mutators…What are they? Another reason to use Mutators is that during network play, the clients will not need to download anything to join, unless of course, they don’t have that mutator or it makes use of actors not shipped with Unreal.

7 Mutators…What are they? So running one for an example… Big head, instagib.

8 Mutators…What are they? In game we get And Instagibbers for all Changing head sizes… As you can see, Mandible here is not doing all that well

9 Mutators…What are they? After a bit of kick’n ass & take’n names… “Look a-his grrreat- huuge- crainium! It’s got It’s own weathar sistem!!!”

10 Mutators…What are they? This is really cool functionality to have at our fingertips. Radically changing the game WITH OUT changing the game type. In effect, Mutators are basically replacement classes. They are launched whenever an actor is spawned and by overriding some of the classes found in the standard Mutator class, we can control what items are to be spawned and which ones to scrap.

11 Mutators…What are they? You’ll find the mutator base class here: Object  Actor  Info  Mutator

12 Mutators…What are they? With the following header: Mutators allow modifications to gameplay while keeping the game rules intact. Mutators are given the opportunity to modify player login parameters with ModifyLogin(), To modify player pawn properties with ModifyPlayer() To change the default weapon for players with GetDefaultWeapon() To modify, remove, or replace all other actors when they are spawned with CheckRelevance(), which is called from the PreBeginPlay() function of all actors except those (Decals, Effects and Projectiles for performance reasons) which have bGameRelevant==true.

13 About the base class The first thing to note about it is that the mutator class not only has functionality to change the game dynamics, but is also a linked list. Look at the declaration: class Mutator extends Info DependsOn(GameInfo) native; var Mutator NextMutator;

14 But first… What is this DependsOn operation?

15 What the Wiki says… DependsOn Takes a class name as parameter. It allows you to automatically import the structs, constants, and enums of a class. You don't need to specify a package name. You can then refer to the structs, enums, and constants using the syntax ClassName.TypeName. The dependsOn modifier takes exactly one parameter. If your class depends on more classes you have to use the modifier several times,

16 Well, hang on a sec We’re in the mutator class, so why are we declaring a mutator first thing? class Mutator extends Info DependsOn(GameInfo) native; var Mutator NextMutator;

17 About the base class Doing so allows the mutators to be chained together and iterated over. This is very important to remember otherwise, you may not be able to compound you mutators together.

18 About the base class For example, from the mutator’s destroyed function: function Destroyed() { local Mutator M; // remove from mutator list if ( Level.Game.BaseMutator == self ) Level.Game.BaseMutator = NextMutator; else { for ( M=Level.Game.BaseMutator; M!=None; M=M.NextMutator ) if ( M.NextMutator == self ) { M.NextMutator = NextMutator;

19 Base class Defaults Default properties: IconMaterialName: allows mutators to have a symbol/graphic associated with them in the form TexturePack.Texture. ConfigMenuClassName: This is used if the mutator needs an extra config menu for special settings.

20 Base class Defaults GroupName: If there are two mutators in the same group, only one is allowed to be used at a time, e.g. Arena and No Superweapons. FriendlyName: This is the name seen in the mutator screen when starting a game.

21 Base class Defaults Description: A longer description/help text to tell players what the mutator does. Note: the real description is stored in the int file and over rides the one listed here.

22 About the base class This class also comes with a core set of basic functions And, unlike some of the other Script, has some useful comments.

23 About the base class event PreBeginPlay() and function bool MutatorIsAllowed() if the mutator isn't allowed, get rid of it. Mutators are allowed if this isn't the demo, or if the class is a basic Mutator. function Destroyed() The Destroyed() function for mutators must perform the added task of removing it from the linked list.

24 About the base class function ModifyLogin(out string Portal, out string Options) ModifyLogin could be used to create some special effect when a player logs in, or make an announcement function ModifyPlayer(Pawn Other) called by GameInfo.RestartPlayer() change the players jumpz, etc. here ModifyPlayer is commonly used to change speed, gravity, jump height, health and such.

25 About the base class function Class GetDefaultWeapon() return what should replace the default weapon mutators further down the list override earlier mutators. function Class GetInventoryClass(string InventoryClassName) return an inventory class - either the class specified by InventoryClassName, or a replacement. Called when spawning initial inventory for player.

26 About the base class function string GetInventoryClassOverride(string InventoryClassName) return the string passed in, or a replacement class name string. function string GetInventoryClassOverride(string InventoryClassName) return the string passed in, or a replacement class name string.

27 About the base class function class MyDefaultWeapon() return the default weapon used by the mutator. function AddMutator(Mutator M) adds a mutator onto the end of the linked list. function string RecommendCombo(string ComboName) used to modify the Combo Adrenalin moves used by players.

28 About the base class function bool ReplaceWith(actor Other, string aClassName) Call this function to replace an actor Other with an actor of aClass. scans the whole map replacing Other with aClass. It is better to call this than to modify it. function bool AlwaysKeep(Actor Other) Force game to always keep this actor, even if other mutators want to get rid of it Important because mutators are supposed to be pretty compatible with each other.

29 About the base class function bool IsRelevant(Actor Other, out byte bSuperRelevant) function bool CheckRelevance(Actor Other) function bool CheckReplacement(Actor Other, out byte bSuperRelevant) These functions check whether an actor is required by the game or not. It is required if a mutator has called AlwaysKeep() on it. CheckReplacement is used, for example, by NoSuperWeapons mutator to replace the Ion Painter with the Sniper Rifle

30 About the base class function PlayerChangedClass(Controller aPlayer) Called when a player sucessfully changes to a new class

31 About the base class function GetServerDetails( out GameInfo.ServerResponseLine ServerState ) function GetServerPlayers( out GameInfo.ServerResponseLine ServerState ) Server stuff. GetServerDetails returns the usual details of the server, plus something telling everyone that our mutator is active on it. GetServerPlayer does nothing (obviously) and ParseChatPercVar could be used for silencing players etc.

32 About the base class And that concludes a very high level walk through of the mutator base class. Now lets do something with it…

33 Building a mutator As always, starting simple. I’m going to implement a real basic mutator that simply doubles the players jump height.

34 Building a mutator Getting the set up stuff out of the way first, we derive our class off the mutator base class and set up our defaults. DefaultProperties { IconMaterialName="MutatorArt.nosym" ConfigMenuClassName="" GroupName="SuperBounce" FriendlyName="Super Bounce" Description="Doubles jump height “ }

35 Building a mutator And now add to the int file: So that we can call it from the menu. [Public] Object=(Class=Class,MetaClass=Engine.Mutator,Name=Eze.Bounce, Description="Doubles jump height.")

36 Building a mutator Our mutator But right now, it doesn’t do a thing.

37 Building a mutator Right, now we want to modify the players jump height…but how…err… Oh yeah, we have a function for that…Modify player…Sounds logical.

38 Building a mutator Our function: function ModifyPlayer(Pawn Other) { local Controller C; for (C = Level.ControllerList; C != None; C = C.NextController) { if (C.Pawn != none ) { C.Pawn.jumpz *=2; } super.ModifyPlayer(other); }

39 Building a mutator Remember the Level has a list of all the controllers in existence in the game, so well just iterate over all of these with the for loop. And then double the jumpz value with C.Pawn.jumpz*=2; Build & give it a shot…

40 Building a mutator Looks like it runs fine… But what’s that stuff falling from the sky? Hrmm…Weird.

41 Building a mutator Look what happens when I jump. I nearly go into orbit! What the heck is going on?

42 Building a mutator Here’s the mistake I made, I placed the following log in the for loop in my home build Log(c.PlayerReplicationInfo.PlayerName$"------------"$C.Pawn.jumpz); …look at what it spat out…

43 Building a mutator Some insanely huge float values…in the tens of thousands! Heh? The jumpZ default is only defined as JumpZ=+00420.000000 in the pawn class. Look again at the log…

44 Building a mutator The player names repeat and get doubled with every pass…even before the match starts. So what’s going on? The mutator is getting called with every access to any pawn. Doubling all of the jumpZ’s. Causing an exponential increase in our jump height.

45 Building a mutator The solution, after much head scratching, was surprisingly simple. I was just how I was accessing my values. It’s a one line fix. C.Pawn.jumpz = C.Pawn.default.jumpz*2; Double my default jump height and then assign it to my pawns jump height. This will allow for dynamic changes specific to the pawn type

46 Congrat’s You’ve just completed you first mutator, ready for release to the world.

47 A bit of polish. On a second look at this modify player function, I had a bit of an epiphany. Or some might say that I grew a brain.

48 A bit of polish. Looking back at what a mutator fundamentally is….a node in a linked list, it occurred to me that using the loop in the modify player function is a bad idea… …real bad.

49 A bit of polish. Think about this for a moment, I’ve a list of objects that I’m using to modify my players in turn…in effect, each node has a turn at processing a player. Thus, each pawn that gets processed in ModifyPlayer, modifies all other players in the game.

50 A bit of polish. Gah! That’s bad! But just for a chuckle, lets say there are 6 players in the game, using the controller loop: (C.Pawn.default.jumpz*2) * 6 * 6 * 6 * 6 * 6 * 6 (C.Pawn.default.jumpz*2;)*6^6 (C.Pawn.default.jumpz*2;)*46656

51 A bit of polish. *46656 !?!? My god! No wonder we go into orbit!

52 The solution: We’ll, not that we know why we were launching our pawns, How do we fix it.

53 The solution: First off, now that we’ve realized that we don’t want to loop over all the controllers here. It’s apparent that the modify player does it for us, we just need to set the new value.

54 The solution: Yup one function. function ModifyPlayer(Pawn Other) { Other.jumpz = Other.default.jumpz*2; super.ModifyPlayer(other); }

55 The Lesson? In many places in the code, objects can be link together in this manner, and it’s frequently not documented all that clearly.

56 The Lesson? Also, UT doesn’t really have any build in data structures (like linked lists and hash tables) to conveniently store stuff. Hence we often have to make our own. And a linked list in this fashion is the most common.

57 Tomorrow We’re going to expand on this to create a mutator that had the jump doubler as part of an adrenalin combo where, when the combo is active, the player can jump twice as high…along with combo effects.


Download ppt "Sega 500 Mutators Jeff “Ezeikeil” Giles"

Similar presentations


Ads by Google