Prepare fixtures

This commit is contained in:
dkanus 2026-07-14 20:27:09 +07:00
commit 9c94356263
6021 changed files with 722805 additions and 22 deletions

View file

@ -0,0 +1,274 @@
/**
* Class for packaging various data types into an array of bytes.
* Copyright 2020 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
* Acedia is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License, or
* (at your option) any later version.
*
* Acedia is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Acedia. If not, see <https://www.gnu.org/licenses/>.
*/
class BitStreamReader extends Object;
// Array of bytes to read from
var private array<byte> stream;
var private int currentBytePointer;
var private int currentBitPointer;
// Write `byte` from `stream[currentBytePointer]` to avoid unnecessary
// array access calls.
var private byte currentByte;
var private const array<byte> bitMask;
var private const array<byte> bitMaskBefore;
var private const array<byte> bitMaskAfter;
var private int tempInt;
var private string tempString;
var private byte temp;
var private byte result;
var private byte rightBoundary;
var private byte remainingToRead;
var private byte byte1, byte2, byte3, byte4;
public final function Initialize(array<byte> newStream)
{
stream = newStream;
currentBytePointer = 0;
currentBitPointer = 0;
if (stream.length > 0) {
currentByte = stream[0];
}
}
private final function ShiftBytePointer()
{
currentBitPointer = 0;
currentBytePointer += 1;
if (currentBytePointer < stream.length) {
currentByte = stream[currentBytePointer];
}
else {
currentByte = 0;
}
}
public final function byte ReadBit()
{
if (currentBytePointer >= stream.length) return 0;
if ((currentByte & bitMask[currentBitPointer]) > 0) {
currentBitPointer += 1;
if (currentBitPointer >= 8) {
ShiftBytePointer();
}
return 1;
}
currentBitPointer += 1;
if (currentBitPointer >= 8) {
ShiftBytePointer();
}
return 0;
}
public final function bool ReadBool()
{
if (currentBytePointer >= stream.length) return false;
if ((currentByte & bitMask[currentBitPointer]) > 0) {
currentBitPointer += 1;
if (currentBitPointer >= 8) {
ShiftBytePointer();
}
return true;
}
currentBitPointer += 1;
if (currentBitPointer >= 8) {
ShiftBytePointer();
}
return false;
}
public final function byte ReadByte(optional int bitLimit)
{
if (currentBytePointer >= stream.length) return 0;
// Default `bitLimit`
if (bitLimit <= 0 || bitLimit > 8) {
bitLimit = 8;
}
// Throw away already read part
result = currentByte & bitMaskAfter[currentBitPointer];
if (bitLimit <= 8 - currentBitPointer)
{
// If all we are asked to read is contained in cuurent `byte` -
// just throw away excessive info by shifting to the right
result = result >>> (8 - currentBitPointer - bitLimit);
currentBitPointer += bitLimit;
if (currentBitPointer >= 8) {
ShiftBytePointer();
}
return result;
}
// Otherwise shift already read part up
rightBoundary = bitLimit - (8 - currentBitPointer);
result = result << rightBoundary;
// Move to the next byte
ShiftBytePointer();
currentBitPointer = rightBoundary;
// Record required part from the second byte
temp = currentByte & bitMaskBefore[rightBoundary];
temp = temp >>> (8 - rightBoundary);
result = result | temp;
return result;
}
public final function int ReadInt(optional int bitLimit)
{
// Default `bitLimit`
if (bitLimit <= 0 || bitLimit > 32) {
bitLimit = 32;
}
byte1 = ReadByte(bitLimit);
if (bitLimit <= 8) {
return byte1;
}
bitLimit -= 8;
byte2 = ReadByte(bitLimit);
if (bitLimit <= 8)
{
tempInt = byte1 << bitLimit;
tempInt = tempInt | byte2;
return tempInt;
}
bitLimit -= 8;
byte3 = ReadByte(bitLimit);
if (bitLimit <= 8)
{
tempInt = byte1 << (bitLimit + 8);
tempInt = tempInt | (byte2 << bitLimit);
tempInt = tempInt | byte3;
return tempInt;
}
bitLimit -= 8;
byte4 = ReadByte(bitLimit);
tempInt = byte1 << (bitLimit + 16);
tempInt = tempInt | (byte2 << (bitLimit + 8));
tempInt = tempInt | (byte3 << bitLimit);
tempInt = tempInt | byte4;
return tempInt;
}
public final function float ReadFloat(
int precisionLevel,
optional byte bitLimit)
{
if (bitLimit < 0 || bitLimit > 32) {
bitLimit = 32;
}
precisionLevel = Max(0, precisionLevel);
return float(ReadInt(bitLimit)) * (0.1 ** precisionLevel);
}
public final function string ReadString(int length)
{
if (length <= 0) return "";
while (length > 0)
{
length -= 1;
tempString $= Chr(ReadByte());
}
return tempString;
}
// String representation of `class`es has a more limited character range,
// which allows us to fit every chgaracter in `class`' name into 6 bits,
// saving 25% space.
// Allowed characters are: digits, upper and lower case letters, dot '.'
// and underscore '_'.
// Any other symbol is converted into an underscore.
private final function byte CompressClassCharacter(byte source)
{
// 26 upper case character
if (source >= 65 && source <= 90) {
return source - 65;
}
// 26 lower case character // 52 total
if (source >= 97 && source <= 122) {
return 26 + (source - 97);
}
// 10 digits // 62 total
if (source >= 48 && source <= 57) {
return 52 + (source - 48);
}
// dot
if (source == 46) {
return 62;
}
// underscore and everything else
return 63;
}
private final function byte DecompressClassCharacter(byte source)
{
if (source >= 63) return 95;
// 26 upper case character
if (source <= 25) {
return source + 65;
}
// 26 lower case character
if (source <= 51) {
return source + 71;
}
// 10 digits
if (source <= 61) {
return source - 4;
}
// dot
// if (source == 62)
return 46;
}
public final function string ReadClassName(int length)
{
if (length <= 0) return "";
while (length > 0)
{
length -= 1;
tempString $= Chr(DecompressClassCharacter(ReadByte(6)));
}
return tempString;
}
defaultproperties
{
bitMask(0) = 128 // 1 0 0 0 0 0 0 0
bitMask(1) = 64 // 0 1 0 0 0 0 0 0
bitMask(2) = 32 // 0 0 1 0 0 0 0 0
bitMask(3) = 16 // 0 0 0 1 0 0 0 0
bitMask(4) = 8 // 0 0 0 0 1 0 0 0
bitMask(5) = 4 // 0 0 0 0 0 1 0 0
bitMask(6) = 2 // 0 0 0 0 0 0 1 0
bitMask(7) = 1 // 0 0 0 0 0 0 0 1
bitMaskBefore(0) = 128 // 1 0 0 0 0 0 0 0
bitMaskBefore(1) = 192 // 1 1 0 0 0 0 0 0
bitMaskBefore(2) = 224 // 1 1 1 0 0 0 0 0
bitMaskBefore(3) = 240 // 1 1 1 1 0 0 0 0
bitMaskBefore(4) = 248 // 1 1 1 1 1 0 0 0
bitMaskBefore(5) = 252 // 1 1 1 1 1 1 0 0
bitMaskBefore(6) = 254 // 1 1 1 1 1 1 1 0
bitMaskBefore(7) = 255 // 1 1 1 1 1 1 1 1
bitMaskAfter(0) = 255 // 1 1 1 1 1 1 1 1
bitMaskAfter(1) = 127 // 0 1 1 1 1 1 1 1
bitMaskAfter(2) = 63 // 0 0 1 1 1 1 1 1
bitMaskAfter(3) = 31 // 0 0 0 1 1 1 1 1
bitMaskAfter(4) = 15 // 0 0 0 0 1 1 1 1
bitMaskAfter(5) = 7 // 0 0 0 0 0 1 1 1
bitMaskAfter(6) = 3 // 0 0 0 0 0 0 1 1
bitMaskAfter(7) = 1 // 0 0 0 0 0 0 0 1
}

View file

@ -0,0 +1,352 @@
/**
* Class for packaging various data types into an array of bytes.
* Copyright 2020 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
* Acedia is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License, or
* (at your option) any later version.
*
* Acedia is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Acedia. If not, see <https://www.gnu.org/licenses/>.
*/
class BitStreamWriter extends Object;
// Array of fully written bytes
var private array<byte> stream;
// Last byte that still has some space to fit data into.
// We start writing data into it's least significant bits and shift them up
// when we want to write more data inside or when we are asked to return
// recorded data.
var private byte unfinishedByte;
// How much space is left in `unfinishedByte`
var private byte bitsLeft;
// Can be used to erase unnecessary bits from a byte
var private const array<byte> bitMaskAfter;
// We'll declare all auxiliary variables as globals to avoid their
// unnecessary creation inside functions, to make them more lightweight.
var private byte shift, altShift;
var private byte temp;
var private int tempInt;
var private byte byte1, byte2, byte3, byte4;
/**
* Resets contents of the `BitStreamWriter`, making it the same as a
* brand new writer.
*
* @return `BitStreamWriter` to allow for function chaining.
*/
public final function BitStreamWriter InitializeStream()
{
stream.length = 0;
unfinishedByte = 0;
bitsLeft = 8;
return self;
}
/**
* Records a bit inside a `BitStreamWriter`.
*
* @param source Byte that defines a bit. We don't look at any actual bits in
* `source`'s representation, but simply consired the bit to be
* `1` if `source > 0` and `0` if `source == 0`.
* @return `BitStreamWriter` to allow for function chaining.
*/
public final function BitStreamWriter WriteBit(byte source)
{
unfinishedByte = unfinishedByte << 1;
if (source > 0) {
unfinishedByte += 1;
}
bitsLeft -= 1;
if (bitsLeft <= 0) {
stream[stream.length] = unfinishedByte;
unfinishedByte = 0;
bitsLeft = 8;
}
return self;
}
/**
* Records a bit inside a `BitStreamWriter`.
*
* @param source Boolean value that defines a bit. `true` means bit is equal
* to `1` and `false` means that it is equal to `0`.
* @return `BitStreamWriter` to allow for function chaining.
*/
public final function BitStreamWriter WriteBoolean(bool isOne)
{
unfinishedByte = unfinishedByte << 1;
if (isOne) {
unfinishedByte += 1;
}
// Update storage
bitsLeft -= 1;
if (bitsLeft <= 0) {
stream[stream.length] = unfinishedByte;
unfinishedByte = 0;
bitsLeft = 8;
}
return self;
}
/**
* Records a `byte` inside a `BitStreamWriter`.
*
* @param source Boolean value that defines a bit. `true` means bit is
* equal to `1` and `false` means that it is equal to `0`.
* @param bitLimit How many of the (least significant) bits to record;
* can be used to compress values that don't need the full `byte`
* value range.
* @return `BitStreamWriter` to allow for function chaining.
*/
public final function BitStreamWriter WriteByte(
byte source,
optional byte bitLimit)
{
// Default `bitLimit`
if (bitLimit < 0 || bitLimit > 8) {
bitLimit = 8;
}
// Zero unnecessary bits
source = source & bitMaskAfter[8 - bitLimit];
if (bitLimit < bitsLeft)
{
// We have enough space to fit all the bits in `unfinishedByte`
unfinishedByte = unfinishedByte << bitLimit;
unfinishedByte = unfinishedByte | source;
// Update storage
bitsLeft -= bitLimit;
if (bitsLeft <= 0)
{
stream[stream.length] = unfinishedByte;
unfinishedByte = 0;
bitsLeft = 8;
}
return self;
}
// If we don't have enough space, - record what can fit in
// current `unfinishedByte`
unfinishedByte = unfinishedByte << bitsLeft;
altShift = bitLimit - bitsLeft;
temp = source >>> altShift;
unfinishedByte = unfinishedByte | temp;
// And add it to the storage
stream[stream.length] = unfinishedByte;
// Create new byte by erasing recorded bits from the `source`
temp = temp << altShift;
unfinishedByte = source ^ temp;
bitsLeft = 8 - altShift;
return self;
}
/**
* Records an `int` inside a `BitStreamWriter`.
*
* @param source Integer value to record into `BitStreamWriter`.
* @param bitLimit How many of the (least significant) bits to record;
* can be used to compress values that don't need the full `int`
* value range.
* @return `BitStreamWriter` to allow for function chaining.
*/
public final function BitStreamWriter WriteInt(
int source,
optional byte bitLimit)
{
// Default `bitLimit`
if (bitLimit == 0) {
bitLimit = 32;
}
byte1 = byte((source & 0xff000000) >>> 24);
byte2 = byte((source & 0x00ff0000) >>> 16);
byte3 = byte((source & 0x0000ff00) >>> 8);
byte4 = source & 0x000000ff;
if (bitLimit > 24) {
WriteByte(byte1, bitLimit - 24);
}
if (bitLimit > 16) {
WriteByte(byte2, bitLimit - 16);
}
if (bitLimit > 8) {
WriteByte(byte3, bitLimit - 8);
}
WriteByte(byte4, bitLimit);
return self;
}
/**
* Records an `float` inside a `BitStreamWriter`.
*
* `floats` can only be recorded with a specified amount of decimal places.
* This is because we can't really get precise float bit representation or
* easily truncate it's value bit-wise, so we multiply it by a specified
* power of 10 and then transfer integer part of the result as `int`.
* Specified precision level IS NOT recorded into `BitStreamWriter`.
*
* @param source Integer value to record into `BitStreamWriter`.
* @param precisionLevel How many decimal places after the dot to record.
* @param bitLimit How many of the (least significant) bits to record;
* can be used to compress values that don't need the full value range of
* truncated float.
* @return `BitStreamWriter` to allow for function chaining.
*/
public final function BitStreamWriter WriteFloat(
float source,
int precisionLevel,
optional byte bitLimit)
{
if (bitLimit < 0 || bitLimit > 32) {
bitLimit = 32;
}
precisionLevel = Max(0, precisionLevel);
tempInt = int(Round( source * (10 ** precisionLevel) ));
WriteInt(tempInt, bitLimit);
return self;
}
/**
* Records an `string` inside a `BitStreamWriter`, treating each code point as
* a byte, which will lead to loss of data when recording `string`s that
* contain code points with values `> 255`.
*
* Does not record `string`'s length or where it ends.
*
* @param source `string` value to record into `BitStreamWriter`.
* @return `BitStreamWriter` to allow for function chaining.
*/
public final function BitStreamWriter WriteString(string source)
{
while (source != "")
{
WriteByte(Asc(source));
source = Mid(0, 1);
}
return self;
}
/**
* Records an string representation of a `class` name inside
* a `BitStreamWriter`, compressing it's characters to 6 bit representation.
*
* Allowed characters are: digits, upper and lower case letters, dot '.'
* and underscore '_'.
* Any other character will be converted into underscore.
*
* Does not record `string`'s length or where it ends.
*
* @param source String representation of a `class`' name value to record
* into `BitStreamWriter`.
* @return `BitStreamWriter` to allow for function chaining.
*/
public final function BitStreamWriter WriteClassName(string source)
{
while (source != "")
{
WriteByte(CompressClassCharacter(Asc(source)), 6);
source = Mid(source, 1);
}
return self;
}
// String representation of `class`es has a more limited character range,
// which allows us to fit every chgaracter in `class`' name into 6 bits,
// saving 25% space.
// Allowed characters are: digits, upper and lower case letters, dot '.'
// and underscore '_'.
// Any other symbol is converted into an underscore.
private final function byte CompressClassCharacter(byte source)
{
// 26 upper case character
if (source >= 65 && source <= 90) {
return source - 65;
}
// 26 lower case character // 52 total
if (source >= 97 && source <= 122) {
return 26 + (source - 97);
}
// 10 digits // 62 total
if (source >= 48 && source <= 57) {
return 52 + (source - 48);
}
// dot
if (source == 46) {
return 62;
}
// underscore (`95`) and everything else
return 63;
}
/**
* Returns all data recorded so far in a caller `BitStreamWriter` as
* an array of bytes. Data is written ion order, starting from bytes with
* lesser indecies and their most significant bits.
*
* @return Array of bytes that contains all data written into caller
* `BitStreamWriter`.
*/
public final function array<byte> GetData()
{
local array<byte> result;
result = stream;
if (bitsLeft < 8) {
result[result.length] = unfinishedByte << bitsLeft;
}
return result;
}
/**
* Returns amount of data (in bits) recorded into caller `BitStreamWriter`.
*
* @return Amount (in bits) of recorded data.
*/
public final function int GetSize()
{
local int sizeInBits;
sizeInBits = stream.length * 8;
if (bitsLeft < 8) {
sizeInBits += (8 - bitsLeft);
}
return sizeInBits;
}
/**
* Returns amount of data (in bytes) recorded into caller `BitStreamWriter`.
*
* @param onlyFullBytes Only count filled bytes, i.e. if last byte only has
* 5 bits (or any amount `<8`) of info written in it -
* method will not count it.
* @return Amount (in bytes) of recorded data.
*/
public final function int GetSizeInBytes(optional bool onlyFullBytes)
{
local int sizeInBytes;
sizeInBytes = stream.length;
if (!onlyFullBytes && bitsLeft < 8) {
sizeInBytes += 1;
}
return sizeInBytes;
}
defaultproperties
{
// With this we do not need to call `Initialize` to use a newly created
// `BitStreamWriter`
bitsLeft = 8
bitMaskAfter(0) = 255 // 1 1 1 1 1 1 1 1
bitMaskAfter(1) = 127 // 0 1 1 1 1 1 1 1
bitMaskAfter(2) = 63 // 0 0 1 1 1 1 1 1
bitMaskAfter(3) = 31 // 0 0 0 1 1 1 1 1
bitMaskAfter(4) = 15 // 0 0 0 0 1 1 1 1
bitMaskAfter(5) = 7 // 0 0 0 0 0 1 1 1
bitMaskAfter(6) = 3 // 0 0 0 0 0 0 1 1
bitMaskAfter(7) = 1 // 0 0 0 0 0 0 0 1
}

View file

@ -0,0 +1,67 @@
class MeanBleedInventory extends Inventory;
const dmtype_bleed=class'NiceDamTypeStalkerBleed';
var int maxBleedCount;
var private float fBleedPeriod;
var int bleedLevel;
var MeanZombieStalker stalker;
event PostBeginPlay()
{
super.PostBeginPlay();
// start the timer
SetTimer(fBleedPeriod, true);
}
event Timer()
{
local pawn locpawn;
local bool amAlive;
local int bleedDamage;
locpawn = Pawn(Owner);
amAlive = locpawn != none && locpawn.Health > 0;
bleedDamage = bleedLevel * 7;
// if pawn owner is dead or bleed count is done - destroy
if (!amAlive || maxBleedCount < 0 || bleedDamage < 1.0)
{
Destroy();
return;
}
maxBleedCount--;
if (stalker != none)
locpawn.TakeDamage(bleedDamage, stalker, locpawn.Location,
vect(0, 0, 0), dmtype_bleed);
else
locpawn.TakeDamage(bleedDamage, locpawn, locpawn.Location,
vect(0, 0, 0), dmtype_bleed);
if (locpawn.isA('KFPawn'))
{
KFPawn(locpawn).HealthToGive -= 2 * bleedLevel;
}
}
// cleanup
function Destroyed()
{
if (stalker != none)
stalker = none;
super.Destroyed();
}
defaultproperties
{
maxBleedCount=7
fBleedPeriod=1.500000
}

View file

@ -0,0 +1,60 @@
class MeanHuskFireProjectile extends NiceHuskFireProjectile;
simulated singular function Touch(Actor Other){
local vector HitLocation, HitNormal;
//Don't touch bulletwhip attachment. Taken from HuskFireProjectile
if ( Other == none || KFBulletWhipAttachment(Other) != none )
return;
if ( Other.bProjTarget || Other.bBlockActors ) {
LastTouched = Other;
if ( Velocity == vect(0,0,0) || Other.IsA('Mover') ) {
ProcessTouch(Other,Location);
LastTouched = none;
return;
}
if ( Other.TraceThisActor(HitLocation, HitNormal, Location, Location - 2*Velocity, GetCollisionExtent()) )
HitLocation = Location;
ProcessTouch(Other, HitLocation);
LastTouched = none;
if ( (Role < ROLE_Authority) && (Other.Role == ROLE_Authority) && (Pawn(Other) != none) )
ClientSideTouch(Other, HitLocation);
}
}
// Don't hit Zed extra collision cylinders
simulated function ProcessTouch(Actor Other, Vector HitLocation) {
// Don't let it hit this player, or blow up on another player
if (Other == none || Other == Instigator || Other.Base == Instigator)
return;
// Don't collide with bullet whip attachments
if (KFBulletWhipAttachment(Other) != none) {
return;
}
// Use the instigator's location if it exists. This fixes issues with
// the original location of the projectile being really far away from
// the real Origloc due to it taking a couple of milliseconds to
// replicate the location to the client and the first replicated location has
// already moved quite a bit.
if (Instigator != none) {
OrigLoc = Instigator.Location;
}
if (!bDud && ((VSizeSquared(Location - OrigLoc) < ArmDistSquared) || OrigLoc == vect(0,0,0))) {
if( Role == ROLE_Authority ) {
AmbientSound=none;
PlaySound(Sound'ProjectileSounds.PTRD_deflect04',,2.0);
Other.TakeDamage( ImpactDamage, Instigator, HitLocation, Normal(Velocity), ImpactDamageType );
}
bDud = true;
Velocity = vect(0,0,0);
LifeSpan=1.0;
SetPhysics(PHYS_Falling);
}
if (!bDud) {
Explode(HitLocation,Normal(HitLocation-Other.Location));
}
}
defaultproperties
{
additionalDamagePart=0.250000
}

View file

@ -0,0 +1,24 @@
class MeanPoisonInventory extends Inventory;
var float poisonStartTime, maxSpeedPenaltyTime, poisonSpeedDown;
simulated function Tick(float DeltaTime) {
if(Level.TimeSeconds - poisonStartTime > maxSpeedPenaltyTime)
Destroy();
}
simulated function float GetMovementModifierFor(Pawn InPawn){
local float actualSpeedDown;
local class<NiceVeterancyTypes> niceVet;
niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(InPawn.PlayerReplicationInfo);
if(niceVet != none){
actualSpeedDown = 1.0 - (1.0 - poisonSpeedDown) * niceVet.static.SlowingModifier(KFPlayerReplicationInfo(InPawn.PlayerReplicationInfo));
actualSpeedDown = FMax(0.0, FMin(1.0, actualSpeedDown));
return actualSpeedDown;
}
// If something went wrong - ignore slowdown altogether
return 1.0;
}
defaultproperties
{
maxSpeedPenaltyTime=5.000000
poisonSpeedDown=0.800000
}

View file

@ -0,0 +1,4 @@
// no use atm
class MeanReplicationInfo extends ReplicationInfo;
defaultproperties{}

View file

