[Tutorial] Custom Perks

  • 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/

S!cK

FNG / Fresh Meat
Nov 22, 2012
9
0
0
Hi everyone :)

I followed the instructions and created two simple Perks like in Tutorial Three. Everything works fine so far, but I recognized that the Zeds disappear instantly when I kill them with the weapon the Perk uses (eg.: G36C). (only the bodies disappear - gibs and blood are present, which is kind of strange.) This doesn't happen with any other weapon, except there is another perk using another weapon. Any ideas why this happens or how I can fix it?
Another problem I have: I can only create Perks with weapons extending KFFire. How should I edit the following lines (or others) when it extends KFShotgunFire (as an example)?
Thanks in advance! :)
Code:
static function AddCustomStats( ClientPerkRepLink Other )
{
    Other.AddCustomValue(Class'MediShotProgress');
    Class'WMediShotFire'.[U]Default.DamageType[/U] = Class'DamTypeMediShotNew';
}
 

forrestmark9

FNG / Fresh Meat
Nov 29, 2011
1,110
40
0
Hi everyone :)

I followed the instructions and created two simple Perks like in Tutorial Three. Everything works fine so far, but I recognized that the Zeds disappear instantly when I kill them with the weapon the Perk uses (eg.: G36C). (only the bodies disappear - gibs and blood are present, which is kind of strange.) This doesn't happen with any other weapon, except there is another perk using another weapon. Any ideas why this happens or how I can fix it?
Another problem I have: I can only create Perks with weapons extending KFFire. How should I edit the following lines (or others) when it extends KFShotgunFire (as an example)?
Thanks in advance! :)
Code:
static function AddCustomStats( ClientPerkRepLink Other )
{
    Other.AddCustomValue(Class'MediShotProgress');
    Class'WMediShotFire'.[U]Default.DamageType[/U] = Class'DamTypeMediShotNew';
}


Do it like this

Code:
static function AddCustomStats( ClientPerkRepLink Other )
{
    Other.AddCustomValue(Class'MediShotProgress');
    Class'WMediShotBullet'.Default.MyDamageType = Class'DamTypeMediShotNew';
}
 

PeridotPikachu

FNG / Fresh Meat
Jan 6, 2013
6
0
0
I have an error with my code that I can't seem to fix. It states that in line 61, "Error, Bad or missing expression in 'If'" I looked it up online and it's supposed to be an error when an if is given something other than a boolean. The confusing part is that there is no if on that line. Also confusing, is that the problem moves when I change the number of lines in the file, like when I delete/add a function. I haven't been able to find anything on this problem, so I'm hoping someone here knows how to fix this? I can post my code if needed.
 

FluX

Grizzled Veteran
Oct 26, 2010
5,394
234
63
www.fluxiserver.co.uk
I have an error with my code that I can't seem to fix. It states that in line 61, "Error, Bad or missing expression in 'If'" I looked it up online and it's supposed to be an error when an if is given something other than a boolean. The confusing part is that there is no if on that line. Also confusing, is that the problem moves when I change the number of lines in the file, like when I delete/add a function. I haven't been able to find anything on this problem, so I'm hoping someone here knows how to fix this? I can post my code if needed.
The code is needed otherwise we can't see how to fix it.
 

PeridotPikachu

FNG / Fresh Meat
Jan 6, 2013
6
0
0
Thank you, sorry about not posting the code, I wasn't sure if anyone might have heard something similar and known right away.
Here's my code, note that there is a few functions that don't do much, as I planned to edit it more after I tested it. I also edited it a bit, where I found mistakes, so now t says the problem is at line 69.

