void CGameServerChannel::OnDisconnect(EDisconnectionCause cause, const char *description) { //CryLogAlways("CGameServerChannel::OnDisconnect(%d, '%s')", cause, description?description:""); CCryAction::GetCryAction()->OnActionEvent(SActionEvent(eAE_clientDisconnected,int(cause),description)); IGameRules *pGameRules = CCryAction::GetCryAction()->GetIGameRulesSystem()->GetCurrentGameRules(); if (pGameRules && IsOnHold()) { pGameRules->OnClientDisconnect(GetChannelId(), cause, description, false); Cleanup(); return; } if (sv_timeout_disconnect && pGameRules && sv_timeout_disconnect->GetIVal()>0 && pGameRules->ShouldKeepClient(GetChannelId(), cause, description)) { if (m_pServerNub->PutChannelOnHold(this)) { pGameRules->OnClientDisconnect(GetChannelId(), cause, description, true); m_hasLoadedLevel=false; return; } } if (pGameRules) pGameRules->OnClientDisconnect(GetChannelId(), cause, description, false); Cleanup(); }
void CGameStats::Connected() { //should not be called if(gEnv->IsClient() && !gEnv->bServer)//pure clients { if(IGameRulesSystem* pGR = gEnv->pGame->GetIGameFramework()->GetIGameRulesSystem()) { IGameRules *pR = pGR->GetCurrentGameRules(); if(pR) { IEntityScriptProxy *pScriptProxy=static_cast<IEntityScriptProxy *>(pR->GetEntity()->GetProxy(ENTITY_PROXY_SCRIPT)); if (pScriptProxy) { string gameState = pScriptProxy->GetState(); if(gameState=="InGame") { m_playing=true; m_gameMode = pR->GetEntity()->GetClass()->GetName(); } } } } if(m_statsTrack) m_statsTrack->Reset(); } }
void OnVehicleEvent(EVehicleEvent event, const SVehicleEventParams& params) { if ( (event == eVE_Destroyed) || (event == eVE_PreVehicleDeletion) || (event == eVE_Hide) ) // Safer to ensure the listener is removed at this point { SetActive(false); } else if (event == eVE_VehicleDeleted) // This shouldn't be called due to above but just in case { SetActive(false); } else if (event == eVE_Collision) // Currently disabled in C2 code { ActivateOutput(&m_actInfo, EOP_Collided, true); } else if (event == eVE_Hit) // Needed to detect collision in C2 code since above is disabled { IGameRules* pGameRules = gEnv->pGame->GetIGameFramework()->GetIGameRulesSystem()->GetCurrentGameRules(); if (pGameRules) { const int collisionHitType = pGameRules->GetHitTypeId("collision"); if (params.iParam == collisionHitType) { ActivateOutput(&m_actInfo, EOP_Collided, true); } } } }
const char *CHUDTagNames::GetPlayerRank(EntityId uiEntityId) { const char *szRank = NULL; IGameRules *pGameRules = g_pGame->GetGameRules(); int iPlayerRank = 0; if(IScriptTable *pGameRulesTable=pGameRules->GetEntity()->GetScriptTable()) { HSCRIPTFUNCTION pfnGetPlayerRank = NULL; if(pGameRulesTable->GetValue("GetPlayerRank",pfnGetPlayerRank) && pfnGetPlayerRank) { Script::CallReturn(gEnv->pScriptSystem,pfnGetPlayerRank,pGameRulesTable,ScriptHandle(uiEntityId),iPlayerRank); gEnv->pScriptSystem->ReleaseFunc(pfnGetPlayerRank); } } if(iPlayerRank) { static string strRank; static wstring wRank; strRank.Format("@ui_short_rank_%d",iPlayerRank); if(gEnv->pSystem->GetLocalizationManager()->LocalizeLabel(strRank,wRank)) { ConvertWString(wRank,strRank); } szRank = strRank.c_str(); } return szRank; }
void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo ) { if (event == eFE_Activate && IsPortActive(pActInfo,0)) { IActor* pActor = GetInputActor( pActInfo ); if (!pActor || pActor!=gEnv->pGame->GetIGameFramework()->GetClientActor()) // to avoid some extra RMIs and object creation. Tho, this causes the node to not work properly if it is used with non players entities. (which was never intended anyway) return; IEntitySystem* pEntSys = gEnv->pEntitySystem; IInventory *pInventory = pActor->GetInventory(); if (!pInventory) return; const string& itemClass = GetPortString(pActInfo, 1); const char* pItemClass = itemClass.c_str(); IEntityClass* pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(pItemClass); EntityId id = pInventory->GetItemByClass(pClass); if (id == 0 || GetPortBool(pActInfo, 3) == false) { if(gEnv->bServer) { gEnv->pGame->GetIGameFramework()->GetIItemSystem()->GiveItem( pActor, pItemClass , false, true, true ); } else { // TODO: instant output activation, with delayed effective change in the inventory, it potentially could cause problems in rare situations pInventory->RMIReqToServer_AddItem( pItemClass ); } ActivateOutput( pActInfo, 0, true ); } else { // item already in inventory ActivateOutput(pActInfo, 0, false); } } else if (event == eFE_PrecacheResources) { const string& itemClass = GetPortString(pActInfo, 1); if (!itemClass.empty()) { IGameRules* pGameRules = CCryAction::GetCryAction()->GetIGameRulesSystem()->GetCurrentGameRules(); CRY_ASSERT_MESSAGE(pGameRules != NULL, "No game rules active, can not precache resources"); if (pGameRules) { pGameRules->PrecacheLevelResource(itemClass.c_str(), eGameResourceType_Item); } } } }
void CGameStats::Report() { if(!m_serverReport) return; int playerCount = m_playerMap.size(); if (CGameServerNub * pServerNub = CCryAction::GetCryAction()->GetGameServerNub()) playerCount = pServerNub->GetPlayerCount(); //All server reporting is done here m_serverReport->SetReportParams(playerCount,m_teamMap.size()); m_serverReport->SetServerValue("gamemode",m_playing?"game":"pre-game"); CryFixedStringT<32> timeleft("-"); if(IGameRulesSystem* pGR = gEnv->pGame->GetIGameFramework()->GetIGameRulesSystem()) { IGameRules *pR = pGR->GetCurrentGameRules(); if(pR && pR->IsTimeLimited() && m_playing) { timeleft.Format("%.0f",pR->GetRemainingGameTime()); } } m_serverReport->SetServerValue("timeleft",timeleft); CryFixedStringT<256> tempStr; m_serverReport->SetServerValue("numplayers",tempStr.Format("%d",playerCount)); int i=0; string mode; for(PlayerStatsMap::const_iterator it=m_playerMap.begin();it!=m_playerMap.end();++it) { static string value; m_serverReport->SetPlayerValue(i, "player", it->second.name); value.Format("%d",it->second.rank); m_serverReport->SetPlayerValue(i, "rank", value); value.Format("%d",it->second.team?it->second.team:(it->second.spectator?0:1)); m_serverReport->SetPlayerValue(i, "team", value); for (std::map<string, int>::const_iterator sit=it->second.scores.begin(); sit!=it->second.scores.end(); ++sit) m_serverReport->SetPlayerValue(i, sit->first, tempStr.Format("%d",sit->second)); ++i; } while (i < playerCount) { m_serverReport->SetPlayerValue(i, "player", "<connecting>"); ++i; } }
//------------------------------------------------------------------------ void CGameServerNub::ResetOnHoldChannels() { for (THoldChannelMap::iterator it=m_onhold.begin(); it!=m_onhold.end(); ++it) { IGameRules *pGameRules = CCryAction::GetCryAction()->GetIGameRulesSystem()->GetCurrentGameRules(); pGameRules->OnClientDisconnect(it->first,eDC_Timeout,"OnHold reseted",false); TServerChannelMap::iterator ch_it = m_channels.find(it->first); if(ch_it!=m_channels.end()) { delete ch_it->second; m_channels.erase(ch_it); } } m_onhold.clear(); }
//------------------------------------------------------------------------ void CVehicleDamages::ParseDamageMultipliers(TDamageMultipliers& multipliersByHitType, TDamageMultipliers& multipliersByProjectile, const CVehicleParams& table) { CVehicleParams damageMultipliersTable = table.findChild("DamageMultipliers"); if (!damageMultipliersTable) return; int i = 0; int c = damageMultipliersTable.getChildCount(); IGameRules* pGR = CCryAction::GetCryAction()->GetIGameRulesSystem()->GetCurrentGameRules(); assert(pGR); for (; i < c; i++) { if (CVehicleParams multiplierTable = damageMultipliersTable.getChild(i)) { string damageType = multiplierTable.getAttr("damageType"); if (!damageType.empty()) { int hitTypeId = 0; if(pGR && damageType != "default") hitTypeId = pGR->GetHitTypeId(damageType.c_str()); assert(hitTypeId != 0 || damageType == "default"); if(hitTypeId != 0 || damageType == "default") { GetAndInsertMultiplier( multipliersByHitType, multiplierTable, int(hitTypeId) ); } } string ammoType = multiplierTable.getAttr("ammoType"); if (!ammoType.empty()) { int projectileType = 0; if(pGR && ammoType != "default") { uint16 classId(~uint16(0)); if( ammoType == "default" || gEnv->pGame->GetIGameFramework()->GetNetworkSafeClassId(classId, ammoType.c_str()) ) { GetAndInsertMultiplier( multipliersByProjectile, multiplierTable, int(classId) ); } } } } } }
void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo ) { if (event == eFE_Activate && IsPortActive(pActInfo, EIP_Trigger)) { IActor* pActor = GetInputActor( pActInfo ); if (!pActor) return; IInventory *pInventory = pActor->GetInventory(); if (!pInventory) return; const bool& addPack = GetPortBool(pActInfo, EIP_AddToggle); const string& packName = GetPortString(pActInfo, EIP_EquipmentPack); const bool& selectPrimary = GetPortBool(pActInfo, EIP_SelectPrimary); if (pActor->IsPlayer()) pInventory->RMIReqToServer_AddEquipmentPack( packName.c_str(), addPack, selectPrimary ); else { if (gEnv->bServer) CCryAction::GetCryAction()->GetIItemSystem()->GetIEquipmentManager()->GiveEquipmentPack( pActor, packName.c_str(), addPack, selectPrimary ); } // TODO: instant output activation, with delayed effective change in the inventory, it potentially could cause problems in rare situations ActivateOutput(pActInfo, EOP_Done, true); } else if (event == eFE_PrecacheResources) { const string& packName = GetPortString(pActInfo, 1); if (!packName.empty()) { IGameRules* pGameRules = CCryAction::GetCryAction()->GetIGameRulesSystem()->GetCurrentGameRules(); CRY_ASSERT_MESSAGE(pGameRules != NULL, "No game rules active, can not precache resources"); if (pGameRules) { pGameRules->PrecacheLevelResource(packName.c_str(), eGameResourceType_Loadout); } } } }
//------------------------------------------------------------------------ void CGameServerNub::RemoveOnHoldChannel(CGameServerChannel *pServerChannel, bool renewed) { for (THoldChannelMap::iterator it=m_onhold.begin(); it!=m_onhold.end(); ++it) { if (it->second.channelId == pServerChannel->GetChannelId()) { m_onhold.erase(it); if(!renewed)//let gamerules know we should get rid of it... { IGameRules *pGameRules = CCryAction::GetCryAction()->GetIGameRulesSystem()->GetCurrentGameRules(); pGameRules->OnClientDisconnect(pServerChannel->GetChannelId(),eDC_Timeout,"OnHold timed out",false); } break; } } if(!renewed) { stl::member_find_and_erase(m_channels, pServerChannel->GetChannelId()); delete pServerChannel; } }
void CVehicleDamageBehaviorBlowTire::DamagePlayers() { // check for the nasty case when the player is shooting at the vehicle tires while prone // under or behind the car, In that case the player should get killed by the vehicle, // otherwise he gets stuck forever. Note that he should only get killed when the tier // is actually destroyed and not by collision resulting by the impulse added by just // shooting at the tiers. Unfortunately using physics for doing this check is not reliable // enough so we have to check it explicitly IEntityPhysicalProxy *pPhysicsProxy = (IEntityPhysicalProxy*)m_pVehicle->GetEntity()->GetProxy(ENTITY_PROXY_PHYSICS); if (!pPhysicsProxy) return; AABB bbox; pPhysicsProxy->GetWorldBounds( bbox ); IPhysicalWorld *pWorld = gEnv->pSystem->GetIPhysicalWorld(); IPhysicalEntity **ppColliders; // check entities in collision with the car int cnt = pWorld->GetEntitiesInBox( bbox.min,bbox.max, ppColliders,ent_living); for (int i = 0; i < cnt; i++) { IEntity *pEntity = gEnv->pEntitySystem->GetEntityFromPhysics( ppColliders[i] ); if (!pEntity) continue; // skip the vehicle itself if (pEntity==m_pVehicle->GetEntity()) continue; IPhysicalEntity *pPhysEnt = pEntity->GetPhysics(); if (!pPhysEnt) continue; IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId()); if(!pActor) continue; //Jan M.: the player is killed when he entered the vehicle while prone although he is still passenger! if(m_pVehicle == pActor->GetLinkedVehicle()) continue; //the player must be prone under the vehicle IAnimatedCharacter * animatedCharacter=pActor->GetAnimatedCharacter(); if (!animatedCharacter) continue; int stance = animatedCharacter->GetCurrentStance(); if (stance!=STANCE_PRONE) continue; pe_player_dimensions dim; if (!pPhysEnt->GetParams(&dim)) continue; // position returned is at entity's feet, add head position from physics Vec3 vPos1=pEntity->GetPos(); vPos1.z = vPos1.z + dim.heightHead; float fZ=bbox.GetCenter().z; if (vPos1.z>fZ) continue; // not under the vehicle // at this point we have a collision with the car moving down and the guy prone under the car, it is safe // to assume he has been squished so let's kill him. if (gEnv->bServer && pActor->GetHealth()>0) { // adding a server hit to make it working in MP IGameRules *pGameRules = gEnv->pGame->GetIGameFramework()->GetIGameRulesSystem()->GetCurrentGameRules(); if (pGameRules) { HitInfo hit; EntityId shooterId=m_pVehicle->GetEntityId(); if (m_pVehicle->GetDriver()) shooterId=m_pVehicle->GetDriver()->GetEntityId(); hit.targetId = pEntity->GetId(); hit.shooterId = shooterId; hit.weaponId = m_pVehicle->GetEntityId(); hit.damage = 1000.f; hit.type = 0; hit.pos = pActor->GetEntity()->GetWorldPos(); pGameRules->ServerHit(hit); } } } //i }
//------------------------------------------------------------------------ SCreateChannelResult CGameServerNub::CreateChannel(INetChannel *pChannel, const char *pRequest) { CRY_ASSERT(m_maxPlayers); CGameServerChannel *pNewChannel; if (!pRequest) { CRY_ASSERT(false); SCreateChannelResult res(eDC_GameError); return res; } SParsedConnectionInfo info = m_pGameContext->ParseConnectionInfo(pRequest); if (!info.allowConnect) { GameWarning( "Not allowed to connect to server: %s", info.errmsg.c_str() ); SCreateChannelResult res(info.cause); cry_strcpy(res.errorMsg, info.errmsg.c_str()); return res; } if (int(m_channels.size()) >= m_maxPlayers) { SCreateChannelResult res(eDC_ServerFull); cry_strcpy(res.errorMsg, string().Format("Disallowing more than %d players",m_maxPlayers).c_str()); return res; } if (info.isMigrating && CCryAction::GetCryAction()->IsGameSessionMigrating()) { pChannel->SetMigratingChannel(true); } pNewChannel = GetOnHoldChannelFor(pChannel); if (!pNewChannel) { pNewChannel = new CGameServerChannel(pChannel, m_pGameContext, this); if (pChannel->GetSession() != CrySessionInvalidHandle) { // There is a valid CrySessionHandle created by the lobby so use this as the channel id // as it contains information that can identify the connection in the lobby. pNewChannel->SetChannelId(pChannel->GetSession()); } else { // No valid CrySessionHandle so create an id here. pNewChannel->SetChannelId(++m_genId); } if (m_channels.find(pNewChannel->GetChannelId()) != m_channels.end()) { CryFatalError("CGameServerNub::CreateChannel: Trying to create channel with duplicate id %d", pNewChannel->GetChannelId()); } m_channels.insert(TServerChannelMap::value_type(pNewChannel->GetChannelId(), pNewChannel)); } else { pNewChannel->SetNetChannel(pChannel); #if !NEW_BANDWIDTH_MANAGEMENT pNewChannel->SetupNetChannel(pChannel); #endif // NEW_BANDWIDTH_MANAGEMENT } ICVar* pPass = gEnv->pConsole->GetCVar("sv_password"); if (pPass && gEnv->bMultiplayer) { pChannel->SetPassword(pPass->GetString()); } pChannel->SetNickname(info.playerName.c_str()); // Host migration if (info.isMigrating && CCryAction::GetCryAction()->IsGameSessionMigrating()) { // Enable the game rules to find the migrating player details by channel id IGameFramework *pGameFramework = gEnv->pGame->GetIGameFramework(); IGameRules *pGameRules = pGameFramework->GetIGameRulesSystem()->GetCurrentGameRules(); if(pGameRules) { EntityId playerID = pGameRules->SetChannelForMigratingPlayer(info.playerName.c_str(), pNewChannel->GetChannelId()); if (playerID) { CryLog("CGameServerNub::CreateChannel() assigning actor %d '%s' to channel %d", playerID, info.playerName.c_str(), pNewChannel->GetChannelId()); pNewChannel->SetPlayerId(playerID); } else { CryLog("CGameServerNub::CreateChannel() failed to assign actor '%s' to channel %d", info.playerName.c_str(), pNewChannel->GetChannelId()); } } else { CryLog("[host migration] terminating because game rules is NULL, game session migrating %d session 0x%08x", CCryAction::GetCryAction()->IsGameSessionMigrating(), pChannel->GetSession()); gEnv->pNetwork->TerminateHostMigration(pChannel->GetSession()); } } m_netchannels.insert(TNetServerChannelMap::value_type(pChannel, pNewChannel->GetChannelId())); return SCreateChannelResult(pNewChannel); }
void CDamageEffectController::Init(CActor* actor) { if (CKVoltEffect::s_hashId == 0) //once initialised it can't be 0 { CKVoltEffect::s_hashId = CreateHash("KVoltFX"); CTinnitusEffect::s_hashId = CreateHash("TinnitusFx"); CEntityTimerEffect::s_hashId = CreateHash("TimerFX"); } IGameRules* pGameRules = g_pGame->GetGameRules(); m_ownerActor = actor; const IItemParamsNode* actorParams = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActorParams(actor->GetEntityClassName()); const IItemParamsNode* damageEffectParams = actorParams ? actorParams->GetChild("DamageEffectParams") : 0; if (damageEffectParams) { int numChildren = damageEffectParams->GetChildCount(); int allowSerialise = 1; damageEffectParams->GetAttribute("allowSerialise", allowSerialise); m_allowSerialise = allowSerialise ? true : false; CRY_ASSERT_MESSAGE(numChildren <= MAX_NUM_DAMAGE_EFFECTS, "Too many damage effects found. Increase the MAX_NUM_DAMAGE_EFFECTS and size of activeEffects and effectsResetSwitch"); for (int i = 0; i < numChildren; i++) { const IItemParamsNode* child = damageEffectParams->GetChild(i); const IItemParamsNode* effect = child->GetChild(0); const char* hittype = child->GetAttribute("hittype"); const char* name = effect->GetName(); m_associatedHitType[i] = pGameRules->GetHitTypeId(hittype); child->GetAttribute("minDamage", m_minDamage[i]); uint64 hashcode = CreateHash(name); if (hashcode == CKVoltEffect::s_hashId) { m_effectList[i] = new CKVoltEffect(); } else if (hashcode == CTinnitusEffect::s_hashId) { m_effectList[i] = new CTinnitusEffect(); } else if (hashcode == CEntityTimerEffect::s_hashId) { m_effectList[i] = new CEntityTimerEffect(); } else { GameWarning("INVALID DAMAGE EFFECT PARSED"); m_associatedHitType[i] = -1; } if(m_effectList[i]) { m_effectList[i]->Init(actor, effect); } } } }
void CUIHUD3D::SpawnHudEntities() { RemoveHudEntities(); if (gEnv->IsEditor() && gEnv->IsEditing()) return; const char* hudprefab = NULL; IGameRules* pGameRules = gEnv->pGame->GetIGameFramework()->GetIGameRulesSystem()->GetCurrentGameRules(); if (pGameRules) { IScriptTable* pTable = pGameRules->GetEntity()->GetScriptTable(); if (pTable) { if (!pTable->GetValue("hud_prefab", hudprefab)) hudprefab = NULL; } } hudprefab = hudprefab ? hudprefab : HUD3D_PREFAB_LIB; XmlNodeRef node = gEnv->pSystem->LoadXmlFromFile(hudprefab); if (node) { // get the prefab with the name defined in HUD3D_PREFAB_NAME XmlNodeRef prefab = NULL; for (int i = 0; i < node->getChildCount(); ++i) { const char* name = node->getChild(i)->getAttr("Name"); if (name && strcmp(name, HUD3D_PREFAB_NAME) == 0) { prefab = node->getChild(i); prefab = prefab ? prefab->findChild("Objects") : XmlNodeRef(); break; } } if (prefab) { // get the PIVOT entity and collect childs XmlNodeRef pivotNode = NULL; std::vector<XmlNodeRef> childs; const int count = prefab->getChildCount(); childs.reserve(count-1); for (int i = 0; i < count; ++i) { const char* name = prefab->getChild(i)->getAttr("Name"); if (strcmp("PIVOT", name) == 0) { assert(pivotNode == NULL); pivotNode = prefab->getChild(i); } else { childs.push_back(prefab->getChild(i)); } } if (pivotNode) { // spawn pivot entity IEntityClass* pEntClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass( pivotNode->getAttr("EntityClass") ); if (pEntClass) { SEntitySpawnParams params; params.nFlags = ENTITY_FLAG_CLIENT_ONLY; params.pClass = pEntClass; m_pHUDRootEntity = gEnv->pEntitySystem->SpawnEntity(params); } if (!m_pHUDRootEntity) return; m_HUDRootEntityId = m_pHUDRootEntity->GetId(); // spawn the childs and link to the pivot enity for (std::vector<XmlNodeRef>::iterator it = childs.begin(); it != childs.end(); ++it) { XmlNodeRef child = *it; pEntClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass( child->getAttr("EntityClass") ); if (pEntClass) { const char* material = child->getAttr("Material"); Vec3 pos; Vec3 scale; Quat rot; child->getAttr("Pos", pos); child->getAttr("Rotate", rot); child->getAttr("Scale", scale); SEntitySpawnParams params; params.nFlags = ENTITY_FLAG_CLIENT_ONLY; params.pClass = pEntClass; params.vPosition = pos; params.qRotation = rot; params.vScale = scale; IEntity* pEntity = gEnv->pEntitySystem->SpawnEntity(params); if (pEntity) { IScriptTable* pScriptTable = pEntity->GetScriptTable(); if (pScriptTable) { SmartScriptTable probs; pScriptTable->GetValue("Properties", probs); XmlNodeRef properties = child->findChild("Properties"); if (probs && properties) { for (int k = 0; k < properties->getNumAttributes(); ++k) { const char* sKey; const char* sVal; properties->getAttributeByIndex(k, &sKey, &sVal); probs->SetValue(sKey, sVal); } } Script::CallMethod(pScriptTable,"OnPropertyChange"); } if (material) { IMaterial* pMat = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(material); if (pMat) pEntity->SetMaterial(pMat); } m_pHUDRootEntity->AttachChild(pEntity); m_HUDEnties.push_back( pEntity->GetId() ); } } } } } } OnVisCVarChange( NULL ); }
void CGameStats::StartGame(bool server) { if(!server && gEnv->bServer)//we simply ignore client events on server return; if(IGameRulesSystem* pGR = gEnv->pGame->GetIGameFramework()->GetIGameRulesSystem()) { IGameRules *pR = pGR->GetCurrentGameRules(); if(pR) { IEntityScriptProxy *pScriptProxy=static_cast<IEntityScriptProxy *>(pR->GetEntity()->GetProxy(ENTITY_PROXY_SCRIPT)); if (pScriptProxy) { string gameState = pScriptProxy->GetState(); if(gameState=="InGame") { m_playing=true; m_gameMode = pR->GetEntity()->GetClass()->GetName(); } } } } if(!m_statsTrack || !m_serverReport) Init(); if(m_serverReport) { ReportGame(); m_serverReport->Update(); } if(m_playing) { if (ILevelInfo* pLevelInfo = gEnv->pGame->GetIGameFramework()->GetILevelSystem()->GetCurrentLevel()) { m_mapName = pLevelInfo->GetName();//we only need pure level name here const char* p = strrchr(m_mapName.c_str(),'/'); if(p != 0 && strlen(p) > 1) { m_mapName = p + 1; char* pStr = const_cast<char*>(m_mapName.data()); pStr[0] = toupper(m_mapName[0]); for(int i = 1; i < m_mapName.size(); ++i) pStr[i] = tolower(m_mapName[i]); } } } if(m_statsTrack && m_playing && gEnv->bServer) m_statsTrack->StartGame(); if(gEnv->bServer && m_playing) { m_roundStart = gEnv->pTimer->GetFrameStartTime(); m_lastPosUpdate = 0.0f; ResetStats(); m_roundStats->Start(m_mapName, m_roundStart); } }