void CFlowNode_AISequenceAction_WeaponHolster::HandleSequenceEvent(AIActionSequence::SequenceEvent sequenceEvent)
{
	switch(sequenceEvent)
	{
	case AIActionSequence::StartAction:
		{
			CRY_ASSERT_MESSAGE(m_actInfo.pEntity, "entity has magically gone");
			if (!m_actInfo.pEntity)
			{
				// the entity has gone for some reason, at least make sure the action gets finished properly and the FG continues
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			assert(gEnv && gEnv->pGame && gEnv->pGame->GetIGameFramework() && gEnv->pGame->GetIGameFramework()->GetIActorSystem());
			IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_actInfo.pEntity->GetId());
			if (!pActor)
			{
				CRY_ASSERT_MESSAGE(0, "Provided entity must be an IActor");
				CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Provided entity %s must be an IActor", m_actInfo.pEntity->GetName());
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			const bool skipHolsterAnimation = GetPortBool(&m_actInfo, InputPort_SkipHolsterAnimation);
			pActor->HolsterItem(true, !skipHolsterAnimation);
			FinishSequenceActionAndActivateOutputPort(OutputPort_Done);
		}
		break;
	}
}
void CFlowNode_AISequenceAction_WeaponDrawFromInventory::HandleSequenceEvent(AIActionSequence::SequenceEvent sequenceEvent)
{
	switch(sequenceEvent)
	{
	case AIActionSequence::StartAction:
		{
			CRY_ASSERT_MESSAGE(m_actInfo.pEntity, "entity has magically gone");
			if (!m_actInfo.pEntity)
			{
				// the entity has gone for some reason, at least make sure the action gets finished properly and the FG continues
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			assert(gEnv && gEnv->pGame && gEnv->pGame->GetIGameFramework() && gEnv->pGame->GetIGameFramework()->GetIActorSystem());
			IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_actInfo.pEntity->GetId());
			if (!pActor)
			{
				CRY_ASSERT_MESSAGE(0, "Provided entity must be an IActor");
				CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Provided entity %s must be an IActor", m_actInfo.pEntity->GetName());
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			assert(gEnv && gEnv->pGame && gEnv->pGame->GetIGameFramework() && gEnv->pGame->GetIGameFramework()->GetIItemSystem());
			IItemSystem* pItemSystem = gEnv->pGame->GetIGameFramework()->GetIItemSystem();

			IInventory* pInventory = pActor->GetInventory();
			if (!pInventory)
			{
				CRY_ASSERT_MESSAGE(0, "Actor has no inventory");
				CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Actor %s has no inventory", m_actInfo.pEntity->GetName());
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			pInventory->SetHolsteredItem(EntityId(0));	// otherwise trying to holster the new weapon later on will not work (i. e. will do nothing)

			// draw the weapon
			const string& weaponName = GetPortString(&m_actInfo, InputPort_WeaponName);
			pItemSystem->SetActorItem(pActor, weaponName.c_str(), false);

			FinishSequenceActionAndActivateOutputPort(OutputPort_Done);
		}
		break;
	}
}
void CFlowNode_AISequenceAction_ApproachAndEnterVehicle::EnterVehicleSeat(bool animationTransitionEnabled, IVehicleSeat* pVehicleSeatHint)
{
	if (!pVehicleSeatHint)
		pVehicleSeatHint = GetVehicleSeat(NULL);

	if (pVehicleSeatHint)
	{
		pVehicleSeatHint->GetVehicle()->RegisterVehicleEventListener(this, "CFlowNode_AISequenceAction_ApproachAndEnterVehicle");
		pVehicleSeatHint->Enter(m_entityId, animationTransitionEnabled);
	}
	else
	{
		// prematurely finish the action as the seat or entity has magically disappeared
		CancelSequenceAndActivateOutputPort(OutputPort_Done);
	}
}
void CFlowNode_AISequenceAction_VehicleRotateTurret::HandleSequenceEvent(AIActionSequence::SequenceEvent sequenceEvent)
{
	switch(sequenceEvent)
	{
	case AIActionSequence::StartAction:
		{
			if (!m_actInfo.pEntity)
			{
				// the entity has gone for some reason, at least make sure the action gets finished properly and the FG continues
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			assert(gEnv && gEnv->pGame && gEnv->pGame->GetIGameFramework() && gEnv->pGame->GetIGameFramework()->GetIActorSystem());
			IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_actInfo.pEntity->GetId());

			// ensure the FG entity is an IActor
			if (!pActor)
			{
				CRY_ASSERT_MESSAGE(0, "no compatible entity was provided");
				CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Actor %s failed to enter vehicle (no compatible entity was provided)", m_actInfo.pEntity->GetName());
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			// get the vehicle the actor is linked to
			IVehicle* pVehicle = pActor->GetLinkedVehicle();
			if (!pVehicle)
			{
				CRY_ASSERT_MESSAGE(0, "agent is not linked to a vehicle");
				CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Actor %s is not linked to a vehicle", m_actInfo.pEntity->GetName());
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			// get the seat the actor is sitting on
			CVehicleSeat* pSeat = static_cast<CVehicleSeat*>(pVehicle->GetSeatForPassenger(m_actInfo.pEntity->GetId()));
			if (!pSeat)
			{
				CRY_ASSERT_MESSAGE(0, "agent is not sitting in the vehicle it is linked to");
				CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Actor %s is not sitting in the vehicle it is linked to", m_actInfo.pEntity->GetName());
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			// scan for the seat-action that allows rotating the turret
			TVehicleSeatActionVector& seatActions = pSeat->GetSeatActions();
			for (TVehicleSeatActionVector::iterator it = seatActions.begin(); it != seatActions.end(); ++it)
			{
				IVehicleSeatAction* pSeatAction = it->pSeatAction;
				if ((m_pActionRotateTurret = CAST_VEHICLEOBJECT(CVehicleSeatActionRotateTurret, pSeatAction)))
				{
					break;
				}
			}

			// ensure the vehicle-seat provided the correct action
			if (!m_pActionRotateTurret)
			{
				CRY_ASSERT_MESSAGE(0, "a CVehicleSeatActionRotateTurret is not provided by the vehicle or someone else in the vehicle has reserved that action already.");
				CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Actor %s could not find a CVehicleSeatActionRotateTurret or that action is already reserved by someone else", m_actInfo.pEntity->GetName());
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			m_pitchThreshold = GetPortFloat(&m_actInfo, InputPort_ThresholdPitch);
			m_yawThreshold = GetPortFloat(&m_actInfo, InputPort_ThresholdYaw);

			Vec3 aimPos = GetPortVec3(&m_actInfo, InputPort_AimPos);
			m_pActionRotateTurret->SetAimGoal(aimPos);
		}
		break;

	case AIActionSequence::SequenceStopped:
		{
			if (m_pActionRotateTurret)
			{
				// cancel the rotation action
				m_pActionRotateTurret->SetAimGoal(Vec3Constants<float>::fVec3_Zero);
				m_pActionRotateTurret = NULL;
			}
		}
		break;
	}
}
void CFlowNode_AISequenceAction_ApproachAndEnterVehicle::HandleSequenceEvent(AIActionSequence::SequenceEvent sequenceEvent)
{
	switch(sequenceEvent)
	{
	case AIActionSequence::StartAction:
		{
			if (!m_actInfo.pEntity)
			{
				// the entity has gone for some reason, at least make sure the action gets finished properly and the FG continues
				UnregisterFromVehicleEvent(NULL);
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			m_entityId = m_actInfo.pEntity->GetId();
			m_vehicleId = GetPortEntityId(&m_actInfo, InputPort_VehicleId);
			m_seatNumber = GetPortInt(&m_actInfo, InputPort_SeatNumber);
			m_fast = GetPortBool(&m_actInfo, InputPort_Fast);

			const bool alsoCheckForCrewHostility = true;
			IVehicle* pVehicle = GetVehicle(alsoCheckForCrewHostility);
			if (!pVehicle)
			{
				CryLog("Actor %s failed to enter vehicle (specified vehicle not found or its crew is hostile towards the actor returned true)", m_actInfo.pEntity->GetName());
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			IVehicleSeat* pSeat = GetVehicleSeat(pVehicle);
			if (!pSeat)
			{
				CryLog("Actor %s failed to enter vehicle (bad seat number provided: %i)", m_actInfo.pEntity->GetName(), m_seatNumber);
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			const IVehicleHelper* pEnterHelper = static_cast<CVehicleSeat*>(pSeat)->GetEnterHelper();
			if (!pEnterHelper)
			{
				CryLog("Actor %s failed to enter vehicle (vehicle has no enter-helper)", m_actInfo.pEntity->GetName());
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
				return;
			}

			m_vehicleSeatEnterPosition = pEnterHelper->GetWorldSpaceTranslation();

			assert(gEnv && gEnv->pGame && gEnv->pGame->GetIGameFramework() && gEnv->pGame->GetIGameFramework()->GetIActorSystem());
			IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_actInfo.pEntity->GetId());

			// if it's the player, have him enter quickly (we assume that the user moved him close enough to the vehicle)
			if (pActor && pActor->IsPlayer())
			{
				EnterVehicleSeat(true, pSeat);
			}
			else if (m_actInfo.pEntity->GetAI())
			{
				if (m_fast)
				{
					TeleportToVehicleSeat();
					EnterVehicleSeat(false, pSeat);
				}
				else
				{
					MovementRequest request;
					request.callback = functor(*this, &CFlowNode_AISequenceAction_ApproachAndEnterVehicle::MovementRequestCallback);
					request.entityID = m_actInfo.pEntity->GetId();
					request.type = MovementRequest::MoveTo;
					request.destination = m_vehicleSeatEnterPosition;
					request.style.SetSpeed((MovementStyle::Speed)GetPortInt(&m_actInfo, InputPort_Speed));
					request.style.SetStance((MovementStyle::Stance)GetPortInt(&m_actInfo, InputPort_Stance));
					m_movementRequestID = gEnv->pAISystem->GetMovementSystem()->QueueRequest(request);
				}
			}
			else if (pActor)
			{
				pActor->HolsterItem(true);
				pActor->MountedGunControllerEnabled(false);
				pActor->GetGameObject()->SetAspectProfile(eEA_Physics, eAP_Alive);
				TeleportToVehicleSeat();
				EnterVehicleSeat(GetAnimationTransitionEnabled(), pSeat);
			}
			else
			{
				CRY_ASSERT_MESSAGE(0, "no compatible entity was provided");
				CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Actor %s failed to enter vehicle (no compatible entity was provided)", m_actInfo.pEntity->GetName());
				CancelSequenceAndActivateOutputPort(OutputPort_Done);
			}
		}
		break;

	case AIActionSequence::SequenceStopped:
		{
			if (m_movementRequestID)
			{
				gEnv->pAISystem->GetMovementSystem()->CancelRequest(m_movementRequestID);
				m_movementRequestID = MovementRequestID::Invalid();
				UnregisterFromVehicleEvent(NULL);
			}
		}
		break;
	}
}