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

494 lines
13 KiB
Ucode
Raw Normal View History

2020-12-13 15:01:13 +00:00
//=============================================================================
// KFWeap_Thrown_C4
//=============================================================================
// C4 explosives
//=============================================================================
// Killing Floor 2
// Copyright (C) 2014-2015 Tripwire Interactive LLC
// Greg Felber / Jeff Robinson
//=============================================================================
class KFWeap_Thrown_C4 extends KFWeap_ThrownBase;
const DETONATE_FIREMODE = 5; // NEW - IronSights Key
var(Animations) const editconst name DetonateAnim;
var(Animations) const editconst name DetonateLastAnim;
/** List of spawned charges (will be detonated oldest to youngest) */
var array<KFProj_Thrown_C4> DeployedCharges;
var class<KFGFxWorld_C4Screen> ScreenUIClass;
var KFGFxWorld_C4Screen ScreenUI;
var float TimeSinceLastUpdate;
var float UpdateInterval; //Seconds
/** Sound to play upon successful detonation */
var() AkEvent DetonateAkEvent;
/** Sound to play upon attempted but unsuccessful detonation */
var() AkEvent DryFireAkEvent;
/** Same as DeployedCharges.Length, but replicated because charges are only tracked on server */
var int NumDeployedCharges;
replication
{
if( bNetDirty )
NumDeployedCharges;
}
/** Route ironsight player input to detonate */
simulated function SetIronSights(bool bNewIronSights)
{
if ( !Instigator.IsLocallyControlled() )
{
return;
}
if ( bNewIronSights )
{
StartFire(DETONATE_FIREMODE);
}
else
{
StopFire(DETONATE_FIREMODE);
}
}
/** Turn on the UI screen when we equip the healer */
simulated function AttachWeaponTo( SkeletalMeshComponent MeshCpnt, optional Name SocketName )
{
super.AttachWeaponTo( MeshCpnt, SocketName );
if( Instigator != none && Instigator.IsLocallyControlled() )
{
// Create the screen's UI piece
if (ScreenUI == none)
{
ScreenUI = new( self ) ScreenUIClass;
ScreenUI.Init();
ScreenUI.Start(true);
}
if ( ScreenUI != none)
{
ScreenUI.SetPause(false);
}
}
}
/** Turn off the UI screen when we unequip the weapon */
simulated function DetachWeapon()
{
super.DetachWeapon();
if ( Instigator != none && Instigator.IsLocallyControlled() && ScreenUI != none )
{
ScreenUI.SetPause();
}
}
simulated event Destroyed()
{
if ( Instigator != none && Instigator.IsLocallyControlled() && ScreenUI != none)
{
ScreenUI.Close();
}
super.Destroyed();
}
/** @see Weapon::Tick */
simulated event Tick(float DeltaTime)
{
Super.Tick(DeltaTime);
TimeSinceLastUpdate+=DeltaTime;
if(TimeSinceLastUpdate > UpdateInterval)
{
UpdateScreenUI();
}
}
/** Only update the screen screen if we have the welder equipped and it's screen values have changed */
simulated function UpdateScreenUI()
{
if ( Instigator != none && Instigator.IsLocallyControlled() && Instigator.Weapon == self )
{
if ( ScreenUI != none )
{
ScreenUI.SetMaxCharges(GetMaxAmmoAmount(0));
ScreenUI.SetActiveCharges(NumDeployedCharges);
TimeSinceLastUpdate=0.0f;
}
}
}
/** Overridded to add spawned charge to list of spawned charges */
simulated function Projectile ProjectileFire()
{
local Projectile P;
local KFProj_Thrown_C4 Charge;
P = super.ProjectileFire();
Charge = KFProj_Thrown_C4( P );
if( Charge != none )
{
if(SkinItemId > 0)
{
Charge.WeaponSkinId = SkinItemId;
Charge.SetWeaponSkin(SkinItemId);
Charge.bNetDirty = true;
}
DeployedCharges.AddItem( Charge );
NumDeployedCharges = DeployedCharges.Length;
bForceNetUpdate = true;
}
return P;
}
/** Detonates the oldest charge */
simulated function Detonate()
{
// auto switch weapon when out of ammo and after detonating the last deployed charge
if( Role == ROLE_Authority )
{
if( DeployedCharges.Length > 0 )
{
DeployedCharges[0].Detonate();
}
if( !HasAnyAmmo() && NumDeployedCharges == 0 )
{
if( CanSwitchWeapons() )
{
Instigator.Controller.ClientSwitchToBestWeapon(false);
}
}
}
}
/** Removes a charge from the list using either an index or an actor and updates NumDeployedCharges */
function RemoveDeployedCharge( optional int ChargeIndex = INDEX_NONE, optional Actor ChargeActor )
{
if( ChargeIndex == INDEX_NONE )
{
if( ChargeActor != none )
{
ChargeIndex = DeployedCharges.Find( ChargeActor );
}
}
if( ChargeIndex != INDEX_NONE )
{
DeployedCharges.Remove( ChargeIndex, 1 );
NumDeployedCharges = DeployedCharges.Length;
bForceNetUpdate = true;
}
}
/** Allows pickup to update weapon properties
* Overridden to allow C4 to update charges
*/
function SetOriginalValuesFromPickup( KFWeapon PickedUpWeapon )
{
local int i;
super.SetOriginalValuesFromPickup( PickedUpWeapon );
DeployedCharges = KFWeap_Thrown_C4(PickedUpWeapon).DeployedCharges;
NumDeployedCharges = DeployedCharges.Length;
bForceNetUpdate = true;
for( i = 0; i < NumDeployedCharges; ++i )
{
// charge alerts (beep, light) need current instigator
DeployedCharges[i].Instigator = Instigator;
DeployedCharges[i].SetOwner(self);
if( Instigator.Controller != none )
{
DeployedCharges[i].InstigatorController = Instigator.Controller;
}
}
}
/**
* Returns true if this weapon uses a secondary ammo pool
*/
static simulated event bool UsesAmmo()
{
return true;
}
simulated function bool HasAmmo( byte FireModeNum, optional int Amount )
{
if( FireModeNum == DETONATE_FIREMODE )
{
return NumDeployedCharges > 0;
}
return super.HasAmmo( FireModeNum, Amount );
}
simulated function BeginFire( byte FireModeNum )
{
if( FireModeNum == DETONATE_FIREMODE && (IsInState('WeaponSprinting') || NumDeployedCharges <= 0))
{
PrepareAndDetonate();
}
else
{
super.BeginFire( FireModeNum );
}
}
simulated function PrepareAndDetonate()
{
local name DetonateAnimName;
local float AnimDuration;
local bool bInSprintState;
DetonateAnimName = ShouldPlayLastAnims() ? DetonateLastAnim : DetonateAnim;
AnimDuration = MySkelMesh.GetAnimLength( DetonateAnimName );
bInSprintState = IsInState( 'WeaponSprinting' );
if( WorldInfo.NetMode != NM_DedicatedServer )
{
if( NumDeployedCharges > 0 )
{
PlaySoundBase( DetonateAkEvent, true );
}
else
{
PlaySoundBase( DryFireAkEvent, true );
}
if( bInSprintState )
{
AnimDuration *= 0.25f;
PlayAnimation( DetonateAnimName, AnimDuration );
}
else
{
PlayAnimation( DetonateAnimName );
}
}
if( Role == ROLE_Authority )
{
Detonate();
}
IncrementFlashCount();
if( bInSprintState )
{
SetTimer( AnimDuration * 0.8f, false, nameof(PlaySprintStart) );
}
else
{
SetTimer( AnimDuration * 0.5f, false, nameof(GotoActiveState) );
}
}
// do nothing, as we have no alt fire mode
simulated function AltFireMode();
/** Allow weapons with abnormal state transitions to always use zed time resist*/
simulated function bool HasAlwaysOnZedTimeResist()
{
return true;
}
/*********************************************************************************************
* State Active
* A Weapon this is being held by a pawn should be in the active state. In this state,
* a weapon should loop any number of idle animations, as well as check the PendingFire flags
* to see if a shot has been fired.
*********************************************************************************************/
simulated state Active
{
/** Overridden to prevent playing fidget if play has no more ammo */
simulated function bool CanPlayIdleFidget(optional bool bOnReload)
{
if( !HasAmmo(0) )
{
return false;
}
return super.CanPlayIdleFidget( bOnReload );
}
}
/*********************************************************************************************
* State WeaponDetonating
* The weapon is in this state while detonating a charge
*********************************************************************************************/
simulated function GotoActiveState();
simulated state WeaponDetonating
{
ignores AllowSprinting;
simulated event BeginState( name PreviousStateName )
{
PrepareAndDetonate();
}
simulated function GotoActiveState()
{
GotoState('Active');
}
}
/*********************************************************************************************
* State WeaponThrowing
* Handles throwing weapon (similar to state GrenadeFiring)
*********************************************************************************************/
simulated state WeaponThrowing
{
/** Never refires. Must re-enter this state instead. */
simulated function bool ShouldRefire()
{
return false;
}
simulated function EndState(Name NextStateName)
{
local KFPerk InstigatorPerk;
Super.EndState(NextStateName);
//Targeted fix for Demolitionist w/ the C4. It should remain in zed time while waiting on
// the fake reload to be triggered. This will return 0 for other perks.
InstigatorPerk = GetPerk();
if( InstigatorPerk != none )
{
SetZedTimeResist( InstigatorPerk.GetZedTimeModifier(self) );
}
}
}
/*********************************************************************************************
* State WeaponEquipping
* The Weapon is in this state while transitioning from Inactive to Active state.
* Typically, the weapon will remain in this state while its selection animation is being played.
* While in this state, the weapon cannot be fired.
*********************************************************************************************/
simulated state WeaponEquipping
{
simulated event BeginState( name PreviousStateName )
{
super.BeginState( PreviousStateName );
// perform a "reload" if we refilled our ammo from empty while it was unequipped
if( !HasAmmo(THROW_FIREMODE) && HasSpareAmmo() )
{
PerformArtificialReload();
}
StopFire(DETONATE_FIREMODE);
}
}
/*********************************************************************************************
* State WeaponPuttingDown
* Putting down weapon in favor of a new one.
* Weapon is transitioning to the Inactive state.
*
* Detonating while putting down causes C4 not to be put down, which causes problems, so let's
* just ignore SetIronSights, which causes detonation
*********************************************************************************************/
simulated state WeaponPuttingDown
{
ignores SetIronSights;
simulated event BeginState( name PreviousStateName )
{
super.BeginState( PreviousStateName );
StopFire(DETONATE_FIREMODE);
}
}
/*********************************************************************************************
* @name Trader
*********************************************************************************************/
/** Returns trader filter index based on weapon type */
static simulated event EFilterTypeUI GetTraderFilter()
{
return FT_Explosive;
}
defaultproperties
{
// start in detonate mode so that an attempt to detonate before any charges are thrown results in
// the proper third-person anim
CurrentFireMode=DETONATE_FIREMODE
// Zooming/Position
PlayerViewOffset=(X=6.0,Y=2,Z=-4)
FireOffset=(X=25,Y=15)
UpdateInterval=0.25f
// Content
PackageKey="C4"
FirstPersonMeshName="Wep_1P_C4_MESH.Wep_1stP_C4_Rig"
FirstPersonAnimSetNames(0)="Wep_1P_C4_ANIM.Wep_1P_C4_ANIM"
PickupMeshName="WEP_3P_C4_MESH.Wep_C4_Pickup"
AttachmentArchetypeName="WEP_C4_ARCH.Wep_C4_3P"
ScreenUIClass=class'KFGFxWorld_C4Screen'
// Anim
FireAnim=C4_Throw
FireLastAnim=C4_Throw_Last
DetonateAnim=Detonate
DetonateLastAnim=Detonate_Last
// Ammo
MagazineCapacity[0]=1
SpareAmmoCapacity[0]=2
InitialSpareMags[0]=1
AmmoPickupScale[0]=1.0
// THROW_FIREMODE
FireInterval(THROW_FIREMODE)=0.25
FireModeIconPaths(THROW_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Grenade'
WeaponProjectiles(THROW_FIREMODE)=class'KFProj_Thrown_C4'
// DETONATE_FIREMODE
FiringStatesArray(DETONATE_FIREMODE)=WeaponDetonating
WeaponFireTypes(DETONATE_FIREMODE)=EWFT_Custom
AmmoCost(DETONATE_FIREMODE)=0
// BASH_FIREMODE
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_C4'
InstantHitDamage(BASH_FIREMODE)=23
// Inventory / Grouping
InventoryGroup=IG_Equipment
2022-05-11 15:13:25 +00:00
GroupPriority=11
2020-12-13 15:01:13 +00:00
WeaponSelectTexture=Texture2D'WEP_UI_C4_TEX.UI_WeaponSelect_C4'
InventorySize=3
AssociatedPerkClasses(0)=class'KFPerk_Demolitionist'
DetonateAkEvent=AkEvent'WW_WEP_EXP_C4.Play_WEP_EXP_C4_Handling_Detonate'
DryFireAkEvent=AkEvent'WW_WEP_EXP_C4.Play_WEP_EXP_C4_DryFire'
// Weapon Upgrade stat boosts
//WeaponUpgrades[1]=(IncrementDamage=1.05f,IncrementWeight=1)
//WeaponUpgrades[2]=(IncrementDamage=1.1f,IncrementWeight=2)
//WeaponUpgrades[3]=(IncrementDamage=1.15f,IncrementWeight=3)
}