//----------------------------------------------------------------------------- // Purpose: // Input : *pstudiohdr - // sequence - // type - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool HasAnimationEventOfType( CStudioHdr *pstudiohdr, int sequence, int type ) { if ( !pstudiohdr || sequence >= pstudiohdr->GetNumSeq() ) return false; mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( sequence ); if ( !&seqdesc ) return false; mstudioevent_t *pevent = GetEventIndexForSequence( seqdesc ); if ( !pevent ) return false; if (seqdesc.numevents == 0 ) return false; int index; for ( index = 0; index < (int)seqdesc.numevents; index++ ) { if ( pevent[ index ].event == type ) { return true; } } return false; }
//----------------------------------------------------------------------------- // Purpose: find the anim events that may have started sounds, and stop them. //----------------------------------------------------------------------------- void C_BaseObject::StopAnimGeneratedSounds( void ) { MDLCACHE_CRITICAL_SECTION(); CStudioHdr *pStudioHdr = GetModelPtr(); if ( !pStudioHdr ) return; mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( GetSequence() ); float flCurrentCycle = GetCycle(); mstudioevent_t *pevent = GetEventIndexForSequence( seqdesc ); for (int i = 0; i < (int)seqdesc.numevents; i++) { if ( pevent[i].cycle < flCurrentCycle ) { if ( pevent[i].event == CL_EVENT_SOUND || pevent[i].event == AE_CL_PLAYSOUND ) { StopSound( entindex(), pevent[i].options ); } } } }
int GetAnimationEvent( CStudioHdr *pstudiohdr, int sequence, animevent_t *pNPCEvent, float flStart, float flEnd, int index ) { if ( !pstudiohdr || sequence >= pstudiohdr->GetNumSeq() || !pNPCEvent ) return 0; mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( sequence ); if (&seqdesc == NULL) return 0; //TGB: make sure it's not a bad ref, or it WILL crash on the next line if (seqdesc.numevents == 0 || index >= (int)seqdesc.numevents ) return 0; // Msg( "flStart %f flEnd %f (%d) %s\n", flStart, flEnd, seqdesc.numevents, seqdesc.label ); mstudioevent_t *pevent = GetEventIndexForSequence( seqdesc ); if (!pevent) //tgb return 0; for (; index < (int)seqdesc.numevents; index++) { // Don't send client-side events to the server AI if ( pevent[index].type & AE_TYPE_NEWEVENTSYSTEM ) { if ( pevent[index].type & AE_TYPE_CLIENT ) continue; } else if ( pevent[index].event >= EVENT_CLIENT ) //Adrian - Support the old event system continue; bool bOverlapEvent = false; if (pevent[index].cycle >= flStart && pevent[index].cycle < flEnd) { bOverlapEvent = true; } // FIXME: doesn't work with animations being played in reverse else if ((seqdesc.flags & STUDIO_LOOPING) && flEnd < flStart) { if (pevent[index].cycle >= flStart || pevent[index].cycle < flEnd) { bOverlapEvent = true; } } if (bOverlapEvent) { pNPCEvent->pSource = NULL; pNPCEvent->cycle = pevent[index].cycle; #if !defined( MAKEXVCD ) pNPCEvent->eventtime = gpGlobals->curtime; #else pNPCEvent->eventtime = 0.0f; #endif pNPCEvent->event = pevent[index].event; pNPCEvent->options = pevent[index].pszOptions(); pNPCEvent->type = pevent[index].type; return index + 1; } } return 0; }
void C_BaseAnimatingOverlay::DoAnimationEvents( CStudioHdr *pStudioHdr ) { MDLCACHE_CRITICAL_SECTION(); if ( !pStudioHdr || !pStudioHdr->SequencesAvailable() ) return; int nSequences = pStudioHdr->GetNumSeq(); BaseClass::DoAnimationEvents( pStudioHdr ); bool watch = false; // Q_strstr( hdr->name, "rifle" ) ? true : false; CheckForLayerChanges( pStudioHdr, gpGlobals->curtime ); // !!! int j; for (j = 0; j < m_AnimOverlay.Count(); j++) { if ( m_AnimOverlay[j].m_nSequence >= nSequences ) { continue; } // Don't bother with 0-weight layers if ( m_AnimOverlay[j].m_flWeight == 0.0f || m_AnimOverlay[j].m_nOrder == MAX_OVERLAYS ) { continue; } mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( m_AnimOverlay[j].m_nSequence ); if ( seqdesc.numevents == 0 ) continue; // stalled? if (m_AnimOverlay[j].m_flCycle == m_flOverlayPrevEventCycle[j]) continue; bool bLoopingSequence = IsSequenceLooping( m_AnimOverlay[j].m_nSequence ); bool bLooped = false; //in client code, m_flOverlayPrevEventCycle is set to -1 when we first start an overlay, looping or not if ( bLoopingSequence && m_flOverlayPrevEventCycle[j] > 0.0f && m_AnimOverlay[j].m_flCycle <= m_flOverlayPrevEventCycle[j] ) { if (m_flOverlayPrevEventCycle[j] - m_AnimOverlay[j].m_flCycle > 0.5) { bLooped = true; } else { // things have backed up, which is bad since it'll probably result in a hitch in the animation playback // but, don't play events again for the same time slice return; } } mstudioevent_t *pevent = GetEventIndexForSequence( seqdesc ); // This makes sure events that occur at the end of a sequence occur are // sent before events that occur at the beginning of a sequence. if (bLooped) { for (int i = 0; i < (int)seqdesc.numevents; i++) { // ignore all non-client-side events if ( pevent[i].type & AE_TYPE_NEWEVENTSYSTEM ) { if ( !(pevent[i].type & AE_TYPE_CLIENT) ) continue; } else if ( pevent[i].Event_OldSystem() < EVENT_CLIENT ) //Adrian - Support the old event system continue; if ( pevent[i].cycle <= m_flOverlayPrevEventCycle[j] ) continue; if ( watch ) { Msg( "%i FE %i Looped cycle %f, prev %f ev %f (time %.3f)\n", gpGlobals->tickcount, pevent[i].Event(), pevent[i].cycle, (float)m_flOverlayPrevEventCycle[j], (float)m_AnimOverlay[j].m_flCycle, gpGlobals->curtime ); } FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].Event(), pevent[ i ].pszOptions() ); } // Necessary to get the next loop working m_flOverlayPrevEventCycle[j] = -0.01; } for (int i = 0; i < (int)seqdesc.numevents; i++) { if ( pevent[i].type & AE_TYPE_NEWEVENTSYSTEM ) { if ( !(pevent[i].type & AE_TYPE_CLIENT) ) continue; } else if ( pevent[i].Event_OldSystem() < EVENT_CLIENT ) //Adrian - Support the old event system continue; bool bStartedSequence = ( m_flOverlayPrevEventCycle[j] > m_AnimOverlay[j].m_flCycle || m_flOverlayPrevEventCycle[j] == 0 ); if ( ( ( pevent[i].cycle > m_flOverlayPrevEventCycle[j] || bStartedSequence && pevent[i].cycle == 0 ) && pevent[i].cycle <= m_AnimOverlay[j].m_flCycle) ) { if ( watch ) { Msg( "%i (seq: %d) FE %i Normal cycle %f, prev %f ev %f (time %.3f)\n", gpGlobals->tickcount, (int)m_AnimOverlay[j].m_nSequence, (int)pevent[i].Event(), (float)pevent[i].cycle, (float)m_flOverlayPrevEventCycle[j], (float)m_AnimOverlay[j].m_flCycle, gpGlobals->curtime ); } FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].Event(), pevent[ i ].pszOptions() ); } } m_flOverlayPrevEventCycle[j] = m_AnimOverlay[j].m_flCycle; } }