Skip to content

Commit

Permalink
add open/close triggers and obey mode to doors
Browse files Browse the repository at this point in the history
adds support for the following keys:
- Obey Trigger Mode
- Fire On Start
- Fire On Start Trigger State
- Fire On Stop
- Fire On Stop Trigger State
- Fire On Open Start
- Fire On Open Start Trigger State
- Fire On Close Start
- Fire On Close Start Trigger State
- Fire On Open End
- Fire On Open End Trigger State
- Fire On Close End
- Fire On Close End Trigger State

legacy "netname" and "fireonopen" keys are converted to one of the new keys, but the maps should be ripented instead later.
  • Loading branch information
wootguy committed Nov 20, 2024
1 parent 3adba50 commit f0f8413
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 16 deletions.
159 changes: 144 additions & 15 deletions dlls/func/CBaseDoor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,79 @@ void CBaseDoor::KeyValue(KeyValueData* pkvd)
pev->scale = atof(pkvd->szValue) * (1.0 / 8.0);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fireonstart"))
{
m_fireOnStart = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fireonstart_triggerstate"))
{
m_fireOnStartMode = (USE_TYPE)atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fireonstop"))
{
m_fireOnStop = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fireonstop_triggerstate"))
{
m_fireOnStopMode = (USE_TYPE)atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fireonopening"))
{
m_fireOnOpenStart = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fireonopening_triggerstate"))
{
m_fireOnOpenStartMode = (USE_TYPE)atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fireonclosing"))
{
m_fireOnCloseStart = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fireonclosing_triggerstate"))
{
m_fireOnCloseStartMode = (USE_TYPE)atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}

else if (FStrEq(pkvd->szKeyName, "fireonopened"))
{
m_fireOnOpenEnd = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fireonopen"))
{
// TODO: ripent. This is a legacy key
m_fireOnOpenEnd = ALLOC_STRING(pkvd->szValue);
m_fireOnOpenEndMode = USE_TOGGLE;
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fireonopened_triggerstate"))
{
m_fireOnOpenEndMode = (USE_TYPE)atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fireonclosed"))
{
m_fireOnCloseEnd = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fireonclosed_triggerstate"))
{
m_fireOnCloseEndMode = (USE_TYPE)atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "m_iObeyTriggerMode"))
{
m_iObeyTriggerMode = (ObeyTriggerMode)atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CBaseToggle::KeyValue(pkvd);
}
Expand Down Expand Up @@ -232,11 +305,31 @@ void CBaseDoor::Spawn()
// Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big
m_vecPosition2 = m_vecPosition1 + (pev->movedir * (fabs(pev->movedir.x * (pev->size.x - 2)) + fabs(pev->movedir.y * (pev->size.y - 2)) + fabs(pev->movedir.z * (pev->size.z - 2)) - m_flLip));
ASSERTSZ(m_vecPosition1 != m_vecPosition2, "door start/end positions are equal\n");

// TODO: ripent this stuff
if (pev->netname && !m_fireOnCloseEnd) {
// legacy fire on opened/closed keys
m_fireOnCloseEnd = pev->netname;
m_fireOnCloseEndMode = USE_TOGGLE;
pev->netname = 0;
}
if (m_fireOnOpenStartMode == 2) m_fireOnCloseEndMode = USE_TOGGLE;
if (m_fireOnOpenEndMode == 2) m_fireOnCloseEndMode = USE_TOGGLE;
if (m_fireOnCloseStartMode == 2) m_fireOnCloseEndMode = USE_TOGGLE;
if (m_fireOnCloseEndMode == 2) m_fireOnCloseEndMode = USE_TOGGLE;
if (m_fireOnStartMode == 2) m_fireOnCloseEndMode = USE_TOGGLE;
if (m_fireOnStopMode == 2) m_fireOnCloseEndMode = USE_TOGGLE;

if (FBitSet(pev->spawnflags, SF_DOOR_START_OPEN))
{ // swap pos1 and pos2, put door at pos2
UTIL_SetOrigin(pev, m_vecPosition2);
m_vecPosition2 = m_vecPosition1;
m_vecPosition1 = pev->origin;

SWAP(m_fireOnCloseStart, m_fireOnOpenStart, string_t);
SWAP(m_fireOnCloseEnd, m_fireOnOpenEnd, string_t);
SWAP(m_fireOnCloseStartMode, m_fireOnOpenStartMode, USE_TYPE);
SWAP(m_fireOnCloseEndMode, m_fireOnOpenEndMode, USE_TYPE);
}

m_toggle_state = TS_AT_BOTTOM;
Expand Down Expand Up @@ -435,7 +528,7 @@ void CBaseDoor::DoorTouch(CBaseEntity* pOther)

m_hActivator = pOther;// remember who activated the door

if (DoorActivate())
if (DoorActivate(USE_TOGGLE))
SetTouch(NULL); // Temporarily disable the touch function, until movement is finished.
}

Expand All @@ -447,20 +540,47 @@ void CBaseDoor::Use(CBaseEntity* pActivator, CBaseEntity* pCaller, USE_TYPE useT
{
m_hActivator = pActivator;

// if not ready to be used, ignore "use" command.
if (m_toggle_state == TS_AT_BOTTOM || (FBitSet(pev->spawnflags, SF_DOOR_NO_AUTO_RETURN) && m_toggle_state == TS_AT_TOP))
DoorActivate();
bool isStopped = m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_AT_TOP;
bool doorOpening = m_toggle_state == TS_GOING_UP || m_toggle_state == TS_AT_TOP;
bool doorClosing = m_toggle_state == TS_GOING_DOWN || m_toggle_state == TS_AT_BOTTOM;

if (m_iObeyTriggerMode == DOOR_OBEY_NO) {
// if not ready to be used, ignore "use" command.
if (m_toggle_state == TS_AT_BOTTOM || (FBitSet(pev->spawnflags, SF_DOOR_NO_AUTO_RETURN) && m_toggle_state == TS_AT_TOP))
DoorActivate(USE_TOGGLE);
}
else if (m_iObeyTriggerMode == DOOR_OBEY_YES || m_iObeyTriggerMode == DOOR_OBEY_YES_MOVING) {
if (doorClosing && useType == USE_OFF) {
return;
}
if (doorOpening && useType == USE_ON) {
return;
}

if (isStopped || m_iObeyTriggerMode == DOOR_OBEY_YES_MOVING)
DoorActivate(useType);
}
}

//
// Causes the door to "do its thing", i.e. start moving, and cascade activation.
//
int CBaseDoor::DoorActivate()
int CBaseDoor::DoorActivate(USE_TYPE useType)
{
if (!UTIL_IsMasterTriggered(m_sMaster, m_hActivator))
return 0;

if (FBitSet(pev->spawnflags, SF_DOOR_NO_AUTO_RETURN) && m_toggle_state == TS_AT_TOP)
bool doorOpening = m_toggle_state == TS_GOING_UP || m_toggle_state == TS_AT_TOP;
bool shouldClose = (doorOpening && useType == USE_TOGGLE) || useType == USE_OFF;

// TODO: this makes sense to do, logically, but sven doesn't do this
/*
if (FBitSet(pev->spawnflags, SF_DOOR_START_OPEN) && useType != USE_TOGGLE) {
shouldClose = !shouldClose;
}
*/

if (FBitSet(pev->spawnflags, SF_DOOR_NO_AUTO_RETURN) && shouldClose)
{// door should close
DoorGoDown();
}
Expand Down Expand Up @@ -493,9 +613,6 @@ void CBaseDoor::DoorGoUp(void)
{
entvars_t* pevActivator;

// It could be going-down, if blocked.
ASSERT(m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_GOING_DOWN);

// emit door moving and stop sounds on CHAN_STATIC so that the multicast doesn't
// filter them out and leave a client stuck with looping door sounds!
if (!FBitSet(pev->spawnflags, SF_DOOR_SILENT))
Expand Down Expand Up @@ -533,6 +650,11 @@ void CBaseDoor::DoorGoUp(void)
}
else
LinearMove(m_vecPosition2, pev->speed);

if (m_fireOnOpenStart)
FireTargets(STRING(m_fireOnOpenStart), m_hActivator, this, m_fireOnOpenStartMode, 0);
if (m_fireOnStart)
FireTargets(STRING(m_fireOnStart), m_hActivator, this, m_fireOnStartMode, 0);
}


Expand Down Expand Up @@ -569,9 +691,10 @@ void CBaseDoor::DoorHitTop(void)
}
}

// Fire the close target (if startopen is set, then "top" is closed) - netname is the close target
if (pev->netname && (pev->spawnflags & SF_DOOR_START_OPEN))
FireTargets(STRING(pev->netname), m_hActivator, this, USE_TOGGLE, 0);
if (m_fireOnOpenEnd)
FireTargets(STRING(m_fireOnOpenEnd), m_hActivator, this, m_fireOnOpenEndMode, 0);
if (m_fireOnStop)
FireTargets(STRING(m_fireOnStop), m_hActivator, this, m_fireOnStopMode, 0);

SUB_UseTargets(m_hActivator, USE_TOGGLE, 0); // this isn't finished
}
Expand All @@ -598,6 +721,11 @@ void CBaseDoor::DoorGoDown(void)
AngularMove(m_vecAngle1, pev->speed);
else
LinearMove(m_vecPosition1, pev->speed);

if (m_fireOnCloseStart)
FireTargets(STRING(m_fireOnCloseStart), m_hActivator, this, m_fireOnCloseStartMode, 0);
if (m_fireOnStart)
FireTargets(STRING(m_fireOnStart), m_hActivator, this, m_fireOnStartMode, 0);
}

//
Expand All @@ -624,9 +752,10 @@ void CBaseDoor::DoorHitBottom(void)

SUB_UseTargets(m_hActivator, USE_TOGGLE, 0); // this isn't finished

// Fire the close target (if startopen is set, then "top" is closed) - netname is the close target
if (pev->netname && !(pev->spawnflags & SF_DOOR_START_OPEN))
FireTargets(STRING(pev->netname), m_hActivator, this, USE_TOGGLE, 0);
if (m_fireOnCloseEnd)
FireTargets(STRING(m_fireOnCloseEnd), m_hActivator, this, m_fireOnCloseEndMode, 0);
if (m_fireOnStop)
FireTargets(STRING(m_fireOnStop), m_hActivator, this, m_fireOnStopMode, 0);
}

void CBaseDoor::Blocked(CBaseEntity* pOther)
Expand Down
26 changes: 25 additions & 1 deletion dlls/func/CBaseDoor.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ typedef struct locksounds // sounds that doors and buttons make when locked/un
BYTE bEOFUnlocked; // true if hit end of list of unlocked sentences
} locksound_t;

enum ObeyTriggerMode {
DOOR_OBEY_NO, // ignore trigger mode
DOOR_OBEY_YES, // obey trigger mode
DOOR_OBEY_YES_MOVING, // obey trigger mode even if moving
};

void PlayLockSounds(entvars_t* pev, locksound_t* pls, int flocked, int fbutton);

class CBaseDoor : public CBaseToggle
Expand Down Expand Up @@ -64,7 +70,7 @@ class CBaseDoor : public CBaseToggle
void EXPORT DoorTouch(CBaseEntity* pOther);

// local functions
int DoorActivate();
int DoorActivate(USE_TYPE useType);
void EXPORT DoorGoUp(void);
void EXPORT DoorGoDown(void);
virtual void EXPORT DoorHitTop(void);
Expand All @@ -81,4 +87,22 @@ class CBaseDoor : public CBaseToggle
BYTE m_bLockedSentence;
BYTE m_bUnlockedSound;
BYTE m_bUnlockedSentence;

// TODO: was 12 keyvalues really necessary for this? I think it can be done with 4.
// what about the multi_manager style with "#1", or using a multi_manager for things that
// always trigger at the same time as the door. Much ripenting needed.
string_t m_fireOnOpenStart;
string_t m_fireOnOpenEnd;
string_t m_fireOnCloseStart;
string_t m_fireOnCloseEnd;
string_t m_fireOnStart;
string_t m_fireOnStop;
USE_TYPE m_fireOnOpenStartMode;
USE_TYPE m_fireOnOpenEndMode;
USE_TYPE m_fireOnCloseStartMode;
USE_TYPE m_fireOnCloseEndMode;
USE_TYPE m_fireOnStartMode;
USE_TYPE m_fireOnStopMode;

ObeyTriggerMode m_iObeyTriggerMode;
};
7 changes: 7 additions & 0 deletions dlls/util/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ struct RGBA {
#define STRING(offset) ((const char *)(gpGlobals->pStringBase + (unsigned int)(offset)))
#define MAKE_STRING(str) ((uint64)(str) - (uint64)(STRING(0)))

// swap 2 values
#define SWAP(a, b, T) { \
T _temp = (a); \
(a) = (b); \
(b) = _temp; \
}

// same as the STRING macro but defined as a function for easy calling in the debugger
inline const char* cstr(string_t s) { return STRING(s); }

Expand Down

0 comments on commit f0f8413

Please sign in to comment.