2020-12-13 15:01:13 +00:00
|
|
|
//=============================================================================
|
|
|
|
// KFExplosion_MineReconstructor
|
|
|
|
//=============================================================================
|
|
|
|
// Used by projectiles and kismet to spawn an explosion
|
|
|
|
//=============================================================================
|
|
|
|
// Killing Floor 2
|
|
|
|
// Copyright (C) 2015 Tripwire Interactive LLC
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
class KFExplosion_MineReconstructor 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 )
|
|
|
|
{
|
2022-09-01 15:58:51 +00:00
|
|
|
return ExplodePawns(bCauseDamage);
|
2020-12-13 15:01:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2021-11-16 17:03:42 +00:00
|
|
|
fMinAmmoutHealing=5; //4;
|
|
|
|
fMaxAmmoutHealing=50; //40
|
2020-12-13 15:01:13 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|