From c7709bb2d5f9a1b978cdc5e01dab07b8ca6285d5 Mon Sep 17 00:00:00 2001 From: Marco Cawthorne Date: Mon, 13 Mar 2023 15:26:35 -0700 Subject: [PATCH] Add NSMoverEntity, a class that handles moving, pushing entity classes such as func_door and the like. --- src/gs-entbase/server/func_button.qc | 200 ++--------- src/gs-entbase/server/func_door.qc | 318 ++++------------ src/gs-entbase/server/func_door_rotating.qc | 378 +++++++------------- src/server/defs.h | 3 - src/shared/NSMoverEntity.h | 110 ++++++ src/shared/NSMoverEntity.qc | 342 ++++++++++++++++++ src/shared/defs.h | 1 + src/shared/include.src | 1 + 8 files changed, 696 insertions(+), 657 deletions(-) create mode 100644 src/shared/NSMoverEntity.h create mode 100644 src/shared/NSMoverEntity.qc diff --git a/src/gs-entbase/server/func_button.qc b/src/gs-entbase/server/func_button.qc index db02683b..e63802fd 100644 --- a/src/gs-entbase/server/func_button.qc +++ b/src/gs-entbase/server/func_button.qc @@ -27,14 +27,6 @@ enumflags SF_BTT_TOUCH_ONLY }; -enum -{ - STATE_RAISED, - STATE_LOWERED, - STATE_UP, - STATE_DOWN -}; - enum { FRAME_OFF, @@ -79,18 +71,14 @@ original position. This entity was introduced in Quake (1996). */ class -func_button:NSSurfacePropEntity +func_button:NSMoverEntity { - int m_iState; + moverState_t m_moverState; float m_flSpeed; float m_flLip; float m_flNextTrigger; float m_flWait; float m_flDelay; - vector m_vecPos1; - vector m_vecPos2; - vector m_vecDest; - vector m_vecMoveDir; string m_strSndPressed; string m_strSndUnpressed; @@ -111,32 +99,24 @@ public: virtual void SpawnKey(string,string); virtual void Spawned(void); virtual void Respawn(void); - virtual void Arrived(void); - virtual void Returned(void); - virtual void MoveBack(void); - virtual void MoveAway(void); virtual void Touch(entity); virtual void Blocked(entity); virtual void Trigger(entity, triggermode_t); virtual void DeathTrigger(void); virtual void PlayerUse(void); - virtual void SetMovementDirection(void); - virtual void MoveToDestination(vector, void(void)); + + virtual void MoverStartsMoving(void); + virtual void MoverFinishesMoving(void); }; void func_button::func_button(void) { - m_iState = 0i; m_flSpeed = 0.0f; m_flLip = 0.0f; m_flNextTrigger = 0.0f; m_flWait = 4.0f; m_flDelay = 0.0f; - m_vecPos1 = [0.0f, 0.0f, 0.0f]; - m_vecPos2 = [0.0f, 0.0f, 0.0f]; - m_vecDest = [0.0f, 0.0f, 0.0f]; - m_vecMoveDir = [0.0f, 0.0f, 0.0f]; m_strSndPressed = __NULL__; m_strSndUnpressed = __NULL__; m_bCanTouch = false; @@ -151,16 +131,11 @@ void func_button::Save(float handle) { super::Save(handle); - SaveInt(handle, "m_iState", m_iState); SaveFloat(handle, "m_flSpeed", m_flSpeed); SaveFloat(handle, "m_flLip", m_flLip); SaveFloat(handle, "m_flNextTrigger", m_flNextTrigger); SaveFloat(handle, "m_flWait", m_flWait); SaveFloat(handle, "m_flDelay", m_flDelay); - SaveVector(handle, "m_vecPos1", m_vecPos1); - SaveVector(handle, "m_vecPos2", m_vecPos2); - SaveVector(handle, "m_vecDest", m_vecDest); - SaveVector(handle, "m_vecMoveDir", m_vecMoveDir); SaveString(handle, "m_strSndPressed", m_strSndPressed); SaveString(handle, "m_strSndUnpressed", m_strSndUnpressed); SaveString(handle, "m_strOnPressed", m_strOnPressed); @@ -175,9 +150,6 @@ void func_button::Restore(string strKey, string strValue) { switch (strKey) { - case "m_iState": - m_iState = ReadInt(strValue); - break; case "m_flSpeed": m_flSpeed = ReadFloat(strValue); break; @@ -193,18 +165,6 @@ func_button::Restore(string strKey, string strValue) case "m_flDelay": m_flDelay = ReadFloat(strValue); break; - case "m_vecPos1": - m_vecPos1 = ReadVector(strValue); - break; - case "m_vecPos2": - m_vecPos2 = ReadVector(strValue); - break; - case "m_vecDest": - m_vecDest = ReadVector(strValue); - break; - case "m_vecMoveDir": - m_vecMoveDir = ReadVector(strValue); - break; case "m_strSndPressed": m_strSndPressed = ReadString(strValue); break; @@ -306,10 +266,6 @@ func_button::Spawned(void) void func_button::Respawn(void) { - RestoreAngles(); - SetMovementDirection(); - ClearAngles(); - SetSolid(SOLID_BSP); SetMovetype(MOVETYPE_PUSH); SetOrigin(GetSpawnOrigin()); @@ -319,6 +275,11 @@ func_button::Respawn(void) ReleaseThink(); SetHealth(GetSpawnHealth()); + RestoreAngles(); + SetPosition1(GetSpawnOrigin()); + SetPosition2(GetDirectionalPosition(GetSpawnAngles(), m_flLip)); + ClearAngles(); + if (health > 0) { takedamage = DAMAGE_YES; Death = DeathTrigger; @@ -328,86 +289,47 @@ func_button::Respawn(void) m_flSpeed = 100; } - m_vecPos1 = GetSpawnOrigin(); - if (HasSpawnFlags(SF_BTT_NOMOVE)) { - m_vecPos2 = m_vecPos1; - } else { - m_vecPos2 = (m_vecPos1 + m_vecMoveDir * (fabs(m_vecMoveDir * size) - m_flLip)); + SetPosition2(GetPosition1()); } m_iValue = 0; - m_iState = STATE_LOWERED; } void -func_button::Arrived(void) +func_button::MoverFinishesMoving(void) { - SetOrigin(m_vecDest); - ClearVelocity(); - ReleaseThink(); - m_bCanTouch = true; - - UseOutput(this, m_strOnIn); - m_iState = STATE_RAISED; - - if (HasSpawnFlags(SF_BTT_TOGGLE) == true) { - return; + static void MoveBack(void) { + MoveToPosition(GetPosition1(), m_flSpeed); } - - if (m_flWait != -1) { + + if (GetMoverState() == MOVER_POS1) { + UseOutput(this, m_strOnOut); + SetFrame(FRAME_OFF); + } else if (GetMoverState() == MOVER_POS2) { + UseOutput(this, m_strOnIn); ScheduleThink(MoveBack, m_flWait); } -} -void -func_button::Returned(void) -{ - UseOutput(this, m_strOnOut); - SetOrigin(m_vecDest); - ClearVelocity(); - ReleaseThink(); - SetFrame(FRAME_OFF); m_bCanTouch = true; - m_iState = STATE_LOWERED; } -void -func_button::MoveBack(void) -{ - m_bCanTouch = false; - m_iState = STATE_DOWN; - m_iValue = 0; - - if (m_strSndUnpressed) { - Sound_Play(this, CHAN_VOICE, m_strSndUnpressed); - } - - if (m_vecPos2 != m_vecPos1) { - MoveToDestination (m_vecPos1, Returned); - } else { - Returned(); - } -} void -func_button::MoveAway(void) +func_button::MoverStartsMoving(void) { - if (m_iState == STATE_UP) { - return; - } - m_bCanTouch = false; - m_iState = STATE_UP; - - if (m_vecPos2 != m_vecPos1) { - MoveToDestination(m_vecPos2, Arrived); - } else { - Arrived(); - } - m_iValue = 1; - SetFrame(FRAME_ON); + if (GetMoverState() == MOVER_1TO2) { + m_iValue = 1; + SetFrame(FRAME_ON); + } else if (GetMoverState() == MOVER_2TO1) { + m_iValue = 0; + + if (m_strSndUnpressed) { + Sound_Play(this, CHAN_VOICE, m_strSndUnpressed); + } + } } /* TODO: Handle state */ @@ -425,9 +347,9 @@ func_button::Trigger(entity act, triggermode_t state) m_flNextTrigger = time + m_flWait; - if ((m_iState == STATE_UP) || (m_iState == STATE_RAISED)){ + if ((m_moverState == MOVER_1TO2) || (m_moverState == MOVER_POS2)){ if (m_flWait != -1) { - MoveBack(); + MoveToPosition(GetPosition1(), m_flSpeed); } return; } @@ -435,8 +357,7 @@ func_button::Trigger(entity act, triggermode_t state) if (m_strSndPressed) Sound_Play(this, CHAN_VOICE, m_strSndPressed); - MoveAway(); - + MoveToPosition(GetPosition2(), m_flSpeed); UseOutput(act, m_strOnPressed); UseTargets(act, TRIG_TOGGLE, m_flDelay); @@ -480,55 +401,6 @@ void func_button::Blocked(entity eBlocker) { if (m_flWait >= 0) { - if (m_iState == STATE_DOWN) { - MoveAway(); - } else { - MoveBack(); - } + MoveToReverse(m_flSpeed); } -} - -void -func_button::SetMovementDirection(void) -{ - if (GetSpawnAngles() == [0,-1,0]) { - m_vecMoveDir = [0,0,1]; - } else if (GetSpawnAngles() == [0,-2,0]) { - m_vecMoveDir = [0,0,-1]; - } else { - makevectors(GetSpawnAngles()); - m_vecMoveDir = v_forward; - } -} - -void -func_button::MoveToDestination(vector vecDest, void(void) func) -{ - vector vecDifference; - float flTravel, fTravelTime; - - if (!m_flSpeed) { - objerror("No speed defined for moving entity! Will not divide by zero."); - } - - m_vecDest = vecDest; - - if (vecDest == origin) { - ClearVelocity(); - ScheduleThink(func, 0.0f); - return; - } - - vecDifference = (vecDest - origin); - flTravel = vlen(vecDifference); - fTravelTime = (flTravel / m_flSpeed); - - if (fTravelTime < 0.1) { - ClearVelocity(); - ScheduleThink(func, 0.0f); - return; - } - - ScheduleThink(func, fTravelTime); - SetVelocity(vecDifference * (1 / fTravelTime)); -} +} \ No newline at end of file diff --git a/src/gs-entbase/server/func_door.qc b/src/gs-entbase/server/func_door.qc index 8e6a7dfd..5bf6276b 100644 --- a/src/gs-entbase/server/func_door.qc +++ b/src/gs-entbase/server/func_door.qc @@ -26,14 +26,6 @@ enumflags { SF_MOV_USE }; -enum -{ - DOORSTATE_RAISED, - DOORSTATE_LOWERED, - DOORSTATE_UP, - DOORSTATE_DOWN -}; - /*!QUAKED func_door (0 .5 .8) ? SF_MOV_OPEN x SF_MOV_UNLINK SF_MOV_PASSABLE x SF_MOV_TOGGLE x x SF_MOV_USE # OVERVIEW This sliding door entity has the ability to slide forth and back on any @@ -72,21 +64,13 @@ X is the integer value set in "movesnd" and "stopsnd". This entity was introduced in Quake (1996). */ class -func_door:NSRenderableEntity +func_door:NSMoverEntity { public: void func_door(void); virtual void Spawned(void); - virtual void PortalOpen(void); - virtual void PortalClose(void); - virtual void SetMovementDirection(void); - virtual void MoveToDestination(vector, void(void) func); - virtual void MoveAway(void); - virtual void MoveBack(void); - virtual void Arrived(void); - virtual void Returned(void); virtual void Respawn(void); virtual void Trigger(entity, triggermode_t); virtual void Blocked(entity); @@ -97,21 +81,18 @@ public: virtual void SpawnKey(string, string); virtual void Input(entity, string, string); + virtual void MoverStartsMoving(void); + virtual void MoverFinishesMoving(void); + private: string targetClose; - vector m_vecPos1; - vector m_vecPos2; - vector m_vecDest; - vector m_vecMoveDir; float m_flSpeed; - float m_flLip; - float m_iState; float m_flNextTrigger; float m_flWait; float m_flDelay; + float m_flLip; int m_iDamage; int m_iLocked; - int m_iPortalState; int m_iForceClosed; bool m_iCanTouch; @@ -128,21 +109,13 @@ private: void func_door::func_door(void) { - m_vecPos1 = - m_vecPos2 = - m_vecDest = - m_vecMoveDir = [0,0,0]; - - m_flSpeed = m_flLip = - m_iState = m_flNextTrigger = m_flWait = m_flDelay = 0.0f; m_iDamage = m_iLocked = - m_iPortalState = m_iForceClosed = 0; m_iCanTouch = false; @@ -163,14 +136,7 @@ func_door::Save(float handle) { super::Save(handle); - SaveVector(handle, "m_vecPos1", m_vecPos1); - SaveVector(handle, "m_vecPos2", m_vecPos2); - SaveVector(handle, "m_vecDest", m_vecDest); - SaveVector(handle, "m_vecMoveDir", m_vecMoveDir); - - SaveFloat(handle, "m_flSpeed", m_flSpeed); SaveFloat(handle, "m_flLip", m_flLip); - SaveFloat(handle, "m_iState", m_iState); SaveFloat(handle, "m_flNextTrigger", m_flNextTrigger); SaveFloat(handle, "m_flWait", m_flWait); SaveFloat(handle, "m_flDelay", m_flDelay); @@ -178,7 +144,6 @@ func_door::Save(float handle) SaveInt(handle, "m_iDamage", m_iDamage); SaveInt(handle, "m_iLocked", m_iLocked); - SaveInt(handle, "m_iPortalState", m_iPortalState); SaveInt(handle, "m_iForceClosed", m_iForceClosed); SaveString(handle, "m_strLockedSfx", m_strLockedSfx); @@ -194,28 +159,9 @@ void func_door::Restore(string strKey, string strValue) { switch (strKey) { - case "m_vecPos1": - m_vecPos1 = ReadVector(strValue); - break; - case "m_vecPos2": - m_vecPos2 = ReadVector(strValue); - break; - case "m_vecDest": - m_vecDest = ReadVector(strValue); - break; - case "m_vecMoveDir": - m_vecMoveDir = ReadVector(strValue); - break; - - case "m_flSpeed": - m_flSpeed = ReadFloat(strValue); - break; case "m_flLip": m_flLip = ReadFloat(strValue); break; - case "m_iState": - m_iState = ReadFloat(strValue); - break; case "m_flNextTrigger": m_flNextTrigger = ReadFloat(strValue); break; @@ -235,9 +181,6 @@ func_door::Restore(string strKey, string strValue) case "m_iLocked": m_iLocked = ReadInt(strValue); break; - case "m_iPortalState": - m_iPortalState = ReadInt(strValue); - break; case "m_iForceClosed": m_iForceClosed = ReadInt(strValue); break; @@ -355,20 +298,10 @@ func_door::Spawned(void) void func_door::Respawn(void) { - /* reset */ - m_vecPos1 = [0,0,0]; - m_vecPos2 = [0,0,0]; - m_vecDest = [0,0,0]; - m_vecMoveDir = [0,0,0]; - /* this is a terrible hack */ if (m_flWait == 0) m_flWait = 0.01f; - RestoreAngles(); - SetMovementDirection(); - ClearAngles(); - if (HasSpawnFlags(SF_MOV_PASSABLE)) SetSolid(SOLID_NOT); else @@ -380,6 +313,11 @@ func_door::Respawn(void) AddFlags(FL_FINDABLE_NONSOLID); ReleaseThink(); + RestoreAngles(); + SetPosition1(GetSpawnOrigin()); + SetPosition2(GetDirectionalPosition(GetSpawnAngles(), m_flLip)); + ClearAngles(); + /* FIXME: Is this correct? */ if (m_flWait == -1) { spawnflags |= SF_MOV_TOGGLE; @@ -394,9 +332,6 @@ func_door::Respawn(void) } m_iValue = 0; - m_iState = DOORSTATE_LOWERED; - m_vecPos1 = GetSpawnOrigin(); - m_vecPos2 = (m_vecPos1 + m_vecMoveDir * (fabs(m_vecMoveDir * size) - m_flLip)); if (spawnflags & SF_MOV_USE) m_iCanTouch = false; @@ -405,12 +340,13 @@ func_door::Respawn(void) if (HasSpawnFlags(SF_MOV_OPEN)) { SetOrigin(m_vecPos2); - m_vecPos2 = m_vecPos1; - m_vecPos1 = origin; + SetPosition2(GetPosition1()); + SetPosition1(GetOrigin()); + m_iValue = 1; - PortalOpen(); + _PortalOpen(); } else { - PortalClose(); + _PortalClose(); } if (targetname) { @@ -436,28 +372,6 @@ func_door::Input(entity eAct, string strInput, string strData) } } -void -func_door::PortalOpen(void) -{ - if (m_iPortalState == 1) - return; - - m_iPortalState = 1; - setorigin(this, origin); - openportal(this, AREAPORTAL_OPEN); -} - -void -func_door::PortalClose(void) -{ - if (m_iPortalState == 0) - return; - - m_iPortalState = 0; - setorigin(this, origin); - openportal(this, AREAPORTAL_CLOSED); -} - void func_door::PlayerUse(void) { @@ -469,94 +383,75 @@ func_door::PlayerUse(void) } void -func_door::Arrived(void) +func_door::MoverFinishesMoving(void) { - SetOrigin(m_vecDest); - ClearVelocity(); - ReleaseThink(); - - m_iState = DOORSTATE_RAISED; - - if (m_strSndStop) { - Sound_Play(this, CHAN_VOICE, m_strSndStop); - } else { - sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); + static void MoveBack(void) { + MoveToPosition(GetPosition1(), m_flSpeed); } - if (m_strSndMove) - sound(this, CHAN_WEAPON, "common/null.wav", 1.0f, ATTN_NORM); - - if ((m_flWait < 0.0f) || HasSpawnFlags(SF_MOV_TOGGLE) == true) - return; - - ScheduleThink(MoveBack, m_flWait); -} - -void -func_door::Returned(void) -{ - SetOrigin(m_vecDest); - ClearVelocity(); - ReleaseThink(); - - if (targetClose) - for (entity f = world; (f = find(f, ::targetname, targetClose));) { - NSEntity trigger = (NSEntity)f; - if (trigger.Trigger != __NULL__) { - trigger.Trigger(this, TRIG_TOGGLE); + /* we arrived at our starting position within the map */ + if (GetMoverState() == MOVER_POS1) { + if (targetClose) + for (entity f = world; (f = find(f, ::targetname, targetClose));) { + NSEntity trigger = (NSEntity)f; + if (trigger.Trigger != __NULL__) { + trigger.Trigger(this, TRIG_TOGGLE); + } } + + if (m_strSndStop) { + Sound_Play(this, CHAN_VOICE, m_strSndStop); + } else { + sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); + } + + if (m_strSndMove) + sound(this, CHAN_WEAPON, "common/null.wav", 1.0f, ATTN_NORM); + + } else if (GetMoverState() == MOVER_POS2) { + if (m_strSndStop) { + Sound_Play(this, CHAN_VOICE, m_strSndStop); + } else { + sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); + } + + if (m_strSndMove) + sound(this, CHAN_WEAPON, "common/null.wav", 1.0f, ATTN_NORM); + + if ((m_flWait < 0.0f) || HasSpawnFlags(SF_MOV_TOGGLE) == true) + return; + + ScheduleThink(MoveBack, m_flWait); } - - if (m_strSndStop) { - Sound_Play(this, CHAN_VOICE, m_strSndStop); - } else { - sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); - } - - if (m_strSndMove) - sound(this, CHAN_WEAPON, "common/null.wav", 1.0f, ATTN_NORM); - - m_iState = DOORSTATE_LOWERED; - PortalClose(); } void -func_door::MoveBack(void) +func_door::MoverStartsMoving(void) { - if (m_strSndClose) { - Sound_Play(this, CHAN_VOICE, m_strSndClose); - } else { - sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); + if (GetMoverState() == MOVER_1TO2) { + if (m_strSndOpen) { + Sound_Play(this, CHAN_VOICE, m_strSndOpen); + } else { + sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); + } + + if (m_strSndMove) + Sound_Play(this, CHAN_WEAPON, m_strSndMove); + + m_iValue = 1; + } else if (GetMoverState() == MOVER_2TO1) { + + if (m_strSndClose) { + Sound_Play(this, CHAN_VOICE, m_strSndClose); + } else { + sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); + } + + if (m_strSndMove) + Sound_Play(this, CHAN_WEAPON, m_strSndMove); + + m_iValue = 0; } - - if (m_strSndMove) - Sound_Play(this, CHAN_WEAPON, m_strSndMove); - - m_iValue = 0; - m_iState = DOORSTATE_DOWN; - MoveToDestination(m_vecPos1, Returned); -} - -void -func_door::MoveAway(void) -{ - if (m_iState == DOORSTATE_UP) { - return; - } - - if (m_strSndOpen) { - Sound_Play(this, CHAN_VOICE, m_strSndOpen); - } else { - sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); - } - - if (m_strSndMove) - Sound_Play(this, CHAN_WEAPON, m_strSndMove); - - m_iValue = 1; - m_iState = DOORSTATE_UP; - MoveToDestination(m_vecPos2, Arrived); - PortalOpen(); } void @@ -573,20 +468,16 @@ func_door::Trigger(entity act, triggermode_t triggerstate) m_flNextTrigger = time + m_flWait; /* only trigger stuff once we are done moving */ - if ((m_iState == DOORSTATE_RAISED) || (m_iState == DOORSTATE_LOWERED)) { + if ((GetMoverState() == MOVER_POS1) || (GetMoverState() == MOVER_POS2)) { UseTargets(act, TRIG_TOGGLE, m_flDelay); } if (triggerstate == TRIG_OFF) { - MoveBack(); + MoveToPosition(GetPosition1(), m_flSpeed); } else if (triggerstate == TRIG_ON) { - MoveAway(); + MoveToPosition(GetPosition2(), m_flSpeed); } else { - if ((m_iState == DOORSTATE_UP) || (m_iState == DOORSTATE_RAISED)){ - MoveBack(); - } else { - MoveAway(); - } + MoveToReverse(m_flSpeed); } } @@ -627,61 +518,10 @@ func_door::Blocked(entity eBlocker) if (!m_iForceClosed) if (m_flWait >= 0) { - if (m_iState == DOORSTATE_DOWN) { - MoveAway(); - } else { - MoveBack(); - } + MoveToReverse(m_flSpeed); } } -void -func_door::SetMovementDirection(void) -{ - if (GetSpawnAngles() == [0,-1,0]) { - m_vecMoveDir = [0,0,1]; - } else if (GetSpawnAngles() == [0,-2,0]) { - m_vecMoveDir = [0,0,-1]; - } else { - makevectors(GetSpawnAngles()); - m_vecMoveDir = v_forward; - } -} - -void -func_door::MoveToDestination(vector vecDest, void(void) func) -{ - vector vecDifference; - float flTravel; - float fTravelTime; - - if (!m_flSpeed) { - objerror("func_door: No speed defined!"); - return; - } - - m_vecDest = vecDest; - - if (vecDest == origin) { - ScheduleThink(func, 0.1f); - ClearVelocity(); - return; - } - - vecDifference = (vecDest - origin); - flTravel = vlen(vecDifference); - fTravelTime = (flTravel / m_flSpeed); - - if (fTravelTime < 0.1) { - ScheduleThink(func, 0.1f); - ClearVelocity(); - return; - } - - ScheduleThink(func, fTravelTime); - SetVelocity(vecDifference * (1.0f / fTravelTime)); -} - void func_water(void) { diff --git a/src/gs-entbase/server/func_door_rotating.qc b/src/gs-entbase/server/func_door_rotating.qc index 2a039219..df9c136b 100644 --- a/src/gs-entbase/server/func_door_rotating.qc +++ b/src/gs-entbase/server/func_door_rotating.qc @@ -68,8 +68,30 @@ Please include an origin brush so that a pivot point will be defined. This entity was introduced in Quake II (1997). */ class -func_door_rotating:NSRenderableEntity +func_door_rotating:NSMoverEntity { +public: + void func_door_rotating(void); + + /* overrides */ + virtual void Spawned(void); + virtual void SpawnKey(string,string); + virtual void Save(float); + virtual void Restore(string,string); + virtual void Use(void); + virtual void Touch(entity); + virtual void Blocked(entity); + virtual void Respawn(void); + virtual void MoverStartsMoving(void); + virtual void MoverFinishesMoving(void); + + virtual void Trigger(entity, triggermode_t); + +#ifdef GS_PHYSICS + nonvirtual void Unhinge(void); +#endif + +private: string targetClose; string m_strSndStop; string m_strSndOpen; @@ -78,43 +100,13 @@ func_door_rotating:NSRenderableEntity float m_flSoundWait; float m_flDistance; float m_flSpeed; - float m_iState; float m_flNextAction; float m_flWait; float m_flDelay; - int m_iPortalState; int m_iDamage; int m_iLocked; - vector m_vecDest; - vector m_vecPos1; - vector m_vecPos2; - vector m_vecMoveDir; - bool m_iCanTouch; - -public: - void func_door_rotating(void); - - virtual void Save(float); - virtual void Restore(string,string); - virtual void Spawned(void); - virtual void PortalOpen(void); - virtual void PortalClose(void); - virtual void Respawn(void); - virtual void Arrived(void); - virtual void Returned(void); - virtual void Back(void); - virtual void Away(void); - virtual void Trigger(entity, triggermode_t); - virtual void Use(void); - virtual void Touch(entity); - virtual void Blocked(entity); - virtual void SetMovementDirection(void); - virtual void SpawnKey(string,string); - virtual void RotToDest(vector angle, void(void) func); - -#ifdef GS_PHYSICS - virtual void Unhinge(void); -#endif + bool m_bCanTouch; + vector m_vecTurnDir; }; void @@ -130,16 +122,11 @@ func_door_rotating::func_door_rotating(void) m_iLocked = 0i; m_flDistance = 90.0f; m_flSpeed = 100.0f; - m_iState = 0i; m_flNextAction = 0.0f; m_flWait = 0.0f; m_flDelay = 4.0f; - m_vecDest = [0.0f, 0.0f, 0.0f]; - m_vecPos1 = [0.0f, 0.0f, 0.0f]; - m_vecPos2 = [0,0,0]; - m_vecMoveDir = [0.0f, 0.0f, 0.0f]; - m_iPortalState = 0i; - m_iCanTouch = false; + m_bCanTouch = false; + m_vecTurnDir = g_vec_null; } void @@ -154,18 +141,13 @@ func_door_rotating::Save(float handle) SaveFloat(handle, "m_flSoundWait", m_flSoundWait); SaveFloat(handle, "m_flDistance", m_flDistance); SaveFloat(handle, "m_flSpeed", m_flSpeed); - SaveFloat(handle, "m_iState", m_iState); SaveFloat(handle, "m_flNextAction", m_flNextAction); SaveFloat(handle, "m_flWait", m_flWait); SaveFloat(handle, "m_flDelay", m_flDelay); - SaveInt(handle, "m_iPortalState", m_iPortalState); SaveInt(handle, "m_iDamage", m_iDamage); SaveInt(handle, "m_iLocked", m_iLocked); - SaveVector(handle, "m_vecDest", m_vecDest); - SaveVector(handle, "m_vecPos1", m_vecPos1); - SaveVector(handle, "m_vecPos2", m_vecPos2); - SaveVector(handle, "m_vecMoveDir", m_vecMoveDir); - SaveBool(handle, "m_iCanTouch", m_iCanTouch); + SaveBool(handle, "m_bCanTouch", m_bCanTouch); + SaveVector(handle, "m_vecTurnDir", m_vecTurnDir); } void @@ -196,9 +178,6 @@ func_door_rotating::Restore(string strKey, string strValue) case "m_flSpeed": m_flSpeed = ReadFloat(strValue); break; - case "m_iState": - m_iState = ReadInt(strValue); - break; case "m_flNextAction": m_flNextAction = ReadFloat(strValue); break; @@ -208,29 +187,17 @@ func_door_rotating::Restore(string strKey, string strValue) case "m_flDelay": m_flDelay = ReadFloat(strValue); break; - case "m_iPortalState": - m_iPortalState = ReadInt(strValue); - break; case "m_iDamage": m_iDamage = ReadInt(strValue); break; case "m_iLocked": m_iLocked = ReadInt(strValue); break; - case "m_vecDest": - m_vecDest = ReadVector(strValue); + case "m_bCanTouch": + m_bCanTouch = ReadInt(strValue); break; - case "m_vecPos1": - m_vecPos1 = ReadVector(strValue); - break; - case "m_vecPos2": - m_vecPos2 = ReadVector(strValue); - break; - case "m_vecMoveDir": - m_vecMoveDir = ReadVector(strValue); - break; - case "m_iCanTouch": - m_iCanTouch = ReadInt(strValue); + case "m_vecTurnDir": + m_vecTurnDir = ReadVector(strValue); break; default: super::Restore(strKey, strValue); @@ -255,10 +222,6 @@ func_door_rotating::Spawned(void) void func_door_rotating::Respawn(void) { - RestoreAngles(); - SetMovementDirection(); - ClearAngles(); - #ifdef GS_PHYSICS SetTakedamage(DAMAGE_YES); SetHealth(100); @@ -272,14 +235,24 @@ func_door_rotating::Respawn(void) ClearVelocity(); ReleaseThink(); - if (spawnflags & SF_ROT_USE) - m_iCanTouch = false; - else - m_iCanTouch = true; + if (HasSpawnFlags(SF_ROT_ZAXIS)) { + m_vecTurnDir = [0,0,1]; + } else if (HasSpawnFlags(SF_ROT_XAXIS)) { + m_vecTurnDir = [1,0,0]; + } else { + m_vecTurnDir = [0,1,0]; + } + + if (spawnflags & SF_ROT_USE) { + m_bCanTouch = false; + } else { + m_bCanTouch = true; + } /* this is a terrible hack */ - if (m_flWait == 0) + if (m_flWait == 0) { m_flWait = 0.01f; + } if (HasSpawnFlags(SF_ROT_USE)) { PlayerUse = Use; @@ -287,26 +260,22 @@ func_door_rotating::Respawn(void) PlayerUse = __NULL__; } - m_vecPos1 = GetSpawnAngles(); + SetPosition1(GetSpawnAngles()); + RestoreAngles(); if (HasSpawnFlags(SF_ROT_BACKWARDS)) { - m_vecPos2 = GetSpawnAngles() + m_vecMoveDir * -m_flDistance; + SetPosition2(GetDirectionalRotation(m_vecTurnDir, -m_flDistance)); } else { - m_vecPos2 = GetSpawnAngles() + m_vecMoveDir * m_flDistance; + SetPosition2(GetDirectionalRotation(m_vecTurnDir, m_flDistance)); } + ClearAngles(); if (HasSpawnFlags(SF_ROT_OPEN)) { - vector vTemp = m_vecPos2; - m_vecPos2 = m_vecPos1; - m_vecPos1 = vTemp; - m_vecMoveDir = m_vecMoveDir * -1; - PortalOpen(); - } else { - PortalClose(); + vector vTemp = GetPosition2(); + SetPosition2(GetPosition1()); + SetPosition1(vTemp); } - m_iState = STATE_LOWERED; - if (HasSpawnFlags(SF_ROT_PASSABLE)) { SetSolid(SOLID_NOT); } @@ -315,7 +284,7 @@ func_door_rotating::Respawn(void) m_iLocked = TRUE; } - SetAngles(m_vecPos1); + SetAngles(GetPosition1()); } void @@ -326,9 +295,6 @@ func_door_rotating::SpawnKey(string strKey, string strValue) case "speed": m_flSpeed = stof(strValue); break; - /*case "lip": - m_flDistance = stof(strValue); - break;*/ case "snd_open": m_strSndOpen = strValue; break; @@ -344,11 +310,11 @@ func_door_rotating::SpawnKey(string strKey, string strValue) break; /* GoldSrc compat */ case "movesnd": - x = stoi(strValue); + x = stoi(strValue); /* sanitize */ m_strSndOpen = m_strSndClose = sprintf("func_door_rotating.move_%i", x); break; case "stopsnd": - x = stoi(strValue); + x = stoi(strValue); /* sanitize */ m_strSndStop = sprintf("func_door_rotating.stop_%i", x); break; case "distance": @@ -364,7 +330,7 @@ func_door_rotating::SpawnKey(string strKey, string strValue) targetClose = strValue; break; case "locked_sound": - x = stoi(strValue); + x = stoi(strValue); /* sanitize */ m_strLockedSfx = sprintf("func_button.hlsfx_%i", x+1i); break; default: @@ -372,34 +338,13 @@ func_door_rotating::SpawnKey(string strKey, string strValue) } } -void -func_door_rotating::PortalOpen(void) -{ - if (m_iPortalState == 1) - return; - - m_iPortalState = 1; - setorigin(this, origin); - openportal(this, AREAPORTAL_OPEN); -} -void -func_door_rotating::PortalClose(void) -{ - if (m_iPortalState == 0) - return; - - m_iPortalState = 0; - setorigin(this, origin); - openportal(this, AREAPORTAL_CLOSED); -} - #ifdef GS_PHYSICS void func_door_rotating::Unhinge(void) { SetTakedamage(DAMAGE_NO); ReleaseThink(); - m_iCanTouch = false; + m_bCanTouch = false; SetSolid(SOLID_PHYSICS_BOX); SetMovetype(MOVETYPE_PHYSICS); physics_enable(this, TRUE); @@ -407,102 +352,60 @@ func_door_rotating::Unhinge(void) #endif void -func_door_rotating::Arrived(void) +func_door_rotating::MoverFinishesMoving(void) { - SetAngles(m_vecDest); - SetAngularVelocity([0,0,0]); - ReleaseThink(); - - m_iState = STATE_RAISED; - - if (m_strSndStop) { - Sound_Play(this, CHAN_VOICE, m_strSndStop); - } else { - sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); + static void RotateBack(void) { + RotateToPosition(GetPosition1(), m_flSpeed); } - if ((m_flWait < 0.0f) || HasSpawnFlags(SF_ROT_TOGGLE) == true) - return; - - ScheduleThink(Back, m_flWait); -} - -void -func_door_rotating::Returned(void) -{ - SetAngles(m_vecDest); - SetAngularVelocity([0,0,0]); - ReleaseThink(); - - if (m_strSndStop) { - Sound_Play(this, CHAN_VOICE, m_strSndStop); - } else { - sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); - } - - if (targetClose) - for (entity f = world; (f = find(f, ::targetname, targetClose));) { - NSEntity trigger = (NSEntity)f; - if (trigger.Trigger != __NULL__) { - trigger.Trigger(this, TRIG_TOGGLE); - } - } - - m_iState = STATE_LOWERED; - - PortalClose(); -} - -void -func_door_rotating::Back(void) -{ - if (!HasSpawnFlags(SF_DOOR_SILENT)) { - if (m_strSndClose) { - Sound_Play(this, CHAN_VOICE, m_strSndClose); + if (GetMoverState() == MOVER_POS1) { + if (m_strSndStop) { + Sound_Play(this, CHAN_VOICE, m_strSndStop); } else { sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); } - } - 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 (!HasSpawnFlags(SF_DOOR_SILENT)) { - if (m_strSndOpen) { - Sound_Play(this, CHAN_VOICE, m_strSndOpen); + if (targetClose) + for (entity f = world; (f = find(f, ::targetname, targetClose));) { + NSEntity trigger = (NSEntity)f; + if (trigger.Trigger != __NULL__) { + trigger.Trigger(this, TRIG_TOGGLE); + } + } + } else if (GetMoverState() == MOVER_POS2) { + if (m_strSndStop) { + Sound_Play(this, CHAN_VOICE, m_strSndStop); } else { sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); } + + if ((m_flWait < 0.0f) || HasSpawnFlags(SF_ROT_TOGGLE) == true) + return; + + ScheduleThink(RotateBack, m_flWait); } +} - m_iState = STATE_UP; - - if (!HasSpawnFlags(SF_ROT_ONEWAY)) { - /* One way doors only work on the Y axis */ - if (!HasSpawnFlags(SF_ROT_ZAXIS) || HasSpawnFlags(SF_ROT_XAXIS)) { - /* get the door facing dir */ - vector door_dir = vectoangles(WorldSpaceCenter() - origin); - makevectors(door_dir); - float flDir = dotproduct(origin - eActivator.origin, v_right); - - if (flDir > 0) { - fDirection = -1.0f; +void +func_door_rotating::MoverStartsMoving(void) +{ + if (GetMoverState() == MOVER_2TO1) { + if (!HasSpawnFlags(SF_DOOR_SILENT)) { + if (m_strSndClose) { + Sound_Play(this, CHAN_VOICE, m_strSndClose); + } else { + sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); + } + } + } else if (GetMoverState() == MOVER_1TO2) { + if (!HasSpawnFlags(SF_DOOR_SILENT)) { + if (m_strSndOpen) { + Sound_Play(this, CHAN_VOICE, m_strSndOpen); + } else { + sound(this, CHAN_VOICE, "common/null.wav", 1.0f, ATTN_NORM); } } } - - RotToDest(m_vecPos2 * fDirection, Arrived); - PortalOpen(); } void @@ -511,24 +414,38 @@ func_door_rotating::Trigger(entity act, triggermode_t state) if (GetMaster() == FALSE) { return; } - if (m_flNextAction > time) { - return; - } - m_flNextAction = time + m_flWait; eActivator = act; + /* this door can swing both ways */ + if (!HasSpawnFlags(SF_ROT_ONEWAY)) { + /* One way doors only work on the Y axis */ + if (!HasSpawnFlags(SF_ROT_ZAXIS) || HasSpawnFlags(SF_ROT_XAXIS)) { + float flDirection = 1.0; + /* get the door facing dir */ + vector door_dir = vectoangles(WorldSpaceCenter() - origin); + makevectors(door_dir); + float flDir = dotproduct(origin - act.origin, v_right); + + if (flDir > 0) { + flDirection = -1.0f; + } + + SetPosition2(GetDirectionalRotation(m_vecTurnDir, m_flDistance * flDirection)); + } + } + if (state == TRIG_TOGGLE) { - if ((m_iState == STATE_UP) || (m_iState == STATE_RAISED)) { - Back(); + if ((GetMoverState() == MOVER_1TO2) || (GetMoverState() == MOVER_POS2)) { + RotateToPosition(GetPosition1(), m_flSpeed); return; } else { - Away(); + RotateToPosition(GetPosition2(), m_flSpeed); } } else if (state == TRIG_OFF) { - Back(); + RotateToPosition(GetPosition1(), m_flSpeed); } else if (state == TRIG_ON) { - Away(); + RotateToPosition(GetPosition2(), m_flSpeed); } UseTargets(act, TRIG_TOGGLE, m_flDelay); @@ -544,8 +461,9 @@ func_door_rotating::Use(void) void func_door_rotating::Touch(entity eToucher) { - if (m_iCanTouch == false) + if (m_bCanTouch == false) { return; + } if (m_iLocked || !GetMaster()) { if (m_flSoundWait < time) @@ -559,7 +477,7 @@ func_door_rotating::Touch(entity eToucher) return; } - if ((m_iState == STATE_UP) || (m_iState == STATE_DOWN)) { + if ((GetMoverState() == MOVER_1TO2) || (GetMoverState() == MOVER_2TO1)) { return; } @@ -576,48 +494,6 @@ func_door_rotating::Blocked(entity eBlocker) } if (m_flWait >= 0) { - if (m_iState == STATE_DOWN) { - Away(); - } else { - Back(); - } - } -} - -void -func_door_rotating::SetMovementDirection(void) -{ - if (HasSpawnFlags(SF_ROT_ZAXIS)) { - m_vecMoveDir = [0,0,1]; - } else if (HasSpawnFlags(SF_ROT_XAXIS)) { - m_vecMoveDir = [1,0,0]; - } else { - m_vecMoveDir = [0,1,0]; - } -} - -void -func_door_rotating::RotToDest(vector vDestAngle, void(void) func) -{ - vector vecAngleDifference; - float flTravelLength, flTravelTime; - - if (!m_flSpeed) { - NSLog("^1func_door_rotating::^3RotToDest^7: No speed defined for %s!", targetname); - Respawn(); - return; - } - - vecAngleDifference = (vDestAngle - angles); - flTravelLength = vlen(vecAngleDifference); - flTravelTime = (flTravelLength / m_flSpeed); - - /* Avoid NAN hack */ - if (flTravelTime <= 0.0f) { - ScheduleThink(func, 0.0f); - } else { - avelocity = (vecAngleDifference * (1 / flTravelTime)); - m_vecDest = vDestAngle; - ScheduleThink(func, flTravelTime); + RotateToReverse(m_flSpeed); } } diff --git a/src/server/defs.h b/src/server/defs.h index eef1adae..a4ad1dc0 100644 --- a/src/server/defs.h +++ b/src/server/defs.h @@ -83,9 +83,6 @@ WriteEntity(MSG_ENTITY, field);\ } -#define AREAPORTAL_CLOSED 0 -#define AREAPORTAL_OPEN 1 - var bool g_isloading = false; var bool autocvar_mp_flashlight = true; diff --git a/src/shared/NSMoverEntity.h b/src/shared/NSMoverEntity.h new file mode 100644 index 00000000..1d3056c5 --- /dev/null +++ b/src/shared/NSMoverEntity.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2023 Vera Visions LLC. + * + * 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. +*/ + +/** The state the NSMoverEntity is in. */ +typedef enum +{ + MOVER_POS1, /**< At the initial starting position. */ + MOVER_POS2, /**< At the final destination. */ + MOVER_1TO2, /**< On its way to the final destination. */ + MOVER_2TO1 /**< on its way back to the starting position. */ +} moverState_t; + +/** The movement type of the NSMoverEntity. */ +typedef enum +{ + MOVERTYPE_TRANSFORM, /**< Moves in a linear fashion. */ + MOVERTYPE_ROTATE, /**< Rotates in a linear fashion. */ +} moverType_t; + + +#define AREAPORTAL_CLOSED 0 +#define AREAPORTAL_OPEN 1 + +/** NSMoverEntity is responsible for handling movement functions of +mainly brush-based entities that move and push other entities around +the game world. Your sub-class will define the type of movement and +the two positions within the entity will traverse - and then do so +at your request. */ +class +NSMoverEntity:NSSurfacePropEntity +{ +public: + void NSMoverEntity(void); + + /** Returns a directional position from the current one. */ + nonvirtual vector GetDirectionalPosition(vector, float); + /** Returns a directional angle from the current one. */ + nonvirtual vector GetDirectionalRotation(vector, float); + + /** Set the movement state. */ + nonvirtual void SetMoverState(moverState_t); + /** Returns the movement state. */ + nonvirtual moverState_t GetMoverState(void); + + /** Set the movement type. */ + nonvirtual void SetMoverType(moverType_t); + /** Returns the movement type. */ + nonvirtual moverType_t GetMoverType(void); + + /** Sets the initial starting position. */ + nonvirtual void SetPosition1(vector); + /** Returns the starting position. */ + nonvirtual vector GetPosition1(void); + + /** Sets the final destination. */ + nonvirtual void SetPosition2(vector); + /** Returns the final destination. */ + nonvirtual vector GetPosition2(void); + + /** Moves this entity to the specified position. */ + nonvirtual void MoveToPosition(vector, float); + /** Rotates this entity to the desired angle. */ + nonvirtual void RotateToPosition(vector, float); + + /** Moves to the reverse state. If a mover is at pos1, it'll go to pos2, etc. */ + nonvirtual void MoveToReverse(float); + /** Rotates to the reversed state. */ + nonvirtual void RotateToReverse(float); + /** Returns if the NSMoverEntity is currently moving. */ + nonvirtual bool IsMoving(void); + + /** Overridable: Called when the mover starts moving from its position to another. */ + virtual void MoverStartsMoving(void); + /** Overridable: Called when the mover completes its movement to a destination. */ + virtual void MoverFinishesMoving(void); + + /* overrides */ +#ifdef SERVER + virtual void Save(float); + virtual void Restore(string, string); +#endif + +private: + vector m_vecPos1; + vector m_vecPos2; + moverState_t m_moverState; + moverType_t m_moverType; + int m_iPortalState; + + nonvirtual void _PortalOpen(void); + nonvirtual void _PortalClose(void); + nonvirtual void _ArrivedAtPosition1(void); + nonvirtual void _ArrivedAtPosition2(void); + nonvirtual void _RotatedToPosition1(void); + nonvirtual void _RotatedToPosition2(void); + nonvirtual void _BeginMoving(void); +}; \ No newline at end of file diff --git a/src/shared/NSMoverEntity.qc b/src/shared/NSMoverEntity.qc new file mode 100644 index 00000000..67e4fba5 --- /dev/null +++ b/src/shared/NSMoverEntity.qc @@ -0,0 +1,342 @@ +void +NSMoverEntity::NSMoverEntity(void) +{ + m_vecPos1 = g_vec_null; + m_vecPos2 = g_vec_null; + m_moverState = MOVER_POS1; + m_moverType = MOVERTYPE_TRANSFORM; + m_iPortalState = 0i; +} + +#ifdef SERVER +void +NSMoverEntity::Save(float handle) +{ + super::Save(handle); + + SaveVector(handle, "m_vecPos1", m_vecPos1); + SaveVector(handle, "m_vecPos2", m_vecPos2); + SaveFloat(handle, "m_moverState", m_moverState); + SaveFloat(handle, "m_moverType", m_moverType); + SaveInt(handle, "m_iPortalState", m_iPortalState); +} + +void +NSMoverEntity::Restore(string strKey, string strValue) +{ + switch (strKey) { + case "m_vecPos1": + m_vecPos1 = ReadVector(strValue); + break; + case "m_vecPos2": + m_vecPos2 = ReadVector(strValue); + break; + case "m_moverState": + m_moverState = ReadFloat(strValue); + break; + case "m_moverType": + m_moverType = ReadFloat(strValue); + break; + case "m_iPortalState": + m_iPortalState = ReadInt(strValue); + break; + default: + super::Restore(strKey, strValue); + } +} +#endif + +vector +NSMoverEntity::GetDirectionalPosition(vector vecAngle, float flLip) +{ + vector vecMoveDir = g_vec_null; + vector vecPos = g_vec_null; + + /* editor angle */ + if (vecAngle == [0,-1,0]) { + vecMoveDir = [0,0,1]; + } else if (vecAngle == [0,-2,0]) { + vecMoveDir = [0,0,-1]; + } else { + /* manually specified angle */ + makevectors(vecAngle); + vecMoveDir = v_forward; + } + + vecPos = (GetOrigin() + vecMoveDir * (fabs(vecMoveDir * size) - flLip)); + return vecPos; +} + +vector +NSMoverEntity::GetDirectionalRotation(vector normalizedAngle, float travelDistance) +{ + vector vecMoveDir = normalizedAngle; + return (GetAngles() + vecMoveDir * travelDistance); +} + +void +NSMoverEntity::SetMoverState(moverState_t val) +{ + m_moverState = val; +} + +moverState_t +NSMoverEntity::GetMoverState(void) +{ + return m_moverState; +} + +void +NSMoverEntity::SetMoverType(moverType_t val) +{ + m_moverType = val; +} + +moverType_t +NSMoverEntity::GetMoverType(void) +{ + + return m_moverType; +} + +void +NSMoverEntity::SetPosition1(vector val) +{ + m_vecPos1 = val; +} + +vector +NSMoverEntity::GetPosition1(void) +{ + return m_vecPos1; +} + +void +NSMoverEntity::SetPosition2(vector val) +{ + m_vecPos2 = val; +} + +vector +NSMoverEntity::GetPosition2(void) +{ + return m_vecPos2; +} + +void +NSMoverEntity::MoveToPosition(vector vecDest, float flSpeed) +{ + vector vecDifference; + float flTravel; + float fTravelTime; + + /* selects which end method to trigger based on state. */ + static void MoveToPosition_Done(float travelTime) { + if (m_moverState == MOVER_1TO2) { + ScheduleThink(_ArrivedAtPosition2, travelTime); + } else if (m_moverState == MOVER_2TO1) { + ScheduleThink(_ArrivedAtPosition1, travelTime); + } + MoverStartsMoving(); + _PortalOpen(); + } + + /* selects which end positition to set based on state */ + static void MoveToPosition_SetDest(vector vecDest) { + if (m_moverState == MOVER_POS2) { + m_vecPos1 = vecDest; + m_moverState = MOVER_2TO1; + } else { + m_moverState = MOVER_1TO2; + m_vecPos2 = vecDest; + } + } + + /* abort if no speed is defined whatsoever */ + if (!flSpeed) { + objerror("NSMoverEntity::MoveToPosition: No speed defined!"); + return; + } + + /* set the appropriate attribute */ + MoveToPosition_SetDest(vecDest); + + /* if we're already there, don't bother and trigger it right now. */ + if (vecDest == GetOrigin()) { + MoveToPosition_Done(0.0f); + ClearVelocity(); + return; + } + + /* calculate travel distance and time */ + vecDifference = (vecDest - GetOrigin()); + flTravel = vlen(vecDifference); + fTravelTime = (flTravel / flSpeed); + + /* schedule the movement and proceed to trigger the end after a certain time */ + MoveToPosition_Done(fTravelTime); + SetVelocity(vecDifference * (1.0f / fTravelTime)); +} + +void +NSMoverEntity::MoveToReverse(float flSpeed) +{ + if ((GetMoverState() == MOVER_POS2) || (GetMoverState() == MOVER_1TO2)){ + MoveToPosition(GetPosition1(), flSpeed); + } else { + MoveToPosition(GetPosition2(), flSpeed); + } +} + +void +NSMoverEntity::RotateToPosition(vector vDestAngle, float flSpeed) +{ + vector vecAngleDifference; + float flTravelLength, flTravelTime; + + static void RotateToPosition_Done(float travelTime) { + if (m_moverState == MOVER_1TO2) { + ScheduleThink(_RotatedToPosition2, travelTime); + } else if (m_moverState == MOVER_2TO1) { + ScheduleThink(_RotatedToPosition1, travelTime); + } + MoverStartsMoving(); + _PortalOpen(); + } + + static void RotateToPosition_SetDest(vector vecDest) { + if (m_moverState == MOVER_POS2) { + m_vecPos1 = vecDest; + m_moverState = MOVER_2TO1; + } else { + m_moverState = MOVER_1TO2; + m_vecPos2 = vecDest; + } + } + + if (!flSpeed) { + NSLog("NSMoverEntity::RotateToPosition: No speed defined!"); + Respawn(); + return; + } + + RotateToPosition_SetDest(vDestAngle); + vecAngleDifference = (vDestAngle - angles); + flTravelLength = vlen(vecAngleDifference); + flTravelTime = (flTravelLength / flSpeed); + + /* Avoid NAN hack */ + if (flTravelTime <= 0.0f) { + if (m_moverState == MOVER_1TO2) { + _RotatedToPosition2(); + } else if (m_moverState == MOVER_2TO1) { + _RotatedToPosition1(); + } + } else { + SetAngularVelocity((vecAngleDifference * (1 / flTravelTime))); + RotateToPosition_Done(flTravelTime); + } +} + +void +NSMoverEntity::RotateToReverse(float flSpeed) +{ + if ((GetMoverState() == MOVER_POS2) || (GetMoverState() == MOVER_1TO2)){ + RotateToPosition(GetPosition1(), flSpeed); + } else { + RotateToPosition(GetPosition2(), flSpeed); + } +} + +bool +NSMoverEntity::IsMoving(void) +{ + switch (GetMoverState()) { + case MOVER_POS1: + case MOVER_POS2: + return false; + break; + default: + return true; + } +} + +void +NSMoverEntity::_PortalOpen(void) +{ + if (m_iPortalState == 1) + return; + + m_iPortalState = 1; + setorigin(this, origin); + openportal(this, AREAPORTAL_OPEN); +} + +void +NSMoverEntity::_PortalClose(void) +{ + if (m_iPortalState == 0) + return; + + m_iPortalState = 0; + setorigin(this, origin); + openportal(this, AREAPORTAL_CLOSED); +} + +void +NSMoverEntity::_ArrivedAtPosition1(void) +{ + SetOrigin(m_vecPos1); + ClearVelocity(); + ReleaseThink(); + m_moverState = MOVER_POS1; + _PortalClose(); + MoverFinishesMoving(); +} + +void +NSMoverEntity::_ArrivedAtPosition2(void) +{ + SetOrigin(m_vecPos2); + ClearVelocity(); + ReleaseThink(); + m_moverState = MOVER_POS2; + MoverFinishesMoving(); +} + +void +NSMoverEntity::_RotatedToPosition1(void) +{ + SetAngles(m_vecPos1); + ClearVelocity(); + ReleaseThink(); + m_moverState = MOVER_POS1; + _PortalClose(); + MoverFinishesMoving(); +} + +void +NSMoverEntity::_RotatedToPosition2(void) +{ + SetAngles(m_vecPos2); + ClearVelocity(); + ReleaseThink(); + m_moverState = MOVER_POS2; + MoverFinishesMoving(); +} + +void +NSMoverEntity::_BeginMoving(void) +{ + +} + +void +NSMoverEntity::MoverStartsMoving(void) +{ +} + +void +NSMoverEntity::MoverFinishesMoving(void) +{ +} \ No newline at end of file diff --git a/src/shared/defs.h b/src/shared/defs.h index bb560f44..bfda0250 100644 --- a/src/shared/defs.h +++ b/src/shared/defs.h @@ -52,6 +52,7 @@ string __fullspawndata; #include "NSTimer.h" #include "NSRenderableEntity.h" #include "NSSurfacePropEntity.h" +#include "NSMoverEntity.h" #include "NSPhysicsEntity.h" #include "NSBrushTrigger.h" #include "NSPointTrigger.h" diff --git a/src/shared/include.src b/src/shared/include.src index c6647550..a1cd2286 100644 --- a/src/shared/include.src +++ b/src/shared/include.src @@ -6,6 +6,7 @@ NSEntity.qc NSTimer.qc NSRenderableEntity.qc NSSurfacePropEntity.qc +NSMoverEntity.qc NSPhysicsEntity.qc NSBrushTrigger.qc NSPointTrigger.qc