1167 lines
32 KiB
Ucode
1167 lines
32 KiB
Ucode
//=============================================================================
|
|
// KFPawn - Assault
|
|
//=============================================================================
|
|
class KFHumanPawn extends KFPawn;
|
|
|
|
//#exec OBJ LOAD FILE=KFCharacters.utx
|
|
//#exec OBJ LOAD FILE=KFSoldiers.ukx
|
|
var float DrugBonusMovement;
|
|
var bool bOnDrugs;
|
|
var Emitter Blood;
|
|
var Sound BreathingSound;
|
|
//var int BreathingTime;
|
|
var Sound MiscSound; //So I can get the damn thing to shutup if the players dead.
|
|
|
|
//var UnderWaterBlur myHitBlur;
|
|
var bool bUsingHitBlur;
|
|
var float StopBlurTime;
|
|
var float BlurFadeOutTime; // Tracks how long we've spend fading out the blur
|
|
var(Blur) float StartingBlurFadeOutTime; // How long to spend fading out the blur
|
|
var(Blur) float NewSchoolHitBlurIntensity; // How intense to make the new school hit blur when you are hit
|
|
var config bool bUseBlurEffect; // Whether or not the blur effect should be used
|
|
var float CurrentBlurIntensity; // The Currently used blur intensity
|
|
|
|
// Jarring
|
|
var() float JarrMoveMag; // Magnitude to move the player
|
|
var() float JarrMoveRate; // Rate at which the player oscillates
|
|
var() float JarrMoveDuration; // scalar duration of the movement
|
|
var() float JarrRotateMag; // Magnitude the player 'rolls'
|
|
var() float JarrRotateRate; // Rate at which the player oscillates/rolls around
|
|
var() float JarrRotateDuration; // scalar duration of the roll
|
|
|
|
var int SpeedAdjustment; // Give our brave melee players a little bit more under the hood.
|
|
var float BaseMeleeIncrease;
|
|
|
|
var int InventorySpeedModifier; // Modifer to the player's speed based on the weapon they are carrying
|
|
var() float HealthSpeedModifier; // The maximum percentage of the default movement speed to reduce speed based on how low the player's health is
|
|
var() float WeightSpeedModifier; // The maximum percentage of the default movement speed to reduce speed based on how much weight the player is carrying
|
|
|
|
var int ScoreCounter; // Once it hits two, reset 3 second score in GRI
|
|
|
|
var bool bAimingRifle;
|
|
|
|
|
|
var CameraEffect CameraEffectFound;
|
|
|
|
var () float MaxCarryWeight;
|
|
|
|
var float CurrentWeight;
|
|
var bool bMeBeDoomed;
|
|
var int AlphaAmount ; // Amount of Alpha for Cash bonus HUD.
|
|
|
|
var() Material InjuredOverlay,CriticalOverlay;
|
|
|
|
var KFPlayerController KFPC;
|
|
|
|
var () int TorchBatteryLife;
|
|
var bool bTorchOn; // HUD var only.
|
|
var int TempScore; // temporary score.
|
|
|
|
var float LastDyingMessageTime;
|
|
var float DyingMessageDelay;
|
|
|
|
/* Should this pawn be allowed to switch Weapons ? */
|
|
var bool bLockWeaponSelection;
|
|
|
|
replication
|
|
{
|
|
reliable if ( bNetDirty && (Role == Role_Authority) )
|
|
bAimingRifle;
|
|
|
|
reliable if ( bNetDirty && (Role == Role_Authority) && bNetOwner )
|
|
CurrentWeight,MaxCarryWeight,AlphaAmount,bTorchOn,TorchBatteryLife,bOnDrugs,
|
|
InventorySpeedModifier;
|
|
|
|
reliable if(RemoteRole == ROLE_AutonomousProxy)
|
|
DoHitCamEffects, StopHitCamEffects;
|
|
|
|
reliable if(Role < ROLE_Authority)
|
|
SetAiming,ServerTossCarriedItems;
|
|
}
|
|
|
|
simulated function Setup(xUtil.PlayerRecord rec, optional bool bLoadNow)
|
|
{
|
|
super.Setup(rec, bLoadNow);
|
|
|
|
if( class<SoldierSpeciesRobot>(Species) != none )
|
|
{
|
|
BreathingSound = class'KFDARSoundGroup'.default.BreathingSound;
|
|
}
|
|
else if( class<AshHardingSpecies>(Species) != none )
|
|
{
|
|
BreathingSound = class'KFFemaleSoundGroup'.default.BreathingSound;
|
|
}
|
|
log(BreathingSound);
|
|
}
|
|
|
|
function VeterancyChanged()
|
|
{
|
|
local Inventory I;
|
|
local KFPlayerReplicationInfo KFPRI;
|
|
local int MaxAmmo;
|
|
|
|
MaxCarryWeight = Default.MaxCarryWeight;
|
|
|
|
KFPRI = KFPlayerReplicationInfo(PlayerReplicationInfo);
|
|
|
|
if ( KFPRI != none && KFPRI.ClientVeteranSkill != none )
|
|
{
|
|
MaxCarryWeight += KFPRI.ClientVeteranSkill.Static.AddCarryMaxWeight(KFPRI);
|
|
}
|
|
|
|
if ( CurrentWeight > MaxCarryWeight ) // Now carrying too much, drop something.
|
|
{
|
|
for ( I = Inventory; I != none; I = I.Inventory )
|
|
{
|
|
if ( KFWeapon(I) != none && !KFWeapon(I).bKFNeverThrow )
|
|
{
|
|
I.Velocity = Velocity;
|
|
I.DropFrom(Location + VRand() * 10);
|
|
if ( CurrentWeight <= MaxCarryWeight )
|
|
{
|
|
break; // Drop weapons until player is capable of carrying them all.
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Make sure nothing is over the Max Ammo amount when changing Veterancy
|
|
for ( I = Inventory; I != none; I = I.Inventory )
|
|
{
|
|
if ( Ammunition(I) != none )
|
|
{
|
|
MaxAmmo = Ammunition(I).default.MaxAmmo;
|
|
|
|
if ( KFPRI != none && KFPRI.ClientVeteranSkill != none )
|
|
{
|
|
MaxAmmo = float(MaxAmmo) * KFPRI.ClientVeteranSkill.static.AddExtraAmmoFor(KFPRI, Ammunition(I).Class);
|
|
}
|
|
|
|
if ( Ammunition(I).AmmoAmount > MaxAmmo )
|
|
{
|
|
Ammunition(I).AmmoAmount = MaxAmmo;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
event PreBeginPlay()
|
|
{
|
|
Super.PreBeginPlay();
|
|
SetTimer(1.5,true);
|
|
|
|
}
|
|
|
|
// Just changed to pendingWeapon
|
|
simulated function ChangedWeapon()
|
|
{
|
|
if(PendingWeapon != none &&
|
|
AllowHoldWeapon(KFWeapon(PendingWeapon)))
|
|
{
|
|
Super.ChangedWeapon();
|
|
|
|
// Experience Level relate stuff .
|
|
if ( Weapon != none && KFWeapon(Weapon).bSpeedMeUp )
|
|
{
|
|
// Adjust Melee weapon speed bonuses depending on perk.
|
|
BaseMeleeIncrease = default.BaseMeleeIncrease;
|
|
|
|
if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none )
|
|
{
|
|
BaseMeleeIncrease += KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.Static.GetMeleeMovementSpeedModifier(KFPlayerReplicationInfo(PlayerReplicationInfo));
|
|
}
|
|
|
|
InventorySpeedModifier = ((default.GroundSpeed * BaseMeleeIncrease) - (KFWeapon(Weapon).Weight * 2));
|
|
}
|
|
else if ( Weapon == none || !KFWeapon(Weapon).bSpeedMeUp )
|
|
{
|
|
InventorySpeedModifier = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PendingWeapon = none;
|
|
}
|
|
}
|
|
|
|
function ServerChangedWeapon(Weapon OldWeapon, Weapon NewWeapon)
|
|
{
|
|
super.ServerChangedWeapon(OldWeapon,NewWeapon);
|
|
|
|
// Experience Level relate stuff .
|
|
if( Weapon!= none && KFWeapon(Weapon).bSpeedMeUp )
|
|
{
|
|
// Adjust Melee weapon speed bonuses depending on perk.
|
|
BaseMeleeIncrease = default.BaseMeleeIncrease;
|
|
|
|
if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none )
|
|
{
|
|
BaseMeleeIncrease += KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.Static.GetMeleeMovementSpeedModifier(KFPlayerReplicationInfo(PlayerReplicationInfo));
|
|
}
|
|
|
|
InventorySpeedModifier = ((default.GroundSpeed * BaseMeleeIncrease) - (KFWeapon(Weapon).Weight * 2));
|
|
}
|
|
else if (Weapon == none || !KfWeapon(Weapon).bSpeedMeUp)
|
|
{
|
|
InventorySpeedModifier = 0;
|
|
}
|
|
}
|
|
|
|
simulated event ModifyVelocity(float DeltaTime, vector OldVelocity)
|
|
{
|
|
local float WeightMod, HealthMod;
|
|
local float EncumbrancePercentage;
|
|
local Inventory Inv;
|
|
|
|
super.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)/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 * HealthMod;
|
|
GroundSpeed *= WeightMod;
|
|
GroundSpeed += InventorySpeedModifier;
|
|
|
|
if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none )
|
|
{
|
|
GroundSpeed *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetMovementSpeedModifier(KFPlayerReplicationInfo(PlayerReplicationInfo), KFGameReplicationInfo(Level.GRI));
|
|
}
|
|
|
|
/* Give the pawn's inventory items a chance to modify his movement speed */
|
|
for( Inv=Inventory; Inv!=None; Inv=Inv.Inventory )
|
|
{
|
|
GroundSpeed *= Inv.GetMovementModifierFor(self);
|
|
}
|
|
}
|
|
}
|
|
|
|
Simulated function tick(float DeltaTime)
|
|
{
|
|
local float BlurAmount;
|
|
|
|
super.Tick(deltaTime);
|
|
|
|
if (KFPC != none)
|
|
{
|
|
if (KFPlayerReplicationInfo(KFPC.PlayerReplicationInfo).ThreeSecondScore > 0 && AlphaAmount > 0)
|
|
AlphaAmount -=2;
|
|
|
|
if (AlphaAmount <= 0)
|
|
{
|
|
KFPlayerReplicationInfo(KFPC.PlayerReplicationInfo).ThreeSecondScore = 0;
|
|
ScoreCounter = 0;
|
|
}
|
|
}
|
|
|
|
if( IsLocallyControlled() )
|
|
{
|
|
if( !bUsingHitBlur && BlurFadeOutTime > 0 )
|
|
{
|
|
BlurFadeOutTime -= deltaTime;
|
|
BlurAmount = BlurFadeOutTime/StartingBlurFadeOutTime * CurrentBlurIntensity;
|
|
|
|
if( BlurFadeOutTime <= 0 )
|
|
{
|
|
BlurFadeOutTime = 0;
|
|
StopHitCamEffects();
|
|
}
|
|
else
|
|
{
|
|
if( bUseBlurEffect )
|
|
{
|
|
if( KFPC == none || !KFPC.PostFX_IsReady() )
|
|
{
|
|
|
|
if( CameraEffectFound != none )
|
|
{
|
|
UnderWaterBlur(CameraEffectFound).BlurAlpha = Lerp( BlurAmount, 255, UnderWaterBlur(CameraEffectFound).default.BlurAlpha );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
KFPC.SetBlur(BlurAmount);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function SetAiming(bool IsAiming)
|
|
{
|
|
bAimingRifle = IsAiming;
|
|
}
|
|
|
|
simulated event HandleWhizSound()
|
|
{
|
|
local float Intensity;
|
|
|
|
// Don't play whizz sounds for bots, or from other players
|
|
if ( IsHumanControlled() && IsLocallyControlled() )
|
|
{
|
|
Spawn(class'ROBulletWhiz',,, mWhizSoundLocation);
|
|
|
|
//log("DistSquared of whiz is "$VSizeSquared(GetBoneCoords(HeadBone).Origin - mWhizSoundLocation));
|
|
|
|
Intensity = 1.0 - ((FMin(VSizeSquared(GetBoneCoords(HeadBone).Origin - mWhizSoundLocation),3600.0))/3600.0); // 3600 = (60*60) = Radius of bullet whiz cylinder squared
|
|
|
|
//log("Intensity of whiz is "$Intensity);
|
|
|
|
AddBlur(0.15, Intensity/2);
|
|
}
|
|
}
|
|
|
|
simulated function AddBlur(Float BlurDuration, float Intensity)
|
|
{
|
|
if( KFPC == none )
|
|
{
|
|
return;
|
|
}
|
|
if(!bUsingHitBlur)
|
|
{
|
|
// If we can't handle the post processing shaders, just do an old style motion blur effect
|
|
if( bUseBlurEffect )
|
|
{
|
|
StartingBlurFadeOutTime = BlurDuration;
|
|
BlurFadeOutTime = StartingBlurFadeOutTime;
|
|
|
|
if( CurrentBlurIntensity < Intensity )
|
|
{
|
|
CurrentBlurIntensity = Intensity;
|
|
}
|
|
|
|
if( !KFPC.PostFX_IsReady() )
|
|
{
|
|
if ( CameraEffectFound == none )
|
|
{
|
|
FindCameraEffect(class 'KFmod.UnderWaterBlur');
|
|
}
|
|
|
|
UnderWaterBlur(CameraEffectFound).BlurAlpha = UnderWaterBlur(CameraEffectFound).default.BlurAlpha;
|
|
}
|
|
else
|
|
{
|
|
KFPC.SetBlur(CurrentBlurIntensity);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Timer()
|
|
{
|
|
//local Actor WallActor;
|
|
//local KFBloodSplatter Streak;
|
|
//local vector WallHit, WallNormal;
|
|
|
|
if (BurnDown > 0)
|
|
{
|
|
LastBurnDamage *= 0.5;
|
|
TakeFireDamage(LastBurnDamage, BurnInstigator);
|
|
}
|
|
else
|
|
{
|
|
RemoveFlamingEffects();
|
|
StopBurnFX();
|
|
}
|
|
|
|
// Flashlight Drain
|
|
if ( KFWeapon(Weapon)!=none && KFWeapon(Weapon).FlashLight!=none )
|
|
{
|
|
// Increment / Decrement battery life
|
|
if (KFWeapon(Weapon).FlashLight.bHasLight && TorchBatteryLife > 0)
|
|
TorchBatteryLife -= 10;
|
|
else if (!KFWeapon(Weapon).FlashLight.bHasLight && TorchBatteryLife < default.TorchBatteryLife)
|
|
{
|
|
TorchBatteryLife += 20;
|
|
if ( TorchBatteryLife > default.TorchBatteryLife )
|
|
{
|
|
TorchBatteryLife = default.TorchBatteryLife;
|
|
}
|
|
}
|
|
}
|
|
else if( TorchBatteryLife<default.TorchBatteryLife )
|
|
{
|
|
TorchBatteryLife += 20;
|
|
if ( TorchBatteryLife > default.TorchBatteryLife )
|
|
{
|
|
TorchBatteryLife = default.TorchBatteryLife;
|
|
}
|
|
}
|
|
|
|
if (Controller != none)
|
|
{
|
|
if(KFPC != none )
|
|
{
|
|
bOnDrugs = false;
|
|
// Update for the scoreboards.
|
|
if (Health <= 0)
|
|
{
|
|
PlaySound(MiscSound,SLOT_Talk);
|
|
return;
|
|
}
|
|
if ( Health < HealthMax * 0.25 )
|
|
{
|
|
PlaySound(BreathingSound, SLOT_Talk, ((50-Health)/5)*TransientSoundVolume,,TransientSoundRadius,, false);
|
|
// Commenting this streak code out because it doesn't work and spams the log - Ramm
|
|
//WallActor = Trace(WallHit, WallNormal, Location - 50 * Velocity, Location, false);
|
|
//Streak= spawn(class 'KFMod.KFBloodSplatter',,,vect(0,0,0), Rotation);
|
|
//if (Streak != none)
|
|
// Streak.SetRotation(Rotator(Velocity));
|
|
}
|
|
|
|
// Accuracy vs. Movement tweakage! - Alex
|
|
if (KFWeapon(Weapon) != none)
|
|
KFWeapon(Weapon).AccuracyUpdate(vsize(Velocity));
|
|
}
|
|
}
|
|
|
|
// TODO: WTF? central here
|
|
// Instantly set the animation to arms at sides Idle if we've got no weapon (rather than Pointing an invisible gun!)
|
|
if (Weapon != none)
|
|
{
|
|
if (WeaponAttachment(Weapon.ThirdPersonActor) == none && VSize(Velocity) <= 0)
|
|
IdleWeaponAnim = IdleRestAnim;
|
|
}
|
|
else if (Weapon == none)
|
|
IdleWeaponAnim = IdleRestAnim;
|
|
|
|
|
|
}
|
|
|
|
simulated function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
|
|
{
|
|
if( Controller!=None && Controller.bGodMode )
|
|
return;
|
|
|
|
if ( KFMonster(InstigatedBy) != none )
|
|
{
|
|
KFMonster(InstigatedBy).bDamagedAPlayer = true;
|
|
}
|
|
|
|
// Don't allow momentum from a player shooting a player
|
|
if( InstigatedBy != none && KFHumanPawn(InstigatedBy) != none )
|
|
{
|
|
Momentum = vect(0,0,0);
|
|
}
|
|
|
|
Super.TakeDamage(Damage,instigatedBy,hitlocation,momentum,damageType);
|
|
|
|
//Bloody Overlays
|
|
if ((Health-Damage) <= 0.5*HealthMax)
|
|
SetOverlayMaterial(InjuredOverlay,0, true);
|
|
|
|
if ( Role == ROLE_Authority && Level.Game.NumPlayers > 1 && Health < 0.25 * HealthMax && Level.TimeSeconds - LastDyingMessageTime > DyingMessageDelay )
|
|
{
|
|
// Tell everyone we're dying
|
|
PlayerController(Instigator.Controller).Speech('AUTO', 6, "");
|
|
|
|
LastDyingMessageTime = Level.TimeSeconds;
|
|
}
|
|
|
|
if( Controller==none || PlayerController(Controller)==None )
|
|
return;
|
|
}
|
|
|
|
function TakeBileDamage()
|
|
{
|
|
local vector BileVect;
|
|
local int RandBileDamage;
|
|
local int actualDamage;
|
|
local vector HitMomentum;
|
|
|
|
RandBileDamage = 2+Rand(3);
|
|
|
|
Super(XPawn).TakeDamage(RandBileDamage, BileInstigator, Location, vect(0,0,0), LastBileDamagedByType);
|
|
healthtoGive-=5;
|
|
|
|
HitMomentum = vect(0,0,0);
|
|
actualDamage = Level.Game.ReduceDamage(RandBileDamage, self, BileInstigator, Location, HitMomentum, LastBileDamagedByType);
|
|
|
|
if( actualDamage <= 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//TODO: move this sanity check to DoHitCamEffect?
|
|
if(Controller == none || PlayerController(Controller) == None)
|
|
return;
|
|
|
|
if(Controller.bGodMode)
|
|
return;
|
|
|
|
BileVect.X=frand();
|
|
BileVect.Y=frand();
|
|
BileVect.Z=frand();
|
|
|
|
if( class<DamTypeBileDeckGun>(LastBileDamagedByType) != none )
|
|
{
|
|
DoHitCamEffects( BileVect, 0.25, 0.75, 0.5 );
|
|
}
|
|
else
|
|
{
|
|
DoHitCamEffects( BileVect, 0.35, 2.0,1.0 );
|
|
}
|
|
}
|
|
|
|
// Overridden to support view shake changes
|
|
function PlayTakeHit(vector HitLocation, int Damage, class<DamageType> DamageType)
|
|
{
|
|
local vector direction;
|
|
local rotator InvRotation;
|
|
local float jarscale;
|
|
|
|
super.PlayTakeHit( HitLocation, Damage, DamageType );
|
|
|
|
// for standalone and client
|
|
// Cooney
|
|
if ( Level.NetMode != NM_DedicatedServer )
|
|
{
|
|
// Get the approximate direction
|
|
// that the hit went into the body
|
|
direction = Location - HitLocation;
|
|
// No up-down jarring effects since
|
|
// I dont have the barrel valocity
|
|
direction.Z = 0.0f;
|
|
direction = normal(direction);
|
|
|
|
// We need to rotate the jarring direction
|
|
// in screen space so basically the
|
|
// exact opposite of the player's pawn's
|
|
// rotation.
|
|
InvRotation.Yaw = -Rotation.Yaw;
|
|
InvRotation.Roll = -Rotation.Roll;
|
|
InvRotation.Pitch = -Rotation.Pitch;
|
|
direction = direction >> InvRotation;
|
|
|
|
jarscale = 0.1f + (Damage/10.0f);
|
|
if ( jarscale > 1.0f )
|
|
{
|
|
jarscale = 1.0f;
|
|
}
|
|
|
|
DoHitCamEffects(direction,jarscale,2.0,1.0);
|
|
}
|
|
}
|
|
|
|
simulated function DoHitCamEffects(vector HitDirection, float JarrScale, float BlurDuration, float JarDurationScale )
|
|
{
|
|
local vector localShakeMoveMag;
|
|
local vector localShakeMoveRate;
|
|
local vector localShakeRotateMag;
|
|
local vector localShakeRotateRate;
|
|
|
|
if( KFPC == none )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( bUseBlurEffect )
|
|
{
|
|
if( !KFPC.PostFX_IsReady() )
|
|
{
|
|
CurrentBlurIntensity = 1.0;
|
|
}
|
|
else
|
|
{
|
|
CurrentBlurIntensity = NewSchoolHitBlurIntensity;
|
|
}
|
|
|
|
AddBlur(BlurDuration,CurrentBlurIntensity);
|
|
}
|
|
|
|
// Shake Moving
|
|
//
|
|
localShakeMoveMag = HitDirection * JarrMoveMag;
|
|
//
|
|
localShakeMoveRate.X = JarrMoveRate;
|
|
localShakeMoveRate.Y = JarrMoveRate;
|
|
localShakeMoveRate.Z = JarrMoveRate;
|
|
//
|
|
// Unfortunately, the HitDirection
|
|
// only transfers maximum offsets to
|
|
// the shake offset max. I have to
|
|
// check it's sign and move that into
|
|
// the rate so it moves the right direction.
|
|
if ( HitDirection.X < 0 )
|
|
localShakeMoveRate.X *= -1;
|
|
if ( HitDirection.Y < 0 )
|
|
localShakeMoveRate.Y *= -1;
|
|
if ( HitDirection.Z < 0 )
|
|
localShakeMoveRate.Z *= -1;
|
|
|
|
// Shake Rotation
|
|
//
|
|
localShakeRotateMag.X = JarrRotateMag*-HitDirection.X;
|
|
localShakeRotateMag.Z = JarrRotateMag*HitDirection.Y;
|
|
//
|
|
localShakeRotateRate.X = JarrRotateRate*-HitDirection.X;
|
|
localShakeRotateRate.Z = JarrRotateRate*HitDirection.Y;
|
|
|
|
KFPC.ShakeView(localShakeRotateMag*JarrScale,
|
|
localShakeRotateRate*(2.0f-JarrScale),
|
|
JarrRotateDuration * JarDurationScale,
|
|
localShakeMoveMag*JarrScale,
|
|
localShakeMoveRate*(2.0f-JarrScale),
|
|
JarrMoveDuration * JarDurationScale);
|
|
}
|
|
|
|
simulated function StopHitCamEffects()
|
|
{
|
|
CurrentBlurIntensity=0.0;
|
|
|
|
if( CameraEffectFound != none )
|
|
{
|
|
RemoveCameraEffect(CameraEffectFound);
|
|
}
|
|
|
|
if( KFPC != none )
|
|
{
|
|
KFPC.StopViewShaking();
|
|
KFPC.SetBlur(0);
|
|
}
|
|
}
|
|
|
|
simulated function died(Controller Killer, class<DamageType> damageType, vector HitLocation)
|
|
{
|
|
StopHitCamEffects();
|
|
super.Died(Killer, damageType, HitLocation);
|
|
}
|
|
|
|
simulated function Destroyed()
|
|
{
|
|
StopHitCamEffects();
|
|
Super.Destroyed();
|
|
}
|
|
|
|
|
|
simulated function CameraEffect FindCameraEffect(class<CameraEffect> CameraEffectClass)
|
|
{
|
|
local PlayerController PlayerControllerLocal;
|
|
local int i;
|
|
|
|
PlayerControllerLocal = Level.GetLocalPlayerController();
|
|
if ( PlayerControllerLocal != None )
|
|
{
|
|
for (i = 0; i < PlayerControllerLocal.CameraEffects.Length; i++)
|
|
if ( PlayerControllerLocal.CameraEffects[i].Class == CameraEffectClass )
|
|
{
|
|
CameraEffectFound = PlayerControllerLocal.CameraEffects[i];
|
|
break;
|
|
}
|
|
if ( CameraEffectFound == None )
|
|
CameraEffectFound = CameraEffect(Level.ObjectPool.AllocateObject(CameraEffectClass));
|
|
if ( CameraEffectFound != None )
|
|
PlayerControllerLocal.AddCameraEffect(CameraEffectFound);
|
|
}
|
|
return CameraEffectFound;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
// RemoveCameraEffect
|
|
//
|
|
// Removes one reference to the CameraEffect from the CameraEffects array. If
|
|
// there are any more references to the same CameraEffect object, they remain
|
|
// there. The CameraEffect will be put back in the ObjectPool if no other
|
|
// references to it are left in the CameraEffects array.
|
|
//=============================================================================
|
|
|
|
simulated function RemoveCameraEffect(CameraEffect CameraEffect)
|
|
{
|
|
local PlayerController PlayerControllerLocal;
|
|
local int i;
|
|
|
|
PlayerControllerLocal = Level.GetLocalPlayerController();
|
|
if ( PlayerControllerLocal != None ) {
|
|
PlayerControllerLocal.RemoveCameraEffect(CameraEffect);
|
|
for (i = 0; i < PlayerControllerLocal.CameraEffects.Length; i++)
|
|
if ( PlayerControllerLocal.CameraEffects[i] == CameraEffect ) {
|
|
log(CameraEffect@"still in CameraEffects array");
|
|
return;
|
|
}
|
|
log("Freeing"@CameraEffect);
|
|
Level.ObjectPool.FreeObject(CameraEffect);
|
|
CameraEffectFound = none;
|
|
}
|
|
}
|
|
|
|
|
|
simulated function PrevWeapon()
|
|
{
|
|
if ( Level.Pauser != None )
|
|
return;
|
|
|
|
if ( Weapon == None && Controller != None )
|
|
{
|
|
Controller.SwitchToBestWeapon();
|
|
return;
|
|
}
|
|
|
|
if ( PendingWeapon != None )
|
|
{
|
|
if ( PendingWeapon.bForceSwitch )
|
|
return;
|
|
PendingWeapon = Inventory.PrevWeapon(None, PendingWeapon);
|
|
}
|
|
else
|
|
{
|
|
PendingWeapon = Inventory.PrevWeapon(None, Weapon);
|
|
}
|
|
|
|
if ( PendingWeapon != None )
|
|
Weapon.PutDown();
|
|
}
|
|
|
|
/* NextWeapon()
|
|
- switch to next inventory group weapon
|
|
*/
|
|
simulated function NextWeapon()
|
|
{
|
|
if ( Level.Pauser != None )
|
|
return;
|
|
|
|
if ( Weapon == None && Controller != None )
|
|
{
|
|
Controller.SwitchToBestWeapon();
|
|
return;
|
|
}
|
|
|
|
if ( PendingWeapon != None )
|
|
{
|
|
if ( PendingWeapon.bForceSwitch )
|
|
return;
|
|
PendingWeapon = Inventory.NextWeapon(None, PendingWeapon);
|
|
}
|
|
else
|
|
{
|
|
PendingWeapon = Inventory.NextWeapon(None, Weapon);
|
|
}
|
|
if ( PendingWeapon != None && Weapon != none )
|
|
Weapon.PutDown();
|
|
}
|
|
|
|
//This is a terribly ugly hack which allows us to silently give
|
|
//weapons to pawns in the case of buy menu consumables
|
|
function SilentGiveWeapon(string aClassName )
|
|
{
|
|
local class<Weapon> WeaponClass;
|
|
local Weapon NewWeapon;
|
|
|
|
WeaponClass = class<Weapon>(DynamicLoadObject(aClassName, class'Class'));
|
|
|
|
if( FindInventoryType(WeaponClass) != None )
|
|
return;
|
|
newWeapon = Spawn(WeaponClass);
|
|
|
|
if( newWeapon != None && KFWeapon(newWeapon) != None)
|
|
KFWeapon(newWeapon).SilentGiveTo(self);
|
|
else if(newWeapon != none)
|
|
newWeapon.GiveTo(self);
|
|
}
|
|
|
|
function bool AddInventory( inventory NewItem )
|
|
{
|
|
if( !super.AddInventory(NewItem) )
|
|
return false;
|
|
|
|
if( KFWeapon(NewItem) != none )
|
|
{
|
|
CurrentWeight += KFWeapon(NewItem).Weight;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Remove Item from this pawn's inventory, if it exists.
|
|
function DeleteInventory( inventory Item )
|
|
{
|
|
local Inventory I;
|
|
local bool bFoundItem;
|
|
|
|
if ( Role != ROLE_Authority )
|
|
{
|
|
return;
|
|
}
|
|
|
|
for ( I = Inventory; I != none; I = I.Inventory )
|
|
{
|
|
if ( I == Item )
|
|
{
|
|
bFoundItem = true;
|
|
}
|
|
}
|
|
|
|
if ( bFoundItem )
|
|
{
|
|
if ( KFWeapon(Item) != none )
|
|
{
|
|
CurrentWeight -= KFWeapon(Item).Weight;
|
|
}
|
|
}
|
|
|
|
super.DeleteInventory(Item);
|
|
}
|
|
|
|
function Drugs()
|
|
{
|
|
|
|
// Still not sure what to do with this.
|
|
// It's some sort of drug heightened adrenal state where the player can run faster etc...
|
|
// Amusingly, it's incremental. So each "hit" (call of this function :P) will send you into
|
|
// a further....enhanced state for the duration of the drug's life (30 seconds max).
|
|
|
|
// call it like so :
|
|
// bOnDrugs = true;
|
|
// Drugs();
|
|
|
|
if(bOnDrugs)
|
|
{
|
|
// Log("You're on Some Drugs");
|
|
DrugBonusMovement = 150;
|
|
Groundspeed +=DrugBonusMovement;
|
|
|
|
PlaySound(BreathingSound, SLOT_Talk, TransientSoundVolume,,TransientSoundRadius,, false);
|
|
Weapon.StartBerserk();
|
|
|
|
KFPC.ShakeView(vect(30,-30,30),vect(200,-300,200),30,vect(-30,30,30),vect(300,-200,200),30);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function AddDefaultInventory()
|
|
{
|
|
local int i;
|
|
|
|
// Add this code in if you want to force bots to spawn without a weapon
|
|
/*if( !IsHumanControlled() )
|
|
{
|
|
return;
|
|
}*/
|
|
|
|
if ( KFSPGameType(Level.Game) != none )
|
|
{
|
|
Level.Game.AddGameSpecificInventory(self);
|
|
|
|
if ( Inventory != none )
|
|
Inventory.OwnerEvent('LoadOut');
|
|
|
|
return;
|
|
}
|
|
|
|
if ( IsLocallyControlled() )
|
|
{
|
|
for ( i = 0; i < 16; i++ )
|
|
if ( RequiredEquipment[i] != "" )
|
|
CreateInventory(RequiredEquipment[i]);
|
|
|
|
if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none )
|
|
{
|
|
KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.AddDefaultInventory(KFPlayerReplicationInfo(PlayerReplicationInfo), self);
|
|
}
|
|
|
|
for ( i = 0; i < 16; i++ )
|
|
if ( (SelectedEquipment[i] == 1) && (OptionalEquipment[i] != "") )
|
|
CreateInventory(OptionalEquipment[i]);
|
|
|
|
Level.Game.AddGameSpecificInventory(self);
|
|
}
|
|
else
|
|
{
|
|
Level.Game.AddGameSpecificInventory(self);
|
|
|
|
for ( i = 15; i >= 0; i-- )
|
|
if ( (SelectedEquipment[i] == 1) && (OptionalEquipment[i] != "") )
|
|
CreateInventory(OptionalEquipment[i]);
|
|
|
|
if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none )
|
|
{
|
|
KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.AddDefaultInventory(KFPlayerReplicationInfo(PlayerReplicationInfo), self);
|
|
}
|
|
|
|
for ( i = 15; i >= 0; i-- )
|
|
if ( RequiredEquipment[i] != "" )
|
|
CreateInventory(RequiredEquipment[i]);
|
|
}
|
|
|
|
// HACK FIXME
|
|
if ( Inventory != None )
|
|
Inventory.OwnerEvent('LoadOut');
|
|
|
|
Controller.ClientSwitchToBestWeapon();
|
|
}
|
|
|
|
function CreateInventoryVeterancy(string InventoryClassName, float SellValue)
|
|
{
|
|
local Inventory Inv;
|
|
local class<Inventory> InventoryClass;
|
|
|
|
InventoryClass = Level.Game.BaseMutator.GetInventoryClass(InventoryClassName);
|
|
if( (InventoryClass!=None) && (FindInventoryType(InventoryClass)==None) )
|
|
{
|
|
Inv = Spawn(InventoryClass);
|
|
if( Inv != none )
|
|
{
|
|
Inv.GiveTo(self);
|
|
if ( Inv != none )
|
|
Inv.PickupFunction(self);
|
|
|
|
if ( KFWeapon(Inv) != none )
|
|
{
|
|
KFWeapon(Inv).SellValue = SellValue;
|
|
}
|
|
|
|
if ( KFGameType(Level.Game) != none )
|
|
{
|
|
KFGameType(Level.Game).WeaponSpawned(Inv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function bool CanCarry( float Weight )
|
|
{
|
|
if(Weight <= 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return ((CurrentWeight+Weight)<=MaxCarryWeight);
|
|
}
|
|
|
|
function bool PerformDodge(eDoubleClickDir DoubleClickMove, vector Dir, vector Cross)
|
|
{
|
|
Return False;
|
|
}
|
|
|
|
function bool ShowStalkers()
|
|
{
|
|
if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none )
|
|
{
|
|
return KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.Static.ShowStalkers(KFPlayerReplicationInfo(PlayerReplicationInfo));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function float GetStalkerViewDistanceMulti()
|
|
{
|
|
if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none )
|
|
{
|
|
return KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.Static.GetStalkerViewDistanceMulti(KFPlayerReplicationInfo(PlayerReplicationInfo));
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
/* ============ AI - Monster threat assessment functionality ==============================
|
|
Clamped from -1 to 100, where 100 is the most threatening ==================================
|
|
===========================================================================================*/
|
|
|
|
function float AssessThreatTo(KFMonsterController Monster, optional bool CheckDistance)
|
|
{
|
|
if(Monster == none || Monster.Pawn == none)
|
|
{
|
|
return -1.f;
|
|
}
|
|
|
|
if(CheckDistance)
|
|
{
|
|
// 5000 == 100m, gives us a nice range of values
|
|
return 5000.f / VSize(Monster.Pawn.Location - Location);
|
|
}
|
|
|
|
return -1.f;
|
|
}
|
|
|
|
/* Returns true if this pawn is able to hold a weapon of the supplied type */
|
|
simulated function bool AllowHoldWeapon(Weapon InWeapon)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// The player wants to switch to weapon group number F.
|
|
simulated function SwitchWeapon(byte F)
|
|
{
|
|
local Weapon DesiredWeap;
|
|
local bool AllowSwitch;
|
|
|
|
DesiredWeap = Weapon.Inventory.WeaponChange(F, false);
|
|
if(DesiredWeap == none )
|
|
{
|
|
DesiredWeap = Inventory.WeaponChange(F, true);
|
|
}
|
|
|
|
if(DesiredWeap != none)
|
|
{
|
|
AllowSwitch = AllowHoldWeapon(DesiredWeap);
|
|
}
|
|
|
|
if(AllowSwitch)
|
|
{
|
|
Super.SwitchWeapon(F);
|
|
}
|
|
}
|
|
|
|
function bool AllowWeaponSwitching()
|
|
{
|
|
return !bLockWeaponSelection ;
|
|
}
|
|
|
|
/* @todo - unique bools ? */
|
|
function bool AllowGrenadeTossing()
|
|
{
|
|
return !bLockWeaponSelection ;
|
|
}
|
|
|
|
/* @todo - unique bools ? */
|
|
function bool AllowQuickHealing()
|
|
{
|
|
return !bLockWeaponSelection;
|
|
}
|
|
|
|
simulated exec function QuickHeal()
|
|
{
|
|
if(AllowQuickHealing())
|
|
{
|
|
Super.QuickHeal();
|
|
}
|
|
}
|
|
|
|
simulated function TossCarriedItems()
|
|
{
|
|
if(Role < Role_Authority)
|
|
{
|
|
ServerTossCarriedItems();
|
|
}
|
|
else
|
|
{
|
|
InternalTossCarriedItems();
|
|
}
|
|
}
|
|
|
|
function ServerTossCarriedItems()
|
|
{
|
|
InternalTossCarriedItems();
|
|
}
|
|
|
|
simulated function InternalTossCarriedItems()
|
|
{
|
|
local Inventory Inv;
|
|
local Vector X,Y,Z;
|
|
|
|
GetAxes(Rotation,X,Y,Z);
|
|
|
|
for( Inv=Inventory; Inv!=None; Inv=Inv.Inventory )
|
|
{
|
|
if(Inv.IsThrowable())
|
|
{
|
|
Inv.Velocity = Vector(Rotation)* 250.f ;
|
|
Inv.DropFrom(Location + 0.8 * CollisionRadius * X - 0.5 * CollisionRadius * Y);
|
|
}
|
|
}
|
|
}
|
|
|
|
simulated function bool IsCarryingThrowableInventory()
|
|
{
|
|
local Inventory Inv;
|
|
for( Inv=Inventory; Inv!=None; Inv=Inv.Inventory )
|
|
{
|
|
if(Inv.IsThrowable())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function ThrowGrenade()
|
|
{
|
|
if(AllowGrenadeTossing())
|
|
{
|
|
Super.ThrowGrenade();
|
|
}
|
|
}
|
|
|
|
// toss out a weapon
|
|
function TossWeapon(Vector TossVel)
|
|
{
|
|
TossCarriedItems();
|
|
Super.TossWeapon(TossVel);
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
BreathingSound=Sound'KFPlayerSound.Malebreath'
|
|
BaseMeleeIncrease=0.200000
|
|
MaxCarryWeight=15.000000
|
|
InjuredOverlay=Shader'KFCharacters.BloodiedShader'
|
|
CriticalOverlay=Shader'KFCharacters.BloodiedShader'
|
|
bCanDodgeDoubleJump=False
|
|
MultiJumpRemaining=0
|
|
MaxMultiJump=0
|
|
RequiredEquipment(0)="KFMod.Knife" // Knife
|
|
RequiredEquipment(1)="KFMod.Single"// Single
|
|
RequiredEquipment(2)="KFMod.Frag"
|
|
RequiredEquipment(3)="KFMod.Syringe" // Syringe
|
|
RequiredEquipment(4)="KFMod.Welder" // Welder
|
|
//RequiredEquipment(5)="KFMod.FakeSyringe" // Welder
|
|
bCanDoubleJump=False
|
|
bCanWallDodge=False
|
|
bUseBlurEffect=true
|
|
|
|
AccelRate=1000.0
|
|
AirControl=+0.15
|
|
GroundSpeed=200.0
|
|
WaterSpeed=200.000000
|
|
AirSpeed=230.000000
|
|
JumpZ=325.000000
|
|
MaxFallSpeed=600.000000
|
|
BaseEyeHeight=44.0
|
|
EyeHeight=44.0
|
|
CrouchHeight=34.000000
|
|
|
|
ControllerClass=Class'KFMod.KFInvasionBot'
|
|
CrouchTurnRightAnim="CrouchR"
|
|
CrouchTurnLeftAnim="CrouchL"
|
|
bDramaticLighting=False
|
|
Mesh=SkeletalMesh'KF_Soldier_Trip.British_Soldier1'//SkeletalMesh'KFSoldiers.Soldier'
|
|
Skins(0)=Combiner'KF_Soldier_Trip_T.Uniforms.brit_soldier_I_cmb'//Texture'KFCharacters.DavinSkin'
|
|
//Skins(1)=Shader'KFCharacters.GasMaskShader'
|
|
CollisionHeight=50.000000
|
|
|
|
TorchBatteryLife=500
|
|
AmbientGlow=0
|
|
|
|
TurnRightAnim="TurnR"
|
|
TurnLeftAnim="TurnL"
|
|
|
|
StartingBlurFadeOutTime=0.5
|
|
NewSchoolHitBlurIntensity=0.8
|
|
|
|
HealthSpeedModifier=0.3
|
|
WeightSpeedModifier=0.13
|
|
|
|
DyingMessageDelay=10.0
|
|
|
|
// Jarring settings
|
|
JarrMoveMag=50.0
|
|
JarrMoveRate=200.0
|
|
JarrMoveDuration=3.0
|
|
JarrRotateMag=1000.0
|
|
JarrRotateRate=10000.0
|
|
JarrRotateDuration=4.0
|
|
|
|
HeadRadius=+7.0
|
|
HeadHeight=2.0
|
|
}
|