mirror of
https://github.com/id-Software/quake-rerelease-qc.git
synced 2024-11-25 05:31:13 +00:00
199 lines
5.1 KiB
C++
199 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
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
|