//------------------------------------------------------------------------ void CVehicleActionDeployRope::OnVehicleEvent(EVehicleEvent event, const SVehicleEventParams& params) { if (event == eVE_PassengerExit && params.iParam == m_seatId) { IActorSystem* pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); assert(pActorSystem); IActor* pActor = pActorSystem->GetActor(params.entityId); if (!pActor) { assert(pActor); return; } m_actorId = pActor->GetEntityId(); DeployRope(); AttachOnRope(pActor->GetEntity()); } else if (event == eVE_Destroyed) { if (m_ropeUpperId) { gEnv->pEntitySystem->RemoveEntity(m_ropeUpperId); m_ropeUpperId = 0; } if (m_ropeLowerId) { gEnv->pEntitySystem->RemoveEntity(m_ropeLowerId); m_ropeLowerId = 0; } } }
//------------------------------------------------------------------------ void CProjectile::Update(SEntityUpdateContext &ctx, int updateSlot) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); if (updateSlot!=0) return; float color[4] = {1,1,1,1}; bool bDebug = g_pGameCVars->i_debug_projectiles > 0; if(bDebug) gEnv->pRenderer->Draw2dLabel(50,15,2.0f,color,false,"Projectile: %s",GetEntity()->GetClass()->GetName()); Vec3 pos = GetEntity()->GetWorldPos(); ScaledEffect(m_pAmmoParams->pScaledEffect); // update whiz if(m_pAmmoParams->pWhiz) { if (m_whizSoundId == INVALID_SOUNDID) { IActor *pActor = g_pGame->GetIGameFramework()->GetClientActor(); if (pActor && (m_ownerId != pActor->GetEntityId())) { float probability = 0.85f; if (Random()<=probability) { Lineseg line(m_last, pos); Vec3 player = pActor->GetEntity()->GetWorldPos(); float t; float distanceSq=Distance::Point_LinesegSq(player, line, t); if (distanceSq < 4.7f*4.7f && (t>=0.0f && t<=1.0f)) { if (distanceSq >= 0.65*0.65) { Sphere s; s.center = player; s.radius = 4.7f; Vec3 entry,exit; int intersect=Intersect::Lineseg_Sphere(line, s, entry,exit); if (intersect==0x1 || intersect==0x3) // one entry or one entry and one exit WhizSound(true, entry, (pos-m_last).GetNormalized()); } } } } } } if (m_trailSoundId==INVALID_SOUNDID) TrailSound(true); m_totalLifetime += ctx.fFrameTime; m_last = pos; }
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; } }
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; }
void CMFXParticleEffect::Execute(const SMFXRunTimeEffectParams& params) { FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION); Vec3 pos = params.pos; Vec3 dir = ZERO; Vec3 inDir = params.dir[0]; Vec3 reverso = inDir * -1.0f; switch (m_particleParams.directionType) { case SMFXParticleParams::eDT_Normal: dir = params.normal; break; case SMFXParticleParams::eDT_Ricochet: dir = reverso.GetRotated(params.normal, gf_PI).normalize(); break; default: dir = params.normal; break; } bool tryToAttachEffect = (CMaterialEffectsCVars::Get().mfx_EnableAttachedEffects != 0); float distToPlayer = 0.f; IActor *pClientActor = gEnv->pGame->GetIGameFramework()->GetClientActor(); if (pClientActor) { distToPlayer = (pClientActor->GetEntity()->GetWorldPos() - params.pos).GetLength(); tryToAttachEffect = tryToAttachEffect && (pClientActor->GetEntityId() != params.trg); } SMFXParticleEntries::const_iterator end = m_particleParams.m_entries.end(); for (SMFXParticleEntries::const_iterator it = m_particleParams.m_entries.begin(); it!=end; ++it) { // choose effect based on distance if ((it->maxdist == 0.f) || (distToPlayer <= it->maxdist) && !it->name.empty() ) { IParticleEffect *pParticle = gEnv->pParticleManager->FindEffect(it->name.c_str()); if (pParticle) { const float pfx_minscale = (it->minscale != 0.f) ? it->minscale : CMaterialEffectsCVars::Get().mfx_pfx_minScale; const float pfx_maxscale = (it->maxscale != 0.f) ? it->maxscale : CMaterialEffectsCVars::Get().mfx_pfx_maxScale; const float pfx_maxdist = (it->maxscaledist != 0.f) ? it->maxscaledist : CMaterialEffectsCVars::Get().mfx_pfx_maxDist; const float truscale = pfx_minscale + ((pfx_maxscale - pfx_minscale) * (distToPlayer!=0.f ? min(1.0f, distToPlayer/pfx_maxdist) : 1.f)); bool particleSpawnedAndAttached = tryToAttachEffect ? AttachToTarget(*it, params, pParticle, dir, truscale) : false; // If not attached, just spawn the particle if (particleSpawnedAndAttached == false) { pParticle->Spawn( true, IParticleEffect::ParticleLoc(pos, dir, truscale) ); } } break; } } }
virtual void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo ) { switch (event) { case eFE_Activate: if (IsPortActive(pActInfo, INP_TRIGGER)) { IActor * pActor = GetAIActor(pActInfo); if (pActor) { int damage = GetPortInt(pActInfo, INP_DAMAGE); if (damage==0) damage = ( GetPortInt( pActInfo, INP_RELATIVEDAMAGE ) * int(pActor->GetMaxHealth()) ) / 100; SendFlowHitToEntity( pActor->GetEntityId(), pActor->GetEntityId(), damage, GetPortVec3(pActInfo, INP_POSITION) ); } } break; } }
bool UpdateEntityIdOutput( SActivationInfo *pActInfo ) { IActor * pActor = CCryAction::GetCryAction()->GetClientActor(); if (pActor) { ActivateOutput(pActInfo, 0, pActor->GetEntityId()); return true; } else return false; }
// 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; } } }
//------------------------------------------------------------------------ void CGameRulesCommonDamageHandling::ClProcessHit(Vec3 dir, EntityId shooterId, EntityId weaponId, float damage, uint16 projectileClassId, uint8 hitTypeId) { const char* hit = g_pGame->GetGameRules()->GetHitType(hitTypeId); if(hit) { IActor *pClientActor = gEnv->pGame->GetIGameFramework()->GetClientActor(); string hitSound; hitSound.Format("ClientDamage%s", hit); float maxHealth = pClientActor->GetMaxHealth(); float normalizedDamage = SATURATE(maxHealth > 0.0f ? damage / maxHealth : 0.0f); CAudioSignalPlayer::JustPlay(hitSound.c_str(), pClientActor->GetEntityId(), "damage", normalizedDamage); } }
void CHeavyWeapon::InitClient( int channelId ) { BaseClass::InitClient(channelId); IActor *pActor = GetOwnerActor(); if(pActor && pActor->GetChannelId() != channelId) { EntityId ownerId = pActor->GetEntityId(); GetGameObject()->InvokeRMIWithDependentObject(ClHeavyWeaponUsed(), SHeavyWeaponUserParams(ownerId), eRMI_ToClientChannel, ownerId, channelId); } else if(m_bIsHighlighted) { GetGameObject()->InvokeRMI(ClHeavyWeaponHighlighted(), SNoParams(), eRMI_ToClientChannel, channelId); } }
//------------------------------------------------------------------------ void CShake::Update(SEntityUpdateContext &ctx, int updateSlot) { IActor *pClient = g_pGame->GetIGameFramework()->GetClientActor(); if (pClient) { float dist2ToClient((pClient->GetEntity()->GetWorldPos() - GetEntity()->GetWorldPos()).len2()); float maxRange(m_radius * m_radius); if (dist2ToClient<maxRange) { IView *pView = g_pGame->GetIGameFramework()->GetIViewSystem()->GetViewByEntityId(pClient->GetEntityId()); if (pView) { float strength = (1.0f - (dist2ToClient/maxRange)) * 0.5f; pView->SetViewShake(ZERO,Vec3(m_shake*strength,0,m_shake*strength),0.1f,0.0225f,1.5f,1); } } } }
//------------------------------------------------------------------------ void CGameRules::ClientHit(const HitInfo &hitInfo) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor(); IEntity *pTarget = m_pEntitySystem->GetEntity(hitInfo.targetId); IEntity *pShooter = m_pEntitySystem->GetEntity(hitInfo.shooterId); IVehicle *pVehicle = g_pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(hitInfo.targetId); IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(hitInfo.targetId); bool dead = pActor?(pActor->GetHealth()<=0):false; if((pClientActor && pClientActor->GetEntity()==pShooter) && pTarget && (pVehicle || pActor) && !dead) { SAFE_HUD_FUNC(GetCrosshair()->CrosshairHit()); SAFE_HUD_FUNC(GetTagNames()->AddEnemyTagName(pActor?pActor->GetEntityId():pVehicle->GetEntityId())); } if(pActor == pClientActor) if (gEnv->pInput) gEnv->pInput->ForceFeedbackEvent( SFFOutputEvent(eDI_XI, eFF_Rumble_Basic, 0.5f * hitInfo.damage * 0.01f, hitInfo.damage * 0.02f, 0.0f)); /* if (gEnv->pAISystem && !gEnv->bMultiplayer) { static int htMelee = GetHitTypeId("melee"); if (pShooter && hitInfo.type != htMelee) { ISurfaceType *pSurfaceType = GetHitMaterial(hitInfo.material); const ISurfaceType::SSurfaceTypeAIParams* pParams = pSurfaceType ? pSurfaceType->GetAIParams() : 0; const float radius = pParams ? pParams->fImpactRadius : 5.0f; gEnv->pAISystem->BulletHitEvent(hitInfo.pos, radius, pShooter->GetAI()); } }*/ CreateScriptHitInfo(m_scriptHitInfo, hitInfo); CallScript(m_clientStateScript, "OnHit", m_scriptHitInfo); bool backface = hitInfo.dir.Dot(hitInfo.normal)>0; if (!hitInfo.remote && hitInfo.targetId && !backface) { if (!gEnv->bServer) GetGameObject()->InvokeRMI(SvRequestHit(), hitInfo, eRMI_ToServer); else ServerHit(hitInfo); } }
//------------------------------------------------------------------------ void CGameRules::OnUserLeftLobby(int channelId) { if (g_pGame->GetHostMigrationState() == CGame::eHMS_WaitingForPlayers) { int migratingIndex = GetMigratingPlayerIndex(channelId); if (migratingIndex >= 0) { // Migrating player has left the lobby so they aren't going to make the migration, remove them FinishMigrationForPlayer(migratingIndex); IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActorByChannelId(channelId); if (pActor) { FakeDisconnectPlayer(pActor->GetEntityId()); } } } }
//------------------------------------------------------------------------ bool CVehicleMountedWeapon::CanZoom() const { if (!CHeavyMountedWeapon::CanZoom()) return false; IVehicle *pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(m_vehicleId); if(pVehicle && !IsRippedOff()) { if (m_pSeatUser != m_pOwnerSeat) return false; IActor* pActor = GetOwnerActor(); IVehicleSeat* pSeat = pActor ? pVehicle->GetSeatForPassenger(pActor->GetEntityId()) : NULL; IVehicleView* pView = pSeat ? pSeat->GetCurrentView() : NULL; if (pView && pView->IsThirdPerson()) return false; } return true; }
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; }
//------------------------------------------------------------------------ bool CVehicleWeapon::CanZoom() const { if (!CWeapon::CanZoom()) return false; if (!m_bOwnerInSeat) return false; IVehicle *pVehicle = GetVehicle(); if(!pVehicle) return false; IActor* pActor = GetOwnerActor(); IVehicleSeat* pSeat = pActor ? pVehicle->GetSeatForPassenger(pActor->GetEntityId()) : NULL; IVehicleView* pView = pSeat ? pSeat->GetCurrentView() : NULL; if (pView && pView->IsThirdPerson()) return false; return true; }
//----------------------------------------------------------------------- void CVehiclePartLight::UpdateLight(const float frameTime) { if (m_slot == -1) return; // move to vehicle event change view? if (m_diffuseMult[0] != m_diffuseMult[1]) { SEntitySlotInfo info; if (m_pVehicle->GetEntity()->GetSlotInfo(m_slot, info) && info.pLight) { CDLight& light = info.pLight->GetLightProperties(); IActor* pActor = CCryAction::GetCryAction()->GetClientActor(); bool localPlayer = (pActor != NULL) && (pActor->GetLinkedVehicle() == m_pVehicle); IVehicleSeat* pSeat = pActor ? m_pVehicle->GetSeatForPassenger(pActor->GetEntityId()) : NULL; IVehicleView* pView = pSeat? pSeat->GetView(pSeat->GetCurrentView()) : NULL; bool isThirdPersonView = pView? pView->IsThirdPerson() : true; if (localPlayer && !isThirdPersonView) light.SetLightColor(ColorF(m_diffuseCol * m_diffuseMult[0], 1.f)); else light.SetLightColor(ColorF(m_diffuseCol * m_diffuseMult[1], 1.f)); } } if (m_pHelper) { const static Matrix33 rot(Matrix33::CreateRotationXYZ(Ang3(0.f, 0.f, DEG2RAD(90.f)))); Matrix34 helperTM; m_pHelper->GetVehicleTM(helperTM); Matrix34 localTM = Matrix33(helperTM) * rot; localTM.SetTranslation(helperTM.GetTranslation()); GetEntity()->SetSlotLocalTM(m_slot, localTM); } }
//------------------------------------------------------------------------ bool CEditorGame::SetGameMode(bool bGameMode) { m_bGameMode = bGameMode; bool on = bGameMode; if (s_pEditorGameMode->GetIVal() == 0) on = m_bPlayer; bool ok = ConfigureNetContext( on ); if (ok) { if(gEnv->IsEditor()) { m_pGame->EditorResetGame(bGameMode); } IGameFramework * pGameFramework = m_pGame->GetIGameFramework(); pGameFramework->OnEditorSetGameMode(bGameMode); IActor *pActor = m_pGame->GetIGameFramework()->GetClientActor(); if (pActor) { if (bGameMode) { // Revive actor in its current location (it will be moved to the editor viewpoint location later) const Vec3 pos = pActor->GetEntity()->GetWorldPos(); const Quat rot = pActor->GetEntity()->GetWorldRotation(); const int teamId = g_pGame->GetGameRules()->GetTeam(pActor->GetEntityId()); g_pGame->GetGameRules()->RevivePlayer(pActor, pos, rot, teamId); } } } else { GameWarning("Failed configuring net context"); } return ok; }
void CGameStats::Dump() { SGetTime time(m_roundStart); //dump some info for debug purposes int lifeNo = 0; if(gEnv->bServer) { for(PlayerStatsMap::const_iterator it = m_playerMap.begin(), eit = m_playerMap.end(); it != eit; ++it) { CryLog("$2Stats for player %s", it->second.name.c_str()); for( SPlayerInfo::TStatsVct::const_iterator si = it->second.stats.begin(); si < it->second.stats.end(); ++si ) { CryLog("Life no: %d", lifeNo); si->get()->Dump(time); ++lifeNo; }; } } else { IActor* pActor = CCryAction::GetCryAction()->GetClientActor(); if(!pActor) return; PlayerStatsMap::iterator it = m_playerMap.find(pActor->GetEntityId()); if(it == m_playerMap.end()) return; for( SPlayerInfo::TStatsVct::iterator si = it->second.stats.begin(); si < it->second.stats.end(); ++si ) { CryLog("Life no: %d", lifeNo); si->get()->Dump(time); ++lifeNo; } } }
//------------------------------------------------------------------------ void CProjectile::EndScaledEffect(const SScaledEffectParams* pScaledEffect) { if (!pScaledEffect || m_scaledEffectval == 0.0f) return; IActor *local = gEnv->pGame->GetIGameFramework()->GetClientActor(); if (local) { if (pScaledEffect->fadeOutTime > 0.0f) { CActor *act = (CActor *)local; if (act->GetScreenEffects() != 0) { CPostProcessEffect *blur = new CPostProcessEffect(local->GetEntityId(), pScaledEffect->ppname, 0.0f); CLinearBlend *linear = new CLinearBlend(1.0f); act->GetScreenEffects()->StartBlend(blur, linear, 1.0f/pScaledEffect->fadeOutTime, 70); } } else { gEnv->p3DEngine->SetPostEffectParam(pScaledEffect->ppname, 0.0f); } } }
//---------------------------------------------------------------------- IView* GetView( SActivationInfo* pActInfo ) { SInputParams inputParams; ReadCurrentInputParams( pActInfo, inputParams ); IGameFramework* pGF = gEnv->pGame->GetIGameFramework(); IView* pView = 0; IView* pActiveView = pGF->GetIViewSystem()->GetActiveView(); eViewType viewType = inputParams.view; if (viewType == VT_FirstPerson) // use player's view { IActor* pActor = pGF->GetClientActor(); if (pActor == 0) return NULL; eRestriction restriction = inputParams.restriction; if (restriction != ER_None) { IVehicle* pVehicle = pActor->GetLinkedVehicle(); if (restriction == ER_InVehicle && pVehicle == 0) return NULL; if (restriction == ER_NoVehicle && pVehicle != 0 /* && pVehicle->GetSeatForPassenger(entityId) != 0 */) return NULL; } EntityId entityId = pActor->GetEntityId(); pView = pGF->GetIViewSystem()->GetViewByEntityId(entityId); } else // active view { pView = pActiveView; } if (pView != pActiveView) return NULL; return pView; }
//------------------------------------------------------------------------ void CProjectile::EndScaledEffect(const SScaledEffectParams *pScaledEffect) { if(!pScaledEffect || m_scaledEffectval == 0.0f) return; IActor *local = gEnv->pGame->GetIGameFramework()->GetClientActor(); if(local) { if(pScaledEffect->fadeOutTime > 0.0f) { CActor *act = (CActor *)local; CScreenEffects *pSE = act->GetScreenEffects(); if(pSE) { IBlendedEffect *blur = CBlendedEffect<CPostProcessEffect>::Create(CPostProcessEffect(local->GetEntityId(),pScaledEffect->ppname, 0.0f)); IBlendType *linear = CBlendType<CLinearBlend>::Create(CLinearBlend(1.0f)); pSE->StartBlend(blur, linear, 1.0f/pScaledEffect->fadeOutTime, CScreenEffects::eSFX_GID_SmokeBlur); } } else { gEnv->p3DEngine->SetPostEffectParam(pScaledEffect->ppname, 0.0f); } } }
//------------------------------------------------------------------------- void CGameRulesStandardState::Add3DWinningTeamMember() { IActor * localActor = g_pGame->GetIGameFramework()->GetClientActor(); if (localActor != NULL && static_cast<CActor*>(localActor)->GetSpectatorState() != CActor::eASS_SpectatorMode && !g_pGame->GetUI()->IsInMenu()) { IEntity * renderModelFromEntity = NULL; if (m_pGameRules->GetTeamCount() > 1) { // Only way to get in here is for it to be a team game (as opposed to every-man-for-himself Instant Action) const int teamId = m_pGameRules->GetTeam(localActor->GetEntityId()); assert(teamId == 1 || teamId == 2); const int enemyTeamId = 3 - teamId; const int clientTeamScore = m_pGameRules->GetTeamsScore(teamId); const int nonClientTeamScore = m_pGameRules->GetTeamsScore(enemyTeamId); bool winning = (clientTeamScore >= nonClientTeamScore); CryLog ("Want to add 3D model of winning team member... local player '%s' is %s", localActor->GetEntity()->GetName(), winning ? " on the winning team" : "not on the winning team"); if (! winning) { if (m_pGameRules->GetTeamPlayerCount(enemyTeamId, false)) { renderModelFromEntity = gEnv->pEntitySystem->GetEntity(m_pGameRules->GetTeamPlayer(enemyTeamId, 0)); } } } if (renderModelFromEntity == NULL) { // Local entity must exist (checked at top of function) so we'll _definitely_ have a renderModelFromEntity after this renderModelFromEntity = localActor->GetEntity(); } // Additional paranoia :) if (renderModelFromEntity) { CryLog ("Adding 3D model of '%s' to accompany scoreboard", renderModelFromEntity->GetName()); INDENT_LOG_DURING_SCOPE(); ICharacterInstance * characterInst = renderModelFromEntity->GetCharacter(0); if (characterInst != NULL) { CMenuRender3DModelMgr *pModelManager = new CMenuRender3DModelMgr(); CMenuRender3DModelMgr::SSceneSettings sceneSettings; sceneSettings.fovScale = 0.5f; sceneSettings.fadeInSpeed = 0.01f; sceneSettings.flashEdgeFadeScale = 0.2f; sceneSettings.ambientLight = Vec4(0.f, 0.f, 0.f, 0.8f); sceneSettings.lights.resize(3); sceneSettings.lights[0].pos.Set(-25.f, -10.f, 30.f); sceneSettings.lights[0].color.Set(5.f, 6.f, 5.5f); sceneSettings.lights[0].specular = 4.f; sceneSettings.lights[0].radius = 400.f; sceneSettings.lights[1].pos.Set(25.f, -4.f, 30.f); sceneSettings.lights[1].color.Set(0.7f, 0.7f, 0.7f); sceneSettings.lights[1].specular = 10.f; sceneSettings.lights[1].radius = 400.f; sceneSettings.lights[2].pos.Set(60.f, 40.f, 10.f); sceneSettings.lights[2].color.Set(0.5f, 1.0f, 0.7f); sceneSettings.lights[2].specular = 10.f; sceneSettings.lights[2].radius = 400.f; pModelManager->SetSceneSettings(sceneSettings); const char * usePlayerModelName = characterInst->GetFilePath(); CMenuRender3DModelMgr::SModelParams params; params.pFilename = usePlayerModelName; params.posOffset.Set(0.1f, 0.f, -0.2f); params.rot.Set(0.f, 0.f, 3.5f); params.scale = 1.35f; params.pName = "char"; params.screenRect[0] = 0.f; params.screenRect[1] = 0.f; params.screenRect[2] = 0.3f; params.screenRect[3] = 0.8f; const float ANIM_SPEED_MULTIPLIER = 0.5f; if (m_pGameRules->GetGameMode() == eGM_Gladiator) { // In Hunter mode, force the model to be a hunter params.pFilename = "_ObjectsSDK/Characters/Human/sdk_player/sdk_player.cdf"; } const CMenuRender3DModelMgr::TAddedModelIndex characterModelIndex = pModelManager->AddModel(params); pModelManager->UpdateAnim(characterModelIndex, "stand_tac_idle_nw_3p_01", ANIM_SPEED_MULTIPLIER); } } } }
//------------------------------------------------------------------------- void CGameRulesStandardState::EnterPostGameState( EPostGameState state ) { #ifndef _RELEASE if(g_pGameCVars->g_hud_postgame_debug) { CryLog("HUD PostGame - Entering new state %i from %i after %.2f seconds", (int)state, (int)m_postGameState, m_timeInCurrentPostGameState); } #endif m_timeInCurrentPostGameState = 0.f; m_postGameState = state; switch (m_postGameState) { case ePGS_FinalKillcam: { if (g_pGameCVars->kc_enableWinningKill) { CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); if (pRecordingSystem) { if(pRecordingSystem->IsPlaybackQueued()) { if(!pRecordingSystem->PlayWinningKillcam()) { CRY_ASSERT_MESSAGE(false, "There should be a Winning Kill queued up when we get here..."); } } else { CRY_ASSERT_MESSAGE(false, "There should be a Winning Kill queued up when we get here..."); } } } break; } case ePGS_HighlightReel: { bool canPlayHighlightReel = false; //Reset to standard style SHUDEvent postEvent(eHUDEvent_ResetHUDStyle); CHUDEventDispatcher::CallEvent(postEvent); CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); if (pRecordingSystem) { if (!(pRecordingSystem->IsPlayingBack() || pRecordingSystem->IsPlaybackQueued())) { canPlayHighlightReel = pRecordingSystem->PlayAllHighlights(false); #ifndef _RELEASE if(g_pGameCVars->g_hud_postgame_debug) { CryLog("HUD PostGame - Could play highlight reel = %s", canPlayHighlightReel ? "True" : "False"); } #endif } } //Change to fixed spectator mode IActor* pLocalActor = g_pGame->GetIGameFramework()->GetClientActor(); IGameRulesSpectatorModule* pSpecMod = g_pGame->GetGameRules()->GetSpectatorModule(); EntityId specEntity = 0; if(pLocalActor && pSpecMod && pSpecMod->ModeIsAvailable(pLocalActor->GetEntityId(), CActor::eASM_Fixed, &specEntity)) { pSpecMod->ChangeSpectatorMode(pLocalActor, CActor::eASM_Fixed, specEntity, true, true); } #ifndef _RELEASE else if(g_pGameCVars->g_hud_postgame_debug) { CryLog("HUD PostGame - Failed to change spectator mode when entering highlight reel"); } #endif if(canPlayHighlightReel) { m_bHasShownHighlightReel = true; } break; } case ePGS_Top3: { g_pGame->GetUI()->ActivateDefaultState(); SHUDEvent scoreboardVisibleEvent( eHUDEvent_MakeMatchEndScoreboardVisible ); scoreboardVisibleEvent.AddData(true); CHUDEventDispatcher::CallEvent(scoreboardVisibleEvent); break; } case ePGS_Scoreboard: { CryLog("HUD PostGame - Activating default state for scoreboard"); // Activating the default state while in this postgame state will cause the scoreboard to show g_pGame->GetUI()->ActivateDefaultState(); break; } } }
virtual void ProcessEvent(EFlowEvent flowEvent, SActivationInfo* pActivationInfo) { if (flowEvent == eFE_Activate && IsPortActive(pActivationInfo, EIP_StartDriving)) { IEntity* pEntity = pActivationInfo->pEntity; if(!pEntity) return; IVehicle* pVehicle; pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle( pEntity->GetId() ); if(!pVehicle || pVehicle->IsDestroyed()) { return; } IVehicleMovement* pMovement = pVehicle->GetMovement(); if (!pMovement) return; CVehicleMovementBase* pMovementBase = StaticCast_CVehicleMovementBase(pMovement); if (!pMovementBase) return; IActor* pPlayer = g_pGame->GetIGameFramework()->GetClientActor(); if (!pPlayer) return; const EntityId localPlayer = pPlayer->GetEntityId(); if (pVehicle->GetSeatCount() == 0) // Don't need to remotely enter { pMovement->StartDriving(localPlayer); } else { pVehicle->EvictAllPassengers(); IVehicleSeat* pSeat = pVehicle->GetSeatById(1); if (pSeat) { // Can't use remote entering to control otherwise if vehicle blows up, player dies //pSeat->EnterRemotely(localPlayer); pMovement->StartDriving(localPlayer); m_prevSeatLockStatus = pSeat->GetLockedStatus(); pSeat->SetLocked(eVSLS_Locked); } } m_fDuration = GetPortFloat(pActivationInfo, EIP_Time); m_fSpeed = GetPortFloat(pActivationInfo, EIP_Speed); m_actInfo = *pActivationInfo; m_entityId = pEntity->GetId(); SetActive(true); } else if (flowEvent == eFE_Update) { if (!m_bActive) { if (m_bNeedsCleanup) { Cleanup(); } return; } IEntity* pEntity = pActivationInfo->pEntity; if(!pEntity) { SetActive(false); return; } IVehicle* pVehicle; pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle( pEntity->GetId() ); if(!pVehicle || pVehicle->IsDestroyed()) { SetActive(false); return; } const float curTime = gEnv->pTimer->GetFrameStartTime().GetSeconds(); if ((curTime - m_fStartedTime) >= m_fDuration) { SetActive(false); ActivateOutput(pActivationInfo, EOP_TimeComplete, true); } else // Update every frame { IVehicleMovement* pMovement = pVehicle->GetMovement(); if (pMovement) { // prevent full pedal being kept pressed, but give it a bit pMovement->OnAction(eVAI_MoveForward, eAAM_OnPress, 1.0f); } } } }
virtual void ProcessEvent( EFlowEvent event,SActivationInfo* pActInfo ) { if (event != eFE_Activate) return; if (!InputEntityIsLocalPlayer( pActInfo )) return; const bool bTriggered = IsPortActive(pActInfo, EIP_Trigger); const bool bFreqTriggered = IsPortActive(pActInfo, EIP_Frequency); if (bTriggered == false && bFreqTriggered == false) return; IGameFramework* pGF = gEnv->pGame->GetIGameFramework(); IView* pView = 0; IView* pActiveView = pGF->GetIViewSystem()->GetActiveView(); int viewType = GetPortInt(pActInfo, EIP_ViewType); if (viewType == VT_FirstPerson) // use player's view { IActor* pActor = pGF->GetClientActor(); if (pActor == 0) return; const int restriction = GetPortInt(pActInfo, EIP_Restriction); if (restriction != ER_None) { IVehicle* pVehicle = pActor->GetLinkedVehicle(); if (restriction == ER_InVehicle && pVehicle == 0) return; if (restriction == ER_NoVehicle && pVehicle != 0 /* && pVehicle->GetSeatForPassenger(entityId) != 0 */) return; } EntityId entityId = pActor->GetEntityId(); pView = pGF->GetIViewSystem()->GetViewByEntityId(entityId); } else // active view { pView = pActiveView; } if (pView == 0 || pView != pActiveView) return; const bool bGroundOnly = GetPortBool(pActInfo, EIP_GroundOnly); Ang3 angles = Ang3(DEG2RAD(GetPortVec3(pActInfo, EIP_Angle))); Vec3 shift = GetPortVec3(pActInfo, EIP_Shift); const float duration = GetPortFloat(pActInfo, EIP_Duration); float freq = GetPortFloat(pActInfo, EIP_Frequency); if (iszero(freq) == false) freq = 1.0f / freq; const float randomness = GetPortFloat(pActInfo, EIP_Randomness); static const bool bFlip = true; // GetPortBool(pActInfo, EIP_Flip); const bool bUpdateOnly = !bTriggered && bFreqTriggered; // it's an update if and only if Frequency has been changed const float distance = GetPortFloat(pActInfo, EIP_Distance); const float rangeMin = GetPortFloat(pActInfo, EIP_RangeMin); const float rangeMax = GetPortFloat(pActInfo, EIP_RangeMax); float amount = min(1.f, max(0.f, (rangeMax - distance) / (rangeMax - rangeMin))); angles *= amount; shift *= amount; pView->SetViewShake(angles, shift, duration, freq, randomness, FLOWGRAPH_SHAKE_ID, bFlip, bUpdateOnly, bGroundOnly); }
//------------------------------------------------------------------------ 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; }
//------------------------------------------- void CGameRules::ProcessClientExplosionScreenFX(const ExplosionInfo &explosionInfo) { IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor(); if (pClientActor) { //Distance float dist = (pClientActor->GetEntity()->GetWorldPos() - explosionInfo.pos).len(); //Is the explosion in Player's FOV (let's suppose the FOV a bit higher, like 80) CActor *pActor = (CActor *)pClientActor; SMovementState state; if (IMovementController *pMV = pActor->GetMovementController()) { pMV->GetMovementState(state); } Vec3 eyeToExplosion = explosionInfo.pos - state.eyePosition; eyeToExplosion.Normalize(); bool inFOV = (state.eyeDirection.Dot(eyeToExplosion) > 0.68f); // if in a vehicle eyeDirection is wrong if(pActor && pActor->GetLinkedVehicle()) { Vec3 eyeDir = static_cast<CPlayer*>(pActor)->GetVehicleViewDir(); inFOV = (eyeDir.Dot(eyeToExplosion) > 0.68f); } //All explosions have radial blur (default 30m radius, to make Sean happy =)) float maxBlurDistance = (explosionInfo.maxblurdistance>0.0f)?explosionInfo.maxblurdistance:30.0f; if (maxBlurDistance>0.0f && g_pGameCVars->g_radialBlur>0.0f && m_explosionScreenFX && explosionInfo.radius>0.5f) { if (inFOV && dist < maxBlurDistance) { ray_hit hit; int col = gEnv->pPhysicalWorld->RayWorldIntersection(explosionInfo.pos , -eyeToExplosion*dist, ent_static | ent_terrain, rwi_stop_at_pierceable|rwi_colltype_any, &hit, 1); //If there was no obstacle between flashbang grenade and player if(!col) { if (CScreenEffects* pSE = pActor->GetScreenEffects()) { float blurRadius = (-1.0f/maxBlurDistance)*dist + 1.0f; gEnv->p3DEngine->SetPostEffectParam("FilterRadialBlurring_Radius", blurRadius); gEnv->p3DEngine->SetPostEffectParam("FilterRadialBlurring_Amount", 1.0f); IBlendedEffect *pBlur = CBlendedEffect<CPostProcessEffect>::Create(CPostProcessEffect(pClientActor->GetEntityId(),"FilterRadialBlurring_Amount", 0.0f)); IBlendType *pLinear = CBlendType<CLinearBlend>::Create(CLinearBlend(1.0f)); pSE->StartBlend(pBlur, pLinear, 1.0f, CScreenEffects::eSFX_GID_RBlur); pSE->SetUpdateCoords("FilterRadialBlurring_ScreenPosX","FilterRadialBlurring_ScreenPosY", explosionInfo.pos); } float distAmp = 1.0f - (dist / maxBlurDistance); if (gEnv->pInput) gEnv->pInput->ForceFeedbackEvent( SFFOutputEvent(eDI_XI, eFF_Rumble_Basic, 0.5f, distAmp*3.0f, 0.0f)); } } } //Flashbang effect if(dist<explosionInfo.radius && inFOV && (!strcmp(explosionInfo.effect_class,"flashbang") || !strcmp(explosionInfo.effect_class,"FlashbangAI"))) { ray_hit hit; int col = gEnv->pPhysicalWorld->RayWorldIntersection(explosionInfo.pos , -eyeToExplosion*dist, ent_static | ent_terrain, rwi_stop_at_pierceable|rwi_colltype_any, &hit, 1); //If there was no obstacle between flashbang grenade and player if(!col) { float power = explosionInfo.flashbangScale; power *= max(0.0f, 1 - (dist/explosionInfo.radius)); float lookingAt = (eyeToExplosion.Dot(state.eyeDirection.normalize()) + 1)*0.5f; power *= lookingAt; SAFE_GAMEAUDIO_SOUNDMOODS_FUNC(AddSoundMood(SOUNDMOOD_EXPLOSION,MIN(power*40.0f,100.0f))); gEnv->p3DEngine->SetPostEffectParam("Flashbang_Time", 1.0f + (power * 4)); gEnv->p3DEngine->SetPostEffectParam("FlashBang_BlindAmount",explosionInfo.blindAmount); gEnv->p3DEngine->SetPostEffectParam("Flashbang_DifractionAmount", (power * 2)); gEnv->p3DEngine->SetPostEffectParam("Flashbang_Active", 1); } } else if(inFOV && (dist < explosionInfo.radius)) { if (explosionInfo.damage>10.0f || explosionInfo.pressure>100.0f) { //Add some angular impulse to the client actor depending on distance, direction... float dt = (1.0f - dist/explosionInfo.radius); dt = dt * dt; float angleZ = gf_PI*0.15f*dt; float angleX = gf_PI*0.15f*dt; pActor->AddAngularImpulse(Ang3(Random(-angleX*0.5f,angleX),0.0f,Random(-angleZ,angleZ)),0.0f,dt*2.0f); } } float fDist2=(pClientActor->GetEntity()->GetWorldPos()-explosionInfo.pos).len2(); if (fDist2<250.0f*250.0f) { if (fDist2<sqr(SAFE_GAMEAUDIO_BATTLESTATUS_FUNC_RET(GetBattleRange()))) SAFE_GAMEAUDIO_BATTLESTATUS_FUNC(TickBattleStatus(1.0f)); } } }
//-------------------------------------------------------------------------------------------------- // Name: SpawnScreenExplosionEffect // Desc: Spawns screen explosion effect //-------------------------------------------------------------------------------------------------- void CExplosionGameEffect::SpawnScreenExplosionEffect(const SExplosionContainer &explosionContainer) { // Disclaimer: this code was originally from GameRulesClientServer::ProcessClientExplosionScreenFX() const ExplosionInfo& explosionInfo = explosionContainer.m_explosionInfo; if(explosionInfo.pressure < 1.0f) return; IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor(); if(pClientActor != NULL && !pClientActor->IsDead()) { CPlayer* pPlayer = static_cast<CPlayer*>(pClientActor); bool hasFlashBangEffect = explosionInfo.blindAmount > 0.0f; // Flashbang friends and self?... if(hasFlashBangEffect) { bool flashBangSelf = true; bool flashBangFriends = false; #ifndef _RELEASE flashBangSelf = g_pGameCVars->g_flashBangSelf != 0; flashBangFriends = g_pGameCVars->g_flashBangFriends != 0; #endif bool ownFlashBang = pPlayer->GetEntityId() == explosionInfo.shooterId; if((!flashBangSelf && ownFlashBang) || // FlashBang self? ((g_pGame->GetGameRules()->GetFriendlyFireRatio()<=0.0f) && (!flashBangFriends) && (!ownFlashBang) && pPlayer->IsFriendlyEntity(explosionInfo.shooterId))) // FlashBang friends? { return; } } // Distance float dist = (pClientActor->GetEntity()->GetWorldPos() - explosionInfo.pos).len(); // Is the explosion in Player's FOV (let's suppose the FOV a bit higher, like 80) SMovementState state; if(IMovementController *pMV = pClientActor->GetMovementController()) { pMV->GetMovementState(state); } Vec3 eyeToExplosion = explosionInfo.pos - state.eyePosition; Vec3 eyeDir = pClientActor->GetLinkedVehicle() ? pPlayer->GetVehicleViewDir() : state.eyeDirection; eyeToExplosion.Normalize(); float eyeDirectionDP = eyeDir.Dot(eyeToExplosion); bool inFOV = (eyeDirectionDP > 0.68f); // All explosions have radial blur (default 30m radius) const float maxBlurDistance = (explosionInfo.maxblurdistance >0.0f) ? explosionInfo.maxblurdistance : 30.0f; if((maxBlurDistance > 0.0f) && (g_pGameCVars->g_radialBlur > 0.0f) && (explosionInfo.radius > 0.5f)) { if (inFOV && (dist < maxBlurDistance)) { const int intersectionObjTypes = ent_static | ent_terrain; const unsigned int intersectionFlags = rwi_stop_at_pierceable|rwi_colltype_any; m_deferredScreenEffects.RequestRayCast(CDeferredExplosionEffect::eDET_RadialBlur, explosionInfo.pos, -eyeToExplosion, dist, maxBlurDistance, intersectionObjTypes, intersectionFlags, NULL, 0); } } // Flashbang effect if(hasFlashBangEffect && ((dist < (explosionInfo.radius*g_pGameCVars->g_flashBangNotInFOVRadiusFraction)) || (inFOV && (dist < explosionInfo.radius)))) { ray_hit hit; const int intersectionObjTypes = ent_static | ent_terrain; const unsigned int intersectionFlags = rwi_stop_at_pierceable|rwi_colltype_any; const int intersectionMaxHits = 1; int collision = gEnv->pPhysicalWorld->RayWorldIntersection( explosionInfo.pos, -eyeToExplosion*dist, intersectionObjTypes, intersectionFlags, &hit, intersectionMaxHits); // If there was no obstacle between flashbang grenade and player if(!collision) { bool enabled = true; if(enabled) { CCCPOINT (FlashBang_Explode_BlindLocalPlayer); float timeScale = max(0.0f, 1 - (dist/explosionInfo.radius)); float lookingAt = max(g_pGameCVars->g_flashBangMinFOVMultiplier, (eyeDirectionDP + 1)*0.5f); float time = explosionInfo.flashbangScale * timeScale *lookingAt; // time is determined by distance to explosion CRY_ASSERT_MESSAGE(pClientActor->IsPlayer(),"Effect shouldn't be spawned if not a player"); SPlayerStats* pStats = static_cast<SPlayerStats*>(pPlayer->GetActorStats()); NET_BATTLECHATTER(BC_Blinded, pPlayer); if(pClientActor->GetEntityId() == explosionInfo.shooterId) { g_pGame->GetPersistantStats()->IncrementClientStats(EIPS_BlindSelf); } else { g_pGame->GetGameRules()->SuccessfulFlashBang(explosionInfo, time); } pPlayer->StartFlashbangEffects(time, explosionInfo.shooterId); gEnv->p3DEngine->SetPostEffectParam("Flashbang_Time", time); gEnv->p3DEngine->SetPostEffectParam("FlashBang_BlindAmount", explosionInfo.blindAmount); gEnv->p3DEngine->SetPostEffectParam("Flashbang_DifractionAmount", time); gEnv->p3DEngine->SetPostEffectParam("Flashbang_Active", 1.0f); CRecordingSystem *pRecordingSystem = g_pGame->GetRecordingSystem(); if (pRecordingSystem) { pRecordingSystem->OnPlayerFlashed(time, explosionInfo.blindAmount); } } } else { CCCPOINT (FlashBang_Explode_NearbyButBlockedByGeometry); } } else if(inFOV && (dist < explosionInfo.radius)) { if(explosionInfo.damage>10.0f || explosionInfo.pressure>100.0f) { // Add some angular impulse to the client actor depending on distance, direction... float dt = (1.0f - dist/explosionInfo.radius); dt = dt * dt; float angleZ = gf_PI*0.15f*dt; float angleX = gf_PI*0.15f*dt; if (pClientActor) { static_cast<CActor*>(pClientActor)->AddAngularImpulse(Ang3(cry_random(-angleX*0.5f,angleX),0.0f,cry_random(-angleZ,angleZ)),0.0f,dt*2.0f); } } } } }//-------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------ 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); } } } } } }