//============================================================================= // KFPawn //============================================================================= class KFPawn extends xPawn dependsOn(xPawnGibGroup); #exec OBJ LOAD FILE=Inf_Weapons.uax #exec OBJ LOAD FILE=Inf_Player.uax // From XPawn var(Gib) class GibGroupClass; var(Gib) int GibCountCalf; var(Gib) int GibCountForearm; var(Gib) int GibCountHead; var(Gib) int GibCountTorso; var(Gib) int GibCountUpperArm; var string KFBSkin; var string KFFSkin; var mesh KFSMesh; var bool bCanBeHealed; var float healthToGive, lastHealTime; var bool bResetingAnimAct; var float NextBileTime, BileFrequency, AnimActResetTime; var int BileCount; var Pawn BileInstigator; var class LastBileDamagedByType; var name ClientIdleWeaponAnim; var bool bThrowingNade; // ARE WE ALREADY THROWING ONE? var Inventory SecondaryItem; // Player Health Bar textures var Texture TeamBeaconTexture, NoEntryTexture; var Material TeamBeaconBorderMaterial; var class LastHitDamType; // records the last kind of damge you took (for siren hack) var (Global) Mesh SafeMesh; // Fire Related var int BurnDown ; // Number of times our zombie must suffer Fire Damage. var bool bAshen; // is our Zed crispy yet? var class BurnEffect; // The appearance of the flames we are attaching to our Zed. var int LastBurnDamage; // Record the last amount of Fire damage the pawn suffered. var Emitter ItBUURRNNNS; var bool bBurnified; var bool bBurnApplied; var pawn LastDamagedBy,BurnInstigator; var() globalconfig bool bDetailedShadows,bRealDeathType,bRealtimeShadows; var KFLevelRules LevRls; var PlayerReplicationInfo OwnerPRI; var byte bIsQuickHealing; /* Feet adjusters ================*/ var bool bHasFootAdjust; var globalconfig bool bDoAdjustFeet; var float MaxZHeight,MinZHeight,OldAdjust[2]; var KFPawnFootAdjuster Adjuster; var Class FeetAdjSpec; // Animations const NUM_FIRE_ANIMS = 4; var name FireAnims[NUM_FIRE_ANIMS]; var name FireAltAnims[NUM_FIRE_ANIMS]; var name FireCrouchAnims[NUM_FIRE_ANIMS]; var name FireCrouchAltAnims[NUM_FIRE_ANIMS]; var name HitAnims[4]; var name PostFireBlendStandAnim; var name PostFireBlendCrouchAnim; // Footstepping var(Sounds) float FootStepSoundRadius; // The radius that footstep sounds can be heard var(Sounds) float QuietFootStepVolume; // The amount to scale footstepsounds when the player is walking slowly var(Sounds) sound SoundFootsteps[20]; // Indexed by ESurfaceTypes (sorry about the literal). var(Bob) float BobSpeedModifier; // A general scalar for walkbob/footstep sound speed var(Bob) float BobScaleModifier; // A general scalar for walkbob intensity var bool bMovementDisabled; // The player can't move right now var float StopDisabledTime; // When the player can move again; // Gore var SeveredAppendageAttachment SeveredLeftArm; // The meaty attachments that get attached when body parts are blown off var SeveredAppendageAttachment SeveredRightArm; // The meaty attachments that get attached when body parts are blown off var SeveredAppendageAttachment SeveredLeftLeg; // The meaty attachments that get attached when body parts are blown off var SeveredAppendageAttachment SeveredRightLeg; // The meaty attachments that get attached when body parts are blown off var SeveredAppendageAttachment SeveredHead; // The meaty attachments that get attached when body parts are blown off var(Gore) float SeveredArmAttachScale; // The drawscale of the arm gore attachement var(Gore) float SeveredLegAttachScale; // The drawscale of the leg gore attachement var(Gore) float SeveredHeadAttachScale; // The drawscale of the head gore attachement var class NeckSpurtEmitterClass; // class of the chopped off head neck emitter var class LimbSpurtEmitterClass; // class of the chopped off head neck emitter var class SeveredArmAttachClass; // class of the severed arm for this role var class SeveredLegAttachClass; // class of the severed arm for this role var class SeveredHeadAttachClass; // class of the severed arm for this role var class BleedingEmitterClass; // class of the bleeding emitter var class ProjectileBloodSplatClass; // class of the wall bloodsplat from a projectile's impact var class DetachedArmClass; // class of detached arm to spawn for this pawn. Modified by the RoleInfo to match the player model var class DetachedLegClass; // class of detached arm to spawn for this pawn. Modified by the RoleInfo to match the player model var bool bLeftArmGibbed; // LeftArm is already blown off var bool bRightArmGibbed; // RightArm is already blown off var bool bLeftLegGibbed; // LeftLeg is already blown off var bool bRightLegGibbed; // RightLeg is already blown off var class ObliteratedEffectClass; // class of detached arm to spawn for this pawn. Modified by the RoleInfo to match the player model var(Sounds) sound DecapitationSound; //The sound of this players head exploding var bool bDestroyNextTick; // Destroy this pawn next tick because destroying it now will cause problems var float TimeSetDestroyNextTickTime; // The time we set the bDestroyNextTick flag var float LastDropCashMessageTime; var float DropCashMessageDelay; var bool bDestroyAfterRagDollTick; // Wait until the ragdoll tick has happened and then destroy. Prevents crashes where we try and destroy the actor right after initializing ragdoll var bool bProcessedRagTickDestroy; // Already called destroy for a bDestroyAfterRagDollTick setting // Collision var KFBulletWhipAttachment AuxCollisionCylinder; // Additional collision cylinder for detecting bullets passing by var bool SavedAuxCollision; // Saved aux collision cylinder status var float NadeThrowTimeout; // Little hack to timeout the grenade throwing flag on the client in case it gets stuck. At some point we should try and track down what is actually causing it to get stuck, this is just a quick fix - Ramm var Emitter AttachedEmitter; /* === Replicated Custom Animation Struct. Used with ACTION_PlayKFReplicatedAnim Objects to allow level designers to play replicated scripted animations on pawns */ struct SScriptedAnimRepInfo { var name BaseAnim; var float BlendInTime; var float BlendOutTime; var float AnimRate; var byte AnimIterations; var bool bLoopAnim; var float StartFrame; }; var SScriptedAnimRepInfo ScriptedAnimData; // Hit detection debugging - Only use when debugging /*var vector DrawLocation; var rotator DrawRotation; var int DrawIndex; var vector HitStart; var vector HitEnd; var byte HitPointDebugByte; var byte OldHitPointDebugByte;*/ replication { reliable if(Role == ROLE_Authority) bBurnified,QuickHeal,ClientCurrentWeaponSold,ClientForceChangeWeapon; reliable if(Role < ROLE_Authority) ServerBuyPotato,ServerBuyWeapon,ServerSellWeapon,ServerBuyKevlar,ServerBuyFirstAid,ServerBuyAmmo,ServerSellAmmo; reliable if(Role < ROLE_Authority) SecondaryItem,TossCash; reliable if ( bNetDirty && (Role == Role_Authority) && bNetOwner ) bMovementDisabled; reliable if(Role == ROLE_Authority && bNetDirty && !bNetOwner) ScriptedAnimData; // Hit detection debugging - Only use when debugging /*reliable if (Role == ROLE_Authority) DrawLocation,DrawRotation,DrawIndex,HitPointDebugByte,HitStart,HitEnd;*/ } simulated function PostBeginPlay() { Super(UnrealPawn).PostBeginPlay(); AssignInitialPose(); if( bActorShadows && bPlayerShadows && (Level.NetMode!=NM_DedicatedServer) ) { if( bDetailedShadows ) PlayerShadow = Spawn(class'KFShadowProject',Self,'',Location); else PlayerShadow = Spawn(class'ShadowProjector',Self,'',Location); PlayerShadow.ShadowActor = self; PlayerShadow.bBlobShadow = bBlobShadow; PlayerShadow.LightDirection = Normal(vect(1,1,3)); PlayerShadow.InitShadow(); } // Only need this on the server if( Role == Role_Authority/*IsLocallyControlled() || Level.NetMode == NM_DedicatedServer || Level.NetMode == NM_ListenServer*/ ) { if ( AuxCollisionCylinder == none ) { AuxCollisionCylinder = Spawn(class 'KFBulletWhipAttachment',self); //AttachToBone(AuxCollisionCylinder, 'CHR_Pelvis'); ///AuxCollisionCylinder = Spawn(class 'ExtendedZCollision',self); //MyExtCollision.SetCollisionSize(ColRadius,ColHeight); AuxCollisionCylinder.bHardAttach = true; //AttachPos = Location + (ColOffset >> Rotation); AuxCollisionCylinder.SetLocation( Location ); AuxCollisionCylinder.SetPhysics( PHYS_None ); AuxCollisionCylinder.SetBase( self ); } SavedAuxCollision = AuxCollisionCylinder.bCollideActors; } } // Setters for extra collision cylinders simulated function ToggleAuxCollision(bool newbCollision) { if ( !newbCollision ) { SavedAuxCollision = AuxCollisionCylinder.bCollideActors; AuxCollisionCylinder.SetCollision(false); } else { AuxCollisionCylinder.SetCollision(SavedAuxCollision); } } function PossessedBy(Controller C) { Super.PossessedBy(C); if ( C.PlayerReplicationInfo != None ) OwnerPRI = C.PlayerReplicationInfo; } simulated Function PostNetBeginPlay() { EnableChannelNotify(1,1); EnableChannelNotify(2,1); super.PostNetBeginPlay(); } simulated function string GetDefaultCharacter() { return "Corporal_Lewis"; } simulated function Setup(xUtil.PlayerRecord rec, optional bool bLoadNow) { local class AttachedEmitterClass; local vector AttachOffset; if( rec.Species==None || Class(rec.Species)==None ) rec = class'xUtil'.static.FindPlayerRecord(GetDefaultCharacter()); Species = rec.Species; RagdollOverride = rec.Ragdoll; if ( Species!=None && !Species.static.Setup(self,rec) ) { rec = class'xUtil'.static.FindPlayerRecord(GetDefaultCharacter()); Species = rec.Species; RagdollOverride = rec.Ragdoll; if ( !Species.static.Setup(self,rec) ) return; } if( rec.AttachedEmitter != "" && AttachedEmitter == none && Level.NetMode != NM_DedicatedServer) { AttachedEmitterClass = class(DynamicLoadObject(rec.AttachedEmitter,class'Class')); AttachedEmitter = Spawn(AttachedEmitterClass, self); if( AttachToBone(AttachedEmitter, rec.BoneName ) ) { AttachOffset.X = rec.XOffset; AttachOffset.Y = rec.YOffset; AttachOffset.Z = rec.ZOffset; AttachedEmitter.SetRelativeLocation( AttachOffset );//vect(rec.XOffset, rec.YOffset, rec.ZOffset) ); } } if( Class(Species) != none ) { DetachedArmClass = Class(Species).default.DetachedArmClass; DetachedLegClass = Class(Species).default.DetachedLegClass; } ResetPhysicsBasedAnim(); // bHasFootAdjust = False; // FeetAdjSpec = Class(rec.Species); // if( !bDoAdjustFeet || FeetAdjSpec==None || Level.NetMode==NM_DedicatedServer ) // return; // if( Adjuster!=None ) // Adjuster.Destroy(); // Adjuster = Spawn(Class'KFPawnFootAdjuster',,,vect(0,0,0),rot(0,0,0)); // Adjuster.AdjustingPawn = Self; // Adjuster.SpecType = FeetAdjSpec; // Adjuster.LinkMesh(Mesh); } // Clean up weapon inventory before level change since certain weapons // (sniper scopes with 3d scopes) won't get properly garbage collected // otherwise. This lead to the webadmin and memory leak issues - Ramm simulated function PreTravelCleanUp() { local Inventory Inv; local KFWeapon invWeapon; local int count; count=0; // consider doing a check on count to make sure it doesn't get too high // and force Unreal to crash with a run away loop for ( Inv=Inventory; Inv!=None; Inv=Inv.Inventory ) { invWeapon = KFWeapon(Inv); if ( invWeapon != None ) { invWeapon.PreTravelCleanUp(); } count++; if( count > 500 ) break; } } //returns how exposed this player is to another actor function float GetExposureTo(vector TestLocation) { local float PercentExposed; if( FastTrace(GetBoneCoords(HeadBone).Origin,TestLocation)) { PercentExposed += 0.5; } if( FastTrace(GetBoneCoords(RootBone).Origin,TestLocation)) { PercentExposed += 0.5; } return PercentExposed; } // Update the shadow if the detail settings have changed in the detail menu simulated function UpdateShadow() { if (bActorShadows && bPlayerShadows && (Level.NetMode != NM_DedicatedServer)) { if (PlayerShadow != none) PlayerShadow.Destroy(); if( bDetailedShadows ) PlayerShadow = Spawn(class'KFShadowProject',Self,'',Location); else PlayerShadow = Spawn(class'ShadowProjector',Self,'',Location); PlayerShadow.ShadowActor = self; PlayerShadow.bBlobShadow = bBlobShadow; PlayerShadow.LightDirection = Normal(vect(1,1,3)); PlayerShadow.InitShadow(); } else if (PlayerShadow != none && Level.NetMode != NM_DedicatedServer) { PlayerShadow.Destroy(); PlayerShadow = none; } } simulated function DoDerezEffect(); function SetScriptedAnimData( name BaseAnim, float BlendInTime, float BlendOutTime, float AnimRate, byte AnimIterations, bool bLoopAnim, float StartFrame) { ScriptedAnimData.BaseAnim = BaseAnim; ScriptedAnimData.BlendInTime = BlendInTime; ScriptedAnimData.BlendOutTime = BlendOutTime; ScriptedAnimdata.AnimRate = AnimRate; ScriptedAnimData.AnimIterations = AnimIterations; ScriptedAnimData.bLoopAnim = bLoopAnim; ScriptedAnimData.StartFrame = StartFrame; /* Play the anim on the server too*/ if(Role == Role_Authority) { PlayScriptedAnim(ScriptedAnimData); } } simulated function PlayScriptedAnim( SScriptedAnimRepInfo AnimData) { if(AnimData.bLoopAnim) { LoopAnim(AnimData.BaseAnim, AnimData.AnimRate, AnimData.BlendInTime); } else { PlayAnim(AnimData.baseAnim,AnimData.AnimRate,AnimData.BlendInTime); } if( AnimData.StartFrame > 0.0 ) SetAnimFrame(AnimData.StartFrame, 0, 1); } simulated event PostNetReceive() { if( ScriptedAnimData.BaseAnim != '') { PlayScriptedAnim(ScriptedAnimData); ScriptedAnimData.BaseAnim = ''; } if ( PlayerReplicationInfo != None ) { Setup(class'xUtil'.static.FindPlayerRecord(PlayerReplicationInfo.CharacterName)); bNetNotify = false; } else if ( (DrivenVehicle != None) && (DrivenVehicle.PlayerReplicationInfo != None) ) { Setup(class'xUtil'.static.FindPlayerRecord(DrivenVehicle.PlayerReplicationInfo.CharacterName)); bNetNotify = false; } } // Don't let this pawn move for a certain amount of time function DisableMovement(float DisableDuration) { StopDisabledTime = Level.TimeSeconds + DisableDuration; bMovementDisabled = true; } // Modify the velocity of the pawn simulated event ModifyVelocity(float DeltaTime, vector OldVelocity) { if( Role == ROLE_Authority ) { if( bMovementDisabled ) { if( Level.TimeSeconds > StopDisabledTime ) { bMovementDisabled = false; } } } if( bMovementDisabled && Physics == PHYS_Walking ) { Velocity.X = 0; Velocity.Y = 0; Velocity.Z = 0; } if ( KFGameReplicationInfo(Level.GRI).BaseDifficulty >= 5 && bMovementDisabled && Velocity.Z > 0 ) { Velocity.Z = 0; } } function TakeFallingDamage() { local float Shake, EffectiveSpeed; local float UsedMaxFallSpeed; UsedMaxFallSpeed = MaxFallSpeed; // Higher max fall speed in low grav so that weapons that push you around // don't cause you to die if( Instigator != none && Instigator.PhysicsVolume.Gravity.Z > class'PhysicsVolume'.default.Gravity.Z ) { UsedMaxFallSpeed *= 2.0; } if (Velocity.Z < -0.5 * UsedMaxFallSpeed) { if ( Role == ROLE_Authority ) { MakeNoise(1.0); if (Velocity.Z < -1 * UsedMaxFallSpeed) { EffectiveSpeed = Velocity.Z; if ( TouchingWaterVolume() ) EffectiveSpeed = FMin(0, EffectiveSpeed + 100); if ( EffectiveSpeed < -1 * UsedMaxFallSpeed ) TakeDamage(-100 * (EffectiveSpeed + UsedMaxFallSpeed)/UsedMaxFallSpeed, None, Location, vect(0,0,0), class'Fell'); } } if ( Controller != None ) { Shake = FMin(1, -1 * Velocity.Z/MaxFallSpeed); Controller.DamageShake(Shake); } } else if (Velocity.Z < -1.4 * JumpZ) MakeNoise(0.5); } exec function TestEye() { local Vector X,Y,Z; if( !class'ROEngine.ROLevelInfo'.static.RODebugMode() ) return; ClearStayingDebugLines(); DrawDebugSphere( EyePosition() + Location, 12, 12, 0, 255, 0); GetAxes( Controller.rotation, X, Y, Z ); DrawStayingDebugLine((EyePosition() + Location), (EyePosition() + Location)+500* X, 0,0,255); DrawStayingDebugLine((EyePosition() + Location), (EyePosition() + Location)+200* Y, 0,255,0); Spawn(class 'ROEngine.RODebugTracer',self,,(EyePosition() + Location),Rotation); } /* DisplayDebug() list important actor variable on canvas. Also show the pawn's controller and weapon info */ simulated function DisplayDebug(Canvas Canvas, out float YL, out float YPos) { local int i; local name Sequence; local float Frame, Rate; Super.DisplayDebug(Canvas, YL, YPos); for( i = 0; i < 16; i++ ) { if( IsAnimating( i ) ) { GetAnimParams( i, Sequence, Frame, Rate ); Canvas.DrawText("Anim:: Channel("@i@") Frame("@Frame@") Rate("@Rate@") Name("@Sequence@")"); YPos += YL; Canvas.SetPos(4,YPos); } } } simulated function DoDamageFX( Name boneName, int Damage, class DamageType, Rotator r ) { local float DismemberProbability; local int RandBone; local bool bDidSever; //log("DamageFX bonename = "$boneName$" "$Level.TimeSeconds$" Damage "$Damage); if ( FRand() > 0.3f || Damage > 30 || Health <= 0 ) { HitFX[HitFxTicker].damtype = DamageType; if( Health <= 0 ) { switch( boneName ) { case 'neck': boneName = HeadBone; break; case 'lfoot': case 'lleg': boneName = 'lthigh'; break; case 'rfoot': case 'rleg': boneName = 'rthigh'; break; case 'righthand': case 'rshoulder': case 'rarm': boneName = 'rfarm'; break; case 'lefthand': case 'lshoulder': case 'larm': boneName = 'lfarm'; break; case 'None': case 'spine': boneName = FireRootBone; break; } if( DamageType.default.bAlwaysSevers || (Damage == 1000) ) { HitFX[HitFxTicker].bSever = true; bDidSever = true; if ( boneName == 'None' ) { boneName = FireRootBone; } } else if( DamageType.Default.GibModifier > 0.0 ) { DismemberProbability = Abs( (Health - Damage*DamageType.Default.GibModifier) / 130.0f ); if( FRand() < DismemberProbability ) { HitFX[HitFxTicker].bSever = true; bDidSever = true; } } } if ( DamageType.default.bNeverSevers || class'GameInfo'.static.UseLowGore() || (Level.Game != none && Level.Game.PreventSever(self, boneName, Damage, DamageType)) ) { HitFX[HitFxTicker].bSever = false; bDidSever = false; } if ( HitFX[HitFxTicker].bSever ) { if( !DamageType.default.bLocationalHit && (boneName == 'None' || boneName == FireRootBone || boneName == 'Spine' )) { RandBone = Rand(4); switch( RandBone ) { case 0: boneName = 'lthigh'; break; case 1: boneName = 'rthigh'; break; case 2: boneName = 'lfarm'; break; case 3: boneName = 'rfarm'; break; case 4: boneName = HeadBone; break; default: boneName = 'lthigh'; } } } if( Health < 0 && Damage > DamageType.default.HumanObliterationThreshhold && Damage != 1000 ) { boneName = 'obliterate'; } HitFX[HitFxTicker].bone = boneName; HitFX[HitFxTicker].rotDir = r; HitFxTicker = HitFxTicker + 1; if( HitFxTicker > ArrayCount(HitFX)-1 ) HitFxTicker = 0; // If this was a really hardcore damage from an explosion, randomly spawn some arms and legs if ( bDidSever && !DamageType.default.bLocationalHit && Damage > 200 && Damage != 1000 ) { if ((Damage > 400 && FRand() < 0.3) || FRand() < 0.1 ) { DoDamageFX(HeadBone,1000,DamageType,r); DoDamageFX('lthigh',1000,DamageType,r); DoDamageFX('rthigh',1000,DamageType,r); DoDamageFX('lfarm',1000,DamageType,r); DoDamageFX('rfarm',1000,DamageType,r); } if ( FRand() < 0.25 ) { DoDamageFX('lthigh',1000,DamageType,r); DoDamageFX('rthigh',1000,DamageType,r); if ( FRand() < 0.5 ) { DoDamageFX('lfarm',1000,DamageType,r); } else { DoDamageFX('rfarm',1000,DamageType,r); } } else if ( FRand() < 0.35 ) DoDamageFX('lthigh',1000,DamageType,r); else if ( FRand() < 0.5 ) DoDamageFX('rthigh',1000,DamageType,r); else if ( FRand() < 0.75 ) { if ( FRand() < 0.5 ) { DoDamageFX('lfarm',1000,DamageType,r); } else { DoDamageFX('rfarm',1000,DamageType,r); } } } } } //Stops the green shit when a player dies. simulated function PlayDying(class DamageType, vector HitLoc) { local float frame, rate; local name seq; local LavaDeath LD; local MiscEmmiter BE; if( Adjuster!=None ) Adjuster.Destroy(); bHasFootAdjust = False; AmbientSound = None; bCanTeleport = false; // sjs - fix karma going crazy when corpses land on teleporters bReplicateMovement = false; bTearOff = true; bPlayedDeath = true; //bFrozenBody = true; SafeMesh = Mesh; if (CurrentCombo != None) CurrentCombo.Destroy(); HitDamageType = DamageType; // these are replicated to other clients TakeHitLocation = HitLoc; if ( DamageType != None ) { if ( DamageType.default.bSkeletize ) { SetOverlayMaterial(DamageType.Default.DamageOverlayMaterial, 4.0, true); if (!bSkeletized) { if ( (Level.NetMode != NM_DedicatedServer) && (SkeletonMesh != None) ) { if ( DamageType.default.bLeaveBodyEffect ) { BE = spawn(class'MiscEmmiter',self); if ( BE != None ) { BE.DamageType = DamageType; BE.HitLoc = HitLoc; bFrozenBody = true; } } GetAnimParams( 0, seq, frame, rate ); LinkMesh(SkeletonMesh, true); Skins.Length = 0; PlayAnim(seq, 0, 0); SetAnimFrame(frame); } if (Physics == PHYS_Walking) Velocity = Vect(0,0,0); SetTearOffMomemtum(GetTearOffMomemtum() * 0.25); bSkeletized = true; if ( (Level.NetMode != NM_DedicatedServer) && (DamageType == class'FellLava') ) { LD = spawn(class'LavaDeath', , , Location + vect(0, 0, 10), Rotation ); if ( LD != None ) LD.SetBase(self); PlaySound( sound'Inf_Weapons.F1.f1_explode01', SLOT_None, 1.5*TransientSoundVolume ); // KFTODO: Replace this sound } } } else if ( DamageType.Default.DeathOverlayMaterial != None ) SetOverlayMaterial(DamageType.Default.DeathOverlayMaterial, DamageType.default.DeathOverlayTime, true); else if ( (DamageType.Default.DamageOverlayMaterial != None) && (Level.DetailMode != DM_Low) && !Level.bDropDetail ) SetOverlayMaterial(DamageType.Default.DamageOverlayMaterial, 2*DamageType.default.DamageOverlayTime, true); } // stop shooting AnimBlendParams(1, 0.0); FireState = FS_None; //LifeSpan = RagdollLifeSpan; GotoState('Dying'); if ( BE != None ) return; PlayDyingAnimation(DamageType, HitLoc); } function PlayDyingAnimation(class 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( Level.PhysicsDetailLevel!=PDL_High && !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 Velocity += GetTearOffMomemtum(); BaseEyeHeight = Default.BaseEyeHeight; SetTwistLook(0, 0); SetInvisibility(0.0); PlayDirectionalDeath(HitLoc); SetPhysics(PHYS_Falling); } // jag // Called when in Ragdoll when we hit something over a certain threshold velocity // Used to play impact sounds. event KImpact(actor other, vector pos, vector impactVel, vector impactNorm) { local float VelocitySquared; local float RagHitVolume; if(Level.TimeSeconds > RagLastSoundTime + RagImpactSoundInterval) { VelocitySquared = VSizeSquared(impactVel); //log("Ragimpact velocity: "$VSize(impactVel)$" VelocitySquared: "$VelocitySquared); RagHitVolume = FMin(2.0,(VelocitySquared/40000)); //log("RagHitVolume = "$RagHitVolume); PlaySound(RagImpactSounds[0], SLOT_None, RagHitVolume); RagLastSoundTime = Level.TimeSeconds; } } //jag simulated function bool ForceDefaultCharacter() { return false; } simulated function ProcessHitFX() { local Coords boneCoords; local class HitEffects[4]; local int i,j; local float GibPerterbation; if( (Level.NetMode == NM_DedicatedServer) || bSkeletized || (Mesh == SkeletonMesh) ) { SimHitFxTicker = HitFxTicker; return; } for ( SimHitFxTicker = SimHitFxTicker; SimHitFxTicker != HitFxTicker; SimHitFxTicker = (SimHitFxTicker + 1) % ArrayCount(HitFX) ) { j++; if ( j > 30 ) { SimHitFxTicker = HitFxTicker; return; } if( (HitFX[SimHitFxTicker].damtype == None) || (Level.bDropDetail && (Level.TimeSeconds - LastRenderTime > 3) && !IsHumanControlled()) ) continue; //log("Processing effects for damtype "$HitFX[SimHitFxTicker].damtype); if( HitFX[SimHitFxTicker].bone == 'obliterate' && !class'GameInfo'.static.UseLowGore()) { SpawnGibs( HitFX[SimHitFxTicker].rotDir, 0); bGibbed = true; // Wait a tick on a listen server so the obliteration can replicate before the pawn is destroyed if( Level.NetMode == NM_ListenServer ) { bDestroyNextTick = true; TimeSetDestroyNextTickTime = Level.TimeSeconds; } else { Destroy(); } return; } boneCoords = GetBoneCoords( HitFX[SimHitFxTicker].bone ); if ( !Level.bDropDetail && !class'GameInfo'.static.NoBlood() && !bSkeletized ) { //AttachEmitterEffect( BleedingEmitterClass, HitFX[SimHitFxTicker].bone, boneCoords.Origin, HitFX[SimHitFxTicker].rotDir ); HitFX[SimHitFxTicker].damtype.static.GetHitEffects( HitEffects, Health ); if( !PhysicsVolume.bWaterVolume ) // don't attach effects under water { for( i = 0; i < ArrayCount(HitEffects); i++ ) { if( HitEffects[i] == None ) continue; AttachEffect( HitEffects[i], HitFX[SimHitFxTicker].bone, boneCoords.Origin, HitFX[SimHitFxTicker].rotDir ); } } } if ( class'GameInfo'.static.UseLowGore() ) HitFX[SimHitFxTicker].bSever = false; if( HitFX[SimHitFxTicker].bSever ) { GibPerterbation = HitFX[SimHitFxTicker].damtype.default.GibPerterbation; bFlaming = HitFX[SimHitFxTicker].DamType.Default.bFlaming; switch( HitFX[SimHitFxTicker].bone ) { case 'obliterate': break; case 'lthigh': if( !bLeftLegGibbed ) { SpawnSeveredGiblet( DetachedLegClass, boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation ); bLeftLegGibbed=true; } break; case 'rthigh': if( !bRightLegGibbed ) { SpawnSeveredGiblet( DetachedLegClass, boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation ); bRightLegGibbed=true; } break; case 'lfarm': if( !bLeftArmGibbed ) { SpawnSeveredGiblet( DetachedArmClass, boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation ); bLeftArmGibbed=true; } break; case 'rfarm': if( !bRightArmGibbed ) { SpawnSeveredGiblet( DetachedArmClass, boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation ); bRightArmGibbed=true; } break; case 'head': SpawnGiblet( GetGibClass(EGT_Head), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation ); break; } if (LastHitDamType == class 'SirenScreamDamage') HideBone(HeadBone); else if( HitFX[SimHitFXTicker].bone != 'Spine' && HitFX[SimHitFXTicker].bone != FireRootBone ) HideBone(HitFX[SimHitFxTicker].bone); } } } simulated function SpawnSeveredGiblet( class GibClass, Vector Location, Rotator Rotation, float GibPerterbation ) { local SeveredAppendage Giblet; local Vector Direction, Dummy; if( (GibClass == None) || class'GameInfo'.static.UseLowGore() ) return; Instigator = self; Giblet = Spawn( GibClass,,, Location, Rotation ); if( Giblet == None ) return; Giblet.SpawnTrail(); GibPerterbation *= 32768.0; Rotation.Pitch += ( FRand() * 2.0 * GibPerterbation ) - GibPerterbation; Rotation.Yaw += ( FRand() * 2.0 * GibPerterbation ) - GibPerterbation; Rotation.Roll += ( FRand() * 2.0 * GibPerterbation ) - GibPerterbation; GetAxes( Rotation, Dummy, Dummy, Direction ); Giblet.Velocity = Velocity + Normal(Direction) * (Giblet.MaxSpeed + (Giblet.MaxSpeed/2) * FRand()); //Giblet.LifeSpan = self.RagdollLifeSpan; } function class GetGibClass(xPawnGibGroup.EGibType gibType) { return GibGroupClass.static.GetGibClass(gibType); } simulated function HideBone(name boneName) { local int BoneScaleSlot; local coords boneCoords; if( boneName == 'lthigh' ) { boneScaleSlot = 0; if( SeveredLeftLeg == none ) { SeveredLeftLeg = Spawn(SeveredLegAttachClass,self); SeveredLeftLeg.SetDrawScale(SeveredLegAttachScale); boneCoords = GetBoneCoords( 'lleg' ); AttachEmitterEffect( LimbSpurtEmitterClass, 'lleg', boneCoords.Origin, rot(0,0,0) ); AttachToBone(SeveredLeftLeg, 'lleg'); } } else if ( boneName == 'rthigh' ) { boneScaleSlot = 1; if( SeveredRightLeg == none ) { SeveredRightLeg = Spawn(SeveredLegAttachClass,self); SeveredRightLeg.SetDrawScale(SeveredLegAttachScale); boneCoords = GetBoneCoords( 'rleg' ); AttachEmitterEffect( LimbSpurtEmitterClass, 'rleg', boneCoords.Origin, rot(0,0,0) ); AttachToBone(SeveredRightLeg, 'rleg'); } } else if( boneName == 'rfarm' ) { boneScaleSlot = 2; if( SeveredRightArm == none ) { SeveredRightArm = Spawn(SeveredArmAttachClass,self); SeveredRightArm.SetDrawScale(SeveredArmAttachScale); boneCoords = GetBoneCoords( 'rarm' ); AttachEmitterEffect( LimbSpurtEmitterClass, 'rarm', boneCoords.Origin, rot(0,0,0) ); AttachToBone(SeveredRightArm, 'rarm'); } } else if ( boneName == 'lfarm' ) { boneScaleSlot = 3; if( SeveredLeftArm == none ) { SeveredLeftArm = Spawn(SeveredArmAttachClass,self); SeveredLeftArm.SetDrawScale(SeveredArmAttachScale); boneCoords = GetBoneCoords( 'larm' ); AttachEmitterEffect( LimbSpurtEmitterClass, 'larm', boneCoords.Origin, rot(0,0,0) ); AttachToBone(SeveredLeftArm, 'larm'); } } else if ( boneName == HeadBone ) { boneScaleSlot = 4; if( SeveredHead == none ) { SeveredHead = Spawn(SeveredHeadAttachClass,self); SeveredHead.SetDrawScale(SeveredHeadAttachScale); boneCoords = GetBoneCoords( 'neck' ); AttachEmitterEffect( NeckSpurtEmitterClass, 'neck', boneCoords.Origin, rot(0,0,0) ); AttachToBone(SeveredHead, 'neck'); } } else if ( boneName == 'spine' ) boneScaleSlot = 5; SetBoneScale(BoneScaleSlot, 0.0, BoneName); } function PlayDyingSound() { if( Level.NetMode!=NM_Client ) { if ( bGibbed ) { PlaySound(GibGroupClass.static.GibSound(), SLOT_Pain,2.0,true,525); return; } if ( HeadVolume.bWaterVolume ) { PlaySound(GetSound(EST_Drown), SLOT_Pain,2.5*TransientSoundVolume,true,500); return; } PlaySound(SoundGroupClass.static.GetDeathSound(), SLOT_Pain,2.5*TransientSoundVolume, true,500); } } // Maybe spawn some chunks when the player gets obliterated simulated function SpawnGibs(Rotator HitRotation, float ChunkPerterbation) { bGibbed = true; PlayDyingSound(); if ( class'GameInfo'.static.UseLowGore() ) return; if ( ItBUURRNNNS != none ) { ItBUURRNNNS.Emitters[0].SkeletalMeshActor = none; ItBUURRNNNS.Destroy(); } if( ObliteratedEffectClass != none ) Spawn( ObliteratedEffectClass,,, Location, HitRotation ); super.SpawnGibs(HitRotation,ChunkPerterbation); if ( FRand() < 0.1 ) { SpawnSeveredGiblet( DetachedLegClass, Location, HitRotation, ChunkPerterbation ); SpawnSeveredGiblet( DetachedLegClass, Location, HitRotation, ChunkPerterbation ); SpawnSeveredGiblet( DetachedArmClass, Location, HitRotation, ChunkPerterbation ); SpawnSeveredGiblet( DetachedArmClass, Location, HitRotation, ChunkPerterbation ); } else if ( FRand() < 0.25 ) { SpawnSeveredGiblet( DetachedLegClass, Location, HitRotation, ChunkPerterbation ); SpawnSeveredGiblet( DetachedLegClass, Location, HitRotation, ChunkPerterbation ); if ( FRand() < 0.5 ) { SpawnSeveredGiblet( DetachedArmClass, Location, HitRotation, ChunkPerterbation ); } } else if ( FRand() < 0.35 ) SpawnSeveredGiblet( DetachedLegClass, Location, HitRotation, ChunkPerterbation ); else if ( FRand() < 0.5 ) { SpawnSeveredGiblet( DetachedArmClass, Location, HitRotation, ChunkPerterbation ); } } simulated function StartDeRes() { if( Level.NetMode == NM_DedicatedServer ) return; AmbientGlow=0; MaxLights=5; // DeResFX = Spawn(class'DeResPart', self, , Location); //Skins[0] = DeResMat0; //Skins[1] = DeResMat1; if( Physics == PHYS_KarmaRagdoll ) { // Remove flames RemoveFlamingEffects(); // Turn off any overlays SetOverlayMaterial(None, 0.0f, true); } } // Remove Shield Sounds , Randomize for Human Pain sound. function int ShieldAbsorb(int dam) { local float Interval, damage, Remaining; //local int PainSound; damage = dam; if ( ShieldStrength == 0 ) return damage; if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none ) { damage *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetBodyArmorDamageModifier(KFPlayerReplicationInfo(PlayerReplicationInfo)); } // Super.ShieldAbsorb(dam); //SetOverlayMaterial( ShieldHitMat, ShieldHitMatTime, false ); // Randomize Painsounds on Armor hit // PainSound = rand(6); // if (PainSound == 0) // PlaySound(sound'KFPlayerSound.hpain3', SLOT_Pain,2*TransientSoundVolume,,400); // else if (PainSound == 1) // PlaySound(sound'KFPlayerSound.hpain2', SLOT_Pain,2*TransientSoundVolume,,400); // else if (PainSound == 2) // PlaySound(sound'KFPlayerSound.hpain1', SLOT_Pain,2*TransientSoundVolume,,400); // else if (PainSound == 3) // PlaySound(sound'KFPlayerSound.hpain3', SLOT_Pain,2*TransientSoundVolume,,400); // else if (PainSound == 4) // PlaySound(sound'KFPlayerSound.hpain2', SLOT_Pain,2*TransientSoundVolume,,400); // else if (PainSound == 5) // PlaySound(sound'KFPlayerSound.hpain1', SLOT_Pain,2*TransientSoundVolume,,400); if ( ShieldStrength > SmallShieldStrength ) { Interval = ShieldStrength - SmallShieldStrength; if ( Interval >= 0.75 * damage ) { ShieldStrength -= 0.75 * damage; if ( ShieldStrength < SmallShieldStrength ) SmallShieldStrength = ShieldStrength; return (0.25 * Damage); } else { ShieldStrength = SmallShieldStrength; damage -= Interval; Remaining = 0.33 * Interval; if ( Remaining <= damage ) return damage; damage -= Remaining; } } if ( ShieldStrength >= 0.5 * damage ) { ShieldStrength -= damage ; SmallShieldStrength = ShieldStrength; return Remaining + (0.25 * damage); // 0.5 } else { damage -= ShieldStrength; ShieldStrength = 0; SmallShieldStrength = 0; } return damage + Remaining; } // Play the pawn firing animations simulated function StartFiringX(bool bAltFire, bool bRapid) { local name FireAnim; local int AnimIndex; if ( HasUDamage() && (Level.TimeSeconds - LastUDamageSoundTime > 0.25) ) { LastUDamageSoundTime = Level.TimeSeconds; PlaySound(UDamageSound, SLOT_None, 1.5*TransientSoundVolume,,700); } if (Physics == PHYS_Swimming) return; AnimIndex = Rand(4); if (bAltFire) { if( bIsCrouched ) { FireAnim = FireCrouchAltAnims[AnimIndex]; } else { FireAnim = FireAltAnims[AnimIndex]; } } else { if( bIsCrouched ) { FireAnim = FireCrouchAnims[AnimIndex]; } else { FireAnim = FireAnims[AnimIndex]; } } AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); if (bRapid) { if (FireState != FS_Looping) { LoopAnim(FireAnim,, 0.0, 1); FireState = FS_Looping; } } else { PlayAnim(FireAnim,, 0.0, 1); FireState = FS_PlayOnce; } IdleTime = Level.TimeSeconds; } simulated function StopFiring() { if (FireState == FS_Looping) FireState = FS_PlayOnce; IdleTime = Level.TimeSeconds; } simulated function AnimEnd(int Channel) { if (Channel == 1) { if (FireState == FS_Ready) { AnimBlendToAlpha(1, 0.0, 0.12); FireState = FS_None; } else if (FireState == FS_PlayOnce) { if( bIsCrouched ) { PlayAnim(PostFireBlendCrouchAnim,, 0.1, 1); } else { PlayAnim(PostFireBlendStandAnim,, 0.1, 1); } FireState = FS_Ready; IdleTime = Level.TimeSeconds; } else AnimBlendToAlpha(1, 0.0, 0.12); } else if ( bKeepTaunting && (Channel == 0) ) PlayVictoryAnimation(); } function RemoveInventorySP( class ItemClass ) { // If this item is in our inventory chain, unlink it. local actor Link; local int Count; local inventory Item ; Item = spawn(ItemClass) ; if ( ItemClass == Weapon.class ) Weapon = None; if ( ItemClass == SelectedItem.class ) SelectedItem = None; for( Link = Self; Link!=None; Link=Link.Inventory ) { if( Link.Inventory.class == ItemClass ) { Link.Inventory = Item.Inventory; Item.Inventory = None; Link.NetUpdateTime = Level.TimeSeconds - 1; Item.NetUpdateTime = Level.TimeSeconds - 1; break; } if ( Level.NetMode == NM_Client ) { Count++; if ( Count > 1000 ) break; } } Item.SetOwner(None); } // another one cut-n-pasted to remove must-have-ammo fetish exec function SwitchToLastWeapon() { if ( (Weapon != None) && (Weapon.OldWeapon != None) ) // && Weapon.OldWeapon.HasAmmo() ) { PendingWeapon = Weapon.OldWeapon; Weapon.PutDown(); } } // TODO: GetWeapon simulated function AddHealth() { local int tempHeal ; if((level.TimeSeconds - lastHealTime) >= 0.1) { if(Health < HealthMax) { tempHeal = int(10 * (level.TimeSeconds - lastHealTime)) ; if(tempHeal>0) lastHealTime = level.TimeSeconds ; Health = Min(Health+tempHeal, HealthMax); HealthToGive -= tempHeal ; } else { lastHealTime = level.timeSeconds ; // if we are all healed, there's gonna be no more healing HealthToGive = 0 ; } } } function bool GiveHealth(int HealAmount, int HealMax) { // Taking this out for now because it nerfs the high level medic perks - Ramm // if(healAmount >= 50) // healAmount = 50; // If someone gets healed while burning, reduce the burn length/damage if( BurnDown > 0 ) { if( BurnDown > 1 ) { BurnDown *= 0.5; } LastBurnDamage *= 0.5; } // Don't let them heal more than the max health if( (healAmount + HealthToGive + Health) > HealthMax) { healAmount = HealthMax - (Health + HealthToGive); if( healAmount == 0 ) { return false; } } if( Health 0.1 || (KFWeapon(Weapon).bIsReloading && !KFWeapon(Weapon).InterruptReload()) ) { return; } //TODO: cache this without setting SecItem yet //SecondaryItem = aFrag; KFWeapon(Weapon).ClientGrenadeState = GN_TempDown; Weapon.PutDown(); break; //aFrag.StartThrow(); } } } function WeaponDown() { local inventory inv; local Frag aFrag; for(inv=inventory; inv!=none; inv=inv.Inventory) { aFrag=Frag(inv); if(aFrag!=none && aFrag.HasAmmo() ) { SecondaryItem = aFrag; aFrag.StartThrow(); } } } simulated function HandleNadeThrowAnim() { if( Weapon != none ) { if( AK47AssaultRifle(Weapon) != none ) { SetAnimAction('Frag_AK47'); } else if( Bullpup(Weapon) != none || SeekerSixRocketLauncher(Weapon) != none) { SetAnimAction('Frag_Bullpup'); } else if( Crossbow(Weapon) != none ) { SetAnimAction('Frag_Crossbow'); } else if( Deagle(Weapon) != none || Magnum44Pistol(Weapon) != none || MK23Pistol(Weapon) != none) { SetAnimAction('Frag_Single9mm'); } else if( KFWeapon(Weapon) != none && KFWeapon(Weapon).bDualWeapon ) { SetAnimAction('Frag_Dual9mm'); } else if( FlameThrower(Weapon) != none ) { SetAnimAction('Frag_Flamethrower'); } else if( Axe(Weapon) != none || DwarfAxe(Weapon) != none ) { SetAnimAction('Frag_Axe'); } else if( Chainsaw(Weapon) != none ) { SetAnimAction('Frag_Chainsaw'); } else if( Katana(Weapon) != none || ClaymoreSword(Weapon) != none ) { SetAnimAction('Frag_Katana'); } else if( Knife(Weapon) != none ) { SetAnimAction('Frag_Knife'); } else if( Machete(Weapon) != none ) { SetAnimAction('Frag_Knife'); } else if( Syringe(Weapon) != none ) { SetAnimAction('Frag_Syringe'); } else if( Welder(Weapon) != none ) { SetAnimAction('Frag_Syringe'); } else if( BoomStick(Weapon) != none ) { SetAnimAction('Frag_HuntingShotgun'); } else if( LAW(Weapon) != none ) { SetAnimAction('Frag_LAW'); } else if( Shotgun(Weapon) != none || BenelliShotgun(Weapon) != none || Trenchgun(Weapon) != none) { SetAnimAction('Frag_Shotgun'); } else if( Winchester(Weapon) != none ) { SetAnimAction('Frag_Winchester'); } else if( Single(Weapon) != none ) { SetAnimAction('Frag_Single9mm'); } else if( M14EBRBattleRifle(Weapon) != none || SPSniperRifle(Weapon) != none ) { SetAnimAction('Frag_M14'); } else if( SCARMK17AssaultRifle(Weapon) != none ) { SetAnimAction('Frag_SCAR'); } else if( AA12AutoShotgun(Weapon) != none || FNFAL_ACOG_AssaultRifle(Weapon) != none || SPAutoShotgun(Weapon) != none ) { SetAnimAction('Frag_AA12'); } else if( MP5MMedicGun(Weapon) != none || KSGShotgun(Weapon) != none ) { SetAnimAction('Frag_MP5'); } else if( MP7MMedicGun(Weapon) != none ) { SetAnimAction('Frag_MP7'); } else if( M7A3MMedicGun(Weapon) != none || KrissMMedicGun(Weapon) != none ) { SetAnimAction('Frag_Kriss'); } else if( PipeBombExplosive(Weapon) != none ) { SetAnimAction('Frag_PipeBomb'); } else if( M79GrenadeLauncher(Weapon) != none || ZEDMKIIWeapon(Weapon) != none ) { SetAnimAction('Frag_M79'); } else if( M32GrenadeLauncher(Weapon) != none ) { SetAnimAction('Frag_M32_MGL'); } else if( SealSquealHarpoonBomber(Weapon) != none ) { SetAnimAction('Frag_IJC_SealSqueal'); } else if( M4203AssaultRifle(Weapon) != none || M99SniperRifle(Weapon) != none ) { SetAnimAction('Frag_M4203'); } else if( M4AssaultRifle(Weapon) != none || MKb42AssaultRifle(Weapon) != none) { SetAnimAction('Frag_M4'); } else if( HuskGun(Weapon) != none ) { SetAnimAction('Frag_HuskGun'); } else if( ZEDGun(Weapon) != none ) { SetAnimAction('Frag_Zed'); } else if( NailGun(Weapon) != none ) { SetAnimAction('Frag_Bullpup'); } else if( SPThompsonSMG(Weapon) != none || ThompsonDrumSMG(Weapon) != none) { SetAnimAction('Frag_IJC_spThompson_Drum'); } else if( ThompsonSMG(Weapon) != none ) { SetAnimAction('Frag_Thompson'); } else if( Scythe(Weapon) != none ) { SetAnimAction('Frag_Scythe'); } else if( Crossbuzzsaw(Weapon) != none ) { SetAnimAction('Frag_Cheetah'); } else if( FlareRevolver(Weapon) != none ) { SetAnimAction('Frag_Single9mm'); } } else { SetAnimAction('Frag_Knife'); } } simulated function ThrowGrenadeFinished() { SecondaryItem = none; KFWeapon(Weapon).ClientGrenadeState = GN_BringUp; Weapon.BringUp(); bThrowingNade = false; } simulated function SetNadeTimeOut(float NewTimeOut) { NadeThrowTimeout = NewTimeOut; } /* Feet height adjusting functions ======================================================*/ simulated function SetFootHeight( float HeightMulti, byte iNum ) { // local rotator R; // // OldAdjust[iNum] = (HeightMulti-OldAdjust[iNum])*0.5+OldAdjust[iNum]; // if( Abs(OldAdjust[iNum]-HeightMulti)<0.1 ) // OldAdjust[iNum] = HeightMulti; // HeightMulti = OldAdjust[iNum]; // HeightMulti = 1.f-HeightMulti; // Invert this value. // switch( FeetAdjSpec.Default.TorseRotType ) // { // case BRot_Yaw: // R.Yaw = FeetAdjSpec.Default.MaxTorsoTurn*HeightMulti; // break; // case BRot_Roll: // R.Roll = FeetAdjSpec.Default.MaxTorsoTurn*HeightMulti; // break; // default: // R.Pitch = FeetAdjSpec.Default.MaxTorsoTurn*HeightMulti; // } // SetBoneRotation(FeetAdjSpec.Default.TorsoBones[iNum],R); // R = rot(0,0,0); // switch( FeetAdjSpec.Default.KneeRotType ) // { // case BRot_Yaw: // R.Yaw = FeetAdjSpec.Default.MaxKneeTurn*HeightMulti; // break; // case BRot_Roll: // R.Roll = FeetAdjSpec.Default.MaxKneeTurn*HeightMulti; // break; // default: // R.Pitch = FeetAdjSpec.Default.MaxKneeTurn*HeightMulti; // } // SetBoneRotation(FeetAdjSpec.Default.KneeBones[iNum],R); } simulated function UpdateFeetCoords() { // local Coords C; // local byte i; // local vector X,Y,Z,HL,Pos; // // GetAxes(Rotation,X,Y,Z); // Pos = Location+PrePivot; // for( i=0; i<2; i++ ) // { // C = GetBoneCoords(FeetAdjSpec.Default.FeetBones[i]); // C.Origin = (C.Origin-Pos)< 0 ) { NadeThrowTimeout -= DeltaTime; } // This is a hack to clear this flag on the client after a bit of time. This fixes a bug where you could get stuck unable to use weapons if( NadeThrowTimeout <= 0 ) { NadeThrowTimeout = 0; ThrowGrenadeFinished(); } } // IN other words - we're moving, we've got a piece, but we're not firing or reloading, or jumping / falling Faust:Perhaps we need that later: VSize(Acceleration) != 0 && if (level.NetMode != NM_DEDICATEDSERVER) { if(bBurnified && !bBurnApplied) { if ( !bGibbed ) { StartBurnFX(); } } else if(!bBurnified && bBurnApplied) StopBurnFX(); } // CheckFlashLightAnims(); if( bResetingAnimAct && (AnimActResetTime 0 && health > 0) // AddHealth() ; else if(healthToGive < 0) healthToGive = 0 ; if(BileCount>0 && NextBileTime1.85 && PrePivot.Z>-35 ) // { // PrePivot.Z-=DeltaTime*60f; // SetDrawScale(DrawScale); // } // } // } // KFTODO: Maybe take this out because we're using notifies for footsteps in third person now // if( Level.Netmode != NM_DedicatedServer ) // { // // do footsteps for nonlocal pawns and bots // if( !IsLocallyControlled() || (Level.Netmode == NM_Standalone && !IsHumanControlled())) // { // CheckFootSteps(DeltaTime); // } // } if( Physics == PHYS_KarmaRagdoll && bDestroyAfterRagDollTick && !bProcessedRagTickDestroy && GetRagDollFrames() > 0 ) { bProcessedRagTickDestroy = true; Destroy(); } // If we've flagged this character to be destroyed next tick, handle that else if( bDestroyNextTick && TimeSetDestroyNextTickTime < Level.TimeSeconds ) { Destroy(); } Super.Tick(deltaTime); } // Blend the upper body back to full body animation. // Called by the native code when AnimBlendTime counts down to zero simulated event AnimBlendTimer() { AnimBlendToAlpha(1, 0.0, 0.12); // Force a new idle anim to play, since we likely just switched weapons bIsIdle=false; IdleTime = Level.TimeSeconds; } simulated event SetAnimAction(name NewAction) { local float UsedBlendOutTime; if( NewAction=='' ) Return; if (!bWaitForAnim) { AnimAction = NewAction; if ( AnimAction == 'Weapon_Switch' ) { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); PlayAnim(NewAction,, 0.0, 1); // Set the timer to blend out the upper body animation if( HasAnim( AnimAction ) ) { UsedBlendOutTime = GetAnimDuration(NewAction, 1.0); } else { UsedBlendOutTime = 0.2; } AnimBlendTime = UsedBlendOutTime + 0.1; } else if ( AnimAction == IdleWeaponAnim ) { PlayAnim(AnimAction,,0.1); AnimBlendToAlpha(1,0.0,0.05); } else if ( AnimAction == 'Reload' ) { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); PlayAnim(NewAction,, 0.0, 1); } else if ( AnimAction == 'AxeAttack' ) { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); PlayAnim(NewAction,, 0.0, 1); } else if ( AnimAction == 'ChainSawAttack' ) { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); PlayAnim(NewAction,, 0.0, 1); } else if ( AnimAction == 'DeagleHold' ) { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); LoopAnim(NewAction,, 0.0, 1); } else if ( AnimAction == 'DualiesHold' ) { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); LoopAnim(NewAction,, 0.0, 1); } else if ( AnimAction == 'Frag_AK47' || AnimAction == 'Frag_Bullpup' || AnimAction == 'Frag_Crossbow' || AnimAction == 'Frag_Single9mm' || AnimAction == 'Frag_Dual9mm' || AnimAction == 'Frag_Flamethrower' || AnimAction == 'Frag_Axe' || AnimAction == 'Frag_Chainsaw' || AnimAction == 'Frag_Katana' || AnimAction == 'Frag_Knife' || AnimAction == 'Frag_Syringe' || AnimAction == 'Frag_HuntingShotgun' || AnimAction == 'Frag_LAW' || AnimAction == 'Frag_Shotgun' || AnimAction == 'Frag_M14' || AnimAction == 'Frag_SCAR' || AnimAction == 'Frag_AA12' || AnimAction == 'Frag_MP7' || AnimAction == 'Frag_PipeBomb' || AnimAction == 'Frag_M79' || AnimAction == 'Frag_M32_MGL' || AnimAction == 'Frag_M4' || AnimAction == 'Frag_M4203' || AnimAction == 'Frag_MP5' || AnimAction == 'Frag_HuskGun' || AnimAction == 'Frag_Kriss' || AnimAction == 'Frag_Thompson' || AnimAction == 'Frag_scythe' || AnimAction == 'Frag_Cheetah' || AnimAction == 'Frag_Zed' || AnimAction == 'Frag_IJC_spThompson_Drum' || AnimAction == 'Frag_IJC_SealSqueal') { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); PlayAnim(NewAction,, 0.0, 1); bThrowingNade = true; } else if ( AnimAction == 'ShotgunFire' ) { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); PlayAnim(NewAction,, 0.0, 1); } else if ( AnimAction == 'DeagleBlast' ) { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); PlayAnim(NewAction,, 0.0, 1); } // Reloads else if ( AnimAction == 'Reload1' || AnimAction == 'Reload_BullPup' || AnimAction == 'Reload_Single9mm' || AnimAction == 'Reload_Winchester' || AnimAction == 'Reload_Crossbow' || AnimAction == 'Reload_Dual9mm' || AnimAction == 'Reload_Flamethrower' || AnimAction == 'Reload_HuntingShotgun' || AnimAction == 'Reload_LAW' || AnimAction == 'Reload_Shotgun' || AnimAction == 'Reload_Winchester' || AnimAction == 'Reload_AK47' || AnimAction == 'Reload_M14' || AnimAction == 'Reload_SCAR' || AnimAction == 'Reload_MP7' || AnimAction == 'Reload_AA12' || AnimAction == 'Reload_Secondary_M4203' || AnimAction == 'Reload_Fal_Acog' || AnimAction == 'Reload_Fal_Acog' || AnimAction == 'Reload_M7A3' || AnimAction == 'Reload_KSG' || AnimAction == 'Reload_Flare' || AnimAction == 'Reload_DualFlare' || AnimAction == 'Reload_Cheetah' || AnimAction == 'Reload_Thompson' || AnimAction == 'Reload_Kriss' || AnimAction == 'Reload_Zed' || AnimAction == 'Reload_IJC_spJackHammer' || AnimAction == 'Reload_spSinper' || AnimAction == 'Reload_IJC_spThompson_Drum' || AnimAction == 'Reload_IJC_SealSqueal' || AnimAction == 'Reload_M32_MGL' || AnimAction == 'Reload_IJC_SeekerSix' || AnimAction == 'Reload_IJC_ZEDV2' ) { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); PlayAnim(NewAction,, 0.1, 1); FireState = FS_Ready; } else if ( ((Physics == PHYS_None)|| ((Level.Game != None) && Level.Game.IsInState('MatchOver'))) && (DrivenVehicle == None) ) { PlayAnim(AnimAction,,0.1); AnimBlendToAlpha(1,0.0,0.05); } else if ( (DrivenVehicle != None) || (Physics == PHYS_Falling) || ((Physics == PHYS_Walking) && (Velocity.Z != 0)) ) { if ( CheckTauntValid(AnimAction) ) { if (FireState == FS_None || FireState == FS_Ready) { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); PlayAnim(NewAction,, 0.1, 1); FireState = FS_Ready; } } else if ( HasAnim(AnimAction) && PlayAnim(AnimAction) ) { if ( Physics != PHYS_None ) bWaitForAnim = true; } else AnimAction = NewAction; } else if (bIsIdle && !bIsCrouched && (Bot(Controller) == None) ) // standing taunt { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); PlayAnim(AnimAction,,0.1,1); } else if (FireState == FS_None || FireState == FS_Ready) { AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone); PlayAnim(NewAction,, 0.1, 1); FireState = FS_Ready; } } if( Level.NetMode!=NM_Client ) { // Reset to fix replication. bResetingAnimAct = True; AnimActResetTime = Level.TimeSeconds+0.45; } } simulated function StartBurnFX() { if( bDeleteMe ) { return; } if( ItBUURRNNNS==None ) { ItBUURRNNNS = Spawn(BurnEffect); ItBUURRNNNS.SetBase(Self); ItBUURRNNNS.Emitters[0].SkeletalMeshActor = self; ItBUURRNNNS.Emitters[0].UseSkeletalLocationAs = PTSU_SpawnOffset; } bBurnApplied = True; } simulated function StopBurnFX() { RemoveFlamingEffects(); if( ItBUURRNNNS!=None ) ItBUURRNNNS.Kill(); bBurnApplied = False; } // Process a precision hit function ProcessLocationalDamage(int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType, array PointsHit ) { local int actualDamage, originalDamage, cumulativeDamage, totalDamage, i; local int HighestDamagePoint, HighestDamageAmount; local bool bHeadShot; // Hit detection debugging // local coords CO; // local vector HeadLoc; // local bool bFirstHit; originalDamage = damage; // If someone else has killed this player , return if( bDeleteMe || PointsHit.Length < 1 || Health <= 0 ) return; // Don't process locational damage if we're not going to damage a friendly anyway if( TeamGame(Level.Game)!=None && TeamGame(Level.Game).FriendlyFireScale==0 && instigatedBy!=None && instigatedBy!=Self && instigatedBy.GetTeamNum()==GetTeamNum() ) { Return; } for(i=0; i HighestDamageAmount ) { HighestDamageAmount = actualDamage; HighestDamagePoint = PointsHit[i]; } // Store if one of the shots was a headshot if( Hitpoints[PointsHit[i]].HitPointType == PHP_Head && class(damageType)!=none && class(damageType).default.bCheckForHeadShots) { bHeadShot = true; } //log("We hit "$GetEnum(enum'EPawnHitPointType',Hitpoints[PointsHit[i]].HitPointType)); // Hit detection debugging /*if( PointsHit[i] != 0 && !bFirstHit ) { CO = GetBoneCoords(Hitpoints[PointsHit[i]].PointBone); HeadLoc = CO.Origin; HeadLoc = HeadLoc + (Hitpoints[PointsHit[i]].PointOffset >> GetBoneRotation(Hitpoints[PointsHit[i]].PointBone)); DrawLocation = HeadLoc; DrawRotation = GetBoneRotation(Hitpoints[PointsHit[i]].PointBone); DrawIndex = PointsHit[i]; HitPointDebugByte++; bFirstHit = true; }*/ // Lets exit out if one of the shots killed the player if ( cumulativeDamage >= Health ) { // Play a sound when someone gets a headshot - KFTODO: Replace this with a better bullet hitting a helmet sound if( bHeadShot ) { PlaySound(sound'ProjectileSounds.impact_metal09', SLOT_None,2.0,true,500); } TakeDamage(totalDamage, instigatedBy, hitlocation, momentum, damageType, HighestDamagePoint); } } if( totalDamage > 0 ) { // If someone else has killed this player , return if( bDeleteMe || Health <= 0 ) return; // Play a sound when someone gets a headshot if( bHeadShot ) { // Play a sound when someone gets a headshot - KFTODO: Replace this with a better bullet hitting a helmet sound PlaySound(sound'ProjectileSounds.impact_metal09', SLOT_None,2.0,true,500); } TakeDamage(totalDamage, instigatedBy, hitlocation, momentum, damageType, HighestDamagePoint); } } // Hit detection debugging - Only use when debugging /* simulated function DrawBoneLocation() { local vector X, Y, Z; GetAxes(DrawRotation, X,Y,Z); ClearStayingDebugLines(); DrawStayingDebugLine(HitStart, HitEnd, 0,255,0); Spawn(class 'ROEngine.RODebugTracer',self,,HitStart,Rotator(Normal(HitEnd-HitStart))); DrawDebugCylinder(DrawLocation,Z,Y,X,Hitpoints[DrawIndex].PointRadius * Hitpoints[DrawIndex].PointScale,Hitpoints[DrawIndex].PointHeight * Hitpoints[DrawIndex].PointScale,10,0, 255, 0); } simulated function DrawDebugCylinder(vector Base,vector X, vector Y,vector Z, FLOAT Radius,float HalfHeight,int NumSides, byte R, byte G, byte B) { local float AngleDelta; local vector LastVertex, Vertex; local int SideIndex; AngleDelta = 2.0f * PI / NumSides; LastVertex = Base + X * Radius; for(SideIndex = 0;SideIndex < NumSides;SideIndex++) { Vertex = Base + (X * Cos(AngleDelta * (SideIndex + 1)) + Y * Sin(AngleDelta * (SideIndex + 1))) * Radius; DrawStayingDebugLine( LastVertex - Z * HalfHeight,Vertex - Z * HalfHeight,R,G,B); DrawStayingDebugLine( LastVertex + Z * HalfHeight,Vertex + Z * HalfHeight,R,G,B); DrawStayingDebugLine( LastVertex - Z * HalfHeight,LastVertex + Z * HalfHeight,R,G,B); LastVertex = Vertex; } }*/ function TakeDamage(int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType, optional int HitIdx ) { local KFPlayerReplicationInfo KFPRI; LastHitDamType = damageType; LastDamagedBy = instigatedBy; super.TakeDamage(Damage, instigatedBy, hitLocation, momentum, damageType); healthtoGive-=5; KFPRI = KFPlayerReplicationInfo(PlayerReplicationInfo); // Just return if this wouldn't even damage us. Prevents us from catching on fire for high level perks that dont take fire damage if( KFPRI != none && KFPRI.ClientVeteranSkill != none ) { if( KFPRI.ClientVeteranSkill.Static.ReduceDamage(KFPRI, self, instigatedBy, Damage, DamageType) <= 0 ) { return; } } if ( class(damageType) != none || class(damageType) != none) { if( TeamGame(Level.Game)!=None && TeamGame(Level.Game).FriendlyFireScale==0 && instigatedBy!=None && instigatedBy!=Self && instigatedBy.GetTeamNum()==GetTeamNum() ) { Return; } // Do burn damage if the damage was significant enough if( Damage > 2 ) { // If we are already burning, and this damage is more than our current burn amount, add more burn time if( BurnDown > 0 && Damage > LastBurnDamage ) { BurnDown = 5; BurnInstigator = instigatedBy; } LastBurnDamage = Damage; if (BurnDown <= 0 ) { bBurnified = true; BurnDown = 5; BurnInstigator = instigatedBy; SetTimer(1.5,true); } } } if(class(DamageType)!=none) { BileCount=7; BileInstigator = instigatedBy; LastBileDamagedByType=class(DamageType); if(NextBileTime< Level.TimeSeconds ) NextBileTime = Level.TimeSeconds+BileFrequency; if ( Level.Game != none && Level.Game.GameDifficulty >= 4.0 && KFPlayerController(Controller) != none && !KFPlayerController(Controller).bVomittedOn) { KFPlayerController(Controller).bVomittedOn = true; KFPlayerController(Controller).VomittedOnTime = Level.TimeSeconds; if ( Controller.TimerRate == 0.0 ) { Controller.SetTimer(10.0, false); } } } else if ( class(DamageType) != none ) { if ( Level.Game != none && Level.Game.GameDifficulty >= 4.0 && KFPlayerController(Controller) != none && !KFPlayerController(Controller).bScreamedAt) { KFPlayerController(Controller).bScreamedAt = true; KFPlayerController(Controller).ScreamTime = Level.TimeSeconds; if ( Controller.TimerRate == 0.0 ) { Controller.SetTimer(10.0, false); } } } } function TakeBileDamage() { Super.TakeDamage(2+Rand(3), BileInstigator, Location, vect(0,0,0), LastBileDamagedByType); healthtoGive-=5; } function bool AddShieldStrength(int ShieldAmount) { if(ShieldStrength >= 100) return false; ShieldStrength+=ShieldAmount; if(ShieldStrength > 100) ShieldStrength = 100; return true ; } function TakeFireDamage(int Damage, pawn BInstigator) { if( Damage > 0 ) { TakeDamage(Damage, BInstigator, Location, vect(0,0,0), class'DamTypeBurned'); if (BurnDown > 0) { BurnDown --; // Decrement the number of FireDamage calls left before our Zombie is extinguished :) } if(BurnDown==0) { bBurnified = false; } } else { BurnDown = 0; bBurnified = false; } } function PlayHit(float Damage, Pawn InstigatedBy, vector HitLocation, class damageType, vector Momentum, optional int HI ) { local Vector HitNormal; local Vector HitRay; local Name HitBone; local float HitBoneDist; local PlayerController PC; local bool bShowEffects, bRecentHit; local ProjectileBloodSplat BloodHit; local rotator SplatRot; bRecentHit = Level.TimeSeconds - LastPainTime < 0.2; // Take you out of ironsights when taking momentum from damage if( VSize(Momentum) > 0 && KFWeapon(Weapon) != none ) { KFWeapon(Weapon).bForceLeaveIronsights = true; } if ( Damage <= 0 ) return; // Call the modified version of the original Pawn playhit OldPlayHit(Damage,InstigatedBy,HitLocation,DamageType,Momentum); PC = PlayerController(Controller); bShowEffects = ( (Level.NetMode != NM_Standalone) || (Level.TimeSeconds - LastRenderTime < 2.5) || ((InstigatedBy != None) && (PlayerController(InstigatedBy.Controller) != None)) || (PC != None) ); if ( !bShowEffects ) return; if ( BurnDown > 0 && !bBurnified ) bBurnified = true; HitRay = vect(0,0,0); if( InstigatedBy != None ) HitRay = Normal(HitLocation-(InstigatedBy.Location+(vect(0,0,1)*InstigatedBy.EyeHeight))); if( DamageType.default.bLocationalHit ) { CalcHitLoc( HitLocation, HitRay, HitBone, HitBoneDist ); } else { HitLocation = Location; HitBone = FireRootBone; HitBoneDist = 0.0f; } if( DamageType.default.bAlwaysSevers && DamageType.default.bSpecial ) HitBone = 'head'; if( InstigatedBy != None ) HitNormal = Normal( Normal(InstigatedBy.Location-HitLocation) + VRand() * 0.2 + vect(0,0,2.8) ); else HitNormal = Normal( Vect(0,0,1) + VRand() * 0.2 + vect(0,0,2.8) ); //log("HitLocation "$Hitlocation) ; if ( DamageType.Default.bCausesBlood && (!bRecentHit || (bRecentHit && (FRand() > 0.8)))) { if ( !class'GameInfo'.static.NoBlood() ) { if ( Momentum != vect(0,0,0) ) SplatRot = rotator(Normal(Momentum)); else { if ( InstigatedBy != None ) SplatRot = rotator(Normal(Location - InstigatedBy.Location)); else SplatRot = rotator(Normal(Location - HitLocation)); } BloodHit = Spawn(ProjectileBloodSplatClass,InstigatedBy,, HitLocation, SplatRot); } } // hack for siren if ( (DamageType.name == 'SirenScreamDamage') && (Health < 0) ) { if( (InstigatedBy != None) && (VSize(InstigatedBy.Location - Location) < 200) ) { DoDamageFX( 'obliterate', 5000 * Damage, DamageType, Rotator(HitNormal) ); } else { DoDamageFX( HeadBone, 5000 * Damage, DamageType, Rotator(HitNormal) ); PlaySound(DecapitationSound, SLOT_Misc,1.30,true,525); } } else DoDamageFX( HitBone, Damage, DamageType, Rotator(HitNormal) ); if (DamageType.default.DamageOverlayMaterial != None && Damage > 0 ) // additional check in case shield absorbed SetOverlayMaterial( DamageType.default.DamageOverlayMaterial, DamageType.default.DamageOverlayTime, false ); } // Modified version of the original Pawn playhit. Set up because we want our blood puffs to be directional based // On the momentum of the bullet, not out from the center of the player function OldPlayHit(float Damage, Pawn InstigatedBy, vector HitLocation, class damageType, vector Momentum, optional int HitIndex) { local PlayerController Hearer; if ( DamageType == None ) return; if ( (Damage <= 0) && ((Controller == None) || !Controller.bGodMode) ) return; if (Damage > DamageType.Default.DamageThreshold) //spawn some blood { SpawnHitEmitter( Damage, InstigatedBy, HitLocation, damageType, Momentum ); } if ( Health <= 0 ) { if ( PhysicsVolume.bDestructive && (PhysicsVolume.ExitActor != None) ) Spawn(PhysicsVolume.ExitActor); return; } if ( Level.TimeSeconds - LastPainTime > 0.1 ) { if ( InstigatedBy != None && (DamageType != None) && DamageType.default.bDirectDamage ) Hearer = PlayerController(InstigatedBy.Controller); if ( Hearer != None ) Hearer.bAcuteHearing = true; PlayTakeHit(HitLocation,Damage,damageType); if ( Hearer != None ) Hearer.bAcuteHearing = false; LastPainTime = Level.TimeSeconds; } } function SpawnHitEmitter( float Damage, Pawn InstigatedBy, vector HitLocation, class damageType, vector Momentum ) { local Vector HitNormal; local class DesiredEffect; local class DesiredEmitter; local vector BloodOffset, Mo; // Play any set effect if ( EffectIsRelevant(Location,true) ) { HitNormal = Normal(HitLocation - Location); DesiredEffect = DamageType.static.GetPawnDamageEffect(HitLocation, Damage, Momentum, self, (Level.bDropDetail || Level.DetailMode == DM_Low)); if ( DesiredEffect != None ) { BloodOffset = 0.2 * CollisionRadius * HitNormal; BloodOffset.Z = BloodOffset.Z * 0.5; Mo = Momentum; if ( Mo.Z > 0 ) Mo.Z *= 0.5; spawn(DesiredEffect,self,,HitLocation + BloodOffset, rotator(Mo)); } // Spawn any preset emitter DesiredEmitter = DamageType.Static.GetPawnDamageEmitter(HitLocation, Damage, Momentum, self, (Level.bDropDetail || Level.DetailMode == DM_Low)); if (DesiredEmitter != None) { if( InstigatedBy != none ) HitNormal = Normal((InstigatedBy.Location+(vect(0,0,1)*InstigatedBy.EyeHeight))-HitLocation); spawn(DesiredEmitter,,,HitLocation+HitNormal + (-HitNormal * CollisionRadius), Rotator(HitNormal)); } } } simulated function AttachEffect( class EmitterClass, Name BoneName, Vector Location, Rotator Rotation ) { local Actor a; local int i; if( bSkeletized || (BoneName == 'None') ) return; for( i = 0; i < Attached.Length; i++ ) { if( Attached[i] == None ) continue; if( Attached[i].AttachmentBone != BoneName ) continue; if( ClassIsChildOf( EmitterClass, Attached[i].Class ) ) return; } a = Spawn( EmitterClass,,, Location, Rotation ); if (a == none) return; if( !AttachToBone( a, BoneName ) ) { log( "Couldn't attach "$EmitterClass$" to "$BoneName, 'Error' ); a.Destroy(); return; } for( i = 0; i < Attached.length; i++ ) { if( Attached[i] == a ) break; } a.SetRelativeRotation( Rotation ); } simulated function SpawnGiblet( class GibClass, Vector Location, Rotator Rotation, float GibPerterbation ) { local Gib Giblet; local Vector Direction, Dummy; if( (GibClass == None) || class'GameInfo'.static.UseLowGore() ) return; Instigator = self; Giblet = Spawn( GibClass,,, Location, Rotation ); if( Giblet == None ) return; Giblet.bFlaming = bFlaming; Giblet.SpawnTrail(); GibPerterbation *= 32768.0; Rotation.Pitch += ( FRand() * 2.0 * GibPerterbation ) - GibPerterbation; Rotation.Yaw += ( FRand() * 2.0 * GibPerterbation ) - GibPerterbation; Rotation.Roll += ( FRand() * 2.0 * GibPerterbation ) - GibPerterbation; GetAxes( Rotation, Dummy, Dummy, Direction ); Giblet.Velocity = Velocity + Normal(Direction) * (250 + 260 * FRand()); Giblet.LifeSpan = Giblet.LifeSpan + 2 * FRand() - 1; } State Dying { simulated function AnimEnd( int Channel ); simulated function bool SpecialCalcView( out Actor ViewActor, out vector CameraLocation, out rotator CameraRotation ) { local Coords Co; local vector HL,HN; ViewActor = Self; Co = GetBoneCoords('CHR_Head'); CameraLocation = Co.Origin+Co.XAxis*8; // Make sure camera dosent show through world geometry. if( Trace(HL,HN,CameraLocation+vect(0,0,25),CameraLocation,False)!=None ) CameraLocation+=HN*25; if( Trace(HL,HN,CameraLocation-vect(0,0,25),CameraLocation,False)!=None ) CameraLocation+=HN*25; if( Trace(HL,HN,CameraLocation+vect(25,0,0),CameraLocation,False)!=None ) CameraLocation+=HN*25; if( Trace(HL,HN,CameraLocation-vect(25,0,0),CameraLocation,False)!=None ) CameraLocation+=HN*25; if( Trace(HL,HN,CameraLocation+vect(0,25,0),CameraLocation,False)!=None ) CameraLocation+=HN*25; if( Trace(HL,HN,CameraLocation-vect(0,25,0),CameraLocation,False)!=None ) CameraLocation+=HN*25; GetAxes(GetBoneRotation('CHR_Head'),Co.XAxis,Co.YAxis,Co.ZAxis); CameraRotation = OrthoRotation(-Co.YAxis,Co.ZAxis,Co.XAxis); // Turns the camera by 90 degrees. Return True; } event FellOutOfWorld(eKillZType KillType) { local LavaDeath LD; // If we fall past a lava killz while dead- burn off skin. if( KillType == KILLZ_Lava ) { if ( !bSkeletized ) { if ( SkeletonMesh != None ) { LinkMesh(SkeletonMesh, true); Skins.Length = 0; } bSkeletized = true; LD = spawn(class'LavaDeath', , , Location + vect(0, 0, 10), Rotation ); if ( LD != None ) LD.SetBase(self); // This should destroy itself once its finished. PlaySound( sound'Inf_Weapons.F1.f1_explode01', SLOT_None, 1.5*TransientSoundVolume ); // KFTODO: Replace this sound } return; } Super.FellOutOfWorld(KillType); } simulated function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class damageType, optional int HI ) { local emitter BloodHit; Health -= Damage; if (Health <= -200) { // Gibbed BloodHit = Spawn(class'KFMod.FeedingSpray',InstigatedBy,,Location,Rotation); // KFTODO: Replace this spawn giblet with // SpawnGiblet(class 'ClotGibHead',HitLocation, self.Rotation, 0.06 ) ; // // SpawnGiblet(class 'ClotGibTorso',HitLocation, self.Rotation, 0.06) ; // SpawnGiblet(class 'ClotGibLowerTorso',HitLocation, self.Rotation, 0.06 ) ; // // SpawnGiblet(class 'ClotGibArm',HitLocation, self.Rotation, 0.06 ) ; // SpawnGiblet(class 'ClotGibArm',HitLocation, self.Rotation, 0.06 ) ; // // SpawnGiblet(class 'ClotGibThigh',HitLocation, self.Rotation, 0.06 ) ; // SpawnGiblet(class 'ClotGibThigh',HitLocation, self.Rotation, 0.06 ) ; // // SpawnGiblet(class 'ClotGibLeg',HitLocation, self.Rotation, 0.06 ) ; // SpawnGiblet(class 'ClotGibLeg',HitLocation, self.Rotation, 0.06 ) ; if( Physics == PHYS_KarmaRagdoll ) { bDestroyAfterRagDollTick = true; } else { Destroy(); } } } simulated function BeginState() { local int i; bSpecialCalcView = Class'KFPawn'.Default.bRealDeathType; if ( Controller != None ) { if ( Controller.bIsPlayer ) Controller.PawnDied(self); else Controller.Destroy(); } for (i = 0; i < Attached.length; i++) if (Attached[i] != None) Attached[i].PawnBaseDied(); AmbientSound = None; if( Level.NetMode==NM_DedicatedServer ) SetTimer(1,False); SetTimer(5,False); } simulated function Timer() { if( Level.NetMode==NM_DedicatedServer ) { Destroy(); Return; } if( Physics!=PHYS_None ) { if( VSize(Velocity)>10 ) { SetTimer(1,False); Return; } SetPhysics(PHYS_None); SetTimer(30,False); if(PlayerShadow != None) PlayerShadow.bShadowActive = false; } else if( (Level.TimeSeconds-LastRenderTime)>40 || Level.bDropDetail ) Destroy(); else SetTimer(5,False); } // We shorten the lifetime when the guys comes to rest. // Alex: No , you dont. event KVelDropBelow() { } } simulated event Destroyed() { local int i; // Make attached explosives blow up when this pawn dies for( i=0; i damageType, vector HitLocation) { local Vector TossVel; local Trigger T; local NavigationPoint N; local PlayerDeathMark D; local Projectile PP; local FakePlayerPawn FP; local int i; if ( bDeleteMe || Level.bLevelChange || Level.Game == None ) return; // already destroyed, or level is being cleaned up if ( DamageType.default.bCausedByWorld && (Killer == None || Killer == Controller) && LastHitBy != None ) Killer = LastHitBy; // mutator hook to prevent deaths // WARNING - don't prevent bot suicides - they suicide when really needed if ( Level.Game.PreventDeath(self, Killer, damageType, HitLocation) ) { Health = max(Health, 1); //mutator should set this higher return; } // Turn off the auxilary collision when the player dies if ( AuxCollisionCylinder != none ) { AuxCollisionCylinder.SetCollision(false,false,false); } // Hack fix for team-killing. if( KFPlayerReplicationInfo(PlayerReplicationInfo)!=None ) { FP = KFPlayerReplicationInfo(PlayerReplicationInfo).GetBlamePawn(); if( FP!=None ) { ForEach DynamicActors(Class'Projectile',PP) { if( PP.Instigator==Self ) PP.Instigator = FP; } } } D = Spawn(Class'PlayerDeathMark'); if( D!=None ) D.Velocity = Velocity; Health = Min(0, Health); if ( Weapon != None && (DrivenVehicle == None || DrivenVehicle.bAllowWeaponToss) ) { if ( Controller != None ) Controller.LastPawnWeapon = Weapon.Class; Weapon.HolderDied(); TossVel = Vector(GetViewRotation()); TossVel = TossVel * ((Velocity Dot TossVel) + 500) + Vect(0,0,200); TossWeapon(TossVel); } if ( DrivenVehicle != None ) { Velocity = DrivenVehicle.Velocity; DrivenVehicle.DriverDied(); } if ( Controller != None ) { Controller.WasKilledBy(Killer); Level.Game.Killed(Killer, Controller, self, damageType); } else Level.Game.Killed(Killer, Controller(Owner), self, damageType); DrivenVehicle = None; if ( Killer != None ) TriggerEvent(Event, self, Killer.Pawn); else TriggerEvent(Event, self, None); // make sure to untrigger any triggers requiring player touch if ( IsPlayerPawn() || WasPlayerPawn() ) { PhysicsVolume.PlayerPawnDiedInVolume(self); ForEach TouchingActors(class'Trigger',T) T.PlayerToucherDied(self); // event for HoldObjectives ForEach TouchingActors(class'NavigationPoint', N) if ( N.bReceivePlayerToucherDiedNotify ) N.PlayerToucherDied( Self ); } // remove powerup effects, etc. RemovePowerups(); Velocity.Z *= 1.3; // Make attached explosives blow up when this pawn dies for( i=0; i 1 && Level.TimeSeconds - LastDropCashMessageTime > DropCashMessageDelay ) { PlayerController(Controller).Speech('AUTO', 4, ""); } // Hack to get Slot machines to accept dosh that's thrown inside their collision cylinder. ForEach CashPickup.TouchingActors(class 'Actor', A) { if(A.IsA('KF_Slot_Machine')) { A.Touch(Cashpickup); } } } } // Used to attach an emitter instead of an xemitter simulated function AttachEmitterEffect( class EmitterClass, Name BoneName, Vector Location, Rotator Rotation ) { local Actor a; local int i; if( bSkeletized || (BoneName == 'None') ) return; for( i = 0; i < Attached.Length; i++ ) { if( Attached[i] == None ) continue; if( Attached[i].AttachmentBone != BoneName ) continue; if( ClassIsChildOf( EmitterClass, Attached[i].Class ) ) return; } a = Spawn( EmitterClass,,, Location, Rotation ); if( !AttachToBone( a, BoneName ) ) { log( "Couldn't attach "$EmitterClass$" to "$BoneName, 'Error' ); a.Destroy(); return; } for( i = 0; i < Attached.length; i++ ) { if( Attached[i] == a ) break; } a.SetRelativeRotation( Rotation ); } simulated function RemoveFlamingEffects() { local int i; if( Level.NetMode == NM_DedicatedServer ) return; for( i=0; i GetVeteran() { if( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none ) { return KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill; } return class'KFVeterancyTypes'; // The base neutral class. } function bool CanCarry( float Weight ) { Return True; } // Validate that client is not hacking. function bool CanBuyNow() { local ShopVolume Sh; if( KFGameType(Level.Game)==None || KFGameType(Level.Game).bWaveInProgress || PlayerReplicationInfo==None ) return False; foreach TouchingActors(Class'ShopVolume',Sh) Return True; Return False; } function bool ItemIsBuyable( Class IC ) { local int i; if( LevRls==None ) { ForEach DynamicActors(Class'KFLevelRules',LevRls) Break; if( LevRls==None ) Return False; } For( i=0; i<25; i++ ) { if( LevRls.ItemForSale[i]==IC ) Return True; } Return False; } simulated function ClientCurrentWeaponSold() { local Inventory I; local int Count; for ( I = Inventory; I != none && Count < 50; I = I.Inventory) { if ( I != Weapon && I != PendingWeapon && Weapon(I) != none ) { PendingWeapon = Weapon(I); break; } Count++; } ChangedWeapon(); } simulated function ClientForceChangeWeapon(Inventory NewWeapon) { PendingWeapon = Weapon(NewWeapon); ChangedWeapon(); } function ServerBuyPotato() { local Controller C; for ( C = Level.ControllerList; C != none; C = C.NextController ) { if ( PlayerController(C) != none && PlayerController(C).SteamStatsAndAchievements != none ) { PlayerController(C).SteamStatsAndAchievements.SetSteamAchievementCompleted(132); } } PlayerReplicationInfo.Score -= 70000; } function ServerBuyWeapon( Class WClass, float ItemWeight ) { local Inventory I, J; local float Price; local bool bIsDualWeapon, bHasDual9mms, bHasDualHCs, bHasDualRevolvers; if ( !CanBuyNow() || Class(WClass) == none || Class(WClass.Default.PickupClass) == none ) { return; } if ( Class(WClass).Default.AppID > 0 && Class(WClass).Default.UnlockedByAchievement != -1 ) { if ( KFSteamStatsAndAchievements(PlayerReplicationInfo.SteamStatsAndAchievements) == none || (!KFSteamStatsAndAchievements(PlayerReplicationInfo.SteamStatsAndAchievements).PlayerOwnsWeaponDLC(Class(WClass).Default.AppID) && KFSteamStatsAndAchievements(PlayerReplicationInfo.SteamStatsAndAchievements).Achievements[Class(WClass).Default.UnlockedByAchievement].bCompleted != 1 )) { return; } } else if ( Class(WClass).Default.AppID > 0 ) { if ( KFSteamStatsAndAchievements(PlayerReplicationInfo.SteamStatsAndAchievements) == none || !KFSteamStatsAndAchievements(PlayerReplicationInfo.SteamStatsAndAchievements).PlayerOwnsWeaponDLC(Class(WClass).Default.AppID)) { return; } } else if ( Class(WClass).Default.UnlockedByAchievement != -1 ) { if ( KFSteamStatsAndAchievements(PlayerReplicationInfo.SteamStatsAndAchievements) == none || KFSteamStatsAndAchievements(PlayerReplicationInfo.SteamStatsAndAchievements).Achievements[Class(WClass).Default.UnlockedByAchievement].bCompleted != 1 ) { return; } } Price = class(WClass.Default.PickupClass).Default.Cost; if ( KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none ) { Price *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), WClass.Default.PickupClass); } for ( I=Inventory; I!=None; I=I.Inventory ) { if( I.Class==WClass ) { Return; // Already has weapon. } if ( I.Class == class'Dualies' ) { bHasDual9mms = true; } else if ( I.Class == class'DualDeagle' || I.Class == class'GoldenDualDeagle' ) { bHasDualHCs = true; } else if ( I.Class == class'Dual44Magnum' ) { bHasDualRevolvers = true; } } if ( WClass == class'DualDeagle' ) { for ( J = Inventory; J != None; J = J.Inventory ) { if ( J.class == class'Deagle' ) { Price = Price / 2; break; } } bIsDualWeapon = true; bHasDualHCs = true; } if ( WClass == class'GoldenDualDeagle' ) { for ( J = Inventory; J != None; J = J.Inventory ) { if ( J.class == class'GoldenDeagle' ) { Price = Price / 2; break; } } bIsDualWeapon = true; bHasDualHCs = true; } if ( WClass == class'Dual44Magnum' ) { for ( J = Inventory; J != None; J = J.Inventory ) { if ( J.class == class'Magnum44Pistol' ) { Price = Price / 2; break; } } bIsDualWeapon = true; bHasDualRevolvers = true; } if ( WClass == class'DualMK23Pistol' ) { for ( J = Inventory; J != None; J = J.Inventory ) { if ( J.class == class'MK23Pistol' ) { Price = Price / 2; break; } } bIsDualWeapon = true; } if ( WClass == class'DualFlareRevolver' ) { for ( J = Inventory; J != None; J = J.Inventory ) { if ( J.class == class'FlareRevolver' ) { Price = Price / 2; break; } } bIsDualWeapon = true; } bIsDualWeapon = bIsDualWeapon || WClass == class'Dualies'; if ( !CanCarry(ItemWeight) ) { Return; } if ( PlayerReplicationInfo.Score < Price ) { Return; // Not enough CASH. } 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; I.GiveTo(self); PlayerReplicationInfo.Score -= Price; if ( bIsDualWeapon ) { KFSteamStatsAndAchievements(PlayerReplicationInfo.SteamStatsAndAchievements).OnDualsAddedToInventory(bHasDual9mms, bHasDualHCs, bHasDualRevolvers); } ClientForceChangeWeapon(I); } SetTraderUpdate(); } function ServerSellWeapon( Class WClass ) { local Inventory I; local Single NewSingle; local Deagle NewDeagle; local Magnum44Pistol New44Magnum; local MK23Pistol NewMK23; local FlareRevolver NewFlare; local float Price; if ( !CanBuyNow() || Class(WClass) == none || Class(WClass.Default.PickupClass) == none ) { 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 = int(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 ( Dualies(I) != none && DualDeagle(I) == none && Dual44Magnum(I) == none && DualMK23Pistol(I) == none && DualFlareRevolver(I) == none ) { NewSingle = Spawn(class'Single'); NewSingle.GiveTo(self); } if ( DualDeagle(I) != none ) { if( GoldenDualDeagle(I) != none ) { NewDeagle = Spawn(class'GoldenDeagle'); } else { NewDeagle = Spawn(class'Deagle'); } NewDeagle.GiveTo(self); Price = Price / 2; NewDeagle.SellValue = Price; } if ( Dual44Magnum(I) != none ) { New44Magnum = Spawn(class'Magnum44Pistol'); New44Magnum.GiveTo(self); Price = Price / 2; New44Magnum.SellValue = Price; } if ( DualMK23Pistol(I) != none ) { NewMK23 = Spawn(class'MK23Pistol'); NewMK23.GiveTo(self); Price = Price / 2; NewMK23.SellValue = Price; } if ( DualFlareRevolver(I) != none ) { NewFlare = Spawn(class'FlareRevolver'); NewFlare.GiveTo(self); Price = Price / 2; NewFlare.SellValue = Price; } if ( I == Weapon || I == PendingWeapon ) { ClientCurrentWeaponSold(); } PlayerReplicationInfo.Score += Price; I.Destroyed(); I.Destroy(); SetTraderUpdate(); if ( KFGameType(Level.Game) != none ) { KFGameType(Level.Game).WeaponDestroyed(WClass); } return; } } } function ServerBuyKevlar() { local float Cost; local int UnitsAffordable; Cost = class'Vest'.default.ItemCost * ((100.0 - ShieldStrength) / 100.0); if ( KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none) { Cost *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), class'Vest'); } if ( !CanBuyNow() || ShieldStrength==100 ) { SetTraderUpdate(); Return; } if ( PlayerReplicationInfo.Score >= Cost ) { PlayerReplicationInfo.Score -= Cost; ShieldStrength = 100; } else if ( ShieldStrength > 0 ) { Cost = class'Vest'.default.ItemCost; if ( KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none) { Cost *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), class'Vest'); } Cost /= 100.0; UnitsAffordable = int(PlayerReplicationInfo.Score / Cost); PlayerReplicationInfo.Score -= int(Cost * UnitsAffordable); ShieldStrength += UnitsAffordable; } SetTraderUpdate(); } function ServerBuyFirstAid() { local int Cost; Cost = class'FirstAidKit'.default.ItemCost; if( !CanBuyNow() || Health==100 ) { SetTraderUpdate(); Return; } if( PlayerReplicationInfo.Score < Cost ) { SetTraderUpdate(); Return; } PlayerReplicationInfo.Score -= Cost; GiveHealth(100, 100); SetTraderUpdate(); } function bool ServerBuyAmmo( Class AClass, bool bOnlyClip ) { local Inventory I; local float Price; local Ammunition AM; local KFWeapon KW; local int c; local float UsedMagCapacity; local Boomstick DBShotty; if ( !CanBuyNow() || AClass == None ) { SetTraderUpdate(); return false; } for ( I=Inventory; I != none; I=I.Inventory ) { if ( I.Class == AClass ) { AM = Ammunition(I); } else if ( KW == None && KFWeapon(I) != None && (Weapon(I).AmmoClass[0] == AClass || Weapon(I).AmmoClass[1] == AClass) ) { KW = KFWeapon(I); } } if ( KW == none || AM == none ) { SetTraderUpdate(); return false; } DBShotty = Boomstick(KW); AM.MaxAmmo = AM.default.MaxAmmo; if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none ) { AM.MaxAmmo = int(float(AM.MaxAmmo) * KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.AddExtraAmmoFor(KFPlayerReplicationInfo(PlayerReplicationInfo), AClass)); } if ( AM.AmmoAmount >= AM.MaxAmmo ) { SetTraderUpdate(); return false; } Price = class(KW.PickupClass).default.AmmoCost * KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetAmmoCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), KW.PickupClass); // Clip price. if ( KW.bHasSecondaryAmmo && AClass == KW.FireModeClass[1].default.AmmoClass ) { UsedMagCapacity = 1; // Secondary Mags always have a Mag Capacity of 1? KW.default.SecondaryMagCapacity; } else { UsedMagCapacity = KW.default.MagCapacity; } if( KW.PickupClass == class'HuskGunPickup' ) { UsedMagCapacity = class(KW.PickupClass).default.BuyClipSize; } if ( bOnlyClip ) { if ( KFPlayerReplicationInfo(PlayerReplicationInfo) != none && KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none ) { if( KW.PickupClass == class'HuskGunPickup' ) { c = UsedMagCapacity * KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.AddExtraAmmoFor(KFPlayerReplicationInfo(PlayerReplicationInfo), AM.Class); } else { c = UsedMagCapacity * KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetMagCapacityMod(KFPlayerReplicationInfo(PlayerReplicationInfo), KW); } } else { c = UsedMagCapacity; } } else { c = (AM.MaxAmmo-AM.AmmoAmount); } Price = int(float(c) / UsedMagCapacity * Price); if ( PlayerReplicationInfo.Score < Price ) // Not enough CASH (so buy the amount you CAN buy). { c *= (PlayerReplicationInfo.Score/Price); if ( c == 0 ) { SetTraderUpdate(); return false; // Couldn't even afford 1 bullet. } AM.AddAmmo(c); if( DBShotty != none ) { DBShotty.AmmoPickedUp(); } PlayerReplicationInfo.Score = Max(PlayerReplicationInfo.Score - (float(c) / UsedMagCapacity * Price), 0); SetTraderUpdate(); return false; } PlayerReplicationInfo.Score = int(PlayerReplicationInfo.Score-Price); AM.AddAmmo(c); if( DBShotty != none ) { DBShotty.AmmoPickedUp(); } SetTraderUpdate(); return true; } function ServerSellAmmo( Class AClass ) { local Inventory I; local float Price; local Ammunition AM; local KFWeapon KW; local int c; if( !CanBuyNow() || AClass==None ) Return; For( I=Inventory; I!=None; I=I.Inventory ) { if( I.Class==AClass ) AM = Ammunition(I); else if( KW==None && KFWeapon(I)!=None && (Weapon(I).AmmoClass[0]==AClass || Weapon(I).AmmoClass[1]==AClass) ) KW = KFWeapon(I); } if( (AM==None && KW==None) || AM.AmmoAmount==AM.MaxAmmo ) Return; Price = Class(KW.PickupClass).Default.AmmoCost; // Clip price. c = KW.Default.MagCapacity; if( c>AM.AmmoAmount ) c = AM.AmmoAmount; Price = float(c)/float(KW.Default.MagCapacity)*Price*0.75; PlayerReplicationInfo.Score+=Price; AM.AmmoAmount-=c; SetTraderUpdate(); } simulated function SetTraderUpdate() { if ( KFPlayerController(Controller) != none ) { KFPlayerController(Controller).DoTraderUpdate(); } } // Allow players spawn on top of each other. event bool EncroachingOn( actor Other ) { if ( Other.bWorldGeometry || Other.bBlocksTeleport ) return true; if ( (Vehicle(Other) != None) && (Weapon != None) && Weapon.IsA('Translauncher') ) return true; return false; } event EncroachedBy( actor Other ) { if ( Pawn(Other)!=None && Vehicle(Other)==None && KFPawn(Other)==None ) gibbedBy(Other); } function name GetWeaponBoneFor(Inventory I) { return 'WeaponR_Bone'; } function name GetOffhandBoneFor(Inventory I) { return 'WeaponL_Bone'; } simulated function SetWeaponAttachment(WeaponAttachment NewAtt) { local KFWeaponAttachment KFWeapAttach; local DualiesAttachment DualiesAttach; local int i; WeaponAttachment = NewAtt; KFWeapAttach = KFWeaponAttachment(WeaponAttachment); DualiesAttach = DualiesAttachment(WeaponAttachment); // For remote clients set the brother class for dualies if( Level.NetMode == NM_Client && DualiesAttach != none ) { for( i = 0; i < Attached.Length; i++ ) { if( Attached[i] == None ) continue; if( DualiesAttachment(Attached[i]) != none && DualiesAttach != Attached[i] ) { DualiesAttach.brother = DualiesAttachment(Attached[i]); DualiesAttachment(Attached[i]).brother = DualiesAttach; break; } } } if( KFWeapAttach != none ) { MovementAnims[0]= KFWeapAttach.MovementAnims[0]; MovementAnims[1]= KFWeapAttach.MovementAnims[1]; MovementAnims[2]= KFWeapAttach.MovementAnims[2]; MovementAnims[3]= KFWeapAttach.MovementAnims[3]; TurnLeftAnim = KFWeapAttach.TurnLeftAnim; TurnRightAnim = KFWeapAttach.TurnRightAnim; SwimAnims[0]= KFWeapAttach.SwimAnims[0]; SwimAnims[1]= KFWeapAttach.SwimAnims[1]; SwimAnims[2]= KFWeapAttach.SwimAnims[2]; SwimAnims[3]= KFWeapAttach.SwimAnims[3]; CrouchAnims[0]= KFWeapAttach.CrouchAnims[0]; CrouchAnims[1]= KFWeapAttach.CrouchAnims[1]; CrouchAnims[2]= KFWeapAttach.CrouchAnims[2]; CrouchAnims[3]= KFWeapAttach.CrouchAnims[3]; WalkAnims[0]= KFWeapAttach.WalkAnims[0]; WalkAnims[1]= KFWeapAttach.WalkAnims[1]; WalkAnims[2]= KFWeapAttach.WalkAnims[2]; WalkAnims[3]= KFWeapAttach.WalkAnims[3]; AirAnims[0]= KFWeapAttach.AirAnims[0]; AirAnims[1]= KFWeapAttach.AirAnims[1]; AirAnims[2]= KFWeapAttach.AirAnims[2]; AirAnims[3]= KFWeapAttach.AirAnims[3]; TakeoffAnims[0]= KFWeapAttach.TakeoffAnims[0]; TakeoffAnims[1]= KFWeapAttach.TakeoffAnims[1]; TakeoffAnims[2]= KFWeapAttach.TakeoffAnims[2]; TakeoffAnims[3]= KFWeapAttach.TakeoffAnims[3]; LandAnims[0]= KFWeapAttach.LandAnims[0]; LandAnims[1]= KFWeapAttach.LandAnims[1]; LandAnims[2]= KFWeapAttach.LandAnims[2]; LandAnims[3]= KFWeapAttach.LandAnims[3]; DoubleJumpAnims[0]= KFWeapAttach.DoubleJumpAnims[0]; DoubleJumpAnims[1]= KFWeapAttach.DoubleJumpAnims[1]; DoubleJumpAnims[2]= KFWeapAttach.DoubleJumpAnims[2]; DoubleJumpAnims[3]= KFWeapAttach.DoubleJumpAnims[3]; DodgeAnims[0]= KFWeapAttach.DodgeAnims[0]; DodgeAnims[1]= KFWeapAttach.DodgeAnims[1]; DodgeAnims[2]= KFWeapAttach.DodgeAnims[2]; DodgeAnims[3]= KFWeapAttach.DodgeAnims[3]; AirStillAnim = KFWeapAttach.AirStillAnim; TakeoffStillAnim = KFWeapAttach.TakeoffStillAnim; CrouchTurnRightAnim = KFWeapAttach.CrouchTurnRightAnim; CrouchTurnLeftAnim = KFWeapAttach.CrouchTurnLeftAnim; IdleCrouchAnim = KFWeapAttach.IdleCrouchAnim; IdleSwimAnim = KFWeapAttach.IdleSwimAnim; IdleWeaponAnim = KFWeapAttach.IdleWeaponAnim; IdleRestAnim = KFWeapAttach.IdleRestAnim; IdleChatAnim = KFWeapAttach.IdleChatAnim; FireAnims[0]=KFWeapAttach.FireAnims[0]; FireAnims[1]=KFWeapAttach.FireAnims[1]; FireAnims[2]=KFWeapAttach.FireAnims[2]; FireAnims[3]=KFWeapAttach.FireAnims[3]; FireAltAnims[0]=KFWeapAttach.FireAltAnims[0]; FireAltAnims[1]=KFWeapAttach.FireAltAnims[1]; FireAltAnims[2]=KFWeapAttach.FireAltAnims[2]; FireAltAnims[3]=KFWeapAttach.FireAltAnims[3]; FireCrouchAnims[0]=KFWeapAttach.FireCrouchAnims[0]; FireCrouchAnims[1]=KFWeapAttach.FireCrouchAnims[1]; FireCrouchAnims[2]=KFWeapAttach.FireCrouchAnims[2]; FireCrouchAnims[3]=KFWeapAttach.FireCrouchAnims[3]; FireCrouchAltAnims[0]=KFWeapAttach.FireCrouchAltAnims[0]; FireCrouchAltAnims[1]=KFWeapAttach.FireCrouchAltAnims[1]; FireCrouchAltAnims[2]=KFWeapAttach.FireCrouchAltAnims[2]; FireCrouchAltAnims[3]=KFWeapAttach.FireCrouchAltAnims[3]; HitAnims[0]=KFWeapAttach.HitAnims[0]; HitAnims[1]=KFWeapAttach.HitAnims[1]; HitAnims[2]=KFWeapAttach.HitAnims[2]; HitAnims[3]=KFWeapAttach.HitAnims[3]; PostFireBlendStandAnim = KFWeapAttach.PostFireBlendStandAnim; PostFireBlendCrouchAnim = KFWeapAttach.PostFireBlendCrouchAnim; } } simulated function PlayDirectionalHit(Vector HitLoc) { local Vector X,Y,Z, Dir; if ( DrivenVehicle != None ) return; GetAxes(Rotation, X,Y,Z); HitLoc.Z = Location.Z; // random if ( VSize(Location - HitLoc) < 1.0 ) { Dir = VRand(); } // hit location based else { Dir = -Normal(Location - HitLoc); } if ( Dir Dot X > 0.7 || Dir == vect(0,0,0)) { PlayAnim(HitAnims[0],, 0.1); } else if ( Dir Dot X < -0.7 ) { PlayAnim(HitAnims[1],, 0.1); } else if ( Dir Dot Y > 0 ) { PlayAnim(HitAnims[3],, 0.1); } else { PlayAnim(HitAnims[2],, 0.1); } } //----------------------------------------------------------------------------- // FootStepping - overriden to support custom footstep volumes //----------------------------------------------------------------------------- simulated function FootStepping(int Side) { local int SurfaceTypeID, i; local actor A; local material FloorMat; local vector HL,HN,Start,End,HitLocation,HitNormal; local float FootVolumeMod; SurfaceTypeID = 0; FootVolumeMod = 1.0; for ( i=0; i 10 ) WalkBob.Z = WalkBob.Z + 0.75 * (Bob * UsedBobScaleModifier) * Speed2D * sin(16 * BobTime); if ( LandBob > 0.01 ) { AppliedBob += FMin(1, 16 * deltatime) * LandBob; LandBob *= (1 - 8*Deltatime); } } else if ( Physics == PHYS_Swimming ) { Speed2D = Sqrt(Velocity.X * Velocity.X + Velocity.Y * Velocity.Y); WalkBob = Y * Bob * 0.5 * Speed2D * sin(4.0 * Level.TimeSeconds); WalkBob.Z = Bob * 1.5 * Speed2D * sin(8.0 * Level.TimeSeconds); } else { BobTime = 0; WalkBob = WalkBob * (1 - FMin(1, 8 * deltatime)); } if ( (Physics != PHYS_Walking) || (VSize(Velocity) < 10) || ((PlayerController(Controller) != None) && PlayerController(Controller).bBehindView) ) return; m = int(0.5 * Pi + 9.0 * OldBobTime/Pi); n = int(0.5 * Pi + 9.0 * BobTime/Pi); if ( (m != n) ) FootStepping(0); } function Sound GetSound(xPawnSoundGroup.ESoundType soundType) { local int SurfaceTypeID; local actor A; local vector HL,HN,Start,End; local material FloorMat; if( SoundGroupClass == none ) { return None; } if( soundType == EST_Land || soundType == EST_Jump ) { 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 SoundGroupClass.static.GetSound(soundType, SurfaceTypeID); } /* Quickly select syring, alt fire once, select old weapon again */ simulated exec function QuickHeal() { local Syringe S; local Inventory I; local byte C; if ( Health>=HealthMax ) return; for( I=Inventory; (I!=None && C++<250); I=I.Inventory ) { S = Syringe(I); if( S!=None ) break; } if ( S == none ) return; if ( S.ChargeBar() < 0.95 ) { if ( PlayerController(Controller) != none && HUDKillingFloor(PlayerController(Controller).myHud) != none ) { HUDKillingFloor(PlayerController(Controller).myHud).ShowQuickSyringe(); } return; // No can heal. } bIsQuickHealing = 1; if ( Weapon==None ) { PendingWeapon = S; ChangedWeapon(); } else if ( Weapon!=S ) { PendingWeapon = S; Weapon.PutDown(); } else // Syringe already selected, just start healing. { bIsQuickHealing = 0; S.HackClientStartFire(); } } simulated exec function ToggleFlashlight() { local KFWeapon KFWeap; if ( Controller == none ) { return; } if ( KFWeapon(Weapon) != none && KFWeapon(Weapon).bTorchEnabled ) { Weapon.ClientStartFire(1); } else { KFWeap = KFWeapon(FindInventoryType(class'Shotgun')); if ( KFWeap == none ) { KFWeap = KFWeapon(FindInventoryType(class'BenelliShotgun')); if ( KFWeap == none ) { KFWeap = KFWeapon(FindInventoryType(class'Dualies')); if ( KFWeap == none || DualDeagle(KFWeap) != none || Dual44Magnum(KFWeap) != none || DualMK23Pistol(KFWeap) != none || DualFlareRevolver(KFWeap) != none ) { KFWeap = KFWeapon(FindInventoryType(class'Single')); } } } if ( KFWeap != none ) { KFWeap.bPendingFlashlight = true; PendingWeapon = KFWeap; if ( Weapon != none ) { Weapon.PutDown(); } else { ChangedWeapon(); } } } } function GiveWeapon(string aClassName ) { local class WeaponClass; local Inventory I; local Weapon NewWeapon; local bool bHasDual9mms, bHasDualHCs, bHasDualRevolvers; WeaponClass = class(DynamicLoadObject(aClassName, class'Class')); for ( I = Inventory; I != none; I = I.Inventory ) { if( I.Class == WeaponClass ) { Return; // Already has weapon. } if ( I.Class == class'Dualies' ) { bHasDual9mms = true; } else if ( I.Class == class'DualDeagle' || I.Class == class'GoldenDualDeagle' ) { bHasDualHCs = true; } else if ( I.Class == class'Dual44Magnum' ) { bHasDualRevolvers = true; } } newWeapon = Spawn(WeaponClass); if ( newWeapon != none ) { newWeapon.GiveTo(self); if ( WeaponClass == class'Dualies' || WeaponClass == class'DualDeagle' || WeaponClass == class'GoldenDualDeagle' || WeaponClass == class'Dual44Magnum' ) { KFSteamStatsAndAchievements(PlayerReplicationInfo.SteamStatsAndAchievements).OnDualsAddedToInventory(bHasDual9mms, bHasDualHCs, bHasDualRevolvers); } if ( KFGameType(Level.Game) != none ) { KFGameType(Level.Game).WeaponSpawned(newWeapon); } } } function bool DoJump( bool bUpdating ) { if ( Super.DoJump(bUpdating) ) { // Take you out of ironsights if you jump on a non-lowgrav map if( KFWeapon(Weapon) != none && PhysicsVolume.Gravity.Z <= class'PhysicsVolume'.default.Gravity.Z ) { KFWeapon(Weapon).ForceZoomOutTime = Level.TimeSeconds + 0.01; } return true; } return false; } function string GetPlayerName() { if( PlayerReplicationInfo != none ) { return PlayerReplicationInfo.PlayerName; } return ""; } defaultproperties { bCanBeHealed=true BileFrequency=0.5 // 1.5 ClientIdleWeaponAnim="" ShieldStrengthMax=100.000000 ShieldHitMat=None GibGroupClass=Class'KFMod.KFHumanGibGroup' SoundGroupClass=Class'KFMod.KFMaleSoundGroup' TeleportFXClass=None TransEffects(0)=None TransEffects(1)=None DeResTime=0.000000 DeResMat0=Texture'KFCharacters.KFDeRez' DeResMat1=Texture'KFCharacters.KFDeRez' DeResLiftVel=(Points=(,(InVal=0.000000,OutVal=0.000000),(InVal=0.000000,OutVal=0.000000))) DeResLiftSoftness=(Points=((OutVal=0.000000),(InVal=0.000000,OutVal=0.000000),(InVal=0.000000,OutVal=0.000000))) DeResLateralFriction=0.000000 RagdollLifeSpan=9999.000000 RagDeathVel=75.000000 RagShootStrength=6000.000000 RagDeathUpKick=100.000000 TransOutEffect(0)=None TransOutEffect(1)=None RequiredEquipment(0)="none" RequiredEquipment(1)="none" bScriptPostRender=True MeleeRange=80.000000 GroundSpeed=240.000000 WaterSpeed=180.000000 AirSpeed=240.000000 JumpZ=300.000000 BaseEyeHeight=44.0//54.000000 EyeHeight=44.0//54.000000 DodgeSpeedFactor=1.000000 DodgeSpeedZ=0.000000 SwimAnims(0)="WalkF" SwimAnims(1)="WalkB" SwimAnims(2)="WalkL" SwimAnims(3)="WalkR" AmbientGlow=0 bClientAnim=True CollisionRadius=20.0//26.000000 CollisionHeight=40.000000 CrouchRadius=20.0 bBlockKarma=True Mass=400.000000 BurnEffect = class 'KFMonsterFlame' bRealDeathType=True bDoAdjustFeet=True bDetailedShadows=True MovementAnims(0)=JogF_Bullpup//RunF MovementAnims(1)=JogB_Bullpup//RunB MovementAnims(2)=JogL_Bullpup//RunL MovementAnims(3)=JogR_Bullpup//RunR // SwimAnims(0)=SwimF // SwimAnims(1)=SwimB // SwimAnims(2)=SwimL // SwimAnims(3)=SwimR CrouchAnims(0)=CHwalkF_BullPup CrouchAnims(1)=CHwalkB_BullPup CrouchAnims(2)=CHwalkL_BullPup CrouchAnims(3)=CHwalkR_BullPup WalkAnims(0)=WalkF_Bullpup WalkAnims(1)=WalkB_Bullpup WalkAnims(2)=WalkL_Bullpup WalkAnims(3)=WalkR_Bullpup AirStillAnim=JumpF_Mid AirAnims(0)=JumpF_Mid AirAnims(1)=JumpF_Mid AirAnims(2)=JumpL_Mid AirAnims(3)=JumpR_Mid TakeoffStillAnim=JumpF_Takeoff TakeoffAnims(0)=JumpF_Takeoff TakeoffAnims(1)=JumpF_Takeoff TakeoffAnims(2)=JumpL_Takeoff TakeoffAnims(3)=JumpR_Takeoff LandAnims(0)=JumpF_Land LandAnims(1)=JumpF_Land LandAnims(2)=JumpL_Land LandAnims(3)=JumpR_Land DoubleJumpAnims(0)=DoubleJumpF DoubleJumpAnims(1)=DoubleJumpB DoubleJumpAnims(2)=DoubleJumpL DoubleJumpAnims(3)=DoubleJumpR DodgeAnims(0)=JumpF_Takeoff DodgeAnims(1)=JumpF_Takeoff DodgeAnims(2)=JumpL_Takeoff DodgeAnims(3)=JumpR_Takeoff WallDodgeAnims(0)=WallDodgeF WallDodgeAnims(1)=WallDodgeB WallDodgeAnims(2)=WallDodgeL WallDodgeAnims(3)=WallDodgeR TurnRightAnim=TurnR TurnLeftAnim=TurnL CrouchTurnRightAnim=CH_TurnR CrouchTurnLeftAnim=CH_TurnL IdleRestAnim=Idle_Rifle//Idle_Rest IdleCrouchAnim=CHIdle_BullPup IdleSwimAnim=Swim_Tread IdleWeaponAnim=Idle_Bullpup//Idle_Rifle IdleHeavyAnim=Idle_Bullpup//Idle_Biggun IdleRifleAnim=Idle_Bullpup//Idle_Rifle IdleChatAnim=Idle_Chat FireAnims(0)=Fire_Bullpup FireAnims(1)=Fire_Bullpup FireAnims(2)=Fire_Bullpup FireAnims(3)=Fire_Bullpup FireAltAnims(0)=Fire_Bullpup FireAltAnims(1)=Fire_Bullpup FireAltAnims(2)=Fire_Bullpup FireAltAnims(3)=Fire_Bullpup FireCrouchAnims(0)=CHFire_BullPup FireCrouchAnims(1)=CHFire_BullPup FireCrouchAnims(2)=CHFire_BullPup FireCrouchAnims(3)=CHFire_BullPup FireCrouchAltAnims(0)=CHFire_BullPup FireCrouchAltAnims(1)=CHFire_BullPup FireCrouchAltAnims(2)=CHFire_BullPup FireCrouchAltAnims(3)=CHFire_BullPup HitAnims(0)=HitF_Bullpup HitAnims(1)=HitB_Bullpup HitAnims(2)=HitL_Bullpup HitAnims(3)=HitR_Bullpup PostFireBlendStandAnim=Blend_Bullpup PostFireBlendCrouchAnim=CHBlend_Bullpup RootBone="CHR_Pelvis" HeadBone="CHR_Head" SpineBone1="CHR_Spine2" SpineBone2="CHR_Spine3" FireRootBone="CHR_Spine1" PrePivot=(X=0.0,Y=0.0,Z=0.0); Species=class'SPECIES_KFMaleHuman' GruntVolume=0.5 FootstepVolume = 0.45 QuietFootStepVolume=0.40 FootStepSoundRadius=125 BobSpeedModifier=0.90 BobScaleModifier=1.0 RagImpactSounds(0)=Sound'KF_PlayerGlobalSnd.Player_BodyImpact' SoundFootsteps(0)=Sound'KF_PlayerGlobalSnd.Player_StepDefault'//Sound'Inf_Player.FootStepDirt' SoundFootsteps(1)=Sound'KF_PlayerGlobalSnd.Player_StepDirt'//Sound'Inf_Player.FootstepGravel' // Rock SoundFootsteps(2)=Sound'KF_PlayerGlobalSnd.Player_StepDirt'//Sound'Inf_Player.FootStepDirt' // Dirt SoundFootsteps(3)=Sound'KF_PlayerGlobalSnd.Player_StepMetal'//Sound'Inf_Player.FootstepMetal' // Metal SoundFootsteps(4)=Sound'KF_PlayerGlobalSnd.Player_StepWood'//Sound'Inf_Player.FootstepWoodenfloor' // Wood SoundFootsteps(5)=Sound'KF_PlayerGlobalSnd.Player_StepGrass'//Sound'Inf_Player.FootstepGrass' // Plant SoundFootsteps(6)=Sound'KF_PlayerGlobalSnd.Player_StepDirt'//Sound'Inf_Player.FootStepDirt' // Flesh SoundFootsteps(7)=Sound'KF_PlayerGlobalSnd.Player_StepDefault'//Sound'Inf_Player.FootstepSnowRough' // Ice SoundFootsteps(8)=Sound'KF_PlayerGlobalSnd.Player_StepDefault'//Sound'Inf_Player.FootstepSnowHard' SoundFootsteps(9)=Sound'KF_PlayerGlobalSnd.Player_StepWater'//Sound'Inf_Player.FootstepWaterShallow' // Shallow Water SoundFootsteps(10)=Sound'KF_PlayerGlobalSnd.Player_StepBrGlass'//Sound'Inf_Player.FootstepGravel' // Glass- Replaceme SoundFootsteps(11)=Sound'KF_PlayerGlobalSnd.Player_StepDefault'//Sound'Inf_Player.FootstepGravel' // Gravel SoundFootsteps(12)=Sound'KF_PlayerGlobalSnd.Player_StepConc'//Sound'Inf_Player.FootstepAsphalt' // Concrete SoundFootsteps(13)=Sound'KF_PlayerGlobalSnd.Player_StepWood'//Sound'Inf_Player.FootstepWoodenfloor' // HollowWood SoundFootsteps(14)=Sound'KF_PlayerGlobalSnd.Player_StepDefault'//Sound'Inf_Player.FootstepMud' // Mud SoundFootsteps(15)=Sound'KF_PlayerGlobalSnd.Player_StepMetal'//Sound'Inf_Player.FootstepMetal' // MetalArmor SoundFootsteps(16)=Sound'KF_PlayerGlobalSnd.Player_StepDefault'//Sound'Inf_Player.FootstepAsphalt_P' // Paper SoundFootsteps(17)=Sound'KF_PlayerGlobalSnd.Player_StepDefault'//Sound'Inf_Player.FootStepDirt' // Cloth SoundFootsteps(18)=Sound'KF_PlayerGlobalSnd.Player_StepDefault'//Sound'Inf_Player.FootStepDirt' // Rubber SoundFootsteps(19)=Sound'KF_PlayerGlobalSnd.Player_StepDefault'//Sound'Inf_Player.FootStepDirt' // Crap SeveredHeadAttachScale=1.1 SeveredLegAttachScale=1.1 SeveredArmAttachScale=1.1 SeveredHeadAttachClass = class'SeveredHeadAttachment' SeveredArmAttachClass = class'SeveredArmAttachment' SeveredLegAttachClass = class'SeveredLegAttachment' NeckSpurtEmitterClass=class'DismembermentJetHead' LimbSpurtEmitterClass=class'DismembermentJetLimb' ObliteratedEffectClass=class'PlayerObliteratedEmitter' // These two are fallbacks. Should assign these in subclasses DetachedArmClass=class'SeveredArmSoldier' DetachedLegClass=class'SeveredLegSoldier' ProjectileBloodSplatClass=class'ROEffects.ProjectileBloodSplat' DecapitationSound=sound'KF_EnemyGlobalSnd.Generic_Decap' DropCashMessageDelay=10.0 bBlockHitPointTraces=False // whole body, do no further checks if we don't at least hit this Hitpoints(MAINCOLLISIONINDEX)=(PointRadius=40,PointHeight=60.0,PointScale=1.0,PointBone=CHR_Pelvis,PointOffset=(X=0.0,Y=-10.0,Z=0.0),DamageMultiplier=0.0,HitPointType=PHP_None) // head Hitpoints(1)=(PointRadius=6.5,PointHeight=8.0,PointScale=1.0,PointBone=CHR_Head,PointOffset=(X=2.0,Y=-2.0,Z=0.0),DamageMultiplier=5.0,HitPointType=PHP_Head) // body Hitpoints(2)=(PointRadius=13.0,PointHeight=15.0,PointScale=1.0,PointBone=CHR_Spine3,PointOffset=(X=0.0,Y=-5.0,Z=0.0),DamageMultiplier=1.0,HitPointType=PHP_Torso) Hitpoints(3)=(PointRadius=12.0,PointHeight=11.0,PointScale=1.0,PointBone=CHR_Spine1,PointOffset=(X=-3.0,Y=-3.0,Z=0.0),DamageMultiplier=1.0,HitPointType=PHP_Torso) // // // upper appendages Hitpoints(4)=(PointRadius=7.0,PointHeight=12.0,PointScale=1.0,PointBone=CHR_LThigh,PointOffset=(X=18.0,Y=1.0,Z=0.0),DamageMultiplier=0.5,HitPointType=PHP_Leg) Hitpoints(5)=(PointRadius=7.0,PointHeight=12.0,PointScale=1.0,PointBone=CHR_RThigh,PointOffset=(X=18.0,Y=1.0,Z=0.0),DamageMultiplier=0.5,HitPointType=PHP_Leg) Hitpoints(6)=(PointRadius=5.0,PointHeight=11.0,PointScale=1.0,PointBone=CHR_LArmUpper,PointOffset=(X=8.0,Y=0.0,Z=1.0),DamageMultiplier=0.3,HitPointType=PHP_Arm) Hitpoints(7)=(PointRadius=5.0,PointHeight=11.0,PointScale=1.0,PointBone=CHR_RArmUpper,PointOffset=(X=8.0,Y=0.0,Z=1.0),DamageMultiplier=0.3,HitPointType=PHP_Arm) // // // lower appendages Hitpoints(8)=(PointRadius=6.0,PointHeight=18.0,PointScale=1.0,PointBone=CHR_LCalf,PointOffset=(X=15.0,Y=0.0,Z=0.0),DamageMultiplier=0.4,HitPointType=PHP_Leg) Hitpoints(9)=(PointRadius=6.0,PointHeight=18.0,PointScale=1.0,PointBone=CHR_RCalf,PointOffset=(X=15.0,Y=0.0,Z=0.0),DamageMultiplier=0.4,HitPointType=PHP_Leg) Hitpoints(10)=(PointRadius=4.0,PointHeight=10.0,PointScale=1.0,PointBone=CHR_LArmForeArm,PointOffset=(X=6.0,Y=0.0,Z=0.0),DamageMultiplier=0.2,HitPointType=PHP_Arm) Hitpoints(11)=(PointRadius=4.0,PointHeight=10.0,PointScale=1.0,PointBone=CHR_RArmForeArm,PointOffset=(X=6.0,Y=0.0,Z=0.0),DamageMultiplier=0.2,HitPointType=PHP_Arm) // // // hands and feet Hitpoints(12)=(PointRadius=4.0,PointHeight=4.0,PointScale=1.0,PointBone=CHR_LArmPalm,PointOffset=(X=5.0,Y=2.0,Z=0.0),DamageMultiplier=0.1,HitPointType=PHP_Hand) Hitpoints(13)=(PointRadius=4.0,PointHeight=4.0,PointScale=1.0,PointBone=CHR_RArmPalm,PointOffset=(X=5.0,Y=2.0,Z=0.0),DamageMultiplier=0.1,HitPointType=PHP_Hand) Hitpoints(14)=(PointRadius=4.0,PointHeight=8.0,PointScale=1.0,PointBone=CHR_LToe1,PointOffset=(X=0.0,Y=0.0,Z=0.0),DamageMultiplier=0.1,HitPointType=PHP_Foot) Hitpoints(15)=(PointRadius=4.0,PointHeight=8.0,PointScale=1.0,PointBone=CHR_RToe1,PointOffset=(X=0.0,Y=0.0,Z=0.0),DamageMultiplier=0.1,HitPointType=PHP_Foot) bForceSkelUpdate=true; }