@ -0,0 +1,91 @@
class MeanVoting extends ScrnVotingOptions;
var NicePack Mut;
function int GetGroupVoteIndex(PlayerController Sender, string Group, string Key, out string Value, out string VoteInfo)
{
local int ZedNumber;
local int BoolValue;
local bool bEnable;
ZedNumber = Mut.ZedNumber(Key);
BoolValue = TryStrToBool(Value);
if(BoolValue == -1)
return VOTE_ILLEGAL;
bEnable = (BoolValue == 1);
if(Key ~= "ALL")
return 0;
if (ZedNumber == -1)
return VOTE_UNKNOWN;
if(bEnable == Mut.ZedDatabase[ZedNumber].bNeedsReplacement)
return VOTE_NOEFECT;
else
return ZedNumber + 1;
return VOTE_UNKNOWN;
}
function ApplyVoteValue(int VoteIndex, string VoteValue)
{
local int i;
local int BoolValue;
local bool bEnable;
local bool bAffectsAll;
bAffectsAll = false;
if(VoteIndex == 0)
bAffectsAll = true;
else
VoteIndex --;
BoolValue = TryStrToBool(VoteValue);
if ( BoolValue == -1 )
return;
bEnable = (BoolValue == 1);
if(!bAffectsAll)
Mut.ZedDatabase[VoteIndex].bNeedsReplacement = bEnable;
else{
for(i = 0; i <= Mut.lastStandardZed;i ++)
Mut.ZedDatabase[i].bNeedsReplacement = bEnable;
}
if(Mut.ZedDatabase[VoteIndex].ZedName ~= "CLOT" || bAffectsAll)
Mut.bReplaceClot = bEnable;
if(Mut.ZedDatabase[VoteIndex].ZedName ~= "CRAWLER" || bAffectsAll)
Mut.bReplaceCrawler = bEnable;
if(Mut.ZedDatabase[VoteIndex].ZedName ~= "STALKER" || bAffectsAll)
Mut.bReplaceStalker = bEnable;
if(Mut.ZedDatabase[VoteIndex].ZedName ~= "GOREFAST" || bAffectsAll)
Mut.bReplaceGorefast = bEnable;
if(Mut.ZedDatabase[VoteIndex].ZedName ~= "BLOAT" || bAffectsAll)
Mut.bReplaceBloat = bEnable;
if(Mut.ZedDatabase[VoteIndex].ZedName ~= "SIREN" || bAffectsAll)
Mut.bReplaceSiren = bEnable;
if(Mut.ZedDatabase[VoteIndex].ZedName ~= "HUSK" || bAffectsAll)
Mut.bReplaceHusk = bEnable;
if(Mut.ZedDatabase[VoteIndex].ZedName ~= "SCRAKE" || bAffectsAll)
Mut.bReplaceScrake = bEnable;
if(Mut.ZedDatabase[VoteIndex].ZedName ~= "FLESHPOUND" || bAffectsAll)
Mut.bReplaceFleshpound = bEnable;
Mut.SaveConfig();
VotingHandler.BroadcastMessage(strRestartRequired);
}
function SendGroupHelp(PlayerController Sender, string Group)
{
local string s;
local int i;
local int ln;
ln = 1;
s $= "ALL";
for ( i=0; i <= Mut.lastStandardZed; ++i ) {
if ( Mut.ZedDatabase[i].bNeedsReplacement )
s @= "%g";
else
s @= "%r";
s $= Caps(Mut.ZedDatabase[i].ZedName); if ( len(s) > 80 ) {
// move to new line
GroupInfo[ln++] = VotingHandler.ParseHelpLine(default.GroupInfo[1] @ s);
s = "";
} }
GroupInfo[ln] = VotingHandler.ParseHelpLine(default.GroupInfo[1] @ s);
super.SendGroupHelp(Sender, Group);
}
defaultproperties
{
DefaultGroup="MEAN"
HelpInfo(0)="%pMEAN %y<zed_name> %gON%w|%rOFF %w Add|Remove mean zeds from the game. Type %bMVOTE MEAN HELP %w for more info."
GroupInfo(0)="%MEAN %y<zed_name> %gON%w|%rOFF %w Add or remove mean zeds from the game."
GroupInfo(1)="%wAvaliable mean zeds:"
}

View file

@ -0,0 +1,88 @@
class MeanZombieBloat extends NiceZombieBloat;
#exec OBJ LOAD FILE=MeanZedSkins.utx
/**
* bAmIBarfing true if the bloat is in the barf animation
*/
var bool bAmIBarfing;
/**
* bileCoolDownTimer timer that counts to when the bloat will spawn another set of pile pellets
* bileCoolDownMax max time in between pellet spawns
*/
var float bileCoolDownTimer,bileCoolDownMax;
/**
* Spawn extra sets of bile pellets here once the bile cool down timer
* has reached the max limit
*/
simulated function Tick(float DeltaTime) {
Super.Tick(DeltaTime);
if(!bDecapitated && bAmIBarfing) {
bileCoolDownTimer+= DeltaTime;
if(bileCoolDownTimer >= bileCoolDownMax) {
SpawnTwoShots();
bileCoolDownTimer= 0.0;
}
}
}
function Touch(Actor Other)
{
if (Other == none)
return;
super.Touch(Other);
if (Other.IsA('ShotgunBullet'))
{
ShotgunBullet(Other).Damage = 0;
}
}
function RangedAttack(Actor A) {
local int LastFireTime;
if ( bShotAnim )
return;
if ( Physics == PHYS_Swimming ) {
SetAnimAction('Claw');
bShotAnim = true;
LastFireTime = Level.TimeSeconds;
}
else if ( VSize(A.Location - Location) < MeleeRange + CollisionRadius + A.CollisionRadius ) {
bShotAnim = true;
LastFireTime = Level.TimeSeconds;
SetAnimAction('Claw');
//PlaySound(sound'Claw2s', SLOT_Interact); KFTODO: Replace this
Controller.bPreparingMove = true;
Acceleration = vect(0,0,0);
}
else if ( (KFDoorMover(A) != none || VSize(A.Location-Location) <= 250) && !bDecapitated ) {
bShotAnim = true;
SetAnimAction('ZombieBarfMoving');
RunAttackTimeout = GetAnimDuration('ZombieBarf', 1.0);
bMovingPukeAttack=true;
// Randomly send out a message about Bloat Vomit burning(3% chance)
if ( FRand() < 0.03 && KFHumanPawn(A) != none && PlayerController(KFHumanPawn(A).Controller) != none ) {
PlayerController(KFHumanPawn(A).Controller).Speech('AUTO', 7, "");
}
}
}
//ZombieBarf animation triggers this
function SpawnTwoShots() {
super.SpawnTwoShots();
bAmIBarfing= true;
}
simulated function AnimEnd(int Channel) {
local name Sequence;
local float Frame, Rate;
GetAnimParams( ExpectingChannel, Sequence, Frame, Rate );
super.AnimEnd(Channel);
if(Sequence == 'ZombieBarf')
bAmIBarfing= false;
}
defaultproperties
{
bileCoolDownMax=0.750000
HeadHealth=125.000000
MenuName="Mean Bloat"
Skins(0)=Combiner'MeanZedSkins.bloat_cmb'
}

View file

@ -0,0 +1,19 @@
class MeanZombieClot extends NiceZombieClot;
#exec OBJ LOAD FILE=MeanZedSkins.utx
function int ModBodyDamage(out int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class<NiceWeaponDamageType> damageType, float headshotLevel, KFPlayerReplicationInfo KFPRI, optional float lockonTime){
local bool bDecreaseDamage;
// Decrease damage if needed
bDecreaseDamage = false;
if(damageType != none)
bDecreaseDamage = (headshotLevel <= 0.0) && damageType.default.bCheckForHeadShots;
if(damageType != none && damageType.default.heatPart > 0)
bDecreaseDamage = false;
if(bDecreaseDamage && HeadHealth > 0)
Damage *= 0.5;
return super.ModBodyDamage(Damage, instigatedBy, hitlocation, momentum, damageType, headshotLevel, KFPRI, lockonTime);
}
defaultproperties
{
MenuName="Mean Clot"
Skins(0)=Combiner'MeanZedSkins.clot_cmb'
}

View file

@ -0,0 +1,55 @@
class MeanZombieCrawler extends NiceZombieCrawler;
#exec OBJ LOAD FILE=MeanZedSkins.utx
simulated function PostBeginPlay() {
super.PostBeginPlay();
PounceSpeed = Rand(221)+330;
MeleeRange = Rand(41)+50;
}
/**
* Copied from ZombieCrawler.Bump() but changed damage type
* to be the new poison damage type
*/
event Bump(actor Other) {
if(bPouncing && KFHumanPawn(Other) != none)
Poison(KFHumanPawn(Other));
super.Bump(Other);
}
function bool MeleeDamageTarget(int hitdamage, vector pushdir) {
local bool result;
result= super.MeleeDamageTarget(hitdamage, pushdir);
if(result && KFHumanPawn(Controller.Target) != none)
Poison(KFHumanPawn(Controller.Target));
return result;
}
function Poison(KFHumanPawn poisonedPawn)
{
local Inventory I;
local bool bFoundPoison;
if (poisonedPawn.Inventory != none)
{
for (I = poisonedPawn.Inventory; I != none; I = I.Inventory)
{
if (MeanPoisonInventory(I) != none)
{
bFoundPoison = true;
MeanPoisonInventory(I).poisonStartTime = Level.TimeSeconds;
}
}
}
if (!bFoundPoison)
{
I = Controller.Spawn(class<Inventory>(DynamicLoadObject(string(class'MeanPoisonInventory'), class'Class')));
MeanPoisonInventory(I).poisonStartTime = Level.TimeSeconds;
I.GiveTo(poisonedPawn);
}
}
defaultproperties
{
GroundSpeed=190.000000
WaterSpeed=175.000000
MenuName="Mean Crawler"
Skins(0)=Combiner'MeanZedSkins.crawler_cmb'
}

View file

@ -0,0 +1,101 @@
class MeanZombieFleshPound extends NiceZombieFleshPound;
#exec OBJ LOAD FILE=MeanZedSkins.utx
state RageCharging
{
Ignores StartChargingFP;
function bool CanGetOutOfWay()
{
return false;
}
// Don't override speed in this state
function bool CanSpeedAdjust()
{
return false;
}
function BeginState()
{
bChargingPlayer = true;
if( Level.NetMode!=NM_DedicatedServer )
ClientChargingAnims();
RageEndTime = (Level.TimeSeconds + 15) + (FRand() * 18);
NetUpdateTime = Level.TimeSeconds - 1;
}
function EndState()
{
bChargingPlayer = false;
bFrustrated = false;
if(Controller != none)
NiceZombieFleshPoundController(Controller).RageFrustrationTimer = 0;
if( Level.NetMode!=NM_DedicatedServer )
ClientChargingAnims();
NetUpdateTime = Level.TimeSeconds - 1;
}
simulated function UpdateGroundSpeed() {
super(NiceMonster).UpdateGroundSpeed();
if (!bShotAnim) {
groundSpeed *= 2.3;
}
}
function Tick( float Delta )
{
// Keep the flesh pound moving toward its target when attacking
if( Role == ROLE_Authority && bShotAnim)
{
if( LookTarget!=none )
{
Acceleration = AccelRate * Normal(LookTarget.Location - Location);
}
}
global.Tick(Delta);
}
function Bump( Actor Other )
{
local float RageBumpDamage;
local KFMonster KFMonst;
KFMonst = KFMonster(Other);
// Hurt/Kill enemies that we run into while raging
if( !bShotAnim && KFMonst!=none && NiceZombieFleshPound(Other)==none && Pawn(Other).Health>0 )
{
// Random chance of doing obliteration damage
if( FRand() < 0.4 )
{
RageBumpDamage = 501;
}
else
{
RageBumpDamage = 450;
}
RageBumpDamage *= KFMonst.PoundRageBumpDamScale;
Other.TakeDamage(RageBumpDamage, self, Other.Location, Velocity * Other.Mass, class'NiceDamTypePoundCrushed');
}
else Global.Bump(Other);
}
// If fleshie hits his target on a charge, then he should settle down for abit.
function bool MeleeDamageTarget(int hitdamage, vector pushdir)
{
local bool RetVal,bWasEnemy;
bWasEnemy = (Controller.Target==Controller.Enemy);
RetVal = Super(NiceMonster).MeleeDamageTarget(hitdamage*1.75, pushdir*3);
// Only stop if you've successfully killed your target
if(Pawn(Controller.Target) == none)
return RetVal;
if( KFPawn(Controller.Target) != none && Pawn(Controller.Target).Health <= 0 && RetVal && bWasEnemy ){
GoToState('');
}
return RetVal;
}
}
defaultproperties
{
MenuName="Mean FleshPound"
Skins(0)=Combiner'MeanZedSkins.fleshpound_cmb'
}

View file

@ -0,0 +1,40 @@
class MeanZombieGorefast extends NiceZombieGorefast;
#exec OBJ LOAD FILE=MeanZedSkins.utx
var float minRageDist;
function bool IsStunPossible(){
return false;
}
function RangedAttack(Actor A) {
Super(NiceMonster).RangedAttack(A);
if(!bShotAnim && !bDecapitated && VSize(A.Location-Location) <= minRageDist)
GoToState('RunningState');
}
state RunningState {
function RangedAttack(Actor A){
if(bShotAnim || Physics == PHYS_Swimming)
return;
else if(CanAttack(A)){
bShotAnim = true;
//Always do the charging melee attack
SetAnimAction('ClawAndMove');
RunAttackTimeout = GetAnimDuration('GoreAttack1', 1.0);
return;
}
}
Begin:
GoTo('CheckCharge');
CheckCharge:
if(Controller != none && Controller.Target != none && VSize(Controller.Target.Location - Location) < minRageDist){
Sleep(0.5 + FRand() * 0.5);
GoTo('CheckCharge');
}
else
GoToState('');
}
defaultproperties
{
minRageDist=1400.000000
MenuName="Mean Gorefast"
Skins(0)=Combiner'MeanZedSkins.gorefast_cmb'
}

View file

@ -0,0 +1,57 @@
class MeanZombieHusk extends NiceZombieHusk;
#exec OBJ LOAD FILE=NicePackT.utx
var int consecutiveShots, totalShots, maxNormalShots;
function DoStun(optional Pawn instigatedBy, optional Vector hitLocation, optional Vector momentum, optional class<NiceWeaponDamageType> damageType, optional float headshotLevel, optional KFPlayerReplicationInfo KFPRI){
super.DoStun(instigatedBy, hitLocation, momentum, damageType, headshotLevel, KFPRI);
totalShots = maxNormalShots;
}
function RangedAttack(Actor A) {
local int LastFireTime;
if ( bShotAnim )
return;
if ( Physics == PHYS_Swimming ) {
SetAnimAction('Claw');
bShotAnim = true;
LastFireTime = Level.TimeSeconds;
}
else if ( VSize(A.Location - Location) < MeleeRange + CollisionRadius + A.CollisionRadius ) {
bShotAnim = true;
LastFireTime = Level.TimeSeconds;
SetAnimAction('Claw');
//PlaySound(sound'Claw2s', SLOT_Interact); KFTODO: Replace this
Controller.bPreparingMove = true;
Acceleration = vect(0,0,0);
}
else if((KFDoorMover(A) != none ||
(!Region.Zone.bDistanceFog && VSize(A.Location-Location) <= 65535) ||
(Region.Zone.bDistanceFog && VSizeSquared(A.Location-Location) < (Square(Region.Zone.DistanceFogEnd) * 0.8))) // Make him come out of the fog a bit
&& !bDecapitated && Physics != PHYS_Falling) {
bShotAnim = true;
SetAnimAction('ShootBurns');
Controller.bPreparingMove = true;
Acceleration = vect(0,0,0);
//Increment the number of consecutive shtos taken and apply the cool down if needed
totalShots ++;
consecutiveShots ++;
if(consecutiveShots < 3 && totalShots > maxNormalShots && VSize(a.location - location) <= 900)
NextFireProjectileTime = Level.TimeSeconds;
else{
NextFireProjectileTime = Level.TimeSeconds + ProjectileFireInterval + (FRand() * 2.0);
consecutiveShots = 0;
}
}
}
defaultproperties
{
maxNormalShots=3
AmmunitionClass=class'MeanZombieHuskAmmo'
remainingStuns=1
MenuName="Mean Husk"
ControllerClass=class'MeanZombieHuskController'
Skins(0)=Texture'NicePackT.MonsterMeanHusk.burns_tatters'
Skins(1)=Shader'NicePackT.MonsterMeanHusk.burns_shdr'
}

View file

@ -0,0 +1,7 @@
class MeanZombieHuskAmmo extends NiceZombieHuskAmmo;
defaultproperties
{
ProjectileClass=class'MeanHuskFireProjectile'
}

View file

@ -0,0 +1,193 @@
class MeanZombieHuskController extends NiceZombieHuskController;
var float aimAtFeetZDelta;
function bool DefendMelee(float Dist) {
return (Dist < 1000);
}
function rotator AdjustAim(FireProperties FiredAmmunition, vector projStart, int aimerror) {
local rotator FireRotation, TargetLook;
local float FireDist, TargetDist, ProjSpeed;
local actor HitActor;
local vector FireSpot, FireDir, TargetVel, HitLocation, HitNormal;
local int realYaw;
local bool bDefendCloseRange, bClean, bLeadTargetNow;
local bool bWantsToAimAtFeet;
if ( FiredAmmunition.ProjectileClass != none )
projspeed = FiredAmmunition.ProjectileClass.default.speed;
// make sure bot has a valid target
if ( Target == none ) {
Target = Enemy;
if ( Target == none )
return Rotation;
}
FireSpot = Target.Location;
TargetDist = VSize(Target.Location - Pawn.Location);
// perfect aim at stationary objects
if ( Pawn(Target) == none ) {
if ( !FiredAmmunition.bTossed )
return rotator(Target.Location - projstart);
else {
FireDir = AdjustToss(projspeed,ProjStart,Target.Location,true);
SetRotation(Rotator(FireDir));
return Rotation;
}
}
bLeadTargetNow = FiredAmmunition.bLeadTarget && bLeadTarget;
bDefendCloseRange = ( (Target == Enemy) && DefendMelee(TargetDist) );
aimerror = AdjustAimError(aimerror,TargetDist,bDefendCloseRange,FiredAmmunition.bInstantHit, bLeadTargetNow);
// lead target with non instant hit projectiles
if ( bLeadTargetNow ) {
TargetVel = Target.Velocity;
// hack guess at projecting falling velocity of target
if ( Target.Physics == PHYS_Falling) {
if ( Target.PhysicsVolume.Gravity.Z <= Target.PhysicsVolume.Default.Gravity.Z ) {
TargetVel.Z = FMin(TargetVel.Z + FMax(-400, Target.PhysicsVolume.Gravity.Z * FMin(1,TargetDist/projSpeed)),0);
} else {
TargetVel.Z = FMin(0, TargetVel.Z);
}
}
// more or less lead target (with some random variation)
FireSpot += FMin(1, 0.7 + 0.6 * FRand()) * TargetVel * TargetDist/projSpeed;
FireSpot.Z = FMin(Target.Location.Z, FireSpot.Z);
/**
* If the target is within 1000uu, offset the Z coordinate of the
* FireSpot vector with aimAtFeetZDelta. Otherwise, the husk will
* aim at behind the target, not at his feet.
*/
if (aimAtFeetZDelta != 0.0 && Target.Physics == PHYS_Falling && bDefendCloseRange) {
FireSpot.Z= Pawn.Location.Z + aimAtFeetZDelta;
}
if ( (Target.Physics != PHYS_Falling) && (FRand() < 0.55) && (VSize(FireSpot - ProjStart) > 1000) ) {
// don't always lead far away targets, especially if they are moving sideways with respect to the bot
TargetLook = Target.Rotation;
if ( Target.Physics == PHYS_Walking )
TargetLook.Pitch = 0;
bClean = ( ((Vector(TargetLook) Dot Normal(Target.Velocity)) >= 0.71) && FastTrace(FireSpot, ProjStart) );
}
else // make sure that bot isn't leading into a wall
bClean = FastTrace(FireSpot, ProjStart);
if ( !bClean) {
// reduce amount of leading
if ( FRand() < 0.3 )
FireSpot = Target.Location;
else
FireSpot = 0.5 * (FireSpot + Target.Location);
}
}
bClean = false; //so will fail first check unless shooting at feet
// Randomly determine if we should try and splash damage with the fire projectile
if( FiredAmmunition.bTrySplash ) {
if( Skill < 2.0 ) {
if(FRand() > 0.85) {
bWantsToAimAtFeet = true;
}
}
else if( Skill < 3.0 ) {
if(FRand() > 0.5) {
bWantsToAimAtFeet = true;
}
}
else if( Skill >= 3.0 ) {
if(FRand() > 0.25) {
bWantsToAimAtFeet = true;
}
}
}
if ( FiredAmmunition.bTrySplash && (Pawn(Target) != none) && (((Target.Physics == PHYS_Falling)
&& (Pawn.Location.Z + 80 >= Target.Location.Z)) || ((Pawn.Location.Z + 19 >= Target.Location.Z)
&& (bDefendCloseRange || bWantsToAimAtFeet))) ) {
HitActor = Trace(HitLocation, HitNormal, FireSpot - vect(0,0,1) * (Target.CollisionHeight + 10), FireSpot, false);
bClean = (HitActor == none);
//So if we're too close, and not jumping, bClean is false
//same distance but jumping, bClean is true
if ( !bClean ) {
FireSpot = HitLocation + vect(0,0,3);
bClean = FastTrace(FireSpot, ProjStart);
}
else
bClean = ( (Target.Physics == PHYS_Falling) && FastTrace(FireSpot, ProjStart) );
/**
* Update the aimAtFeetZDelta variable with the appropriate offset
* once the Husk decides to aim at the target's feet. Update the
* default property so all Super Husks can access it
*/
if (bClean && TargetDist > 625.0) {
aimAtFeetZDelta= FireSpot.Z - Pawn.Location.Z;
}
}
if ( !bClean ) {
//try middle
FireSpot.Z = Target.Location.Z;
bClean = FastTrace(FireSpot, ProjStart);
}
if ( FiredAmmunition.bTossed && !bClean && bEnemyInfoValid ) {
FireSpot = LastSeenPos;
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
if ( HitActor != none ) {
bCanFire = false;
FireSpot += 2 * Target.CollisionHeight * HitNormal;
}
bClean = true;
}
if( !bClean ) {
// try head
FireSpot.Z = Target.Location.Z + 0.9 * Target.CollisionHeight;
bClean = FastTrace(FireSpot, ProjStart);
}
if ( !bClean && (Target == Enemy) && bEnemyInfoValid ) {
FireSpot = LastSeenPos;
if ( Pawn.Location.Z >= LastSeenPos.Z )
FireSpot.Z -= 0.4 * Enemy.CollisionHeight;
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
if ( HitActor != none ) {
FireSpot = LastSeenPos + 2 * Enemy.CollisionHeight * HitNormal;
if ( Monster(Pawn).SplashDamage() && (Skill >= 4) ) {
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
if ( HitActor != none )
FireSpot += 2 * Enemy.CollisionHeight * HitNormal;
}
bCanFire = false;
}
}
// adjust for toss distance
if ( FiredAmmunition.bTossed ) {
FireDir = AdjustToss(projspeed,ProjStart,FireSpot,true);
}
else {
FireDir = FireSpot - ProjStart;
}
FireRotation = Rotator(FireDir);
realYaw = FireRotation.Yaw;
InstantWarnTarget(Target,FiredAmmunition,vector(FireRotation));
FireRotation.Yaw = SetFireYaw(FireRotation.Yaw + aimerror);
FireDir = vector(FireRotation);
// avoid shooting into wall
FireDist = FMin(VSize(FireSpot-ProjStart), 400);
FireSpot = ProjStart + FireDist * FireDir;
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
if ( HitActor != none ) {
if ( HitNormal.Z < 0.7 ) {
FireRotation.Yaw = SetFireYaw(realYaw - aimerror);
FireDir = vector(FireRotation);
FireSpot = ProjStart + FireDist * FireDir;
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
}
if ( HitActor != none ) {
FireSpot += HitNormal * 2 * Target.CollisionHeight;
if ( Skill >= 4 ) {
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
if ( HitActor != none )
FireSpot += Target.CollisionHeight * HitNormal;
}
FireDir = Normal(FireSpot - ProjStart);
FireRotation = rotator(FireDir);
}
}
//Make it so the Husk always shoots the ground it the target is close
SetRotation(FireRotation);
return FireRotation;
}
defaultproperties
{
}

