//============================================================================= // SRHumanPawn //============================================================================= class SRHumanPawn extends KFHumanPawn_Story; var ClientPerkRepLink PerkLink; var transient float CashTossTimer,LongTossCashTimer; var transient byte LongTossCashCount; // Override bad coding in StoryGame simulated function Fire( optional float F ) { Super(Pawn).Fire(F); } function AddDefaultInventory() { if( KFStoryGameInfo(Level.Game)!=none ) Super.AddDefaultInventory(); else Super(KFHumanPawn).AddDefaultInventory(); } function ServerSellAmmo( Class AClass ); final function bool HasWeaponClass( class IC, optional out Inventory Res ) { local Inventory I; for ( I=Inventory; I!=None; I=I.Inventory ) if( I.Class==IC ) { Res = I; return true; } return false; } final function ClientPerkRepLink FindStats() { local LinkedReplicationInfo L; if( Controller==None || Controller.PlayerReplicationInfo==None ) return None; for( L=Controller.PlayerReplicationInfo.CustomReplicationInfo; L!=None; L=L.NextReplicationInfo ) if( ClientPerkRepLink(L)!=None ) return ClientPerkRepLink(L); return None; } function ServerBuyWeapon( Class WClass, float Weight ) { local float Price; local int OtherPrice; local Inventory I,OI; local class SecType; if( !CanBuyNow() || Class(WClass)==None || Class(WClass.Default.PickupClass)==None || HasWeaponClass(WClass) ) Return; // Validate if allowed to buy that weapon. if( PerkLink==None ) PerkLink = FindStats(); if( PerkLink!=None && !PerkLink.CanBuyPickup(Class(WClass.Default.PickupClass)) ) return; Price = class(WClass.Default.PickupClass).Default.Cost; if ( KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none ) Price *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), WClass.Default.PickupClass); Weight = Class(WClass).Default.Weight; if( class'DualWeaponsManager'.Static.IsDualWeapon(WClass,SecType) ) { if( WClass!=class'Dualies' && HasWeaponClass(SecType,OI) ) { Weight-=SecType.Default.Weight; Price*=0.5f; OtherPrice = KFWeapon(OI).SellValue; if( OtherPrice==-1 ) { OtherPrice = class(SecType.Default.PickupClass).Default.Cost * 0.75; if ( KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none ) OtherPrice *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), SecType.Default.PickupClass); } } } else if( class'DualWeaponsManager'.Static.HasDualies(WClass,Inventory) ) return; Price = int(Price); // Truncuate price. if( Weight>0 && !CanCarry(Weight) ) { ClientMessage("Error: "$WClass.Name$" is too heavy ("$CurrentWeight$"+"$Weight$">"$MaxCarryWeight$")"); return; } if ( PlayerReplicationInfo.Score"$int(PlayerReplicationInfo.Score)$")"); Return; } I = Spawn(WClass); if ( I != none ) { if ( KFGameType(Level.Game) != none ) KFGameType(Level.Game).WeaponSpawned(I); KFWeapon(I).UpdateMagCapacity(PlayerReplicationInfo); KFWeapon(I).FillToInitialAmmo(); KFWeapon(I).SellValue = Price * 0.75; if( OtherPrice>0 ) KFWeapon(I).SellValue+=OtherPrice; I.GiveTo(self); PlayerReplicationInfo.Score -= Price; ClientForceChangeWeapon(I); } else ClientMessage("Error: "$WClass.Name$" failed to spawn."); SetTraderUpdate(); } function ServerSellWeapon( Class WClass ) { local Inventory I; local KFWeapon NewWep; local float Price; local class SecType; if ( !CanBuyNow() || Class(WClass) == none || Class(WClass.Default.PickupClass)==none || Class(WClass).Default.bKFNeverThrow ) { SetTraderUpdate(); Return; } for ( I = Inventory; I != none; I = I.Inventory ) { if ( I.Class==WClass ) { if ( KFWeapon(I) != none && KFWeapon(I).SellValue != -1 ) Price = KFWeapon(I).SellValue; else { Price = (class(WClass.default.PickupClass).default.Cost * 0.75); if ( KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none ) Price *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), WClass.Default.PickupClass); } if( class'DualWeaponsManager'.Static.IsDualWeapon(WClass,SecType) ) { NewWep = Spawn(SecType); if( WClass!=class'Dualies' ) { Price *= 0.5f; NewWep.SellValue = Price; } NewWep.GiveTo(self); } if ( I==Weapon || I==PendingWeapon ) { ClientCurrentWeaponSold(); } PlayerReplicationInfo.Score += int(Price); I.Destroy(); SetTraderUpdate(); if ( KFGameType(Level.Game)!=none ) KFGameType(Level.Game).WeaponDestroyed(WClass); return; } } } simulated function AddBlur(Float BlurDuration, float Intensity) { if( KFPC!=none && Viewport(KFPC.Player)!=None ) Super.AddBlur(BlurDuration,Intensity); } simulated function DoHitCamEffects(vector HitDirection, float JarrScale, float BlurDuration, float JarDurationScale ) { if( KFPC!=none && Viewport(KFPC.Player)!=None ) Super.DoHitCamEffects(HitDirection,JarrScale,BlurDuration,JarDurationScale); } simulated function StopHitCamEffects() { if( KFPC!=none && Viewport(KFPC.Player)!=None ) Super.StopHitCamEffects(); } exec function TossCash( int Amount ) { // To fix cash tossing exploit. if( CashTossTimer DamageType, vector HitLoc) { local vector shotDir, hitLocRel, deathAngVel, shotStrength; local float maxDim; local string RagSkelName; local KarmaParamsSkel skelParams; local bool PlayersRagdoll; local PlayerController pc; if ( Level.NetMode != NM_DedicatedServer ) { // Is this the local player's ragdoll? if(OldController != None) pc = PlayerController(OldController); if( pc != none && pc.ViewTarget == self ) PlayersRagdoll = true; // In low physics detail, if we were not just controlling this pawn, // and it has not been rendered in 3 seconds, just destroy it. if( !PlayersRagdoll && (Level.TimeSeconds-LastRenderTime)>3 ) { GoTo'NonRagdoll'; return; } // Try and obtain a rag-doll setup. Use optional 'override' one out of player record first, then use the species one. if( RagdollOverride != "") RagSkelName = RagdollOverride; else if(Species != None) RagSkelName = Species.static.GetRagSkelName( GetMeshName() ); else RagSkelName = "Male1"; // Otherwise assume it is Male1 ragdoll were after here. KMakeRagdollAvailable(); if( KIsRagdollAvailable() && RagSkelName != "" ) { skelParams = KarmaParamsSkel(KParams); skelParams.KSkeleton = RagSkelName; // Stop animation playing. StopAnimating(true); if( DamageType != None ) { if ( DamageType.default.bLeaveBodyEffect ) TearOffMomentum = vect(0,0,0); if( DamageType.default.bKUseOwnDeathVel ) { RagDeathVel = DamageType.default.KDeathVel; RagDeathUpKick = DamageType.default.KDeathUpKick; } } // Set the dude moving in direction he was shot in general shotDir = Normal(GetTearOffMomemtum()); shotStrength = RagDeathVel * shotDir; // Calculate angular velocity to impart, based on shot location. hitLocRel = TakeHitLocation - Location; // We scale the hit location out sideways a bit, to get more spin around Z. hitLocRel.X *= RagSpinScale; hitLocRel.Y *= RagSpinScale; // If the tear off momentum was very small for some reason, make up some angular velocity for the pawn if( VSize(GetTearOffMomemtum()) < 0.01 ) { //Log("TearOffMomentum magnitude of Zero"); deathAngVel = VRand() * 18000.0; } else deathAngVel = RagInvInertia * (hitLocRel Cross shotStrength); // Set initial angular and linear velocity for ragdoll. // Scale horizontal velocity for characters - they run really fast! if ( DamageType.Default.bRubbery ) skelParams.KStartLinVel = vect(0,0,0); if ( Damagetype.default.bKUseTearOffMomentum ) skelParams.KStartLinVel = GetTearOffMomemtum() + Velocity; else { skelParams.KStartLinVel.X = 0.6 * Velocity.X; skelParams.KStartLinVel.Y = 0.6 * Velocity.Y; skelParams.KStartLinVel.Z = 1.0 * Velocity.Z; skelParams.KStartLinVel += shotStrength; } // If not moving downwards - give extra upward kick if( !DamageType.default.bLeaveBodyEffect && !DamageType.Default.bRubbery && (Velocity.Z > -10) ) skelParams.KStartLinVel.Z += RagDeathUpKick; if ( DamageType.Default.bRubbery ) { Velocity = vect(0,0,0); skelParams.KStartAngVel = vect(0,0,0); } else { skelParams.KStartAngVel = deathAngVel; // Set up deferred shot-bone impulse maxDim = Max(CollisionRadius, CollisionHeight); skelParams.KShotStart = TakeHitLocation - (1 * shotDir); skelParams.KShotEnd = TakeHitLocation + (2*maxDim*shotDir); skelParams.KShotStrength = RagShootStrength; } // If this damage type causes convulsions, turn them on here. if(DamageType != None && DamageType.default.bCauseConvulsions) { RagConvulseMaterial=DamageType.default.DamageOverlayMaterial; skelParams.bKDoConvulsions = true; } // Turn on Karma collision for ragdoll. KSetBlockKarma(true); // Set physics mode to ragdoll. // This doesn't actaully start it straight away, it's deferred to the first tick. SetPhysics(PHYS_KarmaRagdoll); // If viewing this ragdoll, set the flag to indicate that it is 'important' if( PlayersRagdoll ) skelParams.bKImportantRagdoll = true; skelParams.bRubbery = DamageType.Default.bRubbery; bRubbery = DamageType.Default.bRubbery; skelParams.KActorGravScale = RagGravScale; return; } // jag } NonRagdoll: // non-ragdoll death fallback LifeSpan = 0.2f; } function float AssessThreatTo(KFMonsterController Monster, optional bool CheckDistance) { local float ThreatRating; local Inventory CurInv; local KF_StoryInventoryItem StoryInv; ThreatRating = FMax(Super(KFHumanPawn).AssessThreatTo(Monster,CheckDistance),0.1f); /* Factor in story Items which adjust your desirability to ZEDs */ for ( CurInv = Inventory; CurInv != none; CurInv = CurInv.Inventory ) { StoryInv = KF_StoryInventoryItem(CurInv); if(StoryInv != none) ThreatRating *= StoryInv.AIThreatModifier; } return ThreatRating; } simulated final function int GetFloorSurface() { local int SurfaceTypeID; local actor A; local vector HL,HN,Start,End; local material FloorMat; if ( (Base!=None) && (!Base.IsA('LevelInfo')) && (Base.SurfaceType!=0) ) SurfaceTypeID = Base.SurfaceType; else { Start = Location - Vect(0,0,1)*CollisionHeight; End = Start - Vect(0,0,16); A = Trace(hl,hn,End,Start,false,,FloorMat); if (FloorMat !=None) SurfaceTypeID = FloorMat.SurfaceType; } return SurfaceTypeID; } simulated function Sound GetSound(xPawnSoundGroup.ESoundType soundType) { local int SurfaceTypeID; if( SoundGroupClass==None ) SoundGroupClass = Class'KFMaleSoundGroup'; if( soundType == EST_Land || soundType == EST_Jump ) SurfaceTypeID = GetFloorSurface(); return SoundGroupClass.static.GetSound(soundType, SurfaceTypeID); } // The player wants to switch to weapon group number F. simulated function SwitchWeapon(byte F) { local Weapon DesiredWeap; local bool AllowSwitch; // Fixed script warnings. if( Weapon!=None && Weapon.Inventory!=None ) DesiredWeap = Weapon.Inventory.WeaponChange(F, false); if(DesiredWeap == none && Inventory!=None ) DesiredWeap = Inventory.WeaponChange(F, true); if(DesiredWeap != none) AllowSwitch = AllowHoldWeapon(DesiredWeap); if( AllowSwitch ) Super(KFPawn).SwitchWeapon(F); } simulated function tick(float DeltaTime) { local KF_StoryPRI PRI; super(KFPawn).Tick(DeltaTime); if( IsLocallyControlled() && !bUsingHitBlur && BlurFadeOutTime > 0 ) { BlurFadeOutTime -= DeltaTime; DeltaTime = BlurFadeOutTime/StartingBlurFadeOutTime * CurrentBlurIntensity; if( BlurFadeOutTime <= 0 ) { BlurFadeOutTime = 0; StopHitCamEffects(); } else if( bUseBlurEffect && KFPC!=none && !KFPC.PostFX_IsReady() ) { if( CameraEffectFound != none ) UnderWaterBlur(CameraEffectFound).BlurAlpha = Lerp( DeltaTime, 255, UnderWaterBlur(CameraEffectFound).default.BlurAlpha ); else KFPC.SetBlur(DeltaTime); } } /* Replicated Location stuff - for tracking this pawn's position to display icons when its not relevant */ PRI = KF_StoryPRI(PlayerReplicationInfo); if(PRI != none && PRI.GetFloatingIconMat() != none) { if(Role == Role_Authority) // server authoritative { if(PRI.GetOwnerPawn() != self) { PRI.SetOwnerPawn(self); PRI.NetUpdateTime = Level.TimeSeconds - 1; } KF_StoryPRI(PlayerReplicationInfo).SetReplicatedPawnLoc(GetHoverIconPosition()); } else if(bDeleteMe || bPendingDelete) // simulated proxy. { PRI.SetOwnerPawn(none); PRI.NetUpdateTime = Level.TimeSeconds - 1; } } } simulated function SetWeaponAttachment(WeaponAttachment NewAtt) { local byte i; Super.SetWeaponAttachment(NewAtt); if( KFWeaponAttachment(WeaponAttachment)!=None ) { // Veryify valid animations. for( i=0; i<4; ++i ) { DoubleJumpAnims[i] = TakeoffAnims[i]; if( !HasAnim(MovementAnims[i]) ) MovementAnims[i] = Default.MovementAnims[i]; if( !HasAnim(WalkAnims[i]) ) MovementAnims[i] = Default.WalkAnims[i]; } if( !HasAnim(IdleWeaponAnim) ) MovementAnims[i] = Default.IdleWeaponAnim; if( !HasAnim(IdleRestAnim) ) MovementAnims[i] = Default.IdleRestAnim; if( !HasAnim(IdleChatAnim) ) MovementAnims[i] = Default.IdleChatAnim; } } defaultproperties { InvisMaterial=Shader'KF_Specimens_Trip_T.patriarch_invisible' WallDodgeAnims(0)="JumpF_Takeoff" WallDodgeAnims(1)="JumpL_Takeoff" WallDodgeAnims(2)="JumpL_Takeoff" WallDodgeAnims(3)="JumpR_Takeoff" MovementAnims(0)="JogF_Pipe" MovementAnims(1)="JogB_Pipe" MovementAnims(2)="JogL_Pipe" MovementAnims(3)="JogR_Pipe" SwimAnims(0)="WalkF_Flamethrower" SwimAnims(1)="WalkB_Flamethrower" SwimAnims(2)="WalkL_Flamethrower" SwimAnims(3)="WalkR_Flamethrower" CrouchAnims(0)="CHwalkF_Pipe" CrouchAnims(1)="CHwalkB_Pipe" CrouchAnims(2)="CHwalkL_Pipe" CrouchAnims(3)="CHwalkR_Pipe" WalkAnims(0)="WalkF_Flamethrower" WalkAnims(1)="WalkB_Flamethrower" WalkAnims(2)="WalkL_Flamethrower" WalkAnims(3)="WalkR_Flamethrower" DoubleJumpAnims(0)="JumpF_Takeoff" DoubleJumpAnims(1)="JumpL_Takeoff" DoubleJumpAnims(2)="JumpL_Takeoff" DoubleJumpAnims(3)="JumpR_Takeoff" IdleWeaponAnim="Idle_Pipe" IdleRestAnim="Idle_Pipe" IdleChatAnim="Idle_Pipe" }