From ffee615ead2829dd9ab080d4549bb4a97b418ceb Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Mon, 31 Aug 2020 09:07:57 +0200 Subject: [PATCH] func_rot_button: Initial implementation. Sounds still missing. --- src/gs-entbase/server.src | 1 + src/gs-entbase/server/func_rot_button.cpp | 214 ++++++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 src/gs-entbase/server/func_rot_button.cpp diff --git a/src/gs-entbase/server.src b/src/gs-entbase/server.src index 2b755566..7e55735d 100644 --- a/src/gs-entbase/server.src +++ b/src/gs-entbase/server.src @@ -47,6 +47,7 @@ server/func_wall.cpp server/func_wall_toggle.cpp server/func_conveyor.cpp server/func_rotating.cpp +server/func_rot_button.cpp server/func_plat.cpp server/func_pendulum.cpp server/func_vehicle.cpp diff --git a/src/gs-entbase/server/func_rot_button.cpp b/src/gs-entbase/server/func_rot_button.cpp new file mode 100644 index 00000000..6fc8613b --- /dev/null +++ b/src/gs-entbase/server/func_rot_button.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/*QUAKED func_rot_button (0 .5 .8) ? FNCROTBUT_NONSOLID FNCROTBUT_REVERSE x x x FNCROTBUT_TOGGLE FNCROTBUT_XAXIS FNCROTBUT_YAXIS FNCROTBUT_TOUCHABLE +"targetname" Name +"target" Name of the entity to trigger when opened +"speed" How fast the button rotates when activated. +"health" If non-zero, the button must be damaged to turn +"wait" Time to wait before button resets itself. -1 makes it stay set. +"distance" Distance in degrees the button will rotate + + +A button that rotates. Used for valves, spigots and alike. +*/ + +enumflags +{ + FNCROTBUT_NONSOLID, + FNCROTBUT_REVERSE, + FNCROTBUT_UNUSED1, + FNCROTBUT_UNUSED2, + FNCROTBUT_UNUSED3, + FNCROTBUT_TOGGLE, + FNCROTBUT_XAXIS, + FNCROTBUT_YAXIS, + FNCROTBUT_TOUCHABLE +}; + +enum +{ + ROTBTNSTATE_OPENED, + ROTBTNSTATE_CLOSED, + ROTBTNSTATE_OPENING, + ROTBTNSTATE_CLOSING +}; + +class func_rot_button:CBaseTrigger +{ + vector m_vecMoveAngle; + int m_iState; + + float m_flSpeed; + float m_flDistance; + float m_flReturnTime; + int m_iHealth; + + void(void) func_rot_button; + + virtual void(void) ArrivedClosed; + virtual void(void) ArrivedOpened; + virtual void(void) TriggerTargets; + virtual void(vector, void()) Rotate; + virtual void(void) TurnToggle; + virtual void(void) PlayerUse; + virtual void(void) Respawn; + virtual void(int) Death; + virtual void(void) touch; +}; + +void +func_rot_button::TriggerTargets(void) +{ + if (m_flDelay > 0) { + CBaseTrigger::UseTargets_Delay(this, TRIG_TOGGLE, m_flDelay); + } else { + CBaseTrigger::UseTargets(this, TRIG_TOGGLE); + } +} + +void +func_rot_button::ArrivedClosed(void) +{ + avelocity = [0,0,0]; + m_iState = ROTBTNSTATE_CLOSED; + TriggerTargets(); + + if (m_flReturnTime > 0.0f) { + think = TurnToggle; + nextthink = ltime + m_flReturnTime; + } +} + +void +func_rot_button::ArrivedOpened(void) +{ + avelocity = [0,0,0]; + m_iState = ROTBTNSTATE_OPENED; +} + +void +func_rot_button::Rotate(vector vecDest, void(void) vFunc) +{ + vector vecAngleDifference; + float flTravelLength, flTravelTime; + + vecAngleDifference = (vecDest - angles); + flTravelLength = vlen(vecAngleDifference); + flTravelTime = (flTravelLength / m_flSpeed); + avelocity = (vecAngleDifference * (1 / flTravelTime)); + + think = vFunc; + nextthink = (ltime + flTravelTime); +} + +void +func_rot_button::PlayerUse(void) +{ + TurnToggle(); +} + +void +func_rot_button::touch(void) +{ + if (spawnflags & FNCROTBUT_TOUCHABLE) + TurnToggle(); +} + +void +func_rot_button::TurnToggle(void) +{ + if (m_iState == ROTBTNSTATE_OPENED) { + Rotate(m_vecMoveAngle, ArrivedClosed); + } else if (m_iState == ROTBTNSTATE_CLOSED) { + Rotate(m_oldAngle, ArrivedOpened); + + /* in toggle mode, we trigger our targets every turn */ + if (spawnflags & FNCROTBUT_TOGGLE) + TriggerTargets(); + } +} + +void +func_rot_button::Death(int i) +{ + takedamage = DAMAGE_NO; + TurnToggle(); +} + +void +func_rot_button::Respawn(void) +{ + SetMovetype(MOVETYPE_PUSH); + + if (spawnflags & FNCROTBUT_NONSOLID) + SetSolid(SOLID_NOT); + else + SetSolid(SOLID_BSP); + + SetModel(m_oldModel); + SetOrigin(m_oldOrigin); + SetAngles(m_oldAngle); + + m_iState = ROTBTNSTATE_OPENED; + think = __NULL__; + nextthink = 0.0f; + + if (m_iHealth > 0) { + takedamage = DAMAGE_YES; + health = m_iHealth; + } + + vector vecMoveDir; + if (spawnflags & FNCROTBUT_XAXIS) { + vecMoveDir = [0,0,1]; + } else if (spawnflags & FNCROTBUT_YAXIS) { + vecMoveDir = [0,1,0]; + } else { + vecMoveDir = [1,0,0]; + } + + if (spawnflags & FNCROTBUT_REVERSE) { + vecMoveDir *= -1; + } + + m_vecMoveAngle = vecMoveDir * m_flDistance; +} + +void +func_rot_button::func_rot_button(void) +{ + for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) { + switch (argv(i)) { + case "distance": + m_flDistance = stof(argv(i+1)); + break; + case "speed": + m_flSpeed = stof(argv(i+1)); + break; + case "wait": + m_flReturnTime = stof(argv(i+1)); + break; + case "health": + m_iHealth = stoi(argv(i+1)); + break; + default: + break; + } + } + + CBaseTrigger::CBaseTrigger(); +}