nuclide/Source/gs-entbase/server/func_door.cpp

361 lines
6.7 KiB
C++
Raw Normal View History

/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
// TODO: Finish these
#define SF_MOV_OPEN 1
#define SF_MOV_UNLINK 4
#define SF_MOV_PASSABLE 8
#define SF_MOV_TOGGLE 32
#define SF_MOV_USE 256
enum
{
STATE_RAISED = 0,
STATE_LOWERED,
STATE_UP,
STATE_DOWN
};
class func_door : CBaseTrigger
{
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;
int m_iMoveSnd;
int m_iStopSnd;
int m_iDamage;
int m_iLocked;
void() func_door;
virtual void() SetMovementDirection;
virtual void(vector vdest, void() func) MoveToDestination;
virtual void() MoveToDestination_End;
virtual void() MoveAway;
virtual void() MoveBack;
virtual void() Precache;
virtual void() Arrived;
virtual void() Returned;
virtual void() Trigger;
virtual void() Blocked;
virtual void() Touch;
virtual void() PlayerUse;
virtual void() m_pMove = 0;
};
void func_door :: Precache (void)
{
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 :: PlayerUse (void)
{
eActivator.gflags &= ~GF_USE_RELEASED;
Trigger();
}
void func_door :: Arrived (void)
{
m_iState = STATE_RAISED;
if(m_iStopSnd > 0 && m_iStopSnd <= 8) {
sound(self, CHAN_VOICE, sprintf("doors/doorstop%i.wav", m_iStopSnd), 1.0, ATTN_NORM);
} else {
sound(self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM);
}
if (!(spawnflags & SF_MOV_USE)) {
touch = Touch;
}
if (m_flWait < 0) {
return;
}
if (!(spawnflags & SF_MOV_TOGGLE)) {
think = MoveBack;
nextthink = (ltime + m_flWait);
}
}
void func_door :: Returned (void)
{
if(m_iStopSnd > 0 && m_iStopSnd <= 8) {
sound(self, CHAN_VOICE, sprintf("doors/doorstop%i.wav", m_iStopSnd), 1.0, ATTN_NORM);
} else {
sound(self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM);
}
if (!(spawnflags & SF_MOV_USE)) {
touch = Touch;
}
m_iState = STATE_LOWERED;
}
void func_door :: MoveBack (void)
{
if(m_iMoveSnd > 0 && m_iMoveSnd <= 10) {
sound(self, CHAN_VOICE, sprintf("doors/doormove%i.wav", m_iMoveSnd), 1.0, ATTN_NORM);
} else {
sound(self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM);
}
if (!(spawnflags & SF_MOV_USE)) {
touch = __NULL__;
}
m_iState = STATE_DOWN;
MoveToDestination(m_vecPos1, Returned);
}
void func_door :: MoveAway (void)
{
if (m_iState == STATE_UP) {
return;
}
if(m_iMoveSnd > 0 && m_iMoveSnd <= 10) {
sound(self, CHAN_VOICE, sprintf("doors/doormove%i.wav", m_iMoveSnd), 1.0, ATTN_NORM);
} else {
sound(self, CHAN_VOICE, "common/null.wav", 1.0, ATTN_NORM);
}
if (!(spawnflags & SF_MOV_TOGGLE)) {
if (m_iState == STATE_RAISED) {
nextthink = (ltime + m_flWait);
return;
}
}
m_iState = STATE_UP;
MoveToDestination(m_vecPos2, Arrived);
}
void func_door :: Trigger (void)
{
if (m_flNextTrigger > ltime) {
if (!(spawnflags & SF_MOV_TOGGLE)) {
return;
}
}
m_flNextTrigger = ltime + m_flWait;
// Only trigger stuff when we are done moving
if ((m_iState == STATE_RAISED) || (m_iState == STATE_LOWERED)) {
if (m_flDelay > 0) {
#ifdef GS_DEVELOPER
print(sprintf("func_door: Delayed trigger of `%s`\n", m_strTarget));
#endif
CBaseTrigger::UseTargets_Delay(m_flDelay);
} else {
#ifdef GS_DEVELOPER
dprint(sprintf("func_door: Normal trigger of `%s`\n", m_strTarget));
#endif
CBaseTrigger::UseTargets();
}
}
if ((m_iState == STATE_UP) || (m_iState == STATE_RAISED)){
MoveBack();
return;
}
MoveAway();
}
void func_door :: Touch (void)
{
if (spawnflags & SF_MOV_TOGGLE) {
return;
}
if (m_iLocked) {
return;
}
if (other.movetype == MOVETYPE_WALK) {
if (other.absmin[2] <= maxs[2] - 2) {
Trigger();
}
}
}
void func_door :: Blocked (void)
{
if(m_iDamage) {
//Damage_Apply(other, self, dmg, other.origin, FALSE);
}
if (m_flWait >= 0) {
if (m_iState == STATE_DOWN) {
MoveAway ();
} else {
MoveBack ();
}
}
}
void func_door :: Respawn (void)
{
solid = SOLID_BSP;
movetype = MOVETYPE_PUSH;
setorigin(this, origin);
setmodel(this, model);
blocked = Blocked;
//Use = Trigger;
if (m_flWait == -1) {
spawnflags |= SF_MOV_TOGGLE;
}
if (!m_flSpeed) {
m_flSpeed = 100;
}
if (!m_iDamage) {
m_iDamage = 2;
}
if (spawnflags & SF_MOV_USE) {
touch = __NULL__;
gflags |= GF_USABLE;
} else {
touch = Touch;
gflags -= gflags & GF_USABLE;
}
m_iState = STATE_LOWERED;
m_vecPos1 = origin;
m_vecPos2 = (m_vecPos1 + m_vecMoveDir * (fabs(m_vecMoveDir * size) - m_flLip));
if (spawnflags & SF_MOV_OPEN) {
setorigin(this, m_vecPos2);
m_vecPos2 = m_vecPos1;
m_vecPos1 = origin;
}
}
void func_door :: SetMovementDirection (void)
{
if (angles == [0,-1,0]) {
m_vecMoveDir = [0,0,1];
} else if (angles == [0,-2,0]) {
m_vecMoveDir = [0,0,-1];
} else {
makevectors(angles);
m_vecMoveDir = v_forward;
}
angles = [0,0,0];
}
void func_door :: MoveToDestination_End (void)
{
setorigin(this, m_vecDest);
velocity = [0,0,0];
nextthink = -1;
m_pMove();
}
void func_door :: MoveToDestination (vector vDestination, void() func)
{
vector vecDifference;
float flTravel;
float 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_door :: func_door (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 "delay":
m_flDelay = stof(argv(i + 1));
break;
case "wait":
m_flWait = stof(argv(i + 1));
break;
default:
break;
}
}
func_door::Precache();
func_door::SetMovementDirection();
func_door::Respawn();
CBaseTrigger::CBaseTrigger();
if (m_strTargetName) {
m_iLocked = TRUE;
}
}
void func_water(void)
{
spawnfunc_func_door();
self.classname = "func_water";
self.solid = SOLID_BSP;
self.skin = CONTENT_WATER;
}