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

203 lines
7.2 KiB
Ucode

class ScrnHuskGunProjectile extends HuskGunProjectile;
var bool bAppliedCharge;
//overrided to use alternate burning mechanism
simulated function HurtRadius( float DamageAmount, float DamageRadius, class<DamageType> DamageType, float Momentum, vector HitLocation )
{
local actor Victims;
local float damageScale, dist;
local vector dirs;
local int NumKilled;
local Pawn P;
local KFMonster KFMonsterVictim;
local KFPawn KFP;
local array<Pawn> CheckedPawns;
local int i;
local bool bAlreadyChecked;
//local int OldHealth;
if ( bHurtEntry )
return;
bHurtEntry = true;
foreach CollidingActors (class 'Actor', Victims, DamageRadius, HitLocation) {
// null pawn variables here just to be sure they didn't left from previous iteration
// and waste another day of my life to looking for this fucking bug -- PooSH /totallyPissedOff!!!
P = none;
KFMonsterVictim = none;
KFP = none;
// don't let blast damage affect fluid - VisibleCollisingActors doesn't really work for them - jag
if( (Victims != self) && (Victims != Instigator) &&(Hurtwall != Victims)
&& (Victims.Role == ROLE_Authority) && !Victims.IsA('FluidSurfaceInfo')
&& ExtendedZCollision(Victims)==None && KFBulletWhipAttachment(Victims)==None )
{
dirs = Victims.Location - HitLocation;
dist = FMax(1,VSize(dirs));
dirs = dirs/dist;
damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius);
if ( Instigator == None || Instigator.Controller == None )
Victims.SetDelayedDamageInstigatorController( InstigatorController );
if ( Victims == LastTouched )
LastTouched = None;
P = Pawn(Victims);
if( P != none ) {
for (i = 0; i < CheckedPawns.Length; i++) {
if (CheckedPawns[i] == P) {
bAlreadyChecked = true;
break;
}
}
if( bAlreadyChecked )
{
bAlreadyChecked = false;
P = none;
continue;
}
if( KFMonsterVictim != none && KFMonsterVictim.Health <= 0 ) {
KFMonsterVictim = none;
}
KFMonsterVictim = KFMonster(Victims);
KFP = KFPawn(Victims);
if( KFMonsterVictim != none )
damageScale *= KFMonsterVictim.GetExposureTo(HitLocation);
else if( KFP != none )
damageScale *= KFP.GetExposureTo(HitLocation);
CheckedPawns[CheckedPawns.Length] = P;
if ( damageScale <= 0)
continue;
}
if ( KFMonsterVictim != none && class'ScrnBalance'.default.Mut.BurnMech != none) {
class'ScrnBalance'.default.Mut.BurnMech.MakeBurnDamage(
KFMonsterVictim,
damageScale * DamageAmount,
Instigator,
Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dirs,
(damageScale * Momentum * dirs),
DamageType
);
}
else {
Victims.TakeDamage
(
damageScale * DamageAmount,
Instigator,
Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dirs,
(damageScale * Momentum * dirs),
DamageType
);
}
if (Vehicle(Victims) != None && Vehicle(Victims).Health > 0)
Vehicle(Victims).DriverRadiusDamage(DamageAmount, DamageRadius, InstigatorController, DamageType, Momentum, HitLocation);
if( Role == ROLE_Authority && KFMonsterVictim != none && KFMonsterVictim.Health <= 0 )
{
NumKilled++;
}
}
}
if( Role == ROLE_Authority )
{
if( NumKilled >= 4 )
{
KFGameType(Level.Game).DramaticEvent(0.05);
}
else if( NumKilled >= 2 )
{
KFGameType(Level.Game).DramaticEvent(0.03);
}
}
bHurtEntry = false;
}
// in case when the projectile touched a victim on spawn and WeaponFire haven't applied charge yet
function CheckCharge()
{
local ScrnHuskGunFire FireMode;
if ( bAppliedCharge )
return;
if ( Instigator != none && Instigator.Weapon != none )
FireMode = ScrnHuskGunFire( Instigator.Weapon.GetFireMode(0) );
if ( FireMode != none )
FireMode.ApplyCharge(self);
}
simulated function ProcessTouch(Actor Other, Vector HitLocation)
{
local vector X;
local Vector TempHitLocation, HitNormal, OtherLocation;
local array<int> HitPoints;
local KFPawn HitPawn;
// Don't let it hit this player, or blow up on another player
if ( Other == none || Other == Instigator || Other.Base == Instigator || !Other.bBlockHitPointTraces )
return;
// Use the instigator's location if it exists. This fixes issues with
// the original location of the projectile being really far away from
// the real Origloc due to it taking a couple of milliseconds to
// replicate the location to the client and the first replicated location has
// already moved quite a bit.
if( Instigator != none ) {
OrigLoc = Instigator.Location;
}
X = Vector(Rotation);
OtherLocation = Other.Location;
if( Instigator != none && ROBulletWhipAttachment(Other) != none ) {
// we touched player's auxilary collision cylinder, not let's trace to the player himself
// Other.Base = KFPawn
if( Other.Base == none || Other.Base.bDeleteMe )
return;
Other = Instigator.HitPointTrace(TempHitLocation, HitNormal, HitLocation + (200 * X), HitPoints, HitLocation,, 1);
if( Other == none || HitPoints.Length == 0 || Other.bDeleteMe )
return; // bullet didn't hit a pawn
HitPawn = KFPawn(Other);
if ( HitPawn != none ) {
// Don't allow hits on people on the same team - except hardcore mode
if ( !class'ScrnBalance'.default.Mut.bHardcore && HitPawn.GetTeamNum() == Instigator.GetTeamNum() )
return;
CheckCharge();
HitPawn.ProcessLocationalDamage(Damage, Instigator, TempHitLocation, MomentumTransfer * Normal(Velocity), MyDamageType,HitPoints);
}
}
else {
CheckCharge();
Other.TakeDamage(ImpactDamage, Instigator, HitLocation, MomentumTransfer * Normal(Velocity), ImpactDamageType);
}
if( !bDud ) {
Explode(HitLocation,Normal(HitLocation-OtherLocation));
}
}
defaultproperties
{
HeadShotDamageMult=1.000000
ImpactDamageType=Class'ScrnBalanceSrv.ScrnDamTypeHuskGunProjectileImpact'
ImpactDamage=65
Damage=30.000000
}