rott/kf_sources/KFMod/Classes/SPShotgunAltFire.uc
2026-07-14 20:27:09 +07:00

242 lines
8.2 KiB
Ucode

//=============================================================================
// SPShotgunAltFire
//=============================================================================
// Steampunk Shotgun Alt fire class.
//=============================================================================
// Killing Floor Source
// Copyright (C) 2013 Tripwire Interactive LLC
// - John "Ramm-Jaeger" Gibson
//=============================================================================
class SPShotgunAltFire extends KFShotgunFire;
var() InterpCurve AppliedMomentumCurve; // How much momentum to apply to a zed based on how much mass it has
var float WideDamageMinHitAngle; // The angle to do sweeping strikes in front of the player. If zero do no strikes
var float PushRange; // The range to push zeds away when firing
simulated function bool AllowFire()
{
if(KFWeapon(Weapon).bIsReloading)
return false;
if(KFPawn(Instigator).SecondaryItem!=none)
return false;
if(KFPawn(Instigator).bThrowingNade)
return false;
// No ammo so just always fire
return true;
}
function DoFireEffect()
{
local Vector StartProj, StartTrace, X,Y,Z;
local Rotator Aim;
local Vector HitLocation, HitNormal;
local Actor Other;
local Pawn Victims;
local vector dir, lookdir;
local float DiffAngle, VictimDist;
local float AppliedMomentum;
local vector Momentum;
Instigator.MakeNoise(1.0);
Weapon.GetViewAxes(X,Y,Z);
StartTrace = Instigator.Location + Instigator.EyePosition();// + X*Instigator.CollisionRadius;
StartProj = StartTrace + X*ProjSpawnOffset.X;
if ( !Weapon.WeaponCentered() && !KFWeap.bAimingRifle )
StartProj = StartProj + Weapon.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);
if( WideDamageMinHitAngle > 0 )
{
foreach Weapon.VisibleCollidingActors( class 'Pawn', Victims, (PushRange * 2), StartTrace )
{
if( Victims.Health <= 0 )
{
continue;
}
if( Victims != Instigator )
{
// Don't push team mates or scripted characters (like the Ringmaster)
if( Victims.GetTeamNum() == Instigator.GetTeamNum()
|| Victims.IsA('KF_StoryNPC') )
{
continue;
}
VictimDist = VSizeSquared(Instigator.Location - Victims.Location);
//log("VictimDist = "$VictimDist$" PushRange = "$(PushRange*PushRange));
if( VictimDist > (((PushRange * 1.1) * (PushRange * 1.1)) + (Victims.CollisionRadius * Victims.CollisionRadius)) )
{
continue;
}
lookdir = Normal(Vector(Instigator.GetViewRotation()));
dir = Normal(Victims.Location - Instigator.Location);
DiffAngle = lookdir dot dir;
dir = Normal((Victims.Location + Victims.EyePosition()) - Instigator.Location);
if( DiffAngle > WideDamageMinHitAngle )
{
AppliedMomentum = InterpCurveEval(AppliedMomentumCurve,Victims.Mass);
HandleAchievement( Victims );
//log("Shot would hit "$Victims$" DiffAngle = "$DiffAngle);
Momentum = (dir * AppliedMomentum)/Victims.Mass;
Victims.AddVelocity( Momentum );
if( KFMonster(Victims) != none )
{
KFMonster(Victims).BreakGrapple();
}
}
// else
// {
// log("Shot would miss "$Victims$" DiffAngle = "$DiffAngle);
// }
}
}
}
if (Instigator != none )
{
// Really boost the momentum for low grav. Weapon only gets momentum on low grav
if( Instigator.Physics == PHYS_Falling
&& Instigator.PhysicsVolume.Gravity.Z > class'PhysicsVolume'.default.Gravity.Z)
{
Instigator.AddVelocity((KickMomentum * 10.0) >> Instigator.GetViewRotation());
}
}
}
function HandleAchievement( Pawn Victim )
{
local KFSteamStatsAndAchievements KFSteamStats;
if ( Victim.IsA( 'ZombieScrake' ) )
{
if (PlayerController( Instigator.Controller ) != none )
{
KFSteamStats = KFSteamStatsAndAchievements(PlayerController(Instigator.Controller).SteamStatsAndAchievements);
if ( KFSteamStats != none )
{
KFSteamStats.CheckAndSetAchievementComplete( KFSteamStats.KFACHIEVEMENT_PushScrakeSPJ );
}
}
}
}
// Handle setting new recoil
simulated function HandleRecoil(float Rec)
{
local rotator NewRecoilRotation;
local KFPlayerController KFPC;
local KFPawn KFPwn;
local vector AdjustedVelocity;
local float AdjustedSpeed;
if( Instigator != none )
{
KFPC = KFPlayerController(Instigator.Controller);
KFPwn = KFPawn(Instigator);
}
if( KFPC == none || KFPwn == none )
return;
if( !KFPC.bFreeCamera )
{
if( Weapon.GetFireMode(1).bIsFiring )
{
NewRecoilRotation.Pitch = RandRange( maxVerticalRecoilAngle * 0.5, maxVerticalRecoilAngle );
NewRecoilRotation.Yaw = RandRange( maxHorizontalRecoilAngle * 0.5, maxHorizontalRecoilAngle );
if( Rand( 2 ) == 1 )
NewRecoilRotation.Yaw *= -1;
if( Weapon.Owner != none && Weapon.Owner.Physics == PHYS_Falling &&
Weapon.Owner.PhysicsVolume.Gravity.Z > class'PhysicsVolume'.default.Gravity.Z )
{
AdjustedVelocity = Weapon.Owner.Velocity;
// Ignore Z velocity in low grav so we don't get massive recoil
AdjustedVelocity.Z = 0;
AdjustedSpeed = VSize(AdjustedVelocity);
//log("AdjustedSpeed = "$AdjustedSpeed$" scale = "$(AdjustedSpeed* RecoilVelocityScale * 0.5));
// Reduce the falling recoil in low grav
NewRecoilRotation.Pitch += (AdjustedSpeed* 3 * 0.5);
NewRecoilRotation.Yaw += (AdjustedSpeed* 3 * 0.5);
}
else
{
//log("Velocity = "$VSize(Weapon.Owner.Velocity)$" scale = "$(VSize(Weapon.Owner.Velocity)* RecoilVelocityScale));
NewRecoilRotation.Pitch += (VSize(Weapon.Owner.Velocity)* 3);
NewRecoilRotation.Yaw += (VSize(Weapon.Owner.Velocity)* 3);
}
NewRecoilRotation.Pitch += (Instigator.HealthMax / Instigator.Health * 5);
NewRecoilRotation.Yaw += (Instigator.HealthMax / Instigator.Health * 5);
NewRecoilRotation *= Rec;
KFPC.SetRecoil(NewRecoilRotation,RecoilRate * (default.FireRate/FireRate));
}
}
}
defaultproperties
{
KickMomentum=(X=-35.000000,Z=5.000000)
ProjPerFire=0//7
bAttachSmokeEmitter=True
TransientSoundVolume=2.0
TransientSoundRadius=500.000000
FireSoundRef="KF_SP_ZEDThrowerSnd.KFO_Shotgun_Secondary_Fire_M"
StereoFireSoundRef="KF_SP_ZEDThrowerSnd.KFO_Shotgun_Secondary_Fire_S"
NoAmmoSoundRef="KF_AA12Snd.AA12_DryFire"
FireRate=1.2
FireAnimRate=1.0
AmmoClass=none
ProjectileClass=none
BotRefireRate=1.750000
FlashEmitterClass=Class'ROEffects.MuzzleFlash1stSPShotgunAlt'
aimerror=1.000000
Spread=0
maxVerticalRecoilAngle=3200
maxHorizontalRecoilAngle=900
FireAimedAnim=Fire_Iron
bModeExclusive=false
//** View shake **//
ShakeOffsetMag=(X=6.0,Y=2.0,Z=6.0)
ShakeOffsetRate=(X=1000.0,Y=1000.0,Z=1000.0)
ShakeOffsetTime=1.25
ShakeRotMag=(X=50.0,Y=50.0,Z=250.0)
ShakeRotRate=(X=12500.0,Y=12500.0,Z=12500.0)
ShakeRotTime=3.0
bWaitForRelease=false
bRandomPitchFireSound=false
PushRange=150
WideDamageMinHitAngle=0.6
AmmoPerFire=0
AppliedMomentumCurve=(Points=((InVal=0.0,OutVal=10000.0),(InVal=350.0,OutVal=175000.0),(InVal=600.0,OutVal=250000.0)))
}