mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2024-12-25 22:35:31 +03:00
Merge pull request #154 from mapbase-source/feature/npc-animation-uprising
The "NPC Animation Uprising" (Code)
This commit is contained in:
commit
b7749dd92e
@ -1990,6 +1990,10 @@ CollideType_t C_BaseAnimating::GetCollideType( void )
|
||||
return BaseClass::GetCollideType();
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar ai_death_pose_enabled( "ai_death_pose_enabled", "1", FCVAR_NONE, "Toggles the death pose fix code, which cancels sequence transitions while a NPC is ragdolling." );
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: if the active sequence changes, keep track of the previous ones and decay them based on their decay rate
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2006,6 +2010,14 @@ void C_BaseAnimating::MaintainSequenceTransitions( IBoneSetup &boneSetup, float
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( IsAboutToRagdoll() && ai_death_pose_enabled.GetBool() )
|
||||
{
|
||||
m_nPrevNewSequenceParity = m_nNewSequenceParity;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_SequenceTransitioner.CheckForSequenceChange(
|
||||
boneSetup.GetStudioHdr(),
|
||||
GetSequence(),
|
||||
@ -2785,14 +2797,29 @@ void C_BaseAnimating::CalculateIKLocks( float currentTime )
|
||||
|
||||
// debugoverlay->AddBoxOverlay( origin, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), QAngle( 0, 0, 0 ), 255, 0, 0, 0, 0 );
|
||||
|
||||
float d = (pTarget->est.pos - origin).Length();
|
||||
Vector vecDelta = (origin - pTarget->est.pos);
|
||||
float d = vecDelta.Length();
|
||||
|
||||
if ( d >= flDist)
|
||||
continue;
|
||||
|
||||
flDist = d;
|
||||
pTarget->SetPos( origin );
|
||||
pTarget->SetAngles( angles );
|
||||
#ifdef MAPBASE
|
||||
// For blending purposes, IK attachments should obey weight
|
||||
if ( pTarget->est.flWeight < 1.0f )
|
||||
{
|
||||
Quaternion qTarget;
|
||||
AngleQuaternion( angles, qTarget );
|
||||
|
||||
QuaternionSlerp( pTarget->est.q, qTarget, pTarget->est.flWeight, pTarget->est.q );
|
||||
pTarget->SetPos( pTarget->est.pos + (vecDelta * pTarget->est.flWeight) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
pTarget->SetPos( origin );
|
||||
pTarget->SetAngles( angles );
|
||||
}
|
||||
// debugoverlay->AddBoxOverlay( pTarget->est.pos, Vector( -pTarget->est.radius, -pTarget->est.radius, -pTarget->est.radius ), Vector( pTarget->est.radius, pTarget->est.radius, pTarget->est.radius), QAngle( 0, 0, 0 ), 0, 255, 0, 0, 0 );
|
||||
}
|
||||
|
||||
|
@ -1095,9 +1095,9 @@ void CBaseAnimatingOverlay::SetLayerNoRestore( int iLayer, bool bNoRestore )
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// From Alien Swarm SDK
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseAnimatingOverlay::SetLayerNoEvents( int iLayer, bool bNoEvents )
|
||||
{
|
||||
@ -1113,6 +1113,17 @@ void CBaseAnimatingOverlay::SetLayerNoEvents( int iLayer, bool bNoEvents )
|
||||
m_AnimOverlay[iLayer].m_fFlags &= ~ANIM_LAYER_NOEVENTS;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseAnimatingOverlay::IsLayerFinished( int iLayer )
|
||||
{
|
||||
if (!IsValidLayer( iLayer ))
|
||||
return true;
|
||||
|
||||
return m_AnimOverlay[iLayer].m_bSequenceFinished;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -181,8 +181,10 @@ public:
|
||||
void SetLayerAutokill( int iLayer, bool bAutokill );
|
||||
void SetLayerLooping( int iLayer, bool bLooping );
|
||||
void SetLayerNoRestore( int iLayer, bool bNoRestore );
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
void SetLayerNoEvents( int iLayer, bool bNoEvents );
|
||||
#ifdef MAPBASE
|
||||
void SetLayerNoEvents( int iLayer, bool bNoEvents ); // From Alien Swarm SDK
|
||||
|
||||
bool IsLayerFinished( int iLayer );
|
||||
#endif
|
||||
|
||||
Activity GetLayerActivity( int iLayer );
|
||||
|
@ -103,6 +103,12 @@ protected:
|
||||
|
||||
inline CBaseEntity *GetActivator();
|
||||
|
||||
#ifdef MAPBASE
|
||||
inline float GetNPCOpenDistance() { return m_flNPCOpenDistance; }
|
||||
inline Activity GetNPCOpenFrontActivity() { return m_eNPCOpenFrontActivity; }
|
||||
inline Activity GetNPCOpenBackActivity() { return m_eNPCOpenBackActivity; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
// Implement these in your leaf class.
|
||||
@ -196,6 +202,12 @@ private:
|
||||
string_t m_SoundOpen;
|
||||
string_t m_SoundClose;
|
||||
|
||||
#ifdef MAPBASE
|
||||
float m_flNPCOpenDistance;
|
||||
Activity m_eNPCOpenFrontActivity;
|
||||
Activity m_eNPCOpenBackActivity;
|
||||
#endif
|
||||
|
||||
// dvs: FIXME: can we remove m_flSpeed from CBaseEntity?
|
||||
//float m_flSpeed; // Rotation speed when opening or closing in degrees per second.
|
||||
|
||||
|
@ -2180,15 +2180,22 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR2 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR2 );
|
||||
//ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR2_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR2_LOW );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_AR2 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_AR2_LOW );
|
||||
#endif
|
||||
|
||||
#ifdef SHARED_COMBINE_ACTIVITIES
|
||||
ADD_ACTIVITY_TO_SR( ACT_COMBINE_THROW_GRENADE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COMBINE_AR2_ALTFIRE );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_COMBINE_THROW_GRENADE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_COMBINE_AR2_ALTFIRE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SPECIAL_ATTACK1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SPECIAL_ATTACK2 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SIGNAL_ADVANCE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SIGNAL_FORWARD );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SIGNAL_GROUP );
|
||||
@ -2198,8 +2205,249 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SIGNAL_TAKECOVER );
|
||||
#endif
|
||||
|
||||
#ifdef COMPANION_HOLSTER_WORKAROUND
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_REVOLVER_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_REVOLVER_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_REVOLVER_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_REVOLVER_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_REVOLVER );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_CROSSBOW_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_CROSSBOW_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_CROSSBOW_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_CROSSBOW_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_CROSSBOW );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_PISTOL_RELAXED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_PISTOL_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_PISTOL_RELAXED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_PISTOL_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_PISTOL_RELAXED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_PISTOL_STIMULATED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_PISTOL_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_PISTOL_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_PISTOL_STIMULATED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_CROUCH_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_CROUCH_AIM_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_CROUCH_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_CROUCH_AIM_PISTOL );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_SHOTGUN );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_SHOTGUN );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_SHOTGUN_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SHOTGUN_LOW );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_SHOTGUN_RELAXED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_SHOTGUN_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_SHOTGUN_RELAXED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_SHOTGUN_STIMULATED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_SHOTGUN_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_SHOTGUN_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_SHOTGUN_STIMULATED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_RPG_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_RPG_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_RPG );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_MELEE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_MELEE );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_PACKAGE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_SUITCASE );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_ARM_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_ARM_SHOTGUN );
|
||||
ADD_ACTIVITY_TO_SR( ACT_ARM_RPG );
|
||||
ADD_ACTIVITY_TO_SR( ACT_ARM_MELEE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_DISARM_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_DISARM_SHOTGUN );
|
||||
ADD_ACTIVITY_TO_SR( ACT_DISARM_RPG );
|
||||
ADD_ACTIVITY_TO_SR( ACT_DISARM_MELEE );
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
ADD_ACTIVITY_TO_SR( ACT_CLIMB_ALL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_CLIMB_IDLE );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_CLIMB_MOUNT_TOP );
|
||||
ADD_ACTIVITY_TO_SR( ACT_CLIMB_MOUNT_BOTTOM );
|
||||
ADD_ACTIVITY_TO_SR( ACT_CLIMB_DISMOUNT_BOTTOM );
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK1_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK2_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_MED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR2_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SMG1_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SHOTGUN_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_PISTOL_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_RPG_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_REVOLVER_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_CROSSBOW_MED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_AR2_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SMG1_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SHOTGUN_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_PISTOL_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_RPG_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_REVOLVER_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_CROSSBOW_MED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_R );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_L );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_R );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_L );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_R_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_L_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_R_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_L_RIFLE );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_R_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_L_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_R_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_L_PISTOL );
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This is a multi-purpose table which links NPC activities to their gesture variants.
|
||||
//-----------------------------------------------------------------------------
|
||||
CAI_BaseNPC::actlink_t CAI_BaseNPC::gm_ActivityGestureLinks[] =
|
||||
{
|
||||
{ ACT_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK1 },
|
||||
{ ACT_RANGE_ATTACK2, ACT_GESTURE_RANGE_ATTACK2 },
|
||||
{ ACT_MELEE_ATTACK1, ACT_GESTURE_MELEE_ATTACK1 },
|
||||
{ ACT_MELEE_ATTACK2, ACT_GESTURE_MELEE_ATTACK2 },
|
||||
{ ACT_RELOAD, ACT_GESTURE_RELOAD },
|
||||
|
||||
{ ACT_RANGE_ATTACK1_LOW, ACT_GESTURE_RANGE_ATTACK1 }, // NOTE: ACT_GESTURE_RANGE_ATTACK1_LOW exists, but isn't used
|
||||
{ ACT_RANGE_ATTACK2_LOW, ACT_GESTURE_RANGE_ATTACK2 }, // NOTE: ACT_GESTURE_RANGE_ATTACK2_LOW exists, but isn't used
|
||||
{ ACT_RELOAD_LOW, ACT_GESTURE_RELOAD },
|
||||
|
||||
{ ACT_MELEE_ATTACK_SWING, ACT_GESTURE_MELEE_ATTACK_SWING },
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
{ ACT_RANGE_ATTACK_AR2, ACT_GESTURE_RANGE_ATTACK_AR2 },
|
||||
{ ACT_RANGE_ATTACK_AR2_LOW, ACT_GESTURE_RANGE_ATTACK_AR2 },
|
||||
{ ACT_RANGE_ATTACK_SMG1, ACT_GESTURE_RANGE_ATTACK_SMG1 },
|
||||
{ ACT_RANGE_ATTACK_SMG1_LOW, ACT_GESTURE_RANGE_ATTACK_SMG1 },
|
||||
{ ACT_RANGE_ATTACK_SHOTGUN, ACT_GESTURE_RANGE_ATTACK_SHOTGUN },
|
||||
{ ACT_RANGE_ATTACK_SHOTGUN_LOW, ACT_GESTURE_RANGE_ATTACK_SHOTGUN },
|
||||
{ ACT_RANGE_ATTACK_PISTOL, ACT_GESTURE_RANGE_ATTACK_PISTOL },
|
||||
{ ACT_RANGE_ATTACK_PISTOL_LOW, ACT_GESTURE_RANGE_ATTACK_PISTOL },
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
{ ACT_SMALL_FLINCH, ACT_GESTURE_SMALL_FLINCH },
|
||||
{ ACT_BIG_FLINCH, ACT_GESTURE_BIG_FLINCH },
|
||||
{ ACT_FLINCH_HEAD, ACT_GESTURE_FLINCH_HEAD },
|
||||
{ ACT_FLINCH_CHEST, ACT_GESTURE_FLINCH_CHEST },
|
||||
{ ACT_FLINCH_STOMACH, ACT_GESTURE_FLINCH_STOMACH },
|
||||
{ ACT_FLINCH_LEFTARM, ACT_GESTURE_FLINCH_LEFTARM },
|
||||
{ ACT_FLINCH_RIGHTARM, ACT_GESTURE_FLINCH_RIGHTARM },
|
||||
{ ACT_FLINCH_LEFTLEG, ACT_GESTURE_FLINCH_LEFTLEG },
|
||||
{ ACT_FLINCH_RIGHTLEG, ACT_GESTURE_FLINCH_RIGHTLEG },
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
#if AR2_ACTIVITY_FIX == 1
|
||||
{ ACT_RELOAD_AR2, ACT_GESTURE_RELOAD_AR2 },
|
||||
{ ACT_RELOAD_AR2_LOW, ACT_GESTURE_RELOAD_AR2 },
|
||||
#endif
|
||||
{ ACT_RELOAD_SMG1, ACT_GESTURE_RELOAD_SMG1 },
|
||||
{ ACT_RELOAD_SMG1_LOW, ACT_GESTURE_RELOAD_SMG1 },
|
||||
{ ACT_RELOAD_SHOTGUN, ACT_GESTURE_RELOAD_SHOTGUN },
|
||||
{ ACT_RELOAD_SHOTGUN_LOW, ACT_GESTURE_RELOAD_SHOTGUN },
|
||||
{ ACT_RELOAD_PISTOL, ACT_GESTURE_RELOAD_PISTOL },
|
||||
{ ACT_RELOAD_PISTOL_LOW, ACT_GESTURE_RELOAD_PISTOL },
|
||||
|
||||
#ifdef SHARED_COMBINE_ACTIVITIES
|
||||
{ ACT_SPECIAL_ATTACK1, ACT_GESTURE_SPECIAL_ATTACK1 },
|
||||
{ ACT_SPECIAL_ATTACK2, ACT_GESTURE_SPECIAL_ATTACK2 },
|
||||
{ ACT_COMBINE_THROW_GRENADE, ACT_GESTURE_COMBINE_THROW_GRENADE },
|
||||
{ ACT_COMBINE_AR2_ALTFIRE, ACT_GESTURE_COMBINE_AR2_ALTFIRE },
|
||||
|
||||
{ ACT_SIGNAL_ADVANCE, ACT_GESTURE_SIGNAL_ADVANCE },
|
||||
{ ACT_SIGNAL_FORWARD, ACT_GESTURE_SIGNAL_FORWARD },
|
||||
{ ACT_SIGNAL_GROUP, ACT_GESTURE_SIGNAL_GROUP },
|
||||
{ ACT_SIGNAL_HALT, ACT_GESTURE_SIGNAL_HALT },
|
||||
{ ACT_SIGNAL_LEFT, ACT_GESTURE_SIGNAL_LEFT },
|
||||
{ ACT_SIGNAL_RIGHT, ACT_GESTURE_SIGNAL_RIGHT },
|
||||
{ ACT_SIGNAL_TAKECOVER, ACT_GESTURE_SIGNAL_TAKECOVER },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_RANGE_ATTACK_REVOLVER, ACT_GESTURE_RANGE_ATTACK_REVOLVER },
|
||||
{ ACT_RANGE_ATTACK_REVOLVER_LOW, ACT_GESTURE_RANGE_ATTACK_REVOLVER },
|
||||
{ ACT_RANGE_ATTACK_CROSSBOW, ACT_GESTURE_RANGE_ATTACK_CROSSBOW },
|
||||
{ ACT_RANGE_ATTACK_CROSSBOW_LOW, ACT_GESTURE_RANGE_ATTACK_CROSSBOW },
|
||||
{ ACT_RANGE_ATTACK_RPG, ACT_GESTURE_RANGE_ATTACK_RPG },
|
||||
{ ACT_RANGE_ATTACK_RPG_LOW, ACT_GESTURE_RANGE_ATTACK_RPG },
|
||||
|
||||
{ ACT_RELOAD_REVOLVER, ACT_GESTURE_RELOAD_REVOLVER },
|
||||
{ ACT_RELOAD_REVOLVER_LOW, ACT_GESTURE_RELOAD_REVOLVER },
|
||||
{ ACT_RELOAD_CROSSBOW, ACT_GESTURE_RELOAD_CROSSBOW },
|
||||
{ ACT_RELOAD_CROSSBOW_LOW, ACT_GESTURE_RELOAD_CROSSBOW },
|
||||
#endif
|
||||
};
|
||||
|
||||
Activity CAI_BaseNPC::GetGestureVersionOfActivity( Activity inActivity )
|
||||
{
|
||||
actlink_t *pTable = gm_ActivityGestureLinks;
|
||||
int actCount = ARRAYSIZE( gm_ActivityGestureLinks );
|
||||
|
||||
for ( int i = 0; i < actCount; i++, pTable++ )
|
||||
{
|
||||
if ( inActivity == pTable->sequence )
|
||||
{
|
||||
return pTable->gesture;
|
||||
}
|
||||
}
|
||||
|
||||
return ACT_INVALID;
|
||||
}
|
||||
|
||||
Activity CAI_BaseNPC::GetSequenceVersionOfGesture( Activity inActivity )
|
||||
{
|
||||
actlink_t *pTable = gm_ActivityGestureLinks;
|
||||
int actCount = ARRAYSIZE( gm_ActivityGestureLinks );
|
||||
|
||||
for (int i = 0; i < actCount; i++, pTable++)
|
||||
{
|
||||
if (inActivity == pTable->gesture)
|
||||
{
|
||||
return pTable->sequence;
|
||||
}
|
||||
}
|
||||
|
||||
return ACT_INVALID;
|
||||
}
|
||||
#endif
|
||||
|
@ -169,6 +169,8 @@ extern ConVar ai_vehicle_avoidance;
|
||||
extern ISoundEmitterSystemBase *soundemitterbase;
|
||||
|
||||
ConVar ai_dynint_always_enabled( "ai_dynint_always_enabled", "0", FCVAR_NONE, "Makes the \"Don't Care\" setting equivalent to \"Yes\"." );
|
||||
|
||||
ConVar ai_debug_fake_sequence_gestures_always_play( "ai_debug_fake_sequence_gestures_always_play", "0", FCVAR_NONE, "Always plays fake sequence gestures." );
|
||||
#endif
|
||||
|
||||
#ifndef _RETAIL
|
||||
@ -313,6 +315,8 @@ ScriptHook_t CAI_BaseNPC::g_Hook_QuerySeeEntity;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_TranslateActivity;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_TranslateSchedule;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_GetActualShootPosition;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_OverrideMove;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_ShouldPlayFakeSequenceGesture;
|
||||
#endif
|
||||
|
||||
//
|
||||
@ -2594,7 +2598,11 @@ bool CAI_BaseNPC::FValidateHintType ( CAI_Hint *pHint )
|
||||
Activity CAI_BaseNPC::GetHintActivity( short sHintType, Activity HintsActivity )
|
||||
{
|
||||
if ( HintsActivity != ACT_INVALID )
|
||||
#ifdef MAPBASE
|
||||
return TranslateActivity( HintsActivity ); // Always translate the activity
|
||||
#else
|
||||
return HintsActivity;
|
||||
#endif
|
||||
|
||||
return ACT_IDLE;
|
||||
}
|
||||
@ -6509,7 +6517,7 @@ CAI_BaseNPC *CAI_BaseNPC::CreateCustomTarget( const Vector &vecOrigin, float dur
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CAI_BaseNPC::TranslateCrouchActivity( Activity eNewActivity )
|
||||
{
|
||||
if (CapabilitiesGet() & bits_CAP_DUCK)
|
||||
if (CapabilitiesGet() & bits_CAP_DUCK && CanTranslateCrouchActivity())
|
||||
{
|
||||
// ========================================================================
|
||||
// The main issue with cover hint nodes is that crouch activities are not translated at the right time
|
||||
@ -6541,10 +6549,18 @@ Activity CAI_BaseNPC::TranslateCrouchActivity( Activity eNewActivity )
|
||||
CAI_Hint *pHint = GetHintNode();
|
||||
if (pHint)
|
||||
{
|
||||
if (pHint->HintType() == HINT_TACTICAL_COVER_LOW || pHint->HintType() == HINT_TACTICAL_COVER_MED)
|
||||
if (pHint->HintType() == HINT_TACTICAL_COVER_LOW)
|
||||
{
|
||||
nCoverActivity = ACT_RANGE_ATTACK1_LOW;
|
||||
}
|
||||
else if (pHint->HintType() == HINT_TACTICAL_COVER_MED)
|
||||
{
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
nCoverActivity = ACT_RANGE_ATTACK1_MED;
|
||||
#else
|
||||
nCoverActivity = ACT_RANGE_ATTACK1_LOW;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6586,15 +6602,30 @@ Activity CAI_BaseNPC::NPC_BackupActivity( Activity eNewActivity )
|
||||
//if (eNewActivity == ACT_DROP_WEAPON)
|
||||
// return TranslateActivity(ACT_IDLE);
|
||||
|
||||
// ---------------------------------------------
|
||||
|
||||
// Accounts for certain act busy activities that aren't on all NPCs.
|
||||
if (eNewActivity == ACT_BUSY_QUEUE || eNewActivity == ACT_BUSY_STAND)
|
||||
return TranslateActivity(ACT_IDLE);
|
||||
|
||||
// ---------------------------------------------
|
||||
|
||||
if (eNewActivity == ACT_WALK_ANGRY)
|
||||
return TranslateActivity(ACT_WALK);
|
||||
|
||||
// GetCoverActivity() should have this covered.
|
||||
// ---------------------------------------------
|
||||
|
||||
// If one climbing animation isn't available, use the other
|
||||
if (eNewActivity == ACT_CLIMB_DOWN)
|
||||
return ACT_CLIMB_UP;
|
||||
else if (eNewActivity == ACT_CLIMB_UP)
|
||||
return ACT_CLIMB_DOWN;
|
||||
|
||||
// ---------------------------------------------
|
||||
|
||||
if (eNewActivity == ACT_COVER_MED)
|
||||
eNewActivity = ACT_COVER_LOW;
|
||||
|
||||
//if (eNewActivity == ACT_COVER)
|
||||
// return TranslateActivity(ACT_IDLE);
|
||||
|
||||
@ -6609,6 +6640,14 @@ Activity CAI_BaseNPC::NPC_BackupActivity( Activity eNewActivity )
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CAI_BaseNPC::NPC_TranslateActivity( Activity eNewActivity )
|
||||
{
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ( GetNavType() == NAV_CLIMB && eNewActivity == ACT_IDLE )
|
||||
{
|
||||
// Schedules which break into idle activities should try to maintain the climbing animation.
|
||||
return ACT_CLIMB_IDLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
Assert( eNewActivity != ACT_INVALID );
|
||||
|
||||
@ -6831,7 +6870,12 @@ void CAI_BaseNPC::ResolveActivityToSequence(Activity NewActivity, int &iSequence
|
||||
|
||||
translatedActivity = TranslateActivity( NewActivity, &weaponActivity );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Cover cases where TranslateActivity() returns a sequence by using ACT_SCRIPT_CUSTOM_MOVE
|
||||
if ( NewActivity == ACT_SCRIPT_CUSTOM_MOVE || translatedActivity == ACT_SCRIPT_CUSTOM_MOVE )
|
||||
#else
|
||||
if ( NewActivity == ACT_SCRIPT_CUSTOM_MOVE )
|
||||
#endif
|
||||
{
|
||||
iSequence = GetScriptCustomMoveSequence();
|
||||
}
|
||||
@ -7017,6 +7061,23 @@ void CAI_BaseNPC::SetIdealActivity( Activity NewActivity )
|
||||
// Perform translation in case we need to change sequences within a single activity,
|
||||
// such as between a standing idle and a crouching idle.
|
||||
ResolveActivityToSequence(m_IdealActivity, m_nIdealSequence, m_IdealTranslatedActivity, m_IdealWeaponActivity);
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Check if we need a gesture to imitate this sequence
|
||||
if ( ShouldPlayFakeSequenceGesture( m_IdealActivity, m_IdealTranslatedActivity ) )
|
||||
{
|
||||
Activity nGesture = SelectFakeSequenceGesture( m_IdealActivity, m_IdealTranslatedActivity );
|
||||
if (nGesture != -1)
|
||||
{
|
||||
PlayFakeSequenceGesture( nGesture, m_IdealActivity, m_IdealTranslatedActivity );
|
||||
}
|
||||
}
|
||||
else if (GetFakeSequenceGesture() != -1)
|
||||
{
|
||||
// Reset the current gesture sequence if there is one
|
||||
ResetFakeSequenceGesture();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -7065,6 +7126,14 @@ void CAI_BaseNPC::AdvanceToIdealActivity(void)
|
||||
//DevMsg("%s: Unable to get from sequence %s to %s!\n", GetClassname(), GetSequenceName(GetSequence()), GetSequenceName(m_nIdealSequence));
|
||||
SetActivity(m_IdealActivity);
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// If there was a gesture imitating a sequence, get rid of it
|
||||
if ( GetFakeSequenceGesture() != -1 )
|
||||
{
|
||||
ResetFakeSequenceGesture();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -7122,6 +7191,12 @@ void CAI_BaseNPC::MaintainActivity(void)
|
||||
}
|
||||
// Else a transition sequence is in progress, do nothing.
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else if (GetFakeSequenceGesture() != -1)
|
||||
{
|
||||
// Don't advance even if the sequence gesture is finished, as advancing would just play the original activity afterwards
|
||||
}
|
||||
#endif
|
||||
// Else get a specific sequence for the activity and try to transition to that.
|
||||
else
|
||||
{
|
||||
@ -7140,11 +7215,103 @@ void CAI_BaseNPC::MaintainActivity(void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool CAI_BaseNPC::ShouldPlayFakeSequenceGesture( Activity nActivity, Activity nTranslatedActivity )
|
||||
{
|
||||
// Don't do anything if we're resetting our activity
|
||||
if (GetActivity() == ACT_RESET)
|
||||
return false;
|
||||
|
||||
// No need to do this while we're moving
|
||||
if (IsCurTaskContinuousMove())
|
||||
return false;
|
||||
|
||||
if (ai_debug_fake_sequence_gestures_always_play.GetBool())
|
||||
return true;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_ShouldPlayFakeSequenceGesture.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
// activity, translatedActivity
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { GetActivityName( nActivity ), GetActivityName( nTranslatedActivity ) };
|
||||
if (g_Hook_ShouldPlayFakeSequenceGesture.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
if (functionReturn.m_type == FIELD_BOOLEAN)
|
||||
return functionReturn.m_bool;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GetHintNode() && GetHintNode()->HintActivityName() != NULL_STRING)
|
||||
{
|
||||
switch (GetHintNode()->HintType())
|
||||
{
|
||||
// Cover nodes with custom activities should allow NPCs to do things like reload while in cover.
|
||||
case HINT_TACTICAL_COVER_LOW:
|
||||
case HINT_TACTICAL_COVER_MED:
|
||||
case HINT_TACTICAL_COVER_CUSTOM:
|
||||
if (HasMemory( bits_MEMORY_INCOVER ))
|
||||
{
|
||||
// Don't attack while using a custom animation in cover
|
||||
if (nActivity != ACT_RANGE_ATTACK1 && nActivity != ACT_RANGE_ATTACK1_LOW)
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Activity CAI_BaseNPC::SelectFakeSequenceGesture( Activity nActivity, Activity nTranslatedActivity )
|
||||
{
|
||||
return GetGestureVersionOfActivity( nTranslatedActivity );
|
||||
}
|
||||
|
||||
inline void CAI_BaseNPC::PlayFakeSequenceGesture( Activity nActivity, Activity nSequence, Activity nTranslatedSequence )
|
||||
{
|
||||
RestartGesture( nActivity, true, true );
|
||||
m_FakeSequenceGestureLayer = FindGestureLayer( nActivity );
|
||||
|
||||
switch ( nSequence )
|
||||
{
|
||||
case ACT_RANGE_ATTACK1:
|
||||
//case ACT_RANGE_ATTACK2:
|
||||
{
|
||||
OnRangeAttack1();
|
||||
|
||||
// FIXME: this seems a bit wacked
|
||||
Weapon_SetActivity( Weapon_TranslateActivity( nSequence ), 0 );
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
inline int CAI_BaseNPC::GetFakeSequenceGesture()
|
||||
{
|
||||
return m_FakeSequenceGestureLayer;
|
||||
}
|
||||
|
||||
void CAI_BaseNPC::ResetFakeSequenceGesture()
|
||||
{
|
||||
SetLayerCycle( m_FakeSequenceGestureLayer, 1.0f );
|
||||
m_FakeSequenceGestureLayer = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns true if our ideal activity has finished playing.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_BaseNPC::IsActivityFinished( void )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (GetFakeSequenceGesture() != -1)
|
||||
{
|
||||
return IsLayerFinished( GetFakeSequenceGesture() );
|
||||
}
|
||||
#endif
|
||||
|
||||
return (IsSequenceFinished() && (GetSequence() == m_nIdealSequence));
|
||||
}
|
||||
|
||||
@ -7180,6 +7347,15 @@ void CAI_BaseNPC::OnChangeActivity( Activity eNewActivity )
|
||||
eNewActivity == ACT_WALK )
|
||||
{
|
||||
Stand();
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Unlock custom cover nodes
|
||||
if (GetHintNode() && GetHintNode()->HintType() == HINT_TACTICAL_COVER_CUSTOM && HasMemory(bits_MEMORY_INCOVER))
|
||||
{
|
||||
GetHintNode()->Unlock( GetHintDelay( GetHintNode()->HintType() ) );
|
||||
SetHintNode( NULL );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -7768,7 +7944,7 @@ int CAI_BaseNPC::HolsterWeapon( void )
|
||||
if ( IsWeaponHolstered() )
|
||||
return -1;
|
||||
|
||||
#ifdef COMPANION_HOLSTER_WORKAROUND
|
||||
#ifdef MAPBASE
|
||||
Activity activity = TranslateActivity( ACT_DISARM );
|
||||
int iHolsterGesture = FindGestureLayer( activity );
|
||||
if ( iHolsterGesture != -1 )
|
||||
@ -7824,7 +8000,7 @@ int CAI_BaseNPC::UnholsterWeapon( void )
|
||||
if ( !IsWeaponHolstered() )
|
||||
return -1;
|
||||
|
||||
#ifdef COMPANION_HOLSTER_WORKAROUND
|
||||
#ifdef MAPBASE
|
||||
Activity activity = TranslateActivity( ACT_ARM );
|
||||
int iHolsterGesture = FindGestureLayer( activity );
|
||||
#else
|
||||
@ -7853,13 +8029,12 @@ int CAI_BaseNPC::UnholsterWeapon( void )
|
||||
{
|
||||
SetActiveWeapon( GetWeapon(i) );
|
||||
|
||||
#ifdef COMPANION_HOLSTER_WORKAROUND
|
||||
int iLayer = AddGesture( activity, true );
|
||||
//iLayer = AddGesture( ACT_GESTURE_ARM, true );
|
||||
#ifdef MAPBASE
|
||||
int iLayer = AddGesture( TranslateActivity( ACT_ARM ), true );
|
||||
#else
|
||||
int iLayer = AddGesture( ACT_ARM, true );
|
||||
//iLayer = AddGesture( ACT_GESTURE_ARM, true );
|
||||
#endif
|
||||
//iLayer = AddGesture( ACT_GESTURE_ARM, true );
|
||||
|
||||
if (iLayer != -1)
|
||||
{
|
||||
@ -8038,6 +8213,26 @@ bool CAI_BaseNPC::DoUnholster( void )
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns true if the NPC should be unholstering their weapon
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_BaseNPC::ShouldUnholsterWeapon( void )
|
||||
{
|
||||
return GetState() == NPC_STATE_COMBAT;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns true if the NPC can unholster their weapon
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_BaseNPC::CanUnholsterWeapon( void )
|
||||
{
|
||||
// Don't unholster during special navigation
|
||||
if ( GetNavType() == NAV_JUMP || GetNavType() == NAV_CLIMB )
|
||||
return false;
|
||||
|
||||
return IsWeaponHolstered();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: Give the NPC in question the weapon specified
|
||||
//------------------------------------------------------------------------------
|
||||
@ -9104,27 +9299,45 @@ Activity CAI_BaseNPC::GetCoverActivity( CAI_Hint *pHint )
|
||||
switch (pHint->HintType())
|
||||
{
|
||||
case HINT_TACTICAL_COVER_MED:
|
||||
#ifndef MAPBASE // I know what you're thinking, but ACT_COVER_MED is pretty much deprecated at this point anyway.
|
||||
{
|
||||
nCoverActivity = ACT_COVER_MED;
|
||||
#ifdef MAPBASE
|
||||
// Some NPCs lack ACT_COVER_MED, but could easily use ACT_COVER_LOW.
|
||||
if (SelectWeightedSequence(nCoverActivity) == ACTIVITY_NOT_AVAILABLE)
|
||||
nCoverActivity = ACT_COVER_LOW;
|
||||
#endif
|
||||
// NPCs which lack ACT_COVER_MED should fall through to HINT_TACTICAL_COVER_LOW
|
||||
if (SelectWeightedSequence( ACT_COVER_MED ) != ACTIVITY_NOT_AVAILABLE)
|
||||
{
|
||||
nCoverActivity = ACT_COVER_MED;
|
||||
}
|
||||
#else
|
||||
nCoverActivity = ACT_COVER_MED;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
case HINT_TACTICAL_COVER_LOW:
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (pHint->HintActivityName() != NULL_STRING)
|
||||
nCoverActivity = (Activity)CAI_BaseNPC::GetActivityID( STRING(pHint->HintActivityName()) );
|
||||
else
|
||||
#endif
|
||||
// Make sure nCoverActivity wasn't already assigned above, then fall through to HINT_TACTICAL_COVER_CUSTOM
|
||||
if (nCoverActivity == ACT_INVALID)
|
||||
nCoverActivity = ACT_COVER_LOW;
|
||||
#else
|
||||
nCoverActivity = ACT_COVER_LOW;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
case HINT_TACTICAL_COVER_CUSTOM:
|
||||
{
|
||||
if (pHint->HintActivityName() != NULL_STRING)
|
||||
{
|
||||
nCoverActivity = (Activity)CAI_BaseNPC::GetActivityID( STRING(pHint->HintActivityName()) );
|
||||
if (nCoverActivity == ACT_INVALID)
|
||||
{
|
||||
m_iszSceneCustomMoveSeq = pHint->HintActivityName();
|
||||
nCoverActivity = ACT_SCRIPT_CUSTOM_MOVE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -9162,6 +9375,13 @@ float CAI_BaseNPC::CalcIdealYaw( const Vector &vecTarget )
|
||||
|
||||
return UTIL_VecToYaw( vecProjection - GetLocalOrigin() );
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
// Allow hint nodes to override the yaw without needing to control AI
|
||||
else if (GetHintNode() && GetHintNode()->OverridesNPCYaw( this ))
|
||||
{
|
||||
return GetHintNode()->Yaw();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return UTIL_VecToYaw ( vecTarget - GetLocalOrigin() );
|
||||
@ -9502,7 +9722,7 @@ void CAI_BaseNPC::HandleAnimEvent( animevent_t *pEvent )
|
||||
if ( GetActiveWeapon() )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
GetActiveWeapon()->Reload_NPC();
|
||||
GetActiveWeapon()->Reload_NPC( true );
|
||||
#else
|
||||
GetActiveWeapon()->WeaponSound( RELOAD_NPC );
|
||||
GetActiveWeapon()->m_iClip1 = GetActiveWeapon()->GetMaxClip1();
|
||||
@ -9526,8 +9746,12 @@ void CAI_BaseNPC::HandleAnimEvent( animevent_t *pEvent )
|
||||
case EVENT_WEAPON_RELOAD_FILL_CLIP:
|
||||
{
|
||||
if ( GetActiveWeapon() )
|
||||
{
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
GetActiveWeapon()->Reload_NPC( false );
|
||||
#else
|
||||
GetActiveWeapon()->m_iClip1 = GetActiveWeapon()->GetMaxClip1();
|
||||
#endif
|
||||
ClearCondition(COND_LOW_PRIMARY_AMMO);
|
||||
ClearCondition(COND_NO_PRIMARY_AMMO);
|
||||
ClearCondition(COND_NO_SECONDARY_AMMO);
|
||||
@ -9542,7 +9766,11 @@ void CAI_BaseNPC::HandleAnimEvent( animevent_t *pEvent )
|
||||
|
||||
case NPC_EVENT_OPEN_DOOR:
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
CBasePropDoor *pDoor = m_hOpeningDoor;
|
||||
#else
|
||||
CBasePropDoor *pDoor = (CBasePropDoor *)(CBaseEntity *)GetNavigator()->GetPath()->GetCurWaypoint()->GetEHandleData();
|
||||
#endif
|
||||
if (pDoor != NULL)
|
||||
{
|
||||
OpenPropDoorNow( pDoor );
|
||||
@ -11904,6 +12132,7 @@ BEGIN_DATADESC( CAI_BaseNPC )
|
||||
DEFINE_KEYFIELD( m_FriendlyFireOverride, FIELD_INTEGER, "FriendlyFireOverride" ),
|
||||
|
||||
DEFINE_KEYFIELD( m_flSpeedModifier, FIELD_FLOAT, "BaseSpeedModifier" ),
|
||||
DEFINE_FIELD( m_FakeSequenceGestureLayer, FIELD_INTEGER ),
|
||||
#endif
|
||||
|
||||
// Satisfy classcheck
|
||||
@ -12061,6 +12290,11 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSetActivityID, "SetActivityID", "Set the NPC's current activity ID." )
|
||||
DEFINE_SCRIPTFUNC( ResetActivity, "Reset the NPC's current activity." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetGestureVersionOfActivity, "GetGestureVersionOfActivity", "Get the gesture activity counterpart of the specified sequence activity, if one exists." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetGestureVersionOfActivityID, "GetGestureVersionOfActivityID", "Get the gesture activity ID counterpart of the specified sequence activity ID, if one exists." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetSequenceVersionOfGesture, "GetSequenceVersionOfGesture", "Get the sequence activity counterpart of the specified gesture activity, if one exists." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetSequenceVersionOfGestureID, "GetSequenceVersionOfGestureID", "Get the sequence activity ID counterpart of the specified gesture activity ID, if one exists." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetSchedule, "GetSchedule", "Get the NPC's current schedule." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetScheduleID, "GetScheduleID", "Get the NPC's current schedule ID." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetSchedule, "SetSchedule", "Set the NPC's current schedule." )
|
||||
@ -12107,10 +12341,17 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTHOOK_PARAM( "schedule", FIELD_CSTRING )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "schedule_id", FIELD_INTEGER )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_GetActualShootPosition, "GetActualShootPosition", FIELD_VOID, "Called when the NPC is getting their actual shoot position, using the default shoot position as the parameter. (NOTE: NPCs which override this themselves might not always use this hook!)" )
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_GetActualShootPosition, "GetActualShootPosition", FIELD_VECTOR, "Called when the NPC is getting their actual shoot position, using the default shoot position as the parameter. (NOTE: NPCs which override this themselves might not always use this hook!)" )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "shootOrigin", FIELD_VECTOR )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "target", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_OverrideMove, "OverrideMove", FIELD_VOID, "Called when the NPC runs movement code, allowing the NPC's movement to be overridden by some other method. (NOTE: NPCs which override this themselves might not always use this hook!)" )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "interval", FIELD_FLOAT )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_ShouldPlayFakeSequenceGesture, "ShouldPlayFakeSequenceGesture", FIELD_BOOLEAN, "Called when an activity is set on a NPC. Returning true will make the NPC convert the activity into a gesture (if a gesture is available) and continue their current activity instead." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "activity", FIELD_CSTRING )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "translatedActivity", FIELD_CSTRING )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
END_SCRIPTDESC();
|
||||
#endif
|
||||
@ -12761,6 +13002,8 @@ CAI_BaseNPC::CAI_BaseNPC(void)
|
||||
#ifdef MAPBASE
|
||||
m_iDynamicInteractionsAllowed = TRS_NONE;
|
||||
m_flSpeedModifier = 1.0f;
|
||||
|
||||
m_FakeSequenceGestureLayer = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -13715,6 +13958,10 @@ bool CAI_BaseNPC::OnUpcomingPropDoor( AILocalMoveGoal_t *pMoveGoal,
|
||||
|
||||
GetNavigator()->GetPath()->PrependWaypoints( pOpenDoorRoute );
|
||||
|
||||
#ifdef MAPBASE
|
||||
GetNavigator()->SetArrivalDirection( opendata.vecFaceDir );
|
||||
#endif
|
||||
|
||||
m_hOpeningDoor = pDoor;
|
||||
pMoveGoal->maxDist = distClear;
|
||||
*pResult = AIMR_CHANGE_TYPE;
|
||||
@ -13735,6 +13982,21 @@ bool CAI_BaseNPC::OnUpcomingPropDoor( AILocalMoveGoal_t *pMoveGoal,
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_BaseNPC::OpenPropDoorBegin( CBasePropDoor *pDoor )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
opendata_t opendata;
|
||||
pDoor->GetNPCOpenData(this, opendata);
|
||||
|
||||
if (HaveSequenceForActivity( opendata.eActivity ))
|
||||
{
|
||||
int iLayer = AddGesture( opendata.eActivity );
|
||||
float flDuration = GetLayerDuration( iLayer );
|
||||
|
||||
// Face the door and wait for the activity to finish before trying to move through the doorway.
|
||||
m_flMoveWaitFinished = gpGlobals->curtime + flDuration + pDoor->GetOpenInterval();
|
||||
AddFacingTarget( opendata.vecFaceDir, 1.0, flDuration );
|
||||
}
|
||||
else
|
||||
#else
|
||||
// dvs: not quite working, disabled for now.
|
||||
//opendata_t opendata;
|
||||
//pDoor->GetNPCOpenData(this, opendata);
|
||||
@ -13744,6 +14006,7 @@ void CAI_BaseNPC::OpenPropDoorBegin( CBasePropDoor *pDoor )
|
||||
// SetIdealActivity(opendata.eActivity);
|
||||
//}
|
||||
//else
|
||||
#endif
|
||||
{
|
||||
// We don't have an appropriate sequence, just open the door magically.
|
||||
OpenPropDoorNow( pDoor );
|
||||
@ -13763,6 +14026,15 @@ void CAI_BaseNPC::OpenPropDoorNow( CBasePropDoor *pDoor )
|
||||
|
||||
// Wait for the door to finish opening before trying to move through the doorway.
|
||||
m_flMoveWaitFinished = gpGlobals->curtime + pDoor->GetOpenInterval();
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Remove the door from our waypoint
|
||||
if (GetNavigator()->GetPath() && GetNavigator()->GetCurWaypointFlags() & bits_WP_TO_DOOR)
|
||||
{
|
||||
GetNavigator()->GetPath()->GetCurWaypoint()->ModifyFlags( bits_WP_TO_DOOR, false );
|
||||
GetNavigator()->GetPath()->GetCurWaypoint()->m_hData = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -15952,6 +16224,26 @@ bool CAI_BaseNPC::CouldShootIfCrouching( CBaseEntity *pTarget )
|
||||
return bResult;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Check if this position will block our line of sight if aiming low.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_BaseNPC::CouldShootIfCrouchingAt( const Vector &vecPosition, const Vector &vecForward, const Vector &vecRight, float flDist )
|
||||
{
|
||||
Vector vGunPos = vecPosition;
|
||||
vGunPos += (GetCrouchGunOffset() + vecRight * 8);
|
||||
|
||||
trace_t tr;
|
||||
AI_TraceLOS( vGunPos, vGunPos + (vecForward * flDist), this, &tr );
|
||||
if (tr.fraction != 1.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -15967,9 +16259,16 @@ bool CAI_BaseNPC::IsCrouchedActivity( Activity activity )
|
||||
case ACT_COVER_SMG1_LOW:
|
||||
case ACT_RELOAD_SMG1_LOW:
|
||||
#ifdef MAPBASE
|
||||
//case ACT_RELOAD_AR2_LOW:
|
||||
#if AR2_ACTIVITY_FIX == 1
|
||||
case ACT_COVER_AR2_LOW:
|
||||
case ACT_RELOAD_AR2_LOW:
|
||||
#endif
|
||||
case ACT_RELOAD_PISTOL_LOW:
|
||||
case ACT_RELOAD_SHOTGUN_LOW:
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
case ACT_RELOAD_REVOLVER_LOW:
|
||||
case ACT_RELOAD_CROSSBOW_LOW:
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -998,6 +998,7 @@ public:
|
||||
Activity NPC_TranslateActivity( Activity eNewActivity );
|
||||
#ifdef MAPBASE
|
||||
Activity TranslateCrouchActivity( Activity baseAct );
|
||||
virtual bool CanTranslateCrouchActivity( void ) { return true; }
|
||||
virtual Activity NPC_BackupActivity( Activity eNewActivity );
|
||||
#endif
|
||||
Activity GetActivity( void ) { return m_Activity; }
|
||||
@ -1020,6 +1021,25 @@ public:
|
||||
|
||||
void SetActivityAndSequence(Activity NewActivity, int iSequence, Activity translatedActivity, Activity weaponActivity);
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------
|
||||
|
||||
// Returns the gesture variant of an activity (i.e. "ACT_GESTURE_RANGE_ATTACK1")
|
||||
static Activity GetGestureVersionOfActivity( Activity inActivity );
|
||||
|
||||
// Returns the sequence variant of a gesture activity
|
||||
static Activity GetSequenceVersionOfGesture( Activity inActivity );
|
||||
|
||||
//-----------------------------------------------------
|
||||
|
||||
virtual bool ShouldPlayFakeSequenceGesture( Activity nActivity, Activity nTranslatedActivity );
|
||||
virtual Activity SelectFakeSequenceGesture( Activity nActivity, Activity nTranslatedActivity );
|
||||
void PlayFakeSequenceGesture( Activity nActivity, Activity nSequence, Activity nTranslatedSequence );
|
||||
|
||||
int GetFakeSequenceGesture();
|
||||
void ResetFakeSequenceGesture();
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
void AdvanceToIdealActivity(void);
|
||||
@ -1033,6 +1053,10 @@ private:
|
||||
Activity m_IdealTranslatedActivity; // Desired actual translated animation state
|
||||
Activity m_IdealWeaponActivity; // Desired weapon animation state
|
||||
|
||||
#ifdef MAPBASE
|
||||
int m_FakeSequenceGestureLayer; // The gesture layer impersonating a sequence (-1 if invalid)
|
||||
#endif
|
||||
|
||||
CNetworkVar(int, m_iDeathPose );
|
||||
CNetworkVar(int, m_iDeathFrame );
|
||||
|
||||
@ -1217,6 +1241,8 @@ public:
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
private:
|
||||
|
||||
// VScript stuff uses "VScript" instead of just "Script" to avoid
|
||||
// confusion with NPC_STATE_SCRIPT or StartScripting
|
||||
HSCRIPT VScriptGetEnemy();
|
||||
@ -1243,6 +1269,11 @@ public:
|
||||
int ScriptTranslateActivity( const char *szActivity ) { return TranslateActivity( (Activity)GetActivityID( szActivity ) ); }
|
||||
int ScriptTranslateActivityID( int iActivity ) { return TranslateActivity( (Activity)iActivity ); }
|
||||
|
||||
const char* VScriptGetGestureVersionOfActivity( const char *pszActivity ) { return GetActivityName( GetGestureVersionOfActivity( (Activity)GetActivityID( pszActivity ) ) ); }
|
||||
int VScriptGetGestureVersionOfActivityID( int iActivity ) { return GetGestureVersionOfActivity( (Activity)iActivity ); }
|
||||
const char* VScriptGetSequenceVersionOfGesture( const char *pszActivity ) { return GetActivityName( GetSequenceVersionOfGesture( (Activity)GetActivityID( pszActivity ) ) ); }
|
||||
int VScriptGetSequenceVersionOfGestureID( int iActivity ) { return GetSequenceVersionOfGesture( (Activity)iActivity ); }
|
||||
|
||||
const char* VScriptGetSchedule();
|
||||
int VScriptGetScheduleID();
|
||||
void VScriptSetSchedule( const char *szSchedule );
|
||||
@ -1731,8 +1762,8 @@ public:
|
||||
virtual bool DoHolster(void);
|
||||
virtual bool DoUnholster(void);
|
||||
|
||||
virtual bool ShouldUnholsterWeapon() { return GetState() == NPC_STATE_COMBAT; }
|
||||
virtual bool CanUnholsterWeapon() { return IsWeaponHolstered(); }
|
||||
virtual bool ShouldUnholsterWeapon();
|
||||
virtual bool CanUnholsterWeapon();
|
||||
|
||||
void InputGiveWeaponHolstered( inputdata_t &inputdata );
|
||||
void InputChangeWeapon( inputdata_t &inputdata );
|
||||
@ -2207,6 +2238,10 @@ public:
|
||||
inline void ForceCrouch( void );
|
||||
inline void ClearForceCrouch( void );
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool CouldShootIfCrouchingAt( const Vector &vecPosition, const Vector &vecForward, const Vector &vecRight, float flDist = 48.0f );
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual bool Crouch( void );
|
||||
virtual bool Stand( void );
|
||||
@ -2266,6 +2301,16 @@ private:
|
||||
static CAI_GlobalScheduleNamespace gm_SchedulingSymbols;
|
||||
static CAI_ClassScheduleIdSpace gm_ClassScheduleIdSpace;
|
||||
|
||||
#ifdef MAPBASE
|
||||
typedef struct
|
||||
{
|
||||
Activity sequence;
|
||||
Activity gesture;
|
||||
} actlink_t;
|
||||
|
||||
static actlink_t gm_ActivityGestureLinks[];
|
||||
#endif
|
||||
|
||||
public:
|
||||
//----------------------------------------------------
|
||||
// Debugging tools
|
||||
@ -2317,6 +2362,7 @@ public:
|
||||
static ScriptHook_t g_Hook_TranslateSchedule;
|
||||
static ScriptHook_t g_Hook_GetActualShootPosition;
|
||||
static ScriptHook_t g_Hook_OverrideMove;
|
||||
static ScriptHook_t g_Hook_ShouldPlayFakeSequenceGesture;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -980,11 +980,12 @@ bool CAI_BaseNPC::FindCoverFromEnemy( bool bNodesOnly, float flMinDistance, floa
|
||||
// FIXME: add to goal
|
||||
if (GetHintNode())
|
||||
{
|
||||
GetNavigator()->SetArrivalActivity( GetCoverActivity( GetHintNode() ) );
|
||||
#ifdef MAPBASE
|
||||
if (GetHintNode()->GetIgnoreFacing() != HIF_NO)
|
||||
#endif
|
||||
GetHintNode()->NPCHandleStartNav( this, true );
|
||||
#else
|
||||
GetNavigator()->SetArrivalActivity( GetCoverActivity( GetHintNode() ) );
|
||||
GetNavigator()->SetArrivalDirection( GetHintNode()->GetDirection() );
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1363,6 +1364,14 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
||||
break;
|
||||
|
||||
case TASK_STOP_MOVING:
|
||||
#ifdef MAPBASE
|
||||
if ( GetNavType() == NAV_CLIMB )
|
||||
{
|
||||
// Don't clear the goal so that the climb can finish
|
||||
DbgNavMsg( this, "Start TASK_STOP_MOVING with climb workaround\n" );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ( ( GetNavigator()->IsGoalSet() && GetNavigator()->IsGoalActive() ) || GetNavType() == NAV_JUMP )
|
||||
{
|
||||
DbgNavMsg( this, "Start TASK_STOP_MOVING\n" );
|
||||
@ -3348,8 +3357,40 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
|
||||
// a navigation while in the middle of a climb
|
||||
if (GetNavType() == NAV_CLIMB)
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (GetActivity() != ACT_CLIMB_DISMOUNT)
|
||||
{
|
||||
// Try to just pause the climb, but dismount if we're in SCHED_FAIL
|
||||
if (IsCurSchedule( SCHED_FAIL, false ))
|
||||
{
|
||||
GetMotor()->MoveClimbStop();
|
||||
}
|
||||
else
|
||||
{
|
||||
GetMotor()->MoveClimbPause();
|
||||
}
|
||||
|
||||
TaskComplete();
|
||||
}
|
||||
else if (IsActivityFinished())
|
||||
{
|
||||
// Dismount complete.
|
||||
GetMotor()->MoveClimbStop();
|
||||
|
||||
// Fix up our position if we have to
|
||||
Vector vecTeleportOrigin;
|
||||
if (GetMotor()->MoveClimbShouldTeleportToSequenceEnd( vecTeleportOrigin ))
|
||||
{
|
||||
SetLocalOrigin( vecTeleportOrigin );
|
||||
}
|
||||
|
||||
TaskComplete();
|
||||
}
|
||||
break;
|
||||
#else
|
||||
// wait until you reach the end
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
DbgNavMsg( this, "TASK_STOP_MOVING Complete\n" );
|
||||
@ -3394,6 +3435,17 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
|
||||
// If the yaw is locked, this function will not act correctly
|
||||
Assert( GetMotor()->IsYawLocked() == false );
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( GetHintNode() && GetHintNode()->OverridesNPCYaw( this ) )
|
||||
{
|
||||
// If the yaw is supposed to use that of a hint node, chain to TASK_FACE_HINTNODE
|
||||
GetMotor()->SetIdealYaw( GetHintNode()->Yaw() );
|
||||
GetMotor()->SetIdealYaw( CalcReasonableFacing( true ) ); // CalcReasonableFacing() is based on previously set ideal yaw
|
||||
ChainRunTask( TASK_FACE_HINTNODE, pTask->flTaskData );
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
Vector vecEnemyLKP = GetEnemyLKP();
|
||||
if (!FInAimCone( vecEnemyLKP ))
|
||||
{
|
||||
@ -4280,6 +4332,15 @@ void CAI_BaseNPC::SetTurnActivity ( void )
|
||||
float flYD;
|
||||
flYD = GetMotor()->DeltaIdealYaw();
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Allow AddTurnGesture() to decide this
|
||||
if (GetMotor()->AddTurnGesture( flYD ))
|
||||
{
|
||||
SetIdealActivity( ACT_IDLE );
|
||||
Remember( bits_MEMORY_TURNING );
|
||||
return;
|
||||
}
|
||||
#else
|
||||
// FIXME: unknown case, update yaw should catch these
|
||||
/*
|
||||
if (GetMotor()->AddTurnGesture( flYD ))
|
||||
@ -4289,6 +4350,7 @@ void CAI_BaseNPC::SetTurnActivity ( void )
|
||||
return;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
if( flYD <= -80 && flYD >= -100 && SelectWeightedSequence( ACT_90_RIGHT ) != ACTIVITY_NOT_AVAILABLE )
|
||||
{
|
||||
|
@ -420,6 +420,24 @@ bool CAI_BehaviorBase::CanUnholsterWeapon( void )
|
||||
|
||||
return m_pBackBridge->BackBridge_CanUnholsterWeapon();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
bool CAI_BehaviorBase::ShouldPickADeathPose( void )
|
||||
{
|
||||
Assert( m_pBackBridge != NULL );
|
||||
|
||||
return m_pBackBridge->BackBridge_ShouldPickADeathPose();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
bool CAI_BehaviorBase::CanTranslateCrouchActivity( void )
|
||||
{
|
||||
Assert( m_pBackBridge != NULL );
|
||||
|
||||
return m_pBackBridge->BackBridge_CanTranslateCrouchActivity();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------
|
||||
|
@ -132,6 +132,8 @@ public:
|
||||
void BridgeHandleAnimEvent( animevent_t *pEvent );
|
||||
#ifdef MAPBASE
|
||||
bool BridgeCanUnholsterWeapon( void );
|
||||
bool BridgeShouldPickADeathPose( void );
|
||||
bool BridgeCanTranslateCrouchActivity( void );
|
||||
#endif
|
||||
|
||||
virtual void GatherConditions();
|
||||
@ -220,6 +222,8 @@ protected:
|
||||
virtual void HandleAnimEvent( animevent_t *pEvent );
|
||||
#ifdef MAPBASE
|
||||
virtual bool CanUnholsterWeapon( void );
|
||||
virtual bool ShouldPickADeathPose( void );
|
||||
virtual bool CanTranslateCrouchActivity( void );
|
||||
#endif
|
||||
|
||||
virtual bool ShouldAlwaysThink();
|
||||
@ -370,6 +374,9 @@ public:
|
||||
#ifdef MAPBASE
|
||||
// For func_tank behavior
|
||||
virtual bool BackBridge_CanUnholsterWeapon( void ) = 0;
|
||||
|
||||
virtual bool BackBridge_ShouldPickADeathPose( void ) = 0;
|
||||
virtual bool BackBridge_CanTranslateCrouchActivity( void ) = 0;
|
||||
#endif
|
||||
|
||||
//-------------------------------------
|
||||
@ -470,6 +477,8 @@ public:
|
||||
void HandleAnimEvent( animevent_t *pEvent );
|
||||
#ifdef MAPBASE
|
||||
bool CanUnholsterWeapon( void );
|
||||
bool ShouldPickADeathPose( void );
|
||||
bool CanTranslateCrouchActivity( void );
|
||||
#endif
|
||||
|
||||
bool ShouldAlwaysThink();
|
||||
@ -534,6 +543,9 @@ private:
|
||||
#ifdef MAPBASE
|
||||
// For func_tank behavior
|
||||
bool BackBridge_CanUnholsterWeapon( void );
|
||||
|
||||
bool BackBridge_ShouldPickADeathPose( void );
|
||||
bool BackBridge_CanTranslateCrouchActivity( void );
|
||||
#endif
|
||||
|
||||
CAI_BehaviorBase **AccessBehaviors();
|
||||
@ -913,6 +925,20 @@ inline bool CAI_BehaviorBase::BridgeCanUnholsterWeapon( void )
|
||||
{
|
||||
return CanUnholsterWeapon();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline bool CAI_BehaviorBase::BridgeShouldPickADeathPose( void )
|
||||
{
|
||||
return ShouldPickADeathPose();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline bool CAI_BehaviorBase::BridgeCanTranslateCrouchActivity( void )
|
||||
{
|
||||
return CanTranslateCrouchActivity();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1498,6 +1524,22 @@ inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_CanUnholsterWeapon( void )
|
||||
{
|
||||
return BaseClass::CanUnholsterWeapon();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template <class BASE_NPC>
|
||||
inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_ShouldPickADeathPose( void )
|
||||
{
|
||||
return BaseClass::ShouldPickADeathPose();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template <class BASE_NPC>
|
||||
inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_CanTranslateCrouchActivity( void )
|
||||
{
|
||||
return BaseClass::CanTranslateCrouchActivity();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------
|
||||
@ -1914,6 +1956,28 @@ inline bool CAI_BehaviorHost<BASE_NPC>::CanUnholsterWeapon( void )
|
||||
|
||||
return BaseClass::CanUnholsterWeapon();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template <class BASE_NPC>
|
||||
inline bool CAI_BehaviorHost<BASE_NPC>::ShouldPickADeathPose( void )
|
||||
{
|
||||
if (m_pCurBehavior)
|
||||
return m_pCurBehavior->BridgeShouldPickADeathPose();
|
||||
|
||||
return BaseClass::ShouldPickADeathPose();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template <class BASE_NPC>
|
||||
inline bool CAI_BehaviorHost<BASE_NPC>::CanTranslateCrouchActivity( void )
|
||||
{
|
||||
if (m_pCurBehavior)
|
||||
return m_pCurBehavior->BridgeCanTranslateCrouchActivity();
|
||||
|
||||
return BaseClass::CanTranslateCrouchActivity();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------
|
||||
|
@ -535,10 +535,11 @@ int CAI_StandoffBehavior::SelectScheduleCheckCover( void )
|
||||
{
|
||||
StandoffMsg( "Regulated to not shoot\n" );
|
||||
#ifdef MAPBASE
|
||||
if ( GetHintType() == HINT_TACTICAL_COVER_LOW || GetHintType() == HINT_TACTICAL_COVER_MED )
|
||||
#else
|
||||
if ( GetHintType() == HINT_TACTICAL_COVER_LOW )
|
||||
if ( GetHintType() == HINT_TACTICAL_COVER_MED || GetCoverActivity() == ACT_COVER_MED )
|
||||
SetPosture( AIP_CROUCHING_MED );
|
||||
else
|
||||
#endif
|
||||
if ( GetHintType() == HINT_TACTICAL_COVER_LOW )
|
||||
SetPosture( AIP_CROUCHING );
|
||||
else
|
||||
SetPosture( AIP_STANDING );
|
||||
@ -557,7 +558,11 @@ int CAI_StandoffBehavior::SelectScheduleEstablishAim( void )
|
||||
{
|
||||
if ( HasCondition( COND_ENEMY_OCCLUDED ) )
|
||||
{
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
if ( GetPosture() == AIP_CROUCHING || GetPosture() == AIP_CROUCHING_MED )
|
||||
#else
|
||||
if ( GetPosture() == AIP_CROUCHING )
|
||||
#endif
|
||||
{
|
||||
// force a stand up, just in case
|
||||
GetOuter()->SpeakSentence( STANDOFF_SENTENCE_STAND_CHECK_TARGET );
|
||||
@ -668,6 +673,15 @@ Activity CAI_MappedActivityBehavior_Temporary::GetMappedActivity( AI_Posture_t p
|
||||
{
|
||||
if ( posture != AIP_STANDING )
|
||||
{
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
// See UpdateTranslateActivityMap() for more information on what this is for
|
||||
if ( posture == AIP_CROUCHING_MED )
|
||||
{
|
||||
if (activity != ACT_RANGE_ATTACK1)
|
||||
posture = AIP_CROUCHING;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned short iActivityTranslation = m_ActivityMap.Find( MAKE_ACTMAP_KEY( posture, activity ) );
|
||||
if ( iActivityTranslation != m_ActivityMap.InvalidIndex() )
|
||||
{
|
||||
@ -685,10 +699,28 @@ Activity CAI_StandoffBehavior::NPC_TranslateActivity( Activity activity )
|
||||
Activity coverActivity = GetCoverActivity();
|
||||
if ( coverActivity != ACT_INVALID )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if ( GetPosture() == AIP_STANDING )
|
||||
{
|
||||
if ( coverActivity == ACT_COVER_LOW )
|
||||
SetPosture( AIP_CROUCHING );
|
||||
else if ( coverActivity == ACT_COVER_MED )
|
||||
{
|
||||
SetPosture( AIP_CROUCHING_MED );
|
||||
coverActivity = ACT_COVER_LOW;
|
||||
}
|
||||
}
|
||||
else if (coverActivity == ACT_COVER_MED)
|
||||
coverActivity = ACT_COVER_LOW;
|
||||
|
||||
if ( activity == ACT_IDLE )
|
||||
activity = coverActivity;
|
||||
#else
|
||||
if (activity == ACT_IDLE)
|
||||
activity = coverActivity;
|
||||
if ( GetPosture() == AIP_STANDING && coverActivity == ACT_COVER_LOW )
|
||||
SetPosture( AIP_CROUCHING );
|
||||
#endif
|
||||
}
|
||||
|
||||
Activity result = GetMappedActivity( GetPosture(), activity );
|
||||
@ -1089,12 +1121,25 @@ void CAI_StandoffBehavior::UnlockHintNode()
|
||||
|
||||
Activity CAI_StandoffBehavior::GetCoverActivity()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// This does two things:
|
||||
// A. Allows medium cover nodes to be used, kind of.
|
||||
// B. GetCoverActivity() already checks everything we checked here.
|
||||
Activity coveract = GetOuter()->GetCoverActivity( GetHintNode() );
|
||||
return coveract == ACT_IDLE ? ACT_INVALID : coveract;
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
// GetCoverActivity() already checks everything we checked here.
|
||||
Activity coverActivity = GetOuter()->GetCoverActivity( GetHintNode() );
|
||||
|
||||
if (coverActivity == ACT_COVER_LOW)
|
||||
{
|
||||
// Check if this node will block our line of sight if aiming low.
|
||||
Vector vHintPos, vHintForward, vHintRight;
|
||||
GetHintNode()->GetPosition( GetHullType(), &vHintPos );
|
||||
vHintForward = GetHintNode()->GetDirection();
|
||||
|
||||
GetHintNode()->GetVectors( NULL, &vHintRight, NULL );
|
||||
if (GetOuter()->CouldShootIfCrouchingAt( vHintPos, vHintForward, vHintRight ))
|
||||
{
|
||||
coverActivity = ACT_COVER_MED;
|
||||
}
|
||||
}
|
||||
|
||||
return coverActivity == ACT_IDLE ? ACT_INVALID : coverActivity;
|
||||
#else
|
||||
CAI_Hint *pHintNode = GetHintNode();
|
||||
if ( pHintNode && pHintNode->HintType() == HINT_TACTICAL_COVER_LOW )
|
||||
@ -1112,6 +1157,14 @@ struct AI_ActivityMapping_t
|
||||
Activity activity;
|
||||
const char * pszWeapon;
|
||||
Activity translation;
|
||||
#ifdef MAPBASE
|
||||
Activity backup;
|
||||
|
||||
AI_ActivityMapping_t( AI_Posture_t _p, Activity _a, const char *_w, Activity _t, Activity _b = ACT_INVALID )
|
||||
{
|
||||
posture = _p; activity = _a; pszWeapon = _w; translation = _t; backup = _b;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
|
||||
@ -1125,15 +1178,60 @@ void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
|
||||
{ AIP_CROUCHING, ACT_WALK_AIM, NULL, ACT_WALK_CROUCH_AIM, },
|
||||
{ AIP_CROUCHING, ACT_RUN_AIM, NULL, ACT_RUN_CROUCH_AIM, },
|
||||
{ AIP_CROUCHING, ACT_RELOAD, NULL, ACT_RELOAD_LOW, },
|
||||
#ifdef MAPBASE
|
||||
{ AIP_CROUCHING, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_LOW, },
|
||||
{ AIP_CROUCHING, ACT_COVER_MED, NULL, ACT_COVER_LOW, },
|
||||
#else
|
||||
{ AIP_CROUCHING, ACT_RANGE_ATTACK_SMG1, NULL, ACT_RANGE_ATTACK_SMG1_LOW, },
|
||||
{ AIP_CROUCHING, ACT_RANGE_ATTACK_AR2, NULL, ACT_RANGE_ATTACK_AR2_LOW, },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
//
|
||||
// ============ Really long explanation that should be in a wiki/documentation article somewhere ~ Blixibon, 10/27/2021 ============
|
||||
//
|
||||
// Standoff behavior assumes low attack animations allow NPCs to see over barricades, with ACT_COVER_LOW being their "safely in cover" animation.
|
||||
// This is why AIP_CROUCHING translates ACT_RANGE_ATTACK1 to its low animation, but translates ACT_IDLE_ANGRY to ACT_COVER_LOW instead of ACT_RANGE_AIM_LOW,
|
||||
// as this would ideally allow NPCs to pop in and out of cover to shoot.
|
||||
// This is also why AIP_PEEKING translates ACT_COVER_LOW to ACT_RANGE_AIM_LOW, as it's supposed to force the NPC to peek over their cover.
|
||||
//
|
||||
// However, this assumption mainly just applies to metrocops. Citizens' low attacking animations crouch low to the ground (which isn't effective for
|
||||
// shooting over most barricades) and, while they do have a distinct ACT_COVER_LOW animation with transitions, they are close enough together that popping
|
||||
// in and out of cover is redundant in most cases. Meanwhile, Combine soldiers have identical ACT_COVER_LOW and ACT_RANGE_AIM_LOW animations, which means
|
||||
// they do not pop in and out of cover and AIP_PEEKING does nothing. This may be the reason why Combine soldiers occasionally get stuck in cover after a fight.
|
||||
//
|
||||
// -------------------------------------------------------------
|
||||
//
|
||||
// As part of Mapbase v7.0's NPC activity overhaul, a new "medium cover" activity set has been added. Metrocops' previous "low cover" animation set (which, as
|
||||
// mentioned before, is different from that of other NPCs) has been retroactively changed to use "medium cover". This was done for a few reasons unrelated to
|
||||
// standoff behavior, but the important point is that these activities indicate a new cover height. This means we can use them to give standoff behavior more leeway
|
||||
// for judging which animations to use in various levels of cover.
|
||||
//
|
||||
// Standoff behavior can use "medium cover" animations in cover which is too high for the "low" animations, and when the medium cover animations are not available,
|
||||
// it simply falls back to the "standing" animations, thus resolving the issue with other NPCs not peeking in and out of cover without requiring new medium cover
|
||||
// animations.
|
||||
//
|
||||
// In Mapbase, this is done by changing AIP_PEEKING to use the medium cover animations and adding a new alternate crouching posture posture called "AIP_CROUCHING_MED",
|
||||
// which only uses the medium cover attack activity and otherwise automatically falls back to AIP_CROUCHING. AIP_CROUCHING_MED is automatically set if the NPC cannot
|
||||
// get LOS from a regular crouching position.
|
||||
//
|
||||
{ AIP_CROUCHING_MED, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_MED, },
|
||||
|
||||
//----
|
||||
{ AIP_PEEKING, ACT_IDLE, NULL, ACT_RANGE_AIM_MED, },
|
||||
{ AIP_PEEKING, ACT_IDLE_ANGRY, NULL, ACT_RANGE_AIM_MED, },
|
||||
{ AIP_PEEKING, ACT_COVER_LOW, NULL, ACT_RANGE_AIM_MED, ACT_IDLE_ANGRY },
|
||||
{ AIP_PEEKING, ACT_COVER_MED, NULL, ACT_RANGE_AIM_MED, ACT_IDLE_ANGRY },
|
||||
{ AIP_PEEKING, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_MED, },
|
||||
{ AIP_PEEKING, ACT_RELOAD, NULL, ACT_RELOAD_LOW, },
|
||||
#else
|
||||
//----
|
||||
{ AIP_PEEKING, ACT_IDLE, NULL, ACT_RANGE_AIM_LOW, },
|
||||
{ AIP_PEEKING, ACT_IDLE_ANGRY, NULL, ACT_RANGE_AIM_LOW, },
|
||||
{ AIP_PEEKING, ACT_COVER_LOW, NULL, ACT_RANGE_AIM_LOW, },
|
||||
{ AIP_PEEKING, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_LOW, },
|
||||
{ AIP_PEEKING, ACT_RELOAD, NULL, ACT_RELOAD_LOW, },
|
||||
#endif
|
||||
};
|
||||
|
||||
m_ActivityMap.RemoveAll();
|
||||
@ -1145,7 +1243,7 @@ void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
|
||||
if ( !mappings[i].pszWeapon || stricmp( mappings[i].pszWeapon, pszWeaponClass ) == 0 )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// Check backup activity
|
||||
// Check NPC backup activity
|
||||
if ( HaveSequenceForActivity( mappings[i].translation ) || HaveSequenceForActivity( GetOuter()->Weapon_TranslateActivity( mappings[i].translation ) ) || HaveSequenceForActivity( GetOuter()->Weapon_BackupActivity( mappings[i].translation ) ) )
|
||||
#else
|
||||
if ( HaveSequenceForActivity( mappings[i].translation ) || HaveSequenceForActivity( GetOuter()->Weapon_TranslateActivity( mappings[i].translation ) ) )
|
||||
@ -1154,6 +1252,14 @@ void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
|
||||
Assert( m_ActivityMap.Find( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ) ) == m_ActivityMap.InvalidIndex() );
|
||||
m_ActivityMap.Insert( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ), mappings[i].translation );
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
// Check activity map backup activity
|
||||
else if ( mappings[i].backup != ACT_INVALID && HaveSequenceForActivity( mappings[i].backup ) )
|
||||
{
|
||||
Assert( m_ActivityMap.Find( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ) ) == m_ActivityMap.InvalidIndex() );
|
||||
m_ActivityMap.Insert( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ), mappings[i].backup );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,9 @@ enum AI_Posture_t
|
||||
AIP_INDIFFERENT,
|
||||
AIP_STANDING,
|
||||
AIP_CROUCHING,
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
AIP_CROUCHING_MED, // See UpdateTranslateActivityMap() for more information on what this is for
|
||||
#endif
|
||||
AIP_PEEKING,
|
||||
};
|
||||
|
||||
@ -149,6 +152,14 @@ protected:
|
||||
|
||||
// Standoff overrides base AI crouch handling
|
||||
bool IsCrouching( void ) { return false; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Standoff overrides base cover activity translation
|
||||
bool CanTranslateCrouchActivity( void ) { return false; }
|
||||
|
||||
// Don't do death poses while crouching
|
||||
bool ShouldPickADeathPose( void ) { return (GetPosture() != AIP_CROUCHING && GetPosture() != AIP_PEEKING) && BaseClass::ShouldPickADeathPose(); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
|
@ -1640,10 +1640,17 @@ void CAI_BlendedMotor::MaintainTurnActivity( void )
|
||||
|
||||
ConVar scene_flatturn( "scene_flatturn", "1" );
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar ai_turning_enabled( "ai_turning_enabled", "1", FCVAR_NONE, "Enables NPC turning, which was previously disabled by Valve at some point after 2004 due to a now-unknown major issue." );
|
||||
#endif
|
||||
|
||||
bool CAI_BlendedMotor::AddTurnGesture( float flYD )
|
||||
{
|
||||
|
||||
// some funky bug with human turn gestures, disable for now
|
||||
#ifdef MAPBASE
|
||||
if (!ai_turning_enabled.GetBool())
|
||||
#endif
|
||||
return false;
|
||||
|
||||
// try using a turn gesture
|
||||
|
@ -35,6 +35,10 @@ CHintCriteria::CHintCriteria( void )
|
||||
m_strGroup = NULL_STRING;
|
||||
m_iFlags = 0;
|
||||
m_HintTypes.Purge();
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
m_pfnFilter = NULL;
|
||||
m_pFilterContext = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1117,10 +1121,10 @@ void CAI_Hint::NPCHandleStartNav( CAI_BaseNPC *pNPC, bool bDefaultFacing )
|
||||
|
||||
HintIgnoreFacing_t facing = GetIgnoreFacing();
|
||||
if (facing == HIF_DEFAULT)
|
||||
facing = bDefaultFacing ? HIF_YES : HIF_NO;
|
||||
facing = bDefaultFacing ? HIF_NO : HIF_YES;
|
||||
|
||||
if (facing == HIF_YES)
|
||||
pNPC->GetNavigator()->SetArrivalDirection(GetDirection());
|
||||
if (facing == HIF_NO)
|
||||
pNPC->GetNavigator()->SetArrivalDirection( GetDirection() );
|
||||
|
||||
if (HintActivityName() != NULL_STRING)
|
||||
{
|
||||
@ -1139,6 +1143,51 @@ void CAI_Hint::NPCHandleStartNav( CAI_BaseNPC *pNPC, bool bDefaultFacing )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns true if this hint should override a NPC's yaw even during regular AI.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_Hint::OverridesNPCYaw( CAI_BaseNPC *pNPC )
|
||||
{
|
||||
switch (HintType())
|
||||
{
|
||||
case HINT_TACTICAL_COVER_CUSTOM:
|
||||
case HINT_TACTICAL_COVER_MED:
|
||||
case HINT_TACTICAL_COVER_LOW:
|
||||
{
|
||||
if (pNPC->HasMemory( bits_MEMORY_INCOVER ))
|
||||
{
|
||||
// By default, don't override yaw on cover nodes unless they use custom activities.
|
||||
HintIgnoreFacing_t facing = GetIgnoreFacing();
|
||||
if (facing == HIF_DEFAULT)
|
||||
return ( HintActivityName() != NULL_STRING );
|
||||
|
||||
return facing == HIF_NO;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case HINT_PLAYER_ALLY_MOVE_AWAY_DEST:
|
||||
{
|
||||
Vector vHintPos;
|
||||
GetPosition( pNPC, &vHintPos );
|
||||
if (VectorsAreEqual( vHintPos, pNPC->GetAbsOrigin(), 0.1f ))
|
||||
{
|
||||
// By default, don't override yaw on move away destinations unless they use custom activities.
|
||||
HintIgnoreFacing_t facing = GetIgnoreFacing();
|
||||
if (facing == HIF_DEFAULT)
|
||||
return ( HintActivityName() != NULL_STRING );
|
||||
|
||||
return facing == HIF_NO;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1258,6 +1307,30 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Test against generic filter
|
||||
// (From Alien Swarm SDK)
|
||||
if ( !hintCriteria.PassesFilter( this ) )
|
||||
{
|
||||
REPORTFAILURE( "Failed filter test" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// (From Alien Swarm SDK)
|
||||
int nRadius = GetRadius();
|
||||
if ( nRadius != 0 )
|
||||
{
|
||||
// Calculate our distance
|
||||
float distance = (GetAbsOrigin() - position).LengthSqr();
|
||||
|
||||
if ( distance > nRadius * nRadius )
|
||||
{
|
||||
REPORTFAILURE( "NPC is not within the node's radius." );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( hintCriteria.HasFlag(bits_HINT_NPC_IN_NODE_FOV) )
|
||||
{
|
||||
if ( pNPC == NULL )
|
||||
@ -1377,10 +1450,18 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
||||
{
|
||||
trace_t tr;
|
||||
// Can my bounding box fit there?
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
Vector vStep( 0, 0, pNPC->StepHeight() );
|
||||
AI_TraceHull ( GetAbsOrigin() + vStep, GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs() - vStep,
|
||||
MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction < 0.95 )
|
||||
#else
|
||||
AI_TraceHull ( GetAbsOrigin(), GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs(),
|
||||
MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction != 1.0 )
|
||||
#endif
|
||||
{
|
||||
REPORTFAILURE( "Node isn't clear." );
|
||||
return false;
|
||||
@ -1396,6 +1477,15 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
||||
// Calculate our distance
|
||||
float distance = (GetAbsOrigin() - position).Length();
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Divide by hint weight
|
||||
float flWeight = GetHintWeight();
|
||||
if ( flWeight != 1.0f )
|
||||
{
|
||||
distance *= GetHintWeightInverse();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Must be closer than the current best
|
||||
if ( distance > *flNearestDistance )
|
||||
{
|
||||
@ -1576,6 +1666,14 @@ void CAI_Hint::OnRestore()
|
||||
m_NodeData.nNodeID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( m_NodeData.nWCNodeID );
|
||||
FixupTargetNode();
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_NodeData.flWeight != 0.0f && m_NodeData.flWeight != 1.0f)
|
||||
{
|
||||
// Re-invert the weight
|
||||
m_NodeData.flWeightInverse = 1.0f / m_NodeData.flWeight;
|
||||
}
|
||||
#endif
|
||||
|
||||
CAI_Node *pNode = GetNode();
|
||||
|
||||
if ( !pNode )
|
||||
@ -1751,6 +1849,11 @@ void CC_ai_drop_hint( const CCommand &args )
|
||||
nodeData.fIgnoreFacing = HIF_DEFAULT;
|
||||
nodeData.minState = NPC_STATE_IDLE;
|
||||
nodeData.maxState = NPC_STATE_COMBAT;
|
||||
#ifdef MAPBASE
|
||||
nodeData.nRadius = 0; // From Alien Swarm SDK
|
||||
nodeData.flWeight = 1.0f;
|
||||
nodeData.flWeightInverse = 1.0f;
|
||||
#endif
|
||||
CAI_Hint *pHint = CAI_HintManager::CreateHint( &nodeData, NULL );
|
||||
if ( pHint )
|
||||
{
|
||||
|
@ -112,6 +112,13 @@ enum Hint_e
|
||||
|
||||
// CS port hints
|
||||
HINT_CSTRIKE_HOSTAGE_ESCAPE = 1100,
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Mapbase hints
|
||||
// (these start at a high number to avoid potential conflicts with mod hints)
|
||||
|
||||
HINT_TACTICAL_COVER_CUSTOM = 10000, // Cover node with a custom hint activity (NPCs can take cover and reload here while playing said activity)
|
||||
#endif
|
||||
};
|
||||
const char *GetHintTypeDescription( Hint_e iHintType );
|
||||
const char *GetHintTypeDescription( CAI_Hint *pHint );
|
||||
@ -120,6 +127,10 @@ const char *GetHintTypeDescription( CAI_Hint *pHint );
|
||||
// CHintCriteria
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
typedef bool (*HintSearchFilterFunc_t)( void *pContext, CAI_Hint *pCandidate );
|
||||
#endif
|
||||
|
||||
class CHintCriteria
|
||||
{
|
||||
public:
|
||||
@ -134,6 +145,11 @@ public:
|
||||
void SetGroup( string_t group );
|
||||
string_t GetGroup( void ) const { return m_strGroup; }
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
void SetFilterFunc( HintSearchFilterFunc_t pfnFilter, void *pContext = NULL ) { m_pfnFilter = pfnFilter; m_pFilterContext = pContext; }
|
||||
bool PassesFilter( CAI_Hint *pCandidate ) const { return (m_pfnFilter) ? (*m_pfnFilter)(m_pFilterContext, pCandidate) : true; }
|
||||
#endif
|
||||
|
||||
int GetFirstHintType( void ) const { return m_iFirstHintType; }
|
||||
int GetLastHintType( void ) const { return m_iLastHintType; }
|
||||
bool MatchesHintType( int hintType ) const;
|
||||
@ -176,6 +192,11 @@ private:
|
||||
|
||||
zoneList_t m_zoneInclude;
|
||||
zoneList_t m_zoneExclude;
|
||||
|
||||
#ifdef MAPBASE
|
||||
HintSearchFilterFunc_t m_pfnFilter;
|
||||
void * m_pFilterContext;
|
||||
#endif
|
||||
};
|
||||
|
||||
class CAI_Node;
|
||||
@ -310,11 +331,21 @@ public:
|
||||
int GetNodeId() { return m_NodeData.nNodeID; }
|
||||
int GetWCId() { return m_NodeData.nWCNodeID; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
int GetRadius() const { return m_NodeData.nRadius; } // From Alien Swarm SDK
|
||||
|
||||
float GetHintWeight() const { return m_NodeData.flWeight; }
|
||||
float GetHintWeightInverse() const { return m_NodeData.flWeightInverse; } // Used to multiply distances
|
||||
#endif
|
||||
|
||||
bool HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, const Vector &position, float *flNearestDistance, bool bIgnoreLock = false, bool bIgnoreHintType = false );
|
||||
bool IsInNodeFOV( CBaseEntity *pOther );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void NPCHandleStartNav( CAI_BaseNPC *pNPC, bool bDefaultFacing );
|
||||
|
||||
// Returns true if this hint should override a NPC's yaw even during regular AI.
|
||||
bool OverridesNPCYaw( CAI_BaseNPC *pNPC );
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
|
@ -173,6 +173,10 @@ BEGIN_SIMPLE_DATADESC( HintNodeData )
|
||||
DEFINE_KEYFIELD( fIgnoreFacing, FIELD_INTEGER, "IgnoreFacing" ),
|
||||
DEFINE_KEYFIELD( minState, FIELD_INTEGER, "MinimumState" ),
|
||||
DEFINE_KEYFIELD( maxState, FIELD_INTEGER, "MaximumState" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( nRadius, FIELD_INTEGER, "radius" ), // From Alien Swarm SDK
|
||||
DEFINE_KEYFIELD( flWeight, FIELD_FLOAT, "hintweight" ),
|
||||
#endif
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
@ -205,6 +209,17 @@ int CNodeEnt::Spawn( const char *pMapData )
|
||||
m_NodeData.minState = NPC_STATE_IDLE;
|
||||
if ( m_NodeData.maxState == NPC_STATE_NONE )
|
||||
m_NodeData.maxState = NPC_STATE_COMBAT;
|
||||
#ifdef MAPBASE
|
||||
if (m_NodeData.flWeight == 0.0f)
|
||||
{
|
||||
m_NodeData.flWeight = 1.0f;
|
||||
}
|
||||
else if (m_NodeData.flWeight != 1.0f)
|
||||
{
|
||||
// Invert the weight so that it could be used as a direct multiplier for distances, etc.
|
||||
m_NodeData.flWeightInverse = 1.0f / m_NodeData.flWeight;
|
||||
}
|
||||
#endif
|
||||
// ---------------------------------------------------------------------------------
|
||||
// If just a hint node (not used for navigation) just create a hint and bail
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
@ -42,6 +42,11 @@ struct HintNodeData
|
||||
HintIgnoreFacing_t fIgnoreFacing;
|
||||
NPC_STATE minState;
|
||||
NPC_STATE maxState;
|
||||
#ifdef MAPBASE
|
||||
int nRadius; // From Alien Swarm SDK
|
||||
float flWeight;
|
||||
float flWeightInverse; // Not saved
|
||||
#endif
|
||||
|
||||
int nWCNodeID; // Node ID assigned by worldcraft (not same as engine!)
|
||||
|
||||
|
@ -14,6 +14,9 @@
|
||||
#include "ai_basenpc.h"
|
||||
#include "ai_localnavigator.h"
|
||||
#include "ai_moveprobe.h"
|
||||
#ifdef MAPBASE
|
||||
#include "ai_hint.h"
|
||||
#endif
|
||||
#include "saverestore_utlvector.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
@ -235,18 +238,47 @@ void CAI_Motor::MoveClimbStart( const Vector &climbDest, const Vector &climbDir
|
||||
// > code are not reciprocal for all state, and furthermore, stomp
|
||||
// > other state?
|
||||
|
||||
bool bGoingUp = (climbDir.z > 0.01);
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ( bGoingUp && GetOuter()->HaveSequenceForActivity( ACT_CLIMB_MOUNT_BOTTOM ) )
|
||||
{
|
||||
SetActivity( ACT_CLIMB_MOUNT_BOTTOM );
|
||||
|
||||
// Steal m_vecDismount for this
|
||||
GetOuter()->GetSequenceLinearMotion( GetSequence(), &m_vecDismount );
|
||||
GetOuter()->SetCycle( GetOuter()->GetMovementFrame( m_vecDismount.z - climbDist ) );
|
||||
}
|
||||
else if ( !bGoingUp && GetOuter()->HaveSequenceForActivity( ACT_CLIMB_MOUNT_TOP ) )
|
||||
{
|
||||
SetActivity( ACT_CLIMB_MOUNT_TOP );
|
||||
|
||||
// Steal m_vecDismount for this
|
||||
GetOuter()->GetSequenceLinearMotion( GetSequence(), &m_vecDismount );
|
||||
GetOuter()->SetCycle( GetOuter()->GetMovementFrame( m_vecDismount.z - climbDist ) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ( fabsf( climbDir.z ) < .1 )
|
||||
{
|
||||
SetActivity( GetNavigator()->GetMovementActivity() );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetActivity( (climbDir.z > -0.01 ) ? ACT_CLIMB_UP : ACT_CLIMB_DOWN );
|
||||
SetActivity( bGoingUp ? ACT_CLIMB_UP : ACT_CLIMB_DOWN );
|
||||
}
|
||||
|
||||
m_nDismountSequence = SelectWeightedSequence( ACT_CLIMB_DISMOUNT );
|
||||
if (m_nDismountSequence != ACT_INVALID)
|
||||
{
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ( !bGoingUp )
|
||||
{
|
||||
int nBottomDismount = SelectWeightedSequence( ACT_CLIMB_DISMOUNT_BOTTOM );
|
||||
if (nBottomDismount != ACTIVITY_NOT_AVAILABLE)
|
||||
m_nDismountSequence = nBottomDismount;
|
||||
}
|
||||
#endif
|
||||
|
||||
GetOuter()->GetSequenceLinearMotion( m_nDismountSequence, &m_vecDismount );
|
||||
}
|
||||
else
|
||||
@ -262,6 +294,76 @@ void CAI_Motor::MoveClimbStart( const Vector &climbDest, const Vector &climbDir
|
||||
|
||||
AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw, int climbNodesLeft )
|
||||
{
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ( (GetActivity() == ACT_CLIMB_MOUNT_TOP || GetActivity() == ACT_CLIMB_MOUNT_BOTTOM) )
|
||||
{
|
||||
if (!GetOuter()->IsActivityFinished())
|
||||
{
|
||||
// Wait for the mounting to finish
|
||||
SetGroundEntity( NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fix up our position if we have to
|
||||
Vector vecTeleportOrigin;
|
||||
if (MoveClimbShouldTeleportToSequenceEnd( vecTeleportOrigin ))
|
||||
{
|
||||
SetLocalOrigin( vecTeleportOrigin );
|
||||
}
|
||||
|
||||
// Reset activity and start from the beginning
|
||||
GetOuter()->ResetActivity();
|
||||
return MoveClimbExecute( climbDest, climbDir, climbDist, yaw, climbNodesLeft );
|
||||
}
|
||||
}
|
||||
else if ( fabsf( climbDir.z ) > .1 && (GetActivity() != ACT_CLIMB_DISMOUNT && GetActivity() != ACT_CLIMB_DISMOUNT_BOTTOM) )
|
||||
{
|
||||
bool bGoingUp = (climbDir.z > -0.01);
|
||||
if ( GetOuter()->HaveSequenceForActivity( ACT_CLIMB_ALL ) )
|
||||
{
|
||||
SetActivity( ACT_CLIMB_ALL );
|
||||
|
||||
// TODO: Use UTIL_VecToPitch() instead if move_yaw becomes a true climb yaw and not just an up-down scalar
|
||||
SetPoseParameter( GetOuter()->LookupPoseMoveYaw(), climbDir.z < 0 ? 180.0 : -180.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
Activity desiredActivity = bGoingUp ? ACT_CLIMB_UP : ACT_CLIMB_DOWN;
|
||||
if ( GetActivity() != desiredActivity )
|
||||
{
|
||||
SetActivity( desiredActivity );
|
||||
}
|
||||
}
|
||||
|
||||
if (m_nDismountSequence != ACT_INVALID)
|
||||
{
|
||||
if (climbNodesLeft <= 2 && climbDist < fabs( m_vecDismount.z ))
|
||||
{
|
||||
if (bGoingUp)
|
||||
{
|
||||
// fixme: No other way to force m_nIdealSequence?
|
||||
GetOuter()->SetActivity( ACT_CLIMB_DISMOUNT );
|
||||
GetOuter()->SetCycle( GetOuter()->GetMovementFrame( m_vecDismount.z - climbDist ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetSequence() != m_nDismountSequence && GetOuter()->GetSequenceActivity( m_nDismountSequence ) == ACT_CLIMB_DISMOUNT_BOTTOM)
|
||||
{
|
||||
SetActivity( ACT_CLIMB_DISMOUNT_BOTTOM );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( climbDir.Length() == 0 && GetOuter()->GetInstantaneousVelocity() <= 0.01 )
|
||||
{
|
||||
// The NPC is somehow stuck climbing with no direction or movement.
|
||||
// This can be caused by NPCs getting stuck in each other and/or being moved away from the ladder.
|
||||
// In these cases, the NPC has to be made unstuck, or else they may remain in an immobile climbing state forever.
|
||||
Warning( "%s had to abort climbing due to no direction or movement\n", GetOuter()->GetDebugName() );
|
||||
return AIMR_ILLEGAL;
|
||||
}
|
||||
#else
|
||||
if ( fabsf( climbDir.z ) > .1 )
|
||||
{
|
||||
if ( GetActivity() != ACT_CLIMB_DISMOUNT )
|
||||
@ -292,13 +394,34 @@ AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vecto
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
float climbSpeed = GetOuter()->GetInstantaneousVelocity();
|
||||
|
||||
if (m_nDismountSequence != ACT_INVALID)
|
||||
{
|
||||
// catch situations where the climb mount/dismount finished before reaching goal
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ((GetActivity() == ACT_CLIMB_DISMOUNT || GetActivity() == ACT_CLIMB_DISMOUNT_BOTTOM))
|
||||
{
|
||||
SetGroundEntity( NULL );
|
||||
|
||||
if (GetOuter()->IsActivityFinished())
|
||||
{
|
||||
// Fix up our position if we have to
|
||||
Vector vecTeleportOrigin;
|
||||
if (MoveClimbShouldTeleportToSequenceEnd( vecTeleportOrigin ))
|
||||
{
|
||||
// Just force it to complete
|
||||
climbDist = 0.0f;
|
||||
}
|
||||
|
||||
climbSpeed = 200.0f;
|
||||
}
|
||||
}
|
||||
#else
|
||||
climbSpeed = MAX( climbSpeed, 30.0 );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -314,7 +437,7 @@ AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vecto
|
||||
climbDist = 0;
|
||||
|
||||
const float climbTime = climbDist / climbSpeed;
|
||||
|
||||
|
||||
SetMoveInterval( GetMoveInterval() - climbTime );
|
||||
SetLocalOrigin( climbDest );
|
||||
|
||||
@ -330,6 +453,20 @@ AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vecto
|
||||
// --------------------------------------------
|
||||
SetIdealYawAndUpdate( yaw );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Lock the yaw if we're in position
|
||||
if ( UTIL_AngleMod( yaw ) == UTIL_AngleMod( GetLocalAngles().y ) )
|
||||
{
|
||||
SetYawLocked( true );
|
||||
}
|
||||
else if ( IsYawLocked() )
|
||||
{
|
||||
// We're in a different position now. Unlock the yaw and update it
|
||||
SetYawLocked( false );
|
||||
UpdateYaw( -1 );
|
||||
}
|
||||
#endif
|
||||
|
||||
return AIMR_OK;
|
||||
}
|
||||
|
||||
@ -340,11 +477,62 @@ void CAI_Motor::MoveClimbStop()
|
||||
else
|
||||
SetActivity( ACT_IDLE );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Unlock desired weapon state so NPCs can unholster their weapons again.
|
||||
GetOuter()->SetDesiredWeaponState( DESIREDWEAPONSTATE_IGNORE );
|
||||
|
||||
// Unlock yaw
|
||||
SetYawLocked( false );
|
||||
#endif
|
||||
|
||||
GetOuter()->RemoveFlag( FL_FLY );
|
||||
SetSmoothedVelocity( vec3_origin );
|
||||
SetGravity( 1.0 );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CAI_Motor::MoveClimbPause()
|
||||
{
|
||||
if (GetActivity() != ACT_CLIMB_DISMOUNT
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
&& GetActivity() != ACT_CLIMB_MOUNT_TOP && GetActivity() != ACT_CLIMB_MOUNT_BOTTOM
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if ( GetActivity() == ACT_CLIMB_ALL )
|
||||
{
|
||||
SetPoseParameter( GetOuter()->LookupPoseMoveYaw(), 0.0f );
|
||||
}
|
||||
|
||||
SetSmoothedVelocity( vec3_origin );
|
||||
}
|
||||
else
|
||||
{
|
||||
// If already dismounting, do nothing
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This is part of a hack needed in cases where ladder mount/dismount animations collide with the world and don't move properly.
|
||||
// It's based off of the same code as scripted_sequence's teleportation fixup, although this function only resolves the bone origin and
|
||||
// returns whether or not teleportation is necessary, as the teleportation is achieved in different ways for different uses of this code.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_Motor::MoveClimbShouldTeleportToSequenceEnd( Vector &teleportOrigin )
|
||||
{
|
||||
QAngle new_angle;
|
||||
GetOuter()->GetBonePosition( 0, teleportOrigin, new_angle );
|
||||
|
||||
// Ensure that there is actually a distance needed to teleport there
|
||||
if ((GetLocalOrigin() - teleportOrigin).Length2DSqr() > Square( 8.0 ))
|
||||
{
|
||||
teleportOrigin.z = GetLocalOrigin().z;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Motion for jumping
|
||||
// Input :
|
||||
@ -651,9 +839,20 @@ void CAI_Motor::MoveFacing( const AILocalMoveGoal_t &move )
|
||||
{
|
||||
// FIXME: move this up to navigator so that path goals can ignore these overrides.
|
||||
Vector dir;
|
||||
float flInfluence = GetFacingDirection( dir );
|
||||
dir = move.facing * (1 - flInfluence) + dir * flInfluence;
|
||||
VectorNormalize( dir );
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (IsDeceleratingToGoal() && (GetOuter()->GetHintNode() /*|| GetOuter()->m_hOpeningDoor*/))
|
||||
{
|
||||
// Don't let the facing queue interfere with arrival direction in important cases
|
||||
dir = move.facing;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
float flInfluence = GetFacingDirection( dir );
|
||||
dir = move.facing * (1 - flInfluence) + dir * flInfluence;
|
||||
VectorNormalize( dir );
|
||||
}
|
||||
|
||||
// ideal facing direction
|
||||
float idealYaw = UTIL_AngleMod( UTIL_VecToYaw( dir ) );
|
||||
|
@ -62,6 +62,10 @@ public:
|
||||
virtual void MoveClimbStart( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw );
|
||||
virtual AIMoveResult_t MoveClimbExecute( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw, int climbNodesLeft );
|
||||
virtual void MoveClimbStop();
|
||||
#ifdef MAPBASE
|
||||
virtual void MoveClimbPause();
|
||||
virtual bool MoveClimbShouldTeleportToSequenceEnd( Vector &teleportOrigin );
|
||||
#endif
|
||||
|
||||
//---------------------------------
|
||||
|
||||
@ -83,6 +87,9 @@ public:
|
||||
const Vector & GetCurVel() const { return m_vecVelocity; }
|
||||
|
||||
virtual float OverrideMaxYawSpeed( Activity activity ) { return -1; }
|
||||
#ifdef MAPBASE
|
||||
virtual
|
||||
#endif
|
||||
bool IsDeceleratingToGoal() const { return false; }
|
||||
|
||||
//---------------------------------
|
||||
|
@ -999,12 +999,23 @@ int CAI_Navigator::GetArrivalSequence( int curSequence )
|
||||
activity = ACT_IDLE;
|
||||
}
|
||||
|
||||
sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( activity ), curSequence );
|
||||
Activity translatedActivity = GetOuter()->TranslateActivity( activity );
|
||||
sequence = GetOuter()->SelectWeightedSequence( translatedActivity, curSequence );
|
||||
|
||||
if ( sequence == ACT_INVALID )
|
||||
{
|
||||
DevMsg( GetOuter(), "No appropriate sequence for arrival activity %s (%d)\n", GetOuter()->GetActivityName( GetPath()->GetArrivalActivity() ), GetPath()->GetArrivalActivity() );
|
||||
sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( ACT_IDLE ), curSequence );
|
||||
#ifdef MAPBASE
|
||||
if ( translatedActivity == ACT_SCRIPT_CUSTOM_MOVE )
|
||||
{
|
||||
// ACT_SCRIPT_CUSTOM_MOVE allows activity translation to resolve into specific sequences
|
||||
sequence = GetOuter()->GetScriptCustomMoveSequence();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
DevMsg( GetOuter(), "No appropriate sequence for arrival activity %s (%d)\n", GetOuter()->GetActivityName( GetPath()->GetArrivalActivity() ), GetPath()->GetArrivalActivity() );
|
||||
sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( ACT_IDLE ), curSequence );
|
||||
}
|
||||
}
|
||||
Assert( sequence != ACT_INVALID );
|
||||
GetPath()->SetArrivalSequence( sequence );
|
||||
@ -1642,6 +1653,15 @@ void CAI_Navigator::MoveCalcBaseGoal( AILocalMoveGoal_t *pMoveGoal )
|
||||
AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint();
|
||||
if ( pCurWaypoint->GetNext() && pCurWaypoint->GetNext()->NavType() != pCurWaypoint->NavType() )
|
||||
pMoveGoal->flags |= AILMG_TARGET_IS_TRANSITION;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// TODO: Better place for this code?
|
||||
if (pMoveGoal->flags & AILMG_TARGET_IS_TRANSITION && pCurWaypoint->GetNext()->NavType() == NAV_CLIMB)
|
||||
{
|
||||
// NPCs need to holster their weapons before climbing.
|
||||
GetOuter()->SetDesiredWeaponState( DESIREDWEAPONSTATE_HOLSTERED );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const Task_t *pCurTask = GetOuter()->GetTask();
|
||||
@ -2164,11 +2184,26 @@ bool CAI_Navigator::OnMoveBlocked( AIMoveResult_t *pResult )
|
||||
if (pDoor != NULL)
|
||||
{
|
||||
GetOuter()->OpenPropDoorBegin( pDoor );
|
||||
#ifdef MAPBASE
|
||||
// Tell the navigation to stop running until we're done.
|
||||
OnNewGoal();
|
||||
#endif
|
||||
*pResult = AIMR_OK;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( GetOuter()->m_hOpeningDoor )
|
||||
{
|
||||
// In the process of opening a door
|
||||
// Because navigation is now supposed to terminate when a NPC begins opening a door, this code should not be reached.
|
||||
DbgNavMsg( GetOuter(), "CAI_Navigator::OnMoveBlocked had to check for m_hOpeningDoor\n" );
|
||||
*pResult = AIMR_OK;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Allow the NPC to override this behavior
|
||||
if ( GetOuter()->OnMoveBlocked( pResult ))
|
||||
@ -2591,8 +2626,12 @@ bool CAI_Navigator::Move( float flInterval )
|
||||
|
||||
if ( GetNavType() == NAV_CLIMB )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
GetMotor()->MoveClimbPause();
|
||||
#else
|
||||
GetMotor()->MoveClimbStop();
|
||||
SetNavType( NAV_GROUND );
|
||||
#endif
|
||||
}
|
||||
GetMotor()->MoveStop();
|
||||
AssertMsg( TaskIsRunning() || TaskIsComplete(), ("Schedule stalled!!\n") );
|
||||
@ -2695,6 +2734,11 @@ void CAI_Navigator::AdvancePath()
|
||||
if (pDoor != NULL)
|
||||
{
|
||||
GetOuter()->OpenPropDoorBegin(pDoor);
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Tell the navigation to stop running until we're done.
|
||||
OnNewGoal();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3880,7 +3924,12 @@ bool CAI_Navigator::GetStoppingPath( CAI_WaypointList * pClippedWaypoints )
|
||||
AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint();
|
||||
if ( pCurWaypoint )
|
||||
{
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
// Since regular climb nav can interrupt itself now, only do this when dismounting
|
||||
bool bMustCompleteCurrent = ( (pCurWaypoint->NavType() == NAV_CLIMB && (GetActivity() == ACT_CLIMB_DISMOUNT || GetActivity() == ACT_CLIMB_MOUNT_TOP)) || pCurWaypoint->NavType() == NAV_JUMP );
|
||||
#else
|
||||
bool bMustCompleteCurrent = ( pCurWaypoint->NavType() == NAV_CLIMB || pCurWaypoint->NavType() == NAV_JUMP );
|
||||
#endif
|
||||
float distRemaining = GetMotor()->MinStoppingDist( 0 );
|
||||
|
||||
if ( bMustCompleteCurrent )
|
||||
|
@ -144,6 +144,31 @@ public:
|
||||
int m_capabilities; // cache this
|
||||
};
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-------------------------------------
|
||||
// Purpose: A version of CNodeFilter which allows hints to influence the result.
|
||||
//-------------------------------------
|
||||
class CNodeHintFilter : public CNodeFilter
|
||||
{
|
||||
public:
|
||||
CNodeHintFilter( CAI_BaseNPC *pNPC, const Vector &pos ) : CNodeFilter( pNPC, pos ) {}
|
||||
CNodeHintFilter( const Vector &pos ) : CNodeFilter( pos ) {}
|
||||
|
||||
virtual float NodeDistanceSqr( CAI_Node &node )
|
||||
{
|
||||
// Heavier hints are considered closer
|
||||
if ( node.GetHint() && node.GetHint()->GetHintWeight() != 1.0f && (node.GetHint()->GetGroup() == NULL_STRING || node.GetHint()->GetGroup() == m_pNPC->GetHintGroup()) )
|
||||
{
|
||||
return CNodeFilter::NodeDistanceSqr( node ) * node.GetHint()->GetHintWeightInverse();
|
||||
}
|
||||
else
|
||||
{
|
||||
return CNodeFilter::NodeDistanceSqr( node );
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAI_Network
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -351,7 +376,12 @@ int CAI_Network::NearestNodeToPoint( CAI_BaseNPC *pNPC, const Vector &vecOrigin,
|
||||
// First get nodes distances and eliminate those that are beyond
|
||||
// the maximum allowed distance for local movements
|
||||
// ---------------------------------------------------------------
|
||||
#ifdef MAPBASE
|
||||
// Allow hint weight to influence supposed distance
|
||||
CNodeHintFilter filter( pNPC, vecOrigin );
|
||||
#else
|
||||
CNodeFilter filter( pNPC, vecOrigin );
|
||||
#endif
|
||||
|
||||
#ifdef AI_PERF_MON
|
||||
m_nPerfStatNN++;
|
||||
@ -605,8 +635,13 @@ CAI_Node *CAI_Network::AddNode( const Vector &origin, float yaw )
|
||||
|
||||
CAI_Link *CAI_Network::CreateLink( int srcID, int destID, CAI_DynamicLink *pDynamicLink )
|
||||
{
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
CAI_Node *pSrcNode = GetNode( srcID );
|
||||
CAI_Node *pDestNode = GetNode( destID );
|
||||
#else
|
||||
CAI_Node *pSrcNode = g_pBigAINet->GetNode( srcID );
|
||||
CAI_Node *pDestNode = g_pBigAINet->GetNode( destID );
|
||||
#endif
|
||||
|
||||
Assert( pSrcNode && pDestNode && pSrcNode != pDestNode );
|
||||
|
||||
|
@ -411,7 +411,12 @@ int CAI_TacticalServices::FindCoverNode(const Vector &vNearPos, const Vector &vT
|
||||
// --------------------------------------------------------
|
||||
pNode->Lock( 1.0 );
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( pNode->GetHint() && ( pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_MED || pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_LOW
|
||||
|| pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_CUSTOM ) )
|
||||
#else
|
||||
if ( pNode->GetHint() && ( pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_MED || pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_LOW ) )
|
||||
#endif
|
||||
{
|
||||
if ( GetOuter()->GetHintNode() )
|
||||
{
|
||||
|
@ -61,11 +61,6 @@
|
||||
extern int g_interactionBarnacleVictimReleased;
|
||||
#endif //HL2_DLL
|
||||
|
||||
#ifdef MAPBASE
|
||||
extern acttable_t *GetSMG1Acttable();
|
||||
extern int GetSMG1ActtableCount();
|
||||
#endif
|
||||
|
||||
extern ConVar weapon_showproficiency;
|
||||
|
||||
ConVar ai_show_hull_attacks( "ai_show_hull_attacks", "0" );
|
||||
@ -2751,19 +2746,22 @@ Activity CBaseCombatCharacter::Weapon_BackupActivity( Activity activity, bool we
|
||||
return activity;
|
||||
}
|
||||
|
||||
acttable_t *pTable = GetSMG1Acttable();
|
||||
int actCount = GetSMG1ActtableCount();
|
||||
for ( int i = 0; i < actCount; i++, pTable++ )
|
||||
acttable_t *pTable = pWeapon->GetBackupActivityList();
|
||||
if (pTable)
|
||||
{
|
||||
if ( activity == pTable->baseAct )
|
||||
int actCount = pWeapon->GetBackupActivityListCount();
|
||||
for ( int i = 0; i < actCount; i++, pTable++ )
|
||||
{
|
||||
// Don't pick SMG animations we don't actually have an animation for.
|
||||
if (GetModelPtr() ? !GetModelPtr()->HaveSequenceForActivity(pTable->weaponAct) : false)
|
||||
if ( activity == pTable->baseAct )
|
||||
{
|
||||
return activity;
|
||||
}
|
||||
// Don't pick SMG animations we don't actually have an animation for.
|
||||
if (GetModelPtr() ? !GetModelPtr()->HaveSequenceForActivity(pTable->weaponAct) : false)
|
||||
{
|
||||
return activity;
|
||||
}
|
||||
|
||||
return (Activity)pTable->weaponAct;
|
||||
return (Activity)pTable->weaponAct;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,28 @@ bool CAI_FuncTankBehavior::IsInterruptable( void )
|
||||
|
||||
return BaseClass::IsInterruptable();
|
||||
}
|
||||
|
||||
ConVar ai_tank_allow_expanded_npcs( "ai_tank_allow_expanded_npcs", "1", FCVAR_NONE, "Allows Father Grigori, Barney, and vortigaunts to automatically man func_tanks." );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_FuncTankBehavior::CanManTank( CFuncTank *pTank, bool bForced )
|
||||
{
|
||||
if (!bForced)
|
||||
{
|
||||
// In order to prevent potential problems in existing maps, Father Grigori, Barney, and vortigaunts can be set to not automatically man func_tanks by default.
|
||||
if (ai_tank_allow_expanded_npcs.GetBool() == false)
|
||||
{
|
||||
const char *pszClass = GetOuter()->GetClassname();
|
||||
if ( FStrEq( pszClass, "npc_monk" ) || FStrEq( pszClass, "npc_barney" ) || FStrEq( pszClass, "npc_vortigaunt" ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -51,6 +51,8 @@ public:
|
||||
void PrescheduleThink();
|
||||
#ifdef MAPBASE
|
||||
bool IsInterruptable( void );
|
||||
|
||||
bool CanManTank( CFuncTank *pTank, bool bForced );
|
||||
#endif
|
||||
|
||||
Activity NPC_TranslateActivity( Activity activity );
|
||||
|
@ -402,7 +402,11 @@ void CFuncTank::InputFindNPCToManTank( inputdata_t &inputdata )
|
||||
{
|
||||
// Verify the npc has the func_tank controller behavior.
|
||||
CAI_FuncTankBehavior *pBehavior;
|
||||
#ifdef MAPBASE
|
||||
if ( pNPC->GetBehavior( &pBehavior ) && pBehavior->CanManTank( this, true ) )
|
||||
#else
|
||||
if ( pNPC->GetBehavior( &pBehavior ) )
|
||||
#endif
|
||||
{
|
||||
m_hController = pNPC;
|
||||
pBehavior->SetFuncTank( this );
|
||||
@ -439,7 +443,7 @@ void CFuncTank::InputTeleportNPCToManTank( inputdata_t &inputdata )
|
||||
{
|
||||
// Verify the npc has the func_tank controller behavior.
|
||||
CAI_FuncTankBehavior *pBehavior;
|
||||
if ( pNPC->GetBehavior( &pBehavior ) )
|
||||
if ( pNPC->GetBehavior( &pBehavior ) && pBehavior->CanManTank( this, true ) )
|
||||
{
|
||||
Vector vecVec;
|
||||
QAngle angAng;
|
||||
@ -512,7 +516,7 @@ void CFuncTank::InputForceNPCToManTank( inputdata_t &inputdata )
|
||||
{
|
||||
// Verify the npc has the func_tank controller behavior.
|
||||
CAI_FuncTankBehavior *pBehavior;
|
||||
if ( pNPC->GetBehavior( &pBehavior ) )
|
||||
if ( pNPC->GetBehavior( &pBehavior ) && pBehavior->CanManTank( this, true ) )
|
||||
{
|
||||
// Set the forced condition
|
||||
pBehavior->SetCondition( CAI_FuncTankBehavior::COND_FUNCTANK_FORCED );
|
||||
@ -627,7 +631,11 @@ void CFuncTank::NPC_FindController( void )
|
||||
continue;
|
||||
|
||||
CAI_FuncTankBehavior *pBehavior;
|
||||
#ifdef MAPBASE
|
||||
if ( pNPC->GetBehavior( &pBehavior ) && pBehavior->CanManTank( this, false ) )
|
||||
#else
|
||||
if ( pNPC->GetBehavior( &pBehavior ) )
|
||||
#endif
|
||||
{
|
||||
// Don't mount the func_tank if your "enemy" is within X feet or it or the npc.
|
||||
CBaseEntity *pEnemy = pNPC->GetEnemy();
|
||||
|
@ -156,6 +156,8 @@ ConVar npc_alyx_crouch( "npc_alyx_crouch", "1" );
|
||||
#ifdef MAPBASE
|
||||
ConVar npc_alyx_interact_manhacks( "npc_alyx_interact_manhacks", "1" );
|
||||
ConVar npc_alyx_interact_turrets( "npc_alyx_interact_turrets", "0" );
|
||||
|
||||
ConVar npc_alyx_allow_fly( "npc_alyx_allow_fly", "0", FCVAR_NONE, "Allows Alyx to use FL_FLY outside of scripted sequences, actbusy, or navigation." );
|
||||
#endif
|
||||
|
||||
// global pointer to Alyx for fast lookups
|
||||
@ -319,7 +321,9 @@ CNPC_Alyx *CNPC_Alyx::GetAlyx( void )
|
||||
//=========================================================
|
||||
bool CNPC_Alyx::CreateBehaviors()
|
||||
{
|
||||
#ifndef MAPBASE // Moved to CNPC_PlayerCompanion
|
||||
AddBehavior( &m_FuncTankBehavior );
|
||||
#endif
|
||||
bool result = BaseClass::CreateBehaviors();
|
||||
|
||||
return result;
|
||||
@ -885,7 +889,11 @@ void CNPC_Alyx::GatherConditions()
|
||||
|
||||
// ROBIN: This was here to solve a problem in a playtest. We've since found what we think was the cause.
|
||||
// It's a useful piece of debug to have lying there, so I've left it in.
|
||||
if ( (GetFlags() & FL_FLY) && m_NPCState != NPC_STATE_SCRIPT && !m_ActBusyBehavior.IsActive() && !m_PassengerBehavior.IsEnabled() )
|
||||
if ( (GetFlags() & FL_FLY) && m_NPCState != NPC_STATE_SCRIPT && !m_ActBusyBehavior.IsActive() && !m_PassengerBehavior.IsEnabled()
|
||||
#ifdef MAPBASE
|
||||
&& GetNavType() != NAV_CLIMB && !npc_alyx_allow_fly.GetBool()
|
||||
#endif
|
||||
)
|
||||
{
|
||||
Warning( "Removed FL_FLY from Alyx, who wasn't running a script or actbusy. Time %.2f, map %s.\n", gpGlobals->curtime, STRING(gpGlobals->mapname) );
|
||||
RemoveFlag( FL_FLY );
|
||||
@ -1687,9 +1695,88 @@ Activity CNPC_Alyx::NPC_TranslateActivity( Activity activity )
|
||||
case ACT_DROP_WEAPON: if ( HasShotgun() ) return (Activity)ACT_DROP_WEAPON_SHOTGUN;
|
||||
}
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
// Alyx has her own pistol readiness animations which use the default activities
|
||||
switch (activity)
|
||||
{
|
||||
case ACT_IDLE_PISTOL_RELAXED:
|
||||
return ACT_IDLE_RELAXED;
|
||||
case ACT_IDLE_PISTOL_STIMULATED:
|
||||
return ACT_IDLE_STIMULATED;
|
||||
case ACT_WALK_PISTOL_RELAXED:
|
||||
return ACT_WALK;
|
||||
case ACT_WALK_PISTOL_STIMULATED:
|
||||
return ACT_WALK_PISTOL;
|
||||
case ACT_RUN_PISTOL_RELAXED:
|
||||
return ACT_RUN;
|
||||
case ACT_RUN_PISTOL_STIMULATED:
|
||||
return ACT_RUN_PISTOL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return activity;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CNPC_Alyx::Weapon_TranslateActivity( Activity activity, bool *pRequired )
|
||||
{
|
||||
activity = BaseClass::Weapon_TranslateActivity( activity, pRequired );
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
// Alyx has her own pistol readiness animations which use the default activities
|
||||
switch (activity)
|
||||
{
|
||||
case ACT_IDLE_PISTOL_RELAXED:
|
||||
return ACT_IDLE_RELAXED;
|
||||
case ACT_IDLE_PISTOL_STIMULATED:
|
||||
return ACT_IDLE_STIMULATED;
|
||||
case ACT_WALK_PISTOL_RELAXED:
|
||||
return ACT_WALK;
|
||||
case ACT_WALK_PISTOL_STIMULATED:
|
||||
return ACT_WALK_PISTOL;
|
||||
case ACT_RUN_PISTOL_RELAXED:
|
||||
return ACT_RUN;
|
||||
case ACT_RUN_PISTOL_STIMULATED:
|
||||
return ACT_RUN_PISTOL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return activity;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CNPC_Alyx::Weapon_BackupActivity( Activity activity, bool weaponTranslationWasRequired, CBaseCombatWeapon *pSpecificWeapon )
|
||||
{
|
||||
activity = BaseClass::Weapon_BackupActivity( activity, weaponTranslationWasRequired, pSpecificWeapon );
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
// Alyx has her own pistol readiness animations which use the default activities
|
||||
switch (activity)
|
||||
{
|
||||
case ACT_IDLE_PISTOL_RELAXED:
|
||||
return ACT_IDLE_RELAXED;
|
||||
case ACT_IDLE_PISTOL_STIMULATED:
|
||||
return ACT_IDLE_STIMULATED;
|
||||
case ACT_WALK_PISTOL_RELAXED:
|
||||
return ACT_WALK;
|
||||
case ACT_WALK_PISTOL_STIMULATED:
|
||||
return ACT_WALK_PISTOL;
|
||||
case ACT_RUN_PISTOL_RELAXED:
|
||||
return ACT_RUN;
|
||||
case ACT_RUN_PISTOL_STIMULATED:
|
||||
return ACT_RUN_PISTOL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return activity;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CNPC_Alyx::ShouldDeferToFollowBehavior()
|
||||
{
|
||||
return BaseClass::ShouldDeferToFollowBehavior();
|
||||
|
@ -91,6 +91,10 @@ public:
|
||||
bool CanSeeEntityInDarkness( CBaseEntity *pEntity );
|
||||
bool IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition );
|
||||
Activity NPC_TranslateActivity ( Activity activity );
|
||||
#ifdef MAPBASE
|
||||
Activity Weapon_TranslateActivity( Activity baseAct, bool *pRequired = NULL );
|
||||
Activity Weapon_BackupActivity( Activity activity, bool weaponTranslationWasRequired = false, CBaseCombatWeapon *pSpecificWeapon = NULL );
|
||||
#endif
|
||||
bool ShouldDeferToFollowBehavior();
|
||||
void BuildScheduleTestBits();
|
||||
bool ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior );
|
||||
@ -231,7 +235,9 @@ private:
|
||||
|
||||
bool m_bShouldHaveEMP;
|
||||
|
||||
#ifndef MAPBASE // Moved to CNPC_PlayerCompanion
|
||||
CAI_FuncTankBehavior m_FuncTankBehavior;
|
||||
#endif
|
||||
|
||||
COutputEvent m_OnFinishInteractWithObject;
|
||||
COutputEvent m_OnPlayerUse;
|
||||
|
@ -439,10 +439,11 @@ CSimpleSimTimer CNPC_Citizen::gm_PlayerSquadEvaluateTimer;
|
||||
bool CNPC_Citizen::CreateBehaviors()
|
||||
{
|
||||
BaseClass::CreateBehaviors();
|
||||
AddBehavior( &m_FuncTankBehavior );
|
||||
#ifdef MAPBASE
|
||||
AddBehavior( &m_RappelBehavior );
|
||||
AddBehavior( &m_PolicingBehavior );
|
||||
#else // Moved to CNPC_PlayerCompanion
|
||||
AddBehavior( &m_FuncTankBehavior );
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@ -2085,6 +2086,13 @@ Activity CNPC_Citizen::NPC_TranslateActivity( Activity activity )
|
||||
return ACT_RUN_AIM_AR2_STIMULATED;
|
||||
if (activity == ACT_WALK_AIM_AR2)
|
||||
return ACT_WALK_AIM_AR2_STIMULATED;
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
if (activity == ACT_RUN_AIM_PISTOL)
|
||||
return ACT_RUN_AIM_PISTOL_STIMULATED;
|
||||
if (activity == ACT_WALK_AIM_PISTOL)
|
||||
return ACT_WALK_AIM_PISTOL_STIMULATED;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -370,7 +370,6 @@ private:
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------
|
||||
CAI_FuncTankBehavior m_FuncTankBehavior;
|
||||
#ifdef MAPBASE
|
||||
CAI_RappelBehavior m_RappelBehavior;
|
||||
CAI_PolicingBehavior m_PolicingBehavior;
|
||||
@ -378,6 +377,8 @@ private:
|
||||
// Rappel
|
||||
virtual bool IsWaitingToRappel( void ) { return m_RappelBehavior.IsWaitingToRappel(); }
|
||||
void BeginRappel() { m_RappelBehavior.BeginRappel(); }
|
||||
#else // Moved to CNPC_PlayerCompanion
|
||||
CAI_FuncTankBehavior m_FuncTankBehavior;
|
||||
#endif
|
||||
|
||||
CHandle<CAI_FollowGoal> m_hSavedFollowGoalEnt;
|
||||
|
@ -43,6 +43,7 @@ int g_fCombineQuestion; // true if an idle grunt asked a question. Cleared wh
|
||||
#ifdef MAPBASE
|
||||
ConVar npc_combine_idle_walk_easy( "npc_combine_idle_walk_easy", "1", FCVAR_NONE, "Mapbase: Allows Combine soldiers to use ACT_WALK_EASY as a walking animation when idle." );
|
||||
ConVar npc_combine_unarmed_anims( "npc_combine_unarmed_anims", "1", FCVAR_NONE, "Mapbase: Allows Combine soldiers to use unarmed idle/walk animations when they have no weapon." );
|
||||
ConVar npc_combine_protected_run( "npc_combine_protected_run", "0", FCVAR_NONE, "Mapbase: Allows Combine soldiers to use \"protected run\" animations." );
|
||||
ConVar npc_combine_altfire_not_allies_only( "npc_combine_altfire_not_allies_only", "1", FCVAR_NONE, "Mapbase: Elites are normally only allowed to fire their alt-fire attack at the player and the player's allies; This allows elites to alt-fire at other enemies too." );
|
||||
|
||||
ConVar npc_combine_new_cover_behavior( "npc_combine_new_cover_behavior", "1", FCVAR_NONE, "Mapbase: Toggles small patches for parts of npc_combine AI related to soldiers failing to take cover. These patches are minimal and only change cases where npc_combine would otherwise look at an enemy without shooting or run up to the player to melee attack when they don't have to. Consult the Mapbase wiki for more information." );
|
||||
@ -127,8 +128,9 @@ Activity ACT_COMBINE_AR2_ALTFIRE;
|
||||
Activity ACT_WALK_EASY;
|
||||
Activity ACT_WALK_MARCH;
|
||||
#ifdef MAPBASE
|
||||
Activity ACT_IDLE_UNARMED;
|
||||
Activity ACT_WALK_UNARMED;
|
||||
Activity ACT_TURRET_CARRY_IDLE;
|
||||
Activity ACT_TURRET_CARRY_WALK;
|
||||
Activity ACT_TURRET_CARRY_RUN;
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------
|
||||
@ -544,7 +546,12 @@ void CNPC_Combine::GatherConditions()
|
||||
|
||||
if( GetState() == NPC_STATE_COMBAT )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// Don't override the standoff
|
||||
if( IsCurSchedule( SCHED_COMBINE_WAIT_IN_COVER, false ) && !m_StandoffBehavior.IsActive() )
|
||||
#else
|
||||
if( IsCurSchedule( SCHED_COMBINE_WAIT_IN_COVER, false ) )
|
||||
#endif
|
||||
{
|
||||
// Soldiers that are standing around doing nothing poll for attack slots so
|
||||
// that they can respond quickly when one comes available. If they can
|
||||
@ -1540,11 +1547,6 @@ void CNPC_Combine::BuildScheduleTestBits( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CNPC_Combine::Weapon_TranslateActivity( Activity eNewActivity, bool *pRequired )
|
||||
{
|
||||
// We have differing low animations and ACT_CROUCHIDLE is not friendly to weapon translation.
|
||||
// ACT_CROUCHIDLE is pretty much deprecated at this point anyway.
|
||||
if (eNewActivity == ACT_CROUCHIDLE)
|
||||
eNewActivity = ACT_RANGE_AIM_LOW;
|
||||
|
||||
return BaseClass::Weapon_TranslateActivity(eNewActivity, pRequired);
|
||||
}
|
||||
|
||||
@ -1553,12 +1555,6 @@ Activity CNPC_Combine::Weapon_TranslateActivity( Activity eNewActivity, bool *pR
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CNPC_Combine::NPC_BackupActivity( Activity eNewActivity )
|
||||
{
|
||||
// Otherwise we move around, T-posing.
|
||||
if (eNewActivity == ACT_WALK)
|
||||
return ACT_WALK_UNARMED;
|
||||
else if (eNewActivity == ACT_RUN)
|
||||
return ACT_RUN_RIFLE;
|
||||
|
||||
// Some models might not contain ACT_COMBINE_BUGBAIT, which the soldier model uses instead of ACT_IDLE_ON_FIRE.
|
||||
// Contrariwise, soldiers may be called to use ACT_IDLE_ON_FIRE in other parts of the AI and need to translate to ACT_COMBINE_BUGBAIT.
|
||||
if (eNewActivity == ACT_COMBINE_BUGBAIT)
|
||||
@ -1630,16 +1626,32 @@ Activity CNPC_Combine::NPC_TranslateActivity( Activity eNewActivity )
|
||||
}
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else if (!GetActiveWeapon() && npc_combine_unarmed_anims.GetBool() && HaveSequenceForActivity(ACT_IDLE_UNARMED))
|
||||
else if (!GetActiveWeapon() && !npc_combine_unarmed_anims.GetBool())
|
||||
{
|
||||
if (eNewActivity == ACT_IDLE || eNewActivity == ACT_IDLE_ANGRY)
|
||||
eNewActivity = ACT_IDLE_UNARMED;
|
||||
eNewActivity = ACT_IDLE_SMG1;
|
||||
else if (eNewActivity == ACT_WALK)
|
||||
eNewActivity = ACT_WALK_UNARMED;
|
||||
eNewActivity = ACT_WALK_RIFLE;
|
||||
else if (eNewActivity == ACT_RUN)
|
||||
eNewActivity = ACT_RUN_RIFLE;
|
||||
}
|
||||
else if (eNewActivity == ACT_WALK && m_NPCState == NPC_STATE_IDLE && npc_combine_idle_walk_easy.GetBool() && HaveSequenceForActivity(ACT_WALK_EASY))
|
||||
else if (m_NPCState == NPC_STATE_IDLE && eNewActivity == ACT_WALK)
|
||||
{
|
||||
eNewActivity = ACT_WALK_EASY;
|
||||
if (npc_combine_idle_walk_easy.GetBool())
|
||||
{
|
||||
// ACT_WALK_EASY has been replaced with ACT_WALK_RELAXED for weapon translation purposes
|
||||
eNewActivity = ACT_WALK_RELAXED;
|
||||
}
|
||||
else if (GetActiveWeapon())
|
||||
{
|
||||
eNewActivity = ACT_WALK_RIFLE;
|
||||
}
|
||||
}
|
||||
|
||||
if ( eNewActivity == ACT_RUN && ( IsCurSchedule( SCHED_TAKE_COVER_FROM_BEST_SOUND ) || IsCurSchedule( SCHED_FLEE_FROM_BEST_SOUND ) ) )
|
||||
{
|
||||
if ( random->RandomInt( 0, 1 ) && npc_combine_protected_run.GetBool() && HaveSequenceForActivity( ACT_RUN_PROTECTED ) )
|
||||
eNewActivity = ACT_RUN_PROTECTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2606,7 +2618,6 @@ int CNPC_Combine::TranslateSchedule( int scheduleType )
|
||||
#ifdef MAPBASE
|
||||
// SCHED_COMBINE_WAIT_IN_COVER uses INCOVER, but only gets out of it when the soldier moves.
|
||||
// That seems to mess up shooting, so this Forget() attempts to fix that.
|
||||
// I don't know if there's a better workaround.
|
||||
Forget( bits_MEMORY_INCOVER );
|
||||
#endif
|
||||
|
||||
@ -3791,6 +3802,13 @@ WeaponProficiency_t CNPC_Combine::CalcWeaponProficiency( CBaseCombatWeapon *pWea
|
||||
{
|
||||
return WEAPON_PROFICIENCY_GOOD;
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else if ( pWeapon->ClassMatches( gm_isz_class_Pistol ) )
|
||||
{
|
||||
// Mods which need a lower soldier pistol accuracy can either change this value or use proficiency override in Hammer.
|
||||
return WEAPON_PROFICIENCY_VERY_GOOD;
|
||||
}
|
||||
#endif
|
||||
|
||||
return BaseClass::CalcWeaponProficiency( pWeapon );
|
||||
}
|
||||
@ -3906,7 +3924,12 @@ bool CNPC_Combine::IsRunningApproachEnemySchedule()
|
||||
|
||||
bool CNPC_Combine::ShouldPickADeathPose( void )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// Check base class as well
|
||||
return !IsCrouching() && BaseClass::ShouldPickADeathPose();
|
||||
#else
|
||||
return !IsCrouching();
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -3940,8 +3963,9 @@ DECLARE_ACTIVITY( ACT_COMBINE_AR2_ALTFIRE )
|
||||
DECLARE_ACTIVITY( ACT_WALK_EASY )
|
||||
DECLARE_ACTIVITY( ACT_WALK_MARCH )
|
||||
#ifdef MAPBASE
|
||||
DECLARE_ACTIVITY( ACT_IDLE_UNARMED )
|
||||
DECLARE_ACTIVITY( ACT_WALK_UNARMED )
|
||||
DECLARE_ACTIVITY( ACT_TURRET_CARRY_IDLE )
|
||||
DECLARE_ACTIVITY( ACT_TURRET_CARRY_WALK )
|
||||
DECLARE_ACTIVITY( ACT_TURRET_CARRY_RUN )
|
||||
#endif
|
||||
|
||||
DECLARE_ANIMEVENT( COMBINE_AE_BEGIN_ALTFIRE )
|
||||
|
@ -1296,7 +1296,11 @@ void CFastZombie::StartTask( const Task_t *pTask )
|
||||
CBaseEntity *pEnemy = GetEnemy();
|
||||
Vector vecJumpDir;
|
||||
|
||||
if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN )
|
||||
if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
|| GetActivity() == ACT_CLIMB_ALL
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// Jump off the pipe backwards!
|
||||
Vector forward;
|
||||
@ -1449,7 +1453,11 @@ int CFastZombie::TranslateSchedule( int scheduleType )
|
||||
break;
|
||||
|
||||
case SCHED_FASTZOMBIE_UNSTICK_JUMP:
|
||||
if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN || GetActivity() == ACT_CLIMB_DISMOUNT )
|
||||
if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN || GetActivity() == ACT_CLIMB_DISMOUNT
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
|| (GetActivity() >= ACT_CLIMB_ALL && GetActivity() <= ACT_CLIMB_DISMOUNT_BOTTOM)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return SCHED_FASTZOMBIE_CLIMBING_UNSTICK_JUMP;
|
||||
}
|
||||
@ -1477,8 +1485,10 @@ int CFastZombie::TranslateSchedule( int scheduleType )
|
||||
//---------------------------------------------------------
|
||||
Activity CFastZombie::NPC_TranslateActivity( Activity baseAct )
|
||||
{
|
||||
#ifndef MAPBASE // Now covered by CAI_BaseNPC::NPC_BackupActivity
|
||||
if ( baseAct == ACT_CLIMB_DOWN )
|
||||
return ACT_CLIMB_UP;
|
||||
#endif
|
||||
|
||||
return BaseClass::NPC_TranslateActivity( baseAct );
|
||||
}
|
||||
|
@ -1537,7 +1537,12 @@ void CNPC_MetroPolice::OnUpdateShotRegulator( )
|
||||
BaseClass::OnUpdateShotRegulator();
|
||||
|
||||
// FIXME: This code (except the burst interval) could be used for all weapon types
|
||||
#ifdef MAPBASE
|
||||
// Only if we actually have the pistol out
|
||||
if ( EntIsClass( GetActiveWeapon(), gm_isz_class_Pistol ) )
|
||||
#else
|
||||
if( Weapon_OwnsThisType( "weapon_pistol" ) )
|
||||
#endif
|
||||
{
|
||||
if ( m_nBurstMode == BURST_NOT_ACTIVE )
|
||||
{
|
||||
@ -3899,6 +3904,15 @@ int CNPC_MetroPolice::SelectScheduleNoDirectEnemy()
|
||||
return SCHED_METROPOLICE_SMASH_PROP;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// If you see your enemy and you're still arming yourself, wait and don't just charge in
|
||||
// (if your weapon is holstered, you're probably about to arm yourself)
|
||||
if ( HasCondition( COND_SEE_ENEMY ) && GetWeapon(0) && (IsWeaponHolstered() || FindGestureLayer( TranslateActivity( ACT_ARM ) ) != -1) )
|
||||
{
|
||||
return SCHED_COMBAT_FACE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SCHED_METROPOLICE_CHASE_ENEMY;
|
||||
}
|
||||
|
||||
@ -4522,34 +4536,7 @@ int CNPC_MetroPolice::SelectBehaviorOverrideSchedule()
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNPC_MetroPolice::IsCrouchedActivity( Activity activity )
|
||||
{
|
||||
Activity realActivity = TranslateActivity(activity);
|
||||
|
||||
switch ( realActivity )
|
||||
{
|
||||
case ACT_RELOAD_LOW:
|
||||
case ACT_COVER_LOW:
|
||||
case ACT_COVER_PISTOL_LOW:
|
||||
case ACT_COVER_SMG1_LOW:
|
||||
case ACT_RELOAD_SMG1_LOW:
|
||||
//case ACT_RELOAD_AR2_LOW:
|
||||
case ACT_RELOAD_PISTOL_LOW:
|
||||
case ACT_RELOAD_SHOTGUN_LOW:
|
||||
|
||||
// These animations aren't actually "low" on metrocops
|
||||
//case ACT_RANGE_AIM_LOW:
|
||||
//case ACT_RANGE_AIM_AR2_LOW:
|
||||
//case ACT_RANGE_AIM_SMG1_LOW:
|
||||
//case ACT_RANGE_AIM_PISTOL_LOW:
|
||||
|
||||
//case ACT_RANGE_ATTACK1_LOW:
|
||||
//case ACT_RANGE_ATTACK_AR2_LOW:
|
||||
//case ACT_RANGE_ATTACK_SMG1_LOW:
|
||||
//case ACT_RANGE_ATTACK_PISTOL_LOW:
|
||||
//case ACT_RANGE_ATTACK2_LOW:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return BaseClass::IsCrouchedActivity( activity );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -61,6 +61,10 @@ int AE_COMPANION_RELEASE_FLARE;
|
||||
#define COMPANION_MELEE_DIST 64.0
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar ai_allow_new_weapons( "ai_allow_new_weapons", "1", FCVAR_NONE, "Allows companion NPCs to automatically pick up and use weapons they were unable pick up before, i.e. 357s or crossbows." );
|
||||
#endif
|
||||
|
||||
#define MAX_TIME_BETWEEN_BARRELS_EXPLODING 5.0f
|
||||
#define MAX_TIME_BETWEEN_CONSECUTIVE_PLAYER_KILLS 3.0f
|
||||
|
||||
@ -211,6 +215,10 @@ bool CNPC_PlayerCompanion::CreateBehaviors()
|
||||
AddBehavior( &m_FollowBehavior );
|
||||
AddBehavior( &m_LeadBehavior );
|
||||
#endif//HL2_EPISODIC
|
||||
|
||||
#ifdef MAPBASE
|
||||
AddBehavior( &m_FuncTankBehavior );
|
||||
#endif
|
||||
|
||||
return BaseClass::CreateBehaviors();
|
||||
}
|
||||
@ -1642,6 +1650,19 @@ Activity CNPC_PlayerCompanion::TranslateActivityReadiness( Activity activity )
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// If we don't have the readiness activity we selected and there's no backup activity available, break the loop and return the base act.
|
||||
bool bRequired;
|
||||
if ( !HaveSequenceForActivity( actremap.mappedActivity ) && !HaveSequenceForActivity( Weapon_TranslateActivity( actremap.mappedActivity, &bRequired ) ) )
|
||||
{
|
||||
Activity backupAct = Weapon_BackupActivity( actremap.mappedActivity, bRequired );
|
||||
if ( backupAct != actremap.mappedActivity )
|
||||
return backupAct;
|
||||
else
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// We've successfully passed all criteria for remapping this
|
||||
return actremap.mappedActivity;
|
||||
}
|
||||
@ -1665,21 +1686,6 @@ Activity CNPC_PlayerCompanion::NPC_TranslateActivity( Activity activity )
|
||||
activity = ACT_RUN_PROTECTED;
|
||||
}
|
||||
|
||||
#ifdef COMPANION_HOLSTER_WORKAROUND
|
||||
if (activity == ACT_DISARM || activity == ACT_ARM)
|
||||
{
|
||||
CBaseCombatWeapon *pWeapon = GetActiveWeapon() ? GetActiveWeapon() : m_hWeapons[m_iLastHolsteredWeapon];
|
||||
if (pWeapon && pWeapon->WeaponClassify() != WEPCLASS_HANDGUN)
|
||||
{
|
||||
switch (activity)
|
||||
{
|
||||
case ACT_DISARM: return ACT_DISARM_RIFLE;
|
||||
case ACT_ARM: return ACT_ARM_RIFLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
activity = BaseClass::NPC_TranslateActivity( activity );
|
||||
|
||||
if ( activity == ACT_IDLE )
|
||||
@ -2748,6 +2754,13 @@ bool CNPC_PlayerCompanion::Weapon_CanUse( CBaseCombatWeapon *pWeapon )
|
||||
{
|
||||
return (NumWeaponsInSquad("weapon_shotgun") < 1 );
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else if (EntIsClass( pWeapon, gm_isz_class_Pistol ) || EntIsClass( pWeapon, gm_isz_class_357 ) || EntIsClass( pWeapon, gm_isz_class_Crossbow ))
|
||||
{
|
||||
// The AI automatically detects these weapons as usable now that there's animations for them, so ensure this behavior can be toggled in situations where that's not desirable
|
||||
return ai_allow_new_weapons.GetBool();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return true;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
#include "ai_behavior_functank.h"
|
||||
#include "mapbase/ai_grenade.h"
|
||||
#endif
|
||||
|
||||
@ -432,6 +433,9 @@ protected:
|
||||
CAI_OperatorBehavior m_OperatorBehavior;
|
||||
CAI_PassengerBehaviorCompanion m_PassengerBehavior;
|
||||
CAI_FearBehavior m_FearBehavior;
|
||||
#endif
|
||||
#ifdef MAPBASE
|
||||
CAI_FuncTankBehavior m_FuncTankBehavior;
|
||||
#endif
|
||||
//-----------------------------------------------------
|
||||
|
||||
|
@ -2718,6 +2718,15 @@ void CNPC_Vortigaunt::OnSquishedGrub( const CBaseEntity *pGrub )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Vortigaunt::AimGun( void )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// Use base for func_tank
|
||||
if (m_FuncTankBehavior.IsRunning())
|
||||
{
|
||||
BaseClass::AimGun();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// If our aim lock is on, don't bother
|
||||
if ( m_flAimDelay >= gpGlobals->curtime )
|
||||
return;
|
||||
|
@ -250,6 +250,10 @@ public:
|
||||
virtual int SelectSchedule( void );
|
||||
virtual int TranslateSchedule( int scheduleType );
|
||||
|
||||
#ifdef MAPBASE
|
||||
Activity NPC_TranslateActivity( Activity eNewActivity );
|
||||
#endif
|
||||
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
|
||||
void PrescheduleThink( void );
|
||||
@ -2036,6 +2040,23 @@ int CProtoSniper::TranslateSchedule( int scheduleType )
|
||||
return BaseClass::TranslateSchedule( scheduleType );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CProtoSniper::NPC_TranslateActivity( Activity eNewActivity )
|
||||
{
|
||||
// ACT_IDLE is now just the soldier's unarmed idle animation.
|
||||
// Use a gun-holding animation like what unhidden snipers were using before.
|
||||
if (!HasSpawnFlags( SF_SNIPER_HIDDEN ) && eNewActivity == ACT_IDLE)
|
||||
{
|
||||
eNewActivity = ACT_IDLE_SMG1;
|
||||
}
|
||||
|
||||
return BaseClass::NPC_TranslateActivity( eNewActivity );
|
||||
}
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------
|
||||
//---------------------------------------------------------
|
||||
void CProtoSniper::ScopeGlint()
|
||||
|
@ -27,6 +27,11 @@
|
||||
// CWeapon357
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE
|
||||
extern acttable_t *GetPistolActtable();
|
||||
extern int GetPistolActtableCount();
|
||||
#endif
|
||||
|
||||
class CWeapon357 : public CBaseHLCombatWeapon
|
||||
{
|
||||
DECLARE_CLASS( CWeapon357, CBaseHLCombatWeapon );
|
||||
@ -69,6 +74,9 @@ public:
|
||||
|
||||
void FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, Vector &vecShootOrigin, Vector &vecShootDir );
|
||||
void Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary );
|
||||
|
||||
virtual acttable_t *GetBackupActivityList() { return GetPistolActtable(); }
|
||||
virtual int GetBackupActivityListCount() { return GetPistolActtableCount(); }
|
||||
#endif
|
||||
|
||||
DECLARE_SERVERCLASS();
|
||||
@ -91,6 +99,22 @@ END_DATADESC()
|
||||
#ifdef MAPBASE
|
||||
acttable_t CWeapon357::m_acttable[] =
|
||||
{
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_IDLE, ACT_IDLE_REVOLVER, true },
|
||||
{ ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_REVOLVER, true },
|
||||
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_REVOLVER, true },
|
||||
{ ACT_RELOAD, ACT_RELOAD_REVOLVER, true },
|
||||
{ ACT_WALK_AIM, ACT_WALK_AIM_REVOLVER, true },
|
||||
{ ACT_RUN_AIM, ACT_RUN_AIM_REVOLVER, true },
|
||||
{ ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_REVOLVER, true },
|
||||
{ ACT_RELOAD_LOW, ACT_RELOAD_REVOLVER_LOW, false },
|
||||
{ ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_REVOLVER_LOW, false },
|
||||
{ ACT_COVER_LOW, ACT_COVER_REVOLVER_LOW, false },
|
||||
{ ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_REVOLVER_LOW, false },
|
||||
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_REVOLVER, false },
|
||||
{ ACT_WALK, ACT_WALK_REVOLVER, true },
|
||||
{ ACT_RUN, ACT_RUN_REVOLVER, true },
|
||||
#else
|
||||
{ ACT_IDLE, ACT_IDLE_PISTOL, true },
|
||||
{ ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_PISTOL, true },
|
||||
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_PISTOL, true },
|
||||
@ -105,24 +129,40 @@ acttable_t CWeapon357::m_acttable[] =
|
||||
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_PISTOL, false },
|
||||
{ ACT_WALK, ACT_WALK_PISTOL, false },
|
||||
{ ACT_RUN, ACT_RUN_PISTOL, false },
|
||||
#endif
|
||||
|
||||
//
|
||||
// Activities ported from weapon_alyxgun below
|
||||
//
|
||||
|
||||
// Readiness activities (not aiming)
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_IDLE_RELAXED, ACT_IDLE_PISTOL_RELAXED, false },//never aims
|
||||
{ ACT_IDLE_STIMULATED, ACT_IDLE_PISTOL_STIMULATED, false },
|
||||
#else
|
||||
{ ACT_IDLE_RELAXED, ACT_IDLE_PISTOL, false },//never aims
|
||||
{ ACT_IDLE_STIMULATED, ACT_IDLE_STIMULATED, false },
|
||||
#endif
|
||||
{ ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_PISTOL, false },//always aims
|
||||
{ ACT_IDLE_STEALTH, ACT_IDLE_STEALTH_PISTOL, false },
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_WALK_RELAXED, ACT_WALK_PISTOL_RELAXED, false },//never aims
|
||||
{ ACT_WALK_STIMULATED, ACT_WALK_PISTOL_STIMULATED, false },
|
||||
#else
|
||||
{ ACT_WALK_RELAXED, ACT_WALK, false },//never aims
|
||||
{ ACT_WALK_STIMULATED, ACT_WALK_STIMULATED, false },
|
||||
#endif
|
||||
{ ACT_WALK_AGITATED, ACT_WALK_AIM_PISTOL, false },//always aims
|
||||
{ ACT_WALK_STEALTH, ACT_WALK_STEALTH_PISTOL, false },
|
||||
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_RUN_RELAXED, ACT_RUN_PISTOL_RELAXED, false },//never aims
|
||||
{ ACT_RUN_STIMULATED, ACT_RUN_PISTOL_STIMULATED, false },
|
||||
#else
|
||||
{ ACT_RUN_RELAXED, ACT_RUN, false },//never aims
|
||||
{ ACT_RUN_STIMULATED, ACT_RUN_STIMULATED, false },
|
||||
#endif
|
||||
{ ACT_RUN_AGITATED, ACT_RUN_AIM_PISTOL, false },//always aims
|
||||
{ ACT_RUN_STEALTH, ACT_RUN_STEALTH_PISTOL, false },
|
||||
|
||||
@ -153,6 +193,11 @@ acttable_t CWeapon357::m_acttable[] =
|
||||
{ ACT_READINESS_RELAXED_TO_STIMULATED_WALK, ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK, false },
|
||||
{ ACT_READINESS_AGITATED_TO_STIMULATED, ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED, false },
|
||||
{ ACT_READINESS_STIMULATED_TO_RELAXED, ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED, false },
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
{ ACT_RANGE_AIM_MED, ACT_RANGE_AIM_REVOLVER_MED, false },
|
||||
{ ACT_RANGE_ATTACK1_MED, ACT_RANGE_ATTACK_REVOLVER_MED, false },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -44,18 +44,33 @@ acttable_t CWeaponAlyxGun::m_acttable[] =
|
||||
#endif
|
||||
|
||||
// Readiness activities (not aiming)
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_IDLE_RELAXED, ACT_IDLE_PISTOL_RELAXED, false },//never aims
|
||||
{ ACT_IDLE_STIMULATED, ACT_IDLE_PISTOL_STIMULATED, false },
|
||||
#else
|
||||
{ ACT_IDLE_RELAXED, ACT_IDLE_PISTOL, false },//never aims
|
||||
{ ACT_IDLE_STIMULATED, ACT_IDLE_STIMULATED, false },
|
||||
#endif
|
||||
{ ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_PISTOL, false },//always aims
|
||||
{ ACT_IDLE_STEALTH, ACT_IDLE_STEALTH_PISTOL, false },
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_WALK_RELAXED, ACT_WALK_PISTOL_RELAXED, false },//never aims
|
||||
{ ACT_WALK_STIMULATED, ACT_WALK_PISTOL_STIMULATED, false },
|
||||
#else
|
||||
{ ACT_WALK_RELAXED, ACT_WALK, false },//never aims
|
||||
{ ACT_WALK_STIMULATED, ACT_WALK_STIMULATED, false },
|
||||
#endif
|
||||
{ ACT_WALK_AGITATED, ACT_WALK_AIM_PISTOL, false },//always aims
|
||||
{ ACT_WALK_STEALTH, ACT_WALK_STEALTH_PISTOL, false },
|
||||
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_RUN_RELAXED, ACT_RUN_PISTOL_RELAXED, false },//never aims
|
||||
{ ACT_RUN_STIMULATED, ACT_RUN_PISTOL_STIMULATED, false },
|
||||
#else
|
||||
{ ACT_RUN_RELAXED, ACT_RUN, false },//never aims
|
||||
{ ACT_RUN_STIMULATED, ACT_RUN_STIMULATED, false },
|
||||
#endif
|
||||
{ ACT_RUN_AGITATED, ACT_RUN_AIM_PISTOL, false },//always aims
|
||||
{ ACT_RUN_STEALTH, ACT_RUN_STEALTH_PISTOL, false },
|
||||
|
||||
|
@ -13,6 +13,11 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
extern acttable_t *GetPistolActtable();
|
||||
extern int GetPistolActtableCount();
|
||||
#endif
|
||||
|
||||
class CWeaponAlyxGun : public CHLSelectFireMachineGun
|
||||
{
|
||||
DECLARE_DATADESC();
|
||||
@ -51,6 +56,11 @@ public:
|
||||
SetTouch(NULL);
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
virtual acttable_t *GetBackupActivityList() { return GetPistolActtable(); }
|
||||
virtual int GetBackupActivityListCount() { return GetPistolActtableCount(); }
|
||||
#endif
|
||||
|
||||
float m_flTooCloseTimer;
|
||||
|
||||
DECLARE_ACTTABLE();
|
||||
|
@ -38,10 +38,6 @@ ConVar sk_weapon_ar2_alt_fire_radius( "sk_weapon_ar2_alt_fire_radius", "10" );
|
||||
ConVar sk_weapon_ar2_alt_fire_duration( "sk_weapon_ar2_alt_fire_duration", "2" );
|
||||
ConVar sk_weapon_ar2_alt_fire_mass( "sk_weapon_ar2_alt_fire_mass", "150" );
|
||||
|
||||
#ifdef MAPBASE
|
||||
extern acttable_t *GetSMG1Acttable();
|
||||
#endif
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
|
||||
@ -100,14 +96,14 @@ acttable_t CWeaponAR2::m_acttable[] =
|
||||
{ ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true },
|
||||
{ ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true },
|
||||
{ ACT_RUN, ACT_RUN_AR2, true },
|
||||
{ ACT_RUN_AIM, ACT_RUN_AIM_RIFLE, true },
|
||||
{ ACT_RUN_AIM, ACT_RUN_AIM_AR2, true },
|
||||
{ ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, true },
|
||||
{ ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, true },
|
||||
{ ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_AR2, false },
|
||||
{ ACT_COVER_LOW, ACT_COVER_SMG1_LOW, false },
|
||||
{ ACT_COVER_LOW, ACT_COVER_AR2_LOW, true },
|
||||
{ ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_AR2_LOW, false },
|
||||
{ ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_AR2_LOW, false },
|
||||
{ ACT_RELOAD_LOW, ACT_RELOAD_SMG1_LOW, false },
|
||||
{ ACT_RELOAD_LOW, ACT_RELOAD_AR2_LOW, false },
|
||||
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_AR2, true },
|
||||
// { ACT_RANGE_ATTACK2, ACT_RANGE_ATTACK_AR2_GRENADE, true },
|
||||
#else
|
||||
@ -160,6 +156,21 @@ acttable_t CWeaponAR2::m_acttable[] =
|
||||
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, true },
|
||||
// { ACT_RANGE_ATTACK2, ACT_RANGE_ATTACK_AR2_GRENADE, true },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_ARM, ACT_ARM_RIFLE, false },
|
||||
{ ACT_DISARM, ACT_DISARM_RIFLE, false },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
{ ACT_RANGE_AIM_MED, ACT_RANGE_AIM_AR2_MED, false },
|
||||
{ ACT_RANGE_ATTACK1_MED, ACT_RANGE_ATTACK_AR2_MED, false },
|
||||
|
||||
{ ACT_COVER_WALL_R, ACT_COVER_WALL_R_RIFLE, false },
|
||||
{ ACT_COVER_WALL_L, ACT_COVER_WALL_L_RIFLE, false },
|
||||
{ ACT_COVER_WALL_LOW_R, ACT_COVER_WALL_LOW_R_RIFLE, false },
|
||||
{ ACT_COVER_WALL_LOW_L, ACT_COVER_WALL_LOW_L_RIFLE, false },
|
||||
#endif
|
||||
};
|
||||
|
||||
IMPLEMENT_ACTTABLE(CWeaponAR2);
|
||||
|
@ -23,6 +23,13 @@ acttable_t CWeaponCitizenPackage::m_acttable[] =
|
||||
{
|
||||
{ ACT_IDLE, ACT_IDLE_PACKAGE, false },
|
||||
{ ACT_WALK, ACT_WALK_PACKAGE, false },
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_RUN, ACT_RUN_PACKAGE, false },
|
||||
|
||||
{ ACT_IDLE_ANGRY, ACT_IDLE_PACKAGE, false },
|
||||
{ ACT_WALK_AIM, ACT_WALK_PACKAGE, false },
|
||||
{ ACT_RUN_AIM, ACT_RUN_PACKAGE, false },
|
||||
#endif
|
||||
};
|
||||
IMPLEMENT_ACTTABLE(CWeaponCitizenPackage);
|
||||
|
||||
@ -70,5 +77,12 @@ acttable_t CWeaponCitizenSuitcase::m_acttable[] =
|
||||
{
|
||||
{ ACT_IDLE, ACT_IDLE_SUITCASE, false },
|
||||
{ ACT_WALK, ACT_WALK_SUITCASE, false },
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_RUN, ACT_RUN_SUITCASE, false },
|
||||
|
||||
{ ACT_IDLE_ANGRY, ACT_IDLE_SUITCASE, false },
|
||||
{ ACT_WALK_AIM, ACT_WALK_SUITCASE, false },
|
||||
{ ACT_RUN_AIM, ACT_RUN_SUITCASE, false },
|
||||
#endif
|
||||
};
|
||||
IMPLEMENT_ACTTABLE(CWeaponCitizenSuitcase);
|
||||
|
@ -542,7 +542,7 @@ public:
|
||||
virtual bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
|
||||
virtual bool Reload( void );
|
||||
#ifdef MAPBASE
|
||||
virtual void Reload_NPC( void );
|
||||
virtual void Reload_NPC( bool bPlaySound = true );
|
||||
#endif
|
||||
virtual void ItemPostFrame( void );
|
||||
virtual void ItemBusyFrame( void );
|
||||
@ -638,6 +638,15 @@ END_DATADESC()
|
||||
#ifdef MAPBASE
|
||||
acttable_t CWeaponCrossbow::m_acttable[] =
|
||||
{
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_CROSSBOW, true },
|
||||
{ ACT_RELOAD, ACT_RELOAD_CROSSBOW, true },
|
||||
{ ACT_IDLE, ACT_IDLE_CROSSBOW, true },
|
||||
{ ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_CROSSBOW, true },
|
||||
|
||||
{ ACT_WALK, ACT_WALK_CROSSBOW, true },
|
||||
{ ACT_WALK_AIM, ACT_WALK_AIM_CROSSBOW, true },
|
||||
#else
|
||||
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SMG1, true },
|
||||
{ ACT_RELOAD, ACT_RELOAD_SMG1, true },
|
||||
{ ACT_IDLE, ACT_IDLE_SMG1, true },
|
||||
@ -645,6 +654,7 @@ acttable_t CWeaponCrossbow::m_acttable[] =
|
||||
|
||||
{ ACT_WALK, ACT_WALK_RIFLE, true },
|
||||
{ ACT_WALK_AIM, ACT_WALK_AIM_RIFLE, true },
|
||||
#endif
|
||||
|
||||
// Readiness activities (not aiming)
|
||||
{ ACT_IDLE_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims
|
||||
@ -673,6 +683,24 @@ acttable_t CWeaponCrossbow::m_acttable[] =
|
||||
{ ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims
|
||||
//End readiness activities
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_WALK_AIM, ACT_WALK_AIM_CROSSBOW, true },
|
||||
{ ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true },
|
||||
{ ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true },
|
||||
{ ACT_RUN, ACT_RUN_CROSSBOW, true },
|
||||
{ ACT_RUN_AIM, ACT_RUN_AIM_CROSSBOW, true },
|
||||
{ ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, true },
|
||||
{ ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, true },
|
||||
{ ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_CROSSBOW, true },
|
||||
{ ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_CROSSBOW_LOW, true },
|
||||
{ ACT_COVER_LOW, ACT_COVER_CROSSBOW_LOW, false },
|
||||
{ ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_CROSSBOW_LOW, false },
|
||||
{ ACT_RELOAD_LOW, ACT_RELOAD_CROSSBOW_LOW, false },
|
||||
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_CROSSBOW, true },
|
||||
|
||||
{ ACT_ARM, ACT_ARM_RIFLE, false },
|
||||
{ ACT_DISARM, ACT_DISARM_RIFLE, false },
|
||||
#else
|
||||
{ ACT_WALK_AIM, ACT_WALK_AIM_RIFLE, true },
|
||||
{ ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true },
|
||||
{ ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true },
|
||||
@ -686,6 +714,12 @@ acttable_t CWeaponCrossbow::m_acttable[] =
|
||||
{ ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_SMG1_LOW, false },
|
||||
{ ACT_RELOAD_LOW, ACT_RELOAD_SMG1_LOW, false },
|
||||
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, true },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
{ ACT_RANGE_AIM_MED, ACT_RANGE_AIM_CROSSBOW_MED, false },
|
||||
{ ACT_RANGE_ATTACK1_MED, ACT_RANGE_ATTACK_CROSSBOW_MED, false },
|
||||
#endif
|
||||
};
|
||||
|
||||
IMPLEMENT_ACTTABLE(CWeaponCrossbow);
|
||||
@ -785,11 +819,15 @@ bool CWeaponCrossbow::Reload( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponCrossbow::Reload_NPC( void )
|
||||
void CWeaponCrossbow::Reload_NPC( bool bPlaySound )
|
||||
{
|
||||
BaseClass::Reload_NPC();
|
||||
BaseClass::Reload_NPC( bPlaySound );
|
||||
|
||||
m_nSkin = 0;
|
||||
int iBody = FindBodygroupByName( "bolt" );
|
||||
if (iBody != -1)
|
||||
SetBodygroup( iBody, 0 );
|
||||
else
|
||||
m_nSkin = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -939,7 +977,11 @@ void CWeaponCrossbow::FireNPCBolt( CAI_BaseNPC *pOwner, Vector &vecShootOrigin,
|
||||
|
||||
m_iClip1--;
|
||||
|
||||
m_nSkin = 1;
|
||||
int iBody = FindBodygroupByName( "bolt" );
|
||||
if (iBody != -1)
|
||||
SetBodygroup( iBody, 1 );
|
||||
else
|
||||
m_nSkin = 1;
|
||||
|
||||
WeaponSound( SINGLE_NPC );
|
||||
WeaponSound( SPECIAL2 );
|
||||
|
@ -42,6 +42,13 @@ acttable_t CWeaponCrowbar::m_acttable[] =
|
||||
{ ACT_MELEE_ATTACK1, ACT_MELEE_ATTACK_SWING, true },
|
||||
{ ACT_IDLE, ACT_IDLE_ANGRY_MELEE, false },
|
||||
{ ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_MELEE, false },
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_RUN, ACT_RUN_MELEE, false },
|
||||
{ ACT_WALK, ACT_WALK_MELEE, false },
|
||||
|
||||
{ ACT_ARM, ACT_ARM_MELEE, false },
|
||||
{ ACT_DISARM, ACT_DISARM_MELEE, false },
|
||||
#endif
|
||||
};
|
||||
|
||||
IMPLEMENT_ACTTABLE(CWeaponCrowbar);
|
||||
|
@ -46,6 +46,12 @@ public:
|
||||
// Animation event
|
||||
virtual void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Don't use backup activities
|
||||
acttable_t *GetBackupActivityList() { return NULL; }
|
||||
int GetBackupActivityListCount() { return 0; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Animation event handlers
|
||||
void HandleAnimEventMeleeHit( animevent_t *pEvent, CBaseCombatCharacter *pOperator );
|
||||
|
@ -108,6 +108,12 @@ public:
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Pistols are their own backup activities
|
||||
virtual acttable_t *GetBackupActivityList() { return NULL; }
|
||||
virtual int GetBackupActivityListCount() { return 0; }
|
||||
#endif
|
||||
|
||||
DECLARE_ACTTABLE();
|
||||
|
||||
private:
|
||||
@ -155,6 +161,40 @@ acttable_t CWeaponPistol::m_acttable[] =
|
||||
// Activities ported from weapon_alyxgun below
|
||||
//
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
// Readiness activities (not aiming)
|
||||
{ ACT_IDLE_RELAXED, ACT_IDLE_PISTOL_RELAXED, false },//never aims
|
||||
{ ACT_IDLE_STIMULATED, ACT_IDLE_PISTOL_STIMULATED, false },
|
||||
{ ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_PISTOL, false },//always aims
|
||||
{ ACT_IDLE_STEALTH, ACT_IDLE_STEALTH_PISTOL, false },
|
||||
|
||||
{ ACT_WALK_RELAXED, ACT_WALK_PISTOL_RELAXED, false },//never aims
|
||||
{ ACT_WALK_STIMULATED, ACT_WALK_PISTOL_STIMULATED, false },
|
||||
{ ACT_WALK_AGITATED, ACT_WALK_AIM_PISTOL, false },//always aims
|
||||
{ ACT_WALK_STEALTH, ACT_WALK_STEALTH_PISTOL, false },
|
||||
|
||||
{ ACT_RUN_RELAXED, ACT_RUN_PISTOL_RELAXED, false },//never aims
|
||||
{ ACT_RUN_STIMULATED, ACT_RUN_PISTOL_STIMULATED, false },
|
||||
{ ACT_RUN_AGITATED, ACT_RUN_AIM_PISTOL, false },//always aims
|
||||
{ ACT_RUN_STEALTH, ACT_RUN_STEALTH_PISTOL, false },
|
||||
|
||||
// Readiness activities (aiming)
|
||||
{ ACT_IDLE_AIM_RELAXED, ACT_IDLE_PISTOL_RELAXED, false },//never aims
|
||||
{ ACT_IDLE_AIM_STIMULATED, ACT_IDLE_AIM_PISTOL_STIMULATED, false },
|
||||
{ ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_PISTOL, false },//always aims
|
||||
{ ACT_IDLE_AIM_STEALTH, ACT_IDLE_STEALTH_PISTOL, false },
|
||||
|
||||
{ ACT_WALK_AIM_RELAXED, ACT_WALK_PISTOL_RELAXED, false },//never aims
|
||||
{ ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_PISTOL, false },
|
||||
{ ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_PISTOL, false },//always aims
|
||||
{ ACT_WALK_AIM_STEALTH, ACT_WALK_AIM_STEALTH_PISTOL, false },//always aims
|
||||
|
||||
{ ACT_RUN_AIM_RELAXED, ACT_RUN_PISTOL_RELAXED, false },//never aims
|
||||
{ ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_PISTOL, false },
|
||||
{ ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_PISTOL, false },//always aims
|
||||
{ ACT_RUN_AIM_STEALTH, ACT_RUN_AIM_STEALTH_PISTOL, false },//always aims
|
||||
//End readiness activities
|
||||
#else
|
||||
// Readiness activities (not aiming)
|
||||
{ ACT_IDLE_RELAXED, ACT_IDLE_PISTOL, false },//never aims
|
||||
{ ACT_IDLE_STIMULATED, ACT_IDLE_STIMULATED, false },
|
||||
@ -187,6 +227,7 @@ acttable_t CWeaponPistol::m_acttable[] =
|
||||
{ ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_PISTOL, false },//always aims
|
||||
{ ACT_RUN_AIM_STEALTH, ACT_RUN_AIM_STEALTH_PISTOL, false },//always aims
|
||||
//End readiness activities
|
||||
#endif
|
||||
|
||||
// Crouch activities
|
||||
{ ACT_CROUCHIDLE_STIMULATED, ACT_CROUCHIDLE_STIMULATED, false },
|
||||
@ -199,11 +240,41 @@ acttable_t CWeaponPistol::m_acttable[] =
|
||||
{ ACT_READINESS_AGITATED_TO_STIMULATED, ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED, false },
|
||||
{ ACT_READINESS_STIMULATED_TO_RELAXED, ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED, false },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_WALK_CROUCH, ACT_WALK_CROUCH_PISTOL, true },
|
||||
{ ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_PISTOL, true },
|
||||
{ ACT_RUN_CROUCH, ACT_RUN_CROUCH_PISTOL, true },
|
||||
{ ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_PISTOL, true },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
{ ACT_RANGE_AIM_MED, ACT_RANGE_AIM_PISTOL_MED, false },
|
||||
{ ACT_RANGE_ATTACK1_MED, ACT_RANGE_ATTACK_PISTOL_MED, false },
|
||||
|
||||
{ ACT_COVER_WALL_R, ACT_COVER_WALL_R_PISTOL, false },
|
||||
{ ACT_COVER_WALL_L, ACT_COVER_WALL_L_PISTOL, false },
|
||||
{ ACT_COVER_WALL_LOW_R, ACT_COVER_WALL_LOW_R_PISTOL, false },
|
||||
{ ACT_COVER_WALL_LOW_L, ACT_COVER_WALL_LOW_L_PISTOL, false },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_ACTTABLE( CWeaponPistol );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Allows Weapon_BackupActivity() to access the pistol's activity table.
|
||||
acttable_t *GetPistolActtable()
|
||||
{
|
||||
return CWeaponPistol::m_acttable;
|
||||
}
|
||||
|
||||
int GetPistolActtableCount()
|
||||
{
|
||||
return ARRAYSIZE(CWeaponPistol::m_acttable);
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1399,6 +1399,11 @@ PRECACHE_WEAPON_REGISTER(weapon_rpg);
|
||||
acttable_t CWeaponRPG::m_acttable[] =
|
||||
{
|
||||
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_RPG, true },
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_RPG_LOW, false },
|
||||
{ ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_RPG_LOW, false },
|
||||
{ ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_RPG, false },
|
||||
#endif
|
||||
|
||||
{ ACT_IDLE_RELAXED, ACT_IDLE_RPG_RELAXED, true },
|
||||
{ ACT_IDLE_STIMULATED, ACT_IDLE_ANGRY_RPG, true },
|
||||
@ -1411,6 +1416,16 @@ acttable_t CWeaponRPG::m_acttable[] =
|
||||
{ ACT_RUN, ACT_RUN_RPG, true },
|
||||
{ ACT_RUN_CROUCH, ACT_RUN_CROUCH_RPG, true },
|
||||
{ ACT_COVER_LOW, ACT_COVER_LOW_RPG, true },
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_ARM, ACT_ARM_RPG, false },
|
||||
{ ACT_DISARM, ACT_DISARM_RPG, false },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
{ ACT_RANGE_AIM_MED, ACT_RANGE_AIM_RPG_MED, false },
|
||||
{ ACT_RANGE_ATTACK1_MED, ACT_RANGE_ATTACK_RPG_MED, false },
|
||||
#endif
|
||||
};
|
||||
|
||||
IMPLEMENT_ACTTABLE(CWeaponRPG);
|
||||
|
@ -108,6 +108,57 @@ END_DATADESC()
|
||||
|
||||
acttable_t CWeaponShotgun::m_acttable[] =
|
||||
{
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
// Note that ACT_IDLE_SHOTGUN_AGITATED seems to be a stand-in for ACT_IDLE_SHOTGUN on citizens,
|
||||
// but that isn't acceptable for NPCs which don't use readiness activities.
|
||||
{ ACT_IDLE, ACT_IDLE_SHOTGUN, true },
|
||||
|
||||
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, true },
|
||||
{ ACT_RELOAD, ACT_RELOAD_SHOTGUN, false },
|
||||
{ ACT_WALK, ACT_WALK_SHOTGUN, true },
|
||||
{ ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_SHOTGUN, true },
|
||||
|
||||
// Readiness activities (not aiming)
|
||||
{ ACT_IDLE_RELAXED, ACT_IDLE_SHOTGUN_RELAXED, false },//never aims
|
||||
{ ACT_IDLE_STIMULATED, ACT_IDLE_SHOTGUN_STIMULATED, false },
|
||||
{ ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_SHOTGUN, false },//always aims
|
||||
|
||||
{ ACT_WALK_RELAXED, ACT_WALK_SHOTGUN_RELAXED, false },//never aims
|
||||
{ ACT_WALK_STIMULATED, ACT_WALK_SHOTGUN_STIMULATED, false },
|
||||
{ ACT_WALK_AGITATED, ACT_WALK_AIM_SHOTGUN, false },//always aims
|
||||
|
||||
{ ACT_RUN_RELAXED, ACT_RUN_SHOTGUN_RELAXED, false },//never aims
|
||||
{ ACT_RUN_STIMULATED, ACT_RUN_SHOTGUN_STIMULATED, false },
|
||||
{ ACT_RUN_AGITATED, ACT_RUN_AIM_SHOTGUN, false },//always aims
|
||||
|
||||
// Readiness activities (aiming)
|
||||
{ ACT_IDLE_AIM_RELAXED, ACT_IDLE_SHOTGUN_RELAXED, false },//never aims
|
||||
{ ACT_IDLE_AIM_STIMULATED, ACT_IDLE_AIM_SHOTGUN_STIMULATED, false },
|
||||
{ ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_SHOTGUN, false },//always aims
|
||||
|
||||
{ ACT_WALK_AIM_RELAXED, ACT_WALK_SHOTGUN_RELAXED, false },//never aims
|
||||
{ ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_SHOTGUN_STIMULATED, false },
|
||||
{ ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_SHOTGUN, false },//always aims
|
||||
|
||||
{ ACT_RUN_AIM_RELAXED, ACT_RUN_SHOTGUN_RELAXED, false },//never aims
|
||||
{ ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_SHOTGUN_STIMULATED, false },
|
||||
{ ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_SHOTGUN, false },//always aims
|
||||
//End readiness activities
|
||||
|
||||
{ ACT_WALK_AIM, ACT_WALK_AIM_SHOTGUN, true },
|
||||
{ ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true },
|
||||
{ ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true },
|
||||
{ ACT_RUN, ACT_RUN_SHOTGUN, true },
|
||||
{ ACT_RUN_AIM, ACT_RUN_AIM_SHOTGUN, true },
|
||||
{ ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, true },
|
||||
{ ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, true },
|
||||
{ ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_SHOTGUN, true },
|
||||
{ ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_SHOTGUN_LOW, true },
|
||||
{ ACT_RELOAD_LOW, ACT_RELOAD_SHOTGUN_LOW, false },
|
||||
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SHOTGUN, false },
|
||||
{ ACT_COVER_LOW, ACT_COVER_SHOTGUN_LOW, false },
|
||||
{ ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_SHOTGUN_LOW, false },
|
||||
#else
|
||||
{ ACT_IDLE, ACT_IDLE_SMG1, true }, // FIXME: hook to shotgun unique
|
||||
|
||||
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, true },
|
||||
@ -153,6 +204,17 @@ acttable_t CWeaponShotgun::m_acttable[] =
|
||||
{ ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_SHOTGUN_LOW, true },
|
||||
{ ACT_RELOAD_LOW, ACT_RELOAD_SHOTGUN_LOW, false },
|
||||
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SHOTGUN, false },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_ARM, ACT_ARM_SHOTGUN, true },
|
||||
{ ACT_DISARM, ACT_DISARM_SHOTGUN, true },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
{ ACT_RANGE_AIM_MED, ACT_RANGE_AIM_SHOTGUN_MED, false },
|
||||
{ ACT_RANGE_ATTACK1_MED, ACT_RANGE_ATTACK_SHOTGUN_MED, false },
|
||||
#endif
|
||||
};
|
||||
|
||||
IMPLEMENT_ACTTABLE(CWeaponShotgun);
|
||||
|
@ -134,6 +134,21 @@ acttable_t CWeaponSMG1::m_acttable[] =
|
||||
{ ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_SMG1_LOW, false },
|
||||
{ ACT_RELOAD_LOW, ACT_RELOAD_SMG1_LOW, false },
|
||||
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, true },
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_ARM, ACT_ARM_RIFLE, false },
|
||||
{ ACT_DISARM, ACT_DISARM_RIFLE, false },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
{ ACT_RANGE_AIM_MED, ACT_RANGE_AIM_SMG1_MED, false },
|
||||
{ ACT_RANGE_ATTACK1_MED, ACT_RANGE_ATTACK_SMG1_MED, false },
|
||||
|
||||
{ ACT_COVER_WALL_R, ACT_COVER_WALL_R_RIFLE, false },
|
||||
{ ACT_COVER_WALL_L, ACT_COVER_WALL_L_RIFLE, false },
|
||||
{ ACT_COVER_WALL_LOW_R, ACT_COVER_WALL_LOW_R_RIFLE, false },
|
||||
{ ACT_COVER_WALL_LOW_L, ACT_COVER_WALL_LOW_L_RIFLE, false },
|
||||
#endif
|
||||
};
|
||||
|
||||
IMPLEMENT_ACTTABLE(CWeaponSMG1);
|
||||
|
@ -41,6 +41,7 @@
|
||||
DEFINE_FIELD( m_vecTossVelocity, FIELD_VECTOR ), \
|
||||
DEFINE_FIELD( m_iLastAnimEventHandled, FIELD_INTEGER ), \
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "ThrowGrenadeAtTarget", InputThrowGrenadeAtTarget ), \
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "ThrowGrenadeGestureAtTarget", InputThrowGrenadeGestureAtTarget ), \
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetGrenades", InputSetGrenades ), \
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "AddGrenades", InputAddGrenades ), \
|
||||
DEFINE_OUTPUT(m_OnThrowGrenade, "OnThrowGrenade"), \
|
||||
@ -124,6 +125,7 @@ public:
|
||||
void InputSetGrenades( inputdata_t &inputdata ) { AddGrenades( inputdata.value.Int() - m_iNumGrenades ); }
|
||||
void InputAddGrenades( inputdata_t &inputdata ) { AddGrenades( inputdata.value.Int() ); }
|
||||
void InputThrowGrenadeAtTarget( inputdata_t &inputdata );
|
||||
void InputThrowGrenadeGestureAtTarget( inputdata_t &inputdata );
|
||||
|
||||
virtual void DelayGrenadeCheck( float delay ) { m_flNextGrenadeCheck = gpGlobals->curtime + delay; }
|
||||
|
||||
@ -294,6 +296,63 @@ void CAI_GrenadeUser<BASE_NPC>::InputThrowGrenadeAtTarget( inputdata_t &inputdat
|
||||
this->ClearSchedule( "Told to throw grenade via input" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Force the combine soldier to throw a grenade at the target using the gesture animation.
|
||||
// If I'm a combine elite, fire my combine ball at the target instead.
|
||||
// Input : &inputdata -
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class BASE_NPC>
|
||||
void CAI_GrenadeUser<BASE_NPC>::InputThrowGrenadeGestureAtTarget( inputdata_t &inputdata )
|
||||
{
|
||||
// Ignore if we're inside a scripted sequence
|
||||
//if ( this->GetState() == NPC_STATE_SCRIPT && this->m_hCine )
|
||||
// return;
|
||||
|
||||
CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller );
|
||||
if ( !pEntity )
|
||||
{
|
||||
DevMsg("%s (%s) received ThrowGrenadeGestureAtTarget input, but couldn't find target entity '%s'\n", this->GetClassname(), this->GetDebugName(), inputdata.value.String() );
|
||||
return;
|
||||
}
|
||||
|
||||
m_hForcedGrenadeTarget = pEntity;
|
||||
m_flNextGrenadeCheck = 0;
|
||||
|
||||
Vector vecTarget = m_hForcedGrenadeTarget->WorldSpaceCenter();
|
||||
|
||||
#ifdef SHARED_COMBINE_ACTIVITIES
|
||||
if (IsAltFireCapable())
|
||||
{
|
||||
if (FVisible( m_hForcedGrenadeTarget ))
|
||||
{
|
||||
m_vecAltFireTarget = vecTarget;
|
||||
m_hForcedGrenadeTarget = NULL;
|
||||
|
||||
int iLayer = AddGesture( ACT_GESTURE_COMBINE_AR2_ALTFIRE );
|
||||
if (iLayer != -1)
|
||||
{
|
||||
this->GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + this->GetLayerDuration( iLayer ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we can, throw a grenade at the target.
|
||||
// Ignore grenade count / distance / etc
|
||||
if (CheckCanThrowGrenade( vecTarget ))
|
||||
{
|
||||
int iLayer = AddGesture( ACT_GESTURE_COMBINE_THROW_GRENADE );
|
||||
if (iLayer != -1)
|
||||
{
|
||||
this->GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + this->GetLayerDuration( iLayer ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
Warning("Gesture grenades/alt-fire not supported\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class BASE_NPC>
|
||||
|
@ -4099,6 +4099,11 @@ BEGIN_DATADESC(CBasePropDoor)
|
||||
DEFINE_KEYFIELD(m_SoundClose, FIELD_SOUNDNAME, "soundcloseoverride"),
|
||||
DEFINE_KEYFIELD(m_ls.sLockedSound, FIELD_SOUNDNAME, "soundlockedoverride"),
|
||||
DEFINE_KEYFIELD(m_ls.sUnlockedSound, FIELD_SOUNDNAME, "soundunlockedoverride"),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD(m_flNPCOpenDistance, FIELD_FLOAT, "opendistoverride"),
|
||||
DEFINE_KEYFIELD(m_eNPCOpenFrontActivity, FIELD_INTEGER, "openfrontactivityoverride"),
|
||||
DEFINE_KEYFIELD(m_eNPCOpenBackActivity, FIELD_INTEGER, "openbackactivityoverride"),
|
||||
#endif
|
||||
DEFINE_KEYFIELD(m_SlaveName, FIELD_STRING, "slavename" ),
|
||||
DEFINE_FIELD(m_bLocked, FIELD_BOOLEAN),
|
||||
//DEFINE_KEYFIELD(m_flBlockDamage, FIELD_FLOAT, "dmg"),
|
||||
@ -4143,6 +4148,11 @@ END_SEND_TABLE()
|
||||
CBasePropDoor::CBasePropDoor( void )
|
||||
{
|
||||
m_hMaster = NULL;
|
||||
#ifdef MAPBASE
|
||||
m_flNPCOpenDistance = -1;
|
||||
m_eNPCOpenFrontActivity = ACT_INVALID;
|
||||
m_eNPCOpenBackActivity = ACT_INVALID;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -4340,6 +4350,32 @@ void CBasePropDoor::CalcDoorSounds()
|
||||
{
|
||||
strSoundLocked = AllocPooledString( pkvHardwareData->GetString( "locked" ) );
|
||||
strSoundUnlocked = AllocPooledString( pkvHardwareData->GetString( "unlocked" ) );
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_eNPCOpenFrontActivity == ACT_INVALID)
|
||||
{
|
||||
const char *pszActivity = pkvHardwareData->GetString( "activity_front" );
|
||||
if (pszActivity[0] != '\0')
|
||||
{
|
||||
m_eNPCOpenFrontActivity = (Activity)CAI_BaseNPC::GetActivityID( pszActivity );
|
||||
if (m_eNPCOpenFrontActivity == ACT_INVALID)
|
||||
m_eNPCOpenFrontActivity = ActivityList_RegisterPrivateActivity( pszActivity );
|
||||
}
|
||||
}
|
||||
if (m_eNPCOpenBackActivity == ACT_INVALID)
|
||||
{
|
||||
const char *pszActivity = pkvHardwareData->GetString( "activity_back" );
|
||||
if (pszActivity[0] != '\0')
|
||||
{
|
||||
m_eNPCOpenBackActivity = (Activity)CAI_BaseNPC::GetActivityID( pszActivity );
|
||||
if (m_eNPCOpenBackActivity == ACT_INVALID)
|
||||
m_eNPCOpenBackActivity = ActivityList_RegisterPrivateActivity( pszActivity );
|
||||
}
|
||||
}
|
||||
|
||||
if (m_flNPCOpenDistance == -1)
|
||||
m_flNPCOpenDistance = pkvHardwareData->GetFloat( "npc_distance", 32.0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
// If any sounds were missing, try the "defaults" block.
|
||||
@ -5940,6 +5976,11 @@ void CPropDoorRotating::DoorResume( void )
|
||||
AngularMove( m_angGoal, m_flSpeed );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar ai_door_enable_acts( "ai_door_enable_acts", "1", FCVAR_NONE, "Enables the new door-opening activities." );
|
||||
ConVar ai_door_open_dist_override( "ai_door_open_dist_override", "-1", FCVAR_NONE, "Overrides the distance from a door a NPC has to navigate to in order to open a door." );
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : vecMoveDir -
|
||||
@ -5961,20 +6002,37 @@ void CPropDoorRotating::GetNPCOpenData(CAI_BaseNPC *pNPC, opendata_t &opendata)
|
||||
|
||||
Vector vecNPCOrigin = pNPC->GetAbsOrigin();
|
||||
|
||||
#ifdef MAPBASE
|
||||
float flPosOffset = ai_door_open_dist_override.GetFloat() >= 0.0f ? ai_door_open_dist_override.GetFloat() : GetNPCOpenDistance();
|
||||
#else
|
||||
float flPosOffset = 64;
|
||||
#endif
|
||||
|
||||
if (pNPC->GetAbsOrigin().Dot(vecForward) > GetAbsOrigin().Dot(vecForward))
|
||||
{
|
||||
// In front of the door relative to the door's forward vector.
|
||||
opendata.vecStandPos += vecForward * 64;
|
||||
opendata.vecStandPos += vecForward * flPosOffset;
|
||||
opendata.vecFaceDir = -vecForward;
|
||||
#ifdef MAPBASE
|
||||
opendata.eActivity = !ai_door_enable_acts.GetBool() ? ACT_INVALID : GetNPCOpenFrontActivity();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Behind the door relative to the door's forward vector.
|
||||
opendata.vecStandPos -= vecForward * 64;
|
||||
opendata.vecStandPos -= vecForward * flPosOffset;
|
||||
opendata.vecFaceDir = vecForward;
|
||||
#ifdef MAPBASE
|
||||
opendata.eActivity = !ai_door_enable_acts.GetBool() ? ACT_INVALID : GetNPCOpenBackActivity();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (opendata.eActivity == ACT_INVALID)
|
||||
opendata.eActivity = ACT_OPEN_DOOR;
|
||||
#else
|
||||
opendata.eActivity = ACT_OPEN_DOOR;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -2296,15 +2296,22 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_AR2 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RELOAD_AR2 );
|
||||
//REGISTER_SHARED_ACTIVITY( ACT_RELOAD_AR2_LOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RELOAD_AR2_LOW );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD_AR2 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_AR2_LOW );
|
||||
#endif
|
||||
|
||||
#ifdef SHARED_COMBINE_ACTIVITIES
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COMBINE_THROW_GRENADE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COMBINE_AR2_ALTFIRE );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_COMBINE_THROW_GRENADE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_COMBINE_AR2_ALTFIRE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_SPECIAL_ATTACK1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_SPECIAL_ATTACK2 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_SIGNAL_ADVANCE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_SIGNAL_FORWARD );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_SIGNAL_GROUP );
|
||||
@ -2314,9 +2321,133 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_SIGNAL_TAKECOVER );
|
||||
#endif
|
||||
|
||||
#ifdef COMPANION_HOLSTER_WORKAROUND
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
REGISTER_SHARED_ACTIVITY( ACT_IDLE_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RELOAD_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_REVOLVER_LOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RELOAD_REVOLVER_LOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_REVOLVER_LOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_REVOLVER_LOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD_REVOLVER );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_IDLE_CROSSBOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_CROSSBOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_CROSSBOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_CROSSBOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_CROSSBOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_CROSSBOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_CROSSBOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RELOAD_CROSSBOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_CROSSBOW_LOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RELOAD_CROSSBOW_LOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_CROSSBOW_LOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_CROSSBOW_LOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_CROSSBOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD_CROSSBOW );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_IDLE_PISTOL_RELAXED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_IDLE_PISTOL_STIMULATED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_PISTOL_RELAXED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_PISTOL_STIMULATED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_PISTOL_RELAXED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_PISTOL_STIMULATED );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_IDLE_AIM_PISTOL_STIMULATED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_PISTOL_STIMULATED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_PISTOL_STIMULATED );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_CROUCH_PISTOL );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_CROUCH_AIM_PISTOL );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_CROUCH_PISTOL );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_CROUCH_AIM_PISTOL );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_IDLE_SHOTGUN );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_SHOTGUN );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_SHOTGUN );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_SHOTGUN_LOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_SHOTGUN_LOW );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_SHOTGUN_RELAXED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_SHOTGUN_STIMULATED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_SHOTGUN_RELAXED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_SHOTGUN_STIMULATED );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_IDLE_AIM_SHOTGUN_STIMULATED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_SHOTGUN_STIMULATED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_SHOTGUN_STIMULATED );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_RPG_LOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_RPG_LOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_RPG );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_WALK_MELEE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_MELEE );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_PACKAGE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RUN_SUITCASE );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_ARM_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_ARM_SHOTGUN );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_ARM_RPG );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_ARM_MELEE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_DISARM_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_DISARM_SHOTGUN );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_DISARM_RPG );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_DISARM_MELEE );
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
REGISTER_SHARED_ACTIVITY( ACT_CLIMB_ALL );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_CLIMB_IDLE );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_CLIMB_MOUNT_TOP );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_CLIMB_MOUNT_BOTTOM );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_CLIMB_DISMOUNT_BOTTOM );
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK1_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK2_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_MED );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_AR2_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_SMG1_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_SHOTGUN_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_PISTOL_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_RPG_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_REVOLVER_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_CROSSBOW_MED );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_AR2_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_SMG1_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_SHOTGUN_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_PISTOL_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_RPG_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_REVOLVER_MED );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_CROSSBOW_MED );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_R );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_L );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_LOW_R );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_LOW_L );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_R_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_L_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_LOW_R_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_LOW_L_RIFLE );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_R_PISTOL );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_L_PISTOL );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_LOW_R_PISTOL );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_LOW_L_PISTOL );
|
||||
#endif
|
||||
|
||||
AssertMsg( g_HighestActivity == LAST_SHARED_ACTIVITY - 1, "Not all activities from ai_activity.h registered in activitylist.cpp" );
|
||||
|
@ -13,42 +13,42 @@
|
||||
|
||||
#ifdef MAPBASE
|
||||
|
||||
// Mapbase adds a few shared activities.
|
||||
//
|
||||
// These used to be placed in between existing activities, as outside of the code activities are based off of strings.
|
||||
// This seemed like a bad idea, but no problems arose at the time.
|
||||
// I later discovered that apparently some things in MP use the direct integers instead of the enum names.
|
||||
// I retroactively put all custom activities at the bottom of the enum instead.
|
||||
// Their placements in activitylist.cpp and ai_activity.cpp have not been changed.
|
||||
// Mapbase adds many new shared activities, primarily for NPCs.
|
||||
//
|
||||
// These are at the bottom of the enum to prevent disruptions in the order of existing activities.
|
||||
//
|
||||
|
||||
// AR2 ACTIVITY FIX
|
||||
// You know all of those AR2 activities that citizens and combine soldiers have?
|
||||
// Yeah, those are unused. It appears Valve forgot to implement them.
|
||||
// Citizens and Combine soldiers have several activities for the SMG1 and AR2 which differ from each other.
|
||||
// Across both NPCs, there are around 20-40 different AR2 animations. Most of these animations are similar to the
|
||||
// SMG1 animations, except their hand positions are adjusted to use the AR2 instead.
|
||||
//
|
||||
// What could be 20-40 different animations on two different characters are not even defined in code.
|
||||
// I didn't even realize they were unused until I saw ACT_RELOAD_AR2, so I don't blame them for never realizing this.
|
||||
// They work surprisingly well for probably never being tested in-game.
|
||||
// Unfortunately, the vast majority of the AR2 animations in those models are not declared as real activities in
|
||||
// code. The AR2 instead falls back to its SMG1 animation counterparts.
|
||||
// This is thought to be an oversight which dates back to late in Half-Life 2's development.
|
||||
//
|
||||
// 1 = Add activities directly
|
||||
// 2 = Add activities as custom activities (todo)
|
||||
//
|
||||
// 2 should only be preferable if adding them like this breaks something.
|
||||
// This preprocessor declares those activities and implements them on the AR2. In-game, they work surprisingly well
|
||||
// despite presumably never being tested in-game during HL2's development.
|
||||
#define AR2_ACTIVITY_FIX 1
|
||||
|
||||
// COMPANION HOLSTER WORKAROUND
|
||||
// I introduced a separate holster/unholster animation to male_shared
|
||||
// and female_shared and I realized it might conflict with Alyx's animation.
|
||||
//
|
||||
// I came up with a solution--ACT_ARM_RIFLE and its disarm counterpart--to solve it.
|
||||
// I didn't think about the fact I could've named them the same as Alyx's so her animations would overwrite it...
|
||||
// ...so this has been deactivated.
|
||||
//#define COMPANION_HOLSTER_WORKAROUND 1
|
||||
|
||||
// SHARED COMBINE ACTIVITIES
|
||||
// This turns ACT_COMBINE_AR2_ALTFIRE and ACT_COMBINE_THROW_GRENADE into shared activities.
|
||||
// This is necessary so other NPCs to use them without having to rely on a bunch of custom activities.
|
||||
// This turns ACT_COMBINE_AR2_ALTFIRE, ACT_COMBINE_THROW_GRENADE, and their new gesture counterparts into shared activities.
|
||||
// This is necessary for other NPCs to use them without having to rely on private custom activities declared through the AI definition system.
|
||||
#define SHARED_COMBINE_ACTIVITIES 1
|
||||
|
||||
// EXPANDED HL2 WEAPON ACTIVITIES
|
||||
// This enables a bunch of new activities for Half-Life 2 weapons, including new 357 animations and readiness activities for pistols.
|
||||
#define EXPANDED_HL2_WEAPON_ACTIVITIES 1
|
||||
|
||||
// EXPANDED NAVIGATION ACTIVITIES
|
||||
// This enables some new navigation-related activities.
|
||||
#define EXPANDED_NAVIGATION_ACTIVITIES 1
|
||||
|
||||
// EXPANDED HL2 COVER ACTIVITIES
|
||||
// This enables some new cover-related activities.
|
||||
#define EXPANDED_HL2_COVER_ACTIVITIES 1
|
||||
|
||||
#endif
|
||||
|
||||
#define ACTIVITY_NOT_AVAILABLE -1
|
||||
@ -2169,16 +2169,23 @@ typedef enum
|
||||
ACT_RUN_AIM_AR2,
|
||||
|
||||
ACT_RELOAD_AR2,
|
||||
//ACT_RELOAD_AR2_LOW,
|
||||
ACT_RELOAD_AR2_LOW,
|
||||
|
||||
ACT_GESTURE_RELOAD_AR2,
|
||||
|
||||
ACT_COVER_AR2_LOW,
|
||||
#endif
|
||||
|
||||
#ifdef SHARED_COMBINE_ACTIVITIES
|
||||
ACT_COMBINE_THROW_GRENADE,
|
||||
ACT_COMBINE_AR2_ALTFIRE,
|
||||
|
||||
// New gesture-based signals as activities for people who want to use them
|
||||
// Gesture versions for existing Combine signal and grenade activities
|
||||
ACT_GESTURE_COMBINE_THROW_GRENADE,
|
||||
ACT_GESTURE_COMBINE_AR2_ALTFIRE,
|
||||
ACT_GESTURE_SPECIAL_ATTACK1,
|
||||
ACT_GESTURE_SPECIAL_ATTACK2,
|
||||
|
||||
ACT_GESTURE_SIGNAL_ADVANCE,
|
||||
ACT_GESTURE_SIGNAL_FORWARD,
|
||||
ACT_GESTURE_SIGNAL_GROUP,
|
||||
@ -2188,9 +2195,143 @@ typedef enum
|
||||
ACT_GESTURE_SIGNAL_TAKECOVER,
|
||||
#endif
|
||||
|
||||
#ifdef COMPANION_HOLSTER_WORKAROUND
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
// Revolver (357)
|
||||
ACT_IDLE_REVOLVER,
|
||||
ACT_IDLE_ANGRY_REVOLVER,
|
||||
ACT_WALK_REVOLVER,
|
||||
ACT_RUN_REVOLVER,
|
||||
ACT_WALK_AIM_REVOLVER,
|
||||
ACT_RUN_AIM_REVOLVER,
|
||||
ACT_RANGE_ATTACK_REVOLVER,
|
||||
ACT_RELOAD_REVOLVER,
|
||||
ACT_RANGE_ATTACK_REVOLVER_LOW,
|
||||
ACT_RELOAD_REVOLVER_LOW,
|
||||
ACT_COVER_REVOLVER_LOW,
|
||||
ACT_RANGE_AIM_REVOLVER_LOW,
|
||||
ACT_GESTURE_RANGE_ATTACK_REVOLVER,
|
||||
ACT_GESTURE_RELOAD_REVOLVER,
|
||||
|
||||
// Crossbow
|
||||
ACT_IDLE_CROSSBOW,
|
||||
ACT_IDLE_ANGRY_CROSSBOW,
|
||||
ACT_WALK_CROSSBOW,
|
||||
ACT_RUN_CROSSBOW,
|
||||
ACT_WALK_AIM_CROSSBOW,
|
||||
ACT_RUN_AIM_CROSSBOW,
|
||||
ACT_RANGE_ATTACK_CROSSBOW,
|
||||
ACT_RELOAD_CROSSBOW,
|
||||
ACT_RANGE_ATTACK_CROSSBOW_LOW,
|
||||
ACT_RELOAD_CROSSBOW_LOW,
|
||||
ACT_COVER_CROSSBOW_LOW,
|
||||
ACT_RANGE_AIM_CROSSBOW_LOW,
|
||||
ACT_GESTURE_RANGE_ATTACK_CROSSBOW,
|
||||
ACT_GESTURE_RELOAD_CROSSBOW,
|
||||
|
||||
// Pistol
|
||||
ACT_IDLE_PISTOL_RELAXED,
|
||||
ACT_IDLE_PISTOL_STIMULATED,
|
||||
ACT_WALK_PISTOL_RELAXED,
|
||||
ACT_WALK_PISTOL_STIMULATED,
|
||||
ACT_RUN_PISTOL_RELAXED,
|
||||
ACT_RUN_PISTOL_STIMULATED,
|
||||
|
||||
ACT_IDLE_AIM_PISTOL_STIMULATED,
|
||||
ACT_WALK_AIM_PISTOL_STIMULATED,
|
||||
ACT_RUN_AIM_PISTOL_STIMULATED,
|
||||
|
||||
ACT_WALK_CROUCH_PISTOL,
|
||||
ACT_WALK_CROUCH_AIM_PISTOL,
|
||||
ACT_RUN_CROUCH_PISTOL,
|
||||
ACT_RUN_CROUCH_AIM_PISTOL,
|
||||
|
||||
// Shotgun
|
||||
ACT_IDLE_SHOTGUN,
|
||||
ACT_WALK_SHOTGUN,
|
||||
ACT_RUN_SHOTGUN,
|
||||
|
||||
ACT_COVER_SHOTGUN_LOW,
|
||||
ACT_RANGE_AIM_SHOTGUN_LOW,
|
||||
|
||||
ACT_WALK_SHOTGUN_RELAXED,
|
||||
ACT_WALK_SHOTGUN_STIMULATED,
|
||||
ACT_RUN_SHOTGUN_RELAXED,
|
||||
ACT_RUN_SHOTGUN_STIMULATED,
|
||||
|
||||
ACT_IDLE_AIM_SHOTGUN_STIMULATED,
|
||||
ACT_WALK_AIM_SHOTGUN_STIMULATED,
|
||||
ACT_RUN_AIM_SHOTGUN_STIMULATED,
|
||||
|
||||
// RPG
|
||||
ACT_RANGE_AIM_RPG_LOW,
|
||||
ACT_RANGE_ATTACK_RPG_LOW,
|
||||
ACT_GESTURE_RANGE_ATTACK_RPG,
|
||||
|
||||
// Melee
|
||||
ACT_WALK_MELEE,
|
||||
ACT_RUN_MELEE,
|
||||
|
||||
// Citizen accessories
|
||||
ACT_RUN_PACKAGE,
|
||||
ACT_RUN_SUITCASE,
|
||||
|
||||
// Holster/Unholster
|
||||
ACT_ARM_RIFLE,
|
||||
ACT_ARM_SHOTGUN,
|
||||
ACT_ARM_RPG,
|
||||
ACT_ARM_MELEE,
|
||||
ACT_DISARM_RIFLE,
|
||||
ACT_DISARM_SHOTGUN,
|
||||
ACT_DISARM_RPG,
|
||||
ACT_DISARM_MELEE,
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
ACT_CLIMB_ALL, // An actual blend animation which uses pose parameters for direction
|
||||
ACT_CLIMB_IDLE,
|
||||
|
||||
ACT_CLIMB_MOUNT_TOP,
|
||||
ACT_CLIMB_MOUNT_BOTTOM,
|
||||
ACT_CLIMB_DISMOUNT_BOTTOM,
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
// Crouch Cover Medium
|
||||
ACT_RANGE_ATTACK1_MED,
|
||||
ACT_RANGE_ATTACK2_MED,
|
||||
ACT_RANGE_AIM_MED,
|
||||
|
||||
ACT_RANGE_ATTACK_AR2_MED,
|
||||
ACT_RANGE_ATTACK_SMG1_MED,
|
||||
ACT_RANGE_ATTACK_SHOTGUN_MED,
|
||||
ACT_RANGE_ATTACK_PISTOL_MED,
|
||||
ACT_RANGE_ATTACK_RPG_MED,
|
||||
ACT_RANGE_ATTACK_REVOLVER_MED,
|
||||
ACT_RANGE_ATTACK_CROSSBOW_MED,
|
||||
|
||||
ACT_RANGE_AIM_AR2_MED,
|
||||
ACT_RANGE_AIM_SMG1_MED,
|
||||
ACT_RANGE_AIM_SHOTGUN_MED,
|
||||
ACT_RANGE_AIM_PISTOL_MED,
|
||||
ACT_RANGE_AIM_RPG_MED,
|
||||
ACT_RANGE_AIM_REVOLVER_MED,
|
||||
ACT_RANGE_AIM_CROSSBOW_MED,
|
||||
|
||||
// Wall Cover (for use in custom cover hints)
|
||||
ACT_COVER_WALL_R,
|
||||
ACT_COVER_WALL_L,
|
||||
ACT_COVER_WALL_LOW_R,
|
||||
ACT_COVER_WALL_LOW_L,
|
||||
|
||||
ACT_COVER_WALL_R_RIFLE,
|
||||
ACT_COVER_WALL_L_RIFLE,
|
||||
ACT_COVER_WALL_LOW_R_RIFLE,
|
||||
ACT_COVER_WALL_LOW_L_RIFLE,
|
||||
|
||||
ACT_COVER_WALL_R_PISTOL,
|
||||
ACT_COVER_WALL_L_PISTOL,
|
||||
ACT_COVER_WALL_LOW_R_PISTOL,
|
||||
ACT_COVER_WALL_LOW_L_PISTOL,
|
||||
#endif
|
||||
|
||||
// this is the end of the global activities, private per-monster activities start here.
|
||||
|
@ -1046,7 +1046,13 @@ WeaponClass_t CBaseCombatWeapon::WeaponClassify()
|
||||
Activity idleact = ActivityOverride(ACT_IDLE_ANGRY, NULL);
|
||||
switch (idleact)
|
||||
{
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
case ACT_IDLE_ANGRY_REVOLVER:
|
||||
#endif
|
||||
case ACT_IDLE_ANGRY_PISTOL: return WEPCLASS_HANDGUN;
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
case ACT_IDLE_ANGRY_CROSSBOW: // For now, crossbows are rifles
|
||||
#endif
|
||||
case ACT_IDLE_ANGRY_SMG1:
|
||||
case ACT_IDLE_ANGRY_AR2: return WEPCLASS_RIFLE;
|
||||
case ACT_IDLE_ANGRY_SHOTGUN: return WEPCLASS_SHOTGUN;
|
||||
@ -1077,6 +1083,11 @@ WeaponClass_t CBaseCombatWeapon::WeaponClassFromString(const char *str)
|
||||
return WEPCLASS_INVALID;
|
||||
}
|
||||
|
||||
#ifdef HL2_DLL
|
||||
extern acttable_t *GetSMG1Acttable();
|
||||
extern int GetSMG1ActtableCount();
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1084,12 +1095,32 @@ bool CBaseCombatWeapon::SupportsBackupActivity(Activity activity)
|
||||
{
|
||||
// Derived classes should override this.
|
||||
|
||||
// Pistol and melee users should not use SMG animations for missing pistol activities.
|
||||
if (WeaponClassify() == WEPCLASS_HANDGUN || IsMeleeWeapon())
|
||||
#ifdef HL2_DLL
|
||||
// Melee users should not use SMG animations for missing activities.
|
||||
if (IsMeleeWeapon() && GetBackupActivityList() == GetSMG1Acttable())
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
acttable_t *CBaseCombatWeapon::GetBackupActivityList()
|
||||
{
|
||||
#ifdef HL2_DLL
|
||||
return GetSMG1Acttable();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int CBaseCombatWeapon::GetBackupActivityListCount()
|
||||
{
|
||||
#ifdef HL2_DLL
|
||||
return GetSMG1ActtableCount();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -2343,9 +2374,10 @@ bool CBaseCombatWeapon::Reload( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCombatWeapon::Reload_NPC( void )
|
||||
void CBaseCombatWeapon::Reload_NPC( bool bPlaySound )
|
||||
{
|
||||
WeaponSound( RELOAD_NPC );
|
||||
if (bPlaySound)
|
||||
WeaponSound( RELOAD_NPC );
|
||||
|
||||
if (UsesClipsForAmmo1())
|
||||
{
|
||||
|
@ -230,6 +230,8 @@ public:
|
||||
static WeaponClass_t WeaponClassFromString(const char *str);
|
||||
|
||||
virtual bool SupportsBackupActivity(Activity activity);
|
||||
virtual acttable_t *GetBackupActivityList();
|
||||
virtual int GetBackupActivityListCount();
|
||||
#endif
|
||||
|
||||
virtual void Equip( CBaseCombatCharacter *pOwner );
|
||||
@ -319,7 +321,7 @@ public:
|
||||
bool ReloadsSingly( void ) const;
|
||||
#ifdef MAPBASE
|
||||
// Originally created for the crossbow, can be used to add special NPC reloading behavior
|
||||
virtual void Reload_NPC( void );
|
||||
virtual void Reload_NPC( bool bPlaySound = true );
|
||||
#endif
|
||||
|
||||
virtual bool AutoFiresFullClip( void ) { return false; }
|
||||
|
@ -81,6 +81,11 @@ acttable_t CWeaponStunStick::m_acttable[] =
|
||||
#endif
|
||||
{ ACT_MELEE_ATTACK1, ACT_MELEE_ATTACK_SWING, true },
|
||||
{ ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_MELEE, true },
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_IDLE, ACT_IDLE_MELEE, false },
|
||||
{ ACT_RUN, ACT_RUN_MELEE, false },
|
||||
{ ACT_WALK, ACT_WALK_MELEE, false },
|
||||
#endif
|
||||
};
|
||||
|
||||
IMPLEMENT_ACTTABLE(CWeaponStunStick);
|
||||
|
@ -83,6 +83,12 @@ public:
|
||||
|
||||
float GetDamageForActivity( Activity hitActivity );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Don't use backup activities
|
||||
acttable_t *GetBackupActivityList() { return NULL; }
|
||||
int GetBackupActivityListCount() { return 0; }
|
||||
#endif
|
||||
|
||||
CWeaponStunStick( const CWeaponStunStick & );
|
||||
|
||||
private:
|
||||
|
@ -398,9 +398,10 @@ bool CWeaponCustomScripted::Reload( void )
|
||||
return BaseClass::Reload();
|
||||
}
|
||||
|
||||
void CWeaponCustomScripted::Reload_NPC( void )
|
||||
void CWeaponCustomScripted::Reload_NPC( bool bPlaySound )
|
||||
{
|
||||
SIMPLE_VOID_OVERRIDE( Reload_NPC, NULL );
|
||||
ScriptVariant_t pArgs[] = { bPlaySound };
|
||||
SIMPLE_VOID_OVERRIDE( Reload_NPC, pArgs );
|
||||
|
||||
BaseClass::Reload_NPC();
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public:
|
||||
void FinishReload( void );
|
||||
void AbortReload( void );
|
||||
bool Reload( void );
|
||||
void Reload_NPC( void );
|
||||
void Reload_NPC( bool bPlaySound = true );
|
||||
|
||||
// Weapon firing
|
||||
void PrimaryAttack( void ); // do "+ATTACK"
|
||||
|
Loading…
Reference in New Issue
Block a user