789 lines
21 KiB
Ucode
789 lines
21 KiB
Ucode
//=============================================================================
|
|
// KFWeap_Healer_Syringe
|
|
//=============================================================================
|
|
// Weapon class used for the healer
|
|
//=============================================================================
|
|
// Killing Floor 2
|
|
// Copyright (C) 2015 Tripwire Interactive LLC
|
|
// - Andrew "Strago" Ladenberger
|
|
//=============================================================================
|
|
class KFWeap_Welder extends KFWeapon
|
|
hidedropdown;
|
|
|
|
/** If set, automatically equip the previous weapon when leaving a door trigger */
|
|
var() bool bAutoUnequip;
|
|
|
|
/*********************************************************************************************
|
|
@name Firing
|
|
********************************************************************************************* */
|
|
|
|
/** Maximum range to find Door */
|
|
var() float WeldingRange;
|
|
/** How many points to add to a door's weld integrity per use (use rate determined by FireInterval) */
|
|
var() float FastenRate;
|
|
/** How many points to subtract from a door's weld integrity per use (use rate determined by FireInterval) */
|
|
var() float UnFastenRate;
|
|
/** Percent repaired per fire interval */
|
|
var() float RepairRate;
|
|
|
|
/** Give the welder extra range when it has a WeldTarget to avoid the ready animation
|
|
activating / deactivating on door that is is currently being damaged */
|
|
var const float ExtraWeldingRange;
|
|
|
|
/** How long (in seconds) it takes to recharge ammo by 1 unit */
|
|
var() float AmmoRechargeRate;
|
|
|
|
/*********************************************************************************************
|
|
@name Animations
|
|
********************************************************************************************* */
|
|
|
|
/** animation names */
|
|
var name IdleWeldAnim;
|
|
var name WeldOpenAnim;
|
|
var name WeldCloseAnim;
|
|
|
|
/** Reference to the door we're pointing at */
|
|
var KFWeldableComponent WeldTarget;
|
|
|
|
/** Store last update to we can prevent idle->ready->idle to quickly */
|
|
var float LastTraceHitTime;
|
|
|
|
/*********************************************************************************************
|
|
@name Screen
|
|
********************************************************************************************* */
|
|
var class<KFGFxWorld_WelderScreen> ScreenUIClass;
|
|
var KFGFxWorld_WelderScreen ScreenUI;
|
|
|
|
simulated event PreBeginPlay()
|
|
{
|
|
local KFGameEngine KFGEngine;
|
|
|
|
Super.PreBeginPlay();
|
|
|
|
KFGEngine = KFGameEngine( Class'KFGameEngine'.static.GetEngine() );
|
|
|
|
if(KFGEngine != none)
|
|
{
|
|
SetShownInInventory(KFGEngine.bShowWelderInInv);
|
|
}
|
|
}
|
|
|
|
simulated function SetShownInInventory(bool bValue)
|
|
{
|
|
InventoryGroup= bValue ? IG_Equipment : IG_None ;
|
|
bAutoUnequip = !bValue;
|
|
}
|
|
|
|
/** 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);
|
|
ScreenUI.SetCharge( AmmoCount[0] );
|
|
ScreenUI.SetIntegrity( 255 );
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Turn off the UI screen when we unequip the healer */
|
|
simulated function DetachWeapon()
|
|
{
|
|
super.DetachWeapon();
|
|
if ( Instigator != none && Instigator.IsLocallyControlled() && ScreenUI != none )
|
|
{
|
|
ScreenUI.SetPause();
|
|
}
|
|
}
|
|
|
|
/** @see Weapon::Tick */
|
|
simulated event Tick(float DeltaTime)
|
|
{
|
|
Super.Tick(DeltaTime);
|
|
|
|
UpdateScreenUI();
|
|
}
|
|
|
|
simulated event Destroyed()
|
|
{
|
|
if ( Instigator != none && Instigator.IsLocallyControlled() && ScreenUI != none)
|
|
{
|
|
ScreenUI.Close();
|
|
}
|
|
super.Destroyed();
|
|
}
|
|
|
|
/** Only update the screen screen if we have the welder equipped and it's screen values have changed */
|
|
simulated function UpdateScreenUI()
|
|
{
|
|
local float WeldPercentageFloat;
|
|
local byte WeldPercentage;
|
|
|
|
if ( Instigator != none && Instigator.IsLocallyControlled() && Instigator.Weapon == self )
|
|
{
|
|
if ( ScreenUI != none )
|
|
{
|
|
// Check if our current ammo reading has changed
|
|
if ( ScreenUI.CurrentCharge != AmmoCount[0] )
|
|
{
|
|
ScreenUI.SetCharge( AmmoCount[0] );
|
|
}
|
|
|
|
if ( WeldTarget != none )
|
|
{
|
|
// Address rounding errors in UI
|
|
WeldPercentageFloat = WeldTarget.GetWeldPct();
|
|
if( WeldPercentageFloat < 1.f && WeldPercentageFloat > 0.f )
|
|
{
|
|
WeldPercentageFloat = 1.f;
|
|
}
|
|
else if( WeldPercentageFloat > 99.f && WeldPercentageFloat < 100.f )
|
|
{
|
|
WeldPercentageFloat = 99.f;
|
|
}
|
|
|
|
WeldPercentage = byte( WeldPercentageFloat );
|
|
// Check if our weld integrity has changed
|
|
if ( WeldPercentage != ScreenUI.IntegrityPercentage )
|
|
{
|
|
ScreenUI.SetIntegrity( WeldPercentage );
|
|
}
|
|
}
|
|
// Remove our weld value
|
|
else if ( ScreenUI.IntegrityPercentage != 255 )
|
|
{
|
|
ScreenUI.SetIntegrity( 255 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************************
|
|
* @name Ammunition
|
|
*********************************************************************************************/
|
|
|
|
simulated function bool HasAnyAmmo()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
simulated function bool HasAmmo( byte FireModeNum, optional int Amount )
|
|
{
|
|
if ( FireModeNum == DEFAULT_FIREMODE || FireModeNum == ALTFIRE_FIREMODE )
|
|
{
|
|
if ( AmmoCount[0] >= AmmoCost[FireModeNum])
|
|
{
|
|
// Requires a valid WeldTarget (see ServerSetWeldTarget)
|
|
return ( WeldTarget != None && CanWeldTarget(FireModeNum) );
|
|
}
|
|
return false;
|
|
}
|
|
|
|
return Super.HasAmmo(FireModeNum, Amount);
|
|
}
|
|
|
|
/** Returns true if weapon should be auto-reloaded */
|
|
simulated function bool ShouldAutoReload(byte FireModeNum)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/*********************************************************************************************
|
|
@name Firing / Projectile
|
|
********************************************************************************************* */
|
|
|
|
/** Unweld with RM/L2 */
|
|
simulated function SetIronSights(bool bNewIronSights)
|
|
{
|
|
if ( !Instigator.IsLocallyControlled() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( bNewIronSights )
|
|
{
|
|
StartFire(ALTFIRE_FIREMODE);
|
|
}
|
|
else
|
|
{
|
|
StopFire(ALTFIRE_FIREMODE);
|
|
}
|
|
}
|
|
|
|
/** Also unweld with MM/R1 */
|
|
simulated function AltFireMode()
|
|
{
|
|
if ( !Instigator.IsLocallyControlled() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// StartFire - StopFire called from KFPlayerInput
|
|
StartFire(ALTFIRE_FIREMODE);
|
|
}
|
|
|
|
/**
|
|
* @see Weapon::StartFire
|
|
*/
|
|
simulated function StartFire(byte FireModeNum)
|
|
{
|
|
// Notify server of the weld target we plan to use
|
|
if ( FireModeNum == DEFAULT_FIREMODE || FireModeNum == ALTFIRE_FIREMODE )
|
|
{
|
|
if ( Role < ROLE_Authority )
|
|
{
|
|
ServerSetWeldTarget(WeldTarget, false);
|
|
}
|
|
}
|
|
|
|
Super.StartFire(FireModeNum);
|
|
}
|
|
|
|
/**
|
|
* If the weapon isn't an instant hit, or a simple projectile, it should use the type EWFT_Custom. In those cases
|
|
* this function will be called. It should be subclassed by the custom weapon.
|
|
*/
|
|
simulated function CustomFire()
|
|
{
|
|
local float CurrentFastenRate, CurrentUnfastenRate;
|
|
WeldTarget = TraceWeldables();
|
|
// Fasten/Unfasten the door
|
|
if ( Role == ROLE_Authority )
|
|
{
|
|
if( !IsTimerActive(nameof(RechargeAmmo)) )
|
|
{
|
|
SetTimer(AmmoRechargeRate, true, nameof(RechargeAmmo));
|
|
}
|
|
|
|
if(WeldTarget != None)
|
|
{
|
|
CurrentFastenRate = FastenRate;
|
|
CurrentUnfastenRate = UnFastenRate;
|
|
|
|
GetPerk().ModifyWeldingRate(CurrentFastenRate, CurrentUnfastenRate);
|
|
|
|
if ( WeldTarget.bIsDestroyed && !WeldTarget.Owner.IsA('KFRepairableActor') )
|
|
{
|
|
WeldTarget.Repair(RepairRate, KFPawn(Instigator));
|
|
}
|
|
else if ( CurrentFireMode == DEFAULT_FIREMODE )
|
|
{
|
|
WeldTarget.Weld(CurrentFastenRate, KFPawn(Instigator));
|
|
}
|
|
else
|
|
{
|
|
WeldTarget.Weld(CurrentUnfastenRate, KFPawn(Instigator));
|
|
}
|
|
}
|
|
}
|
|
|
|
// On the local player check to see if we should stop firing
|
|
// It makes sense to do this in ShouldRefire(), but there is no guarantee
|
|
// that it will sync on server/client. So, use StopFire() instead.
|
|
if ( Instigator.IsLocallyControlled() )
|
|
{
|
|
if ( WeldTarget == none || !CanWeldTarget() )
|
|
{
|
|
// TargetDoor is no longer valid
|
|
StopFire(CurrentFireMode);
|
|
}
|
|
}
|
|
}
|
|
|
|
simulated function bool CanWeldTarget( optional int FireModeNum=CurrentFireMode )
|
|
{
|
|
local KFPerk WelderPerk;
|
|
|
|
WelderPerk = GetPerk();
|
|
|
|
if ( FireModeNum == DEFAULT_FIREMODE && !WeldTarget.CanBeWelded() )
|
|
{
|
|
if( WelderPerk != none && WelderPerk.CanExplosiveWeld() )
|
|
{
|
|
return WeldTarget.CanBeDemoWelded();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
else if ( FireModeNum == ALTFIRE_FIREMODE && !WeldTarget.CanBeUnwelded() )
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/** Ammo regen timer */
|
|
function RechargeAmmo()
|
|
{
|
|
if ( AmmoCount[0] < MagazineCapacity[0] )
|
|
{
|
|
AmmoCount[0]++;
|
|
|
|
// If we are holding down the mouse when we regen enough ammo, fire again
|
|
if ( AmmoCount[0] == AmmoCost[0] )
|
|
{
|
|
Refire();
|
|
if ( !Instigator.IsLocallyControlled() )
|
|
{
|
|
ClientRefire();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ClearTimer(nameof(RechargeAmmo));
|
|
}
|
|
}
|
|
|
|
/** If we are holding down the mouse when we regen enough ammo, fire again */
|
|
simulated function Refire()
|
|
{
|
|
local byte i;
|
|
// if either of the fire modes are pending, perform them
|
|
for( i=0; i<=ALTFIRE_FIREMODE; i++ )
|
|
{
|
|
if( PendingFire(i) )
|
|
{
|
|
SendToFiringState(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** RechargeAmmo is called on authority only. When we have enough ammo to fire again
|
|
* we want to make sure that the client plays his animations and fire effects */
|
|
reliable client function ClientRefire()
|
|
{
|
|
Refire();
|
|
}
|
|
|
|
/** If we recieve a valid door target after the fire key was already pressed down */
|
|
simulated function CheckDelayedStartFire()
|
|
{
|
|
local bool bNotifyServer;
|
|
|
|
if ( WeldTarget != None )
|
|
{
|
|
if( PendingFire(DEFAULT_FIREMODE) )
|
|
{
|
|
BeginFire(DEFAULT_FIREMODE);
|
|
bNotifyServer = true;
|
|
}
|
|
else if( PendingFire(ALTFIRE_FIREMODE) )
|
|
{
|
|
BeginFire(ALTFIRE_FIREMODE);
|
|
bNotifyServer = true;
|
|
}
|
|
|
|
if ( bNotifyServer && Role < ROLE_Authority )
|
|
{
|
|
ServerSetWeldTarget(WeldTarget, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************************
|
|
@name Animation
|
|
********************************************************************************************* */
|
|
|
|
/*********************************************************************************************
|
|
@name WeldTarget
|
|
********************************************************************************************* */
|
|
|
|
/**
|
|
* Find doors within welding range
|
|
* Network: Local Player
|
|
*/
|
|
simulated function bool TickWeldTarget()
|
|
{
|
|
local KFWeldableComponent PreviousTarget;
|
|
|
|
// prevent state from changing too often (also a optimization)
|
|
if ( `TimeSince(LastTraceHitTime) < 0.2f )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
PreviousTarget = WeldTarget;
|
|
WeldTarget = TraceWeldables();
|
|
|
|
// refresh idle anim if TargetDoor has changed
|
|
if ( PreviousTarget != WeldTarget )
|
|
{
|
|
return PlayReadyTransition(PreviousTarget);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/** Network: All */
|
|
simulated function KFWeldableComponent TraceWeldables()
|
|
{
|
|
local KFWeldableComponent WeldableComponent;
|
|
local vector HitLoc, HitNorm, StartTrace, EndTrace, AdjustedAim;
|
|
local bool bIsRepairableActor;
|
|
local KFDoorActor WeldableDoor;
|
|
|
|
// define range to use for CalcWeaponFire()
|
|
StartTrace = Instigator.GetWeaponStartTraceLocation();
|
|
AdjustedAim = vector(GetAdjustedAim(StartTrace));
|
|
EndTrace = StartTrace + AdjustedAim * WeldingRange;
|
|
|
|
// Give the welder extra range when it has a WeldTarget to avoid the ready animation
|
|
// activating / deactivating on door that is is currently being damaged
|
|
if( WeldTarget != none )
|
|
{
|
|
EndTrace += AdjustedAim * ExtraWeldingRange;
|
|
}
|
|
|
|
// find weldable (trace against basic cylinder)
|
|
foreach GetTraceOwner().TraceActors(class'KFWeldableComponent', WeldableComponent, HitLoc, HitNorm, EndTrace, StartTrace)
|
|
{
|
|
if (WeldableComponent.Owner == none)
|
|
{
|
|
// should never happen, right?
|
|
continue;
|
|
}
|
|
|
|
// trace against owner for more accuracy
|
|
if (Trace(HitLoc, HitNorm, EndTrace, StartTrace, true) != WeldableComponent.Owner)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
bIsRepairableActor = WeldableComponent.Owner.IsA('KFRepairableActor');
|
|
|
|
if (!bIsRepairableActor && WeldableComponent.bIsDestroyed )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (bIsRepairableActor && !WeldableComponent.CanBeWelded())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
LastTraceHitTime = WorldInfo.TimeSeconds;
|
|
return WeldableComponent;
|
|
}
|
|
|
|
WeldableDoor = FindRepairableDoor();
|
|
return WeldableDoor != none ? WeldableDoor.WeldableComponent : none;
|
|
}
|
|
|
|
/** Try to find a nearby destroyed door. Can't use TraceActors because the door geometry is gone! */
|
|
simulated function KFDoorActor FindRepairableDoor()
|
|
{
|
|
local KFDoorTrigger DoorTrigger;
|
|
local KFInterface_Usable UsableTrigger;
|
|
local float FacingDot;
|
|
local vector Dir2d;
|
|
local KFPlayerController KFPC;
|
|
|
|
// On local player we can detect the interaction message and early out for perf
|
|
// On the server this is only called when firing (instead of on tick) so it's not as bad,
|
|
// but if needed we could add a LastInteractionMessage var to UpdateInteractionMessages()
|
|
if ( Instigator.IsLocallyControlled() )
|
|
{
|
|
KFPC = KFPlayerController(Instigator.Controller);
|
|
if ( KFPC.MyGFxHUD.CurrentInteractionIndex != IMT_RepairDoor )
|
|
{
|
|
return None;
|
|
}
|
|
}
|
|
|
|
UsableTrigger = class'KFPlayerController'.static.GetCurrentUsableActor(Instigator);
|
|
DoorTrigger = KFDoorTrigger(UsableTrigger);
|
|
|
|
// if we didn't find a door that could be welded, maybe there is one that can be repaired?
|
|
if ( DoorTrigger != None && DoorTrigger.DoorActor != None && DoorTrigger.DoorActor.bIsDestroyed )
|
|
{
|
|
// zero Z to give us a 2d dot product
|
|
Dir2d = Normal2d(DoorTrigger.DoorActor.Location - Instigator.Location);
|
|
FacingDot = vector(Instigator.Rotation) dot (Dir2d);
|
|
if ( FacingDot > 0.87 )
|
|
{
|
|
return DoorTrigger.DoorActor;
|
|
}
|
|
}
|
|
|
|
return None;
|
|
}
|
|
|
|
/** Notify server of new WeldTarget for 'HasAmmo' */
|
|
reliable server private function ServerSetWeldTarget(KFWeldableComponent NewTarget, bool bDelayedStart)
|
|
{
|
|
WeldTarget = NewTarget;
|
|
|
|
if ( bDelayedStart )
|
|
{
|
|
CheckDelayedStartFire();
|
|
}
|
|
}
|
|
|
|
/** Play a transition animation between idle ready states */
|
|
simulated function bool PlayReadyTransition(KFWeldableComponent PreviousTarget)
|
|
{
|
|
local name AnimName;
|
|
local float Duration;
|
|
|
|
if( WeldTarget != None )
|
|
{
|
|
AnimName = WeldOpenAnim;
|
|
// set timer to begin firing if PendingFire is already set
|
|
if ( PreviousTarget == None )
|
|
{
|
|
Duration = MySkelMesh.GetAnimLength(AnimName);
|
|
SetTimer(FMax(Duration - 0.2f, 0.01f), false, nameof(CheckDelayedStartFire));
|
|
}
|
|
}
|
|
else if( PreviousTarget != None )
|
|
{
|
|
AnimName = WeldCloseAnim;
|
|
}
|
|
|
|
if ( AnimName != '' )
|
|
{
|
|
PlayAnimation(AnimName);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*********************************************************************************************
|
|
* state Inactive
|
|
* This state is the default state. It needs to make sure Zooming is reset when entering/leaving
|
|
*********************************************************************************************/
|
|
|
|
auto state Inactive
|
|
{
|
|
simulated function BeginState(name PreviousStateName)
|
|
{
|
|
Super.BeginState(PreviousStateName);
|
|
WeldTarget = none;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************************
|
|
* 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
|
|
{
|
|
simulated event Tick(float DeltaTime)
|
|
{
|
|
// Caution - Super will skip our global, but global will skip super's state function!
|
|
Global.Tick(DeltaTime);
|
|
|
|
if ( Instigator != none && Instigator.IsLocallyControlled() )
|
|
{
|
|
// local player - find nearbydoors
|
|
TickWeldTarget(); // will trace each call, but it's decently fast (zero-extent)
|
|
UpdateScreenUI();
|
|
|
|
if (bAutoUnequip)
|
|
{
|
|
TickAutoUnequip();
|
|
}
|
|
}
|
|
}
|
|
|
|
simulated event OnAnimEnd(AnimNodeSequence SeqNode, float PlayedTime, float ExcessTime)
|
|
{
|
|
local bool bPlayingAnim;
|
|
|
|
if ( Instigator != none && Instigator.IsLocallyControlled() )
|
|
{
|
|
// Update target immediately and enable tick (first time)
|
|
bPlayingAnim = TickWeldTarget();
|
|
|
|
// if animation didn't play in UpdateWeldTarget, play idle normally
|
|
if ( !bPlayingAnim )
|
|
{
|
|
PlayIdleAnim();
|
|
}
|
|
}
|
|
}
|
|
|
|
simulated function PlayIdleAnim()
|
|
{
|
|
local int IdleIndex;
|
|
|
|
if ( Instigator != none && Instigator.IsLocallyControlled() )
|
|
{
|
|
if( WeldTarget != None )
|
|
{
|
|
PlayAnimation(IdleWeldAnim, 0.0, true, 0.2);
|
|
}
|
|
else
|
|
{
|
|
IdleIndex = Rand(IdleAnims.Length);
|
|
PlayAnimation(IdleAnims[IdleIndex], 0.0, true, 0.2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Automatically equip previous weapon when leaving a door trigger */
|
|
simulated function bool TickAutoUnequip()
|
|
{
|
|
local Trigger_PawnsOnly Trigger;
|
|
local KFInventoryManager KFIM;
|
|
|
|
ForEach Instigator.TouchingActors(class'Trigger_PawnsOnly', Trigger)
|
|
{
|
|
if(Trigger.IsA('KFDoorTrigger') || Trigger.IsA('KFRepairableActorTrigger') || Trigger.IsA('KFWeldableTrigger'))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
KFIM = KFInventoryManager( Instigator.InvManager );
|
|
if ( KFIM != None )
|
|
{
|
|
KFIM.SwitchToLastWeapon();
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*********************************************************************************************
|
|
* state WeaponWelding
|
|
* This is the default Firing State. It's performed on both the client and the server.
|
|
*********************************************************************************************/
|
|
|
|
simulated state WeaponWelding extends WeaponFiring
|
|
{
|
|
simulated function byte GetWeaponStateId()
|
|
{
|
|
return WEP_Weld;
|
|
}
|
|
|
|
simulated function BeginState(Name PrevStateName)
|
|
{
|
|
super.BeginState(PrevStateName);
|
|
NotifyBeginState();
|
|
}
|
|
|
|
simulated function EndState(Name NextStateName)
|
|
{
|
|
super.EndState(NextStateName);
|
|
NotifyEndState();
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************************
|
|
* state WeaponSprinting
|
|
* When the pawn is sprinting, they need to check if they should auto unequip the welder.
|
|
*********************************************************************************************/
|
|
|
|
simulated state WeaponSprinting
|
|
{
|
|
simulated event Tick(float DeltaTime)
|
|
{
|
|
Global.Tick(DeltaTime);
|
|
|
|
if (Instigator != none && Instigator.IsLocallyControlled())
|
|
{
|
|
if (bAutoUnequip)
|
|
{
|
|
TickAutoUnequip();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
InventoryGroup=IG_None
|
|
bCanThrow=false
|
|
bDropOnDeath=false
|
|
bAutoUnequip=true
|
|
|
|
PlayerViewOffset=(X=20.0,Y=10,Z=-10)
|
|
|
|
FireTweenTime=0.2f
|
|
WeldingRange=150.f
|
|
ExtraWeldingRange=10
|
|
FastenRate=68.f
|
|
UnFastenRate=-110.f
|
|
RepairRate=0.03f //0.05f
|
|
IdleWeldAnim=Idle_Weld
|
|
WeldOpenAnim=Weld_On
|
|
WeldCloseAnim=Weld_Off
|
|
|
|
// Content
|
|
PackageKey="Welder"
|
|
FirstPersonMeshName="WEP_1P_Welder_MESH.Wep_1stP_Welder_Rig"
|
|
FirstPersonAnimSetNames(0)="WEP_1P_Welder_ANIM.Wep_1st_Welder_Anim"
|
|
AttachmentArchetypeName="WEP_Welder_ARCH.Welder_3P"
|
|
MuzzleFlashTemplateName="WEP_Welder_ARCH.Wep_Welder_MuzzleFlash"
|
|
|
|
// Aim Assist
|
|
AimCorrectionSize=0.f
|
|
bTargetAdhesionEnabled=false
|
|
|
|
// Ammo
|
|
MagazineCapacity[0]=100
|
|
SpareAmmoCapacity[0]=0
|
|
bInfiniteSpareAmmo=true
|
|
AmmoRechargeRate=0.08f
|
|
bAllowClientAmmoTracking=false
|
|
|
|
// Grouping
|
|
GroupPriority=5
|
|
WeaponSelectTexture=Texture2D'ui_weaponselect_tex.UI_WeaponSelect_Welder'
|
|
|
|
// Weld
|
|
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Electricity'
|
|
FiringStatesArray(DEFAULT_FIREMODE)=WeaponWelding
|
|
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Custom
|
|
FireInterval(DEFAULT_FIREMODE)=+0.2
|
|
AmmoCost(DEFAULT_FIREMODE)=7
|
|
|
|
// Un-Weld
|
|
FireModeIconPaths(ALTFIRE_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Electricity'
|
|
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponWelding
|
|
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Custom
|
|
FireInterval(ALTFIRE_FIREMODE)=+0.2
|
|
AmmoCost(ALTFIRE_FIREMODE)=7
|
|
|
|
// Fire Effects
|
|
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_SA_Welder.Play_WEP_SA_Welder_Fire_Loop_M', FirstPersonCue=AkEvent'WW_WEP_SA_Welder.Play_WEP_SA_Welder_Fire_Loop_S')
|
|
WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_SA_Welder.Play_WEP_SA_Welder_Fire_Loop_M', FirstPersonCue=AkEvent'WW_WEP_SA_Welder.Play_WEP_SA_Welder_Fire_Loop_S')
|
|
|
|
// BASH_FIREMODE
|
|
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_Welder'
|
|
InstantHitDamage(BASH_FIREMODE)=20
|
|
|
|
// Advanced (High RPM) Fire Effects
|
|
bLoopingFireAnim(DEFAULT_FIREMODE)=true
|
|
bLoopingFireAnim(ALTFIRE_FIREMODE)=true
|
|
bLoopingFireSnd(DEFAULT_FIREMODE)=true
|
|
bLoopingFireSnd(ALTFIRE_FIREMODE)=true
|
|
WeaponFireLoopEndSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_SA_Welder.Stop_WEP_SA_Welder_Fire_Loop_M', FirstPersonCue=AkEvent'WW_WEP_SA_Welder.Stop_WEP_SA_Welder_Fire_Loop_S')
|
|
|
|
ScreenUIClass=class'KFGFxWorld_WelderScreen'
|
|
|
|
AssociatedPerkClasses(0)=none
|
|
|
|
bStorePreviouslyEquipped=false
|
|
}
|