//========================================================= // 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; }
//========================================================= // 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() { 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() - GetAbsOrigin() ) ); } else { // if there's no enemy, pretend there's a friendly in the way, so the grunt won't shoot. return false; } //UTIL_MakeVectors ( GetAbsAngles() ); vecLeftSide = GetAbsOrigin() - ( gpGlobals->v_right * ( GetBounds().x * 1.5 ) ); vecRightSide = GetAbsOrigin() + ( gpGlobals->v_right * ( GetBounds().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, GetAbsOrigin() ); /* 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->GetAbsOrigin() ) && leftPlane.PointInFront ( pMember->GetAbsOrigin() ) && rightPlane.PointInFront ( pMember->GetAbsOrigin()) ) { // this guy is in the check volume! Don't shoot! return false; } } } return true; }
//========================================================= // // SquadRecruit(), get some monsters of my classification and // link them as a group. returns the group size // //========================================================= int CSquadMonster :: SquadRecruit( int searchRadius, int maxMembers ) { int squadCount; EntityClassification_t iMyClass = Classify();// cache this monster's class // Don't recruit if I'm already in a group if ( InSquad() ) return 0; if ( maxMembers < 2 ) return 0; // I am my own leader m_hSquadLeader = this; squadCount = 1; CBaseEntity *pEntity = NULL; if ( HasNetName() ) { // I have a netname, so unconditionally recruit everyone else with that name. pEntity = UTIL_FindEntityByString( pEntity, "netname", GetNetName() ); while ( pEntity ) { CSquadMonster *pRecruit = pEntity->MySquadMonsterPointer(); if ( pRecruit ) { if ( !pRecruit->InSquad() && pRecruit->Classify() == iMyClass && pRecruit != this ) { // minimum protection here against user error.in worldcraft. if (!SquadAdd( pRecruit )) break; squadCount++; } } pEntity = UTIL_FindEntityByString( pEntity, "netname", GetNetName() ); } } else { while ((pEntity = UTIL_FindEntityInSphere( pEntity, GetAbsOrigin(), searchRadius )) != NULL) { CSquadMonster *pRecruit = pEntity->MySquadMonsterPointer( ); if ( pRecruit && pRecruit != this && pRecruit->IsAlive() && !pRecruit->m_pCine ) { // Can we recruit this guy? if ( !pRecruit->InSquad() && pRecruit->Classify() == iMyClass && ( (iMyClass != EntityClassifications().GetClassificationId( classify::ALIEN_MONSTER )) || FStrEq( GetClassname(), pRecruit->GetClassname() )) && !pRecruit->HasNetName() ) { TraceResult tr; UTIL_TraceLine( GetAbsOrigin() + GetViewOffset(), pRecruit->GetAbsOrigin() + GetViewOffset(), ignore_monsters, pRecruit->edict(), &tr );// try to hit recruit with a traceline. if ( tr.flFraction == 1.0 ) { if (!SquadAdd( pRecruit )) break; squadCount++; } } } } } // no single member squads if (squadCount == 1) { m_hSquadLeader = NULL; } return squadCount; }