class PVetSprinter extends SRVeterancyTypes
abstract;
var array<int> progressArray;
static function AddCustomStats( ClientPerkRepLink Other )
{
Other.AddCustomValue(Class'PistolsProgress');
Class'Single'.Default.DamageType = Class'PistolsDamage';
Class'Dualies'.Default.DamageType = Class'PistolsDamage';
Class'Deagle'.Default.DamageType = Class'PistolsDamage';
Class'DualDeagle'.Default.DamageType = Class'PistolsDamage';
Class'MK23Pistol'.Default.DamageType = Class'PistolsDamage';
Class'DualMK23Pistol'.Default.DamageType = Class'PistolsDamage';
Class'Magnum44Pistol'.Default.DamageType = Class'PistolsDamage';
Class'DualMagnum44Pistol'.Default.DamageType = Class'PistolsDamage';
}
//Perk Progression
static function int GetPerkProgressInt( ClientPerkRepLink StatOther, out int FinalInt, byte CurLevel, byte ReqNum )
{
if (CurLevel < 7)
{
FinalInt= default.progressArray[curLevel];
}
else
{
FinalInt = default.progressArray[6]+GetDoubleScaling(CurLevel,500000);
}
return Min(StatOther.GetCustomValueInt(Class'PistolProgress'),FinalInt);
}
defaultproperties
{
progressArray(0)=5000
progressArray(1)=25000
progressArray(2)=100000
progressArray(3)=500000
progressArray(4)=1500000
progressArray(5)=3500000
progressArray(6)=5500000

VeterancyName="Sprinter"

OnHUDIcon=Texture'KillingFloorHUD.Perks.Perk_Berserker'
OnHUDGoldIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Berserker_Gold'

Requirements(0)="Deal %x pistol damage"

SRLevelEffects(0)="5% Perk Bonus"
SRLevelEffects(1)="10% Perk Bonus"
SRLevelEffects(2)="15% Perk Bonus"
SRLevelEffects(3)="20% Perk Bonus"
SRLevelEffects(4)="25% Perk Bonus"
SRLevelEffects(5)="30% Perk Bonus"
SRLevelEffects(6)="35% Perk Bonus"

CustomLevelInfo="%s Perk Bonus"

PerkIndex=7

}
static function float GetMovementSpeedModifier(KFPlayerReplicationInfo KFPRI, KFGameReplicationInfo KFGRI)
{
return 1.2 +0.2 * float(KFPRI.ClientVeteranSkillLevel);
}
static function string GetCustomLevelInfo( byte Level )
{
local string S;

S = Default.CustomLevelInfo;
ReplaceText(S,"%s",GetPercentStr(0.05 * float(Level)));
return S;
}
static function float GetReloadSpeedModifier(KFPlayerReplicationInfo KFPRI, KFWeapon Other)
{
if ( Single(Other) != none || Dualies(Other) != none
|| Deagle(Other) != none || DualDeagle(Other) != none
|| MK23Pistol(Other) != none || DualMK23Pistol(Other) != none
|| Magnum44Pistol(Other) != none || Dual44Magnum(Other) != none )
{
if ( KFPRI.ClientVeteranSkillLevel == 0 )
return 1.0;
return 1.0 + (0.2 * float(KFPRI.ClientVeteranSkillLevel));
}
return 1.0;
}
static function int AddCarryMaxWeight(KFPlayerReplicationInfo KFPRI)
{
return 0;
}
static function float GetCostScaling(KFPlayerReplicationInfo KFPRI, class<Pickup> Item)
{
if ( Single(Other) != none || Dualies(Other) != none
|| Deagle(Other) != none || DualDeagle(Other) != none
|| MK23Pistol(Other) != none || DualMK23Pistol(Other) != none
|| Magnum44Pistol(Other) != none || Dual44Magnum(Other) != none )
return FMax(0.9 - (0.10 * float(KFPRI.ClientVeteranSkillLevel)),0.1); // Up to 70% discount
return 1.0;
}
static function int AddDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InDamage, class<DamageType> DmgType)
{
if ( Single(Other) != none || Dualies(Other) != none
|| Deagle(Other) != none || DualDeagle(Other) != none
|| MK23Pistol(Other) != none || DualMK23Pistol(Other) != none
|| Magnum44Pistol(Other) != none || Dual44Magnum(Other) != none )
return InDamage * ( 1.0 + ( 0.1 * float(KFPRI.ClientVeteranSkillLevel)));
return InDamage;
}
 
