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

367 lines
6.7 KiB
C++
Raw Normal View History

/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
#define SF_BTT_NOMOVE 1
#define SF_BTT_TOGGLE 32
#define SF_BTT_SPARKS 64
#define SF_BTT_TOUCH_ONLY 256
enum
{
STATE_RAISED,
STATE_LOWERED,
STATE_UP,
STATE_DOWN
};
enum
{
FRAME_OFF,
FRAME_ON
};
class func_button : CBaseTrigger
{
float m_flSpeed;
float m_flLip;
int m_iDamage;
int m_iState;
vector m_vecPos1;
vector m_vecPos2;
int m_iSounds;
float m_flNextTrigger;
vector m_vecDest;
string m_strNoise;
float m_flWait;
float m_flDelay;
virtual void() m_pMove = 0;
virtual void() Precache;
virtual void() Arrived;
virtual void() Returned;
virtual void() MoveBack;
virtual void() MoveAway;
virtual void() Touch;
virtual void() Blocked;
virtual void() Trigger;
virtual void() PlayerUse;
virtual void() SetMovementDirection;
virtual void(vector vdest, void() func) MoveToDestination;
virtual void() MoveToDestination_End;
};
void func_button :: Precache( void )
{
precache_model( model );
switch( m_iSounds ) {
case 0:
m_strNoise = "common/null.wav";
break;
case 1:
m_strNoise = "buttons/button1.wav";
break;
case 2:
m_strNoise = "buttons/button2.wav";
break;
case 3:
m_strNoise = "buttons/button3.wav";
break;
case 4:
m_strNoise = "buttons/button4.wav";
break;
case 5:
m_strNoise = "buttons/button5.wav";
break;
case 6:
m_strNoise = "buttons/button6.wav";
break;
case 7:
m_strNoise = "buttons/button7.wav";
break;
case 8:
m_strNoise = "buttons/button8.wav";
break;
case 9:
m_strNoise = "buttons/button9.wav";
break;
case 10:
m_strNoise = "buttons/button10.wav";
break;
case 11:
m_strNoise = "buttons/button11.wav";
break;
case 12:
m_strNoise = "buttons/latchlocked1.wav";
break;
case 13:
m_strNoise = "buttons/latchunlocked1.wav";
break;
case 14:
m_strNoise = "buttons/lightswitch2.wav";
break;
case 21:
m_strNoise = "buttons/lever1.wav";
break;
case 22:
m_strNoise = "buttons/lever2.wav";
break;
case 23:
m_strNoise = "buttons/lever3.wav";
break;
case 24:
m_strNoise = "buttons/lever4.wav";
break;
case 25:
m_strNoise = "buttons/lever5.wav";
break;
default:
m_strNoise = "buttons/button9.wav";
}
precache_sound( m_strNoise );
}
void func_button :: Arrived( void )
{
m_iState = STATE_RAISED;
if ( !( spawnflags & SF_BTT_TOUCH_ONLY ) ) {
touch = Touch;
}
if ( spawnflags & SF_BTT_TOGGLE ) {
return;
}
if ( m_flWait != -1 ) {
think = MoveBack;
nextthink = ( ltime + m_flWait );
}
}
void func_button :: Returned( void )
{
if ( !( spawnflags & SF_BTT_TOUCH_ONLY ) ) {
touch = Touch;
}
m_iState = STATE_LOWERED;
frame = FRAME_OFF;
}
void func_button :: MoveBack( void )
{
if ( !( spawnflags & SF_BTT_TOUCH_ONLY ) ) {
touch = __NULL__;
}
m_iState = STATE_DOWN;
if ( m_vecPos2 != m_vecPos1 ) {
func_button::MoveToDestination ( m_vecPos1, Returned );
} else {
func_button::Returned();
}
}
void func_button :: MoveAway( void )
{
if ( m_iState == STATE_UP ) {
return;
}
if ( m_iState == STATE_RAISED ) {
nextthink = ( ltime + m_flWait );
return;
}
m_iState = STATE_UP;
if ( m_vecPos2 != m_vecPos1 ) {
func_button::MoveToDestination( m_vecPos2, Arrived );
} else {
func_button::Arrived();
}
frame = FRAME_ON;
}
void func_button :: Trigger( void )
{
if ( m_flNextTrigger > time ) {
return;
}
m_flNextTrigger = time + m_flWait;
if ( ( m_iState == STATE_UP ) || ( m_iState == STATE_RAISED ) ){
if ( m_flWait != -1 ) {
func_button::MoveBack();
}
return;
}
sound( this, CHAN_VOICE, m_strNoise, 1.0, ATTN_NORM );
func_button::MoveAway();
if ( m_flDelay ) {
#ifdef GS_DEVELOPER
dprint( sprintf( "func_button: Delayed trigger of `%s`\n", m_strTarget ) );
#endif
CBaseTrigger::UseTargets_Delay( m_flDelay );
} else {
#ifdef GS_DEVELOPER
print( sprintf( "func_button: Normal trigger of `%s`\n", m_strTarget ) );
#endif
CBaseTrigger::UseTargets();
}
}
void func_button :: Touch( void )
{
if ( other.movetype == MOVETYPE_WALK ) {
func_button::Trigger();
if ( !( spawnflags & SF_BTT_TOUCH_ONLY ) ) {
touch = __NULL__;
}
}
}
void func_button :: PlayerUse ( void )
{
Trigger();
}
void func_button :: Blocked( void )
{
if ( m_iDamage ) {
//Damage_Apply( other, this, dmg, other.origin, FALSE );
}
if ( m_flWait >= 0 ) {
if ( m_iState == STATE_DOWN ) {
func_button::MoveAway ();
} else {
func_button::MoveBack ();
}
}
}
void func_button :: SetMovementDirection( void )
{
if ( angles == '0 -1 0' ) {
movedir = '0 0 1';
} else if ( angles == '0 -2 0' ) {
movedir = '0 0 -1';
} else {
makevectors( angles );
movedir = v_forward;
}
angles = '0 0 0';
}
void func_button :: MoveToDestination_End( void )
{
setorigin( this, m_vecDest );
velocity = '0 0 0';
nextthink = -1;
m_pMove();
}
void func_button :: 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 ) );
}
void func_button :: func_button( 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 "sounds":
m_iSounds = stoi( argv( i + 1 ) );
break;
case "wait":
m_flWait = stof( argv( i + 1 ) );
break;
case "delay":
m_flDelay = stof( argv( i + 1 ) );
break;
default:
break;
}
}
func_button::Precache();
func_button::SetMovementDirection();
CBaseTrigger::CBaseTrigger();
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
setorigin( this, origin );
setmodel( this, model );
blocked = Blocked;
if ( !m_flSpeed ) {
m_flSpeed = 100;
}
if ( spawnflags & SF_BTT_TOUCH_ONLY ) {
touch = Touch;
gflags -= gflags & GF_USABLE;
} else {
touch = __NULL__;
gflags |= GF_USABLE;
}
m_vecPos1 = origin;
if ( spawnflags & SF_BTT_NOMOVE ) {
m_vecPos2 = m_vecPos1;
} else {
m_vecPos2 = ( m_vecPos1 + movedir * ( fabs( movedir * size ) - m_flLip ) );
}
m_iState = STATE_LOWERED;
}