void CNPC_SO_BaseZombie::ForceMove( const Vector &targetPos, const Vector &traceDir, bool bRun ) { // Make sure our zombie gets the message (sometimes it is stubborn) // This bit should force our zombie to listen to us SetEnemy( NULL ); SetSchedule( SCHED_ZOMBIE_AMBUSH_MODE ); Vector chasePosition = targetPos; Vector vUpBit = chasePosition; vUpBit.z += 1; trace_t tr; AI_TraceHull( chasePosition, vUpBit, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); m_vecLastPosition = chasePosition; if ( m_hCine != NULL ) ExitScriptedSequence(); SetCondition( COND_RECEIVED_ORDERS ); if ( bRun ) SetSchedule( SCHED_FORCED_GO_RUN ); else SetSchedule( SCHED_FORCED_GO ); m_flMoveWaitFinished = gpGlobals->curtime; }
//========================================================= // GetIdealState - surveys the Conditions information available // and finds the best new state for a monster. //========================================================= MONSTERSTATE CBaseMonster :: GetIdealState ( void ) { int iConditions; iConditions = IScheduleFlags(); // If no schedule conditions, the new ideal state is probably the reason we're in here. switch ( m_MonsterState ) { case MONSTERSTATE_IDLE: /* IDLE goes to ALERT upon hearing a sound -IDLE goes to ALERT upon being injured IDLE goes to ALERT upon seeing food -IDLE goes to COMBAT upon sighting an enemy IDLE goes to HUNT upon smelling food */ { if ( iConditions & bits_COND_NEW_ENEMY ) { // new enemy! This means an idle monster has seen someone it dislikes, or // that a monster in combat has found a more suitable target to attack m_IdealMonsterState = MONSTERSTATE_COMBAT; } else if ( iConditions & bits_COND_LIGHT_DAMAGE ) { MakeIdealYaw ( m_vecEnemyLKP ); m_IdealMonsterState = MONSTERSTATE_ALERT; } else if ( iConditions & bits_COND_HEAVY_DAMAGE ) { MakeIdealYaw ( m_vecEnemyLKP ); m_IdealMonsterState = MONSTERSTATE_ALERT; } else if ( iConditions & bits_COND_HEAR_SOUND ) { CSound *pSound; pSound = PBestSound(); ASSERT( pSound != NULL ); if ( pSound ) { MakeIdealYaw ( pSound->m_vecOrigin ); if ( pSound->m_iType & (bits_SOUND_COMBAT|bits_SOUND_DANGER) ) m_IdealMonsterState = MONSTERSTATE_ALERT; } } else if ( iConditions & (bits_COND_SMELL | bits_COND_SMELL_FOOD) ) { m_IdealMonsterState = MONSTERSTATE_ALERT; } break; } case MONSTERSTATE_ALERT: /* ALERT goes to IDLE upon becoming bored -ALERT goes to COMBAT upon sighting an enemy ALERT goes to HUNT upon hearing a noise */ { if ( iConditions & (bits_COND_NEW_ENEMY|bits_COND_SEE_ENEMY) ) { // see an enemy we MUST attack m_IdealMonsterState = MONSTERSTATE_COMBAT; } else if ( iConditions & bits_COND_HEAR_SOUND ) { m_IdealMonsterState = MONSTERSTATE_ALERT; CSound *pSound = PBestSound(); ASSERT( pSound != NULL ); if ( pSound ) MakeIdealYaw ( pSound->m_vecOrigin ); } break; } case MONSTERSTATE_COMBAT: /* COMBAT goes to HUNT upon losing sight of enemy COMBAT goes to ALERT upon death of enemy */ { if ( m_hEnemy == NULL ) { m_IdealMonsterState = MONSTERSTATE_ALERT; // pev->effects = EF_BRIGHTFIELD; ALERT ( at_aiconsole, "***Combat state with no enemy!\n" ); } break; } case MONSTERSTATE_HUNT: /* HUNT goes to ALERT upon seeing food HUNT goes to ALERT upon being injured HUNT goes to IDLE if goal touched HUNT goes to COMBAT upon seeing enemy */ { break; } case MONSTERSTATE_SCRIPT: if ( iConditions & (bits_COND_TASK_FAILED|bits_COND_LIGHT_DAMAGE|bits_COND_HEAVY_DAMAGE) ) { ExitScriptedSequence(); // This will set the ideal state } break; case MONSTERSTATE_DEAD: m_IdealMonsterState = MONSTERSTATE_DEAD; break; } return m_IdealMonsterState; }