rott/kf_sources/XGame/Classes/xPawn.uc
2026-07-14 20:27:09 +07:00

2675 lines
74 KiB
Ucode

class xPawn extends UnrealPawn
config(User)
dependsOn(xUtil)
dependsOn(xPawnSoundGroup);
// if _RO_
//dependsOn(xPawnGibGroup);
// ifndef _RO_
//#exec OBJ LOAD FILE=GameSounds.uax
//#exec OBJ LOAD FILE=PlayerSounds.uax
//#exec OBJ LOAD FILE=PlayerFootSteps.uax
//#exec OBJ LOAD FILE=DanFX.utx
// ifndef _RO_
//#exec OBJ LOAD FILE=GeneralAmbience.uax
//#exec OBJ LOAD FILE=GeneralImpacts.uax
//#exec OBJ LOAD FILE=DeRez.utx
//#exec OBJ LOAD FILE=WeaponSounds.uax
var int RepeaterDeathCount;
var Combo CurrentCombo;
var bool bBerserk;
var bool bInvis;
var bool bOldInvis;
var bool bGibbed;
var bool bCanDodgeDoubleJump;
var bool bCanBoostDodge;
var bool bAlreadySetup;
var bool bSpawnIn;
var bool bSpawnDone;
var bool bFrozenBody;
var bool bFlaming;
var bool bRubbery;
var bool bClearWeaponOffsets; // for certain custom player models
var(UDamage) Material UDamageWeaponMaterial; // Weapon overlay material
var(UDamage) Sound UDamageSound;
var UDamageTimer UDamageTimer;
var float UDamageTime;
var float LastUDamageSoundTime;
var Material InvisMaterial;
var(Shield) float ShieldStrengthMax; // max strength
var float SmallShieldStrength; // for preventing shieldstacking
var(Shield) Material ShieldHitMat;
var(Shield) float ShieldHitMatTime;
var class<SpeciesType> Species;
var(Sounds) float GruntVolume;
var(Sounds) float FootstepVolume;
var transient int SimHitFxTicker;
// if _RO_
//var(Gib) class<xPawnGibGroup> GibGroupClass;
//var(Gib) int GibCountCalf;
//var(Gib) int GibCountForearm;
//var(Gib) int GibCountHead;
//var(Gib) int GibCountTorso;
//var(Gib) int GibCountUpperArm;
var float MinTimeBetweenPainSounds;
var localized string HeadShotMessage;
// Common sounds
//var(Sounds) sound SoundFootsteps[11]; // Indexed by ESurfaceTypes (sorry about the literal).
var(Sounds) class<xPawnSoundGroup> SoundGroupClass;
var class<Actor> TeleportFXClass;
var class<Actor> TransEffects[2];
var WeaponAttachment WeaponAttachment;
var ShadowProjector PlayerShadow;
var int MultiJumpRemaining;
var int MaxMultiJump;
var int MultiJumpBoost; // depends on the tolerance (100)
var name WallDodgeAnims[4];
var name IdleHeavyAnim;
var name IdleRifleAnim;
var name FireHeavyRapidAnim;
var name FireHeavyBurstAnim;
var name FireRifleRapidAnim;
var name FireRifleBurstAnim;
var name FireRootBone;
var enum EFireAnimState
{
FS_None,
FS_PlayOnce,
FS_Looping,
FS_Ready
} FireState;
var Mesh SkeletonMesh;
var bool bSkeletized;
var bool bDeRes;
var float DeResTime;
var Emitter DeResFX;
var Material DeResMat0, DeResMat1;
var(DeRes) InterpCurve DeResLiftVel; // speed (over time) at which body rises
var(DeRes) InterpCurve DeResLiftSoftness; // vertical 'sprinyness' (over time) of bone lifters
var(DeRes) float DeResGravScale; // reduce gravity on corpse during de-res
var(DeRes) float DeResLateralFriction; // sideways friction while lifting
var(Karma) float RagdollLifeSpan; // MAXIMUM time the ragdoll will be around. De-res's early if it comes to rest.
var(Karma) float RagInvInertia; // Use to work out how much 'spin' ragdoll gets on death.
var(Karma) float RagDeathVel; // How fast ragdoll moves upon death
var(Karma) float RagShootStrength; // How much effect shooting ragdolls has. Be careful!
var(Karma) float RagSpinScale; // Increase propensity to spin around Z (up).
var(Karma) float RagDeathUpKick; // Amount of upwards kick ragdolls get when they die
var(Karma) float RagGravScale;
var(Karma) material RagConvulseMaterial;
// Ragdoll impact sounds.
var(Karma) array<sound> RagImpactSounds;
var(Karma) float RagImpactSoundInterval;
var(Karma) float RagImpactVolume;
var transient float RagLastSoundTime;
var string RagdollOverride;
// translocate effect
var class<Actor> TransOutEffect[2];
var Controller OldController;
var Material RealSkins[4];
var class<TeamVoicePack> VoiceClass;
var(AI) globalconfig string PlacedCharacterName;
var globalconfig string PlacedFemaleCharacterName;
var byte TeamSkin; // what team's skin is currently set
replication
{
reliable if( Role==ROLE_Authority )
bInvis;
reliable if( bNetOwner && (Role==ROLE_Authority) )
bBerserk, MaxMultiJump, MultiJumpBoost, bCanDodgeDoubleJump, bCanBoostDodge;
reliable if( Role==ROLE_Authority )
ClientSetUDamageTime;
}
simulated function Fire( optional float F )
{
if ( (Weapon != None) && (Weapon.bBerserk != bBerserk) )
{
if ( bBerserk )
Weapon.StartBerserk();
else
Weapon.StopBerserk();
}
Super.Fire(F);
}
simulated function AltFire( optional float F )
{
if ( (Weapon != None) && (Weapon.bBerserk != bBerserk) )
{
if ( bBerserk )
Weapon.StartBerserk();
else
Weapon.StopBerserk();
}
Super.AltFire(F);
}
simulated function PlayWaiting() {}
function RosterEntry GetPlacedRoster()
{
PlayerReplicationInfo.CharacterName = PlacedCharacterName;
return class'xRosterEntry'.static.CreateRosterEntryCharacter(PlacedCharacterName);
}
function PossessedBy(Controller C)
{
Super.PossessedBy(C);
if ( Controller != None )
OldController = Controller;
}
// return true if was controlled by a Player (AI or human)
simulated function bool WasPlayerPawn()
{
return ( (OldController != None) && OldController.bIsPlayer );
}
function DoTranslocateOut(Vector PrevLocation)
{
if ( (PlayerReplicationInfo == None) || (PlayerReplicationInfo.Team == None) || (PlayerReplicationInfo.Team.TeamIndex == 0) )
Spawn(TransOutEffect[0], self,, PrevLocation, rotator(Location - PrevLocation));
else
Spawn(TransOutEffect[1], self,, PrevLocation, rotator(Location - PrevLocation));
}
// Set up default blending parameters and pose. Ensures the mesh doesn't have only a T-pose whenever it first springs into view.
simulated function AssignInitialPose()
{
if ( DrivenVehicle != None )
{
if ( HasAnim(DrivenVehicle.DriveAnim) )
LoopAnim(DrivenVehicle.DriveAnim,, 0.1);
else
LoopAnim('Vehicle_Driving',, 0.1);
}
else
TweenAnim(MovementAnims[0],0.0);
AnimBlendParams(1, 1.0, 0.2, 0.2, 'Bip01 Spine1');
BoneRefresh();
}
simulated function Destroyed()
{
if( PlayerShadow != None )
PlayerShadow.Destroy();
if( DeResFX != None )
{
DeResFX.Emitters[0].SkeletalMeshActor = None;
DeResFX.Kill();
}
Super.Destroyed();
}
simulated function RemoveFlamingEffects()
{
local int i;
if( Level.NetMode == NM_DedicatedServer )
return;
for( i=0; i<Attached.length; i++ )
{
if( Attached[i].IsA('xEmitter') && !Attached[i].IsA('BloodJet'))
{
xEmitter(Attached[i]).mRegen = false;
}
}
}
simulated event PhysicsVolumeChange( PhysicsVolume NewVolume )
{
if ( NewVolume.bWaterVolume )
RemoveFlamingEffects();
Super.PhysicsVolumeChange(NewVolume);
}
/* return a value (typically 0 to 1) adjusting pawn's perceived strength if under some special influence (like berserk)
*/
function float AdjustedStrength()
{
if ( bBerserk )
return 1.0;
return 0;
}
function DeactivateSpawnProtection()
{
if ( bSpawnDone )
return;
bSpawnDone = true;
if ( Level.TimeSeconds - SpawnTime < DeathMatch(Level.Game).SpawnProtectionTime )
{
bSpawnIn = true;
if ( OverlayMaterial == ShieldHitMat )
SetOverlayMaterial(None,0,true);
SpawnTime = Level.TimeSeconds - DeathMatch(Level.Game).SpawnProtectionTime - 1;
}
}
function PlayTeleportEffect( bool bOut, bool bSound)
{
if ( !bSpawnIn && (Level.TimeSeconds - SpawnTime < DeathMatch(Level.Game).SpawnProtectionTime) )
{
bSpawnIn = true;
SetOverlayMaterial( ShieldHitMat, DeathMatch(Level.Game).SpawnProtectionTime, false );
if ( (PlayerReplicationInfo == None) || (PlayerReplicationInfo.Team == None) || (PlayerReplicationInfo.Team.TeamIndex == 0) )
Spawn(TransEffects[0],,,Location + CollisionHeight * vect(0,0,0.75));
else
Spawn(TransEffects[1],,,Location + CollisionHeight * vect(0,0,0.75));
}
else if ( bOut )
DoTranslocateOut(Location);
else if ( (PlayerReplicationInfo == None) || (PlayerReplicationInfo.Team == None) || (PlayerReplicationInfo.Team.TeamIndex == 0) )
Spawn(TransEffects[0],self,,Location + CollisionHeight * vect(0,0,0.75));
else
Spawn(TransEffects[1],self,,Location + CollisionHeight * vect(0,0,0.75));
Super.PlayTeleportEffect( bOut, bSound );
}
function PlayMoverHitSound()
{
PlaySound(SoundGroupClass.static.GetHitSound(), SLOT_Interact);
}
function PlayDyingSound()
{
// Dont play dying sound if a skeleton. Tricky without vocal chords.
if ( bSkeletized )
return;
if ( bGibbed )
{
// if _RO_
//PlaySound(GibGroupClass.static.GibSound(), SLOT_Pain,3.5*TransientSoundVolume,true,500);
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);
}
function Gasp()
{
if ( Role != ROLE_Authority )
return;
if ( BreathTime < 2 )
PlaySound(GetSound(EST_Gasp), SLOT_Interact);
else
PlaySound(GetSound(EST_BreatheAgain), SLOT_Interact);
}
function Controller GetKillerController()
{
if ( Controller != None )
return Controller;
if ( OldController != None )
return OldController;
return None;
}
simulated function int GetTeamNum()
{
if ( Controller != None )
return Controller.GetTeamNum();
if ( (DrivenVehicle != None) && (DrivenVehicle.Controller != None) )
return DrivenVehicle.Controller.GetTeamNum();
if ( OldController != None )
return OldController.GetTeamNum();
if ( (PlayerReplicationInfo == None) || (PlayerReplicationInfo.Team == None) )
return 255;
return PlayerReplicationInfo.Team.TeamIndex;
}
function TeamInfo GetTeam()
{
if ( PlayerReplicationInfo != None )
return PlayerReplicationInfo.Team;
if ( (DrivenVehicle != None) && (DrivenVehicle.PlayerReplicationInfo != None) )
return DrivenVehicle.PlayerReplicationInfo.Team;
if ( (OldController != None) && (OldController.PlayerReplicationInfo != None) )
return OldController.PlayerReplicationInfo.Team;
return None;
}
function RemovePowerups()
{
if (CurrentCombo != None)
{
CurrentCombo.Destroy();
if ( Controller != None )
Controller.Adrenaline = 0;
}
if ( UDamageTimer != None )
{
UDamageTimer.Destroy();
DisableUDamage();
}
Super.RemovePowerups();
}
simulated function TickFX(float DeltaTime)
{
local int i,NumSkins;
if ( SimHitFxTicker != HitFxTicker )
{
ProcessHitFX();
}
if(bInvis && !bOldInvis) // Going invisible
{
if ( Left(string(Skins[0]),21) ~= "UT2004PlayerSkins.Xan" )
Skins[2] = Material(DynamicLoadObject("UT2004PlayerSkins.XanMk3V2_abdomen", class'Material'));
// Save the 'real' non-invis skin
NumSkins = Clamp(Skins.Length,2,4);
for ( i=0; i<NumSkins; i++ )
{
RealSkins[i] = Skins[i];
Skins[i] = InvisMaterial;
}
// Remove/disallow projectors on invisible people
Projectors.Remove(0, Projectors.Length);
bAcceptsProjectors = false;
// Invisible - no shadow
if(PlayerShadow != None)
PlayerShadow.bShadowActive = false;
// No giveaway flames either
RemoveFlamingEffects();
}
else if(!bInvis && bOldInvis) // Going visible
{
NumSkins = Clamp(Skins.Length,2,4);
for ( i=0; i<NumSkins; i++ )
Skins[i] = RealSkins[i];
bAcceptsProjectors = Default.bAcceptsProjectors;
if(PlayerShadow != None)
PlayerShadow.bShadowActive = true;
}
bOldInvis = bInvis;
bDrawCorona = ( !bNoCoronas && !bInvis && (Level.NetMode != NM_DedicatedServer) && !bPlayedDeath && (Level.GRI != None) && Level.GRI.bAllowPlayerLights
&& (PlayerReplicationInfo != None) );
if ( bDrawCorona && (PlayerReplicationInfo.Team != None) )
{
if ( PlayerReplicationInfo.Team.TeamIndex == 0 )
// Temp commented out - Ramm
// Texture = Texture'RedMarker_t';
//else
// Texture = Texture'BlueMarker_t';
}
}
simulated function StartDriving(Vehicle V)
{
local int i;
Super.StartDriving(V);
if( PlayerShadow != None )
PlayerShadow.bShadowActive = false;
if ( xWeaponAttachment(WeaponAttachment) != None )
xWeaponAttachment(WeaponAttachment).Hide(true);
//hack for sticky grenades
for (i = 0; i < Attached.Length; i++)
if (Projectile(Attached[i]) != None)
Attached[i].SetBase(None);
}
simulated function StopDriving(Vehicle V)
{
Super.StopDriving(V);
if( PlayerShadow != None )
PlayerShadow.bShadowActive = !bInvis;
if ( xWeaponAttachment(WeaponAttachment) != None )
xWeaponAttachment(WeaponAttachment).Hide(false);
}
simulated function AttachEffect( class<xEmitter> 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 event SetHeadScale(float NewScale)
{
HeadScale = NewScale;
SetBoneScale(4,HeadScale,'head');
}
//simulated function SpawnGiblet( class<Gib> 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;
// // Temp commented out - Ramm
// //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;
//}
simulated function ProcessHitFX()
{
local Coords boneCoords;
local class<xEmitter> 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;
boneCoords = GetBoneCoords( HitFX[SimHitFxTicker].bone );
if ( !Level.bDropDetail && !bSkeletized )
{
// if _RO_
//AttachEffect( GibGroupClass.static.GetBloodEmitClass(), 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 'lthigh':
case 'rthigh':
//SpawnGiblet( GetGibClass(EGT_Calf), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
//SpawnGiblet( GetGibClass(EGT_Calf), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
//GibCountCalf -= 2;
break;
case 'rfarm':
case 'lfarm':
//SpawnGiblet( GetGibClass(EGT_UpperArm), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
//SpawnGiblet( GetGibClass(EGT_Forearm), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
//GibCountForearm--;
//GibCountUpperArm--;
break;
case 'head':
//SpawnGiblet( GetGibClass(EGT_Head), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
//GibCountTorso--;
break;
case 'spine':
case 'none':
//SpawnGiblet( GetGibClass(EGT_Torso), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
//GibCountTorso--;
bGibbed = true;
//while( GibCountHead-- > 0 )
//SpawnGiblet( GetGibClass(EGT_Head), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
//while( GibCountForearm-- > 0 )
//SpawnGiblet( GetGibClass(EGT_UpperArm), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
//while( GibCountUpperArm-- > 0 )
//SpawnGiblet( GetGibClass(EGT_Forearm), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
if ( !bFlaming && !Level.bDropDetail && (Level.DetailMode != DM_Low) && PlayerCanSeeMe() )
{
// extra gibs!!!
GibPerterbation = FMin(1.0, 1.5 * GibPerterbation);
//SpawnGiblet( GetGibClass(EGT_Calf), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
//SpawnGiblet( GetGibClass(EGT_Calf), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
//SpawnGiblet( GetGibClass(EGT_UpperArm), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
//SpawnGiblet( GetGibClass(EGT_Forearm), boneCoords.Origin, HitFX[SimHitFxTicker].rotDir, GibPerterbation );
}
break;
}
HideBone(HitFX[SimHitFxTicker].bone);
}
}
}
simulated function HideBone(name boneName)
{
local int BoneScaleSlot;
if( boneName == 'lthigh' )
boneScaleSlot = 0;
else if ( boneName == 'rthigh' )
boneScaleSlot = 1;
else if( boneName == 'rfarm' )
boneScaleSlot = 2;
else if ( boneName == 'lfarm' )
boneScaleSlot = 3;
else if ( boneName == 'head' )
boneScaleSlot = 4;
else if ( boneName == 'spine' )
boneScaleSlot = 5;
SetBoneScale(BoneScaleSlot, 0.0, BoneName);
}
function CalcHitLoc( Vector hitLoc, Vector hitRay, out Name boneName, out float dist )
{
boneName = GetClosestBone( hitLoc, hitRay, dist );
}
function DoDamageFX( Name boneName, int Damage, class<DamageType> DamageType, Rotator r )
{
local float DismemberProbability;
local bool bExtraGib;
if ( FRand() > 0.3f || Damage > 30 || Health <= 0 )
{
HitFX[HitFxTicker].damtype = DamageType;
if( Health <= 0 )
{
switch( boneName )
{
case 'lfoot':
boneName = 'lthigh';
break;
case 'rfoot':
boneName = 'rthigh';
break;
case 'rhand':
boneName = 'rfarm';
break;
case 'lhand':
boneName = 'lfarm';
break;
case 'rshoulder':
case 'lshoulder':
boneName = 'spine';
break;
}
if( DamageType.default.bAlwaysSevers || (Damage == 1000) )
{
HitFX[HitFxTicker].bSever = true;
if ( boneName == 'None' )
{
boneName = 'spine';
bExtraGib = true;
}
}
else if( (Damage*DamageType.Default.GibModifier > 50+120*FRand()) && (Damage + Health > 0) ) // total gib prob
{
HitFX[HitFxTicker].bSever = true;
boneName = 'spine';
bExtraGib = true;
}
else
{
DismemberProbability = Abs( (Health - Damage*DamageType.Default.GibModifier) / 130.0f );
switch( boneName )
{
case 'lthigh':
case 'rthigh':
case 'rfarm':
case 'lfarm':
case 'head':
if( FRand() < DismemberProbability )
HitFX[HitFxTicker].bSever = true;
break;
case 'None':
boneName = 'spine';
case 'spine':
if( FRand() < DismemberProbability * 0.3 )
{
HitFX[HitFxTicker].bSever = true;
if ( FRand() < 0.65 )
bExtraGib = true;
}
break;
}
}
}
if ( DamageType.default.bNeverSevers || class'GameInfo'.static.UseLowGore()
|| (Level.Game != None && Level.Game.PreventSever(self, boneName, Damage, DamageType)) )
{
HitFX[HitFxTicker].bSever = false;
bExtraGib = false;
}
HitFX[HitFxTicker].bone = boneName;
HitFX[HitFxTicker].rotDir = r;
HitFxTicker = HitFxTicker + 1;
if( HitFxTicker > ArrayCount(HitFX)-1 )
HitFxTicker = 0;
if ( bExtraGib )
{
if ( FRand() < 0.25 )
{
DoDamageFX('lthigh',1000,DamageType,r);
DoDamageFX('rthigh',1000,DamageType,r);
}
else if ( FRand() < 0.35 )
DoDamageFX('lthigh',1000,DamageType,r);
else if ( FRand() < 0.5 )
DoDamageFX('rthigh',1000,DamageType,r);
}
}
}
simulated function StartDeRes()
{
local KarmaParamsSkel skelParams;
local int i;
if( Level.NetMode == NM_DedicatedServer )
return;
AmbientGlow=254;
MaxLights=0;
// if _RO_
//DeResFX = Spawn(class'DeResPart', self, , Location);
if ( DeResFX != None )
{
DeResFX.Emitters[0].SkeletalMeshActor = self;
DeResFX.SetBase(self);
}
Skins[0] = DeResMat0;
Skins[1] = DeResMat1;
if ( Skins.Length > 2 )
{
for ( i=2; i<Skins.Length; i++ )
Skins[i] = DeResMat0;
}
if( Physics == PHYS_KarmaRagdoll )
{
// Attach bone lifter to raise body
KAddBoneLifter('bip01 Spine', DeResLiftVel, DeResLateralFriction, DeResLiftSoftness);
KAddBoneLifter('bip01 Spine2', DeResLiftVel, DeResLateralFriction, DeResLiftSoftness);
// Turn off gravity while de-res-ing
KSetActorGravScale(DeResGravScale);
// Turn off collision with the world for the ragdoll.
KSetBlockKarma(false);
// Turn off convulsions during de-res
skelParams = KarmaParamsSkel(KParams);
skelParams.bKDoConvulsions = false;
}
// ifndef _RO_
//AmbientSound = Sound'GeneralAmbience.Texture19';
SoundRadius = 40.0;
// Turn off collision when we de-res (avoids rockets etc. hitting corpse!)
SetCollision(false, false, false);
// Remove/disallow projectors
Projectors.Remove(0, Projectors.Length);
bAcceptsProjectors = false;
// Remove shadow
if(PlayerShadow != None)
PlayerShadow.bShadowActive = false;
// Remove flames
RemoveFlamingEffects();
// Turn off any overlays
SetOverlayMaterial(None, 0.0f, true);
bDeRes = true;
}
simulated function SetOverlayMaterial( Material mat, float time, bool bOverride )
{
if ( Level.bDropDetail || Level.DetailMode == DM_Low )
time *= 0.75;
Super.SetOverlayMaterial(mat,time,bOverride);
}
simulated function TickDeRes(float DeltaTime)
{
if(LifeSpan < 3.0)
{
AmbientGlow = BYTE(254.0 * (LifeSpan / 3.0)); // Scale down over time.
//ScaleGlow = 1.0 * (LifeSpan / 3.0); // Scale down over time.
//Log("SG:"$ScaleGlow$" AG:"$AmbientGlow);
}
}
simulated function Tick(float DeltaTime)
{
if ( Level.NetMode == NM_DedicatedServer )
return;
if ( Controller != None )
OldController = Controller;
TickFX(DeltaTime);
if ( bDeRes )
TickDeRes(DeltaTime);
}
simulated function PostBeginPlay()
{
Super.PostBeginPlay();
AssignInitialPose();
if(bActorShadows && bPlayerShadows && (Level.NetMode != NM_DedicatedServer))
{
PlayerShadow = Spawn(class'ShadowProjector',Self,'',Location);
PlayerShadow.ShadowActor = self;
PlayerShadow.bBlobShadow = bBlobShadow;
PlayerShadow.LightDirection = Normal(vect(1,1,3));
PlayerShadow.LightDistance = 320;
PlayerShadow.MaxTraceDistance = 350;
PlayerShadow.InitShadow();
}
}
simulated function PostNetBeginPlay()
{
Super.PostNetBeginPlay();
MultiJumpRemaining = MaxMultiJump;
bCanDoubleJump = CanMultiJump();
}
function int ShieldAbsorb( int dam )
{
local float Interval, damage, Remaining;
damage = dam;
if ( ShieldStrength == 0 )
{
return damage;
}
SetOverlayMaterial( ShieldHitMat, ShieldHitMatTime, false );
// ifndef _RO_
//PlaySound(sound'WeaponSounds.ArmorHit', SLOT_Pain,2*TransientSoundVolume,,400);
if ( ShieldStrength > 100 )
{
Interval = ShieldStrength - 100;
if ( Interval >= damage )
{
ShieldStrength -= damage;
return 0;
}
else
{
ShieldStrength = 100;
damage -= Interval;
}
}
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 -= 0.5 * damage;
SmallShieldStrength = ShieldStrength;
return Remaining + (0.5 * damage);
}
else
{
damage -= ShieldStrength;
ShieldStrength = 0;
SmallShieldStrength = 0;
}
return damage + Remaining;
}
function PlayHit(float Damage, Pawn InstigatedBy, vector HitLocation, class<DamageType> damageType, vector Momentum, optional int HitIndex)
{
local Vector HitNormal;
local Vector HitRay;
local Name HitBone;
local float HitBoneDist;
local PlayerController PC;
local bool bShowEffects, bRecentHit;
//local BloodSpurt BloodHit;
bRecentHit = Level.TimeSeconds - LastPainTime < 0.5;
Super.PlayHit(Damage,InstigatedBy,HitLocation,DamageType,Momentum);
if ( Damage <= 0 )
return;
PC = PlayerController(Controller);
bShowEffects = ( (Level.NetMode != NM_Standalone) || (Level.TimeSeconds - LastRenderTime < 2.5)
|| ((InstigatedBy != None) && (PlayerController(InstigatedBy.Controller) != None))
|| (PC != None) );
if ( !bShowEffects )
return;
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 = 'None';
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) );
if ( DamageType.Default.bCausesBlood )
{
// if _RO_
// if ( class'GameInfo'.static.UseLowGore() )
// {
// if ( class'GameInfo'.static.NoBlood() )
// BloodHit = BloodSpurt(Spawn( GibGroupClass.default.NoBloodHitClass,InstigatedBy,, HitLocation ));
// else
// BloodHit = BloodSpurt(Spawn( GibGroupClass.default.LowGoreBloodHitClass,InstigatedBy,, HitLocation ));
// }
// else
// BloodHit = BloodSpurt(Spawn(GibGroupClass.default.BloodHitClass,InstigatedBy,, HitLocation, Rotator(HitNormal)));
// if ( BloodHit != None )
// {
// BloodHit.bMustShow = !bRecentHit;
// if ( Momentum != vect(0,0,0) )
// BloodHit.HitDir = Momentum;
// else
// {
// if ( InstigatedBy != None )
// BloodHit.HitDir = Location - InstigatedBy.Location;
// else
// BloodHit.HitDir = Location - HitLocation;
// BloodHit.HitDir.Z = 0;
// }
// }
}
// hack for flak cannon gibbing
if ( (DamageType.name == 'DamTypeFlakChunk') && (Health < 0) && (InstigatedBy != None) && (VSize(InstigatedBy.Location - Location) < 350) )
DoDamageFX( HitBone, 8*Damage, DamageType, Rotator(HitNormal) );
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 );
}
function bool CheckReflect( Vector HitLocation, out Vector RefNormal, int Damage )
{
if (Weapon != None)
return Weapon.CheckReflect( HitLocation, RefNormal, Damage );
else
return false;
}
function name GetWeaponBoneFor(Inventory I)
{
return 'righthand';
}
function name GetOffhandBoneFor(Inventory I)
{
return 'bip01 l hand';
}
event Landed(vector HitNormal)
{
super.Landed( HitNormal );
MultiJumpRemaining = MaxMultiJump;
if ( (Health > 0) && !bHidden && (Level.TimeSeconds - SplashTime > 0.25) )
PlayOwnedSound(GetSound(EST_Land), SLOT_Interact, FMin(1,-0.3 * Velocity.Z/JumpZ));
}
// ----- animation ----- //
simulated function name GetAnimSequence()
{
local name anim;
local float frame, rate;
GetAnimParams(0, anim, frame, rate);
return anim;
}
simulated function PlayDoubleJump()
{
local name Anim;
Anim = DoubleJumpAnims[Get4WayDirection()];
if ( PlayAnim(Anim, 1.0, 0.1) )
bWaitForAnim = true;
AnimAction = Anim;
}
simulated function bool FindValidTaunt( out name Sequence )
{
local int i,j;
for( i=0; i<TauntAnims.Length; i++ )
{
if( Sequence == TauntAnims[i] )
return true;
}
// see if a valid alias exists
j = class'SpeciesType'.static.GetOffsetForSequence(Sequence);
if ( (j < 0) || (j >= TauntAnims.Length) )
return false;
Sequence = TauntAnims[j];
return (Sequence != '' );
}
simulated event SetAnimAction(name NewAction)
{
if (!bWaitForAnim)
{
AnimAction = NewAction;
if ( AnimAction == 'Weapon_Switch' )
{
AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone);
PlayAnim(NewAction,, 0.0, 1);
}
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 ( PlayAnim(AnimAction) )
{
if ( Physics != PHYS_None )
bWaitForAnim = true;
}
else
AnimAction = '';
}
else if (bIsIdle && !bIsCrouched && (Bot(Controller) == None) ) // standing taunt
{
PlayAnim(AnimAction,,0.1);
AnimBlendToAlpha(1,0.0,0.05);
}
else // running taunt
{
if (FireState == FS_None || FireState == FS_Ready)
{
AnimBlendParams(1, 1.0, 0.0, 0.2, FireRootBone);
PlayAnim(NewAction,, 0.1, 1);
FireState = FS_Ready;
}
}
}
}
simulated function StartFiring(bool bHeavy, bool bRapid)
{
local name FireAnim;
if ( HasUDamage() && (Level.TimeSeconds - LastUDamageSoundTime > 0.25) )
{
LastUDamageSoundTime = Level.TimeSeconds;
PlaySound(UDamageSound, SLOT_None, 1.5*TransientSoundVolume,,700);
}
if (Physics == PHYS_Swimming)
return;
if (bHeavy)
{
if (bRapid)
FireAnim = FireHeavyRapidAnim;
else
FireAnim = FireHeavyBurstAnim;
}
else
{
if (bRapid)
FireAnim = FireRifleRapidAnim;
else
FireAnim = FireRifleBurstAnim;
}
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)
{
PlayAnim(IdleWeaponAnim,, 0.2, 1);
FireState = FS_Ready;
IdleTime = Level.TimeSeconds;
}
else
AnimBlendToAlpha(1, 0.0, 0.12);
}
else if ( bKeepTaunting && (Channel == 0) )
PlayVictoryAnimation();
}
function PlayWeaponSwitch(Weapon NewWeapon)
{
SetAnimAction('Weapon_Switch');
}
function PlayVictoryAnimation()
{
local int tauntNum;
// First 4 taunts are 'order' anims. Don't pick them.
tauntNum = Rand(TauntAnims.Length - 3);
SetAnimAction(TauntAnims[3 + tauntNum]);
}
simulated function SetWeaponAttachment(WeaponAttachment NewAtt)
{
WeaponAttachment = NewAtt;
if (xWeaponAttachment(WeaponAttachment).bHeavy)
IdleWeaponAnim = IdleHeavyAnim;
else
IdleWeaponAnim = IdleRifleAnim;
}
// Event called whenever ragdoll convulses
event KSkelConvulse()
{
if(RagConvulseMaterial != None)
SetOverlayMaterial(RagConvulseMaterial, 0.4, true);
}
simulated final function RandSpin(float spinRate)
{
DesiredRotation = RotRand(true);
RotationRate.Yaw = spinRate * 2 *FRand() - spinRate;
RotationRate.Pitch = spinRate * 2 *FRand() - spinRate;
RotationRate.Roll = spinRate * 2 *FRand() - spinRate;
bFixedRotationDir = true;
bRotateToDesired = false;
}
simulated function PlayDying(class<DamageType> DamageType, vector HitLoc)
{
local float frame, rate;
local name seq;
// if _RO_
//local LavaDeath LD;
local BodyEffect BE;
AmbientSound = None;
bCanTeleport = false; // sjs - fix karma going crazy when corpses land on teleporters
bReplicateMovement = false;
bTearOff = true;
bPlayedDeath = true;
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'BodyEffect',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);
TearOffMomentum *= 0.25;
bSkeletized = true;
if ( (Level.NetMode != NM_DedicatedServer) && (DamageType == class'FellLava') )
{
// if _RO_
//LD = spawn(class'LavaDeath', , , Location + vect(0, 0, 10), Rotation );
//if ( LD != None )
// LD.SetBase(self);
//PlaySound( sound'WeaponSounds.BExplosion5', SLOT_None, 1.5*TransientSoundVolume );
}
}
}
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> 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) )
{
Destroy();
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
Log("xPawn.PlayDying: No Species");
// If we managed to find a name, try and make a rag-doll slot availbale.
if( RagSkelName != "" )
{
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(TearOffMomentum);
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(TearOffMomentum) < 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 = TearOffMomentum + 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
}
// non-ragdoll death fallback
Velocity += TearOffMomentum;
BaseEyeHeight = Default.BaseEyeHeight;
SetTwistLook(0, 0);
SetInvisibility(0.0);
PlayDirectionalDeath(HitLoc);
SetPhysics(PHYS_Falling);
}
simulated function SpawnGibs(Rotator HitRotation, float ChunkPerterbation)
{
bGibbed = true;
PlayDyingSound();
// IF _RO_
return;
// if( GibCountTorso+GibCountHead+GibCountForearm+GibCountUpperArm > 3 )
// {
// if ( class'GameInfo'.static.UseLowGore() )
// {
// if ( !class'GameInfo'.static.NoBlood() )
// Spawn( GibGroupClass.default.LowGoreBloodGibClass,,,Location );
// }
// else
// Spawn( GibGroupClass.default.BloodGibClass,,,Location );
// }
// if ( class'GameInfo'.static.UseLowGore() )
// return;
//
// SpawnGiblet( GetGibClass(EGT_Torso), Location, HitRotation, ChunkPerterbation );
// GibCountTorso--;
//
// while( GibCountTorso-- > 0 )
// SpawnGiblet( GetGibClass(EGT_Torso), Location, HitRotation, ChunkPerterbation );
// while( GibCountHead-- > 0 )
// SpawnGiblet( GetGibClass(EGT_Head), Location, HitRotation, ChunkPerterbation );
// while( GibCountForearm-- > 0 )
// SpawnGiblet( GetGibClass(EGT_UpperArm), Location, HitRotation, ChunkPerterbation );
// while( GibCountUpperArm-- > 0 )
// SpawnGiblet( GetGibClass(EGT_Forearm), Location, HitRotation, ChunkPerterbation );
}
function ClientDying(class<DamageType> DamageType, vector HitLocation)
{
}
function PlayTakeHit(vector HitLocation, int Damage, class<DamageType> DamageType)
{
PlayDirectionalHit(HitLocation);
if( Level.TimeSeconds - LastPainSound < MinTimeBetweenPainSounds )
return;
LastPainSound = Level.TimeSeconds;
if( HeadVolume.bWaterVolume )
{
if( DamageType.IsA('Drowned') )
PlaySound( GetSound(EST_Drown), SLOT_Pain,1.5*TransientSoundVolume );
else
PlaySound( GetSound(EST_HitUnderwater), SLOT_Pain,1.5*TransientSoundVolume );
return;
}
PlaySound(SoundGroupClass.static.GetHitSound(), SLOT_Pain,2*TransientSoundVolume,,200);
}
// 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 int numSounds, soundNum;
numSounds = RagImpactSounds.Length;
//log("ouch! iv:"$VSize(impactVel));
if(numSounds > 0 && Level.TimeSeconds > RagLastSoundTime + RagImpactSoundInterval)
{
soundNum = Rand(numSounds);
//Log("Play Sound:"$soundNum);
PlaySound(RagImpactSounds[soundNum], SLOT_Pain, RagImpactVolume);
RagLastSoundTime = Level.TimeSeconds;
}
}
//jag
simulated function PlayDirectionalDeath(Vector HitLoc)
{
local Vector X,Y,Z, Dir;
GetAxes(Rotation, X,Y,Z);
HitLoc.Z = Location.Z;
// random
if ( VSize(Velocity) < 10.0 && VSize(Location - HitLoc) < 1.0 )
{
Dir = VRand();
}
// velocity based
else if ( VSize(Velocity) > 0.0 )
{
Dir = Normal(Velocity*Vect(1,1,0));
}
// hit location based
else
{
Dir = -Normal(Location - HitLoc);
}
if ( Dir Dot X > 0.7 || Dir == vect(0,0,0))
PlayAnim('DeathB',, 0.2);
else if ( Dir Dot X < -0.7 )
PlayAnim('DeathF',, 0.2);
else if ( Dir Dot Y > 0 )
PlayAnim('DeathL',, 0.2);
else if ( HasAnim('DeathR') )
PlayAnim('DeathR',, 0.2);
else
PlayAnim('DeathF',, 0.2);
}
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('HitF',, 0.1);
}
else if ( Dir Dot X < -0.7 )
{
PlayAnim('HitB',, 0.1);
}
else if ( Dir Dot Y > 0 )
{
PlayAnim('HitR',, 0.1);
}
else
{
PlayAnim('HitL',, 0.1);
}
}
simulated function FootStepping(int Side)
{
local int SurfaceNum, i;
local actor A;
local material FloorMat;
local vector HL,HN,Start,End/*,HitLocation,HitNormal*/;
SurfaceNum = 0;
for ( i=0; i<Touching.Length; i++ )
if ( ((PhysicsVolume(Touching[i]) != None) && PhysicsVolume(Touching[i]).bWaterVolume)
|| (FluidSurfaceInfo(Touching[i]) != None) )
{
// ifndef _RO_
/*if ( FRand() < 0.5 )
PlaySound(sound'PlayerSounds.FootStepWater2', SLOT_Interact, FootstepVolume );
else
PlaySound(sound'PlayerSounds.FootStepWater1', SLOT_Interact, FootstepVolume );
if ( !Level.bDropDetail && (Level.DetailMode != DM_Low) && (Level.NetMode != NM_DedicatedServer)
&& !Touching[i].TraceThisActor(HitLocation, HitNormal,Location - CollisionHeight*vect(0,0,1.1), Location) )
Spawn(class'ROEffects.WaterRingEmitter',,,HitLocation,rot(16384,0,0));*/
return;
}
if ( bIsCrouched || bIsWalking )
return;
if ( (Base!=None) && (!Base.IsA('LevelInfo')) && (Base.SurfaceType!=0) )
{
SurfaceNum = 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)
SurfaceNum = FloorMat.SurfaceType;
}
//PlaySound(SoundFootsteps[SurfaceNum], SLOT_Interact, FootstepVolume,,400 );
}
simulated function PlayFootStepLeft()
{
PlayFootStep(-1);
}
simulated function PlayFootStepRight()
{
PlayFootStep(1);
}
// ----- shield control ----- //
function float GetShieldStrengthMax()
{
return ShieldStrengthMax;
}
function float GetShieldStrength()
{
// could return max if it's active right now, which make it unable to be recharged while it's on...
return ShieldStrength;
}
function int CanUseShield(int ShieldAmount)
{
ShieldStrength = Max(ShieldStrength,0);
if ( ShieldStrength < ShieldStrengthMax )
{
if ( ShieldAmount == 50 )
ShieldAmount = 50 - SmallShieldStrength;
return (Min(ShieldStrengthMax, ShieldStrength + ShieldAmount) - ShieldStrength);
}
return 0;
}
function bool AddShieldStrength(int ShieldAmount)
{
local int OldShieldStrength;
OldShieldStrength = ShieldStrength;
ShieldStrength += CanUseShield(ShieldAmount);
if ( ShieldAmount == 50 )
{
SmallShieldStrength = 50;
if ( ShieldStrength < 50 )
ShieldStrength = 50;
}
return (ShieldStrength != OldShieldStrength);
}
function bool InCurrentCombo()
{
return (CurrentCombo != None);
}
// used by bots doing combos
function DoComboName( string ComboClassName )
{
local class<Combo> ComboClass;
ComboClass = class<Combo>( DynamicLoadObject( ComboClassName, class'Class' ) );
if ( ComboClass != None )
DoCombo( ComboClass );
else
log("WARNING - Couldn't create combo "$ComboClassName);
}
function DoCombo( class<Combo> ComboClass )
{
local int i;
if ( ComboClass != None )
{
if (CurrentCombo == None)
{
CurrentCombo = Spawn( ComboClass, self );
// Record stats for using the combo
UnrealMPGameInfo(Level.Game).SpecialEvent(PlayerReplicationInfo,""$CurrentCombo.Class);
if ( ComboClass.Name == 'ComboSpeed' )
i = 0;
else if ( ComboClass.Name == 'ComboBerserk' )
i = 1;
else if ( ComboClass.Name == 'ComboDefensive' )
i = 2;
else if ( ComboClass.Name == 'ComboInvis' )
i = 3;
else
i = 4;
TeamPlayerReplicationInfo(PlayerReplicationInfo).Combos[i] += 1;
}
}
}
simulated function bool HasUDamage()
{
return (UDamageTime > Level.TimeSeconds);
}
function ClientSetUDamageTime(float NewUDam)
{
UDamageTime = Level.TimeSeconds + NewUDam;
}
function EnableUDamage(float amount)
{
UDamageTime = FMax(UDamageTime, Level.TimeSeconds+amount);
ClientSetUDamageTime(UDamageTime - Level.TimeSeconds);
if ( UDamageTimer == None )
UDamageTimer = Spawn(class'UDamageTimer',self);
UDamageTimer.SetTimer(UDamageTime - Level.TimeSeconds - 3,false);
LightType = LT_Steady;
bDynamicLight = true;
SetWeaponOverlay(UDamageWeaponMaterial, UDamageTime - Level.TimeSeconds, false);
}
function DisableUDamage()
{
LightType = LT_None;
bDynamicLight = false;
UDamageTime = Level.TimeSeconds - 1;
ClientSetUDamageTime(-1);
SetWeaponOverlay(UDamageWeaponMaterial, UDamageTime - Level.TimeSeconds, false);
}
function SetWeaponOverlay(Material mat, float time, bool override)
{
if (Weapon != None)
{
Weapon.SetOverlayMaterial(mat, time, override);
if (WeaponAttachment(Weapon.ThirdPersonActor) != None)
WeaponAttachment(Weapon.ThirdPersonActor).SetOverlayMaterial(mat, time, override);
}
}
function ChangedWeapon()
{
Super.ChangedWeapon();
if (Weapon != None && Role < ROLE_Authority)
{
if (bBerserk)
Weapon.StartBerserk();
else if ( Weapon.bBerserk )
Weapon.StopBerserk();
}
}
function ServerChangedWeapon(Weapon OldWeapon, Weapon NewWeapon)
{
local float InvisTime;
if ( bInvis )
{
if ( (OldWeapon != None) && (OldWeapon.OverlayMaterial == InvisMaterial) )
InvisTime = OldWeapon.ClientOverlayCounter;
else
InvisTime = 20000;
}
if (HasUDamage() || bInvis)
SetWeaponOverlay(None, 0.f, true);
Super.ServerChangedWeapon(OldWeapon, NewWeapon);
if (bInvis)
SetWeaponOverlay(InvisMaterial, InvisTime, true);
else if (HasUDamage())
SetWeaponOverlay(UDamageWeaponMaterial, UDamageTime - Level.TimeSeconds, false);
if (bBerserk)
Weapon.StartBerserk();
else if ( Weapon.bBerserk )
Weapon.StopBerserk();
}
function SetInvisibility(float time)
{
bInvis = (time > 0.0);
if (Role == ROLE_Authority)
{
if (bInvis)
{
if ( (time == 2000000.0) && Level.Game.IsA('xMutantGame') ) // for mutant game
Visibility = Default.Visibility;
else
Visibility = 1;
SetWeaponOverlay(InvisMaterial, time, true);
}
else
{
Visibility = Default.Visibility;
if (HasUDamage())
SetWeaponOverlay(UDamageWeaponMaterial, UDamageTime - Level.TimeSeconds, true);
else
SetWeaponOverlay(None, 0.0, true);
}
}
}
/* BotDodge()
returns appropriate vector for dodge in direction Dir (which should be normalized)
*/
function vector BotDodge(Vector Dir)
{
local vector Vel;
Vel = DodgeSpeedFactor*GroundSpeed*Dir;
Vel.Z = DodgeSpeedZ;
return Vel;
}
function bool Dodge(eDoubleClickDir DoubleClickMove)
{
local vector X,Y,Z, TraceStart, TraceEnd, Dir, Cross, HitLocation, HitNormal;
local Actor HitActor;
local rotator TurnRot;
if ( bIsCrouched || bWantsToCrouch || (Physics != PHYS_Walking && Physics != PHYS_Falling) )
return false;
TurnRot.Yaw = Rotation.Yaw;
GetAxes(TurnRot,X,Y,Z);
if ( Physics == PHYS_Falling )
{
if ( !bCanWallDodge )
return false;
if (DoubleClickMove == DCLICK_Forward)
TraceEnd = -X;
else if (DoubleClickMove == DCLICK_Back)
TraceEnd = X;
else if (DoubleClickMove == DCLICK_Left)
TraceEnd = Y;
else if (DoubleClickMove == DCLICK_Right)
TraceEnd = -Y;
TraceStart = Location - CollisionHeight*Vect(0,0,1) + TraceEnd*CollisionRadius;
TraceEnd = TraceStart + TraceEnd*32.0;
HitActor = Trace(HitLocation, HitNormal, TraceEnd, TraceStart, false, vect(1,1,1));
if ( (HitActor == None) || (!HitActor.bWorldGeometry && (Mover(HitActor) == None)) )
return false;
}
if (DoubleClickMove == DCLICK_Forward)
{
Dir = X;
Cross = Y;
}
else if (DoubleClickMove == DCLICK_Back)
{
Dir = -1 * X;
Cross = Y;
}
else if (DoubleClickMove == DCLICK_Left)
{
Dir = -1 * Y;
Cross = X;
}
else if (DoubleClickMove == DCLICK_Right)
{
Dir = Y;
Cross = X;
}
if ( AIController(Controller) != None )
Cross = vect(0,0,0);
return PerformDodge(DoubleClickMove, Dir,Cross);
}
function bool PerformDodge(eDoubleClickDir DoubleClickMove, vector Dir, vector Cross)
{
local float VelocityZ;
local name Anim;
if ( Physics == PHYS_Falling )
{
if (DoubleClickMove == DCLICK_Forward)
Anim = WallDodgeAnims[0];
else if (DoubleClickMove == DCLICK_Back)
Anim = WallDodgeAnims[1];
else if (DoubleClickMove == DCLICK_Left)
Anim = WallDodgeAnims[2];
else if (DoubleClickMove == DCLICK_Right)
Anim = WallDodgeAnims[3];
if ( PlayAnim(Anim, 1.0, 0.1) )
bWaitForAnim = true;
AnimAction = Anim;
TakeFallingDamage();
if (Velocity.Z < -DodgeSpeedZ*0.5)
Velocity.Z += DodgeSpeedZ*0.5;
}
VelocityZ = Velocity.Z;
Velocity = DodgeSpeedFactor*GroundSpeed*Dir + (Velocity Dot Cross)*Cross;
if ( !bCanDodgeDoubleJump )
MultiJumpRemaining = 0;
if ( bCanBoostDodge || (Velocity.Z < -100) )
Velocity.Z = VelocityZ + DodgeSpeedZ;
else
Velocity.Z = DodgeSpeedZ;
CurrentDir = DoubleClickMove;
SetPhysics(PHYS_Falling);
PlayOwnedSound(GetSound(EST_Dodge), SLOT_Pain, GruntVolume,,80);
return true;
}
function DoDoubleJump( bool bUpdating )
{
PlayDoubleJump();
if ( !bIsCrouched && !bWantsToCrouch )
{
if ( !IsLocallyControlled() || (AIController(Controller) != None) )
MultiJumpRemaining -= 1;
Velocity.Z = JumpZ + MultiJumpBoost;
SetPhysics(PHYS_Falling);
if ( !bUpdating )
PlayOwnedSound(GetSound(EST_DoubleJump), SLOT_Pain, GruntVolume,,80);
}
}
function bool CanDoubleJump()
{
return ( (MultiJumpRemaining > 0) && (Physics == PHYS_Falling) );
}
function bool CanMultiJump()
{
return ( MaxMultiJump > 0 );
}
function bool DoJump( bool bUpdating )
{
// This extra jump allows a jumping or dodging pawn to jump again mid-air
// (via thrusters). The pawn must be within +/- 100 velocity units of the
// apex of the jump to do this special move.
if ( !bUpdating && CanDoubleJump()&& (Abs(Velocity.Z) < 100) && IsLocallyControlled() )
{
if ( PlayerController(Controller) != None )
PlayerController(Controller).bDoubleJump = true;
DoDoubleJump(bUpdating);
MultiJumpRemaining -= 1;
return true;
}
if ( Super.DoJump(bUpdating) )
{
if ( !bUpdating )
PlayOwnedSound(GetSound(EST_Jump), SLOT_Pain, GruntVolume,,80);
return true;
}
return false;
}
simulated function NotifyTeamChanged()
{
// my PRI now has a new team
PostNetReceive();
}
simulated event PostNetReceive()
{
if ( ForceDefaultCharacter() )
{
Setup(class'xUtil'.static.FindPlayerRecord(GetDefaultCharacter()));
bNetNotify = false;
}
else 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;
}
}
simulated function ClientRestart()
{
Super.ClientRestart();
if ( Controller != None )
OldController = Controller;
}
simulated function bool CheckValidFemaleDefault()
{
return ( (PlacedFemaleCharacterName ~= "Tamika")
|| (PlacedFemaleCharacterName ~= "Sapphire")
|| (PlacedFemaleCharacterName ~= "Enigma")
|| (PlacedFemaleCharacterName ~= "Cathode")
|| (PlacedFemaleCharacterName ~= "Rylisa")
|| (PlacedFemaleCharacterName ~= "Ophelia")
|| (PlacedFemaleCharacterName ~= "Zarina") );
}
simulated function bool CheckValidMaleDefault()
{
return ( (PlacedCharacterName ~= "Jakob")
|| (PlacedCharacterName ~= "Gorge")
|| (PlacedCharacterName ~= "Malcolm")
|| (PlacedCharacterName ~= "Xan")
|| (PlacedCharacterName ~= "Brock")
|| (PlacedCharacterName ~= "Gaargod")
|| (PlacedCharacterName ~= "Axon") );
}
simulated function bool ForceDefaultCharacter()
{
local PlayerController P;
if ( !class'DeathMatch'.default.bForceDefaultCharacter )
return false;
// validate and use player's model for enemies of same sex
P = Level.GetLocalPlayerController();
if ( (P != None) && (P.PlayerReplicationInfo != None) )
{
if ( P.PlayerReplicationInfo.bIsFemale )
{
PlacedFemaleCharacterName = P.PlayerReplicationInfo.CharacterName;
if ( !CheckValidFemaleDefault() )
{
PlacedFemaleCharacterName = "Tamika";
return false;
}
}
else
{
PlacedCharacterName = P.PlayerReplicationInfo.CharacterName;
if ( !CheckValidMaleDefault() )
{
PlacedCharacterName = "Jakob";
return false;
}
}
}
return true;
}
simulated function string GetDefaultCharacter()
{
if ( Level.IsDemoBuild() )
{
PlacedFemaleCharacterName = "Tamika";
PlacedCharacterName = "Jakob";
}
else
{
// make sure picking from valid default characters
if ( !CheckValidFemaleDefault() )
PlacedFemaleCharacterName = "Tamika";
if ( !CheckValidMaleDefault() )
PlacedCharacterName = "Jakob";
}
// return appropriate character based on this pawn's sex
if ( (PlayerReplicationInfo != None) && PlayerReplicationInfo.bIsFemale )
return PlacedFemaleCharacterName;
else
return PlacedCharacterName;
}
simulated function Setup(xUtil.PlayerRecord rec, optional bool bLoadNow)
{
if ( (rec.Species == None) || ForceDefaultCharacter() )
rec = class'xUtil'.static.FindPlayerRecord(GetDefaultCharacter());
Species = rec.Species;
RagdollOverride = rec.Ragdoll;
if ( !Species.static.Setup(self,rec) )
{
rec = class'xUtil'.static.FindPlayerRecord(GetDefaultCharacter());
if ( !Species.static.Setup(self,rec) )
return;
}
ResetPhysicsBasedAnim();
}
simulated function ResetPhysicsBasedAnim()
{
bIsIdle = false;
bWaitForAnim = false;
}
function Sound GetSound(xPawnSoundGroup.ESoundType soundType)
{
return SoundGroupClass.static.GetSound(soundType);
}
//function class<Gib> GetGibClass(xPawnGibGroup.EGibType gibType)
//{
// return GibGroupClass.static.GetGibClass(gibType);
//}
simulated function DoDerezEffect()
{
Spawn(TeleportFXClass);
}
State Dying
{
simulated function AnimEnd( int Channel )
{
ReduceCylinder();
}
event FellOutOfWorld(eKillZType KillType)
{
// if _RO_
//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;
// if _RO_
//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'WeaponSounds.BExplosion5', SLOT_None, 1.5*TransientSoundVolume );
}
return;
}
Super.FellOutOfWorld(KillType);
}
function LandThump()
{
// animation notify - play sound if actually landed, and animation also shows it
if ( Physics == PHYS_None)
{
bThumped = true;
PlaySound(GetSound(EST_CorpseLanded));
}
}
simulated function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
{
local Vector SelfToHit, SelfToInstigator, CrossPlaneNormal;
local float W;
local float YawDir;
local Vector HitNormal, shotDir;
local Vector PushLinVel, PushAngVel;
local Name HitBone;
local float HitBoneDist;
local int MaxCorpseYawRate;
if ( bFrozenBody || bRubbery )
return;
if( Physics == PHYS_KarmaRagdoll )
{
// Can't shoot corpses during de-res
if( bDeRes || bRubbery )
return;
// Throw the body if its a rocket explosion or shock combo
if( damageType.Default.bThrowRagdoll )
{
shotDir = Normal(Momentum);
PushLinVel = (RagDeathVel * shotDir) + vect(0, 0, 250);
PushAngVel = Normal(shotDir Cross vect(0, 0, 1)) * -18000;
KSetSkelVel( PushLinVel, PushAngVel );
}
else if( damageType.Default.bRagdollBullet )
{
if ( Momentum == vect(0,0,0) )
Momentum = HitLocation - InstigatedBy.Location;
if ( FRand() < 0.65 )
{
if ( Velocity.Z <= 0 )
PushLinVel = vect(0,0,40);
PushAngVel = Normal(Normal(Momentum) Cross vect(0, 0, 1)) * -8000 ;
PushAngVel.X *= 0.5;
PushAngVel.Y *= 0.5;
PushAngVel.Z *= 4;
KSetSkelVel( PushLinVel, PushAngVel );
}
PushLinVel = RagShootStrength*Normal(Momentum);
KAddImpulse(PushLinVel, HitLocation);
if ( (LifeSpan > 0) && (LifeSpan < DeResTime + 2) )
LifeSpan += 0.2;
}
else
{
PushLinVel = RagShootStrength*Normal(Momentum);
KAddImpulse(PushLinVel, HitLocation);
}
if ( (DamageType.Default.DamageOverlayMaterial != None) && (Level.DetailMode != DM_Low) && !Level.bDropDetail )
SetOverlayMaterial(DamageType.Default.DamageOverlayMaterial, DamageType.default.DamageOverlayTime, true);
return;
}
if ( DamageType.default.bFastInstantHit && GetAnimSequence() == 'Death_Spasm' && RepeaterDeathCount < 6)
{
PlayAnim('Death_Spasm',, 0.2);
RepeaterDeathCount++;
}
else if (Damage > 0)
{
if ( InstigatedBy != None )
{
if ( InstigatedBy.IsA('xPawn') && xPawn(InstigatedBy).bBerserk )
Damage *= 2;
// Figure out which direction to spin:
if( InstigatedBy.Location != Location )
{
SelfToInstigator = InstigatedBy.Location - Location;
SelfToHit = HitLocation - Location;
CrossPlaneNormal = Normal( SelfToInstigator cross Vect(0,0,1) );
W = CrossPlaneNormal dot Location;
if( HitLocation dot CrossPlaneNormal < W )
YawDir = -1.0;
else
YawDir = 1.0;
}
}
if( VSize(Momentum) < 10 )
{
Momentum = - Normal(SelfToInstigator) * Damage * 1000.0;
Momentum.Z = Abs( Momentum.Z );
}
SetPhysics(PHYS_Falling);
Momentum = Momentum / Mass;
AddVelocity( Momentum );
bBounce = true;
RotationRate.Pitch = 0;
RotationRate.Yaw += VSize(Momentum) * YawDir;
MaxCorpseYawRate = 150000;
RotationRate.Yaw = Clamp( RotationRate.Yaw, -MaxCorpseYawRate, MaxCorpseYawRate );
RotationRate.Roll = 0;
bFixedRotationDir = true;
bRotateToDesired = false;
Health -= Damage;
CalcHitLoc( HitLocation, vect(0,0,0), HitBone, HitBoneDist );
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) );
DoDamageFX( HitBone, Damage, DamageType, Rotator(HitNormal) );
}
}
simulated function BeginState()
{
Super.BeginState();
AmbientSound = None;
}
simulated function Timer()
{
local KarmaParamsSkel skelParams;
if ( !PlayerCanSeeMe() )
{
Destroy();
}
// If we are running out of life, bute we still haven't come to rest, force the de-res.
// unless pawn is the viewtarget of a player who used to own it
else if ( LifeSpan <= DeResTime && bDeRes == false )
{
skelParams = KarmaParamsSkel(KParams);
// check not viewtarget
if ( (PlayerController(OldController) != None) && (PlayerController(OldController).ViewTarget == self)
&& (Viewport(PlayerController(OldController).Player) != None) )
{
skelParams.bKImportantRagdoll = true;
LifeSpan = FMax(LifeSpan,DeResTime + 2.0);
SetTimer(1.0, false);
return;
}
else
{
skelParams.bKImportantRagdoll = false;
}
// spawn derez
StartDeRes();
}
else
{
SetTimer(1.0, false);
}
}
// We shorten the lifetime when the guys comes to rest.
event KVelDropBelow()
{
local float NewLifeSpan;
if(bDeRes == false)
{
//Log("Low Vel - Reducing LifeSpan!");
NewLifeSpan = DeResTime + 3.5;
if(NewLifeSpan < LifeSpan)
LifeSpan = NewLifeSpan;
}
}
}
defaultproperties
{
bNetNotify=true
// if _RO_
// Default everything to Characters_anm.ger_rifleman_tunic
//Mesh=SkeletalMesh'Characters_anm.ger_rifleman_tunic'
//Skins(0)=Texture'Characters_tex.ger_uniforms.ger_rifleman_tunic'
//Skins(1)=Texture'Characters_tex.ger_heads.ger_face01'
// else
// default everything to ThunderCrash.Jakob
// Mesh=Mesh'ThunderCrash.JakobM'
// Skins(0)=Texture'DemoPlayerSkins.Jakob_Body'
// Skins(1)=Texture'DemoPlayerSkins.Jakob_NewHead'
Species=class'SPECIES_Human'
// Temp commented out - Ramm
SoundGroupClass=none//class'xMercMaleSoundGroup'
// if _RO_
//GibGroupClass=class'xPawnGibGroup'
bStatic=False
DrawScale=1.0
Buoyancy=+00099.000000
UnderWaterTime=+00020.000000
bCanStrafe=True
DrawType=DT_Mesh
Style=STY_Normal
LightBrightness=255
LightHue=204
LightSaturation=0
LightRadius=3
RotationRate=(Pitch=3072,Yaw=20000,Roll=2048)
//BloodEffect=class'BloodJet'
//LowGoreBlood=class'AlienSmallHit'
AirControl=+0.35
bStasis=false
bCanCrouch=true
bCanClimbLadders=True
bCanPickupInventory=True
WalkingPct=+0.4
CrouchedPct=+0.4
BaseEyeHeight=38.0
EyeHeight=38.0
CollisionRadius=25.0
CollisionHeight=44.0
GroundSpeed=440.0
AirSpeed=440.0
WaterSpeed=220.0
DodgeSpeedFactor=1.5
DodgeSpeedZ=210.0
AccelRate=2048.0
JumpZ=340.0
CrouchHeight=29.0
CrouchRadius=25.0
LODBias=1.8
ShieldStrengthMax=150.0
PrePivot=(X=0.0,Y=0.0,Z=-5.0);
ControllerClass=class'XGame.xBot'
// ifndef _RO_
// SoundFootsteps(0)=Sound'PlayerSounds.Final.FootstepDefault'
// SoundFootsteps(1)=Sound'PlayerSounds.Final.FootstepRock'
// SoundFootsteps(2)=Sound'PlayerSounds.Final.FootstepDirt'
// SoundFootsteps(3)=Sound'PlayerSounds.Final.FootStepMetal'
// SoundFootsteps(4)=Sound'PlayerSounds.Final.FootstepWood'
// SoundFootsteps(5)=Sound'PlayerSounds.Final.FootstepPlant'
// SoundFootsteps(6)=Sound'PlayerSounds.Final.FootstepFlesh'
// SoundFootsteps(7)=Sound'PlayerSounds.Final.FootstepIce'
// SoundFootsteps(8)=Sound'PlayerSounds.Final.FootstepSnow'
// SoundFootsteps(9)=Sound'PlayerSounds.Final.FootstepWater'
// SoundFootsteps(10)=Sound'PlayerSounds.Final.FootstepGlass'
RequiredEquipment(0)="XWeapons.AssaultRifle"
RequiredEquipment(1)="XWeapons.ShieldGun"
MinTimeBetweenPainSounds=0.35
ScaleGlow=1.0
AmbientGlow=40
// Temp commented out - Ramm
TeleportFXClass=none//class'TransEffect'
// GibCountCalf=4
// GibCountForearm=2
// GibCountHead=2
// GibCountTorso=2
// GibCountUpperArm=2
bDoTorsoTwist=true
bActorShadows=true
bPlayerShadows=true
// ifndef _RO_
//ShieldHitMat=Material'XGameShaders.PlayerShaders.PlayerShieldSh'
ShieldHitMatTime=1.0
// ifndef _RO_
//UDamageWeaponMaterial=Material'XGameShaders.PlayerShaders.WeaponUDamageShader'
//InvisMaterial=FinalBlend'XEffectMat.InvisOverlayFB'
bPhysicsAnimUpdate=true
MovementAnims(0)=RunF
MovementAnims(1)=RunB
MovementAnims(2)=RunL
MovementAnims(3)=RunR
SwimAnims(0)=SwimF
SwimAnims(1)=SwimB
SwimAnims(2)=SwimL
SwimAnims(3)=SwimR
CrouchAnims(0)=CrouchF
CrouchAnims(1)=CrouchB
CrouchAnims(2)=CrouchL
CrouchAnims(3)=CrouchR
WalkAnims(0)=WalkF
WalkAnims(1)=WalkB
WalkAnims(2)=WalkL
WalkAnims(3)=WalkR
AirStillAnim=Jump_Mid
AirAnims(0)=JumpF_Mid
AirAnims(1)=JumpB_Mid
AirAnims(2)=JumpL_Mid
AirAnims(3)=JumpR_Mid
TakeoffStillAnim=Jump_Takeoff
TakeoffAnims(0)=JumpF_Takeoff
TakeoffAnims(1)=JumpB_Takeoff
TakeoffAnims(2)=JumpL_Takeoff
TakeoffAnims(3)=JumpR_Takeoff
LandAnims(0)=JumpF_Land
LandAnims(1)=JumpB_Land
LandAnims(2)=JumpL_Land
LandAnims(3)=JumpR_Land
DoubleJumpAnims(0)=DoubleJumpF
DoubleJumpAnims(1)=DoubleJumpB
DoubleJumpAnims(2)=DoubleJumpL
DoubleJumpAnims(3)=DoubleJumpR
DodgeAnims(0)=DodgeF
DodgeAnims(1)=DodgeB
DodgeAnims(2)=DodgeL
DodgeAnims(3)=DodgeR
WallDodgeAnims(0)=WallDodgeF
WallDodgeAnims(1)=WallDodgeB
WallDodgeAnims(2)=WallDodgeL
WallDodgeAnims(3)=WallDodgeR
TurnRightAnim=TurnR
TurnLeftAnim=TurnL
CrouchTurnRightAnim=Crouch_TurnR
CrouchTurnLeftAnim=Crouch_TurnL
IdleRestAnim=Idle_Rest
IdleCrouchAnim=Crouch
IdleSwimAnim=Swim_Tread
IdleWeaponAnim=Idle_Rifle
IdleHeavyAnim=Idle_Biggun
IdleRifleAnim=Idle_Rifle
IdleChatAnim=Idle_Chat
FireHeavyRapidAnim=Biggun_Burst
FireHeavyBurstAnim=Biggun_Aimed
FireRifleRapidAnim=Rifle_Burst
FireRifleBurstAnim=Rifle_Aimed
MaxMultiJump=1
MultiJumpRemaining=1
MultiJumpBoost=25
RagdollLifeSpan=13
RagDeathVel=200
RagInvInertia=4
RagShootStrength=8000
RagSpinScale=2.5
RagDeathUpKick=150
RagGravScale=1.0
Begin Object Class=KarmaParamsSkel Name=PawnKParams
KFriction=0.6
KRestitution=0.3
KAngularDamping=0.05
KLinearDamping=0.15
KBuoyancy=1
KStartEnabled=True
KImpactThreshold=500
KVelDropBelowThreshold=50
KConvulseSpacing=(Min=0.5,Max=2.2)
bHighDetailOnly=False
Name="PawnKParams"
End Object
KParams=KarmaParams'PawnKParams'
// ifndef _RO_
//RagImpactSounds(0)=sound'GeneralImpacts.Breakbone_01'
//RagImpactSounds(1)=sound'GeneralImpacts.Breakbone_02'
//RagImpactSounds(2)=sound'GeneralImpacts.Breakbone_03'
RagImpactVolume=2.5
RagImpactSoundInterval=0.5
VoiceType="xGame.MercMaleVoice"
RootBone="Bip01"
HeadBone="Bip01 Head"
SpineBone1="Bip01 Spine1"
SpineBone2="Bip01 Spine2"
FireRootBone="Bip01 Spine"
// ifndef _RO_
//UDamageSound=Sound'GameSounds.UDamageFire'
GruntVolume=0.18
FootstepVolume=0.15
DeResTime=6.0
// ifndef _RO_
//DeResMat0=FinalBlend'DeRez.DeRezFinalBody'
//DeResMat1=FinalBlend'DeRez.DeRezFinalHead'
DeResLiftVel=(Points=((InVal=0,OutVal=0),(InVal=2.5,OutVal=32),(InVal=100,OutVal=32)))
DeResLiftSoftness=(Points=((InVal=0,OutVal=0.3),(InVal=2.5,OutVal=0.05),(InVal=100,OutVal=0.05)))
DeResGravScale=0.0
DeResLateralFriction=0.3
// Temp commented out - Ramm
TransOutEffect(0)=none//class'NewTransDeResRed'
TransOutEffect(1)=none//class'NewTransDeResBlue'
TransEffects(0)=none//class'NewTransEffect'
TransEffects(1)=none//class'NewTransEffectBlue'
PlacedCharacterName="Jakob"
PlacedFemaleCharacterName="Tamika"
MaxLights=8
bDramaticLighting=true
bCanDodgeDoubleJump=true
bCanWallDodge=true
bNoCoronas=false
// Temp commented out - Ramm
Texture=none//Texture'RedMarker_t'
}