1
0
KF2-Dev-Scripts/KFGameContent/Classes/KFProj_Bullet_ParasiteImplanterAlt.uc
2021-09-03 00:46:08 +03:00

382 lines
10 KiB
Ucode

//=============================================================================
// 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
Damage=400 //250
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';
}