Exemple #1
0
/********************************
CloseTop()
    Close the currently open message by reading all
    availabe lines of the Top response if any.
PARAM
    NONE
RETURN
    UTE_SUCCESS         - Success
    UTE_NOCONNECTION    - NOT connected
*********************************/
int CUT_POP3Client::CloseTop(){
    int     error = UTE_SUCCESS;

    if(m_bTopOpen == FALSE)
        return OnError(UTE_SUCCESS);

    //check to see if the connection is made
    if(!IsConnected())
        return OnError(UTE_NOCONNECTION);
    
    int len;

    while(!m_bReadTopFinished) {
        if(IsAborted()) {       // Test for abortion flag
            error = UTE_ABORTED;
            break;
            }

        //read in a line
        len = ReceiveLine(m_szBuf,sizeof(m_szBuf),m_nPOP3TimeOut);
        
        if( len  <= 0 )
            break;
        
        if(m_szBuf[0] == '.' && len <= 3)
            break;
        }

    m_bTopOpen = FALSE;
    m_bReadTopFinished = FALSE;

    return OnError(error);
}
Exemple #2
0
void CurlDownloaderRequest::SendImpl ()
{
	LOG_CURL ("BRIDGE CurlDownloaderRequest::Send %p\n", this);

	if (IsAborted ())
		return;

	VERIFY_MAIN_THREAD

	state = OPENED;

	if (isPost ())
		curl_easy_setopt(curl, CURLOPT_POST, 1);

	// we're ready to start the connection, set the headers
	response = new CurlDownloaderResponse (bridge, this);
	curl_easy_setopt (curl, CURLOPT_URL, GetUri ());
	curl_easy_setopt (curl, CURLOPT_HTTPHEADER, headers);
	curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, data_received);
	curl_easy_setopt (curl, CURLOPT_WRITEDATA, response);
	curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, header_received);
	curl_easy_setopt (curl, CURLOPT_WRITEHEADER, response);

	response->Open ();
}
Exemple #3
0
PrintDraw::~PrintDraw() {
	DrawLock __;
	if(IsAborted())
		::AbortDoc(handle);
	else
		::EndDoc(handle);
	DeleteDC(handle);
	handle = NULL;
}
Exemple #4
0
void PrintDraw::EndPage()
{
	DrawLock __;
	if(IsAborted()) return;
	Unselect();
	ASSERT(printer);
	if(::EndPage(handle) <= 0)
		Abort();
}
Exemple #5
0
void PrintDraw::StartPage()
{
	DrawLock __;
	if(IsAborted()) return;
	Unselect();
	if(::StartPage(handle) <= 0)
		Abort();
	else
		InitPrinter();
}
CRef<CPrefetchRequest> CPrefetchManager_Impl::AddAction(TPriority priority,
                                                        IPrefetchAction* action,
                                                        IPrefetchListener* listener)
{
    CMutexGuard guard0(GetMainPoolMutex());
    if ( action && IsAborted() ) {
        throw prefetch::CCancelRequestException();
    }
    CMutexGuard guard(m_StateMutex->GetData());
    CRef<CPrefetchRequest> req(new CPrefetchRequest(m_StateMutex,
                                                    action,
                                                    listener,
                                                    priority));
    AddTask(req);
    return req;
}
Exemple #7
0
int CUT_POP3Client::POP3Connect(LPCSTR mailHost, LPCSTR user, LPCSTR password) {

    int     error;

    //close any open connection
    POP3Close();

    //connect
    if((error = Connect(m_nPort, mailHost, m_nConnectTimeout)) != UTE_SUCCESS) 
        return OnError(error);
    
    //get the response code
	if(GetResponseCode(m_nPOP3TimeOut) == FALSE)
		return OnError(UTE_CONNECT_TIMEOUT);

    //send the user name
    Send("USER ");
    Send(user);
    Send("\r\n");

    if(GetResponseCode(m_nPOP3TimeOut) == FALSE)
        return OnError(UTE_USER_FAILED);

    if(IsAborted())         // Test for abortion flag
        return OnError(UTE_ABORTED);

    //send the password
    Send("PASS ");
    Send(password);
    Send("\r\n");

    if(GetResponseCode(m_nPOP3TimeOut) == FALSE)
        return OnError(UTE_PASS_FAILED);


    return OnError(UTE_SUCCESS);
}
Exemple #8
0
/***************************************************
ReceiveFileStatus
    This virtual function is called during a 
    ReceiveToFile function.
Params
    bytesReceived - number of bytes received so far
Return
    TRUE - allow the receive to continue
    FALSE - abort the receive
****************************************************/
BOOL CUT_FingerClient::ReceiveFileStatus(long bytesReceived){
    if(IsAborted())     
        return FALSE;
    return CUT_WSClient::ReceiveFileStatus(bytesReceived);
}
Exemple #9
0
/*********************************************
Finger
    Performs the finger for the specified address
    the information that is returned can be 
    retrieved with the GetReturnLine function.

    If filename parameter was specified all the 
    received data is saved in the file. In this 
    case you can't access data with GetReturnLine 
    function.

Params
    address     - address to perform the finger on. 
                  address format is: @domain.com or 
                  [email protected]

    dest        - data source for saving received data
    [fileType]  -   -1              - don't use
                    UTM_OM_WRITING  - open writing
                    UTM_OM_APPEND   - open for appending 


Return
    UTE_SUCCESS                 - success
    UTE_INVALID_ADDRESS_FORMAT  - invalid address format
    UTE_INVALID_ADDRESS         - invalid address
    UTE_CONNECT_FAILED          - connection failed
    UTE_NO_RESPONSE             - no response
    UTE_ABORTED                 - aborted
    UTE_CONNECT_TIMEOUT         - time out
**********************************************/
int CUT_FingerClient::Finger(LPTSTR address, CUT_DataSource & dest, OpenMsgType fileType) 
{
    
    int     error = UTE_SUCCESS;
    int     len;
    char    buf[MAX_PATH+1];
    char    domain[MAX_PATH+1];

    //delete prev finger information
    m_listReturnLines.ClearList();          

    //split the address apart
	// v4.2 address splitting into name and domain allows AC macro, hence LPTSTR in interface.
    if(SplitAddress(buf,domain,AC(address)) != UTE_SUCCESS)
        return OnError(UTE_INVALID_ADDRESS_FORMAT);

    //check to see if the domain is a name or address
    if(IsIPAddress(domain) != TRUE) {
        //get the name from the address
        if(GetAddressFromName(domain,domain,sizeof(domain)) != UTE_SUCCESS)
            return OnError(UTE_INVALID_ADDRESS);
        }

    //connect using a timeout
    if((error=Connect(m_nPort, domain, m_nConnectTimeout)) != UTE_SUCCESS)
        return OnError(error);

    if(IsAborted())                         // Test abort flag
        error = UTE_ABORTED;                // Aborted

    if(error == UTE_SUCCESS) {

        //send the name to finger
        Send(buf);
        Send("\r\n");

        // Read data into the file
        if(fileType != -1) {
            error = Receive(dest, fileType, m_nReceiveTimeout);
            }

        // Read data line by line & save it in the string list
        else {
            //read in the return lines

			// v4.2 change to eliminate C4127:conditional expression is constant
			for(;;) {
				if(IsAborted()) {                       // Test abort flag
                    error = UTE_ABORTED;                // Aborted
                    break;
                    }

                //wait for a receive
                if(WaitForReceive(m_nReceiveTimeout, 0)!= UTE_SUCCESS)
                    break;
        
                //get the information
                len = ReceiveLine(buf, sizeof(buf)-1);
                if(len <= 0)
                    break;
        
                buf[len]=0;
                CUT_StrMethods::RemoveCRLF(buf);

                //store the information
                m_listReturnLines.AddString(buf);
                }

            if (error == UTE_SUCCESS && m_listReturnLines.GetCount() == 0)
                error = UTE_NO_RESPONSE;                // No response
            }
        }

    // Close connection
    CloseConnection();

    return OnError(error);
}
Exemple #10
0
/********************************
    Virtual function designed to be overridden to  
    receive report of progress of save message process.

    To abort the Save Message process return false

PARAM
    bytesRetrieved - Number of bytes received so far
RETURN
    TRUE    - to continue
    FALSE   - to cancel
*********************************/
BOOL CUT_POP3Client::OnSaveMsg(long /*  bytesRetrieved */ ){
    return !IsAborted();
}
Exemple #11
0
/********************************
RetrieveUID
    Retrieves the unique-id of one or all messages. You can use
    the GetUID(...) method to get the unique-id string.

    "The unique-id of a message is an arbitrary server-determined
    string, consisting of one to 70 characters in the range 0x21
    to 0x7E, which uniquely identifies a message within a
    maildrop and which persists across sessions.  This
    persistence is required even if a session ends without
    entering the UPDATE state.  The server should never reuse an
    unique-id in a given maildrop, for as long as the entity
    using the unique-id exists.

    Note that messages marked as deleted are not listed." RFC 1939

PARAM
    [msgNumber] - the number of message to get UID for.
                  If set to -1 (default) retieve UIDs for all messages
RETURN
    UTE_SUCCESS         - Success
    UTE_NOCONNECTION    - NOT connected
    UTE_SVR_NO_RESPONSE - no response from Server
    UTE_UIDL_FAILED     - UIDL command has timed out without a response from the server
*********************************/
int CUT_POP3Client::RetrieveUID(int msgNumber)
{
    int error = UTE_SUCCESS;

    // clear the current vector
    m_vecUID.erase(m_vecUID.begin(), m_vecUID.end());

    //check to see if the connection is made
    if(!IsConnected())
        return OnError(UTE_NOCONNECTION);

    //send the UIDL command
    if(msgNumber >= 1)
        _snprintf(m_szBuf,sizeof(m_szBuf)-1,"UIDL %d\r\n", msgNumber);
    else 
        _snprintf(m_szBuf,sizeof(m_szBuf)-1,"UIDL\r\n");
    Send(m_szBuf);

    //get the response
    if(ReceiveLine(m_szBuf,sizeof(m_szBuf),m_nPOP3TimeOut) <= 0)
        return OnError(UTE_SVR_NO_RESPONSE);

    if(m_szBuf[0] != '+')  // '-' response probably flags 'not implemented'.
        return OnError(UTE_UIDL_FAILED);        // UIDL was/is an optional POP3 option 

    // If we are getting only one UID - get it from the response
    char        szBuffer[MAX_UID_STRING_LENGTH + 1];
    MessageUID  messageID;
    if(msgNumber >= 1) {
        if(CUT_StrMethods::ParseString(m_szBuf," \r\n", 2, szBuffer, MAX_UID_STRING_LENGTH) != UTE_SUCCESS)
            return OnError(UTE_INVALID_RESPONSE);

        // Initialize UID structure
        messageID.m_nMessageNumber = msgNumber;
        messageID.m_strUID = szBuffer;

        // Add UID structure to the vector
        m_vecUID.push_back(messageID);
        }

    // We should get the multiline response with UIDs
    else {
        int len;
        while(!m_bReadTopFinished) {
            if(IsAborted()) {       // Test for abortion flag
                error = UTE_ABORTED;
                break;
                }

            // read in a line
            len = ReceiveLine(m_szBuf,sizeof(m_szBuf),m_nPOP3TimeOut);
            if( len  <= 0 ) {
                error = UTE_SOCK_TIMEOUT;
                break;
                }

            // end of multiline response
            if(m_szBuf[0] == '.' && len <= 3)
                break;

            // Get message number
            if(CUT_StrMethods::ParseString(m_szBuf," \r\n", 0, &messageID.m_nMessageNumber) != UTE_SUCCESS) {
                error = UTE_INVALID_RESPONSE;
                break;
                }

            // Get message UID
            if(CUT_StrMethods::ParseString(m_szBuf," \r\n", 1, szBuffer, MAX_UID_STRING_LENGTH) != UTE_SUCCESS) {
                error = UTE_INVALID_RESPONSE;
                break;
                }

            // Initialize UID structure
            messageID.m_strUID = szBuffer;

            // Add UID structure to the vector
            m_vecUID.push_back(messageID);
            }
        }

    return OnError(error);
}
Exemple #12
0
/********************************
SaveMsg()
    Retrives (RETR) and Saves the specified message to 
    the data source
NOTE
    Message index is 1 based NOT zero based
PARAM   
    index       - Index of the message to be saved
    dest        - destination data source
RETURN
    UTE_SUCCESS         - Success
    UTE_NOCONNECTION    - NOT connected
    UTE_SVR_NO_RESPONSE - no response from Server
    UTE_FILE_OPEN_ERROR - Not able to open file for writing
    UTE_RETR_FAILED     - RETR command has timed out without a response from the server
    UTE_SOCK_TIMEOUT    - Timed out while receiving parts of the message
    UTE_ABORTED         - User canceled the Save to file process
*********************************/
int CUT_POP3Client::SaveMsg(int index, CUT_DataSource & dest) {

    int         error = UTE_SUCCESS;
    int         len;
    UINT        bytesReceived = 0;

    //check to see if the connection is made
    if(!IsConnected())
        return OnError(UTE_NOCONNECTION);

    //open the destination file
    if(dest.Open(UTM_OM_WRITING) == -1)
        return OnError(UTE_FILE_OPEN_ERROR);

    //send the RETR command
    _snprintf(m_szBuf,sizeof(m_szBuf)-1,"RETR %d\r\n",index);
    Send(m_szBuf);
    

    //get the response
    if(ReceiveLine(m_szBuf,sizeof(m_szBuf)-1, m_nPOP3TimeOut) <= 0)
        return OnError(UTE_SVR_NO_RESPONSE);

    if(m_szBuf[0] != '+')
        return OnError(UTE_RETR_FAILED);

    //read in and save the message
	// v4.2 change to eliminate C4127: conditional expression is constant
    for(;;) {
        if(IsAborted()) {       // Test for abortion flag
            error = UTE_ABORTED;
            break;
            }
    
        //read in a line
        len = ReceiveLine(m_szBuf,sizeof(m_szBuf)-1,m_nPOP3TimeOut);


        if( len  <= 0 ) {
            error = UTE_SOCK_TIMEOUT;
            break;
            }

        bytesReceived += len;

        if (OnSaveMsg(bytesReceived) != TRUE) {
            error = UTE_ABORTED;       // User cancel the save message
            break; // call status func
            }

        //if a period is found at the beginning of a line then
        //check to see if it is the end of the message
        if(m_szBuf[0] == '.') {
            //end of message
            if(len == 3)       
                break;
            
            //save line
            else
                dest.Write(&m_szBuf[1], len-1);
            }
        else
            dest.Write(m_szBuf, len);
    }

    // Close data source
    dest.Close();

    return OnError(error);
}
void CDialogActorContext::CancelCurrent(bool bResetStates)
{
	if (!m_bNeedsCancel)
		return;

	assert (m_bInCancel == false);
	if (m_bInCancel == true)
		return;
	m_bInCancel = true;

	// remove from AG
	if (m_pAGState != 0)
	{
		m_pAGState->RemoveListener(this);
		if (bResetStates)
		{
			ResetAGState();
		}
		m_pAGState = 0;
	}
	m_queryID = 0;
	m_bAnimStarted = false;

	// reset lookat
	IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_entityID);
	if (pEntity)
	{
		IAIObject* pAI = pEntity->GetAI();
		if (pAI)
		{
			IAIActor* pAIActor = pAI->CastToIAIActor();
			if (pAIActor)
			{
				if (m_bLookAtNeedsReset)
				{
					pAIActor->ResetLookAt();
					m_bLookAtNeedsReset = false;
				}
			
				IPipeUser* pPipeUser = pAI->CastToIPipeUser();
				if (pPipeUser)
				{
					if (m_goalPipeID > 0)
					{
						if (GetAIBehaviourMode() == CDialogSession::eDIB_InterruptMedium)
						{
							int dummyPipe = 0;
							ExecuteAI(dummyPipe, "ACT_DIALOG_OVER", 0, false);
						}
						pPipeUser->UnRegisterGoalPipeListener( this, m_goalPipeID );
						pPipeUser->RemoveSubPipe(m_goalPipeID, true);
						m_goalPipeID = 0;
					}
					if (m_exPosAnimPipeID > 0)
					{
						pPipeUser->UnRegisterGoalPipeListener( this, m_exPosAnimPipeID );
						pPipeUser->CancelSubPipe(m_exPosAnimPipeID);
						pPipeUser->RemoveSubPipe(m_exPosAnimPipeID, false);
						m_exPosAnimPipeID = 0;
					}
				}
			}
		}
	}

	// facial expression is always reset
	// if (bResetStates)
	{
		// Reset Facial Expression
		IEntity* pActorEntity = m_pSession->GetActorEntity(m_actorID);
		if (pActorEntity)
		{
			DoFacialExpression(pActorEntity, "", 1.0f, 0.0f);
		}
	}

	// should we stop the current sound?
	// we don't stop the sound if the actor aborts and has eDACF_NoAbortSound set.
	// if actor died (entity destroyed) though, sound is stopped anyway
	const bool bDontStopSound = (IsAborted() == false && CheckActorFlags(CDialogSession::eDACF_NoAbortSound))
		|| (IsAborted() 
		&& CheckActorFlags(CDialogSession::eDACF_NoAbortSound)
		&& GetAbortReason() != CDialogSession::eAR_ActorDead
		&& GetAbortReason() != CDialogSession::eAR_EntityDestroyed);

	if (bDontStopSound == false)
	{
		// stop sound (this also forces m_soundId to be INVALID_SOUNDID) and markes Context as non-playing!
		// e.g. IsStillPlaying will then return false
		// we explicitly stop the sound in the d'tor if we don't take this path here
		StopSound(); 
	}

	IEntitySystem* pES = gEnv->pEntitySystem;
	pES->RemoveEntityEventListener( m_entityID, ENTITY_EVENT_AI_DONE, this );
	pES->RemoveEntityEventListener( m_entityID, ENTITY_EVENT_DONE, this );
	pES->RemoveEntityEventListener( m_entityID, ENTITY_EVENT_RESET, this );

	m_phase = eDAC_Idle;

	m_bInCancel = false;
	m_bNeedsCancel = false;
}
bool CDialogActorContext::Update(float dt)
{
	if (IsAborted())
		return true;

	// FIXME: this should never happen, as we should get a notification before.
	//        temp leave in for tracking down a bug [AlexL: 23/11/2006]
	IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_entityID);
	if (pEntity == 0)
	{
		m_pIActor = 0;
		GameWarning("[DIALOG] CDialogActorContext::Update: %s Actor=%d (EntityId=%d) no longer existent.",
			m_pSession->GetDebugName(), m_actorID, m_entityID);
		AbortContext(true, CDialogSession::eAR_EntityDestroyed);
		return true;
	}

	CDialogSession::AlertnessInterruptMode alertnessInterruptMode = m_pSession->GetAlertnessInterruptMode();
	if(alertnessInterruptMode != CDialogSession::None)
	{
		if(IAIObject* aiObject = pEntity->GetAI())
		{
			if(IAIActorProxy* aiActorProxy = aiObject->GetProxy())
			{
				if(aiActorProxy->GetAlertnessState() >= alertnessInterruptMode)
				{
					AbortContext(true, CDialogSession::eAR_AIAborted);
					return true;
				}
			}
		}
	}

	float now = m_pSession->GetCurTime();

	if (!CheckActorFlags(CDialogSession::eDACF_NoActorDeadAbort) && m_pIActor && m_pIActor->IsDead())
	{
		if (!IsAborted())
		{
			DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Actor=%d (EntityId=%d) has died. Aborting.",
				m_pSession->GetDebugName(), m_actorID, m_entityID);
			AbortContext(true, CDialogSession::eAR_ActorDead);
			return true;
		}
	}

	if (m_bIsLocalPlayer)
	{
		// when the local player is involved in the conversation do some special checks
		if (DoLocalPlayerChecks(dt) == false)
		{
			DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Abort from LocalPlayer.", m_pSession->GetDebugName());
			AbortContext(true, m_bIsAwareInRange == false ? CDialogSession::eAR_PlayerOutOfRange : CDialogSession::eAR_PlayerOutOfView);
			return true;
		}
	}

	if (m_bAbortFromAI)
	{
		m_bAbortFromAI = false;
		if (!IsAborted())
		{
			DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Abort from AI.", m_pSession->GetDebugName());
			AbortContext(true, CDialogSession::eAR_AIAborted);
			return true;
		}
	}

	if (SessionAllowsLookAt())
	{
		DoStickyLookAt();
	}

	int loop = 0;
	do 
	{
		// DiaLOG::Log("[DIALOG] DiaLOG::eAlways"CDialogActorContext::Update: %s now=%f actorId=%d loop=%d", m_pSession->GetDebugName(), now, m_actorID, loop);

		bool bAdvance = false;
		switch (m_phase)
		{
		case eDAC_Idle:
			break;

		case eDAC_NewLine:
			{
				m_bHasScheduled = false;
				m_lookAtTimeOut = LOOKAT_TIMEOUT;
				m_animTimeOut   = ANIM_TIMEOUT;
				m_soundTimeOut  = SOUND_TIMEOUT; // wait one second until sound is timed out
				m_bAnimScheduled = false;
				m_bAnimStarted   = false;
				m_bSoundScheduled = false;
				m_bSoundStarted   = false;
				m_soundLength   = 0.0f;

				if (m_pCurLine->m_flagResetLookAt)
				{
					m_stickyLookAtActorID = CDialogScript::NO_ACTOR_ID;
					m_lookAtActorID = CDialogScript::NO_ACTOR_ID;
				}
				// check if look-at sticky is set
				else if (m_pCurLine->m_lookatActor != CDialogScript::NO_ACTOR_ID)
				{
					if (m_pCurLine->m_flagLookAtSticky == false)
					{
						m_lookAtActorID = m_pCurLine->m_lookatActor;
						m_stickyLookAtActorID = CDialogScript::NO_ACTOR_ID;
					}
					else
					{
						m_stickyLookAtActorID = m_pCurLine->m_lookatActor;
						m_lookAtActorID = CDialogScript::NO_ACTOR_ID;
					}
				}

				bAdvance = true;

				// handle the first sticky look-at here
				if (SessionAllowsLookAt())
				{
					DoStickyLookAt();
				}









			}
			break;

		case eDAC_LookAt:
			{
				bool bWaitForLookAtFinish = true;
				bAdvance = true;
	
				if (SessionAllowsLookAt() == false)
				{
					break;
				}

				// Question: maybe do this although EP is requested
				if (bWaitForLookAtFinish && m_lookAtActorID != CDialogScript::NO_ACTOR_ID && m_pCurLine->m_flagAGEP == false) 
				{
					IEntity* pActorEntity = m_pSession->GetActorEntity(m_actorID);
					IEntity* pLookAtEntity = m_pSession->GetActorEntity(m_lookAtActorID);
					if (pActorEntity != 0)
					{
						m_lookAtTimeOut -= dt;
						bool bTargetReached;
						//bool bSuccess = DoLookAt(pActorEntity, pLookAtEntity, bTargetReached);
						DoLookAt(pActorEntity, pLookAtEntity, bTargetReached);
						//DiaLOG::Log(DiaLOG::eDebugA, "[DIALOG] CDialogActorContext::Update: %s now=%f actorID=%d phase=eDAC_LookAt %d",
						//	m_pSession->GetDebugName(), now, m_actorID, bTargetReached);

						if (/* bSuccess == false || */ bTargetReached || m_lookAtTimeOut<=0.0f)
						{
							DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s now=%f actorID=%d phase=eDAC_LookAt %s",
								m_pSession->GetDebugName(), now, m_actorID, bTargetReached ? "Target Reached" : "Timed Out");
							m_lookAtActorID = CDialogScript::NO_ACTOR_ID;
						}
						else
							bAdvance = false;
					}
				}
			}
			break;

		case eDAC_Anim:
			{
				bAdvance = true;
				if (SessionAllowsLookAt() && m_lookAtActorID != CDialogScript::NO_ACTOR_ID) // maybe: don't do this when EP is requested [&& m_pCurLine->m_flagAGEP == false]
				{
					IEntity* pActorEntity = m_pSession->GetActorEntity(m_actorID);
					IEntity* pLookAtEntity = m_pSession->GetActorEntity(m_lookAtActorID);
					if (pActorEntity != 0)
					{
						m_lookAtTimeOut -= dt;
						bool bTargetReached;
						//bool bSuccess = DoLookAt(pActorEntity, pLookAtEntity, bTargetReached);
						DoLookAt(pActorEntity, pLookAtEntity, bTargetReached);
						if (/* bSuccess == false || */ bTargetReached || m_lookAtTimeOut<=0.0f)
						{
							DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s now=%f actorID=%d phase=eDAC_Anim %s",
								m_pSession->GetDebugName(), now, m_actorID, bTargetReached ? "Target Reached" : "Timed Out");
							m_lookAtActorID = CDialogScript::NO_ACTOR_ID;
						}
						else
							bAdvance = false;
					}
				}
				const bool bHasAnim = !m_pCurLine->m_anim.empty();
				if (SessionAllowsAnim() && bHasAnim)
				{
					bAdvance = false;
					if (!m_bAnimScheduled)
					{
						m_bSoundStopsAnim = false; // whenever there is a new animation, no need for the still playing sound
						                           // to stop the animation
						m_bAnimStarted = false;
						m_bAnimScheduled = true;
						// schedule animation
						IEntity* pActorEntity = m_pSession->GetActorEntity(m_actorID);
						if (pActorEntity)
							DoAnimAction(pActorEntity, m_pCurLine->m_anim, m_pCurLine->m_flagAGSignal, m_pCurLine->m_flagAGEP);
						else
							bAdvance = true;
					}
					else
					{
						// we scheduled it already
						// wait until it starts or timeout
						m_animTimeOut-=dt;
						bAdvance = m_animTimeOut <= 0.0f || m_bAnimStarted;
						if (bAdvance)
						{
							DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Now=%f actorID=%d phase=eDAC_Anim %s",
								m_pSession->GetDebugName(), now, m_actorID, m_bAnimStarted ? "Anim Started" : "Anim Timed Out");
						}
					}
				}
			}
			break;

		case eDAC_ScheduleSoundPlay:
			{
				bAdvance = true;
				const bool bHasSound  = !m_pCurLine->m_sound.empty();
				if (bHasSound)
				{
					if (m_bSoundScheduled == false)
					{
						IEntity* pActorEntity = m_pSession->GetActorEntity(m_actorID);
						if (pActorEntity == 0)
							break;

						IEntityAudioProxy* pActorAudioProxy = m_pSession->GetEntityAudioProxy(pActorEntity);
						if (pActorAudioProxy == 0)
							break;

						REINST("play voice line");
						// start a new sound
						//int sFlags = CDialogActorContext::SOUND_FLAGS;
						//if (CDialogSystem::sLoadSoundSynchronously != 0)
						//	sFlags |= FLAG_SOUND_LOAD_SYNCHRONOUSLY;
						//
						//// if it's the local player make the sound relative to the entity
						//if (m_bIsLocalPlayer)
						//	sFlags |= FLAG_SOUND_RELATIVE;

						//const char* soundKey = GetSoundKey(m_pCurLine->m_sound);
						//ISound* pSound = 0;

						//pSound = gEnv->pAudioSystem->CreateSound(soundKey, sFlags);

						//DiaLOG::Log(DiaLOG::eDebugA, "[DIALOG] CDialogActorContex::Update: %s Now=%f actorID=%d phase=eDAC_ScheduleSoundPlay: Starting '%s' [key=%s]",
						//	m_pSession->GetDebugName(), now, m_actorID, m_pCurLine->m_sound.c_str(), soundKey);

						//if (!pSound) 
						//{
						//	GameWarning("[DIALOG] CDialogActorContext::Update: %s ActorID=%d: Cannot play sound '%s'",
						//		m_pSession->GetDebugName(), m_actorID, m_pCurLine->m_sound.c_str());
						//}

						//if (pSound)
						//{
						//	if (m_bSoundStopsAnim)
						//	{
						//		m_bSoundStopsAnim = false;
						//		if (m_pAGState != 0)
						//		{
						//			ResetAGState();
						//			DiaLOG::Log(DiaLOG::eDebugA, "[DIALOG] CDialogActorContext::Update: %s Now=%f actorID=%d phase=eDAC_ScheduleSoundPlay: Stopping old animation",
						//				m_pSession->GetDebugName(), now, m_actorID);
						//		}
						//	}
						//	StopSound(); // apparently, if we dont explicitely stop the sound, in rare cases it never stops. Im pretty sure that is an engine/fmod bug.
						//	             // stopping it this way may lead to some subtitles staying for an extra couple seconds on screen (this comes from another engine bug/problem related to an extra fade out time added to cover the dummy NAX soudns) 
						//	m_soundID = pSound->GetId();
						//	m_bSoundStarted = false;
						//	m_bSoundScheduled = true;
						//	// tell the animation whether to stop on sound stop
						//	m_bSoundStopsAnim = m_pCurLine->m_flagSoundStopsAnim;

						//	DiaLOG::Log(DiaLOG::eDebugA, "[DIALOG] CDialogActorContext::Update: %s Now=%f actorID=%d phase=eDAC_ScheduleSoundPlay: Reg as listener on 0x%p '%s'",
						//		m_pSession->GetDebugName(), now, m_actorID, pSound, pSound->GetName());

						//	pSound->SetSemantic(eSoundSemantic_Dialog);
						//	pSound->AddEventListener(this, "DialogActor"); // event listener will set m_soundLength
						//	// sound proxy uses head pos on dialog sounds
						//	const bool bResult = pActorAudioProxy->PlaySound(pSound, Vec3(ZERO), FORWARD_DIRECTION, 1.0f);

						//	if (bResult)
						//	{
						//		// Fetch some localization info for the sound
						//		ILocalizationManager* pLocMgr = gEnv->pSystem->GetLocalizationManager();
						//		if (pLocMgr && CDialogSystem::sWarnOnMissingLoc != 0)
						//		{
						//			SLocalizedInfoGame GameInfo;

						//			const bool bFound = pLocMgr->GetLocalizedInfoByKey(soundKey, GameInfo);
						//			if (!bFound)
						//			{
						//				GameWarning("[DIALOG] CDialogActorContext::Update: '%s' DialogScript '%s': Localized info for '%s' not found!", 
						//					m_pSession->GetDebugName(), m_pSession->GetScript()->GetID().c_str(), m_pCurLine->m_sound.c_str());
						//			}
						//		}

						//		bAdvance = false; // don't advance
						//	}
						//	else
						//	{
						//		GameWarning("[DIALOG] CDialogActorContext::Update: %s ActorID=%d: Cannot play sound '%s' [AudioProxy ignored playback]",
						//			m_pSession->GetDebugName(), m_actorID, m_pCurLine->m_sound.c_str());

						//		pSound->Stop(ESoundStopMode_AtOnce);
						//		m_soundID = INVALID_SOUNDID;
						//		pSound->RemoveEventListener(this);
						//		pSound = NULL;
						//	}
						//}
						//else
						//{
						//	GameWarning("[DIALOG] CDialogActorContext::Update: %s ActorID=%d: Cannot play sound '%s' [AudioProxy returns invalid sound]",
						//		m_pSession->GetDebugName(), m_actorID, m_pCurLine->m_sound.c_str());
						//}
					}
					else
					{
						// sound has been scheduled
						// wait for sound start or timeout
						m_soundTimeOut-=dt;
						const bool bTimedOut = m_soundTimeOut <= 0.0f;
						bAdvance = bTimedOut || m_bSoundStarted;
						if (bAdvance)
						{
							if (bTimedOut)
								StopSound(true); // unregister from sound as listener and free resource
							DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Now=%f actorID=%d phase=eDAC_ScheduleSoundPlay %s",
								m_pSession->GetDebugName(), now, m_actorID, m_bSoundStarted ? "Sound Started" : "Sound Timed Out");
						}
					}
				}
			}
			break;

		case eDAC_SoundFacial:
			{
				bAdvance = true;
				const bool bHasSound  = !m_pCurLine->m_sound.empty();
				const bool bHasFacial = !m_pCurLine->m_facial.empty() || m_pCurLine->m_flagResetFacial;
				if (bHasFacial)
				{
					IEntity* pActorEntity = m_pSession->GetActorEntity(m_actorID);
					if (pActorEntity)
						DoFacialExpression(pActorEntity, m_pCurLine->m_facial, m_pCurLine->m_facialWeight, m_pCurLine->m_facialFadeTime);
				}

				float delay = m_pCurLine->m_delay;
				if (bHasSound && m_bSoundStarted)
				{
					if (m_soundLength < 0.0f)
					{
						m_soundLength = Random(2.0f,6.0f);
						DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Now=%f actorID=%d phase=eDAC_SoundFacial Faking SoundTime to %f",
							m_pSession->GetDebugName(), now, m_actorID, m_soundLength);
					}

					DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Now=%f actorID=%d phase=eDAC_SoundFacial Delay=%f SoundTime=%f",
						m_pSession->GetDebugName(), now , m_actorID, delay, m_soundLength);
					delay += m_soundLength;
				}

				// schedule END
				if (delay < 0.0f)
					delay = 0.0f;
				m_pSession->ScheduleNextLine(delay+0.05f); // ~1 frame at 20 fps. we now stop the current line sound before going for next line. Sometimes, this stop call is right before the
																									 // sound has actually stopped in engine side. When that happens, the engine is adding ~2 seconds extra to the sound duration (because fade problems related to NAX header)
																									 // and that looks bad if subtitles are enabled. So we add this small delay here to try to minimize that situation.
																									 // this is part of the workaround for some dialogs apparently never finishing in the engine side (rare).
				m_bHasScheduled = true;
			}
			break;

		case eDAC_EndLine:
			bAdvance = true;
			if (m_bHasScheduled == false)
			{
				m_bHasScheduled = true;
				m_pSession->ScheduleNextLine(m_pCurLine->m_delay);
			}
			break;
		}

		if (bAdvance)
		{
			AdvancePhase();
			dt = 0.0f;
			++loop;
			assert (loop <= eDAC_EndLine+1);
			if (loop > eDAC_EndLine+1)
			{
				DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Actor=%d InternalLoopCount=%d. Final Exit!",
					m_pSession->GetDebugName(), m_actorID, loop);
			}
		}
		else
			break;
	}
	while (true);

	return true;
}
bool CDialogActorContext::Update(float dt)
{
    if (IsAborted())
        return true;

    // FIXME: this should never happen, as we should get a notification before.
    //        temp leave in for tracking down a bug [AlexL: 23/11/2006]
    IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_entityID);
    if (pEntity == 0)
    {
        m_pIActor = 0;
        GameWarning("[DIALOG] CDialogActorContext::Update: %s Actor=%d (EntityId=%d) no longer existent.",
                    m_pSession->GetDebugName(), m_actorID, m_entityID);
        AbortContext(true, CDialogSession::eAR_EntityDestroyed);
        return true;
    }

    CDialogSession::AlertnessInterruptMode alertnessInterruptMode = m_pSession->GetAlertnessInterruptMode();
    if(alertnessInterruptMode != CDialogSession::None)
    {
        if(IAIObject* aiObject = pEntity->GetAI())
        {
            if(IAIActorProxy* aiActorProxy = aiObject->GetProxy())
            {
                if(aiActorProxy->GetAlertnessState() >= alertnessInterruptMode)
                {
                    AbortContext(true, CDialogSession::eAR_AIAborted);
                    return true;
                }
            }
        }
    }

    float now = m_pSession->GetCurTime();

    if (!CheckActorFlags(CDialogSession::eDACF_NoActorDeadAbort) && m_pIActor && m_pIActor->IsDead())
    {
        if (!IsAborted())
        {
            DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Actor=%d (EntityId=%d) has died. Aborting.",
                        m_pSession->GetDebugName(), m_actorID, m_entityID);
            AbortContext(true, CDialogSession::eAR_ActorDead);
            return true;
        }
    }

    if (m_bIsLocalPlayer)
    {
        // when the local player is involved in the conversation do some special checks
        if (DoLocalPlayerChecks(dt) == false)
        {
            DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Abort from LocalPlayer.", m_pSession->GetDebugName());
            AbortContext(true, m_bIsAwareInRange == false ? CDialogSession::eAR_PlayerOutOfRange : CDialogSession::eAR_PlayerOutOfView);
            return true;
        }
    }

    if (m_bAbortFromAI)
    {
        m_bAbortFromAI = false;
        if (!IsAborted())
        {
            DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Abort from AI.", m_pSession->GetDebugName());
            AbortContext(true, CDialogSession::eAR_AIAborted);
            return true;
        }
    }

    if (SessionAllowsLookAt())
    {
        DoStickyLookAt();
    }

    int loop = 0;
    do
    {
        // DiaLOG::Log("[DIALOG] DiaLOG::eAlways"CDialogActorContext::Update: %s now=%f actorId=%d loop=%d", m_pSession->GetDebugName(), now, m_actorID, loop);

        bool bAdvance = false;
        switch (m_phase)
        {
        case eDAC_Idle:
            break;

        case eDAC_NewLine:
        {
            m_bHasScheduled = false;
            m_lookAtTimeOut = LOOKAT_TIMEOUT;
            m_animTimeOut   = ANIM_TIMEOUT;
            m_soundTimeOut  = SOUND_TIMEOUT; // wait one second until sound is timed out
            m_bAnimScheduled = false;
            m_bAnimStarted   = false;
            m_bSoundScheduled = false;
            m_bSoundStarted   = false;
            m_soundLength   = 0.0f;

            if (m_pCurLine->m_flagResetLookAt)
            {
                m_stickyLookAtActorID = CDialogScript::NO_ACTOR_ID;
                m_lookAtActorID = CDialogScript::NO_ACTOR_ID;
            }
            // check if look-at sticky is set
            else if (m_pCurLine->m_lookatActor != CDialogScript::NO_ACTOR_ID)
            {
                if (m_pCurLine->m_flagLookAtSticky == false)
                {
                    m_lookAtActorID = m_pCurLine->m_lookatActor;
                    m_stickyLookAtActorID = CDialogScript::NO_ACTOR_ID;
                }
                else
                {
                    m_stickyLookAtActorID = m_pCurLine->m_lookatActor;
                    m_lookAtActorID = CDialogScript::NO_ACTOR_ID;
                }
            }

            bAdvance = true;

            // handle the first sticky look-at here
            if (SessionAllowsLookAt())
            {
                DoStickyLookAt();
            }

#if 0   // test for immediate scheduling of next line while the current line is still playing
            // maybe we're going to use some special delay TAGS like FORCE_NEXT, WAIT
            if (m_pCurLine->m_delay <= -999.0f)
            {
                m_bHasScheduled = true;
                m_pSession->ScheduleNextLine(0.0f);
            }
#endif
        }
        break;

        case eDAC_LookAt:
        {
            bool bWaitForLookAtFinish = true;
            bAdvance = true;

            if (SessionAllowsLookAt() == false)
            {
                break;
            }

            // Question: maybe do this although EP is requested
            if (bWaitForLookAtFinish && m_lookAtActorID != CDialogScript::NO_ACTOR_ID && m_pCurLine->m_flagAGEP == false)
            {
                IEntity* pActorEntity = m_pSession->GetActorEntity(m_actorID);
                IEntity* pLookAtEntity = m_pSession->GetActorEntity(m_lookAtActorID);
                if (pActorEntity != 0)
                {
                    m_lookAtTimeOut -= dt;
                    bool bTargetReached;
                    //bool bSuccess = DoLookAt(pActorEntity, pLookAtEntity, bTargetReached);
                    DoLookAt(pActorEntity, pLookAtEntity, bTargetReached);
                    //DiaLOG::Log(DiaLOG::eDebugA, "[DIALOG] CDialogActorContext::Update: %s now=%f actorID=%d phase=eDAC_LookAt %d",
                    //	m_pSession->GetDebugName(), now, m_actorID, bTargetReached);

                    if (/* bSuccess == false || */ bTargetReached || m_lookAtTimeOut<=0.0f)
                    {
                        DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s now=%f actorID=%d phase=eDAC_LookAt %s",
                                    m_pSession->GetDebugName(), now, m_actorID, bTargetReached ? "Target Reached" : "Timed Out");
                        m_lookAtActorID = CDialogScript::NO_ACTOR_ID;
                    }
                    else
                        bAdvance = false;
                }
            }
        }
        break;

        case eDAC_Anim:
        {
            bAdvance = true;
            if (SessionAllowsLookAt() && m_lookAtActorID != CDialogScript::NO_ACTOR_ID) // maybe: don't do this when EP is requested [&& m_pCurLine->m_flagAGEP == false]
            {
                IEntity* pActorEntity = m_pSession->GetActorEntity(m_actorID);
                IEntity* pLookAtEntity = m_pSession->GetActorEntity(m_lookAtActorID);
                if (pActorEntity != 0)
                {
                    m_lookAtTimeOut -= dt;
                    bool bTargetReached;
                    //bool bSuccess = DoLookAt(pActorEntity, pLookAtEntity, bTargetReached);
                    DoLookAt(pActorEntity, pLookAtEntity, bTargetReached);
                    if (/* bSuccess == false || */ bTargetReached || m_lookAtTimeOut<=0.0f)
                    {
                        DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s now=%f actorID=%d phase=eDAC_Anim %s",
                                    m_pSession->GetDebugName(), now, m_actorID, bTargetReached ? "Target Reached" : "Timed Out");
                        m_lookAtActorID = CDialogScript::NO_ACTOR_ID;
                    }
                    else
                        bAdvance = false;
                }
            }
            const bool bHasAnim = !m_pCurLine->m_anim.empty();
            if (SessionAllowsAnim() && bHasAnim)
            {
                bAdvance = false;
                if (!m_bAnimScheduled)
                {
                    m_bSoundStopsAnim = false; // whenever there is a new animation, no need for the still playing sound
                    // to stop the animation
                    m_bAnimStarted = false;
                    m_bAnimScheduled = true;
                    // schedule animation
                    IEntity* pActorEntity = m_pSession->GetActorEntity(m_actorID);
                    if (pActorEntity)
                        DoAnimAction(pActorEntity, m_pCurLine->m_anim, m_pCurLine->m_flagAGSignal, m_pCurLine->m_flagAGEP);
                    else
                        bAdvance = true;
                }
                else
                {
                    // we scheduled it already
                    // wait until it starts or timeout
                    m_animTimeOut-=dt;
                    bAdvance = m_animTimeOut <= 0.0f || m_bAnimStarted;
                    if (bAdvance)
                    {
                        DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Now=%f actorID=%d phase=eDAC_Anim %s",
                                    m_pSession->GetDebugName(), now, m_actorID, m_bAnimStarted ? "Anim Started" : "Anim Timed Out");
                    }
                }
            }
        }
        break;

        case eDAC_ScheduleSoundPlay:
        {
            bAdvance = true;
            const bool bHasSound  = m_pCurLine->m_audioID != INVALID_AUDIO_CONTROL_ID;
            if (bHasSound)
            {
                if (m_bSoundScheduled == false)
                {
                    IEntity* pActorEntity = m_pSession->GetActorEntity(m_actorID);
                    if (pActorEntity == 0)
                        break;

                    IEntityAudioProxy* pActorAudioProxy = m_pSession->GetEntityAudioProxy(pActorEntity);

                    if (pActorAudioProxy == 0)
                        break;

                    if(m_SpeechAuxProxy == INVALID_AUDIO_PROXY_ID)
                    {
                        m_SpeechAuxProxy = pActorAudioProxy->CreateAuxAudioProxy();
                        pActorAudioProxy->AddAsListenerToAuxAudioProxy(m_SpeechAuxProxy, &CDialogActorContext::OnAudioTriggerFinished, eART_AUDIO_CALLBACK_MANAGER_REQUEST, eACMRT_REPORT_FINISHED_TRIGGER_INSTANCE);
                    }
                    UpdateAuxProxyPosition();

                    SAudioCallBackInfos callbackInfos(0, (void*)CDialogActorContext::GetClassIdentifier(), reinterpret_cast<void*>(static_cast<intptr_t>(m_ContextID)), eARF_PRIORITY_NORMAL | eARF_SYNC_FINISHED_CALLBACK);
                    if(!pActorAudioProxy->ExecuteTrigger(m_pCurLine->m_audioID, eLSM_None, m_SpeechAuxProxy, callbackInfos))
                    {
                        m_bSoundStarted = false;
                        m_bHasScheduled = false;
                        m_pSession->ScheduleNextLine(2.0f);
                    }
                    else
                    {
                        m_bSoundStarted = true;
                        m_bHasScheduled = true;
                        //todo: get the length of the sound to schedule the next line (set m_soundLength). Currently we schedule the next line as soon as the current one is finished, ignoring the specified "delay" parameter. its done in: DialogTriggerFinishedCallback

                        const char* triggerName = gEnv->pAudioSystem->GetAudioControlName(eACT_TRIGGER, m_pCurLine->m_audioID);
                        if (triggerName == NULL)
                            triggerName =  "dialog trigger";
                        DiaLOG::Log(DiaLOG::eDebugA, "[DIALOG] CDialogActorContex::Update: %s Now=%f actorID=%d phase=eDAC_ScheduleSoundPlay: Starting '%s'",
                                    m_pSession->GetDebugName(), now, m_actorID, triggerName);
                    }
                }
                else
                {
                    // sound has been scheduled
                    // wait for sound start or timeout
                    m_soundTimeOut-=dt;
                    const bool bTimedOut = m_soundTimeOut <= 0.0f;
                    bAdvance = bTimedOut || m_bSoundStarted;
                    if (bAdvance)
                    {
                        if (bTimedOut)
                            StopSound(true); // unregister from sound as listener and free resource
                        DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Now=%f actorID=%d phase=eDAC_ScheduleSoundPlay %s",
                                    m_pSession->GetDebugName(), now, m_actorID, m_bSoundStarted ? "Sound Started" : "Sound Timed Out");
                    }
                }
            }
        }
        break;

        case eDAC_SoundFacial:
        {
            bAdvance = true;
            const bool bHasSound  = m_pCurLine->m_audioID != INVALID_AUDIO_CONTROL_ID;
            const bool bHasFacial = !m_pCurLine->m_facial.empty() || m_pCurLine->m_flagResetFacial;
            if (bHasFacial)
            {
                IEntity* pActorEntity = m_pSession->GetActorEntity(m_actorID);
                if (pActorEntity)
                    DoFacialExpression(pActorEntity, m_pCurLine->m_facial, m_pCurLine->m_facialWeight, m_pCurLine->m_facialFadeTime);
            }

            //hd-todo: re-add me, when we have a way to query the length of the audio-lines
            //float delay = m_pCurLine->m_delay;
            //if (bHasSound && m_bSoundStarted)
            //{
            //	if (m_soundLength <= 0.0f)
            //	{
            //		m_soundLength = cry_random(2.0f, 6.0f);
            //		DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Now=%f actorID=%d phase=eDAC_SoundFacial Faking SoundTime to %f",
            //			m_pSession->GetDebugName(), now, m_actorID, m_soundLength);
            //	}

            //	DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Now=%f actorID=%d phase=eDAC_SoundFacial Delay=%f SoundTime=%f",
            //		m_pSession->GetDebugName(), now , m_actorID, delay, m_soundLength);
            //	delay += m_soundLength;
            //}

            //// schedule END
            //if (delay < 0.0f)
            //	delay = 0.0f;
            //m_pSession->ScheduleNextLine(delay+0.05f); // ~1 frame at 20 fps. we now stop the current line sound before going for next line. Sometimes, this stop call is right before the
            //																					 // sound has actually stopped in engine side. When that happens, the engine is adding ~2 seconds extra to the sound duration (because fade problems related to NAX header)
            //																					 // and that looks bad if subtitles are enabled. So we add this small delay here to try to minimize that situation.
            //																					 // this is part of the workaround for some dialogs apparently never finishing in the engine side (rare).
            //m_bHasScheduled = true;
        }
        break;

        case eDAC_EndLine:
            bAdvance = true;
            if (m_bHasScheduled == false)
            {
                m_bHasScheduled = true;
                m_pSession->ScheduleNextLine(m_pCurLine->m_delay);
            }
            break;
        }

        if (bAdvance)
        {
            AdvancePhase();
            dt = 0.0f;
            ++loop;
            assert (loop <= eDAC_EndLine+1);
            if (loop > eDAC_EndLine+1)
            {
                DiaLOG::Log(DiaLOG::eAlways, "[DIALOG] CDialogActorContext::Update: %s Actor=%d InternalLoopCount=%d. Final Exit!",
                            m_pSession->GetDebugName(), m_actorID, loop);
            }
        }
        else
        {
            if (IsStillPlaying())
            {
                UpdateAuxProxyPosition();
            }

            break;
        }
    }
    while (true);

    return true;
}
void BasicEvent::SetAborted()
{
    ASSERT(!IsAborted()
           && "Tried to abort an already aborted event!");
    m_abortState = AbortState::STATE_ABORTED;
}