1
0
KF2-Dev-Scripts/KFGameContent/Classes/KFProj_Thrown_C4.uc
2020-12-13 18:01:13 +03:00

434 lines
11 KiB
Ucode

//=============================================================================
// KFProj_Thrown_C4
//=============================================================================
// Projectile class for C4 weapon
//=============================================================================
// Killing Floor 2
// Copyright (C) 2015 Tripwire Interactive LLC
// Jeff Robinson
//=============================================================================
class KFProj_Thrown_C4 extends KFProjectile;
var KFImpactEffectInfo ImpactEffectInfo;
/** "beep" sound to play (on an interval) when instigator is within blast radius */
var() AkEvent ProximityAlertAkEvent;
/** Time between proximity beeps */
var() float ProximityAlertInterval;
/** Time between proximity beeps when the instigator is within "fatal" radius */
var() float ProximityAlertIntervalClose;
/** Time until next alert */
var transient float ProximityAlertTimer;
/** Visual component of this projectile (we don't use ProjEffects particle system because we need to manipulate the MIC) */
var StaticMeshComponent ChargeMesh;
/** Mesh MIC, used to make LED blink */
var MaterialInstanceConstant ChargeMIC;
/** Dynamic light for blinking */
var PointLightComponent BlinkLightComp;
/** Blink colors */
var LinearColor BlinkColorOn, BlinkColorOff;
/** How long LED and dynamic light should stay lit for */
var float BlinkTime;
var ParticleSystem BlinkFX;
var ParticleSystemComponent BlinkPSC;
/** Id for skin override */
var repnotify int WeaponSkinId;
replication
{
if(bNetDirty)
WeaponSkinId;
}
simulated function PostBeginPlay()
{
if( WorldInfo.NetMode != NM_Client )
{
if( InstigatorController != none )
{
class'KFGameplayPoolManager'.static.GetPoolManager().AddProjectileToPool( self, PPT_C4 );
}
else
{
Destroy();
return;
}
}
super.PostBeginPlay();
ProximityAlertTimer = ProximityAlertInterval;
AdjustCanDisintigrate();
ChargeMIC = ChargeMesh.CreateAndSetMaterialInstanceConstant(0);
}
/** 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 (StuckToActor != none)
{
UpdateAlert(DeltaTime);
}
}
/** Checks if deployed charge should play a warning "beep" for the instigator. Beeps faster if the instigator is within "lethal" range. */
simulated function UpdateAlert( float DeltaTime )
{
local vector ToInstigator, BBoxCenter;
local float DistToInstigator, DamageScale;
local Actor TraceActor;
local Box BBox;
if( WorldInfo.NetMode == NM_DedicatedServer )
{
return;
}
if( bHasExploded || bHasDisintegrated )
{
return;
}
if( ProximityAlertTimer <= 0 )
{
return;
}
ProximityAlertTimer -= DeltaTime;
if( ProximityAlertTimer > 0 )
{
return;
}
ProximityAlertTimer = ProximityAlertInterval;
// only play sound for instigator (based on distance)
if( Instigator != none && Instigator.IsLocallyControlled() )
{
ToInstigator = Instigator.Location - Location;
DistToInstigator = VSize( ToInstigator );
if( DistToInstigator <= ExplosionTemplate.DamageRadius )
{
Instigator.GetComponentsBoundingBox(BBox);
BBoxCenter = (BBox.Min + BBox.Max) * 0.5f;
TraceActor = class'GameExplosionActor'.static.StaticTraceExplosive(BBoxCenter, Location + vect(0,0,20), self);
if( TraceActor == none || TraceActor == Instigator )
{
DamageScale = FClamp(1.f - DistToInstigator/ExplosionTemplate.DamageRadius, 0.f, 1.f);
DamageScale = DamageScale ** ExplosionTemplate.DamageFalloffExponent;
if( ExplosionTemplate.Damage * DamageScale > Instigator.Health )
{
ProximityAlertTimer = ProximityAlertIntervalClose;
}
PlaySoundBase( ProximityAlertAkEvent, true );
}
}
}
// blink for everyone to see
BlinkOn();
}
/** Turns on LED and dynamic light */
simulated function BlinkOn()
{
if( BlinkPSC == none )
{
BlinkPSC = WorldInfo.MyEmitterPool.SpawnEmitter(BlinkFX, Location + (vect(0,0,4) + vect(8,0,0) >> Rotation),, self,,, true);
}
BlinkPSC.SetFloatParameter('Glow', 1.0);
ChargeMIC.SetVectorParameterValue('Vector_GlowColor', BlinkColorOn);
BlinkLightComp.SetEnabled( true );
SetTimer( BlinkTime, false, nameof(BlinkOff) );
}
/** Turns off LED and dynamic light */
simulated function BlinkOff()
{
if( BlinkPSC != none )
{
BlinkPSC.SetFloatParameter('Glow', 0.0);
}
ChargeMIC.SetVectorParameterValue('Vector_GlowColor', BlinkColorOff);
BlinkLightComp.SetEnabled( false );
}
simulated function SetStickOrientation(vector HitNormal)
{
local rotator StickRot;
StickRot = CalculateStickOrientation(HitNormal);
SetRotation(StickRot);
}
/** Causes charge to explode */
function Detonate()
{
local KFWeap_Thrown_C4 C4WeaponOwner;
local vector ExplosionNormal;
if( Role == ROLE_Authority )
{
C4WeaponOwner = KFWeap_Thrown_C4( Owner );
if( C4WeaponOwner != none )
{
C4WeaponOwner.RemoveDeployedCharge(, self);
}
}
ExplosionNormal = vect(0,0,1) >> Rotation;
Explode( Location, ExplosionNormal );
}
simulated function Explode(vector HitLocation, vector HitNormal)
{
if( WorldInfo.NetMode != NM_DedicatedServer )
{
BlinkOff();
}
super.Explode( HitLocation, HitNormal );
}
simulated function Disintegrate( rotator InDisintegrateEffectRotation )
{
local KFWeap_Thrown_C4 C4WeaponOwner;
if( Role == ROLE_Authority )
{
C4WeaponOwner = KFWeap_Thrown_C4( Owner );
if( C4WeaponOwner != none )
{
C4WeaponOwner.RemoveDeployedCharge(, self);
}
}
if( WorldInfo.NetMode != NM_DedicatedServer )
{
BlinkOff();
}
super.Disintegrate( InDisintegrateEffectRotation );
}
// for nukes && concussive force
simulated protected function PrepareExplosionTemplate()
{
class'KFPerk_Demolitionist'.static.PrepareExplosive( Instigator, self );
super.PrepareExplosionTemplate();
}
simulated protected function SetExplosionActorClass()
{
local KFPlayerReplicationInfo InstigatorPRI;
if( WorldInfo.TimeDilation < 1.f && Instigator != none )
{
InstigatorPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo);
if( InstigatorPRI != none )
{
if( InstigatorPRI.bNukeActive && class'KFPerk_Demolitionist'.static.ProjectileShouldNuke( self ) )
{
ExplosionActorClass = class'KFPerk_Demolitionist'.static.GetNukeExplosionActorClass();
}
}
}
super.SetExplosionActorClass();
}
/** Blows up on a timer */
function Timer_Explode()
{
Detonate();
}
/** Remove C4 from pool */
simulated event Destroyed()
{
if( WorldInfo.NetMode != NM_Client )
{
if( InstigatorController != none )
{
class'KFGameplayPoolManager'.static.GetPoolManager().RemoveProjectileFromPool( self, PPT_C4 );
}
}
super.Destroyed();
}
/** 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_Explode) );
}
}
simulated function SetWeaponSkin(int SkinId)
{
local array<MaterialInterface> SkinMICs;
local int i;
if (SkinId > 0)
{
SkinMICs = class'KFWeaponSkinList'.static.GetWeaponSkin(SkinId, WST_FirstPerson);
for (i = 0; i < SkinMICs.length; i++)
{
ChargeMesh.SetMaterial(i, SkinMICs[i]);
}
}
ChargeMIC = ChargeMesh.CreateAndSetMaterialInstanceConstant(0);
}
defaultproperties
{
StuckToBoneIdx=INDEX_NONE
Physics=PHYS_Falling
MaxSpeed=1200.0
Speed=1200.0
TossZ=100
GravityScale=1.0
LifeSpan=0
bBounce=true
GlassShatterType=FMGS_ShatterDamaged
ExplosionActorClass=class'KFExplosionActorC4'
DamageRadius=0
bCollideComplex=true
bIgnoreFoliageTouch=true
bBlockedByInstigator=false
bAlwaysReplicateExplosion=true
bNetTemporary=false
bCanBeDamaged=true
bCanDisintegrate=true
Begin Object Name=CollisionCylinder
BlockNonZeroExtent=false
// for siren scream
CollideActors=true
End Object
AlwaysRelevantDistanceSquared=6250000 // 25m, same as grenade
AltExploEffects=KFImpactEffectInfo'WEP_C4_ARCH.C4_Explosion_Concussive_Force'
// blink light
Begin Object Class=PointLightComponent Name=BlinkPointLight
LightColor=(R=255,G=63,B=63,A=255)
Brightness=4.f
Radius=300.f
FalloffExponent=10.f
CastShadows=False
CastStaticShadows=FALSE
CastDynamicShadows=False
bCastPerObjectShadows=false
bEnabled=FALSE
LightingChannels=(Indoor=TRUE,Outdoor=TRUE,bInitialized=TRUE)
Translation=(X=8, Z=4)
End Object
BlinkLightComp=BlinkPointLight
Components.Add(BlinkPointLight)
// projectile mesh (use this instead of ProjEffects particle system)
Begin Object Class=StaticMeshComponent Name=StaticMeshComponent0
StaticMesh=StaticMesh'WEP_3P_C4_MESH.Wep_C4_Projectile'
bCastDynamicShadow=FALSE
CollideActors=false
LightingChannels=(bInitialized=True,Dynamic=True,Indoor=True,Outdoor=True)
End Object
ChargeMesh=StaticMeshComponent0
Components.Add(StaticMeshComponent0)
// explosion light
Begin Object Class=PointLightComponent Name=ExplosionPointLight
LightColor=(R=252,G=218,B=171,A=255)
Brightness=4.f
Radius=2000.f
FalloffExponent=10.f
CastShadows=False
CastStaticShadows=FALSE
CastDynamicShadows=False
bCastPerObjectShadows=false
bEnabled=FALSE
LightingChannels=(Indoor=TRUE,Outdoor=TRUE,bInitialized=TRUE)
End Object
// explosion
Begin Object Class=KFGameExplosion Name=ExploTemplate0
Damage=820
DamageRadius=400
DamageFalloffExponent=2.f
DamageDelay=0.f
// Damage Effects
MyDamageType=class'KFDT_Explosive_C4'
KnockDownStrength=0
FractureMeshRadius=200.0
FracturePartVel=500.0
ExplosionEffects=KFImpactEffectInfo'WEP_C4_ARCH.C4_Explosion'
ExplosionSound=AkEvent'WW_WEP_EXP_C4.Play_WEP_EXP_C4_Explosion'
// Dynamic Light
ExploLight=ExplosionPointLight
ExploLightStartFadeOutTime=0.0
ExploLightFadeOutTime=0.2
// Camera Shake
CamShake=CameraShake'FX_CameraShake_Arch.Misc_Explosions.Light_Explosion_Rumble'
CamShakeInnerRadius=200
CamShakeOuterRadius=900
CamShakeFalloff=1.5f
bOrientCameraShakeTowardsEpicenter=true
End Object
ExplosionTemplate=ExploTemplate0
ImpactEffectInfo=KFImpactEffectInfo'WEP_C4_ARCH.C4_Projectile_Impacts'
ProjDisintegrateTemplate=ParticleSystem'ZED_Siren_EMIT.FX_Siren_grenade_disable_01'
ProximityAlertAkEvent=AkEvent'WW_WEP_EXP_C4.Play_WEP_EXP_C4_Prox_Beep'
ProximityAlertInterval=1.0
ProximityAlertIntervalClose=0.5
BlinkTime=0.2f
BlinkColorOff=(R=0, G=0, B=0)
BlinkColorOn=(R=1, G=0, B=0)
BlinkFX=ParticleSystem'WEP_C4_EMIT.FX_C4_Glow'
bCanStick=true
Begin Object Class=KFProjectileStickHelper Name=StickHelper0
StickAkEvent=AkEvent'WW_WEP_EXP_C4.Play_WEP_EXP_C4_Handling_Place'
End Object
StickHelper=StickHelper0
}