//------------------------------------------------------------------------ void CGameRulesHoldObjectiveBase::Update( float frameTime ) { if (m_bHasNetSerialized && !gEnv->bServer) { for (int i = 0; i < HOLD_OBJECTIVE_MAX_ENTITIES; ++ i) { SHoldEntityDetails *pDetails = &m_entities[i]; int oldControllingTeamId = pDetails->m_controllingTeamId; int oldTeam1Count = pDetails->m_insideCount[0]; int oldTeam2Count = pDetails->m_insideCount[1]; int team1Count = pDetails->m_serializedInsideCount[0]; int team2Count = pDetails->m_serializedInsideCount[1]; DetermineControllingTeamId(pDetails, team1Count, team2Count); if ((oldTeam1Count != team1Count) || (oldTeam2Count != team2Count)) { pDetails->m_insideCount[0] = team1Count; pDetails->m_insideCount[1] = team2Count; if (pDetails->m_id) { OnInsideStateChanged(pDetails); if (oldControllingTeamId != pDetails->m_controllingTeamId) { OnControllingTeamChanged(pDetails, oldControllingTeamId); } } } } m_bHasNetSerialized = false; } EntityId localPlayerId = g_pGame->GetIGameFramework()->GetClientActorId(); for (int i = 0; i < HOLD_OBJECTIVE_MAX_ENTITIES; ++ i) { SHoldEntityDetails *pDetails = &m_entities[i]; #ifndef _RELEASE DebugDrawCylinder(pDetails); #endif if (pDetails->m_id && pDetails->m_totalInsideBoxCount) { CheckCylinder(pDetails, localPlayerId); } else if (pDetails->m_pendingId) { DoAddEntityId(1, pDetails->m_pendingId, i, pDetails->m_isNewEntity); pDetails->m_pendingId = 0; pDetails->m_isNewEntity = false; } } UpdateEffect(frameTime); if (m_pStartingAnimSequence && gEnv->pMovieSystem) { m_deferredTrackViewTime -= frameTime; if (m_deferredTrackViewTime < 0.f) { CGameRules *pGameRules = g_pGame->GetGameRules(); const float currentTime = (pGameRules->GetServerTime() * 0.001f); const float timeStarted = m_pendingTimeAdded.GetSeconds(); const float timeSinceStarted = currentTime - timeStarted; const float playingTime = gEnv->pMovieSystem->GetPlayingTime(m_pStartingAnimSequence); CryLog("CGameRulesHoldObjectiveBase::Update() anim sequence %s at %f seconds (should be at least %f)", m_pStartingAnimSequence->GetName(), playingTime, timeSinceStarted); if (playingTime < timeSinceStarted) { gEnv->pMovieSystem->SetPlayingTime(m_pStartingAnimSequence, timeSinceStarted); } m_pStartingAnimSequence = NULL; } } }
void Animation::ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule, nsCSSPropertySet& aSetProperties, bool& aNeedsRefreshes) { if (!mEffect || mEffect->IsFinishedTransition()) { return; } AnimationPlayState playState = PlayState(); if (playState == AnimationPlayState::Running || playState == AnimationPlayState::Pending) { aNeedsRefreshes = true; } // In order to prevent flicker, there are a few cases where we want to use // a different time for rendering that would otherwise be returned by // GetCurrentTime. These are: // // (a) For animations that are pausing but which are still running on the // compositor. In this case we send a layer transaction that removes the // animation but which also contains the animation values calculated on // the main thread. To prevent flicker when this occurs we want to ensure // the timeline time used to calculate the main thread animation values // does not lag far behind the time used on the compositor. Ideally we // would like to use the "animation ready time" calculated at the end of // the layer transaction as the timeline time but it will be too late to // update the style rule at that point so instead we just use the current // wallclock time. // // (b) For animations that are pausing that we have already taken off the // compositor. In this case we record a pending ready time but we don't // apply it until the next tick. However, while waiting for the next tick, // we should still use the pending ready time as the timeline time. If we // use the regular timeline time the animation may appear jump backwards // if the main thread's timeline time lags behind the compositor. // // (c) For animations that are play-pending due to an aborted pause operation // (i.e. a pause operation that was interrupted before we entered the // paused state). When we cancel a pending pause we might momentarily take // the animation off the compositor, only to re-add it moments later. In // that case the compositor might have been ahead of the main thread so we // should use the current wallclock time to ensure the animation doesn't // temporarily jump backwards. // // To address each of these cases we temporarily tweak the hold time // immediately before updating the style rule and then restore it immediately // afterwards. This is purely to prevent visual flicker. Other behavior // such as dispatching events continues to rely on the regular timeline time. { AutoRestore<Nullable<TimeDuration>> restoreHoldTime(mHoldTime); bool updatedHoldTime = false; AnimationPlayState playState = PlayState(); if (playState == AnimationPlayState::Pending && mHoldTime.IsNull() && !mStartTime.IsNull()) { Nullable<TimeDuration> timeToUse = mPendingReadyTime; if (timeToUse.IsNull() && mTimeline && mTimeline->TracksWallclockTime()) { timeToUse = mTimeline->ToTimelineTime(TimeStamp::Now()); } if (!timeToUse.IsNull()) { mHoldTime.SetValue((timeToUse.Value() - mStartTime.Value()) .MultDouble(mPlaybackRate)); // Push the change down to the effect UpdateEffect(); updatedHoldTime = true; } } mEffect->ComposeStyle(aStyleRule, aSetProperties); if (updatedHoldTime) { UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async); } mFinishedAtLastComposeStyle = (playState == AnimationPlayState::Finished); } }
void CASW_Weapon_Chainsaw::Fire( const Vector &vecOrigSrc, const Vector &vecDir ) { CASW_Marine *pMarine = GetMarine(); if ( !pMarine ) { return; } StopAttackOffSound(); StartChainsawSound(); if ( m_flFireAnimTime < gpGlobals->curtime ) { pMarine->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN_PRIMARY ); m_flFireAnimTime = gpGlobals->curtime + 0.1f; } Vector vecDest = vecOrigSrc + (vecDir * ASW_CHAINSAW_RANGE); bool bDamageTime = m_flDmgTime < gpGlobals->curtime; bool bHit = false; Ray_t ray; ray.Init( vecOrigSrc, vecDest, Vector( -5, -5, -5 ), Vector( 5, 5, 25 ) ); CBaseEntity *(pEntities[ 8 ]); CHurtableEntitiesEnum hurtableEntities( pEntities, 8 ); partition->EnumerateElementsAlongRay( PARTITION_ENGINE_NON_STATIC_EDICTS | PARTITION_ENGINE_SOLID_EDICTS, ray, false, &hurtableEntities ); trace_t tr; for ( int i = 0; i < hurtableEntities.GetCount(); ++i ) { CBaseEntity *pEntity = pEntities[ i ]; if ( pEntity == NULL || pEntity == pMarine ) continue; bHit = true; if ( bDamageTime ) { // wide mode does damage to the ent, and radius damage if ( pEntity->m_takedamage != DAMAGE_NO ) { CTraceFilterOnlyHitThis filter( pEntity ); UTIL_TraceHull( vecOrigSrc, vecDest, Vector( -5, -5, -2 ), Vector( 5, 5, 25 ), MASK_SHOT, &filter, &tr ); ClearMultiDamage(); float fDamage = 0.5f * GetWeaponInfo()->m_flBaseDamage + MarineSkills()->GetSkillBasedValueByMarine( pMarine, ASW_MARINE_SKILL_MELEE, ASW_MARINE_SUBSKILL_MELEE_DMG ); CTakeDamageInfo info( this, pMarine, fDamage * g_pGameRules->GetDamageMultiplier(), DMG_SLASH ); info.SetWeapon( this ); CalculateMeleeDamageForce( &info, vecDir, tr.endpos ); pEntity->DispatchTraceAttack( info, vecDir, &tr ); ApplyMultiDamage(); } // radius damage a little more potent in multiplayer. #ifndef CLIENT_DLL //RadiusDamage( CTakeDamageInfo( this, pMarine, sk_plr_dmg_asw_ml.GetFloat() * g_pGameRules->GetDamageMultiplier() / 4, DMG_ENERGYBEAM | DMG_BLAST | DMG_ALWAYSGIB ), tr.endpos, 128, CLASS_NONE, NULL ); #endif } } if ( bHit ) { if ( bDamageTime ) { m_bIsFiring = true; m_flLastHitTime = gpGlobals->curtime; m_flTargetChainsawPitch = 0.0f; #ifndef CLIENT_DLL pMarine->OnWeaponFired( this, 1 ); #endif if ( !pMarine->IsAlive() ) return; // uses 5 ammo/second if ( gpGlobals->curtime >= m_flAmmoUseTime ) { // chainsaw no longer uses ammo m_flAmmoUseTime = gpGlobals->curtime + 0.2; /* // decrement ammo //m_iClip1 -= 1; #ifdef GAME_DLL CASW_Marine *pMarine = GetMarine(); if (pMarine && m_iClip1 <= 0 && pMarine->GetAmmoCount(m_iPrimaryAmmoType) <= 0 ) { // check he doesn't have ammo in an ammo bay CASW_Weapon_Ammo_Bag* pAmmoBag = dynamic_cast<CASW_Weapon_Ammo_Bag*>(pMarine->GetASWWeapon(0)); if (!pAmmoBag) pAmmoBag = dynamic_cast<CASW_Weapon_Ammo_Bag*>(pMarine->GetASWWeapon(1)); if (!pAmmoBag || !pAmmoBag->CanGiveAmmoToWeapon(this)) pMarine->GetMarineSpeech()->Chatter(CHATTER_NO_AMMO); } #endif */ } m_flDmgTime = gpGlobals->curtime + ASW_CHAINSAW_DISCHARGE_INTERVAL; if ( m_flShakeTime < gpGlobals->curtime ) { CASW_Player *pPlayer = pMarine->GetCommander(); if (pPlayer && pMarine->IsInhabited()) { // #ifndef CLIENT_DLL // if (gpGlobals->maxClients == 1) // only shake the screen from the server in singleplayer (in multi it'll be predicted) // { // ASW_TransmitShakeEvent( pPlayer, 5.0f, 100.0f, 1.75f, SHAKE_START ); // } // #else // ASW_TransmitShakeEvent( pPlayer, 5.0f, 100.0f, 1.75f, SHAKE_START ); // #endif } m_flShakeTime = gpGlobals->curtime + 0.5; } } Vector vecUp, vecRight; QAngle angDir; VectorAngles( vecDir, angDir ); AngleVectors( angDir, NULL, &vecRight, &vecUp ); Vector tmpSrc = vecOrigSrc + (vecUp * -8) + (vecRight * 3); //UTIL_ImpactTrace( &tr, DMG_SLASH ); UpdateEffect( tmpSrc, tr.endpos ); } }