//========================================================= // // SquadMakeEnemy - makes everyone in the squad angry at // the same entity. // //========================================================= void CSquadMonster :: SquadMakeEnemy ( CBaseEntity *pEnemy ) { if (!InSquad()) return; if ( !pEnemy ) { ALERT ( at_console, "ERROR: SquadMakeEnemy() - pEnemy is NULL!\n" ); return; } CSquadMonster *pSquadLeader = MySquadLeader( ); for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) { CSquadMonster *pMember = pSquadLeader->MySquadMember(i); if (pMember) { // reset members who aren't activly engaged in fighting if (pMember->m_hEnemy != pEnemy && !pMember->HasConditions( bits_COND_SEE_ENEMY)) { if ( pMember->m_hEnemy != NULL) { // remember their current enemy pMember->PushEnemy( pMember->m_hEnemy, pMember->m_vecEnemyLKP ); } // give them a new enemy pMember->m_hEnemy = pEnemy; pMember->m_vecEnemyLKP = pEnemy->pev->origin; pMember->SetConditions ( bits_COND_NEW_ENEMY ); } } } }
//========================================================= // FValidateCover - determines whether or not the chosen // cover location is a good one to move to. (currently based // on proximity to others in the squad) //========================================================= BOOL CSquadMonster :: SquadMemberInRange ( const Vector &vecLocation, float flDist ) { if (!InSquad()) return FALSE; CSquadMonster *pSquadLeader = MySquadLeader(); for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) { CSquadMonster *pSquadMember = pSquadLeader->MySquadMember(i); if (pSquadMember && (vecLocation - pSquadMember->pev->origin ).Length2D() <= flDist) return TRUE; } return FALSE; }
//========================================================= // // SquadCount(), return the number of members of this squad // callable from leaders & followers // //========================================================= int CSquadMonster :: SquadCount( void ) { if (!InSquad()) return 0; CSquadMonster *pSquadLeader = MySquadLeader(); int squadCount = 0; for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) { if (pSquadLeader->MySquadMember(i) != NULL) squadCount++; } return squadCount; }
//========================================================= // FValidateCover - determines whether or not the chosen // cover location is a good one to move to. (currently based // on proximity to others in the squad) //========================================================= bool CSquadMonster::SquadMemberInRange( const Vector &vecLocation, float flDist ) { if (!InSquad()) return false; CSquadMonster *pSquadLeader = MySquadLeader(); for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) { CSquadMonster *pSquadMember = pSquadLeader->MySquadMember(i); if (pSquadMember && (vecLocation - pSquadMember->GetAbsOrigin() ).Length2D() <= flDist) return true; } return false; }
//========================================================= // SquadEnemySplit- returns TRUE if not all squad members // are fighting the same enemy. //========================================================= BOOL CSquadMonster :: SquadEnemySplit ( void ) { if (!InSquad()) return FALSE; CSquadMonster *pSquadLeader = MySquadLeader(); CBaseEntity *pEnemy = pSquadLeader->m_hEnemy; for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) { CSquadMonster *pMember = pSquadLeader->MySquadMember(i); if (pMember != NULL && pMember->m_hEnemy != NULL && pMember->m_hEnemy != pEnemy) { return TRUE; } } return FALSE; }
//========================================================= // SquadEnemySplit- returns true if not all squad members // are fighting the same enemy. //========================================================= bool CSquadMonster::SquadEnemySplit() { if (!InSquad()) return false; CSquadMonster *pSquadLeader = MySquadLeader(); CBaseEntity *pEnemy = pSquadLeader->m_hEnemy; for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) { CSquadMonster *pMember = pSquadLeader->MySquadMember(i); if (pMember != NULL && pMember->m_hEnemy != NULL && pMember->m_hEnemy != pEnemy) { return true; } } return false; }
//========================================================= // FCanActiveIdle //========================================================= BOOL CHoundeye :: FCanActiveIdle ( void ) { if ( InSquad() ) { CSquadMonster *pSquadLeader = MySquadLeader(); for (int i = 0; i < MAX_SQUAD_MEMBERS;i++) { CSquadMonster *pMember = pSquadLeader->MySquadMember(i); if ( pMember != NULL && pMember != this && pMember->m_iHintNode != NO_NODE ) { // someone else in the group is active idling right now! return FALSE; } } return TRUE; } return TRUE; }
//========================================================= // NoFriendlyFire - checks for possibility of friendly fire // // Builds a large box in front of the grunt and checks to see // if any squad members are in that box. //========================================================= BOOL CSquadMonster :: NoFriendlyFire( void ) { if ( !InSquad() ) { return TRUE; } CPlane backPlane; CPlane leftPlane; CPlane rightPlane; Vector vecLeftSide; Vector vecRightSide; Vector v_left; //!!!BUGBUG - to fix this, the planes must be aligned to where the monster will be firing its gun, not the direction it is facing!!! if ( m_hEnemy != NULL ) { UTIL_MakeVectors ( UTIL_VecToAngles( m_hEnemy->Center() - pev->origin ) ); } else { // if there's no enemy, pretend there's a friendly in the way, so the grunt won't shoot. return FALSE; } //UTIL_MakeVectors ( pev->angles ); vecLeftSide = pev->origin - ( gpGlobals->v_right * ( pev->size.x * 1.5 ) ); vecRightSide = pev->origin + ( gpGlobals->v_right * ( pev->size.x * 1.5 ) ); v_left = gpGlobals->v_right * -1; leftPlane.InitializePlane ( gpGlobals->v_right, vecLeftSide ); rightPlane.InitializePlane ( v_left, vecRightSide ); backPlane.InitializePlane ( gpGlobals->v_forward, pev->origin ); /* ALERT ( at_console, "LeftPlane: %f %f %f : %f\n", leftPlane.m_vecNormal.x, leftPlane.m_vecNormal.y, leftPlane.m_vecNormal.z, leftPlane.m_flDist ); ALERT ( at_console, "RightPlane: %f %f %f : %f\n", rightPlane.m_vecNormal.x, rightPlane.m_vecNormal.y, rightPlane.m_vecNormal.z, rightPlane.m_flDist ); ALERT ( at_console, "BackPlane: %f %f %f : %f\n", backPlane.m_vecNormal.x, backPlane.m_vecNormal.y, backPlane.m_vecNormal.z, backPlane.m_flDist ); */ CSquadMonster *pSquadLeader = MySquadLeader(); for (int i = 0; i < MAX_SQUAD_MEMBERS; i++) { CSquadMonster *pMember = pSquadLeader->MySquadMember(i); if (pMember && pMember != this) { if ( backPlane.PointInFront ( pMember->pev->origin ) && leftPlane.PointInFront ( pMember->pev->origin ) && rightPlane.PointInFront ( pMember->pev->origin) ) { // this guy is in the check volume! Don't shoot! return FALSE; } } } return TRUE; }