First commit
This commit is contained in:
commit
5b48414900
126
sources/Data/NiceClientData.uc
Normal file
126
sources/Data/NiceClientData.uc
Normal file
@ -0,0 +1,126 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceClientData
|
||||
//==============================================================================
|
||||
// Adds data interface relevant only to client,
|
||||
// as well as client implementation of more general functions.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NiceClientData extends NiceData
|
||||
config(NicePack);
|
||||
|
||||
var protected NiceStorageClient ownerStorage;
|
||||
// Server has yet unsent changes to this data
|
||||
// (according to latest information from server)
|
||||
var protected bool _isUpToDate;
|
||||
// We can currently send server changes in this data
|
||||
var protected bool _hasWriteRights;
|
||||
|
||||
static function NiceData NewData(string newID){
|
||||
local NiceData newData;
|
||||
newData = new class'NiceClientData';
|
||||
newData.ID = newID;
|
||||
return newData;
|
||||
}
|
||||
|
||||
// #private
|
||||
function SetOwnerStorage( NiceRemoteHack.DataRef dataRef,
|
||||
NiceStorageClient newOwner){
|
||||
if(ID ~= class'NiceRemoteHack'.static.GetDataRefID(dataRef))
|
||||
ownerStorage = newOwner;
|
||||
}
|
||||
|
||||
function bool IsUpToDate(){
|
||||
return _isUpToDate;
|
||||
}
|
||||
|
||||
// #private
|
||||
function SetUpToDate(NiceRemoteHack.DataRef dataRef, bool newStatus){
|
||||
if(ID ~= class'NiceRemoteHack'.static.GetDataRefID(dataRef))
|
||||
_isUpToDate = newStatus;
|
||||
}
|
||||
|
||||
function bool HasWriteRights(){
|
||||
return _hasWriteRights;
|
||||
}
|
||||
|
||||
// #private
|
||||
function SetWriteRights(NiceRemoteHack.DataRef dataRef, bool newRights){
|
||||
if(ID ~= class'NiceRemoteHack'.static.GetDataRefID(dataRef))
|
||||
_hasWriteRights = newRights;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// > Setter / getters for variables that perform necessary synchronization
|
||||
function SetByte(string variableName, byte variableValue){
|
||||
if(!HasWriteRights()) return;
|
||||
if(ownerStorage == none) return;
|
||||
if(ownerStorage.remoteRI == none) return;
|
||||
|
||||
_SetByte(V(ID, variableName), variableValue);
|
||||
events.static.CallVariableUpdated(ID, variableName);
|
||||
events.static.CallByteVariableUpdated(ID, variableName, variableValue);
|
||||
ownerStorage.remoteRI.ServerSendByte(V(ID, variableName), variableValue);
|
||||
}
|
||||
|
||||
function SetInt(string variableName, int variableValue){
|
||||
if(!HasWriteRights()) return;
|
||||
if(ownerStorage == none) return;
|
||||
if(ownerStorage.remoteRI == none) return;
|
||||
|
||||
_SetInt(V(ID, variableName), variableValue);
|
||||
events.static.CallVariableUpdated(ID, variableName);
|
||||
events.static.CallIntVariableUpdated(ID, variableName, variableValue);
|
||||
ownerStorage.remoteRI.ServerSendInt(V(ID, variableName), variableValue);
|
||||
}
|
||||
|
||||
function SetBool(string variableName, bool variableValue){
|
||||
if(!HasWriteRights()) return;
|
||||
if(ownerStorage == none) return;
|
||||
if(ownerStorage.remoteRI == none) return;
|
||||
|
||||
_SetBool(V(ID, variableName), variableValue);
|
||||
events.static.CallVariableUpdated(ID, variableName);
|
||||
events.static.CallBoolVariableUpdated(ID, variableName, variableValue);
|
||||
ownerStorage.remoteRI.ServerSendBool(V(ID, variableName), variableValue);
|
||||
}
|
||||
|
||||
function SetFloat(string variableName, float variableValue){
|
||||
if(!HasWriteRights()) return;
|
||||
if(ownerStorage == none) return;
|
||||
if(ownerStorage.remoteRI == none) return;
|
||||
|
||||
_SetFloat(V(ID, variableName), variableValue);
|
||||
events.static.CallVariableUpdated(ID, variableName);
|
||||
events.static.CallFloatVariableUpdated(ID, variableName, variableValue);
|
||||
ownerStorage.remoteRI.ServerSendFloat(V(ID, variableName), variableValue);
|
||||
}
|
||||
|
||||
function SetString(string variableName, string variableValue){
|
||||
if(!HasWriteRights()) return;
|
||||
if(ownerStorage == none) return;
|
||||
if(ownerStorage.remoteRI == none) return;
|
||||
|
||||
_SetString(V(ID, variableName), variableValue);
|
||||
events.static.CallVariableUpdated(ID, variableName);
|
||||
events.static.CallStringVariableUpdated(ID, variableName, variableValue);
|
||||
ownerStorage.remoteRI.ServerSendString(V(ID, variableName), variableValue);
|
||||
}
|
||||
|
||||
function SetClass(string variableName, class<Actor> variableValue){
|
||||
if(!HasWriteRights()) return;
|
||||
if(ownerStorage == none) return;
|
||||
if(ownerStorage.remoteRI == none) return;
|
||||
|
||||
_SetClass(V(ID, variableName), variableValue);
|
||||
events.static.CallVariableUpdated(ID, variableName);
|
||||
events.static.CallClassVariableUpdated(ID, variableName, variableValue);
|
||||
ownerStorage.remoteRI.ServerSendClass(V(ID, variableName), variableValue);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
243
sources/Data/NiceData.uc
Normal file
243
sources/Data/NiceData.uc
Normal file
@ -0,0 +1,243 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceData
|
||||
//==============================================================================
|
||||
// Base class for remote data, defines basic interface,
|
||||
// used by both server and client storages.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NiceData extends NiceRemoteHack
|
||||
abstract
|
||||
config(NicePack);
|
||||
|
||||
var const class<NiceRemoteDataEvents> events;
|
||||
|
||||
enum EValueType{
|
||||
VTYPE_BOOL,
|
||||
VTYPE_BYTE,
|
||||
VTYPE_INT,
|
||||
VTYPE_FLOAT,
|
||||
VTYPE_STRING,
|
||||
VTYPE_CLASS,
|
||||
VTYPE_NULL // Variable doesn't exist (in this storage)
|
||||
};
|
||||
|
||||
struct Variable{
|
||||
var protected string myName;
|
||||
// Value of what type is currently stored in this struct
|
||||
var protected EValueType currentType;
|
||||
|
||||
// Containers for various value types
|
||||
var protected byte storedByte;
|
||||
var protected int storedInt;
|
||||
var protected bool storedBool;
|
||||
var protected float storedFloat;
|
||||
var protected string storedString;
|
||||
var protected class<Actor> storedClass;
|
||||
};
|
||||
|
||||
enum EDataPriority{ // Data change messages from server to client are...
|
||||
// ...sent immediately;
|
||||
NSP_REALTIME,
|
||||
// ...sent with time intervals between them;
|
||||
NSP_HIGH,
|
||||
// ...sent with time intervals between them,
|
||||
// but only if high-priority queue is empty.
|
||||
NSP_LOW
|
||||
// Data change messages from clients are always sent immediately.
|
||||
};
|
||||
|
||||
var protected string ID;
|
||||
var protected array<Variable> variables;
|
||||
|
||||
static function NiceData NewData(string newID){
|
||||
local NiceData newData;
|
||||
newData = new class'NiceData';
|
||||
newData.ID = newID;
|
||||
return newData;
|
||||
}
|
||||
|
||||
function string GetID(){
|
||||
return ID;
|
||||
}
|
||||
|
||||
function bool IsEmpty(){
|
||||
return variables.length <= 0;
|
||||
}
|
||||
|
||||
function EValueType GetVariableType(string variableName){
|
||||
local int index;
|
||||
index = GetVariableIndex(variableName);
|
||||
if(index < 0)
|
||||
return VTYPE_NULL;
|
||||
return variables[index].currentType;
|
||||
}
|
||||
|
||||
function array<string> GetVariableNames(){
|
||||
local int i;
|
||||
local array<string> mapResult;
|
||||
for(i = 0;i < variables.length;i ++)
|
||||
mapResult[i] = variables[i].myName;
|
||||
return mapResult;
|
||||
}
|
||||
|
||||
protected function int GetVariableIndex(string variableName){
|
||||
local int i;
|
||||
for(i = 0;i < variables.length;i ++)
|
||||
if(variables[i].myName ~= variableName)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// > Setter / getters for variables that perform necessary synchronization.
|
||||
|
||||
function SetByte(string variableName, byte variableValue);
|
||||
function byte GetByte(string variableName, optional byte defaultValue){
|
||||
local int index;
|
||||
index = GetVariableIndex(variableName);
|
||||
if(index < 0)
|
||||
return defaultValue;
|
||||
if(variables[index].currentType != EValueType.VTYPE_BYTE)
|
||||
return defaultValue;
|
||||
return variables[index].storedByte;
|
||||
}
|
||||
|
||||
function SetInt(string variableName, int variableValue);
|
||||
function int GetInt(string variableName, optional int defaultValue){
|
||||
local int index;
|
||||
index = GetVariableIndex(variableName);
|
||||
if(index < 0)
|
||||
return defaultValue;
|
||||
if(variables[index].currentType != EValueType.VTYPE_INT)
|
||||
return defaultValue;
|
||||
return variables[index].storedInt;
|
||||
}
|
||||
|
||||
function SetBool(string variableName, bool variableValue);
|
||||
function bool GetBool(string variableName, optional bool defaultValue){
|
||||
local int index;
|
||||
index = GetVariableIndex(variableName);
|
||||
if(index < 0)
|
||||
return defaultValue;
|
||||
if(variables[index].currentType != EValueType.VTYPE_BOOL)
|
||||
return defaultValue;
|
||||
return variables[index].storedBool;
|
||||
}
|
||||
|
||||
function SetFloat(string variableName, float variableValue);
|
||||
function float GetFloat(string variableName, optional float defaultValue){
|
||||
local int index;
|
||||
index = GetVariableIndex(variableName);
|
||||
if(index < 0)
|
||||
return defaultValue;
|
||||
if(variables[index].currentType != EValueType.VTYPE_FLOAT)
|
||||
return defaultValue;
|
||||
return variables[index].storedFloat;
|
||||
}
|
||||
|
||||
function SetString(string variableName, string variableValue);
|
||||
function string GetString(string variableName, optional string defaultValue){
|
||||
local int index;
|
||||
index = GetVariableIndex(variableName);
|
||||
if(index < 0)
|
||||
return defaultValue;
|
||||
if(variables[index].currentType != EValueType.VTYPE_STRING)
|
||||
return defaultValue;
|
||||
return variables[index].storedString;
|
||||
}
|
||||
|
||||
function SetClass(string variableName, class<Actor> variableValue);
|
||||
function class<Actor> GetClass( string variableName,
|
||||
optional class<Actor> defaultValue){
|
||||
local int index;
|
||||
index = GetVariableIndex(variableName);
|
||||
if(index < 0)
|
||||
return defaultValue;
|
||||
if(variables[index].currentType != EValueType.VTYPE_CLASS)
|
||||
return defaultValue;
|
||||
return variables[index].storedClass;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// > Setter that records variables locally, without any synchronization work.
|
||||
// #private
|
||||
function _SetByte(DataRef dataRef, byte variableValue){
|
||||
local int index;
|
||||
local Variable newValue;
|
||||
newValue.myName = dataRef.variable;
|
||||
newValue.storedByte = variableValue;
|
||||
newValue.currentType = VTYPE_BYTE;
|
||||
index = GetVariableIndex(dataRef.variable);
|
||||
if(index < 0)
|
||||
index = variables.length;
|
||||
variables[index] = newValue;
|
||||
}
|
||||
|
||||
function _SetInt(DataRef dataRef, int variableValue){
|
||||
local int index;
|
||||
local Variable newValue;
|
||||
newValue.myName = dataRef.variable;
|
||||
newValue.storedInt = variableValue;
|
||||
newValue.currentType = VTYPE_INT;
|
||||
index = GetVariableIndex(dataRef.variable);
|
||||
if(index < 0)
|
||||
index = variables.length;
|
||||
variables[index] = newValue;
|
||||
}
|
||||
|
||||
function _SetBool(DataRef dataRef, bool variableValue){
|
||||
local int index;
|
||||
local Variable newValue;
|
||||
newValue.myName = dataRef.variable;
|
||||
newValue.storedBool = variableValue;
|
||||
newValue.currentType = VTYPE_BOOL;
|
||||
index = GetVariableIndex(dataRef.variable);
|
||||
if(index < 0)
|
||||
index = variables.length;
|
||||
variables[index] = newValue;
|
||||
}
|
||||
|
||||
function _SetFloat(DataRef dataRef, float variableValue){
|
||||
local int index;
|
||||
local Variable newValue;
|
||||
newValue.myName = dataRef.variable;
|
||||
newValue.storedFloat = variableValue;
|
||||
newValue.currentType = VTYPE_FLOAT;
|
||||
index = GetVariableIndex(dataRef.variable);
|
||||
if(index < 0)
|
||||
index = variables.length;
|
||||
variables[index] = newValue;
|
||||
}
|
||||
|
||||
function _SetString(DataRef dataRef, string variableValue){
|
||||
local int index;
|
||||
local Variable newValue;
|
||||
newValue.myName = dataRef.variable;
|
||||
newValue.storedString = variableValue;
|
||||
newValue.currentType = VTYPE_STRING;
|
||||
index = GetVariableIndex(dataRef.variable);
|
||||
if(index < 0)
|
||||
index = variables.length;
|
||||
variables[index] = newValue;
|
||||
}
|
||||
|
||||
function _SetClass(DataRef dataRef, class<Actor> variableValue){
|
||||
local int index;
|
||||
local Variable newValue;
|
||||
newValue.myName = dataRef.variable;
|
||||
newValue.storedClass = variableValue;
|
||||
newValue.currentType = VTYPE_CLASS;
|
||||
index = GetVariableIndex(dataRef.variable);
|
||||
if(index < 0)
|
||||
index = variables.length;
|
||||
variables[index] = newValue;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
events=class'NiceRemoteDataEvents'
|
||||
}
|
16
sources/Data/NiceDataQueue.uc
Normal file
16
sources/Data/NiceDataQueue.uc
Normal file
@ -0,0 +1,16 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceDataQueue
|
||||
//==============================================================================
|
||||
// Implements a queue of updates for data stored on a server.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NiceDataQueue extends Object
|
||||
config(NicePack);
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
79
sources/Data/NiceRemoteDataAdapter.uc
Normal file
79
sources/Data/NiceRemoteDataAdapter.uc
Normal file
@ -0,0 +1,79 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceRemoteDataAdapter
|
||||
//==============================================================================
|
||||
// Temporary stand-in for future functionality.
|
||||
// Use this class to catch events from storages.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NiceRemoteDataAdapter extends Object
|
||||
dependson(NiceStorageBase);
|
||||
|
||||
var LevelInfo level;
|
||||
|
||||
static function DataCreated(string dataID);
|
||||
|
||||
// Called on clients the moment client storage connects to the server one.
|
||||
static function LinkEstablished();
|
||||
|
||||
// Called on client after server responds to his request
|
||||
// to check if certain data exists.
|
||||
static function DataExistResponse(string dataID, bool doesExist);
|
||||
|
||||
// Called on client after server responds to his connection request.
|
||||
static function ConnectionRequestResponse
|
||||
( string dataID,
|
||||
NiceStorageBase.ECreateDataResponse response
|
||||
);
|
||||
|
||||
// Fired-off when writing rights to a certain data were granted.
|
||||
// Always called on server.
|
||||
// Only called on client that gained writing rights.
|
||||
static function WriteAccessGranted( string dataID,
|
||||
NicePlayerController newOwner);
|
||||
|
||||
// Fired-off when server refused to grant writing rights to data.
|
||||
// Always called on server.
|
||||
// Only called on client that tried to gain writing rights.
|
||||
static function WriteAccessRevoked( string dataID,
|
||||
NicePlayerController newOwner);
|
||||
|
||||
// Fired-off when writing rights to a certain data were revoked.
|
||||
// Always called on server.
|
||||
// Only called on client that lost writing rights.
|
||||
static function WriteAccessRefused( string dataID,
|
||||
NicePlayerController newOwner);
|
||||
|
||||
// Fired off on client when server finished sending him all the info about
|
||||
// particular data set.
|
||||
static function DataUpToDate(string dataID);
|
||||
|
||||
// Fire off on server and listening clients when
|
||||
// a particular variable was updated.
|
||||
static function VariableUpdated( string dataID,
|
||||
string varName);
|
||||
static function BoolVariableUpdated(string dataID,
|
||||
string varName,
|
||||
bool newValue);
|
||||
static function ByteVariableUpdated(string dataID,
|
||||
string varName,
|
||||
byte newValue);
|
||||
static function IntVariableUpdated( string dataID,
|
||||
string varName,
|
||||
int newValue);
|
||||
static function FloatVariableUpdated( string dataID,
|
||||
string varName,
|
||||
float newValue);
|
||||
static function StringVariableUpdated( string dataID,
|
||||
string varName,
|
||||
string newValue);
|
||||
static function ClassVariableUpdated( string dataID,
|
||||
string varName,
|
||||
class<Actor> newValue);
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
149
sources/Data/NiceRemoteDataEvents.uc
Normal file
149
sources/Data/NiceRemoteDataEvents.uc
Normal file
@ -0,0 +1,149 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceRemoteDataEvents
|
||||
//==============================================================================
|
||||
// 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 NiceRemoteDataEvents extends Object
|
||||
dependson(NiceStorageBase);
|
||||
|
||||
var array< class<NiceRemoteDataAdapter> > adapters;
|
||||
|
||||
// If adapter was already added also returns 'false'.
|
||||
static function bool AddAdapter(class<NiceRemoteDataAdapter> 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<NiceRemoteDataAdapter> 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 CallLinkEstablished(){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.LinkEstablished();
|
||||
}
|
||||
|
||||
static function CallDataCreated(string dataID){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.DataCreated(dataID);
|
||||
}
|
||||
|
||||
static function CallDataExistResponse(string dataID, bool doesExist){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.DataExistResponse(dataID, doesExist);
|
||||
}
|
||||
|
||||
static function CallConnectionRequestResponse
|
||||
( string dataID,
|
||||
NiceStorageBase.ECreateDataResponse response
|
||||
){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.ConnectionRequestResponse(dataID, response);
|
||||
}
|
||||
|
||||
static function CallVariableUpdated(string dataID, string variableName){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.VariableUpdated(dataID, variableName);
|
||||
}
|
||||
|
||||
static function CallBoolVariableUpdated(string dataID, string variableName,
|
||||
bool newValue){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.BoolVariableUpdated( dataID, variableName,
|
||||
newValue);
|
||||
}
|
||||
|
||||
static function CallByteVariableUpdated(string dataID, string variableName,
|
||||
byte newValue){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.ByteVariableUpdated( dataID, variableName,
|
||||
newValue);
|
||||
}
|
||||
|
||||
static function CallIntVariableUpdated( string dataID, string variableName,
|
||||
int newValue){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.IntVariableUpdated( dataID, variableName,
|
||||
newValue);
|
||||
}
|
||||
|
||||
static function CallFloatVariableUpdated( string dataID, string variableName,
|
||||
float newValue){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.FloatVariableUpdated(dataID, variableName,
|
||||
newValue);
|
||||
}
|
||||
|
||||
static function CallStringVariableUpdated( string dataID, string variableName,
|
||||
string newValue){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.StringVariableUpdated( dataID,
|
||||
variableName,
|
||||
newValue);
|
||||
}
|
||||
|
||||
static function CallClassVariableUpdated( string dataID, string variableName,
|
||||
class<Actor> newValue){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.ClassVariableUpdated(dataID, variableName,
|
||||
newValue);
|
||||
}
|
||||
|
||||
static function CallDataUpToDate(string dataID){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.DataUpToDate(dataID);
|
||||
}
|
||||
|
||||
static function CallWriteAccessGranted( string dataID,
|
||||
NicePlayerController newOwner){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.WriteAccessGranted(dataID, newOwner);
|
||||
}
|
||||
|
||||
static function CallWritingAccessRevoked( string dataID,
|
||||
NicePlayerController newOwner){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.WriteAccessRevoked(dataID, newOwner);
|
||||
}
|
||||
|
||||
static function CallWriteAccessRefused( string dataID,
|
||||
NicePlayerController newOwner){
|
||||
local int i;
|
||||
for(i = 0;i < default.adapters.length;i ++)
|
||||
default.adapters[i].static.WriteAccessRefused(dataID, newOwner);
|
||||
}
|
47
sources/Data/NiceRemoteHack.uc
Normal file
47
sources/Data/NiceRemoteHack.uc
Normal file
@ -0,0 +1,47 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceRemoteHack
|
||||
//==============================================================================
|
||||
// Structure introduced for simple 'hack':
|
||||
// ~ We want our replication info class to call methods that
|
||||
// we would otherwise mark as 'protected';
|
||||
// ~ To make this possible we introduce this structure that would can only
|
||||
// be filled with valid data (non-empty name of relevant data)
|
||||
// by other protected methods of this class;
|
||||
// ~ Methods that that we wish only replication info to access will accept
|
||||
// this structure as a parameter and only function if
|
||||
// it's filled with valid data.
|
||||
// ~ This way users won't be able to actually make these methods
|
||||
// do any work, but replication info, that will be called from within
|
||||
// with valid 'DataRef' structure, will be able to invoke them.
|
||||
// ~ In addition we add the ability for this structure
|
||||
// to point at a specific variable.
|
||||
// ~ Such variables are marked with '#private' in comments.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NiceRemoteHack extends Object
|
||||
abstract;
|
||||
|
||||
struct DataRef{
|
||||
var protected string ID;
|
||||
var protected string variable;
|
||||
};
|
||||
|
||||
// Creates validation structure for data set with a given name
|
||||
protected function DataRef V(string ID, optional string variable){
|
||||
local DataRef validRef;
|
||||
validRef.ID = ID;
|
||||
validRef.variable = variable;
|
||||
return validRef;
|
||||
}
|
||||
|
||||
static function string GetDataRefID(DataRef dataRef){
|
||||
return dataRef.ID;
|
||||
}
|
||||
|
||||
static function string GetDataRefVar(DataRef dataRef){
|
||||
return dataRef.variable;
|
||||
}
|
258
sources/Data/NiceRepInfoRemoteData.uc
Normal file
258
sources/Data/NiceRepInfoRemoteData.uc
Normal file
@ -0,0 +1,258 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceRepInfoRemoteData
|
||||
//==============================================================================
|
||||
// Replication info class for replicating messages needed by Storage system.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NiceRepInfoRemoteData extends ReplicationInfo
|
||||
dependson(NiceRemoteHack);
|
||||
|
||||
replication{
|
||||
reliable if(Role == ROLE_Authority)
|
||||
ClientConnectionResponse, ClientDataExistResponse,
|
||||
ClientOpenWriteRights, ClientCloseWriteRights, ClientRefuseWriteRights;
|
||||
reliable if(Role < ROLE_Authority)
|
||||
ServerCreateData, ServerAddListener, ServerAskDataExist,
|
||||
ServerRequestWriteAccess, ServerGiveupWriteAccess;
|
||||
// For sending data
|
||||
reliable if(Role == ROLE_Authority)
|
||||
ClientSendBool, ClientSendByte, ClientSendInt, ClientSendFloat,
|
||||
ClientSendString, ClientSendClass;
|
||||
reliable if(Role < ROLE_Authority)
|
||||
ServerSendBool, ServerSendByte, ServerSendInt, ServerSendFloat,
|
||||
ServerSendString, ServerSendClass;
|
||||
}
|
||||
|
||||
// These variables are needed in almost every function in this class,
|
||||
// so they're declared in a scope of whole class and are setup via
|
||||
// 'SetupVars' call.
|
||||
var string dataID;
|
||||
var string dataVarName;
|
||||
var NiceData remoteData;
|
||||
var NiceStorageBase storage;
|
||||
var NiceStorageClient storageClient;
|
||||
var NiceStorageServer storageServer;
|
||||
var NicePlayerController ownerPlayer;
|
||||
|
||||
simulated function SetupVars(NiceRemoteHack.DataRef dataRef){
|
||||
dataID = class'NiceRemoteHack'.static.GetDataRefID(dataRef);
|
||||
dataVarName = class'NiceRemoteHack'.static.GetDataRefVar(dataRef);
|
||||
storage = class'NicePack'.static.GetStorage(level);
|
||||
ownerPlayer = NicePlayerController(owner);
|
||||
if(level.netMode == NM_DedicatedServer)
|
||||
storageServer = NiceStorageServer(storage);
|
||||
else
|
||||
storageClient = NiceStorageClient(storage);
|
||||
if(storage != none)
|
||||
remoteData = storage.GetData(dataID);
|
||||
}
|
||||
|
||||
function ServerSendBool(NiceRemoteHack.DataRef dataRef, bool varValue){
|
||||
SetupVars(dataRef);
|
||||
if(remoteData == none) return;
|
||||
remoteData.SetBool(dataVarName, varValue);
|
||||
}
|
||||
|
||||
function ServerSendByte(NiceRemoteHack.DataRef dataRef, byte varValue){
|
||||
SetupVars(dataRef);
|
||||
if(remoteData == none) return;
|
||||
remoteData.SetByte(dataVarName, varValue);
|
||||
}
|
||||
|
||||
function ServerSendInt(NiceRemoteHack.DataRef dataRef, int varValue){
|
||||
SetupVars(dataRef);
|
||||
if(remoteData == none) return;
|
||||
remoteData.SetInt(dataVarName, varValue);
|
||||
}
|
||||
|
||||
function ServerSendFloat(NiceRemoteHack.DataRef dataRef, float varValue){
|
||||
SetupVars(dataRef);
|
||||
if(remoteData == none) return;
|
||||
remoteData.SetFloat(dataVarName, varValue);
|
||||
}
|
||||
|
||||
function ServerSendString(NiceRemoteHack.DataRef dataRef, string varValue){
|
||||
SetupVars(dataRef);
|
||||
if(remoteData == none) return;
|
||||
remoteData.SetString(dataVarName, varValue);
|
||||
}
|
||||
|
||||
function ServerSendClass(NiceRemoteHack.DataRef dataRef, class<Actor> varValue){
|
||||
SetupVars(dataRef);
|
||||
if(remoteData == none) return;
|
||||
remoteData.SetClass(dataVarName, varValue);
|
||||
}
|
||||
|
||||
simulated function ClientSendByte( NiceRemoteHack.DataRef dataRef,
|
||||
byte varValue,
|
||||
bool replicationFinished){
|
||||
if(level.netMode == NM_DedicatedServer) return;
|
||||
// Full 'SetupVars' is an overkill
|
||||
storageClient = NiceStorageClient(class'NicePack'.static.GetStorage(level));
|
||||
if(storageClient == none) return;
|
||||
storageClient.CheckinByte(dataRef, varValue, replicationFinished);
|
||||
}
|
||||
|
||||
simulated function ClientSendBool( NiceRemoteHack.DataRef dataRef,
|
||||
bool varValue,
|
||||
bool replicationFinished){
|
||||
if(level.netMode == NM_DedicatedServer) return;
|
||||
// Full 'SetupVars' is an overkill
|
||||
storageClient = NiceStorageClient(class'NicePack'.static.GetStorage(level));
|
||||
if(storageClient == none) return;
|
||||
storageClient.CheckinBool(dataRef, varValue, replicationFinished);
|
||||
}
|
||||
|
||||
simulated function ClientSendInt( NiceRemoteHack.DataRef dataRef,
|
||||
int varValue,
|
||||
bool replicationFinished){
|
||||
if(level.netMode == NM_DedicatedServer) return;
|
||||
// Full 'SetupVars' is an overkill
|
||||
storageClient = NiceStorageClient(class'NicePack'.static.GetStorage(level));
|
||||
if(storageClient == none) return;
|
||||
storageClient.CheckinInt(dataRef, varValue, replicationFinished);
|
||||
}
|
||||
|
||||
simulated function ClientSendFloat( NiceRemoteHack.DataRef dataRef,
|
||||
float varValue,
|
||||
bool replicationFinished){
|
||||
if(level.netMode == NM_DedicatedServer) return;
|
||||
// Full 'SetupVars' is an overkill
|
||||
storageClient = NiceStorageClient(class'NicePack'.static.GetStorage(level));
|
||||
if(storageClient == none) return;
|
||||
storageClient.CheckinFloat(dataRef, varValue, replicationFinished);
|
||||
}
|
||||
|
||||
simulated function ClientSendString(NiceRemoteHack.DataRef dataRef,
|
||||
string varValue,
|
||||
bool replicationFinished){
|
||||
if(level.netMode == NM_DedicatedServer) return;
|
||||
// Full 'SetupVars' is an overkill
|
||||
storageClient = NiceStorageClient(class'NicePack'.static.GetStorage(level));
|
||||
if(storageClient == none) return;
|
||||
storageClient.CheckinString(dataRef, varValue, replicationFinished);
|
||||
}
|
||||
|
||||
simulated function ClientSendClass( NiceRemoteHack.DataRef dataRef,
|
||||
class<Actor> varValue,
|
||||
bool replicationFinished){
|
||||
if(level.netMode == NM_DedicatedServer) return;
|
||||
// Full 'SetupVars' is an overkill
|
||||
storageClient = NiceStorageClient(class'NicePack'.static.GetStorage(level));
|
||||
if(storageClient == none) return;
|
||||
storageClient.CheckinClass(dataRef, varValue, replicationFinished);
|
||||
}
|
||||
|
||||
function ServerCreateData( NiceRemoteHack.DataRef dataRef,
|
||||
NiceData.EDataPriority priority){
|
||||
local NiceServerData serverData;
|
||||
SetupVars(dataRef);
|
||||
if(ownerPlayer == none) return;
|
||||
if(storageServer == none) return;
|
||||
if(storageServer.CreateData(dataID, priority))
|
||||
ClientConnectionResponse(dataRef, NSCDR_CREATED, true);
|
||||
else{
|
||||
if(remoteData != none)
|
||||
// We've failed to create new data because it already exists;
|
||||
ClientConnectionResponse( dataRef, NSCDR_ALREADYEXISTS,
|
||||
remoteData.IsEmpty());
|
||||
else
|
||||
// We've failed to create new data for some other reason.
|
||||
ClientConnectionResponse(dataRef, NSCDR_DOESNTEXIST, true);
|
||||
}
|
||||
serverData = NiceServerData(remoteData);
|
||||
if(serverData != none)
|
||||
serverData.AddListener(ownerPlayer);
|
||||
}
|
||||
|
||||
function ServerAddListener(NiceRemoteHack.DataRef dataRef){
|
||||
local NiceServerData serverData;
|
||||
SetupVars(dataRef);
|
||||
if(ownerPlayer == none) return;
|
||||
if(storageServer == none) return;
|
||||
serverData = NiceServerData(remoteData);
|
||||
if(serverData != none){
|
||||
ClientConnectionResponse( dataRef, NSCDR_CONNECTED,
|
||||
serverData.IsEmpty());
|
||||
}
|
||||
else
|
||||
ClientConnectionResponse(dataRef, NSCDR_DOESNTEXIST, true);
|
||||
if(serverData != none)
|
||||
serverData.AddListener(ownerPlayer);
|
||||
}
|
||||
|
||||
function ServerAskDataExist(NiceRemoteHack.DataRef dataRef){
|
||||
SetupVars(dataRef);
|
||||
if(storage == none) return;
|
||||
ClientDataExistResponse(dataRef, storage.DoesDataExistLocally(dataID));
|
||||
}
|
||||
|
||||
simulated function ClientDataExistResponse( NiceRemoteHack.DataRef dataRef,
|
||||
bool doesExist){
|
||||
if(level.netMode == NM_DedicatedServer) return;
|
||||
SetupVars(dataRef);
|
||||
if(storage == none) return;
|
||||
storage.events.static.CallDataExistResponse(dataID, doesExist);
|
||||
}
|
||||
|
||||
simulated function ClientConnectionResponse
|
||||
(
|
||||
NiceRemoteHack.DataRef dataRef,
|
||||
NiceStorageBase.ECreateDataResponse response,
|
||||
bool replicationFinished
|
||||
){
|
||||
if(level.netMode == NM_DedicatedServer) return;
|
||||
SetupVars(dataRef);
|
||||
if(storageClient == none) return;
|
||||
if(response != NSCDR_DOESNTEXIST)
|
||||
storageClient.CheckinData(dataRef, replicationFinished);
|
||||
storageClient.events.static.CallConnectionRequestResponse(dataID, response);
|
||||
}
|
||||
|
||||
simulated function ClientOpenWriteRights(NiceRemoteHack.DataRef dataRef){
|
||||
local NiceClientData clientData;
|
||||
if(level.netMode == NM_DedicatedServer) return;
|
||||
SetupVars(dataRef);
|
||||
clientData = NiceClientData(remoteData);
|
||||
if(clientData == none)
|
||||
return;
|
||||
clientData.SetWriteRights(dataRef, true);
|
||||
storageClient.events.static.CallWriteAccessGranted(dataID, ownerPlayer);
|
||||
}
|
||||
|
||||
simulated function ClientCloseWriteRights(NiceRemoteHack.DataRef dataRef){
|
||||
local NiceClientData clientData;
|
||||
if(level.netMode == NM_DedicatedServer) return;
|
||||
SetupVars(dataRef);
|
||||
clientData = NiceClientData(remoteData);
|
||||
if(clientData == none)
|
||||
return;
|
||||
clientData.SetWriteRights(dataRef, false);
|
||||
storageClient.events.static.CallWritingAccessRevoked(dataID, ownerPlayer);
|
||||
}
|
||||
|
||||
simulated function ClientRefuseWriteRights(NiceRemoteHack.DataRef dataRef){
|
||||
if(level.netMode == NM_DedicatedServer) return;
|
||||
SetupVars(dataRef);
|
||||
storageClient.events.static.CallWriteAccessRefused(dataID, ownerPlayer);
|
||||
}
|
||||
|
||||
function ServerRequestWriteAccess(NiceRemoteHack.DataRef dataRef){
|
||||
SetupVars(dataRef);
|
||||
if(storageServer == none) return;
|
||||
storageServer.OpenWriteAccess(dataRef, ownerPlayer);
|
||||
}
|
||||
|
||||
function ServerGiveupWriteAccess(NiceRemoteHack.DataRef dataRef){
|
||||
SetupVars(dataRef);
|
||||
if(storageServer == none) return;
|
||||
storageServer.CloseWriteAccess(dataRef);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
262
sources/Data/NiceServerData.uc
Normal file
262
sources/Data/NiceServerData.uc
Normal file
@ -0,0 +1,262 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceServerData
|
||||
//==============================================================================
|
||||
// Adds data interface relevant only to server,
|
||||
// as well as server implementation of more general functions.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NiceServerData extends NiceData
|
||||
config(NicePack);
|
||||
|
||||
var NiceStorageServer ownerStorage;
|
||||
var EDataPriority priority;
|
||||
// Priority should only be set once, otherwise it can lead to issues
|
||||
var bool wasPrioritySet;
|
||||
// List of players who've requested replication of relevant Data set
|
||||
var array<NicePlayerController> listeners;
|
||||
// We can currently send server changes in this data
|
||||
var protected NicePlayerController writeRightsOwner;
|
||||
// Only admin players can get writing access to this data
|
||||
// (but once writing access is given
|
||||
// it won't close until player closes it or disconnects)
|
||||
var bool isAdminOnly;
|
||||
|
||||
static function NiceData NewData(string newID){
|
||||
local NiceData newData;
|
||||
newData = new class'NiceServerData';
|
||||
newData.ID = newID;
|
||||
return newData;
|
||||
}
|
||||
|
||||
function EDataPriority GetPriority(){
|
||||
return priority;
|
||||
}
|
||||
|
||||
// #private
|
||||
function SetOwnerStorage( NiceRemoteHack.DataRef dataRef,
|
||||
NiceStorageServerBase newOwner){
|
||||
if(ID ~= class'NiceRemoteHack'.static.GetDataRefID(dataRef))
|
||||
ownerStorage = NiceStorageServer(newOwner);//NICETODO: temp hack
|
||||
}
|
||||
|
||||
// #private
|
||||
function SetPriority( NiceRemoteHack.DataRef dataRef,
|
||||
EDataPriority newPriority){
|
||||
if(wasPrioritySet) return;
|
||||
if(ID ~= class'NiceRemoteHack'.static.GetDataRefID(dataRef)){
|
||||
priority = newPriority;
|
||||
wasPrioritySet = true;
|
||||
}
|
||||
}
|
||||
|
||||
function NicePlayerController GetWriteRightsOwner(){
|
||||
return writeRightsOwner;
|
||||
}
|
||||
|
||||
// #private
|
||||
function SetWriteRightsOwner( NiceRemoteHack.DataRef dataRef,
|
||||
NicePlayerController newOwner){
|
||||
if(ID ~= class'NiceRemoteHack'.static.GetDataRefID(dataRef))
|
||||
writeRightsOwner = newOwner;
|
||||
}
|
||||
|
||||
// Add 'NicePlayerController' referencing a player that should
|
||||
// start listening to changes in this data set
|
||||
function AddListener(NicePlayerController niceClient){
|
||||
local int i;
|
||||
if(ownerStorage == none) return;
|
||||
if(niceClient == none || niceClient.remoteRI == none) return;
|
||||
|
||||
// Make sure this client isn't already added
|
||||
for(i = 0;i < listeners.length;i ++)
|
||||
if(listeners[i] == niceClient)
|
||||
return;
|
||||
listeners[listeners.length] = niceClient;
|
||||
ownerStorage.AddConnection(niceClient);
|
||||
// Replicate all the current data to this client
|
||||
if(priority == NSP_REALTIME)
|
||||
ReplicateToClient(V(ID), niceClient);
|
||||
else
|
||||
ownerStorage.PushDataIntoQueue(V(ID), niceClient, priority);
|
||||
}
|
||||
|
||||
function bool IsListener(NicePlayerController niceClient){
|
||||
local int i;
|
||||
if(niceClient == none) return false;
|
||||
for(i = 0;i < listeners.length;i ++)
|
||||
if(niceClient == listeners[i])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// When the client disconnects - references to it's PC become 'null'.
|
||||
// This function gets gets rid of them.
|
||||
// #private
|
||||
function PurgeNullListeners(DataRef dataRef){
|
||||
local int i;
|
||||
local array<NicePlayerController> newListeners;
|
||||
if(dataRef.ID != ID) return;
|
||||
for(i = 0;i < listeners.length;i ++)
|
||||
if(listeners[i] != none)
|
||||
newListeners[newListeners.length] = listeners[i];
|
||||
listeners = newListeners;
|
||||
}
|
||||
|
||||
// #private
|
||||
function ReplicateToClient( NiceRemoteHack.DataRef dataRef,
|
||||
NicePlayerController nicePlayer){
|
||||
local int i;
|
||||
if(nicePlayer == none || nicePlayer.remoteRI == none) return;
|
||||
// Replication is only finished with last variable
|
||||
for(i = 0;i < variables.length - 1;i ++)
|
||||
ReplicateVariableToClient(V(ID), variables[i].myName, nicePlayer, false);
|
||||
ReplicateVariableToClient(V(ID), variables[variables.length - 1].myName,
|
||||
nicePlayer, true);
|
||||
}
|
||||
|
||||
// #private
|
||||
function ReplicateVariableToAll(NiceRemoteHack.DataRef dataRef,
|
||||
string variable){
|
||||
local int i;
|
||||
if(ID ~= class'NiceRemoteHack'.static.GetDataRefID(dataRef)){
|
||||
for(i = 0;i < listeners.length;i ++)
|
||||
ReplicateVariableToClient(V(ID), variable, listeners[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
// Guaranteed to check that 'niceClient' and it's 'remoteRI' are '!= none'.
|
||||
// #private
|
||||
function ReplicateVariableToClient( NiceRemoteHack.DataRef dataRef,
|
||||
string variable,
|
||||
NicePlayerController niceClient,
|
||||
bool replicationFinished){
|
||||
local int index;
|
||||
if(niceClient == none || niceClient.remoteRI == none) return;
|
||||
index = GetVariableIndex(variable);
|
||||
if(index < 0)
|
||||
return;
|
||||
// NICETODO: change replication function based on variable's type
|
||||
switch(variables[index].currentType){
|
||||
case VTYPE_BOOL:
|
||||
niceClient.remoteRI.ClientSendBool( V(ID, variables[index].myName),
|
||||
variables[index].storedBool,
|
||||
replicationFinished);
|
||||
break;
|
||||
case VTYPE_BYTE:
|
||||
niceClient.remoteRI.ClientSendBYTE( V(ID, variables[index].myName),
|
||||
variables[index].storedByte,
|
||||
replicationFinished);
|
||||
break;
|
||||
case VTYPE_INT:
|
||||
niceClient.remoteRI.ClientSendInt( V(ID, variables[index].myName),
|
||||
variables[index].storedInt,
|
||||
replicationFinished);
|
||||
break;
|
||||
case VTYPE_FLOAT:
|
||||
niceClient.remoteRI.ClientSendFloat(V(ID, variables[index].myName),
|
||||
variables[index].storedFloat,
|
||||
replicationFinished);
|
||||
break;
|
||||
case VTYPE_STRING:
|
||||
niceClient.remoteRI.ClientSendString(V(ID, variables[index].myName),
|
||||
variables[index].storedString,
|
||||
replicationFinished);
|
||||
break;
|
||||
case VTYPE_CLASS:
|
||||
niceClient.remoteRI.ClientSendClass(V(ID, variables[index].myName),
|
||||
variables[index].storedClass,
|
||||
replicationFinished);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// > Setter / getters for variables that perform necessary synchronization
|
||||
function SetByte(string variableName, byte variableValue){
|
||||
if(writeRightsOwner != none) return;
|
||||
|
||||
_SetByte(V(ID, variableName), variableValue);
|
||||
events.static.CallVariableUpdated(ID, variableName);
|
||||
events.static.CallByteVariableUpdated(ID, variableName, variableValue);
|
||||
|
||||
if(priority == NSP_REALTIME)
|
||||
ReplicateVariableToAll(V(ID), variableName);
|
||||
else
|
||||
ownerStorage.PushRequestIntoQueues(V(ID), variableName, priority);
|
||||
}
|
||||
|
||||
function SetInt(string variableName, int variableValue){
|
||||
if(writeRightsOwner != none) return;
|
||||
|
||||
_SetInt(V(ID, variableName), variableValue);
|
||||
events.static.CallVariableUpdated(ID, variableName);
|
||||
events.static.CallIntVariableUpdated(ID, variableName, variableValue);
|
||||
|
||||
if(priority == NSP_REALTIME)
|
||||
ReplicateVariableToAll(V(ID), variableName);
|
||||
else
|
||||
ownerStorage.PushRequestIntoQueues(V(ID), variableName, priority);
|
||||
}
|
||||
|
||||
function SetBool(string variableName, bool variableValue){
|
||||
if(writeRightsOwner != none) return;
|
||||
|
||||
_SetBool(V(ID, variableName), variableValue);
|
||||
events.static.CallVariableUpdated(ID, variableName);
|
||||
events.static.CallBoolVariableUpdated(ID, variableName, variableValue);
|
||||
|
||||
if(priority == NSP_REALTIME)
|
||||
ReplicateVariableToAll(V(ID), variableName);
|
||||
else
|
||||
ownerStorage.PushRequestIntoQueues(V(ID), variableName, priority);
|
||||
}
|
||||
|
||||
function SetFloat(string variableName, float variableValue){
|
||||
if(writeRightsOwner != none) return;
|
||||
|
||||
_SetFloat(V(ID, variableName), variableValue);
|
||||
events.static.CallVariableUpdated(ID, variableName);
|
||||
events.static.CallFloatVariableUpdated(ID, variableName, variableValue);
|
||||
|
||||
if(priority == NSP_REALTIME)
|
||||
ReplicateVariableToAll(V(ID), variableName);
|
||||
else
|
||||
ownerStorage.PushRequestIntoQueues(V(ID), variableName, priority);
|
||||
}
|
||||
|
||||
function SetString(string variableName, string variableValue){
|
||||
if(writeRightsOwner != none) return;
|
||||
|
||||
_SetString(V(ID, variableName), variableValue);
|
||||
events.static.CallVariableUpdated(ID, variableName);
|
||||
events.static.CallStringVariableUpdated(ID, variableName, variableValue);
|
||||
|
||||
if(priority == NSP_REALTIME)
|
||||
ReplicateVariableToAll(V(ID), variableName);
|
||||
else
|
||||
ownerStorage.PushRequestIntoQueues(V(ID), variableName, priority);
|
||||
}
|
||||
|
||||
function SetClass(string variableName, class<Actor> variableValue){
|
||||
if(writeRightsOwner != none) return;
|
||||
|
||||
_SetClass(V(ID, variableName), variableValue);
|
||||
events.static.CallVariableUpdated(ID, variableName);
|
||||
events.static.CallClassVariableUpdated(ID, variableName, variableValue);
|
||||
|
||||
if(priority == NSP_REALTIME)
|
||||
ReplicateVariableToAll(V(ID), variableName);
|
||||
else
|
||||
ownerStorage.PushRequestIntoQueues(V(ID), variableName, priority);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
wasPrioritySet=false
|
||||
}
|
51
sources/Data/NiceStorageBase.uc
Normal file
51
sources/Data/NiceStorageBase.uc
Normal file
@ -0,0 +1,51 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceStorageBase
|
||||
//==============================================================================
|
||||
// Basic storage interface for creating and fetching data instances,
|
||||
// relevant on both client and server.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NiceStorageBase extends NiceRemoteHack
|
||||
abstract
|
||||
config(NicePack);
|
||||
|
||||
var const class<NiceRemoteDataEvents> events;
|
||||
// Type of actor variables used on this storage to collect data
|
||||
var const class<NiceData> dataClass;
|
||||
// Data collected so far
|
||||
var protected array<NiceData> localStorage;
|
||||
|
||||
enum ECreateDataResponse{
|
||||
NSCDR_CONNECTED,
|
||||
NSCDR_ALREADYEXISTS,
|
||||
NSCDR_CREATED,
|
||||
NSCDR_DOESNTEXIST
|
||||
};
|
||||
|
||||
function bool CreateData(string ID, NiceData.EDataPriority priority);
|
||||
|
||||
function bool DoesDataExistLocally(string ID){
|
||||
if(GetData(ID) == none)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function NiceData GetData(string ID){
|
||||
local int i;
|
||||
for(i = 0;i < localStorage.length;i ++){
|
||||
if(localStorage[i] == none) continue;
|
||||
if(localStorage[i].GetID() ~= ID)
|
||||
return localStorage[i];
|
||||
}
|
||||
return none;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
dataClass=class'NiceData'
|
||||
events=class'NiceRemoteDataEvents'
|
||||
}
|
191
sources/Data/NiceStorageClient.uc
Normal file
191
sources/Data/NiceStorageClient.uc
Normal file
@ -0,0 +1,191 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceStorageClient
|
||||
//==============================================================================
|
||||
// Implements storage methods relevant only to client.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NiceStorageClient extends NiceStorageBase
|
||||
config(NicePack);
|
||||
|
||||
var NiceRepInfoRemoteData remoteRI;
|
||||
|
||||
function bool ConnectData(string ID){
|
||||
if(ID == "") return false;
|
||||
if(remoteRI == none) return false;
|
||||
remoteRI.ServerAddListener(V(ID));
|
||||
return true;
|
||||
}
|
||||
|
||||
function bool IsLinkEstablished(){
|
||||
return (remoteRI == none);
|
||||
}
|
||||
|
||||
// Requests a creation of remote data storage on server.
|
||||
function bool CreateData(string ID, NiceData.EDataPriority priority){
|
||||
if(ID == "") return false;
|
||||
if(remoteRI == none) return false;
|
||||
if(DoesDataExistLocally(ID)) return false;
|
||||
remoteRI.ServerCreateData(V(ID), priority);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checks if server has data with a given name.
|
||||
// Responds via calling 'DataExistResponse' event.
|
||||
function DoesDataExistOnServer(string dataID){
|
||||
if(remoteRI == none) return;
|
||||
if(DoesDataExistLocally(dataID))
|
||||
events.static.CallDataExistResponse(dataID, true);
|
||||
else
|
||||
remoteRI.ServerAskDataExist(V(dataID));
|
||||
}
|
||||
|
||||
// Must be already connected to data to do this
|
||||
function bool RequestWriteAccess(string dataID){
|
||||
if(remoteRI == none) return false;
|
||||
if(!DoesDataExistLocally(dataID)) return false;
|
||||
remoteRI.ServerRequestWriteAccess(V(dataID));
|
||||
return true;
|
||||
}
|
||||
|
||||
function bool GiveupWriteAccess(string dataID){
|
||||
local NiceClientData data;
|
||||
if(remoteRI == none) return false;
|
||||
if(!DoesDataExistLocally(dataID)) return false;
|
||||
|
||||
data = NiceClientData(GetData(dataID));
|
||||
if(data == none || !data.HasWriteRights())
|
||||
return false;
|
||||
data.SetWriteRights(V(dataID), false);
|
||||
remoteRI.ServerGiveupWriteAccess(V(dataID));
|
||||
return true;
|
||||
}
|
||||
|
||||
// #private
|
||||
function CheckinData(DataRef dataRef, bool replicationFinished){
|
||||
local NiceClientData clientData;
|
||||
// This shouldn't happen, but just in case
|
||||
if(DoesDataExistLocally(dataRef.ID)) return;
|
||||
// Create data as requested
|
||||
clientData =
|
||||
NiceClientData(class'NiceClientData'.static.NewData(dataRef.ID));
|
||||
if(clientData == none)
|
||||
return;
|
||||
localStorage[localStorage.length] = clientData;
|
||||
clientData.SetOwnerStorage(dataRef, self);
|
||||
clientData.SetUpToDate(dataRef, replicationFinished);
|
||||
}
|
||||
|
||||
// #private
|
||||
function CheckinBool(DataRef dataRef, bool value, bool replicationFinished){
|
||||
local NiceClientData clientData;
|
||||
|
||||
clientData = NiceClientData(GetData(dataRef.ID));
|
||||
if(clientData == none)
|
||||
return;
|
||||
clientData.SetUpToDate(dataRef, replicationFinished);
|
||||
clientData._SetBool(dataRef, value);
|
||||
// Events
|
||||
events.static.CallVariableUpdated(dataRef.ID, dataRef.variable);
|
||||
events.static.CallBoolVariableUpdated(dataRef.ID, dataRef.variable, value);
|
||||
if(replicationFinished)
|
||||
events.static.CallDataUpToDate(dataRef.ID);
|
||||
}
|
||||
|
||||
function CheckinByte(DataRef dataRef, byte value, bool replicationFinished){
|
||||
local NiceClientData clientData;
|
||||
|
||||
clientData = NiceClientData(GetData(dataRef.ID));
|
||||
if(clientData == none)
|
||||
return;
|
||||
clientData.SetUpToDate(dataRef, replicationFinished);
|
||||
clientData._SetByte(dataRef, value);
|
||||
// Events
|
||||
events.static.CallVariableUpdated(dataRef.ID, dataRef.variable);
|
||||
events.static.CallByteVariableUpdated(dataRef.ID, dataRef.variable, value);
|
||||
if(replicationFinished)
|
||||
events.static.CallDataUpToDate(dataRef.ID);
|
||||
}
|
||||
|
||||
function CheckinInt(DataRef dataRef, int value, bool replicationFinished){
|
||||
local NiceClientData clientData;
|
||||
|
||||
clientData = NiceClientData(GetData(dataRef.ID));
|
||||
if(clientData == none)
|
||||
return;
|
||||
clientData.SetUpToDate(dataRef, replicationFinished);
|
||||
clientData._SetInt(dataRef, value);
|
||||
// Events
|
||||
events.static.CallVariableUpdated(dataRef.ID, dataRef.variable);
|
||||
events.static.CallIntVariableUpdated(dataRef.ID, dataRef.variable, value);
|
||||
if(replicationFinished)
|
||||
events.static.CallDataUpToDate(dataRef.ID);
|
||||
}
|
||||
|
||||
function CheckinFloat(DataRef dataRef, float value, bool replicationFinished){
|
||||
local NiceClientData clientData;
|
||||
|
||||
clientData = NiceClientData(GetData(dataRef.ID));
|
||||
if(clientData == none)
|
||||
return;
|
||||
clientData.SetUpToDate(dataRef, replicationFinished);
|
||||
clientData._SetFloat(dataRef, value);
|
||||
// Events
|
||||
events.static.CallVariableUpdated(dataRef.ID, dataRef.variable);
|
||||
events.static.CallFloatVariableUpdated(dataRef.ID, dataRef.variable, value);
|
||||
if(replicationFinished)
|
||||
events.static.CallDataUpToDate(dataRef.ID);
|
||||
}
|
||||
|
||||
function CheckinString(DataRef dataRef, string value, bool replicationFinished){
|
||||
local NiceClientData clientData;
|
||||
|
||||
clientData = NiceClientData(GetData(dataRef.ID));
|
||||
if(clientData == none)
|
||||
return;
|
||||
clientData.SetUpToDate(dataRef, replicationFinished);
|
||||
clientData._SetString(dataRef, value);
|
||||
// Events
|
||||
events.static.CallVariableUpdated(dataRef.ID, dataRef.variable);
|
||||
events.static.CallStringVariableUpdated(dataRef.ID, dataRef.variable,
|
||||
value);
|
||||
if(replicationFinished)
|
||||
events.static.CallDataUpToDate(dataRef.ID);
|
||||
}
|
||||
|
||||
function CheckinClass( DataRef dataRef, class<Actor> value,
|
||||
bool replicationFinished){
|
||||
local NiceClientData clientData;
|
||||
|
||||
clientData = NiceClientData(GetData(dataRef.ID));
|
||||
if(clientData == none)
|
||||
return;
|
||||
clientData.SetUpToDate(dataRef, replicationFinished);
|
||||
clientData._SetClass(dataRef, value);
|
||||
// Events
|
||||
events.static.CallVariableUpdated(dataRef.ID, dataRef.variable);
|
||||
events.static.CallClassVariableUpdated(dataRef.ID, dataRef.variable, value);
|
||||
if(replicationFinished)
|
||||
events.static.CallDataUpToDate(dataRef.ID);
|
||||
}
|
||||
|
||||
// NICETODO: to debug, remove later
|
||||
function Print(NicePlayerController pc){
|
||||
local int i, j;
|
||||
local array<string> names;
|
||||
for(i = 0;i < localStorage.length;i ++){
|
||||
pc.ClientMessage("Data:"@localStorage[i].GetID());
|
||||
names = localStorage[i].GetVariableNames();
|
||||
for(j = 0;j < names.length;j ++){
|
||||
pc.ClientMessage(">" @ names[j] @ " = " @ String(localStorage[i].GetInt(names[j])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
dataClass=class'NiceClientData'
|
||||
}
|
224
sources/Data/NiceStorageServer.uc
Normal file
224
sources/Data/NiceStorageServer.uc
Normal file
@ -0,0 +1,224 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceStorageServer
|
||||
//==============================================================================
|
||||
// Implements queue-related storage methods relevant only to server.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NiceStorageServer extends NiceStorageServerBase
|
||||
config(NicePack);
|
||||
|
||||
function bool CanGrantWriteRights( NiceServerData data,
|
||||
NicePlayerController clientRef){
|
||||
if(!super.CanGrantWriteRights(data, clientRef))
|
||||
return false;
|
||||
if(HasPendingChanges(data.GetID(), clientRef))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checks if given data has some changes not yet replicated to the player.
|
||||
// Works only on a server.
|
||||
function bool HasPendingChanges(string dataID,
|
||||
NicePlayerController nicePlayer){
|
||||
local NiceServerData dataToCheck;
|
||||
local int connectionIndex;
|
||||
local ClientConnection connection;
|
||||
|
||||
connectionIndex = FindConnection(nicePlayer);
|
||||
if(connectionIndex < 0)
|
||||
return false;
|
||||
connection = connections[connectionIndex];
|
||||
dataToCheck = NiceServerData(GetData(dataID));
|
||||
if(dataToCheck == none)
|
||||
return false;
|
||||
switch(dataToCheck.priority){
|
||||
case NSP_REALTIME:
|
||||
return false;
|
||||
case NSP_HIGH:
|
||||
return HasPendingChangesInQueue(dataID,
|
||||
connection.highPriorityQueue);
|
||||
default:
|
||||
return HasPendingChangesInQueue(dataID,
|
||||
connection.lowPriorityQueue);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function bool HasPendingChangesInQueue( string dataID,
|
||||
RequestQueue queue){
|
||||
local int i;
|
||||
for(i = queue.newIndex;i < queue.requests.length;i ++)
|
||||
if(queue.requests[i].dataID == dataID)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function bool DoesQueueContainRequest
|
||||
(
|
||||
RequestQueue queue,
|
||||
ReplicationRequest request
|
||||
){
|
||||
local int i;
|
||||
for(i = queue.newIndex;i < queue.requests.length;i ++)
|
||||
if(queue.requests[i] == request)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Replicates most pressing request for given connection.
|
||||
// Returns 'true' if we were able to replicate something.
|
||||
protected function bool ReplicateTopConnectionRequest
|
||||
(
|
||||
NicePlayerController clientRef
|
||||
){
|
||||
local int queueLength;
|
||||
local int connectionIndex;
|
||||
local ClientConnection connectionCopy;
|
||||
|
||||
connectionIndex = FindConnection(clientRef);
|
||||
if(connectionIndex < 0)
|
||||
return false;
|
||||
connectionCopy = connections[connectionIndex];
|
||||
// Try high priority queue
|
||||
queueLength = connectionCopy.highPriorityQueue.requests.length -
|
||||
connectionCopy.highPriorityQueue.newIndex;
|
||||
if(queueLength > 0){
|
||||
ReplicateTopQueueRequest(clientRef, connectionCopy.highPriorityQueue);
|
||||
connections[connectionIndex] = connectionCopy;
|
||||
return true;
|
||||
}
|
||||
// Then, if high-priority one was empty, try low priority queue
|
||||
queueLength = connectionCopy.lowPriorityQueue.requests.length -
|
||||
connectionCopy.lowPriorityQueue.newIndex;
|
||||
if(queueLength > 0){
|
||||
ReplicateTopQueueRequest(clientRef, connectionCopy.lowPriorityQueue);
|
||||
connections[connectionIndex] = connectionCopy;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Replicates top request of given queue and removes former from the latter.
|
||||
// - Requires queue to be non-empty.
|
||||
// - Doesn't check if client and queue are related.
|
||||
protected function ReplicateTopQueueRequest(NicePlayerController clientRef,
|
||||
out RequestQueue queue){
|
||||
local ReplicationRequest request;
|
||||
local NiceServerData dataToReplicate;
|
||||
local bool replicationFinished;
|
||||
request = queue.requests[queue.newIndex];
|
||||
dataToReplicate = NiceServerData(GetData(request.dataID));
|
||||
if(dataToReplicate == none)
|
||||
return;
|
||||
|
||||
// Update queue index first, so that 'HasPendingChanges'
|
||||
// can return an up-to-date result.
|
||||
queue.newIndex ++;
|
||||
replicationFinished = !HasPendingChanges( dataToReplicate.GetID(),
|
||||
clientRef);
|
||||
dataToReplicate.ReplicateVariableToClient( V(request.dataID),
|
||||
request.variable, clientRef,
|
||||
replicationFinished);
|
||||
// Preserve invariant
|
||||
if(queue.newIndex >= queue.requests.length){
|
||||
queue.newIndex = 0;
|
||||
queue.requests.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected function PushRequestToConnection
|
||||
( ReplicationRequest request,
|
||||
NicePlayerController clientRef,
|
||||
NiceData.EDataPriority priority
|
||||
){
|
||||
local int connectionIndex;
|
||||
local RequestQueue givenQueue;
|
||||
local ClientConnection connectionCopy;
|
||||
if(priority == NSP_REALTIME) return;
|
||||
|
||||
connectionIndex = FindConnection(clientRef);
|
||||
if(connectionIndex < 0)
|
||||
return;
|
||||
connectionCopy = connections[connectionIndex];
|
||||
// Use appropriate queue
|
||||
switch(priority){
|
||||
case NSP_HIGH:
|
||||
givenQueue = connectionCopy.highPriorityQueue;
|
||||
if(!DoesQueueContainRequest(givenQueue, request)){
|
||||
connectionCopy.highPriorityQueue.
|
||||
requests[givenQueue.requests.length] = request;
|
||||
}
|
||||
break;
|
||||
case NSP_LOW:
|
||||
givenQueue = connectionCopy.lowPriorityQueue;
|
||||
if(!DoesQueueContainRequest(givenQueue, request)){
|
||||
connectionCopy.lowPriorityQueue.
|
||||
requests[givenQueue.requests.length] = request;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
connections[connectionIndex] = connectionCopy;
|
||||
}
|
||||
|
||||
// Pushes requests to replicate variable change to all active connections
|
||||
// #private
|
||||
function PushRequestIntoQueues( NiceRemoteHack.DataRef dataRef,
|
||||
string variableName,
|
||||
NiceData.EDataPriority priority){
|
||||
local int i;
|
||||
local NiceServerData data;
|
||||
local ReplicationRequest request;
|
||||
data = NiceServerData(GetData(dataRef.ID));
|
||||
if(data == none)
|
||||
return;
|
||||
request.dataID = data.GetID();
|
||||
request.variable = variableName;
|
||||
for(i = 0;i < connections.length;i ++)
|
||||
if(data.IsListener(connections[i].player))
|
||||
PushRequestToConnection(request, connections[i].player, priority);
|
||||
}
|
||||
|
||||
// Pushes requests necessary to perform initial replication
|
||||
// of given 'updatedData' to given 'nicePlayer'
|
||||
// #private
|
||||
function PushDataIntoQueue( NiceRemoteHack.DataRef dataRef,
|
||||
NicePlayerController clientRef,
|
||||
NiceData.EDataPriority priority){
|
||||
local int i;
|
||||
local NiceServerData dataToPush;
|
||||
local ReplicationRequest request;
|
||||
local array<string> dataVariables;
|
||||
dataToPush = NiceServerData(GetData(dataRef.ID));
|
||||
if(dataToPush == none)
|
||||
return;
|
||||
request.dataID = dataToPush.GetID();
|
||||
dataVariables = dataToPush.GetVariableNames();
|
||||
for(i = 0;i < dataVariables.length;i ++){
|
||||
request.variable = dataVariables[i];
|
||||
PushRequestToConnection(request, clientRef, priority);
|
||||
}
|
||||
}
|
||||
|
||||
function Tick(float delta){
|
||||
local int i;
|
||||
local bool didReplicate;
|
||||
for(i = 0;i < connections.length;i ++){
|
||||
if(connections[i].replicationCountdown > 0)
|
||||
connections[i].replicationCountdown -= delta;
|
||||
if(connections[i].replicationCountdown <= 0.0){
|
||||
didReplicate = ReplicateTopConnectionRequest(connections[i].player);
|
||||
if(didReplicate)
|
||||
connections[i].replicationCountdown = replicationCooldown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
206
sources/Data/NiceStorageServerBase.uc
Normal file
206
sources/Data/NiceStorageServerBase.uc
Normal file
@ -0,0 +1,206 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceStorageServerBase
|
||||
//==============================================================================
|
||||
// Implements storage methods relevant only to server.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NiceStorageServerBase extends NiceStorageBase
|
||||
abstract
|
||||
config(NicePack);
|
||||
|
||||
struct ReplicationRequest{
|
||||
var string dataID;
|
||||
var string variable;
|
||||
};
|
||||
|
||||
struct RequestQueue{
|
||||
// Elements with indices below this one were already replicated
|
||||
var int newIndex;
|
||||
var array<ReplicationRequest> requests;
|
||||
// All changes must preserve following invariants:
|
||||
// - newIndex >= 0
|
||||
// - newIndex <= requests.length
|
||||
};
|
||||
|
||||
struct ClientConnection{
|
||||
var NicePlayerController player;
|
||||
var float replicationCountdown;
|
||||
var RequestQueue lowPriorityQueue;
|
||||
var RequestQueue highPriorityQueue;
|
||||
};
|
||||
|
||||
// List of all the players who are connected to any of our data
|
||||
var protected array<ClientConnection> connections;
|
||||
|
||||
// How much time needs to pass before we send new data;
|
||||
// Each client has it's own cooldowns;
|
||||
// Not applicable to 'NSP_REALTIME' priority
|
||||
// since everything is replicated immediately then.
|
||||
var config float replicationCooldown;
|
||||
|
||||
//==============================================================================
|
||||
// > Variables related to purging 'none' actors
|
||||
// After client disconnects - it's reference will only uselessly
|
||||
// clutter connection or listeners references, -
|
||||
// that's why we need to do periodic "clean ups".
|
||||
|
||||
// Time between purges
|
||||
var config float cleanupCooldown;
|
||||
// We clear all lost connections every purge, but only this many data sets
|
||||
var config int cleanupPassesPerRound;
|
||||
|
||||
var protected float cleanupCountDown;
|
||||
// Next index of the next data to be cleaned
|
||||
var protected int cleanupNextDataIndex;
|
||||
|
||||
function bool CreateData(string ID, NiceData.EDataPriority priority){
|
||||
local NiceServerData serverData;
|
||||
if(ID == "") return false;
|
||||
if(DoesDataExistLocally(ID)) return false;
|
||||
serverData = NiceServerData(class'NiceServerData'.static.NewData(ID));
|
||||
if(!StoreData(serverData, priority))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Puts given with data in the storage without any synchronization work.
|
||||
// Can fail if data with the same ID already exists.
|
||||
function bool StoreData(NiceData data, NiceData.EDataPriority priority){
|
||||
local string ID;
|
||||
local NiceServerData serverData;
|
||||
serverData = NiceServerData(data);
|
||||
if(serverData == none) return false;
|
||||
ID = serverData.GetID();
|
||||
if(DoesDataExistLocally(ID))
|
||||
return false;
|
||||
localStorage[localStorage.length] = serverData;
|
||||
serverData.SetOwnerStorage(V(ID), self);
|
||||
serverData.SetPriority(V(ID), priority);
|
||||
events.static.CallDataCreated(ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
function bool CanGrantWriteRights( NiceServerData data,
|
||||
NicePlayerController clientRef){
|
||||
local bool isClientAdmin;
|
||||
if(data == none) return false;
|
||||
if(data.GetWriteRightsOwner() != none) return false;
|
||||
// Admin rights check
|
||||
isClientAdmin = false;
|
||||
if(clientRef != none && clientRef.PlayerReplicationInfo != none)
|
||||
isClientAdmin = clientRef.PlayerReplicationInfo.bAdmin;
|
||||
if(data.isAdminOnly && !isClientAdmin)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// #private
|
||||
function bool OpenWriteAccess(DataRef dataRef, NicePlayerController niceClient){
|
||||
local NiceServerData data;
|
||||
if(niceClient == none || niceClient.remoteRI == none) return false;
|
||||
|
||||
data = NiceServerData(GetData(dataRef.ID));
|
||||
if(data == none)
|
||||
return false;
|
||||
if(CanGrantWriteRights(data, niceClient)){
|
||||
data.SetWriteRightsOwner(dataRef, niceClient);
|
||||
events.static.CallWriteAccessGranted(dataRef.ID, niceClient);
|
||||
niceClient.remoteRI.ClientOpenWriteRights(dataRef);
|
||||
return true;
|
||||
}
|
||||
events.static.CallWriteAccessRefused( dataRef.ID,
|
||||
data.GetWriteRightsOwner());
|
||||
niceClient.remoteRI.ClientRefuseWriteRights(dataRef);
|
||||
return false;
|
||||
}
|
||||
|
||||
// #private
|
||||
function bool CloseWriteAccess(DataRef dataRef){
|
||||
local NiceServerData data;
|
||||
local NicePlayerController oldOwner;
|
||||
|
||||
data = NiceServerData(GetData(dataRef.ID));
|
||||
if(data == none)
|
||||
return false;
|
||||
oldOwner = data.GetWriteRightsOwner();
|
||||
if(oldOwner == none)
|
||||
return false;
|
||||
data.SetWriteRightsOwner(dataRef, none);
|
||||
events.static.CallWritingAccessRevoked(dataRef.ID, oldOwner);
|
||||
if(oldOwner.remoteRI != none)
|
||||
oldOwner.remoteRI.ClientCloseWriteRights(dataRef);
|
||||
return true;
|
||||
}
|
||||
|
||||
function AddConnection(NicePlayerController clientRef){
|
||||
local int i;
|
||||
local int newIndex;
|
||||
local ClientConnection newConnection;
|
||||
if(clientRef == none) return;
|
||||
for(i = 0;i < connections.length;i ++)
|
||||
if(connections[i].player == clientRef)
|
||||
return;
|
||||
newConnection.player = clientRef;
|
||||
newConnection.lowPriorityQueue.newIndex = 0;
|
||||
newConnection.highPriorityQueue.newIndex = 0;
|
||||
newIndex = connections.length;
|
||||
connections[newIndex] = newConnection;
|
||||
}
|
||||
|
||||
// Returns index for a connection for 'clientRef',
|
||||
// returns -1 if there's no connection for it.
|
||||
protected function int FindConnection(NicePlayerController clientRef){
|
||||
local int i;
|
||||
// Connection can contain 'none' values due to players disconnecting,
|
||||
if(clientRef == none)
|
||||
return -1;
|
||||
for(i = 0;i < connections.length;i ++)
|
||||
if(connections[i].player == clientRef)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected function CleanupConnections(){
|
||||
local int i;
|
||||
local array<ClientConnection> newConnections;
|
||||
|
||||
for(i = 0;i < connections.length;i ++)
|
||||
if(connections[i].player != none)
|
||||
newConnections[newConnections.length] = connections[i];
|
||||
connections = newConnections;
|
||||
}
|
||||
|
||||
// There might be a potentially huge number of data with listeners,
|
||||
// so we'll clean only a certain amount of the at a time.
|
||||
protected function DoCleanupListenersRound(int passesAmount){
|
||||
local NiceServerData serverData;
|
||||
if(localStorage.length <= 0) return;
|
||||
if(cleanupNextDataIndex < 0 || cleanupNextDataIndex >= localStorage.length)
|
||||
cleanupNextDataIndex = 0;
|
||||
serverData = NiceServerData(localStorage[cleanupNextDataIndex]);
|
||||
if(serverData != none)
|
||||
serverData.PurgeNullListeners(V(serverData.GetID()));
|
||||
cleanupNextDataIndex ++;
|
||||
DoCleanupListenersRound(passesAmount - 1);
|
||||
}
|
||||
|
||||
function Tick(float delta){
|
||||
cleanupCountDown -= delta;
|
||||
if(cleanupCountDown <= 0){
|
||||
cleanupCountDown = cleanupCooldown;
|
||||
CleanupConnections();
|
||||
DoCleanupListenersRound(cleanupPassesPerRound);
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
dataClass=class'NiceServerData'
|
||||
cleanupCooldown=1.0
|
||||
cleanupPassesPerRound=10
|
||||
replicationCooldown=0.025
|
||||
}
|
19
sources/Data/Plain/NiceArchivator.uc
Normal file
19
sources/Data/Plain/NiceArchivator.uc
Normal 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
|
||||
{
|
||||
}
|
34
sources/Data/Plain/NiceDictionary.uc
Normal file
34
sources/Data/Plain/NiceDictionary.uc
Normal file
@ -0,0 +1,34 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceDictionary
|
||||
//==============================================================================
|
||||
// Stores pair of variable names and their shorteners for `NiceArchivator`.
|
||||
//==============================================================================
|
||||
// Class hierarchy: Object > NiceDictionary
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
|
||||
class NiceDictionary extends Object
|
||||
abstract;
|
||||
|
||||
struct Definition
|
||||
{
|
||||
var string fullName;
|
||||
var string shortName;
|
||||
};
|
||||
|
||||
var public const array<Definition> definitions;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
definitions(0)=(fullName="Location",shortName="L")
|
||||
definitions(1)=(fullName="Momentum",shortName="M")
|
||||
definitions(2)=(fullName="HeadshotLevel",shortName="H")
|
||||
definitions(3)=(fullName="Damage",shortName="D")
|
||||
definitions(4)=(fullName="LockonTime",shortName="T")
|
||||
definitions(5)=(fullName="Spread",shortName="S")
|
||||
definitions(6)=(fullName="ContiniousFire",shortName="C")
|
||||
}
|
183
sources/Data/Plain/NicePlainData.uc
Normal file
183
sources/Data/Plain/NicePlainData.uc
Normal file
@ -0,0 +1,183 @@
|
||||
//==============================================================================
|
||||
// NicePack / NicePlainData
|
||||
//==============================================================================
|
||||
// Provides functionality for local data storage of named variables for
|
||||
// following types:
|
||||
// bool, byte, int, float, string, class<Object>.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NicePlainData extends Object;
|
||||
|
||||
struct DataPair{
|
||||
var string key;
|
||||
var string value;
|
||||
};
|
||||
|
||||
struct Data{
|
||||
var array<DataPair> pairs;
|
||||
};
|
||||
|
||||
// Returns index of variable with name 'varName', returns -1 if no entry found
|
||||
static function int LookupVar(Data mySet, string varName){
|
||||
local int i;
|
||||
for(i = 0;i < mySet.pairs.length;i ++)
|
||||
if(mySet.pairs[i].key ~= varName)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static function bool GetBool( Data mySet,
|
||||
string varName,
|
||||
optional bool defaultValue){
|
||||
local int index;
|
||||
index = LookupVar(mySet, varName);
|
||||
if(index < 0)
|
||||
return defaultValue;
|
||||
else
|
||||
return bool(mySet.pairs[index].value);
|
||||
}
|
||||
|
||||
|
||||
static function SetBool(out Data mySet, string varName, bool varValue){
|
||||
local int index;
|
||||
local DataPair newPair;
|
||||
index = LookupVar(mySet, varName);
|
||||
if(index < 0){
|
||||
newPair.key = varName;
|
||||
newPair.value = string(varValue);
|
||||
mySet.pairs[mySet.pairs.length] = newPair;
|
||||
}
|
||||
else
|
||||
mySet.pairs[index].value = string(varValue);
|
||||
}
|
||||
|
||||
static function byte GetByte( Data mySet,
|
||||
string varName,
|
||||
optional byte defaultValue){
|
||||
local int index;
|
||||
index = LookupVar(mySet, varName);
|
||||
if(index < 0)
|
||||
return defaultValue;
|
||||
else
|
||||
return byte(mySet.pairs[index].value);
|
||||
}
|
||||
|
||||
static function SetByte(out Data mySet, string varName, byte varValue){
|
||||
local int index;
|
||||
local DataPair newPair;
|
||||
index = LookupVar(mySet, varName);
|
||||
if(index < 0){
|
||||
newPair.key = varName;
|
||||
newPair.value = string(varValue);
|
||||
mySet.pairs[mySet.pairs.length] = newPair;
|
||||
}
|
||||
else
|
||||
mySet.pairs[index].value = string(varValue);
|
||||
}
|
||||
|
||||
static function int GetInt( Data mySet,
|
||||
string varName,
|
||||
optional int defaultValue){
|
||||
local int index;
|
||||
index = LookupVar(mySet, varName);
|
||||
if(index < 0)
|
||||
return defaultValue;
|
||||
else
|
||||
return int(mySet.pairs[index].value);
|
||||
}
|
||||
|
||||
static function SetInt(out Data mySet, string varName, int varValue){
|
||||
local int index;
|
||||
local DataPair newPair;
|
||||
index = LookupVar(mySet, varName);
|
||||
if(index < 0){
|
||||
newPair.key = varName;
|
||||
newPair.value = string(varValue);
|
||||
mySet.pairs[mySet.pairs.length] = newPair;
|
||||
}
|
||||
else
|
||||
mySet.pairs[index].value = string(varValue);
|
||||
}
|
||||
|
||||
static function float GetFloat( Data mySet,
|
||||
string varName,
|
||||
optional float defaultValue){
|
||||
local int index;
|
||||
index = LookupVar(mySet, varName);
|
||||
if(index < 0)
|
||||
return defaultValue;
|
||||
else
|
||||
return float(mySet.pairs[index].value);
|
||||
}
|
||||
|
||||
static function SetFloat(out Data mySet, string varName, float varValue){
|
||||
local int index;
|
||||
local DataPair newPair;
|
||||
index = LookupVar(mySet, varName);
|
||||
if(index < 0){
|
||||
newPair.key = varName;
|
||||
newPair.value = string(varValue);
|
||||
mySet.pairs[mySet.pairs.length] = newPair;
|
||||
}
|
||||
else
|
||||
mySet.pairs[index].value = string(varValue);
|
||||
}
|
||||
|
||||
static function string GetString( Data mySet,
|
||||
string varName,
|
||||
optional string defaultValue){
|
||||
local int index;
|
||||
index = LookupVar(mySet, varName);
|
||||
if(index < 0)
|
||||
return defaultValue;
|
||||
else
|
||||
return mySet.pairs[index].value;
|
||||
}
|
||||
|
||||
static function SetString(out Data mySet, string varName, string varValue){
|
||||
local int index;
|
||||
local DataPair newPair;
|
||||
index = LookupVar(mySet, varName);
|
||||
if(index < 0){
|
||||
newPair.key = varName;
|
||||
newPair.value = varValue;
|
||||
mySet.pairs[mySet.pairs.length] = newPair;
|
||||
}
|
||||
else
|
||||
mySet.pairs[index].value = varValue;
|
||||
}
|
||||
|
||||
static function class<Object> GetClass( Data mySet,
|
||||
string varName,
|
||||
optional class<Object> defaultValue){
|
||||
local int index;
|
||||
local string className;
|
||||
index = LookupVar(mySet, varName);
|
||||
if(index < 0)
|
||||
return defaultValue;
|
||||
className = mySet.pairs[index].value;
|
||||
return class<Object>(DynamicLoadObject(className, class'Class'));
|
||||
}
|
||||
|
||||
static function SetClass( out Data mySet,
|
||||
string varName,
|
||||
optional class<Object> varValue){
|
||||
local int index;
|
||||
local DataPair newPair;
|
||||
index = LookupVar(mySet, varName);
|
||||
if(index < 0){
|
||||
newPair.key = varName;
|
||||
newPair.value = string(varValue);
|
||||
mySet.pairs[mySet.pairs.length] = newPair;
|
||||
}
|
||||
else
|
||||
mySet.pairs[index].value = string(varValue);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
}
|
4
sources/Effects/NiceBlockHitEmitter.uc
Normal file
4
sources/Effects/NiceBlockHitEmitter.uc
Normal file
@ -0,0 +1,4 @@
|
||||
class NiceBlockHitEmitter extends MetalHitEmitter;
|
||||
defaultproperties
|
||||
{
ImpactSounds(0)=None
ImpactSounds(1)=None
ImpactSounds(2)=None
RemoteRole=ROLE_SimulatedProxy
|
||||
}
|
5
sources/Effects/NiceFreezeParticlesBase.uc
Normal file
5
sources/Effects/NiceFreezeParticlesBase.uc
Normal file
@ -0,0 +1,5 @@
|
||||
// ScrN copy
|
||||
class NiceFreezeParticlesBase extends Emitter;
|
||||
defaultproperties
|
||||
{
bNoDelete=False
|
||||
}
|
8
sources/Effects/NiceFreezeParticlesDirectional.uc
Normal file
8
sources/Effects/NiceFreezeParticlesDirectional.uc
Normal file
@ -0,0 +1,8 @@
|
||||
// ScrN copy
|
||||
class NiceFreezeParticlesDirectional extends NiceFreezeParticlesBase;
|
||||
simulated function Trigger(Actor other, Pawn eventInstigator){
|
||||
emitters[0].SpawnParticle(1);
|
||||
}
|
||||
defaultproperties
|
||||
{
Style=STY_Additive
bHardAttach=True
bDirectional=True
|
||||
}
|
21
sources/Effects/NiceIceChunkEmitter.uc
Normal file
21
sources/Effects/NiceIceChunkEmitter.uc
Normal file
@ -0,0 +1,21 @@
|
||||
class NiceIceChunkEmitter extends Emitter;
|
||||
var() array<Sound> ImpactSounds;
|
||||
simulated function PostBeginPlay(){
|
||||
if(ImpactSounds.Length > 0)
|
||||
PlaySound(ImpactSounds[Rand(ImpactSounds.Length)]);
|
||||
}
|
||||
// NICETODO: change linksfrom HTeac_A to NicePackSM (and change that file)
|
||||
defaultproperties
|
||||
{
ImpactSounds(0)=Sound'KFWeaponSound.bullethitglass'
ImpactSounds(1)=Sound'KFWeaponSound.bullethitglass2'
Begin Object Class=MeshEmitter Name=MeshEmitter0
StaticMesh=StaticMesh'HTec_A.IceChunk1'
UseCollision=True
RespawnDeadParticles=False
SpinParticles=True
DampRotation=True
UniformSize=True
AutomaticInitialSpawning=False
Acceleration=(Z=-1000.000000)
DampingFactorRange=(X=(Min=0.200000,Max=0.200000),Y=(Min=0.200000,Max=0.200000),Z=(Min=0.200000,Max=0.200000))
ColorScale(0)=(Color=(B=255,G=255,R=255,A=255))
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255,A=255))
MaxParticles=5
SpinsPerSecondRange=(X=(Max=1.000000),Y=(Max=1.000000),Z=(Max=1.000000))
StartSpinRange=(X=(Min=-1.000000,Max=1.000000),Y=(Min=-1.000000,Max=1.000000),Z=(Min=-1.000000,Max=1.000000))
RotationDampingFactorRange=(X=(Min=0.200000,Max=0.200000),Y=(Min=0.200000,Max=0.200000),Z=(Min=0.200000,Max=0.200000))
StartSizeRange=(X=(Min=5.000000,Max=8.000000),Y=(Min=5.000000,Max=8.000000),Z=(Min=5.000000,Max=8.000000))
InitialParticlesPerSecond=10000.000000
StartVelocityRange=(X=(Min=-75.000000,Max=75.000000),Y=(Min=-75.000000,Max=75.000000),Z=(Min=-100.000000,Max=300.000000))
End Object
Emitters(0)=MeshEmitter'NicePack.NiceIceChunkEmitter.MeshEmitter0'
|
||||
Begin Object Class=MeshEmitter Name=MeshEmitter2
StaticMesh=StaticMesh'HTec_A.IceChunk2'
UseCollision=True
RespawnDeadParticles=False
SpinParticles=True
DampRotation=True
UniformSize=True
AutomaticInitialSpawning=False
Acceleration=(Z=-1000.000000)
DampingFactorRange=(X=(Min=0.200000,Max=0.200000),Y=(Min=0.200000,Max=0.200000),Z=(Min=0.200000,Max=0.200000))
ColorScale(0)=(Color=(B=255,G=255,R=255,A=255))
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255,A=255))
MaxParticles=8
DetailMode=DM_High
SpinsPerSecondRange=(X=(Max=1.000000),Y=(Max=1.000000),Z=(Max=1.000000))
StartSpinRange=(X=(Min=-1.000000,Max=1.000000),Y=(Min=-1.000000,Max=1.000000),Z=(Min=-1.000000,Max=1.000000))
RotationDampingFactorRange=(X=(Min=0.200000,Max=0.200000),Y=(Min=0.200000,Max=0.200000),Z=(Min=0.200000,Max=0.200000))
StartSizeRange=(X=(Min=3.000000,Max=6.000000),Y=(Min=3.000000,Max=6.000000),Z=(Min=3.000000,Max=6.000000))
InitialParticlesPerSecond=10000.000000
StartVelocityRange=(X=(Min=-150.000000,Max=150.000000),Y=(Min=-150.000000,Max=150.000000),Z=(Min=-100.000000,Max=500.000000))
End Object
Emitters(1)=MeshEmitter'NicePack.NiceIceChunkEmitter.MeshEmitter2'
|
||||
Begin Object Class=MeshEmitter Name=MeshEmitter3
StaticMesh=StaticMesh'HTec_A.IceChunk3'
UseCollision=True
RespawnDeadParticles=False
SpinParticles=True
DampRotation=True
UniformSize=True
AutomaticInitialSpawning=False
Acceleration=(Z=-1000.000000)
DampingFactorRange=(X=(Min=0.200000,Max=0.200000),Y=(Min=0.200000,Max=0.200000),Z=(Min=0.200000,Max=0.200000))
ColorScale(0)=(Color=(B=255,G=255,R=255,A=255))
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255,A=255))
MaxParticles=12
DetailMode=DM_High
SpinsPerSecondRange=(X=(Max=1.000000),Y=(Max=1.000000),Z=(Max=1.000000))
StartSpinRange=(X=(Min=-1.000000,Max=1.000000),Y=(Min=-1.000000,Max=1.000000),Z=(Min=-1.000000,Max=1.000000))
RotationDampingFactorRange=(X=(Min=0.200000,Max=0.200000),Y=(Min=0.200000,Max=0.200000),Z=(Min=0.200000,Max=0.200000))
StartSizeRange=(X=(Min=2.000000,Max=5.000000),Y=(Min=2.000000,Max=5.000000),Z=(Min=2.000000,Max=5.000000))
InitialParticlesPerSecond=10000.000000
StartVelocityRange=(X=(Min=-200.000000,Max=200.000000),Y=(Min=-200.000000,Max=200.000000),Z=(Min=-100.000000,Max=500.000000))
End Object
Emitters(2)=MeshEmitter'NicePack.NiceIceChunkEmitter.MeshEmitter3'
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter8
UseCollision=True
FadeOut=True
FadeIn=True
RespawnDeadParticles=False
UniformSize=True
AutomaticInitialSpawning=False
UseRandomSubdivision=True
Acceleration=(Z=-1000.000000)
ExtentMultiplier=(X=0.000000,Y=0.000000,Z=0.000000)
DampingFactorRange=(X=(Min=0.250000,Max=0.250000),Y=(Min=0.250000,Max=0.250000),Z=(Min=0.250000,Max=0.250000))
ColorScale(0)=(Color=(B=255,G=255,R=255,A=255))
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255,A=255))
FadeOutStartTime=0.500000
MaxParticles=55
DetailMode=DM_SuperHigh
UseRotationFrom=PTRS_Actor
StartSizeRange=(X=(Min=0.700000,Max=1.700000))
InitialParticlesPerSecond=10000.000000
DrawStyle=PTDS_AlphaBlend
Texture=Texture'Effects_Tex.BulletHits.snowchunksfinal'
TextureUSubdivisions=2
TextureVSubdivisions=2
LifetimeRange=(Min=1.400000,Max=1.400000)
StartVelocityRange=(X=(Min=-200.000000,Max=200.000000),Y=(Min=-200.000000,Max=200.000000),Z=(Min=-300.000000,Max=350.000000))
End Object
Emitters(3)=SpriteEmitter'NicePack.NiceIceChunkEmitter.SpriteEmitter8'
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter9
ProjectionNormal=(Y=1.000000,Z=0.000000)
FadeOut=True
FadeIn=True
RespawnDeadParticles=False
SpinParticles=True
UseSizeScale=True
UseRegularSizeScale=False
UniformSize=True
AutomaticInitialSpawning=False
Acceleration=(Z=-1000.000000)
ColorScale(0)=(Color=(B=255,G=255,R=255,A=255))
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255,A=255))
Opacity=0.500000
FadeOutStartTime=0.442500
FadeInEndTime=0.007500
MaxParticles=25
DetailMode=DM_High
UseRotationFrom=PTRS_Actor
SpinCCWorCW=(X=0.000000)
SpinsPerSecondRange=(X=(Max=0.300000))
StartSpinRange=(X=(Min=-0.300000,Max=0.300000))
SizeScale(0)=(RelativeSize=0.400000)
SizeScale(1)=(RelativeTime=0.500000,RelativeSize=0.700000)
SizeScale(2)=(RelativeTime=1.000000,RelativeSize=1.300000)
StartSizeRange=(X=(Min=20.000000,Max=40.000000),Y=(Min=20.000000,Max=40.000000),Z=(Min=20.000000,Max=40.000000))
InitialParticlesPerSecond=10000.000000
DrawStyle=PTDS_AlphaBlend
Texture=Texture'Effects_Tex.BulletHits.watersplatter2'
TextureUSubdivisions=2
TextureVSubdivisions=2
LifetimeRange=(Min=0.750000,Max=0.750000)
StartVelocityRange=(X=(Min=-150.000000,Max=150.000000),Y=(Min=-150.000000,Max=150.000000),Z=(Min=-25.000000,Max=300.000000))
End Object
Emitters(4)=SpriteEmitter'NicePack.NiceIceChunkEmitter.SpriteEmitter9'
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter10
ProjectionNormal=(Y=1.000000,Z=0.000000)
FadeOut=True
RespawnDeadParticles=False
SpinParticles=True
UseSizeScale=True
UseRegularSizeScale=False
UniformSize=True
Acceleration=(Z=-15.000000)
ColorScale(0)=(Color=(B=255,G=255,R=255,A=255))
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255,A=255))
Opacity=0.250000
FadeOutStartTime=0.175000
MaxParticles=5
StartLocationRange=(X=(Min=10.000000,Max=10.000000))
AddLocationFromOtherEmitter=0
UseRotationFrom=PTRS_Actor
SpinCCWorCW=(X=0.000000)
SpinsPerSecondRange=(X=(Max=0.200000))
StartSpinRange=(X=(Min=-0.300000,Max=0.300000))
SizeScale(0)=(RelativeSize=0.400000)
SizeScale(1)=(RelativeTime=0.560000,RelativeSize=1.000000)
StartSizeRange=(X=(Min=6.000000,Max=60.000000),Y=(Min=6.000000,Max=60.000000),Z=(Min=6.000000,Max=60.000000))
InitialParticlesPerSecond=1.000000
DrawStyle=PTDS_AlphaBlend
Texture=Texture'kf_fx_trip_t.Misc.smoke_animated'
TextureUSubdivisions=8
TextureVSubdivisions=8
LifetimeRange=(Min=0.350000,Max=0.350000)
End Object
Emitters(5)=SpriteEmitter'NicePack.NiceIceChunkEmitter.SpriteEmitter10'
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter11
ProjectionNormal=(Y=1.000000,Z=0.000000)
FadeOut=True
RespawnDeadParticles=False
SpinParticles=True
UseSizeScale=True
UseRegularSizeScale=False
UniformSize=True
Acceleration=(Z=-15.000000)
ColorScale(0)=(Color=(B=255,G=255,R=255,A=255))
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255,A=255))
Opacity=0.250000
FadeOutStartTime=0.175000
MaxParticles=8
StartLocationRange=(X=(Min=10.000000,Max=10.000000))
AddLocationFromOtherEmitter=1
UseRotationFrom=PTRS_Actor
SpinCCWorCW=(X=0.000000)
SpinsPerSecondRange=(X=(Max=0.200000))
StartSpinRange=(X=(Min=-0.300000,Max=0.300000))
SizeScale(0)=(RelativeSize=0.400000)
SizeScale(1)=(RelativeTime=0.560000,RelativeSize=1.000000)
StartSizeRange=(X=(Min=6.000000,Max=60.000000),Y=(Min=6.000000,Max=60.000000),Z=(Min=6.000000,Max=60.000000))
InitialParticlesPerSecond=1.000000
DrawStyle=PTDS_AlphaBlend
Texture=Texture'kf_fx_trip_t.Misc.smoke_animated'
TextureUSubdivisions=8
TextureVSubdivisions=8
LifetimeRange=(Min=0.350000,Max=0.350000)
End Object
Emitters(6)=SpriteEmitter'NicePack.NiceIceChunkEmitter.SpriteEmitter11'
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter12
ProjectionNormal=(Y=1.000000,Z=0.000000)
FadeOut=True
RespawnDeadParticles=False
SpinParticles=True
UseSizeScale=True
UseRegularSizeScale=False
UniformSize=True
Acceleration=(Z=-15.000000)
ColorScale(0)=(Color=(B=255,G=255,R=255,A=255))
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255,A=255))
Opacity=0.250000
FadeOutStartTime=0.175000
MaxParticles=12
DetailMode=DM_High
StartLocationRange=(X=(Min=10.000000,Max=10.000000))
AddLocationFromOtherEmitter=2
UseRotationFrom=PTRS_Actor
SpinCCWorCW=(X=0.000000)
SpinsPerSecondRange=(X=(Max=0.200000))
StartSpinRange=(X=(Min=-0.300000,Max=0.300000))
SizeScale(0)=(RelativeSize=0.400000)
SizeScale(1)=(RelativeTime=0.560000,RelativeSize=1.000000)
StartSizeRange=(X=(Min=6.000000,Max=60.000000),Y=(Min=6.000000,Max=60.000000),Z=(Min=6.000000,Max=60.000000))
InitialParticlesPerSecond=1.000000
DrawStyle=PTDS_AlphaBlend
Texture=Texture'kf_fx_trip_t.Misc.smoke_animated'
TextureUSubdivisions=8
TextureVSubdivisions=8
LifetimeRange=(Min=0.350000,Max=0.350000)
End Object
Emitters(7)=SpriteEmitter'NicePack.NiceIceChunkEmitter.SpriteEmitter12'
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter13
ProjectionNormal=(Y=1.000000,Z=0.000000)
FadeOut=True
FadeIn=True
RespawnDeadParticles=False
SpinParticles=True
UseSizeScale=True
UseRegularSizeScale=False
UniformSize=True
AutomaticInitialSpawning=False
Acceleration=(Z=-1000.000000)
ColorScale(0)=(Color=(B=255,G=255,R=255,A=255))
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255,A=255))
Opacity=0.250000
FadeOutStartTime=0.442500
FadeInEndTime=0.007500
MaxParticles=12
StartLocationRange=(X=(Min=20.000000,Max=20.000000))
UseRotationFrom=PTRS_Actor
SpinCCWorCW=(X=0.000000)
SpinsPerSecondRange=(X=(Max=0.300000))
StartSpinRange=(X=(Min=-0.300000,Max=0.300000))
SizeScale(0)=(RelativeSize=0.400000)
SizeScale(1)=(RelativeTime=0.500000,RelativeSize=0.900000)
SizeScale(2)=(RelativeTime=1.000000,RelativeSize=1.300000)
StartSizeRange=(X=(Min=25.000000,Max=45.000000),Y=(Min=25.000000,Max=45.000000),Z=(Min=25.000000,Max=45.000000))
InitialParticlesPerSecond=10000.000000
DrawStyle=PTDS_AlphaBlend
Texture=Texture'Effects_Tex.BulletHits.watersplashcloud'
TextureUSubdivisions=1
TextureVSubdivisions=1
LifetimeRange=(Min=0.750000,Max=0.750000)
StartVelocityRange=(X=(Min=-150.000000,Max=150.000000),Y=(Min=-150.000000,Max=150.000000),Z=(Min=-5.000000,Max=150.000000))
End Object
Emitters(8)=SpriteEmitter'NicePack.NiceIceChunkEmitter.SpriteEmitter13'
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter14
ProjectionNormal=(Y=1.000000,Z=0.000000)
FadeOut=True
RespawnDeadParticles=False
SpinParticles=True
UseSizeScale=True
UseRegularSizeScale=False
UniformSize=True
AutomaticInitialSpawning=False
Acceleration=(Z=-22.000000)
DampingFactorRange=(X=(Min=0.250000,Max=0.250000),Y=(Min=0.250000,Max=0.250000),Z=(Min=0.250000,Max=0.250000))
ColorScale(0)=(Color=(B=255,G=255,R=255,A=255))
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255,A=255))
Opacity=0.500000
FadeOutStartTime=2.720000
MaxParticles=25
DetailMode=DM_High
StartLocationRange=(X=(Min=-10.000000,Max=10.000000),Y=(Min=-10.000000,Max=10.000000),Z=(Min=-10.000000,Max=10.000000))
UseRotationFrom=PTRS_Actor
SpinCCWorCW=(X=0.000000)
SpinsPerSecondRange=(X=(Max=0.150000))
StartSpinRange=(X=(Min=-1.000000,Max=1.000000))
SizeScale(0)=(RelativeSize=2.200000)
SizeScale(1)=(RelativeTime=0.500000,RelativeSize=3.200000)
SizeScale(2)=(RelativeTime=1.000000,RelativeSize=4.000000)
StartSizeRange=(X=(Min=1.000000,Max=20.000000),Y=(Min=1.000000,Max=20.000000),Z=(Min=1.000000,Max=20.000000))
InitialParticlesPerSecond=10000.000000
DrawStyle=PTDS_AlphaBlend
Texture=Texture'Effects_Tex.explosions.DSmoke_2'
TextureUSubdivisions=1
TextureVSubdivisions=1
StartVelocityRange=(X=(Min=-350.000000,Max=350.000000),Y=(Min=-350.000000,Max=350.000000),Z=(Min=-5.000000,Max=50.000000))
VelocityLossRange=(X=(Min=3.000000,Max=3.000000),Y=(Min=3.000000,Max=3.000000))
End Object
Emitters(9)=SpriteEmitter'NicePack.NiceIceChunkEmitter.SpriteEmitter14'
|
||||
Begin Object Class=SpriteEmitter Name=SpriteEmitter15
UseCollision=True
UseColorScale=True
FadeOut=True
FadeIn=True
RespawnDeadParticles=False
UniformSize=True
AutomaticInitialSpawning=False
UseRandomSubdivision=True
Acceleration=(Z=-1000.000000)
ExtentMultiplier=(X=0.000000,Y=0.000000,Z=0.000000)
DampingFactorRange=(X=(Min=0.250000,Max=0.250000),Y=(Min=0.250000,Max=0.250000),Z=(Min=0.250000,Max=0.250000))
ColorScale(0)=(Color=(B=174,G=174,R=205,A=255))
ColorScale(1)=(RelativeTime=1.000000,Color=(B=174,G=174,R=205,A=255))
FadeOutStartTime=0.500000
MaxParticles=15
UseRotationFrom=PTRS_Actor
StartSizeRange=(X=(Min=0.700000,Max=1.700000))
InitialParticlesPerSecond=10000.000000
DrawStyle=PTDS_AlphaBlend
Texture=Texture'Effects_Tex.BulletHits.snowchunksfinal'
TextureUSubdivisions=2
TextureVSubdivisions=2
LifetimeRange=(Min=1.400000,Max=1.400000)
StartVelocityRange=(X=(Min=-200.000000,Max=200.000000),Y=(Min=-200.000000,Max=200.000000),Z=(Min=-300.000000,Max=350.000000))
End Object
Emitters(10)=SpriteEmitter'NicePack.NiceIceChunkEmitter.SpriteEmitter15'
|
||||
AutoDestroy=True
bNoDelete=False
bNetTemporary=True
RemoteRole=ROLE_SimulatedProxy
LifeSpan=5.000000
TransientSoundVolume=150.000000
TransientSoundRadius=80.000000
|
||||
}
|
10
sources/Effects/NiceNitroDecal.uc
Normal file
10
sources/Effects/NiceNitroDecal.uc
Normal file
@ -0,0 +1,10 @@
|
||||
// ScrN copy
|
||||
class NiceNitroDecal extends ProjectedDecal;
|
||||
#exec OBJ LOAD FILE=HTec_A.ukx
|
||||
simulated function BeginPlay(){
|
||||
if(!level.bDropDetail && FRand() < 0.4)
projTexture = Texture'HTec_A.Nitro.NitroSplat';
|
||||
super.BeginPlay();
|
||||
}
|
||||
defaultproperties
|
||||
{
bClipStaticMesh=True
CullDistance=7000.000000
LifeSpan=5.000000
DrawScale=0.500000
|
||||
}
|
6
sources/Effects/NiceNitroGroundEffect.uc
Normal file
6
sources/Effects/NiceNitroGroundEffect.uc
Normal file
@ -0,0 +1,6 @@
|
||||
// ScrN copy
|
||||
class NiceNitroGroundEffect extends NiceFreezeParticlesDirectional;
|
||||
defaultproperties
|
||||
{
Begin Object Class=SpriteEmitter Name=SpriteEmitter0
FadeOut=True
FadeIn=True
RespawnDeadParticles=False
SpinParticles=True
UseSizeScale=True
UseRegularSizeScale=False
UniformSize=True
AutomaticInitialSpawning=False
ExtentMultiplier=(X=0.000000,Y=0.000000)
ColorScale(0)=(Color=(B=255,G=255,R=255,A=255))
ColorScale(1)=(RelativeTime=1.000000,Color=(B=255,G=255,R=255,A=255))
Opacity=0.470000
FadeOutStartTime=0.940000
FadeInEndTime=0.300000
MaxParticles=50
StartLocationShape=PTLS_Polar
SpinsPerSecondRange=(X=(Max=0.035000))
StartSpinRange=(X=(Min=-0.200000,Max=0.300000))
SizeScale(0)=(RelativeTime=0.500000,RelativeSize=0.900000)
SizeScale(1)=(RelativeTime=1.000000,RelativeSize=0.500000)
StartSizeRange=(X=(Min=15.000000,Max=35.000000),Y=(Min=15.000000,Max=35.000000),Z=(Min=15.000000,Max=35.000000))
InitialParticlesPerSecond=60.000000
DrawStyle=PTDS_AlphaBlend
Texture=Texture'Effects_Tex.explosions.DSmoke_2'
LifetimeRange=(Min=2.000000,Max=2.000000)
StartVelocityRange=(X=(Min=-85.000000,Max=85.000000),Y=(Min=-85.000000,Max=85.000000))
StartVelocityRadialRange=(Min=-40.000000,Max=40.000000)
End Object
Emitters(0)=SpriteEmitter'NicePack.NiceNitroGroundEffect.SpriteEmitter0'
|
||||
LifeSpan=5.000000
|
||||
}
|
190
sources/GUI/NiceGUIBuyMenu.uc
Normal file
190
sources/GUI/NiceGUIBuyMenu.uc
Normal file
@ -0,0 +1,190 @@
|
||||
class NiceGUIBuyMenu extends UT2k4MainPage;
|
||||
//The "Header"
|
||||
var automated GUIImage HeaderBG_Left;
|
||||
var automated GUIImage HeaderBG_Center;
|
||||
var automated GUIImage HeaderBG_Right;
|
||||
var automated GUILabel CurrentPerkLabel;
|
||||
var automated GUILabel TimeLeftLabel;
|
||||
var automated GUILabel WaveLabel;
|
||||
var automated GUILabel HeaderBG_Left_Label;
|
||||
var automated KFQuickPerkSelect QuickPerkSelect;
|
||||
var automated KFBuyMenuFilter BuyMenuFilter;
|
||||
var automated GUIButton StoreTabButton;
|
||||
var automated GUIButton PerkTabButton;
|
||||
//The "Footer"
|
||||
var automated GUIImage WeightBG;
|
||||
var automated GUIImage WeightIcon;
|
||||
var automated GUIImage WeightIconBG;
|
||||
var automated KFWeightBar WeightBar;
|
||||
//const BUYLIST_CATS =7;
|
||||
var() editconst noexport float SavedPitch;
|
||||
var color RedColor;
|
||||
var color GreenGreyColor;
|
||||
var() UT2K4TabPanel ActivePanel;
|
||||
var localized string CurrentPerk;
|
||||
var localized string NoActivePerk;
|
||||
var localized string TraderClose;
|
||||
var localized string WaveString;
|
||||
var localized string LvAbbrString;
|
||||
function InitComponent(GUIController MyC, GUIComponent MyO)
|
||||
{
|
||||
local int i;
|
||||
super.InitComponent(MyC, MyO);
|
||||
c_Tabs.BackgroundImage = none;
|
||||
c_Tabs.BackgroundStyle = none;
|
||||
InitTabs();
|
||||
for ( i = 0; i < c_Tabs.TabStack.Length; i++ )
|
||||
{
|
||||
c_Tabs.TabStack[i].bVisible = false;
|
||||
}
|
||||
UpdateWeightBar();
|
||||
}
|
||||
function InitTabs()
|
||||
{
|
||||
local int i;
|
||||
for ( i = 0; i < PanelCaption.Length && i < PanelClass.Length && i < PanelHint.Length; i++ )
|
||||
{
|
||||
c_Tabs.AddTab(PanelCaption[i], PanelClass[i],, PanelHint[i]);
|
||||
}
|
||||
}
|
||||
function UpdateWeightBar()
|
||||
{
|
||||
if ( KFHumanPawn(PlayerOwner().Pawn) != none )
|
||||
{
|
||||
WeightBar.MaxBoxes = KFHumanPawn(PlayerOwner().Pawn).MaxCarryWeight;
|
||||
WeightBar.CurBoxes = KFHumanPawn(PlayerOwner().Pawn).CurrentWeight;
|
||||
}
|
||||
}
|
||||
event Opened(GUIComponent Sender)
|
||||
{
|
||||
local rotator PlayerRot;
|
||||
super.Opened(Sender);
|
||||
c_Tabs.ActivateTabByName(PanelCaption[0], true);
|
||||
// Tell the controller that he is on a shopping spree
|
||||
if ( KFPlayerController(PlayerOwner()) != none )
|
||||
{
KFPlayerController(PlayerOwner()).bShopping = true;
|
||||
}
|
||||
if ( KFWeapon(KFHumanPawn(PlayerOwner().Pawn).Weapon).bAimingRifle )
|
||||
{
|
||||
KFWeapon(KFHumanPawn(PlayerOwner().Pawn).Weapon).IronSightZoomOut();
|
||||
}
|
||||
// Set camera's pitch to zero when menu initialised (otherwise spinny weap goes kooky)
|
||||
PlayerRot = PlayerOwner().Rotation;
|
||||
SavedPitch = PlayerRot.Pitch;
|
||||
PlayerRot.Yaw = PlayerRot.Yaw % 65536;
|
||||
PlayerRot.Pitch = 0;
|
||||
PlayerRot.Roll = 0;
|
||||
PlayerOwner().SetRotation(PlayerRot);
|
||||
SetTimer(0.05f, true);
|
||||
}
|
||||
function Timer()
|
||||
{
|
||||
UpdateHeader();
|
||||
UpdateWeightBar();
|
||||
}
|
||||
function InternalOnClose(optional bool bCanceled)
|
||||
{
|
||||
local rotator NewRot;
|
||||
// Reset player
|
||||
NewRot = PlayerOwner().Rotation;
|
||||
NewRot.Pitch = SavedPitch;
|
||||
PlayerOwner().SetRotation(NewRot);
|
||||
Super.OnClose(bCanceled);
|
||||
}
|
||||
function UpdateHeader()
|
||||
{
|
||||
local int TimeLeftMin, TimeLeftSec;
|
||||
local string TimeString;
|
||||
if ( KFPlayerController(PlayerOwner()) == none || PlayerOwner().PlayerReplicationInfo == none ||
|
||||
PlayerOwner().GameReplicationInfo == none )
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Current Perk
|
||||
if ( KFPlayerController(PlayerOwner()).SelectedVeterancy != none )
|
||||
{
|
||||
CurrentPerkLabel.Caption = CurrentPerk$":" @ KFPlayerController(PlayerOwner()).SelectedVeterancy.default.VeterancyName @ LvAbbrString$KFPlayerReplicationInfo(PlayerOwner().PlayerReplicationInfo).ClientVeteranSkillLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentPerkLabel.Caption = CurrentPerk$":" @ NoActivePerk;
|
||||
}
|
||||
// Trader time left
|
||||
TimeLeftMin = KFGameReplicationInfo(PlayerOwner().GameReplicationInfo).TimeToNextWave / 60;
|
||||
TimeLeftSec = KFGameReplicationInfo(PlayerOwner().GameReplicationInfo).TimeToNextWave % 60;
|
||||
if ( TimeLeftMin < 1 )
|
||||
{
|
||||
TimeString = "00:";
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeString = "0" $ TimeLeftMin $ ":";
|
||||
}
|
||||
if ( TimeLeftSec >= 10 )
|
||||
{
|
||||
TimeString = TimeString $ TimeLeftSec;
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeString = TimeString $ "0" $ TimeLeftSec;
|
||||
}
|
||||
TimeLeftLabel.Caption = TraderClose @ TimeString;
|
||||
if ( KFGameReplicationInfo(PlayerOwner().GameReplicationInfo).TimeToNextWave < 10 )
|
||||
{
|
||||
TimeLeftLabel.TextColor = RedColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeLeftLabel.TextColor = GreenGreyColor;
|
||||
}
|
||||
// Wave Counter
|
||||
WaveLabel.Caption = WaveString$":" @ (KFGameReplicationInfo(PlayerOwner().GameReplicationInfo).WaveNumber + 1)$"/"$KFGameReplicationInfo(PlayerOwner().GameReplicationInfo).FinalWave;
|
||||
}
|
||||
function KFBuyMenuClosed(optional bool bCanceled)
|
||||
{
|
||||
local rotator NewRot;
|
||||
// Reset player
|
||||
NewRot = PlayerOwner().Rotation;
|
||||
NewRot.Pitch = SavedPitch;
|
||||
PlayerOwner().SetRotation(NewRot);
|
||||
Super.OnClose(bCanceled);
|
||||
if ( KFPlayerController(PlayerOwner()) != none )
|
||||
{
KFPlayerController(PlayerOwner()).bShopping = false;
|
||||
}
|
||||
}
|
||||
function CloseSale(bool savePurchases)
|
||||
{
|
||||
Controller.CloseMenu(!savePurchases);
|
||||
}
|
||||
function bool ButtonClicked(GUIComponent Sender)
|
||||
{
|
||||
if ( Sender == PerkTabButton )
|
||||
{
|
||||
HandleParameters(PanelCaption[1], "OhHi!");
|
||||
}
|
||||
if ( Sender == StoreTabButton )
|
||||
{
|
||||
HandleParameters(PanelCaption[0], "OhHi!");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
defaultproperties
|
||||
{
Begin Object Class=GUIImage Name=HBGLeft
Image=Texture'KF_InterfaceArt_tex.Menu.Thin_border'
ImageStyle=ISTY_Stretched
Hint="Perk Quick Select"
WinTop=0.001000
WinLeft=0.001000
WinWidth=0.332300
WinHeight=0.100000
End Object
HeaderBG_Left=GUIImage'NicePack.NiceGUIBuyMenu.HBGLeft'
|
||||
Begin Object Class=GUIImage Name=HBGCenter
Image=Texture'KF_InterfaceArt_tex.Menu.Thin_border'
ImageStyle=ISTY_Stretched
Hint="Trading Time Left"
WinTop=0.001000
WinLeft=0.334000
WinWidth=0.331023
WinHeight=0.100000
End Object
HeaderBG_Center=GUIImage'NicePack.NiceGUIBuyMenu.HBGCenter'
|
||||
Begin Object Class=GUIImage Name=HBGRight
Image=Texture'KF_InterfaceArt_tex.Menu.Thin_border'
ImageStyle=ISTY_Stretched
Hint="Current Perk"
WinTop=0.001000
WinLeft=0.666000
WinWidth=0.332000
WinHeight=0.100000
End Object
HeaderBG_Right=GUIImage'NicePack.NiceGUIBuyMenu.HBGRight'
|
||||
Begin Object Class=GUILabel Name=Perk
TextAlign=TXTA_Center
TextColor=(B=158,G=176,R=175)
WinTop=0.010000
WinLeft=0.665000
WinWidth=0.329761
WinHeight=0.050000
End Object
CurrentPerkLabel=GUILabel'NicePack.NiceGUIBuyMenu.Perk'
|
||||
Begin Object Class=GUILabel Name=Time
Caption="Trader closes in 00:31"
TextAlign=TXTA_Center
TextColor=(B=158,G=176,R=175)
TextFont="UT2LargeFont"
WinTop=0.020952
WinLeft=0.335000
WinWidth=0.330000
WinHeight=0.035000
End Object
TimeLeftLabel=GUILabel'NicePack.NiceGUIBuyMenu.Time'
|
||||
Begin Object Class=GUILabel Name=Wave
Caption="Wave: 7/10"
TextAlign=TXTA_Center
TextColor=(B=158,G=176,R=175)
WinTop=0.052857
WinLeft=0.336529
WinWidth=0.327071
WinHeight=0.035000
End Object
WaveLabel=GUILabel'NicePack.NiceGUIBuyMenu.Wave'
|
||||
Begin Object Class=GUILabel Name=HBGLL
Caption="Quick Perk Select"
TextAlign=TXTA_Center
TextColor=(B=158,G=176,R=175)
TextFont="UT2ServerListFont"
WinTop=0.007238
WinLeft=0.024937
WinWidth=0.329761
WinHeight=0.019524
End Object
HeaderBG_Left_Label=GUILabel'NicePack.NiceGUIBuyMenu.HBGLL'
|
||||
Begin Object Class=KFQuickPerkSelect Name=QS
WinTop=0.011906
WinLeft=0.008008
WinWidth=0.316601
WinHeight=0.082460
OnDraw=QS.MyOnDraw
End Object
QuickPerkSelect=KFQuickPerkSelect'NicePack.NiceGUIBuyMenu.QS'
|
||||
Begin Object Class=KFBuyMenuFilter Name=filter
WinTop=0.051000
WinLeft=0.670000
WinWidth=0.305000
WinHeight=0.082460
OnDraw=filter.MyOnDraw
End Object
BuyMenuFilter=KFBuyMenuFilter'NicePack.NiceGUIBuyMenu.filter'
|
||||
Begin Object Class=GUIButton Name=StoreTabB
Caption="Store"
FontScale=FNS_Small
WinTop=0.072762
WinLeft=0.202801
WinWidth=0.050000
WinHeight=0.022000
OnClick=NiceGUIBuyMenu.ButtonClicked
OnKeyEvent=StoreTabB.InternalOnKeyEvent
End Object
StoreTabButton=GUIButton'NicePack.NiceGUIBuyMenu.StoreTabB'
|
||||
Begin Object Class=GUIButton Name=PerkTabB
Caption="Perk"
FontScale=FNS_Small
WinTop=0.072762
WinLeft=0.127234
WinWidth=0.050000
WinHeight=0.022000
OnClick=NiceGUIBuyMenu.ButtonClicked
OnKeyEvent=PerkTabB.InternalOnKeyEvent
End Object
PerkTabButton=GUIButton'NicePack.NiceGUIBuyMenu.PerkTabB'
|
||||
Begin Object Class=GUIImage Name=Weight
Image=Texture'KF_InterfaceArt_tex.Menu.Thin_border'
ImageStyle=ISTY_Stretched
WinTop=0.934206
WinLeft=0.001000
WinWidth=0.663086
WinHeight=0.065828
End Object
WeightBG=GUIImage'NicePack.NiceGUIBuyMenu.Weight'
|
||||
Begin Object Class=GUIImage Name=WeightIco
Image=Texture'KillingFloorHUD.HUD.Hud_Weight'
ImageStyle=ISTY_Scaled
WinTop=0.946166
WinLeft=0.009961
WinWidth=0.033672
WinHeight=0.048992
RenderWeight=0.460000
End Object
WeightIcon=GUIImage'NicePack.NiceGUIBuyMenu.WeightIco'
|
||||
Begin Object Class=GUIImage Name=WeightIcoBG
Image=Texture'KF_InterfaceArt_tex.Menu.Perk_box_unselected'
ImageStyle=ISTY_Scaled
WinTop=0.942416
WinLeft=0.006055
WinWidth=0.041484
WinHeight=0.054461
RenderWeight=0.450000
End Object
WeightIconBG=GUIImage'NicePack.NiceGUIBuyMenu.WeightIcoBG'
|
||||
Begin Object Class=KFWeightBar Name=WeightB
WinTop=0.945302
WinLeft=0.055266
WinWidth=0.443888
WinHeight=0.053896
OnDraw=WeightB.MyOnDraw
End Object
WeightBar=KFWeightBar'NicePack.NiceGUIBuyMenu.WeightB'
|
||||
RedColor=(R=255,A=255)
GreenGreyColor=(B=158,G=176,R=175,A=255)
CurrentPerk="Current Perk"
NoActivePerk="No Active Perk!"
TraderClose="Trader Closes in"
WaveString="Wave"
LvAbbrString="Lv"
Begin Object Class=GUITabControl Name=PageTabs
bDockPanels=True
TabHeight=0.025000
BackgroundStyleName="TabBackground"
WinTop=0.078000
WinLeft=0.005000
WinWidth=0.990000
WinHeight=0.025000
RenderWeight=0.490000
TabOrder=0
bAcceptsInput=True
OnActivate=PageTabs.InternalOnActivate
OnChange=NiceGUIBuyMenu.InternalOnChange
End Object
c_Tabs=GUITabControl'NicePack.NiceGUIBuyMenu.PageTabs'
|
||||
Begin Object Class=BackgroundImage Name=PageBackground
Image=Texture'Engine.WhiteSquareTexture'
ImageColor=(B=20,G=20,R=20)
ImageStyle=ISTY_Tiled
RenderWeight=0.001000
End Object
i_Background=BackgroundImage'NicePack.NiceGUIBuyMenu.PageBackground'
|
||||
PanelClass(0)="KFGUI.KFTab_BuyMenu"
PanelClass(1)="KFGUI.KFTab_Perks"
PanelCaption(0)="Store"
PanelCaption(1)="Perks"
PanelHint(0)="Trade equipment and ammunition"
PanelHint(1)="Select your current Perk"
bAllowedAsLast=True
OnClose=NiceGUIBuyMenu.KFBuyMenuClosed
WhiteColor=(B=255,G=255,R=255)
|
||||
}
|
76
sources/GUI/NiceGUIPerkButton.uc
Normal file
76
sources/GUI/NiceGUIPerkButton.uc
Normal file
@ -0,0 +1,76 @@
|
||||
class NiceGUIPerkButton extends GUIButton;
|
||||
var bool isAltSkill;
|
||||
var int skillPerkIndex, skillIndex;
|
||||
var class<NiceSkill> associatedSkill;
|
||||
function InitComponent(GUIController MyController, GUIComponent MyOwner)
|
||||
{
|
||||
OnDraw = DrawSkillButton;
|
||||
OnClick = SkillChange;
|
||||
Super.InitComponent(MyController, MyOwner);
|
||||
}
|
||||
function bool SkillChange(GUIComponent Sender){
|
||||
local byte newSkillChoice;
|
||||
local NicePlayerController skillOwner;
|
||||
if(isAltSkill)
newSkillChoice = 1;
|
||||
else
newSkillChoice = 0;
|
||||
skillOwner = NicePlayerController(PlayerOwner());
|
||||
if(skillOwner != none){
skillOwner.ServerSetSkill(skillPerkIndex, skillIndex, newSkillChoice);
skillOwner.SaveConfig();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function bool DrawSkillButton(Canvas cnvs){
|
||||
// Variables that contain information about this button's skill
|
||||
local NicePlayerController skillOwner;
|
||||
local bool bAvailable, bSelected, bPending;
|
||||
// Variables needed for text drawing
|
||||
local int descLineOffset; // How much vertical space description took so far
|
||||
local string skillEffects, line; // 'line' is next line from description to be drawn, 'skillEffects' is a not-yet drawn part of skill's effect description
|
||||
local float textWidth, textHeight, nameHeight; // Variables for storing amount of space text uses
|
||||
local int horizontalOffset, verticalOffset, smVerticalOffset; // Spaces between text and borders ('smVerticalOffset' is space between skill's name and description)
|
||||
// Old values for font and it's scale
|
||||
local Font oldFont;
|
||||
local float oldFontScaleX, oldFontScaleY;
|
||||
// Get skill parameters
|
||||
skillOwner = NicePlayerController(PlayerOwner());
|
||||
bAvailable = class'NiceVeterancyTypes'.static.CanUseSkill(skillOwner, associatedSkill);
|
||||
if(bAvailable)
bSelected = class'NiceVeterancyTypes'.static.HasSkill(skillOwner, associatedSkill);
|
||||
bPending = class'NiceVeterancyTypes'.static.IsSkillPending(skillOwner, associatedSkill);
|
||||
if(skillOwner == none || associatedSkill == none)
return true;
|
||||
// Text offset parameters that seem to give a good result
|
||||
horizontalOffset = 10;
|
||||
verticalOffset = 5;
|
||||
smVerticalOffset = 2;
|
||||
// Backup old font values and set the new ones
|
||||
oldFont = cnvs.Font;
|
||||
oldFontScaleX = cnvs.FontScaleX;
|
||||
oldFontScaleY = cnvs.FontScaleY;
|
||||
cnvs.Font = class'ROHUD'.Static.LoadSmallFontStatic(3);
|
||||
cnvs.FontScaleX = 1.0;
|
||||
cnvs.FontScaleY = 1.0;
|
||||
// Draw text
|
||||
// - Name
|
||||
cnvs.SetPos(ActualLeft() + horizontalOffset, ActualTop() + verticalOffset);
|
||||
if(!bAvailable)
cnvs.SetDrawColor(0, 0, 0);
|
||||
else if(bSelected)
cnvs.SetDrawColor(255, 255, 255);
|
||||
else
cnvs.SetDrawColor(128, 128, 128);
|
||||
cnvs.DrawText(associatedSkill.default.skillName);
|
||||
cnvs.TextSize(associatedSkill.default.skillName, textWidth, nameHeight);
|
||||
// - Description
|
||||
cnvs.Font = class'ROHUD'.Static.LoadSmallFontStatic(5);
|
||||
if(!bAvailable)
cnvs.SetDrawColor(0, 0, 0);
|
||||
else if(bSelected)
cnvs.SetDrawColor(220, 220, 220);//180
|
||||
else
cnvs.SetDrawColor(140, 140, 140);//100
|
||||
skillEffects = associatedSkill.default.skillEffects;
|
||||
while(Len(skillEffects) > 0){
cnvs.WrapText(skillEffects, line, ActualWidth() - horizontalOffset * 2, cnvs.Font, cnvs.FontScaleX);
cnvs.SetPos(ActualLeft() + horizontalOffset, ActualTop() + verticalOffset + nameHeight + smVerticalOffset + descLineOffset);
cnvs.DrawText(line);
cnvs.TextSize(line, textWidth, textHeight);
descLineOffset += textHeight;
|
||||
}
|
||||
// Draw border
|
||||
if(bAvailable && bSelected || bPending){
if(bAvailable && bSelected)
cnvs.SetDrawColor(255, 255, 255);
else
cnvs.SetDrawColor(64, 64, 64);
cnvs.SetPos(ActualLeft(), ActualTop());
cnvs.DrawLine(3, ActualWidth());
cnvs.DrawLine(1, ActualHeight());
cnvs.SetPos(ActualLeft() + ActualWidth() + 2, ActualTop() + ActualHeight());
cnvs.DrawLine(2, ActualWidth() + 2);
cnvs.SetPos(ActualLeft() + ActualWidth(), ActualTop() + ActualHeight() + 2);
cnvs.DrawLine(0, ActualHeight() + 2);
|
||||
}
|
||||
cnvs.Font = oldFont;
|
||||
cnvs.FontScaleX = oldFontScaleX;
|
||||
cnvs.FontScaleY = oldFontScaleY;
|
||||
return true;
|
||||
}
|
||||
defaultproperties
|
||||
{
|
||||
}
|
70
sources/GUI/NiceGUISettings.uc
Normal file
70
sources/GUI/NiceGUISettings.uc
Normal file
@ -0,0 +1,70 @@
|
||||
class NiceGUISettings extends Settings_Tabs;
|
||||
//var automated GUIButton skillButtonA;
|
||||
var array<string> ForceProjItems;
|
||||
var automated moCheckBox ch_WeapManagement;
|
||||
var automated moCheckBox ch_AltSwitches;
|
||||
var automated moCheckBox ch_DispCounters;
|
||||
var automated moCheckBox ch_DisWeapProgress;
|
||||
var automated moCheckBox ch_ShowHLMessages;
|
||||
var automated moCheckBox ch_CancelFire;
|
||||
var automated moCheckBox ch_CancelSwitching;
|
||||
var automated moCheckBox ch_CancelNades;
|
||||
var automated moCheckBox ch_CancelAiming;
|
||||
var automated moCheckBox ch_ReloadWontWork;
|
||||
var automated GUISectionBackground bg_WEAP;
|
||||
var automated GUISectionBackground bg_RELOAD;
|
||||
function InitComponent(GUIController MyController, GUIComponent MyOwner){
|
||||
super.InitComponent(MyController, MyOwner);
|
||||
}
|
||||
function InternalOnLoadINI(GUIComponent sender, string s){
|
||||
local NicePlayerController nicePlayer;
|
||||
nicePlayer = NicePlayerController(PlayerOwner());
|
||||
if(nicePlayer == none)
return;
|
||||
switch(sender){
|
||||
case ch_WeapManagement:
ch_WeapManagement.Checked(nicePlayer.bNiceWeaponManagement);
break;
|
||||
case ch_AltSwitches:
ch_AltSwitches.Checked(nicePlayer.bFlagAltSwitchesModes);
break;
|
||||
case ch_DispCounters:
ch_DispCounters.Checked(nicePlayer.bFlagDisplayCounters);
break;
|
||||
case ch_DisWeapProgress:
ch_DisWeapProgress.Checked(nicePlayer.bFlagDisplayWeaponProgress);
break;
|
||||
case ch_ShowHLMessages:
ch_ShowHLMessages.Checked(nicePlayer.bFlagShowHLMessages);
break;
|
||||
case ch_CancelFire:
ch_CancelFire.Checked(nicePlayer.bRelCancelByFire);
break;
|
||||
case ch_CancelSwitching:
ch_CancelSwitching.Checked(nicePlayer.bRelCancelBySwitching);
break;
|
||||
case ch_CancelNades:
ch_CancelNades.Checked(nicePlayer.bRelCancelByNades);
break;
|
||||
case ch_CancelAiming:
ch_CancelAiming.Checked(nicePlayer.bRelCancelByAiming);
break;
|
||||
case ch_ReloadWontWork:
ch_ReloadWontWork.Checked(nicePlayer.bFlagUseServerReload);
break;
|
||||
}
|
||||
}
|
||||
function InternalOnChange(GUIComponent Sender){
|
||||
local NicePlayerController nicePlayer;
|
||||
super.InternalOnChange(Sender);
|
||||
nicePlayer = NicePlayerController(PlayerOwner());
|
||||
if(nicePlayer == none)
return;
|
||||
switch(sender){
|
||||
case ch_WeapManagement:
nicePlayer.bNiceWeaponManagement = ch_WeapManagement.IsChecked();
break;
|
||||
case ch_AltSwitches:
nicePlayer.ServerSetAltSwitchesModes(ch_AltSwitches.IsChecked());
break;
|
||||
case ch_DispCounters:
nicePlayer.ServerSetDisplayCounters(ch_DispCounters.IsChecked());
break;
|
||||
case ch_DisWeapProgress:
nicePlayer.ServerSetDisplayWeaponProgress(ch_DisWeapProgress.IsChecked());
break;
|
||||
case ch_ShowHLMessages:
nicePlayer.ServerSetHLMessages(ch_ShowHLMessages.IsChecked());
break;
|
||||
case ch_CancelFire:
nicePlayer.bRelCancelByFire = ch_CancelFire.IsChecked();
break;
|
||||
case ch_CancelSwitching:
nicePlayer.bRelCancelBySwitching = ch_CancelSwitching.IsChecked();
break;
|
||||
case ch_CancelNades:
nicePlayer.bRelCancelByNades = ch_CancelNades.IsChecked();
break;
|
||||
case ch_CancelAiming:
nicePlayer.bRelCancelByAiming = ch_CancelAiming.IsChecked();
break;
|
||||
case ch_ReloadWontWork:
nicePlayer.ServerSetUseServerReload(ch_ReloadWontWork.IsChecked());
break;
|
||||
}
|
||||
nicePlayer.ClientSaveConfig();
|
||||
}
|
||||
// size = (x=0.0125, y=0.0) ; (w=1.0, h=0.865)
|
||||
// tab order
|
||||
defaultproperties
|
||||
{
Begin Object Class=moCheckBox Name=WeaponManagement
CaptionWidth=0.955000
Caption="Nice weapon management"
ComponentClassName="ScrnBalanceSrv.ScrnGUICheckBoxButton"
OnCreateComponent=WeaponManagement.InternalOnCreateComponent
IniOption="@Internal"
Hint="If checked, NicePack will use it's own system to manage weapon switching"
WinTop=0.050000
WinLeft=0.012500
WinWidth=0.278000
TabOrder=4
OnChange=NiceGUISettings.InternalOnChange
OnLoadINI=NiceGUISettings.InternalOnLoadINI
End Object
ch_WeapManagement=moCheckBox'NicePack.NiceGUISettings.WeaponManagement'
|
||||
Begin Object Class=moCheckBox Name=AltSwitches
CaptionWidth=0.955000
Caption="Alt fire switches modes"
ComponentClassName="ScrnBalanceSrv.ScrnGUICheckBoxButton"
OnCreateComponent=AltSwitches.InternalOnCreateComponent
IniOption="@Internal"
Hint="Assault-rifle only; if enabled - alt fire button switches between fire modes, otherwise - acts as an alt fire"
WinTop=0.100000
WinLeft=0.012500
WinWidth=0.278000
TabOrder=6
OnChange=NiceGUISettings.InternalOnChange
OnLoadINI=NiceGUISettings.InternalOnLoadINI
End Object
ch_AltSwitches=moCheckBox'NicePack.NiceGUISettings.AltSwitches'
|
||||
Begin Object Class=moCheckBox Name=DispCounters
CaptionWidth=0.955000
Caption="Display counters"
ComponentClassName="ScrnBalanceSrv.ScrnGUICheckBoxButton"
OnCreateComponent=DispCounters.InternalOnCreateComponent
IniOption="@Internal"
Hint="Toggles display of the various counters used by skills"
WinTop=0.150000
WinLeft=0.012500
WinWidth=0.278000
TabOrder=7
OnChange=NiceGUISettings.InternalOnChange
OnLoadINI=NiceGUISettings.InternalOnLoadINI
End Object
ch_DispCounters=moCheckBox'NicePack.NiceGUISettings.DispCounters'
|
||||
Begin Object Class=moCheckBox Name=DispWeapProgress
CaptionWidth=0.955000
Caption="Display weapon progress"
ComponentClassName="ScrnBalanceSrv.ScrnGUICheckBoxButton"
OnCreateComponent=DispWeapProgress.InternalOnCreateComponent
IniOption="@Internal"
Hint="Displays weapon progress rate, whoever it's defined by a skill that's using this functionality"
WinTop=0.200000
WinLeft=0.012500
WinWidth=0.278000
TabOrder=8
OnChange=NiceGUISettings.InternalOnChange
OnLoadINI=NiceGUISettings.InternalOnLoadINI
End Object
ch_DisWeapProgress=moCheckBox'NicePack.NiceGUISettings.DispWeapProgress'
|
||||
Begin Object Class=moCheckBox Name=ShowHLMessages
CaptionWidth=0.955000
Caption="Show Hardcore Level messages"
ComponentClassName="ScrnBalanceSrv.ScrnGUICheckBoxButton"
OnCreateComponent=ShowHLMessages.InternalOnCreateComponent
IniOption="@Internal"
Hint="Enable to be notified each time Hardcore Level is changed"
WinTop=0.300000
WinLeft=0.012500
WinWidth=0.278000
TabOrder=9
OnChange=NiceGUISettings.InternalOnChange
OnLoadINI=NiceGUISettings.InternalOnLoadINI
End Object
ch_ShowHLMessages=moCheckBox'NicePack.NiceGUISettings.ShowHLMessages'
|
||||
Begin Object Class=moCheckBox Name=CancelFire
CaptionWidth=0.955000
Caption="Cancel reload by shooting"
ComponentClassName="ScrnBalanceSrv.ScrnGUICheckBoxButton"
OnCreateComponent=CancelFire.InternalOnCreateComponent
IniOption="@Internal"
Hint="If checked, you'll be able to cancel reload of converted weapons by shooting (when you have ammo)"
WinTop=0.050000
WinLeft=0.517500
WinWidth=0.287000
TabOrder=11
OnChange=NiceGUISettings.InternalOnChange
OnLoadINI=NiceGUISettings.InternalOnLoadINI
End Object
ch_CancelFire=moCheckBox'NicePack.NiceGUISettings.CancelFire'
|
||||
Begin Object Class=moCheckBox Name=CancelSwitching
CaptionWidth=0.955000
Caption="Cancel reload by switching weapons"
ComponentClassName="ScrnBalanceSrv.ScrnGUICheckBoxButton"
OnCreateComponent=CancelSwitching.InternalOnCreateComponent
IniOption="@Internal"
Hint="If checked, you'll be able to cancel reload of converted weapons by switching to different weapon"
WinTop=0.100000
WinLeft=0.517500
WinWidth=0.287000
TabOrder=12
OnChange=NiceGUISettings.InternalOnChange
OnLoadINI=NiceGUISettings.InternalOnLoadINI
End Object
ch_CancelSwitching=moCheckBox'NicePack.NiceGUISettings.CancelSwitching'
|
||||
Begin Object Class=moCheckBox Name=CancelNades
CaptionWidth=0.955000
Caption="Cancel reload by throwing grenades"
ComponentClassName="ScrnBalanceSrv.ScrnGUICheckBoxButton"
OnCreateComponent=CancelNades.InternalOnCreateComponent
IniOption="@Internal"
Hint="If checked, you'll be able to cancel reload of converted weapons by throwing a grenade"
WinTop=0.150000
WinLeft=0.517500
WinWidth=0.287000
TabOrder=13
OnChange=NiceGUISettings.InternalOnChange
OnLoadINI=NiceGUISettings.InternalOnLoadINI
End Object
ch_CancelNades=moCheckBox'NicePack.NiceGUISettings.CancelNades'
|
||||
Begin Object Class=moCheckBox Name=CancelAiming
CaptionWidth=0.955000
Caption="Cancel reload by aiming"
ComponentClassName="ScrnBalanceSrv.ScrnGUICheckBoxButton"
OnCreateComponent=CancelAiming.InternalOnCreateComponent
IniOption="@Internal"
Hint="If checked, you'll be able to cancel reload of converted weapons by going into iron sights (when you have ammo)"
WinTop=0.200000
WinLeft=0.517500
WinWidth=0.287000
TabOrder=14
OnChange=NiceGUISettings.InternalOnChange
OnLoadINI=NiceGUISettings.InternalOnLoadINI
End Object
ch_CancelAiming=moCheckBox'NicePack.NiceGUISettings.CancelAiming'
|
||||
Begin Object Class=moCheckBox Name=ServerReload
CaptionWidth=0.955000
Caption="My reload doesn't work"
ComponentClassName="ScrnBalanceSrv.ScrnGUICheckBoxButton"
OnCreateComponent=ServerReload.InternalOnCreateComponent
IniOption="@Internal"
Hint="Check this option ONLY in case converted weapons don't reload at all for you; this option should fix the problem, but then latency will affect both reload and active reload"
WinTop=0.250000
WinLeft=0.517500
WinWidth=0.287000
TabOrder=15
OnChange=NiceGUISettings.InternalOnChange
OnLoadINI=NiceGUISettings.InternalOnLoadINI
End Object
ch_ReloadWontWork=moCheckBox'NicePack.NiceGUISettings.ServerReload'
|
||||
Begin Object Class=GUISectionBackground Name=WEAPBG
Caption="General weapon settings"
WinTop=0.012500
WinWidth=0.495000
WinHeight=0.287500
RenderWeight=0.100100
OnPreDraw=WeaponsBG.InternalPreDraw
End Object
bg_WEAP=GUISectionBackground'NicePack.NiceGUISettings.WEAPBG'
|
||||
Begin Object Class=GUISectionBackground Name=RELOADBG
Caption="Weapon reload settings"
WinTop=0.012500
WinLeft=0.505000
WinWidth=0.495000
WinHeight=0.287500
RenderWeight=0.100100
OnPreDraw=WeaponsBG.InternalPreDraw
End Object
bg_RELOAD=GUISectionBackground'NicePack.NiceGUISettings.RELOADBG'
|
||||
}
|
216
sources/GUI/NiceInteraction.uc
Normal file
216
sources/GUI/NiceInteraction.uc
Normal file
@ -0,0 +1,216 @@
|
||||
class NiceInteraction extends Interaction
|
||||
dependson(NicePack)
|
||||
dependson(NiceAbilityManager);
|
||||
#exec OBJ LOAD FILE=KillingFloor2HUD.utx
|
||||
var NicePack NicePackMutator;
|
||||
var Material bleedIcon, poisonIcon;
|
||||
var Texture greenBar, redBar;
|
||||
var Texture shield;
|
||||
var float size;
|
||||
// Weapon box sizes
|
||||
var float InventoryBoxWidth;
|
||||
var float InventoryBoxHeight;
|
||||
var float BorderSize;
|
||||
event NotifyLevelChange(){
|
||||
Master.RemoveInteraction(self);
|
||||
}
|
||||
function RegisterMutator(NicePack activePack){
|
||||
NicePackMutator = activePack;
|
||||
}
|
||||
function bool isPoisoned(ScrnHumanPawn pwn){
|
||||
local Inventory I;
|
||||
if(pwn.Inventory != none)
for(I = pwn.Inventory; I != none; I = I.Inventory)
if(I != none && MeanPoisonInventory(I) != none)
return true;
|
||||
return false;
|
||||
}
|
||||
function PostRender(Canvas C){
|
||||
local int i;
|
||||
local NicePack niceMutator;
|
||||
local NiceHumanPawn nicePawn;
|
||||
local class<NiceVeterancyTypes> niceVet;
|
||||
local MeanReplicationInfo szRI;
|
||||
local NiceWeapon niceWeap;
|
||||
local NicePlayerController nicePlayer;
|
||||
local ScrnHUD scrnHUDInstance;
|
||||
local Texture barTexture;
|
||||
local int x, y, center, barWidth, offset;
|
||||
local int missesWidth, missesHeight, missesSpace;
|
||||
local int missesX, missesY;
|
||||
if(C == none) return;
|
||||
if(C.ViewPort == none) return;
|
||||
if(C.ViewPort.Actor == none) return;
|
||||
if(C.ViewPort.Actor.Pawn == none) return;
|
||||
nicePlayer = NicePlayerController(C.ViewPort.Actor.Pawn.Controller);
|
||||
niceWeap = NiceWeapon(C.ViewPort.Actor.Pawn.Weapon);
|
||||
if(nicePlayer == none)
return;
|
||||
scrnHUDInstance = ScrnHUD(nicePlayer.myHUD);
|
||||
//// Draw bleed and poison icons
|
||||
C.SetDrawColor(255, 255, 255);
|
||||
szRI = class'MeanReplicationInfo'.static.findSZri(ViewportOwner.Actor.PlayerReplicationInfo);
|
||||
offset = 4;
|
||||
if(szRI != none){
if(szRI.isBleeding){
x = C.ClipX * 0.007;
y = C.ClipY * 0.93 - size * offset;
C.SetPos(x, y);
C.DrawTile(bleedIcon, size, size, 0, 0, bleedIcon.MaterialUSize(), bleedIcon.MaterialVSize());
}
offset++;
if(isPoisoned(ScrnHumanPawn(C.ViewPort.Actor.Pawn))){
x = C.ClipX * 0.007;
y = C.ClipY * 0.93 - size * offset;
C.SetPos(x, y);
C.DrawTile(poisonIcon, size, size, 0, 0, poisonIcon.MaterialUSize(), poisonIcon.MaterialVSize());
}
|
||||
}
|
||||
if(niceWeap != none && niceWeap.bShowSecondaryCharge && scrnHUDInstance != none){
C.ColorModulate.X = 1;
C.ColorModulate.Y = 1;
C.ColorModulate.Z = 1;
C.ColorModulate.W = scrnHUDInstance.HudOpacity / 255;
if(!scrnHUDInstance.bLightHud)
scrnHUDInstance.DrawSpriteWidget(C, scrnHUDInstance.SecondaryClipsBG);
scrnHUDInstance.DrawSpriteWidget(C, scrnHUDInstance.SecondaryClipsIcon);
scrnHUDInstance.SecondaryClipsDigits.value = niceWeap.secondaryCharge;
scrnHUDInstance.DrawNumericWidget(C, scrnHUDInstance.SecondaryClipsDigits, scrnHUDInstance.DigitsSmall);
|
||||
}
|
||||
niceMutator = class'NicePack'.static.Myself(C.ViewPort.Actor.Pawn.Level);
|
||||
if(niceMutator == none)
return;
|
||||
//// Draw counters
|
||||
if(nicePlayer != none && nicePlayer.bFlagDisplayCounters){
x = C.ClipX * 0.5 - (64 + 2) * niceMutator.GetVisibleCountersAmount();
y = C.ClipY * 0.01;
for(i = 0;i < niceMutator.niceCounterSet.Length;i ++)
if(niceMutator.niceCounterSet[i].value != 0 || niceMutator.niceCounterSet[i].bShowZeroValue){
DrawCounter(C, niceMutator.niceCounterSet[i], x, y, C.ViewPort.Actor.Pawn.PlayerReplicationInfo.Team);
x += 128 + 4;
}
|
||||
}
|
||||
//// Draw weapons progress bars
|
||||
if(nicePlayer != none && nicePlayer.bFlagDisplayWeaponProgress){
x = C.ClipX - InventoryBoxWidth * C.ClipX - 5;
y = C.ClipY * 0.5 - 0.5 * (InventoryBoxHeight * C.ClipX + 4) * niceMutator.niceWeapProgressSet.Length;
for(i = 0;i < niceMutator.niceWeapProgressSet.Length;i ++){
DrawWeaponProgress(C, niceMutator.niceWeapProgressSet[i], x, y,
C.ViewPort.Actor.Pawn.PlayerReplicationInfo.Team);
y += (InventoryBoxHeight * C.ClipX + 4);
}
|
||||
}
|
||||
//// Draw invincibility bar
|
||||
nicePawn = NiceHumanPawn(nicePlayer.pawn);
|
||||
if(nicePawn != none && nicePawn.invincibilityTimer != 0.0){
C.SetDrawColor(255, 255, 255);
if(nicePawn.invincibilityTimer > 0)
barTexture = greenBar;
else
barTexture = redBar;
center = C.ClipX * 0.5;
y = C.ClipY * 0.75;
barWidth = C.ClipX * 0.2;
niceVet = class'NiceVeterancyTypes'.static.
GetVeterancy(nicePawn.PlayerReplicationInfo);
if(niceVet != none){
if(nicePawn.invincibilityTimer > 0){
barWidth *= nicePawn.invincibilityTimer
/ niceVet.static.GetInvincibilityDuration(nicePawn.KFPRI);
}
else{
barWidth *= nicePawn.invincibilityTimer /
class'NiceSkillZerkGunzerker'.default.cooldown;
}
}
else
barWidth = 0;
x = center - (barWidth / 2);
C.SetPos(x, y);
C.DrawTile(barTexture, barWidth, 32, 0, 0, barTexture.MaterialUSize(), barTexture.MaterialVSize());
if(nicePawn.safeMeleeMisses <= 0)
return;
missesSpace = 10;//64x64 => 16x16
missesHeight = 16;
missesWidth = nicePawn.safeMeleeMisses * 16
+ (nicePawn.safeMeleeMisses - 1) * missesSpace;
missesX = center - (missesWidth / 2);
missesY = y + (32 - missesHeight) * 0.5;
for(i = 0;i < nicePawn.safeMeleeMisses;i ++){
C.SetPos(missesX + i * (16 + missesSpace), missesY);
C.DrawTile(shield, 16, 16, 0, 0, shield.MaterialUSize(), shield.MaterialVSize());
}
|
||||
}
|
||||
// Draw cooldowns
|
||||
if(nicePlayer.abilityManager == none)
return;
|
||||
for(i = 0;i < nicePlayer.abilityManager.currentAbilitiesAmount;i ++)
DrawAbilityCooldown(C, i);
|
||||
}
|
||||
function DrawCounter(Canvas C, NicePack.CounterDisplay counter, int x, int y, TeamInfo team){
|
||||
local float borderSpace;
|
||||
local Texture textureToDraw;
|
||||
local float textWidth, textHeight;
|
||||
local string textToDraw;
|
||||
// Some per-defined values for drawing
|
||||
local int iconSize, backgroundWidth, backgroundHeight;
|
||||
// Fill some constants that will dictate how to display counter
|
||||
iconSize = 64;
|
||||
backgroundWidth = 128;
|
||||
backgroundHeight = 64;
|
||||
borderSpace = 8;
|
||||
// Reset color
|
||||
if(team.teamIndex == 0)
C.SetDrawColor(255, 64, 64);
|
||||
else
C.SetDrawColor(team.teamColor.R, team.teamColor.G, team.teamColor.B);
|
||||
// Draw background
|
||||
C.SetPos(x, y);
|
||||
textureToDraw = Texture(class'HUDKillingFloor'.default.HealthBG.WidgetTexture);
|
||||
C.DrawTile(textureToDraw, 128, 64, 0, 0, textureToDraw.MaterialUSize(), textureToDraw.MaterialVSize());
|
||||
// Draw appropriate icon
|
||||
C.SetPos(x + borderSpace, y + borderSpace);
|
||||
textureToDraw = counter.icon;
|
||||
C.DrawTile(textureToDraw, 64 - 2*borderSpace, 64 - 2 * borderSpace, 0, 0,
textureToDraw.MaterialUSize(), textureToDraw.MaterialVSize());
|
||||
// Draw numbers
|
||||
textToDraw = string(counter.value);
|
||||
C.Font = class'ROHUD'.Static.LoadSmallFontStatic(1);
|
||||
C.TextSize(textToDraw, textWidth, textHeight);
|
||||
C.SetPos(x + iconSize + (backgroundWidth - iconSize - textWidth) / 2, y + (backgroundHeight - textHeight) / 2 + 2);
|
||||
C.DrawText(textToDraw);
|
||||
}
|
||||
function DrawAbilityCooldown(Canvas C, int abilityIndex){
|
||||
local Texture skillTexture, backgroundTexture;
|
||||
local NiceHumanPawn nicePawn;
|
||||
local NicePlayerController nicePlayer;
|
||||
local class<NiceVeterancyTypes> niceVet;
|
||||
local int x, y;
|
||||
local string textToDraw;
|
||||
local float textWidth, textHeight;
|
||||
local NiceAbilityManager.EAbilityState abilityState;
|
||||
if(C == none) return;
|
||||
if(C.ViewPort == none) return;
|
||||
if(C.ViewPort.Actor == none) return;
|
||||
nicePawn = NiceHumanPawn(C.ViewPort.Actor.Pawn);
|
||||
nicePlayer = NicePlayerController(C.ViewPort.Actor.Pawn.Controller);
|
||||
if(nicePawn == none)
return;
|
||||
if(nicePlayer == none || nicePlayer.abilityManager == none)
return;
|
||||
niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(nicePawn.KFPRI);
|
||||
skillTexture =
nicePlayer.abilityManager.currentAbilities[abilityIndex].
description.icon;
|
||||
if(skillTexture == none)
return;
|
||||
// Set stuff up
|
||||
x = C.ClipX * 0.265;
|
||||
x += abilityIndex * (10 + 64);
|
||||
y = C.ClipY * 0.93;
|
||||
textToDraw = string(int(Ceil(nicePlayer.abilityManager.currentAbilities[abilityIndex].cooldown)));
|
||||
backgroundTexture = Texture'KillingFloorHUD.HUD.Hud_Box_128x64';
|
||||
// Reset color
|
||||
C.SetDrawColor(255, 64, 64);
|
||||
// Draw background
|
||||
C.SetPos(x, y);
|
||||
C.DrawTile(backgroundTexture, 64, 64, 0, 0, backgroundTexture.MaterialUSize(), backgroundTexture.MaterialVSize());
|
||||
C.SetPos(x, y);
|
||||
C.DrawTile(skillTexture, 64, 64, 0, 0, skillTexture.MaterialUSize(), skillTexture.MaterialVSize());
|
||||
// Draw additional background
|
||||
abilityState =
nicePlayer.abilityManager.currentAbilities[abilityIndex].myState;
|
||||
if(abilityState == ASTATE_ACTIVE)
C.SetDrawColor(255, 0, 0, 128);
|
||||
if(abilityState == ASTATE_COOLDOWN)
C.SetDrawColor(0, 0, 0, 192);
|
||||
if(abilityState != ASTATE_READY){
C.SetPos(x, y);
C.DrawTileStretched(Material'KillingFloorHUD.HUD.WhiteTexture', 64, 64);
|
||||
}
|
||||
// Draw cooldown stuff
|
||||
if(abilityState == ASTATE_COOLDOWN){
C.SetDrawColor(255, 192, 192);
C.Font = class'ROHUD'.static.LoadSmallFontStatic(1);
C.TextSize(textToDraw, textWidth, textHeight);
C.SetPos(x, y);
C.SetPos(x + (64 - textWidth) / 2, y + (64 - textHeight) / 2 + 2);
C.DrawText(textToDraw);
|
||||
}
|
||||
// Draw calibration GUI
|
||||
DrawCalibrationStars(C);
|
||||
}
|
||||
function DrawCalibrationStars(Canvas C){
|
||||
local Texture starTexture;
|
||||
local int x, y, i;
|
||||
local int starsAmount;
|
||||
local NiceHumanPawn nicePawn;
|
||||
local NicePlayerController nicePlayer;
|
||||
if(C == none) return;
|
||||
if(C.ViewPort == none) return;
|
||||
if(C.ViewPort.Actor == none) return;
|
||||
nicePawn = NiceHumanPawn(C.ViewPort.Actor.Pawn);
|
||||
if(nicePawn == none)
return;
|
||||
if(nicePawn.currentCalibrationState == CALSTATE_NOABILITY)
return;
|
||||
nicePlayer = NicePlayerController(nicePawn.controller);
|
||||
if(nicePlayer == none)
return;
|
||||
starsAmount = nicePawn.calibrationScore;
|
||||
x = C.ClipX * 0.5;
|
||||
x -= 0.5 * (starsAmount * 32 + (starsAmount - 1) * 16);
|
||||
if(nicePawn.currentCalibrationState == CALSTATE_ACTIVE)
y = C.ClipY * 0.6;
|
||||
else
y = C.ClipY * 0.02;
|
||||
starTexture = Texture'KillingFloorHUD.HUD.Hud_Perk_Star';
|
||||
for(i = 0;i < starsAmount;i ++){
C.SetPos(x, y);
C.SetDrawColor(255, 255, 255);
C.DrawTile(starTexture, 32, 32, 0, 0, starTexture.MaterialUSize(), starTexture.MaterialVSize());
x += 32 + 16;
|
||||
}
|
||||
}
|
||||
function DrawWeaponProgress(Canvas C, NicePack.WeaponProgressDisplay weapProgress, int x, int y, TeamInfo team){
|
||||
local float textWidth, textHeight;
|
||||
local string textToDraw;
|
||||
local float TempWidth, TempHeight, TempBorder;
|
||||
TempWidth = InventoryBoxWidth * C.ClipX;
|
||||
TempHeight = InventoryBoxHeight * C.ClipX;
|
||||
TempBorder = BorderSize * C.ClipX;
|
||||
// Draw background bar
|
||||
if(team.teamIndex == 0)
C.SetDrawColor(255, 64, 64, 64);
|
||||
else
C.SetDrawColor(team.teamColor.R, team.teamColor.G, team.teamColor.B, 64);
|
||||
C.SetPos(x, y);
|
||||
C.DrawTile(Texture'Engine.WhiteSquareTexture', TempWidth * weapProgress.progress, TempHeight, 0, 0, 2, 2);
|
||||
// Draw this item's Background
|
||||
if(team.teamIndex == 0)
C.SetDrawColor(255, 64, 64);
|
||||
else
C.SetDrawColor(team.teamColor.R, team.teamColor.G, team.teamColor.B);
|
||||
C.SetPos(x, y);
|
||||
C.DrawTileStretched(Texture'KillingFloorHUD.HUD.HUD_Rectangel_W_Stroke', TempWidth, TempHeight);
|
||||
// Draw the Weapon's Icon over the Background
|
||||
C.SetDrawColor(255, 255, 255);
|
||||
C.SetPos(x + TempBorder, y + TempBorder);
|
||||
if(weapProgress.weapClass.default.HudImage != none)
C.DrawTile(weapProgress.weapClass.default.HudImage,
TempWidth - (2.0 * TempBorder), TempHeight - (2.0 * TempBorder), 0, 0, 256, 192);
|
||||
// Draw counter, if needed
|
||||
if(team.teamIndex == 0)
C.SetDrawColor(255, 64, 64);
|
||||
else
C.SetDrawColor(team.teamColor.R, team.teamColor.G, team.teamColor.B);
|
||||
if(weapProgress.bShowCounter){
textToDraw = string(weapProgress.counter);
C.Font = class'ROHUD'.Static.LoadSmallFontStatic(5);
C.TextSize(textToDraw, textWidth, textHeight);
C.SetPos(x + TempWidth - TempBorder - textWidth, y + TempHeight - TempBorder - textHeight + 2);
C.DrawText(textToDraw);
|
||||
}
|
||||
}
|
||||
function bool KeyEvent(EInputKey Key, EInputAction Action, float Delta){
|
||||
local bool bNeedsReload;
|
||||
local string Alias, LeftPart, RigthPart;
|
||||
local NiceWeapon niceWeap;
|
||||
local NicePlayerController nicePlayer;
|
||||
// Find controller and current weapon
|
||||
nicePlayer = NicePlayerController(ViewportOwner.Actor);
|
||||
if(nicePlayer == none)
return false;
|
||||
if(nicePlayer.Pawn != none)
niceWeap = NiceWeapon(nicePlayer.Pawn.Weapon);
|
||||
// If this is a button press - detect alias
|
||||
if(Action == IST_Press){
// Check for reload command
Alias = nicePlayer.ConsoleCommand("KEYBINDING" @ nicePlayer.ConsoleCommand("KEYNAME" @ Key));
if(nicePlayer.bAdvReloadCheck)
bNeedsReload = InStr(Caps(Alias), "RELOADMENOW") > -1 || InStr(Caps(Alias), "RELOADWEAPON") > -1;
if(Divide(Alias, " ", LeftPart, RigthPart))
Alias = LeftPart;
if(Key == IK_MouseWheelUp || Key == IK_MouseWheelDown){
nicePlayer.UpdateSelectors();
if(nicePlayer.hasZeroSelector && nicePlayer.bUsesMouseWheel && nicePlayer.bNiceWeaponManagement){
nicePlayer.ScrollSelector(0, nicePlayer.bMouseWheelLoops, Key == IK_MouseWheelUp);
return true;
}
}
|
||||
}
|
||||
// Open trader on movement
|
||||
if(Alias ~= "MoveForward" || Alias ~= "MoveBackward" || Alias ~= "TurnLeft" || Alias ~= "TurnRight"
|| Alias ~= "StrafeLeft" || Alias ~= "StrafeRight" || Alias ~= "Axis"){
|
||||
// Open trader if it's a pre-game
if(NicePackMutator.bIsPreGame && NicePackMutator.bInitialTrader && (NicePackMutator.bStillDuringInitTrader || !nicePlayer.bOpenedInitTrader) && nicePlayer.Pawn != none){
nicePlayer.ShowBuyMenu("Initial trader", KFHumanPawn(nicePlayer.Pawn).MaxCarryWeight);
nicePlayer.bOpenedInitTrader = true;
return true;
}
//nicePlayer.ClientOpenMenu("NicePack.NiceGUIBuyMenu",,"Test stuff",string(15));
|
||||
}
|
||||
// Reload if we've detected a reload alias in this button's command
|
||||
if(niceWeap != none && !nicePlayer.bUseServerReload &&
(bNeedsReload || Alias ~= "ReloadMeNow" || Alias ~= "ReloadWeapon"))
niceWeap.ClientReloadMeNow();
|
||||
return false;
|
||||
}
|
||||
defaultproperties
|
||||
{
bleedIcon=Texture'NicePackT.MeanZeds.bleedIcon'
poisonIcon=Texture'NicePackT.MeanZeds.poisonIcon'
greenBar=Texture'KFStoryGame_Tex.HUD.Batter_Fill'
redBar=Texture'KFStoryGame_Tex.HUD.BarFill_Red'
Shield=Texture'KillingFloorHUD.HUD.Hud_Shield'
Size=75.599998
InventoryBoxWidth=0.100000
InventoryBoxHeight=0.075000
BorderSize=0.005000
bVisible=True
|
||||
}
|
54
sources/GUI/NiceInvasionLoginMenu.uc
Normal file
54
sources/GUI/NiceInvasionLoginMenu.uc
Normal file
@ -0,0 +1,54 @@
|
||||
class NiceInvasionLoginMenu extends ScrnInvasionLoginMenu;
|
||||
var bool bShowScrnMenu;
|
||||
// copy-pasted from ScrnInvasionLoginMenu to change change remove news tab and add skills tab
|
||||
function InitComponent(GUIController MyController, GUIComponent MyOwner){
|
||||
local int i;
|
||||
local string s;
|
||||
local eFontScale FS;
|
||||
local SRMenuAddition M;
|
||||
local int indexAfterScrn;
|
||||
// Setup panel classes.
|
||||
Panels[0].ClassName = string(Class'ScrnBalanceSrv.ScrnTab_MidGamePerks');
|
||||
Panels[1].ClassName = string(Class'NicePack.NicePanelSkills');
|
||||
Panels[2].ClassName = string(Class'SRTab_MidGameVoiceChat');
|
||||
Panels[3].ClassName = string(Class'SRTab_MidGameStats');
|
||||
Panels[0].Caption = Class'KFInvasionLoginMenu'.Default.Panels[1].Caption;
|
||||
Panels[1].Caption = "Skills";
|
||||
Panels[2].Caption = Class'KFInvasionLoginMenu'.Default.Panels[2].Caption;
|
||||
Panels[0].Hint = Class'KFInvasionLoginMenu'.Default.Panels[1].Hint;
|
||||
Panels[1].Hint = "Customize your perk";
|
||||
Panels[2].Hint = Class'KFInvasionLoginMenu'.Default.Panels[2].Hint;
|
||||
b_Spec.Caption=class'KFTab_MidGamePerks'.default.b_Spec.Caption;
|
||||
b_MatchSetup.Caption=class'KFTab_MidGamePerks'.default.b_MatchSetup.Caption;
|
||||
b_KickVote.Caption=class'KFTab_MidGamePerks'.default.b_KickVote.Caption;
|
||||
b_MapVote.Caption=class'KFTab_MidGamePerks'.default.b_MapVote.Caption;
|
||||
b_Quit.Caption=class'KFTab_MidGamePerks'.default.b_Quit.Caption;
|
||||
b_Favs.Caption=class'KFTab_MidGamePerks'.default.b_Favs.Caption;
|
||||
b_Favs.Hint=class'KFTab_MidGamePerks'.default.b_Favs.Hint;
|
||||
b_Settings.Caption=class'KFTab_MidGamePerks'.default.b_Settings.Caption;
|
||||
b_Browser.Caption=class'KFTab_MidGamePerks'.default.b_Browser.Caption;
|
||||
// Other panels
|
||||
Panels[4].ClassName = "ScrnBalanceSrv.ScrnTab_Achievements";
|
||||
Panels[4].Caption = "Achievements";
|
||||
Panels[4].Hint = "ScrN server-side achievements";
|
||||
if(default.bShowScrnMenu){
Panels[5].ClassName = "ScrnBalanceSrv.ScrnTab_UserSettings";
Panels[5].Caption = "ScrN Features";
Panels[5].Hint = "ScrN Balance features, settings and info";
indexAfterScrn = 6;
|
||||
}
|
||||
else
indexAfterScrn = 5;
|
||||
Panels[indexAfterScrn].ClassName = "NicePack.NiceGUISettings";
|
||||
Panels[indexAfterScrn].Caption = "Nice settings";
|
||||
Panels[indexAfterScrn].Hint = "Settings specific to NicePack mutator";
|
||||
Panels.Length = indexAfterScrn + 1;
|
||||
Super(UT2K4PlayerLoginMenu).InitComponent(MyController, MyOwner);
|
||||
// Mod menus
|
||||
foreach MyController.ViewportOwner.Actor.DynamicActors(class'SRMenuAddition',M)
if( M.bHasInit )
{
AddOnList[AddOnList.Length] = M;
M.NotifyMenuOpen(Self,MyController);
}
|
||||
s = GetSizingCaption();
|
||||
for ( i = 0; i < Controls.Length; i++ )
|
||||
{
if (GUIButton(Controls[i]) != none)
{
GUIButton(Controls[i]).bAutoSize = true;
GUIButton(Controls[i]).SizingCaption = s;
GUIButton(Controls[i]).AutoSizePadding.HorzPerc = 0.04;
GUIButton(Controls[i]).AutoSizePadding.VertPerc = 0.5;
}
|
||||
}
|
||||
s = class'KFTab_MidGamePerks'.default.PlayerStyleName;
|
||||
PlayerStyle = MyController.GetStyle(s, fs);
|
||||
InitGRI();
|
||||
}
|
||||
defaultproperties
|
||||
{
|
||||
}
|
14
sources/GUI/NiceLobbyFooter.uc
Normal file
14
sources/GUI/NiceLobbyFooter.uc
Normal file
@ -0,0 +1,14 @@
|
||||
class NiceLobbyFooter extends ScrnLobbyFooter;
|
||||
function bool OnFooterClick(GUIComponent Sender)
|
||||
{
|
||||
if (Sender == b_Perks){
PlayerOwner().ClientOpenMenu(string(Class'NicePack.NiceInvasionLoginMenu'), false);
return false;
|
||||
}
|
||||
else if(Sender == b_ViewMap){
if(KF_StoryGRI(PlayerOwner().Level.GRI) == none){
LobbyMenu(PageOwner).bAllowClose = true;
PlayerOwner().ClientCloseMenu(true, false);
LobbyMenu(PageOwner).bAllowClose = false;
}
|
||||
}
|
||||
else if(Sender == b_Ready){
return super(LobbyFooter).OnFooterClick(Sender); // bypass serverperks
|
||||
}
|
||||
else
return super.OnFooterClick(Sender);
|
||||
}
|
||||
defaultproperties
|
||||
{
|
||||
}
|
4
sources/GUI/NiceLobbyMenu.uc
Normal file
4
sources/GUI/NiceLobbyMenu.uc
Normal file
@ -0,0 +1,4 @@
|
||||
class NiceLobbyMenu extends ScrnLobbyMenu;
|
||||
defaultproperties
|
||||
{
Begin Object Class=NiceLobbyFooter Name=BuyFooter
RenderWeight=0.300000
TabOrder=8
bBoundToParent=False
bScaleToParent=False
OnPreDraw=BuyFooter.InternalOnPreDraw
End Object
t_Footer=NiceLobbyFooter'NicePack.NiceLobbyMenu.BuyFooter'
|
||||
}
|
26
sources/GUI/NicePanelSkills.uc
Normal file
26
sources/GUI/NicePanelSkills.uc
Normal file
@ -0,0 +1,26 @@
|
||||
class NicePanelSkills extends Settings_Tabs;
|
||||
var automated NiceGUIPerkButton skillButtonA[5], skillButtonB[5];
|
||||
function ShowPanel(bool bShow){
|
||||
local int i;
|
||||
local class<NiceVeterancyTypes> niceVet;
|
||||
local NicePlayerController nicePlayer;
|
||||
Super.ShowPanel(bShow);
|
||||
nicePlayer = NicePlayerController(PlayerOwner());
|
||||
if(nicePlayer != none)
niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(nicePlayer.PlayerReplicationInfo);
|
||||
if(niceVet != none){
for(i = 0;i < 5;i ++){
skillButtonA[i].skillIndex = i;
skillButtonB[i].skillIndex = i;
skillButtonA[i].skillPerkIndex = niceVet.default.PerkIndex;
skillButtonB[i].skillPerkIndex = niceVet.default.PerkIndex;
skillButtonA[i].isAltSkill = false;
skillButtonB[i].isAltSkill = true;
skillButtonA[i].associatedSkill = niceVet.default.SkillGroupA[i];
skillButtonB[i].associatedSkill = niceVet.default.SkillGroupB[i];
}
|
||||
}
|
||||
}
|
||||
// size = (x=0.0125, y=0.0) ; (w=1.0, h=0.865)
|
||||
// setup caption
|
||||
defaultproperties
|
||||
{
Begin Object Class=NiceGUIPerkButton Name=btn1A
WinTop=0.012500
WinWidth=0.495000
WinHeight=0.160000
RenderWeight=2.000000
TabOrder=1
bBoundToParent=True
bScaleToParent=True
bMouseOverSound=False
OnClickSound=CS_None
OnKeyEvent=btn1A.InternalOnKeyEvent
End Object
skillButtonA(0)=NiceGUIPerkButton'NicePack.NicePanelSkills.btn1A'
|
||||
Begin Object Class=NiceGUIPerkButton Name=btn2A
WinTop=0.188500
WinWidth=0.495000
WinHeight=0.160000
RenderWeight=2.000000
TabOrder=3
bBoundToParent=True
bScaleToParent=True
bMouseOverSound=False
OnClickSound=CS_None
OnKeyEvent=btn2A.InternalOnKeyEvent
End Object
skillButtonA(1)=NiceGUIPerkButton'NicePack.NicePanelSkills.btn2A'
|
||||
Begin Object Class=NiceGUIPerkButton Name=btn3A
WinTop=0.364500
WinWidth=0.495000
WinHeight=0.160000
RenderWeight=2.000000
TabOrder=5
bBoundToParent=True
bScaleToParent=True
bMouseOverSound=False
OnClickSound=CS_None
OnKeyEvent=btn3A.InternalOnKeyEvent
End Object
skillButtonA(2)=NiceGUIPerkButton'NicePack.NicePanelSkills.btn3A'
|
||||
Begin Object Class=NiceGUIPerkButton Name=btn4A
WinTop=0.540500
WinWidth=0.495000
WinHeight=0.160000
RenderWeight=2.000000
TabOrder=7
bBoundToParent=True
bScaleToParent=True
bMouseOverSound=False
OnClickSound=CS_None
OnKeyEvent=btn4A.InternalOnKeyEvent
End Object
skillButtonA(3)=NiceGUIPerkButton'NicePack.NicePanelSkills.btn4A'
|
||||
Begin Object Class=NiceGUIPerkButton Name=btn5A
WinTop=0.716500
WinWidth=0.495000
WinHeight=0.160000
RenderWeight=2.000000
TabOrder=9
bBoundToParent=True
bScaleToParent=True
bMouseOverSound=False
OnClickSound=CS_None
OnKeyEvent=btn5A.InternalOnKeyEvent
End Object
skillButtonA(4)=NiceGUIPerkButton'NicePack.NicePanelSkills.btn5A'
|
||||
Begin Object Class=NiceGUIPerkButton Name=btn1B
WinTop=0.012500
WinLeft=0.505000
WinWidth=0.495000
WinHeight=0.160000
RenderWeight=2.000000
TabOrder=2
bBoundToParent=True
bScaleToParent=True
bMouseOverSound=False
OnClickSound=CS_None
OnKeyEvent=btn1B.InternalOnKeyEvent
End Object
skillButtonB(0)=NiceGUIPerkButton'NicePack.NicePanelSkills.btn1B'
|
||||
Begin Object Class=NiceGUIPerkButton Name=btn2B
WinTop=0.188500
WinLeft=0.505000
WinWidth=0.495000
WinHeight=0.160000
RenderWeight=2.000000
TabOrder=4
bBoundToParent=True
bScaleToParent=True
bMouseOverSound=False
OnClickSound=CS_None
OnKeyEvent=btn2B.InternalOnKeyEvent
End Object
skillButtonB(1)=NiceGUIPerkButton'NicePack.NicePanelSkills.btn2B'
|
||||
Begin Object Class=NiceGUIPerkButton Name=btn3B
WinTop=0.364500
WinLeft=0.505000
WinWidth=0.495000
WinHeight=0.160000
RenderWeight=2.000000
TabOrder=6
bBoundToParent=True
bScaleToParent=True
bMouseOverSound=False
OnClickSound=CS_None
OnKeyEvent=btn3B.InternalOnKeyEvent
End Object
skillButtonB(2)=NiceGUIPerkButton'NicePack.NicePanelSkills.btn3B'
|
||||
Begin Object Class=NiceGUIPerkButton Name=btn4B
WinTop=0.540500
WinLeft=0.505000
WinWidth=0.495000
WinHeight=0.160000
RenderWeight=2.000000
TabOrder=8
bBoundToParent=True
bScaleToParent=True
bMouseOverSound=False
OnClickSound=CS_None
OnKeyEvent=btn4B.InternalOnKeyEvent
End Object
skillButtonB(3)=NiceGUIPerkButton'NicePack.NicePanelSkills.btn4B'
|
||||
Begin Object Class=NiceGUIPerkButton Name=btn5B
WinTop=0.716500
WinLeft=0.505000
WinWidth=0.495000
WinHeight=0.160000
RenderWeight=2.000000
TabOrder=10
bBoundToParent=True
bScaleToParent=True
bMouseOverSound=False
OnClickSound=CS_None
OnKeyEvent=btn5B.InternalOnKeyEvent
End Object
skillButtonB(4)=NiceGUIPerkButton'NicePack.NicePanelSkills.btn5B'
|
||||
}
|
53
sources/NiceFFVoting.uc
Normal file
53
sources/NiceFFVoting.uc
Normal file
@ -0,0 +1,53 @@
|
||||
class NiceFFVoting extends ScrnVotingOptions;
|
||||
var NicePack Mut;
|
||||
const VOTE_CHANGE = 1;
|
||||
const VOTE_RESET = 2;
|
||||
function int GetGroupVoteIndex(PlayerController Sender, string Group, string Key, out string Value, out string VoteInfo){
|
||||
local TeamGame TG;
|
||||
local float ffScale;
|
||||
local bool bCanIncrease;
|
||||
ffScale = float(Value);
|
||||
TG = TeamGame(Level.Game);
|
||||
bCanIncrease = true;
|
||||
if(Mut != none){
|
||||
bCanIncrease = !Mut.bFFWasIncreased || !Mut.bOneFFIncOnly;
|
||||
if(Mut.ScrnGT != none)
|
||||
bCanIncrease = bCanIncrease && (!Mut.bNoLateFFIncrease || (Mut.ScrnGT.WaveNum < 1 || (Mut.ScrnGT.WaveNum == 2 && Mut.ScrnGT.bTradingDoorsOpen)));
|
||||
}
|
||||
if(Key ~= "CHANGE"){
|
||||
if(ffScale < 0.0 || ffScale > 1.0)
|
||||
return VOTE_ILLEGAL;
|
||||
if(TG != none && (ffScale <= TG.FriendlyFireScale || bCanIncrease))
|
||||
return VOTE_CHANGE;
|
||||
else
|
||||
return VOTE_ILLEGAL;
|
||||
}
|
||||
else if(Key ~= "RESET")
|
||||
return VOTE_RESET;
|
||||
return VOTE_UNKNOWN;
|
||||
}
|
||||
function ApplyVoteValue(int VoteIndex, string VoteValue){
|
||||
local TeamGame TG;
|
||||
local float ffScale;
|
||||
TG = TeamGame(Level.Game);
|
||||
if(VoteIndex == VOTE_CHANGE){
|
||||
ffScale = float(VoteValue);
|
||||
ffScale = FMax(0.0, FMin(1.0, ffScale));
|
||||
}
|
||||
else if(VoteIndex == VOTE_RESET)
|
||||
ffScale = TG.default.FriendlyFireScale;
|
||||
if(TG != none){
|
||||
if(ffScale > TG.FriendlyFireScale)
|
||||
Mut.bFFWasIncreased = true;
|
||||
TG.FriendlyFireScale = ffScale;
|
||||
}
|
||||
}
|
||||
function SendGroupHelp(PlayerController Sender, string Group){
|
||||
super.SendGroupHelp(Sender, Group);
|
||||
}
|
||||
defaultproperties
|
||||
{
|
||||
DefaultGroup="FF"
|
||||
HelpInfo(0)="%pFF %gRESET%w|%rCHANGE %y<ff_scale> %wChanges friendly fire scale."
|
||||
GroupInfo(0)="%pFF %gRESET%w|%rCHANGE %y<ff_scale> %wChanges friendly fire scale."
|
||||
}
|
74
sources/NiceGameType.uc
Normal file
74
sources/NiceGameType.uc
Normal file
@ -0,0 +1,74 @@
|
||||
// made to fix KFStoryGameInfo loading for KFO maps
|
||||
class NiceGameType extends ScrnGameType;
|
||||
var NicePack NicePackMutator;
|
||||
function RegisterMutator(NicePack activePack){
|
||||
NicePackMutator = activePack;
|
||||
}
|
||||
function OverrideMonsterHealth(KFMonster M){}
|
||||
/*event InitGame(string Options, out string Error){
|
||||
local int i, j;
|
||||
if(ScrnGameLength == none)
ScrnGameLength = new(none, string(KFGameLength)) class'ScrnGameLength';
|
||||
for(i = 0;i < ScrnGameLength.
|
||||
}*/
|
||||
function int SpawnSquad(ZombieVolume ZVol, out array< class<KFMonster> > Squad, optional bool bLogSpawned ){
|
||||
local int i, j;
|
||||
local array<NicePack.ZedRecord> zedDatabase;
|
||||
if(NicePackMutator != none){
zedDatabase = NicePackMutator.zedDatabase;
for(i = 0;i < zedDatabase.Length;i ++){
for(j = 0;j < Squad.Length;j ++){
if(zedDatabase[i].bNeedsReplacement && zedDatabase[i].ZedType == Squad[j])
Squad[j] = zeddatabase[i].MeanZedType;
}
}
|
||||
}
|
||||
return super.SpawnSquad(ZVol, Squad, bLogSpawned);
|
||||
}
|
||||
function SetupWave(){
|
||||
Super.SetupWave();
|
||||
// Event call
|
||||
NicePackMutator.WaveStart();
|
||||
}
|
||||
function RestartPlayer(Controller aPlayer){
|
||||
Super.RestartPlayer(aPlayer);
|
||||
if(aPlayer.Pawn != none && NicePlayerController(aPlayer) != none)
NicePlayerController(aPlayer).PawnSpawned();
|
||||
}
|
||||
State MatchInProgress{
|
||||
function BeginState(){
Super(Invasion).BeginState();
|
||||
WaveNum = InitialWave;
InvasionGameReplicationInfo(GameReplicationInfo).WaveNumber = WaveNum;
|
||||
if(NicePackMutator.bInitialTrader)
WaveCountDown = NicePackMutator.initialTraderTime + 5;
else
WaveCountDown = 10;
|
||||
SetupPickups();
if(ScrnGameLength != none && !ScrnGameLength.LoadWave(WaveNum))
DoWaveEnd();
|
||||
// Event call
NicePackMutator.MatchBegan();
|
||||
}
|
||||
function DoWaveEnd(){
Super.DoWaveEnd();
// Event call
NicePackMutator.TraderStart();
|
||||
}
|
||||
function StartWaveBoss(){
Super.StartWaveBoss();
// Event call
NicePackMutator.WaveStart();
|
||||
}
|
||||
}
|
||||
function DramaticEvent(float BaseZedTimePossibility, optional float DesiredZedTimeDuration){
|
||||
local bool bWasZedTime;
|
||||
bWasZedTime = bZEDTimeActive;
|
||||
Super.DramaticEvent(BaseZedTimePossibility, DesiredZedTimeDuration);
|
||||
// Call event
|
||||
if(!bWasZedTime && bZEDTimeActive)
NicePackMutator.ZedTimeActivated();
|
||||
}
|
||||
event Tick(float DeltaTime){
|
||||
local float TrueTimeFactor;
|
||||
local Controller C;
|
||||
if(bZEDTimeActive){
TrueTimeFactor = 1.1 / Level.TimeDilation;
CurrentZEDTimeDuration -= DeltaTime * TrueTimeFactor;
if(CurrentZEDTimeDuration < (ZEDTimeDuration*0.166) && CurrentZEDTimeDuration > 0 ){
if(!bSpeedingBackUp){
bSpeedingBackUp = true;
|
||||
for(C = Level.ControllerList;C != none;C = C.NextController){
if(KFPlayerController(C)!= none)
KFPlayerController(C).ClientExitZedTime();
}
}
SetGameSpeed(Lerp( (CurrentZEDTimeDuration/(ZEDTimeDuration*0.166)), 1.0, 0.2 ));
}
if(CurrentZEDTimeDuration <= 0){
if(bZEDTimeActive)
NicePackMutator.ZedTimeDeactivated();
bZEDTimeActive = false;
bSpeedingBackUp = false;
SetGameSpeed(1.0);
ZedTimeExtensionsUsed = 0;
}
|
||||
}
|
||||
}
|
||||
function Killed(Controller Killer, Controller Killed, Pawn KilledPawn, class<DamageType> dmgType){
|
||||
local GameRules rules;
|
||||
local ScrnGameRules scrnRules;
|
||||
local KFSteamStatsAndAchievements StatsAndAchievements;
|
||||
Super.Killed(Killer, Killed, KilledPawn, dmgType);
|
||||
if(PlayerController(Killer) != none){
if(NiceMonster(KilledPawn) != none && Killed != Killer){
StatsAndAchievements = KFSteamStatsAndAchievements(PlayerController(Killer).SteamStatsAndAchievements);
if(StatsAndAchievements != none){
if(KilledPawn.IsA('NiceZombieStalker') || KilledPawn.IsA('MeanZombieStalker')){
if(class<NiceDamTypeWinchester>(dmgType) != none)
StatsAndAchievements.AddStalkerKillWithLAR();
}
else if(KilledPawn.IsA('NiceZombieClot') || KilledPawn.IsA('MeanZombieClot')){
if(class<NiceDamTypeWinchester>(dmgType) != none)
KFSteamStatsAndAchievements(PlayerController(Killer).SteamStatsAndAchievements).AddClotKillWithLAR();
}
if(class<NiceWeaponDamageType>(dmgType) != none){
for(rules = Level.Game.GameRulesModifiers;rules != none;rules = rules.NextGameRules)
if(ScrnGameRules(rules) != none){
scrnRules = ScrnGameRules(rules);
break;
}
if(scrnRules != none)
class<NiceWeaponDamageType>(dmgType).Static.AwardNiceKill(StatsAndAchievements, KFPlayerController(Killer), KFMonster(KilledPawn), scrnRules.HardcoreLevel);
}
}
}
|
||||
}
|
||||
}
|
||||
// Reloaded to award damage
|
||||
function int ReduceDamage(int Damage, pawn injured, pawn instigatedBy, vector HitLocation, out vector Momentum, class<DamageType> DamageType){
|
||||
local NiceMonster niceZed;
|
||||
local KFPlayerController PC;
|
||||
niceZed = NiceMonster(Injured);
|
||||
if(niceZed != none){
if(instigatedBy != none){
PC = KFPlayerController(instigatedBy.Controller);
if(class<NiceWeaponDamageType>(damageType) != none && PC != none)
class<NiceWeaponDamageType>(damageType).Static.AwardNiceDamage(KFSteamStatsAndAchievements(PC.SteamStatsAndAchievements), Clamp(Damage, 1, Injured.Health), niceZed.scrnRules.HardcoreLevel);
}
|
||||
}
|
||||
return Super.ReduceDamage(Damage, injured, InstigatedBy, HitLocation, Momentum, DamageType);
|
||||
}
|
||||
defaultproperties
|
||||
{
GameName="Nice Floor"
Description="Nice Edition of ScrN Killing Floor game mode (ScrnGameType)."
|
||||
}
|
837
sources/NiceHumanPawn.uc
Normal file
837
sources/NiceHumanPawn.uc
Normal file
@ -0,0 +1,837 @@
|
||||
class NiceHumanPawn extends ScrnHumanPawn
|
||||
dependson(NiceWeapon);
|
||||
var bool bReactiveArmorUsed;
|
||||
var float maniacTimeout;
|
||||
var float stationaryTime;
|
||||
var float forcedZedTimeCountDown;
|
||||
var bool bGotFreeJacket;
|
||||
var float lastHMGShieldUpdateTime;
|
||||
var int hmgShieldLevel;
|
||||
var ScrnHUD scrnHUDInstance;
|
||||
// Position value means it's a count down for how much invincibility is left,
|
||||
// Negative value is for counting down a cool-down after a failed head-shot with a melee weapon
|
||||
var float invincibilityTimer;
|
||||
var int safeMeleeMisses;
|
||||
var float ffScale;
|
||||
var float medicAdrenaliteTime;
|
||||
var float regenTime;
|
||||
var bool bZedTimeInvincible;
|
||||
enum ECalibrationState{
|
||||
// Calibration isn't available due to lack of ability
|
||||
CALSTATE_NOABILITY,
|
||||
CALSTATE_ACTIVE,
|
||||
CALSTATE_FINISHED
|
||||
};
|
||||
var float gunslingerTimer;
|
||||
var ECalibrationState currentCalibrationState;
|
||||
var int calibrationScore;
|
||||
var int calibrationHits, calibrationTotalShots;
|
||||
var float calibrationRemainingTime;
|
||||
var array<NiceMonster> calibrateUsedZeds;
|
||||
var int nicePrevPerkLevel;
|
||||
var class<NiceVeterancyTypes> nicePrevPerkClass;
|
||||
struct WeaponTimePair{
|
||||
var NiceWeapon niceWeap;
|
||||
var float reloadTime;
|
||||
};
|
||||
var array<WeaponTimePair> holsteredReloadList;
|
||||
var float holsteredReloadCountDown;
|
||||
var const float defaultInvincibilityDuration;
|
||||
struct InvincExtentions{
|
||||
var NiceMonster zed;
|
||||
var bool hadMiss;
|
||||
var int extentionsDone;
|
||||
};
|
||||
var array<InvincExtentions> zedInvExtList;
|
||||
var int headshotStack;
|
||||
replication{
|
||||
reliable if(Role == ROLE_Authority)
|
||||
headshotStack, hmgShieldLevel, forcedZedTimeCountDown, maniacTimeout, invincibilityTimer, safeMeleeMisses, ffScale,
|
||||
currentCalibrationState, calibrationScore, gunslingerTimer;
|
||||
reliable if(Role == ROLE_Authority)
|
||||
ClientChangeWeapon;
|
||||
reliable if(Role < ROLE_AUTHORITY)
|
||||
ServerUpdateCalibration, ServerCooldownAbility;
|
||||
}
|
||||
simulated function bool IsZedExtentionsRecorded(NiceMonster niceZed){
|
||||
local int i;
|
||||
for(i = 0;i < zedInvExtList.length;i ++)
|
||||
if(zedInvExtList[i].zed == niceZed)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
function ReplaceRequiredEquipment(){
|
||||
Super.ReplaceRequiredEquipment();
|
||||
RequiredEquipment[0] = String(class'ScrnBalanceSrv.ScrnKnife');//String(class'NicePack.NiceKnife');
|
||||
RequiredEquipment[1] = String(class'NicePack.NiceWinchester');//String(class'NicePack.Nice9mmPlus');
|
||||
RequiredEquipment[2] = String(class'ScrnBalanceSrv.ScrnFrag');
|
||||
RequiredEquipment[3] = String(class'ScrnBalanceSrv.ScrnSyringe');
|
||||
RequiredEquipment[4] = String(class'KFMod.Welder');
|
||||
}
|
||||
simulated function int CalculateCalibrationScore(){
|
||||
local float accuracy;
|
||||
accuracy = (float(calibrationHits)) / (float(calibrationTotalShots));
|
||||
// Very low accuracy (<60%) or not enough shots (<2) - 1 star
|
||||
if(calibrationTotalShots < 2 || accuracy < 0.6)
|
||||
return 1;
|
||||
// Here we definitely have at least 60% accuracy and 2 shots.
|
||||
// Low accuracy (<80%) or not enough shots (<5) - 2 stars.
|
||||
if(calibrationTotalShots < 5 || accuracy < 0.8)
|
||||
return 2;
|
||||
// Here we definitely have at least 80% accuracy and 5 shots.
|
||||
// If amount of shots is below 7 - it's 3 stars at most.
|
||||
if(calibrationTotalShots < 7)
|
||||
return 3;
|
||||
// Here we definitely have at least 80% accuracy and 7 shots.
|
||||
// Unless accuracy is 100% and player made 10 shots - it's 4 stars.
|
||||
if(accuracy < 1.0 || calibrationTotalShots < 10)
|
||||
return 4;
|
||||
// Here we definitely have 100% accuracy and at least 10 shots.
|
||||
// 5 stars.
|
||||
return 5;
|
||||
}
|
||||
function ServerUpdateCalibration(bool isHit, NiceMonster targetMonster){
|
||||
local int i;
|
||||
if(isHit){
|
||||
for(i = 0;i < calibrateUsedZeds.length;i ++)
|
||||
if(calibrateUsedZeds[i] == targetMonster)
|
||||
return;
|
||||
calibrationHits += 1;
|
||||
}
|
||||
calibrationTotalShots += 1;
|
||||
calibrateUsedZeds[calibrateUsedZeds.length] = targetMonster;
|
||||
}
|
||||
simulated function int GetZedExtentionsIndex(NiceMonster niceZed){
|
||||
local int i;
|
||||
local int foundIndex;
|
||||
local InvincExtentions newRecord;
|
||||
local array<InvincExtentions> newList;
|
||||
if(niceZed == none || niceZed.health <= 0)
|
||||
return -1;
|
||||
foundIndex = -1;
|
||||
for(i = 0;i < zedInvExtList.Length;i ++)
|
||||
if(zedInvExtList[i].zed != none && zedInvExtList[i].zed.health > 0){
|
||||
newList[newList.Length] = zedInvExtList[i];
|
||||
if(zedInvExtList[i].zed == niceZed)
|
||||
foundIndex = newList.Length - 1;
|
||||
}
|
||||
if(foundIndex < 0){
|
||||
foundIndex = newList.Length;
|
||||
newRecord.zed = niceZed;
|
||||
newList[foundIndex] = newRecord;
|
||||
}
|
||||
zedInvExtList = newList;
|
||||
return foundIndex;
|
||||
}
|
||||
simulated function bool TryExtendingInv(NiceMonster niceZed,
|
||||
bool meleeAttempt, bool wasHeadshot){
|
||||
local class<NiceVeterancyTypes> niceVet;
|
||||
local int zedExtIndex;
|
||||
local bool success;
|
||||
if(niceZed == none) return false;
|
||||
niceVet = class'NiceVeterancyTypes'.static.
|
||||
GetVeterancy(PlayerReplicationInfo);
|
||||
if(niceVet == none)
|
||||
return false;
|
||||
zedExtIndex = GetZedExtentionsIndex(niceZed);
|
||||
if(zedExtIndex >= 0 && !wasHeadshot)
|
||||
zedInvExtList[zedExtIndex].hadMiss = true;
|
||||
if(zedExtIndex >= 0){
|
||||
success = zedInvExtList[zedExtIndex].extentionsDone
|
||||
<= niceVet.static.GetInvincibilityExtentions(KFPRI);
|
||||
success = success && !zedInvExtList[zedExtIndex].hadMiss;
|
||||
}
|
||||
else
|
||||
success = wasHeadshot;
|
||||
if(invincibilityTimer < 0)
|
||||
success = false;
|
||||
if(success){
|
||||
if(zedExtIndex >= 0)
|
||||
zedInvExtList[zedExtIndex].extentionsDone ++;
|
||||
invincibilityTimer = niceVet.static.GetInvincibilityDuration(KFPRI);
|
||||
safeMeleeMisses = niceVet.static.GetInvincibilitySafeMisses(KFPRI);
|
||||
return true;
|
||||
}
|
||||
if(wasHeadshot)
|
||||
return false;
|
||||
if(meleeAttempt){
|
||||
safeMeleeMisses --;
|
||||
if(safeMeleeMisses < 0)
|
||||
ResetMeleeInvincibility();
|
||||
return false;
|
||||
}
|
||||
if(niceVet.static.hasSkill( NicePlayerController(controller),
|
||||
class'NiceSkillZerkGunzerker')){
|
||||
invincibilityTimer = class'NiceSkillZerkGunzerker'.default.cooldown;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
simulated function int FindInHolsteredList(NiceWeapon niceWeap){
|
||||
local int i;
|
||||
for(i = 0;i < holsteredReloadList.Length;i ++)
|
||||
if(holsteredReloadList[i].niceWeap == niceWeap)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
simulated function ProgressHeadshotStack(bool bIncrease, int minStack, int maxStack, int maxSoftLimit){
|
||||
if(bIncrease && headshotStack < maxStack)
|
||||
headshotStack ++;
|
||||
if(!bIncrease && headshotStack > minStack){
|
||||
if(headshotStack > maxSoftLimit)
|
||||
headshotStack = maxSoftLimit;
|
||||
else
|
||||
headshotStack --;
|
||||
}
|
||||
headshotStack = Max(minStack, headshotStack);
|
||||
headshotStack = Min(maxStack, headshotStack);
|
||||
}
|
||||
simulated function int GetHeadshotStack(int minStack, int maxStack){
|
||||
headshotStack = Max(minStack, headshotStack);
|
||||
headshotStack = Min(maxStack, headshotStack);
|
||||
return headshotStack;
|
||||
}
|
||||
simulated function int GetTimeDilationStage(float dilation){
|
||||
if(dilation <= 0.1)
|
||||
return 0;
|
||||
else if(dilation < 1.1)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
simulated function ResetMeleeInvincibility(){
|
||||
invincibilityTimer = 0.0;
|
||||
safeMeleeMisses = 0;
|
||||
ApplyWeaponStats(weapon);
|
||||
}
|
||||
function ServerCooldownAbility(string abilityID){
|
||||
local int index;
|
||||
local NicePlayerController nicePlayer;
|
||||
nicePlayer = NicePlayerController(controller);
|
||||
if(nicePlayer == none || nicePlayer.abilityManager == none)
|
||||
return;
|
||||
index = nicePlayer.abilityManager.GetAbilityIndex(abilityID);
|
||||
if(index >= 0)
|
||||
nicePlayer.abilityManager.SetAbilityState(index, ASTATE_COOLDOWN);
|
||||
}
|
||||
simulated function Tick(float deltaTime){
|
||||
local int index;
|
||||
local Inventory Item;
|
||||
local NiceWeapon niceWeap;
|
||||
local WeaponTimePair newPair;
|
||||
local array<WeaponTimePair> newWTPList;
|
||||
local NicePack niceMutator;
|
||||
local NicePlayerController nicePlayer;
|
||||
nicePlayer = NicePlayerController(Controller);
|
||||
if(Role == Role_AUTHORITY){
|
||||
// Calibration
|
||||
if( currentCalibrationState == CALSTATE_ACTIVE
|
||||
&& calibrationRemainingTime > 0.0){
|
||||
calibrationScore = CalculateCalibrationScore();
|
||||
calibrationRemainingTime -= deltaTime;
|
||||
if(calibrationRemainingTime <= 0 || calibrationScore == 5){
|
||||
currentCalibrationState = CALSTATE_FINISHED;
|
||||
calibrateUsedZeds.length = 0;
|
||||
if(nicePlayer != none && nicePlayer.abilityManager != none)
|
||||
nicePlayer.abilityManager.SetAbilityState(0, ASTATE_COOLDOWN);
|
||||
}
|
||||
}
|
||||
// Gunslinger
|
||||
if( gunslingerTimer > 0
|
||||
&& nicePlayer != none && nicePlayer.abilityManager != none){
|
||||
gunslingerTimer -= deltaTime;
|
||||
if(gunslingerTimer <= 0)
|
||||
nicePlayer.abilityManager.SetAbilityState(1, ASTATE_COOLDOWN);
|
||||
}
|
||||
// Regen
|
||||
if(class'NiceVeterancyTypes'.static.hasSkill(NicePlayerController(Controller), class'NiceSkillMedicRegeneration')){
|
||||
if(health < healthMax)
|
||||
regenTime += deltaTime;
|
||||
while(regenTime > class'NiceSkillMedicRegeneration'.default.regenFrequency){
|
||||
if(health < healthMax)
|
||||
health += 1;
|
||||
else
|
||||
regenTime = 0.0;
|
||||
regenTime -= class'NiceSkillMedicRegeneration'.default.regenFrequency;
|
||||
}
|
||||
}
|
||||
// Update adrenaline
|
||||
medicAdrenaliteTime -= deltaTime;
|
||||
// This needs updating
|
||||
if(Level.Game != none)
|
||||
ffScale = TeamGame(Level.Game).FriendlyFireScale;
|
||||
else
|
||||
ffScale = 0;
|
||||
// Manage melee-invincibility
|
||||
if(invincibilityTimer < 0){
|
||||
invincibilityTimer += deltaTime;
|
||||
if(invincibilityTimer > 0)
|
||||
ResetMeleeInvincibility();
|
||||
}
|
||||
if(invincibilityTimer > 0){
|
||||
invincibilityTimer -= deltaTime;
|
||||
if(invincibilityTimer < 0)
|
||||
ResetMeleeInvincibility();
|
||||
}
|
||||
// Manage demo's 'Maniac' skill
|
||||
maniacTimeout -= deltaTime;
|
||||
}
|
||||
super.Tick(deltaTime);
|
||||
// Restore icons
|
||||
if(Role < Role_AUTHORITY){
|
||||
if(scrnHUDInstance == none && nicePlayer != none)
|
||||
scrnHUDInstance = ScrnHUD(nicePlayer.myHUD);
|
||||
if(scrnHUDInstance != none && NiceWeapon(weapon) == none){
|
||||
scrnHUDInstance.ClipsIcon.WidgetTexture = Texture'KillingFloorHUD.HUD.Hud_Ammo_Clip';
|
||||
scrnHUDInstance.BulletsInClipIcon.WidgetTexture = Texture'KillingFloorHUD.HUD.Hud_Bullets';
|
||||
scrnHUDInstance.SecondaryClipsIcon.WidgetTexture = Texture'KillingFloor2HUD.HUD.Hud_M79';
|
||||
}
|
||||
}
|
||||
// Update stationary time
|
||||
if(bIsCrouched && VSize(Velocity) <= 0.0)
|
||||
stationaryTime += deltaTime;
|
||||
else
|
||||
stationaryTime = 0.0;
|
||||
// Update zed countdown time
|
||||
if(forcedZedTimeCountDown > 0)
|
||||
forcedZedTimeCountDown -= deltaTime;
|
||||
else
|
||||
forcedZedTimeCountDown = 0.0;
|
||||
niceMutator = class'NicePack'.static.Myself(Level);
|
||||
if(niceMutator != none)
|
||||
niceMutator.ClearWeapProgress();
|
||||
if(!class'NiceVeterancyTypes'.static.hasSkill(NicePlayerController(Controller), class'NiceSkillEnforcerMultitasker'))
|
||||
return;
|
||||
if(Role < ROLE_Authority && nicePlayer != none && nicePlayer.bFlagDisplayWeaponProgress){
|
||||
// Update weapon progress for this skill
|
||||
if(niceMutator == none)
|
||||
return;
|
||||
for(Item = Inventory; Item != none; Item = Item.Inventory){
|
||||
niceWeap = NiceWeapon(Item);
|
||||
if(niceWeap != none && niceWeap != weapon && !niceWeap.IsMagazineFull()){
|
||||
niceMutator.AddWeapProgress(niceWeap.class, niceWeap.holsteredCompletition,
|
||||
true, niceWeap.GetMagazineAmmo());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Auto-reload holstered weapons
|
||||
holsteredReloadCountDown -= deltaTime;
|
||||
if(holsteredReloadCountDown <= 0.0){
|
||||
// Progress current list
|
||||
for(Item = Inventory; Item != none; Item = Item.Inventory){
|
||||
niceWeap = NiceWeapon(Item);
|
||||
if(niceWeap == none || niceWeap == weapon || niceWeap.IsMagazineFull())
|
||||
continue;
|
||||
index = FindInHolsteredList(niceWeap);
|
||||
if(index >= 0){
|
||||
// Detract time
|
||||
holsteredReloadList[index].reloadTime -=
|
||||
0.25 / class'NiceSkillEnforcerMultitasker'.default.reloadSlowDown;
|
||||
// Add ammo if time is up
|
||||
if(holsteredReloadList[index].reloadTime < 0.0)
|
||||
niceWeap.ClientReloadAmmo();
|
||||
}
|
||||
}
|
||||
// Make new list
|
||||
for(Item = Inventory; Item != none; Item = Item.Inventory){
|
||||
niceWeap = NiceWeapon(Item);
|
||||
if(niceWeap == none)
|
||||
continue;
|
||||
// Reset holstered completion timer
|
||||
if(niceWeap == weapon || niceWeap.IsMagazineFull()){
|
||||
niceWeap.holsteredCompletition = 0.0;
|
||||
continue;
|
||||
}
|
||||
// Update list
|
||||
index = FindInHolsteredList(niceWeap);
|
||||
if(index < 0 || holsteredReloadList[index].reloadTime <= 0.0){
|
||||
newPair.niceWeap = niceWeap;
|
||||
newPair.reloadTime = niceWeap.TimeUntillReload();
|
||||
newWTPList[newWTPList.Length] = newPair;
|
||||
}
|
||||
else
|
||||
newWTPList[newWTPList.Length] = holsteredReloadList[index];
|
||||
// Update holstered completion timer
|
||||
niceWeap.holsteredCompletition = newWTPList[newWTPList.Length - 1].reloadTime / niceWeap.TimeUntillReload();
|
||||
niceWeap.holsteredCompletition = 1.0 - niceWeap.holsteredCompletition;
|
||||
}
|
||||
holsteredReloadList = newWTPList;
|
||||
holsteredReloadCountDown = 0.25;
|
||||
}
|
||||
}
|
||||
/*function ServerBuyWeapon(class<Weapon> WClass, float ItemWeight){
|
||||
local Inventory I;
|
||||
local NiceSingle nicePistol;
|
||||
local class<NiceWeaponPickup> WP;
|
||||
local float Price, Weight, SellValue;
|
||||
nicePistol = NiceSingle(FindInventoryType(WClass));
|
||||
if(nicePistol != none && nicePistol.class != WClass)
|
||||
nicePistol = none;
|
||||
if((nicePistol != none && nicePistol.bIsDual))
|
||||
return;
|
||||
if(nicePistol == none)
|
||||
super.ServerBuyWeapon(WClass, ItemWeight);
|
||||
else{
|
||||
if(!CanBuyNow() || class<NiceWeapon>(WClass) == none)
|
||||
return;
|
||||
WP = class<NiceWeaponPickup>(WClass.Default.PickupClass);
|
||||
if(WP == none)
|
||||
return;
|
||||
if(PerkLink == none)
|
||||
PerkLink = FindStats();
|
||||
if(PerkLink != none && !PerkLink.CanBuyPickup(WP))
|
||||
return;
|
||||
Price = WP.Default.Cost;
|
||||
if(KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none){
|
||||
Price *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), WP);
|
||||
if(class'ScrnBalance'.default.Mut.bBuyPerkedWeaponsOnly
|
||||
&& WP.default.CorrespondingPerkIndex != 7
|
||||
&& WP.default.CorrespondingPerkIndex != KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.default.PerkIndex )
|
||||
return;
|
||||
}
|
||||
SellValue = Price * 0.75;
|
||||
Price = int(Price);
|
||||
Weight = Class<KFWeapon>(WClass).default.Weight;
|
||||
if(nicePistol.default.DualClass != none)
|
||||
Weight = nicePistol.default.DualClass.default.Weight - Weight;
|
||||
if((Weight > 0 && !CanCarry(Weight)) || PlayerReplicationInfo.Score < Price)
|
||||
return;
|
||||
I = Spawn(WClass, self);
|
||||
if(I != none){
|
||||
if(KFGameType(Level.Game) != none)
|
||||
KFGameType(Level.Game).WeaponSpawned(I);
|
||||
KFWeapon(I).UpdateMagCapacity(PlayerReplicationInfo);
|
||||
KFWeapon(I).SellValue = SellValue;
|
||||
I.GiveTo(self);
|
||||
PlayerReplicationInfo.Score -= Price;
|
||||
UsedStartCash(Price);
|
||||
}
|
||||
else
|
||||
ClientMessage("Error: Weapon failed to spawn.");
|
||||
SetTraderUpdate();
|
||||
}
|
||||
}
|
||||
function ServerSellWeapon(class<Weapon> WClass){
|
||||
local NiceSingle nicePistol;
|
||||
local NiceDualies niceDual;
|
||||
nicePistol = NiceSingle(FindInventoryType(WClass));
|
||||
niceDual = NiceDualies(FindInventoryType(WClass));
|
||||
if(niceDual != none && niceDual.class != WClass)
|
||||
niceDual = none;
|
||||
if(niceDual == none){
|
||||
// If this a single pistol that is part of dual pistol weapon - double the cost, because it will be cut back by parent 'ServerSellWeapon'
|
||||
if(nicePistol != none && nicePistol.bIsDual)
|
||||
nicePistol.SellValue *= 2;
|
||||
super.ServerSellWeapon(WClass);
|
||||
}
|
||||
else{
|
||||
nicePistol = niceDual.ServerSwitchToSingle();
|
||||
if(nicePistol == none)
|
||||
return;
|
||||
else{
|
||||
nicePistol.RemoveDual(CurrentWeight);
|
||||
nicePistol.SellValue *= 0.5;
|
||||
PlayerReplicationInfo.Score += nicePistol.SellValue;
|
||||
SetTraderUpdate();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
// NICETODO: do we even need this one?
|
||||
simulated function ClientChangeWeapon(NiceWeapon newWeap){
|
||||
weapon = newWeap;
|
||||
PendingWeapon = newWeap;
|
||||
if(newWeap != none){
|
||||
newWeap.ClientState = WS_Hidden;
|
||||
ChangedWeapon();
|
||||
}
|
||||
PendingWeapon = none;
|
||||
}
|
||||
|
||||
// Validate that client is not hacking.
|
||||
function bool CanBuyNow(){
|
||||
local NicePlayerController niceController;
|
||||
niceController = NicePlayerController(Controller);
|
||||
if(niceController == none)
|
||||
return false;
|
||||
if(NiceGameType(Level.Game) != none && NiceGameType(Level.Game).NicePackMutator != none
|
||||
&& NiceGameType(Level.Game).NicePackMutator.bIsPreGame)
|
||||
return true;
|
||||
if(NiceTSCGame(Level.Game) != none && NiceTSCGame(Level.Game).NicePackMutator != none
|
||||
&& NiceTSCGame(Level.Game).NicePackMutator.bIsPreGame)
|
||||
return true;
|
||||
return Super.CanBuyNow();
|
||||
}
|
||||
// Overridden to not modify dual pistols' weapon group
|
||||
function bool AddInventory(inventory NewItem){
|
||||
local KFWeapon weap;
|
||||
local bool GroupChanged;
|
||||
weap = KFWeapon(NewItem);
|
||||
if(weap != none){
|
||||
if(Dualies(weap) != none){
|
||||
if((DualDeagle(weap) != none || Dual44Magnum(weap) != none || DualMK23Pistol(weap) != none)
|
||||
&& weap.InventoryGroup != 4 ) {
|
||||
if(KFPRI != none &&
|
||||
ClassIsChildOf(KFPRI.ClientVeteranSkill, class'ScrnBalanceSrv.ScrnVetGunslinger'))
|
||||
weap.InventoryGroup = 3;
|
||||
else
|
||||
weap.InventoryGroup = 2;
|
||||
GroupChanged = true;
|
||||
}
|
||||
}
|
||||
else if(weap.class == class'Single'){
|
||||
weap.bKFNeverThrow = false;
|
||||
}
|
||||
weap.bIsTier3Weapon = true;
|
||||
}
|
||||
if(GroupChanged)
|
||||
ClientSetInventoryGroup(NewItem.class, NewItem.InventoryGroup);
|
||||
if(super(SRHumanPawn).AddInventory(NewItem)){
|
||||
if(weap != none && weap.bTorchEnabled)
|
||||
AddToFlashlightArray(weap.class);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
simulated function CookGrenade(){
|
||||
local ScrnFrag aFrag;
|
||||
local NiceWeapon niceWeap;
|
||||
niceWeap = NiceWeapon(Weapon);
|
||||
if(niceWeap != none)
|
||||
niceWeap.ClientForceInterruptReload(CANCEL_COOKEDNADE);
|
||||
if(secondaryItem != none)
|
||||
return;
|
||||
if(scrnPerk == none || !scrnPerk.static.CanCookNade(KFPRI, Weapon))
|
||||
return;
|
||||
aFrag = ScrnFrag(FindPlayerGrenade());
|
||||
if(aFrag == none)
|
||||
return;
|
||||
if( !aFrag.HasAmmo() || bThrowingNade
|
||||
|| aFrag.bCooking || aFrag.bThrowingCooked
|
||||
|| level.timeSeconds - aFrag.cookExplodeTimer <= 0.1)
|
||||
return;
|
||||
if( niceWeap == none
|
||||
|| (niceWeap.bIsReloading && !niceWeap.InterruptReload()))
|
||||
return;
|
||||
aFrag.CookNade();
|
||||
niceWeap.ClientGrenadeState = GN_TempDown;
|
||||
niceWeap.PutDown();
|
||||
}
|
||||
simulated function ThrowGrenade(){
|
||||
local NiceWeapon niceWeap;
|
||||
niceWeap = NiceWeapon(Weapon);
|
||||
if(niceWeap != none)
|
||||
niceWeap.ClientForceInterruptReload(CANCEL_NADE);
|
||||
if(bThrowingNade || SecondaryItem != none)
|
||||
return;
|
||||
if( niceWeap == none
|
||||
|| (niceWeap.bIsReloading && !niceWeap.InterruptReload()))
|
||||
return;
|
||||
if(playerGrenade == none)
|
||||
playerGrenade = FindPlayerGrenade();
|
||||
if(playerGrenade != none && playerGrenade.HasAmmo()){
|
||||
niceWeap.clientGrenadeState = GN_TempDown;
|
||||
niceWeap.PutDown();
|
||||
}
|
||||
}
|
||||
simulated function HandleNadeThrowAnim()
|
||||
{
|
||||
if(NiceWinchester(Weapon) != none)
|
||||
SetAnimAction('Frag_Winchester');
|
||||
/*if(NiceM14EBRBattleRifle(Weapon) != none || NiceMaulerRifle(Weapon) != none)
|
||||
SetAnimAction('Frag_M14');
|
||||
else
|
||||
else if(Crossbow(Weapon) != none)
|
||||
SetAnimAction('Frag_Crossbow');
|
||||
else if(NiceM99SniperRifle(Weapon) != none)
|
||||
SetAnimAction('Frag_M4203');//MEANTODO
|
||||
else if(NiceAK47AssaultRifle(Weapon) != none)
|
||||
SetAnimAction('Frag_AK47');
|
||||
else if(NiceBullpup(Weapon) != none || NiceNailGun(Weapon) != none)
|
||||
SetAnimAction('Frag_Bullpup');
|
||||
else if(NiceBoomStick(Weapon) != none)
|
||||
SetAnimAction('Frag_HuntingShotgun');
|
||||
else if(NiceShotgun(Weapon) != none || NiceBenelliShotgun(Weapon) != none || NiceTrenchgun(Weapon) != none)
|
||||
SetAnimAction('Frag_Shotgun');
|
||||
else if(NiceSCARMK17AssaultRifle(Weapon) != none)
|
||||
SetAnimAction('Frag_SCAR');
|
||||
else if(NiceAA12AutoShotgun(Weapon) != none || NiceFNFAL_ACOG_AssaultRifle(Weapon) != none || NiceSPAutoShotgun(Weapon) != none)
|
||||
SetAnimAction('Frag_AA12');
|
||||
else if(NiceM4AssaultRifle(Weapon) != none || NiceMKb42AssaultRifle(Weapon) != none)
|
||||
SetAnimAction('Frag_M4');
|
||||
else if(NiceThompsonDrumSMG(Weapon) != none)
|
||||
SetAnimAction('Frag_IJC_spThompson_Drum');*/
|
||||
Super.HandleNadeThrowAnim();
|
||||
}
|
||||
// Remove blur for sharpshooter with a right skill
|
||||
function bool ShouldBlur(){
|
||||
local class<NiceVeterancyTypes> niceVet;
|
||||
niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(PlayerReplicationInfo);
|
||||
if(niceVet != none && niceVet.static.hasSkill(NicePlayerController(Controller), class'NiceSkillEnforcerUnshakable'))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
simulated function AddBlur(Float BlurDuration, float Intensity){
|
||||
if(shouldBlur())
|
||||
Super.AddBlur(BlurDuration, Intensity);
|
||||
}
|
||||
simulated exec function ToggleFlashlight(){
|
||||
local NiceWeapon niceWeap;
|
||||
niceWeap = NiceWeapon(Weapon);
|
||||
if(niceWeap != none && niceWeap.bUseFlashlightToToggle)
|
||||
niceWeap.SecondDoToggle();
|
||||
}
|
||||
simulated function ApplyWeaponStats(Weapon NewWeapon){
|
||||
local KFWeapon Weap;
|
||||
local float weaponWeight;
|
||||
local class<NiceVeterancyTypes> niceVet;
|
||||
BaseMeleeIncrease = default.BaseMeleeIncrease;
|
||||
InventorySpeedModifier = 0;
|
||||
Weap = KFWeapon(NewWeapon);
|
||||
SetAmmoStatus();
|
||||
if(KFPRI != none && Weap != none){
|
||||
Weap.bIsTier3Weapon = Weap.default.bIsTier3Weapon;
|
||||
if(Weap.bSpeedMeUp){
|
||||
if(KFPRI.ClientVeteranSkill != none)
|
||||
BaseMeleeIncrease += KFPRI.ClientVeteranSkill.Static.GetMeleeMovementSpeedModifier(KFPRI);
|
||||
InventorySpeedModifier = (default.GroundSpeed * BaseMeleeIncrease);
|
||||
}
|
||||
if ( ScrnPerk != none ) {
|
||||
InventorySpeedModifier +=
|
||||
default.GroundSpeed * ScrnPerk.static.GetWeaponMovementSpeedBonus(KFPRI, NewWeapon);
|
||||
}
|
||||
// Mod speed depending on current weapon's weight
|
||||
niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(PlayerReplicationInfo);
|
||||
if(niceVet != none)
|
||||
weaponWeight = niceVet.static.GetPerceivedWeight(KFPlayerReplicationInfo(PlayerReplicationInfo), Weap);
|
||||
else
|
||||
weaponWeight = Weap.weight;
|
||||
InventorySpeedModifier += default.GroundSpeed * (8 - weaponWeight) * 0.025;
|
||||
// ScrN Armor can slow down players (or even boost) -- PooSH
|
||||
InventorySpeedModifier -= default.GroundSpeed * GetCurrentVestClass().default.SpeedModifier;
|
||||
}
|
||||
}
|
||||
simulated function ModifyVelocity(float DeltaTime, vector OldVelocity){
|
||||
local NicePack NicePackMutator;
|
||||
local NicePlayerController nicePlayer;
|
||||
local float MovementMod;
|
||||
local float WeightMod, HealthMod, TempMod;
|
||||
local float EncumbrancePercentage;
|
||||
local Inventory Inv;
|
||||
local KF_StoryInventoryItem StoryInv;
|
||||
local bool bAllowSlowDown;
|
||||
local float adrSpeedBonus;
|
||||
bAllowSlowDown = true;
|
||||
nicePlayer = NicePlayerController(Controller);
|
||||
if(class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillEnforcerUnstoppable'))
|
||||
bAllowSlowDown = false;
|
||||
super(KFPawn).ModifyVelocity(DeltaTime, OldVelocity);
|
||||
if(Controller != none)
|
||||
{
|
||||
// Calculate encumbrance, but cap it to the maxcarryweight so when we use dev weapon cheats we don't move mega slow
|
||||
EncumbrancePercentage = (FMin(CurrentWeight, MaxCarryWeight) / default.MaxCarryWeight); //changed MaxCarryWeight to default.MaxCarryWeight
|
||||
// Calculate the weight modifier to speed
|
||||
WeightMod = (1.0 - (EncumbrancePercentage * WeightSpeedModifier));
|
||||
// Calculate the health modifier to speed
|
||||
HealthMod = ((Health/HealthMax) * HealthSpeedModifier) + (1.0 - HealthSpeedModifier);
|
||||
|
||||
// Apply all the modifiers
|
||||
GroundSpeed = default.GroundSpeed;
|
||||
MovementMod = 1.0;
|
||||
if(bAllowSlowDown || HealthMod > 1.0)
|
||||
MovementMod *= HealthMod;
|
||||
if(bAllowSlowDown || WeightMod > 1.0)
|
||||
MovementMod *= WeightMod;
|
||||
|
||||
if(KFPRI != none && KFPRI.ClientVeteranSkill != none){
|
||||
MovementMod *= KFPRI.ClientVeteranSkill.static.GetMovementSpeedModifier(KFPRI, KFGameReplicationInfo(Level.GRI));
|
||||
}
|
||||
|
||||
for(Inv = Inventory;Inv != none;Inv = Inv.Inventory){
|
||||
TempMod = Inv.GetMovementModifierFor(self);
|
||||
if(bAllowSlowDown || TempMod > 1.0)
|
||||
MovementMod *= TempMod;
|
||||
|
||||
StoryInv = KF_StoryInventoryItem(Inv);
|
||||
if(StoryInv != none && StoryInv.bUseForcedGroundSpeed)
|
||||
{
|
||||
GroundSpeed = StoryInv.ForcedGroundSpeed;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(bTraderSpeedBoost && !KFGameReplicationInfo(Level.GRI).bWaveInProgress)
|
||||
MovementMod *= TraderSpeedBoost;
|
||||
if(Health < HealthMax && medicAdrenaliteTime > 0){
|
||||
// Calulate boos from adrenaline
|
||||
adrSpeedBonus = Health * (1 - class'NiceSkillMedicAdrenalineShot'.default.speedBoost) +
|
||||
(100 * class'NiceSkillMedicAdrenalineShot'.default.speedBoost - class'NiceSkillMedicAdrenalineShot'.default.minHealth);
|
||||
adrSpeedBonus /= (100 - class'NiceSkillMedicAdrenalineShot'.default.minHealth);
|
||||
adrSpeedBonus = FMin(adrSpeedBonus, class'NiceSkillMedicAdrenalineShot'.default.speedBoost);
|
||||
adrSpeedBonus = FMax(adrSpeedBonus, 1.0);
|
||||
MovementMod *= adrSpeedBonus;
|
||||
}
|
||||
GroundSpeed = default.GroundSpeed * MovementMod;
|
||||
AccelRate = default.AccelRate * MovementMod;
|
||||
if(bAllowSlowDown || InventorySpeedModifier > 0)
|
||||
GroundSpeed += InventorySpeedModifier;
|
||||
if(nicePlayer != none && nicePlayer.IsZedTimeActive() && class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillZerkZEDAccelerate'))
|
||||
AccelRate *= 100;
|
||||
}
|
||||
NicePackMutator = class'NicePack'.static.Myself(Level);
|
||||
if(NicePackMutator != none && NicePackMutator.bIsPreGame && NicePackMutator.bInitialTrader && NicePackMutator.bStillDuringInitTrader)
|
||||
GroundSpeed = 1;
|
||||
}
|
||||
function getFreeJacket(){
|
||||
if(!bGotFreeJacket && ShieldStrength < LightVestClass.default.ShieldCapacity && class'NiceVeterancyTypes'.static.SomeoneHasSkill(NicePlayerController(Controller), class'NiceSkillSupportArmory')){
|
||||
if(SetVestClass(LightVestClass)){
|
||||
ShieldStrength = LightVestClass.default.ShieldCapacity;
|
||||
bGotFreeJacket = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
simulated function TakeDamage(int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex){
|
||||
local int needArmor;
|
||||
local int healAmount;
|
||||
local float healPotency;
|
||||
local bool bOldArmorStops;
|
||||
local float adrResistance;
|
||||
local NicePlayerController nicePlayer;
|
||||
ApplyWeaponStats(Weapon);
|
||||
if(invincibilityTimer > 0)
|
||||
return;
|
||||
nicePlayer = NicePlayerController(Controller);
|
||||
if(bZedTimeInvincible){
|
||||
if(nicePlayer != none && nicePlayer.IsZedTimeActive())
|
||||
return;
|
||||
else
|
||||
bZedTimeInvincible = false;
|
||||
}
|
||||
// Adrenaline damage decrease
|
||||
if(medicAdrenaliteTime > 0){
|
||||
adrResistance = Health * (1 - class'NiceSkillMedicAdrenalineShot'.default.resistBoost) +
|
||||
(100 * class'NiceSkillMedicAdrenalineShot'.default.resistBoost - class'NiceSkillMedicAdrenalineShot'.default.minHealth);
|
||||
adrResistance /= (100 - class'NiceSkillMedicAdrenalineShot'.default.minHealth);
|
||||
adrResistance = FMin(adrResistance, class'NiceSkillMedicAdrenalineShot'.default.resistBoost);
|
||||
adrResistance = FMax(adrResistance, 1.0);
|
||||
Damage *= adrResistance;
|
||||
}
|
||||
if(nicePlayer != none && nicePlayer.IsZedTimeActive()
|
||||
&& class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillZerkZEDUnbreakable'))
|
||||
return;
|
||||
if(hmgShieldLevel > 0 && class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillEnforcerFullCounter')){
|
||||
if(Damage < 20 && InstigatedBy.default.HealthMax < 1500){
|
||||
Damage *= class'NiceSkillEnforcerFullCounter'.default.damageReduction;
|
||||
hmgShieldLevel --;
|
||||
}
|
||||
else{
|
||||
if(hmgShieldLevel == class'NiceSkillEnforcerFullCounter'.default.layersAmount)
|
||||
Damage *= class'NiceSkillEnforcerFullCounter'.default.damageReduction * float(hmgShieldLevel) /
|
||||
float(class'NiceSkillEnforcerFullCounter'.default.layersAmount);
|
||||
hmgShieldLevel = 0;
|
||||
}
|
||||
}
|
||||
lastHMGShieldUpdateTime = Level.TimeSeconds;
|
||||
if(damageType != none && class<NiceDamTypeDrug>(damageType) == none){
|
||||
bOldArmorStops = damageType.default.bArmorStops;
|
||||
if(class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillHeavyCoating'))
|
||||
damageType.default.bArmorStops = true;
|
||||
}
|
||||
lastExplosionDistance = 0.0; // hack, but scrn fucks with usotherwise
|
||||
super.TakeDamage(Damage, InstigatedBy, hitLocation, Momentum, damageType, HitIndex);
|
||||
// Commando's zed time
|
||||
if( forcedZedTimeCountDown <= 0.0
|
||||
&& health < class'NiceSkillCommandoCriticalFocus'.default.healthBoundary && KFGameType(Level.Game) != none
|
||||
&& class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillCommandoCriticalFocus') ){
|
||||
KFGameType(Level.Game).DramaticEvent(1.0);
|
||||
forcedZedTimeCountDown = class'NiceSkillCommandoCriticalFocus'.default.cooldown;
|
||||
}
|
||||
if(damageType != none)
|
||||
damageType.default.bArmorStops = bOldArmorStops;
|
||||
// Do heavy mg's armor healing
|
||||
if(class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillHeavySafeguard') && health < HealthMax * 0.5 && ShieldStrength > 0){
|
||||
healAmount = HealthMax - health;
|
||||
healPotency = 1.0;
|
||||
if(health < HealthMax * 0.25)
|
||||
healPotency = 2.0;
|
||||
else if(health < HealthMax * 0.1)
|
||||
healPotency = 10.0;
|
||||
needArmor = float(healAmount) * healPotency * class'NiceSkillHeavySafeguard'.default.healingCost;
|
||||
ShieldStrength -= needArmor;
|
||||
if(ShieldStrength < 0)
|
||||
ShieldStrength = 0;
|
||||
health += HealAmount * 0.5;
|
||||
TakeHealing(self, HealAmount * 0.5, HealPotency);
|
||||
}
|
||||
if(ShieldStrength <= 0)
|
||||
getFreeJacket();
|
||||
}
|
||||
function int ShieldAbsorb(int damage){
|
||||
if(ShieldStrength > 0 && class'NiceVeterancyTypes'.static.HasSkill(NicePlayerController(Controller), class'NiceSkillHeavySafeguard'))
|
||||
return damage;
|
||||
return super.ShieldAbsorb(damage);
|
||||
}
|
||||
function Timer(){
|
||||
if(BurnDown > 0 && BurnInstigator != self && KFPawn(BurnInstigator) != none)
|
||||
LastBurnDamage *= 1.8;
|
||||
super(SRHumanPawn).Timer();
|
||||
// tick down health if it's greater than max
|
||||
if(Health > HealthMax){
|
||||
if(Health > 100)
|
||||
Health -= 5;
|
||||
if(Health < HealthMax)
|
||||
Health = HealthMax;
|
||||
}
|
||||
SetAmmoStatus();
|
||||
ApplyWeaponFlashlight(true);
|
||||
// Regenerate HMG's full counter shield
|
||||
if(hmgShieldLevel < class'NiceSkillEnforcerFullCounter'.default.layersAmount && Level.TimeSeconds - lastHMGShieldUpdateTime > class'NiceSkillEnforcerFullCounter'.default.coolDown){
|
||||
lastHMGShieldUpdateTime = Level.TimeSeconds;
|
||||
hmgShieldLevel ++;
|
||||
}
|
||||
}
|
||||
/*simulated function Fire(optional float F){
|
||||
local bool bRecManualReload;
|
||||
local NiceSingle singleWeap;
|
||||
local ScrnPlayerController PC;
|
||||
singleWeap = NiceSingle(weapon);
|
||||
PC = ScrnPlayerController(Controller);
|
||||
if(PC != none && singleWeap != none && singleWeap.bIsDual && singleWeap.otherMagazine > 0){
|
||||
bRecManualReload = PC.bManualReload;
|
||||
PC.bManualReload = false;
|
||||
super.Fire(F);
|
||||
PC.bManualReload = bRecManualReload;
|
||||
}
|
||||
else
|
||||
super.Fire(F);
|
||||
}*/
|
||||
function float AssessThreatTo(KFMonsterController Monster, optional bool CheckDistance){
|
||||
return super(SRHumanPawn).AssessThreatTo(Monster, CheckDistance);
|
||||
}
|
||||
function VeterancyChanged(){
|
||||
local NicePlayerController nicePlayer;
|
||||
if(KFPRI == none)
|
||||
return;
|
||||
nicePlayer = NicePlayerController(Controller);
|
||||
nicePrevPerkLevel = KFPRI.ClientVeteranSkillLevel;
|
||||
nicePrevPerkClass = class<NiceVeterancyTypes>(KFPRI.ClientVeteranSkill);
|
||||
if(nicePlayer != none && nicePlayer.abilityManager != none)
|
||||
nicePlayer.abilityManager.ClearAbilities();
|
||||
if(nicePrevPerkClass != none && Role == Role_AUTHORITY)
|
||||
nicePrevPerkClass.static.SetupAbilities(KFPRI);
|
||||
if(nicePlayer != none){
|
||||
nicePlayer.TriggerSelectEventOnPerkChange(nicePrevPerkClass,
|
||||
class<NiceVeterancyTypes>(KFPRI.ClientVeteranSkill));
|
||||
}
|
||||
|
||||
super.VeterancyChanged();
|
||||
}
|
||||
/*simulated function AltFire(optional float F){
|
||||
if(NiceMedicGun(Weapon) != none)
|
||||
super(SRHumanPawn).AltFire(F);
|
||||
else
|
||||
super.AltFire(F);
|
||||
}*/
|
||||
defaultproperties
|
||||
{
|
||||
defaultInvincibilityDuration=2.000000
|
||||
BaseMeleeIncrease=0.000000
|
||||
}
|
1099
sources/NicePack.uc
Normal file
1099
sources/NicePack.uc
Normal file
File diff suppressed because it is too large
Load Diff
126
sources/NicePathBuilder.uc
Normal file
126
sources/NicePathBuilder.uc
Normal file
@ -0,0 +1,126 @@
|
||||
//==============================================================================
|
||||
// NicePack / NicePathBuilder
|
||||
//==============================================================================
|
||||
// - Class that allows to build string representation of paths like:
|
||||
// "/home/dk", "/Weapons/M14Ebr/StateMachine", "Store/Weapons[7].ID"
|
||||
// that are used in various places in this mutator.
|
||||
// - Reserved symbol that can't be used in names provided by user: '/'.
|
||||
// - Works by appending new elements to the end of already existed path
|
||||
// like a stack, making it possible to either remove elements from the end
|
||||
// or flush and clear the whole accumulated path.
|
||||
// - Designed to support flow-syntax allowing user to build paths like follows:
|
||||
// path.AddElement("").AddElement("home").AddElement("dk").ToString()
|
||||
// => "/home/dk/"
|
||||
// path.AddElement("Store").AddElement("Weapons").AddElement("")
|
||||
// .ToString()
|
||||
// => "Store/Weapons/"
|
||||
// - Element names can be empty:
|
||||
// /folder//another/
|
||||
// above contains following names (in order): "folder", "", "another", "".
|
||||
// - Can parse preexistent path from string,
|
||||
// which may lead to a failed state in case of incorrect formatting.
|
||||
//==============================================================================
|
||||
// Class hierarchy: Object > NicePathBuilder
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NicePathBuilder extends Object;
|
||||
|
||||
// 'true' if path is in an invalid state, meaning no operations except
|
||||
// 'Flush' and 'Parse' (that completely clear current path)
|
||||
// can be performed.
|
||||
var protected bool _isInvalid;
|
||||
// Elements of currently built path.
|
||||
var protected array<string> currentPath;
|
||||
|
||||
// Constants that store reserved symbols.
|
||||
var const string resElementSeparator;
|
||||
|
||||
// Checks if path is currently empty.
|
||||
// Invalid path isn't considered empty.
|
||||
function bool IsEmpty(){
|
||||
if(IsInvalid())
|
||||
return false;
|
||||
return (currentPath.length <= 0);
|
||||
}
|
||||
|
||||
function bool IsInvalid(){
|
||||
return _isInvalid;
|
||||
}
|
||||
|
||||
// Forcefully enters this path into an invalid state.
|
||||
function NicePathBuilder Fail(){
|
||||
_isInvalid = true;
|
||||
return self;
|
||||
}
|
||||
|
||||
// Checks if passed name valid, i.e. doesn't contain any reserved characters.
|
||||
function bool IsNameValid(string nameToCheck){
|
||||
if(InStr(nameToCheck, resElementSeparator) >= 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 'AddElement(<elementName>)' effectively adds '/<elementName>' to the path.
|
||||
// ~ If given name contains reserved characters - path will become invalid.
|
||||
function NicePathBuilder AddElement(string elementName){
|
||||
if(IsInvalid()) return self;
|
||||
if(!IsNameValid(elementName)) return Fail();
|
||||
currentPath[currentPath.length] = elementName;
|
||||
return self;
|
||||
}
|
||||
|
||||
// Returns string representation of this path.
|
||||
// Returns empty string if path is invalid or empty.
|
||||
function string ToString(){
|
||||
local int i;
|
||||
local string accumulator;
|
||||
if(IsInvalid()) return "";
|
||||
if(IsEmpty()) return "";
|
||||
accumulator = currentPath[0];
|
||||
for(i = 1;i < currentPath.length;i ++)
|
||||
accumulator = accumulator $ resElementSeparator $ currentPath[i];
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
// Removes several last elements.
|
||||
function NicePathBuilder RemoveMany(int howMuchToRemove){
|
||||
local int newLength;
|
||||
if(IsInvalid()) return self;
|
||||
newLength = currentPath.length - howMuchToRemove;
|
||||
if(newLength < 0)
|
||||
newLength = 0;
|
||||
currentPath.length = newLength;
|
||||
return self;
|
||||
}
|
||||
|
||||
// Removes last element, identical to 'RemoveMany(1)'.
|
||||
function NicePathBuilder RemoveLast(){
|
||||
return RemoveMany(1);
|
||||
}
|
||||
|
||||
// Returns array of elements in the current path.
|
||||
function array<string> GetElements(){
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
// Clears current path and resets absolute path flag to 'false'.
|
||||
function NicePathBuilder Flush(){
|
||||
currentPath.length = 0;
|
||||
_isInvalid = false;
|
||||
return self;
|
||||
}
|
||||
|
||||
function NicePathBuilder Parse(string toParse){
|
||||
Flush();
|
||||
Split(toParse, resElementSeparator, currentPath);
|
||||
return self;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
resElementSeparator="/"
|
||||
}
|
1474
sources/NicePlayerController.uc
Normal file
1474
sources/NicePlayerController.uc
Normal file
File diff suppressed because it is too large
Load Diff
12
sources/NiceRandomItemSpawn.uc
Normal file
12
sources/NiceRandomItemSpawn.uc
Normal file
@ -0,0 +1,12 @@
|
||||
class NiceRandomItemSpawn extends ScrnRandomItemSpawn;
|
||||
defaultproperties
|
||||
{
|
||||
PickupClasses(0)=Class'NicePack.NiceWinchesterPickup'
|
||||
/*PickupClasses(0)=Class'NicePack.Nice9mmPlusPickup'
|
||||
PickupClasses(1)=Class'NicePack.NiceShotgunPickup'
|
||||
PickupClasses(2)=Class'NicePack.NiceBullpupPickup'
|
||||
PickupClasses(3)=Class'NicePack.NiceMagnumPickup'
|
||||
PickupClasses(4)=Class'NicePack.NiceWinchesterPickup'
|
||||
PickupClasses(5)=Class'NicePack.NiceM79Pickup'
|
||||
PickupClasses(8)=Class'NicePack.NiceMAC10Pickup'*/
|
||||
}
|
459
sources/NiceReplicationInfo.uc
Normal file
459
sources/NiceReplicationInfo.uc
Normal file
@ -0,0 +1,459 @@
|
||||
//==============================================================================
|
||||
// NicePack / NiceReplicationInfo
|
||||
//==============================================================================
|
||||
// Manages sending messages from clients to server.
|
||||
//==============================================================================
|
||||
// 'Nice pack' source
|
||||
// Do whatever the fuck you want with it
|
||||
// Author: dkanus
|
||||
// E-mail: dkanus@gmail.com
|
||||
//==============================================================================
|
||||
class NiceReplicationInfo extends ReplicationInfo
|
||||
dependson(NiceBullet);
|
||||
var NicePack Mut;
|
||||
replication{
|
||||
reliable if(Role < ROLE_Authority)
|
||||
ServerDamagePawn, ServerDealDamage, ServerDealMeleeDamage,
|
||||
ServerUpdateHit, ServerExplode, ServerJunkieExtension,
|
||||
/*ServerStickProjectile*/ServerHealTarget;
|
||||
}
|
||||
// Makes server to spawn a sticked projectile.
|
||||
/*simulated function ServerStickProjectile
|
||||
(
|
||||
KFHumanPawn instigator,
|
||||
Actor base,
|
||||
name bone,
|
||||
Vector shift,
|
||||
Rotator direction,
|
||||
NiceBullet.ExplosionData expData
|
||||
){
|
||||
class'NiceProjectileSpawner'.static.
|
||||
StickProjectile(instigator, base, bone, shift, direction, expData);
|
||||
}*/
|
||||
// Returns scale value that determines how to scale explosion damage to
|
||||
// given victim.
|
||||
// Method assumes that a valid victim was passed.
|
||||
simulated function float GetDamageScale(Actor victim, Vector explosionLocation,
|
||||
Vector victimPoint,
|
||||
float explRadius, float explExp){
|
||||
local Vector dirToVictim;
|
||||
local float scale;
|
||||
local float distToVictim;
|
||||
local KFPawn victimKFPawn;
|
||||
local KFMonster victimMonster;
|
||||
dirToVictim = victimPoint - explosionLocation;
|
||||
distToVictim = FMax(1.0, VSize(dirToVictim));
|
||||
scale = 1 - FMax(0.0, (distToVictim - victim.collisionRadius) / explRadius);
|
||||
if(scale <= 0)
|
||||
scale = 0;
|
||||
else
|
||||
scale = scale ** explExp;
|
||||
// Try scaling for exposure level (only available to monsters and KFPawns)
|
||||
victimKFPawn = KFPawn(victim);
|
||||
victimMonster = KFMonster(victim);
|
||||
if(victimKFPawn != none && victimKFPawn.health <= 0)
|
||||
scale *= victimKFPawn.GetExposureTo(explosionLocation);
|
||||
else if(victimMonster != none && victimMonster.health <= 0)
|
||||
scale *= victimMonster.GetExposureTo(explosionLocation);
|
||||
return scale;
|
||||
}
|
||||
// Returns scale values that determine how to scale explosion damage to
|
||||
// given victim.
|
||||
// There's two scale values due to how kf1 calculated explosion damage:
|
||||
// by scaling it according to distance to two different points
|
||||
// (location of the victim and a point 75% of collision height higher).
|
||||
// First scale will be the one with the highest number.
|
||||
// Method assumes that a valid victim was passed.
|
||||
simulated function CalculateDamageScales( out float scale1, out float scale2,
|
||||
Actor victim,
|
||||
Vector explosionLocation,
|
||||
float explRadius, float explExp){
|
||||
local Vector victimPoint1, victimPoint2;
|
||||
local float swap;
|
||||
victimPoint1 = victim.location;
|
||||
victimPoint2 = victim.location;
|
||||
victimPoint2.z += victim.CollisionHeight * 0.75;
|
||||
scale1 = GetDamageScale(victim, explosionLocation, victimPoint1,
|
||||
explRadius, explExp);
|
||||
scale2 = GetDamageScale(victim, explosionLocation, victimPoint2,
|
||||
explRadius, explExp);
|
||||
if(scale1 < scale2){
|
||||
swap = scale1;
|
||||
scale1 = scale2;
|
||||
scale2 = swap;
|
||||
}
|
||||
}
|
||||
// Simulates an explosion on a server.
|
||||
simulated function ServerExplode
|
||||
(
|
||||
float explDamage,
|
||||
float explRadius,
|
||||
float explExp,
|
||||
class<NiceWeaponDamageType> explDmgType,
|
||||
float momentum,
|
||||
Vector explLocation,
|
||||
Pawn instigator,
|
||||
optional bool allowDoubleExplosion,
|
||||
optional Actor explosionTarget,
|
||||
optional vector explosiveDirection
|
||||
){
|
||||
local Actor victim;
|
||||
local int numKilled;
|
||||
local Vector dirToVictim;
|
||||
local Vector hitLocation;
|
||||
local float scale1, scale2;
|
||||
if(Role < ROLE_Authority) return;
|
||||
foreach CollidingActors(class'Actor', victim, explRadius, explLocation){
|
||||
if(victim == none || victim == self) continue;
|
||||
if(victim.role < ROLE_Authority) continue;
|
||||
if(ExtendedZCollision(victim) != none) continue;
|
||||
if(Trigger(victim) != none) continue;
|
||||
dirToVictim = Normal(victim.location - explLocation);
|
||||
hitLocation = victim.location - 0.5 *
|
||||
(victim.collisionHeight + victim.collisionRadius) * dirToVictim;
|
||||
CalculateDamageScales( scale1, scale2,
|
||||
victim, explLocation, explRadius, explExp);
|
||||
// Deal main damage
|
||||
if(scale1 > 0){
|
||||
ServerDealDamage( victim, explDamage * scale1, instigator,
|
||||
hitLocation, scale1 * momentum * dirToVictim,
|
||||
explDmgType);
|
||||
}
|
||||
// Deal secondary damage
|
||||
if(allowDoubleExplosion && victim != none && scale2 > 0){
|
||||
ServerDealDamage( victim, explDamage * scale2, instigator,
|
||||
hitLocation, scale2 * momentum * dirToVictim,
|
||||
explDmgType);
|
||||
}
|
||||
if(NiceMonster(victim) != none && NiceMonster(victim).health <= 0)
|
||||
numKilled ++;
|
||||
}
|
||||
if(numKilled >= 4)
|
||||
KFGameType(level.game).DramaticEvent(0.05);
|
||||
else if(numKilled >= 2)
|
||||
KFGameType(level.game).DramaticEvent(0.03);
|
||||
}
|
||||
simulated function ServerDamagePawn
|
||||
(
|
||||
KFPawn injured,
|
||||
int damage,
|
||||
Pawn instigatedBy,
|
||||
Vector hitLocation,
|
||||
Vector momentum,
|
||||
Class<DamageType> damageType,
|
||||
int hitPoint
|
||||
){
|
||||
local array<int> hitPoints;
|
||||
if(injured == none) return;
|
||||
hitPoints[0] = hitPoint;
|
||||
injured.ProcessLocationalDamage(damage, instigatedBy, hitLocation, momentum,
|
||||
damageType, hitPoints);
|
||||
}
|
||||
simulated function HandleNiceHealingMechanicsAndSkills
|
||||
(
|
||||
NiceHumanPawn healer,
|
||||
NiceHumanPawn healed,
|
||||
float healPotency
|
||||
){
|
||||
local bool hasZEDHeavenCanceller;
|
||||
local NicePlayerController nicePlayer;
|
||||
if(healer == none || healed == none) return;
|
||||
nicePlayer = NicePlayerController(healer.controller);
|
||||
if(nicePlayer == none)
|
||||
return;
|
||||
if(class'NiceVeterancyTypes'.static.
|
||||
hasSkill(nicePlayer, class'NiceSkillMedicAdrenalineShot')){
|
||||
healed.medicAdrenaliteTime =
|
||||
class'NiceSkillMedicAdrenalineShot'.default.boostTime;
|
||||
}
|
||||
if(class'NiceVeterancyTypes'.static.
|
||||
hasSkill(nicePlayer, class'NiceSkillMedicSymbioticHealth')){
|
||||
healer.TakeHealing(
|
||||
healer,
|
||||
healer.healthMax *
|
||||
class'NiceSkillMedicSymbioticHealth'.default.selfBoost,
|
||||
healPotency,
|
||||
KFWeapon(healer.weapon));
|
||||
}
|
||||
hasZEDHeavenCanceller = class'NiceVeterancyTypes'.static.
|
||||
hasSkill(nicePlayer, class'NiceSkillMedicZEDHeavenCanceller');
|
||||
if(nicePlayer.IsZedTimeActive() && hasZEDHeavenCanceller){
|
||||
healed.health = healed.healthMax;
|
||||
healed.bZedTimeInvincible = true;
|
||||
}
|
||||
}
|
||||
simulated function RemovePoisonAndBleed(NiceHumanPawn healed){
|
||||
local Inventory I;
|
||||
local MeanReplicationInfo MRI;
|
||||
// No bleeding
|
||||
MRI = class'MeanReplicationInfo'.static.
|
||||
findSZri(healed.PlayerReplicationInfo);
|
||||
if(MRI != none)
|
||||
MRI.stopBleeding();
|
||||
// No poison
|
||||
if(healed.inventory == none) return;
|
||||
for(I = healed.inventory; I != none; I = I.inventory){
|
||||
if(MeanPoisonInventory(I) != none)
|
||||
I.Destroy();
|
||||
}
|
||||
}
|
||||
// Tells server to heal given human pawn.
|
||||
simulated function ServerHealTarget(NiceHumanPawn healed, float charPotency,
|
||||
Pawn instigator){
|
||||
local NiceHumanPawn healer;
|
||||
local KFPlayerReplicationInfo KFPRI;
|
||||
local float healTotal;
|
||||
local float healPotency;
|
||||
if(instigator == none || healed == none) return;
|
||||
if(healed.health <= 0 || healed.health >= healed.healthMax) return;
|
||||
KFPRI = KFPlayerReplicationInfo(instigator.PlayerReplicationInfo);
|
||||
if(KFPRI == none || KFPRI.ClientVeteranSkill == none)
|
||||
return;
|
||||
healer = NiceHumanPawn(instigator);
|
||||
if(healer == none)
|
||||
return;
|
||||
healPotency = KFPRI.ClientVeteranSkill.static.GetHealPotency(KFPRI);
|
||||
healTotal = charPotency * healPotency;
|
||||
|
||||
healer.AlphaAmount = 255;
|
||||
/* if(NiceMedicGun(healer.weapon) != none)
|
||||
NiceMedicGun(healer.weapon).ClientSuccessfulHeal(healer, healed);
|
||||
if(healed.health >= healed.healthMax){
|
||||
healed.GiveHealth(healTotal, healed.healthMax);
|
||||
return;
|
||||
}*/
|
||||
HandleNiceHealingMechanicsAndSkills(healer, healed, healPotency);
|
||||
if(healed.health < healed.healthMax){
|
||||
healed.TakeHealing( healed, healTotal, healPotency,
|
||||
KFWeapon(instigator.weapon));
|
||||
}
|
||||
RemovePoisonAndBleed(healed);
|
||||
}
|
||||
simulated function HandleNiceDamageMechanicsAndSkills
|
||||
(
|
||||
NiceMonster niceZed,
|
||||
out int damage,
|
||||
NiceHumanPawn nicePawn,
|
||||
out Vector hitLocation,
|
||||
out Vector momentum,
|
||||
class<NiceWeaponDamageType> damageType,
|
||||
out float headshotLevel,
|
||||
out float lockonTime
|
||||
){
|
||||
local bool hasZEDFrenzy;
|
||||
local bool hasTranquilizer;
|
||||
local bool hasVorpalBlade;
|
||||
local NiceMonsterController zedController;
|
||||
local NicePlayerController nicePlayer;
|
||||
if(niceZed == none) return;
|
||||
if(nicePawn == none) return;
|
||||
nicePlayer = NicePlayerController(nicePawn.controller);
|
||||
if(nicePlayer == none)
|
||||
return;
|
||||
// Medic's skills
|
||||
if(class<NiceDamTypeMedicDart>(damageType) != none){
|
||||
hasTranquilizer = class'NiceVeterancyTypes'.static.
|
||||
hasSkill(nicePlayer, class'NiceSkillMedicTranquilizer');
|
||||
hasZEDFrenzy = class'NiceVeterancyTypes'.static.
|
||||
hasSkill(nicePlayer, class'NiceSkillMedicZEDFrenzy');
|
||||
// Medic's suppression
|
||||
if(hasTranquilizer)
|
||||
niceZed.mind = FMin(niceZed.mind, 0.5);
|
||||
// Medic's frenzy
|
||||
if(hasZEDFrenzy && nicePlayer.IsZedTimeActive()){
|
||||
niceZed.madnessCountDown =
|
||||
class'NiceSkillMedicZEDFrenzy'.default.madnessTime;
|
||||
zedController = NiceMonsterController(niceZed.controller);
|
||||
if(zedController != none)
|
||||
zedController.FindNewEnemy();
|
||||
}
|
||||
}
|
||||
// Zerker's skills
|
||||
if(class<niceDamageTypeVetBerserker>(DamageType) != none){
|
||||
hasVorpalBlade = class'NiceVeterancyTypes'.static.
|
||||
HasSkill(nicePlayer, class'NiceSkillZerkVorpalBlade');
|
||||
if( hasVorpalBlade && headshotLevel > 0.0
|
||||
&& !nicePawn.IsZedExtentionsRecorded(niceZed))
|
||||
damage *= class'NiceSkillZerkVorpalBlade'.default.damageBonus;
|
||||
}
|
||||
}
|
||||
simulated function UpdateMeleeInvincibility
|
||||
(
|
||||
NiceMonster niceZed,
|
||||
int damage,
|
||||
NiceHumanPawn nicePawn,
|
||||
Vector hitLocation,
|
||||
Vector momentum,
|
||||
class<NiceWeaponDamageType> damageType,
|
||||
float headshotLevel,
|
||||
bool mainTarget
|
||||
){
|
||||
local bool hasGunzerker;
|
||||
local bool allowedInvincibility;
|
||||
if(nicePawn == none) return;
|
||||
if(niceZed == none) return;
|
||||
allowedInvincibility = class'NiceVeterancyTypes'.static.
|
||||
GetVeterancy(nicePawn.PlayerReplicationInfo) == class'NiceVetBerserker';
|
||||
allowedInvincibility = allowedInvincibility || niceZed.headHealth <= 0;
|
||||
if(!allowedInvincibility)
|
||||
return;
|
||||
// Handle non-melee cases (gunzerker-invincibility)
|
||||
hasGunzerker = class'NiceVeterancyTypes'.static.
|
||||
hasSkill( NicePlayerController(nicePawn.controller),
|
||||
class'NiceSkillZerkGunzerker');
|
||||
if(hasGunzerker && class<niceDamageTypeVetBerserker>(damageType) == none)
|
||||
nicePawn.TryExtendingInv(niceZed, false, headshotLevel > 0.0);
|
||||
// Handle melee-cases
|
||||
if(mainTarget && class<niceDamageTypeVetBerserker>(damageType) != none)
|
||||
nicePawn.TryExtendingInv(niceZed, true, headshotLevel > 0.0);
|
||||
nicePawn.ApplyWeaponStats(nicePawn.weapon);
|
||||
}
|
||||
simulated function UpdateArdour(bool isKill, NicePlayerController nicePlayer){
|
||||
local bool hasArdour;
|
||||
local NiceHumanPawn nicePawn;
|
||||
local float cooldownChange;
|
||||
if(nicePlayer == none) return;
|
||||
if(nicePlayer.abilityManager == none) return;
|
||||
nicePawn = NiceHumanPawn(nicePlayer.pawn);
|
||||
if(nicePawn == none)
|
||||
return;
|
||||
hasArdour = class'NiceVeterancyTypes'.static.
|
||||
hasSkill( nicePlayer,
|
||||
class'NiceSkillSharpshooterArdour');
|
||||
if(!hasArdour)
|
||||
return;
|
||||
cooldownChange =
|
||||
class'NiceSkillSharpshooterArdour'.default.
|
||||
headshotKillReduction[nicePawn.calibrationScore - 1];
|
||||
if(!isKill){
|
||||
cooldownChange *=
|
||||
class'NiceSkillSharpshooterArdour'.default.justHeadshotReduction;
|
||||
}
|
||||
nicePlayer.abilityManager.AddToCooldown(1, -cooldownChange);
|
||||
}
|
||||
// Returns 'true' if before calling it zed was alive and had a head.
|
||||
simulated function bool ServerDealDamageBase
|
||||
(
|
||||
Actor other,
|
||||
int damage,
|
||||
Pawn instigatedBy,
|
||||
Vector hitLocation,
|
||||
Vector momentum,
|
||||
class<NiceWeaponDamageType> damageType,
|
||||
optional float headshotLevel,
|
||||
optional float lockonTime
|
||||
){
|
||||
local NiceMonster niceZed;
|
||||
local NiceHumanPawn nicePawn;
|
||||
local NicePlayerController nicePlayer;
|
||||
local bool zedWasAliveWithHead;
|
||||
if(other == none) return false;
|
||||
niceZed = NiceMonster(other);
|
||||
nicePawn = NiceHumanPawn(InstigatedBy);
|
||||
if(nicePawn != none)
|
||||
nicePlayer = NicePlayerController(nicePawn.Controller);
|
||||
if(niceZed == none || nicePlayer == none){
|
||||
other.TakeDamage( damage, instigatedBy,
|
||||
hitLocation, momentum, damageType);
|
||||
return false;
|
||||
}
|
||||
zedWasAliveWithHead = (niceZed.health > 0.0) && (niceZed.headHealth > 0.0);
|
||||
HandleNiceDamageMechanicsAndSkills( niceZed, damage, nicePawn,
|
||||
hitLocation, momentum, damageType,
|
||||
headshotLevel, lockonTime);
|
||||
niceZed.TakeDamageClient( damage, instigatedBy, hitLocation, momentum,
|
||||
damageType, headshotLevel, lockonTime);
|
||||
return zedWasAliveWithHead;
|
||||
}
|
||||
// Tells server to damage given pawn.
|
||||
simulated function ServerDealDamage
|
||||
(
|
||||
Actor other,
|
||||
int damage,
|
||||
Pawn instigatedBy,
|
||||
Vector hitLocation,
|
||||
Vector momentum,
|
||||
class<NiceWeaponDamageType> damageType,
|
||||
optional float headshotLevel,
|
||||
optional float lockonTime
|
||||
){
|
||||
local NiceMonster niceZed;
|
||||
local bool zedWasAliveWithHead;
|
||||
if(headshotLevel > 0)
|
||||
UpdateArdour(false, NicePlayerController(instigatedBy.controller));
|
||||
zedWasAliveWithHead = ServerDealDamageBase( other, damage, instigatedBy,
|
||||
hitLocation, momentum,
|
||||
damageType, headshotLevel,
|
||||
lockonTime);
|
||||
if(!zedWasAliveWithHead)
|
||||
return;
|
||||
niceZed = NiceMonster(other);
|
||||
if( niceZed != none
|
||||
&& (niceZed.health < 0 || niceZed.headHealth < 0))
|
||||
UpdateArdour(true, NicePlayerController(instigatedBy.controller));
|
||||
UpdateMeleeInvincibility( niceZed, damage,
|
||||
NiceHumanPawn(instigatedBy),
|
||||
hitLocation, momentum, damageType,
|
||||
headshotLevel, true);
|
||||
}
|
||||
// Tells server to damage given pawn with melee.
|
||||
// Difference with 'ServerDealDamage' is that this function passes data about
|
||||
// whether our target was 'main' target of melee swing
|
||||
// or was hit by AOE effect.
|
||||
simulated function ServerDealMeleeDamage
|
||||
(
|
||||
Actor other,
|
||||
int damage,
|
||||
Pawn instigatedBy,
|
||||
Vector hitLocation,
|
||||
Vector momentum,
|
||||
class<NiceWeaponDamageType> damageType,
|
||||
bool mainTarget,
|
||||
optional float headshotLevel
|
||||
){
|
||||
local bool zedWasAliveWithHead;
|
||||
zedWasAliveWithHead = ServerDealDamageBase( other, damage, instigatedBy,
|
||||
hitLocation, momentum,
|
||||
damageType, headshotLevel, 0.0);
|
||||
if(!zedWasAliveWithHead)
|
||||
return;
|
||||
UpdateMeleeInvincibility( NiceMonster(other), damage,
|
||||
NiceHumanPawn(instigatedBy),
|
||||
hitLocation, momentum, damageType,
|
||||
headshotLevel, mainTarget);
|
||||
}
|
||||
simulated function ServerUpdateHit
|
||||
(
|
||||
Actor tpActor,
|
||||
Actor hitActor,
|
||||
Vector clientHitLoc,
|
||||
Vector hitNormal,
|
||||
optional Vector hitLocDiff
|
||||
){
|
||||
local KFWeaponAttachment weapAttach;
|
||||
weapAttach = KFWeaponAttachment(tpActor);
|
||||
if(weapAttach != none)
|
||||
weapAttach.UpdateHit(hitActor, clientHitLoc + hitLocDiff, hitNormal);
|
||||
}
|
||||
simulated function ServerJunkieExtension( NicePlayerController player,
|
||||
bool isHeadshot){
|
||||
local NiceGameType niceGame;
|
||||
local class<NiceVeterancyTypes> niceVet;
|
||||
if(player == none || player.bJunkieExtFailed) return;
|
||||
niceGame = NiceGameType(player.Level.Game);
|
||||
if(niceGame == none || !niceGame.bZEDTimeActive)
|
||||
return;
|
||||
niceVet = class'NiceVeterancyTypes'.static.
|
||||
GetVeterancy(player.PlayerReplicationInfo);
|
||||
if(niceVet == none)
|
||||
return;
|
||||
if(niceVet.static.hasSkill(player, class'NiceSkillSharpshooterZEDAdrenaline')){
|
||||
if(!isHeadshot)
|
||||
player.bJunkieExtFailed = true;
|
||||
else if(Mut != none)
|
||||
Mut.JunkieZedTimeExtend();
|
||||
}
|
||||
}
|
||||
defaultproperties
|
||||
{
|
||||
}
|
79
sources/NiceRules.uc
Normal file
79
sources/NiceRules.uc
Normal file
@ -0,0 +1,79 @@
|
||||
class NiceRules extends GameRules;
|
||||
var ScrnGameRules ScrnRules;
|
||||
function PostBeginPlay(){
|
||||
if(Level.Game.GameRulesModifiers == none)
Level.Game.GameRulesModifiers = Self;
|
||||
else{
// We need to be the ones giving achievements first
Self.AddGameRules(Level.Game.GameRulesModifiers);
Level.Game.GameRulesModifiers = Self;
|
||||
}
|
||||
if(NicePack(Owner) != none)
ScrnRules = NicePack(Owner).ScrnMut.GameRules;
|
||||
else{
Log("Wrong owner! Owner must be NicePack!");
Destroy();
|
||||
}
|
||||
}
|
||||
function bool CheckEndGame(PlayerReplicationInfo Winner, string Reason){
|
||||
local bool bWin;
|
||||
local string MapName;
|
||||
if(Level.Game.IsInState('PendingMatch'))
return false;
|
||||
if(Level.Game.bGameEnded)
return true;
|
||||
if(NextGameRules != none && !NextGameRules.CheckEndGame(Winner,Reason))
return false;
|
||||
if(ScrnRules.Mut.bStoryMode)
bWin = Reason ~= "WinAction";
|
||||
else{
bWin = KFGameReplicationInfo(Level.GRI) != none && KFGameReplicationInfo(Level.GRI).EndGameType == 2;
|
||||
}
|
||||
if(bWin){
// Map achievements
MapName = ScrnRules.Mut.KF.GetCurrentMapName(Level);
ScrnRules.CheckMapAlias(MapName);
GiveMapAchievements(MapName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// We would never get ScrN Sui and Hoe achievs with our new zeds, so let's add them ourselves. For different reasons.
|
||||
function GiveMapAchievements(optional String MapName){
|
||||
local bool bCustomMap, bGiveHardAch, bGiveSuiAch, bGiveHoeAch, bNewAch;
|
||||
local ScrnPlayerInfo SPI;
|
||||
local ClientPerkRepLink PerkLink;
|
||||
local TeamInfo WinnerTeam;
|
||||
WinnerTeam = TeamInfo(Level.Game.GameReplicationInfo.Winner);
|
||||
if(ScrnRules.Mut.bStoryMode){
bGiveHardAch = Level.Game.GameDifficulty >= 4;
bGiveSuiAch = Level.Game.GameDifficulty >= 5;
bGiveHoeAch = Level.Game.GameDifficulty >= 7;
|
||||
}
|
||||
else{
bGiveHardAch = ScrnRules.HardcoreLevel >= 5;
bGiveSuiAch = ScrnRules.HardcoreLevel >= 10;
bGiveHoeAch = ScrnRules.HardcoreLevel >= 15;
|
||||
}
|
||||
for (SPI = ScrnRules.PlayerInfo;SPI != none;SPI = SPI.NextPlayerInfo){
if (SPI.PlayerOwner == none || SPI.PlayerOwner.PlayerReplicationInfo == none)
continue;
PerkLink = SPI.GetRep();
if(PerkLink == none)
continue;
if(WinnerTeam != none && SPI.PlayerOwner.PlayerReplicationInfo.Team != WinnerTeam)
continue; // no candies for loosers
// additional achievements that are granted only when surviving the game
if(ScrnPlayerController(SPI.PlayerOwner) != none && !ScrnPlayerController(SPI.PlayerOwner).bChangedPerkDuringGame)
SPI.ProgressAchievement('PerkFavorite', 1);
|
||||
//unlock "Normal" achievement and see if the map is found
bCustomMap = ScrnRules.MapAchClass.static.UnlockMapAchievement(PerkLink, MapName, 0) == -2;
bNewAch = false;
if(bCustomMap){
//map not found - progress custom map achievements
if(bGiveHardAch)
ScrnRules.AchClass.static.ProgressAchievementByID(PerkLink, 'WinCustomMapsHard', 1);
if(bGiveSuiAch)
ScrnRules.AchClass.static.ProgressAchievementByID(PerkLink, 'WinCustomMapsSui', 1);
if(bGiveHoeAch)
ScrnRules.AchClass.static.ProgressAchievementByID(PerkLink, 'WinCustomMapsHoE', 1);
ScrnRules.AchClass.static.ProgressAchievementByID(PerkLink, 'WinCustomMapsNormal', 1);
ScrnRules.AchClass.static.ProgressAchievementByID(PerkLink, 'WinCustomMaps', 1);
}
else{
//map found - give related achievements
if(bGiveHardAch)
ScrnRules.MapAchClass.static.UnlockMapAchievement(PerkLink, MapName, 1);
if(bGiveSuiAch)
ScrnRules.MapAchClass.static.UnlockMapAchievement(PerkLink, MapName, 2);
if(bGiveHoeAch)
ScrnRules.MapAchClass.static.UnlockMapAchievement(PerkLink, MapName, 3);
}
|
||||
}
|
||||
}
|
||||
function int NetDamage(int OriginalDamage, int Damage, pawn injured, pawn instigatedBy, vector HitLocation, out vector Momentum, class<DamageType> DamageType){
|
||||
local TeamGame TG;
|
||||
TG = TeamGame(Level.Game);
|
||||
if(KFPawn(injured) != none && TG != none && Damage > 0 && class<DamTypeEnemyBase>(DamageType) == none){
if((KFPawn(instigatedBy) != none || FakePlayerPawn(instigatedBy) != none) && (instigatedBy.PlayerReplicationInfo == none || instigatedBy.PlayerReplicationInfo.bOnlySpectator)){
Momentum = vect(0,0,0);
if(NoFF(injured, TG.FriendlyFireScale))
return 0;
else if(OriginalDamage == Damage)
return Damage * TG.FriendlyFireScale;
}
else if(instigatedBy == none && !DamageType.default.bCausedByWorld){
Momentum = vect(0,0,0);
if(NoFF(injured, TG.FriendlyFireScale))
return 0;
else if(OriginalDamage == Damage)
return Damage * TG.FriendlyFireScale;
}
|
||||
}
|
||||
return super.NetDamage(OriginalDamage, Damage, injured, instigatedBy, HitLocation, Momentum, DamageType);
|
||||
}
|
||||
function bool NoFF(Pawn injured, float FF){
|
||||
return (FF == 0.0 || (Vehicle(injured) != none && Vehicle(injured).bNoFriendlyFire));
|
||||
}
|
||||
function RaiseHardcoreLevel(float inc, string reason){
|
||||
local string s;
|
||||
local Controller P;
|
||||
local NicePlayerController nicePlayer;
|
||||
|
||||
if(ScrnRules.HardcoreLevelFloat < ScrnRules.HardcoreLevel)
ScrnRules.HardcoreLevelFloat = ScrnRules.HardcoreLevel;
|
||||
ScrnRules.HardcoreLevelFloat += inc;
|
||||
ScrnRules.HardcoreLevel = int(ScrnRules.HardcoreLevelFloat + 0.01);
|
||||
ScrnRules.Mut.HardcoreLevel = clamp(ScrnRules.HardcoreLevel, 0, 255);
|
||||
ScrnRules.Mut.NetUpdateTime = Level.TimeSeconds - 1;
|
||||
|
||||
s = ScrnRules.msgHardcore;
|
||||
ReplaceText(s, "%a", String(ScrnRules.HardcoreLevel));
|
||||
ReplaceText(s, "%i", String(inc));
|
||||
ReplaceText(s, "%r", reason);
|
||||
for(P = Level.ControllerList; P != none; P = P.nextController){
nicePlayer = NicePlayerController(P);
if(nicePlayer != none && nicePlayer.bFlagShowHLMessages)
nicePlayer.ClientMessage(s);
|
||||
}
|
||||
}
|
||||
function bool PreventDeath(Pawn Killed, Controller Killer, class<DamageType> damageType, vector HitLocation){
|
||||
local NiceHumanPawn nicePawn;
|
||||
local NicePlayerController nicePlayer;
|
||||
nicePlayer = NicePlayerController(Killed.controller);
|
||||
nicePawn = NiceHumanPawn(Killed);
|
||||
if(nicePawn != none && (!nicePawn.bReactiveArmorUsed)
&& class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillDemoReactiveArmor')){
nicePawn.bReactiveArmorUsed = true;
nicePlayer.niceRI.ServerExplode(class'NiceSkillDemoReactiveArmor'.default.baseDamage,
class'NiceSkillDemoReactiveArmor'.default.explRadius,
class'NiceSkillDemoReactiveArmor'.default.explExponent,
class'NiceDamTypeDemoSafeExplosion',
class'NiceSkillDemoReactiveArmor'.default.explMomentum,
killed.location, killed, true
);
return true;
|
||||
}
|
||||
if(NextGameRules != none)
return NextGameRules.PreventDeath(Killed, Killer, damageType, HitLocation);
|
||||
return false;
|
||||
}
|
||||
defaultproperties
|
||||
{
|
||||
}
|
9
sources/NiceSoundCls.uc
Normal file
9
sources/NiceSoundCls.uc
Normal file
@ -0,0 +1,9 @@
|
||||
class NiceSoundCls extends Effects;
|
||||
var Sound effectSound;
|
||||
var float effectVolume;
|
||||
simulated function PostBeginPlay(){
|
||||
if(effectSound != none)
PlaySound(effectSound,, effectVolume);
|
||||
}
|
||||
defaultproperties
|
||||
{
DrawType=DT_None
LifeSpan=0.100000
|
||||
}
|
20
sources/Perks/Abilities/NiceAbilitiesAdapter.uc
Normal file
20
sources/Perks/Abilities/NiceAbilitiesAdapter.uc
Normal file
@ -0,0 +1,20 @@
|
||||
//==============================================================================
|
||||
// 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
|
||||
{
|
||||
}
|
57
sources/Perks/Abilities/NiceAbilitiesEvents.uc
Normal file
57
sources/Perks/Abilities/NiceAbilitiesEvents.uc
Normal file
@ -0,0 +1,57 @@
|
||||
//==============================================================================
|
||||
// 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
|
||||
{
|
||||
}
|
137
sources/Perks/Abilities/NiceAbilityManager.uc
Normal file
137
sources/Perks/Abilities/NiceAbilityManager.uc
Normal file
@ -0,0 +1,137 @@
|
||||
//==============================================================================
|
||||
// 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 float 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 float 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.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, float 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 Tick(float deltaTime){
|
||||
local int i;
|
||||
if(Role != Role_AUTHORITY) return;
|
||||
for(i = 0;i < currentAbilitiesAmount;i ++)
AddToCooldown(i, -deltaTime);
|
||||
}
|
||||
defaultproperties
|
||||
{
maxAbilitiesAmount=5
Events=Class'NicePack.NiceAbilitiesEvents'
DrawType=DT_None
|
||||
}
|
8
sources/Perks/Berserker/NiceDamageTypeVetBerserker.uc
Normal file
8
sources/Perks/Berserker/NiceDamageTypeVetBerserker.uc
Normal file
@ -0,0 +1,8 @@
|
||||
class NiceDamageTypeVetBerserker extends NiceWeaponDamageType
|
||||
abstract;
|
||||
static function AwardNiceDamage(KFSteamStatsAndAchievements KFStatsAndAchievements, int Amount, int HL){
|
||||
if(SRStatsBase(KFStatsAndAchievements) != none && SRStatsBase(KFStatsAndAchievements).Rep != none)
SRStatsBase(KFStatsAndAchievements).Rep.ProgressCustomValue(Class'NiceVetBerserkerExp', Int(Float(Amount) * class'NicePack'.default.vetZerkDamageExpCost * getScale(HL)));
|
||||
}
|
||||
defaultproperties
|
||||
{
HeadShotDamageMult=1.250000
bIsMeleeDamage=True
DeathString="%o was beat down by %k."
FemaleSuicide="%o beat herself down."
MaleSuicide="%o beat himself down."
bRagdollBullet=True
bBulletHit=True
PawnDamageEmitter=Class'ROEffects.ROBloodPuff'
LowGoreDamageEmitter=Class'ROEffects.ROBloodPuffNoGore'
LowDetailEmitter=Class'ROEffects.ROBloodPuffSmall'
FlashFog=(X=600.000000)
KDamageImpulse=2000.000000
KDeathVel=100.000000
KDeathUpKick=25.000000
VehicleDamageScaling=0.600000
|
||||
}
|
88
sources/Perks/Berserker/NiceVetBerserker.uc
Normal file
88
sources/Perks/Berserker/NiceVetBerserker.uc
Normal file
@ -0,0 +1,88 @@
|
||||
class NiceVetBerserker extends NiceVeterancyTypes
|
||||
abstract;
|
||||
static function AddCustomStats(ClientPerkRepLink Other){
|
||||
other.AddCustomValue(Class'NiceVetBerserkerExp');
|
||||
}
|
||||
static function int GetStatValueInt(ClientPerkRepLink StatOther, byte ReqNum){
|
||||
return StatOther.GetCustomValueInt(Class'NiceVetBerserkerExp');
|
||||
}
|
||||
static function array<int> GetProgressArray(byte ReqNum, optional out int DoubleScalingBase){
|
||||
return default.progressArray0;
|
||||
}
|
||||
static function int AddDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InDamage, class<DamageType> DmgType){
|
||||
local float perkDamage;
|
||||
local class<NiceWeaponPickup> pickupClass;
|
||||
pickupClass = GetPickupFromDamageType(DmgType);
|
||||
perkDamage = float(InDamage);
|
||||
if(IsPerkedPickup(pickupClass))
perkDamage *= 2;
|
||||
return perkDamage;
|
||||
}
|
||||
static function float GetFireSpeedModStatic(KFPlayerReplicationInfo KFPRI, class<Weapon> other){
|
||||
local float bonus;
|
||||
local class<NiceWeaponPickup> pickupClass;
|
||||
local NiceHumanPawn nicePawn;
|
||||
local NicePlayerController nicePlayer;
|
||||
pickupClass = GetPickupFromWeapon(other);
|
||||
bonus = 1.0;
|
||||
nicePlayer = NicePlayerController(KFPRI.Owner);
|
||||
if(IsPerkedPickup(pickupClass))
bonus *= 1.25;
|
||||
nicePawn = NiceHumanPawn(nicePlayer.Pawn);
|
||||
if(nicePlayer != none && nicePawn != none && HasSkill(nicePlayer, class'NiceSkillZerkFury') && IsPerkedPickup(pickupClass)){
if(nicePawn != none && nicePawn.invincibilityTimer > 0.0)
bonus *= class'NiceSkillZerkFury'.default.attackSpeedBonus;
|
||||
}
|
||||
if(nicePlayer != none && nicePawn != none && nicePlayer.IsZedTimeActive() && IsPerkedPickup(pickupClass)
&& HasSkill(nicePlayer, class'NiceSkillZerkZEDAccelerate'))
bonus /= (nicePawn.Level.TimeDilation / 1.1);
|
||||
return bonus;
|
||||
}
|
||||
static function float GetMeleeMovementSpeedModifier(KFPlayerReplicationInfo KFPRI){
|
||||
return 0.2;
|
||||
}
|
||||
static function float GetMovementSpeedModifier(KFPlayerReplicationInfo KFPRI, KFGameReplicationInfo KFGRI)
|
||||
{
|
||||
local NicePlayerController nicePlayer;
|
||||
nicePlayer = NicePlayerController(KFPRI.Owner);
|
||||
if(nicePlayer != none && nicePlayer.IsZedTimeActive()
&& HasSkill(nicePlayer, class'NiceSkillZerkZEDAccelerate'))
return 1.0 / fmin(1.0, (KFGRI.Level.TimeDilation / 1.1));
|
||||
return 1.0;
|
||||
}
|
||||
static function float GetWeaponMovementSpeedBonus(KFPlayerReplicationInfo KFPRI, Weapon Weap){
|
||||
local float bonus;
|
||||
local NicePlayerController nicePlayer;
|
||||
local NiceHumanPawn nicePawn;
|
||||
bonus = 0.0;
|
||||
nicePlayer = NicePlayerController(KFPRI.Owner);
|
||||
if(nicePlayer != none)
nicePawn = NiceHumanPawn(nicePlayer.Pawn);
|
||||
if(nicePlayer != none && nicePawn != none && HasSkill(nicePlayer, class'NiceSkillZerkWhirlwind')){
if(nicePawn != none && nicePawn.invincibilityTimer > 0.0)
bonus = 1.0;
|
||||
}
|
||||
return bonus;
|
||||
}
|
||||
static function bool CanBeGrabbed(KFPlayerReplicationInfo KFPRI, KFMonster Other){
|
||||
return false;
|
||||
}
|
||||
// Set number times Zed Time can be extended
|
||||
static function int ZedTimeExtensions(KFPlayerReplicationInfo KFPRI){
|
||||
return 4;
|
||||
}
|
||||
static function float SlowingModifier(KFPlayerReplicationInfo KFPRI){
|
||||
return 1.2;
|
||||
}
|
||||
static function int GetInvincibilityExtentions(KFPlayerReplicationInfo KFPRI){
|
||||
return 3;
|
||||
}
|
||||
static function int GetInvincibilityDuration(KFPlayerReplicationInfo KFPRI){
|
||||
local NicePlayerController nicePlayer;
|
||||
nicePlayer = NicePlayerController(KFPRI.Owner);
|
||||
if( nicePlayer != none
&& HasSkill(nicePlayer, class'NiceSkillZerkColossus')){
return 3.0 + class'NiceSkillZerkColossus'.default.timeBonus;
|
||||
}
|
||||
return 3.0;
|
||||
}
|
||||
static function int GetInvincibilitySafeMisses(KFPlayerReplicationInfo KFPRI){
|
||||
local NicePlayerController nicePlayer;
|
||||
nicePlayer = NicePlayerController(KFPRI.Owner);
|
||||
if( nicePlayer != none
&& HasSkill(nicePlayer, class'NiceSkillZerkUndead')){
return 1 + class'NiceSkillZerkUndead'.default.addedSafeMisses;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static function string GetCustomLevelInfo(byte Level){
|
||||
return default.CustomLevelInfo;
|
||||
}
|
||||
defaultproperties
|
||||
{
bNewTypePerk=True
SkillGroupA(0)=Class'NicePack.NiceSkillZerkWindCutter'
SkillGroupA(1)=Class'NicePack.NiceSkillZerkWhirlwind'
SkillGroupA(2)=Class'NicePack.NiceSkillZerkColossus'
SkillGroupA(3)=Class'NicePack.NiceSkillZerkUndead'
SkillGroupA(4)=Class'NicePack.NiceSkillZerkZEDAccelerate'
SkillGroupB(0)=Class'NicePack.NiceSkillZerkCleave'
SkillGroupB(1)=Class'NicePack.NiceSkillZerkFury'
SkillGroupB(2)=Class'NicePack.NiceSkillZerkGunzerker'
SkillGroupB(3)=Class'NicePack.NiceSkillZerkVorpalBlade'
SkillGroupB(4)=Class'NicePack.NiceSkillZerkZEDUnbreakable'
progressArray0(0)=100
progressArray0(1)=1000
progressArray0(2)=3000
progressArray0(3)=10000
progressArray0(4)=30000
progressArray0(5)=100000
progressArray0(6)=200000
DefaultDamageType=Class'NicePack.NiceDamageTypeVetBerserker'
OnHUDIcons(0)=(PerkIcon=Texture'KillingFloorHUD.Perks.Perk_Berserker',StarIcon=Texture'KillingFloorHUD.HUD.Hud_Perk_Star',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(1)=(PerkIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Berserker_Gold',StarIcon=Texture'KillingFloor2HUD.Perk_Icons.Hud_Perk_Star_Gold',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(2)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Berserker_Green',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Green',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(3)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Berserker_Blue',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Blue',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(4)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Berserker_Purple',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Purple',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(5)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Berserker_Orange',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Orange',DrawColor=(B=255,G=255,R=255,A=255))
CustomLevelInfo="Level up by doing damage with perked weapons|100% extra melee damage|25% faster melee attacks|20% faster melee movement|Melee invincibility lasts 3 seconds|Melee invincibility doesn't reset on your first miss|Up to 4 Zed-Time Extensions|Can't be grabbed by clots|Can activate melee-invincibility with non-decapitating head-shots up to 3 times"
PerkIndex=4
OnHUDIcon=Texture'KillingFloorHUD.Perks.Perk_Berserker'
OnHUDGoldIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Berserker_Gold'
VeterancyName="Berserker"
Requirements(0)="Required experience for the next level: %x"
|
||||
}
|
4
sources/Perks/Berserker/NiceVetBerserkerExp.uc
Normal file
4
sources/Perks/Berserker/NiceVetBerserkerExp.uc
Normal file
@ -0,0 +1,4 @@
|
||||
class NiceVetBerserkerExp extends SRCustomProgressInt;
|
||||
defaultproperties
|
||||
{
ProgressName="Berserker exp."
|
||||
}
|
5
sources/Perks/Berserker/Skills/NiceSkillZerkBrawler.uc
Normal file
5
sources/Perks/Berserker/Skills/NiceSkillZerkBrawler.uc
Normal file
@ -0,0 +1,5 @@
|
||||
class NiceSkillZerkBrawler extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
SkillName="Brawler"
SkillEffects="Clots can't grab you."
|
||||
}
|
6
sources/Perks/Berserker/Skills/NiceSkillZerkCleave.uc
Normal file
6
sources/Perks/Berserker/Skills/NiceSkillZerkCleave.uc
Normal file
@ -0,0 +1,6 @@
|
||||
class NiceSkillZerkCleave extends NiceSkill
|
||||
abstract;
|
||||
var float bonusDegrees;
|
||||
defaultproperties
|
||||
{
bonusDegrees=0.523599
SkillName="Cleave"
SkillEffects="Add 30 degrees to wide attacks with melee weapons."
|
||||
}
|
6
sources/Perks/Berserker/Skills/NiceSkillZerkColossus.uc
Normal file
6
sources/Perks/Berserker/Skills/NiceSkillZerkColossus.uc
Normal file
@ -0,0 +1,6 @@
|
||||
class NiceSkillZerkColossus extends NiceSkill
|
||||
abstract;
|
||||
var float timeBonus;
|
||||
defaultproperties
|
||||
{
timeBonus=1.000000
SkillName="Colossus"
SkillEffects="Invincibility period lasts 1 second longer."
|
||||
}
|
6
sources/Perks/Berserker/Skills/NiceSkillZerkFury.uc
Normal file
6
sources/Perks/Berserker/Skills/NiceSkillZerkFury.uc
Normal file
@ -0,0 +1,6 @@
|
||||
class NiceSkillZerkFury extends NiceSkill
|
||||
abstract;
|
||||
var float attackSpeedBonus;
|
||||
defaultproperties
|
||||
{
attackSpeedBonus=1.500000
SkillName="Fury"
SkillEffects="Attack 50% faster during invincibility."
|
||||
}
|
6
sources/Perks/Berserker/Skills/NiceSkillZerkGunzerker.uc
Normal file
6
sources/Perks/Berserker/Skills/NiceSkillZerkGunzerker.uc
Normal file
@ -0,0 +1,6 @@
|
||||
class NiceSkillZerkGunzerker extends NiceSkill
|
||||
abstract;
|
||||
var float cooldown;
|
||||
defaultproperties
|
||||
{
cooldown=-2.000000
SkillName="Gunzerker"
SkillEffects="You're able to activate melee-invincibility with non-melee headshots, but your misses are punished by a 2 second cooldown, during which you cannot activate invincibility."
|
||||
}
|
6
sources/Perks/Berserker/Skills/NiceSkillZerkUndead.uc
Normal file
6
sources/Perks/Berserker/Skills/NiceSkillZerkUndead.uc
Normal file
@ -0,0 +1,6 @@
|
||||
class NiceSkillZerkUndead extends NiceSkill
|
||||
abstract;
|
||||
var int addedSafeMisses;
|
||||
defaultproperties
|
||||
{
addedSafeMisses=1
SkillName="Undead"
SkillEffects="Get additional safe melee-miss during invincibility period."
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
class NiceSkillZerkVorpalBlade extends NiceSkill
|
||||
abstract;
|
||||
var float damageBonus;
|
||||
defaultproperties
|
||||
{
damageBonus=2.000000
SkillName="Vorpal blade"
SkillEffects="Your head-shot deals double damage on your first invincibility extension against the zed."
|
||||
}
|
5
sources/Perks/Berserker/Skills/NiceSkillZerkWhirlwind.uc
Normal file
5
sources/Perks/Berserker/Skills/NiceSkillZerkWhirlwind.uc
Normal file
@ -0,0 +1,5 @@
|
||||
class NiceSkillZerkWhirlwind extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
SkillName="Whirlwind"
SkillEffects="Move twice as fast during invincibility."
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
class NiceSkillZerkWindCutter extends NiceSkill
|
||||
abstract;
|
||||
var float rangeBonus;
|
||||
defaultproperties
|
||||
{
rangeBonus=1.500000
SkillName="Wind cutter"
SkillEffects="Increase your reach with melee-weapons by 50%."
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class NiceSkillZerkZEDAccelerate extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
SkillName="Accelerate"
SkillEffects="Move and attack at the same speed during zed-time."
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class NiceSkillZerkZEDUnbreakable extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
SkillName="Unbreakable"
SkillEffects="You resist all damage during zed time."
|
||||
}
|
14
sources/Perks/Commando/NiceDamageTypeVetCommando.uc
Normal file
14
sources/Perks/Commando/NiceDamageTypeVetCommando.uc
Normal file
@ -0,0 +1,14 @@
|
||||
class NiceDamageTypeVetCommando extends NiceWeaponDamageType
|
||||
abstract;
|
||||
static function AwardKill(KFSteamStatsAndAchievements KFStatsAndAchievements, KFPlayerController Killer, KFMonster Killed ){
|
||||
if(Killed.IsA('ZombieStalker'))
KFStatsAndAchievements.AddStalkerKill();
|
||||
}
|
||||
static function AwardDamage(KFSteamStatsAndAchievements KFStatsAndAchievements, int Amount){
|
||||
KFStatsAndAchievements.AddBullpupDamage(Amount);
|
||||
}
|
||||
static function AwardNiceDamage(KFSteamStatsAndAchievements KFStatsAndAchievements, int Amount, int HL){
|
||||
if(SRStatsBase(KFStatsAndAchievements) != none && SRStatsBase(KFStatsAndAchievements).Rep != none)
SRStatsBase(KFStatsAndAchievements).Rep.ProgressCustomValue(Class'NiceVetCommandoExp', Int(Float(Amount) * class'NicePack'.default.vetCommandoDamageExpCost * getScale(HL)));
|
||||
}
|
||||
defaultproperties
|
||||
{
|
||||
}
|
38
sources/Perks/Commando/NiceVetCommando.uc
Normal file
38
sources/Perks/Commando/NiceVetCommando.uc
Normal file
@ -0,0 +1,38 @@
|
||||
class NiceVetCommando extends NiceVeterancyTypes
|
||||
abstract;
|
||||
static function AddCustomStats(ClientPerkRepLink Other){
|
||||
other.AddCustomValue(Class'NiceVetCommandoExp');
|
||||
}
|
||||
static function int GetStatValueInt(ClientPerkRepLink StatOther, byte ReqNum){
|
||||
return StatOther.GetCustomValueInt(Class'NiceVetCommandoExp');
|
||||
}
|
||||
static function array<int> GetProgressArray(byte ReqNum, optional out int DoubleScalingBase){
|
||||
return default.progressArray0;
|
||||
}
|
||||
static function float GetHealthBarsDistanceMulti(KFPlayerReplicationInfo KFPRI){
|
||||
if(KFPRI != none && SomeoneHasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillCommandoStrategist'))
return class'NiceSkillCommandoStrategist'.default.visionRadius;
|
||||
return 0.0;
|
||||
}
|
||||
static function float GetStalkerViewDistanceMulti(KFPlayerReplicationInfo KFPRI){
|
||||
if(KFPRI != none && SomeoneHasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillCommandoStrategist'))
return class'NiceSkillCommandoStrategist'.default.visionRadius;
|
||||
return 0.0;
|
||||
}
|
||||
static function float GetMagCapacityMod(KFPlayerReplicationInfo KFPRI, KFWeapon Other){
|
||||
local class<NiceWeaponPickup> pickupClass;
|
||||
pickupClass = GetPickupFromWeapon(other.class);
|
||||
if(IsPerkedPickup(pickupClass) && HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillCommandoLargerMags'))
return class'NiceSkillCommandoLargerMags'.default.sizeBonus;
|
||||
return 1.0;
|
||||
}
|
||||
static function float GetReloadSpeedModifierStatic(KFPlayerReplicationInfo KFPRI, class<KFWeapon> Other){
|
||||
return 1.3;
|
||||
}
|
||||
static function int ZedTimeExtensions(KFPlayerReplicationInfo KFPRI){
|
||||
if(HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillCommandoTactitian'))
return class'NiceSkillCommandoTactitian'.default.bonusExt + 3;
|
||||
return 3;
|
||||
}
|
||||
static function string GetCustomLevelInfo(byte Level){
|
||||
return default.CustomLevelInfo;
|
||||
}
|
||||
defaultproperties
|
||||
{
bNewTypePerk=True
SkillGroupA(0)=Class'NicePack.NiceSkillCommandoTactitian'
SkillGroupA(1)=Class'NicePack.NiceSkillCommandoCriticalFocus'
SkillGroupA(2)=Class'NicePack.NiceSkillCommandoLargerMags'
SkillGroupA(3)=Class'NicePack.NiceSkillCommandoPerfectExecution'
SkillGroupA(4)=Class'NicePack.NiceSkillCommandoZEDProfessional'
SkillGroupB(0)=Class'NicePack.NiceSkillCommandoStrategist'
SkillGroupB(1)=Class'NicePack.NiceSkillCommandoTrashCleaner'
SkillGroupB(2)=Class'NicePack.NiceSkillCommandoExplosivePower'
SkillGroupB(3)=Class'NicePack.NiceSkillCommandoThinOut'
SkillGroupB(4)=Class'NicePack.NiceSkillCommandoZEDEvisceration'
progressArray0(0)=100
progressArray0(1)=1000
progressArray0(2)=3000
progressArray0(3)=10000
progressArray0(4)=30000
progressArray0(5)=100000
progressArray0(6)=200000
DefaultDamageType=Class'NicePack.NiceDamageTypeVetCommando'
OnHUDIcons(0)=(PerkIcon=Texture'KillingFloorHUD.Perks.Perk_Commando',StarIcon=Texture'KillingFloorHUD.HUD.Hud_Perk_Star',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(1)=(PerkIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Commando_Gold',StarIcon=Texture'KillingFloor2HUD.Perk_Icons.Hud_Perk_Star_Gold',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(2)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Commando_Green',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Green',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(3)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Commando_Blue',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Blue',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(4)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Commando_Purple',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Purple',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(5)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Commando_Orange',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Orange',DrawColor=(B=255,G=255,R=255,A=255))
CustomLevelInfo="Level up by doing damage with perked weapons|30% faster reload with all weapons|You get three additional Zed-Time Extensions"
PerkIndex=3
OnHUDIcon=Texture'KillingFloorHUD.Perks.Perk_Commando'
OnHUDGoldIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Commando_Gold'
VeterancyName="Commando"
Requirements(0)="Required experience for the next level: %x"
|
||||
}
|
4
sources/Perks/Commando/NiceVetCommandoExp.uc
Normal file
4
sources/Perks/Commando/NiceVetCommandoExp.uc
Normal file
@ -0,0 +1,4 @@
|
||||
class NiceVetCommandoExp extends SRCustomProgressInt;
|
||||
defaultproperties
|
||||
{
ProgressName="Commando exp."
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
class NiceSkillCommandoCriticalFocus extends NiceSkill
|
||||
abstract;
|
||||
var float cooldown;
|
||||
var float healthBoundary;
|
||||
function static SkillSelected(NicePlayerController nicePlayer){
|
||||
local NicePack niceMutator;
|
||||
super.SkillSelected(nicePlayer);
|
||||
niceMutator = class'NicePack'.static.Myself(nicePlayer.Level);
|
||||
if(niceMutator == none || niceMutator.Role == Role_AUTHORITY)
return;
|
||||
niceMutator.AddCounter("npCommandoCriticalFocus", Texture'NicePackT.HudCounter.commandoCounter', false, default.class);
|
||||
}
|
||||
function static SkillDeSelected(NicePlayerController nicePlayer){
|
||||
local NicePack niceMutator;
|
||||
super.SkillDeSelected(nicePlayer);
|
||||
niceMutator = class'NicePack'.static.Myself(nicePlayer.Level);
|
||||
if(niceMutator == none || niceMutator.Role == Role_AUTHORITY)
return;
|
||||
niceMutator.RemoveCounter("npCommandoCriticalFocus");
|
||||
}
|
||||
function static int UpdateCounterValue(string counterName, NicePlayerController nicePlayer){
|
||||
local NiceHumanPawn nicePawn;
|
||||
if(nicePlayer == none || counterName != "npCommandoCriticalFocus")
return 0;
|
||||
nicePawn = NiceHumanPawn(nicePlayer.pawn);
|
||||
if(nicePawn == none)
return 0;
|
||||
return Ceil(nicePawn.forcedZedTimeCountDown);
|
||||
}
|
||||
defaultproperties
|
||||
{
cooldown=30.000000
healthBoundary=50.000000
SkillName="Critical focus"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
class NiceSkillCommandoExplosivePower extends NiceSkill
|
||||
abstract;
|
||||
var float dmgMod;
|
||||
defaultproperties
|
||||
{
dmgMod=1.200000
SkillName="Explosive power"
SkillEffects="Burst fire deals 20% more damage and has reduced delay between shots."
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
class NiceSkillCommandoLargerMags extends NiceSkill
|
||||
abstract;
|
||||
var float sizeBonus;
|
||||
defaultproperties
|
||||
{
sizeBonus=1.500000
SkillName="Larger mags"
SkillEffects="50% larger assault rifles' magazines."
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class NiceSkillCommandoPerfectExecution extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
SkillName="Perfect execution"
SkillEffects="Raging scrake or fleshpound activates zed-time."
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
class NiceSkillCommandoStrategist extends NiceSkill
|
||||
abstract;
|
||||
var float visionRadius; // 1.0 ~ 16m
|
||||
defaultproperties
|
||||
{
visionRadius=1.000000
bBroadcast=True
SkillName="Strategist"
SkillEffects="You and your teammates can see enemies' health and invisible zeds from 16 meters."
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
class NiceSkillCommandoTactitian extends NiceSkill
|
||||
abstract;
|
||||
var int bonusExt;
|
||||
defaultproperties
|
||||
{
bonusExt=2
SkillName="Tactician"
SkillEffects="Gain two additional zed-time extensions."
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
class NiceSkillCommandoThinOut extends NiceSkill
|
||||
abstract;
|
||||
var float damageMult;
|
||||
var float maxDistance;
|
||||
defaultproperties
|
||||
{
damageMult=2.000000
MaxDistance=800.000000
SkillName="Thin out"
SkillEffects="Deal double damage against non-trash zeds, when there's either a huge zed or another zed of the same type within 16 meters of you."
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
class NiceSkillCommandoTrashCleaner extends NiceSkill
|
||||
abstract;
|
||||
var float decapitationMultiLimit;
|
||||
defaultproperties
|
||||
{
decapitationMultiLimit=0.600000
SkillName="Trash cleaner"
SkillEffects="Get finisher property on your shots against low-health zeds, but your weapons leave more decapitated zeds behind."
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class NiceSkillCommandoZEDEvisceration extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
SkillName="Evisceration"
SkillEffects="During zed-time both 'Trash cleaner' and 'Thin out' skills are active."
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class NiceSkillCommandoZEDProfessional extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
SkillName="Professionalism"
SkillEffects="Your reloads aren't slowed down during zed-time."
|
||||
}
|
5
sources/Perks/Demolitions/NiceDamTypeDemoBlunt.uc
Normal file
5
sources/Perks/Demolitions/NiceDamTypeDemoBlunt.uc
Normal file
@ -0,0 +1,5 @@
|
||||
class NiceDamTypeDemoBlunt extends NiceDamageTypeVetDemolitions
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
HeadShotDamageMult=2.000000
bSniperWeapon=True
DeathString="%k killed %o (LAW Impact)."
FemaleSuicide="%o shot herself in the foot."
MaleSuicide="%o shot himself in the foot."
bRagdollBullet=True
bBulletHit=True
FlashFog=(X=600.000000)
KDamageImpulse=5000.000000
KDeathVel=200.000000
KDeathUpKick=50.000000
VehicleDamageScaling=0.700000
|
||||
}
|
9
sources/Perks/Demolitions/NiceDamTypeDemoExplosion.uc
Normal file
9
sources/Perks/Demolitions/NiceDamTypeDemoExplosion.uc
Normal file
@ -0,0 +1,9 @@
|
||||
class NiceDamTypeDemoExplosion extends NiceDamageTypeVetDemolitions;
|
||||
static function GetHitEffects(out class<xEmitter> HitEffects[4], int VictimHealth){
|
||||
HitEffects[0] = class'HitSmoke';
|
||||
if(VictimHealth <= 0)
HitEffects[1] = class'KFHitFlame';
|
||||
else if(FRand() < 0.8)
HitEffects[1] = class'KFHitFlame';
|
||||
}
|
||||
defaultproperties
|
||||
{
stunMultiplier=0.600000
bIsExplosive=True
DeathString="%o filled %k's body with shrapnel."
FemaleSuicide="%o blew up."
MaleSuicide="%o blew up."
bLocationalHit=False
bThrowRagdoll=True
bExtraMomentumZ=True
DamageThreshold=1
DeathOverlayMaterial=Combiner'Effects_Tex.GoreDecals.PlayerDeathOverlay'
DeathOverlayTime=999.000000
KDamageImpulse=3000.000000
KDeathVel=300.000000
KDeathUpKick=250.000000
HumanObliterationThreshhold=150
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
class NiceDamTypeDemoSafeExplosion extends NiceDamTypeDemoExplosion;
|
||||
defaultproperties
|
||||
{
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
class NiceDamageTypeVetDemolitions extends NiceWeaponDamageType
|
||||
abstract;
|
||||
static function AwardNiceDamage(KFSteamStatsAndAchievements KFStatsAndAchievements, int Amount, int HL){
|
||||
if(SRStatsBase(KFStatsAndAchievements) != none && SRStatsBase(KFStatsAndAchievements).Rep != none)
SRStatsBase(KFStatsAndAchievements).Rep.ProgressCustomValue(Class'NiceVetDemolitionsExp', Int(Float(Amount) * class'NicePack'.default.vetDemoDamageExpCost * getScale(HL)));
|
||||
}
|
||||
defaultproperties
|
||||
{
|
||||
}
|
66
sources/Perks/Demolitions/NiceVetDemolitions.uc
Normal file
66
sources/Perks/Demolitions/NiceVetDemolitions.uc
Normal file
@ -0,0 +1,66 @@
|
||||
class NiceVetDemolitions extends NiceVeterancyTypes
|
||||
abstract;
|
||||
static function AddCustomStats(ClientPerkRepLink Other){
|
||||
other.AddCustomValue(Class'NiceVetDemolitionsExp');
|
||||
}
|
||||
static function int GetStatValueInt(ClientPerkRepLink StatOther, byte ReqNum){
|
||||
return StatOther.GetCustomValueInt(Class'NiceVetDemolitionsExp');
|
||||
}
|
||||
static function array<int> GetProgressArray(byte ReqNum, optional out int DoubleScalingBase){
|
||||
return default.progressArray0;
|
||||
}
|
||||
static function int ReduceDamage(KFPlayerReplicationInfo KFPRI, KFPawn Injured, Pawn Instigator, int InDamage, class<DamageType> DmgType){
|
||||
local NicePlayerController nicePlayer;
|
||||
if(class<NiceDamTypeDemoSafeExplosion>(DmgType) != none)
return 0;
|
||||
nicePlayer = NicePlayerController(KFPRI.Owner);
|
||||
if(nicePlayer != none && Instigator == nicePlayer.pawn && nicePlayer.IsZedTimeActive()
&& HasSkill(nicePlayer, class'NiceSkillDemoZEDDuckAndCover'))
return 0.0;
|
||||
if((class<KFWeaponDamageType>(DmgType) != none && class<KFWeaponDamageType>(DmgType).default.bIsExplosive))
return float(InDamage) * 0.5;
|
||||
return InDamage;
|
||||
}
|
||||
static function float AddExtraAmmoFor(KFPlayerReplicationInfo KFPRI, Class<Ammunition> AmmoType){
|
||||
local float bonusNades, bonusPipes;
|
||||
// Default bonus
|
||||
bonusNades = 5;
|
||||
bonusPipes = 6;
|
||||
if(AmmoType == class'FragAmmo')
return 1.0 + 0.2 * bonusNades;
|
||||
if(ClassIsChildOf(AmmoType, class'PipeBombAmmo'))
return 1.0 + 0.5 * bonusPipes;
|
||||
return 1.0;
|
||||
}
|
||||
static function int AddDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InDamage, class<DamageType> DmgType){
|
||||
local float perkDamage;
|
||||
local class<NiceWeaponPickup> pickupClass;
|
||||
pickupClass = GetPickupFromDamageType(DmgType);
|
||||
perkDamage = float(InDamage);
|
||||
if(DmgType == class'NicePack.NiceDamTypeDemoExplosion')
return 1.6 * perkDamage;
|
||||
if(IsPerkedPickup(pickupClass))
perkDamage *= 1.25;
|
||||
else if( pickupClass != none && pickupClass.default.weight <= class'NiceSkillDemoOffperk'.default.weightBound
&& HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillDemoOffperk') )
perkDamage *= class'NiceSkillDemoOffperk'.default.damageBonus;
|
||||
if( KFPRI != none && class<NiceDamTypeDemoBlunt>(DmgType) != none
&& SomeoneHasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillDemoOnperk') )
perkDamage *= class'NiceSkillDemoOnperk'.default.damageBonus;
|
||||
return perkDamage;
|
||||
}
|
||||
static function float GetReloadSpeedModifierStatic(KFPlayerReplicationInfo KFPRI, class<KFWeapon> other){
|
||||
local NiceHumanPawn nicePawn;
|
||||
local class<NiceWeaponPickup> pickupClass;
|
||||
// Pistols reload
|
||||
if( other != none && other.default.weight <= class'NiceSkillDemoOffperk'.default.weightBound
&& HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillDemoOffperk') )
return class'NiceSkillDemoOffperk'.default.reloadBonus;
|
||||
// Maniac reload
|
||||
pickupClass = GetPickupFromWeapon(other);
|
||||
if(KFPRI != none && PlayerController(KFPRI.Owner) != none)
nicePawn = NiceHumanPawn(PlayerController(KFPRI.Owner).Pawn);
|
||||
if(nicePawn != none && nicePawn.maniacTimeout >= 0.0 && IsPerkedPickup(pickupClass))
return class'NiceSkillDemoManiac'.default.reloadSpeedup;
|
||||
return 1.0;
|
||||
}
|
||||
static function float stunDurationMult(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, class<NiceWeaponDamageType> DmgType){
|
||||
if(HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillDemoConcussion'))
return class'NiceSkillDemoConcussion'.default.durationMult;
|
||||
return 1.0;
|
||||
}
|
||||
static function int AddStunScore(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InStunScore, class<NiceWeaponDamageType> DmgType){
|
||||
return int(float(InStunScore) * 1.5);
|
||||
}
|
||||
static function int AddFlinchScore(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InFlinchScore, class<NiceWeaponDamageType> DmgType){
|
||||
return int(float(InFlinchScore) * 1.5);
|
||||
}
|
||||
static function string GetCustomLevelInfo(byte Level){
|
||||
return default.CustomLevelInfo;
|
||||
}
|
||||
defaultproperties
|
||||
{
bNewTypePerk=True
SkillGroupA(0)=Class'NicePack.NiceSkillDemoOnperk'
SkillGroupA(1)=Class'NicePack.NiceSkillDemoDirectApproach'
SkillGroupA(2)=Class'NicePack.NiceSkillDemoConcussion'
SkillGroupA(3)=Class'NicePack.NiceSkillDemoAPShot'
SkillGroupA(4)=Class'NicePack.NiceSkillDemoZEDDuckAndCover'
SkillGroupB(0)=Class'NicePack.NiceSkillDemoOffperk'
SkillGroupB(1)=Class'NicePack.NiceSkillDemoVolatile'
SkillGroupB(2)=Class'NicePack.NiceSkillDemoReactiveArmor'
SkillGroupB(3)=Class'NicePack.NiceSkillDemoManiac'
SkillGroupB(4)=Class'NicePack.NiceSkillDemoZEDFullBlast'
progressArray0(0)=100
progressArray0(1)=1000
progressArray0(2)=3000
progressArray0(3)=10000
progressArray0(4)=30000
progressArray0(5)=100000
progressArray0(6)=200000
DefaultDamageType=Class'NicePack.NiceDamageTypeVetDemolitions'
OnHUDIcons(0)=(PerkIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Demolition',StarIcon=Texture'KillingFloorHUD.HUD.Hud_Perk_Star',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(1)=(PerkIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Demolition_Gold',StarIcon=Texture'KillingFloor2HUD.Perk_Icons.Hud_Perk_Star_Gold',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(2)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Demolition_Green',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Green',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(3)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Demolition_Blue',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Blue',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(4)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Demolition_Purple',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Purple',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(5)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Demolition_Orange',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Orange',DrawColor=(B=255,G=255,R=255,A=255))
CustomLevelInfo="Level up by doing damage with perked weapons|25% extra explosives damage|50% better stun and flinch ability for all weapons|50% resistance to explosives|+5 grenades|+6 pipe bombs"
PerkIndex=6
OnHUDIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Demolition'
OnHUDGoldIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Demolition_Gold'
VeterancyName="Demolitions"
Requirements(0)="Required experience for the next level: %x"
|
||||
}
|
4
sources/Perks/Demolitions/NiceVetDemolitionsExp.uc
Normal file
4
sources/Perks/Demolitions/NiceVetDemolitionsExp.uc
Normal file
@ -0,0 +1,4 @@
|
||||
class NiceVetDemolitionsExp extends SRCustomProgressInt;
|
||||
defaultproperties
|
||||
{
ProgressName="Demolitions exp."
|
||||
}
|
7
sources/Perks/Demolitions/Skills/NiceSkillDemoAPShot.uc
Normal file
7
sources/Perks/Demolitions/Skills/NiceSkillDemoAPShot.uc
Normal file
@ -0,0 +1,7 @@
|
||||
class NiceSkillDemoAPShot extends NiceSkill
|
||||
abstract;
|
||||
var float minCos;
|
||||
var float damageRatio;
|
||||
defaultproperties
|
||||
{
minCos=0.707000
damageRatio=1.000000
SkillName="AP shot"
SkillEffects="Deal full blast damage behind the target you've hit."
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
class NiceSkillDemoConcussion extends NiceSkill
|
||||
abstract;
|
||||
var float durationMult;
|
||||
defaultproperties
|
||||
{
durationMult=2.000000
SkillName="Concussion"
SkillEffects="You stun zeds for twice longer time than usual."
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class NiceSkillDemoDirectApproach extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
SkillName="Direct approach"
SkillEffects="Your explosives will first hit target zed as a blunt before exploding."
|
||||
}
|
28
sources/Perks/Demolitions/Skills/NiceSkillDemoManiac.uc
Normal file
28
sources/Perks/Demolitions/Skills/NiceSkillDemoManiac.uc
Normal file
@ -0,0 +1,28 @@
|
||||
class NiceSkillDemoManiac extends NiceSkill
|
||||
abstract;
|
||||
var float reloadBoostTime;
|
||||
var float reloadSpeedup;
|
||||
function static SkillSelected(NicePlayerController nicePlayer){
|
||||
local NicePack niceMutator;
|
||||
super.SkillSelected(nicePlayer);
|
||||
niceMutator = class'NicePack'.static.Myself(nicePlayer.Level);
|
||||
if(niceMutator == none || niceMutator.Role == Role_AUTHORITY)
return;
|
||||
niceMutator.AddCounter("npDemoManiac", Texture'NicePackT.HudCounter.demo', false, default.class);
|
||||
}
|
||||
function static SkillDeSelected(NicePlayerController nicePlayer){
|
||||
local NicePack niceMutator;
|
||||
super.SkillDeSelected(nicePlayer);
|
||||
niceMutator = class'NicePack'.static.Myself(nicePlayer.Level);
|
||||
if(niceMutator == none || niceMutator.Role == Role_AUTHORITY)
return;
|
||||
niceMutator.RemoveCounter("npDemoManiac");
|
||||
}
|
||||
function static int UpdateCounterValue(string counterName, NicePlayerController nicePlayer){
|
||||
local NiceHumanPawn nicePawn;
|
||||
if(nicePlayer == none || counterName != "npDemoManiac")
return 0;
|
||||
nicePawn = NiceHumanPawn(nicePlayer.pawn);
|
||||
if(nicePawn == none || nicePawn.maniacTimeout <= 0.0)
return 0;
|
||||
return Ceil(nicePawn.maniacTimeout);
|
||||
}
|
||||
defaultproperties
|
||||
{
reloadBoostTime=5.000000
reloadSpeedup=1.500000
SkillName="Maniac"
SkillEffects="Reload 50% faster for 5 seconds after killing something."
|
||||
}
|
8
sources/Perks/Demolitions/Skills/NiceSkillDemoOffperk.uc
Normal file
8
sources/Perks/Demolitions/Skills/NiceSkillDemoOffperk.uc
Normal file
@ -0,0 +1,8 @@
|
||||
class NiceSkillDemoOffperk extends NiceSkill
|
||||
abstract;
|
||||
var float damageBonus;
|
||||
var float reloadBonus;
|
||||
var int weightBound;
|
||||
defaultproperties
|
||||
{
damageBonus=1.250000
ReloadBonus=1.250000
weightBound=4
SkillName="Offperk"
SkillEffects="Reload light weapons (less than 5 pounds) 25% faster and do 25% more damage with them."
|
||||
}
|
7
sources/Perks/Demolitions/Skills/NiceSkillDemoOnperk.uc
Normal file
7
sources/Perks/Demolitions/Skills/NiceSkillDemoOnperk.uc
Normal file
@ -0,0 +1,7 @@
|
||||
class NiceSkillDemoOnperk extends NiceSkill
|
||||
abstract;
|
||||
var float damageBonus;
|
||||
var float speedBonus;
|
||||
defaultproperties
|
||||
{
damageBonus=1.200000
speedBonus=1.500000
bBroadcast=True
SkillName="Onperk"
SkillEffects="Deal 20% more damage with your blunts and make your perk weapon's projectiles fly 50% faster."
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
class NiceSkillDemoReactiveArmor extends NiceSkill
|
||||
abstract;
|
||||
var float baseDamage;
|
||||
var float perNadeDamage;
|
||||
var float explRadius;
|
||||
var float explExponent;
|
||||
var float explMomentum;
|
||||
defaultproperties
|
||||
{
BaseDamage=3000.000000
explRadius=1000.000000
explExponent=1.000000
explMomentum=150000.000000
SkillName="Reactive armor"
SkillEffects="Once per wave your death will be prevented, while zeds all around you will be blown to bits."
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
class NiceSkillDemoVolatile extends NiceSkill
|
||||
abstract;
|
||||
var float safeDistanceMult;
|
||||
var float explRangeMult;
|
||||
var float falloffMult;
|
||||
defaultproperties
|
||||
{
safeDistanceMult=0.500000
explRangeMult=1.000000
falloffMult=0.500000
SkillName="Volatile"
SkillEffects="Safe range for your explosives is halved and explosion damage experiences smaller fall off."
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class NiceSkillDemoZEDDuckAndCover extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
SkillName="Duck and cover"
SkillEffects="During zed time you can't deal yourself any damage."
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
class NiceSkillDemoZEDFullBlast extends NiceSkill
|
||||
abstract;
|
||||
var float explRadiusMult;
|
||||
defaultproperties
|
||||
{
explRadiusMult=1.350000
SkillName="Full blast"
SkillEffects="During zed time your explosions have 35% larger radius and their damage doesn't suffer from a fall off."
|
||||
}
|
10
sources/Perks/Enforcer/NiceDamageTypeVetEnforcer.uc
Normal file
10
sources/Perks/Enforcer/NiceDamageTypeVetEnforcer.uc
Normal file
@ -0,0 +1,10 @@
|
||||
class NiceDamageTypeVetEnforcer extends NiceWeaponDamageType
|
||||
abstract;
|
||||
|
||||
static function AwardNiceDamage(KFSteamStatsAndAchievements KFStatsAndAchievements, int Amount, int HL){
|
||||
if(SRStatsBase(KFStatsAndAchievements) != none && SRStatsBase(KFStatsAndAchievements).Rep != none)
SRStatsBase(KFStatsAndAchievements).Rep.ProgressCustomValue(Class'NiceVetSupportExp', Int(Float(Amount) * class'NicePack'.default.vetSupportDamageExpCost * getScale(HL)));
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
badDecapMod=1.000000
bIsProjectile=True
HeadShotDamageMult=1.500000
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
class NiceDamageTypeVetEnforcerBullets extends NiceDamageTypeVetEnforcer
|
||||
abstract;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
badDecapMod=0.2500000
goodDecapMod=0.500000
bodyDestructionMult=1.000000
HeadShotDamageMult=1.000000
|
||||
}
|
118
sources/Perks/Enforcer/NiceVetEnforcer.uc
Normal file
118
sources/Perks/Enforcer/NiceVetEnforcer.uc
Normal file
@ -0,0 +1,118 @@
|
||||
class NiceVetEnforcer extends NiceVeterancyTypes
|
||||
abstract;
|
||||
|
||||
static function AddCustomStats(ClientPerkRepLink Other){
|
||||
Other.AddCustomValue(Class'NiceVetSupportExp');
|
||||
}
|
||||
|
||||
static function int GetStatValueInt(ClientPerkRepLink StatOther, byte ReqNum){
|
||||
return StatOther.GetCustomValueInt(Class'NiceVetSupportExp');
|
||||
}
|
||||
|
||||
static function array<int> GetProgressArray(byte ReqNum, optional out int DoubleScalingBase){
|
||||
return default.progressArray0;
|
||||
}
|
||||
|
||||
// Other bonuses
|
||||
|
||||
static function float GetPenetrationDamageMulti(KFPlayerReplicationInfo KFPRI, float DefaultPenDamageReduction, class<NiceWeaponDamageType> fireIntance){
|
||||
local float bonusReduction;
|
||||
local float PenDamageInverse;
|
||||
bonusReduction = 0.0;
|
||||
if(class<NiceDamageTypeVetEnforcerBullets>(fireIntance) != none)
|
||||
return DefaultPenDamageReduction;
|
||||
if(HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillSupportStubbornness'))
bonusReduction = class'NiceSkillSupportStubbornness'.default.penLossRed;
|
||||
PenDamageInverse = (1.0 - FMax(0, DefaultPenDamageReduction));
|
||||
return DefaultPenDamageReduction + PenDamageInverse * (0.6 + 0.4 * bonusReduction); // 60% better penetrations + bonus
|
||||
}
|
||||
|
||||
static function int AddStunScore(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InStunScore, class<NiceWeaponDamageType> DmgType){
|
||||
local class<NiceWeaponPickup> pickupClass;
|
||||
pickupClass = GetPickupFromDamageType(DmgType);
|
||||
if(KFPRI != none && IsPerkedPickup(pickupClass) && HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillEnforcerBombard'))
return InStunScore * class'NiceSkillEnforcerBombard'.default.stunMult;
|
||||
return InStunScore;
|
||||
}
|
||||
|
||||
static function class<Grenade> GetNadeType(KFPlayerReplicationInfo KFPRI){
|
||||
/*if(HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillSupportCautious'))
return class'NicePack.NiceDelayedNade';
|
||||
return class'NicePack.NiceNailNade';*/
|
||||
return class'NicePack.NiceCryoNade';
|
||||
}
|
||||
|
||||
static function int ReduceDamage(KFPlayerReplicationInfo KFPRI, KFPawn Injured, Pawn Instigator, int InDamage, class<DamageType> DmgType){
|
||||
if(HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillEnforcerDetermination') && Injured.Health < class'NiceSkillEnforcerDetermination'.default.healthBound)
|
||||
InDamage *= (1 - class'NiceSkillEnforcerDetermination'.default.addedResist);
|
||||
if(HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillEnforcerUnshakable'))
|
||||
InDamage *= (1 - class'NiceSkillEnforcerUnshakable'.default.skillResist);
|
||||
if(HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillHeavyCoating') && Injured.ShieldStrength > 0){
|
||||
if( class<KFWeaponDamageType>(DmgType) != none
|
||||
&& ((class<KFWeaponDamageType>(DmgType).default.bDealBurningDamage && KFMonster(Instigator) != none)
|
||||
|| DmgType == class'NiceZombieTeslaHusk'.default.MyDamageType) )
|
||||
InDamage *= (1 - class'NiceSkillHeavyCoating'.default.huskResist);
|
||||
}
|
||||
return InDamage;
|
||||
}
|
||||
|
||||
static function float GetFireSpeedModStatic(KFPlayerReplicationInfo KFPRI, class<Weapon> other){
|
||||
local float fireSpeed;
|
||||
local NicePlayerController nicePlayer;
|
||||
local class<NiceWeaponPickup> pickupClass;
|
||||
pickupClass = GetPickupFromWeapon(other);
|
||||
if(KFPRI.Owner == none)
|
||||
return 1.0;
|
||||
if(IsPerkedPickup(pickupClass) && HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillHeavyOverclocking'))
|
||||
fireSpeed = class'NiceSkillHeavyOverclocking'.default.fireSpeedMult;
|
||||
else
|
||||
fireSpeed = 1.0;
|
||||
nicePlayer = NicePlayerController(KFPRI.Owner);
|
||||
/*if(nicePlayer != none && HasSkill(nicePlayer, class'NiceSkillEnforcerZEDBarrage'))
|
||||
fireSpeed /= (KFPRI.Owner.Level.TimeDilation / 1.1);*/
|
||||
return fireSpeed;
|
||||
}
|
||||
|
||||
static function float ModifyRecoilSpread(KFPlayerReplicationInfo KFPRI, WeaponFire other, out float Recoil){
|
||||
local class<NiceWeaponPickup> pickupClass;
|
||||
pickupClass = GetPickupFromWeaponFire(other);
|
||||
if(IsPerkedPickup(pickupClass) && HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillHeavyOverclocking'))
|
||||
Recoil = class'NiceSkillHeavyOverclocking'.default.fireSpeedMult;
|
||||
else
|
||||
Recoil = 1.0;
|
||||
return Recoil;
|
||||
}
|
||||
|
||||
/*static function float GetMagCapacityModStatic(KFPlayerReplicationInfo KFPRI, class<KFWeapon> other){
|
||||
local class<NiceWeapon> niceWeap;
|
||||
niceWeap = class<NiceWeapon>(other);
|
||||
if(niceWeap != none && niceWeap.default.reloadType == RTYPE_MAG)
|
||||
return 1.5;
|
||||
if(other == class'NicePack.NiceM41AAssaultRifle' || other == class'NicePack.NiceChainGun' || other == class'NicePack.NiceStinger' )
|
||||
return 1.5;
|
||||
return 1.0;
|
||||
}*/
|
||||
|
||||
static function float GetMovementSpeedModifier(KFPlayerReplicationInfo KFPRI, KFGameReplicationInfo KFGRI){
|
||||
if(HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillEnforcerUnstoppable'))
|
||||
return class'NiceSkillEnforcerUnstoppable'.default.speedMult;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
static function bool CanBePulled(KFPlayerReplicationInfo KFPRI){
|
||||
if(HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillEnforcerUnstoppable'))
|
||||
return false;
|
||||
return super.CanBePulled(KFPRI);
|
||||
}
|
||||
|
||||
static function float SlowingModifier(KFPlayerReplicationInfo KFPRI){
|
||||
if(HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillEnforcerUnstoppable'))
|
||||
return 0.0;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
static function string GetCustomLevelInfo(byte Level){
|
||||
return default.CustomLevelInfo;
|
||||
}
|
||||
defaultproperties
|
||||
{
bNewTypePerk=True
|
||||
SkillGroupA(0)=Class'NicePack.NiceSkillEnforcerUnstoppable'
SkillGroupA(1)=Class'NicePack.NiceSkillEnforcerBombard'
SkillGroupA(2)=Class'NicePack.NiceSkillEnforcerFullCounter'
SkillGroupA(4)=Class'NicePack.NiceSkillEnforcerZEDBarrage'
|
||||
SkillGroupB(0)=Class'NicePack.NiceSkillEnforcerUnshakable'
SkillGroupB(1)=Class'NicePack.NiceSkillEnforcerMultitasker'
SkillGroupB(2)=Class'NicePack.NiceSkillEnforcerDetermination'
SkillGroupB(4)=Class'NicePack.NiceSkillEnforcerZEDJuggernaut'
progressArray0(0)=100
progressArray0(1)=1000
progressArray0(2)=3000
progressArray0(3)=10000
progressArray0(4)=30000
progressArray0(5)=100000
progressArray0(6)=200000
DefaultDamageType=Class'NicePack.NiceDamageTypeVetEnforcer'
OnHUDIcons(0)=(PerkIcon=Texture'KillingFloorHUD.Perks.Perk_Support',StarIcon=Texture'KillingFloorHUD.HUD.Hud_Perk_Star',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(1)=(PerkIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Support_Gold',StarIcon=Texture'KillingFloor2HUD.Perk_Icons.Hud_Perk_Star_Gold',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(2)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Support_Green',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Green',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(3)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Support_Blue',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Blue',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(4)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Support_Purple',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Purple',DrawColor=(B=255,G=255,R=255,A=255))
OnHUDIcons(5)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Support_Orange',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Orange',DrawColor=(B=255,G=255,R=255,A=255))
CustomLevelInfo="Level up by doing damage with perked weapons|60% better penetration with all weapons"
PerkIndex=1
OnHUDIcon=Texture'KillingFloorHUD.Perks.Perk_Support'
OnHUDGoldIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Support_Gold'
VeterancyName="Enforcer"
Requirements(0)="Required experience for the next level: %x"
|
||||
}
|
4
sources/Perks/Enforcer/NiceVetSupportExp.uc
Normal file
4
sources/Perks/Enforcer/NiceVetSupportExp.uc
Normal file
@ -0,0 +1,4 @@
|
||||
class NiceVetSupportExp extends SRCustomProgressInt;
|
||||
defaultproperties
|
||||
{
ProgressName="Enforcer exp."
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
class NiceSkillEnforcerBombard extends NiceSkill
|
||||
abstract;
|
||||
var float stunMult;
|
||||
var float spreadMult;
|
||||
defaultproperties
|
||||
{
stunMult=3.000000
spreadMult=0.500000
SkillName="Bombard"
SkillEffects="Your perked weapons are 3 times as good at stunning."
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
class NiceSkillEnforcerMultitasker extends NiceSkill
|
||||
abstract;
|
||||
var float reloadSlowDown;
|
||||
defaultproperties
|
||||
{
reloadSlowDown=5.000000
SkillName="Multitasker"
SkillEffects="Reload holstered weapons at five times as much time."
|
||||
}
|
5
sources/Perks/Enforcer/Skills/NiceSkillSupportAntiZed.uc
Normal file
5
sources/Perks/Enforcer/Skills/NiceSkillSupportAntiZed.uc
Normal file
@ -0,0 +1,5 @@
|
||||
class NiceSkillSupportAntiZed extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
SkillName="Anti-zed rounds"
SkillEffects="When shotgun pellets pass screaming siren, they gain x4 damage boost."
|
||||
}
|
5
sources/Perks/Enforcer/Skills/NiceSkillSupportArmory.uc
Normal file
5
sources/Perks/Enforcer/Skills/NiceSkillSupportArmory.uc
Normal file
@ -0,0 +1,5 @@
|
||||
class NiceSkillSupportArmory extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
bBroadcast=True
SkillName="Armory"
SkillEffects="Once per wave your team-mates will receive armored jacket when they run out of armor."
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
class NiceSkillSupportBigGameHunter extends NiceSkillGenAmmo
|
||||
abstract;
|
||||
var float damageBonus;
|
||||
defaultproperties
|
||||
{
damageBonus=1.600000
SkillName="Big-game hunter"
SkillEffects="Gain 60% damage bonus with grenades, but carry 5 grenades less."
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class NiceSkillSupportCautious extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
SkillName="Cautious"
SkillEffects="Your grenades won't explode if you're too close to them."
|
||||
}
|
18
sources/Perks/Enforcer/Skills/NiceSkillSupportDiversity.uc
Normal file
18
sources/Perks/Enforcer/Skills/NiceSkillSupportDiversity.uc
Normal file
@ -0,0 +1,18 @@
|
||||
class NiceSkillSupportDiversity extends NiceSkill
|
||||
abstract;
|
||||
var int bonusWeight;
|
||||
static function UpdateWeight(NicePlayerController nicePlayer){
|
||||
local NiceHumanPawn nicePawn;
|
||||
if(nicePawn == none || nicePawn.KFPRI == none) return;
|
||||
nicePawn.maxCarryWeight = nicePawn.default.maxCarryWeight;
|
||||
if(nicePawn.KFPRI.clientVeteranSkill != none)
nicePawn.maxCarryWeight += nicePawn.KFPRI.clientVeteranSkill.static.AddCarryMaxWeight(nicePawn.KFPRI);
|
||||
}
|
||||
function static SkillSelected(NicePlayerController nicePlayer){
|
||||
UpdateWeight(nicePlayer);
|
||||
}
|
||||
function static SkillDeSelected(NicePlayerController nicePlayer){
|
||||
UpdateWeight(nicePlayer);
|
||||
}
|
||||
defaultproperties
|
||||
{
bonusWeight=5
SkillName="Diversity"
SkillEffects="Gain +5 weight slots."
|
||||
}
|
7
sources/Perks/Enforcer/Skills/NiceSkillSupportGraze.uc
Normal file
7
sources/Perks/Enforcer/Skills/NiceSkillSupportGraze.uc
Normal file
@ -0,0 +1,7 @@
|
||||
class NiceSkillSupportGraze extends NiceSkill
|
||||
abstract;
|
||||
var float hsBonusZoneMult;
|
||||
var float grazeDamageMult;
|
||||
defaultproperties
|
||||
{
hsBonusZoneMult=1.500000
grazeDamageMult=0.750000
SkillName="Graze"
SkillEffects="Your perked projectile can hit zeds' extended head zone for 75% of damage even if they miss the normal one."
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
class NiceSkillSupportObsessive extends NiceSkill
|
||||
abstract;
|
||||
var float reloadLevel;
|
||||
var float reloadBonus;
|
||||
defaultproperties
|
||||
{
reloadLevel=0.650000
ReloadBonus=1.500000
SkillName="Obsessive"
SkillEffects="Reload 50% faster when you lack at most 35% of bullets in the magazine."
|
||||
}
|
5
sources/Perks/Enforcer/Skills/NiceSkillSupportSlugs.uc
Normal file
5
sources/Perks/Enforcer/Skills/NiceSkillSupportSlugs.uc
Normal file
@ -0,0 +1,5 @@
|
||||
class NiceSkillSupportSlugs extends NiceSkill
|
||||
abstract;
|
||||
defaultproperties
|
||||
{
SkillName="Slugs"
SkillEffects="Pellets shots replaced by slugs on shotguns."
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user