quake-rerelease-qc/quakec_mg1/rotate.qc
2022-04-06 14:43:08 -05:00

198 lines
5.1 KiB
C++

/* Copyright (C) 1996-2022 id Software LLC
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
See file, 'COPYING', for details.
*/
/*
===============================================================================
Bmodel rotation
===============================================================================
*/
vector ModAngles(vector a)
{
while(a_x > 360) a_x -= 360;
while(a_x < 0) a_x += 360;
while(a_y > 360) a_y -= 360;
while(a_y < 0) a_y += 360;
while(a_z > 360) a_z -= 360;
while(a_x < 0) a_z += 360;
return a;
}
float Clamp(float v, float min, float max)
{
if(v < min) return min;
if(v > max) return max;
return v;
}
/*QUAKED info_rotate (0.4 1.0 0.6) (-8 -8 -8) (8 8 8)
Used to indicate center of rotation.
*/
void info_rotate_axis()
{
remove(self);
}
/*
===============================================================================
Continuous rotation
self.state = state: either off, on, accel up, or deccel down.
self.avelocity = rotation degrees per second
self.speed = current fraction of angluar velocity
self.distance = change in self.speed per second, negative if decelerating
self.delay = editor field for how long the acceleration should take
===============================================================================
*/
enum : int
{
RotateStateOff,
RotateStateAccelUp,
RotateStateOn,
RotateStateDecelDown
};
void rotate_object_continuously_tick(float DeltaTime)
{
self.angles = ModAngles(self.angles + self.avelocity * DeltaTime);
}
void rotate_object_tween_tick(float DeltaTime)
{
self.speed += self.distance * DeltaTime;
self.speed = Clamp(self.speed, 0, 1);
if(self.speed == 0)
{
self.state = RotateStateOff;
RemoveFrameTickEntity(self);
return;
}
if(self.speed == 1)
{
self.state = RotateStateOn;
self.tick = rotate_object_continuously_tick;
self.tick(DeltaTime);
return;
}
self.angles = ModAngles(self.angles + self.avelocity * DeltaTime * self.speed);
}
void rotate_object_continuously_use()
{
if(self.delay <= 0)
{
//No acceleration, just toggle on or off
if(self.state == RotateStateOff)
{
self.state = RotateStateOn;
RegisterFrameTickEntity(self);
}
else
{
self.state = RotateStateOff;
RemoveFrameTickEntity(self);
}
return;
}
switch(self.state)
{
case RotateStateOff:
self.state = RotateStateAccelUp;
self.tick = rotate_object_tween_tick;
self.distance = fabs(self.distance);
RegisterFrameTickEntity(self);
return;
case RotateStateAccelUp:
self.state = RotateStateDecelDown;
self.tick = rotate_object_tween_tick;
self.distance = -fabs(self.distance);
return;
case RotateStateOn:
self.state = RotateStateDecelDown;
self.tick = rotate_object_tween_tick;
self.distance = -fabs(self.distance);
return;
case RotateStateDecelDown:
self.state = RotateStateAccelUp;
self.tick = rotate_object_tween_tick;
self.distance = fabs(self.distance);
return;
}
}
/*QUAKED rotate_object_continuously (0.4 1.0 0.6) (? ? ?) (? ? ?) START_OFF
Non-solid object that rotates continuously.
Trigger to turn on and off.
*/
void rotate_object_continuously()
{
if(!self.avelocity)
{
self.avelocity = '0 30 0';
}
if(self.delay > 0)
{
self.distance = 1 / self.delay;
}
if(self.spawnflags & SOLID_BSP)
{
self.movetype = MOVETYPE_PUSH;
self.solid = SOLID_BSP;
}
else
{
self.movetype = MOVETYPE_NONE;
self.solid = SOLID_NOT;
}
self.angles = '0 0 0';
if(self.pos2)
{
self.origin = self.pos2;
setorigin(self, self.origin);
}
setmodel(self, self.model);
self.use = rotate_object_continuously_use;
self.tick = rotate_object_continuously_tick;
if(self.spawnflags & START_OFF)
{
self.state = RotateStateOff;
}
else
{
self.state = RotateStateOn;
self.speed = 1;
RegisterFrameTickEntity(self);
}
}
/*
===============================================================================
Accel/decel rotation
===============================================================================
*/