2021-09-02 21:46:08 +00:00
|
|
|
//=============================================================================
|
|
|
|
// KFProj_Bullet_ParasiteImplanterAlt
|
|
|
|
//=============================================================================
|
|
|
|
//=============================================================================
|
|
|
|
// Killing Floor 2
|
|
|
|
// Copyright (C) 2021 Tripwire Interactive LLC
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
class KFProj_Bullet_ParasiteImplanterAlt extends KFProjectile;
|
|
|
|
|
|
|
|
var float FuseTime;
|
|
|
|
|
|
|
|
/** This is the effect indicator that is played for the current user **/
|
|
|
|
var(Projectile) ParticleSystem ProjIndicatorTemplate;
|
|
|
|
var ParticleSystemComponent ProjIndicatorEffects;
|
|
|
|
|
|
|
|
var bool IndicatorActive;
|
|
|
|
var transient bool bShouldEnableIndicator;
|
|
|
|
|
|
|
|
var Class<GameExplosionActor> HumanExplosionActorClass;
|
|
|
|
var KFGameExplosion HumanExplosionTemplate;
|
|
|
|
|
|
|
|
var private AKEvent SeedTimerOutEvent;
|
|
|
|
|
|
|
|
simulated function TryActivateIndicator()
|
|
|
|
{
|
|
|
|
if(!IndicatorActive && Instigator != None)
|
|
|
|
{
|
|
|
|
IndicatorActive = true;
|
|
|
|
|
|
|
|
if(WorldInfo.NetMode == NM_Standalone || Instigator.Role == Role_AutonomousProxy ||
|
|
|
|
(Instigator.Role == ROLE_Authority && WorldInfo.NetMode == NM_ListenServer && Instigator.IsLocallyControlled() ))
|
|
|
|
{
|
|
|
|
if( ProjIndicatorTemplate != None )
|
|
|
|
{
|
|
|
|
ProjIndicatorEffects = WorldInfo.MyEmitterPool.SpawnEmitterCustomLifetime(ProjIndicatorTemplate);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ProjIndicatorEffects != None)
|
|
|
|
{
|
|
|
|
ProjIndicatorEffects.SetAbsolute(false, false, false);
|
|
|
|
ProjIndicatorEffects.SetLODLevel(WorldInfo.bDropDetail ? 1 : 0);
|
|
|
|
ProjIndicatorEffects.bUpdateComponentInTick = true;
|
|
|
|
AttachComponent(ProjIndicatorEffects);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the initial velocity and cook time
|
|
|
|
*/
|
|
|
|
simulated event PostBeginPlay()
|
|
|
|
{
|
|
|
|
Super.PostBeginPlay();
|
|
|
|
|
|
|
|
if (Role == ROLE_Authority)
|
|
|
|
{
|
|
|
|
SetTimer(FuseTime, false, 'Timer_Detonate');
|
|
|
|
}
|
|
|
|
|
|
|
|
AdjustCanDisintigrate();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Explode after a certain amount of time
|
|
|
|
*/
|
|
|
|
function Timer_Detonate()
|
|
|
|
{
|
|
|
|
Detonate();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Called when the owning instigator controller has left a game */
|
|
|
|
simulated function OnInstigatorControllerLeft()
|
|
|
|
{
|
|
|
|
if( WorldInfo.NetMode != NM_Client )
|
|
|
|
{
|
|
|
|
SetTimer( 1.f + Rand(5) + fRand(), false, nameOf(Timer_Detonate) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Trace down and get the location to spawn the explosion effects and decal
|
|
|
|
*/
|
|
|
|
simulated function GetExplodeEffectLocation(out vector HitLocation, out vector HitRotation, out Actor HitActor)
|
|
|
|
{
|
|
|
|
local vector EffectStartTrace, EffectEndTrace;
|
|
|
|
local TraceHitInfo HitInfo;
|
|
|
|
|
|
|
|
EffectStartTrace = Location + vect(0,0,1) * 4.f;
|
|
|
|
EffectEndTrace = EffectStartTrace - vect(0,0,1) * 32.f;
|
|
|
|
|
|
|
|
// Find where to put the decal
|
|
|
|
HitActor = Trace(HitLocation, HitRotation, EffectEndTrace, EffectStartTrace, false,, HitInfo, TRACEFLAG_Bullet);
|
|
|
|
|
|
|
|
// If the locations are zero (probably because this exploded in the air) set defaults
|
|
|
|
if (IsZero(HitLocation))
|
|
|
|
{
|
|
|
|
HitLocation = Location;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsZero(HitRotation))
|
|
|
|
{
|
|
|
|
HitRotation = vect(0,0,1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Used to check current status of StuckTo actor (to figure out if we should fall) */
|
|
|
|
simulated event Tick(float DeltaTime)
|
|
|
|
{
|
|
|
|
super.Tick(DeltaTime);
|
|
|
|
|
|
|
|
StickHelper.Tick(DeltaTime);
|
|
|
|
|
|
|
|
if (!IsZero(Velocity))
|
|
|
|
{
|
|
|
|
SetRelativeRotation(rotator(Velocity));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bShouldEnableIndicator)
|
|
|
|
{
|
|
|
|
TryActivateIndicator();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function Explode(vector HitLocation, vector HitNormal)
|
|
|
|
{
|
|
|
|
StickHelper.UnPin();
|
|
|
|
super.Explode(HitLocation, HitNormal);
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function SyncOriginalLocation()
|
|
|
|
{
|
|
|
|
local Actor HitActor;
|
|
|
|
local vector HitLocation, HitNormal;
|
|
|
|
local TraceHitInfo HitInfo;
|
|
|
|
|
|
|
|
if (Role < ROLE_Authority && Instigator != none && Instigator.IsLocallyControlled())
|
|
|
|
{
|
|
|
|
HitActor = Trace(HitLocation, HitNormal, OriginalLocation, Location,,, HitInfo, TRACEFLAG_Bullet);
|
|
|
|
if (HitActor != none)
|
|
|
|
{
|
|
|
|
StickHelper.TryStick(HitNormal, HitLocation, HitActor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated protected function StopSimulating()
|
|
|
|
{
|
|
|
|
super.StopSimulating();
|
|
|
|
|
|
|
|
if (ProjIndicatorEffects!=None)
|
|
|
|
{
|
|
|
|
ProjIndicatorEffects.DeactivateSystem();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Causes charge to explode */
|
|
|
|
function Detonate()
|
|
|
|
{
|
|
|
|
local KFPawn_Monster KFPM;
|
|
|
|
//@Todo: Some VFX?
|
|
|
|
if (StuckToActor != none)
|
|
|
|
{
|
|
|
|
KFPM = KFPawn_Monster(StuckToActor);
|
|
|
|
if (KFPM != none)
|
|
|
|
{
|
|
|
|
KFPM.ParasiteSeeds.RemoveItem(self);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
StickHelper.UnPin();
|
|
|
|
ShutDown();
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function OnActorSticked(Actor TargetActor)
|
|
|
|
{
|
|
|
|
local KFPawn_Monster KFPM;
|
|
|
|
|
|
|
|
KFPM = KFPawn_Monster(TargetActor);
|
|
|
|
if (KFPM != none)
|
|
|
|
{
|
|
|
|
if (Role == ROLE_Authority)
|
|
|
|
{
|
|
|
|
KFPM.AddParasiteSeed(self);
|
|
|
|
PlaySoundBase(SeedTimerOutEvent, false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WorldInfo.NetMode == NM_Client || WorldInfo.NetMode == NM_StandAlone)
|
|
|
|
{
|
|
|
|
bShouldEnableIndicator = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function ExplodeOnHuman(Vector HitLocation, Vector HitNormal, Actor HitActor)
|
|
|
|
{
|
|
|
|
local vector NudgedHitLocation, ExplosionDirection;
|
|
|
|
|
|
|
|
if (HumanExplosionTemplate != None)
|
|
|
|
{
|
|
|
|
StopSimulating();
|
|
|
|
|
|
|
|
// using a hit location slightly away from the impact point is nice for certain things
|
|
|
|
NudgedHitLocation = HitLocation + (HitNormal * 32.f);
|
|
|
|
|
|
|
|
ExplosionActor = Spawn(HumanExplosionActorClass, self,, NudgedHitLocation, rotator(HitNormal));
|
|
|
|
if (ExplosionActor != None)
|
|
|
|
{
|
|
|
|
ExplosionActor.Instigator = Instigator;
|
|
|
|
ExplosionActor.InstigatorController = InstigatorController;
|
|
|
|
|
|
|
|
PrepareExplosionTemplate();
|
|
|
|
|
|
|
|
// If the locations are zero (probably because this exploded in the air) set defaults
|
|
|
|
if( IsZero(HitLocation) )
|
|
|
|
{
|
|
|
|
HitLocation = Location;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( IsZero(HitNormal) )
|
|
|
|
{
|
|
|
|
HitNormal = vect(0,0,1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// these are needed for the decal tracing later in GameExplosionActor.Explode()
|
|
|
|
HumanExplosionTemplate.HitLocation = HitLocation;// NudgedHitLocation
|
|
|
|
HumanExplosionTemplate.HitNormal = HitNormal;
|
|
|
|
|
|
|
|
// If desired, attach to mover if we hit one
|
|
|
|
if(bAttachExplosionToHitMover && InterpActor(HitActor) != None)
|
|
|
|
{
|
|
|
|
ExplosionActor.Attachee = HitActor;
|
|
|
|
HumanExplosionTemplate.bAttachExplosionEmitterToAttachee = TRUE;
|
|
|
|
ExplosionActor.SetBase(HitActor);
|
|
|
|
}
|
|
|
|
|
|
|
|
// directional?
|
|
|
|
if (HumanExplosionTemplate.bDirectionalExplosion)
|
|
|
|
{
|
|
|
|
ExplosionDirection = GetExplosionDirection(HitNormal);
|
|
|
|
//DrawDebugLine(ExplosionActor.Location, ExplosionActor.Location+ExplosionDirection*64, 255, 255, 0, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// @todo: make this function responsible for setting explosion instance parameters, and take instance parameters
|
|
|
|
// out of GearExplosion (e.g. Attachee)
|
|
|
|
PrepareExplosionActor(ExplosionActor);
|
|
|
|
|
|
|
|
ExplosionActor.Explode(HumanExplosionTemplate, ExplosionDirection); // go bewm
|
|
|
|
}
|
|
|
|
|
|
|
|
// done with it
|
|
|
|
if (!bPendingDelete && !bDeleteMe)
|
|
|
|
{
|
|
|
|
// defer destruction so any replication of explosion stuff can happen if necessary
|
|
|
|
DeferredDestroy(PostExplosionLifetime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal)
|
|
|
|
{
|
|
|
|
if (KFPawn_Human(Other) != none && Other != Instigator)
|
|
|
|
{
|
|
|
|
ExplodeOnHuman(HitLocation, HitNormal, Other);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
super.ProcessTouch(Other, HitLocation, HitNormal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
defaultproperties
|
|
|
|
{
|
|
|
|
ProjFlightTemplate=ParticleSystem'WEP_ParasiteImplanter_EMIT.FX_Seed_Projectile'
|
|
|
|
ProjIndicatorTemplate=ParticleSystem'WEP_ParasiteImplanter_EMIT.FX_Seed_Projectile_Indicator'
|
|
|
|
|
|
|
|
bWarnAIWhenFired=true
|
|
|
|
|
|
|
|
MaxSpeed=15000.0 //10000.0 //4000.0
|
|
|
|
Speed=15000.0 //10000.0 //4000.0
|
|
|
|
TerminalVelocity=15000.0 //10000.0 //4000.0
|
|
|
|
|
|
|
|
Physics=PHYS_Falling
|
|
|
|
|
|
|
|
TossZ=0 //150
|
|
|
|
GravityScale=0 //0.01 //0.7
|
|
|
|
|
|
|
|
GlassShatterType=FMGS_ShatterAll
|
|
|
|
|
|
|
|
bCollideComplex=true
|
|
|
|
|
|
|
|
bIgnoreFoliageTouch=true
|
|
|
|
|
|
|
|
bBlockedByInstigator=false
|
|
|
|
bAlwaysReplicateExplosion=true
|
|
|
|
|
|
|
|
FuseTime=6.0 //4.0
|
|
|
|
|
|
|
|
bNetTemporary=false
|
|
|
|
NetPriority=5
|
|
|
|
NetUpdateFrequency=200
|
|
|
|
|
|
|
|
bNoReplicationToInstigator=false
|
|
|
|
bUseClientSideHitDetection=true
|
|
|
|
bUpdateSimulatedPosition=true
|
|
|
|
bSyncToOriginalLocation=true
|
|
|
|
bSyncToThirdPersonMuzzleLocation=true
|
|
|
|
|
|
|
|
PinBoneIdx=INDEX_None
|
|
|
|
|
|
|
|
bCanBeDamaged=true
|
|
|
|
bCanDisintegrate=true
|
|
|
|
ExplosionActorClass=class'KFExplosion_ParasiteSeed'
|
|
|
|
HumanExplosionActorClass=class'KFExplosion_ParasiteSeedHuman'
|
|
|
|
|
|
|
|
// explosion
|
|
|
|
Begin Object Class=KFGameExplosion Name=ExploTemplate0
|
2021-11-16 17:03:42 +00:00
|
|
|
Damage=300 //400
|
2021-09-02 21:46:08 +00:00
|
|
|
DamageRadius=450
|
|
|
|
DamageFalloffExponent=0.5f //1.f
|
|
|
|
DamageDelay=0.f
|
|
|
|
MyDamageType=class'KFDT_Toxic_ParasiteSeedExplosion'
|
|
|
|
|
|
|
|
// Damage Effects
|
|
|
|
KnockDownStrength=0
|
|
|
|
KnockDownRadius=0
|
|
|
|
FractureMeshRadius=0
|
|
|
|
FracturePartVel=0
|
|
|
|
// ExplosionEffects=KFImpactEffectInfo'FX_Impacts_ARCH.Explosions.MedicGrenade_Explosion'
|
|
|
|
ExplosionSound=AkEvent'WW_WEP_Medic_GrenadeLauncher.Play_WEP_Medic_GrenadeLauncher_Grenade_Explosion'
|
|
|
|
MomentumTransferScale=0
|
|
|
|
|
|
|
|
// Camera Shake
|
|
|
|
CamShake=none
|
|
|
|
CamShakeInnerRadius=0
|
|
|
|
CamShakeOuterRadius=0
|
|
|
|
CamShakeFalloff=1.5f
|
|
|
|
bOrientCameraShakeTowardsEpicenter=true
|
|
|
|
End Object
|
|
|
|
ExplosionTemplate=ExploTemplate0
|
|
|
|
|
|
|
|
Begin Object Class=KFGameExplosion Name=ExploTemplate1
|
|
|
|
Damage=1 //250
|
|
|
|
DamageRadius=100 //450
|
|
|
|
DamageFalloffExponent=0.5f //1.f
|
|
|
|
DamageDelay=0.f
|
|
|
|
|
|
|
|
// Damage Effects
|
|
|
|
KnockDownStrength=0
|
|
|
|
KnockDownRadius=0
|
|
|
|
FractureMeshRadius=0
|
|
|
|
FracturePartVel=0
|
|
|
|
// ExplosionEffects=KFImpactEffectInfo'FX_Impacts_ARCH.Explosions.MedicGrenade_Explosion'
|
|
|
|
ExplosionSound=AkEvent'WW_WEP_Medic_GrenadeLauncher.Play_WEP_Medic_GrenadeLauncher_Grenade_Explosion'
|
|
|
|
MomentumTransferScale=0
|
|
|
|
|
|
|
|
// Camera Shake
|
|
|
|
CamShake=none
|
|
|
|
CamShakeInnerRadius=0
|
|
|
|
CamShakeOuterRadius=0
|
|
|
|
CamShakeFalloff=1.5f
|
|
|
|
bOrientCameraShakeTowardsEpicenter=true
|
|
|
|
End Object
|
|
|
|
HumanExplosionTemplate=ExploTemplate1
|
|
|
|
|
|
|
|
bCanStick=true
|
|
|
|
bCanPin=true
|
|
|
|
|
|
|
|
Begin Object Class=KFProjectileStickHelper_ParasiteImplanter Name=StickHelper0
|
|
|
|
End Object
|
|
|
|
StickHelper=StickHelper0
|
|
|
|
|
|
|
|
ProjDisintegrateTemplate=ParticleSystem'ZED_Siren_EMIT.FX_Siren_grenade_disable_01'
|
|
|
|
|
|
|
|
bShouldEnableIndicator=false;
|
|
|
|
|
|
|
|
ImpactEffects = KFImpactEffectInfo'WEP_ParasiteImplanter_ARCH.Wep_Parasite_Impact_Alt'
|
|
|
|
|
|
|
|
SeedTimerOutEvent = AkEvent'WW_WEP_ParasiteImplanter.Play_WEP_ParasiteImplanter_Seed_Timer_Out';
|
|
|
|
}
|