1
0
KF2-Dev-Scripts/KFGame/Classes/AICommand_StepAside.uc

350 lines
9.2 KiB
Ucode
Raw Normal View History

2020-12-13 15:01:13 +00:00
//=============================================================================
// AICommand_StepAside
//=============================================================================
//
//=============================================================================
// Killing Floor 2
// Copyright (C) 2015 Tripwire Interactive LLC
//=============================================================================
class AICommand_StepAside extends AICommand
within KFAIController;
var BasedPosition PreStepAsideLocation;
var BasedPosition StepAsideLocation;
var bool bDelayStep;
var bool bNoFocus;
var vector OriginalFocalPoint;
var actor OriginalFocus;
/*********************************************************************************************
* Initialization
********************************************************************************************* */
/** Simple constructor that pushes a new instance of the command for the AI */
static function bool StepAside( KFAIController AI, Pawn NewStepAsideGoal, bool inbDelayStep, optional bool inNoFocus )
{
local AICommand_StepAside Cmd;
if( AI != None &&
AI.StepAsideGoal == None &&
NewStepAsideGoal != None )
{
Cmd = new(AI) class'AICommand_StepAside';
if( Cmd != None )
{
AI.StepAsideGoal = NewStepAsideGoal;
Cmd.bDelayStep = inbDelayStep;
Cmd.bNoFocus = inNoFocus;
AI.PushCommand( Cmd );
return true;
}
}
return false;
}
function Pushed()
{
//MyKFPawn.SetDesiredRotation( MyKFPawn.DesiredRotation );
//MyKFPawn.bDisableTurnInPlace = true;
MyKFPawn.SetSprinting(false);
// do not do this, this is set in the above function do not reset it
//MyKFPawn.bIsSprinting = false;
// if( Focus != none )
// {
// OriginalFocus = Focus;
// }
// OriginalFocalPoint = GetFocalPoint();
if( Steering != none )
{
Steering.EnableDefaultAcceleration();
}
Super.Pushed();
Vect2BP( PreStepAsideLocation, Pawn.Location );
// If we just need to stand still for a second
if( bDelayStep )
{
`AILog( "Going to Command_DelayStep state", 'Command_StepAside' );
AIActionStatus = "Delaying StepAside";
GotoState( 'Command_DelayStep' );
}
else
{
// Otherwise, do the step aside
`AILog( "Going to Command_StepAside state", 'Command_StepAside' );
GotoState( 'Command_StepAside' );
}
}
function Popped()
{
// if( OriginalFocus != none )
// {
// Focus = OriginalFocus;
// }
// SetFocalPoint( OriginalFocalPoint );
AIActionStatus = "Finished StepAside";
if( Steering != none )
{
Steering.DisableDefaultAcceleration();
}
Super.Popped();
StepAsideGoal = None;
if( !bNoFocus )
{
Focus = None;
}
if( Pawn != None )
{
Pawn.ZeroMovementVariables();
}
if(bReevaluatePath)
{
`AILog( GetFuncName()$"() Calling NotifyNeedRepath on "$outer, 'Command_StepAside' );
outer.NotifyNeedRepath();
}
}
state Command_StepAside
{
/** Returns true if the specified vector is valid for us to move to */
function bool IsValidMoveLocation( Vector ChkLoc )
{
return PointReachable( ChkLoc );
}
/** Returns a location that Best moves out of the way of StepAsideGoal */
function bool GetStepAsideLocation()
{
local vector X, Y, Z, HitLocation, HitNormal;
local array<vector> ChkLocs;
local int Idx;
local float StepDist;
// If stepping aside from self, pick random direction
if( StepAsideGoal == Pawn )
{
X = VRand();
//X = Vector(Pawn.Rotation); NEWJC (haven't tested yet)
}
else
// first try a direction perpendicular to the target's velocity
if( VSizeSq(StepAsideGoal.Acceleration) > 0 )
{
X = StepAsideGoal.Acceleration;
}
else
if( bMovingToGoal )
{
`AILog( "- IS MOVING"@MoveTarget@MoveGoal@BP2Vect(MovePosition), 'Command_StepAside' );
if( MoveTarget != None )
{
X = MoveTarget.Location - Pawn.Location;
}
else
if( MoveGoal != None )
{
X = MoveGoal.Location - Pawn.Location;
}
else
if( BP2Vect(MovePosition) != vect(0,0,0) )
{
X = BP2Vect( MovePosition ) - Pawn.Location;
}
else
{
`AILog( self$" Moving but to where??", 'Command_StepAside' );
}
}
else
{
X = Vector(Pawn.Rotation);
}
// Ignore vertical component
X.Z = 0;
X = Normal(X);
Z = vect( 0,0,1 );
Y = Normal( X cross Z );
if( Normal(Pawn.Location-StepAsideGoal.Location) dot Y < 0.f )
{
// flip the y to avoid running into them more
Y = -Y;
}
StepDist = MaxStepAsideDist;
// test first dir at Max Distance
ChkLocs[0] = Pawn.Location + Y * StepDist + X * StepDist * 0.1f;
// half dir Max Distance
ChkLocs[1] = Pawn.Location + X * StepDist * 0.5f + Y * StepDist * 0.5f;
// other dir Max Distance
ChkLocs[2] = Pawn.Location - Y * StepDist + X * StepDist * 0.1f;
// half other dir Max Distance
ChkLocs[3] = Pawn.Location + X * StepDist * 0.5f - Y * StepDist * 0.5f;
// Forward until there is room to get out
ChkLocs[4] = Pawn.Location + X * StepDist;
// slightly back a bit
ChkLocs[5] = Pawn.Location + Y * StepDist - X * StepDist *0.1f;
// slightly back a bit in other dir
ChkLocs[6] = Pawn.Location - Y * StepDist - X * StepDist * 0.1f;
// back more
ChkLocs[7] = Pawn.Location + Y * StepDist - X * StepDist * 0.25f;
// back other dir more
ChkLocs[8] = Pawn.Location - Y * StepDist - X * StepDist * 0.25f;
// return the first valid one
for( Idx = 0; Idx < ChkLocs.Length; Idx++ )
{
if( IsValidMoveLocation(ChkLocs[Idx]) &&
(Trace(HitLocation, HitNormal, ChkLocs[Idx], Pawn.Location, true) == None || VSize(HitLocation - Pawn.Location) > StepDist * 0.5) )
{
Debug_StepRot = Rotator( X );
Vect2BP( Debug_StepLoc, ChkLocs[Idx] );
Vect2BP( StepAsideLocation, ChkLocs[Idx] );
return true;
}
}
`AILog( self$" FAILED TO FIND STEP ASIDE LOCATION... RESORT TO STANDING STILL", 'Command_StepAside' );
LastFailedToFindStepAsideLocation = WorldInfo.TimeSeconds;
return false;
}
function Actor StepAside_GetMoveFocus()
{
return StepAsideGoal;
if( bNoFocus )
{
return None;
}
if( Enemy != None )
{
return Enemy;
}
if( bMovingToGoal )
{
`AILog( self$" bMovingToGoal || bMovingToCover, Focus is MoveTarget:" @ MoveTarget, 'Command_StepAside' );
return MoveTarget;
}
`AILog( self$" !HasAnyEnemies(), Focus is StepAsideGoal:" @ StepAsideGoal, 'Command_StepAside' );
return StepAsideGoal;
}
Begin:
if( StepAsideGoal != None && !bIgnoreStepAside && `TimeSince(LastFailedToFindStepAsideLocation) > 1.f )
{
`AILog( self$" Starting to step aside...", 'Command_StepAside' );
bReevaluatePath = true;
if( GetStepAsideLocation() )
{
AIActionStatus = "Stepping Aside From "$StepAsideGoal;
//MyKFPawn.LookAtPawn(StepAsideGoal);
//MoveToDirectNonPathPos( BP2Vect(StepAsideLocation), StepAside_GetMoveFocus(),, Pawn.bIsWalking );
MoveTo( BP2Vect(StepAsideLocation), StepAside_GetMoveFocus(),, Pawn.bIsWalking );
// check to see if they are still running into us
if( StepAsideGoal != None && StepAsideGoal != Pawn &&
(Pawn.Touching.Find(StepAsideGoal) != -1 || StepAsideGoal.ReachedPoint(BP2Vect( PreStepAsideLocation ), None )) )
{
`AILog( self$" Still touching, moving again"@Pawn.Touching.Find(StepAsideGoal)@StepAsideGoal.ReachedPoint(BP2Vect( PreStepAsideLocation ), None ), 'Command_StepAside' );
// (obstructing pawn may get out of my way)
Sleep( 0.5f + FRand() * 1.f );
// set the prestepasidelocation to the current location so that we avoid getting stuck
Vect2BP( PreStepAsideLocation, Pawn.Location );
Goto( 'Begin' );
}
}
Sleep( 0.1f + FRand() * 0.5f );
}
else
{
`AILog( self$" No step aside goal?", 'Command_StepAside' );
Sleep( 0.5f );
}
`AILog( self$" Finished stepping aside", 'Command_StepAside' );
//SetFocalPoint(Vect(0,0,0));
//MyKFPawn.ResetDesiredRotation();
Status = 'Success';
PopCommand( self );
}
state Command_DelayStep
{
Begin:
//`AILog( self$" Begin delay step aside" );
if( StepAsideGoal != None )
{
if( Pawn != None )
{
Pawn.ZeroMovementVariables();
}
}
// Just stop moving for a sec or two
Sleep( 0.3f + (FRand() * 0.5f) );
//`AILog( self$" Finished delay step aside" );
Status = 'Success';
PopCommand( self );
}
/*********************************************************************************************
* Debugging
********************************************************************************************* */
/** Build debug string */
event String GetDumpString()
{
return Super.GetDumpString()@"Goal:"@StepAsideGoal;
}
simulated function DrawDebug( HUD HUD, name Category )
{
Super.DrawDebug( HUD, Category );
if( Category == 'Pathing' )
{
// Debug step asside
DrawDebugCoordinateSystem( Pawn.Location, Debug_StepRot, 64.f );
DrawDebugLine( BP2Vect( Debug_StepLoc ), Pawn.Location, 255, 255, 255 );
DrawDebugLine( GetDestinationPosition(), Pawn.Location, 64, 128, 255 );
DrawDebugBox( BP2Vect( PreStepAsideLocation ), vect( 5,5,5 ), 255, 0, 0 );
}
}
defaultproperties
{
bAllowedToAttack=false
bReplaceActiveSameClassInstance=true
}