1493 lines
34 KiB
Ucode
1493 lines
34 KiB
Ucode
//=============================================================================
|
|
// The moving brush class.
|
|
// This is a built-in Unreal class and it shouldn't be modified.
|
|
// Note that movers by default have bNoDelete==true. This makes movers and their default properties
|
|
// remain on the client side. If a mover subclass has bNoDelete=false, then its default properties must
|
|
// be replicated
|
|
//=============================================================================
|
|
class Mover extends Actor
|
|
native
|
|
nativereplication;
|
|
|
|
// How the mover should react when it encroaches an actor.
|
|
var() enum EMoverEncroachType
|
|
{
|
|
ME_StopWhenEncroach, // Stop when we hit an actor.
|
|
ME_ReturnWhenEncroach, // Return to previous position when we hit an actor.
|
|
ME_CrushWhenEncroach, // Crush the poor helpless actor.
|
|
ME_IgnoreWhenEncroach, // Ignore encroached actors.
|
|
} MoverEncroachType;
|
|
|
|
// How the mover moves from one position to another.
|
|
var() enum EMoverGlideType
|
|
{
|
|
MV_MoveByTime, // Move linearly.
|
|
MV_GlideByTime, // Move with smooth acceleration.
|
|
} MoverGlideType;
|
|
|
|
// What classes can bump trigger this mover
|
|
var() enum EBumpType
|
|
{
|
|
BT_PlayerBump, // Can only be bumped by player.
|
|
BT_PawnBump, // Can be bumped by any pawn
|
|
BT_AnyBump, // Can be bumped by any solid actor
|
|
} BumpType;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Keyframe numbers.
|
|
var() byte KeyNum; // Current or destination keyframe.
|
|
var byte PrevKeyNum; // Previous keyframe.
|
|
var() const byte NumKeys; // Number of keyframes in total (0-3).
|
|
var() const byte WorldRaytraceKey; // Raytrace the world with the brush here.
|
|
var() const byte BrushRaytraceKey; // Raytrace the brush here.
|
|
var byte StartKeyNum;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Movement parameters.
|
|
var() float MoveTime; // Time to spend moving between keyframes.
|
|
var() float StayOpenTime; // How long to remain open before closing.
|
|
var() float OtherTime; // TriggerPound stay-open time.
|
|
var() int EncroachDamage; // How much to damage encroached actors.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Mover state.
|
|
var() bool bToggleDirection;
|
|
var() bool bTriggerOnceOnly; // Go dormant after first trigger.
|
|
var() bool bSlave; // This brush is a slave.
|
|
var() bool bUseTriggered; // Triggered by player grab
|
|
var() bool bDamageTriggered; // Triggered by taking damage
|
|
var() bool bDynamicLightMover; // Apply dynamic lighting to mover.
|
|
var() bool bUseShortestRotation; // rot by -90 instead of +270 and so on.
|
|
var(ReturnGroup) bool bIsLeader;
|
|
var() name PlayerBumpEvent; // Optional event to cause when the player bumps the mover.
|
|
var() name BumpEvent; // Optional event to cause when any valid bumper bumps the mover.
|
|
var actor SavedTrigger; // Who we were triggered by.
|
|
var() float DamageThreshold; // minimum damage to trigger
|
|
var int numTriggerEvents; // number of times triggered ( count down to untrigger )
|
|
var Mover Leader; // for having multiple movers return together
|
|
var Mover Follower;
|
|
var(ReturnGroup) name ReturnGroup; // if none, same as tag
|
|
var() float DelayTime; // delay before starting to open
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Audio.
|
|
var(MoverSounds) sound OpeningSound; // When start opening.
|
|
var(MoverSounds) sound OpenedSound; // When finished opening.
|
|
var(MoverSounds) sound ClosingSound; // When start closing.
|
|
var(MoverSounds) sound ClosedSound; // When finish closing.
|
|
var(MoverSounds) sound MoveAmbientSound; // Optional ambient sound when moving.
|
|
var(MoverSounds) sound LoopSound; // Played on Loop
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Events
|
|
|
|
var(MoverEvents) name OpeningEvent; // Event to cause when opening
|
|
var(MoverEvents) name OpenedEvent; // Event to cause when opened
|
|
var(MoverEvents) name ClosingEvent; // Event to cause when closing
|
|
var(MoverEvents) name ClosedEvent; // Event to cause when closed
|
|
var(MoverEvents) name LoopEvent; // Event to cause when the mover loops
|
|
//-----------------------------------------------------------------------------
|
|
// Other stuff
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Internal.
|
|
var vector KeyPos[24];
|
|
var rotator KeyRot[24];
|
|
var vector BasePos, OldPos, OldPrePivot, SavedPos;
|
|
var rotator BaseRot, OldRot, SavedRot;
|
|
var float PhysAlpha; // Interpolating position, 0.0-1.0.
|
|
var float PhysRate; // Interpolation rate per second.
|
|
|
|
// AI related
|
|
var NavigationPoint myMarker;
|
|
var bool bOpening, bDelaying, bClientPause;
|
|
var bool bClosed; // mover is in closed position, and no longer moving
|
|
var bool bPlayerOnly;
|
|
var(AI) bool bAutoDoor; // automatically setup Door NavigationPoint for this mover
|
|
var(AI) bool bNoAIRelevance; // don't warn about this mover during path review
|
|
var bool bJumpLift;
|
|
|
|
var() bool bOscillatingLoop; // Goes from 0 up to X then back down to 0
|
|
|
|
// for client side replication
|
|
var byte ClientStop;
|
|
var vector SimOldPos;
|
|
var int SimOldRotPitch, SimOldRotYaw, SimOldRotRoll;
|
|
var vector SimInterpolate;
|
|
var vector RealPosition;
|
|
var rotator RealRotation;
|
|
var int ClientUpdate;
|
|
|
|
var byte StoppedPosition;
|
|
|
|
// Used for Oscillation
|
|
var int StepDirection; // 1 = Moving forward, -1 moving Backward
|
|
|
|
// Used for controlling antiportals
|
|
var array<AntiPortalActor> AntiPortals;
|
|
var() name AntiPortalTag;
|
|
|
|
// Resetting
|
|
var bool bResetting, BACKUP_bHidden;
|
|
var name Backup_InitialState;
|
|
|
|
|
|
replication
|
|
{
|
|
// Things the server should send to the client.
|
|
reliable if( Role==ROLE_Authority )
|
|
SimOldPos, SimOldRotPitch, SimOldRotYaw, SimOldRotRoll, SimInterpolate, RealPosition, RealRotation, StoppedPosition;
|
|
}
|
|
|
|
|
|
function bool SelfTriggered()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
function Actor SpecialHandling(Pawn Other)
|
|
{
|
|
local Actor A;
|
|
|
|
if ( myMarker != None )
|
|
{
|
|
A = MyMarker.SpecialHandling(Other);
|
|
if ( A == None )
|
|
return MyMarker;
|
|
return A;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
/* StartInterpolation()
|
|
when this function is called, the actor will start moving along an interpolation path
|
|
beginning at Dest
|
|
*/
|
|
simulated function StartInterpolation()
|
|
{
|
|
GotoState('');
|
|
bInterpolating = true;
|
|
SetPhysics(PHYS_None);
|
|
}
|
|
|
|
simulated function Timer()
|
|
{
|
|
if ( Velocity != vect(0,0,0) )
|
|
{
|
|
if ( bClientPause )
|
|
bClientPause = false;
|
|
return;
|
|
}
|
|
if ( Level.NetMode == NM_Client && !bClientAuthoritative )
|
|
{
|
|
if ( ClientUpdate == 0 ) // not doing a move
|
|
{
|
|
if ( bClientPause )
|
|
{
|
|
if ( VSize(RealPosition - Location) > 3 )
|
|
SetLocation(RealPosition);
|
|
else
|
|
RealPosition = Location;
|
|
SetRotation(RealRotation);
|
|
bClientPause = false;
|
|
}
|
|
else if ( RealPosition != Location )
|
|
bClientPause = true;
|
|
}
|
|
else
|
|
bClientPause = false;
|
|
}
|
|
else
|
|
{
|
|
if ( bCollideActors )
|
|
{
|
|
if ( RealRotation != Rotation )
|
|
RealRotation = Rotation;
|
|
if ( RealPosition != Location )
|
|
RealPosition = Location;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Movement functions.
|
|
|
|
// Interpolate to keyframe KeyNum in Seconds time.
|
|
simulated final function InterpolateTo( byte NewKeyNum, float Seconds )
|
|
{
|
|
local Mover M;
|
|
|
|
ForEach BasedActors(class'Mover', M)
|
|
M.BaseStarted();
|
|
|
|
NewKeyNum = Clamp( NewKeyNum, 0, ArrayCount(KeyPos)-1 );
|
|
if( NewKeyNum==PrevKeyNum && KeyNum!=PrevKeyNum )
|
|
{
|
|
// Reverse the movement smoothly.
|
|
PhysAlpha = 1.0 - PhysAlpha;
|
|
OldPos = BasePos + KeyPos[KeyNum];
|
|
OldRot = BaseRot + KeyRot[KeyNum];
|
|
}
|
|
else
|
|
{
|
|
// Start a new movement.
|
|
OldPos = Location;
|
|
OldRot = Rotation;
|
|
PhysAlpha = 0.0;
|
|
}
|
|
|
|
if ( bResetting ) // resetting mover, do it at max speed
|
|
Seconds = 0.005;
|
|
|
|
// Setup physics.
|
|
SetPhysics(PHYS_MovingBrush);
|
|
bInterpolating = true;
|
|
PrevKeyNum = KeyNum;
|
|
KeyNum = NewKeyNum;
|
|
PhysRate = 1.0 / FMax(Seconds, 0.005);
|
|
|
|
ClientUpdate++;
|
|
SimOldPos = OldPos;
|
|
SimOldRotYaw = OldRot.Yaw;
|
|
SimOldRotPitch = OldRot.Pitch;
|
|
SimOldRotRoll = OldRot.Roll;
|
|
SimInterpolate.X = 100 * PhysAlpha;
|
|
SimInterpolate.Y = 100 * FMax(0.01, PhysRate);
|
|
SimInterpolate.Z = 256 * PrevKeyNum + KeyNum;
|
|
NetUpdateTime = Level.TimeSeconds - 1;
|
|
}
|
|
|
|
// Set the specified keyframe.
|
|
final function SetKeyframe( byte NewKeyNum, vector NewLocation, rotator NewRotation )
|
|
{
|
|
KeyNum = Clamp( NewKeyNum, 0, ArrayCount(KeyPos)-1 );
|
|
KeyPos[KeyNum] = NewLocation;
|
|
KeyRot[KeyNum] = NewRotation;
|
|
}
|
|
|
|
// Interpolation ended.
|
|
simulated event KeyFrameReached()
|
|
{
|
|
local byte OldKeyNum;
|
|
local Mover M;
|
|
|
|
OldKeyNum = PrevKeyNum;
|
|
PrevKeyNum = KeyNum;
|
|
PhysAlpha = 0;
|
|
ClientUpdate--;
|
|
|
|
// If more than two keyframes, chain them.
|
|
if( KeyNum>0 && KeyNum<OldKeyNum )
|
|
{
|
|
// Chain to previous.
|
|
InterpolateTo(KeyNum-1,MoveTime);
|
|
}
|
|
else if( KeyNum<NumKeys-1 && KeyNum>OldKeyNum )
|
|
{
|
|
// Chain to next.
|
|
InterpolateTo(KeyNum+1,MoveTime);
|
|
}
|
|
else
|
|
{
|
|
// Finished interpolating.
|
|
AmbientSound = None;
|
|
NetUpdateTime = Level.TimeSeconds - 1;
|
|
if ( bJumpLift && (KeyNum == 1) )
|
|
FinishNotify();
|
|
if ( (ClientUpdate == 0) && ((Level.NetMode != NM_Client) || bClientAuthoritative) )
|
|
{
|
|
RealPosition = Location;
|
|
RealRotation = Rotation;
|
|
ForEach BasedActors(class'Mover', M)
|
|
M.BaseFinished();
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Mover functions.
|
|
|
|
// Notify AI that mover finished movement
|
|
function FinishNotify()
|
|
{
|
|
local Controller C;
|
|
|
|
for ( C=Level.ControllerList; C!=None; C=C.nextController )
|
|
if ( (C.Pawn != None) && (C.PendingMover == self) )
|
|
C.MoverFinished();
|
|
}
|
|
|
|
// Handle when the mover finishes closing.
|
|
function FinishedClosing()
|
|
{
|
|
local Mover M;
|
|
|
|
// Update sound effects.
|
|
PlaySound( ClosedSound, SLOT_None, SoundVolume / 255.0, false, SoundRadius, SoundPitch / 64.0);
|
|
|
|
// Handle Events
|
|
|
|
TriggerEvent( ClosedEvent, Self, Instigator );
|
|
|
|
// Notify our triggering actor that we have completed.
|
|
if( SavedTrigger != None )
|
|
SavedTrigger.EndEvent();
|
|
|
|
SavedTrigger = None;
|
|
Instigator = None;
|
|
If ( MyMarker != None )
|
|
MyMarker.MoverClosed();
|
|
bClosed = true;
|
|
FinishNotify();
|
|
for ( M=Leader; M!=None; M=M.Follower )
|
|
if ( !M.bClosed )
|
|
return;
|
|
UnTriggerEvent(OpeningEvent, Self, Instigator);
|
|
}
|
|
|
|
// Handle when the mover finishes opening.
|
|
function FinishedOpening()
|
|
{
|
|
// Update sound effects.
|
|
PlaySound( OpenedSound, SLOT_None, SoundVolume / 255.0, false, SoundRadius, SoundPitch / 64.0);
|
|
|
|
// Trigger any chained movers / Events
|
|
TriggerEvent(Event, Self, Instigator);
|
|
TriggerEvent(OpenedEvent, Self, Instigator);
|
|
|
|
If ( MyMarker != None )
|
|
MyMarker.MoverOpened();
|
|
FinishNotify();
|
|
}
|
|
|
|
// Open the mover.
|
|
function DoOpen()
|
|
{
|
|
bOpening = true;
|
|
bDelaying = false;
|
|
InterpolateTo( 1, MoveTime );
|
|
MakeNoise(1.0);
|
|
PlaySound( OpeningSound, SLOT_None, SoundVolume / 255.0, false, SoundRadius, SoundPitch / 64.0);
|
|
AmbientSound = MoveAmbientSound;
|
|
TriggerEvent(OpeningEvent, Self, Instigator);
|
|
if ( Follower != None )
|
|
Follower.DoOpen();
|
|
}
|
|
|
|
// Close the mover.
|
|
function DoClose()
|
|
{
|
|
bOpening = false;
|
|
bDelaying = false;
|
|
InterpolateTo( Max(0,KeyNum-1), MoveTime );
|
|
MakeNoise(1.0);
|
|
PlaySound( ClosingSound, SLOT_None, SoundVolume / 255.0, false, SoundRadius, SoundPitch / 64.0);
|
|
UntriggerEvent(Event, self, Instigator);
|
|
AmbientSound = MoveAmbientSound;
|
|
TriggerEvent(ClosingEvent,Self,Instigator);
|
|
if ( Follower != None )
|
|
Follower.DoClose();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Engine notifications.
|
|
|
|
// When mover enters gameplay.
|
|
simulated function BeginPlay()
|
|
{
|
|
local AntiPortalActor AntiPortalA;
|
|
|
|
if(AntiPortalTag != '')
|
|
{
|
|
foreach AllActors(class'AntiPortalActor',AntiPortalA,AntiPortalTag)
|
|
{
|
|
AntiPortals.Length = AntiPortals.Length + 1;
|
|
AntiPortals[AntiPortals.Length - 1] = AntiPortalA;
|
|
}
|
|
}
|
|
|
|
// timer updates real position every second in network play
|
|
if ( Level.NetMode != NM_Standalone )
|
|
{
|
|
if ( Level.NetMode == NM_Client && bClientAuthoritative )
|
|
settimer(4.0, true);
|
|
else
|
|
settimer(1.0, true);
|
|
if ( Role < ROLE_Authority )
|
|
return;
|
|
}
|
|
|
|
RealPosition = Location;
|
|
RealRotation = Rotation;
|
|
|
|
// Init key info.
|
|
Super.BeginPlay();
|
|
KeyNum = Clamp( KeyNum, 0, ArrayCount(KeyPos)-1 );
|
|
PhysAlpha = 0.0;
|
|
StartKeyNum = KeyNum;
|
|
|
|
// Set initial location.
|
|
Move( BasePos + KeyPos[KeyNum] - Location );
|
|
|
|
// Initial rotation.
|
|
SetRotation( BaseRot + KeyRot[KeyNum] );
|
|
|
|
// find movers in same group
|
|
if ( ReturnGroup == '' )
|
|
ReturnGroup = tag;
|
|
Leader = None;
|
|
Follower = None;
|
|
}
|
|
|
|
// Immediately after mover enters gameplay.
|
|
function PostBeginPlay()
|
|
{
|
|
local mover M;
|
|
|
|
RealRotation = Rotation;
|
|
RealPosition = Location;
|
|
|
|
Backup_InitialState = InitialState;
|
|
BACKUP_bHidden = bHidden;
|
|
|
|
// Initialize all slaves.
|
|
if( !bSlave )
|
|
{
|
|
foreach DynamicActors( class 'Mover', M, Tag )
|
|
{
|
|
if( M.bSlave )
|
|
{
|
|
M.GotoState('');
|
|
M.SetBase( Self );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( bIsLeader )
|
|
{
|
|
Leader = self;
|
|
ForEach DynamicActors( class'Mover', M )
|
|
if ( (M != self) && (M.ReturnGroup == ReturnGroup) )
|
|
{
|
|
M.Leader = self;
|
|
M.Follower = Follower;
|
|
Follower = M;
|
|
}
|
|
}
|
|
else if ( Leader == None )
|
|
{
|
|
// if no one in returngroup, I am the leader anyway
|
|
ForEach DynamicActors( class'Mover', M )
|
|
{
|
|
if ( (M != self) && (M.ReturnGroup == ReturnGroup) )
|
|
return;
|
|
}
|
|
Leader = self;
|
|
}
|
|
}
|
|
|
|
|
|
function SetResetStatus( bool bNewStatus )
|
|
{
|
|
NetUpdateTime = Level.TimeSeconds - 1;
|
|
bHidden = BACKUP_bHidden;
|
|
bResetting = bNewStatus;
|
|
if ( Follower != None )
|
|
Follower.SetResetStatus( bNewStatus );
|
|
}
|
|
|
|
function Reset()
|
|
{
|
|
SetResetStatus( true );
|
|
DoClose();
|
|
SetResetStatus( false );
|
|
EnableTrigger();
|
|
GotoState(Backup_InitialState, '');
|
|
}
|
|
|
|
function MakeGroupStop()
|
|
{
|
|
// Stop moving immediately.
|
|
bInterpolating = false;
|
|
NetUpdateTime = Level.TimeSeconds - 1;
|
|
AmbientSound = None;
|
|
GotoState( , '' );
|
|
|
|
if ( Follower != None )
|
|
Follower.MakeGroupStop();
|
|
}
|
|
|
|
function MakeGroupReturn()
|
|
{
|
|
// Abort move and reverse course.
|
|
bInterpolating = false;
|
|
NetUpdateTime = Level.TimeSeconds - 1;
|
|
AmbientSound = None;
|
|
|
|
if(bIsLeader || Leader==Self)
|
|
{
|
|
if( KeyNum<PrevKeyNum )
|
|
GotoState( , 'Open' );
|
|
else
|
|
GotoState( , 'Close' );
|
|
}
|
|
|
|
if ( Follower != None )
|
|
Follower.MakeGroupReturn();
|
|
}
|
|
|
|
// Return true to abort, false to continue.
|
|
function bool EncroachingOn( actor Other )
|
|
{
|
|
local Pawn P;
|
|
|
|
if ( Other == None )
|
|
return false;
|
|
if ( ((Pawn(Other) != None) && (Pawn(Other).Controller == None)) || Other.IsA('Decoration') )
|
|
{
|
|
Other.TakeDamage(10000, None, Other.Location, vect(0,0,0), class'Crushed');
|
|
return false;
|
|
}
|
|
if ( Other.IsA('Pickup') )
|
|
{
|
|
if ( !Other.bAlwaysRelevant && (Other.Owner == None) )
|
|
Other.Destroy();
|
|
return false;
|
|
}
|
|
if ( Other.IsA('Fragment') || Other.IsA('SeveredAppendage') || Other.IsA('Projectile') )
|
|
{
|
|
Other.Destroy();
|
|
return false;
|
|
}
|
|
|
|
// Damage the encroached actor.
|
|
if( EncroachDamage != 0 )
|
|
Other.TakeDamage( EncroachDamage, Instigator, Other.Location, vect(0,0,0), class'Crushed' );
|
|
|
|
// If we have a bump-player event, and Other is a pawn, do the bump thing.
|
|
P = Pawn(Other);
|
|
if( P!=None && (P.Controller != None) && P.IsPlayerPawn() )
|
|
{
|
|
if ( PlayerBumpEvent!='' )
|
|
Bump( Other );
|
|
if ( (P != None) && (P.Controller != None) && (P.Base != self) && (P.Controller.PendingMover == self) )
|
|
P.Controller.UnderLift(self); // pawn is under lift - tell him to move
|
|
}
|
|
|
|
if ( Leader == None )
|
|
Leader = self;
|
|
|
|
// Stop, return, or whatever.
|
|
if( MoverEncroachType == ME_StopWhenEncroach )
|
|
{
|
|
Leader.MakeGroupStop();
|
|
return true;
|
|
}
|
|
else if( MoverEncroachType == ME_ReturnWhenEncroach )
|
|
{
|
|
Leader.MakeGroupReturn();
|
|
if ( Other.IsA('Pawn') )
|
|
Pawn(Other).PlayMoverHitSound();
|
|
return true;
|
|
}
|
|
else if( MoverEncroachType == ME_CrushWhenEncroach )
|
|
{
|
|
// Kill it.
|
|
Other.KilledBy( Instigator );
|
|
return false;
|
|
}
|
|
else if( MoverEncroachType == ME_IgnoreWhenEncroach )
|
|
{
|
|
// Ignore it.
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// When bumped by player.
|
|
function Bump( actor Other )
|
|
{
|
|
local pawn P;
|
|
|
|
P = Pawn(Other);
|
|
if ( bUseTriggered && (P != None) && !P.IsHumanControlled() && P.IsPlayerPawn() && !bDelaying && !bOpening )
|
|
{
|
|
Trigger(P,P);
|
|
P.Controller.WaitForMover(self);
|
|
}
|
|
if ( (BumpType != BT_AnyBump) && (P == None) )
|
|
return;
|
|
if ( (BumpType == BT_PlayerBump) && !P.IsPlayerPawn() )
|
|
return;
|
|
if ( (BumpType == BT_PawnBump) && P.bAmbientCreature )
|
|
return;
|
|
TriggerEvent(BumpEvent, self, P);
|
|
|
|
if ( (P != None) && P.IsPlayerPawn() )
|
|
TriggerEvent(PlayerBumpEvent, self, P);
|
|
}
|
|
|
|
// When damaged
|
|
function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation,
|
|
Vector momentum, class<DamageType> damageType, optional int HitIndex)
|
|
{
|
|
if ( bDamageTriggered && (Damage >= DamageThreshold) )
|
|
{
|
|
if ( (AIController(instigatedBy.Controller) != None)
|
|
&& (instigatedBy.Controller.Focus == self) )
|
|
instigatedBy.Controller.StopFiring();
|
|
self.Trigger(self, instigatedBy);
|
|
if ( (AIController(instigatedBy.Controller) != None) && (instigatedBy.Controller.Target == self) )
|
|
instigatedBy.Controller.StopFiring();
|
|
}
|
|
}
|
|
|
|
|
|
//========================================================================
|
|
// Master State for OpenTimed mover states (for movers that open and close)
|
|
|
|
// Laurent -- Moved out of state for reset
|
|
function DisableTrigger();
|
|
function EnableTrigger();
|
|
|
|
state OpenTimedMover
|
|
{
|
|
function bool ShouldReTrigger()
|
|
{
|
|
return( false );
|
|
}
|
|
|
|
function Reset()
|
|
{
|
|
SetResetStatus( true );
|
|
GotoState(Backup_InitialState, 'Close');
|
|
}
|
|
|
|
function BeginState()
|
|
{
|
|
EnableTrigger();
|
|
}
|
|
|
|
Open:
|
|
if ( bTriggerOnceOnly )
|
|
Disable('Trigger');
|
|
bClosed = false;
|
|
DisableTrigger();
|
|
if ( DelayTime > 0 )
|
|
{
|
|
bDelaying = true;
|
|
Sleep(DelayTime);
|
|
}
|
|
DoOpen();
|
|
FinishInterpolation();
|
|
FinishedOpening();
|
|
Sleep( StayOpenTime );
|
|
if ( bTriggerOnceOnly )
|
|
GotoState('WasOpenTimedMover', '');
|
|
Close:
|
|
DoClose();
|
|
FinishInterpolation();
|
|
FinishedClosing();
|
|
EnableTrigger();
|
|
if ( bResetting )
|
|
{
|
|
SetResetStatus( false );
|
|
GotoState( Backup_InitialState, '' );
|
|
Stop;
|
|
}
|
|
Sleep( StayOpenTime );
|
|
if( ShouldReTrigger() )
|
|
{
|
|
SavedTrigger = None;
|
|
GotoState( 'StandOpenTimed', 'Open' );
|
|
}
|
|
}
|
|
|
|
|
|
state WasOpenTimedMover
|
|
{
|
|
function Reset()
|
|
{
|
|
SetResetStatus( true );
|
|
GotoState(Backup_InitialState, 'Close');
|
|
}
|
|
}
|
|
|
|
|
|
// Open when stood on, wait, then close.
|
|
state() StandOpenTimed extends OpenTimedMover
|
|
{
|
|
function bool ShouldReTrigger()
|
|
{
|
|
local int i;
|
|
|
|
for( i = 0; i < Attached.Length; i++ )
|
|
if( CanTrigger( Attached[i] ) )
|
|
return( true );
|
|
|
|
return( false );
|
|
}
|
|
|
|
function bool CanTrigger( Actor Other )
|
|
{
|
|
local pawn P;
|
|
|
|
P = Pawn(Other);
|
|
if ( (BumpType != BT_AnyBump) && (P == None) )
|
|
return (false);
|
|
if ( (BumpType == BT_PlayerBump) && !P.IsPlayerPawn() )
|
|
return (false);
|
|
if ( (BumpType == BT_PawnBump) && (Other.Mass < 10) )
|
|
return (false);
|
|
|
|
TriggerEvent(BumpEvent, self, P); // gam -- this _might_ cause problems. Blame Goose.
|
|
|
|
return( true );
|
|
}
|
|
|
|
function Attach( actor Other )
|
|
{
|
|
if( !CanTrigger( Other ) )
|
|
return;
|
|
|
|
SavedTrigger = None;
|
|
|
|
GotoState( 'StandOpenTimed', 'Open' );
|
|
}
|
|
|
|
function DisableTrigger()
|
|
{
|
|
Disable( 'Attach' );
|
|
}
|
|
|
|
function EnableTrigger()
|
|
{
|
|
Enable('Attach');
|
|
}
|
|
}
|
|
|
|
// Open when bumped, wait, then close.
|
|
state() BumpOpenTimed extends OpenTimedMover
|
|
{
|
|
function Bump( actor Other )
|
|
{
|
|
if ( (BumpType != BT_AnyBump) && (Pawn(Other) == None) )
|
|
return;
|
|
if ( (BumpType == BT_PlayerBump) && !Pawn(Other).IsPlayerPawn() )
|
|
return;
|
|
if ( (BumpType == BT_PawnBump) && (Other.Mass < 10) )
|
|
return;
|
|
Global.Bump( Other );
|
|
SavedTrigger = None;
|
|
Instigator = Pawn(Other);
|
|
Instigator.Controller.WaitForMover(self);
|
|
GotoState( 'BumpOpenTimed', 'Open' );
|
|
}
|
|
|
|
function DisableTrigger()
|
|
{
|
|
Disable( 'Bump' );
|
|
}
|
|
|
|
function EnableTrigger()
|
|
{
|
|
Enable('Bump');
|
|
}
|
|
}
|
|
|
|
// When triggered, open, wait, then close.
|
|
state() TriggerOpenTimed extends OpenTimedMover
|
|
{
|
|
function bool SelfTriggered()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
function Trigger( actor Other, pawn EventInstigator )
|
|
{
|
|
SavedTrigger = Other;
|
|
Instigator = EventInstigator;
|
|
if ( SavedTrigger != None )
|
|
SavedTrigger.BeginEvent();
|
|
GotoState( 'TriggerOpenTimed', 'Open' );
|
|
}
|
|
|
|
function DisableTrigger()
|
|
{
|
|
Disable('Trigger');
|
|
}
|
|
|
|
function EnableTrigger()
|
|
{
|
|
Enable('Trigger');
|
|
}
|
|
}
|
|
|
|
state() LoopMove
|
|
{
|
|
function bool SelfTriggered()
|
|
{
|
|
return false;
|
|
}
|
|
event Trigger( actor Other, pawn EventInstigator )
|
|
{
|
|
Disable ('Trigger');
|
|
Enable ('UnTrigger');
|
|
|
|
SavedTrigger = Other;
|
|
Instigator = EventInstigator;
|
|
if ( SavedTrigger != None )
|
|
SavedTrigger.BeginEvent();
|
|
|
|
bOpening = true;
|
|
|
|
PlaySound( OpeningSound, SLOT_None );
|
|
AmbientSound = MoveAmbientSound;
|
|
|
|
GotoState( 'LoopMove', 'Running' );
|
|
}
|
|
|
|
event UnTrigger( actor Other, pawn EventInstigator )
|
|
{
|
|
Disable ('UnTrigger');
|
|
Enable ('Trigger');
|
|
|
|
SavedTrigger = Other;
|
|
Instigator = EventInstigator;
|
|
GotoState( 'LoopMove', 'Stopping' );
|
|
}
|
|
|
|
event KeyFrameReached()
|
|
{
|
|
}
|
|
|
|
function BeginState()
|
|
{
|
|
bOpening = false;
|
|
bDelaying = false;
|
|
}
|
|
|
|
Running:
|
|
FinishInterpolation();
|
|
InterpolateTo( (KeyNum + 1) % NumKeys, MoveTime );
|
|
GotoState( 'LoopMove', 'Running' );
|
|
|
|
Stopping:
|
|
FinishInterpolation();
|
|
FinishedOpening();
|
|
UnTriggerEvent(Event, self, Instigator);
|
|
bOpening = false;
|
|
Stop;
|
|
}
|
|
|
|
//=================================================================
|
|
// Other Mover States
|
|
|
|
// Toggle when triggered.
|
|
state() TriggerToggle
|
|
{
|
|
function bool SelfTriggered()
|
|
{
|
|
return false;
|
|
}
|
|
function Reset()
|
|
{
|
|
super.Reset();
|
|
|
|
if ( bOpening || bDelaying )
|
|
{
|
|
// Reset instantly
|
|
SetResetStatus( true );
|
|
GotoState( 'TriggerToggle', 'Close' );
|
|
}
|
|
}
|
|
|
|
function Trigger( actor Other, pawn EventInstigator )
|
|
{
|
|
SavedTrigger = Other;
|
|
Instigator = EventInstigator;
|
|
if ( SavedTrigger != None )
|
|
SavedTrigger.BeginEvent();
|
|
if( KeyNum==0 || KeyNum<PrevKeyNum )
|
|
GotoState( 'TriggerToggle', 'Open' );
|
|
else
|
|
{
|
|
if( EventInstigator.Controller != none && AIController(EventInstigator.Controller) == none )
|
|
GotoState( 'TriggerToggle', 'Close' );
|
|
// KFO Mod
|
|
else
|
|
{
|
|
GotoState( 'TriggerToggle', 'Close' );
|
|
}
|
|
// END KFO
|
|
//else
|
|
// log("Don't let bots close doors!!! bClosed = "$bClosed);
|
|
}
|
|
}
|
|
Open:
|
|
bClosed = false;
|
|
if ( DelayTime > 0 )
|
|
{
|
|
bDelaying = true;
|
|
Sleep(DelayTime);
|
|
}
|
|
DoOpen();
|
|
FinishInterpolation();
|
|
FinishedOpening();
|
|
if ( SavedTrigger != None )
|
|
SavedTrigger.EndEvent();
|
|
Stop;
|
|
Close:
|
|
DoClose();
|
|
FinishInterpolation();
|
|
FinishedClosing();
|
|
SetResetStatus( false );
|
|
}
|
|
|
|
// Open when triggered, close when get untriggered.
|
|
state() TriggerControl
|
|
{
|
|
function bool SelfTriggered()
|
|
{
|
|
return false;
|
|
}
|
|
function Reset()
|
|
{
|
|
super.Reset();
|
|
|
|
if ( numTriggerEvents > 0 )
|
|
{
|
|
// Reset instantly
|
|
SetResetStatus( true );
|
|
numTriggerEvents = 0;
|
|
UnTrigger(None, None);
|
|
}
|
|
}
|
|
|
|
function Trigger( actor Other, pawn EventInstigator )
|
|
{
|
|
numTriggerEvents++;
|
|
SavedTrigger = Other;
|
|
Instigator = EventInstigator;
|
|
if ( SavedTrigger != None )
|
|
SavedTrigger.BeginEvent();
|
|
if ( !bOpening )
|
|
GotoState( 'TriggerControl', 'Open' );
|
|
}
|
|
|
|
function UnTrigger( actor Other, pawn EventInstigator )
|
|
{
|
|
numTriggerEvents--;
|
|
if ( numTriggerEvents <=0 )
|
|
{
|
|
numTriggerEvents = 0;
|
|
SavedTrigger = Other;
|
|
Instigator = EventInstigator;
|
|
if ( SavedTrigger != None )
|
|
SavedTrigger.BeginEvent();
|
|
GotoState( 'TriggerControl', 'Close' );
|
|
}
|
|
}
|
|
|
|
function BeginState()
|
|
{
|
|
numTriggerEvents = 0;
|
|
}
|
|
|
|
Open:
|
|
bClosed = false;
|
|
if ( DelayTime > 0 )
|
|
{
|
|
bDelaying = true;
|
|
Sleep(DelayTime);
|
|
}
|
|
if ( !bOpening )
|
|
DoOpen();
|
|
FinishInterpolation();
|
|
FinishedOpening();
|
|
if ( SavedTrigger != None )
|
|
SavedTrigger.EndEvent();
|
|
if( bTriggerOnceOnly )
|
|
GotoState('WasTriggerControl');
|
|
Stop;
|
|
Close:
|
|
if ( bOpening )
|
|
DoClose();
|
|
FinishInterpolation();
|
|
FinishedClosing();
|
|
SetResetStatus( false );
|
|
}
|
|
|
|
state WasTriggerControl
|
|
{
|
|
function bool SelfTriggered()
|
|
{
|
|
return false;
|
|
}
|
|
function Reset()
|
|
{
|
|
super.Reset();
|
|
|
|
// Reset instantly
|
|
SetResetStatus( true );
|
|
GotoState('TriggerControl','Close');
|
|
}
|
|
}
|
|
|
|
// Start pounding when triggered.
|
|
state() TriggerPound
|
|
{
|
|
function bool SelfTriggered()
|
|
{
|
|
return false;
|
|
}
|
|
function Reset()
|
|
{
|
|
super.Reset();
|
|
|
|
if ( numTriggerEvents > 0 )
|
|
{
|
|
// Reset instantly
|
|
SetResetStatus( true );
|
|
numTriggerEvents = 0;
|
|
UnTrigger(None,None);
|
|
}
|
|
}
|
|
|
|
function Trigger( actor Other, pawn EventInstigator )
|
|
{
|
|
numTriggerEvents++;
|
|
SavedTrigger = Other;
|
|
Instigator = EventInstigator;
|
|
GotoState( 'TriggerPound', 'Open' );
|
|
}
|
|
function UnTrigger( actor Other, pawn EventInstigator )
|
|
{
|
|
numTriggerEvents--;
|
|
if ( numTriggerEvents <= 0 )
|
|
{
|
|
numTriggerEvents = 0;
|
|
SavedTrigger = None;
|
|
Instigator = None;
|
|
GotoState( 'TriggerPound', 'Close' );
|
|
}
|
|
}
|
|
function BeginState()
|
|
{
|
|
numTriggerEvents = 0;
|
|
}
|
|
|
|
Open:
|
|
if ( bTriggerOnceOnly )
|
|
Disable('Trigger');
|
|
bClosed = false;
|
|
if ( DelayTime > 0 )
|
|
{
|
|
bDelaying = true;
|
|
Sleep(DelayTime);
|
|
}
|
|
DoOpen();
|
|
FinishInterpolation();
|
|
Sleep(OtherTime);
|
|
Close:
|
|
DoClose();
|
|
FinishInterpolation();
|
|
Sleep(StayOpenTime);
|
|
SetResetStatus( false );
|
|
if( bTriggerOnceOnly )
|
|
GotoState('WasTriggerPound');
|
|
if( SavedTrigger != None )
|
|
goto 'Open';
|
|
}
|
|
|
|
|
|
state WasTriggerPound
|
|
{
|
|
function Reset()
|
|
{
|
|
super.Reset();
|
|
|
|
// Reset instantly
|
|
SetResetStatus( true );
|
|
GotoState('TriggerPound','Open');
|
|
}
|
|
}
|
|
|
|
function SetStoppedPosition(byte NewPos)
|
|
{
|
|
NetUpdateTime = Level.TimeSeconds - 1;
|
|
StoppedPosition = NewPos;
|
|
}
|
|
|
|
// Open when triggered, stop when untriggered, close when reset.
|
|
state() TriggerAdvance
|
|
{
|
|
function bool SelfTriggered()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
function Reset()
|
|
{
|
|
super.Reset();
|
|
|
|
// Reset instantly
|
|
SetResetStatus( true );
|
|
numTriggerEvents = 0;
|
|
GotoState('TriggerAdvance','Close');
|
|
}
|
|
|
|
function Trigger( actor Other, pawn EventInstigator )
|
|
{
|
|
numTriggerEvents++;
|
|
SavedTrigger = Other;
|
|
Instigator = EventInstigator;
|
|
if ( SavedTrigger != None )
|
|
SavedTrigger.BeginEvent();
|
|
SetStoppedPosition(0);
|
|
SetPhysics(PHYS_MovingBrush);
|
|
AmbientSound = MoveAmbientSound;
|
|
if ( !bOpening )
|
|
GotoState( 'TriggerAdvance', 'Open' );
|
|
}
|
|
|
|
function UnTrigger( actor Other, pawn EventInstigator )
|
|
{
|
|
numTriggerEvents--;
|
|
if ( numTriggerEvents <=0 )
|
|
{
|
|
AmbientSound = None;
|
|
numTriggerEvents = 0;
|
|
SavedTrigger = Other;
|
|
Instigator = EventInstigator;
|
|
if ( SavedTrigger != None )
|
|
SavedTrigger.BeginEvent();
|
|
SetStoppedPosition(1);
|
|
SetPhysics(PHYS_None);
|
|
}
|
|
}
|
|
|
|
function BeginState()
|
|
{
|
|
numTriggerEvents = 0;
|
|
}
|
|
|
|
function EndState()
|
|
{
|
|
AmbientSound = None;
|
|
}
|
|
|
|
Open:
|
|
if ( Physics == PHYS_None ) // Check if Mover has been UnTriggered since
|
|
GotoState( 'TriggerAdvance', '' );
|
|
bClosed = false;
|
|
if ( DelayTime > 0 )
|
|
{
|
|
bDelaying = true;
|
|
Sleep(DelayTime);
|
|
}
|
|
if ( Physics == PHYS_None ) // Check if Mover has been UnTriggered since
|
|
GotoState( 'TriggerAdvance', '' );
|
|
SetStoppedPosition(0);
|
|
DoOpen();
|
|
FinishInterpolation();
|
|
FinishedOpening();
|
|
if ( SavedTrigger != None )
|
|
SavedTrigger.EndEvent();
|
|
GotoState('WasTriggerAdvance');
|
|
Stop;
|
|
Close:
|
|
SetStoppedPosition(0);
|
|
SetPhysics(PHYS_MovingBrush);
|
|
DoClose();
|
|
FinishInterpolation();
|
|
FinishedClosing();
|
|
SetResetStatus( false );
|
|
Stop;
|
|
}
|
|
|
|
state WasTriggerAdvance
|
|
{
|
|
function bool SelfTriggered()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
function Reset()
|
|
{
|
|
super.Reset();
|
|
|
|
// Reset instantly
|
|
SetResetStatus( true );
|
|
GotoState('TriggerAdvance','Close');
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
// Bump states.
|
|
|
|
|
|
// Open when bumped, close when reset.
|
|
state() BumpButton
|
|
{
|
|
function Bump( actor Other )
|
|
{
|
|
if ( (BumpType != BT_AnyBump) && (Pawn(Other) == None) )
|
|
return;
|
|
if ( (BumpType == BT_PlayerBump) && !Pawn(Other).IsPlayerPawn() )
|
|
return;
|
|
if ( (BumpType == BT_PawnBump) && (Other.Mass < 10) )
|
|
return;
|
|
Global.Bump( Other );
|
|
SavedTrigger = Other;
|
|
Instigator = Pawn( Other );
|
|
Instigator.Controller.WaitForMover(self);
|
|
GotoState( 'BumpButton', 'Open' );
|
|
}
|
|
function BeginEvent()
|
|
{
|
|
bSlave=true;
|
|
}
|
|
function EndEvent()
|
|
{
|
|
bSlave = false;
|
|
Instigator = None;
|
|
GotoState( 'BumpButton', 'Close' );
|
|
}
|
|
Open:
|
|
if ( bTriggerOnceOnly )
|
|
Disable('Trigger');
|
|
bClosed = false;
|
|
Disable( 'Bump' );
|
|
if ( DelayTime > 0 )
|
|
{
|
|
bDelaying = true;
|
|
Sleep(DelayTime);
|
|
}
|
|
DoOpen();
|
|
FinishInterpolation();
|
|
FinishedOpening();
|
|
if( bTriggerOnceOnly )
|
|
GotoState('WasBumpButton');
|
|
if( bSlave )
|
|
Stop;
|
|
Close:
|
|
DoClose();
|
|
FinishInterpolation();
|
|
FinishedClosing();
|
|
SetResetStatus( false );
|
|
Enable( 'Bump' );
|
|
}
|
|
|
|
state WasBumpButton
|
|
{
|
|
function Reset()
|
|
{
|
|
super.Reset();
|
|
|
|
// Reset instantly
|
|
SetResetStatus( true );
|
|
GotoState('BumpButton','Close');
|
|
}
|
|
}
|
|
|
|
|
|
function MoverLooped() // Cause the LoopEvent and play the Loop Sound
|
|
{
|
|
// Event and sound
|
|
|
|
TriggerEvent(LoopEvent, Self, Instigator);
|
|
If (LoopSound!=None)
|
|
PlaySound( LoopSound, SLOT_None, SoundVolume / 255.0, false, SoundRadius, SoundPitch / 64.0);
|
|
}
|
|
|
|
// -----------------------------
|
|
// Loop this mover from the moment we begin
|
|
|
|
state() ConstantLoop
|
|
{
|
|
event KeyFrameReached()
|
|
{
|
|
if (bOscillatingLoop)
|
|
{
|
|
|
|
if ( (KeyNum==0) || (KeyNum==NumKeys-1) ) // Flip
|
|
{
|
|
StepDirection*= -1;
|
|
MoverLooped();
|
|
}
|
|
|
|
KeyNum += StepDirection;
|
|
InterpolateTo( KeyNum, MoveTime );
|
|
}
|
|
else
|
|
{
|
|
InterpolateTo( (KeyNum + 1) % NumKeys, MoveTime );
|
|
if (KeyNum==0)
|
|
MoverLooped();
|
|
}
|
|
|
|
}
|
|
|
|
function BeginState()
|
|
{
|
|
bOpening = false;
|
|
bDelaying = false;
|
|
}
|
|
|
|
Begin:
|
|
InterpolateTo( 1, MoveTime );
|
|
|
|
Running:
|
|
FinishInterpolation();
|
|
GotoState( 'ConstantLoop', 'Running' );
|
|
|
|
}
|
|
|
|
// --------
|
|
// LeadInOutLooper - A Looping move that goes from 0 to 1 when trigger, loops 1-x then returns to 0 when triggered again
|
|
|
|
state() LeadInOutLooper
|
|
{
|
|
function Trigger( actor Other, pawn EventInstigator )
|
|
{
|
|
// Sanity check
|
|
|
|
if (NumKeys<3)
|
|
{
|
|
log("LeadInOutLooper detected with <3 movement keys");
|
|
return;
|
|
}
|
|
|
|
InterpolateTo(1,MoveTime);
|
|
}
|
|
|
|
event KeyFrameReached()
|
|
{
|
|
if (KeyNum!=0)
|
|
{
|
|
InterpolateTo(2,MoveTime);
|
|
gotoState('LeadInOutLooping');
|
|
}
|
|
}
|
|
|
|
function BeginState()
|
|
{
|
|
bOpening = false;
|
|
bDelaying = false;
|
|
}
|
|
|
|
}
|
|
|
|
state LeadInOutLooping
|
|
{
|
|
function Trigger(actor Other, pawn EventInstigator)
|
|
{
|
|
InterpolateTo(0,MoveTime);
|
|
GotoState('LeadInOutLooper');
|
|
}
|
|
|
|
event KeyFrameReached()
|
|
{
|
|
if (bOscillatingLoop)
|
|
{
|
|
if ( (KeyNum==1) || (KeyNum==NumKeys-1) ) // Flip
|
|
{
|
|
StepDirection*= -1;
|
|
MoverLooped();
|
|
}
|
|
|
|
KeyNum += StepDirection;
|
|
InterpolateTo( KeyNum, MoveTime );
|
|
}
|
|
else
|
|
{
|
|
KeyNum++;
|
|
if (KeyNum==NumKeys)
|
|
{
|
|
KeyNum=1;
|
|
MoverLooped();
|
|
}
|
|
|
|
InterpolateTo( KeyNum, MoveTime );
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
function BaseStarted();
|
|
function BaseFinished();
|
|
|
|
// toggles between rotation directions when triggered, stops rotating when untriggered
|
|
state() RotatingMover
|
|
{
|
|
simulated function BaseStarted()
|
|
{
|
|
local actor OldBase;
|
|
|
|
bFixedRotationDir = true;
|
|
OldBase = Base;
|
|
SetPhysics(PHYS_Rotating);
|
|
SetBase(OldBase);
|
|
}
|
|
|
|
simulated function BaseFinished()
|
|
{
|
|
local actor OldBase;
|
|
|
|
OldBase = Base;
|
|
SetPhysics(PHYS_None);
|
|
SetBase(OldBase);
|
|
if ( bToggleDirection )
|
|
{
|
|
RotationRate.Yaw *= -1;
|
|
RotationRate.Pitch *= -1;
|
|
RotationRate.Roll *= -1;
|
|
}
|
|
}
|
|
|
|
simulated function BeginState()
|
|
{
|
|
SetTimer(0.0,false);
|
|
}
|
|
}
|
|
|
|
simulated function UpdatePrecacheStaticMeshes()
|
|
{
|
|
if ( (DrawType == DT_StaticMesh) && StaticMesh != None )
|
|
Level.AddPrecacheStaticMesh( StaticMesh );
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
bNoDelete=true
|
|
bPathColliding=true
|
|
MoverEncroachType=ME_ReturnWhenEncroach
|
|
MoverGlideType=MV_GlideByTime
|
|
NumKeys=2
|
|
BrushRaytraceKey=0
|
|
MoveTime=+00001.000000
|
|
StayOpenTime=+00004.000000
|
|
bStatic=False
|
|
bDynamicLightMover=False
|
|
bHidden=false
|
|
CollisionRadius=+00160.000000
|
|
CollisionHeight=+00160.000000
|
|
bCollideActors=True
|
|
bBlockActors=True
|
|
Physics=PHYS_MovingBrush
|
|
InitialState=BumpOpenTimed
|
|
TransientSoundVolume=+00001.000000
|
|
SoundVolume=228
|
|
NetPriority=2.7
|
|
bAlwaysRelevant=true
|
|
RemoteRole=ROLE_SimulatedProxy
|
|
bClosed=true
|
|
bToggleDirection=true
|
|
bShadowCast=true
|
|
bEdShouldSnap=true
|
|
bAcceptsProjectors=true
|
|
StepDirection=1
|
|
bOnlyDirtyReplication=true
|
|
NetUpdateFrequency=1
|
|
bUseDynamicLights=true
|
|
}
|