
Quake
Devels - Rotation Locking Code
Source Author: WolfWings ShadowFlight
Tutorial Author: Cryect
Difficulty: Easy
This is a great little tutorial. Do you remember in quake 1 there was the remote control tag bombs that stick to guys till it blows up. Well this tutorial lets you do that and more. Lets say you see a turning gear shoot it and you will see the shot move with it if you use this code. I even have used this in fact I thank WolfWings ShadowFlight for saving me all this time I would have spent doing this. If you wish to check out how I used the code go see ST Weapon Factory. Unfortunately we have not released the code since currently we are in beta but soon I will go over a tutorial on a sentry gun I think. Well here is the code.
/*
=================
stuck_prethink
This is a series of support
routines for locking an object against another,
I.E. Proximity mines,
Arrows, C4, etc, etc...
The other object can
rotate and move at will, the 'stuck to' object won't
budge from the spot it
hit, period.
stick(edict_t *projectile,
edict_t *object)
Here's the entry point to
this function.
Projectile is, I.E. the
arrow.
Object is, I.E. the wall,
or tank, or icarus, or makron, etc, etc...
Stick will set up all the
required stuff properly,
including movetype, solid,
etc, etc.
To use, simply call the
stick(projectile, object) function.
projectile is then 'glued'
to object, unless object is the world,
in which case it is simply
held in place. :-)
=================
*/
void VectorRotate(vec3_t
in, vec3_t angles, vec3_t out) {
float cv, sv,
angle, tv;
VectorCopy(in, out);
angle = (-angles[PITCH]) * M_PI / 180;
cv = cos(angle);
sv = sin(angle);
tv = (out[0] * cv) - (out[2] * sv);
out[2] = (out[2] * cv) + (out[0] * sv);
out[0] = tv;
angle = (angles[YAW]) * M_PI / 180;
cv = cos(angle);
sv = sin(angle);
tv = (out[0] * cv) - (out[1] * sv);
out[1] = (out[1] * cv) + (out[0] * sv);
out[0] = tv;
angle = (angles[ROLL]) * M_PI / 180;
cv = cos(angle);
sv = sin(angle);
tv = (out[1] * cv) - (out[2] * sv);
out[2] = (out[2] * cv) + (out[1] * sv);
out[1] = tv;
}
void VectorUnrotate(vec3_t
in, vec3_t angles, vec3_t out) {
float cv, sv,
angle, tv;
VectorCopy(in, out);
angle = (-angles[ROLL]) * M_PI / 180;
cv = cos(angle);
sv = sin(angle);
tv = (out[1] * cv) - (out[2] * sv);
out[2] = (out[2] * cv) + (out[1] * sv);
out[1] = tv;
angle = (-angles[YAW]) * M_PI / 180;
cv = cos(angle);
sv = sin(angle);
tv = (out[0] * cv) - (out[1] * sv);
out[1] = (out[1] * cv) + (out[0] * sv);
out[0] = tv;
angle = (angles[PITCH]) * M_PI / 180;
cv = cos(angle);
sv = sin(angle);
tv = (out[0] * cv) - (out[2] * sv);
out[2] = (out[2] * cv) + (out[0] * sv);
out[0] = tv;
}
void stuck_prethink
(edict_t *self)
{
vec3_t temp, new;
vec_t tv, xv, yv,
zv;
float angle, cv,
sv;
edict_t *other;
other = self->goalentity;
if (!other->inuse) {
}
VectorRotate(self->pos1, other->s.angles, temp);
VectorRotate(self->pos2, other->s.angles, new);
VectorAdd(other->s.origin, temp, self->s.origin);
VectorSubtract(new, temp, new);
vectoangles(new, self->s.angles);
}
void
Calc_StuckOffset(edict_t *self, edict_t *other) {
float cv, sv;
float angle;
vec_t tv, xv, yv,
zv;
vec3_t forward;
VectorSubtract(self->s.origin, other->s.origin,
forward);
VectorUnrotate(forward, other->s.angles,
self->pos1);
AngleVectors(self->s.angles, forward, NULL, NULL);
VectorMA(self->s.origin, 64, forward, forward);
VectorSubtract(forward, other->s.origin, forward);
VectorUnrotate(forward, other->s.angles, self->pos2);
}
void stick(edict_t
*projectile, edict_t *object) {
projectile->solid = SOLID_NOT;
projectile->movetype = MOVETYPE_FLY;
VectorClear(projectile->velocity);
VectorClear(projectile->avelocity);
if (object != g_edicts) {
Calc_StuckOffset(projectile, object);
projectile->goalentity = object;
projectile->prethink = stuck_prethink;
} else
projectile->prethink = NULL;
}
/*
=================
dart_prethink
This is a support routine
for keeping an
object velocity-aligned,
for I.E. arrows.
=================
*/
void dart_prethink
(edict_t *ent) {
vec3_t move;
vectoangles(ent->velocity, move);
VectorSubtract(move, ent->s.angles, move);
move[0] = fmod((move[0] + 180), 360) - 180;
move[1] = fmod((move[1] + 180), 360) - 180;
move[2] = fmod((move[2] + 180), 360) - 180;
VectorScale(move, 1/FRAMETIME, ent->avelocity);
}
/*
=================
fire_arrow
=================
*/
void arrow_touch (edict_t
*ent, edict_t *other, cplane_t *plane, csurface_t *surf)
{
vec3_t origin;
int n;
if (other == ent->owner) // FIXME: Let arrow hit
player, but not when they've just fired it
return;
if (surf && (surf->flags & SURF_SKY))
{
G_FreeEdict (ent);
return;
}
if (ent->owner->client)
PlayerNoise(ent->owner, ent->s.origin,
PNOISE_IMPACT);
if (other->takedamage)
T_Damage (other, ent, ent->owner,
ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0,
MOD_UNKNOWN);
ent->s.sound = 0;
ent->think = G_FreeEdict;
ent->nextthink = level.time + (FRAMETIME * 100);
stick(ent, other);
}
void fire_arrow (edict_t
*self, vec3_t start, vec3_t aimdir, int damage, int speed)
{
edict_t *arrow;
vec3_t forward,
right, up, dir;
vectoangles (aimdir, dir);
AngleVectors (dir, forward, right, up);
arrow = G_Spawn();
VectorScale (aimdir, speed, arrow->velocity);
VectorMA (arrow->velocity, 100 + crandom() * 10.0, up,
arrow->velocity);
VectorMA (arrow->velocity, crandom() * 10.0, right,
arrow->velocity);
VectorCopy (start, arrow->s.origin);
vectoangles (dir, arrow->s.angles);
arrow->prethink = dart_prethink; // Keeps the arrow
aligned, so it arcs through the air nicely.
arrow->movetype = MOVETYPE_TOSS;
arrow->gravity = 0.5;
arrow->clipmask = MASK_SHOT;
arrow->solid = SOLID_BBOX;
VectorClear (arrow->mins);
VectorClear (arrow->maxs);
arrow->s.modelindex = gi.modelindex
("models/objects/rocket/tris.md2"); // The Chaos DM arrow works
great, BTW.
arrow->owner = self;
arrow->touch = arrow_touch;
arrow->nextthink = level.time + 30;
arrow->think = G_FreeEdict;
arrow->dmg = damage;
arrow->s.sound = gi.soundindex
("misc/lasfly.wav");
arrow->classname = "arrow";
if (self->client)
check_dodge (self, arrow->s.origin, dir,
speed);
gi.linkentity (arrow);
}
Alright there is some
nifty extras in there even such as the dart prethink which is great also. Okay
so just basicly use the stuck function to stick the object on. That was simple
and give credit to WolfWings
ShadowFlight.
Tutorial by Cryect
|
This site, and all content and
graphics displayed on it, |