rott/kf_sources/ScrnHMG/Classes/Stinger.uc
2026-07-14 20:27:09 +07:00

319 lines
11 KiB
Ucode

//--------------------------------------//
// Weapon Import to kf by Exod (erick610)//
// Bugfixed, enhanced and balanced for HMg by [ScrN]PooSH
//--------------------------------------//
class Stinger extends KFWeapon
config(user);
struct AnimSeq {
var name AnimName; // sequence name
var float AnimRateMult; // additional animation rate multiplier (it will be mulpilied by ReloadAnimRate and ReloadBonus)
var float TweenTime;
var int SkipFrames; // how many frames to skip from the begining of animation. Animation ending can be skipped by limiting Duration
var float Duration; // how long till the next animation (it will be mulpilied by ReloadAnimRate and ReloadBonus)
var string SoundRef; //reference to the sound that should be played
var sound Sound; //sound that should be played during this animation
};
var array<AnimSeq> ReloadAnims;
var float ReloadBonus; //perked reload multiplier
var transient float NextReloadAnimTime; // time when the next part of reload animation sequence must be played
var transient int NextReloadAnimIndex; // index of the next animation in ReloadAnims to play
var transient int OldMagAmmoRemaining;
static function PreloadAssets(Inventory Inv, optional bool bSkipRefCount)
{
local int i;
local Stinger W;
super.PreloadAssets(Inv, bSkipRefCount);
W = Stinger(Inv);
for ( i = 0; i < default.ReloadAnims.Length; ++i ) {
if ( default.ReloadAnims[i].Sound == none && default.ReloadAnims[i].SoundRef != "" )
default.ReloadAnims[i].Sound = sound(DynamicLoadObject(default.ReloadAnims[i].SoundRef, class'sound'));
if ( W != none ) {
W.ReloadAnims[i].Sound = default.ReloadAnims[i].Sound;
}
}
}
static function bool UnloadAssets()
{
local int i;
for ( i = 0; i < default.ReloadAnims.Length; ++i ) {
if ( default.ReloadAnims[i].SoundRef != "" )
default.ReloadAnims[i].Sound = none;
}
return super.UnloadAssets();
}
simulated function PostNetReceive()
{
super.PostNetReceive();
if ( Role < ROLE_Authority ) {
if ( OldMagAmmoRemaining != MagAmmoRemaining ) {
if ( OldMagAmmoRemaining < MagAmmoRemaining ) {
//just reloaded
if ( IsInState('Reloading') )
GotoState('');
}
OldMagAmmoRemaining = MagAmmoRemaining;
}
}
}
simulated function HandleSleeveSwapping();
simulated function bool StartFire(int Mode)
{
if( !super.StartFire(Mode) ) // returns false when mag is empty
return false;
if( AmmoAmount(Mode) <= 0 )
return false;
AnimStopLooping();
if( !FireMode[Mode].IsInState('FireLoop') ) {
FireMode[Mode].StartFiring();
return true;
}
return false;
}
simulated function AnimEnd(int channel)
{
local name anim;
local float frame, rate;
if( !FireMode[0].IsInState('FireLoop') && !FireMode[1].IsInState('FireLoop') )
{
GetAnimParams(0, anim, frame, rate);
if (ClientState == WS_ReadyToFire)
{
if ((FireMode[0] == None || !FireMode[0].bIsFiring) && (FireMode[1] == None || !FireMode[1].bIsFiring))
{
PlayIdle();
}
}
}
}
simulated function bool ConsumeAmmo( int Mode, float Load, optional bool bAmountNeededIsMax )
{
local Inventory Inv;
local bool bOutOfAmmo;
local KFWeapon KFWeap;
if ( Super(Weapon).ConsumeAmmo(Mode, Load, bAmountNeededIsMax) )
{
if ( Load > 0 && (Mode == 0 || bReduceMagAmmoOnSecondaryFire) ) {
MagAmmoRemaining -= Load; // Changed from "MagAmmoRemaining--" -- PooSH
if ( MagAmmoRemaining < 0 )
MagAmmoRemaining = 0;
}
OldMagAmmoRemaining = MagAmmoRemaining;
NetUpdateTime = Level.TimeSeconds - 1;
if ( FireMode[Mode].AmmoPerFire > 0 && InventoryGroup > 0 && !bMeleeWeapon && bConsumesPhysicalAmmo &&
(Ammo[0] == none || FireMode[0] == none || FireMode[0].AmmoPerFire <= 0 || Ammo[0].AmmoAmount < FireMode[0].AmmoPerFire) &&
(Ammo[1] == none || FireMode[1] == none || FireMode[1].AmmoPerFire <= 0 || Ammo[1].AmmoAmount < FireMode[1].AmmoPerFire) )
{
bOutOfAmmo = true;
for ( Inv = Instigator.Inventory; Inv != none; Inv = Inv.Inventory )
{
KFWeap = KFWeapon(Inv);
if ( Inv.InventoryGroup > 0 && KFWeap != none && !KFWeap.bMeleeWeapon && KFWeap.bConsumesPhysicalAmmo &&
((KFWeap.Ammo[0] != none && KFWeap.FireMode[0] != none && KFWeap.FireMode[0].AmmoPerFire > 0 &&KFWeap.Ammo[0].AmmoAmount >= KFWeap.FireMode[0].AmmoPerFire) ||
(KFWeap.Ammo[1] != none && KFWeap.FireMode[1] != none && KFWeap.FireMode[1].AmmoPerFire > 0 && KFWeap.Ammo[1].AmmoAmount >= KFWeap.FireMode[1].AmmoPerFire)) )
{
bOutOfAmmo = false;
break;
}
}
if ( bOutOfAmmo )
{
PlayerController(Instigator.Controller).Speech('AUTO', 3, "");
}
}
return true;
}
return false;
}
// since we don't have 'Tip' bone, need this hack
simulated function vector GetEffectStart()
{
return super(Weapon).GetEffectStart();
}
simulated function ClientReload()
{
super.ClientReload();
GotoState('Reloading');
}
simulated state Reloading
{
ignores PlayIdle;
simulated function BeginState()
{
NextReloadAnimIndex = 0;
NextReloadAnimTime = Level.TimeSeconds - 1; //play now
if ( KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo) != none && KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill != none )
ReloadBonus = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill.Static.GetReloadSpeedModifier(KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo), self);
else
ReloadBonus = 1.0;
}
simulated function PlayNextSeq()
{
local AnimSeq seq;
seq = ReloadAnims[NextReloadAnimIndex];
if ( seq.AnimName != '' ) {
PlayAnim(seq.AnimName, seq.AnimRateMult * ReloadAnimRate * ReloadBonus, seq.TweenTime);
if ( seq.SkipFrames > 0 )
SetAnimFrame(seq.SkipFrames, 0 , 1);
}
if ( seq.Sound != none ) {
PlaySound(seq.Sound);
}
NextReloadAnimTime = Level.TimeSeconds + seq.Duration * ReloadAnimRate * ReloadBonus;
}
simulated function WeaponTick(float dt)
{
super.WeaponTick(dt);
if ( !bIsReloading ) {
GotoState('');
return;
}
if ( NextReloadAnimTime <= Level.TimeSeconds && NextReloadAnimIndex < ReloadAnims.length ) {
PlayNextSeq();
NextReloadAnimIndex++;
}
}
simulated function ActuallyFinishReloading()
{
global.ActuallyFinishReloading();
GotoState('');
}
}
exec function StingerX(int value)
{
StingerAttachment(ThirdPersonActor).FlashOffset.X = value;
StingerAttachment(ThirdPersonActor).mMuzFlash3rd.Destroy();
}
exec function StingerY(int value)
{
StingerAttachment(ThirdPersonActor).FlashOffset.Y = value;
StingerAttachment(ThirdPersonActor).mMuzFlash3rd.Destroy();
}
exec function StingerZ(int value)
{
StingerAttachment(ThirdPersonActor).FlashOffset.Z = value;
StingerAttachment(ThirdPersonActor).mMuzFlash3rd.Destroy();
}
exec function StingerP(int value)
{
StingerAttachment(ThirdPersonActor).FlashRotationOffset.Pitch = value;
StingerAttachment(ThirdPersonActor).mMuzFlash3rd.Destroy();
}
exec function StingerYaw(int value)
{
StingerAttachment(ThirdPersonActor).FlashRotationOffset.Yaw = value;
StingerAttachment(ThirdPersonActor).mMuzFlash3rd.Destroy();
}
exec function StingerR(int value)
{
StingerAttachment(ThirdPersonActor).FlashRotationOffset.Roll = value;
StingerAttachment(ThirdPersonActor).mMuzFlash3rd.Destroy();
}
defaultproperties
{
ReloadAnims(0)=(AnimName="WeaponRampDown",AnimRateMult=4.000000,TweenTime=0.010000,Duration=0.500000,SoundRef="HMG_S.Stinger.StingerRapidStop")
ReloadAnims(1)=(AnimName="WeaponPutDown",AnimRateMult=0.600000,TweenTime=0.010000,Duration=0.816667)
ReloadAnims(2)=(Duration=0.500000,SoundRef="KF_AA12Snd.AA12_Reload_011")
ReloadAnims(3)=(Duration=0.500000,SoundRef="KF_M32Snd.M32_Reload_000")
ReloadAnims(4)=(Duration=0.600000,SoundRef="KF_M32Snd.M32_Reload_280")
ReloadAnims(5)=(AnimName="WeaponEquip",AnimRateMult=0.800000,TweenTime=0.100000,Duration=0.933333,SoundRef="HMG_S.Stinger.StingerTakeOut")
ReloadAnims(6)=(AnimName="WeaponRampDown",AnimRateMult=4.000000,Duration=0.500000,SoundRef="HMG_S.Stinger.StingerRapidStop")
MagCapacity=123
ReloadRate=4.250000
ReloadAnimRate=1.000000
FlashBoneName="Stinger-TurretMini"
WeaponReloadAnim="Reload_AA12"
Weight=13.000000
IdleAimAnim="WeaponIdle"
StandardDisplayFOV=55.000000
bModeZeroCanDryFire=True
TraderInfoTexture=Texture'HMG_T.Stinger.Trader_Stinger'
bIsTier3Weapon=True
MeshRef="HMG_A.SK_WP_Stinger_1P"
SkinRefs(0)="HMG_T.Stinger.StingerSkin"
SkinRefs(1)="HMG_T.Stinger.T_WP_StingerCord_D"
SelectSoundRef="HMG_S.Stinger.StingerTakeOut"
HudImageRef="HMG_T.Stinger.Unselected_Stinger"
SelectedHudImageRef="HMG_T.Stinger.Selected_Stinger"
PlayerIronSightFOV=65.000000
ZoomedDisplayFOV=20.000000
FireModeClass(0)=Class'ScrnHMG.StingerFire'
FireModeClass(1)=Class'ScrnHMG.StingerAltFire'
IdleAnim="WeaponIdle"
PutDownAnim="WeaponPutDown"
SelectForce="SwitchToAssaultRifle"
AIRating=0.550000
CurrentRating=0.550000
bShowChargingBar=True
Description="Stinger Minigun first was designed by Liandri corp. as a mining tool, but later converted into military service. Fires shards of unprocessed Tarydium crystal."
EffectOffset=(X=100.000000,Y=25.000000,Z=-5.000000)
DisplayFOV=55.000000
Priority=140
SmallEffectOffset=(X=100.000000,Y=25.000000,Z=-5.000000)
CustomCrosshair=11
CustomCrossHairTextureName="Crosshairs.HUD.Crosshair_Cross5"
InventoryGroup=4
GroupOffset=7
PickupClass=Class'ScrnHMG.StingerPickup'
PlayerViewOffset=(X=50.000000,Y=-4.000000,Z=-4.000000)
BobDamping=6.000000
AttachmentClass=Class'ScrnHMG.StingerAttachment'
IconCoords=(X1=245,Y1=39,X2=329,Y2=79)
ItemName="Stinger Minigun SE"
}