View file

@ -0,0 +1,47 @@
class MeanZombieScrake extends NiceZombieScrake;
#exec OBJ LOAD FILE=MeanZedSkins.utx
function RangedAttack(Actor A){
Super.RangedAttack(A);
if(!bShotAnim){
if(bConfusedState)
return;
if(float(Health) / HealthMax < 0.75 || lastStunTime >= 0.0){
MovementAnims[0] = 'ChargeF';
GoToState('RunningState');
}
}
}
simulated event SetAnimAction(name NewAction){
if(Role < Role_AUTHORITY && NewAction == 'ChargeF')
PlayAnim('ChargeF', GetOriginalGroundSpeed() * 3.5);
else
super.SetAnimAction(NewAction);
}
simulated function Unstun(){
bCharging = true;
MovementAnims[0] = 'ChargeF';
GoToState('RunningState');
super.Unstun();
}
function TakeDamageClient(int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<NiceWeaponDamageType> damageType, float headshotLevel, float lockonTime){
Super.TakeDamageClient(Damage, instigatedBy, hitLocation, momentum, damageType, headshotLevel, lockonTime);
if(bIsStunned && Health > 0 && (headshotLevel <= 0.0) && Level.TimeSeconds > LastStunTime + 0.1)
Unstun();
}
function TakeFireDamage(int Damage, Pawn Instigator){
Super.TakeFireDamage(Damage, Instigator);
if(bIsStunned && Health > 0 && Damage > 150 && Level.TimeSeconds > LastStunTime + 0.1)
Unstun();
}
function bool CheckMiniFlinch(int flinchScore, Pawn instigatedBy, Vector hitLocation, Vector momentum, class<NiceWeaponDamageType> damageType, float headshotLevel, KFPlayerReplicationInfo KFPRI){
if((ClassIsChildOf(damageType, class 'DamTypeMelee') || ClassIsChildOf(damageType, class 'NiceDamageTypeVetBerserker'))
&& !KFPRI.ClientVeteranSkill.Static.CanMeleeStun() && (headshotLevel <= 0.0) && flinchScore < 250)
return false;
return super.CheckMiniFlinch(flinchScore, instigatedBy, hitLocation, momentum, damageType, headshotLevel, KFPRI);
}
defaultproperties
{
MenuName="Mean Scrake"
Skins(0)=Shader'MeanZedSkins.scrake_FB'
Skins(1)=TexPanner'MeanZedSkins.scrake_saw_panner'
}

View file

@ -0,0 +1,10 @@
class MeanZombieSiren extends NiceZombieSiren;
#exec OBJ LOAD FILE=MeanZedSkins.utx
defaultproperties
{
ScreamRadius=800
ScreamForce=-200000
MenuName="Mean Siren"
Skins(0)=FinalBlend'MeanZedSkins.siren_hair_fb'
Skins(1)=Combiner'MeanZedSkins.siren_cmb'
}

View file

@ -0,0 +1,275 @@
class MeanZombieStalker extends NiceZombieStalker;
#exec OBJ LOAD FILE=MeanZedSkins.utx
simulated function Tick(float DeltaTime)
{
Super(NiceMonster).Tick(DeltaTime);
if(Role == ROLE_Authority && bShotAnim && !bWaitForAnim){
if( LookTarget!=none ) {
Acceleration = AccelRate * Normal(LookTarget.Location - Location);
}
}
if(Level.NetMode == NM_DedicatedServer)
return; // Servers aren't interested in this info.
if(bZapped){
// Make sure we check if we need to be cloaked as soon as the zap wears off
NextCheckTime = Level.TimeSeconds;
}
else if( Level.TimeSeconds > NextCheckTime && Health > 0 )
{
NextCheckTime = Level.TimeSeconds + 0.5;
if(LocalKFHumanPawn != none && LocalKFHumanPawn.Health > 0 && LocalKFHumanPawn.ShowStalkers() &&
VSizeSquared(Location - LocalKFHumanPawn.Location) < LocalKFHumanPawn.GetStalkerViewDistanceMulti() * 640000.0) // 640000 = 800 Units
bSpotted = True;
else
bSpotted = false;
if(!bSpotted && !bCloaked && Skins[0] != Combiner'MeanZedSkins.stalker_cmb')
UncloakStalker();
else if (Level.TimeSeconds - LastUncloakTime > 1.2){
// if we're uberbrite, turn down the light
if( bSpotted && Skins[0] != Finalblend'KFX.StalkerGlow' ){
bUnlit = false;
CloakStalker();
}
else if(Skins[0] != Shader'MeanZedSkins.stalker_invisible')
CloakStalker();
}
}
}
simulated function CloakStalker()
{
// No cloaking if zapped
if( bZapped )
{
return;
}
if ( bSpotted )
{
if( Level.NetMode == NM_DedicatedServer )
return;
Skins[0] = Finalblend'KFX.StalkerGlow';
Skins[1] = Finalblend'KFX.StalkerGlow';
bUnlit = true;
return;
}
if ( !bDecapitated ) // No head, no cloak, honey. updated : Being charred means no cloak either :D Not.
{
Visibility = 1;
bCloaked = true;
if( Level.NetMode == NM_DedicatedServer )
Return;
Skins[0] = Shader'MeanZedSkins.stalker_invisible';
Skins[1] = Shader'MeanZedSkins.stalker_invisible';
// Invisible - no shadow
if(PlayerShadow != none)
PlayerShadow.bShadowActive = false;
if(RealTimeShadow != none)
RealTimeShadow.Destroy();
// Remove/disallow projectors on invisible people
Projectors.Remove(0, Projectors.Length);
bAcceptsProjectors = false;
SetOverlayMaterial(Material'KFX.FBDecloakShader', 0.25, true);
}
}
simulated function UnCloakStalker()
{
if (bZapped)
{
return;
}
if (!bCrispified)
{
LastUncloakTime = Level.TimeSeconds;
Visibility = default.Visibility;
bCloaked = false;
bUnlit = false;
// 25% chance of our Enemy saying something about us being invisible
// added Controller check here
if (Level.NetMode!=NM_Client && !KFGameType(Level.Game).bDidStalkerInvisibleMessage && FRand()<0.25 && Controller != none && Controller.Enemy!=none &&
PlayerController(Controller.Enemy.Controller)!=none)
{
PlayerController(Controller.Enemy.Controller).Speech('AUTO', 17, "");
KFGameType(Level.Game).bDidStalkerInvisibleMessage = true;
}
if( Level.NetMode == NM_DedicatedServer )
Return;
if ( Skins[0] != Combiner'MeanZedSkins.stalker_cmb' )
{
Skins[1] = FinalBlend'MeanZedSkins.stalker_fb';
Skins[0] = Combiner'MeanZedSkins.stalker_cmb';
if (PlayerShadow != none)
PlayerShadow.bShadowActive = true;
bAcceptsProjectors = true;
SetOverlayMaterial(Material'KFX.FBDecloakShader', 0.25, true);
}
}
}
simulated function SetZappedBehavior()
{
super(NiceMonster).SetZappedBehavior();
bUnlit = false;
// Handle setting the zed to uncloaked so the zapped overlay works properly
if( Level.Netmode != NM_DedicatedServer )
{
Skins[1] = FinalBlend'MeanZedSkins.stalker_fb';
Skins[0] = Combiner'MeanZedSkins.stalker_cmb';
if (PlayerShadow != none)
PlayerShadow.bShadowActive = true;
bAcceptsProjectors = true;
SetOverlayMaterial(Material'KFZED_FX_T.Energy.ZED_overlay_Hit_Shdr', 999, true);
}
}
function RangedAttack(Actor A) {
if ( bShotAnim || Physics == PHYS_Swimming)
return;
else if ( CanAttack(A) ) {
bShotAnim = true;
SetAnimAction('ClawAndMove');
//PlaySound(sound'Claw2s', SLOT_none); KFTODO: Replace this
return;
}
}
// Copied from the Gorefast code
// Overridden to handle playing upper body only attacks when moving
simulated event SetAnimAction(name NewAction) {
if( NewAction=='' )
Return;
ExpectingChannel = AttackAndMoveDoAnimAction(NewAction);
bWaitForAnim= false;
if( Level.NetMode!=NM_Client ) {
AnimAction = NewAction;
bResetAnimAct = True;
ResetAnimActTime = Level.TimeSeconds+0.3;
}
}
// Copied from the Gorefast code, updated with the stalker attacks
// Handle playing the anim action on the upper body only if we're attacking and moving
simulated function int AttackAndMoveDoAnimAction( name AnimName ) {
local int meleeAnimIndex;
if( AnimName == 'ClawAndMove' ) {
meleeAnimIndex = Rand(3);
AnimName = meleeAnims[meleeAnimIndex];
}
if( AnimName=='StalkerSpinAttack' || AnimName=='StalkerAttack1' || AnimName=='JumpAttack') {
AnimBlendParams(1, 1.0, 0.0,, FireRootBone);
PlayAnim(AnimName,, 0.1, 1);
return 1;
}
return super.DoAnimAction( AnimName );
}
function bool MeleeDamageTarget(int hitdamage, vector pushdir)
{
local bool result;
local float effectStrenght;
local NiceHumanPawn targetPawn;
result = super(NiceMonster).MeleeDamageTarget(hitdamage, pushdir);
// if true means we checked ctlr and ctrl.target != none
if (result)
targetPawn = NiceHumanPawn(Controller.Target);
if (result && targetPawn != none)
{
if (targetPawn.ShieldStrength > 100)
return result;
else if (targetPawn.ShieldStrength <= 0)
effectStrenght = 1.0;
else
effectStrenght = (100 - targetPawn.ShieldStrength) * 0.01;
MakeBleed(targetPawn, effectStrenght);
}
return result;
}
final private function MakeBleed(NiceHumanPawn poorpawn, coerce int effectStrenght)
{
local Inventory I;
local MeanBleedInventory bleedinv;
local bool bFoundPoison;
if (poorpawn.Inventory != none)
{
for (I = poorpawn.Inventory; I != none; I = I.Inventory)
{
if (MeanBleedInventory(I) != none)
{
bleedinv = MeanBleedInventory(I);
bFoundPoison = true;
bleedinv.stalker = self;
bleedinv.bleedLevel = effectStrenght;
// reset bleed count
bleedinv.maxBleedCount = bleedinv.default.maxBleedCount;
}
}
}
if (!bFoundPoison)
{
I = Controller.Spawn(class<Inventory>(DynamicLoadObject(string(class'MeanBleedInventory'), class'Class')));
bleedinv = MeanBleedInventory(I);
bleedinv.stalker = self;
bleedinv.bleedLevel = effectStrenght;
bleedinv.GiveTo(poorpawn);
}
}
function RemoveHead()
{
Super(NiceMonster).RemoveHead();
if (!bCrispified)
{
Skins[1] = FinalBlend'MeanZedSkins.stalker_fb';
Skins[0] = Combiner'MeanZedSkins.stalker_cmb';
}
}
simulated function PlayDying(class<DamageType> DamageType, vector HitLoc)
{
Super(NiceMonster).PlayDying(DamageType,HitLoc);
if(bUnlit)
bUnlit=!bUnlit;
LocalKFHumanPawn = none;
if (!bCrispified)
{
Skins[1] = FinalBlend'MeanZedSkins.stalker_fb';
Skins[0] = Combiner'MeanZedSkins.stalker_cmb';
}
}
static simulated function PreCacheMaterials(LevelInfo myLevel)
{//should be derived and used.
myLevel.AddPrecacheMaterial(Combiner'MeanZedSkins.stalker_cmb');
myLevel.AddPrecacheMaterial(Combiner'MeanZedSkins.stalker_env_cmb');
myLevel.AddPrecacheMaterial(Texture'MeanZedSkins.stalker_diff');
myLevel.AddPrecacheMaterial(Texture'MeanZedSkins.stalker_spec');
myLevel.AddPrecacheMaterial(Material'MeanZedSkins.stalker_invisible');
myLevel.AddPrecacheMaterial(Combiner'MeanZedSkins.StalkerCloakOpacity_cmb');
myLevel.AddPrecacheMaterial(Material'MeanZedSkins.StalkerCloakEnv_rot');
myLevel.AddPrecacheMaterial(Material'MeanZedSkins.stalker_opacity_osc');
myLevel.AddPrecacheMaterial(Material'KFCharacters.StalkerSkin');
}
defaultproperties
{
MeleeDamage=6
MenuName="Mean Stalker"
Skins(0)=Shader'MeanZedSkins.stalker_invisible'
Skins(1)=Shader'MeanZedSkins.stalker_invisible'
}

View file

@ -0,0 +1,26 @@
class Nice9mm extends NiceSingle;
static function PreloadAssets(Inventory Inv, optional bool bSkipRefCount){
super.PreloadAssets(Inv, bSkipRefCount);
// A bit of a temporary hack.
// There's currently no nice way to call preload assets function for a grenade, so just always load nails' resources
//class'NiceNail'.static.PreloadAssets();
}
defaultproperties
{
DualClass=class'NiceDual9mm'
reloadPreEndFrame=0.117000
reloadEndFrame=0.617000
reloadChargeEndFrame=-1.000000
reloadMagStartFrame=0.167000
reloadChargeStartFrame=-1.000000
HudImage=Texture'KillingFloorHUD.WeaponSelect.single_9mm_unselected'
SelectedHudImage=Texture'KillingFloorHUD.WeaponSelect.single_9mm'
FireModeClass(0)=class'Nice9mmFire'
SelectSound=Sound'KF_9MMSnd.9mm_Select'
Description="A 9mm Pistol. What it lacks in stopping power, it compensates for with a quick refire."
PickupClass=class'Nice9mmPickup'
AttachmentClass=class'Nice9mmAttachment'
ItemName="Beretta"
Mesh=SkeletalMesh'KF_Weapons_Trip.9mm_Trip'
Skins(0)=Combiner'KF_Weapons_Trip_T.Pistols.Ninemm_cmb'
}

View file

@ -0,0 +1,13 @@
class Nice9mmAmmo extends NiceAmmo;
#EXEC OBJ LOAD FILE=InterfaceContent.utx
defaultproperties
{
WeaponPickupClass=class'Nice9mmPickup'
AmmoPickupAmount=30
MaxAmmo=240
InitialAmount=60
PickupClass=Class'KFMod.SingleAmmoPickup'
IconMaterial=Texture'KillingFloorHUD.Generic.HUD'
IconCoords=(X1=413,Y1=82,X2=457,Y2=125)
ItemName="9mm bullets"
}

View file

@ -0,0 +1,9 @@
class Nice9mmAmmoPickup extends NiceAmmoPickup;
defaultproperties
{
AmmoAmount=30
InventoryType=class'Nice9mmAmmo'
RespawnTime=0.000000
PickupMessage="Rounds (9mm)"
StaticMesh=StaticMesh'KillingFloorStatics.DualiesAmmo'
}

View file

@ -0,0 +1,5 @@
class Nice9mmAttachment extends NiceSingleAttachment;
defaultproperties
{
Mesh=SkeletalMesh'KF_Weapons3rd_Trip.Single9mm_3rd'
}

View file

@ -0,0 +1,12 @@
class Nice9mmFire extends NiceSingleFire;
defaultproperties
{
ProjectileSpeed=21300.000000
maxVerticalRecoilAngle=75
maxHorizontalRecoilAngle=35
StereoFireSound=SoundGroup'KF_9MMSnd.9mm_FireST'
DamageType=class'NiceDamType9mm'
FireSound=SoundGroup'KF_9MMSnd.9mm_Fire'
NoAmmoSound=Sound'KF_9MMSnd.9mm_DryFire'
AmmoClass=class'Nice9mmAmmo'
}

View file

@ -0,0 +1,10 @@
class Nice9mmPickup extends NiceSinglePickup;
defaultproperties
{
bBackupWeapon=True
cost=100
Description="A 9mm Pistol. What it lacks in stopping power, it compensates for with a quick refire."
ItemName="Beretta"
ItemShortName="Beretta"
InventoryType=class'Nice9mm'
}

View file

@ -0,0 +1,47 @@
class Nice9mmPlus extends NiceSingle;
simulated function AltFire(float F){
if(bIsDual)
super.AltFire(F);
else
ToggleLaser();
}
simulated function SecondDoToggle(){
ToggleLaser();
}
simulated function ToggleLaser(){
if(!Instigator.IsLocallyControlled())
return;
// Will redo this bit later, but so far it'll have to do
if(LaserType == 0)
LaserType = 1;
else
LaserType = 0;
ApplyLaserState();
}
defaultproperties
{
DualClass=class'NiceDual9mmPlus'
bUseFlashlightToToggle=True
reloadPreEndFrame=0.117000
reloadEndFrame=0.617000
reloadChargeEndFrame=-1.000000
reloadMagStartFrame=0.167000
reloadChargeStartFrame=-1.000000
bTorchEnabled=True
SleeveNum=0
TraderInfoTexture=Texture'NicePackT.NinePP.HUD_Single_Trader'
MeshRef="NicePackA.NinePP.Single_1P"
SkinRefs(1)="ScrnWeaponPack_T.MedicPistol.Slide_cmb"
SkinRefs(2)="ScrnWeaponPack_T.MedicPistol.frame_cmb"
SkinRefs(3)="ScrnWeaponPack_T.MedicPistol.Slide_cmb"
SkinRefs(4)="ScrnWeaponPack_T.MedicPistol.Slide_cmb"
SelectSoundRef="KF_9MMSnd.9mm_Select"
HudImageRef="NicePackT.NinePP.HUD_Single_UnSelected"
SelectedHudImageRef="NicePackT.NinePP.HUD_Single_Selected"
FireModeClass(0)=class'Nice9mmPlusFire'
Description="A 9mm handgun, with a functional laser sight and flashlight. The barrel has been replaced with one that can chamber hotter ammunition loads, meaning faster bullets, meaning more damage!"
GroupOffset=3
PickupClass=class'Nice9mmPlusPickup'
AttachmentClass=class'Nice9mmPlusAttachment'
ItemName="Beretta"
}

View file

@ -0,0 +1,12 @@
class Nice9mmPlusAmmo extends NiceAmmo;
defaultproperties
{
WeaponPickupClass=class'Nice9mmPlusPickup'
AmmoPickupAmount=15
MaxAmmo=150
InitialAmount=60
PickupClass=class'Nice9mmPlusAmmoPickup'
IconMaterial=Texture'KillingFloorHUD.Generic.HUD'
IconCoords=(X1=413,Y1=82,X2=457,Y2=125)
ItemName="9mm +P+ bullets"
}

View file

@ -0,0 +1,9 @@
class Nice9mmPlusAmmoPickup extends NiceAmmoPickup;
defaultproperties
{
AmmoAmount=15
InventoryType=class'Nice9mmPlusAmmo'
RespawnTime=0.000000
PickupMessage="Rounds (9mm +P+)"
StaticMesh=StaticMesh'KillingFloorStatics.DualiesAmmo'
}

View file

@ -0,0 +1,5 @@
class Nice9mmPlusAttachment extends NiceSingleAttachment;
defaultproperties
{
MeshRef="NicePackA.NinePP.Single_3P"
}

View file

@ -0,0 +1,13 @@
class Nice9mmPlusFire extends NiceSingleFire;
defaultproperties
{
ProjectileSpeed=21300.000000
maxVerticalRecoilAngle=0
maxHorizontalRecoilAngle=0
FireSoundRef="NicePackSnd.NinePP.Fire1"
StereoFireSoundRef="NicePackSnd.NinePP.Fire1"
NoAmmoSoundRef="KF_9MMSnd.9mm_DryFire"
DamageType=class'NiceDamType9mmPlus'
FireRate=0.250000
AmmoClass=class'Nice9mmPlusAmmo'
}

View file

@ -0,0 +1,15 @@
class Nice9mmPlusPickup extends NiceSinglePickup;
defaultproperties
{
bBackupWeapon=True
cost=100
AmmoCost=5
BuyClipSize=15
Description="A 9mm handgun, with a functional laser sight and flashlight. The barrel has been replaced with one that can chamber hotter ammunition loads, meaning faster bullets, meaning more damage!"
ItemName="Beretta"
ItemShortName="9mm"
InventoryType=class'Nice9mmPlus'
PickupMessage="You got the 9mm!"
StaticMesh=StaticMesh'NicePackSM.NinePP.Pickup'
DrawScale=0.100000
}

View file

@ -0,0 +1,12 @@
class NiceAA12Ammo extends NiceAmmo;
#EXEC OBJ LOAD FILE=KillingFloorHUD.utx
defaultproperties
{
WeaponPickupClass=class'NiceAA12Pickup'
AmmoPickupAmount=20
MaxAmmo=100
InitialAmount=25
PickupClass=class'NiceAA12AmmoPickup'
IconMaterial=Texture'KillingFloorHUD.Generic.HUD'
IconCoords=(X1=451,Y1=445,X2=510,Y2=500)
}

View file

@ -0,0 +1,8 @@
class NiceAA12AmmoPickup extends NiceAmmoPickup;
defaultproperties
{
AmmoAmount=20
InventoryType=class'NiceAA12Ammo'
PickupMessage="12-Gauge Drum"
StaticMesh=None
}

View file

