//------------------------------------------------------------------------ void CGameRulesHoldObjectiveBase::InsideStateChanged(SHoldEntityDetails *pDetails) { pDetails->m_insideCount[0] = pDetails->m_insideEntities[0].size(); pDetails->m_insideCount[1] = pDetails->m_insideEntities[1].size(); int team1Count = pDetails->m_insideCount[0]; int team2Count = pDetails->m_insideCount[1]; int oldControllingTeamId = pDetails->m_controllingTeamId; DetermineControllingTeamId(pDetails, team1Count, team2Count); if( oldControllingTeamId != pDetails->m_controllingTeamId ) { OnControllingTeamChanged(pDetails, oldControllingTeamId); } CHANGED_NETWORK_STATE(g_pGame->GetGameRules(), HOLD_OBJECTIVE_STATE_ASPECT); OnInsideStateChanged(pDetails); }
//------------------------------------------------------------------------ void CGameRulesKingOfTheHillObjective::OnNewHoldEntity(SHoldEntityDetails *pDetails, int index) { CRY_ASSERT(index < HOLD_OBJECTIVE_MAX_ENTITIES); SKotHEntity *pKotHEntity = &m_additionalInfo[index]; pKotHEntity->Reset(); pDetails->m_pAdditionalData = pKotHEntity; if (gEnv->bServer) { g_pGame->GetGameRules()->SetTeam(0, pDetails->m_id); } if (gEnv->IsClient()) { pKotHEntity->m_needsIconUpdate = true; // Can't set icon straight away since the lua 'checkFunc' will give an incorrect result InitEntityAudio(pDetails); } OnInsideStateChanged(pDetails); // Cache radius pulse effect scale IEntity *pEntity = gEnv->pEntitySystem->GetEntity(pDetails->m_id); if (pEntity) { SmartScriptTable pScriptTable = pEntity->GetScriptTable(); if (pScriptTable) { SmartScriptTable pPropertiesTable; if (pScriptTable->GetValue("Properties", pPropertiesTable)) { float fRadiusEffectScale = 1.f; if (pPropertiesTable->GetValue("radiusEffectScale", fRadiusEffectScale)) { pKotHEntity->m_radiusEffectScale = fRadiusEffectScale; } } } } }
//------------------------------------------------------------------------ void CGameRulesHoldObjectiveBase::CheckLocalPlayerInside(SHoldEntityDetails *pDetails, const IEntity *pHoldEntity, const IEntity *pLocalPlayer) { const EntityId localPlayerId = pLocalPlayer->GetId(); const int teamId = g_pGame->GetGameRules()->GetTeam(localPlayerId); const int teamIdx = teamId - 1; if ((teamId == 1) || (teamId == 2)) { const Vec3 holdEntPos = pHoldEntity->GetWorldPos(); const Vec3 playerPos = pLocalPlayer->GetWorldPos(); const Vec3 diff = (playerPos - holdEntPos); // Check z first if ((diff.z >= pDetails->m_controlOffsetZ) && (diff.z <= (pDetails->m_controlOffsetZ + pDetails->m_controlHeight))) { // Now check x & y (box test) if ((fabs(diff.x) <= pDetails->m_controlRadius) && (fabs(diff.y) <= pDetails->m_controlRadius)) { stl::push_back_unique(pDetails->m_insideBoxEntities[teamIdx], localPlayerId); // Now check cylinder const float flatDistSqr = (diff.x * diff.x) + (diff.y * diff.y); if (flatDistSqr < pDetails->m_controlRadiusSqr) { // Player is inside pDetails->m_localPlayerIsWithinRange = true; OnLocalPlayerInsideStateChanged(pDetails); stl::push_back_unique(pDetails->m_insideEntities[teamIdx], localPlayerId); // Update actual objective implementation OnInsideStateChanged(pDetails); } } } } }
//------------------------------------------------------------------------ void CGameRulesHoldObjectiveBase::Update( float frameTime ) { if (m_bHasNetSerialized && !gEnv->bServer) { for (int i = 0; i < HOLD_OBJECTIVE_MAX_ENTITIES; ++ i) { SHoldEntityDetails *pDetails = &m_entities[i]; int oldControllingTeamId = pDetails->m_controllingTeamId; int oldTeam1Count = pDetails->m_insideCount[0]; int oldTeam2Count = pDetails->m_insideCount[1]; int team1Count = pDetails->m_serializedInsideCount[0]; int team2Count = pDetails->m_serializedInsideCount[1]; DetermineControllingTeamId(pDetails, team1Count, team2Count); if ((oldTeam1Count != team1Count) || (oldTeam2Count != team2Count)) { pDetails->m_insideCount[0] = team1Count; pDetails->m_insideCount[1] = team2Count; if (pDetails->m_id) { OnInsideStateChanged(pDetails); if (oldControllingTeamId != pDetails->m_controllingTeamId) { OnControllingTeamChanged(pDetails, oldControllingTeamId); } } } } m_bHasNetSerialized = false; } EntityId localPlayerId = g_pGame->GetIGameFramework()->GetClientActorId(); for (int i = 0; i < HOLD_OBJECTIVE_MAX_ENTITIES; ++ i) { SHoldEntityDetails *pDetails = &m_entities[i]; #ifndef _RELEASE DebugDrawCylinder(pDetails); #endif if (pDetails->m_id && pDetails->m_totalInsideBoxCount) { CheckCylinder(pDetails, localPlayerId); } else if (pDetails->m_pendingId) { DoAddEntityId(1, pDetails->m_pendingId, i, pDetails->m_isNewEntity); pDetails->m_pendingId = 0; pDetails->m_isNewEntity = false; } } UpdateEffect(frameTime); if (m_pStartingAnimSequence && gEnv->pMovieSystem) { m_deferredTrackViewTime -= frameTime; if (m_deferredTrackViewTime < 0.f) { CGameRules *pGameRules = g_pGame->GetGameRules(); const float currentTime = (pGameRules->GetServerTime() * 0.001f); const float timeStarted = m_pendingTimeAdded.GetSeconds(); const float timeSinceStarted = currentTime - timeStarted; const float playingTime = gEnv->pMovieSystem->GetPlayingTime(m_pStartingAnimSequence); CryLog("CGameRulesHoldObjectiveBase::Update() anim sequence %s at %f seconds (should be at least %f)", m_pStartingAnimSequence->GetName(), playingTime, timeSinceStarted); if (playingTime < timeSinceStarted) { gEnv->pMovieSystem->SetPlayingTime(m_pStartingAnimSequence, timeSinceStarted); } m_pStartingAnimSequence = NULL; } } }
//------------------------------------------------------------------------ void CGameRulesHoldObjectiveBase::CheckCylinder( SHoldEntityDetails *pDetails, EntityId localPlayerId ) { IEntity *pHoldEntity = gEnv->pEntitySystem->GetEntity(pDetails->m_id); if (pHoldEntity) { pDetails->m_totalInsideBoxCount = 0; const Vec3 &holdPos = pHoldEntity->GetPos(); bool hasChanged = false; bool localPlayerWithinRange = false; for (int teamIdx = 0; teamIdx < NUM_TEAMS; ++ teamIdx) { const int previousNumEntities = pDetails->m_insideEntities[teamIdx].size(); pDetails->m_insideEntities[teamIdx].clear(); const TEntityIdVec &boxEntities = pDetails->m_insideBoxEntities[teamIdx]; const int numBoxEntities = boxEntities.size(); pDetails->m_totalInsideBoxCount += numBoxEntities; for (int entIdx = 0; entIdx < numBoxEntities; ++ entIdx) { EntityId playerId = boxEntities[entIdx]; IEntity *pPlayer = gEnv->pEntitySystem->GetEntity(playerId); if (pPlayer) { //Make sure we're not in a vehicle for C3 if(IActor * pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(playerId)) { if(pActor->GetLinkedVehicle() != NULL) continue; } const Vec3 &playerPos = pPlayer->GetPos(); const float xDist = playerPos.x - holdPos.x; const float yDist = playerPos.y - holdPos.y; const float flatDistSqr = (xDist * xDist) + (yDist * yDist); if (flatDistSqr < pDetails->m_controlRadiusSqr) { pDetails->m_insideEntities[teamIdx].push_back(playerId); if (playerId == localPlayerId) { localPlayerWithinRange = true; } } } } if (pDetails->m_insideEntities[teamIdx].size() != previousNumEntities) { hasChanged = true; } } if (hasChanged) { if (localPlayerWithinRange != pDetails->m_localPlayerIsWithinRange) { if (localPlayerWithinRange) { pDetails->m_localPlayerIsWithinRange = true; CCCPOINT(HoldObjective_LocalPlayerEnterArea); } else { pDetails->m_localPlayerIsWithinRange = false; CCCPOINT(HoldObjective_LocalPlayerLeaveArea); } OnLocalPlayerInsideStateChanged(pDetails); } if (gEnv->bServer) { InsideStateChanged(pDetails); } else { OnInsideStateChanged(pDetails); } } } }