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

253 lines
5.4 KiB
Ucode

/**
* Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
*/
class GameAICmd_Hover_MoveToGoal extends GameAICommand;
var transient Actor Path, Find;
var transient Actor Goal;
var float Radius;
var transient bool bWasFiring;
var float DesiredHoverHeight;
var transient float CurrentHoverHeight;
var float SubGoalReachDist;
/** how close to get to the enemy (only valid of bCompleteMove is TRUE) */
var float GoalDistance;
/** current vector destination */
var transient vector MoveVectDest;
var transient ReachSpec CurrentSpec;
/** GoW global macros */
/** Simple constructor that pushes a new instance of the command for the AI */
static function bool MoveToGoal( GameAIController AI, Actor InGoal, float InGoalDistance, float InHoverHeight )
{
local GameAICmd_Hover_MoveToGoal Cmd;
if( AI != None && AI.Pawn != None && AI.Pawn.bCanFly)
{
Cmd = new(AI) class'GameAICmd_Hover_MoveToGoal';
if( Cmd != None )
{
Cmd.GoalDistance = InGoalDistance;
Cmd.Goal = InGoal;
Cmd.DesiredHoverHeight = InHoverHeight;
Cmd.CurrentHoverHeight = InHoverHeight;
AI.PushCommand( Cmd );
return TRUE;
}
}
return FALSE;
}
function Pushed()
{
Super.Pushed();
GotoState('Moving');
}
function bool HandlePathObstruction(Actor BlockedBy)
{
// ! intentionally does not pass on to children
MoveTimer = -1.f; // kills latent moveto's
GotoState('MoveDown');
return false;
}
state MoveDown `DEBUGSTATE
{
function vector GetMoveDest()
{
local float Height,RadRad;
local navigationPoint PtForHeight;
local vector Dest,HitLocation,HitNormal;
local actor HitActor;
if(Pawn.Anchor != none)
{
PtForHeight = Pawn.Anchor;
}
else if(RouteCache.Length > 0 && RouteCache[0] != none)
{
PtForHeight = RouteCache[0];
}
if(PtForHeight != none)
{
PtForHeight.GetBoundingCylinder(RadRad,Height);
CurrentHoverHeight = Max(0.f, Height - (Pawn.GetCollisionHeight()*0.5f));
Dest = PtForHeight.Location;
Dest.z = PtForHeight.Location.Z + CurrentHoverHeight;
}
else
{
// do a linecheck down to find the ground
HitActor = Trace(HitLocation,HitNormal,Pawn.Location + vect(0,0,-4096.f),Pawn.Location);
if(HitActor != none)
{
Dest = HitLocation;
Dest.Z += Pawn.GetCollisionHeight() * 1.5f;
}
else
{
`AILog(GetFuncName()@"Could not find good hover height!");
Dest = Pawn.Location;
}
}
return Dest;
}
Begin:
MoveTo(GetMoveDest());
Sleep(1.0f);
GotoState('Moving');
};
state Moving `DEBUGSTATE
{
final function bool ReachedDest(Actor Dest)
{
local float latDistSq;
local float VertDist;
latDistSq = VSizeSq2D(Pawn.Location - Dest.Location);
//@TONKS_TEMP
`AILog("LatDist:"@sqrt(latDistSq));
if(latDistSq < SubGoalReachDist * SubGoalReachDist)
{
VertDist = abs(Pawn.Location.Z - Dest.location.Z);
//@TONKS_TEMP
`AILog("VertDist:"@VertDist);
if(VertDist < max(SubGoalReachDist,CurrentHoverHeight+(Pawn.GetCollisionHeight()*2)) )
{
return true;
}
}
return false;
}
final protected function bool PopNextNode( out vector Dest )
{
while( RouteCache.Length > 0 &&
RouteCache[0] != None )
{
if( ReachedDest( RouteCache[0] ) )
{
//debug
`AILog( "Reached route cache 0:"@RouteCache[0] );
// MAKE SURE ANCHOR IS UPDATED -- this is cause of NO CURRENT PATH bug
Pawn.SetAnchor( RouteCache[0] );
//debug
`AILog( "Remove from route:"@RouteCache[0], 'Move' );
RouteCache_RemoveIndex( 0 );
// reset hoverheight since we just arrived at a subgoal
CurrentHoverHeight = DesiredHoverHeight;
}
else
{
//debug
`AILog( "Did NOT reach route cache 0:"@RouteCache[0] );
break;
}
}
if( RouteCache.Length < 1 )
{
return false;
}
CurrentSpec = Pawn.Anchor.GetReachSpecTo(RouteCache[0]);
Dest = RouteCache[0].Location;
return true;
}
Begin:
`AILog("BEGIN TAG"@GetSTatename());
Find = Goal;
Radius = Pawn.GetCollisionRadius() + Enemy.GetCollisionRadius();
if( IsEnemyBasedOnInterpActor( Enemy ) == TRUE )
{
Find = Enemy.Base;
Radius = 0.f;
}
Radius = FMax(Radius, GoalDistance);
if( ActorReachable(Find) )
{
MoveVectDest = Find.Location;
MoveVectDest.Z += CurrentHoverHeight;
`AILog("Moving directly to "$Find);
MoveTo(MoveVectDest,Enemy);
}
else
{
//FIXME: Navmesh
/* // Try to find path to enemy
Path = GeneratePathTo( Find,GoalDistance, TRUE );
// If no path available
if( Path == None )
{
`AILog("Could not find path to enemy!!!");
GotoState( 'DelayFailure' );
}
else
{
//debug
`AILog( "Found path toward enemy..."@Find@Path, 'Move' );
while(PopNextNode(MoveVectDest))
{
MoveVectDest.Z += CurrentHoverHeight;
if(CurrentHoverHeight > CurrentSpec.CollisionHeight && !FastTrace(MoveVectDest,Pawn.Location,pawn.GetCollisionExtent()))
{
`AILog("Could not trace to next position, trying to move down...");
GotoState('MoveDown');
}
else
{
`AILog("Moving to "$MoveVectDest);
MoveTo(MoveVectDest,Enemy);
}
}
}
*/
}
GotoState('DelaySuccess');
}
/** Allows subclasses to determine if our enemy is based on an interp actor or not **/
function bool IsEnemyBasedOnInterpActor( Pawn InEnemy )
{
return FALSE;
}
defaultproperties
{
SubGoalReachDist=768.f
}