@ -0,0 +1,51 @@
class NiceAA12Attachment extends NiceAttachment;
defaultproperties
{
mMuzFlashClass=Class'ROEffects.MuzzleFlash3rdKar'
mShellCaseEmitterClass=Class'KFMod.KFShotgunShellSpewer'
MovementAnims(0)="JogF_AA12"
MovementAnims(1)="JogB_AA12"
MovementAnims(2)="JogL_AA12"
MovementAnims(3)="JogR_AA12"
TurnLeftAnim="TurnL_AA12"
TurnRightAnim="TurnR_AA12"
CrouchAnims(0)="CHWalkF_AA12"
CrouchAnims(1)="CHWalkB_AA12"
CrouchAnims(2)="CHWalkL_AA12"
CrouchAnims(3)="CHWalkR_AA12"
WalkAnims(0)="WalkF_AA12"
WalkAnims(1)="WalkB_AA12"
WalkAnims(2)="WalkL_AA12"
WalkAnims(3)="WalkR_AA12"
CrouchTurnRightAnim="CH_TurnR_AA12"
CrouchTurnLeftAnim="CH_TurnL_AA12"
IdleCrouchAnim="CHIdle_AA12"
IdleWeaponAnim="Idle_AA12"
IdleRestAnim="Idle_AA12"
IdleChatAnim="Idle_AA12"
IdleHeavyAnim="Idle_AA12"
IdleRifleAnim="Idle_AA12"
FireAnims(0)="Fire_AA12"
FireAnims(1)="Fire_AA12"
FireAnims(2)="Fire_AA12"
FireAnims(3)="Fire_AA12"
FireAltAnims(0)="Fire_AA12"
FireAltAnims(1)="Fire_AA12"
FireAltAnims(2)="Fire_AA12"
FireAltAnims(3)="Fire_AA12"
FireCrouchAnims(0)="CHFire_AA12"
FireCrouchAnims(1)="CHFire_AA12"
FireCrouchAnims(2)="CHFire_AA12"
FireCrouchAnims(3)="CHFire_AA12"
FireCrouchAltAnims(0)="CHFire_AA12"
FireCrouchAltAnims(1)="CHFire_AA12"
FireCrouchAltAnims(2)="CHFire_AA12"
FireCrouchAltAnims(3)="CHFire_AA12"
HitAnims(0)="HitF_AA12"
HitAnims(1)="HitB_AA12"
HitAnims(2)="HitL_AA12"
HitAnims(3)="HitR_AA12"
PostFireBlendStandAnim="Blend_AA12"
PostFireBlendCrouchAnim="CHBlend_AA12"
MeshRef="KF_Weapons3rd2_Trip.AA12_3rd"
}

View file

@ -0,0 +1,57 @@
class NiceAA12AutoShotgun extends NiceWeapon;
// Use alt fire to switch fire modes
simulated function AltFire(float F){
DoToggle();
}
exec function SwitchModes(){
DoToggle();
}
defaultproperties
{
reloadPreEndFrame=0.473000
reloadEndFrame=0.828000
reloadChargeEndFrame=-1.000000
reloadMagStartFrame=0.591000
reloadChargeStartFrame=-1.000000
MagCapacity=20
Weight=6.000000
ReloadRate=3.133000
ReloadAnim="Reload"
ReloadAnimRate=1.000000
WeaponReloadAnim="Reload_AA12"
bHasAimingMode=True
IdleAimAnim="Idle_Iron"
StandardDisplayFOV=65.000000
TraderInfoTexture=Texture'KillingFloor2HUD.Trader_Weapon_Icons.Trader_AA12'
bIsTier3Weapon=True
MeshRef="KF_Weapons2_Trip.AA12_Trip"
SkinRefs(0)="KF_Weapons2_Trip_T.Special.AA12_cmb"
SelectSoundRef="KF_AA12Snd.AA12_Select"
HudImageRef="KillingFloor2HUD.WeaponSelect.AA12_unselected"
SelectedHudImageRef="KillingFloor2HUD.WeaponSelect.AA12"
PlayerIronSightFOV=80.000000
ZoomedDisplayFOV=45.000000
FireModeClass(0)=class'NiceAA12Fire'
FireModeClass(1)=Class'KFMod.NoFire'
PutDownAnim="PutDown"
SelectForce="SwitchToAssaultRifle"
AIRating=0.550000
CurrentRating=0.550000
bShowChargingBar=True
Description="An advanced fully automatic shotgun."
EffectOffset=(X=100.000000,Y=25.000000,Z=-10.000000)
DisplayFOV=65.000000
Priority=200
InventoryGroup=4
GroupOffset=10
PickupClass=class'NiceAA12Pickup'
PlayerViewOffset=(X=25.000000,Y=20.000000,Z=-2.000000)
BobDamping=6.000000
AttachmentClass=class'NiceAA12Attachment'
IconCoords=(X1=245,Y1=39,X2=329,Y2=79)
ItemName="AA12 Shotgun"
TransientSoundVolume=1.250000
}

View file

@ -0,0 +1,26 @@
class NiceAA12Fire extends NiceShotgunFire;
defaultproperties
{
ProjPerFire=5
KickMomentum=(X=-35.000000,Z=5.000000)
maxVerticalRecoilAngle=1000
maxHorizontalRecoilAngle=500
ShellEjectClass=Class'ROEffects.KFShellEjectShotty'
ShellEjectBoneName="Shell_eject"
FireSoundRef="KF_AA12Snd.AA12_Fire"
StereoFireSoundRef="KF_AA12Snd.AA12_FireST"
NoAmmoSoundRef="KF_AA12Snd.AA12_DryFire"
DamageType=class'NiceDamTypeAA12Shotgun'
DamageMax=48
Momentum=60000.000000
bWaitForRelease=False
FireAnimRate=1.000000
FireRate=0.200000
AmmoClass=class'NiceAA12Ammo'
ShakeRotMag=(Z=250.000000)
ShakeRotTime=3.000000
ShakeOffsetMag=(Z=6.000000)
ShakeOffsetTime=1.250000
BotRefireRate=0.250000
Spread=1125.000000
}

View file

@ -0,0 +1,24 @@
class NiceAA12Pickup extends NiceWeaponPickup;
defaultproperties
{
cost=1250
AmmoCost=50
BuyClipSize=20
PowerValue=85
SpeedValue=65
RangeValue=20
Description="An advanced fully automatic shotgun."
ItemName="AA12 Shotgun"
ItemShortName="AA12 Shotgun"
AmmoItemName="12-gauge drum"
CorrespondingPerkIndex=1
EquipmentCategoryID=3
VariantClasses(0)=Class'KFMod.GoldenAA12Pickup'
InventoryType=class'NiceAA12AutoShotgun'
PickupMessage="You got the AA12 auto shotgun."
PickupSound=Sound'KF_AA12Snd.AA12_Pickup'
PickupForce="AssaultRiflePickup"
StaticMesh=StaticMesh'KF_pickups2_Trip.Shotguns.AA12_Pickup'
CollisionRadius=35.000000
CollisionHeight=5.000000
}

View file

@ -0,0 +1,13 @@
class NiceAK12Ammo extends NiceAmmo;
#EXEC OBJ LOAD FILE=KillingFloorHUD.utx
defaultproperties
{
WeaponPickupClass=class'NiceAK12Pickup'
AmmoPickupAmount=30
MaxAmmo=270
InitialAmount=60
PickupClass=class'NiceAK12AmmoPickup'
IconMaterial=Texture'KillingFloorHUD.Generic.HUD'
IconCoords=(X1=336,Y1=82,X2=382,Y2=125)
ItemName="5.45x39mm"
}

View file

@ -0,0 +1,8 @@
class NiceAK12AmmoPickup extends NiceAmmoPickup;
defaultproperties
{
AmmoAmount=30
InventoryType=class'NiceAK12Ammo'
PickupMessage="Rounds 5.45x39mm"
StaticMesh=StaticMesh'KillingFloorStatics.L85Ammo'
}

View file

@ -0,0 +1,62 @@
class NiceAK12AssaultRifle extends NiceAssaultRifle;
defaultproperties
{
bSemiAutoFireEnabled=False
bBurstFireEnabled=True
reloadPreEndFrame=0.158000
reloadEndFrame=0.521000
reloadChargeEndFrame=0.726000
reloadMagStartFrame=0.363000
reloadChargeStartFrame=0.726000
MagazineBone="Bone_Magazine"
MagCapacity=40
ReloadRate=3.000000
ReloadAnim="Reload"
ReloadAnimRate=1.000000
WeaponReloadAnim="Reload_AK47"
Weight=6.000000
bHasAimingMode=True
IdleAimAnim="Idle_Iron"
StandardDisplayFOV=55.000000
SleeveNum=8
TraderInfoTexture=Texture'ScrnWeaponPack_T.AK12.AK12_trader'
bIsTier3Weapon=True
MeshRef="ScrnWeaponPack_A.AK12_mesh"
SkinRefs(0)="ScrnWeaponPack_T.AK12.AK12_tex_1_cmb"
SkinRefs(1)="ScrnWeaponPack_T.AK12.AK12_tex_2_cmb"
SkinRefs(2)="ScrnWeaponPack_T.AK12.AK12_tex_3_cmb"
SkinRefs(3)="ScrnWeaponPack_T.AK12.AK12_tex_4_cmb"
SkinRefs(4)="ScrnWeaponPack_T.AK12.AK12_tex_5_cmb"
SkinRefs(5)="ScrnWeaponPack_T.AK12.AK12_tex_6_cmb"
SkinRefs(6)="ScrnWeaponPack_T.AK12.AK12_tex_7_cmb"
SkinRefs(7)="ScrnWeaponPack_T.AK12.AK12_aimpoint_sh"
SkinRefs(8)="KF_Weapons_Trip_T.hands.hands_1stP_military_cmb"
SelectSoundRef="ScrnWeaponPack_SND.AK12.AK12_select"
HudImageRef="ScrnWeaponPack_T.AK12.AK12_Unselect"
SelectedHudImageRef="ScrnWeaponPack_T.AK12.AK12_select"
PlayerIronSightFOV=65.000000
ZoomedDisplayFOV=20.000000
FireModeClass(0)=class'NiceAK12Fire'
FireModeClass(1)=Class'KFMod.NoFire'
PutDownAnim="PutDown"
SelectAnimRate=1.300000
SelectForce="SwitchToAssaultRifle"
AIRating=0.550000
CurrentRating=0.550000
bShowChargingBar=True
Description="The Kalashnikov AK-12 (formerly AK-200) is the newest derivative of the Soviet/Russian AK-47 series of assault rifles and was proposed for possible general issue to the Russian Army. This version uses the 5.45x39mm ammo (the same as AK-74)"
EffectOffset=(X=100.000000,Y=25.000000,Z=-10.000000)
DisplayFOV=55.000000
Priority=145
CustomCrosshair=11
CustomCrossHairTextureName="Crosshairs.HUD.Crosshair_Cross5"
InventoryGroup=4
GroupOffset=7
PickupClass=class'NiceAK12Pickup'
PlayerViewOffset=(X=-0.500000,Y=20.000000,Z=-3.000000)
BobDamping=6.000000
AttachmentClass=class'NiceAK12Attachment'
IconCoords=(X1=245,Y1=39,X2=329,Y2=79)
ItemName="AK12"
TransientSoundVolume=1.250000
}

View file

@ -0,0 +1,57 @@
class NiceAK12Attachment extends NiceAttachment;
simulated function WeaponLight();
defaultproperties
{
bSpawnLight=False
mMuzFlashClass=Class'ScrnWeaponPack.MuzzleFlashAK12AR'
mTracerClass=Class'KFMod.KFNewTracer'
mShellCaseEmitterClass=Class'KFMod.KFShellSpewer'
MovementAnims(0)="JogF_AK47"
MovementAnims(1)="JogB_AK47"
MovementAnims(2)="JogL_AK47"
MovementAnims(3)="JogR_AK47"
TurnLeftAnim="TurnL_AK47"
TurnRightAnim="TurnR_AK47"
CrouchAnims(0)="CHWalkF_AK47"
CrouchAnims(1)="CHWalkB_AK47"
CrouchAnims(2)="CHWalkL_AK47"
CrouchAnims(3)="CHWalkR_AK47"
WalkAnims(0)="WalkF_AK47"
WalkAnims(1)="WalkB_AK47"
WalkAnims(2)="WalkL_AK47"
WalkAnims(3)="WalkR_AK47"
CrouchTurnRightAnim="CH_TurnR_AK47"
CrouchTurnLeftAnim="CH_TurnL_AK47"
IdleCrouchAnim="CHIdle_AK47"
IdleWeaponAnim="Idle_AK47"
IdleRestAnim="Idle_AK47"
IdleChatAnim="Idle_AK47"
IdleHeavyAnim="Idle_AK47"
IdleRifleAnim="Idle_AK47"
FireAnims(0)="Fire_AK47"
FireAnims(1)="Fire_AK47"
FireAnims(2)="Fire_AK47"
FireAnims(3)="Fire_AK47"
FireAltAnims(0)="IS_Fire_AK47"
FireAltAnims(1)="IS_Fire_AK47"
FireAltAnims(2)="IS_Fire_AK47"
FireAltAnims(3)="IS_Fire_AK47"
FireCrouchAnims(0)="CHFire_AK47"
FireCrouchAnims(1)="CHFire_AK47"
FireCrouchAnims(2)="CHFire_AK47"
FireCrouchAnims(3)="CHFire_AK47"
FireCrouchAltAnims(0)="CHFire_AK47"
FireCrouchAltAnims(1)="CHFire_AK47"
FireCrouchAltAnims(2)="CHFire_AK47"
FireCrouchAltAnims(3)="CHFire_AK47"
HitAnims(0)="HitF_AK47"
HitAnims(1)="HitB_AK47"
HitAnims(2)="HitL_AK47"
HitAnims(3)="HitR_AK47"
PostFireBlendStandAnim="Blend_AK47"
PostFireBlendCrouchAnim="CHBlend_AK47"
MeshRef="ScrnWeaponPack_A.AK12_3rd"
bHeavy=True
SplashEffect=Class'ROEffects.BulletSplashEmitter'
CullDistance=5000.000000
}

View file

@ -0,0 +1,37 @@
class NiceAK12Fire extends NiceFire;
defaultproperties
{
MaxBurstLength=4
zedTimeFireSpeedUp=1.500000
ProjectileSpeed=44000.000000
FireAimedAnim="Fire_Iron"
RecoilRate=0.040000
maxVerticalRecoilAngle=160
maxHorizontalRecoilAngle=80
ShellEjectClass=Class'ScrnWeaponPack.KFShellEjectAK12AR'
ShellEjectBoneName="Shell_eject"
bAccuracyBonusForSemiAuto=True
bRandomPitchFireSound=False
FireSoundRef="ScrnWeaponPack_SND.AK12.AK12_shot"
StereoFireSoundRef="ScrnWeaponPack_SND.AK12.AK12_shot"
NoAmmoSoundRef="ScrnWeaponPack_SND.AK12.AK12_empty"
DamageType=class'NiceDamTypeAK12AssaultRifle'
DamageMax=68
Momentum=18500.000000
bPawnRapidFireAnim=True
TransientSoundVolume=3.800000
FireLoopAnim="Fire"
TweenTime=0.025000
FireForce="AssaultRifleFire"
FireRate=0.095000
AmmoClass=class'NiceAK12Ammo'
ShakeRotMag=(X=50.000000,Y=50.000000,Z=350.000000)
ShakeRotRate=(X=5000.000000,Y=5000.000000,Z=5000.000000)
ShakeRotTime=0.750000
ShakeOffsetMag=(X=6.000000,Y=3.000000,Z=7.500000)
ShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000)
ShakeOffsetTime=1.250000
BotRefireRate=0.990000
FlashEmitterClass=Class'ScrnWeaponPack.MuzzleFlashAK12AR'
aimerror=42.000000
}

View file

@ -0,0 +1,26 @@
class NiceAK12Pickup extends NiceWeaponPickup;
defaultproperties
{
Weight=6.000000
cost=750
AmmoCost=25
BuyClipSize=40
PowerValue=55
SpeedValue=80
RangeValue=30
Description="The Kalashnikov AK-12 (formerly AK-200) is the newest derivative of the Soviet/Russian AK-47 series of assault rifles and was proposed for possible general issue to the Russian Army. This version uses the 5.45x39mm ammo (the same as AK-74)"
ItemName="AK12"
ItemShortName="AK12"
AmmoItemName="5.45x39mm"
AmmoMesh=StaticMesh'KillingFloorStatics.L85Ammo'
CorrespondingPerkIndex=3
EquipmentCategoryID=2
InventoryType=class'NiceAK12AssaultRifle'
PickupMessage="You got the AK-12"
PickupSound=Sound'ScrnWeaponPack_SND.AK12.AK12_select'
PickupForce="AssaultRiflePickup"
StaticMesh=StaticMesh'ScrnWeaponPack_SM.AK12_st'
DrawScale=1.100000
CollisionRadius=25.000000
CollisionHeight=5.000000
}

View file

@ -0,0 +1,13 @@
class NiceAK47Ammo extends NiceAmmo;
#EXEC OBJ LOAD FILE=KillingFloorHUD.utx
defaultproperties
{
WeaponPickupClass=class'NiceAK47Pickup'
AmmoPickupAmount=30
MaxAmmo=240
InitialAmount=90
PickupClass=class'NiceAK47AmmoPickup'
IconMaterial=Texture'KillingFloorHUD.Generic.HUD'
IconCoords=(X1=336,Y1=82,X2=382,Y2=125)
ItemName="AK47 bullets"
}

View file

@ -0,0 +1,8 @@
class NiceAK47AmmoPickup extends NiceAmmoPickup;
defaultproperties
{
AmmoAmount=30
InventoryType=class'NiceAK47Ammo'
PickupMessage="Rounds 7.62mm"
StaticMesh=StaticMesh'KillingFloorStatics.L85Ammo'
}

View file

@ -0,0 +1,55 @@
class NiceAK47AssaultRifle extends NiceAssaultRifle;
#exec OBJ LOAD FILE=KillingFloorWeapons.utx
#exec OBJ LOAD FILE=KillingFloorHUD.utx
#exec OBJ LOAD FILE=Inf_Weapons_Foley.uax
defaultproperties
{
bSemiAutoFireEnabled=False
bBurstFireEnabled=True
reloadPreEndFrame=0.167000
reloadEndFrame=0.578000
reloadChargeEndFrame=0.800000
reloadMagStartFrame=0.433000
reloadChargeStartFrame=0.711000
MagazineBone="MagazineAK"
MagCapacity=30
ReloadRate=3.000000
ReloadAnim="Reload"
ReloadAnimRate=1.000000
WeaponReloadAnim="Reload_AK47"
Weight=6.000000
bHasAimingMode=True
IdleAimAnim="Idle_Iron"
StandardDisplayFOV=60.000000
TraderInfoTexture=Texture'KillingFloor2HUD.Trader_Weapon_Icons.Trader_AK_47'
bIsTier2Weapon=True
MeshRef="KF_Weapons2_Trip.AK47_Trip"
SkinRefs(0)="KF_Weapons2_Trip_T.Rifles.AK47_cmb"
SelectSoundRef="KF_AK47Snd.AK47_Select"
HudImageRef="KillingFloor2HUD.WeaponSelect.Ak_47_unselected"
SelectedHudImageRef="KillingFloor2HUD.WeaponSelect.Ak_47"
PlayerIronSightFOV=65.000000
ZoomedDisplayFOV=32.000000
FireModeClass(0)=class'NiceAK47Fire'
FireModeClass(1)=Class'KFMod.NoFire'
PutDownAnim="PutDown"
SelectForce="SwitchToAssaultRifle"
AIRating=0.550000
CurrentRating=0.550000
bShowChargingBar=True
Description="A classic Russian assault rifle. Can be fired in semi or full auto with nice knock down power but not great accuracy."
EffectOffset=(X=100.000000,Y=25.000000,Z=-10.000000)
DisplayFOV=60.000000
Priority=95
CustomCrosshair=11
CustomCrossHairTextureName="Crosshairs.HUD.Crosshair_Cross5"
InventoryGroup=3
GroupOffset=7
PickupClass=class'NiceAK47Pickup'
PlayerViewOffset=(X=18.000000,Y=22.000000,Z=-6.000000)
BobDamping=6.000000
AttachmentClass=class'NiceAK47Attachment'
IconCoords=(X1=245,Y1=39,X2=329,Y2=79)
ItemName="AK47"
TransientSoundVolume=1.250000
}

View file

@ -0,0 +1,56 @@
class NiceAK47Attachment extends NiceAttachment;
defaultproperties
{
mMuzFlashClass=Class'ROEffects.MuzzleFlash3rdMP'
mTracerClass=Class'KFMod.KFNewTracer'
mShellCaseEmitterClass=Class'KFMod.KFShellSpewer'
MovementAnims(0)="JogF_AK47"
MovementAnims(1)="JogB_AK47"
MovementAnims(2)="JogL_AK47"
MovementAnims(3)="JogR_AK47"
TurnLeftAnim="TurnL_AK47"
TurnRightAnim="TurnR_AK47"
CrouchAnims(0)="CHWalkF_AK47"
CrouchAnims(1)="CHWalkB_AK47"
CrouchAnims(2)="CHWalkL_AK47"
CrouchAnims(3)="CHWalkR_AK47"
WalkAnims(0)="WalkF_AK47"
WalkAnims(1)="WalkB_AK47"
WalkAnims(2)="WalkL_AK47"
WalkAnims(3)="WalkR_AK47"
CrouchTurnRightAnim="CH_TurnR_AK47"
CrouchTurnLeftAnim="CH_TurnL_AK47"
IdleCrouchAnim="CHIdle_AK47"
IdleWeaponAnim="Idle_AK47"
IdleRestAnim="Idle_AK47"
IdleChatAnim="Idle_AK47"
IdleHeavyAnim="Idle_AK47"
IdleRifleAnim="Idle_AK47"
FireAnims(0)="Fire_AK47"
FireAnims(1)="Fire_AK47"
FireAnims(2)="Fire_AK47"
FireAnims(3)="Fire_AK47"
FireAltAnims(0)="Fire_AK47"
FireAltAnims(1)="Fire_AK47"
FireAltAnims(2)="Fire_AK47"
FireAltAnims(3)="Fire_AK47"
FireCrouchAnims(0)="CHFire_AK47"
FireCrouchAnims(1)="CHFire_AK47"
FireCrouchAnims(2)="CHFire_AK47"
FireCrouchAnims(3)="CHFire_AK47"
FireCrouchAltAnims(0)="CHFire_AK47"
FireCrouchAltAnims(1)="CHFire_AK47"
FireCrouchAltAnims(2)="CHFire_AK47"
FireCrouchAltAnims(3)="CHFire_AK47"
HitAnims(0)="HitF_AK47"
HitAnims(1)="HitB_AK47"
HitAnims(2)="HitL_AK47"
HitAnims(3)="HitR_AK47"
PostFireBlendStandAnim="Blend_AK47"
PostFireBlendCrouchAnim="CHBlend_AK47"
MeshRef="KF_Weapons3rd_Trip.AK47_3rd"
bRapidFire=True
bAltRapidFire=True
SplashEffect=Class'ROEffects.BulletSplashEmitter'
CullDistance=5000.000000
}

View file

@ -0,0 +1,37 @@
class NiceAK47Fire extends NiceFire;
defaultproperties
{
zedTimeFireSpeedUp=1.200000
ProjectileSpeed=35750.000000
FireAimedAnim="Fire_Iron"
RecoilRate=0.070000
maxVerticalRecoilAngle=210
maxHorizontalRecoilAngle=105
ShellEjectClass=Class'ROEffects.KFShellEjectAK'
ShellEjectBoneName="Shell_eject"
bAccuracyBonusForSemiAuto=True
bRandomPitchFireSound=False
FireSoundRef="KF_AK47Snd.AK47_Fire"
StereoFireSoundRef="KF_AK47Snd.AK47_FireST"
NoAmmoSoundRef="KF_AK47Snd.AK47_DryFire"
DamageType=class'NiceDamTypeAK47AssaultRifle'
DamageMin=60
DamageMax=60
Momentum=8500.000000
bPawnRapidFireAnim=True
TransientSoundVolume=1.800000
FireLoopAnim="Fire"
TweenTime=0.025000
FireForce="AssaultRifleFire"
FireRate=0.109000
AmmoClass=class'NiceAK47Ammo'
ShakeRotMag=(X=50.000000,Y=50.000000,Z=350.000000)
ShakeRotRate=(X=5000.000000,Y=5000.000000,Z=5000.000000)
ShakeRotTime=0.750000
ShakeOffsetMag=(X=6.000000,Y=3.000000,Z=7.500000)
ShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000)
ShakeOffsetTime=1.250000
BotRefireRate=0.990000
FlashEmitterClass=Class'ROEffects.MuzzleFlash1stSTG'
aimerror=42.000000
}

