2021-12-09 19:33:06 +03:00
//=============================================================================
// KFProj_Dosh
//=============================================================================
// Projectile for the doshinegun
//=============================================================================
// Killing Floor 2
// Copyright (C) 2021 Tripwire Interactive LLC
//=============================================================================
class KFProj _Dosh extends KFProj _RicochetBullet
hidedropdown ;
` define KFPROJ_DOSH_CACHED_LOCATION 20
var PrimitiveComponent DroppedPickupMesh ;
/** Dampen amount for every bounce */
var ( ) float DampenFactor ;
/** Dampen amount for parallel angle to velocity */
var ( ) float DampenFactorParallel ;
var transient Vector PreviousLocations [ ` KFPROJ_DOSH_CACHED_LOCATION];
var transient rotator PreviousRotations [ ` KFPROJ_DOSH_CACHED_LOCATION];
2022-03-29 20:30:25 +03:00
var transient Vector Ceiling ;
2021-12-09 19:33:06 +03:00
// Make sure that last location always exists.
simulated event PostBeginPlay ( )
{
Super . PostBeginPlay ( ) ;
}
event Tick ( float DeltaTime )
{
local int i ;
for ( i = ` KFPROJ_DOSH_CACHED_LOCATION - 1; i > 0; --i)
{
PreviousLocations [ i ] = PreviousLocations [ i - 1 ] ;
PreviousRotations [ i ] = PreviousRotations [ i - 1 ] ;
}
if ( ` KFPROJ_DOSH_CACHED_LOCATION > 0)
{
PreviousLocations [ 0 ] = Location ;
PreviousRotations [ 0 ] = Rotation ;
}
}
/ * *
* Give a little bounce
* /
simulated event HitWall ( vector HitNormal , Actor Wall , PrimitiveComponent WallComp )
{
local TraceHitInfo HitInfo ;
// check to make sure we didn't hit a pawn
if ( Pawn ( Wall ) == none )
{
if ( ! Wall . bStatic && Wall . bCanBeDamaged && ( DamageRadius == 0 || bDamageDestructiblesOnTouch ) && ! CheckRepeatingTouch ( Wall ) )
{
HitInfo . HitComponent = WallComp ;
HitInfo . Item = INDEX _None ;
Wall . TakeDamage ( Damage , InstigatorController , Location , MomentumTransfer * Normal ( Velocity ) , MyDamageType , HitInfo , self ) ;
}
}
Bounce ( HitNormal , Wall ) ;
}
/ * * A d j u s t s m o v e m e n t / p h y s i c s o f p r o j e c t i l e .
* Returns true if projectile actually bounced / was allowed to bounce * /
simulated function bool Bounce ( vector HitNormal , Actor BouncedOff )
{
Velocity = DampingFactor * ( Velocity - 2.0 * HitNormal * ( Velocity dot HitNormal ) ) ;
if ( WorldInfo . NetMode != NM _DedicatedServer )
{
// do the impact effects
` ImpactEffectManager.PlayImpactEffects(Location, Instigator, HitNormal, ImpactEffects );
}
// also done from ProcessDestructibleTouchOnBounce. update LastBounced to solve problem with bouncing rapidly between world/non-world geometry
LastBounced . Actor = BouncedOff ;
LastBounced . Time = WorldInfo . TimeSeconds ;
SpawnDosh ( BouncedOff ) ;
Destroy ( ) ;
return true ;
}
function SpawnDosh ( Actor BouncedOff )
{
local KFDroppedPickup _Cash P ;
local int i ;
2022-03-29 20:30:25 +03:00
local Vector Pos ;
local rotator Rot ;
2021-12-09 19:33:06 +03:00
if ( WorldInfo . NetMode == NM _Client )
return ;
if ( Pawn ( BouncedOff ) == none )
{
2022-03-29 20:30:25 +03:00
Pos = Location ;
Rot = Rotation ;
P = Spawn ( class 'KFDroppedPickup_Cash' , , , Pos , Rot , , false ) ;
2021-12-09 19:33:06 +03:00
if ( P == none )
{
for ( i = 0 ; i < ` KFPROJ_DOSH_CACHED_LOCATION; ++i)
{
2022-03-29 20:30:25 +03:00
Pos = PreviousLocations [ i ] ;
Rot = PreviousRotations [ i ] ;
P = Spawn ( class 'KFDroppedPickup_Cash' , , , Pos , Rot , , false ) ;
2021-12-09 19:33:06 +03:00
if ( P != none )
{
break ;
}
}
}
2022-03-29 20:30:25 +03:00
// DrawDebugSphere( Pos, 20, 8, 0, 255, 255, true );
if ( P != none && RelocateFromCeiling ( Pos ) )
{
P . Destroy ( ) ;
if ( Ceiling . Z > - 10000 )
{
// DrawDebugSphere( Ceiling, 22, 8, 255, 255, 0, true );
P = Spawn ( class 'KFDroppedPickup_Cash' , , , Ceiling , Rot , , false ) ;
Velocity = vect ( 0 , 0 , 0 ) ;
}
}
2021-12-09 19:33:06 +03:00
}
else
{
P = Spawn ( class 'KFDroppedPickup_Cash' , , , Location , Rotation , , true ) ;
}
if ( P == None )
{
Destroy ( ) ;
}
else
{
P . SetPhysics ( PHYS _Falling ) ;
P . InventoryClass = class 'KFInventory_Money' ;
P . Inventory = Instigator . CreateInventory ( P . InventoryClass ) ;
P . Velocity = Velocity ;
P . Instigator = Instigator ;
P . SetPickupMesh ( DroppedPickupMesh ) ;
P . SetPickupParticles ( none ) ;
P . CashAmount = class 'KFWeap_AssaultRifle_Doshinegun' . default . DoshCost ;
}
}
//==============
// Touching
// Overridden to get bouncing off of destructible meshes
simulated function ProcessTouch ( Actor Other , Vector HitLocation , Vector HitNormal )
{
local KFPawn KFP ;
local KFPawn _Human KFPH ;
local KFPlayerReplicationInfo KFPRI ;
2022-06-14 18:52:40 +03:00
local TraceHitInfo HitInfo ;
2021-12-09 19:33:06 +03:00
KFPH = KFPawn _Human ( Other ) ;
if ( KFPH != none && KFPH != Instigator )
{
KFPRI = KFPlayerReplicationInfo ( KFPH . PlayerReplicationInfo ) ;
if ( KFPRI != none )
{
KFPRI . AddDosh ( class 'KFWeap_AssaultRifle_Doshinegun' . default . DoshCost ) ;
Destroy ( ) ;
return ;
}
}
2022-06-14 18:52:40 +03:00
else if ( Other != Instigator && Other . bCanBeDamaged )
2021-12-09 19:33:06 +03:00
{
KFP = KFPawn ( Other ) ;
if ( KFP != None )
{
// check/ignore repeat touch events
if ( CheckRepeatingTouch ( Other ) )
{
return ;
}
ProcessBulletTouch ( Other , HitLocation , HitNormal ) ;
Bounce ( HitNormal , Other ) ;
return ;
}
else
{
2022-06-14 18:52:40 +03:00
HitInfo . HitComponent = LastTouchComponent ;
HitInfo . Item = INDEX _None ; // force TraceComponent on fractured meshes
Other . TakeDamage ( Damage , InstigatorController , HitLocation , MomentumTransfer * Normal ( Velocity ) , MyDamageType , HitInfo , self ) ; // special cases for types of destructibles, bShouldBreakSolidGlassOnBounce
2021-12-09 19:33:06 +03:00
return ;
}
}
super . ProcessTouch ( Other , HitLocation , HitNormal ) ;
}
simulated function SyncOriginalLocation ( )
{
local Actor HitActor ;
local vector HitLocation , HitNormal ;
local TraceHitInfo HitInfo ;
if ( Role < ROLE _Authority && Instigator != none && Instigator . IsLocallyControlled ( ) )
{
HitActor = Trace ( HitLocation , HitNormal , OriginalLocation , Location , , , HitInfo , TRACEFLAG _Bullet ) ;
if ( HitActor != none )
{
Bounce ( HitNormal , HitActor ) ;
}
}
Super . SyncOriginalLocation ( ) ;
}
2022-03-29 20:30:25 +03:00
simulated function bool RelocateFromCeiling ( Vector Pos )
{
local Actor HitActorVolume , HitActorWorld , HitActorVolumeBack ;
local Vector HitLocationVolume , HitLocationWorld ;
local Vector HitNormalUnused ;
HitActorWorld = Owner . Trace ( HitLocationWorld , HitNormalUnused , Pos - vect ( 0 , 0 , 10000 ) , Pos , false , , , TRACEFLAG _Bullet ) ;
if ( HitActorWorld != none )
{
HitActorVolume = KFWeapon ( Owner ) . DoTraceNative ( HitLocationVolume , Pos , Pos - vect ( 0 , 0 , 10000 ) ) ;
if ( HitActorVolume == none || ( HitLocationWorld . Z + 80 ) > HitLocationVolume . Z || IsZero ( HitLocationVolume - Pos ) )
{
return false ;
}
// DrawDebugSphere( HitLocationWorld , 32, 8, 0, 255, 0, true );
// DrawDebugSphere( HitLocationVolume, 30, 8, 255, 0, 0, true );
HitLocationWorld += vect ( 0 , 0 , 1 ) ;
HitActorVolumeBack = KFWeapon ( Owner ) . DoTraceNative ( HitLocationVolume , HitLocationWorld , HitLocationWorld + vect ( 0 , 0 , 10000 ) ) ;
if ( HitActorVolumeBack != none && ! IsZero ( HitLocationVolume - HitLocationWorld ) )
{
// DrawDebugSphere( HitLocationVolume, 28, 8, 255, 255, 0, true );
Ceiling = HitLocationVolume - vect ( 0 , 0 , 10 ) ;
return true ;
}
}
Ceiling = Vect ( 0 , 0 , - 10000 ) ;
return true ;
}
2021-12-09 19:33:06 +03:00
defaultproperties
{
MaxSpeed = 7500.0 //5000.0
Speed = 7500.0 //5000.0
GravityScale = 0.57 //0.4
Physics = PHYS _Falling
TossZ = 100 //150
MomentumTransfer = 50000.0
DamageRadius = 0
bWarnAIWhenFired = true
BouncesLeft = 1
DampingFactor = 0.1
DampenFactor = 0.250000
DampenFactorParallel = 0.400000
LifeSpan = 120 //8
bNetTemporary = False
NetPriority = 5
NetUpdateFrequency = 200
ProjFlightTemplate = ParticleSystem 'WEP_Doshinegun_EMIT.PS_Trail'
ProjFlightTemplateZedTime = ParticleSystem 'WEP_Doshinegun_EMIT.PS_Trail'
ImpactEffects = KFImpactEffectInfo 'WEP_Doshinegun_ARCH.Dosh_Impact'
Begin Object Class = SkeletalMeshComponent Name = PickupMesh0
SkeletalMesh = SkeletalMesh 'GP_Mesh.dosh_SM'
PhysicsAsset = PhysicsAsset 'GP_Mesh.dosh_SM_Physics'
BlockNonZeroExtent = false
CastShadow = false
End Object
DroppedPickupMesh = PickupMesh0
}