386 lines
12 KiB
Ucode
386 lines
12 KiB
Ucode
//=============================================================================
|
|
// KFWeap_Rifle_FrostShotgunAxe
|
|
//=============================================================================
|
|
// A Rifle with an axe that freezes enemies
|
|
//=============================================================================
|
|
// Killing Floor 2
|
|
// Copyright (C) 2019 Tripwire Interactive LLC
|
|
//=============================================================================
|
|
|
|
class KFWeap_Rifle_FrostShotgunAxe extends KFWeap_MeleeBase;
|
|
|
|
var float LastFireInterval;
|
|
var int iInstantHitDamageOnEnemyFrozen;
|
|
var int iNormalInstantHitDamage;
|
|
|
|
/** Returns trader filter index based on weapon type */
|
|
static simulated event EFilterTypeUI GetTraderFilter()
|
|
{
|
|
return FT_Shotgun;
|
|
}
|
|
|
|
static simulated event EFilterTypeUI GetAltTraderFilter()
|
|
{
|
|
return FT_Melee;
|
|
}
|
|
|
|
simulated event PreBeginPlay()
|
|
{
|
|
super.PreBeginPlay();
|
|
iNormalInstantHitDamage = InstantHitDamage[BASH_FIREMODE];
|
|
}
|
|
|
|
/**
|
|
* See Pawn.ProcessInstantHit
|
|
* @param DamageReduction: Custom KF parameter to handle penetration damage reduction
|
|
*/
|
|
simulated function ProcessInstantHitEx(byte FiringMode, ImpactInfo Impact, optional int NumHits, optional out float out_PenetrationVal, optional int ImpactNum)
|
|
{
|
|
local KFPerk InstigatorPerk;
|
|
|
|
InstigatorPerk = GetPerk();
|
|
if (InstigatorPerk != none)
|
|
{
|
|
InstigatorPerk.UpdatePerkHeadShots(Impact, InstantHitDamageTypes[FiringMode], ImpactNum);
|
|
}
|
|
|
|
super.ProcessInstantHitEx(FiringMode, Impact, NumHits, out_PenetrationVal, ImpactNum);
|
|
}
|
|
|
|
/** process local player impact for clientside hit detection */
|
|
event RecieveClientImpact(byte FiringMode, const out ImpactInfo Impact, optional out float PenetrationValue, optional int ImpactNum)
|
|
{
|
|
// skip KFWeap_MeleeBase because it does melee stuff
|
|
super(KFWeapon).RecieveClientImpact(FiringMode, Impact, PenetrationValue, ImpactNum);
|
|
}
|
|
|
|
/** Override melee SetIronSights (which sends to heavy attack) so that this weapon ironsights normally*/
|
|
simulated function SetIronSights(bool bNewIronSights)
|
|
{
|
|
super(KFWeapon).SetIronSights(bNewIronSights);
|
|
}
|
|
|
|
/** Override melee ShouldOwnerWalk which doesn't account for walking when in ironsights */
|
|
simulated function bool ShouldOwnerWalk()
|
|
{
|
|
return super(KFWeapon).ShouldOwnerWalk();
|
|
}
|
|
|
|
/** Save off the start time for the bash to determine whether this will be a normal stab or a bullet stab */
|
|
simulated function StartFire(byte FireModeNum)
|
|
{
|
|
// copying over auto reload functionality since MeleeBase overrides this by default
|
|
if (FireModeNum == DEFAULT_FIREMODE && ShouldAutoReload(FireModeNum))
|
|
{
|
|
FireModeNum = RELOAD_FIREMODE;
|
|
}
|
|
|
|
if (FireModeNum == RELOAD_FIREMODE)
|
|
{
|
|
// Skip Super/ ServerStartFire and let server wait for ServerSendToReload to force state synchronization
|
|
BeginFire(FireModeNum);
|
|
return;
|
|
}
|
|
if( FireModeNum == BASH_FIREMODE && WeaponFireTypes[FireModeNum] == EWFT_Custom )
|
|
{
|
|
super.StartMeleeFire(FireModeNum, MeleeAttackHelper.ChooseAttackDir(), ATK_Normal);
|
|
return;
|
|
}
|
|
super.StartFire(FireModeNum);
|
|
}
|
|
|
|
/** Override to drop the player out of ironsights first */
|
|
simulated function AltFireMode()
|
|
{
|
|
if (!Instigator.IsLocallyControlled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// break out of ironsights when starting to block
|
|
if (bUsingSights)
|
|
{
|
|
SetIronSights(false);
|
|
}
|
|
|
|
StartFire(BLOCK_FIREMODE);
|
|
}
|
|
|
|
simulated state MeleeBlocking
|
|
{
|
|
simulated function BeginState(name PreviousStateName)
|
|
{
|
|
super.BeginState(PreviousStateName);
|
|
if (bUsingSights)
|
|
{
|
|
SetIronSights(false);
|
|
}
|
|
}
|
|
simulated function bool AllowIronSights() { return false; }
|
|
}
|
|
|
|
simulated function float GetFireInterval(byte FireModeNum)
|
|
{
|
|
if (FireModeNum == DEFAULT_FIREMODE && AmmoCount[FireModeNum] == 0)
|
|
{
|
|
return LastFireInterval;
|
|
}
|
|
|
|
return super.GetFireInterval(FireModeNum);
|
|
}
|
|
|
|
/** Called during reload state */
|
|
simulated function bool CanOverrideMagReload(byte FireModeNum)
|
|
{
|
|
if (FireModeNum == BLOCK_FIREMODE)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return super.CanOverrideMagReload(FireModeNum);
|
|
}
|
|
|
|
/** returns the damage amount for this attack */
|
|
simulated function int GetMeleeDamage(byte FireModeNum, optional vector RayDir)
|
|
{
|
|
local KFMeleeHelperWeaponFrostShotgunAxe oHelper;
|
|
local int Damage;
|
|
oHelper = KFMeleeHelperWeaponFrostShotgunAxe(MeleeAttackHelper);
|
|
if(oHelper.IsEnemyIced())
|
|
{
|
|
InstantHitDamage[FireModeNum] = iInstantHitDamageOnEnemyFrozen;
|
|
}
|
|
else
|
|
{
|
|
InstantHitDamage[FireModeNum] = iNormalInstantHitDamage;
|
|
}
|
|
Damage = Super.GetMeleeDamage(FireModeNum, RayDir);
|
|
return Damage;
|
|
}
|
|
|
|
|
|
|
|
simulated function int GetModifiedDamage(byte FireModeNum, optional vector RayDir)
|
|
{
|
|
switch(FireModeNum)
|
|
{
|
|
case DEFAULT_FIREMODE:
|
|
return GetUpgradedStatValue(InstantHitDamage[FireModeNum], EWUS_Damage0 , CurrentWeaponUpgradeIndex);
|
|
break;
|
|
case ALTFIRE_FIREMODE:
|
|
return GetUpgradedStatValue(InstantHitDamage[FireModeNum], EWUS_Damage1 , CurrentWeaponUpgradeIndex);
|
|
break;
|
|
case BASH_FIREMODE:
|
|
return GetUpgradedStatValue(InstantHitDamage[FireModeNum], EWUS_Damage2 , CurrentWeaponUpgradeIndex);
|
|
break;
|
|
}
|
|
return GetUpgradedStatValue(InstantHitDamage[FireModeNum], EWUS_Damage0 , CurrentWeaponUpgradeIndex);
|
|
}
|
|
|
|
/** Allows weapon to calculate its own damage for display in trader */
|
|
static simulated function float CalculateTraderWeaponStatDamage()
|
|
{
|
|
local float BaseDamage, DoTDamage;
|
|
local class<KFDamageType> DamageType;
|
|
|
|
BaseDamage = default.InstantHitDamage[DEFAULT_FIREMODE];
|
|
|
|
DamageType = class<KFDamageType>(default.InstantHitDamageTypes[DEFAULT_FIREMODE]);
|
|
if (DamageType != none && DamageType.default.DoT_Type != DOT_None)
|
|
{
|
|
DoTDamage = (DamageType.default.DoT_Duration / DamageType.default.DoT_Interval) * (BaseDamage * DamageType.default.DoT_DamageScale);
|
|
}
|
|
|
|
return BaseDamage * default.NumPellets[DEFAULT_FIREMODE] + DoTDamage;
|
|
}
|
|
|
|
/** Allows weapon to calculate its own fire rate for display in trader */
|
|
static simulated function float CalculateTraderWeaponStatFireRate()
|
|
{
|
|
return 60.f / default.FireInterval[DEFAULT_FIREMODE]; // attacks per minute
|
|
}
|
|
|
|
/** Spawn projectile is called once for each shot pellet fired */
|
|
simulated function KFProjectile SpawnAllProjectiles(class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir)
|
|
{
|
|
local KFPerk InstigatorPerk;
|
|
|
|
if (CurrentFireMode == GRENADE_FIREMODE)
|
|
{
|
|
return Super.SpawnProjectile(KFProjClass, RealStartLoc, AimDir);
|
|
}
|
|
|
|
InstigatorPerk = GetPerk();
|
|
if (InstigatorPerk != none)
|
|
{
|
|
Spread[CurrentFireMode] = default.Spread[CurrentFireMode] * InstigatorPerk.GetTightChokeModifier();
|
|
}
|
|
|
|
return super.SpawnAllProjectiles(KFProjClass, RealStartLoc, AimDir);
|
|
}
|
|
|
|
/** Plays a 'settle' animation after a melee attack is finished */
|
|
simulated function PlayMeleeSettleAnim()
|
|
{
|
|
PlayAnimation(MeleeAttackSettleAnims[0], 0.0, false, 0.1);
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
// MeleeBase
|
|
bMeleeWeapon=true
|
|
|
|
// Inventory / Grouping
|
|
InventoryGroup=IG_Primary
|
|
InventorySize=7
|
|
GroupPriority=80 //75
|
|
WeaponSelectTexture = Texture2D'WEP_UI_Frost_Shotgun_Axe_TEX.UI_WeaponSelect_FrostGun'
|
|
// Perks
|
|
AssociatedPerkClasses(0)=class'KFPerk_Support'
|
|
AssociatedPerkClasses(1)=class'KFPerk_Berserker'
|
|
|
|
// FOV
|
|
MeshFOV=65
|
|
MeshIronSightFOV=45
|
|
PlayerIronSightFOV=65
|
|
|
|
// Depth of field
|
|
DOF_FG_FocalRadius=50
|
|
DOF_FG_MaxNearBlurSize=3.5
|
|
|
|
// Content
|
|
PackageKey = "Frost_Shotgun_Axe"
|
|
FirstPersonMeshName="WEP_1P_Frost_Shotgun_Axe_MESH.Wep_1stP_Frost_Shotgun_Axe_Rig"
|
|
FirstPersonAnimSetNames(0)="WEP_1P_Frost_Shotgun_Axe_ANIM.WEP_1stP_Frost_Shotgun_Axe"
|
|
PickupMeshName="WEP_3P_Frost_Shotgun_Axe_MESH.Wep_3rdP_Frost_Shotgun_Pickup"
|
|
AttachmentArchetypeName="WEP_Frost_Shotgun_Axe_ARCH.Wep_Frost_Shotgun_Axe_3P"
|
|
MuzzleFlashTemplateName="WEP_Frost_Shotgun_Axe_ARCH.Wep_Frost_Shotgun_Axe_MuzzleFlash"
|
|
|
|
// Ammo
|
|
MagazineCapacity[0]=6
|
|
SpareAmmoCapacity[0]=66
|
|
InitialSpareMags[0]=4
|
|
AmmoPickupScale[0]=1
|
|
bCanBeReloaded=true
|
|
bReloadFromMagazine=false // @TODO: Turn off once animations are done
|
|
|
|
// Zooming/Position
|
|
PlayerViewOffset = (X = 8.0,Y = 7,Z = -3.5)
|
|
IronSightPosition = (X = 0,Y = 0,Z = 0)
|
|
|
|
// AI warning system
|
|
bWarnAIWhenAiming = true
|
|
AimWarningDelay = (X = 0.4f, Y = 0.8f)
|
|
AimWarningCooldown = 0.0f
|
|
|
|
// Recoil
|
|
maxRecoilPitch = 1050 //550
|
|
minRecoilPitch = 900 //400
|
|
maxRecoilYaw = 350 //150
|
|
minRecoilYaw = -350 //-150
|
|
RecoilRate = 0.075
|
|
RecoilMaxYawLimit = 500
|
|
RecoilMinYawLimit = 65035
|
|
RecoilMaxPitchLimit = 900
|
|
RecoilMinPitchLimit = 64785
|
|
RecoilISMaxYawLimit = 50
|
|
RecoilISMinYawLimit = 65485
|
|
RecoilISMaxPitchLimit = 500
|
|
RecoilISMinPitchLimit = 65485
|
|
RecoilViewRotationScale = 0.6
|
|
|
|
FallingRecoilModifier=1.5
|
|
HippedRecoilModifier=1.3
|
|
|
|
IronSightMeshFOVCompensationScale = 1.5
|
|
|
|
// DEFAULT_FIREMODE
|
|
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_ShotgunSingle'
|
|
FiringStatesArray(DEFAULT_FIREMODE)=WeaponSingleFiring
|
|
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile
|
|
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_Frost_Shotgun_Axe'
|
|
InstantHitDamage(DEFAULT_FIREMODE)=30 //32 //30
|
|
InstantHitDamageTypes(DEFAULT_FIREMODE) = class'KFDT_Ballistic_Frost_Shotgun_Axe'
|
|
FireInterval(DEFAULT_FIREMODE)=0.5 //0.25 // 240 RPM
|
|
Spread(DEFAULT_FIREMODE)=0.13 //0.007
|
|
PenetrationPower(DEFAULT_FIREMODE)=2
|
|
FireOffset = (X = 25,Y = 3.0,Z = -2.5)
|
|
NumPellets(DEFAULT_FIREMODE)=7
|
|
AmmoCost(DEFAULT_FIREMODE)=1
|
|
LastFireInterval=0.5
|
|
|
|
// RELOAD_FIREMODE
|
|
FiringStatesArray(RELOAD_FIREMODE)="Reloading"
|
|
WeaponFireTypes(RELOAD_FIREMODE)=EWFT_InstantHit
|
|
|
|
// BASH_FIREMODE
|
|
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Slashing_Frost_Shotgun_Axe'
|
|
InstantHitDamage(BASH_FIREMODE)=75 //120
|
|
FiringStatesArray(BASH_FIREMODE)=MeleeChainAttacking
|
|
WeaponFireTypes(BASH_FIREMODE)=EWFT_Custom
|
|
InstantHitMomentum(BASH_FIREMODE)=10000.f
|
|
iInstantHitDamageOnEnemyFrozen = 185 //360; //300;
|
|
|
|
// Custom animations
|
|
FireSightedAnims = (Shoot_Iron)
|
|
BonesToLockOnEmpty = (RW_Hammer)
|
|
bHasFireLastAnims = true
|
|
|
|
// Defensive
|
|
BlockDamageMitigation=0.6f
|
|
ParryDamageMitigationPercent=0.5
|
|
ParryStrength=4
|
|
|
|
// Block Effects
|
|
BlockSound=AkEvent'WW_WEP_Bullet_Impacts.Play_Block_MEL_Hammer'
|
|
ParrySound=AkEvent'WW_WEP_Bullet_Impacts.Play_Parry_Wood'
|
|
|
|
// Fire Effects
|
|
WeaponFireSnd(DEFAULT_FIREMODE) = (DefaultCue = AkEvent'WW_WEP_FrostFang.Play_FrostFang_Shoot_3p', FirstPersonCue = AkEvent'WW_WEP_FrostFang.Play_FrostFang_Shoot_1p') // @TODO: Replace Me
|
|
WeaponDryFireSnd(DEFAULT_FIREMODE) = AkEvent'WW_WEP_FrostFang.Play_FrostFang_Dryfire' // @TODO: Replace Me
|
|
EjectedShellForegroundDuration = 1.5f
|
|
|
|
// Attachments
|
|
bHasIronSights = true
|
|
bHasFlashlight = false
|
|
|
|
WeaponFireWaveForm = ForceFeedbackWaveform'FX_ForceFeedback_ARCH.Gunfire.Medium_Recoil'
|
|
|
|
// Aim Assist
|
|
AimCorrectionSize=40.f
|
|
|
|
// Melee
|
|
|
|
|
|
// Melee hitbox
|
|
Begin Object Class=KFMeleeHelperWeaponFrostShotgunAxe Name=MeleeHelper_0
|
|
MaxHitRange=250
|
|
HitboxChain.Add((BoneOffset=(X=+3,Z=-190)))
|
|
HitboxChain.Add((BoneOffset=(X=-3,Z=-170)))
|
|
HitboxChain.Add((BoneOffset=(X=+3,Z=-150)))
|
|
HitboxChain.Add((BoneOffset=(X=-3,Z=-130)))
|
|
HitboxChain.Add((BoneOffset=(X=+3,Z=-110)))
|
|
HitboxChain.Add((BoneOffset=(X=-3,Z=-90)))
|
|
HitboxChain.Add((BoneOffset=(X=+3,Z=-70)))
|
|
HitboxChain.Add((BoneOffset=(X=-3,Z=-50)))
|
|
HitboxChain.Add((BoneOffset=(X=+3,Z=-30)))
|
|
HitboxChain.Add((BoneOffset=(Z=10)))
|
|
WorldImpactEffects=KFImpactEffectInfo'FX_Impacts_ARCH.Bladed_melee_impact'
|
|
MeleeImpactCamShakeScale=0.03f
|
|
bUseDirectionalMelee=true
|
|
bHasChainAttacks=true
|
|
bUseMeleeHitTimer=false
|
|
// modified combo sequences
|
|
ChainSequence_F=(DIR_Left, DIR_ForwardRight, DIR_ForwardLeft, DIR_ForwardRight, DIR_ForwardLeft)
|
|
ChainSequence_B=(DIR_BackwardRight, DIR_ForwardLeft, DIR_BackwardLeft, DIR_ForwardRight, DIR_Left, DIR_Right, DIR_Left)
|
|
ChainSequence_L=(DIR_Right, DIR_Left, DIR_ForwardRight, DIR_ForwardLeft, DIR_Right, DIR_Left)
|
|
ChainSequence_R=(DIR_Left, DIR_Right, DIR_ForwardLeft, DIR_ForwardRight, DIR_Left, DIR_Right)
|
|
End Object
|
|
MeleeAttackHelper=MeleeHelper_0
|
|
|
|
// Weapon Upgrades
|
|
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.125f), (Stat=EWUS_Damage1, Scale=1.125f), (Stat=EWUS_Damage2, Scale=1.1f), (Stat=EWUS_Weight, Add=1)))
|
|
WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.25f), (Stat=EWUS_Damage1, Scale=1.25f), (Stat=EWUS_Damage2, Scale=1.2f), (Stat=EWUS_Weight, Add=2)))
|
|
|
|
bHasToBeConsideredAsRangedWeaponForPerks=true;
|
|
} |