241 lines
6.0 KiB
Ucode
241 lines
6.0 KiB
Ucode
|
//=============================================================================
|
||
|
// 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];
|
||
|
|
||
|
// 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 );
|
||
|
}
|
||
|
|
||
|
/** Adjusts movement/physics of projectile.
|
||
|
* 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;
|
||
|
|
||
|
if ( WorldInfo.NetMode == NM_Client )
|
||
|
return;
|
||
|
|
||
|
if (Pawn(BouncedOff) == none)
|
||
|
{
|
||
|
P = Spawn(class'KFDroppedPickup_Cash',,, Location, Rotation,, false);
|
||
|
|
||
|
if (P == none)
|
||
|
{
|
||
|
for (i = 0; i < `KFPROJ_DOSH_CACHED_LOCATION; ++i)
|
||
|
{
|
||
|
P = Spawn(class'KFDroppedPickup_Cash',,, PreviousLocations[i], PreviousRotations[i],, false);
|
||
|
if (P != none)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
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;
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
else if ( Other != Instigator && Other.bCanBeDamaged && (!Other.bWorldGeometry || !Other.bStatic) )
|
||
|
{
|
||
|
KFP = KFPawn( Other );
|
||
|
if ( KFP != None )
|
||
|
{
|
||
|
// check/ignore repeat touch events
|
||
|
if( CheckRepeatingTouch(Other) )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ProcessBulletTouch(Other, HitLocation, HitNormal);
|
||
|
|
||
|
Bounce(HitNormal, Other);
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ProcessDestructibleTouchOnBounce( Other, HitLocation, HitNormal );
|
||
|
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();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
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
|
||
|
}
|