Last edited:

Guardiannknight

FNG / Fresh Meat
Mar 24, 2012
420
0
0
www.guardiansworlds.com
Thank you, sorry about not posting the code, I wasn't sure if anyone might have heard something similar and known right away.
Here's my code, note that there is a few functions that don't do much, as I planned to edit it more after I tested it. I also edited it a bit, where I found mistakes, so now t says the problem is at line 69.

class PVetSprinter extends SRVeterancyTypes
abstract;
var array<int> progressArray;
static function AddCustomStats( ClientPerkRepLink Other )
{
Other.AddCustomValue(Class'PistolsProgress');
Class'Single'.Default.DamageType = Class'PistolsDamage';
Class'Dualies'.Default.DamageType = Class'PistolsDamage';
Class'Deagle'.Default.DamageType = Class'PistolsDamage';
Class'DualDeagle'.Default.DamageType = Class'PistolsDamage';
Class'MK23Pistol'.Default.DamageType = Class'PistolsDamage';
Class'DualMK23Pistol'.Default.DamageType = Class'PistolsDamage';
Class'Magnum44Pistol'.Default.DamageType = Class'PistolsDamage';
Class'DualMagnum44Pistol'.Default.DamageType = Class'PistolsDamage';
}
//Perk Progression
static function int GetPerkProgressInt( ClientPerkRepLink StatOther, out int FinalInt, byte CurLevel, byte ReqNum )
{
if (CurLevel < 7)
{
FinalInt= default.progressArray[curLevel];
}
else
{
FinalInt = default.progressArray[6]+GetDoubleScaling(CurLevel,500000);
}
return Min(StatOther.GetCustomValueInt(Class'PistolProgress'),FinalInt);
}
defaultproperties
{
progressArray(0)=5000
progressArray(1)=25000
progressArray(2)=100000
progressArray(3)=500000
progressArray(4)=1500000
progressArray(5)=3500000
progressArray(6)=5500000

VeterancyName="Sprinter"

OnHUDIcon=Texture'KillingFloorHUD.Perks.Perk_Berserker'
OnHUDGoldIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Berserker_Gold'

Requirements(0)="Deal %x pistol damage"

SRLevelEffects(0)="5% Perk Bonus"
SRLevelEffects(1)="10% Perk Bonus"
SRLevelEffects(2)="15% Perk Bonus"
SRLevelEffects(3)="20% Perk Bonus"
SRLevelEffects(4)="25% Perk Bonus"
SRLevelEffects(5)="30% Perk Bonus"
SRLevelEffects(6)="35% Perk Bonus"

CustomLevelInfo="%s Perk Bonus"

PerkIndex=7

}
static function float GetMovementSpeedModifier(KFPlayerReplicationInfo KFPRI, KFGameReplicationInfo KFGRI)
{
return 1.2 +0.2 * float(KFPRI.ClientVeteranSkillLevel);
}
static function string GetCustomLevelInfo( byte Level )
{
local string S;

S = Default.CustomLevelInfo;
ReplaceText(S,"%s",GetPercentStr(0.05 * float(Level)));
return S;
}
static function float GetReloadSpeedModifier(KFPlayerReplicationInfo KFPRI, KFWeapon Other)
{
if ( Single(Other) != none || Dualies(Other) != none
|| Deagle(Other) != none || DualDeagle(Other) != none
|| MK23Pistol(Other) != none || DualMK23Pistol(Other) != none
|| Magnum44Pistol(Other) != none || Dual44Magnum(Other) != none )
{
if ( KFPRI.ClientVeteranSkillLevel == 0 )
return 1.0;
return 1.0 + (0.2 * float(KFPRI.ClientVeteranSkillLevel));
}
return 1.0;
}
static function int AddCarryMaxWeight(KFPlayerReplicationInfo KFPRI)
{
return 0;
}
static function float GetCostScaling(KFPlayerReplicationInfo KFPRI, class<Pickup> Item)
{
if ( Single(Other) != none || Dualies(Other) != none
|| Deagle(Other) != none || DualDeagle(Other) != none
|| MK23Pistol(Other) != none || DualMK23Pistol(Other) != none
|| Magnum44Pistol(Other) != none || Dual44Magnum(Other) != none )
return FMax(0.9 - (0.10 * float(KFPRI.ClientVeteranSkillLevel)),0.1); // Up to 70% discount
return 1.0;
}
static function int AddDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InDamage, class<DamageType> DmgType)
{
if ( Single(Other) != none || Dualies(Other) != none
|| Deagle(Other) != none || DualDeagle(Other) != none
|| MK23Pistol(Other) != none || DualMK23Pistol(Other) != none
|| Magnum44Pistol(Other) != none || Dual44Magnum(Other) != none )
return InDamage * ( 1.0 + ( 0.1 * float(KFPRI.ClientVeteranSkillLevel)));
return InDamage;
}




