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

341 lines
8.7 KiB
Ucode

/**
* Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
*/
class GameAIController extends AIController
dependson(GameTypes)
abstract
native
config(Game);
/** Current command stack, with the last element being the currently active (ticked) one */
var() editinline transient const GameAICommand CommandList;
/** Whether this AI has a runaway loop or not. If it does we are going to do AbortCommand( CommandList ) at the end of Tick(). **/
var transient bool bHasRunawayCommandList;
/** Debug log file, @see: AILog */
var transient FileLog AILogFile;
var(Debug) config bool bAILogging;
var(Debug) config bool bAILogToWindow;
var(Debug) config bool bFlushAILogEachLine;
var(Debug) config bool bMapBasedLogName;
var(Debug) config bool bAIDrawDebug;
var transient bool bAIBroken;
var(Debug) float DebugTextMaxLen;
var(Debug) transient const array<AICmdHistoryItem> CommandHistory;
var(Debug) config int CommandHistoryNum;
/** List of categories to filter */
var(Debug) config array<Name> AILogFilter;
// DEMO RECORDING PROPERTIES - for saving AI info into demos
var string DemoActionString;
cpptext
{
#if !DO_AI_LOGGING
#if COMPILER_SUPPORTS_NOOP
#define AIObjLog __noop
#define AILog __noop
#define AI_LOG __noop
#elif SUPPORTS_VARIADIC_MACROS
#define AIObjLog(...)
#define AILog(...)
#define AI_LOG(...)
#else
#define AIObjLog GNull->Logf
#define AILog GNull->Logf
#define AI_LOG GNull->Logf
#endif
#else
#define AI_LOG(Object, FuncParams) \
if(RUNTIME_DO_AI_LOGGING)\
{\
Object->AILog FuncParams;\
}
#define AIObjLog(FuncParams) AI_LOG(AI,FuncParams)
VARARG_DECL(void,void,{},AILog,VARARG_NONE,const TCHAR*,VARARG_NONE,VARARG_NONE);
VARARG_DECL(void,void,{},AILog,VARARG_NONE,const TCHAR*,VARARG_EXTRA(enum EName E),VARARG_EXTRA(E));
#endif
UBOOL Tick( FLOAT DeltaTime, enum ELevelTick TickType );
virtual EGotoState GotoState( FName State, UBOOL bForceEvents = 0, UBOOL bKeepStack = 0 );
virtual void ProcessState( FLOAT DeltaSeconds );
virtual void StoreCommandHistory( UGameAICommand* Cmd );
/**
* DebugLog function which is called to log information specific to this AI (call NAVHANDLE_DEBUG_LOG macro, don't call this directly)
* @param LogText - text to log for this AI
*/
virtual void DebugLogInternal(const TCHAR* LogText)
{
AI_LOG(this,(LogText));
}
};
replication
{
if( bDemoRecording )
DemoActionString;
}
/** returns all AI Commands in the CommandList that are of the specified class or a subclass
* @note this function is only useful on the server
* @param BaseClass the base class of GameAICommand to return
* @param (out) Cmd the returned GameAICommand for each iteration
*/
native final iterator function AllCommands(class<GameAICommand> BaseClass, out GameAICommand Cmd);
/**
* PushCommand
* pushes a new AI command on top of the command stack
* @param NewCommand - command to place on top of stack
*/
native function PushCommand(GameAICommand NewCommand);
/**
* PopCommand
* will pop the passed command (and everything above it in the stack)
* @param ToBePoppedCommand - the command to pop
*/
native function PopCommand(GameAICommand ToBePoppedCommand);
/** AbortCommand
* Aborts a command (and all of its children)
* @param AbortCmd - the command to abort (can be NULL, in which case AbortClass will be used to determine which command to abort
* @param AbortClass - not used unless AbortCmd is NULL, in which case the first command int he stack of class 'AbortClass' will be aborted (and all its children)
*/
native function bool AbortCommand( GameAICommand AbortCmd, optional class<GameAICommand> AbortClass );
native final function GameAICommand GetActiveCommand();
/** checks the command stack for too many commands and/or infinite recursion */
native final function CheckCommandCount();
native final function DumpCommandStack();
/** finds and returns the lowest command of the specified class on the stack (will return subclasses of the specified class) */
native final function coerce GameAICommand FindCommandOfClass(class<GameAICommand> SearchClass) const;
/** This will search the CommandList for the passed in command class. **/
native function GameAICommand GetAICommandInStack( const class<GameAICommand> InClass );
/** return desired offset to move position... used for MoveTo/MoveToward */
function float GetDestinationOffset();
// called from movetogoal when we arrive at our destination
function ReachedMoveGoal();
function ReachedIntermediateMoveGoal();
/**
* =====
* DEBUG
* =====
*/
event Destroyed()
{
Super.Destroyed();
if (AILogFile != None)
{
AILogFile.Destroy();
}
// so this cases handles when AI has been destroyed. We need to give a chance to the AICmds to handle that case
if( Commandlist != None )
{
AbortCommand( CommandList );
}
}
protected function RecordDemoAILog( coerce string LogText );
`if(`__TW_PATHFINDING_)
event AILog_Internal( coerce string LogText, optional Name LogCategory, optional bool bForce, optional bool BugIt, optional bool bSkipExtraInfo )
`else
event AILog_Internal( coerce string LogText, optional Name LogCategory, optional bool bForce )
`endif
{
`if(`notdefined(FINAL_RELEASE))
local int Idx;
local String ActionStr, FinalStr;
local String FileName;
local GameAICommand ActiveCommand;
local int FileNameLength;
local Engine Eng;
Eng = class'Engine'.static.GetEngine();
if( Eng.bDisableAILogging )
{
return;
}
if( !bForce &&
!bAILogging )
{
return;
}
if (WorldInfo.IsConsoleBuild(CONSOLE_PS3))
{
return;
}
if( !bForce )
{
for( Idx = 0; Idx < AILogFilter.Length; Idx++ )
{
if( AILogFilter[Idx] == LogCategory )
{
return;
}
}
}
if (AILogFile == None)
{
AILogFile = Spawn(class'FileLog');
if (bMapBasedLogName)
{
FileName = WorldInfo.GetMapName()$"_"$string(self);
FileName = Repl(FileName,"ai_","",false);
}
else
{
FileName = string(self);
}
// for consoles we need to make certain the filename is short enough
if( class'WorldInfo'.static.GetWorldInfo().IsConsoleBuild() == TRUE )
{
// Include the file extension in determining the length
FileNameLength = Len(Filename) + 6;
// make sure file name isn't too long for consoles
if(FileNameLength > 40)
{
// Make sure there is room for the .ailog part too
FileName = Right(Filename,34);
}
}
AILogFile.bKillDuringLevelTransition = TRUE;
AILogFile.bFlushEachWrite = bFlushAILogEachLine;
// Use async unless flushing was requested
AILogFile.bWantsAsyncWrites = !bFlushAILogEachLine;
AILogFile.OpenLog(FileName,".ailog");
}
ActionStr = String(GetStateName());
ActiveCommand = GetActiveCommand();
if (ActiveCommand != None)
{
ActionStr = String(ActiveCommand.Class)$":"$String(ActiveCommand.GetStateName());
}
FinalStr = "["$WorldInfo.TimeSeconds$"]"@ActionStr$":"@LogText;
AILogFile.Logf(FinalStr);
if (WorldInfo.IsRecordingDemo())
{
RecordDemoAILog(FinalStr);
}
`Log( Pawn@"["$WorldInfo.TimeSeconds$"]"@ActionStr$":"@LogText, bAILogToWindow );
`endif
}
/** SetDesiredRotation
* Calls Pawn's SetDesiredRotation: Simple interface to Pawn
*/
function SetDesiredRotation(Rotator TargetDesiredRotation, bool InLockDesiredRotation=FALSE, bool InUnlockWhenReached=FALSE, FLOAT InterpolationTime=-1.f/*Use Default RotationRate*/)
{
if ( Pawn!=none )
{
Pawn.SetDesiredRotation(TargetDesiredRotation, InLockDesiredRotation, InUnlockWhenReached, InterpolationTime);
}
}
/**
* ===========
* DEBUG STATES
* ===========
*/
state DEBUGSTATE
{
function BeginState( Name PreviousStateName )
{
//debug
`AILog( "BEGINSTATE"@PreviousStateName, 'State' );
}
function EndState( Name NextStateName )
{
//debug
`AILog( "ENDSTATE"@NextStateName, 'State' );
}
function PushedState()
{
//debug
`AILog( "PUSHED", 'State' );
}
function PoppedState()
{
//debug
`AILog( "POPPED", 'State' );
}
function ContinuedState()
{
//debug
`AILog( "CONTINUED", 'State' );
}
function PausedState()
{
//debug
`AILog( "PAUSED", 'State' );
}
}
/** @return a String with the Cmd and the State that the AI is in. **/
simulated final event string GetActionString()
{
local string ActionStr;
local GameAICommand ActiveCmd;
if( WorldInfo.IsPlayingDemo() )
{
return DemoActionString;
}
else
{
ActiveCmd = GetActiveCommand();
if( ActiveCmd != None )
{
ActionStr = string(ActiveCmd.Class)$":"$string(ActiveCmd.GetStateName());
}
else
{
ActionStr = string(default.Class)$":"$string(GetStateName());
}
return ActionStr;
}
}
defaultproperties
{
}