class ScrnChainsaw extends Chainsaw; var float IdleFuelConsumeTime; // time between fuel consumption on idle var sound EngineStartSound, EngineStopSound; var string EngineStartSoundRef, EngineStopSoundRef; struct SoundList { var string SoundRef; var sound Sound; var float Duration; }; var array ReloadSounds; var float TotalReloadSoundDuration; // total duration of all reload sounds var transient float TimeToNextReloadSound; var transient int NextReloadSoundIndex; var transient bool bBlownUpThisReload; var transient int OldMagAmmoRemaining; var ScrnFakedProjectile FakedGasCan; //adds a faked gas can during reload replication { reliable if(Role == ROLE_Authority) HideGasCan; } simulated function PostNetReceive() { super.PostNetReceive(); if ( Role < ROLE_Authority ) { if ( OldMagAmmoRemaining != MagAmmoRemaining ) { if ( MagAmmoRemaining == 0 ) { if ( ThirdPersonActor != none ) ThirdPersonActor.AmbientSound = none; TexPanner(Skins[1]).PanRate = 0; // stop saw cycling PlaySound(EngineStopSound); } else if ( OldMagAmmoRemaining < MagAmmoRemaining && MagAmmoRemaining > 0 ) { //just reloaded if ( IsInState('Reloading') ) GotoState(''); if ( ThirdPersonActor != none ) ThirdPersonActor.AmbientSound = ThirdPersonActor.default.AmbientSound; TexPanner(Skins[1]).PanRate = 3; // start saw cycling PlaySound(EngineStartSound); if ( !IsAnimating() ) PlayIdle(); } OldMagAmmoRemaining = MagAmmoRemaining; } } } static function PreloadAssets(Inventory Inv, optional bool bSkipRefCount) { local int i; local ScrnChainsaw W; super.PreloadAssets(Inv, bSkipRefCount); W = ScrnChainsaw(Inv); default.EngineStartSound = sound(DynamicLoadObject(default.EngineStartSoundRef, class'sound')); default.EngineStopSound = sound(DynamicLoadObject(default.EngineStopSoundRef, class'sound')); for ( i = 0; i < default.ReloadSounds.Length; ++i ) { default.ReloadSounds[i].Sound = sound(DynamicLoadObject(default.ReloadSounds[i].SoundRef, class'sound')); if ( W != none ) { W.ReloadSounds[i].Sound = default.ReloadSounds[i].Sound; } } if ( W != none ) { W.EngineStartSound = default.EngineStartSound; W.EngineStopSound = default.EngineStopSound; W.CalcReloadSoundDuration(); default.TotalReloadSoundDuration = W.TotalReloadSoundDuration; } } static function bool UnloadAssets() { local int i; default.EngineStartSound = none; default.EngineStopSound = none; default.TotalReloadSoundDuration = 0; for ( i = 0; i < default.ReloadSounds.Length; ++i ) { default.ReloadSounds[i].Sound = none; } return super.UnloadAssets(); } simulated function PostBeginPlay() { super.PostBeginPlay(); AttachGasCan(); CalcReloadSoundDuration(); } simulated function AttachGasCan() { if ( Level.NetMode != NM_DedicatedServer ) { if ( FakedGasCan == none ) //only spawn FakedGasCan once FakedGasCan = spawn(class'ScrnFakedGasCan',self); if ( FakedGasCan != none ) { AttachToBone(FakedGasCan, 'Chainsaw'); //attach faked shell to chainsaw FakedGasCan.SetDrawScale(0.01); FakedGasCan.SetRelativeLocation(vect(-3, 2, 3)); //x y z FakedGasCan.SetRelativeRotation(rot(-4000, 38000, 12000)); //pitch yaw roll } } } simulated function CalcReloadSoundDuration() { local int i; TotalReloadSoundDuration = 0; for ( i = 0; i < default.ReloadSounds.Length; ++i ) { ReloadSounds[i].Duration = GetSoundDuration(ReloadSounds[i].Sound); TotalReloadSoundDuration += ReloadSounds[i].Duration; } } 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; if ( MagAmmoRemaining == 0 ) { ThirdPersonActor.AmbientSound = none; TexPanner(Skins[1]).PanRate = 0; // stop saw cycling PlaySound(EngineStopSound); } } 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; } simulated function ClientReload() { super.ClientReload(); if (FakedGasCan != none) FakedGasCan.SetDrawScale(2); //test // if MagAmmoRemaining == 0, chaisaw is already stopped if ( MagAmmoRemaining > 0 ) PlaySound(EngineStopSound); ThirdPersonActor.AmbientSound = none; GotoState('Reloading'); } simulated function ActuallyFinishReloading() { super.ActuallyFinishReloading(); IdleFuelConsumeTime = default.IdleFuelConsumeTime; GotoState(''); if ( MagAmmoRemaining > 0) { PlaySound(EngineStartSound); ThirdPersonActor.AmbientSound = ThirdPersonActor.default.AmbientSound; TexPanner(Skins[1]).PanRate = 3; // start saw cycling PlayIdle(); } } simulated function ClientFinishReloading() { super.ClientFinishReloading(); if ( Level.NetMode != NM_DedicatedServer ) { if (FakedGasCan != none) FakedGasCan.SetDrawScale(0.01); //hide gas can after reload } } simulated function WeaponTick(float dt) { super.WeaponTick(dt); if ( Role == Role_Authority ) { if ( !bIsReloading ) { if ( MagAmmoRemaining <= 0) { ThirdPersonActor.AmbientSound = none; TexPanner(Skins[1]).PanRate = 0; // stop saw cycling } else { if ( Level.TimeSeconds - FireMode[0].NextFireTime > 1.0 && Level.TimeSeconds - FireMode[1].NextFireTime > 1.0 ) { //consume ammo on idle IdleFuelConsumeTime -= dt; if ( IdleFuelConsumeTime <= 0 ) { ConsumeAmmo(0, 1); IdleFuelConsumeTime = default.IdleFuelConsumeTime; } } } } } } // there is no reload animation for Chainsaw, so play slow put down animation // taking sounds from flamethrower reload simulated state Reloading { simulated function BeginState() { NextReloadSoundIndex = 0; TimeToNextReloadSound = ReloadRate * 0.2; bBlownUpThisReload = false; } simulated function WeaponTick(float dt) { super.WeaponTick(dt); if ( NextReloadSoundIndex < ReloadSounds.length ) { // if ( NextReloadSoundIndex < ReloadSounds.length - 2 ) // ThirdPersonActor.AmbientSound = none; TimeToNextReloadSound -= dt; if ( TimeToNextReloadSound <= 0 ) { PlaySound(ReloadSounds[NextReloadSoundIndex].Sound); TimeToNextReloadSound += 0.8*ReloadRate * ReloadSounds[NextReloadSoundIndex].Duration/TotalReloadSoundDuration; NextReloadSoundIndex++; } } } function TakeDamage(int Damage, Pawn EventInstigator, vector HitLocation, vector Momentum, class DamageType, optional int HitIndex) { local ScrnFlameNade nade; local int FuelInTank; //blow the fuel inside a tank on fire damage received (excluding DoT) if ( bBlownUpThisReload || DamageType == none || Damage < 5 || DamageType == class'DamTypeFlamethrower' ) return; if ( Level.TimeSeconds > ReloadTimer + ReloadRate*0.9 ) //almost finished reloading, don't blow up return; if ( DamageType.default.bFlaming || (class(DamageType) != none && class(DamageType).default.bDealBurningDamage) ) { bBlownUpThisReload = true; FuelInTank = MagAmmoRemaining + (MagCapacity - MagAmmoRemaining) * (Level.TimeSeconds - ReloadTimer) / ReloadRate; if ( FuelInTank > AmmoAmount(0) ) FuelInTank = AmmoAmount(0); if ( FuelInTank < 1 ) return; nade = spawn(class'ScrnBalanceSrv.ScrnFlameNade'); HideGasCan(); AttachToBone(nade, 'Chainsaw'); //attempt to move explosion onto chainsaw to make it obvious that the gas can caused the explosion nade.SetRelativeLocation(vect(-3, 2, 3)); //move nade to exact gas can location nade.SetTimer(0, false); // it will be blown up manualy nade.Instigator = Instigator; // the more fuel in tank, the higher is explosion nade.Damage = FuelInTank; AddAmmo(-FuelInTank, 0); nade.Explode(Location, vect(0,0,1)); } } } simulated function HideGasCan() { if ( Level.NetMode != NM_DedicatedServer ) { FakedGasCan.SetDrawScale(0.01); //hide gas can after reload } } //destroy gas can on destroy simulated function Destroyed() { if ( FakedGasCan != none && !FakedGasCan.bDeleteMe ) FakedGasCan.Destroy(); super.Destroyed(); } simulated function PlayIdle() { if ( MagAmmoRemaining > 0 ) super.PlayIdle(); } defaultproperties { IdleFuelConsumeTime=5.000000 EngineStartSoundRef="KF_ChainsawSnd.Chainsaw_FalseStart4" EngineStopSoundRef="KF_ChainsawSnd.Chainsaw_Deselect1" ReloadSounds(0)=(SoundRef="KF_FlamethrowerSnd.FT_Reload1") ReloadSounds(1)=(SoundRef="KF_FlamethrowerSnd.FT_Reload2") ReloadSounds(2)=(SoundRef="KF_FlamethrowerSnd.FT_Reload3") ReloadSounds(3)=(SoundRef="KF_FlamethrowerSnd.FT_Reload4") ReloadSounds(4)=(SoundRef="KF_FlamethrowerSnd.FT_Reload5") ReloadSounds(5)=(SoundRef="KF_FlamethrowerSnd.FT_Reload5b") ReloadSounds(6)=(SoundRef="KF_FlamethrowerSnd.FT_Reload6") ReloadSounds(7)=(SoundRef="KF_ChainsawSnd.Chainsaw_FalseStart1") ReloadSounds(8)=(SoundRef="KF_ChainsawSnd.Chainsaw_FalseStart2") MagCapacity=105 ReloadRate=2.666667 ReloadAnim="PutDown" ReloadAnimRate=0.250000 WeaponReloadAnim="Reload_Flamethrower" bAmmoHUDAsBar=True FireModeClass(0)=Class'ScrnBalanceSrv.ScrnChainsawFire' FireModeClass(1)=Class'ScrnBalanceSrv.ScrnChainsawAltFire' bMeleeWeapon=False bShowChargingBar=True Description="This legendary chainsaw is used through the centuries to fight evil forces" PickupClass=Class'ScrnBalanceSrv.ScrnChainsawPickup' ItemName="Ash's Chainsaw" }