357 lines
10 KiB
Ucode
357 lines
10 KiB
Ucode
//=============================================================================
|
|
// 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
|
|
}
|