void CDestructibleModel::RegisterDestroyedStimulus() { // Register audio and visual stimulus if specified. if( (m_nDestroyAlarmLevel > 0) && (m_fStimRadius > 0.f) ) { LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); // Extract who caused an explosion. HOBJECT hDamager = m_hLastDamager; if( IsExplosion( hDamager ) ) { Explosion* pExplosion = (Explosion*)g_pLTServer->HandleToObject(m_hLastDamager); hDamager = pExplosion->GetFiredFrom(); } // If damager is still not a character (possibly because an explosion was triggered), assume player. // Better solution - set the alignment of the damager on the explosion? if( !IsCharacter( hDamager ) ) { CPlayerObj *pPlayer = g_pCharacterMgr->FindPlayer(); if ( pPlayer ) { hDamager = pPlayer->m_hObject; } } g_pAIStimulusMgr->RegisterStimulus( kStim_EnemyDisturbanceSound, m_nDestroyAlarmLevel, hDamager, m_hObject, vPos, m_fStimRadius ); m_eStimID = g_pAIStimulusMgr->RegisterStimulus( kStim_EnemyDisturbanceVisible, m_nDestroyAlarmLevel + 1, hDamager, m_hObject, vPos, m_fStimRadius ); } }
void CDestructibleModel::RegisterDestroyedStimulus() { // Register audio and visual stimulus if specified. if( (m_nDestroyAlarmLevel > 0) && (m_fStimRadius > 0.f) ) { LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); // Extract who caused an explosion. HOBJECT hDamager = m_hLastDamager; if( IsExplosion( hDamager ) ) { Explosion* pExplosion = (Explosion*)g_pLTServer->HandleToObject(m_hLastDamager); hDamager = pExplosion->GetFiredFrom(); } // If damager is still not a character (possibly because an explosion was triggered), assume player. // Better solution - set the alignment of the damager on the explosion? if( !IsCharacter( hDamager ) ) { CPlayerObj *pPlayer = g_pCharacterMgr->FindPlayer(); if ( pPlayer ) { hDamager = pPlayer->m_hObject; } } if ( IsCharacter(hDamager) ) { CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(hDamager); if ( pCharacter ) { // Register the disturbance sound. StimulusRecordCreateStruct DisturbanceSoundSCS( kStim_DisturbanceSound, pCharacter->GetAlignment(), vPos, hDamager ); DisturbanceSoundSCS.m_hStimulusTarget = m_hObject; DisturbanceSoundSCS.m_flAlarmScalar = (float)m_nDestroyAlarmLevel; DisturbanceSoundSCS.m_flRadiusScalar = m_fStimRadius; g_pAIStimulusMgr->RegisterStimulus( DisturbanceSoundSCS ); // Register the visible disturbance. StimulusRecordCreateStruct DisturbanceVisibleSCS( kStim_DisturbanceVisible, pCharacter->GetAlignment(), vPos, hDamager ); DisturbanceVisibleSCS.m_hStimulusTarget = m_hObject; DisturbanceVisibleSCS.m_flAlarmScalar = (float)(m_nDestroyAlarmLevel + 1); DisturbanceVisibleSCS.m_flRadiusScalar = m_fStimRadius; m_eStimID = g_pAIStimulusMgr->RegisterStimulus( DisturbanceVisibleSCS ); } } } }
void Prop::HandleTouch(HOBJECT hToucher) { // Only characters can touch props. if( ( hToucher != LTNULL ) && ( !IsCharacter(hToucher) ) && ( !IsExplosion(hToucher) ) ) { return; } if ( (m_eState == kState_PropDestroyed) || (m_eState == kState_PropKnocked) || (!(m_pDisturb && m_pDisturb->pPD)) ) { return; } // Resolve the toucher to a character handle. HOBJECT hCharacter = LTNULL; if( IsCharacterHitBox( hToucher ) ) { CCharacterHitBox* pHB = (CCharacterHitBox*)g_pLTServer->HandleToObject(hToucher); hCharacter = pHB->GetModelObject(); } else if( IsExplosion( hToucher ) ) { Explosion* pExplosion = (Explosion*)g_pLTServer->HandleToObject(hToucher); hCharacter = pExplosion->GetFiredFrom(); } else if( IsCharacter( hToucher ) ) { hCharacter = hToucher; } // Only players can touch (for now). if((hCharacter != LTNULL) && !IsPlayer(hCharacter)) return; if(m_eState == kState_PropTouching) { // Clear sound if done playing. ClearTouchSoundIfDone(LTFALSE); // Check if both sound and animation are done, or just the sound for a "knock." if( m_pDisturb->hTouchSound == LTNULL ) { switch( m_pDisturb->eTouchAnimType ) { // Touch animations reset. case kPA_Touch: ClearTouchAnimIfDone(m_pDisturb->hTouchAnim, LTFALSE); if( g_pLTServer->GetModelAnimation(m_hObject) != m_pDisturb->hTouchAnim ) { m_eState = kState_PropDefault; return; } break; // Knock animations remain on the last frame forever. case kPA_Knock: if( MS_PLAYDONE & g_pLTServer->GetModelPlaybackState(m_hObject) ) { m_bTouchable = LTFALSE; g_pCommonLT->SetObjectFlags(m_hObject, OFT_User, 0, USRFLG_CAN_ACTIVATE); m_eState = kState_PropKnocked; return; } break; } } } // Play the touch sound and animation. if( (m_eState == kState_PropDefault) && (hCharacter != LTNULL)) { LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); // Play sound. PlayTouchSound(vPos); // Play animation. if(m_pDisturb->hTouchAnim != INVALID_ANI) { g_pLTServer->SetModelAnimation(m_hObject, m_pDisturb->hTouchAnim); g_pLTServer->SetModelLooping(m_hObject, LTFALSE); g_pLTServer->ResetModelAnimation(m_hObject); } // Register touch disturbance stimulus. if( (m_pDisturb->pPD->nTouchAlarmLevel > 0) && (m_pDisturb->pPD->fStimRadius > 0.f) ) { g_pAIStimulusMgr->RegisterStimulus( kStim_EnemyDisturbanceSound, m_pDisturb->pPD->nTouchAlarmLevel, hCharacter, m_hObject, vPos, m_pDisturb->pPD->fStimRadius ); // Props that are knocked over have a visual stimulus too. if( m_pDisturb->eTouchAnimType == kPA_Knock ) { g_pAIStimulusMgr->RegisterStimulus( kStim_EnemyDisturbanceVisible, m_pDisturb->pPD->nTouchAlarmLevel + 1, hCharacter, m_hObject, vPos, m_pDisturb->pPD->fStimRadius ); } } m_eState = kState_PropTouching; } // Update while playing touch sound and/or animation. SetNextUpdate(UPDATE_NEXT_FRAME); }
void Prop::HandleHit( HOBJECT hDamager ) { if( ( hDamager != LTNULL ) && ( !IsCharacter(hDamager) ) && ( !IsExplosion(hDamager) ) ) { return; } if( (m_eState == kState_PropDestroyed) || (m_eState == kState_PropKnocked) || (!(m_pDisturb && m_pDisturb->pPD)) ) { return; } // If we don't have a valid hit animation default to the touch animation... if( m_pDisturb->hHitAnim == INVALID_ANI ) HandleTouch( hDamager ); // Resolve the toucher to a character handle. HOBJECT hCharacter = LTNULL; if( IsCharacterHitBox( hDamager ) ) { CCharacterHitBox* pHB = (CCharacterHitBox*)g_pLTServer->HandleToObject(hDamager); hCharacter = pHB->GetModelObject(); } else if( IsExplosion( hDamager ) ) { Explosion* pExplosion = (Explosion*)g_pLTServer->HandleToObject(hDamager); hCharacter = pExplosion->GetFiredFrom(); } else if( IsCharacter( hDamager ) ) { hCharacter = hDamager; } // Only characters can hit (for now). if((hCharacter != LTNULL) && !IsCharacter(hCharacter)) return; if(m_eState == kState_PropHit) { // Check if both sound and animation are done ClearHitSoundIfDone( LTFALSE ); if( m_pDisturb->hHitSound == LTNULL ) { ClearHitAnimIfDone( LTFALSE ); if( g_pLTServer->GetModelAnimation(m_hObject) != m_pDisturb->hHitAnim ) { m_eState = kState_PropDefault; return; } } } // Play the hit sound and animation. if( (m_eState == kState_PropDefault) && (hCharacter != LTNULL)) { LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); // Play sound. PlayHitSound(vPos); // Play animation. if(m_pDisturb->hHitAnim != INVALID_ANI) { g_pLTServer->SetModelAnimation( m_hObject, m_pDisturb->hHitAnim ); g_pLTServer->SetModelLooping( m_hObject, LTFALSE ); g_pLTServer->ResetModelAnimation(m_hObject); } // Register touch disturbance stimulus. if( (m_pDisturb->pPD->nHitAlarmLevel > 0) && (m_pDisturb->pPD->fStimRadius > 0.f) ) { g_pAIStimulusMgr->RegisterStimulus( kStim_EnemyDisturbanceSound, m_pDisturb->pPD->nHitAlarmLevel, hCharacter, m_hObject, vPos, m_pDisturb->pPD->fStimRadius ); } m_eState = kState_PropHit; } // Update while playing touch sound and/or animation. SetNextUpdate(UPDATE_NEXT_FRAME); }