319 lines
11 KiB
Ucode
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"
|
|
}
|