nuclide/Source/gs-entbase/server/func_door.cpp

361 lines
7 KiB
C++

/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
// TODO: Finish these
#define SF_MOV_OPEN 1
#define SF_MOV_UNLINK 4
#define SF_MOV_PASSABLE 8
#define SF_MOV_TOGGLE 32
#define SF_MOV_USE 256
enum
{
STATE_RAISED = 0,
STATE_LOWERED,
STATE_UP,
STATE_DOWN
};
class CFuncDoor : CBaseTrigger
{
vector m_vecPos1;
vector m_vecPos2;
vector m_vecDest;
vector m_vecMoveDir;
float m_flSpeed;
float m_flLip;
float m_iState;
float m_flNextTrigger;
float m_flWait;
float m_flDelay;
int m_iMoveSnd;
int m_iStopSnd;
int m_iDamage;
int m_iLocked;
void() CFuncDoor;
virtual void() SetMovementDirection;
virtual void(vector vdest, void() func) MoveToDestination;
virtual void() MoveToDestination_End;
virtual void() MoveAway;
virtual void() MoveBack;
virtual void() Precache;
virtual void() Arrived;
virtual void() Returned;
virtual void() Trigger;
virtual void() Blocked;
virtual void() Touch;
virtual void() PlayerUse;
virtual void() m_pMove = 0;
};
void CFuncDoor :: Precache ( void )
{
if( m_iMoveSnd > 0 && m_iMoveSnd <= 10 ) {
precache_sound( sprintf( "doors/doormove%i.wav", m_iMoveSnd ) );
} else {
precache_sound( "common/null.wav" );
}
if( m_iStopSnd > 0 && m_iStopSnd <= 8 ) {
precache_sound( sprintf( "doors/doorstop%i.wav", m_iStopSnd ) );
} else {
precache_sound( "common/null.wav" );
}
}
void CFuncDoor :: PlayerUse ( void )
{
eActivator.gflags &= ~GF_USE_RELEASED;
Trigger();
}
void CFuncDoor :: Arrived ( void )
{
m_iState = STATE_RAISED;
if( m_iStopSnd > 0 && m_iStopSnd <= 8 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doorstop%i.wav", m_iStopSnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( !( spawnflags & SF_MOV_USE ) ) {
touch = Touch;
}
if ( m_flWait < 0 ) {
return;
}
if ( !( spawnflags & SF_MOV_TOGGLE ) ) {
think = MoveBack;
nextthink = ( ltime + m_flWait );
}
}
void CFuncDoor :: Returned ( void )
{
if( m_iStopSnd > 0 && m_iStopSnd <= 8 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doorstop%i.wav", m_iStopSnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( !( spawnflags & SF_MOV_USE ) ) {
touch = Touch;
}
m_iState = STATE_LOWERED;
}
void CFuncDoor :: MoveBack ( void )
{
if( m_iMoveSnd > 0 && m_iMoveSnd <= 10 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doormove%i.wav", m_iMoveSnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( !( spawnflags & SF_MOV_USE ) ) {
touch = __NULL__;
}
m_iState = STATE_DOWN;
MoveToDestination( m_vecPos1, Returned );
}
void CFuncDoor :: MoveAway ( void )
{
if ( m_iState == STATE_UP ) {
return;
}
if( m_iMoveSnd > 0 && m_iMoveSnd <= 10 ) {
sound( self, CHAN_VOICE, sprintf( "doors/doormove%i.wav", m_iMoveSnd ), 1.0, ATTN_NORM );
} else {
sound( self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM );
}
if ( !( spawnflags & SF_MOV_TOGGLE ) ) {
if ( m_iState == STATE_RAISED ) {
nextthink = ( ltime + m_flWait );
return;
}
}
m_iState = STATE_UP;
MoveToDestination( m_vecPos2, Arrived );
}
void CFuncDoor :: Trigger ( void )
{
if ( m_flNextTrigger > ltime ) {
if ( !( spawnflags & SF_MOV_TOGGLE ) ) {
return;
}
}
m_flNextTrigger = ltime + m_flWait;
// Only trigger stuff when we are done moving
if ( ( m_iState == STATE_RAISED ) || ( m_iState == STATE_LOWERED ) ) {
if ( m_flDelay > 0 ) {
#ifdef GS_DEVELOPER
print( sprintf( "CFuncDoor: Delayed trigger of `%s`\n", m_strTarget ) );
#endif
CBaseTrigger::UseTargets_Delay( m_flDelay );
} else {
#ifdef GS_DEVELOPER
dprint( sprintf( "CFuncDoor: Normal trigger of `%s`\n", m_strTarget ) );
#endif
CBaseTrigger::UseTargets();
}
}
if ( ( m_iState == STATE_UP ) || ( m_iState == STATE_RAISED ) ){
MoveBack();
return;
}
MoveAway();
}
void CFuncDoor :: Touch ( void )
{
if ( spawnflags & SF_MOV_TOGGLE ) {
return;
}
if ( m_iLocked ) {
return;
}
if ( other.movetype == MOVETYPE_WALK ) {
if ( other.absmin[2] <= maxs[2] - 2 ) {
Trigger();
}
}
}
void CFuncDoor :: Blocked ( void )
{
if( m_iDamage ) {
//Damage_Apply( other, self, dmg, other.origin, FALSE );
}
if ( m_flWait >= 0 ) {
if ( m_iState == STATE_DOWN ) {
MoveAway ();
} else {
MoveBack ();
}
}
}
void CFuncDoor :: Respawn ( void )
{
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
setorigin( this, origin );
setmodel( this, model );
blocked = Blocked;
//Use = Trigger;
if ( m_flWait == -1 ) {
spawnflags |= SF_MOV_TOGGLE;
}
if ( !m_flSpeed ) {
m_flSpeed = 100;
}
if ( !m_iDamage ) {
m_iDamage = 2;
}
if ( spawnflags & SF_MOV_USE ) {
touch = __NULL__;
gflags |= GF_USABLE;
} else {
touch = Touch;
gflags -= gflags & GF_USABLE;
}
m_iState = STATE_LOWERED;
m_vecPos1 = origin;
m_vecPos2 = ( m_vecPos1 + m_vecMoveDir * ( fabs( m_vecMoveDir * size ) - m_flLip ) );
if ( spawnflags & SF_MOV_OPEN ) {
setorigin( this, m_vecPos2 );
m_vecPos2 = m_vecPos1;
m_vecPos1 = origin;
}
}
void CFuncDoor :: CFuncDoor ( void )
{
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "speed":
m_flSpeed = stof( argv( i + 1 ) );
break;
case "lip":
m_flLip = stof( argv( i + 1 ) );
break;
case "movesnd":
m_iMoveSnd = stoi( argv( i + 1 ) );
break;
case "stopsnd":
m_iStopSnd = stoi( argv( i + 1 ) );
break;
case "delay":
m_flDelay = stof( argv( i + 1 ) );
break;
case "wait":
m_flWait = stof( argv( i + 1 ) );
break;
default:
break;
}
}
CFuncDoor::Precache();
CFuncDoor::SetMovementDirection();
CFuncDoor::Respawn();
CBaseTrigger::CBaseTrigger();
if ( m_strTargetName ) {
m_iLocked = TRUE;
}
}
void CFuncDoor :: SetMovementDirection ( void )
{
if ( angles == '0 -1 0' ) {
m_vecMoveDir = '0 0 1';
} else if ( angles == '0 -2 0' ) {
m_vecMoveDir = '0 0 -1';
} else {
makevectors( angles );
m_vecMoveDir = v_forward;
}
angles = '0 0 0';
}
void CFuncDoor :: MoveToDestination_End ( void )
{
setorigin( this, m_vecDest );
velocity = '0 0 0';
nextthink = -1;
m_pMove();
}
void CFuncDoor :: MoveToDestination ( vector vDestination, void() func )
{
vector vecDifference;
float flTravel, fTravelTime;
if ( !m_flSpeed ) {
objerror( "No speed defined for moving entity! Will not divide by zero." );
}
m_pMove = func;
m_vecDest = vDestination;
think = MoveToDestination_End;
if ( vDestination == origin ) {
velocity = '0 0 0';
nextthink = ( ltime + 0.1 );
return;
}
vecDifference = ( vDestination - origin );
flTravel = vlen( vecDifference );
fTravelTime = ( flTravel / m_flSpeed );
if ( fTravelTime < 0.1 ) {
velocity = '0 0 0';
nextthink = ltime + 0.1;
return;
}
nextthink = ( ltime + fTravelTime );
velocity = ( vecDifference * ( 1 / fTravelTime ) );
}
CLASSEXPORT( func_door, CFuncDoor )
void func_water ( void )
{
spawnfunc_CFuncDoor();
self.classname = "CFuncWater";
self.solid = SOLID_BSP;
self.skin = CONTENT_WATER;
}