//============================================================================= // ChainsawFire //============================================================================= // Looping chainsaw fire class //============================================================================= // Killing Floor Source // Copyright (C) 2009 Tripwire Interactive LLC // - John "Ramm-Jaeger" Gibson //============================================================================= class ChainsawFire extends KFMeleeFire; // sound var sound FireStartSound; // The sound to play at the beginning of the ambient fire sound var sound FireEndSound; // The sound to play at the end of the ambient fire sound var float AmbientFireSoundRadius; // The sound radius for the ambient fire sound var sound AmbientFireSound; // The ambient fire sound var sound AmbientIdleSound; // The ambient idle sound var byte AmbientFireVolume; // How loud to play the looping ambient fire sound var string FireStartSoundRef; var string FireEndSoundRef; var string AmbientFireSoundRef; var string AmbientIdleSoundRef; var int maxAdditionalDamage; static function PreloadAssets(optional KFMeleeFire Spawned) { super.PreloadAssets(Spawned); default.FireStartSound = sound(DynamicLoadObject(default.FireStartSoundRef, class'sound', true)); default.FireEndSound = sound(DynamicLoadObject(default.FireEndSoundRef, class'sound', true)); default.AmbientFireSound = sound(DynamicLoadObject(default.AmbientFireSoundRef, class'sound', true)); default.AmbientIdleSound = sound(DynamicLoadObject(default.AmbientIdleSoundRef, class'sound', true)); if ( ChainsawFire(Spawned) != none ) { ChainsawFire(Spawned).FireStartSound = default.FireStartSound; ChainsawFire(Spawned).FireEndSound = default.FireEndSound; ChainsawFire(Spawned).AmbientFireSound = default.AmbientFireSound; ChainsawFire(Spawned).AmbientIdleSound = default.AmbientIdleSound; } } static function bool UnloadAssets() { super.UnloadAssets(); default.FireStartSound = none; default.FireEndSound = none; default.AmbientFireSound = none; default.AmbientIdleSound = none; return true; } // Sends the fire class to the looping state function StartFiring() { GotoState('FireLoop'); } // Handles toggling the weapon attachment's ambient sound on and off function PlayAmbientSound(Sound aSound) { local WeaponAttachment WA; WA = WeaponAttachment(Weapon.ThirdPersonActor); if ( Weapon == none || (WA == none)) return; if(aSound == None) { WA.SoundVolume = WA.default.SoundVolume; WA.SoundRadius = WA.default.SoundRadius; } else { WA.SoundVolume = AmbientFireVolume; WA.SoundRadius = AmbientFireSoundRadius; } WA.AmbientSound = aSound; } function PlayDefaultAmbientSound() { local WeaponAttachment WA; WA = WeaponAttachment(Weapon.ThirdPersonActor); if ( Weapon == none || (WA == none)) return; WA.SoundVolume = WA.default.SoundVolume; WA.SoundRadius = WA.default.SoundRadius; WA.AmbientSound=WA.default.AmbientSound; } // Make sure we are in the fire looping state when we fire event ModeDoFire() { local float Rec; if( AllowFire() && IsInState('FireLoop')) { Rec = GetFireSpeed(); FireRate = default.FireRate/Rec; FireAnimRate = default.FireAnimRate*Rec; ReloadAnimRate = default.ReloadAnimRate*Rec; if (MaxHoldTime > 0.0) HoldTime = FMin(HoldTime, MaxHoldTime); // server if (Weapon.Role == ROLE_Authority) { Weapon.ConsumeAmmo(ThisModeNum, Load); DoFireEffect(); HoldTime = 0; // if bot decides to stop firing, HoldTime must be reset first if ( (Instigator == None) || (Instigator.Controller == None) ) return; if ( AIController(Instigator.Controller) != None ) AIController(Instigator.Controller).WeaponFireAgain(BotRefireRate, true); Instigator.DeactivateSpawnProtection(); } // client if (Instigator.IsLocallyControlled()) { ShakeView(); PlayFiring(); FlashMuzzleFlash(); StartMuzzleSmoke(); ClientPlayForceFeedback(FireForce); } else // server ServerPlayFiring(); Weapon.IncrementFlashCount(ThisModeNum); // set the next firing time. must be careful here so client and server do not get out of sync if (bFireOnRelease) { if (bIsFiring) NextFireTime += MaxHoldTime + FireRate; else NextFireTime = Level.TimeSeconds + FireRate; } else { NextFireTime += FireRate; NextFireTime = FMax(NextFireTime, Level.TimeSeconds); } Load = AmmoPerFire; HoldTime = 0; if (Instigator.PendingWeapon != Weapon && Instigator.PendingWeapon != None) { bIsFiring = false; Weapon.PutDown(); } if( Weapon.Owner != none && Weapon.Owner.Physics != PHYS_Falling ) { Weapon.Owner.Velocity.x *= KFMeleeGun(Weapon).ChopSlowRate; Weapon.Owner.Velocity.y *= KFMeleeGun(Weapon).ChopSlowRate; } } } function DoFireEffect() { local KFMeleeGun kf; local int damage ; local Actor HitActor; local vector StartTrace, EndTrace, HitLocation, HitNormal; local rotator PointRot; local int MyDamage; local bool bBackStabbed; if(KFMeleeGun(Weapon) == none) return; kf = KFMeleeGun(Weapon); damage = MeleeDamage + Rand(MaxAdditionalDamage) ; MyDamage = MeleeDamage + Rand(MaxAdditionalDamage); If( !KFWeapon(Weapon).bNoHit ) { MyDamage = MeleeDamage + Rand(MaxAdditionalDamage); StartTrace = Instigator.Location + Instigator.EyePosition(); if( Instigator.Controller!=None && PlayerController(Instigator.Controller)==None && Instigator.Controller.Enemy!=None ) { PointRot = rotator(Instigator.Controller.Enemy.Location-StartTrace); // Give aimbot for bots. } else { PointRot = Instigator.GetViewRotation(); } EndTrace = StartTrace + vector(PointRot)*weaponRange; HitActor = Instigator.Trace( HitLocation, HitNormal, EndTrace, StartTrace, true); if (HitActor!=None) { //ImpactShakeView(); if( HitActor.IsA('ExtendedZCollision') && HitActor.Base != none && HitActor.Base.IsA('KFMonster') ) { HitActor = HitActor.Base; } if ( (HitActor.IsA('KFMonster') || HitActor.IsA('KFHumanPawn')) && KFMeleeGun(Weapon).BloodyMaterial!=none ) { Weapon.Skins[KFMeleeGun(Weapon).BloodSkinSwitchArray] = KFMeleeGun(Weapon).BloodyMaterial; Weapon.texture = Weapon.default.Texture; } if( Level.NetMode==NM_Client ) { Return; } if( HitActor.IsA('Pawn') && !HitActor.IsA('Vehicle') && (Normal(HitActor.Location-Instigator.Location) Dot vector(HitActor.Rotation))>0 ) { bBackStabbed = true; MyDamage*=2; // Backstab >:P } if( (KFMonster(HitActor)!=none) ) { // log(VSize(Instigator.Velocity)); KFMonster(HitActor).bBackstabbed = bBackStabbed; HitActor.TakeDamage(MyDamage, Instigator, HitLocation, vector(PointRot), hitDamageClass) ; if(MeleeHitSounds.Length > 0) { Weapon.PlaySound(MeleeHitSounds[Rand(MeleeHitSounds.length)],SLOT_None,MeleeHitVolume,,,,false); } if(VSize(Instigator.Velocity) > 300 && KFMonster(HitActor).Mass <= Instigator.Mass) { KFMonster(HitActor).FlipOver(); } } else { HitActor.TakeDamage(MyDamage, Instigator, HitLocation, vector(PointRot), hitDamageClass) ; if( KFWeaponAttachment(Weapon.ThirdPersonActor)!=None ) KFWeaponAttachment(Weapon.ThirdPersonActor).UpdateHit(HitActor,HitLocation,HitNormal); } } } } function Timer() { PlayDefaultAmbientSound(); } /* =================================================================================== * * FireLoop * This state handles looping the firing animations and ambient fire sounds as well * as firing rounds. * * modified by: Ramm 1/17/05 * =================================================================================== */ state FireLoop { function BeginState() { NextFireTime = Level.TimeSeconds - 0.1; //fire now! Weapon.LoopAnim(FireLoopAnim, FireLoopAnimRate, TweenTime); Weapon.PlayOwnedSound(FireStartSound,SLOT_Interact,AmbientFireVolume/127,,AmbientFireSoundRadius,,false); SetTimer(Weapon.GetSoundDuration(FireStartSound) / (1.1/Weapon.Level.TimeDilation), False); } function Timer() { PlayAmbientSound(AmbientFireSound); } // Overriden because we play an anbient fire sound function PlayFiring() {} function ServerPlayFiring() {} function EndState() { Weapon.AnimStopLooping(); PlayAmbientSound(none); Weapon.PlayOwnedSound(FireEndSound,SLOT_Interact,AmbientFireVolume/127,,AmbientFireSoundRadius,,false); SetTimer(Weapon.GetSoundDuration(FireEndSound) / (1.1/Weapon.Level.TimeDilation), False); Weapon.StopFire(ThisModeNum); } function StopFiring() { GotoState(''); } function ModeTick(float dt) { Super.ModeTick(dt); if ( !bIsFiring || !AllowFire() ) // stopped firing, magazine empty { GotoState(''); return; } } } function float MaxRange() { return weaponRange; } defaultproperties { hitDamageClass=Class'KFMod.DamTypeChainsaw' TransientSoundVolume=2.000000 FireSound=none FireRate=0.100000 MeleeHitSoundRefs(0)="KF_AxeSnd.Axe_HitFlesh" FireStartSoundRef="KF_ChainsawSnd.Chainsaw_RevLong_Start" FireEndSoundRef="KF_ChainsawSnd.Chainsaw_RevLong_End" NoAmmoSoundRef="KF_FlamethrowerSnd.FT_DryFire" AmbientFireSoundRadius=500 AmbientFireSoundRef="KF_ChainsawSnd.Chainsaw_RevLong_Loop" AmbientFireVolume=255 FireLoopAnim=Fire FireEndAnim=Idle FireAnim='' HitEffectClass=class'ChainsawHitEffect' MeleeDamage=14 // Increased in Balance Round 2 MaxAdditionalDamage=5 }