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

393 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.
*
****/
#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;
vector m_vecMoveDir;
virtual void() m_pMove = 0;
virtual void() Precache;
virtual void() Respawn;
virtual void() Arrived;
virtual void() Returned;
virtual void() MoveBack;
virtual void() MoveAway;
virtual void() Touch;
virtual void() Blocked;
virtual void() Trigger;
virtual void() Use;
virtual void(entity eAttacker, int iType, int iDamage) vPain;
virtual void(entity eAttacker, int iType, int iDamage) vDeath;
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;
} else {
touch = __NULL__;
}
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)
{
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;
}
touch = __NULL__;
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::Use(void)
{
Trigger();
}
void func_button::vPain (entity attacker, int type, int damage)
{
Trigger();
}
void func_button::vDeath (entity attacker, int type, int damage)
{
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 (m_oldAngle == '0 -1 0') {
m_vecMoveDir = '0 0 1';
} else if (m_oldAngle == '0 -2 0') {
m_vecMoveDir = '0 0 -1';
} else {
makevectors(m_oldAngle);
m_vecMoveDir = v_forward;
}
}
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::Respawn(void)
{
func_button::SetMovementDirection();
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
setorigin(this, m_oldOrigin);
setmodel(this, m_oldModel);
blocked = Blocked;
velocity = [0,0,0];
nextthink = -1;
health = m_oldHealth;
if (health > 0) {
takedamage = DAMAGE_YES;
}
if (!m_flSpeed) {
m_flSpeed = 100;
}
if (spawnflags & SF_BTT_TOUCH_ONLY) {
touch = Touch;
PlayerUse = __NULL__;
} else {
touch = __NULL__;
PlayerUse = Use;
}
m_vecPos1 = m_oldOrigin;
if (spawnflags & SF_BTT_NOMOVE) {
m_vecPos2 = m_vecPos1;
} else {
m_vecPos2 = (m_vecPos1 + m_vecMoveDir * (fabs(m_vecMoveDir * size) - m_flLip));
}
m_iState = STATE_LOWERED;
}
void func_button::func_button(void)
{
func_button::Precache();
CBaseTrigger::CBaseTrigger();
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::Respawn();
angles = [0,0,0];
}