2020-12-13 15:01:13 +00:00
//=============================================================================
// KFWeaponAttachment
//=============================================================================
// Base class for third person weapon attachments
//=============================================================================
// Killing Floor 2
// Copyright (C) 2015 Tripwire Interactive LLC
// - Andrew "Strago" Ladenberger
//=============================================================================
class KFWeaponAttachment extends Actor
hidecategories ( Object , Movement , Attachment , Collision , Physics , Advanced , Debug , Mobile )
native ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ name Mesh Components
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/** Editable SkeletalMesh set by the archetype */
var ( ) const SkeletalMesh SkelMesh ;
/** Extra pawn anim set when weapon is equipped */
var ( ) AnimSet CharacterAnimSet ;
/** Anim set to use for 3rd person weapon anims */
var ( ) AnimSet WeaponAnimSet ;
/** Third Person Weapon SkelMesh */
var transient SkeletalMeshComponent WeapMesh ;
/** If true this third person weapon is part of the pawn's mesh */
var ( ) bool bWeapMeshIsPawnMesh ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ name LaserSight
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
var ( ) bool bHasLaserSight ;
var ( ) const KFLaserSightAttachment LaserSightArchetype ;
var transient KFLaserSightAttachment LaserSight ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ name Fire Effects
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/** A muzzle flash instance */
var KFMuzzleFlash MuzzleFlash ;
/** A reference to the muzzle flash template */
var ( ) const KFMuzzleFlash MuzzleFlashTemplate ;
var float MaxFireEffectDistance ;
/** replicated information on a hit we've taken */
struct native KFTracerInfo
{
/** Tracer Effect */
var ( ) ParticleSystem TracerTemplate ;
/** The velocity the tracer should travel at */
var ( ) int TracerVelocity ;
/** Show the tracer when the weapon is firing in normal time */
var ( ) bool bDoTracerDuringNormalTime ;
/** Show the tracer when the weapon is firing in zed time */
var ( ) bool bDoTracerDuringZedTime ;
/** How far away the hitlocation has to be to spawn this tracer */
var int MinTracerEffectDistanceSquared ;
/** Actual tracer velocity vector, set at runtime */
var vector VelocityVector ;
structdefaultproperties
{
TracerVelocity = 7000
bDoTracerDuringNormalTime = true
bDoTracerDuringZedTime = false
MinTracerEffectDistanceSquared = 40000
}
} ;
/** Tracer effect info per fire mode */
var ( ) array < KFTracerInfo > TracerInfos ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ name Material Effects
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/** MIC for blood effects */
var transient MaterialInstanceConstant WeaponMIC ;
var transient float BloodParamValue ;
const BloodParamName = 'Scalar_Blood_Contrast' ;
const MinBloodParamValue = 0.20 f ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ name Animation - ( using const FNames for 'static' data )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/** Replicated state of the 1st person weapon */
enum EWeaponState
{
WEP _Idle ,
WEP _Reload ,
WEP _ReloadEmpty ,
WEP _Reload _Elite ,
WEP _ReloadEmpty _Elite ,
WEP _ReloadSingle ,
WEP _ReloadSingleEmpty ,
WEP _ReloadSingle _Elite ,
WEP _ReloadSingleEmpty _Elite ,
WEP _ReloadSecondary ,
WEP _ReloadSecondary _Elite ,
2021-09-02 21:46:08 +00:00
WEP _ReloadSecondaryEmpty ,
WEP _ReloadSecondaryEmpty _Elite ,
2020-12-13 15:01:13 +00:00
WEP _ReloadDualsOneEmpty ,
WEP _ReloadDualsOneEmpty _Elite ,
WEP _MeleeBasic ,
WEP _MeleeChain , // @deprecated
WEP _MeleeSustained ,
WEP _Melee _L ,
WEP _Melee _R ,
WEP _Melee _F ,
WEP _Melee _B ,
WEP _MeleeHeavy _L ,
WEP _MeleeHeavy _R ,
WEP _MeleeHeavy _F ,
WEP _MeleeHeavy _B ,
WEP _MeleeBlock ,
WEP _Cleaning ,
WEP _Equipping ,
WEP _PutAway ,
WEP _Grenade ,
WEP _Heal ,
WEP _HealQuick ,
WEP _Weld ,
WEP _Custom0 ,
WEP _Custom1 ,
WEP _Custom2 ,
WEP _Custom3 ,
WEP _Custom4 ,
WEP _Custom5 ,
WEP _Custom6 ,
WEP _Custom7 ,
WEP _Custom8 ,
WEP _Custom9 ,
} ;
/** Animation rate to scale all of our 3rd person animations by */
var protected transient float ThirdPersonAnimRate ;
/** Animation Physics Recoil */
var GameSkelCtrl _Recoil . RecoilDef Recoil _Hand ;
var GameSkelCtrl _Recoil . RecoilDef Recoil _Spine ;
/** MELEE */
const MeleeBasic = 'Melee' ;
const CH _MeleeBasic = 'Melee_CH' ;
/** directional attack anims */
const MeleeAnim _F = 'Atk_F' ;
const MeleeAnim _B = 'Atk_B' ;
const MeleeAnim _L = 'Atk_L' ;
const MeleeAnim _R = 'Atk_R' ;
const CH _MeleeAnim _F = 'Atk_F_CH' ;
const CH _MeleeAnim _B = 'Atk_B_CH' ;
const CH _MeleeAnim _L = 'Atk_L_CH' ;
const CH _MeleeAnim _R = 'Atk_R_CH' ;
/** heavy attack anims */
const MeleeHeavy _F = 'Atk_H_F' ;
const MeleeHeavy _B = 'Atk_H_B' ;
const MeleeHeavy _L = 'Atk_H_L' ;
const MeleeHeavy _R = 'Atk_H_R' ;
const CH _MeleeHeavy _F = 'Atk_H_F_CH' ;
const CH _MeleeHeavy _B = 'Atk_H_B_CH' ;
const CH _MeleeHeavy _L = 'Atk_H_L_CH' ;
const CH _MeleeHeavy _R = 'Atk_H_R_CH' ;
/** Continious (aka chainsaw) melee */
const MeleeLoopAnim = 'Atk_F_Loop' ;
const MeleeStartAnim = 'Atk_F_In' ;
const MeleeEndAnim = 'Atk_F_Out' ;
const CH _MeleeLoopAnim = 'Atk_F_Loop_CH' ;
const CH _MeleeStartAnim = 'Atk_F_In_CH' ;
const CH _MeleeEndAnim = 'Atk_F_Out_CH' ;
/** blocking/parry anims */
const BlockLoopAnim = 'Brace_Loop' ;
const BlockStartAnim = 'Brace_In' ;
const BlockEndAnim = 'Brace_Out' ;
const CH _BlockLoopAnim = 'Brace_Loop_CH' ;
const CH _BlockStartAnim = 'Brace_In_CH' ;
const CH _BlockEndAnim = 'Brace_Out_CH' ;
/** melee misc */
const CleanWeaponAnim = 'Clean_NoBlood' ;
const CH _CleanWeaponAnim = 'Clean_NoBlood_CH' ;
/** General, all inventory items anims */
const GrenadeAnim = 'Nade_Throw' ;
const EquipAnim = 'Equip' ;
const PutAwayAnim = 'PutAway' ;
const CH _GrenadeAnim = 'Nade_Throw_CH' ;
const CH _EquipAnim = 'Equip_CH' ;
const CH _PutAwayAnim = 'PutAway_CH' ;
/** Reload (magazine) anims */
const ReloadEmptyAnim = 'Reload_Empty' ;
const ReloadHalfAnim = 'Reload_Half' ;
const ReloadEmptyEliteAnim = 'Reload_Empty_Elite' ;
const ReloadHalfEliteAnim = 'Reload_Half_Elite' ;
const ReloadDualsOneEmptyAnim = 'Reload_Empty_Half' ;
const ReloadDualsOneEmptyEliteAnim = 'Reload_Empty_Half_Elite' ;
const CH _ReloadEmptyAnim = 'Reload_Empty_CH' ;
const CH _ReloadHalfAnim = 'Reload_Half_CH' ;
const CH _ReloadEmptyEliteAnim = 'Reload_Empty_Elite_CH' ;
const CH _ReloadHalfEliteAnim = 'Reload_Half_Elite_CH' ;
const CH _ReloadDualsOneEmptyAnim = 'Reload_Empty_Half_CH' ;
const CH _ReloadDualsOneEmptyEliteAnim = 'Reload_Empty_Half_Elite_CH' ;
/** Reload (single) anims */
const ReloadOpenAnim = 'Reload_Open' ;
const ReloadInsertAnim = 'Reload_Insert' ;
const ReloadCloseAnim = 'Reload_Close' ;
const ReloadOpenEliteAnim = 'Reload_Open_Elite' ;
const ReloadInsertEliteAnim = 'Reload_Insert_Elite' ;
const ReloadCloseEliteAnim = 'Reload_Close_Elite' ;
const ReloadOpenEmptyAnim = 'Reload_Open_Shell' ;
const ReloadOpenEmptyEliteAnim = 'Reload_Open_Shell_Elite' ;
const CH _ReloadOpenAnim = 'Reload_Open_CH' ;
const CH _ReloadInsertAnim = 'Reload_Insert_CH' ;
const CH _ReloadCloseAnim = 'Reload_Close_CH' ;
const CH _ReloadOpenEliteAnim = 'Reload_Open_Elite_CH' ;
const CH _ReloadInsertEliteAnim = 'Reload_Insert_Elite_CH' ;
const CH _ReloadCloseEliteAnim = 'Reload_Close_Elite_CH' ;
const CH _ReloadOpenEmptyAnim = 'Reload_Open_Shell_CH' ;
const CH _ReloadOpenEmptyEliteAnim = 'Reload_Open_Shell_Elite_CH' ;
/** Used only by the healing syringe */
const HealSelfAnim = 'Healer_Self' ;
const HealOtherAnim = 'Healer_F' ;
const QuickHealAnim = 'Heal_Quick' ;
const CH _HealSelfAnim = 'Healer_Self_CH' ;
const CH _HealOtherAnim = 'Healer_F_CH' ;
const CH _QuickHealAnim = 'Heal_Quick_CH' ;
/** Used only by the welder */
const WeldStartAnim = 'Welder_Start' ;
const WeldLoopAnim = 'Welder_Loop' ;
const WeldEndAnim = 'Welder_End' ;
const CH _WeldStartAnim = 'Welder_Start_CH' ;
const CH _WeldLoopAnim = 'Welder_Loop_CH' ;
const CH _WeldEndAnim = 'Welder_End_CH' ;
/** Additive shoot anims */
const ShootAnim = 'ADD_Shoot' ;
const CrouchShootAnim = 'ADD_CH_Shoot' ;
const IronShootAnim = 'ADD_Iron_Shoot' ;
/** Weapon shoots */
const WeaponFireAnim = 'Shoot' ;
const WeaponAltFireAnim = 'Shoot' ;
const WeaponIronFireAnim = 'Iron_Shoot' ;
/** (TEMP) blend settings */
var ( Anims ) float DefaultBlendInTime ;
var ( Anims ) float DefaultBlendOutTime ;
var ( Anims ) float ShootBlendInTime ;
var ( Anims ) float ShootBlendOutTime ;
/** Enable recoile skeletal controls */
var ( Anims ) bool bPlayIKRecoil ;
/** Save the last random index so we can choose a different one */
var transient byte LastMeleeAnimIdx ;
/** If set, check a character AnimNodeSlot and attempt to synchronize the weapon */
var transient bool bSynchronizeWeaponAnim ;
var transient AnimNodeSlot SyncPawnNode ;
var transient name SyncAnimName ;
var transient bool bSyncAnimCheckRelevance ;
/** Info for state LoopingWeaponAction */
var transient name LoopingAnim ;
var transient name LoopIntroAnim ;
var transient name LoopOutroAnim ;
var transient bool bLoopSynchedWeaponAnim ;
/** Cached AnimNodeSequence for the 3rd person weapon mesh */
var transient AnimNodeSequence WeapAnimNode ;
/** Profile name for this weapon */
var ( Anims ) name AimOffsetProfileName ;
/** Used by AimOffset node when bTurnOffWhenReloadingWeapon==TRUE */
var transient bool bIsReloading ;
var transient int WeaponSkinId ;
var bool bWaitingForWeaponSkinLoad ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ name Attach / Detach
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/** Weapon Mesh Attachment */
native event ChangeVisibility ( bool bIsVisible ) ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ name Skins
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
native function bool StartLoadWeaponSkin ( int SkinId ) ;
event PreBeginPlay ( )
{
local int i ;
if ( WeapMesh != None && ! bWeapMeshIsPawnMesh )
{
if ( WeaponAnimSet != None )
{
WeapMesh . AnimSets [ 0 ] = WeaponAnimSet ;
}
if ( SkelMesh != none )
{
// set the skeletal mesh from our archetype to the WeaponAttachment
WeapMesh . SkeletalMesh = SkelMesh ;
}
WeapAnimNode = AnimNodeSequence ( WeapMesh . Animations ) ;
}
for ( i = 0 ; i < TracerInfos . Length ; ++ i )
{
TracerInfos [ i ] . VelocityVector = vect ( 1 , 0 , 0 ) * TracerInfos [ i ] . TracerVelocity ;
}
super . PreBeginPlay ( ) ;
}
/** Attach weapon to owner's skeletal mesh */
simulated function AttachTo ( KFPawn P )
{
local byte WeaponAnimSetIdx ;
if ( bWeapMeshIsPawnMesh )
{
WeapMesh = P . Mesh ;
}
else if ( WeapMesh != None )
{
// Attach Weapon mesh to player skel mesh
WeapMesh . SetShadowParent ( P . Mesh ) ;
P . Mesh . AttachComponent ( WeapMesh , P . WeaponAttachmentSocket ) ;
}
// Additional attachments
if ( bHasLaserSight && ! P . IsFirstPerson ( ) )
{
AttachLaserSight ( ) ;
}
// Animation
if ( CharacterAnimSet != None )
{
WeaponAnimSetIdx = P . CharacterArch . GetWeaponAnimSetIdx ( ) ;
P . Mesh . AnimSets [ WeaponAnimSetIdx ] = CharacterAnimSet ;
// update animations will reload all AnimSeqs with the new AnimSet
P . Mesh . UpdateAnimations ( ) ;
}
// update aim offset nodes with new profile for this weapon
P . SetAimOffsetNodesProfile ( AimOffsetProfileName ) ;
//Do a first chance weapon skin switch (EX: changed weapon w/o ID changing by throwing a dualie)
if ( KFPawn _Human ( P ) != None && KFPawn _Human ( P ) . WeaponSkinItemId > 0 )
{
SetWeaponSkin ( KFPawn _Human ( P ) . WeaponSkinItemId ) ;
}
}
/** Detach weapon from owner's skeletal mesh */
simulated function DetachFrom ( KFPawn P )
{
// detach effects
if ( MuzzleFlash != None )
{
MuzzleFlash . DetachMuzzleFlash ( WeapMesh ) ;
}
// Finally, detach weapon mesh
if ( bWeapMeshIsPawnMesh )
{
WeapMesh = None ;
}
else if ( WeapMesh != None )
{
WeapMesh . SetShadowParent ( None ) ;
P . Mesh . DetachComponent ( WeapMesh ) ;
}
}
simulated function AttachMuzzleFlash ( )
{
if ( WeapMesh != none && MuzzleFlash == None )
{
MuzzleFlash = new ( self ) Class 'KFMuzzleFlash' ( MuzzleFlashTemplate ) ;
MuzzleFlash . AttachMuzzleFlash ( WeapMesh ) ;
}
}
simulated function AttachLaserSight ( )
{
if ( WeapMesh != none && LaserSight == None && LaserSightArchetype != None )
{
LaserSight = new ( self ) Class 'KFLaserSightAttachment' ( LaserSightArchetype ) ;
LaserSight . AttachLaserSight ( WeapMesh , false ) ;
}
}
/ * *
* Assign weapon skin to 3 rd person mesh
* /
event SetWeaponSkin ( int ItemId , optional bool bFinishedLoading = false )
{
local array < MaterialInterface > SkinMICs ;
if ( ItemId > 0 && WorldInfo . NetMode != NM _DedicatedServer && ! bWaitingForWeaponSkinLoad )
{
if ( ! bFinishedLoading && StartLoadWeaponSkin ( ItemId ) )
{
return ;
}
SkinMICs = class 'KFWeaponSkinList' . static . GetWeaponSkin ( ItemId , WST _ThirdPerson ) ;
if ( SkinMICs . Length > 0 )
{
WeapMesh . SetMaterial ( 0 , SkinMICs [ 0 ] ) ;
}
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ name Fire Effect Methods
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ * *
* Need to either call Instigator . ActorEffectIsRelevant ( ) , or determine our
* own Location and LastRenderTime before calling Super . ActorEffectIsRelevant ( ) .
* /
simulated function bool ActorEffectIsRelevant ( Pawn EffectInstigator , bool bForceDedicated , optional float VisibleCullDistance = 5000.0 , optional float HiddenCullDistance = 350.0 )
{
if ( Instigator != None )
{
return Instigator . ActorEffectIsRelevant ( EffectInstigator , bForceDedicated , VisibleCullDistance , HiddenCullDistance ) ;
}
return FALSE ;
}
/ * *
* The Weapon attachment , though hidden , is also responsible for controlling
* the first person effects for a weapon .
* /
simulated function FirstPersonFireEffects ( Weapon W , vector HitLocation ) // Should be subclassed
{
if ( W != None )
{
SpawnTracer ( W . GetMuzzleLoc ( ) , HitLocation ) ;
}
}
simulated function StopFirstPersonFireEffects ( Weapon W ) // Should be subclassed
{
if ( W != None )
{
// Tell the weapon to cause the muzzle flash, etc.
W . StopFireEffects ( Pawn ( Owner ) . FiringMode ) ;
}
}
simulated function StartFire ( )
{
}
simulated function StartPawnCrouch ( )
{
}
simulated function EndPawnCrouch ( )
{
}
simulated function SetWeaponUsingIronSights ( bool bUsingIronSights )
{
}
simulated function SetWeaponAltFireMode ( bool bUsingAltFireMode )
{
}
/ * *
* Spawn all of the effects that will be seen in behindview / remote clients . This
* function is called from the pawn , and should only be called when on a remote client or
* if the local client is in a 3 rd person mode .
* @ return TRUE if the effect culling check passes
* /
simulated function bool ThirdPersonFireEffects ( vector HitLocation , KFPawn P , byte ThirdPersonAnimRateByte )
{
local EAnimSlotStance AnimType ;
SpawnTracer ( GetMuzzleLocation ( ) , HitLocation ) ;
// Effects below this point are culled based on visibility and distance
if ( ! ActorEffectIsRelevant ( P , false , MaxFireEffectDistance ) )
{
return false ;
}
DecodeThirdPersonAnimRate ( ThirdPersonAnimRateByte ) ;
// Weapon shoot anims
if ( ! bWeapMeshIsPawnMesh )
{
PlayWeaponFireAnim ( ) ;
}
if ( P . IsDoingSpecialMove ( ) && P . SpecialMoves [ P . SpecialMove ] . bAllowFireAnims )
{
AnimType = EAS _Additive ;
}
else
{
AnimType = EAS _FullBody ;
}
// Character shoot anims
if ( ! P . IsDoingSpecialMove ( ) || AnimType == EAS _Additive )
{
PlayPawnFireAnim ( P , AnimType ) ;
// interrupt other weapon action anims (e.g. Reload)
if ( ! P . IsDoingSpecialMove ( ) )
{
P . StopBodyAnim ( P . bIsCrouched ? EAS _CH _UpperBody : EAS _UpperBody , 0.1 f ) ;
}
if ( OnWeaponStateChanged != None )
{
OnWeaponStateChanged ( true ) ;
}
}
CauseMuzzleFlash ( P . FiringMode ) ;
return true ;
}
/** Plays fire animation on weapon mesh */
simulated function PlayWeaponFireAnim ( )
{
local float Duration ;
if ( Instigator . bIsWalking )
{
Duration = WeapMesh . GetAnimLength ( WeaponIronFireAnim ) ;
WeapMesh . PlayAnim ( WeaponIronFireAnim , Duration / ThirdPersonAnimRate , , true ) ;
}
else
{
Duration = WeapMesh . GetAnimLength ( WeaponFireAnim ) ;
WeapMesh . PlayAnim ( WeaponFireAnim , Duration / ThirdPersonAnimRate , , true ) ;
}
}
/** Plays fire animation on pawn */
simulated function PlayPawnFireAnim ( KFPawn P , EAnimSlotStance AnimType )
{
if ( P . bIsCrouched )
{
P . PlayBodyAnim ( CrouchShootAnim , AnimType , ThirdPersonAnimRate , ShootBlendInTime , ShootBlendOutTime ) ;
}
else if ( P . bIsWalking )
{
P . PlayBodyAnim ( IronShootAnim , AnimType , ThirdPersonAnimRate , ShootBlendInTime , ShootBlendOutTime ) ;
}
else
{
P . PlayBodyAnim ( ShootAnim , AnimType , ThirdPersonAnimRate , ShootBlendInTime , ShootBlendOutTime ) ;
}
}
simulated function StopThirdPersonFireEffects ( optional bool bForce )
{
if ( MuzzleFlash != None )
{
MuzzleFlash . StopMuzzleFlash ( bForce ) ;
}
}
/** @return the starting location for effects (e.g. tracers) */
simulated function vector GetMuzzleLocation ( optional byte MuzzleID )
{
local vector SocketLocation ;
if ( MuzzleFlashTemplate != none )
{
WeapMesh . GetSocketWorldLocationAndRotation ( MuzzleFlashTemplate . GetSocketName ( ) , SocketLocation ) ;
return SocketLocation ;
}
else
{
` log("Missing 3rd person muzzle socket for"@SkelMesh);
return WeapMesh . Bounds . Origin + ( vect ( 45 , 0 , 0 ) >> Instigator . Rotation ) ;
}
}
/** Spawn tracer effects for this weapon */
simulated function SpawnTracer ( vector EffectLocation , vector HitLocation )
{
local ParticleSystemComponent E ;
local vector Dir ;
local float DistSQ ;
local float TracerDuration ;
local KFTracerInfo TracerInfo ;
if ( Instigator == None || Instigator . FiringMode >= TracerInfos . Length )
{
return ;
}
TracerInfo = TracerInfos [ Instigator . FiringMode ] ;
if ( ( ( ` NotInZedTime(self) && TracerInfo.bDoTracerDuringNormalTime)
|| ( ` IsInZedTime(self) && TracerInfo.bDoTracerDuringZedTime))
&& TracerInfo . TracerTemplate != none )
{
Dir = HitLocation - EffectLocation ;
DistSQ = VSizeSq ( Dir ) ;
if ( DistSQ > TracerInfo . MinTracerEffectDistanceSquared )
{
// Lifetime scales based on the distance from the impact point. Subtract a frame so it doesn't clip.
TracerDuration = fMin ( ( Sqrt ( DistSQ ) - 100. f ) / TracerInfo . TracerVelocity , 1. f ) ;
if ( TracerDuration > 0. f )
{
E = WorldInfo . MyEmitterPool . SpawnEmitter ( TracerInfo . TracerTemplate , EffectLocation , rotator ( Dir ) ) ;
E . SetVectorParameter ( 'Tracer_Velocity' , TracerInfo . VelocityVector ) ;
E . SetFloatParameter ( 'Tracer_Lifetime' , TracerDuration ) ;
}
}
}
}
/** Attach if needed, trigger muzzle flash, trigger shell eject */
simulated function CauseMuzzleFlash ( byte FiringMode )
{
if ( MuzzleFlash == None && MuzzleFlashTemplate != None )
{
AttachMuzzleFlash ( ) ;
}
if ( MuzzleFlash != None )
{
MuzzleFlash . CauseMuzzleFlash ( FiringMode ) ;
if ( MuzzleFlash . bAutoActivateShellEject )
{
MuzzleFlash . CauseShellEject ( ) ;
}
}
}
/** notify to spawn a shell eject from the muzzle flash component */
simulated function ANIMNOTIFY _ShellEject ( )
{
if ( MuzzleFlash == None && MuzzleFlashTemplate != None )
{
MuzzleFlash = new ( self ) Class 'KFMuzzleFlash' ( MuzzleFlashTemplate ) ;
MuzzleFlash . AttachMuzzleFlash ( WeapMesh ) ;
}
if ( MuzzleFlash != None )
{
MuzzleFlash . CauseShellEject ( ) ;
}
}
/** Adds some value to this weapon's blood material parameter */
simulated function AddBattleBlood ( float InBloodParamIncrementValue )
{
// Weapon shoot anims
if ( ! bWeapMeshIsPawnMesh )
{
if ( WeaponMIC == None && WeapMesh != None )
{
WeaponMIC = WeapMesh . CreateAndSetMaterialInstanceConstant ( 0 ) ;
}
if ( WeaponMIC != None )
{
BloodParamValue = FMax ( BloodParamValue + InBloodParamIncrementValue , MinBloodParamValue ) ;
WeaponMIC . SetScalarParameterValue ( BloodParamName , BloodParamValue ) ;
}
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ name Character Animation
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
delegate OnWeaponStateChanged ( optional bool bInterrupted ) ;
/ * *
* Plays a split ( upper and lower body ) animation on the owning pawn
* Network : All but dedicated
*
* @ param P Owning pawn to play animation on
* @ param AnimName Anim to play
* @ param bPlaySynchronizedWeaponAnim If true , try to play the same animation on the weapon mesh
* /
simulated function float PlayCharacterMeshAnim ( KFPawn P , name AnimName , optional bool bPlaySynchedWeaponAnim , optional bool bLooping )
{
local float Duration ;
local EAnimSlotStance Stance ;
// skip weapon anims while in a special move
if ( P . IsDoingSpecialMove ( ) && ! P . SpecialMoves [ P . SpecialMove ] . bAllowThirdPersonWeaponAnims )
{
return 0. f ;
}
Stance = ( ! P . bIsCrouched ) ? EAS _UpperBody : EAS _CH _UpperBody ;
Duration = P . PlayBodyAnim ( AnimName , Stance , ThirdPersonAnimRate , DefaultBlendInTime , DefaultBlendOutTime , bLooping ) ;
if ( Duration > 0 && bPlaySynchedWeaponAnim )
{
PlayWeaponMeshAnim ( AnimName , P . BodyStanceNodes [ Stance ] , bLooping ) ;
}
` log(GetFuncName()@"called on:" $ P@"Anim:" $ AnimName@"Duration:" $ Duration, bDebug);
return Duration ;
}
function DecodeThirdPersonAnimRate ( byte ThirdPersonAnimRateByte )
{
ThirdPersonAnimRate = 1. f + ByteToFloat ( ThirdPersonAnimRateByte ) ;
}
/** Called from the pawn when our first person weapon changes states */
simulated function UpdateThirdPersonWeaponAction ( EWeaponState NewWeaponState , KFPawn P , byte ThirdPersonAnimRateByte )
{
ClearTimer ( nameof ( LoopWeaponMeleeAnim ) ) ;
bIsReloading = false ;
// We need our anim rate scale before doing anything
DecodeThirdPersonAnimRate ( ThirdPersonAnimRateByte ) ;
if ( OnWeaponStateChanged != None )
{
OnWeaponStateChanged ( ) ;
}
` log(GetFuncName()@"called on"@self@"State:"@EWeaponState(NewWeaponState), bDebug);
switch ( NewWeaponState )
{
case WEP _Equipping :
PlayCharacterMeshAnim ( P , P . bIsCrouched ? CH _EquipAnim : EquipAnim ) ;
break ;
case WEP _PutAway :
PlayCharacterMeshAnim ( P , P . bIsCrouched ? CH _PutAwayAnim : PutAwayAnim ) ;
break ;
case WEP _Grenade :
PlayCharacterMeshAnim ( P , P . bIsCrouched ? CH _GrenadeAnim : GrenadeAnim ) ;
break ;
case WEP _Heal :
PlayHealAnim ( P ) ;
break ;
case WEP _HealQuick :
PlayCharacterMeshAnim ( P , P . bIsCrouched ? CH _QuickHealAnim : QuickHealAnim ) ;
break ;
case WEP _Weld :
PlayWeldAnim ( P ) ;
break ;
case WEP _Cleaning :
PlayCharacterMeshAnim ( P , P . bIsCrouched ? CH _CleanWeaponAnim : CleanWeaponAnim ) ;
break ;
case WEP _MeleeBasic :
//case WEP_MeleeChain:
case WEP _Melee _B :
case WEP _Melee _F :
case WEP _Melee _L :
case WEP _Melee _R :
case WEP _MeleeHeavy _B :
case WEP _MeleeHeavy _F :
case WEP _MeleeHeavy _L :
case WEP _MeleeHeavy _R :
PlayMeleeAtkAnim ( NewWeaponState , P ) ;
break ;
case WEP _MeleeSustained :
PlayMeleeSustainedAnim ( P ) ;
break ;
case WEP _MeleeBlock :
PlayMeleeBlockAnim ( P ) ;
break ;
case WEP _Reload :
case WEP _ReloadEmpty :
case WEP _Reload _Elite :
case WEP _ReloadEmpty _Elite :
case WEP _ReloadSecondary :
case WEP _ReloadSecondary _Elite :
case WEP _ReloadDualsOneEmpty :
case WEP _ReloadDualsOneEmpty _Elite :
2021-09-02 21:46:08 +00:00
case WEP _ReloadSecondaryEmpty :
case WEP _ReloadSecondaryEmpty _Elite :
2020-12-13 15:01:13 +00:00
bIsReloading = true ;
PlayReloadMagazineAnim ( NewWeaponState , P ) ;
break ;
case WEP _ReloadSingle :
case WEP _ReloadSingle _Elite :
case WEP _ReloadSingleEmpty :
case WEP _ReloadSingleEmpty _Elite :
bIsReloading = true ;
PlayReloadSingleAnim ( NewWeaponState , P ) ;
break ;
}
}
/** Play a melee attack animation */
simulated function float PlayMeleeAtkAnim ( EWeaponState NewWeaponState , KFPawn P )
{
local name AnimName ;
local float Duration ;
// third-person melee notifies don't properly handle the bIgnoreIfActorHidden setting because their owning actor isn't ever hidden (because it's the pawn),
// so just don't play third-person melee anims on first-person pawns (there's no need to anyway)
if ( P . IsFirstPerson ( ) )
{
return Duration ;
}
switch ( NewWeaponState )
{
case WEP _MeleeBasic :
AnimName = P . bIsCrouched ? CH _MeleeBasic : MeleeBasic ;
break ;
case WEP _MeleeHeavy _B :
AnimName = P . bIsCrouched ? CH _MeleeHeavy _B : MeleeHeavy _B ;
break ;
case WEP _MeleeHeavy _F :
AnimName = P . bIsCrouched ? CH _MeleeHeavy _F : MeleeHeavy _F ;
break ;
case WEP _MeleeHeavy _L :
AnimName = P . bIsCrouched ? CH _MeleeHeavy _L : MeleeHeavy _L ;
break ;
case WEP _MeleeHeavy _R :
AnimName = P . bIsCrouched ? CH _MeleeHeavy _R : MeleeHeavy _R ;
break ;
case WEP _Melee _B :
AnimName = P . bIsCrouched ? CH _MeleeAnim _B : MeleeAnim _B ;
break ;
case WEP _Melee _F :
AnimName = P . bIsCrouched ? CH _MeleeAnim _F : MeleeAnim _F ;
break ;
case WEP _Melee _L :
AnimName = P . bIsCrouched ? CH _MeleeAnim _L : MeleeAnim _L ;
break ;
case WEP _Melee _R :
AnimName = P . bIsCrouched ? CH _MeleeAnim _R : MeleeAnim _R ;
break ;
//case WEP_MeleeChain:
// AnimName = GetRandomDirectionalMeleeAnim(P);
// break;
}
if ( AnimName != '' )
{
Duration = PlayCharacterMeshAnim ( P , AnimName ) ;
//if ( WeaponState == WEP_MeleeChain && Duration > 0 )
//{
// SetTimer(FMax(0.01, Duration - MeleeLoopAtkTimeFromEnd), false, nameof(LoopWeaponMeleeAnim));
//}
}
return Duration ;
}
/** Helper for PlayMeleeAtkAnim */
simulated function name GetRandomDirectionalMeleeAnim ( Pawn P )
{
local byte AnimIdx , NumTries ;
do
{
// pick a random animation, different than the last
AnimIdx = Rand ( 4 ) ;
NumTries ++ ;
} until ( LastMeleeAnimIdx != AnimIdx || NumTries >= 4 ) ;
LastMeleeAnimIdx = AnimIdx ;
switch ( AnimIdx )
{
case 0 :
return P . bIsCrouched ? CH _MeleeAnim _F : MeleeAnim _F ;
case 1 :
return P . bIsCrouched ? CH _MeleeAnim _B : MeleeAnim _B ;
case 2 :
return P . bIsCrouched ? CH _MeleeAnim _L : MeleeAnim _L ;
case 3 :
return P . bIsCrouched ? CH _MeleeAnim _R : MeleeAnim _R ;
}
}
/** Restart (aka Loop) this weapon state animation */
simulated function LoopWeaponMeleeAnim ( )
{
local KFPawn P ;
P = KFPawn ( Owner ) ;
if ( P != None && ! P . IsDoingSpecialMove ( ) )
{
UpdateThirdPersonWeaponAction ( WEP _MeleeChain , P , P . GetWeaponAttachmentAnimRateByte ( ) ) ;
}
}
/** Play a 3rd person weapon action anim */
simulated function PlayMeleeBlockAnim ( KFPawn P )
{
if ( P . bIsCrouched )
{
StartLoopingAnim ( P , CH _BlockLoopAnim , CH _BlockStartAnim , CH _BlockEndAnim ) ;
}
else
{
StartLoopingAnim ( P , BlockLoopAnim , BlockStartAnim , BlockEndAnim ) ;
}
}
/** Play a 3rd person weapon action anim */
simulated function PlayMeleeSustainedAnim ( KFPawn P )
{
if ( P . bIsCrouched )
{
StartLoopingAnim ( P , CH _MeleeLoopAnim , CH _MeleeStartAnim , CH _MeleeEndAnim ) ;
}
else
{
StartLoopingAnim ( P , MeleeLoopAnim , MeleeStartAnim , MeleeEndAnim ) ;
}
}
/** Play a 3rd person reload animation */
simulated function PlayReloadMagazineAnim ( EWeaponState NewWeaponState , KFPawn P )
{
local name AnimName ;
switch ( NewWeaponState )
{
case WEP _Reload :
AnimName = ( ! P . bIsCrouched ) ? ReloadHalfAnim : CH _ReloadHalfAnim ;
break ;
case WEP _ReloadEmpty :
AnimName = ( ! P . bIsCrouched ) ? ReloadEmptyAnim : CH _ReloadEmptyAnim ;
break ;
case WEP _ReloadDualsOneEmpty :
AnimName = ( ! P . bIsCrouched ) ? ReloadDualsOneEmptyAnim : CH _ReloadDualsOneEmptyAnim ;
break ;
case WEP _Reload _Elite :
AnimName = ( ! P . bIsCrouched ) ? ReloadHalfEliteAnim : CH _ReloadHalfEliteAnim ;
break ;
case WEP _ReloadEmpty _Elite :
AnimName = ( ! P . bIsCrouched ) ? ReloadEmptyEliteAnim : CH _ReloadEmptyEliteAnim ;
break ;
case WEP _ReloadDualsOneEmpty _Elite :
AnimName = ( ! P . bIsCrouched ) ? ReloadDualsOneEmptyEliteAnim : CH _ReloadDualsOneEmptyEliteAnim ;
break ;
}
PlayCharacterMeshAnim ( P , AnimName , true ) ;
}
/** Play a 3rd person reload animation */
simulated function PlayReloadSingleAnim ( EWeaponState NewWeaponState , KFPawn P )
{
switch ( NewWeaponState )
{
case WEP _ReloadSingle :
if ( P . bIsCrouched )
StartLoopingAnim ( P , CH _ReloadInsertAnim , CH _ReloadOpenAnim , CH _ReloadCloseAnim , true ) ;
else
StartLoopingAnim ( P , ReloadInsertAnim , ReloadOpenAnim , ReloadCloseAnim , true ) ;
break ;
case WEP _ReloadSingle _Elite :
if ( P . bIsCrouched )
StartLoopingAnim ( P , CH _ReloadInsertEliteAnim , CH _ReloadOpenEliteAnim , CH _ReloadCloseEliteAnim , true ) ;
else
StartLoopingAnim ( P , ReloadInsertEliteAnim , ReloadOpenEliteAnim , ReloadCloseEliteAnim , true ) ;
break ;
case WEP _ReloadSingleEmpty :
if ( P . bIsCrouched )
StartLoopingAnim ( P , CH _ReloadInsertAnim , CH _ReloadOpenEmptyAnim , CH _ReloadCloseAnim , true ) ;
else
StartLoopingAnim ( P , ReloadInsertAnim , ReloadOpenEmptyAnim , ReloadCloseAnim , true ) ;
break ;
case WEP _ReloadSingleEmpty _Elite :
if ( P . bIsCrouched )
StartLoopingAnim ( P , CH _ReloadInsertEliteAnim , CH _ReloadOpenEmptyEliteAnim , CH _ReloadCloseEliteAnim , true ) ;
else
StartLoopingAnim ( P , ReloadInsertEliteAnim , ReloadOpenEmptyEliteAnim , ReloadCloseEliteAnim , true ) ;
break ;
}
}
/** Play a 3rd person heal animation */
simulated function PlayHealAnim ( KFPawn P )
{
if ( P . bIsCrouched )
{
PlayCharacterMeshAnim ( P , ( P . FiringMode == 0 ) ? CH _HealOtherAnim : CH _HealSelfAnim ) ;
}
else
{
PlayCharacterMeshAnim ( P , ( P . FiringMode == 0 ) ? HealOtherAnim : HealSelfAnim ) ;
}
}
/* Plays a 3rd person weld animation */
simulated function PlayWeldAnim ( KFPawn P )
{
if ( P . bIsCrouched )
{
StartLoopingAnim ( P , CH _WeldLoopAnim , CH _WeldStartAnim , CH _WeldEndAnim ) ;
}
else
{
StartLoopingAnim ( P , WeldLoopAnim , WeldStartAnim , WeldEndAnim ) ;
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ name Weapon Animation
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
simulated function PlayWeaponMeshAnim ( name AnimName , AnimNodeSlot SyncNode , bool bLoop )
{
local float Duration ;
// Weapon shoot anims
if ( ! bWeapMeshIsPawnMesh )
{
Duration = WeapMesh . GetAnimLength ( AnimName ) ;
WeapMesh . PlayAnim ( AnimName , Duration / ThirdPersonAnimRate , bLoop ) ;
// syncronize this with the character anim
if ( SyncNode != None )
{
bSynchronizeWeaponAnim = true ;
SyncPawnNode = SyncNode ;
SyncAnimName = AnimName ;
bSyncAnimCheckRelevance = false ;
}
}
}
/** Tick is used by bSynchronizeWeaponAnim */
simulated event Tick ( float DeltaTime )
{
// If we're playing a a syncronzied weapon action, check the owner pawn's animation
if ( ! bWeapMeshIsPawnMesh && bSynchronizeWeaponAnim && SyncPawnNode != None && WeapMesh . bForceRefpose == 0 )
{
// check to see if the character anim is still playing
if ( ! SyncPawnNode . bIsPlayingCustomAnim
|| ( ! SyncPawnNode . bRelevant && bSyncAnimCheckRelevance )
|| SyncPawnNode . GetPlayedAnimation ( ) != SyncAnimName )
{
if ( WeapAnimNode . bPlaying && WeapAnimNode . AnimSeqName == SyncAnimName )
{
InterruptWeaponAnim ( ) ;
}
bSynchronizeWeaponAnim = false ;
}
// After character mesh has been ticked once start checking node relevance
bSyncAnimCheckRelevance = true ;
}
}
/** Stops a currently playing 3rd person weapon animation */
simulated function InterruptWeaponAnim ( )
{
// Weapon shoot anims
if ( ! bWeapMeshIsPawnMesh )
{
WeapAnimNode . StopAnim ( ) ;
// Return to RefPos, because StopAnim doesn't call OnAnimEnd
if ( WeapAnimNode . bForceRefposeWhenNotPlaying )
{
WeapMesh . SetForceRefPose ( TRUE ) ;
}
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ name Rendering / Lighting
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/** Set the lighting channels on all the appropriate weapon attachment mesh(es) */
simulated function SetMeshLightingChannels ( LightingChannelContainer NewLightingChannels )
{
if ( ! bWeapMeshIsPawnMesh )
{
WeapMesh . SetLightingChannels ( NewLightingChannels ) ;
}
if ( LaserSight != none )
{
LaserSight . SetMeshLightingChannels ( NewLightingChannels ) ;
}
}
/** Debug */
simulated function bool HasIndoorLighting ( )
{
return WeapMesh . LightingChannels . Indoor ;
}
/** Debug */
simulated function bool HasOutdoorLighting ( )
{
return WeapMesh . LightingChannels . Outdoor ;
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* State LoopingWeaponAction
* Plays a looping character animation with optional intro / outro anims . Most weapon
* actions don ' t use state logic , but looping is complex enough that states are useful .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
simulated function StartLoopingAnim ( KFPawn P , name InLoopAnim , optional name InIntroAnim , optional name InOutroAnim , optional bool bPlaySynchedWeaponAnim )
{
if ( ! P . IsDoingSpecialMove ( ) )
{
LoopingAnim = InLoopAnim ;
LoopIntroAnim = InIntroAnim ;
LoopOutroAnim = InOutroAnim ;
bLoopSynchedWeaponAnim = bPlaySynchedWeaponAnim ;
GotoState ( 'LoopingWeaponAction' ) ;
}
}
// Global declarations for LoopingWeaponAction
simulated function PlayLoopAnim ( ) ;
simulated State LoopingWeaponAction
{
/** Play intro anim and start timer */
simulated function BeginState ( name PreviousStateName )
{
local KFPawn P ;
local float Duration ;
P = KFPawn ( Owner ) ;
if ( LoopIntroAnim != '' )
{
Duration = PlayCharacterMeshAnim ( P , LoopIntroAnim , bLoopSynchedWeaponAnim ) ;
if ( Duration > 0 )
{
// 0.2f should match the blend in time of the loop anim
SetTimer ( Duration - 0.2 f , false , nameof ( PlayLoopAnim ) ) ;
return ;
}
}
// no intro, start immediately
PlayLoopAnim ( ) ;
}
/** Make sure looping anim is stopped */
simulated function EndState ( Name NextStateName )
{
local KFPawn P ;
P = KFPawn ( Owner ) ;
if ( P != None )
{
P . StopBodyAnim ( EAS _UpperBody , 0.1 f ) ;
P . StopBodyAnim ( EAS _CH _UpperBody , 0.1 f ) ;
}
if ( bLoopSynchedWeaponAnim && bSynchronizeWeaponAnim )
{
InterruptWeaponAnim ( ) ;
}
}
/** Play main looping anim */
simulated function PlayLoopAnim ( )
{
local KFPawn P ;
P = KFPawn ( Owner ) ;
if ( P != None )
{
PlayCharacterMeshAnim ( P , LoopingAnim , bLoopSynchedWeaponAnim , true ) ;
}
}
/** Stop looping state and play outro anim */
simulated function UpdateThirdPersonWeaponAction ( EWeaponState NewWeaponState , KFPawn P , byte ThirdPersonAnimRateByte )
{
GotoState ( '' ) ;
if ( LoopOutroAnim != '' )
{
DecodeThirdPersonAnimRate ( ThirdPersonAnimRateByte ) ;
PlayCharacterMeshAnim ( P , LoopOutroAnim , bLoopSynchedWeaponAnim ) ;
}
Global . UpdateThirdPersonWeaponAction ( NewWeaponState , P , ThirdPersonAnimRateByte ) ;
}
/** Stop looping state */
simulated function bool ThirdPersonFireEffects ( vector HitLocation , KFPawn P , byte ThirdPersonAnimRateByte )
{
GotoState ( '' ) ;
return Global . ThirdPersonFireEffects ( HitLocation , P , ThirdPersonAnimRateByte ) ;
}
/** Stop looping state */
simulated function DetachFrom ( KFPawn P )
{
GotoState ( '' ) ;
Global . DetachFrom ( P ) ;
}
}
2021-06-02 20:06:18 +00:00
/** Special event added for weap attachments. Free for use */
function OnSpecialEvent ( int Arg ) ;
2020-12-13 15:01:13 +00:00
defaultproperties
{
Begin Object class = AnimNodeSequence Name = MeshSequenceA
bForceRefposeWhenNotPlaying = true
End Object
// Weapon SkeletalMesh
Begin Object Class = SkeletalMeshComponent Name = SkeletalMeshComponent0
bOwnerNoSee = true
bOnlyOwnerSee = false
CollideActors = false
AlwaysLoadOnClient = true
AlwaysLoadOnServer = true
MaxDrawDistance = 4000
bUpdateSkelWhenNotRendered = false
bIgnoreControllersWhenNotRendered = true
bOverrideAttachmentOwnerVisibility = true
bAcceptsDynamicDecals = FALSE
Animations = MeshSequenceA
CastShadow = true
bCastDynamicShadow = true
bPerBoneMotionBlur = true
bForceRefPose = 1
// Default to outdoor. If indoor, this will be set when TWIndoorLightingVolume::Touch() event is received at spawn.
LightingChannels = ( Outdoor = TRUE , bInitialized = TRUE )
End Object
WeapMesh = SkeletalMeshComponent0
LaserSightArchetype = KFLaserSightAttachment 'FX_LaserSight_ARCH.Default_LaserSight_3P'
TickGroup = TG _DuringAsyncWork
NetUpdateFrequency = 10
RemoteRole = ROLE _None
bReplicateInstigator = true
MaxFireEffectDistance = 5000.0
AimOffsetProfileName = Default
// temp
DefaultBlendInTime = 0.2 f
DefaultBlendOutTime = 0.2 f
ShootBlendInTime = 0.1
ShootBlendOutTime = 0.1
ThirdPersonAnimRate = 1.0 f
LastMeleeAnimIdx = 255
bWaitingForWeaponSkinLoad = false
}