2675 lines
74 KiB
Ucode
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'
|
|
}
|