BVB Source Codes

CRYENGINE Show GameStats.cpp Source code

Return Download CRYENGINE: download GameStats.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /*************************************************************************
  4.    -------------------------------------------------------------------------
  5.    $Id$
  6.    $DateTime$
  7.    Description:
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    - 17:11:2006   15:38 : Created by Stas Spivakov
  12.  
  13. *************************************************************************/
  14. #include "StdAfx.h"
  15. #include "GameStats.h"
  16. #include <CryNetwork/INetwork.h>
  17. #include <CryNetwork/INetworkService.h>
  18. #include <CryGame/IGameFramework.h>
  19. #include "IGameRulesSystem.h"
  20. #include "CryAction.h"
  21. #include "GameContext.h"
  22. #include "ILevelSystem.h"
  23. #include "GameServerNub.h"
  24. #include "GameStatsConfig.h"
  25. #include "CryActionCVars.h"
  26. #include <CryGame/IGameStatistics.h>
  27.  
  28. const float REPORT_INTERVAL = 1.0f;//each second send state to network engine
  29. const float UPDATE_INTERVAL = 20.0f;
  30.  
  31. const bool DEBUG_VERBOSE = false;  // Default should be false
  32.  
  33. struct SGetTime
  34. {
  35.         SGetTime() : hasvalue(false), s(0.0f){}
  36.         SGetTime(const CTimeValue& start) : hasvalue(false), s(start){}
  37.         operator const CTimeValue&()
  38.         {
  39.                 if (!hasvalue)
  40.                 {
  41.                         t = gEnv->pTimer->GetFrameStartTime() - s;
  42.                         hasvalue = true;
  43.                 }
  44.                 return t;
  45.         }
  46.         bool       hasvalue;
  47.         CTimeValue t;
  48.         CTimeValue s;
  49. };
  50.  
  51. struct CGameStats::Listener
  52.         : public IServerReportListener,
  53.           public IStatsTrackListener
  54. {
  55.         virtual void OnError(EServerReportError err)
  56.         {
  57.                 switch (err)
  58.                 {
  59.                 case eSRE_socket:
  60.                         GameWarning("Server report error : socket.");
  61.                         break;
  62.                 case eSRE_connect:
  63.                         GameWarning("Server report error : could not connect to master server.");
  64.                         break;
  65.                 case eSRE_noreply:
  66.                         GameWarning("Server report error : no reply from master server, check internet connection or firewall settings.");
  67.                         break;
  68.                 }
  69.         }
  70.  
  71.         virtual void OnPublicIP(uint32 ip, unsigned short port)
  72.         {
  73.                 string ip_str;
  74.                 ip_str.Format("%u.%u.%u.%u", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
  75.                 CryLog("Server's public address is %s:%u", ip_str.c_str(), port);
  76.                 ip_str += ":";
  77.                 ip_str += gEnv->pConsole->GetCVar("sv_port")->GetString();
  78.                 CCryAction::GetCryAction()->OnActionEvent(SActionEvent(eAE_serverIp, port, ip_str));
  79.         }
  80.  
  81.         virtual void OnError(EStatsTrackError)
  82.         {
  83.         }
  84.         CGameStats* m_pStats;
  85. };
  86.  
  87. // IHostMigrationEventListener
  88. IHostMigrationEventListener::EHostMigrationReturn CGameStats::OnInitiate(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  89. {
  90.         return IHostMigrationEventListener::Listener_Done;
  91. }
  92.  
  93. IHostMigrationEventListener::EHostMigrationReturn CGameStats::OnDisconnectClient(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  94. {
  95.         return IHostMigrationEventListener::Listener_Done;
  96. }
  97.  
  98. IHostMigrationEventListener::EHostMigrationReturn CGameStats::OnDemoteToClient(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  99. {
  100.         if (!hostMigrationInfo.ShouldMigrateNub())
  101.         {
  102.                 return IHostMigrationEventListener::Listener_Done;
  103.         }
  104.  
  105.         if (m_serverReport)
  106.         {
  107.                 m_serverReport->StopReporting();
  108.         }
  109.  
  110.         return IHostMigrationEventListener::Listener_Done;
  111. }
  112.  
  113. IHostMigrationEventListener::EHostMigrationReturn CGameStats::OnPromoteToServer(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  114. {
  115.         if (!hostMigrationInfo.ShouldMigrateNub())
  116.         {
  117.                 return IHostMigrationEventListener::Listener_Done;
  118.         }
  119.  
  120.         // Set up server side stats and start reporting the game on LAN browsers
  121.         Init();
  122.         ReportSession();
  123.  
  124.         return IHostMigrationEventListener::Listener_Done;
  125. }
  126.  
  127. IHostMigrationEventListener::EHostMigrationReturn CGameStats::OnReconnectClient(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  128. {
  129.         return IHostMigrationEventListener::Listener_Done;
  130. }
  131.  
  132. IHostMigrationEventListener::EHostMigrationReturn CGameStats::OnFinalise(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  133. {
  134.         return IHostMigrationEventListener::Listener_Done;
  135. }
  136.  
  137. IHostMigrationEventListener::EHostMigrationReturn CGameStats::OnTerminate(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  138. {
  139.         return IHostMigrationEventListener::Listener_Done;
  140. }
  141.  
  142. IHostMigrationEventListener::EHostMigrationReturn CGameStats::OnReset(SHostMigrationInfo& hostMigrationInfo, HMStateType& state)
  143. {
  144.         return IHostMigrationEventListener::Listener_Done;
  145. }
  146. // ~IHostMigrationEventListener
  147.  
  148. static const int MAX_INT = 0x7FFFFFFF;//maximum int (spelled by nonosuit voice)
  149.  
  150. struct CGameStats::SStatsTrackHelper
  151. {
  152.         SStatsTrackHelper(CGameStats* p) : m_parent(p), m_errors(0){}
  153.  
  154.         template<class T>
  155.         void ServerValue(const char* key, T value)
  156.         {
  157.                 int id = m_parent->m_config->GetKeyId(key);
  158.                 if (id != -1)
  159.                         m_parent->m_statsTrack->SetServerValue(id, value);
  160.                 else
  161.                         m_errors.push_back(key);
  162.         }
  163.  
  164.         template<class T>
  165.         void PlayerValue(int idx, const char* key, T value)
  166.         {
  167.                 int id = m_parent->m_config->GetKeyId(key);
  168.                 if (id != -1)
  169.                         m_parent->m_statsTrack->SetPlayerValue(idx, id, value);
  170.                 else
  171.                         m_errors.push_back(key);
  172.         }
  173.  
  174.         void PlayerCatValue(int idx, const char* cat, const char* key, int value)
  175.         {
  176.                 int mod = m_parent->m_config->GetCategoryMod(cat);
  177.                 int code = m_parent->m_config->GetCodeByKeyName(cat, key);
  178.                 int id = m_parent->m_config->GetKeyId(key);
  179.                 if (id != -1 && code != -1 && mod > 1)
  180.                 {
  181.                         int64 val = (value * mod + code);
  182.                         if (val > MAX_INT)
  183.                         {
  184.                                 //we need to clamp value so it will be biggest possible value with correct remainder from division by mod
  185.                                 val = MAX_INT - (MAX_INT % mod) + code;
  186.                                 if (val > MAX_INT)//still too big
  187.                                         val -= mod;
  188.                         }
  189.                         m_parent->m_statsTrack->SetPlayerValue(idx, id, (int)val);
  190.                 }
  191.                 else
  192.                         m_errors.push_back(key);
  193.         }
  194.  
  195.         template<class T>
  196.         void TeamValue(int idx, const char* key, T value)
  197.         {
  198.                 int id = m_parent->m_config->GetKeyId(key);
  199.                 if (id != -1)
  200.                         m_parent->m_statsTrack->SetTeamValue(idx, id, value);
  201.                 else
  202.                         m_errors.push_back(key);
  203.         }
  204.  
  205.         CGameStats*         m_parent;
  206.         std::vector<string> m_errors;
  207. };
  208.  
  209. template<class T>
  210. struct TTimeStampedData
  211. {
  212.         std::vector<std::pair<CTimeValue, T>> m_data;
  213.         void Value(const CTimeValue& t, const T& data)
  214.         {
  215.                 CRY_ASSERT(m_data.empty() || m_data.back().first <= t);//check that data is always ordered correctly
  216.                 m_data.push_back(std::make_pair(t, data));
  217.         }
  218. };
  219.  
  220. template<class T>
  221. static void SaveToXML(const XmlNodeRef& n, const char* name, const T& a)
  222. {
  223.         n->setAttr(name, a);
  224. }
  225.  
  226. static void SaveToXML(const XmlNodeRef& n, const char* name, const Vec3& a)
  227. {
  228.         XmlNodeRef v = gEnv->pSystem->CreateXmlNode("vec3");
  229.         v->setAttr("name", name);
  230.         v->setAttr("x", a.x);
  231.         v->setAttr("y", a.y);
  232.         v->setAttr("z", a.z);
  233.         n->addChild(v);
  234. }
  235.  
  236. static void SaveToXML(const XmlNodeRef& n, const char* name, const CTimeValue& t)
  237. {
  238.         n->setAttr(name, t.GetMilliSecondsAsInt64());
  239. }
  240.  
  241. template<class T>
  242. static void SaveToXML(const XmlNodeRef& n, const char* name, const TTimeStampedData<T>& data)
  243. {
  244.         XmlNodeRef v = gEnv->pSystem->CreateXmlNode("values");
  245.         v->setAttr("name", name);
  246.         for (int i = 0; i < data.m_data.size(); ++i)
  247.         {
  248.                 XmlNodeRef c = gEnv->pSystem->CreateXmlNode("value");
  249.                 SaveToXML(c, "time", data.m_data[i].first);
  250.                 T::SaveToXML(c, "", data.m_data[i].second);
  251.                 v->addChild(c);
  252.         }
  253.         n->addChild(v);
  254. }
  255.  
  256. struct CGameStats::SPlayerStats : public _reference_target_t
  257. {
  258.         void GetMemoryUsage(ICrySizer* pSizer) const { /*nothing*/ }
  259.         struct SVehicles
  260.         {
  261.                 struct SVehicle
  262.                 {
  263.                         SVehicle(const char* name) : m_name(name){}
  264.                         string     m_name; //class Name
  265.                         CTimeValue m_used;
  266.                 };
  267.                 struct SVehicleCompare
  268.                 {
  269.                         const bool operator()(const SVehicle& a, const string& b) { return a.m_name < b; }
  270.                         const bool operator()(const string& a, const SVehicle& b) { return a < b.m_name; }
  271.                 };
  272.                 typedef std::vector<SVehicle> TVehicles;
  273.                 SVehicles() : m_curVehicle(m_vehicles.end()), m_inVehicle(false)
  274.                 {}
  275.  
  276.                 void Enter(const char* vehicle, const CTimeValue& t)
  277.                 {
  278.                         if (m_curVehicle != m_vehicles.end() && m_curVehicle->m_name == vehicle)//entered current vehicle
  279.                         {
  280.                                 return;
  281.                         }
  282.                         //find it and add if needed
  283.                         TVehicles::iterator it = std::lower_bound(m_vehicles.begin(), m_vehicles.end(), CONST_TEMP_STRING(vehicle), SVehicleCompare());
  284.                         if (it == m_vehicles.end())
  285.                         {
  286.                                 m_curVehicle = m_vehicles.insert(m_vehicles.end(), SVehicle(vehicle));
  287.                         }
  288.                         else
  289.                         {
  290.                                 if (it->m_name == vehicle)
  291.                                 {
  292.                                         m_curVehicle = it;
  293.                                 }
  294.                                 else
  295.                                 {
  296.                                         m_curVehicle = m_vehicles.insert(it, SVehicle(vehicle));
  297.                                 }
  298.                         }
  299.                         m_inVehicle = true;
  300.                         m_enteredVehicle = t;
  301.                 }
  302.  
  303.                 void Leave(const char* vehicle, const CTimeValue& t)
  304.                 {
  305.                         if (m_curVehicle != m_vehicles.end())
  306.                         {
  307.                                 CRY_ASSERT(!vehicle || m_curVehicle->m_name == vehicle);
  308.                                 m_curVehicle->m_used += t - m_enteredVehicle;
  309.                                 m_curVehicle = m_vehicles.end();
  310.                         }
  311.                         m_inVehicle = false;
  312.                 }
  313.  
  314.                 bool                m_inVehicle;
  315.                 CTimeValue          m_enteredVehicle;
  316.                 TVehicles           m_vehicles;
  317.                 TVehicles::iterator m_curVehicle;
  318.  
  319.                 void                GetMemoryUsage(ICrySizer* pSizer) const { /*nothing*/ }
  320.         };
  321.  
  322.         struct SWeapons
  323.         {
  324.                 struct SWeapon
  325.                 {
  326.                         SWeapon(const char* n) : m_name(n), m_kills(0), m_shots(0), m_hits(0), m_reloads(0), m_damage(0.0f){}
  327.                         string      m_name;//class Name
  328.                         CTimeValue  m_used;
  329.  
  330.                         int         m_kills;
  331.                         int         m_shots;
  332.                         int         m_hits;
  333.                         int         m_reloads;
  334.                         float       m_damage;
  335.  
  336.                         static void SaveToXML(const XmlNodeRef& n, const char* name, const SWeapon& a)
  337.                         {
  338.                                 XmlNodeRef w = gEnv->pSystem->CreateXmlNode(name) ;
  339.                                 ::SaveToXML(w, "name", a.m_name) ;
  340.                                 ::SaveToXML(w, "used", a.m_used) ;
  341.                                 ::SaveToXML(w, "kills", a.m_kills) ;
  342.                                 ::SaveToXML(w, "shots", a.m_shots) ;
  343.                                 ::SaveToXML(w, "hits", a.m_hits) ;
  344.                                 ::SaveToXML(w, "reloads", a.m_reloads) ;
  345.                                 ::SaveToXML(w, "damage", a.m_damage);
  346.                                 n->addChild(w);
  347.                         }
  348.                 };
  349.                 typedef std::vector<SWeapon> TWeapons;
  350.  
  351.                 SWeapons() : m_curWeapon(m_weapons.end())
  352.                 {
  353.                 }
  354.  
  355.                 struct SWeaponCompare
  356.                 {
  357.                         const bool operator()(const SWeapon& a, const string& b) { return a.m_name < b; }
  358.                         const bool operator()(const string& a, const SWeapon& b) { return a < b.m_name; }
  359.                 };
  360.  
  361.                 void SelectWeapon(const char* name, const CTimeValue& time)
  362.                 {
  363.                         if (m_curWeapon != m_weapons.end() && m_curWeapon->m_name == name)//entered current vehicle
  364.                         {
  365.                                 return;
  366.                         }
  367.                         DeselectWeapon(time);//deselect old one
  368.                         //find it and add if needed
  369.                         TWeapons::iterator it = std::lower_bound(m_weapons.begin(), m_weapons.end(), CONST_TEMP_STRING(name), SWeaponCompare());
  370.                         if (it == m_weapons.end())
  371.                         {
  372.                                 m_curWeapon = m_weapons.insert(m_weapons.end(), SWeapon(name));
  373.                         }
  374.                         else
  375.                         {
  376.                                 if (it->m_name == name)
  377.                                 {
  378.                                         m_curWeapon = it;
  379.                                 }
  380.                                 else
  381.                                 {
  382.                                         m_curWeapon = m_weapons.insert(it, SWeapon(name));
  383.                                 }
  384.                         }
  385.                         m_selected = time;
  386.                 }
  387.  
  388.                 void DeselectWeapon(const CTimeValue& t)
  389.                 {
  390.                         if (m_curWeapon != m_weapons.end())
  391.                         {
  392.                                 m_curWeapon->m_used += t - m_selected;
  393.                                 m_curWeapon = m_weapons.end();
  394.                         }
  395.                 }
  396.  
  397.                 void Kill()
  398.                 {
  399.                         if (m_curWeapon != m_weapons.end())
  400.                                 m_curWeapon->m_kills++;
  401.                 }
  402.  
  403.                 void Kill(const char* name)
  404.                 {
  405.                         if (m_curWeapon != m_weapons.end() && m_curWeapon->m_name == name)
  406.                         {
  407.                                 m_curWeapon->m_kills++;
  408.                         }
  409.                         else
  410.                         {
  411.                                 TWeapons::iterator it = std::lower_bound(m_weapons.begin(), m_weapons.end(), CONST_TEMP_STRING(name), SWeaponCompare());
  412.                                 if (it != m_weapons.end() && it->m_name == name)
  413.                                         it->m_kills++;
  414.                         }
  415.                 }
  416.  
  417.                 void Shot(int pel)
  418.                 {
  419.                         if (m_curWeapon != m_weapons.end())
  420.                         {
  421.                                 m_curWeapon->m_shots += pel;
  422.                         }
  423.                 }
  424.  
  425.                 void Damage(float val)
  426.                 {
  427.                         if (m_curWeapon != m_weapons.end())
  428.                                 m_curWeapon->m_damage += val;
  429.                 }
  430.  
  431.                 void Damage(const char* name, float val)
  432.                 {
  433.                         TWeapons::iterator it = std::lower_bound(m_weapons.begin(), m_weapons.end(), CONST_TEMP_STRING(name), SWeaponCompare());
  434.                         if (it != m_weapons.end() && it->m_name == name)
  435.                                 it->m_damage += val;
  436.                 }
  437.  
  438.                 void Hit()
  439.                 {
  440.                         if (m_curWeapon != m_weapons.end())
  441.                         {
  442.                                 m_curWeapon->m_hits++;
  443.                         }
  444.                 }
  445.  
  446.                 void Hit(const char* name)
  447.                 {
  448.                         TWeapons::iterator it = std::lower_bound(m_weapons.begin(), m_weapons.end(), CONST_TEMP_STRING(name), SWeaponCompare());
  449.                         if (it != m_weapons.end() && it->m_name == name)
  450.                                 it->m_hits++;
  451.                 }
  452.  
  453.                 void Reload()
  454.                 {
  455.                         if (m_curWeapon != m_weapons.end())
  456.                         {
  457.                                 m_curWeapon->m_reloads++;
  458.                         }
  459.                 }
  460.  
  461.                 const char* GetCurrent() const
  462.                 {
  463.                         if (m_curWeapon != m_weapons.end())
  464.                         {
  465.                                 return m_curWeapon->m_name.c_str();
  466.                         }
  467.                         return "";
  468.                 }
  469.  
  470.                 TWeapons           m_weapons;
  471.                 TWeapons::iterator m_curWeapon;
  472.                 CTimeValue         m_selected;
  473.  
  474.                 static void        SaveToXML(const XmlNodeRef& n, const char* name, const SWeapons& a)
  475.                 {
  476.                         XmlNodeRef w = gEnv->pSystem->CreateXmlNode(name);
  477.                         for (int i = 0; i < a.m_weapons.size(); ++i)
  478.                         {
  479.                                 SWeapon::SaveToXML(w, "weapon", a.m_weapons[i]);
  480.                         }
  481.                         n->addChild(w);
  482.                 }
  483.         };
  484.  
  485.         struct SSuitMode
  486.         {
  487.                 SSuitMode() :
  488.                         m_currentMode(-1)
  489.                 {
  490.                         std::fill(m_kills, m_kills + 4, 0);
  491.                 }
  492.                 void SwitchMode(int mode, const CTimeValue& time)
  493.                 {
  494.                         if (m_currentMode >= 0 && m_currentMode < 4)
  495.                         {
  496.                                 m_used[m_currentMode] += time - m_lastTime;
  497.                         }
  498.                         m_currentMode = mode;
  499.                         m_lastTime = time;
  500.                 }
  501.                 void OnKill()
  502.                 {
  503.                         if (m_currentMode >= 0 && m_currentMode < 4)
  504.                                 m_kills[m_currentMode]++;
  505.                 }
  506.                 CTimeValue m_lastTime;
  507.                 int        m_currentMode;
  508.                 int        m_kills[4];
  509.                 CTimeValue m_used[4];
  510.         };
  511.  
  512.         struct SPlayerPos
  513.         {
  514.                 Vec3        pos;
  515.                 Vec3        fwd;
  516.                 float       terrainHeight;
  517.                 float       camHeight;
  518.  
  519.                 static void SaveToXML(const XmlNodeRef& n, const char* name, const SPlayerPos& a)
  520.                 {
  521.                         ::SaveToXML(n, "pos", a.pos) ;
  522.                         ::SaveToXML(n, "fwd", a.fwd) ;
  523.                         ::SaveToXML(n, "ground", a.terrainHeight) ;
  524.                         ::SaveToXML(n, "camera", a.camHeight);
  525.                 }
  526.         };
  527.         struct SPlayerEvent
  528.         {
  529.                 string      event;
  530.                 string      str_param;
  531.                 int         int_param;
  532.                 Vec3        vec3_param;
  533.                 float       float_param;
  534.                 string      str_2_param;
  535.                 static void SaveToXML(const XmlNodeRef& n, const char* name, const SPlayerEvent& a)
  536.                 {
  537.                         ::SaveToXML(n, "name", a.event) ;
  538.                         ::SaveToXML(n, "str_param", a.str_param) ;
  539.                         ::SaveToXML(n, "int_param", a.int_param) ;
  540.                         ::SaveToXML(n, "vec3_param", a.vec3_param) ;
  541.                         ::SaveToXML(n, "float_param", a.float_param) ;
  542.                         ::SaveToXML(n, "str_2_param", a.str_2_param);
  543.                 }
  544.  
  545.                 void GetMemoryUsage(ICrySizer* pSizer) const
  546.                 {
  547.                         pSizer->AddObject(event);
  548.                         pSizer->AddObject(str_param);
  549.                         pSizer->AddObject(str_2_param);
  550.                 }
  551.         };
  552.         SPlayerStats(const CTimeValue& t)
  553.                 : m_kills(0)
  554.                 , m_deaths(0)
  555.                 , m_shots(0)
  556.                 , m_hits(0)
  557.                 , m_melee(0)
  558.                 , m_revives(0)
  559.                 , m_inVehicle(false)
  560.                 , m_started(t)
  561.                 , m_dead(false)
  562.         {
  563.  
  564.         }
  565.  
  566.         void EnterVehicle(const char* vehicle, const CTimeValue& t)
  567.         {
  568.                 m_weapons.DeselectWeapon(t); //de-select weapon while in vehicle
  569.                 m_vehicles.Enter(vehicle, t);
  570.         }
  571.  
  572.         void LeaveVehicle(const char* vehicle, const CTimeValue& t)
  573.         {
  574.                 m_vehicles.Leave(vehicle, t);
  575.         }
  576.  
  577.         void SelectSuitMode(int mode, const CTimeValue& t)
  578.         {
  579.                 m_suit.SwitchMode(mode, t);
  580.         }
  581.  
  582.         void ClientKill(const char* wep, const CTimeValue& time)
  583.         {
  584.                 m_suit.OnKill();
  585.                 if (wep)
  586.                         m_weapons.Kill(wep);
  587.         }
  588.  
  589.         void ClientDeath(const CTimeValue& time)
  590.         {
  591.                 m_suit.SwitchMode(-1, time);//switch off
  592.                 m_vehicles.Leave(0, time);
  593.         }
  594.  
  595.         void ClientRevive(const CTimeValue& time)
  596.         {
  597.  
  598.         }
  599.  
  600.         void SelectWeapon(const char* name, const CTimeValue& time)
  601.         {
  602.                 m_weapons.SelectWeapon(name, time);
  603.         }
  604.  
  605.         void Spectator(bool spectator, const CTimeValue& time)
  606.         {
  607.                 if (spectator)
  608.                         m_weapons.DeselectWeapon(time);
  609.                 PlayerEvent(time, "spectator", "", spectator ? 1 : 0, ZERO);
  610.         }
  611.  
  612.         void WeaponShot(int pel, const CTimeValue& t, const Vec3& pos)
  613.         {
  614.                 m_weapons.Shot(pel);
  615.                 PlayerEvent(t, "fire", m_weapons.GetCurrent(), pel, pos);
  616.         }
  617.  
  618.         void Reload(const CTimeValue& t, const Vec3& pos)
  619.         {
  620.                 m_weapons.Reload();
  621.                 PlayerEvent(t, "reload", m_weapons.GetCurrent(), 0, pos);
  622.         }
  623.  
  624.         void FiremodeChanged(const CTimeValue& t, const Vec3& pos, const char* modeName)
  625.         {
  626.                 PlayerEvent(t, "firemode_changed", modeName, 0, pos);
  627.         }
  628.  
  629.         void ZoomIn(const CTimeValue& t, const Vec3& pos)
  630.         {
  631.                 PlayerEvent(t, "zoom_in", 0, 0, pos);
  632.         }
  633.  
  634.         void ZoomOut(const CTimeValue& t, const Vec3& pos)
  635.         {
  636.                 PlayerEvent(t, "zoom_out", 0, 0, pos);
  637.         }
  638.  
  639.         void WeaponDamage(const char* wep, float val)
  640.         {
  641.                 if (wep)
  642.                         m_weapons.Damage(wep, val);
  643.                 else
  644.                         m_weapons.Damage(val);
  645.         }
  646.  
  647.         void WeaponHit(const char* wep)
  648.         {
  649.                 if (wep)
  650.                         m_weapons.Hit(wep);
  651.                 else
  652.                         m_weapons.Hit();
  653.         }
  654.  
  655.         void WeaponKill(const char* wep)
  656.         {
  657.                 if (wep)
  658.                         m_weapons.Kill(wep);
  659.                 else
  660.                         m_weapons.Kill();
  661.         }
  662.  
  663.         void End(const CTimeValue& time)
  664.         {
  665.                 m_weapons.DeselectWeapon(time);
  666.                 m_vehicles.Leave(0, time);
  667.                 m_suit.SwitchMode(-1, time);
  668.                 m_ended = time;
  669.         }
  670.  
  671.         void Dump(const CTimeValue& time) const
  672.         {
  673.                 CryLog("$3=====Dumping player stats====");
  674.                 CryLog("Kills: %d", m_kills);
  675.                 CryLog("Deaths: %d", m_deaths);
  676.                 CryLog("Shots: %d", m_shots);
  677.                 CryLog("Hits: %d", m_hits);
  678.                 CryLog("Melee: %d", m_melee);
  679.                 CryLog("Revive: %d", m_revives);
  680.                 CryLog("Playtime: %d sec", int((time - m_started).GetSeconds()));
  681.                 /*CryLog("$3====Suit modes :");
  682.                    for(int i=0;i<4;++i)
  683.                    {
  684.                    int suit_time = 0;
  685.                    if(m_suit.m_currentMode == i)
  686.                    {
  687.                     suit_time = int((time - m_suit.m_lastTime + m_suit.m_used[i]).GetSeconds());
  688.                    }
  689.                    else
  690.                    {
  691.                     suit_time = int(m_suit.m_used[i].GetSeconds());
  692.                    }
  693.  
  694.                    CryLog("   Mode (%d) Time: %d sec Kills: %d", i, suit_time, m_suit.m_kills[i]);
  695.                    }
  696.  
  697.                    CryLog("$3====Vehicles :");
  698.                    for(int i=0;i<m_vehicles.m_vehicles.size();++i)
  699.                    {
  700.                    int vehicle_time = 0;
  701.                    if(m_vehicles.m_inVehicle && m_vehicles.m_curVehicle == (m_vehicles.m_vehicles.begin()+i))
  702.                    {
  703.                     vehicle_time = int((time - m_vehicles.m_enteredVehicle + m_vehicles.m_vehicles[i].m_used).GetSeconds());
  704.                    }
  705.                    else
  706.                    {
  707.                     vehicle_time = int(m_vehicles.m_vehicles[i].m_used.GetSeconds());
  708.                    }
  709.                    CryLog("   Vehicle %s Time: %d sec", m_vehicles.m_vehicles[i].m_name.c_str(), vehicle_time);
  710.                    }
  711.                  */
  712.                 CryLog("$3====Weapons :");
  713.                 for (int i = 0; i < m_weapons.m_weapons.size(); ++i)
  714.                 {
  715.                         const SWeapons::SWeapon& wep = m_weapons.m_weapons[i];
  716.                         int weapon_time = 0;
  717.                         if (!m_vehicles.m_inVehicle && m_weapons.m_curWeapon == (m_weapons.m_weapons.begin() + i))
  718.                         {
  719.                                 weapon_time = int((wep.m_used + time - m_weapons.m_selected).GetSeconds());
  720.                         }
  721.                         else
  722.                         {
  723.                                 weapon_time = int(wep.m_used.GetSeconds());
  724.                         }
  725.                         CryLog("   Weapon %s Time: %d sec shots %d hits %d kills %d", wep.m_name.c_str(), weapon_time, wep.m_shots, wep.m_hits, wep.m_kills);
  726.                 }
  727.                 CryLog("$3=====End player stats dump===");
  728.         }
  729.  
  730.         void PlayerPos(const CTimeValue& t, const Vec3& pos, const Vec3& fwd, float terrain, float camheight)
  731.         {
  732.                 SPlayerPos p;
  733.                 p.pos = pos;
  734.                 p.fwd = fwd;
  735.                 p.terrainHeight = terrain;
  736.                 p.camHeight = camheight;
  737.                 m_positions.Value(t, p);
  738.         }
  739.  
  740.         void PlayerEvent(const CTimeValue& t, const char* name, const char* param = 0, int iparam = 0, const Vec3& vparam = Vec3(0, 0, 0),
  741.                          float fparam = 0.0f, const char* sparam = 0)
  742.         {
  743.                 SPlayerEvent e;
  744.                 e.event = name;
  745.                 e.str_param = param;
  746.                 e.int_param = iparam;
  747.                 e.vec3_param = vparam;
  748.                 e.float_param = fparam;
  749.                 e.str_2_param = sparam;
  750.                 m_events.Value(t, e);
  751.         }
  752.  
  753.         static void SaveToXML(const XmlNodeRef& n, const char* name, const SPlayerStats& a)
  754.         {
  755.                 ::SaveToXML(n, "kills", a.m_kills);
  756.                 ::SaveToXML(n, "deaths", a.m_deaths);
  757.                 ::SaveToXML(n, "shots", a.m_shots);
  758.                 ::SaveToXML(n, "hits", a.m_hits);
  759.                 ::SaveToXML(n, "melee", a.m_melee);
  760.                 ::SaveToXML(n, "revives", a.m_revives);
  761.                 ::SaveToXML(n, "start", a.m_started);
  762.                 ::SaveToXML(n, "end", a.m_ended);
  763.                 SWeapons::SaveToXML(n, "weapons", a.m_weapons);
  764.                 ::SaveToXML(n, "positions", a.m_positions);
  765.                 ::SaveToXML(n, "events", a.m_events);
  766.         }
  767.  
  768.         int                            m_kills;
  769.         int                            m_deaths;
  770.         int                            m_shots;
  771.         int                            m_hits;
  772.         int                            m_melee;
  773.         int                            m_revives;
  774.  
  775.         bool                           m_inVehicle;
  776.  
  777.         CTimeValue                     m_started;
  778.         CTimeValue                     m_ended;
  779.         SVehicles                      m_vehicles;
  780.         SWeapons                       m_weapons;
  781.         SSuitMode                      m_suit;
  782.         bool                           m_dead;
  783.         TTimeStampedData<SPlayerPos>   m_positions;
  784.         TTimeStampedData<SPlayerEvent> m_events;
  785. };
  786.  
  787. struct CGameStats::SRoundStats
  788. {
  789.         SRoundStats()
  790.                 : m_roundTime(0)
  791.                 , m_victoryCondition(0)
  792.                 , m_respawn(false)
  793.                 , m_ranked(0)
  794.                 , m_round(0)
  795.                 , m_winner(0)
  796.         {}
  797.  
  798.         static void SaveToXML(const XmlNodeRef& n, const char* name, const SRoundStats& a)
  799.         {
  800.                 ::SaveToXML(n, "mapname", a.m_mapName);
  801.                 ::SaveToXML(n, "roundTime", a.m_roundTime);
  802.                 ::SaveToXML(n, "victoryCondition", a.m_victoryCondition);
  803.                 ::SaveToXML(n, "respawn", a.m_respawn);
  804.                 ::SaveToXML(n, "ranked", a.m_ranked);
  805.                 ::SaveToXML(n, "winner", a.m_winner);
  806.                 ::SaveToXML(n, "duration", a.m_duration);
  807.         }
  808.  
  809.         void Start(const char* mapname, const CTimeValue& time)
  810.         {
  811.                 m_mapName = mapname;
  812.                 if (ICVar* pV = gEnv->pConsole->GetCVar("g_roundtime"))
  813.                         m_roundTime = pV->GetIVal();
  814.                 if (ICVar* pV = gEnv->pConsole->GetCVar("g_victoryCondition"))
  815.                         m_victoryCondition = pV->GetIVal();
  816.                 if (ICVar* pV = gEnv->pConsole->GetCVar("g_respawn"))
  817.                         m_respawn = pV->GetIVal() != 0;
  818.                 if (ICVar* pV = gEnv->pConsole->GetCVar("g_ranked"))
  819.                         m_ranked = pV->GetIVal();
  820.                 m_round++;
  821.                 m_winner = 0;
  822.                 m_start = time;
  823.         }
  824.  
  825.         void End(int winner, const CTimeValue& time)
  826.         {
  827.                 m_winner = winner;
  828.                 m_duration = time - m_start;
  829.         }
  830.  
  831.         string     m_mapName;
  832.         int        m_roundTime;
  833.         int        m_victoryCondition;
  834.         bool       m_respawn;
  835.         int        m_ranked;
  836.         int        m_round;
  837.         int        m_winner;
  838.         CTimeValue m_start;
  839.         CTimeValue m_duration;
  840. };
  841.  
  842. CGameStats::CGameStats(CCryAction* pGameFramework)
  843.         : m_pGameFramework(pGameFramework)
  844.         , m_pActorSystem(pGameFramework->GetIActorSystem())
  845.         , m_statsTrack(0)
  846.         , m_serverReport(0)
  847.         , m_pListener(new Listener())
  848.         , m_lastUpdate(0.0f)
  849.         , m_lastReport(0.0f)
  850.         , m_playing(false)
  851.         , m_stateChanged(false)
  852.         , m_startReportNeeded(false)
  853.         , m_lastPosUpdate(0.0f)
  854.         , m_reportStarted(false)
  855. {
  856.         m_pListener->m_pStats = this;
  857.  
  858.         CCryAction::GetCryAction()->GetIGameplayRecorder()->RegisterListener(this);
  859.         CCryAction::GetCryAction()->GetILevelSystem()->AddListener(this);
  860.         CCryAction::GetCryAction()->RegisterListener(this, "GameStats", FRAMEWORKLISTENERPRIORITY_DEFAULT);
  861.         m_config = CCryAction::GetCryAction()->GetGameStatsConfig();
  862.         if (!gEnv->bServer)//we may not have a chance to do that
  863.                 Init();
  864.  
  865.         gEnv->pNetwork->AddHostMigrationEventListener(this, "CGameStats", ELPT_PostEngine);
  866. }
  867.  
  868. CGameStats::~CGameStats()
  869. {
  870.         gEnv->pNetwork->RemoveHostMigrationEventListener(this);
  871.  
  872.         if (m_serverReport)
  873.                 m_serverReport->StopReporting();
  874.  
  875.         delete m_pListener;
  876.         m_pListener = 0;
  877.  
  878.         CCryAction::GetCryAction()->GetIGameplayRecorder()->UnregisterListener(this);
  879.         CCryAction::GetCryAction()->GetILevelSystem()->RemoveListener(this);
  880.         CCryAction::GetCryAction()->UnregisterListener(this);
  881. }
  882.  
  883. /*static const struct
  884.    {
  885.    EGameplayEvent key;
  886.    const char*    name;
  887.    }
  888.    gEventNames[]={{eGE_GameReset,                                               "eGE_GameReset"},
  889.               {eGE_GameStarted,                                         "eGE_GameStarted"},
  890.               {eGE_GameEnd,                                                             "eGE_GameEnd"},
  891.               {eGE_SuddenDeath,                                         "eGE_SuddenDeath"},
  892.               {eGE_RoundEnd,                                                    "eGE_RoundEnd"},
  893.               {eGE_Connected,                                                   "eGE_Connected"},
  894.               {eGE_Disconnected,                                        "eGE_Disconnected"},
  895.               {eGE_Renamed,                                                             "eGE_Renamed"},
  896.               {eGE_ChangedTeam,                                         "eGE_ChangedTeam"},
  897.               {eGE_Died,                                                                        "eGE_Died"},
  898.               {eGE_Scored,                                                              "eGE_Scored"},
  899.               {eGE_Currency,                                                    "eGE_Currency"},
  900.               {eGE_Rank,                                                                        "eGE_Rank"},
  901.               {eGE_Spectator,                                                   "eGE_Spectator"},
  902.               {eGE_ScoreReset,                                          "eGE_ScoreReset"},
  903.  
  904.               {eGE_AttachedAccessory,                   "eGE_AttachedAccessory"},
  905.  
  906.               {eGE_ZoomedIn,                                                    "eGE_ZoomedIn"},
  907.               {eGE_ZoomedOut,                                                   "eGE_ZoomedOut"},
  908.  
  909.               {eGE_Kill,                                                                        "eGE_Kill"},
  910.               {eGE_Death,                                                                       "eGE_Death"},
  911.               {eGE_Revive,                                                              "eGE_Revive"},
  912.  
  913.               {eGE_SuitModeChanged,                             "eGE_SuitModeChanged"},
  914.  
  915.               {eGE_Hit,                                                                         "eGE_Hit"},
  916.               {eGE_Damage,                                                              "eGE_Damage"},
  917.  
  918.               {eGE_WeaponHit,                                                   "eGE_WeaponHit"},
  919.               {eGE_WeaponReload,                                        "eGE_WeaponReload"},
  920.               {eGE_WeaponShot,                                          "eGE_WeaponShot"},
  921.               {eGE_WeaponMelee,                                         "eGE_WeaponMelee"},
  922.               {eGE_WeaponFireModeChanged,       "eGE_WeaponFireModeChanged"},
  923.  
  924.               {eGE_ItemSelected,                                        "eGE_ItemSelected"},
  925.               {eGE_ItemPickedUp,                                        "eGE_ItemPickedUp"},
  926.               {eGE_ItemDropped,                                         "eGE_ItemDropped"},
  927.               {eGE_ItemBought,                                          "eGE_ItemBought"},
  928.  
  929.               {eGE_EnteredVehicle,                              "eGE_EnteredVehicle"},
  930.               {eGE_LeftVehicle,                                         "eGE_LeftVehicle"}};
  931.  
  932.    static const unsigned int gEventNamesNum = CRY_ARRAY_COUNT(gEventNames);*/
  933.  
  934. void CGameStats::OnGameplayEvent(IEntity* pEntity, const GameplayEvent& event)
  935. {
  936.         /*      for(int i=0;i<gEventNamesNum;++i)
  937.            {
  938.             if(gEventNames[i].key == event.event)
  939.             {
  940.               CryLog("GameStats : Event %s",gEventNames[i].name);
  941.             }
  942.            }*/
  943.  
  944.         int e_id = pEntity ? (int) pEntity->GetId() : 0;
  945.         switch (event.event)
  946.         {
  947.         case eGE_GameStarted:
  948.                 StartGame(event.value != 0);
  949.                 break;
  950.         case eGE_GameEnd:
  951.                 EndGame(event.value != 0);
  952.                 break;
  953.         case eGE_SuddenDeath:
  954.                 SuddenDeath(event.value != 0);
  955.                 break;
  956.         case eGE_RoundEnd:
  957.                 EndRound(event.value != 0, atoi(event.description));
  958.                 break;
  959.         case eGE_Renamed:
  960.                 SetName(e_id, event.description);
  961.                 break;
  962.         case eGE_Scored:
  963.                 SetScore(e_id, event.description, (int)event.value);
  964.                 break;
  965.         case eGE_Kill:
  966.                 OnKill(e_id, (EntityId*)event.extra);
  967.                 if (pEntity)
  968.                         ProcessPlayerStat(pEntity, event);
  969.                 break;
  970.         case eGE_Death:
  971.                 OnDeath(e_id, (int)(TRUNCATE_PTR)event.extra);
  972.                 if (pEntity)
  973.                         ProcessPlayerStat(pEntity, event);
  974.                 break;
  975.         case eGE_WeaponShot:
  976.         case eGE_WeaponHit:
  977.         case eGE_SuitModeChanged:
  978.         case eGE_WeaponMelee:
  979.         case eGE_LeftVehicle:
  980.         case eGE_EnteredVehicle:
  981.         case eGE_ItemSelected:
  982.         case eGE_WeaponReload:
  983.         case eGE_Damage:
  984.         case eGE_Revive:
  985.         case eGE_WeaponFireModeChanged:
  986.         case eGE_ZoomedIn:
  987.         case eGE_ZoomedOut:
  988.                 if (pEntity)
  989.                         ProcessPlayerStat(pEntity, event);
  990.                 break;
  991.         case eGE_Connected:
  992.                 {
  993.                         bool restored = event.value != 0.0f;
  994.  
  995.                         struct SExtraData
  996.                         {
  997.                                 int status[2];
  998.                         };
  999.  
  1000.                         SExtraData* pExtra = static_cast<SExtraData*>(event.extra);
  1001.                         NewPlayer(e_id, pExtra->status[0], pExtra->status[1] != 0, restored);
  1002.                 }
  1003.                 break;
  1004.         case eGE_ChangedTeam:
  1005.                 SetTeam(e_id, (int)event.value);
  1006.                 break;
  1007.         case eGE_Spectator:
  1008.                 SetSpectator(e_id, (int)event.value);
  1009.                 if (pEntity)
  1010.                         ProcessPlayerStat(pEntity, event);
  1011.                 break;
  1012.         case eGE_Disconnected:
  1013.                 RemovePlayer(e_id, event.value != 0);
  1014.                 break;
  1015.         case eGE_ScoreReset:
  1016.                 ResetScore(e_id);
  1017.                 break;
  1018.         case eGE_Rank:
  1019.                 SetRank(e_id, (int)event.value);
  1020.                 break;
  1021.         case eGE_GameReset:
  1022.                 GameReset();
  1023.                 break;
  1024.         default:
  1025.                 break;
  1026.         }
  1027. }
  1028.  
  1029. void CGameStats::OnActionEvent(const SActionEvent& event)
  1030. {
  1031.         if (event.m_event == eAE_disconnected && !gEnv->bServer)//on disconnect submit our stats
  1032.         {
  1033.                 if (m_statsTrack && m_playing)
  1034.                 {
  1035.                         /*for(PlayerStatsMap::iterator it = m_playerMap.begin(), eit = m_playerMap.end();it!=eit; ++it)
  1036.                            {
  1037.                            SubmitPlayerStats(it->second);
  1038.                            m_statsTrack->PlayerDisconnected(it->second.id);
  1039.                            it->second.stats = new SPlayerStats();
  1040.                            }*/
  1041.                         //clients are not submitting any date if disconnected occasionally
  1042.                         m_statsTrack->Reset();
  1043.                 }
  1044.         }
  1045. }
  1046.  
  1047. void CGameStats::OnLevelNotFound(const char* levelName)
  1048. {
  1049.         m_startReportNeeded = false;
  1050. }
  1051.  
  1052. void CGameStats::OnLoadingStart(ILevelInfo* pLevel)
  1053. {
  1054.         if (gEnv->bServer)
  1055.         {
  1056.                 ReportGame();
  1057.  
  1058.                 if (pLevel && m_serverReport)
  1059.                 {
  1060.                         if (*(pLevel->GetDisplayName()))
  1061.                                 m_serverReport->SetServerValue("mapname", pLevel->GetDisplayName());
  1062.                         else
  1063.                                 m_serverReport->SetServerValue("mapname", pLevel->GetName());
  1064.                 }
  1065.  
  1066.                 if (m_startReportNeeded)
  1067.                 {
  1068.                         if (m_serverReport && !m_reportStarted)
  1069.                         {
  1070.                                 m_serverReport->StartReporting(gEnv->pGameFramework->GetServerNetNub(), m_pListener);
  1071.                                 m_reportStarted = true;
  1072.                         }
  1073.                         m_startReportNeeded = false;
  1074.                 }
  1075.  
  1076.                 if (m_serverReport)
  1077.                 {
  1078.                         m_serverReport->Update();
  1079.                         m_stateChanged = false;
  1080.                 }
  1081.         }
  1082. }
  1083.  
  1084. void CGameStats::OnLoadingLevelEntitiesStart(ILevelInfo* pLevel)
  1085. {
  1086. }
  1087.  
  1088. void CGameStats::OnLoadingComplete(ILevelInfo* pLevel)
  1089. {
  1090. }
  1091.  
  1092. void CGameStats::OnLoadingError(ILevelInfo* pLevel, const char* error)
  1093. {
  1094.         m_startReportNeeded = false;
  1095. }
  1096.  
  1097. void CGameStats::OnLoadingProgress(ILevelInfo* pLevel, int progressAmount)
  1098. {
  1099. }
  1100.  
  1101. void CGameStats::OnUnloadComplete(ILevelInfo* pLevel)
  1102. {
  1103. }
  1104.  
  1105. void CGameStats::OnKill(int plrId, EntityId* extra)
  1106. {
  1107.  
  1108. }
  1109.  
  1110. void CGameStats::OnDeath(int plrId, int shooterId)
  1111. {
  1112. }
  1113.  
  1114. void CGameStats::StartSession()
  1115. {
  1116.         m_roundStats.reset(new SRoundStats());
  1117.  
  1118.         m_startReportNeeded = true;
  1119.         if (!m_statsTrack || !m_serverReport)
  1120.                 Init();
  1121.         if (!m_reportStarted && !m_startReportNeeded)//OnLoadingStart was not able to start report
  1122.                 m_startReportNeeded = true;
  1123.         ReportSession();
  1124. }
  1125.  
  1126. void CGameStats::EndSession()
  1127. {
  1128.         m_startReportNeeded = false;
  1129.         m_reportStarted = false;
  1130.         if (m_serverReport)
  1131.         {
  1132.                 m_serverReport->StopReporting();
  1133.         }
  1134. }
  1135.  
  1136. void CGameStats::StartGame(bool server)
  1137. {
  1138.         if (!server && gEnv->bServer)//we simply ignore client events on server
  1139.                 return;
  1140.  
  1141.         if (IGameRulesSystem* pGR = gEnv->pGameFramework->GetIGameRulesSystem())
  1142.         {
  1143.                 IGameRules* pR = pGR->GetCurrentGameRules();
  1144.                 if (pR)
  1145.                 {
  1146.                         IEntityScriptComponent* pScriptProxy = static_cast<IEntityScriptComponent*>(pR->GetEntity()->GetProxy(ENTITY_PROXY_SCRIPT));
  1147.                         if (pScriptProxy)
  1148.                         {
  1149.                                 string gameState = pScriptProxy->GetState();
  1150.                                 if (gameState == "InGame")
  1151.                                 {
  1152.                                         m_playing = true;
  1153.                                         m_gameMode = pR->GetEntity()->GetClass()->GetName();
  1154.                                 }
  1155.                         }
  1156.                 }
  1157.         }
  1158.  
  1159.         if (!m_statsTrack || !m_serverReport)
  1160.                 Init();
  1161.  
  1162.         if (m_serverReport)
  1163.         {
  1164.                 ReportGame();
  1165.                 m_serverReport->Update();
  1166.         }
  1167.  
  1168.         if (m_playing)
  1169.         {
  1170.                 if (ILevelInfo* pLevelInfo = gEnv->pGameFramework->GetILevelSystem()->GetCurrentLevel())
  1171.                 {
  1172.                         m_mapName = pLevelInfo->GetName();//we only need pure level name here
  1173.                         const char* p = strrchr(m_mapName.c_str(), '/');
  1174.                         if (p != 0 && strlen(p) > 1)
  1175.                         {
  1176.                                 m_mapName = p + 1;
  1177.                                 char* pStr = const_cast<char*>(m_mapName.data());
  1178.                                 pStr[0] = toupper(m_mapName[0]);
  1179.                                 for (int i = 1; i < m_mapName.size(); ++i)
  1180.                                         pStr[i] = tolower(m_mapName[i]);
  1181.                         }
  1182.                 }
  1183.         }
  1184.  
  1185.         if (m_statsTrack && m_playing && gEnv->bServer)
  1186.                 m_statsTrack->StartGame();
  1187.  
  1188.         if (gEnv->bServer && m_playing)
  1189.         {
  1190.                 m_roundStart = gEnv->pTimer->GetFrameStartTime();
  1191.                 m_lastPosUpdate = 0.0f;
  1192.                 ResetStats();
  1193.                 m_roundStats->Start(m_mapName, m_roundStart);
  1194.         }
  1195. }
  1196.  
  1197. void CGameStats::ResetStats()
  1198. {
  1199.         SGetTime time(m_roundStart);
  1200.         for (PlayerStatsMap::iterator it = m_playerMap.begin(), eit = m_playerMap.end(); it != eit; ++it)
  1201.         {
  1202.                 it->second.stats.clear();
  1203.                 it->second.stats.push_back(new SPlayerStats(time));
  1204.                 if (IActor* pActor = m_pGameFramework->GetIActorSystem()->GetActor(it->first))
  1205.                 {
  1206.                         if (IItem* pI = pActor->GetCurrentItem())
  1207.                         {
  1208.                                 it->second.stats.back()->SelectWeapon(pI->GetEntity()->GetClass()->GetName(), time);
  1209.                         }
  1210.                 }
  1211.         }
  1212. }
  1213.  
  1214. void CGameStats::SaveStats()
  1215. {
  1216.         if (m_roundStats->m_round)
  1217.         {
  1218.                 SGetTime time(m_roundStart);
  1219.                 CryFixedStringT<128> timeStr;
  1220.                 time_t ltime;
  1221.                 ::time(&ltime);
  1222.                 tm* today = localtime(&ltime);
  1223.                 strftime(timeStr.m_str, timeStr.MAX_SIZE, "%y-%m-%d_%H%M%S", today);
  1224.  
  1225.                 XmlNodeRef root = gEnv->pSystem->CreateXmlNode("round");
  1226.                 root->setAttr("round", m_roundStats->m_round);
  1227.                 SRoundStats::SaveToXML(root, "", *m_roundStats.get());
  1228.                 for (PlayerStatsMap::iterator it = m_playerMap.begin(), eit = m_playerMap.end(); it != eit; ++it)
  1229.                 {
  1230.                         for (SPlayerInfo::TStatsVct::iterator si = it->second.stats.begin(); si < it->second.stats.end(); ++si)
  1231.                         {
  1232.                                 it->second.stats.back()->End(time);
  1233.  
  1234.                                 XmlNodeRef plr = gEnv->pSystem->CreateXmlNode("player");
  1235.                                 if (IEntity* p = gEnv->pEntitySystem->GetEntity(it->first))
  1236.                                 {
  1237.                                         plr->setAttr("id", p->GetId());
  1238.                                         if (IActor* pAct = m_pGameFramework->GetIActorSystem()->GetActor(p->GetId()))
  1239.                                         {
  1240.                                                 int profile = m_pGameFramework->GetNetChannel(pAct->GetChannelId())->GetProfileId();
  1241.                                                 plr->setAttr("profile", profile);
  1242.                                         }
  1243.                                 }
  1244.                                 plr->setAttr("name", it->second.name);
  1245.                                 plr->setAttr("team", it->second.team);
  1246.                                 plr->setAttr("spectator", it->second.spectator);
  1247.  
  1248.                                 SPlayerStats::SaveToXML(plr, "", *(si->get()));
  1249.                                 root->addChild(plr);
  1250.                         }
  1251.                 }
  1252.                 root->saveToFile(string().Format("%s/StatsLogs/Round_%s.xml", gEnv->pCryPak->GetAlias("%USER%"), timeStr.c_str()));
  1253.         }
  1254. }
  1255.  
  1256. void CGameStats::EndGame(bool server)
  1257. {
  1258.         if (!server && gEnv->bServer) //we simply ignore client events on server
  1259.                 return;
  1260.  
  1261.         if (m_statsTrack && m_playing)
  1262.         {
  1263.                 SGetTime time(m_roundStart);
  1264.  
  1265.                 if (gEnv->bServer)
  1266.                         SubmitServerStats();
  1267.                 for (PlayerStatsMap::iterator it = m_playerMap.begin(), eit = m_playerMap.end(); it != eit; ++it)
  1268.                 {
  1269.                         SubmitPlayerStats(it->second, gEnv->bServer, it->first == CCryAction::GetCryAction()->GetClientActorId());
  1270.                         it->second.stats.push_back(new SPlayerStats(time));
  1271.                 }
  1272.                 m_statsTrack->EndGame();
  1273.         }
  1274.  
  1275.         m_playing = false;
  1276.  
  1277.         ReportGame();
  1278.  
  1279.         if (m_serverReport)
  1280.                 m_serverReport->Update();
  1281. }
  1282.  
  1283. void CGameStats::NewPlayer(int plr, int team, bool spectator, bool restored)
  1284. {
  1285.         SGetTime time(m_roundStart);
  1286.  
  1287.         if (DEBUG_VERBOSE)
  1288.                 CryLog("CGameStats::NewPlayer %08X %s", plr, restored ? "restored" : "");
  1289.         PlayerStatsMap::iterator it = m_playerMap.find(plr);
  1290.         if (it == m_playerMap.end())
  1291.         {
  1292.                 it = m_playerMap.insert(std::make_pair(plr, SPlayerInfo())).first;
  1293.         }
  1294.         else
  1295.         {
  1296.                 if (DEBUG_VERBOSE)
  1297.                         CryLog("CGameStats::NewPlayer restored not found");
  1298.         }
  1299.  
  1300.         if (m_statsTrack)
  1301.         {
  1302.                 if (restored)
  1303.                         m_statsTrack->PlayerConnected(it->second.id);
  1304.                 else
  1305.                         it->second.id = m_statsTrack->AddPlayer(plr);
  1306.         }
  1307.         else
  1308.                 it->second.id = -1;
  1309.         if (!it->second.stats.empty())
  1310.                 it->second.stats.back()->End(time);
  1311.         it->second.stats.push_back(new SPlayerStats(time));
  1312.  
  1313.         if (IActor* pActor = m_pGameFramework->GetIActorSystem()->GetActor(plr))
  1314.         {
  1315.                 if (IItem* pI = pActor->GetCurrentItem())
  1316.                 {
  1317.                         it->second.stats.back()->SelectWeapon(pI->GetEntity()->GetClass()->GetName(), time);
  1318.                 }
  1319.         }
  1320.  
  1321.         if (!restored)
  1322.         {
  1323.                 it->second.team = team;
  1324.                 it->second.rank = 1;
  1325.                 it->second.spectator = spectator;
  1326.                 it->second.name = gEnv->pEntitySystem->GetEntity(plr)->GetName();
  1327.         }
  1328.  
  1329.         m_stateChanged = true;
  1330.  
  1331.         Report();
  1332.  
  1333.         if (m_serverReport && m_playerMap.size() == gEnv->pConsole->GetCVar("sv_maxplayers")->GetIVal())//if server is full, report now
  1334.         {
  1335.                 m_serverReport->Update();
  1336.                 m_stateChanged = false;
  1337.         }
  1338. }
  1339.  
  1340. void CGameStats::EndRound(bool server, int winner)
  1341. {
  1342.         if (!gEnv->bServer || !server)
  1343.                 return;
  1344.         m_roundStats->End(winner, gEnv->pTimer->GetFrameStartTime());
  1345.  
  1346.         if (CCryActionCVars::Get().g_statisticsMode == 1)
  1347.                 SaveStats();
  1348. }
  1349.  
  1350. void CGameStats::SuddenDeath(bool server)
  1351. {
  1352.  
  1353. }
  1354.  
  1355. void CGameStats::RemovePlayer(int plr, bool keep)
  1356. {
  1357.         SGetTime time(m_roundStart);
  1358.  
  1359.         if (DEBUG_VERBOSE)
  1360.                 CryLog("CGameStats::RemovePlayer %08X %s", plr, keep ? "keep" : "");
  1361.         PlayerStatsMap::iterator it = m_playerMap.find(plr);
  1362.  
  1363.         if (it == m_playerMap.end())
  1364.                 return;
  1365.  
  1366.         if (m_statsTrack && m_playing)
  1367.         {
  1368.                 SubmitPlayerStats(it->second, gEnv->bServer, false);
  1369.                 m_statsTrack->PlayerDisconnected(it->second.id);
  1370.         }
  1371.         it->second.stats.push_back(new SPlayerStats(time));
  1372.  
  1373.         if (!keep)
  1374.         {
  1375.                 m_stateChanged = true;
  1376.  
  1377.                 int num_players = m_playerMap.size();
  1378.  
  1379.                 m_playerMap.erase(it);
  1380.  
  1381.                 Report();
  1382.  
  1383.                 if (m_serverReport && num_players == gEnv->pConsole->GetCVar("sv_maxplayers")->GetIVal())//if server was full, report now
  1384.                 {
  1385.                         m_serverReport->Update();
  1386.                         m_stateChanged = false;
  1387.                 }
  1388.         }
  1389. }
  1390.  
  1391. void CGameStats::CreateNewLifeStats(int plr)
  1392. {
  1393.         SGetTime time(m_roundStart);
  1394.  
  1395.         PlayerStatsMap::iterator it = m_playerMap.find(plr);
  1396.         if (it == m_playerMap.end())
  1397.                 return;
  1398.  
  1399.         CRY_ASSERT(!it->second.stats.empty());
  1400.  
  1401.         if (it->second.stats.back()->m_deaths < 1)
  1402.                 return;//initial resp
  1403.         it->second.stats.back()->End(time);
  1404.  
  1405.         it->second.stats.push_back(new SPlayerStats(time));
  1406. }
  1407.  
  1408. void CGameStats::ResetScore(int plr)
  1409. {
  1410.         int i = 0;
  1411.         for (PlayerStatsMap::iterator it = m_playerMap.begin(), eit = m_playerMap.end(); it != eit; ++it, ++i)
  1412.         {
  1413.                 if (it->first != plr)
  1414.                         continue;
  1415.                 for (std::map<string, int>::iterator sit = it->second.scores.begin(); sit != it->second.scores.end(); ++sit)
  1416.                 {
  1417.                         sit->second = 0;
  1418.                         if (m_serverReport)
  1419.                                 m_serverReport->SetPlayerValue(i, sit->first, "0");
  1420.                 }
  1421.                 break;
  1422.         }
  1423.         m_stateChanged = true;
  1424. }
  1425.  
  1426. void CGameStats::SetName(int plr, const char* name)
  1427. {
  1428.         PlayerStatsMap::iterator it = m_playerMap.find(plr);
  1429.  
  1430.         if (it == m_playerMap.end())
  1431.                 return;
  1432.  
  1433.         it->second.name = name;
  1434.  
  1435.         m_stateChanged = true;
  1436. }
  1437.  
  1438. void CGameStats::SetScore(int plr, const char* desc, int value)
  1439. {
  1440.         PlayerStatsMap::iterator it = m_playerMap.find(plr);
  1441.  
  1442.         if (it != m_playerMap.end())
  1443.         {
  1444.                 it->second.scores[desc] = value;
  1445.                 m_stateChanged = true;
  1446.         }
  1447. }
  1448.  
  1449. void CGameStats::SetTeam(int plr, int value)
  1450. {
  1451.         PlayerStatsMap::iterator it = m_playerMap.find(plr);
  1452.  
  1453.         if (it != m_playerMap.end())
  1454.         {
  1455.                 it->second.team = value;
  1456.                 m_stateChanged = true;
  1457.         }
  1458.  
  1459. }
  1460.  
  1461. void CGameStats::SetRank(int plr, int value)
  1462. {
  1463.         PlayerStatsMap::iterator it = m_playerMap.find(plr);
  1464.  
  1465.         if (it != m_playerMap.end())
  1466.         {
  1467.                 it->second.rank = value;
  1468.                 m_stateChanged = true;
  1469.         }
  1470. }
  1471.  
  1472. void CGameStats::SetSpectator(int plr, int value)
  1473. {
  1474.         PlayerStatsMap::iterator it = m_playerMap.find(plr);
  1475.  
  1476.         if (it != m_playerMap.end())
  1477.         {
  1478.                 it->second.spectator = value != 0;
  1479.         }
  1480.         m_stateChanged = true;
  1481. }
  1482.  
  1483. void CGameStats::GameReset()
  1484. {
  1485.         m_playing = false;
  1486.         m_playerMap.clear();
  1487.         m_teamMap.clear();
  1488.  
  1489.         if (m_statsTrack)
  1490.                 m_statsTrack->Reset();
  1491.         m_stateChanged = true;
  1492. }
  1493.  
  1494. void CGameStats::Connected()
  1495. {
  1496.         //should not be called
  1497.         if (gEnv->IsClient() && !gEnv->bServer)//pure clients
  1498.         {
  1499.                 if (IGameRulesSystem* pGR = gEnv->pGameFramework->GetIGameRulesSystem())
  1500.                 {
  1501.                         IGameRules* pR = pGR->GetCurrentGameRules();
  1502.                         if (pR)
  1503.                         {
  1504.                                 IEntityScriptComponent* pScriptProxy = static_cast<IEntityScriptComponent*>(pR->GetEntity()->GetProxy(ENTITY_PROXY_SCRIPT));
  1505.                                 if (pScriptProxy)
  1506.                                 {
  1507.                                         string gameState = pScriptProxy->GetState();
  1508.                                         if (gameState == "InGame")
  1509.                                         {
  1510.                                                 m_playing = true;
  1511.                                                 m_gameMode = pR->GetEntity()->GetClass()->GetName();
  1512.                                         }
  1513.                                 }
  1514.                         }
  1515.                 }
  1516.                 if (m_statsTrack)
  1517.                         m_statsTrack->Reset();
  1518.         }
  1519. }
  1520.  
  1521. void CGameStats::Update()
  1522. {
  1523.         //iterate players map and get positions
  1524.         SGetTime time(m_roundStart);
  1525.         CTimeValue gametime = time;
  1526.  
  1527.         if (gametime > m_lastUpdate + UPDATE_INTERVAL)
  1528.         {
  1529.                 m_lastUpdate = gametime;
  1530.                 m_lastReport = gametime;
  1531.                 Report();
  1532.  
  1533.                 if (m_stateChanged)
  1534.                 {
  1535.                         if (m_serverReport)
  1536.                                 m_serverReport->Update();
  1537.                         m_stateChanged = false;
  1538.                 }
  1539.         }
  1540.         else
  1541.         {
  1542.                 if (gametime > m_lastReport + REPORT_INTERVAL)
  1543.                 {
  1544.                         Report();
  1545.                         m_lastReport = gametime;
  1546.                 }
  1547.         }
  1548. }
  1549.  
  1550. void CGameStats::Dump()
  1551. {
  1552.         SGetTime time(m_roundStart);
  1553.         //dump some info for debug purposes
  1554.         int lifeNo = 0;
  1555.  
  1556.         if (gEnv->bServer)
  1557.         {
  1558.                 for (PlayerStatsMap::const_iterator it = m_playerMap.begin(), eit = m_playerMap.end(); it != eit; ++it)
  1559.                 {
  1560.                         CryLog("$2Stats for player %s", it->second.name.c_str());
  1561.                         for (SPlayerInfo::TStatsVct::const_iterator si = it->second.stats.begin(); si < it->second.stats.end(); ++si)
  1562.                         {
  1563.                                 CryLog("Life no: %d", lifeNo);
  1564.                                 si->get()->Dump(time);
  1565.                                 ++lifeNo;
  1566.                         }
  1567.                         ;
  1568.                 }
  1569.         }
  1570.         else
  1571.         {
  1572.                 IActor* pActor = CCryAction::GetCryAction()->GetClientActor();
  1573.                 if (!pActor)
  1574.                         return;
  1575.  
  1576.                 PlayerStatsMap::iterator it = m_playerMap.find(pActor->GetEntityId());
  1577.                 if (it == m_playerMap.end())
  1578.                         return;
  1579.  
  1580.                 for (SPlayerInfo::TStatsVct::iterator si = it->second.stats.begin(); si < it->second.stats.end(); ++si)
  1581.                 {
  1582.                         CryLog("Life no: %d", lifeNo);
  1583.                         si->get()->Dump(time);
  1584.                         ++lifeNo;
  1585.                 }
  1586.         }
  1587. }
  1588.  
  1589. void CGameStats::ReportSession()
  1590. {
  1591.         if (!m_serverReport)
  1592.                 return;
  1593.  
  1594.         string name;
  1595.         ICVar* pName = gEnv->pConsole->GetCVar("sv_servername");
  1596.         if (pName)
  1597.                 name = pName->GetString();
  1598.         if (name.empty())
  1599.                 name = gEnv->pNetwork->GetHostName();
  1600.  
  1601.         CCryAction::GetCryAction()->OnActionEvent(SActionEvent(eAE_serverName, 0, name));
  1602.  
  1603.         if (gEnv->pConsole->GetCVar("sv_lanonly")->GetIVal())//we're on LAN so report our name
  1604.         {
  1605.                 string ip = gEnv->pNetwork->GetHostName();
  1606.                 ip += ":";
  1607.                 ip += gEnv->pConsole->GetCVar("sv_port")->GetString();
  1608.                 CCryAction::GetCryAction()->OnActionEvent(SActionEvent(eAE_serverIp, 0, ip));
  1609.         }
  1610.  
  1611.         if (m_serverReport)
  1612.         {
  1613.                 m_serverReport->SetServerValue("hostname", name);
  1614.                 m_serverReport->SetServerValue("hostport", gEnv->pConsole->GetCVar("sv_port")->GetString());
  1615.  
  1616.                 char strProductVersion[256];
  1617.                 gEnv->pSystem->GetProductVersion().ToString(strProductVersion);
  1618.                 m_serverReport->SetServerValue("gamever", strProductVersion);
  1619.                 m_serverReport->SetServerValue("maxplayers", gEnv->pConsole->GetCVar("sv_maxplayers")->GetString());
  1620.                 ICVar* pFF = gEnv->pConsole->GetCVar("g_friendlyfireratio");
  1621.                 m_serverReport->SetServerValue("friendlyfire", pFF ? ((pFF->GetFVal() != 0) ? "1" : "0") : 0);
  1622.                 m_serverReport->SetServerValue("dx10", CCryAction::GetCryAction()->GetGameContext()->HasContextFlag(eGSF_ImmersiveMultiplayer) ? "1" : "0");
  1623.         }
  1624.  
  1625.         ReportGame();
  1626.  
  1627.         if ((CCryAction::GetCryAction()->GetILevelSystem()->IsLevelLoaded() && CCryAction::GetCryAction()->IsGameStarted()) || m_startReportNeeded)//otherwise, OnLoadingStart will report it
  1628.         {
  1629.                 if (m_serverReport && !m_reportStarted)//report now
  1630.                 {
  1631.                         m_serverReport->StartReporting(gEnv->pGameFramework->GetServerNetNub(), m_pListener);
  1632.                         m_reportStarted = true;
  1633.                 }
  1634.                 m_startReportNeeded = false;
  1635.         }
  1636.  
  1637.         m_startReportNeeded = !m_reportStarted;
  1638. }
  1639.  
  1640. void CGameStats::ReportGame()
  1641. {
  1642.         string mode;
  1643.         if (IEntity* pGRE = gEnv->pGameFramework->GetIGameRulesSystem()->GetCurrentGameRulesEntity())
  1644.         {
  1645.                 mode = pGRE->GetClass()->GetName();
  1646.         }
  1647.         else
  1648.                 mode = gEnv->pConsole->GetCVar("sv_gamerules")->GetString();
  1649.  
  1650.         string name;
  1651.         ICVar* pName = gEnv->pConsole->GetCVar("sv_servername");
  1652.         if (pName)
  1653.                 name = pName->GetString();
  1654.  
  1655.         string timelimit;
  1656.         static ICVar* pVar = gEnv->pConsole->GetCVar("g_timelimit");
  1657.         timelimit = pVar ? pVar->GetString() : "0";
  1658.  
  1659.         if (m_serverReport)
  1660.         {
  1661.                 string levelname;
  1662.                 if (GetLevelName(levelname))
  1663.                         m_serverReport->SetServerValue("mapname", levelname.c_str());
  1664.                 m_serverReport->SetServerValue("gametype", mode);
  1665.  
  1666.                 m_serverReport->SetServerValue("timelimit", pVar ? pVar->GetString() : "0");
  1667.         }
  1668.  
  1669.         Report();
  1670. }
  1671.  
  1672. void CGameStats::Report()
  1673. {
  1674.         if (!m_serverReport)
  1675.                 return;
  1676.  
  1677.         int playerCount = m_playerMap.size();
  1678.         if (CGameServerNub* pServerNub = CCryAction::GetCryAction()->GetGameServerNub())
  1679.                 playerCount = pServerNub->GetPlayerCount();
  1680.  
  1681.         //All server reporting is done here
  1682.         m_serverReport->SetReportParams(playerCount, m_teamMap.size());
  1683.         m_serverReport->SetServerValue("gamemode", m_playing ? "game" : "pre-game");
  1684.  
  1685.         CryFixedStringT<32> timeleft("-");
  1686.         if (IGameRulesSystem* pGR = gEnv->pGameFramework->GetIGameRulesSystem())
  1687.         {
  1688.                 IGameRules* pR = pGR->GetCurrentGameRules();
  1689.                 if (pR && pR->IsTimeLimited() && m_playing)
  1690.                 {
  1691.                         timeleft.Format("%.0f", pR->GetRemainingGameTime());
  1692.                 }
  1693.         }
  1694.  
  1695.         m_serverReport->SetServerValue("timeleft", timeleft);
  1696.  
  1697.         CryFixedStringT<256> tempStr;
  1698.  
  1699.         m_serverReport->SetServerValue("numplayers", tempStr.Format("%d", playerCount));
  1700.  
  1701.         int i = 0;
  1702.  
  1703.         string mode;
  1704.         for (PlayerStatsMap::const_iterator it = m_playerMap.begin(); it != m_playerMap.end(); ++it)
  1705.         {
  1706.                 static string value;
  1707.                 m_serverReport->SetPlayerValue(i, "player", it->second.name);
  1708.                 value.Format("%d", it->second.rank);
  1709.                 m_serverReport->SetPlayerValue(i, "rank", value);
  1710.                 value.Format("%d", it->second.team ? it->second.team : (it->second.spectator ? 0 : 1));
  1711.                 m_serverReport->SetPlayerValue(i, "team", value);
  1712.                 for (std::map<string, int>::const_iterator sit = it->second.scores.begin(); sit != it->second.scores.end(); ++sit)
  1713.                         m_serverReport->SetPlayerValue(i, sit->first, tempStr.Format("%d", sit->second));
  1714.                 ++i;
  1715.         }
  1716.         while (i < playerCount)
  1717.         {
  1718.                 m_serverReport->SetPlayerValue(i, "player", "<connecting>");
  1719.                 ++i;
  1720.         }
  1721. }
  1722.  
  1723. void CGameStats::ProcessPlayerStat(IEntity* pEntity, const GameplayEvent& event)
  1724. {
  1725.         if (CCryActionCVars::Get().g_statisticsMode != 1)
  1726.                 return;
  1727.  
  1728.         SGetTime time(m_roundStart);
  1729.  
  1730.         const int e_id = pEntity->GetId();
  1731.         PlayerStatsMap::iterator it = m_playerMap.find(e_id);
  1732.         if (it == m_playerMap.end())
  1733.                 return;
  1734.         SPlayerStats& plr = *(it->second.stats.back());
  1735.         if (gEnv->bServer)
  1736.         {
  1737.                 switch (event.event)
  1738.                 {
  1739.                 case eGE_Kill:
  1740.                         plr.m_kills++;
  1741.                         {
  1742.                                 EntityId* params = (EntityId*)event.extra;
  1743.                                 IEntity* weapon = gEnv->pEntitySystem->GetEntity(params[0]);
  1744.                                 string wname = event.description ? event.description : "";
  1745.                                 if (weapon)
  1746.                                         wname = weapon->GetClass()->GetName();
  1747.                                 plr.PlayerEvent(time, "kill", wname, params[1], pEntity->GetWorldPos());
  1748.                         }
  1749.                         break;
  1750.                 case eGE_Death:
  1751.                         plr.m_deaths++;
  1752.                         plr.m_inVehicle = false;
  1753.                         plr.PlayerEvent(time, "death", "", 0, pEntity->GetWorldPos());
  1754.                         break;
  1755.                 case eGE_Revive:
  1756.                         plr.m_revives++;
  1757.                         plr.PlayerEvent(time, "spawn", "", int(event.value), pEntity->GetWorldPos());
  1758.                         CreateNewLifeStats(e_id);
  1759.                         break;
  1760.                 case eGE_WeaponMelee:
  1761.                         {
  1762.                                 plr.m_melee++;
  1763.                                 plr.PlayerEvent(time, "weapon_melee");
  1764.                         }
  1765.                         break;
  1766.                 case eGE_EnteredVehicle:
  1767.                         plr.m_inVehicle = true;
  1768.                         break;
  1769.                 case eGE_LeftVehicle:
  1770.                         plr.m_inVehicle = false;
  1771.                         break;
  1772.                 }
  1773.         }
  1774.  
  1775.         static string vehicle_name;
  1776.  
  1777.         switch (event.event)
  1778.         {
  1779.         case eGE_WeaponShot:
  1780.                 if (!plr.m_inVehicle)
  1781.                 {
  1782.                         if (event.description == NULL)
  1783.                                 break;
  1784.  
  1785.                         if (strstr(event.description, "bullet") != 0 || strcmp(event.description, "shotgunshell") == 0 || strcmp(event.description, "alienmount_acmo") == 0)//only counting these
  1786.                                 plr.m_shots += int(event.value);
  1787.                 }
  1788.                 plr.WeaponShot(int(event.value), time, pEntity->GetWorldPos());
  1789.                 break;
  1790.         /*case eGE_Damage:
  1791.            {
  1792.             float dmgVal = event.value;
  1793.             const char* weaponName = event.description;
  1794.             plr.WeaponDamage(weaponName, dmgVal);
  1795.  
  1796.            }break;*/
  1797.         case eGE_WeaponHit:
  1798.                 if (!plr.m_inVehicle)
  1799.                 {
  1800.                         float dmgVal = event.value;
  1801.                         const char* weaponName = event.description;
  1802.                         uint32 targetId = (uint32) reinterpret_cast<TRUNCATE_PTR>(event.extra);
  1803.                         const Vec3 fakePos(0, 0, 0);
  1804.                         const char* bodyPart = event.strData;
  1805.  
  1806.                         plr.WeaponHit(weaponName);
  1807.                         plr.WeaponDamage(weaponName, dmgVal);
  1808.                         plr.PlayerEvent(time, "hit", weaponName, targetId, fakePos, dmgVal, bodyPart);
  1809.  
  1810.                 }
  1811.                 break;
  1812.         case eGE_Kill:
  1813.                 {
  1814.                         plr.ClientKill(event.description, time);
  1815.  
  1816.                         EntityId* params = (EntityId*)event.extra;
  1817.                         IEntity* pWeapon = 0;
  1818.                         if (params)
  1819.                                 gEnv->pEntitySystem->GetEntity(params[0]);
  1820.                         plr.WeaponKill(pWeapon ? pWeapon->GetClass()->GetName() : 0);
  1821.                 }
  1822.                 break;
  1823.         case eGE_Death:
  1824.                 plr.ClientDeath(time);
  1825.                 break;
  1826.         case eGE_Revive:
  1827.                 plr.ClientRevive(time);
  1828.                 break;
  1829.         case eGE_SuitModeChanged:
  1830.                 plr.SelectSuitMode(int(event.value), time);
  1831.                 break;
  1832.         case eGE_EnteredVehicle:
  1833.                 {
  1834.                         if (IVehicle* pV = CCryAction::GetCryAction()->GetIVehicleSystem()->GetVehicle((EntityId)(TRUNCATE_PTR)event.extra))
  1835.                         {
  1836.                                 vehicle_name.Format("%s_%s", pV->GetEntity()->GetClass()->GetName(), pV->GetModification());
  1837.                                 plr.EnterVehicle(vehicle_name, time);
  1838.                         }
  1839.                 }
  1840.                 break;
  1841.         case eGE_LeftVehicle:
  1842.                 {
  1843.                         if (IVehicle* pV = CCryAction::GetCryAction()->GetIVehicleSystem()->GetVehicle((EntityId)(TRUNCATE_PTR)event.extra))
  1844.                         {
  1845.                                 vehicle_name.Format("%s_%s", pV->GetEntity()->GetClass()->GetName(), pV->GetModification());
  1846.                                 plr.LeaveVehicle(vehicle_name, time);
  1847.                         }
  1848.                 }
  1849.                 break;
  1850.         case eGE_ItemSelected:
  1851.                 {
  1852.                         if (IEntity* pI = gEnv->pEntitySystem->GetEntity(EntityId((TRUNCATE_PTR)event.extra)))
  1853.                                 plr.SelectWeapon(pI->GetClass()->GetName(), time);
  1854.                 }
  1855.                 break;
  1856.         case eGE_WeaponReload:
  1857.                 {
  1858.                         plr.Reload(time, pEntity->GetWorldPos());
  1859.                         break;
  1860.                 }
  1861.         case eGE_Spectator:
  1862.                 plr.Spectator(event.value != 0, time);
  1863.                 break;
  1864.         case eGE_WeaponFireModeChanged:
  1865.                 {
  1866.                         plr.FiremodeChanged(time, pEntity->GetWorldPos(), event.description);
  1867.                         break;
  1868.                 }
  1869.         case eGE_ZoomedIn:
  1870.                 {
  1871.                         plr.ZoomIn(time, pEntity->GetWorldPos());
  1872.                         break;
  1873.                 }
  1874.         case eGE_ZoomedOut:
  1875.                 {
  1876.                         plr.ZoomOut(time, pEntity->GetWorldPos());
  1877.                         break;
  1878.                 }
  1879.         }
  1880. }
  1881.  
  1882. bool CGameStats::GetLevelName(string& mapname)
  1883. {
  1884.         string levelname;
  1885.         if (ILevelInfo* pLevelInfo = gEnv->pGameFramework->GetILevelSystem()->GetCurrentLevel())
  1886.         {
  1887.                 levelname = pLevelInfo->GetDisplayName();
  1888.                 if (levelname.empty())
  1889.                         levelname = gEnv->pGameFramework->GetLevelName();
  1890.         }
  1891.         if (levelname.empty())
  1892.                 return false;
  1893.         else
  1894.         {
  1895.                 mapname = levelname;
  1896.                 return true;
  1897.         }
  1898. }
  1899.  
  1900. void CGameStats::SubmitPlayerStats(const SPlayerInfo& plr, bool server, bool client)
  1901. {
  1902.         if (!m_statsTrack)
  1903.                 return;
  1904.         SStatsTrackHelper hlp(this);
  1905.         //server stats
  1906.  
  1907.         const SPlayerStats& stats = *(plr.stats.back());
  1908.         if (server)
  1909.         {
  1910.                 hlp.PlayerValue(plr.id, "name", plr.name.c_str());
  1911.                 hlp.PlayerValue(plr.id, "rank", plr.rank);
  1912.                 hlp.PlayerValue(plr.id, "kills", stats.m_kills);
  1913.                 hlp.PlayerValue(plr.id, "deaths", stats.m_deaths);
  1914.                 hlp.PlayerValue(plr.id, "shots", stats.m_shots);
  1915.                 hlp.PlayerValue(plr.id, "hits", stats.m_hits);
  1916.                 hlp.PlayerValue(plr.id, "melee", stats.m_melee);
  1917.         }
  1918.  
  1919.         //here are some client-only stats - mainly times
  1920.         if (client)
  1921.         {
  1922.                 CTimeValue time = SGetTime(m_roundStart);
  1923.                 plr.stats.back()->End(time);
  1924.                 int played = int((time - plr.stats.back()->m_started).GetSeconds() + 0.5f);
  1925.                 int played_minutes = played / 60;
  1926.                 hlp.PlayerValue(plr.id, "played", played_minutes);
  1927.                 static string keyName;
  1928.  
  1929.                 keyName.Format("Played%s", m_gameMode.c_str());
  1930.                 hlp.PlayerCatValue(plr.id, "mode", keyName, played);
  1931.  
  1932.                 keyName.Format("PlayedMap%s", m_mapName.c_str());
  1933.                 hlp.PlayerCatValue(plr.id, "map", keyName, played);
  1934.  
  1935.                 for (int i = 0; i < 4; ++i)
  1936.                 {
  1937.                         int used = int(stats.m_suit.m_used[i].GetSeconds() + 0.5f);
  1938.                         if (!used)
  1939.                                 continue;
  1940.                         keyName.Format("UsedSuit%d", i);
  1941.                         hlp.PlayerCatValue(plr.id, "suit_mode", keyName, used);
  1942.                 }
  1943.  
  1944.                 for (int i = 0; i < stats.m_vehicles.m_vehicles.size(); ++i)
  1945.                 {
  1946.                         const SPlayerStats::SVehicles::SVehicle& veh = stats.m_vehicles.m_vehicles[i];
  1947.                         int used = int(veh.m_used.GetSeconds() + 0.5f);
  1948.                         keyName.Format("UsedVehicle%s", veh.m_name.c_str());
  1949.                         hlp.PlayerCatValue(plr.id, "vehicle", keyName, used);
  1950.                 }
  1951.  
  1952.                 for (int i = 0; i < stats.m_weapons.m_weapons.size(); ++i)
  1953.                 {
  1954.                         const SPlayerStats::SWeapons::SWeapon& wep = stats.m_weapons.m_weapons[i];
  1955.                         if (!wep.m_kills)
  1956.                                 continue;
  1957.  
  1958.                         keyName.Format("WeaponKills%s", wep.m_name.c_str());
  1959.                         hlp.PlayerCatValue(plr.id, "weapon", keyName, wep.m_kills);
  1960.                 }
  1961.         }
  1962.  
  1963.         //Debugging stuff
  1964.         if (!hlp.m_errors.empty())
  1965.         {
  1966.                 GameWarning("Stats tracking : SubmitPlayerStats tried to use %d missing key(s)", (int)hlp.m_errors.size());
  1967.                 for (int i = 0; i < hlp.m_errors.size(); ++i)
  1968.                 {
  1969.                         GameWarning("     Key %s not found", hlp.m_errors[i].c_str());
  1970.                 }
  1971.         }
  1972. }
  1973.  
  1974. void CGameStats::SubmitServerStats()
  1975. {
  1976.         SStatsTrackHelper hlp(this);
  1977.  
  1978.         string mode;
  1979.         if (IEntity* pGRE = gEnv->pGameFramework->GetIGameRulesSystem()->GetCurrentGameRulesEntity())
  1980.         {
  1981.                 mode = pGRE->GetClass()->GetName();
  1982.         }
  1983.         else
  1984.                 mode = gEnv->pConsole->GetCVar("sv_gamerules")->GetString();
  1985.  
  1986.         char strProductVersion[256];
  1987.         gEnv->pSystem->GetProductVersion().ToString(strProductVersion);
  1988.  
  1989.         string name;
  1990.         ICVar* pName = gEnv->pConsole->GetCVar("sv_servername");
  1991.         if (pName)
  1992.                 name = pName->GetString();
  1993.         if (name.empty())
  1994.                 name = gEnv->pNetwork->GetHostName();
  1995.  
  1996.         string levelname;
  1997.         GetLevelName(levelname);
  1998.  
  1999.         hlp.ServerValue("mapname", levelname);
  2000.         hlp.ServerValue("gametype", mode);
  2001.         hlp.ServerValue("hostname", name);
  2002.         hlp.ServerValue("gamever", strProductVersion);
  2003. }
  2004.  
  2005. void CGameStats::Init()
  2006. {
  2007.         // michiel - GS
  2008.         return;
  2009. }
  2010.  
  2011. void CGameStats::GetMemoryStatistics(ICrySizer* s)
  2012. {
  2013.         s->AddObject(this, sizeof(*this));
  2014.         s->AddObject(m_playerMap);
  2015. }
  2016.  
  2017. void CGameStats::SPlayerInfo::GetMemoryUsage(ICrySizer* pSizer) const
  2018. {
  2019.         pSizer->AddObject(name);
  2020.         pSizer->AddObject(scores);
  2021.         pSizer->AddObject(stats);
  2022. }
  2023.  
downloadGameStats.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top