Engine
Class Mover

source: c:\runehov\Engine\Classes\Mover.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Brush
         |
         +--Engine.Mover
Direct Known Subclasses:AttachMover, Door

class Mover
extends Engine.Brush

//============================================================================= // The moving brush class. // This is a built-in Unreal class and it shouldn't be modified. //=============================================================================
Variables
 byte BrushRaytraceKey
           Raytrace the brush here.
 name BumpEvent
           Optional event to cause when any valid bumper bumps the mover.
 float DamageThreshold
           minimum damage to trigger
 float DelayTime
           delay before starting to open
 enum EBumpType
 enum EMoverEncroachType
 enum EMoverGlideType
 int EncroachDamage
           How much to damage encroached actors.
 name InterpolateEvent[16]
           RUME: Events to call at each interpolation point
 byte KeyNum
           Current or destination keyframe.
 vector KeyPos[16]
           delay before starting to open
 rotator KeyRot[16]
           delay before starting to open
 float MoveTime[16]
           Time to spend moving between keyframes. RUNE: Variable movetimes
 byte NumKeys
           Number of keyframes in total (0-3).
 float OtherTime
           TriggerPound stay-open time.
 name PlayerBumpEvent
           Optional event to cause when the player bumps the mover.
 byte PrevKeyNum
           Previous keyframe.
 rotator RealRotation
           delay before starting to open
 name ReturnGroup
           if none, same as tag
 OldPrePivot, SavedPos
           delay before starting to open
 OldRot, SavedRot
           delay before starting to open
 Actor SavedTrigger
           Who we were triggered by.
 float StayOpenTime
           How long to remain open before closing.
 byte WorldRaytraceKey
           Raytrace the world with the brush here.
 bool bDamageTriggered
           Triggered by taking damage
 bool bDynamicLightMover
           Apply dynamic lighting to mover.
 bool bSlave
           This brush is a slave.
 bool bTriggerOnceOnly
           Go dormant after first trigger.
 bool bUseTriggered
           Triggered by player grab
 NavigationPoint myMarker
           delay before starting to open

States
should

Function Summary
 void FindTriggerActor()
 
simulated
Timer()


State should Function Summary
 void Attach(Actor Other)
 bool HandleDoor(Pawn Other)
     
// Open when stood on, wait, then close.
 void EndEvent()
 void BeginEvent()
 void Bump(Actor Other)
 bool HandleDoor(Pawn Other)
     
// Open when bumped, close when reset.
 void Bump(Actor Other)
 bool HandleDoor(Pawn Other)
     
// Open when bumped, wait, then close.
 void BeginState()
 void UnTrigger(Actor Other, Pawn EventInstigator)
 void Trigger(Actor Other, Pawn EventInstigator)
 bool HandleDoor(Pawn Other)
     
// Start pounding when triggered.
 void BeginState()
 void UnTrigger(Actor Other, Pawn EventInstigator)
 void Trigger(Actor Other, Pawn EventInstigator)
 bool HandleDoor(Pawn Other)
     
// Open when triggered, close when get untriggered.
 void Trigger(Actor Other, Pawn EventInstigator)
 bool HandleDoor(Pawn Other)
     
// Toggle when triggered.
 void BeginState()
 void Trigger(Actor Other, Pawn EventInstigator)
 bool HandleDoor(Pawn Other)
     
// When triggered, open, wait, then close.
 bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
 bool UseTrigger(Actor Other)
 void Bump(Actor Other)
     
// When bumped by player.
 bool EncroachingOn(Actor Other)
     
// Return true to abort, false to continue.
 void MakeGroupReturn()
 void MakeGroupStop()
 void PostBeginPlay()
     
// Immediately after mover enters gameplay.
 void DoClose()
     
// Close the mover.
 void DoOpen()
     
// Open the mover.
 void FinishedOpening()
     
// Handle when the mover finishes opening.
 void FinishedClosing()
     
// Handle when the mover finishes closing.
 void FinishNotify()
     
// Notify AI that mover finished movement
 void InterpolateEnd(Actor Other)
     
// Interpolation ended.
 void SetKeyframe(byte NewKeyNum, vector NewLocation, rotator NewRotation)
     
// Set the specified keyframe.
 void InterpolateTo(byte NewKeyNum, float Seconds)
     
// Interpolate to keyframe KeyNum in Seconds time.
 Actor SpecialHandling(Pawn Other)
 bool HandleTriggerDoor(Pawn Other)
 bool HandleDoor(Pawn Other)
     
implement the appropriate version
*/



Source Code


