git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@468 e016b1c5-ed68-44aa-a2f7-31cac88cffde
687 lines
19 KiB
C++
687 lines
19 KiB
C++
// renderextras.cpp: misc gl render code and the HUD
|
|
|
|
#include "cube.h"
|
|
|
|
void line(int x1, int y1, float z1, int x2, int y2, float z2)
|
|
{
|
|
glBegin(GL_POLYGON);
|
|
glVertex3f((float)x1, z1, (float)y1);
|
|
glVertex3f((float)x1, z1, y1+0.01f);
|
|
glVertex3f((float)x2, z2, y2+0.01f);
|
|
glVertex3f((float)x2, z2, (float)y2);
|
|
glEnd();
|
|
xtraverts += 4;
|
|
};
|
|
|
|
void linestyle(float width, int r, int g, int b)
|
|
{
|
|
glLineWidth(width);
|
|
glColor3ub(r,g,b);
|
|
};
|
|
|
|
void box(block &b, float z1, float z2, float z3, float z4)
|
|
{
|
|
glBegin(GL_POLYGON);
|
|
glVertex3f((float)b.x, z1, (float)b.y);
|
|
glVertex3f((float)b.x+b.xs, z2, (float)b.y);
|
|
glVertex3f((float)b.x+b.xs, z3, (float)b.y+b.ys);
|
|
glVertex3f((float)b.x, z4, (float)b.y+b.ys);
|
|
glEnd();
|
|
xtraverts += 4;
|
|
};
|
|
|
|
void dot(int x, int y, float z)
|
|
{
|
|
const float DOF = 0.1f;
|
|
glBegin(GL_POLYGON);
|
|
glVertex3f(x-DOF, (float)z, y-DOF);
|
|
glVertex3f(x+DOF, (float)z, y-DOF);
|
|
glVertex3f(x+DOF, (float)z, y+DOF);
|
|
glVertex3f(x-DOF, (float)z, y+DOF);
|
|
glEnd();
|
|
xtraverts += 4;
|
|
};
|
|
|
|
void blendbox(int x1, int y1, int x2, int y2, bool border, int tex)
|
|
{
|
|
glDepthMask(GL_FALSE);
|
|
glDisable(GL_TEXTURE_2D);
|
|
if(tex>=0)
|
|
{
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glDisable(GL_BLEND);
|
|
glColor3d(1.0, 1.0, 1.0);
|
|
|
|
int texw = 512;
|
|
int texh = texw;
|
|
int cols = (int)((x2-x1)/texw+1);
|
|
int rows = (int)((y2-y1)/texh+1);
|
|
xtraverts += cols*rows*4;
|
|
|
|
loopj(rows)
|
|
{
|
|
float ytexcut = 0.0f;
|
|
float yboxcut = 0.0f;
|
|
if((j+1)*texh>y2-y1) // cut last row to match the box height
|
|
{
|
|
yboxcut = (float)(((j+1)*texh)-(y2-y1));
|
|
ytexcut = (float)(((j+1)*texh)-(y2-y1))/texh;
|
|
}
|
|
|
|
loopi(cols)
|
|
{
|
|
float xtexcut = 0.0f;
|
|
float xboxcut = 0.0f;
|
|
if((i+1)*texw>x2-x1)
|
|
{
|
|
xboxcut = (float)(((i+1)*texw)-(x2-x1));
|
|
xtexcut = (float)(((i+1)*texw)-(x2-x1))/texw;
|
|
}
|
|
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2f(0.0f, 0.0f); glVertex2f((float)x1+texw*i, (float)y1+texh*j);
|
|
glTexCoord2f(1-xtexcut, 0); glVertex2f(x1+texw*(i+1)-xboxcut, (float)y1+texh*j);
|
|
glTexCoord2f(1-xtexcut, 1-ytexcut); glVertex2f(x1+texw*(i+1)-xboxcut, (float)y1+texh*(j+1)-yboxcut);
|
|
glTexCoord2f(0, 1-ytexcut); glVertex2f((float)x1+texw*i, y1+texh*(j+1)-yboxcut);
|
|
glEnd();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(border) glColor3d(0.7, 0.7, 0.7); //glColor3d(0.5, 0.3, 0.4);
|
|
else glColor3d(1.0, 1.0, 1.0);
|
|
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2f(0, 0); glVertex2i(x1, y1);
|
|
glTexCoord2f(1, 0); glVertex2i(x2, y1);
|
|
glTexCoord2f(1, 1); glVertex2i(x2, y2);
|
|
glTexCoord2f(0, 1); glVertex2i(x1, y2);
|
|
glEnd();
|
|
xtraverts += 4;
|
|
};
|
|
|
|
glDisable(GL_BLEND);
|
|
if(tex>=0) glDisable(GL_TEXTURE_2D);
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
glBegin(GL_POLYGON);
|
|
glColor3d(0.6, 0.6, 0.6); //glColor3d(0.2, 0.7, 0.4);
|
|
glVertex2i(x1, y1);
|
|
glVertex2i(x2, y1);
|
|
glVertex2i(x2, y2);
|
|
glVertex2i(x1, y2);
|
|
glEnd();
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
glEnable(GL_BLEND);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glDepthMask(GL_TRUE);
|
|
};
|
|
|
|
const int MAXSPHERES = 50;
|
|
struct sphere { vec o; float size, max; int type; sphere *next; };
|
|
sphere spheres[MAXSPHERES], *slist = NULL, *sempty = NULL;
|
|
bool sinit = false;
|
|
|
|
void newsphere(vec &o, float max, int type)
|
|
{
|
|
if(!sinit)
|
|
{
|
|
loopi(MAXSPHERES)
|
|
{
|
|
spheres[i].next = sempty;
|
|
sempty = &spheres[i];
|
|
};
|
|
sinit = true;
|
|
};
|
|
if(sempty)
|
|
{
|
|
sphere *p = sempty;
|
|
sempty = p->next;
|
|
p->o = o;
|
|
p->max = max;
|
|
p->size = 1;
|
|
p->type = type;
|
|
p->next = slist;
|
|
slist = p;
|
|
};
|
|
};
|
|
|
|
void renderspheres(int time)
|
|
{
|
|
glDepthMask(GL_FALSE);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
glBindTexture(GL_TEXTURE_2D, 4);
|
|
|
|
for(sphere *p, **pp = &slist; p = *pp;)
|
|
{
|
|
glPushMatrix();
|
|
float size = p->size/p->max;
|
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f-size);
|
|
glTranslatef(p->o.x, p->o.z, p->o.y);
|
|
glRotatef(lastmillis/5.0f, 1, 1, 1);
|
|
glScalef(p->size, p->size, p->size);
|
|
glCallList(1);
|
|
glScalef(0.8f, 0.8f, 0.8f);
|
|
glCallList(1);
|
|
glPopMatrix();
|
|
xtraverts += 12*6*2;
|
|
|
|
if(p->size>p->max)
|
|
{
|
|
*pp = p->next;
|
|
p->next = sempty;
|
|
sempty = p;
|
|
}
|
|
else
|
|
{
|
|
p->size += time/100.0f;
|
|
pp = &p->next;
|
|
};
|
|
};
|
|
|
|
glDisable(GL_BLEND);
|
|
glDepthMask(GL_TRUE);
|
|
};
|
|
|
|
string closeent;
|
|
char *entnames[] =
|
|
{
|
|
"none?", "light", "playerstart",
|
|
"clips", "ammobox","grenades",
|
|
"health", "armour", "akimbo",
|
|
"mapmodel", "trigger",
|
|
"ladder", "ctf-flag", "?", "?", "?",
|
|
};
|
|
|
|
void renderents() // show sparkly thingies for map entities in edit mode
|
|
{
|
|
closeent[0] = 0;
|
|
if(!editmode) return;
|
|
loopv(ents)
|
|
{
|
|
entity &e = ents[i];
|
|
if(e.type==NOTUSED) continue;
|
|
vec v = { e.x, e.y, e.z };
|
|
particle_splash(2, 2, 40, v);
|
|
};
|
|
int e = closestent();
|
|
if(e>=0)
|
|
{
|
|
entity &c = ents[e];
|
|
sprintf_s(closeent)("closest entity = %s (%d, %d, %d, %d), selection = (%d, %d)", entnames[c.type], c.attr1, c.attr2, c.attr3, c.attr4, getvar("selxs"), getvar("selys"));
|
|
};
|
|
};
|
|
|
|
void loadsky(char *basename)
|
|
{
|
|
static string lastsky = "";
|
|
if(strcmp(lastsky, basename)==0) return;
|
|
char *side[] = { "ft", "bk", "lf", "rt", "dn", "up" };
|
|
int texnum = 14;
|
|
loopi(6)
|
|
{
|
|
sprintf_sd(name)("packages/%s_%s.jpg", basename, side[i]);
|
|
int xs, ys;
|
|
if(!installtex(texnum+i, path(name), xs, ys, true)) conoutf("could not load sky textures");
|
|
};
|
|
strcpy_s(lastsky, basename);
|
|
};
|
|
|
|
COMMAND(loadsky, ARG_1STR);
|
|
|
|
float cursordepth = 0.9f;
|
|
GLint viewport[4];
|
|
GLdouble mm[16], pm[16];
|
|
vec worldpos;
|
|
|
|
void readmatrices()
|
|
{
|
|
glGetIntegerv(GL_VIEWPORT, viewport);
|
|
glGetDoublev(GL_MODELVIEW_MATRIX, mm);
|
|
glGetDoublev(GL_PROJECTION_MATRIX, pm);
|
|
};
|
|
|
|
// stupid function to cater for stupid ATI linux drivers that return incorrect depth values
|
|
|
|
float depthcorrect(float d)
|
|
{
|
|
return (d<=1/256.0f) ? d*256 : d;
|
|
};
|
|
|
|
// find out the 3d target of the crosshair in the world easily and very acurately.
|
|
// sadly many very old cards and drivers appear to fuck up on glReadPixels() and give false
|
|
// coordinates, making shooting and such impossible.
|
|
// also hits map entities which is unwanted.
|
|
// could be replaced by a more acurate version of monster.cpp los() if needed
|
|
|
|
void readdepth(int w, int h)
|
|
{
|
|
glReadPixels(w/2, h/2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &cursordepth);
|
|
double worldx = 0, worldy = 0, worldz = 0;
|
|
gluUnProject(w/2, h/2, depthcorrect(cursordepth), mm, pm, viewport, &worldx, &worldz, &worldy);
|
|
worldpos.x = (float)worldx;
|
|
worldpos.y = (float)worldy;
|
|
worldpos.z = (float)worldz;
|
|
vec r = { (float)mm[0], (float)mm[4], (float)mm[8] };
|
|
vec u = { (float)mm[1], (float)mm[5], (float)mm[9] };
|
|
setorient(r, u);
|
|
};
|
|
|
|
void drawicon(float tx, float ty, int x, int y, int tex = 5, float scaling = 1/3.0f) // EDIT: AH
|
|
{
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
|
glBegin(GL_QUADS);
|
|
tx /= 192;
|
|
ty /= 192;
|
|
float o = scaling;
|
|
int s = 120;
|
|
glTexCoord2f(tx, ty); glVertex2i(x, y);
|
|
glTexCoord2f(tx+o, ty); glVertex2i(x+s, y);
|
|
glTexCoord2f(tx+o, ty+o); glVertex2i(x+s, y+s);
|
|
glTexCoord2f(tx, ty+o); glVertex2i(x, y+s);
|
|
glEnd();
|
|
xtraverts += 4;
|
|
};
|
|
|
|
void invertperspective()
|
|
{
|
|
// This only generates a valid inverse matrix for matrices generated by gluPerspective()
|
|
GLdouble inv[16];
|
|
memset(inv, 0, sizeof(inv));
|
|
|
|
inv[0*4+0] = 1.0/pm[0*4+0];
|
|
inv[1*4+1] = 1.0/pm[1*4+1];
|
|
inv[2*4+3] = 1.0/pm[3*4+2];
|
|
inv[3*4+2] = -1.0;
|
|
inv[3*4+3] = pm[2*4+2]/pm[3*4+2];
|
|
|
|
glLoadMatrixd(inv);
|
|
};
|
|
|
|
VAR(crosshairsize, 0, 15, 50);
|
|
|
|
int dblend = 0;
|
|
void damageblend(int n) { dblend += n; };
|
|
|
|
VAR(hidestats, 0, 0, 1);
|
|
VAR(crosshairfx, 0, 1, 1);
|
|
|
|
/*VAR(scopefov, 5, 50, 50);
|
|
bool scoped = false;
|
|
int oldfov = 100;
|
|
|
|
void togglescope(bool deactivate)
|
|
{
|
|
if(player1->gunselect==GUN_SNIPER)
|
|
{
|
|
if(!scoped) oldfov = getvar("fov");
|
|
scoped = !scoped;
|
|
setvar("fov", scoped ? scopefov : oldfov);
|
|
}
|
|
}*/
|
|
|
|
void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater)
|
|
{
|
|
readmatrices();
|
|
if(editmode)
|
|
{
|
|
if(cursordepth==1.0f) worldpos = player1->o;
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
cursorupdate();
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
};
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
invertperspective();
|
|
glPushMatrix();
|
|
glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
|
|
glEnable(GL_BLEND);
|
|
|
|
if(dblend || underwater)
|
|
{
|
|
glDepthMask(GL_FALSE);
|
|
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
|
glBegin(GL_QUADS);
|
|
if(dblend) glColor3d(0.0f, 0.9f, 0.9f);
|
|
else glColor3d(0.9f, 0.5f, 0.0f);
|
|
glVertex2i(0, 0);
|
|
glVertex2i(VIRTW, 0);
|
|
glVertex2i(VIRTW, VIRTH);
|
|
glVertex2i(0, VIRTH);
|
|
glEnd();
|
|
glDepthMask(GL_TRUE);
|
|
dblend -= min(1, curtime/3);
|
|
if(dblend<0) dblend = 0;
|
|
};
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
char *command = getcurcommand();
|
|
dynent *player = playerincrosshair();
|
|
dynent *bot = botincrosshair();
|
|
if(command) draw_textf("> %s_", 20, 1570, 2, command);
|
|
else if(closeent[0]) draw_text(closeent, 20, 1570, 2);
|
|
else if(player || (bot && (player=bot))) draw_text(player->name, 20, 1570, 2);
|
|
|
|
renderscores();
|
|
if(!rendermenu())
|
|
{
|
|
if(scoped && player1->gunselect == GUN_SNIPER)
|
|
{
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glEnable(GL_ALPHA_TEST);
|
|
glAlphaFunc(GL_GREATER, 0.9f);
|
|
glBindTexture(GL_TEXTURE_2D, 10);
|
|
glBegin(GL_QUADS);
|
|
glColor3ub(255,255,255);
|
|
|
|
glTexCoord2d(0.0, 0.0); glVertex2f(0, 0);
|
|
glTexCoord2d(1.0, 0.0); glVertex2f(VIRTW, 0);
|
|
glTexCoord2d(1.0, 1.0); glVertex2f(VIRTW, VIRTH);
|
|
glTexCoord2d(0.0, 1.0); glVertex2f(0, VIRTH);
|
|
|
|
glEnd();
|
|
glDisable(GL_ALPHA_TEST);
|
|
}
|
|
else if(player1->gunselect != GUN_SNIPER && !player1->reloading && !player1->state==CS_DEAD)
|
|
{
|
|
glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);
|
|
bool teammate_in_xhair = player ? (isteam(player->team, player1->team) && player->state!=CS_DEAD) : false;
|
|
glBindTexture(GL_TEXTURE_2D, teammate_in_xhair ? 9 : 1);
|
|
glBegin(GL_QUADS);
|
|
glColor3ub(255,255,255);
|
|
if(crosshairfx)
|
|
{
|
|
if(player1->gunwait && !teammate_in_xhair) glColor3ub(128,128,128);
|
|
else if(player1->health<=25 || teammate_in_xhair) glColor3ub(255,0,0);
|
|
else if(player1->health<=50) glColor3ub(255,128,0);
|
|
};
|
|
float chsize = (float)crosshairsize * (player1->gunselect==GUN_ASSAULT && player1->shots > 3 ? 1.4f : 1.0f) * (teammate_in_xhair ? 2.0f : 1.0f);
|
|
glTexCoord2d(0.0, 0.0); glVertex2f(VIRTW/2 - chsize, VIRTH/2 - chsize);
|
|
glTexCoord2d(1.0, 0.0); glVertex2f(VIRTW/2 + chsize, VIRTH/2 - chsize);
|
|
glTexCoord2d(1.0, 1.0); glVertex2f(VIRTW/2 + chsize, VIRTH/2 + chsize);
|
|
glTexCoord2d(0.0, 1.0); glVertex2f(VIRTW/2 - chsize, VIRTH/2 + chsize);
|
|
glEnd();
|
|
}
|
|
};
|
|
|
|
glPopMatrix();
|
|
|
|
glPushMatrix();
|
|
glOrtho(0, VIRTW*4/3, VIRTH*4/3, 0, -1, 1);
|
|
renderconsole();
|
|
|
|
if(!hidestats)
|
|
{
|
|
glPopMatrix();
|
|
glPushMatrix();
|
|
glOrtho(0, VIRTW*3/2, VIRTH*3/2, 0, -1, 1);
|
|
draw_textf("fps %d", 3200, 2320, 2, curfps);
|
|
draw_textf("lod %d", 3200, 2390, 2, lod_factor());
|
|
draw_textf("wqd %d", 3200, 2460, 2, nquads);
|
|
draw_textf("wvt %d", 3200, 2530, 2, curvert);
|
|
draw_textf("evt %d", 3200, 2600, 2, xtraverts);
|
|
};
|
|
|
|
glPopMatrix();
|
|
|
|
if(player1->state==CS_ALIVE)
|
|
{
|
|
glPushMatrix();
|
|
glOrtho(0, VIRTW/2, VIRTH/2, 0, -1, 1);
|
|
draw_textf("%d", 90, 827, 2, player1->health);
|
|
if(player1->armour) draw_textf("%d", 390, 827, 2, player1->armour);
|
|
//draw_textf("%d", 690, 827, 2, player1->mag[player1->gunselect]);
|
|
if (player1->gunselect!=GUN_KNIFE)
|
|
{
|
|
//draw_textf("%d", 690, 827, 2, player1->mag[player1->gunselect]);
|
|
char gunstats [64];
|
|
if (player1->gunselect!=GUN_GRENADE)
|
|
sprintf(gunstats,"%i/%i",player1->mag[player1->gunselect],player1->ammo[player1->gunselect]);
|
|
else sprintf(gunstats,"%i",player1->mag[player1->gunselect]);
|
|
draw_text(gunstats, 690, 827, 2);
|
|
//clean up pointer?
|
|
//delete gunstats;
|
|
}
|
|
|
|
glPopMatrix();
|
|
|
|
// EDIT: AH - ctf
|
|
#define ctf_scl 0.75
|
|
if(m_ctf)
|
|
{
|
|
glPushMatrix();
|
|
glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
glColor4f(1.0f, 1.0f, 1.0f, 0.2f);
|
|
if(flaginfos[TEAM_CLA].state == CTFF_INBASE) glDisable(GL_BLEND); else glEnable(GL_BLEND);
|
|
drawicon(64*ctf_scl, 0, 1940, 1650, 11, 1.0f/4.0f);
|
|
if(flaginfos[TEAM_RVSF].state == CTFF_INBASE) glDisable(GL_BLEND); else glEnable(GL_BLEND);
|
|
drawicon(0, 0, 1820, 1650, 11, 1.0f/4.0f);
|
|
glDisable(GL_BLEND);
|
|
drawicon((float)(rb_team_int(player1->team)*64*ctf_scl), (float)(64*ctf_scl), VIRTW-128-10, 10, 11, 1.0/4.0); // shows which team you are
|
|
glPopMatrix();
|
|
|
|
// big flag icon
|
|
flaginfo &f = flaginfos[rb_opposite(rb_team_int(player1->team))];
|
|
if(f.state==CTFF_STOLEN && f.thief == player1 && f.pick_ack )
|
|
{
|
|
glPushMatrix();
|
|
glOrtho(0, VIRTW/2, VIRTH/2, 0, -1, 1);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
glColor4f(1.0f, 1.0f, 1.0f, (float)(sin(lastmillis / 100.0) + 1) / 2);
|
|
glEnable(GL_BLEND);
|
|
drawicon((float)(rb_opposite(rb_team_int(player1->team))*128*ctf_scl),(float)(128*ctf_scl), 1065, VIRTH/2/3*2, 11, 1.0/2.0);
|
|
glPopMatrix();
|
|
};
|
|
};
|
|
|
|
glPushMatrix();
|
|
glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
|
|
glDisable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glColor4f(1.0f, 1.0f, 1.0f, (float) 0.2f+(sin(lastmillis/100)+1)/2);
|
|
|
|
if(player1->health <= 20)
|
|
{
|
|
glEnable(GL_BLEND);
|
|
drawicon(64, 0, 20, 1650); //drawicon(128, 128, 20, 1650);
|
|
glDisable(GL_BLEND);
|
|
}
|
|
else drawicon(64, 0, 20, 1650); //drawicon(128, 128, 20, 1650);
|
|
if(player1->armour) drawicon((float)(128), 0, 620, 1650); //if(player1->armour) drawicon((float)(player1->armourtype*64), 0, 620, 1650);
|
|
int g = player1->gunselect;
|
|
int r = 64;
|
|
if(g>2) { g -= 3; r = 128; };
|
|
|
|
if(!player1->mag[player1->gunselect] && player1->gunselect != GUN_KNIFE && player1->gunselect != GUN_GRENADE)
|
|
{
|
|
glEnable(GL_BLEND);
|
|
drawicon((float)(g*64), (float)r, 1220, 1650);
|
|
glDisable(GL_BLEND);
|
|
}
|
|
else
|
|
{
|
|
if (player1->gunselect==GUN_GRENADE) drawicon(0, 0, 1220, 1650);
|
|
else drawicon((float)(g*64), (float)r, 1220, 1650);
|
|
}
|
|
glPopMatrix();
|
|
};
|
|
|
|
glDisable(GL_BLEND);
|
|
glDisable(GL_TEXTURE_2D);
|
|
glEnable(GL_DEPTH_TEST);
|
|
};
|
|
|
|
#define MAXSHOTLINES 100
|
|
struct shotline
|
|
{
|
|
vec from, to;
|
|
bool inuse;
|
|
int millis;
|
|
};
|
|
shotline shotlines[MAXSHOTLINES];
|
|
|
|
void shotlinereset() { loopi(MAXSHOTLINES) shotlines[i].inuse = false; };
|
|
|
|
void addshotline(dynent *d, vec &from, vec &to)
|
|
{
|
|
if(d == player1) return;
|
|
if(rnd(3) != 0) return;
|
|
loopi(MAXSHOTLINES)
|
|
{
|
|
shotline *s = &shotlines[i];
|
|
if(s->inuse) continue;
|
|
int start = 10;
|
|
vdist(_dist, _unitv, player1->o, to);
|
|
if(_dist <= 10.0f) start = 8;
|
|
else start = 5;
|
|
|
|
vdist(dist, unitv, from, to);
|
|
vdiv(unitv, dist);
|
|
s->inuse = true;
|
|
s->from = unitv;
|
|
vmul(s->from, dist/10*start);
|
|
vadd(s->from, from);
|
|
s->to = unitv;
|
|
vmul(s->to, dist/10*-(10-start-2));
|
|
vadd(s->to, to);
|
|
s->millis = lastmillis;
|
|
return;
|
|
};
|
|
};
|
|
|
|
VAR(shotline_duration, 0, 75, 10000);
|
|
|
|
void rendershotlines()
|
|
{
|
|
loopi(MAXSHOTLINES)
|
|
{
|
|
shotline *s = &shotlines[i];
|
|
if(!s->inuse) continue;
|
|
if(lastmillis-s->millis > shotline_duration) { s->inuse = false; continue; }
|
|
glPushMatrix();
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);
|
|
glDisable(GL_FOG);
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
glBegin(GL_LINES);
|
|
glColor4f(1.0f, 1.0f, 0.7f, 0.5f);
|
|
glVertex3f(s->from.x, s->from.z, s->from.y);
|
|
glVertex3f(s->to.x, s->to.z, s->to.y);
|
|
glEnd();
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
glEnable(GL_FOG);
|
|
glDisable(GL_BLEND);
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
glPopMatrix();
|
|
};
|
|
};
|
|
|
|
void renderphysents()
|
|
{
|
|
loopv(physents)
|
|
{
|
|
physent *p = physents[i];
|
|
if(!p) continue;
|
|
string model;
|
|
float z = p->o.z;
|
|
|
|
switch(p->state)
|
|
{
|
|
case NADE_THROWED:
|
|
strcpy_s(model, "weapons/grenade/static");
|
|
break;
|
|
case GIB:
|
|
default:
|
|
sprintf_s(model)("misc/gib0%i", (((4*(int)p)+p->timetolife)%3)+1);
|
|
int t = lastmillis-p->millis;
|
|
if(t>p->timetolife-2000)
|
|
{
|
|
t -= p->timetolife-2000;
|
|
z -= t*t/4000000000.0f*t;
|
|
}
|
|
break;
|
|
}
|
|
path(model);
|
|
rendermodel(model, 0, 1, 0, 0, p->o.x, z, p->o.y, p->yaw, p->pitch, false, 2.0f, 100.0f, 0, 0);
|
|
};
|
|
};
|
|
|
|
VAR(gibnum, 0, 6, 1000);
|
|
VAR(gibttl, 0, 5000, 15000);
|
|
VAR(gibspeed, 1, 5, 20);
|
|
|
|
void addgib(dynent *d)
|
|
{
|
|
if(!d) return;
|
|
playsound(S_GIB, &d->o);
|
|
|
|
loopi(gibnum)
|
|
{
|
|
physent *p = new_physent();
|
|
p->owner = d;
|
|
p->millis = lastmillis;
|
|
p->timetolife = gibttl+rnd(10)*100;
|
|
|
|
p->state = GIB;
|
|
|
|
p->isphysent = true;
|
|
p->gravity = 20;
|
|
p->timeinair = 0;
|
|
p->onfloor = false;
|
|
|
|
p->o = d->o;
|
|
p->o.z -= d->aboveeye;
|
|
|
|
float gibvelangle = (float) rnd(360);
|
|
float speed = (float) gibspeed;
|
|
p->vel.x = sin(gibvelangle)*speed*rnd(1000)/1000.0f;
|
|
p->vel.y = cos(gibvelangle)*speed*rnd(1000)/1000.0f;
|
|
p->vel.z = speed*rnd(1000)/1000.0f;
|
|
vdiv(p->vel, 10.0f);
|
|
|
|
p->yaw = (float)rnd(360);
|
|
p->pitch = (float)rnd(360);
|
|
p->rotspeed = 3.0f;
|
|
}
|
|
};
|
|
|
|
void loadingscreen()
|
|
{
|
|
glPushMatrix();
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glDisable(GL_BLEND);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 8);
|
|
glBegin(GL_QUADS);
|
|
|
|
glTexCoord2f(0, 0); glVertex2i(0, 0);
|
|
glTexCoord2f(1, 0); glVertex2i(VIRTW, 0);
|
|
glTexCoord2f(1, 1); glVertex2i(VIRTW, VIRTH);
|
|
glTexCoord2f(0, 1); glVertex2i(0, VIRTH);
|
|
|
|
glEnd();
|
|
|
|
SDL_GL_SwapBuffers();
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
glDisable(GL_BLEND);
|
|
|
|
glPopMatrix();
|
|
}
|