2020-12-13 15:01:13 +00:00
|
|
|
//=============================================================================
|
|
|
|
// KFWeap_AssaultRifle_LazerCutter
|
|
|
|
//=============================================================================
|
|
|
|
// Killing Floor 2
|
|
|
|
// Copyright (C) 2017 Tripwire Interactive LLC
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
class KFWeap_AssaultRifle_LazerCutter extends KFWeap_FlameBase;
|
|
|
|
|
|
|
|
/** The amount of time it takes to reach the next charge level */
|
|
|
|
var float ChargeTimePerLevel;
|
|
|
|
/** How often ammo is consumed once the weapon is fully charged*/
|
|
|
|
var float OverchargeConsumeTime;
|
|
|
|
/** How often ammo is consumed if the weapon is charging*/
|
|
|
|
var float ChargeConsumeTime;
|
|
|
|
/** Total time spent during this weapon charged */
|
|
|
|
var float TotalChargeTime;
|
|
|
|
/** Total time spent charing in this charge level*/
|
|
|
|
var float CurrentChargeTime;
|
|
|
|
/** How often to signal 3p fire effects*/
|
|
|
|
var float FlashInterval;
|
|
|
|
/** Timer for keeping track of when to deal damage to targets in the beam*/
|
|
|
|
var float DamageTime;
|
|
|
|
/** Timer keeping track of how long remains in the beam duration*/
|
|
|
|
var float FiringTime;
|
|
|
|
/** Timer keeping track of when to flash next*/
|
|
|
|
var float FlashTime;
|
|
|
|
|
|
|
|
/** Movement and rotation limits when charging*/
|
|
|
|
var float ChargingRotationSpeedLimit;
|
|
|
|
var float ChargingMovementSpeedModifier;
|
|
|
|
/** Movement and rotation limits when firing*/
|
|
|
|
var array<float> FiringRotationSpeedLimit;
|
|
|
|
var float FiringMovementSpeedModifier;
|
|
|
|
|
|
|
|
/** Base size of the beam*/
|
|
|
|
var float BaseScale;
|
|
|
|
/** Amount to increase the size of the beam per charge level*/
|
|
|
|
var float ScalePerChargeLevel;
|
|
|
|
/** Amount of damage to deal per tick per charge level (added to InstantHitDamage)*/
|
|
|
|
var float DamagePerChargeLevel;
|
|
|
|
/** Firing duration at no charge level*/
|
|
|
|
var float BaseDuration;
|
|
|
|
/** Firing duration added per charge level*/
|
|
|
|
var float DurationPerChargeLevel;
|
|
|
|
/** Highest charge level of the beam*/
|
|
|
|
var int MaxChargeLevel;
|
|
|
|
|
|
|
|
/** Charge in animation */
|
|
|
|
var(Animations) const editconst name AltFireLoopStartAnim;
|
|
|
|
/** Charge animations per level */
|
|
|
|
var(Animations) const editconst name AltFireBeamInAnimL1;
|
|
|
|
var(Animations) const editconst name AltFireBeamInAnimL2;
|
|
|
|
var(Animations) const editconst name AltFireBeamInAnimL3;
|
|
|
|
/** Animations to loop if stuck at a charge level*/
|
|
|
|
var(Animations) const editconst name AltFireLoopAnimL1;
|
|
|
|
var(Animations) const editconst name AltFireLoopAnimL2;
|
|
|
|
var(Animations) const editconst name AltFireLoopAnimL3;
|
|
|
|
/** Firing animations per level */
|
|
|
|
var(Animations) const editconst name CustomFireLoopAnimL1;
|
|
|
|
var(Animations) const editconst name CustomFireLoopAnimL2;
|
|
|
|
var(Animations) const editconst name CustomFireLoopAnimL3;
|
|
|
|
/** Firing end animations */
|
|
|
|
var(Animations) const editconst name CustomFireLoopEndLastAnim;
|
|
|
|
var(Animations) const editconst name CustomFireLoopEndAnim;
|
|
|
|
|
|
|
|
/** Muzzle flash effects per level */
|
|
|
|
var const ParticleSystem MuzzleFlashEffectL1;
|
|
|
|
var const ParticleSystem MuzzleFlashEffectL2;
|
|
|
|
var const ParticleSystem MuzzleFlashEffectL3;
|
|
|
|
|
|
|
|
/** Looping sound event for when the beam is firing */
|
|
|
|
var array<WeaponFireSndInfo> FireLoopSounds;
|
|
|
|
/** Sound event to kill the looping firing beam when it ends*/
|
|
|
|
var WeaponFireSndInfo FireLoopStop;
|
|
|
|
/** Looping sound event for when the beam is charing */
|
|
|
|
var array<WeaponFireSndInfo> ChargeSounds;
|
|
|
|
/** Kill all sounds events on the weapon*/
|
|
|
|
var WeaponFireSndInfo InterruptSoundEvent;
|
|
|
|
/** Sound info for the full auto mode when in zed time*/
|
|
|
|
var WeaponFireSndInfo SingleShotFireSnd;
|
|
|
|
|
|
|
|
/** Color for the weapon center when charging/firing*/
|
|
|
|
var LinearColor DefaultFireModeColor;
|
|
|
|
var LinearColor EnergyColorL0;
|
|
|
|
var LinearColor EnergyColorL1;
|
|
|
|
var LinearColor EnergyColorL2;
|
|
|
|
var LinearColor EnergyColorL3;
|
|
|
|
|
|
|
|
/** Effect that happens while charging up the beam*/
|
|
|
|
var transient ParticleSystemComponent ChargingPSC;
|
|
|
|
var const ParticleSystem ChargingEffect;
|
|
|
|
|
|
|
|
/** Amount of time over which to reduce the rotation speed limit back to normal*/
|
|
|
|
var float MaxRotationAdjustmentTime;
|
|
|
|
/** Curve used for determining how much to reduce the rotation speed to*/
|
|
|
|
var InterpCurveFloat RotationAdjustmentCurve;
|
|
|
|
|
|
|
|
/** Used to gate the beam firing muzzle flash to only play once after the beam starts */
|
|
|
|
var bool bPlayMuzzleFlash;
|
|
|
|
|
|
|
|
simulated function Activate()
|
|
|
|
{
|
|
|
|
super.Activate();
|
|
|
|
|
|
|
|
SetBeamColor(0); // set the initial beam color
|
|
|
|
}
|
|
|
|
|
|
|
|
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 CustomFire()
|
|
|
|
{
|
|
|
|
// tell remote clients that we fired, to trigger effects
|
|
|
|
if (CurrentFireMode == CUSTOM_FIREMODE)
|
|
|
|
{
|
|
|
|
IncrementFlashCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
super.CustomFire();
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function AltFireMode()
|
|
|
|
{
|
|
|
|
super.AltFireMode();
|
|
|
|
|
|
|
|
// different beam colors for different fire modes
|
|
|
|
SetBeamColor(GetChargeLevel());
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function int GetChargeLevel()
|
|
|
|
{
|
|
|
|
return Min(TotalChargeTime / ChargeTimePerLevel, MaxChargeLevel);
|
|
|
|
}
|
|
|
|
|
|
|
|
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 (CurrentFireMode == DEFAULT_FIREMODE)
|
|
|
|
{
|
|
|
|
ConsumeAmmo(CurrentFireMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
NotifyWeaponFired(CurrentFireMode);
|
|
|
|
|
|
|
|
// Play fire effects now (don't wait for WeaponFired to replicate)
|
|
|
|
PlayFireEffects(CurrentFireMode, vect(0, 0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function name GetLoopStartFireAnim(byte FireModeNum)
|
|
|
|
{
|
|
|
|
if (FireModeNum == ALTFIRE_FIREMODE)
|
|
|
|
{
|
|
|
|
return AltFireLoopStartAnim;
|
|
|
|
}
|
|
|
|
else if (FireModeNum == CUSTOM_FIREMODE)
|
|
|
|
{
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.GetLoopStartFireAnim(FireModeNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function name GetLoopEndFireAnim(byte FireModeNum)
|
|
|
|
{
|
|
|
|
local bool bPlayFireLast;
|
|
|
|
|
|
|
|
if (FireModeNum == ALTFIRE_FIREMODE)
|
|
|
|
{
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
else if (FireModeNum == CUSTOM_FIREMODE)
|
|
|
|
{
|
|
|
|
bPlayFireLast = ShouldPlayFireLast(FireModeNum);
|
|
|
|
|
|
|
|
if (bPlayFireLast && CustomFireLoopEndLastAnim != '')
|
|
|
|
{
|
|
|
|
return CustomFireLoopEndLastAnim;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return CustomFireLoopEndAnim;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.GetLoopEndFireAnim(FireModeNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function name GetLoopingFireAnim(byte FireModeNum)
|
|
|
|
{
|
|
|
|
if (FireModeNum == ALTFIRE_FIREMODE)
|
|
|
|
{
|
|
|
|
return AltFireLoopStartAnim;
|
|
|
|
}
|
|
|
|
else if (FireModeNum == CUSTOM_FIREMODE)
|
|
|
|
{
|
|
|
|
switch (GetChargeLevel())
|
|
|
|
{
|
|
|
|
case 3:
|
|
|
|
return CustomFireLoopAnimL3;
|
|
|
|
case 2:
|
|
|
|
return CustomFireLoopAnimL2;
|
|
|
|
case 1:
|
|
|
|
case 0:
|
|
|
|
return CustomFireLoopAnimL1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.GetLoopingFireAnim(FireModeNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function CauseMuzzleFlash(byte FireModeNum)
|
|
|
|
{
|
|
|
|
if (MuzzleFlash == None)
|
|
|
|
{
|
|
|
|
AttachMuzzleFlash();
|
|
|
|
}
|
|
|
|
|
|
|
|
// swap the muzzle flash per charge level (this should do nothing for full-auto)
|
|
|
|
if (MuzzleFlash != none)
|
|
|
|
{
|
|
|
|
if (FireModeNum == CUSTOM_FIREMODE)
|
|
|
|
{
|
|
|
|
if (bPlayMuzzleFlash)
|
|
|
|
{
|
|
|
|
switch (GetChargeLevel())
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
bPlayMuzzleFlash = false;
|
|
|
|
// setting to 0 so that the muzzle flash doesn't get turned off based on a timer
|
|
|
|
MuzzleFlash.MuzzleFlash.Duration = 0.0f;
|
|
|
|
super.CauseMuzzleFlash(FireModeNum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// otherwise use the default
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MuzzleFlash.MuzzleFlash.ParticleSystemTemplate = MuzzleFlashTemplate.MuzzleFlash.ParticleSystemTemplate;
|
|
|
|
MuzzleFlash.MuzzleFlash.PSC.SetTemplate(MuzzleFlashTemplate.MuzzleFlash.ParticleSystemTemplate);
|
|
|
|
MuzzleFlash.MuzzleFlash.Duration = MuzzleFlashTemplate.MuzzleFlash.Duration;
|
|
|
|
super.CauseMuzzleFlash(FireModeNum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function SetBeamColor(int ChargeLevel)
|
|
|
|
{
|
|
|
|
local LinearColor BeamColor;
|
|
|
|
local int i;
|
|
|
|
|
|
|
|
if (bUseAltFireMode)
|
|
|
|
{
|
|
|
|
switch (ChargeLevel)
|
|
|
|
{
|
|
|
|
case 3:
|
|
|
|
BeamColor = EnergyColorL3;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
BeamColor = EnergyColorL2;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
BeamColor = EnergyColorL1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BeamColor = EnergyColorL0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BeamColor = DefaultFireModeColor;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WorldInfo.NetMode != NM_DedicatedServer)
|
|
|
|
{
|
|
|
|
for (i = 0; i < WeaponMICs.Length; ++i)
|
|
|
|
{
|
|
|
|
if (WeaponMICs[i] != none)
|
|
|
|
{
|
|
|
|
WeaponMICs[i].SetVectorParameterValue('Energy_Color', BeamColor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** True if we want to override the looping fire sounds with fire sounds from another firemode
|
|
|
|
* Overrides the KFWeapon functionality because the LaserCutter doesn't have a SingleFireSoundIndex but still has a single fire sound
|
|
|
|
*/
|
|
|
|
simulated function bool ShouldForceSingleFireSound()
|
|
|
|
{
|
|
|
|
// If this weapon has a single-shot firemode, disable looping fire sounds during zedtime
|
|
|
|
return `IsInZedTime(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tells the weapon to play a firing sound (uses CurrentFireMode)
|
|
|
|
* Overrides the base KFWeapon functionality because the LazerCutter has a different way of finding the single shot sound
|
|
|
|
*/
|
|
|
|
simulated function PlayFiringSound(byte FireModeNum)
|
|
|
|
{
|
|
|
|
local bool bUseSingleFireSound;
|
|
|
|
|
|
|
|
MakeNoise(1.0, 'PlayerFiring'); // AI
|
|
|
|
|
|
|
|
if (!bPlayingLoopingFireSnd)
|
|
|
|
{
|
|
|
|
// Use the single fire sound if we're in zed time and want to play single fire sounds
|
|
|
|
if (FireModeNum < bLoopingFireSnd.Length && bLoopingFireSnd[FireModeNum] && ShouldForceSingleFireSound())
|
|
|
|
{
|
|
|
|
bUseSingleFireSound = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bUseSingleFireSound)
|
|
|
|
{
|
|
|
|
WeaponPlayFireSound(SingleShotFireSnd.DefaultCue, SingleShotFireSnd.FirstPersonCue);
|
|
|
|
}
|
|
|
|
else if (FireModeNum < WeaponFireSnd.Length)
|
|
|
|
{
|
|
|
|
WeaponPlayFireSound(WeaponFireSnd[FireModeNum].DefaultCue, WeaponFireSnd[FireModeNum].FirstPersonCue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// which category this shows up under in the trader
|
|
|
|
// FlameBase defaults to Flame, so this needs to override
|
|
|
|
static simulated event EFilterTypeUI GetTraderFilter()
|
|
|
|
{
|
|
|
|
return FT_Electric;
|
|
|
|
}
|
|
|
|
|
|
|
|
static simulated event EFilterTypeUI GetAltTraderFilter()
|
|
|
|
{
|
|
|
|
return FT_Assault;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the FlameBase CalculateTraderWeaponStatDamage uses spray damage
|
|
|
|
// LazerCutter will just show the full auto damage like a normal KFWeapon
|
|
|
|
static simulated function float CalculateTraderWeaponStatDamage()
|
|
|
|
{
|
|
|
|
local float CalculatedDamage;
|
|
|
|
CalculatedDamage = default.InstantHitDamage[DEFAULT_FIREMODE];
|
|
|
|
return CalculatedDamage;
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated state LazerCharge extends WeaponFiring
|
|
|
|
{
|
|
|
|
simulated function FireAmmunition(){}
|
|
|
|
|
|
|
|
simulated function bool AllowIronSights() { return false; }
|
|
|
|
|
|
|
|
// can't switch fire modes when charging or firing the beam
|
|
|
|
simulated function AltFireMode() {}
|
|
|
|
simulated function AltFireModeRelease() {}
|
|
|
|
|
|
|
|
simulated event OnAnimEnd(AnimNodeSequence SeqNode, float PlayedTime, float ExcessTime)
|
|
|
|
{
|
|
|
|
local name WeaponFireAnimName;
|
|
|
|
|
|
|
|
if (WorldInfo.NetMode != NM_DedicatedServer)
|
|
|
|
{
|
|
|
|
if (AmmoCount[DEFAULT_FIREMODE] == 0)
|
|
|
|
{
|
|
|
|
// get the next looping animation we have and play that instead
|
|
|
|
// this will happen when a player gets stuck at a level by running out of ammo
|
|
|
|
switch (GetChargeLevel())
|
|
|
|
{
|
|
|
|
case 3:
|
|
|
|
case 2:
|
|
|
|
WeaponFireAnimName = AltFireLoopAnimL3;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
WeaponFireAnimName = AltFireLoopAnimL2;
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
WeaponFireAnimName = AltFireLoopAnimL1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// if an animation has ended early and the player still has ammo
|
|
|
|
// continue onto the next beam in animation
|
|
|
|
switch (GetChargeLevel())
|
|
|
|
{
|
|
|
|
case 3:
|
|
|
|
// once it hits the max level it just loops
|
|
|
|
WeaponFireAnimName = AltFireLoopAnimL3;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
WeaponFireAnimName = AltFireBeamInAnimL2;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
WeaponFireAnimName = AltFireBeamInAnimL1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WeaponFireAnimName != '' && WeaponAnimSeqNode.AnimSeq.SequenceName != WeaponFireAnimName)
|
|
|
|
{
|
|
|
|
PlayAnimation(WeaponFireAnimName, MySkelMesh.GetAnimLength(WeaponFireAnimName), AmmoCount[DEFAULT_FIREMODE] == 0, FireTweenTime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated event BeginState(Name PreviousStateName)
|
|
|
|
{
|
|
|
|
local KFPawn_Human OwnerHuman;
|
|
|
|
local KFPlayerController OwnerController;
|
|
|
|
OwnerHuman = KFPawn_Human(Instigator);
|
|
|
|
|
|
|
|
super.BeginState(PreviousStateName);
|
|
|
|
|
|
|
|
// reset charging variables
|
|
|
|
TotalChargeTime = 0;
|
|
|
|
CurrentChargeTime = 0;
|
|
|
|
DamageTime = 0;
|
|
|
|
FiringTime = 0;
|
|
|
|
FlashTime = 0;
|
|
|
|
|
|
|
|
// slow down the player's movement and rotation when charging
|
|
|
|
MovementSpeedMod = ChargingMovementSpeedModifier;
|
|
|
|
if (OwnerHuman != None)
|
|
|
|
{
|
|
|
|
OwnerController = KFPlayerController(OwnerHuman.Controller);
|
|
|
|
if (OwnerController != none)
|
|
|
|
{
|
|
|
|
OwnerController.RotationSpeedLimit = ChargingRotationSpeedLimit;
|
|
|
|
}
|
|
|
|
OwnerHuman.UpdateGroundSpeed();
|
|
|
|
}
|
|
|
|
|
|
|
|
// kick the player out of ironsights (no ironsights when shooting the beam)
|
|
|
|
if (bUsingSights)
|
|
|
|
{
|
|
|
|
SetIronSights(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// setup the charging particle effect
|
|
|
|
// setup the charging particle effect
|
|
|
|
if (ChargingPSC == none)
|
|
|
|
{
|
|
|
|
ChargingPSC = new(self) class'ParticleSystemComponent';
|
|
|
|
|
|
|
|
if (MySkelMesh != none)
|
|
|
|
{
|
|
|
|
MySkelMesh.AttachComponentToSocket(ChargingPSC, 'MuzzleFlash');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
AttachComponent(ChargingPSC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ChargingPSC.ActivateSystem();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ChargingPSC != none)
|
|
|
|
{
|
|
|
|
ChargingPSC.SetTemplate(ChargingEffect);
|
|
|
|
}
|
|
|
|
|
|
|
|
global.OnStartFire();
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function bool ShouldRefire()
|
|
|
|
{
|
|
|
|
// ignore how much ammo is left (super/global counts ammo)
|
|
|
|
return StillFiring(CurrentFireMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated event Tick(float DeltaTime)
|
|
|
|
{
|
|
|
|
local float ConsumeTime, ChargeRTPC;
|
|
|
|
local name WeaponFireAnimName;
|
|
|
|
local int StartChargeLevel, EndChargeLevel;
|
|
|
|
|
|
|
|
global.Tick(DeltaTime);
|
|
|
|
|
|
|
|
StartChargeLevel = GetChargeLevel();
|
|
|
|
|
|
|
|
FlashTime += DeltaTime;
|
|
|
|
ConsumeTime = GetChargeLevel() >= MaxChargeLevel ? OverchargeConsumeTime : ChargeConsumeTime;
|
|
|
|
|
|
|
|
// Don't charge unless we're holding down the button and still have ammo
|
|
|
|
if (PendingFire(CurrentFireMode) && AmmoCount[DEFAULT_FIREMODE] > 0)
|
|
|
|
{
|
|
|
|
TotalChargeTime += DeltaTime;
|
|
|
|
CurrentChargeTime += DeltaTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ConsumeTime > 0)
|
|
|
|
{
|
|
|
|
// consume ammo whenever the charge level goes up
|
|
|
|
while (CurrentChargeTime >= ConsumeTime)
|
|
|
|
{
|
|
|
|
CurrentChargeTime -= ConsumeTime;
|
|
|
|
ConsumeAmmo(ALTFIRE_FIREMODE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// triggers 3p visual effects/anims
|
|
|
|
while (FlashTime >= FlashInterval)
|
|
|
|
{
|
|
|
|
FlashTime -= FlashInterval;
|
|
|
|
IncrementFlashCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
EndChargeLevel = GetChargeLevel();
|
|
|
|
// whenever the charge level increases, check to play a new shoot loop animation
|
|
|
|
if (EndChargeLevel != StartChargeLevel)
|
|
|
|
{
|
|
|
|
// play a sound event for the new charge level
|
|
|
|
if (EndChargeLevel >= 0 && EndChargeLevel < ChargeSounds.Length)
|
|
|
|
{
|
|
|
|
StartLoopingFireSound(CurrentFireMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
// play the animation for the next charge level, these will loop if sitting in this state
|
|
|
|
if (bPlayingLoopingFireAnim)
|
|
|
|
{
|
|
|
|
switch (GetChargeLevel())
|
|
|
|
{
|
|
|
|
case 3:
|
|
|
|
// once it hits the max level it just loops
|
|
|
|
WeaponFireAnimName = AltFireLoopAnimL3;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
WeaponFireAnimName = AltFireBeamInAnimL2;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
WeaponFireAnimName = AltFireBeamInAnimL1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WeaponFireAnimName != '' && WeaponAnimSeqNode.AnimSeq.SequenceName != WeaponFireAnimName)
|
|
|
|
{
|
|
|
|
PlayAnimation(WeaponFireAnimName, MySkelMesh.GetAnimLength(WeaponFireAnimName), GetChargeLevel() == 3, FireTweenTime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// set the beam color based on the current charge level
|
|
|
|
SetBeamColor(GetChargeLevel());
|
|
|
|
|
|
|
|
// set an RTPC for charging sounds
|
|
|
|
ChargeRTPC = FMin(TotalChargeTime / (MaxChargeLevel * ChargeTimePerLevel), 1.f);
|
|
|
|
KFPawn(Instigator).SetWeaponComponentRTPCValue("Weapon_Charge", ChargeRTPC); //For looping component
|
|
|
|
Instigator.SetRTPCValue('Weapon_Charge', ChargeRTPC); //For one-shot sounds
|
|
|
|
}
|
|
|
|
|
|
|
|
//Now that we're done charging, directly call FireAmmunition. This will handle the actual projectile fire and scaling.
|
|
|
|
simulated function EndState(Name NextStateName)
|
|
|
|
{
|
|
|
|
local KFPawn_Human OwnerHuman;
|
|
|
|
local KFPlayerController OwnerController;
|
|
|
|
|
|
|
|
OwnerHuman = KFPawn_Human(Instigator);
|
|
|
|
|
|
|
|
// reset the player's movement and rotation speed
|
|
|
|
MovementSpeedMod = 1.f;
|
|
|
|
|
|
|
|
if (OwnerHuman != None)
|
|
|
|
{
|
|
|
|
OwnerController = KFPlayerController(OwnerHuman.Controller);
|
|
|
|
if (OwnerController != none)
|
|
|
|
{
|
|
|
|
OwnerController.RotationSpeedLimit = -1.f;
|
|
|
|
}
|
|
|
|
OwnerHuman.UpdateGroundSpeed();
|
|
|
|
}
|
|
|
|
|
|
|
|
ClearZedTimeResist();
|
|
|
|
ClearPendingFire(CurrentFireMode);
|
|
|
|
ClearTimer(nameof(RefireCheckTimer));
|
|
|
|
|
|
|
|
NotifyWeaponFinishedFiring(CurrentFireMode);
|
|
|
|
|
|
|
|
KFPawn(Instigator).bHasStartedFire = false;
|
|
|
|
KFPawn(Instigator).bNetDirty = true;
|
|
|
|
|
|
|
|
super.EndState(NextStateName);
|
|
|
|
}
|
|
|
|
|
|
|
|
function DropFrom(vector StartLocation, vector StartVelocity)
|
|
|
|
{
|
|
|
|
global.DropFrom(StartLocation, StartVelocity);
|
|
|
|
|
|
|
|
if (Instigator == none)
|
|
|
|
{
|
|
|
|
// weapon was actually dropped
|
|
|
|
WeaponAnimSeqNode.StopAnim();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function PutDownWeapon()
|
|
|
|
{
|
|
|
|
TotalChargeTime = 0;
|
|
|
|
CurrentChargeTime = 0;
|
|
|
|
|
|
|
|
global.PutDownWeapon();
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function HandleFinishedFiring()
|
|
|
|
{
|
|
|
|
SendToFiringState(CUSTOM_FIREMODE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated state SprayingFireLazer extends SprayingFire
|
|
|
|
{
|
|
|
|
simulated function bool AllowIronSights() { return false; }
|
|
|
|
|
|
|
|
// can't switch fire modes when charging or firing the beam
|
|
|
|
simulated function AltFireMode(){}
|
|
|
|
simulated function AltFireModeRelease(){}
|
|
|
|
|
|
|
|
simulated function BeginState(Name PreviousStateName)
|
|
|
|
{
|
|
|
|
local KFPawn_Human OwnerHuman;
|
|
|
|
local KFPlayerController OwnerController;
|
|
|
|
local float ChargeLevel;
|
|
|
|
OwnerHuman = KFPawn_Human(Instigator);
|
|
|
|
ChargeLevel = GetChargeLevel();
|
|
|
|
|
|
|
|
// play the muzzle flash once (it will then stick around until firing is over)
|
|
|
|
bPlayMuzzleFlash = true;
|
|
|
|
|
|
|
|
// reset firing variables
|
|
|
|
FlashTime = 0;
|
|
|
|
|
|
|
|
// If we're firing without charging, still consume one ammo
|
|
|
|
if (TotalChargeTime < ChargeConsumeTime)
|
|
|
|
{
|
|
|
|
ConsumeAmmo(CurrentFireMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
// slow down the player's movement and rotation when firing
|
|
|
|
MovementSpeedMod = FiringMovementSpeedModifier;
|
|
|
|
if (OwnerHuman != None)
|
|
|
|
{
|
|
|
|
OwnerController = KFPlayerController(OwnerHuman.Controller);
|
|
|
|
if (OwnerController != none)
|
|
|
|
{
|
|
|
|
if (ChargeLevel >= 0 && ChargeLevel < FiringRotationSpeedLimit.Length)
|
|
|
|
{
|
|
|
|
OwnerController.RotationSpeedLimit = FiringRotationSpeedLimit[ChargeLevel];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OwnerHuman.UpdateGroundSpeed();
|
|
|
|
}
|
|
|
|
|
|
|
|
// the firing time will be used to determine how long the firing portion will last
|
|
|
|
// scale this based on the charge level
|
|
|
|
FiringTime = BaseDuration + ChargeLevel * DurationPerChargeLevel;
|
|
|
|
|
|
|
|
// kick the player out of ironsights (no ironsights when shooting the beam)
|
|
|
|
if (bUsingSights)
|
|
|
|
{
|
|
|
|
SetIronSights(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// stop the charging particle system
|
|
|
|
if (ChargingPSC != none)
|
|
|
|
{
|
|
|
|
ChargingPSC.DeactivateSystem();
|
|
|
|
}
|
|
|
|
|
|
|
|
super.BeginState(PreviousStateName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// show debug boxes around the bones used for tracing collisions
|
|
|
|
simulated function DebugRenderBones()
|
|
|
|
{
|
|
|
|
local Vector BoneLoc;
|
|
|
|
local string BoneString;
|
|
|
|
local int x, y;
|
|
|
|
local vector BoxExtent;
|
|
|
|
|
|
|
|
for (x = 0; x < ArrayCount(FlamePool); x++)
|
|
|
|
{
|
|
|
|
for (y = 1; y <= 15; y++)
|
|
|
|
{
|
|
|
|
BoxExtent.X = BaseScale + ScalePerChargeLevel * (GetChargeLevel() - 1);
|
|
|
|
BoxExtent.Y = BaseScale + ScalePerChargeLevel * (GetChargeLevel() - 1);
|
|
|
|
BoxExtent.Z = 1;
|
|
|
|
|
|
|
|
BoneString = "Bone";
|
|
|
|
if (y < 10)
|
|
|
|
{
|
|
|
|
BoneString $= "0";
|
|
|
|
}
|
|
|
|
BoneString $= string(y);
|
|
|
|
|
|
|
|
BoneLoc = FlamePool[x].SkeletalSprayMesh.GetBoneLocation(name(BoneString));
|
|
|
|
DrawDebugBox(BoneLoc, BoxExtent, 255, 255, 0, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function DamageActorsCheck()
|
|
|
|
{
|
|
|
|
local KFPawn HitPawn;
|
|
|
|
local vector BeamExtent, SmallBeamExtent;
|
|
|
|
local int FlamePoolCounter, BoneCounter;
|
|
|
|
local string BoneString;
|
|
|
|
local vector BoneLoc, PrevBoneLoc;
|
|
|
|
local KFPawn OwnerPawn;
|
|
|
|
local int CurrentCollisions;
|
|
|
|
local array<KFPawn> AlreadyHitActors;
|
|
|
|
local array<Actor> HitDamageActors;
|
|
|
|
local array<Actor> HitBeamActors;
|
|
|
|
local array<vector> DamageHitLocations;
|
|
|
|
local array<vector> BeamHitLocations;
|
|
|
|
local vector HitLocation;
|
|
|
|
local int i;
|
|
|
|
|
|
|
|
// scale the size of the damage collision volume based on the charge level
|
|
|
|
BeamExtent.X = BaseScale + ScalePerChargeLevel * (GetChargeLevel() - 1);
|
|
|
|
BeamExtent.Y = BaseScale + ScalePerChargeLevel * (GetChargeLevel() - 1);
|
|
|
|
BeamExtent.Z = 1;
|
|
|
|
// matching the extent size of the spray actor
|
|
|
|
SmallBeamExtent.X = 8.f;
|
|
|
|
SmallBeamExtent.Y = 8.f;
|
|
|
|
SmallBeamExtent.Z = 8.f;
|
|
|
|
|
|
|
|
CurrentCollisions = 0;
|
|
|
|
OwnerPawn = KFPawn(Owner);
|
|
|
|
|
|
|
|
for (FlamePoolCounter = 0; FlamePoolCounter < ArrayCount(FlamePool); FlamePoolCounter++)
|
|
|
|
{
|
|
|
|
// assumes 15 bones used in the laser mesh
|
|
|
|
for (BoneCounter = 1; BoneCounter < 15; BoneCounter++)
|
|
|
|
{
|
|
|
|
BoneString = "Bone";
|
|
|
|
if (BoneCounter < 10)
|
|
|
|
{
|
|
|
|
BoneString $= "0";
|
|
|
|
}
|
|
|
|
BoneString $= string(BoneCounter);
|
|
|
|
|
|
|
|
BoneLoc = FlamePool[FlamePoolCounter].SkeletalSprayMesh.GetBoneLocation(name(BoneString));
|
|
|
|
if (BoneCounter != 1)
|
|
|
|
{
|
|
|
|
if(CurrentCollisions < FlamePool[FlamePoolCounter].MaxSprayMeshesCollided)
|
|
|
|
{
|
|
|
|
// large damage collision radius
|
|
|
|
HitDamageActors = BeamLineCheck(PrevBoneLoc, BoneLoc, BeamExtent, DamageHitLocations);
|
|
|
|
// smaller box for the beam itself
|
|
|
|
HitBeamActors = BeamLineCheck(PrevBoneLoc, BoneLoc, SmallBeamExtent, BeamHitLocations);
|
|
|
|
|
|
|
|
// stop the beam if the actual laser (small extent) looks like it would collide with something
|
|
|
|
// but until then still do damage in the larger area based on charge level
|
|
|
|
// this will mean that the beam can hit people around small corners at high charge levels
|
|
|
|
// but it won't be stuck as easily on when super charged
|
|
|
|
for(i = 0; i < HitDamageActors.Length; i++)
|
|
|
|
{
|
|
|
|
if (CurrentCollisions < FlamePool[FlamePoolCounter].MaxSprayMeshesCollided)
|
|
|
|
{
|
|
|
|
HitPawn = KFPawn(HitDamageActors[i]);
|
|
|
|
// hit another pawn in the world
|
|
|
|
if (HitPawn != none && HitPawn.Base != Owner && HitPawn != Owner && HitPawn.bBlockActors && AlreadyHitActors.Find(HitPawn) == INDEX_NONE)
|
|
|
|
{
|
|
|
|
CurrentCollisions++;
|
|
|
|
// keep track of which actors were hit so fat actors don't get caught multiple times
|
|
|
|
AlreadyHitActors.AddItem(HitPawn);
|
|
|
|
|
|
|
|
HitLocation = vect(0, 0, 0);
|
|
|
|
if (DamageHitLocations.Length > i)
|
|
|
|
{
|
|
|
|
HitLocation = DamageHitLocations[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
// scale the damage based on charge level, using the InstantHitDamage as the base
|
|
|
|
HitPawn.TakeDamage(InstantHitDamage[ALTFIRE_FIREMODE] + GetChargeLevel() * DamagePerChargeLevel, OwnerPawn.Controller, HitLocation, vect(0, 0, 0), InstantHitDamageTypes[ALTFIRE_FIREMODE],,self);
|
|
|
|
}
|
|
|
|
// hit world geometry (with small extent), set to max collisions to stop the beam
|
|
|
|
else if (HitDamageActors[i] != none && HitDamageActors[i].Base != Owner && HitDamageActors[i] != Owner && HitDamageActors[i].bBlockActors && HitDamageActors[i].bWorldGeometry && HitBeamActors.Find(HitDamageActors[i]) != INDEX_NONE)
|
|
|
|
{
|
|
|
|
CurrentCollisions = FlamePool[FlamePoolCounter].MaxSprayMeshesCollided;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PrevBoneLoc = BoneLoc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated event Tick(float DeltaTime)
|
|
|
|
{
|
|
|
|
global.Tick(DeltaTime);
|
|
|
|
|
|
|
|
if (FiringTime > 0.0f)
|
|
|
|
{
|
|
|
|
FiringTime -= DeltaTime;
|
|
|
|
DamageTime += DeltaTime;
|
|
|
|
FlashTime += DeltaTime;
|
|
|
|
|
|
|
|
// check for damaging actors after a set interval
|
|
|
|
while (DamageTime >= FireInterval[ALTFIRE_FIREMODE])
|
|
|
|
{
|
|
|
|
DamageTime -= FireInterval[ALTFIRE_FIREMODE];
|
|
|
|
DamageActorsCheck();
|
|
|
|
}
|
|
|
|
|
|
|
|
// triggers 3p visual effects/anims
|
|
|
|
while (FlashTime >= FlashInterval)
|
|
|
|
{
|
|
|
|
FlashTime -= FlashInterval;
|
|
|
|
IncrementFlashCount();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// when the charge/firing time is over, exit this state
|
|
|
|
GotoState('Active');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function EndState(Name NextStateName)
|
|
|
|
{
|
|
|
|
local int FlamePoolCounter;
|
|
|
|
local KFPawn_Human OwnerHuman;
|
|
|
|
local KFPlayerController OwnerController;
|
|
|
|
OwnerHuman = KFPawn_Human(Instigator);
|
|
|
|
|
|
|
|
// reset the player's movement and rotation speed modifiers
|
|
|
|
MovementSpeedMod = 1.f;
|
|
|
|
if (OwnerHuman != None)
|
|
|
|
{
|
|
|
|
OwnerController = KFPlayerController(OwnerHuman.Controller);
|
|
|
|
if (OwnerController != none)
|
|
|
|
{
|
|
|
|
// set the starting point for the rotation curve to line up with the current speed limit
|
|
|
|
if(RotationAdjustmentCurve.Points.Length > 0)
|
|
|
|
{
|
|
|
|
RotationAdjustmentCurve.Points[0].OutVal = OwnerController.RotationSpeedLimit;
|
|
|
|
}
|
|
|
|
|
|
|
|
OwnerController.StartRotationAdjustment(RotationAdjustmentCurve, MaxRotationAdjustmentTime);
|
|
|
|
}
|
|
|
|
OwnerHuman.UpdateGroundSpeed();
|
|
|
|
}
|
|
|
|
|
|
|
|
// reset the mesh size
|
|
|
|
for (FlamePoolCounter = 0; FlamePoolCounter < ArrayCount(FlamePool); FlamePoolCounter++)
|
|
|
|
{
|
|
|
|
FlamePool[FlamePoolCounter].SkeletalSprayMesh.SetScale(1.f);
|
|
|
|
}
|
|
|
|
|
|
|
|
// manually turn off the muzzle flash since these won't kill themselves
|
|
|
|
if (MuzzleFlash.MuzzleFlash.PSC != none)
|
|
|
|
{
|
|
|
|
MuzzleFlash.MuzzleFlash.PSC.DeactivateSystem();
|
|
|
|
}
|
|
|
|
|
|
|
|
// return the beam color back to the default
|
|
|
|
SetBeamColor(0);
|
|
|
|
|
|
|
|
// reset charging variables
|
|
|
|
TotalChargeTime = 0;
|
|
|
|
CurrentChargeTime = 0;
|
|
|
|
DamageTime = 0;
|
|
|
|
FiringTime = 0;
|
|
|
|
FlashTime = 0;
|
|
|
|
ClearFlashLocation();
|
|
|
|
ClearTimer('RefireCheckTimer');
|
|
|
|
ClearPendingFire(0);
|
|
|
|
|
|
|
|
super.EndState(NextStateName);
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function bool ShouldRefire()
|
|
|
|
{
|
|
|
|
return FiringTime > 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function bool IsFiring()
|
|
|
|
{
|
|
|
|
return FiringTime > 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function bool TryPutDown()
|
|
|
|
{
|
|
|
|
// can't put down when firing
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
simulated function StartLoopingFireSound(byte FireModeNum)
|
|
|
|
{
|
|
|
|
local float ChargeLevel;
|
|
|
|
|
|
|
|
switch (FireModeNum)
|
|
|
|
{
|
|
|
|
case ALTFIRE_FIREMODE:
|
|
|
|
ChargeLevel = GetChargeLevel();
|
|
|
|
WeaponFireSnd[FireModeNum] = FireLoopSounds[ChargeLevel];
|
|
|
|
break;
|
|
|
|
case CUSTOM_FIREMODE:
|
|
|
|
ChargeLevel = GetChargeLevel();
|
|
|
|
WeaponFireSnd[FireModeNum] = ChargeSounds[ChargeLevel];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
super.StartLoopingFireSound(FireModeNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
defaultproperties
|
|
|
|
{
|
|
|
|
FlameSprayArchetype = SprayActor_Flame'WEP_Laser_Cutter_ARCH.WEP_Laser_Cutter_Flame'
|
|
|
|
|
2023-09-21 19:31:11 +00:00
|
|
|
ChargeTimePerLevel = 0.7f;
|
2023-10-17 23:03:17 +00:00
|
|
|
ChargeConsumeTime = 0.084f; //Consumes 25 on full charge
|
2020-12-13 15:01:13 +00:00
|
|
|
OverchargeConsumeTime = 0; //Setting to 0 or below deactivates ammo consumption while holding a charge
|
|
|
|
|
|
|
|
// Shooting Animations
|
|
|
|
FireSightedAnims[0]=Shoot_Iron
|
|
|
|
FireSightedAnims[1]=Shoot_Iron2
|
|
|
|
FireSightedAnims[2]=Shoot_Iron3
|
|
|
|
|
|
|
|
// FOV
|
|
|
|
MeshIronSightFOV=52
|
|
|
|
PlayerIronSightFOV=70
|
|
|
|
|
|
|
|
// Depth of field
|
|
|
|
DOF_FG_FocalRadius=85
|
|
|
|
DOF_FG_MaxNearBlurSize=2.5
|
|
|
|
|
|
|
|
// Content
|
|
|
|
PackageKey="Laser_Cutter"
|
|
|
|
FirstPersonMeshName="wep_1p_laser_cutter_mesh.Wep_1stP_Laser_Cutter_Rig"
|
|
|
|
FirstPersonAnimSetNames(0)="wep_1p_laser_cutter_anim.wep_1p_laser_cutter_anim"
|
|
|
|
PickupMeshName="WEP_3P_Laser_Cutter_Mesh.Wep_3rdP_Laser_Cutter_Pickup"
|
|
|
|
AttachmentArchetypeName="WEP_Laser_Cutter_ARCH.Wep_Laser_Cutter_3P"
|
|
|
|
MuzzleFlashTemplateName="WEP_Laser_Cutter_ARCH.Wep_Laser_Cutter_MuzzleFlash_1P"
|
|
|
|
|
|
|
|
// Zooming/Position
|
|
|
|
PlayerViewOffset = (X = 3.0, Y = 10, Z = -1)
|
2022-09-01 15:58:51 +00:00
|
|
|
IronSightPosition = (X = 0, Y = 0.037, Z = 0.11)
|
2020-12-13 15:01:13 +00:00
|
|
|
|
|
|
|
// Ammo
|
|
|
|
MagazineCapacity[0] = 50
|
2023-09-21 19:31:11 +00:00
|
|
|
SpareAmmoCapacity[0] = 450
|
2020-12-13 15:01:13 +00:00
|
|
|
InitialSpareMags[0] = 1
|
|
|
|
bCanBeReloaded = true
|
|
|
|
bReloadFromMagazine = true
|
|
|
|
|
|
|
|
// Recoil
|
|
|
|
maxRecoilPitch = 100
|
|
|
|
minRecoilPitch = 70
|
|
|
|
maxRecoilYaw = 100
|
|
|
|
minRecoilYaw = -100
|
|
|
|
RecoilRate = 0.063
|
|
|
|
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 / Grouping
|
|
|
|
InventorySize = 8
|
|
|
|
GroupPriority = 125
|
|
|
|
WeaponSelectTexture=Texture2D'WEP_UI_Laser_Cutter_TEX.UI_WeaponSelect_Laser_Cutter'
|
|
|
|
AssociatedPerkClasses(0) = class'KFPerk_Survivalist'
|
|
|
|
|
|
|
|
// DEFAULT_FIREMODE
|
|
|
|
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletAuto'
|
|
|
|
FiringStatesArray(DEFAULT_FIREMODE)=WeaponFiring
|
|
|
|
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_InstantHit
|
|
|
|
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_LazerCutter'
|
|
|
|
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_LazerCutter'
|
|
|
|
FireInterval(DEFAULT_FIREMODE)=+0.0857 // 700 RPM
|
|
|
|
Spread(DEFAULT_FIREMODE)=0.015
|
2023-09-21 19:31:11 +00:00
|
|
|
InstantHitDamage(DEFAULT_FIREMODE)=55.0
|
2020-12-13 15:01:13 +00:00
|
|
|
FireOffset=(X=30,Y=4.5,Z=-5)
|
|
|
|
AmmoCost(DEFAULT_FIREMODE)=1
|
|
|
|
|
|
|
|
// ALT_FIREMODE
|
|
|
|
FireModeIconPaths(ALTFIRE_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Electricity'
|
|
|
|
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_InstantHit
|
|
|
|
WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Bullet_LazerCutter'
|
|
|
|
InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_LazerCutter_Beam'
|
|
|
|
FireInterval(ALTFIRE_FIREMODE)=+0.07 // 857 RPM
|
|
|
|
Spread(ALTFIRE_FIREMODE)=0.0085
|
|
|
|
InstantHitDamage(ALTFIRE_FIREMODE)=40.0
|
|
|
|
FiringStatesArray(ALTFIRE_FIREMODE)=LazerCharge
|
|
|
|
AmmoCost(ALTFIRE_FIREMODE)=1
|
|
|
|
|
|
|
|
|
|
|
|
// BASH_FIREMODE
|
|
|
|
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_LazerCutter'
|
|
|
|
InstantHitDamage(BASH_FIREMODE)=26
|
|
|
|
|
|
|
|
// Fire Effects
|
|
|
|
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue = AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_FullAuto_LP_3P', FirstPersonCue = AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_FullAuto_LP_1P')
|
|
|
|
WeaponFireLoopEndSnd(DEFAULT_FIREMODE)=(DefaultCue = AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_FullAuto_LP_End_3P', FirstPersonCue = AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_FullAuto_LP_End_1P')
|
|
|
|
WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LaserCutter_DryFire'
|
|
|
|
SingleShotFireSnd=(DefaultCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Single_3P', FirstPersonCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Single_1P')
|
|
|
|
|
|
|
|
WeaponFireSnd(ALTFIRE_FIREMODE)={(
|
|
|
|
DefaultCue = AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Beam_Shoot_LP_Level_0_3P',
|
|
|
|
FirstPersonCue = AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Beam_Shoot_LP_Level_0_1P'
|
|
|
|
)}
|
|
|
|
WeaponFireLoopEndSnd(ALTFIRE_FIREMODE)={(
|
|
|
|
DefaultCue = AkEvent'WW_WEP_Lazer_Cutter.Stop_WEP_LazerCutter_Beam_Shoot_Loop_3P',
|
|
|
|
FirstPersonCue = AkEvent'WW_WEP_Lazer_Cutter.Stop_WEP_LazerCutter_Beam_Shoot_LP_1P'
|
|
|
|
)}
|
|
|
|
|
|
|
|
WeaponFireSnd(CUSTOM_FIREMODE)={(
|
|
|
|
DefaultCue = AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LaserCutter_Beam_Charged_LP_Level_0_3P',
|
|
|
|
FirstPersonCue = AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LaserCutter_Beam_Charged_LP_Level_0_1P'
|
|
|
|
)}
|
|
|
|
WeaponFireLoopEndSnd(CUSTOM_FIREMODE)={(
|
|
|
|
DefaultCue = AkEvent'WW_WEP_Lazer_Cutter.Stop_WEP_LazerCutter_Interrupt_3P',
|
|
|
|
FirstPersonCue = AkEvent'WW_WEP_Lazer_Cutter.Stop_WEP_LazerCutter_Interrupt_1P'
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
|
|
// Advanced (High RPM) Fire Effects
|
|
|
|
bLoopingFireAnim(DEFAULT_FIREMODE)=true
|
|
|
|
bLoopingFireSnd(DEFAULT_FIREMODE)=true
|
|
|
|
bLoopingFireAnim(ALTFIRE_FIREMODE)=true
|
|
|
|
bLoopingFireSnd(ALTFIRE_FIREMODE)=true
|
|
|
|
bLoopingFireAnim(CUSTOM_FIREMODE)=true
|
|
|
|
bLoopingFireSnd(CUSTOM_FIREMODE)=true
|
|
|
|
|
|
|
|
// Attachments
|
|
|
|
bHasIronSights = true
|
|
|
|
bHasFlashlight = false
|
|
|
|
|
|
|
|
FireModeIconPaths(CUSTOM_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Electricity'
|
|
|
|
FiringStatesArray(CUSTOM_FIREMODE)=SprayingFireLazer
|
|
|
|
WeaponFireTypes(CUSTOM_FIREMODE)=EWFT_Custom
|
|
|
|
FireInterval(CUSTOM_FIREMODE)=+0.07 // 857 RPM
|
|
|
|
AmmoCost(CUSTOM_FIREMODE)=1
|
|
|
|
|
|
|
|
BaseScale=40.f;
|
|
|
|
ScalePerChargeLevel=10.f;
|
|
|
|
|
|
|
|
DamagePerChargeLevel=5.f;
|
|
|
|
|
|
|
|
FlashInterval = 0.15f;
|
|
|
|
|
|
|
|
BaseDuration=0.25f;
|
|
|
|
DurationPerChargeLevel=0.75f;
|
|
|
|
|
|
|
|
MaxChargeLevel=3;
|
|
|
|
|
|
|
|
ChargingRotationSpeedLimit = 0.f;
|
|
|
|
ChargingMovementSpeedModifier = 1.f;
|
2023-09-21 19:31:11 +00:00
|
|
|
FiringRotationSpeedLimit(0)=900.f;
|
|
|
|
FiringRotationSpeedLimit(1)=800.f;
|
|
|
|
FiringRotationSpeedLimit(2)=700.f;
|
|
|
|
FiringRotationSpeedLimit(3)=600.f;
|
|
|
|
FiringMovementSpeedModifier=1f;
|
2020-12-13 15:01:13 +00:00
|
|
|
|
|
|
|
MaxRotationAdjustmentTime = 0.25f;
|
|
|
|
RotationAdjustmentCurve = { (Points = ((InVal = 0.000000,OutVal = 120.0f),
|
|
|
|
(InVal = 1.000000,OutVal = 2000.0f,InterpMode = CIM_CurveAuto))) }
|
|
|
|
|
|
|
|
AltFireLoopStartAnim=Beam_Charge_In_lvl1;
|
|
|
|
AltFireBeamInAnimL1=Beam_Charge_In_lvl2;
|
|
|
|
AltFireBeamInAnimL2=Beam_Charge_In_lvl3;
|
|
|
|
AltFireLoopAnimL1=Beam_Charge_Loop_lvl1;
|
|
|
|
AltFireLoopAnimL2=Beam_Charge_Loop_lvl2;
|
|
|
|
AltFireLoopAnimL3=Beam_Charge_Loop_lvl3;
|
|
|
|
CustomFireLoopAnimL1=Beam_Shoot_Loop_lvl1;
|
|
|
|
CustomFireLoopAnimL2=Beam_Shoot_Loop_lvl2;
|
|
|
|
CustomFireLoopAnimL3=Beam_Shoot_Loop_lvl3;
|
|
|
|
CustomFireLoopEndLastAnim=Beam_Shoot_End_Last;
|
|
|
|
CustomFireLoopEndAnim=Beam_Shoot_End;
|
|
|
|
|
|
|
|
bHasFireLastAnims=true
|
|
|
|
BonesToLockOnEmpty=(RW_Magazine1, RW_BatteryContactLeft, RW_BatteryContactRight)
|
|
|
|
|
|
|
|
// Weapon Upgrade stat boosts
|
2021-06-02 20:06:18 +00:00
|
|
|
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.0f), (Stat=EWUS_Damage1, Scale=1.0f), (Stat=EWUS_Weight, Add=0)))
|
2020-12-13 15:01:13 +00:00
|
|
|
|
|
|
|
MuzzleFlashEffectL1=ParticleSystem'WEP_Laser_Cutter_EMIT.FX_Laser_Cutter_Beam_Muzzleflash_01'
|
|
|
|
MuzzleFlashEffectL2=ParticleSystem'WEP_Laser_Cutter_EMIT.FX_Laser_Cutter_Beam_Muzzleflash_02'
|
|
|
|
MuzzleFlashEffectL3=ParticleSystem'WEP_Laser_Cutter_EMIT.FX_Laser_Cutter_Beam_Muzzleflash_03'
|
|
|
|
ChargingEffect=ParticleSystem'WEP_Laser_Cutter_EMIT.FX_Laser_Cutter_Beam_Charge_00'
|
|
|
|
|
|
|
|
FireLoopSounds(0)={(
|
|
|
|
DefaultCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Beam_Shoot_LP_Level_0_3P',
|
|
|
|
FirstPersonCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Beam_Shoot_LP_Level_0_1P')}
|
|
|
|
FireLoopSounds(1)={(
|
|
|
|
DefaultCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Beam_Shoot_LP_Level_1_3P',
|
|
|
|
FirstPersonCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Beam_Shoot_LP_Level_1_1P')}
|
|
|
|
FireLoopSounds(2)={(
|
|
|
|
DefaultCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Beam_Shoot_LP_Level_2_3P',
|
|
|
|
FirstPersonCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Beam_Shoot_LP_Level_2_1P')}
|
|
|
|
FireLoopSounds(3)={(
|
|
|
|
DefaultCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Beam_Shoot_LP_Level_3_3P',
|
|
|
|
FirstPersonCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Beam_Shoot_LP_Level_3_1P')}
|
|
|
|
|
|
|
|
FireLoopStop={(
|
|
|
|
DefaultCue=AkEvent'WW_WEP_Lazer_Cutter.Stop_WEP_LazerCutter_Beam_Shoot_Loop_3P',
|
|
|
|
FirstPersonCue=AkEvent'WW_WEP_Lazer_Cutter.Stop_WEP_LazerCutter_Beam_Shoot_LP_1P')}
|
|
|
|
|
|
|
|
ChargeSounds(0)={(
|
|
|
|
DefaultCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LaserCutter_Beam_Charged_LP_Level_0_3P',
|
|
|
|
FirstPersonCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LaserCutter_Beam_Charged_LP_Level_0_1P')}
|
|
|
|
ChargeSounds(1)={(
|
|
|
|
DefaultCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LaserCutter_Beam_Charged_LP_Level_1_3P',
|
|
|
|
FirstPersonCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LaserCutter_Beam_Charged_LP_Level_1_1P')}
|
|
|
|
ChargeSounds(2)={(
|
|
|
|
DefaultCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LaserCutter_Beam_Charged_LP_Level_2_3P',
|
|
|
|
FirstPersonCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LaserCutter_Beam_Charged_LP_Level_2_1P')}
|
|
|
|
ChargeSounds(3)={(
|
|
|
|
DefaultCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LaserCutter_Beam_Charged_LP_Level_3_3P',
|
|
|
|
FirstPersonCue=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LaserCutter_Beam_Charged_LP_Level_3_1P')}
|
|
|
|
|
|
|
|
InterruptSoundEvent={(
|
|
|
|
DefaultCue=AkEvent'WW_WEP_Lazer_Cutter.Stop_WEP_LazerCutter_Interrupt_3P',
|
|
|
|
FirstPersonCue=AkEvent'WW_WEP_Lazer_Cutter.Stop_WEP_LazerCutter_Interrupt_1P')}
|
|
|
|
|
|
|
|
PilotLightPlayEvent=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LazerCutter_Idle_LP'
|
|
|
|
PilotLightStopEvent=AkEvent'WW_WEP_Lazer_Cutter.Stop_WEP_LazerCutter_Idle_LP'
|
|
|
|
|
|
|
|
DefaultFireModeColor=(R=5.f,G=1.f,B=20.f)
|
|
|
|
EnergyColorL0=(R=5.f,G=1.f,B=20.f)
|
|
|
|
EnergyColorL1=(R=20.f,G=5.f,B=200.f)
|
|
|
|
EnergyColorL2=(R=5.f,G=25.f,B=200.f)
|
|
|
|
EnergyColorL3=(R=20.f,G=50.f,B=200.f)
|
|
|
|
|
|
|
|
NumBloodMapMaterials=5
|
|
|
|
}
|
|
|
|
|
|
|
|
|