upload
This commit is contained in:
24
KFGameContent/Classes/KFDT_Ballistic_HRG_MedicMissile.uc
Normal file
24
KFGameContent/Classes/KFDT_Ballistic_HRG_MedicMissile.uc
Normal file
@ -0,0 +1,24 @@
|
||||
//=============================================================================
|
||||
// KFDT_Ballistic_HRG_MedicMissile
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Ballistic_HRG_MedicMissile extends KFDT_Ballistic_Shell
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
KDamageImpulse=3000
|
||||
KDeathUpKick=1000
|
||||
KDeathVel=500
|
||||
|
||||
StumblePower=10
|
||||
GunHitPower=45
|
||||
|
||||
ModifierPerkList(0)=class'KFPerk_FieldMedic'
|
||||
|
||||
WeaponDef=class'KFWeapDef_HRG_MedicMissile'
|
||||
}
|
25
KFGameContent/Classes/KFDT_Ballistic_ZedMKIII_Rocket.uc
Normal file
25
KFGameContent/Classes/KFDT_Ballistic_ZedMKIII_Rocket.uc
Normal file
@ -0,0 +1,25 @@
|
||||
//=============================================================================
|
||||
// KFDT_Ballistic_ZedMKIII_Rocket
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
class KFDT_Ballistic_ZedMKIII_Rocket extends KFDT_Ballistic_Shell
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
KDamageImpulse=3000
|
||||
KDeathUpKick=1000
|
||||
KDeathVel=500
|
||||
|
||||
KnockdownPower=50
|
||||
StumblePower=100
|
||||
GunHitPower=70
|
||||
|
||||
ModifierPerkList(0)=class'KFPerk_Demolitionist'
|
||||
|
||||
WeaponDef=class'KFWeapDef_ZedMKIII'
|
||||
}
|
16
KFGameContent/Classes/KFDT_Bludgeon_HRG_BallisticBouncer.uc
Normal file
16
KFGameContent/Classes/KFDT_Bludgeon_HRG_BallisticBouncer.uc
Normal file
@ -0,0 +1,16 @@
|
||||
//=============================================================================
|
||||
// KFDT_Bludgeon_HRG_BallisticBouncer
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Bludgeon_HRG_BallisticBouncer extends KFDT_Bludgeon_RifleButt
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
//defaults
|
||||
WeaponDef=class'KFWeapDef_HRG_BallisticBouncer'
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
//=============================================================================
|
||||
// KFDT_Bludgeon_HRG_BallisticBouncer_Shot
|
||||
//=============================================================================
|
||||
// Balls hit hard
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Bludgeon_HRG_BallisticBouncer_Shot extends KFDT_Bludgeon
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
KDamageImpulse=900
|
||||
KDeathUpKick=-300
|
||||
KDeathVel=100
|
||||
|
||||
StumblePower=400
|
||||
GunHitPower=300
|
||||
MeleeHitPower=150
|
||||
KnockdownPower=100
|
||||
|
||||
WeaponDef=class'KFWeapDef_HRG_BallisticBouncer'
|
||||
}
|
16
KFGameContent/Classes/KFDT_Bludgeon_HRG_MedicMissile.uc
Normal file
16
KFGameContent/Classes/KFDT_Bludgeon_HRG_MedicMissile.uc
Normal file
@ -0,0 +1,16 @@
|
||||
//=============================================================================
|
||||
// KFDT_Bludgeon_HRG_MedicMissile
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Bludgeon_HRG_MedicMissile extends KFDT_Bludgeon_RifleButt
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
//defaults
|
||||
WeaponDef=class'KFWeapDef_HRG_MedicMissile'
|
||||
}
|
16
KFGameContent/Classes/KFDT_Bludgeon_HVStormCannon.uc
Normal file
16
KFGameContent/Classes/KFDT_Bludgeon_HVStormCannon.uc
Normal file
@ -0,0 +1,16 @@
|
||||
//=============================================================================
|
||||
// KFDT_Bludgeon_HVStormCannon
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Bludgeon_HVStormCannon extends KFDT_Bludgeon_RifleButt
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
//defaults
|
||||
WeaponDef=class'KFWeapDef_HVStormCannon'
|
||||
}
|
16
KFGameContent/Classes/KFDT_Bludgeon_ZedMKIII.uc
Normal file
16
KFGameContent/Classes/KFDT_Bludgeon_ZedMKIII.uc
Normal file
@ -0,0 +1,16 @@
|
||||
//=============================================================================
|
||||
// KFDT_Bludgeon_ZedMKIII
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Bludgeon_ZedMKIII extends KFDT_Bludgeon_RifleButt
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
//defaults
|
||||
WeaponDef=class'KFWeapDef_ZedMKIII'
|
||||
}
|
54
KFGameContent/Classes/KFDT_EMP_HVStormCannon.uc
Normal file
54
KFGameContent/Classes/KFDT_EMP_HVStormCannon.uc
Normal file
@ -0,0 +1,54 @@
|
||||
//=============================================================================
|
||||
// KFDT_EMP_HVStormCannon
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_EMP_HVStormCannon extends KFDT_EMP
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
var ParticleSystem ForceImpactEffect;
|
||||
var AkEvent ForceImpactSound;
|
||||
|
||||
static function PlayImpactHitEffects( KFPawn P, vector HitLocation, vector HitDirection, byte HitZoneIndex, optional Pawn HitInstigator )
|
||||
{
|
||||
local KFSkinTypeEffects SkinType;
|
||||
|
||||
if ( P.CharacterArch != None && default.EffectGroup < FXG_Max )
|
||||
{
|
||||
SkinType = P.GetHitZoneSkinTypeEffects( HitZoneIndex );
|
||||
|
||||
if (SkinType != none)
|
||||
{
|
||||
SkinType.PlayImpactParticleEffect(P, HitLocation, HitDirection, HitZoneIndex, default.EffectGroup, default.ForceImpactEffect);
|
||||
SkinType.PlayTakeHitSound(P, HitLocation, HitInstigator, default.EffectGroup, default.ForceImpactSound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
KDamageImpulse=2000
|
||||
KDeathUpKick=400
|
||||
KDeathVel=250
|
||||
|
||||
KnockdownPower=20
|
||||
StunPower=50
|
||||
StumblePower=200
|
||||
GunHitPower=150
|
||||
MeleeHitPower=100
|
||||
EMPPower=0 // Don't use the affliction here, we manage this on KFWeap_HVStormCannon to completely synchronize it with the logic of the weapon
|
||||
|
||||
GoreDamageGroup=DGT_EMP
|
||||
EffectGroup=FXG_Electricity
|
||||
|
||||
ForceImpactEffect=ParticleSystem'WEP_HVStormCannon_EMIT.FX_HVStormCannon_Impact'
|
||||
ForceImpactSound=AkEvent'WW_WEP_HVStormCannon.Play_WEP_HVStormCannon_Impact'
|
||||
|
||||
WeaponDef=class'KFWeapDef_HVStormCannon'
|
||||
|
||||
//Perk
|
||||
ModifierPerkList(0)=class'KFPerk_Sharpshooter'
|
||||
}
|
32
KFGameContent/Classes/KFDT_Explosive_HRG_MedicMissile.uc
Normal file
32
KFGameContent/Classes/KFDT_Explosive_HRG_MedicMissile.uc
Normal file
@ -0,0 +1,32 @@
|
||||
//=============================================================================
|
||||
// KFDT_Explosive_HRG_MedicMissile
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Explosive_HRG_MedicMissile extends KFDT_Explosive
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bShouldSpawnPersistentBlood=false
|
||||
|
||||
RadialDamageImpulse=2500
|
||||
GibImpulseScale=0.15
|
||||
KDeathUpKick=1500
|
||||
KDeathVel=500
|
||||
|
||||
KnockdownPower=50
|
||||
StumblePower=200
|
||||
|
||||
bExtraMomentumZ=false
|
||||
|
||||
bCanObliterate=false
|
||||
|
||||
//Perk
|
||||
ModifierPerkList(0)=class'KFPerk_FieldMedic'
|
||||
|
||||
WeaponDef=class'KFWeapDef_HRG_MedicMissile'
|
||||
}
|
30
KFGameContent/Classes/KFDT_Explosive_ZedMKIII.uc
Normal file
30
KFGameContent/Classes/KFDT_Explosive_ZedMKIII.uc
Normal file
@ -0,0 +1,30 @@
|
||||
//=============================================================================
|
||||
// KFDT_Explosive_ZedMKIII
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
class KFDT_Explosive_ZedMKIII extends KFDT_Explosive
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bShouldSpawnPersistentBlood=true
|
||||
|
||||
// physics impact
|
||||
RadialDamageImpulse=10000
|
||||
KDeathUpKick=2000
|
||||
KDeathVel=500
|
||||
|
||||
KnockdownPower=150
|
||||
StumblePower=350
|
||||
|
||||
//Perk
|
||||
ModifierPerkList(0)=class'KFPerk_Demolitionist'
|
||||
|
||||
ObliterationHealthThreshold=-500
|
||||
ObliterationDamageThreshold=500
|
||||
WeaponDef=class'KFWeapDef_ZedMKIII'
|
||||
}
|
69
KFGameContent/Classes/KFDT_Microwave_ZedMKIII.uc
Normal file
69
KFGameContent/Classes/KFDT_Microwave_ZedMKIII.uc
Normal file
@ -0,0 +1,69 @@
|
||||
//=============================================================================
|
||||
// KFDT_Microwave_ZedMKIII
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Microwave_ZedMKIII extends KFDT_Microwave
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
var ParticleSystem ForceImpactEffect;
|
||||
var AkEvent ForceImpactSound;
|
||||
|
||||
/** Allows the damage type to customize exactly which hit zones it can dismember */
|
||||
static simulated function bool CanDismemberHitZone( name InHitZoneName )
|
||||
{
|
||||
if( super.CanDismemberHitZone( InHitZoneName ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
switch ( InHitZoneName )
|
||||
{
|
||||
case 'lupperarm':
|
||||
case 'rupperarm':
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static function PlayImpactHitEffects( KFPawn P, vector HitLocation, vector HitDirection, byte HitZoneIndex, optional Pawn HitInstigator )
|
||||
{
|
||||
local KFSkinTypeEffects SkinType;
|
||||
|
||||
if ( P.CharacterArch != None && default.EffectGroup < FXG_Max )
|
||||
{
|
||||
SkinType = P.GetHitZoneSkinTypeEffects( HitZoneIndex );
|
||||
|
||||
if (SkinType != none)
|
||||
{
|
||||
SkinType.PlayImpactParticleEffect(P, HitLocation, HitDirection, HitZoneIndex, default.EffectGroup, default.ForceImpactEffect);
|
||||
SkinType.PlayTakeHitSound(P, HitLocation, HitInstigator, default.EffectGroup, default.ForceImpactSound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
KDamageImpulse=550
|
||||
GibImpulseScale=0.85
|
||||
KDeathUpKick=-200
|
||||
KDeathVel=200
|
||||
|
||||
StumblePower=18
|
||||
StunPower=15
|
||||
GunHitPower=15
|
||||
|
||||
WeaponDef=class'KFWeapDef_ZedMKIII'
|
||||
|
||||
//Perk
|
||||
ModifierPerkList(0)=class'KFPerk_Demolitionist'
|
||||
|
||||
EffectGroup=FXG_MicrowaveProj
|
||||
|
||||
ForceImpactEffect=ParticleSystem'WEP_ZEDMKIII_EMIT.FX_ZEDMKIII_Bullet_Impact'
|
||||
ForceImpactSound=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Shoot_Impact'
|
||||
}
|
283
KFGameContent/Classes/KFExplosion_HRG_BallisticBouncer.uc
Normal file
283
KFGameContent/Classes/KFExplosion_HRG_BallisticBouncer.uc
Normal file
@ -0,0 +1,283 @@
|
||||
//=============================================================================
|
||||
// KFExplosion_HRG_BallisticBouncer
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFExplosion_HRG_BallisticBouncer 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 )
|
||||
{
|
||||
return ExplodePawns(bCauseDamage);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
fMinAmmoutHealing=5; //4;
|
||||
fMaxAmmoutHealing=50; //40
|
||||
|
||||
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;
|
||||
}
|
73
KFGameContent/Classes/KFExplosion_HRG_MedicMissile.uc
Normal file
73
KFGameContent/Classes/KFExplosion_HRG_MedicMissile.uc
Normal file
@ -0,0 +1,73 @@
|
||||
//=============================================================================
|
||||
// KFExplosion_HRG_MedicMissile
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFExplosion_HRG_MedicMissile extends KFExplosionActorLingering;
|
||||
|
||||
var private int HealingValue;
|
||||
|
||||
// Disable Knockdown for friendlies
|
||||
protected function bool KnockdownPawn(BaseAiPawn Victim, float DistFromExplosion)
|
||||
{
|
||||
if (Victim.GetTeamNum() != Instigator.GetTeamNum())
|
||||
{
|
||||
return Super.KnockdownPawn(Victim, DistFromExplosion);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disable Stumble for friendlies
|
||||
protected function bool StumblePawn(BaseAiPawn Victim, float DistFromExplosion)
|
||||
{
|
||||
if (Victim.GetTeamNum() != Instigator.GetTeamNum())
|
||||
{
|
||||
return Super.StumblePawn(Victim, DistFromExplosion);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected simulated function AffectsPawn(Pawn Victim, float DamageScale)
|
||||
{
|
||||
local KFPawn KFP;
|
||||
|
||||
if( bWasFadedOut|| bDeleteMe || bPendingDelete )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
KFP = KFPawn(Victim);
|
||||
|
||||
if (KFP == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (KFP.GetTeamNum() == Instigator.GetTeamNum())
|
||||
{
|
||||
KFP.HealDamage(HealingValue, Instigator.Controller, class'KFDT_Healing');
|
||||
}
|
||||
else
|
||||
{
|
||||
super.AffectsPawn(VIctim, DamageScale);
|
||||
|
||||
KFP.ApplyDamageOverTime(class'KFDT_Toxic_HRG_MedicMissile'.default.PoisonPower, Instigator.Controller, class'KFDT_Toxic_HRG_MedicMissile');
|
||||
}
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
Interval=0f
|
||||
MaxTime=0f
|
||||
|
||||
bOnlyDamagePawns=true
|
||||
bDoFullDamage=false
|
||||
|
||||
bExplodeMoreThanOnce=false
|
||||
|
||||
HealingValue=50
|
||||
}
|
@ -386,6 +386,8 @@ function UpdateGameSettings()
|
||||
local int NumHumanPlayers, i;
|
||||
local KFGameEngine KFEngine;
|
||||
|
||||
super.UpdateGameSettings();
|
||||
|
||||
if (WorldInfo.NetMode == NM_DedicatedServer || WorldInfo.NetMode == NM_ListenServer)
|
||||
{
|
||||
//`REMOVEMESOON_ServerTakeoverLog("KFGameInfo_Survival.UpdateGameSettings 1 - GameInterface: "$GameInterface);
|
||||
|
@ -550,14 +550,16 @@ function byte PickTeam(byte Current, Controller C, const out UniqueNetId PlayerI
|
||||
/** Return whether a team change is allowed. */
|
||||
function bool ChangeTeam(Controller Other, int N, bool bNewTeam)
|
||||
{
|
||||
if( Other.PlayerReplicationInfo == none
|
||||
|| Other.PlayerReplicationInfo.bBot
|
||||
|| (!Other.PlayerReplicationInfo.bOnlySpectator
|
||||
&& ArrayCount(Teams) > N
|
||||
&& Other.PlayerReplicationInfo.Team != Teams[N]) )
|
||||
if (ArrayCount(Teams) > N)
|
||||
{
|
||||
SetTeam( Other, Teams[N] );
|
||||
return true;
|
||||
if( Other.PlayerReplicationInfo == none
|
||||
|| Other.PlayerReplicationInfo.bBot
|
||||
|| ( !Other.PlayerReplicationInfo.bOnlySpectator
|
||||
&& Other.PlayerReplicationInfo.Team != Teams[N] ) )
|
||||
{
|
||||
SetTeam( Other, Teams[N] );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -445,6 +445,7 @@ event PostLogin( PlayerController NewPlayer )
|
||||
{
|
||||
local KFPlayerController_WeeklySurvival KFPC_WS;
|
||||
local KFPawn_Customization KFCustomizePawn;
|
||||
|
||||
super.PostLogin(NewPlayer);
|
||||
|
||||
KFPC_WS = KFPlayerController_WeeklySurvival(NewPlayer);
|
||||
@ -544,6 +545,12 @@ function WaveEnded(EWaveEndCondition WinCondition)
|
||||
// This function is called multiple times in a row. Only apply it once.
|
||||
bWasFirstTime = bWaveStarted;
|
||||
|
||||
// Choose new perk before the end of wave message triggers in supper.
|
||||
if (MyKFGRI.IsRandomPerkMode() && WinCondition == WEC_WaveWon)
|
||||
{
|
||||
ChooseRandomPerks();
|
||||
}
|
||||
|
||||
super.WaveEnded(WinCondition);
|
||||
|
||||
if (OutbreakEvent.ActiveEvent.bPermanentZedTime && ZedTimeRemaining > ZedTimeBlendOutTime)
|
||||
@ -1315,6 +1322,10 @@ function WaveStarted()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Weekly 17: VIP MODE
|
||||
*/
|
||||
|
||||
function OnVIPDiesEndMatch()
|
||||
{
|
||||
local KFPlayerController KFPC;
|
||||
@ -1500,6 +1511,182 @@ function OnOutbreakWaveWon()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Weekly 18: Random Perks
|
||||
*/
|
||||
|
||||
simulated function NotifyPlayerStatsInitialized(KFPlayerController_WeeklySurvival KFPC)
|
||||
{
|
||||
if (KFPC != none && MyKFGRI.IsRandomPerkMode())
|
||||
{
|
||||
ChooseInitialRandomPerk(KFPC);
|
||||
}
|
||||
}
|
||||
|
||||
function ChooseInitialRandomPerk(KFPlayerController_WeeklySurvival KFPC_WS)
|
||||
{
|
||||
local KFPlayerController_WeeklySurvival OtherKFPC;
|
||||
local array<class<KFPerk> > AvailablePerks;
|
||||
local int i;
|
||||
local byte NewPerkIndex;
|
||||
local bool bPerkFound;
|
||||
|
||||
`Log("CHOOSING INITIAL PERKS");
|
||||
|
||||
for (i = 0; i < KFPC_WS.PerkList.Length; ++i)
|
||||
{
|
||||
bPerkFound = false;
|
||||
|
||||
foreach WorldInfo.AllControllers(class'KFPlayerController_WeeklySurvival', OtherKFPC)
|
||||
{
|
||||
if (OtherKFPC == KFPC_WS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (KFPC_WS.Perklist[i].PerkClass == OtherKFPC.CurrentPerk.Class)
|
||||
{
|
||||
bPerkFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bPerkFound)
|
||||
{
|
||||
AvailablePerks.AddItem(KFPC_WS.PerkList[i].PerkClass);
|
||||
}
|
||||
}
|
||||
|
||||
if (AvailablePerks.Length == 0)
|
||||
{
|
||||
for (i = 0; i < KFPC_WS.Perklist.Length; ++i)
|
||||
{
|
||||
AvailablePerks.AddItem(KFPC_WS.Perklist[i].PerkClass);
|
||||
}
|
||||
KFPC_WS.LockedPerks.Length = 0;
|
||||
}
|
||||
|
||||
NewPerkIndex = Rand(AvailablePerks.Length);
|
||||
|
||||
KFPC_WS.LockedPerks.AddItem(AvailablePerks[NewPerkIndex]);
|
||||
KFPC_WS.ForceNewPerk(AvailablePerks[NewPerkIndex]);
|
||||
}
|
||||
|
||||
function ChooseRandomPerks()
|
||||
{
|
||||
local KFPlayerController_WeeklySurvival KFPC;
|
||||
local array<class<KFPerk> > AvailablePerks;
|
||||
local array<class<KFPerk> > PickedPerks;
|
||||
local int i, j;
|
||||
local byte NewPerkIndex;
|
||||
local bool bPerkFound;
|
||||
|
||||
foreach WorldInfo.AllControllers(class'KFPlayerController_WeeklySurvival', KFPC)
|
||||
{
|
||||
AvailablePerks.Length = 0;
|
||||
|
||||
for (i = 0; i < KFPC.Perklist.Length; ++i)
|
||||
{
|
||||
bPerkFound = false;
|
||||
for (j = 0; j < PickedPerks.Length; ++j)
|
||||
{
|
||||
if (KFPC.Perklist[i].PerkClass == PickedPerks[j])
|
||||
{
|
||||
bPerkFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bPerkFound)
|
||||
{
|
||||
for (j = 0; j < KFPC.LockedPerks.Length; ++j)
|
||||
{
|
||||
if (KFPC.Perklist[i].PerkClass == KFPC.LockedPerks[j])
|
||||
{
|
||||
bPerkFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bPerkFound)
|
||||
{
|
||||
AvailablePerks.AddItem(KFPC.Perklist[i].PerkClass);
|
||||
}
|
||||
}
|
||||
|
||||
if (AvailablePerks.Length == 0)
|
||||
{
|
||||
for (i = 0; i < KFPC.Perklist.Length; ++i)
|
||||
{
|
||||
bPerkFound = false;
|
||||
for (j = 0; j < PickedPerks.Length; ++j)
|
||||
{
|
||||
if (KFPC.Perklist[i].PerkClass == PickedPerks[j])
|
||||
{
|
||||
bPerkFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bPerkFound && KFPC.Perklist[i].PerkClass != KFPC.CurrentPerk.Class)
|
||||
{
|
||||
AvailablePerks.AddItem(KFPC.Perklist[i].PerkClass);
|
||||
}
|
||||
}
|
||||
|
||||
if (AvailablePerks.Length == 0)
|
||||
{
|
||||
for (i = 0; i < KFPC.Perklist.Length; ++i)
|
||||
{
|
||||
AvailablePerks.AddItem(KFPC.Perklist[i].PerkClass);
|
||||
PickedPerks.Length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
KFPC.LockedPerks.Length = 0;
|
||||
}
|
||||
|
||||
NewPerkIndex = Rand(AvailablePerks.Length);
|
||||
PickedPerks.AddItem(AvailablePerks[NewPerkIndex]);
|
||||
KFPC.LockedPerks.AddItem(AvailablePerks[NewPerkIndex]);
|
||||
|
||||
KFPC.ForceNewPerk(AvailablePerks[NewPerkIndex]);
|
||||
|
||||
KFPC.PlayRandomPerkChosenSound();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Overide BroadcastLocalizedMessage for the RandomPerk weekly (18)
|
||||
// Perk is replicated while the message is sent through a RPC, so the message arrives before
|
||||
// the perk is updated on clients.
|
||||
// Override the BroadcastLocalizedMessage function to RPC each player the message with their own
|
||||
// new perk class as the optional object so the client knows the information before it gets the perk updated.
|
||||
//
|
||||
event BroadcastLocalizedMessage( class<LocalMessage> InMessageClass, optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject )
|
||||
{
|
||||
if (!MyKFGRI.IsRandomPerkMode() || Switch != GMT_WaveEnd)
|
||||
{
|
||||
Super.BroadcastLocalizedMessage(InMessageClass, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
BroadcastCustomWaveEndMessage(self, InMessageClass, Switch);
|
||||
}
|
||||
}
|
||||
|
||||
function BroadcastCustomWaveEndMessage( actor Sender, class<LocalMessage> InMessageClass, optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject )
|
||||
{
|
||||
local KFPlayerController KFPC;
|
||||
|
||||
foreach WorldInfo.AllControllers(class'KFPlayerController', KFPC)
|
||||
{
|
||||
KFPC.ReceiveLocalizedMessage( InMessageClass, Switch, RelatedPRI_1, RelatedPRI_2, KFPC.GetPerk().Class);
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
//Overrides
|
||||
|
@ -1220,6 +1220,21 @@ defaultproperties
|
||||
, class'KFGameContent.KFPawn_ZedHans'),
|
||||
)}
|
||||
|
||||
// Random Perks
|
||||
SetEvents[18]={(
|
||||
EventDifficulty=2,
|
||||
GameLength=GL_Normal,
|
||||
DoshOnKillGlobalModifier=1.3,
|
||||
SpawnReplacementList={(
|
||||
(SpawnEntry=AT_Clot,NewClass=(class'KFGameContent.KFPawn_ZedCrawler'),PercentChance=0.3),
|
||||
(SpawnEntry=AT_AlphaClot,NewClass=(class'KFGameContent.KFPawn_ZedCrawler'),PercentChance=0.3),
|
||||
(SpawnEntry=AT_SlasherClot,NewClass=(class'KFGameContent.KFPawn_ZedStalker'),PercentChance=0.3),
|
||||
(SpawnEntry=AT_Bloat,NewClass=(class'KFGameContent.KFPawn_ZedSiren'),PercentChance=0.3),
|
||||
(SpawnEntry=AT_Scrake,NewClass=(class'KFGameContent.KFPawn_ZedFleshpound'),PercentChance=0.3)
|
||||
|
||||
)}
|
||||
)}
|
||||
|
||||
//Test events from here down. These don't end up in the regular rotation.
|
||||
// The override ID starts from one higher than the last SetEvents entry above.
|
||||
// Ex: Big head = 7, Horde = 8
|
||||
|
22
KFGameContent/Classes/KFProj_Bullet_HVStormCannon.uc
Normal file
22
KFGameContent/Classes/KFProj_Bullet_HVStormCannon.uc
Normal file
@ -0,0 +1,22 @@
|
||||
//=============================================================================
|
||||
// KFProj_Bullet_HVStormCannon
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFProj_Bullet_HVStormCannon extends KFProj_Bullet
|
||||
hidedropdown;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
MaxSpeed=22500.0
|
||||
Speed=22500.0
|
||||
|
||||
DamageRadius=0
|
||||
|
||||
ProjFlightTemplate = ParticleSystem'WEP_HVStormCannon_EMIT.FX_HVStormCannon_Projectile'
|
||||
ImpactEffects = KFImpactEffectInfo'WEP_HVStormCannon_ARCH.Wep_HVStormCannon_Impact'
|
||||
}
|
||||
|
22
KFGameContent/Classes/KFProj_Bullet_ZedMKIII.uc
Normal file
22
KFGameContent/Classes/KFProj_Bullet_ZedMKIII.uc
Normal file
@ -0,0 +1,22 @@
|
||||
//=============================================================================
|
||||
// KFProj_Bullet_ZedMKIII
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFProj_Bullet_ZedMKIII extends KFProj_Bullet
|
||||
hidedropdown;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
MaxSpeed=22500.0
|
||||
Speed=22500.0
|
||||
|
||||
DamageRadius=0
|
||||
|
||||
ProjFlightTemplate = ParticleSystem'WEP_ZEDMKIII_EMIT.FX_ZEDMKIII_Bullet_Projectile'
|
||||
ImpactEffects = KFImpactEffectInfo'WEP_ZEDMKIII_ARCH.FX_ZEDMKIII_Bullet_Impact'
|
||||
}
|
||||
|
@ -69,7 +69,9 @@ simulated protected function PrepareExplosionTemplate()
|
||||
{
|
||||
class'KFPerk_Demolitionist'.static.PrepareExplosive( Instigator, self );
|
||||
|
||||
super.PrepareExplosionTemplate();
|
||||
GetRadialDamageValues(ExplosionTemplate.Damage, ExplosionTemplate.DamageRadius, ExplosionTemplate.DamageFalloffExponent);
|
||||
|
||||
// super.PrepareExplosionTemplate();
|
||||
}
|
||||
|
||||
simulated protected function SetExplosionActorClass()
|
||||
|
@ -133,7 +133,9 @@ simulated protected function PrepareExplosionTemplate()
|
||||
{
|
||||
class'KFPerk_Berserker'.static.PrepareExplosive( Instigator, self );
|
||||
|
||||
super.PrepareExplosionTemplate();
|
||||
GetRadialDamageValues(ExplosionTemplate.Damage, ExplosionTemplate.DamageRadius, ExplosionTemplate.DamageFalloffExponent);
|
||||
|
||||
//super.PrepareExplosionTemplate();
|
||||
}
|
||||
|
||||
|
||||
|
556
KFGameContent/Classes/KFProj_HRG_BallisticBouncer.uc
Normal file
556
KFGameContent/Classes/KFProj_HRG_BallisticBouncer.uc
Normal file
@ -0,0 +1,556 @@
|
||||
//=============================================================================
|
||||
// KFProj_HRG_BallisticBouncer
|
||||
//=============================================================================
|
||||
// Projectile class for HRG Ballistic Bouncer
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
class KFProj_HRG_BallisticBouncer extends KFProjectile;
|
||||
|
||||
/** Dampen amount for every bounce */
|
||||
var float DampenFactor;
|
||||
|
||||
/** Dampen amount for parallel angle to velocity */
|
||||
var float DampenFactorParallel;
|
||||
|
||||
/** Sound mine makes when it hits something and bounces off */
|
||||
var AkEvent BounceAkEvent;
|
||||
|
||||
/** Sound mine makes when it hits something and comes to rest */
|
||||
var AkEvent ImpactAkEvent;
|
||||
|
||||
/** Sound mine makes when it hits something and bounces off */
|
||||
var AkEvent BounceAkEventHeavy;
|
||||
|
||||
/** Sound mine makes when it hits something and comes to rest */
|
||||
var AkEvent ImpactAkEventHeavy;
|
||||
|
||||
/** Particle System spawned when it hits something */
|
||||
var ParticleSystem HitFXTemplate;
|
||||
var transient ParticleSystemComponent HitPSC;
|
||||
|
||||
/** Particle System for the fade out burst **/
|
||||
var ParticleSystem BurstFXTemplate;
|
||||
var transient ParticleSystemComponent BurstPSC;
|
||||
|
||||
/** Sound for the fade out burst **/
|
||||
var AkEvent BurstAkEvent;
|
||||
|
||||
/** Decal settings */
|
||||
var MaterialInterface ImpactDecalMaterial;
|
||||
var float ImpactDecalWidth;
|
||||
var float ImpactDecalHeight;
|
||||
var float ImpactDecalThickness;
|
||||
|
||||
var int MaxBounces;
|
||||
var int NumBounces;
|
||||
|
||||
var float MaxInitialSpeedByCharge;
|
||||
var float MinInitialSpeedByCharge;
|
||||
|
||||
var float MaxCollisionRadius;
|
||||
var float MinCollisionRadius;
|
||||
var float MaxCollisionHeight;
|
||||
var float MinCollisionHeight;
|
||||
|
||||
var float MaxScalePerPercentage;
|
||||
var float MinScalePerPercentage;
|
||||
|
||||
var int MaxBouncesPerPercentage;
|
||||
var int MinBouncesPerPercentage;
|
||||
|
||||
var float MaxLifeSpanPerPercentage;
|
||||
var float MinLifeSpanPerPercentage;
|
||||
|
||||
var float InheritedScale;
|
||||
|
||||
var repnotify float fChargePercentage;
|
||||
|
||||
var float fCachedCylinderWidth, fCachedCylinderHeight;
|
||||
|
||||
var float ArmDistSquared;
|
||||
|
||||
var bool bFadingOut;
|
||||
var float FadeOutTime;
|
||||
|
||||
var transient byte RequiredImpactsForSeasonal;
|
||||
var transient array<Pawn> ImpactVictims;
|
||||
|
||||
replication
|
||||
{
|
||||
if( bNetDirty )
|
||||
InheritedScale, fChargePercentage, MaxBounces;
|
||||
}
|
||||
|
||||
simulated event ReplicatedEvent( name VarName )
|
||||
{
|
||||
if( VarName == nameOf(fChargePercentage))
|
||||
{
|
||||
fCachedCylinderWidth = Lerp(MinCollisionRadius, MaxCollisionRadius, fChargePercentage);
|
||||
fCachedCylinderHeight = Lerp(MinCollisionHeight, MaxCollisionHeight, fChargePercentage);
|
||||
// CylinderComponent(CollisionComponent).SetCylinderSize(fCachedCylinderWidth, fCachedCylinderHeight);
|
||||
SetCollisionSize(fCachedCylinderWidth, fCachedCylinderHeight);
|
||||
ApplyVFXParams(fChargePercentage);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.ReplicatedEvent( VarName );
|
||||
}
|
||||
}
|
||||
|
||||
simulated event PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
RequiredImpactsForSeasonal = class'KFSeasonalEventStats_Xmas2022'.static.GetMaxBallisticBouncerImpacts();
|
||||
}
|
||||
|
||||
simulated function SetInheritedScale(float Scale, float ChargePercentage)
|
||||
{
|
||||
local float NewSpeed;
|
||||
|
||||
InheritedScale = Scale;
|
||||
|
||||
fChargePercentage = ChargePercentage;
|
||||
fChargePercentage = FMax(0.1, fChargePercentage);
|
||||
|
||||
if (WorldInfo.NetMode == NM_DedicatedServer)
|
||||
{
|
||||
SetCollisionSize(Lerp(MinCollisionRadius, MaxCollisionRadius, fChargePercentage), Lerp(MinCollisionHeight, MaxCollisionHeight, ChargePercentage));
|
||||
}
|
||||
|
||||
NewSpeed = Lerp(MinInitialSpeedByCharge, MaxInitialSpeedByCharge, fChargePercentage);
|
||||
Velocity = Normal(Velocity) * NewSpeed;
|
||||
Speed = NewSpeed;
|
||||
|
||||
MaxBounces = Lerp(MinBouncesPerPercentage, MaxBouncesPerPercentage, fChargePercentage);
|
||||
|
||||
LifeSpan = Lerp(MinLifeSpanPerPercentage, MaxLifeSpanPerPercentage, fChargePercentage);
|
||||
|
||||
if (ProjEffects != none)
|
||||
{
|
||||
ProjEffects.SetScale(Lerp(MinScalePerPercentage, MaxScalePerPercentage, fChargePercentage));
|
||||
}
|
||||
|
||||
if (WorldInfo.NetMode != NM_DedicatedServer)
|
||||
{
|
||||
ApplyVFXParams(fChargePercentage);
|
||||
}
|
||||
|
||||
bNetDirty=true;
|
||||
}
|
||||
|
||||
function RestoreCylinder()
|
||||
{
|
||||
CylinderComponent(CollisionComponent).SetCylinderSize(fCachedCylinderWidth, fCachedCylinderHeight);
|
||||
}
|
||||
|
||||
simulated function BounceNoCheckRepeatingTouch(vector HitNormal, Actor BouncedOff)
|
||||
{
|
||||
local vector VNorm;
|
||||
|
||||
// Reflect off BouncedOff w/damping
|
||||
VNorm = (Velocity dot HitNormal) * HitNormal;
|
||||
|
||||
if (NumBounces < MaxBounces)
|
||||
{
|
||||
Velocity = -VNorm + (Velocity - VNorm);
|
||||
}
|
||||
else
|
||||
{
|
||||
Velocity = -VNorm * DampenFactor + (Velocity - VNorm) * DampenFactorParallel;
|
||||
}
|
||||
|
||||
Speed = VSize(Velocity);
|
||||
|
||||
// Play a sound
|
||||
PlayImpactSound();
|
||||
|
||||
// Spawn impact particle system, server needs to send the message (it's the only one storing MaxBounces)
|
||||
if (WorldInfo.NetMode != NM_DedicatedServer)
|
||||
{
|
||||
if (NumBounces < MaxBounces)
|
||||
{
|
||||
PlayImpactVFX(HitNormal);
|
||||
}
|
||||
|
||||
`ImpactEffectManager.PlayImpactEffects(Location, Instigator, VNorm, ImpactEffects);
|
||||
}
|
||||
|
||||
++NumBounces;
|
||||
}
|
||||
|
||||
/** Adjusts movement/physics of projectile.
|
||||
* Returns true if projectile actually bounced / was allowed to bounce */
|
||||
simulated function bool Bounce( vector HitNormal, Actor BouncedOff )
|
||||
{
|
||||
// Avoid crazy bouncing
|
||||
if (CheckRepeatingTouch(BouncedOff))
|
||||
{
|
||||
CylinderComponent(CollisionComponent).SetCylinderSize(1,1);
|
||||
SetTimer(0.06f, false, nameof(RestoreCylinder));
|
||||
return false;
|
||||
}
|
||||
|
||||
BounceNoCheckRepeatingTouch(HitNormal, BouncedOff);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Plays a sound on impact */
|
||||
simulated function PlayImpactSound( optional bool bIsAtRest )
|
||||
{
|
||||
if( WorldInfo.NetMode != NM_DedicatedServer )
|
||||
{
|
||||
if( bIsAtRest )
|
||||
{
|
||||
if(fChargePercentage < 0.75f)
|
||||
PostAkEvent( ImpactAkEvent, true, true, false );
|
||||
else
|
||||
PostAkEvent( ImpactAkEventHeavy, true, true, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fChargePercentage < 0.75f)
|
||||
PostAkEvent( BounceAkEvent, true, true, false );
|
||||
else
|
||||
PostAkEvent( BounceAkEventHeavy, true, true, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function PlayImpactVFX(vector HitNormal)
|
||||
{
|
||||
HitPSC = WorldInfo.MyEmitterPool.SpawnEmitter(HitFXTemplate, ProjEffects.GetPosition(), rotator(HitNormal));
|
||||
HitPSC.SetFloatParameter(name("Charge"), fChargePercentage);
|
||||
}
|
||||
|
||||
simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal)
|
||||
{
|
||||
local float TraveledDistance;
|
||||
|
||||
TraveledDistance = (`TimeSince(CreationTime) * Speed);
|
||||
TraveledDistance *= TraveledDistance;
|
||||
|
||||
// If we collided with a Siren shield, let the shield code handle touches
|
||||
if( Other.IsA('KFTrigger_SirenProjectileShield') )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Other != Instigator && Other.GetTeamNum() != GetTeamNum())
|
||||
{
|
||||
// check/ignore repeat touch events
|
||||
if (!CheckRepeatingTouch(Other))
|
||||
{
|
||||
ProcessBulletTouch(Other, HitLocation, HitNormal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function ProcessBulletTouch(Actor Other, Vector HitLocation, Vector HitNormal)
|
||||
{
|
||||
local Pawn Victim;
|
||||
local array<ImpactInfo> HitZoneImpactList;
|
||||
//local ImpactInfo ImpactInfoFallBack;
|
||||
local vector StartTrace, EndTrace, Direction; //, DirectionFallBack;
|
||||
local TraceHitInfo HitInfo;
|
||||
local KFWeapon KFW;
|
||||
|
||||
Victim = Pawn( Other );
|
||||
if ( Victim == none )
|
||||
{
|
||||
if ( bDamageDestructiblesOnTouch && Other.bCanBeDamaged )
|
||||
{
|
||||
HitInfo.HitComponent = LastTouchComponent;
|
||||
HitInfo.Item = INDEX_None; // force TraceComponent on fractured meshes
|
||||
Other.TakeDamage(Damage, InstigatorController, Location, MomentumTransfer * Normal(Velocity), MyDamageType, HitInfo, self);
|
||||
}
|
||||
|
||||
// Reduce the penetration power to zero if we hit something other than a pawn or foliage actor
|
||||
if( InteractiveFoliageActor(Other) == None )
|
||||
{
|
||||
PenetrationPower = 0;
|
||||
|
||||
BounceNoCheckRepeatingTouch(HitNormal, Other);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bSpawnShrapnel)
|
||||
{
|
||||
//spawn straight forward through the zed
|
||||
SpawnShrapnel(Other, HitLocation, HitNormal, rotator(Velocity), ShrapnelSpreadWidthZed, ShrapnelSpreadHeightZed);
|
||||
}
|
||||
|
||||
StartTrace = HitLocation;
|
||||
Direction = Normal(Velocity);
|
||||
EndTrace = StartTrace + Direction * (Victim.CylinderComponent.CollisionRadius * 6.0);
|
||||
|
||||
TraceProjHitZones(Victim, EndTrace, StartTrace, HitZoneImpactList);
|
||||
|
||||
//`Log("HitZoneImpactList: " $HitZoneImpactList.Length);
|
||||
|
||||
if ( HitZoneImpactList.length > 0 )
|
||||
{
|
||||
HitZoneImpactList[0].RayDir = Direction;
|
||||
|
||||
if( Owner != none )
|
||||
{
|
||||
KFW = KFWeapon( Owner );
|
||||
if( KFW != none )
|
||||
{
|
||||
KFW.HandleProjectileImpact(WeaponFireMode, HitZoneImpactList[0], PenetrationPower);
|
||||
}
|
||||
}
|
||||
|
||||
IncrementNumImpacts(Victim);
|
||||
|
||||
BounceNoCheckRepeatingTouch(HitNormal, Other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function IncrementNumImpacts(Pawn Victim)
|
||||
{
|
||||
local int i;
|
||||
local KFPlayerController KFPC;
|
||||
|
||||
if (WorldInfo.NetMode == NM_Client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
KFPC = KFPlayerController(InstigatorController);
|
||||
|
||||
if (KFPC == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ImpactVictims.Length; ++i)
|
||||
{
|
||||
if (Victim == ImpactVictims[i])
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ImpactVictims.AddItem(Victim);
|
||||
|
||||
UpdateImpactsSeasonalObjective(KFPC);
|
||||
}
|
||||
|
||||
function UpdateImpactsSeasonalObjective(KFPlayerController KFPC)
|
||||
{
|
||||
local byte ObjectiveIndex;
|
||||
|
||||
ObjectiveIndex = 3;
|
||||
|
||||
if (ImpactVictims.Length >= RequiredImpactsForSeasonal)
|
||||
{
|
||||
// Check parent controller.
|
||||
KFPC.ClientOnTryCompleteObjective(ObjectiveIndex, SEI_Winter);
|
||||
}
|
||||
}
|
||||
|
||||
simulated event HitWall( vector HitNormal, Actor Wall, PrimitiveComponent WallComp )
|
||||
{
|
||||
// Don't collide with other projectiles
|
||||
if( Wall.class == class )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Bounce( HitNormal, Wall );
|
||||
}
|
||||
|
||||
simulated function SpawnBurstFX()
|
||||
{
|
||||
local vector vec;
|
||||
|
||||
if( WorldInfo.NetMode == NM_DedicatedServer || WorldInfo.MyEmitterPool == none || ProjEffects == none )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BurstPSC = WorldInfo.MyEmitterPool.SpawnEmitter(BurstFXTemplate, ProjEffects.GetPosition(), rotator(vect(0,0,1)), self, , ,true);
|
||||
|
||||
vec.X = fChargePercentage;
|
||||
vec.Y = fChargePercentage;
|
||||
vec.Z = fChargePercentage;
|
||||
|
||||
BurstPSC.SetVectorParameter(name("BlobCharge"), vec);
|
||||
BurstPSC.SetFloatParameter(name("MineFxControlParam"), fChargePercentage);
|
||||
|
||||
PostAkEvent(BurstAkEvent, true, true, false);
|
||||
}
|
||||
|
||||
simulated function Tick(float Delta)
|
||||
{
|
||||
if (NumBounces < MaxBounces || bFadingOut)
|
||||
return;
|
||||
|
||||
if (Speed < 20.0f)
|
||||
{
|
||||
bFadingOut = true;
|
||||
StopSimulating();
|
||||
|
||||
SpawnBurstFX();
|
||||
|
||||
// Tell clients to tear off and fade out on their own
|
||||
if( WorldInfo.NetMode != NM_Client )
|
||||
{
|
||||
ClearTimer(nameof(Timer_Destroy));
|
||||
|
||||
SetTimer( 1.0f, false, nameOf(Timer_Destroy) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function Timer_Destroy()
|
||||
{
|
||||
if (BurstPSC != none)
|
||||
{
|
||||
BurstPSC.DeactivateSystem();
|
||||
}
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
simulated function ApplyVFXParams(float ChargePercent)
|
||||
{
|
||||
if (ProjEffects != none)
|
||||
{
|
||||
ProjEffects.SetFloatParameter(name("InflateBlob"), ChargePercent);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
ProcessBulletTouch(HitActor, HitLocation, HitNormal);
|
||||
}
|
||||
}
|
||||
|
||||
Super.SyncOriginalLocation();
|
||||
}
|
||||
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
TerminalVelocity=5000
|
||||
TossZ=150
|
||||
GravityScale=0.5
|
||||
MomentumTransfer=50000.0
|
||||
|
||||
LifeSpan=300
|
||||
PostExplosionLifetime=1
|
||||
Physics=PHYS_Falling
|
||||
bBounce=true
|
||||
|
||||
ProjFlightTemplate= ParticleSystem'WEP_HRG_BallisticBouncer_EMIT.FX_HRG_BallisticBouncer_Ball_Projectile'
|
||||
BurstFXTemplate= ParticleSystem'WEP_HRG_BallisticBouncer_EMIT.FX_HRG_BallisticBouncer_Ball_Explode'
|
||||
HitFXTemplate= ParticleSystem'WEP_HRG_BallisticBouncer_EMIT.FX_HRG_BallisticBouncer_Ball_Hit'
|
||||
|
||||
bSuppressSounds=false
|
||||
bAmbientSoundZedTimeOnly=false
|
||||
bAutoStartAmbientSound=false
|
||||
bStopAmbientSoundOnExplode=true
|
||||
|
||||
ImpactAkEvent=AkEvent'WW_WEP_HRG_BallisticBouncer.Play_WEP_HRG_BallisticBouncer_Ball_Impact'
|
||||
BounceAkEvent=AkEvent'WW_WEP_HRG_BallisticBouncer.Play_WEP_HRG_BallisticBouncer_Ball_Impact'
|
||||
ImpactAkEventHeavy=AkEvent'WW_WEP_HRG_BallisticBouncer.Play_WEP_HRG_BallisticBouncer_Ball_Impact_Heavy'
|
||||
BounceAkEventHeavy=AkEvent'WW_WEP_HRG_BallisticBouncer.Play_WEP_HRG_BallisticBouncer_Ball_Impact_Heavy'
|
||||
|
||||
BurstAkEvent=AkEvent'WW_WEP_HRG_BallisticBouncer.Play_WEP_HRG_BallisticBouncer_Ball_Explosion'
|
||||
|
||||
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=0.f
|
||||
CollisionHeight=0.f
|
||||
CollideActors=true
|
||||
BlockNonZeroExtent=false
|
||||
PhysMaterialOverride=PhysicalMaterial'WEP_HRG_BallisticBouncer_EMIT.BloatPukeMine_PM'
|
||||
End Object
|
||||
|
||||
bCollideComplex=TRUE // Ignore simple collision on StaticMeshes, and collide per poly
|
||||
bUseClientSideHitDetection=true
|
||||
bNoReplicationToInstigator=false
|
||||
bUpdateSimulatedPosition=true
|
||||
|
||||
bProjTarget=true
|
||||
bCanBeDamaged=false
|
||||
bNoEncroachCheck=true
|
||||
bPushedByEncroachers=false
|
||||
DampenFactor=0.175f
|
||||
DampenFactorParallel=0.175f
|
||||
|
||||
ExtraLineCollisionOffsets.Add((Y=-20))
|
||||
ExtraLineCollisionOffsets.Add((Y=20))
|
||||
ExtraLineCollisionOffsets.Add((Z=-20))
|
||||
ExtraLineCollisionOffsets.Add((Z=20))
|
||||
// Since we're still using an extent cylinder, we need a line at 0
|
||||
ExtraLineCollisionOffsets.Add(())
|
||||
GlassShatterType=FMGS_ShatterAll
|
||||
InheritedScale=1
|
||||
|
||||
MaxInitialSpeedByCharge=5000
|
||||
MinInitialSpeedByCharge=1500
|
||||
|
||||
MaxCollisionRadius=20
|
||||
MinCollisionRadius=10
|
||||
MaxCollisionHeight=20
|
||||
MinCollisionHeight=10
|
||||
|
||||
MaxScalePerPercentage=1.5f
|
||||
MinScalePerPercentage=0.5f
|
||||
|
||||
MaxBouncesPerPercentage=5
|
||||
MinBouncesPerPercentage=1
|
||||
|
||||
MaxLifespanPerPercentage=500
|
||||
MinLifeSpanPerPercentage=300
|
||||
|
||||
bBlockedByInstigator=true
|
||||
bNetTemporary=false
|
||||
|
||||
bSyncToOriginalLocation=true
|
||||
bSyncToThirdPersonMuzzleLocation=true
|
||||
|
||||
bReplicateLocationOnExplosion=true
|
||||
|
||||
TouchTimeThreshhold=0.05
|
||||
|
||||
MaxBounces=0
|
||||
NumBounces=0
|
||||
|
||||
ArmDistSquared=0
|
||||
|
||||
// Fade out properties
|
||||
FadeOutTime=5.0f
|
||||
|
||||
// ImpactEffects= KFImpactEffectInfo'WEP_DragonsBreath_ARCH.DragonsBreath_bullet_impact'
|
||||
}
|
128
KFGameContent/Classes/KFProj_Rocket_HRG_MedicMissile.uc
Normal file
128
KFGameContent/Classes/KFProj_Rocket_HRG_MedicMissile.uc
Normal file
@ -0,0 +1,128 @@
|
||||
//=============================================================================
|
||||
// KFProj_Rocket_HRG_MedicMissile
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFProj_Rocket_HRG_MedicMissile extends KFProj_BallisticExplosive
|
||||
hidedropdown;
|
||||
|
||||
simulated function bool AllowNuke()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function bool AllowDemolitionistConcussive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function bool AllowDemolitionistExplosionChangeRadius()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated protected function PrepareExplosionTemplate()
|
||||
{
|
||||
local Weapon OwnerWeapon;
|
||||
local Pawn OwnerPawn;
|
||||
local KFPerk_Survivalist Perk;
|
||||
|
||||
super(KFProjectile).PrepareExplosionTemplate();
|
||||
|
||||
OwnerWeapon = Weapon(Owner);
|
||||
if (OwnerWeapon != none)
|
||||
{
|
||||
OwnerPawn = Pawn(OwnerWeapon.Owner);
|
||||
if (OwnerPawn != none)
|
||||
{
|
||||
Perk = KFPerk_Survivalist(KFPawn(OwnerPawn).GetPerk());
|
||||
if (Perk != none)
|
||||
{
|
||||
ExplosionTemplate.DamageRadius *= KFPawn(OwnerPawn).GetPerk().GetAoERadiusModifier();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function AdjustCanDisintigrate()
|
||||
{
|
||||
// This weapon is not from Demolitionist, so always enable Siren disintegrate
|
||||
bCanDisintegrate = true;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Physics=PHYS_Projectile
|
||||
Speed=5000
|
||||
MaxSpeed=5000
|
||||
TossZ=0
|
||||
GravityScale=1.0
|
||||
MomentumTransfer=50000.0
|
||||
ArmDistSquared=150000 // 4 meters
|
||||
|
||||
bCollideWithTeammates=true
|
||||
|
||||
bWarnAIWhenFired=true
|
||||
|
||||
ProjFlightTemplate=ParticleSystem'WEP_HRG_MedicMissile_EMIT.FX_HRG_MedicMissile_Projectile'
|
||||
ProjFlightTemplateZedTime=ParticleSystem'WEP_HRG_MedicMissile_EMIT.FX_HRG_MedicMissile_Projectile_ZED_TIME'
|
||||
ProjDudTemplate=ParticleSystem'WEP_HRG_MedicMissile_EMIT.FX_HRG_MedicMissile_Projectile_Dud'
|
||||
GrenadeBounceEffectInfo=KFImpactEffectInfo'WEP_HRG_MedicMissile_ARCH.HRG_MedicMissile_Projectile_Impacts'
|
||||
|
||||
ProjDisintegrateTemplate=ParticleSystem'ZED_Siren_EMIT.FX_Siren_grenade_disable_01'
|
||||
bCanDisintegrate=true
|
||||
|
||||
AmbientSoundPlayEvent=AkEvent'WW_WEP_HRG_MedicMissile.Play_WEP_HRG_MedicMissile_Projectile_Loop'
|
||||
AmbientSoundStopEvent=AkEvent'WW_WEP_HRG_MedicMissile.Stop_WEP_HRG_MedicMissile_Projectile_Loop'
|
||||
|
||||
AltExploEffects=KFImpactEffectInfo'WEP_HRG_MedicMissile_ARCH.HRG_MedicMissile_Explosion_Concussive_Force'
|
||||
|
||||
ExplosionActorClass=class'KFExplosion_HRG_MedicMissile'
|
||||
|
||||
// Grenade explosion light
|
||||
Begin Object Class=PointLightComponent Name=ExplosionPointLight
|
||||
LightColor=(R=60,G=200,B=255,A=255)
|
||||
Brightness=2.f
|
||||
Radius=1500.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=400
|
||||
DamageRadius=300
|
||||
DamageFalloffExponent=2
|
||||
DamageDelay=0.f
|
||||
|
||||
// Damage Effects
|
||||
MyDamageType=class'KFDT_Explosive_HRG_MedicMissile'
|
||||
KnockDownStrength=0
|
||||
FractureMeshRadius=0.0
|
||||
FracturePartVel=0.0
|
||||
ExplosionEffects=KFImpactEffectInfo'WEP_HRG_MedicMissile_ARCH.HRG_MedicMissile_Explosion'
|
||||
ExplosionSound=AkEvent'WW_WEP_HRG_MedicMissile.Play_WEP_HRG_MedicMissile_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
|
||||
|
||||
bCanApplyDemolitionistPerks=false
|
||||
}
|
123
KFGameContent/Classes/KFProj_Rocket_ZedMKIII.uc
Normal file
123
KFGameContent/Classes/KFProj_Rocket_ZedMKIII.uc
Normal file
@ -0,0 +1,123 @@
|
||||
//=============================================================================
|
||||
// KFProj_Rocket_ZedMKIII
|
||||
//=============================================================================
|
||||
// KFProj_Rocket_ZedMKIII rocket
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
class KFProj_Rocket_ZedMKIII extends KFProj_BallisticExplosive
|
||||
hidedropdown;
|
||||
|
||||
/** Our intended target actor */
|
||||
var private KFPawn LockedTarget;
|
||||
|
||||
/** How much 'stickyness' when seeking toward our target. Determines how accurate rocket is */
|
||||
var const float SeekStrength;
|
||||
|
||||
replication
|
||||
{
|
||||
if( bNetInitial )
|
||||
LockedTarget;
|
||||
}
|
||||
|
||||
function SetLockedTarget( KFPawn NewTarget )
|
||||
{
|
||||
LockedTarget = NewTarget;
|
||||
}
|
||||
|
||||
simulated event Tick( float DeltaTime )
|
||||
{
|
||||
local vector TargetImpactPos, DirToTarget;
|
||||
|
||||
super.Tick( DeltaTime );
|
||||
|
||||
// Skip the first frame, then start seeking
|
||||
if( !bHasExploded
|
||||
&& LockedTarget != none
|
||||
&& Physics == PHYS_Projectile
|
||||
&& Velocity != vect(0,0,0)
|
||||
&& LockedTarget.IsAliveAndWell()
|
||||
&& `TimeSince(CreationTime) > 0.03f )
|
||||
{
|
||||
// Grab our desired relative impact location from the weapon class
|
||||
TargetImpactPos = class'KFWeap_ZedMKIII'.static.GetLockedTargetLoc( LockedTarget );
|
||||
|
||||
// Seek towards target
|
||||
Speed = VSize( Velocity );
|
||||
DirToTarget = Normal( TargetImpactPos - Location );
|
||||
Velocity = Normal( Velocity + (DirToTarget * (SeekStrength * DeltaTime)) ) * Speed;
|
||||
|
||||
// Aim rotation towards velocity every frame
|
||||
SetRotation( rotator(Velocity) );
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
Physics=PHYS_Projectile
|
||||
Speed=4000 //6000
|
||||
MaxSpeed=4000 //6000
|
||||
TossZ=0
|
||||
GravityScale=1.0
|
||||
MomentumTransfer=50000.0f
|
||||
ArmDistSquared=110000.0f //20000.0f // 110000.0f // 4 meters 150000.0
|
||||
|
||||
SeekStrength=928000.0f // 128000.0f
|
||||
|
||||
bWarnAIWhenFired=true
|
||||
|
||||
ProjFlightTemplate=ParticleSystem'WEP_ZEDMKIII_EMIT.FX_ZEDMKIII_Rocket'
|
||||
ProjFlightTemplateZedTime=ParticleSystem'WEP_ZEDMKIII_EMIT.FX_ZEDMKIII_Rocket_ZED_TIME'
|
||||
ProjDudTemplate=ParticleSystem'WEP_ZEDMKIII_EMIT.FX_ZEDMKIII_Rocket_Dud'
|
||||
GrenadeBounceEffectInfo=KFImpactEffectInfo'WEP_RPG7_ARCH.RPG7_Projectile_Impacts'
|
||||
ProjDisintegrateTemplate=ParticleSystem'ZED_Siren_EMIT.FX_Siren_grenade_disable_01'
|
||||
|
||||
AmbientSoundPlayEvent=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Rocket_LP'
|
||||
AmbientSoundStopEvent=AkEvent'WW_WEP_ZEDMKIII.Stop_WEP_ZEDMKIII_Rocket_LP'
|
||||
|
||||
AltExploEffects=KFImpactEffectInfo'WEP_ZEDMKIII_ARCH.FX_ZEDMKIII_Explosion_Concussive_force'
|
||||
|
||||
// Grenade 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=200
|
||||
DamageRadius=300
|
||||
DamageFalloffExponent=2
|
||||
DamageDelay=0.f
|
||||
|
||||
// Damage Effects
|
||||
MyDamageType=class'KFDT_Explosive_ZedMKIII'
|
||||
KnockDownStrength=0
|
||||
FractureMeshRadius=200.0
|
||||
FracturePartVel=500.0
|
||||
ExplosionEffects=KFImpactEffectInfo'WEP_ZEDMKIII_ARCH.FX_ZEDMKIII_Explosion'
|
||||
ExplosionSound=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Explosion'
|
||||
|
||||
// Dynamic Light
|
||||
ExploLight=ExplosionPointLight
|
||||
ExploLightStartFadeOutTime=0.0
|
||||
ExploLightFadeOutTime=0.2
|
||||
|
||||
// Camera Shake
|
||||
CamShake=CameraShake'FX_CameraShake_Arch.Misc_Explosions.Light_Explosion_Rumble'
|
||||
CamShakeInnerRadius=0
|
||||
CamShakeOuterRadius=500
|
||||
CamShakeFalloff=3.f
|
||||
bOrientCameraShakeTowardsEpicenter=true
|
||||
End Object
|
||||
ExplosionTemplate=ExploTemplate0
|
||||
}
|
183
KFGameContent/Classes/KFSeasonalEventStats_Xmas2022.uc
Normal file
183
KFGameContent/Classes/KFSeasonalEventStats_Xmas2022.uc
Normal file
@ -0,0 +1,183 @@
|
||||
//=============================================================================
|
||||
// KFSeasonalEventStats_Xmas2022
|
||||
//=============================================================================
|
||||
// Tracks event-specific challenges/accomplishments for Xmas 2022
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
class KFSeasonalEventStats_Xmas2022 extends KFSeasonalEventStats;
|
||||
|
||||
/**
|
||||
Required impacts of the same projectile to count for the objective. I.e. 3 means
|
||||
that a ballistic bouncer projectile needs to make 3 impacts to count for the objective
|
||||
*/
|
||||
var private const byte HRGBBProjectilImpactsRequired;
|
||||
|
||||
var transient private const int FrozenZedsRequired, ShotgunJumpsRequired, BallisticBouncerImpactsRequired, EndlessWaveRequired, XmasEventIndex;
|
||||
|
||||
var transient int ShotgunJumpsIdx;
|
||||
|
||||
private event Initialize(string MapName)
|
||||
{
|
||||
local string CapsMapName;
|
||||
CapsMapName = Caps(MapName);
|
||||
|
||||
bObjectiveIsValidForMap[0] = 1; // Freeze 500 Zeds using ice arsenal
|
||||
bObjectiveIsValidForMap[1] = 0; // Complete the Weekly on Crash
|
||||
bObjectiveIsValidForMap[2] = 0; // Use 4 Boomstick Jumps in a same match on Crash
|
||||
bObjectiveIsValidForMap[3] = 1; // Hit 3 Zeds with a shot of HRG Ballistic Bouncer (15 times)
|
||||
bObjectiveIsValidForMap[4] = 0; // Complete wave 15 on Endless Hard or higher difficulty on Crash
|
||||
|
||||
if (CapsMapName == "KF-CRASH")
|
||||
{
|
||||
bObjectiveIsValidForMap[1] = 1;
|
||||
bObjectiveIsValidForMap[2] = 1;
|
||||
bObjectiveIsValidForMap[4] = 1;
|
||||
}
|
||||
|
||||
SetSeasonalEventStatsMax(FrozenZedsRequired, 0, ShotgunJumpsRequired, BallisticBouncerImpactsRequired, 0);
|
||||
}
|
||||
|
||||
simulated event OnStatsInitialized()
|
||||
{
|
||||
super.OnStatsInitialized();
|
||||
|
||||
CheckRestartObjective(ShotgunJumpsIdx, ShotgunJumpsRequired);
|
||||
}
|
||||
|
||||
private event GrantEventItems()
|
||||
{
|
||||
if (Outer.IsEventObjectiveComplete(0) &&
|
||||
Outer.IsEventObjectiveComplete(1) &&
|
||||
Outer.IsEventObjectiveComplete(2) &&
|
||||
Outer.IsEventObjectiveComplete(3) &&
|
||||
Outer.IsEventObjectiveComplete(4))
|
||||
{
|
||||
GrantEventItem(9568);
|
||||
}
|
||||
}
|
||||
|
||||
simulated event OnGameWon(class<GameInfo> GameClass, int Difficulty, int GameLength, bool bCoOp)
|
||||
{
|
||||
local int ObjIdx;
|
||||
ObjIdx = 1;
|
||||
|
||||
// Crash weekly
|
||||
if (bObjectiveIsValidForMap[ObjIdx] != 0)
|
||||
{
|
||||
if (GameClass == class'KFGameInfo_WeeklySurvival')
|
||||
{
|
||||
FinishedObjective(XmasEventIndex, ObjIdx);
|
||||
}
|
||||
}
|
||||
|
||||
CheckRestartObjective(ShotgunJumpsIdx, ShotgunJumpsRequired);
|
||||
}
|
||||
|
||||
simulated event OnGameEnd(class<GameInfo> GameClass)
|
||||
{
|
||||
CheckRestartObjective(ShotgunJumpsIdx, ShotgunJumpsRequired);
|
||||
}
|
||||
|
||||
simulated function CheckRestartObjective(int ObjectiveIndex, int ObjectiveLimit)
|
||||
{
|
||||
local int StatValue;
|
||||
|
||||
StatValue = Outer.GetSeasonalEventStatValue(ObjectiveIndex);
|
||||
|
||||
if (StatValue != 0 && StatValue < ObjectiveLimit)
|
||||
{
|
||||
ResetSeasonalEventStat(ObjectiveIndex);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function OnTryCompleteObjective(int ObjectiveIndex, int EventIndex)
|
||||
{
|
||||
local int FrozenZedsIdx, BallisticBouncerImpactsIdx, ObjectiveLimit;
|
||||
local bool bValidIdx;
|
||||
|
||||
FrozenZedsIdx = 0;
|
||||
BallisticBouncerImpactsIdx = 3;
|
||||
bValidIdx = false;
|
||||
|
||||
if(EventIndex == XmasEventIndex)
|
||||
{
|
||||
if (ObjectiveIndex == FrozenZedsIdx)
|
||||
{
|
||||
ObjectiveLimit = FrozenZedsRequired;
|
||||
bValidIdx = true;
|
||||
}
|
||||
else if (ObjectiveIndex == ShotgunJumpsIdx)
|
||||
{
|
||||
ObjectiveLimit = ShotgunJumpsRequired;
|
||||
bValidIdx = true;
|
||||
}
|
||||
else if (ObjectiveIndex == BallisticBouncerImpactsIdx)
|
||||
{
|
||||
ObjectiveLimit = BallisticBouncerImpactsRequired;
|
||||
bValidIdx = true;
|
||||
}
|
||||
|
||||
if (bValidIdx && bObjectiveIsValidForMap[ObjectiveIndex] != 0)
|
||||
{
|
||||
IncrementSeasonalEventStat(ObjectiveIndex, 1);
|
||||
if (Outer.GetSeasonalEventStatValue(ObjectiveIndex) >= ObjectiveLimit)
|
||||
{
|
||||
FinishedObjective(XmasEventIndex, ObjectiveIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated event OnWaveCompleted(class<GameInfo> GameClass, int Difficulty, int WaveNum)
|
||||
{
|
||||
local int ObjIdx;
|
||||
|
||||
// Complete wave 15 on Endless Hard or higher difficulty on Crash
|
||||
ObjIdx = 4;
|
||||
if (bObjectiveIsValidForMap[ObjIdx] != 0)
|
||||
{
|
||||
if (WaveNum >= EndlessWaveRequired && GameClass == class'KFGameInfo_Endless' && Difficulty >= `DIFFICULTY_HARD)
|
||||
{
|
||||
FinishedObjective(XmasEventIndex, ObjIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function OnAfflictionCaused(EAfflictionType Type)
|
||||
{
|
||||
local int ObjIdx;
|
||||
|
||||
ObjIdx = 0;
|
||||
|
||||
if (bObjectiveIsValidForMap[ObjIdx] != 0)
|
||||
{
|
||||
if (Type == AF_Freeze)
|
||||
{
|
||||
IncrementSeasonalEventStat(ObjIdx, 1);
|
||||
if (Outer.GetSeasonalEventStatValue(ObjIdx) >= FrozenZedsRequired)
|
||||
{
|
||||
FinishedObjective(XmasEventIndex, ObjIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static function byte GetMaxBallisticBouncerImpacts()
|
||||
{
|
||||
return default.HRGBBProjectilImpactsRequired;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ShotgunJumpsIdx=2
|
||||
|
||||
FrozenZedsRequired=500
|
||||
ShotgunJumpsRequired=4
|
||||
BallisticBouncerImpactsRequired=30
|
||||
EndlessWaveRequired=15
|
||||
XmasEventIndex=SEI_Winter
|
||||
|
||||
HRGBBProjectilImpactsRequired=2
|
||||
}
|
95
KFGameContent/Classes/KFShotgunJumpEndVolume.uc
Normal file
95
KFGameContent/Classes/KFShotgunJumpEndVolume.uc
Normal file
@ -0,0 +1,95 @@
|
||||
|
||||
|
||||
//=============================================================================
|
||||
// KFShotgunJumpEndVolume
|
||||
//=============================================================================
|
||||
// Barmwich volume used tracking the start of shotgun jumps.
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFShotgunJumpEndVolume extends PhysicsVolume
|
||||
placeable;
|
||||
|
||||
/** Objective index for the event this is tied to */
|
||||
var() int ObjectiveIndex;
|
||||
|
||||
/** Index of the event this is tied to */
|
||||
var() int EventIndex;
|
||||
|
||||
/** All volumes that track the begin of a shotgun jump in the area */
|
||||
var() array<KFShotgunJumpStartVolume> LinkedVolumes;
|
||||
|
||||
var transient bool bIsDataValid;
|
||||
|
||||
var array<KFPlayerController> SucceededControllers;
|
||||
|
||||
simulated event PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
|
||||
bIsDataValid = IsObjectiveDataValid();
|
||||
|
||||
if (LinkedVolumes.Length == 0)
|
||||
{
|
||||
`warn("Volume [" $self $"] has no linked volumes (KFShotgunJumpStartVolume).");
|
||||
}
|
||||
}
|
||||
|
||||
simulated event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal )
|
||||
{
|
||||
local KFPawn_Human KFPH;
|
||||
local KFPlayerController KFPC;
|
||||
local KFShotgunJumpStartVolume StartVolume;
|
||||
|
||||
KFPH = KFPawn_Human(Other);
|
||||
if (KFPH == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
KFPC = KFPlayerController(KFPH.Controller);
|
||||
|
||||
if (KFPC == none || IsCompletedByController(KFPC))
|
||||
return;
|
||||
|
||||
foreach LinkedVolumes(StartVolume)
|
||||
{
|
||||
if (StartVolume.IsPlayerTracked(KFPC))
|
||||
{
|
||||
StartVolume.RemoveTrackedPlayer(KFPC);
|
||||
if (KFPC.bShotgunJumping)
|
||||
{
|
||||
SucceededControllers.AddItem(KFPC);
|
||||
KFPC.ClientOnTryCompleteObjective(ObjectiveIndex, EventIndex);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function bool IsCompletedByController(KFPlayerController Controller)
|
||||
{
|
||||
local KFPlayerController Current;
|
||||
|
||||
foreach SucceededControllers(Current)
|
||||
{
|
||||
if (Controller == Current)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function bool IsObjectiveDataValid()
|
||||
{
|
||||
return ObjectiveIndex >= 0 && ObjectiveIndex < 5 && EventIndex > SEI_None && EventIndex < SEI_MAX;
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
bIsDataValid = false
|
||||
}
|
151
KFGameContent/Classes/KFShotgunJumpStartVolume.uc
Normal file
151
KFGameContent/Classes/KFShotgunJumpStartVolume.uc
Normal file
@ -0,0 +1,151 @@
|
||||
|
||||
|
||||
//=============================================================================
|
||||
// KFShotgunJumpStartVolume
|
||||
//=============================================================================
|
||||
// Barmwich volume used tracking the start of shotgun jumps.
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFShotgunJumpStartVolume extends PhysicsVolume
|
||||
placeable;
|
||||
|
||||
/** Max time we keep track of players */
|
||||
var() float TrackedPlayerLifetime;
|
||||
|
||||
var Info ShotgunJumpVolumeTimer;
|
||||
|
||||
struct KFTrackedController
|
||||
{
|
||||
var KFPlayerController KFPC;
|
||||
var float ExitTimestamp;
|
||||
var bool bInVolume;
|
||||
|
||||
structdefaultproperties
|
||||
{
|
||||
KFPC=none
|
||||
ExitTimestamp=0
|
||||
bInVolume=false
|
||||
}
|
||||
};
|
||||
|
||||
var transient array<KFTrackedController> TrackedControllers;
|
||||
|
||||
simulated event PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
|
||||
if ( Role < ROLE_Authority )
|
||||
return;
|
||||
|
||||
ShotgunJumpVolumeTimer = Spawn(class'VolumeTimer', self);
|
||||
}
|
||||
|
||||
simulated event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal )
|
||||
{
|
||||
local KFPawn_Human KFPH;
|
||||
local KFPlayerController KFPC;
|
||||
local KFTrackedController NewTrackedController;
|
||||
local int i;
|
||||
|
||||
KFPH = KFPawn_Human(Other);
|
||||
if (KFPH == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
KFPC = KFPlayerController(KFPH.Controller);
|
||||
if (KFPC == none)
|
||||
return;
|
||||
|
||||
for (i = 0; i < TrackedControllers.Length; ++i)
|
||||
{
|
||||
if (TrackedControllers[i].KFPC == KFPC)
|
||||
{
|
||||
TrackedControllers[i].bInVolume = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Update current time
|
||||
NewTrackedController.KFPC = KFPC;
|
||||
NewTrackedController.bInVolume = true;
|
||||
|
||||
TrackedControllers.AddItem(NewTrackedController);
|
||||
}
|
||||
|
||||
simulated event Untouch(Actor Other)
|
||||
{
|
||||
local KFPawn_Human KFPH;
|
||||
local int i;
|
||||
local KFPlayerController KFPC;
|
||||
|
||||
KFPH = KFPawn_Human(Other);
|
||||
if (KFPH == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
KFPC = KFPlayerController(KFPH.Controller);
|
||||
if (KFPC == none)
|
||||
return;
|
||||
|
||||
for (i = 0; i < TrackedControllers.Length; ++i)
|
||||
{
|
||||
if (TrackedControllers[i].KFPC == KFPC)
|
||||
{
|
||||
TrackedControllers[i].ExitTimestamp = WorldInfo.TimeSeconds;
|
||||
TrackedControllers[i].bInVolume = false;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function TimerPop(VolumeTimer T)
|
||||
{
|
||||
local int i;
|
||||
|
||||
for (i = TrackedControllers.Length-1; i >= 0 ; --i)
|
||||
{
|
||||
if (!TrackedControllers[i].bInVolume && (`TimeSince(TrackedControllers[i].ExitTimestamp) >= TrackedPlayerLifetime) )
|
||||
{
|
||||
TrackedControllers.Remove(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function RemoveTrackedPlayer(KFPlayerController KFPC)
|
||||
{
|
||||
local int i;
|
||||
|
||||
for (i = TrackedControllers.Length-1; i >= 0 ; --i)
|
||||
{
|
||||
if (TrackedControllers[i].KFPC == KFPC)
|
||||
{
|
||||
TrackedControllers.Remove(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bool IsPlayerTracked(KFPlayerController KFPC)
|
||||
{
|
||||
local KFTrackedController TrackedController;
|
||||
foreach TrackedControllers(TrackedController)
|
||||
{
|
||||
if (TrackedController.KFPC == KFPC)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
TrackedPlayerLifetime = 1.0f;
|
||||
}
|
120
KFGameContent/Classes/KFWeapAttach_HRG_BallisticBouncer.uc
Normal file
120
KFGameContent/Classes/KFWeapAttach_HRG_BallisticBouncer.uc
Normal file
@ -0,0 +1,120 @@
|
||||
//=============================================================================
|
||||
// KFWeapAttach_HRG_BallisticBouncer
|
||||
//=============================================================================
|
||||
//
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFWeapAttach_HRG_BallisticBouncer extends KFWeaponAttachment;
|
||||
|
||||
var() StaticMesh ChargeStaticMesh;
|
||||
var transient StaticMeshComponent ChargeAttachment;
|
||||
var transient MaterialInstanceConstant ChargeMIC;
|
||||
|
||||
var float MinProjPlaceholderScale;
|
||||
var float MaxProjPlaceHolderScale;
|
||||
|
||||
var bool bIsCharging;
|
||||
var bool bIsFullyCharged;
|
||||
|
||||
var repnotify float StartFireTime;
|
||||
|
||||
var int ChargeLevel;
|
||||
|
||||
var float ChargeRTPC;
|
||||
|
||||
simulated function StartFire()
|
||||
{
|
||||
StartFireTime = WorldInfo.TimeSeconds;
|
||||
bIsCharging = true;
|
||||
|
||||
if (ChargeAttachment == none)
|
||||
{
|
||||
ChargeAttachment = new (self) class'StaticMeshComponent';
|
||||
ChargeAttachment.SetStaticMesh(ChargeStaticMesh);
|
||||
|
||||
if (WeapMesh != none)
|
||||
{
|
||||
WeapMesh.AttachComponentToSocket(ChargeAttachment, 'MuzzleFlash');
|
||||
}
|
||||
else
|
||||
{
|
||||
AttachComponent(ChargeAttachment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ChargeAttachment != none)
|
||||
{
|
||||
ChargeAttachment.SetScale(MinProjPlaceholderScale);
|
||||
ChargeAttachment.SetHidden(false);
|
||||
}
|
||||
}
|
||||
|
||||
simulated event Tick(float DeltaTime)
|
||||
{
|
||||
local float ChargeValue;
|
||||
|
||||
if(bIsCharging && !bIsFullyCharged)
|
||||
{
|
||||
ChargeValue = FMin(class'KFWeap_HRG_BallisticBouncer'.default.MaxChargeTime, WorldInfo.TimeSeconds - StartFireTime) / class'KFWeap_HRG_BallisticBouncer'.default.MaxChargeTime;
|
||||
|
||||
if (ChargeValue >= 1.0f)
|
||||
{
|
||||
bIsFullyCharged = true;
|
||||
ChargeValue = 1.0f;
|
||||
}
|
||||
|
||||
if( ChargeAttachment != none)
|
||||
{
|
||||
ChargeAttachment.SetScale(MinProjPlaceholderScale + (MaxProjPlaceHolderScale - MinProjPlaceholderScale) * ChargeValue);
|
||||
}
|
||||
}
|
||||
|
||||
Super.Tick(DeltaTime);
|
||||
}
|
||||
|
||||
simulated function FirstPersonFireEffects(Weapon W, vector HitLocation)
|
||||
{
|
||||
super.FirstPersonFireEffects(W, HitLocation);
|
||||
if (ChargeAttachment != none)
|
||||
{
|
||||
ChargeAttachment.SetHidden(true);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function bool ThirdPersonFireEffects(vector HitLocation, KFPawn P, byte ThirdPersonAnimRateByte)
|
||||
{
|
||||
bIsCharging = false;
|
||||
bIsFullyCharged = false;
|
||||
ChargeRTPC=0;
|
||||
|
||||
if (ChargeAttachment != none)
|
||||
{
|
||||
ChargeAttachment.SetHidden(true);
|
||||
}
|
||||
|
||||
return Super.ThirdPersonFireEffects(HitLocation, P, ThirdPersonAnimRateByte);
|
||||
}
|
||||
|
||||
simulated function CauseMuzzleFlash(byte FiringMode)
|
||||
{
|
||||
if (MuzzleFlash == None && MuzzleFlashTemplate != None)
|
||||
{
|
||||
AttachMuzzleFlash();
|
||||
}
|
||||
|
||||
Super.CauseMuzzleFlash(FiringMode);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ChargeRTPC=0
|
||||
MuzzleFlashTemplate=KFMuzzleFlash'WEP_Mine_Reconstructor_Arch.Wep_Mine_Reconstructor_MuzzleFlash_3P'
|
||||
|
||||
ChargeStaticMesh = StaticMesh'WEP_HRG_BallisticBouncer_EMIT.HRG_BallisticBouncer_ball_MESH'
|
||||
MinProjPlaceholderScale = 2.0f;
|
||||
MaxProjPlaceholderScale = 3.0f;
|
||||
}
|
@ -196,7 +196,7 @@ defaultproperties
|
||||
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Bludgeon_Doshinegun_Shot'
|
||||
FireInterval(DEFAULT_FIREMODE)=+0.2
|
||||
Spread(DEFAULT_FIREMODE)=0.015
|
||||
InstantHitDamage(DEFAULT_FIREMODE)=60.0 //55.0 //60.0
|
||||
InstantHitDamage(DEFAULT_FIREMODE)=80 //60.0 //55.0 //60.0
|
||||
FireOffset=(X=30,Y=4.5,Z=-5)
|
||||
|
||||
// ALT_FIREMODE
|
||||
@ -206,7 +206,7 @@ defaultproperties
|
||||
WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Dosh'
|
||||
InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Bludgeon_Doshinegun_Shot'
|
||||
FireInterval(ALTFIRE_FIREMODE)=+0.2
|
||||
InstantHitDamage(ALTFIRE_FIREMODE)=60.0 //55.0 //60.0
|
||||
InstantHitDamage(ALTFIRE_FIREMODE)=80 //60.0 //55.0 //60.0
|
||||
Spread(ALTFIRE_FIREMODE)=0.015
|
||||
|
||||
// BASH_FIREMODE
|
||||
@ -239,7 +239,7 @@ defaultproperties
|
||||
WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.47f), (Stat=EWUS_Damage1, Scale=1.47f), (Stat=EWUS_Weight, Add=2)))
|
||||
WeaponUpgrades[3]=(Stats=((Stat=EWUS_Damage0, Scale=1.70f), (Stat=EWUS_Damage1, Scale=1.70f), (Stat=EWUS_Weight, Add=3)))
|
||||
|
||||
DoshCost = 20; //25;
|
||||
DoshCost = 10 //20; //25;
|
||||
bUsesSecondaryAmmoAltHUD=true
|
||||
bAllowClientAmmoTracking=false
|
||||
bIsBeingDropped=false
|
||||
|
@ -142,7 +142,7 @@ defaultproperties
|
||||
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Grenade_GravityImploder'
|
||||
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_GravityImploderImpact'
|
||||
InstantHitDamage(DEFAULT_FIREMODE)=150
|
||||
FireInterval(DEFAULT_FIREMODE)=1.33 //45 RPM
|
||||
FireInterval(DEFAULT_FIREMODE)=1 // 60 RPM //1.33 //45 RPM
|
||||
Spread(DEFAULT_FIREMODE)=0.02 //0
|
||||
PenetrationPower(DEFAULT_FIREMODE)=0
|
||||
FireOffset=(X=25,Y=3.0,Z=-2.5)
|
||||
@ -152,7 +152,7 @@ defaultproperties
|
||||
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSingleFiring
|
||||
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Projectile
|
||||
WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Grenade_GravityImploderAlt'
|
||||
FireInterval(ALTFIRE_FIREMODE)=1.33 //45 RPM
|
||||
FireInterval(ALTFIRE_FIREMODE)=1 // 60 RPM //1.33 //45 RPM
|
||||
InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_GravityImploderImpactAlt'
|
||||
InstantHitDamage(ALTFIRE_FIREMODE)=200
|
||||
Spread(ALTFIRE_FIREMODE)=0.02 //0.0085
|
||||
|
766
KFGameContent/Classes/KFWeap_HRG_BallisticBouncer.uc
Normal file
766
KFGameContent/Classes/KFWeap_HRG_BallisticBouncer.uc
Normal file
@ -0,0 +1,766 @@
|
||||
//=============================================================================
|
||||
// KFWeap_HRG_BallisticBouncer
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
class KFWeap_HRG_BallisticBouncer extends KFWeapon;
|
||||
|
||||
//Props related to charging the weapon
|
||||
var float MaxChargeTime;
|
||||
var float ValueIncreaseTime;
|
||||
var float DmgIncreasePerCharge;
|
||||
var float AOEIncreasePerCharge;
|
||||
var float IncapIncreasePerCharge;
|
||||
var int AmmoIncreasePerCharge;
|
||||
|
||||
var transient float ChargeTime;
|
||||
var transient float ConsumeAmmoTime;
|
||||
var transient float MaxChargeLevel;
|
||||
|
||||
var ParticleSystem ChargedEffect;
|
||||
|
||||
var transient ParticleSystemComponent FullyChargedPSC;
|
||||
var transient bool bIsFullyCharged;
|
||||
|
||||
var const WeaponFireSndInfo FullyChargedSound;
|
||||
|
||||
var float FullChargedTimerInterval;
|
||||
var float FXScalingFactorByCharge, ChargePercentage;
|
||||
var float MinScale, MaxScale;
|
||||
|
||||
var int MaxDamageByCharge;
|
||||
var int MinDamageByCharge;
|
||||
|
||||
const SecondaryFireAnim = 'Alt_Fire';
|
||||
const SecondaryFireIronAnim = 'Alt_Fire_Iron';
|
||||
const SecondaryFireAnimEmpty = 'Alt_Fire_Empty';
|
||||
const SecondaryFireIronAnimEmpty = 'Alt_Fire_Iron_Empty';
|
||||
var bool bHasToLaunchEmptyAnim;
|
||||
|
||||
var SkelControlSingleBone Control;
|
||||
|
||||
var bool bBlocked;
|
||||
|
||||
var() StaticMesh ChargeStaticMesh;
|
||||
var transient StaticMeshComponent ChargeAttachment;
|
||||
var transient MaterialInstanceConstant ChargeMIC;
|
||||
|
||||
var float MinProjPlaceholderScale;
|
||||
var float MaxProjPlaceHolderScale;
|
||||
|
||||
Replication
|
||||
{
|
||||
if(Role == Role_Authority && bNetDirty)
|
||||
ChargeTime;
|
||||
}
|
||||
|
||||
simulated event PostInitAnimTree( SkeletalMeshComponent SkelComp )
|
||||
{
|
||||
local vector vec;
|
||||
local float fPercentage;
|
||||
|
||||
super.PostInitAnimTree( SkelComp );
|
||||
|
||||
Control = SkelControlSingleBone( SkelComp.FindSkelControl('AmmoControl') );
|
||||
if( Control != none )
|
||||
{
|
||||
Control.SetSkelControlActive( true );
|
||||
}
|
||||
|
||||
//from 0 to -8
|
||||
// If AmmoCount is being replicated, don't allow the client to modify it here
|
||||
fPercentage = FMin((float(AmmoCount[0])/(MagazineCapacity[0])), 1);
|
||||
vec.X = Control.BoneTranslation.X;
|
||||
vec.Y = Control.BoneTranslation.Y;
|
||||
vec.Z = Lerp(-8, 0, fPercentage);
|
||||
Control.BoneTranslation = vec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Weapon::ConsumeAmmo
|
||||
*/
|
||||
simulated function ConsumeAmmo(byte FireModeNum)
|
||||
{
|
||||
local vector vec;
|
||||
local float fPercentage;
|
||||
|
||||
//from 0 to -8
|
||||
// If AmmoCount is being replicated, don't allow the client to modify it here
|
||||
if (Role == ROLE_Authority)
|
||||
{
|
||||
fPercentage = FMin(float(AmmoCount[0])/(MagazineCapacity[0]), 1);
|
||||
super.ConsumeAmmo(FireModeNum);
|
||||
|
||||
if(Control != none)
|
||||
{
|
||||
vec.X = Control.BoneTranslation.X;
|
||||
vec.Y = Control.BoneTranslation.Y;
|
||||
vec.Z = Lerp(-8, 0, fPercentage);
|
||||
Control.BoneTranslation = vec;
|
||||
}
|
||||
|
||||
//Notify the client about the new percentage as the client is not tracking the ammo
|
||||
ClientUpdateVisualAmmo(fPercentage);
|
||||
}
|
||||
}
|
||||
|
||||
reliable client function ClientUpdateVisualAmmo(float BoneControlTranslation)
|
||||
{
|
||||
local vector vec;
|
||||
|
||||
if ( Role < ROLE_Authority && Control != none )
|
||||
{
|
||||
vec.X = Control.BoneTranslation.X;
|
||||
vec.Y = Control.BoneTranslation.Y;
|
||||
vec.Z = Lerp(-8, 0, BoneControlTranslation);
|
||||
Control.BoneTranslation = vec;
|
||||
}
|
||||
}
|
||||
|
||||
simulated function StartFire(byte FiremodeNum)
|
||||
{
|
||||
if (IsTimerActive('RefireCheckTimer') || bBlocked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(Role != Role_Authority && FireModeNum == DEFAULT_FIREMODE && HasAmmo(DEFAULT_FIREMODE))
|
||||
{
|
||||
bBlocked = true;
|
||||
if(IsTimerActive(nameof(UnlockClientFire)))
|
||||
{
|
||||
ClearTimer(nameof(UnlockClientFire));
|
||||
}
|
||||
}
|
||||
|
||||
super.StartFire(FiremodeNum);
|
||||
|
||||
if ( PendingFire(RELOAD_FIREMODE) && Role != Role_Authority)
|
||||
{
|
||||
bBlocked = false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
simulated function RefireCheckTimer()
|
||||
{
|
||||
Super.RefireCheckTimer();
|
||||
if(bBlocked && Role != Role_Authority)
|
||||
{
|
||||
SetTimer(0.25f , false, nameof(UnlockClientFire));
|
||||
}
|
||||
}
|
||||
|
||||
reliable client function UnlockClientFire()
|
||||
{
|
||||
bBlocked = false;
|
||||
}
|
||||
|
||||
simulated function OnStartFire()
|
||||
{
|
||||
local KFPawn PawnInst;
|
||||
PawnInst = KFPawn(Instigator);
|
||||
|
||||
if (PawnInst != none)
|
||||
{
|
||||
PawnInst.OnStartFire();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
simulated function FireAmmunition()
|
||||
{
|
||||
// Let the accuracy tracking system know that we fired
|
||||
HandleWeaponShotTaken(CurrentFireMode);
|
||||
|
||||
// Handle the different fire types
|
||||
switch (WeaponFireTypes[CurrentFireMode])
|
||||
{
|
||||
case EWFT_InstantHit:
|
||||
// Launch a projectile if we are in zed time, and this weapon has a projectile to launch for this mode
|
||||
if (`IsInZedTime(self) && WeaponProjectiles[CurrentFireMode] != none )
|
||||
{
|
||||
ProjectileFire();
|
||||
}
|
||||
else
|
||||
{
|
||||
InstantFireClient();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EWFT_Projectile:
|
||||
ProjectileFire();
|
||||
break;
|
||||
|
||||
case EWFT_Custom:
|
||||
CustomFire();
|
||||
break;
|
||||
}
|
||||
|
||||
//// If we're firing without charging, still consume one ammo
|
||||
if (GetChargeLevel() < 1)
|
||||
{
|
||||
ConsumeAmmo(CurrentFireMode);
|
||||
}
|
||||
|
||||
NotifyWeaponFired(CurrentFireMode);
|
||||
|
||||
// Play fire effects now (don't wait for WeaponFired to replicate)
|
||||
PlayFireEffects(CurrentFireMode, vect(0, 0, 0));
|
||||
}
|
||||
|
||||
simulated function ANIMNOTIFY_FILLMAG()
|
||||
{
|
||||
local vector vec;
|
||||
|
||||
if (Control != none)
|
||||
{
|
||||
vec.X = Control.BoneTranslation.X;
|
||||
vec.Y = Control.BoneTranslation.Y;
|
||||
vec.Z = 0;
|
||||
Control.BoneTranslation = vec;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Weapon::HasAmmo
|
||||
*/
|
||||
simulated event bool HasAmmo( byte FireModeNum, optional int Amount )
|
||||
{
|
||||
local KFPerk InstigatorPerk;
|
||||
// we can always do a melee attack
|
||||
if( FireModeNum == BASH_FIREMODE )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else if ( FireModeNum == RELOAD_FIREMODE )
|
||||
{
|
||||
return CanReload();
|
||||
}
|
||||
else if ( FireModeNum == GRENADE_FIREMODE )
|
||||
{
|
||||
if( KFInventoryManager(InvManager) != none )
|
||||
{
|
||||
return KFInventoryManager(InvManager).HasGrenadeAmmo(Amount);
|
||||
}
|
||||
}
|
||||
|
||||
InstigatorPerk = GetPerk();
|
||||
if( InstigatorPerk != none && InstigatorPerk.GetIsUberAmmoActive( self ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// If passed in ammo isn't set, use default ammo cost.
|
||||
if( Amount == 0 )
|
||||
{
|
||||
Amount = AmmoCost[FireModeNum];
|
||||
}
|
||||
|
||||
return AmmoCount[GetAmmoType(FireModeNum)] >= Amount;
|
||||
}
|
||||
|
||||
simulated state MineReconstructorCharge extends WeaponFiring
|
||||
{
|
||||
//For minimal code purposes, I'll directly call global.FireAmmunition after charging is released
|
||||
simulated function FireAmmunition()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Store start fire time so we don't have to timer this
|
||||
simulated event BeginState(Name PreviousStateName)
|
||||
{
|
||||
local KFPerk InstigatorPerk;
|
||||
|
||||
super.BeginState(PreviousStateName);
|
||||
|
||||
InstigatorPerk = GetPerk();
|
||||
if( InstigatorPerk != none )
|
||||
{
|
||||
SetZedTimeResist( InstigatorPerk.GetZedTimeModifier(self) );
|
||||
}
|
||||
|
||||
ChargeTime = 0;
|
||||
ConsumeAmmoTime = 0;
|
||||
MaxChargeLevel = int(MaxChargeTime / ValueIncreaseTime);
|
||||
|
||||
if (WorldInfo.NetMode == NM_Client || WorldInfo.NetMode == NM_Standalone)
|
||||
{
|
||||
if (ChargeAttachment == none)
|
||||
{
|
||||
ChargeAttachment = new (self) class'StaticMeshComponent';
|
||||
|
||||
// ChargeAttachment.SetActorCollision(false, false);
|
||||
ChargeAttachment.SetStaticMesh(ChargeStaticMesh);
|
||||
// ChargeAttachment.SetShadowParent(Mesh);
|
||||
|
||||
ChargeMIC = ChargeAttachment.CreateAndSetMaterialInstanceConstant(0);
|
||||
|
||||
MySkelMesh.AttachComponentToSocket(ChargeAttachment, 'MuzzleFlash');
|
||||
|
||||
ChargeAttachment.SetHidden(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ChargeAttachment.SetStaticMesh(ChargeStaticMesh);
|
||||
}
|
||||
}
|
||||
|
||||
bIsFullyCharged = false;
|
||||
|
||||
global.OnStartFire();
|
||||
|
||||
ChargeTime = 0;
|
||||
FXScalingFactorByCharge = 0;
|
||||
}
|
||||
|
||||
simulated function bool ShouldRefire()
|
||||
{
|
||||
// ignore how much ammo is left (super/global counts ammo)
|
||||
return StillFiring(CurrentFireMode);
|
||||
}
|
||||
|
||||
simulated event Tick(float DeltaTime)
|
||||
{
|
||||
local float ChargeRTPC;
|
||||
local float InstantHitDamageValue;
|
||||
local float NewScale;
|
||||
|
||||
global.Tick(DeltaTime);
|
||||
|
||||
if (ChargeAttachment != none && ChargeAttachment.StaticMesh == none)
|
||||
{
|
||||
ChargeAttachment.SetStaticMesh(ChargeStaticMesh);
|
||||
}
|
||||
|
||||
if(bIsFullyCharged) return;
|
||||
|
||||
// Don't charge unless we're holding down the button
|
||||
if (PendingFire(CurrentFireMode))
|
||||
{
|
||||
ConsumeAmmoTime += DeltaTime;
|
||||
}
|
||||
|
||||
if (bIsFullyCharged)
|
||||
{
|
||||
if (ConsumeAmmoTime >= FullChargedTimerInterval)
|
||||
{
|
||||
ConsumeAmmo(DEFAULT_FIREMODE);
|
||||
ConsumeAmmoTime -= FullChargedTimerInterval;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't charge unless we're holding down the button
|
||||
if (PendingFire(CurrentFireMode))
|
||||
{
|
||||
if(Role == Role_Authority && !bIsFullyCharged)
|
||||
{
|
||||
ChargeTime += DeltaTime;
|
||||
bNetDirty = true;
|
||||
}
|
||||
|
||||
ChargePercentage = FMin(ChargeTime / MaxChargeTime, 1);
|
||||
|
||||
if (ChargeAttachment != none && !bIsFullyCharged)
|
||||
{
|
||||
FXScalingFactorByCharge = FMin(Lerp(MinScale, MaxScale, ChargeTime / MaxChargeTime), MaxScale);
|
||||
|
||||
if(ChargePercentage < 0.1f)
|
||||
{
|
||||
InstantHitDamageValue = Lerp(MinDamageByCharge, MaxDamageByCharge, 0.1f);
|
||||
}
|
||||
else
|
||||
{
|
||||
InstantHitDamageValue = Lerp(MinDamageByCharge, MaxDamageByCharge, ChargePercentage);
|
||||
}
|
||||
InstantHitDamage[DEFAULT_FIREMODE] = InstantHitDamageValue;
|
||||
|
||||
NewScale = Lerp(MinProjPlaceholderScale, MaxProjPlaceholderScale, ChargePercentage);
|
||||
|
||||
ChargeAttachment.SetHidden(false);
|
||||
ChargeAttachment.SetScale( NewScale );
|
||||
|
||||
if (ChargeMIC != none)
|
||||
{
|
||||
// Change Color
|
||||
ChargeMIC.SetScalarParameterValue('Charge', ChargePercentage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChargeRTPC = FMin(ChargeTime / MaxChargeTime, 1.f);
|
||||
KFPawn(Instigator).SetWeaponComponentRTPCValue("Weapon_Charge", ChargeRTPC); //For looping component
|
||||
Instigator.SetRTPCValue('Weapon_Charge', ChargeRTPC); //For one-shot sounds
|
||||
|
||||
if (ConsumeAmmoTime >= ValueIncreaseTime && !bIsFullyCharged)
|
||||
{
|
||||
ConsumeAmmo(DEFAULT_FIREMODE);
|
||||
ConsumeAmmoTime -= ValueIncreaseTime;
|
||||
}
|
||||
|
||||
if (ChargeTime >= MaxChargeTime || !HasAmmo(DEFAULT_FIREMODE))
|
||||
{
|
||||
bIsFullyCharged = true;
|
||||
|
||||
if(( Instigator.Role != ROLE_Authority ) || WorldInfo.NetMode == NM_Standalone)
|
||||
{
|
||||
if (FullyChargedPSC == none)
|
||||
{
|
||||
FullyChargedPSC = new(self) class'ParticleSystemComponent';
|
||||
|
||||
if(MySkelMesh != none)
|
||||
{
|
||||
MySkelMesh.AttachComponentToSocket(FullyChargedPSC, 'MuzzleFlash');
|
||||
}
|
||||
else
|
||||
{
|
||||
AttachComponent(FullyChargedPSC);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FullyChargedPSC.ActivateSystem();
|
||||
}
|
||||
|
||||
FullyChargedPSC.SetTemplate(ChargedEffect);
|
||||
|
||||
|
||||
KFPawn(Instigator).SetWeaponAmbientSound(FullyChargedSound.DefaultCue, FullyChargedSound.FirstPersonCue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Now that we're done charging, directly call FireAmmunition. This will handle the actual projectile fire and scaling.
|
||||
simulated event EndState(Name NextStateName)
|
||||
{
|
||||
if(Role == Role_Authority)
|
||||
{
|
||||
UnlockClientFire();
|
||||
}
|
||||
|
||||
ClearZedTimeResist();
|
||||
ClearPendingFire(CurrentFireMode);
|
||||
ClearTimer(nameof(RefireCheckTimer));
|
||||
|
||||
KFPawn(Instigator).bHasStartedFire = false;
|
||||
KFPawn(Instigator).bNetDirty = true;
|
||||
|
||||
if (ChargeAttachment != none)
|
||||
{
|
||||
ChargeAttachment.SetHidden(true);
|
||||
ChargeAttachment.SetScale(MinProjPlaceholderScale);
|
||||
}
|
||||
|
||||
if (FullyChargedPSC != none)
|
||||
{
|
||||
FullyChargedPSC.DeactivateSystem();
|
||||
}
|
||||
|
||||
KFPawn(Instigator).SetWeaponAmbientSound(none);
|
||||
}
|
||||
|
||||
simulated function HandleFinishedFiring()
|
||||
{
|
||||
global.FireAmmunition();
|
||||
|
||||
if (bPlayingLoopingFireAnim)
|
||||
{
|
||||
StopLoopingFireEffects(CurrentFireMode);
|
||||
}
|
||||
|
||||
SetTimer(0.1f, false, 'Timer_StopFireEffects');
|
||||
|
||||
NotifyWeaponFinishedFiring(CurrentFireMode);
|
||||
|
||||
super.HandleFinishedFiring();
|
||||
//`Log("ChargePercentage"@ChargePercentage);
|
||||
}
|
||||
|
||||
simulated function PutDownWeapon()
|
||||
{
|
||||
global.FireAmmunition();
|
||||
|
||||
if (bPlayingLoopingFireAnim)
|
||||
{
|
||||
StopLoopingFireEffects(CurrentFireMode);
|
||||
}
|
||||
|
||||
SetTimer(0.1f, false, 'Timer_StopFireEffects');
|
||||
|
||||
if (ChargeAttachment != none)
|
||||
{
|
||||
ChargeAttachment.SetHidden(true);
|
||||
ChargeAttachment.SetScale(MinProjPlaceholderScale);
|
||||
}
|
||||
|
||||
NotifyWeaponFinishedFiring(CurrentFireMode);
|
||||
|
||||
if(Role == Role_Authority)
|
||||
{
|
||||
UnlockClientFire();
|
||||
}
|
||||
|
||||
super.PutDownWeapon();
|
||||
}
|
||||
}
|
||||
|
||||
simulated function StopFireEffects(byte FireModeNum)
|
||||
{
|
||||
Super.StopFireEffects(FireModeNum);
|
||||
|
||||
if (ChargeAttachment != none)
|
||||
{
|
||||
ChargeAttachment.SetStaticMesh(none); // if we don't do this it doesn't work ?!, when starting fire it assigns again so no problem..
|
||||
|
||||
ChargeAttachment.SetHidden(true);
|
||||
ChargeAttachment.SetScale(MinProjPlaceholderScale);
|
||||
}
|
||||
}
|
||||
|
||||
// Placing the actual Weapon Firing end state here since we need it to happen at the end of the actual firing loop.
|
||||
simulated function Timer_StopFireEffects()
|
||||
{
|
||||
// Simulate weapon firing effects on the local client
|
||||
if (WorldInfo.NetMode == NM_Client)
|
||||
{
|
||||
Instigator.WeaponStoppedFiring(self, false);
|
||||
|
||||
if (ChargeAttachment != none)
|
||||
{
|
||||
ChargeAttachment.SetHidden(true);
|
||||
}
|
||||
|
||||
if (FullyChargedPSC != none)
|
||||
{
|
||||
FullyChargedPSC.DeactivateSystem();
|
||||
}
|
||||
}
|
||||
|
||||
ClearFlashCount();
|
||||
ClearFlashLocation();
|
||||
}
|
||||
|
||||
simulated state Active
|
||||
{
|
||||
simulated function BeginState(name PreviousStateName)
|
||||
{
|
||||
Super.BeginState(PreviousStateName);
|
||||
if(Role == Role_Authority)
|
||||
{
|
||||
UnlockClientFire();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
simulated function KFProjectile SpawnProjectile(class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir)
|
||||
{
|
||||
local KFProj_HRG_BallisticBouncer BouncingProj;
|
||||
|
||||
BouncingProj = KFProj_HRG_BallisticBouncer(super.SpawnProjectile(KFProjClass, RealStartLoc, AimDir));
|
||||
//Calc and set scaling values
|
||||
if (BouncingProj != none)
|
||||
{
|
||||
ChargePercentage = FMax(0.1, ChargePercentage);
|
||||
FXScalingFactorByCharge = FMax(0.1, FXScalingFactorByCharge);
|
||||
BouncingProj.SetInheritedScale(FXScalingFactorByCharge, ChargePercentage);
|
||||
return BouncingProj;
|
||||
}
|
||||
return none;
|
||||
}
|
||||
|
||||
simulated function CauseMuzzleFlash(byte FireModeNum)
|
||||
{
|
||||
local vector vec;
|
||||
|
||||
if (MuzzleFlash == None)
|
||||
{
|
||||
AttachMuzzleFlash();
|
||||
}
|
||||
|
||||
if (MuzzleFlash != none)
|
||||
{
|
||||
vec.X = ChargePercentage;
|
||||
vec.Y = ChargePercentage;
|
||||
vec.Z = ChargePercentage;
|
||||
|
||||
MuzzleFlash.MuzzleFlash.PSC.SetVectorParameter(name("Charge"), vec);
|
||||
MuzzleFlash.CauseMuzzleFlash(FireModeNum);
|
||||
}
|
||||
|
||||
super.CauseMuzzleFlash(FireModeNum);
|
||||
}
|
||||
|
||||
simulated function int GetChargeLevel()
|
||||
{
|
||||
return Min(ChargeTime / ValueIncreaseTime, MaxChargeLevel);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
|
||||
PAWN ADJUST DAMAGE
|
||||
|
||||
****************************************************************/
|
||||
|
||||
// increase the instant hit damage based on the charge level
|
||||
simulated function int GetModifiedDamage(byte FireModeNum, optional vector RayDir)
|
||||
{
|
||||
local int ModifiedDamage;
|
||||
ModifiedDamage = super.GetModifiedDamage(FireModeNum, RayDir);
|
||||
return ModifiedDamage;
|
||||
}
|
||||
|
||||
state WeaponSingleFiring
|
||||
{
|
||||
/** Get whether we should play the reload anim as well or not */
|
||||
simulated function name GetWeaponFireAnim(byte FireModeNum)
|
||||
{
|
||||
if(bUsingSights)
|
||||
{
|
||||
return (bHasToLaunchEmptyAnim == false) ? SecondaryFireIronAnim : SecondaryFireIronAnimEmpty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (bHasToLaunchEmptyAnim == false) ? SecondaryFireIronAnim : SecondaryFireIronAnimEmpty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
//Gameplay Props
|
||||
MaxChargeTime=0.6
|
||||
AmmoIncreasePerCharge=1
|
||||
ValueIncreaseTime=0.1
|
||||
|
||||
//FOR LERPING DAMANGE
|
||||
MaxDamageByCharge=600
|
||||
MinDamageByCharge=60
|
||||
// FOV
|
||||
Meshfov=80
|
||||
MeshIronSightFOV=65 //52
|
||||
PlayerIronSightFOV=50 //80
|
||||
|
||||
// Depth of field
|
||||
DOF_FG_FocalRadius=150
|
||||
DOF_FG_MaxNearBlurSize=1
|
||||
|
||||
// Content
|
||||
PackageKey="HRG_BallisticBouncer"
|
||||
FirstPersonMeshName="wep_1p_hrg_ballisticbouncer_mesh.Wep_1stP_HRG_BallisticBouncer_Rig"
|
||||
FirstPersonAnimSetNames(0)="wep_1p_hrg_ballisticbouncer_anim.Wep_1stP_BallisticBouncer_Anim"
|
||||
PickupMeshName="wep_3p_hrg_ballisticbouncer_mesh.Wep_3rdP_HRG_BallisticBouncer_Pickup"
|
||||
AttachmentArchetypeName="wep_hrg_ballisticbouncer_arch.Wep_HRG_BallisticBouncer_3P"
|
||||
MuzzleFlashTemplateName="WEP_HRG_BallisticBouncer_ARCH.Wep_HRG_BallisticBouncer_MuzzleFlash"
|
||||
|
||||
Begin Object Name=FirstPersonMesh
|
||||
// new anim tree with skelcontrol to rotate cylinders
|
||||
AnimTreeTemplate=AnimTree'WEP_HRG_BallisticBouncer_ARCH.WEP_1stP_Animtree_HRG_BallisticBouncer'
|
||||
End Object
|
||||
|
||||
// Zooming/Position
|
||||
PlayerViewOffset=(X=0.0,Y=12,Z=-1)
|
||||
IronSightPosition=(X=0,Y=0,Z=0)
|
||||
|
||||
// Controls the rotation when Hans(the bastard) grabs you
|
||||
QuickWeaponDownRotation=(Pitch=-19192,Yaw=-11500,Roll=16384) // (Pitch=-19192,Yaw=-11000,Roll=16384)
|
||||
|
||||
// Ammo
|
||||
MagazineCapacity[0]=18
|
||||
SpareAmmoCapacity[0]=162
|
||||
InitialSpareMags[0]=3 //2
|
||||
AmmoPickupScale[0]=1.5 //1 //0.75
|
||||
bCanBeReloaded=true
|
||||
bReloadFromMagazine=true
|
||||
|
||||
// Recoil
|
||||
maxRecoilPitch=180
|
||||
minRecoilPitch=140
|
||||
maxRecoilYaw=150
|
||||
minRecoilYaw=-150
|
||||
RecoilRate=0.085
|
||||
RecoilMaxYawLimit=500
|
||||
RecoilMinYawLimit=65035
|
||||
RecoilMaxPitchLimit=900
|
||||
RecoilMinPitchLimit=65035
|
||||
RecoilISMaxYawLimit=75
|
||||
RecoilISMinYawLimit=65460
|
||||
RecoilISMaxPitchLimit=375
|
||||
RecoilISMinPitchLimit=65460
|
||||
RecoilViewRotationScale=0.25
|
||||
IronSightMeshFOVCompensationScale=1.5
|
||||
HippedRecoilModifier=1.5
|
||||
|
||||
// Inventory
|
||||
InventorySize=5
|
||||
GroupPriority=80 //75
|
||||
WeaponSelectTexture=Texture2D'wep_ui_hrg_ballisticbouncer_tex.UI_WeaponSelect_HRG_BallisticBouncer'
|
||||
|
||||
// DEFAULT_FIREMODE
|
||||
//FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Grenade' //@TODO: Replace me
|
||||
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_ShotgunSingle'
|
||||
FiringStatesArray(DEFAULT_FIREMODE)=MineReconstructorCharge
|
||||
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile
|
||||
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_HRG_BallisticBouncer'
|
||||
FireInterval(DEFAULT_FIREMODE)=+0.223 //+0.33
|
||||
InstantHitDamage(DEFAULT_FIREMODE)=100
|
||||
PenetrationPower(DEFAULT_FIREMODE)=0.0;
|
||||
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Bludgeon_HRG_BallisticBouncer_Shot'
|
||||
FireOffset=(X=39,Y=4.5,Z=-10)
|
||||
|
||||
// ALT_FIREMODE
|
||||
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponFiring
|
||||
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_None
|
||||
|
||||
// BASH_FIREMODE
|
||||
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HRG_BallisticBouncer'
|
||||
InstantHitDamage(BASH_FIREMODE)=27
|
||||
|
||||
// Fire Effects
|
||||
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_HRG_BallisticBouncer.Play_WEP_HRG_BallisticBouncer_3P_Start', FirstPersonCue=AkEvent'WW_WEP_HRG_BallisticBouncer.Play_WEP_HRG_BallisticBouncer_1P_Start')
|
||||
WeaponFireLoopEndSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_HRG_BallisticBouncer.Play_WEP_HRG_BallisticBouncer_3P_Shoot', FirstPersonCue=AkEvent'WW_WEP_HRG_BallisticBouncer.Play_WEP_HRG_BallisticBouncer_1P_Shoot')
|
||||
FullyChargedSound=(DefaultCue = AkEvent'WW_WEP_HRG_BallisticBouncer.Play_WEP_HRG_BallisticBouncer_Charged_3P', FirstPersonCue=AkEvent'WW_WEP_HRG_BallisticBouncer.Play_WEP_HRG_BallisticBouncer_Charged')
|
||||
|
||||
WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_HRG_BallisticBouncer.Play_WEP_HRG_BallisticBouncer_DryFire'
|
||||
|
||||
// Advanced (High RPM) Fire Effects
|
||||
bLoopingFireAnim(DEFAULT_FIREMODE)=true
|
||||
bLoopingFireSnd(DEFAULT_FIREMODE)=true
|
||||
SingleFireSoundIndex=FIREMODE_NONE
|
||||
|
||||
// Attachments
|
||||
bHasIronSights=true
|
||||
bHasFlashlight=false
|
||||
|
||||
AssociatedPerkClasses(0)= class'KFPerk_Support'
|
||||
|
||||
WeaponFireWaveForm=ForceFeedbackWaveform'FX_ForceFeedback_ARCH.Gunfire.Weak_Recoil'
|
||||
|
||||
ChargedEffect=ParticleSystem'WEP_HRG_BallisticBouncer_EMIT.FX_Mine_HRG_BallisticBouncer_FullCharge'
|
||||
|
||||
FullChargedTimerInterval=2.0f
|
||||
|
||||
// Weapon Upgrade stat boosts
|
||||
//WeaponUpgrades[1]=(IncrementDamage=1.1f,IncrementWeight=1)
|
||||
|
||||
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Weight, Add=1)))
|
||||
WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.3f), (Stat=EWUS_Weight, Add=2)))
|
||||
|
||||
FXScalingFactorByCharge = 0;
|
||||
MinScale=0.5
|
||||
MaxScale=1.5
|
||||
|
||||
bBlocked = false;
|
||||
|
||||
bAllowClientAmmoTracking = false;
|
||||
|
||||
ChargeStaticMesh = StaticMesh'WEP_HRG_BallisticBouncer_EMIT.HRG_BallisticBouncer_ball_MESH'
|
||||
MinProjPlaceholderScale = 2.0f;
|
||||
MaxProjPlaceholderScale = 3.0f;
|
||||
}
|
210
KFGameContent/Classes/KFWeap_HRG_MedicMissile.uc
Normal file
210
KFGameContent/Classes/KFWeap_HRG_MedicMissile.uc
Normal file
@ -0,0 +1,210 @@
|
||||
//=============================================================================
|
||||
// KFWeap_HRG_MedicMissile
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFWeap_HRG_MedicMissile extends KFWeap_GrenadeLauncher_Base;
|
||||
|
||||
/** Back blash explosion template. */
|
||||
var() GameExplosion ExplosionTemplate;
|
||||
|
||||
/** Holds an offest for spawning back blast effects. */
|
||||
var() vector BackBlastOffset;
|
||||
|
||||
/** Fires a projectile, but also does the back blast */
|
||||
simulated function CustomFire()
|
||||
{
|
||||
local KFExplosionActorReplicated ExploActor;
|
||||
local vector SpawnLoc;
|
||||
local rotator SpawnRot;
|
||||
|
||||
ProjectileFire();
|
||||
|
||||
if ( Instigator.Role < ROLE_Authority )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetBackBlastLocationAndRotation(SpawnLoc, SpawnRot);
|
||||
|
||||
// explode using the given template
|
||||
ExploActor = Spawn(class'KFExplosionActorReplicated', self,, SpawnLoc, SpawnRot,, true);
|
||||
if (ExploActor != None)
|
||||
{
|
||||
ExploActor.InstigatorController = Instigator.Controller;
|
||||
ExploActor.Instigator = Instigator;
|
||||
|
||||
// So we get backblash decal from this explosion
|
||||
ExploActor.bTraceForHitActorWhenDirectionalExplosion = true;
|
||||
|
||||
ExploActor.Explode(ExplosionTemplate, vector(SpawnRot));
|
||||
}
|
||||
|
||||
if ( bDebug )
|
||||
{
|
||||
DrawDebugCone(SpawnLoc, vector(SpawnRot), ExplosionTemplate.DamageRadius, ExplosionTemplate.DirectionalExplosionAngleDeg * DegToRad,
|
||||
ExplosionTemplate.DirectionalExplosionAngleDeg * DegToRad, 16, MakeColor(64,64,255,0), TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the world location for spawning back blast and the direction to send the back blast in
|
||||
*/
|
||||
simulated function GetBackBlastLocationAndRotation(out vector BlastLocation, out rotator BlastRotation)
|
||||
{
|
||||
local vector X, Y, Z;
|
||||
local Rotator ViewRotation;
|
||||
|
||||
if( Instigator != none )
|
||||
{
|
||||
if( bUsingSights )
|
||||
{
|
||||
ViewRotation = Instigator.GetViewRotation();
|
||||
|
||||
// Add in the free-aim rotation
|
||||
if ( KFPlayerController(Instigator.Controller) != None )
|
||||
{
|
||||
ViewRotation += KFPlayerController(Instigator.Controller).WeaponBufferRotation;
|
||||
}
|
||||
|
||||
GetAxes(ViewRotation, X, Y, Z);
|
||||
|
||||
BlastRotation = Rotator(Vector(ViewRotation) * -1);
|
||||
BlastLocation = Instigator.GetWeaponStartTraceLocation() + X * BackBlastOffset.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewRotation = Instigator.GetViewRotation();
|
||||
|
||||
// Add in the free-aim rotation
|
||||
if ( KFPlayerController(Instigator.Controller) != None )
|
||||
{
|
||||
ViewRotation += KFPlayerController(Instigator.Controller).WeaponBufferRotation;
|
||||
}
|
||||
|
||||
BlastRotation = Rotator(Vector(ViewRotation) * -1);
|
||||
BlastLocation = Instigator.GetPawnViewLocation() + (BackBlastOffset >> ViewRotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Locks the bolt bone in place to the open position (Called by animnotify) */
|
||||
simulated function ANIMNOTIFY_LockBolt()
|
||||
{
|
||||
// Consider us empty after every shot so the rocket gets hidden
|
||||
EmptyMagBlendNode.SetBlendTarget(1, 0);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ForceReloadTime=0.4f
|
||||
|
||||
// Inventory
|
||||
InventoryGroup=IG_Primary
|
||||
GroupPriority=100
|
||||
InventorySize=7
|
||||
WeaponSelectTexture=Texture2D'WEP_UI_HRG_MedicMissile_TEX.UI_WeaponSelect_HRG_MedicMissile'
|
||||
|
||||
// FOV
|
||||
MeshFOV=75
|
||||
MeshIronSightFOV=65
|
||||
PlayerIronSightFOV=70
|
||||
PlayerSprintFOV=95
|
||||
|
||||
// Depth of field
|
||||
DOF_FG_FocalRadius=50
|
||||
DOF_FG_MaxNearBlurSize=2.5
|
||||
|
||||
// Zooming/Position
|
||||
PlayerViewOffset=(X=10.0,Y=10,Z=-2)
|
||||
FastZoomOutTime=0.2
|
||||
|
||||
// Content
|
||||
PackageKey="HRG_MedicMissile"
|
||||
FirstPersonMeshName="WEP_1P_HRG_MedicMissile_MESH.Wep_1stP_HRG_MedicMissile_Rig"
|
||||
FirstPersonAnimSetNames(0)="WEP_1P_HRG_MedicMissile_ANIM.Wep_1stP_HRG_MedicMissile_Anim"
|
||||
PickupMeshName="WEP_3P_HRG_MedicMissile_MESH.Wep_HRG_MedicMissile_Pickup"
|
||||
AttachmentArchetypeName="WEP_HRG_MedicMissile_ARCH.Wep_HRG_MedicMissile_3P"
|
||||
MuzzleFlashTemplateName="WEP_HRG_MedicMissile_ARCH.Wep_HRG_MedicMissile_MuzzleFlash"
|
||||
|
||||
// Zooming/Position
|
||||
IronSightPosition=(X=0,Y=0,Z=0)
|
||||
|
||||
// Ammo
|
||||
MagazineCapacity[0]=1
|
||||
SpareAmmoCapacity[0]=22
|
||||
InitialSpareMags[0]=6
|
||||
AmmoPickupScale[0]=4.0
|
||||
bCanBeReloaded=true
|
||||
bReloadFromMagazine=true
|
||||
|
||||
// Recoil
|
||||
maxRecoilPitch=800
|
||||
minRecoilPitch=675
|
||||
maxRecoilYaw=400
|
||||
minRecoilYaw=-400
|
||||
RecoilRate=0.085
|
||||
RecoilBlendOutRatio=0.35
|
||||
RecoilMaxYawLimit=500
|
||||
RecoilMinYawLimit=65035
|
||||
RecoilMaxPitchLimit=1500
|
||||
RecoilMinPitchLimit=64785
|
||||
RecoilISMaxYawLimit=50
|
||||
RecoilISMinYawLimit=65485
|
||||
RecoilISMaxPitchLimit=500
|
||||
RecoilISMinPitchLimit=65485
|
||||
RecoilViewRotationScale=0.8
|
||||
FallingRecoilModifier=1.5
|
||||
HippedRecoilModifier=1.25
|
||||
|
||||
// DEFAULT_FIREMODE
|
||||
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'UI_FireModes_TEX.UI_FireModeSelect_Rocket'
|
||||
FiringStatesArray(DEFAULT_FIREMODE)=WeaponSingleFireAndReload
|
||||
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Custom
|
||||
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Rocket_HRG_MedicMissile'
|
||||
FireInterval(DEFAULT_FIREMODE)=+0.25
|
||||
InstantHitDamage(DEFAULT_FIREMODE)=100.0
|
||||
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_HRG_MedicMissile'
|
||||
Spread(DEFAULT_FIREMODE)=0.025
|
||||
FireOffset=(X=20,Y=4.0,Z=-3)
|
||||
BackBlastOffset=(X=-20,Y=4.0,Z=-3)
|
||||
|
||||
// ALT_FIREMODE
|
||||
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSingleFiring
|
||||
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_None
|
||||
|
||||
// Back blash explosion settings. Using archetype so that clients can serialize the content
|
||||
// without loading the 1st person weapon content (avoid 'Begin Object')!
|
||||
ExplosionTemplate=KFGameExplosion'WEP_HRG_MedicMissile_ARCH.Wep_HRG_MedicMissile_BackBlastExplosion'
|
||||
|
||||
// BASH_FIREMODE
|
||||
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HRG_MedicMissile'
|
||||
InstantHitDamage(BASH_FIREMODE)=27
|
||||
|
||||
// Fire Effects
|
||||
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_HRG_MedicMissile.Play_WEP_HRG_MedicMissile_3P_Shoot', FirstPersonCue=AkEvent'WW_WEP_HRG_MedicMissile.Play_WEP_HRG_MedicMissile_1P_Shoot')
|
||||
|
||||
//@todo: add akevent when we have it
|
||||
WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_HRG_MedicMissile.Play_WEP_HRG_MedicMissile_DryFire'
|
||||
|
||||
// Animation
|
||||
bHasFireLastAnims=true
|
||||
IdleFidgetAnims=(Guncheck_v1, Guncheck_v2)
|
||||
|
||||
BonesToLockOnEmpty=(RW_Grenade1)
|
||||
|
||||
// Attachments
|
||||
bHasIronSights=true
|
||||
bHasFlashlight=false
|
||||
|
||||
AssociatedPerkClasses(0)=class'KFPerk_FieldMedic'
|
||||
|
||||
WeaponFireWaveForm=ForceFeedbackWaveform'FX_ForceFeedback_ARCH.Gunfire.Heavy_Recoil_SingleShot'
|
||||
|
||||
// Weapon Upgrade stat boosts
|
||||
//WeaponUpgrades[1]=(IncrementDamage=1.1f,IncrementWeight=1)
|
||||
|
||||
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.1f), (Stat=EWUS_Weight, Add=1)))
|
||||
}
|
@ -76,6 +76,7 @@ var Array<bool> HolographicSightUseDefaultByChargeLevel;
|
||||
simulated function PostBeginPlay()
|
||||
{
|
||||
CurrentChargeLevel=0;
|
||||
|
||||
if( WeaponMICs.Length > `SONICGUN_MIC_SIGHT_INDEX )
|
||||
{
|
||||
if (!HolographicSightUseDefaultByChargeLevel[0])
|
||||
@ -94,7 +95,6 @@ simulated function PostBeginPlay()
|
||||
simulated function AltFireMode()
|
||||
{
|
||||
// skip super
|
||||
|
||||
if (!Instigator.IsLocallyControlled())
|
||||
{
|
||||
return;
|
||||
@ -127,19 +127,6 @@ simulated function name GetReloadAnimName(bool bTacticalReload)
|
||||
}
|
||||
}
|
||||
|
||||
simulated function StartFire(byte FireModeNum)
|
||||
{
|
||||
if (FireModeNum == ALTFIRE_FIREMODE)
|
||||
{
|
||||
if (!IsCanIncrementCharge())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
super.StartFire(FireModeNum);
|
||||
}
|
||||
|
||||
/*********************************************************************************************
|
||||
* State WeaponSonicGunCharging
|
||||
* The weapon is in this state while detonating a charge
|
||||
@ -184,7 +171,7 @@ simulated state WeaponSonicGunSingleFiring extends WeaponSingleFiring
|
||||
local vector UsedKickMomentum;
|
||||
|
||||
// Push the player back when they fire a fully charged sonic blast
|
||||
if (Instigator != none && CurrentChargeLevel == 1 ) //2
|
||||
if (Instigator != none && CurrentChargeLevel == MaxChargeLevel )
|
||||
{
|
||||
UsedKickMomentum.X = -FullyChargedKickMomentum;
|
||||
|
||||
@ -208,21 +195,26 @@ simulated state WeaponSonicGunSingleFiring extends WeaponSingleFiring
|
||||
|
||||
simulated function FireAmmunition()
|
||||
{
|
||||
super.FireAmmunition();
|
||||
CurrentChargeLevel=0;
|
||||
if (CurrentFireMode == ALTFIRE_FIREMODE)
|
||||
{
|
||||
// Instant shoot: always use max level
|
||||
CurrentChargeLevel = MaxChargeLevel;
|
||||
}
|
||||
|
||||
if( WeaponMICs.Length > `SONICGUN_MIC_SIGHT_INDEX )
|
||||
{
|
||||
if (!HolographicSightUseDefaultByChargeLevel[0])
|
||||
if (!HolographicSightUseDefaultByChargeLevel[CurrentChargeLevel])
|
||||
{
|
||||
WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].SetVectorParameterValue('Vector_Center_Color_A', HolographicSightByChargeLevel[0]);
|
||||
WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].SetVectorParameterValue('Vector_Scanline_Color_Mult', HolographicSightScanlineByChargeLevel[0]);
|
||||
WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].SetVectorParameterValue('Vector_Center_Color_A', HolographicSightByChargeLevel[CurrentChargeLevel]);
|
||||
WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].SetVectorParameterValue('Vector_Scanline_Color_Mult', HolographicSightScanlineByChargeLevel[CurrentChargeLevel]);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].ClearParameterValues();
|
||||
}
|
||||
}
|
||||
|
||||
super.FireAmmunition();
|
||||
CurrentChargeLevel=0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,7 +311,7 @@ simulated function float GetForceReloadDelay()
|
||||
simulated function KFProjectile SpawnProjectile( class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir )
|
||||
{
|
||||
local KFProjectile SpawnedProjectile;
|
||||
local int ProjDamage;
|
||||
local int ProjDamage;
|
||||
|
||||
// Spawn projectile
|
||||
SpawnedProjectile = Spawn( KFProjClass, Self,, RealStartLoc,,,true);
|
||||
@ -329,9 +321,9 @@ simulated function KFProjectile SpawnProjectile( class<KFProjectile> KFProjClass
|
||||
// these properties are replicated via TakeHitInfo
|
||||
if ( InstantHitDamage.Length > CurrentFireMode && InstantHitDamageTypes.Length > CurrentFireMode )
|
||||
{
|
||||
InstantHitDamage[DEFAULT_FIREMODE] = SonicBlastDamageByChargeLevel[CurrentChargeLevel];
|
||||
InstantHitMomentum[DEFAULT_FIREMODE]=SonicBlastMomentumByChargeLevel[CurrentChargeLevel];
|
||||
InstantHitDamageTypes[DEFAULT_FIREMODE]=SonicBlastDamageTypeByChargeLevel[CurrentChargeLevel];
|
||||
InstantHitDamage[CurrentFiremode] = SonicBlastDamageByChargeLevel[CurrentChargeLevel];
|
||||
InstantHitMomentum[CurrentFiremode]=SonicBlastMomentumByChargeLevel[CurrentChargeLevel];
|
||||
InstantHitDamageTypes[CurrentFiremode]=SonicBlastDamageTypeByChargeLevel[CurrentChargeLevel];
|
||||
|
||||
ProjDamage = GetModifiedDamage(CurrentFireMode);
|
||||
SpawnedProjectile.Damage = ProjDamage;
|
||||
@ -341,7 +333,7 @@ simulated function KFProjectile SpawnProjectile( class<KFProjectile> KFProjClass
|
||||
// Set the penetration power for this projectile
|
||||
// because of clientside hit detection, we need two variables --
|
||||
// one that replicates on init and one that updates but doesn't replicate
|
||||
PenetrationPower[DEFAULT_FIREMODE]=SonicBlastPenetrationPowerByChargeLevel[CurrentChargeLevel];
|
||||
PenetrationPower[CurrentFireMode]=SonicBlastPenetrationPowerByChargeLevel[CurrentChargeLevel];
|
||||
SpawnedProjectile.InitialPenetrationPower = GetInitialPenetrationPower(CurrentFireMode);
|
||||
SpawnedProjectile.PenetrationPower = SpawnedProjectile.InitialPenetrationPower;
|
||||
|
||||
@ -356,7 +348,7 @@ simulated function KFProjectile SpawnProjectile( class<KFProjectile> KFProjClass
|
||||
//Overriding to make KFProjectile Class for default fire mode to be dependant on charge level
|
||||
simulated function class<KFProjectile> GetKFProjectileClass()
|
||||
{
|
||||
if (CurrentFireMode == DEFAULT_FIREMODE)
|
||||
if (CurrentFireMode == DEFAULT_FIREMODE || CurrentFireMode == ALTFIRE_FIREMODE)
|
||||
{
|
||||
return SonicBlastProjectileClassByChargeLevel[CurrentChargeLevel];
|
||||
}
|
||||
@ -377,7 +369,7 @@ simulated function float GetUpgradedPenetration(optional int FireMode = DEFAULT_
|
||||
//Overriding to change shot sounds for default fire mode to be dependant on charge level
|
||||
simulated function PlayFireEffects( byte FireModeNum, optional vector HitLocation )
|
||||
{
|
||||
WeaponFireSnd[DEFAULT_FIREMODE]=SonicBlastFireSoundByChargeLevel[CurrentChargeLevel];
|
||||
WeaponFireSnd[CurrentFireMode]=SonicBlastFireSoundByChargeLevel[CurrentChargeLevel];
|
||||
super.PlayFireEffects(FireModeNum, HitLocation);
|
||||
}
|
||||
|
||||
@ -398,7 +390,7 @@ simulated function ProcessInstantHitEx(byte FiringMode, ImpactInfo Impact, optio
|
||||
IndexMomentumMultiplierByZed = MomentumMultiplierByZedArray.Find('ZedClassName', Impact.HitActor.Class.Name);
|
||||
if (IndexMomentumMultiplierByZed != INDEX_NONE)
|
||||
{
|
||||
InstantHitMomentum[DEFAULT_FIREMODE] *= MomentumMultiplierByZedArray[IndexMomentumMultiplierByZed].MomentumMultiplier;
|
||||
InstantHitMomentum[CurrentFireMode] *= MomentumMultiplierByZedArray[IndexMomentumMultiplierByZed].MomentumMultiplier;
|
||||
}
|
||||
}
|
||||
|
||||
@ -452,8 +444,8 @@ defaultproperties
|
||||
DOF_FG_MaxNearBlurSize=3.5
|
||||
|
||||
// Ammo
|
||||
MagazineCapacity[0]=12 //8
|
||||
SpareAmmoCapacity[0]=96 //72
|
||||
MagazineCapacity[0]=10 //12 //8
|
||||
SpareAmmoCapacity[0]=90 //96 //72
|
||||
InitialSpareMags[0]=1
|
||||
bCanBeReloaded=true
|
||||
bReloadFromMagazine=true
|
||||
@ -500,9 +492,16 @@ defaultproperties
|
||||
FallingMomentumReduction=0.5
|
||||
|
||||
// ALTFIRE_FIREMODE (remote detonate)
|
||||
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSonicGunCharging
|
||||
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Custom
|
||||
AmmoCost(ALTFIRE_FIREMODE)=0
|
||||
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSonicGunSingleFiring
|
||||
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Projectile
|
||||
WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_SonicBlastFullyCharged_HRG_SonicGun'
|
||||
FireInterval(ALTFIRE_FIREMODE)=0.75
|
||||
InstantHitDamage(ALTFIRE_FIREMODE)=125
|
||||
InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_HRG_SonicGun_SonicBlastFullyCharged'
|
||||
InstantHitMomentum(ALTFIRE_FIREMODE)=200000
|
||||
Spread(ALTFIRE_FIREMODE)=0.005
|
||||
PenetrationPower(ALTFIRE_FIREMODE)=2.0
|
||||
AmmoCost(ALTFIRE_FIREMODE)=1
|
||||
|
||||
// BASH_FIREMODE
|
||||
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HRG_SonicGun'
|
||||
|
417
KFGameContent/Classes/KFWeap_HVStormCannon.uc
Normal file
417
KFGameContent/Classes/KFWeap_HVStormCannon.uc
Normal file
@ -0,0 +1,417 @@
|
||||
//=============================================================================
|
||||
// KFWeap_HVStormCannon
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFWeap_HVStormCannon extends KFWeap_ScopedBase;
|
||||
|
||||
var const float TrackingInstanceTimeDelaySeconds;
|
||||
var const float TrackingRadius;
|
||||
var const int TrackingDamageValue;
|
||||
var const array<float> TrackingDamage;
|
||||
|
||||
var int WeaponID;
|
||||
|
||||
struct HVStormCannon_ProjectileTrackingInstance
|
||||
{
|
||||
var int NumberHits;
|
||||
var float TimeNextJump;
|
||||
var KFPawn_Monster LastTarget;
|
||||
var array<KFPawn_Monster> HitTargets;
|
||||
var Controller Instigator; // Instigator that shot the bullet
|
||||
var byte IDCounter;
|
||||
|
||||
structdefaultproperties
|
||||
{
|
||||
NumberHits=0
|
||||
TimeNextJump=0
|
||||
LastTarget=none
|
||||
Instigator=none
|
||||
}
|
||||
};
|
||||
|
||||
var array<HVStormCannon_ProjectileTrackingInstance> HVStormCannon_ProjectileTracking;
|
||||
|
||||
event PostBeginPlay()
|
||||
{
|
||||
local int Counter;
|
||||
local KFPlayerController KFPC;
|
||||
|
||||
Super.PostBeginPlay();
|
||||
|
||||
Counter = 0;
|
||||
foreach WorldInfo.AllControllers(class'KFPlayerController', KFPC)
|
||||
{
|
||||
++Counter;
|
||||
if (KFPC == Instigator.Controller)
|
||||
{
|
||||
WeaponID = Counter * 1000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function ProcessInstantHitEx(byte FiringMode, ImpactInfo Impact, optional int NumHits, optional out float out_PenetrationVal, optional int ImpactNum )
|
||||
{
|
||||
local int HitZoneIdx;
|
||||
local KFPawn_Monster Target;
|
||||
local HVStormCannon_ProjectileTrackingInstance NewTrackingInstance;
|
||||
local KFPlayerController KFPC;
|
||||
|
||||
if (Role == ROLE_Authority)
|
||||
{
|
||||
Target = KFPawn_Monster(Impact.HitActor);
|
||||
if (Target != none && !Target.bIsHeadless)
|
||||
{
|
||||
HitZoneIdx = Target.HitZones.Find('ZoneName', Impact.HitInfo.BoneName);
|
||||
if (HitZoneIdx == HZI_Head && Target.IsAliveAndWell())
|
||||
{
|
||||
NewTrackingInstance.TimeNextJump = WorldInfo.TimeSeconds + TrackingInstanceTimeDelaySeconds;
|
||||
NewTrackingInstance.LastTarget = Target;
|
||||
NewTrackingInstance.HitTargets.AddItem(Target);
|
||||
NewTrackingInstance.Instigator = Instigator.Controller;
|
||||
|
||||
KFPC = KFPlayerController(Instigator.Controller);
|
||||
NewTrackingInstance.IDCounter = KFPC.StormCannonIDCounter;
|
||||
|
||||
if (KFPC.StormCannonIDCounter < 255)
|
||||
{
|
||||
++KFPC.StormCannonIDCounter;
|
||||
}
|
||||
else
|
||||
{
|
||||
KFPC.StormCannonIDCounter = 0;
|
||||
}
|
||||
|
||||
// We simulate EMP affliction on Server, we can't use the affliction itself because it's duration is super hard to control
|
||||
// To completely sync with the logic of TrackingInstanceTimeDelaySeconds
|
||||
|
||||
// Simulate start EMP affliction
|
||||
Target.bEmpPanicked = true;
|
||||
Target.OnStackingAfflictionChanged(AF_EMP);
|
||||
|
||||
HVStormCannon_ProjectileTracking.AddItem(NewTrackingInstance);
|
||||
|
||||
StartBeamVFX(Target, NewTrackingInstance.IDCounter);
|
||||
}
|
||||
}
|
||||
}
|
||||
super.ProcessInstantHitEx( FiringMode, Impact, NumHits, out_PenetrationVal, ImpactNum );
|
||||
}
|
||||
|
||||
function KFPawn_Monster SearchClosestTarget(HVStormCannon_ProjectileTrackingInstance CurrentTrackingInstance)
|
||||
{
|
||||
local KFPawn_Monster CurrentTarget, BestTarget;
|
||||
local TraceHitInfo HitInfo;
|
||||
|
||||
local float BestDistance;
|
||||
local float Distance;
|
||||
|
||||
local vector ReferenceLocation;
|
||||
|
||||
local vector HitLocation, HitNormal;
|
||||
local Actor HitActor;
|
||||
|
||||
ReferenceLocation = CurrentTrackingInstance.LastTarget.Mesh.GetBoneLocation('head');
|
||||
|
||||
//CurrentTrackingInstance.LastTarget.DrawDebugSphere(ReferenceLocation, CurrentTrackingInstance.LastTarget.GetCollisionRadius() + TrackingRadius, 10, 0, 255, 0, true);
|
||||
|
||||
foreach CollidingActors(class'KFPawn_Monster'
|
||||
, CurrentTarget
|
||||
, CurrentTrackingInstance.LastTarget.GetCollisionRadius() + TrackingRadius
|
||||
, ReferenceLocation
|
||||
, true,, HitInfo)
|
||||
{
|
||||
if (!CurrentTarget.IsAliveAndWell() || CurrentTarget.bIsCloaking)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the target does have map geometry in between..
|
||||
HitActor = Trace(HitLocation, HitNormal, CurrentTarget.Mesh.GetBoneLocation('head'), ReferenceLocation,,,,TRACEFLAG_Bullet);
|
||||
|
||||
if (HitActor != none && KFPawn_Monster(HitActor) == none)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't hit again targets..
|
||||
if (CurrentTrackingInstance.HitTargets.Find(CurrentTarget) != INDEX_NONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// The closest..
|
||||
Distance = VSizeSq(ReferenceLocation - CurrentTarget.Mesh.GetBoneLocation('head'));
|
||||
|
||||
if (BestTarget == none)
|
||||
{
|
||||
BestTarget = CurrentTarget;
|
||||
BestDistance = Distance;
|
||||
}
|
||||
else if (BestDistance > Distance)
|
||||
{
|
||||
BestTarget = CurrentTarget;
|
||||
BestDistance = Distance;
|
||||
}
|
||||
}
|
||||
|
||||
return BestTarget;
|
||||
}
|
||||
|
||||
function UpdateTracking()
|
||||
{
|
||||
local int i;
|
||||
local KFPawn_Monster NextTarget;
|
||||
local bool bClear;
|
||||
local TraceHitInfo HitInfo;
|
||||
|
||||
HitInfo.BoneName = 'head'; // we force headshot
|
||||
|
||||
for (i = HVStormCannon_ProjectileTracking.Length - 1; i >= 0; i--)
|
||||
{
|
||||
bClear = false;
|
||||
|
||||
if (WorldInfo.TimeSeconds >= HVStormCannon_ProjectileTracking[i].TimeNextJump)
|
||||
{
|
||||
// Simulate stop EMP affliction
|
||||
HVStormCannon_ProjectileTracking[i].LastTarget.bEmpPanicked = false;
|
||||
HVStormCannon_ProjectileTracking[i].LastTarget.OnStackingAfflictionChanged(AF_EMP);
|
||||
|
||||
if (HVStormCannon_ProjectileTracking[i].NumberHits < TrackingDamage.length)
|
||||
{
|
||||
NextTarget = SearchClosestTarget(HVStormCannon_ProjectileTracking[i]);
|
||||
if (NextTarget != none)
|
||||
{
|
||||
HVStormCannon_ProjectileTracking[i].TimeNextJump = WorldInfo.TimeSeconds + TrackingInstanceTimeDelaySeconds;
|
||||
|
||||
// Simulate start EMP affliction
|
||||
NextTarget.bEmpPanicked = true;
|
||||
NextTarget.OnStackingAfflictionChanged(AF_EMP);
|
||||
|
||||
StartBeamVFX(NextTarget, HVStormCannon_ProjectileTracking[i].IDCounter);
|
||||
|
||||
HVStormCannon_ProjectileTracking[i].LastTarget = NextTarget;
|
||||
HVStormCannon_ProjectileTracking[i].HitTargets.AddItem(NextTarget);
|
||||
|
||||
NextTarget.TakeDamage(TrackingDamageValue * TrackingDamage[HVStormCannon_ProjectileTracking[i].NumberHits]
|
||||
, HVStormCannon_ProjectileTracking[i].Instigator
|
||||
, NextTarget.Mesh.GetBoneLocation('head')
|
||||
, vect(0,0,0)
|
||||
, class'KFDT_HVStormCannonSpread'
|
||||
, HitInfo);
|
||||
|
||||
++HVStormCannon_ProjectileTracking[i].NumberHits;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there are no targets we finish early
|
||||
bClear = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Max hits reached
|
||||
bClear = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bClear)
|
||||
{
|
||||
StopBeamVFX(HVStormCannon_ProjectileTracking[i].IDCounter);
|
||||
HVStormCannon_ProjectileTracking.Remove(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated event Tick(float DeltaTime)
|
||||
{
|
||||
Super.Tick(DeltaTime);
|
||||
|
||||
if (Role == ROLE_Authority)
|
||||
{
|
||||
UpdateTracking();
|
||||
}
|
||||
|
||||
if (Role != ROLE_Authority || WorldInfo.NetMode == NM_Standalone)
|
||||
{
|
||||
UpdateAmmoCounter();
|
||||
}
|
||||
}
|
||||
|
||||
simulated function StartBeamVFX(KFPawn_Monster KFPM, byte ID)
|
||||
{
|
||||
local KFPlayerController KFPC;
|
||||
|
||||
if (Role == ROLE_Authority)
|
||||
{
|
||||
// Send RPC to all players
|
||||
foreach WorldInfo.AllControllers(class'KFPlayerController', KFPC)
|
||||
{
|
||||
KFPC.AddStormCannonVFX(KFPM, GetID(ID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function StopBeamVFX(byte ID)
|
||||
{
|
||||
local KFPlayerController KFPC;
|
||||
|
||||
if (Role == ROLE_Authority)
|
||||
{
|
||||
// Send RPC to all players
|
||||
foreach WorldInfo.AllControllers(class'KFPlayerController', KFPC)
|
||||
{
|
||||
KFPC.RemoveStormCannonVFX(GetID(ID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function int GetID(byte ID)
|
||||
{
|
||||
return WeaponID + ID;
|
||||
}
|
||||
|
||||
simulated function KFProjectile SpawnProjectile( class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir )
|
||||
{
|
||||
local vector SocketLocation;
|
||||
local rotator SocketRotation;
|
||||
local vector SpawnLocation;
|
||||
local vector SpawnDirection;
|
||||
|
||||
if(bUsingSights && MySkelMesh.GetSocketWorldLocationAndRotation('MuzzleFlash_Scope', SocketLocation, SocketRotation, 0))
|
||||
{
|
||||
SpawnLocation = SocketLocation;
|
||||
SpawnDirection = vector(SocketRotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
SpawnLocation = RealStartLoc;
|
||||
SpawnDirection = AimDir;
|
||||
}
|
||||
|
||||
return super.SpawnProjectile(KFProjClass, SpawnLocation, SpawnDirection);
|
||||
}
|
||||
|
||||
simulated function UpdateAmmoCounter()
|
||||
{
|
||||
local float PercentageAmmo;
|
||||
|
||||
PercentageAmmo = float((AmmoCount[0] - 1)) / float(MagazineCapacity[0]);
|
||||
|
||||
WeaponMICs[3].SetScalarParameterValue('opacity', PercentageAmmo);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
// FOV
|
||||
MeshFOV=70
|
||||
MeshIronSightFOV=52
|
||||
PlayerIronSightFOV=70
|
||||
|
||||
// Depth of field
|
||||
DOF_FG_FocalRadius=0
|
||||
DOF_FG_MaxNearBlurSize=2.5
|
||||
|
||||
// Content
|
||||
PackageKey="HVStormCannon"
|
||||
FirstPersonMeshName="WEP_1P_HVStormCannon_MESH.Wep_1stP_HVStormCannon_Rig"
|
||||
FirstPersonAnimSetNames(0)="WEP_1P_HVStormCannon_ANIM.Wep_1p_HVStormCannon_Anim"
|
||||
PickupMeshName="WEP_3P_HVStormCannon_MESH.Wep_HRG_HVStormCannon_Pickup"
|
||||
AttachmentArchetypeName = "WEP_HVStormCannon_ARCH.HVStormCannon_3P"
|
||||
MuzzleFlashTemplateName="WEP_HVStormCannon_ARCH.Wep_HVStormCannon_MuzzleFlash"
|
||||
|
||||
// Ammo
|
||||
MagazineCapacity[0]=8
|
||||
SpareAmmoCapacity[0]=96
|
||||
InitialSpareMags[0]=2
|
||||
bCanBeReloaded=true
|
||||
bReloadFromMagazine=true
|
||||
|
||||
// Zooming/Position
|
||||
PlayerViewOffset=(X=12.0,Y=13,Z=-2) //x7
|
||||
IronSightPosition=(X=-5,Y=-0.01,Z=0.30) //X=-5,Y=-0.019,Z=0.22
|
||||
|
||||
// AI warning system
|
||||
bWarnAIWhenAiming=true
|
||||
AimWarningDelay=(X=0.4f, Y=0.8f)
|
||||
AimWarningCooldown=0.0f
|
||||
|
||||
// Recoil
|
||||
maxRecoilPitch=300
|
||||
minRecoilPitch=200
|
||||
maxRecoilYaw=150
|
||||
minRecoilYaw=-150
|
||||
RecoilRate=0.08
|
||||
RecoilMaxYawLimit=500
|
||||
RecoilMinYawLimit=1000
|
||||
RecoilMaxPitchLimit=1250
|
||||
RecoilMinPitchLimit=1500
|
||||
RecoilISMaxYawLimit=50
|
||||
RecoilISMinYawLimit=1000
|
||||
RecoilISMaxPitchLimit=500
|
||||
RecoilISMinPitchLimit=1000
|
||||
RecoilViewRotationScale=0.6
|
||||
IronSightMeshFOVCompensationScale=1.5
|
||||
|
||||
// Inventory
|
||||
InventorySize=8
|
||||
GroupPriority=125
|
||||
WeaponSelectTexture=Texture2D'wep_ui_hvstormcannon_tex.UI_WeaponSelect_HVStormCannon'
|
||||
|
||||
// DEFAULT_FIREMODE
|
||||
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletSingle'
|
||||
FiringStatesArray(DEFAULT_FIREMODE)=WeaponFiring
|
||||
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile
|
||||
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_HVStormCannon'
|
||||
InstantHitDamage(DEFAULT_FIREMODE)=150
|
||||
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_EMP_HVStormCannon'
|
||||
|
||||
// ALT_FIREMODE
|
||||
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponFiring
|
||||
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_None
|
||||
|
||||
FireInterval(DEFAULT_FIREMODE)=0.4 // 150 RPM // 0.8 // 75 RPM
|
||||
Spread(DEFAULT_FIREMODE)=0.005
|
||||
PenetrationPower(DEFAULT_FIREMODE)=0
|
||||
FireOffset=(X=30,Y=16,Z=-8)
|
||||
|
||||
// BASH_FIREMODE
|
||||
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HVStormCannon'
|
||||
InstantHitDamage(BASH_FIREMODE)=27
|
||||
|
||||
// Fire Effects
|
||||
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_HVStormCannon.Play_WEP_HVStormCannon_Shoot_3P', FirstPersonCue=AkEvent'WW_WEP_HVStormCannon.Play_WEP_HVStormCannon_Shoot_1P')
|
||||
WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_SA_Winchester.Play_WEP_SA_Winchester_Handling_DryFire'
|
||||
|
||||
// Attachments
|
||||
bHasIronSights=true
|
||||
bHasFlashlight=false
|
||||
|
||||
AssociatedPerkClasses(0)=class'KFPerk_Sharpshooter'
|
||||
|
||||
TrackingInstanceTimeDelaySeconds=0.15
|
||||
TrackingRadius=200.0 // in cm, this is added to the Radius of the Zed that's spreading
|
||||
TrackingDamageValue=150
|
||||
|
||||
TrackingDamage = (0.75f, 0.5f, 0.25f)
|
||||
|
||||
WeaponID=0
|
||||
|
||||
// Scope Render
|
||||
// 2D scene capture
|
||||
Begin Object Name=SceneCapture2DComponent0
|
||||
//TextureTarget=TextureRenderTarget2D'Wep_Mat_Lib.WEP_ScopeLense_Target'
|
||||
FieldOfView=12.5 //23.0 // "1.5X" = 35.0(our real world FOV determinant)/1.5
|
||||
End Object
|
||||
|
||||
ScopedSensitivityMod=8.0 //16.0
|
||||
ScopeLenseMICTemplate=MaterialInstanceConstant'WEP_1P_HVStormCannon_MAT.Wep_1stP_HVStormCannon_Lens_MIC'
|
||||
ScopeMICIndex = 1
|
||||
|
||||
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1)))
|
||||
|
||||
NumBloodMapMaterials=4
|
||||
}
|
@ -20,6 +20,9 @@ defaultproperties
|
||||
FirstPersonMeshName="WEP_1P_Demo_Knife_MESH.Wep_1stP_Demo_Knife_Rig"
|
||||
AttachmentArchetypeName="WEP_Demo_Knife_ARCH.Wep_Demo_Knife_3P"
|
||||
|
||||
Spread(DEFAULT_FIREMODE)=1.0
|
||||
Spread(ALTFIRE_FIREMODE)=1.0
|
||||
|
||||
Begin Object Name=FirstPersonMesh
|
||||
AnimSets(0)=AnimSet'WEP_1P_CommandoKnife_ANIM.Wep_1stP_CommKnife_Anim'
|
||||
End Object
|
||||
|
@ -74,7 +74,6 @@ simulated state WeaponDoubleBarrelFiring extends WeaponSingleFiring
|
||||
|
||||
simulated function BeginState(name PreviousStateName)
|
||||
{
|
||||
local vector UsedKickMomentum;
|
||||
local KFMapInfo KFMI;
|
||||
Super.BeginState(PreviousStateName);
|
||||
|
||||
@ -84,24 +83,8 @@ simulated state WeaponDoubleBarrelFiring extends WeaponSingleFiring
|
||||
return;
|
||||
}
|
||||
|
||||
// Push the player back when they fire both barrels
|
||||
if (Instigator != none )
|
||||
{
|
||||
UsedKickMomentum.X = -DoubleBarrelKickMomentum;
|
||||
|
||||
if( Instigator.Physics == PHYS_Falling )
|
||||
{
|
||||
UsedKickMomentum = UsedKickMomentum >> Instigator.GetViewRotation();
|
||||
UsedKickMomentum *= FallingMomentumReduction;
|
||||
}
|
||||
else
|
||||
{
|
||||
UsedKickMomentum = UsedKickMomentum >> Instigator.Rotation;
|
||||
UsedKickMomentum.Z = 0;
|
||||
}
|
||||
|
||||
Instigator.AddVelocity(UsedKickMomentum,Instigator.Location,none);
|
||||
}
|
||||
// Push the player back when they fire both barrels
|
||||
ApplyKickMomentum(DoubleBarrelKickMomentum, FallingMomentumReduction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,6 @@ simulated state WeaponQuadBarrelFiring extends WeaponSingleFiring
|
||||
|
||||
simulated function BeginState(name PreviousStateName)
|
||||
{
|
||||
local vector UsedKickMomentum;
|
||||
local KFMapInfo KFMI;
|
||||
Super.BeginState(PreviousStateName);
|
||||
|
||||
@ -96,51 +95,17 @@ simulated state WeaponQuadBarrelFiring extends WeaponSingleFiring
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Push the player back when they fire both barrels
|
||||
if (Instigator != none)
|
||||
{
|
||||
UsedKickMomentum.X = -DoubleBarrelKickMomentum;
|
||||
|
||||
if (Instigator.Physics == PHYS_Falling)
|
||||
{
|
||||
UsedKickMomentum = UsedKickMomentum >> Instigator.GetViewRotation();
|
||||
UsedKickMomentum *= FallingMomentumReduction;
|
||||
}
|
||||
else
|
||||
{
|
||||
UsedKickMomentum = UsedKickMomentum >> Instigator.Rotation;
|
||||
UsedKickMomentum.Z = 0;
|
||||
}
|
||||
|
||||
Instigator.AddVelocity(UsedKickMomentum,Instigator.Location,none);
|
||||
}
|
||||
ApplyKickMomentum(DoubleBarrelKickMomentum, FallingMomentumReduction);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function BeginState(name PreviousStateName)
|
||||
{
|
||||
local vector UsedKickMomentum;
|
||||
Super.BeginState(PreviousStateName);
|
||||
|
||||
// Push the player back when they fire both barrels
|
||||
if (Instigator != none)
|
||||
{
|
||||
UsedKickMomentum.X = -DoubleBarrelKickMomentum;
|
||||
|
||||
if (Instigator.Physics == PHYS_Falling)
|
||||
{
|
||||
UsedKickMomentum = UsedKickMomentum >> Instigator.GetViewRotation();
|
||||
UsedKickMomentum *= FallingMomentumReduction;
|
||||
}
|
||||
else
|
||||
{
|
||||
UsedKickMomentum = UsedKickMomentum >> Instigator.Rotation;
|
||||
UsedKickMomentum.Z = 0;
|
||||
}
|
||||
|
||||
Instigator.AddVelocity(UsedKickMomentum,Instigator.Location,none);
|
||||
}
|
||||
ApplyKickMomentum(DoubleBarrelKickMomentum, FallingMomentumReduction);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
|
564
KFGameContent/Classes/KFWeap_ZedMKIII.uc
Normal file
564
KFGameContent/Classes/KFWeap_ZedMKIII.uc
Normal file
@ -0,0 +1,564 @@
|
||||
//=============================================================================
|
||||
// KFWeap_ZedMKIII
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFWeap_ZedMKIII extends KFWeap_RifleBase;
|
||||
|
||||
/** Number of shots required in a row before firing a rocket */
|
||||
var const byte NumBulletsBeforeRocket;
|
||||
/** Minimum distance a target can be from the crosshair to be considered for lock on */
|
||||
var const float MinTargetDistFromCrosshairSQ;
|
||||
/** Dot product FOV that targets need to stay within to maintain a target lock */
|
||||
var const float MaxLockMaintainFOVDotThreshold;
|
||||
/** Time interval for updating radar positions */
|
||||
var const float RadarUpdateEntitiesTime;
|
||||
/** Distance the radar can track enemies */
|
||||
var const float MaxRadarDistance;
|
||||
/** Speed at which the radar moves (rad/sec) */
|
||||
var const float RadarSpeed;
|
||||
/** */
|
||||
var const byte RadarTargetSize;
|
||||
|
||||
var transient array<KFPawn_Monster> EnemiesInRadar;
|
||||
var transient byte NumShotsFired;
|
||||
var transient float PrevAngle;
|
||||
var transient bool bRequiresRadarClear;
|
||||
|
||||
var class<KFGFxWorld_WeaponRadar> RadarUIClass;
|
||||
var KFGFxWorld_WeaponRadar RadarUI;
|
||||
|
||||
var const float MaxTargetAngle;
|
||||
var transient float CosTargetAngle;
|
||||
|
||||
var transient bool LastShotIsRocket;
|
||||
var WeaponFireSndInfo NormalFireSound;
|
||||
var WeaponFireSndInfo RocketFireSound;
|
||||
|
||||
simulated event PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
|
||||
CosTargetAngle = Cos(MaxTargetAngle * DegToRad);
|
||||
}
|
||||
|
||||
simulated function AltFireMode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an potential target TA determine if we can lock on to it. By default only allow locking on
|
||||
* to pawns.
|
||||
*/
|
||||
simulated function bool CanLockOnTo(Actor TA)
|
||||
{
|
||||
Local KFPawn PawnTarget;
|
||||
|
||||
PawnTarget = KFPawn(TA);
|
||||
|
||||
// Make sure the pawn is legit, isn't dead, and isn't already at full health
|
||||
if ((TA == None) || !TA.bProjTarget || TA.bDeleteMe || (PawnTarget == None) ||
|
||||
(TA == Instigator) || (PawnTarget.Health <= 0) ||
|
||||
!HasAmmo(DEFAULT_FIREMODE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure and only lock onto players on the same team
|
||||
return !WorldInfo.GRI.OnSameTeam(Instigator, TA);
|
||||
}
|
||||
|
||||
/** Finds a new lock on target */
|
||||
simulated function bool FindTarget( out KFPawn RecentlyLocked )
|
||||
{
|
||||
local KFPawn P, BestTargetLock;
|
||||
local byte TeamNum;
|
||||
local vector AimStart, AimDir, TargetLoc, Projection, DirToPawn, LinePoint;
|
||||
local Actor HitActor;
|
||||
local float PointDistSQ, Score, BestScore, TargetSizeSQ;
|
||||
|
||||
TeamNum = Instigator.GetTeamNum();
|
||||
AimStart = GetSafeStartTraceLocation();
|
||||
AimDir = vector( GetAdjustedAim(AimStart) );
|
||||
BestScore = 0.f;
|
||||
|
||||
foreach WorldInfo.AllPawns( class'KFPawn', P )
|
||||
{
|
||||
if (!CanLockOnTo(P))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Want alive pawns and ones we already don't have locked
|
||||
if( P != none && P.IsAliveAndWell() && P.GetTeamNum() != TeamNum )
|
||||
{
|
||||
TargetLoc = GetLockedTargetLoc( P );
|
||||
Projection = TargetLoc - AimStart;
|
||||
DirToPawn = Normal( Projection );
|
||||
|
||||
// Filter out pawns too far from center
|
||||
|
||||
if( AimDir dot DirToPawn < CosTargetAngle )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check to make sure target isn't too far from center
|
||||
PointDistToLine( TargetLoc, AimDir, AimStart, LinePoint );
|
||||
PointDistSQ = VSizeSQ( LinePoint - P.Location );
|
||||
|
||||
TargetSizeSQ = P.GetCollisionRadius() * 2.f;
|
||||
TargetSizeSQ *= TargetSizeSQ;
|
||||
|
||||
// Make sure it's not obstructed
|
||||
HitActor = class'KFAIController'.static.ActorBlockTest(self, TargetLoc, AimStart,, true, true);
|
||||
if( HitActor != none && HitActor != P )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Distance from target has much more impact on target selection score
|
||||
Score = VSizeSQ( Projection ) + PointDistSQ;
|
||||
if( BestScore == 0.f || Score < BestScore )
|
||||
{
|
||||
BestTargetLock = P;
|
||||
BestScore = Score;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( BestTargetLock != none )
|
||||
{
|
||||
RecentlyLocked = BestTargetLock;
|
||||
|
||||
// Plays sound/FX when locking on to a new target
|
||||
// PlayTargetLockOnEffects();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RecentlyLocked = none;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Adjusts our destination target impact location */
|
||||
static simulated function vector GetLockedTargetLoc( Pawn P )
|
||||
{
|
||||
// Go for the chest, but just in case we don't have something with a chest bone we'll use collision and eyeheight settings
|
||||
if( P.Mesh.SkeletalMesh != none && P.Mesh.bAnimTreeInitialised )
|
||||
{
|
||||
if( P.Mesh.MatchRefBone('Spine2') != INDEX_NONE )
|
||||
{
|
||||
return P.Mesh.GetBoneLocation( 'Spine2' );
|
||||
}
|
||||
else if( P.Mesh.MatchRefBone('Spine1') != INDEX_NONE )
|
||||
{
|
||||
return P.Mesh.GetBoneLocation( 'Spine1' );
|
||||
}
|
||||
|
||||
return P.Mesh.GetPosition() + ((P.CylinderComponent.CollisionHeight + (P.BaseEyeHeight * 0.5f)) * vect(0,0,1)) ;
|
||||
}
|
||||
|
||||
// General chest area, fallback
|
||||
return P.Location + ( vect(0,0,1) * P.BaseEyeHeight * 0.75f );
|
||||
}
|
||||
|
||||
simulated function PlayFireEffects( byte FireModeNum, optional vector HitLocation )
|
||||
{
|
||||
if (LastShotIsRocket)
|
||||
{
|
||||
super.PlayFireEffects(ALTFIRE_FIREMODE, HitLocation);
|
||||
|
||||
WeaponPlayFireSound(WeaponFireSnd[ALTFIRE_FIREMODE].DefaultCue, WeaponFireSnd[ALTFIRE_FIREMODE].FirstPersonCue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
super.PlayFireEffects(FireModeNum, HitLocation);
|
||||
}
|
||||
|
||||
simulated function Projectile ProjectileFire()
|
||||
{
|
||||
if (CurrentFireMode == DEFAULT_FIREMODE || CurrentFireMode == ALTFIRE_FIREMODE)
|
||||
{
|
||||
if (NumShotsFired >= NumBulletsBeforeRocket)
|
||||
{
|
||||
WeaponFireSnd[ALTFIRE_FIREMODE]=RocketFireSound;
|
||||
CurrentFireMode = ALTFIRE_FIREMODE;
|
||||
NumShotsFired = 0;
|
||||
LastShotIsRocket = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
WeaponFireSnd[ALTFIRE_FIREMODE]=NormalFireSound;
|
||||
CurrentFireMode = DEFAULT_FIREMODE;
|
||||
++NumShotsFired;
|
||||
LastShotIsRocket = false;
|
||||
}
|
||||
}
|
||||
|
||||
return super.ProjectileFire();
|
||||
}
|
||||
|
||||
/** Spawn projectile is called once for each rocket fired. In burst mode it will cycle through targets until it runs out */
|
||||
simulated function KFProjectile SpawnProjectile( class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir )
|
||||
{
|
||||
local KFProj_Rocket_ZedMKIII RocketProj;
|
||||
local KFPawn TargetPawn;
|
||||
|
||||
if ( CurrentFireMode == ALTFIRE_FIREMODE )
|
||||
{
|
||||
FindTarget(TargetPawn);
|
||||
|
||||
RocketProj = KFProj_Rocket_ZedMKIII( super.SpawnProjectile( class<KFProjectile>(WeaponProjectiles[CurrentFireMode]) , RealStartLoc, AimDir) );
|
||||
|
||||
if( RocketProj != none )
|
||||
{
|
||||
// We'll aim our rocket at a target here otherwise we will spawn a dumbfire rocket at the end of the function
|
||||
if ( TargetPawn != none)
|
||||
{
|
||||
//Seek to new target, then remove it
|
||||
RocketProj.SetLockedTarget( TargetPawn );
|
||||
}
|
||||
}
|
||||
|
||||
// Resetting the firemode to default.
|
||||
CurrentFireMode = DEFAULT_FIREMODE;
|
||||
|
||||
return RocketProj;
|
||||
}
|
||||
|
||||
return super.SpawnProjectile( KFProjClass, RealStartLoc, AimDir );
|
||||
}
|
||||
|
||||
/*********************************************************************************************
|
||||
* state WeaponFiring
|
||||
* This is the default Firing State. It's performed on both the client and the server.
|
||||
*********************************************************************************************/
|
||||
simulated state WeaponFiring
|
||||
{
|
||||
// Reset num shots fired when stop shooting
|
||||
simulated event EndState( Name NextStateName)
|
||||
{
|
||||
super.EndState(NextStateName);
|
||||
|
||||
NumShotsFired = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************
|
||||
* Radar implementation
|
||||
*********************************************************************************************/
|
||||
|
||||
simulated state WeaponEquipping
|
||||
{
|
||||
simulated function BeginState(Name PreviousStateName)
|
||||
{
|
||||
super.BeginState(PreviousStateName);
|
||||
|
||||
PrevAngle = 0.0f;
|
||||
|
||||
if (WorldInfo.NetMode == NM_Client || WorldInfo.NetMode == NM_Standalone)
|
||||
{
|
||||
StartRadar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated state WeaponPuttingDown
|
||||
{
|
||||
simulated function BeginState(Name PreviousStateName)
|
||||
{
|
||||
super.BeginState(PreviousStateName);
|
||||
|
||||
if (WorldInfo.NetMode == NM_Client || WorldInfo.NetMode == NM_Standalone)
|
||||
{
|
||||
StopRadar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function StartRadar()
|
||||
{
|
||||
SetTimer(RadarUpdateEntitiesTime, true, nameof(UpdateRadarEntities));
|
||||
}
|
||||
|
||||
simulated function StopRadar()
|
||||
{
|
||||
ClearTimer(nameof(UpdateRadarEntities));
|
||||
EnemiesInRadar.Length = 0;
|
||||
}
|
||||
|
||||
simulated function UpdateRadarEntities()
|
||||
{
|
||||
local KFPawn_Monster KFPM;
|
||||
local int RadarIndex;
|
||||
local bool bIsAlive;
|
||||
|
||||
bIsAlive = false;
|
||||
|
||||
// Get nearby enemies
|
||||
foreach CollidingActors(class'KFPawn_Monster', KFPM, MaxRadarDistance, Location, true)
|
||||
{
|
||||
RadarIndex = FindEnemyTrackedByRadar(KFPM);
|
||||
bIsAlive = KFPM.IsAliveAndWell();
|
||||
|
||||
if (RadarIndex == INDEX_NONE)
|
||||
{
|
||||
if (bIsAlive)
|
||||
{
|
||||
EnemiesInRadar.AddItem(KFPM);
|
||||
}
|
||||
}
|
||||
else if(!bIsAlive)
|
||||
{
|
||||
EnemiesInRadar.RemoveItem(KFPM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function int FindEnemyTrackedByRadar(KFPawn_Monster KFPM)
|
||||
{
|
||||
local int i;
|
||||
|
||||
for (i = 0; i < EnemiesInRadar.Length; ++i)
|
||||
{
|
||||
if (KFPM == EnemiesInRadar[i] )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return INDEX_NONE;
|
||||
}
|
||||
|
||||
simulated function Tick(float Delta)
|
||||
{
|
||||
local float DistanceSqrd;
|
||||
local vector Distance, ScreenDirection, UILocation;
|
||||
local rotator ViewRotation;
|
||||
local int i;
|
||||
local array<vector> RadarElements;
|
||||
|
||||
super.Tick(Delta);
|
||||
|
||||
if (RadarUI != none)
|
||||
{
|
||||
if (bRequiresRadarClear)
|
||||
{
|
||||
RadarUI.Clear();
|
||||
}
|
||||
|
||||
if (EnemiesInRadar.Length == 0)
|
||||
{
|
||||
if (bRequiresRadarClear)
|
||||
{
|
||||
bRequiresRadarClear = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ViewRotation = Rotation;
|
||||
ViewRotation.Yaw *= -1;
|
||||
ViewRotation.Pitch = 0;
|
||||
ViewRotation.Roll = 0;
|
||||
|
||||
RadarElements.Length = 0;
|
||||
|
||||
for (i = EnemiesInRadar.Length - 1; i >= 0; --i)
|
||||
{
|
||||
if (!EnemiesInRadar[i].IsAliveAndWell())
|
||||
{
|
||||
EnemiesInRadar.Remove(i, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
Distance = EnemiesInRadar[i].Location - Location;
|
||||
DistanceSqrd = VSizeSQ(Distance);
|
||||
|
||||
if (DistanceSqrd > MaxRadarDistance * MaxRadarDistance)
|
||||
{
|
||||
EnemiesInRadar.Remove(i, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
Distance.Z = 0;
|
||||
ScreenDirection = Distance >> ViewRotation;
|
||||
|
||||
UILocation.X = ScreenDirection.Y / MaxRadarDistance;
|
||||
UILocation.Y = ScreenDirection.X / MaxRadarDistance;
|
||||
|
||||
RadarElements.AddItem(UILocation);
|
||||
}
|
||||
|
||||
if (RadarElements.length > 0)
|
||||
{
|
||||
RadarUI.AddRadarElements(RadarElements);
|
||||
bRequiresRadarClear = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Radar UI */
|
||||
reliable client function ClientWeaponSet(bool bOptionalSet, optional bool bDoNotActivate)
|
||||
{
|
||||
local KFInventoryManager KFIM;
|
||||
|
||||
super.ClientWeaponSet(bOptionalSet, bDoNotActivate);
|
||||
|
||||
if (RadarUI == none && RadarUIClass != none)
|
||||
{
|
||||
KFIM = KFInventoryManager(InvManager);
|
||||
if (KFIM != none)
|
||||
{
|
||||
//Create the screen's UI piece
|
||||
RadarUI = KFGFxWorld_WeaponRadar(KFIM.GetRadarUIMovie(RadarUIClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ItemRemovedFromInvManager()
|
||||
{
|
||||
local KFInventoryManager KFIM;
|
||||
|
||||
Super.ItemRemovedFromInvManager();
|
||||
|
||||
if (RadarUI != none)
|
||||
{
|
||||
KFIM = KFInventoryManager(InvManager);
|
||||
if (KFIM != none)
|
||||
{
|
||||
//Create the screen's UI piece
|
||||
KFIM.RemoveRadarUIMovie(RadarUI.class);
|
||||
|
||||
RadarUI.Close();
|
||||
RadarUI = none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** */
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
// FOV
|
||||
MeshFOV=70
|
||||
MeshIronSightFOV=30 //52
|
||||
PlayerIronSightFOV=70
|
||||
|
||||
// Depth of field
|
||||
DOF_FG_FocalRadius=85
|
||||
DOF_FG_MaxNearBlurSize=2.5
|
||||
|
||||
// Zooming/Position
|
||||
IronSightPosition=(X=14,Y=0.05,Z=-0.5) // x=-8,Y=0.01,Z=0.85
|
||||
PlayerViewOffset=(X=22,Y=12,Z=-2.5)
|
||||
|
||||
// Content
|
||||
PackageKey="ZedMKIII"
|
||||
FirstPersonMeshName="WEP_1P_ZEDMKIII_MESH.Wep_1stP_ZEDMKIII_Rig"
|
||||
FirstPersonAnimSetNames(0)="WEP_1P_ZEDMKIII_ANIM.Wep_1stP_ZEDMKIII_Anim"
|
||||
PickupMeshName="WEP_3P_ZEDMKIII_MESH.Wep_3rdP_ZEDMKIII_Pickup"
|
||||
AttachmentArchetypeName = "WEP_ZEDMKIII_ARCH.Wep_ZEDMKIII_3P"
|
||||
MuzzleFlashTemplateName="WEP_ZEDMKIII_ARCH.Wep_ZEDMKIII_MuzzleFlash"
|
||||
|
||||
// Ammo
|
||||
MagazineCapacity[0]=100
|
||||
SpareAmmoCapacity[0]=400
|
||||
InitialSpareMags[0]=1
|
||||
bCanBeReloaded=true
|
||||
bReloadFromMagazine=true
|
||||
|
||||
bCanRefillSecondaryAmmo=0
|
||||
|
||||
// Recoil
|
||||
maxRecoilPitch=125
|
||||
minRecoilPitch=100
|
||||
maxRecoilYaw=120
|
||||
minRecoilYaw=-100
|
||||
RecoilRate=0.085
|
||||
RecoilMaxYawLimit=500
|
||||
RecoilMinYawLimit=65035
|
||||
RecoilMaxPitchLimit=900
|
||||
RecoilMinPitchLimit=65035
|
||||
RecoilISMaxYawLimit=75
|
||||
RecoilISMinYawLimit=65460
|
||||
RecoilISMaxPitchLimit=375
|
||||
RecoilISMinPitchLimit=65460
|
||||
IronSightMeshFOVCompensationScale=4.0
|
||||
|
||||
// Inventory
|
||||
InventorySize=9
|
||||
GroupPriority=125
|
||||
WeaponSelectTexture=Texture2D'wep_ui_zedmkiii_tex.UI_WeaponSelect_ZEDMKIII'
|
||||
|
||||
// DEFAULT_FIREMODE
|
||||
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletAuto'
|
||||
FiringStatesArray(DEFAULT_FIREMODE)=WeaponFiring
|
||||
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile
|
||||
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_ZedMKIII'
|
||||
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Microwave_ZedMKIII'
|
||||
|
||||
// ALT_FIREMODE
|
||||
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSingleFiring
|
||||
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Projectile
|
||||
WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Rocket_ZedMKIII'
|
||||
InstantHitDamage(ALTFIRE_FIREMODE)=100
|
||||
InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_ZedMKIII_Rocket'
|
||||
Spread(ALTFIRE_FIREMODE)=0.025
|
||||
AmmoCost(ALTFIRE_FIREMODE)=1
|
||||
|
||||
FireInterval(DEFAULT_FIREMODE)=0.15 // 400 RPM //0.12 // 500 RPM //+0.1 // 600 RPM
|
||||
Spread(DEFAULT_FIREMODE)=0.0085
|
||||
PenetrationPower(DEFAULT_FIREMODE)=4.0
|
||||
InstantHitDamage(DEFAULT_FIREMODE)=50.0
|
||||
FireOffset=(X=30,Y=8,Z=-15)
|
||||
|
||||
// BASH_FIREMODE
|
||||
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_ZedMKIII'
|
||||
InstantHitDamage(BASH_FIREMODE)=27
|
||||
|
||||
// Fire Effects
|
||||
NormalFireSound=(DefaultCue=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Shoot_Single_3P', FirstPersonCue=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Shoot_Single_1P')
|
||||
RocketFireSound=(DefaultCue=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Shoot_Rocket_3P', FirstPersonCue=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Shoot_Rocket_1P')
|
||||
|
||||
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Shoot_LP_3P', FirstPersonCue=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Shoot_LP_1P')
|
||||
WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Shoot_Single_3P', FirstPersonCue=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Shoot_Single_1P')
|
||||
WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Handling_DryFire'
|
||||
WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Handling_DryFire'
|
||||
|
||||
// Advanced (High RPM) Fire Effects
|
||||
bLoopingFireAnim(DEFAULT_FIREMODE)=true
|
||||
bLoopingFireSnd(DEFAULT_FIREMODE)=true
|
||||
WeaponFireLoopEndSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Shoot_LP_End_3P', FirstPersonCue=AkEvent'WW_WEP_ZEDMKIII.Play_WEP_ZEDMKIII_Shoot_LP_End_1P')
|
||||
SingleFireSoundIndex=ALTFIRE_FIREMODE
|
||||
|
||||
// Attachments
|
||||
bHasIronSights=true
|
||||
bHasFlashlight=false
|
||||
|
||||
AssociatedPerkClasses(0)=class'KFPerk_Demolitionist'
|
||||
|
||||
NumBulletsBeforeRocket=6
|
||||
NumShotsFired=0
|
||||
MinTargetDistFromCrosshairSQ=2500.0f
|
||||
MaxLockMaintainFOVDotThreshold=0.36f
|
||||
|
||||
RadarUpdateEntitiesTime=0.1f
|
||||
MaxRadarDistance=2000
|
||||
RadarSpeed=2.0f
|
||||
RadarTargetSize=10.0f
|
||||
|
||||
RadarUIClass=class'KFGFxWorld_WeaponRadar'
|
||||
|
||||
NumBloodMapMaterials=2
|
||||
bRequiresRadarClear=false
|
||||
|
||||
MaxTargetAngle=10
|
||||
|
||||
LastShotIsRocket=false
|
||||
}
|
Reference in New Issue
Block a user