mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-23 12:52:46 +00:00
grr, it was r_part.c, not r_efrag, but that's sorted properly now
This commit is contained in:
parent
eba467689a
commit
e0c11b2f87
4 changed files with 1725 additions and 1 deletions
|
@ -131,7 +131,7 @@ client_LIBS= $(top_builddir)/libs/gamecode/libQFgamecode.la $(top_builddir)/libs
|
|||
client_LIB_DEPS= libqfsys.a libqfsnd.a libqfcd.a libqfjs.a libqfnet.a
|
||||
|
||||
client_SOURCES= cl_cam.c cl_cmd.c cl_demo.c cl_input.c cl_main.c cl_parse.c \
|
||||
cl_tent.c console.c keys.c sbar.c sw_rpart.c sw_rview.c \
|
||||
cl_tent.c console.c keys.c sbar.c r_part.c r_view.c \
|
||||
nonintel.c gib.c gib_instructions.c gib_vars.c \
|
||||
gib_interpret.c gib_modules.c gib_parse.c gib_stack.c vid.c
|
||||
|
||||
|
|
644
nq/source/r_part.c
Normal file
644
nq/source/r_part.c
Normal file
|
@ -0,0 +1,644 @@
|
|||
|
||||
/*
|
||||
r_part.c
|
||||
|
||||
@description@
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
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:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "r_local.h"
|
||||
#include "QF/qargs.h"
|
||||
#include "QF/console.h"
|
||||
#include "server.h"
|
||||
#include "QF/msg.h"
|
||||
|
||||
#define MAX_PARTICLES 2048 // default max # of particles at one
|
||||
// time
|
||||
#define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter
|
||||
// what's
|
||||
// on the command line
|
||||
|
||||
int ramp1[8] = { 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61 };
|
||||
int ramp2[8] = { 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66 };
|
||||
int ramp3[8] = { 0x6d, 0x6b, 6, 5, 4, 3 };
|
||||
|
||||
particle_t *active_particles, *free_particles;
|
||||
|
||||
particle_t *particles;
|
||||
int r_numparticles;
|
||||
|
||||
vec3_t r_pright, r_pup, r_ppn;
|
||||
|
||||
extern cvar_t *gl_particles;
|
||||
|
||||
/*
|
||||
===============
|
||||
R_InitParticles
|
||||
===============
|
||||
*/
|
||||
void
|
||||
R_InitParticles (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = COM_CheckParm ("-particles");
|
||||
|
||||
if (i) {
|
||||
r_numparticles = (int) (atoi (com_argv[i + 1]));
|
||||
if (r_numparticles < ABSOLUTE_MIN_PARTICLES)
|
||||
r_numparticles = ABSOLUTE_MIN_PARTICLES;
|
||||
} else {
|
||||
r_numparticles = MAX_PARTICLES;
|
||||
}
|
||||
|
||||
particles = (particle_t *)
|
||||
Hunk_AllocName (r_numparticles * sizeof (particle_t), "particles");
|
||||
}
|
||||
|
||||
#ifdef QUAKE2
|
||||
void
|
||||
R_DarkFieldParticles (entity_t *ent)
|
||||
{
|
||||
int i, j, k;
|
||||
particle_t *p;
|
||||
float vel;
|
||||
vec3_t dir;
|
||||
vec3_t org;
|
||||
|
||||
org[0] = ent->origin[0];
|
||||
org[1] = ent->origin[1];
|
||||
org[2] = ent->origin[2];
|
||||
for (i = -16; i < 16; i += 8)
|
||||
for (j = -16; j < 16; j += 8)
|
||||
for (k = 0; k < 32; k += 8) {
|
||||
if (!free_particles)
|
||||
return;
|
||||
p = free_particles;
|
||||
free_particles = p->next;
|
||||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
p->die = cl.time + 0.2 + (rand () & 7) * 0.02;
|
||||
p->color = 150 + rand () % 6;
|
||||
p->type = pt_slowgrav;
|
||||
|
||||
dir[0] = j * 8;
|
||||
dir[1] = i * 8;
|
||||
dir[2] = k * 8;
|
||||
|
||||
p->org[0] = org[0] + i + (rand () & 3);
|
||||
p->org[1] = org[1] + j + (rand () & 3);
|
||||
p->org[2] = org[2] + k + (rand () & 3);
|
||||
|
||||
VectorNormalize (dir);
|
||||
vel = 50 + (rand () & 63);
|
||||
VectorScale (dir, vel, p->vel);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_EntityParticles
|
||||
===============
|
||||
*/
|
||||
|
||||
#define NUMVERTEXNORMALS 162
|
||||
extern float r_avertexnormals[NUMVERTEXNORMALS][3];
|
||||
vec3_t avelocities[NUMVERTEXNORMALS];
|
||||
float beamlength = 16;
|
||||
vec3_t avelocity = { 23, 7, 3 };
|
||||
float partstep = 0.01;
|
||||
float timescale = 0.01;
|
||||
|
||||
void
|
||||
R_EntityParticles (entity_t *ent)
|
||||
{
|
||||
int count;
|
||||
int i;
|
||||
particle_t *p;
|
||||
float angle;
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
vec3_t forward;
|
||||
float dist;
|
||||
|
||||
dist = 64;
|
||||
count = 50;
|
||||
|
||||
if (!avelocities[0][0]) {
|
||||
for (i = 0; i < NUMVERTEXNORMALS * 3; i++)
|
||||
avelocities[0][i] = (rand () & 255) * 0.01;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < NUMVERTEXNORMALS; i++) {
|
||||
angle = cl.time * avelocities[i][0];
|
||||
sy = sin (angle);
|
||||
cy = cos (angle);
|
||||
angle = cl.time * avelocities[i][1];
|
||||
sp = sin (angle);
|
||||
cp = cos (angle);
|
||||
angle = cl.time * avelocities[i][2];
|
||||
sr = sin (angle);
|
||||
cr = cos (angle);
|
||||
|
||||
forward[0] = cp * cy;
|
||||
forward[1] = cp * sy;
|
||||
forward[2] = -sp;
|
||||
|
||||
if (!free_particles)
|
||||
return;
|
||||
p = free_particles;
|
||||
free_particles = p->next;
|
||||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
p->die = cl.time + 0.01;
|
||||
p->color = 0x6f;
|
||||
p->type = pt_explode;
|
||||
|
||||
p->org[0] =
|
||||
ent->origin[0] + r_avertexnormals[i][0] * dist +
|
||||
forward[0] * beamlength;
|
||||
p->org[1] =
|
||||
ent->origin[1] + r_avertexnormals[i][1] * dist +
|
||||
forward[1] * beamlength;
|
||||
p->org[2] =
|
||||
ent->origin[2] + r_avertexnormals[i][2] * dist +
|
||||
forward[2] * beamlength;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ClearParticles
|
||||
===============
|
||||
*/
|
||||
void
|
||||
R_ClearParticles (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
free_particles = &particles[0];
|
||||
active_particles = NULL;
|
||||
|
||||
for (i = 0; i < r_numparticles; i++)
|
||||
particles[i].next = &particles[i + 1];
|
||||
particles[r_numparticles - 1].next = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
R_ReadPointFile_f (void)
|
||||
{
|
||||
QFile *f;
|
||||
vec3_t org;
|
||||
int r;
|
||||
int c;
|
||||
particle_t *p;
|
||||
char name[MAX_OSPATH];
|
||||
char buf[256];
|
||||
|
||||
snprintf (name, sizeof (name), "maps/%s.pts", sv.name);
|
||||
|
||||
COM_FOpenFile (name, &f);
|
||||
if (!f) {
|
||||
Con_Printf ("couldn't open %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
Con_Printf ("Reading %s...\n", name);
|
||||
c = 0;
|
||||
for (;;) {
|
||||
if (!Qgets (f, buf, sizeof (buf)))
|
||||
break;
|
||||
r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]);
|
||||
if (r != 3)
|
||||
break;
|
||||
c++;
|
||||
|
||||
if (!free_particles) {
|
||||
Con_Printf ("Not enough free particles\n");
|
||||
break;
|
||||
}
|
||||
p = free_particles;
|
||||
free_particles = p->next;
|
||||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
p->die = 99999;
|
||||
p->color = (-c) & 15;
|
||||
p->type = pt_static;
|
||||
VectorCopy (vec3_origin, p->vel);
|
||||
VectorCopy (org, p->org);
|
||||
}
|
||||
|
||||
Qclose (f);
|
||||
Con_Printf ("%i points read\n", c);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ParseParticleEffect
|
||||
|
||||
Parse an effect out of the server message
|
||||
===============
|
||||
*/
|
||||
void
|
||||
R_ParseParticleEffect (void)
|
||||
{
|
||||
vec3_t org, dir;
|
||||
int i, count, msgcount, color;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
org[i] = MSG_ReadCoord (net_message);
|
||||
for (i = 0; i < 3; i++)
|
||||
dir[i] = MSG_ReadChar (net_message) * (1.0 / 16);
|
||||
msgcount = MSG_ReadByte (net_message);
|
||||
color = MSG_ReadByte (net_message);
|
||||
|
||||
if (msgcount == 255)
|
||||
count = 1024;
|
||||
else
|
||||
count = msgcount;
|
||||
|
||||
R_RunParticleEffect (org, dir, color, count);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ParticleExplosion
|
||||
|
||||
===============
|
||||
*/
|
||||
void
|
||||
R_ParticleExplosion (vec3_t org)
|
||||
{
|
||||
int i, j;
|
||||
particle_t *p;
|
||||
|
||||
for (i = 0; i < 1024; i++) {
|
||||
if (!free_particles)
|
||||
return;
|
||||
p = free_particles;
|
||||
free_particles = p->next;
|
||||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
p->die = cl.time + 5;
|
||||
p->color = ramp1[0];
|
||||
p->ramp = rand () & 3;
|
||||
if (i & 1) {
|
||||
p->type = pt_explode;
|
||||
for (j = 0; j < 3; j++) {
|
||||
p->org[j] = org[j] + ((rand () % 32) - 16);
|
||||
p->vel[j] = (rand () % 512) - 256;
|
||||
}
|
||||
} else {
|
||||
p->type = pt_explode2;
|
||||
for (j = 0; j < 3; j++) {
|
||||
p->org[j] = org[j] + ((rand () % 32) - 16);
|
||||
p->vel[j] = (rand () % 512) - 256;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ParticleExplosion2
|
||||
|
||||
===============
|
||||
*/
|
||||
void
|
||||
R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
|
||||
{
|
||||
int i, j;
|
||||
particle_t *p;
|
||||
int colorMod = 0;
|
||||
|
||||
for (i = 0; i < 512; i++) {
|
||||
if (!free_particles)
|
||||
return;
|
||||
p = free_particles;
|
||||
free_particles = p->next;
|
||||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
p->die = cl.time + 0.3;
|
||||
p->color = colorStart + (colorMod % colorLength);
|
||||
colorMod++;
|
||||
|
||||
p->type = pt_blob;
|
||||
for (j = 0; j < 3; j++) {
|
||||
p->org[j] = org[j] + ((rand () % 32) - 16);
|
||||
p->vel[j] = (rand () % 512) - 256;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_BlobExplosion
|
||||
|
||||
===============
|
||||
*/
|
||||
void
|
||||
R_BlobExplosion (vec3_t org)
|
||||
{
|
||||
int i, j;
|
||||
particle_t *p;
|
||||
|
||||
for (i = 0; i < 1024; i++) {
|
||||
if (!free_particles)
|
||||
return;
|
||||
p = free_particles;
|
||||
free_particles = p->next;
|
||||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
p->die = cl.time + 1 + (rand () & 8) * 0.05;
|
||||
|
||||
if (i & 1) {
|
||||
p->type = pt_blob;
|
||||
p->color = 66 + rand () % 6;
|
||||
for (j = 0; j < 3; j++) {
|
||||
p->org[j] = org[j] + ((rand () % 32) - 16);
|
||||
p->vel[j] = (rand () % 512) - 256;
|
||||
}
|
||||
} else {
|
||||
p->type = pt_blob2;
|
||||
p->color = 150 + rand () % 6;
|
||||
for (j = 0; j < 3; j++) {
|
||||
p->org[j] = org[j] + ((rand () % 32) - 16);
|
||||
p->vel[j] = (rand () % 512) - 256;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_RunParticleEffect
|
||||
|
||||
===============
|
||||
*/
|
||||
void
|
||||
R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
|
||||
{
|
||||
int i, j;
|
||||
particle_t *p;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!free_particles)
|
||||
return;
|
||||
p = free_particles;
|
||||
free_particles = p->next;
|
||||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
if (count == 1024) { // rocket explosion
|
||||
p->die = cl.time + 5;
|
||||
p->color = ramp1[0];
|
||||
p->ramp = rand () & 3;
|
||||
if (i & 1) {
|
||||
p->type = pt_explode;
|
||||
for (j = 0; j < 3; j++) {
|
||||
p->org[j] = org[j] + ((rand () % 32) - 16);
|
||||
p->vel[j] = (rand () % 512) - 256;
|
||||
}
|
||||
} else {
|
||||
p->type = pt_explode2;
|
||||
for (j = 0; j < 3; j++) {
|
||||
p->org[j] = org[j] + ((rand () % 32) - 16);
|
||||
p->vel[j] = (rand () % 512) - 256;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p->die = cl.time + 0.1 * (rand () % 5);
|
||||
p->color = (color & ~7) + (rand () & 7);
|
||||
p->type = pt_slowgrav;
|
||||
for (j = 0; j < 3; j++) {
|
||||
p->org[j] = org[j] + ((rand () & 15) - 8);
|
||||
p->vel[j] = dir[j] * 15; // + (rand()%300)-150;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_LavaSplash
|
||||
|
||||
===============
|
||||
*/
|
||||
void
|
||||
R_LavaSplash (vec3_t org)
|
||||
{
|
||||
int i, j, k;
|
||||
particle_t *p;
|
||||
float vel;
|
||||
vec3_t dir;
|
||||
|
||||
for (i = -16; i < 16; i++)
|
||||
for (j = -16; j < 16; j++)
|
||||
for (k = 0; k < 1; k++) {
|
||||
if (!free_particles)
|
||||
return;
|
||||
p = free_particles;
|
||||
free_particles = p->next;
|
||||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
p->die = cl.time + 2 + (rand () & 31) * 0.02;
|
||||
p->color = 224 + (rand () & 7);
|
||||
p->type = pt_slowgrav;
|
||||
|
||||
dir[0] = j * 8 + (rand () & 7);
|
||||
dir[1] = i * 8 + (rand () & 7);
|
||||
dir[2] = 256;
|
||||
|
||||
p->org[0] = org[0] + dir[0];
|
||||
p->org[1] = org[1] + dir[1];
|
||||
p->org[2] = org[2] + (rand () & 63);
|
||||
|
||||
VectorNormalize (dir);
|
||||
vel = 50 + (rand () & 63);
|
||||
VectorScale (dir, vel, p->vel);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_TeleportSplash
|
||||
|
||||
===============
|
||||
*/
|
||||
void
|
||||
R_TeleportSplash (vec3_t org)
|
||||
{
|
||||
int i, j, k;
|
||||
particle_t *p;
|
||||
float vel;
|
||||
vec3_t dir;
|
||||
|
||||
for (i = -16; i < 16; i += 4)
|
||||
for (j = -16; j < 16; j += 4)
|
||||
for (k = -24; k < 32; k += 4) {
|
||||
if (!free_particles)
|
||||
return;
|
||||
p = free_particles;
|
||||
free_particles = p->next;
|
||||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
p->die = cl.time + 0.2 + (rand () & 7) * 0.02;
|
||||
p->color = 7 + (rand () & 7);
|
||||
p->type = pt_slowgrav;
|
||||
|
||||
dir[0] = j * 8;
|
||||
dir[1] = i * 8;
|
||||
dir[2] = k * 8;
|
||||
|
||||
p->org[0] = org[0] + i + (rand () & 3);
|
||||
p->org[1] = org[1] + j + (rand () & 3);
|
||||
p->org[2] = org[2] + k + (rand () & 3);
|
||||
|
||||
VectorNormalize (dir);
|
||||
vel = 50 + (rand () & 63);
|
||||
VectorScale (dir, vel, p->vel);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
|
||||
{
|
||||
vec3_t vec;
|
||||
float len;
|
||||
int j;
|
||||
particle_t *p;
|
||||
int dec;
|
||||
static int tracercount;
|
||||
|
||||
if (type == 0)
|
||||
R_AddFire (start, end, ent);
|
||||
|
||||
if (!gl_particles->int_val)
|
||||
return;
|
||||
|
||||
VectorSubtract (end, start, vec);
|
||||
len = VectorNormalize (vec);
|
||||
if (type < 128)
|
||||
dec = 3;
|
||||
else {
|
||||
dec = 1;
|
||||
type -= 128;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
len -= dec;
|
||||
|
||||
if (!free_particles)
|
||||
return;
|
||||
p = free_particles;
|
||||
free_particles = p->next;
|
||||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
VectorCopy (vec3_origin, p->vel);
|
||||
p->die = cl.time + 2;
|
||||
|
||||
switch (type) {
|
||||
case 0: // rocket trail
|
||||
p->ramp = (rand () & 3);
|
||||
p->color = ramp3[(int) p->ramp];
|
||||
p->type = pt_fire;
|
||||
for (j = 0; j < 3; j++)
|
||||
p->org[j] = start[j] + ((rand () % 6) - 3);
|
||||
break;
|
||||
|
||||
case 1: // smoke smoke
|
||||
p->ramp = (rand () & 3) + 2;
|
||||
p->color = ramp3[(int) p->ramp];
|
||||
p->type = pt_fire;
|
||||
for (j = 0; j < 3; j++)
|
||||
p->org[j] = start[j] + ((rand () % 6) - 3);
|
||||
break;
|
||||
|
||||
case 2: // blood
|
||||
p->type = pt_grav;
|
||||
p->color = 67 + (rand () & 3);
|
||||
for (j = 0; j < 3; j++)
|
||||
p->org[j] = start[j] + ((rand () % 6) - 3);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 5: // tracer
|
||||
p->die = cl.time + 0.5;
|
||||
p->type = pt_static;
|
||||
if (type == 3)
|
||||
p->color = 52 + ((tracercount & 4) << 1);
|
||||
else
|
||||
p->color = 230 + ((tracercount & 4) << 1);
|
||||
|
||||
tracercount++;
|
||||
|
||||
VectorCopy (start, p->org);
|
||||
if (tracercount & 1) {
|
||||
p->vel[0] = 30 * vec[1];
|
||||
p->vel[1] = 30 * -vec[0];
|
||||
} else {
|
||||
p->vel[0] = 30 * -vec[1];
|
||||
p->vel[1] = 30 * vec[0];
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // slight blood
|
||||
p->type = pt_grav;
|
||||
p->color = 67 + (rand () & 3);
|
||||
for (j = 0; j < 3; j++)
|
||||
p->org[j] = start[j] + ((rand () % 6) - 3);
|
||||
len -= 3;
|
||||
break;
|
||||
|
||||
case 6: // voor trail
|
||||
p->color = 9 * 16 + 8 + (rand () & 3);
|
||||
p->type = pt_static;
|
||||
p->die = cl.time + 0.3;
|
||||
for (j = 0; j < 3; j++)
|
||||
p->org[j] = start[j] + ((rand () & 15) - 8);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
VectorAdd (start, vec, start);
|
||||
}
|
||||
}
|
804
nq/source/r_view.c
Normal file
804
nq/source/r_view.c
Normal file
|
@ -0,0 +1,804 @@
|
|||
/*
|
||||
view.c
|
||||
|
||||
@description@
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
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:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "view.h"
|
||||
#include "r_local.h"
|
||||
#include "host.h"
|
||||
#include "QF/cmd.h"
|
||||
#include "chase.h"
|
||||
#include "draw.h"
|
||||
#include "screen.h"
|
||||
#include "QF/console.h"
|
||||
#include "QF/msg.h"
|
||||
|
||||
/*
|
||||
|
||||
The view is allowed to move slightly from it's true position for bobbing,
|
||||
but if it exceeds 8 pixels linear distance (spherical, not box), the list of
|
||||
entities sent from the server may not include everything in the pvs, especially
|
||||
when crossing a water boudnary.
|
||||
|
||||
*/
|
||||
|
||||
cvar_t *scr_ofsx;
|
||||
cvar_t *scr_ofsy;
|
||||
cvar_t *scr_ofsz;
|
||||
|
||||
cvar_t *cl_rollspeed;
|
||||
cvar_t *cl_rollangle;
|
||||
|
||||
cvar_t *cl_bob;
|
||||
cvar_t *cl_bobcycle;
|
||||
cvar_t *cl_bobup;
|
||||
|
||||
cvar_t *v_kicktime;
|
||||
cvar_t *v_kickroll;
|
||||
cvar_t *v_kickpitch;
|
||||
|
||||
cvar_t *v_iyaw_cycle;
|
||||
cvar_t *v_iroll_cycle;
|
||||
cvar_t *v_ipitch_cycle;
|
||||
cvar_t *v_iyaw_level;
|
||||
cvar_t *v_iroll_level;
|
||||
cvar_t *v_ipitch_level;
|
||||
|
||||
cvar_t *v_idlescale;
|
||||
|
||||
cvar_t *crosshair;
|
||||
cvar_t *crosshaircolor;
|
||||
cvar_t *cl_crossx;
|
||||
cvar_t *cl_crossy;
|
||||
|
||||
cvar_t *gl_cshiftpercent;
|
||||
|
||||
cvar_t *brightness;
|
||||
cvar_t *contrast;
|
||||
|
||||
float v_dmg_time, v_dmg_roll, v_dmg_pitch;
|
||||
|
||||
extern int in_forward, in_forward2, in_back;
|
||||
|
||||
void BuildGammaTable (float, float);
|
||||
|
||||
/*
|
||||
===============
|
||||
V_CalcBob
|
||||
|
||||
===============
|
||||
*/
|
||||
float
|
||||
V_CalcBob (void)
|
||||
{
|
||||
float bob;
|
||||
float cycle;
|
||||
|
||||
cycle = cl.time - (int) (cl.time / cl_bobcycle->value) * cl_bobcycle->value;
|
||||
cycle /= cl_bobcycle->value;
|
||||
if (cycle < cl_bobup->value)
|
||||
cycle = M_PI * cycle / cl_bobup->value;
|
||||
else
|
||||
cycle =
|
||||
M_PI + M_PI * (cycle - cl_bobup->value) / (1.0 - cl_bobup->value);
|
||||
|
||||
// bob is proportional to velocity in the xy plane
|
||||
// (don't count Z, or jumping messes it up)
|
||||
|
||||
bob =
|
||||
sqrt (cl.velocity[0] * cl.velocity[0] +
|
||||
cl.velocity[1] * cl.velocity[1]) * cl_bob->value;
|
||||
//Con_Printf ("speed: %5.1f\n", Length(cl.velocity));
|
||||
bob = bob * 0.3 + bob * 0.7 * sin (cycle);
|
||||
if (bob > 4)
|
||||
bob = 4;
|
||||
else if (bob < -7)
|
||||
bob = -7;
|
||||
return bob;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
cvar_t *v_centermove;
|
||||
cvar_t *v_centerspeed;
|
||||
|
||||
|
||||
void
|
||||
V_StartPitchDrift (void)
|
||||
{
|
||||
#if 1
|
||||
if (cl.laststop == cl.time) {
|
||||
return; // something else is keeping it from
|
||||
// drifting
|
||||
}
|
||||
#endif
|
||||
if (cl.nodrift || !cl.pitchvel) {
|
||||
cl.pitchvel = v_centerspeed->value;
|
||||
cl.nodrift = false;
|
||||
cl.driftmove = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
V_StopPitchDrift (void)
|
||||
{
|
||||
cl.laststop = cl.time;
|
||||
cl.nodrift = true;
|
||||
cl.pitchvel = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
V_DriftPitch
|
||||
|
||||
Moves the client pitch angle towards cl.idealpitch sent by the server.
|
||||
|
||||
If the user is adjusting pitch manually, either with lookup/lookdown,
|
||||
mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped.
|
||||
|
||||
Drifting is enabled when the center view key is hit, mlook is released and
|
||||
lookspring is non 0, or when
|
||||
===============
|
||||
*/
|
||||
void
|
||||
V_DriftPitch (void)
|
||||
{
|
||||
float delta, move;
|
||||
|
||||
if (noclip_anglehack || !cl.onground || cls.demoplayback) {
|
||||
cl.driftmove = 0;
|
||||
cl.pitchvel = 0;
|
||||
return;
|
||||
}
|
||||
// don't count small mouse motion
|
||||
if (cl.nodrift) {
|
||||
if (fabs (cl.cmd.forwardmove) < cl_forwardspeed->value)
|
||||
cl.driftmove = 0;
|
||||
else
|
||||
cl.driftmove += host_frametime;
|
||||
|
||||
if (cl.driftmove > v_centermove->value) {
|
||||
V_StartPitchDrift ();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
delta = cl.idealpitch - cl.viewangles[PITCH];
|
||||
|
||||
if (!delta) {
|
||||
cl.pitchvel = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
move = host_frametime * cl.pitchvel;
|
||||
cl.pitchvel += host_frametime * v_centerspeed->value;
|
||||
|
||||
//Con_Printf ("move: %f (%f)\n", move, host_frametime);
|
||||
|
||||
if (delta > 0) {
|
||||
if (move > delta) {
|
||||
cl.pitchvel = 0;
|
||||
move = delta;
|
||||
}
|
||||
cl.viewangles[PITCH] += move;
|
||||
} else if (delta < 0) {
|
||||
if (move > -delta) {
|
||||
cl.pitchvel = 0;
|
||||
move = -delta;
|
||||
}
|
||||
cl.viewangles[PITCH] -= move;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
PALETTE FLASHES
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
cshift_t cshift_empty = { {130, 80, 50}
|
||||
, 0
|
||||
};
|
||||
cshift_t cshift_water = { {130, 80, 50}
|
||||
, 128
|
||||
};
|
||||
cshift_t cshift_slime = { {0, 25, 5}
|
||||
, 150
|
||||
};
|
||||
cshift_t cshift_lava = { {255, 80, 0}
|
||||
, 150
|
||||
};
|
||||
|
||||
cvar_t *v_gamma;
|
||||
|
||||
byte gammatable[256]; // palette is sent through this
|
||||
|
||||
/*
|
||||
=================
|
||||
V_CheckGamma
|
||||
=================
|
||||
*/
|
||||
qboolean
|
||||
V_CheckGamma (void)
|
||||
{
|
||||
static float oldbrightness;
|
||||
static float oldcontrast;
|
||||
|
||||
if ((brightness->value == oldbrightness) && contrast->value == oldcontrast)
|
||||
return false;
|
||||
oldbrightness = brightness->value;
|
||||
oldcontrast = contrast->value;
|
||||
|
||||
BuildGammaTable (brightness->value, contrast->value);
|
||||
vid.recalc_refdef = 1; // force a surface cache flush
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
V_ParseDamage
|
||||
===============
|
||||
*/
|
||||
void
|
||||
V_ParseDamage (void)
|
||||
{
|
||||
int armor, blood;
|
||||
vec3_t from;
|
||||
int i;
|
||||
vec3_t forward, right, up;
|
||||
entity_t *ent;
|
||||
float side;
|
||||
float count;
|
||||
|
||||
armor = MSG_ReadByte (net_message);
|
||||
blood = MSG_ReadByte (net_message);
|
||||
for (i = 0; i < 3; i++)
|
||||
from[i] = MSG_ReadCoord (net_message);
|
||||
|
||||
count = blood * 0.5 + armor * 0.5;
|
||||
if (count < 10)
|
||||
count = 10;
|
||||
|
||||
cl.faceanimtime = cl.time + 0.2; // but sbar face into pain frame
|
||||
|
||||
cl.cshifts[CSHIFT_DAMAGE].percent += 3 * count;
|
||||
if (cl.cshifts[CSHIFT_DAMAGE].percent < 0)
|
||||
cl.cshifts[CSHIFT_DAMAGE].percent = 0;
|
||||
if (cl.cshifts[CSHIFT_DAMAGE].percent > 150)
|
||||
cl.cshifts[CSHIFT_DAMAGE].percent = 150;
|
||||
|
||||
if (armor > blood) {
|
||||
cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200;
|
||||
cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100;
|
||||
cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100;
|
||||
} else if (armor) {
|
||||
cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220;
|
||||
cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50;
|
||||
cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50;
|
||||
} else {
|
||||
cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255;
|
||||
cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0;
|
||||
cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// calculate view angle kicks
|
||||
//
|
||||
ent = &cl_entities[cl.viewentity];
|
||||
|
||||
VectorSubtract (from, ent->origin, from);
|
||||
VectorNormalize (from);
|
||||
|
||||
AngleVectors (ent->angles, forward, right, up);
|
||||
|
||||
side = DotProduct (from, right);
|
||||
v_dmg_roll = count * side * v_kickroll->value;
|
||||
|
||||
side = DotProduct (from, forward);
|
||||
v_dmg_pitch = count * side * v_kickpitch->value;
|
||||
|
||||
v_dmg_time = v_kicktime->value;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
V_cshift_f
|
||||
==================
|
||||
*/
|
||||
void
|
||||
V_cshift_f (void)
|
||||
{
|
||||
cshift_empty.destcolor[0] = atoi (Cmd_Argv (1));
|
||||
cshift_empty.destcolor[1] = atoi (Cmd_Argv (2));
|
||||
cshift_empty.destcolor[2] = atoi (Cmd_Argv (3));
|
||||
cshift_empty.percent = atoi (Cmd_Argv (4));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
V_BonusFlash_f
|
||||
|
||||
When you run over an item, the server sends this command
|
||||
==================
|
||||
*/
|
||||
void
|
||||
V_BonusFlash_f (void)
|
||||
{
|
||||
cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215;
|
||||
cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186;
|
||||
cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69;
|
||||
cl.cshifts[CSHIFT_BONUS].percent = 50;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
V_SetContentsColor
|
||||
|
||||
Underwater, lava, etc each has a color shift
|
||||
=============
|
||||
*/
|
||||
void
|
||||
V_SetContentsColor (int contents)
|
||||
{
|
||||
switch (contents) {
|
||||
case CONTENTS_EMPTY:
|
||||
case CONTENTS_SOLID:
|
||||
cl.cshifts[CSHIFT_CONTENTS] = cshift_empty;
|
||||
break;
|
||||
case CONTENTS_LAVA:
|
||||
cl.cshifts[CSHIFT_CONTENTS] = cshift_lava;
|
||||
break;
|
||||
case CONTENTS_SLIME:
|
||||
cl.cshifts[CSHIFT_CONTENTS] = cshift_slime;
|
||||
break;
|
||||
default:
|
||||
cl.cshifts[CSHIFT_CONTENTS] = cshift_water;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
V_CalcPowerupCshift
|
||||
=============
|
||||
*/
|
||||
void
|
||||
V_CalcPowerupCshift (void)
|
||||
{
|
||||
if (cl.items & IT_QUAD) {
|
||||
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
|
||||
cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0;
|
||||
cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255;
|
||||
cl.cshifts[CSHIFT_POWERUP].percent = 30;
|
||||
} else if (cl.items & IT_SUIT) {
|
||||
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
|
||||
cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
|
||||
cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
|
||||
cl.cshifts[CSHIFT_POWERUP].percent = 20;
|
||||
} else if (cl.items & IT_INVISIBILITY) {
|
||||
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100;
|
||||
cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100;
|
||||
cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100;
|
||||
cl.cshifts[CSHIFT_POWERUP].percent = 100;
|
||||
} else if (cl.items & IT_INVULNERABILITY) {
|
||||
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255;
|
||||
cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
|
||||
cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
|
||||
cl.cshifts[CSHIFT_POWERUP].percent = 30;
|
||||
} else
|
||||
cl.cshifts[CSHIFT_POWERUP].percent = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
VIEW RENDERING
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
float
|
||||
angledelta (float a)
|
||||
{
|
||||
a = anglemod (a);
|
||||
if (a > 180)
|
||||
a -= 360;
|
||||
return a;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CalcGunAngle
|
||||
==================
|
||||
*/
|
||||
void
|
||||
CalcGunAngle (void)
|
||||
{
|
||||
float yaw, pitch, move;
|
||||
static float oldyaw = 0;
|
||||
static float oldpitch = 0;
|
||||
|
||||
yaw = r_refdef.viewangles[YAW];
|
||||
pitch = -r_refdef.viewangles[PITCH];
|
||||
|
||||
yaw = angledelta (yaw - r_refdef.viewangles[YAW]) * 0.4;
|
||||
if (yaw > 10)
|
||||
yaw = 10;
|
||||
if (yaw < -10)
|
||||
yaw = -10;
|
||||
pitch = angledelta (-pitch - r_refdef.viewangles[PITCH]) * 0.4;
|
||||
if (pitch > 10)
|
||||
pitch = 10;
|
||||
if (pitch < -10)
|
||||
pitch = -10;
|
||||
move = host_frametime * 20;
|
||||
if (yaw > oldyaw) {
|
||||
if (oldyaw + move < yaw)
|
||||
yaw = oldyaw + move;
|
||||
} else {
|
||||
if (oldyaw - move > yaw)
|
||||
yaw = oldyaw - move;
|
||||
}
|
||||
|
||||
if (pitch > oldpitch) {
|
||||
if (oldpitch + move < pitch)
|
||||
pitch = oldpitch + move;
|
||||
} else {
|
||||
if (oldpitch - move > pitch)
|
||||
pitch = oldpitch - move;
|
||||
}
|
||||
|
||||
oldyaw = yaw;
|
||||
oldpitch = pitch;
|
||||
|
||||
cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw;
|
||||
cl.viewent.angles[PITCH] = -(r_refdef.viewangles[PITCH] + pitch);
|
||||
|
||||
cl.viewent.angles[ROLL] -=
|
||||
v_idlescale->value * sin (cl.time * v_iroll_cycle->value) *
|
||||
v_iroll_level->value;
|
||||
cl.viewent.angles[PITCH] -=
|
||||
v_idlescale->value * sin (cl.time * v_ipitch_cycle->value) *
|
||||
v_ipitch_level->value;
|
||||
cl.viewent.angles[YAW] -=
|
||||
v_idlescale->value * sin (cl.time * v_iyaw_cycle->value) *
|
||||
v_iyaw_level->value;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
V_BoundOffsets
|
||||
==============
|
||||
*/
|
||||
void
|
||||
V_BoundOffsets (void)
|
||||
{
|
||||
entity_t *ent;
|
||||
|
||||
ent = &cl_entities[cl.viewentity];
|
||||
|
||||
// absolutely bound refresh reletive to entity clipping hull
|
||||
// so the view can never be inside a solid wall
|
||||
|
||||
if (r_refdef.vieworg[0] < ent->origin[0] - 14)
|
||||
r_refdef.vieworg[0] = ent->origin[0] - 14;
|
||||
else if (r_refdef.vieworg[0] > ent->origin[0] + 14)
|
||||
r_refdef.vieworg[0] = ent->origin[0] + 14;
|
||||
if (r_refdef.vieworg[1] < ent->origin[1] - 14)
|
||||
r_refdef.vieworg[1] = ent->origin[1] - 14;
|
||||
else if (r_refdef.vieworg[1] > ent->origin[1] + 14)
|
||||
r_refdef.vieworg[1] = ent->origin[1] + 14;
|
||||
if (r_refdef.vieworg[2] < ent->origin[2] - 22)
|
||||
r_refdef.vieworg[2] = ent->origin[2] - 22;
|
||||
else if (r_refdef.vieworg[2] > ent->origin[2] + 30)
|
||||
r_refdef.vieworg[2] = ent->origin[2] + 30;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
V_AddIdle
|
||||
|
||||
Idle swaying
|
||||
==============
|
||||
*/
|
||||
void
|
||||
V_AddIdle (void)
|
||||
{
|
||||
r_refdef.viewangles[ROLL] +=
|
||||
v_idlescale->value * sin (cl.time * v_iroll_cycle->value) *
|
||||
v_iroll_level->value;
|
||||
r_refdef.viewangles[PITCH] +=
|
||||
v_idlescale->value * sin (cl.time * v_ipitch_cycle->value) *
|
||||
v_ipitch_level->value;
|
||||
r_refdef.viewangles[YAW] +=
|
||||
v_idlescale->value * sin (cl.time * v_iyaw_cycle->value) *
|
||||
v_iyaw_level->value;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
V_CalcViewRoll
|
||||
|
||||
Roll is induced by movement and damage
|
||||
==============
|
||||
*/
|
||||
void
|
||||
V_CalcViewRoll (void)
|
||||
{
|
||||
float side;
|
||||
|
||||
side = V_CalcRoll (cl_entities[cl.viewentity].angles, cl.velocity);
|
||||
r_refdef.viewangles[ROLL] += side;
|
||||
|
||||
if (v_dmg_time > 0) {
|
||||
r_refdef.viewangles[ROLL] +=
|
||||
v_dmg_time / v_kicktime->value * v_dmg_roll;
|
||||
r_refdef.viewangles[PITCH] +=
|
||||
v_dmg_time / v_kicktime->value * v_dmg_pitch;
|
||||
v_dmg_time -= host_frametime;
|
||||
}
|
||||
|
||||
if (cl.stats[STAT_HEALTH] <= 0) {
|
||||
r_refdef.viewangles[ROLL] = 80; // dead view angle
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
V_CalcIntermissionRefdef
|
||||
|
||||
==================
|
||||
*/
|
||||
void
|
||||
V_CalcIntermissionRefdef (void)
|
||||
{
|
||||
entity_t *ent, *view;
|
||||
float old;
|
||||
|
||||
// ent is the player model (visible when out of body)
|
||||
ent = &cl_entities[cl.viewentity];
|
||||
// view is the weapon model (only visible from inside body)
|
||||
view = &cl.viewent;
|
||||
|
||||
VectorCopy (ent->origin, r_refdef.vieworg);
|
||||
VectorCopy (ent->angles, r_refdef.viewangles);
|
||||
view->model = NULL;
|
||||
|
||||
// always idle in intermission
|
||||
old = v_idlescale->value;
|
||||
Cvar_SetValue (v_idlescale, 1);
|
||||
V_AddIdle ();
|
||||
Cvar_SetValue (v_idlescale, old);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
V_CalcRefdef
|
||||
|
||||
==================
|
||||
*/
|
||||
void
|
||||
V_CalcRefdef (void)
|
||||
{
|
||||
entity_t *ent, *view;
|
||||
int i;
|
||||
vec3_t forward, right, up;
|
||||
vec3_t angles;
|
||||
float bob;
|
||||
static float oldz = 0;
|
||||
|
||||
V_DriftPitch ();
|
||||
|
||||
// ent is the player model (visible when out of body)
|
||||
ent = &cl_entities[cl.viewentity];
|
||||
// view is the weapon model (only visible from inside body)
|
||||
view = &cl.viewent;
|
||||
|
||||
|
||||
// transform the view offset by the model's matrix to get the offset from
|
||||
// model origin for the view
|
||||
ent->angles[YAW] = cl.viewangles[YAW]; // the model should face
|
||||
// the view dir
|
||||
ent->angles[PITCH] = -cl.viewangles[PITCH]; // the model should face
|
||||
// the view dir
|
||||
|
||||
|
||||
bob = V_CalcBob ();
|
||||
|
||||
// refresh position
|
||||
VectorCopy (ent->origin, r_refdef.vieworg);
|
||||
r_refdef.vieworg[2] += cl.viewheight + bob;
|
||||
|
||||
// never let it sit exactly on a node line, because a water plane can
|
||||
// dissapear when viewed with the eye exactly on it.
|
||||
// the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis
|
||||
r_refdef.vieworg[0] += 1.0 / 32;
|
||||
r_refdef.vieworg[1] += 1.0 / 32;
|
||||
r_refdef.vieworg[2] += 1.0 / 32;
|
||||
|
||||
VectorCopy (cl.viewangles, r_refdef.viewangles);
|
||||
V_CalcViewRoll ();
|
||||
V_AddIdle ();
|
||||
|
||||
// offsets
|
||||
angles[PITCH] = -ent->angles[PITCH]; // because entity pitches are
|
||||
// actually backward
|
||||
angles[YAW] = ent->angles[YAW];
|
||||
angles[ROLL] = ent->angles[ROLL];
|
||||
|
||||
AngleVectors (angles, forward, right, up);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
r_refdef.vieworg[i] += scr_ofsx->value * forward[i]
|
||||
+ scr_ofsy->value * right[i]
|
||||
+ scr_ofsz->value * up[i];
|
||||
|
||||
|
||||
V_BoundOffsets ();
|
||||
|
||||
// set up gun position
|
||||
VectorCopy (cl.viewangles, view->angles);
|
||||
|
||||
CalcGunAngle ();
|
||||
|
||||
VectorCopy (ent->origin, view->origin);
|
||||
view->origin[2] += cl.viewheight;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
view->origin[i] += forward[i] * bob * 0.4;
|
||||
// view->origin[i] += right[i]*bob*0.4;
|
||||
// view->origin[i] += up[i]*bob*0.8;
|
||||
}
|
||||
view->origin[2] += bob;
|
||||
|
||||
// fudge position around to keep amount of weapon visible
|
||||
// roughly equal with different FOV
|
||||
|
||||
#if 0
|
||||
if (cl.model_precache[cl.stats[STAT_WEAPON]]
|
||||
&& strcmp (cl.model_precache[cl.stats[STAT_WEAPON]]->name,
|
||||
"progs/v_shot2.mdl"))
|
||||
#endif
|
||||
if (cl_sbar->int_val == 0 && scr_viewsize->int_val >= 100);
|
||||
else if (scr_viewsize->int_val == 110)
|
||||
view->origin[2] += 1;
|
||||
else if (scr_viewsize->int_val == 100)
|
||||
view->origin[2] += 2;
|
||||
else if (scr_viewsize->int_val == 90)
|
||||
view->origin[2] += 1;
|
||||
else if (scr_viewsize->int_val == 80)
|
||||
view->origin[2] += 0.5;
|
||||
|
||||
view->model = cl.model_precache[cl.stats[STAT_WEAPON]];
|
||||
view->frame = cl.stats[STAT_WEAPONFRAME];
|
||||
view->colormap = vid.colormap;
|
||||
|
||||
// set up the refresh position
|
||||
VectorAdd (r_refdef.viewangles, cl.punchangle, r_refdef.viewangles);
|
||||
|
||||
// smooth out stair step ups
|
||||
if (cl.onground && ent->origin[2] - oldz > 0) {
|
||||
float steptime;
|
||||
|
||||
steptime = cl.time - cl.oldtime;
|
||||
if (steptime < 0)
|
||||
//FIXME I_Error ("steptime < 0");
|
||||
steptime = 0;
|
||||
|
||||
oldz += steptime * 80;
|
||||
if (oldz > ent->origin[2])
|
||||
oldz = ent->origin[2];
|
||||
if (ent->origin[2] - oldz > 12)
|
||||
oldz = ent->origin[2] - 12;
|
||||
r_refdef.vieworg[2] += oldz - ent->origin[2];
|
||||
view->origin[2] += oldz - ent->origin[2];
|
||||
} else
|
||||
oldz = ent->origin[2];
|
||||
|
||||
if (chase_active->int_val)
|
||||
Chase_Update ();
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
V_RenderView
|
||||
|
||||
The player's clipping box goes from (-16 -16 -24) to (16 16 32) from
|
||||
the entity origin, so any view position inside that will be valid
|
||||
==================
|
||||
*/
|
||||
extern vrect_t scr_vrect;
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
=============
|
||||
V_Init
|
||||
=============
|
||||
*/
|
||||
void
|
||||
V_Init (void)
|
||||
{
|
||||
Cmd_AddCommand ("v_cshift", V_cshift_f, "No Description");
|
||||
Cmd_AddCommand ("bf", V_BonusFlash_f, "No Description");
|
||||
Cmd_AddCommand ("centerview", V_StartPitchDrift, "No Description");
|
||||
|
||||
v_centermove = Cvar_Get ("v_centermove", "0.15", CVAR_NONE, 0, "None");
|
||||
v_centerspeed = Cvar_Get ("v_centerspeed", "500", CVAR_NONE, 0, "None");
|
||||
|
||||
v_iyaw_cycle = Cvar_Get ("v_iyaw_cycle", "2", CVAR_NONE, 0, "None");
|
||||
v_iroll_cycle = Cvar_Get ("v_iroll_cycle", "0.5", CVAR_NONE, 0, "None");
|
||||
v_ipitch_cycle = Cvar_Get ("v_ipitch_cycle", "1", CVAR_NONE, 0, "None");
|
||||
v_iyaw_level = Cvar_Get ("v_iyaw_level", "0.3", CVAR_NONE, 0, "None");
|
||||
v_iroll_level = Cvar_Get ("v_iroll_level", "0.1", CVAR_NONE, 0, "None");
|
||||
v_ipitch_level = Cvar_Get ("v_ipitch_level", "0.3", CVAR_NONE, 0, "None");
|
||||
|
||||
v_idlescale = Cvar_Get ("v_idlescale", "0", CVAR_NONE, 0, "None");
|
||||
crosshair = Cvar_Get ("crosshair", "0", CVAR_ARCHIVE, 0, "None");
|
||||
crosshaircolor = Cvar_Get ("crosshaircolor", "79", CVAR_ARCHIVE, 0, "None");
|
||||
cl_crossx = Cvar_Get ("cl_crossx", "0", CVAR_NONE, 0, "None");
|
||||
cl_crossy = Cvar_Get ("cl_crossy", "0", CVAR_NONE, 0, "None");
|
||||
gl_cshiftpercent = Cvar_Get ("gl_cshiftpercent", "100", CVAR_NONE, 0, "None");
|
||||
|
||||
scr_ofsx = Cvar_Get ("scr_ofsx", "0", CVAR_NONE, 0, "None");
|
||||
scr_ofsy = Cvar_Get ("scr_ofsy", "0", CVAR_NONE, 0, "None");
|
||||
scr_ofsz = Cvar_Get ("scr_ofsz", "0", CVAR_NONE, 0, "None");
|
||||
cl_rollspeed = Cvar_Get ("cl_rollspeed", "200", CVAR_NONE, 0, "None");
|
||||
cl_rollangle = Cvar_Get ("cl_rollangle", "2.0", CVAR_NONE, 0, "None");
|
||||
cl_bob = Cvar_Get ("cl_bob", "0.02", CVAR_NONE, 0, "None");
|
||||
cl_bobcycle = Cvar_Get ("cl_bobcycle", "0.6", CVAR_NONE, 0, "None");
|
||||
cl_bobup = Cvar_Get ("cl_bobup", "0.5", CVAR_NONE, 0, "None");
|
||||
|
||||
v_kicktime = Cvar_Get ("v_kicktime", "0.5", CVAR_NONE, 0, "None");
|
||||
v_kickroll = Cvar_Get ("v_kickroll", "0.6", CVAR_NONE, 0, "None");
|
||||
v_kickpitch = Cvar_Get ("v_kickpitch", "0.6", CVAR_NONE, 0, "None");
|
||||
|
||||
BuildGammaTable (1.0, 1.0); // no gamma yet
|
||||
brightness = Cvar_Get ("brightness", "1", CVAR_ARCHIVE, 0, "None");
|
||||
contrast = Cvar_Get ("contrast", "1", CVAR_ARCHIVE, 0, "None");
|
||||
}
|
276
nq/source/sw_refrag.c
Normal file
276
nq/source/sw_refrag.c
Normal file
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
r_efrag.c
|
||||
|
||||
@description@
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
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:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "QF/console.h"
|
||||
#include "QF/sys.h"
|
||||
#include "r_local.h"
|
||||
|
||||
mnode_t *r_pefragtopnode;
|
||||
|
||||
|
||||
//===========================================================================
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
ENTITY FRAGMENT FUNCTIONS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
efrag_t **lastlink;
|
||||
|
||||
vec3_t r_emins, r_emaxs;
|
||||
|
||||
entity_t *r_addent;
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_RemoveEfrags
|
||||
|
||||
Call when removing an object from the world or moving it to another position
|
||||
================
|
||||
*/
|
||||
void
|
||||
R_RemoveEfrags (entity_t *ent)
|
||||
{
|
||||
efrag_t *ef, *old, *walk, **prev;
|
||||
|
||||
ef = ent->efrag;
|
||||
|
||||
while (ef) {
|
||||
prev = &ef->leaf->efrags;
|
||||
while (1) {
|
||||
walk = *prev;
|
||||
if (!walk)
|
||||
break;
|
||||
if (walk == ef) { // remove this fragment
|
||||
*prev = ef->leafnext;
|
||||
break;
|
||||
} else
|
||||
prev = &walk->leafnext;
|
||||
}
|
||||
|
||||
old = ef;
|
||||
ef = ef->entnext;
|
||||
|
||||
// put it on the free list
|
||||
old->entnext = cl.free_efrags;
|
||||
cl.free_efrags = old;
|
||||
}
|
||||
|
||||
ent->efrag = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
R_SplitEntityOnNode
|
||||
===================
|
||||
*/
|
||||
void
|
||||
R_SplitEntityOnNode (mnode_t *node)
|
||||
{
|
||||
efrag_t *ef;
|
||||
mplane_t *splitplane;
|
||||
mleaf_t *leaf;
|
||||
int sides;
|
||||
|
||||
if (node->contents == CONTENTS_SOLID) {
|
||||
return;
|
||||
}
|
||||
// add an efrag if the node is a leaf
|
||||
|
||||
if (node->contents < 0) {
|
||||
if (!r_pefragtopnode)
|
||||
r_pefragtopnode = node;
|
||||
|
||||
leaf = (mleaf_t *) node;
|
||||
|
||||
// grab an efrag off the free list
|
||||
ef = cl.free_efrags;
|
||||
if (!ef) {
|
||||
Con_Printf ("Too many efrags!\n");
|
||||
return; // no free fragments...
|
||||
}
|
||||
cl.free_efrags = cl.free_efrags->entnext;
|
||||
|
||||
ef->entity = r_addent;
|
||||
|
||||
// add the entity link
|
||||
*lastlink = ef;
|
||||
lastlink = &ef->entnext;
|
||||
ef->entnext = NULL;
|
||||
|
||||
// set the leaf links
|
||||
ef->leaf = leaf;
|
||||
ef->leafnext = leaf->efrags;
|
||||
leaf->efrags = ef;
|
||||
|
||||
return;
|
||||
}
|
||||
// NODE_MIXED
|
||||
|
||||
splitplane = node->plane;
|
||||
sides = BOX_ON_PLANE_SIDE (r_emins, r_emaxs, splitplane);
|
||||
|
||||
if (sides == 3) {
|
||||
// split on this plane
|
||||
// if this is the first splitter of this bmodel, remember it
|
||||
if (!r_pefragtopnode)
|
||||
r_pefragtopnode = node;
|
||||
}
|
||||
// recurse down the contacted sides
|
||||
if (sides & 1)
|
||||
R_SplitEntityOnNode (node->children[0]);
|
||||
|
||||
if (sides & 2)
|
||||
R_SplitEntityOnNode (node->children[1]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
R_SplitEntityOnNode2
|
||||
===================
|
||||
*/
|
||||
void
|
||||
R_SplitEntityOnNode2 (mnode_t *node)
|
||||
{
|
||||
mplane_t *splitplane;
|
||||
int sides;
|
||||
|
||||
if (node->visframe != r_visframecount)
|
||||
return;
|
||||
|
||||
if (node->contents < 0) {
|
||||
if (node->contents != CONTENTS_SOLID)
|
||||
r_pefragtopnode = node; // we've reached a non-solid leaf, so
|
||||
//
|
||||
//
|
||||
// it's
|
||||
// visible and not BSP clipped
|
||||
return;
|
||||
}
|
||||
|
||||
splitplane = node->plane;
|
||||
sides = BOX_ON_PLANE_SIDE (r_emins, r_emaxs, splitplane);
|
||||
|
||||
if (sides == 3) {
|
||||
// remember first splitter
|
||||
r_pefragtopnode = node;
|
||||
return;
|
||||
}
|
||||
// not split yet; recurse down the contacted side
|
||||
if (sides & 1)
|
||||
R_SplitEntityOnNode2 (node->children[0]);
|
||||
else
|
||||
R_SplitEntityOnNode2 (node->children[1]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
R_AddEfrags
|
||||
===========
|
||||
*/
|
||||
void
|
||||
R_AddEfrags (entity_t *ent)
|
||||
{
|
||||
model_t *entmodel;
|
||||
int i;
|
||||
|
||||
if (!ent->model)
|
||||
return;
|
||||
|
||||
if (ent == cl_entities)
|
||||
return; // never add the world
|
||||
|
||||
r_addent = ent;
|
||||
|
||||
lastlink = &ent->efrag;
|
||||
r_pefragtopnode = NULL;
|
||||
|
||||
entmodel = ent->model;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
r_emins[i] = ent->origin[i] + entmodel->mins[i];
|
||||
r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
|
||||
}
|
||||
|
||||
R_SplitEntityOnNode (cl.worldmodel->nodes);
|
||||
|
||||
ent->topnode = r_pefragtopnode;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_StoreEfrags
|
||||
|
||||
// FIXME: a lot of this goes away with edge-based
|
||||
================
|
||||
*/
|
||||
void
|
||||
R_StoreEfrags (efrag_t **ppefrag)
|
||||
{
|
||||
entity_t *pent;
|
||||
model_t *clmodel;
|
||||
efrag_t *pefrag;
|
||||
|
||||
|
||||
while ((pefrag = *ppefrag) != NULL) {
|
||||
pent = pefrag->entity;
|
||||
clmodel = pent->model;
|
||||
|
||||
switch (clmodel->type) {
|
||||
case mod_alias:
|
||||
case mod_brush:
|
||||
case mod_sprite:
|
||||
pent = pefrag->entity;
|
||||
|
||||
if ((pent->visframe != r_framecount) &&
|
||||
(cl_numvisedicts < MAX_VISEDICTS)) {
|
||||
cl_visedicts[cl_numvisedicts++] = pent;
|
||||
|
||||
// mark that we've recorded this entity for this frame
|
||||
pent->visframe = r_framecount;
|
||||
}
|
||||
|
||||
ppefrag = &pefrag->leafnext;
|
||||
break;
|
||||
|
||||
default:
|
||||
Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue