1
0
KF2-Dev-Scripts/Engine/Classes/LadderVolume.uc
2020-12-13 18:01:13 +03:00

151 lines
4.0 KiB
Ucode

/*=============================================================================
// LadderVolumes, when touched, cause ladder supporting actors to use Phys_Ladder.
// note that underwater ladders won't be waterzones (no breathing problems)
// Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
============================================================================= */
class LadderVolume extends PhysicsVolume
native
placeable;
var() rotator WallDir;
var vector LookDir;
var vector ClimbDir; // pawn can move in this direction (or reverse)
var const Ladder LadderList; // list of Ladder actors associated with this LadderVolume
var() bool bNoPhysicalLadder; // if true, won't push into/keep player against geometry in lookdir
var() bool bAutoPath; // add top and bottom ladders automatically
var() bool bAllowLadderStrafing; // if true, players on ladder can strafe sideways
var Pawn PendingClimber;
/** Editor visual cue for the direction of the wall */
var ArrowComponent WallDirArrow;
cpptext
{
// Editor modification
#if WITH_EDITOR
FVector FindTop(FVector V);
FVector FindCenter();
virtual INT AddMyMarker(AActor *S);
#endif
virtual void PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent);
}
simulated event PostBeginPlay()
{
local Ladder L, M;
local vector Dir;
Super.PostBeginPlay();
LookDir = vector(WallDir);
if ( !bAutoPath && (LookDir.Z != 0) )
{
ClimbDir = vect(0,0,1);
for ( L=LadderList; L!=None; L=L.LadderList )
for ( M=LadderList; M!=None; M=M.LadderList )
if ( M != L )
{
Dir = Normal(M.Location - L.Location);
if ( (Dir dot ClimbDir) < 0 )
Dir *= -1;
ClimbDir += Dir;
}
ClimbDir = Normal(ClimbDir);
if ( (ClimbDir Dot vect(0,0,1)) < 0 )
ClimbDir *= -1;
}
}
function bool InUse(Pawn Ignored)
{
local Pawn StillClimbing;
ForEach TouchingActors(class'Pawn',StillClimbing)
{
if ( (StillClimbing != Ignored) && StillClimbing.bCollideActors && StillClimbing.bBlockActors )
return true;
}
if ( PendingClimber != None )
{
if ( (PendingClimber.Controller == None)
|| !PendingClimber.bCollideActors || !PendingClimber.bBlockActors
|| (Ladder(PendingClimber.Controller.MoveTarget) == None)
|| (Ladder(PendingClimber.Controller.MoveTarget).MyLadder != self) )
PendingClimber = None;
}
return ( (PendingClimber != None) && (PendingClimber != Ignored) );
}
simulated event PawnEnteredVolume(Pawn P)
{
local rotator PawnRot;
Super.PawnEnteredVolume(P);
if ( !P.CanGrabLadder() )
return;
PawnRot = P.Rotation;
PawnRot.Pitch = 0;
if ( (vector(PawnRot) Dot LookDir > 0.9)
|| ((AIController(P.Controller) != None) && (Ladder(P.Controller.MoveTarget) != None)) )
P.ClimbLadder(self);
else if ( !P.bDeleteMe && (P.Controller != None) )
spawn(class'PotentialClimbWatcher',P);
}
simulated event PawnLeavingVolume(Pawn P)
{
local Controller C;
if ( P.OnLadder != self )
return;
Super.PawnLeavingVolume(P);
P.OnLadder = None;
P.EndClimbLadder(self);
if ( P == PendingClimber )
PendingClimber = None;
// tell all waiting pawns, if not in use
if ( !InUse(P) )
{
foreach WorldInfo.AllControllers(class'Controller', C)
{
if (C.bPreparingMove && Ladder(C.MoveTarget) != None && Ladder(C.MoveTarget).MyLadder == self)
{
C.bPreparingMove = false;
PendingClimber = C.Pawn;
return;
}
}
}
}
simulated event PhysicsChangedFor(Actor Other)
{
if ( (Other.Physics == PHYS_Falling) || (Other.Physics == PHYS_Ladder) || Other.bDeleteMe || (Pawn(Other) == None) || (Pawn(Other).Controller == None) )
return;
spawn(class'PotentialClimbWatcher',Other);
}
defaultproperties
{
Begin Object Class=ArrowComponent Name=Arrow
ArrowColor=(R=150,G=100,B=150)
ArrowSize=5.0
End Object
WallDirArrow = Arrow
Components.Add(Arrow)
Begin Object Name=BrushComponent0
HiddenEditor=false
End Object
RemoteRole=ROLE_SimulatedProxy
ClimbDir=(X=+0.0,Y=+0.0,Z=+1.0)
bAutoPath=true
bAllowLadderStrafing=true
}