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:
@@ -134,6 +134,8 @@ public:
|
|||||||
virtual void MonsterThink( void );
|
virtual void MonsterThink( void );
|
||||||
void EXPORT CallMonsterThink( void ) { this->MonsterThink(); }
|
void EXPORT CallMonsterThink( void ) { this->MonsterThink(); }
|
||||||
virtual int IRelationship ( CMBaseEntity *pTarget );
|
virtual int IRelationship ( CMBaseEntity *pTarget );
|
||||||
|
virtual int IRelationship ( int iTargetClass );
|
||||||
|
int IRelationshipByClass ( int iClass );
|
||||||
virtual void MonsterInit ( void );
|
virtual void MonsterInit ( void );
|
||||||
virtual void MonsterInitDead( void ); // Call after animation/pose is set up
|
virtual void MonsterInitDead( void ); // Call after animation/pose is set up
|
||||||
virtual void BecomeDead( void );
|
virtual void BecomeDead( void );
|
||||||
@@ -1655,7 +1657,16 @@ public:
|
|||||||
void HandleAnimEvent(MonsterEvent_t *pEvent);
|
void HandleAnimEvent(MonsterEvent_t *pEvent);
|
||||||
void SetActivity(Activity NewActivity);
|
void SetActivity(Activity NewActivity);
|
||||||
|
|
||||||
|
Schedule_t *GetSchedule( void );
|
||||||
|
Schedule_t *GetScheduleOfType ( int Type );
|
||||||
|
|
||||||
|
BOOL CheckRangeAttack1( float flDot, float flDist );
|
||||||
|
BOOL CheckMeleeAttack1( float flDot, float flDist );
|
||||||
|
BOOL CheckRangeAttack2( float flDot, float flDist );
|
||||||
|
|
||||||
void Minigun(void);
|
void Minigun(void);
|
||||||
|
|
||||||
|
CUSTOM_SCHEDULES
|
||||||
|
|
||||||
float m_flMinigunSpinTime;
|
float m_flMinigunSpinTime;
|
||||||
};
|
};
|
||||||
@@ -1695,4 +1706,8 @@ public:
|
|||||||
int m_iBodyGibs;
|
int m_iBodyGibs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// Looking for Stukabat? It's located in cmflyingmonster.h
|
||||||
|
//=========================================================
|
||||||
|
|
||||||
#endif // BASEMONSTER_H
|
#endif // BASEMONSTER_H
|
||||||
|
|||||||
@@ -1060,8 +1060,8 @@ void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacke
|
|||||||
{
|
{
|
||||||
if ( pEntity->v.takedamage != DAMAGE_NO )
|
if ( pEntity->v.takedamage != DAMAGE_NO )
|
||||||
{
|
{
|
||||||
if (UTIL_IsPlayer(pEntity))
|
if (UTIL_IsPlayer(pEntity))
|
||||||
{
|
{
|
||||||
// blast's don't tavel into or out of water
|
// blast's don't tavel into or out of water
|
||||||
if (bInWater && pEntity->v.waterlevel == 0)
|
if (bInWater && pEntity->v.waterlevel == 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -1100,11 +1100,11 @@ void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacke
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
UTIL_TakeDamage ( pEntity, pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
|
UTIL_TakeDamage ( pEntity, pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pEntity->v.euser4 != NULL)
|
else if (pEntity->v.euser4 != NULL)
|
||||||
{
|
{
|
||||||
// UNDONE: this should check a damage mask, not an ignore
|
// UNDONE: this should check a damage mask, not an ignore
|
||||||
CMBaseEntity *pMonster = GetClassPtr((CMBaseEntity *)VARS(pEntity));
|
CMBaseEntity *pMonster = GetClassPtr((CMBaseEntity *)VARS(pEntity));
|
||||||
|
|
||||||
@@ -1151,7 +1151,60 @@ void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacke
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
pMonster->TakeDamage ( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
|
pMonster->TakeDamage ( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!UTIL_IsPlayer(pEntity))
|
||||||
|
{
|
||||||
|
// I'm doing really bad copypastes instead of making the code clean!
|
||||||
|
// Remind me to refactor this, this is not how this is supposed to be written!
|
||||||
|
// -Giegue
|
||||||
|
edict_t *pMonster = pEntity;
|
||||||
|
|
||||||
|
if ( iClassIgnore != CLASS_NONE && pMonster->v.iuser4 == iClassIgnore )
|
||||||
|
{// houndeyes don't hurt other houndeyes with their attack
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// blast's don't tavel into or out of water
|
||||||
|
if (bInWater && pEntity->v.waterlevel == 0)
|
||||||
|
continue;
|
||||||
|
if (!bInWater && pEntity->v.waterlevel == 3)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
vecSpot = UTIL_BodyTarget( pMonster, vecSrc );
|
||||||
|
|
||||||
|
UTIL_TraceLine ( vecSrc, vecSpot, dont_ignore_monsters, ENT(pevInflictor), &tr );
|
||||||
|
|
||||||
|
if ( tr.flFraction == 1.0 || tr.pHit == pEntity )
|
||||||
|
{// the explosion can 'see' this entity, so hurt them!
|
||||||
|
if (tr.fStartSolid)
|
||||||
|
{
|
||||||
|
// if we're stuck inside them, fixup the position and distance
|
||||||
|
tr.vecEndPos = vecSrc;
|
||||||
|
tr.flFraction = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// decrease damage for an ent that's farther from the bomb.
|
||||||
|
flAdjustedDamage = ( vecSrc - tr.vecEndPos ).Length() * falloff;
|
||||||
|
flAdjustedDamage = flDamage - flAdjustedDamage;
|
||||||
|
|
||||||
|
if ( flAdjustedDamage < 0 )
|
||||||
|
{
|
||||||
|
flAdjustedDamage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ALERT( at_console, "hit %s\n", STRING( pEntity->pev->classname ) );
|
||||||
|
if (tr.flFraction != 1.0)
|
||||||
|
{
|
||||||
|
ClearMultiDamage( );
|
||||||
|
UTIL_TraceAttack( pMonster, pevInflictor, flAdjustedDamage, (tr.vecEndPos - vecSrc).Normalize( ), &tr, bitsDamageType );
|
||||||
|
ApplyMultiDamage( pevInflictor, pevAttacker );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UTIL_TakeDamageExternal( pMonster, pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1207,6 +1260,8 @@ edict_t* CMBaseMonster :: CheckTraceHullAttack( float flDist, int iDamage, int i
|
|||||||
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pEntity));
|
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pEntity));
|
||||||
pMonster->TakeDamage( pev, pev, iDamage, iDmgType );
|
pMonster->TakeDamage( pev, pev, iDamage, iDmgType );
|
||||||
}
|
}
|
||||||
|
else if (!UTIL_IsPlayer(pEntity))
|
||||||
|
UTIL_TakeDamageExternal( pEntity, pev, pev, iDamage, iDmgType );
|
||||||
}
|
}
|
||||||
|
|
||||||
return pEntity;
|
return pEntity;
|
||||||
@@ -1386,8 +1441,8 @@ void CMBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShootin
|
|||||||
// do damage, paint decals
|
// do damage, paint decals
|
||||||
if (tr.flFraction != 1.0)
|
if (tr.flFraction != 1.0)
|
||||||
{
|
{
|
||||||
if (UTIL_IsPlayer(tr.pHit)) // is this a player?
|
if (UTIL_IsPlayer(tr.pHit)) // is this a player?
|
||||||
{
|
{
|
||||||
edict_t *pPlayer = tr.pHit;
|
edict_t *pPlayer = tr.pHit;
|
||||||
|
|
||||||
if ( iDamage )
|
if ( iDamage )
|
||||||
@@ -1396,60 +1451,63 @@ void CMBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShootin
|
|||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
DecalGunshot( &tr, iBulletType );
|
DecalGunshot( &tr, iBulletType );
|
||||||
}
|
}
|
||||||
else switch(iBulletType)
|
else
|
||||||
{
|
{
|
||||||
default:
|
switch(iBulletType)
|
||||||
case BULLET_MONSTER_9MM:
|
|
||||||
UTIL_TraceAttack(pPlayer, pevAttacker, gSkillData.monDmg9MM, vecDir, &tr, DMG_BULLET);
|
|
||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
|
||||||
DecalGunshot( &tr, iBulletType );
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BULLET_MONSTER_MP5:
|
|
||||||
UTIL_TraceAttack(pPlayer, pevAttacker, gSkillData.monDmgMP5, vecDir, &tr, DMG_BULLET);
|
|
||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
|
||||||
DecalGunshot( &tr, iBulletType );
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BULLET_MONSTER_12MM:
|
|
||||||
UTIL_TraceAttack(pPlayer, pevAttacker, gSkillData.monDmg12MM, vecDir, &tr, DMG_BULLET);
|
|
||||||
if ( !tracer )
|
|
||||||
{
|
{
|
||||||
|
default:
|
||||||
|
case BULLET_MONSTER_9MM:
|
||||||
|
UTIL_TraceAttack(pPlayer, pevAttacker, gSkillData.monDmg9MM, vecDir, &tr, DMG_BULLET);
|
||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
DecalGunshot( &tr, iBulletType );
|
DecalGunshot( &tr, iBulletType );
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BULLET_MONSTER_762:
|
|
||||||
UTIL_TraceAttack(pPlayer, pevAttacker, gSkillData.monDmg762, vecDir, &tr, DMG_BULLET);
|
|
||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
|
||||||
DecalGunshot( &tr, iBulletType );
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BULLET_MONSTER_357:
|
|
||||||
UTIL_TraceAttack(pPlayer, pevAttacker, gSkillData.monDmg357, vecDir, &tr, DMG_BULLET);
|
|
||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
|
||||||
DecalGunshot( &tr, iBulletType );
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BULLET_NONE: // FIX
|
|
||||||
UTIL_TraceAttack(pPlayer, pevAttacker, 50, vecDir, &tr, DMG_CLUB);
|
|
||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
|
||||||
// only decal glass
|
|
||||||
if ( !FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != 0)
|
|
||||||
{
|
|
||||||
UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0,2) );
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BULLET_MONSTER_MP5:
|
||||||
|
UTIL_TraceAttack(pPlayer, pevAttacker, gSkillData.monDmgMP5, vecDir, &tr, DMG_BULLET);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_MONSTER_12MM:
|
||||||
|
UTIL_TraceAttack(pPlayer, pevAttacker, gSkillData.monDmg12MM, vecDir, &tr, DMG_BULLET);
|
||||||
|
if ( !tracer )
|
||||||
|
{
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_MONSTER_762:
|
||||||
|
UTIL_TraceAttack(pPlayer, pevAttacker, gSkillData.monDmg762, vecDir, &tr, DMG_BULLET);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_MONSTER_357:
|
||||||
|
UTIL_TraceAttack(pPlayer, pevAttacker, gSkillData.monDmg357, vecDir, &tr, DMG_BULLET);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_NONE: // FIX
|
||||||
|
UTIL_TraceAttack(pPlayer, pevAttacker, 50, vecDir, &tr, DMG_CLUB);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
// only decal glass
|
||||||
|
if ( !FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != 0)
|
||||||
|
{
|
||||||
|
UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0,2) );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tr.pHit->v.euser4 != NULL)
|
else if (tr.pHit->v.euser4 != NULL) // monstermod monster
|
||||||
{
|
{
|
||||||
CMBaseEntity *pMonster = GetClassPtr((CMBaseMonster *)VARS(tr.pHit));
|
CMBaseEntity *pMonster = GetClassPtr((CMBaseMonster *)VARS(tr.pHit));
|
||||||
|
|
||||||
if ( iDamage )
|
if ( iDamage )
|
||||||
@@ -1458,56 +1516,124 @@ void CMBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShootin
|
|||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
DecalGunshot( &tr, iBulletType );
|
DecalGunshot( &tr, iBulletType );
|
||||||
}
|
}
|
||||||
else switch(iBulletType)
|
else
|
||||||
{
|
{
|
||||||
default:
|
switch(iBulletType)
|
||||||
case BULLET_MONSTER_9MM:
|
|
||||||
pMonster->TraceAttack(pevAttacker, gSkillData.monDmg9MM, vecDir, &tr, DMG_BULLET);
|
|
||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
|
||||||
DecalGunshot( &tr, iBulletType );
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BULLET_MONSTER_MP5:
|
|
||||||
pMonster->TraceAttack(pevAttacker, gSkillData.monDmgMP5, vecDir, &tr, DMG_BULLET);
|
|
||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
|
||||||
DecalGunshot( &tr, iBulletType );
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BULLET_MONSTER_12MM:
|
|
||||||
pMonster->TraceAttack(pevAttacker, gSkillData.monDmg12MM, vecDir, &tr, DMG_BULLET);
|
|
||||||
if ( !tracer )
|
|
||||||
{
|
{
|
||||||
|
default:
|
||||||
|
case BULLET_MONSTER_9MM:
|
||||||
|
pMonster->TraceAttack(pevAttacker, gSkillData.monDmg9MM, vecDir, &tr, DMG_BULLET);
|
||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
DecalGunshot( &tr, iBulletType );
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_MONSTER_MP5:
|
||||||
|
pMonster->TraceAttack(pevAttacker, gSkillData.monDmgMP5, vecDir, &tr, DMG_BULLET);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_MONSTER_12MM:
|
||||||
|
pMonster->TraceAttack(pevAttacker, gSkillData.monDmg12MM, vecDir, &tr, DMG_BULLET);
|
||||||
|
if ( !tracer )
|
||||||
|
{
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_MONSTER_762:
|
||||||
|
pMonster->TraceAttack(pevAttacker, gSkillData.monDmg762, vecDir, &tr, DMG_BULLET);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_MONSTER_357:
|
||||||
|
pMonster->TraceAttack(pevAttacker, gSkillData.monDmg357, vecDir, &tr, DMG_BULLET);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_NONE: // FIX
|
||||||
|
pMonster->TraceAttack(pevAttacker, 50, vecDir, &tr, DMG_CLUB);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
// only decal glass
|
||||||
|
if ( !FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != 0)
|
||||||
|
{
|
||||||
|
UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0,2) );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
case BULLET_MONSTER_762:
|
else if (!UTIL_IsPlayer(tr.pHit)) // normal game monster
|
||||||
pMonster->TraceAttack(pevAttacker, gSkillData.monDmg762, vecDir, &tr, DMG_BULLET);
|
{
|
||||||
|
edict_t *pMonster = tr.pHit;
|
||||||
|
|
||||||
|
if ( iDamage )
|
||||||
|
{
|
||||||
|
UTIL_TraceAttack(pMonster, pevAttacker, iDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB) );
|
||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
DecalGunshot( &tr, iBulletType );
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
}
|
||||||
break;
|
else
|
||||||
|
{
|
||||||
case BULLET_MONSTER_357:
|
switch(iBulletType)
|
||||||
pMonster->TraceAttack(pevAttacker, gSkillData.monDmg357, vecDir, &tr, DMG_BULLET);
|
|
||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
|
||||||
DecalGunshot( &tr, iBulletType );
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BULLET_NONE: // FIX
|
|
||||||
pMonster->TraceAttack(pevAttacker, 50, vecDir, &tr, DMG_CLUB);
|
|
||||||
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
|
||||||
// only decal glass
|
|
||||||
if ( !FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != 0)
|
|
||||||
{
|
{
|
||||||
UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0,2) );
|
default:
|
||||||
}
|
case BULLET_MONSTER_9MM:
|
||||||
|
UTIL_TraceAttack(pMonster, pevAttacker, gSkillData.monDmg9MM, vecDir, &tr, DMG_BULLET);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BULLET_MONSTER_MP5:
|
||||||
|
UTIL_TraceAttack(pMonster, pevAttacker, gSkillData.monDmgMP5, vecDir, &tr, DMG_BULLET);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_MONSTER_12MM:
|
||||||
|
UTIL_TraceAttack(pMonster, pevAttacker, gSkillData.monDmg12MM, vecDir, &tr, DMG_BULLET);
|
||||||
|
if ( !tracer )
|
||||||
|
{
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_MONSTER_762:
|
||||||
|
UTIL_TraceAttack(pMonster, pevAttacker, gSkillData.monDmg762, vecDir, &tr, DMG_BULLET);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_MONSTER_357:
|
||||||
|
UTIL_TraceAttack(pMonster, pevAttacker, gSkillData.monDmg357, vecDir, &tr, DMG_BULLET);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
DecalGunshot( &tr, iBulletType );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BULLET_NONE: // FIX
|
||||||
|
UTIL_TraceAttack(pMonster, pevAttacker, 50, vecDir, &tr, DMG_CLUB);
|
||||||
|
TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
|
||||||
|
// only decal glass
|
||||||
|
if ( !FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != 0)
|
||||||
|
{
|
||||||
|
UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0,2) );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ void CMBaseMonster :: Look ( int iDistance )
|
|||||||
// DON'T let visibility information from last frame sit around!
|
// 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);
|
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
|
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];
|
pSightEnt = pList[i];
|
||||||
// !!!temporarily only considering other monsters and clients, don't see prisoners
|
// !!!temporarily only considering other monsters and clients, don't see prisoners
|
||||||
if ( pSightEnt != this->edict() &&
|
if ( pSightEnt != this->edict() && !FBitSet( pSightEnt->v.spawnflags, SF_MONSTER_PRISONER ) && pSightEnt->v.health > 0 )
|
||||||
!FBitSet( pSightEnt->v.spawnflags, SF_MONSTER_PRISONER ) &&
|
|
||||||
pSightEnt->v.health > 0 )
|
|
||||||
{
|
{
|
||||||
// is this a player AND are they alive?
|
// is this a player AND are they alive?
|
||||||
if (UTIL_IsPlayer(pSightEnt) && UTIL_IsAlive(pSightEnt))
|
if (UTIL_IsPlayer(pSightEnt) && UTIL_IsAlive(pSightEnt))
|
||||||
{
|
{
|
||||||
// the looker will want to consider this entity
|
// the looker will want to consider this entity
|
||||||
// don't check anything else about an entity that can't be seen.
|
// don't check anything else about an entity that can't be seen.
|
||||||
if ( UTIL_FInViewCone( pSightEnt, ENT(pev), m_flFieldOfView ) &&
|
if ( UTIL_FInViewCone( pSightEnt, ENT(pev), m_flFieldOfView ) && !FBitSet( pSightEnt->v.flags, FL_NOTARGET ) && UTIL_FVisible( pSightEnt, ENT(pev) ) )
|
||||||
!FBitSet( pSightEnt->v.flags, FL_NOTARGET ) && UTIL_FVisible( pSightEnt, ENT(pev) ) )
|
|
||||||
{
|
{
|
||||||
m_edictList[m_edictList_count] = pSightEnt;
|
m_edictList[m_edictList_count] = pSightEnt;
|
||||||
m_edictList_count++;
|
m_edictList_count++;
|
||||||
|
|
||||||
// if we see a client, remember that (mostly for scripted AI)
|
// if we see a client, remember that (mostly for scripted AI)
|
||||||
iSighted |= bits_COND_SEE_CLIENT;
|
iSighted |= bits_COND_SEE_CLIENT;
|
||||||
|
|
||||||
// is this monster NOT a scientist?
|
// is this monster NOT a scientist?
|
||||||
if (strcmp(STRING(pev->model), "models/scientist.mdl") != 0)
|
if (strcmp(STRING(pev->model), "models/scientist.mdl") != 0)
|
||||||
@@ -166,19 +163,19 @@ void CMBaseMonster :: Look ( int iDistance )
|
|||||||
iSighted |= bits_COND_SEE_ENEMY;
|
iSighted |= bits_COND_SEE_ENEMY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pSightEnt->v.euser4 != NULL)
|
else if (pSightEnt->v.euser4 != NULL)
|
||||||
{
|
{
|
||||||
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pSightEnt));
|
/* MonsterMod monster looking at another MonsterMod monster */
|
||||||
|
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pSightEnt));
|
||||||
|
|
||||||
// the looker will want to consider this entity
|
// 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.
|
// 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 ) &&
|
if ( IRelationship( pMonster ) != R_NO && UTIL_FInViewCone( pSightEnt, ENT(pev), m_flFieldOfView ) && !FBitSet( pSightEnt->v.flags, FL_NOTARGET ) && UTIL_FVisible( pSightEnt, ENT(pev) ) )
|
||||||
!FBitSet( pSightEnt->v.flags, FL_NOTARGET ) && UTIL_FVisible( pSightEnt, ENT(pev) ) )
|
|
||||||
{
|
{
|
||||||
m_edictList[m_edictList_count] = pSightEnt;
|
m_edictList[m_edictList_count] = pSightEnt;
|
||||||
m_edictList_count++;
|
m_edictList_count++;
|
||||||
|
|
||||||
if ( ENT(pMonster->pev) == m_hEnemy )
|
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 );
|
SetActivity( ACT_IDLE );
|
||||||
ChangeSchedule( GetScheduleOfType( SCHED_WAIT_TRIGGER ) );
|
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.
|
// relationship between two types of monster.
|
||||||
//=========================================================
|
//=========================================================
|
||||||
int CMBaseMonster::IRelationship ( CMBaseEntity *pTarget )
|
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] =
|
static int iEnemy[16][16] =
|
||||||
{ // NONE MACH PLYR HPASS HMIL AMIL APASS AMONST APREY APRED INSECT PLRALY PBWPN ABWPN RXPIT RXSHK
|
{ // 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 }
|
/*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 iNearest;
|
||||||
int iDist;
|
int iDist;
|
||||||
int iBestRelationship;
|
int iBestRelationship;
|
||||||
edict_t *pReturn;
|
edict_t *pReturn;
|
||||||
edict_t *pEnt;
|
edict_t *pEnt;
|
||||||
int edictList_index = 0;
|
int edictList_index = 0;
|
||||||
|
|
||||||
iNearest = 8192;// so first visible entity will become the closest.
|
iNearest = 8192;// so first visible entity will become the closest.
|
||||||
|
|
||||||
iBestRelationship = R_NO;
|
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) )
|
if ( UTIL_IsPlayer(pEnt) )
|
||||||
{
|
{
|
||||||
// it's a player...
|
// it's a player...
|
||||||
iDist = ( pEnt->v.origin - pev->origin ).Length();
|
iDist = ( pEnt->v.origin - pev->origin ).Length();
|
||||||
|
|
||||||
if ( iDist <= iNearest )
|
if ( iDist <= iNearest )
|
||||||
{
|
{
|
||||||
iNearest = iDist;
|
iNearest = iDist;
|
||||||
iBestRelationship = R_NM; // player is always nemsis
|
iBestRelationship = R_NM; // player is always nemesis
|
||||||
pReturn = pEnt;
|
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));
|
CMBaseMonster *pNextEnt = GetClassPtr((CMBaseMonster *)VARS(pEnt));
|
||||||
if ( pNextEnt->IsAlive() )
|
if ( pNextEnt->IsAlive() )
|
||||||
{
|
{
|
||||||
if ( IRelationship( pNextEnt) > iBestRelationship )
|
if ( IRelationship( pNextEnt ) > iBestRelationship )
|
||||||
{
|
{
|
||||||
// this entity is disliked MORE than the entity that we
|
// this entity is disliked MORE than the entity that we
|
||||||
// currently think is the best visible enemy. No need to do
|
// 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();
|
iNearest = ( pNextEnt->pev->origin - pev->origin ).Length();
|
||||||
pReturn = pEnt;
|
pReturn = pEnt;
|
||||||
}
|
}
|
||||||
else if ( IRelationship( pNextEnt) == iBestRelationship )
|
else if ( IRelationship( pNextEnt ) == iBestRelationship )
|
||||||
{
|
{
|
||||||
// this entity is disliked just as much as the entity that
|
// this entity is disliked just as much as the entity that
|
||||||
// we currently think is the best visible enemy, so we only
|
// we currently think is the best visible enemy, so we only
|
||||||
// get mad at it if it is closer.
|
// get mad at it if it is closer.
|
||||||
iDist = ( pNextEnt->pev->origin - pev->origin ).Length();
|
iDist = ( pNextEnt->pev->origin - pev->origin ).Length();
|
||||||
|
|
||||||
if ( iDist <= iNearest )
|
if ( iDist <= iNearest )
|
||||||
{
|
{
|
||||||
iNearest = iDist;
|
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;
|
return pReturn;
|
||||||
|
|||||||
@@ -1807,7 +1807,7 @@ int UTIL_TakeDamage( edict_t *pEdict, entvars_t *pevInflictor, entvars_t *pevAtt
|
|||||||
WRITE_COORD( pevInflictor->origin.z );
|
WRITE_COORD( pevInflictor->origin.z );
|
||||||
MESSAGE_END();
|
MESSAGE_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
return fTookDamage;
|
return fTookDamage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1888,7 +1888,7 @@ void UTIL_TraceAttack( edict_t *pEdict, entvars_t *pevAttacker, float flDamage,
|
|||||||
{
|
{
|
||||||
AddMultiDamage( pevAttacker, pEdict, flDamage, bitsDamageType );
|
AddMultiDamage( pevAttacker, pEdict, flDamage, bitsDamageType );
|
||||||
|
|
||||||
SpawnBlood(ptr->vecEndPos, BLOOD_COLOR_RED, flDamage);// a little surface blood.
|
SpawnBlood(ptr->vecEndPos, BLOOD_COLOR_RED, flDamage);// a little surface blood.
|
||||||
|
|
||||||
UTIL_TraceBleed( pEdict, flDamage, vecDir, ptr, bitsDamageType );
|
UTIL_TraceBleed( pEdict, flDamage, vecDir, ptr, bitsDamageType );
|
||||||
}
|
}
|
||||||
@@ -1968,3 +1968,11 @@ bool UTIL_IsBSPModel( edict_t *pent )
|
|||||||
{
|
{
|
||||||
return (pent->v.solid == SOLID_BSP || pent->v.movetype == MOVETYPE_PUSHSTEP);
|
return (pent->v.solid == SOLID_BSP || pent->v.movetype == MOVETYPE_PUSHSTEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UTIL_TakeDamageExternal( edict_t *pEdict, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
|
||||||
|
{
|
||||||
|
// Tell AMXX to call TakeDamage for us.
|
||||||
|
char extCmd[64];
|
||||||
|
sprintf( extCmd, "monster_hurt_entity %i %i %i %f %i\n", ENTINDEX( pEdict ), ENTINDEX( ENT( pevInflictor ) ), ENTINDEX( ENT( pevAttacker ) ), flDamage, bitsDamageType );
|
||||||
|
SERVER_COMMAND( extCmd );
|
||||||
|
}
|
||||||
|
|||||||
@@ -538,3 +538,4 @@ Vector UTIL_Center(edict_t *pEdict);
|
|||||||
edict_t *UTIL_GetNextTarget( edict_t *pEntity );
|
edict_t *UTIL_GetNextTarget( edict_t *pEntity );
|
||||||
edict_t *UTIL_FindNearestPlayer(edict_t *pEdict, float m_flFieldOfView);
|
edict_t *UTIL_FindNearestPlayer(edict_t *pEdict, float m_flFieldOfView);
|
||||||
bool UTIL_IsBSPModel( edict_t *pent );
|
bool UTIL_IsBSPModel( edict_t *pent );
|
||||||
|
void UTIL_TakeDamageExternal( edict_t *pEdict, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ void ApplyMultiDamage(entvars_t *pevInflictor, entvars_t *pevAttacker )
|
|||||||
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(gMultiDamage.pEntity));
|
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(gMultiDamage.pEntity));
|
||||||
pMonster->TakeDamage(pevInflictor, pevAttacker, gMultiDamage.amount, gMultiDamage.type );
|
pMonster->TakeDamage(pevInflictor, pevAttacker, gMultiDamage.amount, gMultiDamage.type );
|
||||||
}
|
}
|
||||||
|
else if (!UTIL_IsPlayer(gMultiDamage.pEntity))
|
||||||
|
UTIL_TakeDamageExternal(gMultiDamage.pEntity, pevInflictor, pevAttacker, gMultiDamage.amount, gMultiDamage.type );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user