/******************************** 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); }
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 (); }
PrintDraw::~PrintDraw() { DrawLock __; if(IsAborted()) ::AbortDoc(handle); else ::EndDoc(handle); DeleteDC(handle); handle = NULL; }
void PrintDraw::EndPage() { DrawLock __; if(IsAborted()) return; Unselect(); ASSERT(printer); if(::EndPage(handle) <= 0) Abort(); }
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; }
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); }
/*************************************************** 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); }
/********************************************* 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); }
/******************************** 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(); }
/******************************** 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); }
/******************************** 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; }