void CTentacle :: DieThink( void ) { pev->nextthink = gpGlobals-> time + 0.1; DispatchAnimEvents( ); StudioFrameAdvance( ); ChangeYaw( 24 ); if (m_fSequenceFinished) { if (pev->sequence == m_iGoalAnim) { switch( m_iGoalAnim ) { case TENTACLE_ANIM_Engine_Idle: case TENTACLE_ANIM_Engine_Sway: case TENTACLE_ANIM_Engine_Swat: case TENTACLE_ANIM_Engine_Bob: m_iGoalAnim = TENTACLE_ANIM_Engine_Sway + RANDOM_LONG( 0, 2 ); break; case TENTACLE_ANIM_Engine_Death1: case TENTACLE_ANIM_Engine_Death2: case TENTACLE_ANIM_Engine_Death3: UTIL_Remove( this ); return; } } // ALERT( at_console, "%d : %d => ", pev->sequence, m_iGoalAnim ); pev->sequence = FindTransition( pev->sequence, m_iGoalAnim, &m_iDir ); // ALERT( at_console, "%d\n", pev->sequence ); if (m_iDir > 0) { pev->frame = 0; } else { pev->frame = 255; } ResetSequenceInfo( ); float dy; switch( pev->sequence ) { case TENTACLE_ANIM_Floor_Rear: case TENTACLE_ANIM_Floor_Rear_Idle: case TENTACLE_ANIM_Lev1_Rear: case TENTACLE_ANIM_Lev1_Rear_Idle: case TENTACLE_ANIM_Lev2_Rear: case TENTACLE_ANIM_Lev2_Rear_Idle: case TENTACLE_ANIM_Lev3_Rear: case TENTACLE_ANIM_Lev3_Rear_Idle: case TENTACLE_ANIM_Engine_Idle: case TENTACLE_ANIM_Engine_Sway: case TENTACLE_ANIM_Engine_Swat: case TENTACLE_ANIM_Engine_Bob: case TENTACLE_ANIM_Engine_Death1: case TENTACLE_ANIM_Engine_Death2: case TENTACLE_ANIM_Engine_Death3: pev->framerate = RANDOM_FLOAT( m_iDir - 0.2, m_iDir + 0.2 ); dy = 180; break; default: pev->framerate = 1.5; dy = 0; break; } pev->ideal_yaw = m_flInitialYaw + dy; } }
int32 VirtualRenderer::RenderLoop() { BList timeList(1); EventComposant *composant; bigtime_t *time, *time2, duration; bool firstTrackActive = true; int i, j, timeEvent; roster = BMediaRoster::Roster(); /* Retrieve all the times where an event occur (starts and stops) in the list */ for (i = 0; i < eventList->CountItems(); i++) { composant = eventList->ItemAt(i); composant->startRendered = false; composant->endRendered = false; time = new bigtime_t; *time = composant->time; timeList.AddItem(time); time = new bigtime_t; *time = composant->time + composant->end; timeList.AddItem(time); } timeList.SortItems(compare); /* Instantiate a writer node */ writer = new DiskWriter(prefs->saveFile, prefs->format, prefs->video_codec, prefs->audio_codec, 0); roster->SetRefFor(writer->Node(), prefs->saveFile, true, &duration); BMessenger *messenger = new BMessenger(this);; roster->SetRunModeNode(writer->Node(), BMediaNode::B_OFFLINE); roster->StartWatching(*messenger, writer->Node(), B_MEDIA_NODE_STOPPED); /* if there is not video available at the beginning, we need a null generator to fill in the beginning of the file, else we enter the loop */ // if (eventList->FirstItem()->time != 0) // { // nullgen = new NullGen; // // } timeEvent = 0; media_output outputs[3]; int32 numOutputs; media_input inputs[4]; int32 numInputs; media_source sources[2]; media_destination destinations[2]; media_format format; media_node filterNode, transitionNode; bool doConnect = false; bool writerConnected = false; bool reader1Connected = false; bool reader2Connected = false; bool filterConnected = false; bool transitionConnected = false; for (timeEvent = 0; timeEvent < timeList.CountItems(); timeEvent++) { if (acquire_sem(lock_sem) == B_OK) { i = 0; // while (*((bigtime_t*)timeList.ItemAt(timeEvent)) != eventList->ItemAt(i)->time) // i++; duration = *((bigtime_t*)timeList.ItemAt(timeEvent)); while (i < eventList->CountItems()) { composant = eventList->ItemAt(i); if ((composant->time == duration) && !composant->startRendered) { composant->startRendered = true; break; } if ((composant->time + composant->end == duration) && !composant->endRendered) { composant->endRendered = true; break; } i++; } /* We must find the events that just terminated */ for (j = i; j < eventList->CountItems(); j++) { composant = (EventComposant*)eventList->ItemAt(j); if (composant->time + composant->end == *(bigtime_t*)timeList.ItemAt(timeEvent)) switch (composant->event) { case video1: roster->ReleaseNode(reader1->Node()); reader1 = NULL; reader1Connected = false; break; case video2: roster->ReleaseNode(reader2->Node()); reader2 = NULL; reader2Connected = false; break; case transition: firstTrackActive = !firstTrackActive; roster->GetConnectedInputsFor(filterNode, &inputs[0], 2, &numInputs); roster->Disconnect(reader1->Node().node, inputs[0].source, transitionNode.node, inputs[0].destination); roster->Disconnect(reader2->Node().node, inputs[1].source, transitionNode.node, inputs[1].destination); roster->GetConnectedOutputsFor(transitionNode, &outputs[0], 1, &numOutputs); if (filterConnected) { roster->Disconnect(transitionNode.node, outputs[0].source, filterNode.node, outputs[0].destination); if (firstTrackActive) roster->Connect(inputs[0].source, outputs[0].destination, &inputs[0].format, &outputs[0], &inputs[0]); else roster->Connect(inputs[1].source, outputs[0].destination, &inputs[1].format, &outputs[0], &inputs[1]); } else { roster->Disconnect(transitionNode.node, outputs[0].source, writer->Node().node, outputs[0].destination); if (firstTrackActive) roster->Connect(inputs[0].source, outputs[0].destination, &inputs[0].format, &outputs[0], &inputs[0]); else roster->Connect(inputs[1].source, outputs[0].destination, &inputs[1].format, &outputs[0], &inputs[1]); } transitionConnected = false; break; case filter: roster->GetConnectedInputsFor(filterNode, &inputs[0], 1, &numInputs); if (transitionConnected) { roster->Disconnect(transitionNode.node, inputs[0].source, filterNode.node, inputs[0].destination); roster->GetConnectedOutputsFor(filterNode, &outputs[0], 1, &numOutputs); roster->Disconnect(filterNode.node, outputs[0].source, writer->Node().node, outputs[0].destination); roster->Connect(inputs[0].source, outputs[0].destination, &inputs[0].format, &outputs[0], &inputs[0]); filterConnected = false; } else if (firstTrackActive) { roster->Disconnect(reader1->Node().node, inputs[0].source, filterNode.node, inputs[0].destination); roster->GetConnectedOutputsFor(filterNode, &outputs[0], 1, &numOutputs); roster->Disconnect(filterNode.node, outputs[0].source, writer->Node().node, outputs[0].destination); roster->Connect(inputs[0].source, outputs[0].destination, &inputs[0].format, &outputs[0], &inputs[0]); filterConnected = false; } else if (!firstTrackActive) { roster->Disconnect(reader2->Node().node, inputs[0].source, filterNode.node, inputs[0].destination); roster->GetConnectedOutputsFor(filterNode, &outputs[0], 1, &numOutputs); roster->Disconnect(filterNode.node, outputs[0].source, writer->Node().node, outputs[0].destination); roster->Connect(inputs[0].source, outputs[0].destination, &inputs[0].format, &outputs[0], &inputs[0]); filterConnected = false; } break; default: break; } } if (timeEvent == timeList.CountItems() - 1) break; doConnect = false; composant = eventList->ItemAt(i); switch (composant->event) { case video1: if (reader1 != NULL) { roster->GetConnectedOutputsFor(reader1->Node(), outputs, 1, &numOutputs); if (numOutputs == 1) { destinations[0] = outputs[0].destination; doConnect = true; } //roster->ReleaseNode(reader1->Node()); delete reader1; reader1Connected = false; reader1 = NULL; } reader1 = new FileReader(composant->u.video.filepath, composant->u.video.filepath, 0); roster->SetRunModeNode(reader1->Node(), BMediaNode::B_OFFLINE); if (doConnect) { roster->GetFreeOutputsFor(reader1->Node(), outputs, 1, &numOutputs); roster->Connect(outputs[0].source, destinations[0], &outputs[0].format, &outputs[0], &inputs[0]); reader1Connected = true; } else if (transitionConnected) { roster->GetFreeInputsFor(transitionNode, inputs, 1, &numInputs); roster->GetFreeOutputsFor(reader1->Node(), outputs, 1, &numOutputs); roster->GetFormatFor(outputs[0], &format); roster->Connect(outputs[0].source, inputs[0].destination, &format, &outputs[0], &inputs[0]); reader1Connected = true; } else if (filterConnected) { roster->GetFreeInputsFor(filterNode, inputs, 1, &numInputs); roster->GetFreeOutputsFor(reader1->Node(), outputs, 1, &numOutputs); roster->GetFormatFor(outputs[0], &format); roster->Connect(outputs[0].source, inputs[0].destination, &format, &outputs[0], &inputs[0]); reader1Connected = true; } else if (!writerConnected && firstTrackActive) { roster->GetFreeInputsFor(writer->Node(), inputs, 1, &numInputs); roster->GetFreeOutputsFor(reader1->Node(), outputs, 1, &numOutputs); roster->GetFormatFor(outputs[0], &format); roster->Connect(outputs[0].source, inputs[0].destination, &format, &outputs[0], &inputs[0]); writerConnected = true; reader1Connected = true; } time = (bigtime_t*)timeList.ItemAt(timeEvent); time2 = (bigtime_t*)timeList.ItemAt(timeEvent + 1); /* Tell the nodes to start until next time event */ roster->RollNode(writer->Node(), *time, *time2); if (filterConnected) roster->RollNode(filterNode, *time, *time2); if (transitionConnected) roster->RollNode(transitionNode, *time, *time2); roster->RollNode(reader1->Node(), *time, *time2, composant->u.video.begin); break; case video2: if (reader2 != NULL) { roster->GetConnectedOutputsFor(reader2->Node(), outputs, 1, &numOutputs); if (numOutputs == 1) { destinations[0] = outputs[0].destination; doConnect = true; } //roster->ReleaseNode(reader2->Node()); delete reader2; reader2Connected = false; reader2 = NULL; } reader2 = new FileReader(composant->u.video.filepath, composant->u.video.filepath, 0); roster->SetRunModeNode(reader2->Node(), BMediaNode::B_OFFLINE); if (doConnect) { roster->GetFreeOutputsFor(reader2->Node(), outputs, 1, &numOutputs); roster->Connect(outputs[0].source, destinations[0], &outputs[0].format, &outputs[0], &inputs[0]); reader2Connected = true; } // else if (transitionConnected) // { // roster->GetFreeInputsFor(transitionNode, inputs, 1, &numInputs); // roster->GetFreeOutputsFor(reader2->Node(), outputs, 1, &numOutputs); // roster->GetFormatFor(outputs[0], &format); // roster->Connect(outputs[0].source, inputs[0].destination, &format, &outputs[0], &inputs[0]); // reader2Connected = true; // } // else if (filterConnected) // { // roster->GetFreeInputsFor(filterNode, inputs, 1, &numInputs); // roster->GetFreeOutputsFor(reader2->Node(), outputs, 1, &numOutputs); // roster->GetFormatFor(outputs[0], &format); // roster->Connect(outputs[0].source, inputs[0].destination, &format, &outputs[0], &inputs[0]); // reader2Connected = true; // } // else if (!writerConnected && !firstTrackActive) // { // roster->GetFreeInputsFor(writer->Node(), inputs, 1, &numInputs); // roster->GetFreeOutputsFor(reader2->Node(), outputs, 1, &numOutputs); // roster->GetFormatFor(outputs[0], &format); // roster->Connect(outputs[0].source, inputs[0].destination, &format, &outputs[0], &inputs[0]); // writerConnected = true; // reader2Connected = true; // } time = (bigtime_t*)timeList.ItemAt(timeEvent); time2 = (bigtime_t*)timeList.ItemAt(timeEvent + 1); roster->RollNode(writer->Node(), *time, *time2); if (filterConnected) roster->RollNode(filterNode, *time, *time2); if (transitionConnected) roster->RollNode(transitionNode, *time, *time2); if (reader1Connected && firstTrackActive) roster->RollNode(transitionNode, *time, *time2); if (reader2Connected && !firstTrackActive) roster->RollNode(reader2->Node(), *time, *time2, composant->u.video.begin); break; case filter: /* Handle filter events */ if (filterConnected) { roster->GetConnectedOutputsFor(filterNode, outputs, 1, &numOutputs); if (numOutputs == 1) { destinations[0] = outputs[0].destination; doConnect = true; } roster->GetConnectedInputsFor(filterNode, inputs, 1, &numInputs); if (numInputs == 1) { sources[0] = inputs[0].source; } roster->ReleaseNode(filterNode); filterConnected = false; } FindFilter(composant->u.filter.type, &filterNode); SetFilterParameters(filterNode, composant->u.filter.param_list); roster->SetRunModeNode(filterNode, BMediaNode::B_OFFLINE); if (doConnect) { roster->GetFreeOutputsFor(filterNode, &outputs[1], 1, &numOutputs); roster->Connect(outputs[1].source, destinations[0], &outputs[0].format, &outputs[1], &inputs[1]); filterConnected = true; } else if (transitionConnected) { roster->GetConnectedOutputsFor(transitionNode, &outputs[0], 1, &numOutputs); roster->Disconnect(transitionNode.node, outputs[0].source, writer->Node().node, outputs[0].destination); roster->GetFreeInputsFor(filterNode, &inputs[0], 1, &numInputs); roster->Connect(outputs[0].source, inputs[0].destination, &outputs[0].format, &outputs[0], &inputs[0]); roster->GetFreeOutputsFor(filterNode, &outputs[1], 1, &numOutputs); roster->GetFreeInputsFor(writer->Node(), &inputs[1], 1, &numInputs); roster->Connect(outputs[1].source, inputs[1].destination, &inputs[1].format, &outputs[1], &inputs[1]); filterConnected = true; } else if (reader1Connected && firstTrackActive) { roster->GetConnectedOutputsFor(reader1->Node(), &outputs[0], 1, &numOutputs); roster->Disconnect(reader1->Node().node, outputs[0].source, writer->Node().node, outputs[0].destination); roster->GetFreeInputsFor(filterNode, &inputs[0], 1, &numInputs); roster->Connect(outputs[0].source, inputs[0].destination, &outputs[0].format, &outputs[0], &inputs[0]); roster->GetFreeOutputsFor(filterNode, &outputs[1], 1, &numOutputs); roster->GetFreeInputsFor(writer->Node(), &inputs[1], 1, &numInputs); roster->Connect(outputs[1].source, inputs[1].destination, &inputs[1].format, &outputs[1], &inputs[1]); filterConnected = true; } else if (reader2Connected && !firstTrackActive) { roster->GetConnectedOutputsFor(reader2->Node(), &outputs[0], 1, &numOutputs); roster->Disconnect(reader2->Node().node, outputs[0].source, writer->Node().node, outputs[0].destination); roster->GetFreeInputsFor(filterNode, &inputs[0], 1, &numInputs); roster->Connect(outputs[0].source, inputs[0].destination, &outputs[0].format, &outputs[0], &inputs[0]); roster->GetFreeOutputsFor(filterNode, &outputs[1], 1, &numOutputs); roster->GetFreeInputsFor(writer->Node(), &inputs[1], 1, &numInputs); roster->Connect(outputs[1].source, inputs[1].destination, &inputs[1].format, &outputs[1], &inputs[1]); filterConnected = true; } time = (bigtime_t*)timeList.ItemAt(timeEvent); time2 = (bigtime_t*)timeList.ItemAt(timeEvent + 1); /* Tell the nodes to start until next time event */ roster->RollNode(writer->Node(), *time, *time2); if (filterConnected) roster->RollNode(filterNode, *time, *time2); if (transitionConnected) roster->RollNode(transitionNode, *time, *time2); if (reader2Connected) roster->RollNode(reader2->Node(), *time, *time2); if (reader1Connected) roster->RollNode(reader1->Node(), *time, *time2); break; case transition: /* Handle transition events */ if (transitionConnected) { roster->GetConnectedOutputsFor(transitionNode, outputs, 1, &numOutputs); if (numOutputs == 1) { destinations[0] = outputs[0].destination; doConnect = true; } roster->GetConnectedInputsFor(transitionNode, inputs, 2, &numInputs); if (numInputs) { sources[0] = inputs[0].source; sources[1] = inputs[1].source; } roster->ReleaseNode(transitionNode); transitionConnected = false; } FindTransition(composant->u.transition.type, &transitionNode); roster->SetRunModeNode(transitionNode, BMediaNode::B_OFFLINE); if (doConnect) { roster->GetFreeInputsFor(transitionNode, &inputs[2], 2, &numInputs); roster->Connect(inputs[0].source, inputs[2].destination, &inputs[0].format, &outputs[1], &inputs[2]); roster->Connect(inputs[1].source, inputs[3].destination, &inputs[1].format, &outputs[1], &inputs[2]); roster->GetFreeOutputsFor(transitionNode, &outputs[1], 1, &numOutputs); roster->Connect(outputs[1].source, destinations[0], &outputs[0].format, &outputs[1], &inputs[0]); transitionConnected = true; } else if (filterConnected) { roster->GetConnectedInputsFor(filterNode, inputs, 1, &numInputs); if (reader1Connected) roster->Disconnect(reader1->Node().node, inputs[0].source, filterNode.node, inputs[0].destination); else if (reader2Connected) roster->Disconnect(reader2->Node().node, inputs[0].source, filterNode.node, inputs[0].destination); roster->GetFreeInputsFor(transitionNode, &inputs[2], 2, &numInputs); roster->GetFreeOutputsFor(reader1->Node(), &outputs[0], 1, &numOutputs); roster->Connect(outputs[0].source, inputs[2].destination, &outputs[0].format, &outputs[0], &inputs[2]); roster->GetFreeOutputsFor(reader2->Node(), &outputs[0], 1, &numOutputs); roster->Connect(outputs[0].source, inputs[3].destination, &outputs[0].format, &outputs[0], &inputs[3]); roster->GetFreeOutputsFor(transitionNode, &outputs[2], 1, &numOutputs); roster->Connect(outputs[2].source, inputs[0].destination, &inputs[0].format, &outputs[2], &inputs[0]); transitionConnected = true; } else if (reader1Connected && firstTrackActive) { roster->GetConnectedOutputsFor(reader1->Node(), &outputs[0], 1, &numOutputs); roster->Disconnect(reader1->Node().node, outputs[0].source, writer->Node().node, outputs[0].destination); roster->GetFreeInputsFor(transitionNode, &inputs[0], 2, &numInputs); roster->Connect(outputs[0].source, inputs[0].destination, &outputs[0].format, &outputs[0], &inputs[0]); roster->GetFreeOutputsFor(reader2->Node(), &outputs[1], 1, &numOutputs); roster->Connect(outputs[1].source, inputs[1].destination, &outputs[0].format, &outputs[1], &inputs[1]); roster->GetFreeOutputsFor(transitionNode, &outputs[1], 1, &numOutputs); roster->GetFreeInputsFor(writer->Node(), &inputs[1], 1, &numInputs); roster->Connect(outputs[1].source, inputs[1].destination, &inputs[1].format, &outputs[1], &inputs[1]); transitionConnected = true; } else if (reader2Connected && !firstTrackActive) { roster->GetConnectedOutputsFor(reader2->Node(), &outputs[0], 1, &numOutputs); roster->Disconnect(reader2->Node().node, outputs[0].source, writer->Node().node, outputs[0].destination); roster->GetFreeInputsFor(transitionNode, &inputs[0], 2, &numInputs); roster->Connect(outputs[0].source, inputs[0].destination, &outputs[0].format, &outputs[0], &inputs[0]); roster->GetFreeOutputsFor(reader1->Node(), &outputs[1], 1, &numOutputs); roster->Connect(outputs[1].source, inputs[1].destination, &outputs[0].format, &outputs[1], &inputs[1]); roster->GetFreeOutputsFor(transitionNode, &outputs[1], 1, &numOutputs); roster->GetFreeInputsFor(writer->Node(), &inputs[1], 1, &numInputs); roster->Connect(outputs[1].source, inputs[1].destination, &inputs[1].format, &outputs[1], &inputs[1]); transitionConnected = true; } time = (bigtime_t*)timeList.ItemAt(timeEvent); time2 = (bigtime_t*)timeList.ItemAt(timeEvent + 1); /* Tell the nodes to start until next time event */ roster->RollNode(writer->Node(), *time, *time2); if (filterConnected) roster->RollNode(filterNode, *time, *time2); if (transitionConnected) roster->RollNode(transitionNode, *time, *time2); if (reader2Connected) roster->RollNode(reader2->Node(), *time, *time2); if (reader1Connected) roster->RollNode(reader1->Node(), *time, *time2); break; default: break; } } // release_sem(lock_sem); } delete writer; return B_OK; }
// // TentacleThink // void CTentacle :: Cycle( void ) { // ALERT( at_console, "%s %.2f %d %d\n", STRING( pev->targetname ), pev->origin.z, m_MonsterState, m_IdealMonsterState ); pev->nextthink = gpGlobals-> time + 0.1; // ALERT( at_console, "%s %d %d %d %f %f\n", STRING( pev->targetname ), pev->sequence, m_iGoalAnim, m_iDir, pev->framerate, pev->health ); if (m_MonsterState == MONSTERSTATE_SCRIPT || m_IdealMonsterState == MONSTERSTATE_SCRIPT) { pev->angles.y = m_flInitialYaw; pev->ideal_yaw = m_flInitialYaw; ClearConditions( IgnoreConditions() ); MonsterThink( ); m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; return; } DispatchAnimEvents( ); StudioFrameAdvance( ); ChangeYaw( pev->yaw_speed ); CSound *pSound; Listen( ); // Listen will set this if there's something in my sound list if ( HasConditions( bits_COND_HEAR_SOUND ) ) pSound = PBestSound(); else pSound = NULL; if ( pSound ) { Vector vecDir; if (gpGlobals->time - m_flPrevSoundTime < 0.5) { float dt = gpGlobals->time - m_flPrevSoundTime; vecDir = pSound->m_vecOrigin + (pSound->m_vecOrigin - m_vecPrevSound) / dt - pev->origin; } else { vecDir = pSound->m_vecOrigin - pev->origin; } m_flPrevSoundTime = gpGlobals->time; m_vecPrevSound = pSound->m_vecOrigin; m_flSoundYaw = UTIL_VecToYaw ( vecDir ) - m_flInitialYaw; m_iSoundLevel = Level( vecDir.z ); if (m_flSoundYaw < -180) m_flSoundYaw += 360; if (m_flSoundYaw > 180) m_flSoundYaw -= 360; // ALERT( at_console, "sound %d %.0f\n", m_iSoundLevel, m_flSoundYaw ); if (m_flSoundTime < gpGlobals->time) { // play "I hear new something" sound char *sound; switch( RANDOM_LONG(0,1) ) { case 0: sound = "tentacle/te_alert1.wav"; break; case 1: sound = "tentacle/te_alert2.wav"; break; } // UTIL_EmitAmbientSound(ENT(pev), pev->origin + Vector( 0, 0, MyHeight()), sound, 1.0, ATTN_NORM, 0, 100); } m_flSoundTime = gpGlobals->time + RANDOM_FLOAT( 5.0, 10.0 ); } // clip ideal_yaw float dy = m_flSoundYaw; switch( pev->sequence ) { case TENTACLE_ANIM_Floor_Rear: case TENTACLE_ANIM_Floor_Rear_Idle: case TENTACLE_ANIM_Lev1_Rear: case TENTACLE_ANIM_Lev1_Rear_Idle: case TENTACLE_ANIM_Lev2_Rear: case TENTACLE_ANIM_Lev2_Rear_Idle: case TENTACLE_ANIM_Lev3_Rear: case TENTACLE_ANIM_Lev3_Rear_Idle: if (dy < 0 && dy > -m_flMaxYaw) dy = -m_flMaxYaw; if (dy > 0 && dy < m_flMaxYaw) dy = m_flMaxYaw; break; default: if (dy < -m_flMaxYaw) dy = -m_flMaxYaw; if (dy > m_flMaxYaw) dy = m_flMaxYaw; } pev->ideal_yaw = m_flInitialYaw + dy; if (m_fSequenceFinished) { // ALERT( at_console, "%s done %d %d\n", STRING( pev->targetname ), pev->sequence, m_iGoalAnim ); if (pev->health <= 1) { m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; if (pev->sequence == TENTACLE_ANIM_Pit_Idle) { pev->health = 75; } } else if ( m_flSoundTime > gpGlobals->time ) { if (m_flSoundYaw >= -(m_flMaxYaw + 30) && m_flSoundYaw <= (m_flMaxYaw + 30)) { // strike m_iGoalAnim = LookupActivity( ACT_T_STRIKE + m_iSoundLevel ); } else if (m_flSoundYaw >= -m_flMaxYaw * 2 && m_flSoundYaw <= m_flMaxYaw * 2) { // tap m_iGoalAnim = LookupActivity( ACT_T_TAP + m_iSoundLevel ); } else { // go into rear idle m_iGoalAnim = LookupActivity( ACT_T_REARIDLE + m_iSoundLevel ); } } else if (pev->sequence == TENTACLE_ANIM_Pit_Idle) { // stay in pit until hear noise m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; } else if (pev->sequence == m_iGoalAnim) { if (MyLevel() >= 0 && gpGlobals->time < m_flSoundTime) { if (RANDOM_LONG(0,9) < m_flSoundTime - gpGlobals->time) { // continue stike m_iGoalAnim = LookupActivity( ACT_T_STRIKE + m_iSoundLevel ); } else { // tap m_iGoalAnim = LookupActivity( ACT_T_TAP + m_iSoundLevel ); } } else if (MyLevel( ) < 0) { m_iGoalAnim = LookupActivity( ACT_T_IDLE + 0 ); } else { if (m_flNextSong < gpGlobals->time) { // play "I hear new something" sound char *sound; switch( RANDOM_LONG(0,1) ) { case 0: sound = "tentacle/te_sing1.wav"; break; case 1: sound = "tentacle/te_sing2.wav"; break; } EMIT_SOUND(ENT(pev), CHAN_VOICE, sound, 1.0, ATTN_NORM); m_flNextSong = gpGlobals->time + RANDOM_FLOAT( 10, 20 ); } if (RANDOM_LONG(0,15) == 0) { // idle on new level m_iGoalAnim = LookupActivity( ACT_T_IDLE + RANDOM_LONG(0,3) ); } else if (RANDOM_LONG(0,3) == 0) { // tap m_iGoalAnim = LookupActivity( ACT_T_TAP + MyLevel( ) ); } else { // idle m_iGoalAnim = LookupActivity( ACT_T_IDLE + MyLevel( ) ); } } if (m_flSoundYaw < 0) m_flSoundYaw += RANDOM_FLOAT( 2, 8 ); else m_flSoundYaw -= RANDOM_FLOAT( 2, 8 ); } pev->sequence = FindTransition( pev->sequence, m_iGoalAnim, &m_iDir ); if (m_iDir > 0) { pev->frame = 0; } else { m_iDir = -1; // just to safe pev->frame = 255; } ResetSequenceInfo( ); m_flFramerateAdj = RANDOM_FLOAT( -0.2, 0.2 ); pev->framerate = m_iDir * 1.0 + m_flFramerateAdj; switch( pev->sequence) { case TENTACLE_ANIM_Floor_Tap: case TENTACLE_ANIM_Lev1_Tap: case TENTACLE_ANIM_Lev2_Tap: case TENTACLE_ANIM_Lev3_Tap: { Vector vecSrc; UTIL_MakeVectors( pev->angles ); TraceResult tr1, tr2; vecSrc = pev->origin + Vector( 0, 0, MyHeight() - 4); UTIL_TraceLine( vecSrc, vecSrc + gpGlobals->v_forward * 512, ignore_monsters, ENT( pev ), &tr1 ); vecSrc = pev->origin + Vector( 0, 0, MyHeight() + 8); UTIL_TraceLine( vecSrc, vecSrc + gpGlobals->v_forward * 512, ignore_monsters, ENT( pev ), &tr2 ); // ALERT( at_console, "%f %f\n", tr1.flFraction * 512, tr2.flFraction * 512 ); m_flTapRadius = SetBlending( 0, RANDOM_FLOAT( tr1.flFraction * 512, tr2.flFraction * 512 ) ); } break; default: m_flTapRadius = 336; // 400 - 64 break; } pev->view_ofs.z = MyHeight( ); // ALERT( at_console, "seq %d\n", pev->sequence ); } if (m_flPrevSoundTime + 2.0 > gpGlobals->time) { // 1.5 normal speed if hears sounds pev->framerate = m_iDir * 1.5 + m_flFramerateAdj; } else if (m_flPrevSoundTime + 5.0 > gpGlobals->time) { // slowdown to normal pev->framerate = m_iDir + m_iDir * (5 - (gpGlobals->time - m_flPrevSoundTime)) / 2 + m_flFramerateAdj; } }