166 lines
5.4 KiB
Ucode
166 lines
5.4 KiB
Ucode
//=============================================================================
|
|
// KFMeleeHelperWeapon
|
|
//=============================================================================
|
|
// Manages melee attack related functionality for 1st person weapons
|
|
//=============================================================================
|
|
// Killing Floor 2
|
|
// Copyright (C) 2015 Tripwire Interactive LLC
|
|
//=============================================================================
|
|
class KFMeleeHelperWeaponFrostShotgunAxe extends KFMeleeHelperWeapon
|
|
config(Game);
|
|
|
|
var bool bIcedEnemy;
|
|
var ParticleSystem ChargedEffect;
|
|
var ParticleSystemComponent FullyChargedPSC;
|
|
var AkEvent oFrozenSound;
|
|
var AkEvent oHitSoundAkEvent;
|
|
|
|
simulated function PawnTakeDamage(ImpactInfo Impact,byte FiringMode, vector Momentum)
|
|
{
|
|
local int InstantDamage;
|
|
|
|
bIcedEnemy = false;
|
|
if(Impact.HitActor.IsA('KFPawn_Monster'))
|
|
{
|
|
if(KFPawn_Monster(Impact.HitActor).IsDoingSpecialMove(SM_Frozen))
|
|
{
|
|
bIcedEnemy = true;
|
|
}
|
|
}
|
|
InstantDamage = GetMeleeDamage(FiringMode, Impact.RayDir);
|
|
Impact.HitActor.TakeDamage(InstantDamage, Instigator.Controller,
|
|
Impact.HitLocation, Momentum,
|
|
GetDamageType(FiringMode), Impact.HitInfo, Outer );
|
|
|
|
}
|
|
|
|
simulated function bool IsEnemyIced(){
|
|
return bIcedEnemy;
|
|
}
|
|
|
|
|
|
/** Called from state MeleeAtacking */
|
|
simulated function BeginMeleeAttack(optional bool bIsChainAttack)
|
|
{
|
|
local Pawn P;
|
|
local KFPawn_Monster KFPM;
|
|
local vector Projection;
|
|
local float MeleeDuration;
|
|
|
|
// Don't let a weak zed grab us when we just melee attacked
|
|
// Ramm - commented out, too exploitable
|
|
// SetWeakZedGrabCooldownOnPawn(0.5);
|
|
|
|
// initialize attack settings
|
|
bHasAlreadyHit = false;
|
|
bHitEnemyThisAttack = false;
|
|
|
|
// Let the playercontroller know we did an attack
|
|
if ( Instigator != None && Instigator.Controller != none &&
|
|
KFPlayerController(Instigator.Controller) != none )
|
|
{
|
|
KFPlayerController(Instigator.Controller).AddShotsFired(1);
|
|
}
|
|
|
|
// Clear reset flag (see InitAttackSequence, ContinueMeleeAttack)
|
|
bResetChainSequence = false;
|
|
|
|
// save the direction of this attack
|
|
CurrentAttackDir = ( CurrentFireMode == CUSTOM_FIREMODE ) ? DIR_None : GetNextAttackDir();
|
|
|
|
// Notify enemy pawns of melee strike
|
|
if( WorldInfo.NetMode != NM_Client )
|
|
{
|
|
foreach WorldInfo.AllPawns( class'Pawn', P )
|
|
{
|
|
if( P.GetTeamNum() != Instigator.GetTeamNum() && P.IsAliveAndWell() && !P.IsHumanControlled() )
|
|
{
|
|
Projection = Instigator.Location - P.Location;
|
|
if( VSizeSQ(Projection) <= Square(MaxHitRange + P.CylinderComponent.CollisionRadius) )
|
|
{
|
|
KFPM = KFPawn_Monster( P );
|
|
if( KFPM != none && KFPM.MyKFAIC != none )
|
|
{
|
|
KFPM.MyKFAIC.ReceiveMeleeWarning( CurrentAttackDir, Projection, Instigator );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Select and play attack animation
|
|
MeleeDuration = PlayMeleeAttackAnimation();
|
|
|
|
if ( MeleeDuration > 0.f )
|
|
{
|
|
// @hack: Add current DeltaSeconds to timer. This fixes an off-by-one frame issue that can
|
|
// that can cause the timer to interrupt animation at low framerate. This is particularly
|
|
// bad for melee when using impact anim notifies.
|
|
SetTimer(MeleeDuration + WorldInfo.DeltaSeconds, FALSE, nameof(MeleeCheckTimer), self);
|
|
|
|
// set the timer to check for hits
|
|
if( bUseMeleeHitTimer && InitialImpactDelay > 0.f )
|
|
{
|
|
// Clear complete time so it is intialized properly
|
|
ImpactComplete_ActorTime = -1.f;
|
|
SetTimer(InitialImpactDelay, FALSE, nameof(MeleeImpactTimer), self);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
`warn("MeleeDuration is zero!!!");
|
|
SetTimer(0.001, false, nameof(HandleFinishedFiring));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called by ProcessMeleeHit to spawn effects
|
|
* Network: Local Player and Server
|
|
*/
|
|
simulated function PlayMeleeHitEffects(Actor Target, vector HitLocation, vector HitDirection, optional bool bShakeInstigatorCamera=true)
|
|
{
|
|
// @note: Skipping super(). No victim camera shake is intentional
|
|
if( WorldInfo.NetMode != NM_DedicatedServer )
|
|
{
|
|
// first person (local) fire effects
|
|
if ( Instigator.IsFirstPerson() )
|
|
{
|
|
PlayerController(Instigator.Controller).ClientPlayCameraShake(MeleeImpactCamShake, MeleeImpactCamShakeScale, true, CAPS_UserDefined, rotator(-HitDirection));
|
|
|
|
if ( Target.IsA('Pawn') )
|
|
{
|
|
AddBlood(0.01f, 0.1f);
|
|
if(KFPawn_Monster(Target).IsDoingSpecialMove(SM_Frozen))
|
|
{
|
|
|
|
if( IsZero(HitDirection) && Instigator != none )
|
|
{
|
|
HitDirection = Normal(Instigator.Location - HitLocation);
|
|
}
|
|
|
|
WorldInfo.MyEmitterPool.SpawnEmitter(ChargedEffect, HitLocation, rotator(HitDirection), Target);
|
|
Instigator.PlayAkEvent(oFrozenSound);
|
|
Instigator.PlayAkEvent(oHitSoundAkEvent);
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we hit a pawn we can skip the Tracing code in PlayImpactEffects. Pawn FX are handled in
|
|
// PlayHit and this prevents incorrect (world) FX from playing if the trace is bad.
|
|
if ( !(Target.bCanBeDamaged && Target.IsA('Pawn')) )
|
|
{
|
|
// Use ImpactEffectManager to material based world impacts
|
|
`ImpactEffectManager.PlayImpactEffects(HitLocation, Instigator, HitDirection, WorldImpactEffects);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
defaultproperties
|
|
{
|
|
oFrozenSound=AkEvent'WW_WEP_SA_CompoundBow.Play_Arrow_Impact_Cryo'
|
|
oHitSoundAkEvent=AkEvent'WW_WEP_FrostFang.Play_FrostFang_Base_Impact'
|
|
ChargedEffect=ParticleSystem'WEP_Frost_Shotgun_Axe_EMIT.FX_FrostFang_Melee_ImpactFrozen_01';
|
|
HitboxBoneName=RW_Weapon
|
|
}
|