1
0
KF2-Dev-Scripts/KFGameContent/Classes/KFWeap_HRG_Energy.uc

511 lines
15 KiB
Ucode
Raw Normal View History

2021-09-02 21:46:08 +00:00
//=============================================================================
// KFWeap_HRG_Energy
//=============================================================================
//=============================================================================
// Killing Floor 2
// Copyright (C) 2021 Tripwire Interactive LLC
//=============================================================================
class KFWeap_HRG_Energy extends KFWeap_PistolBase;
`define HRG_ENERGY_MIC_LED_INDEX_1 0
`define HRG_ENERGY_MIC_SCREEN_INDEX 1
`define HRG_ENERGY_MIC_LED_INDEX_2 2
/*********************************************************************************************
@name Optics UI
********************************************************************************************* */
var class<KFGFxWorld_MedicOptics> OpticsUIClass;
var KFGFxWorld_MedicOptics OpticsUI;
/** The last updated value for our ammo - Used to know when to update our optics ammo */
var byte StoredPrimaryAmmo;
var byte StoredSecondaryAmmo;
var transient float AltFireMaxShots;
/** Modifier applied to the alt fire animation */
var float SecondaryFireAnimRateModifier;
/** Material colors applied to different fire modes */
var LinearColor DefaultFireMaterialColor;
var LinearColor AltFireMaterialColor;
/** How much recoil the altfire should do */
var protected const float AltFireRecoilScale;
simulated event PreBeginPlay()
{
super.PreBeginPlay();
AltFireMaxShots = MagazineCapacity[DEFAULT_FIREMODE] / AmmoCost[ALTFIRE_FIREMODE];
}
simulated function Activate()
{
super.Activate();
UpdateMaterial(bUseAltFireMode ? ALTFIRE_FIREMODE : DEFAULT_FIREMODE);
}
simulated function UpdateMaterial(byte FireMode)
{
local LinearColor MatColor;
MatColor = FireMode == DEFAULT_FIREMODE ? DefaultFireMaterialColor : AltFireMaterialColor;
if( WeaponMICs.Length > `HRG_ENERGY_MIC_LED_INDEX_1 )
{
WeaponMICs[`HRG_ENERGY_MIC_LED_INDEX_1].SetVectorParameterValue('Vector_GlowColor', MatColor);
}
if (WeaponMICs.Length > `HRG_ENERGY_MIC_SCREEN_INDEX)
{
WeaponMICs[`HRG_ENERGY_MIC_SCREEN_INDEX].SetVectorParameterValue('Color_override', MatColor);
}
if( WeaponMICs.Length > `HRG_ENERGY_MIC_LED_INDEX_2 )
{
WeaponMICs[`HRG_ENERGY_MIC_LED_INDEX_2].SetVectorParameterValue('Vector_GlowColor', MatColor);
}
}
/**
* Check target locking - server-side only
* HealAmmo Regen client and server
*/
simulated event Tick( FLOAT DeltaTime )
{
if (Instigator != none && Instigator.weapon == self)
{
UpdateOpticsUI();
}
Super.Tick(DeltaTime);
}
/*********************************************************************************************
@name Optics UI
********************************************************************************************* */
/** Get our optics movie from the inventory once our InvManager is created */
reliable client function ClientWeaponSet(bool bOptionalSet, optional bool bDoNotActivate)
{
local KFInventoryManager KFIM;
super.ClientWeaponSet(bOptionalSet, bDoNotActivate);
if (OpticsUI == none)
{
KFIM = KFInventoryManager(InvManager);
if (KFIM != none)
{
//Create the screen's UI piece
OpticsUI = KFGFxWorld_MedicOptics(KFIM.GetOpticsUIMovie(OpticsUIClass));
}
}
}
function ItemRemovedFromInvManager()
{
local KFInventoryManager KFIM;
local KFWeap_MedicBase KFW;
Super.ItemRemovedFromInvManager();
if (OpticsUI != none)
{
KFIM = KFInventoryManager(InvManager);
if (KFIM != none)
{
// @todo future implementation will have optics in base weapon class
foreach KFIM.InventoryActors(class'KFWeap_MedicBase', KFW)
{
// This is not a MedicBase, no need to check against itself
if(KFW.OpticsUI.Class == OpticsUI.class)
{
// A different weapon is still using this optics class
return;
}
}
//Create the screen's UI piece
KFIM.RemoveOpticsUIMovie(OpticsUI.class);
OpticsUI.Close();
OpticsUI = none;
}
}
}
/** Unpause our optics movie and reinitialize our ammo when we equip the weapon */
simulated function AttachWeaponTo(SkeletalMeshComponent MeshCpnt, optional Name SocketName)
{
super.AttachWeaponTo(MeshCpnt, SocketName);
if (OpticsUI != none)
{
OpticsUI.SetPause(false);
OpticsUI.ClearLockOn();
UpdateOpticsUI(true);
OpticsUI.SetShotPercentCost( AmmoCost[ALTFIRE_FIREMODE]);
}
}
/** Pause the optics movie once we unequip the weapon so it's not playing in the background */
simulated function DetachWeapon()
{
local Pawn OwnerPawn;
super.DetachWeapon();
OwnerPawn = Pawn(Owner);
if( OwnerPawn != none && OwnerPawn.Weapon == self )
{
if (OpticsUI != none)
{
OpticsUI.SetPause();
}
}
}
/**
* Update our displayed ammo count if it's changed
*/
simulated function UpdateOpticsUI(optional bool bForceUpdate)
{
if (OpticsUI != none && OpticsUI.OpticsContainer != none)
{
if (AmmoCount[DEFAULT_FIREMODE] != StoredPrimaryAmmo || bForceUpdate)
{
StoredPrimaryAmmo = AmmoCount[DEFAULT_FIREMODE];
OpticsUI.SetPrimaryAmmo(StoredPrimaryAmmo);
if(AmmoCount[DEFAULT_FIREMODE] < AmmoCost[ALTFIRE_FIREMODE])
{
OpticsUI.SetHealerCharge(0);
}
else
{
OpticsUI.SetHealerCharge((AmmoCount[DEFAULT_FIREMODE] / AmmoCost[ALTFIRE_FIREMODE]) / AltFireMaxShots * 100);
}
}
if(OpticsUI.MinPercentPerShot != AmmoCost[ALTFIRE_FIREMODE])
{
OpticsUI.SetShotPercentCost( AmmoCost[ALTFIRE_FIREMODE] );
}
}
}
/** Healing charge doesn't count as ammo for purposes of inventory management (e.g. switching) */
simulated function bool HasAnyAmmo()
{
return HasSpareAmmo() || HasAmmo(DEFAULT_FIREMODE) || HasSpareAmmo(ALTFIRE_FIREMODE) || HasAmmo(ALTFIRE_FIREMODE);
}
simulated function StartFire(byte FireModeNum)
{
if (FireModeNum == DEFAULT_FIREMODE && bUseAltFireMode)
{
if (AmmoCount[FireModeNum] < AmmoCost[ALTFIRE_FIREMODE] && SpareAmmoCount[FireModeNum] > 0)
{
BeginFire(RELOAD_FIREMODE);
return;
}
}
super.StartFire(FireModeNum);
}
simulated function AltFireMode()
{
if ( !Instigator.IsLocallyControlled() )
{
return;
}
if ( !bUseAltFireMode && SpareAmmoCount[0] + AmmoCount[0] < AmmoCost[1] )
{
return;
}
super.AltFireMode();
UpdateMaterial(bUseAltFireMode ? ALTFIRE_FIREMODE : DEFAULT_FIREMODE);
NotifyAltFireUsage();
}
/** Overriden to use WeaponAnimSeqNode */
simulated function PlayWeaponAnimation(name Sequence, float fDesiredDuration, optional bool bLoop, optional SkeletalMeshComponent SkelMesh)
{
local float DesiredRate;
if ( Mesh != none && Instigator != none && WorldInfo.NetMode != NM_DedicatedServer )
{
if ( WeaponAnimSeqNode != None )
{
if (WeaponAnimSeqNode.AnimSeq == None || WeaponAnimSeqNode.AnimSeq.SequenceName != Sequence)
{
WeaponAnimSeqNode.SetAnim(Sequence);
}
if(fDesiredDuration > 0.0 && WeaponAnimSeqNode.AnimSeq.RateScale > 0.0)
{
DesiredRate = WeaponAnimSeqNode.AnimSeq.SequenceLength / (fDesiredDuration * WeaponAnimSeqNode.AnimSeq.RateScale);
WeaponAnimSeqNode.PlayAnim(bLoop, DesiredRate);
}
else
{
WeaponAnimSeqNode.PlayAnim(bLoop, DefaultAnimSpeed);
}
}
}
}
/**
* PlayFireEffects Is the root function that handles all of the effects associated with
* a weapon. This function creates the 1st person effects. It should only be called
* on a locally controlled player.
*/
simulated function PlayFireEffects( byte FireModeNum, optional vector HitLocation )
{
local name WeaponFireAnimName;
local KFPerk CurrentPerk;
local float TempTweenTime, AdjustedAnimLength;
// If we have stopped the looping fire sound to play single fire sounds for zed time
// start the looping sound back up again when the time is back above zed time speed
if( FireModeNum < bLoopingFireSnd.Length && bLoopingFireSnd[FireModeNum] && !bPlayingLoopingFireSnd )
{
StartLoopingFireSound(FireModeNum);
}
PlayFiringSound(CurrentFireMode);
if( Instigator != none )
{
// Tell our pawn about any changes in animation speed
UpdateWeaponAttachmentAnimRate( GetThirdPersonAnimRate() );
if( Instigator.IsLocallyControlled() )
{
if( Instigator.IsFirstPerson() )
{
if ( !bPlayingLoopingFireAnim )
{
WeaponFireAnimName = GetWeaponFireAnim(FireModeNum);
if ( WeaponFireAnimName != '' )
{
AdjustedAnimLength = MySkelMesh.GetAnimLength(WeaponFireAnimName);
TempTweenTime = FireTweenTime;
if (FireModeNum == ALTFIRE_FIREMODE)
{
AdjustedAnimLength *= SecondaryFireAnimRateModifier;
}
CurrentPerk = GetPerk();
if( CurrentPerk != none )
{
CurrentPerk.ModifyRateOfFire( AdjustedAnimLength, self );
// We need to unlock the slide if we fire from zero ammo while uber ammo is active
if( EmptyMagBlendNode != none
&& BonesToLockOnEmpty.Length > 0
&& AmmoCount[GetAmmoType(FireModeNum)] == 0
&& CurrentPerk.GetIsUberAmmoActive(self) )
{
EmptyMagBlendNode.SetBlendTarget( 0, 0 );
TempTweenTime = 0.f;
}
}
PlayAnimation(WeaponFireAnimName, AdjustedAnimLength,, TempTweenTime);
}
}
// Start muzzle flash effect
CauseMuzzleFlash(FireModeNum);
}
HandleRecoil();
ShakeView();
if (AmmoCount[0] == 0 && ForceReloadTimeOnEmpty > 0)
{
SetTimer(ForceReloadTimeOnEmpty, false, nameof(ForceReload));
}
}
}
}
simulated function ModifyRecoil( out float CurrentRecoilModifier )
{
if( CurrentFireMode == ALTFIRE_FIREMODE )
{
CurrentRecoilModifier *= AltFireRecoilScale;
}
super.ModifyRecoil( CurrentRecoilModifier );
}
simulated function NotifyAltFireUsage()
{
local KFPawn_Human KFPH;
// Notify 3P to change material.
KFPH = KFPawn_Human(Instigator);
if (KFPH != none)
{
KFPH.SetUsingAltFireMode(bUseAltFireMode, true);
KFPH.bNetDirty = true;
}
}
simulated state WeaponEquipping
{
simulated function BeginState(Name PreviousStateName)
{
super.BeginState(PreviousStateName);
// NotifyAltFireUsage();
if (WorldInfo.NetMode == NM_Client || WorldInfo.NetMode == NM_Standalone)
{
SetTimer(1.0f, false, nameof(NotifyAltFireUsage));
}
}
}
/** Returns animation to play based on reload type and status */
simulated function name GetReloadAnimName( bool bTacticalReload )
{
return bTacticalReload ? ReloadNonEmptyMagEliteAnim : ReloadNonEmptyMagAnim;
}
simulated function ConsumeAmmo( byte FireModeNum )
{
super.ConsumeAmmo(FireModeNum);
if( bUseAltFireMode && SpareAmmoCount[0] + AmmoCount[0] < AmmoCost[1] )
{
bUseAltFireMode = false;
UpdateMaterial(DEFAULT_FIREMODE);
NotifyAltFireUsage();
}
}
defaultproperties
{
// Inventory
InventoryGroup=IG_Secondary
InventorySize=4
GroupPriority=125
bCanThrow=true
bDropOnDeath=true
WeaponSelectTexture=Texture2D'WEP_UI_HRG_Energy_TEX.UI_WeaponSelect_HRG_Energy'
SecondaryAmmoTexture=Texture2D'UI_SecondaryAmmo_TEX.MedicDarts'
AssociatedPerkClasses(0)=class'KFPerk_Gunslinger'
// Shooting Animations
FireSightedAnims[0]=Shoot_Iron
FireSightedAnims[1]=Shoot_Iron2
FireSightedAnims[2]=Shoot_Iron3
// FOV
MeshFOV=86
MeshIronSightFOV=77
PlayerIronSightFOV=77
// Depth of field
DOF_FG_FocalRadius=40
DOF_FG_MaxNearBlurSize=3.5
// Zooming/Position
PlayerViewOffset=(X=29.0,Y=13,Z=-4)
//Content
PackageKey="HRG_Energy"
FirstPersonMeshName="WEP_1P_HRG_Energy_MESH.Wep_1stP_HRG_Energy_Rig"
FirstPersonAnimSetNames(0)="WEP_1P_HRG_Energy_ANIM.WEP_1P_HRG_Energy_ANIM"
PickupMeshName="wep_3p_HRG_Energy_mesh.Wep_HRG_Energy_Pickup"
AttachmentArchetypeName="WEP_HRG_Energy_ARCH.Wep_HRG_Energy_3P"
MuzzleFlashTemplateName="WEP_HRG_Energy_ARCH.Wep_HRG_Energy_MuzzleFlash"
OpticsUIClass=class'KFGFxWorld_MedicOptics'
// Zooming/Position
IronSightPosition=(X=15,Y=0,Z=0)
// Ammo
MagazineCapacity[0]=15
2021-11-16 17:03:42 +00:00
SpareAmmoCapacity[0]=120 //135
2021-09-02 21:46:08 +00:00
InitialSpareMags[0]=2
bCanBeReloaded=true
bReloadFromMagazine=true
MagazineCapacity[1]=0
bCanRefillSecondaryAmmo=false
// Recoil
maxRecoilPitch=475 //250
minRecoilPitch=425 //200
maxRecoilYaw=130 //100
minRecoilYaw=-130 //-100
RecoilRate=0.07
RecoilMaxYawLimit=500
RecoilMinYawLimit=65035
RecoilMaxPitchLimit=900
RecoilMinPitchLimit=65035
RecoilISMaxYawLimit=50
RecoilISMinYawLimit=65485
RecoilISMaxPitchLimit=250
RecoilISMinPitchLimit=65485
AltFireRecoilScale=2.0f
// DEFAULT_FIREMODE
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletSingle'
FiringStatesArray(DEFAULT_FIREMODE)=WeaponSingleFiring
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_InstantHit
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_HRG_Energy'
FireInterval(DEFAULT_FIREMODE)=+0.175 //342 RPM
PenetrationPower(DEFAULT_FIREMODE)=1.0
2021-11-16 17:03:42 +00:00
InstantHitDamage(DEFAULT_FIREMODE)=80 //90.0 //125.0
2021-09-02 21:46:08 +00:00
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_HRG_Energy_Primary'
Spread(DEFAULT_FIREMODE)=0.015
FireOffset=(X=20,Y=4.0,Z=-3)
// ALTFIRE_FIREMODE
FireModeIconPaths(ALTFIRE_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Electricity'
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponFiring
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_InstantHit
FireInterval(ALTFIRE_FIREMODE)=+0.705 //85 RPM
WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Bullet_HRG_Energy_Secondary'
InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_HRG_Energy_Secondary'
InstantHitMomentum(ALTFIRE_FIREMODE)=1.0
PenetrationPower(ALTFIRE_FIREMODE)=3.0
2021-11-16 17:03:42 +00:00
InstantHitDamage(ALTFIRE_FIREMODE)=120.0 // 300.0 //475.0
2021-09-02 21:46:08 +00:00
PenetrationDamageReductionCurve(ALTFIRE_FIREMODE)=(Points=((InVal=0.f,OutVal=0.f),(InVal=1.f, OutVal=1.f)))
AmmoCost(ALTFIRE_FIREMODE)=3
// BASH_FIREMODE
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HRG_Energy'
InstantHitDamage(BASH_FIREMODE)=26
// Fire Effects
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'ww_wep_hrg_energy.Play_WEP_HRG_Energy_3P_Shoot', FirstPersonCue=AkEvent'ww_wep_hrg_energy.Play_WEP_HRG_Energy_1P_Shoot')
WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'ww_wep_hrg_energy.Play_WEP_HRG_Energy_3P_ShootAlt', FirstPersonCue=AkEvent'ww_wep_hrg_energy.Play_WEP_HRG_Energy_1P_ShootAlt')
WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_SA_MedicPistol.Play_SA_MedicPistol_Handling_DryFire'
WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_SA_MedicDart.Play_WEP_SA_Medic_Dart_DryFire'
// Attachments
bHasIronSights=true
bHasFlashlight=false
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1)))
SecondaryFireAnimRateModifier = 2.0f;
DefaultFireMaterialColor=(R=0.90f,G=0.26f,B=0.0f)
AltFireMaterialColor=(R=0.7f,G=0.04f,B=0.9f)
NumBloodMapMaterials=3
// bForceHandleImpacts=true;
}