10 enum SCR_EGameModeRecordType
 
   28 class SCR_IGameModeRecord
 
   35     SCR_EGameModeRecordType GetRecordType();
 
   48         return string.Format(
"%1;%2;%3",
 
   49             GetRecordType().ToString(),
 
   50             GetTimestamp().ToString(),
 
   57     protected string Save();
 
   61     protected void Load(array<string> tokens);
 
   65     static ref SCR_IGameModeRecord LoadFromString(
string str)
 
   67         array<string> tokens = {};
 
   68         str.Split(
";", tokens, 
false);
 
   70         int type = tokens[0].ToInt();
 
   71         tokens.RemoveOrdered(0);
 
   73         float timeStamp = tokens[0].ToFloat();
 
   74         tokens.RemoveOrdered(0);
 
   78             case SCR_EGameModeRecordType.Death:
 
   80                 ref SCR_IGameModeRecord record = 
new SCR_DeathRecord();
 
   81                 record.m_fTimestamp = timeStamp;
 
   87             case SCR_EGameModeRecordType.Movement:
 
   89                 ref SCR_IGameModeRecord record = 
new SCR_MovementRecord();
 
   90                 record.m_fTimestamp = timeStamp;
 
   96             case SCR_EGameModeRecordType.Connection:
 
   98                 ref SCR_IGameModeRecord record = 
new SCR_ConnectionRecord();
 
   99                 record.m_fTimestamp = timeStamp;
 
  105             case SCR_EGameModeRecordType.Spawn:
 
  107                 ref SCR_IGameModeRecord record = 
new SCR_SpawnRecord();
 
  108                 record.m_fTimestamp = timeStamp;
 
  114             case SCR_EGameModeRecordType.AILOD:
 
  116                 ref SCR_IGameModeRecord record = 
new SCR_AILODRecord();
 
  117                 record.m_fTimestamp = timeStamp;
 
  128 sealed 
class SCR_DeathRecord : SCR_IGameModeRecord
 
  131     vector m_InstigatorPosition;
 
  133     FactionKey m_InstigatorFaction;
 
  139     sealed 
override SCR_EGameModeRecordType GetRecordType()
 
  141         return SCR_EGameModeRecordType.Death;
 
  145     override string Save()
 
  148         string ipos = 
string.Format(
"%1,%2,%3", m_InstigatorPosition[0], m_InstigatorPosition[1], m_InstigatorPosition[2]);
 
  149         return string.Format(
"%1;%2;%3;%4;%5;%6;%7", pos, ipos, 
m_Faction, m_InstigatorFaction, (
int)m_WeaponType, m_PlayerId, m_InstigatorId);
 
  153     protected sealed 
override void Load(array<string> tokens)
 
  155         array <string> pos = {};
 
  156         tokens[0].Split(
",", pos, 
true);
 
  157         m_Position = Vector(pos[0].ToFloat(), pos[1].ToFloat(), pos[2].ToFloat());
 
  159         array <string> ipos = {};
 
  160         tokens[1].Split(
",", ipos, 
true);
 
  161         m_InstigatorPosition = Vector(ipos[0].ToFloat(), ipos[1].ToFloat(), ipos[2].ToFloat());
 
  164         m_InstigatorFaction = tokens[3];
 
  166         m_WeaponType = tokens[4].ToInt();
 
  167         m_PlayerId = tokens[5].ToInt();
 
  168         m_InstigatorId = tokens[6].ToInt();
 
  178     static ref SCR_DeathRecord CreateNew(
int playerId, IEntity playerEntity, IEntity killerEntity, 
Instigator killer)
 
  180         SCR_DeathRecord record = 
new SCR_DeathRecord();
 
  181         record.m_Position = playerEntity.GetOrigin();
 
  182         record.m_fTimestamp = playerEntity.GetWorld().GetWorldTime();
 
  183         record.m_PlayerId = playerId;
 
  184         record.m_InstigatorId = killer.GetInstigatorPlayerID();
 
  185         FactionAffiliationComponent factionComponent = FactionAffiliationComponent.Cast(playerEntity.FindComponent(FactionAffiliationComponent));
 
  186         if (factionComponent)
 
  188             Faction faction = factionComponent.GetAffiliatedFaction();
 
  190                 record.m_Faction = faction.GetFactionKey();
 
  195             record.m_InstigatorPosition = killerEntity.GetOrigin();
 
  197             ChimeraCharacter ch = ChimeraCharacter.Cast(killerEntity);
 
  200                 BaseWeaponManagerComponent wpm = ch.GetCharacterController().GetWeaponManagerComponent();
 
  205                         record.m_WeaponType = weapon.GetWeaponType();
 
  209             FactionAffiliationComponent instigatorFactionComponent = FactionAffiliationComponent.Cast(killerEntity.FindComponent(FactionAffiliationComponent));
 
  210             if (instigatorFactionComponent)
 
  212                 Faction instigatorFaction = instigatorFactionComponent.GetAffiliatedFaction();
 
  213                 if (instigatorFaction)
 
  214                     record.m_InstigatorFaction = instigatorFaction.GetFactionKey();
 
  224 sealed 
class SCR_MovementRecord : SCR_IGameModeRecord
 
  230     sealed 
override SCR_EGameModeRecordType GetRecordType()
 
  232         return SCR_EGameModeRecordType.Movement;
 
  236     override string Save()
 
  239         return string.Format(
"%1;%2;", pos, m_PlayerId);
 
  243     protected sealed 
override void Load(array<string> tokens)
 
  245         array <string> pos = {};
 
  246         tokens[0].Split(
",", pos, 
true);
 
  247         m_Position = Vector(pos[0].ToFloat(), pos[1].ToFloat(), pos[2].ToFloat());
 
  248         m_PlayerId = tokens[1].ToInt();
 
  256     static ref SCR_MovementRecord CreateNew(IEntity player, 
int playerId)
 
  258         SCR_MovementRecord record = 
new SCR_MovementRecord();
 
  259         record.m_Position = player.GetOrigin();
 
  260         record.m_PlayerId = playerId;
 
  261         record.m_fTimestamp = player.GetWorld().GetWorldTime();
 
  267 sealed 
class SCR_ConnectionRecord : SCR_IGameModeRecord
 
  273     sealed 
override SCR_EGameModeRecordType GetRecordType()
 
  275         return SCR_EGameModeRecordType.Connection;
 
  279     override string Save()
 
  281         return string.Format(
"%1;%2;", m_PlayerId, m_PlayerName);
 
  285     protected sealed 
override void Load(array<string> tokens)
 
  287         m_PlayerId = tokens[0].ToInt();
 
  288         m_PlayerName = tokens[1];
 
  296     static ref SCR_ConnectionRecord CreateNew(
int playerId, 
string playerName)
 
  298         SCR_ConnectionRecord record = 
new SCR_ConnectionRecord();
 
  299         record.m_PlayerId = playerId;
 
  300         record.m_PlayerName = playerName;
 
  301         record.m_fTimestamp = 
GetGame().GetWorld().GetWorldTime();
 
  306 sealed 
class SCR_SpawnRecord : SCR_IGameModeRecord 
 
  311     sealed 
override SCR_EGameModeRecordType GetRecordType()
 
  313         return SCR_EGameModeRecordType.Spawn;
 
  316     override string Save()
 
  318         return string.Format(
"%1;%2;", m_PlayerId, m_FactionColor);
 
  321     protected sealed 
override void Load(array<string> tokens)
 
  323         m_PlayerId = tokens[0].ToInt();
 
  324         m_FactionColor = tokens[1].ToInt();
 
  329     void SCR_SpawnRecord()
 
  337     static ref SCR_SpawnRecord CreateNew(
int playerId, 
int factionColor)
 
  339         SCR_SpawnRecord record = 
new SCR_SpawnRecord();
 
  340         record.m_PlayerId = playerId;
 
  341         record.m_FactionColor = factionColor;
 
  342         record.m_fTimestamp = 
GetGame().GetWorld().GetWorldTime();
 
  347 sealed 
class SCR_AILODRecord : SCR_IGameModeRecord
 
  354     int m_PerceptionCounter = 0;
 
  356     sealed 
override SCR_EGameModeRecordType GetRecordType()
 
  358         return SCR_EGameModeRecordType.AILOD;
 
  361     override string Save()
 
  364         return string.Format(
"%1;%2;%3;%4;%5;%6", m_ID, pos, m_LOD, 
m_Type, m_BTCounter, m_PerceptionCounter);
 
  367     protected sealed 
override void Load(array<string> tokens)
 
  369         array <string> pos = {};
 
  371         tokens[1].Split(
",", pos, 
true);
 
  372         m_Position = Vector(pos[0].ToFloat(), pos[1].ToFloat(), pos[2].ToFloat());
 
  373         m_LOD = tokens[2].ToInt();
 
  374         m_Type = tokens[3].ToInt();
 
  375         m_BTCounter = tokens[4].ToInt();
 
  376         m_PerceptionCounter = tokens[5].ToInt();
 
  383     static ref SCR_AILODRecord CreateNew(AIAgent agent)
 
  385         SCR_AILODRecord record = 
new SCR_AILODRecord();
 
  386         record.m_fTimestamp = 
GetGame().GetWorld().GetWorldTime();
 
  387         record.m_LOD = agent.GetLOD();
 
  389         IEntity ent = agent.GetControlledEntity();
 
  392             record.m_Type = ETypeOfAgent.Group;
 
  393             record.m_Position = group.GetCenterOfMass();
 
  398                 record.m_Position = ent.GetOrigin();
 
  399             if (AIFlock.Cast(agent))
 
  400                 record.m_Type = ETypeOfAgent.Bird;
 
  402                 record.m_Type = ETypeOfAgent.Player;
 
  404                 record.m_Type = ETypeOfAgent.Agent;         
 
  407         AIChimeraBehaviorTreeComponent btComp = AIChimeraBehaviorTreeComponent.Cast(agent.FindComponent(AIChimeraBehaviorTreeComponent));
 
  409             record.m_BTCounter = btComp.GetSimulateCounter();
 
  413             PerceptionComponent percComp = PerceptionComponent.Cast(ent.FindComponent(PerceptionComponent));
 
  415                 record.m_PerceptionCounter = percComp.GetSimulateCounter();
 
  417         record.m_ID = agent.GetID().ToString().Substring(2,16);
 
  423 class SCR_GameModeStatistics
 
  426     static const int RECORD_INTERVAL_MS = 1000;
 
  429     private static ref array<ref SCR_IGameModeRecord> s_aRecordBuffer = {};
 
  432     private static ref FileHandle s_pFileHandle;
 
  435     private static const string k_sExtension = 
".txt";
 
  439     static bool IsRecording()
 
  449     static void StartRecording()
 
  453             Debug.Error(
"Already recording!");
 
  457         string filename = 
"GameStatistics_" + FormatTimestamp() + k_sExtension;
 
  458         s_pFileHandle = FileIO.OpenFile(
"$logs:/" + filename, FileMode.WRITE);
 
  463     static bool CanFlush()
 
  465         return s_aRecordBuffer.Count() > 0;
 
  474             Debug.Error(
"Cannot flush buffer, statistics are not being recorded!");
 
  482         for (
int i = 0, count = s_aRecordBuffer.Count(); i < count; i++)
 
  484             SCR_IGameModeRecord record = s_aRecordBuffer[i];
 
  488             string entry = record.SaveToString();
 
  492             s_pFileHandle.WriteLine(entry);
 
  496         s_aRecordBuffer.Clear();
 
  501     static void StopRecording()
 
  505             Debug.Error(
"Not recording!");
 
  513         s_pFileHandle.Close();
 
  514         s_pFileHandle = 
null;
 
  523     static void RecordDeath(
int playerId, IEntity playerEntity, IEntity killerEntity, 
Instigator killer)
 
  525         SCR_DeathRecord rec = SCR_DeathRecord.CreateNew(playerId, playerEntity, killerEntity, killer);
 
  526         s_aRecordBuffer.Insert(rec);
 
  533     static void RecordMovement(IEntity player, 
int playerId)
 
  535         SCR_MovementRecord rec = SCR_MovementRecord.CreateNew(player, playerId);
 
  536         s_aRecordBuffer.Insert(rec);
 
  543     static void RecordConnection(
int playerId, 
string playerName)
 
  545         SCR_ConnectionRecord rec = SCR_ConnectionRecord.CreateNew(playerId, playerName);
 
  546         s_aRecordBuffer.Insert(rec);
 
  553     static void RecordSpawn(
int playerId, 
int factionColor)
 
  555         SCR_SpawnRecord rec = SCR_SpawnRecord.CreateNew(playerId, factionColor);
 
  556         s_aRecordBuffer.Insert(rec);
 
  562     static void RecordAILOD(AIAgent aiagent)
 
  564         SCR_AILODRecord rec = SCR_AILODRecord.CreateNew(aiagent);
 
  565         s_aRecordBuffer.Insert(rec);
 
  570     static int OpenStatistics(
string filename, notnull array<ref SCR_IGameModeRecord> outRecords)
 
  573         if (!filename.EndsWith(k_sExtension))
 
  574             filename += k_sExtension;
 
  576         if (!FileIO.FileExists(filename))
 
  579         FileHandle fileHnd = FileIO.OpenFile(filename, FileMode.READ);
 
  585         while (fileHnd.ReadLine(temp) > 0)
 
  587             ref SCR_IGameModeRecord record = SCR_IGameModeRecord.LoadFromString(temp);
 
  590                 outRecords.Insert(record);
 
  602     static void FilterRecords(
typename predicate, notnull array<SCR_IGameModeRecord> records, out array<SCR_IGameModeRecord> filteredRecords)
 
  604         foreach (SCR_IGameModeRecord record : records)
 
  606             if (record.Type().IsInherited(predicate))
 
  607                 filteredRecords.Insert(record);
 
  613     static void FilterRecordsRefRef(
typename predicate, notnull array<ref SCR_IGameModeRecord> records, out array<ref SCR_IGameModeRecord> filteredRecords)
 
  615         foreach (SCR_IGameModeRecord record : records)
 
  617             if (record.Type().IsInherited(predicate))
 
  618                 filteredRecords.Insert(record);
 
  624     static void FilterRecordsWeakRef(
typename predicate, notnull array<SCR_IGameModeRecord> records, out array<ref SCR_IGameModeRecord> filteredRecords)
 
  626         foreach (SCR_IGameModeRecord record : records)
 
  628             if (record.Type().IsInherited(predicate))
 
  629                 filteredRecords.Insert(record);
 
  635     private static string FormatTimestamp()
 
  637         int year, month, day;
 
  638         System.GetYearMonthDay(year, month, day);
 
  641             smonth = 
string.Format(
"0%1", month);
 
  643             smonth = 
string.Format(
"%1", month);
 
  646             sday = 
string.Format(
"0%1", day);
 
  648             sday = 
string.Format(
"%1", day);
 
  651         System.GetHourMinuteSecond(h, m, s);
 
  654             sh = 
string.Format(
"0%1", h);
 
  656             sh = 
string.Format(
"%1", h);
 
  659             sm = 
string.Format(
"0%1", m);
 
  661             sm = 
string.Format(
"%1", m);
 
  663             ss = 
string.Format(
"0%1", s);
 
  665             ss = 
string.Format(
"%1", s);
 
  667         return string.Format(
"%1%2%3-%4%5%6", year, smonth, sday, sh, sm, ss);
 
  672 class SCR_StatisticsDrawerEntityClass : GenericEntityClass
 
  679     protected ref array<ref SCR_IGameModeRecord> m_aRecords;
 
  682     protected bool m_bUseHistory = 
false;
 
  685     protected bool m_bNoZBuffer = 
false;
 
  688     protected float m_fGizmosScaleMultiplier = 1.0;
 
  691     protected int m_iUniquePlayerCount = 0;
 
  694     protected int m_iTargetPlayer = 0;
 
  697     protected bool m_bDraw = 
true;
 
  700     protected bool m_bDrawDeaths = 
true;
 
  703     protected bool m_bDrawDeathsInfo = 
true;
 
  706     protected bool m_bDrawMovement = 
true;
 
  709     protected bool m_bDrawPlayerNames = 
true;
 
  712     protected bool m_bDrawAILODs = 
true;
 
  715     protected bool m_bAutoPlay;
 
  718     protected float m_fPlaybackSpeed = 1.0;
 
  721     protected float m_fCurrentTime;
 
  724     protected float m_fMaxTime;
 
  727     protected float m_fHistoryLength = 10000;
 
  730     protected ref map<int, ref array<ref SCR_IGameModeRecord>> m_aDeathRecords = 
new map<int, ref array<ref SCR_IGameModeRecord>>();
 
  733     protected ref map<int, ref array<ref SCR_IGameModeRecord>> m_aMovementRecords = 
new map<int, ref array<ref SCR_IGameModeRecord>>();
 
  736     protected ref map<int, ref array<ref SCR_IGameModeRecord>> m_aSpawnRecords = 
new map<int, ref array<ref SCR_IGameModeRecord>>();
 
  739     protected ref array<ref SCR_IGameModeRecord> m_aConnectionRecords = {};
 
  742     protected ref map<string, ref array<ref SCR_IGameModeRecord>> m_aAILODRecords = 
new map<string, ref array<ref SCR_IGameModeRecord>>();
 
  744     protected ref array<ref Shape> m_aShapes = {};
 
  745     protected ref array<ref DebugText> m_aTexts = {};
 
  748     protected ref map<int, string> m_mPlayerNames = 
new map<int, string>();
 
  753     private static const float MAX_MOVEMENT_SPEED = 11.1;
 
  755     protected static const float TELEPORT_DISTANCE = MAX_MOVEMENT_SPEED * (SCR_GameModeStatistics.RECORD_INTERVAL_MS / 1000.0);
 
  756     protected static const float TELEPORT_DISTANCE_SQ = TELEPORT_DISTANCE * TELEPORT_DISTANCE;
 
  759     protected static const int PLAYER_COLORS_COUNT = 27;
 
  760     protected static const vector PLAYER_COLORS_ARRAY[PLAYER_COLORS_COUNT] = {
 
  761         "255 255 255", 
"169 244 0", 
"244 67 54", 
"233 30 99", 
"156 39 176", 
"63 81 181", 
"0 188 212", 
"0 150 136", 
"76 175 80", 
"205 220 57",
 
  762         "255 235 59", 
"255 152 0", 
"121 85 72", 
"95 125 139",
"62 69 81",
"3 159 244",
"244 67 54",
"233 30 99", 
"156 39 176",
 
  763         "63 81 181", 
"0 188 212", 
"0 150 136", 
"76 175 80", 
"205 220 57", 
"255 235 59", 
"255 157 0", 
"121 85 139" 
  766     protected static const vector AILOD_COLORS_ARRAY[11] = {
 
  780     protected bool m_bFactionColors = 
false;
 
  784     protected bool IsEmpty()
 
  786         if (!m_aRecords || m_aRecords.Count() < 1)
 
  794     protected bool OpenStatisticsFile(
string filename)
 
  797         int count = SCR_GameModeStatistics.OpenStatistics(filename, m_aRecords);
 
  803     protected void Clear()
 
  807         m_aDeathRecords.Clear();
 
  808         m_aMovementRecords.Clear();
 
  809         m_aConnectionRecords.Clear();
 
  810         m_aAILODRecords.Clear();
 
  818     protected void Close()
 
  826     protected void LoadRecords(array<ref SCR_IGameModeRecord> records)
 
  831         array<ref SCR_IGameModeRecord> deaths = {};
 
  832         SCR_GameModeStatistics.FilterRecordsRefRef(SCR_DeathRecord, records, deaths);
 
  834         array<ref SCR_IGameModeRecord> movement = {};
 
  835         SCR_GameModeStatistics.FilterRecordsRefRef(SCR_MovementRecord, records, movement);
 
  837         array<ref SCR_IGameModeRecord> lodRecords = {};
 
  838         SCR_GameModeStatistics.FilterRecordsRefRef(SCR_AILODRecord, records, lodRecords);
 
  840         SCR_GameModeStatistics.FilterRecordsRefRef(SCR_ConnectionRecord, records, m_aConnectionRecords);
 
  842         array<ref SCR_IGameModeRecord> spawn = {};
 
  843         SCR_GameModeStatistics.FilterRecordsRefRef(SCR_SpawnRecord, records, spawn);
 
  845         vector max = 
"-999999 -999999 -999999";
 
  846         vector min = 
"999999 999999 999999";
 
  849         m_aMovementRecords.Clear();
 
  850         foreach (SCR_IGameModeRecord record : movement)
 
  852             SCR_MovementRecord movementRecord = SCR_MovementRecord.Cast(record);
 
  853             if (!m_aMovementRecords.Contains(movementRecord.m_PlayerId))
 
  856                 m_aMovementRecords.Insert(movementRecord.m_PlayerId, 
new array<ref SCR_IGameModeRecord>());
 
  860             m_aMovementRecords[movementRecord.m_PlayerId].Insert(movementRecord);
 
  863             for (
int i = 0; i < 3; i++)
 
  865                 if (movementRecord.m_Position[i] < min[i])
 
  866                     min[i] = movementRecord.m_Position[i];
 
  868                 if (movementRecord.m_Position[i] > max[i])
 
  869                     max[i] = movementRecord.m_Position[i];
 
  874         m_aDeathRecords.Clear();
 
  875         foreach (SCR_IGameModeRecord record : deaths)
 
  877             SCR_DeathRecord deathRecord = SCR_DeathRecord.Cast(record);
 
  878             if (!m_aDeathRecords.Contains(deathRecord.m_PlayerId))
 
  881                 m_aDeathRecords.Insert(deathRecord.m_PlayerId, 
new array<ref SCR_IGameModeRecord>());
 
  885             m_aDeathRecords[deathRecord.m_PlayerId].Insert(deathRecord);
 
  890         m_aSpawnRecords.Clear();
 
  891         foreach (SCR_IGameModeRecord record : spawn)
 
  893             SCR_SpawnRecord spawnRecord = SCR_SpawnRecord.Cast(record);
 
  894             if (!m_aSpawnRecords.Contains(spawnRecord.m_PlayerId))
 
  897                 m_aSpawnRecords.Insert(spawnRecord.m_PlayerId, 
new array<ref SCR_IGameModeRecord>());
 
  901             m_aSpawnRecords[spawnRecord.m_PlayerId].Insert(spawnRecord);
 
  905         m_aAILODRecords.Clear();
 
  906         foreach (SCR_IGameModeRecord record : lodRecords)
 
  908             SCR_AILODRecord lodRecord = SCR_AILODRecord.Cast(record);
 
  909             if (!m_aAILODRecords.Contains(lodRecord.m_ID))
 
  912                 m_aAILODRecords.Insert(lodRecord.m_ID, 
new array<ref SCR_IGameModeRecord>());
 
  916             m_aAILODRecords[lodRecord.m_ID].Insert(lodRecord);
 
  920         if (records.Count() > 0)
 
  921             m_fMaxTime = records[records.Count() - 1].GetTimestamp();
 
  926         m_iUniquePlayerCount = 0;
 
  927         m_mPlayerNames.Clear();
 
  928         for (
int i = 0, count = m_aConnectionRecords.Count(); i < count; ++i)
 
  930             SCR_ConnectionRecord record = SCR_ConnectionRecord.Cast(m_aConnectionRecords[i]);
 
  931             int playerId = record.m_PlayerId;
 
  935             if (!m_mPlayerNames.Contains(playerId))
 
  937                 string name = 
"Unnamed";
 
  938                 if (!record.m_PlayerName.IsEmpty())
 
  939                     name = record.m_PlayerName;
 
  941                 m_mPlayerNames.Insert(playerId, name);
 
  942                 ++m_iUniquePlayerCount;
 
  952     private bool DrawCheck(
string label, inout 
bool outValue)
 
  954         bool previousValue = outValue;
 
  955         DbgUI.Check(label, outValue);
 
  956         return previousValue != outValue;
 
  961     private bool DrawSlider(
string label, inout 
float outValue, 
float min, 
float max, 
int pxWidth)
 
  963         float previousValue = outValue;
 
  964         DbgUI.SliderFloat(label, outValue, min, max, pxWidth);
 
  965         return previousValue != outValue;
 
  970     private bool DrawAdvancementButton(
string negativeLabel, 
string positiveLabel, inout 
float refValue, 
float addValue)
 
  972         float previousValue = refValue;
 
  973         if (DbgUI.Button(negativeLabel)) refValue = refValue - addValue;
 
  975         if (DbgUI.Button(positiveLabel)) refValue = refValue + addValue;
 
  976         return (previousValue != refValue);
 
  980     protected override void EOnFrame(IEntity owner, 
float timeSlice)
 
  982         bool isDirty = 
false;
 
  984         int spacerHeight = 32;
 
  986         DbgUI.Begin(
"GameMode Statistics");
 
  991                 DbgUI.Text(
"File to open: ");
 
  992                 string filename = 
"MyFile.gmstats";
 
  993                 DbgUI.InputText(
"", filename, pxWidth);
 
  995                 if (DbgUI.Button(
"Open")) 
 
  999                     OpenStatisticsFile(filename);
 
 1000                     LoadRecords(m_aRecords);
 
 1007                 DbgUI.Text(
"No data, load statistics first!");
 
 1014             if (DbgUI.Button(
"Close"))
 
 1019                 m_fCurrentTime = 0.0;
 
 1020                 m_bAutoPlay = 
false;
 
 1027             DbgUI.Text(
string.Format(
"Total Records: %1", m_aRecords.Count()));
 
 1030             DbgUI.Spacer(spacerHeight);
 
 1031             DbgUI.Text(
"Properties");
 
 1032             if (DrawCheck(
"Enabled", m_bDraw)) isDirty = 
true;
 
 1033             if (DrawCheck(
"Draw Death Records", m_bDrawDeaths)) isDirty = 
true;
 
 1034             if (m_bDrawDeaths && DrawCheck(
"Draw Death Infoboxes", m_bDrawDeathsInfo)) isDirty = 
true;
 
 1035             if (DrawCheck(
"Draw Movement Records", m_bDrawMovement)) isDirty = 
true;
 
 1036             if (DrawCheck(
"Draw Player List", m_bDrawPlayerNames)) isDirty = 
true;
 
 1037             if (DrawCheck(
"Draw AILODs", m_bDrawAILODs)) isDirty = 
true;
 
 1038             if (DrawCheck(
"Limit History Length", m_bUseHistory)) isDirty = 
true;
 
 1039             if (DrawCheck(
"No Z Buffer", m_bNoZBuffer)) isDirty = 
true;
 
 1040             if (DrawCheck(
"Faction Colors", m_bFactionColors)) isDirty = 
true;
 
 1041             if (DrawSlider(
"Gizmos Scale", m_fGizmosScaleMultiplier, 0.1, 25.0, pxWidth)) isDirty = 
true;
 
 1042             if (DbgUI.Button(
"Re-center camera"))
 
 1048                 DbgUI.Text(
"History Length = " + m_fHistoryLength * 0.001 + 
"s");
 
 1049                 if (DrawSlider(
"History Length", m_fHistoryLength, 100, 1000000, pxWidth)) isDirty = 
true;
 
 1051                 DbgUI.Spacer(spacerHeight);
 
 1052                 DbgUI.Text(
"Playback");
 
 1053                 DbgUI.Text(
string.Format(
"Time: %1 / %2 s", m_fCurrentTime * 0.001, m_fMaxTime * 0.001));
 
 1055                 string autoPlayText;
 
 1057                     autoPlayText = 
"Pause";
 
 1059                     autoPlayText = 
"Play";
 
 1062                 if (DbgUI.Button(autoPlayText))
 
 1063                     m_bAutoPlay = !m_bAutoPlay;
 
 1066                 if (DbgUI.Button(
"Stop"))
 
 1068                     m_bAutoPlay = 
false;
 
 1069                     m_fCurrentTime = 0.0;
 
 1074                 if (DrawSlider(
"Playback Speed: " + m_fPlaybackSpeed + 
"x", m_fPlaybackSpeed, 0.0, 16.0, pxWidth)) {}
 
 1078                 DbgUI.InputInt(
"Seek Time: (s)", seekTime, pxWidth);
 
 1080                 if (DbgUI.Button(
"Seek"))
 
 1082                     m_fCurrentTime = seekTime * 1000.0;
 
 1087                 if (DrawAdvancementButton(
"-1s", 
"+1s", m_fCurrentTime, 1000)) isDirty = 
true;
 
 1089                 if (DrawAdvancementButton(
"-2s", 
"+2s", m_fCurrentTime, 2000)) isDirty = 
true;
 
 1091                 if (DrawAdvancementButton(
"-5s", 
"+5s", m_fCurrentTime, 5000)) isDirty = 
true;
 
 1093                 if (DrawAdvancementButton(
"-10s", 
"+10s", m_fCurrentTime, 10000)) isDirty = 
true;
 
 1095                 if (DrawAdvancementButton(
"-30s", 
"+30s", m_fCurrentTime, 30000)) isDirty = 
true;
 
 1097                 if (DrawAdvancementButton(
"-60s", 
"+60s", m_fCurrentTime, 60000)) isDirty = 
true;
 
 1099                 if (DrawAdvancementButton(
"-100s", 
"+100s", m_fCurrentTime, 100000)) isDirty = 
true;
 
 1101                 if (DrawAdvancementButton(
"-300s", 
"+300s", m_fCurrentTime, 300000)) isDirty = 
true;
 
 1103                 if (DrawAdvancementButton(
"-600s", 
"+600s", m_fCurrentTime, 600000)) isDirty = 
true;
 
 1106                 m_fCurrentTime = Math.Clamp(m_fCurrentTime, 0, m_fMaxTime);
 
 1111                     m_fCurrentTime += timeSlice * m_fPlaybackSpeed * 1000.0; 
 
 1120         if (m_bDrawPlayerNames)
 
 1121             if (DrawPlayerList(pxWidth, spacerHeight)) isDirty = 
true;
 
 1131     protected void Repaint()
 
 1141         if (m_bDrawMovement)
 
 1142             RepaintMovement(m_iTargetPlayer);
 
 1145             RepaintDeaths(m_iTargetPlayer);
 
 1153     protected bool DrawPlayerList(
int pxWidth = 150, 
int spacerHeight = 16)
 
 1155         bool isDirty = 
false;
 
 1156         DbgUI.Begin(
"Player List");
 
 1159             string filterText = 
"Filter : ";
 
 1160             if (m_iTargetPlayer <= 0)
 
 1161                 filterText += 
"All players";
 
 1165                 if (m_mPlayerNames.Contains(m_iTargetPlayer))
 
 1166                     filterText += m_mPlayerNames[m_iTargetPlayer];
 
 1168                     filterText += 
"N/A";
 
 1171                 filterText = 
string.Format(
"%1 (Id: %2)", filterText, m_iTargetPlayer);
 
 1175             int previousValue = m_iTargetPlayer;
 
 1176             DbgUI.Text(filterText);
 
 1177             if (DrawSlider(
"", m_iTargetPlayer, 0, m_iUniquePlayerCount, pxWidth)) isDirty = 
true;
 
 1180             DbgUI.Spacer(spacerHeight);
 
 1181             DbgUI.Text(
"Players: ");
 
 1182             foreach (
int playerId, 
string playerName : m_mPlayerNames)
 
 1184                 string playerText = 
string.Format(
"%1: %2", playerId, playerName);
 
 1187                 vector rgb = PLAYER_COLORS_ARRAY[ playerId % PLAYER_COLORS_COUNT ];
 
 1188                 int color = ARGB(255, rgb[0], rgb[1], rgb[2]);
 
 1189                 DbgUI.Panel(playerText+
"_panel", 16, 16, color);
 
 1192                 DbgUI.Text(playerText);
 
 1200     protected float GetAlpha(
float timeStamp)
 
 1202         return Math.InverseLerp(m_fCurrentTime - m_fHistoryLength, m_fCurrentTime, timeStamp);
 
 1206     protected int GetShapeFlags()
 
 1208         int flags = ShapeFlags.TRANSP;
 
 1210             flags |= ShapeFlags.NOZBUFFER;
 
 1216     protected void RepaintAILODs()
 
 1218         vector characterRGB = PLAYER_COLORS_ARRAY[0];
 
 1219         vector groupRGB = PLAYER_COLORS_ARRAY[1];
 
 1221         int shapeFlags = GetShapeFlags();
 
 1222         float baseSphereScale = m_fGizmosScaleMultiplier * 0.25;
 
 1223         float baseCylinderScale = m_fGizmosScaleMultiplier * 2.5;
 
 1224         foreach(array<ref SCR_IGameModeRecord> lodRecords : m_aAILODRecords)
 
 1227             for (
int j = 0; j < lodRecords.Count(); j++)
 
 1229                 SCR_AILODRecord aiRecord = SCR_AILODRecord.Cast(lodRecords[j]);
 
 1230                 SCR_AILODRecord prevAiRecord;
 
 1232                     prevAiRecord = SCR_AILODRecord.Cast(lodRecords[j-1]);
 
 1233                 float timeStamp = aiRecord.GetTimestamp();
 
 1239                     if (timeStamp > m_fCurrentTime)
 
 1243                     alpha = GetAlpha(timeStamp);
 
 1244                     if (alpha <= 0.0 || alpha > 1.0)  
 
 1249                 vector LODcolor = AILOD_COLORS_ARRAY[aiRecord.m_LOD];
 
 1250                 color = ARGB(255 * alpha, LODcolor[0], LODcolor[1], LODcolor[2]);
 
 1252                 float scaleAlpha = Math.Lerp(0.7, 1.0, alpha); 
 
 1253                 if (aiRecord.m_Type == ETypeOfAgent.Group)
 
 1255                     ref Shape cylinder = Shape.CreateCylinder(color, shapeFlags | ShapeFlags.NOOUTLINE, aiRecord.m_Position, baseSphereScale * scaleAlpha, baseCylinderScale * scaleAlpha);
 
 1256                     m_aShapes.Insert(cylinder);
 
 1258                 else if ((aiRecord.m_Type == ETypeOfAgent.Agent))
 
 1260                     ref Shape sphere = Shape.CreateSphere(color, shapeFlags | ShapeFlags.NOOUTLINE, aiRecord.m_Position, baseSphereScale * scaleAlpha);
 
 1261                     m_aShapes.Insert(sphere);
 
 1263                 else if ((aiRecord.m_Type == ETypeOfAgent.Bird))
 
 1266                     points[0] = aiRecord.m_Position - Vector(m_fGizmosScaleMultiplier, 0, 0);
 
 1267                     points[1] = aiRecord.m_Position + Vector(m_fGizmosScaleMultiplier, 0, 0);
 
 1268                     points[2] = aiRecord.m_Position - Vector(0, m_fGizmosScaleMultiplier, 0);
 
 1269                     points[3] = aiRecord.m_Position + Vector(0, m_fGizmosScaleMultiplier, 0);
 
 1270                     points[4] = aiRecord.m_Position - Vector(0, 0, m_fGizmosScaleMultiplier);
 
 1271                     points[5] = aiRecord.m_Position + Vector(0, 0, m_fGizmosScaleMultiplier);
 
 1272                     points[6] = aiRecord.m_Position - Vector(m_fGizmosScaleMultiplier, 0, 0);
 
 1273                     ref Shape sphere = Shape.CreateLines(color, shapeFlags | ShapeFlags.NOOUTLINE, points, 7);
 
 1274                     m_aShapes.Insert(sphere);
 
 1278                     ref Shape cylinder = Shape.CreateCylinder(ARGB(255 * alpha, 0xff, 0xff, 0 ),
 
 1279                      shapeFlags | ShapeFlags.NOOUTLINE, aiRecord.m_Position, baseSphereScale * scaleAlpha, baseCylinderScale * scaleAlpha);
 
 1280                     m_aShapes.Insert(cylinder);
 
 1282                 int btCounterNum = aiRecord.m_BTCounter;
 
 1283                 int percCounterNum = aiRecord.m_PerceptionCounter;
 
 1284                 if (!btCounterNum && !percCounterNum)
 
 1288                     btCounterNum -= prevAiRecord.m_BTCounter;
 
 1289                     percCounterNum -= prevAiRecord.m_PerceptionCounter;
 
 1291                 string text = 
string.Format(
"%1,%2", btCounterNum, percCounterNum);
 
 1296                 mat[3] = aiRecord.m_Position + 3 * vector.Up;
 
 1298                 ref DebugText textShape = DebugTextWorldSpace.CreateInWorld(GetWorld(), text, DebugTextFlags.FACE_CAMERA | DebugTextFlags.CENTER, mat, 0.5, color, 0xFF111111); 
 
 1299                 m_aTexts.Insert(textShape);
 
 1305     protected void RepaintDeaths(
int filterPlayerId = -1)
 
 1307         const int black50A = ARGB(100, 0, 0, 0); 
 
 1308         int shapeFlags = GetShapeFlags();
 
 1310         foreach (
int playerId, array<ref SCR_IGameModeRecord> playerRecords : m_aDeathRecords)
 
 1313             if (filterPlayerId > 0)
 
 1315                 if (filterPlayerId != playerId)
 
 1319             array<ref SCR_IGameModeRecord> spawnRecords= m_aSpawnRecords.Get(playerId);
 
 1322             const vector extents = 
"0.25 0.25 0.25";
 
 1323             vector scaledExtents = m_fGizmosScaleMultiplier * extents;
 
 1324             foreach (SCR_IGameModeRecord genericRecord : playerRecords)
 
 1326                 SCR_DeathRecord record = SCR_DeathRecord.Cast(genericRecord); 
 
 1327                 float timeStamp = record.GetTimestamp();
 
 1333                     if (timeStamp > m_fCurrentTime)
 
 1337                     alpha = GetAlpha(timeStamp);
 
 1338                     if (alpha <= 0.0 || alpha > 1.0) 
 
 1342                 int instigatorColor = black50A;
 
 1344                 vector victimRGB = PLAYER_COLORS_ARRAY[ record.m_PlayerId % PLAYER_COLORS_COUNT ];
 
 1346                 if (m_bFactionColors && spawnRecords)
 
 1348                     while(spawnId > -1 && spawnRecords[spawnId].GetTimestamp() > timeStamp)
 
 1350                     while(spawnId+1 < spawnRecords.Count() && spawnRecords[spawnId+1].GetTimestamp() < timeStamp)
 
 1352                     victimColor = SCR_SpawnRecord.Cast(spawnRecords[spawnId]).m_FactionColor;
 
 1355                     victimColor = ARGB(255 * alpha, victimRGB[0], victimRGB[1], victimRGB[2]);
 
 1358                 vector instigatorPosition;
 
 1360                 if (m_bDrawDeathsInfo)
 
 1367                     string victimName = 
"Unknown";
 
 1368                     if (m_mPlayerNames.Contains(record.m_PlayerId))
 
 1369                         victimName = m_mPlayerNames[record.m_PlayerId];
 
 1372                     string instigatorName = 
"Unknown";
 
 1373                     if (record.m_InstigatorId > 0)
 
 1374                         if (m_mPlayerNames.Contains(record.m_InstigatorId))
 
 1375                             instigatorName = m_mPlayerNames[record.m_InstigatorId];
 
 1379                     if (record.m_InstigatorId != record.m_PlayerId &&
 
 1380                         record.m_InstigatorPosition != record.m_Position)
 
 1382                         vector instigatorRGB = PLAYER_COLORS_ARRAY[ record.m_InstigatorId % PLAYER_COLORS_COUNT ];
 
 1383                         instigatorColor = ARGB(alpha * 255, instigatorRGB[0], instigatorRGB[1], instigatorRGB[2]);
 
 1385                         ref Shape arrowShape = Shape.CreateArrow(record.m_InstigatorPosition, record.m_Position, 0.5, instigatorColor, shapeFlags);
 
 1386                         m_aShapes.Insert(arrowShape);
 
 1388                         float distance = vector.Distance(record.m_InstigatorPosition, record.m_Position);
 
 1389                         deathText = 
string.Format(
"Victim: %1\nFaction: %2\n\nInstigator: %3\nFaction: %4\n\nDistance: %5m\nWeapon: %6\nTime: %7s",
 
 1393                             record.m_InstigatorFaction,
 
 1395                             typename.EnumToString(
EWeaponType, record.m_WeaponType),
 
 1399                         instigatorPosition = record.m_InstigatorPosition;
 
 1404                         deathText = 
string.Format(
"Victim: %1\nFaction:(%2)\n\nInstigator: (Self/Unknown)\n\nTime: %3s",
 
 1411                         instigatorPosition = record.m_Position;
 
 1412                         instigatorColor = victimColor;
 
 1416                     int backgroundColor = ARGB(100 * alpha, 0.0, 0.0, 0.0);
 
 1419                     vector textPosition = vector.Lerp(record.m_Position, instigatorPosition, 0.5) + 
"0 0.1 0"; 
 
 1420                     ref DebugText textShape = DebugTextWorldSpace.Create(GetWorld(), deathText, DebugTextFlags.FACE_CAMERA | DebugTextFlags.CENTER, textPosition[0], textPosition[1], textPosition[2], 16.0, color: instigatorColor, bgColor: backgroundColor);
 
 1421                     m_aTexts.Insert(textShape);
 
 1425                 ref Shape deathShape = Shape.Create(ShapeType.BBOX, victimColor, shapeFlags,  -scaledExtents, scaledExtents);
 
 1426                 vector transformation[4];
 
 1427                 Math3D.MatrixIdentity3(transformation);
 
 1428                 transformation[3] = record.m_Position;
 
 1429                 deathShape.SetMatrix(transformation);
 
 1431                 m_aShapes.Insert(deathShape);
 
 1437     protected void RepaintMovement(
int filterPlayerId = -1)
 
 1439         int shapeFlags = GetShapeFlags();
 
 1440         float baseSphereScale = m_fGizmosScaleMultiplier * 0.125;
 
 1441         float baseArrowScale = m_fGizmosScaleMultiplier * 0.25;
 
 1442         foreach (
int playerId, array<ref SCR_IGameModeRecord> playerRecords : m_aMovementRecords)
 
 1445             if (filterPlayerId > 0)
 
 1447                 if (filterPlayerId != playerId)
 
 1452             array<ref SCR_IGameModeRecord> spawnRecords= m_aSpawnRecords.Get(playerId);
 
 1455             for (
int i = 0, count = playerRecords.Count(); i < count - 1; i++)
 
 1457                 SCR_MovementRecord record = SCR_MovementRecord.Cast(playerRecords[i]);
 
 1458                 float timeStamp = record.GetTimestamp();
 
 1461                 SCR_MovementRecord nextRecord = SCR_MovementRecord.Cast(playerRecords[i+1]);
 
 1466                     if (timeStamp > m_fCurrentTime)
 
 1470                     alpha = GetAlpha(timeStamp);
 
 1471                     if (alpha <= 0.0 || alpha > 1.0) 
 
 1477                 if (vector.DistanceSqXZ(record.m_Position, nextRecord.m_Position) >= TELEPORT_DISTANCE_SQ)
 
 1480                 vector playerRGB = PLAYER_COLORS_ARRAY[ record.m_PlayerId % PLAYER_COLORS_COUNT ];
 
 1482                 if (m_bFactionColors && spawnRecords)
 
 1484                     while(spawnId > -1 && spawnRecords[spawnId].GetTimestamp() > timeStamp)
 
 1486                     while(spawnId+1 < spawnRecords.Count() && spawnRecords[spawnId+1].GetTimestamp() < timeStamp)
 
 1488                     playerColor = SCR_SpawnRecord.Cast(spawnRecords[spawnId]).m_FactionColor;
 
 1491                     playerColor = ARGB(255 * alpha, playerRGB[0], playerRGB[1], playerRGB[2]);
 
 1496                 float scaleAlpha = Math.Lerp(0.7, 1.0, alpha); 
 
 1497                 ref Shape arrowShape = Shape.CreateArrow(record.m_Position, nextRecord.m_Position, baseArrowScale * scaleAlpha, playerColor, shapeFlags);
 
 1498                 ref Shape sphereShape = Shape.CreateSphere(playerColor, shapeFlags | ShapeFlags.NOOUTLINE, record.m_Position, baseSphereScale * scaleAlpha);
 
 1499                 m_aShapes.Insert(arrowShape);
 
 1500                 m_aShapes.Insert(sphereShape);
 
 1506     protected void FocusCamera(vector mins, vector maxs, 
float height = 100.0)
 
 1508         CameraManager cameraManager = 
GetGame().GetCameraManager();
 
 1512         CameraBase camera = cameraManager.CurrentCamera();
 
 1516         vector center = vector.Lerp(mins, maxs, 0.5);
 
 1517         vector 
position = Vector(center[0], center[1] + height, center[2]);
 
 1519         vector transform[4];
 
 1520         Math3D.AnglesToMatrix(
"0 -89.9 0", transform);
 
 1523         camera.SetWorldTransform(transform);
 
 1530     void SCR_StatisticsDrawerEntity(IEntitySource src, IEntity parent)
 
 1532         SetEventMask(EntityEvent.INIT | EntityEvent.FRAME);
 
 1538     void ~SCR_StatisticsDrawerEntity()