Code:
class railFire extends InstantFire;
#exec LOAD OBJ FILE=forcompile\WGS_rail_SNDS.uax PACKAGE=WGS_UWEPm
var() class<railBeamEffect> BeamClass;
var() float ChargeExponent;
var() float HeadShotDamageMult;
var() float HeadShotRadius;
var() class<DamageType> HeadshotDamageType;
var() float LimbShotDamageMult;
var() float TorsoShotRadius;
var() class<DamageType> TorsoshotDamageType;
var rail Gun;
simulated function PostBeginPlay()
{
Super.PostBeginPlay();
Gun = rail(Owner);
}
function StartBerserk() {
FireRate = default.FireRate * 0.70;
FireAnimRate = default.FireAnimRate / 0.70;
}
//Discharge after firing.
function DoFireEffect()
{
local float DamageMult;
DamageMult = Gun.ChargeLevel ** ChargeExponent;
DamageMax = Default.DamageMax * DamageMult;
DamageMin = Default.DamageMin * DamageMult;
Super.DoFireEffect();
Gun.ChargeLevel = 0;
}
function DoTrace(Vector Start, Rotator Dir)
{
local Vector X, End, HitLocation, HitNormal;
local Actor Other;
local int Damage;
local float dist;
local name HitBone;
local vector BoneTestLocation, ClosestLocation;
local float HitHorizontal, HitVertical;
X = Vector(Dir);
End = Start + TraceRange * X;
//Can fire straight through anything but world geometry.
foreach Weapon.TraceActors(class'Actor', Other, HitLocation, HitNormal, End, Start)
{
if(Other == Instigator)
continue;
//Commented out to make the rail bolt pass through walls
/* if(Other.bWorldGeometry)
{
if(WeaponAttachment(Weapon.ThirdPersonActor) != None)
WeaponAttachment(Weapon.ThirdPersonActor).UpdateHit(Other, HitLocation, HitNormal);
break;
} */
Damage = DamageMin;
if((DamageMin != DamageMax) && (FRand() > 0.5))
Damage += Rand(1 + DamageMax - DamageMin);
if(Other.IsA('Pawn'))
{
Instigator.PlaySound(Sound'WGS_UWEPm.rail_hitarmor');
//Find a point on the victim's Z axis at the same height as the HitLocation.
ClosestLocation = Other.Location;
ClosestLocation.Z += (HitLocation - Other.Location).Z;
//Extend the shot along its direction to a point where it is closest to the victim's Z axis.
BoneTestLocation = X;
BoneTestLocation *= VSize(ClosestLocation - HitLocation);
BoneTestLocation *= normal(ClosestLocation - HitLocation) dot normal(HitLocation - Start);
BoneTestLocation += HitLocation;
//Vehicles 'head' considered to be dead centre.
if(Other.IsA('Vehicle'))
{
Instigator.PlaySound(Sound'WGS_UWEPm.rail_hitflesh');
HitVertical = Abs(BoneTestLocation.Z - Other.Location.Z);
BoneTestLocation.Z = Other.Location.Z;
HitHorizontal = VSize(BoneTestLocation - Other.Location);
if(HitVertical < Other.CollisionHeight * 0.6 && HitHorizontal < Other.CollisionRadius * 0.6)
{
if(HitVertical < Other.CollisionHeight * 0.4 && HitHorizontal < Other.CollisionRadius * 0.4)
HitBone = 'head';
else
HitBone = 'spine';
}
else
HitBone = 'vehicle';
}
else
{
//Find the closest bone.
HitBone = Other.GetClosestBone(BoneTestLocation, X, dist, 'head', HeadShotRadius);
if(HitBone != 'head')
HitBone = Other.GetClosestBone(BoneTestLocation, X, dist, 'spine', TorsoShotRadius);
}
//Caters for monsters, and anything else without any bones.
if(HitBone =='None')
{
Instigator.PlaySound(Sound'WGS_UWEPm.rail_hitflesh');
HitVertical = BoneTestLocation.Z - Other.Location.Z;
BoneTestLocation.Z = Other.Location.Z;
HitHorizontal = VSize(BoneTestLocation - Other.Location);
if(HitHorizontal < Other.CollisionRadius * 0.6)
{
if(HitVertical > Other.CollisionHeight * 0.8)
HitBone = 'head';
else if(HitVertical > Other.CollisionHeight * -0.4)
HitBone = 'spine';
}
}
if(HitBone == 'head')
{
Damage *= HeadShotDamageMult;
DamageType = HeadshotDamageType;
}
else if(HitBone == 'spine')
DamageType = TorsoshotDamageType;
else
{
Damage *= LimbShotDamageMult;
DamageType = Default.DamageType;
}
}
Damage *= DamageAtten;
Damage *= Instigator.DamageScaling;
Other.TakeDamage(Damage, Instigator, HitLocation, Momentum * X, DamageType);
//Hack to get headshot announcements for killing monsters.
if(HitBone == 'head' && Other.IsA('Monster') && Pawn(Other).Health <= 0)
Instigator.ReceiveLocalizedMessage(class'wgsSpecialKillMessage', 0, Instigator.PlayerReplicationInfo, None, None);
HitNormal = Vect(0,0,0);
}
if(Other == None)
{
HitLocation = End;
HitNormal = Vect(0,0,0);
}
SpawnBeamEffect(Start, Dir, HitLocation, HitNormal, 0);
}
function InitEffects()
{
Super.InitEffects();
if ( FlashEmitter != None )
Weapon.AttachToBone(FlashEmitter, 'Bone_Flash');
}
function SpawnBeamEffect(Vector Start, Rotator Dir, Vector HitLocation, Vector HitNormal, int ReflectNum)
{
local railBeamEffect Beam;
Beam = Spawn(BeamClass,,, Start, Dir);
Beam.AimAt(HitLocation, HitNormal, Gun.ChargeLevel);
}
Bookmarks