Try putting your default properties stuff at the end. I'm on my phone, so i cannot really show you what I mean. But your code like speed increase and such, should go before your default properties. Default properties should be last. :)
 

PeridotPikachu

FNG / Fresh Meat
Jan 6, 2013
6
0
0
Thank you for the suggestion, didn't think about that. I'll try that and then edit the post to say if it worked.

I still have the same problem but thank you for telling me about default properties, I'll remember to put that at the end in the future.
 
Last edited:

Guardiannknight

FNG / Fresh Meat
Mar 24, 2012
420
0
0
www.guardiansworlds.com
Thank you for the suggestion, didn't think about that. I'll try that and then edit the post to say if it worked.

I still have the same problem but thank you for telling me about default properties, I'll remember to put that at the end in the future.


So your still having a problem after you code looks like this?

Spoiler!



if so, please post the error log so we can see what the error is :) But remember, we will need what the code looks like exactly when you get the error. So, we will need the current code and also the error log (the part of the log where you are getting the error and what the error is) :) that should find your problem :)

also, use spoiler tags to keep the code and error log from taking up the page. Do this by

[spoiler ]


[/spoiler ]

just move the ] over to the r :)
 
Last edited:

EpharGy

FNG / Fresh Meat
Jan 3, 2011
1,350
63
0
Australia
www.sykosis.co.uk
Code:
    Class'Single'.Default.DamageType = Class'PistolsDamage';
    Class'Dualies'.Default.DamageType = Class'PistolsDamage';
    Class'Deagle'.Default.DamageType = Class'PistolsDamage';
    Class'DualDeagle'.Default.DamageType = Class'PistolsDamage';
    Class'MK23Pistol'.Default.DamageType = Class'PistolsDamage';
    Class'DualMK23Pistol'.Default.DamageType = Class'PistolsDamage';
    Class'Magnum44Pistol'.Default.DamageType = Class'PistolsDamage';
    Class'DualMagnum44Pistol'.Default.DamageType = Class'PistolsDamage';

You changing the defaults for the wrong classes, your want to change the fire class of each weapon, not the inventory class.

The below part wont cause issues but you can skip an if check, what is 1 + (0.2*0)? 1 still, so you dont need the if ClientVeteranSkillLevel == 0 check.
Code:
static function float GetReloadSpeedModifier(KFPlayerReplicationInfo KFPRI, KFWeapon Other)
{
if ( Single(Other) != none || Dualies(Other) != none
|| Deagle(Other) != none || DualDeagle(Other) != none
|| MK23Pistol(Other) != none || DualMK23Pistol(Other) != none
|| Magnum44Pistol(Other) != none || Dual44Magnum(Other) != none )
{
if ( KFPRI.ClientVeteranSkillLevel == 0 )
return 1.0;
return 1.0 + (0.2 * float(KFPRI.ClientVeteranSkillLevel));
}
return 1.0;
}
 
