/*** * * Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved. * * See the file LICENSE attached with the sources for usage details. * ****/ enumflags { SF_ROT_OPEN, SF_ROT_BACKWARDS, SF_ROT_UNUSED1, SF_ROT_PASSABLE, SF_ROT_ONEWAY, SF_ROT_TOGGLE, SF_ROT_ZAXIS, SF_ROT_XAXIS, SF_ROT_USE, SF_ROT_NOMONSTERS }; #define SF_DOOR_SILENT 0x80000000i class func_door_rotating:CBaseTrigger { int m_iMoveSnd; int m_iStopSnd; int m_iDamage; int m_iLocked; float m_flDistance; float m_flSpeed; float m_flLip; float m_iState; float m_flNextAction; float m_flWait; float m_flDelay; vector m_vecDest; vector m_vecPos1; vector m_vecPos2; vector m_vecMoveDir; virtual void() m_pMove = 0; void() func_door_rotating; virtual void() Respawn; virtual void() Precache; virtual void() Arrived; virtual void() Returned; virtual void() Back; virtual void() Away; virtual void() Trigger; virtual void() Use; virtual void() Touch; virtual void() Blocked; virtual void() SetMovementDirection; virtual void(vector angle, void() func) RotToDest; virtual void() RotToDest_End; }; void func_door_rotating::Precache(void) { if (spawnflags & SF_DOOR_SILENT) { return; } 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 func_door_rotating::Arrived(void) { m_iState = STATE_RAISED; if (m_iStopSnd > 0 && m_iStopSnd <= 8) { sound(this, CHAN_VOICE, sprintf("doors/doorstop%i.wav", m_iStopSnd), 1.0, ATTN_NORM); } else { sound(this, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM); } if (!(spawnflags & SF_ROT_USE)) { touch = Touch; } if (m_flWait < 0) { return; } think = Back; nextthink = (ltime + m_flWait); } void func_door_rotating::Returned(void) { if (!(spawnflags & SF_ROT_USE)) { touch = Touch; } m_iState = STATE_LOWERED; } void func_door_rotating::Back(void) { if (!(spawnflags & SF_DOOR_SILENT)) { if (m_iMoveSnd > 0 && m_iMoveSnd <= 10) { sound(this, CHAN_VOICE, sprintf("doors/doormove%i.wav", m_iMoveSnd), 1.0, ATTN_NORM); } else { sound(this, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM); } } if (!(spawnflags & SF_ROT_USE)) { touch = __NULL__; } m_iState = STATE_DOWN; RotToDest(m_vecPos1, Returned); } void func_door_rotating::Away(void) { float fDirection = 1.0; if (m_iState == STATE_UP) { return; } if (!(spawnflags & SF_DOOR_SILENT)) { if (m_iMoveSnd > 0 && m_iMoveSnd <= 10) { sound(this, CHAN_VOICE, sprintf("doors/doormove%i.wav", m_iMoveSnd), 1.0, ATTN_NORM); } else { sound(this, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM); } } if (m_iState == STATE_RAISED) { nextthink = (ltime + m_flWait); return; } m_iState = STATE_UP; if (!(spawnflags & SF_ROT_ONEWAY)) { /* One way doors only work on the Y axis */ if (!(spawnflags & SF_ROT_ZAXIS || spawnflags & SF_ROT_XAXIS)) { vector vDifference = eActivator.origin - origin; vector vAngles = eActivator.angles; vAngles[0] = vAngles[2] = 0; makevectors(vAngles); vector vNext = (eActivator.origin + (v_forward * 10)) - origin; if (((vDifference[0] * vNext[1]) - (vDifference[1] * vNext[0])) < 0) { fDirection = -1.0f; } } } RotToDest(m_vecPos2 * fDirection, Arrived); } void func_door_rotating::Trigger(void) { if (m_flNextAction > time) { return; } m_flNextAction = time + m_flWait; if ((m_iState == STATE_UP) || (m_iState == STATE_RAISED)) { Back(); return; } Away(); if (m_flDelay) { #ifdef GS_DEVELOPER print(sprintf("func_door_rotating: Delayed trigger of `%s`\n", m_strTarget)); #endif CBaseTrigger::UseTargets_Delay(m_flDelay); } else { #ifdef GS_DEVELOPER print(sprintf("func_door_rotating: Normal trigger of `%s`\n", m_strTarget)); #endif CBaseTrigger::UseTargets(); } } void func_door_rotating::Use(void) { eActivator.gflags &= ~GF_USE_RELEASED; Trigger(); } void func_door_rotating::Touch(void) { if (spawnflags & SF_ROT_USE) { return; } if (m_iLocked) { return; } if (other.movetype == MOVETYPE_WALK) { eActivator = other; Trigger(); } touch = __NULL__; } void func_door_rotating::Blocked(void) { if (m_iDamage) { Damage_Apply(other, this, m_iDamage, other.origin, FALSE); } if (m_flWait >= 0) { if (m_iState == STATE_DOWN) { Away(); } else { Back(); } } } void func_door_rotating::SetMovementDirection(void) { if (spawnflags & SF_ROT_ZAXIS) { m_vecMoveDir = [0,0,1]; } else if (spawnflags & SF_ROT_XAXIS) { m_vecMoveDir = [1,0,0]; } else { m_vecMoveDir = [0,1,0]; } if (spawnflags & SF_ROT_BACKWARDS) { m_vecMoveDir *= 1; } } void func_door_rotating::RotToDest_End(void) { angles = m_vecDest; avelocity = [0,0,0]; nextthink = -1; m_pMove(); } void func_door_rotating::RotToDest(vector vDestAngle, void() func) { vector vecAngleDifference; float flTravelLength, flTravelTime; if (!m_flSpeed) { print("^1func_door_rotating^7: No speed defined for moving entity!"); func_door_rotating::Respawn(); return; } vecAngleDifference = (vDestAngle - angles); flTravelLength = vlen(vecAngleDifference); flTravelTime = (flTravelLength / m_flSpeed); avelocity = (vecAngleDifference * (1 / flTravelTime)); m_vecDest = vDestAngle; m_pMove = func; think = RotToDest_End; nextthink = (ltime + flTravelTime); } void func_door_rotating::Respawn(void) { func_door_rotating::SetMovementDirection(); if (!m_flSpeed) { m_flSpeed = 100; } if (!m_flLip) { m_flLip = 90; } if (!m_flDelay) { m_flDelay = 4; } if (!m_flDistance) { m_flDistance = 90; } solid = SOLID_BSP; movetype = MOVETYPE_PUSH; setorigin(this, m_oldOrigin); setmodel(this, m_oldModel); think = __NULL__; nextthink = -1; m_pMove = 0; avelocity = [0,0,0]; blocked = Blocked; if (spawnflags & SF_ROT_USE) { touch = __NULL__; PlayerUse = Use; } else { touch = Touch; PlayerUse = __NULL__; } m_iState = STATE_LOWERED; m_vecPos1 = m_oldAngle; m_vecPos2 = m_oldAngle + m_vecMoveDir * m_flDistance; if (spawnflags & SF_ROT_OPEN) { vector vTemp = m_vecPos2; m_vecPos2 = m_vecPos1; m_vecPos1 = vTemp; m_vecMoveDir = m_vecMoveDir * -1; } if (m_strTargetName) { m_iLocked = TRUE; } angles = m_vecPos1; } void func_door_rotating::func_door_rotating(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 "distance": m_flDistance = stof(argv(i+1)); break; case "delay": m_flDelay = stof(argv(i+1)); break; case "dmg": m_iDamage = stoi(argv(i+1)); break; default: break; } } func_door_rotating::Precache(); CBaseEntity::CBaseEntity(); func_door_rotating::Respawn(); }