View file

@ -0,0 +1,27 @@
class NiceAK47Pickup extends NiceWeaponPickup;
defaultproperties
{
Weight=6.000000
cost=750
AmmoCost=26
BuyClipSize=30
PowerValue=40
SpeedValue=80
RangeValue=50
Description="Standard issue military rifle. Equipped with an integrated 2X scope."
ItemName="AK47"
ItemShortName="AK47"
AmmoItemName="7.62mm Ammo"
AmmoMesh=StaticMesh'KillingFloorStatics.L85Ammo'
CorrespondingPerkIndex=3
EquipmentCategoryID=2
VariantClasses(0)=Class'KFMod.GoldenAK47pickup'
VariantClasses(1)=Class'KFMod.NeonAK47Pickup'
InventoryType=class'NiceAK47AssaultRifle'
PickupMessage="You got the AK47"
PickupSound=Sound'KF_AK47Snd.AK47_Pickup'
PickupForce="AssaultRiflePickup"
StaticMesh=StaticMesh'KF_pickups_Trip.Rifle.AK47_Pickup'
CollisionRadius=25.000000
CollisionHeight=5.000000
}

View file

@ -0,0 +1,70 @@
class NiceAUG_A1AR extends NiceScopedWeapon;
#EXEC OBJ LOAD FILE=HMG_T.utx
#EXEC OBJ LOAD FILE=HMG_S.uax
#EXEC OBJ LOAD FILE=HMG_A.ukx
simulated function AltFire(float F){
if(ReadyToFire(0))
DoToggle();
}
exec function SwitchModes(){
DoToggle();
}
defaultproperties
{
lenseMaterialID=4
scopePortalFOVHigh=17.000000
scopePortalFOV=17.000000
ZoomMatRef="HMG_T.AUG.AUG-A1_scope_FB"
ScriptedTextureFallbackRef="HMG_T.AUG.alpha_lens_64x64"
CrosshairTexRef="HMG_T.AUG.AUG-A1_scope"
reloadPreEndFrame=0.400000
reloadEndFrame=0.645000
reloadChargeEndFrame=0.805000
reloadMagStartFrame=0.500000
reloadChargeStartFrame=0.700000
MagazineBone="clip"
bHasScope=True
ZoomedDisplayFOVHigh=70.000000
MagCapacity=30
ReloadRate=3.500000
ReloadAnim="Reload"
ReloadAnimRate=1.000000
WeaponReloadAnim="Reload_BullPup"
Weight=9.000000
bHasAimingMode=True
IdleAimAnim="Idle_Iron"
StandardDisplayFOV=65.000000
SleeveNum=0
TraderInfoTexture=Texture'HMG_T.AUG.trader_AUG_A1'
bIsTier2Weapon=True
MeshRef="HMG_A.AUG_A1_mesh"
SkinRefs(0)="KF_Weapons3_Trip_T.hands.Priest_Hands_1st_P"
SkinRefs(1)="HMG_T.AUG.body"
SkinRefs(2)="HMG_T.AUG.mag"
SkinRefs(3)="HMG_T.AUG.Rec"
SkinRefs(4)="HMG_T.AUG.alpha_lens_64x64"
SelectSoundRef="HMG_S.AUGND.aug_draw"
HudImageRef="HMG_T.AUG.AUG_A1_Unselected"
SelectedHudImageRef="HMG_T.AUG.AUG_A1_Selected"
PlayerIronSightFOV=32.000000
ZoomedDisplayFOV=70.000000
FireModeClass(0)=class'NiceAUG_A1ARFire'
FireModeClass(1)=Class'KFMod.NoFire'
PutDownAnim="PutDown"
SelectForce="SwitchToAssaultRifle"
AIRating=0.650000
CurrentRating=0.650000
Description="Steyr AUG 1977 Steyr-Daimler-Puch AG & Co KG"
DisplayFOV=65.000000
Priority=170
CustomCrosshair=11
CustomCrossHairTextureName="Crosshairs.HUD.Crosshair_Cross5"
InventoryGroup=4
GroupOffset=3
PickupClass=class'NiceAUG_A1ARPickup'
PlayerViewOffset=(X=15.000000,Y=12.000000,Z=-2.000000)
BobDamping=5.000000
AttachmentClass=class'NiceAUG_A1ARAttachment'
IconCoords=(X1=253,Y1=146,X2=333,Y2=181)
ItemName="Steyr AUG A1"
}

View file

@ -0,0 +1,12 @@
class NiceAUG_A1ARAmmo extends NiceAmmo;
defaultproperties
{
WeaponPickupClass=class'NiceAUG_A1ARPickup'
AmmoPickupAmount=30
MaxAmmo=240
InitialAmount=60
PickupClass=class'NiceAUG_A1ARAmmoPickup'
IconMaterial=Texture'KillingFloorHUD.Generic.HUD'
IconCoords=(X1=336,Y1=82,X2=382,Y2=125)
ItemName="5.56mm NATO"
}

View file

@ -0,0 +1,8 @@
class NiceAUG_A1ARAmmoPickup extends NiceAmmoPickup;
defaultproperties
{
AmmoAmount=30
InventoryType=class'NiceAUG_A1ARAmmo'
PickupMessage="5.56mm NATO"
StaticMesh=StaticMesh'KillingFloorStatics.L85Ammo'
}

View file

@ -0,0 +1,59 @@
class NiceAUG_A1ARAttachment extends NiceAttachment;
defaultproperties
{
mMuzFlashClass=Class'ROEffects.MuzzleFlash3rdMP'
mTracerClass=Class'KFMod.KFNewTracer'
mShellCaseEmitterClass=Class'KFMod.KFShellSpewer'
ShellEjectBoneName="Shell_eject"
MovementAnims(0)="JogF_SCAR"
MovementAnims(1)="JogB_SCAR"
MovementAnims(2)="JogL_SCAR"
MovementAnims(3)="JogR_SCAR"
TurnLeftAnim="TurnL_SCAR"
TurnRightAnim="TurnR_SCAR"
CrouchAnims(0)="CHWalkF_SCAR"
CrouchAnims(1)="CHWalkB_SCAR"
CrouchAnims(2)="CHWalkL_SCAR"
CrouchAnims(3)="CHWalkR_SCAR"
WalkAnims(0)="WalkF_SCAR"
WalkAnims(1)="WalkB_SCAR"
WalkAnims(2)="WalkL_SCAR"
WalkAnims(3)="WalkR_SCAR"
CrouchTurnRightAnim="CH_TurnR_SCAR"
CrouchTurnLeftAnim="CH_TurnL_SCAR"
IdleCrouchAnim="CHIdle_SCAR"
IdleWeaponAnim="Idle_SCAR"
IdleRestAnim="Idle_SCAR"
IdleChatAnim="Idle_SCAR"
IdleHeavyAnim="Idle_SCAR"
IdleRifleAnim="Idle_SCAR"
FireAnims(0)="Fire_SCAR"
FireAnims(1)="Fire_SCAR"
FireAnims(2)="Fire_SCAR"
FireAnims(3)="Fire_SCAR"
FireAltAnims(0)="Fire_SCAR"
FireAltAnims(1)="Fire_SCAR"
FireAltAnims(2)="Fire_SCAR"
FireAltAnims(3)="Fire_SCAR"
FireCrouchAnims(0)="CHFire_SCAR"
FireCrouchAnims(1)="CHFire_SCAR"
FireCrouchAnims(2)="CHFire_SCAR"
FireCrouchAnims(3)="CHFire_SCAR"
FireCrouchAltAnims(0)="CHFire_SCAR"
FireCrouchAltAnims(1)="CHFire_SCAR"
FireCrouchAltAnims(2)="CHFire_SCAR"
FireCrouchAltAnims(3)="CHFire_SCAR"
HitAnims(0)="HitF_SCAR"
HitAnims(1)="HitB_SCAR"
HitAnims(2)="HitL_SCAR"
HitAnims(3)="HitR_SCAR"
PostFireBlendStandAnim="Blend_SCAR"
PostFireBlendCrouchAnim="CHBlend_SCAR"
MeshRef="HMG_A.AUG_A1_3rd"
bHeavy=True
bRapidFire=True
bAltRapidFire=True
SplashEffect=Class'ROEffects.BulletSplashEmitter'
CullDistance=5000.000000
DrawScale=0.800000
}

View file

@ -0,0 +1,35 @@
class NiceAUG_A1ARFire extends NiceHeavyFire;
defaultproperties
{
ProjectileSpeed=48500.000000
FireAimedAnim="Idle_Iron"
RecoilRate=0.080000
maxVerticalRecoilAngle=500
maxHorizontalRecoilAngle=250
ShellEjectClass=Class'ROEffects.KFShellEjectBullpup'
ShellEjectBoneName="Shell_eject"
bAccuracyBonusForSemiAuto=True
FireSoundRef="HMG_S.AUGND.aug_fire"
StereoFireSoundRef="HMG_S.AUGND.aug_fire"
NoAmmoSoundRef="HMG_S.AUGND.aug_empty"
DamageType=class'NiceDamTypeAUG_A1AR'
DamageMin=105
DamageMax=105
Momentum=12000.000000
bPawnRapidFireAnim=True
TransientSoundVolume=1.800000
FireLoopAnim="Fire"
TweenTime=0.025000
FireForce="AssaultRifleFire"
FireRate=0.200000
AmmoClass=class'NiceAUG_A1ARAmmo'
ShakeRotMag=(X=75.000000,Y=75.000000,Z=250.000000)
ShakeRotRate=(X=10000.000000,Y=10000.000000,Z=10000.000000)
ShakeRotTime=0.500000
ShakeOffsetMag=(X=6.000000,Y=3.000000,Z=10.000000)
ShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000)
ShakeOffsetTime=1.000000
BotRefireRate=0.990000
FlashEmitterClass=Class'ROEffects.MuzzleFlash1stSTG'
aimerror=42.000000
}

View file

@ -0,0 +1,24 @@
class NiceAUG_A1ARPickup extends NiceWeaponPickup;
defaultproperties
{
cost=1000
Weight=9.000000
AmmoCost=80
BuyClipSize=25
PowerValue=45
SpeedValue=65
RangeValue=90
Description="Steyr AUG 1977 Steyr-Daimler-Puch AG & Co KG"
ItemName="Steyr AUG A1"
ItemShortName="AUG A1"
AmmoItemName="Rounds 5.56mm NATO"
CorrespondingPerkIndex=1
EquipmentCategoryID=2
InventoryType=class'NiceAUG_A1AR'
PickupMessage="You picked up the Steyr AUG A1"
PickupSound=Sound'HMG_S.AUG.aug_pickup'
PickupForce="AssaultRiflePickup"
StaticMesh=StaticMesh'HMG_A.AUG_A1_st'
CollisionRadius=30.000000
CollisionHeight=5.000000
}

View file

@ -0,0 +1,25 @@
//==============================================================================
// NicePack / NiceAbilitiesAdapter
//==============================================================================
// Temporary stand-in for future functionality.
// Use this class to catch events from players' abilities.
//==============================================================================
// 'Nice pack' source
// Do whatever the fuck you want with it
// Author: dkanus
// E-mail: dkanus@gmail.com
//==============================================================================
class NiceAbilitiesAdapter extends Object;
var LevelInfo level;
static function AbilityActivated( string abilityID,
NicePlayerController relatedPlayer);
static function AbilityAdded( string abilityID,
NicePlayerController relatedPlayer);
static function AbilityRemoved( string abilityID,
NicePlayerController relatedPlayer);
static function ModAbilityCooldown( string abilityID,
NicePlayerController relatedPlayer,
out float cooldown);
defaultproperties
{
}

View file

@ -0,0 +1,79 @@
//==============================================================================
// NicePack / NiceAbilitiesEvents
//==============================================================================
// Temporary stand-in for future functionality.
//==============================================================================
// 'Nice pack' source
// Do whatever the fuck you want with it
// Author: dkanus
// E-mail: dkanus@gmail.com
//==============================================================================
class NiceAbilitiesEvents extends Object;
var array< class<NiceAbilitiesAdapter> > adapters;
// If adapter was already added also returns 'false'.
static function bool AddAdapter(class<NiceAbilitiesAdapter> newAdapter,
optional LevelInfo level){
local int i;
if(newAdapter == none) return false;
for(i = 0;i < default.adapters.length;i ++)
if(default.adapters[i] == newAdapter)
return false;
newAdapter.default.level = level;
default.adapters[default.adapters.length] = newAdapter;
return true;
}
// If adapter wasn't even present also returns 'false'.
static function bool RemoveAdapter(class<NiceAbilitiesAdapter> adapter){
local int i;
if(adapter == none) return false;
for(i = 0;i < default.adapters.length;i ++){
if(default.adapters[i] == adapter){
default.adapters.Remove(i, 1);
return true;
}
}
return false;
}
static function CallAbilityActivated
(
string abilityID,
NicePlayerController relatedPlayer
){
local int i;
for(i = 0;i < default.adapters.length;i ++)
default.adapters[i].static.AbilityActivated(abilityID, relatedPlayer);
}
static function CallAbilityAdded
(
string abilityID,
NicePlayerController relatedPlayer
){
local int i;
for(i = 0;i < default.adapters.length;i ++)
default.adapters[i].static.AbilityAdded(abilityID, relatedPlayer);
}
static function CallAbilityRemoved
(
string abilityID,
NicePlayerController relatedPlayer
){
local int i;
for(i = 0;i < default.adapters.length;i ++)
default.adapters[i].static.AbilityRemoved(abilityID, relatedPlayer);
}
static function CallModAbilityCooldown
(
string abilityID,
NicePlayerController relatedPlayer,
out float cooldown
){
local int i;
for(i = 0;i < default.adapters.length;i ++){
default.adapters[i].static.ModAbilityCooldown( abilityID,
relatedPlayer,
cooldown);
}
}
defaultproperties
{
}

View file

@ -0,0 +1,178 @@
//==============================================================================
// NicePack / NiceAbilityManager
//==============================================================================
// Class that manager active abilities, introduced along with a NicePack.
// Can support at most 5 ('maxAbilitiesAmount') different abilities at once.
// NICETODO: refactor later
//==============================================================================
// 'Nice pack' source
// Do whatever the fuck you want with it
// Author: dkanus
// E-mail: dkanus@gmail.com
//==============================================================================
class NiceAbilityManager extends Actor;
var const int maxAbilitiesAmount;
// Defines a list of all possible ability's states
enum EAbilityState{
// Ability is ready to use
ASTATE_READY,
// Ability is being used
ASTATE_ACTIVE,
// Ability is on cooldown
ASTATE_COOLDOWN
};
// Describes all the necessary information about an ability
struct NiceAbilityDescription{
// Ability's ID, supposed to be unique per ability,
// but no checks are enforced yet
var string ID;
// Image to be used as an ability's icon
var Texture icon;
// Default cooldown duration
var int cooldownLength;
// Can ability be canceled once activated?
var bool canBeCancelled;
};
// Complete description of current status of an ability,
// including it's complete description.
struct NiceAbilityStatus{
// Complete description of ability in question
var NiceAbilityDescription description;
// Current cooldown value
var int cooldown;
// Current state of an ability
var EAbilityState myState;
};
var NiceAbilityStatus currentAbilities[5];
var int currentAbilitiesAmount;
// Refers to the player whose abilities we manage
var NicePlayerController relatedPlayer;
var const class<NiceAbilitiesEvents> events;
// Unfortunately this hackk is required to force replication of structure array
var int hackCounter;
replication{
reliable if(Role == ROLE_Authority)
currentAbilities, currentAbilitiesAmount, hackCounter;
}
simulated function PostBeginPlay(){
relatedPlayer = NicePlayerController(owner);
}
function AddAbility(NiceAbilityDescription description){
local int i;
local NiceAbilityStatus newRecord;
if(currentAbilitiesAmount >= maxAbilitiesAmount) return;
for(i = 0;i < currentAbilitiesAmount;i ++)
if(currentAbilities[i].description.ID ~= description.ID)
return;
newRecord.description = description;
newRecord.cooldown = 0;
newRecord.myState = ASTATE_READY;
currentAbilities[currentAbilitiesAmount] = newRecord;
currentAbilitiesAmount += 1;
events.static.CallAbilityAdded(description.ID, relatedPlayer);
netUpdateTime = level.timeSeconds - 1;
}
function RemoveAbility(string abilityID){
local int i, j;
local bool wasRemoved;
j = 0;
for(i = 0;i < currentAbilitiesAmount;i ++){
if(currentAbilities[i].description.ID ~= abilityID){
wasRemoved = true;
continue;
}
currentAbilities[j] = currentAbilities[i];
j += 1;
}
currentAbilitiesAmount = j;
if(wasRemoved)
events.static.CallAbilityRemoved(abilityID, relatedPlayer);
netUpdateTime = level.timeSeconds - 1;
}
function ClearAbilities(){
currentAbilitiesAmount = 0;
netUpdateTime = level.timeSeconds - 1;
}
// Returns index of the ability with a given name.
// Returns '-1' if such ability doesn't exist.
simulated function int GetAbilityIndex(string abilityID){
local int i;
for(i = 0;i < currentAbilitiesAmount;i ++)
if(currentAbilities[i].description.ID ~= abilityID)
return i;
return -1;
}
simulated function bool IsAbilityActive(string abilityID){
local int index;
index = GetAbilityIndex(abilityID);
if(index < 0)
return false;
return (currentAbilities[index].myState == ASTATE_ACTIVE);
}
// Sets ability to a proper state.
// Does nothing if ability is already in a specified state.
// Setting active ability to a ready state is only allowed
// if ability can be canceled.
// Updates cooldown to full length if new state is 'ASTATE_COOLDOWN'.
function SetAbilityState(int abilityIndex, EAbilityState newState){
local float cooldown;
local EAbilityState currentState;
if(abilityIndex < 0 || abilityIndex >= currentAbilitiesAmount) return;
currentState = currentAbilities[abilityIndex].myState;
if(currentState == newState)
return;
if( currentState == ASTATE_ACTIVE && newState == ASTATE_READY
&& !currentAbilities[abilityIndex].description.canBeCancelled)
return;
currentAbilities[abilityIndex].myState = newState;
if(newState == ASTATE_COOLDOWN){
cooldown = currentAbilities[abilityIndex].description.cooldownLength;
events.static.CallModAbilityCooldown(
currentAbilities[abilityIndex].description.ID,
relatedPlayer,
cooldown
);
currentAbilities[abilityIndex].cooldown = cooldown;
}
hackCounter ++;
netUpdateTime = level.timeSeconds - 1;
// Fire off events
if(newState == ASTATE_ACTIVE){
events.static.CallAbilityActivated(
currentAbilities[abilityIndex].description.ID,
relatedPlayer
);
}
}
// Changes ability's cooldown by a given amount.
// If this brings cooldown to zero or below -
// resets current ability to a 'ready' (ASTATE_READY) state.
function AddToCooldown(int abilityIndex, int delta){
if(abilityIndex < 0 || abilityIndex >= currentAbilitiesAmount) return;
if(currentAbilities[abilityIndex].myState != ASTATE_COOLDOWN) return;
currentAbilities[abilityIndex].cooldown += delta;
if(currentAbilities[abilityIndex].cooldown <= 0)
SetAbilityState(abilityIndex, ASTATE_READY);
hackCounter ++;
}
function AddToAllCooldowns(int delta){
local int i;
for (i = 0; i < currentAbilitiesAmount; i += 1) {
if (currentAbilities[i].myState == ASTATE_COOLDOWN) {
currentAbilities[i].cooldown += delta;
if(currentAbilities[i].cooldown <= 0) {
SetAbilityState(i, ASTATE_READY);
}
}
}
hackCounter ++;
}
defaultproperties
{
maxAbilitiesAmount=5
Events=class'NiceAbilitiesEvents'
DrawType=DT_None
}

View file

@ -0,0 +1,12 @@
class NiceAmmo extends KFAmmunition;
var class<NiceWeaponPickup> WeaponPickupClass;
function UpdateAmmoAmount(){
MaxAmmo = Default.MaxAmmo;
if(KFPawn(Owner) != none && KFPlayerReplicationInfo(KFPawn(Owner).PlayerReplicationInfo) != none &&
KFPlayerReplicationInfo(KFPawn(Owner).PlayerReplicationInfo).ClientVeteranSkill != none)
MaxAmmo = float(MaxAmmo) * KFPlayerReplicationInfo(KFPawn(Owner).PlayerReplicationInfo).ClientVeteranSkill.Static.AddExtraAmmoFor(KFPlayerReplicationInfo(KFPawn(Owner).PlayerReplicationInfo), Class);
AmmoAmount = Min(AmmoAmount, MaxAmmo);
}
defaultproperties
{
}

View file

@ -0,0 +1,45 @@
class NiceAmmoPickup extends ScrnAmmoPickup;
state Pickup
{
// When touched by an actor.
function Touch(Actor Other){
local Inventory CurInv;
local bool bPickedUp;
local int AmmoPickupAmount;
if(Pawn(Other) != none && Pawn(Other).bCanPickupInventory && Pawn(Other).Controller != none && FastTrace(Other.Location, Location)){
for(CurInv = Other.Inventory;CurInv != none;CurInv = CurInv.Inventory){
if(KFAmmunition(CurInv) != none && KFAmmunition(CurInv).bAcceptsAmmoPickups){
if(KFAmmunition(CurInv).AmmoPickupAmount > 0){
if(KFAmmunition(CurInv).AmmoAmount < KFAmmunition(CurInv).MaxAmmo){
if(KFPlayerReplicationInfo(Pawn(Other).PlayerReplicationInfo) != none && KFPlayerReplicationInfo(Pawn(Other).PlayerReplicationInfo).ClientVeteranSkill != none)
AmmoPickupAmount = float(KFAmmunition(CurInv).AmmoPickupAmount) * KFPlayerReplicationInfo(Pawn(Other).PlayerReplicationInfo).ClientVeteranSkill.static.GetAmmoPickupMod(KFPlayerReplicationInfo(Pawn(Other).PlayerReplicationInfo), KFAmmunition(CurInv));
else
AmmoPickupAmount = KFAmmunition(CurInv).AmmoPickupAmount;
KFAmmunition(CurInv).AmmoAmount = Min(KFAmmunition(CurInv).MaxAmmo, KFAmmunition(CurInv).AmmoAmount + AmmoPickupAmount);
bPickedUp = true;
}
}
else if(KFAmmunition(CurInv).AmmoAmount < KFAmmunition(CurInv).MaxAmmo){
bPickedUp = true;
if(FRand() <= (1.0 / Level.Game.GameDifficulty))
KFAmmunition(CurInv).AmmoAmount++;
}
}
}
if(bPickedUp){
AnnouncePickup(Pawn(Other));
GotoState('Sleeping', 'Begin');
if(KFGameType(Level.Game) != none)
KFGameType(Level.Game).AmmoPickedUp(self);
}
}
}
}
defaultproperties
{
}