Last edited:

PeridotPikachu

FNG / Fresh Meat
Jan 6, 2013
6
0
0
Thanks to both of you for your comments, I'll fix the defaults to the weapons fires when I can, if it doesn't work I'll get screenshots of everything. Also, I updated my post when I changed the code at all, with the exception of when I move the defaultproperties. I'l make sure to have the current code after changes in spoilers.
 

Gartley

Grizzled Veteran
Dec 27, 2010
2,339
349
83
UK
www.wildcardproductionstudios.co.uk
Formatting saves lives
Spoiler!


-Movement speed is fast, REALLY fast. At level six the player will be moving at 240% base speed. That is WAY to fast and will be overpowered. Consider matching medic's speed or lower (lower better). Which leads onto:

-Good idea to cap scaling values based on perk level.
static function int AddDamage
static function float GetReloadSpeedModifier
static function float GetMovementSpeedModifier

Movement speed as an example.
return 1.05 + FMin(0.05 * float(KFPRI.ClientVeteranSkillLevel - 2),0.55);

-Redundent function
static function int AddCarryMaxWeight(KFPlayerReplicationInfo KFPRI)

That's from what I could see at a casual glance. Check your work for typos and mistakes.

Happy modding. :D
 

EpharGy

FNG / Fresh Meat
Jan 3, 2011
1,350
63
0
Australia
www.sykosis.co.uk
Code:
static function int AddDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InDamage, class<DamageType> DmgType)
{
	if ( Single(Other) != none || Dualies(Other) != none || Deagle(Other) != none || DualDeagle(Other) != none
	|| MK23Pistol(Other) != none || DualMK23Pistol(Other) != none || Magnum44Pistol(Other) != none || Dual44Magnum(Other) != none )
		return InDamage * ( 1.0 + ( 0.1 * float(KFPRI.ClientVeteranSkillLevel)));			
	return InDamage;
}

After looking at Gartley's post, you should be specifying the Damage types not the inventory. Have a look through one of the default perks to see what i mean.
 

PeridotPikachu

FNG / Fresh Meat
Jan 6, 2013
6
0
0
Again, thanks to everyone who's helping me. I know the formatting is a mess, I had a friend rushing me so I would join his server, plus I wanted to get it done and see how it worked since this was mostly an experimental perk. I will post whether the changes each of you have suggested fix the issue most likely later day. Also, parts like the movement speed that need a cap is where I wanted to test and see if it worked, and probably would have really focused on making the perk reasonable after getting a feel for how things worked after testing. The pointless carry weight function was where I wanted to test if you could reduce carry weight, once the code started working. However, I didn't want to cause errors to the first test of the perk by doing that. Still, you have all be a great help, since I probably would have had to deal with all the other mistakes. Sorry I keep taking so long to respond and test the code, suddenly got very busy.
 

PeridotPikachu

FNG / Fresh Meat
Jan 6, 2013
6
0
0
I finally got it! The main problem was that I apparently copy pasted the Single(other) != none and the rest of them every time, instead of using the class'DualiesPickup' and such. I went back through and fixed those, then after fixing some issues like 44Magnum instead of Magnum44 it compiled. Thank you so much for helping me debug my perk. Hopefully I understand enough now to not get as many errors in the future.
 

Darkhp

FNG / Fresh Meat
May 9, 2013
2
0
0
Hi peopple...

first off all sorry for my bad english... i still have problems writing downs my thoughts.

you see... i was reading this tutorial got a error just in the beginning...

this is my code

Code:
class RATVetCommando extends SRVetCommando
	abstract;
defaultproperties
{
	VeterancyName="RAT Comando"
}

just a coppy from the first code... the problem is that every time i try to copile this is what happen:

