Exemple #1
0
//------------------------------------------------------------------------
bool CItem::PlayFragment(IAction* pAction, float speedOverride, float timeOverride, float animWeight, float ffeedbackWeight, bool concentratedFire)
{
    _smart_ptr<IAction> pActionPtr(pAction);

    CRY_ASSERT(pAction);
    if(!pAction)
        {
            return false;
        }

    CWeapon *pWeapon = static_cast<CWeapon*>(GetIWeapon());
    if (pWeapon && pWeapon->IsProxyWeapon())
        {
            return false;
        }

    bool success = false;

    float speed = (float)__fsel(-speedOverride, 1.0f, speedOverride);
    FragmentID fragID = pAction->GetFragmentID();
    pAction->SetSubContext(m_subContext);
    IActionController *pActionController = GetActionController();
    if ((fragID != FRAGMENT_ID_INVALID) && pActionController)
        {
            float fragmentDuration, transitionDuration;
            if (pActionController->QueryDuration(*pAction, fragmentDuration, transitionDuration))
                {
                    float duration = fragmentDuration+transitionDuration;
                    if ((duration > 0.0f) && (timeOverride > 0.0f))
                        {
                            speed = (duration / timeOverride);
                            CRY_ASSERT((speed > 0.0f) && (speed < 99999.0f));
                        }

                    if(duration > 0.f)
                        {
                            m_animationTime[eIGS_Owner] = (uint32) MAX((duration*1000.0f/speed) - 20, 0.0f);
                        }

                    pAction->SetSpeedBias(speed);
                    pAction->SetAnimWeight(animWeight);

                    if(concentratedFire)
                        {
                            pAction->SetParam(CItem::sActionParamCRCs.concentratedFire, 1.f);
                        }

                    if(ffeedbackWeight != 1.f)
                        {
                            pAction->SetParam(CItem::sActionParamCRCs.ffeedbackScale, ffeedbackWeight);
                        }

                    pActionController->Queue(pAction);

                    success = true;
                }
        }

    return success;
}
// ----------------------------------------------------------------------------
CExactPositioning::ETriggerState CExactPositioning::StateFinalPreparation_HandleEvent( SStateMachineEvent& event )
{
	switch( event.type )
	{
	case ESME_Enter:
		{
			CRY_ASSERT( m_pExactPositioningTarget->preparing );
			CRY_ASSERT( !m_pExactPositioningTarget->activated );

			if ( !m_pAnimatedCharacter )
				return eTS_Disabled;

			IActionController* pActionController = m_pAnimatedCharacter->GetActionController();
			if ( !pActionController )
				return eTS_Disabled;

			if ( m_pExactPositioningTarget->pAction->GetStatus() != IAction::None )
				return eTS_Disabled;

			m_pAnimAction = m_pExactPositioningTarget->pAction;
			pActionController->Queue( *m_pAnimAction );

			// We've queued the animation, let listeners know
			if ( m_triggerQueryStart )
			{
				SendQueryComplete( m_triggerQueryStart, true );
				m_triggerQueryStart = 0;
			}

			break;
		}

	case ESME_Update:
		if ( m_pPendingRequest.get() )
			return eTS_Disabled;

		CRY_ASSERT( m_pAnimAction.get() );
		switch( m_pAnimAction->GetStatus() )
		{
		case IAction::Pending:
			break;
		case IAction::Installed:
			return eTS_Running;
			break;
		case IAction::Finished: // this means 'about to finish'
		case IAction::None:
			return eTS_Completing;
			break;
		}

		break;
	};

	return m_state;
}
void CMountedGunController::OnEnter(EntityId mountedGunId)
{
    CRY_ASSERT_MESSAGE(m_pControlledPlayer, "Controlled player not initialized");

    ICharacterInstance* pCharacter = m_pControlledPlayer->IsThirdPerson() ? m_pControlledPlayer->GetEntity()->GetCharacter(0) : m_pControlledPlayer->GetShadowCharacter();
    if (pCharacter)
        {
            CItem* pWeapon = static_cast<CItem*>(g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(mountedGunId));
            assert(pWeapon);

            IActionController* pActionController = m_pControlledPlayer->GetAnimatedCharacter()->GetActionController();
            if (pActionController && m_pMannequinParams)
                {
                    SAFE_RELEASE(m_pMovementAction);

                    m_pMovementAction = new TPlayerAction(PP_PlayerAction, m_pMannequinParams->fragmentIDs.MotionMounted);
                    m_pMovementAction->AddRef();
                    pActionController->Queue(m_pMovementAction);
                }

            //////////////////////////////////////////////////////////////////////////
            // NOTE: This should go through mannequin
            CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
            if (pRecordingSystem)
                {
                    const SParams& pWeaponParams = pWeapon->GetParams();

                    IAnimationSet* pAnimationSet = pCharacter->GetIAnimationSet();
                    const int upAnimId = pAnimationSet->GetAnimIDByName(pWeaponParams.mountedTPAimAnims[MountedTPAimAnim::Up].c_str());
                    const int downAnimId = pAnimationSet->GetAnimIDByName(pWeaponParams.mountedTPAimAnims[MountedTPAimAnim::Down].c_str());

                    pRecordingSystem->OnMountedGunEnter(m_pControlledPlayer, upAnimId, downAnimId);
                }

            //////////////////////////////////////////////////////////////////////////

            IAnimatedCharacter* pAnimatedCharacter = m_pControlledPlayer->GetAnimatedCharacter();
            CRY_ASSERT(pAnimatedCharacter);

            pAnimatedCharacter->RequestPhysicalColliderMode(eColliderMode_Disabled, eColliderModeLayer_Game, "CMountedGunController::OnEnter");
            pAnimatedCharacter->SetNoMovementOverride(true);

            if (gEnv->bMultiplayer)
                pAnimatedCharacter->EnableRigidCollider(0.5f);
            else if (m_pControlledPlayer->IsPlayer())
                pAnimatedCharacter->EnableRigidCollider(1.5f);

            pAnimatedCharacter->GetGroundAlignmentParams().SetFlag(eGA_AllowWithNoCollision, true);

            BATTLECHATTER(BC_WatchMyBack, m_pControlledPlayer->GetEntityId());
        }
}
void CInteractiveObjectRegistry::ApplyInteractionToObject(IEntity *pEntity, const TagID interactionTypeTag, const int interactionIndex) const
{
	if (m_pDatabaseObject && m_pControllerDef)
	{
		IMannequin &mannequinSys = gEnv->pGame->GetIGameFramework()->GetMannequinInterface();
		SAnimationContext animContext(*m_pControllerDef);

		IActionController *pActionController = mannequinSys.CreateActionController(pEntity, animContext);

		int scopeContextID = m_pControllerDef->m_scopeContexts.Find("SlaveObject");
		pActionController->SetScopeContext(scopeContextID, *pEntity, pEntity->GetCharacter(0), m_pDatabaseObject);
		TagState fragTags = TAG_STATE_EMPTY;
		const CTagDefinition *pTagDef = m_pControllerDef->GetFragmentTagDef(m_interactFragID);
		if (pTagDef)
		{
			pTagDef->Set(fragTags, interactionTypeTag, true);
		}
		IAction *pAction = new TAction<SAnimationContext>(0, m_interactFragID, fragTags);
		pAction->SetOptionIdx(interactionIndex);
		pActionController->Queue(pAction);

		// Set the time increments to non-zero to force the ActionController::Update() to drive the animation to the end.
		// When time increment is zero, animation position will not update. This will be changed to a simpler process by Tom Berry at some point.
		const uint32 totalScopes = pActionController->GetTotalScopes();
		for(uint32 s=0; s<totalScopes; ++s)
		{
			pActionController->GetScope(s)->IncrementTime(0.001f);
		}
		pActionController->Update(1000.0f);
		// "false" here leaves the anim on the transition queue in the animation system so it isn't cleared on pActionController->Release().
		pActionController->ClearScopeContext(scopeContextID, false);

		pActionController->Release();

		CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
		if (pRecordingSystem)
		{
			pRecordingSystem->OnInteractiveObjectFinishedUse(pEntity->GetId(), interactionTypeTag, interactionIndex);
		}

	}
}
// ----------------------------------------------------------------------------
bool CMannequinAGState::SetActionOrSignalInput(_smart_ptr<CAnimActionAGAction>& pAction, TKeyValue& currentValue, InputID inputID, EAIActionType actionType, const char* defaultValue, uint32 defaultValueCRC, const char* value, TAnimationGraphQueryID* pQueryID, bool optional)
{
	IActionController* pActionController = GetActionController();
	if (!pActionController)
		return false;

	// TODO Where to get the priorities from?
	const int MANNEQUIN_PRIORITY = 2; // currently equal to PP_Action, just above movement, but underneath urgent actions, hit death, etc.

	TAnimationGraphQueryID queryID = 0;
	if (pQueryID)
		queryID = *pQueryID = GenerateQueryID();

	const uint32 valueCRC = CCrc32::ComputeLowercase(value);

	static uint32 idleCRC = CCrc32::ComputeLowercase("idle");
	static uint32 noneCRC = CCrc32::ComputeLowercase("none");
	const bool isUnsupportedFragmentID = ((valueCRC == idleCRC) || (valueCRC == noneCRC));
	const FragmentID fragmentID = isUnsupportedFragmentID ? FRAGMENT_ID_INVALID : pActionController->GetContext().controllerDef.m_fragmentIDs.Find(valueCRC);

	const bool isDefaultValue = (valueCRC == defaultValueCRC);

	const bool somethingIsPendingOrInstalled = pAction && pAction->IsPendingOrInstalled();

	if (isDefaultValue)
	{
		if ( actionType == EAT_Looping )
		{
			StopAnyLoopingExactPositioningAction();
		}

		const bool isPendingOrInstalled = !somethingIsPendingOrInstalled; // the fake action 'idle' isPendingOrInstalled if something else is NOT pending or installed
		if (isPendingOrInstalled)
		{
			// In the old sense: the current requested 'value' did not change, we were already 'idle'
			SendEvent_Entered(NULL, queryID, true);
		}
		else
		{
			currentValue = defaultValue;

			if (pAction)
			{
				pAction->Stop(); // this will eventually call Entered(..,false) of the user that was waiting on Entered()
				pAction = NULL;
			}

			// TODO: This is not entirely correct. The Entered() event for the idle action should only
			//   be called when you exactly "go back to idle". But this is not well defined in mannequin,
			//   so I just send it right away...
			SendEvent_Entered(NULL, queryID, true);

			SendEvent_ChangedInput(inputID, true); // tell whoever is listening to the input that it changed
		}

		return true;
	}
	else if (fragmentID != FRAGMENT_ID_INVALID)
	{
		const bool isPendingOrInstalled = 
			somethingIsPendingOrInstalled &&
			(pAction->GetValueCRC() == valueCRC);
		if (isPendingOrInstalled)
		{
			// In the old sense: the current requested 'value' did not change
			
			// reuse the old queryid, if there is one, otherwise set the new one
			if (pAction->GetQueryID())
			{
				queryID = pAction->GetQueryID();
				if (pQueryID)
					*pQueryID = queryID;
			}
			else
			{
				if (queryID)
					pAction->SetQueryID(queryID);
			}

			if (pAction->GetStatus() == IAction::Installed)
			{
				// The other system is already playing the same action.
				// Send the 'entered' event immediately
				// (afai can see the AG only did this for signals for some reason??)
				SendEvent_Entered(pAction, pAction->GetQueryID(), true);
			}
		}
		else
		{
			currentValue = value;

			pAction = new CAnimActionAGAction(MANNEQUIN_PRIORITY, fragmentID, *this, actionType, value, valueCRC, queryID);
			pActionController->Queue(*pAction.get());

			SendEvent_ChangedInput(inputID, true); // tell whoever is listening the input that it changed
		}

		return true;
	}
	else if (!optional)
	{
		// 'not optional' means invalid values get translated into the default value
		// (so we always set a value, hence the setting of values is 'not optional')
		// Recurse and pass the defaultValue as value:
		return SetActionOrSignalInput(pAction, currentValue, inputID, actionType, defaultValue, defaultValueCRC, defaultValue, NULL, true);
	}
	else
	{
#ifndef _RELEASE
		if(!isUnsupportedFragmentID)
		{
			CryWarning( VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CMannequinAGState::SetInput: Unable to find animation '%s'", value);
		}
#endif //#ifndef _RELEASE
		return false;
	}
}