2022-05-11 15:13:25 +00:00
|
|
|
//=============================================================================
|
|
|
|
// KFWeap_AutoTurret
|
|
|
|
//=============================================================================
|
|
|
|
//=============================================================================
|
|
|
|
// Killing Floor 2
|
|
|
|
// Copyright (C) 2022 Tripwire Interactive LLC
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
class KFWeap_AutoTurret extends KFWeap_ThrownBase;
|
|
|
|
|
|
|
|
`define AUTOTURRET_MIC_LED_INDEX 2
|
|
|
|
|
|
|
|
const DETONATE_FIREMODE = 5; // NEW - IronSights Key
|
|
|
|
|
|
|
|
var(Animations) const editconst name DetonateAnim;
|
|
|
|
var(Animations) const editconst name DetonateLastAnim;
|
|
|
|
|
|
|
|
/** Sound to play upon successful detonation */
|
|
|
|
var() AkEvent DetonateAkEvent;
|
|
|
|
|
|
|
|
/** Strenght applied to forward dir to get the throwing velocity */
|
|
|
|
var const float ThrowStrength;
|
|
|
|
/** Max num of turrets that can be deployed */
|
|
|
|
var const byte MaxTurretsDeployed;
|
|
|
|
/** Offset to spawn the dron (screen coordinates) */
|
|
|
|
var const vector TurretSpawnOffset;
|
|
|
|
|
|
|
|
var transient byte NumDeployedTurrets;
|
|
|
|
var transient KFPlayerController KFPC;
|
|
|
|
|
|
|
|
/** If the turret is in a state available for throw another to fix some animation issues. */
|
|
|
|
var transient bool bTurretReadyToUse;
|
|
|
|
|
|
|
|
var repnotify float CurrentAmmoPercentage;
|
|
|
|
|
|
|
|
const TransitionParamName = 'transition_full_to_empty';
|
|
|
|
const EmptyParamName = 'Blinking_0_off___1_on';
|
|
|
|
|
2022-06-14 15:52:40 +00:00
|
|
|
var transient bool bDetonateLocked;
|
|
|
|
|
2022-05-11 15:13:25 +00:00
|
|
|
replication
|
|
|
|
{
|
|
|
|
if( bNetDirty )
|
|
|
|
NumDeployedTurrets, CurrentAmmoPercentage, bTurretReadyToUse;
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated event ReplicatedEvent(name VarName)
|
|
|
|
{
|
|
|
|
if (VarName == nameof(CurrentAmmoPercentage))
|
|
|
|
{
|
|
|
|
UpdateMaterialColor(CurrentAmmoPercentage);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Super.ReplicatedEvent(VarName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated event PreBeginPlay()
|
|
|
|
{
|
|
|
|
local class<KFWeap_AutoTurretWeapon> WeaponClass;
|
|
|
|
|
|
|
|
super.PreBeginPlay();
|
|
|
|
|
|
|
|
WeaponClass = class<KFWeap_AutoTurretWeapon> (DynamicLoadObject(class'KFPawn_AutoTurret'.default.WeaponDefinition.default.WeaponClassPath, class'Class'));
|
|
|
|
WeaponClass.static.TriggerAsyncContentLoad(WeaponClass);
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated event PostBeginPlay()
|
|
|
|
{
|
|
|
|
super.PostBeginPlay();
|
|
|
|
|
|
|
|
if (Role == ROLE_Authority)
|
|
|
|
{
|
|
|
|
KFPC = KFPlayerController(Instigator.Controller);
|
|
|
|
NumDeployedTurrets = KFPC.DeployedTurrets.Length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Route ironsight player input to detonate */
|
|
|
|
simulated function SetIronSights(bool bNewIronSights)
|
|
|
|
{
|
|
|
|
if ( !Instigator.IsLocallyControlled() )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( bNewIronSights )
|
|
|
|
{
|
|
|
|
StartFire(DETONATE_FIREMODE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
StopFire(DETONATE_FIREMODE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Overridded to add spawned turret to list of spawned turrets */
|
|
|
|
simulated function Projectile ProjectileFire()
|
|
|
|
{
|
|
|
|
local vector SpawnLocation, SpawnDirection;
|
|
|
|
local KFPawn_AutoTurret SpawnedActor;
|
|
|
|
|
|
|
|
if (Role == ROLE_Authority && CurrentFireMode == DEFAULT_FIREMODE)
|
|
|
|
{
|
|
|
|
GetTurretSpawnLocationAndDir(SpawnLocation, SpawnDirection);
|
|
|
|
SpawnedActor = Spawn(class'KFPawn_AutoTurret', self,, SpawnLocation + (TurretSpawnOffset >> Rotation), Rotation,,true);
|
|
|
|
|
|
|
|
if( SpawnedActor != none )
|
|
|
|
{
|
|
|
|
SpawnedActor.OwnerWeapon = self;
|
|
|
|
SpawnedActor.SetPhysics(PHYS_Falling);
|
|
|
|
SpawnedActor.Velocity = SpawnDirection * ThrowStrength;
|
|
|
|
SpawnedActor.UpdateInstigator(Instigator);
|
|
|
|
SpawnedActor.UpdateWeaponUpgrade(CurrentWeaponUpgradeIndex);
|
|
|
|
SpawnedActor.SetTurretState(ETS_Throw);
|
|
|
|
|
|
|
|
KFPC.DeployedTurrets.AddItem( SpawnedActor );
|
|
|
|
NumDeployedTurrets = KFPC.DeployedTurrets.Length;
|
2022-06-29 16:11:27 +00:00
|
|
|
bTurretReadyToUse = false;
|
2022-05-11 15:13:25 +00:00
|
|
|
bForceNetUpdate = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return none;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return super.ProjectileFire();
|
|
|
|
}
|
|
|
|
|
|
|
|
return none;
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function GetTurretSpawnLocationAndDir(out vector SpawnLocation, out vector SpawnDirection)
|
|
|
|
{
|
|
|
|
local vector StartTrace, EndTrace, RealStartLoc, AimDir;
|
|
|
|
local ImpactInfo TestImpact;
|
|
|
|
local vector DirA, DirB;
|
|
|
|
local Quat Q;
|
|
|
|
|
|
|
|
// This is where we would start an instant trace. (what CalcWeaponFire uses)
|
|
|
|
StartTrace = GetSafeStartTraceLocation();
|
|
|
|
AimDir = Vector(GetAdjustedAim( StartTrace ));
|
|
|
|
|
|
|
|
// this is the location where the projectile is spawned.
|
|
|
|
RealStartLoc = GetPhysicalFireStartLoc(AimDir);
|
|
|
|
|
|
|
|
if( StartTrace != RealStartLoc )
|
|
|
|
{
|
|
|
|
// if projectile is spawned at different location of crosshair,
|
|
|
|
// then simulate an instant trace where crosshair is aiming at, Get hit info.
|
|
|
|
EndTrace = StartTrace + AimDir * GetTraceRange();
|
|
|
|
TestImpact = CalcWeaponFire( StartTrace, EndTrace );
|
|
|
|
// Store the original aim direction without correction
|
|
|
|
DirB = AimDir;
|
|
|
|
|
|
|
|
// Then we realign projectile aim direction to match where the crosshair did hit.
|
|
|
|
AimDir = Normal(TestImpact.HitLocation - RealStartLoc);
|
|
|
|
|
|
|
|
// Store the desired corrected aim direction
|
|
|
|
DirA = AimDir;
|
|
|
|
|
|
|
|
// Clamp the maximum aim adjustment for the AimDir so you don't get wierd
|
|
|
|
// cases where the projectiles velocity is going WAY off of where you
|
|
|
|
// are aiming. This can happen if you are really close to what you are
|
|
|
|
// shooting - Ramm
|
|
|
|
if ( (DirA dot DirB) < MaxAimAdjust_Cos )
|
|
|
|
{
|
|
|
|
Q = QuatFromAxisAndAngle(Normal(DirB cross DirA), MaxAimAdjust_Angle);
|
|
|
|
AimDir = QuatRotateVector(Q,DirB);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SpawnDirection = AimDir;
|
|
|
|
SpawnLocation = RealStartLoc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Detonates the oldest turret */
|
2022-09-01 15:58:51 +00:00
|
|
|
simulated function Detonate(optional bool bKeepTurret = false)
|
2022-05-11 15:13:25 +00:00
|
|
|
{
|
2022-06-29 16:11:27 +00:00
|
|
|
local int i;
|
|
|
|
local array<Actor> TurretsCopy;
|
|
|
|
|
2022-05-11 15:13:25 +00:00
|
|
|
// auto switch weapon when out of ammo and after detonating the last deployed turret
|
|
|
|
if( Role == ROLE_Authority )
|
|
|
|
{
|
2022-06-29 16:11:27 +00:00
|
|
|
TurretsCopy = KFPC.DeployedTurrets;
|
|
|
|
for (i = 0; i < TurretsCopy.Length; i++)
|
2022-05-11 15:13:25 +00:00
|
|
|
{
|
2022-09-01 15:58:51 +00:00
|
|
|
if (bKeepTurret && i == 0)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-05-11 15:55:04 +00:00
|
|
|
if (KFPawn_HRG_Warthog(TurretsCopy[i]) != none)
|
|
|
|
{
|
|
|
|
KFPawn_HRG_Warthog(TurretsCopy[i]).SetTurretState(ETS_Detonate);
|
|
|
|
}
|
|
|
|
else if (KFPawn_Autoturret(TurretsCopy[i]) != none)
|
|
|
|
{
|
|
|
|
KFPawn_Autoturret(TurretsCopy[i]).SetTurretState(ETS_Detonate);
|
|
|
|
}
|
2022-05-11 15:13:25 +00:00
|
|
|
}
|
2022-06-29 16:11:27 +00:00
|
|
|
|
2022-09-01 15:58:51 +00:00
|
|
|
KFPC.DeployedTurrets.Remove(bKeepTurret ? 1 : 0, KFPC.DeployedTurrets.Length);
|
2022-06-29 16:11:27 +00:00
|
|
|
|
2022-05-11 15:13:25 +00:00
|
|
|
SetReadyToUse(true);
|
|
|
|
|
|
|
|
if( !HasAnyAmmo() && NumDeployedTurrets == 0 )
|
|
|
|
{
|
|
|
|
if( CanSwitchWeapons() )
|
|
|
|
{
|
|
|
|
Instigator.Controller.ClientSwitchToBestWeapon(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Removes a turret from the list using either an index or an actor and updates NumDeployedTurrets */
|
|
|
|
function RemoveDeployedTurret( optional int Index = INDEX_NONE, optional Actor TurretActor )
|
|
|
|
{
|
|
|
|
if( Index == INDEX_NONE )
|
|
|
|
{
|
|
|
|
if( TurretActor != none )
|
|
|
|
{
|
|
|
|
Index = KFPC.DeployedTurrets.Find( TurretActor );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( Index != INDEX_NONE )
|
|
|
|
{
|
|
|
|
KFPC.DeployedTurrets.Remove( Index, 1 );
|
|
|
|
NumDeployedTurrets = KFPC.DeployedTurrets.Length;
|
|
|
|
bForceNetUpdate = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function SetOriginalValuesFromPickup( KFWeapon PickedUpWeapon )
|
|
|
|
{
|
|
|
|
local int i;
|
2023-05-11 15:55:04 +00:00
|
|
|
local Actor WeaponPawn;
|
2022-05-11 15:13:25 +00:00
|
|
|
|
|
|
|
super.SetOriginalValuesFromPickup( PickedUpWeapon );
|
|
|
|
|
2022-06-29 16:11:27 +00:00
|
|
|
if (PickedUpWeapon.KFPlayer != none && PickedUpWeapon.KFPlayer != KFPC)
|
2022-05-11 15:13:25 +00:00
|
|
|
{
|
2022-09-01 15:58:51 +00:00
|
|
|
for (i = 0; i < PickedUpWeapon.KFPlayer.DeployedTurrets.Length; i++)
|
|
|
|
{
|
|
|
|
KFPC.DeployedTurrets.AddItem(PickedUpWeapon.KFPlayer.DeployedTurrets[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
PickedUpWeapon.KFPlayer.DeployedTurrets.Remove(0, PickedUpWeapon.KFPlayer.DeployedTurrets.Length);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (KFPC.DeployedTurrets.Length > 1)
|
|
|
|
{
|
|
|
|
Detonate(true);
|
2022-05-11 15:13:25 +00:00
|
|
|
}
|
|
|
|
|
2022-06-29 16:11:27 +00:00
|
|
|
PickedUpWeapon.KFPlayer = none;
|
|
|
|
|
2022-05-11 15:13:25 +00:00
|
|
|
NumDeployedTurrets = KFPC.DeployedTurrets.Length;
|
|
|
|
bForceNetUpdate = true;
|
|
|
|
|
|
|
|
for( i = 0; i < NumDeployedTurrets; ++i )
|
|
|
|
{
|
2023-05-11 15:55:04 +00:00
|
|
|
WeaponPawn = KFPC.DeployedTurrets[i];
|
|
|
|
if (WeaponPawn != none)
|
|
|
|
{
|
|
|
|
// charge alerts (beep, light) need current instigator
|
|
|
|
WeaponPawn.Instigator = Instigator;
|
|
|
|
WeaponPawn.SetOwner(self);
|
2022-05-11 15:13:25 +00:00
|
|
|
|
2023-05-11 15:55:04 +00:00
|
|
|
if (Instigator.Controller != none)
|
|
|
|
{
|
|
|
|
if (KFPawn_HRG_Warthog(KFPC.DeployedTurrets[i]) != none)
|
|
|
|
{
|
|
|
|
KFPawn_HRG_Warthog(KFPC.DeployedTurrets[i]).InstigatorController = Instigator.Controller;
|
|
|
|
}
|
|
|
|
else if (KFPawn_Autoturret(KFPC.DeployedTurrets[i]) != none)
|
|
|
|
{
|
|
|
|
KFPawn_Autoturret(KFPC.DeployedTurrets[i]).InstigatorController = Instigator.Controller;
|
|
|
|
}
|
|
|
|
}
|
2022-05-11 15:13:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-29 16:11:27 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Drop this item out in to the world
|
|
|
|
*/
|
|
|
|
function DropFrom(vector StartLocation, vector StartVelocity)
|
|
|
|
{
|
|
|
|
local DroppedPickup P;
|
|
|
|
|
|
|
|
// Offset spawn closer to eye location
|
|
|
|
StartLocation.Z += Instigator.BaseEyeHeight / 2;
|
|
|
|
|
|
|
|
// for some reason, Inventory::DropFrom removes weapon from inventory whether it was able to spawn the pickup or not.
|
|
|
|
// we only want the weapon removed from inventory if pickup was successfully spawned, so instead of calling the supers,
|
|
|
|
// do all the super functionality here.
|
|
|
|
|
|
|
|
if( !CanThrow() )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( DroppedPickupClass == None || DroppedPickupMesh == None )
|
|
|
|
{
|
|
|
|
Destroy();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the last bool param is to prevent collision from preventing spawns
|
|
|
|
P = Spawn(DroppedPickupClass,,, StartLocation,,,true);
|
|
|
|
if( P == None )
|
|
|
|
{
|
|
|
|
// if we can't spawn the pickup (likely for collision reasons),
|
|
|
|
// just return without removing from inventory or destroying, which removes from inventory
|
|
|
|
PlayerController(Instigator.Controller).ReceiveLocalizedMessage( class'KFLocalMessage_Game', GMT_FailedDropInventory );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( Instigator != None && Instigator.InvManager != None )
|
|
|
|
{
|
|
|
|
Instigator.InvManager.RemoveFromInventory(Self);
|
|
|
|
|
|
|
|
if( Instigator.IsAliveAndWell() && !Instigator.InvManager.bPendingDelete )
|
|
|
|
{
|
|
|
|
`DialogManager.PlayDropWeaponDialog( KFPawn(Instigator) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SetupDroppedPickup( P, StartVelocity );
|
|
|
|
|
|
|
|
KFDroppedPickup(P).PreviousOwner = KFPlayerController(Instigator.Controller);
|
|
|
|
|
|
|
|
Instigator = None;
|
|
|
|
GotoState('');
|
|
|
|
|
|
|
|
AIController = None;
|
|
|
|
}
|
|
|
|
|
2022-05-11 15:13:25 +00:00
|
|
|
/**
|
|
|
|
* 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 NumDeployedTurrets > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.HasAmmo( FireModeNum, Amount );
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function BeginFire( byte FireModeNum )
|
|
|
|
{
|
2023-05-11 15:55:04 +00:00
|
|
|
local bool bCanDetonate;
|
|
|
|
|
2022-05-11 15:13:25 +00:00
|
|
|
// Clear any pending detonate if we pressed the main fire
|
|
|
|
// That prevents strange holding right click behaviour and sound issues
|
|
|
|
if (FireModeNum == DEFAULT_FIREMODE)
|
|
|
|
{
|
|
|
|
ClearPendingFire(DETONATE_FIREMODE);
|
|
|
|
}
|
|
|
|
|
2022-06-14 15:52:40 +00:00
|
|
|
if (FireModeNum == DETONATE_FIREMODE )
|
2022-05-11 15:13:25 +00:00
|
|
|
{
|
2022-06-14 15:52:40 +00:00
|
|
|
if (bDetonateLocked)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NumDeployedTurrets > 0 && bTurretReadyToUse)
|
2022-05-11 15:13:25 +00:00
|
|
|
{
|
2023-05-11 15:55:04 +00:00
|
|
|
bCanDetonate = NumDeployedTurrets > 0;
|
|
|
|
|
|
|
|
if (bCanDetonate)
|
|
|
|
{
|
|
|
|
PrepareAndDetonate();
|
|
|
|
}
|
2022-05-11 15:13:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-05-11 15:55:04 +00:00
|
|
|
if (KFPC != none)
|
|
|
|
{
|
|
|
|
NumDeployedTurrets = KFPC.DeployedTurrets.Length;
|
|
|
|
}
|
|
|
|
|
2022-05-11 15:13:25 +00:00
|
|
|
if (FireModeNum == DEFAULT_FIREMODE
|
|
|
|
&& NumDeployedTurrets >= MaxTurretsDeployed
|
2022-06-29 16:11:27 +00:00
|
|
|
&& HasAnyAmmo())
|
2022-05-11 15:13:25 +00:00
|
|
|
{
|
|
|
|
if (!bTurretReadyToUse)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2022-06-29 16:11:27 +00:00
|
|
|
|
2022-05-11 15:13:25 +00:00
|
|
|
PrepareAndDetonate();
|
|
|
|
}
|
|
|
|
|
|
|
|
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( NumDeployedTurrets > 0 )
|
|
|
|
{
|
|
|
|
PlaySoundBase( DetonateAkEvent, true );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( bInSprintState )
|
|
|
|
{
|
|
|
|
AnimDuration *= 0.25f;
|
|
|
|
PlayAnimation( DetonateAnimName, AnimDuration );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PlayAnimation( DetonateAnimName );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( Role == ROLE_Authority )
|
|
|
|
{
|
|
|
|
Detonate();
|
|
|
|
}
|
|
|
|
|
2023-05-25 20:42:10 +00:00
|
|
|
CurrentFireMode = DETONATE_FIREMODE;
|
2022-05-11 15:13:25 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
function CheckTurretAmmo()
|
|
|
|
{
|
|
|
|
local float Percentage;
|
|
|
|
local KFWeapon Weapon;
|
|
|
|
local KFPawn KFP;
|
|
|
|
|
|
|
|
if (Role == Role_Authority)
|
|
|
|
{
|
2022-06-29 16:11:27 +00:00
|
|
|
if (KFPC == none)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-11 15:13:25 +00:00
|
|
|
if (KFPC.DeployedTurrets.Length > 0)
|
|
|
|
{
|
2023-05-11 15:55:04 +00:00
|
|
|
if (KFPawn_HRG_Warthog(KFPC.DeployedTurrets[0]) != none)
|
|
|
|
{
|
|
|
|
Weapon = KFWeapon(KFPawn_HRG_Warthog(KFPC.DeployedTurrets[0]).Weapon);
|
|
|
|
}
|
|
|
|
else if (KFPawn_Autoturret(KFPC.DeployedTurrets[0]) != none)
|
|
|
|
{
|
|
|
|
Weapon = KFWeapon(KFPawn_Autoturret(KFPC.DeployedTurrets[0]).Weapon);
|
|
|
|
}
|
|
|
|
|
2022-05-11 15:13:25 +00:00
|
|
|
if (Weapon != none)
|
|
|
|
{
|
|
|
|
Percentage = float(Weapon.AmmoCount[0]) / Weapon.MagazineCapacity[0];
|
|
|
|
if (Percentage != CurrentAmmoPercentage)
|
|
|
|
{
|
|
|
|
CurrentAmmoPercentage = Percentage;
|
|
|
|
bNetDirty = true;
|
|
|
|
|
|
|
|
if (WorldInfo.NetMode == NM_Standalone)
|
|
|
|
{
|
|
|
|
UpdateMaterialColor(CurrentAmmoPercentage);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KFP = KFPawn(Instigator);
|
2022-06-29 16:11:27 +00:00
|
|
|
if (KFP != none)
|
|
|
|
{
|
|
|
|
KFP.OnWeaponSpecialAction( 1 + (CurrentAmmoPercentage * 100) );
|
|
|
|
}
|
2022-05-11 15:13:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function SetReadyToUse(bool bReady)
|
|
|
|
{
|
|
|
|
if (bTurretReadyToUse != bReady)
|
|
|
|
{
|
|
|
|
bTurretReadyToUse = bReady;
|
|
|
|
bNetDirty = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated event Tick(float DeltaTime)
|
|
|
|
{
|
|
|
|
super.Tick(DeltaTime);
|
|
|
|
|
|
|
|
if (Role == Role_Authority)
|
|
|
|
{
|
|
|
|
CheckTurretAmmo();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function UpdateMaterialColor(float Percentage)
|
|
|
|
{
|
|
|
|
if (NumDeployedTurrets == 0)
|
|
|
|
{
|
|
|
|
WeaponMICs[`AUTOTURRET_MIC_LED_INDEX].SetScalarParameterValue(EmptyParamName, 0);
|
|
|
|
}
|
|
|
|
else if (Percentage >= 0)
|
|
|
|
{
|
|
|
|
WeaponMICs[`AUTOTURRET_MIC_LED_INDEX].SetScalarParameterValue(TransitionParamName, 1.0f - Percentage);
|
|
|
|
WeaponMICs[`AUTOTURRET_MIC_LED_INDEX].SetScalarParameterValue(EmptyParamName, Percentage == 0 ? 1 : 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function SetWeaponUpgradeLevel(int WeaponUpgradeLevel)
|
|
|
|
{
|
|
|
|
local Actor Turret;
|
|
|
|
local KFPawn_AutoTurret TurretPawn;
|
|
|
|
|
|
|
|
super.SetWeaponUpgradeLevel(WeaponUpgradeLevel);
|
|
|
|
|
|
|
|
if (KFPC != none)
|
|
|
|
{
|
|
|
|
foreach KFPC.DeployedTurrets(Turret)
|
|
|
|
{
|
|
|
|
TurretPawn = KFPawn_AutoTurret(Turret);
|
|
|
|
if (TurretPawn != none)
|
|
|
|
{
|
|
|
|
TurretPawn.UpdateWeaponUpgrade(WeaponUpgradeLevel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-14 15:52:40 +00:00
|
|
|
/**
|
|
|
|
* GRENADE FIRING
|
|
|
|
* There's a bug that alt fire interrupts the grenade anim at any moment,
|
|
|
|
* This avoids being able to altfire until the throw animation ends or the
|
|
|
|
* interrupt notify is reached.
|
|
|
|
*/
|
|
|
|
|
|
|
|
simulated state GrenadeFiring
|
|
|
|
{
|
|
|
|
simulated function EndState(Name NextStateName)
|
|
|
|
{
|
|
|
|
ClearDetonateLock();
|
|
|
|
Super.EndState(NextStateName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Play animation at the start of the GrenadeFiring state */
|
|
|
|
simulated function PlayGrenadeThrow()
|
|
|
|
{
|
|
|
|
local name WeaponFireAnimName;
|
|
|
|
local float InterruptTime;
|
|
|
|
|
|
|
|
PlayFiringSound(CurrentFireMode);
|
|
|
|
|
|
|
|
if( Instigator != none && Instigator.IsFirstPerson() )
|
|
|
|
{
|
|
|
|
WeaponFireAnimName = GetGrenadeThrowAnim();
|
|
|
|
|
|
|
|
if ( WeaponFireAnimName != '' )
|
|
|
|
{
|
|
|
|
InterruptTime = MySkelMesh.GetAnimInterruptTime(WeaponFireAnimName);
|
|
|
|
PlayAnimation(WeaponFireAnimName, MySkelMesh.GetAnimLength(WeaponFireAnimName),,FireTweenTime);
|
|
|
|
|
|
|
|
bDetonateLocked = true;
|
|
|
|
SetTimer(InterruptTime, false, nameof(ClearDetonateLock));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function ClearDetonateLock()
|
|
|
|
{
|
|
|
|
bDetonateLocked = false;
|
|
|
|
ClearTimer(nameof(ClearDetonateLock));
|
|
|
|
}
|
|
|
|
|
|
|
|
/***/
|
|
|
|
|
|
|
|
|
2022-05-11 15:13:25 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Trader
|
|
|
|
//
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/** Allows weapon to calculate its own stats for display in trader */
|
|
|
|
static simulated event SetTraderWeaponStats( out array<STraderItemWeaponStats> WeaponStats )
|
|
|
|
{
|
|
|
|
super.SetTraderWeaponStats(WeaponStats);
|
|
|
|
|
|
|
|
WeaponStats.Length = 4;
|
|
|
|
|
|
|
|
WeaponStats[0].StatType = TWS_Damage;
|
|
|
|
WeaponStats[0].StatValue = class'KFWeap_AutoTurretWeapon'.static.CalculateTraderWeaponStatDamage();
|
|
|
|
|
|
|
|
WeaponStats[1].StatType = TWS_Penetration;
|
|
|
|
WeaponStats[1].StatValue = class'KFWeap_AutoTurretWeapon'.default.PenetrationPower[DEFAULT_FIREMODE];
|
|
|
|
|
|
|
|
WeaponStats[2].StatType = TWS_Range;
|
|
|
|
// This is now set in native since EffectiveRange has been moved to KFWeaponDefinition
|
|
|
|
// WeaponStats[2].StatValue = CalculateTraderWeaponStatRange();
|
|
|
|
|
|
|
|
WeaponStats[3].StatType = TWS_RateOfFire;
|
|
|
|
WeaponStats[3].StatValue = class'KFWeap_AutoTurretWeapon'.static.CalculateTraderWeaponStatFireRate();
|
|
|
|
}
|
|
|
|
|
|
|
|
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=0,Y=0)
|
|
|
|
TurretSpawnOffset=(X=0, Y=15, Z=-50)
|
|
|
|
|
|
|
|
// Content
|
|
|
|
PackageKey="AutoTurret"
|
|
|
|
FirstPersonMeshName="Wep_1P_AutoTurret_MESH.Wep_1stP_AutoTurret_Rig"
|
|
|
|
FirstPersonAnimSetNames(0)="Wep_1P_AutoTurret_ANIM.Wep_1P_AutoTurret_ANIM"
|
|
|
|
PickupMeshName="wep_3p_autoturret_mesh.Wep_AutoTurret_Pickup"
|
|
|
|
AttachmentArchetypeName="WEP_AutoTurret_ARCH.Wep_AutoTurret_3P"
|
|
|
|
|
|
|
|
// Anim
|
|
|
|
FireAnim=C4_Throw
|
|
|
|
FireLastAnim=C4_Throw_Last
|
|
|
|
|
|
|
|
DetonateAnim=Detonate
|
|
|
|
DetonateLastAnim=Detonate_Last
|
|
|
|
|
|
|
|
// Ammo
|
|
|
|
MagazineCapacity[0]=1
|
|
|
|
SpareAmmoCapacity[0]=3
|
|
|
|
InitialSpareMags[0]=1
|
|
|
|
AmmoPickupScale[0]=1.0
|
|
|
|
|
|
|
|
// THROW_FIREMODE
|
|
|
|
FireInterval(THROW_FIREMODE)=0.25
|
|
|
|
FireModeIconPaths(THROW_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Drone'
|
|
|
|
|
|
|
|
// DETONATE_FIREMODE
|
|
|
|
FiringStatesArray(DETONATE_FIREMODE)=WeaponDetonating
|
|
|
|
WeaponFireTypes(DETONATE_FIREMODE)=EWFT_Custom
|
|
|
|
AmmoCost(DETONATE_FIREMODE)=0
|
|
|
|
|
|
|
|
// BASH_FIREMODE
|
|
|
|
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_AutoTurret'
|
|
|
|
InstantHitDamage(BASH_FIREMODE)=26
|
|
|
|
|
|
|
|
// Inventory / Grouping
|
|
|
|
InventoryGroup=IG_Equipment
|
|
|
|
GroupPriority=11
|
|
|
|
WeaponSelectTexture=Texture2D'WEP_UI_AutoTurret_TEX.UI_WeaponSelect_AutoTurret'
|
|
|
|
InventorySize=3
|
|
|
|
|
|
|
|
DetonateAkEvent=AkEvent'ww_wep_autoturret.Play_WEP_AutoTurret_Detonate_Trigger'
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
|
|
|
AssociatedPerkClasses(0)=class'KFPerk_Commando'
|
|
|
|
|
|
|
|
MaxTurretsDeployed=1
|
|
|
|
NumDeployedTurrets=0
|
|
|
|
ThrowStrength=1350.0f
|
|
|
|
bTurretReadyToUse=true
|
|
|
|
|
|
|
|
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)))
|
|
|
|
NumBloodMapMaterials=3
|
2022-06-14 15:52:40 +00:00
|
|
|
|
|
|
|
bDetonateLocked=false
|
2023-05-11 15:55:04 +00:00
|
|
|
CurrentAmmoPercentage=-1.0f
|
2022-05-11 15:13:25 +00:00
|
|
|
}
|