• Please make sure you are familiar with the forum rules. You can find them here: https://forums.tripwireinteractive.com/index.php?threads/forum-rules.2334636/

Code [Tutorial] Re-skinning a weapon.

So you've created yourself a bad *** skin in photo shop but now want to know how to get it onto a weapon.

Well first off this isn't Source. You can't simply replace your texture file and then go play on servers with the cvar sv_pure set to 0. Unreal just doesn't work that way.

I'm going to show you the easiest way to do this within the limitations of this Engine.

Prerequisites

Creating a Basic Mutator by Benjamin
Modifying Existing Weapons by Benjamin
Importing Textures by Whisky

The Mutator

Code:
class MutWeapReskin extends Mutator;

#exec obj load file="CUSTOMTEXTUREPACKAGE.utx" PACKAGE=MutWeapReskin

simulated function PostBeginPlay()
{
        class'WEAPONCLASS'.default.skins[0] = Combiner'MutWeapReskin.CUSTOMTEXTURE';
}

defaultproperties
{
     bAddToServerPackages=True
     GroupName="KF-"
     FriendlyName=""
     Description=""     
     Role=ROLE_Authority
     RemoteRole=ROLE_SimulatedProxy
     bAlwaysRelevant=true
}

That was easy wasn't it?

Breakdown

We start by loading the texture package we created into memory so it can find the texture. In this, as it's a small mut, I've told the code to repackage our utx into the mutator package as well. So then we have only to give out one file to clients. This works best on SMALL mods like reskins and hud changes. It's not really suitable for larger mods.

Code:
#exec obj load file="CUSTOMTEXTUREPACKAGE.utx" PACKAGE=MutWeapReskin

We call upon the PostBeginPlay() function because we want to change variable of the weapon's skin before the game starts. We then edit the weapon's defualt properties to reflect our changes. Something to bare in mind at this point is that there are currently two texture variables used by the weapons. Skins and SkinRef so check which one you need to replace before compiling otherwise you'll just get errors.

Code:
simulated function PostBeginPlay()
{
        class'AKFWEAPON'.default.skins[0] = Combiner'MutWeapReskin.CUSTOMTEXTURE';
}

In defualt properties:

Code:
bAddToServerPackages = true

is set so that a client connecting to a server running this mod downloads the required files. Better than manually adding to the server's config file.

Also the don't forget the group name must be prefixed with KF- otherwise it won't show up in the mutator list.

The following is a bit tricker to explain, so bare with me.

Code:
Role=ROLE_Authority
RemoteRole=ROLE_SimulatedProxy
bAlwaysRelevant=true

What we are doing here is telling the mutator that server is the boss and that the clients have to follow suit. This is to make sure the weapon var is replicated to the clients. Otherwise the server has a new skin but the client doesn't.

In regards to the 3rd person texture. You can't replace this by one line of code. What you have to do is create a new 3rd person mesh (duplication the existing and a new texture applied in the KFEd should be sufficient) then create a new attachment class and use the PostBeginPlay function to call on that

Code:
WEAPONCLASS.default.AttachmentClass=Class'MutWeapReskin.NewWeapAttactmentClass'

Extras

Some other variables you maybe interested in:
WEAPONCLASS.default.TraderInfoTexture - the image displayed by the trader
WEAPONCLASS.default.mesh & meshref for the actual 3D model (again depends on the weapon)
WEAPONCLASS.default.ItemName
PICKUPCLASS.default.ItemName
PICKUPCLASS.default.ItemShortName - string for the item's name (Yes there are 3 variables for this)
PICKUPCLASS.default.PickupMessage - string displayed on weapon pickup.
 
Last edited:
This tutorial should be improved to not pollute clients.

Quick rundown of what to change and explanation.

We're going to need to get rid of this defaultproperty changer because this is the cause of our client pollution. So remove this:
Code:
simulated function PostBeginPlay()
{
        class'AKFWEAPON'.default.skins[0] = Combiner'MutWeapReskin.CUSTOMTEXTURE';
}
And rewrite it such that:
Code:
function bool CheckReplacement(Actor Other, out byte bSuperRelevant)
{
        if(Other.IsA('MyWeaponClass')){
                class'MyWeaponClass'.Skins[0] = Combiner'MyWeapon.MyTexture';
        }
        return Super.CheckReplacement(Other, bSuperRelevant);
}
Note that you need to keep all the code from Gartley's class, we're just replacing PostBeginPlay().

This will not change the default property and will not greylist the client until they restart the game.
 
Upvote 0
This tutorial should be improved to not pollute clients.

Quick rundown of what to change and explanation.

We're going to need to get rid of this defaultproperty changer because this is the cause of our client pollution. So remove this:
Code:
simulated function PostBeginPlay()
{
        class'AKFWEAPON'.default.skins[0] = Combiner'MutWeapReskin.CUSTOMTEXTURE';
}
And rewrite it such that:
Code:
function bool CheckReplacement(Actor Other, out byte bSuperRelevant)
{
        if(Other.IsA('MyWeaponClass')){
                class'MyWeaponClass'.Skins[0] = Combiner'MyWeapon.MyTexture';
        }
        return Super.CheckReplacement(Other, bSuperRelevant);
}
Note that you need to keep all the code from Gartley's class, we're just replacing PostBeginPlay().

This will not change the default property and will not greylist the client until they restart the game.

Credit: a1estar (however you spell his name) :p
 
Upvote 0
This tutorial should be improved to not pollute clients.

Quick rundown of what to change and explanation.

We're going to need to get rid of this defaultproperty changer because this is the cause of our client pollution. So remove this:
Code:
simulated function PostBeginPlay()
{
        class'AKFWEAPON'.default.skins[0] = Combiner'MutWeapReskin.CUSTOMTEXTURE';
}
And rewrite it such that:
Code:
function bool CheckReplacement(Actor Other, out byte bSuperRelevant)
{
        if(Other.IsA('MyWeaponClass')){
                class'MyWeaponClass'.Skins[0] = Combiner'MyWeapon.MyTexture';
        }
        return Super.CheckReplacement(Other, bSuperRelevant);
}
Note that you need to keep all the code from Gartley's class, we're just replacing PostBeginPlay().

This will not change the default property and will not greylist the client until they restart the game.

Hm, as far as I know, Skins are not replicated to the clients, so this will not work online.
 
Upvote 0
I'm learning to mod KF, this tutorial is very useful, but it only seems to work with weapons that use skins[], not skinrefs[]. When I try to do that with the following script, for the MAC10, I get the compiler error for the line attempting to change skinrefs[0]:
Code:
(8): Error: Type mismatch in '='

My Mutator:
Spoiler!
I can't change the mesh/animation either, but I think that's a different issue.
 
Upvote 0
Code:
[...]
simulated function PostBeginPlay()
{
       [...]
       class'MAC10MP'.default.skinrefs[0]=Combiner'bkmac.MAC10_cmb';
}
[...]
Should be redone as:
Code:
[...]
simulated function PostBeginPlay()
{
       [...]
       class'MAC10MP'.default.skinrefs[0]=[COLOR=Lime]"bkmac.MAC10_cmb"[/COLOR];
}
[...]
This is because skinrefs is a string, not a material.
 
Last edited:
Upvote 0