905 lines
35 KiB
Ucode
905 lines
35 KiB
Ucode
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;
|
|
var float nextFreezeTime;
|
|
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;
|
|
var float bruteTimer;
|
|
var float quadDamageRemaining;
|
|
replication{
|
|
reliable if(Role == ROLE_Authority)
|
|
headshotStack, hmgShieldLevel, forcedZedTimeCountDown, maniacTimeout, invincibilityTimer, safeMeleeMisses, ffScale,
|
|
currentCalibrationState, calibrationScore, gunslingerTimer, quadDamageRemaining;
|
|
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;
|
|
}
|
|
|
|
// TODO remove this Scrn func
|
|
function ReplaceRequiredEquipment()
|
|
{
|
|
RequiredEquipment[0] = string(class'NiceMachete');
|
|
RequiredEquipment[1] = string(class'Nice9mmPlus');
|
|
RequiredEquipment[2] = string(class'ScrnFrag');
|
|
RequiredEquipment[3] = string(class'ScrnSyringe');
|
|
RequiredEquipment[4] = string(class'KFMod.Welder');
|
|
}
|
|
|
|
simulated function int CalculateCalibrationScore(){
|
|
local float accuracy;
|
|
accuracy = (float(calibrationHits)) / (float(calibrationTotalShots));
|
|
if(calibrationTotalShots <= 0)
|
|
return 3;
|
|
// Very low accuracy (<60%) or not enough shots (<2) - 1 star
|
|
if(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(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;
|
|
if (niceVet == class'NiceVetEnforcer')
|
|
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 NiceMonster niceZed;
|
|
local NiceWeapon niceWeap;
|
|
local WeaponTimePair newPair;
|
|
local array<WeaponTimePair> newWTPList;
|
|
local NicePlayerController nicePlayer;
|
|
|
|
nicePlayer = NicePlayerController(Controller);
|
|
|
|
if (Role == Role_AUTHORITY)
|
|
{
|
|
// Brutal carnage
|
|
if (bruteTimer > 0)
|
|
{
|
|
bruteTimer -= deltaTime;
|
|
if (bruteTimer <= 0)
|
|
{
|
|
if(nicePlayer != none && nicePlayer.abilityManager != none)
|
|
{
|
|
nicePlayer.abilityManager.SetAbilityState(1, ASTATE_COOLDOWN);
|
|
}
|
|
}
|
|
}
|
|
// Ice giant NiceSkillEnforcerZEDIceGiant
|
|
if( nicePlayer != none && nicePlayer.IsZedTimeActive()
|
|
&& nextFreezeTime < level.timeSeconds
|
|
&& class'NiceVeterancyTypes'.static.hasSkill(
|
|
nicePlayer, class'NiceSkillEnforcerZEDIceGiant'))
|
|
{
|
|
nextFreezeTime =
|
|
level.timeSeconds + class'NiceCryoNade'.default.freezeRate;
|
|
foreach CollidingActors(
|
|
class 'NiceMonster', niceZed,
|
|
class'NiceCryoNade'.default.damageRadius,
|
|
location)
|
|
{
|
|
if(niceZed.Health <= 0) {
|
|
continue;
|
|
}
|
|
niceZed.TakeDamage(
|
|
class'NiceCryoNade'.default.damage,
|
|
self,
|
|
niceZed.location,
|
|
vect(0,0,0),
|
|
class'NiceCryoNade'.default.myDamageType);
|
|
}
|
|
}
|
|
// 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'NiceSkillCommandoRegeneration')){
|
|
if(health < healthMax)
|
|
regenTime += deltaTime;
|
|
while(regenTime > class'NiceSkillCommandoRegeneration'.default.regenFrequency){
|
|
if(health < healthMax)
|
|
health += 1;
|
|
else
|
|
regenTime = 0.0;
|
|
regenTime -= class'NiceSkillCommandoRegeneration'.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;
|
|
|
|
if(!class'NiceVeterancyTypes'.static.hasSkill(NicePlayerController(Controller), class'NiceSkillEnforcerMultitasker'))
|
|
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 NiceGameType NiceGT;
|
|
|
|
NiceGT = NiceGameType(Level.Game);
|
|
if (NicePlayerController(Controller) == none)
|
|
return false;
|
|
if (NiceGT != none && NiceGT.NicePackMutator != none
|
|
&& NiceGT.NicePackMutator.bIsPreGame)
|
|
return true;
|
|
|
|
// skip Scrn code!
|
|
return super(KFPawn).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'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()))
|
|
{
|
|
super.ThrowGrenade();
|
|
return;
|
|
}
|
|
|
|
if(playerGrenade == none)
|
|
playerGrenade = FindPlayerGrenade();
|
|
if(playerGrenade != none && playerGrenade.HasAmmo()){
|
|
niceWeap.clientGrenadeState = GN_TempDown;
|
|
niceWeap.PutDown();
|
|
}
|
|
}
|
|
simulated function HandleNadeThrowAnim()
|
|
{
|
|
if(NiceM14EBRBattleRifle(Weapon) != none || NiceMaulerRifle(Weapon) != none)
|
|
SetAnimAction('Frag_M14');
|
|
else if(NiceWinchester(Weapon) != none)
|
|
SetAnimAction('Frag_Winchester');
|
|
else if(Crossbow(Weapon) != none)
|
|
SetAnimAction('Frag_Crossbow');
|
|
else if(NiceM99SniperRifle(Weapon) != none)
|
|
SetAnimAction('Frag_M4203');
|
|
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'NiceSkillEnforcerUnstoppable'))
|
|
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'NiceSkillCommandoAdrenalineShot'.default.speedBoost) +
|
|
(100 * class'NiceSkillCommandoAdrenalineShot'.default.speedBoost - class'NiceSkillCommandoAdrenalineShot'.default.minHealth);
|
|
adrSpeedBonus /= (100 - class'NiceSkillCommandoAdrenalineShot'.default.minHealth);
|
|
adrSpeedBonus = FMin(adrSpeedBonus, class'NiceSkillCommandoAdrenalineShot'.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 float oldHealthToGive;
|
|
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'NiceSkillCommandoAdrenalineShot'.default.resistBoost) +
|
|
(100 * class'NiceSkillCommandoAdrenalineShot'.default.resistBoost - class'NiceSkillCommandoAdrenalineShot'.default.minHealth);
|
|
adrResistance /= (100 - class'NiceSkillCommandoAdrenalineShot'.default.minHealth);
|
|
adrResistance = FMin(adrResistance, class'NiceSkillCommandoAdrenalineShot'.default.resistBoost);
|
|
adrResistance = FMax(adrResistance, 1.0);
|
|
Damage *= adrResistance;
|
|
}
|
|
if(nicePlayer != none && nicePlayer.IsZedTimeActive()
|
|
&& class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillZerkZEDUnbreakable'))
|
|
return;
|
|
lastHMGShieldUpdateTime = Level.TimeSeconds;
|
|
if(damageType != none && class<NiceDamTypeDrug>(damageType) == none){
|
|
bOldArmorStops = damageType.default.bArmorStops;
|
|
if(class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillEnforcerCoating'))
|
|
damageType.default.bArmorStops = true;
|
|
}
|
|
lastExplosionDistance = 0.0; // hack, but scrn fucks with usotherwise
|
|
oldHealthToGive = healthToGive; // remember this to restore this value, in case we are using safeguard skill
|
|
super.TakeDamage(Damage, InstigatedBy, hitLocation, Momentum, damageType, HitIndex);
|
|
if (class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillHeavySafeguard')) {
|
|
healthToGive = oldHealthToGive;
|
|
clientHealthToGive = healthToGive;
|
|
}
|
|
// 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 + 1, 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);
|
|
}
|
|
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);
|
|
}
|
|
|
|
// added copy-cated function to disable some log
|
|
simulated function Setup(xUtil.PlayerRecord rec, optional bool bLoadNow)
|
|
{
|
|
local ScrnPlayerController PC;
|
|
local string CN;
|
|
|
|
PC = ScrnPlayerController(Controller);
|
|
if ( PC != none && IsLocallyControlled() )
|
|
{
|
|
// check this only on player side, because it stores
|
|
// RedCharacter & BlueCharacter in the config
|
|
CN = rec.DefaultName;
|
|
if ( !PC.ValidateCharacter(CN) ) {
|
|
// character invalid, change it valid one, which was set up in ValidateCharacter()
|
|
rec = class'xUtil'.static.FindPlayerRecord(CN);
|
|
PC.ChangeCharacter(CN);
|
|
}
|
|
}
|
|
|
|
super(KFPawn).Setup(rec, bLoadNow);
|
|
|
|
if( class<SoldierSpeciesRobot>(Species) != none )
|
|
{
|
|
BreathingSound = class'KFDARSoundGroup'.default.BreathingSound;
|
|
}
|
|
else if( class<AshHardingSpecies>(Species) != none )
|
|
{
|
|
BreathingSound = class'KFFemaleSoundGroup'.default.BreathingSound;
|
|
}
|
|
// disable the log!!!
|
|
// log(BreathingSound);
|
|
}
|
|
|
|
|
|
defaultproperties
|
|
{
|
|
defaultInvincibilityDuration=2.000000
|
|
BaseMeleeIncrease=0.000000
|
|
}
|