/*** * * 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; angles = [0,0,0]; } 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(); }