1
0
KF2-Dev-Scripts/KFGameContent/Classes/KFExplosion_HRG_BallisticBouncer.uc

284 lines
8.1 KiB
Ucode
Raw Normal View History

2022-11-27 21:49:25 +00:00
//=============================================================================
// KFExplosion_HRG_BallisticBouncer
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFExplosion_HRG_BallisticBouncer extends KFExplosionActorLingering;
var() class<KFDamageType> HealingDamageType;
var() float HealingAmount;
var AkEvent SmokeLoopStartEvent;
var AkEvent SmokeLoopStopEvent;
var KFPerk CachedInstigatorPerk;
var float fChargePercentage;
var float fMinAmmoutHealing;
var float fMaxAmmoutHealing;
var float fAltMinAmmoutHealing;
var float fAltMaxAmmoutHealing;
var bool bHealsInstigator;
var bool bHealsDifferentAmmoutToInstigator;
/* Only used if bOnlyDamagePawns is active to create fractures in walls */
var bool bAllowFractureDamage;
simulated function SpawnExplosionParticleSystem(ParticleSystem Template)
{
local ParticleSystemComponent PSC;
local vector vec;
// If the template is none, grab the default
if( !ExplosionTemplate.bAllowPerMaterialFX && Template == none )
{
Template = KFGameExplosion(ExplosionTemplate).ExplosionEffects.DefaultImpactEffect.ParticleTemplate;
}
// Use custom pool
PSC = WorldInfo.MyEmitterPool.SpawnEmitter(Template, Location, rotator(ExplosionTemplate.HitNormal), None);
//fChargePercentage
vec.X = fChargePercentage;
vec.Y = fChargePercentage;
vec.Z = fChargePercentage;
PSC.SetVectorParameter( name("BlobCharge"), vec);
PSC.SetFloatParameter( name("MineFxControlParam"), fChargePercentage);
}
/*
* @param Direction For bDirectionalExplosion=true explosions, this is the forward direction of the blast.
* Overridden to add the ability to spawn fragments from the explosion
**/
simulated function Explode(GameExplosion NewExplosionTemplate, optional vector Direction)
{
local KFPawn KFP;
super.Explode(NewExplosionTemplate, Direction);
if( Instigator != none )
{
KFP = KFPawn(Instigator);
if( KFP != none )
{
CachedInstigatorPerk = KFP.GetPerk();
}
}
if (Role == Role_Authority)
{
//DelayedExplosionDamage();
SetTimer(Interval, false, nameof(DelayedExplosionDamage), self);
}
}
/**
* Deal damage or heal players
*/
protected simulated function AffectsPawn(Pawn Victim, float DamageScale)
{
local KFPawn_Human HumanVictim;
local KFPawn_Monster MonsterVictim;
local KFProj_MedicGrenade OwnerProjectile;
local bool bCanRepairArmor;
local Box BBox;
local vector BBoxCenter;
local Actor HitActor;
local bool bDamageBlocked;
if( Victim != none && Victim.IsAliveAndWell() )
{
MonsterVictim = KFPawn_Monster(Victim);
if( MonsterVictim != none )
{
if( bWasFadedOut|| bDeleteMe || bPendingDelete )
{
return;
}
Victim.GetComponentsBoundingBox(BBox);
BBoxCenter = (BBox.Min + BBox.Max) * 0.5f;
HitActor = TraceExplosive(BBoxCenter, Location + vect(0, 0, 20));
bDamageBlocked = (HitActor != None && HitActor != Victim);
if(bDamageBlocked && HitActor.IsA('KFDoorActor'))
{
bDamageBlocked = false;
}
if( !bDamageBlocked )
{
Victim.TakeRadiusDamage(InstigatorController, ExplosionTemplate.Damage * DamageScale, ExplosionTemplate.DamageRadius,
ExplosionTemplate.MyDamageType, ExplosionTemplate.MomentumTransferScale, Location, bDoFullDamage,
(Owner != None) ? Owner : self, ExplosionTemplate.DamageFalloffExponent);
}
}
else
{
Victim.GetComponentsBoundingBox(BBox);
BBoxCenter = (BBox.Min + BBox.Max) * 0.5f;
HitActor = TraceExplosive(BBoxCenter, Location + vect(0, 0, 20));
bDamageBlocked = (HitActor != None && HitActor != Victim);
if(bDamageBlocked && HitActor.IsA('KFDoorActor'))
{
bDamageBlocked = false;
}
if(!bDamageBlocked)
{
if(!bHealsInstigator && Victim == Instigator)
{
return;
}
HumanVictim = KFPawn_Human(Victim);
if( HumanVictim != none && HumanVictim.GetExposureTo(Location) > 0 )
{
OwnerProjectile = KFProj_MedicGrenade(Owner);
if( OwnerProjectile != none )
{
bCanRepairArmor = OwnerProjectile.HealedPawns.Find( HumanVictim ) == INDEX_NONE;
}
if(bHealsDifferentAmmoutToInstigator && bHealsInstigator && Victim == Instigator)
{
HumanVictim.HealDamage( Lerp(fAltMinAmmoutHealing, fAltMaxAmmoutHealing, fChargePercentage), InstigatorController, HealingDamageType, bCanRepairArmor);
}
else
{
HumanVictim.HealDamage( Lerp(fMinAmmoutHealing, fMaxAmmoutHealing, fChargePercentage), InstigatorController, HealingDamageType, bCanRepairArmor);
}
if( bCanRepairArmor )
{
OwnerProjectile.HealedPawns.AddItem( HumanVictim );
}
}
}
}
}
}
protected simulated function bool DoExplosionDamage(bool bCauseDamage, bool bCauseEffects)
{
if( bWasFadedOut || bDeleteMe || bPendingDelete )
{
return false;
}
if( bOnlyDamagePawns && bAllowFractureDamage )
{
ExplodeFractures();
}
if( bOnlyDamagePawns )
{
return ExplodePawns(bCauseDamage);
}
return super(KFExplosionActor).DoExplosionDamage(bCauseDamage, bCauseEffects);
}
/** Check fractures only if */
protected simulated function ExplodeFractures()
{
local Actor Victim;
local bool bCauseFractureEffects;
local float CheckRadius, VictimDist;
local Box BBox;
local FracturedStaticMeshActor FracActor;
local byte WantPhysChunksAndParticles;
local TraceHitInfo HitInfo;
if( bWasFadedOut || bDeleteMe || bPendingDelete )
{
return;
}
bCauseFractureEffects = WorldInfo.NetMode != NM_DedicatedServer && ExplosionTemplate.bCausesFracture;
if( !bCauseFractureEffects )
{
return;
}
// determine radius to check
CheckRadius = GetEffectCheckRadius(true, bCauseFractureEffects, WorldInfo.NetMode != NM_Client);
if ( CheckRadius > 0.0 )
{
foreach CollidingActors(class'Actor', Victim, CheckRadius, Location, ExplosionTemplate.bUseOverlapCheck,,HitInfo )
{
if ( Victim != Self
&& (!Victim.bWorldGeometry || Victim.bCanBeDamaged)
&& (NavigationPoint(Victim) == None)
&& Victim != ExplosionTemplate.ActorToIgnoreForDamage
&& (!ExplosionTemplate.bIgnoreInstigator || Victim != Instigator)
&& !ClassIsChildOf(Victim.Class, ExplosionTemplate.ActorClassToIgnoreForDamage)
&& !IsBehindExplosion(Victim) )
{
// return if this is a pawn
if(GamePawn(Victim) != none)
{
return;
}
// check if visible, unless physics object
// note: using bbox center instead of location, because that's what visiblecollidingactors does
Victim.GetComponentsBoundingBox(BBox);
// adjust distance if using overlap check
VictimDist = ExplosionTemplate.bUseOverlapCheck ? BoxDistanceToPoint(Location, BBox) : VSize(Location - Victim.Location);
FracActor = FracturedStaticMeshActor(Victim);
if ( (FracActor != None)
&& (VictimDist < ExplosionTemplate.FractureMeshRadius)
&& (FracActor.Physics == PHYS_None)
&& FracActor.IsFracturedByDamageType(ExplosionTemplate.MyDamageType)
&& FracActor.FractureEffectIsRelevant( false, Instigator, WantPhysChunksAndParticles) )
{
// Let kismet know that we were hit by an explosion
FracActor.NotifyHitByExplosion(InstigatorController, ExplosionTemplate.Damage, ExplosionTemplate.MyDamageType);
FracActor.BreakOffPartsInRadius(Location, ExplosionTemplate.FractureMeshRadius, ExplosionTemplate.FracturePartVel, WantPhysChunksAndParticles == 1 ? true : false);
}
}
}
}
}
DefaultProperties
{
HealingDamageType=class'KFDT_Healing'
HealingAmount=0;
fMinAmmoutHealing=5; //4;
fMaxAmmoutHealing=50; //40
Interval=0
MaxTime=0.0
FadeOutTime=0.0
bExplodeMoreThanOnce=false
bDoFullDamage=false
bOnlyDamagePawns=true
bAllowFractureDamage=true
bSkipLineCheckForPawns=true
LoopStartEvent=none
LoopStopEvent=none
//EXPERIMENTAL FEATURES FOR DESIGN
bHealsInstigator = false;
bHealsDifferentAmmoutToInstigator = false;
fAltMinAmmoutHealing=1;
fAltMaxAmmoutHealing=5;
}