thirtyflightsofloving/tfol/g_abel_camshoot.c

430 lines
No EOL
8.2 KiB
C

#include "g_local.h"
// =================== TARGET_CAMSHOOT
#define CAMBULLET_SPEED 512
void FireTarget2(edict_t *ent)
{
edict_t *t;
if (ent->target2)
{
t = NULL;
while ((t = G_Find (t, FOFS(targetname), ent->target2)))
{
// doors fire area portals in a specific way
if (!Q_stricmp(t->classname, "func_areaportal") &&
(!Q_stricmp(ent->classname, "func_door") || !Q_stricmp(ent->classname, "func_door_rotating")
/*DWH*/ || !Q_stricmp(ent->classname,"func_door_rot_dh")))
continue;
if (t == ent)
{
gi.dprintf ("WARNING: Entity used itself.\n");
}
else
{
if (t->use)
t->use (t, ent, ent);
}
if (!ent->inuse)
{
gi.dprintf("entity was removed while using targets\n");
return;
}
}
}
}
void FirePathTarget(edict_t *ent)
{
edict_t *t;
if (ent->pathtarget)
{
t = NULL;
while ((t = G_Find (t, FOFS(targetname), ent->pathtarget)))
{
// doors fire area portals in a specific way
if (!Q_stricmp(t->classname, "func_areaportal") &&
(!Q_stricmp(ent->classname, "func_door") || !Q_stricmp(ent->classname, "func_door_rotating")
/*DWH*/ || !Q_stricmp(ent->classname,"func_door_rot_dh")))
continue;
if (t == ent)
{
gi.dprintf ("WARNING: Entity used itself.\n");
}
else
{
if (t->use)
{
t->use (t, ent, ent);
}
}
if (!ent->inuse)
{
gi.dprintf("entity was removed while using targets\n");
return;
}
}
}
}
//this is the physical bullet model.
edict_t *CreateCamBullet(edict_t *self, edict_t *ent)
{
edict_t *player;
edict_t *gib;
vec3_t forward, up, right, v, randAng;
player = &g_edicts[1]; // Gotta be, since this is SP only
gib = G_Spawn();
gi.setmodel (gib, "models/objects/bullet/tris.md2");
gib->solid = SOLID_NOT;
VectorCopy(self->s.origin, gib->s.origin);
//gib->s.origin[2] += 24;
gib->movetype = MOVETYPE_FLY;
if (ent->message)
{
edict_t *steerEnt;
steerEnt = G_Find(NULL,FOFS(targetname), ent->message);
if (steerEnt)
{
vec3_t angToSteerEnt;
VectorSubtract (steerEnt->s.origin, gib->s.origin, angToSteerEnt);
vectoangles(angToSteerEnt,angToSteerEnt);
VectorCopy(angToSteerEnt, gib->s.angles);
}
}
else
{
VectorCopy(player->client->ps.viewangles, gib->s.angles);
}
if (gib->s.angles[PITCH] > 0)
gib->s.angles[PITCH] = 0;
gib->s.angles[ROLL] = crandom() * 180;
gib->avelocity[ROLL] = -512;
AngleVectors(gib->s.angles, forward, NULL, up);
VectorMA(gib->s.origin, -44.5, forward, gib->s.origin);
VectorMA(gib->s.origin, 1.8, up, gib->s.origin);
VectorScale (forward, CAMBULLET_SPEED, gib->velocity);
gib->s.renderfx |= RF_MINLIGHT;
gi.linkentity (gib);
return gib;
}
float Lerp2(float value1, float value2, float amount)
{
float delta = value2 - value1;
return value1 + amount * delta;
}
void DeactivateCam(edict_t *self)
{
edict_t *player;
player = &g_edicts[1]; // Gotta be, since this is SP only
camera_off(player);
}
void WarpToNextPoint(edict_t *self, edict_t *nextTarget);
void trackcam_think(edict_t *self)
{
vec3_t finalPos;
finalPos[0] = Lerp2(self->pos1[0], self->pos2[0], self->moveinfo.remaining_distance);
finalPos[1] = Lerp2(self->pos1[1], self->pos2[1], self->moveinfo.remaining_distance);
finalPos[2] = Lerp2(self->pos1[2], self->pos2[2], self->moveinfo.remaining_distance);
VectorCopy(finalPos, self->s.origin);
self->moveinfo.remaining_distance += self->moveinfo.accel;
if (self->moveinfo.remaining_distance >= 1)
{
if (!self->target_ent->target2)
{
//fire any target2
if (self->target_ent->target)
{
edict_t *aimpoint;
aimpoint = G_Find(NULL,FOFS(targetname), self->target_ent->target);
if (aimpoint)
{
FireTarget2(aimpoint);
}
}
DeactivateCam(self);
return;
}
else
{
edict_t *nextTarget;
nextTarget = G_Find(NULL,FOFS(targetname), self->target_ent->target2);
if (nextTarget)
{
FirePathTarget(nextTarget);
WarpToNextPoint(self, nextTarget);
}
else
{
DeactivateCam(self);
return;
}
}
return;
}
self->think = trackcam_think;
self->nextthink = level.time + FRAMETIME;
}
void WarpToNextPoint(edict_t *self, edict_t *nextTarget)
{
self->target_ent = nextTarget;
self->s.event = EV_OTHER_TELEPORT;
VectorClear(self->avelocity);
VectorClear(self->velocity);
VectorCopy(nextTarget->s.origin, self->s.old_origin);
VectorCopy(nextTarget->s.origin, self->s.origin);
VectorCopy(nextTarget->s.angles, self->s.angles);
self->touch = NULL;
if (nextTarget->move_angles)
{
self->avelocity[0] = nextTarget->move_angles[0];
self->avelocity[1] = nextTarget->move_angles[1];
self->avelocity[2] = nextTarget->move_angles[2];
}
if (!nextTarget->speed)
self->speed = 16;
else
self->speed = nextTarget->speed;
if (nextTarget->target)
{
edict_t *aimTarget;
vec3_t v;
aimTarget = G_Find(NULL,FOFS(targetname), nextTarget->target);
if (!aimTarget)
return;
VectorSubtract (nextTarget->s.origin, aimTarget->s.origin, v);
self->moveinfo.distance = VectorLength(v);
//this is the 0-1 transition.
self->moveinfo.remaining_distance = 0;
//this is the step to increase each frame.
self->moveinfo.accel = self->speed / self->moveinfo.distance;
VectorCopy(nextTarget->s.origin, self->pos1 );
VectorCopy(aimTarget->s.origin, self->pos2 );
trackcam_think(self);
}
else
{
DeactivateCam(self);
}
}
void camTrack_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{
edict_t *player;
edict_t *nextTarget;
if (!plane)
return;
player = &g_edicts[1]; // Gotta be, since this is SP only
//delete bullet model.
G_FreeEdict(self->child);
//hit wall.
//if no next target, then abort.
if (!self->owner->target)
{
camera_off(player);
//fire targets.
FireTarget2(self->owner);
return;
}
//fire targets.
FireTarget2(self->owner);
nextTarget = G_Find(NULL,FOFS(targetname), self->owner->target);
if (!nextTarget)
{
camera_off(player);
return;
}
FirePathTarget(nextTarget);
WarpToNextPoint(self, nextTarget);
}
edict_t *camTrack(edict_t *self)
{
edict_t *player;
edict_t *gib;
vec3_t forward, right, v, randAng;
player = &g_edicts[1]; // Gotta be, since this is SP only
gib = G_Spawn();
gib->touch = camTrack_touch;
//gi.setmodel (gib, self->usermodel);
gib->solid = SOLID_TRIGGER;
VectorCopy(player->s.origin, gib->s.origin);
gib->s.origin[2] += 24;
gib->movetype = MOVETYPE_FLY;
if (self->message)
{
edict_t *steerEnt;
steerEnt = G_Find(NULL,FOFS(targetname), self->message);
if (steerEnt)
{
vec3_t angToSteerEnt;
VectorSubtract (steerEnt->s.origin, gib->s.origin, angToSteerEnt);
vectoangles(angToSteerEnt,angToSteerEnt);
VectorCopy(angToSteerEnt, gib->s.angles);
}
}
else
{
VectorCopy(player->client->ps.viewangles, gib->s.angles);
}
if (gib->s.angles[PITCH] > 0)
gib->s.angles[PITCH] = 0;
gib->avelocity[ROLL] = 20; //camera roll.
AngleVectors(gib->s.angles, forward, NULL, NULL);
VectorScale (forward, CAMBULLET_SPEED, gib->velocity);
gi.linkentity (gib);
return gib;
}
void use_camshoot(edict_t *self, edict_t *other, edict_t *activator)
{
edict_t *player;
edict_t *target;
player = &g_edicts[1]; // Gotta be, since this is SP only
if(!player->client)
return;
if(player->client->spycam) // already using camera
return;
target = camTrack(self);
if(!target)
return;
target->owner = self;
player->client->ps.stats[STAT_USEABLE] = 0;
player->client->ps.stats[STAT_HINTTITLE] = 1;
VectorClear (player->velocity);
if (!(self->spawnflags & 1))
{
target->child = CreateCamBullet(target, self);
}
player->client->spycam = target;
player->client->monitor = self;
camera_on(player);
//player->client->ps.pmove.pm_time = 160>>3; // hold time
//player->client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT;
if (self->spawnflags & 1)
{
//skip the bulletcam, go straight to the tracks.
edict_t *nextTarget;
nextTarget = NULL;
nextTarget = G_Find(NULL,FOFS(targetname), self->target);
if (!nextTarget)
{
camera_off(player);
return;
}
FirePathTarget(nextTarget);
WarpToNextPoint(target, nextTarget);
}
}
void SP_target_camshoot(edict_t *self)
{
self->use = use_camshoot;
//self->svflags = SVF_NOCLIENT;
gi.linkentity (self);
}