hlsdk-xash3d/dlls/doors.cpp

1131 lines
29 KiB
C++
Raw Normal View History

2016-06-04 15:24:23 +02:00
/***
*
* 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.
*
****/
/*
===== doors.cpp ========================================================
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "doors.h"
2017-07-20 09:22:02 +02:00
#include "game.h"
2017-07-05 23:30:10 +02:00
#include "weapons.h"
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
extern void SetMovedir( entvars_t *ev );
2016-06-04 15:24:23 +02:00
#define noiseMoving noise1
#define noiseArrived noise2
class CBaseDoor : public CBaseToggle
{
public:
void Spawn( void );
void Precache( void );
virtual void KeyValue( KeyValueData *pkvd );
virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual void Blocked( CBaseEntity *pOther );
2016-07-31 15:48:50 +02:00
virtual int ObjectCaps( void )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if( pev->spawnflags & SF_ITEM_USE_ONLY )
return ( CBaseToggle::ObjectCaps() & ~FCAP_ACROSS_TRANSITION ) | FCAP_IMPULSE_USE;
2016-06-04 15:24:23 +02:00
else
return (CBaseToggle::ObjectCaps() & ~FCAP_ACROSS_TRANSITION);
};
2016-07-31 15:48:50 +02:00
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
2016-06-04 15:24:23 +02:00
virtual void SetToggleState( int state );
// used to selectivly override defaults
void EXPORT DoorTouch( CBaseEntity *pOther );
// local functions
2016-07-31 15:48:50 +02:00
int DoorActivate();
2016-06-04 15:24:23 +02:00
void EXPORT DoorGoUp( void );
void EXPORT DoorGoDown( void );
void EXPORT DoorHitTop( void );
void EXPORT DoorHitBottom( void );
2016-07-31 15:48:50 +02:00
BYTE m_bHealthValue;// some doors are medi-kit doors, they give players health
BYTE m_bMoveSnd; // sound a door makes while moving
BYTE m_bStopSnd; // sound a door makes when it stops
2016-06-04 15:24:23 +02:00
locksound_t m_ls; // door lock sounds
2016-07-31 15:48:50 +02:00
BYTE m_bLockedSound; // ordinals from entity selection
BYTE m_bLockedSentence;
BYTE m_bUnlockedSound;
BYTE m_bUnlockedSentence;
2016-06-04 15:24:23 +02:00
};
TYPEDESCRIPTION CBaseDoor::m_SaveData[] =
2016-06-04 15:24:23 +02:00
{
DEFINE_FIELD( CBaseDoor, m_bHealthValue, FIELD_CHARACTER ),
DEFINE_FIELD( CBaseDoor, m_bMoveSnd, FIELD_CHARACTER ),
DEFINE_FIELD( CBaseDoor, m_bStopSnd, FIELD_CHARACTER ),
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
DEFINE_FIELD( CBaseDoor, m_bLockedSound, FIELD_CHARACTER ),
DEFINE_FIELD( CBaseDoor, m_bLockedSentence, FIELD_CHARACTER ),
2016-07-31 15:48:50 +02:00
DEFINE_FIELD( CBaseDoor, m_bUnlockedSound, FIELD_CHARACTER ),
DEFINE_FIELD( CBaseDoor, m_bUnlockedSentence, FIELD_CHARACTER ),
2016-06-04 15:24:23 +02:00
};
IMPLEMENT_SAVERESTORE( CBaseDoor, CBaseToggle )
2016-06-04 15:24:23 +02:00
#define DOOR_SENTENCEWAIT 6
#define DOOR_SOUNDWAIT 3
#define BUTTON_SOUNDWAIT 0.5
// play door or button locked or unlocked sounds.
// pass in pointer to valid locksound struct.
// if flocked is true, play 'door is locked' sound,
// otherwise play 'door is unlocked' sound
// NOTE: this routine is shared by doors and buttons
2016-07-31 15:48:50 +02:00
void PlayLockSounds( entvars_t *pev, locksound_t *pls, int flocked, int fbutton )
2016-06-04 15:24:23 +02:00
{
// LOCKED SOUND
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
// CONSIDER: consolidate the locksound_t struct (all entries are duplicates for lock/unlock)
// CONSIDER: and condense this code.
float flsoundwait;
2016-07-31 15:48:50 +02:00
if( fbutton )
2016-06-04 15:24:23 +02:00
flsoundwait = BUTTON_SOUNDWAIT;
else
flsoundwait = DOOR_SOUNDWAIT;
2016-07-31 15:48:50 +02:00
if( flocked )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
int fplaysound = ( pls->sLockedSound && gpGlobals->time > pls->flwaitSound );
int fplaysentence = ( pls->sLockedSentence && !pls->bEOFLocked && gpGlobals->time > pls->flwaitSentence );
2016-06-04 15:24:23 +02:00
float fvol;
2016-07-31 15:48:50 +02:00
if( fplaysound && fplaysentence )
2016-06-04 15:24:23 +02:00
fvol = 0.25;
else
fvol = 1.0;
// if there is a locked sound, and we've debounced, play sound
2016-07-31 15:48:50 +02:00
if( fplaysound )
2016-06-04 15:24:23 +02:00
{
// play 'door locked' sound
2017-07-23 23:24:55 +02:00
EMIT_SOUND( ENT( pev ), CHAN_ITEM, STRING( pls->sLockedSound ), fvol, ATTN_NORM );
2016-06-04 15:24:23 +02:00
pls->flwaitSound = gpGlobals->time + flsoundwait;
}
// if there is a sentence, we've not played all in list, and we've debounced, play sound
2016-07-31 15:48:50 +02:00
if( fplaysentence )
2016-06-04 15:24:23 +02:00
{
// play next 'door locked' sentence in group
int iprev = pls->iLockedSentence;
2016-07-31 15:48:50 +02:00
pls->iLockedSentence = SENTENCEG_PlaySequentialSz( ENT( pev ), STRING( pls->sLockedSentence ),
0.85, ATTN_NORM, 0, 100, pls->iLockedSentence, FALSE );
2016-06-04 15:24:23 +02:00
pls->iUnlockedSentence = 0;
// make sure we don't keep calling last sentence in list
2016-07-31 15:48:50 +02:00
pls->bEOFLocked = ( iprev == pls->iLockedSentence );
2016-06-04 15:24:23 +02:00
pls->flwaitSentence = gpGlobals->time + DOOR_SENTENCEWAIT;
}
}
else
{
// UNLOCKED SOUND
2016-07-31 15:48:50 +02:00
int fplaysound = ( pls->sUnlockedSound && gpGlobals->time > pls->flwaitSound );
int fplaysentence = ( pls->sUnlockedSentence && !pls->bEOFUnlocked && gpGlobals->time > pls->flwaitSentence );
2016-06-04 15:24:23 +02:00
float fvol;
// if playing both sentence and sound, lower sound volume so we hear sentence
2016-07-31 15:48:50 +02:00
if( fplaysound && fplaysentence )
2016-06-04 15:24:23 +02:00
fvol = 0.25;
else
fvol = 1.0;
// play 'door unlocked' sound if set
2016-07-31 15:48:50 +02:00
if( fplaysound )
2016-06-04 15:24:23 +02:00
{
2017-07-23 23:24:55 +02:00
EMIT_SOUND( ENT( pev ), CHAN_ITEM, STRING( pls->sUnlockedSound ), fvol, ATTN_NORM );
2016-06-04 15:24:23 +02:00
pls->flwaitSound = gpGlobals->time + flsoundwait;
}
// play next 'door unlocked' sentence in group
2016-07-31 15:48:50 +02:00
if( fplaysentence )
2016-06-04 15:24:23 +02:00
{
int iprev = pls->iUnlockedSentence;
2016-07-31 15:48:50 +02:00
pls->iUnlockedSentence = SENTENCEG_PlaySequentialSz( ENT( pev ), STRING( pls->sUnlockedSentence ),
0.85, ATTN_NORM, 0, 100, pls->iUnlockedSentence, FALSE );
2016-06-04 15:24:23 +02:00
pls->iLockedSentence = 0;
// make sure we don't keep calling last sentence in list
2016-07-31 15:48:50 +02:00
pls->bEOFUnlocked = ( iprev == pls->iUnlockedSentence );
2016-06-04 15:24:23 +02:00
pls->flwaitSentence = gpGlobals->time + DOOR_SENTENCEWAIT;
}
}
}
//
// Cache user-entity-field values until spawn is called.
//
void CBaseDoor::KeyValue( KeyValueData *pkvd )
{
2016-07-31 15:48:50 +02:00
if( FStrEq( pkvd->szKeyName, "skin" ) )//skin is used for content type
2016-06-04 15:24:23 +02:00
{
2017-06-29 15:56:03 +02:00
pev->skin = atoi( pkvd->szValue );
2016-06-04 15:24:23 +02:00
pkvd->fHandled = TRUE;
}
2016-07-31 15:48:50 +02:00
else if( FStrEq( pkvd->szKeyName, "movesnd" ) )
2016-06-04 15:24:23 +02:00
{
2017-06-29 15:56:03 +02:00
m_bMoveSnd = atoi( pkvd->szValue );
2016-06-04 15:24:23 +02:00
pkvd->fHandled = TRUE;
}
2016-07-31 15:48:50 +02:00
else if( FStrEq( pkvd->szKeyName, "stopsnd" ) )
2016-06-04 15:24:23 +02:00
{
2017-06-29 15:56:03 +02:00
m_bStopSnd = atoi( pkvd->szValue );
2016-06-04 15:24:23 +02:00
pkvd->fHandled = TRUE;
}
2016-07-31 15:48:50 +02:00
else if( FStrEq( pkvd->szKeyName, "healthvalue" ) )
2016-06-04 15:24:23 +02:00
{
2017-06-29 15:56:03 +02:00
m_bHealthValue = atoi( pkvd->szValue );
2016-06-04 15:24:23 +02:00
pkvd->fHandled = TRUE;
}
2016-07-31 15:48:50 +02:00
else if( FStrEq( pkvd->szKeyName, "locked_sound" ) )
2016-06-04 15:24:23 +02:00
{
2017-06-29 15:56:03 +02:00
m_bLockedSound = atoi( pkvd->szValue );
2016-06-04 15:24:23 +02:00
pkvd->fHandled = TRUE;
}
2016-07-31 15:48:50 +02:00
else if( FStrEq( pkvd->szKeyName, "locked_sentence" ) )
2016-06-04 15:24:23 +02:00
{
2017-06-29 15:56:03 +02:00
m_bLockedSentence = atoi( pkvd->szValue );
2016-06-04 15:24:23 +02:00
pkvd->fHandled = TRUE;
}
2016-07-31 15:48:50 +02:00
else if( FStrEq( pkvd->szKeyName, "unlocked_sound" ) )
2016-06-04 15:24:23 +02:00
{
2017-06-29 15:56:03 +02:00
m_bUnlockedSound = atoi( pkvd->szValue );
2016-06-04 15:24:23 +02:00
pkvd->fHandled = TRUE;
}
2016-07-31 15:48:50 +02:00
else if( FStrEq( pkvd->szKeyName, "unlocked_sentence" ) )
2016-06-04 15:24:23 +02:00
{
2017-06-29 15:56:03 +02:00
m_bUnlockedSentence = atoi( pkvd->szValue );
2016-06-04 15:24:23 +02:00
pkvd->fHandled = TRUE;
}
2016-07-31 15:48:50 +02:00
else if( FStrEq( pkvd->szKeyName, "WaveHeight" ) )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
pev->scale = atof( pkvd->szValue ) * ( 1.0 / 8.0 );
2016-06-04 15:24:23 +02:00
pkvd->fHandled = TRUE;
}
else
CBaseToggle::KeyValue( pkvd );
}
/*QUAKED func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK TOGGLE
if two doors touch, they are assumed to be connected and operate as a unit.
TOGGLE causes the door to wait in both the start and end states for a trigger event.
START_OPEN causes the door to move to its destination when spawned, and operate in reverse.
It is used to temporarily or permanently close off an area when triggered (not usefull for
touch or takedamage doors).
"angle" determines the opening direction
"targetname" if set, no touch field will be spawned and a remote button or trigger
field activates the door.
"health" if set, door must be shot open
"speed" movement speed (100 default)
"wait" wait before returning (3 default, -1 = never return)
"lip" lip remaining at end of move (8 default)
"dmg" damage to inflict when blocked (2 default)
"sounds"
0) no sound
1) stone
2) base
3) stone chain
4) screechy metal
*/
LINK_ENTITY_TO_CLASS( func_door, CBaseDoor )
2016-06-04 15:24:23 +02:00
//
// func_water - same as a door.
//
LINK_ENTITY_TO_CLASS( func_water, CBaseDoor )
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
void CBaseDoor::Spawn()
2016-06-04 15:24:23 +02:00
{
Precache();
2016-07-31 15:48:50 +02:00
SetMovedir( pev );
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if( pev->skin == 0 )
{
//normal door
2016-07-31 15:48:50 +02:00
if( FBitSet( pev->spawnflags, SF_DOOR_PASSABLE ) )
pev->solid = SOLID_NOT;
2016-06-04 15:24:23 +02:00
else
2016-07-31 15:48:50 +02:00
pev->solid = SOLID_BSP;
2016-06-04 15:24:23 +02:00
}
else
{
// special contents
2016-07-31 15:48:50 +02:00
pev->solid = SOLID_NOT;
2016-06-04 15:24:23 +02:00
SetBits( pev->spawnflags, SF_DOOR_SILENT ); // water is silent for now
}
2016-07-31 15:48:50 +02:00
pev->movetype = MOVETYPE_PUSH;
UTIL_SetOrigin( pev, pev->origin );
SET_MODEL( ENT( pev ), STRING( pev->model ) );
if( pev->speed == 0 )
2016-06-04 15:24:23 +02:00
pev->speed = 100;
2016-07-31 15:48:50 +02:00
m_vecPosition1 = pev->origin;
2016-06-04 15:24:23 +02:00
// Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big
2016-07-31 15:48:50 +02:00
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" );
if( FBitSet( pev->spawnflags, SF_DOOR_START_OPEN ) )
{
// swap pos1 and pos2, put door at pos2
2016-07-31 15:48:50 +02:00
UTIL_SetOrigin( pev, m_vecPosition2 );
2016-06-04 15:24:23 +02:00
m_vecPosition2 = m_vecPosition1;
m_vecPosition1 = pev->origin;
}
m_toggle_state = TS_AT_BOTTOM;
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
// if the door is flagged for USE button activation only, use NULL touch function
2016-07-31 15:48:50 +02:00
if( FBitSet( pev->spawnflags, SF_DOOR_USE_ONLY ) )
2016-06-04 15:24:23 +02:00
{
SetTouch( NULL );
}
else // touchable button
SetTouch( &CBaseDoor::DoorTouch );
}
2016-07-31 15:48:50 +02:00
void CBaseDoor::SetToggleState( int state )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if( state == TS_AT_TOP )
2016-06-04 15:24:23 +02:00
UTIL_SetOrigin( pev, m_vecPosition2 );
else
UTIL_SetOrigin( pev, m_vecPosition1 );
}
void CBaseDoor::Precache( void )
{
2017-06-29 15:56:03 +02:00
const char *pszSound;
BOOL NullSound = FALSE;
2016-06-04 15:24:23 +02:00
// set the door's "in-motion" sound
2016-07-31 15:48:50 +02:00
switch( m_bMoveSnd )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
case 1:
pszSound = "doors/doormove1.wav";
2016-07-31 15:48:50 +02:00
break;
case 2:
pszSound = "doors/doormove2.wav";
2016-07-31 15:48:50 +02:00
break;
case 3:
pszSound = "doors/doormove3.wav";
2016-07-31 15:48:50 +02:00
break;
case 4:
pszSound = "doors/doormove4.wav";
2016-07-31 15:48:50 +02:00
break;
case 5:
pszSound = "doors/doormove5.wav";
2016-07-31 15:48:50 +02:00
break;
case 6:
pszSound = "doors/doormove6.wav";
2016-07-31 15:48:50 +02:00
break;
case 7:
pszSound = "doors/doormove7.wav";
2016-07-31 15:48:50 +02:00
break;
case 8:
pszSound = "doors/doormove8.wav";
2016-07-31 15:48:50 +02:00
break;
case 9:
pszSound = "doors/doormove9.wav";
2016-07-31 15:48:50 +02:00
break;
case 10:
pszSound = "doors/doormove10.wav";
2016-07-31 15:48:50 +02:00
break;
case 0:
2016-07-31 15:48:50 +02:00
default:
pszSound = "common/null.wav";
NullSound = TRUE;
2016-07-31 15:48:50 +02:00
break;
2016-06-04 15:24:23 +02:00
}
if( !NullSound )
PRECACHE_SOUND( pszSound );
pev->noiseMoving = MAKE_STRING( pszSound );
NullSound = FALSE;
// set the door's 'reached destination' stop sound
2016-07-31 15:48:50 +02:00
switch( m_bStopSnd )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
case 1:
pszSound = "doors/doorstop1.wav";
2016-07-31 15:48:50 +02:00
break;
case 2:
pszSound = "doors/doorstop2.wav";
2016-07-31 15:48:50 +02:00
break;
case 3:
pszSound = "doors/doorstop3.wav";
2016-07-31 15:48:50 +02:00
break;
case 4:
pszSound = "doors/doorstop4.wav";
2016-07-31 15:48:50 +02:00
break;
case 5:
pszSound = "doors/doorstop5.wav";
2016-07-31 15:48:50 +02:00
break;
case 6:
2017-07-20 20:32:06 +02:00
pszSound = "doors/doorstop6.wav";
2016-07-31 15:48:50 +02:00
break;
case 7:
pszSound = "doors/doorstop7.wav";
2016-07-31 15:48:50 +02:00
break;
case 8:
pszSound = "doors/doorstop8.wav";
2016-07-31 15:48:50 +02:00
break;
case 0:
2016-07-31 15:48:50 +02:00
default:
pszSound = "common/null.wav";
NullSound = TRUE;
2016-07-31 15:48:50 +02:00
break;
2016-06-04 15:24:23 +02:00
}
if( !NullSound )
PRECACHE_SOUND( pszSound );
pev->noiseArrived = MAKE_STRING( pszSound );
2016-06-04 15:24:23 +02:00
// get door button sounds, for doors which are directly 'touched' to open
2016-07-31 15:48:50 +02:00
if( m_bLockedSound )
2016-06-04 15:24:23 +02:00
{
pszSound = ButtonSound( (int)m_bLockedSound );
2016-07-31 15:48:50 +02:00
PRECACHE_SOUND( pszSound );
m_ls.sLockedSound = MAKE_STRING( pszSound );
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
if( m_bUnlockedSound )
2016-06-04 15:24:23 +02:00
{
pszSound = ButtonSound( (int)m_bUnlockedSound );
2016-07-31 15:48:50 +02:00
PRECACHE_SOUND( pszSound );
m_ls.sUnlockedSound = MAKE_STRING( pszSound );
2016-06-04 15:24:23 +02:00
}
// get sentence group names, for doors which are directly 'touched' to open
2016-07-31 15:48:50 +02:00
switch( m_bLockedSentence )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
case 1:
// access denied
m_ls.sLockedSentence = MAKE_STRING( "NA" );
2016-07-31 15:48:50 +02:00
break;
case 2:
// security lockout
m_ls.sLockedSentence = MAKE_STRING( "ND" );
2016-07-31 15:48:50 +02:00
break;
case 3:
// blast door
m_ls.sLockedSentence = MAKE_STRING( "NF" );
2016-07-31 15:48:50 +02:00
break;
case 4:
// fire door
m_ls.sLockedSentence = MAKE_STRING( "NFIRE" );
2016-07-31 15:48:50 +02:00
break;
case 5:
// chemical door
m_ls.sLockedSentence = MAKE_STRING( "NCHEM" );
2016-07-31 15:48:50 +02:00
break;
case 6:
// radiation door
m_ls.sLockedSentence = MAKE_STRING( "NRAD" );
2016-07-31 15:48:50 +02:00
break;
case 7:
// gen containment
m_ls.sLockedSentence = MAKE_STRING( "NCON" );
2016-07-31 15:48:50 +02:00
break;
case 8:
// maintenance door
m_ls.sLockedSentence = MAKE_STRING( "NH" );
2016-07-31 15:48:50 +02:00
break;
case 9:
// broken door
m_ls.sLockedSentence = MAKE_STRING( "NG" );
2016-07-31 15:48:50 +02:00
break;
default:
m_ls.sLockedSentence = 0;
break;
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
switch( m_bUnlockedSentence )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
case 1:
// access granted
m_ls.sUnlockedSentence = MAKE_STRING( "EA" );
2016-07-31 15:48:50 +02:00
break;
case 2:
// security door
m_ls.sUnlockedSentence = MAKE_STRING( "ED" );
2016-07-31 15:48:50 +02:00
break;
case 3:
// blast door
m_ls.sUnlockedSentence = MAKE_STRING( "EF" );
2016-07-31 15:48:50 +02:00
break;
case 4:
// fire door
m_ls.sUnlockedSentence = MAKE_STRING( "EFIRE" );
2016-07-31 15:48:50 +02:00
break;
case 5:
// chemical door
m_ls.sUnlockedSentence = MAKE_STRING( "ECHEM" );
2016-07-31 15:48:50 +02:00
break;
case 6:
// radiation door
m_ls.sUnlockedSentence = MAKE_STRING( "ERAD" );
2016-07-31 15:48:50 +02:00
break;
case 7:
// gen containment
m_ls.sUnlockedSentence = MAKE_STRING( "ECON" );
2016-07-31 15:48:50 +02:00
break;
case 8:
// maintenance door
m_ls.sUnlockedSentence = MAKE_STRING( "EH" );
2016-07-31 15:48:50 +02:00
break;
default:
m_ls.sUnlockedSentence = 0;
break;
2016-06-04 15:24:23 +02:00
}
}
//
// Doors not tied to anything (e.g. button, another door) can be touched, to make them activate.
//
void CBaseDoor::DoorTouch( CBaseEntity *pOther )
{
// Ignore touches by anything but players
2019-09-24 00:00:37 +02:00
if( !pOther->IsPlayer() )
2016-06-04 15:24:23 +02:00
return;
// If door has master, and it's not ready to trigger,
// play 'locked' sound
2016-07-31 15:48:50 +02:00
if( m_sMaster && !UTIL_IsMasterTriggered( m_sMaster, pOther ) )
PlayLockSounds( pev, &m_ls, TRUE, FALSE );
2016-06-04 15:24:23 +02:00
// If door is somebody's target, then touching does nothing.
// You have to activate the owner (e.g. button).
2016-07-31 15:48:50 +02:00
if( !FStringNull( pev->targetname ) )
2016-06-04 15:24:23 +02:00
{
// play locked sound
2016-07-31 15:48:50 +02:00
PlayLockSounds( pev, &m_ls, TRUE, FALSE );
2016-06-04 15:24:23 +02:00
return;
}
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
m_hActivator = pOther;// remember who activated the door
2019-09-24 00:00:37 +02:00
if( DoorActivate() )
2016-06-04 15:24:23 +02:00
SetTouch( NULL ); // Temporarily disable the touch function, until movement is finished.
}
//
// Used by SUB_UseTargets, when a door is the target of a button.
//
void CBaseDoor::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
m_hActivator = pActivator;
// if not ready to be used, ignore "use" command.
2016-07-31 15:48:50 +02:00
if( m_toggle_state == TS_AT_BOTTOM || ( FBitSet( pev->spawnflags, SF_DOOR_NO_AUTO_RETURN ) && m_toggle_state == TS_AT_TOP ) )
2016-06-04 15:24:23 +02:00
DoorActivate();
}
//
// Causes the door to "do its thing", i.e. start moving, and cascade activation.
//
2016-07-31 15:48:50 +02:00
int CBaseDoor::DoorActivate()
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if( !UTIL_IsMasterTriggered( m_sMaster, m_hActivator ) )
2016-06-04 15:24:23 +02:00
return 0;
2016-07-31 15:48:50 +02:00
if( FBitSet( pev->spawnflags, SF_DOOR_NO_AUTO_RETURN ) && m_toggle_state == TS_AT_TOP )
{
// door should close
2016-06-04 15:24:23 +02:00
DoorGoDown();
}
else
{
// door should open
2017-06-29 15:56:03 +02:00
if( m_hActivator != 0 && m_hActivator->IsPlayer() )
{
// give health if player opened the door (medikit)
//VARS( m_eoActivator )->health += m_bHealthValue;
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
m_hActivator->TakeHealth( m_bHealthValue, DMG_GENERIC );
2016-06-04 15:24:23 +02:00
}
// play door unlock sounds
2016-07-31 15:48:50 +02:00
PlayLockSounds( pev, &m_ls, FALSE, FALSE );
2016-06-04 15:24:23 +02:00
DoorGoUp();
}
return 1;
}
extern Vector VecBModelOrigin( entvars_t* pevBModel );
//
// Starts the door going to its "up" position (simply ToggleData->vecPosition2).
//
void CBaseDoor::DoorGoUp( void )
{
2016-07-31 15:48:50 +02:00
entvars_t *pevActivator;
2016-06-04 15:24:23 +02:00
// It could be going-down, if blocked.
2016-07-31 15:48:50 +02:00
ASSERT( m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_GOING_DOWN );
2016-06-04 15:24:23 +02:00
// 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!
2016-07-31 15:48:50 +02:00
if( !FBitSet( pev->spawnflags, SF_DOOR_SILENT ) )
if( m_toggle_state != TS_GOING_UP && m_toggle_state != TS_GOING_DOWN )
2017-07-23 23:24:55 +02:00
EMIT_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noiseMoving ), 1, ATTN_NORM );
2016-06-04 15:24:23 +02:00
m_toggle_state = TS_GOING_UP;
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
SetMoveDone( &CBaseDoor::DoorHitTop );
2016-07-31 15:48:50 +02:00
if( FClassnameIs( pev, "func_door_rotating" ) ) // !!! BUGBUG Triggered doors don't work with this yet
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
float sign = 1.0;
2016-06-04 15:24:23 +02:00
2017-06-29 15:56:03 +02:00
if( m_hActivator != 0 )
2016-06-04 15:24:23 +02:00
{
pevActivator = m_hActivator->pev;
2016-07-31 15:48:50 +02:00
if( !FBitSet( pev->spawnflags, SF_DOOR_ONEWAY ) && pev->movedir.y ) // Y axis rotation, move away from the player
2016-06-04 15:24:23 +02:00
{
Vector vec = pevActivator->origin - pev->origin;
Vector angles = pevActivator->angles;
angles.x = 0;
angles.z = 0;
2016-07-31 15:48:50 +02:00
UTIL_MakeVectors( angles );
//Vector vnext = ( pevToucher->origin + ( pevToucher->velocity * 10 ) ) - pev->origin;
UTIL_MakeVectors( pevActivator->angles );
Vector vnext = ( pevActivator->origin + ( gpGlobals->v_forward * 10 ) ) - pev->origin;
if( ( vec.x * vnext.y - vec.y * vnext.x ) < 0 )
2016-06-04 15:24:23 +02:00
sign = -1.0;
}
}
2016-07-31 15:48:50 +02:00
AngularMove( m_vecAngle2*sign, pev->speed );
2016-06-04 15:24:23 +02:00
}
else
2016-07-31 15:48:50 +02:00
LinearMove( m_vecPosition2, pev->speed );
2016-06-04 15:24:23 +02:00
}
//
// The door has reached the "up" position. Either go back down, or wait for another activation.
//
void CBaseDoor::DoorHitTop( void )
{
2016-07-31 15:48:50 +02:00
if( !FBitSet( pev->spawnflags, SF_DOOR_SILENT ) )
2016-06-04 15:24:23 +02:00
{
2017-07-23 23:24:55 +02:00
STOP_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noiseMoving ) );
EMIT_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noiseArrived ), 1, ATTN_NORM );
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
ASSERT( m_toggle_state == TS_GOING_UP );
2016-06-04 15:24:23 +02:00
m_toggle_state = TS_AT_TOP;
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
// toggle-doors don't come down automatically, they wait for refire.
2016-07-31 15:48:50 +02:00
if( FBitSet( pev->spawnflags, SF_DOOR_NO_AUTO_RETURN ) )
2016-06-04 15:24:23 +02:00
{
// Re-instate touch method, movement is complete
2016-07-31 15:48:50 +02:00
if( !FBitSet( pev->spawnflags, SF_DOOR_USE_ONLY ) )
2016-06-04 15:24:23 +02:00
SetTouch( &CBaseDoor::DoorTouch );
}
else
{
// In flWait seconds, DoorGoDown will fire, unless wait is -1, then door stays open
pev->nextthink = pev->ltime + m_flWait;
SetThink( &CBaseDoor::DoorGoDown );
2016-07-31 15:48:50 +02:00
if( m_flWait == -1 )
2016-06-04 15:24:23 +02:00
{
pev->nextthink = -1;
}
}
// Fire the close target (if startopen is set, then "top" is closed) - netname is the close target
2016-07-31 15:48:50 +02:00
if( pev->netname && ( pev->spawnflags & SF_DOOR_START_OPEN ) )
FireTargets( STRING( pev->netname ), m_hActivator, this, USE_TOGGLE, 0 );
2016-06-04 15:24:23 +02:00
SUB_UseTargets( m_hActivator, USE_TOGGLE, 0 ); // this isn't finished
}
//
// Starts the door going to its "down" position (simply ToggleData->vecPosition1).
//
void CBaseDoor::DoorGoDown( void )
{
2016-07-31 15:48:50 +02:00
if( !FBitSet( pev->spawnflags, SF_DOOR_SILENT ) )
if( m_toggle_state != TS_GOING_UP && m_toggle_state != TS_GOING_DOWN )
2017-07-23 23:24:55 +02:00
EMIT_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noiseMoving ), 1, ATTN_NORM );
2016-06-04 15:24:23 +02:00
#ifdef DOOR_ASSERT
2016-07-31 15:48:50 +02:00
ASSERT( m_toggle_state == TS_AT_TOP );
2016-06-04 15:24:23 +02:00
#endif // DOOR_ASSERT
m_toggle_state = TS_GOING_DOWN;
SetMoveDone( &CBaseDoor::DoorHitBottom );
2016-07-31 15:48:50 +02:00
if( FClassnameIs( pev, "func_door_rotating" ) )//rotating door
AngularMove( m_vecAngle1, pev->speed );
2016-06-04 15:24:23 +02:00
else
2016-07-31 15:48:50 +02:00
LinearMove( m_vecPosition1, pev->speed );
2016-06-04 15:24:23 +02:00
}
//
// The door has reached the "down" position. Back to quiescence.
//
void CBaseDoor::DoorHitBottom( void )
{
2016-07-31 15:48:50 +02:00
if( !FBitSet( pev->spawnflags, SF_DOOR_SILENT ) )
2016-06-04 15:24:23 +02:00
{
2017-07-23 23:24:55 +02:00
STOP_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noiseMoving ) );
EMIT_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noiseArrived ), 1, ATTN_NORM );
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
ASSERT( m_toggle_state == TS_GOING_DOWN );
2016-06-04 15:24:23 +02:00
m_toggle_state = TS_AT_BOTTOM;
// Re-instate touch method, cycle is complete
2016-07-31 15:48:50 +02:00
if( FBitSet( pev->spawnflags, SF_DOOR_USE_ONLY ) )
{
// use only door
2016-06-04 15:24:23 +02:00
SetTouch( NULL );
}
else // touchable door
SetTouch( &CBaseDoor::DoorTouch );
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
2016-07-31 15:48:50 +02:00
if( pev->netname && !( pev->spawnflags & SF_DOOR_START_OPEN ) )
FireTargets( STRING( pev->netname ), m_hActivator, this, USE_TOGGLE, 0 );
2016-06-04 15:24:23 +02:00
}
void CBaseDoor::Blocked( CBaseEntity *pOther )
{
edict_t *pentTarget = NULL;
CBaseDoor *pDoor = NULL;
2016-06-04 15:24:23 +02:00
// Hurt the blocker a little.
2016-07-31 15:48:50 +02:00
if( pev->dmg )
2016-06-04 15:24:23 +02:00
pOther->TakeDamage( pev, pev, pev->dmg, DMG_CRUSH );
2017-07-20 09:22:02 +02:00
if( satchelfix.value )
{
// Detonate satchels
if( !strcmp( "monster_satchel", STRING( pOther->pev->classname ) ) )
( (CSatchel*)pOther )->Use( this, this, USE_ON, 0 );
}
2017-07-05 23:30:10 +02:00
2016-06-04 15:24:23 +02:00
// if a door has a negative wait, it would never come back if blocked,
// so let it just squash the object to death real fast
2016-07-31 15:48:50 +02:00
if( m_flWait >= 0 )
2016-06-04 15:24:23 +02:00
{
// BMod Start - Door sound fix.
if( !FBitSet( pev->spawnflags, SF_DOOR_SILENT ) )
2017-07-23 23:24:55 +02:00
STOP_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noiseMoving ) );
// BMod End
2016-07-31 15:48:50 +02:00
if( m_toggle_state == TS_GOING_DOWN )
2016-06-04 15:24:23 +02:00
{
DoorGoUp();
}
else
{
DoorGoDown();
}
}
// Block all door pieces with the same targetname here.
2016-07-31 15:48:50 +02:00
if( !FStringNull( pev->targetname ) )
2016-06-04 15:24:23 +02:00
{
2017-07-23 23:24:55 +02:00
for( ; ; )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
pentTarget = FIND_ENTITY_BY_TARGETNAME( pentTarget, STRING( pev->targetname ) );
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if( VARS( pentTarget ) != pev )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if( FNullEnt( pentTarget ) )
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
if( FClassnameIs( pentTarget, "func_door" ) || FClassnameIs( pentTarget, "func_door_rotating" ) )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
pDoor = GetClassPtr( (CBaseDoor *)VARS( pentTarget ) );
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if( pDoor->m_flWait >= 0 )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if( pDoor->pev->velocity == pev->velocity && pDoor->pev->avelocity == pev->velocity )
2016-06-04 15:24:23 +02:00
{
// this is the most hacked, evil, bastardized thing I've ever seen. kjb
2016-07-31 15:48:50 +02:00
if( FClassnameIs( pentTarget, "func_door" ) )
{
// set origin to realign normal doors
2016-06-04 15:24:23 +02:00
pDoor->pev->origin = pev->origin;
pDoor->pev->velocity = g_vecZero;// stop!
}
else
2016-07-31 15:48:50 +02:00
{
// set angles to realign rotating doors
2016-06-04 15:24:23 +02:00
pDoor->pev->angles = pev->angles;
pDoor->pev->avelocity = g_vecZero;
}
}
2016-07-31 15:48:50 +02:00
if( !FBitSet( pev->spawnflags, SF_DOOR_SILENT ) )
2017-07-23 23:24:55 +02:00
STOP_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noiseMoving ) );
2016-02-29 21:04:01 +01:00
2016-07-31 15:48:50 +02:00
if( pDoor->m_toggle_state == TS_GOING_DOWN )
2016-06-04 15:24:23 +02:00
pDoor->DoorGoUp();
else
pDoor->DoorGoDown();
}
}
}
}
}
}
/*QUAKED FuncRotDoorSpawn (0 .5 .8) ? START_OPEN REVERSE
DOOR_DONT_LINK TOGGLE X_AXIS Y_AXIS
if two doors touch, they are assumed to be connected and operate as
a unit.
TOGGLE causes the door to wait in both the start and end states for
a trigger event.
START_OPEN causes the door to move to its destination when spawned,
and operate in reverse. It is used to temporarily or permanently
close off an area when triggered (not usefull for touch or
takedamage doors).
You need to have an origin brush as part of this entity. The
center of that brush will be
the point around which it is rotated. It will rotate around the Z
axis by default. You can
check either the X_AXIS or Y_AXIS box to change that.
"distance" is how many degrees the door will be rotated.
"speed" determines how fast the door moves; default value is 100.
REVERSE will cause the door to rotate in the opposite direction.
"angle" determines the opening direction
"targetname" if set, no touch field will be spawned and a remote
button or trigger field activates the door.
"health" if set, door must be shot open
"speed" movement speed (100 default)
"wait" wait before returning (3 default, -1 = never return)
"dmg" damage to inflict when blocked (2 default)
"sounds"
0) no sound
1) stone
2) base
3) stone chain
4) screechy metal
*/
2016-06-04 15:24:23 +02:00
class CRotDoor : public CBaseDoor
{
public:
void Spawn( void );
virtual void SetToggleState( int state );
};
LINK_ENTITY_TO_CLASS( func_door_rotating, CRotDoor )
2016-06-04 15:24:23 +02:00
void CRotDoor::Spawn( void )
{
Precache();
// set the axis of rotation
CBaseToggle::AxisDir( pev );
// check for clockwise rotation
2016-07-31 15:48:50 +02:00
if( FBitSet( pev->spawnflags, SF_DOOR_ROTATE_BACKWARDS ) )
2016-06-04 15:24:23 +02:00
pev->movedir = pev->movedir * -1;
2016-07-31 15:48:50 +02:00
//m_flWait = 2; who the hell did this? (sjb)
m_vecAngle1 = pev->angles;
m_vecAngle2 = pev->angles + pev->movedir * m_flMoveDistance;
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
ASSERTSZ( m_vecAngle1 != m_vecAngle2, "rotating door start/end positions are equal" );
if( FBitSet( pev->spawnflags, SF_DOOR_PASSABLE ) )
pev->solid = SOLID_NOT;
2016-06-04 15:24:23 +02:00
else
2016-07-31 15:48:50 +02:00
pev->solid = SOLID_BSP;
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
pev->movetype = MOVETYPE_PUSH;
UTIL_SetOrigin( pev, pev->origin );
SET_MODEL( ENT( pev ), STRING( pev->model ) );
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if( pev->speed == 0 )
2016-06-04 15:24:23 +02:00
pev->speed = 100;
2016-07-31 15:48:50 +02:00
// DOOR_START_OPEN is to allow an entity to be lighted in the closed position
// but spawn in the open position
2016-07-31 15:48:50 +02:00
if( FBitSet( pev->spawnflags, SF_DOOR_START_OPEN ) )
{
// swap pos1 and pos2, put door at pos2, invert movement direction
2016-06-04 15:24:23 +02:00
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;
2016-07-31 15:48:50 +02:00
if( FBitSet( pev->spawnflags, SF_DOOR_USE_ONLY ) )
2016-06-04 15:24:23 +02:00
{
SetTouch( NULL );
}
else // touchable button
SetTouch( &CBaseDoor::DoorTouch );
}
2016-07-31 15:48:50 +02:00
void CRotDoor::SetToggleState( int state )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
if( state == TS_AT_TOP )
2016-06-04 15:24:23 +02:00
pev->angles = m_vecAngle2;
else
pev->angles = m_vecAngle1;
UTIL_SetOrigin( pev, pev->origin );
}
class CMomentaryDoor : public CBaseToggle
{
public:
2016-07-31 15:48:50 +02:00
void Spawn( void );
2016-06-04 15:24:23 +02:00
void Precache( void );
void EXPORT MomentaryMoveDone( void );
2019-05-13 00:08:25 +02:00
void EXPORT StopMoveSound( void );
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
void KeyValue( KeyValueData *pkvd );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual int ObjectCaps( void ) { return CBaseToggle::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
BYTE m_bMoveSnd; // sound a door makes while moving
BYTE m_bStopSnd; // sound a door makes when it stops
2016-06-04 15:24:23 +02:00
};
LINK_ENTITY_TO_CLASS( momentary_door, CMomentaryDoor )
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
TYPEDESCRIPTION CMomentaryDoor::m_SaveData[] =
2016-06-04 15:24:23 +02:00
{
DEFINE_FIELD( CMomentaryDoor, m_bMoveSnd, FIELD_CHARACTER ),
DEFINE_FIELD( CMomentaryDoor, m_bStopSnd, FIELD_CHARACTER ),
};
IMPLEMENT_SAVERESTORE( CMomentaryDoor, CBaseToggle )
2016-06-04 15:24:23 +02:00
void CMomentaryDoor::Spawn( void )
{
2016-07-31 15:48:50 +02:00
SetMovedir( pev );
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
pev->solid = SOLID_BSP;
pev->movetype = MOVETYPE_PUSH;
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
UTIL_SetOrigin( pev, pev->origin );
SET_MODEL( ENT( pev ), STRING( pev->model ) );
if( pev->speed == 0 )
2016-06-04 15:24:23 +02:00
pev->speed = 100;
2016-07-31 15:48:50 +02:00
if( pev->dmg == 0 )
2016-06-04 15:24:23 +02:00
pev->dmg = 2;
2016-07-31 15:48:50 +02:00
m_vecPosition1 = pev->origin;
2016-06-04 15:24:23 +02:00
// Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big
2016-07-31 15:48:50 +02:00
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" );
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if( FBitSet( pev->spawnflags, SF_DOOR_START_OPEN ) )
2016-06-04 15:24:23 +02:00
{ // swap pos1 and pos2, put door at pos2
2016-07-31 15:48:50 +02:00
UTIL_SetOrigin( pev, m_vecPosition2 );
2016-06-04 15:24:23 +02:00
m_vecPosition2 = m_vecPosition1;
m_vecPosition1 = pev->origin;
}
SetTouch( NULL );
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
Precache();
}
2016-06-04 15:24:23 +02:00
void CMomentaryDoor::Precache( void )
{
const char *pszSound;
BOOL NullSound = FALSE;
// set the door's "in-motion" sound
2016-07-31 15:48:50 +02:00
switch( m_bMoveSnd )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
case 1:
pszSound = "doors/doormove1.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 2:
pszSound = "doors/doormove2.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 3:
pszSound = "doors/doormove3.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 4:
pszSound = "doors/doormove4.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 5:
pszSound = "doors/doormove5.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 6:
pszSound = "doors/doormove6.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 7:
pszSound = "doors/doormove7.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 8:
pszSound = "doors/doormove8.wav";
2016-06-04 15:24:23 +02:00
break;
case 0:
2016-06-04 15:24:23 +02:00
default:
pszSound = "common/null.wav";
NullSound = TRUE;
2016-06-04 15:24:23 +02:00
break;
}
if( !NullSound )
PRECACHE_SOUND( pszSound );
pev->noiseMoving = MAKE_STRING( pszSound );
NullSound = FALSE;
// set the door's 'reached destination' stop sound
2016-07-31 15:48:50 +02:00
switch( m_bStopSnd )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
case 1:
pszSound = "doors/doorstop1.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 2:
pszSound = "doors/doorstop2.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 3:
pszSound = "doors/doorstop3.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 4:
pszSound = "doors/doorstop4.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 5:
pszSound = "doors/doorstop5.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 6:
pszSound = "doors/doorstop6.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 7:
pszSound = "doors/doorstop7.wav";
2016-06-04 15:24:23 +02:00
break;
2016-07-31 15:48:50 +02:00
case 8:
pszSound = "doors/doorstop8.wav";
2016-06-04 15:24:23 +02:00
break;
case 0:
2016-06-04 15:24:23 +02:00
default:
pszSound = "common/null.wav";
NullSound = TRUE;
2016-06-04 15:24:23 +02:00
break;
}
if( !NullSound )
PRECACHE_SOUND( pszSound );
pev->noiseArrived = MAKE_STRING( pszSound );
2016-06-04 15:24:23 +02:00
}
void CMomentaryDoor::KeyValue( KeyValueData *pkvd )
{
2016-07-31 15:48:50 +02:00
if( FStrEq( pkvd->szKeyName, "movesnd" ) )
2016-06-04 15:24:23 +02:00
{
2017-06-29 15:56:03 +02:00
m_bMoveSnd = atoi( pkvd->szValue );
2016-06-04 15:24:23 +02:00
pkvd->fHandled = TRUE;
}
2016-07-31 15:48:50 +02:00
else if( FStrEq( pkvd->szKeyName, "stopsnd" ) )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
m_bStopSnd = atof( pkvd->szValue );
2016-06-04 15:24:23 +02:00
pkvd->fHandled = TRUE;
}
2016-07-31 15:48:50 +02:00
else if( FStrEq( pkvd->szKeyName, "healthvalue" ) )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
//m_bHealthValue = atof( pkvd->szValue );
2016-06-04 15:24:23 +02:00
pkvd->fHandled = TRUE;
}
else
CBaseToggle::KeyValue( pkvd );
}
void CMomentaryDoor::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
2016-07-31 15:48:50 +02:00
if( useType != USE_SET ) // Momentary buttons will pass down a float in here
2016-06-04 15:24:23 +02:00
return;
2016-07-31 15:48:50 +02:00
if( value > 1.0 )
2016-06-04 15:24:23 +02:00
value = 1.0;
2016-07-31 15:48:50 +02:00
if( value < 0.0 )
2016-02-29 21:04:01 +01:00
value = 0.0;
2016-07-31 15:48:50 +02:00
Vector move = m_vecPosition1 + ( value * ( m_vecPosition2 - m_vecPosition1 ) );
2016-06-04 15:24:23 +02:00
Vector delta = move - pev->origin;
//float speed = delta.Length() * 10;
float speed = delta.Length() / 0.1; // move there in 0.1 sec
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if( speed != 0 )
2016-06-04 15:24:23 +02:00
{
// This entity only thinks when it moves, so if it's thinking, it's in the process of moving
// play the sound when it starts moving(not yet thinking)
2016-07-31 15:48:50 +02:00
if( pev->nextthink < pev->ltime || pev->nextthink == 0 )
2017-07-23 23:24:55 +02:00
EMIT_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noiseMoving ), 1, ATTN_NORM );
// If we already moving to designated point, return
else if( move == m_vecFinalDest )
return;
2016-06-04 15:24:23 +02:00
LinearMove( move, speed );
SetMoveDone( &CMomentaryDoor::MomentaryMoveDone );
}
}
void CMomentaryDoor::MomentaryMoveDone( void )
2019-05-13 00:08:25 +02:00
{
SetThink(&CMomentaryDoor::StopMoveSound);
pev->nextthink = pev->ltime + 0.1;
}
void CMomentaryDoor::StopMoveSound()
2016-06-04 15:24:23 +02:00
{
2017-07-23 23:24:55 +02:00
STOP_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noiseMoving ) );
EMIT_SOUND( ENT( pev ), CHAN_STATIC, STRING( pev->noiseArrived ), 1, ATTN_NORM );
2019-05-13 00:08:25 +02:00
pev->nextthink = -1;
ResetThink();
2016-04-17 22:30:05 +02:00
}