979 lines
39 KiB
Ucode
979 lines
39 KiB
Ucode
class NicePack extends Mutator
|
|
dependson(NiceStorageServer)
|
|
config(NicePack);
|
|
// Should we scale health off all zeds to 6-player level?
|
|
var config bool bScaleZedHealth;
|
|
// Should we replace all pickups with their Nice versions when available?
|
|
var config bool bReplacePickups;
|
|
// Settings for initial trader
|
|
var config bool bInitialTrader; // Use initial trader system?
|
|
var config bool bStillDuringInitTrader; // Force players to stand still during initial trader
|
|
var config int initialTraderTime; // How much time should be allowed for initial trade?
|
|
// Progressive dosh config
|
|
var config bool bUseProgresiveCash; // Use progressive dosh system?
|
|
var config array<int> waveCash;
|
|
var config float lateMultiplier;
|
|
// Experience-conversion controlling variables
|
|
var config bool bConvertExp; // Should we even convert old exp into a new one?
|
|
var config float vetFieldMedicExpCost; // Amount of exp per HP healed
|
|
var config float vetFieldMedicDmgExpCost; // Amount of exp per 1 medic damage
|
|
var config float vetSharpHeadshotExpCost; // Amount of exp per head-shot
|
|
var config float vetSupportDamageExpCost; // Amount of exp per 1 shotgun damage
|
|
var config float vetCommandoDamageExpCost; // Amount of exp per 1 assault rifle damage
|
|
var config float vetDemoDamageExpCost; // Amount of exp per 1 explosive damage
|
|
var config float vetZerkDamageExpCost; // Amount of exp per 1 melee damage
|
|
var config float vetHeavyMGDamageExpCost; // Amount of exp per 1 heavy machine gun damage
|
|
var config float vetGunslingerKillExpCost; // Amount of exp per 1 assault rifle damage
|
|
// Allow changing skills at any time
|
|
var config bool bAlwaysAllowSkillChange;
|
|
// Variables for controlling how zeds spawn
|
|
var config float minSpawnRate, maxSpawnRate; // Minimum and maximum allowed spawn rate
|
|
var config int minimalSpawnDistance; // Minimal distance between ZedVolume and players that should allow for zeds to spawn
|
|
// FF voting - related settings
|
|
var config bool bOneFFIncOnly; // Option that only allows one FF increase per game
|
|
var config bool bNoLateFFIncrease; // Disables FF increase through voting after 1st wave
|
|
// Configuration variables that store whether or not to replace the specimen with it's mean counterpart
|
|
var config bool bReplaceCrawler, bReplaceStalker, bReplaceClot, bReplaceGorefast, bReplaceBloat, bReplaceSiren, bReplaceHusk, bReplaceScrake, bReplaceFleshpound;
|
|
var config int bigZedMinHealth; // If zed's base Health >= this value, zed counts as Big
|
|
var config int mediumZedMinHealth;
|
|
|
|
var int maxPlayersInGame;
|
|
|
|
// 'Adrenaline junkie' zed-time extensions
|
|
var int junkieDoneGoals; // How many times we collected enough head-shots to trigger zed-time extension
|
|
var int junkieNextGoal; // How many head-shots we need for next zed-time extension
|
|
var int junkieDoneHeadshots; // How many head-shot in a row was done from the start of last zed-time
|
|
var array<String> replCaps;
|
|
var bool bFFWasIncreased;
|
|
var int nextSirenScreamID;
|
|
var int stuckCounter;
|
|
// Max dead bodies among all players
|
|
var int maxDeadBodies;
|
|
var int deadBodyCounter;
|
|
var ScrnBalance ScrnMut;
|
|
var ScrnGameType ScrnGT;
|
|
var NiceGameType NiceGT;
|
|
var NicePack Mut;
|
|
var NiceRules GameRules;
|
|
var NiceStorageServer serverStorage;
|
|
var bool interactionAdded;
|
|
var bool bIsPreGame;
|
|
var bool bIsTraderTime;
|
|
var bool bWasZedTime;
|
|
var array<KFHumanPawn> recordedHumanPawns;
|
|
struct PlayerRecord{
|
|
var string steamID;
|
|
var bool bHasSpawned;
|
|
var int lastCashWave; //Last wave in which player either participated, or for which he received cash
|
|
var int kills, assists, deaths;
|
|
};
|
|
var array<PlayerRecord> PlayerDatabase;
|
|
// Zed hardcore level record
|
|
struct ZedRecord{
|
|
var string ZedName;
|
|
var class<NiceMonster> ZedType;
|
|
var class<NiceMonster> MeanZedType;
|
|
var bool bAlreadySpawned;
|
|
var bool bMeanAlreadySpawned;
|
|
var float HL;
|
|
var float MeanHLBonus;
|
|
var bool bNeedsReplacement;
|
|
};
|
|
var int lastStandardZed;
|
|
var array<ZedRecord> ZedDatabase;
|
|
struct NicePickupReplacement{
|
|
var class<Pickup> vanillaClass;
|
|
var class<Pickup> scrnClass;
|
|
var class<Pickup> newClass;
|
|
};
|
|
var array<NicePickupReplacement> pickupReplaceArray;
|
|
struct CounterDisplay{
|
|
var string cName;
|
|
var Texture icon;
|
|
var int value;
|
|
var bool bShowZeroValue;
|
|
var class<NiceSkill> ownerSkill;
|
|
};
|
|
var array<CounterDisplay> niceCounterSet;
|
|
|
|
// Replication of config between player and server
|
|
var int SrvFlags;
|
|
var array<NicePlayerController> playersList;
|
|
var NicePathBuilder globalPathBuilder;
|
|
|
|
replication{
|
|
reliable if(Role == ROLE_Authority)
|
|
SrvFlags, bIsPreGame, junkieDoneHeadshots, junkieNextGoal;
|
|
}
|
|
|
|
static function NicePathBuilder GetPathBuilder(){
|
|
if(default.globalPathBuilder == none)
|
|
default.globalPathBuilder = new() class'NicePathBuilder';
|
|
return default.globalPathBuilder;
|
|
}
|
|
|
|
static final function NiceStorageBase GetStorage(LevelInfo level){
|
|
local NicePlayerController localPlayer;
|
|
if(default.serverStorage != none) return default.serverStorage;
|
|
localPlayer = NicePlayerController(level.GetLocalPlayerController());
|
|
if(localPlayer != none)
|
|
return localPlayer.storageClient;
|
|
return none;
|
|
}
|
|
|
|
static final function NicePack Myself(LevelInfo Level){
|
|
local Mutator M;
|
|
local NicePack NicePackMutator;
|
|
if(default.Mut != none)
|
|
return default.Mut;
|
|
// server-side
|
|
if(Level != none && Level.Game != none){
|
|
for(M = Level.Game.BaseMutator;M != none;M = M.NextMutator){
|
|
NicePackMutator = NicePack(M);
|
|
if(NicePackMutator != none){
|
|
default.Mut = NicePackMutator;
|
|
return NicePackMutator;
|
|
}
|
|
}
|
|
}
|
|
// client-side
|
|
foreach Level.DynamicActors(class'NicePack', NicePackMutator){
|
|
default.Mut = NicePackMutator;
|
|
return NicePackMutator;
|
|
}
|
|
return none;
|
|
}
|
|
function PreBeginPlay()
|
|
{
|
|
local ZombieVolume ZV;
|
|
super.PreBeginPlay();
|
|
foreach AllActors(Class'ZombieVolume', ZV)
|
|
ZV.MinDistanceToPlayer = minimalSpawnDistance;
|
|
AddToPackageMap("NicePackA.ukx");
|
|
AddToPackageMap("NicePackSM.usx");
|
|
AddToPackageMap("NicePackSnd.uax");
|
|
AddToPackageMap("NicePackT.utx");
|
|
}
|
|
|
|
simulated function PostBeginPlay()
|
|
{
|
|
local ScrnVotingHandlerMut VH;
|
|
local MeanVoting VO;
|
|
local NiceFFVoting FFVO;
|
|
|
|
super.PostBeginPlay();
|
|
|
|
class'ScrnLightVestPickup'.default.cost = 50;
|
|
class'ScrnHorzineVestPickup'.default.weight = 2;
|
|
class'ScrnHorzineVestPickup'.default.cost = 750;
|
|
class'NicePack'.default.Mut = self;
|
|
|
|
// Abilities
|
|
class'NiceAbilityManager'.default.events.static.AddAdapter(class'NiceSharpshooterAbilitiesAdapter', level);
|
|
class'NiceAbilityManager'.default.events.static.AddAdapter(class'NiceEnforcerAbilitiesAdapter', level);
|
|
|
|
SetTimer(0.25, true);
|
|
if (Role < ROLE_Authority)
|
|
return;
|
|
// Create sync node
|
|
serverStorage = new class'NiceStorageServer';
|
|
default.serverStorage = serverStorage;
|
|
serverStorage.events.static.AddAdapter(class'NiceRemoteDataAdapter', Level);
|
|
// Find game type and ScrN mutator
|
|
ScrnGT = ScrnGameType(Level.Game);
|
|
NiceGT = NiceGameType(Level.Game);
|
|
if (NiceGT == none)
|
|
{
|
|
Log("ERROR: Wrong GameType (requires NiceGameType)", class.Outer.Name);
|
|
Destroy();
|
|
return;
|
|
}
|
|
// FIXME poosh forces this variable in his mutator...
|
|
NiceGT.LoginMenuClass = string(class'NiceInvasionLoginMenu');
|
|
NiceGT.RegisterMutator(self);
|
|
ScrnMut = NiceGT.ScrnBalanceMut;
|
|
if(bReplacePickups)
|
|
ScrnMut.bReplacePickups = false;
|
|
// Replication of some variables
|
|
SetReplicationData();
|
|
// Game rules
|
|
GameRules = Spawn(class'NiceRules', self);
|
|
// -- Lower starting HL
|
|
ScrnMut.GameRules.HardcoreLevel -= 7;
|
|
ScrnMut.GameRules.HardcoreLevelFloat -= 7;
|
|
|
|
// -- Fill-in zed info
|
|
// - Clot
|
|
ZedDatabase[0].bNeedsReplacement = bReplaceClot;
|
|
// - Crawler
|
|
ZedDatabase[1].bNeedsReplacement = bReplaceCrawler;
|
|
// - Stalker
|
|
ZedDatabase[2].bNeedsReplacement = bReplaceStalker;
|
|
// - Gorefast
|
|
ZedDatabase[3].bNeedsReplacement = bReplaceGorefast;
|
|
// - Bloat
|
|
ZedDatabase[4].bNeedsReplacement = bReplaceBloat;
|
|
// - Siren
|
|
ZedDatabase[5].bNeedsReplacement = bReplaceSiren;
|
|
// - Husk
|
|
ZedDatabase[6].bNeedsReplacement = bReplaceHusk;
|
|
// - Scrake
|
|
ZedDatabase[7].bNeedsReplacement = bReplaceScrake;
|
|
// - Fleshpound
|
|
ZedDatabase[8].bNeedsReplacement = bReplaceFleshpound;
|
|
// FIXME!!!
|
|
lastStandardZed = 8;
|
|
|
|
// Add voting for mean zeds
|
|
VH = class'ScrnVotingHandlerMut'.static.GetVotingHandler(Level.Game);
|
|
if(VH == none){
|
|
Level.Game.AddMutator(string(class'ScrnVotingHandlerMut'), false);
|
|
VH = class'ScrnVotingHandlerMut'.static.GetVotingHandler(Level.Game);
|
|
}
|
|
if(VH != none){
|
|
VO = MeanVoting(VH.AddVotingOptions(class'MeanVoting'));
|
|
if(VO != none)
|
|
VO.Mut = self;
|
|
FFVO = NiceFFVoting(VH.AddVotingOptions(class'NiceFFVoting'));
|
|
if(FFVO != none)
|
|
FFVO.Mut = self;
|
|
}
|
|
else
|
|
log("Unable to spawn voting handler mutator", class.outer.name);
|
|
}
|
|
|
|
simulated function PostNetBeginPlay()
|
|
{
|
|
super.PostNetBeginPlay();
|
|
|
|
if (Role < ROLE_Authority)
|
|
LoadReplicationData();
|
|
}
|
|
|
|
simulated function LoadReplicationData()
|
|
{
|
|
bInitialTrader = (SrvFlags & 0x00000001) > 0;
|
|
bStillDuringInitTrader = (SrvFlags & 0x00000002) > 0;
|
|
}
|
|
|
|
function SetReplicationData()
|
|
{
|
|
SrvFlags = 0;
|
|
if (bInitialTrader)
|
|
SrvFlags = SrvFlags | 0x00000001;
|
|
if (bStillDuringInitTrader)
|
|
SrvFlags = SrvFlags | 0x00000002;
|
|
}
|
|
|
|
simulated function Timer(){
|
|
local KFHumanPawn nextPawn;
|
|
local int currentPlayersMax;
|
|
local Controller P;
|
|
local NicePlayerController nicePlayer;
|
|
// Cull excessive pawns
|
|
if(Role < Role_AUTHORITY){
|
|
recordedHumanPawns.Length = 0;
|
|
foreach DynamicActors(class'KFHumanPawn', nextPawn)
|
|
if(nextPawn != none && nextPawn.health > 0)
|
|
recordedHumanPawns[recordedHumanPawns.Length] = nextPawn;
|
|
return;
|
|
}
|
|
// Broadcast skills & record latest player controller list
|
|
BroadcastSkills();
|
|
playersList.length = 0;
|
|
for(P = Level.ControllerList; P != none; P = P.nextController){
|
|
nicePlayer = NicePlayerController(P);
|
|
if(nicePlayer != none){
|
|
nicePlayer.wallHitsLeft = 10;
|
|
//nicePlayer.FreeOldStuckBullets();
|
|
playersList[playersList.Length] = nicePlayer;
|
|
if(nicePlayer.Pawn != none && nicePlayer.Pawn.health > 0 && !nicePlayer.PlayerReplicationInfo.bIsSpectator
|
|
&& !nicePlayer.PlayerReplicationInfo.bOnlySpectator)
|
|
currentPlayersMax ++;
|
|
}
|
|
}
|
|
maxPlayersInGame = Max(maxPlayersInGame, currentPlayersMax);
|
|
}
|
|
|
|
// initial tick, does some job and shuts down
|
|
auto state loadInteractionnSpawnRate
|
|
{
|
|
// state tick, overrides global
|
|
simulated function Tick(float Delta)
|
|
{
|
|
local NiceInteraction niceInt;
|
|
local NicePlayerController localPlayer;
|
|
|
|
if (level.netMode == NM_DedicatedServer)
|
|
{
|
|
// set spawn rate!
|
|
if (ScrnMut != none)
|
|
ScrnMut.OriginalWaveSpawnPeriod = FMax(minSpawnRate, FMin(maxSpawnRate, ScrnMut.OriginalWaveSpawnPeriod));
|
|
// do not execute below code on dedicated servers!
|
|
GoToState('');
|
|
DisableServerGlobalTick();
|
|
return;
|
|
}
|
|
|
|
localPlayer = NicePlayerController(Level.GetLocalPlayerController());
|
|
if (localPlayer == none)
|
|
return;
|
|
|
|
// spawn some magic
|
|
if (localPlayer.storageClient != none && localPlayer.remoteRI != none)
|
|
{
|
|
localPlayer.storageClient.remoteRI = localPlayer.remoteRI;
|
|
localPlayer.storageClient.events.static.CallLinkEstablished();
|
|
}
|
|
|
|
// Actually add the interaction
|
|
niceInt = NiceInteraction(localPlayer.Player.InteractionMaster.AddInteraction(string(class'NiceInteraction'), localPlayer.Player));
|
|
niceInt.RegisterMutator(Self);
|
|
|
|
// break this state and go to global
|
|
GoToState('');
|
|
}
|
|
}
|
|
|
|
// disable tick for servers!
|
|
final private function DisableServerGlobalTick()
|
|
{
|
|
Disable('Tick');
|
|
}
|
|
|
|
// global tick
|
|
simulated function Tick(float Delta)
|
|
{
|
|
local int i;
|
|
local NicePlayerController localPlayer;
|
|
|
|
localPlayer = NicePlayerController(Level.GetLocalPlayerController());
|
|
// Check if the local PlayerController is available yet
|
|
if (localPlayer == none)
|
|
return;
|
|
|
|
if (localPlayer.bFlagDisplayCounters)
|
|
{
|
|
for (i = 0; i < niceCounterSet.Length; i++)
|
|
{
|
|
if (niceCounterSet[i].ownerSkill == none)
|
|
niceCounterSet[i].value = UpdateCounterValue(niceCounterSet[i].cName);
|
|
else if(class'NiceVeterancyTypes'.static.hasSkill(localPlayer, niceCounterSet[i].ownerSkill))
|
|
niceCounterSet[i].value = niceCounterSet[i].ownerSkill.static.
|
|
UpdateCounterValue(niceCounterSet[i].cName, localPlayer);
|
|
else
|
|
niceCounterSet[i].value = 0;
|
|
}
|
|
}
|
|
// Reset tick counter for traces
|
|
localPlayer.tracesThisTick = 0;
|
|
// Manage resetting of effects' limits
|
|
if (Level.TimeSeconds >= localPlayer.nextEffectsResetTime)
|
|
{
|
|
localPlayer.nextEffectsResetTime = Level.TimeSeconds + 0.1;
|
|
localPlayer.currentEffectTimeWindow ++;
|
|
if (localPlayer.currentEffectTimeWindow >= 10)
|
|
localPlayer.currentEffectTimeWindow = 0;
|
|
localPlayer.effectsSpawned[localPlayer.currentEffectTimeWindow] = 0;
|
|
}
|
|
}
|
|
|
|
simulated function bool CheckReplacement(Actor Other, out byte bSuperRelevant){
|
|
local int i;
|
|
local NiceMonster niceMonster;
|
|
local NiceZombieBoss boss;
|
|
local Controller cIt;
|
|
local int currNumPlayers;
|
|
local NicePlayerController playerContr;
|
|
local NiceRepInfoRemoteData remoteRI;
|
|
local NiceReplicationInfo niceRI;
|
|
local PlayerReplicationInfo pri;
|
|
// Replace loot on levels
|
|
if(Other.class == class'KFRandomItemSpawn' || Other.class == class'ScrnRandomItemSpawn'){
|
|
ReplaceWith(Other, string(class'NiceRandomItemSpawn'));
|
|
return false;
|
|
}
|
|
else if(Other.class == class'KFAmmoPickup' || Other.class == class'ScrnAmmoPickup') {
|
|
ReplaceWith(Other, string(class'NiceAmmoPickup'));
|
|
return false;
|
|
}
|
|
else if(bReplacePickups && Pickup(Other) != none){
|
|
i = FindPickupReplacementIndex(Pickup(Other));
|
|
if (i != -1){
|
|
ReplaceWith(Other, String(pickupReplaceArray[i].NewClass));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
// Add our replication info
|
|
if(PlayerReplicationInfo(Other) != none && NicePlayerController(PlayerReplicationInfo(Other).Owner) != none){
|
|
pri = PlayerReplicationInfo(Other);
|
|
niceRI = spawn(class'NiceReplicationInfo', pri.Owner);
|
|
niceRI.Mut = self;
|
|
remoteRI = spawn(class'NiceRepInfoRemoteData', pri.Owner);
|
|
playerContr = NicePlayerController(PlayerReplicationInfo(Other).Owner);
|
|
playerContr.niceRI = niceRI;
|
|
playerContr.remoteRI = remoteRI;
|
|
}
|
|
niceMonster = NiceMonster(Other);
|
|
if(niceMonster != none){
|
|
if (bUseProgresiveCash) {
|
|
niceMonster.ScoringValue = 0;
|
|
}
|
|
}
|
|
// Replace zeds with a healthier ones.
|
|
// Code taken from a scary ghost's SpecimenHPConfig
|
|
if(!bScaleZedHealth)
|
|
return true;
|
|
boss = NiceZombieBoss(Other);
|
|
if(niceMonster != none){
|
|
for(cIt= Level.ControllerList; cIt != none; cIt= cIt.NextController)
|
|
if(cIt.bIsPlayer && cIt.Pawn != none && cIt.Pawn.Health > 0)
|
|
currNumPlayers++;
|
|
if(boss == none) {
|
|
niceMonster.Health *= hpScale(niceMonster.PlayerCountHealthScale) / niceMonster.NumPlayersHealthModifer();
|
|
niceMonster.HealthMax = niceMonster.Health;
|
|
niceMonster.HeadHealth *= hpScale(niceMonster.PlayerNumHeadHealthScale) / niceMonster.NumPlayersHeadHealthModifer();
|
|
niceMonster.HeadHealthMax = niceMonster.HeadHealth;
|
|
if(Level.Game.NumPlayers == 1){
|
|
niceMonster.MeleeDamage /= 0.75;
|
|
niceMonster.ScreamDamage /= 0.75;
|
|
niceMonster.SpinDamConst /= 0.75;
|
|
niceMonster.SpinDamRand /= 0.75;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
// returns -1, if not found
|
|
function int FindPickupReplacementIndex(Pickup item)
|
|
{
|
|
local int i;
|
|
for(i=0; i < pickupReplaceArray.length;i ++){
|
|
if(pickupReplaceArray[i].vanillaClass == item.class || pickupReplaceArray[i].scrnClass == item.class)
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
// Try to extend zed-time, junkie-style
|
|
function JunkieZedTimeExtend(){
|
|
if((ScrnGT != none && !ScrnGT.bZEDTimeActive) || ScrnGT.CurrentZEDTimeDuration <= 0)
|
|
return;
|
|
junkieDoneHeadshots ++;
|
|
if(junkieNextGoal <= junkieDoneHeadshots){
|
|
junkieDoneHeadshots = 0;
|
|
junkieDoneGoals ++;
|
|
junkieNextGoal ++;
|
|
ScrnGT.DramaticEvent(1.0);
|
|
}
|
|
}
|
|
simulated function AddCounter(string cName, Texture icon, optional bool bShowZeroValue,
|
|
optional class<NiceSkill> owner){
|
|
local CounterDisplay newCounter;
|
|
RemoveCounter(cName);
|
|
newCounter.cName = cName;
|
|
newCounter.icon = icon;
|
|
newCounter.bShowZeroValue = bShowZeroValue;
|
|
newCounter.ownerSkill = owner;
|
|
niceCounterSet[niceCounterSet.Length] = newCounter;
|
|
}
|
|
simulated function RemoveCounter(string cName){
|
|
local int i;
|
|
local array<CounterDisplay> newCounterSet;
|
|
for(i = 0;i < niceCounterSet.Length;i ++)
|
|
if(niceCounterSet[i].cName != cName)
|
|
newCounterSet[newCounterSet.Length] = niceCounterSet[i];
|
|
niceCounterSet = newCounterSet;
|
|
}
|
|
simulated function int GetVisibleCountersAmount(){
|
|
local int i;
|
|
local int amount;
|
|
for(i = 0;i < niceCounterSet.Length;i ++)
|
|
if(niceCounterSet[i].value != 0 || niceCounterSet[i].bShowZeroValue)
|
|
amount ++;
|
|
return amount;
|
|
}
|
|
simulated function int UpdateCounterValue(string cName){
|
|
return 0;
|
|
}
|
|
|
|
// Returns cash per wave based on current difficulty
|
|
// Returns cash per wave based on current difficulty
|
|
function int GetWaveCash(int lastCashWave, int nextWave){
|
|
local int i;
|
|
local int accumulatedDosh;
|
|
for (i = lastCashWave; i < nextWave; i += 1) {
|
|
accumulatedDosh += waveCash[i];
|
|
}
|
|
if (lastCashWave + 1 < nextWave) {
|
|
accumulatedDosh *= lateMultiplier;
|
|
}
|
|
return accumulatedDosh;
|
|
}
|
|
// Gives out appropriate (for the wave he entered) amount of dosh to the player
|
|
function GiveProgressiveDosh(NicePlayerController nicePlayer){
|
|
local int nextWave;
|
|
local PlayerRecord record;
|
|
// Too early to give dosh
|
|
if(!ScrnGT.IsInState('MatchInProgress'))
|
|
return;
|
|
// Real spectators shouldn't be affected
|
|
if(nicePlayer == none) return;
|
|
if(nicePlayer.PlayerReplicationInfo.bIsSpectator) return;
|
|
if(nicePlayer.PlayerReplicationInfo.bOnlySpectator) return;
|
|
record = FindPlayerRecord(nicePlayer.steamID64);
|
|
nextWave = ScrnGT.WaveNum + 1;
|
|
nicePlayer.PlayerReplicationInfo.Score += GetWaveCash(record.lastCashWave, nextWave);
|
|
record.lastCashWave = nextWave;
|
|
UpdatePlayerRecord(record);
|
|
}
|
|
|
|
simulated function Mutate(string MutateString, PlayerController kfPlayer)
|
|
{
|
|
local int i, readLenght;
|
|
local NicePlayerController nicePlayer;
|
|
local NiceServerData remoteData;
|
|
// Tokens from 'MutateString'
|
|
local array<String> wordsArray;
|
|
local String command, mod;
|
|
local String white;
|
|
local BitStreamWriter inputStream;
|
|
local BitStreamReader outputStream;
|
|
// Array with command modifiers.
|
|
// Always contains at least 10 elements, that may be empty strings if there wasn't enough modifiers.
|
|
// Done for safe access without the need to check for bounds.
|
|
local array<String> modArray;
|
|
|
|
super.Mutate(MutateString, kfPlayer);
|
|
|
|
// Helpful sequence
|
|
white = chr(27)$chr(200)$chr(200)$chr(200);
|
|
// Transform our command into array for convenience
|
|
Split(MutateString, " ", wordsArray);
|
|
// Exit if command is empty
|
|
if(wordsArray.Length == 0)
|
|
return;
|
|
// Fancier access
|
|
command = wordsArray[0];
|
|
if(wordsArray.Length > 1)
|
|
mod = wordsArray[1];
|
|
else
|
|
mod = "";
|
|
i = 0;
|
|
while(i + 1 < wordsArray.Length || i < 10){
|
|
if(i + 1 < wordsArray.Length)
|
|
modArray[i] = wordsArray[i+1];
|
|
else
|
|
modArray[i] = "";
|
|
i ++;
|
|
}
|
|
nicePlayer = NicePlayerController(kfPlayer);
|
|
if(command ~= "ECHO")
|
|
kfPlayer.ClientMessage(Mid(MutateString, 5));
|
|
else if(command ~= "ZED" && bAlwaysAllowSkillChange)
|
|
ScrnGT.DramaticEvent(1.0);
|
|
else if(command ~= "SAVECFG" && nicePlayer != none)
|
|
nicePlayer.ClientSaveConfig();
|
|
else if(command ~= "CONFIG" && nicePlayer != none){
|
|
if(nicePlayer.bFlagAltSwitchesModes)
|
|
nicePlayer.ClientMessage(white$"Alt fire button will switch between single and burst modes for assault rifles");
|
|
else
|
|
nicePlayer.ClientMessage(white$"Alt fire button will shoot either single or burst mode for assault rifles");
|
|
if(nicePlayer.bFlagShowHLMessages)
|
|
nicePlayer.ClientMessage(white$"Messages about HL change will be displayed for you");
|
|
else
|
|
nicePlayer.ClientMessage(white$"Messages about HL change will be hidden from you");
|
|
}
|
|
else if(command ~= "HLMESSAGES" && nicePlayer != none){
|
|
if(mod ~= "ON")
|
|
nicePlayer.ServerSetHLMessages(true);
|
|
else if(mod ~= "OFF")
|
|
nicePlayer.ServerSetHLMessages(false);
|
|
}
|
|
else if(command ~= "ALTSWITCH"){
|
|
if(mod ~= "ON")
|
|
nicePlayer.ServerSetAltSwitchesModes(true);
|
|
else if(mod ~= "OFF")
|
|
nicePlayer.ServerSetAltSwitchesModes(false);
|
|
}
|
|
else if(command ~= "SETKEY" && nicePlayer != none){
|
|
if(Int(mod) > 0)
|
|
nicePlayer.ClientSetKey(Int(mod));
|
|
}
|
|
else if(command ~= "NICEWEAPMANAGE" && nicePlayer != none){
|
|
if(mod ~= "ON")
|
|
nicePlayer.ClientSetNiceWeapManagement(true);
|
|
else if(mod ~= "OFF")
|
|
nicePlayer.ClientSetNiceWeapManagement(false);
|
|
}
|
|
else if(command ~= "DEBUG" && nicePlayer != none){
|
|
if(mod ~= "ON")
|
|
nicePlayer.ServerSetDebug(true);
|
|
else if(mod ~= "OFF")
|
|
nicePlayer.ServerSetDebug(false);
|
|
}
|
|
else if(command ~= "LOGLINE" && nicePlayer != none)
|
|
nicePlayer.ClientLog("UserLine:"$mod);
|
|
else if(command ~= "CREATE"){
|
|
nicePlayer.ClientMessage("ATTEMPT"@string(serverStorage));
|
|
serverStorage.CreateData(modArray[0], NSP_HIGH);
|
|
remoteData = NiceServerData(serverStorage.GetData(modArray[0]));
|
|
remoteData.isAdminOnly = true;
|
|
nicePlayer.ClientMessage("ATTEMPT2"@string(remoteData));
|
|
}
|
|
else if(command ~= "CREATELOW"){
|
|
serverStorage.CreateData(modArray[0], NSP_LOW);
|
|
}
|
|
else if(command ~= "SET"){
|
|
remoteData = NiceServerData(serverStorage.GetData(modArray[0]));
|
|
nicePlayer.ClientMessage("SETATTEMPT"@string(remoteData));
|
|
remoteData.SetInt(modArray[1], Int(modArray[2]));
|
|
nicePlayer.ClientMessage("SETATTEMPT 2"@modArray[1]@modArray[2]);
|
|
}
|
|
else if(command ~= "PRINT"){
|
|
nicePlayer.ClientPrint();
|
|
}
|
|
else if(command ~= "TEST"){
|
|
inputStream = new class'BitStreamWriter';
|
|
outputStream = new class'BitStreamReader';
|
|
inputStream.WriteInt(Len(mod), 5);
|
|
inputStream.WriteClassName(mod);
|
|
outputStream.Initialize(inputStream.GetData());
|
|
readLenght = outputStream.ReadInt(5);
|
|
nicePlayer.ClientMessage("Input lenght:" @ string(Len(mod)));
|
|
nicePlayer.ClientMessage("Compressed lenght:" @ string(inputStream.GetSizeInBytes()) );
|
|
nicePlayer.ClientMessage("Output:"@outputStream.ReadClassName(readLenght));
|
|
}
|
|
}
|
|
/* Good test for writer
|
|
else if(command ~= "TEST"){
|
|
inputStream = new class'BitStreamWriter';
|
|
outputStream = new class'BitStreamReader';
|
|
//stream.PushByte(167, int(mod));
|
|
inputStream.WriteInt(3, 3);
|
|
inputStream.WriteByte(49, 7);
|
|
inputStream.WriteInt(1651779982, 25);
|
|
inputStream.WriteInt(2, 2);
|
|
bytes = inputStream.GetData();
|
|
bits = inputStream.GetSize();
|
|
nicePlayer.ClientMessage("SIZE:" @ string(bits));
|
|
for (i = 0; i < bytes.length; i += 1) {
|
|
nicePlayer.ClientMessage("Content:" @ string(bytes[i]));
|
|
}
|
|
outputStream.Initialize(bytes);
|
|
//nicePlayer.ClientMessage("OUT:" @ string(outputStream.ReadByte(3)));
|
|
//nicePlayer.ClientMessage("OUT:" @ string(outputStream.ReadByte(7)));
|
|
nicePlayer.ClientMessage("OUT:" @ string(outputStream.ReadByte(8)));
|
|
nicePlayer.ClientMessage("OUT:" @ string(outputStream.ReadByte(4)));
|
|
nicePlayer.ClientMessage("OUT:" @ string(outputStream.ReadByte(4)));
|
|
outputStream.Initialize(bytes);
|
|
nicePlayer.ClientMessage("OUT:" @ string(outputStream.ReadByte(3)));
|
|
nicePlayer.ClientMessage("OUT:" @ string(outputStream.ReadByte(7)));
|
|
nicePlayer.ClientMessage("OUT:" @ string(outputStream.ReadByte(5)));
|
|
outputStream.Initialize(bytes);
|
|
nicePlayer.ClientMessage("OUT:" @ string(outputStream.ReadInt(3)));
|
|
nicePlayer.ClientMessage("OUT:" @ string(outputStream.ReadByte(7)));
|
|
nicePlayer.ClientMessage("OUT:" @ string(outputStream.ReadInt(25)));
|
|
nicePlayer.ClientMessage("OUT:" @ string(outputStream.ReadInt(2)));
|
|
}
|
|
*/
|
|
// Event functions
|
|
// Called at the start of the match
|
|
function MatchBegan(){
|
|
}
|
|
// Called when new wave begins
|
|
function WaveStart(){
|
|
local Controller P;
|
|
local NiceHumanPawn nicePawn;
|
|
local NicePlayerController nicePlayer;
|
|
bIsPreGame = false;
|
|
bIsTraderTime = false;
|
|
for(P = Level.ControllerList; P != none; P = P.nextController){
|
|
nicePlayer = NicePlayerController(P);
|
|
if(nicePlayer != none){
|
|
// Give out armor
|
|
nicePawn = NiceHumanPawn(nicePlayer.Pawn);
|
|
if(nicePawn != none && nicePawn.Health > 0){
|
|
nicePawn.bGotFreeJacket = false;
|
|
nicePawn.getFreeJacket();
|
|
nicePawn.bReactiveArmorUsed = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Called when trader time begins
|
|
simulated function TraderStart(){
|
|
local Controller P;
|
|
local NiceHumanPawn nicePawn;
|
|
local NicePlayerController nicePlayer;
|
|
bIsTraderTime = true;
|
|
for(P = Level.ControllerList; P != none; P = P.nextController){
|
|
nicePlayer = NicePlayerController(P);
|
|
if(nicePlayer != none){
|
|
nicePlayer.TryActivatePendingSkills();
|
|
nicePlayer.ClientSaveConfig();
|
|
nicePawn = NiceHumanPawn(nicePlayer.Pawn);
|
|
if (bUseProgresiveCash) {
|
|
GiveProgressiveDosh(nicePlayer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Called when zed-time begins
|
|
simulated function ZedTimeActivated(){
|
|
}
|
|
// Called when zed-time deactivated
|
|
simulated function ZedTimeDeactivated(){
|
|
local Controller P;
|
|
local NicePlayerController Player;
|
|
junkieNextGoal=1;
|
|
junkieDoneGoals=0;
|
|
junkieDoneHeadshots=0;
|
|
for(P = Level.ControllerList; P != none; P = P.nextController){
|
|
Player = NicePlayerController(P);
|
|
if(Player != none)
|
|
Player.bJunkieExtFailed = false;
|
|
}
|
|
}
|
|
// Returns player record, corresponding to the given steam id
|
|
function PlayerRecord FindPlayerRecord(string steamID){
|
|
local int i;
|
|
local PlayerRecord newRecord;
|
|
for(i = 0;i < PlayerDatabase.Length;i ++)
|
|
if(PlayerDatabase[i].steamID == steamID)
|
|
return PlayerDatabase[i];
|
|
newRecord.steamID = steamID;
|
|
newRecord.bHasSpawned = false;
|
|
newRecord.lastCashWave = 0;
|
|
newRecord.kills = 0;
|
|
newRecord.assists = 0;
|
|
newRecord.deaths = 0;
|
|
PlayerDatabase[PlayerDatabase.Length] = newRecord;
|
|
return newRecord;
|
|
}
|
|
// Updates existing PlayerRecord (with a same steam id) and adds a new one, if necessary (record with a same steam is not found)
|
|
function UpdatePlayerRecord(PlayerRecord record){
|
|
local int i;
|
|
for(i = 0;i < PlayerDatabase.Length;i ++)
|
|
if(PlayerDatabase[i].steamID == record.steamID){
|
|
PlayerDatabase[i] = record;
|
|
return;
|
|
}
|
|
PlayerDatabase[PlayerDatabase.Length] = record;
|
|
}
|
|
// Checks if it should be possible to change skills right now
|
|
function bool CanChangeSkill(NicePlayerController player){
|
|
local PlayerRecord record;
|
|
record = FindPlayerRecord(player.SteamID64);
|
|
return (bIsTraderTime || (bIsPreGame && bInitialTrader) || bAlwaysAllowSkillChange || !record.bHasSpawned);
|
|
}
|
|
// Outputs info about given skill in console
|
|
function DisplaySkill(class<NiceSkill> skill, int level, bool selected, PlayerController player){
|
|
local String skillColor;
|
|
local String white;
|
|
if(selected)
|
|
skillColor = chr(27)$chr(1)$chr(200)$chr(1);
|
|
else
|
|
skillColor = chr(27)$chr(200)$chr(1)$chr(1);
|
|
white = chr(27)$chr(200)$chr(200)$chr(200);
|
|
player.ClientMessage(white$"Level"@String(level)$skillColor@"skill"$white$":"@skill.default.SkillName);
|
|
// Just in case description is too long
|
|
player.ClientMessage(" ");
|
|
}
|
|
function UpdateHealthLevels(){
|
|
local Controller P, S;
|
|
local NiceHumanPawn updatePawn;
|
|
for(P = Level.ControllerList;P != none;P = P.nextController){
|
|
updatePawn = NiceHumanPawn(P.Pawn);
|
|
if(updatePawn == none)
|
|
continue;
|
|
updatePawn.HealthMax = (updatePawn.default.HealthMax + updatePawn.HealthBonus) * updatePawn.ScrnPerk.static.HealthMaxMult(KFPlayerReplicationInfo(P.PlayerReplicationInfo), updatePawn);
|
|
for(S = Level.ControllerList;S != none;S = S.nextController)
|
|
if(NicePlayerController(S) != none)
|
|
NicePlayerController(S).ClientUpdatePawnMaxHealth(updatePawn, updatePawn.HealthMax);
|
|
}
|
|
}
|
|
function BroadcastSkills(){
|
|
local int i, j;
|
|
local bool bSameSkillFound;
|
|
local Controller P;
|
|
local NicePlayerController nicePlayer;
|
|
local array< class<NiceSkill> > playerSkills;
|
|
// Skills to broadcast
|
|
local array<int> teamNumbers;
|
|
local array< class<NiceSkill> > skillsToSend;
|
|
for(P = Level.ControllerList;P != none;P = P.nextController){
|
|
nicePlayer = NicePlayerController(P);
|
|
if(nicePlayer != none){
|
|
playerSkills = nicePlayer.GetActiveBroadcastSkills();
|
|
// Process player's skills
|
|
for(i = 0;i < playerSkills.Length;i ++){
|
|
bSameSkillFound = false;
|
|
// Try to find if someone already shares the same skill in the same team
|
|
for(j = 0;j < skillsToSend.Length && !bSameSkillFound;j ++)
|
|
if(playerSkills[i] == skillsToSend[j] && teamNumbers[j] == nicePlayer.PlayerReplicationInfo.Team.TeamIndex)
|
|
bSameSkillFound = true;
|
|
// If not - add it
|
|
if(!bSameSkillFound){
|
|
teamNumbers[teamNumbers.Length] = nicePlayer.PlayerReplicationInfo.Team.TeamIndex;
|
|
skillsToSend[skillsToSend.Length] = playerSkills[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for(P = Level.ControllerList;P != none;P = P.nextController){
|
|
nicePlayer = NicePlayerController(P);
|
|
if(nicePlayer != none){
|
|
for(i = 0;i < skillsToSend.Length;i ++)
|
|
if(teamNumbers[i] == nicePlayer.PlayerReplicationInfo.Team.TeamIndex)
|
|
nicePlayer.ClientReceiveSkill(skillsToSend[i]);
|
|
nicePlayer.ClientBroadcastEnded();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Function for broadcasting messages to players
|
|
function BroadcastToAll(string message){
|
|
local Controller P;
|
|
local PlayerController Player;
|
|
for(P = Level.ControllerList; P != none; P = P.nextController){
|
|
Player = PlayerController(P);
|
|
if(Player != none)
|
|
Player.ClientMessage(message);
|
|
}
|
|
}
|
|
// Function for finding number, corresponding to zed's name
|
|
function int ZedNumber(String ZedName){
|
|
local int i;
|
|
for(i = 0;i < ZedDatabase.Length;i ++)
|
|
if(ZedName ~= ZedDatabase[i].ZedName)
|
|
return i;
|
|
return -1;
|
|
}
|
|
// Function for correct hp scaling
|
|
function float hpScale(float hpScale) {
|
|
return 1.0 + 5.0 * hpScale;
|
|
}
|
|
static function FillPlayInfo(PlayInfo PlayInfo){
|
|
Super.FillPlayInfo(PlayInfo);
|
|
PlayInfo.AddSetting("NicePack", "bScaleZedHealth", "Scale zeds' health?", 0, 0, "check");
|
|
PlayInfo.AddSetting("NicePack", "bReplacePickups", "Replace pickups?", 0, 0, "check");
|
|
PlayInfo.AddSetting("NicePack", "bInitialTrader", "Use init trader?", 0, 0, "check");
|
|
PlayInfo.AddSetting("NicePack", "bStillDuringInitTrader", "Be still during init trader?", 0, 0, "check");
|
|
PlayInfo.AddSetting("NicePack", "initialTraderTime", "Time for init trader?", 0, 0, "text", "3;1:999");
|
|
PlayInfo.AddSetting("NicePack", "bUseProgresiveCash", "Use progressive dosh?", 0, 0, "check");
|
|
PlayInfo.AddSetting("NicePack", "bConvertExp", "Convert old exp?", 0, 0, "check");
|
|
PlayInfo.AddSetting("NicePack", "bAlwaysAllowSkillChange", "Skill change at anytime?", 0, 0, "check");
|
|
PlayInfo.AddSetting("NicePack", "minimalSpawnDistance", "Min spawn distance", 0, 0, "text", "5;0:99999");
|
|
PlayInfo.AddSetting("NicePack", "minSpawnRate", "Min spawn rate", 0, 0, "text", "6;0.0:10.0");
|
|
PlayInfo.AddSetting("NicePack", "maxSpawnRate", "Max spawn rate", 0, 0, "text", "6;0.0:10.0");
|
|
PlayInfo.AddSetting("NicePack", "bOneFFIncOnly", "Only 1 FF increase?", 0, 0, "check");
|
|
PlayInfo.AddSetting("NicePack", "bNoLateFFIncrease", "FF increase wave 1 only?", 0, 0, "check");
|
|
}
|
|
static function string GetDescriptionText(string SettingName){
|
|
switch (SettingName){
|
|
case "bScaleZedHealth":
|
|
return "Should we scale health off all zeds to 6-player level?";
|
|
case "bReplacePickups":
|
|
return "Should we replace all pickups with their Nice versions when available?";
|
|
case "bInitialTrader":
|
|
return "Use initial trader system?";
|
|
case "bStillDuringInitTrader":
|
|
return "Force players to stand still during initial trader?";
|
|
case "initialTraderTime":
|
|
return "How much time should be allowed for initial trade?";
|
|
case "bUseProgresiveCash":
|
|
return "Use progressive dosh system?";
|
|
case "bConvertExp":
|
|
return "Should we convert old exp into a new one?";
|
|
case "bAlwaysAllowSkillChange":
|
|
return "Allows changing skills at any time.";
|
|
case "minimalSpawnDistance":
|
|
return "Minimal distance between ZedVolume and players that should allow for zeds to spawn.";
|
|
case "minSpawnRate":
|
|
return "Minimal allowed spawn rate.";
|
|
case "maxSpawnRate":
|
|
return "Maximal allowed spawn rate.";
|
|
case "bOneFFIncOnly":
|
|
return "Option that only allows one FF increase per game.";
|
|
case "bNoLateFFIncrease":
|
|
return "Disables FF increase through voting after 1st wave.";
|
|
}
|
|
return Super.GetDescriptionText(SettingName);
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
GroupName="KFNicePack"
|
|
FriendlyName="Package for nice/mean servers"
|
|
Description="Does stuff."
|
|
bAlwaysRelevant=True
|
|
RemoteRole=ROLE_SimulatedProxy
|
|
bAddToServerPackages=True
|
|
|
|
// used in scrn voting and HL calculation
|
|
// TODO remove HL!
|
|
ZedDatabase(00)=(ZedName="Clot",ZedType=class'NiceZombieClot',MeanZedType=class'MeanZombieClot',HL=0.0,MeanHLBonus=0.5)
|
|
ZedDatabase(01)=(ZedName="Crawler",ZedType=class'NiceZombieCrawler',MeanZedType=class'MeanZombieCrawler',HL=0.5,MeanHLBonus=1.5)
|
|
ZedDatabase(02)=(ZedName="Stalker",ZedType=class'NiceZombieStalker',MeanZedType=class'MeanZombieStalker',HL=0.5,MeanHLBonus=0.5)
|
|
ZedDatabase(03)=(ZedName="Gorefast",ZedType=class'NiceZombieGorefast',MeanZedType=class'MeanZombieGorefast',HL=0.0,MeanHLBonus=0.5)
|
|
ZedDatabase(04)=(ZedName="Bloat",ZedType=class'NiceZombieBloat',MeanZedType=class'MeanZombieBloat',HL=0.0,MeanHLBonus=0.5)
|
|
ZedDatabase(05)=(ZedName="Siren",ZedType=class'NiceZombieSiren',MeanZedType=class'MeanZombieSiren',HL=1.0,MeanHLBonus=1.0)
|
|
ZedDatabase(06)=(ZedName="Husk",ZedType=class'NiceZombieHusk',MeanZedType=class'MeanZombieHusk',HL=1.0,MeanHLBonus=1.5)
|
|
ZedDatabase(07)=(ZedName="Scrake",ZedType=class'NiceZombieScrake',MeanZedType=class'MeanZombieScrake',HL=1.5,MeanHLBonus=1.5)
|
|
ZedDatabase(08)=(ZedName="Fleshpound",ZedType=class'NiceZombieFleshPound',MeanZedType=class'MeanZombieFleshPound',HL=2.5,MeanHLBonus=1.5)
|
|
ZedDatabase(09)=(ZedName="Shiver",ZedType=class'NiceZombieShiver',HL=1.0)
|
|
ZedDatabase(10)=(ZedName="Jason",ZedType=class'NiceZombieJason',HL=1.5)
|
|
ZedDatabase(11)=(ZedName="Tesla Husk",ZedType=class'NiceZombieTeslaHusk',HL=1.5)
|
|
ZedDatabase(12)=(ZedName="Brute",ZedType=class'NiceZombieBrute',HL=2.0)
|
|
ZedDatabase(13)=(ZedName="Ghost",ZedType=class'NiceZombieGhost',HL=0.5)
|
|
ZedDatabase(14)=(ZedName="Sick",ZedType=class'NiceZombieSick',HL=1.0)
|
|
|
|
bScaleZedHealth=True
|
|
bReplacePickups=True
|
|
bInitialTrader=True
|
|
initialTraderTime=10
|
|
bUseProgresiveCash=True
|
|
waveCash(0)=1000
|
|
waveCash(1)=900
|
|
waveCash(2)=800
|
|
waveCash(3)=650
|
|
waveCash(4)=600
|
|
waveCash(5)=450
|
|
waveCash(6)=350
|
|
waveCash(7)=250
|
|
lateMultiplier=0.5
|
|
bConvertExp=True
|
|
vetFieldMedicExpCost=2.000000
|
|
vetFieldMedicDmgExpCost=0.025000
|
|
vetSharpHeadshotExpCost=10.000000
|
|
vetSupportDamageExpCost=0.050000
|
|
vetCommandoDamageExpCost=0.050000
|
|
vetDemoDamageExpCost=0.050000
|
|
vetZerkDamageExpCost=0.050000
|
|
vetHeavyMGDamageExpCost=0.050000
|
|
vetGunslingerKillExpCost=20.000000
|
|
bigZedMinHealth=1000
|
|
mediumZedMinHealth=500
|
|
minSpawnRate=0.700000
|
|
maxSpawnRate=1.500000
|
|
minimalSpawnDistance=600
|
|
bNoLateFFIncrease=True
|
|
junkieNextGoal=1
|
|
bIsPreGame=True
|
|
|
|
// replace pickups that map spawn's itself
|
|
pickupReplaceArray(00)=(vanillaClass=Class'KFMod.MAC10Pickup',scrnClass=Class'ScrnMAC10Pickup',NewClass=class'NiceMAC10Pickup')
|
|
pickupReplaceArray(01)=(vanillaClass=Class'KFMod.WinchesterPickup',scrnClass=Class'ScrnWinchesterPickup',NewClass=class'NiceWinchesterPickup')
|
|
pickupReplaceArray(02)=(vanillaClass=Class'KFMod.CrossbowPickup',scrnClass=Class'ScrnCrossbowPickup',NewClass=class'NiceCrossbowPickup')
|
|
pickupReplaceArray(03)=(vanillaClass=Class'KFMod.SPSniperPickup',scrnClass=Class'ScrnSPSniperPickup',NewClass=class'NiceMaulerPickup')
|
|
pickupReplaceArray(04)=(vanillaClass=Class'KFMod.M14EBRPickup',scrnClass=Class'ScrnM14EBRPickup',NewClass=class'NiceM14EBRPickup')
|
|
pickupReplaceArray(05)=(vanillaClass=Class'KFMod.M99Pickup',scrnClass=Class'ScrnM99Pickup',NewClass=class'NiceM99Pickup')
|
|
pickupReplaceArray(06)=(vanillaClass=Class'KFMod.ShotgunPickup',scrnClass=Class'ScrnShotgunPickup',NewClass=class'NiceShotgunPickup')
|
|
pickupReplaceArray(07)=(vanillaClass=Class'KFMod.BoomStickPickup',scrnClass=Class'ScrnBoomStickPickup',NewClass=class'NiceBoomStickPickup')
|
|
pickupReplaceArray(08)=(vanillaClass=Class'KFMod.NailGunPickup',scrnClass=Class'ScrnNailGunPickup',NewClass=class'NiceNailGunPickup')
|
|
pickupReplaceArray(09)=(vanillaClass=Class'KFMod.KSGPickup',scrnClass=Class'ScrnKSGPickup',NewClass=class'NiceKSGPickup')
|
|
pickupReplaceArray(10)=(vanillaClass=Class'KFMod.BenelliPickup',scrnClass=Class'ScrnBenelliPickup',NewClass=class'NiceBenelliPickup')
|
|
pickupReplaceArray(11)=(vanillaClass=Class'KFMod.AA12Pickup',scrnClass=Class'ScrnAA12Pickup',NewClass=class'NiceAA12Pickup')
|
|
pickupReplaceArray(12)=(vanillaClass=Class'KFMod.MachetePickup',scrnClass=Class'ScrnMachetePickup',NewClass=class'NiceMachetePickup')
|
|
} |