View file

@ -0,0 +1,19 @@
//==============================================================================
// NicePack / NiceArchivator
//==============================================================================
// "Compresses" and "decompresses" parts of NicePlain data into
// string for replication.
//==============================================================================
// Class hierarchy: Object > NiceArchivator
//==============================================================================
// 'Nice pack' source
// Do whatever the fuck you want with it
// Author: dkanus
// E-mail: dkanus@gmail.com
//==============================================================================
class NiceArchivator extends Object;
defaultproperties
{
}

View file

@ -0,0 +1,306 @@
class NiceAssaultRifle extends NiceWeapon;
var bool newStatesLoaded;
var bool bAutoFireEnabled;
var bool bSemiAutoFireEnabled;
var bool bBurstFireEnabled;
var bool bIsBursting;
var bool bIsAltSwitches;
var bool bMustSwitchMode; // Switch between auto and semi-auto/burst modes as soon as possible
var Pawn rememberedOwner;
enum EFireType{
ETYPE_NONE,
ETYPE_AUTO,
ETYPE_SEMI,
ETYPE_BURST
};
var EFireType MainFire;
var EFireType SndFire;
var EFireType PendingFire;
replication
{
reliable if(Role < ROLE_Authority)
ServerForceBurst, ServerApplyFireModes, ServerChangeFireTypes;
reliable if(Role == ROLE_Authority)
MainFire, SndFire, PendingFire, ClientNiceChangeFireMode, ClientChangeBurstLength;
}
simulated function EFireType GetComplimentaryFire(EFireType type){
if(type == ETYPE_AUTO || type == ETYPE_none)
return ETYPE_AUTO;
if(type == ETYPE_SEMI)
return ETYPE_BURST;
return ETYPE_SEMI;
}
simulated function int AmountOfActiveModes(){
if(bAutoFireEnabled && bSemiAutoFireEnabled && bBurstFireEnabled)
return 3;
else if(!bAutoFireEnabled && !bSemiAutoFireEnabled && !bBurstFireEnabled)
return 0;
else if( (bAutoFireEnabled && bSemiAutoFireEnabled) || (bAutoFireEnabled && bBurstFireEnabled) || (bSemiAutoFireEnabled && bBurstFireEnabled) )
return 2;
return 1;
}
function ServerApplyFireModes(){
local NiceFire niceRifleFire;
local NicePlayerController nicePlayer;
niceRifleFire = NiceFire(FireMode[0]);
if(Instigator != none)
nicePlayer = NicePlayerController(Instigator.Controller);
if(niceRifleFire == none)
return;
if(MainFire == ETYPE_AUTO)
niceRifleFire.bWaitForRelease = false;
else if(MainFire == ETYPE_SEMI){
niceRifleFire.bSemiMustBurst = false;
niceRifleFire.bWaitForRelease = true;
}
else if(MainFire == ETYPE_BURST){
niceRifleFire.bSemiMustBurst = true;
niceRifleFire.bWaitForRelease = true;
niceRifleFire.currentContext.burstLength = niceRifleFire.MaxBurstLength;
if(SndFire == ETYPE_SEMI)
SndFire = ETYPE_BURST;
}
if(nicePlayer != none && !nicePlayer.bFlagAltSwitchesModes){
if(SndFire == ETYPE_SEMI)
niceRifleFire.currentContext.burstLength = 1;
else if(SndFire == ETYPE_BURST)
niceRifleFire.currentContext.burstLength = niceRifleFire.MaxBurstLength;
}
if(!bIsReloading && IsFiring()){
StopFire(0);
StopFire(1);
}
ClientNiceChangeFireMode(niceRifleFire.bWaitForRelease, niceRifleFire.bSemiMustBurst);
ClientChangeBurstLength(niceRifleFire.currentContext.burstLength);
}
simulated function ResetFireModes(){
local int modesCount;
local NicePlayerController nicePlayer;
modesCount = AmountOfActiveModes();
nicePlayer = NicePlayerController(Instigator.Controller);
if(modesCount <= 0 || nicePlayer == none)
return;
if(nicePlayer.bFlagAltSwitchesModes){
if(modesCount == 1){
if(bAutoFireEnabled)
MainFire = ETYPE_AUTO;
else if(bSemiAutoFireEnabled)
MainFire = ETYPE_SEMI;
else if(bBurstFireEnabled)
MainFire = ETYPE_BURST;
}
else if(modesCount == 2){
if(bAutoFireEnabled){
MainFire = ETYPE_AUTO;
if(bSemiAutoFireEnabled)
PendingFire = ETYPE_SEMI;
else if(bBurstFireEnabled)
PendingFire = ETYPE_BURST;
}
else{
MainFire = ETYPE_SEMI;
PendingFire = ETYPE_BURST;
}
}
else{
MainFire = ETYPE_AUTO;
PendingFire = ETYPE_SEMI;
}
}
else{
if(modesCount == 1){
if(bAutoFireEnabled)
MainFire = ETYPE_AUTO;
else if(bSemiAutoFireEnabled)
MainFire = ETYPE_SEMI;
else if(bBurstFireEnabled)
MainFire = ETYPE_BURST;
SndFire = ETYPE_none;
}
else if(modesCount == 2){
if(bAutoFireEnabled){
MainFire = ETYPE_AUTO;
if(bSemiAutoFireEnabled)
SndFire = ETYPE_SEMI;
else if(bBurstFireEnabled)
SndFire = ETYPE_BURST;
}
else{
MainFire = ETYPE_SEMI;
SndFire = ETYPE_BURST;
}
}
else{
MainFire = ETYPE_AUTO;
SndFire = ETYPE_SEMI;
}
}
ServerChangeFireTypes(MainFire, SndFire, PendingFire);
ServerApplyFireModes();
}
function ServerChangeFireTypes(EFireType newMain, EFireType newSnd, EFireType newPending){
MainFire = newMain;
SndFire = newSnd;
PendingFire = newPending;
}
function ServerForceBurst(){
local NiceFire niceRifleFire;
niceRifleFire = NiceFire(FireMode[0]);
if(niceRifleFire != none)
niceRifleFire.DoBurst();
}
// Use alt fire to switch fire modes
simulated function AltFire(float F){
local NiceFire niceRifleFire;
local NicePlayerController nicePlayer;
niceRifleFire = NiceFire(FireMode[0]);
nicePlayer = NicePlayerController(Instigator.Controller);
if(nicePlayer != none && niceRifleFire != none && SndFire != ETYPE_NONE){
if(FireModeClass[1] == class'KFMod.NoFire'){
if(nicePlayer.bFlagAltSwitchesModes)
SwitchModes();
else{
niceRifleFire.DoBurst();
ServerForceBurst();
super.AltFire(F);
}
return;
}
}
super.AltFire(F);
}
exec simulated function SwitchModes(){
if(Role < ROLE_Authority && AmountOfActiveModes() > 1)
bMustSwitchMode = !bMustSwitchMode;
}
simulated function DoToggle(){
local EFireType tempType;
local PlayerController player;
if(IsFiring())
return;
player = Level.GetLocalPlayerController();
if(player != none && AmountOfActiveModes() > 1){
tempType = MainFire;
MainFire = PendingFire;
PendingFire = tempType;
player.bFire = 0;
player.bAltFire = 0;
ServerChangeFireTypes(MainFire, SndFire, PendingFire);
ServerApplyFireModes();
PlayOwnedSound(ToggleSound, SLOT_none, 2.0,,,, false);
if(MainFire == ETYPE_AUTO)
player.ReceiveLocalizedMessage(class'NiceAssaultRifleMessage', 1);
else if(MainFire == ETYPE_SEMI)
player.ReceiveLocalizedMessage(class'NiceAssaultRifleMessage', 0);
else if(MainFire == ETYPE_BURST)
player.ReceiveLocalizedMessage(class'NiceAssaultRifleMessage', 2);
}
}
simulated function SecondDoToggle(){
local EFireType choosenType;
local NiceFire niceRifleFire;
local NicePlayerController nicePlayer;
if(FireModeClass[1] != class'KFMod.NoFire'){
DoToggle();
return;
}
niceRifleFire = NiceFire(FireMode[0]);
nicePlayer = NicePlayerController(Instigator.Controller);
if(IsFiring() || AmountOfActiveModes() < 3 || nicePlayer == none || niceRifleFire == none)
return;
if(nicePlayer.bFlagAltSwitchesModes){
if(MainFire == ETYPE_AUTO){
PendingFire = GetComplimentaryFire(PendingFire);
choosenType = PendingFire;
}
else{
MainFire = GetComplimentaryFire(MainFire);
choosenType = MainFire;
}
}
else{
SndFire = GetComplimentaryFire(SndFire);
choosenType = SndFire;
}
ServerChangeFireTypes(MainFire, SndFire, PendingFire);
ServerApplyFireModes();
PlayOwnedSound(ToggleSound, SLOT_none, 2.0,,,, false);
if(choosenType == ETYPE_SEMI)
nicePlayer.ReceiveLocalizedMessage(class'NiceAssaultRifleMessage', 4);
else
nicePlayer.ReceiveLocalizedMessage(class'NiceAssaultRifleMessage', 5);
}
simulated function ClientNiceChangeFireMode(bool bNewWaitForRelease, bool bNewSemiMustBurst){
local NiceFire niceF;
if(!bIsReloading && IsFiring()){
StopFire(0);
StopFire(1);
}
niceF = NiceFire(FireMode[0]);
FireMode[0].bWaitForRelease = bNewWaitForRelease;
FireMode[0].bNowWaiting = bNewWaitForRelease;
if(niceF != none)
niceF.bSemiMustBurst = bNewSemiMustBurst;
}
simulated function ClientChangeBurstLength(int newBurstLength){
if(NiceFire(FireMode[0]) != none)
NiceFire(FireMode[0]).currentContext.burstLength = newBurstLength;
}
simulated function bool AltFireCanForceInterruptReload(){
local NicePlayerController nicePlayer;
nicePlayer = NicePlayerController(Instigator.Controller);
if(nicePlayer != none)
return (!nicePlayer.bFlagAltSwitchesModes) && (GetMagazineAmmo() > 0);
return false;
}
simulated function WeaponTick(float dt){
local NicePlayerController nicePlayer;
super.WeaponTick(dt);
if(bMustSwitchMode && FireMode[0].NextFireTime /*+ 0.1*/ < Level.TimeSeconds && Role < ROLE_Authority){
DoToggle();
bMustSwitchMode = false;
}
nicePlayer = NicePlayerController(Instigator.Controller);
if(Role == ROLE_Authority && nicePlayer != none && (bIsAltSwitches != nicePlayer.bFlagAltSwitchesModes || (rememberedOwner != Instigator))){
if(newStatesLoaded)
ServerApplyFireModes();
else
ResetFireModes();
bIsAltSwitches = nicePlayer.bFlagAltSwitchesModes;
rememberedOwner = Instigator;
}
}
function NicePlainData.Data GetNiceData(){
local NicePlainData.Data transferData;
transferData = super.GetNiceData();
class'NicePlainData'.static.SetInt(transferData, "MainFire", int(MainFire));
class'NicePlainData'.static.SetInt(transferData, "SndFire", int(SndFire));
class'NicePlainData'.static.SetInt(transferData, "PendingFire", int(PendingFire));
return transferData;
}
function SetNiceData(NicePlainData.Data transferData, optional NiceHumanPawn newOwner){
local EFireType newFireType;
super.SetNiceData(transferData, newOwner);
newStatesLoaded = false;
if(class'NicePlainData'.static.LookupVar(transferData, "MainFire") < 0)
ResetFireModes();
else{
newFireType = EFireType(class'NicePlainData'.static.GetInt(transferData, "MainFire"));
MainFire = newFireType;
newFireType = EFireType(class'NicePlainData'.static.GetInt(transferData, "SndFire"));
SndFire = newFireType;
newFireType = EFireType(class'NicePlainData'.static.GetInt(transferData, "PendingFire"));
PendingFire = newFireType;
newStatesLoaded = true;
}
}
defaultproperties
{
bAutoFireEnabled=True
bSemiAutoFireEnabled=True
MainFire=ETYPE_AUTO
SndFire=ETYPE_SEMI
PendingFire=ETYPE_BURST
bUseFlashlightToToggle=True
}

View file

@ -0,0 +1,9 @@
class NiceAssaultRifleMessage extends BullpupSwitchMessage;
defaultproperties
{
SwitchMessage(2)="Set to Burst Fire."
SwitchMessage(3)="Set to 5-Burst Fire."
SwitchMessage(4)="Secondary mode now set to Semi-Automatic."
SwitchMessage(5)="Secondary mode now set to Burst Fire."
}

View file

@ -0,0 +1,131 @@
class NiceAttachment extends ScrnLaserWeaponAttachment
abstract;
var array<string> SkinRefs;
var bool bSpawnLight;
var bool bSecondaryModeNoEffects;
static function PreloadAssets(optional KFWeaponAttachment Spawned){
local int i;
if(default.Mesh == none && default.MeshRef != "")
UpdateDefaultMesh(Mesh(DynamicLoadObject(default.MeshRef, class'Mesh', true)));
if(default.AmbientSound == none && default.AmbientSoundRef != "")
default.AmbientSound = sound(DynamicLoadObject(default.AmbientSoundRef, class'Sound', true));
if(Spawned != none){
Spawned.LinkMesh(default.Mesh);
Spawned.AmbientSound = default.AmbientSound;
}
for(i = 0; i < default.SkinRefs.Length;i ++){
if(default.SkinRefs[i] != "" && (default.Skins.Length < i + 1 || default.Skins[i] == none))
default.Skins[i] = Material(DynamicLoadObject(default.SkinRefs[i], class'Material'));
if(Spawned != none)
Spawned.Skins[i] = default.Skins[i];
}
}
static function bool UnloadAssets(){
local int i;
UpdateDefaultMesh(none);
default.AmbientSound = none;
for(i = 0;i < default.Skins.Length;i ++)
default.Skins[i] = none;
return super.UnloadAssets();
}
simulated event ThirdPersonEffects(){
local NicePlayerController PC;
if((Level.NetMode == NM_DedicatedServer) || (Instigator == none))
return;
PC = NicePlayerController(Level.GetLocalPlayerController());
if(FiringMode == 0){
if(OldSpawnHitCount != SpawnHitCount){
OldSpawnHitCount = SpawnHitCount;
GetHitInfo();
if(((Instigator != none) && (Instigator.Controller == PC)) || (VSize(PC.ViewTarget.Location - mHitLocation) < 4000)){
if(PC != Instigator.Controller){
if(mHitActor != none)
Spawn(class'ROBulletHitEffect',,, mHitLocation, Rotator(-mHitNormal));
CheckForSplash();
SpawnTracer();
}
}
}
}
if(FlashCount > 0){
if(KFPawn(Instigator) != none){
if(FiringMode == 0)
KFPawn(Instigator).StartFiringX(false, bRapidFire);
else
KFPawn(Instigator).StartFiringX(true, bRapidFire);
}
if(bDoFiringEffects && (!bSecondaryModeNoEffects || FiringMode == 0)){
if((Level.TimeSeconds - LastRenderTime > 0.2) && (Instigator.Controller != PC))
return;
if(bSpawnLight)
WeaponLight();
DoFlashEmitter();
ThirdPersonShellEject();
}
}
else{
GotoState('');
if(KFPawn(Instigator) != none)
KFPawn(Instigator).StopFiring();
}
}
function UpdateHit(Actor HitActor, vector HitLocation, vector HitNormal){
SpawnHitCount++;
mHitLocation = HitLocation;
mHitActor = HitActor;
mHitNormal = HitNormal;
NetUpdateTime = Level.TimeSeconds - 1;
}
simulated function ThirdPersonShellEject(){
if((mShellCaseEmitter == none) && (Level.DetailMode != DM_Low) && !Level.bDropDetail){
mShellCaseEmitter = Spawn(mShellCaseEmitterClass);
if(mShellCaseEmitter != none)
AttachToBone(mShellCaseEmitter, 'ShellPort');
}
if(mShellCaseEmitter != none)
mShellCaseEmitter.mStartParticles++;
}
simulated function SpawnTracerAtLocation(vector HitLocation){
local vector SpawnLoc, SpawnDir, SpawnVel;
local float hitDist;
if(!bDoFiringEffects)
return;
if(mTracer == none)
mTracer = Spawn(mTracerClass);
if(mTracer != none){
SpawnLoc = GetTracerStart();
mTracer.SetLocation(SpawnLoc);
hitDist = VSize(HitLocation - SpawnLoc) - mTracerPullback;
SpawnDir = Normal(HitLocation - SpawnLoc);
if(hitDist > mTracerMinDistance){
SpawnVel = SpawnDir * mTracerSpeed;
mTracer.Emitters[0].StartVelocityRange.X.Min = SpawnVel.X;
mTracer.Emitters[0].StartVelocityRange.X.Max = SpawnVel.X;
mTracer.Emitters[0].StartVelocityRange.Y.Min = SpawnVel.Y;
mTracer.Emitters[0].StartVelocityRange.Y.Max = SpawnVel.Y;
mTracer.Emitters[0].StartVelocityRange.Z.Min = SpawnVel.Z;
mTracer.Emitters[0].StartVelocityRange.Z.Max = SpawnVel.Z;
mTracer.Emitters[0].LifetimeRange.Min = hitDist / mTracerSpeed;
mTracer.Emitters[0].LifetimeRange.Max = mTracer.Emitters[0].LifetimeRange.Min;
mTracer.SpawnParticle(1);
}
}
}
simulated function CheckForSplashAtLocation(vector HitLoc){
local Actor HitActor;
local vector HitNormal, HitLocation;
if(!Level.bDropDetail && (Level.DetailMode != DM_Low) && (SplashEffect != none) && !Instigator.PhysicsVolume.bWaterVolume){
// check for splash
bTraceWater = true;
HitActor = Trace(HitLocation, HitNormal, HitLoc, Instigator.Location, true);
bTraceWater = false;
if((FluidSurfaceInfo(HitActor) != none) || ((PhysicsVolume(HitActor) != none) && PhysicsVolume(HitActor).bWaterVolume))
Spawn(SplashEffect,,,HitLocation, rot(16384,0,0));
}
}
defaultproperties
{
bSpawnLight=True
}

View file

@ -0,0 +1,11 @@
class NiceAvoidMarker extends AvoidMarker;
function bool RelevantTo(Pawn P){
local NiceZombieFleshpound niceFP;
niceFP = NiceZombieFleshpound(P);
if(niceFP != none && niceFP.IsInState('RageCharging'))
return false;
return super.RelevantTo(P);
}
defaultproperties
{
}

View file

@ -0,0 +1,17 @@
class NiceAvoidMarkerCarnage extends NiceAvoidMarker;
var float healthLevel;
function bool RelevantTo(Pawn P){
local NiceMonster niceZed;
niceZed = NiceMonster(P);
if (niceZed != none && niceZed.default.health <= healthLevel)
{
return true;
}
return false;
}
defaultproperties
{
lifespan = 2.5
}

View file

@ -0,0 +1,11 @@
class NiceAvoidMarkerExplosive extends NiceAvoidMarker;
function bool RelevantTo(Pawn P){
local NiceMonster niceZed;
niceZed = NiceMonster(P);
if(niceZed != none && niceZed.default.Health >= 1000 && NiceZombieFleshpound(P) == none)
return false;
return super.RelevantTo(P);
}
defaultproperties
{
}

View file

@ -0,0 +1,38 @@
class NiceAvoidMarkerFP extends NiceAvoidMarker;
var NiceZombieFleshpound niceFP;
state BigMeanAndScary
{
Begin:
StartleBots();
Sleep(1.0);
GoTo('Begin');
}
function InitFor(NiceMonster V){
if(V != none){
niceFP = NiceZombieFleshpound(V);
SetCollisionSize(niceFP.CollisionRadius * 3, niceFP.CollisionHeight + CollisionHeight);
SetBase(niceFP);
GoToState('BigMeanAndScary');
}
}
function Touch( actor Other ){
if((Pawn(Other) != none) && KFMonsterController(Pawn(Other).Controller) != none && RelevantTo(Pawn(Other)))
KFMonsterController(Pawn(Other).Controller).AvoidThisMonster(niceFP);
}
function bool RelevantTo(Pawn P){
local NiceMonster niceZed;
niceZed = NiceMonster(P);
if(niceZed != none && (niceZed.default.Health >= 1000 || NiceZombieJason(niceZed) != none))
return false;
return (niceFP != none && VSizeSquared(niceFP.Velocity) >= 75 && Super.RelevantTo(P) && niceFP.Velocity dot (P.Location - niceFP.Location) > 0 );
}
function StartleBots(){
local KFMonster P;
if(niceFP != none)
ForEach CollidingActors(class'KFMonster', P, CollisionRadius)
if(RelevantTo(P))
KFMonsterController(P.Controller).AvoidThisMonster(niceFP);
}
defaultproperties
{
}

View file

@ -0,0 +1,11 @@
class NiceAvoidMarkerFlame extends NiceAvoidMarker;
function bool RelevantTo(Pawn P){
local NiceMonster niceZed;
niceZed = NiceMonster(P);
if(niceZed != none && niceZed.bFireImmune)
return false;
return super.RelevantTo(P);
}
defaultproperties
{
}

View file

@ -0,0 +1,29 @@
class NiceAxe extends NiceMeleeWeapon;
defaultproperties
{
weaponRange=80.000000
BloodSkinSwitchArray=0
BloodyMaterialRef="KF_Weapons_Trip_T.melee.axe_bloody_cmb"
bSpeedMeUp=True
Weight=5.000000
StandardDisplayFOV=75.000000
TraderInfoTexture=Texture'KillingFloorHUD.Trader_Weapon_Images.Trader_Axe'
bIsTier2Weapon=True
MeshRef="KF_Weapons_Trip.Axe_Trip"
SkinRefs(0)="KF_Weapons_Trip_T.melee.axe_cmb"
SelectSoundRef="KF_AxeSnd.Axe_Select"
HudImageRef="KillingFloorHUD.WeaponSelect.Axe_unselected"
SelectedHudImageRef="KillingFloorHUD.WeaponSelect.Axe"
FireModeClass(0)=class'NiceAxeFire'
FireModeClass(1)=class'NiceAxeFireB'
AIRating=0.300000
Description="A common two-handed fireman's axe."
DisplayFOV=75.000000
Priority=55
GroupOffset=3
PickupClass=class'NiceAxePickup'
BobDamping=8.000000
AttachmentClass=class'NiceAxeAttachment'
IconCoords=(X1=169,Y1=39,X2=241,Y2=77)
ItemName="Axe"
}

View file

