//------------------------------------------------------------------------
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;
		}
	}
}
Exemplo n.º 2
0
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 );
	}
}