void Mark2_BlasterAttack( qboolean advance ) { if ( TIMER_Done( NPC, "attackDelay" ) ) // Attack? { if ( NPCInfo->localState == LSTATE_NONE ) // He's up so shoot less often. { TIMER_Set( NPC, "attackDelay", Q_irand( 500, 2000 ) ); } else { TIMER_Set( NPC, "attackDelay", Q_irand( 100, 500 ) ); } Mark2_FireBlaster( advance ); return; } else if ( advance ) { Mark2_Hunt(); } }
/* ------------------------- Mark2_AttackDecision ------------------------- */ void Mark2_AttackDecision( void ) { float distance; qboolean visible; qboolean advance; NPC_FaceEnemy( qtrue ); distance = (int) DistanceHorizontalSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ); visible = NPC_ClearLOS4( NPC->enemy ); advance = (qboolean)(distance > MIN_DISTANCE_SQR); // He's been ordered to get up if (NPCInfo->localState == LSTATE_RISINGUP) { NPC->flags &= ~FL_SHIELDED; NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1START, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE ); if ((NPC->client->ps.legsTimer<=0) && NPC->client->ps.torsoAnim == BOTH_RUN1START ) { NPCInfo->localState = LSTATE_NONE; // He's up again. } return; } // If we cannot see our target, move to see it if ((!visible) || (!NPC_FaceEnemy(qtrue))) { // If he's going down or is down, make him get up if ((NPCInfo->localState == LSTATE_DOWN) || (NPCInfo->localState == LSTATE_DROPPINGDOWN)) { if ( TIMER_Done( NPC, "downTime" ) ) // Down being down?? (The delay is so he doesn't pop up and down when the player goes in and out of range) { NPCInfo->localState = LSTATE_RISINGUP; NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1STOP, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE ); TIMER_Set( NPC, "runTime", Q_irand( 3000, 8000) ); // So he runs for a while before testing to see if he should drop down. } } else { Mark2_Hunt(); } return; } // He's down but he could advance if he wants to. if ((advance) && (TIMER_Done( NPC, "downTime" )) && (NPCInfo->localState == LSTATE_DOWN)) { NPCInfo->localState = LSTATE_RISINGUP; NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1STOP, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE ); TIMER_Set( NPC, "runTime", Q_irand( 3000, 8000) ); // So he runs for a while before testing to see if he should drop down. } NPC_FaceEnemy( qtrue ); // Dropping down to shoot if (NPCInfo->localState == LSTATE_DROPPINGDOWN) { NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1STOP, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE ); TIMER_Set( NPC, "downTime", Q_irand( 3000, 9000) ); if ((NPC->client->ps.legsTimer<=0) && NPC->client->ps.torsoAnim == BOTH_RUN1STOP ) { NPC->flags |= FL_SHIELDED; NPCInfo->localState = LSTATE_DOWN; } } // He's down and shooting else if (NPCInfo->localState == LSTATE_DOWN) { NPC->flags |= FL_SHIELDED;//only damagable by lightsabers and missiles Mark2_BlasterAttack(qfalse); } else if (TIMER_Done( NPC, "runTime" )) // Lowering down to attack. But only if he's done running at you. { NPCInfo->localState = LSTATE_DROPPINGDOWN; } else if (advance) { // We can see enemy so shoot him if timer lets you. Mark2_BlasterAttack(advance); } }