@ -0,0 +1,45 @@
class NiceAxeAttachment extends NiceMeleeAttachment;
defaultproperties
{
MovementAnims(0)="JogF_Axe"
MovementAnims(1)="JogB_Axe"
MovementAnims(2)="JogL_Axe"
MovementAnims(3)="JogR_Axe"
TurnLeftAnim="TurnL_Axe"
TurnRightAnim="TurnR_Axe"
CrouchAnims(0)="CHwalkF_Axe"
CrouchAnims(1)="CHwalkB_Axe"
CrouchAnims(2)="CHwalkL_Axe"
CrouchAnims(3)="CHwalkR_Axe"
CrouchTurnRightAnim="CH_TurnR_Axe"
CrouchTurnLeftAnim="CH_TurnL_Axe"
IdleCrouchAnim="CHIdle_Axe"
IdleWeaponAnim="Idle_Axe"
IdleRestAnim="Idle_Axe"
IdleChatAnim="Idle_Axe"
IdleHeavyAnim="Idle_Axe"
IdleRifleAnim="Idle_Axe"
FireAnims(0)="Attack1_Axe"
FireAnims(1)="Attack2_Axe"
FireAnims(2)="Attack3_Axe"
FireAnims(3)="Attack3_Axe"
FireAltAnims(0)="Attack1_Axe"
FireAltAnims(1)="Attack2_Axe"
FireAltAnims(2)="Attack3_Axe"
FireAltAnims(3)="Attack3_Axe"
FireCrouchAnims(0)="CHAttack1_Axe"
FireCrouchAnims(1)="CHAttack2_Axe"
FireCrouchAnims(2)="CHAttack3_Axe"
FireCrouchAnims(3)="CHAttack3_Axe"
FireCrouchAltAnims(0)="CHAttack1_Axe"
FireCrouchAltAnims(1)="CHAttack2_Axe"
FireCrouchAltAnims(2)="CHAttack3_Axe"
FireCrouchAltAnims(3)="CHAttack3_Axe"
HitAnims(0)="HitF_Axe"
HitAnims(1)="HitB_Axe"
HitAnims(2)="HitL_Axe"
HitAnims(3)="HitR_Axe"
PostFireBlendStandAnim="Blend_Axe"
PostFireBlendCrouchAnim="CHBlend_Axe"
MeshRef="KF_Weapons3rd_Trip.Axe_3rd"
}

View file

@ -0,0 +1,18 @@
class NiceAxeFire extends NiceMeleeFire;
defaultproperties
{
weaponRange=90.000000
damageDelay=0.600000
FireAnims(0)="Fire"
FireAnims(1)="Fire2"
FireAnims(2)="fire3"
FireAnims(3)="Fire4"
HitEffectClass=Class'KFMod.AxeHitEffect'
MeleeHitSoundRefs(0)="KF_AxeSnd.Axe_HitFlesh"
WideDamageMinHitAngle=0.750000
DamageType=class'NiceDamTypeAxe'
DamageMax=175
FireAnimRate=0.893333
FireRate=1.100000
BotRefireRate=0.850000
}

View file

@ -0,0 +1,14 @@
class NiceAxeFireB extends NiceMeleeFire;
defaultproperties
{
weaponRange=90.000000
damageDelay=0.760000
FireAnims(0)="PowerAttack"
HitEffectClass=Class'KFMod.AxeHitEffect'
MeleeHitSoundRefs(0)="KF_AxeSnd.Axe_HitFlesh"
DamageType=class'NiceDamTypeAxe'
DamageMax=275
bWaitForRelease=True
FireRate=1.333000
BotRefireRate=0.850000
}

View file

@ -0,0 +1,21 @@
class NiceAxePickup extends NiceWeaponPickup;
defaultproperties
{
Weight=5.000000
cost=250
PowerValue=56
SpeedValue=32
RangeValue=-20
Description="A sturdy fireman's axe."
ItemName="Axe"
ItemShortName="Axe"
CorrespondingPerkIndex=4
VariantClasses(0)=Class'KFMod.GoldenKatanaPickup'
InventoryType=class'NiceAxe'
PickupMessage="You got the Fire Axe."
PickupSound=Sound'KF_AxeSnd.Axe_Pickup'
PickupForce="AssaultRiflePickup"
StaticMesh=StaticMesh'KF_pickups_Trip.melee.Axe_Pickup'
CollisionRadius=27.000000
CollisionHeight=5.000000
}

View file

@ -0,0 +1,38 @@
class NiceBallisticHarpoon extends NiceBullet;
// Have we added this harpoon to a stuck projectiles list?
var bool bAddedMyself;
simulated function Tick(float delta){
local NiceSealSquealHarpoonBomber harpoonWeap;
if(bInitFinished && !bAddedMyself && bStuck && nicePlayer == localPlayer){
bAddedMyself = true;
harpoonWeap = NiceSealSquealHarpoonBomber(sourceWeapon);
harpoonWeap.stuckProjectiles[harpoonWeap.stuckProjectiles.Length] = stuckID;
}
super.Tick(delta);
}
function KillBullet(){
local int index;
local NiceSealSquealHarpoonBomber harpoonWeap;
if(bStuck && sourceWeapon != none){
harpoonWeap = NiceSealSquealHarpoonBomber(sourceWeapon);
for(index = 0;index < harpoonWeap.stuckProjectiles.Length;index ++)
if(harpoonWeap.stuckProjectiles[index] == stuckID){
NiceSealSquealHarpoonBomber(sourceWeapon).stuckProjectiles[index] = -1;
break;
}
}
super.KillBullet();
}
defaultproperties
{
charMinExplosionDist=300.000000
bDisableComplexMovement=False
movementFallTime=1.000000
TrailClass=Class'KFMod.SealSquealFuseEmitter'
trailXClass=None
regularImpact=(noiseRef="KF_FY_SealSquealSND.WEP_Harpoon_Hit_Flesh")
explosionImpact=(bImportanEffect=True,decalClass=Class'KFMod.KFScorchMark',EmitterClass=Class'KFMod.KFNadeLExplosion',emitterShiftWall=20.000000,emitterShiftPawn=20.000000,noiseRef="KF_FY_SealSquealSND.WEP_Harpoon_Explode",noiseVolume=2.000000)
disintegrationImpact=(EmitterClass=Class'KFMod.SirenNadeDeflect',noiseRef="Inf_Weapons.faust_explode_distant02",noiseVolume=2.000000)
StaticMeshRef="KF_IJC_Halloween_Weps2.Harpoon_Projectile"
AmbientSoundRef="KF_IJC_HalloweenSnd.KF_FlarePistol_Projectile_Loop"
}

View file

@ -0,0 +1,14 @@
class NiceBallisticNade extends NiceBullet;
defaultproperties
{
charMinExplosionDist=250.000000
bDisableComplexMovement=False
movementAcceleration=(Z=-490.000000)
movementFallTime=1.000000
TrailClass=Class'ROEffects.PanzerfaustTrail'
trailXClass=None
explosionImpact=(bImportanEffect=True,decalClass=Class'KFMod.KFScorchMark',EmitterClass=Class'KFMod.KFNadeLExplosion',emitterShiftWall=20.000000,emitterShiftPawn=20.000000,noiseRef="KF_GrenadeSnd.Nade_Explode_1",noiseVolume=2.000000)
disintegrationImpact=(EmitterClass=Class'KFMod.SirenNadeDeflect',noiseRef="Inf_Weapons.faust_explode_distant02",noiseVolume=2.000000)
StaticMeshRef="kf_generic_sm.40mm_Warhead"
DrawScale=3.000000
}

View file

@ -0,0 +1,11 @@
class NiceBenelliAmmo extends NiceAmmo;
defaultproperties
{
WeaponPickupClass=class'NiceBenelliPickup'
AmmoPickupAmount=6
MaxAmmo=60
InitialAmount=15
PickupClass=class'NiceBenelliAmmoPickup'
IconMaterial=Texture'KillingFloorHUD.Generic.HUD'
IconCoords=(X1=451,Y1=445,X2=510,Y2=500)
}

View file

@ -0,0 +1,8 @@
class NiceBenelliAmmoPickup extends NiceAmmoPickup;
defaultproperties
{
AmmoAmount=6
InventoryType=class'NiceBenelliAmmo'
PickupMessage="12-Gauge Shells"
StaticMesh=None
}

View file

@ -0,0 +1,21 @@
class NiceBenelliAttachment extends NiceShotgunAttachment;
defaultproperties
{
FireAnims(0)="Fire_Benelli"
FireAnims(1)="Fire_Benelli"
FireAnims(2)="Fire_Benelli"
FireAnims(3)="Fire_Benelli"
FireAltAnims(0)="Fire_Benelli"
FireAltAnims(1)="Fire_Benelli"
FireAltAnims(2)="Fire_Benelli"
FireAltAnims(3)="Fire_Benelli"
FireCrouchAnims(0)="CHFire_Benelli"
FireCrouchAnims(1)="CHFire_Benelli"
FireCrouchAnims(2)="CHFire_Benelli"
FireCrouchAnims(3)="CHFire_Benelli"
FireCrouchAltAnims(0)="CHFire_Benelli"
FireCrouchAltAnims(1)="CHFire_Benelli"
FireCrouchAltAnims(2)="CHFire_Benelli"
FireCrouchAltAnims(3)="CHFire_Benelli"
MeshRef="KF_Weapons3rd3_Trip.Benelli_3rd"
}

View file

@ -0,0 +1,14 @@
class NiceBenelliFire extends NiceShotgunFire;
defaultproperties
{
KickMomentum=(X=-45.000000,Z=10.000000)
ShellEjectClass=Class'ROEffects.KFShellEjectBenelli'
ShellEjectBoneName="Shell_eject"
DamageType=class'NiceDamTypeBenelli'
FireAnimRate=1.000000
FireRate=0.200000
DamageMax=63
AmmoClass=class'NiceBenelliAmmo'
Spread=1125.000000
BotRefireRate=0.200000
}

View file

@ -0,0 +1,25 @@
class NiceBenelliPickup extends NiceWeaponPickup;
defaultproperties
{
Weight=8.000000
cost=500
AmmoCost=13
BuyClipSize=6
PowerValue=70
SpeedValue=60
RangeValue=15
Description="A military tactical shotgun with semi automatic fire capability. Holds up to 6 shells. "
ItemName="Benelli shotgun"
ItemShortName="Benelli shotgun"
AmmoItemName="12-gauge shells"
CorrespondingPerkIndex=1
EquipmentCategoryID=2
VariantClasses(0)=Class'KFMod.GoldenBenelliPickup'
InventoryType=class'NiceBenelliShotgun'
PickupMessage="You got the Benelli shotgun"
PickupSound=Sound'KF_M4ShotgunSnd.foley.WEP_Benelli_Foley_Pickup'
PickupForce="AssaultRiflePickup"
StaticMesh=StaticMesh'KF_pickups3_Trip.Rifles.Benelli_Pickup'
CollisionRadius=35.000000
CollisionHeight=5.000000
}

View file

@ -0,0 +1,52 @@
class NiceBenelliShotgun extends NiceWeapon;
simulated function fillSubReloadStages(){
// Loading 6 shells during 174 frames tops, with first shell loaded at frame 22, with 24 frames between load moments
generateReloadStages(6, 174, 22, 24);
}
defaultproperties
{
bChangeClipIcon=True
hudClipTexture=Texture'KillingFloorHUD.HUD.Hud_Single_Bullet'
reloadType=RTYPE_SINGLE
FirstPersonFlashlightOffset=(X=-25.000000,Y=-18.000000,Z=8.000000)
MagCapacity=6
ReloadRate=0.750000
ReloadAnim="Reload"
ReloadAnimRate=1.200000
bHoldToReload=True
WeaponReloadAnim="Reload_Shotgun"
Weight=5.000000
bTorchEnabled=True
bHasAimingMode=True
IdleAimAnim="Idle_Iron"
StandardDisplayFOV=65.000000
SleeveNum=2
TraderInfoTexture=Texture'KillingFloor2HUD.Trader_Weapon_Icons.Trader_Beneli'
bIsTier2Weapon=True
MeshRef="KF_Wep_Benelli.Benelli_Trip"
SkinRefs(0)="KF_Weapons4_Trip_T.Weapons.Benelli_M4_cmb"
SkinRefs(1)="KF_Weapons2_Trip_T.Special.Aimpoint_sight_shdr"
SelectSoundRef="KF_M4ShotgunSnd.WEP_Benelli_Foley_Select"
HudImageRef="KillingFloor2HUD.WeaponSelect.Beneli_unselected"
SelectedHudImageRef="KillingFloor2HUD.WeaponSelect.Beneli"
PlayerIronSightFOV=70.000000
ZoomedDisplayFOV=40.000000
FireModeClass(0)=class'NiceBenelliFire'
FireModeClass(1)=Class'KFMod.NoFire'
PutDownAnim="PutDown"
AIRating=0.600000
CurrentRating=0.600000
bShowChargingBar=True
Description="A military tactical shotgun with semi automatic fire capability. Holds up to 6 shells. "
DisplayFOV=65.000000
Priority=170
InventoryGroup=3
GroupOffset=9
PickupClass=class'NiceBenelliPickup'
PlayerViewOffset=(X=20.000000,Y=18.750000,Z=-7.500000)
BobDamping=7.000000
AttachmentClass=class'NiceBenelliAttachment'
IconCoords=(X1=169,Y1=172,X2=245,Y2=208)
ItemName="Benelli shotgun"
TransientSoundVolume=1.000000
}

View file

@ -0,0 +1,8 @@
class NiceBlockHitEmitter extends MetalHitEmitter;
defaultproperties
{
ImpactSounds(0)=None
ImpactSounds(1)=None
ImpactSounds(2)=None
RemoteRole=ROLE_SimulatedProxy
}

View file

@ -0,0 +1,9 @@
class NiceBlowerThrower extends BlowerThrower;
defaultproperties
{
AppID=0
FireModeClass(0)=class'NiceBlowerThrowerFire'
FireModeClass(1)=class'NiceBlowerThrowerAltFire'
PickupClass=class'NiceBlowerThrowerPickup'
ItemName="BlowerThrower NW"
}

View file

@ -0,0 +1,5 @@
class NiceBlowerThrowerAltFire extends BlowerThrowerAltFire;
defaultproperties
{
AmmoClass=class'NiceBlowerThrowerAmmo'
}

View file

@ -0,0 +1,7 @@
class NiceBlowerThrowerAmmo extends BlowerThrowerAmmo;
#EXEC OBJ LOAD FILE=KillingFloorHUD.utx
defaultproperties
{
MaxAmmo=400
PickupClass=class'NiceBlowerThrowerAmmoPickup'
}

View file

@ -0,0 +1,5 @@
class NiceBlowerThrowerAmmoPickup extends BlowerThrowerAmmoPickup;
defaultproperties
{
InventoryType=class'NiceBlowerThrowerAmmo'
}

View file

@ -0,0 +1,5 @@
class NiceBlowerThrowerFire extends BlowerThrowerFire;
defaultproperties
{
AmmoClass=class'NiceBlowerThrowerAmmo'
}

View file

@ -0,0 +1,8 @@
class NiceBlowerThrowerPickup extends BlowerThrowerPickup;
defaultproperties
{
ItemName="Blower Thrower Bile Launcher NW"
ItemShortName="Blower Thrower NW"
InventoryType=class'NiceBlowerThrower'
PickupMessage="You got the BlowerThrower NW"
}

View file

@ -0,0 +1,103 @@
class NiceBoomStick extends NiceWeapon;
#EXEC OBJ LOAD FILE=KillingFloorHUD.utx
var float glueTiming;
var float firstShellTiming, secondShellTiming, jumpTiming;
var const string firstShellStr, secondShellStr, jumpStr;
simulated function PostBeginPlay(){
local EventRecord record;
local AutoReloadAnimDesc reloadDesc;
// Setup animation timings
autoReloadsDescriptions.Length = 0;
reloadDesc.canInterruptFrame = 0.056;
reloadDesc.trashStartFrame = secondShellTiming;
reloadDesc.resumeFrame = 0.056;
reloadDesc.speedFrame = 0.056;
// Setup all possible fire animations
reloadDesc.animName = 'Fire_Both';
autoReloadsDescriptions[0] = reloadDesc;
reloadDesc.animName = 'Fire_Both_Iron';
autoReloadsDescriptions[1] = reloadDesc;
reloadDesc.animName = 'Fire_Last';
autoReloadsDescriptions[2] = reloadDesc;
reloadDesc.animName = 'Fire_Last_Iron';
autoReloadsDescriptions[3] = reloadDesc;
// Setup reload events
record.eventName = jumpStr;
record.eventFrame = jumpTiming;
relEvents[relEvents.Length] = record;
record.eventName = firstShellStr;
record.eventFrame = firstShellTiming;
relEvents[relEvents.Length] = record;
record.eventName = secondShellStr;
record.eventFrame = secondShellTiming;
relEvents[relEvents.Length] = record;
super.PostBeginPlay();
}
simulated function ReloadEvent(string eventName){
if(eventName ~= jumpStr && GetMagazineAmmo() > 0)
SetAnimFrame(glueTiming);
if(eventName ~= firstShellStr)
MagAmmoRemainingClient = Min(1, AmmoAmount(0));
else if(eventName ~= secondShellStr)
MagAmmoRemainingClient = Min(2, AmmoAmount(0));
ServerSetMagSize(MagAmmoRemainingClient, bRoundInChamber, Level.TimeSeconds);
}
simulated function AddAutoReloadedAmmo(){
MagAmmoRemainingClient = Min(2, AmmoAmount(0));
ServerSetMagSize(MagAmmoRemainingClient, bRoundInChamber, Level.TimeSeconds);
}
simulated function bool AltFireCanForceInterruptReload(){
return (GetMagazineAmmo() > 0);
}
defaultproperties
{
glueTiming=0.633330
firstShellTiming=0.555550
secondShellTiming=0.733330
jumpTiming=0.388880
firstShellStr="firstShell"
secondShellStr="secondShellStr"
jumpStr="jumpStr"
bChangeClipIcon=True
hudClipTexture=Texture'KillingFloorHUD.HUD.Hud_Single_Bullet'
reloadType=RTYPE_AUTO
ForceZoomOutOnFireTime=0.010000
ForceZoomOutOnAltFireTime=0.010000
MagCapacity=2
Weight=6.000000
ReloadRate=2.250000
ReloadAnim="Reload"
ReloadAnimRate=1.100000
bHoldToReload=True
WeaponReloadAnim="Reload_HuntingShotgun"
bHasAimingMode=True
IdleAimAnim="Idle_Iron"
StandardDisplayFOV=55.000000
TraderInfoTexture=Texture'KillingFloorHUD.Trader_Weapon_Images.Trader_Hunting_Shotgun'
bIsTier2Weapon=True
MeshRef="KF_Weapons_Trip.BoomStick_Trip"
SkinRefs(0)="KF_Weapons_Trip_T.Shotguns.boomstick_cmb"
SelectSoundRef="KF_DoubleSGSnd.2Barrel_Select"
HudImageRef="KillingFloorHUD.WeaponSelect.BoomStic_unselected"
SelectedHudImageRef="KillingFloorHUD.WeaponSelect.BoomStick"
PlayerIronSightFOV=70.000000
ZoomedDisplayFOV=40.000000
FireModeClass(0)=class'NiceBoomStickAltFire'
FireModeClass(1)=class'NiceBoomStickFire'
PutDownAnim="PutDown"
AIRating=0.900000
CurrentRating=0.900000
bSniping=False
Description="A double barreled shotgun used by big game hunters. It fires two slugs simultaneously and can bring down even the largest targets, quickly."
DisplayFOV=55.000000
Priority=160
InventoryGroup=4
GroupOffset=2
PickupClass=class'NiceBoomStickPickup'
PlayerViewOffset=(X=8.000000,Y=14.000000,Z=-8.000000)
BobDamping=6.000000
AttachmentClass=class'NiceBoomStickAttachment'
ItemName="Hunting Shotgun"
bUseDynamicLights=True
TransientSoundVolume=1.000000
}

View file

@ -0,0 +1,26 @@
class NiceBoomStickAltFire extends NiceBoomStickFire;
// Overload to force last shot to have a different animation with reload
// NICETODO: uncomment this
function name GetCorrectAnim(bool bLoop, bool bAimed) {
if(currentContext.sourceWeapon != none && currentContext.sourceWeapon.MagAmmoRemainingClient > 0)
return super.GetCorrectAnim(bLoop, bAimed);
if(bAimed)
return 'Fire_Last_Iron';
else
return 'Fire_Last';
return FireAnim;
}
defaultproperties
{
KickMomentum=(X=-50.000000,Z=22.000000)
FireAimedAnim="Fire_Iron"
maxVerticalRecoilAngle=1500
FireSoundRef="KF_DoubleSGSnd.2Barrel_Fire"
StereoFireSoundRef="KF_DoubleSGSnd.2Barrel_FireST"
TransientSoundVolume=1.800000
FireAnim="Fire"
AmmoPerFire=1
ShakeRotMag=(X=50.000000,Y=50.000000,Z=400.000000)
ShakeRotTime=5.000000
ShakeOffsetTime=3.000000
}

View file

@ -0,0 +1,51 @@
class NiceBoomStickAttachment extends NiceAttachment;
defaultproperties
{
mMuzFlashClass=Class'ROEffects.MuzzleFlash3rdKar'
mShellCaseEmitterClass=Class'KFMod.KFShotgunShellSpewer'
MovementAnims(0)="JogF_HuntingShotgun"
MovementAnims(1)="JogB_HuntingShotgun"
MovementAnims(2)="JogL_HuntingShotgun"
MovementAnims(3)="JogR_HuntingShotgun"
TurnLeftAnim="TurnL_HuntingShotgun"
TurnRightAnim="TurnR_HuntingShotgun"
CrouchAnims(0)="CHwalkF_HuntingShotgun"
CrouchAnims(1)="CHwalkB_HuntingShotgun"
CrouchAnims(2)="CHwalkL_HuntingShotgun"
CrouchAnims(3)="CHwalkR_HuntingShotgun"
WalkAnims(0)="WalkF_HuntingShotgun"
WalkAnims(1)="WalkB_HuntingShotgun"
WalkAnims(2)="WalkL_HuntingShotgun"
WalkAnims(3)="WalkR_HuntingShotgun"
CrouchTurnRightAnim="CH_TurnR_HuntingShotgun"
CrouchTurnLeftAnim="CH_TurnL_HuntingShotgun"
IdleCrouchAnim="CHIdle_HuntingShotgun"
IdleWeaponAnim="Idle_HuntingShotgun"
IdleRestAnim="Idle_HuntingShotgun"
IdleChatAnim="Idle_HuntingShotgun"
IdleHeavyAnim="Idle_HuntingShotgun"
IdleRifleAnim="Idle_HuntingShotgun"
FireAnims(0)="Fire_HuntingShotgun"
FireAnims(1)="Fire_HuntingShotgun"
FireAnims(2)="Fire_HuntingShotgun"
FireAnims(3)="Fire_HuntingShotgun"
FireAltAnims(0)="Fire_HuntingShotgun"
FireAltAnims(1)="Fire_HuntingShotgun"
FireAltAnims(2)="Fire_HuntingShotgun"
FireAltAnims(3)="Fire_HuntingShotgun"
FireCrouchAnims(0)="CHFire_HuntingShotgun"
FireCrouchAnims(1)="CHFire_HuntingShotgun"
FireCrouchAnims(2)="CHFire_HuntingShotgun"
FireCrouchAnims(3)="CHFire_HuntingShotgun"
FireCrouchAltAnims(0)="CHFire_HuntingShotgun"
FireCrouchAltAnims(1)="CHFire_HuntingShotgun"
FireCrouchAltAnims(2)="CHFire_HuntingShotgun"
FireCrouchAltAnims(3)="CHFire_HuntingShotgun"
HitAnims(0)="HitF_HuntingShotgun"
HitAnims(1)="HitB_HuntingShotgun"
HitAnims(2)="HitL_HuntingShotgun"
HitAnims(3)="HitR_HuntingShotgun"
PostFireBlendStandAnim="Blend_HuntingShotgun"
PostFireBlendCrouchAnim="CHBlend_HuntingShotgun"
MeshRef="KF_Weapons3rd_Trip.HuntingShot_3rd"
}

