1
0
KF2-Dev-Scripts/KFGameContent/Classes/KFWeap_HuskCannon.uc
2024-01-23 19:25:12 +03:00

518 lines
14 KiB
Ucode

//=============================================================================
// KFWeap_Flame_HuskCannon
//=============================================================================
// Husk Cannon weapon code
//=============================================================================
// Killing Floor 2
// Copyright (C) 2017 Tripwire Interactive LLC
//=============================================================================
class KFWeap_HuskCannon extends KFWeapon;
//Props related to charging the weapon
var float MaxChargeTime;
var float ValueIncreaseTime;
var float DmgIncreasePerCharge;
var float AOEIncreasePerCharge;
var float IncapIncreasePerCharge;
var int AmmoIncreasePerCharge;
var transient float ChargeTime;
var transient float ConsumeAmmoTime;
var transient float MaxChargeLevel;
var ParticleSystem ChargingEffect;
var ParticleSystem ChargedEffect;
var const ParticleSystem MuzzleFlashEffectL1;
var const ParticleSystem MuzzleFlashEffectL2;
var const ParticleSystem MuzzleFlashEffectL3;
var transient ParticleSystemComponent ChargingPSC;
var transient bool bIsFullyCharged;
var const WeaponFireSndInfo FullyChargedSound;
var float FullChargedTimerInterval;
static simulated event EFilterTypeUI GetTraderFilter()
{
return FT_Flame;
}
static simulated function float CalculateTraderWeaponStatDamage()
{
local float CalculatedDamage;
local class<KFDamageType> DamageType;
local GameExplosion ExplosionInstance;
ExplosionInstance = class<KFProjectile>(default.WeaponProjectiles[DEFAULT_FIREMODE]).default.ExplosionTemplate;
CalculatedDamage = default.InstantHitDamage[DEFAULT_FIREMODE] + ExplosionInstance.Damage;
DamageType = class<KFDamageType>(ExplosionInstance.MyDamageType);
if (DamageType != none && DamageType.default.DoT_Type != DOT_None)
{
CalculatedDamage += (DamageType.default.DoT_Duration / DamageType.default.DoT_Interval) * (CalculatedDamage * DamageType.default.DoT_DamageScale);
}
return CalculatedDamage;
}
/**
* @see Weapon::ConsumeAmmo
*/
simulated function ConsumeAmmo(byte FireModeNum)
{
local KFPerk InstigatorPerk;
`if(`notdefined(ShippingPC))
if (bInfiniteAmmo)
{
return;
}
`endif
InstigatorPerk = GetPerk();
if (InstigatorPerk != none && InstigatorPerk.GetIsUberAmmoActive(self)) //check for pyro maniac
{
return;
}
// If AmmoCount is being replicated, don't allow the client to modify it here
if (Role == ROLE_Authority || bAllowClientAmmoTracking)
{
super.ConsumeAmmo(FireModeNum);
}
}
simulated function StartFire(byte FiremodeNum)
{
if (IsTimerActive('RefireCheckTimer'))
{
return;
}
super.StartFire(FiremodeNum);
}
simulated function OnStartFire()
{
local KFPawn PawnInst;
PawnInst = KFPawn(Instigator);
if (PawnInst != none)
{
PawnInst.OnStartFire();
}
}
simulated function FireAmmunition()
{
// Let the accuracy tracking system know that we fired
HandleWeaponShotTaken(CurrentFireMode);
// Handle the different fire types
switch (WeaponFireTypes[CurrentFireMode])
{
case EWFT_InstantHit:
// Launch a projectile if we are in zed time, and this weapon has a projectile to launch for this mode
if (`IsInZedTime(self) && WeaponProjectiles[CurrentFireMode] != none )
{
ProjectileFire();
}
else
{
InstantFireClient();
}
break;
case EWFT_Projectile:
ProjectileFire();
break;
case EWFT_Custom:
CustomFire();
break;
}
// If we're firing without charging, still consume one ammo
if (GetChargeLevel() < 1)
{
ConsumeAmmo(CurrentFireMode);
}
NotifyWeaponFired(CurrentFireMode);
// Play fire effects now (don't wait for WeaponFired to replicate)
PlayFireEffects(CurrentFireMode, vect(0, 0, 0));
}
simulated state HuskCannonCharge extends WeaponFiring
{
//For minimal code purposes, I'll directly call global.FireAmmunition after charging is released
simulated function FireAmmunition()
{}
//Store start fire time so we don't have to timer this
simulated event BeginState(Name PreviousStateName)
{
super.BeginState(PreviousStateName);
ChargeTime = 0;
ConsumeAmmoTime = 0;
MaxChargeLevel = int(MaxChargeTime / ValueIncreaseTime);
if (ChargingPSC == none)
{
ChargingPSC = new(self) class'ParticleSystemComponent';
if(MySkelMesh != none)
{
MySkelMesh.AttachComponentToSocket(ChargingPSC, 'MuzzleFlash');
}
else
{
AttachComponent(ChargingPSC);
}
}
else
{
ChargingPSC.ActivateSystem();
}
bIsFullyCharged = false;
global.OnStartFire();
if(ChargingPSC != none)
{
ChargingPSC.SetTemplate(ChargingEffect);
}
}
simulated function bool ShouldRefire()
{
// ignore how much ammo is left (super/global counts ammo)
return StillFiring(CurrentFireMode);
}
simulated event Tick(float DeltaTime)
{
local float ChargeRTPC;
global.Tick(DeltaTime);
// Don't charge unless we're holding down the button
if (PendingFire(CurrentFireMode))
{
ConsumeAmmoTime += DeltaTime;
}
if (bIsFullyCharged)
{
if (ConsumeAmmoTime >= FullChargedTimerInterval)
{
//ConsumeAmmo(DEFAULT_FIREMODE);
ConsumeAmmoTime -= FullChargedTimerInterval;
}
return;
}
// Don't charge unless we're holding down the button
if (PendingFire(CurrentFireMode))
{
ChargeTime += DeltaTime;
}
ChargeRTPC = FMin(ChargeTime / MaxChargeTime, 1.f);
KFPawn(Instigator).SetWeaponComponentRTPCValue("Weapon_Charge", ChargeRTPC); //For looping component
Instigator.SetRTPCValue('Weapon_Charge', ChargeRTPC); //For one-shot sounds
if (ConsumeAmmoTime >= ValueIncreaseTime)
{
ConsumeAmmo(DEFAULT_FIREMODE);
ConsumeAmmoTime -= ValueIncreaseTime;
}
if (ChargeTime >= MaxChargeTime || !HasAmmo(DEFAULT_FIREMODE))
{
bIsFullyCharged = true;
ChargingPSC.SetTemplate(ChargedEffect);
KFPawn(Instigator).SetWeaponAmbientSound(FullyChargedSound.DefaultCue, FullyChargedSound.FirstPersonCue);
}
}
//Now that we're done charging, directly call FireAmmunition. This will handle the actual projectile fire and scaling.
simulated event EndState(Name NextStateName)
{
ClearZedTimeResist();
ClearPendingFire(CurrentFireMode);
ClearTimer(nameof(RefireCheckTimer));
KFPawn(Instigator).bHasStartedFire = false;
KFPawn(Instigator).bNetDirty = true;
if (ChargingPSC != none)
{
ChargingPSC.DeactivateSystem();
}
KFPawn(Instigator).SetWeaponAmbientSound(none);
}
simulated function HandleFinishedFiring()
{
global.FireAmmunition();
if (bPlayingLoopingFireAnim)
{
StopLoopingFireEffects(CurrentFireMode);
}
if (MuzzleFlash != none)
{
SetTimer(MuzzleFlash.MuzzleFlash.Duration, false, 'Timer_StopFireEffects');
}
else
{
SetTimer(0.3f, false, 'Timer_StopFireEffects');
}
NotifyWeaponFinishedFiring(CurrentFireMode);
super.HandleFinishedFiring();
}
}
// Placing the actual Weapon Firing end state here since we need it to happen at the end of the actual firing loop.
simulated function Timer_StopFireEffects()
{
// Simulate weapon firing effects on the local client
if (WorldInfo.NetMode == NM_Client)
{
Instigator.WeaponStoppedFiring(self, false);
}
ClearFlashCount();
ClearFlashLocation();
}
simulated function KFProjectile SpawnProjectile(class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir)
{
local KFProj_HuskCannon_Fireball HuskBall;
local int Charges;
HuskBall = KFProj_HuskCannon_Fireball(super.SpawnProjectile(KFProjClass, RealStartLoc, AimDir));
//Calc and set scaling values
if (HuskBall != none)
{
Charges = GetChargeLevel();
HuskBall.DamageScale = 1.f + DmgIncreasePerCharge * Charges;
HuskBall.AOEScale = 1.f + AOEIncreasePerCharge * Charges;
HuskBall.IncapScale = 1.f + IncapIncreasePerCharge * Charges;
return HuskBall;
}
return none;
}
simulated function CauseMuzzleFlash(byte FireModeNum)
{
if (MuzzleFlash == None)
{
AttachMuzzleFlash();
}
if (MuzzleFlash != none)
{
switch (GetChargeFXLevel())
{
case 1:
MuzzleFlash.MuzzleFlash.ParticleSystemTemplate = MuzzleFlashEffectL1;
MuzzleFlash.MuzzleFlash.PSC.SetTemplate(MuzzleFlashEffectL1);
break;
case 2:
MuzzleFlash.MuzzleFlash.ParticleSystemTemplate = MuzzleFlashEffectL2;
MuzzleFlash.MuzzleFlash.PSC.SetTemplate(MuzzleFlashEffectL2);
break;
case 3:
MuzzleFlash.MuzzleFlash.ParticleSystemTemplate = MuzzleFlashEffectL3;
MuzzleFlash.MuzzleFlash.PSC.SetTemplate(MuzzleFlashEffectL3);
break;
}
}
super.CauseMuzzleFlash(FireModeNum);
}
simulated function int GetChargeLevel()
{
return Min(ChargeTime / ValueIncreaseTime, MaxChargeLevel);
}
// Should generally match up with KFWeapAttach_HuskCannon::GetChargeFXLevel
simulated function int GetChargeFXLevel()
{
local int ChargeLevel;
ChargeLevel = GetChargeLevel();
if (ChargeLevel < 1)
{
return 1;
}
else if (ChargeLevel < MaxChargeLevel)
{
return 2;
}
else
{
return 3;
}
}
// increase the instant hit damage based on the charge level
simulated function int GetModifiedDamage(byte FireModeNum, optional vector RayDir)
{
local int ModifiedDamage;
ModifiedDamage = super.GetModifiedDamage(FireModeNum, RayDir);
if (FireModeNum == DEFAULT_FIREMODE)
{
ModifiedDamage = ModifiedDamage * (1.f + DmgIncreasePerCharge * GetChargeLevel());
}
return ModifiedDamage;
}
defaultproperties
{
//Gameplay Props
MaxChargeTime=1.0
ValueIncreaseTime=0.2
DmgIncreasePerCharge=0.8
AOEIncreasePerCharge=0.6
IncapIncreasePerCharge=0.22
AmmoIncreasePerCharge=1
// Shooting Animations
FireSightedAnims[0]=Shoot
FireSightedAnims[1]=Shoot_Heavy_Iron
FireLoopSightedAnim=ShootLoop_Iron
FireLoopEndAnim=ShootLoop_End
FireLoopEndSightedAnim=ShootLoop_Iron_End
// FOV
Meshfov=80
MeshIronSightFOV=65 //52
PlayerIronSightFOV=50 //80
// Depth of field
DOF_FG_FocalRadius=150
DOF_FG_MaxNearBlurSize=1
// Content
PackageKey="HuskCannon"
FirstPersonMeshName="WEP_1P_HuskCannon_MESH.Wep_1stP_HuskCannon_Rig"
FirstPersonAnimSetNames(0)="WEP_1P_HuskCannon_ANIM.Wep_1stP_HuskCannon_Anim"
PickupMeshName="wep_3p_huskcannon_mesh.Wep_3rdP_HuskCannon_Pickup"
AttachmentArchetypeName="WEP_HuskCannon_ARCH.Wep_HuskCannon_3P"
MuzzleFlashTemplateName="WEP_HuskCannon_ARCH.Wep_HuskCannon_MuzzleFlash"
// Zooming/Position
PlayerViewOffset=(X=20.0,Y=12,Z=-1)
IronSightPosition=(X=0,Y=0,Z=-0.18)
// Ammo
MagazineCapacity[0]=30
SpareAmmoCapacity[0]=150
InitialSpareMags[0]=1
AmmoPickupScale[0]=0.75
bCanBeReloaded=true
bReloadFromMagazine=true
// Recoil
maxRecoilPitch=150
minRecoilPitch=115
maxRecoilYaw=115
minRecoilYaw=-115
RecoilRate=0.085
RecoilMaxYawLimit=500
RecoilMinYawLimit=65035
RecoilMaxPitchLimit=900
RecoilMinPitchLimit=65035
RecoilISMaxYawLimit=75
RecoilISMinYawLimit=65460
RecoilISMaxPitchLimit=375
RecoilISMinPitchLimit=65460
RecoilViewRotationScale=0.25
IronSightMeshFOVCompensationScale=1.5
HippedRecoilModifier=1.5
// Inventory
InventorySize=8
GroupPriority=75
WeaponSelectTexture=Texture2D'WEP_UI_HuskCannon_TEX.UI_WeaponSelect_HuskCannon' //@TODO: Replace me
// DEFAULT_FIREMODE
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Grenade' //@TODO: Replace me
FiringStatesArray(DEFAULT_FIREMODE)=HuskCannonCharge
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile
Spread(DEFAULT_FIREMODE) = 0.0085
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_HuskCannon_Fireball'
FireInterval(DEFAULT_FIREMODE)=+0.223 //269 RPMs
InstantHitDamage(DEFAULT_FIREMODE)=40
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Explosive_HuskCannonImpact'
FireOffset=(X=30,Y=4.5,Z=-5)
WeaponFireTypes(ALTFIRE_FIREMODE) = EWFT_None
// BASH_FIREMODE
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HuskCannon'
InstantHitDamage(BASH_FIREMODE)=28
// Fire Effects
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Husk_Cannon.Play_WEP_Husk_Cannon_3P_Start', FirstPersonCue=AkEvent'WW_WEP_Husk_Cannon.Play_WEP_Husk_Cannon_1P_Start')
WeaponFireLoopEndSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Husk_Cannon.Play_WEP_Husk_Cannon_3P_Fire', FirstPersonCue=AkEvent'WW_WEP_Husk_Cannon.Play_WEP_Husk_Cannon_1P_Fire')
FullyChargedSound=(DefaultCue = AkEvent'WW_WEP_Husk_Cannon.Play_WEP_Husk_Cannon_Charged_3P', FirstPersonCue=AkEvent'WW_WEP_Husk_Cannon.Play_WEP_Husk_Cannon_Charged')
WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_SA_Flamethrower.Play_WEP_SA_Flamethrower_Handling_DryFire' //@TODO: Replace me
WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_SA_Flamethrower.Play_WEP_SA_Flamethrower_Handling_DryFire' //@TODO: Replace me
// Advanced (High RPM) Fire Effects
bLoopingFireAnim(DEFAULT_FIREMODE)=true
bLoopingFireSnd(DEFAULT_FIREMODE)=true
SingleFireSoundIndex=FIREMODE_NONE
bLoopingFireAnim(ALTFIRE_FIREMODE)=false
bLoopingFireSnd(ALTFIRE_FIREMODE)=false
Spread(ALTFIRE_FIREMODE) = 0.0085
// Attachments
bHasIronSights=true
bHasFlashlight=false
AssociatedPerkClasses(0)= class'KFPerk_Firebug'
AssociatedPerkClasses(1)= class'KFPerk_Demolitionist'
WeaponFireWaveForm=ForceFeedbackWaveform'FX_ForceFeedback_ARCH.Gunfire.Weak_Recoil'
ChargingEffect=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Charging_01'
ChargedEffect=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_Charged_01'
MuzzleFlashEffectL1=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_MuzzleFlash_L1_1P'
MuzzleFlashEffectL2=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_MuzzleFlash_L2_1P'
MuzzleFlashEffectL3=ParticleSystem'WEP_HuskCannon_EMIT.FX_Huskcannon_MuzzleFlash_L3_1P'
FullChargedTimerInterval=2.0f
// Weapon Upgrade stat boosts
//WeaponUpgrades[1]=(IncrementDamage=1.1f,IncrementWeight=1)
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.1f), (Stat=EWUS_Weight, Add=1)))
}