nuclide/src/shared/NSMoverEntity.qc

382 lines
7.8 KiB
Plaintext

/*
* Copyright (c) 2023-2024 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.
*/
void
NSMoverEntity::NSMoverEntity(void)
{
m_vecPos1 = g_vec_null;
m_vecPos2 = g_vec_null;
m_vecPos3 = g_vec_null;
m_vecPos4 = g_vec_null;
m_moverState = MOVER_POS1;
m_moverType = MOVERTYPE_LINEAR;
m_iPortalState = 0i;
m_bUseMoveDir = false;
}
#ifdef SERVER
void
NSMoverEntity::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "movedir":
m_vecMoveDir = ReadVector(strValue);
m_bUseMoveDir = true;
break;
default:
super::SpawnKey(strKey, strValue);
}
}
void
NSMoverEntity::Save(float handle)
{
super::Save(handle);
SaveVector(handle, "m_vecPos1", m_vecPos1);
SaveVector(handle, "m_vecPos2", m_vecPos2);
SaveVector(handle, "m_vecPos3", m_vecPos3);
SaveVector(handle, "m_vecPos4", m_vecPos4);
SaveFloat(handle, "m_moverState", m_moverState);
SaveFloat(handle, "m_moverType", m_moverType);
SaveInt(handle, "m_iPortalState", m_iPortalState);
SaveVector(handle, "m_vecMoveDir", m_vecMoveDir);
SaveBool(handle, "m_bUseMoveDir", m_bUseMoveDir);
}
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_vecPos3":
m_vecPos3 = ReadVector(strValue);
break;
case "m_vecPos4":
m_vecPos4 = 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;
case "m_vecMoveDir":
m_vecMoveDir = ReadVector(strValue);
break;
case "m_bUseMoveDir":
m_bUseMoveDir = ReadBool(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;
if (m_bUseMoveDir == true) {
makevectors(m_vecMoveDir);
vecMoveDir = v_forward;
} else {
/* 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::SetMoverPosition1(vector val)
{
m_vecPos1 = val;
}
vector
NSMoverEntity::GetMoverPosition1(void)
{
return m_vecPos1;
}
void
NSMoverEntity::SetMoverPosition2(vector val)
{
m_vecPos2 = val;
}
vector
NSMoverEntity::GetMoverPosition2(void)
{
return m_vecPos2;
}
void
NSMoverEntity::SetMoverRotation1(vector val)
{
m_vecPos3 = val;
}
vector
NSMoverEntity::GetMoverRotation1(void)
{
return m_vecPos3;
}
void
NSMoverEntity::SetMoverRotation2(vector val)
{
m_vecPos4 = val;
}
vector
NSMoverEntity::GetMoverRotation2(void)
{
return m_vecPos4;
}
void
NSMoverEntity::MoveToPosition(vector vecDest, float flSpeed)
{
MoveAndRotateToPosition(vecDest, GetAngles(), flSpeed);
}
void
NSMoverEntity::MoveAndRotateToPosition(vector vecDest, vector vecAngle, float flSpeed)
{
vector vecDifference;
vector vecAngleDifference;
float flTravel;
float fTravelTime;
/* selects which end method to trigger based on state. */
static void MoveToRotPosition_Done(float travelTime) {
if (m_moverState == MOVER_1TO2) {
ScheduleThink(_ArrivedAtRotPosition2, travelTime);
} else if (m_moverState == MOVER_2TO1) {
ScheduleThink(_ArrivedAtRotPosition1, travelTime);
}
MoverStartsMoving();
_PortalOpen();
}
/* selects which end positition to set based on state */
static void MoveToRotPosition_SetDest(vector vecDest, vector vecAngle) {
if (m_moverState == MOVER_POS2) {
m_vecPos1 = vecDest;
m_vecPos3 = vecAngle;
m_moverState = MOVER_2TO1;
} else {
m_moverState = MOVER_1TO2;
m_vecPos2 = vecDest;
m_vecPos4 = vecAngle;
}
}
/* abort if no speed is defined whatsoever */
if (!flSpeed) {
EntWarning("NSMoverEntity::MoveToPosition: No speed defined!");
return;
}
/* set the appropriate attribute */
MoveToRotPosition_SetDest(vecDest, vecAngle);
/* calculate travel distance and time */
vecDifference = (vecDest - GetOrigin());
vecAngleDifference = (vecAngle - GetAngles());
flTravel = vlen(vecDifference);
fTravelTime = (flTravel / flSpeed);
/* if we won't move far enough, we may rotate? */
if (!flTravel) {
flTravel = vlen(vecAngleDifference);
fTravelTime = (flTravel / flSpeed);
}
/* if we're already there, don't bother and trigger it right now. */
if (fTravelTime <= 0.0) {
if (m_moverState == MOVER_1TO2) {
MoverStartsMoving();
_ArrivedAtRotPosition2();
MoverFinishesMoving();
} else if (m_moverState == MOVER_2TO1) {
MoverStartsMoving();
_ArrivedAtRotPosition1();
MoverFinishesMoving();
}
return;
}
/* schedule the movement and proceed to trigger the end after a certain time */
SetVelocity(vecDifference * (1.0f / fTravelTime));
SetAngularVelocity((vecAngleDifference * (1.0 / fTravelTime)));
MoveToRotPosition_Done(fTravelTime);
}
void
NSMoverEntity::MoveToReverse(float flSpeed)
{
if ((GetMoverState() == MOVER_POS2) || (GetMoverState() == MOVER_1TO2)){
MoveToPosition(GetMoverPosition1(), flSpeed);
} else {
MoveToPosition(GetMoverPosition2(), flSpeed);
}
}
void
NSMoverEntity::RotateToPosition(vector vecAngle, float flSpeed)
{
MoveAndRotateToPosition(GetOrigin(), vecAngle, flSpeed);
}
void
NSMoverEntity::RotateToReverse(float flSpeed)
{
if ((GetMoverState() == MOVER_POS2) || (GetMoverState() == MOVER_1TO2)){
RotateToPosition(GetMoverRotation1(), flSpeed);
} else {
RotateToPosition(GetMoverRotation2(), 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::_ArrivedAtRotPosition1(void)
{
SetOrigin(m_vecPos1);
SetAngles(m_vecPos3);
ClearVelocity();
ReleaseThink();
m_moverState = MOVER_POS1;
_PortalClose();
MoverFinishesMoving();
}
void
NSMoverEntity::_ArrivedAtRotPosition2(void)
{
SetOrigin(m_vecPos2);
SetAngles(m_vecPos4);
ClearVelocity();
ReleaseThink();
m_moverState = MOVER_POS2;
MoverFinishesMoving();
}
void
NSMoverEntity::_BeginMoving(void)
{
}
void
NSMoverEntity::MoverStartsMoving(void)
{
}
void
NSMoverEntity::MoverFinishesMoving(void)
{
}