319 lines
10 KiB
Ucode
319 lines
10 KiB
Ucode
//=============================================================================
|
|
// BaseAIController
|
|
//=============================================================================
|
|
//
|
|
//=============================================================================
|
|
// Killing Floor 2
|
|
// Copyright (C) 2015 Tripwire Interactive LLC
|
|
//=============================================================================
|
|
class BaseAIController extends GameAIController
|
|
dependson(BaseAIPawn, PluginBase, AIPluginMovement)
|
|
implements(PlugInOwnerInterface)
|
|
native
|
|
config(AI);
|
|
|
|
var transient BaseAIPawn MyBaseAIPawn;
|
|
var transient BaseAISquad BaseSquad;
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// animation related vars
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Plugins
|
|
// ----------------------------------------------------------------------- //
|
|
var const public{protected} array<AITickablePlugin> TickablePlugins;
|
|
|
|
var instanced PluginSquad SquadPlugin;
|
|
|
|
var instanced AIPluginMovement MovementPlugin;
|
|
var class<AIPluginMovement> MovementPluginClass;
|
|
|
|
var instanced AIPluginLeap LeapPlugin;
|
|
var class<AIPluginLeap> LeapPluginClass;
|
|
|
|
var instanced AIPluginStuckFix StuckFixPlugin;
|
|
var class<AIPluginStuckFix> StuckFixPluginClass;
|
|
|
|
// base off KFAICommandHistory
|
|
var transient BaseAiPlugInHistory MyAiPlugInHistory;
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Movement
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// perception
|
|
// ----------------------------------------------------------------------- //
|
|
var bool bUsePerceptionHearing;
|
|
var bool bAlwaysAssignEnemy;
|
|
|
|
/** When last time our enemy was visible */
|
|
var float LastEnemySightedTime;
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// firing
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Target selection/limitation
|
|
// ----------------------------------------------------------------------- //
|
|
/** List of targets to shoot at */
|
|
var array<Actor> TargetList;
|
|
/** List of prohibited targets */
|
|
var array<Actor> ProhibitedTargetList;
|
|
|
|
var transient BaseAIPawn SquadAssignedTarget;
|
|
|
|
struct native LocalEnemyInfo
|
|
{
|
|
var array<float> PerceptionTimestamp;
|
|
var EWSPerceptionMode LatestPerception;
|
|
var EWSPerceptionMode DominantPerception;
|
|
var int VisibleCoverActions;
|
|
|
|
var float CurrentThreat;
|
|
var vector LatestLocation; //latest location with Seen perception
|
|
var Pawn Pawn;
|
|
|
|
var bool bSeenBefore;
|
|
var bool bIsPlayer;
|
|
|
|
structcpptext
|
|
{
|
|
/** Constructors */
|
|
FLocalEnemyInfo() {}
|
|
FLocalEnemyInfo(EEventParm)
|
|
{
|
|
|
|
}
|
|
FLocalEnemyInfo(APawn* InPawn)
|
|
{
|
|
appMemzero(this, sizeof(FLocalEnemyInfo));
|
|
Pawn = InPawn;
|
|
}
|
|
|
|
FORCEINLINE UBOOL CanBeSeenWithAction(BYTE Action) const
|
|
{
|
|
return (VisibleCoverActions & (1 << Action)) != 0;
|
|
}
|
|
|
|
UBOOL operator==(const FLocalEnemyInfo& InEnemyInfo) const
|
|
{
|
|
return Pawn == InEnemyInfo.Pawn;
|
|
}
|
|
|
|
UBOOL operator==(const APawn* EnemyPawn) const
|
|
{
|
|
return Pawn == EnemyPawn;
|
|
}
|
|
}
|
|
};
|
|
var array<LocalEnemyInfo> LocalEnemyList;
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Attachments and SpecialActionSttachments
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Enable/Disable Navmesh and plugins
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
/** If this is on, NPC will always try to use Nav Mesh Path Finding Before Path Node */
|
|
var bool bUseNavMesh;
|
|
/** If this is on, NPC will always try to use plugins for movement. Only works with navmesh */
|
|
var bool bUsePluginsForMovement;
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// debug variables
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
var(Debug) config int PlugInHistoryNum;
|
|
|
|
cpptext
|
|
{
|
|
virtual void Initialize();
|
|
void OnLevelStreamedOut(ULevel* Level);
|
|
virtual UBOOL Tick(FLOAT DeltaTime, enum ELevelTick TickType);
|
|
|
|
virtual void PreBeginPlay();
|
|
virtual void BeginDestroy();
|
|
virtual void GetSquadEnemies(TArray<class APawn*>& Items, UBOOL bExcludeProhibitedTargets = FALSE, UBOOL bExcludeBeliefInfo = FALSE);
|
|
|
|
virtual UBOOL IsFriendly(const class AController* const TestPlayer) const;
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Movement
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// perception
|
|
// ----------------------------------------------------------------------- //
|
|
void UpdateEnemyKnowledge(INT EnemyIdx, BYTE Perception);
|
|
|
|
#if !DO_BASEAI_LOGGING
|
|
# if COMPILER_SUPPORTS_NOOP
|
|
# define BaseAILog __noop
|
|
# else
|
|
# define BaseAILog GNull->Logf
|
|
# endif
|
|
static class FOutputDeviceRedirectorBase* GLog;
|
|
#else
|
|
VARARG_DECL(void,void,{},BaseAILog,VARARG_NONE,const TCHAR*,VARARG_NONE,VARARG_NONE);
|
|
VARARG_DECL(void,void,{},BaseAILog,VARARG_NONE,const TCHAR*,VARARG_EXTRA(enum EName E),VARARG_EXTRA(E));
|
|
#endif
|
|
|
|
// AI debug stuff:
|
|
virtual void GetGameSpecificDebug(BYTE element, TArrayNoInit<FString>& outLogLines, TArray<struct FSpaceLineInfo>* Lines = NULL) const;
|
|
|
|
static TArray<UClass*> InitializedAIClasses;
|
|
}
|
|
|
|
/** Called ONCe per class for class specific initialization (e.g. ETQ queries)
|
|
*/
|
|
event InitializeAIClass()
|
|
{
|
|
}
|
|
|
|
event Possess(Pawn inPawn, bool bVehicleTransition)
|
|
{
|
|
super.Possess(inPawn, bVehicleTransition);
|
|
|
|
if (inPawn != none)
|
|
{
|
|
MyBaseAIPawn = BaseAIPawn(inPawn);
|
|
`if(`notdefined(__TW_BASEAI_LEAN_))
|
|
InitializeDefaultBehavior();
|
|
|
|
// setup movement properties
|
|
SetupPathfinding();
|
|
`endif
|
|
}
|
|
}
|
|
|
|
function PawnDied(Pawn InPawn)
|
|
{
|
|
CleanUp();
|
|
super.PawnDied(InPawn);
|
|
}
|
|
|
|
/** This function needs to stay final */
|
|
native final function float UpdateEnemyRange();
|
|
native final function EWSSymbolicAngle UpdateEnemyAngle();
|
|
|
|
native function CleanUp(optional bool bBeingDestroyed);
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// PlugInOwner interface plimentation
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
function BaseAiPlugInHistory GetAiPlugInHistory()
|
|
{
|
|
return MyAiPlugInHistory;
|
|
}
|
|
|
|
function float GetTimeSince( float Time2Test )
|
|
{
|
|
return `TimeSince(Time2Test);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Squad mechanics
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
native function int BroadcastEnemyKnowledge(Pawn EnemyPawn, EWSPerceptionMode Perception);
|
|
native function RemoveEnemy(Pawn EnemyPawn);
|
|
native function RemoveAllEnemies();
|
|
native final function bool IsFriendlyPawn(Pawn TestPlayer) const;
|
|
native noexport function bool IsFriendly(Controller TestPlayer) const;
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Animation related
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// perception
|
|
// ----------------------------------------------------------------------- //
|
|
native final function UpdateEnemyPerception(optional bool bSkipResponseDelay);
|
|
|
|
/** Selects a target from the TargetList or selects an enemy normally */
|
|
native function bool SelectTargetInternal(bool bOnlyFromTargetList);
|
|
native event bool SetEnemy(Pawn NewEnemy);
|
|
native function bool SelectEnemy();
|
|
native function bool SelectTarget();
|
|
|
|
// @todo this will be handled by squads
|
|
//function NotifyKilled(Controller Killer, Controller Killed, Pawn KilledPawn)
|
|
function NotifyKilled(Controller Killer, Controller Killed, pawn KilledPawn, class<DamageType> damageTyp)
|
|
{
|
|
// remove focus from killed enemy
|
|
if (KilledPawn == Focus)
|
|
{
|
|
Focus = None;
|
|
}
|
|
|
|
// Controller's implementation mess with Enemy, so work on this before calling parent
|
|
RemoveEnemy(KilledPawn);
|
|
|
|
super.NotifyKilled(Killer, Killed, KilledPawn, damageTyp);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// logic flow control
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Navigation
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Movement
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
function StopMovement(optional EActionPriority ActionPriority = AP_Logic)
|
|
{
|
|
if(MovementPlugin != None)
|
|
{
|
|
MovementPlugin.AbortMove(FALSE);
|
|
}
|
|
|
|
if( LeapPlugin != none )
|
|
{
|
|
LeapPlugin.AbortMove(FALSE);
|
|
}
|
|
|
|
if( StuckFixPlugin != none )
|
|
{
|
|
StuckFixPlugin.AbortMove(false);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Attachments and SpecialActionSttachments
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Level progress
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
// Debug functions
|
|
// ----------------------------------------------------------------------- //
|
|
native function DrawEnemyPerception(Canvas DrawCanvas);
|
|
|
|
function DrawDebugTextToHud( HUD HUD, String Text, optional color TextColor );
|
|
|
|
defaultproperties
|
|
{
|
|
bAlwaysAssignEnemy=true
|
|
bUsePerceptionHearing=false
|
|
|
|
// this one is a legacy thing - this needs to be true even for AI actors
|
|
// because only then PlayerReplicationInfo will be created - teams for example need that
|
|
// @todo - really needs to be refactored, but can be soooo tricky
|
|
//bIsPlayer=TRUE
|
|
|
|
MovementPlugin=None
|
|
//MovementPluginClass="AIPluginMovement_Recast"
|
|
}
|