Heading: --------------------------RATperks - Release--------------------------
Warning: Failed to load 'RATperks.u': Can't find file 'RATperks.u'
Warning: Failed loading package: Can't find file 'RATperks.u'
Log: Analyzing...
Log: FactoryCreateText: Class with ClassFactoryUC (0 1 ..\RATperks\Classes\RATVetCommando.uc)
Log: Class: RATVetCommando extends SRVetCommando
Log: Imported: Class RATperks.RATVetCommando
Critical: Superclass SRVetCommando of class RATVetCommando not found
Exit: Executing UObject::StaticShutdownAfterError
Critical: UMakeCommandlet::Main
Exit: Exiting.
Log: FileManager: Reading 0 GByte 206 MByte 510 KByte 101 Bytes from HD took 1.772011 seconds (1.583011 reading, 0.189000 seeking).
Log: FileManager: 0.063000 seconds spent with misc. duties
Uninitialized: Name subsystem shut down
Uninitialized: Log file closed, 05/09/13 14:50:02




I dont know what happen and neither how to solve it... so any help is useful...

i download the serverperks and put it on the System folder.. also i edited the killingfloor.ini
 

[SM]TOPSGT

FNG / Fresh Meat
Jul 12, 2011
376
5
0
Colorado
slsnipers.enjin.com
This bit of code below is taken from the perk listed above. I'm not sure if this is the correct format or code but i like the concept. I was working on a gunslinger perk but was having trouble getting the perk to register the damage done. I solved it by an award damage line in the dam type file. Is this a good way to insure that each weapon given to a perk will add to the dam stats in the way we want? Can a weapon be given to one perk registering one type of damage and also given to another perk and register damage to that perk also. An example would be the MK23 can it give bullpup damage for the Commando and demo damage if used by the Demoman? Is this a good addition to every perk for it's weapon group?

Code:
static function AddCustomStats( ClientPerkRepLink Other )
{
    Other.AddCustomValue(Class'PistolsProgress');
    Class'Single'.Default.DamageType = Class'PistolsDamage';
    Class'Dualies'.Default.DamageType = Class'PistolsDamage';
    Class'Deagle'.Default.DamageType = Class'PistolsDamage';
    Class'DualDeagle'.Default.DamageType = Class'PistolsDamage';
    Class'MK23Pistol'.Default.DamageType = Class'PistolsDamage';
    Class'DualMK23Pistol'.Default.DamageType = Class'PistolsDamage';
    Class'Magnum44Pistol'.Default.DamageType = Class'PistolsDamage';
    Class'DualMagnum44Pistol'.Default.DamageType = Class'PistolsDamage';
}

If someone has a better way.......Also if this method is sound but the actual code is incorrect in some way, please correct.
 

Moneigh

FNG / Fresh Meat
Jun 3, 2013
9
0
0
Hey all, I've been trying to figure this all out based on examples from here, a few other threads, the default KF perks, and a few other things.
In the end, I tried to make my own perk (surprise! :p ).
Using UCC make, I sort of plotted along, clearing the first error. And then the next. And the next. Lol.
Regrettably, it doesn't tell me what line the error occurs at, and it stops as soon as it hits the first error :( .

But anyways... I was wondering if someone could give me a lil hand with this combat medic perk I was putting together (I'd say it's still in testing... but I haven't tested it yet :p ).

So, I sorta split it up into the problems I think are left...
THIS gets Error, Unknown Property,'progressArrayA' in 'Function MoonVetPerk.MoonVetCombatMedic.GetPerkProgressInt'
Compile aborted due to errors.
Spoiler!

THIS is when I put in a perk bonus. For example, movement speed...
"Error, Bad or missing expression in 'If'"
Spoiler!

And here's the final perk that I'd wanted to test out before making minor changes for balancing and putting in level descriptions...
Spoiler!

Progress Array numbers were simply inserted with minimal thought, as perk lvling speed hasn't been determined yet.

but yeah, this is where I came from after trying to learn from all the examples I could find, it's killing me xD .
Any thoughts? :)