//============================================================================= // KFProj_BloodBall_HRG_Vampire //============================================================================= // Projectile class for Vampire //============================================================================= // Killing Floor 2 // Copyright (C) 2020 Tripwire Interactive LLC //============================================================================= class KFProj_BloodBall_HRG_Vampire extends KFProjectile; /** Storing all relative info about Blood Ball charged (in order to help in replication) */ struct BloodBallChargeInfo { var float ChargePercentage; var float DamageByChargePercentage; }; /** Dampen amount for every bounce */ var float DampenFactor; /** Dampen amount for parallel angle to velocity */ var float DampenFactorParallel; /** Vector to offset the ground FX particle system by when landing */ var vector LandedFXOffset; /** Armed mine collision settings */ /** Decal settings */ var MaterialInterface ImpactDecalMaterial; var float ImpactDecalWidth; var float ImpactDecalHeight; var float ImpactDecalThickness; var float MaxExplodeTriggerHeightPerPercentage; var float MinExplodeTriggerHeightPerPercentage; var float MaxDamageRadiusPerPercentage; var float MinDamageRadiusPerPercentage; var float MaxCollisionRadius; var float MinCollisionRadius; var float MaxCollisionHeight; var float MinCollisionHeight; var float MaxDamagePerPercentage; var float MinDamagePerPercentage; var repnotify BloodBallChargeInfo BloodBallCharge; var float fCachedCylinderWidth, fCachedCylinderHeight; //EXPERIMENTAL FEATURES var bool bCantBeTouchedByInstigator; var bool bManuallyDetonated; var bool bCantDetonateOnFullHP; replication { if( bNetDirty && Role == Role_Authority) BloodBallCharge; } simulated event ReplicatedEvent( name VarName ) { super.ReplicatedEvent( VarName ); if( VarName == nameOf(BloodBallCharge)) { ScalingExplosionTemplateByBloodBallCharge(); ScalingProjEffectsByBloodBallCharge(); } } simulated function SetInheritedScale(float NewChargePercentage, float NewDamageByChargePercentage) { BloodBallCharge.DamageByChargePercentage=NewDamageByChargePercentage; BloodBallCharge.ChargePercentage = FMax(0.1, NewChargePercentage);//We want to see at least a bit of the projectile. ScalingExplosionTemplateByBloodBallCharge(); ScalingProjEffectsByBloodBallCharge(); bNetDirty=true; } simulated function ScalingExplosionTemplateByBloodBallCharge() { fCachedCylinderWidth = Lerp(MinCollisionRadius, MaxCollisionRadius, BloodBallCharge.ChargePercentage); fCachedCylinderHeight = Lerp(MinCollisionHeight, MaxCollisionHeight, BloodBallCharge.ChargePercentage); CylinderComponent(CollisionComponent).SetCylinderSize(fCachedCylinderWidth, fCachedCylinderHeight); ExplosionTemplate.DamageRadius = FMax(MinDamageRadiusPerPercentage, Lerp(MinDamageRadiusPerPercentage, MaxDamageRadiusPerPercentage, BloodBallCharge.DamageByChargePercentage)); ExplosionTemplate.Damage = FMax(MinDamagePerPercentage, Lerp(MinDamagePerPercentage, MaxDamagePerPercentage, BloodBallCharge.DamageByChargePercentage)); } simulated function ScalingProjEffectsByBloodBallCharge() { local vector ChargePercentageVector; ChargePercentageVector.X = BloodBallCharge.ChargePercentage; ChargePercentageVector.Y = BloodBallCharge.ChargePercentage; ChargePercentageVector.Z = BloodBallCharge.ChargePercentage; if(ProjEffects != None) { ProjEffects.SetVectorParameter( name("BlobCharge"), ChargePercentageVector); ProjEffects.SetFloatParameter( name("MineFxControlParam"), BloodBallCharge.ChargePercentage); } } simulated event PostBeginPlay() { super.PostBeginPlay(); BloodBallCharge.ChargePercentage=0; BloodBallCharge.DamageByChargePercentage=0; } simulated function SpawnFlightEffects() { super.SpawnFlightEffects(); } /** Validates a touch */ simulated protected function PrepareExplosionTemplate() { local Weapon OwnerWeapon; local Pawn OwnerPawn; super(KFProjectile).PrepareExplosionTemplate(); OwnerWeapon = Weapon(Owner); if (OwnerWeapon != none) { OwnerPawn = Pawn(OwnerWeapon.Owner); if (OwnerPawn != none) { ExplosionTemplate.DamageRadius *= KFPawn(OwnerPawn).GetPerk().GetAoERadiusModifier(); } } } simulated protected function PrepareExplosionActor(GameExplosionActor GEA) { KFExplosion_HRG_Vampire_BloodBall(GEA).ChargePercentage = BloodBallCharge.ChargePercentage; KFExplosion_HRG_Vampire_BloodBall(GEA).DamageByChargePercentage = BloodBallCharge.DamageByChargePercentage; super.PrepareExplosionActor(GEA); } /** Call ProcessBulletTouch */ simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal) { if (Other == Instigator || CheckRepeatingTouch(Other)) { return; } if (IgnoreTouchActor != Other) { ProcessBulletTouch(Other, HitLocation, HitNormal); } super.ProcessTouch(Other, HitLocation, HitNormal); } defaultproperties { Speed=2000 MaxSpeed=2000 TerminalVelocity=2000 TossZ=150 GravityScale=0.5 MomentumTransfer=50000.0 LifeSpan=300 PostExplosionLifetime=1 Physics=PHYS_Falling bBounce=true ProjFlightTemplate= ParticleSystem'WEP_HRG_Vampire_EMIT.FX_HRG_Vampire_BlobProjectile_01' ExplosionActorClass=class'KFExplosion_HRG_Vampire_BloodBall' bSuppressSounds=false bAmbientSoundZedTimeOnly=false bAutoStartAmbientSound=false bStopAmbientSoundOnExplode=true AmbientSoundPlayEvent=None AmbientSoundStopEvent=None Begin Object Class=AkComponent name=AmbientAkSoundComponent bStopWhenOwnerDestroyed=true bForceOcclusionUpdateInterval=true OcclusionUpdateInterval=0.25f End Object AmbientComponent=AmbientAkSoundComponent Components.Add(AmbientAkSoundComponent) //ImpactDecalMaterial=DecalMaterial'FX_Mat_Lib.FX_Puke_Mine_Splatter_DM' ImpactDecalWidth=178.f ImpactDecalHeight=178.f ImpactDecalThickness=28.f Begin Object Name=CollisionCylinder CollisionRadius=10.f CollisionHeight=10.f CollideActors=true //PhysMaterialOverride=PhysicalMaterial'WEP_Mine_Reconstructor_EMIT.BloatPukeMine_PM' End Object bCollideActors=true bProjTarget=true bCanBeDamaged=false bCollideComplex=true bNoEncroachCheck=true bPushedByEncroachers=false DampenFactor=0.125f DampenFactorParallel=0.175f LandedFXOffset=(X=0,Y=0,Z=2) // Since we're still using an extent cylinder, we need a line at 0 ExtraLineCollisionOffsets.Add(()) // Explosion Begin Object Class=KFGameExplosion Name=ExploTemplate0 Damage=200 DamageRadius=200 DamageFalloffExponent=0.5f DamageDelay=0.f MyDamageType=class'KFDT_Toxic_HRG_Vampire_BloodBall' //bIgnoreInstigator is set to true in PrepareExplosionTemplate //Impulse applied to Zeds MomentumTransferScale=45000 // Damage Effects KnockDownStrength=0 KnockDownRadius=0 FractureMeshRadius=0 FracturePartVel=0 ExplosionEffects=KFImpactEffectInfo'WEP_HRG_Vampire_Arch.HRG_Vampire_BlobFireImpacts' ExplosionSound=None bAllowPerMaterialFX=true //MomentumTransferScale=0 // Dynamic Light ExploLight=none // Camera Shake CamShake=CameraShake'WEP_Mine_Reconstructor_Arch.Camera_Shake' CamShakeInnerRadius=200 CamShakeOuterRadius=400 CamShakeFalloff=1.f bOrientCameraShakeTowardsEpicenter=true End Object ExplosionTemplate=ExploTemplate0 GlassShatterType=FMGS_ShatterAll MaxExplodeTriggerHeightPerPercentage=22 MinExplodeTriggerHeightPerPercentage=11 MaxDamageRadiusPerPercentage=280 //340 MinDamageRadiusPerPercentage=130 //160 MaxDamagePerPercentage=200 //150 MinDamagePerPercentage=20 //15 MaxCollisionRadius=20 MinCollisionRadius=10 MaxCollisionHeight=20 MinCollisionHeight=10 bBlockedByInstigator=true bNetTemporary=false bSyncToOriginalLocation=true bSyncToThirdPersonMuzzleLocation=true bUseClientSideHitDetection=true bUpdateSimulatedPosition=false TouchTimeThreshhold=0.05 //EXPERIMENTAL FEATURES FOR DESING bManuallyDetonated=false bCantBeTouchedByInstigator=true bCantDetonateOnFullHP=true AssociatedPerkClass=class'KFPerk_FieldMedic' }