1
0
KF2-Dev-Scripts/Engine/Classes/PhysicsVolume.uc
2021-06-02 23:06:18 +03:00

277 lines
9.8 KiB
Ucode

//=============================================================================
// PhysicsVolume: a bounding volume which affects actor physics
// Each Actor is affected at any time by one PhysicsVolume
// Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
//=============================================================================
class PhysicsVolume extends Volume
native
nativereplication
placeable;
/** This property is a bit like gravity, though it can be used to apply force in any
direction using the three axes. Objects within the volume will be accelerated
up to the designated velocity while taking friction values into effect
*/
var() interp vector ZoneVelocity;
var() bool bVelocityAffectsWalking; // Will the zone velocity affect walking?
var() float GroundFriction; // This property allows you to control how much friction you will have as you move across the ground while within the volume. This can be used to simulate slippery surfaces such as ice or oil
var() float TerminalVelocity; // Terminal velocity
var() float DamagePerSec; // This property allows a volume to damage a player as long as they are within it. Using a negative value will allow the volume to have a regenerative effect. NB. bPainCausing must be set to TRUE to activate this
var() class<DamageType> DamageType<AllowAbstract>; // When damage is applied to an object, it is done so using a specific DamageType. Each available DamageType has a KDamageImpulse property which controls the magnitude of the impulse to be applied along the momentum vector. Runtime users should be aware that due to the lack of default weapons and the limited number of damage types, this property will not be extremely useful.
var() int Priority; // This property determines which PhysicsVolume takes precedence if they overlap
var() float FluidFriction; // This property controls the amount of friction applied by the volume as you move through it. The higher this value, the harder it will feel to move through
var() bool bPainCausing; // This property activates the ability to cause damage. Used in conjunction with DamagePerSecond and PainInterval
var() float PainInterval; // Amount of time, in seconds, between damage applications. NB. bPainCausing must be set to TRUE to activate this
var() bool bAIShouldIgnorePain; // If this property is TRUE AI should not treat paths inside this volume differently even if the volume causes pain
var() bool bEntryPain; // This property describes whether or not pain should be caused when something enters the volume - this is in addition to damage per second. NB. bPainCausing must be set to TRUE to activate this
var bool BACKUP_bPainCausing;
var() bool bDestructive; // Destroys most actors which enter it
var() bool bNoInventory; // If set, any items dropped within this volume will have a limited lifetime
var() bool bMoveProjectiles; // this velocity zone should impart velocity to projectiles and effects
var() bool bBounceVelocity; // this velocity zone should bounce actors that land in it
var() bool bNeutralZone; // Players can't take damage in this zone
var() bool bCrowdAgentsPlayDeathAnim; // If TRUE, crowd agents entering this volume play their death animation
var() bool bPhysicsOnContact; // By default, the origin of an Actor must be inside a PhysicsVolume for it to affect it. If this flag is true though, if this Actor touches the volume at all, it will affect it
var() float RigidBodyDamping; // This controls the force that will be applied to PHYS_RigidBody objects in this volume to get them to match the ZoneVelocity
var() float MaxDampingForce; // Applies a cap on the maximum damping force that is applied to objects
var bool bWaterVolume; // If set to TRUE, this volume becomes a water volume - applying FluidFriction and allowing sound effects etc as the player enters and exits the water
var Info PainTimer;
var Controller DamageInstigator; // Controller that gets credit for any damage caused by this volume
var transient PhysicsVolume NextPhysicsVolume;
struct CheckpointRecord
{
var bool bPainCausing;
var bool bActive;
};
cpptext
{
virtual void Spawned();
virtual void PostLoad();
virtual void BeginDestroy();
virtual void Serialize(FArchive& Ar);
void Register();
void Unregister();
INT* GetOptimizedRepList( BYTE* InDefault, FPropertyRetirement* Retire, INT* Ptr, UPackageMap* Map, UActorChannel* Channel );
void SetZone( UBOOL bTest, UBOOL bForceRefresh );
virtual UBOOL ShouldTrace(UPrimitiveComponent* Primitive,AActor *SourceActor, DWORD TraceFlags);
virtual UBOOL WillHurt(APawn *P);
#if WITH_EDITOR
virtual void CheckForErrors();
#endif
virtual FLOAT GetVolumeRBGravityZ() { return GetGravityZ(); }
}
native function float GetGravityZ();
native function float GetGravityZHuman();
native function float GetGravityZMonster();
native function vector GetZoneVelocityForActor(Actor TheActor);
simulated event PostBeginPlay()
{
Super.PostBeginPlay();
BACKUP_bPainCausing = bPainCausing;
if ( Role < ROLE_Authority )
return;
if ( bPainCausing )
{
PainTimer = Spawn(class'VolumeTimer', self);
}
}
/* Reset() - reset actor to initial state - used when restarting level without reloading. */
function Reset()
{
bPainCausing = BACKUP_bPainCausing;
bForceNetUpdate = TRUE;
}
/* Called when an actor in this PhysicsVolume changes its physics mode
*/
event PhysicsChangedFor(Actor Other);
event ActorEnteredVolume(Actor Other);
event ActorLeavingVolume(Actor Other);
event PawnEnteredVolume(Pawn Other);
event PawnLeavingVolume(Pawn Other);
simulated function OnToggle( SeqAct_Toggle inAction )
{
// don't allow this action to modify the collision of static volumes as we won't be able to update the client
if (!bStatic || RemoteRole > ROLE_None)
{
Super.OnToggle(inAction);
}
if (inAction.InputLinks[0].bHasImpulse)
{
// Turn on pain if that was it's original state
bPainCausing = BACKUP_bPainCausing;
}
else if (inAction.InputLinks[1].bHasImpulse)
{
// Turn off pain
bPainCausing = FALSE;
}
else if (inAction.InputLinks[2].bHasImpulse)
{
// Toggle pain off, or on if original state caused pain
bPainCausing = !bPainCausing && BACKUP_bPainCausing;
}
}
simulated event CollisionChanged()
{
// disable Volume behaviour of toggling rigid body collision...
}
/*
TimerPop
damage touched actors if pain causing.
since PhysicsVolume is static, this function is actually called by a volumetimer
*/
function TimerPop(VolumeTimer T)
{
local Actor A;
if ( T == PainTimer )
{
if ( !bPainCausing )
return;
ForEach TouchingActors(class'Actor', A)
{
if ( A.bCanBeDamaged && !A.bStatic )
{
CausePainTo(A);
}
}
}
}
simulated event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal )
{
Super.Touch(Other, OtherComp, HitLocation, HitNormal);
if ( (Other == None) || Other.bStatic )
return;
if ( bNoInventory && (DroppedPickup(Other) != None) && (Other.Owner == None) )
{
Other.LifeSpan = 1.5;
return;
}
if ( bMoveProjectiles && (ZoneVelocity != vect(0,0,0)) )
{
if ( Other.Physics == PHYS_Projectile )
Other.Velocity += ZoneVelocity;
else if ( (Other.Base == None) && Other.IsA('Emitter') && (Other.Physics == PHYS_None) )
{
Other.SetPhysics(PHYS_Projectile);
Other.Velocity += ZoneVelocity;
}
}
if ( bPainCausing )
{
if ( Other.bDestroyInPainVolume )
{
Other.VolumeBasedDestroy(self);
return;
}
if (bEntryPain && Other.bCanBeDamaged)
{
CausePainTo(Other);
}
}
}
function CausePainTo(Actor Other)
{
if (DamagePerSec > 0)
{
if ( WorldInfo.bSoftKillZ && (Other.Physics != PHYS_Walking) )
return;
if ( (DamageType == None) || (DamageType == class'DamageType') )
`log("No valid damagetype ("$DamageType$") specified for "$PathName(self));
Other.TakeDamage(DamagePerSec*PainInterval, DamageInstigator, Location, vect(0,0,1), DamageType,, self);
}
else
{
Other.HealDamage(-DamagePerSec * PainInterval, DamageInstigator, DamageType);
}
}
/** called from GameInfo::SetPlayerDefaults() on the Pawn's PhysicsVolume after the its default movement properties have been restored
* allows the volume to reapply any movement modifiers on the Pawn
*/
function ModifyPlayer(Pawn PlayerPawn);
/** notification when a Pawn inside this volume becomes the ViewTarget for a PlayerController */
function NotifyPawnBecameViewTarget(Pawn P, PlayerController PC);
/** Kismet hook to set DamageInstigator */
function OnSetDamageInstigator(SeqAct_SetDamageInstigator Action)
{
DamageInstigator = Action.GetController(Action.DamageInstigator);
}
function bool ShouldSaveForCheckpoint()
{
return (bPainCausing != BACKUP_bPainCausing);
}
function CreateCheckpointRecord(out CheckpointRecord Record)
{
Record.bPainCausing = bPainCausing;
}
function ApplyCheckpointRecord(const out CheckpointRecord Record)
{
bPainCausing = Record.bPainCausing;
}
defaultproperties
{
Begin Object Name=BrushComponent0
CollideActors=true
BlockActors=false
BlockZeroExtent=true
BlockNonZeroExtent=true
BlockRigidBody=false
End Object
MaxDampingForce=1000000.0
FluidFriction=+0.3
bVelocityAffectsWalking=true
TerminalVelocity=4000.0
bAlwaysRelevant=true
bOnlyDirtyReplication=true
GroundFriction=+00008.000000
NetUpdateFrequency=0.1
bSkipActorPropertyReplication=true
DamageType=class'Engine.DamageType'
bEntryPain=true
PainInterval=1.f
// LDs might just want to toggle pain, which is server only
// we prevent the collision toggle from working in cases where that wouldn't replicate
bForceAllowKismetModification=true
}