958 lines
22 KiB
C++
958 lines
22 KiB
C++
/***
|
|
*
|
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
|
*
|
|
* This product contains software technology licensed from Id
|
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
|
* All Rights Reserved.
|
|
*
|
|
* Use, distribution, and modification of this source code and/or resulting
|
|
* object code is restricted to non-commercial enhancements to products from
|
|
* Valve LLC. All other use, distribution, or modification is prohibited
|
|
* without written permission from Valve LLC.
|
|
*
|
|
****/
|
|
|
|
#include "stdafx.h"
|
|
#include "cbase.h"
|
|
#include "doors.h"
|
|
|
|
extern void SetMovedir(entvars_t *ev);
|
|
|
|
#define noiseMoving noise1
|
|
#define noiseArrived noise2
|
|
|
|
class CBaseDoor : public CBaseToggle
|
|
{
|
|
public:
|
|
void Spawn(void);
|
|
void Restart(void);
|
|
void Precache(void);
|
|
void KeyValue(KeyValueData *pkvd);
|
|
void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
|
|
void Blocked(CBaseEntity *pOther);
|
|
|
|
int ObjectCaps(void)
|
|
{
|
|
if (pev->spawnflags & SF_ITEM_USE_ONLY)
|
|
return (CBaseToggle::ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_IMPULSE_USE;
|
|
else
|
|
return (CBaseToggle::ObjectCaps() & ~FCAP_ACROSS_TRANSITION);
|
|
};
|
|
|
|
int Save(CSave &save);
|
|
int Restore(CRestore &restore);
|
|
void SetToggleState(int state);
|
|
|
|
public:
|
|
static TYPEDESCRIPTION m_SaveData[];
|
|
|
|
public:
|
|
void EXPORT DoorTouch(CBaseEntity *pOther);
|
|
int DoorActivate(void);
|
|
void EXPORT DoorGoUp(void);
|
|
void EXPORT DoorGoDown(void);
|
|
void EXPORT DoorHitTop(void);
|
|
void EXPORT DoorHitBottom(void);
|
|
|
|
public:
|
|
BYTE m_bHealthValue;
|
|
BYTE m_bMoveSnd;
|
|
BYTE m_bStopSnd;
|
|
locksound_t m_ls;
|
|
BYTE m_bLockedSound;
|
|
BYTE m_bLockedSentence;
|
|
BYTE m_bUnlockedSound;
|
|
BYTE m_bUnlockedSentence;
|
|
float m_lastBlockedTimestamp;
|
|
};
|
|
|
|
TYPEDESCRIPTION CBaseDoor::m_SaveData[] =
|
|
{
|
|
DEFINE_FIELD(CBaseDoor, m_bHealthValue, FIELD_CHARACTER),
|
|
DEFINE_FIELD(CBaseDoor, m_bMoveSnd, FIELD_CHARACTER),
|
|
DEFINE_FIELD(CBaseDoor, m_bStopSnd, FIELD_CHARACTER),
|
|
DEFINE_FIELD(CBaseDoor, m_bLockedSound, FIELD_CHARACTER),
|
|
DEFINE_FIELD(CBaseDoor, m_bLockedSentence, FIELD_CHARACTER),
|
|
DEFINE_FIELD(CBaseDoor, m_bUnlockedSound, FIELD_CHARACTER),
|
|
DEFINE_FIELD(CBaseDoor, m_bUnlockedSentence, FIELD_CHARACTER),
|
|
};
|
|
|
|
IMPLEMENT_SAVERESTORE(CBaseDoor, CBaseToggle);
|
|
|
|
#define DOOR_SENTENCEWAIT 6
|
|
#define DOOR_SOUNDWAIT 3
|
|
#define BUTTON_SOUNDWAIT 0.5
|
|
|
|
void PlayLockSounds(entvars_t *pev, locksound_t *pls, int flocked, int fbutton)
|
|
{
|
|
float flsoundwait = fbutton ? BUTTON_SOUNDWAIT : DOOR_SOUNDWAIT;
|
|
|
|
if (flocked)
|
|
{
|
|
int fplaysound = (pls->sLockedSound && gpGlobals->time > pls->flwaitSound);
|
|
int fplaysentence = (pls->sLockedSentence && !pls->bEOFLocked && gpGlobals->time > pls->flwaitSentence);
|
|
float fvol = (fplaysound && fplaysentence) ? 0.25 : 1;
|
|
|
|
if (fplaysound)
|
|
{
|
|
EMIT_SOUND(ENT(pev), CHAN_ITEM, (char *)STRING(pls->sLockedSound), fvol, ATTN_NORM);
|
|
pls->flwaitSound = gpGlobals->time + flsoundwait;
|
|
}
|
|
|
|
if (fplaysentence)
|
|
{
|
|
int iprev = pls->iLockedSentence;
|
|
pls->iLockedSentence = SENTENCEG_PlaySequentialSz(ENT(pev), STRING(pls->sLockedSentence), 0.85, ATTN_NORM, 0, 100, pls->iLockedSentence, FALSE);
|
|
pls->iUnlockedSentence = 0;
|
|
pls->bEOFLocked = (iprev == pls->iLockedSentence);
|
|
pls->flwaitSentence = gpGlobals->time + DOOR_SENTENCEWAIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int fplaysound = (pls->sUnlockedSound && gpGlobals->time > pls->flwaitSound);
|
|
int fplaysentence = (pls->sUnlockedSentence && !pls->bEOFUnlocked && gpGlobals->time > pls->flwaitSentence);
|
|
float fvol = (fplaysound && fplaysentence) ? 0.25 : 1;
|
|
|
|
if (fplaysound)
|
|
{
|
|
EMIT_SOUND(ENT(pev), CHAN_ITEM, (char *)STRING(pls->sUnlockedSound), fvol, ATTN_NORM);
|
|
pls->flwaitSound = gpGlobals->time + flsoundwait;
|
|
}
|
|
|
|
if (fplaysentence)
|
|
{
|
|
int iprev = pls->iUnlockedSentence;
|
|
pls->iUnlockedSentence = SENTENCEG_PlaySequentialSz(ENT(pev), STRING(pls->sUnlockedSentence), 0.85, ATTN_NORM, 0, 100, pls->iUnlockedSentence, FALSE);
|
|
pls->iLockedSentence = 0;
|
|
pls->bEOFUnlocked = (iprev == pls->iUnlockedSentence);
|
|
pls->flwaitSentence = gpGlobals->time + DOOR_SENTENCEWAIT;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CBaseDoor::KeyValue(KeyValueData *pkvd)
|
|
{
|
|
if (FStrEq(pkvd->szKeyName, "skin"))
|
|
{
|
|
pev->skin = atoi(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "movesnd"))
|
|
{
|
|
m_bMoveSnd = atoi(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "stopsnd"))
|
|
{
|
|
m_bStopSnd = atoi(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "healthvalue"))
|
|
{
|
|
m_bHealthValue = atoi(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "locked_sound"))
|
|
{
|
|
m_bLockedSound = atoi(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "locked_sentence"))
|
|
{
|
|
m_bLockedSentence = atoi(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "unlocked_sound"))
|
|
{
|
|
m_bUnlockedSound = atoi(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "unlocked_sentence"))
|
|
{
|
|
m_bUnlockedSentence = atoi(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "WaveHeight"))
|
|
{
|
|
pev->scale = atof(pkvd->szValue) * (1.0 / 8);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
CBaseToggle::KeyValue(pkvd);
|
|
}
|
|
|
|
LINK_ENTITY_TO_CLASS(func_door, CBaseDoor);
|
|
LINK_ENTITY_TO_CLASS(func_water, CBaseDoor);
|
|
|
|
void CBaseDoor::Spawn(void)
|
|
{
|
|
Precache();
|
|
SetMovedir(pev);
|
|
|
|
if (pev->skin == 0)
|
|
{
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_PASSABLE))
|
|
pev->solid = SOLID_NOT;
|
|
else
|
|
pev->solid = SOLID_BSP;
|
|
}
|
|
else
|
|
{
|
|
pev->solid = SOLID_NOT;
|
|
SetBits(pev->spawnflags, SF_DOOR_SILENT);
|
|
}
|
|
|
|
pev->movetype = MOVETYPE_PUSH;
|
|
UTIL_SetOrigin(pev, pev->origin);
|
|
SET_MODEL(ENT(pev), STRING(pev->model));
|
|
|
|
if (pev->speed == 0)
|
|
pev->speed = 100;
|
|
|
|
m_vecPosition1 = pev->origin;
|
|
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));
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_START_OPEN))
|
|
{
|
|
UTIL_SetOrigin(pev, m_vecPosition2);
|
|
m_vecPosition2 = m_vecPosition1;
|
|
m_vecPosition1 = pev->origin;
|
|
}
|
|
|
|
m_toggle_state = TS_AT_BOTTOM;
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_USE_ONLY))
|
|
SetTouch(NULL);
|
|
else
|
|
SetTouch(&CBaseDoor::DoorTouch);
|
|
|
|
m_lastBlockedTimestamp = 0;
|
|
}
|
|
|
|
void CBaseDoor::Restart(void)
|
|
{
|
|
SetMovedir(pev);
|
|
m_toggle_state = TS_AT_BOTTOM;
|
|
DoorGoDown();
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_USE_ONLY))
|
|
SetTouch(NULL);
|
|
else
|
|
SetTouch(&CBaseDoor::DoorTouch);
|
|
}
|
|
|
|
void CBaseDoor::SetToggleState(int state)
|
|
{
|
|
if (state == TS_AT_TOP)
|
|
UTIL_SetOrigin(pev, m_vecPosition2);
|
|
else
|
|
UTIL_SetOrigin(pev, m_vecPosition1);
|
|
}
|
|
|
|
void CBaseDoor::Precache(void)
|
|
{
|
|
switch (m_bMoveSnd)
|
|
{
|
|
case 0: pev->noiseMoving = ALLOC_STRING("common/null.wav"); break;
|
|
case 1:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove1.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove1.wav");
|
|
break;
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove2.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove2.wav");
|
|
break;
|
|
}
|
|
|
|
case 3:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove3.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove3.wav");
|
|
break;
|
|
}
|
|
|
|
case 4:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove4.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove4.wav");
|
|
break;
|
|
}
|
|
|
|
case 5:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove5.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove5.wav");
|
|
break;
|
|
}
|
|
|
|
case 6:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove6.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove6.wav");
|
|
break;
|
|
}
|
|
|
|
case 7:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove7.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove7.wav");
|
|
break;
|
|
}
|
|
|
|
case 8:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove8.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove8.wav");
|
|
break;
|
|
}
|
|
|
|
case 9:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove9.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove9.wav");
|
|
break;
|
|
}
|
|
|
|
case 10:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove10.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove10.wav");
|
|
break;
|
|
}
|
|
|
|
default: pev->noiseMoving = ALLOC_STRING("common/null.wav"); break;
|
|
}
|
|
|
|
switch (m_bStopSnd)
|
|
{
|
|
case 0: pev->noiseArrived = ALLOC_STRING("common/null.wav"); break;
|
|
case 1:
|
|
{
|
|
PRECACHE_SOUND("doors/doorstop1.wav");
|
|
pev->noiseArrived = ALLOC_STRING("doors/doorstop1.wav");
|
|
break;
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
PRECACHE_SOUND("doors/doorstop2.wav");
|
|
pev->noiseArrived = ALLOC_STRING("doors/doorstop2.wav");
|
|
break;
|
|
}
|
|
|
|
case 3:
|
|
{
|
|
PRECACHE_SOUND("doors/doorstop3.wav");
|
|
pev->noiseArrived = ALLOC_STRING("doors/doorstop3.wav");
|
|
break;
|
|
}
|
|
|
|
case 4:
|
|
{
|
|
PRECACHE_SOUND("doors/doorstop4.wav");
|
|
pev->noiseArrived = ALLOC_STRING("doors/doorstop4.wav");
|
|
break;
|
|
}
|
|
|
|
case 5:
|
|
{
|
|
PRECACHE_SOUND("doors/doorstop5.wav");
|
|
pev->noiseArrived = ALLOC_STRING("doors/doorstop5.wav");
|
|
break;
|
|
}
|
|
|
|
case 6:
|
|
{
|
|
PRECACHE_SOUND("doors/doorstop6.wav");
|
|
pev->noiseArrived = ALLOC_STRING("doors/doorstop6.wav");
|
|
break;
|
|
}
|
|
|
|
case 7:
|
|
{
|
|
PRECACHE_SOUND("doors/doorstop7.wav");
|
|
pev->noiseArrived = ALLOC_STRING("doors/doorstop7.wav");
|
|
break;
|
|
}
|
|
|
|
case 8:
|
|
{
|
|
PRECACHE_SOUND("doors/doorstop8.wav");
|
|
pev->noiseArrived = ALLOC_STRING("doors/doorstop8.wav");
|
|
break;
|
|
}
|
|
|
|
default: pev->noiseArrived = ALLOC_STRING("common/null.wav"); break;
|
|
}
|
|
|
|
if (m_bLockedSound)
|
|
{
|
|
char *pszSound = ButtonSound((int)m_bLockedSound);
|
|
PRECACHE_SOUND(pszSound);
|
|
m_ls.sLockedSound = ALLOC_STRING(pszSound);
|
|
}
|
|
|
|
if (m_bUnlockedSound)
|
|
{
|
|
char *pszSound = ButtonSound((int)m_bUnlockedSound);
|
|
PRECACHE_SOUND(pszSound);
|
|
m_ls.sUnlockedSound = ALLOC_STRING(pszSound);
|
|
}
|
|
|
|
switch (m_bLockedSentence)
|
|
{
|
|
case 1: m_ls.sLockedSentence = ALLOC_STRING("NA"); break;
|
|
case 2: m_ls.sLockedSentence = ALLOC_STRING("ND"); break;
|
|
case 3: m_ls.sLockedSentence = ALLOC_STRING("NF"); break;
|
|
case 4: m_ls.sLockedSentence = ALLOC_STRING("NFIRE"); break;
|
|
case 5: m_ls.sLockedSentence = ALLOC_STRING("NCHEM"); break;
|
|
case 6: m_ls.sLockedSentence = ALLOC_STRING("NRAD"); break;
|
|
case 7: m_ls.sLockedSentence = ALLOC_STRING("NCON"); break;
|
|
case 8: m_ls.sLockedSentence = ALLOC_STRING("NH"); break;
|
|
case 9: m_ls.sLockedSentence = ALLOC_STRING("NG"); break;
|
|
default: m_ls.sLockedSentence = 0; break;
|
|
}
|
|
|
|
switch (m_bUnlockedSentence)
|
|
{
|
|
case 1: m_ls.sUnlockedSentence = ALLOC_STRING("EA"); break;
|
|
case 2: m_ls.sUnlockedSentence = ALLOC_STRING("ED"); break;
|
|
case 3: m_ls.sUnlockedSentence = ALLOC_STRING("EF"); break;
|
|
case 4: m_ls.sUnlockedSentence = ALLOC_STRING("EFIRE"); break;
|
|
case 5: m_ls.sUnlockedSentence = ALLOC_STRING("ECHEM"); break;
|
|
case 6: m_ls.sUnlockedSentence = ALLOC_STRING("ERAD"); break;
|
|
case 7: m_ls.sUnlockedSentence = ALLOC_STRING("ECON"); break;
|
|
case 8: m_ls.sUnlockedSentence = ALLOC_STRING("EH"); break;
|
|
default: m_ls.sUnlockedSentence = 0; break;
|
|
}
|
|
}
|
|
|
|
void CBaseDoor::DoorTouch(CBaseEntity *pOther)
|
|
{
|
|
entvars_t *pevToucher = pOther->pev;
|
|
|
|
if (pevToucher->deadflag != DEAD_NO)
|
|
return;
|
|
|
|
if (m_sMaster && !UTIL_IsMasterTriggered(m_sMaster, pOther))
|
|
PlayLockSounds(pev, &m_ls, TRUE, FALSE);
|
|
|
|
if (!FStringNull(pev->targetname))
|
|
{
|
|
PlayLockSounds(pev, &m_ls, TRUE, FALSE);
|
|
return;
|
|
}
|
|
|
|
m_hActivator = pOther;
|
|
|
|
if (DoorActivate())
|
|
SetTouch(NULL);
|
|
}
|
|
|
|
void CBaseDoor::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
|
|
{
|
|
m_hActivator = pActivator;
|
|
|
|
if (m_toggle_state == TS_AT_BOTTOM || FBitSet(pev->spawnflags, SF_DOOR_NO_AUTO_RETURN) && m_toggle_state == TS_AT_TOP)
|
|
DoorActivate();
|
|
}
|
|
|
|
int CBaseDoor::DoorActivate(void)
|
|
{
|
|
if (!UTIL_IsMasterTriggered(m_sMaster, m_hActivator))
|
|
return 0;
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_NO_AUTO_RETURN) && m_toggle_state == TS_AT_TOP)
|
|
{
|
|
DoorGoDown();
|
|
return 1;
|
|
}
|
|
|
|
if (m_hActivator != 0 && m_hActivator->IsPlayer())
|
|
m_hActivator->TakeHealth(m_bHealthValue, DMG_GENERIC);
|
|
|
|
PlayLockSounds(pev, &m_ls, FALSE, FALSE);
|
|
DoorGoUp();
|
|
return 1;
|
|
}
|
|
|
|
extern Vector VecBModelOrigin(entvars_t *pevBModel);
|
|
|
|
void CBaseDoor::DoorGoUp(void)
|
|
{
|
|
entvars_t *pevActivator;
|
|
bool isReversing = m_toggle_state == TS_GOING_DOWN;
|
|
|
|
ASSERT(m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_GOING_DOWN);
|
|
|
|
if (m_toggle_state != TS_GOING_DOWN)
|
|
{
|
|
if (!FBitSet(pev->spawnflags, SF_DOOR_SILENT))
|
|
EMIT_SOUND(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseMoving), 1, ATTN_NORM);
|
|
}
|
|
|
|
m_toggle_state = TS_GOING_UP;
|
|
SetMoveDone(&CBaseDoor::DoorHitTop);
|
|
|
|
if (FClassnameIs(pev, "func_door_rotating"))
|
|
{
|
|
float sign = 1;
|
|
|
|
if (m_hActivator != 0)
|
|
{
|
|
pevActivator = m_hActivator->pev;
|
|
|
|
if (!FBitSet(pev->spawnflags, SF_DOOR_ONEWAY) && pev->movedir.y)
|
|
{
|
|
float loX = pev->mins.x + pev->origin.x;
|
|
float loY = pev->mins.y + pev->origin.y;
|
|
float hiX = pev->maxs.x + pev->origin.x;
|
|
float hiY = pev->maxs.y + pev->origin.y;
|
|
float momentArmX = pevActivator->origin.x - pev->origin.x;
|
|
float momentArmY = pevActivator->origin.y - pev->origin.y;
|
|
|
|
if (loX > pevActivator->origin.x)
|
|
{
|
|
if (pevActivator->origin.y < loY)
|
|
{
|
|
if (fabs(momentArmY) > fabs(momentArmX))
|
|
sign = (momentArmY < 0) ? 1 : -1;
|
|
else
|
|
sign = (momentArmX > 0) ? 1 : -1;
|
|
}
|
|
else if (pevActivator->origin.y > hiY)
|
|
{
|
|
if (fabs(momentArmY) > fabs(momentArmX))
|
|
sign = (momentArmY < 0) ? 1 : -1;
|
|
else
|
|
sign = (momentArmX < 0) ? 1 : -1;
|
|
}
|
|
else
|
|
sign = (momentArmY < 0) ? 1 : -1;
|
|
}
|
|
else
|
|
{
|
|
if (pevActivator->origin.x <= hiX)
|
|
{
|
|
if (pevActivator->origin.y > loY)
|
|
sign = (momentArmX > 0) ? 1 : -1;
|
|
else if (pevActivator->origin.y > hiY)
|
|
sign = (momentArmX < 0) ? 1 : -1;
|
|
}
|
|
else if (pevActivator->origin.y < loY)
|
|
{
|
|
if (fabs(momentArmY) > fabs(momentArmX))
|
|
sign = (momentArmY > 0) ? 1 : -1;
|
|
else
|
|
sign = (momentArmX > 0) ? 1 : -1;
|
|
}
|
|
else if (pevActivator->origin.y > hiY)
|
|
{
|
|
if (fabs(momentArmY) > fabs(momentArmX))
|
|
sign = (momentArmY > 0) ? 1 : -1;
|
|
else
|
|
sign = (momentArmX < 0) ? 1 : -1;
|
|
}
|
|
else
|
|
sign = (momentArmY > 0) ? 1 : -1;
|
|
}
|
|
|
|
if (isReversing)
|
|
sign = -sign;
|
|
}
|
|
}
|
|
|
|
AngularMove(m_vecAngle2 * sign, pev->speed);
|
|
}
|
|
else
|
|
LinearMove(m_vecPosition2, pev->speed);
|
|
}
|
|
|
|
void CBaseDoor::DoorHitTop(void)
|
|
{
|
|
if (!FBitSet(pev->spawnflags, SF_DOOR_SILENT))
|
|
{
|
|
STOP_SOUND(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseMoving));
|
|
EMIT_SOUND(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseArrived), 1, ATTN_NORM);
|
|
}
|
|
|
|
ASSERT(m_toggle_state == TS_GOING_UP);
|
|
m_toggle_state = TS_AT_TOP;
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_NO_AUTO_RETURN))
|
|
{
|
|
if (!FBitSet(pev->spawnflags, SF_DOOR_USE_ONLY))
|
|
SetTouch(&CBaseDoor::DoorTouch);
|
|
}
|
|
else
|
|
{
|
|
pev->nextthink = pev->ltime + m_flWait;
|
|
SetThink(&CBaseDoor::DoorGoDown);
|
|
|
|
if (m_flWait == -1)
|
|
pev->nextthink = -1;
|
|
}
|
|
|
|
if (pev->netname && (pev->spawnflags & SF_DOOR_START_OPEN))
|
|
FireTargets(STRING(pev->netname), m_hActivator, this, USE_TOGGLE, 0);
|
|
|
|
SUB_UseTargets(m_hActivator, USE_TOGGLE, 0);
|
|
}
|
|
|
|
void CBaseDoor::DoorGoDown(void)
|
|
{
|
|
if (m_toggle_state != TS_GOING_UP)
|
|
{
|
|
if (!FBitSet(pev->spawnflags, SF_DOOR_SILENT))
|
|
EMIT_SOUND(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseMoving), VOL_NORM, ATTN_NORM);
|
|
}
|
|
|
|
#ifdef DOOR_ASSERT
|
|
ASSERT(m_toggle_state == TS_AT_TOP);
|
|
#endif
|
|
m_toggle_state = TS_GOING_DOWN;
|
|
|
|
SetMoveDone(&CBaseDoor::DoorHitBottom);
|
|
|
|
if (FClassnameIs(pev, "func_door_rotating"))
|
|
AngularMove(m_vecAngle1, pev->speed);
|
|
else
|
|
LinearMove(m_vecPosition1, pev->speed);
|
|
}
|
|
|
|
void CBaseDoor::DoorHitBottom(void)
|
|
{
|
|
if (!FBitSet(pev->spawnflags, SF_DOOR_SILENT))
|
|
{
|
|
STOP_SOUND(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseMoving));
|
|
EMIT_SOUND(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseArrived), VOL_NORM, ATTN_NORM);
|
|
}
|
|
|
|
ASSERT(m_toggle_state == TS_GOING_DOWN);
|
|
m_toggle_state = TS_AT_BOTTOM;
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_USE_ONLY))
|
|
SetTouch(NULL);
|
|
else
|
|
SetTouch(&CBaseDoor::DoorTouch);
|
|
|
|
SUB_UseTargets(m_hActivator, USE_TOGGLE, 0);
|
|
|
|
if (pev->netname && !(pev->spawnflags & SF_DOOR_START_OPEN))
|
|
FireTargets(STRING(pev->netname), m_hActivator, this, USE_TOGGLE, 0);
|
|
}
|
|
|
|
void CBaseDoor::Blocked(CBaseEntity *pOther)
|
|
{
|
|
edict_t *pentTarget = NULL;
|
|
|
|
if (pev->dmg)
|
|
pOther->TakeDamage(pev, pev, pev->dmg, DMG_CRUSH);
|
|
|
|
if (gpGlobals->time - m_lastBlockedTimestamp >= 0.25)
|
|
{
|
|
m_lastBlockedTimestamp = gpGlobals->time;
|
|
|
|
if (m_flWait >= 0)
|
|
{
|
|
if (m_toggle_state == TS_GOING_DOWN)
|
|
DoorGoUp();
|
|
else
|
|
DoorGoDown();
|
|
}
|
|
|
|
if (!FStringNull(pev->targetname))
|
|
{
|
|
edict_t *pentTarget = NULL;
|
|
|
|
while (1)
|
|
{
|
|
pentTarget = FIND_ENTITY_BY_TARGETNAME(pentTarget, STRING(pev->targetname));
|
|
|
|
if (VARS(pentTarget) != pev)
|
|
{
|
|
if (FNullEnt(pentTarget))
|
|
break;
|
|
|
|
if (FClassnameIs(pentTarget, "func_door") || FClassnameIs(pentTarget, "func_door_rotating"))
|
|
{
|
|
CBaseDoor *pDoor = GetClassPtr((CBaseDoor *)VARS(pentTarget));
|
|
|
|
if (pDoor->m_flWait >= 0)
|
|
{
|
|
if (pDoor->pev->velocity == pev->velocity && pDoor->pev->avelocity == pev->velocity)
|
|
{
|
|
if (FClassnameIs(pentTarget, "func_door"))
|
|
{
|
|
pDoor->pev->origin = pev->origin;
|
|
pDoor->pev->velocity = g_vecZero;
|
|
}
|
|
else
|
|
{
|
|
pDoor->pev->angles = pev->angles;
|
|
pDoor->pev->avelocity = g_vecZero;
|
|
}
|
|
}
|
|
|
|
if (pDoor->m_toggle_state == TS_GOING_DOWN)
|
|
pDoor->DoorGoUp();
|
|
else
|
|
pDoor->DoorGoDown();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class CRotDoor : public CBaseDoor
|
|
{
|
|
public:
|
|
void Restart(void);
|
|
void Spawn(void);
|
|
void SetToggleState(int state);
|
|
};
|
|
|
|
LINK_ENTITY_TO_CLASS(func_door_rotating, CRotDoor);
|
|
|
|
void CRotDoor::Restart(void)
|
|
{
|
|
CBaseToggle::AxisDir(pev);
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_ROTATE_BACKWARDS))
|
|
pev->movedir = pev->movedir * -1;
|
|
|
|
if (pev->speed == 0)
|
|
pev->speed = 100;
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_START_OPEN))
|
|
{
|
|
pev->angles = m_vecAngle2;
|
|
Vector vecSav = m_vecAngle1;
|
|
m_vecAngle2 = m_vecAngle1;
|
|
m_vecAngle1 = vecSav;
|
|
pev->movedir = pev->movedir * -1;
|
|
}
|
|
|
|
m_toggle_state = TS_AT_BOTTOM;
|
|
DoorGoDown();
|
|
}
|
|
|
|
void CRotDoor::Spawn(void)
|
|
{
|
|
Precache();
|
|
CBaseToggle::AxisDir(pev);
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_ROTATE_BACKWARDS))
|
|
pev->movedir = pev->movedir * -1;
|
|
|
|
m_vecAngle1 = pev->angles;
|
|
m_vecAngle2 = pev->angles + pev->movedir * m_flMoveDistance;
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_PASSABLE))
|
|
pev->solid = SOLID_NOT;
|
|
else
|
|
pev->solid = SOLID_BSP;
|
|
|
|
pev->movetype = MOVETYPE_PUSH;
|
|
UTIL_SetOrigin(pev, pev->origin);
|
|
SET_MODEL(ENT(pev), STRING(pev->model));
|
|
|
|
if (pev->speed == 0)
|
|
pev->speed = 100;
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_START_OPEN))
|
|
{
|
|
pev->angles = m_vecAngle2;
|
|
Vector vecSav = m_vecAngle1;
|
|
m_vecAngle2 = m_vecAngle1;
|
|
m_vecAngle1 = vecSav;
|
|
pev->movedir = pev->movedir * -1;
|
|
}
|
|
|
|
m_toggle_state = TS_AT_BOTTOM;
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_USE_ONLY))
|
|
SetTouch(NULL);
|
|
else
|
|
SetTouch(&CBaseDoor::DoorTouch);
|
|
}
|
|
|
|
void CRotDoor::SetToggleState(int state)
|
|
{
|
|
if (state == TS_AT_TOP)
|
|
pev->angles = m_vecAngle2;
|
|
else
|
|
pev->angles = m_vecAngle1;
|
|
|
|
UTIL_SetOrigin(pev, pev->origin);
|
|
}
|
|
|
|
class CMomentaryDoor : public CBaseToggle
|
|
{
|
|
public:
|
|
void Spawn(void);
|
|
void Precache(void);
|
|
void KeyValue(KeyValueData *pkvd);
|
|
void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
|
|
int ObjectCaps(void) { return CBaseToggle::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
|
int Save(CSave &save);
|
|
int Restore(CRestore &restore);
|
|
|
|
public:
|
|
static TYPEDESCRIPTION m_SaveData[];
|
|
|
|
public:
|
|
BYTE m_bMoveSnd;
|
|
};
|
|
|
|
LINK_ENTITY_TO_CLASS(momentary_door, CMomentaryDoor);
|
|
|
|
TYPEDESCRIPTION CMomentaryDoor::m_SaveData[] =
|
|
{
|
|
DEFINE_FIELD(CMomentaryDoor, m_bMoveSnd, FIELD_CHARACTER),
|
|
};
|
|
|
|
IMPLEMENT_SAVERESTORE(CMomentaryDoor, CBaseToggle);
|
|
|
|
void CMomentaryDoor::Spawn(void)
|
|
{
|
|
SetMovedir(pev);
|
|
|
|
pev->solid = SOLID_BSP;
|
|
pev->movetype = MOVETYPE_PUSH;
|
|
|
|
UTIL_SetOrigin(pev, pev->origin);
|
|
SET_MODEL(ENT(pev), STRING(pev->model));
|
|
|
|
if (pev->speed == 0)
|
|
pev->speed = 100;
|
|
|
|
if (pev->dmg == 0)
|
|
pev->dmg = 2;
|
|
|
|
m_vecPosition1 = pev->origin;
|
|
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));
|
|
|
|
if (FBitSet(pev->spawnflags, SF_DOOR_START_OPEN))
|
|
{
|
|
UTIL_SetOrigin(pev, m_vecPosition2);
|
|
m_vecPosition2 = m_vecPosition1;
|
|
m_vecPosition1 = pev->origin;
|
|
}
|
|
|
|
SetTouch(NULL);
|
|
Precache();
|
|
}
|
|
|
|
void CMomentaryDoor::Precache(void)
|
|
{
|
|
switch (m_bMoveSnd)
|
|
{
|
|
case 0: pev->noiseMoving = ALLOC_STRING("common/null.wav"); break;
|
|
case 1:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove1.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove1.wav");
|
|
break;
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove2.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove2.wav");
|
|
break;
|
|
}
|
|
|
|
case 3:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove3.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove3.wav");
|
|
break;
|
|
}
|
|
|
|
case 4:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove4.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove4.wav");
|
|
break;
|
|
}
|
|
|
|
case 5:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove5.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove5.wav");
|
|
break;
|
|
}
|
|
|
|
case 6:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove6.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove6.wav");
|
|
break;
|
|
}
|
|
|
|
case 7:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove7.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove7.wav");
|
|
break;
|
|
}
|
|
|
|
case 8:
|
|
{
|
|
PRECACHE_SOUND("doors/doormove8.wav");
|
|
pev->noiseMoving = ALLOC_STRING("doors/doormove8.wav");
|
|
break;
|
|
}
|
|
|
|
default: pev->noiseMoving = ALLOC_STRING("common/null.wav"); break;
|
|
}
|
|
}
|
|
|
|
void CMomentaryDoor::KeyValue(KeyValueData *pkvd)
|
|
{
|
|
if (FStrEq(pkvd->szKeyName, "movesnd"))
|
|
{
|
|
m_bMoveSnd = atoi(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "stopsnd"))
|
|
{
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "healthvalue"))
|
|
{
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
CBaseToggle::KeyValue(pkvd);
|
|
}
|
|
|
|
void CMomentaryDoor::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
|
|
{
|
|
if (useType != USE_SET)
|
|
return;
|
|
|
|
if (value > 1)
|
|
value = 1;
|
|
|
|
Vector move = m_vecPosition1 + (value * (m_vecPosition2 - m_vecPosition1));
|
|
Vector delta = move - pev->origin;
|
|
float speed = delta.Length() * 10;
|
|
|
|
if (speed)
|
|
{
|
|
if (pev->nextthink < pev->ltime || !pev->nextthink)
|
|
EMIT_SOUND(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseMoving), VOL_NORM, ATTN_NORM);
|
|
|
|
LinearMove(move, speed);
|
|
}
|
|
} |