247 lines
6.6 KiB
Ucode
247 lines
6.6 KiB
Ucode
//=============================================================================
|
|
// KFMGA_Target
|
|
//=============================================================================
|
|
// Actor used as an individual target in any of the target minigames. Calls
|
|
// back into the base target game that spawned it when it takes valid
|
|
// damage.
|
|
//=============================================================================
|
|
// Killing Floor 2
|
|
// Copyright (C) 2015 Tripwire Interactive LLC
|
|
// - Dan Weiss
|
|
//=============================================================================
|
|
|
|
class KFMGA_Target extends Actor
|
|
implements(KFInterface_MinigameTarget);
|
|
|
|
/** Visual component of the target */
|
|
var() StaticMeshComponent Mesh;
|
|
|
|
/** Collision cylinder*/
|
|
var() CylinderComponent CollisionCylinder;
|
|
|
|
/** How many hits before the game is notified of "death" */
|
|
var() repnotify int NumHits;
|
|
|
|
/** Rigged target game that spawned this target. Used to sync owner chain on remote clients */
|
|
var repnotify KFMG_TargetGame SpawnerOwner;
|
|
|
|
/** Index this was added in to make sure arrays stay fully in sync */
|
|
var repnotify int SpawnerOwnerIndex;
|
|
|
|
/** Whether or not to ignore radius damage sources (ex: grenades) */
|
|
var() bool bIgnoreRadiusDamage;
|
|
|
|
/** Whether or not target is active */
|
|
var repnotify bool bActiveTarget;
|
|
|
|
/** List of acceptable damage types */
|
|
var array< class<DamageType> > AcceptedDamageTypes;
|
|
|
|
/** Name of bone we are based on */
|
|
var name AttachBoneName;
|
|
|
|
//----------------------
|
|
// Client FX
|
|
var() ParticleSystem DeathVFXTemplate;
|
|
var() AkEvent DeathSFX;
|
|
var() AkComponent DeathSFXComponent;
|
|
var() AkEvent InvalidHitSFX;
|
|
|
|
replication
|
|
{
|
|
if (bNetDirty)
|
|
SpawnerOwner, SpawnerOwnerIndex, bActiveTarget, NumHits;
|
|
}
|
|
|
|
simulated event ReplicatedEvent(name VarName)
|
|
{
|
|
super.ReplicatedEvent(VarName);
|
|
|
|
//Allow the target to manage its own state in the main rig's targets array.
|
|
if (VarName == 'SpawnerOwner' || VarName == 'SpawnerOwnerIndex')
|
|
{
|
|
if (SpawnerOwner != none && SpawnerOwnerIndex >= 0)
|
|
{
|
|
AddToOwnerArray();
|
|
}
|
|
}
|
|
else if (VarName == 'bActiveTarget')
|
|
{
|
|
if (bActiveTarget)
|
|
{
|
|
SetActive();
|
|
}
|
|
else
|
|
{
|
|
SetInactive();
|
|
}
|
|
}
|
|
else if (VarName == 'NumHits')
|
|
{
|
|
if (NumHits == 0)
|
|
{
|
|
PlayDeath();
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Called via repnotify on clients to sync with main spawner's target array */
|
|
simulated function AddToOwnerArray()
|
|
{
|
|
if (SpawnerOwner.MinigameTargets.Find(self) == INDEX_NONE)
|
|
{
|
|
SpawnerOwner.MinigameTargets[SpawnerOwnerIndex] = self;
|
|
SpawnerOwner.UpdateBase(self);
|
|
}
|
|
}
|
|
|
|
simulated function TakeRadiusDamage(Controller InstigatedBy, float BaseDamage, float DamageRadius, class<DamageType> DamageType, float Momentum, vector HurtOrigin, bool bFullDamage, Actor DamageCauser, optional float DamageFalloffExponent = 1.f, optional bool bAdjustRadiusDamage=true)
|
|
{
|
|
if (!bIgnoreRadiusDamage || AcceptedDamageTypes.Find(DamageType) != INDEX_NONE)
|
|
{
|
|
TakeDamage(BaseDamage, InstigatedBy, HurtOrigin, vect(0,0,0), DamageType, , DamageCauser);
|
|
}
|
|
}
|
|
|
|
/** The amount of damage is unimportant in this case. These targets will never be killed, but simply be reset
|
|
* to their initial condition upon "death". Track number of hits and go into death condition once
|
|
* specified hit count has been reached.
|
|
*/
|
|
simulated event TakeDamage(int DamageAmount, Controller EventInstigator, vector HitLocation, vector Momentum, class<DamageType> DamageType, optional TraceHitInfo HitInfo, optional Actor DamageCauser)
|
|
{
|
|
local int i;
|
|
|
|
if (!bActiveTarget)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < AcceptedDamageTypes.Length; ++i)
|
|
{
|
|
//Valid hit
|
|
if (DamageType == AcceptedDamageTypes[i] || ClassIsChildOf(DamageType, AcceptedDamageTypes[i]))
|
|
{
|
|
ValidHit(EventInstigator, DamageCauser);
|
|
return;
|
|
}
|
|
}
|
|
|
|
InvalidHit(EventInstigator, DamageCauser);
|
|
}
|
|
|
|
function ValidHit(Controller EventInstigator, Actor HitActor)
|
|
{
|
|
local KFMG_TargetGame TargetGame;
|
|
|
|
if (Role == ROLE_Authority)
|
|
{
|
|
--NumHits;
|
|
if (NumHits <= 0)
|
|
{
|
|
PlayDeath();
|
|
SetInactive();
|
|
TargetGame = KFMG_TargetGame(Owner);
|
|
if (TargetGame != none)
|
|
{
|
|
TargetGame.TargetHit(self, EventInstigator);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
simulated function InvalidHit(Controller EventInstigator, Actor HitActor)
|
|
{
|
|
if (DeathSFXComponent != none)
|
|
{
|
|
DeathSFXComponent.PlayEvent(InvalidHitSFX, , false, true);
|
|
}
|
|
}
|
|
|
|
/** Do any resets necessary here, including health and visual items. */
|
|
simulated event Reset()
|
|
{
|
|
super.Reset();
|
|
|
|
SetRelativeLocation(vect(0, 0, 0));
|
|
NumHits = default.NumHits;
|
|
}
|
|
|
|
simulated event SetActive()
|
|
{
|
|
bActiveTarget = true;
|
|
SetHidden(false);
|
|
}
|
|
|
|
simulated event SetInactive()
|
|
{
|
|
bActiveTarget = false;
|
|
SetHidden(true);
|
|
}
|
|
|
|
simulated event Finalize();
|
|
|
|
simulated event PlayDeath()
|
|
{
|
|
if (WorldInfo.NetMode != NM_DedicatedServer && !IsAlive())
|
|
{
|
|
if (DeathVFXTemplate != none)
|
|
{
|
|
WorldInfo.MyEmitterPool.SpawnEmitter(DeathVFXTemplate, Location);
|
|
}
|
|
|
|
if (DeathSFXComponent != none)
|
|
{
|
|
DeathSFXComponent.PlayEvent(DeathSFX, , false, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
simulated function bool IsAlive()
|
|
{
|
|
return NumHits > 0;
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
NumHits = 1
|
|
bStatic = false
|
|
|
|
Begin Object class=CylinderComponent Name=Cylinder0
|
|
CollisionRadius = 25.0
|
|
CollisionHeight = 25.0
|
|
BlockNonZeroExtent = true
|
|
BlockZeroExtent = true
|
|
BlockActors = true
|
|
CollideActors = true
|
|
End Object
|
|
Components.Add(Cylinder0)
|
|
CollisionCylinder = Cylinder0
|
|
CollisionComponent = Cylinder0
|
|
|
|
Begin Object class=StaticMeshComponent Name=Mesh0
|
|
End Object
|
|
Mesh = Mesh0
|
|
Components.Add(Mesh0)
|
|
|
|
Begin Object class=AkComponent Name=DeathSFX0
|
|
End Object
|
|
DeathSFXComponent=DeathSFX0
|
|
Components.Add(DeathSFX0)
|
|
|
|
RemoteRole = ROLE_SimulatedProxy
|
|
NetPriority = +00002.500000
|
|
|
|
bCollideActors = true
|
|
bBlockActors = false
|
|
bProjTarget = true
|
|
bCanBeDamaged = true
|
|
CollisionType = COLLIDE_TouchAll
|
|
|
|
bIgnoreRadiusDamage = true
|
|
|
|
SpawnerOwnerIndex = -1
|
|
|
|
AcceptedDamageTypes.Add(class'KFDT_Ballistic_9mm')
|
|
|
|
bAlwaysRelevant = true
|
|
} |