View file

@ -0,0 +1,63 @@
class NiceBoomStickFire extends NiceShotgunFire;
var Emitter Flash2Emitter;
var name MuzzleBoneLeft;
var name MuzzleBoneRight;
simulated function InitEffects(){
if((Level.NetMode == NM_DedicatedServer) || (AIController(Instigator.Controller) != none))
return;
if((FlashEmitterClass != none) && ((FlashEmitter == none) || FlashEmitter.bDeleteMe)){
FlashEmitter = Weapon.Spawn(FlashEmitterClass);
Weapon.AttachToBone(FlashEmitter, MuzzleBoneLeft);
}
if((FlashEmitterClass != none) && ((Flash2Emitter == none) || Flash2Emitter.bDeleteMe)){
Flash2Emitter = Weapon.Spawn(FlashEmitterClass);
Weapon.AttachToBone(Flash2Emitter, MuzzleBoneRight);
}
if((SmokeEmitterClass != none) && ((SmokeEmitter == none) || SmokeEmitter.bDeleteMe))
SmokeEmitter = Weapon.Spawn(SmokeEmitterClass);
}
simulated function DestroyEffects(){
super.DestroyEffects();
if(Flash2Emitter != none)
Flash2Emitter.Destroy();
}//MEANTODO
function FlashMuzzleFlash(){
if(currentContext.sourceWeapon == none)
return;
if(currentContext.sourceWeapon.MagAmmoRemainingClient == 2){
if(Flash2Emitter != none)
Flash2Emitter.Trigger(Weapon, Instigator);
}
else if(FlashEmitter != none)
FlashEmitter.Trigger(Weapon, Instigator);
}
defaultproperties
{
MuzzleBoneLeft="Tip_Left"
MuzzleBoneRight="Tip_Right"
FireIncompleteAnim="Fire_Last"
FireIncompleteAimedAnim="Fire_Last_Iron"
bCanFireIncomplete=True
ProjPerFire=10
KickMomentum=(X=-105.000000,Z=55.000000)
FireAimedAnim="Fire_Both_Iron"
RecoilRate=0.070000
maxVerticalRecoilAngle=3200
FireSoundRef="KF_DoubleSGSnd.2Barrel_Fire_Dual"
StereoFireSoundRef="KF_DoubleSGSnd.2Barrel_Fire_DualST"
NoAmmoSoundRef="KF_DoubleSGSnd.2Barrel_DryFire"
DamageType=class'NiceDamTypeDBShotgun'
DamageMax=63
TransientSoundVolume=1.900000
FireAnim="Fire_Both"
FireRate=0.000000
AmmoClass=class'NiceDBShotgunAmmo'
AmmoPerFire=2
ShakeRotMag=(X=75.000000,Y=75.000000,Z=600.000000)
ShakeRotTime=6.000000
ShakeOffsetTime=3.500000
BotRefireRate=2.500000
aimerror=2.000000
Spread=2000.000000
FireAnimRate=1.25
}

View file

@ -0,0 +1,24 @@
class NiceBoomStickPickup extends NiceWeaponPickup;
var int SingleShotCount;
defaultproperties
{
cost=750
AmmoCost=5
BuyClipSize=2
PowerValue=90
SpeedValue=30
RangeValue=12
Description="A double barreled shotgun used by big game hunters."
ItemName="Hunting Shotgun"
ItemShortName="Hunting Shotgun"
AmmoItemName="12-gauge Hunting shells"
CorrespondingPerkIndex=1
EquipmentCategoryID=3
InventoryType=class'NiceBoomStick'
PickupMessage="You got the Hunting Shotgun"
PickupSound=Sound'KF_DoubleSGSnd.2Barrel_Pickup'
PickupForce="AssaultRiflePickup"
StaticMesh=StaticMesh'KF_pickups_Trip.Shotgun.boomstick_pickup'
CollisionRadius=35.000000
CollisionHeight=5.000000
}

View file

@ -0,0 +1,90 @@
class NiceBossHPNeedle extends Decoration
NotPlaceable;
#exec obj load file="NewPatchSM.usx"
simulated function DroppedNow()
{
SetCollision(True);
SetPhysics(PHYS_Falling);
bFixedRotationDir = True;
RotationRate = RotRand(True);
}
simulated function HitWall( vector HitNormal, actor HitWall )
{
local rotator R;
if( VSize(Velocity)<40 )
{
SetPhysics(PHYS_none);
R.Roll = Rand(65536);
R.Yaw = Rand(65536);
SetRotation(R);
Return;
}
Velocity = MirrorVectorByNormal(Velocity,HitNormal)*0.75;
if( HitWall!=none && HitWall.Physics!=PHYS_none )
Velocity+=HitWall.Velocity;
}
simulated function Landed( vector HitNormal )
{
HitWall(HitNormal,none);
}
function TakeDamage( int NDamage, Pawn instigatedBy, Vector hitlocation,
Vector momentum, class<DamageType> damageType, optional int HitIndex)
{
if( Physics==PHYS_none )
{
SetPhysics(PHYS_Falling);
bFixedRotationDir = True;
RotationRate = RotRand(True);
Velocity = vect(0,0,0);
}
Velocity+=momentum/10;
}
simulated function Destroyed();
function Bump( actor Other );
singular function PhysicsVolumeChange( PhysicsVolume NewVolume );
// Overriden so it doesn't damage the patriarch when he drops a needle!
singular function BaseChange()
{
if( Velocity.Z < -500 )
TakeDamage( (1-Velocity.Z/30),Instigator,Location,vect(0,0,0) , class'Crushed');
if( base == none )
{
if ( !bInterpolating && bPushable && (Physics == PHYS_none) )
SetPhysics(PHYS_Falling);
}
else if( Pawn(Base) != none )
{
//Base.TakeDamage( (1-Velocity.Z/400)* mass/Base.Mass,Instigator,Location,0.5 * Velocity , class'Crushed');
Velocity.Z = 100;
if (FRand() < 0.5)
Velocity.X += 70;
else
Velocity.Y += 70;
SetPhysics(PHYS_Falling);
}
else if( Decoration(Base)!=none && Velocity.Z<-500 )
{
Base.TakeDamage((1 - Mass/Base.Mass * Velocity.Z/30), Instigator, Location, 0.2 * Velocity, class'Crushed');
Velocity.Z = 100;
if (FRand() < 0.5)
Velocity.X += 70;
else
Velocity.Y += 70;
SetPhysics(PHYS_Falling);
}
else
instigator = none;
}
defaultproperties
{
DrawType=DT_StaticMesh
StaticMesh=StaticMesh'NewPatchSM.BossSyringe'
bStatic=False
RemoteRole=ROLE_None
LifeSpan=300.000000
CollisionRadius=4.000000
CollisionHeight=4.000000
bCollideWorld=True
bProjTarget=True
bBounce=True
}

View file

@ -0,0 +1,21 @@
class NiceBossLAWProj extends LAWProj;
//-----------------------------------------------------------------------------
// PostBeginPlay
//-----------------------------------------------------------------------------
simulated function PostBeginPlay()
{
// Difficulty Scaling
if(Level.Game != none){
if(Level.Game.GameDifficulty >= 5.0) // Hell on Earth & Suicidal
damage = default.damage * 1.3;
else
damage = default.damage * 1.0;
}
super.PostBeginPlay();
}
defaultproperties
{
ArmDistSquared=0.000000
Damage=200.000000
MyDamageType=Class'KFMod.DamTypeFrag'
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,331 @@
//======================================================================================================================
// NicePack / NiceBulletAdapter
//======================================================================================================================
// Temporary stand-in for future functionality.
//======================================================================================================================
// 'Nice pack' source
// Do whatever the fuck you want with it
// Author: dkanus
// E-mail: dkanus@gmail.com
//======================================================================================================================
class NiceBulletAdapter extends Object;
var const int BigZedMinHealth; // If zed's base Health >= this value, zed counts as Big
var const int MediumZedMinHealth; // If zed's base Health >= this value, zed counts as Medium-size
static function Explode(
NiceBullet bullet,
NiceReplicationInfo niceRI,
Vector hitLocation,
optional Actor explosionTarget
) {
if (!bullet.bGhost) {
niceRI.ServerExplode(
bullet.charExplosionDamage,
bullet.charExplosionRadius,
bullet.charExplosionExponent,
bullet.charExplosionDamageType,
bullet.charExplosionMomentum,
hitLocation,
bullet.instigator,
explosionTarget,
Vector(bullet.Rotation),
bullet.bStuck
);
if (KFMonster(bullet.base) != none && bullet.bStuck && bullet.bStuckToHead) {
niceRI.ServerDealDamage(
KFMonster(bullet.base),
bullet.charExplosionDamage,
bullet.instigator,
hitLocation,
bullet.charExplosionMomentum * vect(0, 0, -1),
bullet.charExplosionDamageType,
1.0
);
}
}
}
static function HandleCalibration (
bool isHeadshot,
NiceHumanPawn nicePawn,
NiceMonster targetZed
) {
if (nicePawn == none || nicePawn.currentCalibrationState != CALSTATE_ACTIVE) {
return;
}
nicePawn.ServerUpdateCalibration(isHeadshot, targetZed);
}
static function HitWall(
NiceBullet bullet,
NiceReplicationInfo niceRI,
Actor targetWall,
Vector hitLocation,
Vector hitNormal
) {
local NicePlayerController nicePlayer;
nicePlayer = NicePlayerController(bullet.Instigator.Controller);
if (nicePlayer == none) {
return;
}
if (!bullet.bAlreadyHitZed) {
HandleCalibration(false, NiceHumanPawn(bullet.Instigator), none);
}
if (
!targetWall.bStatic &&
!targetWall.bWorldGeometry &&
nicePlayer != none &&
(nicePlayer.wallHitsLeft > 0 || Projectile(targetWall) != none)
) {
niceRI.ServerDealDamage(
targetWall,
bullet.charOrigDamage,
bullet.Instigator,
hitLocation,
bullet.charMomentumTransfer * hitNormal,
bullet.charDamageType
);
nicePlayer.wallHitsLeft --;
}
}
static function HandleScream(
NiceBullet bullet,
NiceReplicationInfo niceRI,
Vector location,
Vector entryDirection
) {
bullet.charIsDud = true;
}
static function HitPawn(
NiceBullet bullet,
NiceReplicationInfo niceRI,
KFPawn targetPawn,
Vector hitLocation,
Vector hitNormal,
array<int> hitPoints
) {
local NiceMedicProjectile niceDart;
niceDart = NiceMedicProjectile(bullet);
if (niceDart == none) {
niceRI.ServerDealDamage(
targetPawn,
bullet.charDamage,
bullet.instigator,
HitLocation,
hitNormal * bullet.charMomentumTransfer,
bullet.charDamageType
);
} else {
niceRI.ServerHealTarget(NiceHumanPawn(targetPawn), bullet.charDamage, bullet.instigator);
}
}
static function HitZed(
NiceBullet bullet,
NiceReplicationInfo niceRI,
KFMonster kfZed,
Vector hitLocation,
Vector hitNormal,
float headshotLevel
) {
local bool bIsHeadshot, bIsPreciseHeadshot;
local float actualDamage;
local int lockonTicks;
local float lockOnTickRate;
local float angle;
local NiceHumanPawn nicePawn;
local NicePlayerController nicePlayer;
local class<NiceVeterancyTypes> niceVet;
nicePlayer = NicePlayerController(bullet.Instigator.Controller);
if (
nicePlayer != none &&
nicePlayer.abilityManager != none &&
nicePlayer.abilityManager.IsAbilityActive(class'NiceSkillEnforcerBruteA'.default.abilityID)
) {
headshotLevel = 0.0;
}
bIsHeadshot = (headshotLevel > 0.0);
bIsPreciseHeadshot = (headshotLevel > bullet.charDamageType.default.prReqPrecise);
if (!bullet.bAlreadyHitZed || bIsHeadshot) {
HandleCalibration(bIsHeadshot, NiceHumanPawn(bullet.Instigator), NiceMonster(kfZed));
}
if (bIsHeadshot && bullet.sourceWeapon != none) {
bullet.sourceWeapon.lastHeadshotTime = bullet.Level.TimeSeconds;
}
if (nicePlayer == none) {
return;
}
nicePawn = NiceHumanPawn(bullet.instigator);
if (
!bIsHeadshot &&
nicePawn != none &&
nicePlayer.abilityManager != none &&
nicePlayer.abilityManager.IsAbilityActive(class'NiceSkillSharpshooterReaperA'.default.abilityID)
) {
nicePawn.ServerCooldownAbility(class'NiceSkillSharpshooterReaperA'.default.abilityID);
}
niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo));
if (bullet.charCausePain) {
actualDamage = bullet.charOrigDamage;
} else {
actualDamage = bullet.charDamage;
}
if (headshotLevel > 0) {
actualDamage *= bullet.charContiniousBonus;
}
if (bullet.bGrazing) {
actualDamage *= class'NiceSkillSupportGraze'.default.grazeDamageMult;
}
bullet.bGrazing = false;
if (
kfZed == bullet.lockonZed &&
bullet.lockonTime > bullet.sourceWeapon.stdFireRate &&
niceVet != none &&
niceVet.static.hasSkill(nicePlayer, class'NiceSkillSharpshooterKillConfirmed')
) {
lockOnTickRate =class'NiceSkillSharpshooterKillConfirmed'.default.stackDelay;
lockonTicks = Ceil(bullet.lockonTime / lockOnTickRate) - 1;
lockonTicks = Min(class'NiceSkillSharpshooterKillConfirmed'.default.maxStacks, lockonTicks);
// actualDamage *= 1.0 +
// 0.5 * lockonTicks * (lockonTicks + 1) * class'NiceSkillSharpshooterKillConfirmed'.default.damageBonus;
// damageMod *= 1.0 + lockonTicks * class'NiceSkillSharpshooterKillConfirmed'.default.damageBonus;
actualDamage *= 1.0 + lockonTicks * class'NiceSkillSharpshooterKillConfirmed'.default.damageBonus;
}
if (!bullet.bGhost) {
niceRI.ServerDealDamage(
kfZed,
actualDamage,
bullet.instigator,
hitLocation,
bullet.charMomentumTransfer * hitNormal,
bullet.charDamageType,
headshotLevel,
bullet.lockonTime
);
}
//// Handle angled shots
angle = asin(hitNormal.Z);
// Apply angled shots
if ((angle > 0.8 || angle < -0.45) && bullet.bCanAngleDamage && kfZed != none) {
bullet.bCanAngleDamage = false;
bullet.bAlreadyHitZed = true;
if (ZedPenetration(bullet.charDamage, bullet, kfZed, bIsHeadshot, bIsPreciseHeadshot)) {
HitZed(bullet, niceRI, kfZed, hitLocation, hitNormal, headshotLevel);
}
}
//// 'Bore' support skill
if (
niceVet != none &&
nicePlayer.IsZedTimeActive() &&
bullet.insideBouncesLeft > 0 &&
niceVet.static.hasSkill(nicePlayer, class'NiceSkillSupportZEDBore')
) {
// Count one bounce
bullet.insideBouncesLeft --;
// Swap head-shot level
if (headshotLevel <= 0.0) {
headshotLevel = class'NiceSkillSupportZEDBore'.default.minHeadshotPrecision;
} else {
headshotLevel = -headshotLevel;
}
// Deal next batch of damage
ZedPenetration(bullet.charDamage, bullet, kfZed, false, false);
HitZed(bullet, niceRI, kfZed, hitLocation, hitNormal, headshotLevel);
}
bullet.insideBouncesLeft = 2;
}
static function bool ZedPenetration(
out float Damage,
NiceBullet bullet,
KFMonster targetZed,
bool bIsHeadshot,
bool bIsPreciseHeadshot
) {
local float reductionMod;
local NiceMonster niceZed;
local NicePlayerController nicePlayer;
local int actualMaxPenetrations;
local class<NiceVeterancyTypes> niceVet;
local class<NiceWeaponDamageType> niceDmgType;
// True if we can penetrate even body, but now penetrating a head and shouldn't reduce damage too much
local bool bEasyHeadPenetration;
// Init variables
niceZed = NiceMonster(targetZed);
nicePlayer = NicePlayerController(bullet.Instigator.Controller);
niceVet = none;
if (nicePlayer != none) {
niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo));
}
niceDmgType = bullet.charDamageType;
bEasyHeadPenetration = bIsHeadshot && !niceDmgType.default.bPenetrationHSOnly;
reductionMod = 1.0f;
// Apply zed reduction and perk reduction of reduction`
if (niceZed != none) {
// Railgun skill exception
if (
niceVet != none &&
niceVet.static.hasSkill(nicePlayer, class'NiceSkillSharpshooterZEDRailgun') &&
nicePlayer.IsZedTimeActive()
) {
return true;
}
if (niceZed.default.Health >= default.BigZedMinHealth && !bEasyHeadPenetration) {
reductionMod *= niceDmgType.default.BigZedPenDmgReduction;
} else if (niceZed.default.Health >= default.MediumZedMinHealth && !bEasyHeadPenetration) {
reductionMod *= niceDmgType.default.MediumZedPenDmgReduction;
}
} else {
reductionMod *= niceDmgType.default.BigZedPenDmgReduction;
}
if (niceVet != none) {
reductionMod = niceVet.static.GetPenetrationDamageMulti(
KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo),
reductionMod,
niceDmgType
);
}
actualMaxPenetrations = niceDmgType.default.maxPenetrations;
if (
niceVet != none &&
!bullet.charWasHipFired &&
niceVet.static.hasSkill(nicePlayer, class'NiceSkillSharpshooterSurgical') &&
bIsHeadshot
) {
actualMaxPenetrations += 1;
reductionMod = FMax(reductionMod, class'NiceSkillSharpshooterSurgical'.default.penDmgReduction);
}
// Assign new damage value and tell us if we should stop with penetration
Damage *= reductionMod * niceDmgType.default.PenDmgReduction;
bullet.decapMod *= reductionMod * niceDmgType.default.PenDecapReduction;
bullet.incapMod *= reductionMod * niceDmgType.default.PenIncapReduction;
if (niceVet != none && actualMaxPenetrations >= 0) {
actualMaxPenetrations +=
niceVet.static.GetAdditionalPenetrationAmount(KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo));
}
if (!bIsHeadshot && niceDmgType.default.bPenetrationHSOnly) {
return false;
}
if (actualMaxPenetrations < 0) {
return true;
}
if (Damage / bullet.charOrigDamage < (niceDmgType.default.PenDmgReduction ** (actualMaxPenetrations + 1)) + 0.0001 || Damage < 1) {
return false;
}
return true;
}
defaultproperties {
BigZedMinHealth=1000
MediumZedMinHealth=500
}

View file

@ -0,0 +1,53 @@
class NiceBullpup extends NiceAssaultRifle;
#exec OBJ LOAD FILE=KillingFloorWeapons.utx
#exec OBJ LOAD FILE=KillingFloorHUD.utx
#exec OBJ LOAD FILE=Inf_Weapons_Foley.uax
defaultproperties
{
reloadPreEndFrame=0.333000
reloadEndFrame=0.783000
reloadChargeEndFrame=-1.000000
reloadMagStartFrame=0.483000
reloadChargeStartFrame=-1.000000
MagCapacity=30
ReloadRate=1.966667
ReloadAnim="Reload"
ReloadAnimRate=1.000000
WeaponReloadAnim="Reload_BullPup"
Weight=5.000000
bHasAimingMode=True
IdleAimAnim="Idle_Iron"
StandardDisplayFOV=70.000000
SleeveNum=2
TraderInfoTexture=Texture'KillingFloorHUD.Trader_Weapon_Images.Trader_Bullpup'
MeshRef="KF_Weapons_Trip.Bullpup_Trip"
SkinRefs(0)="KF_Weapons_Trip_T.Rifles.bullpup_cmb"
SkinRefs(1)="KF_Weapons_Trip_T.Rifles.reflex_sight_A_unlit"
SelectSoundRef="KF_BullpupSnd.Bullpup_Select"
HudImageRef="KillingFloorHUD.WeaponSelect.Bullpup_unselected"
SelectedHudImageRef="KillingFloorHUD.WeaponSelect.Bullpup"
PlayerIronSightFOV=65.000000
ZoomedDisplayFOV=40.000000
FireModeClass(0)=class'NiceBullpupFire'
FireModeClass(1)=Class'KFMod.NoFire'
PutDownAnim="PutDown"
SelectForce="SwitchToAssaultRifle"
AIRating=0.550000
CurrentRating=0.550000
bShowChargingBar=True
Description="A military grade automatic rifle. Can be fired in semi-auto or full auto firemodes and comes equipped with a scope for increased accuracy."
EffectOffset=(X=100.000000,Y=25.000000,Z=-10.000000)
DisplayFOV=70.000000
Priority=70
CustomCrosshair=11
CustomCrossHairTextureName="Crosshairs.HUD.Crosshair_Cross5"
InventoryGroup=3
GroupOffset=1
PickupClass=class'NiceBullpupPickup'
PlayerViewOffset=(X=20.000000,Y=21.500000,Z=-9.000000)
BobDamping=6.000000
AttachmentClass=class'NiceBullpupAttachment'
IconCoords=(X1=245,Y1=39,X2=329,Y2=79)
ItemName="Bullpup"
TransientSoundVolume=1.250000
}

View file

@ -0,0 +1,13 @@
class NiceBullpupAmmo extends NiceAmmo;
#EXEC OBJ LOAD FILE=KillingFloorHUD.utx
defaultproperties
{
WeaponPickupClass=class'NiceBullpupPickup'
AmmoPickupAmount=30
MaxAmmo=240
InitialAmount=45
PickupClass=class'NiceBullpupAmmoPickup'
IconMaterial=Texture'KillingFloorHUD.Generic.HUD'
IconCoords=(X1=336,Y1=82,X2=382,Y2=125)
ItemName="Bullpup bullets"
}

View file

@ -0,0 +1,8 @@
class NiceBullpupAmmoPickup extends NiceAmmoPickup;
defaultproperties
{
AmmoAmount=30
InventoryType=class'NiceBullpupAmmo'
PickupMessage="Rounds (5.56 NATO)"
StaticMesh=StaticMesh'KillingFloorStatics.L85Ammo'
}

Some files were not shown because too many files have changed in this diff Show more