upload
This commit is contained in:
parent
23d1ca3a9a
commit
2c6c4ddc5c
36
KFGame/Classes/KFDT_Toxic_HRG_Locust.uc
Normal file
36
KFGame/Classes/KFDT_Toxic_HRG_Locust.uc
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Ballistic_HRG_Locust
|
||||||
|
//=============================================================================
|
||||||
|
// HRG Locust bullet impact
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
class KFDT_Toxic_HRG_Locust extends KFDT_Bleeding
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
// Damage dealt when zeds touch each other and spread the afflictions
|
||||||
|
var int SpreadOnTouchDamage;
|
||||||
|
|
||||||
|
static function int GetSpreadOnTouchDamage()
|
||||||
|
{
|
||||||
|
return default.SpreadOnTouchDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
DoT_Type=DOT_Bleeding
|
||||||
|
DoT_Duration=3.0
|
||||||
|
DoT_Interval=0.5
|
||||||
|
DoT_DamageScale=0.5
|
||||||
|
|
||||||
|
BleedPower = 20
|
||||||
|
PoisonPower = 25
|
||||||
|
|
||||||
|
ModifierPerkList(0)=class'KFPerk_Survivalist'
|
||||||
|
|
||||||
|
WeaponDef=class'KFWeapDef_HRG_Locust'
|
||||||
|
|
||||||
|
SpreadOnTouchDamage=30
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
class KFGFXSpecialEventObjectivesContainer_Fall2022 extends KFGFxSpecialEventObjectivesContainer;
|
||||||
|
|
||||||
|
function Initialize(KFGFxObject_Menu NewParentMenu)
|
||||||
|
{
|
||||||
|
super.Initialize(NewParentMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
ObjectiveIconURLs[0] = "Halloween2022_UI.UI_Objectives_Halloween2022_CreaturesInDarkness" // Kill 15 Bosses on any map or mode
|
||||||
|
ObjectiveIconURLs[1] = "Spring_UI.UI_Objectives_Spring_Weekly" // Complete the Weekly on BarmwichTown
|
||||||
|
ObjectiveIconURLs[2] = "Halloween2022_UI.UI_Objetives_Halloween2022_ElementalMedallions" // Open the Weapon Room
|
||||||
|
ObjectiveIconURLs[3] = "Halloween2022_UI.UI_Objectives_Halloween2022_ZedOnFire" // Make 50 Zeds to pass through the bonfires of Barmwitch Town
|
||||||
|
ObjectiveIconURLs[4] = "Halloween2022_UI.UI_Objetives_Halloween2022_LongNightofWitches" // Complete wave 15 on Endless Hard or higher difficulty on Barmwitch Town
|
||||||
|
|
||||||
|
//defaults
|
||||||
|
AllCompleteRewardIconURL="CHR_PlagueDoctorUniform_Item_TEX.potionbackpack.plaguedoctorbackpack_precious_large"
|
||||||
|
ChanceDropIconURLs[0]="CHR_CosmeticSet14_Item_TEX.Tickets.CyberPunk_ticket"
|
||||||
|
ChanceDropIconURLs[1]="CHR_CosmeticSet14_Item_TEX.Tickets.CyberPunk_ticket_golden"
|
||||||
|
IconURL="halloween2022_ui.KF2_Halloween_BloodandBonfires_SmallLogo"
|
||||||
|
|
||||||
|
UsesProgressList[0] = true
|
||||||
|
UsesProgressList[1] = false
|
||||||
|
UsesProgressList[2] = false
|
||||||
|
UsesProgressList[3] = true
|
||||||
|
UsesProgressList[4] = false
|
||||||
|
}
|
49
KFGame/Classes/KFGFxWidget_VIP.uc
Normal file
49
KFGame/Classes/KFGFxWidget_VIP.uc
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFGFxWidget_VIP
|
||||||
|
//=============================================================================
|
||||||
|
// HUD Widget that displays VIP messages to the player
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFGFxWidget_VIP extends GFxObject;
|
||||||
|
|
||||||
|
function SetVIP()
|
||||||
|
{
|
||||||
|
SetString("VIPSetLocalised", Class'KFCommon_LocalizedStrings'.default.VIPString);
|
||||||
|
SetString("VIPObjectiveSetLocalised", Class'KFCommon_LocalizedStrings'.default.VIPObjectiveBString);
|
||||||
|
SetString("VIPPlayerSet", Class'KFCommon_LocalizedStrings'.default.VIPObjectiveCString);
|
||||||
|
|
||||||
|
SetBool("VIPPlayerNameSetVisibility", true);
|
||||||
|
SetBool("VIPHideHealthBar", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function SetNOVIP(string VIPPlayerName, int VIPCurrentHealth, int VIPMaxHealth)
|
||||||
|
{
|
||||||
|
SetString("VIPSetLocalised", Class'KFCommon_LocalizedStrings'.default.VIPString);
|
||||||
|
SetString("VIPObjectiveSetLocalised", Class'KFCommon_LocalizedStrings'.default.VIPObjectiveAString);
|
||||||
|
SetString("VIPPlayerSet", VIPPlayerName);
|
||||||
|
|
||||||
|
SetBool("VIPPlayerNameSetVisibility", true);
|
||||||
|
|
||||||
|
UpdateHealth(VIPCurrentHealth, VIPMaxHealth);
|
||||||
|
}
|
||||||
|
|
||||||
|
function UpdateVIPVisibility(bool visible)
|
||||||
|
{
|
||||||
|
if (visible)
|
||||||
|
{
|
||||||
|
SetBool("VIPSetVisibility", true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetBool("VIPSetVisibility", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function UpdateHealth(int VIPCurrentHealth, int VIPMaxHealth)
|
||||||
|
{
|
||||||
|
SetFloat("VIPHealthBarPercentage", VIPMaxHealth != 0 ? (float(VIPCurrentHealth) / VIPMaxHealth) : 0.0f);
|
||||||
|
}
|
29
KFGame/Classes/KFWeapDef_G36C.uc
Normal file
29
KFGame/Classes/KFWeapDef_G36C.uc
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFWeaponDefintion
|
||||||
|
//=============================================================================
|
||||||
|
// A lightweight container for basic weapon properties that can be safely
|
||||||
|
// accessed without a weapon actor (UI, remote clients).
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
class KFWeapDef_G36C extends KFWeaponDefinition
|
||||||
|
abstract;
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
WeaponClassPath="KFGameContent.KFWeap_AssaultRifle_G36C"
|
||||||
|
|
||||||
|
BuyPrice=1600
|
||||||
|
AmmoPricePerMag=36
|
||||||
|
ImagePath="wep_ui_g36c_tex.UI_WeaponSelect_G36C"
|
||||||
|
|
||||||
|
EffectiveRange=70
|
||||||
|
|
||||||
|
UpgradePrice[0]=1500
|
||||||
|
|
||||||
|
UpgradeSellPrice[0]=1125
|
||||||
|
|
||||||
|
SharedUnlockId=SCU_G36C
|
||||||
|
|
||||||
|
}
|
24
KFGame/Classes/KFWeapDef_HRG_Dragonbreath.uc
Normal file
24
KFGame/Classes/KFWeapDef_HRG_Dragonbreath.uc
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFWeapDef_Dragonbreath
|
||||||
|
// This is the Doomstick
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2017 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
class KFWeapDef_HRG_Dragonbreath extends KFWeaponDefinition
|
||||||
|
abstract;
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
WeaponClassPath="KFGameContent.KFWeap_HRG_Dragonbreath"
|
||||||
|
|
||||||
|
BuyPrice=1400
|
||||||
|
AmmoPricePerMag=25
|
||||||
|
ImagePath="WEP_UI_HRG_MegaDragonsbreath_TEX.UI_WeaponSelect_HRG_MegaDragonsbreath"
|
||||||
|
|
||||||
|
EffectiveRange=25
|
||||||
|
|
||||||
|
UpgradePrice[0]=1500
|
||||||
|
|
||||||
|
UpgradeSellPrice[0]=1125
|
||||||
|
}
|
28
KFGame/Classes/KFWeapDef_HRG_Locust.uc
Normal file
28
KFGame/Classes/KFWeapDef_HRG_Locust.uc
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFWeapDef_HRG_Locust
|
||||||
|
//=============================================================================
|
||||||
|
// A lightweight container for basic weapon properties that can be safely
|
||||||
|
// accessed without a weapon actor (UI, remote clients).
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
class KFWeapDef_HRG_Locust extends KFWeaponDefinition
|
||||||
|
abstract;
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
WeaponClassPath="KFGameContent.KFWeap_HRG_Locust"
|
||||||
|
|
||||||
|
BuyPrice=900
|
||||||
|
AmmoPricePerMag=40
|
||||||
|
ImagePath="wep_ui_hrg_locust_tex.UI_WeaponSelect_HRG_Locust"
|
||||||
|
|
||||||
|
EffectiveRange=100
|
||||||
|
|
||||||
|
UpgradePrice[0]=700
|
||||||
|
UpgradePrice[1]=1500
|
||||||
|
|
||||||
|
UpgradeSellPrice[0]=525
|
||||||
|
UpgradeSellPrice[1]=1650
|
||||||
|
}
|
26
KFGame/Classes/KFWeapDef_Scythe.uc
Normal file
26
KFGame/Classes/KFWeapDef_Scythe.uc
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFWeapDef_Scythe
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
class KFWeapDef_Scythe extends KFWeaponDefinition
|
||||||
|
abstract;
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
WeaponClassPath="KFGameContent.KFWeap_Edged_Scythe"
|
||||||
|
|
||||||
|
BuyPrice=1500
|
||||||
|
ImagePath="WEP_UI_Scythe_TEX.UI_WeaponSelect_Scythe"
|
||||||
|
|
||||||
|
EffectiveRange=5
|
||||||
|
|
||||||
|
UpgradePrice[0]=1500
|
||||||
|
|
||||||
|
UpgradeSellPrice[0]=1125
|
||||||
|
|
||||||
|
SharedUnlockId=SCU_Scythe
|
||||||
|
|
||||||
|
}
|
77
KFGameContent/Classes/KFBarmwichBonfireVolume.uc
Normal file
77
KFGameContent/Classes/KFBarmwichBonfireVolume.uc
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFBarmwichBonfireVolume
|
||||||
|
//=============================================================================
|
||||||
|
// Barmwich volume used for bonfires. Triggers seasonal progression.
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFBarmwichBonfireVolume extends KFPhysicsDamageByPawnVolume
|
||||||
|
placeable;
|
||||||
|
|
||||||
|
/** Objective index for the event this is tied to */
|
||||||
|
var() int ObjectiveIndex;
|
||||||
|
|
||||||
|
/** Index of the event this is tied to */
|
||||||
|
var() int EventIndex;
|
||||||
|
|
||||||
|
var array<Actor> AffectedActors;
|
||||||
|
|
||||||
|
var transient bool bIsDataValid;
|
||||||
|
|
||||||
|
simulated event PostBeginPlay()
|
||||||
|
{
|
||||||
|
Super.PostBeginPlay();
|
||||||
|
|
||||||
|
bIsDataValid = IsObjectiveDataValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
function CausePainTo(Actor Other)
|
||||||
|
{
|
||||||
|
Super.CausePainTo(Other);
|
||||||
|
|
||||||
|
if (bIsDataValid && KFPawn_Monster(Other) != none && KFPawn_Monster(Other).IsAliveAndWell())
|
||||||
|
{
|
||||||
|
if (AffectedActors.Find(Other) == INDEX_NONE)
|
||||||
|
{
|
||||||
|
AffectedActors.AddItem(Other);
|
||||||
|
NotifyProgression();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function NotifyProgression()
|
||||||
|
{
|
||||||
|
local KFPlayerController KFPC;
|
||||||
|
|
||||||
|
if (!bIsDataValid)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach WorldInfo.AllControllers(class'KFPlayerController', KFPC)
|
||||||
|
{
|
||||||
|
KFPC.ClientOnTryCompleteObjective(ObjectiveIndex, EventIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ClearAllActors()
|
||||||
|
{
|
||||||
|
AffectedActors.Remove(0, AffectedActors.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ClearActor(Actor Other)
|
||||||
|
{
|
||||||
|
AffectedActors.RemoveItem(Other);
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function bool IsObjectiveDataValid()
|
||||||
|
{
|
||||||
|
return ObjectiveIndex >= 0 && ObjectiveIndex < 5 && EventIndex > SEI_None && EventIndex < SEI_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
bIsDataValid = false;
|
||||||
|
}
|
87
KFGameContent/Classes/KFDT_Ballistic_G36C.uc
Normal file
87
KFGameContent/Classes/KFDT_Ballistic_G36C.uc
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Ballistic_G36C
|
||||||
|
//=============================================================================
|
||||||
|
// Class Description
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFDT_Ballistic_G36C extends KFDT_Ballistic_AssaultRifle
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
/** G36C has still to play a metal effect if impacting metal. (and we demoted to impact on Flesh) */
|
||||||
|
var ParticleSystem MetalImpactEffect;
|
||||||
|
var AkEvent MetalImpactSound;
|
||||||
|
|
||||||
|
static function PlayImpactHitEffects( KFPawn P, vector HitLocation, vector HitDirection, byte HitZoneIndex, optional Pawn HitInstigator )
|
||||||
|
{
|
||||||
|
local KFSkinTypeEffects SkinType, OriginalSkinType, FleshSkinType;
|
||||||
|
local int i;
|
||||||
|
|
||||||
|
if ( P.CharacterArch != None && default.EffectGroup < FXG_Max )
|
||||||
|
{
|
||||||
|
// Search if affected target has Flesh skin type
|
||||||
|
for (i = 0; i < P.CharacterArch.ImpactSkins.Length ; ++i)
|
||||||
|
{
|
||||||
|
if (P.CharacterArch.ImpactSkins[i].Name == 'Flesh'
|
||||||
|
|| P.CharacterArch.ImpactSkins[i].Name == 'Tough_Flesh')
|
||||||
|
{
|
||||||
|
FleshSkinType = P.CharacterArch.ImpactSkins[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SkinType = P.GetHitZoneSkinTypeEffects( HitZoneIndex );
|
||||||
|
OriginalSkinType = SkinType;
|
||||||
|
|
||||||
|
// If we don't hit flesh or shield, try to demote to Flesh
|
||||||
|
if (SkinType != none && SkinType.Name != 'Flesh' && SkinType.Name != 'Tough_Flesh' && SkinType.Name != 'ShieldEffects')
|
||||||
|
{
|
||||||
|
// We default to none as we don't want bullet to ricochet if any
|
||||||
|
SkinType = none;
|
||||||
|
|
||||||
|
// Demote to flesh skin hit
|
||||||
|
if (FleshSkinType != none)
|
||||||
|
{
|
||||||
|
SkinType = FleshSkinType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we hit metal we have to make sure we play it's Metal impact effect (this effect doesn't contain bullet ricochet) (don't play sound though!)
|
||||||
|
if (OriginalSkinType != none && (OriginalSkinType.Name == 'Metal' || OriginalSkinType.Name == 'Machine'))
|
||||||
|
{
|
||||||
|
OriginalSkinType.PlayImpactParticleEffect(P, HitLocation, HitDirection, HitZoneIndex, default.EffectGroup, default.MetalImpactEffect);
|
||||||
|
OriginalSkinType.PlayTakeHitSound(P, HitLocation, HitInstigator, default.EffectGroup, default.MetalImpactSound);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SkinType != none)
|
||||||
|
{
|
||||||
|
SkinType.PlayImpactParticleEffect(P, HitLocation, HitDirection, HitZoneIndex, default.EffectGroup);
|
||||||
|
SkinType.PlayTakeHitSound(P, HitLocation, HitInstigator, default.EffectGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
KDamageImpulse=900
|
||||||
|
KDeathUpKick=-300
|
||||||
|
KDeathVel=100
|
||||||
|
|
||||||
|
DamageModifierAP=0.8f
|
||||||
|
ArmorDamageModifier=15.0f
|
||||||
|
|
||||||
|
StumblePower=15
|
||||||
|
GunHitPower=15
|
||||||
|
|
||||||
|
WeaponDef=class'KFWeapDef_G36C'
|
||||||
|
|
||||||
|
//Perk
|
||||||
|
ModifierPerkList(0)=class'KFPerk_Swat'
|
||||||
|
|
||||||
|
MetalImpactEffect=ParticleSystem'FX_Impacts_EMIT.FX_Wep_Impact_MetalArmor_E'
|
||||||
|
MetalImpactSound=AkEvent'WW_Skin_Impacts.Play_Slashing_Metal_3P'
|
||||||
|
}
|
82
KFGameContent/Classes/KFDT_Ballistic_HRG_Dragonbreath.uc
Normal file
82
KFGameContent/Classes/KFDT_Ballistic_HRG_Dragonbreath.uc
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Ballistic_HRG_Dragonbreath
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFDT_Ballistic_HRG_Dragonbreath extends KFDT_Ballistic_Shotgun
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
// Damage type to use for the burning damage over time
|
||||||
|
var class<KFDamageType> BurnDamageType;
|
||||||
|
|
||||||
|
/** Allows the damage type to customize exactly which hit zones it can dismember */
|
||||||
|
static simulated function bool CanDismemberHitZone( name InHitZoneName )
|
||||||
|
{
|
||||||
|
if( super.CanDismemberHitZone( InHitZoneName ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( InHitZoneName )
|
||||||
|
{
|
||||||
|
case 'lupperarm':
|
||||||
|
case 'rupperarm':
|
||||||
|
case 'chest':
|
||||||
|
case 'heart':
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Play damage type specific impact effects when taking damage */
|
||||||
|
static function PlayImpactHitEffects( KFPawn P, vector HitLocation, vector HitDirection, byte HitZoneIndex, optional Pawn HitInstigator )
|
||||||
|
{
|
||||||
|
// Play burn effect when dead
|
||||||
|
if( P.bPlayedDeath && P.WorldInfo.TimeSeconds > P.TimeOfDeath )
|
||||||
|
{
|
||||||
|
default.BurnDamageType.static.PlayImpactHitEffects(P, HitLocation, HitDirection, HitZoneIndex, HitInstigator);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.PlayImpactHitEffects(P, HitLocation, HitDirection, HitZoneIndex, HitInstigator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called when damage is dealt to apply additional damage type (e.g. Damage Over Time) */
|
||||||
|
static function ApplySecondaryDamage( KFPawn Victim, int DamageTaken, optional Controller InstigatedBy )
|
||||||
|
{
|
||||||
|
// Overriden to specific a different damage type to do the burn damage over
|
||||||
|
// time. We do this so we don't get shotgun pellet impact sounds/fx during
|
||||||
|
// the DOT burning.
|
||||||
|
if ( default.BurnDamageType.default.DoT_Type != DOT_None )
|
||||||
|
{
|
||||||
|
Victim.ApplyDamageOverTime(DamageTaken, InstigatedBy, default.BurnDamageType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
GoreDamageGroup=DGT_Shotgun
|
||||||
|
BloodSpread=0.4
|
||||||
|
BloodScale=0.6
|
||||||
|
|
||||||
|
KDamageImpulse=3500
|
||||||
|
KDeathUpKick=800
|
||||||
|
KDeathVel=650
|
||||||
|
GibImpulseScale=1.0
|
||||||
|
|
||||||
|
BurnPower=40
|
||||||
|
StumblePower=40
|
||||||
|
GunHitPower=50
|
||||||
|
|
||||||
|
WeaponDef=class'KFWeapDef_HRG_Dragonbreath'
|
||||||
|
|
||||||
|
BurnDamageType=class'KFDT_Fire_HRG_DragonsBreathDoT'
|
||||||
|
|
||||||
|
EffectGroup=FXG_IncendiaryRound
|
||||||
|
|
||||||
|
ModifierPerkList(0)=class'KFPerk_Firebug'
|
||||||
|
}
|
18
KFGameContent/Classes/KFDT_Ballistic_HRG_Locust.uc
Normal file
18
KFGameContent/Classes/KFDT_Ballistic_HRG_Locust.uc
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Ballistic_HRG_Locust
|
||||||
|
//=============================================================================
|
||||||
|
// HRG Locust bullet impact
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
class KFDT_Ballistic_HRG_Locust extends KFDamageType
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
ModifierPerkList(0)=class'KFPerk_Survivalist'
|
||||||
|
|
||||||
|
WeaponDef=class'KFWeapDef_HRG_Locust'
|
||||||
|
}
|
16
KFGameContent/Classes/KFDT_Bludgeon_G36C.uc
Normal file
16
KFGameContent/Classes/KFDT_Bludgeon_G36C.uc
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Bludgeon_G36C
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFDT_Bludgeon_G36C extends KFDT_Bludgeon_RifleButt
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
//defaults
|
||||||
|
WeaponDef=class'KFWeapDef_G36C'
|
||||||
|
}
|
16
KFGameContent/Classes/KFDT_Bludgeon_HRG_Dragonbreath.uc
Normal file
16
KFGameContent/Classes/KFDT_Bludgeon_HRG_Dragonbreath.uc
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Bludgeon_HRG_Dragonbreath
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2017 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFDT_Bludgeon_HRG_Dragonbreath extends KFDT_Bludgeon_RifleButt
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
//defaults
|
||||||
|
WeaponDef=class'KFWeapDef_HRG_Dragonbreath'
|
||||||
|
}
|
15
KFGameContent/Classes/KFDT_Bludgeon_HRG_Locust.uc
Normal file
15
KFGameContent/Classes/KFDT_Bludgeon_HRG_Locust.uc
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Bludgeon_HRG_Locust
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
class KFDT_Bludgeon_HRG_Locust extends KFDT_Bludgeon_RifleButt
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
//defaults
|
||||||
|
WeaponDef=class'KFWeapDef_HRG_Locust'
|
||||||
|
}
|
40
KFGameContent/Classes/KFDT_Explosive_HRG_Locust.uc
Normal file
40
KFGameContent/Classes/KFDT_Explosive_HRG_Locust.uc
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Explosive_HRG_Locust
|
||||||
|
//=============================================================================
|
||||||
|
// Explosive damage type for the HRG Locust
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
class KFDT_Explosive_HRG_Locust extends KFDT_Explosive
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
// Damage type to use for the damage over time effect
|
||||||
|
var class<KFDamageType> DoTDamageType;
|
||||||
|
|
||||||
|
/** Called when damage is dealt to apply additional damage type (e.g. Damage Over Time) */
|
||||||
|
static function ApplySecondaryDamage(KFPawn Victim, int DamageTaken, optional Controller InstigatedBy)
|
||||||
|
{
|
||||||
|
if (Victim.Controller == InstigatedBy)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (default.DoTDamageType.default.DoT_Type != DOT_None)
|
||||||
|
{
|
||||||
|
Victim.ApplyDamageOverTime(DamageTaken, InstigatedBy, default.DoTDamageType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
//Perk
|
||||||
|
ModifierPerkList(0)=class'KFPerk_Survivalist'
|
||||||
|
WeaponDef=class'KFWeapDef_HRG_Locust'
|
||||||
|
|
||||||
|
DoTDamageType=class'KFDT_Toxic_HRG_Locust'
|
||||||
|
|
||||||
|
bCausesFracture=false
|
||||||
|
bCanPlayDeadHitEffects=false
|
||||||
|
}
|
39
KFGameContent/Classes/KFDT_Fire_Ground_HRG_DragonBreath.uc
Normal file
39
KFGameContent/Classes/KFDT_Fire_Ground_HRG_DragonBreath.uc
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Fire_Ground_HRG_DragonBreath
|
||||||
|
//=============================================================================
|
||||||
|
// Damage caused by burning from being hit by a HRG dragon breath ground fire
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFDT_Fire_Ground_HRG_DragonBreath extends KFDT_Fire_Ground
|
||||||
|
abstract;
|
||||||
|
|
||||||
|
static function int GetKillerDialogID()
|
||||||
|
{
|
||||||
|
return 86;//KILL_Fire
|
||||||
|
}
|
||||||
|
|
||||||
|
static function int GetDamagerDialogID()
|
||||||
|
{
|
||||||
|
return 102;//DAMZ_Fire
|
||||||
|
}
|
||||||
|
|
||||||
|
static function int GetDamageeDialogID()
|
||||||
|
{
|
||||||
|
return 116;//DAMP_Fire
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
WeaponDef=class'KFWeapDef_HRG_Dragonbreath'
|
||||||
|
|
||||||
|
DoT_Type=DOT_Fire
|
||||||
|
DoT_Duration=2.7
|
||||||
|
DoT_Interval=0.5
|
||||||
|
DoT_DamageScale=0.7
|
||||||
|
|
||||||
|
BurnPower=10
|
||||||
|
}
|
||||||
|
|
41
KFGameContent/Classes/KFDT_Fire_HRG_DragonsBreathDoT.uc
Normal file
41
KFGameContent/Classes/KFDT_Fire_HRG_DragonsBreathDoT.uc
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Fire_HRG_DragonsBreathDoT
|
||||||
|
//=============================================================================
|
||||||
|
// Damage caused by burning from being hit by an HRG dragon's breath round
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFDT_Fire_HRG_DragonsBreathDoT extends KFDT_Fire
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
static function int GetKillerDialogID()
|
||||||
|
{
|
||||||
|
return 86;//KILL_Fire
|
||||||
|
}
|
||||||
|
|
||||||
|
static function int GetDamagerDialogID()
|
||||||
|
{
|
||||||
|
return 102;//DAMZ_Fire
|
||||||
|
}
|
||||||
|
|
||||||
|
static function int GetDamageeDialogID()
|
||||||
|
{
|
||||||
|
return 116;//DAMP_Fire
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
WeaponDef=class'KFWeapDef_HRG_Dragonbreath'
|
||||||
|
|
||||||
|
DoT_Type=DOT_Fire
|
||||||
|
DoT_Duration=2.7 //5.0 //1.0
|
||||||
|
DoT_Interval=0.5
|
||||||
|
DoT_DamageScale=0.7 //1.0
|
||||||
|
|
||||||
|
BurnPower=10 //1.0 //18.5
|
||||||
|
}
|
||||||
|
|
23
KFGameContent/Classes/KFDT_Piercing_ScytheStab.uc
Normal file
23
KFGameContent/Classes/KFDT_Piercing_ScytheStab.uc
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Piercing_ScytheStab
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFDT_Piercing_ScytheStab extends KFDT_Piercing
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
KDamageImpulse=200
|
||||||
|
KDeathUpKick=250
|
||||||
|
|
||||||
|
StumblePower=50
|
||||||
|
MeleeHitPower=100
|
||||||
|
|
||||||
|
WeaponDef=class'KFWeapDef_Scythe'
|
||||||
|
|
||||||
|
ModifierPerkList(0)=class'KFPerk_Berserker'
|
||||||
|
}
|
23
KFGameContent/Classes/KFDT_Piercing_ScytheStabFolded.uc
Normal file
23
KFGameContent/Classes/KFDT_Piercing_ScytheStabFolded.uc
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Piercing_ScytheStabFolded
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFDT_Piercing_ScytheStabFolded extends KFDT_Piercing
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
KDamageImpulse=200
|
||||||
|
KDeathUpKick=250
|
||||||
|
|
||||||
|
StumblePower=50
|
||||||
|
MeleeHitPower=100
|
||||||
|
|
||||||
|
WeaponDef=class'KFWeapDef_Scythe'
|
||||||
|
|
||||||
|
ModifierPerkList(0)=class'KFPerk_Berserker'
|
||||||
|
}
|
140
KFGameContent/Classes/KFDT_Slashing_ScytheLong.uc
Normal file
140
KFGameContent/Classes/KFDT_Slashing_ScytheLong.uc
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Slashing_ScytheLong
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFDT_Slashing_ScytheLong extends KFDT_Slashing
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
/** Allows the damage type to customize exactly which hit zones it can dismember */
|
||||||
|
static simulated function bool CanDismemberHitZone( name InHitZoneName )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Allows the damage type to map a hit zone to a different bone for dismemberment purposes */
|
||||||
|
static simulated function GetBoneToDismember(KFPawn_Monster InPawn, vector HitDirection, name InHitZoneName, out name OutBoneName)
|
||||||
|
{
|
||||||
|
local EPawnOctant SlashDir;
|
||||||
|
local KFCharacterInfo_Monster MonsterInfo;
|
||||||
|
|
||||||
|
MonsterInfo = InPawn.GetCharacterMonsterInfo();
|
||||||
|
if ( MonsterInfo == none )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SlashDir = GetLastSlashDirection(InPawn, HitDirection);
|
||||||
|
|
||||||
|
if( SlashDir == DIR_Forward || SlashDir == DIR_Backward )
|
||||||
|
{
|
||||||
|
if( InHitZoneName == 'chest' || InHitZoneName == 'head' )
|
||||||
|
{
|
||||||
|
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
|
||||||
|
{
|
||||||
|
// Randomly pick the left or right shoulder bone and split the guy in half vertically
|
||||||
|
OutBoneName = Rand(2) == 0
|
||||||
|
? MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName
|
||||||
|
: MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( SlashDir == DIR_Left || SlashDir == DIR_Right )
|
||||||
|
{
|
||||||
|
if( InHitZoneName == 'chest' || InHitZoneName == 'abdomen' || InHitZoneName == 'stomach' )
|
||||||
|
{
|
||||||
|
if( MonsterInfo.SpecialMeleeDismemberment.bAllowHorizontalSplit )
|
||||||
|
{
|
||||||
|
// Split the guy in half horizontally
|
||||||
|
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.SpineBoneName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( SlashDir == DIR_ForwardLeft || SlashDir == DIR_BackwardRight )
|
||||||
|
{
|
||||||
|
if( InHitZoneName == 'chest' )
|
||||||
|
{
|
||||||
|
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
|
||||||
|
{
|
||||||
|
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( InHitZoneName == 'head' )
|
||||||
|
{
|
||||||
|
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
|
||||||
|
{
|
||||||
|
// Use a random chance to decide whether to dismember the head or the shoulder constraints
|
||||||
|
if( Rand(2) == 0 )
|
||||||
|
{
|
||||||
|
// ... and choose one of the shoulder constraints at random
|
||||||
|
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( SlashDir == DIR_ForwardRight || SlashDir == DIR_BackwardLeft )
|
||||||
|
{
|
||||||
|
if( InHitZoneName == 'chest' )
|
||||||
|
{
|
||||||
|
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
|
||||||
|
{
|
||||||
|
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( InHitZoneName == 'head' )
|
||||||
|
{
|
||||||
|
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
|
||||||
|
{
|
||||||
|
// Use a random chance to decide whether to dismember the head or the shoulder constraints
|
||||||
|
if( Rand(2) == 0 )
|
||||||
|
{
|
||||||
|
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Allows the damage type to modify the impulse when a specified hit zone is dismembered */
|
||||||
|
static simulated function ModifyDismembermentHitImpulse(KFPawn_Monster InPawn, name InHitZoneName, vector HitDirection,
|
||||||
|
out vector OutImpulseDir, out vector OutParentImpulseDir,
|
||||||
|
out float OutImpulseScale, out float OutParentImpulseScale)
|
||||||
|
{
|
||||||
|
local EPawnOctant SlashDir;
|
||||||
|
|
||||||
|
SlashDir = GetLastSlashDirection(InPawn, HitDirection);
|
||||||
|
|
||||||
|
// Apply upward impulse on decapitation from a clean horizontal slash
|
||||||
|
if( InHitZoneName == 'head' &&
|
||||||
|
( SlashDir == DIR_Left || SlashDir == DIR_Right ) )
|
||||||
|
{
|
||||||
|
OutImpulseDir += 10*vect(0,0,1);
|
||||||
|
OutImpulseDir = Normal(OutImpulseDir);
|
||||||
|
OutParentImpulseScale = 0.f;
|
||||||
|
}
|
||||||
|
// Do not apply any impulse on split in half from a vertical slash
|
||||||
|
else if( (InHitZoneName == 'head' || InHitZoneName == 'chest' ) &&
|
||||||
|
( SlashDir == DIR_Forward || SlashDir == DIR_Backward) )
|
||||||
|
{
|
||||||
|
OutImpulseScale = 0.f;
|
||||||
|
OutParentImpulseScale = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
KDamageImpulse=10000 //1500
|
||||||
|
KDeathUpKick=2000 //200
|
||||||
|
KDeathVel=3750 //375
|
||||||
|
|
||||||
|
KnockdownPower=0
|
||||||
|
StunPower=0
|
||||||
|
StumblePower=100
|
||||||
|
MeleeHitPower=100
|
||||||
|
|
||||||
|
WeaponDef=class'KFWeapDef_Scythe'
|
||||||
|
ModifierPerkList(0)=class'KFPerk_Berserker'
|
||||||
|
}
|
38
KFGameContent/Classes/KFDT_Slashing_ScytheLongAlt.uc
Normal file
38
KFGameContent/Classes/KFDT_Slashing_ScytheLongAlt.uc
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Slashing_ScytheLongAlt
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFDT_Slashing_ScytheLongAlt extends KFDT_Slashing_ZweihanderHeavy
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
KDamageImpulse=3600 //1600
|
||||||
|
KDeathUpKick=400 //200
|
||||||
|
KDeathVel=750 //500
|
||||||
|
|
||||||
|
KnockdownPower=50
|
||||||
|
StunPower=0
|
||||||
|
StumblePower=200
|
||||||
|
MeleeHitPower=100
|
||||||
|
|
||||||
|
// Obliteration
|
||||||
|
GoreDamageGroup = DGT_Explosive
|
||||||
|
RadialDamageImpulse = 8000.f // This controls how much impulse is applied to gibs when exploding
|
||||||
|
bUseHitLocationForGibImpulses = true // This will make the impulse origin where the victim was hit for directional gibs
|
||||||
|
bPointImpulseTowardsOrigin = true // This creates an impulse direction aligned along hitlocation and pawn location -- this will push all gibs in the same direction
|
||||||
|
ImpulseOriginScale = 100.f // Higher means more directional gibbing, lower means more outward (and upward) gibbing
|
||||||
|
ImpulseOriginLift = 150.f
|
||||||
|
MaxObliterationGibs = 12 // Maximum number of gibs that can be spawned by obliteration, 0=MAX
|
||||||
|
bCanGib = true
|
||||||
|
bCanObliterate = true
|
||||||
|
ObliterationHealthThreshold = 0
|
||||||
|
ObliterationDamageThreshold = 100
|
||||||
|
|
||||||
|
WeaponDef=class'KFWeapDef_Scythe'
|
||||||
|
ModifierPerkList(0)=class'KFPerk_Berserker'
|
||||||
|
}
|
140
KFGameContent/Classes/KFDT_Slashing_ScytheShort.uc
Normal file
140
KFGameContent/Classes/KFDT_Slashing_ScytheShort.uc
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Slashing_ScytheShort
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFDT_Slashing_ScytheShort extends KFDT_Slashing
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
/** Allows the damage type to customize exactly which hit zones it can dismember */
|
||||||
|
static simulated function bool CanDismemberHitZone( name InHitZoneName )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Allows the damage type to map a hit zone to a different bone for dismemberment purposes */
|
||||||
|
static simulated function GetBoneToDismember(KFPawn_Monster InPawn, vector HitDirection, name InHitZoneName, out name OutBoneName)
|
||||||
|
{
|
||||||
|
local EPawnOctant SlashDir;
|
||||||
|
local KFCharacterInfo_Monster MonsterInfo;
|
||||||
|
|
||||||
|
MonsterInfo = InPawn.GetCharacterMonsterInfo();
|
||||||
|
if ( MonsterInfo == none )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SlashDir = GetLastSlashDirection(InPawn, HitDirection);
|
||||||
|
|
||||||
|
if( SlashDir == DIR_Forward || SlashDir == DIR_Backward )
|
||||||
|
{
|
||||||
|
if( InHitZoneName == 'chest' || InHitZoneName == 'head' )
|
||||||
|
{
|
||||||
|
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
|
||||||
|
{
|
||||||
|
// Randomly pick the left or right shoulder bone and split the guy in half vertically
|
||||||
|
OutBoneName = Rand(2) == 0
|
||||||
|
? MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName
|
||||||
|
: MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( SlashDir == DIR_Left || SlashDir == DIR_Right )
|
||||||
|
{
|
||||||
|
if( InHitZoneName == 'chest' || InHitZoneName == 'abdomen' || InHitZoneName == 'stomach' )
|
||||||
|
{
|
||||||
|
if( MonsterInfo.SpecialMeleeDismemberment.bAllowHorizontalSplit )
|
||||||
|
{
|
||||||
|
// Split the guy in half horizontally
|
||||||
|
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.SpineBoneName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( SlashDir == DIR_ForwardLeft || SlashDir == DIR_BackwardRight )
|
||||||
|
{
|
||||||
|
if( InHitZoneName == 'chest' )
|
||||||
|
{
|
||||||
|
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
|
||||||
|
{
|
||||||
|
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( InHitZoneName == 'head' )
|
||||||
|
{
|
||||||
|
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
|
||||||
|
{
|
||||||
|
// Use a random chance to decide whether to dismember the head or the shoulder constraints
|
||||||
|
if( Rand(2) == 0 )
|
||||||
|
{
|
||||||
|
// ... and choose one of the shoulder constraints at random
|
||||||
|
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( SlashDir == DIR_ForwardRight || SlashDir == DIR_BackwardLeft )
|
||||||
|
{
|
||||||
|
if( InHitZoneName == 'chest' )
|
||||||
|
{
|
||||||
|
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
|
||||||
|
{
|
||||||
|
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( InHitZoneName == 'head' )
|
||||||
|
{
|
||||||
|
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
|
||||||
|
{
|
||||||
|
// Use a random chance to decide whether to dismember the head or the shoulder constraints
|
||||||
|
if( Rand(2) == 0 )
|
||||||
|
{
|
||||||
|
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Allows the damage type to modify the impulse when a specified hit zone is dismembered */
|
||||||
|
static simulated function ModifyDismembermentHitImpulse(KFPawn_Monster InPawn, name InHitZoneName, vector HitDirection,
|
||||||
|
out vector OutImpulseDir, out vector OutParentImpulseDir,
|
||||||
|
out float OutImpulseScale, out float OutParentImpulseScale)
|
||||||
|
{
|
||||||
|
local EPawnOctant SlashDir;
|
||||||
|
|
||||||
|
SlashDir = GetLastSlashDirection(InPawn, HitDirection);
|
||||||
|
|
||||||
|
// Apply upward impulse on decapitation from a clean horizontal slash
|
||||||
|
if( InHitZoneName == 'head' &&
|
||||||
|
( SlashDir == DIR_Left || SlashDir == DIR_Right ) )
|
||||||
|
{
|
||||||
|
OutImpulseDir += 10*vect(0,0,1);
|
||||||
|
OutImpulseDir = Normal(OutImpulseDir);
|
||||||
|
OutParentImpulseScale = 0.f;
|
||||||
|
}
|
||||||
|
// Do not apply any impulse on split in half from a vertical slash
|
||||||
|
else if( (InHitZoneName == 'head' || InHitZoneName == 'chest' ) &&
|
||||||
|
( SlashDir == DIR_Forward || SlashDir == DIR_Backward) )
|
||||||
|
{
|
||||||
|
OutImpulseScale = 0.f;
|
||||||
|
OutParentImpulseScale = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
KDamageImpulse=10000 //1500
|
||||||
|
KDeathUpKick=2000 //200
|
||||||
|
KDeathVel=3750 //375
|
||||||
|
|
||||||
|
KnockdownPower=0
|
||||||
|
StunPower=0
|
||||||
|
StumblePower=50
|
||||||
|
MeleeHitPower=100
|
||||||
|
|
||||||
|
WeaponDef=class'KFWeapDef_Scythe'
|
||||||
|
ModifierPerkList(0)=class'KFPerk_Berserker'
|
||||||
|
}
|
38
KFGameContent/Classes/KFDT_Slashing_ScytheShortAlt.uc
Normal file
38
KFGameContent/Classes/KFDT_Slashing_ScytheShortAlt.uc
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFDT_Slashing_ScytheShortAlt
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFDT_Slashing_ScytheShortAlt extends KFDT_Slashing_ZweihanderHeavy
|
||||||
|
abstract
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
KDamageImpulse=3600 //1600
|
||||||
|
KDeathUpKick=400 //200
|
||||||
|
KDeathVel=750 //500
|
||||||
|
|
||||||
|
KnockdownPower=0
|
||||||
|
StunPower=0
|
||||||
|
StumblePower=150
|
||||||
|
MeleeHitPower=100
|
||||||
|
|
||||||
|
// Obliteration
|
||||||
|
GoreDamageGroup = DGT_Explosive
|
||||||
|
RadialDamageImpulse = 8000.f // This controls how much impulse is applied to gibs when exploding
|
||||||
|
bUseHitLocationForGibImpulses = true // This will make the impulse origin where the victim was hit for directional gibs
|
||||||
|
bPointImpulseTowardsOrigin = true // This creates an impulse direction aligned along hitlocation and pawn location -- this will push all gibs in the same direction
|
||||||
|
ImpulseOriginScale = 100.f // Higher means more directional gibbing, lower means more outward (and upward) gibbing
|
||||||
|
ImpulseOriginLift = 150.f
|
||||||
|
MaxObliterationGibs = 12 // Maximum number of gibs that can be spawned by obliteration, 0=MAX
|
||||||
|
bCanGib = true
|
||||||
|
bCanObliterate = true
|
||||||
|
ObliterationHealthThreshold = 0
|
||||||
|
ObliterationDamageThreshold = 100
|
||||||
|
|
||||||
|
WeaponDef=class'KFWeapDef_Scythe'
|
||||||
|
ModifierPerkList(0)=class'KFPerk_Berserker'
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFExplosion_HRG_Dragonbreath_GroundFire
|
||||||
|
//=============================================================================
|
||||||
|
// Explosion actor class for ground fire
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFExplosion_HRG_Dragonbreath_GroundFire extends KFExplosionActorLingering;
|
||||||
|
|
||||||
|
|
||||||
|
simulated function SpawnExplosionParticleSystem(ParticleSystem Template)
|
||||||
|
{
|
||||||
|
// If the template is none, grab the default
|
||||||
|
if( !ExplosionTemplate.bAllowPerMaterialFX && Template == none )
|
||||||
|
{
|
||||||
|
Template = KFGameExplosion(ExplosionTemplate).ExplosionEffects.DefaultImpactEffect.ParticleTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use custom pool
|
||||||
|
WorldInfo.GroundFireEmitterPool.SpawnEmitter(Template, Location, rotator(ExplosionTemplate.HitNormal), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
//Interval=0.25f INTERVAL IS OVERRIDDEN BY ITS PROJECTILE
|
||||||
|
MaxTime=2.0
|
||||||
|
|
||||||
|
ExplosionLightPriority=LPP_Low
|
||||||
|
LoopStartEvent=AkEvent'ww_wep_hrg_megadragonbreath.Play_WEP_HRG_MegaDragonbreath_Flame_LP'
|
||||||
|
LoopStopEvent=AkEvent'ww_wep_hrg_megadragonbreath.Stop_WEP_HRG_MegaDragonbreath_End_Flame_LP'
|
||||||
|
}
|
22
KFGameContent/Classes/KFExplosion_HRG_Locust.uc
Normal file
22
KFGameContent/Classes/KFExplosion_HRG_Locust.uc
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFExplosion_HRG_Locust
|
||||||
|
//=============================================================================
|
||||||
|
// Explosion actor class for HRG Locust
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFExplosion_HRG_Locust extends KFExplosionActorLingering;
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
Interval=0.5f
|
||||||
|
MaxTime=3.0
|
||||||
|
|
||||||
|
bOnlyDamagePawns=true
|
||||||
|
bDoFullDamage=false
|
||||||
|
|
||||||
|
LoopStartEvent=AkEvent'WW_WEP_HRG_Locust.Play_WEP_HRG_Locust_Insects'
|
||||||
|
LoopStopEvent=AkEvent'WW_WEP_HRG_Locust.Stop_WEP_HRG_Locust_Insect'
|
||||||
|
}
|
25
KFGameContent/Classes/KFProj_HRG_Dragonbreath_Splash.uc
Normal file
25
KFGameContent/Classes/KFProj_HRG_Dragonbreath_Splash.uc
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFProj_HRG_DragonBreath_Splash
|
||||||
|
//=============================================================================
|
||||||
|
// Projectile class for hrg dragonbreath gun splash. Handles a few overrides.
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFProj_HRG_DragonBreath_Splash extends KFProj_FlareGunSplash;
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
PostExplosionLifetime=2.5
|
||||||
|
ExplosionActorClass=class'KFExplosion_HRG_Dragonbreath_GroundFire'
|
||||||
|
|
||||||
|
Begin Object Name=ExploTemplate0
|
||||||
|
Damage=8
|
||||||
|
DamageRadius=150.0
|
||||||
|
MyDamageType=class'KFDT_Fire_Ground_HRG_DragonBreath'
|
||||||
|
ExplosionEffects=KFImpactEffectInfo'WEP_Flamethrower_ARCH.GroundFire_Impacts'
|
||||||
|
End Object
|
||||||
|
|
||||||
|
AssociatedPerkClass=none
|
||||||
|
}
|
171
KFGameContent/Classes/KFProj_HRG_Locust.uc
Normal file
171
KFGameContent/Classes/KFProj_HRG_Locust.uc
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFProj_HRG_Locust
|
||||||
|
//=============================================================================
|
||||||
|
// HRG Locust projectile
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
class KFProj_HRG_Locust extends KFProj_BallisticExplosive
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
/** Our intended target actor */
|
||||||
|
var private KFPawn LockedTarget;
|
||||||
|
|
||||||
|
/** How much 'stickyness' when seeking toward our target. Determines how accurate rocket is */
|
||||||
|
var const float SeekStrength;
|
||||||
|
|
||||||
|
replication
|
||||||
|
{
|
||||||
|
if( bNetInitial )
|
||||||
|
LockedTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
function SetLockedTarget( KFPawn NewTarget )
|
||||||
|
{
|
||||||
|
LockedTarget = NewTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function bool AllowNuke()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function bool AllowDemolitionistConcussive()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function bool AllowDemolitionistExplosionChangeRadius()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated event Tick( float DeltaTime )
|
||||||
|
{
|
||||||
|
local vector TargetImpactPos, DirToTarget;
|
||||||
|
|
||||||
|
super.Tick( DeltaTime );
|
||||||
|
|
||||||
|
// Skip the first frame, then start seeking
|
||||||
|
if( !bHasExploded
|
||||||
|
&& LockedTarget != none
|
||||||
|
&& Physics == PHYS_Projectile
|
||||||
|
&& Velocity != vect(0,0,0)
|
||||||
|
&& LockedTarget.IsAliveAndWell()
|
||||||
|
&& `TimeSince(CreationTime) > 0.03f )
|
||||||
|
{
|
||||||
|
// Grab our desired relative impact location from the weapon class
|
||||||
|
TargetImpactPos = class'KFWeap_HRG_Locust'.static.GetLockedTargetLoc( LockedTarget );
|
||||||
|
|
||||||
|
// Seek towards target
|
||||||
|
Speed = VSize( Velocity );
|
||||||
|
DirToTarget = Normal( TargetImpactPos - Location );
|
||||||
|
Velocity = Normal( Velocity + (DirToTarget * (SeekStrength * DeltaTime)) ) * Speed;
|
||||||
|
|
||||||
|
// Aim rotation towards velocity every frame
|
||||||
|
SetRotation( rotator(Velocity) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated protected function PrepareExplosionTemplate()
|
||||||
|
{
|
||||||
|
local Weapon OwnerWeapon;
|
||||||
|
local Pawn OwnerPawn;
|
||||||
|
local KFPerk_Survivalist Perk;
|
||||||
|
|
||||||
|
super(KFProjectile).PrepareExplosionTemplate();
|
||||||
|
|
||||||
|
OwnerWeapon = Weapon(Owner);
|
||||||
|
if (OwnerWeapon != none)
|
||||||
|
{
|
||||||
|
OwnerPawn = Pawn(OwnerWeapon.Owner);
|
||||||
|
if (OwnerPawn != none)
|
||||||
|
{
|
||||||
|
Perk = KFPerk_Survivalist(KFPawn(OwnerPawn).GetPerk());
|
||||||
|
if (Perk != none)
|
||||||
|
{
|
||||||
|
ExplosionTemplate.DamageRadius *= KFPawn(OwnerPawn).GetPerk().GetAoERadiusModifier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
Physics=PHYS_Projectile
|
||||||
|
Speed=4000 //6000
|
||||||
|
MaxSpeed=4000 //6000
|
||||||
|
TossZ=0
|
||||||
|
GravityScale=1.0
|
||||||
|
MomentumTransfer=0.0f
|
||||||
|
|
||||||
|
Damage=10
|
||||||
|
DamageRadius=0
|
||||||
|
|
||||||
|
SeekStrength=928000.0f // 128000.0f
|
||||||
|
|
||||||
|
bWarnAIWhenFired=true
|
||||||
|
|
||||||
|
ProjFlightTemplate=ParticleSystem'WEP_HRG_Locust_EMIT.FX_HRG_Locust_Projectile'
|
||||||
|
ProjFlightTemplateZedTime=ParticleSystem'WEP_HRG_Locust_EMIT.FX_HRG_Locust_Projectile_ZED_TIME'
|
||||||
|
ProjDisintegrateTemplate=ParticleSystem'WEP_HRG_Locust_EMIT.FX_Flying_Bugs_dispersion'
|
||||||
|
|
||||||
|
AmbientSoundPlayEvent=AkEvent'WW_WEP_Seeker_6.Play_WEP_Seeker_6_Projectile'
|
||||||
|
AmbientSoundStopEvent=AkEvent'WW_WEP_Seeker_6.Stop_WEP_Seeker_6_Projectile'
|
||||||
|
|
||||||
|
ExplosionActorClass=class'KFExplosion_HRG_Locust'
|
||||||
|
|
||||||
|
AltExploEffects=KFImpactEffectInfo'WEP_HRG_Locust_ARCH.FX_HRG_Locust_Explosion_Concussive_force'
|
||||||
|
|
||||||
|
// Grenade explosion light
|
||||||
|
Begin Object Class=PointLightComponent Name=ExplosionPointLight
|
||||||
|
LightColor=(R=252,G=218,B=171,A=255)
|
||||||
|
Brightness=4.f
|
||||||
|
Radius=2000.f
|
||||||
|
FalloffExponent=10.f
|
||||||
|
CastShadows=False
|
||||||
|
CastStaticShadows=FALSE
|
||||||
|
CastDynamicShadows=False
|
||||||
|
bCastPerObjectShadows=false
|
||||||
|
bEnabled=FALSE
|
||||||
|
LightingChannels=(Indoor=TRUE,Outdoor=TRUE,bInitialized=TRUE)
|
||||||
|
End Object
|
||||||
|
|
||||||
|
// explosion
|
||||||
|
Begin Object Class=KFGameExplosion Name=ExploTemplate0
|
||||||
|
Damage=60
|
||||||
|
DamageRadius=200
|
||||||
|
DamageFalloffExponent=0.5f
|
||||||
|
DamageDelay=0.f
|
||||||
|
|
||||||
|
//Impulse applied to Zeds
|
||||||
|
MomentumTransferScale=1
|
||||||
|
|
||||||
|
// Damage Effects
|
||||||
|
MyDamageType=class'KFDT_Explosive_HRG_Locust'
|
||||||
|
KnockDownStrength=0
|
||||||
|
FractureMeshRadius=0.0
|
||||||
|
FracturePartVel=0.0
|
||||||
|
ExplosionEffects=KFImpactEffectInfo'WEP_HRG_Locust_ARCH.FX_HRG_Locust_Explosion_Concussive_force'
|
||||||
|
ExplosionSound=AkEvent'WW_WEP_Seeker_6.Play_WEP_Seeker_6_Explosion'
|
||||||
|
|
||||||
|
// Dynamic Light
|
||||||
|
ExploLight=ExplosionPointLight
|
||||||
|
ExploLightStartFadeOutTime=0.0
|
||||||
|
ExploLightFadeOutTime=0.2
|
||||||
|
|
||||||
|
// Camera Shake
|
||||||
|
CamShake=CameraShake'FX_CameraShake_Arch.Misc_Explosions.Light_Explosion_Rumble'
|
||||||
|
CamShakeInnerRadius=0
|
||||||
|
CamShakeOuterRadius=500
|
||||||
|
CamShakeFalloff=3.f
|
||||||
|
bOrientCameraShakeTowardsEpicenter=true
|
||||||
|
|
||||||
|
bIgnoreInstigator=true
|
||||||
|
End Object
|
||||||
|
ExplosionTemplate=ExploTemplate0
|
||||||
|
|
||||||
|
bCanDisintegrate=false
|
||||||
|
}
|
85
KFGameContent/Classes/KFProj_Pellet_HRG_Dragonbreath.uc
Normal file
85
KFGameContent/Classes/KFProj_Pellet_HRG_Dragonbreath.uc
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFProj_Pellet_HRG_Dragonbreath
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFProj_Pellet_HRG_Dragonbreath extends KFProj_Bullet_Pellet
|
||||||
|
hidedropdown;
|
||||||
|
|
||||||
|
|
||||||
|
/** Last hit normal from Touch() or HitWall() */
|
||||||
|
var vector LastHitNormal;
|
||||||
|
|
||||||
|
var float GroundFireChance;
|
||||||
|
|
||||||
|
|
||||||
|
simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal)
|
||||||
|
{
|
||||||
|
LastHitNormal = HitNormal;
|
||||||
|
Super.ProcessTouch(Other, HitLocation, HitNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Explode this Projectile
|
||||||
|
*/
|
||||||
|
simulated function TriggerExplosion(Vector HitLocation, Vector HitNormal, Actor HitActor)
|
||||||
|
{
|
||||||
|
LastHitNormal = HitNormal;
|
||||||
|
Super.TriggerExplosion(HitLocation, HitNormal, HitActor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
simulated protected function StopSimulating()
|
||||||
|
{
|
||||||
|
local vector FlameSpawnVel;
|
||||||
|
|
||||||
|
if (Role == ROLE_Authority && Physics == PHYS_Falling && FRand() < GroundFireChance)
|
||||||
|
{
|
||||||
|
//SpawnGroundFire();
|
||||||
|
FlameSpawnVel = 0.25f * CalculateResidualFlameVelocity(LastHitNormal, Normal(Velocity), VSize(Velocity));
|
||||||
|
SpawnResidualFlame(class'KFProj_HRG_DragonBreath_Splash', Location + (LastHitNormal * 10.f), FlameSpawnVel);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.StopSimulating();
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
GroundFireChance=1.f
|
||||||
|
Physics=PHYS_Falling
|
||||||
|
|
||||||
|
MaxSpeed=7000.0
|
||||||
|
Speed=7000.0
|
||||||
|
TerminalVelocity=7000.0
|
||||||
|
|
||||||
|
bWarnAIWhenFired=true
|
||||||
|
|
||||||
|
DamageRadius=0
|
||||||
|
GravityScale=0.35
|
||||||
|
TossZ=0
|
||||||
|
|
||||||
|
Begin Object Class=PointLightComponent Name=PointLight0
|
||||||
|
LightColor=(R=252,G=218,B=171,A=255)
|
||||||
|
Brightness=0.5f
|
||||||
|
Radius=500.f
|
||||||
|
FalloffExponent=10.f
|
||||||
|
CastShadows=False
|
||||||
|
CastStaticShadows=FALSE
|
||||||
|
CastDynamicShadows=False
|
||||||
|
bCastPerObjectShadows=false
|
||||||
|
bEnabled=true
|
||||||
|
LightingChannels=(Indoor=TRUE,Outdoor=TRUE,bInitialized=TRUE)
|
||||||
|
End Object
|
||||||
|
ProjFlightLight=PointLight0
|
||||||
|
|
||||||
|
ImpactEffects=KFImpactEffectInfo'WEP_DragonsBreath_ARCH.DragonsBreath_bullet_impact'
|
||||||
|
ProjFlightTemplate=ParticleSystem'WEP_DragonsBreath_EMIT.Tracer.FX_DragonsBreath_Tracer'
|
||||||
|
ProjFlightTemplateZedTime=ParticleSystem'WEP_DragonsBreath_EMIT.Tracer.FX_DragonsBreath_Tracer_ZEDTime'
|
||||||
|
|
||||||
|
AmbientSoundPlayEvent=AkEvent'WW_WEP_SA_DragonsBreath.Play_SA_DragonsBreath_Projectile_Loop'
|
||||||
|
AmbientSoundStopEvent=AkEvent'WW_WEP_SA_DragonsBreath.Stop_SA_DragonsBreath_Projectile_Loop'
|
||||||
|
}
|
||||||
|
|
128
KFGameContent/Classes/KFSeasonalEventStats_Fall2022.uc
Normal file
128
KFGameContent/Classes/KFSeasonalEventStats_Fall2022.uc
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFSeasonalEventStats_Fall2022
|
||||||
|
//=============================================================================
|
||||||
|
// Tracks event-specific challenges/accomplishments for Fall 2022
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2021 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
class KFSeasonalEventStats_Fall2022 extends KFSeasonalEventStats;
|
||||||
|
|
||||||
|
var transient private const int BossKillsRequired, ZedsInBonfiresRequired, EndlessWaveRequired;
|
||||||
|
|
||||||
|
private event Initialize(string MapName)
|
||||||
|
{
|
||||||
|
local string CapsMapName;
|
||||||
|
CapsMapName = Caps(MapName);
|
||||||
|
|
||||||
|
bObjectiveIsValidForMap[0] = 1; // Kill 15 Bosses on any map or mode
|
||||||
|
bObjectiveIsValidForMap[1] = 0; // Complete the Weekly on BarmwichTown
|
||||||
|
bObjectiveIsValidForMap[2] = 0; // Open the Weapon Room
|
||||||
|
bObjectiveIsValidForMap[3] = 0; // Make 50 Zeds to pass through the bonfires of Barmwitch Town
|
||||||
|
bObjectiveIsValidForMap[4] = 0; // Complete wave 15 on Endless Hard or higher difficulty on Barmwitch Town
|
||||||
|
|
||||||
|
if (CapsMapName == "KF-BARMWICHTOWN")
|
||||||
|
{
|
||||||
|
bObjectiveIsValidForMap[1] = 1;
|
||||||
|
bObjectiveIsValidForMap[2] = 1;
|
||||||
|
bObjectiveIsValidForMap[3] = 1;
|
||||||
|
bObjectiveIsValidForMap[4] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetSeasonalEventStatsMax(BossKillsRequired, 0, 0, ZedsInBonfiresRequired, EndlessWaveRequired);
|
||||||
|
}
|
||||||
|
|
||||||
|
private event GrantEventItems()
|
||||||
|
{
|
||||||
|
if (Outer.IsEventObjectiveComplete(0) &&
|
||||||
|
Outer.IsEventObjectiveComplete(1) &&
|
||||||
|
Outer.IsEventObjectiveComplete(2) &&
|
||||||
|
Outer.IsEventObjectiveComplete(3) &&
|
||||||
|
Outer.IsEventObjectiveComplete(4))
|
||||||
|
{
|
||||||
|
GrantEventItem(9424);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kill 15 Bosses on any map or mode
|
||||||
|
simulated function OnBossDied()
|
||||||
|
{
|
||||||
|
local int ObjIdx;
|
||||||
|
ObjIdx = 0;
|
||||||
|
|
||||||
|
// Boss kills in any map
|
||||||
|
if (bObjectiveIsValidForMap[ObjIdx] != 0)
|
||||||
|
{
|
||||||
|
IncrementSeasonalEventStat(ObjIdx, 1);
|
||||||
|
if (Outer.GetSeasonalEventStatValue(ObjIdx) >= BossKillsRequired)
|
||||||
|
{
|
||||||
|
FinishedObjective(SEI_Fall, ObjIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complete the Weekly on Netherhold
|
||||||
|
simulated event OnGameWon(class<GameInfo> GameClass, int Difficulty, int GameLength, bool bCoOp)
|
||||||
|
{
|
||||||
|
local int ObjIdx;
|
||||||
|
ObjIdx = 1;
|
||||||
|
|
||||||
|
if (bObjectiveIsValidForMap[ObjIdx] != 0)
|
||||||
|
{
|
||||||
|
if (GameClass == class'KFGameInfo_WeeklySurvival')
|
||||||
|
{
|
||||||
|
FinishedObjective(SEI_Fall, ObjIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complete wave 15 on Endless Hard or higher difficulty on Netherhold
|
||||||
|
simulated event OnWaveCompleted(class<GameInfo> GameClass, int Difficulty, int WaveNum)
|
||||||
|
{
|
||||||
|
local int ObjIdx;
|
||||||
|
ObjIdx = 4;
|
||||||
|
|
||||||
|
if (bObjectiveIsValidForMap[ObjIdx] != 0)
|
||||||
|
{
|
||||||
|
if (WaveNum >= EndlessWaveRequired && GameClass == class'KFGameInfo_Endless' && Difficulty >= `DIFFICULTY_HARD)
|
||||||
|
{
|
||||||
|
FinishedObjective(SEI_Fall, ObjIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function OnTryCompleteObjective(int ObjectiveIndex, int EventIndex)
|
||||||
|
{
|
||||||
|
local int WeaponRoomIdx, BonfireIdx;
|
||||||
|
WeaponRoomIdx = 2;
|
||||||
|
BonfireIdx = 3;
|
||||||
|
|
||||||
|
if(EventIndex == SEI_Fall)
|
||||||
|
{
|
||||||
|
if (ObjectiveIndex == WeaponRoomIdx)
|
||||||
|
{
|
||||||
|
if (bObjectiveIsValidForMap[ObjectiveIndex] != 0)
|
||||||
|
{
|
||||||
|
FinishedObjective(SEI_Fall, ObjectiveIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ObjectiveIndex == BonfireIdx)
|
||||||
|
{
|
||||||
|
if (bObjectiveIsValidForMap[ObjectiveIndex] != 0)
|
||||||
|
{
|
||||||
|
IncrementSeasonalEventStat(ObjectiveIndex, 1);
|
||||||
|
if (Outer.GetSeasonalEventStatValue(ObjectiveIndex) >= ZedsInBonfiresRequired)
|
||||||
|
{
|
||||||
|
FinishedObjective(SEI_Fall, ObjectiveIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
BossKillsRequired=15
|
||||||
|
EndlessWaveRequired=15
|
||||||
|
ZedsInBonfiresRequired=50
|
||||||
|
}
|
83
KFGameContent/Classes/KFWeapAttach_HRG_Dragonbreath.uc
Normal file
83
KFGameContent/Classes/KFWeapAttach_HRG_Dragonbreath.uc
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFWeapAttach_HRG_Dragonbreath
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFWeapAttach_HRG_Dragonbreath extends KFWeaponAttachment;
|
||||||
|
|
||||||
|
`define HRGDRAGONBREATH_MIC_BARREL_INDEX 0
|
||||||
|
|
||||||
|
var transient float BarrelHeatPerProjectile;
|
||||||
|
var transient float MaxBarrelHeat;
|
||||||
|
var transient float BarrelCooldownRate;
|
||||||
|
var transient float CurrentBarrelHeat;
|
||||||
|
var transient float LastBarrelHeat;
|
||||||
|
var transient int NumPelletsDefault;
|
||||||
|
var transient int NumPelletsAlt;
|
||||||
|
|
||||||
|
simulated event PreBeginPlay()
|
||||||
|
{
|
||||||
|
Super.PreBeginPlay();
|
||||||
|
|
||||||
|
BarrelHeatPerProjectile = class'KFWeap_HRG_Dragonbreath'.default.BarrelHeatPerProjectile;
|
||||||
|
MaxBarrelHeat = class'KFWeap_HRG_Dragonbreath'.default.MaxBarrelHeat;
|
||||||
|
BarrelCooldownRate = class'KFWeap_HRG_Dragonbreath'.default.BarrelCooldownRate;
|
||||||
|
NumPelletsDefault = class'KFWeap_HRG_Dragonbreath'.default.NumPellets[0];
|
||||||
|
NumPelletsAlt = class'KFWeap_HRG_Dragonbreath'.default.NumPellets[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated event PostBeginPlay()
|
||||||
|
{
|
||||||
|
Super.PostBeginPlay();
|
||||||
|
|
||||||
|
// Force start with "Glow_Intensity" of 0.0f
|
||||||
|
LastBarrelHeat = MaxBarrelHeat;
|
||||||
|
ChangeBarrelMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function ChangeBarrelMaterial()
|
||||||
|
{
|
||||||
|
if( CurrentBarrelHeat != LastBarrelHeat )
|
||||||
|
{
|
||||||
|
if ( WeaponMIC == None && WeapMesh != None )
|
||||||
|
{
|
||||||
|
WeaponMIC = WeapMesh.CreateAndSetMaterialInstanceConstant(`HRGDRAGONBREATH_MIC_BARREL_INDEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
WeaponMIC.SetScalarParameterValue('Barrel_intensity', CurrentBarrelHeat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function Tick(float Delta)
|
||||||
|
{
|
||||||
|
Super.Tick(Delta);
|
||||||
|
|
||||||
|
CurrentBarrelHeat = fmax(CurrentBarrelHeat - BarrelCooldownRate * Delta, 0.0f);
|
||||||
|
ChangeBarrelMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Override to update emissive in weapon's barrel after firing */
|
||||||
|
simulated function PlayWeaponFireAnim()
|
||||||
|
{
|
||||||
|
local float BarrelHeatPerShot;
|
||||||
|
local KFPawn OwnerPawn;
|
||||||
|
|
||||||
|
Super.PlayWeaponFireAnim();
|
||||||
|
|
||||||
|
OwnerPawn = KFPawn(Owner);
|
||||||
|
|
||||||
|
BarrelHeatPerShot = BarrelHeatPerProjectile * (OwnerPawn.FiringMode == 0 ? NumPelletsDefault : NumPelletsAlt);
|
||||||
|
CurrentBarrelHeat = fmin(CurrentBarrelHeat + BarrelHeatPerShot, MaxBarrelHeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
CurrentBarrelHeat=0.0f
|
||||||
|
LastBarrelHeat=0.0f
|
||||||
|
NumPelletsDefault=0
|
||||||
|
NumPelletsAlt=0
|
||||||
|
}
|
144
KFGameContent/Classes/KFWeapAttach_Scythe.uc
Normal file
144
KFGameContent/Classes/KFWeapAttach_Scythe.uc
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFWeapAttach_Scythe
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFWeapAttach_Scythe extends KFWeaponAttachment;
|
||||||
|
|
||||||
|
var const float UnfoldBlendingDuration;
|
||||||
|
var const float UnfoldedAnimRateModifier;
|
||||||
|
const FoldAnim = 'Clean_NoBlood';
|
||||||
|
|
||||||
|
var AnimTree CustomAnimTree;
|
||||||
|
var AnimNodeBlendPerBone FoldBlendNode;
|
||||||
|
|
||||||
|
var transient bool bIsFolded;
|
||||||
|
|
||||||
|
event PreBeginPlay()
|
||||||
|
{
|
||||||
|
Super.PreBeginPlay();
|
||||||
|
|
||||||
|
// Override the animtree. Doing this here (before AttachTo) instead of in defaultprops
|
||||||
|
// avoids an undesired call to our owning Pawn's PostInitAnimTree
|
||||||
|
if ( CustomAnimTree != None )
|
||||||
|
{
|
||||||
|
WeapMesh.SetAnimTreeTemplate(CustomAnimTree);
|
||||||
|
|
||||||
|
WeapAnimNode = AnimNodeSequence(WeapMesh.FindAnimNode('WeaponSeq'));
|
||||||
|
FoldBlendNode = AnimNodeBlendPerBone(WeapMesh.FindAnimNode('FoldBlendNode'));
|
||||||
|
|
||||||
|
// The special event might have arrived before the attachment is created, but it's updated in the owner, so copy the state here...
|
||||||
|
if (KFPawn(Owner) != none && FoldBlendNode != none)
|
||||||
|
{
|
||||||
|
bIsFolded = KFPawn(Owner).WeaponSpecialAction == 0;
|
||||||
|
FoldBlendNode.SetBlendTarget(bIsFolded ? 1.0f : 0.0f, 0.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function ChangeMode()
|
||||||
|
{
|
||||||
|
bIsFolded = !bIsFolded;
|
||||||
|
|
||||||
|
// FoldControl = SkelControlSingleBone( WeapMesh.FindSkelControl('FoldControl') );
|
||||||
|
if( FoldBlendNode != none )
|
||||||
|
{
|
||||||
|
FoldBlendNode.SetBlendTarget( bIsFolded ? 1.0f : 0.0f, 0.0f );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called from the pawn when our first person weapon changes states */
|
||||||
|
simulated function UpdateThirdPersonWeaponAction(EWeaponState NewWeaponState, KFPawn P, byte ThirdPersonAnimRateByte )
|
||||||
|
{
|
||||||
|
Super.UpdateThirdPersonWeaponAction(NewWeaponState, P, ThirdPersonAnimRate);
|
||||||
|
|
||||||
|
if (NewWeaponState == WEP_Cleaning)
|
||||||
|
{
|
||||||
|
if (WeapAnimNode != none)
|
||||||
|
{
|
||||||
|
if (WeapAnimNode.AnimSeq == none)
|
||||||
|
{
|
||||||
|
WeapAnimNode.SetAnim(FoldAnim);
|
||||||
|
}
|
||||||
|
|
||||||
|
WeapAnimNode.PlayAnim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function ANIMNOTIFY_ShellEject()
|
||||||
|
{
|
||||||
|
ChangeMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 AnimRate;
|
||||||
|
local float Duration;
|
||||||
|
local EAnimSlotStance Stance;
|
||||||
|
local string AnimStr;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
AnimRate = ThirdPersonAnimRate;
|
||||||
|
AnimStr = Caps(string(AnimName));
|
||||||
|
|
||||||
|
if (!bIsFolded && (InStr(AnimStr, "ATK") != INDEX_NONE || InStr(AnimName, "COMB") != INDEX_NONE))
|
||||||
|
{
|
||||||
|
AnimRate *= UnfoldedAnimRateModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
Duration = P.PlayBodyAnim(AnimName, Stance, AnimRate, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Special event added for weap attachments. Free for use */
|
||||||
|
function OnSpecialEvent(int Arg)
|
||||||
|
{
|
||||||
|
bIsFolded = Arg == 0;
|
||||||
|
|
||||||
|
// FoldControl = SkelControlSingleBone( WeapMesh.FindSkelControl('FoldControl') );
|
||||||
|
if( FoldBlendNode != none )
|
||||||
|
{
|
||||||
|
FoldBlendNode.SetBlendTarget( bIsFolded ? 1.0f : 0.0f, 0.0f );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
CustomAnimTree=AnimTree'WEP_Scythe_ARCH.3P_Scythe_Animtree'
|
||||||
|
bIsFolded=true;
|
||||||
|
UnfoldBlendingDuration=0.25f
|
||||||
|
UnfoldedAnimRateModifier=0.7f;
|
||||||
|
|
||||||
|
// Weapon SkeletalMesh
|
||||||
|
Begin Object Name=SkeletalMeshComponent0
|
||||||
|
bForceRefPose=0
|
||||||
|
End Object
|
||||||
|
}
|
174
KFGameContent/Classes/KFWeap_AssaultRifle_G36C.uc
Normal file
174
KFGameContent/Classes/KFWeap_AssaultRifle_G36C.uc
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFWeap_AssaultRifle_G36C
|
||||||
|
//=============================================================================
|
||||||
|
// Class Description
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFWeap_AssaultRifle_G36C extends KFWeap_SMGBase;
|
||||||
|
|
||||||
|
simulated function ZoomIn(bool bAnimateTransition, float ZoomTimeToGo)
|
||||||
|
{
|
||||||
|
super.ZoomIn(bAnimateTransition, ZoomTimeToGo);
|
||||||
|
|
||||||
|
if (LaserSight != none)
|
||||||
|
{
|
||||||
|
LaserSight.ChangeVisibility(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function ZoomOut( bool bAnimateTransition, float ZoomTimeToGo )
|
||||||
|
{
|
||||||
|
super.ZoomOut( bAnimateTransition, ZoomTimeToGo );
|
||||||
|
|
||||||
|
if (LaserSight != none)
|
||||||
|
{
|
||||||
|
LaserSight.ChangeVisibility(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function AttachLaserSight()
|
||||||
|
{
|
||||||
|
if( WorldInfo.NetMode == NM_DedicatedServer )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.AttachLaserSight();
|
||||||
|
|
||||||
|
if (LaserSight != none)
|
||||||
|
{
|
||||||
|
LaserSight.bForceDotToMatch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
bHasFireLastAnims=true
|
||||||
|
BonesToLockOnEmpty=(RW_Bolt, RW_Charging_Handle)
|
||||||
|
|
||||||
|
// Shooting Animations
|
||||||
|
FireSightedAnims[0]=Shoot_Iron
|
||||||
|
FireSightedAnims[1]=Shoot_Iron2
|
||||||
|
FireSightedAnims[2]=Shoot_Iron3
|
||||||
|
|
||||||
|
// FOV
|
||||||
|
MeshFOV=70
|
||||||
|
MeshIronSightFOV=20
|
||||||
|
PlayerIronSightFOV=70
|
||||||
|
|
||||||
|
// Depth of field
|
||||||
|
DOF_FG_FocalRadius=150
|
||||||
|
DOF_FG_MaxNearBlurSize=3
|
||||||
|
|
||||||
|
// Zooming/Position
|
||||||
|
IronSightPosition=(X=40,Y=0.1,Z=-4.57)
|
||||||
|
PlayerViewOffset=(X=14,Y=11,Z=-5)
|
||||||
|
|
||||||
|
// Content
|
||||||
|
PackageKey="G36C"
|
||||||
|
FirstPersonMeshName="WEP_1P_G36C_MESH.Wep_1stP_G36C_Rig"
|
||||||
|
FirstPersonAnimSetNames(0)="WEP_1P_G36C_ANIM.Wep_1stP_G36C_Anim"
|
||||||
|
PickupMeshName="WEP_3P_G36C_MESH.Wep_G36C_Pickup"
|
||||||
|
AttachmentArchetypeName="WEP_G36C_ARCH.Wep_G36C_3P"
|
||||||
|
MuzzleFlashTemplateName="WEP_G36C_ARCH.Wep_G36C_MuzzleFlash"
|
||||||
|
|
||||||
|
LaserSightTemplate=KFLaserSightAttachment'FX_LaserSight_ARCH.LaserSight_WithAttachment_1P'
|
||||||
|
|
||||||
|
// Ammo
|
||||||
|
MagazineCapacity[0]=30
|
||||||
|
SpareAmmoCapacity[0]=450
|
||||||
|
InitialSpareMags[0]=3
|
||||||
|
bCanBeReloaded=true
|
||||||
|
bReloadFromMagazine=true
|
||||||
|
|
||||||
|
// Recoil
|
||||||
|
maxRecoilPitch=50
|
||||||
|
minRecoilPitch=40
|
||||||
|
maxRecoilYaw=70
|
||||||
|
minRecoilYaw=-70
|
||||||
|
RecoilRate=0.085
|
||||||
|
RecoilMaxYawLimit=500
|
||||||
|
RecoilMinYawLimit=65035
|
||||||
|
RecoilMaxPitchLimit=900
|
||||||
|
RecoilMinPitchLimit=65035
|
||||||
|
RecoilISMaxYawLimit=100
|
||||||
|
RecoilISMinYawLimit=65460
|
||||||
|
RecoilISMaxPitchLimit=350
|
||||||
|
RecoilISMinPitchLimit=65460
|
||||||
|
IronSightMeshFOVCompensationScale=6.0
|
||||||
|
|
||||||
|
// Old Recoil Data
|
||||||
|
// maxRecoilPitch=80
|
||||||
|
// minRecoilPitch=65
|
||||||
|
// maxRecoilYaw=60
|
||||||
|
// minRecoilYaw=-60
|
||||||
|
// RecoilRate=0.063
|
||||||
|
// RecoilMaxYawLimit=400
|
||||||
|
// RecoilMinYawLimit=65135
|
||||||
|
// RecoilMaxPitchLimit=800
|
||||||
|
// RecoilMinPitchLimit=65035
|
||||||
|
// RecoilISMaxYawLimit=150
|
||||||
|
// RecoilISMinYawLimit=65385
|
||||||
|
// RecoilISMaxPitchLimit=350
|
||||||
|
// RecoilISMinPitchLimit=65435
|
||||||
|
// IronSightMeshFOVCompensationScale=1.5
|
||||||
|
|
||||||
|
// Inventory
|
||||||
|
InventorySize=7
|
||||||
|
GroupPriority=100
|
||||||
|
WeaponSelectTexture=Texture2D'wep_ui_g36c_tex.UI_WeaponSelect_G36C'
|
||||||
|
|
||||||
|
// DEFAULT_FIREMODE
|
||||||
|
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletAuto'
|
||||||
|
FiringStatesArray(DEFAULT_FIREMODE)=WeaponFiring
|
||||||
|
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_InstantHit
|
||||||
|
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_AssaultRifle'
|
||||||
|
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_G36C'
|
||||||
|
PenetrationPower(DEFAULT_FIREMODE)=4.0
|
||||||
|
FireInterval(DEFAULT_FIREMODE)=+0.08 // 750 RPM
|
||||||
|
Spread(DEFAULT_FIREMODE)=0.005
|
||||||
|
InstantHitDamage(DEFAULT_FIREMODE)=45.0
|
||||||
|
FireOffset=(X=30,Y=4.5,Z=-5)
|
||||||
|
|
||||||
|
// ALT_FIREMODE
|
||||||
|
FireModeIconPaths(ALTFIRE_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletSingle'
|
||||||
|
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSingleFiring
|
||||||
|
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_InstantHit
|
||||||
|
WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Bullet_AssaultRifle'
|
||||||
|
InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_G36C'
|
||||||
|
PenetrationPower(ALTFIRE_FIREMODE)=4.0
|
||||||
|
FireInterval(ALTFIRE_FIREMODE)=+0.08 // 750 RPM
|
||||||
|
InstantHitDamage(ALTFIRE_FIREMODE)=45.0
|
||||||
|
Spread(ALTFIRE_FIREMODE)=0.005
|
||||||
|
|
||||||
|
// BASH_FIREMODE
|
||||||
|
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_G36C'
|
||||||
|
InstantHitDamage(BASH_FIREMODE)=26
|
||||||
|
|
||||||
|
// Fire Effects
|
||||||
|
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_G36C.Play_WEP_G36C_3P_Shoot_LP', FirstPersonCue=AkEvent'WW_WEP_G36C.Play_WEP_G36C_1P_Shoot_LP')
|
||||||
|
WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_G36C.Play_WEP_G36C_3P_Shoot_Single', FirstPersonCue=AkEvent'WW_WEP_G36C.Play_WEP_G36C_1P_Shoot_Single')
|
||||||
|
WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_SA_AK12.Play_WEP_SA_AK12_Handling_DryFire' //@TODO: Replace me
|
||||||
|
WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_SA_AK12.Play_WEP_SA_AK12_Handling_DryFire' //@TODO: Replace me
|
||||||
|
// WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_G36C.Play_WEP_G36C_Dry_Fire'
|
||||||
|
// WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_G36C.Play_WEP_G36C_Dry_Fire'
|
||||||
|
|
||||||
|
// Advanced (High RPM) Fire Effects
|
||||||
|
bLoopingFireAnim(DEFAULT_FIREMODE)=true
|
||||||
|
bLoopingFireSnd(DEFAULT_FIREMODE)=true
|
||||||
|
WeaponFireLoopEndSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_G36C.Play_WEP_G36C_3P_End_LP', FirstPersonCue=AkEvent'WW_WEP_G36C.Play_WEP_G36C_1P_End_LP')
|
||||||
|
SingleFireSoundIndex=ALTFIRE_FIREMODE
|
||||||
|
|
||||||
|
// Attachments
|
||||||
|
bHasIronSights=true
|
||||||
|
bHasFlashlight=false
|
||||||
|
bHasLaserSight=true
|
||||||
|
|
||||||
|
AssociatedPerkClasses(0)=class'KFPerk_Swat'
|
||||||
|
|
||||||
|
// Weapon Upgrade stat boosts
|
||||||
|
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1)))
|
||||||
|
}
|
437
KFGameContent/Classes/KFWeap_Edged_Scythe.uc
Normal file
437
KFGameContent/Classes/KFWeap_Edged_Scythe.uc
Normal file
@ -0,0 +1,437 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFWeap_Edged_AbominationAxe
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class KFWeap_Edged_Scythe extends KFWeap_MeleeBase;
|
||||||
|
|
||||||
|
var const array<MeleeHitBoxInfo> HitboxChainFolded;
|
||||||
|
var const array<MeleeHitBoxInfo> HitboxChainUnfolded;
|
||||||
|
|
||||||
|
var const int MaxHitRangeFolded;
|
||||||
|
var const int MaxHitRangeUnfolded;
|
||||||
|
|
||||||
|
var const int FoldedDamage;
|
||||||
|
var const int FoldedDamageAlt;
|
||||||
|
|
||||||
|
var const int UnfoldedDamage;
|
||||||
|
var const int UnfoldedDamageAlt;
|
||||||
|
|
||||||
|
var const class<DamageType> FoldedDT;
|
||||||
|
var const class<DamageType> FoldedDTAlt;
|
||||||
|
|
||||||
|
var const class<DamageType> UnfoldedDT;
|
||||||
|
var const class<DamageType> UnfoldedDTAlt;
|
||||||
|
|
||||||
|
var const float UnfoldBlendingDuration;
|
||||||
|
|
||||||
|
var const float FoldedAttackAnimRate;
|
||||||
|
|
||||||
|
var const vector PlayerViewOffsetUnfolded;
|
||||||
|
|
||||||
|
var transient vector OriginalPlayerViewOffset;
|
||||||
|
var transient bool bIsFolded;
|
||||||
|
|
||||||
|
var AnimNodeBlendPerBone FoldBlendNode;
|
||||||
|
|
||||||
|
var const ParticleSystem BloodParticles;
|
||||||
|
|
||||||
|
const BloodParticlesSocket = 'BlockEffect';
|
||||||
|
|
||||||
|
var ParticleSystem FoldedTrailParticleSystem;
|
||||||
|
var ParticleSystem UnfoldedTrailParticleSystem;
|
||||||
|
|
||||||
|
simulated event PreBeginPlay()
|
||||||
|
{
|
||||||
|
Super.PreBeginPlay();
|
||||||
|
|
||||||
|
OriginalPlayerViewOffset = PlayerViewOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
event PostBeginPlay()
|
||||||
|
{
|
||||||
|
Super.PostBeginPlay();
|
||||||
|
|
||||||
|
ChangeMode(true, false);
|
||||||
|
|
||||||
|
SetFoldedBladeBlendTarget(1.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/** The SkeletalMeshComponents Animations are being instanced from AnimTreeTemplate
|
||||||
|
* before PostInitAnimTree. Be sure to never set the Mesh's animations directly through
|
||||||
|
* the package */
|
||||||
|
simulated event PostInitAnimTree(SkeletalMeshComponent SkelComp)
|
||||||
|
{
|
||||||
|
Super.PostInitAnimTree(SkelComp);
|
||||||
|
|
||||||
|
FoldBlendNode = AnimNodeBlendPerBone(SkelComp.FindAnimNode('FoldBlendNode'));
|
||||||
|
|
||||||
|
SetFoldedBladeBlendTarget(1.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/** Returns true if weapon can potentially be reloaded */
|
||||||
|
simulated function bool CanReload(optional byte FireModeNum)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated state WeaponUpkeep
|
||||||
|
{
|
||||||
|
simulated function BeginState(name PreviousStateName)
|
||||||
|
{
|
||||||
|
local name AnimName;
|
||||||
|
local float Duration;
|
||||||
|
|
||||||
|
AnimName = CleanNonBloodyAnim;
|
||||||
|
|
||||||
|
Duration = MySkelMesh.GetAnimLength(AnimName);
|
||||||
|
if ( Duration > 0.f )
|
||||||
|
{
|
||||||
|
if ( Instigator.IsFirstPerson() )
|
||||||
|
{
|
||||||
|
PlayAnimation(AnimName);
|
||||||
|
SetTimer(Duration, FALSE, nameof(SwapComplete));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
`warn("Duration is zero!!!"@AnimName);
|
||||||
|
SetTimer(0.001, FALSE, nameof(SwapComplete));
|
||||||
|
}
|
||||||
|
|
||||||
|
NotifyBeginState();
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function BeginFire(byte FireModeNum)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated event EndState(Name NextStateName)
|
||||||
|
{
|
||||||
|
ClearTimer(nameof(SwapComplete));
|
||||||
|
Super.EndState(NextStateName);
|
||||||
|
NotifyEndState();
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function SwapComplete()
|
||||||
|
{
|
||||||
|
if (Role == ROLE_Authority)
|
||||||
|
{
|
||||||
|
GotoState('Active');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GotoState('Active');
|
||||||
|
ServerSwapComplete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server reliable function ServerSwapComplete()
|
||||||
|
{
|
||||||
|
GotoState('Active');
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function ChangeMode(bool IsFolded, bool bApplyBlend = true)
|
||||||
|
{
|
||||||
|
if (MeleeAttackHelper == none)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (IsFolded)
|
||||||
|
{
|
||||||
|
MeleeAttackHelper.SetMeleeRange(MaxHitRangeFolded);
|
||||||
|
MeleeAttackHelper.SetHitBoxChain(HitboxChainFolded);
|
||||||
|
|
||||||
|
InstantHitDamage[DEFAULT_FIREMODE] = FoldedDamage;
|
||||||
|
InstantHitDamage[HEAVY_ATK_FIREMODE] = FoldedDamageAlt;
|
||||||
|
|
||||||
|
InstantHitDamageTypes[DEFAULT_FIREMODE] = FoldedDT;
|
||||||
|
InstantHitDamageTypes[HEAVY_ATK_FIREMODE] = FoldedDTAlt;
|
||||||
|
|
||||||
|
PlayerViewOffset = OriginalPlayerViewOffset;
|
||||||
|
|
||||||
|
InstantHitDamageTypes[BASH_FIREMODE]=class'KFDT_Piercing_ScytheStabFolded';
|
||||||
|
InstantHitMomentum[BASH_FIREMODE]=100000.f;
|
||||||
|
InstantHitDamage[BASH_FIREMODE]=40;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MeleeAttackHelper.SetMeleeRange(MaxHitRangeUnfolded);
|
||||||
|
MeleeAttackHelper.SetHitBoxChain(HitboxChainUnfolded);
|
||||||
|
|
||||||
|
InstantHitDamage[DEFAULT_FIREMODE] = UnfoldedDamage;
|
||||||
|
InstantHitDamage[HEAVY_ATK_FIREMODE] = UnfoldedDamageAlt;
|
||||||
|
|
||||||
|
InstantHitDamageTypes[DEFAULT_FIREMODE] = UnfoldedDT;
|
||||||
|
InstantHitDamageTypes[HEAVY_ATK_FIREMODE] = UnfoldedDTAlt;
|
||||||
|
|
||||||
|
PlayerViewOffset = PlayerViewOffsetUnfolded;
|
||||||
|
|
||||||
|
InstantHitDamageTypes[BASH_FIREMODE]=class'KFDT_Piercing_ScytheStab';
|
||||||
|
InstantHitMomentum[BASH_FIREMODE]=100000.f;
|
||||||
|
InstantHitDamage[BASH_FIREMODE]=60;
|
||||||
|
}
|
||||||
|
|
||||||
|
NotifyServerMode(bIsFolded);
|
||||||
|
|
||||||
|
if (bApplyBlend)
|
||||||
|
{
|
||||||
|
SetFoldedBladeBlendTarget(bIsFolded ? 1.0f : 0.0f, UnfoldBlendingDuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function SetFoldedBladeBlendTarget(float Value, float BlendTime)
|
||||||
|
{
|
||||||
|
if ( FoldBlendNode != None )
|
||||||
|
{
|
||||||
|
FoldBlendNode.SetBlendTarget(Value, BlendTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function StartFire(byte FireModeNum)
|
||||||
|
{
|
||||||
|
if (StartFireDisabled && FireModeNum == BLOCK_FIREMODE)
|
||||||
|
{
|
||||||
|
StartFireDisabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FireModeNum == DEFAULT_FIREMODE || FireModeNum == HEAVY_ATK_FIREMODE)
|
||||||
|
{
|
||||||
|
DistortTrailParticle = bIsFolded ? FoldedTrailParticleSystem : UnfoldedTrailParticleSystem;
|
||||||
|
}
|
||||||
|
else if (FireModeNum == BASH_FIREMODE)
|
||||||
|
{
|
||||||
|
DistortTrailParticle = none;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.StartFire(FireModeNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
static simulated function float CalculateTraderWeaponStatDamage()
|
||||||
|
{
|
||||||
|
// How is this calculated for this weapon?
|
||||||
|
return default.UnfoldedDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function PlayAnimation(name Sequence, optional float fDesiredDuration, optional bool bLoop, optional float BlendInTime=0.1, optional float BlendOutTime=0.0)
|
||||||
|
{
|
||||||
|
local string NewAnimName;
|
||||||
|
|
||||||
|
if (Sequence == 'Idle' ||
|
||||||
|
Sequence == 'Guncheck_V1' ||
|
||||||
|
Sequence == 'Guncheck_V2' ||
|
||||||
|
Sequence == 'Guncheck_V3')
|
||||||
|
{
|
||||||
|
NewAnimName = string(Sequence);
|
||||||
|
NewAnimName $= ((bIsFolded) ? "_Folded" : "_Unfolded");
|
||||||
|
Super.PlayAnimation(name(NewAnimName), fDesiredDuration, bLoop, BlendInTime, BlendOutTime);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Super.PlayAnimation(Sequence, fDesiredDuration, bLoop, BlendInTime, BlendOutTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function ModifyMeleeAttackSpeed(out float InSpeed, optional int FireMode = DEFAULT_FIREMODE, optional int UpgradeIndex = INDEX_NONE, optional KFPerk CurrentPerk)
|
||||||
|
{
|
||||||
|
Super.ModifyMeleeAttackSpeed(InSpeed, FireMode, UpgradeIndex, CurrentPerk);
|
||||||
|
|
||||||
|
if (bIsFolded)
|
||||||
|
{
|
||||||
|
InSpeed *= FoldedAttackAnimRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overriden to apply fold/unfold logic
|
||||||
|
*/
|
||||||
|
simulated function ANIMNOTIFY_LockBolt()
|
||||||
|
{
|
||||||
|
bIsFolded = !bIsFolded;
|
||||||
|
ChangeMode(bIsFolded);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unused */
|
||||||
|
simulated function ANIMNOTIFY_UnLockBolt()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Play blood VFX as we only use one anim. */
|
||||||
|
simulated function ANIMNOTIFY_CleanBlood()
|
||||||
|
{
|
||||||
|
if (!bIsBloody)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WorldInfo.NetMode != NM_DedicatedServer && BloodParticles != none)
|
||||||
|
{
|
||||||
|
WorldInfo.MyEmitterPool.SpawnEmitterMeshAttachment(BloodParticles, MySkelMesh, BloodParticlesSocket, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Super.ANIMNOTIFY_CleanBlood();
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated state WeaponEquipping
|
||||||
|
{
|
||||||
|
/** Initialize the weapon as being active and ready to go. */
|
||||||
|
simulated event BeginState(Name PreviousStateName)
|
||||||
|
{
|
||||||
|
Super.BeginState(PreviousStateName);
|
||||||
|
|
||||||
|
if (WorldInfo.NetMode != NM_Client)
|
||||||
|
{
|
||||||
|
NotifyInitialState(bIsFolded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Should replicate to 3P to show the shield effects
|
||||||
|
*/
|
||||||
|
simulated function NotifyInitialState(bool bFolded)
|
||||||
|
{
|
||||||
|
local KFPawn KFP;
|
||||||
|
|
||||||
|
if (WorldInfo.NetMode != NM_Client)
|
||||||
|
{
|
||||||
|
`Log("NotifyInitialState: " $bFolded);
|
||||||
|
|
||||||
|
KFP = KFPawn(Instigator);
|
||||||
|
KFP.OnWeaponSpecialAction(bFolded ? 0 : 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reliable server function NotifyServerMode(bool bFolded)
|
||||||
|
{
|
||||||
|
bIsFolded = bFolded;
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
// Zooming/Position
|
||||||
|
PlayerViewOffset=(X=10,Y=0,Z=-10) // (X=2,Y=0,Z=0)
|
||||||
|
PlayerViewOffsetUnfolded=(X=12,Y=0,Z=-7)
|
||||||
|
|
||||||
|
// Content
|
||||||
|
PackageKey="Scythe"
|
||||||
|
FirstPersonMeshName="WEP_1P_Scythe_MESH.Wep_1stP_Scythe_Rig"
|
||||||
|
FirstPersonAnimSetNames(0)="WEP_1P_Scythe_ANIM.Wep_1st_Scythe_Anim"
|
||||||
|
FirstPersonAnimTree="WEP_1P_Scythe_ANIM.1P_Scythe_Animtree"
|
||||||
|
PickupMeshName="wep_3p_scythe_mesh.Wep_3rdP_Scythe_Pickup"
|
||||||
|
AttachmentArchetypeName="WEP_Scythe_ARCH.Wep_Scythe_3P"
|
||||||
|
|
||||||
|
// Short Range Mode Params
|
||||||
|
MaxHitRangeFolded=220
|
||||||
|
FoldedDamage = 70
|
||||||
|
FoldedDamageAlt = 120
|
||||||
|
FoldedDT=class'KFDT_Slashing_ScytheShort'
|
||||||
|
FoldedDTAlt=class'KFDT_Slashing_ScytheShortAlt'
|
||||||
|
HitboxChainFolded = {(
|
||||||
|
(BoneOffset=(X=+3,Z=190)),
|
||||||
|
(BoneOffset=(X=-3,Z=170)),
|
||||||
|
(BoneOffset=(X=+3,Z=150)),
|
||||||
|
(BoneOffset=(X=-3,Z=130)),
|
||||||
|
(BoneOffset=(X=+3,Z=110)),
|
||||||
|
(BoneOffset=(X=-3,Z=90)),
|
||||||
|
(BoneOffset=(X=+3,Z=70)),
|
||||||
|
(BoneOffset=(X=-3,Z=50)),
|
||||||
|
(BoneOffset=(X=+3,Z=30)),
|
||||||
|
(BoneOffset=(Z=10))
|
||||||
|
)}
|
||||||
|
|
||||||
|
// Long Range Mode Params
|
||||||
|
MaxHitRangeUnfolded=300
|
||||||
|
UnfoldedDamage=140
|
||||||
|
UnfoldedDamageAlt=190
|
||||||
|
UnfoldedDT=class'KFDT_Slashing_ScytheLong'
|
||||||
|
UnfoldedDTAlt=class'KFDT_Slashing_ScytheLongAlt'
|
||||||
|
HitboxChainUnfolded = {(
|
||||||
|
(BoneOffset=(X=-3,Z=290)),
|
||||||
|
(BoneOffset=(X=-3,Z=270)),
|
||||||
|
(BoneOffset=(X=-3,Z=250)),
|
||||||
|
(BoneOffset=(X=+3,Z=230)),
|
||||||
|
(BoneOffset=(X=-3,Z=210)),
|
||||||
|
(BoneOffset=(X=+3,Z=190)),
|
||||||
|
(BoneOffset=(X=-3,Z=170)),
|
||||||
|
(BoneOffset=(X=+3,Z=150)),
|
||||||
|
(BoneOffset=(X=-3,Z=130)),
|
||||||
|
(BoneOffset=(X=+3,Z=110)),
|
||||||
|
(BoneOffset=(X=-3,Z=90)),
|
||||||
|
(BoneOffset=(X=+3,Z=70)),
|
||||||
|
(BoneOffset=(X=-3,Z=50)),
|
||||||
|
(BoneOffset=(X=+3,Z=30)),
|
||||||
|
(BoneOffset=(Z=10))
|
||||||
|
)}
|
||||||
|
|
||||||
|
Begin Object Name=MeleeHelper_0
|
||||||
|
WorldImpactEffects=KFImpactEffectInfo'FX_Impacts_ARCH.Bladed_melee_impact'
|
||||||
|
MeleeImpactCamShakeScale=0.04f //0.5
|
||||||
|
// modified combo sequences
|
||||||
|
ChainSequence_F=(DIR_ForwardRight, DIR_ForwardLeft, DIR_ForwardRight, DIR_ForwardLeft)
|
||||||
|
ChainSequence_B=(DIR_BackwardLeft, DIR_BackwardRight, DIR_BackwardLeft, DIR_ForwardRight, DIR_Left, DIR_Right, DIR_Left)
|
||||||
|
ChainSequence_L=(DIR_Right, DIR_Left)
|
||||||
|
ChainSequence_R=(DIR_Left, DIR_Right, DIR_ForwardLeft, DIR_ForwardRight, DIR_Left, DIR_Right)
|
||||||
|
End Object
|
||||||
|
|
||||||
|
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Slashing_ScytheShort'
|
||||||
|
InstantHitMomentum(DEFAULT_FIREMODE)=30000.f
|
||||||
|
|
||||||
|
InstantHitDamageTypes(HEAVY_ATK_FIREMODE)=class'KFDT_Slashing_ScytheShortAlt'
|
||||||
|
FiringStatesArray(HEAVY_ATK_FIREMODE)=MeleeHeavyAttacking
|
||||||
|
InstantHitMomentum(HEAVY_ATK_FIREMODE)=30000.f
|
||||||
|
|
||||||
|
// Defined in ChangeMode function
|
||||||
|
//InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Piercing_ScytheStab'
|
||||||
|
//InstantHitMomentum(BASH_FIREMODE)=100000.f
|
||||||
|
//InstantHitDamage(BASH_FIREMODE)=50
|
||||||
|
|
||||||
|
// Inventory
|
||||||
|
GroupPriority=50
|
||||||
|
InventorySize=7
|
||||||
|
WeaponSelectTexture=Texture2D'WEP_UI_Scythe_TEX.UI_WeaponSelect_Scythe'
|
||||||
|
|
||||||
|
|
||||||
|
AssociatedPerkClasses(0)=class'KFPerk_Berserker'
|
||||||
|
|
||||||
|
// Block Sounds
|
||||||
|
BlockSound=AkEvent'WW_WEP_Bullet_Impacts.Play_Block_MEL_Katana'
|
||||||
|
ParrySound=AkEvent'WW_WEP_Bullet_Impacts.Play_Parry_Metal'
|
||||||
|
|
||||||
|
ParryDamageMitigationPercent=0.4
|
||||||
|
BlockDamageMitigation=0.5
|
||||||
|
ParryStrength=5
|
||||||
|
|
||||||
|
bIsFolded=true
|
||||||
|
|
||||||
|
BonesToLockOnEmpty.Empty()
|
||||||
|
|
||||||
|
UnfoldBlendingDuration=0.05f
|
||||||
|
|
||||||
|
FoldedAttackAnimRate=0.65f
|
||||||
|
|
||||||
|
// IdleFidgetAnims=(Guncheck_v1, Guncheck_v2, Guncheck_v3)
|
||||||
|
|
||||||
|
// Weapon Upgrade stat boosts
|
||||||
|
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1)))
|
||||||
|
|
||||||
|
DistortTrailParticle = none
|
||||||
|
WhiteTrailParticle = none
|
||||||
|
BlueTrailParticle = none
|
||||||
|
RedTrailParticle = none
|
||||||
|
|
||||||
|
FoldedTrailParticleSystem=ParticleSystem'WEP_Scythe_EMIT.FX_Scythe_Custom_R_01'
|
||||||
|
UnfoldedTrailParticleSystem=ParticleSystem'WEP_Scythe_EMIT.FX_Scythe_Custom_Unfold_01';
|
||||||
|
|
||||||
|
BloodParticles = ParticleSystem'WEP_1P_KATANA_EMIT.FX_katana_blood_flick_01'
|
||||||
|
}
|
286
KFGameContent/Classes/KFWeap_HRG_Dragonbreath.uc
Normal file
286
KFGameContent/Classes/KFWeap_HRG_Dragonbreath.uc
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFWeap_HRG_Dragonbreath
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//=============================================================================
|
||||||
|
class KFWeap_HRG_Dragonbreath extends KFWeap_ShotgunBase;
|
||||||
|
|
||||||
|
/** How much to scale recoil when firing in double barrel fire. */
|
||||||
|
var(Recoil) float QuadFireRecoilModifier;
|
||||||
|
|
||||||
|
/** Shoot animation to play when shooting both barrels from the hip */
|
||||||
|
var(Animations) const editconst name FireQuadAnim;
|
||||||
|
|
||||||
|
/** How much momentum to apply when fired in double barrel */
|
||||||
|
var(Recoil) float DoubleBarrelKickMomentum;
|
||||||
|
|
||||||
|
/** How much to reduce shoot momentum when falling */
|
||||||
|
var(Recoil) float FallingMomentumReduction;
|
||||||
|
|
||||||
|
var(Spread) const float SpreadWidthDegrees;
|
||||||
|
var(Spread) const float SpreadWidthDegreesAlt;
|
||||||
|
|
||||||
|
var transient float StartingPelletPosition;
|
||||||
|
var transient float StartingPelletPositionAlt;
|
||||||
|
|
||||||
|
var const float BarrelHeatPerProjectile;
|
||||||
|
var const float MaxBarrelHeat;
|
||||||
|
var const float BarrelCooldownRate;
|
||||||
|
var transient float CurrentBarrelHeat;
|
||||||
|
var transient float LastBarrelHeat;
|
||||||
|
|
||||||
|
simulated event PreBeginPlay()
|
||||||
|
{
|
||||||
|
Super.PreBeginPlay();
|
||||||
|
|
||||||
|
Spread[DEFAULT_FIREMODE] = SpreadWidthDegrees * DegToRad / NumPellets[DEFAULT_FIREMODE];
|
||||||
|
Spread[ALTFIRE_FIREMODE] = SpreadWidthDegreesAlt * DegToRad / NumPellets[ALTFIRE_FIREMODE];
|
||||||
|
|
||||||
|
StartingPelletPosition = -SpreadWidthDegrees * DegToRad / 2.0f;
|
||||||
|
StartingPelletPositionAlt = -SpreadWidthDegreesAlt * DegToRad / 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated event PostBeginPlay()
|
||||||
|
{
|
||||||
|
Super.PostBeginPlay();
|
||||||
|
|
||||||
|
// Force start with "Glow_Intensity" of 0.0f
|
||||||
|
LastBarrelHeat = MaxBarrelHeat;
|
||||||
|
ChangeBarrelMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function AltFireMode()
|
||||||
|
{
|
||||||
|
if ( !Instigator.IsLocallyControlled() )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StartFire(ALTFIRE_FIREMODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns number of projectiles to fire from SpawnProjectile */
|
||||||
|
simulated function byte GetNumProjectilesToFire(byte FireModeNum)
|
||||||
|
{
|
||||||
|
return NumPellets[CurrentFireMode];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handle one-hand fire anims */
|
||||||
|
simulated function name GetWeaponFireAnim(byte FireModeNum)
|
||||||
|
{
|
||||||
|
if (bUsingSights)
|
||||||
|
{
|
||||||
|
return FireSightedAnims[FireModeNum];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (FireModeNum == ALTFIRE_FIREMODE)
|
||||||
|
{
|
||||||
|
return FireQuadAnim;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FireAnim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function KFProjectile SpawnAllProjectiles(class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir)
|
||||||
|
{
|
||||||
|
local int ProjectilesToFire, i;
|
||||||
|
local float InitialOffset;
|
||||||
|
|
||||||
|
ProjectilesToFire = GetNumProjectilesToFire(CurrentFireMode);
|
||||||
|
if (CurrentFireMode == GRENADE_FIREMODE || ProjectilesToFire <= 1)
|
||||||
|
{
|
||||||
|
return SpawnProjectile(KFProjClass, RealStartLoc, AimDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
InitialOffset = CurrentFireMode == DEFAULT_FIREMODE ? StartingPelletPosition : StartingPelletPositionAlt;
|
||||||
|
|
||||||
|
for (i = 0; i < ProjectilesToFire; i++)
|
||||||
|
{
|
||||||
|
SpawnProjectile(KFProjClass, RealStartLoc, CalculateSpread(InitialOffset, Spread[CurrentFireMode], i, CurrentFireMode == ALTFIRE_FIREMODE));
|
||||||
|
CurrentBarrelHeat = fmin(CurrentBarrelHeat + BarrelHeatPerProjectile, MaxBarrelHeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChangeBarrelMaterial();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function vector CalculateSpread(float InitialOffset, float CurrentSpread, byte PelletNum, bool bHorizontal)
|
||||||
|
{
|
||||||
|
local Vector X, Y, Z, POVLoc;
|
||||||
|
local Quat R;
|
||||||
|
local rotator POVRot;
|
||||||
|
|
||||||
|
if (Instigator != None && Instigator.Controller != none)
|
||||||
|
{
|
||||||
|
Instigator.Controller.GetPlayerViewPoint(POVLoc, POVRot);
|
||||||
|
}
|
||||||
|
|
||||||
|
GetAxes(POVRot, X, Y, Z);
|
||||||
|
|
||||||
|
R = QuatFromAxisAndAngle(bHorizontal ? Z : Y, InitialOffset + CurrentSpread * PelletNum);
|
||||||
|
return QuatRotateVector(R, vector(POVRot));
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function ChangeBarrelMaterial()
|
||||||
|
{
|
||||||
|
local int i;
|
||||||
|
|
||||||
|
if( CurrentBarrelHeat != LastBarrelHeat )
|
||||||
|
{
|
||||||
|
for( i = 0; i < WeaponMICs.Length; ++i )
|
||||||
|
{
|
||||||
|
if( WeaponMICs[i] != none )
|
||||||
|
{
|
||||||
|
WeaponMICs[i].SetScalarParameterValue('Barrel_intensity', CurrentBarrelHeat);
|
||||||
|
LastBarrelHeat = CurrentBarrelHeat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function Tick(float Delta)
|
||||||
|
{
|
||||||
|
Super.Tick(Delta);
|
||||||
|
|
||||||
|
CurrentBarrelHeat = fmax(CurrentBarrelHeat - BarrelCooldownRate * Delta, 0.0f);
|
||||||
|
ChangeBarrelMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
// Inventory
|
||||||
|
InventorySize=7
|
||||||
|
GroupPriority=110
|
||||||
|
WeaponSelectTexture=Texture2D'WEP_UI_HRG_MegaDragonsbreath_TEX.UI_WeaponSelect_HRG_MegaDragonsbreath'
|
||||||
|
|
||||||
|
// FOV
|
||||||
|
MeshFOV=60
|
||||||
|
MeshIronSightFOV=52
|
||||||
|
PlayerIronSightFOV=70
|
||||||
|
|
||||||
|
// Depth of field
|
||||||
|
DOF_FG_FocalRadius=65
|
||||||
|
DOF_FG_MaxNearBlurSize=3
|
||||||
|
|
||||||
|
// Zooming/Position
|
||||||
|
PlayerViewOffset=(X=15.0,Y=8.0,Z=-4.5)
|
||||||
|
IronSightPosition=(X=3,Y=0,Z=0)
|
||||||
|
|
||||||
|
// Content
|
||||||
|
PackageKey="HRG_MegaDragonsbreath"
|
||||||
|
FirstPersonMeshName="wep_1p_hrg_megadragonsbreath_mesh.Wep_1stP_HRG_MegaDragonsbreath_Rig"
|
||||||
|
FirstPersonAnimSetNames(0)="wep_1p_hrg_megadragonsbreath_anim.Wep_1stP_HRG_MegaDragonsbreath_Anim"
|
||||||
|
PickupMeshName="wep_3p_hrg_megadragonsbreath_mesh.Wep_3rdP_HRG_MegaDragonsbreath_Pickup"
|
||||||
|
AttachmentArchetypeName="wep_hrg_megadragonsbreath_arch.Wep_HRG_MegaDragonsbreath_3P"
|
||||||
|
MuzzleFlashTemplateName="wep_hrg_megadragonsbreath_arch.Wep_HRG_MegaDragonsbreath_MuzzleFlash"
|
||||||
|
|
||||||
|
// Animations
|
||||||
|
FireAnim=Shoot_Single
|
||||||
|
FireQuadAnim=Shoot_Double
|
||||||
|
FireSightedAnims[0]=Shoot_Iron_Single
|
||||||
|
FireSightedAnims[1]=Shoot_Iron_Double
|
||||||
|
bHasFireLastAnims=false
|
||||||
|
|
||||||
|
// 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_Pellet_HRG_Dragonbreath'
|
||||||
|
InstantHitDamage(DEFAULT_FIREMODE)=28.0 //36
|
||||||
|
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_HRG_Dragonbreath'
|
||||||
|
PenetrationPower(DEFAULT_FIREMODE)=4.0
|
||||||
|
FireInterval(DEFAULT_FIREMODE)=0.25 // 240 RPM
|
||||||
|
FireOffset=(X=25,Y=3.5,Z=-4)
|
||||||
|
NumPellets(DEFAULT_FIREMODE)=8
|
||||||
|
Spread(DEFAULT_FIREMODE)=0
|
||||||
|
ForceReloadTimeOnEmpty=0.3
|
||||||
|
|
||||||
|
// ALT_FIREMODE
|
||||||
|
FireModeIconPaths(ALTFIRE_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_ShotgunAuto'
|
||||||
|
FiringStatesArray(ALTFIRE_FIREMODE)= WeaponSingleFiring
|
||||||
|
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Projectile
|
||||||
|
WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Pellet_HRG_Dragonbreath'
|
||||||
|
InstantHitDamage(ALTFIRE_FIREMODE)=28.0
|
||||||
|
InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_HRG_Dragonbreath'
|
||||||
|
PenetrationPower(ALTFIRE_FIREMODE)=4.0
|
||||||
|
FireInterval(ALTFIRE_FIREMODE)=0.25 // 240 RPM
|
||||||
|
NumPellets(ALTFIRE_FIREMODE)=8
|
||||||
|
Spread(ALTFIRE_FIREMODE)=0
|
||||||
|
AmmoCost(ALTFIRE_FIREMODE)=1
|
||||||
|
DoubleBarrelKickMomentum=1000
|
||||||
|
FallingMomentumReduction=0.5
|
||||||
|
|
||||||
|
// BASH_FIREMODE
|
||||||
|
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HRG_Dragonbreath'
|
||||||
|
InstantHitDamage(BASH_FIREMODE)=27
|
||||||
|
|
||||||
|
// Fire Effects
|
||||||
|
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Quad_Shotgun.Play_Quad_Shotgun_Fire_3P_Single', FirstPersonCue=AkEvent'WW_WEP_Quad_Shotgun.Play_Quad_Shotgun_Fire_1P_Single') //@TODO: Replace
|
||||||
|
WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Quad_Shotgun.Play_Quad_Shotgun_Fire_3P_AltFire', FirstPersonCue=AkEvent'WW_WEP_Quad_Shotgun.Play_Quad_Shotgun_Fire_1P_AltFire') //@TODO: Replace
|
||||||
|
|
||||||
|
WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_Quad_Shotgun.Play_Quad_Shotgun_DryFire' //@TODO: Replace
|
||||||
|
WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_Quad_Shotgun.Play_Quad_Shotgun_DryFire' //@TODO: Replace
|
||||||
|
|
||||||
|
// Attachments
|
||||||
|
bHasIronSights=true
|
||||||
|
bHasFlashlight=false
|
||||||
|
|
||||||
|
// Ammo
|
||||||
|
MagazineCapacity[0]=4
|
||||||
|
SpareAmmoCapacity[0]=60 //48 //72
|
||||||
|
InitialSpareMags[0]=3 //8
|
||||||
|
AmmoPickupScale[0]=2.0 //3.0
|
||||||
|
bCanBeReloaded=true
|
||||||
|
bReloadFromMagazine=true
|
||||||
|
bNoMagazine=true
|
||||||
|
|
||||||
|
// Recoil
|
||||||
|
maxRecoilPitch=1200 //900
|
||||||
|
minRecoilPitch=775
|
||||||
|
maxRecoilYaw=800 //500
|
||||||
|
minRecoilYaw=-500
|
||||||
|
RecoilRate=0.085
|
||||||
|
RecoilBlendOutRatio=1.1
|
||||||
|
RecoilMaxYawLimit=500
|
||||||
|
RecoilMinYawLimit=65035
|
||||||
|
RecoilMaxPitchLimit=1500
|
||||||
|
RecoilMinPitchLimit=64785
|
||||||
|
RecoilISMaxYawLimit=50
|
||||||
|
RecoilISMinYawLimit=65485
|
||||||
|
RecoilISMaxPitchLimit=500
|
||||||
|
RecoilISMinPitchLimit=65485
|
||||||
|
RecoilViewRotationScale=0.8
|
||||||
|
FallingRecoilModifier=1.5
|
||||||
|
HippedRecoilModifier=1.1 //1.25
|
||||||
|
QuadFireRecoilModifier=2.0
|
||||||
|
|
||||||
|
AssociatedPerkClasses(0)=class'KFPerk_Firebug'
|
||||||
|
|
||||||
|
WeaponFireWaveForm=ForceFeedbackWaveform'FX_ForceFeedback_ARCH.Gunfire.Heavy_Recoil_SingleShot'
|
||||||
|
|
||||||
|
|
||||||
|
// Weapon Upgrade stat boosts
|
||||||
|
//WeaponUpgrades[1]=(IncrementDamage=1.15f,IncrementWeight=1)
|
||||||
|
|
||||||
|
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1)))
|
||||||
|
|
||||||
|
SpreadWidthDegrees=7.0f
|
||||||
|
SpreadWidthDegreesAlt=15.0f
|
||||||
|
|
||||||
|
StartingPelletPosition=0.0f
|
||||||
|
StartingPelletPositionAlt=0.0f
|
||||||
|
|
||||||
|
MaxBarrelHeat=5.0f
|
||||||
|
BarrelHeatPerProjectile=0.089f
|
||||||
|
BarrelCooldownRate=0.45f
|
||||||
|
|
||||||
|
CurrentBarrelHeat=0.0f
|
||||||
|
LastBarrelHeat=0.0f
|
||||||
|
|
||||||
|
NumBloodMapMaterials=3
|
||||||
|
}
|
684
KFGameContent/Classes/KFWeap_HRG_Locust.uc
Normal file
684
KFGameContent/Classes/KFWeap_HRG_Locust.uc
Normal file
@ -0,0 +1,684 @@
|
|||||||
|
//=============================================================================
|
||||||
|
// KFWeap_HRG_Locust
|
||||||
|
//=============================================================================
|
||||||
|
// A mosquito rocket launcher
|
||||||
|
//=============================================================================
|
||||||
|
// Killing Floor 2
|
||||||
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
class KFWeap_HRG_Locust extends KFWeap_GrenadeLauncher_Base;
|
||||||
|
|
||||||
|
const MAX_LOCKED_TARGETS = 6;
|
||||||
|
|
||||||
|
/** Constains all currently locked-on targets */
|
||||||
|
var protected array<Pawn> LockedTargets;
|
||||||
|
|
||||||
|
/** How much to scale recoil when firing in multi-rocket mode */
|
||||||
|
var float BurstFireRecoilModifier;
|
||||||
|
|
||||||
|
/** The last time a target was acquired */
|
||||||
|
var protected float LastTargetLockTime;
|
||||||
|
|
||||||
|
/** The last time a target validation check was performed */
|
||||||
|
var protected float LastTargetValidationCheckTime;
|
||||||
|
|
||||||
|
/** How much time after a lock on occurs before another is allowed */
|
||||||
|
var const float TimeBetweenLockOns;
|
||||||
|
|
||||||
|
/** How much time should pass between target validation checks */
|
||||||
|
var const float TargetValidationCheckInterval;
|
||||||
|
|
||||||
|
/** Minimum distance a target can be from the crosshair to be considered for lock on */
|
||||||
|
var const float MinTargetDistFromCrosshairSQ;
|
||||||
|
|
||||||
|
/** Dot product FOV that targets need to stay within to maintain a target lock */
|
||||||
|
var const float MaxLockMaintainFOVDotThreshold;
|
||||||
|
|
||||||
|
/** Sound Effects to play when Locking */
|
||||||
|
var AkBaseSoundObject LockAcquiredSoundFirstPerson;
|
||||||
|
var AkBaseSoundObject LockLostSoundFirstPerson;
|
||||||
|
|
||||||
|
/** Icon textures for lock on drawing */
|
||||||
|
var const Texture2D LockedOnIcon;
|
||||||
|
var LinearColor LockedIconColor;
|
||||||
|
|
||||||
|
/** Ironsights Audio */
|
||||||
|
var AkComponent IronsightsComponent;
|
||||||
|
var AkEvent IronsightsZoomInSound;
|
||||||
|
var AkEvent IronsightsZoomOutSound;
|
||||||
|
|
||||||
|
/** Reduction for the amount of damage dealt to the weapon owner (including damage by the explosion) */
|
||||||
|
var() float SelfDamageReductionValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle between DEFAULT and ALTFIRE
|
||||||
|
*/
|
||||||
|
simulated function AltFireMode()
|
||||||
|
{
|
||||||
|
super.AltFireMode();
|
||||||
|
|
||||||
|
LockedTargets.Length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************
|
||||||
|
* @name Target Locking And Validation
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
/** We need to update our locked targets every frame and make sure they're within view and not dead */
|
||||||
|
simulated event Tick( float DeltaTime )
|
||||||
|
{
|
||||||
|
local Pawn RecentlyLocked, StaticLockedTargets[6];
|
||||||
|
local bool bUpdateServerTargets;
|
||||||
|
local int i;
|
||||||
|
|
||||||
|
super.Tick( DeltaTime );
|
||||||
|
|
||||||
|
if( bUsingSights && bUseAltFireMode
|
||||||
|
&& Instigator != none
|
||||||
|
&& Instigator.IsLocallyControlled() )
|
||||||
|
{
|
||||||
|
if( `TimeSince(LastTargetLockTime) > TimeBetweenLockOns
|
||||||
|
&& LockedTargets.Length < AmmoCount[GetAmmoType(0)]
|
||||||
|
&& LockedTargets.Length < MAX_LOCKED_TARGETS)
|
||||||
|
{
|
||||||
|
bUpdateServerTargets = FindTargets( RecentlyLocked );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( LockedTargets.Length > 0 )
|
||||||
|
{
|
||||||
|
bUpdateServerTargets = bUpdateServerTargets || ValidateTargets( RecentlyLocked );
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are a client, synchronize our targets with the server
|
||||||
|
if( bUpdateServerTargets && Role < ROLE_Authority )
|
||||||
|
{
|
||||||
|
for( i = 0; i < MAX_LOCKED_TARGETS; ++i )
|
||||||
|
{
|
||||||
|
if( i < LockedTargets.Length )
|
||||||
|
{
|
||||||
|
StaticLockedTargets[i] = LockedTargets[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StaticLockedTargets[i] = none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerSyncLockedTargets( StaticLockedTargets );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an potential target TA determine if we can lock on to it. By default only allow locking on
|
||||||
|
* to pawns.
|
||||||
|
*/
|
||||||
|
simulated function bool CanLockOnTo(Actor TA)
|
||||||
|
{
|
||||||
|
Local KFPawn PawnTarget;
|
||||||
|
|
||||||
|
PawnTarget = KFPawn(TA);
|
||||||
|
|
||||||
|
// Make sure the pawn is legit, isn't dead, and isn't already at full health
|
||||||
|
if ((TA == None) || !TA.bProjTarget || TA.bDeleteMe || (PawnTarget == None) ||
|
||||||
|
(TA == Instigator) || (PawnTarget.Health <= 0) ||
|
||||||
|
!HasAmmo(DEFAULT_FIREMODE))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure and only lock onto players on the same team
|
||||||
|
return !WorldInfo.GRI.OnSameTeam(Instigator, TA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Finds a new lock on target, adds it to the target array and returns TRUE if the array was updated */
|
||||||
|
simulated function bool FindTargets( out Pawn RecentlyLocked )
|
||||||
|
{
|
||||||
|
local Pawn P, BestTargetLock;
|
||||||
|
local byte TeamNum;
|
||||||
|
local vector AimStart, AimDir, TargetLoc, Projection, DirToPawn, LinePoint;
|
||||||
|
local Actor HitActor;
|
||||||
|
local float PointDistSQ, Score, BestScore, TargetSizeSQ;
|
||||||
|
|
||||||
|
TeamNum = Instigator.GetTeamNum();
|
||||||
|
AimStart = GetSafeStartTraceLocation();
|
||||||
|
AimDir = vector( GetAdjustedAim(AimStart) );
|
||||||
|
BestScore = 0.f;
|
||||||
|
|
||||||
|
//Don't add targets if we're already burst firing
|
||||||
|
if (IsInState('WeaponBurstFiring'))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach WorldInfo.AllPawns( class'Pawn', P )
|
||||||
|
{
|
||||||
|
if (!CanLockOnTo(P))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Want alive pawns and ones we already don't have locked
|
||||||
|
if( P != none && P.IsAliveAndWell() && P.GetTeamNum() != TeamNum && LockedTargets.Find(P) == INDEX_NONE )
|
||||||
|
{
|
||||||
|
TargetLoc = GetLockedTargetLoc( P );
|
||||||
|
Projection = TargetLoc - AimStart;
|
||||||
|
DirToPawn = Normal( Projection );
|
||||||
|
|
||||||
|
// Filter out pawns too far from center
|
||||||
|
if( AimDir dot DirToPawn < 0.5f )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to make sure target isn't too far from center
|
||||||
|
PointDistToLine( TargetLoc, AimDir, AimStart, LinePoint );
|
||||||
|
PointDistSQ = VSizeSQ( LinePoint - P.Location );
|
||||||
|
|
||||||
|
TargetSizeSQ = P.GetCollisionRadius() * 2.f;
|
||||||
|
TargetSizeSQ *= TargetSizeSQ;
|
||||||
|
|
||||||
|
if( PointDistSQ > (TargetSizeSQ + MinTargetDistFromCrosshairSQ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure it's not obstructed
|
||||||
|
HitActor = class'KFAIController'.static.ActorBlockTest(self, TargetLoc, AimStart,, true, true);
|
||||||
|
if( HitActor != none && HitActor != P )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Distance from target has much more impact on target selection score
|
||||||
|
Score = VSizeSQ( Projection ) + PointDistSQ;
|
||||||
|
if( BestScore == 0.f || Score < BestScore )
|
||||||
|
{
|
||||||
|
BestTargetLock = P;
|
||||||
|
BestScore = Score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( BestTargetLock != none )
|
||||||
|
{
|
||||||
|
LastTargetLockTime = WorldInfo.TimeSeconds;
|
||||||
|
LockedTargets.AddItem( BestTargetLock );
|
||||||
|
RecentlyLocked = BestTargetLock;
|
||||||
|
|
||||||
|
// Plays sound/FX when locking on to a new target
|
||||||
|
PlayTargetLockOnEffects();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecentlyLocked = none;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks to ensure all of our current locked targets are valid */
|
||||||
|
simulated function bool ValidateTargets( optional Pawn RecentlyLocked )
|
||||||
|
{
|
||||||
|
local int i;
|
||||||
|
local bool bShouldRemoveTarget, bAlteredTargets;
|
||||||
|
local vector AimStart, AimDir, TargetLoc;
|
||||||
|
local Actor HitActor;
|
||||||
|
|
||||||
|
if( `TimeSince(LastTargetValidationCheckTime) < TargetValidationCheckInterval )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LastTargetValidationCheckTime = WorldInfo.TimeSeconds;
|
||||||
|
|
||||||
|
AimStart = GetSafeStartTraceLocation();
|
||||||
|
AimDir = vector( GetAdjustedAim(AimStart) );
|
||||||
|
|
||||||
|
bAlteredTargets = false;
|
||||||
|
for( i = 0; i < LockedTargets.Length; ++i )
|
||||||
|
{
|
||||||
|
// For speed don't bother checking a target we just locked
|
||||||
|
if( RecentlyLocked != none && RecentlyLocked == LockedTargets[i] )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bShouldRemoveTarget = false;
|
||||||
|
|
||||||
|
if( LockedTargets[i] == none
|
||||||
|
|| !LockedTargets[i].IsAliveAndWell() )
|
||||||
|
{
|
||||||
|
bShouldRemoveTarget = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TargetLoc = GetLockedTargetLoc( LockedTargets[i] );
|
||||||
|
if( AimDir dot Normal(LockedTargets[i].Location - AimStart) >= MaxLockMaintainFOVDotThreshold )
|
||||||
|
{
|
||||||
|
HitActor = class'KFAIController'.static.ActorBlockTest( self, TargetLoc, AimStart,, true, true );
|
||||||
|
if( HitActor != none && HitActor != LockedTargets[i] )
|
||||||
|
{
|
||||||
|
bShouldRemoveTarget = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bShouldRemoveTarget = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A target was invalidated, remove it from the list
|
||||||
|
if( bShouldRemoveTarget )
|
||||||
|
{
|
||||||
|
LockedTargets.Remove( i, 1 );
|
||||||
|
--i;
|
||||||
|
bAlteredTargets = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plays sound/FX when losing a target lock, but only if we didn't play a lock on this frame
|
||||||
|
if( bAlteredTargets && RecentlyLocked == none )
|
||||||
|
{
|
||||||
|
PlayTargetLostEffects();
|
||||||
|
}
|
||||||
|
|
||||||
|
return bAlteredTargets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Synchronizes our locked targets with the server */
|
||||||
|
reliable server function ServerSyncLockedTargets( Pawn TargetPawns[MAX_LOCKED_TARGETS] )
|
||||||
|
{
|
||||||
|
local int i;
|
||||||
|
|
||||||
|
LockedTargets.Length = 0;
|
||||||
|
for( i = 0; i < MAX_LOCKED_TARGETS; ++i )
|
||||||
|
{
|
||||||
|
if (TargetPawns[i] != none)
|
||||||
|
{
|
||||||
|
LockedTargets.AddItem(TargetPawns[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adjusts our destination target impact location */
|
||||||
|
static simulated function vector GetLockedTargetLoc( Pawn P )
|
||||||
|
{
|
||||||
|
// Go for the chest, but just in case we don't have something with a chest bone we'll use collision and eyeheight settings
|
||||||
|
if( P.Mesh.SkeletalMesh != none && P.Mesh.bAnimTreeInitialised )
|
||||||
|
{
|
||||||
|
if( P.Mesh.MatchRefBone('Spine2') != INDEX_NONE )
|
||||||
|
{
|
||||||
|
return P.Mesh.GetBoneLocation( 'Spine2' );
|
||||||
|
}
|
||||||
|
else if( P.Mesh.MatchRefBone('Spine1') != INDEX_NONE )
|
||||||
|
{
|
||||||
|
return P.Mesh.GetBoneLocation( 'Spine1' );
|
||||||
|
}
|
||||||
|
|
||||||
|
return P.Mesh.GetPosition() + ((P.CylinderComponent.CollisionHeight + (P.BaseEyeHeight * 0.5f)) * vect(0,0,1)) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// General chest area, fallback
|
||||||
|
return P.Location + ( vect(0,0,1) * P.BaseEyeHeight * 0.75f );
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function ZoomIn(bool bAnimateTransition, float ZoomTimeToGo)
|
||||||
|
{
|
||||||
|
super.ZoomIn(bAnimateTransition, ZoomTimeToGo);
|
||||||
|
|
||||||
|
if (IronsightsZoomInSound != none && Instigator != none && Instigator.IsLocallyControlled())
|
||||||
|
{
|
||||||
|
IronsightsComponent.PlayEvent(IronsightsZoomInSound, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Clear all locked targets when zooming out, both server and client */
|
||||||
|
simulated function ZoomOut( bool bAnimateTransition, float ZoomTimeToGo )
|
||||||
|
{
|
||||||
|
super.ZoomOut( bAnimateTransition, ZoomTimeToGo );
|
||||||
|
|
||||||
|
if (IronsightsZoomOutSound != none && Instigator != none && Instigator.IsLocallyControlled())
|
||||||
|
{
|
||||||
|
IronsightsComponent.PlayEvent(IronsightsZoomOutSound, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Play a target lost effect if we're clearing targets on the way out
|
||||||
|
if( Instigator.IsLocallyControlled() && LockedTargets.Length > 0 )
|
||||||
|
{
|
||||||
|
PlayTargetLostEffects();
|
||||||
|
}
|
||||||
|
LockedTargets.Length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Play FX or sounds when locking on to a new target */
|
||||||
|
simulated function PlayTargetLockOnEffects()
|
||||||
|
{
|
||||||
|
if( Instigator != none && Instigator.IsHumanControlled() )
|
||||||
|
{
|
||||||
|
PlaySoundBase( LockAcquiredSoundFirstPerson, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Play FX or sounds when losing a target lock */
|
||||||
|
simulated function PlayTargetLostEffects()
|
||||||
|
{
|
||||||
|
if( Instigator != none && Instigator.IsHumanControlled() )
|
||||||
|
{
|
||||||
|
PlaySoundBase( LockLostSoundFirstPerson, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************
|
||||||
|
* @name Projectile Spawning
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
/** Spawn projectile is called once for each rocket fired. In burst mode it will cycle through targets until it runs out */
|
||||||
|
simulated function KFProjectile SpawnProjectile( class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir )
|
||||||
|
{
|
||||||
|
local KFProj_HRG_Locust LocustProj;
|
||||||
|
|
||||||
|
if( CurrentFireMode == GRENADE_FIREMODE )
|
||||||
|
{
|
||||||
|
return super.SpawnProjectile( KFProjClass, RealStartLoc, AimDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to set our target if we are firing from a locked on position
|
||||||
|
if( bUsingSights
|
||||||
|
&& CurrentFireMode == ALTFIRE_FIREMODE
|
||||||
|
&& LockedTargets.Length > 0 )
|
||||||
|
{
|
||||||
|
// We'll aim our rocket at a target here otherwise we will spawn a dumbfire rocket at the end of the function
|
||||||
|
if( LockedTargets.Length > 0 )
|
||||||
|
{
|
||||||
|
// Spawn our projectile and set its target
|
||||||
|
LocustProj = KFProj_HRG_Locust( super.SpawnProjectile(KFProjClass, RealStartLoc, AimDir) );
|
||||||
|
if( LocustProj != none )
|
||||||
|
{
|
||||||
|
//Seek to new target, then remove from list. Always use first target in the list for new fire.
|
||||||
|
LocustProj.SetLockedTarget( KFPawn(LockedTargets[0]) );
|
||||||
|
LockedTargets.Remove(0, 1);
|
||||||
|
|
||||||
|
return LocustProj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.SpawnProjectile( KFProjClass, RealStartLoc, AimDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************
|
||||||
|
* @name Targeting HUD -- Partially adapted from KFWeap_Rifle_RailGun
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
/** Handle drawing our custom lock on HUD */
|
||||||
|
simulated function DrawHUD( HUD H, Canvas C )
|
||||||
|
{
|
||||||
|
local int i;
|
||||||
|
|
||||||
|
if( !bUsingSights || LockedTargets.Length == 0 )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw target locked icons
|
||||||
|
C.EnableStencilTest( true );
|
||||||
|
for( i = 0; i < LockedTargets.Length; ++i )
|
||||||
|
{
|
||||||
|
if( LockedTargets[i] != none )
|
||||||
|
{
|
||||||
|
DrawTargetingIcon( C, i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
C.EnableStencilTest( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Draws a targeting icon for each one of our locked targets */
|
||||||
|
simulated function DrawTargetingIcon( Canvas Canvas, int Index )
|
||||||
|
{
|
||||||
|
local vector WorldPos, ScreenPos;
|
||||||
|
local float IconSize, IconScale;
|
||||||
|
|
||||||
|
// Project world pos to canvas
|
||||||
|
WorldPos = GetLockedTargetLoc( LockedTargets[Index] );
|
||||||
|
ScreenPos = Canvas.Project( WorldPos );//WorldToCanvas(Canvas, WorldPos);
|
||||||
|
|
||||||
|
// calculate scale based on resolution and distance
|
||||||
|
IconScale = fMin( float(Canvas.SizeX) / 1024.f, 1.f );
|
||||||
|
// Scale down up to 40 meters away, with a clamp at 20% size
|
||||||
|
IconScale *= fClamp( 1.f - VSize(WorldPos - Instigator.Location) / 4000.f, 0.2f, 1.f );
|
||||||
|
|
||||||
|
// Apply size scale
|
||||||
|
IconSize = 200.f * IconScale;
|
||||||
|
ScreenPos.X -= IconSize / 2.f;
|
||||||
|
ScreenPos.Y -= IconSize / 2.f;
|
||||||
|
|
||||||
|
// Off-screen check
|
||||||
|
if( ScreenPos.X < 0 || ScreenPos.X > Canvas.SizeX || ScreenPos.Y < 0 || ScreenPos.Y > Canvas.SizeY )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Canvas.SetPos( ScreenPos.X, ScreenPos.Y );
|
||||||
|
|
||||||
|
// Draw the icon
|
||||||
|
Canvas.DrawTile( LockedOnIcon, IconSize, IconSize, 0, 0, LockedOnIcon.SizeX, LockedOnIcon.SizeY, LockedIconColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************
|
||||||
|
* State WeaponSingleFiring
|
||||||
|
* Fire must be released between every shot.
|
||||||
|
*********************************************************************************************/
|
||||||
|
|
||||||
|
simulated state WeaponSingleFiring
|
||||||
|
{
|
||||||
|
simulated function BeginState( Name PrevStateName )
|
||||||
|
{
|
||||||
|
LockedTargets.Length = 0;
|
||||||
|
|
||||||
|
super.BeginState( PrevStateName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************
|
||||||
|
* State WeaponBurstFiring
|
||||||
|
* Fires a burst of bullets. Fire must be released between every shot.
|
||||||
|
*********************************************************************************************/
|
||||||
|
|
||||||
|
simulated state WeaponBurstFiring
|
||||||
|
{
|
||||||
|
simulated function int GetBurstAmount()
|
||||||
|
{
|
||||||
|
// Clamp our bursts to either the number of targets or how much ammo we have remaining
|
||||||
|
return Clamp( LockedTargets.Length, 1, AmmoCount[GetAmmoType(CurrentFireMode)] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Overridden to apply scaled recoil when in multi-rocket mode */
|
||||||
|
simulated function ModifyRecoil( out float CurrentRecoilModifier )
|
||||||
|
{
|
||||||
|
super.ModifyRecoil( CurrentRecoilModifier );
|
||||||
|
|
||||||
|
CurrentRecoilModifier *= BurstFireRecoilModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function bool ShouldRefire()
|
||||||
|
{
|
||||||
|
return LockedTargets.Length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated function FireAmmunition()
|
||||||
|
{
|
||||||
|
super.FireAmmunition();
|
||||||
|
if (Role < ROLE_Authority)
|
||||||
|
{
|
||||||
|
LockedTargets.Remove(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simulated event EndState( Name NextStateName )
|
||||||
|
{
|
||||||
|
LockedTargets.Length = 0;
|
||||||
|
|
||||||
|
super.EndState( NextStateName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reduce the damage received and apply it to the shield
|
||||||
|
*/
|
||||||
|
function AdjustDamage(out int InDamage, class<DamageType> DamageType, Actor DamageCauser)
|
||||||
|
{
|
||||||
|
super.AdjustDamage(InDamage, DamageType, DamageCauser);
|
||||||
|
|
||||||
|
if (Instigator != none && DamageCauser.Instigator == Instigator)
|
||||||
|
{
|
||||||
|
InDamage *= SelfDamageReductionValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
ForceReloadTime=0.4f
|
||||||
|
|
||||||
|
// Inventory
|
||||||
|
InventoryGroup=IG_Primary
|
||||||
|
GroupPriority=100
|
||||||
|
InventorySize=6
|
||||||
|
WeaponSelectTexture=Texture2D'wep_ui_hrg_locust_tex.UI_WeaponSelect_HRG_Locust'
|
||||||
|
|
||||||
|
// FOV
|
||||||
|
MeshFOV=86
|
||||||
|
MeshIronSightFOV=65
|
||||||
|
PlayerIronSightFOV=70
|
||||||
|
PlayerSprintFOV=95
|
||||||
|
|
||||||
|
// Depth of field
|
||||||
|
DOF_FG_FocalRadius=50
|
||||||
|
DOF_FG_MaxNearBlurSize=2.5
|
||||||
|
|
||||||
|
// Zooming/Position
|
||||||
|
PlayerViewOffset=(X=20.0,Y=5,Z=-5)
|
||||||
|
FastZoomOutTime=0.2
|
||||||
|
|
||||||
|
// Content
|
||||||
|
PackageKey="HRG_Locust"
|
||||||
|
FirstPersonMeshName="wep_1p_hrg_locust_mesh.Wep_1stP_HRG_Locust_Rig"
|
||||||
|
FirstPersonAnimSetNames(0)="WEP_1P_HRG_Locust_ANIM.Wep_1stP_HRG_Locust_Anim"
|
||||||
|
PickupMeshName="wep_3p_hrg_locust_mesh.Wep_3rdP_HRG_Locust_Pickup"
|
||||||
|
AttachmentArchetypeName="wep_hrg_locust_arch.Wep_HRG_Locust_3P"
|
||||||
|
MuzzleFlashTemplateName="wep_hrg_locust_arch.Wep_HRG_Locust_MuzzleFlash"
|
||||||
|
|
||||||
|
// Target Locking
|
||||||
|
MinTargetDistFromCrosshairSQ=2500.0f // 0.5 meters
|
||||||
|
TimeBetweenLockOns=0.06f
|
||||||
|
TargetValidationCheckInterval=0.1f
|
||||||
|
MaxLockMaintainFOVDotThreshold=0.36f
|
||||||
|
|
||||||
|
// LockOn Visuals
|
||||||
|
LockedOnIcon=Texture2D'Wep_Scope_TEX.Wep_1stP_Yellow_Red_Target'
|
||||||
|
LockedIconColor=(R=1.f, G=0.f, B=0.f, A=0.5f)
|
||||||
|
|
||||||
|
// Lock On/Lost Sounds
|
||||||
|
LockAcquiredSoundFirstPerson=AkEvent'WW_WEP_SA_Railgun.Play_Railgun_Scope_Locked'
|
||||||
|
LockLostSoundFirstPerson=AkEvent'WW_WEP_SA_Railgun.Play_Railgun_Scope_Lost'
|
||||||
|
|
||||||
|
// Zooming/Position
|
||||||
|
IronSightPosition=(X=0,Y=-0.065,Z=-0.31)
|
||||||
|
|
||||||
|
// Ammo
|
||||||
|
MagazineCapacity[0]=6
|
||||||
|
SpareAmmoCapacity[0]=84
|
||||||
|
InitialSpareMags[0]=3
|
||||||
|
AmmoPickupScale[0]=2.0
|
||||||
|
bCanBeReloaded=true
|
||||||
|
bReloadFromMagazine=true
|
||||||
|
|
||||||
|
// Recoil
|
||||||
|
maxRecoilPitch=400
|
||||||
|
minRecoilPitch=275
|
||||||
|
maxRecoilYaw=200
|
||||||
|
minRecoilYaw=-200
|
||||||
|
RecoilRate=0.085
|
||||||
|
RecoilBlendOutRatio=0.35
|
||||||
|
RecoilMaxYawLimit=500
|
||||||
|
RecoilMinYawLimit=65035
|
||||||
|
RecoilMaxPitchLimit=1500
|
||||||
|
RecoilMinPitchLimit=64785
|
||||||
|
RecoilISMaxYawLimit=50
|
||||||
|
RecoilISMinYawLimit=65485
|
||||||
|
RecoilISMaxPitchLimit=500
|
||||||
|
RecoilISMinPitchLimit=65485
|
||||||
|
RecoilViewRotationScale=0.8
|
||||||
|
FallingRecoilModifier=1.5
|
||||||
|
HippedRecoilModifier=1.25
|
||||||
|
BurstFireRecoilModifier=0.15f // Reduce recoil between rockets when in burst mode
|
||||||
|
|
||||||
|
// DEFAULT_FIREMODE
|
||||||
|
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'UI_FireModes_TEX.UI_FireModeSelect_Rocket'
|
||||||
|
FiringStatesArray(DEFAULT_FIREMODE)=WeaponFiring
|
||||||
|
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile
|
||||||
|
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_HRG_Locust'
|
||||||
|
FireInterval(DEFAULT_FIREMODE)=+0.35
|
||||||
|
InstantHitDamage(DEFAULT_FIREMODE)=1 //140 // 120.0 //100.00
|
||||||
|
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_HRG_Locust'
|
||||||
|
Spread(DEFAULT_FIREMODE)=0.025
|
||||||
|
FireOffset=(X=20,Y=4.0,Z=-3)
|
||||||
|
|
||||||
|
// ALT_FIREMODE
|
||||||
|
FireModeIconPaths(ALTFIRE_FIREMODE)= Texture2D'UI_SecondaryAmmo_TEX.UI_FireModeSelect_AutoTarget'
|
||||||
|
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponBurstFiring
|
||||||
|
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Projectile
|
||||||
|
WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_HRG_Locust'
|
||||||
|
FireInterval(ALTFIRE_FIREMODE)=+0.3 //0.1
|
||||||
|
InstantHitDamage(ALTFIRE_FIREMODE)=1 //140 // 120.0 //100.00
|
||||||
|
InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_HRG_Locust'
|
||||||
|
Spread(ALTFIRE_FIREMODE)=0.025
|
||||||
|
AmmoCost(ALTFIRE_FIREMODE)=1
|
||||||
|
|
||||||
|
// BASH_FIREMODE
|
||||||
|
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HRG_Locust'
|
||||||
|
InstantHitDamage(BASH_FIREMODE)=29
|
||||||
|
|
||||||
|
// Fire Effects
|
||||||
|
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Seeker_6.Play_WEP_Seeker_6_Fire_3P', FirstPersonCue=AkEvent'WW_WEP_Seeker_6.Play_WEP_Seeker_6_Fire_1P')
|
||||||
|
WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Seeker_6.Play_WEP_Seeker_6_Fire_3P', FirstPersonCue=AkEvent'WW_WEP_Seeker_6.Play_WEP_Seeker_6_Fire_1P')
|
||||||
|
WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_SA_RPG7.Play_WEP_SA_RPG7_DryFire'
|
||||||
|
WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_SA_RPG7.Play_WEP_SA_RPG7_DryFire'
|
||||||
|
|
||||||
|
// Animation
|
||||||
|
bHasFireLastAnims=true
|
||||||
|
IdleFidgetAnims=(Guncheck_v1, Guncheck_v2)
|
||||||
|
|
||||||
|
//BonesToLockOnEmpty=(RW_Grenade1)
|
||||||
|
|
||||||
|
// Attachments
|
||||||
|
bHasIronSights=true
|
||||||
|
bHasFlashlight=false
|
||||||
|
|
||||||
|
AssociatedPerkClasses(0)=class'KFPerk_Survivalist'
|
||||||
|
|
||||||
|
WeaponFireWaveForm=ForceFeedbackWaveform'FX_ForceFeedback_ARCH.Gunfire.Heavy_Recoil_SingleShot'
|
||||||
|
|
||||||
|
// Audio
|
||||||
|
Begin Object Class=AkComponent name=IronsightsComponent0
|
||||||
|
bForceOcclusionUpdateInterval=true
|
||||||
|
OcclusionUpdateInterval=0.f // never update occlusion for footsteps
|
||||||
|
bStopWhenOwnerDestroyed=true
|
||||||
|
End Object
|
||||||
|
IronsightsComponent=IronsightsComponent0
|
||||||
|
Components.Add(IronsightsComponent0)
|
||||||
|
IronsightsZoomInSound=AkEvent'WW_WEP_Seeker_6.Play_Seeker_6_Iron_In'
|
||||||
|
IronsightsZoomOutSound=AkEvent'WW_WEP_Seeker_6.Play_Seeker_6_Iron_In_Out'
|
||||||
|
|
||||||
|
// Weapon Upgrade stat boosts
|
||||||
|
//WeaponUpgrades[1]=(IncrementDamage=1.125f,IncrementWeight=1)
|
||||||
|
|
||||||
|
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1)))
|
||||||
|
WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.3f), (Stat=EWUS_Damage1, Scale=1.3f), (Stat=EWUS_Weight, Add=2)))
|
||||||
|
|
||||||
|
SelfDamageReductionValue = 0f;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user