virtual void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo ) { switch (event) { case eFE_Initialize: case eFE_Activate: { IActorSystem *pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); IActorIteratorPtr actorIt = pActorSystem->CreateActorIterator(); int iNumPlayers = 0; IActor *pActor = actorIt->Next(); while(iNumPlayers < 4 && pActor) { if(pActor->GetChannelId()) { ActivateOutput(pActInfo, iNumPlayers, pActor->GetEntityId()); ++iNumPlayers; } pActor = actorIt->Next(); } } break; } }
//-------------------------------------------------------------- void CWeaponSystem::OnGameTokenEvent( EGameTokenEvent event,IGameToken *pGameToken ) { assert(pGameToken); if(EGAMETOKEN_EVENT_CHANGE == event) { bool handled = false; if(!strcmp("weapon.effects.ice",pGameToken->GetName())) { pGameToken->GetValueAs(m_frozenEnvironment); handled = true; } else if(!strcmp("weapon.effects.wet",pGameToken->GetName())) { pGameToken->GetValueAs(m_wetEnvironment); handled = true; } if (handled) { IGameFramework* pGF = gEnv->pGame->GetIGameFramework(); IActorSystem* pAS = pGF->GetIActorSystem(); int count = pAS->GetActorCount(); if (count) { IActorIteratorPtr it = pAS->CreateActorIterator(); while (CActor* pActor = (CActor*)it->Next()) { CPlayer *pPlayer = (pActor->GetActorClass() == CPlayer::GetActorClassType()) ? static_cast<CPlayer*>(pActor) : 0; if (pPlayer && pPlayer->GetNanoSuit()) { // go through all players and turn their ice effects on/off IEntityRenderProxy* pRenderProxy = (IEntityRenderProxy*)pPlayer->GetEntity()->GetProxy(ENTITY_PROXY_RENDER); if (pRenderProxy) { uint8 mask = pRenderProxy->GetMaterialLayersMask(); uint32 blend = pRenderProxy->GetMaterialLayersBlend(); mask = IsFrozenEnvironment() ? mask|MTL_LAYER_DYNAMICFROZEN : mask&~MTL_LAYER_DYNAMICFROZEN; mask = IsWetEnvironment() ? mask|MTL_LAYER_WET : mask&~MTL_LAYER_WET; pRenderProxy->SetMaterialLayersMask(mask); pRenderProxy->SetMaterialLayersBlend(blend); if (CItem* pItem = static_cast<CItem*>(pPlayer->GetCurrentItem(true))) { pItem->FrostSync(true); pItem->WetSync(true); } if (COffHand* pOffHand = static_cast<COffHand*>(pPlayer->GetItemByClass(CItem::sOffHandClass))) { pOffHand->FrostSync(pOffHand->GetOffHandState() != eOHS_INIT_STATE); pOffHand->WetSync(pOffHand->GetOffHandState() != eOHS_INIT_STATE); } } } } } } } }
void CCheckpointSystem::WriteActorData(XmlNodeRef parentNode) { XmlNodeRef node = GetISystem()->CreateXmlNode(ACTOR_FLAGS_SECTION); //write only data for non-active or hidden actors XmlNodeRef activatedActors = GetISystem()->CreateXmlNode(ACTIVATED_ACTORS_SECTION); char buffer[100]; IActorSystem *pActorSystem = CCryAction::GetCryAction()->GetIActorSystem(); IActorIteratorPtr it = pActorSystem->CreateActorIterator(); while (IActor *pActor = it->Next()) { IEntity *pEntity = pActor->GetEntity(); if(!pEntity->IsHidden() && pEntity->IsActive()) { EntityId id = pEntity->GetId(); const char *name = pEntity->GetName(); //we have to rely on names, since Id's change on level reexport _snprintf(buffer, sizeof(buffer), "%s%i", "id", id); activatedActors->setAttr(buffer, name); } } node->addChild(activatedActors); parentNode->addChild(node); }
//------------------------------------------------------------------------ void CGameRulesMPDamageHandling::SvOnCollision(const IEntity *pVictimEntity, const CGameRules::SCollisionHitInfo& collisionHitInfo) { FUNCTION_PROFILER(gEnv->pSystem, PROFILE_GAME); CRY_ASSERT(gEnv->bMultiplayer); #if !defined(_RELEASE) if (g_pGameCVars->g_DisableCollisionDamage) return; #endif IGameFramework* gameFramwork = g_pGame->GetIGameFramework(); EntityId victimID = pVictimEntity->GetId(); EntityId offenderID = collisionHitInfo.targetId; const IEntity* pOffenderEntity = gEnv->pEntitySystem->GetEntity(offenderID); float currentTime = gEnv->pTimer->GetCurrTime(); CActor* victimActor = static_cast<CActor*>(gameFramwork->GetIActorSystem()->GetActor(victimID)); IVehicle* offenderVehicle = gameFramwork->GetIVehicleSystem()->GetVehicle(offenderID); IVehicle* victimVehicle = gameFramwork->GetIVehicleSystem()->GetVehicle(victimID); IActor* offenderActor = gameFramwork->GetIActorSystem()->GetActor(offenderID); if(pOffenderEntity && !offenderVehicle && !offenderActor) { if( IEntity* pParent = pOffenderEntity->GetParent() ) { offenderVehicle = gameFramwork->GetIVehicleSystem()->GetVehicle(pParent->GetId()); } } // Vehicles being flipped do no damage, for now if (offenderVehicle != NULL && offenderVehicle->GetStatus().beingFlipped) return; // Players can't damage vehicles if (victimVehicle && offenderActor) return; // Filter frequent collisions if (pOffenderEntity) { FRAME_PROFILER("Filter out recent collisions", gEnv->pSystem, PROFILE_GAME); EntityCollisionRecords::const_iterator collisionRecordIter = m_entityCollisionRecords.find(victimID); if (collisionRecordIter != m_entityCollisionRecords.end()) { const EntityCollisionRecord& record = collisionRecordIter->second; if (record.entityID == offenderID && record.time + EntityCollisionIgnoreTimeBetweenCollisions > currentTime) { return; } } } float offenderMass = collisionHitInfo.target_mass; enum { CollisionWithEntity, CollisionWithStaticWorld } collisionType = (pOffenderEntity || offenderMass > 0.0f) ? CollisionWithEntity : CollisionWithStaticWorld; const Vec3& victimVelocity = collisionHitInfo.velocity; const Vec3& offenderVelocity = collisionHitInfo.target_velocity; float relativeSpeedSq = 0.0f; float minSpeedToCareAboutCollisionSq = 0.0f; float contactMass = 0.0f; bool offenderIsBig = offenderMass > 1000.f; switch (collisionType) { case CollisionWithEntity: { Vec3 relativeVelocity = victimVelocity - offenderVelocity; relativeSpeedSq = relativeVelocity.GetLengthSquared(); minSpeedToCareAboutCollisionSq = sqr(10.0f); if (victimActor && offenderIsBig) { minSpeedToCareAboutCollisionSq = sqr(1.0f); } if (victimActor && offenderVehicle) { //Players won't be hurt by vehicles with a negative kill player speed if(offenderVehicle->GetDamageParams().aiKillPlayerSpeed < 0.f) { return; } minSpeedToCareAboutCollisionSq = sqr(2.0f); } const float offenderSpeedSq = offenderVelocity.GetLengthSquared(); if (offenderSpeedSq == 0.0f) // -- if collision target it not moving { minSpeedToCareAboutCollisionSq *= sqr(2.0f); } ////////////////////////////////////////////////////////////////////////// contactMass = offenderMass; break; } case CollisionWithStaticWorld: { // Actors don't take damage from running into walls! if (victimActor) { return; } relativeSpeedSq = victimVelocity.GetLengthSquared(); minSpeedToCareAboutCollisionSq = sqr(7.5f); contactMass = collisionHitInfo.mass; break; } } const bool contactMassIsTooLowToCare = contactMass < 0.01f; if (contactMassIsTooLowToCare) return; ////////////////////////////////////////////////////////////////////////// // Calculate the collision damage if (relativeSpeedSq >= minSpeedToCareAboutCollisionSq) { bool useDefaultCalculation = true; float fEnergy = 0.f; float damage = 0.f; EntityId kickerId = 0; // Calculate damage if (offenderVehicle && victimActor) { useDefaultCalculation = false; damage = ProcessActorVehicleCollision(victimActor, victimID, offenderVehicle, offenderID, damage, collisionHitInfo, kickerId); } else if (offenderIsBig && victimActor) // i.e. a kickable car { // Try to find the kicker CTimeValue time = gEnv->pTimer->GetAsyncTime(); IActorSystem* pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); IActorIteratorPtr pActorIterator = pActorSystem->CreateActorIterator(); IActor* pActor = pActorIterator->Next(); float lowestTime = 5.f; while (pActor != NULL) { CPlayer* pPlayer = static_cast<CPlayer*>(pActor); EntityId kicked = pPlayer->GetLargeObjectInteraction().GetLastObjectId(); if (kicked==offenderID) { float timeSinceKick = (time - pPlayer->GetLargeObjectInteraction().GetLastObjectTime()).GetSeconds(); if (timeSinceKick < lowestTime) { // We found the kicker and the kicked kickerId = pActor->GetEntityId(); lowestTime = timeSinceKick; } } pActor = pActorIterator->Next(); } damage = ProcessActorKickedVehicle(victimActor, victimID, kickerId, offenderID, damage, collisionHitInfo); useDefaultCalculation = false; } if (useDefaultCalculation) { fEnergy = GetCollisionEnergy(pVictimEntity, collisionHitInfo); if (victimVehicle || offenderIsBig) { damage = 0.0005f * fEnergy; } else { damage = 0.0025f * fEnergy; } // Apply damage multipliers damage *= GetCollisionDamageMult(pVictimEntity, pOffenderEntity, collisionHitInfo); if (victimActor) { const bool victimIsPlayer = victimActor->IsPlayer(); if (victimIsPlayer) { damage = AdjustPlayerCollisionDamage(pVictimEntity, pOffenderEntity, collisionHitInfo, damage); } } } if (damage >= DAMAGE_THRESHOLD_COLLISIONS) { HitInfo hit; hit.damage = damage; hit.pos = collisionHitInfo.pos; if (collisionHitInfo.target_velocity.GetLengthSquared() > 1e-6) hit.dir = collisionHitInfo.target_velocity.GetNormalized(); hit.radius = 0.0f; hit.partId = collisionHitInfo.partId; hit.targetId = victimID; hit.weaponId = offenderID; hit.shooterId = kickerId != 0 ? kickerId : offenderID; hit.material = 0; hit.type = CGameRules::EHitType::Collision; hit.explosion = false; CGameRules *pGameRules = g_pGame->GetGameRules(); if (pGameRules->GetTeamCount() > 1) { int shooterTeamId = pGameRules->GetTeam(hit.shooterId); int targetTeamId = pGameRules->GetTeam(hit.targetId); if (shooterTeamId && (shooterTeamId == targetTeamId)) { damage = GetFriendlyFireDamage(damage, hit, victimActor); } } if (damage >= DAMAGE_THRESHOLD_COLLISIONS) { IScriptTable* pVictimScript = pVictimEntity ? pVictimEntity->GetScriptTable() : NULL; IScriptTable* pOffenderScript = pOffenderEntity ? pOffenderEntity->GetScriptTable() : NULL; if (!pOffenderEntity && pVictimEntity) { pOffenderEntity = pVictimEntity; offenderID = victimID; } m_entityCollisionRecords[victimID] = EntityCollisionRecord(offenderID, currentTime); if(victimVehicle) { victimVehicle->OnHit(hit); } else if (pVictimScript) { FRAME_PROFILER("Call to OnHit", gEnv->pSystem, PROFILE_GAME); if (!IsDead(victimActor, pVictimScript)) { if (IActor* offenderDriver = offenderVehicle ? offenderVehicle->GetDriver() : NULL) hit.shooterId = offenderDriver->GetEntityId(); DelegateServerHit(pVictimScript, hit, victimActor); } } } } } }
////////////////////////////////////////////////////////////////////////// //this respawns the active AI at their spawn locations void CCheckpointSystem::RespawnAI(XmlNodeRef data) { if(!data) return; XmlNodeRef actorData = data->findChild(ACTOR_FLAGS_SECTION); if(!actorData) { CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed reading actor data from checkpoint, actors won't be respawned"); return; } IActorSystem *pActorSystem = CCryAction::GetCryAction()->GetIActorSystem(); //first run through all actors and hide/deactivate them IActorIteratorPtr it = pActorSystem->CreateActorIterator(); while (IActor *pActor = it->Next()) { IEntity *pEntity = pActor->GetEntity(); //deactivate all actors pEntity->Hide(true); pEntity->Activate(false); } //load actorflags for active actors XmlNodeRef activatedActors = actorData->findChild(ACTIVATED_ACTORS_SECTION); if(activatedActors) { int actorFlags = activatedActors->getNumAttributes(); const char *key; const char *value; for(int i = 0; i < actorFlags; ++i) { activatedActors->getAttributeByIndex(i, &key, &value); //format is "idXXX" CRY_ASSERT(strlen(key)>2); EntityId id = (EntityId)(atoi(&key[2])); bool foundEntity = RepairEntityId(id, value); if(foundEntity) { IActor* pActor = pActorSystem->GetActor(id); if(pActor) { pActor->GetEntity()->Hide(false); pActor->GetEntity()->Activate(true); } else CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed finding actor %i from checkpoint.", (int)id); } else CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed finding actor %s from checkpoint, actor is not setup correctly.", value); } } else CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Deactivated actors section was missing in checkpoint."); it = pActorSystem->CreateActorIterator(); //iterate all actors and respawn if active while (IActor *pActor = it->Next()) { IEntity *pEntity = pActor->GetEntity(); if(pEntity->GetId() == LOCAL_PLAYER_ENTITY_ID) //don't respawn player continue; //we don't respawn deactivated actors if(!pEntity->IsHidden() && pEntity->IsActive()) { pActor->SetHealth(0); pActor->Respawn(); } else //but we still reset their position { pActor->ResetToSpawnLocation(); } } }
//------------------------------------------------------------------------ bool CGameRules::OnPromoteToServer(SHostMigrationInfo& hostMigrationInfo, uint32& state) { if (!g_pGame->GetIGameFramework()->ShouldMigrateNub(hostMigrationInfo.m_session)) { return true; } CryLogAlways("[Host Migration]: CGameRules::OnPromoteToServer() started"); // Server time will change after we migrate (change from old server time to new server time) m_gameStartedTime.SetValue(m_gameStartedTime.GetValue() - m_cachedServerTime.GetValue()); m_gameStartTime.SetValue(m_gameStartTime.GetValue() - m_cachedServerTime.GetValue()); // If this migration has reset (we're not the original anticipated host, remove any entities from the first attempt if (!m_hostMigrationCachedEntities.empty()) { HostMigrationRemoveDuplicateDynamicEntities(); } // Now we know we're the server, remove the actors for anyone we know isn't going to migrate CGameLobby *pGameLobby = g_pGame->GetGameLobby(); CRY_ASSERT(pGameLobby); if (pGameLobby) { TPlayers playersToRemove; IActorSystem *pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem(); playersToRemove.reserve(pActorSystem->GetActorCount()); IActorIteratorPtr actorIt = pActorSystem->CreateActorIterator(); IActor *pActor; while (pActor = actorIt->Next()) { if (pActor->IsPlayer()) { CRY_ASSERT(pActor->GetChannelId()); SCryMatchMakingConnectionUID conId = pGameLobby->GetConnectionUIDFromChannelID((int) pActor->GetChannelId()); if (pGameLobby->GetSessionNames().Find(conId) == SSessionNames::k_unableToFind) { CryLog(" player '%s' has not got a corresponding CGameLobby entry, removing actor", pActor->GetEntity()->GetName()); playersToRemove.push_back(pActor->GetEntityId()); } } } const int numPlayersToRemove = playersToRemove.size(); for (int i = 0; i < numPlayersToRemove; ++ i) { FakeDisconnectPlayer(playersToRemove[i]); } } for (uint32 i = 0; i < MAX_PLAYERS; ++ i) { m_migratedPlayerChannels[i] = 0; } IItemSystem *pItemSystem = g_pGame->GetIGameFramework()->GetIItemSystem(); IEntityItPtr it = gEnv->pEntitySystem->GetEntityIterator(); it->MoveFirst(); for (uint32 i = 0; i < m_hostMigrationItemMaxCount; ++ i) { m_pHostMigrationItemInfo[i].Reset(); } uint32 itemIndex = 0; IEntity *pEntity = NULL; while (pEntity = it->Next()) { IItem *pItem = pItemSystem->GetItem(pEntity->GetId()); if (pItem) { if (pItem->GetOwnerId()) { IEntity *pOwner = gEnv->pEntitySystem->GetEntity(pItem->GetOwnerId()); if (pOwner) { EntityId currentItemId = 0; IActor *pOwnerActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pOwner->GetId()); if (pOwnerActor) { IItem *pCurrentItem = pOwnerActor->GetCurrentItem(); currentItemId = pCurrentItem ? pCurrentItem->GetEntityId() : 0; } CryLog("[CG] Item '%s' is owned by '%s'", pEntity->GetName(), pOwner->GetName()); //m_pHostMigrationItemInfo[itemIndex].Set(pEntity->GetId(), pOwner->GetId(), pItem->IsUsed(), (pItem->GetEntityId() == currentItemId)); itemIndex ++; if (itemIndex >= m_hostMigrationItemMaxCount) { CRY_ASSERT(itemIndex < m_hostMigrationItemMaxCount); break; } } } } // Tell entities that we're host migrating // - Currently only used by ForbiddenArea but may well be needed for other entities later // - Currently only called on the new server, add to OnDemoteToClient if we need to use this on a client IScriptTable *pScript = pEntity->GetScriptTable(); if (pScript != NULL && pScript->GetValueType("OnHostMigration") == svtFunction) { m_pScriptSystem->BeginCall(pScript, "OnHostMigration"); m_pScriptSystem->PushFuncParam(pScript); m_pScriptSystem->PushFuncParam(true); m_pScriptSystem->EndCall(); } } // This needs initialising on the new server otherwise the respawn timer will be counting down // from uninitialised data. Likewise for the pre-round timer. ResetReviveCycleTime(); const int numRespawnParams = m_respawndata.size(); for (int i = 0; i < numRespawnParams; ++ i) { SEntityRespawnData *pData = &m_respawndata[i]; pEntity = gEnv->pEntitySystem->GetEntity(pData->m_currentEntityId); if (pEntity == NULL) { CryLog(" detected respawn entity (id=%u) is not present, scheduling for respawn", pData->m_currentEntityId); ScheduleEntityRespawn(pData->m_currentEntityId, false, g_pGameCVars->g_defaultItemRespawnTimer); } } CryLog("[Host Migration]: CGameRules::OnPromoteToServer() finished"); CCCPOINT(HostMigration_OnPromoteToServer); return true; }