//============================================================================= // KFPathnode //============================================================================= // Base KF NavigationPoint that provides some additional options //============================================================================= // Killing Floor 2 // Copyright (C) 2012-2013 Tripwire Interactive LLC //============================================================================= class KFPathnode extends PathNode native(Waypoint); /** Used internally, set to true if this node is a jump destination for a KFJumpSpot node */ var() duplicatetransient editconst bool bIsJumpDest; var() duplicatetransient editconst bool bIsDropDownDest; var() duplicatetransient editconst vector JumpVelocity; /** How long the jump should take. Altering this value changes the JumpVelocity. */ var() duplicatetransient float JumpTime; var() duplicatetransient bool bDebugLogAnchorUsability; var() duplicatetransient bool bAutoConnectToOtherFloors; var() duplicatetransient bool bPauseWhenReached; var() duplicatetransient float PauseDuration; var() const editconst bool bHasDoorLOS; /** If this node is on a wall and connected to a ceiling node, then auto adjust those node's height if too low */ var() bool bAutoAdjustZToCeiling; var class WallReachSpecClass; var bool bAutoFlushPersistentDebugLines; /** If checked, this pathnode will not be considered by the trader trail emitter */ var() bool bIgnoredByTraderTrail; cpptext { #if WITH_EDITOR virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent ); virtual void AddForcedSpecs( AScout *Scout ) {} virtual UReachSpec* ForcePathTo(ANavigationPoint *Nav, AScout *Scout = NULL, UClass* ReachSpecClass = NULL ); virtual UBOOL ProscribePathTo(ANavigationPoint *Nav, AScout *Scout = NULL); virtual UBOOL ConnectWallToFloor( AKFPathnode* FloorNode ) { return FALSE; } virtual UBOOL ConnectFloorToWall( AKFPathnode* WallNode ); virtual void AddFloorToWallSpec(); virtual void AddSpecialReachSpecs(); virtual UBOOL CanConnectTo(ANavigationPoint* Nav, UBOOL bCheckDistance); virtual void CheckForErrors(); virtual void PostEditMove( UBOOL bFinished ); virtual void AutoAdjustHeightToCeiling(); #endif //WITH_EDITOR /** Overridden to support wall node Max2DDistToFloorNodes and MaxDropFromWallDistance overrides */ virtual UClass* GetReachSpecClass( ANavigationPoint* Nav, UClass* DefaultReachSpecClass ); /** Clean up when destroyed */ virtual void PostScriptDestroyed(); /** Reset DropDownDest flag */ virtual void ClearPaths(); virtual UBOOL CalculateJumpVelocity( AScout *Scout ); } native function vector ComputeTrajectoryByTime( vector StartPosition, vector EndPosition, float EndTime ); /** Returns this node's "up" direction, or 0 if using default floor. GetUpDir() isn't native and this allows script to call it. As an example, "Up" for KFWallPathnodes is: -(Rotation.Vector()) */ native function vector GetUpVector(); native function bool IsUsableAnchorFor( Pawn P ); /** Returns the nearest valid navigation on the floor to the given actor */ static final function NavigationPoint GetNearestFloorNavToActor(Actor ChkActor, optional class RequiredClass,optional array ExcludeList,optional float MinDist) { local NavigationPoint Nav, BestNav; local float Dist, BestDist; if( ChkActor != None ) { // iterate through all points in the level foreach ChkActor.WorldInfo.AllNavigationPoints( class'NavigationPoint', Nav ) { if( Nav.bWallNode ) { continue; } // if no filter class specified, and // if nav is available to the check actor, and // if the nav isn't part of the excluded list, if ( (RequiredClass == None || Nav.class == RequiredClass) && ExcludeList.Find(Nav) == INDEX_NONE ) { // pick the closest Dist = VSize( Nav.Location-ChkActor.Location ); if( Dist > MinDist ) { if( BestNav == None || Dist < BestDist ) { BestNav = Nav; BestDist = Dist; } } } } } return BestNav; } /** Returns the nearest valid navigation on the floor to the given actor within a certain radius */ static final function NavigationPoint GetNearestValidFloorNavWithinRadiusToPawn(Pawn ChkPawn, float MinDist, optional class RequiredClass,optional array ExcludeList) { local NavigationPoint BestNav; local float Dist, BestDist; local array ValidNavs; local Cylinder PawnCylinder; local int i; if( ChkPawn != None ) { PawnCylinder.Radius = ChkPawn.GetCollisionRadius(); PawnCylinder.Height = ChkPawn.GetCollisionHeight(); GetAllNavInRadius( ChkPawn, ChkPawn.Location, MinDist, ValidNavs, true,, PawnCylinder ); for( i = 0; i < ValidNavs.Length; i++ ) { if( ValidNavs[i].bWallNode ) { continue; } if( !ValidNavs[i].IsUsableAnchorFor( ChkPawn ) ) { continue; } // if no filter class specified, and // if nav is available to the check actor, and // if the nav isn't part of the excluded list, if ( (RequiredClass == None || ValidNavs[i].class == RequiredClass) && ExcludeList.Find(ValidNavs[i]) == INDEX_NONE ) { // pick the closest Dist = VSize( ValidNavs[i].Location-ChkPawn.Location ); if( Dist > MinDist ) { if( BestNav == None || Dist < BestDist ) { BestNav = ValidNavs[i]; BestDist = Dist; } } } } } return BestNav; } event NotifyReachedBy( Pawn P ) { if( P.Controller != none && KFAIController(P.Controller) != none ) { `AILog_Ext( GetFuncName()$" by "$P, 'PathWarning', KFAIController(P.Controller) ); } } simulated event string GetDebugAbbrev() { return "KFPN"; } simulated function DrawDebugInfo( HUD HUD ) { local KFDebugLines KFDL; local int i; KFDL = class'KFDebugLines'.static.GetDebugLines(); if( KFDL != none ) { for( i = 0; i < PathList.Length; i++ ) { KFDL.AddDebugLine( Location, PathList[i].GetEnd().Location, 0, 100, 150, true,, name, i ); KFDL.AddDebugText3D( (Location + PathList[i].GetEnd().Location) * 0.5f, string(PathList[i]), true, 50, 100, 150, true,,,, name, i ); } } } DefaultProperties { bBuildLongPaths=false bDebugLogAnchorUsability=false WallReachSpecClass=class'KFGame.FloorToWallReachSpec' bAutoConnectToOtherFloors=true bIgnoredByTraderTrail=false JumpTime=0.45f }