Added support for NPC door opening activities and adjustable open distance

This commit is contained in:
Blixibon 2021-11-04 09:27:30 -05:00
parent 97a6934061
commit 0ce4251ba3
4 changed files with 125 additions and 2 deletions

View File

@ -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.

View File

@ -9763,7 +9763,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 );
@ -13951,6 +13955,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;
@ -13971,6 +13979,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);
@ -13980,6 +14003,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 );
@ -13999,6 +14023,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
}

View File

@ -2184,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 ))
@ -2719,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
{

View File

@ -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
}