280 lines
7.2 KiB
Ucode
280 lines
7.2 KiB
Ucode
//=============================================================================
|
|
// Frag Fire
|
|
//=============================================================================
|
|
class FragFire extends RocketFire; // AssaultGrenade
|
|
|
|
const mNumGrenades = 8;
|
|
var float mCurrentRoll;
|
|
var float mBlend;
|
|
var float mRollInc;
|
|
var float mNextRoll;
|
|
var float mDrumRotationsPerSec;
|
|
var float mRollPerSec;
|
|
var Frag mGun;
|
|
var int mCurrentSlot;
|
|
var int mNextEmptySlot;
|
|
|
|
var() float mScale;
|
|
var() float mScaleMultiplier;
|
|
|
|
var() float mSpeedMin;
|
|
var() float mSpeedMax;
|
|
var() float mHoldSpeedMin;
|
|
var() float mHoldSpeedMax;
|
|
var() float mHoldSpeedGainPerSec;
|
|
var() float mHoldClampMax;
|
|
|
|
var() float mWaitTime;
|
|
|
|
function PlayFiring()
|
|
{
|
|
if ( Weapon.Mesh != None )
|
|
{
|
|
if ( FireCount > 0 )
|
|
{
|
|
if ( Weapon.HasAnim(FireLoopAnim) )
|
|
{
|
|
Weapon.PlayAnim(FireLoopAnim, FireLoopAnimRate, 0.0);
|
|
}
|
|
else
|
|
{
|
|
Weapon.PlayAnim(FireAnim, FireAnimRate, TweenTime);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Weapon.PlayAnim(FireAnim, FireAnimRate, TweenTime);
|
|
}
|
|
}
|
|
Weapon.PlayOwnedSound(FireSound,SLOT_Interact,TransientSoundVolume,,TransientSoundRadius,Default.FireAnimRate/FireAnimRate,false);
|
|
ClientPlayForceFeedback(FireForce); // jdf
|
|
|
|
FireCount++;
|
|
}
|
|
|
|
function PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
mRollInc = -1.f * 65536.f / mNumGrenades;
|
|
mRollPerSec = 65536.f * mDrumRotationsPerSec;
|
|
mGun = Frag(Weapon);
|
|
mHoldClampMax = (mHoldSpeedMax - mHoldSpeedMin) / mHoldSpeedGainPerSec;
|
|
}
|
|
|
|
// Client-side only: update the first person drum rotation
|
|
|
|
simulated function bool UpdateRoll(float dt)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
simulated function ReturnToIdle()
|
|
{
|
|
|
|
}
|
|
|
|
/* Accessor function that returns the type of projectile we want this weapon to fire right now. */
|
|
function class<Projectile> GetDesiredProjectileClass()
|
|
{
|
|
if ( KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo) != none &&
|
|
KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill != none )
|
|
{
|
|
return KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill.Static.GetNadeType(KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo));
|
|
}
|
|
|
|
return Super.GetDesiredProjectileClass();
|
|
}
|
|
|
|
/* Convenient place to perform changes to a newly spawned projectile */
|
|
function PostSpawnProjectile(Projectile P)
|
|
{
|
|
local Grenade g;
|
|
local vector X, Y, Z;
|
|
local float pawnSpeed;
|
|
|
|
G = Grenade(P);
|
|
|
|
if(G != none)
|
|
{
|
|
Weapon.GetViewAxes(X,Y,Z);
|
|
pawnSpeed = X dot Instigator.Velocity;
|
|
|
|
if ( Bot(Instigator.Controller) != None )
|
|
{
|
|
G.Speed = mHoldSpeedMax;
|
|
}
|
|
else
|
|
{
|
|
G.Speed = mHoldSpeedMin + HoldTime*mHoldSpeedGainPerSec;
|
|
}
|
|
|
|
G.Speed = FClamp(g.Speed, mHoldSpeedMin, mHoldSpeedMax);
|
|
G.Speed = pawnSpeed + G.Speed;
|
|
G.Velocity = G.Speed * Vector(G.Rotation);
|
|
|
|
Super.PostSpawnProjectile(G);
|
|
}
|
|
}
|
|
|
|
function InitEffects()
|
|
{
|
|
}
|
|
|
|
function DoFireEffect()
|
|
{
|
|
local Vector StartProj, StartTrace, X,Y,Z;
|
|
local Rotator Aim;
|
|
local Vector HitLocation, HitNormal;
|
|
local Actor Other;
|
|
local int Hand;
|
|
|
|
Instigator.MakeNoise(1.0);
|
|
Weapon.GetViewAxes(X,Y,Z);
|
|
|
|
StartTrace = Instigator.Location + Instigator.EyePosition();// + X*Instigator.CollisionRadius;
|
|
StartProj = StartTrace + X*ProjSpawnOffset.X;
|
|
|
|
if( PlayerController(Instigator.Controller)!=None )
|
|
{ // We must do this as server dosen't get a chance to set weapon handedness.
|
|
Hand = int(PlayerController(Instigator.Controller).Handedness);
|
|
if( Hand==-1 || Hand==1 )
|
|
StartProj = StartProj + Hand * Y*ProjSpawnOffset.Y + Z*ProjSpawnOffset.Z;
|
|
}
|
|
|
|
// check if projectile would spawn through a wall and adjust start location accordingly
|
|
Other = Weapon.Trace(HitLocation, HitNormal, StartProj, StartTrace, false);
|
|
if (Other != None)
|
|
StartProj = HitLocation;
|
|
|
|
Aim = AdjustAim(StartProj, AimError);
|
|
|
|
SpawnProjectile(StartProj, Aim);
|
|
}
|
|
|
|
event ModeDoFire()
|
|
{
|
|
if (!AllowFire())
|
|
return;
|
|
|
|
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();
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
|
|
state Wait
|
|
{
|
|
function BeginState()
|
|
{
|
|
SetTimer(mWaitTime, false);
|
|
}
|
|
|
|
function Timer()
|
|
{
|
|
GotoState('LoadNext'); //goto idle if out of ammo?
|
|
}
|
|
}
|
|
|
|
state LoadNext
|
|
{
|
|
function BeginState()
|
|
{
|
|
if (Level.NetMode != NM_Client)
|
|
Weapon.PlaySound(ReloadSound,SLOT_None,,,512.0,,false);
|
|
ClientPlayForceFeedback(ReloadForce);
|
|
}
|
|
|
|
function ModeTick(float dt)
|
|
{
|
|
if ( Weapon.Mesh != Weapon.OldMesh )
|
|
GotoState('Idle');
|
|
else if (UpdateRoll(dt))
|
|
GotoState('Idle');
|
|
}
|
|
}
|
|
|
|
function PlayFireEnd()
|
|
{
|
|
if(weapon.ammoAmount(0) <= 0)
|
|
weapon.DoAutoSwitch() ;
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
mBlend=1.000000
|
|
mDrumRotationsPerSec=0.400000
|
|
mScale=1.000000
|
|
mScaleMultiplier=0.900000
|
|
mSpeedMin=150.000000
|
|
mSpeedMax=1000.000000
|
|
mHoldSpeedMin=850.000000
|
|
mHoldSpeedMax=1600.000000
|
|
mHoldSpeedGainPerSec=750.000000
|
|
mWaitTime=0.500000
|
|
ProjSpawnOffset=(X=25.0,Y=-10.000000,Z=0.000000)
|
|
bFireOnRelease=True
|
|
bWaitForRelease=True
|
|
PreFireTime=0.500000
|
|
FireLoopAnim="LoopThrow"
|
|
FireSound=Sound'KF_AxeSnd.Axe_Fire'
|
|
FireRate=1.500000
|
|
AmmoClass=Class'KFMod.FragAmmo'
|
|
ShakeOffsetMag=(X=25.000000,Y=25.000000,Z=25.000000)
|
|
ShakeOffsetRate=(X=0.000000)
|
|
ProjectileClass=Class'Nade'
|
|
BotRefireRate=2.500000
|
|
FlashEmitterClass=None
|
|
SpreadStyle=SS_Random
|
|
}
|