00001	//=============================================================================
00002	// The moving brush class.
00003	// This is a built-in Unreal class and it shouldn't be modified.
00004	//=============================================================================
00005	class Mover extends Brush
00006		native;
00007	//	nativereplication;
00008	
00009	// How the mover should react when it encroaches an actor.
00010	var() enum EMoverEncroachType
00011	{
00012		ME_StopWhenEncroach,	// Stop when we hit an actor.
00013		ME_ReturnWhenEncroach,	// Return to previous position when we hit an actor.
00014	   	ME_CrushWhenEncroach,   // Crush the poor helpless actor.
00015	   	ME_IgnoreWhenEncroach,  // Ignore encroached actors.
00016	} MoverEncroachType;
00017	
00018	// How the mover moves from one position to another.
00019	var() enum EMoverGlideType
00020	{
00021		MV_MoveByTime,			// Move linearly.
00022		MV_GlideByTime,			// Move with smooth acceleration.
00023	} MoverGlideType;
00024	
00025	// What classes can bump trigger this mover
00026	var() enum EBumpType
00027	{
00028		BT_PlayerBump,		// Can only be bumped by player.
00029		BT_PawnBump,		// Can be bumped by any pawn
00030		BT_CreatureBump,	// RUNE:  Non-player pawn bump
00031		BT_AnyBump,			// Cany be bumped by any solid actor
00032	} BumpType;
00033	
00034	//-----------------------------------------------------------------------------
00035	// Keyframe numbers.
00036	var() byte       KeyNum;           // Current or destination keyframe.
00037	var byte         PrevKeyNum;       // Previous keyframe.
00038	var() const byte NumKeys;          // Number of keyframes in total (0-3).
00039	var() const byte WorldRaytraceKey; // Raytrace the world with the brush here.
00040	var() const byte BrushRaytraceKey; // Raytrace the brush here.
00041	
00042	//-----------------------------------------------------------------------------
00043	// Movement parameters.
00044	var() float      MoveTime[16];      // Time to spend moving between keyframes. RUNE:  Variable movetimes
00045	var() float      StayOpenTime;     // How long to remain open before closing.
00046	var() float      OtherTime;        // TriggerPound stay-open time.
00047	var() int        EncroachDamage;   // How much to damage encroached actors.
00048	var() name		 InterpolateEvent[16]; // RUME:  Events to call at each interpolation point
00049	
00050	//-----------------------------------------------------------------------------
00051	// Mover state.
00052	var() bool       bTriggerOnceOnly; // Go dormant after first trigger.
00053	var() bool       bSlave;           // This brush is a slave.
00054	var() bool		 bUseTriggered;		// Triggered by player grab
00055	var() bool		 bDamageTriggered;	// Triggered by taking damage
00056	var() bool       bDynamicLightMover; // Apply dynamic lighting to mover.
00057	var() name       PlayerBumpEvent;  // Optional event to cause when the player bumps the mover.
00058	var() name       BumpEvent;			// Optional event to cause when any valid bumper bumps the mover.
00059	var   actor      SavedTrigger;      // Who we were triggered by.
00060	var() float		 DamageThreshold;	// minimum damage to trigger
00061	var	  int		 numTriggerEvents;	// number of times triggered ( count down to untrigger )
00062	var	  Mover		 Leader;			// for having multiple movers return together
00063	var	  Mover		 Follower;
00064	var() name		 ReturnGroup;		// if none, same as tag
00065	var() float		 DelayTime;			// delay before starting to open
00066	
00067	//-----------------------------------------------------------------------------
00068	// Audio.
00069	var(MoverSounds) sound      OpeningSound;     // When start opening.
00070	var(MoverSounds) sound      OpenedSound;      // When finished opening.
00071	var(MoverSounds) sound      ClosingSound;     // When start closing.
00072	var(MoverSounds) sound      ClosedSound;      // When finish closing.
00073	var(MoverSounds) sound      MoveAmbientSound; // Optional ambient sound when moving.
00074	
00075	//-----------------------------------------------------------------------------
00076	// Internal.
00077	var vector       KeyPos[16];
00078	var rotator      KeyRot[16];
00079	var vector       BasePos, OldPos, OldPrePivot, SavedPos;
00080	var rotator      BaseRot, OldRot, SavedRot;
00081	
00082	// AI related
00083	var       NavigationPoint  myMarker;
00084	var		  Actor			TriggerActor;
00085	var		  Actor         TriggerActor2;
00086	var		  Pawn			WaitingPawn;
00087	var		  bool			bOpening, bDelaying, bClientPause;
00088	var		  bool			bPlayerOnly;
00089	var		  Trigger		RecommendedTrigger;
00090	
00091	// for client side replication
00092	var		vector			SimOldPos;
00093	var		int				SimOldRotPitch, SimOldRotYaw, SimOldRotRoll;
00094	var		vector			SimInterpolate;
00095	var		vector			RealPosition;
00096	var     rotator			RealRotation;
00097	var		int				ClientUpdate;
00098	
00099	replication
00100	{
00101		// Things the server should send to the client.
00102		reliable if( Role==ROLE_Authority )
00103			SimOldPos, SimOldRotPitch, SimOldRotYaw, SimOldRotRoll, SimInterpolate, RealPosition, RealRotation;
00104	}
00105	
00106	simulated function Timer()
00107	{
00108		if ( Velocity != vect(0,0,0) )
00109		{
00110			bClientPause = false;
00111			return;		
00112		}
00113		if ( Level.NetMode == NM_Client )
00114		{
00115			if ( ClientUpdate == 0 ) // not doing a move
00116			{
00117				if ( bClientPause )
00118				{
00119					if ( VSize(RealPosition - Location) > 3 )
00120						SetLocation(RealPosition);
00121					else
00122						RealPosition = Location;
00123					SetRotation(RealRotation);
00124					bClientPause = false;
00125				}
00126				else if ( RealPosition != Location )
00127					bClientPause = true;
00128			}
00129			else
00130				bClientPause = false;
00131		}
00132		else
00133		{
00134			RealPosition = Location;
00135			RealRotation = Rotation;
00136		}
00137	}
00138			
00139	function FindTriggerActor()
00140	{
00141		local Actor A;
00142	
00143		TriggerActor = None;
00144		TriggerActor2 = None;
00145		ForEach AllActors(class 'Actor', A)
00146			if ( (A.Event == Tag) && (A.IsA('Trigger') || A.IsA('Mover')) )
00147			{
00148				if ( A.IsA('Counter') || A.IsA('Pawn') )
00149				{
00150					bPlayerOnly = true;
00151					return; //FIXME - handle counters
00152				}
00153				if (TriggerActor == None)
00154					TriggerActor = A;
00155				else if ( TriggerActor2 == None )
00156					TriggerActor2 = A;
00157			}
00158	
00159		if ( TriggerActor == None )
00160		{
00161			bPlayerOnly = (BumpType == BT_PlayerBump);
00162			return;
00163		}
00164	
00165		bPlayerOnly = ( TriggerActor.IsA('Trigger') && (Trigger(TriggerActor).TriggerType == TT_PlayerProximity) );
00166		if ( bPlayerOnly && ( TriggerActor2 != None) )
00167		{
00168			bPlayerOnly = ( TriggerActor2.IsA('Trigger') && (Trigger(TriggerActor).TriggerType == TT_PlayerProximity) );
00169			if ( !bPlayerOnly )
00170			{
00171				A = TriggerActor;
00172				TriggerActor = TriggerActor2;
00173				TriggerActor2 = A;
00174			}
00175		}
00176	}
00177	
00178	/* set specialgoal/movetarget or special pause if necessary
00179	if mover can't be affected by this pawn, return false
00180	Each mover state should implement the appropriate version
00181	*/
00182	function bool HandleDoor(pawn Other)
00183	{
00184		return false;
00185	}
00186	
00187	function bool HandleTriggerDoor(pawn Other)
00188	{
00189		local bool bOne, bTwo;
00190		local float DP1, DP2, Dist1, Dist2;
00191	
00192		if ( bOpening || bDelaying )
00193		{
00194			WaitingPawn = Other;
00195			Other.SpecialPause = 2.5;
00196			return true;
00197		}
00198		if ( bPlayerOnly && !Other.bIsPlayer )
00199			return false;
00200		if ( bUseTriggered )
00201		{
00202			WaitingPawn = Other;
00203			Other.SpecialPause = 2.5;
00204			Trigger(Other, Other);
00205			return true;
00206		}
00207		if ( (BumpEvent == tag) || (Other.bIsPlayer && (PlayerBumpEvent == tag)) )
00208		{
00209			WaitingPawn = Other;
00210			Other.SpecialPause = 2.5;
00211			if ( Other.Base == Self )
00212				Trigger(Other, Other);
00213			return true;
00214		}
00215		if ( bDamageTriggered )
00216		{
00217			WaitingPawn = Other;
00218			Other.SpecialGoal = self;
00219			if ( !Other.bCanDoSpecial || (Other.Weapon == None) )
00220				return false;
00221	
00222			Other.Target = self;
00223			Other.bShootSpecial = true;
00224			Trigger(Self, Other);
00225			Other.bFire = 0;
00226			Other.bAltFire = 0;
00227			return true;
00228		}
00229	
00230		if ( RecommendedTrigger != None )
00231		{
00232			Other.SpecialGoal = RecommendedTrigger;
00233			Other.MoveTarget = RecommendedTrigger;
00234			return True;
00235		}
00236	
00237		bOne = ( (TriggerActor != None) 
00238				&& (!TriggerActor.IsA('Trigger') || Trigger(TriggerActor).IsRelevant(Other)) );
00239		bTwo = ( (TriggerActor2 != None) 
00240				&& (!TriggerActor2.IsA('Trigger') || Trigger(TriggerActor2).IsRelevant(Other)) );
00241		
00242		if ( bOne && bTwo )
00243		{
00244			// Dotp, dist
00245			Dist1 = VSize(TriggerActor.Location - Other.Location);
00246			Dist2 = VSize(TriggerActor2.Location - Other.Location);
00247			if ( Dist1 < Dist2 )
00248			{
00249				if ( (Dist1 < 500) && Other.ActorReachable(TriggerActor) )
00250					bTwo = false;
00251			}
00252			else if ( (Dist2 < 500) && Other.ActorReachable(TriggerActor2) )
00253				bOne = false;
00254			
00255			if ( bOne && bTwo )
00256			{
00257				DP1 = Normal(Location - Other.Location) Dot (TriggerActor.Location - Other.Location)/Dist1;
00258				DP2 = Normal(Location - Other.Location) Dot (TriggerActor2.Location - Other.Location)/Dist2;
00259				if ( (DP1 > 0) && (DP2 < 0) )
00260					bOne = false;
00261				else if ( (DP1 < 0) && (DP2 > 0) )
00262					bTwo = false;
00263				else if ( Dist1 < Dist2 )
00264					bTwo = false;
00265				else 
00266					bOne = false;
00267			}
00268		}
00269	
00270		if ( bOne )
00271		{
00272			Other.SpecialGoal = TriggerActor;
00273			Other.MoveTarget = TriggerActor;
00274			return True;
00275		}
00276		else if ( bTwo )
00277		{
00278			Other.SpecialGoal = TriggerActor2;
00279			Other.MoveTarget = TriggerActor2;
00280			return True;
00281		}
00282		return false;
00283	}
00284	
00285	function Actor SpecialHandling(Pawn Other)
00286	{
00287		if ( bDamageTriggered )	
00288		{
00289			if ( !Other.bCanDoSpecial || (Other.Weapon == None) )
00290				return None;
00291	
00292			Other.Target = self;
00293			Other.bShootSpecial = true;
00294	//		Other.FireWeapon();
00295			Other.bFire = 0;
00296			Other.bAltFire = 0;
00297			return self;
00298		}
00299	
00300		if ( BumpType == BT_PlayerBump && !Other.bIsPlayer )
00301			return None;
00302	
00303		return self;
00304	}
00305	
00306	//-----------------------------------------------------------------------------
00307	// Movement functions.
00308	
00309	// Interpolate to keyframe KeyNum in Seconds time.
00310	final function InterpolateTo( byte NewKeyNum, float Seconds )
00311	{
00312		local Actor A;
00313	
00314		NewKeyNum = Clamp( NewKeyNum, 0, ArrayCount(KeyPos)-1 );
00315		if( NewKeyNum==PrevKeyNum && KeyNum!=PrevKeyNum )
00316		{
00317			// Reverse the movement smoothly.
00318			PhysAlpha = 1.0 - PhysAlpha;
00319			OldPos    = BasePos + KeyPos[KeyNum];
00320			OldRot    = BaseRot + KeyRot[KeyNum];
00321		}
00322		else
00323		{
00324			// Start a new movement.
00325			OldPos    = Location;
00326			OldRot    = Rotation;
00327			PhysAlpha = 0.0;
00328		}
00329	
00330		// Setup physics.
00331		SetPhysics(PHYS_MovingBrush);
00332		bInterpolating   = true;
00333		PrevKeyNum       = KeyNum;
00334		KeyNum			 = NewKeyNum;
00335		PhysRate         = 1.0 / FMax(Seconds, 0.005);
00336	
00337		ClientUpdate++;
00338		SimOldPos = OldPos;
00339		SimOldRotYaw = OldRot.Yaw;
00340		SimOldRotPitch = OldRot.Pitch;
00341		SimOldRotRoll = OldRot.Roll;
00342		SimInterpolate.X = 100 * PhysAlpha;
00343		SimInterpolate.Y = 100 * FMax(0.01, PhysRate);
00344		SimInterpolate.Z = 256 * PrevKeyNum + KeyNum;
00345		
00346		// Call events at each interpolation point	
00347		if(InterpolateEvent[PrevKeyNum] != 'None')
00348		{ // Call the event on this interpolation point
00349			foreach AllActors(class 'Actor', A, InterpolateEvent[PrevKeyNum])
00350			{
00351				A.Trigger(self, None);
00352			}
00353		}	
00354	}
00355	
00356	// Set the specified keyframe.
00357	final function SetKeyframe( byte NewKeyNum, vector NewLocation, rotator NewRotation )
00358	{
00359		KeyNum         = Clamp( NewKeyNum, 0, ArrayCount(KeyPos)-1 );
00360		KeyPos[KeyNum] = NewLocation;
00361		KeyRot[KeyNum] = NewRotation;
00362	}
00363	
00364	// Interpolation ended.
00365	function InterpolateEnd( actor Other )
00366	{
00367		local byte OldKeyNum;
00368		local Actor A;
00369	
00370		OldKeyNum  = PrevKeyNum;
00371		PrevKeyNum = KeyNum;
00372		PhysAlpha  = 0;
00373		ClientUpdate--;
00374	
00375		// If more than two keyframes, chain them.
00376		if( KeyNum>0 && KeyNum<OldKeyNum )
00377		{
00378			// Chain to previous.
00379			InterpolateTo(KeyNum-1, MoveTime[KeyNum-1]); // RUNE:  Added variable Movetimes
00380		}
00381		else if( KeyNum<NumKeys-1 && KeyNum>OldKeyNum )
00382		{
00383			// Chain to next.
00384			InterpolateTo(KeyNum+1, MoveTime[KeyNum]); // RUNE:  Added variable Movetimes
00385		}
00386		else
00387		{
00388			// Call events at each interpolation point (end point)
00389			if(InterpolateEvent[PrevKeyNum] != 'None')
00390			{ // Call the event on this interpolation point
00391				foreach AllActors(class 'Actor', A, InterpolateEvent[PrevKeyNum])
00392				{
00393					A.Trigger(self, None);
00394				}
00395			}	
00396			
00397			// Finished interpolating.
00398			AmbientSound = None;
00399			if ( (ClientUpdate == 0) && (Level.NetMode != NM_Client) )
00400			{
00401				RealPosition = Location;
00402				RealRotation = Rotation;
00403			}
00404		}
00405	}
00406	
00407	//-----------------------------------------------------------------------------
00408	// Mover functions.
00409	
00410	// Notify AI that mover finished movement
00411	function FinishNotify()
00412	{
00413		local Pawn P;
00414	
00415		if ( StandingCount > 0 )
00416			for ( P=Level.PawnList; P!=None; P=P.nextPawn )
00417				if ( P.Base == self )
00418				{
00419					P.StopWaiting();
00420					if ( (P.SpecialGoal == self) || (P.SpecialGoal == myMarker) )
00421						P.SpecialGoal = None; 
00422					if ( P == WaitingPawn )
00423						WaitingPawn = None;
00424				}
00425	
00426		if ( WaitingPawn != None )
00427		{
00428			WaitingPawn.StopWaiting();
00429			if ( (WaitingPawn.SpecialGoal == self) || (WaitingPawn.SpecialGoal == myMarker) )
00430				WaitingPawn.SpecialGoal = None; 
00431			WaitingPawn = None;
00432		}
00433	}
00434	
00435	// Handle when the mover finishes closing.
00436	function FinishedClosing()
00437	{
00438		// Update sound effects.
00439		PlaySound( ClosedSound, SLOT_None );
00440	
00441		// Notify our triggering actor that we have completed.
00442		if( SavedTrigger != None )
00443			SavedTrigger.EndEvent();
00444		SavedTrigger = None;
00445		Instigator = None;
00446		FinishNotify(); 
00447	}
00448	
00449	// Handle when the mover finishes opening.
00450	function FinishedOpening()
00451	{
00452		local actor A;
00453	
00454		// Update sound effects.
00455		PlaySound( OpenedSound, SLOT_None );
00456		
00457		// Trigger any chained movers.
00458		if( Event != '' )
00459			foreach AllActors( class 'Actor', A, Event )
00460				A.Trigger( Self, Instigator );
00461	
00462		FinishNotify();
00463	}
00464	
00465	// Open the mover.
00466	function DoOpen()
00467	{
00468		bOpening = true;
00469		bDelaying = false;
00470		InterpolateTo( 1, MoveTime[0] ); // RUNE:  Added variable Movetimes
00471		PlaySound( OpeningSound, SLOT_None );
00472		AmbientSound = MoveAmbientSound;
00473	}
00474	
00475	// Close the mover.
00476	function DoClose()
00477	{
00478		local actor A;
00479	
00480		bOpening = false;
00481		bDelaying = false;
00482		InterpolateTo( Max(0,KeyNum-1), MoveTime[Max(0, KeyNum-1)]); // RUNE:  Added variable Movetimes
00483		PlaySound( ClosingSound, SLOT_None );
00484		if( Event != '' )
00485			foreach AllActors( class 'Actor', A, Event )
00486				A.UnTrigger( Self, Instigator );
00487		AmbientSound = MoveAmbientSound;
00488	}
00489	
00490	//-----------------------------------------------------------------------------
00491	// Engine notifications.
00492	
00493	// When mover enters gameplay.
00494	simulated function BeginPlay()
00495	{
00496		local rotator R;
00497	
00498		// timer updates real position every second in network play
00499		if ( Level.NetMode != NM_Standalone )
00500		{
00501			if ( Level.NetMode == NM_Client )
00502				settimer(4.0, true);
00503			else
00504				settimer(1.0, true);
00505			if ( Role < ROLE_Authority )
00506				return;
00507		}
00508	
00509		if ( Level.NetMode != NM_Client )
00510		{
00511			RealPosition = Location;
00512			RealRotation = Rotation;
00513		}
00514	
00515		// Init key info.
00516		Super.BeginPlay();
00517		KeyNum         = Clamp( KeyNum, 0, ArrayCount(KeyPos)-1 );
00518		PhysAlpha      = 0.0;
00519	
00520		// Set initial location.
00521		Move( BasePos + KeyPos[KeyNum] - Location );
00522	
00523		// Initial rotation.
00524		SetRotation( BaseRot + KeyRot[KeyNum] );
00525	
00526		// find movers in same group
00527		if ( ReturnGroup == '' )
00528			ReturnGroup = tag;
00529	}
00530	
00531	// Immediately after mover enters gameplay.
00532	function PostBeginPlay()
00533	{
00534		local mover M;
00535	
00536		//brushes can't be deleted, so if not relevant, make it invisible and non-colliding
00537		if ( !Level.Game.IsRelevant(self) )
00538		{
00539			SetCollision(false, false, false);
00540			SetLocation(Location + vect(0,0,20000)); // temp since still in bsp
00541			bHidden = true;
00542		}
00543		else
00544		{
00545			FindTriggerActor();
00546			// Initialize all slaves.
00547			if( !bSlave )
00548			{
00549				foreach AllActors( class 'Mover', M, Tag )
00550				{
00551					if( M.bSlave )
00552					{
00553						M.GotoState('');
00554						M.SetBase( Self );
00555					}
00556				}
00557			}
00558			if ( Leader == None )
00559			{	
00560				Leader = self;
00561				ForEach AllActors( class'Mover', M )
00562					if ( (M != self) && (M.ReturnGroup == ReturnGroup) )
00563					{
00564						M.Leader = self;
00565						M.Follower = Follower;
00566						Follower = M;
00567					}
00568			}
00569		}
00570	}
00571	
00572	function MakeGroupStop()
00573	{
00574		// Stop moving immediately.
00575		bInterpolating = false;
00576		AmbientSound = None;
00577		GotoState( , '' );
00578	
00579		if ( Follower != None )
00580			Follower.MakeGroupStop();
00581	}
00582	
00583	function MakeGroupReturn()
00584	{
00585		// Abort move and reverse course.
00586		bInterpolating = false;
00587		AmbientSound = None;
00588		if( KeyNum<PrevKeyNum )
00589			GotoState( , 'Open' );
00590		else
00591			GotoState( , 'Close' );
00592	
00593		if ( Follower != None )
00594			Follower.MakeGroupReturn();
00595	}
00596			
00597	// Return true to abort, false to continue.
00598	function bool EncroachingOn( actor Other )
00599	{
00600		local Pawn P;
00601		if ( Other.IsA('Carcass') || Other.IsA('Decoration') )
00602		{
00603			Other.TakeDamage(10000, None, Other.Location, vect(0,0,0), 'Crushed');
00604			return false;
00605		}
00606		if ( Other.IsA('Fragment') || (Other.IsA('Inventory') && (Other.Owner == None)) )
00607		{
00608			Other.Destroy();
00609			return false;
00610		}
00611	
00612		// Damage the encroached actor.
00613		if( EncroachDamage != 0 )
00614			Other.TakeDamage( EncroachDamage, Instigator, Other.Location, vect(0,0,0), 'Crushed' );
00615	
00616		// If we have a bump-player event, and Other is a pawn, do the bump thing.
00617		P = Pawn(Other);
00618		if( P!=None && P.bIsPlayer )
00619		{
00620			if ( PlayerBumpEvent!='' )
00621				Bump( Other );
00622			if ( (MyMarker != None) && (P.Base != self) 
00623				&& (P.Location.Z < MyMarker.Location.Z - P.CollisionHeight - 0.7 * MyMarker.CollisionHeight) )
00624				// pawn is under lift - tell him to move
00625				P.UnderLift(self);
00626		}
00627	
00628		// Stop, return, or whatever.
00629		if( MoverEncroachType == ME_StopWhenEncroach )
00630		{
00631			Leader.MakeGroupStop();
00632			return true;
00633		}
00634		else if( MoverEncroachType == ME_ReturnWhenEncroach )
00635		{
00636			Leader.MakeGroupReturn();
00637			return true;
00638		}
00639		else if( MoverEncroachType == ME_CrushWhenEncroach )
00640		{
00641			// Kill it.
00642			Other.KilledBy( Instigator );
00643			return false;
00644		}
00645		else if( MoverEncroachType == ME_IgnoreWhenEncroach )
00646		{
00647			// Ignore it.
00648			return false;
00649		}
00650	}
00651	
00652	// When bumped by player.
00653	function Bump( actor Other )
00654	{
00655		local actor A;
00656		local pawn  P;
00657	
00658		P = Pawn(Other);
00659		if ( (BumpType != BT_AnyBump) && (P == None) )
00660			return;
00661		if ( (BumpType == BT_PlayerBump) && !P.bIsPlayer )
00662			return;
00663		if ( (BumpType == BT_PawnBump) && (Other.Mass < 10) )
00664			return;
00665		if((BumpType == BT_CreatureBump) && (Other.Mass < 10 || P.bIsPlayer))
00666			return; // RUNE:  Non-player pawn bump
00667	
00668		if( BumpEvent!='' )
00669			foreach AllActors( class 'Actor', A, BumpEvent )
00670				A.Trigger( Self, P );
00671	
00672		if ( P != None )
00673		{
00674			if( P.bIsPlayer && (PlayerBumpEvent!='') )
00675					foreach AllActors( class 'Actor', A, PlayerBumpEvent )
00676							A.Trigger( Self, P );
00677	
00678			if ( P.SpecialGoal == self )
00679				P.SpecialGoal = None;
00680		}
00681	}
00682	
00683	function bool UseTrigger(Actor Other)
00684	{
00685		if ( bUseTriggered )
00686		{
00687			self.Trigger(self, Pawn(Other));
00688			return true;
00689		}
00690		return false;
00691	}
00692	
00693	function bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
00694	{
00695		if ( bDamageTriggered && (Damage >= DamageThreshold) )
00696			self.Trigger(self, EventInstigator);
00697	
00698		return false;
00699	}
00700	
00701	
00702	//-----------------------------------------------------------------------------
00703	// Trigger states.
00704	
00705	// When triggered, open, wait, then close.
00706	state() TriggerOpenTimed
00707	{
00708		function bool HandleDoor(pawn Other)
00709		{
00710			return HandleTriggerDoor(Other);
00711		}
00712	
00713		function Trigger( actor Other, pawn EventInstigator )
00714		{
00715			SavedTrigger = Other;
00716			Instigator = EventInstigator;
00717			if ( SavedTrigger != None )
00718				SavedTrigger.BeginEvent();
00719			GotoState( 'TriggerOpenTimed', 'Open' );
00720		}
00721	
00722		function BeginState()
00723		{
00724			bOpening = false;
00725		}
00726	
00727	Open:
00728		Disable( 'Trigger' );
00729		if ( DelayTime > 0 )
00730		{
00731			bDelaying = true;
00732			Sleep(DelayTime);
00733		}
00734		DoOpen();
00735		FinishInterpolation();
00736		FinishedOpening();
00737		Sleep( StayOpenTime );
00738		if( bTriggerOnceOnly )
00739			GotoState('');
00740	Close:
00741		DoClose();
00742		FinishInterpolation();
00743		FinishedClosing();
00744		Enable( 'Trigger' );
00745	}
00746	
00747	// Toggle when triggered.
00748	state() TriggerToggle
00749	{
00750		function bool HandleDoor(pawn Other)
00751		{
00752			return HandleTriggerDoor(Other);
00753		}
00754		
00755		function Trigger( actor Other, pawn EventInstigator )
00756		{
00757			SavedTrigger = Other;
00758			Instigator = EventInstigator;
00759			if ( SavedTrigger != None )
00760				SavedTrigger.BeginEvent();
00761			if( KeyNum==0 || KeyNum<PrevKeyNum )
00762				GotoState( 'TriggerToggle', 'Open' );
00763			else
00764				GotoState( 'TriggerToggle', 'Close' );
00765		}
00766	Open:
00767		if ( DelayTime > 0 )
00768		{
00769			bDelaying = true;
00770			Sleep(DelayTime);
00771		}
00772		DoOpen();
00773		FinishInterpolation();
00774		FinishedOpening();
00775		if ( SavedTrigger != None )
00776			SavedTrigger.EndEvent();
00777		if( bTriggerOnceOnly ) // RUNE
00778			GotoState('');
00779		Stop;
00780	Close:		
00781		DoClose();
00782		FinishInterpolation();
00783		FinishedClosing();
00784	}
00785	
00786	// Open when triggered, close when get untriggered.
00787	state() TriggerControl
00788	{
00789		function bool HandleDoor(pawn Other)
00790		{
00791			return HandleTriggerDoor(Other);
00792		}
00793	
00794		function Trigger( actor Other, pawn EventInstigator )
00795		{
00796			numTriggerEvents++;
00797			SavedTrigger = Other;
00798			Instigator = EventInstigator;
00799			if ( SavedTrigger != None )
00800				SavedTrigger.BeginEvent();
00801			GotoState( 'TriggerControl', 'Open' );
00802		}
00803		function UnTrigger( actor Other, pawn EventInstigator )
00804		{
00805			numTriggerEvents--;
00806			if ( numTriggerEvents <=0 )
00807			{
00808				numTriggerEvents = 0;
00809				SavedTrigger = Other;
00810				Instigator = EventInstigator;
00811				SavedTrigger.BeginEvent();
00812				GotoState( 'TriggerControl', 'Close' );
00813			}
00814		}
00815	
00816		function BeginState()
00817		{
00818			numTriggerEvents = 0;
00819		}
00820	
00821	Open:
00822		if ( DelayTime > 0 )
00823		{
00824			bDelaying = true;
00825			Sleep(DelayTime);
00826		}
00827		DoOpen();
00828		FinishInterpolation();
00829		FinishedOpening();
00830		SavedTrigger.EndEvent();
00831		if( bTriggerOnceOnly )
00832			GotoState('');
00833		Stop;
00834	Close:		
00835		DoClose();
00836		FinishInterpolation();
00837		FinishedClosing();
00838	}
00839	
00840	// Start pounding when triggered.
00841	state() TriggerPound
00842	{
00843		function bool HandleDoor(pawn Other)
00844		{
00845			return HandleTriggerDoor(Other);
00846		}
00847	
00848		function Trigger( actor Other, pawn EventInstigator )
00849		{
00850			numTriggerEvents++;
00851			SavedTrigger = Other;
00852			Instigator = EventInstigator;
00853			GotoState( 'TriggerPound', 'Open' );
00854		}
00855		function UnTrigger( actor Other, pawn EventInstigator )
00856		{
00857			numTriggerEvents--;
00858			if ( numTriggerEvents <= 0 )
00859			{
00860				numTriggerEvents = 0;
00861				SavedTrigger = None;
00862				Instigator = None;
00863				GotoState( 'TriggerPound', 'Close' );
00864			}
00865		}
00866		function BeginState()
00867		{
00868			numTriggerEvents = 0;
00869		}
00870	
00871	Open:
00872		if ( DelayTime > 0 )
00873		{
00874			bDelaying = true;
00875			Sleep(DelayTime);
00876		}
00877		DoOpen();
00878		FinishInterpolation();
00879		Sleep(OtherTime);
00880	Close:
00881		DoClose();
00882		FinishInterpolation();
00883		Sleep(StayOpenTime);
00884		if( bTriggerOnceOnly )
00885			GotoState('');
00886		if( SavedTrigger != None )
00887			goto 'Open';
00888	}
00889	
00890	//-----------------------------------------------------------------------------
00891	// Bump states.
00892	
00893	// Open when bumped, wait, then close.
00894	state() BumpOpenTimed
00895	{
00896		function bool HandleDoor(pawn Other)
00897		{
00898			if ( (BumpType == BT_PlayerBump) && !Other.bIsPlayer )
00899				return false;
00900	
00901			Bump(Other);
00902			WaitingPawn = Other;
00903			Other.SpecialPause = 2.5;
00904			return true;
00905		}
00906	
00907		function Bump( actor Other )
00908		{
00909			if ( (BumpType != BT_AnyBump) && (Pawn(Other) == None) )
00910				return;
00911			if ( (BumpType == BT_PlayerBump) && !Pawn(Other).bIsPlayer )
00912				return;
00913			if ( (BumpType == BT_PawnBump) && (Other.Mass < 10) )
00914				return;
00915			if((BumpType == BT_CreatureBump) && (Other.Mass < 10 || Pawn(Other).bIsPlayer))
00916				return; // RUNE:  Non-player pawn bump
00917	
00918			Global.Bump( Other );
00919			SavedTrigger = None;
00920			Instigator = Pawn(Other);
00921			GotoState( 'BumpOpenTimed', 'Open' );
00922		}
00923	Open:
00924		Disable( 'Bump' );
00925		if ( DelayTime > 0 )
00926		{
00927			bDelaying = true;
00928			Sleep(DelayTime);
00929		}
00930		DoOpen();
00931		FinishInterpolation();
00932		FinishedOpening();
00933		Sleep( StayOpenTime );
00934		if( bTriggerOnceOnly )
00935			GotoState('');
00936	Close:
00937		DoClose();
00938		FinishInterpolation();
00939		FinishedClosing();
00940		Enable( 'Bump' );
00941	}
00942	
00943	// Open when bumped, close when reset.
00944	state() BumpButton
00945	{
00946		function bool HandleDoor(pawn Other)
00947		{
00948			if ( (BumpType == BT_PlayerBump) && !Other.bIsPlayer )
00949				return false;
00950	
00951			Bump(Other);
00952			return false; //let pawn try to move around this button
00953		}
00954	
00955		function Bump( actor Other )
00956		{
00957			if ( (BumpType != BT_AnyBump) && (Pawn(Other) == None) )
00958				return;
00959			if ( (BumpType == BT_PlayerBump) && !Pawn(Other).bIsPlayer )
00960				return;
00961			if ( (BumpType == BT_PawnBump) && (Other.Mass < 10) )
00962				return;
00963			if((BumpType == BT_CreatureBump) && (Other.Mass < 10 || Pawn(Other).bIsPlayer))
00964				return; // RUNE:  Non-player pawn bump
00965	
00966			Global.Bump( Other );
00967			SavedTrigger = Other;
00968			Instigator = Pawn( Other );
00969			GotoState( 'BumpButton', 'Open' );
00970		}
00971		function BeginEvent()
00972		{
00973			bSlave=true;
00974		}
00975		function EndEvent()
00976		{
00977			bSlave     = false;
00978			Instigator = None;
00979			GotoState( 'BumpButton', 'Close' );
00980		}
00981	Open:
00982		Disable( 'Bump' );
00983		if ( DelayTime > 0 )
00984		{
00985			bDelaying = true;
00986			Sleep(DelayTime);
00987		}
00988		DoOpen();
00989		FinishInterpolation();
00990		FinishedOpening();
00991		if( bTriggerOnceOnly )
00992			GotoState('');
00993		if( bSlave )
00994			Stop;
00995	Close:
00996		DoClose();
00997		FinishInterpolation();
00998		FinishedClosing();
00999		Enable( 'Bump' );
01000	}
01001	
01002	//-----------------------------------------------------------------------------
01003	// Stand states.
01004	
01005	// Open when stood on, wait, then close.
01006	state() StandOpenTimed
01007	{
01008		function bool HandleDoor(pawn Other)
01009		{
01010			if ( bPlayerOnly && !Other.bIsPlayer )
01011				return false;
01012			Other.SpecialPause = 2.5;
01013			WaitingPawn = Other;
01014			if ( Other.Base == self )
01015				Attach(Other);
01016			return true;
01017		}
01018	
01019		function Attach( actor Other )
01020		{
01021			local pawn  P;
01022	
01023			P = Pawn(Other);
01024			if ( (BumpType != BT_AnyBump) && (P == None) )
01025				return;
01026			if ( (BumpType == BT_PlayerBump) && !P.bIsPlayer )
01027				return;
01028			if ( (BumpType == BT_PawnBump) && (Other.Mass < 10) )
01029				return;
01030			if((BumpType == BT_CreatureBump) && (Other.Mass < 10 || P.bIsPlayer))
01031				return; // RUNE:  Non-player pawn bump
01032	
01033			SavedTrigger = None;
01034			GotoState( 'StandOpenTimed', 'Open' );
01035		}
01036	Open:
01037		Disable( 'Attach' );
01038		if ( DelayTime > 0 )
01039		{
01040			bDelaying = true;
01041			Sleep(DelayTime);
01042		}
01043		DoOpen();
01044		FinishInterpolation();
01045		FinishedOpening();
01046		Sleep( StayOpenTime );
01047		if( bTriggerOnceOnly )
01048			GotoState('');
01049	Close:
01050		DoClose();
01051		FinishInterpolation();
01052		FinishedClosing();
01053		Enable( 'Attach' );
01054	}
01055	
01056	defaultproperties
01057	{
01058	     MoverEncroachType=ME_ReturnWhenEncroach
01059	     MoverGlideType=MV_GlideByTime
01060	     NumKeys=2
01061	     MoveTime(0)=1.000000
01062	     MoveTime(1)=1.000000
01063	     MoveTime(2)=1.000000
01064	     MoveTime(3)=1.000000
01065	     MoveTime(4)=1.000000
01066	     MoveTime(5)=1.000000
01067	     MoveTime(6)=1.000000
01068	     MoveTime(7)=1.000000
01069	     MoveTime(8)=1.000000
01070	     MoveTime(9)=1.000000
01071	     MoveTime(10)=1.000000
01072	     MoveTime(11)=1.000000
01073	     MoveTime(12)=1.000000
01074	     MoveTime(13)=1.000000
01075	     MoveTime(14)=1.000000
01076	     MoveTime(15)=1.000000
01077	     StayOpenTime=4.000000
01078	     bStatic=False
01079	     bIsMover=True
01080	     bAlwaysRelevant=True
01081	     Physics=PHYS_MovingBrush
01082	     RemoteRole=ROLE_SimulatedProxy
01083	     InitialState=BumpOpenTimed
01084	     SoundVolume=228
01085	     TransientSoundVolume=3.000000
01086	     CollisionRadius=160.000000
01087	     CollisionHeight=160.000000
01088	     bCollideActors=True
01089	     bBlockActors=True
01090	     bBlockPlayers=True
01091	     bSweepable=True
01092	     NetPriority=2.700000
01093	}

End Source Code