git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@893 e016b1c5-ed68-44aa-a2f7-31cac88cffde
652 lines
19 KiB
C++
652 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 quad(GLuint tex, float x, float y, float s, float tx, float ty, float ts)
|
|
{
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2f(tx, ty); glVertex2f(x, y);
|
|
glTexCoord2f(tx+ts, ty); glVertex2f(x+s, y);
|
|
glTexCoord2f(tx+ts, ty+ts); glVertex2f(x+s, y+s);
|
|
glTexCoord2f(tx, ty+ts); glVertex2f(x, y+s);
|
|
glEnd();
|
|
xtraverts += 4;
|
|
}
|
|
|
|
void circle(GLuint tex, float x, float y, float r, float tx, float ty, float tr, int subdiv = 32)
|
|
{
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
|
glBegin(GL_TRIANGLE_FAN);
|
|
glTexCoord2f(tx, ty);
|
|
glVertex2f(x, y);
|
|
loopi(subdiv+1)
|
|
{
|
|
float c = cosf(2*M_PI*i/float(subdiv)), s = sinf(2*M_PI*i/float(subdiv));
|
|
glTexCoord2f(tx + tr*c, ty + tr*s);
|
|
glVertex2f(x + r*c, y + r*s);
|
|
}
|
|
glEnd();
|
|
xtraverts += subdiv+2;
|
|
}
|
|
|
|
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);
|
|
glColor3f(1, 1, 1);
|
|
|
|
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, 0); 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) glColor3f(0.7f, 0.7f, 0.7f); //glColor3d(0.5, 0.3, 0.4);
|
|
else glColor3f(1, 1, 1);
|
|
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);
|
|
glColor3f(0.6f, 0.6f, 0.6f); //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);
|
|
}
|
|
|
|
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];
|
|
s_sprintf(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"));
|
|
}
|
|
}
|
|
|
|
float cursordepth = 0.9f;
|
|
GLint viewport[4];
|
|
GLdouble mm[16], pm[16];
|
|
vec worldpos, camup, camright;
|
|
|
|
void readmatrices()
|
|
{
|
|
glGetIntegerv(GL_VIEWPORT, viewport);
|
|
glGetDoublev(GL_MODELVIEW_MATRIX, mm);
|
|
glGetDoublev(GL_PROJECTION_MATRIX, pm);
|
|
camright = vec(float(mm[0]), float(mm[4]), float(mm[8]));
|
|
camup = vec(float(mm[1]), float(mm[5]), float(mm[9]));
|
|
}
|
|
|
|
// 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, vec &pos)
|
|
{
|
|
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);
|
|
pos.x = (float)worldx;
|
|
pos.y = (float)worldy;
|
|
pos.z = (float)worldz;
|
|
}
|
|
|
|
void drawicon(Texture *tex, float x, float y, float s, int col, int row, float ts)
|
|
{
|
|
if(tex && tex->xs == tex->ys) quad(tex->id, x, y, s, ts*col, ts*row, ts);
|
|
}
|
|
|
|
void drawequipicon(float x, float y, int col, int row, float blend)
|
|
{
|
|
static Texture *tex = NULL;
|
|
if(!tex) tex = textureload("packages/misc/items.png");
|
|
if(tex)
|
|
{
|
|
if(blend) glEnable(GL_BLEND);
|
|
drawicon(tex, x, y, 120, col, row, 1/3.0f);
|
|
if(blend) glDisable(GL_BLEND);
|
|
}
|
|
}
|
|
|
|
void drawradaricon(float x, float y, float s, int col, int row, bool blend)
|
|
{
|
|
static Texture *tex = NULL;
|
|
if(!tex) tex = textureload("packages/misc/radaricons.png");
|
|
if(tex)
|
|
{
|
|
if(blend) glEnable(GL_BLEND);
|
|
drawicon(tex, x, y, s, col, row, 1/4.0f);
|
|
if(blend) glDisable(GL_BLEND);
|
|
}
|
|
}
|
|
|
|
void drawctficon(float x, float y, float s, int col, int row, float ts)
|
|
{
|
|
static Texture *tex = NULL;
|
|
if(!tex) tex = textureload("packages/misc/teamicons.png");
|
|
if(tex) drawicon(tex, x, y, s, col, row, ts);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
VARP(crosshairsize, 0, 15, 50);
|
|
|
|
int dblend = 0;
|
|
void damageblend(int n) { dblend += n; }
|
|
|
|
VARP(hidestats, 0, 1, 1);
|
|
VARP(crosshairfx, 0, 1, 1);
|
|
VARP(hideradar, 0, 0, 1);
|
|
VARP(radarres, 1, 64, 1024);
|
|
VARP(radarentsize, 1, 4, 64);
|
|
VARP(hidectfhud, 0, 0, 1);
|
|
VARP(hideteamhud, 0, 0, 1);
|
|
|
|
bool showmap = false;
|
|
void toggleshowmap() { showmap = !showmap; }
|
|
COMMAND(toggleshowmap, ARG_NONE);
|
|
|
|
void drawscope()
|
|
{
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glEnable(GL_ALPHA_TEST);
|
|
glAlphaFunc(GL_GREATER, 0.9f);
|
|
static Texture *scopetex = NULL;
|
|
if(!scopetex) scopetex = textureload("packages/misc/scope.png");
|
|
glBindTexture(GL_TEXTURE_2D, scopetex->id);
|
|
glBegin(GL_QUADS);
|
|
glColor3ub(255,255,255);
|
|
|
|
glTexCoord2i(0, 0); glVertex2i(0, 0);
|
|
glTexCoord2i(1, 0); glVertex2i(VIRTW, 0);
|
|
glTexCoord2i(1, 1); glVertex2i(VIRTW, VIRTH);
|
|
glTexCoord2i(0, 1); glVertex2i(0, VIRTH);
|
|
|
|
glEnd();
|
|
glDisable(GL_ALPHA_TEST);
|
|
}
|
|
|
|
void drawcrosshair(bool showteamwarning)
|
|
{
|
|
glBlendFunc(GL_ONE, GL_ONE);
|
|
static Texture *teammatetex = NULL;
|
|
if(!teammatetex) teammatetex = textureload("packages/misc/teammate.png");
|
|
glBindTexture(GL_TEXTURE_2D, showteamwarning ? teammatetex->id : crosshair->id);
|
|
glBegin(GL_QUADS);
|
|
glColor3ub(255,255,255);
|
|
if(crosshairfx)
|
|
{
|
|
if(showteamwarning) glColor3ub(255, 0, 0);
|
|
else if(player1->gunwait) glColor3ub(128,128,128);
|
|
else if(!m_osok)
|
|
{
|
|
if(player1->health<=25) 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) * (showteamwarning ? 2.0f : 1.0f);
|
|
glTexCoord2i(0, 0); glVertex2f(VIRTW/2 - chsize, VIRTH/2 - chsize);
|
|
glTexCoord2i(1, 0); glVertex2f(VIRTW/2 + chsize, VIRTH/2 - chsize);
|
|
glTexCoord2i(1, 1); glVertex2f(VIRTW/2 + chsize, VIRTH/2 + chsize);
|
|
glTexCoord2i(0, 1); glVertex2f(VIRTW/2 - chsize, VIRTH/2 + chsize);
|
|
glEnd();
|
|
}
|
|
|
|
void drawequipicons()
|
|
{
|
|
glDisable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glColor4f(1.0f, 1.0f, 1.0f, 0.2f+(sinf(lastmillis/100.0f)+1.0f)/2.0f);
|
|
|
|
// health & armor
|
|
if(player1->armour) drawequipicon(620, 1650, 2, 0, false);
|
|
drawequipicon(20, 1650, 1, 0, (player1->health <= 20 && !m_osok));
|
|
|
|
// weapons
|
|
int c = player1->gunselect, r = 1;
|
|
if(c>2) { c -= 3; r = 2; }
|
|
if(c==GUN_GRENADE) c = r = 0;
|
|
|
|
drawequipicon(1220, 1650, c, r, (!player1->mag[player1->gunselect] && player1->gunselect != GUN_KNIFE && player1->gunselect != GUN_GRENADE));
|
|
glEnable(GL_BLEND);
|
|
}
|
|
|
|
void drawradarent(float x, float y, float yaw, int col, int row, float iconsize, bool blend)
|
|
{
|
|
glPushMatrix();
|
|
glTranslatef(x, y, 0);
|
|
glRotatef(yaw, 0, 0, 1);
|
|
drawradaricon(-iconsize/2.0f, -iconsize/2.0f, iconsize, col, row, blend);
|
|
glPopMatrix();
|
|
}
|
|
|
|
bool insideradar(const vec ¢erpos, float radius, const vec &o)
|
|
{
|
|
// return o.reject(centerpos, radius);
|
|
return o.distxy(centerpos)<=radius;
|
|
}
|
|
|
|
void drawradar(const vec ¢er, float angle, int radarres, int w, int h, bool fullscreen)
|
|
{
|
|
glPushMatrix();
|
|
glDisable(GL_BLEND);
|
|
|
|
const float worldsize = (float)ssize;
|
|
const float radarviewsize = fullscreen ? VIRTH : VIRTH/6;
|
|
const float radarsize = worldsize/radarres*radarviewsize;
|
|
|
|
if(fullscreen) glTranslatef(VIRTW/2-radarviewsize/2, 0, 0);
|
|
else glTranslatef(VIRTW-radarviewsize-10, 10, 0);
|
|
glTranslatef(radarviewsize/2, radarviewsize/2, 0);
|
|
glRotatef(angle, 0, 0, 1);
|
|
glTranslatef(-radarviewsize/2, -radarviewsize/2, 0);
|
|
|
|
extern GLuint minimaptex;
|
|
|
|
vec centerpos(min(max(center.x, radarres/2), worldsize-radarres/2), min(max(center.y, radarres/2), worldsize-radarres/2), 0);
|
|
circle(minimaptex, radarviewsize/2, radarviewsize/2, radarviewsize/2, centerpos.x/worldsize, centerpos.y/worldsize, radarres/2/worldsize);
|
|
//quad(minimaptex, 0, 0, radarviewsize, (centerpos.x-radarres/2)/worldsize, (centerpos.y-radarres/2)/worldsize, radarres/worldsize);
|
|
glTranslatef(-(centerpos.x-radarres/2)/worldsize*radarsize, -(centerpos.y-radarres/2)/worldsize*radarsize, 0);
|
|
|
|
const float iconsize = radarentsize/(float)radarres*radarviewsize;
|
|
const float coordtrans = radarsize/worldsize;
|
|
|
|
drawradarent(player1->o.x*coordtrans, player1->o.y*coordtrans, player1->yaw, player1->state==CS_ALIVE ? (player1->attacking ? 2 : 0) : 1, 2, iconsize, false); // local player
|
|
loopv(players) // other players
|
|
{
|
|
playerent *pl = players[i];
|
|
if(!pl || !isteam(player1->team, pl->team) || !insideradar(centerpos, radarres/2, pl->o)) continue;
|
|
drawradarent(pl->o.x*coordtrans, pl->o.y*coordtrans, pl->yaw, pl->state==CS_ALIVE ? (pl->attacking ? 2 : 0) : 1, team_int(pl->team), iconsize, false);
|
|
}
|
|
if(m_ctf)
|
|
{
|
|
glColor4f(1.0f, 1.0f, 1.0f, (sinf(lastmillis / 100.0f) + 1.0f) / 2.0f);
|
|
loopi(2) // flag items
|
|
{
|
|
flaginfo &f = flaginfos[i];
|
|
entity *e = f.flag;
|
|
if(!e) continue;
|
|
if(f.state==CTFF_STOLEN && f.actor && insideradar(centerpos, radarres/2, f.actor->o))
|
|
drawradarent(f.actor->o.x*coordtrans+iconsize/2, f.actor->o.y*coordtrans+iconsize/2, 0, 3, f.team, iconsize, true); // draw near flag thief
|
|
else if(insideradar(centerpos, radarres/2, vec(e->x, e->y, centerpos.z))) drawradarent(e->x*coordtrans, e->y*coordtrans, 0, 3, f.team, iconsize, false); // draw on entitiy pos
|
|
}
|
|
}
|
|
|
|
glEnable(GL_BLEND);
|
|
glPopMatrix();
|
|
}
|
|
|
|
void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater)
|
|
{
|
|
readmatrices();
|
|
if(editmode)
|
|
{
|
|
if(cursordepth==1.0f) worldpos = camera1->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) glColor3f(0.0f, 0.9f, 0.9f);
|
|
else glColor3f(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);
|
|
|
|
playerent *targetplayer = playerincrosshair();
|
|
bool didteamkill = player1->lastteamkill && player1->lastteamkill + 5000 > lastmillis;
|
|
bool menuvisible = rendermenu();
|
|
|
|
if(player1->state==CS_ALIVE && !player1->reloading && !didteamkill && !menuvisible)
|
|
{
|
|
bool drawteamwarning = targetplayer ? (isteam(targetplayer->team, player1->team) && targetplayer->state!=CS_DEAD) : false;
|
|
if(player1->gunselect==GUN_SNIPER && scoped) drawscope();
|
|
else if((player1->gunselect!=GUN_SNIPER || drawteamwarning)) drawcrosshair(drawteamwarning);
|
|
}
|
|
|
|
drawequipicons();
|
|
|
|
if(!hideradar)
|
|
{
|
|
if(showmap) drawradar(vec(ssize/2, ssize/2, 0), 0, ssize, w, h, true);
|
|
else drawradar(player1->o, -player1->yaw, radarres, w, h, false);
|
|
}
|
|
|
|
if(getcurcommand()) rendercommand(20, 1570);
|
|
else if(closeent[0]) draw_text(closeent, 20, 1570);
|
|
else if(targetplayer) draw_text(targetplayer->name, 20, 1570);
|
|
|
|
glPopMatrix();
|
|
|
|
glPushMatrix();
|
|
glOrtho(0, VIRTW*2, VIRTH*2, 0, -1, 1);
|
|
renderconsole();
|
|
if(!hidestats)
|
|
{
|
|
const int left = (VIRTW-225-10)*2, top = (VIRTH*7/8)*2;
|
|
draw_textf("fps %d", left, top, curfps);
|
|
draw_textf("lod %d", left, top+80, lod_factor());
|
|
draw_textf("wqd %d", left, top+160, nquads);
|
|
draw_textf("wvt %d", left, top+240, curvert);
|
|
draw_textf("evt %d", left, top+320, xtraverts);
|
|
}
|
|
glPopMatrix();
|
|
|
|
if(player1->state==CS_ALIVE)
|
|
{
|
|
glPushMatrix();
|
|
glOrtho(0, VIRTW/2, VIRTH/2, 0, -1, 1);
|
|
draw_textf("%d", 90, 827, player1->health);
|
|
if(player1->armour) draw_textf("%d", 390, 827, player1->armour);
|
|
if(player1->gunselect!=GUN_KNIFE)
|
|
{
|
|
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);
|
|
}
|
|
glPopMatrix();
|
|
|
|
if(m_teammode && !hideteamhud)
|
|
{
|
|
glPushMatrix();
|
|
glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
|
|
glDisable(GL_BLEND);
|
|
drawctficon(VIRTW-120-10, VIRTH/6+10+10, 120, team_int(player1->team), 1, 1/4.0f); // local players team
|
|
glEnable(GL_BLEND);
|
|
draw_textf(player1->team, VIRTW-VIRTH/6-10, VIRTH/6+10+10+120/2);
|
|
glPopMatrix();
|
|
}
|
|
|
|
if(didteamkill)
|
|
{
|
|
glPushMatrix();
|
|
glOrtho(0, VIRTW/3, VIRTH/3, 0, -1, 1);
|
|
draw_text("\f3you killed a teammate", VIRTW/3/40, VIRTH/3/2);
|
|
glPopMatrix();
|
|
}
|
|
|
|
if(m_ctf && !hidectfhud)
|
|
{
|
|
glPushMatrix();
|
|
glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
|
|
glColor4f(1.0f, 1.0f, 1.0f, 0.2f);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
|
|
loopi(2) // flag state
|
|
{
|
|
if(flaginfos[i].state == CTFF_INBASE) glDisable(GL_BLEND); else glEnable(GL_BLEND);
|
|
drawctficon(i*120+VIRTW/4.0f*3.0f, 1650, 120, i, 0, 1/4.0f);
|
|
}
|
|
|
|
// big flag-stolen icon
|
|
flaginfo &f = flaginfos[team_opposite(team_int(player1->team))];
|
|
if(f.state==CTFF_STOLEN && f.actor == player1 && f.ack)
|
|
{
|
|
glColor4f(1.0f, 1.0f, 1.0f, (sinf(lastmillis/100.0f)+1.0f) / 2.0f);
|
|
glEnable(GL_BLEND);
|
|
drawctficon(VIRTW-225-10, VIRTH*5/8, 225, team_opposite(team_int(player1->team)), 1, 1/2.0f);
|
|
glDisable(GL_BLEND);
|
|
}
|
|
glPopMatrix();
|
|
}
|
|
}
|
|
|
|
glDisable(GL_BLEND);
|
|
glDisable(GL_TEXTURE_2D);
|
|
glEnable(GL_DEPTH_TEST);
|
|
}
|
|
|
|
void renderbounceents()
|
|
{
|
|
loopv(bounceents)
|
|
{
|
|
bounceent *p = bounceents[i];
|
|
if(!p) continue;
|
|
string model;
|
|
float z = p->o.z;
|
|
|
|
switch(p->bouncestate)
|
|
{
|
|
case NADE_THROWED:
|
|
s_strcpy(model, "weapons/grenade/static");
|
|
break;
|
|
case GIB:
|
|
default:
|
|
{
|
|
uint n = (((4*(uint)(size_t)p)+(uint)p->timetolife)%3)+1;
|
|
s_sprintf(model)("misc/gib0%u", n);
|
|
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, ANIM_MAPMODEL|ANIM_LOOP, 0, 1.1f, p->o.x, z, p->o.y, p->yaw, p->pitch, 10.0f);
|
|
}
|
|
}
|
|
|
|
VARP(gibnum, 0, 6, 1000);
|
|
VARP(gibttl, 0, 5000, 15000);
|
|
VARP(gibspeed, 1, 30, 100);
|
|
|
|
void addgib(playerent *d)
|
|
{
|
|
if(!d) return;
|
|
playsound(S_GIB, &d->o);
|
|
|
|
loopi(gibnum)
|
|
{
|
|
bounceent *p = newbounceent();
|
|
p->owner = d;
|
|
p->millis = lastmillis;
|
|
p->timetolife = gibttl+rnd(10)*100;
|
|
p->bouncestate = GIB;
|
|
|
|
p->o = d->o;
|
|
p->o.z -= d->aboveeye;
|
|
|
|
p->yaw = (float)rnd(360);
|
|
p->pitch = (float)rnd(360);
|
|
|
|
p->maxspeed = 30.0f;
|
|
p->rotspeed = 3.0f;
|
|
|
|
const float angle = (float)rnd(360);
|
|
const float speed = (float)gibspeed;
|
|
|
|
p->vel.x = sinf(RAD*angle)*rnd(1000)/1000.0f;
|
|
p->vel.y = cosf(RAD*angle)*rnd(1000)/1000.0f;
|
|
p->vel.z = rnd(1000)/1000.0f;
|
|
p->vel.mul(speed/100.0f);
|
|
}
|
|
}
|
|
|
|
void loadingscreen()
|
|
{
|
|
static Texture *logo = NULL;
|
|
if(!logo) logo = textureload("packages/misc/startscreen.png");
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
|
|
glClearColor(0, 0, 0, 1);
|
|
glColor3f(1, 1, 1);
|
|
|
|
loopi(2)
|
|
{
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
quad(logo->id, (VIRTW-VIRTH)/2, 0, VIRTH, 0, 0, 1);
|
|
SDL_GL_SwapBuffers();
|
|
}
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
glEnable(GL_DEPTH_TEST);
|
|
}
|
|
|