704 lines
30 KiB
Ucode
704 lines
30 KiB
Ucode
//=============================================================================
|
|
// KFGameplayEventsWriter
|
|
//=============================================================================
|
|
// Class Description
|
|
//=============================================================================
|
|
// Killing Floor 2
|
|
// Copyright (C) 2015 Tripwire Interactive LLC
|
|
// - @author Jonathan Howard 140807
|
|
// - Author 11/1/2013
|
|
//=============================================================================
|
|
|
|
class KFGameplayEventsWriter extends GameplayEventsWriter
|
|
config(GameStats)
|
|
native(Analytics);
|
|
|
|
`include(KFGame\KFGameAnalytics.uci);
|
|
|
|
/*
|
|
* Gameplay
|
|
*/
|
|
|
|
/* Zed events*/
|
|
const GAMEEVENT_ZED_DIED = 1010;
|
|
const GAMEEVENT_ZED_SPAWNED = 1011;
|
|
|
|
/*
|
|
* Debugging
|
|
*/
|
|
|
|
/** Spawn volume: 1100 - 1110 */
|
|
const GAMEEVENT_SPAWNVOLUME_RATING = 2002;
|
|
const GAMEEVENT_SPAWNVOLUME_PLAYERS = 2003;
|
|
const GAMEEVENT_SPAWNVOLUME_BESTRATING = 2004;
|
|
|
|
/** AI Events: 1200 - 1299 */
|
|
const GAMEEVENT_AI_MOVEFAILURE = 2100;
|
|
const GAMEEVENT_AI_BUMP = 2101;
|
|
const GAMEEVENT_AI_JUMPSPOT = 2102;
|
|
const GAMEEVENT_AI_HITWALL = 2103;
|
|
const GAMEEVENT_AI_JUMPOVERWALL = 2104;
|
|
const GAMEEVENT_AI_WAITFORDOOR = 2105;
|
|
const GAMEEVENT_AI_FINISHEDWAITFORDOOR = 2106;
|
|
const GAMEEVENT_AI_FAILEDADJUSTFROMWALL = 2107;
|
|
const GAMEEVENT_AI_CHARGEATTACK = 2108;
|
|
const GAMEEVENT_AI_CHANGEDENEMY = 2109;
|
|
const GAMEEVENT_AI_GETNEXTMOVEGOALFAILURE = 2110;
|
|
const GAMEEVENT_AI_REDIRECTEDPATH = 2111;
|
|
const GAMEEVENT_AI_BLOCKEDPATH = 2112;
|
|
const GAMEEVENT_AI_PATHOBSTRUCTION_FAIL = 2113;
|
|
const GAMEEVENT_AI_PATHOBSTRUCTION_REPATH = 2114;
|
|
const GAMEEVENT_AI_MOVE_TIMEOUT = 2115;
|
|
const GAMEEVENT_AI_INVALIDATE_ANCHOR = 2116;
|
|
const GAMEEVENT_AI_ANCHOR_FALLBACK_FAILED = 2117;
|
|
const GAMEEVENT_AI_FAILED_ANCHOR = 2118;
|
|
const GAMEEVENT_AI_BASED_ON_PAWN = 2119;
|
|
const GAMEEVENT_AI_HEADLESS_WANDER = 2120;
|
|
const GAMEEVENT_AI_DESTROYED_DOOR = 2121;
|
|
const GAMEEVENT_AI_PATHGOALEVAL_ABORT = 2122;
|
|
const GAMEEVENT_AI_PATH_FAILURE = 2123;
|
|
|
|
var globalconfig bool bRecordAIDebugInfo;
|
|
|
|
/** Index of file in use by this writer */
|
|
var int StatsFileIndex;
|
|
|
|
/** Emulate a singleton/static variable for the event */
|
|
var transient Controller LastDiedController;
|
|
|
|
cpptext
|
|
{
|
|
/** Cleanup the native memory allocations */
|
|
virtual void BeginDestroy();
|
|
};
|
|
|
|
/*
|
|
* @name Aliased resolution functions into script from native (defined from GameplayEventsWriter)
|
|
*/
|
|
|
|
/** Turns a weapon class into an index, possibly adding new information to the array **/
|
|
function native int ResolveWeaponClassIndex(class WeaponClass);
|
|
|
|
/** Turns a damage class into an index, possibly adding new information to the array **/
|
|
function native int ResolveDamageClassIndex(class DamageClass);
|
|
|
|
/** Turns a projectile class into an index, possibly adding new information to the array **/
|
|
function native int ResolveProjectileClassIndex(class ProjectileClass);
|
|
|
|
/** Turns a pawn class into an index, possibly adding new information to the array **/
|
|
function native int ResolvePawnIndex(class PawnClass);
|
|
|
|
/** Turns an actor class into an index, possibly adding new information to the array **/
|
|
function native int ResolveActorIndex(Actor Actor);
|
|
|
|
/**
|
|
* Creates the archive that we are going to write to
|
|
* @param Filename - name of the file that will be open for serialization
|
|
* @return TRUE if successful, else FALSE
|
|
*/
|
|
native function bool OpenStatsFile(string Filename);
|
|
|
|
/**
|
|
* Can the writer get access to a file to write to (XBOX specific)
|
|
*/
|
|
native function bool CanAcquireFile();
|
|
|
|
function LogSpawnVolumeRating( KFSpawnVolume SpawnVolume, float FinalRating, float UsageRating, float LocationRating )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
local vector InteriorBB;
|
|
local string ToolTipText;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID',GAMEEVENT_SPAWNVOLUME_RATING);
|
|
PLE.AddVector( 'BaseLocation', SpawnVolume.Location );
|
|
PLE.AddString('Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_TrafficLight'");
|
|
PLE.AddString('Name', SpawnVolume.Name );
|
|
PLE.AddVector( 'BoxLoc', SpawnVolume.Location );
|
|
PLE.AddVector('BoxColor',vect(0,255,0));
|
|
InteriorBB = SpawnVolume.VisibilityBounds.BoxExtent;
|
|
PLE.AddVector( 'BoxExtent', InteriorBB );
|
|
PLE.AddVector('HeatmapPoint',SpawnVolume.Location);
|
|
ToolTipText = "Final Rating: "$FinalRating$"\nUsage Rating: "$UsageRating$"\nLocation Rating: "$LocationRating;
|
|
PLE.AddString('Text',ToolTipText);
|
|
PLE.CommitToDisk();
|
|
|
|
}
|
|
|
|
function LogPlayersAtSpawn( KFPlayerController KFPC, vector ViewLoc, rotator ViewRot )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
local string ToolTipText;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID',GAMEEVENT_SPAWNVOLUME_PLAYERS);
|
|
PLE.AddVector( 'BaseLocation', ViewLoc );
|
|
PLE.AddString('Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Attractor'");
|
|
PLE.AddString('Name', KFPC.Name );
|
|
ToolTipText = "Player: "$KFPC.Name$"\nViewLoc: "$ViewLoc$"\nViewRot: "$ViewRot;
|
|
PLE.AddString('Text',ToolTipText);
|
|
PLE.AddVector( 'LineStart', ViewLoc );
|
|
PLE.AddVector('LineColor',vect(0,255,0));
|
|
PLE.AddVector( 'LineEnd', ViewLoc + vector(ViewRot) * 750.f );
|
|
PLE.AddInt('PlayerIndex',ResolvePlayerIndex(KFPC));
|
|
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
function LogBestSpawnVolume(KFSpawnVolume KFSV, int WaveNum, int SpawnCount)
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
local string ToolTipText;
|
|
local vector InteriorBB;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID',GAMEEVENT_SPAWNVOLUME_BESTRATING);
|
|
PLE.AddVector( 'BaseLocation', KFSV.Location );
|
|
PLE.AddString('Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Spawn'");
|
|
PLE.AddString('Name',KFSV.Name);
|
|
ToolTipText = "Wave " $WaveNum $"\nSpawned "$ SpawnCount $" Zeds" $"\nTimes chosen for spawn: "$KFSV.VolumeChosenCount;
|
|
PLE.AddString('Text',ToolTipText);
|
|
PLE.AddVector( 'BoxLoc', KFSV.Location );
|
|
InteriorBB = KFSV.VisibilityBounds.BoxExtent;
|
|
PLE.AddVector( 'BoxExtent', InteriorBB );
|
|
PLE.AddVector('HeatmapPoint',KFSV.Location);
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
|
|
/*********************************************************************************************
|
|
* AI specific gameplay events
|
|
**********************************************************************************************/
|
|
|
|
function LogAIPathFailure( KFAIController KFAIC, NavigationPoint Anchor, actor Goal, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
local int i;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID', GAMEEVENT_AI_PATH_FAILURE );
|
|
PLE.AddVector( 'BaseLocation', KFAIC.Pawn.Location );
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Repulsor'" );
|
|
PLE.AddString( 'Name',KFAIC.Pawn.Name );
|
|
if( Anchor != None )
|
|
{
|
|
PLE.AddVector( 'SphereLoc', Anchor.Location );
|
|
PLE.AddFloat( 'SphereRadius', 32.f );
|
|
PLE.AddVector( 'SphereColor', vect(0,255,0) );
|
|
}
|
|
if( Goal != None )
|
|
{
|
|
PLE.AddVector( 'LineStart', KFAIC.Pawn.Location );
|
|
PLE.AddVector( 'LineEnd', KFAIC.MoveGoal.Location );
|
|
PLE.AddVector( 'LineColor', vect(0,0,255) );
|
|
}
|
|
if( KFAIC.RouteCache.Length > 0 )
|
|
{
|
|
ToolTipText = ToolTipText$" RCItems:"$KFAIC.RouteCache.Length;
|
|
for( i = 0; i < KFAIC.RouteCache.Length; i++ )
|
|
{
|
|
ToolTipText = ToolTipText$" RC0:"$KFAIC.RouteCache[i];
|
|
}
|
|
}
|
|
|
|
ToolTipText = ToolTipText;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'HeatmapPoint', KFAIC.Pawn.Location);
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
function LogAIHeadlessWander( KFAIController KFAIC, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID', GAMEEVENT_AI_HEADLESS_WANDER );
|
|
PLE.AddVector( 'BaseLocation', KFAIC.Pawn.Location );
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Repulsor'" );
|
|
PLE.AddString( 'Name',KFAIC.Pawn.Name );
|
|
|
|
ToolTipText = ToolTipText;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'HeatmapPoint', KFAIC.Pawn.Location);
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
function LogAIBasedOnPawn( KFAIController KFAIC, Pawn BasePawn, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID', GAMEEVENT_AI_BASED_ON_PAWN );
|
|
PLE.AddVector( 'BaseLocation', KFAIC.Pawn.Location );
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Repulsor'" );
|
|
PLE.AddString( 'Name',KFAIC.Pawn.Name );
|
|
ToolTipText = ToolTipText;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'LineStart', KFAIC.Pawn.Location );
|
|
PLE.AddVector( 'LineEnd', BasePawn.Location );
|
|
PLE.AddVector( 'HeatmapPoint', KFAIC.Pawn.Location);
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
/*********************************************************************************************
|
|
* Anchor issues
|
|
* Checking issues with NPC path starting navigation points.
|
|
********************************************************************************************* */
|
|
|
|
/** This is evil - when initial abort for Goal_At evaluator happens, when NPC's anchor is also the goal */
|
|
function LogAIPathGoalEvalAbort( KFAIController KFAIC, PathGoalEvaluator PathEvaluator, NavigationPoint StartNav, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
local KFPawn NPC;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
// Get the NPC Controller's KFPawn
|
|
NPC = KFAIC.MyKFPawn;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
// For the visualizer to work, add the event ID param for the define you added in KFGameAnalytics.uci
|
|
PLE.AddInt( 'EventID', GAMEEVENT_AI_PATHGOALEVAL_ABORT );
|
|
// For the visualizer to work, you must also add the 'name' parameter - the name of the main actor involved should be fine
|
|
PLE.AddString( 'Name', NPC.Name );
|
|
// For the visualizer to work, you must add a BaseLocation vector, which is where the sprite will be drawn
|
|
PLE.AddVector( 'BaseLocation', NPC.Location );
|
|
// The sprite to render at BaseLocation
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Repulsor'" );
|
|
// This is the text to show as a tooltip when the mouse pointer is hovering over a gameplayevent icon
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
// Define a red line to render from the NPC to StartNav's location, using the 'LineStart' and 'LineEnd' parameters
|
|
PLE.AddVector( 'LineStart', NPC.Location );
|
|
PLE.AddVector( 'LineEnd', StartNav.Location );
|
|
PLE.AddVector( 'LineColor', vect(255,0,0) );
|
|
// Define a red sphere to render at StartNav's location
|
|
PLE.AddVector( 'SphereLoc', StartNav.Location );
|
|
PLE.AddFloat( 'SphereRadius', 32.f );
|
|
PLE.AddVector( 'SphereColor', vect(255,0,0) );
|
|
// Marks the pawn's location for the HeatMapVisualizer
|
|
PLE.AddVector( 'HeatmapPoint', NPC.Location );
|
|
// Save the data
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
function LogAIDestroyedDoor( KFAIController KFAIC, KFDoorActor Door, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID', GAMEEVENT_AI_DESTROYED_DOOR );
|
|
PLE.AddVector( 'BaseLocation', Door.Location );
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Repulsor'" );
|
|
PLE.AddString( 'Name',KFAIC.Pawn.Name );
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'LineStart', Door.Location );
|
|
PLE.AddVector( 'LineEnd', KFAIC.Pawn.Location );
|
|
PLE.AddVector( 'HeatmapPoint', Door.Location );
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
/**
|
|
* This is very bad - it happens when an NPC cannot find a valid starting navigation point when
|
|
* generating a path. FindPath will fail, and no partial path will be found either. This is a
|
|
* time when something has gone very wrong (like the NPC spawned in an invalid location with
|
|
* no pathnodes). Teleporting the NPC to the nearest NavigationPoint that's not visible to
|
|
* players is the quick-fix if other attempts fail (moving a bit and trying to find a valid anchor
|
|
* again, etc).
|
|
*/
|
|
function LogAIFailedAnchor( int EventID, KFAIController KFAIC, Actor MoveTarget, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID', GAMEEVENT_AI_ANCHOR_FALLBACK_FAILED);
|
|
PLE.AddVector( 'BaseLocation', KFAIC.Pawn.Location );
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Repulsor'" );
|
|
PLE.AddString( 'Name',KFAIC.Pawn.Name );
|
|
|
|
if( MoveTarget != none )
|
|
{
|
|
ToolTipText = ToolTipText$" MoveTarget:"$MoveTarget;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'LineStart', KFAIC.Pawn.Location );
|
|
PLE.AddVector( 'LineEnd', MoveTarget.Location );
|
|
}
|
|
PLE.AddVector( 'HeatmapPoint',KFAIC.Pawn.Location);
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
/**
|
|
* An NPC on a path has been unexpectedly blocked, and the HandlePathObstruction() event
|
|
* successfully built a path around it.
|
|
*/
|
|
function LogAIPathObstruction( int EventID, KFAIController KFAIC, Actor Obstruction, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
local float Radius, Height;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID', EventID ); //GAMEEVENT_AI_PATHOBSTRUCTION_REPATH);
|
|
PLE.AddVector( 'BaseLocation', KFAIC.Pawn.Location );
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Repulsor'" );
|
|
PLE.AddString( 'Name',KFAIC.Pawn.Name );
|
|
|
|
PLE.AddVector( 'SphereLoc', Obstruction.Location );
|
|
Obstruction.GetBoundingCylinder( Radius,Height) ;
|
|
PLE.AddFloat( 'SphereRadius',Radius );
|
|
PLE.AddVector( 'SphereColor',vect(255,0,0) );
|
|
|
|
ToolTipText = ToolTipText$" Obstruction:"$Obstruction;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'LineStart', KFAIC.Pawn.Location );
|
|
PLE.AddVector( 'LineEnd', Obstruction.Location );
|
|
PLE.AddVector( 'HeatmapPoint',KFAIC.Pawn.Location);
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
/**
|
|
* Sometimes an NPC is blocked by something unexpected when on a path. After a few re-tries,
|
|
* the NPC will often temporarily block the next pathnode he's attempting to reach and generate
|
|
* a new path, in an effort to path around the obstruction.
|
|
*/
|
|
function LogAIBlockedPath( KFAIController KFAIC, NavigationPoint Start, NavigationPoint End, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID', GAMEEVENT_AI_BlockedPath);
|
|
PLE.AddVector( 'BaseLocation', KFAIC.Pawn.Location );
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Repulsor'" );
|
|
PLE.AddString( 'Name',KFAIC.Pawn.Name );
|
|
ToolTipText = ToolTipText$" MoveTarget: "$KFAIC.MoveTarget$" MoveGoal: "$KFAIC.MoveTarget;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'LineStart', Start.Location );
|
|
PLE.AddVector( 'LineEnd', End.Location );
|
|
PLE.AddVector( 'HeatmapPoint',KFAIC.Pawn.Location);
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
/**
|
|
* An NPC using the AIMoveToGoal command has decided to alter its path due to an obstruction, which
|
|
* can include other Zeds, doors, welded doors, etc.
|
|
*/
|
|
function LogAIRedirectedPath( KFAIController KFAIC, actor MoveGoal, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
`AILog_Ext( KFAIC.Pawn$" GAMEEVENT_AI_REDIRECTEDPATH at "$KFAIC.Pawn.Location$" MoveGoal: "$MoveGoal$" ToolTipText: "$ToolTipText, 'Critical', KFAIC );
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID', GAMEEVENT_AI_REDIRECTEDPATH );
|
|
PLE.AddVector( 'BaseLocation', KFAIC.Pawn.Location );
|
|
PLE.AddString( 'Sprite', "Texture2D'EditorResources.Crowd.T_Crowd_Repulsor'" );
|
|
PLE.AddString( 'Name', KFAIC.Pawn.Name );
|
|
ToolTipText = ToolTipText$" Base: "$KFAIC.Pawn.Base$" MG Dist:"$VSize(MoveGoal.Location - KFAIC.Pawn.Location)$" SS? "$KFAIC.MyKFPawn.IsUsingSuperSpeed();
|
|
//ToolTipText = "Wave " $WaveNum $"\nSpawned "$ SpawnCount $" Zeds" $"\nTimes chosen for spawn: "$KFSV.VolumeChosenCount;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'LineStart', KFAIC.Pawn.Location );
|
|
PLE.AddVector( 'LineEnd', KFAIC.Pawn.Location + vector(KFAIC.Pawn.Rotation) * 350.f );
|
|
if( KFAIC.MoveGoal != none )
|
|
{
|
|
PLE.AddVector( 'SecondLineStart', KFAIC.Pawn.Location );
|
|
PLE.AddVector( 'SecondLineEnd', KFAIC.MoveGoal.Location );
|
|
PLE.AddVector( 'SecondLineColor', vect(1,1,0) );
|
|
}
|
|
PLE.AddVector( 'HeatmapPoint',KFAIC.Pawn.Location);
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
function LogAIMoveFailure( KFAIController KFAIC, vector NPCLocation, rotator NPCRotation, actor MoveGoal, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID', GAMEEVENT_AI_MOVEFAILURE );
|
|
PLE.AddVector( 'BaseLocation', NPCLocation );
|
|
PLE.AddString( 'Sprite', "Texture2D'EditorResources.Crowd.T_Crowd_Crosswalk'" );
|
|
PLE.AddString( 'Name', KFAIC.Pawn.Name );
|
|
if( MoveGoal != none )
|
|
{
|
|
ToolTipText = ToolTipText$" MG Dist:"$VSize(MoveGoal.Location - KFAIC.Pawn.Location)$" SS? "$KFAIC.MyKFPawn.IsUsingSuperSpeed();
|
|
}
|
|
else
|
|
{
|
|
ToolTipText = ToolTipText$" SS? "$KFAIC.MyKFPawn.IsUsingSuperSpeed();
|
|
}
|
|
if( KFAIC.MyKFPawn.Base != none )
|
|
{
|
|
ToolTipText = ToolTipText$" Base:"$KFAIC.MyKFPawn.Base;
|
|
}
|
|
else
|
|
{
|
|
ToolTipText = ToolTipText$" NO BASE!";
|
|
}
|
|
//ToolTipText = "Wave " $WaveNum $"\nSpawned "$ SpawnCount $" Zeds" $"\nTimes chosen for spawn: "$KFSV.VolumeChosenCount;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'LineStart', NPCLocation );
|
|
PLE.AddVector( 'LineEnd', NPCLocation + vector(NPCRotation) * 350.f );
|
|
if( KFAIC.MoveGoal != none || KFAIC.MoveTarget != none )
|
|
{
|
|
PLE.AddVector( 'SecondLineStart', NPCLocation );
|
|
if( KFAIC.MoveTarget != none )
|
|
{
|
|
PLE.AddVector( 'SecondLineEnd', KFAIC.MoveTarget.Location );
|
|
}
|
|
else
|
|
{
|
|
PLE.AddVector( 'SecondLineEnd', KFAIC.MoveGoal.Location );
|
|
}
|
|
PLE.AddVector( 'SecondLineColor', vect(1,1,0) );
|
|
}
|
|
PLE.AddVector( 'HeatmapPoint', NPCLocation );
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
function LogAIGetNextMoveGoalFailure( KFAIController KFAIC, vector NPCLocation, rotator NPCRotation, actor MoveGoal, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
`AIlog_Ext( KFAIC.Pawn$" LogAIGetNextMoveGoalFailure at "$NPCLocation$" MoveGoal: "$MoveGoal$" ToolTipText: "$ToolTipText, 'PathWarning', KFAIC );
|
|
// KFAIC.AIBugItStringCreator( KFAIC.Pawn.Location, KFAIC.Pawn.Rotation, GoString, LocString );
|
|
// `Log( GoString );
|
|
// `Log( LocString );
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID', GAMEEVENT_AI_GETNEXTMOVEGOALFAILURE );
|
|
PLE.AddVector( 'BaseLocation', NPCLocation );
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Spawn'" );
|
|
PLE.AddString( 'Name',KFAIC.Pawn.Name );
|
|
ToolTipText = ToolTipText$" Base: "$KFAIC.Pawn.Base$" MG Dist:"$VSize(MoveGoal.Location - KFAIC.Pawn.Location)$" SS: "$KFAIC.MyKFPawn.IsUsingSuperSpeed();
|
|
//ToolTipText = "Wave " $WaveNum $"\nSpawned "$ SpawnCount $" Zeds" $"\nTimes chosen for spawn: "$KFSV.VolumeChosenCount;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'LineStart', NPCLocation );
|
|
PLE.AddVector( 'LineEnd', NPCLocation + vector(NPCRotation) * 350.f );
|
|
if( KFAIC.MoveGoal != none )
|
|
{
|
|
PLE.AddVector( 'SecondLineStart', NPCLocation );
|
|
PLE.AddVector( 'SecondLineEnd', KFAIC.MoveGoal.Location );
|
|
PLE.AddVector( 'SecondLineColor', vect(1,1,0) );
|
|
}
|
|
PLE.AddVector( 'HeatmapPoint',NPCLocation);
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
/**
|
|
* LogAIChargeAttack()
|
|
* @param KFAIC KFAIController
|
|
* @param ChargeStartLocation NPC's location at start of the charge attack
|
|
* @param ChargeEndLocation NPC's location when finished the charge attack
|
|
* @param ToolTipText ToolTip text shown for this event's icon
|
|
*/
|
|
function LogAIChargeAttack( KFAIController KFAIC, vector ChargeStartLocation, vector ChargeEndLocation, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID',GAMEEVENT_AI_CHARGEATTACK );
|
|
PLE.AddVector( 'BaseLocation', ChargeStartLocation );
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Attractor'" );
|
|
PLE.AddString( 'Name',KFAIC.Pawn.Name );
|
|
ToolTipText = ToolTipText$" Enemy: "$KFAIC.Enemy;
|
|
//ToolTipText = "Wave " $WaveNum $"\nSpawned "$ SpawnCount $" Zeds" $"\nTimes chosen for spawn: "$KFSV.VolumeChosenCount;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'LineStart', ChargeStartLocation );
|
|
PLE.AddVector( 'LineEnd', ChargeEndLocation );
|
|
PLE.AddVector( 'HeatmapPoint', ChargeStartLocation );
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
/**
|
|
* LogAIBump()
|
|
* @param KFAIC KFAIController
|
|
* @param NPCLocation NPC's Location at time of event
|
|
* @param NPCRotation NPC's Rotation at time of event
|
|
* @param Other Other actor that was bumped into
|
|
* @param ToolTipText ToolTip text shown for this event's icon
|
|
*/
|
|
function LogAIBump( int EventID, KFAIController KFAIC, vector NPCLocation, rotator NPCRotation, actor Other, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID',GAMEEVENT_AI_BUMP );
|
|
PLE.AddVector( 'BaseLocation', NPCLocation );
|
|
PLE.AddString( 'Sprite', "Texture2D'EditorResources.Crowd.T_Crowd_TrafficLight'" );
|
|
PLE.AddString( 'Name',KFAIC.Pawn.Name );
|
|
ToolTipText = ToolTipText$" Other: "$Other$" Base: "$KFAIC.Pawn.Base$" SS: "$KFAIC.MyKFPawn.IsUsingSuperSpeed()$" Command: "$KFAIC.CachedAICommandList;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'LineStart', NPCLocation );
|
|
PLE.AddVector( 'LineEnd', NPCLocation + vector(NPCRotation) * 750.f );
|
|
PLE.AddVector( 'HeatmapPoint',NPCLocation );
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
/**
|
|
* LogAIFailedAdjustFromWall()
|
|
* @param KFAIC KFAIController
|
|
* @param NPCLocation NPC's Location at time of event
|
|
* @param NPCRotation NPC's Rotation at time of event
|
|
* @param Wall Wall actor that NPC couldn't adjust around
|
|
* @param ToolTipText ToolTip text shown for this event's icon
|
|
*/
|
|
function LogAIWall( int EventID, KFAIController KFAIC, vector NPCLocation, rotator NPCRotation, actor Wall, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID', EventID); // GAMEEVENT_AI_FAILEDADJUSTFROMWALL );
|
|
PLE.AddVector( 'BaseLocation', NPCLocation );
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Spawn'" );
|
|
PLE.AddString( 'Name',KFAIC.Pawn.Name );
|
|
ToolTipText = ToolTipText$" Wall: "$Wall$" Phys: "$KFAIC.Pawn.GetPhysicsName()$" SS: "$KFAIC.MyKFPawn.IsUsingSuperSpeed();
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'LineStart', NPCLocation );
|
|
PLE.AddVector( 'LineEnd', NPCLocation + vector(NPCRotation) * 250.f );
|
|
PLE.AddVector( 'HeatmapPoint',NPCLocation );
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
|
|
/**
|
|
* LogAIWaitForDoor()
|
|
* @param KFAIC KFAIController
|
|
* @param NPCLocation NPC's Location at time of event
|
|
* @param Door Door that NPC must wait for
|
|
* @param ToolTipText ToolTip text shown for this event's icon
|
|
*/
|
|
function LogAIDoor( int EventID, KFAIController KFAIC, vector NPCLocation, KFDoorActor Door, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID', EventID); // GAMEEVENT_AI_WAITFORDOOR );
|
|
PLE.AddVector( 'BaseLocation', NPCLocation );
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.door'" );
|
|
PLE.AddString( 'Name',KFAIC.Pawn.Name );
|
|
ToolTipText = ToolTipText$" Command: "$KFAIC.CachedAICommandList;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
PLE.AddVector( 'LineStart', NPCLocation );
|
|
PLE.AddVector( 'LineEnd', Door.Location );
|
|
PLE.AddVector( 'HeatmapPoint', NPCLocation );
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
/**
|
|
* LogAIJumpSpot()
|
|
* @param KFAIC KFAIController
|
|
* @param NPCLocation NPC's Location at time of event
|
|
* @param NPCRotation NPC's Rotation at time of event
|
|
* @param JumpSpot JumpSpot that was used
|
|
* @param ToolTipText ToolTip text shown for this event's icon
|
|
*/
|
|
//function LogAIJumpSpot( KFAIController KFAIC, vector NPCLocation, rotator NPCRotation, KFJumpSpot JumpSpot, string ToolTipText )
|
|
//{
|
|
// local GenericParamListStatEntry PLE;
|
|
|
|
// if ( !bRecordAIDebugInfo ) return;
|
|
|
|
// PLE = GetGenericParamListEntry();
|
|
// PLE.AddInt( 'EventID', GAMEEVENT_AI_JUMPSPOT );
|
|
// PLE.AddVector( 'BaseLocation', KFAIC.Pawn.Location );
|
|
// PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Spawn'" );
|
|
// PLE.AddString( 'Name', KFAIC.Pawn.Name );
|
|
// ToolTipText = ToolTipText$" SSpeed: "$KFAIC.MyKFPawn.IsUsingSuperSpeed();
|
|
// PLE.AddString( 'Text', ToolTipText );
|
|
// // Line to new enemy
|
|
// PLE.AddVector( 'LineStart', KFAIC.Pawn.Location );
|
|
// PLE.AddVector('LineColor',vect(0,255,0));
|
|
// PLE.AddVector( 'LineEnd', JumpSpot.Location );
|
|
// PLE.CommitToDisk();
|
|
//}
|
|
|
|
/**
|
|
* LogAIChangedEnemy()
|
|
* @param KFAIC KFAIController
|
|
* @param NewEnemy New enemy to begin targeting
|
|
* @param OldEnemy Previous enemy
|
|
* @param ToolTipText ToolTip text shown for this event's icon
|
|
*/
|
|
function LogAIChangedEnemy( KFAIController KFAIC, Pawn NewEnemy, Pawn OldEnemy, string ToolTipText )
|
|
{
|
|
local GenericParamListStatEntry PLE;
|
|
|
|
if ( !bRecordAIDebugInfo ) return;
|
|
|
|
|
|
PLE = GetGenericParamListEntry();
|
|
PLE.AddInt( 'EventID',GAMEEVENT_AI_CHANGEDENEMY);
|
|
PLE.AddVector( 'BaseLocation', KFAIC.Pawn.Location );
|
|
PLE.AddString( 'Sprite',"Texture2D'EditorResources.Crowd.T_Crowd_Behavior'" );
|
|
PLE.AddString( 'Name', KFAIC.Pawn.Name );
|
|
ToolTipText = ToolTipText$" from "$OldEnemy.PlayerReplicationInfo.PlayerName$" to "$NewEnemy.PlayerReplicationInfo.PlayerName$" "$KFAIC.CachedAICommandList;
|
|
PLE.AddString( 'Text', ToolTipText );
|
|
// Line to new enemy
|
|
PLE.AddVector( 'LineStart', KFAIC.Pawn.Location );
|
|
PLE.AddVector('LineColor',vect(0,255,0));
|
|
PLE.AddVector( 'LineEnd', NewEnemy.Location );
|
|
PLE.CommitToDisk();
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
SupportedEvents.Add((EventID=GAMEEVENT_ZED_DIED,EventName="Zed died",StatGroup=(Group=GSG_Game,Level=3),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_SPAWNVOLUME_RATING,EventName="SpawnVolume Rating",StatGroup=(Group=GSG_Game,Level=3),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_SPAWNVOLUME_PLAYERS,EventName="Player positions at AISpawn",StatGroup=(Group=GSG_Game,Level=3),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_SPAWNVOLUME_BESTRATING,EventName="The best rated spawn volume",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_MOVEFAILURE,EventName="AI move failures",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_BUMP,EventName="AI Bumped",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_JUMPSPOT,EventName="AI using JumpSpot",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_HITWALL,EventName="AI HitWall events",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_JUMPOVERWALL,EventName="AI high-jump locations",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_WAITFORDOOR,EventName="AI waiting for door",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_FINISHEDWAITFORDOOR,EventName="AI finished waiting for door",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_FAILEDADJUSTFROMWALL,EventName="AI Failed AdjustFromWall",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_CHARGEATTACK,EventName="AI charge attack start/end locations",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_CHANGEDENEMY,EventName="AI changed enemy",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_REDIRECTEDPATH,EventName="AI path redirected",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_BLOCKEDPATH,EventName="AI blocked its path",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_PATHOBSTRUCTION_FAIL,EventName="AI Obstructed",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_PATHOBSTRUCTION_REPATH,EventName="AI Obstructed Repath",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_INVALIDATE_ANCHOR,EventName="AI Invalidated Anchor",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_MOVE_TIMEOUT,EventName="AI Move Timed Out",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_ANCHOR_FALLBACK_FAILED,EventName="AI Failed Fallback Anchor",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_FAILED_ANCHOR,EventName="AI Failed Anchor Find",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_BASED_ON_PAWN,EventName="AI Landed On Pawn",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_HEADLESS_WANDER,EventName="AI Headless Wander",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_DESTROYED_DOOR,EventName="AI Destroyed Door",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_PATHGOALEVAL_ABORT,EventName="GoalEval Initial Abort",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_AI_PATH_FAILURE,EventName="PathFind Failure",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
}
|
|
|