// IWeaponEventListener //--------------------------------------- void CMiscAnnouncer::OnShoot(IWeapon *pWeapon, EntityId shooterId, EntityId ammoId, IEntityClass* pAmmoType, const Vec3 &pos, const Vec3 &dir, const Vec3 &vel) { if(!ma_enabled || !AnnouncerRequired()) return; CWeapon *pWeaponImpl = static_cast<CWeapon*>(pWeapon); IEntityClass *pWeaponEntityClass = pWeaponImpl->GetEntity()->GetClass(); g_pGame->GetWeaponSystem()->GetWeaponAlias().UpdateClass(&pWeaponEntityClass); DbgLog("CMiscAnnouncer::OnShoot() pWeaponImpl=%s; shooter=%d; pAmmoType=%s", pWeaponImpl->GetEntity()->GetName(), g_pGame->GetGameRules()->GetEntityName(shooterId), pAmmoType->GetName()); TWeaponFiredMap::iterator it = m_weaponFiredMap.find(pWeaponEntityClass); if(it != m_weaponFiredMap.end()) { SOnWeaponFired &onWeaponFired = it->second; DbgLog("CMiscAnnouncer::OnShoot() has found the firing weaponClass in our weaponFiredMap. With announcement=%s", onWeaponFired.m_announcementName.c_str()); // we only want to play the announcement once each game/round IActor *pClientActor = gEnv->pGame->GetIGameFramework()->GetClientActor(); CGameRules *pGameRules = g_pGame->GetGameRules(); int clientTeam = pGameRules->GetTeam(pClientActor->GetEntityId()); int shooterTeam = pGameRules->GetTeam(shooterId); if (clientTeam == shooterTeam) { if (!onWeaponFired.m_havePlayedFriendly) { DbgLog("CMiscAnnouncer::OnShoot() we've not played this friendly annoucement already. Let's do it"); CAnnouncer::GetInstance()->Announce(shooterId, onWeaponFired.m_announcementID, CAnnouncer::eAC_inGame); } else { DbgLog("CMiscAnnouncer::OnShoot() we've already played this friendly announcement. Not playing again"); } onWeaponFired.m_havePlayedFriendly = true; } else { if (!onWeaponFired.m_havePlayedEnemy) { DbgLog("CMiscAnnouncer::OnShoot() we've not played this enemy announcement already. Let's do it"); CAnnouncer::GetInstance()->Announce(shooterId, onWeaponFired.m_announcementID, CAnnouncer::eAC_inGame); } else { DbgLog("CMiscAnnouncer::OnShoot() we've already played this enemy announcement. Not playing again."); } onWeaponFired.m_havePlayedEnemy = true; } } }
bool AllowedToTargetPlayer(const EntityId attackerId, const EntityId victimEntityId) { CGameRules *pGameRules = g_pGame->GetGameRules(); if(pGameRules && pGameRules->IsTeamGame()) { const int clientTeamId = pGameRules->GetTeam(attackerId); const int victimTeamId = pGameRules->GetTeam(victimEntityId); return (clientTeamId != victimTeamId) || (g_pGameCVars->g_friendlyfireratio > 0.0f); } return true; }
float CGameRulesMPDamageHandling::CalculateFriendlyFireRatio(EntityId entityId1, EntityId entityId2) { CGameRules *pGameRules = m_pGameRules; if (entityId1 != entityId2 && pGameRules->GetTeamCount() > 1) { int team1 = pGameRules->GetTeam(entityId1); if( team1 == pGameRules->GetTeam(entityId2) ) { return pGameRules->GetFriendlyFireRatio(); } } //Not on same team so full damage return 1.f; }
bool CHUDCrosshair::IsFriendlyEntity(IEntity *pEntity) { IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor(); CGameRules *pGameRules = g_pGame->GetGameRules(); if(!pEntity || !pClientActor || !pGameRules) return false; // Less than 2 teams means we are in a FFA based game. if(pGameRules->GetTeamCount() < 2) return false; bool bFriendly = false; int iClientTeam = pGameRules->GetTeam(pClientActor->GetEntityId()); // First, check if entity is a player IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId()); if(pActor && pActor->IsPlayer()) { if(iClientTeam && (pGameRules->GetTeam(pActor->GetEntityId()) == iClientTeam)) { bFriendly = true; } } else { // Then, check if entity is a vehicle IVehicle *pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(pEntity->GetId()); if(pVehicle && pGameRules->GetTeam(pVehicle->GetEntityId()) == iClientTeam && pVehicle->GetStatus().passengerCount) { IActor *pDriver = pVehicle->GetDriver(); /*if(pDriver && pGameRules->GetTeam(pDriver->GetEntityId()) == iClientTeam) bFriendly = true; else bFriendly = false;*/ bFriendly = true; //fix for bad raycast if(pDriver && pDriver == pClientActor) bFriendly = false; } } return bFriendly; }
//--------------------------------------- //Returns signal index of 0 (for team 0 and 1) and 1 for team 2 int CAreaAnnouncer::GetAreaAnnouncerTeamIndex(const EntityId clientId) { int team = 0; CGameRules* pGameRules = g_pGame->GetGameRules(); if(pGameRules) { team = pGameRules->GetTeam(clientId); } return CLAMP(team - 1, 0, AREA_ANNOUNCERS - 1); }
bool CHUDTagNames::IsFriendlyToClient(EntityId uiEntityId) { IActor *client = g_pGame->GetIGameFramework()->GetClientActor(); CGameRules *pGameRules = g_pGame->GetGameRules(); if(!client || !pGameRules) return false; int playerTeam = pGameRules->GetTeam(client->GetEntityId()); // if this actor is spectating, use the team of the player they are spectating instead... if(static_cast<CActor*>(client)->GetSpectatorMode() == CActor::eASM_Follow) { playerTeam = pGameRules->GetTeam(static_cast<CActor*>(client)->GetSpectatorTarget()); } // Less than 2 teams means we are in a FFA based game. if(pGameRules->GetTeam(uiEntityId) == playerTeam && pGameRules->GetTeamCount() > 1) return true; return false; }
void CDangerousRigidBody::ProcessEvent( SEntityEvent& event ) { switch(event.event) { case ENTITY_EVENT_COLLISION: { if(m_dangerous) { EventPhysCollision *pCollision = (EventPhysCollision *)(event.nParam[0]); if(pCollision->pEntity[0] && pCollision->pEntity[1]) { IPhysicalEntity* pOtherEntityPhysics = GetEntity()->GetPhysics() != pCollision->pEntity[0] ? pCollision->pEntity[0] : pCollision->pEntity[1]; if( IEntity* pOtherEntity = gEnv->pEntitySystem->GetEntityFromPhysics(pOtherEntityPhysics) ) { EntityId localClientId = gEnv->pGame->GetIGameFramework()->GetClientActorId(); if(pOtherEntity->GetId() == localClientId) //Handle collision locally { float currentTime = gEnv->pTimer->GetFrameStartTime().GetSeconds(); if(currentTime - m_lastHitTime > m_timeBetweenHits) { CGameRules* pGameRules = g_pGame->GetGameRules(); bool sameTeam = m_activatorTeam && (pGameRules->GetTeam(localClientId) == m_activatorTeam); float damageDealt = !sameTeam ? m_damageDealt : g_pGameCVars->g_friendlyfireratio * m_damageDealt; Vec3 rigidBodyPos = GetEntity()->GetWorldPos(); HitInfo hitInfo(0, localClientId, 0, damageDealt, 0.0f, 0, 0, sDangerousRigidBodyHitTypeId, rigidBodyPos, (pOtherEntity->GetWorldPos()-rigidBodyPos).GetNormalized(), Vec3(ZERO)); pGameRules->ClientHit(hitInfo); m_lastHitTime = currentTime; } } } } } } break; case ENTITY_EVENT_RESET: { Reset(); } break; } }
void CServerPlayerTracker::KillOccurred(const HitInfo &hitInfo, uint16 victimChannelId, bool bExpectKillCam) { if(hitInfo.targetId != GetEntityId() && bExpectKillCam) //We don't expect killcams when a player kills themselves { SKillCamValidation& victimData = GetOrCreateVictimData(victimChannelId); victimData.vLastKillDir = hitInfo.dir; victimData.uKills++; victimData.fLastKillTime = gEnv->pTimer->GetCurrTime(); } CGameRules * pGameRules = g_pGame->GetGameRules(); CGameRules::eThreatRating threatRating = pGameRules->GetThreatRatingByTeam(pGameRules->GetTeam(hitInfo.targetId), pGameRules->GetTeam(GetEntityId())); if(threatRating == CGameRules::eHostile) { m_nTotalHostileKills++; } }
void CUIObjectives::OnRequestMissionObjectives( const SUIEvent& event ) { CGameRules* pGameRules = GetGameRules(); if ( pGameRules && g_pGame->GetIGameFramework()->GetClientActor() ) { CActor* pActor = pGameRules->GetActorByChannelId( g_pGame->GetIGameFramework()->GetClientActor()->GetChannelId() ); if ( pActor ) { std::map< string, int > tmpList; int teamID = pGameRules->GetTeam( pActor->GetEntityId() ); for ( TObjectiveMap::iterator it = m_ObjectiveMap.begin(); it != m_ObjectiveMap.end(); ++it ) { CGameRules::TObjective* pObjective = pGameRules->GetObjective( teamID, it->first.c_str() ); if ( pObjective ) tmpList[ it->first ] = pObjective->status; } for ( std::map< string, int >::iterator it = tmpList.begin(); it != tmpList.end(); ++it ) MissionObjectiveAdded( it->first, it->second ); } } }
//------------------------------------------------------------------------ EGameRulesMissionObjectives CGameRulesKingOfTheHillObjective::GetIcon( SHoldEntityDetails *pDetails, const char **ppOutName, const char **ppOutColour ) { SKotHEntity *pKotHEntity = static_cast<SKotHEntity*>(pDetails->m_pAdditionalData); CRY_ASSERT(pKotHEntity); EGameRulesMissionObjectives requestedIcon = EGRMO_Unknown; if (!pDetails->m_id) { requestedIcon = EGRMO_Unknown; } else { bool iconAllowed = true; if (!m_shouldShowIconFunc.empty()) { IEntity *pEntity = gEnv->pEntitySystem->GetEntity(pDetails->m_id); if (pEntity) { IScriptTable *pEntityScript = pEntity->GetScriptTable(); HSCRIPTFUNCTION iconCheckFunc; if (pEntityScript != NULL && pEntityScript->GetValue(m_shouldShowIconFunc.c_str(), iconCheckFunc)) { IScriptSystem *pScriptSystem = gEnv->pScriptSystem; bool result = false; if (Script::CallReturn(pScriptSystem, iconCheckFunc, pEntityScript, result)) { if (!result) { requestedIcon = EGRMO_Unknown; iconAllowed = false; } } } } } if (iconAllowed) { const char *pFriendlyColour = "#9AD5B7"; const char *pHostileColour = "#AC0000"; const char *pNeutralColour = "#666666"; CGameRules *pGameRules = g_pGame->GetGameRules(); int localTeamId = pGameRules->GetTeam(g_pGame->GetIGameFramework()->GetClientActorId()); if ( (pDetails->m_controllingTeamId == 0) ) { requestedIcon = m_neutralIcon; *ppOutName = m_iconTextCapture.c_str(); *ppOutColour = pNeutralColour; } else if( (pDetails->m_controllingTeamId == CONTESTED_TEAM_ID) ) { requestedIcon = m_contestedIcon; *ppOutName = m_iconTextClear.c_str(); *ppOutColour = pHostileColour; } else if (pDetails->m_controllingTeamId == localTeamId) { requestedIcon = m_friendlyIcon; *ppOutName = m_iconTextDefend.c_str(); *ppOutColour = pFriendlyColour; } else { requestedIcon = m_hostileIcon; *ppOutName = m_iconTextClear.c_str(); *ppOutColour = pHostileColour; } } } return requestedIcon; }
//------------------------------------------------------------------------ void CGameRulesKingOfTheHillObjective::ClSiteChangedOwner( SHoldEntityDetails *pDetails, int oldTeamId ) { // Site has been captured CGameRules *pGameRules = g_pGame->GetGameRules(); EntityId clientActorId = g_pGame->GetIGameFramework()->GetClientActorId(); int localTeam = pGameRules->GetTeam(clientActorId); SKotHEntity *pKotHEntity = static_cast<SKotHEntity*>(pDetails->m_pAdditionalData); CRY_ASSERT(pKotHEntity); const int ownerTeamId = pDetails->m_controllingTeamId; if (ownerTeamId > 0) { ClSiteChangedOwnerAnnouncement(pDetails, clientActorId, ownerTeamId, localTeam); if (localTeam == ownerTeamId) { CCCPOINT(KingOfTheHillObjective_SiteCapturedByFriendlyTeam); if (!m_friendlyCaptureString.empty()) { SHUDEventWrapper::GameStateNotify(m_friendlyCaptureString.c_str()); } if (!m_gameStateFriendlyString.empty()) { const char *localisedMessage = CHUDUtils::LocalizeString(m_gameStateFriendlyString.c_str()); SHUDEventWrapper::OnGameStatusUpdate(eGBNFLP_Good, localisedMessage); } } else { CCCPOINT(KingOfTheHillObjective_SiteCapturedByEnemyTeam); if (!m_enemyCaptureString.empty()) { SHUDEventWrapper::GameStateNotify(m_enemyCaptureString.c_str()); } if (!m_gameStateEnemyString.empty()) { const char *localisedMessage = CHUDUtils::LocalizeString(m_gameStateEnemyString.c_str()); SHUDEventWrapper::OnGameStatusUpdate(eGBNFLP_Bad, localisedMessage); } } } else if (oldTeamId > 0) { if (localTeam == oldTeamId) { CCCPOINT(KingOfTheHillObjective_SiteLostByFriendlyTeam); if (!m_friendlyLostString.empty()) { SHUDEventWrapper::GameStateNotify(m_friendlyLostString.c_str()); } } else { CCCPOINT(KingOfTheHillObjective_SiteLostByEnemyTeam); if (!m_enemyLostString.empty()) { SHUDEventWrapper::GameStateNotify(m_enemyLostString.c_str()); } } if (!m_gameStateNeutralString.empty()) { const char *localisedMessage = CHUDUtils::LocalizeString(m_gameStateNeutralString.c_str()); SHUDEventWrapper::OnGameStatusUpdate(eGBNFLP_Neutral, localisedMessage); } } int currActiveIndex = -1; for (int i = 0; i < HOLD_OBJECTIVE_MAX_ENTITIES; i ++) { if( !m_entities[i].m_id) { continue; } ++currActiveIndex; if( &m_entities[i] != pDetails ) { continue; } CRY_TODO( 23,03,2010, "HUD: OnSiteCaptured events are being sent multiple times from multiple places. /FH"); SHUDEvent siteIsCaptured(eHUDEvent_OnSiteCaptured); siteIsCaptured.eventIntData = currActiveIndex; siteIsCaptured.eventIntData2 = ownerTeamId; CHUDEventDispatcher::CallEvent(siteIsCaptured); } }
//------------------------------------------------------------------------ void CGameRulesKingOfTheHillObjective::Update( float frameTime ) { BaseType::Update(frameTime); CGameRules *pGameRules = g_pGame->GetGameRules(); IGameRulesScoringModule *pScoringModule = pGameRules->GetScoringModule(); const int localTeamId = pGameRules->GetTeam(g_pGame->GetIGameFramework()->GetClientActorId()); for (int i = 0; i < HOLD_OBJECTIVE_MAX_ENTITIES; ++ i) { SHoldEntityDetails *pDetails = &m_entities[i]; if (!pDetails->m_id) { continue; } SKotHEntity *pKotHEntity = static_cast<SKotHEntity *>(pDetails->m_pAdditionalData); CRY_ASSERT(pKotHEntity); if (gEnv->bServer && pScoringModule) { #ifndef _RELEASE if (g_pGameCVars->g_KingOfTheHillObjective_watchLvl) { IEntity *pEntity = gEnv->pEntitySystem->GetEntity(pDetails->m_id); const char *pEntName = pEntity ? pEntity->GetName() : "<NULL>"; if (pDetails->m_controllingTeamId == CONTESTED_TEAM_ID) { CryWatch("KotH entity '%s' is contested", pEntName); } else if (pDetails->m_controllingTeamId == 0) { CryWatch("KotH entity '%s' has no players nearby", pEntName); } else { CryWatch("KotH entity '%s' controlled by team %i, scoreTimerLength='%.2f', timeSinceLastScore='%.2f'", pEntName, pDetails->m_controllingTeamId, pKotHEntity->m_scoreTimerLength, pKotHEntity->m_timeSinceLastScore); } } #endif if (pKotHEntity->m_scoringTeamId) { const int teamIndex = pKotHEntity->m_scoringTeamId - 1; CRY_ASSERT_MESSAGE(teamIndex >= 0 && teamIndex < NUM_TEAMS, "Update() scoringTeamId is out of range"); pKotHEntity->m_timeSinceLastScore += frameTime; if (pKotHEntity->m_timeSinceLastScore >= pKotHEntity->m_scoreTimerLength) { pScoringModule->OnTeamScoringEvent(teamIndex + 1, EGRST_KingOfTheHillObjectiveHeld); pKotHEntity->m_timeSinceLastScore = 0.f; AwardPlayerPoints(&pDetails->m_insideEntities[teamIndex], EGRST_KingOfTheHillObjectiveHeld); CCCPOINT_IF((pKotHEntity->m_scoringTeamId == 1), KingOfTheHillObjective_TeamMarinesScored); CCCPOINT_IF((pKotHEntity->m_scoringTeamId == 2), KingOfTheHillObjective_TeamCellScored); } } } if (gEnv->IsClient()) { if (m_useIcons && pKotHEntity->m_needsIconUpdate) { UpdateIcon(pDetails); } if (pGameRules->GetGameMode() == eGM_CrashSite) { if (pDetails->m_localPlayerIsWithinRange && pDetails->m_controllingTeamId != CONTESTED_TEAM_ID) { CPersistantStats::GetInstance()->IncrementClientStats(EFPS_CrashSiteHeldTime, frameTime); } } if (pKotHEntity->m_bPulseEnabled) { pKotHEntity->m_pulseTime -= frameTime; if (pKotHEntity->m_pulseTime < 0.f) { eRadiusPulseType pulseType = GetPulseType(pDetails); const float radiusEffectScale = pKotHEntity->m_radiusEffectScale * pDetails->m_controlRadius; RadiusEffectPulse(pDetails->m_id, pulseType, radiusEffectScale); pKotHEntity->m_pulseTime = m_pulseTimerLength; } } else { if (!m_shouldDoPulseEffectFunc.empty()) { IEntity *pEntity = gEnv->pEntitySystem->GetEntity(pDetails->m_id); if (pEntity) { IScriptTable *pEntityScript = pEntity->GetScriptTable(); HSCRIPTFUNCTION pulseCheckFunc; if (pEntityScript != NULL && pEntityScript->GetValue(m_shouldDoPulseEffectFunc.c_str(), pulseCheckFunc)) { IScriptSystem *pScriptSystem = gEnv->pScriptSystem; bool result = false; if (Script::CallReturn(pScriptSystem, pulseCheckFunc, pEntityScript, result)) { pKotHEntity->m_bPulseEnabled = result; } } } } } const float fOldScoringSFX = pKotHEntity->m_fScoringSFX; if(pKotHEntity->m_scoringTeamId) { pKotHEntity->m_fScoringSFX = min(pKotHEntity->m_fScoringSFX + (frameTime * 2.0f), 1.0f); } else { pKotHEntity->m_fScoringSFX = max(pKotHEntity->m_fScoringSFX - (frameTime * 1.0f), 0.0f); } if(pKotHEntity->m_fScoringSFX != fOldScoringSFX) UpdateEntityAudio(pDetails); } } }
void CHUDTagNames::DrawTagName(IVehicle *pVehicle) { CRY_ASSERT(pVehicle); if(!pVehicle) return; CActor *pClientActor = static_cast<CActor *>(g_pGame->GetIGameFramework()->GetClientActor()); CGameRules *pGameRules = g_pGame->GetGameRules(); int iClientTeam = pGameRules->GetTeam(pClientActor->GetEntityId()); bool bThirdPerson = pClientActor->IsThirdPerson(); bool bDrawSeatTagNames = false; if(pClientActor->GetSpectatorMode() == CActor::eASM_Follow) { IActor *pFollowedActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pClientActor->GetSpectatorTarget()); if(pFollowedActor) bDrawSeatTagNames = (pVehicle == pFollowedActor->GetLinkedVehicle()); } else bDrawSeatTagNames = (pVehicle == pClientActor->GetLinkedVehicle()); if(bDrawSeatTagNames) { // When this is local player vehicle, we always display all passengers name above their head so that he can identify them for(int iSeatId=1; iSeatId<=pVehicle->GetLastSeatId(); iSeatId++) { IVehicleSeat *pVehicleSeat = pVehicle->GetSeatById(iSeatId); if(!pVehicleSeat) continue; IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pVehicleSeat->GetPassenger()); if(!pActor || (pActor == pClientActor && !bThirdPerson)) continue; DrawTagName(pActor,true); } return; } ColorF rgbTagName = COLOR_ENEMY; // Driver seat is always 1 IVehicleSeat *pVehicleSeat = pVehicle->GetSeatById(1); if(!pVehicleSeat) return; IVehicleHelper *pVehicleHelper = pVehicleSeat->GetSitHelper(); if(!pVehicleHelper) return; Vec3 vWorldPos = pVehicleHelper->GetWorldTM().GetTranslation(); // Add some offset to be above the driver/pilot vWorldPos.z += 1.2f; AABB box; pVehicle->GetEntity()->GetWorldBounds(box); bool bDrawOnTop = false; if(ProjectOnSphere(vWorldPos,box)) { bDrawOnTop = true; } m_tagNamesVector.resize(0); for(int iSeatId=1; iSeatId<=pVehicle->GetLastSeatId(); iSeatId++) { IVehicleSeat *pVehicleSeat = pVehicle->GetSeatById(iSeatId); if(!pVehicleSeat) continue; EntityId uiEntityId = pVehicleSeat->GetPassenger(); IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(uiEntityId); if(!pActor) continue; const char *szRank = GetPlayerRank(uiEntityId); IEntity *pEntity = pActor->GetEntity(); if(!pEntity) continue; char szText[HUD_MAX_STRING_SIZE]; if(szRank) { sprintf(szText,"%s %s",szRank,pEntity->GetName()); } else { sprintf(szText,"%s",pEntity->GetName()); } if(0 == iClientTeam) { if(uiEntityId && IsFriendlyToClient(uiEntityId)) { rgbTagName = COLOR_FRIEND; } } else if(uiEntityId && pGameRules->GetTeam(uiEntityId) == iClientTeam) { rgbTagName = COLOR_FRIEND; } if(pActor->GetHealth() <= 0) { rgbTagName = COLOR_DEAD; } m_tagNamesVector.resize(m_tagNamesVector.size()+1); STagName *pTagName = &m_tagNamesVector[m_tagNamesVector.size()-1]; pTagName->strName = szText; pTagName->vWorld = vWorldPos; pTagName->bDrawOnTop = bDrawOnTop; pTagName->rgb = rgbTagName; } DrawTagNames(); }
void CHUDTagNames::Update() { CActor *pClientActor = static_cast<CActor *>(g_pGame->GetIGameFramework()->GetClientActor()); CGameRules *pGameRules = g_pGame->GetGameRules(); if(!pClientActor || !pGameRules || !gEnv->bMultiplayer) return; int iClientTeam = pGameRules->GetTeam(pClientActor->GetEntityId()); // Skip enemies, they need to be added only when shot // (except in spectator mode when we display everyone) for(int iTeam = 0; iTeam < pGameRules->GetTeamCount() + 1; ++iTeam) { if((iTeam == iClientTeam) || (pClientActor->GetSpectatorMode() != CActor::eASM_None)) { int iTeamPlayerCount = pGameRules->GetTeamPlayerCount(iTeam); for(int iPlayer=0; iPlayer<iTeamPlayerCount; iPlayer++) { IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pGameRules->GetTeamPlayer(iTeam,iPlayer)); if(!pActor) continue; // Never display the local player if(pActor == pClientActor) continue; // never display other spectators if(static_cast<CActor*>(pActor)->GetSpectatorMode() != CActor::eASM_None) continue; // never display the name of the player we're spectating (it's shown separately with their current health) if(pClientActor->GetSpectatorMode() == CActor::eASM_Follow && pClientActor->GetSpectatorTarget() == pActor->GetEntityId()) continue; DrawTagName(pActor); } } } IVehicleSystem *pVehicleSystem = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem(); if(!pVehicleSystem) return; IVehicleIteratorPtr pVehicleIter = pVehicleSystem->CreateVehicleIterator(); while(IVehicle *pVehicle=pVehicleIter->Next()) { SVehicleStatus rVehicleStatus = pVehicle->GetStatus(); if(0 == rVehicleStatus.passengerCount) continue; // Skip enemy vehicles, they need to be added only when shot (except in spectator mode...) bool bEnemyVehicle = true; for(int iSeatId=1; iSeatId<=pVehicle->GetLastSeatId(); iSeatId++) { IVehicleSeat *pVehicleSeat = pVehicle->GetSeatById(iSeatId); if(!pVehicleSeat) continue; EntityId uiEntityId = pVehicleSeat->GetPassenger(); if(0 == iClientTeam) { if(uiEntityId && IsFriendlyToClient(uiEntityId)) { bEnemyVehicle = false; } } else if(uiEntityId && pGameRules->GetTeam(uiEntityId) == iClientTeam) { bEnemyVehicle = false; } } if(bEnemyVehicle && (pClientActor->GetSpectatorMode() == CActor::eASM_None)) // again, draw enemies in spectator mode continue; DrawTagName(pVehicle); } // don't need to do any of this if we're in spectator mode - all player names will have been drawn above. if(pClientActor->GetSpectatorMode() == CActor::eASM_None) { for(TEnemyTagNamesList::iterator iter=m_enemyTagNamesList.begin(); iter!=m_enemyTagNamesList.end(); ++iter) { SEnemyTagName *pEnemyTagName = &(*iter); if(gEnv->pTimer->GetAsyncTime().GetSeconds() >= pEnemyTagName->fSpawnTime+((float) g_pGameCVars->hud_mpNamesDuration)) { // Note: iter=my_list.erase(iter) may not be standard/safe TEnemyTagNamesList::iterator iterNext = iter; ++iterNext; m_enemyTagNamesList.erase(iter); iter = iterNext; } else { IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEnemyTagName->uiEntityId); if(pActor) DrawTagName(pActor); IVehicle *pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(pEnemyTagName->uiEntityId); if(pVehicle) DrawTagName(pVehicle); } } } }
//------------------------------------------------------------------------ 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); } } } } } }
float CGameRulesMPDamageHandling::ProcessActorKickedVehicle(IActor* victimActor, EntityId victimId, EntityId kickerId, EntityId vehicleId, float damage, const CGameRules::SCollisionHitInfo& collisionHitInfo) { float angSpeedSq = 0.f; const IEntity* pVehicleEntity = gEnv->pEntitySystem->GetEntity(vehicleId); if (pVehicleEntity) { IPhysicalEntity* pent = pVehicleEntity->GetPhysics(); if (pent) { pe_status_dynamics psd; if (pent->GetStatus(&psd)) { angSpeedSq = psd.w.GetLengthSquared(); } } } const Vec3& actorVelocity = collisionHitInfo.velocity; const Vec3& vehicleVelocity = collisionHitInfo.target_velocity; const float vehicleSpeedSq = vehicleVelocity.GetLengthSquared() + angSpeedSq; if (vehicleSpeedSq < 1.5f) return 0.f; float damageScale = 1.f; if (g_pGameCVars->g_mpKickableCars) { if (kickerId==victimId || FindKickableCarRecord(vehicleId, victimId)) return 0.f; CGameRules *pGameRules = g_pGame->GetGameRules(); if (pGameRules->GetTeamCount() > 1) { int kickerTeamId = pGameRules->GetTeam(kickerId); int victimTeamId = pGameRules->GetTeam(victimId); if (kickerTeamId==victimTeamId) // Friendly fire { float friendlyFireRatio = pGameRules->GetFriendlyFireRatio(); if (friendlyFireRatio>0.f) { damageScale = friendlyFireRatio; } else { return 0.f; } } } InsertKickableCarRecord(vehicleId, victimId); } // Damage, for now, is based purely on vehicle speed const float vehicleKillSpeed = m_vehicleDamageSettings.killSpeed; const float invVehicleKillSpeed = 1.f/(vehicleKillSpeed+0.01f); const float maxActorHealth = victimActor->GetMaxHealth(); damage = 0.1f + sqrtf(vehicleSpeedSq+0.04f) * invVehicleKillSpeed; damage = min(damage, 1.f) * maxActorHealth * damageScale; return damage; }
void CPlayerRotation::TargetAimAssistance(CWeapon* pWeapon, float& followH, float& followV, float& scale, float& _fZoomAmount, const Vec3 playerView[4]) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); CRY_ASSERT(m_player.IsClient()); followH = 0.0f; followV = 0.0f; scale = 1.0f; float bestScale = 1.0f; const Vec3 playerFwd = playerView[1]; const Vec3 playerRgt = playerView[0]; const Vec3 playerUp = playerView[2]; const Vec3 playerPos = playerView[3]; Vec3 follow_target_pos(ZERO); float follow_vote_leader = 0.0f; float snap_vote_leader = 0.0f; Vec3 follow_target_dir(ZERO); Vec3 snap_target_dir(ZERO); EntityId follow_target_id = 0; EntityId snap_target_id = 0; CGameRules * pGameRules = g_pGame->GetGameRules(); float distance_follow_threshold_near = max(0.0f, g_pGameCVars->aim_assistMinDistance); float distance_follow_threshold_far = max(20.0f, g_pGameCVars->aim_assistMaxDistance); int playerTeam = pGameRules->GetTeam(m_player.GetEntity()->GetId()); float cloakedPlayerMultiplier = g_pGameCVars->pl_aim_cloaked_multiplier; const bool multipleTeams = pGameRules->GetTeamCount() > 0; const float fFollowFalloffDist = g_pGameCVars->aim_assistFalloffDistance + FLT_EPSILON*g_pGameCVars->aim_assistFalloffDistance; const bool playerIsScoped = m_player.GetActorStats()->isScoped; float minTurnScale, fAimAssistStrength, fMaxDistMult; if(pWeapon) { const float fZoomAmount = pWeapon->GetZoomTransition(); _fZoomAmount = fZoomAmount; const float fStrength = g_pGameCVars->aim_assistStrength; const float fStrengthIronSight = playerIsScoped ? g_pGameCVars->aim_assistStrength_SniperScope : g_pGameCVars->aim_assistStrength_IronSight; const float fDiff = fStrengthIronSight - fStrength; fAimAssistStrength = fStrength + (fZoomAmount * fDiff); const float fMinTurn = g_pGameCVars->aim_assistMinTurnScale; const float fMinTurnIronSight = playerIsScoped ? g_pGameCVars->aim_assistMinTurnScale_SniperScope : g_pGameCVars->aim_assistMinTurnScale_IronSight; const float fMinTurnDiff = fMinTurnIronSight - fMinTurn; minTurnScale = fMinTurn + (fZoomAmount * fMinTurnDiff); const float fMaxAssistDist = g_pGameCVars->aim_assistMaxDistance; const float fMaxAssistDist_Iron = playerIsScoped ? g_pGameCVars->aim_assistMaxDistance_SniperScope : g_pGameCVars->aim_assistMaxDistance_IronSight; const float fMaxAssistDistDiff = (fMaxAssistDist_Iron - fMaxAssistDist) * fZoomAmount; fMaxDistMult = (fMaxAssistDist + fMaxAssistDistDiff) * __fres(fMaxAssistDist); } else { _fZoomAmount = 0.0f; fMaxDistMult = 1.0f; fAimAssistStrength = g_pGameCVars->aim_assistStrength; minTurnScale = g_pGameCVars->aim_assistMinTurnScale; } const float falloffStartDistance = g_pGameCVars->aim_assistSlowFalloffStartDistance; const float falloffPerMeter = 1.0f / (g_pGameCVars->aim_assistSlowDisableDistance - falloffStartDistance); const TAutoaimTargets& aaTargets = g_pGame->GetAutoAimManager().GetAutoAimTargets(); const int targetCount = aaTargets.size(); float fBestTargetDistance = FLT_MAX; #if DBG_AUTO_AIM SAuxGeomRenderFlags oldFlags = gEnv->pRenderer->GetIRenderAuxGeom()->GetRenderFlags(); SAuxGeomRenderFlags newFlags = e_Def3DPublicRenderflags; newFlags.SetAlphaBlendMode(e_AlphaBlended); newFlags.SetDepthTestFlag(e_DepthTestOff); newFlags.SetCullMode(e_CullModeNone); gEnv->pRenderer->GetIRenderAuxGeom()->SetRenderFlags(newFlags); #endif for (int i = 0; i < targetCount; ++i) { const SAutoaimTarget& target = aaTargets[i]; CRY_ASSERT(target.entityId != m_player.GetEntityId()); //Skip friendly ai if(gEnv->bMultiplayer) { if(multipleTeams && (pGameRules->GetTeam(target.entityId) == playerTeam)) { continue; } } else { if (target.HasFlagSet(eAATF_AIHostile) == false) continue; distance_follow_threshold_far = fMaxDistMult * (target.HasFlagSet(eAATF_AIRadarTagged) ? g_pGameCVars->aim_assistMaxDistanceTagged : g_pGameCVars->aim_assistMaxDistance); } Vec3 targetPos = target.primaryAimPosition; Vec3 targetDistVec = (targetPos - playerPos); float distance = targetDistVec.GetLength(); if (distance <= 0.1f) continue; Vec3 dirToTarget = targetDistVec / distance; // fast reject everything behind player, too far away or too near from line of view // sort rest by angle to crosshair and distance from player float alignment = playerFwd * dirToTarget; if (alignment <= 0.0f) continue; if ((distance < distance_follow_threshold_near) || (distance > distance_follow_threshold_far)) continue; const int kAutoaimVisibilityLatency = 2; CPlayerVisTable::SVisibilityParams visParams(target.entityId); visParams.queryParams = eVQP_IgnoreGlass; if (!g_pGame->GetPlayerVisTable()->CanLocalPlayerSee(visParams, kAutoaimVisibilityLatency)) { // Since both player and target entities are ignored, and the ray still intersected something, there's something in the way. // Need to profile this and see if it's faster to do the below checks before doing the linetest. It's fairly expensive but // linetests generally are as well... - Richard continue; } #if DBG_AUTO_AIM const ColorB green(0,255,0,255); const ColorB darkgreen(0,155,0,225); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine( playerPos, darkgreen, targetPos, green); #endif const float angleDot = dirToTarget.dot(-playerRgt); const float angle = (RAD2DEG(acos_tpl(angleDot)) - 90.f); const float absAngle = fabsf(angle); const float angleDotV = playerUp.dot(dirToTarget); const float angleToTargetV = (RAD2DEG(acos_tpl(angleDotV)) - 90.f); const float absAngleV = fabsf(angleToTargetV); const float slowModifiedDistance = distance * g_pGameCVars->aim_assistSlowDistanceModifier; const float radius_slow_threshold_inner = 0.5f; const float radius_slow_threshold_outer = g_pGameCVars->aim_assistSlowThresholdOuter; const float angle_slow_threshold_inner = RAD2DEG(atan_tpl(radius_slow_threshold_inner / slowModifiedDistance)); const float angle_slow_threshold_outer = RAD2DEG(atan_tpl(radius_slow_threshold_outer / slowModifiedDistance)); float angle_slow_fractionH = clamp_tpl((absAngle - angle_slow_threshold_inner) / (angle_slow_threshold_outer - angle_slow_threshold_inner), 0.0f, 1.0f); float angle_slow_fractionV = clamp_tpl((absAngleV - angle_slow_threshold_inner) / (angle_slow_threshold_outer - angle_slow_threshold_inner), 0.0f, 1.0f); float angle_slow_fraction = max(angle_slow_fractionH, angle_slow_fractionV); const float distance_follow_fraction = clamp_tpl((distance - fFollowFalloffDist) / (distance_follow_threshold_far - fFollowFalloffDist), 0.0f, 1.0f); const float radius_follow_threshold_inner = target.innerRadius; const float radius_follow_threshold_outer = target.outerRadius; const float radius_snap = target.HasFlagSet(eAATF_AIRadarTagged) ? target.snapRadiusTagged * g_pGameCVars->aim_assistSnapRadiusTaggedScale : target.snapRadius * g_pGameCVars->aim_assistSnapRadiusScale; const float angle_follow_threshold_inner = RAD2DEG(atan_tpl(radius_follow_threshold_inner / distance)); const float angle_follow_threshold_outer = RAD2DEG(atan_tpl(radius_follow_threshold_outer / distance)); const float angle_follow_fraction = clamp_tpl((absAngle - angle_follow_threshold_inner) / (angle_follow_threshold_outer - angle_follow_threshold_inner), 0.0f, 1.0f); const float angle_follow_fractionV = clamp_tpl((absAngleV - angle_follow_threshold_inner) / (angle_follow_threshold_outer - angle_follow_threshold_inner), 0.0f, 1.0f); const float worst_follow_fraction = (float)__fsel(angle_follow_fraction - angle_follow_fractionV, angle_follow_fraction, angle_follow_fractionV); float follow_fraction = ((1.0f - worst_follow_fraction) * (1.0f - distance_follow_fraction)); float follow_vote = follow_fraction; //clamp the lower bound of the distance_slow_modifier so it can't be lower than the angle slow fraction // which prevents close but off-centre targets slowing us too much const float distance_slow_modifier = clamp_tpl( 1.0f - ((distance - falloffStartDistance) * falloffPerMeter), angle_slow_fraction, 1.0f); const float fCombinedModifier = angle_slow_fraction * distance_slow_modifier; fBestTargetDistance = (float)__fsel(fCombinedModifier - bestScale, fBestTargetDistance, distance); bestScale = min(fCombinedModifier, bestScale); if (follow_vote > follow_vote_leader) { follow_vote_leader = follow_vote; //m_follow_target_id only gets set after the loop -> this won't get hit when a target is selected // as a follow target for the first time. This doesn't need to be in the loop. if ( m_follow_target_id == target.entityId) { const Vec3 follow_target_dir_local = m_follow_target_dir; Vec3 target_rgt = playerRgt; Vec3 target_up = target_rgt.cross(follow_target_dir_local); target_rgt = follow_target_dir_local.cross(target_up); target_rgt.Normalize(); target_up.Normalize(); float alignH = dirToTarget * -target_rgt; float alignV = dirToTarget.z - follow_target_dir_local.z; float angleH = min(fabsf(alignH * fAimAssistStrength), fabsf(angleDot)); float angleV = min(fabsf(alignV * fAimAssistStrength), fabsf(angleDotV)); followH = follow_fraction * (float)__fsel(angleDot, angleH, -angleH); followV = follow_fraction * (float)__fsel(angleDotV, angleV, -angleV); follow_vote_leader += 0.05f; // anti oscillation between different targets follow_target_pos = targetPos; } follow_target_id = target.entityId; snap_target_id = target.entityId; follow_target_dir = dirToTarget; snap_target_dir = PickBestSnapDirection(playerPos, playerFwd, target); } else if (!follow_target_id && (radius_snap > 0.0f)) { Lineseg lineSegment; lineSegment.start = playerPos; lineSegment.end = playerPos + (playerFwd * (distance + radius_snap)); Sphere sphere; sphere.center = targetPos; sphere.radius = radius_snap; Vec3 intersectionPoint; if (Intersect::Lineseg_SphereFirst(lineSegment, sphere, intersectionPoint)) { float t = 0.0f; const float snap_fraction = 1.0f - (Distance::Point_Lineseg(targetPos, lineSegment, t) * (float)__fres(radius_snap)); if (snap_fraction > snap_vote_leader) { snap_vote_leader = snap_fraction; snap_target_id = target.entityId; snap_target_dir = PickBestSnapDirection(playerPos, playerFwd, target); } } } } #if DBG_AUTO_AIM if ((!follow_target_pos.IsZeroFast()) && (g_pGameCVars->pl_targeting_debug != 0)) { float radius_inner = 0.30f; float radius_outer = 0.33f; ColorB colorInner(255,255,0,0x40); ColorB colorOuter(255,255,0,0x40); DrawDisc(follow_target_pos, follow_target_dir, radius_inner, radius_outer, colorInner, colorOuter); } gEnv->pRenderer->GetIRenderAuxGeom()->SetRenderFlags(oldFlags); #endif m_follow_target_id = follow_target_id; m_follow_target_dir = follow_target_dir; //IMPORTANT: Apply the minimum-distance scaling of the slowdown _after_ calculating the slowdown for the best target // as we want to help the player aim at the nearest target, and modifying the slowdown multiplier prior to this // could result in a different target being selected const float fSlowDownProximityFadeInBand = (g_pGameCVars->aim_assistSlowStopFadeinDistance - g_pGameCVars->aim_assistSlowStartFadeinDistance) + FLT_EPSILON; float fSlowDownProximityScale = (fBestTargetDistance - g_pGameCVars->aim_assistSlowStartFadeinDistance) / fSlowDownProximityFadeInBand; Limit(fSlowDownProximityScale, 0.0f, 1.0f); float fInvBestScale = (1.0f - bestScale) * fSlowDownProximityScale; bestScale = 1.0f - fInvBestScale; scale = minTurnScale + ((1.0f - minTurnScale) * bestScale); UpdateCurrentSnapTarget(snap_target_id, snap_target_dir); }
void CHUDTagNames::DrawTagName(IActor *pActor,bool bLocalVehicle) { CRY_ASSERT(pActor); if(!pActor) return; IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor(); CGameRules *pGameRules = g_pGame->GetGameRules(); int iClientTeam = pGameRules->GetTeam(pClientActor->GetEntityId()); if(!bLocalVehicle && pActor->GetLinkedVehicle()) return; const char *szRank = GetPlayerRank(pActor->GetEntityId()); IEntity *pEntity = pActor->GetEntity(); if(!pEntity) return; char szText[HUD_MAX_STRING_SIZE]; if(szRank) { sprintf(szText,"%s %s",szRank,pEntity->GetName()); } else { sprintf(szText,"%s",pEntity->GetName()); } ICharacterInstance *pCharacterInstance = pEntity->GetCharacter(0); if(!pCharacterInstance) return; ISkeletonPose *pSkeletonPose = pCharacterInstance->GetISkeletonPose(); if(!pSkeletonPose) return; int16 sHeadID = pSkeletonPose->GetJointIDByName("Bip01 Head"); if(-1 == sHeadID) return; Matrix34 matWorld = pEntity->GetWorldTM() * Matrix34(pSkeletonPose->GetAbsJointByID(sHeadID)); Vec3 vWorldPos = matWorld.GetTranslation(); // Who has a bigger head? :) vWorldPos.z += 0.4f; AABB box; pEntity->GetWorldBounds(box); bool bDrawOnTop = bLocalVehicle; if(ProjectOnSphere(vWorldPos,box)) { bDrawOnTop = true; } ColorF rgbTagName = COLOR_ENEMY; if(0 == iClientTeam) { if(IsFriendlyToClient(pActor->GetEntityId())) { rgbTagName = COLOR_FRIEND; } } else if(pGameRules->GetTeam(pActor->GetEntityId()) == iClientTeam) { rgbTagName = COLOR_FRIEND; } if(pActor->GetHealth() <= 0) { rgbTagName = COLOR_DEAD; } m_tagNamesVector.resize(1); for(std::vector<EntityId>::iterator iter=SAFE_HUD_FUNC_RET(GetRadar()->GetSelectedTeamMates())->begin(); iter!=SAFE_HUD_FUNC_RET(GetRadar()->GetSelectedTeamMates())->end(); ++iter) { if(pActor->GetEntityId() == *iter) { // Teammate is selected in radar, force the visibility of that name bDrawOnTop = true; break; } } STagName *pTagName = &m_tagNamesVector[0]; pTagName->strName = szText; pTagName->vWorld = vWorldPos; pTagName->bDrawOnTop = bDrawOnTop; pTagName->rgb = rgbTagName; DrawTagNames(); }
//------------------------------------------------------------------------ void CWeapon::OnShoot(EntityId shooterId, EntityId ammoId, IEntityClass* pAmmoType, const Vec3 &pos, const Vec3 &dir, const Vec3&vel) { BROADCAST_WEAPON_EVENT(OnShoot, (this, shooterId, ammoId, pAmmoType, pos, dir, vel)); //FIXME:quick temporary solution CActor *pActor = static_cast<CActor*> (g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(shooterId)); if (pActor) pActor->HandleEvent(SGameObjectEvent(eCGE_OnShoot,eGOEF_ToExtensions)); IActor *pClientActor=m_pGameFramework->GetClientActor(); if (pActor && pActor->GetActorClass() == CPlayer::GetActorClassType() && IsServer()) { if (pActor == pClientActor) { if (IAIObject *pAIObject=pActor->GetEntity()->GetAI()) gEnv->pAISystem->SendSignal(SIGNALFILTER_LEADER, 1, "OnEnableFire", pAIObject, 0); } CPlayer *pPlayer=static_cast<CPlayer *>(pActor); CNanoSuit *pSuit=pPlayer->GetNanoSuit(); if(m_fm && strcmp(m_fm->GetType(), "Repair")) { if(pSuit) { if (pSuit->GetMode() == NANOMODE_STRENGTH && !IsMounted()) pSuit->SetSuitEnergy(pSuit->GetSuitEnergy()-g_pGameCVars->g_suitRecoilEnergyCost); else if(pSuit->GetMode() == NANOMODE_CLOAK) pSuit->SetSuitEnergy(0.0f); } } if (gEnv->bServer && pSuit && pSuit->IsInvulnerable()) pSuit->SetInvulnerability(false); } if (pClientActor && m_fm && strcmp(m_fm->GetType(), "Thrown")) { // inform the HUDRadar about the sound event Vec3 vPlayerPos=pClientActor->GetEntity()->GetWorldPos(); float fDist2=(vPlayerPos-pos).len2(); if (fDist2<250.0f*250.0f) { //if (pClientActor->GetEntityId() != shooterId) // pHUD->ShowSoundOnRadar(pos); if(gEnv->bMultiplayer) { CGameRules *pGameRules = g_pGame->GetGameRules(); if(pGameRules->GetTeamCount() < 2 || (pGameRules->GetTeam(shooterId) != pGameRules->GetTeam(pClientActor->GetEntityId()))) { //Small workaround for patch2... IFireMode* pFM = GetFireMode(GetCurrentFireMode()); bool grenade = pFM?(pFM->GetAmmoType()==CItem::sScarGrenadeClass):false; //~... if (!IsSilencerAttached() || grenade) { SAFE_HUD_FUNC(GetRadar()->AddEntityTemporarily(shooterId, 5.0f)); } else if(fDist2<5.0f*5.0f) { //Silencer attached SAFE_HUD_FUNC(GetRadar()->AddEntityTemporarily(shooterId, 5.0f)); } } } if ((!IsSilencerAttached()) && fDist2<sqr(SAFE_HUD_FUNC_RET(GetBattleRange()))) SAFE_HUD_FUNC(TickBattleStatus(1.0f)); } } }
void CAVMine::ProcessEvent(SEntityEvent &event) { if (m_frozen) return; switch(event.event) { case ENTITY_EVENT_ENTERAREA: { IEntity * pEntity = gEnv->pEntitySystem->GetEntity(event.nParam[0]); CGameRules* pGR = g_pGame->GetGameRules(); if(pEntity && pGR) { // if this is a team game, mines aren't set off by their own team if(pGR->GetTeamCount() > 0 && (m_teamId != 0 && pGR->GetTeam(pEntity->GetId()) == m_teamId)) break; // otherwise, not set off by the player who dropped them. if(pGR->GetTeamCount() == 0 && m_ownerId == pEntity->GetId()) break; // or a vehicle that player might happen to be in IVehicle* pVehicle = g_pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(event.nParam[0]); if(pVehicle && pVehicle->GetSeatForPassenger(m_ownerId)) break; IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus)) { // only count moving objects if(physStatus.v.GetLengthSquared() > 0.1f) m_currentWeight += physStatus.mass; if (m_currentWeight > m_triggerWeight) Explode(true); } } } break; } case ENTITY_EVENT_LEAVEAREA: { IEntity * pEntity = gEnv->pEntitySystem->GetEntity(event.nParam[0]); if(pEntity) { IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus)) { m_currentWeight -= physStatus.mass; if(m_currentWeight < 0) m_currentWeight = 0; } } } break; } default: break; } return CProjectile::ProcessEvent(event); }
void CAVMine::ProcessEvent(SEntityEvent &event) { if (m_frozen) return; switch(event.event) { case ENTITY_EVENT_ENTERAREA: { IEntity * pEntity = gEnv->pEntitySystem->GetEntity((EntityId)event.nParam[0]); CGameRules* pGR = g_pGame->GetGameRules(); if(pEntity && pGR) { // if this is a team game, mines aren't set off by their own team if(pGR->GetTeamCount() > 0 && (m_teamId != 0 && pGR->GetTeam(pEntity->GetId()) == m_teamId)) break; IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus)) { // only count moving objects if(physStatus.v.GetLengthSquared() > 0.1f) m_currentWeight += physStatus.mass; if (m_currentWeight > m_triggerWeight) Explode(true); } } } break; } case ENTITY_EVENT_LEAVEAREA: { IEntity * pEntity = gEnv->pEntitySystem->GetEntity((EntityId)event.nParam[0]); if(pEntity) { IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus)) { m_currentWeight -= physStatus.mass; if(m_currentWeight < 0) m_currentWeight = 0; } } } break; } default: break; } return CProjectile::ProcessEvent(event); }
void CClaymore::Update(SEntityUpdateContext &ctx, int updateSlot) { CProjectile::Update(ctx, updateSlot); bool debug = (g_pGameCVars->g_debugMines != 0); if(gEnv->bServer) { if(m_armed) { CGameRules* pGR = g_pGame->GetGameRules(); if(pGR) { for(std::list<EntityId>::iterator it = m_targetList.begin(); it != m_targetList.end(); ++it) { IEntity* pEntity = gEnv->pEntitySystem->GetEntity(*it); if(!pEntity) continue; // if this is a team game, claymores aren't set off by their own team... if(pGR->GetTeamCount() > 0 && (m_teamId != 0 && pGR->GetTeam(pEntity->GetId()) == m_teamId)) continue; // otherwise, not set off by the player who dropped them. if(pGR->GetTeamCount() == 0 && m_ownerId == pEntity->GetId()) continue; IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus) && physStatus.v.GetLengthSquared() > 0.01f) { // now check angle between this claymore and approaching object // to see if it is within the angular range m_triggerAngle. // If it is, then check distance is less than m_triggerRange, // and also check line-of-sight between the two entities. IRenderAuxGeom * pRAG = gEnv->pRenderer->GetIRenderAuxGeom(); pRAG->SetRenderFlags( e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeNone ); AABB entityBBox; pEntity->GetWorldBounds(entityBBox); if(debug) { pRAG->DrawAABB( entityBBox, true, ColorF(1,0,0,0.4f), eBBD_Faceted ); } Vec3 enemyDir = entityBBox.GetCenter() - GetEntity()->GetPos(); Vec3 checkDir = enemyDir; checkDir.z = 0; float distanceSq = enemyDir.GetLengthSquared(); // for players a simple distance check is fine, but for vehicles use a better intersection check // so any corner of the vehicle going inside the zone sets off the claymore. static float playerRadius = 2.5f; bool inside = false; if(entityBBox.GetRadius() < playerRadius) { inside = (distanceSq < (m_triggerRadius * m_triggerRadius)); } else { static ray_hit hit; if(gEnv->pPhysicalWorld->CollideEntityWithBeam(pEntity->GetPhysics(), GetEntity()->GetWorldPos(), enemyDir, m_triggerRadius, &hit)) { inside = true; enemyDir = hit.pt - GetEntity()->GetWorldPos(); } } if(inside) { enemyDir.NormalizeSafe(); checkDir.NormalizeSafe(); float dotProd = checkDir.Dot(m_triggerDirection); if(debug) { pRAG->DrawLine(GetEntity()->GetPos(), ColorF(1,0,0,1), GetEntity()->GetPos() + Matrix33::CreateRotationZ(m_triggerAngle/2.0f)*m_triggerDirection*m_triggerRadius, ColorF(1,0,0,1), 5.0f); pRAG->DrawLine(GetEntity()->GetPos(), ColorF(1,0,0,1), GetEntity()->GetPos() + Matrix33::CreateRotationZ(-m_triggerAngle/2.0f)*m_triggerDirection*m_triggerRadius, ColorF(1,0,0,1), 5.0f); ColorF clr; clr.a = 0.3f; clr.b = 0.4f; clr.g = 0.1f; clr.r = 1.0f; pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + (enemyDir * m_triggerRadius), clr, 5.0f); } if(dotProd > cry_cosf(m_triggerAngle/2.0f)) { static const int objTypes = ent_all&(~ent_terrain); static const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any; ray_hit hit; int col = gEnv->pPhysicalWorld->RayWorldIntersection(GetEntity()->GetPos(), (enemyDir * m_triggerRadius * 1.5f), objTypes, flags, &hit, 1, GetEntity()->GetPhysics()); bool bang = false; if (!col) bang = true; else if (entityBBox.IsContainPoint(hit.pt)) bang = true; else if (hit.pt.GetSquaredDistance(GetEntity()->GetWorldPos()) >= distanceSq) bang = true; if (bang) { // pass in the explosion normal, which is -m_triggerDirection Explode(true, false, Vec3(0,0,0), -m_triggerDirection); if(debug) { ColorF clr; clr.a = 0.3f; clr.g = 0.1f; clr.r = 1.0f; clr.b = 1.0f; pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + (enemyDir * m_triggerRadius), clr, 5.0f); } } } } } } } } } else { m_timeToArm -= gEnv->pTimer->GetFrameTime(); if(m_timeToArm <= 0.0f) { m_armed = true; IEntityTriggerProxy *pTriggerProxy = (IEntityTriggerProxy*)(GetEntity()->GetProxy(ENTITY_PROXY_TRIGGER)); if (!pTriggerProxy) { GetEntity()->CreateProxy(ENTITY_PROXY_TRIGGER); pTriggerProxy = (IEntityTriggerProxy*)GetEntity()->GetProxy(ENTITY_PROXY_TRIGGER); } if(pTriggerProxy) { // create a trigger volume a couple of metres bigger than we need, to ensure we catch vehicles. // Checks above will still make sure the entity is within the radius before detonating though. float radius = m_triggerRadius + 2.0f; AABB boundingBox = AABB(Vec3(-radius,-radius,-radius), Vec3(radius,radius,radius)); pTriggerProxy->SetTriggerBounds(boundingBox); } } } } if(debug && m_armed) { IRenderAuxGeom * pRAG = gEnv->pRenderer->GetIRenderAuxGeom(); ColorF clr; clr.a = 0.3f; clr.b = 0.4f; clr.g = 0.1f; clr.r = 1.0f; pRAG->SetRenderFlags( e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeNone ); pRAG->DrawCylinder(GetEntity()->GetPos(), Vec3(0, 0, 1), m_triggerRadius, m_triggerRadius * 2.0f, clr); Vec3 size(m_triggerRadius + 2.0f, m_triggerRadius + 2.0f, m_triggerRadius + 2.0f); AABB box(GetEntity()->GetPos() - size, GetEntity()->GetPos() + size); pRAG->DrawAABB(box, false, ColorF(0.1f, 0.1f, 0.1f, 0.1f), eBBD_Faceted); pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + m_triggerDirection, clr, 5.0f); } }
static void GetTalosInput(CPlayerRotation * pPlayerRotation, const CPlayer& rPlayer, float& x, float& z, const Vec3 playerView[4], float fFrameTime) { //Do I need to reproject the view to actually get the positioning correct? Shouldn't be. const Vec3 playerFwd = playerView[1]; const Vec3 playerRgt = playerView[0]; const Vec3 playerUp = playerView[2]; const Vec3 playerViewPos = playerView[3]; Vec3 playerPos = playerViewPos; IPhysicalEntity * pPhysicalEntity = rPlayer.GetEntity()->GetPhysics(); if(pPhysicalEntity) { pe_status_dynamics dyn_status; pPhysicalEntity->GetStatus(&dyn_status); playerPos = playerViewPos + (dyn_status.v * fFrameTime * 2.0f); } Vec3 follow_target_dir(ZERO); EntityId follow_target_id = 0; static EntityId s_follow_target_id = 0; CGameRules * pGameRules = g_pGame->GetGameRules(); int playerTeam = pGameRules->GetTeam(rPlayer.GetEntity()->GetId()); float cloakedPlayerMultiplier = g_pGameCVars->pl_aim_cloaked_multiplier; const bool multipleTeams = pGameRules->GetTeamCount() > 0; const TAutoaimTargets& aaTargets = g_pGame->GetAutoAimManager().GetAutoAimTargets(); const int targetCount = aaTargets.size(); float fBestTargetDistance = FLT_MAX; for (int i = 0; i < targetCount; ++i) { const SAutoaimTarget& target = aaTargets[i]; if(multipleTeams && (pGameRules->GetTeam(target.entityId) == playerTeam)) { continue; } Vec3 targetPos = target.secondaryAimPosition; IEntity * pEntity = gEnv->pEntitySystem->GetEntity(target.entityId); if(pEntity) { IPhysicalEntity * pPhysicalEntity2 = pEntity->GetPhysics(); if(pPhysicalEntity2) { pe_status_dynamics dyn_status; pPhysicalEntity2->GetStatus(&dyn_status); targetPos = targetPos + (dyn_status.v * fFrameTime); } } Vec3 targetDistVec = (targetPos - playerPos); float distance = targetDistVec.GetLength(); if (distance <= 0.01f) continue; Vec3 dirToTarget = targetDistVec / distance; // fast reject everything behind player, too far away or too near from line of view // sort rest by angle to crosshair and distance from player const int kAutoaimVisibilityLatency = 1; if (!g_pGame->GetPlayerVisTable()->CanLocalPlayerSee(target.entityId, kAutoaimVisibilityLatency)) { // Since both player and target entities are ignored, and the ray still intersected something, there's something in the way. // Need to profile this and see if it's faster to do the below checks before doing the linetest. It's fairly expensive but // linetests generally are as well... - Richard continue; } const float angleDot = dirToTarget.dot(-playerRgt); const float angle = (RAD2DEG(acos_tpl(angleDot)) - 90.f); const float absAngle = fabsf(angle); const float angleDotV = playerUp.dot(dirToTarget); const float angleToTargetV = (RAD2DEG(acos_tpl(angleDotV)) - 90.f); const float absAngleV = fabsf(angleToTargetV); if ( s_follow_target_id == target.entityId ) { follow_target_id = target.entityId; follow_target_dir = dirToTarget; break; } else if(distance < fBestTargetDistance) { fBestTargetDistance = distance; follow_target_id = target.entityId; follow_target_dir = dirToTarget; } } if(follow_target_id != 0) { //Player up is the normal of the plane that we are rotating around - (Correct? Or do we want to project both the player direction and the target direction onto the X/Y plane?) Vec3 vProjectedTargetHorz = playerUp.cross(follow_target_dir.cross(playerUp)); Vec3 vProjectedTargetVert = playerRgt.cross(follow_target_dir.cross(playerRgt)); float horzDot = vProjectedTargetHorz.GetNormalized().dot(playerFwd); float vertDot = vProjectedTargetVert.GetNormalized().dot(playerFwd); const float directionDotHorz = follow_target_dir.dot(playerRgt); const float directionDotVert = follow_target_dir.dot(playerUp); const float angle = acos_tpl(horzDot); const float angleToTargetV = acos_tpl(vertDot); const float fHorzFinalAngle = (float)__fsel(directionDotHorz, -angle, angle); const float fVertFinalAngle = (float)__fsel(directionDotVert, angleToTargetV, -angleToTargetV); //CryWatch("Angle to target: %.6f", RAD2DEG(angle)); //CryWatch("Final Angle to target: %.6f", RAD2DEG(fHorzFinalAngle)); x = x + fVertFinalAngle; z = z + fHorzFinalAngle; } s_follow_target_id = follow_target_id; return; }