//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: A base class for model-based doors. The exact movement required to // open or close the door is not dictated by this class, only //that the door has open, closed, opening, and closing states. // // Doors must satisfy these requirements: // // - Derived classes must support being opened by NPCs. // - Never autoclose in the face of a player. // - Never close into an NPC. // //=============================================================================// #ifndef BASEPROPDOOR_H #define BASEPROPDOOR_H #ifdef _WIN32 #pragma once #endif #include "entityoutput.h" #include "locksounds.h" #include "props.h" extern ConVar g_debug_doors; struct opendata_t { Vector vecStandPos; // Where the NPC should stand. Vector vecFaceDir; // What direction the NPC should face. Activity eActivity; // What activity the NPC should play. }; abstract_class CBasePropDoor : public CDynamicProp { public: DECLARE_CLASS(CBasePropDoor, CDynamicProp); DECLARE_SERVERCLASS(); CBasePropDoor(void); void Spawn(); void Precache(); void Activate(); int ObjectCaps(); void HandleAnimEvent(animevent_t * pEvent); // Base class services. // Do not make the functions in this block virtual!! // { inline bool IsDoorOpen(); inline bool IsDoorAjar(); inline bool IsDoorOpening(); inline bool IsDoorClosed(); inline bool IsDoorClosing(); inline bool IsDoorLocked(); inline bool IsDoorBlocked() const; inline bool IsNPCOpening(CAI_BaseNPC * pNPC); inline bool IsPlayerOpening(); inline bool IsOpener(CBaseEntity * pEnt); bool NPCOpenDoor(CAI_BaseNPC * pNPC); bool TestCollision(const Ray_t &ray, unsigned int mask, trace_t &trace); // } // Implement these in your leaf class. // { virtual bool DoorCanClose(bool bAutoClose) { return true; } virtual bool DoorCanOpen(void) { return true; } virtual void GetNPCOpenData(CAI_BaseNPC * pNPC, opendata_t & opendata) = 0; virtual float GetOpenInterval(void) = 0; // } protected: enum DoorState_t { DOOR_STATE_CLOSED = 0, DOOR_STATE_OPENING, DOOR_STATE_OPEN, DOOR_STATE_CLOSING, DOOR_STATE_AJAR, }; // dvs: FIXME: make these private void DoorClose(); CBasePropDoor *GetMaster(void) { return m_hMaster; } bool HasSlaves(void) { return (m_hDoorList.Count() > 0); } inline void SetDoorState(DoorState_t eDoorState); float m_flAutoReturnDelay; // How many seconds to wait before automatically // closing, -1 never closes automatically. CUtlVector > m_hDoorList; // List of doors linked to us inline CBaseEntity *GetActivator(); private: // Implement these in your leaf class. // { // Called when the door becomes fully open. virtual void OnDoorOpened() {} // Called when the door becomes fully closed. virtual void OnDoorClosed() {} // Called to tell the door to start opening. virtual void BeginOpening(CBaseEntity * pOpenAwayFrom) = 0; // Called to tell the door to start closing. virtual void BeginClosing(void) = 0; // Called when blocked to tell the door to stop moving. virtual void DoorStop(void) = 0; // Called when blocked to tell the door to continue moving. virtual void DoorResume(void) = 0; // Called to send the door instantly to its spawn positions. virtual void DoorTeleportToSpawnPosition() = 0; // } private: // Main entry points for the door base behaviors. // Do not make the functions in this block virtual!! // { bool DoorActivate(); void DoorOpen(CBaseEntity * pOpenAwayFrom); void OpenIfUnlocked(CBaseEntity * pActivator, CBaseEntity * pOpenAwayFrom); void DoorOpenMoveDone(); void DoorCloseMoveDone(); void DoorAutoCloseThink(); void Lock(); void Unlock(); void Use(CBaseEntity * pActivator, CBaseEntity * pCaller, USE_TYPE useType, float value); void OnUse(CBaseEntity * pActivator, CBaseEntity * pCaller, USE_TYPE useType, float value); inline bool WillAutoReturn() { return m_flAutoReturnDelay != -1; } void StartBlocked(CBaseEntity * pOther); void OnStartBlocked(CBaseEntity * pOther); void MasterStartBlocked(CBaseEntity * pOther); void Blocked(CBaseEntity * pOther); void EndBlocked(void); void OnEndBlocked(void); void UpdateAreaPortals(bool bOpen); // Input handlers void InputClose(inputdata_t & inputdata); void InputLock(inputdata_t & inputdata); void InputOpen(inputdata_t & inputdata); void InputOpenAwayFrom(inputdata_t & inputdata); void InputToggle(inputdata_t & inputdata); void InputUnlock(inputdata_t & inputdata); void SetDoorBlocker(CBaseEntity * pBlocker); void SetMaster(CBasePropDoor * pMaster) { m_hMaster = pMaster; } void CalcDoorSounds(); // } int m_nHardwareType; DoorState_t m_eDoorState; // Holds whether the door is open, closed, // opening, or closing. locksound_t m_ls; // The sounds the door plays when being locked, unlocked, etc. EHANDLE m_hActivator; bool m_bLocked; // True if the door is locked. EHANDLE m_hBlocker; // Entity blocking the door currently bool m_bFirstBlocked; // Marker for being the first door (in a group) to be // blocked (needed for motion control) bool m_bForceClosed; // True if this door must close no matter what. string_t m_SoundMoving; string_t m_SoundOpen; string_t m_SoundClose; // dvs: FIXME: can we remove m_flSpeed from CBaseEntity? // float m_flSpeed; // Rotation speed when opening or closing in degrees // per second. DECLARE_DATADESC(); string_t m_SlaveName; CHandle m_hMaster; static void RegisterPrivateActivities(); // Outputs COutputEvent m_OnBlockedClosing; // Triggered when the door becomes blocked // while closing. COutputEvent m_OnBlockedOpening; // Triggered when the door becomes blocked // while opening. COutputEvent m_OnUnblockedClosing; // Triggered when the door becomes // unblocked while closing. COutputEvent m_OnUnblockedOpening; // Triggered when the door becomes // unblocked while opening. COutputEvent m_OnFullyClosed; // Triggered when the door reaches the fully // closed position. COutputEvent m_OnFullyOpen; // Triggered when the door reaches the fully // open position. COutputEvent m_OnClose; // Triggered when the door is told to close. COutputEvent m_OnOpen; // Triggered when the door is told to open. COutputEvent m_OnLockedUse; // Triggered when the user tries to open a locked door. }; void CBasePropDoor::SetDoorState(DoorState_t eDoorState) { m_eDoorState = eDoorState; } bool CBasePropDoor::IsDoorOpen() { return m_eDoorState == DOOR_STATE_OPEN; } bool CBasePropDoor::IsDoorAjar() { return (m_eDoorState == DOOR_STATE_AJAR); } bool CBasePropDoor::IsDoorOpening() { return m_eDoorState == DOOR_STATE_OPENING; } bool CBasePropDoor::IsDoorClosed() { return m_eDoorState == DOOR_STATE_CLOSED; } bool CBasePropDoor::IsDoorClosing() { return m_eDoorState == DOOR_STATE_CLOSING; } bool CBasePropDoor::IsDoorLocked() { return m_bLocked; } CBaseEntity *CBasePropDoor::GetActivator() { return m_hActivator; } bool CBasePropDoor::IsDoorBlocked() const { return (m_hBlocker != NULL); } bool CBasePropDoor::IsNPCOpening(CAI_BaseNPC *pNPC) { return (pNPC == (CAI_BaseNPC *)GetActivator()); } inline bool CBasePropDoor::IsPlayerOpening() { return (GetActivator() && GetActivator()->IsPlayer()); } inline bool CBasePropDoor::IsOpener(CBaseEntity *pEnt) { return (GetActivator() == pEnt); } #endif // BASEPROPDOOR_H