![]() |
![]() |
|
#1
|
|||
|
|||
|
Prerequisites: Killing Floor SDK (Steam->Library->Tools)
Creating a Basic Mutator Step-by-step Instructions 1. Create directory hierarchy Create a directory in .../steamapps/common/killingfloor with the same name you wish to give your mutator. Create a subdirectory inside this named Classes. You should now have a directory structure that looks like this: .../steamapps/common/killingfloor/ExampleMutator/Classes 2. Create main mutator script file Inside the classes subdirectory create a file with a .uc extension with a name matching the mutator's main directory name, for example ExampleMutator.uc. The path of this file should look like this: .../steamapps/common/killingfloor/ExampleMutator/Classes/ExampleMutator.uc 3. Tell compiler we want to include this mutator in the compilation In order to have the compiler actually compile your mutator you must add an entry for it in a file named killingfloor.ini, located in the game's system directory. Open this file, search for the section with several lines beginning with EditPackages=PackageName. Add an entry at the bottom of this list to include the name of your mutator package, which should look like this: EditPackages=ExampleMutator 4. Add some code to the mutator script Code:
class ExampleMutator extends Mutator;
defaultproperties
{
GroupName="KFExampleMutator"
FriendlyName="Example Mutator"
Description="Mutator description here"
}
5. Compile using UCC Compiling the mutator is as simple as calling ucc make, which can be found in the system directory (in fact the file is simply called ucc.exe and make is a command line argument). Note that if you have previously compiled the mutator you must remove its .u file from the system directory in order to recompile (otherwise the mutator will be ignored in the compilation process). If you cannot find ucc.exe you may not have the Killing Floor SDK installed. Find it on Steam in the 'tools' section. Additionally you may want to remove certain files and have the console wait before closing, so that you can view the compilation output (and thus determine if it failed and why). You could do all this by opening command prompt and typing the commands manually, but it's far simpler to use a batch file. Create a batch file (anywhere - the desktop is good for easy access) with a name such as ExampleMutator.bat and copy the following lines in: Code:
del "C:\Program Files\Steam\steamapps\common\killingfloor\System\ExampleMutator.u" "C:\Program Files\Steam\steamapps\common\killingfloor\System\UCC.exe" make del "C:\Program Files\Steam\steamapps\common\killingfloor\System\steam_appid.txt" pause Run the batch file and tada! If compilation was successful, you have just made your first mutator. If not, you have made a mistake. 6. Functional mutator example Here is a functional, more interesting mutator to take a look at: Code:
class ExampleMutator extends Mutator;
function PostBeginPlay()
{
SetTimer(1, true);
}
function Timer()
{
local KFHumanPawn Player;
foreach DynamicActors(class 'KFHumanPawn', Player)
{
if (Player.Health + 2 <= Player.HealthMax) Player.Health += 2;
else Player.Health = Player.HealthMax;
}
}
defaultproperties
{
GroupName="KFExampleMutator"
FriendlyName="Example Mutator"
Description="Mutator description here"
}
7. Where do I go from here? Now that you understand how to compile a mutator, I'd recommend first taking a look at the official UnrealScript Language Reference which covers all aspects of the language itself. If you plan to write mutators which work online it's vital that you understand how the networking is handled, and I'd suggest reading the Unreal Networking Architecture article on this. If you want to know more about the engine (and particularly which classes are available to use) you can either browse through the script files yourself, or check out the BeyondUnreal Wiki. I'd recommend getting a good text editor with support for line numbers (I suggest Notepad++ for this) and a search tool for searching the entire library of script files for finding where specific classes and variables are defined (I'd recommend Windows Grep as it's powerful, fast, and free). Last edited by Benjamin; 05-25-2012 at 05:32 AM. |
|
#2
|
|||
|
|||
|
should add a function to customize the regen amount, otherwise GOOD JOB.
john was talking about doing this, and so was i, but now that it's been done, we dont have to ![]() keep up the good work. |
|
#3
|
|||
|
|||
|
Well, I wanted to keep it as simple as possible - I did actually edit a regen mutator I made which allowed customizing the regen speed and amount. Thanks, I plan to do some more (such as covering how to run code client-side and what bAddToServerPackages is used for).
I'm not exactly fluent when it comes to UnrealScript but I'd like to teach what I know and get other people interested. This forum needs more coders! |
|
#4
|
|||
|
|||
|
how do i create a mutator to modify specimen properties? (e.g. increase patriarch health, etc. ) i know that for players modifyplayers is used but what about the specimens?
|
|
#5
|
|||
|
|||
|
You can simply change a 'defaultproperties' variable of the relevant class when the mutator is loaded (in the PostBeginPlay function), like so:
Code:
class'ZombieBoss'.default.HealthMax = 9999; Last edited by Benjamin; 06-30-2010 at 08:31 AM. |
|
#6
|
|||
|
|||
|
i tried your suggestion.
"Error, Unrecognized member 'defaultproperties' in class 'Class'" speed doesn't seem to be in kfchar but rather in kfmod. also i tried both "class'ZombieClotBase'.default.GroundSpeed = 150;" and "class'ZombieClotBase'.default.GroundSpeed = 150;" in event PostBeginPlay() but they were still slow.
|
|
#7
|
|||
|
|||
|
Sorry, made a little mistake up there and it should have been 'default' instead of 'defaultproperties'.
When changing a default variable make sure you change it for the most derived class (which in the case of a clot is ZombieClot). Try setting ZombieClot's default GroundSpeed variable instead. Last edited by Benjamin; 06-30-2010 at 11:38 AM. |
|
#8
|
|||
|
|||
|
Thanks I'll try that when I get home. I'm at work right now. Your antiblock mutator does not require to be downloaded by clients. Is it possible for me to make a mutator that modifies the specimens as mentioned above without the clients having to download the mutator? Are there lines of code I can add to ensure that they don't download it? I want the gameplay to surprise the players. Thanks.
|
|
#9
|
|||
|
|||
|
Actually, it's simply a matter of not adding a particular line of code:
Code:
bAddToServerPackages=true Quote:
Code:
function bool CheckReplacement(Actor Other, out byte bSuperRelevant)
{
if (ZombieClot(Other) != None)
{
ZombieClot(Other).GroundSpeed = 10;
}
return Super.CheckReplacement(Other, bSuperRelevant);
}
|
|
#10
|
|||
|
|||
|
I see. Does that mean I should use both the CheckReplacement function and change the default groundspeed as you've mentioned?
"I'd suggest that for such variables you simply set the default properties on both the server and the client." CheckReplacement does this already right? Or do I have to do some other coding? "or instance uncrouching resets GroundSpeed to the default" Since the specimens do not crouch, I don't have to worry about the groundspeed resetting, do I? I'm kind of lost as far as covering all bases to make sure it works. Thanks for all these info Benjamin.
Last edited by krispyk; 06-30-2010 at 09:45 PM. |
|
#11
|
|||
|
|||
|
Well, that was just an example. There are other reasons for the specimen speed being temporarily altered, such as when attacking a door. For what you want you'll need to have both the server and client execute the mutator functions, and alter the default properties.
If you want to know if and when certain variables are changed, run WinGrep and search for the desired variable with a "*.uc" file filter in the killingfloor directory. |
|
#12
|
|||
|
|||
|
Quote:
This might be an easier mod to make than groundspeed.
|
|
#13
|
|||
|
|||
|
For HealthMax I'd recommend changing the default value. It won't match up with the default value on the client, but that shouldn't be an issue since the client never has to deal directly with health variables. I can only think of one thing that'd be strange for clients, and that's that in the cutscene for the patriarch the original HealthMax value will show in the corner. If you don't want this just use CheckReplacement instead (but not both). I think you'll need to alter Health too.
As I said before, check out the Multiplayer Mutators tutorial, it explains how to run functions client-side. Last edited by Benjamin; 06-30-2010 at 10:42 PM. |
|
#14
|
|||
|
|||
|
Thanks for the reply. I've been learning a lot as of late and I'm almost finished with my mutator. Is it possible for a mutator to execute a function or a command depending on which wave it is? Thanks.
Last edited by krispyk; 07-01-2010 at 04:07 AM. |
|
#15
|
|||
|
|||
|
Yeah, this is possible. For example, if you want to run per-wave code every timer call you can do something like this:
Code:
function Timer()
{
local KFGameType KF;
KF = KFGameType(Level.Game);
if (KF == None || !KF.bWaveInProgress) return;
if (KF.WaveNum == 1) {
// Handle wave 1 stuff
}
if (KF.WaveNum == 2) {
// Handle wave 2 stuff
}
}
|
|
#16
|
|||
|
|||
|
That's good news. The only problem I have is that I already use Timer() to change the maxplayers.
Code:
function PostBeginPlay()
{
// some code here to set specimen health
SetTimer(1, false);
}
function Timer()
{
Level.Game.MaxPlayers = 12;
}
Last edited by krispyk; 07-01-2010 at 06:14 AM. |
|
#17
|
|||
|
|||
|
You could either use states or simply use a variable to indicate what should happen:
Code:
function PostBeginPlay()
{
// some code here to set specimen health
SetTimer(1, true);
}
function Timer()
{
if (MyVar == 0) {
Level.Game.MaxPlayers = 12;
MyVar = 1;
}
else
{
// Handle other stuff here
}
}
|
|
#18
|
|||
|
|||
|
Edit: I think I've figured the timeout part. Thanks for everything Benjamin. What I'll do now is do some tests to see cpu/memory usage and how it affects pings. Thanks again.
Last edited by krispyk; 07-02-2010 at 04:16 AM. |
|
#19
|
|||
|
|||
|
I'd suggest simply using the lobby timeout setting in the server rules.
|
|
#20
|
||||
|
||||
|
Nice tutorial, but I think you shouldn't use "foreach DynamicActors" to get playerpawns:
Code:
function Timer()
{
local Controller C;
local KFHumanPawn Player;
for (C = Level.ControllerList; C != None; C = C.NextController) {
if (C.Pawn != None && KFHumanPawn(C.Pawn) != None) {
Player = KFHumanPawn(C.Pawn);
// stuff
}
}
}
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|