mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-04-16 14:32:31 +03:00
Grenade/alt-fire item dropping for metrocops and player companions
This commit is contained in:
parent
24e6ab3767
commit
85097e119e
@ -230,7 +230,9 @@ DEFINE_INPUTFUNC( FIELD_STRING, "SetPoliceGoal", InputSetPoliceGoal ),
|
|||||||
DEFINE_AIGRENADE_DATADESC()
|
DEFINE_AIGRENADE_DATADESC()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAPBASE
|
||||||
DEFINE_FIELD( m_iLastAnimEventHandled, FIELD_INTEGER ),
|
DEFINE_FIELD( m_iLastAnimEventHandled, FIELD_INTEGER ),
|
||||||
|
#endif
|
||||||
DEFINE_FIELD( m_fIsElite, FIELD_BOOLEAN ),
|
DEFINE_FIELD( m_fIsElite, FIELD_BOOLEAN ),
|
||||||
#ifndef MAPBASE
|
#ifndef MAPBASE
|
||||||
DEFINE_FIELD( m_vecAltFireTarget, FIELD_VECTOR ),
|
DEFINE_FIELD( m_vecAltFireTarget, FIELD_VECTOR ),
|
||||||
@ -3687,7 +3689,9 @@ void CNPC_Combine::SetActivity( Activity NewActivity )
|
|||||||
{
|
{
|
||||||
BaseClass::SetActivity( NewActivity );
|
BaseClass::SetActivity( NewActivity );
|
||||||
|
|
||||||
|
#ifndef MAPBASE // CAI_GrenadeUser
|
||||||
m_iLastAnimEventHandled = -1;
|
m_iLastAnimEventHandled = -1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -59,7 +59,7 @@ public:
|
|||||||
// Create components
|
// Create components
|
||||||
virtual bool CreateComponents();
|
virtual bool CreateComponents();
|
||||||
|
|
||||||
#ifndef MAPBASE
|
#ifndef MAPBASE // CAI_GrenadeUser
|
||||||
bool CanThrowGrenade( const Vector &vecTarget );
|
bool CanThrowGrenade( const Vector &vecTarget );
|
||||||
bool CheckCanThrowGrenade( const Vector &vecTarget );
|
bool CheckCanThrowGrenade( const Vector &vecTarget );
|
||||||
#endif
|
#endif
|
||||||
@ -118,7 +118,7 @@ public:
|
|||||||
const char* GetGrenadeAttachment() { return "lefthand"; }
|
const char* GetGrenadeAttachment() { return "lefthand"; }
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
#ifndef MAPBASE
|
#ifndef MAPBASE // CAI_GrenadeUser
|
||||||
void DelayAltFireAttack( float flDelay );
|
void DelayAltFireAttack( float flDelay );
|
||||||
void DelaySquadAltFireAttack( float flDelay );
|
void DelaySquadAltFireAttack( float flDelay );
|
||||||
#endif
|
#endif
|
||||||
@ -131,7 +131,7 @@ public:
|
|||||||
Vector EyeOffset( Activity nActivity );
|
Vector EyeOffset( Activity nActivity );
|
||||||
Vector EyePosition( void );
|
Vector EyePosition( void );
|
||||||
Vector BodyTarget( const Vector &posSrc, bool bNoisy = true );
|
Vector BodyTarget( const Vector &posSrc, bool bNoisy = true );
|
||||||
#ifndef MAPBASE
|
#ifndef MAPBASE // CAI_GrenadeUser
|
||||||
Vector GetAltFireTarget();
|
Vector GetAltFireTarget();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -320,7 +320,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
int m_nKickDamage;
|
int m_nKickDamage;
|
||||||
#ifndef MAPBASE
|
#ifndef MAPBASE // CAI_GrenadeUser
|
||||||
Vector m_vecTossVelocity;
|
Vector m_vecTossVelocity;
|
||||||
EHANDLE m_hForcedGrenadeTarget;
|
EHANDLE m_hForcedGrenadeTarget;
|
||||||
#else
|
#else
|
||||||
@ -334,12 +334,12 @@ private:
|
|||||||
// Time Variables
|
// Time Variables
|
||||||
float m_flNextPainSoundTime;
|
float m_flNextPainSoundTime;
|
||||||
float m_flNextAlertSoundTime;
|
float m_flNextAlertSoundTime;
|
||||||
#ifndef MAPBASE
|
#ifndef MAPBASE // CAI_GrenadeUser
|
||||||
float m_flNextGrenadeCheck;
|
float m_flNextGrenadeCheck;
|
||||||
#endif
|
#endif
|
||||||
float m_flNextLostSoundTime;
|
float m_flNextLostSoundTime;
|
||||||
float m_flAlertPatrolTime; // When to stop doing alert patrol
|
float m_flAlertPatrolTime; // When to stop doing alert patrol
|
||||||
#ifndef MAPBASE
|
#ifndef MAPBASE // CAI_GrenadeUser
|
||||||
float m_flNextAltFireTime; // Elites only. Next time to begin considering alt-fire attack.
|
float m_flNextAltFireTime; // Elites only. Next time to begin considering alt-fire attack.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -351,7 +351,7 @@ private:
|
|||||||
CAI_Sentence< CNPC_Combine > m_Sentences;
|
CAI_Sentence< CNPC_Combine > m_Sentences;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MAPBASE
|
#ifndef MAPBASE // CAI_GrenadeUser
|
||||||
int m_iNumGrenades;
|
int m_iNumGrenades;
|
||||||
#endif
|
#endif
|
||||||
CAI_AssaultBehavior m_AssaultBehavior;
|
CAI_AssaultBehavior m_AssaultBehavior;
|
||||||
@ -365,9 +365,11 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
#ifndef MAPBASE // CAI_GrenadeUser
|
||||||
int m_iLastAnimEventHandled;
|
int m_iLastAnimEventHandled;
|
||||||
|
#endif
|
||||||
bool m_fIsElite;
|
bool m_fIsElite;
|
||||||
#ifndef MAPBASE
|
#ifndef MAPBASE // CAI_GrenadeUser
|
||||||
Vector m_vecAltFireTarget;
|
Vector m_vecAltFireTarget;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -261,6 +261,7 @@ BEGIN_DATADESC( CNPC_MetroPolice )
|
|||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
DEFINE_AIGRENADE_DATADESC()
|
DEFINE_AIGRENADE_DATADESC()
|
||||||
DEFINE_INPUT( m_iGrenadeCapabilities, FIELD_INTEGER, "SetGrenadeCapabilities" ),
|
DEFINE_INPUT( m_iGrenadeCapabilities, FIELD_INTEGER, "SetGrenadeCapabilities" ),
|
||||||
|
DEFINE_INPUT( m_iGrenadeDropCapabilities, FIELD_INTEGER, "SetGrenadeDropCapabilities" ),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
@ -517,6 +518,11 @@ CNPC_MetroPolice::CNPC_MetroPolice()
|
|||||||
{
|
{
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
m_iGrenadeCapabilities = GRENCAP_GRENADE;
|
m_iGrenadeCapabilities = GRENCAP_GRENADE;
|
||||||
|
|
||||||
|
if (ai_grenade_always_drop.GetBool())
|
||||||
|
{
|
||||||
|
m_iGrenadeDropCapabilities = (eGrenadeDropCapabilities)(GRENDROPCAP_GRENADE | GRENDROPCAP_ALTFIRE | GRENDROPCAP_INTERRUPTED);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3681,6 +3687,11 @@ void CNPC_MetroPolice::Event_Killed( const CTakeDamageInfo &info )
|
|||||||
DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );
|
DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );
|
||||||
pHL2GameRules->NPC_DroppedHealth();
|
pHL2GameRules->NPC_DroppedHealth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Drop grenades if we should
|
||||||
|
DropGrenadeItemsOnDeath( info, pPlayer );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseClass::Event_Killed( info );
|
BaseClass::Event_Killed( info );
|
||||||
|
@ -67,8 +67,12 @@ public:
|
|||||||
|
|
||||||
const char* GetGrenadeAttachment() { return "LHand"; }
|
const char* GetGrenadeAttachment() { return "LHand"; }
|
||||||
|
|
||||||
virtual bool IsAltFireCapable() { return (m_iGrenadeCapabilities & GRENCAP_ALTFIRE) != 0; }
|
virtual bool IsAltFireCapable() { return (m_iGrenadeCapabilities & GRENCAP_ALTFIRE) != 0 && BaseClass::IsAltFireCapable(); }
|
||||||
virtual bool IsGrenadeCapable() { return (m_iGrenadeCapabilities & GRENCAP_GRENADE) != 0; }
|
virtual bool IsGrenadeCapable() { return (m_iGrenadeCapabilities & GRENCAP_GRENADE) != 0; }
|
||||||
|
|
||||||
|
virtual bool ShouldDropGrenades() { return (m_iGrenadeDropCapabilities & GRENDROPCAP_GRENADE) != 0 && BaseClass::ShouldDropGrenades(); }
|
||||||
|
virtual bool ShouldDropInterruptedGrenades() { return (m_iGrenadeDropCapabilities & GRENDROPCAP_INTERRUPTED) != 0 && BaseClass::ShouldDropInterruptedGrenades(); }
|
||||||
|
virtual bool ShouldDropAltFire() { return (m_iGrenadeDropCapabilities & GRENDROPCAP_ALTFIRE) != 0 && BaseClass::ShouldDropAltFire(); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Vector EyeDirection3D( void ) { return CAI_BaseHumanoid::EyeDirection3D(); } // cops don't have eyes
|
Vector EyeDirection3D( void ) { return CAI_BaseHumanoid::EyeDirection3D(); } // cops don't have eyes
|
||||||
@ -520,6 +524,7 @@ private:
|
|||||||
|
|
||||||
// Determines whether this NPC is allowed to use grenades or alt-fire stuff.
|
// Determines whether this NPC is allowed to use grenades or alt-fire stuff.
|
||||||
eGrenadeCapabilities m_iGrenadeCapabilities;
|
eGrenadeCapabilities m_iGrenadeCapabilities;
|
||||||
|
eGrenadeDropCapabilities m_iGrenadeDropCapabilities;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AIHANDLE m_hManhack;
|
AIHANDLE m_hManhack;
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
#include "mapbase/GlobalStrings.h"
|
#include "mapbase/GlobalStrings.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
|
#include "vehicle_base.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ConVar ai_debug_readiness("ai_debug_readiness", "0" );
|
ConVar ai_debug_readiness("ai_debug_readiness", "0" );
|
||||||
@ -148,6 +149,7 @@ BEGIN_DATADESC( CNPC_PlayerCompanion )
|
|||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
DEFINE_AIGRENADE_DATADESC()
|
DEFINE_AIGRENADE_DATADESC()
|
||||||
DEFINE_INPUT( m_iGrenadeCapabilities, FIELD_INTEGER, "SetGrenadeCapabilities" ),
|
DEFINE_INPUT( m_iGrenadeCapabilities, FIELD_INTEGER, "SetGrenadeCapabilities" ),
|
||||||
|
DEFINE_INPUT( m_iGrenadeDropCapabilities, FIELD_INTEGER, "SetGrenadeDropCapabilities" ),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
@ -175,6 +177,19 @@ string_t CNPC_PlayerCompanion::gm_iszAR2Classname;
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CNPC_PlayerCompanion::CNPC_PlayerCompanion()
|
||||||
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (ai_grenade_always_drop.GetBool())
|
||||||
|
{
|
||||||
|
m_iGrenadeDropCapabilities = (eGrenadeDropCapabilities)(GRENDROPCAP_GRENADE | GRENDROPCAP_ALTFIRE | GRENDROPCAP_INTERRUPTED);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CNPC_PlayerCompanion::CreateBehaviors()
|
bool CNPC_PlayerCompanion::CreateBehaviors()
|
||||||
{
|
{
|
||||||
#ifdef HL2_EPISODIC
|
#ifdef HL2_EPISODIC
|
||||||
@ -4179,6 +4194,38 @@ void CNPC_PlayerCompanion::OnPlayerKilledOther( CBaseEntity *pVictim, const CTak
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CNPC_PlayerCompanion::Event_Killed( const CTakeDamageInfo &info )
|
||||||
|
{
|
||||||
|
// For now, allied player companions are set to always drop grenades and other items
|
||||||
|
// even if the player did not kill them
|
||||||
|
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
|
||||||
|
if (!IsPlayerAlly( pPlayer ))
|
||||||
|
{
|
||||||
|
pPlayer = ToBasePlayer( info.GetAttacker() );
|
||||||
|
|
||||||
|
// See if there's a player in a vehicle instead (from CNPC_CombineS)
|
||||||
|
if ( !pPlayer )
|
||||||
|
{
|
||||||
|
CPropVehicleDriveable *pVehicle = dynamic_cast<CPropVehicleDriveable *>( info.GetAttacker() ) ;
|
||||||
|
if ( pVehicle && pVehicle->GetDriver() && pVehicle->GetDriver()->IsPlayer() )
|
||||||
|
{
|
||||||
|
pPlayer = assert_cast<CBasePlayer *>( pVehicle->GetDriver() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pPlayer != NULL )
|
||||||
|
{
|
||||||
|
// Drop grenades if we should
|
||||||
|
DropGrenadeItemsOnDeath( info, pPlayer );
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseClass::Event_Killed( info );
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CNPC_PlayerCompanion::Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info )
|
void CNPC_PlayerCompanion::Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info )
|
||||||
|
@ -108,8 +108,10 @@ class CNPC_PlayerCompanion : public CAI_PlayerAlly
|
|||||||
{
|
{
|
||||||
DECLARE_CLASS( CNPC_PlayerCompanion, CAI_PlayerAlly );
|
DECLARE_CLASS( CNPC_PlayerCompanion, CAI_PlayerAlly );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
CNPC_PlayerCompanion();
|
||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
bool CreateBehaviors();
|
bool CreateBehaviors();
|
||||||
void Precache();
|
void Precache();
|
||||||
@ -237,6 +239,7 @@ public:
|
|||||||
// This is just here to overwrite ai_playerally's TLK_ENEMY_DEAD
|
// This is just here to overwrite ai_playerally's TLK_ENEMY_DEAD
|
||||||
virtual void OnKilledNPC(CBaseCombatCharacter *pKilled) {}
|
virtual void OnKilledNPC(CBaseCombatCharacter *pKilled) {}
|
||||||
|
|
||||||
|
virtual void Event_Killed( const CTakeDamageInfo &info );
|
||||||
virtual void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info );
|
virtual void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info );
|
||||||
virtual void DoCustomCombatAI( void );
|
virtual void DoCustomCombatAI( void );
|
||||||
#endif
|
#endif
|
||||||
@ -337,13 +340,18 @@ public:
|
|||||||
bool AllowReadinessValueChange( void );
|
bool AllowReadinessValueChange( void );
|
||||||
|
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
virtual bool IsAltFireCapable() { return (m_iGrenadeCapabilities & GRENCAP_ALTFIRE) != 0; }
|
virtual bool IsAltFireCapable() { return (m_iGrenadeCapabilities & GRENCAP_ALTFIRE) != 0 && BaseClass::IsAltFireCapable(); }
|
||||||
virtual bool IsGrenadeCapable() { return (m_iGrenadeCapabilities & GRENCAP_GRENADE) != 0; }
|
virtual bool IsGrenadeCapable() { return (m_iGrenadeCapabilities & GRENCAP_GRENADE) != 0; }
|
||||||
|
|
||||||
|
virtual bool ShouldDropGrenades() { return (m_iGrenadeDropCapabilities & GRENDROPCAP_GRENADE) != 0 && BaseClass::ShouldDropGrenades(); }
|
||||||
|
virtual bool ShouldDropInterruptedGrenades() { return (m_iGrenadeDropCapabilities & GRENDROPCAP_INTERRUPTED) != 0 && BaseClass::ShouldDropInterruptedGrenades(); }
|
||||||
|
virtual bool ShouldDropAltFire() { return (m_iGrenadeDropCapabilities & GRENDROPCAP_ALTFIRE) != 0 && BaseClass::ShouldDropAltFire(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Determines whether this NPC is allowed to use grenades or alt-fire stuff.
|
// Determines whether this NPC is allowed to use grenades or alt-fire stuff.
|
||||||
eGrenadeCapabilities m_iGrenadeCapabilities;
|
eGrenadeCapabilities m_iGrenadeCapabilities;
|
||||||
|
eGrenadeDropCapabilities m_iGrenadeDropCapabilities;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -11,3 +11,5 @@
|
|||||||
|
|
||||||
int COMBINE_AE_BEGIN_ALTFIRE;
|
int COMBINE_AE_BEGIN_ALTFIRE;
|
||||||
int COMBINE_AE_ALTFIRE;
|
int COMBINE_AE_ALTFIRE;
|
||||||
|
|
||||||
|
ConVar ai_grenade_always_drop( "ai_grenade_always_drop", "0", FCVAR_NONE, "Causes non-Combine grenade user NPCs to be allowed to drop grenades, alt-fire items, etc. *IF* the keyvalue has not already been set in Hammer. This is useful for debugging purposes or if a mod which was developed before this feature was introduced wants its NPCs to drop grenades and beyond without recompiling all of the maps." );
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
#include "basegrenade_shared.h"
|
#include "basegrenade_shared.h"
|
||||||
#include "ai_squad.h"
|
#include "ai_squad.h"
|
||||||
#include "GlobalStrings.h"
|
#include "GlobalStrings.h"
|
||||||
|
#include "gameweaponmanager.h"
|
||||||
|
#include "hl2_gamerules.h"
|
||||||
|
#include "weapon_physcannon.h"
|
||||||
|
|
||||||
#define COMBINE_AE_GREN_TOSS ( 7 )
|
#define COMBINE_AE_GREN_TOSS ( 7 )
|
||||||
|
|
||||||
@ -36,6 +39,7 @@
|
|||||||
DEFINE_FIELD( m_flNextAltFireTime, FIELD_TIME ), \
|
DEFINE_FIELD( m_flNextAltFireTime, FIELD_TIME ), \
|
||||||
DEFINE_FIELD( m_vecAltFireTarget, FIELD_VECTOR ), \
|
DEFINE_FIELD( m_vecAltFireTarget, FIELD_VECTOR ), \
|
||||||
DEFINE_FIELD( m_vecTossVelocity, FIELD_VECTOR ), \
|
DEFINE_FIELD( m_vecTossVelocity, FIELD_VECTOR ), \
|
||||||
|
DEFINE_FIELD( m_iLastAnimEventHandled, FIELD_INTEGER ), \
|
||||||
DEFINE_INPUTFUNC( FIELD_STRING, "ThrowGrenadeAtTarget", InputThrowGrenadeAtTarget ), \
|
DEFINE_INPUTFUNC( FIELD_STRING, "ThrowGrenadeAtTarget", InputThrowGrenadeAtTarget ), \
|
||||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetGrenades", InputSetGrenades ), \
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetGrenades", InputSetGrenades ), \
|
||||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "AddGrenades", InputAddGrenades ), \
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "AddGrenades", InputAddGrenades ), \
|
||||||
@ -61,12 +65,22 @@
|
|||||||
extern int COMBINE_AE_BEGIN_ALTFIRE;
|
extern int COMBINE_AE_BEGIN_ALTFIRE;
|
||||||
extern int COMBINE_AE_ALTFIRE;
|
extern int COMBINE_AE_ALTFIRE;
|
||||||
|
|
||||||
|
extern ConVar ai_grenade_always_drop;
|
||||||
|
|
||||||
enum eGrenadeCapabilities
|
enum eGrenadeCapabilities
|
||||||
{
|
{
|
||||||
GRENCAP_GRENADE = (1 << 0),
|
GRENCAP_GRENADE = (1 << 0),
|
||||||
GRENCAP_ALTFIRE = (1 << 1),
|
GRENCAP_ALTFIRE = (1 << 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// What grenade/item types NPCs are capable of dropping
|
||||||
|
enum eGrenadeDropCapabilities
|
||||||
|
{
|
||||||
|
GRENDROPCAP_GRENADE = (1 << 0),
|
||||||
|
GRENDROPCAP_ALTFIRE = (1 << 1),
|
||||||
|
GRENDROPCAP_INTERRUPTED = (1 << 2), // Drops grenades when interrupted mid-animation
|
||||||
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Other classes can use this and access some CAI_GrenadeUser functions.
|
// Other classes can use this and access some CAI_GrenadeUser functions.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -102,7 +116,8 @@ public:
|
|||||||
m_OnOutOfGrenades.Set( pLastGrenade, pLastGrenade, this );
|
m_OnOutOfGrenades.Set( pLastGrenade, pLastGrenade, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool IsAltFireCapable() { return false; }
|
// Use secondary ammo as a way of checking if this is a weapon which can be alt-fired (e.g. AR2 or SMG)
|
||||||
|
virtual bool IsAltFireCapable() { return (GetActiveWeapon() && GetActiveWeapon()->UsesSecondaryAmmo()); }
|
||||||
virtual bool IsGrenadeCapable() { return true; }
|
virtual bool IsGrenadeCapable() { return true; }
|
||||||
inline bool HasGrenades() { return m_iNumGrenades > 0; }
|
inline bool HasGrenades() { return m_iNumGrenades > 0; }
|
||||||
|
|
||||||
@ -113,6 +128,7 @@ public:
|
|||||||
virtual void DelayGrenadeCheck( float delay ) { m_flNextGrenadeCheck = gpGlobals->curtime + delay; }
|
virtual void DelayGrenadeCheck( float delay ) { m_flNextGrenadeCheck = gpGlobals->curtime + delay; }
|
||||||
|
|
||||||
void HandleAnimEvent( animevent_t *pEvent );
|
void HandleAnimEvent( animevent_t *pEvent );
|
||||||
|
void SetActivity( Activity NewActivity );
|
||||||
|
|
||||||
// Soldiers use "lefthand", cops use "LHand", and citizens use "anim_attachment_LH"
|
// Soldiers use "lefthand", cops use "LHand", and citizens use "anim_attachment_LH"
|
||||||
virtual const char* GetGrenadeAttachment() { return "anim_attachment_LH"; }
|
virtual const char* GetGrenadeAttachment() { return "anim_attachment_LH"; }
|
||||||
@ -131,6 +147,12 @@ public:
|
|||||||
// For OnThrowGrenade + point_entity_replace, see grenade_frag.cpp
|
// For OnThrowGrenade + point_entity_replace, see grenade_frag.cpp
|
||||||
bool UsingOnThrowGrenade() { return m_OnThrowGrenade.NumberOfElements() > 0; }
|
bool UsingOnThrowGrenade() { return m_OnThrowGrenade.NumberOfElements() > 0; }
|
||||||
|
|
||||||
|
// For dropping grenades and beyond
|
||||||
|
void DropGrenadeItemsOnDeath( const CTakeDamageInfo &info, CBasePlayer *pPlayer );
|
||||||
|
virtual bool ShouldDropGrenades() { return HasGrenades(); }
|
||||||
|
virtual bool ShouldDropInterruptedGrenades() { return true; }
|
||||||
|
virtual bool ShouldDropAltFire() { return HasGrenades(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void StartTask_FaceAltFireTarget( const Task_t *pTask );
|
void StartTask_FaceAltFireTarget( const Task_t *pTask );
|
||||||
@ -151,6 +173,9 @@ protected: // We can't have any private saved variables because only derived cla
|
|||||||
Vector m_vecAltFireTarget;
|
Vector m_vecAltFireTarget;
|
||||||
Vector m_vecTossVelocity;
|
Vector m_vecTossVelocity;
|
||||||
|
|
||||||
|
// CNPC_Combine port for determining if we tossed a grenade
|
||||||
|
int m_iLastAnimEventHandled;
|
||||||
|
|
||||||
COutputEHANDLE m_OnThrowGrenade;
|
COutputEHANDLE m_OnThrowGrenade;
|
||||||
COutputEHANDLE m_OnOutOfGrenades;
|
COutputEHANDLE m_OnOutOfGrenades;
|
||||||
};
|
};
|
||||||
@ -166,6 +191,8 @@ void CAI_GrenadeUser<BASE_NPC>::HandleAnimEvent( animevent_t *pEvent )
|
|||||||
if (this->GetActiveWeapon())
|
if (this->GetActiveWeapon())
|
||||||
this->GetActiveWeapon()->WeaponSound( SPECIAL1 );
|
this->GetActiveWeapon()->WeaponSound( SPECIAL1 );
|
||||||
|
|
||||||
|
m_iLastAnimEventHandled = pEvent->event;
|
||||||
|
|
||||||
//SpeakIfAllowed( TLK_CMB_THROWGRENADE, "altfire:1" );
|
//SpeakIfAllowed( TLK_CMB_THROWGRENADE, "altfire:1" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -185,6 +212,8 @@ void CAI_GrenadeUser<BASE_NPC>::HandleAnimEvent( animevent_t *pEvent )
|
|||||||
|
|
||||||
AddGrenades(-1);
|
AddGrenades(-1);
|
||||||
|
|
||||||
|
m_iLastAnimEventHandled = pEvent->event;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,12 +250,25 @@ void CAI_GrenadeUser<BASE_NPC>::HandleAnimEvent( animevent_t *pEvent )
|
|||||||
|
|
||||||
// wait six seconds before even looking again to see if a grenade can be thrown.
|
// wait six seconds before even looking again to see if a grenade can be thrown.
|
||||||
m_flNextGrenadeCheck = gpGlobals->curtime + 6;
|
m_flNextGrenadeCheck = gpGlobals->curtime + 6;
|
||||||
|
|
||||||
|
m_iLastAnimEventHandled = pEvent->event;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseClass::HandleAnimEvent( pEvent );
|
BaseClass::HandleAnimEvent( pEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <class BASE_NPC>
|
||||||
|
void CAI_GrenadeUser<BASE_NPC>::SetActivity( Activity NewActivity )
|
||||||
|
{
|
||||||
|
BaseClass::SetActivity( NewActivity );
|
||||||
|
|
||||||
|
m_iLastAnimEventHandled = -1;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Force the combine soldier to throw a grenade at the target
|
// Purpose: Force the combine soldier to throw a grenade at the target
|
||||||
// If I'm a combine elite, fire my combine ball at the target instead.
|
// If I'm a combine elite, fire my combine ball at the target instead.
|
||||||
@ -534,6 +576,105 @@ void CAI_GrenadeUser<BASE_NPC>::ClearAttackConditions()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Drops grenades and alt-fire items on death. Based on code from npc_combines.cpp and npc_combine.cpp
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <class BASE_NPC>
|
||||||
|
void CAI_GrenadeUser<BASE_NPC>::DropGrenadeItemsOnDeath( const CTakeDamageInfo &info, CBasePlayer *pPlayer )
|
||||||
|
{
|
||||||
|
// Elites drop alt-fire ammo, so long as they weren't killed by dissolving.
|
||||||
|
if( IsAltFireCapable() && ShouldDropAltFire() )
|
||||||
|
{
|
||||||
|
CBaseEntity *pItem;
|
||||||
|
if (this->GetActiveWeapon() && FClassnameIs( this->GetActiveWeapon(), "weapon_smg1" ))
|
||||||
|
pItem = this->DropItem( "item_ammo_smg1_grenade", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );
|
||||||
|
else
|
||||||
|
pItem = this->DropItem( "item_ammo_ar2_altfire", WorldSpaceCenter() + RandomVector( -4, 4 ), RandomAngle( 0, 360 ) );
|
||||||
|
|
||||||
|
if ( pItem )
|
||||||
|
{
|
||||||
|
IPhysicsObject *pObj = pItem->VPhysicsGetObject();
|
||||||
|
|
||||||
|
if ( pObj )
|
||||||
|
{
|
||||||
|
Vector vel = RandomVector( -64.0f, 64.0f );
|
||||||
|
AngularImpulse angImp = RandomAngularImpulse( -300.0f, 300.0f );
|
||||||
|
|
||||||
|
vel[2] = 0.0f;
|
||||||
|
pObj->AddVelocity( &vel, &angImp );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( info.GetDamageType() & DMG_DISSOLVE )
|
||||||
|
{
|
||||||
|
CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating*>(pItem);
|
||||||
|
|
||||||
|
if( pAnimating )
|
||||||
|
{
|
||||||
|
pAnimating->Dissolve( NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WeaponManager_AddManaged( pItem );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( IsGrenadeCapable() )
|
||||||
|
{
|
||||||
|
if ( ShouldDropGrenades() )
|
||||||
|
{
|
||||||
|
CHalfLife2 *pHL2GameRules = static_cast<CHalfLife2 *>(g_pGameRules);
|
||||||
|
|
||||||
|
// Attempt to drop a grenade
|
||||||
|
if ( pHL2GameRules->NPC_ShouldDropGrenade( pPlayer ) )
|
||||||
|
{
|
||||||
|
this->DropItem( "weapon_frag", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );
|
||||||
|
pHL2GameRules->NPC_DroppedGrenade();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if I was killed before I could finish throwing my grenade, drop
|
||||||
|
// a grenade item that the player can retrieve.
|
||||||
|
if (GetActivity() == ACT_RANGE_ATTACK2 && ShouldDropInterruptedGrenades())
|
||||||
|
{
|
||||||
|
if( m_iLastAnimEventHandled != COMBINE_AE_GREN_TOSS )
|
||||||
|
{
|
||||||
|
// Drop the grenade as an item.
|
||||||
|
Vector vecStart;
|
||||||
|
this->GetAttachment( GetGrenadeAttachment(), vecStart );
|
||||||
|
|
||||||
|
CBaseEntity *pItem = DropItem( "weapon_frag", vecStart, RandomAngle(0,360) );
|
||||||
|
|
||||||
|
if ( pItem )
|
||||||
|
{
|
||||||
|
IPhysicsObject *pObj = pItem->VPhysicsGetObject();
|
||||||
|
|
||||||
|
if ( pObj )
|
||||||
|
{
|
||||||
|
Vector vel;
|
||||||
|
vel.x = random->RandomFloat( -100.0f, 100.0f );
|
||||||
|
vel.y = random->RandomFloat( -100.0f, 100.0f );
|
||||||
|
vel.z = random->RandomFloat( 800.0f, 1200.0f );
|
||||||
|
AngularImpulse angImp = RandomAngularImpulse( -300.0f, 300.0f );
|
||||||
|
|
||||||
|
vel[2] = 0.0f;
|
||||||
|
pObj->AddVelocity( &vel, &angImp );
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the Citadel we need to dissolve this
|
||||||
|
if ( PlayerHasMegaPhysCannon() && GlobalEntity_GetCounter("super_phys_gun") != 1 )
|
||||||
|
{
|
||||||
|
CBaseCombatWeapon *pWeapon = static_cast<CBaseCombatWeapon *>(pItem);
|
||||||
|
|
||||||
|
pWeapon->Dissolve( NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Task helpers
|
// Purpose: Task helpers
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user