Start making monstermod aware of normal HL monsters.

This is still heavily experimental and its use is not yet recommended.
This commit is contained in:
Giegue
2023-02-15 21:19:57 -03:00
parent 5830ac7908
commit 6e1081d793
6 changed files with 368 additions and 141 deletions

View File

@@ -120,7 +120,7 @@ void CMBaseMonster :: Look ( int iDistance )
// DON'T let visibility information from last frame sit around!
ClearConditions(bits_COND_SEE_HATE | bits_COND_SEE_DISLIKE | bits_COND_SEE_ENEMY | bits_COND_SEE_FEAR | bits_COND_SEE_NEMESIS | bits_COND_SEE_CLIENT);
m_edictList_count = 0;
m_edictList_count = 0;
edict_t *pSightEnt = NULL;// the current visible entity that we're dealing with
@@ -137,23 +137,20 @@ void CMBaseMonster :: Look ( int iDistance )
{
pSightEnt = pList[i];
// !!!temporarily only considering other monsters and clients, don't see prisoners
if ( pSightEnt != this->edict() &&
!FBitSet( pSightEnt->v.spawnflags, SF_MONSTER_PRISONER ) &&
pSightEnt->v.health > 0 )
if ( pSightEnt != this->edict() && !FBitSet( pSightEnt->v.spawnflags, SF_MONSTER_PRISONER ) && pSightEnt->v.health > 0 )
{
// is this a player AND are they alive?
if (UTIL_IsPlayer(pSightEnt) && UTIL_IsAlive(pSightEnt))
{
// is this a player AND are they alive?
if (UTIL_IsPlayer(pSightEnt) && UTIL_IsAlive(pSightEnt))
{
// the looker will want to consider this entity
// don't check anything else about an entity that can't be seen.
if ( UTIL_FInViewCone( pSightEnt, ENT(pev), m_flFieldOfView ) &&
!FBitSet( pSightEnt->v.flags, FL_NOTARGET ) && UTIL_FVisible( pSightEnt, ENT(pev) ) )
if ( UTIL_FInViewCone( pSightEnt, ENT(pev), m_flFieldOfView ) && !FBitSet( pSightEnt->v.flags, FL_NOTARGET ) && UTIL_FVisible( pSightEnt, ENT(pev) ) )
{
m_edictList[m_edictList_count] = pSightEnt;
m_edictList_count++;
m_edictList[m_edictList_count] = pSightEnt;
m_edictList_count++;
// if we see a client, remember that (mostly for scripted AI)
iSighted |= bits_COND_SEE_CLIENT;
// if we see a client, remember that (mostly for scripted AI)
iSighted |= bits_COND_SEE_CLIENT;
// is this monster NOT a scientist?
if (strcmp(STRING(pev->model), "models/scientist.mdl") != 0)
@@ -166,19 +163,19 @@ void CMBaseMonster :: Look ( int iDistance )
iSighted |= bits_COND_SEE_ENEMY;
}
}
}
}
else if (pSightEnt->v.euser4 != NULL)
{
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pSightEnt));
}
}
else if (pSightEnt->v.euser4 != NULL)
{
/* MonsterMod monster looking at another MonsterMod monster */
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pSightEnt));
// the looker will want to consider this entity
// don't check anything else about an entity that can't be seen, or an entity that you don't care about.
if ( IRelationship( pMonster ) != R_NO && UTIL_FInViewCone( pSightEnt, ENT(pev), m_flFieldOfView ) &&
!FBitSet( pSightEnt->v.flags, FL_NOTARGET ) && UTIL_FVisible( pSightEnt, ENT(pev) ) )
if ( IRelationship( pMonster ) != R_NO && UTIL_FInViewCone( pSightEnt, ENT(pev), m_flFieldOfView ) && !FBitSet( pSightEnt->v.flags, FL_NOTARGET ) && UTIL_FVisible( pSightEnt, ENT(pev) ) )
{
m_edictList[m_edictList_count] = pSightEnt;
m_edictList_count++;
m_edictList[m_edictList_count] = pSightEnt;
m_edictList_count++;
if ( ENT(pMonster->pev) == m_hEnemy )
{
@@ -210,6 +207,47 @@ void CMBaseMonster :: Look ( int iDistance )
}
}
}
else if (!UTIL_IsPlayer(pSightEnt))
{
/* MonsterMod monster looking at a NON-MonsterMod monster */
// the looker will want to consider this entity
// don't check anything else about an entity that can't be seen, or an entity that you don't care about.
if ( IRelationship( pSightEnt->v.iuser4 ) != R_NO && UTIL_FInViewCone( pSightEnt, ENT(pev), m_flFieldOfView ) && !FBitSet( pSightEnt->v.flags, FL_NOTARGET ) && UTIL_FVisible( pSightEnt, ENT(pev) ) )
{
m_edictList[m_edictList_count] = pSightEnt;
m_edictList_count++;
if ( pSightEnt == m_hEnemy )
{
// we know this ent is visible, so if it also happens to be our enemy, store that now.
iSighted |= bits_COND_SEE_ENEMY;
}
// don't add the Enemy's relationship to the conditions. We only want to worry about conditions when
// we see monsters other than the Enemy.
switch ( IRelationship ( pSightEnt->v.iuser4 ) )
{
case R_NM:
iSighted |= bits_COND_SEE_NEMESIS;
break;
case R_HT:
iSighted |= bits_COND_SEE_HATE;
break;
case R_DL:
iSighted |= bits_COND_SEE_DISLIKE;
break;
case R_FR:
iSighted |= bits_COND_SEE_FEAR;
break;
case R_AL:
break;
default:
ALERT ( at_aiconsole, "%s can't assess %s\n", STRING(pev->classname), STRING(pSightEnt->v.classname ) );
break;
}
}
}
}
}
}
@@ -1743,6 +1781,9 @@ void CMBaseMonster :: StartMonster ( void )
SetActivity( ACT_IDLE );
ChangeSchedule( GetScheduleOfType( SCHED_WAIT_TRIGGER ) );
}
// Notify normal game engine of monster classify
pev->iuser4 = Classify();
}
@@ -1784,6 +1825,14 @@ int CMBaseMonster::TaskIsRunning( void )
// relationship between two types of monster.
//=========================================================
int CMBaseMonster::IRelationship ( CMBaseEntity *pTarget )
{
return IRelationshipByClass( pTarget->Classify() );
}
int CMBaseMonster::IRelationship ( int iTargetClass )
{
return IRelationshipByClass( iTargetClass );
}
int CMBaseMonster::IRelationshipByClass ( int iClass )
{
static int iEnemy[16][16] =
{ // NONE MACH PLYR HPASS HMIL AMIL APASS AMONST APREY APRED INSECT PLRALY PBWPN ABWPN RXPIT RXSHK
@@ -1805,7 +1854,7 @@ int CMBaseMonster::IRelationship ( CMBaseEntity *pTarget )
/*RXSHOCKTRP*/ { R_NO ,R_DL ,R_HT ,R_DL ,R_HT ,R_HT ,R_DL ,R_NO ,R_NO ,R_DL ,R_NO ,R_DL, R_NO, R_NO, R_AL, R_AL }
};
return iEnemy[ Classify() ][ pTarget->Classify() ];
return iEnemy[ Classify() ][ iClass ];
}
//=========================================================
@@ -2019,38 +2068,39 @@ edict_t *CMBaseMonster :: BestVisibleEnemy ( void )
int iNearest;
int iDist;
int iBestRelationship;
edict_t *pReturn;
edict_t *pEnt;
int edictList_index = 0;
edict_t *pReturn;
edict_t *pEnt;
int edictList_index = 0;
iNearest = 8192;// so first visible entity will become the closest.
iBestRelationship = R_NO;
pReturn = NULL;
pReturn = NULL;
while (edictList_index < m_edictList_count)
while (edictList_index < m_edictList_count)
{
pEnt = m_edictList[edictList_index];
pEnt = m_edictList[edictList_index];
if ( UTIL_IsPlayer(pEnt) )
{
// it's a player...
if ( UTIL_IsPlayer(pEnt) )
{
// it's a player...
iDist = ( pEnt->v.origin - pev->origin ).Length();
if ( iDist <= iNearest )
{
iNearest = iDist;
iBestRelationship = R_NM; // player is always nemsis
iBestRelationship = R_NM; // player is always nemesis
pReturn = pEnt;
}
}
else if (pEnt->v.euser4 != NULL)
{
}
else if (pEnt->v.euser4 != NULL)
{
// it's a monstermod monster...
CMBaseMonster *pNextEnt = GetClassPtr((CMBaseMonster *)VARS(pEnt));
if ( pNextEnt->IsAlive() )
{
if ( IRelationship( pNextEnt) > iBestRelationship )
if ( IRelationship( pNextEnt ) > iBestRelationship )
{
// this entity is disliked MORE than the entity that we
// currently think is the best visible enemy. No need to do
@@ -2059,13 +2109,13 @@ edict_t *CMBaseMonster :: BestVisibleEnemy ( void )
iNearest = ( pNextEnt->pev->origin - pev->origin ).Length();
pReturn = pEnt;
}
else if ( IRelationship( pNextEnt) == iBestRelationship )
else if ( IRelationship( pNextEnt ) == iBestRelationship )
{
// this entity is disliked just as much as the entity that
// we currently think is the best visible enemy, so we only
// get mad at it if it is closer.
iDist = ( pNextEnt->pev->origin - pev->origin ).Length();
if ( iDist <= iNearest )
{
iNearest = iDist;
@@ -2074,9 +2124,34 @@ edict_t *CMBaseMonster :: BestVisibleEnemy ( void )
}
}
}
}
}
else if (!UTIL_IsPlayer(pEnt))
{
// it's a game default monster...
if ( UTIL_IsAlive(pEnt) )
{
//repeat2
if ( IRelationship( pEnt->v.iuser4 ) > iBestRelationship )
{
iBestRelationship = IRelationship( pEnt->v.iuser4 );
iNearest = ( pEnt->v.origin - pev->origin ).Length();
pReturn = pEnt;
}
else if ( IRelationship( pEnt->v.iuser4 ) == iBestRelationship )
{
iDist = ( pEnt->v.origin - pev->origin ).Length();
edictList_index++;
if ( iDist <= iNearest )
{
iNearest = iDist;
iBestRelationship = IRelationship( pEnt->v.iuser4 );
pReturn = pEnt;
}
}
}
}
edictList_index++;
}
return pReturn;