//========================================================= // GetSchedule - Decides which type of schedule best suits // the monster's current state and conditions. Then calls // monster's member function to get a pointer to a schedule // of the proper type. //========================================================= Schedule_t *CAGrunt :: GetSchedule ( void ) { if ( HasConditions(bits_COND_HEAR_SOUND) ) { CSound *pSound; pSound = PBestSound(); ASSERT( pSound != NULL ); if ( pSound && (pSound->m_iType & bits_SOUND_DANGER) ) { // dangerous sound nearby! return GetScheduleOfType( SCHED_TAKE_COVER_FROM_BEST_SOUND ); } } switch ( m_MonsterState ) { case MONSTERSTATE_COMBAT: { // dead enemy if ( HasConditions( bits_COND_ENEMY_DEAD ) ) { // call base class, all code to handle dead enemies is centralized there. return CBaseMonster :: GetSchedule(); } if ( HasConditions(bits_COND_NEW_ENEMY) ) { return GetScheduleOfType( SCHED_WAKE_ANGRY ); } // zap player! if ( HasConditions ( bits_COND_CAN_MELEE_ATTACK1 ) ) { AttackSound();// this is a total hack. Should be parto f the schedule return GetScheduleOfType ( SCHED_MELEE_ATTACK1 ); } if ( HasConditions ( bits_COND_HEAVY_DAMAGE ) ) { return GetScheduleOfType( SCHED_SMALL_FLINCH ); } // can attack if ( HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) && OccupySlot ( bits_SLOTS_AGRUNT_HORNET ) ) { return GetScheduleOfType ( SCHED_RANGE_ATTACK1 ); } if ( OccupySlot ( bits_SLOT_AGRUNT_CHASE ) ) { return GetScheduleOfType ( SCHED_CHASE_ENEMY ); } return GetScheduleOfType ( SCHED_STANDOFF ); } } return CSquadMonster :: GetSchedule(); }
//========================================================= // GetSchedule //========================================================= Schedule_t *CHoundeye :: GetSchedule( void ) { switch ( m_MonsterState ) { case MONSTERSTATE_COMBAT: { // dead enemy if ( HasConditions( bits_COND_ENEMY_DEAD ) ) { // call base class, all code to handle dead enemies is centralized there. return CBaseMonster :: GetSchedule(); } if ( HasConditions( bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE ) ) { if ( RANDOM_FLOAT( 0 , 1 ) <= 0.4 ) { TraceResult tr; UTIL_MakeVectors( pev->angles ); UTIL_TraceHull( pev->origin, pev->origin + gpGlobals->v_forward * -128, dont_ignore_monsters, head_hull, ENT( pev ), &tr ); if ( tr.flFraction == 1.0 ) { // it's clear behind, so the hound will jump return GetScheduleOfType ( SCHED_HOUND_HOP_RETREAT ); } } return GetScheduleOfType ( SCHED_TAKE_COVER_FROM_ENEMY ); } if ( HasConditions( bits_COND_CAN_RANGE_ATTACK1 ) ) { if ( OccupySlot ( bits_SLOTS_HOUND_ATTACK ) ) { return GetScheduleOfType ( SCHED_RANGE_ATTACK1 ); } return GetScheduleOfType ( SCHED_HOUND_AGITATED ); } break; } default: break; } return CSquadMonster :: GetSchedule(); }
//----------------------------------------------------------------------------- // Purpose: Try to get one of a contiguous range of slots // Input : slotIDStart - start of slot range // slotIDEnd - end of slot range // hEnemy - enemy this slot is for // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CAI_Squad::OccupyStrategySlotRange( CBaseEntity *pEnemy, int slotIDStart, int slotIDEnd, int *pSlot ) { #ifndef PER_ENEMY_SQUADSLOTS // FIXME: combat slots need to be per enemy, not per squad. // As it is, once a squad is occupied it stops making even simple attacks to other things nearby. // This code may make soldiers too aggressive if (GetLeader() && pEnemy != GetLeader()->GetEnemy()) { *pSlot = SQUAD_SLOT_NONE; return true; } #endif // If I'm already occupying this slot if ( *pSlot >= slotIDStart && *pSlot <= slotIDEnd) return true; for ( int i = slotIDStart; i <= slotIDEnd; i++ ) { // Check enemy to see if slot already occupied if (!IsSlotOccupied(pEnemy, i)) { // Clear any previous spot; if (*pSlot != SQUAD_SLOT_NONE) { // As a debug measure check to see if slot was filled if (!IsSlotOccupied(pEnemy, *pSlot)) { DevMsg( "ERROR! Vacating an empty slot!\n"); } // Free the slot VacateSlot(pEnemy, *pSlot); } // Fill the slot OccupySlot(pEnemy, i); *pSlot = i; return true; } } return false; }